summaryrefslogtreecommitdiffstats
path: root/libs/nanopb/tests/oneof
diff options
context:
space:
mode:
Diffstat (limited to 'libs/nanopb/tests/oneof')
-rw-r--r--libs/nanopb/tests/oneof/SConscript33
-rw-r--r--libs/nanopb/tests/oneof/decode_oneof.c131
-rw-r--r--libs/nanopb/tests/oneof/encode_oneof.c64
-rw-r--r--libs/nanopb/tests/oneof/oneof.proto32
4 files changed, 260 insertions, 0 deletions
diff --git a/libs/nanopb/tests/oneof/SConscript b/libs/nanopb/tests/oneof/SConscript
new file mode 100644
index 00000000..22634fb0
--- /dev/null
+++ b/libs/nanopb/tests/oneof/SConscript
@@ -0,0 +1,33 @@
+# Test the 'oneof' feature for generating C unions.
+
+Import('env')
+
+import re
+
+match = None
+if 'PROTOC_VERSION' in env:
+ match = re.search('([0-9]+).([0-9]+).([0-9]+)', env['PROTOC_VERSION'])
+
+if match:
+ version = map(int, match.groups())
+
+# Oneof is supported by protoc >= 2.6.0
+if env.GetOption('clean') or (match and (version[0] > 2 or (version[0] == 2 and version[1] >= 6))):
+ env.NanopbProto('oneof')
+
+ enc = env.Program(['encode_oneof.c',
+ 'oneof.pb.c',
+ '$COMMON/pb_encode.o',
+ '$COMMON/pb_common.o'])
+
+ dec = env.Program(['decode_oneof.c',
+ 'oneof.pb.c',
+ '$COMMON/pb_decode.o',
+ '$COMMON/pb_common.o'])
+
+ env.RunTest("message1.pb", enc, ARGS = ['1'])
+ env.RunTest("message1.txt", [dec, 'message1.pb'], ARGS = ['1'])
+ env.RunTest("message2.pb", enc, ARGS = ['2'])
+ env.RunTest("message2.txt", [dec, 'message2.pb'], ARGS = ['2'])
+ env.RunTest("message3.pb", enc, ARGS = ['3'])
+ env.RunTest("message3.txt", [dec, 'message3.pb'], ARGS = ['3'])
diff --git a/libs/nanopb/tests/oneof/decode_oneof.c b/libs/nanopb/tests/oneof/decode_oneof.c
new file mode 100644
index 00000000..37075cd6
--- /dev/null
+++ b/libs/nanopb/tests/oneof/decode_oneof.c
@@ -0,0 +1,131 @@
+/* Decode a message using oneof fields */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pb_decode.h>
+#include "oneof.pb.h"
+#include "test_helpers.h"
+#include "unittests.h"
+
+/* Test the 'OneOfMessage' */
+int test_oneof_1(pb_istream_t *stream, int option)
+{
+ OneOfMessage msg;
+ int status = 0;
+
+ /* To better catch initialization errors */
+ memset(&msg, 0xAA, sizeof(msg));
+
+ if (!pb_decode(stream, OneOfMessage_fields, &msg))
+ {
+ printf("Decoding failed: %s\n", PB_GET_ERROR(stream));
+ return 1;
+ }
+
+ /* Check that the basic fields work normally */
+ TEST(msg.prefix == 123);
+ TEST(msg.suffix == 321);
+
+ /* Check that we got the right oneof according to command line */
+ if (option == 1)
+ {
+ TEST(msg.which_values == OneOfMessage_first_tag);
+ TEST(msg.values.first == 999);
+ }
+ else if (option == 2)
+ {
+ TEST(msg.which_values == OneOfMessage_second_tag);
+ TEST(strcmp(msg.values.second, "abcd") == 0);
+ }
+ else if (option == 3)
+ {
+ TEST(msg.which_values == OneOfMessage_third_tag);
+ TEST(msg.values.third.array[0] == 1);
+ TEST(msg.values.third.array[1] == 2);
+ TEST(msg.values.third.array[2] == 3);
+ TEST(msg.values.third.array[3] == 4);
+ TEST(msg.values.third.array[4] == 5);
+ }
+
+ return status;
+}
+
+
+/* Test the 'PlainOneOfMessage' */
+int test_oneof_2(pb_istream_t *stream, int option)
+{
+ PlainOneOfMessage msg = PlainOneOfMessage_init_zero;
+ int status = 0;
+
+ if (!pb_decode(stream, PlainOneOfMessage_fields, &msg))
+ {
+ printf("Decoding failed: %s\n", PB_GET_ERROR(stream));
+ return 1;
+ }
+
+ /* Check that we got the right oneof according to command line */
+ if (option == 1)
+ {
+ TEST(msg.which_values == OneOfMessage_first_tag);
+ TEST(msg.values.first == 999);
+ }
+ else if (option == 2)
+ {
+ TEST(msg.which_values == OneOfMessage_second_tag);
+ TEST(strcmp(msg.values.second, "abcd") == 0);
+ }
+ else if (option == 3)
+ {
+ TEST(msg.which_values == OneOfMessage_third_tag);
+ TEST(msg.values.third.array[0] == 1);
+ TEST(msg.values.third.array[1] == 2);
+ TEST(msg.values.third.array[2] == 3);
+ TEST(msg.values.third.array[3] == 4);
+ TEST(msg.values.third.array[4] == 5);
+ }
+
+ return status;
+}
+
+int main(int argc, char **argv)
+{
+ uint8_t buffer[OneOfMessage_size];
+ size_t count;
+ int option;
+
+ if (argc != 2)
+ {
+ fprintf(stderr, "Usage: decode_oneof [number]\n");
+ return 1;
+ }
+ option = atoi(argv[1]);
+
+ SET_BINARY_MODE(stdin);
+ count = fread(buffer, 1, sizeof(buffer), stdin);
+
+ if (!feof(stdin))
+ {
+ printf("Message does not fit in buffer\n");
+ return 1;
+ }
+
+ {
+ int status = 0;
+ pb_istream_t stream;
+
+ stream = pb_istream_from_buffer(buffer, count);
+ status = test_oneof_1(&stream, option);
+
+ if (status != 0)
+ return status;
+
+ stream = pb_istream_from_buffer(buffer, count);
+ status = test_oneof_2(&stream, option);
+
+ if (status != 0)
+ return status;
+ }
+
+ return 0;
+}
diff --git a/libs/nanopb/tests/oneof/encode_oneof.c b/libs/nanopb/tests/oneof/encode_oneof.c
new file mode 100644
index 00000000..913d2d43
--- /dev/null
+++ b/libs/nanopb/tests/oneof/encode_oneof.c
@@ -0,0 +1,64 @@
+/* Encode a message using oneof fields */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <pb_encode.h>
+#include "oneof.pb.h"
+#include "test_helpers.h"
+
+int main(int argc, char **argv)
+{
+ uint8_t buffer[OneOfMessage_size];
+ OneOfMessage msg = OneOfMessage_init_zero;
+ pb_ostream_t stream;
+ int option;
+
+ if (argc != 2)
+ {
+ fprintf(stderr, "Usage: encode_oneof [number]\n");
+ return 1;
+ }
+ option = atoi(argv[1]);
+
+ /* Prefix and suffix are used to test that the union does not disturb
+ * other fields in the same message. */
+ msg.prefix = 123;
+
+ /* We encode one of the 'values' fields based on command line argument */
+ if (option == 1)
+ {
+ msg.which_values = OneOfMessage_first_tag;
+ msg.values.first = 999;
+ }
+ else if (option == 2)
+ {
+ msg.which_values = OneOfMessage_second_tag;
+ strcpy(msg.values.second, "abcd");
+ }
+ else if (option == 3)
+ {
+ msg.which_values = OneOfMessage_third_tag;
+ msg.values.third.array_count = 5;
+ msg.values.third.array[0] = 1;
+ msg.values.third.array[1] = 2;
+ msg.values.third.array[2] = 3;
+ msg.values.third.array[3] = 4;
+ msg.values.third.array[4] = 5;
+ }
+
+ msg.suffix = 321;
+
+ stream = pb_ostream_from_buffer(buffer, sizeof(buffer));
+
+ if (pb_encode(&stream, OneOfMessage_fields, &msg))
+ {
+ SET_BINARY_MODE(stdout);
+ fwrite(buffer, 1, stream.bytes_written, stdout);
+ return 0;
+ }
+ else
+ {
+ fprintf(stderr, "Encoding failed: %s\n", PB_GET_ERROR(&stream));
+ return 1;
+ }
+}
diff --git a/libs/nanopb/tests/oneof/oneof.proto b/libs/nanopb/tests/oneof/oneof.proto
new file mode 100644
index 00000000..b4fe56f2
--- /dev/null
+++ b/libs/nanopb/tests/oneof/oneof.proto
@@ -0,0 +1,32 @@
+syntax = "proto2";
+
+import 'nanopb.proto';
+
+message SubMessage
+{
+ repeated int32 array = 1 [(nanopb).max_count = 8];
+}
+
+/* Oneof in a message with other fields */
+message OneOfMessage
+{
+ required int32 prefix = 1;
+ oneof values
+ {
+ int32 first = 5;
+ string second = 6 [(nanopb).max_size = 8];
+ SubMessage third = 7;
+ }
+ required int32 suffix = 99;
+}
+
+/* Oneof in a message by itself */
+message PlainOneOfMessage
+{
+ oneof values
+ {
+ int32 first = 5;
+ string second = 6 [(nanopb).max_size = 8];
+ SubMessage third = 7;
+ }
+} \ No newline at end of file