From 262c62676cf740ec3ce14a22bde47b7968fec8f0 Mon Sep 17 00:00:00 2001 From: Petteri Aimonen Date: Sun, 8 Sep 2013 17:52:03 +0300 Subject: Start moving the tests into subfolders. Transition to SCons for build system for the tests. Only a few tests updated so far. Have to include all the rest before merging to mainline. Update issue 63 Status: Started --- tests/Makefile | 143 +---------- tests/SConstruct | 77 ++++++ tests/alltypes.options | 3 - tests/alltypes.proto | 93 ------- tests/alltypes/alltypes.options | 3 + tests/alltypes/alltypes.proto | 93 +++++++ tests/alltypes/decode_alltypes.c | 197 +++++++++++++++ tests/alltypes/encode_alltypes.c | 130 ++++++++++ tests/alltypes_with_extra_fields.pb | Bin 523 -> 0 bytes tests/backwards_compatibility/alltypes_legacy.c | 93 +++++++ tests/backwards_compatibility/alltypes_legacy.h | 178 +++++++++++++ tests/backwards_compatibility/decode_legacy.c | 197 +++++++++++++++ tests/backwards_compatibility/encode_legacy.c | 131 ++++++++++ tests/basic_buffer/SConscript | 12 + tests/basic_buffer/decode_buffer.c | 83 ++++++ tests/basic_buffer/encode_buffer.c | 33 +++ tests/basic_stream/decode_stream.c | 83 ++++++ tests/basic_stream/encode_stream.c | 37 +++ tests/bc_alltypes.pb.c | 93 ------- tests/bc_alltypes.pb.h | 178 ------------- tests/bc_decode.c | 197 --------------- tests/bc_encode.c | 131 ---------- tests/callbacks.proto | 16 -- tests/callbacks/callbacks.proto | 16 ++ tests/callbacks/decode_callbacks.c | 93 +++++++ tests/callbacks/encode_callbacks.c | 86 +++++++ tests/callbacks2.proto | 9 - tests/common/SConscript | 14 ++ tests/common/person.proto | 20 ++ tests/common/unittestproto.proto | 32 +++ tests/common/unittests.h | 14 ++ tests/decode_unittests.c | 306 ----------------------- tests/decode_unittests/SConscript | 4 + tests/decode_unittests/decode_unittests.c | 306 +++++++++++++++++++++++ tests/encode_unittests.c | 287 --------------------- tests/encode_unittests/SConscript | 5 + tests/encode_unittests/encode_unittests.c | 287 +++++++++++++++++++++ tests/extensions.options | 1 - tests/extensions.proto | 17 -- tests/extensions/decode_extensions.c | 43 ++++ tests/extensions/encode_extensions.c | 38 +++ tests/extensions/extensions.options | 1 + tests/extensions/extensions.proto | 17 ++ tests/extra_fields/alltypes_with_extra_fields.pb | Bin 0 -> 523 bytes tests/extra_fields/person_with_extra_field.pb | Bin 0 -> 90 bytes tests/funny-proto+name.proto | 0 tests/missing_fields.proto | 138 ---------- tests/missing_fields/missing_fields.c | 49 ++++ tests/missing_fields/missing_fields.proto | 138 ++++++++++ tests/multiple_files/callbacks.proto | 16 ++ tests/multiple_files/callbacks2.proto | 9 + tests/multiple_files/test_multiple_files.c | 13 + tests/no_messages.proto | 7 - tests/no_messages/no_messages.proto | 7 + tests/options.expected | 7 - tests/options.proto | 73 ------ tests/options/options.expected | 7 + tests/options/options.proto | 73 ++++++ tests/person.proto | 20 -- tests/person_with_extra_field.pb | Bin 90 -> 0 bytes tests/special_characters/funny-proto+name.proto | 0 tests/test_decode1.c | 83 ------ tests/test_decode2.c | 83 ------ tests/test_decode3.c | 197 --------------- tests/test_decode_callbacks.c | 93 ------- tests/test_decode_extensions.c | 43 ---- tests/test_encode1.c | 33 --- tests/test_encode2.c | 37 --- tests/test_encode3.c | 130 ---------- tests/test_encode_callbacks.c | 86 ------- tests/test_encode_extensions.c | 38 --- tests/test_missing_fields.c | 49 ---- tests/test_multiple_files.c | 13 - tests/testperson.pb | 3 - tests/unittestproto.proto | 32 --- tests/unittests.h | 14 -- 76 files changed, 2638 insertions(+), 2650 deletions(-) create mode 100644 tests/SConstruct delete mode 100644 tests/alltypes.options delete mode 100644 tests/alltypes.proto create mode 100644 tests/alltypes/alltypes.options create mode 100644 tests/alltypes/alltypes.proto create mode 100644 tests/alltypes/decode_alltypes.c create mode 100644 tests/alltypes/encode_alltypes.c delete mode 100644 tests/alltypes_with_extra_fields.pb create mode 100644 tests/backwards_compatibility/alltypes_legacy.c create mode 100644 tests/backwards_compatibility/alltypes_legacy.h create mode 100644 tests/backwards_compatibility/decode_legacy.c create mode 100644 tests/backwards_compatibility/encode_legacy.c create mode 100644 tests/basic_buffer/SConscript create mode 100644 tests/basic_buffer/decode_buffer.c create mode 100644 tests/basic_buffer/encode_buffer.c create mode 100644 tests/basic_stream/decode_stream.c create mode 100644 tests/basic_stream/encode_stream.c delete mode 100644 tests/bc_alltypes.pb.c delete mode 100644 tests/bc_alltypes.pb.h delete mode 100644 tests/bc_decode.c delete mode 100644 tests/bc_encode.c delete mode 100644 tests/callbacks.proto create mode 100644 tests/callbacks/callbacks.proto create mode 100644 tests/callbacks/decode_callbacks.c create mode 100644 tests/callbacks/encode_callbacks.c delete mode 100644 tests/callbacks2.proto create mode 100644 tests/common/SConscript create mode 100644 tests/common/person.proto create mode 100644 tests/common/unittestproto.proto create mode 100644 tests/common/unittests.h delete mode 100644 tests/decode_unittests.c create mode 100644 tests/decode_unittests/SConscript create mode 100644 tests/decode_unittests/decode_unittests.c delete mode 100644 tests/encode_unittests.c create mode 100644 tests/encode_unittests/SConscript create mode 100644 tests/encode_unittests/encode_unittests.c delete mode 100644 tests/extensions.options delete mode 100644 tests/extensions.proto create mode 100644 tests/extensions/decode_extensions.c create mode 100644 tests/extensions/encode_extensions.c create mode 100644 tests/extensions/extensions.options create mode 100644 tests/extensions/extensions.proto create mode 100644 tests/extra_fields/alltypes_with_extra_fields.pb create mode 100644 tests/extra_fields/person_with_extra_field.pb delete mode 100644 tests/funny-proto+name.proto delete mode 100644 tests/missing_fields.proto create mode 100644 tests/missing_fields/missing_fields.c create mode 100644 tests/missing_fields/missing_fields.proto create mode 100644 tests/multiple_files/callbacks.proto create mode 100644 tests/multiple_files/callbacks2.proto create mode 100644 tests/multiple_files/test_multiple_files.c delete mode 100644 tests/no_messages.proto create mode 100644 tests/no_messages/no_messages.proto delete mode 100644 tests/options.expected delete mode 100644 tests/options.proto create mode 100644 tests/options/options.expected create mode 100644 tests/options/options.proto delete mode 100644 tests/person.proto delete mode 100644 tests/person_with_extra_field.pb create mode 100644 tests/special_characters/funny-proto+name.proto delete mode 100644 tests/test_decode1.c delete mode 100644 tests/test_decode2.c delete mode 100644 tests/test_decode3.c delete mode 100644 tests/test_decode_callbacks.c delete mode 100644 tests/test_decode_extensions.c delete mode 100644 tests/test_encode1.c delete mode 100644 tests/test_encode2.c delete mode 100644 tests/test_encode3.c delete mode 100644 tests/test_encode_callbacks.c delete mode 100644 tests/test_encode_extensions.c delete mode 100644 tests/test_missing_fields.c delete mode 100644 tests/test_multiple_files.c delete mode 100644 tests/testperson.pb delete mode 100644 tests/unittestproto.proto delete mode 100644 tests/unittests.h (limited to 'tests') diff --git a/tests/Makefile b/tests/Makefile index 9696b79..fb37e63 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -1,143 +1,6 @@ -CFLAGS=-ansi -Wall -Werror -I .. -g -O0 -DEPS=../pb_decode.h ../pb_encode.h ../pb.h person.pb.h \ - callbacks2.pb.h callbacks.pb.h unittests.h unittestproto.pb.h \ - alltypes.pb.h missing_fields.pb.h -TESTS= decode_unittests encode_unittests \ - test_decode1 test_decode2 test_decode3 test_decode3_buf \ - test_encode1 test_encode2 test_encode3 test_encode3_buf \ - test_decode_callbacks test_encode_callbacks \ - test_missing_fields test_no_messages test_funny_name \ - test_multiple_files test_cxxcompile test_options \ - bc_encode bc_decode test_encode_extensions test_decode_extensions - -# More strict checks for the core part of nanopb -CC_VERSION=$(shell $(CC) -v 2>&1) -CFLAGS_CORE= -ifneq (,$(findstring gcc,$(CC_VERSION))) - CFLAGS_CORE=-pedantic -Wextra -Wcast-qual -Wlogical-op -Wconversion - CFLAGS+=--coverage -fstack-protector-all - LDFLAGS+=--coverage -endif -ifneq (,$(findstring clang,$(CC_VERSION))) - CFLAGS_CORE=-pedantic -Wextra -Wcast-qual -Wconversion -endif - -# Also use mudflap if it is available -# To enable, run with make -B USE_MUDFLAP=y -USE_MUDFLAP ?= n -ifeq ($(USE_MUDFLAP),y) - CFLAGS += -fmudflap - LDFLAGS += -lmudflap -fmudflap -endif - -all: breakpoints $(TESTS) run_unittests +all: + scons clean: - rm -f $(TESTS) person.pb* alltypes.pb* *.o *.gcda *.gcno *.pb.h *.pb.c - -%.pb.o: %.pb.c %.pb.h - $(CC) $(CFLAGS) $(CFLAGS_CORE) -c -o $@ $< - -%.o: %.c -%.o: %.c $(DEPS) - $(CC) $(CFLAGS) -c -o $@ $< - -pb_encode.o: ../pb_encode.c $(DEPS) - $(CC) $(CFLAGS) $(CFLAGS_CORE) -c -o $@ $< -pb_decode.o: ../pb_decode.c $(DEPS) - $(CC) $(CFLAGS) $(CFLAGS_CORE) -c -o $@ $< - -# Test for compilability with c++ compiler - -pb_encode.cxx.o: ../pb_encode.c $(DEPS) - $(CXX) $(CFLAGS) $(CFLAGS_CORE) -c -o $@ $< -pb_decode.cxx.o: ../pb_decode.c $(DEPS) - $(CXX) $(CFLAGS) $(CFLAGS_CORE) -c -o $@ $< - -# Test for PB_BUF_ONLY compilation option - -pb_encode.buf.o: ../pb_encode.c $(DEPS) - $(CC) -DPB_BUFFER_ONLY $(CFLAGS) $(CFLAGS_CORE) -c -o $@ $< -pb_decode.buf.o: ../pb_decode.c $(DEPS) - $(CC) -DPB_BUFFER_ONLY $(CFLAGS) $(CFLAGS_CORE) -c -o $@ $< -%.buf.o: %.c $(DEPS) - $(CC) -DPB_BUFFER_ONLY $(CFLAGS) -c -o $@ $< -test_encode3_buf: test_encode3.buf.o pb_encode.buf.o alltypes.pb.o - $(CC) $(LDFLAGS) $^ -o $@ -test_decode3_buf: test_decode3.buf.o pb_decode.buf.o alltypes.pb.o - $(CC) $(LDFLAGS) $^ -o $@ - -test_cxxcompile: pb_encode.cxx.o pb_decode.cxx.o -test_decode1: test_decode1.o pb_decode.o person.pb.o -test_decode2: test_decode2.o pb_decode.o person.pb.o -test_decode3: test_decode3.o pb_decode.o alltypes.pb.o -test_encode1: test_encode1.o pb_encode.o person.pb.o -test_encode2: test_encode2.o pb_encode.o person.pb.o -test_encode3: test_encode3.o pb_encode.o alltypes.pb.o -test_multiple_files: test_multiple_files.o pb_encode.o callbacks2.pb.o callbacks.pb.o -test_decode_callbacks: test_decode_callbacks.o pb_decode.o callbacks.pb.o -test_encode_callbacks: test_encode_callbacks.o pb_encode.o callbacks.pb.o -test_missing_fields: test_missing_fields.o pb_encode.o pb_decode.o missing_fields.pb.o -decode_unittests: decode_unittests.o pb_decode.o unittestproto.pb.o -encode_unittests: encode_unittests.o pb_encode.o unittestproto.pb.o -test_no_messages: no_messages.pb.h no_messages.pb.c no_messages.pb.o -test_funny_name: funny-proto+name.pb.h funny-proto+name.pb.o -bc_encode: bc_alltypes.pb.o pb_encode.o bc_encode.o -bc_decode: bc_alltypes.pb.o pb_decode.o bc_decode.o -test_encode_extensions: test_encode_extensions.c pb_encode.o alltypes.pb.o extensions.pb.o -test_decode_extensions: test_decode_extensions.c pb_decode.o alltypes.pb.o extensions.pb.o - -%.pb: %.proto - protoc -I. -I../generator -I/usr/include -o$@ $< - -%.pb.c %.pb.h: %.pb ../generator/nanopb_generator.py - python ../generator/nanopb_generator.py $< - -breakpoints: ../*.c *.c - grep -n 'return false;' $^ | cut -d: -f-2 | xargs -n 1 echo b > $@ - -coverage: run_unittests - gcov pb_encode.gcda - gcov pb_decode.gcda - -run_unittests: $(TESTS) - rm -f *.gcda - - ./decode_unittests > /dev/null - ./encode_unittests > /dev/null - - [ "`./test_encode1 | ./test_decode1`" = \ - "`./test_encode1 | protoc --decode=Person -I. -I../generator -I/usr/include person.proto`" ] - - [ "`./test_encode2 | ./test_decode1`" = \ - "`./test_encode2 | protoc --decode=Person -I. -I../generator -I/usr/include person.proto`" ] - - [ "`./test_encode2 | ./test_decode2`" = \ - "`./test_encode2 | protoc --decode=Person -I. -I../generator -I/usr/include person.proto`" ] - - [ "`./test_decode2 < person_with_extra_field.pb`" = \ - "`./test_encode2 | ./test_decode2`" ] - - [ "`./test_encode_callbacks | ./test_decode_callbacks`" = \ - "`./test_encode_callbacks | protoc --decode=TestMessage callbacks.proto`" ] - - ./test_encode3 | ./test_decode3 - ./test_encode3 1 | ./test_decode3 1 - ./test_encode3 1 | protoc --decode=AllTypes -I. -I../generator -I/usr/include alltypes.proto >/dev/null - ./test_encode3_buf 1 | ./test_decode3_buf 1 - ./test_decode3 < alltypes_with_extra_fields.pb - ./bc_encode | ./bc_decode - ./test_encode_extensions | ./test_decode_extensions - - ./test_missing_fields - -test_options: options.pb.h options.expected options.pb.o - cat options.expected | while read -r p; do \ - if ! grep -q "$$p" $<; then \ - echo Expected: "$$p"; \ - exit 1; \ - fi \ - done + scons -c -run_fuzztest: test_decode3 - bash -c 'ulimit -c unlimited; I=1; while true; do cat /dev/urandom | ./test_decode3 > /dev/null; I=$$(($$I+1)); echo -en "\r$$I"; done' diff --git a/tests/SConstruct b/tests/SConstruct new file mode 100644 index 0000000..0ec1e54 --- /dev/null +++ b/tests/SConstruct @@ -0,0 +1,77 @@ +env = DefaultEnvironment() + +env.Append(CPPPATH = ["#../", "#common"]) + +# Build command for building .pb from .proto using protoc +def proto_actions(source, target, env, for_signature): + dirs = ' '.join(['-I' + env.GetBuildPath(d) for d in env['PROTOCPATH']]) + return '$PROTOC $PROTOCFLAGS %s -o%s %s' % (dirs, target[0], source[0]) + +proto_file_builder = Builder(generator = proto_actions, + suffix = '.pb', + src_suffix = '.proto') +env.Append(BUILDERS = {'Proto': proto_file_builder}) +env.SetDefault(PROTOC = 'protoc') + +# Define the include path to find nanopb.proto +env.Append(PROTOCPATH = ['#../generator', '/usr/include', '.']) + +# Build command for running nanopb generator +import os.path +def nanopb_targets(target, source, env): + basename = os.path.splitext(str(source[0]))[0] + target.append(basename + '.pb.h') + return target, source + +nanopb_file_builder = Builder(action = '$NANOPB_GENERATOR $NANOPB_FLAGS $SOURCE', + suffix = '.pb.c', + src_suffix = '.pb', + emitter = nanopb_targets) +env.Append(BUILDERS = {'Nanopb': nanopb_file_builder}) +env.SetDefault(NANOPB_GENERATOR = 'python ' + env.GetBuildPath("#../generator/nanopb_generator.py")) + +# Combined method to run both protoc and nanopb generator +def run_protoc_and_nanopb(env, source): + b1 = env.Proto(source) + b2 = env.Nanopb(source) + return b1 + b2 +env.AddMethod(run_protoc_and_nanopb, "NanopbProto") + +# Build command that runs a test program and saves the output +def run_test_actions(source, target, env, for_signature): + cmd = str(source[0]) # Name of binary + if len(source) > 1: + cmd += ' <' + str(source[1]) # Input file + cmd += ' >' + str(target[0]) + return cmd + +run_test_builder = Builder(generator = run_test_actions, + suffix = '.output') +env.Append(BUILDERS = {'RunTest': run_test_builder}) + +# Build command that decodes a message using protoc +def decode_actions(source, target, env, for_signature): + dirs = ' '.join(['-I' + env.GetBuildPath(d) for d in env['PROTOCPATH']]) + return '$PROTOC $PROTOCFLAGS %s --decode=%s %s <%s >%s' % (dirs, env['MESSAGE'], source[1], source[0], target[0]) + +decode_builder = Builder(generator = decode_actions, + suffix = '.decoded') +env.Append(BUILDERS = {'Decode': decode_builder}) + +# Build command that asserts that two files be equal +def compare_files(target, source, env): + data1 = open(str(source[0]), 'rb').read() + data2 = open(str(source[1]), 'rb').read() + if data1 == data2: +# open(str(target[0]), 'w').write('OK') + return 0 + else: + return "Test failed: %s and %s differ!" % (source[0], source[1]) + +compare_builder = Builder(action = compare_files, + suffix = '.equal') +env.Append(BUILDERS = {'Compare': compare_builder}) + +# Now include the SConscript files from all subdirectories +SConscript(Glob('*/SConscript'), exports = 'env') + diff --git a/tests/alltypes.options b/tests/alltypes.options deleted file mode 100644 index b31e3cf..0000000 --- a/tests/alltypes.options +++ /dev/null @@ -1,3 +0,0 @@ -* max_size:16 -* max_count:5 - diff --git a/tests/alltypes.proto b/tests/alltypes.proto deleted file mode 100644 index a2cf8bb..0000000 --- a/tests/alltypes.proto +++ /dev/null @@ -1,93 +0,0 @@ -message SubMessage { - required string substuff1 = 1 [default = "1"]; - required int32 substuff2 = 2 [default = 2]; - optional fixed32 substuff3 = 3 [default = 3]; -} - -message EmptyMessage { - -} - -enum MyEnum { - Zero = 0; - First = 1; - Second = 2; - Truth = 42; -} - -message AllTypes { - required int32 req_int32 = 1; - required int64 req_int64 = 2; - required uint32 req_uint32 = 3; - required uint64 req_uint64 = 4; - required sint32 req_sint32 = 5; - required sint64 req_sint64 = 6; - required bool req_bool = 7; - - required fixed32 req_fixed32 = 8; - required sfixed32 req_sfixed32= 9; - required float req_float = 10; - - required fixed64 req_fixed64 = 11; - required sfixed64 req_sfixed64= 12; - required double req_double = 13; - - required string req_string = 14; - required bytes req_bytes = 15; - required SubMessage req_submsg = 16; - required MyEnum req_enum = 17; - required EmptyMessage req_emptymsg = 18; - - - repeated int32 rep_int32 = 21; - repeated int64 rep_int64 = 22; - repeated uint32 rep_uint32 = 23; - repeated uint64 rep_uint64 = 24; - repeated sint32 rep_sint32 = 25; - repeated sint64 rep_sint64 = 26; - repeated bool rep_bool = 27; - - repeated fixed32 rep_fixed32 = 28; - repeated sfixed32 rep_sfixed32= 29; - repeated float rep_float = 30; - - repeated fixed64 rep_fixed64 = 31; - repeated sfixed64 rep_sfixed64= 32; - repeated double rep_double = 33; - - repeated string rep_string = 34; - repeated bytes rep_bytes = 35; - repeated SubMessage rep_submsg = 36; - repeated MyEnum rep_enum = 37; - repeated EmptyMessage rep_emptymsg = 38; - - optional int32 opt_int32 = 41 [default = 4041]; - optional int64 opt_int64 = 42 [default = 4042]; - optional uint32 opt_uint32 = 43 [default = 4043]; - optional uint64 opt_uint64 = 44 [default = 4044]; - optional sint32 opt_sint32 = 45 [default = 4045]; - optional sint64 opt_sint64 = 46 [default = 4046]; - optional bool opt_bool = 47 [default = false]; - - optional fixed32 opt_fixed32 = 48 [default = 4048]; - optional sfixed32 opt_sfixed32= 49 [default = 4049]; - optional float opt_float = 50 [default = 4050]; - - optional fixed64 opt_fixed64 = 51 [default = 4051]; - optional sfixed64 opt_sfixed64= 52 [default = 4052]; - optional double opt_double = 53 [default = 4053]; - - optional string opt_string = 54 [default = "4054"]; - optional bytes opt_bytes = 55 [default = "4055"]; - optional SubMessage opt_submsg = 56; - optional MyEnum opt_enum = 57 [default = Second]; - optional EmptyMessage opt_emptymsg = 58; - - // Just to make sure that the size of the fields has been calculated - // properly, i.e. otherwise a bug in last field might not be detected. - required int32 end = 99; - - - extensions 200 to 255; -} - diff --git a/tests/alltypes/alltypes.options b/tests/alltypes/alltypes.options new file mode 100644 index 0000000..b31e3cf --- /dev/null +++ b/tests/alltypes/alltypes.options @@ -0,0 +1,3 @@ +* max_size:16 +* max_count:5 + diff --git a/tests/alltypes/alltypes.proto b/tests/alltypes/alltypes.proto new file mode 100644 index 0000000..a2cf8bb --- /dev/null +++ b/tests/alltypes/alltypes.proto @@ -0,0 +1,93 @@ +message SubMessage { + required string substuff1 = 1 [default = "1"]; + required int32 substuff2 = 2 [default = 2]; + optional fixed32 substuff3 = 3 [default = 3]; +} + +message EmptyMessage { + +} + +enum MyEnum { + Zero = 0; + First = 1; + Second = 2; + Truth = 42; +} + +message AllTypes { + required int32 req_int32 = 1; + required int64 req_int64 = 2; + required uint32 req_uint32 = 3; + required uint64 req_uint64 = 4; + required sint32 req_sint32 = 5; + required sint64 req_sint64 = 6; + required bool req_bool = 7; + + required fixed32 req_fixed32 = 8; + required sfixed32 req_sfixed32= 9; + required float req_float = 10; + + required fixed64 req_fixed64 = 11; + required sfixed64 req_sfixed64= 12; + required double req_double = 13; + + required string req_string = 14; + required bytes req_bytes = 15; + required SubMessage req_submsg = 16; + required MyEnum req_enum = 17; + required EmptyMessage req_emptymsg = 18; + + + repeated int32 rep_int32 = 21; + repeated int64 rep_int64 = 22; + repeated uint32 rep_uint32 = 23; + repeated uint64 rep_uint64 = 24; + repeated sint32 rep_sint32 = 25; + repeated sint64 rep_sint64 = 26; + repeated bool rep_bool = 27; + + repeated fixed32 rep_fixed32 = 28; + repeated sfixed32 rep_sfixed32= 29; + repeated float rep_float = 30; + + repeated fixed64 rep_fixed64 = 31; + repeated sfixed64 rep_sfixed64= 32; + repeated double rep_double = 33; + + repeated string rep_string = 34; + repeated bytes rep_bytes = 35; + repeated SubMessage rep_submsg = 36; + repeated MyEnum rep_enum = 37; + repeated EmptyMessage rep_emptymsg = 38; + + optional int32 opt_int32 = 41 [default = 4041]; + optional int64 opt_int64 = 42 [default = 4042]; + optional uint32 opt_uint32 = 43 [default = 4043]; + optional uint64 opt_uint64 = 44 [default = 4044]; + optional sint32 opt_sint32 = 45 [default = 4045]; + optional sint64 opt_sint64 = 46 [default = 4046]; + optional bool opt_bool = 47 [default = false]; + + optional fixed32 opt_fixed32 = 48 [default = 4048]; + optional sfixed32 opt_sfixed32= 49 [default = 4049]; + optional float opt_float = 50 [default = 4050]; + + optional fixed64 opt_fixed64 = 51 [default = 4051]; + optional sfixed64 opt_sfixed64= 52 [default = 4052]; + optional double opt_double = 53 [default = 4053]; + + optional string opt_string = 54 [default = "4054"]; + optional bytes opt_bytes = 55 [default = "4055"]; + optional SubMessage opt_submsg = 56; + optional MyEnum opt_enum = 57 [default = Second]; + optional EmptyMessage opt_emptymsg = 58; + + // Just to make sure that the size of the fields has been calculated + // properly, i.e. otherwise a bug in last field might not be detected. + required int32 end = 99; + + + extensions 200 to 255; +} + diff --git a/tests/alltypes/decode_alltypes.c b/tests/alltypes/decode_alltypes.c new file mode 100644 index 0000000..55d025c --- /dev/null +++ b/tests/alltypes/decode_alltypes.c @@ -0,0 +1,197 @@ +/* Tests the decoding of all types. + * This is the counterpart of test_encode3. + * Run e.g. ./test_encode3 | ./test_decode3 + */ + +#include +#include +#include +#include +#include "alltypes.pb.h" + +#define TEST(x) if (!(x)) { \ + printf("Test " #x " failed.\n"); \ + return false; \ + } + +/* This function is called once from main(), it handles + the decoding and checks the fields. */ +bool check_alltypes(pb_istream_t *stream, int mode) +{ + AllTypes alltypes; + + /* Fill with garbage to better detect initialization errors */ + memset(&alltypes, 0xAA, sizeof(alltypes)); + + if (!pb_decode(stream, AllTypes_fields, &alltypes)) + return false; + + TEST(alltypes.req_int32 == -1001); + TEST(alltypes.req_int64 == -1002); + TEST(alltypes.req_uint32 == 1003); + TEST(alltypes.req_uint64 == 1004); + TEST(alltypes.req_sint32 == -1005); + TEST(alltypes.req_sint64 == -1006); + TEST(alltypes.req_bool == true); + + TEST(alltypes.req_fixed32 == 1008); + TEST(alltypes.req_sfixed32 == -1009); + TEST(alltypes.req_float == 1010.0f); + + TEST(alltypes.req_fixed64 == 1011); + TEST(alltypes.req_sfixed64 == -1012); + TEST(alltypes.req_double == 1013.0f); + + TEST(strcmp(alltypes.req_string, "1014") == 0); + TEST(alltypes.req_bytes.size == 4); + TEST(memcmp(alltypes.req_bytes.bytes, "1015", 4) == 0); + TEST(strcmp(alltypes.req_submsg.substuff1, "1016") == 0); + TEST(alltypes.req_submsg.substuff2 == 1016); + TEST(alltypes.req_submsg.substuff3 == 3); + TEST(alltypes.req_enum == MyEnum_Truth); + + TEST(alltypes.rep_int32_count == 5 && alltypes.rep_int32[4] == -2001 && alltypes.rep_int32[0] == 0); + TEST(alltypes.rep_int64_count == 5 && alltypes.rep_int64[4] == -2002 && alltypes.rep_int64[0] == 0); + TEST(alltypes.rep_uint32_count == 5 && alltypes.rep_uint32[4] == 2003 && alltypes.rep_uint32[0] == 0); + TEST(alltypes.rep_uint64_count == 5 && alltypes.rep_uint64[4] == 2004 && alltypes.rep_uint64[0] == 0); + TEST(alltypes.rep_sint32_count == 5 && alltypes.rep_sint32[4] == -2005 && alltypes.rep_sint32[0] == 0); + TEST(alltypes.rep_sint64_count == 5 && alltypes.rep_sint64[4] == -2006 && alltypes.rep_sint64[0] == 0); + TEST(alltypes.rep_bool_count == 5 && alltypes.rep_bool[4] == true && alltypes.rep_bool[0] == false); + + TEST(alltypes.rep_fixed32_count == 5 && alltypes.rep_fixed32[4] == 2008 && alltypes.rep_fixed32[0] == 0); + TEST(alltypes.rep_sfixed32_count == 5 && alltypes.rep_sfixed32[4] == -2009 && alltypes.rep_sfixed32[0] == 0); + TEST(alltypes.rep_float_count == 5 && alltypes.rep_float[4] == 2010.0f && alltypes.rep_float[0] == 0.0f); + + TEST(alltypes.rep_fixed64_count == 5 && alltypes.rep_fixed64[4] == 2011 && alltypes.rep_fixed64[0] == 0); + TEST(alltypes.rep_sfixed64_count == 5 && alltypes.rep_sfixed64[4] == -2012 && alltypes.rep_sfixed64[0] == 0); + TEST(alltypes.rep_double_count == 5 && alltypes.rep_double[4] == 2013.0 && alltypes.rep_double[0] == 0.0); + + TEST(alltypes.rep_string_count == 5 && strcmp(alltypes.rep_string[4], "2014") == 0 && alltypes.rep_string[0][0] == '\0'); + TEST(alltypes.rep_bytes_count == 5 && alltypes.rep_bytes[4].size == 4 && alltypes.rep_bytes[0].size == 0); + TEST(memcmp(alltypes.rep_bytes[4].bytes, "2015", 4) == 0); + + TEST(alltypes.rep_submsg_count == 5); + TEST(strcmp(alltypes.rep_submsg[4].substuff1, "2016") == 0 && alltypes.rep_submsg[0].substuff1[0] == '\0'); + TEST(alltypes.rep_submsg[4].substuff2 == 2016 && alltypes.rep_submsg[0].substuff2 == 0); + TEST(alltypes.rep_submsg[4].substuff3 == 2016 && alltypes.rep_submsg[0].substuff3 == 3); + + TEST(alltypes.rep_enum_count == 5 && alltypes.rep_enum[4] == MyEnum_Truth && alltypes.rep_enum[0] == MyEnum_Zero); + TEST(alltypes.rep_emptymsg_count == 5); + + if (mode == 0) + { + /* Expect default values */ + TEST(alltypes.has_opt_int32 == false); + TEST(alltypes.opt_int32 == 4041); + TEST(alltypes.has_opt_int64 == false); + TEST(alltypes.opt_int64 == 4042); + TEST(alltypes.has_opt_uint32 == false); + TEST(alltypes.opt_uint32 == 4043); + TEST(alltypes.has_opt_uint64 == false); + TEST(alltypes.opt_uint64 == 4044); + TEST(alltypes.has_opt_sint32 == false); + TEST(alltypes.opt_sint32 == 4045); + TEST(alltypes.has_opt_sint64 == false); + TEST(alltypes.opt_sint64 == 4046); + TEST(alltypes.has_opt_bool == false); + TEST(alltypes.opt_bool == false); + + TEST(alltypes.has_opt_fixed32 == false); + TEST(alltypes.opt_fixed32 == 4048); + TEST(alltypes.has_opt_sfixed32 == false); + TEST(alltypes.opt_sfixed32 == 4049); + TEST(alltypes.has_opt_float == false); + TEST(alltypes.opt_float == 4050.0f); + + TEST(alltypes.has_opt_fixed64 == false); + TEST(alltypes.opt_fixed64 == 4051); + TEST(alltypes.has_opt_sfixed64 == false); + TEST(alltypes.opt_sfixed64 == 4052); + TEST(alltypes.has_opt_double == false); + TEST(alltypes.opt_double == 4053.0); + + TEST(alltypes.has_opt_string == false); + TEST(strcmp(alltypes.opt_string, "4054") == 0); + TEST(alltypes.has_opt_bytes == false); + TEST(alltypes.opt_bytes.size == 4); + TEST(memcmp(alltypes.opt_bytes.bytes, "4055", 4) == 0); + TEST(alltypes.has_opt_submsg == false); + TEST(strcmp(alltypes.opt_submsg.substuff1, "1") == 0); + TEST(alltypes.opt_submsg.substuff2 == 2); + TEST(alltypes.opt_submsg.substuff3 == 3); + TEST(alltypes.has_opt_enum == false); + TEST(alltypes.opt_enum == MyEnum_Second); + TEST(alltypes.has_opt_emptymsg == false); + } + else + { + /* Expect filled-in values */ + TEST(alltypes.has_opt_int32 == true); + TEST(alltypes.opt_int32 == 3041); + TEST(alltypes.has_opt_int64 == true); + TEST(alltypes.opt_int64 == 3042); + TEST(alltypes.has_opt_uint32 == true); + TEST(alltypes.opt_uint32 == 3043); + TEST(alltypes.has_opt_uint64 == true); + TEST(alltypes.opt_uint64 == 3044); + TEST(alltypes.has_opt_sint32 == true); + TEST(alltypes.opt_sint32 == 3045); + TEST(alltypes.has_opt_sint64 == true); + TEST(alltypes.opt_sint64 == 3046); + TEST(alltypes.has_opt_bool == true); + TEST(alltypes.opt_bool == true); + + TEST(alltypes.has_opt_fixed32 == true); + TEST(alltypes.opt_fixed32 == 3048); + TEST(alltypes.has_opt_sfixed32 == true); + TEST(alltypes.opt_sfixed32 == 3049); + TEST(alltypes.has_opt_float == true); + TEST(alltypes.opt_float == 3050.0f); + + TEST(alltypes.has_opt_fixed64 == true); + TEST(alltypes.opt_fixed64 == 3051); + TEST(alltypes.has_opt_sfixed64 == true); + TEST(alltypes.opt_sfixed64 == 3052); + TEST(alltypes.has_opt_double == true); + TEST(alltypes.opt_double == 3053.0); + + TEST(alltypes.has_opt_string == true); + TEST(strcmp(alltypes.opt_string, "3054") == 0); + TEST(alltypes.has_opt_bytes == true); + TEST(alltypes.opt_bytes.size == 4); + TEST(memcmp(alltypes.opt_bytes.bytes, "3055", 4) == 0); + TEST(alltypes.has_opt_submsg == true); + TEST(strcmp(alltypes.opt_submsg.substuff1, "3056") == 0); + TEST(alltypes.opt_submsg.substuff2 == 3056); + TEST(alltypes.opt_submsg.substuff3 == 3); + TEST(alltypes.has_opt_enum == true); + TEST(alltypes.opt_enum == MyEnum_Truth); + TEST(alltypes.has_opt_emptymsg == true); + } + + TEST(alltypes.end == 1099); + + return true; +} + +int main(int argc, char **argv) +{ + /* Whether to expect the optional values or the default values. */ + int mode = (argc > 1) ? atoi(argv[1]) : 0; + + /* Read the data into buffer */ + uint8_t buffer[1024]; + size_t count = fread(buffer, 1, sizeof(buffer), stdin); + + /* Construct a pb_istream_t for reading from the buffer */ + pb_istream_t stream = pb_istream_from_buffer(buffer, count); + + /* Decode and print out the stuff */ + if (!check_alltypes(&stream, mode)) + { + printf("Parsing failed: %s\n", PB_GET_ERROR(&stream)); + return 1; + } else { + return 0; + } +} diff --git a/tests/alltypes/encode_alltypes.c b/tests/alltypes/encode_alltypes.c new file mode 100644 index 0000000..982ad3c --- /dev/null +++ b/tests/alltypes/encode_alltypes.c @@ -0,0 +1,130 @@ +/* Attempts to test all the datatypes supported by ProtoBuf. + */ + +#include +#include +#include +#include +#include "alltypes.pb.h" + +int main(int argc, char **argv) +{ + int mode = (argc > 1) ? atoi(argv[1]) : 0; + + /* Initialize the structure with constants */ + AllTypes alltypes = {0}; + + alltypes.req_int32 = -1001; + alltypes.req_int64 = -1002; + alltypes.req_uint32 = 1003; + alltypes.req_uint64 = 1004; + alltypes.req_sint32 = -1005; + alltypes.req_sint64 = -1006; + alltypes.req_bool = true; + + alltypes.req_fixed32 = 1008; + alltypes.req_sfixed32 = -1009; + alltypes.req_float = 1010.0f; + + alltypes.req_fixed64 = 1011; + alltypes.req_sfixed64 = -1012; + alltypes.req_double = 1013.0; + + strcpy(alltypes.req_string, "1014"); + alltypes.req_bytes.size = 4; + memcpy(alltypes.req_bytes.bytes, "1015", 4); + strcpy(alltypes.req_submsg.substuff1, "1016"); + alltypes.req_submsg.substuff2 = 1016; + alltypes.req_enum = MyEnum_Truth; + + alltypes.rep_int32_count = 5; alltypes.rep_int32[4] = -2001; + alltypes.rep_int64_count = 5; alltypes.rep_int64[4] = -2002; + alltypes.rep_uint32_count = 5; alltypes.rep_uint32[4] = 2003; + alltypes.rep_uint64_count = 5; alltypes.rep_uint64[4] = 2004; + alltypes.rep_sint32_count = 5; alltypes.rep_sint32[4] = -2005; + alltypes.rep_sint64_count = 5; alltypes.rep_sint64[4] = -2006; + alltypes.rep_bool_count = 5; alltypes.rep_bool[4] = true; + + alltypes.rep_fixed32_count = 5; alltypes.rep_fixed32[4] = 2008; + alltypes.rep_sfixed32_count = 5; alltypes.rep_sfixed32[4] = -2009; + alltypes.rep_float_count = 5; alltypes.rep_float[4] = 2010.0f; + + alltypes.rep_fixed64_count = 5; alltypes.rep_fixed64[4] = 2011; + alltypes.rep_sfixed64_count = 5; alltypes.rep_sfixed64[4] = -2012; + alltypes.rep_double_count = 5; alltypes.rep_double[4] = 2013.0; + + alltypes.rep_string_count = 5; strcpy(alltypes.rep_string[4], "2014"); + alltypes.rep_bytes_count = 5; alltypes.rep_bytes[4].size = 4; + memcpy(alltypes.rep_bytes[4].bytes, "2015", 4); + + alltypes.rep_submsg_count = 5; + strcpy(alltypes.rep_submsg[4].substuff1, "2016"); + alltypes.rep_submsg[4].substuff2 = 2016; + alltypes.rep_submsg[4].has_substuff3 = true; + alltypes.rep_submsg[4].substuff3 = 2016; + + alltypes.rep_enum_count = 5; alltypes.rep_enum[4] = MyEnum_Truth; + alltypes.rep_emptymsg_count = 5; + + if (mode != 0) + { + /* Fill in values for optional fields */ + alltypes.has_opt_int32 = true; + alltypes.opt_int32 = 3041; + alltypes.has_opt_int64 = true; + alltypes.opt_int64 = 3042; + alltypes.has_opt_uint32 = true; + alltypes.opt_uint32 = 3043; + alltypes.has_opt_uint64 = true; + alltypes.opt_uint64 = 3044; + alltypes.has_opt_sint32 = true; + alltypes.opt_sint32 = 3045; + alltypes.has_opt_sint64 = true; + alltypes.opt_sint64 = 3046; + alltypes.has_opt_bool = true; + alltypes.opt_bool = true; + + alltypes.has_opt_fixed32 = true; + alltypes.opt_fixed32 = 3048; + alltypes.has_opt_sfixed32 = true; + alltypes.opt_sfixed32 = 3049; + alltypes.has_opt_float = true; + alltypes.opt_float = 3050.0f; + + alltypes.has_opt_fixed64 = true; + alltypes.opt_fixed64 = 3051; + alltypes.has_opt_sfixed64 = true; + alltypes.opt_sfixed64 = 3052; + alltypes.has_opt_double = true; + alltypes.opt_double = 3053.0; + + alltypes.has_opt_string = true; + strcpy(alltypes.opt_string, "3054"); + alltypes.has_opt_bytes = true; + alltypes.opt_bytes.size = 4; + memcpy(alltypes.opt_bytes.bytes, "3055", 4); + alltypes.has_opt_submsg = true; + strcpy(alltypes.opt_submsg.substuff1, "3056"); + alltypes.opt_submsg.substuff2 = 3056; + alltypes.has_opt_enum = true; + alltypes.opt_enum = MyEnum_Truth; + alltypes.has_opt_emptymsg = true; + } + + alltypes.end = 1099; + + uint8_t buffer[1024]; + pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer)); + + /* Now encode it and check if we succeeded. */ + if (pb_encode(&stream, AllTypes_fields, &alltypes)) + { + fwrite(buffer, 1, stream.bytes_written, stdout); + return 0; /* Success */ + } + else + { + fprintf(stderr, "Encoding failed: %s\n", PB_GET_ERROR(&stream)); + return 1; /* Failure */ + } +} diff --git a/tests/alltypes_with_extra_fields.pb b/tests/alltypes_with_extra_fields.pb deleted file mode 100644 index f9f5394..0000000 Binary files a/tests/alltypes_with_extra_fields.pb and /dev/null differ diff --git a/tests/backwards_compatibility/alltypes_legacy.c b/tests/backwards_compatibility/alltypes_legacy.c new file mode 100644 index 0000000..b144b1e --- /dev/null +++ b/tests/backwards_compatibility/alltypes_legacy.c @@ -0,0 +1,93 @@ +/* Automatically generated nanopb constant definitions */ +/* Generated by 0.2.0-dev at Sun Feb 17 00:09:53 2013. */ +/* This is a file generated using nanopb-0.2.0-dev. + * It is used as a part of test suite in order to detect any + * incompatible changes made to the generator in future versions. + */ + +#include "bc_alltypes.pb.h" + +const char SubMessage_substuff1_default[16] = "1"; +const int32_t SubMessage_substuff2_default = 2; +const uint32_t SubMessage_substuff3_default = 3; +const int32_t AllTypes_opt_int32_default = 4041; +const int64_t AllTypes_opt_int64_default = 4042; +const uint32_t AllTypes_opt_uint32_default = 4043; +const uint64_t AllTypes_opt_uint64_default = 4044; +const int32_t AllTypes_opt_sint32_default = 4045; +const int64_t AllTypes_opt_sint64_default = 4046; +const bool AllTypes_opt_bool_default = false; +const uint32_t AllTypes_opt_fixed32_default = 4048; +const int32_t AllTypes_opt_sfixed32_default = 4049; +const float AllTypes_opt_float_default = 4050; +const uint64_t AllTypes_opt_fixed64_default = 4051; +const int64_t AllTypes_opt_sfixed64_default = 4052; +const double AllTypes_opt_double_default = 4053; +const char AllTypes_opt_string_default[16] = "4054"; +const AllTypes_opt_bytes_t AllTypes_opt_bytes_default = {4, {0x34,0x30,0x35,0x35}}; +const MyEnum AllTypes_opt_enum_default = MyEnum_Second; + + +const pb_field_t SubMessage_fields[4] = { + PB_FIELD( 1, STRING , REQUIRED, STATIC, SubMessage, substuff1, substuff1, &SubMessage_substuff1_default), + PB_FIELD( 2, INT32 , REQUIRED, STATIC, SubMessage, substuff2, substuff1, &SubMessage_substuff2_default), + PB_FIELD( 3, FIXED32 , OPTIONAL, STATIC, SubMessage, substuff3, substuff2, &SubMessage_substuff3_default), + PB_LAST_FIELD +}; + +const pb_field_t AllTypes_fields[53] = { + PB_FIELD( 1, INT32 , REQUIRED, STATIC, AllTypes, req_int32, req_int32, 0), + PB_FIELD( 2, INT64 , REQUIRED, STATIC, AllTypes, req_int64, req_int32, 0), + PB_FIELD( 3, UINT32 , REQUIRED, STATIC, AllTypes, req_uint32, req_int64, 0), + PB_FIELD( 4, UINT64 , REQUIRED, STATIC, AllTypes, req_uint64, req_uint32, 0), + PB_FIELD( 5, SINT32 , REQUIRED, STATIC, AllTypes, req_sint32, req_uint64, 0), + PB_FIELD( 6, SINT64 , REQUIRED, STATIC, AllTypes, req_sint64, req_sint32, 0), + PB_FIELD( 7, BOOL , REQUIRED, STATIC, AllTypes, req_bool, req_sint64, 0), + PB_FIELD( 8, FIXED32 , REQUIRED, STATIC, AllTypes, req_fixed32, req_bool, 0), + PB_FIELD( 9, SFIXED32, REQUIRED, STATIC, AllTypes, req_sfixed32, req_fixed32, 0), + PB_FIELD( 10, FLOAT , REQUIRED, STATIC, AllTypes, req_float, req_sfixed32, 0), + PB_FIELD( 11, FIXED64 , REQUIRED, STATIC, AllTypes, req_fixed64, req_float, 0), + PB_FIELD( 12, SFIXED64, REQUIRED, STATIC, AllTypes, req_sfixed64, req_fixed64, 0), + PB_FIELD( 13, DOUBLE , REQUIRED, STATIC, AllTypes, req_double, req_sfixed64, 0), + PB_FIELD( 14, STRING , REQUIRED, STATIC, AllTypes, req_string, req_double, 0), + PB_FIELD( 15, BYTES , REQUIRED, STATIC, AllTypes, req_bytes, req_string, 0), + PB_FIELD( 16, MESSAGE , REQUIRED, STATIC, AllTypes, req_submsg, req_bytes, &SubMessage_fields), + PB_FIELD( 17, ENUM , REQUIRED, STATIC, AllTypes, req_enum, req_submsg, 0), + PB_FIELD( 21, INT32 , REPEATED, STATIC, AllTypes, rep_int32, req_enum, 0), + PB_FIELD( 22, INT64 , REPEATED, STATIC, AllTypes, rep_int64, rep_int32, 0), + PB_FIELD( 23, UINT32 , REPEATED, STATIC, AllTypes, rep_uint32, rep_int64, 0), + PB_FIELD( 24, UINT64 , REPEATED, STATIC, AllTypes, rep_uint64, rep_uint32, 0), + PB_FIELD( 25, SINT32 , REPEATED, STATIC, AllTypes, rep_sint32, rep_uint64, 0), + PB_FIELD( 26, SINT64 , REPEATED, STATIC, AllTypes, rep_sint64, rep_sint32, 0), + PB_FIELD( 27, BOOL , REPEATED, STATIC, AllTypes, rep_bool, rep_sint64, 0), + PB_FIELD( 28, FIXED32 , REPEATED, STATIC, AllTypes, rep_fixed32, rep_bool, 0), + PB_FIELD( 29, SFIXED32, REPEATED, STATIC, AllTypes, rep_sfixed32, rep_fixed32, 0), + PB_FIELD( 30, FLOAT , REPEATED, STATIC, AllTypes, rep_float, rep_sfixed32, 0), + PB_FIELD( 31, FIXED64 , REPEATED, STATIC, AllTypes, rep_fixed64, rep_float, 0), + PB_FIELD( 32, SFIXED64, REPEATED, STATIC, AllTypes, rep_sfixed64, rep_fixed64, 0), + PB_FIELD( 33, DOUBLE , REPEATED, STATIC, AllTypes, rep_double, rep_sfixed64, 0), + PB_FIELD( 34, STRING , REPEATED, STATIC, AllTypes, rep_string, rep_double, 0), + PB_FIELD( 35, BYTES , REPEATED, STATIC, AllTypes, rep_bytes, rep_string, 0), + PB_FIELD( 36, MESSAGE , REPEATED, STATIC, AllTypes, rep_submsg, rep_bytes, &SubMessage_fields), + PB_FIELD( 37, ENUM , REPEATED, STATIC, AllTypes, rep_enum, rep_submsg, 0), + PB_FIELD( 41, INT32 , OPTIONAL, STATIC, AllTypes, opt_int32, rep_enum, &AllTypes_opt_int32_default), + PB_FIELD( 42, INT64 , OPTIONAL, STATIC, AllTypes, opt_int64, opt_int32, &AllTypes_opt_int64_default), + PB_FIELD( 43, UINT32 , OPTIONAL, STATIC, AllTypes, opt_uint32, opt_int64, &AllTypes_opt_uint32_default), + PB_FIELD( 44, UINT64 , OPTIONAL, STATIC, AllTypes, opt_uint64, opt_uint32, &AllTypes_opt_uint64_default), + PB_FIELD( 45, SINT32 , OPTIONAL, STATIC, AllTypes, opt_sint32, opt_uint64, &AllTypes_opt_sint32_default), + PB_FIELD( 46, SINT64 , OPTIONAL, STATIC, AllTypes, opt_sint64, opt_sint32, &AllTypes_opt_sint64_default), + PB_FIELD( 47, BOOL , OPTIONAL, STATIC, AllTypes, opt_bool, opt_sint64, &AllTypes_opt_bool_default), + PB_FIELD( 48, FIXED32 , OPTIONAL, STATIC, AllTypes, opt_fixed32, opt_bool, &AllTypes_opt_fixed32_default), + PB_FIELD( 49, SFIXED32, OPTIONAL, STATIC, AllTypes, opt_sfixed32, opt_fixed32, &AllTypes_opt_sfixed32_default), + PB_FIELD( 50, FLOAT , OPTIONAL, STATIC, AllTypes, opt_float, opt_sfixed32, &AllTypes_opt_float_default), + PB_FIELD( 51, FIXED64 , OPTIONAL, STATIC, AllTypes, opt_fixed64, opt_float, &AllTypes_opt_fixed64_default), + PB_FIELD( 52, SFIXED64, OPTIONAL, STATIC, AllTypes, opt_sfixed64, opt_fixed64, &AllTypes_opt_sfixed64_default), + PB_FIELD( 53, DOUBLE , OPTIONAL, STATIC, AllTypes, opt_double, opt_sfixed64, &AllTypes_opt_double_default), + PB_FIELD( 54, STRING , OPTIONAL, STATIC, AllTypes, opt_string, opt_double, &AllTypes_opt_string_default), + PB_FIELD( 55, BYTES , OPTIONAL, STATIC, AllTypes, opt_bytes, opt_string, &AllTypes_opt_bytes_default), + PB_FIELD( 56, MESSAGE , OPTIONAL, STATIC, AllTypes, opt_submsg, opt_bytes, &SubMessage_fields), + PB_FIELD( 57, ENUM , OPTIONAL, STATIC, AllTypes, opt_enum, opt_submsg, &AllTypes_opt_enum_default), + PB_FIELD( 99, INT32 , REQUIRED, STATIC, AllTypes, end, opt_enum, 0), + PB_LAST_FIELD +}; + diff --git a/tests/backwards_compatibility/alltypes_legacy.h b/tests/backwards_compatibility/alltypes_legacy.h new file mode 100644 index 0000000..037b347 --- /dev/null +++ b/tests/backwards_compatibility/alltypes_legacy.h @@ -0,0 +1,178 @@ +/* Automatically generated nanopb header */ +/* This is a file generated using nanopb-0.2.0-dev. + * It is used as a part of test suite in order to detect any + * incompatible changes made to the generator in future versions. + */ + +#ifndef _PB_ALLTYPES_PB_H_ +#define _PB_ALLTYPES_PB_H_ +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Enum definitions */ +typedef enum _MyEnum { + MyEnum_Zero = 0, + MyEnum_First = 1, + MyEnum_Second = 2, + MyEnum_Truth = 42 +} MyEnum; + +/* Struct definitions */ +typedef struct _SubMessage { + char substuff1[16]; + int32_t substuff2; + bool has_substuff3; + uint32_t substuff3; +} SubMessage; + +typedef struct { + size_t size; + uint8_t bytes[16]; +} AllTypes_req_bytes_t; + +typedef struct { + size_t size; + uint8_t bytes[16]; +} AllTypes_rep_bytes_t; + +typedef struct { + size_t size; + uint8_t bytes[16]; +} AllTypes_opt_bytes_t; + +typedef struct _AllTypes { + int32_t req_int32; + int64_t req_int64; + uint32_t req_uint32; + uint64_t req_uint64; + int32_t req_sint32; + int64_t req_sint64; + bool req_bool; + uint32_t req_fixed32; + int32_t req_sfixed32; + float req_float; + uint64_t req_fixed64; + int64_t req_sfixed64; + double req_double; + char req_string[16]; + AllTypes_req_bytes_t req_bytes; + SubMessage req_submsg; + MyEnum req_enum; + size_t rep_int32_count; + int32_t rep_int32[5]; + size_t rep_int64_count; + int64_t rep_int64[5]; + size_t rep_uint32_count; + uint32_t rep_uint32[5]; + size_t rep_uint64_count; + uint64_t rep_uint64[5]; + size_t rep_sint32_count; + int32_t rep_sint32[5]; + size_t rep_sint64_count; + int64_t rep_sint64[5]; + size_t rep_bool_count; + bool rep_bool[5]; + size_t rep_fixed32_count; + uint32_t rep_fixed32[5]; + size_t rep_sfixed32_count; + int32_t rep_sfixed32[5]; + size_t rep_float_count; + float rep_float[5]; + size_t rep_fixed64_count; + uint64_t rep_fixed64[5]; + size_t rep_sfixed64_count; + int64_t rep_sfixed64[5]; + size_t rep_double_count; + double rep_double[5]; + size_t rep_string_count; + char rep_string[5][16]; + size_t rep_bytes_count; + AllTypes_rep_bytes_t rep_bytes[5]; + size_t rep_submsg_count; + SubMessage rep_submsg[5]; + size_t rep_enum_count; + MyEnum rep_enum[5]; + bool has_opt_int32; + int32_t opt_int32; + bool has_opt_int64; + int64_t opt_int64; + bool has_opt_uint32; + uint32_t opt_uint32; + bool has_opt_uint64; + uint64_t opt_uint64; + bool has_opt_sint32; + int32_t opt_sint32; + bool has_opt_sint64; + int64_t opt_sint64; + bool has_opt_bool; + bool opt_bool; + bool has_opt_fixed32; + uint32_t opt_fixed32; + bool has_opt_sfixed32; + int32_t opt_sfixed32; + bool has_opt_float; + float opt_float; + bool has_opt_fixed64; + uint64_t opt_fixed64; + bool has_opt_sfixed64; + int64_t opt_sfixed64; + bool has_opt_double; + double opt_double; + bool has_opt_string; + char opt_string[16]; + bool has_opt_bytes; + AllTypes_opt_bytes_t opt_bytes; + bool has_opt_submsg; + SubMessage opt_submsg; + bool has_opt_enum; + MyEnum opt_enum; + int32_t end; +} AllTypes; + +/* Default values for struct fields */ +extern const char SubMessage_substuff1_default[16]; +extern const int32_t SubMessage_substuff2_default; +extern const uint32_t SubMessage_substuff3_default; +extern const int32_t AllTypes_opt_int32_default; +extern const int64_t AllTypes_opt_int64_default; +extern const uint32_t AllTypes_opt_uint32_default; +extern const uint64_t AllTypes_opt_uint64_default; +extern const int32_t AllTypes_opt_sint32_default; +extern const int64_t AllTypes_opt_sint64_default; +extern const bool AllTypes_opt_bool_default; +extern const uint32_t AllTypes_opt_fixed32_default; +extern const int32_t AllTypes_opt_sfixed32_default; +extern const float AllTypes_opt_float_default; +extern const uint64_t AllTypes_opt_fixed64_default; +extern const int64_t AllTypes_opt_sfixed64_default; +extern const double AllTypes_opt_double_default; +extern const char AllTypes_opt_string_default[16]; +extern const AllTypes_opt_bytes_t AllTypes_opt_bytes_default; +extern const MyEnum AllTypes_opt_enum_default; + +/* Struct field encoding specification for nanopb */ +extern const pb_field_t SubMessage_fields[4]; +extern const pb_field_t AllTypes_fields[53]; + +/* Check that field information fits in pb_field_t */ +#if !defined(PB_FIELD_16BIT) && !defined(PB_FIELD_32BIT) +STATIC_ASSERT((pb_membersize(AllTypes, req_submsg) < 256 && pb_membersize(AllTypes, rep_submsg[0]) < 256 && pb_membersize(AllTypes, opt_submsg) < 256), YOU_MUST_DEFINE_PB_FIELD_16BIT_FOR_MESSAGES_SubMessage_AllTypes) +#endif + +#if !defined(PB_FIELD_32BIT) +STATIC_ASSERT((pb_membersize(AllTypes, req_submsg) < 65536 && pb_membersize(AllTypes, rep_submsg[0]) < 65536 && pb_membersize(AllTypes, opt_submsg) < 65536), YOU_MUST_DEFINE_PB_FIELD_32BIT_FOR_MESSAGES_SubMessage_AllTypes) +#endif + +/* On some platforms (such as AVR), double is really float. + * These are not directly supported by nanopb, but see example_avr_double. + */ +STATIC_ASSERT(sizeof(double) == 8, DOUBLE_MUST_BE_8_BYTES) + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/tests/backwards_compatibility/decode_legacy.c b/tests/backwards_compatibility/decode_legacy.c new file mode 100644 index 0000000..b74172f --- /dev/null +++ b/tests/backwards_compatibility/decode_legacy.c @@ -0,0 +1,197 @@ +/* Tests the decoding of all types. + * This is a backwards-compatibility test, using bc_alltypes.pb.h. + * It is similar to test_decode3, but duplicated in order to allow + * test_decode3 to test any new features introduced later. + * + * Run e.g. ./bc_encode | ./bc_decode + */ + +#include +#include +#include +#include +#include "bc_alltypes.pb.h" + +#define TEST(x) if (!(x)) { \ + printf("Test " #x " failed.\n"); \ + return false; \ + } + +/* This function is called once from main(), it handles + the decoding and checks the fields. */ +bool check_alltypes(pb_istream_t *stream, int mode) +{ + AllTypes alltypes; + + /* Fill with garbage to better detect initialization errors */ + memset(&alltypes, 0xAA, sizeof(alltypes)); + + if (!pb_decode(stream, AllTypes_fields, &alltypes)) + return false; + + TEST(alltypes.req_int32 == -1001); + TEST(alltypes.req_int64 == -1002); + TEST(alltypes.req_uint32 == 1003); + TEST(alltypes.req_uint64 == 1004); + TEST(alltypes.req_sint32 == -1005); + TEST(alltypes.req_sint64 == -1006); + TEST(alltypes.req_bool == true); + + TEST(alltypes.req_fixed32 == 1008); + TEST(alltypes.req_sfixed32 == -1009); + TEST(alltypes.req_float == 1010.0f); + + TEST(alltypes.req_fixed64 == 1011); + TEST(alltypes.req_sfixed64 == -1012); + TEST(alltypes.req_double == 1013.0f); + + TEST(strcmp(alltypes.req_string, "1014") == 0); + TEST(alltypes.req_bytes.size == 4); + TEST(memcmp(alltypes.req_bytes.bytes, "1015", 4) == 0); + TEST(strcmp(alltypes.req_submsg.substuff1, "1016") == 0); + TEST(alltypes.req_submsg.substuff2 == 1016); + TEST(alltypes.req_submsg.substuff3 == 3); + TEST(alltypes.req_enum == MyEnum_Truth); + + TEST(alltypes.rep_int32_count == 5 && alltypes.rep_int32[4] == -2001 && alltypes.rep_int32[0] == 0); + TEST(alltypes.rep_int64_count == 5 && alltypes.rep_int64[4] == -2002 && alltypes.rep_int64[0] == 0); + TEST(alltypes.rep_uint32_count == 5 && alltypes.rep_uint32[4] == 2003 && alltypes.rep_uint32[0] == 0); + TEST(alltypes.rep_uint64_count == 5 && alltypes.rep_uint64[4] == 2004 && alltypes.rep_uint64[0] == 0); + TEST(alltypes.rep_sint32_count == 5 && alltypes.rep_sint32[4] == -2005 && alltypes.rep_sint32[0] == 0); + TEST(alltypes.rep_sint64_count == 5 && alltypes.rep_sint64[4] == -2006 && alltypes.rep_sint64[0] == 0); + TEST(alltypes.rep_bool_count == 5 && alltypes.rep_bool[4] == true && alltypes.rep_bool[0] == false); + + TEST(alltypes.rep_fixed32_count == 5 && alltypes.rep_fixed32[4] == 2008 && alltypes.rep_fixed32[0] == 0); + TEST(alltypes.rep_sfixed32_count == 5 && alltypes.rep_sfixed32[4] == -2009 && alltypes.rep_sfixed32[0] == 0); + TEST(alltypes.rep_float_count == 5 && alltypes.rep_float[4] == 2010.0f && alltypes.rep_float[0] == 0.0f); + + TEST(alltypes.rep_fixed64_count == 5 && alltypes.rep_fixed64[4] == 2011 && alltypes.rep_fixed64[0] == 0); + TEST(alltypes.rep_sfixed64_count == 5 && alltypes.rep_sfixed64[4] == -2012 && alltypes.rep_sfixed64[0] == 0); + TEST(alltypes.rep_double_count == 5 && alltypes.rep_double[4] == 2013.0 && alltypes.rep_double[0] == 0.0); + + TEST(alltypes.rep_string_count == 5 && strcmp(alltypes.rep_string[4], "2014") == 0 && alltypes.rep_string[0][0] == '\0'); + TEST(alltypes.rep_bytes_count == 5 && alltypes.rep_bytes[4].size == 4 && alltypes.rep_bytes[0].size == 0); + TEST(memcmp(alltypes.rep_bytes[4].bytes, "2015", 4) == 0); + + TEST(alltypes.rep_submsg_count == 5); + TEST(strcmp(alltypes.rep_submsg[4].substuff1, "2016") == 0 && alltypes.rep_submsg[0].substuff1[0] == '\0'); + TEST(alltypes.rep_submsg[4].substuff2 == 2016 && alltypes.rep_submsg[0].substuff2 == 0); + TEST(alltypes.rep_submsg[4].substuff3 == 2016 && alltypes.rep_submsg[0].substuff3 == 3); + + TEST(alltypes.rep_enum_count == 5 && alltypes.rep_enum[4] == MyEnum_Truth && alltypes.rep_enum[0] == MyEnum_Zero); + + if (mode == 0) + { + /* Expect default values */ + TEST(alltypes.has_opt_int32 == false); + TEST(alltypes.opt_int32 == 4041); + TEST(alltypes.has_opt_int64 == false); + TEST(alltypes.opt_int64 == 4042); + TEST(alltypes.has_opt_uint32 == false); + TEST(alltypes.opt_uint32 == 4043); + TEST(alltypes.has_opt_uint64 == false); + TEST(alltypes.opt_uint64 == 4044); + TEST(alltypes.has_opt_sint32 == false); + TEST(alltypes.opt_sint32 == 4045); + TEST(alltypes.has_opt_sint64 == false); + TEST(alltypes.opt_sint64 == 4046); + TEST(alltypes.has_opt_bool == false); + TEST(alltypes.opt_bool == false); + + TEST(alltypes.has_opt_fixed32 == false); + TEST(alltypes.opt_fixed32 == 4048); + TEST(alltypes.has_opt_sfixed32 == false); + TEST(alltypes.opt_sfixed32 == 4049); + TEST(alltypes.has_opt_float == false); + TEST(alltypes.opt_float == 4050.0f); + + TEST(alltypes.has_opt_fixed64 == false); + TEST(alltypes.opt_fixed64 == 4051); + TEST(alltypes.has_opt_sfixed64 == false); + TEST(alltypes.opt_sfixed64 == 4052); + TEST(alltypes.has_opt_double == false); + TEST(alltypes.opt_double == 4053.0); + + TEST(alltypes.has_opt_string == false); + TEST(strcmp(alltypes.opt_string, "4054") == 0); + TEST(alltypes.has_opt_bytes == false); + TEST(alltypes.opt_bytes.size == 4); + TEST(memcmp(alltypes.opt_bytes.bytes, "4055", 4) == 0); + TEST(alltypes.has_opt_submsg == false); + TEST(strcmp(alltypes.opt_submsg.substuff1, "1") == 0); + TEST(alltypes.opt_submsg.substuff2 == 2); + TEST(alltypes.opt_submsg.substuff3 == 3); + TEST(alltypes.has_opt_enum == false); + TEST(alltypes.opt_enum == MyEnum_Second); + } + else + { + /* Expect filled-in values */ + TEST(alltypes.has_opt_int32 == true); + TEST(alltypes.opt_int32 == 3041); + TEST(alltypes.has_opt_int64 == true); + TEST(alltypes.opt_int64 == 3042); + TEST(alltypes.has_opt_uint32 == true); + TEST(alltypes.opt_uint32 == 3043); + TEST(alltypes.has_opt_uint64 == true); + TEST(alltypes.opt_uint64 == 3044); + TEST(alltypes.has_opt_sint32 == true); + TEST(alltypes.opt_sint32 == 3045); + TEST(alltypes.has_opt_sint64 == true); + TEST(alltypes.opt_sint64 == 3046); + TEST(alltypes.has_opt_bool == true); + TEST(alltypes.opt_bool == true); + + TEST(alltypes.has_opt_fixed32 == true); + TEST(alltypes.opt_fixed32 == 3048); + TEST(alltypes.has_opt_sfixed32 == true); + TEST(alltypes.opt_sfixed32 == 3049); + TEST(alltypes.has_opt_float == true); + TEST(alltypes.opt_float == 3050.0f); + + TEST(alltypes.has_opt_fixed64 == true); + TEST(alltypes.opt_fixed64 == 3051); + TEST(alltypes.has_opt_sfixed64 == true); + TEST(alltypes.opt_sfixed64 == 3052); + TEST(alltypes.has_opt_double == true); + TEST(alltypes.opt_double == 3053.0); + + TEST(alltypes.has_opt_string == true); + TEST(strcmp(alltypes.opt_string, "3054") == 0); + TEST(alltypes.has_opt_bytes == true); + TEST(alltypes.opt_bytes.size == 4); + TEST(memcmp(alltypes.opt_bytes.bytes, "3055", 4) == 0); + TEST(alltypes.has_opt_submsg == true); + TEST(strcmp(alltypes.opt_submsg.substuff1, "3056") == 0); + TEST(alltypes.opt_submsg.substuff2 == 3056); + TEST(alltypes.opt_submsg.substuff3 == 3); + TEST(alltypes.has_opt_enum == true); + TEST(alltypes.opt_enum == MyEnum_Truth); + } + + TEST(alltypes.end == 1099); + + return true; +} + +int main(int argc, char **argv) +{ + /* Whether to expect the optional values or the default values. */ + int mode = (argc > 1) ? atoi(argv[1]) : 0; + + /* Read the data into buffer */ + uint8_t buffer[1024]; + size_t count = fread(buffer, 1, sizeof(buffer), stdin); + + /* Construct a pb_istream_t for reading from the buffer */ + pb_istream_t stream = pb_istream_from_buffer(buffer, count); + + /* Decode and print out the stuff */ + if (!check_alltypes(&stream, mode)) + { + printf("Parsing failed: %s\n", PB_GET_ERROR(&stream)); + return 1; + } else { + return 0; + } +} diff --git a/tests/backwards_compatibility/encode_legacy.c b/tests/backwards_compatibility/encode_legacy.c new file mode 100644 index 0000000..e84f090 --- /dev/null +++ b/tests/backwards_compatibility/encode_legacy.c @@ -0,0 +1,131 @@ +/* Attempts to test all the datatypes supported by ProtoBuf. + * This is a backwards-compatibility test, using bc_alltypes.pb.h. + * It is similar to test_encode3, but duplicated in order to allow + * test_encode3 to test any new features introduced later. + */ + +#include +#include +#include +#include +#include "bc_alltypes.pb.h" + +int main(int argc, char **argv) +{ + int mode = (argc > 1) ? atoi(argv[1]) : 0; + + /* Initialize the structure with constants */ + AllTypes alltypes = {0}; + + alltypes.req_int32 = -1001; + alltypes.req_int64 = -1002; + alltypes.req_uint32 = 1003; + alltypes.req_uint64 = 1004; + alltypes.req_sint32 = -1005; + alltypes.req_sint64 = -1006; + alltypes.req_bool = true; + + alltypes.req_fixed32 = 1008; + alltypes.req_sfixed32 = -1009; + alltypes.req_float = 1010.0f; + + alltypes.req_fixed64 = 1011; + alltypes.req_sfixed64 = -1012; + alltypes.req_double = 1013.0; + + strcpy(alltypes.req_string, "1014"); + alltypes.req_bytes.size = 4; + memcpy(alltypes.req_bytes.bytes, "1015", 4); + strcpy(alltypes.req_submsg.substuff1, "1016"); + alltypes.req_submsg.substuff2 = 1016; + alltypes.req_enum = MyEnum_Truth; + + alltypes.rep_int32_count = 5; alltypes.rep_int32[4] = -2001; + alltypes.rep_int64_count = 5; alltypes.rep_int64[4] = -2002; + alltypes.rep_uint32_count = 5; alltypes.rep_uint32[4] = 2003; + alltypes.rep_uint64_count = 5; alltypes.rep_uint64[4] = 2004; + alltypes.rep_sint32_count = 5; alltypes.rep_sint32[4] = -2005; + alltypes.rep_sint64_count = 5; alltypes.rep_sint64[4] = -2006; + alltypes.rep_bool_count = 5; alltypes.rep_bool[4] = true; + + alltypes.rep_fixed32_count = 5; alltypes.rep_fixed32[4] = 2008; + alltypes.rep_sfixed32_count = 5; alltypes.rep_sfixed32[4] = -2009; + alltypes.rep_float_count = 5; alltypes.rep_float[4] = 2010.0f; + + alltypes.rep_fixed64_count = 5; alltypes.rep_fixed64[4] = 2011; + alltypes.rep_sfixed64_count = 5; alltypes.rep_sfixed64[4] = -2012; + alltypes.rep_double_count = 5; alltypes.rep_double[4] = 2013.0; + + alltypes.rep_string_count = 5; strcpy(alltypes.rep_string[4], "2014"); + alltypes.rep_bytes_count = 5; alltypes.rep_bytes[4].size = 4; + memcpy(alltypes.rep_bytes[4].bytes, "2015", 4); + + alltypes.rep_submsg_count = 5; + strcpy(alltypes.rep_submsg[4].substuff1, "2016"); + alltypes.rep_submsg[4].substuff2 = 2016; + alltypes.rep_submsg[4].has_substuff3 = true; + alltypes.rep_submsg[4].substuff3 = 2016; + + alltypes.rep_enum_count = 5; alltypes.rep_enum[4] = MyEnum_Truth; + + if (mode != 0) + { + /* Fill in values for optional fields */ + alltypes.has_opt_int32 = true; + alltypes.opt_int32 = 3041; + alltypes.has_opt_int64 = true; + alltypes.opt_int64 = 3042; + alltypes.has_opt_uint32 = true; + alltypes.opt_uint32 = 3043; + alltypes.has_opt_uint64 = true; + alltypes.opt_uint64 = 3044; + alltypes.has_opt_sint32 = true; + alltypes.opt_sint32 = 3045; + alltypes.has_opt_sint64 = true; + alltypes.opt_sint64 = 3046; + alltypes.has_opt_bool = true; + alltypes.opt_bool = true; + + alltypes.has_opt_fixed32 = true; + alltypes.opt_fixed32 = 3048; + alltypes.has_opt_sfixed32 = true; + alltypes.opt_sfixed32 = 3049; + alltypes.has_opt_float = true; + alltypes.opt_float = 3050.0f; + + alltypes.has_opt_fixed64 = true; + alltypes.opt_fixed64 = 3051; + alltypes.has_opt_sfixed64 = true; + alltypes.opt_sfixed64 = 3052; + alltypes.has_opt_double = true; + alltypes.opt_double = 3053.0; + + alltypes.has_opt_string = true; + strcpy(alltypes.opt_string, "3054"); + alltypes.has_opt_bytes = true; + alltypes.opt_bytes.size = 4; + memcpy(alltypes.opt_bytes.bytes, "3055", 4); + alltypes.has_opt_submsg = true; + strcpy(alltypes.opt_submsg.substuff1, "3056"); + alltypes.opt_submsg.substuff2 = 3056; + alltypes.has_opt_enum = true; + alltypes.opt_enum = MyEnum_Truth; + } + + alltypes.end = 1099; + + uint8_t buffer[1024]; + pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer)); + + /* Now encode it and check if we succeeded. */ + if (pb_encode(&stream, AllTypes_fields, &alltypes)) + { + fwrite(buffer, 1, stream.bytes_written, stdout); + return 0; /* Success */ + } + else + { + fprintf(stderr, "Encoding failed!\n"); + return 1; /* Failure */ + } +} diff --git a/tests/basic_buffer/SConscript b/tests/basic_buffer/SConscript new file mode 100644 index 0000000..5b85e13 --- /dev/null +++ b/tests/basic_buffer/SConscript @@ -0,0 +1,12 @@ +# Build and run a basic round-trip test using memory buffer encoding. + +Import("env") + +env.Program(["encode_buffer.c", "#common/person.pb.c", "#common/pb_encode.o"]) +env.Program(["decode_buffer.c", "#common/person.pb.c", "#common/pb_decode.o"]) + +env.RunTest("encode_buffer") +env.RunTest(["decode_buffer", "encode_buffer.output"]) +env.Decode(["encode_buffer.output", "#common/person.proto"], MESSAGE = "Person") +env.Compare(["decode_buffer.output", "encode_buffer.decoded"]) + diff --git a/tests/basic_buffer/decode_buffer.c b/tests/basic_buffer/decode_buffer.c new file mode 100644 index 0000000..56bbd8f --- /dev/null +++ b/tests/basic_buffer/decode_buffer.c @@ -0,0 +1,83 @@ +/* A very simple decoding test case, using person.proto. + * Produces output compatible with protoc --decode. + * Reads the encoded data from stdin and prints the values + * to stdout as text. + * + * Run e.g. ./test_encode1 | ./test_decode1 + */ + +#include +#include +#include "person.pb.h" + +/* This function is called once from main(), it handles + the decoding and printing. */ +bool print_person(pb_istream_t *stream) +{ + int i; + Person person; + + if (!pb_decode(stream, Person_fields, &person)) + return false; + + /* Now the decoding is done, rest is just to print stuff out. */ + + printf("name: \"%s\"\n", person.name); + printf("id: %ld\n", (long)person.id); + + if (person.has_email) + printf("email: \"%s\"\n", person.email); + + for (i = 0; i < person.phone_count; i++) + { + Person_PhoneNumber *phone = &person.phone[i]; + printf("phone {\n"); + printf(" number: \"%s\"\n", phone->number); + + if (phone->has_type) + { + switch (phone->type) + { + case Person_PhoneType_WORK: + printf(" type: WORK\n"); + break; + + case Person_PhoneType_HOME: + printf(" type: HOME\n"); + break; + + case Person_PhoneType_MOBILE: + printf(" type: MOBILE\n"); + break; + } + } + printf("}\n"); + } + + return true; +} + +int main() +{ + /* Read the data into buffer */ + uint8_t buffer[512]; + size_t count = fread(buffer, 1, sizeof(buffer), stdin); + + if (!feof(stdin)) + { + printf("Message does not fit in buffer\n"); + return 1; + } + + /* Construct a pb_istream_t for reading from the buffer */ + pb_istream_t stream = pb_istream_from_buffer(buffer, count); + + /* Decode and print out the stuff */ + if (!print_person(&stream)) + { + printf("Parsing failed: %s\n", PB_GET_ERROR(&stream)); + return 1; + } else { + return 0; + } +} diff --git a/tests/basic_buffer/encode_buffer.c b/tests/basic_buffer/encode_buffer.c new file mode 100644 index 0000000..742c99f --- /dev/null +++ b/tests/basic_buffer/encode_buffer.c @@ -0,0 +1,33 @@ +/* A very simple encoding test case using person.proto. + * Just puts constant data in the fields and encodes into + * buffer, which is then written to stdout. + */ + +#include +#include +#include "person.pb.h" + +int main() +{ + /* Initialize the structure with constants */ + Person person = {"Test Person 99", 99, true, "test@person.com", + 3, {{"555-12345678", true, Person_PhoneType_MOBILE}, + {"99-2342", false, 0}, + {"1234-5678", true, Person_PhoneType_WORK}, + }}; + + uint8_t buffer[512]; + pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer)); + + /* Now encode it and check if we succeeded. */ + if (pb_encode(&stream, Person_fields, &person)) + { + fwrite(buffer, 1, stream.bytes_written, stdout); + return 0; /* Success */ + } + else + { + fprintf(stderr, "Encoding failed: %s\n", PB_GET_ERROR(&stream)); + return 1; /* Failure */ + } +} diff --git a/tests/basic_stream/decode_stream.c b/tests/basic_stream/decode_stream.c new file mode 100644 index 0000000..2142977 --- /dev/null +++ b/tests/basic_stream/decode_stream.c @@ -0,0 +1,83 @@ +/* Same as test_decode1 but reads from stdin directly. + */ + +#include +#include +#include "person.pb.h" + +/* This function is called once from main(), it handles + the decoding and printing. + Ugly copy-paste from test_decode1.c. */ +bool print_person(pb_istream_t *stream) +{ + int i; + Person person; + + if (!pb_decode(stream, Person_fields, &person)) + return false; + + /* Now the decoding is done, rest is just to print stuff out. */ + + printf("name: \"%s\"\n", person.name); + printf("id: %ld\n", (long)person.id); + + if (person.has_email) + printf("email: \"%s\"\n", person.email); + + for (i = 0; i < person.phone_count; i++) + { + Person_PhoneNumber *phone = &person.phone[i]; + printf("phone {\n"); + printf(" number: \"%s\"\n", phone->number); + + if (phone->has_type) + { + switch (phone->type) + { + case Person_PhoneType_WORK: + printf(" type: WORK\n"); + break; + + case Person_PhoneType_HOME: + printf(" type: HOME\n"); + break; + + case Person_PhoneType_MOBILE: + printf(" type: MOBILE\n"); + break; + } + } + printf("}\n"); + } + + return true; +} + +/* This binds the pb_istream_t to stdin */ +bool callback(pb_istream_t *stream, uint8_t *buf, size_t count) +{ + FILE *file = (FILE*)stream->state; + bool status; + + status = (fread(buf, 1, count, file) == count); + + if (feof(file)) + stream->bytes_left = 0; + + return status; +} + +int main() +{ + /* Maximum size is specified to prevent infinite length messages from + * hanging this in the fuzz test. + */ + pb_istream_t stream = {&callback, stdin, 10000}; + if (!print_person(&stream)) + { + printf("Parsing failed: %s\n", PB_GET_ERROR(&stream)); + return 1; + } else { + return 0; + } +} diff --git a/tests/basic_stream/encode_stream.c b/tests/basic_stream/encode_stream.c new file mode 100644 index 0000000..fd25c6c --- /dev/null +++ b/tests/basic_stream/encode_stream.c @@ -0,0 +1,37 @@ +/* Same as test_encode1.c, except writes directly to stdout. + */ + +#include +#include +#include "person.pb.h" + +/* This binds the pb_ostream_t into the stdout stream */ +bool streamcallback(pb_ostream_t *stream, const uint8_t *buf, size_t count) +{ + FILE *file = (FILE*) stream->state; + return fwrite(buf, 1, count, file) == count; +} + +int main() +{ + /* Initialize the structure with constants */ + Person person = {"Test Person 99", 99, true, "test@person.com", + 3, {{"555-12345678", true, Person_PhoneType_MOBILE}, + {"99-2342", false, 0}, + {"1234-5678", true, Person_PhoneType_WORK}, + }}; + + /* Prepare the stream, output goes directly to stdout */ + pb_ostream_t stream = {&streamcallback, stdout, SIZE_MAX, 0}; + + /* Now encode it and check if we succeeded. */ + if (pb_encode(&stream, Person_fields, &person)) + { + return 0; /* Success */ + } + else + { + fprintf(stderr, "Encoding failed: %s\n", PB_GET_ERROR(&stream)); + return 1; /* Failure */ + } +} diff --git a/tests/bc_alltypes.pb.c b/tests/bc_alltypes.pb.c deleted file mode 100644 index b144b1e..0000000 --- a/tests/bc_alltypes.pb.c +++ /dev/null @@ -1,93 +0,0 @@ -/* Automatically generated nanopb constant definitions */ -/* Generated by 0.2.0-dev at Sun Feb 17 00:09:53 2013. */ -/* This is a file generated using nanopb-0.2.0-dev. - * It is used as a part of test suite in order to detect any - * incompatible changes made to the generator in future versions. - */ - -#include "bc_alltypes.pb.h" - -const char SubMessage_substuff1_default[16] = "1"; -const int32_t SubMessage_substuff2_default = 2; -const uint32_t SubMessage_substuff3_default = 3; -const int32_t AllTypes_opt_int32_default = 4041; -const int64_t AllTypes_opt_int64_default = 4042; -const uint32_t AllTypes_opt_uint32_default = 4043; -const uint64_t AllTypes_opt_uint64_default = 4044; -const int32_t AllTypes_opt_sint32_default = 4045; -const int64_t AllTypes_opt_sint64_default = 4046; -const bool AllTypes_opt_bool_default = false; -const uint32_t AllTypes_opt_fixed32_default = 4048; -const int32_t AllTypes_opt_sfixed32_default = 4049; -const float AllTypes_opt_float_default = 4050; -const uint64_t AllTypes_opt_fixed64_default = 4051; -const int64_t AllTypes_opt_sfixed64_default = 4052; -const double AllTypes_opt_double_default = 4053; -const char AllTypes_opt_string_default[16] = "4054"; -const AllTypes_opt_bytes_t AllTypes_opt_bytes_default = {4, {0x34,0x30,0x35,0x35}}; -const MyEnum AllTypes_opt_enum_default = MyEnum_Second; - - -const pb_field_t SubMessage_fields[4] = { - PB_FIELD( 1, STRING , REQUIRED, STATIC, SubMessage, substuff1, substuff1, &SubMessage_substuff1_default), - PB_FIELD( 2, INT32 , REQUIRED, STATIC, SubMessage, substuff2, substuff1, &SubMessage_substuff2_default), - PB_FIELD( 3, FIXED32 , OPTIONAL, STATIC, SubMessage, substuff3, substuff2, &SubMessage_substuff3_default), - PB_LAST_FIELD -}; - -const pb_field_t AllTypes_fields[53] = { - PB_FIELD( 1, INT32 , REQUIRED, STATIC, AllTypes, req_int32, req_int32, 0), - PB_FIELD( 2, INT64 , REQUIRED, STATIC, AllTypes, req_int64, req_int32, 0), - PB_FIELD( 3, UINT32 , REQUIRED, STATIC, AllTypes, req_uint32, req_int64, 0), - PB_FIELD( 4, UINT64 , REQUIRED, STATIC, AllTypes, req_uint64, req_uint32, 0), - PB_FIELD( 5, SINT32 , REQUIRED, STATIC, AllTypes, req_sint32, req_uint64, 0), - PB_FIELD( 6, SINT64 , REQUIRED, STATIC, AllTypes, req_sint64, req_sint32, 0), - PB_FIELD( 7, BOOL , REQUIRED, STATIC, AllTypes, req_bool, req_sint64, 0), - PB_FIELD( 8, FIXED32 , REQUIRED, STATIC, AllTypes, req_fixed32, req_bool, 0), - PB_FIELD( 9, SFIXED32, REQUIRED, STATIC, AllTypes, req_sfixed32, req_fixed32, 0), - PB_FIELD( 10, FLOAT , REQUIRED, STATIC, AllTypes, req_float, req_sfixed32, 0), - PB_FIELD( 11, FIXED64 , REQUIRED, STATIC, AllTypes, req_fixed64, req_float, 0), - PB_FIELD( 12, SFIXED64, REQUIRED, STATIC, AllTypes, req_sfixed64, req_fixed64, 0), - PB_FIELD( 13, DOUBLE , REQUIRED, STATIC, AllTypes, req_double, req_sfixed64, 0), - PB_FIELD( 14, STRING , REQUIRED, STATIC, AllTypes, req_string, req_double, 0), - PB_FIELD( 15, BYTES , REQUIRED, STATIC, AllTypes, req_bytes, req_string, 0), - PB_FIELD( 16, MESSAGE , REQUIRED, STATIC, AllTypes, req_submsg, req_bytes, &SubMessage_fields), - PB_FIELD( 17, ENUM , REQUIRED, STATIC, AllTypes, req_enum, req_submsg, 0), - PB_FIELD( 21, INT32 , REPEATED, STATIC, AllTypes, rep_int32, req_enum, 0), - PB_FIELD( 22, INT64 , REPEATED, STATIC, AllTypes, rep_int64, rep_int32, 0), - PB_FIELD( 23, UINT32 , REPEATED, STATIC, AllTypes, rep_uint32, rep_int64, 0), - PB_FIELD( 24, UINT64 , REPEATED, STATIC, AllTypes, rep_uint64, rep_uint32, 0), - PB_FIELD( 25, SINT32 , REPEATED, STATIC, AllTypes, rep_sint32, rep_uint64, 0), - PB_FIELD( 26, SINT64 , REPEATED, STATIC, AllTypes, rep_sint64, rep_sint32, 0), - PB_FIELD( 27, BOOL , REPEATED, STATIC, AllTypes, rep_bool, rep_sint64, 0), - PB_FIELD( 28, FIXED32 , REPEATED, STATIC, AllTypes, rep_fixed32, rep_bool, 0), - PB_FIELD( 29, SFIXED32, REPEATED, STATIC, AllTypes, rep_sfixed32, rep_fixed32, 0), - PB_FIELD( 30, FLOAT , REPEATED, STATIC, AllTypes, rep_float, rep_sfixed32, 0), - PB_FIELD( 31, FIXED64 , REPEATED, STATIC, AllTypes, rep_fixed64, rep_float, 0), - PB_FIELD( 32, SFIXED64, REPEATED, STATIC, AllTypes, rep_sfixed64, rep_fixed64, 0), - PB_FIELD( 33, DOUBLE , REPEATED, STATIC, AllTypes, rep_double, rep_sfixed64, 0), - PB_FIELD( 34, STRING , REPEATED, STATIC, AllTypes, rep_string, rep_double, 0), - PB_FIELD( 35, BYTES , REPEATED, STATIC, AllTypes, rep_bytes, rep_string, 0), - PB_FIELD( 36, MESSAGE , REPEATED, STATIC, AllTypes, rep_submsg, rep_bytes, &SubMessage_fields), - PB_FIELD( 37, ENUM , REPEATED, STATIC, AllTypes, rep_enum, rep_submsg, 0), - PB_FIELD( 41, INT32 , OPTIONAL, STATIC, AllTypes, opt_int32, rep_enum, &AllTypes_opt_int32_default), - PB_FIELD( 42, INT64 , OPTIONAL, STATIC, AllTypes, opt_int64, opt_int32, &AllTypes_opt_int64_default), - PB_FIELD( 43, UINT32 , OPTIONAL, STATIC, AllTypes, opt_uint32, opt_int64, &AllTypes_opt_uint32_default), - PB_FIELD( 44, UINT64 , OPTIONAL, STATIC, AllTypes, opt_uint64, opt_uint32, &AllTypes_opt_uint64_default), - PB_FIELD( 45, SINT32 , OPTIONAL, STATIC, AllTypes, opt_sint32, opt_uint64, &AllTypes_opt_sint32_default), - PB_FIELD( 46, SINT64 , OPTIONAL, STATIC, AllTypes, opt_sint64, opt_sint32, &AllTypes_opt_sint64_default), - PB_FIELD( 47, BOOL , OPTIONAL, STATIC, AllTypes, opt_bool, opt_sint64, &AllTypes_opt_bool_default), - PB_FIELD( 48, FIXED32 , OPTIONAL, STATIC, AllTypes, opt_fixed32, opt_bool, &AllTypes_opt_fixed32_default), - PB_FIELD( 49, SFIXED32, OPTIONAL, STATIC, AllTypes, opt_sfixed32, opt_fixed32, &AllTypes_opt_sfixed32_default), - PB_FIELD( 50, FLOAT , OPTIONAL, STATIC, AllTypes, opt_float, opt_sfixed32, &AllTypes_opt_float_default), - PB_FIELD( 51, FIXED64 , OPTIONAL, STATIC, AllTypes, opt_fixed64, opt_float, &AllTypes_opt_fixed64_default), - PB_FIELD( 52, SFIXED64, OPTIONAL, STATIC, AllTypes, opt_sfixed64, opt_fixed64, &AllTypes_opt_sfixed64_default), - PB_FIELD( 53, DOUBLE , OPTIONAL, STATIC, AllTypes, opt_double, opt_sfixed64, &AllTypes_opt_double_default), - PB_FIELD( 54, STRING , OPTIONAL, STATIC, AllTypes, opt_string, opt_double, &AllTypes_opt_string_default), - PB_FIELD( 55, BYTES , OPTIONAL, STATIC, AllTypes, opt_bytes, opt_string, &AllTypes_opt_bytes_default), - PB_FIELD( 56, MESSAGE , OPTIONAL, STATIC, AllTypes, opt_submsg, opt_bytes, &SubMessage_fields), - PB_FIELD( 57, ENUM , OPTIONAL, STATIC, AllTypes, opt_enum, opt_submsg, &AllTypes_opt_enum_default), - PB_FIELD( 99, INT32 , REQUIRED, STATIC, AllTypes, end, opt_enum, 0), - PB_LAST_FIELD -}; - diff --git a/tests/bc_alltypes.pb.h b/tests/bc_alltypes.pb.h deleted file mode 100644 index 037b347..0000000 --- a/tests/bc_alltypes.pb.h +++ /dev/null @@ -1,178 +0,0 @@ -/* Automatically generated nanopb header */ -/* This is a file generated using nanopb-0.2.0-dev. - * It is used as a part of test suite in order to detect any - * incompatible changes made to the generator in future versions. - */ - -#ifndef _PB_ALLTYPES_PB_H_ -#define _PB_ALLTYPES_PB_H_ -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* Enum definitions */ -typedef enum _MyEnum { - MyEnum_Zero = 0, - MyEnum_First = 1, - MyEnum_Second = 2, - MyEnum_Truth = 42 -} MyEnum; - -/* Struct definitions */ -typedef struct _SubMessage { - char substuff1[16]; - int32_t substuff2; - bool has_substuff3; - uint32_t substuff3; -} SubMessage; - -typedef struct { - size_t size; - uint8_t bytes[16]; -} AllTypes_req_bytes_t; - -typedef struct { - size_t size; - uint8_t bytes[16]; -} AllTypes_rep_bytes_t; - -typedef struct { - size_t size; - uint8_t bytes[16]; -} AllTypes_opt_bytes_t; - -typedef struct _AllTypes { - int32_t req_int32; - int64_t req_int64; - uint32_t req_uint32; - uint64_t req_uint64; - int32_t req_sint32; - int64_t req_sint64; - bool req_bool; - uint32_t req_fixed32; - int32_t req_sfixed32; - float req_float; - uint64_t req_fixed64; - int64_t req_sfixed64; - double req_double; - char req_string[16]; - AllTypes_req_bytes_t req_bytes; - SubMessage req_submsg; - MyEnum req_enum; - size_t rep_int32_count; - int32_t rep_int32[5]; - size_t rep_int64_count; - int64_t rep_int64[5]; - size_t rep_uint32_count; - uint32_t rep_uint32[5]; - size_t rep_uint64_count; - uint64_t rep_uint64[5]; - size_t rep_sint32_count; - int32_t rep_sint32[5]; - size_t rep_sint64_count; - int64_t rep_sint64[5]; - size_t rep_bool_count; - bool rep_bool[5]; - size_t rep_fixed32_count; - uint32_t rep_fixed32[5]; - size_t rep_sfixed32_count; - int32_t rep_sfixed32[5]; - size_t rep_float_count; - float rep_float[5]; - size_t rep_fixed64_count; - uint64_t rep_fixed64[5]; - size_t rep_sfixed64_count; - int64_t rep_sfixed64[5]; - size_t rep_double_count; - double rep_double[5]; - size_t rep_string_count; - char rep_string[5][16]; - size_t rep_bytes_count; - AllTypes_rep_bytes_t rep_bytes[5]; - size_t rep_submsg_count; - SubMessage rep_submsg[5]; - size_t rep_enum_count; - MyEnum rep_enum[5]; - bool has_opt_int32; - int32_t opt_int32; - bool has_opt_int64; - int64_t opt_int64; - bool has_opt_uint32; - uint32_t opt_uint32; - bool has_opt_uint64; - uint64_t opt_uint64; - bool has_opt_sint32; - int32_t opt_sint32; - bool has_opt_sint64; - int64_t opt_sint64; - bool has_opt_bool; - bool opt_bool; - bool has_opt_fixed32; - uint32_t opt_fixed32; - bool has_opt_sfixed32; - int32_t opt_sfixed32; - bool has_opt_float; - float opt_float; - bool has_opt_fixed64; - uint64_t opt_fixed64; - bool has_opt_sfixed64; - int64_t opt_sfixed64; - bool has_opt_double; - double opt_double; - bool has_opt_string; - char opt_string[16]; - bool has_opt_bytes; - AllTypes_opt_bytes_t opt_bytes; - bool has_opt_submsg; - SubMessage opt_submsg; - bool has_opt_enum; - MyEnum opt_enum; - int32_t end; -} AllTypes; - -/* Default values for struct fields */ -extern const char SubMessage_substuff1_default[16]; -extern const int32_t SubMessage_substuff2_default; -extern const uint32_t SubMessage_substuff3_default; -extern const int32_t AllTypes_opt_int32_default; -extern const int64_t AllTypes_opt_int64_default; -extern const uint32_t AllTypes_opt_uint32_default; -extern const uint64_t AllTypes_opt_uint64_default; -extern const int32_t AllTypes_opt_sint32_default; -extern const int64_t AllTypes_opt_sint64_default; -extern const bool AllTypes_opt_bool_default; -extern const uint32_t AllTypes_opt_fixed32_default; -extern const int32_t AllTypes_opt_sfixed32_default; -extern const float AllTypes_opt_float_default; -extern const uint64_t AllTypes_opt_fixed64_default; -extern const int64_t AllTypes_opt_sfixed64_default; -extern const double AllTypes_opt_double_default; -extern const char AllTypes_opt_string_default[16]; -extern const AllTypes_opt_bytes_t AllTypes_opt_bytes_default; -extern const MyEnum AllTypes_opt_enum_default; - -/* Struct field encoding specification for nanopb */ -extern const pb_field_t SubMessage_fields[4]; -extern const pb_field_t AllTypes_fields[53]; - -/* Check that field information fits in pb_field_t */ -#if !defined(PB_FIELD_16BIT) && !defined(PB_FIELD_32BIT) -STATIC_ASSERT((pb_membersize(AllTypes, req_submsg) < 256 && pb_membersize(AllTypes, rep_submsg[0]) < 256 && pb_membersize(AllTypes, opt_submsg) < 256), YOU_MUST_DEFINE_PB_FIELD_16BIT_FOR_MESSAGES_SubMessage_AllTypes) -#endif - -#if !defined(PB_FIELD_32BIT) -STATIC_ASSERT((pb_membersize(AllTypes, req_submsg) < 65536 && pb_membersize(AllTypes, rep_submsg[0]) < 65536 && pb_membersize(AllTypes, opt_submsg) < 65536), YOU_MUST_DEFINE_PB_FIELD_32BIT_FOR_MESSAGES_SubMessage_AllTypes) -#endif - -/* On some platforms (such as AVR), double is really float. - * These are not directly supported by nanopb, but see example_avr_double. - */ -STATIC_ASSERT(sizeof(double) == 8, DOUBLE_MUST_BE_8_BYTES) - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif diff --git a/tests/bc_decode.c b/tests/bc_decode.c deleted file mode 100644 index b74172f..0000000 --- a/tests/bc_decode.c +++ /dev/null @@ -1,197 +0,0 @@ -/* Tests the decoding of all types. - * This is a backwards-compatibility test, using bc_alltypes.pb.h. - * It is similar to test_decode3, but duplicated in order to allow - * test_decode3 to test any new features introduced later. - * - * Run e.g. ./bc_encode | ./bc_decode - */ - -#include -#include -#include -#include -#include "bc_alltypes.pb.h" - -#define TEST(x) if (!(x)) { \ - printf("Test " #x " failed.\n"); \ - return false; \ - } - -/* This function is called once from main(), it handles - the decoding and checks the fields. */ -bool check_alltypes(pb_istream_t *stream, int mode) -{ - AllTypes alltypes; - - /* Fill with garbage to better detect initialization errors */ - memset(&alltypes, 0xAA, sizeof(alltypes)); - - if (!pb_decode(stream, AllTypes_fields, &alltypes)) - return false; - - TEST(alltypes.req_int32 == -1001); - TEST(alltypes.req_int64 == -1002); - TEST(alltypes.req_uint32 == 1003); - TEST(alltypes.req_uint64 == 1004); - TEST(alltypes.req_sint32 == -1005); - TEST(alltypes.req_sint64 == -1006); - TEST(alltypes.req_bool == true); - - TEST(alltypes.req_fixed32 == 1008); - TEST(alltypes.req_sfixed32 == -1009); - TEST(alltypes.req_float == 1010.0f); - - TEST(alltypes.req_fixed64 == 1011); - TEST(alltypes.req_sfixed64 == -1012); - TEST(alltypes.req_double == 1013.0f); - - TEST(strcmp(alltypes.req_string, "1014") == 0); - TEST(alltypes.req_bytes.size == 4); - TEST(memcmp(alltypes.req_bytes.bytes, "1015", 4) == 0); - TEST(strcmp(alltypes.req_submsg.substuff1, "1016") == 0); - TEST(alltypes.req_submsg.substuff2 == 1016); - TEST(alltypes.req_submsg.substuff3 == 3); - TEST(alltypes.req_enum == MyEnum_Truth); - - TEST(alltypes.rep_int32_count == 5 && alltypes.rep_int32[4] == -2001 && alltypes.rep_int32[0] == 0); - TEST(alltypes.rep_int64_count == 5 && alltypes.rep_int64[4] == -2002 && alltypes.rep_int64[0] == 0); - TEST(alltypes.rep_uint32_count == 5 && alltypes.rep_uint32[4] == 2003 && alltypes.rep_uint32[0] == 0); - TEST(alltypes.rep_uint64_count == 5 && alltypes.rep_uint64[4] == 2004 && alltypes.rep_uint64[0] == 0); - TEST(alltypes.rep_sint32_count == 5 && alltypes.rep_sint32[4] == -2005 && alltypes.rep_sint32[0] == 0); - TEST(alltypes.rep_sint64_count == 5 && alltypes.rep_sint64[4] == -2006 && alltypes.rep_sint64[0] == 0); - TEST(alltypes.rep_bool_count == 5 && alltypes.rep_bool[4] == true && alltypes.rep_bool[0] == false); - - TEST(alltypes.rep_fixed32_count == 5 && alltypes.rep_fixed32[4] == 2008 && alltypes.rep_fixed32[0] == 0); - TEST(alltypes.rep_sfixed32_count == 5 && alltypes.rep_sfixed32[4] == -2009 && alltypes.rep_sfixed32[0] == 0); - TEST(alltypes.rep_float_count == 5 && alltypes.rep_float[4] == 2010.0f && alltypes.rep_float[0] == 0.0f); - - TEST(alltypes.rep_fixed64_count == 5 && alltypes.rep_fixed64[4] == 2011 && alltypes.rep_fixed64[0] == 0); - TEST(alltypes.rep_sfixed64_count == 5 && alltypes.rep_sfixed64[4] == -2012 && alltypes.rep_sfixed64[0] == 0); - TEST(alltypes.rep_double_count == 5 && alltypes.rep_double[4] == 2013.0 && alltypes.rep_double[0] == 0.0); - - TEST(alltypes.rep_string_count == 5 && strcmp(alltypes.rep_string[4], "2014") == 0 && alltypes.rep_string[0][0] == '\0'); - TEST(alltypes.rep_bytes_count == 5 && alltypes.rep_bytes[4].size == 4 && alltypes.rep_bytes[0].size == 0); - TEST(memcmp(alltypes.rep_bytes[4].bytes, "2015", 4) == 0); - - TEST(alltypes.rep_submsg_count == 5); - TEST(strcmp(alltypes.rep_submsg[4].substuff1, "2016") == 0 && alltypes.rep_submsg[0].substuff1[0] == '\0'); - TEST(alltypes.rep_submsg[4].substuff2 == 2016 && alltypes.rep_submsg[0].substuff2 == 0); - TEST(alltypes.rep_submsg[4].substuff3 == 2016 && alltypes.rep_submsg[0].substuff3 == 3); - - TEST(alltypes.rep_enum_count == 5 && alltypes.rep_enum[4] == MyEnum_Truth && alltypes.rep_enum[0] == MyEnum_Zero); - - if (mode == 0) - { - /* Expect default values */ - TEST(alltypes.has_opt_int32 == false); - TEST(alltypes.opt_int32 == 4041); - TEST(alltypes.has_opt_int64 == false); - TEST(alltypes.opt_int64 == 4042); - TEST(alltypes.has_opt_uint32 == false); - TEST(alltypes.opt_uint32 == 4043); - TEST(alltypes.has_opt_uint64 == false); - TEST(alltypes.opt_uint64 == 4044); - TEST(alltypes.has_opt_sint32 == false); - TEST(alltypes.opt_sint32 == 4045); - TEST(alltypes.has_opt_sint64 == false); - TEST(alltypes.opt_sint64 == 4046); - TEST(alltypes.has_opt_bool == false); - TEST(alltypes.opt_bool == false); - - TEST(alltypes.has_opt_fixed32 == false); - TEST(alltypes.opt_fixed32 == 4048); - TEST(alltypes.has_opt_sfixed32 == false); - TEST(alltypes.opt_sfixed32 == 4049); - TEST(alltypes.has_opt_float == false); - TEST(alltypes.opt_float == 4050.0f); - - TEST(alltypes.has_opt_fixed64 == false); - TEST(alltypes.opt_fixed64 == 4051); - TEST(alltypes.has_opt_sfixed64 == false); - TEST(alltypes.opt_sfixed64 == 4052); - TEST(alltypes.has_opt_double == false); - TEST(alltypes.opt_double == 4053.0); - - TEST(alltypes.has_opt_string == false); - TEST(strcmp(alltypes.opt_string, "4054") == 0); - TEST(alltypes.has_opt_bytes == false); - TEST(alltypes.opt_bytes.size == 4); - TEST(memcmp(alltypes.opt_bytes.bytes, "4055", 4) == 0); - TEST(alltypes.has_opt_submsg == false); - TEST(strcmp(alltypes.opt_submsg.substuff1, "1") == 0); - TEST(alltypes.opt_submsg.substuff2 == 2); - TEST(alltypes.opt_submsg.substuff3 == 3); - TEST(alltypes.has_opt_enum == false); - TEST(alltypes.opt_enum == MyEnum_Second); - } - else - { - /* Expect filled-in values */ - TEST(alltypes.has_opt_int32 == true); - TEST(alltypes.opt_int32 == 3041); - TEST(alltypes.has_opt_int64 == true); - TEST(alltypes.opt_int64 == 3042); - TEST(alltypes.has_opt_uint32 == true); - TEST(alltypes.opt_uint32 == 3043); - TEST(alltypes.has_opt_uint64 == true); - TEST(alltypes.opt_uint64 == 3044); - TEST(alltypes.has_opt_sint32 == true); - TEST(alltypes.opt_sint32 == 3045); - TEST(alltypes.has_opt_sint64 == true); - TEST(alltypes.opt_sint64 == 3046); - TEST(alltypes.has_opt_bool == true); - TEST(alltypes.opt_bool == true); - - TEST(alltypes.has_opt_fixed32 == true); - TEST(alltypes.opt_fixed32 == 3048); - TEST(alltypes.has_opt_sfixed32 == true); - TEST(alltypes.opt_sfixed32 == 3049); - TEST(alltypes.has_opt_float == true); - TEST(alltypes.opt_float == 3050.0f); - - TEST(alltypes.has_opt_fixed64 == true); - TEST(alltypes.opt_fixed64 == 3051); - TEST(alltypes.has_opt_sfixed64 == true); - TEST(alltypes.opt_sfixed64 == 3052); - TEST(alltypes.has_opt_double == true); - TEST(alltypes.opt_double == 3053.0); - - TEST(alltypes.has_opt_string == true); - TEST(strcmp(alltypes.opt_string, "3054") == 0); - TEST(alltypes.has_opt_bytes == true); - TEST(alltypes.opt_bytes.size == 4); - TEST(memcmp(alltypes.opt_bytes.bytes, "3055", 4) == 0); - TEST(alltypes.has_opt_submsg == true); - TEST(strcmp(alltypes.opt_submsg.substuff1, "3056") == 0); - TEST(alltypes.opt_submsg.substuff2 == 3056); - TEST(alltypes.opt_submsg.substuff3 == 3); - TEST(alltypes.has_opt_enum == true); - TEST(alltypes.opt_enum == MyEnum_Truth); - } - - TEST(alltypes.end == 1099); - - return true; -} - -int main(int argc, char **argv) -{ - /* Whether to expect the optional values or the default values. */ - int mode = (argc > 1) ? atoi(argv[1]) : 0; - - /* Read the data into buffer */ - uint8_t buffer[1024]; - size_t count = fread(buffer, 1, sizeof(buffer), stdin); - - /* Construct a pb_istream_t for reading from the buffer */ - pb_istream_t stream = pb_istream_from_buffer(buffer, count); - - /* Decode and print out the stuff */ - if (!check_alltypes(&stream, mode)) - { - printf("Parsing failed: %s\n", PB_GET_ERROR(&stream)); - return 1; - } else { - return 0; - } -} diff --git a/tests/bc_encode.c b/tests/bc_encode.c deleted file mode 100644 index e84f090..0000000 --- a/tests/bc_encode.c +++ /dev/null @@ -1,131 +0,0 @@ -/* Attempts to test all the datatypes supported by ProtoBuf. - * This is a backwards-compatibility test, using bc_alltypes.pb.h. - * It is similar to test_encode3, but duplicated in order to allow - * test_encode3 to test any new features introduced later. - */ - -#include -#include -#include -#include -#include "bc_alltypes.pb.h" - -int main(int argc, char **argv) -{ - int mode = (argc > 1) ? atoi(argv[1]) : 0; - - /* Initialize the structure with constants */ - AllTypes alltypes = {0}; - - alltypes.req_int32 = -1001; - alltypes.req_int64 = -1002; - alltypes.req_uint32 = 1003; - alltypes.req_uint64 = 1004; - alltypes.req_sint32 = -1005; - alltypes.req_sint64 = -1006; - alltypes.req_bool = true; - - alltypes.req_fixed32 = 1008; - alltypes.req_sfixed32 = -1009; - alltypes.req_float = 1010.0f; - - alltypes.req_fixed64 = 1011; - alltypes.req_sfixed64 = -1012; - alltypes.req_double = 1013.0; - - strcpy(alltypes.req_string, "1014"); - alltypes.req_bytes.size = 4; - memcpy(alltypes.req_bytes.bytes, "1015", 4); - strcpy(alltypes.req_submsg.substuff1, "1016"); - alltypes.req_submsg.substuff2 = 1016; - alltypes.req_enum = MyEnum_Truth; - - alltypes.rep_int32_count = 5; alltypes.rep_int32[4] = -2001; - alltypes.rep_int64_count = 5; alltypes.rep_int64[4] = -2002; - alltypes.rep_uint32_count = 5; alltypes.rep_uint32[4] = 2003; - alltypes.rep_uint64_count = 5; alltypes.rep_uint64[4] = 2004; - alltypes.rep_sint32_count = 5; alltypes.rep_sint32[4] = -2005; - alltypes.rep_sint64_count = 5; alltypes.rep_sint64[4] = -2006; - alltypes.rep_bool_count = 5; alltypes.rep_bool[4] = true; - - alltypes.rep_fixed32_count = 5; alltypes.rep_fixed32[4] = 2008; - alltypes.rep_sfixed32_count = 5; alltypes.rep_sfixed32[4] = -2009; - alltypes.rep_float_count = 5; alltypes.rep_float[4] = 2010.0f; - - alltypes.rep_fixed64_count = 5; alltypes.rep_fixed64[4] = 2011; - alltypes.rep_sfixed64_count = 5; alltypes.rep_sfixed64[4] = -2012; - alltypes.rep_double_count = 5; alltypes.rep_double[4] = 2013.0; - - alltypes.rep_string_count = 5; strcpy(alltypes.rep_string[4], "2014"); - alltypes.rep_bytes_count = 5; alltypes.rep_bytes[4].size = 4; - memcpy(alltypes.rep_bytes[4].bytes, "2015", 4); - - alltypes.rep_submsg_count = 5; - strcpy(alltypes.rep_submsg[4].substuff1, "2016"); - alltypes.rep_submsg[4].substuff2 = 2016; - alltypes.rep_submsg[4].has_substuff3 = true; - alltypes.rep_submsg[4].substuff3 = 2016; - - alltypes.rep_enum_count = 5; alltypes.rep_enum[4] = MyEnum_Truth; - - if (mode != 0) - { - /* Fill in values for optional fields */ - alltypes.has_opt_int32 = true; - alltypes.opt_int32 = 3041; - alltypes.has_opt_int64 = true; - alltypes.opt_int64 = 3042; - alltypes.has_opt_uint32 = true; - alltypes.opt_uint32 = 3043; - alltypes.has_opt_uint64 = true; - alltypes.opt_uint64 = 3044; - alltypes.has_opt_sint32 = true; - alltypes.opt_sint32 = 3045; - alltypes.has_opt_sint64 = true; - alltypes.opt_sint64 = 3046; - alltypes.has_opt_bool = true; - alltypes.opt_bool = true; - - alltypes.has_opt_fixed32 = true; - alltypes.opt_fixed32 = 3048; - alltypes.has_opt_sfixed32 = true; - alltypes.opt_sfixed32 = 3049; - alltypes.has_opt_float = true; - alltypes.opt_float = 3050.0f; - - alltypes.has_opt_fixed64 = true; - alltypes.opt_fixed64 = 3051; - alltypes.has_opt_sfixed64 = true; - alltypes.opt_sfixed64 = 3052; - alltypes.has_opt_double = true; - alltypes.opt_double = 3053.0; - - alltypes.has_opt_string = true; - strcpy(alltypes.opt_string, "3054"); - alltypes.has_opt_bytes = true; - alltypes.opt_bytes.size = 4; - memcpy(alltypes.opt_bytes.bytes, "3055", 4); - alltypes.has_opt_submsg = true; - strcpy(alltypes.opt_submsg.substuff1, "3056"); - alltypes.opt_submsg.substuff2 = 3056; - alltypes.has_opt_enum = true; - alltypes.opt_enum = MyEnum_Truth; - } - - alltypes.end = 1099; - - uint8_t buffer[1024]; - pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer)); - - /* Now encode it and check if we succeeded. */ - if (pb_encode(&stream, AllTypes_fields, &alltypes)) - { - fwrite(buffer, 1, stream.bytes_written, stdout); - return 0; /* Success */ - } - else - { - fprintf(stderr, "Encoding failed!\n"); - return 1; /* Failure */ - } -} diff --git a/tests/callbacks.proto b/tests/callbacks.proto deleted file mode 100644 index ccd1edd..0000000 --- a/tests/callbacks.proto +++ /dev/null @@ -1,16 +0,0 @@ -message SubMessage { - optional string stringvalue = 1; - repeated int32 int32value = 2; - repeated fixed32 fixed32value = 3; - repeated fixed64 fixed64value = 4; -} - -message TestMessage { - optional string stringvalue = 1; - repeated int32 int32value = 2; - repeated fixed32 fixed32value = 3; - repeated fixed64 fixed64value = 4; - optional SubMessage submsg = 5; - repeated string repeatedstring = 6; -} - diff --git a/tests/callbacks/callbacks.proto b/tests/callbacks/callbacks.proto new file mode 100644 index 0000000..ccd1edd --- /dev/null +++ b/tests/callbacks/callbacks.proto @@ -0,0 +1,16 @@ +message SubMessage { + optional string stringvalue = 1; + repeated int32 int32value = 2; + repeated fixed32 fixed32value = 3; + repeated fixed64 fixed64value = 4; +} + +message TestMessage { + optional string stringvalue = 1; + repeated int32 int32value = 2; + repeated fixed32 fixed32value = 3; + repeated fixed64 fixed64value = 4; + optional SubMessage submsg = 5; + repeated string repeatedstring = 6; +} + diff --git a/tests/callbacks/decode_callbacks.c b/tests/callbacks/decode_callbacks.c new file mode 100644 index 0000000..b505692 --- /dev/null +++ b/tests/callbacks/decode_callbacks.c @@ -0,0 +1,93 @@ +/* Decoding testcase for callback fields. + * Run e.g. ./test_encode_callbacks | ./test_decode_callbacks + */ + +#include +#include +#include "callbacks.pb.h" + +bool print_string(pb_istream_t *stream, const pb_field_t *field, void **arg) +{ + uint8_t buffer[1024] = {0}; + + /* We could read block-by-block to avoid the large buffer... */ + if (stream->bytes_left > sizeof(buffer) - 1) + return false; + + if (!pb_read(stream, buffer, stream->bytes_left)) + return false; + + /* Print the string, in format comparable with protoc --decode. + * Format comes from the arg defined in main(). + */ + printf((char*)*arg, buffer); + return true; +} + +bool print_int32(pb_istream_t *stream, const pb_field_t *field, void **arg) +{ + uint64_t value; + if (!pb_decode_varint(stream, &value)) + return false; + + printf((char*)*arg, (long)value); + return true; +} + +bool print_fixed32(pb_istream_t *stream, const pb_field_t *field, void **arg) +{ + uint32_t value; + if (!pb_decode_fixed32(stream, &value)) + return false; + + printf((char*)*arg, (long)value); + return true; +} + +bool print_fixed64(pb_istream_t *stream, const pb_field_t *field, void **arg) +{ + uint64_t value; + if (!pb_decode_fixed64(stream, &value)) + return false; + + printf((char*)*arg, (long long)value); + return true; +} + +int main() +{ + uint8_t buffer[1024]; + size_t length = fread(buffer, 1, 1024, stdin); + pb_istream_t stream = pb_istream_from_buffer(buffer, length); + + /* Note: empty initializer list initializes the struct with all-0. + * This is recommended so that unused callbacks are set to NULL instead + * of crashing at runtime. + */ + TestMessage testmessage = {}; + + testmessage.submsg.stringvalue.funcs.decode = &print_string; + testmessage.submsg.stringvalue.arg = "submsg {\n stringvalue: \"%s\"\n"; + testmessage.submsg.int32value.funcs.decode = &print_int32; + testmessage.submsg.int32value.arg = " int32value: %ld\n"; + testmessage.submsg.fixed32value.funcs.decode = &print_fixed32; + testmessage.submsg.fixed32value.arg = " fixed32value: %ld\n"; + testmessage.submsg.fixed64value.funcs.decode = &print_fixed64; + testmessage.submsg.fixed64value.arg = " fixed64value: %lld\n}\n"; + + testmessage.stringvalue.funcs.decode = &print_string; + testmessage.stringvalue.arg = "stringvalue: \"%s\"\n"; + testmessage.int32value.funcs.decode = &print_int32; + testmessage.int32value.arg = "int32value: %ld\n"; + testmessage.fixed32value.funcs.decode = &print_fixed32; + testmessage.fixed32value.arg = "fixed32value: %ld\n"; + testmessage.fixed64value.funcs.decode = &print_fixed64; + testmessage.fixed64value.arg = "fixed64value: %lld\n"; + testmessage.repeatedstring.funcs.decode = &print_string; + testmessage.repeatedstring.arg = "repeatedstring: \"%s\"\n"; + + if (!pb_decode(&stream, TestMessage_fields, &testmessage)) + return 1; + + return 0; +} diff --git a/tests/callbacks/encode_callbacks.c b/tests/callbacks/encode_callbacks.c new file mode 100644 index 0000000..3bb6a45 --- /dev/null +++ b/tests/callbacks/encode_callbacks.c @@ -0,0 +1,86 @@ +/* Encoding testcase for callback fields */ + +#include +#include +#include +#include "callbacks.pb.h" + +bool encode_string(pb_ostream_t *stream, const pb_field_t *field, void * const *arg) +{ + char *str = "Hello world!"; + + if (!pb_encode_tag_for_field(stream, field)) + return false; + + return pb_encode_string(stream, (uint8_t*)str, strlen(str)); +} + +bool encode_int32(pb_ostream_t *stream, const pb_field_t *field, void * const *arg) +{ + if (!pb_encode_tag_for_field(stream, field)) + return false; + + return pb_encode_varint(stream, 42); +} + +bool encode_fixed32(pb_ostream_t *stream, const pb_field_t *field, void * const *arg) +{ + if (!pb_encode_tag_for_field(stream, field)) + return false; + + uint32_t value = 42; + return pb_encode_fixed32(stream, &value); +} + +bool encode_fixed64(pb_ostream_t *stream, const pb_field_t *field, void * const *arg) +{ + if (!pb_encode_tag_for_field(stream, field)) + return false; + + uint64_t value = 42; + return pb_encode_fixed64(stream, &value); +} + +bool encode_repeatedstring(pb_ostream_t *stream, const pb_field_t *field, void * const *arg) +{ + char *str[4] = {"Hello world!", "", "Test", "Test2"}; + int i; + + for (i = 0; i < 4; i++) + { + if (!pb_encode_tag_for_field(stream, field)) + return false; + + if (!pb_encode_string(stream, (uint8_t*)str[i], strlen(str[i]))) + return false; + } + return true; +} + +int main() +{ + uint8_t buffer[1024]; + pb_ostream_t stream = pb_ostream_from_buffer(buffer, 1024); + TestMessage testmessage = {}; + + testmessage.stringvalue.funcs.encode = &encode_string; + testmessage.int32value.funcs.encode = &encode_int32; + testmessage.fixed32value.funcs.encode = &encode_fixed32; + testmessage.fixed64value.funcs.encode = &encode_fixed64; + + testmessage.has_submsg = true; + testmessage.submsg.stringvalue.funcs.encode = &encode_string; + testmessage.submsg.int32value.funcs.encode = &encode_int32; + testmessage.submsg.fixed32value.funcs.encode = &encode_fixed32; + testmessage.submsg.fixed64value.funcs.encode = &encode_fixed64; + + testmessage.repeatedstring.funcs.encode = &encode_repeatedstring; + + if (!pb_encode(&stream, TestMessage_fields, &testmessage)) + return 1; + + if (fwrite(buffer, stream.bytes_written, 1, stdout) != 1) + return 2; + + return 0; +} diff --git a/tests/callbacks2.proto b/tests/callbacks2.proto deleted file mode 100644 index 9a55e15..0000000 --- a/tests/callbacks2.proto +++ /dev/null @@ -1,9 +0,0 @@ -// Test if including generated header file for this file + implicit include of -// callbacks.pb.h still compiles. Used with test_compiles.c. -import "callbacks.proto"; - -message Callback2Message { - required TestMessage tstmsg = 1; - required SubMessage submsg = 2; -} - diff --git a/tests/common/SConscript b/tests/common/SConscript new file mode 100644 index 0000000..ef3cdca --- /dev/null +++ b/tests/common/SConscript @@ -0,0 +1,14 @@ +# Build the common files needed by multiple test cases + +Import('env') + +# Protocol definitions for the encode/decode_unittests +env.NanopbProto("unittestproto") + +# Protocol definitions for basic_buffer/stream tests +env.NanopbProto("person") + +# Binaries of the pb_decode.c and pb_encode.c +env.Object("pb_decode.o", "#../pb_decode.c") +env.Object("pb_encode.o", "#../pb_encode.c") + diff --git a/tests/common/person.proto b/tests/common/person.proto new file mode 100644 index 0000000..dafcf93 --- /dev/null +++ b/tests/common/person.proto @@ -0,0 +1,20 @@ +import "nanopb.proto"; + +message Person { + required string name = 1 [(nanopb).max_size = 40]; + required int32 id = 2; + optional string email = 3 [(nanopb).max_size = 40]; + + enum PhoneType { + MOBILE = 0; + HOME = 1; + WORK = 2; + } + + message PhoneNumber { + required string number = 1 [(nanopb).max_size = 40]; + optional PhoneType type = 2 [default = HOME]; + } + + repeated PhoneNumber phone = 4 [(nanopb).max_count = 5]; +} diff --git a/tests/common/unittestproto.proto b/tests/common/unittestproto.proto new file mode 100644 index 0000000..7024942 --- /dev/null +++ b/tests/common/unittestproto.proto @@ -0,0 +1,32 @@ +import 'nanopb.proto'; + +message IntegerArray { + repeated int32 data = 1 [(nanopb).max_count = 10]; +} + +message FloatArray { + repeated float data = 1 [(nanopb).max_count = 10]; +} + +message StringMessage { + required string data = 1 [(nanopb).max_size = 10]; +} + +message CallbackArray { + // We cheat a bit and use this message for testing other types, too. + // Nanopb does not care about the actual defined data type for callback + // fields. + repeated int32 data = 1; +} + +message IntegerContainer { + required IntegerArray submsg = 1; +} + +message CallbackContainer { + required CallbackArray submsg = 1; +} + +message CallbackContainerContainer { + required CallbackContainer submsg = 1; +} diff --git a/tests/common/unittests.h b/tests/common/unittests.h new file mode 100644 index 0000000..c2b470a --- /dev/null +++ b/tests/common/unittests.h @@ -0,0 +1,14 @@ +#include + +#define COMMENT(x) printf("\n----" x "----\n"); +#define STR(x) #x +#define STR2(x) STR(x) +#define TEST(x) \ + if (!(x)) { \ + fprintf(stderr, "\033[31;1mFAILED:\033[22;39m " __FILE__ ":" STR2(__LINE__) " " #x "\n"); \ + status = 1; \ + } else { \ + printf("\033[32;1mOK:\033[22;39m " #x "\n"); \ + } + + diff --git a/tests/decode_unittests.c b/tests/decode_unittests.c deleted file mode 100644 index 6ad05f0..0000000 --- a/tests/decode_unittests.c +++ /dev/null @@ -1,306 +0,0 @@ -#define NANOPB_INTERNALS - -#include -#include -#include "pb_decode.h" -#include "unittests.h" -#include "unittestproto.pb.h" - -#define S(x) pb_istream_from_buffer((uint8_t*)x, sizeof(x) - 1) - -bool stream_callback(pb_istream_t *stream, uint8_t *buf, size_t count) -{ - if (stream->state != NULL) - return false; /* Simulate error */ - - if (buf != NULL) - memset(buf, 'x', count); - return true; -} - -/* Verifies that the stream passed to callback matches the byte array pointed to by arg. */ -bool callback_check(pb_istream_t *stream, const pb_field_t *field, void **arg) -{ - int i; - uint8_t byte; - pb_bytes_array_t *ref = (pb_bytes_array_t*) *arg; - - for (i = 0; i < ref->size; i++) - { - if (!pb_read(stream, &byte, 1)) - return false; - - if (byte != ref->bytes[i]) - return false; - } - - return true; -} - -int main() -{ - int status = 0; - - { - uint8_t buffer1[] = "foobartest1234"; - uint8_t buffer2[sizeof(buffer1)]; - pb_istream_t stream = pb_istream_from_buffer(buffer1, sizeof(buffer1)); - - COMMENT("Test pb_read and pb_istream_t"); - TEST(pb_read(&stream, buffer2, 6)) - TEST(memcmp(buffer2, "foobar", 6) == 0) - TEST(stream.bytes_left == sizeof(buffer1) - 6) - TEST(pb_read(&stream, buffer2 + 6, stream.bytes_left)) - TEST(memcmp(buffer1, buffer2, sizeof(buffer1)) == 0) - TEST(stream.bytes_left == 0) - TEST(!pb_read(&stream, buffer2, 1)) - } - - { - uint8_t buffer[20]; - pb_istream_t stream = {&stream_callback, NULL, 20}; - - COMMENT("Test pb_read with custom callback"); - TEST(pb_read(&stream, buffer, 5)) - TEST(memcmp(buffer, "xxxxx", 5) == 0) - TEST(!pb_read(&stream, buffer, 50)) - stream.state = (void*)1; /* Simulated error return from callback */ - TEST(!pb_read(&stream, buffer, 5)) - stream.state = NULL; - TEST(pb_read(&stream, buffer, 15)) - } - - { - pb_istream_t s; - uint64_t u; - int64_t i; - - COMMENT("Test pb_decode_varint"); - TEST((s = S("\x00"), pb_decode_varint(&s, &u) && u == 0)); - TEST((s = S("\x01"), pb_decode_varint(&s, &u) && u == 1)); - TEST((s = S("\xAC\x02"), pb_decode_varint(&s, &u) && u == 300)); - TEST((s = S("\xFF\xFF\xFF\xFF\x0F"), pb_decode_varint(&s, &u) && u == UINT32_MAX)); - TEST((s = S("\xFF\xFF\xFF\xFF\x0F"), pb_decode_varint(&s, (uint64_t*)&i) && i == UINT32_MAX)); - TEST((s = S("\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x01"), - pb_decode_varint(&s, (uint64_t*)&i) && i == -1)); - TEST((s = S("\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x01"), - pb_decode_varint(&s, &u) && u == UINT64_MAX)); - } - - { - pb_istream_t s; - COMMENT("Test pb_skip_varint"); - TEST((s = S("\x00""foobar"), pb_skip_varint(&s) && s.bytes_left == 6)) - TEST((s = S("\xAC\x02""foobar"), pb_skip_varint(&s) && s.bytes_left == 6)) - TEST((s = S("\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x01""foobar"), - pb_skip_varint(&s) && s.bytes_left == 6)) - TEST((s = S("\xFF"), !pb_skip_varint(&s))) - } - - { - pb_istream_t s; - COMMENT("Test pb_skip_string") - TEST((s = S("\x00""foobar"), pb_skip_string(&s) && s.bytes_left == 6)) - TEST((s = S("\x04""testfoobar"), pb_skip_string(&s) && s.bytes_left == 6)) - TEST((s = S("\x04"), !pb_skip_string(&s))) - TEST((s = S("\xFF"), !pb_skip_string(&s))) - } - - { - pb_istream_t s = S("\x01\xFF\xFF\x03"); - pb_field_t f = {1, PB_LTYPE_VARINT, 0, 0, 4, 0, 0}; - uint32_t d; - COMMENT("Test pb_dec_varint using uint32_t") - TEST(pb_dec_varint(&s, &f, &d) && d == 1) - - /* Verify that no more than data_size is written. */ - d = 0; - f.data_size = 1; - TEST(pb_dec_varint(&s, &f, &d) && (d == 0xFF || d == 0xFF000000)) - } - - { - pb_istream_t s; - pb_field_t f = {1, PB_LTYPE_SVARINT, 0, 0, 4, 0, 0}; - int32_t d; - - COMMENT("Test pb_dec_svarint using int32_t") - TEST((s = S("\x01"), pb_dec_svarint(&s, &f, &d) && d == -1)) - TEST((s = S("\x02"), pb_dec_svarint(&s, &f, &d) && d == 1)) - TEST((s = S("\xfe\xff\xff\xff\x0f"), pb_dec_svarint(&s, &f, &d) && d == INT32_MAX)) - TEST((s = S("\xff\xff\xff\xff\x0f"), pb_dec_svarint(&s, &f, &d) && d == INT32_MIN)) - } - - { - pb_istream_t s; - pb_field_t f = {1, PB_LTYPE_SVARINT, 0, 0, 8, 0, 0}; - uint64_t d; - - COMMENT("Test pb_dec_svarint using uint64_t") - TEST((s = S("\x01"), pb_dec_svarint(&s, &f, &d) && d == -1)) - TEST((s = S("\x02"), pb_dec_svarint(&s, &f, &d) && d == 1)) - TEST((s = S("\xFE\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x01"), pb_dec_svarint(&s, &f, &d) && d == INT64_MAX)) - TEST((s = S("\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x01"), pb_dec_svarint(&s, &f, &d) && d == INT64_MIN)) - } - - { - pb_istream_t s; - pb_field_t f = {1, PB_LTYPE_FIXED32, 0, 0, 4, 0, 0}; - float d; - - COMMENT("Test pb_dec_fixed32 using float (failures here may be caused by imperfect rounding)") - TEST((s = S("\x00\x00\x00\x00"), pb_dec_fixed32(&s, &f, &d) && d == 0.0f)) - TEST((s = S("\x00\x00\xc6\x42"), pb_dec_fixed32(&s, &f, &d) && d == 99.0f)) - TEST((s = S("\x4e\x61\x3c\xcb"), pb_dec_fixed32(&s, &f, &d) && d == -12345678.0f)) - TEST((s = S("\x00"), !pb_dec_fixed32(&s, &f, &d) && d == -12345678.0f)) - } - - { - pb_istream_t s; - pb_field_t f = {1, PB_LTYPE_FIXED64, 0, 0, 8, 0, 0}; - double d; - - COMMENT("Test pb_dec_fixed64 using double (failures here may be caused by imperfect rounding)") - TEST((s = S("\x00\x00\x00\x00\x00\x00\x00\x00"), pb_dec_fixed64(&s, &f, &d) && d == 0.0)) - TEST((s = S("\x00\x00\x00\x00\x00\xc0\x58\x40"), pb_dec_fixed64(&s, &f, &d) && d == 99.0)) - TEST((s = S("\x00\x00\x00\xc0\x29\x8c\x67\xc1"), pb_dec_fixed64(&s, &f, &d) && d == -12345678.0f)) - } - - { - pb_istream_t s; - struct { size_t size; uint8_t bytes[5]; } d; - pb_field_t f = {1, PB_LTYPE_BYTES, 0, 0, sizeof(d), 0, 0}; - - COMMENT("Test pb_dec_bytes") - TEST((s = S("\x00"), pb_dec_bytes(&s, &f, &d) && d.size == 0)) - TEST((s = S("\x01\xFF"), pb_dec_bytes(&s, &f, &d) && d.size == 1 && d.bytes[0] == 0xFF)) - TEST((s = S("\x05xxxxx"), pb_dec_bytes(&s, &f, &d) && d.size == 5)) - TEST((s = S("\x05xxxx"), !pb_dec_bytes(&s, &f, &d))) - - /* Note: the size limit on bytes-fields is not strictly obeyed, as - * the compiler may add some padding to the struct. Using this padding - * is not a very good thing to do, but it is difficult to avoid when - * we use only a single uint8_t to store the size of the field. - * Therefore this tests against a 10-byte string, while otherwise even - * 6 bytes should error out. - */ - TEST((s = S("\x10xxxxxxxxxx"), !pb_dec_bytes(&s, &f, &d))) - } - - { - pb_istream_t s; - pb_field_t f = {1, PB_LTYPE_STRING, 0, 0, 5, 0, 0}; - char d[5]; - - COMMENT("Test pb_dec_string") - TEST((s = S("\x00"), pb_dec_string(&s, &f, &d) && d[0] == '\0')) - TEST((s = S("\x04xyzz"), pb_dec_string(&s, &f, &d) && strcmp(d, "xyzz") == 0)) - TEST((s = S("\x05xyzzy"), !pb_dec_string(&s, &f, &d))) - } - - { - pb_istream_t s; - IntegerArray dest; - - COMMENT("Testing pb_decode with repeated int32 field") - TEST((s = S(""), pb_decode(&s, IntegerArray_fields, &dest) && dest.data_count == 0)) - TEST((s = S("\x08\x01\x08\x02"), pb_decode(&s, IntegerArray_fields, &dest) - && dest.data_count == 2 && dest.data[0] == 1 && dest.data[1] == 2)) - s = S("\x08\x01\x08\x02\x08\x03\x08\x04\x08\x05\x08\x06\x08\x07\x08\x08\x08\x09\x08\x0A"); - TEST(pb_decode(&s, IntegerArray_fields, &dest) && dest.data_count == 10 && dest.data[9] == 10) - s = S("\x08\x01\x08\x02\x08\x03\x08\x04\x08\x05\x08\x06\x08\x07\x08\x08\x08\x09\x08\x0A\x08\x0B"); - TEST(!pb_decode(&s, IntegerArray_fields, &dest)) - } - - { - pb_istream_t s; - IntegerArray dest; - - COMMENT("Testing pb_decode with packed int32 field") - TEST((s = S("\x0A\x00"), pb_decode(&s, IntegerArray_fields, &dest) - && dest.data_count == 0)) - TEST((s = S("\x0A\x01\x01"), pb_decode(&s, IntegerArray_fields, &dest) - && dest.data_count == 1 && dest.data[0] == 1)) - TEST((s = S("\x0A\x0A\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A"), pb_decode(&s, IntegerArray_fields, &dest) - && dest.data_count == 10 && dest.data[0] == 1 && dest.data[9] == 10)) - TEST((s = S("\x0A\x0B\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B"), !pb_decode(&s, IntegerArray_fields, &dest))) - - /* Test invalid wire data */ - TEST((s = S("\x0A\xFF"), !pb_decode(&s, IntegerArray_fields, &dest))) - TEST((s = S("\x0A\x01"), !pb_decode(&s, IntegerArray_fields, &dest))) - } - - { - pb_istream_t s; - IntegerArray dest; - - COMMENT("Testing pb_decode with unknown fields") - TEST((s = S("\x18\x0F\x08\x01"), pb_decode(&s, IntegerArray_fields, &dest) - && dest.data_count == 1 && dest.data[0] == 1)) - TEST((s = S("\x19\x00\x00\x00\x00\x00\x00\x00\x00\x08\x01"), pb_decode(&s, IntegerArray_fields, &dest) - && dest.data_count == 1 && dest.data[0] == 1)) - TEST((s = S("\x1A\x00\x08\x01"), pb_decode(&s, IntegerArray_fields, &dest) - && dest.data_count == 1 && dest.data[0] == 1)) - TEST((s = S("\x1B\x08\x01"), !pb_decode(&s, IntegerArray_fields, &dest))) - TEST((s = S("\x1D\x00\x00\x00\x00\x08\x01"), pb_decode(&s, IntegerArray_fields, &dest) - && dest.data_count == 1 && dest.data[0] == 1)) - } - - { - pb_istream_t s; - CallbackArray dest; - struct { size_t size; uint8_t bytes[10]; } ref; - dest.data.funcs.decode = &callback_check; - dest.data.arg = &ref; - - COMMENT("Testing pb_decode with callbacks") - /* Single varint */ - ref.size = 1; ref.bytes[0] = 0x55; - TEST((s = S("\x08\x55"), pb_decode(&s, CallbackArray_fields, &dest))) - /* Packed varint */ - ref.size = 3; ref.bytes[0] = ref.bytes[1] = ref.bytes[2] = 0x55; - TEST((s = S("\x0A\x03\x55\x55\x55"), pb_decode(&s, CallbackArray_fields, &dest))) - /* Packed varint with loop */ - ref.size = 1; ref.bytes[0] = 0x55; - TEST((s = S("\x0A\x03\x55\x55\x55"), pb_decode(&s, CallbackArray_fields, &dest))) - /* Single fixed32 */ - ref.size = 4; ref.bytes[0] = ref.bytes[1] = ref.bytes[2] = ref.bytes[3] = 0xAA; - TEST((s = S("\x0D\xAA\xAA\xAA\xAA"), pb_decode(&s, CallbackArray_fields, &dest))) - /* Single fixed64 */ - ref.size = 8; memset(ref.bytes, 0xAA, 8); - TEST((s = S("\x09\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"), pb_decode(&s, CallbackArray_fields, &dest))) - /* Unsupported field type */ - TEST((s = S("\x0B\x00"), !pb_decode(&s, CallbackArray_fields, &dest))) - - /* Just make sure that our test function works */ - ref.size = 1; ref.bytes[0] = 0x56; - TEST((s = S("\x08\x55"), !pb_decode(&s, CallbackArray_fields, &dest))) - } - - { - pb_istream_t s; - IntegerArray dest; - - COMMENT("Testing pb_decode message termination") - TEST((s = S(""), pb_decode(&s, IntegerArray_fields, &dest))) - TEST((s = S("\x00"), pb_decode(&s, IntegerArray_fields, &dest))) - TEST((s = S("\x08\x01"), pb_decode(&s, IntegerArray_fields, &dest))) - TEST((s = S("\x08\x01\x00"), pb_decode(&s, IntegerArray_fields, &dest))) - TEST((s = S("\x08"), !pb_decode(&s, IntegerArray_fields, &dest))) - } - - { - pb_istream_t s; - IntegerContainer dest = {}; - - COMMENT("Testing pb_decode_delimited") - TEST((s = S("\x09\x0A\x07\x0A\x05\x01\x02\x03\x04\x05"), - pb_decode_delimited(&s, IntegerContainer_fields, &dest)) && - dest.submsg.data_count == 5) - } - - if (status != 0) - fprintf(stdout, "\n\nSome tests FAILED!\n"); - - return status; -} diff --git a/tests/decode_unittests/SConscript b/tests/decode_unittests/SConscript new file mode 100644 index 0000000..860d773 --- /dev/null +++ b/tests/decode_unittests/SConscript @@ -0,0 +1,4 @@ +Import('env') +env.Program(["decode_unittests.c", "#common/unittestproto.pb.c", "#common/pb_decode.o"]) +env.RunTest('decode_unittests') + diff --git a/tests/decode_unittests/decode_unittests.c b/tests/decode_unittests/decode_unittests.c new file mode 100644 index 0000000..6ad05f0 --- /dev/null +++ b/tests/decode_unittests/decode_unittests.c @@ -0,0 +1,306 @@ +#define NANOPB_INTERNALS + +#include +#include +#include "pb_decode.h" +#include "unittests.h" +#include "unittestproto.pb.h" + +#define S(x) pb_istream_from_buffer((uint8_t*)x, sizeof(x) - 1) + +bool stream_callback(pb_istream_t *stream, uint8_t *buf, size_t count) +{ + if (stream->state != NULL) + return false; /* Simulate error */ + + if (buf != NULL) + memset(buf, 'x', count); + return true; +} + +/* Verifies that the stream passed to callback matches the byte array pointed to by arg. */ +bool callback_check(pb_istream_t *stream, const pb_field_t *field, void **arg) +{ + int i; + uint8_t byte; + pb_bytes_array_t *ref = (pb_bytes_array_t*) *arg; + + for (i = 0; i < ref->size; i++) + { + if (!pb_read(stream, &byte, 1)) + return false; + + if (byte != ref->bytes[i]) + return false; + } + + return true; +} + +int main() +{ + int status = 0; + + { + uint8_t buffer1[] = "foobartest1234"; + uint8_t buffer2[sizeof(buffer1)]; + pb_istream_t stream = pb_istream_from_buffer(buffer1, sizeof(buffer1)); + + COMMENT("Test pb_read and pb_istream_t"); + TEST(pb_read(&stream, buffer2, 6)) + TEST(memcmp(buffer2, "foobar", 6) == 0) + TEST(stream.bytes_left == sizeof(buffer1) - 6) + TEST(pb_read(&stream, buffer2 + 6, stream.bytes_left)) + TEST(memcmp(buffer1, buffer2, sizeof(buffer1)) == 0) + TEST(stream.bytes_left == 0) + TEST(!pb_read(&stream, buffer2, 1)) + } + + { + uint8_t buffer[20]; + pb_istream_t stream = {&stream_callback, NULL, 20}; + + COMMENT("Test pb_read with custom callback"); + TEST(pb_read(&stream, buffer, 5)) + TEST(memcmp(buffer, "xxxxx", 5) == 0) + TEST(!pb_read(&stream, buffer, 50)) + stream.state = (void*)1; /* Simulated error return from callback */ + TEST(!pb_read(&stream, buffer, 5)) + stream.state = NULL; + TEST(pb_read(&stream, buffer, 15)) + } + + { + pb_istream_t s; + uint64_t u; + int64_t i; + + COMMENT("Test pb_decode_varint"); + TEST((s = S("\x00"), pb_decode_varint(&s, &u) && u == 0)); + TEST((s = S("\x01"), pb_decode_varint(&s, &u) && u == 1)); + TEST((s = S("\xAC\x02"), pb_decode_varint(&s, &u) && u == 300)); + TEST((s = S("\xFF\xFF\xFF\xFF\x0F"), pb_decode_varint(&s, &u) && u == UINT32_MAX)); + TEST((s = S("\xFF\xFF\xFF\xFF\x0F"), pb_decode_varint(&s, (uint64_t*)&i) && i == UINT32_MAX)); + TEST((s = S("\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x01"), + pb_decode_varint(&s, (uint64_t*)&i) && i == -1)); + TEST((s = S("\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x01"), + pb_decode_varint(&s, &u) && u == UINT64_MAX)); + } + + { + pb_istream_t s; + COMMENT("Test pb_skip_varint"); + TEST((s = S("\x00""foobar"), pb_skip_varint(&s) && s.bytes_left == 6)) + TEST((s = S("\xAC\x02""foobar"), pb_skip_varint(&s) && s.bytes_left == 6)) + TEST((s = S("\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x01""foobar"), + pb_skip_varint(&s) && s.bytes_left == 6)) + TEST((s = S("\xFF"), !pb_skip_varint(&s))) + } + + { + pb_istream_t s; + COMMENT("Test pb_skip_string") + TEST((s = S("\x00""foobar"), pb_skip_string(&s) && s.bytes_left == 6)) + TEST((s = S("\x04""testfoobar"), pb_skip_string(&s) && s.bytes_left == 6)) + TEST((s = S("\x04"), !pb_skip_string(&s))) + TEST((s = S("\xFF"), !pb_skip_string(&s))) + } + + { + pb_istream_t s = S("\x01\xFF\xFF\x03"); + pb_field_t f = {1, PB_LTYPE_VARINT, 0, 0, 4, 0, 0}; + uint32_t d; + COMMENT("Test pb_dec_varint using uint32_t") + TEST(pb_dec_varint(&s, &f, &d) && d == 1) + + /* Verify that no more than data_size is written. */ + d = 0; + f.data_size = 1; + TEST(pb_dec_varint(&s, &f, &d) && (d == 0xFF || d == 0xFF000000)) + } + + { + pb_istream_t s; + pb_field_t f = {1, PB_LTYPE_SVARINT, 0, 0, 4, 0, 0}; + int32_t d; + + COMMENT("Test pb_dec_svarint using int32_t") + TEST((s = S("\x01"), pb_dec_svarint(&s, &f, &d) && d == -1)) + TEST((s = S("\x02"), pb_dec_svarint(&s, &f, &d) && d == 1)) + TEST((s = S("\xfe\xff\xff\xff\x0f"), pb_dec_svarint(&s, &f, &d) && d == INT32_MAX)) + TEST((s = S("\xff\xff\xff\xff\x0f"), pb_dec_svarint(&s, &f, &d) && d == INT32_MIN)) + } + + { + pb_istream_t s; + pb_field_t f = {1, PB_LTYPE_SVARINT, 0, 0, 8, 0, 0}; + uint64_t d; + + COMMENT("Test pb_dec_svarint using uint64_t") + TEST((s = S("\x01"), pb_dec_svarint(&s, &f, &d) && d == -1)) + TEST((s = S("\x02"), pb_dec_svarint(&s, &f, &d) && d == 1)) + TEST((s = S("\xFE\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x01"), pb_dec_svarint(&s, &f, &d) && d == INT64_MAX)) + TEST((s = S("\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x01"), pb_dec_svarint(&s, &f, &d) && d == INT64_MIN)) + } + + { + pb_istream_t s; + pb_field_t f = {1, PB_LTYPE_FIXED32, 0, 0, 4, 0, 0}; + float d; + + COMMENT("Test pb_dec_fixed32 using float (failures here may be caused by imperfect rounding)") + TEST((s = S("\x00\x00\x00\x00"), pb_dec_fixed32(&s, &f, &d) && d == 0.0f)) + TEST((s = S("\x00\x00\xc6\x42"), pb_dec_fixed32(&s, &f, &d) && d == 99.0f)) + TEST((s = S("\x4e\x61\x3c\xcb"), pb_dec_fixed32(&s, &f, &d) && d == -12345678.0f)) + TEST((s = S("\x00"), !pb_dec_fixed32(&s, &f, &d) && d == -12345678.0f)) + } + + { + pb_istream_t s; + pb_field_t f = {1, PB_LTYPE_FIXED64, 0, 0, 8, 0, 0}; + double d; + + COMMENT("Test pb_dec_fixed64 using double (failures here may be caused by imperfect rounding)") + TEST((s = S("\x00\x00\x00\x00\x00\x00\x00\x00"), pb_dec_fixed64(&s, &f, &d) && d == 0.0)) + TEST((s = S("\x00\x00\x00\x00\x00\xc0\x58\x40"), pb_dec_fixed64(&s, &f, &d) && d == 99.0)) + TEST((s = S("\x00\x00\x00\xc0\x29\x8c\x67\xc1"), pb_dec_fixed64(&s, &f, &d) && d == -12345678.0f)) + } + + { + pb_istream_t s; + struct { size_t size; uint8_t bytes[5]; } d; + pb_field_t f = {1, PB_LTYPE_BYTES, 0, 0, sizeof(d), 0, 0}; + + COMMENT("Test pb_dec_bytes") + TEST((s = S("\x00"), pb_dec_bytes(&s, &f, &d) && d.size == 0)) + TEST((s = S("\x01\xFF"), pb_dec_bytes(&s, &f, &d) && d.size == 1 && d.bytes[0] == 0xFF)) + TEST((s = S("\x05xxxxx"), pb_dec_bytes(&s, &f, &d) && d.size == 5)) + TEST((s = S("\x05xxxx"), !pb_dec_bytes(&s, &f, &d))) + + /* Note: the size limit on bytes-fields is not strictly obeyed, as + * the compiler may add some padding to the struct. Using this padding + * is not a very good thing to do, but it is difficult to avoid when + * we use only a single uint8_t to store the size of the field. + * Therefore this tests against a 10-byte string, while otherwise even + * 6 bytes should error out. + */ + TEST((s = S("\x10xxxxxxxxxx"), !pb_dec_bytes(&s, &f, &d))) + } + + { + pb_istream_t s; + pb_field_t f = {1, PB_LTYPE_STRING, 0, 0, 5, 0, 0}; + char d[5]; + + COMMENT("Test pb_dec_string") + TEST((s = S("\x00"), pb_dec_string(&s, &f, &d) && d[0] == '\0')) + TEST((s = S("\x04xyzz"), pb_dec_string(&s, &f, &d) && strcmp(d, "xyzz") == 0)) + TEST((s = S("\x05xyzzy"), !pb_dec_string(&s, &f, &d))) + } + + { + pb_istream_t s; + IntegerArray dest; + + COMMENT("Testing pb_decode with repeated int32 field") + TEST((s = S(""), pb_decode(&s, IntegerArray_fields, &dest) && dest.data_count == 0)) + TEST((s = S("\x08\x01\x08\x02"), pb_decode(&s, IntegerArray_fields, &dest) + && dest.data_count == 2 && dest.data[0] == 1 && dest.data[1] == 2)) + s = S("\x08\x01\x08\x02\x08\x03\x08\x04\x08\x05\x08\x06\x08\x07\x08\x08\x08\x09\x08\x0A"); + TEST(pb_decode(&s, IntegerArray_fields, &dest) && dest.data_count == 10 && dest.data[9] == 10) + s = S("\x08\x01\x08\x02\x08\x03\x08\x04\x08\x05\x08\x06\x08\x07\x08\x08\x08\x09\x08\x0A\x08\x0B"); + TEST(!pb_decode(&s, IntegerArray_fields, &dest)) + } + + { + pb_istream_t s; + IntegerArray dest; + + COMMENT("Testing pb_decode with packed int32 field") + TEST((s = S("\x0A\x00"), pb_decode(&s, IntegerArray_fields, &dest) + && dest.data_count == 0)) + TEST((s = S("\x0A\x01\x01"), pb_decode(&s, IntegerArray_fields, &dest) + && dest.data_count == 1 && dest.data[0] == 1)) + TEST((s = S("\x0A\x0A\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A"), pb_decode(&s, IntegerArray_fields, &dest) + && dest.data_count == 10 && dest.data[0] == 1 && dest.data[9] == 10)) + TEST((s = S("\x0A\x0B\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B"), !pb_decode(&s, IntegerArray_fields, &dest))) + + /* Test invalid wire data */ + TEST((s = S("\x0A\xFF"), !pb_decode(&s, IntegerArray_fields, &dest))) + TEST((s = S("\x0A\x01"), !pb_decode(&s, IntegerArray_fields, &dest))) + } + + { + pb_istream_t s; + IntegerArray dest; + + COMMENT("Testing pb_decode with unknown fields") + TEST((s = S("\x18\x0F\x08\x01"), pb_decode(&s, IntegerArray_fields, &dest) + && dest.data_count == 1 && dest.data[0] == 1)) + TEST((s = S("\x19\x00\x00\x00\x00\x00\x00\x00\x00\x08\x01"), pb_decode(&s, IntegerArray_fields, &dest) + && dest.data_count == 1 && dest.data[0] == 1)) + TEST((s = S("\x1A\x00\x08\x01"), pb_decode(&s, IntegerArray_fields, &dest) + && dest.data_count == 1 && dest.data[0] == 1)) + TEST((s = S("\x1B\x08\x01"), !pb_decode(&s, IntegerArray_fields, &dest))) + TEST((s = S("\x1D\x00\x00\x00\x00\x08\x01"), pb_decode(&s, IntegerArray_fields, &dest) + && dest.data_count == 1 && dest.data[0] == 1)) + } + + { + pb_istream_t s; + CallbackArray dest; + struct { size_t size; uint8_t bytes[10]; } ref; + dest.data.funcs.decode = &callback_check; + dest.data.arg = &ref; + + COMMENT("Testing pb_decode with callbacks") + /* Single varint */ + ref.size = 1; ref.bytes[0] = 0x55; + TEST((s = S("\x08\x55"), pb_decode(&s, CallbackArray_fields, &dest))) + /* Packed varint */ + ref.size = 3; ref.bytes[0] = ref.bytes[1] = ref.bytes[2] = 0x55; + TEST((s = S("\x0A\x03\x55\x55\x55"), pb_decode(&s, CallbackArray_fields, &dest))) + /* Packed varint with loop */ + ref.size = 1; ref.bytes[0] = 0x55; + TEST((s = S("\x0A\x03\x55\x55\x55"), pb_decode(&s, CallbackArray_fields, &dest))) + /* Single fixed32 */ + ref.size = 4; ref.bytes[0] = ref.bytes[1] = ref.bytes[2] = ref.bytes[3] = 0xAA; + TEST((s = S("\x0D\xAA\xAA\xAA\xAA"), pb_decode(&s, CallbackArray_fields, &dest))) + /* Single fixed64 */ + ref.size = 8; memset(ref.bytes, 0xAA, 8); + TEST((s = S("\x09\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"), pb_decode(&s, CallbackArray_fields, &dest))) + /* Unsupported field type */ + TEST((s = S("\x0B\x00"), !pb_decode(&s, CallbackArray_fields, &dest))) + + /* Just make sure that our test function works */ + ref.size = 1; ref.bytes[0] = 0x56; + TEST((s = S("\x08\x55"), !pb_decode(&s, CallbackArray_fields, &dest))) + } + + { + pb_istream_t s; + IntegerArray dest; + + COMMENT("Testing pb_decode message termination") + TEST((s = S(""), pb_decode(&s, IntegerArray_fields, &dest))) + TEST((s = S("\x00"), pb_decode(&s, IntegerArray_fields, &dest))) + TEST((s = S("\x08\x01"), pb_decode(&s, IntegerArray_fields, &dest))) + TEST((s = S("\x08\x01\x00"), pb_decode(&s, IntegerArray_fields, &dest))) + TEST((s = S("\x08"), !pb_decode(&s, IntegerArray_fields, &dest))) + } + + { + pb_istream_t s; + IntegerContainer dest = {}; + + COMMENT("Testing pb_decode_delimited") + TEST((s = S("\x09\x0A\x07\x0A\x05\x01\x02\x03\x04\x05"), + pb_decode_delimited(&s, IntegerContainer_fields, &dest)) && + dest.submsg.data_count == 5) + } + + if (status != 0) + fprintf(stdout, "\n\nSome tests FAILED!\n"); + + return status; +} diff --git a/tests/encode_unittests.c b/tests/encode_unittests.c deleted file mode 100644 index c3634ac..0000000 --- a/tests/encode_unittests.c +++ /dev/null @@ -1,287 +0,0 @@ -#define NANOPB_INTERNALS - -#include -#include -#include "pb_encode.h" -#include "unittests.h" -#include "unittestproto.pb.h" - -bool streamcallback(pb_ostream_t *stream, const uint8_t *buf, size_t count) -{ - /* Allow only 'x' to be written */ - while (count--) - { - if (*buf++ != 'x') - return false; - } - return true; -} - -bool fieldcallback(pb_ostream_t *stream, const pb_field_t *field, void * const *arg) -{ - int value = 0x55; - if (!pb_encode_tag_for_field(stream, field)) - return false; - return pb_encode_varint(stream, value); -} - -bool crazyfieldcallback(pb_ostream_t *stream, const pb_field_t *field, void * const *arg) -{ - /* This callback writes different amount of data the second time. */ - uint32_t *state = (uint32_t*)arg; - *state <<= 8; - if (!pb_encode_tag_for_field(stream, field)) - return false; - return pb_encode_varint(stream, *state); -} - -/* Check that expression x writes data y. - * Y is a string, which may contain null bytes. Null terminator is ignored. - */ -#define WRITES(x, y) \ -memset(buffer, 0xAA, sizeof(buffer)), \ -s = pb_ostream_from_buffer(buffer, sizeof(buffer)), \ -(x) && \ -memcmp(buffer, y, sizeof(y) - 1) == 0 && \ -buffer[sizeof(y) - 1] == 0xAA - -int main() -{ - int status = 0; - - { - uint8_t buffer1[] = "foobartest1234"; - uint8_t buffer2[sizeof(buffer1)]; - pb_ostream_t stream = pb_ostream_from_buffer(buffer2, sizeof(buffer1)); - - COMMENT("Test pb_write and pb_ostream_t"); - TEST(pb_write(&stream, buffer1, sizeof(buffer1))); - TEST(memcmp(buffer1, buffer2, sizeof(buffer1)) == 0); - TEST(!pb_write(&stream, buffer1, 1)); - TEST(stream.bytes_written == sizeof(buffer1)); - } - - { - uint8_t buffer1[] = "xxxxxxx"; - pb_ostream_t stream = {&streamcallback, 0, SIZE_MAX, 0}; - - COMMENT("Test pb_write with custom callback"); - TEST(pb_write(&stream, buffer1, 5)); - buffer1[0] = 'a'; - TEST(!pb_write(&stream, buffer1, 5)); - } - - { - uint8_t buffer[30]; - pb_ostream_t s; - - COMMENT("Test pb_encode_varint") - TEST(WRITES(pb_encode_varint(&s, 0), "\0")); - TEST(WRITES(pb_encode_varint(&s, 1), "\1")); - TEST(WRITES(pb_encode_varint(&s, 0x7F), "\x7F")); - TEST(WRITES(pb_encode_varint(&s, 0x80), "\x80\x01")); - TEST(WRITES(pb_encode_varint(&s, UINT32_MAX), "\xFF\xFF\xFF\xFF\x0F")); - TEST(WRITES(pb_encode_varint(&s, UINT64_MAX), "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x01")); - } - - { - uint8_t buffer[30]; - pb_ostream_t s; - - COMMENT("Test pb_encode_tag") - TEST(WRITES(pb_encode_tag(&s, PB_WT_STRING, 5), "\x2A")); - TEST(WRITES(pb_encode_tag(&s, PB_WT_VARINT, 99), "\x98\x06")); - } - - { - uint8_t buffer[30]; - pb_ostream_t s; - pb_field_t field = {10, PB_LTYPE_SVARINT}; - - COMMENT("Test pb_encode_tag_for_field") - TEST(WRITES(pb_encode_tag_for_field(&s, &field), "\x50")); - - field.type = PB_LTYPE_FIXED64; - TEST(WRITES(pb_encode_tag_for_field(&s, &field), "\x51")); - - field.type = PB_LTYPE_STRING; - TEST(WRITES(pb_encode_tag_for_field(&s, &field), "\x52")); - - field.type = PB_LTYPE_FIXED32; - TEST(WRITES(pb_encode_tag_for_field(&s, &field), "\x55")); - } - - { - uint8_t buffer[30]; - pb_ostream_t s; - - COMMENT("Test pb_encode_string") - TEST(WRITES(pb_encode_string(&s, (const uint8_t*)"abcd", 4), "\x04""abcd")); - TEST(WRITES(pb_encode_string(&s, (const uint8_t*)"abcd\x00", 5), "\x05""abcd\x00")); - TEST(WRITES(pb_encode_string(&s, (const uint8_t*)"", 0), "\x00")); - } - - { - uint8_t buffer[30]; - pb_ostream_t s; - uint8_t value = 1; - int32_t max = INT32_MAX; - int32_t min = INT32_MIN; - int64_t lmax = INT64_MAX; - int64_t lmin = INT64_MIN; - pb_field_t field = {1, PB_LTYPE_VARINT, 0, 0, sizeof(value)}; - - COMMENT("Test pb_enc_varint and pb_enc_svarint") - TEST(WRITES(pb_enc_varint(&s, &field, &value), "\x01")); - - field.data_size = sizeof(max); - TEST(WRITES(pb_enc_svarint(&s, &field, &max), "\xfe\xff\xff\xff\x0f")); - TEST(WRITES(pb_enc_svarint(&s, &field, &min), "\xff\xff\xff\xff\x0f")); - - field.data_size = sizeof(lmax); - TEST(WRITES(pb_enc_svarint(&s, &field, &lmax), "\xFE\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x01")); - TEST(WRITES(pb_enc_svarint(&s, &field, &lmin), "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x01")); - } - - { - uint8_t buffer[30]; - pb_ostream_t s; - float fvalue; - double dvalue; - - COMMENT("Test pb_enc_fixed32 using float") - fvalue = 0.0f; - TEST(WRITES(pb_enc_fixed32(&s, NULL, &fvalue), "\x00\x00\x00\x00")) - fvalue = 99.0f; - TEST(WRITES(pb_enc_fixed32(&s, NULL, &fvalue), "\x00\x00\xc6\x42")) - fvalue = -12345678.0f; - TEST(WRITES(pb_enc_fixed32(&s, NULL, &fvalue), "\x4e\x61\x3c\xcb")) - - COMMENT("Test pb_enc_fixed64 using double") - dvalue = 0.0; - TEST(WRITES(pb_enc_fixed64(&s, NULL, &dvalue), "\x00\x00\x00\x00\x00\x00\x00\x00")) - dvalue = 99.0; - TEST(WRITES(pb_enc_fixed64(&s, NULL, &dvalue), "\x00\x00\x00\x00\x00\xc0\x58\x40")) - dvalue = -12345678.0; - TEST(WRITES(pb_enc_fixed64(&s, NULL, &dvalue), "\x00\x00\x00\xc0\x29\x8c\x67\xc1")) - } - - { - uint8_t buffer[30]; - pb_ostream_t s; - struct { size_t size; uint8_t bytes[5]; } value = {5, {'x', 'y', 'z', 'z', 'y'}}; - - COMMENT("Test pb_enc_bytes") - TEST(WRITES(pb_enc_bytes(&s, NULL, &value), "\x05xyzzy")) - value.size = 0; - TEST(WRITES(pb_enc_bytes(&s, NULL, &value), "\x00")) - } - - { - uint8_t buffer[30]; - pb_ostream_t s; - char value[30] = "xyzzy"; - - COMMENT("Test pb_enc_string") - TEST(WRITES(pb_enc_string(&s, &StringMessage_fields[0], &value), "\x05xyzzy")) - value[0] = '\0'; - TEST(WRITES(pb_enc_string(&s, &StringMessage_fields[0], &value), "\x00")) - memset(value, 'x', 30); - TEST(WRITES(pb_enc_string(&s, &StringMessage_fields[0], &value), "\x0Axxxxxxxxxx")) - } - - { - uint8_t buffer[10]; - pb_ostream_t s; - IntegerArray msg = {5, {1, 2, 3, 4, 5}}; - - COMMENT("Test pb_encode with int32 array") - - TEST(WRITES(pb_encode(&s, IntegerArray_fields, &msg), "\x0A\x05\x01\x02\x03\x04\x05")) - - msg.data_count = 0; - TEST(WRITES(pb_encode(&s, IntegerArray_fields, &msg), "")) - - msg.data_count = 10; - TEST(!pb_encode(&s, IntegerArray_fields, &msg)) - } - - { - uint8_t buffer[10]; - pb_ostream_t s; - FloatArray msg = {1, {99.0f}}; - - COMMENT("Test pb_encode with float array") - - TEST(WRITES(pb_encode(&s, FloatArray_fields, &msg), - "\x0A\x04\x00\x00\xc6\x42")) - - msg.data_count = 0; - TEST(WRITES(pb_encode(&s, FloatArray_fields, &msg), "")) - - msg.data_count = 3; - TEST(!pb_encode(&s, FloatArray_fields, &msg)) - } - - { - uint8_t buffer[10]; - pb_ostream_t s; - CallbackArray msg; - - msg.data.funcs.encode = &fieldcallback; - - COMMENT("Test pb_encode with callback field.") - TEST(WRITES(pb_encode(&s, CallbackArray_fields, &msg), "\x08\x55")) - } - - { - uint8_t buffer[10]; - pb_ostream_t s; - IntegerContainer msg = {{5, {1,2,3,4,5}}}; - - COMMENT("Test pb_encode with packed array in a submessage.") - TEST(WRITES(pb_encode(&s, IntegerContainer_fields, &msg), - "\x0A\x07\x0A\x05\x01\x02\x03\x04\x05")) - } - - { - uint8_t buffer[20]; - pb_ostream_t s; - IntegerContainer msg = {{5, {1,2,3,4,5}}}; - - COMMENT("Test pb_encode_delimited.") - TEST(WRITES(pb_encode_delimited(&s, IntegerContainer_fields, &msg), - "\x09\x0A\x07\x0A\x05\x01\x02\x03\x04\x05")) - } - - { - uint8_t buffer[10]; - pb_ostream_t s; - CallbackContainer msg; - CallbackContainerContainer msg2; - uint32_t state = 1; - - msg.submsg.data.funcs.encode = &fieldcallback; - msg2.submsg.submsg.data.funcs.encode = &fieldcallback; - - COMMENT("Test pb_encode with callback field in a submessage.") - TEST(WRITES(pb_encode(&s, CallbackContainer_fields, &msg), "\x0A\x02\x08\x55")) - TEST(WRITES(pb_encode(&s, CallbackContainerContainer_fields, &msg2), - "\x0A\x04\x0A\x02\x08\x55")) - - /* Misbehaving callback: varying output between calls */ - msg.submsg.data.funcs.encode = &crazyfieldcallback; - msg.submsg.data.arg = &state; - msg2.submsg.submsg.data.funcs.encode = &crazyfieldcallback; - msg2.submsg.submsg.data.arg = &state; - - TEST(!pb_encode(&s, CallbackContainer_fields, &msg)) - state = 1; - TEST(!pb_encode(&s, CallbackContainerContainer_fields, &msg2)) - } - - if (status != 0) - fprintf(stdout, "\n\nSome tests FAILED!\n"); - - return status; -} diff --git a/tests/encode_unittests/SConscript b/tests/encode_unittests/SConscript new file mode 100644 index 0000000..0864a91 --- /dev/null +++ b/tests/encode_unittests/SConscript @@ -0,0 +1,5 @@ +# Build and run the stand-alone unit tests for the nanopb encoder part. + +Import('env') +env.Program(["encode_unittests.c", "#common/unittestproto.pb.c", "#common/pb_encode.o"]) +env.RunTest('encode_unittests') diff --git a/tests/encode_unittests/encode_unittests.c b/tests/encode_unittests/encode_unittests.c new file mode 100644 index 0000000..c3634ac --- /dev/null +++ b/tests/encode_unittests/encode_unittests.c @@ -0,0 +1,287 @@ +#define NANOPB_INTERNALS + +#include +#include +#include "pb_encode.h" +#include "unittests.h" +#include "unittestproto.pb.h" + +bool streamcallback(pb_ostream_t *stream, const uint8_t *buf, size_t count) +{ + /* Allow only 'x' to be written */ + while (count--) + { + if (*buf++ != 'x') + return false; + } + return true; +} + +bool fieldcallback(pb_ostream_t *stream, const pb_field_t *field, void * const *arg) +{ + int value = 0x55; + if (!pb_encode_tag_for_field(stream, field)) + return false; + return pb_encode_varint(stream, value); +} + +bool crazyfieldcallback(pb_ostream_t *stream, const pb_field_t *field, void * const *arg) +{ + /* This callback writes different amount of data the second time. */ + uint32_t *state = (uint32_t*)arg; + *state <<= 8; + if (!pb_encode_tag_for_field(stream, field)) + return false; + return pb_encode_varint(stream, *state); +} + +/* Check that expression x writes data y. + * Y is a string, which may contain null bytes. Null terminator is ignored. + */ +#define WRITES(x, y) \ +memset(buffer, 0xAA, sizeof(buffer)), \ +s = pb_ostream_from_buffer(buffer, sizeof(buffer)), \ +(x) && \ +memcmp(buffer, y, sizeof(y) - 1) == 0 && \ +buffer[sizeof(y) - 1] == 0xAA + +int main() +{ + int status = 0; + + { + uint8_t buffer1[] = "foobartest1234"; + uint8_t buffer2[sizeof(buffer1)]; + pb_ostream_t stream = pb_ostream_from_buffer(buffer2, sizeof(buffer1)); + + COMMENT("Test pb_write and pb_ostream_t"); + TEST(pb_write(&stream, buffer1, sizeof(buffer1))); + TEST(memcmp(buffer1, buffer2, sizeof(buffer1)) == 0); + TEST(!pb_write(&stream, buffer1, 1)); + TEST(stream.bytes_written == sizeof(buffer1)); + } + + { + uint8_t buffer1[] = "xxxxxxx"; + pb_ostream_t stream = {&streamcallback, 0, SIZE_MAX, 0}; + + COMMENT("Test pb_write with custom callback"); + TEST(pb_write(&stream, buffer1, 5)); + buffer1[0] = 'a'; + TEST(!pb_write(&stream, buffer1, 5)); + } + + { + uint8_t buffer[30]; + pb_ostream_t s; + + COMMENT("Test pb_encode_varint") + TEST(WRITES(pb_encode_varint(&s, 0), "\0")); + TEST(WRITES(pb_encode_varint(&s, 1), "\1")); + TEST(WRITES(pb_encode_varint(&s, 0x7F), "\x7F")); + TEST(WRITES(pb_encode_varint(&s, 0x80), "\x80\x01")); + TEST(WRITES(pb_encode_varint(&s, UINT32_MAX), "\xFF\xFF\xFF\xFF\x0F")); + TEST(WRITES(pb_encode_varint(&s, UINT64_MAX), "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x01")); + } + + { + uint8_t buffer[30]; + pb_ostream_t s; + + COMMENT("Test pb_encode_tag") + TEST(WRITES(pb_encode_tag(&s, PB_WT_STRING, 5), "\x2A")); + TEST(WRITES(pb_encode_tag(&s, PB_WT_VARINT, 99), "\x98\x06")); + } + + { + uint8_t buffer[30]; + pb_ostream_t s; + pb_field_t field = {10, PB_LTYPE_SVARINT}; + + COMMENT("Test pb_encode_tag_for_field") + TEST(WRITES(pb_encode_tag_for_field(&s, &field), "\x50")); + + field.type = PB_LTYPE_FIXED64; + TEST(WRITES(pb_encode_tag_for_field(&s, &field), "\x51")); + + field.type = PB_LTYPE_STRING; + TEST(WRITES(pb_encode_tag_for_field(&s, &field), "\x52")); + + field.type = PB_LTYPE_FIXED32; + TEST(WRITES(pb_encode_tag_for_field(&s, &field), "\x55")); + } + + { + uint8_t buffer[30]; + pb_ostream_t s; + + COMMENT("Test pb_encode_string") + TEST(WRITES(pb_encode_string(&s, (const uint8_t*)"abcd", 4), "\x04""abcd")); + TEST(WRITES(pb_encode_string(&s, (const uint8_t*)"abcd\x00", 5), "\x05""abcd\x00")); + TEST(WRITES(pb_encode_string(&s, (const uint8_t*)"", 0), "\x00")); + } + + { + uint8_t buffer[30]; + pb_ostream_t s; + uint8_t value = 1; + int32_t max = INT32_MAX; + int32_t min = INT32_MIN; + int64_t lmax = INT64_MAX; + int64_t lmin = INT64_MIN; + pb_field_t field = {1, PB_LTYPE_VARINT, 0, 0, sizeof(value)}; + + COMMENT("Test pb_enc_varint and pb_enc_svarint") + TEST(WRITES(pb_enc_varint(&s, &field, &value), "\x01")); + + field.data_size = sizeof(max); + TEST(WRITES(pb_enc_svarint(&s, &field, &max), "\xfe\xff\xff\xff\x0f")); + TEST(WRITES(pb_enc_svarint(&s, &field, &min), "\xff\xff\xff\xff\x0f")); + + field.data_size = sizeof(lmax); + TEST(WRITES(pb_enc_svarint(&s, &field, &lmax), "\xFE\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x01")); + TEST(WRITES(pb_enc_svarint(&s, &field, &lmin), "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x01")); + } + + { + uint8_t buffer[30]; + pb_ostream_t s; + float fvalue; + double dvalue; + + COMMENT("Test pb_enc_fixed32 using float") + fvalue = 0.0f; + TEST(WRITES(pb_enc_fixed32(&s, NULL, &fvalue), "\x00\x00\x00\x00")) + fvalue = 99.0f; + TEST(WRITES(pb_enc_fixed32(&s, NULL, &fvalue), "\x00\x00\xc6\x42")) + fvalue = -12345678.0f; + TEST(WRITES(pb_enc_fixed32(&s, NULL, &fvalue), "\x4e\x61\x3c\xcb")) + + COMMENT("Test pb_enc_fixed64 using double") + dvalue = 0.0; + TEST(WRITES(pb_enc_fixed64(&s, NULL, &dvalue), "\x00\x00\x00\x00\x00\x00\x00\x00")) + dvalue = 99.0; + TEST(WRITES(pb_enc_fixed64(&s, NULL, &dvalue), "\x00\x00\x00\x00\x00\xc0\x58\x40")) + dvalue = -12345678.0; + TEST(WRITES(pb_enc_fixed64(&s, NULL, &dvalue), "\x00\x00\x00\xc0\x29\x8c\x67\xc1")) + } + + { + uint8_t buffer[30]; + pb_ostream_t s; + struct { size_t size; uint8_t bytes[5]; } value = {5, {'x', 'y', 'z', 'z', 'y'}}; + + COMMENT("Test pb_enc_bytes") + TEST(WRITES(pb_enc_bytes(&s, NULL, &value), "\x05xyzzy")) + value.size = 0; + TEST(WRITES(pb_enc_bytes(&s, NULL, &value), "\x00")) + } + + { + uint8_t buffer[30]; + pb_ostream_t s; + char value[30] = "xyzzy"; + + COMMENT("Test pb_enc_string") + TEST(WRITES(pb_enc_string(&s, &StringMessage_fields[0], &value), "\x05xyzzy")) + value[0] = '\0'; + TEST(WRITES(pb_enc_string(&s, &StringMessage_fields[0], &value), "\x00")) + memset(value, 'x', 30); + TEST(WRITES(pb_enc_string(&s, &StringMessage_fields[0], &value), "\x0Axxxxxxxxxx")) + } + + { + uint8_t buffer[10]; + pb_ostream_t s; + IntegerArray msg = {5, {1, 2, 3, 4, 5}}; + + COMMENT("Test pb_encode with int32 array") + + TEST(WRITES(pb_encode(&s, IntegerArray_fields, &msg), "\x0A\x05\x01\x02\x03\x04\x05")) + + msg.data_count = 0; + TEST(WRITES(pb_encode(&s, IntegerArray_fields, &msg), "")) + + msg.data_count = 10; + TEST(!pb_encode(&s, IntegerArray_fields, &msg)) + } + + { + uint8_t buffer[10]; + pb_ostream_t s; + FloatArray msg = {1, {99.0f}}; + + COMMENT("Test pb_encode with float array") + + TEST(WRITES(pb_encode(&s, FloatArray_fields, &msg), + "\x0A\x04\x00\x00\xc6\x42")) + + msg.data_count = 0; + TEST(WRITES(pb_encode(&s, FloatArray_fields, &msg), "")) + + msg.data_count = 3; + TEST(!pb_encode(&s, FloatArray_fields, &msg)) + } + + { + uint8_t buffer[10]; + pb_ostream_t s; + CallbackArray msg; + + msg.data.funcs.encode = &fieldcallback; + + COMMENT("Test pb_encode with callback field.") + TEST(WRITES(pb_encode(&s, CallbackArray_fields, &msg), "\x08\x55")) + } + + { + uint8_t buffer[10]; + pb_ostream_t s; + IntegerContainer msg = {{5, {1,2,3,4,5}}}; + + COMMENT("Test pb_encode with packed array in a submessage.") + TEST(WRITES(pb_encode(&s, IntegerContainer_fields, &msg), + "\x0A\x07\x0A\x05\x01\x02\x03\x04\x05")) + } + + { + uint8_t buffer[20]; + pb_ostream_t s; + IntegerContainer msg = {{5, {1,2,3,4,5}}}; + + COMMENT("Test pb_encode_delimited.") + TEST(WRITES(pb_encode_delimited(&s, IntegerContainer_fields, &msg), + "\x09\x0A\x07\x0A\x05\x01\x02\x03\x04\x05")) + } + + { + uint8_t buffer[10]; + pb_ostream_t s; + CallbackContainer msg; + CallbackContainerContainer msg2; + uint32_t state = 1; + + msg.submsg.data.funcs.encode = &fieldcallback; + msg2.submsg.submsg.data.funcs.encode = &fieldcallback; + + COMMENT("Test pb_encode with callback field in a submessage.") + TEST(WRITES(pb_encode(&s, CallbackContainer_fields, &msg), "\x0A\x02\x08\x55")) + TEST(WRITES(pb_encode(&s, CallbackContainerContainer_fields, &msg2), + "\x0A\x04\x0A\x02\x08\x55")) + + /* Misbehaving callback: varying output between calls */ + msg.submsg.data.funcs.encode = &crazyfieldcallback; + msg.submsg.data.arg = &state; + msg2.submsg.submsg.data.funcs.encode = &crazyfieldcallback; + msg2.submsg.submsg.data.arg = &state; + + TEST(!pb_encode(&s, CallbackContainer_fields, &msg)) + state = 1; + TEST(!pb_encode(&s, CallbackContainerContainer_fields, &msg2)) + } + + if (status != 0) + fprintf(stdout, "\n\nSome tests FAILED!\n"); + + return status; +} diff --git a/tests/extensions.options b/tests/extensions.options deleted file mode 100644 index a5cd61d..0000000 --- a/tests/extensions.options +++ /dev/null @@ -1 +0,0 @@ -* max_size:16 diff --git a/tests/extensions.proto b/tests/extensions.proto deleted file mode 100644 index d85e819..0000000 --- a/tests/extensions.proto +++ /dev/null @@ -1,17 +0,0 @@ -import 'alltypes.proto'; - -extend AllTypes { - optional int32 AllTypes_extensionfield1 = 255; -} - -message ExtensionMessage { - extend AllTypes { - optional ExtensionMessage AllTypes_extensionfield2 = 254; - required ExtensionMessage AllTypes_extensionfield3 = 253; - repeated ExtensionMessage AllTypes_extensionfield4 = 252; - } - - required string test1 = 1; - required int32 test2 = 2; -} - diff --git a/tests/extensions/decode_extensions.c b/tests/extensions/decode_extensions.c new file mode 100644 index 0000000..ef6a022 --- /dev/null +++ b/tests/extensions/decode_extensions.c @@ -0,0 +1,43 @@ +/* Test decoding of extension fields. */ + +#include +#include +#include +#include +#include "alltypes.pb.h" +#include "extensions.pb.h" + +#define TEST(x) if (!(x)) { \ + printf("Test " #x " failed.\n"); \ + return 2; \ + } + +int main(int argc, char **argv) +{ + uint8_t buffer[1024]; + size_t count = fread(buffer, 1, sizeof(buffer), stdin); + pb_istream_t stream = pb_istream_from_buffer(buffer, count); + + AllTypes alltypes = {}; + + int32_t extensionfield1; + pb_extension_t ext1 = {&AllTypes_extensionfield1, &extensionfield1, NULL}; + alltypes.extensions = &ext1; + + ExtensionMessage extensionfield2 = {}; + pb_extension_t ext2 = {&ExtensionMessage_AllTypes_extensionfield2, &extensionfield2, NULL}; + ext1.next = &ext2; + + if (!pb_decode(&stream, AllTypes_fields, &alltypes)) + { + printf("Parsing failed: %s\n", PB_GET_ERROR(&stream)); + return 1; + } + + TEST(extensionfield1 == 12345) + TEST(strcmp(extensionfield2.test1, "test") == 0) + TEST(extensionfield2.test2 == 54321) + + return 0; +} + diff --git a/tests/extensions/encode_extensions.c b/tests/extensions/encode_extensions.c new file mode 100644 index 0000000..8857f14 --- /dev/null +++ b/tests/extensions/encode_extensions.c @@ -0,0 +1,38 @@ +/* Tests extension fields. + */ + +#include +#include +#include +#include +#include "alltypes.pb.h" +#include "extensions.pb.h" + +int main(int argc, char **argv) +{ + AllTypes alltypes = {}; + + int32_t extensionfield1 = 12345; + pb_extension_t ext1 = {&AllTypes_extensionfield1, &extensionfield1, NULL}; + alltypes.extensions = &ext1; + + ExtensionMessage extensionfield2 = {"test", 54321}; + pb_extension_t ext2 = {&ExtensionMessage_AllTypes_extensionfield2, &extensionfield2, NULL}; + ext1.next = &ext2; + + uint8_t buffer[1024]; + pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer)); + + /* Now encode it and check if we succeeded. */ + if (pb_encode(&stream, AllTypes_fields, &alltypes)) + { + fwrite(buffer, 1, stream.bytes_written, stdout); + return 0; /* Success */ + } + else + { + fprintf(stderr, "Encoding failed: %s\n", PB_GET_ERROR(&stream)); + return 1; /* Failure */ + } +} + diff --git a/tests/extensions/extensions.options b/tests/extensions/extensions.options new file mode 100644 index 0000000..a5cd61d --- /dev/null +++ b/tests/extensions/extensions.options @@ -0,0 +1 @@ +* max_size:16 diff --git a/tests/extensions/extensions.proto b/tests/extensions/extensions.proto new file mode 100644 index 0000000..d85e819 --- /dev/null +++ b/tests/extensions/extensions.proto @@ -0,0 +1,17 @@ +import 'alltypes.proto'; + +extend AllTypes { + optional int32 AllTypes_extensionfield1 = 255; +} + +message ExtensionMessage { + extend AllTypes { + optional ExtensionMessage AllTypes_extensionfield2 = 254; + required ExtensionMessage AllTypes_extensionfield3 = 253; + repeated ExtensionMessage AllTypes_extensionfield4 = 252; + } + + required string test1 = 1; + required int32 test2 = 2; +} + diff --git a/tests/extra_fields/alltypes_with_extra_fields.pb b/tests/extra_fields/alltypes_with_extra_fields.pb new file mode 100644 index 0000000..f9f5394 Binary files /dev/null and b/tests/extra_fields/alltypes_with_extra_fields.pb differ diff --git a/tests/extra_fields/person_with_extra_field.pb b/tests/extra_fields/person_with_extra_field.pb new file mode 100644 index 0000000..ced3057 Binary files /dev/null and b/tests/extra_fields/person_with_extra_field.pb differ diff --git a/tests/funny-proto+name.proto b/tests/funny-proto+name.proto deleted file mode 100644 index e69de29..0000000 diff --git a/tests/missing_fields.proto b/tests/missing_fields.proto deleted file mode 100644 index cbb23ba..0000000 --- a/tests/missing_fields.proto +++ /dev/null @@ -1,138 +0,0 @@ -/* Test for one missing field among many */ - -message AllFields -{ - required int32 field1 = 1; - required int32 field2 = 2; - required int32 field3 = 3; - required int32 field4 = 4; - required int32 field5 = 5; - required int32 field6 = 6; - required int32 field7 = 7; - required int32 field8 = 8; - required int32 field9 = 9; - required int32 field10 = 10; - required int32 field11 = 11; - required int32 field12 = 12; - required int32 field13 = 13; - required int32 field14 = 14; - required int32 field15 = 15; - required int32 field16 = 16; - required int32 field17 = 17; - required int32 field18 = 18; - required int32 field19 = 19; - required int32 field20 = 20; - required int32 field21 = 21; - required int32 field22 = 22; - required int32 field23 = 23; - required int32 field24 = 24; - required int32 field25 = 25; - required int32 field26 = 26; - required int32 field27 = 27; - required int32 field28 = 28; - required int32 field29 = 29; - required int32 field30 = 30; - required int32 field31 = 31; - required int32 field32 = 32; - required int32 field33 = 33; - required int32 field34 = 34; - required int32 field35 = 35; - required int32 field36 = 36; - required int32 field37 = 37; - required int32 field38 = 38; - required int32 field39 = 39; - required int32 field40 = 40; - required int32 field41 = 41; - required int32 field42 = 42; - required int32 field43 = 43; - required int32 field44 = 44; - required int32 field45 = 45; - required int32 field46 = 46; - required int32 field47 = 47; - required int32 field48 = 48; - required int32 field49 = 49; - required int32 field50 = 50; - required int32 field51 = 51; - required int32 field52 = 52; - required int32 field53 = 53; - required int32 field54 = 54; - required int32 field55 = 55; - required int32 field56 = 56; - required int32 field57 = 57; - required int32 field58 = 58; - required int32 field59 = 59; - required int32 field60 = 60; - required int32 field61 = 61; - required int32 field62 = 62; - required int32 field63 = 63; - required int32 field64 = 64; -} - -message MissingField -{ - required int32 field1 = 1; - required int32 field2 = 2; - required int32 field3 = 3; - required int32 field4 = 4; - required int32 field5 = 5; - required int32 field6 = 6; - required int32 field7 = 7; - required int32 field8 = 8; - required int32 field9 = 9; - required int32 field10 = 10; - required int32 field11 = 11; - required int32 field12 = 12; - required int32 field13 = 13; - required int32 field14 = 14; - required int32 field15 = 15; - required int32 field16 = 16; - required int32 field17 = 17; - required int32 field18 = 18; - required int32 field19 = 19; - required int32 field20 = 20; - required int32 field21 = 21; - required int32 field22 = 22; - required int32 field23 = 23; - required int32 field24 = 24; - required int32 field25 = 25; - required int32 field26 = 26; - required int32 field27 = 27; - required int32 field28 = 28; - required int32 field29 = 29; - required int32 field30 = 30; - required int32 field31 = 31; - required int32 field32 = 32; - required int32 field33 = 33; - required int32 field34 = 34; - required int32 field35 = 35; - required int32 field36 = 36; - required int32 field37 = 37; - required int32 field38 = 38; - required int32 field39 = 39; - required int32 field40 = 40; - required int32 field41 = 41; - required int32 field42 = 42; - required int32 field43 = 43; - required int32 field44 = 44; - required int32 field45 = 45; - required int32 field46 = 46; - required int32 field47 = 47; - required int32 field48 = 48; - required int32 field49 = 49; - required int32 field50 = 50; - required int32 field51 = 51; - required int32 field52 = 52; - required int32 field53 = 53; - required int32 field54 = 54; - required int32 field55 = 55; - required int32 field56 = 56; - required int32 field57 = 57; - required int32 field58 = 58; - required int32 field59 = 59; - required int32 field60 = 60; - required int32 field61 = 61; - required int32 field62 = 62; -/* required int32 field63 = 63; */ - required int32 field64 = 64; -} - diff --git a/tests/missing_fields/missing_fields.c b/tests/missing_fields/missing_fields.c new file mode 100644 index 0000000..2774184 --- /dev/null +++ b/tests/missing_fields/missing_fields.c @@ -0,0 +1,49 @@ +/* Checks that missing required fields are detected properly */ + +#include +#include +#include +#include "missing_fields.pb.h" + +int main() +{ + uint8_t buffer[512] = {}; + + /* Create a message with one missing field */ + { + MissingField msg = {}; + pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer)); + if (!pb_encode(&stream, MissingField_fields, &msg)) + { + printf("Encode failed.\n"); + return 1; + } + } + + /* Test that it decodes properly if we don't require that field */ + { + MissingField msg = {}; + pb_istream_t stream = pb_istream_from_buffer(buffer, sizeof(buffer)); + + if (!pb_decode(&stream, MissingField_fields, &msg)) + { + printf("Decode failed: %s\n", PB_GET_ERROR(&stream)); + return 2; + } + } + + /* Test that it does *not* decode properly if we require the field */ + { + AllFields msg = {}; + pb_istream_t stream = pb_istream_from_buffer(buffer, sizeof(buffer)); + + if (pb_decode(&stream, AllFields_fields, &msg)) + { + printf("Decode didn't detect missing field.\n"); + return 3; + } + } + + return 0; /* All ok */ +} + diff --git a/tests/missing_fields/missing_fields.proto b/tests/missing_fields/missing_fields.proto new file mode 100644 index 0000000..cbb23ba --- /dev/null +++ b/tests/missing_fields/missing_fields.proto @@ -0,0 +1,138 @@ +/* Test for one missing field among many */ + +message AllFields +{ + required int32 field1 = 1; + required int32 field2 = 2; + required int32 field3 = 3; + required int32 field4 = 4; + required int32 field5 = 5; + required int32 field6 = 6; + required int32 field7 = 7; + required int32 field8 = 8; + required int32 field9 = 9; + required int32 field10 = 10; + required int32 field11 = 11; + required int32 field12 = 12; + required int32 field13 = 13; + required int32 field14 = 14; + required int32 field15 = 15; + required int32 field16 = 16; + required int32 field17 = 17; + required int32 field18 = 18; + required int32 field19 = 19; + required int32 field20 = 20; + required int32 field21 = 21; + required int32 field22 = 22; + required int32 field23 = 23; + required int32 field24 = 24; + required int32 field25 = 25; + required int32 field26 = 26; + required int32 field27 = 27; + required int32 field28 = 28; + required int32 field29 = 29; + required int32 field30 = 30; + required int32 field31 = 31; + required int32 field32 = 32; + required int32 field33 = 33; + required int32 field34 = 34; + required int32 field35 = 35; + required int32 field36 = 36; + required int32 field37 = 37; + required int32 field38 = 38; + required int32 field39 = 39; + required int32 field40 = 40; + required int32 field41 = 41; + required int32 field42 = 42; + required int32 field43 = 43; + required int32 field44 = 44; + required int32 field45 = 45; + required int32 field46 = 46; + required int32 field47 = 47; + required int32 field48 = 48; + required int32 field49 = 49; + required int32 field50 = 50; + required int32 field51 = 51; + required int32 field52 = 52; + required int32 field53 = 53; + required int32 field54 = 54; + required int32 field55 = 55; + required int32 field56 = 56; + required int32 field57 = 57; + required int32 field58 = 58; + required int32 field59 = 59; + required int32 field60 = 60; + required int32 field61 = 61; + required int32 field62 = 62; + required int32 field63 = 63; + required int32 field64 = 64; +} + +message MissingField +{ + required int32 field1 = 1; + required int32 field2 = 2; + required int32 field3 = 3; + required int32 field4 = 4; + required int32 field5 = 5; + required int32 field6 = 6; + required int32 field7 = 7; + required int32 field8 = 8; + required int32 field9 = 9; + required int32 field10 = 10; + required int32 field11 = 11; + required int32 field12 = 12; + required int32 field13 = 13; + required int32 field14 = 14; + required int32 field15 = 15; + required int32 field16 = 16; + required int32 field17 = 17; + required int32 field18 = 18; + required int32 field19 = 19; + required int32 field20 = 20; + required int32 field21 = 21; + required int32 field22 = 22; + required int32 field23 = 23; + required int32 field24 = 24; + required int32 field25 = 25; + required int32 field26 = 26; + required int32 field27 = 27; + required int32 field28 = 28; + required int32 field29 = 29; + required int32 field30 = 30; + required int32 field31 = 31; + required int32 field32 = 32; + required int32 field33 = 33; + required int32 field34 = 34; + required int32 field35 = 35; + required int32 field36 = 36; + required int32 field37 = 37; + required int32 field38 = 38; + required int32 field39 = 39; + required int32 field40 = 40; + required int32 field41 = 41; + required int32 field42 = 42; + required int32 field43 = 43; + required int32 field44 = 44; + required int32 field45 = 45; + required int32 field46 = 46; + required int32 field47 = 47; + required int32 field48 = 48; + required int32 field49 = 49; + required int32 field50 = 50; + required int32 field51 = 51; + required int32 field52 = 52; + required int32 field53 = 53; + required int32 field54 = 54; + required int32 field55 = 55; + required int32 field56 = 56; + required int32 field57 = 57; + required int32 field58 = 58; + required int32 field59 = 59; + required int32 field60 = 60; + required int32 field61 = 61; + required int32 field62 = 62; +/* required int32 field63 = 63; */ + required int32 field64 = 64; +} + diff --git a/tests/multiple_files/callbacks.proto b/tests/multiple_files/callbacks.proto new file mode 100644 index 0000000..ccd1edd --- /dev/null +++ b/tests/multiple_files/callbacks.proto @@ -0,0 +1,16 @@ +message SubMessage { + optional string stringvalue = 1; + repeated int32 int32value = 2; + repeated fixed32 fixed32value = 3; + repeated fixed64 fixed64value = 4; +} + +message TestMessage { + optional string stringvalue = 1; + repeated int32 int32value = 2; + repeated fixed32 fixed32value = 3; + repeated fixed64 fixed64value = 4; + optional SubMessage submsg = 5; + repeated string repeatedstring = 6; +} + diff --git a/tests/multiple_files/callbacks2.proto b/tests/multiple_files/callbacks2.proto new file mode 100644 index 0000000..9a55e15 --- /dev/null +++ b/tests/multiple_files/callbacks2.proto @@ -0,0 +1,9 @@ +// Test if including generated header file for this file + implicit include of +// callbacks.pb.h still compiles. Used with test_compiles.c. +import "callbacks.proto"; + +message Callback2Message { + required TestMessage tstmsg = 1; + required SubMessage submsg = 2; +} + diff --git a/tests/multiple_files/test_multiple_files.c b/tests/multiple_files/test_multiple_files.c new file mode 100644 index 0000000..cb4e16d --- /dev/null +++ b/tests/multiple_files/test_multiple_files.c @@ -0,0 +1,13 @@ +/* + * Tests if still compile if typedefs are redfefined in STATIC_ASSERTS when + * proto file includes another poto file + */ + +#include +#include +#include "callbacks2.pb.h" + +int main() +{ + return 0; +} diff --git a/tests/no_messages.proto b/tests/no_messages.proto deleted file mode 100644 index 279216b..0000000 --- a/tests/no_messages.proto +++ /dev/null @@ -1,7 +0,0 @@ -/* Test that a file without any messages works. */ - -enum Test { - First = 1; -} - - diff --git a/tests/no_messages/no_messages.proto b/tests/no_messages/no_messages.proto new file mode 100644 index 0000000..279216b --- /dev/null +++ b/tests/no_messages/no_messages.proto @@ -0,0 +1,7 @@ +/* Test that a file without any messages works. */ + +enum Test { + First = 1; +} + + diff --git a/tests/options.expected b/tests/options.expected deleted file mode 100644 index e6179a2..0000000 --- a/tests/options.expected +++ /dev/null @@ -1,7 +0,0 @@ -char filesize\[20\]; -char msgsize\[30\]; -char fieldsize\[40\]; -pb_callback_t int32_callback; -\sEnumValue1 = 1 -Message5_EnumValue1 -} pb_packed my_packed_struct; diff --git a/tests/options.proto b/tests/options.proto deleted file mode 100644 index b5badcf..0000000 --- a/tests/options.proto +++ /dev/null @@ -1,73 +0,0 @@ -/* Test nanopb option parsing. - * options.expected lists the patterns that are searched for in the output. - */ - -import "nanopb.proto"; - -// File level options -option (nanopb_fileopt).max_size = 20; - -message Message1 -{ - required string filesize = 1; -} - -// Message level options -message Message2 -{ - option (nanopb_msgopt).max_size = 30; - required string msgsize = 1; -} - -// Field level options -message Message3 -{ - required string fieldsize = 1 [(nanopb).max_size = 40]; -} - -// Forced callback field -message Message4 -{ - required int32 int32_callback = 1 [(nanopb).type = FT_CALLBACK]; -} - -// Short enum names -enum Enum1 -{ - option (nanopb_enumopt).long_names = false; - EnumValue1 = 1; - EnumValue2 = 2; -} - -message EnumTest -{ - required Enum1 field = 1 [default = EnumValue2]; -} - -// Short enum names inside message -message Message5 -{ - enum Enum2 - { - option (nanopb_enumopt).long_names = false; - EnumValue1 = 1; - } - required Enum2 field = 1 [default = EnumValue1]; -} - -// Packed structure -message my_packed_struct -{ - option (nanopb_msgopt).packed_struct = true; - optional int32 myfield = 1; -} - -// Message with ignored field -// Note: doesn't really test if the field is missing in the output, -// but atleast tests that the output compiles. -message Message6 -{ - required int32 field1 = 1; - optional int32 field2 = 2 [(nanopb).type = FT_IGNORE]; -} - diff --git a/tests/options/options.expected b/tests/options/options.expected new file mode 100644 index 0000000..e6179a2 --- /dev/null +++ b/tests/options/options.expected @@ -0,0 +1,7 @@ +char filesize\[20\]; +char msgsize\[30\]; +char fieldsize\[40\]; +pb_callback_t int32_callback; +\sEnumValue1 = 1 +Message5_EnumValue1 +} pb_packed my_packed_struct; diff --git a/tests/options/options.proto b/tests/options/options.proto new file mode 100644 index 0000000..b5badcf --- /dev/null +++ b/tests/options/options.proto @@ -0,0 +1,73 @@ +/* Test nanopb option parsing. + * options.expected lists the patterns that are searched for in the output. + */ + +import "nanopb.proto"; + +// File level options +option (nanopb_fileopt).max_size = 20; + +message Message1 +{ + required string filesize = 1; +} + +// Message level options +message Message2 +{ + option (nanopb_msgopt).max_size = 30; + required string msgsize = 1; +} + +// Field level options +message Message3 +{ + required string fieldsize = 1 [(nanopb).max_size = 40]; +} + +// Forced callback field +message Message4 +{ + required int32 int32_callback = 1 [(nanopb).type = FT_CALLBACK]; +} + +// Short enum names +enum Enum1 +{ + option (nanopb_enumopt).long_names = false; + EnumValue1 = 1; + EnumValue2 = 2; +} + +message EnumTest +{ + required Enum1 field = 1 [default = EnumValue2]; +} + +// Short enum names inside message +message Message5 +{ + enum Enum2 + { + option (nanopb_enumopt).long_names = false; + EnumValue1 = 1; + } + required Enum2 field = 1 [default = EnumValue1]; +} + +// Packed structure +message my_packed_struct +{ + option (nanopb_msgopt).packed_struct = true; + optional int32 myfield = 1; +} + +// Message with ignored field +// Note: doesn't really test if the field is missing in the output, +// but atleast tests that the output compiles. +message Message6 +{ + required int32 field1 = 1; + optional int32 field2 = 2 [(nanopb).type = FT_IGNORE]; +} + diff --git a/tests/person.proto b/tests/person.proto deleted file mode 100644 index dafcf93..0000000 --- a/tests/person.proto +++ /dev/null @@ -1,20 +0,0 @@ -import "nanopb.proto"; - -message Person { - required string name = 1 [(nanopb).max_size = 40]; - required int32 id = 2; - optional string email = 3 [(nanopb).max_size = 40]; - - enum PhoneType { - MOBILE = 0; - HOME = 1; - WORK = 2; - } - - message PhoneNumber { - required string number = 1 [(nanopb).max_size = 40]; - optional PhoneType type = 2 [default = HOME]; - } - - repeated PhoneNumber phone = 4 [(nanopb).max_count = 5]; -} diff --git a/tests/person_with_extra_field.pb b/tests/person_with_extra_field.pb deleted file mode 100644 index ced3057..0000000 Binary files a/tests/person_with_extra_field.pb and /dev/null differ diff --git a/tests/special_characters/funny-proto+name.proto b/tests/special_characters/funny-proto+name.proto new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_decode1.c b/tests/test_decode1.c deleted file mode 100644 index 56bbd8f..0000000 --- a/tests/test_decode1.c +++ /dev/null @@ -1,83 +0,0 @@ -/* A very simple decoding test case, using person.proto. - * Produces output compatible with protoc --decode. - * Reads the encoded data from stdin and prints the values - * to stdout as text. - * - * Run e.g. ./test_encode1 | ./test_decode1 - */ - -#include -#include -#include "person.pb.h" - -/* This function is called once from main(), it handles - the decoding and printing. */ -bool print_person(pb_istream_t *stream) -{ - int i; - Person person; - - if (!pb_decode(stream, Person_fields, &person)) - return false; - - /* Now the decoding is done, rest is just to print stuff out. */ - - printf("name: \"%s\"\n", person.name); - printf("id: %ld\n", (long)person.id); - - if (person.has_email) - printf("email: \"%s\"\n", person.email); - - for (i = 0; i < person.phone_count; i++) - { - Person_PhoneNumber *phone = &person.phone[i]; - printf("phone {\n"); - printf(" number: \"%s\"\n", phone->number); - - if (phone->has_type) - { - switch (phone->type) - { - case Person_PhoneType_WORK: - printf(" type: WORK\n"); - break; - - case Person_PhoneType_HOME: - printf(" type: HOME\n"); - break; - - case Person_PhoneType_MOBILE: - printf(" type: MOBILE\n"); - break; - } - } - printf("}\n"); - } - - return true; -} - -int main() -{ - /* Read the data into buffer */ - uint8_t buffer[512]; - size_t count = fread(buffer, 1, sizeof(buffer), stdin); - - if (!feof(stdin)) - { - printf("Message does not fit in buffer\n"); - return 1; - } - - /* Construct a pb_istream_t for reading from the buffer */ - pb_istream_t stream = pb_istream_from_buffer(buffer, count); - - /* Decode and print out the stuff */ - if (!print_person(&stream)) - { - printf("Parsing failed: %s\n", PB_GET_ERROR(&stream)); - return 1; - } else { - return 0; - } -} diff --git a/tests/test_decode2.c b/tests/test_decode2.c deleted file mode 100644 index 2142977..0000000 --- a/tests/test_decode2.c +++ /dev/null @@ -1,83 +0,0 @@ -/* Same as test_decode1 but reads from stdin directly. - */ - -#include -#include -#include "person.pb.h" - -/* This function is called once from main(), it handles - the decoding and printing. - Ugly copy-paste from test_decode1.c. */ -bool print_person(pb_istream_t *stream) -{ - int i; - Person person; - - if (!pb_decode(stream, Person_fields, &person)) - return false; - - /* Now the decoding is done, rest is just to print stuff out. */ - - printf("name: \"%s\"\n", person.name); - printf("id: %ld\n", (long)person.id); - - if (person.has_email) - printf("email: \"%s\"\n", person.email); - - for (i = 0; i < person.phone_count; i++) - { - Person_PhoneNumber *phone = &person.phone[i]; - printf("phone {\n"); - printf(" number: \"%s\"\n", phone->number); - - if (phone->has_type) - { - switch (phone->type) - { - case Person_PhoneType_WORK: - printf(" type: WORK\n"); - break; - - case Person_PhoneType_HOME: - printf(" type: HOME\n"); - break; - - case Person_PhoneType_MOBILE: - printf(" type: MOBILE\n"); - break; - } - } - printf("}\n"); - } - - return true; -} - -/* This binds the pb_istream_t to stdin */ -bool callback(pb_istream_t *stream, uint8_t *buf, size_t count) -{ - FILE *file = (FILE*)stream->state; - bool status; - - status = (fread(buf, 1, count, file) == count); - - if (feof(file)) - stream->bytes_left = 0; - - return status; -} - -int main() -{ - /* Maximum size is specified to prevent infinite length messages from - * hanging this in the fuzz test. - */ - pb_istream_t stream = {&callback, stdin, 10000}; - if (!print_person(&stream)) - { - printf("Parsing failed: %s\n", PB_GET_ERROR(&stream)); - return 1; - } else { - return 0; - } -} diff --git a/tests/test_decode3.c b/tests/test_decode3.c deleted file mode 100644 index 55d025c..0000000 --- a/tests/test_decode3.c +++ /dev/null @@ -1,197 +0,0 @@ -/* Tests the decoding of all types. - * This is the counterpart of test_encode3. - * Run e.g. ./test_encode3 | ./test_decode3 - */ - -#include -#include -#include -#include -#include "alltypes.pb.h" - -#define TEST(x) if (!(x)) { \ - printf("Test " #x " failed.\n"); \ - return false; \ - } - -/* This function is called once from main(), it handles - the decoding and checks the fields. */ -bool check_alltypes(pb_istream_t *stream, int mode) -{ - AllTypes alltypes; - - /* Fill with garbage to better detect initialization errors */ - memset(&alltypes, 0xAA, sizeof(alltypes)); - - if (!pb_decode(stream, AllTypes_fields, &alltypes)) - return false; - - TEST(alltypes.req_int32 == -1001); - TEST(alltypes.req_int64 == -1002); - TEST(alltypes.req_uint32 == 1003); - TEST(alltypes.req_uint64 == 1004); - TEST(alltypes.req_sint32 == -1005); - TEST(alltypes.req_sint64 == -1006); - TEST(alltypes.req_bool == true); - - TEST(alltypes.req_fixed32 == 1008); - TEST(alltypes.req_sfixed32 == -1009); - TEST(alltypes.req_float == 1010.0f); - - TEST(alltypes.req_fixed64 == 1011); - TEST(alltypes.req_sfixed64 == -1012); - TEST(alltypes.req_double == 1013.0f); - - TEST(strcmp(alltypes.req_string, "1014") == 0); - TEST(alltypes.req_bytes.size == 4); - TEST(memcmp(alltypes.req_bytes.bytes, "1015", 4) == 0); - TEST(strcmp(alltypes.req_submsg.substuff1, "1016") == 0); - TEST(alltypes.req_submsg.substuff2 == 1016); - TEST(alltypes.req_submsg.substuff3 == 3); - TEST(alltypes.req_enum == MyEnum_Truth); - - TEST(alltypes.rep_int32_count == 5 && alltypes.rep_int32[4] == -2001 && alltypes.rep_int32[0] == 0); - TEST(alltypes.rep_int64_count == 5 && alltypes.rep_int64[4] == -2002 && alltypes.rep_int64[0] == 0); - TEST(alltypes.rep_uint32_count == 5 && alltypes.rep_uint32[4] == 2003 && alltypes.rep_uint32[0] == 0); - TEST(alltypes.rep_uint64_count == 5 && alltypes.rep_uint64[4] == 2004 && alltypes.rep_uint64[0] == 0); - TEST(alltypes.rep_sint32_count == 5 && alltypes.rep_sint32[4] == -2005 && alltypes.rep_sint32[0] == 0); - TEST(alltypes.rep_sint64_count == 5 && alltypes.rep_sint64[4] == -2006 && alltypes.rep_sint64[0] == 0); - TEST(alltypes.rep_bool_count == 5 && alltypes.rep_bool[4] == true && alltypes.rep_bool[0] == false); - - TEST(alltypes.rep_fixed32_count == 5 && alltypes.rep_fixed32[4] == 2008 && alltypes.rep_fixed32[0] == 0); - TEST(alltypes.rep_sfixed32_count == 5 && alltypes.rep_sfixed32[4] == -2009 && alltypes.rep_sfixed32[0] == 0); - TEST(alltypes.rep_float_count == 5 && alltypes.rep_float[4] == 2010.0f && alltypes.rep_float[0] == 0.0f); - - TEST(alltypes.rep_fixed64_count == 5 && alltypes.rep_fixed64[4] == 2011 && alltypes.rep_fixed64[0] == 0); - TEST(alltypes.rep_sfixed64_count == 5 && alltypes.rep_sfixed64[4] == -2012 && alltypes.rep_sfixed64[0] == 0); - TEST(alltypes.rep_double_count == 5 && alltypes.rep_double[4] == 2013.0 && alltypes.rep_double[0] == 0.0); - - TEST(alltypes.rep_string_count == 5 && strcmp(alltypes.rep_string[4], "2014") == 0 && alltypes.rep_string[0][0] == '\0'); - TEST(alltypes.rep_bytes_count == 5 && alltypes.rep_bytes[4].size == 4 && alltypes.rep_bytes[0].size == 0); - TEST(memcmp(alltypes.rep_bytes[4].bytes, "2015", 4) == 0); - - TEST(alltypes.rep_submsg_count == 5); - TEST(strcmp(alltypes.rep_submsg[4].substuff1, "2016") == 0 && alltypes.rep_submsg[0].substuff1[0] == '\0'); - TEST(alltypes.rep_submsg[4].substuff2 == 2016 && alltypes.rep_submsg[0].substuff2 == 0); - TEST(alltypes.rep_submsg[4].substuff3 == 2016 && alltypes.rep_submsg[0].substuff3 == 3); - - TEST(alltypes.rep_enum_count == 5 && alltypes.rep_enum[4] == MyEnum_Truth && alltypes.rep_enum[0] == MyEnum_Zero); - TEST(alltypes.rep_emptymsg_count == 5); - - if (mode == 0) - { - /* Expect default values */ - TEST(alltypes.has_opt_int32 == false); - TEST(alltypes.opt_int32 == 4041); - TEST(alltypes.has_opt_int64 == false); - TEST(alltypes.opt_int64 == 4042); - TEST(alltypes.has_opt_uint32 == false); - TEST(alltypes.opt_uint32 == 4043); - TEST(alltypes.has_opt_uint64 == false); - TEST(alltypes.opt_uint64 == 4044); - TEST(alltypes.has_opt_sint32 == false); - TEST(alltypes.opt_sint32 == 4045); - TEST(alltypes.has_opt_sint64 == false); - TEST(alltypes.opt_sint64 == 4046); - TEST(alltypes.has_opt_bool == false); - TEST(alltypes.opt_bool == false); - - TEST(alltypes.has_opt_fixed32 == false); - TEST(alltypes.opt_fixed32 == 4048); - TEST(alltypes.has_opt_sfixed32 == false); - TEST(alltypes.opt_sfixed32 == 4049); - TEST(alltypes.has_opt_float == false); - TEST(alltypes.opt_float == 4050.0f); - - TEST(alltypes.has_opt_fixed64 == false); - TEST(alltypes.opt_fixed64 == 4051); - TEST(alltypes.has_opt_sfixed64 == false); - TEST(alltypes.opt_sfixed64 == 4052); - TEST(alltypes.has_opt_double == false); - TEST(alltypes.opt_double == 4053.0); - - TEST(alltypes.has_opt_string == false); - TEST(strcmp(alltypes.opt_string, "4054") == 0); - TEST(alltypes.has_opt_bytes == false); - TEST(alltypes.opt_bytes.size == 4); - TEST(memcmp(alltypes.opt_bytes.bytes, "4055", 4) == 0); - TEST(alltypes.has_opt_submsg == false); - TEST(strcmp(alltypes.opt_submsg.substuff1, "1") == 0); - TEST(alltypes.opt_submsg.substuff2 == 2); - TEST(alltypes.opt_submsg.substuff3 == 3); - TEST(alltypes.has_opt_enum == false); - TEST(alltypes.opt_enum == MyEnum_Second); - TEST(alltypes.has_opt_emptymsg == false); - } - else - { - /* Expect filled-in values */ - TEST(alltypes.has_opt_int32 == true); - TEST(alltypes.opt_int32 == 3041); - TEST(alltypes.has_opt_int64 == true); - TEST(alltypes.opt_int64 == 3042); - TEST(alltypes.has_opt_uint32 == true); - TEST(alltypes.opt_uint32 == 3043); - TEST(alltypes.has_opt_uint64 == true); - TEST(alltypes.opt_uint64 == 3044); - TEST(alltypes.has_opt_sint32 == true); - TEST(alltypes.opt_sint32 == 3045); - TEST(alltypes.has_opt_sint64 == true); - TEST(alltypes.opt_sint64 == 3046); - TEST(alltypes.has_opt_bool == true); - TEST(alltypes.opt_bool == true); - - TEST(alltypes.has_opt_fixed32 == true); - TEST(alltypes.opt_fixed32 == 3048); - TEST(alltypes.has_opt_sfixed32 == true); - TEST(alltypes.opt_sfixed32 == 3049); - TEST(alltypes.has_opt_float == true); - TEST(alltypes.opt_float == 3050.0f); - - TEST(alltypes.has_opt_fixed64 == true); - TEST(alltypes.opt_fixed64 == 3051); - TEST(alltypes.has_opt_sfixed64 == true); - TEST(alltypes.opt_sfixed64 == 3052); - TEST(alltypes.has_opt_double == true); - TEST(alltypes.opt_double == 3053.0); - - TEST(alltypes.has_opt_string == true); - TEST(strcmp(alltypes.opt_string, "3054") == 0); - TEST(alltypes.has_opt_bytes == true); - TEST(alltypes.opt_bytes.size == 4); - TEST(memcmp(alltypes.opt_bytes.bytes, "3055", 4) == 0); - TEST(alltypes.has_opt_submsg == true); - TEST(strcmp(alltypes.opt_submsg.substuff1, "3056") == 0); - TEST(alltypes.opt_submsg.substuff2 == 3056); - TEST(alltypes.opt_submsg.substuff3 == 3); - TEST(alltypes.has_opt_enum == true); - TEST(alltypes.opt_enum == MyEnum_Truth); - TEST(alltypes.has_opt_emptymsg == true); - } - - TEST(alltypes.end == 1099); - - return true; -} - -int main(int argc, char **argv) -{ - /* Whether to expect the optional values or the default values. */ - int mode = (argc > 1) ? atoi(argv[1]) : 0; - - /* Read the data into buffer */ - uint8_t buffer[1024]; - size_t count = fread(buffer, 1, sizeof(buffer), stdin); - - /* Construct a pb_istream_t for reading from the buffer */ - pb_istream_t stream = pb_istream_from_buffer(buffer, count); - - /* Decode and print out the stuff */ - if (!check_alltypes(&stream, mode)) - { - printf("Parsing failed: %s\n", PB_GET_ERROR(&stream)); - return 1; - } else { - return 0; - } -} diff --git a/tests/test_decode_callbacks.c b/tests/test_decode_callbacks.c deleted file mode 100644 index b505692..0000000 --- a/tests/test_decode_callbacks.c +++ /dev/null @@ -1,93 +0,0 @@ -/* Decoding testcase for callback fields. - * Run e.g. ./test_encode_callbacks | ./test_decode_callbacks - */ - -#include -#include -#include "callbacks.pb.h" - -bool print_string(pb_istream_t *stream, const pb_field_t *field, void **arg) -{ - uint8_t buffer[1024] = {0}; - - /* We could read block-by-block to avoid the large buffer... */ - if (stream->bytes_left > sizeof(buffer) - 1) - return false; - - if (!pb_read(stream, buffer, stream->bytes_left)) - return false; - - /* Print the string, in format comparable with protoc --decode. - * Format comes from the arg defined in main(). - */ - printf((char*)*arg, buffer); - return true; -} - -bool print_int32(pb_istream_t *stream, const pb_field_t *field, void **arg) -{ - uint64_t value; - if (!pb_decode_varint(stream, &value)) - return false; - - printf((char*)*arg, (long)value); - return true; -} - -bool print_fixed32(pb_istream_t *stream, const pb_field_t *field, void **arg) -{ - uint32_t value; - if (!pb_decode_fixed32(stream, &value)) - return false; - - printf((char*)*arg, (long)value); - return true; -} - -bool print_fixed64(pb_istream_t *stream, const pb_field_t *field, void **arg) -{ - uint64_t value; - if (!pb_decode_fixed64(stream, &value)) - return false; - - printf((char*)*arg, (long long)value); - return true; -} - -int main() -{ - uint8_t buffer[1024]; - size_t length = fread(buffer, 1, 1024, stdin); - pb_istream_t stream = pb_istream_from_buffer(buffer, length); - - /* Note: empty initializer list initializes the struct with all-0. - * This is recommended so that unused callbacks are set to NULL instead - * of crashing at runtime. - */ - TestMessage testmessage = {}; - - testmessage.submsg.stringvalue.funcs.decode = &print_string; - testmessage.submsg.stringvalue.arg = "submsg {\n stringvalue: \"%s\"\n"; - testmessage.submsg.int32value.funcs.decode = &print_int32; - testmessage.submsg.int32value.arg = " int32value: %ld\n"; - testmessage.submsg.fixed32value.funcs.decode = &print_fixed32; - testmessage.submsg.fixed32value.arg = " fixed32value: %ld\n"; - testmessage.submsg.fixed64value.funcs.decode = &print_fixed64; - testmessage.submsg.fixed64value.arg = " fixed64value: %lld\n}\n"; - - testmessage.stringvalue.funcs.decode = &print_string; - testmessage.stringvalue.arg = "stringvalue: \"%s\"\n"; - testmessage.int32value.funcs.decode = &print_int32; - testmessage.int32value.arg = "int32value: %ld\n"; - testmessage.fixed32value.funcs.decode = &print_fixed32; - testmessage.fixed32value.arg = "fixed32value: %ld\n"; - testmessage.fixed64value.funcs.decode = &print_fixed64; - testmessage.fixed64value.arg = "fixed64value: %lld\n"; - testmessage.repeatedstring.funcs.decode = &print_string; - testmessage.repeatedstring.arg = "repeatedstring: \"%s\"\n"; - - if (!pb_decode(&stream, TestMessage_fields, &testmessage)) - return 1; - - return 0; -} diff --git a/tests/test_decode_extensions.c b/tests/test_decode_extensions.c deleted file mode 100644 index ef6a022..0000000 --- a/tests/test_decode_extensions.c +++ /dev/null @@ -1,43 +0,0 @@ -/* Test decoding of extension fields. */ - -#include -#include -#include -#include -#include "alltypes.pb.h" -#include "extensions.pb.h" - -#define TEST(x) if (!(x)) { \ - printf("Test " #x " failed.\n"); \ - return 2; \ - } - -int main(int argc, char **argv) -{ - uint8_t buffer[1024]; - size_t count = fread(buffer, 1, sizeof(buffer), stdin); - pb_istream_t stream = pb_istream_from_buffer(buffer, count); - - AllTypes alltypes = {}; - - int32_t extensionfield1; - pb_extension_t ext1 = {&AllTypes_extensionfield1, &extensionfield1, NULL}; - alltypes.extensions = &ext1; - - ExtensionMessage extensionfield2 = {}; - pb_extension_t ext2 = {&ExtensionMessage_AllTypes_extensionfield2, &extensionfield2, NULL}; - ext1.next = &ext2; - - if (!pb_decode(&stream, AllTypes_fields, &alltypes)) - { - printf("Parsing failed: %s\n", PB_GET_ERROR(&stream)); - return 1; - } - - TEST(extensionfield1 == 12345) - TEST(strcmp(extensionfield2.test1, "test") == 0) - TEST(extensionfield2.test2 == 54321) - - return 0; -} - diff --git a/tests/test_encode1.c b/tests/test_encode1.c deleted file mode 100644 index 742c99f..0000000 --- a/tests/test_encode1.c +++ /dev/null @@ -1,33 +0,0 @@ -/* A very simple encoding test case using person.proto. - * Just puts constant data in the fields and encodes into - * buffer, which is then written to stdout. - */ - -#include -#include -#include "person.pb.h" - -int main() -{ - /* Initialize the structure with constants */ - Person person = {"Test Person 99", 99, true, "test@person.com", - 3, {{"555-12345678", true, Person_PhoneType_MOBILE}, - {"99-2342", false, 0}, - {"1234-5678", true, Person_PhoneType_WORK}, - }}; - - uint8_t buffer[512]; - pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer)); - - /* Now encode it and check if we succeeded. */ - if (pb_encode(&stream, Person_fields, &person)) - { - fwrite(buffer, 1, stream.bytes_written, stdout); - return 0; /* Success */ - } - else - { - fprintf(stderr, "Encoding failed: %s\n", PB_GET_ERROR(&stream)); - return 1; /* Failure */ - } -} diff --git a/tests/test_encode2.c b/tests/test_encode2.c deleted file mode 100644 index fd25c6c..0000000 --- a/tests/test_encode2.c +++ /dev/null @@ -1,37 +0,0 @@ -/* Same as test_encode1.c, except writes directly to stdout. - */ - -#include -#include -#include "person.pb.h" - -/* This binds the pb_ostream_t into the stdout stream */ -bool streamcallback(pb_ostream_t *stream, const uint8_t *buf, size_t count) -{ - FILE *file = (FILE*) stream->state; - return fwrite(buf, 1, count, file) == count; -} - -int main() -{ - /* Initialize the structure with constants */ - Person person = {"Test Person 99", 99, true, "test@person.com", - 3, {{"555-12345678", true, Person_PhoneType_MOBILE}, - {"99-2342", false, 0}, - {"1234-5678", true, Person_PhoneType_WORK}, - }}; - - /* Prepare the stream, output goes directly to stdout */ - pb_ostream_t stream = {&streamcallback, stdout, SIZE_MAX, 0}; - - /* Now encode it and check if we succeeded. */ - if (pb_encode(&stream, Person_fields, &person)) - { - return 0; /* Success */ - } - else - { - fprintf(stderr, "Encoding failed: %s\n", PB_GET_ERROR(&stream)); - return 1; /* Failure */ - } -} diff --git a/tests/test_encode3.c b/tests/test_encode3.c deleted file mode 100644 index 982ad3c..0000000 --- a/tests/test_encode3.c +++ /dev/null @@ -1,130 +0,0 @@ -/* Attempts to test all the datatypes supported by ProtoBuf. - */ - -#include -#include -#include -#include -#include "alltypes.pb.h" - -int main(int argc, char **argv) -{ - int mode = (argc > 1) ? atoi(argv[1]) : 0; - - /* Initialize the structure with constants */ - AllTypes alltypes = {0}; - - alltypes.req_int32 = -1001; - alltypes.req_int64 = -1002; - alltypes.req_uint32 = 1003; - alltypes.req_uint64 = 1004; - alltypes.req_sint32 = -1005; - alltypes.req_sint64 = -1006; - alltypes.req_bool = true; - - alltypes.req_fixed32 = 1008; - alltypes.req_sfixed32 = -1009; - alltypes.req_float = 1010.0f; - - alltypes.req_fixed64 = 1011; - alltypes.req_sfixed64 = -1012; - alltypes.req_double = 1013.0; - - strcpy(alltypes.req_string, "1014"); - alltypes.req_bytes.size = 4; - memcpy(alltypes.req_bytes.bytes, "1015", 4); - strcpy(alltypes.req_submsg.substuff1, "1016"); - alltypes.req_submsg.substuff2 = 1016; - alltypes.req_enum = MyEnum_Truth; - - alltypes.rep_int32_count = 5; alltypes.rep_int32[4] = -2001; - alltypes.rep_int64_count = 5; alltypes.rep_int64[4] = -2002; - alltypes.rep_uint32_count = 5; alltypes.rep_uint32[4] = 2003; - alltypes.rep_uint64_count = 5; alltypes.rep_uint64[4] = 2004; - alltypes.rep_sint32_count = 5; alltypes.rep_sint32[4] = -2005; - alltypes.rep_sint64_count = 5; alltypes.rep_sint64[4] = -2006; - alltypes.rep_bool_count = 5; alltypes.rep_bool[4] = true; - - alltypes.rep_fixed32_count = 5; alltypes.rep_fixed32[4] = 2008; - alltypes.rep_sfixed32_count = 5; alltypes.rep_sfixed32[4] = -2009; - alltypes.rep_float_count = 5; alltypes.rep_float[4] = 2010.0f; - - alltypes.rep_fixed64_count = 5; alltypes.rep_fixed64[4] = 2011; - alltypes.rep_sfixed64_count = 5; alltypes.rep_sfixed64[4] = -2012; - alltypes.rep_double_count = 5; alltypes.rep_double[4] = 2013.0; - - alltypes.rep_string_count = 5; strcpy(alltypes.rep_string[4], "2014"); - alltypes.rep_bytes_count = 5; alltypes.rep_bytes[4].size = 4; - memcpy(alltypes.rep_bytes[4].bytes, "2015", 4); - - alltypes.rep_submsg_count = 5; - strcpy(alltypes.rep_submsg[4].substuff1, "2016"); - alltypes.rep_submsg[4].substuff2 = 2016; - alltypes.rep_submsg[4].has_substuff3 = true; - alltypes.rep_submsg[4].substuff3 = 2016; - - alltypes.rep_enum_count = 5; alltypes.rep_enum[4] = MyEnum_Truth; - alltypes.rep_emptymsg_count = 5; - - if (mode != 0) - { - /* Fill in values for optional fields */ - alltypes.has_opt_int32 = true; - alltypes.opt_int32 = 3041; - alltypes.has_opt_int64 = true; - alltypes.opt_int64 = 3042; - alltypes.has_opt_uint32 = true; - alltypes.opt_uint32 = 3043; - alltypes.has_opt_uint64 = true; - alltypes.opt_uint64 = 3044; - alltypes.has_opt_sint32 = true; - alltypes.opt_sint32 = 3045; - alltypes.has_opt_sint64 = true; - alltypes.opt_sint64 = 3046; - alltypes.has_opt_bool = true; - alltypes.opt_bool = true; - - alltypes.has_opt_fixed32 = true; - alltypes.opt_fixed32 = 3048; - alltypes.has_opt_sfixed32 = true; - alltypes.opt_sfixed32 = 3049; - alltypes.has_opt_float = true; - alltypes.opt_float = 3050.0f; - - alltypes.has_opt_fixed64 = true; - alltypes.opt_fixed64 = 3051; - alltypes.has_opt_sfixed64 = true; - alltypes.opt_sfixed64 = 3052; - alltypes.has_opt_double = true; - alltypes.opt_double = 3053.0; - - alltypes.has_opt_string = true; - strcpy(alltypes.opt_string, "3054"); - alltypes.has_opt_bytes = true; - alltypes.opt_bytes.size = 4; - memcpy(alltypes.opt_bytes.bytes, "3055", 4); - alltypes.has_opt_submsg = true; - strcpy(alltypes.opt_submsg.substuff1, "3056"); - alltypes.opt_submsg.substuff2 = 3056; - alltypes.has_opt_enum = true; - alltypes.opt_enum = MyEnum_Truth; - alltypes.has_opt_emptymsg = true; - } - - alltypes.end = 1099; - - uint8_t buffer[1024]; - pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer)); - - /* Now encode it and check if we succeeded. */ - if (pb_encode(&stream, AllTypes_fields, &alltypes)) - { - fwrite(buffer, 1, stream.bytes_written, stdout); - return 0; /* Success */ - } - else - { - fprintf(stderr, "Encoding failed: %s\n", PB_GET_ERROR(&stream)); - return 1; /* Failure */ - } -} diff --git a/tests/test_encode_callbacks.c b/tests/test_encode_callbacks.c deleted file mode 100644 index 3bb6a45..0000000 --- a/tests/test_encode_callbacks.c +++ /dev/null @@ -1,86 +0,0 @@ -/* Encoding testcase for callback fields */ - -#include -#include -#include -#include "callbacks.pb.h" - -bool encode_string(pb_ostream_t *stream, const pb_field_t *field, void * const *arg) -{ - char *str = "Hello world!"; - - if (!pb_encode_tag_for_field(stream, field)) - return false; - - return pb_encode_string(stream, (uint8_t*)str, strlen(str)); -} - -bool encode_int32(pb_ostream_t *stream, const pb_field_t *field, void * const *arg) -{ - if (!pb_encode_tag_for_field(stream, field)) - return false; - - return pb_encode_varint(stream, 42); -} - -bool encode_fixed32(pb_ostream_t *stream, const pb_field_t *field, void * const *arg) -{ - if (!pb_encode_tag_for_field(stream, field)) - return false; - - uint32_t value = 42; - return pb_encode_fixed32(stream, &value); -} - -bool encode_fixed64(pb_ostream_t *stream, const pb_field_t *field, void * const *arg) -{ - if (!pb_encode_tag_for_field(stream, field)) - return false; - - uint64_t value = 42; - return pb_encode_fixed64(stream, &value); -} - -bool encode_repeatedstring(pb_ostream_t *stream, const pb_field_t *field, void * const *arg) -{ - char *str[4] = {"Hello world!", "", "Test", "Test2"}; - int i; - - for (i = 0; i < 4; i++) - { - if (!pb_encode_tag_for_field(stream, field)) - return false; - - if (!pb_encode_string(stream, (uint8_t*)str[i], strlen(str[i]))) - return false; - } - return true; -} - -int main() -{ - uint8_t buffer[1024]; - pb_ostream_t stream = pb_ostream_from_buffer(buffer, 1024); - TestMessage testmessage = {}; - - testmessage.stringvalue.funcs.encode = &encode_string; - testmessage.int32value.funcs.encode = &encode_int32; - testmessage.fixed32value.funcs.encode = &encode_fixed32; - testmessage.fixed64value.funcs.encode = &encode_fixed64; - - testmessage.has_submsg = true; - testmessage.submsg.stringvalue.funcs.encode = &encode_string; - testmessage.submsg.int32value.funcs.encode = &encode_int32; - testmessage.submsg.fixed32value.funcs.encode = &encode_fixed32; - testmessage.submsg.fixed64value.funcs.encode = &encode_fixed64; - - testmessage.repeatedstring.funcs.encode = &encode_repeatedstring; - - if (!pb_encode(&stream, TestMessage_fields, &testmessage)) - return 1; - - if (fwrite(buffer, stream.bytes_written, 1, stdout) != 1) - return 2; - - return 0; -} diff --git a/tests/test_encode_extensions.c b/tests/test_encode_extensions.c deleted file mode 100644 index 8857f14..0000000 --- a/tests/test_encode_extensions.c +++ /dev/null @@ -1,38 +0,0 @@ -/* Tests extension fields. - */ - -#include -#include -#include -#include -#include "alltypes.pb.h" -#include "extensions.pb.h" - -int main(int argc, char **argv) -{ - AllTypes alltypes = {}; - - int32_t extensionfield1 = 12345; - pb_extension_t ext1 = {&AllTypes_extensionfield1, &extensionfield1, NULL}; - alltypes.extensions = &ext1; - - ExtensionMessage extensionfield2 = {"test", 54321}; - pb_extension_t ext2 = {&ExtensionMessage_AllTypes_extensionfield2, &extensionfield2, NULL}; - ext1.next = &ext2; - - uint8_t buffer[1024]; - pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer)); - - /* Now encode it and check if we succeeded. */ - if (pb_encode(&stream, AllTypes_fields, &alltypes)) - { - fwrite(buffer, 1, stream.bytes_written, stdout); - return 0; /* Success */ - } - else - { - fprintf(stderr, "Encoding failed: %s\n", PB_GET_ERROR(&stream)); - return 1; /* Failure */ - } -} - diff --git a/tests/test_missing_fields.c b/tests/test_missing_fields.c deleted file mode 100644 index 2774184..0000000 --- a/tests/test_missing_fields.c +++ /dev/null @@ -1,49 +0,0 @@ -/* Checks that missing required fields are detected properly */ - -#include -#include -#include -#include "missing_fields.pb.h" - -int main() -{ - uint8_t buffer[512] = {}; - - /* Create a message with one missing field */ - { - MissingField msg = {}; - pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer)); - if (!pb_encode(&stream, MissingField_fields, &msg)) - { - printf("Encode failed.\n"); - return 1; - } - } - - /* Test that it decodes properly if we don't require that field */ - { - MissingField msg = {}; - pb_istream_t stream = pb_istream_from_buffer(buffer, sizeof(buffer)); - - if (!pb_decode(&stream, MissingField_fields, &msg)) - { - printf("Decode failed: %s\n", PB_GET_ERROR(&stream)); - return 2; - } - } - - /* Test that it does *not* decode properly if we require the field */ - { - AllFields msg = {}; - pb_istream_t stream = pb_istream_from_buffer(buffer, sizeof(buffer)); - - if (pb_decode(&stream, AllFields_fields, &msg)) - { - printf("Decode didn't detect missing field.\n"); - return 3; - } - } - - return 0; /* All ok */ -} - diff --git a/tests/test_multiple_files.c b/tests/test_multiple_files.c deleted file mode 100644 index cb4e16d..0000000 --- a/tests/test_multiple_files.c +++ /dev/null @@ -1,13 +0,0 @@ -/* - * Tests if still compile if typedefs are redfefined in STATIC_ASSERTS when - * proto file includes another poto file - */ - -#include -#include -#include "callbacks2.pb.h" - -int main() -{ - return 0; -} diff --git a/tests/testperson.pb b/tests/testperson.pb deleted file mode 100644 index d1eb8cf..0000000 --- a/tests/testperson.pb +++ /dev/null @@ -1,3 +0,0 @@ - - Test Person7foobar@foobar.com" - 555-12345678 \ No newline at end of file diff --git a/tests/unittestproto.proto b/tests/unittestproto.proto deleted file mode 100644 index 7024942..0000000 --- a/tests/unittestproto.proto +++ /dev/null @@ -1,32 +0,0 @@ -import 'nanopb.proto'; - -message IntegerArray { - repeated int32 data = 1 [(nanopb).max_count = 10]; -} - -message FloatArray { - repeated float data = 1 [(nanopb).max_count = 10]; -} - -message StringMessage { - required string data = 1 [(nanopb).max_size = 10]; -} - -message CallbackArray { - // We cheat a bit and use this message for testing other types, too. - // Nanopb does not care about the actual defined data type for callback - // fields. - repeated int32 data = 1; -} - -message IntegerContainer { - required IntegerArray submsg = 1; -} - -message CallbackContainer { - required CallbackArray submsg = 1; -} - -message CallbackContainerContainer { - required CallbackContainer submsg = 1; -} diff --git a/tests/unittests.h b/tests/unittests.h deleted file mode 100644 index c2b470a..0000000 --- a/tests/unittests.h +++ /dev/null @@ -1,14 +0,0 @@ -#include - -#define COMMENT(x) printf("\n----" x "----\n"); -#define STR(x) #x -#define STR2(x) STR(x) -#define TEST(x) \ - if (!(x)) { \ - fprintf(stderr, "\033[31;1mFAILED:\033[22;39m " __FILE__ ":" STR2(__LINE__) " " #x "\n"); \ - status = 1; \ - } else { \ - printf("\033[32;1mOK:\033[22;39m " #x "\n"); \ - } - - -- cgit v1.2.3