From 262c62676cf740ec3ce14a22bde47b7968fec8f0 Mon Sep 17 00:00:00 2001 From: Petteri Aimonen Date: Sun, 8 Sep 2013 17:52:03 +0300 Subject: [PATCH 01/10] 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 --- .gitignore | 20 +-- tests/Makefile | 143 +----------------- tests/SConstruct | 77 ++++++++++ tests/{ => alltypes}/alltypes.options | 0 tests/{ => alltypes}/alltypes.proto | 0 .../decode_alltypes.c} | 0 .../encode_alltypes.c} | 0 .../alltypes_legacy.c} | 0 .../alltypes_legacy.h} | 0 .../decode_legacy.c} | 0 .../encode_legacy.c} | 0 tests/basic_buffer/SConscript | 12 ++ .../decode_buffer.c} | 0 .../encode_buffer.c} | 0 .../decode_stream.c} | 0 .../encode_stream.c} | 0 tests/{ => callbacks}/callbacks.proto | 0 .../decode_callbacks.c} | 0 .../encode_callbacks.c} | 0 tests/common/SConscript | 14 ++ tests/{ => common}/person.proto | 0 tests/{ => common}/unittestproto.proto | 0 tests/{ => common}/unittests.h | 0 tests/decode_unittests/SConscript | 4 + .../{ => decode_unittests}/decode_unittests.c | 0 tests/encode_unittests/SConscript | 5 + .../{ => encode_unittests}/encode_unittests.c | 0 .../decode_extensions.c} | 0 .../encode_extensions.c} | 0 tests/{ => extensions}/extensions.options | 0 tests/{ => extensions}/extensions.proto | 0 .../alltypes_with_extra_fields.pb | Bin .../person_with_extra_field.pb | Bin .../missing_fields.c} | 0 .../{ => missing_fields}/missing_fields.proto | 0 tests/multiple_files/callbacks.proto | 16 ++ tests/{ => multiple_files}/callbacks2.proto | 0 .../test_multiple_files.c | 0 tests/{ => no_messages}/no_messages.proto | 0 tests/{ => options}/options.expected | 0 tests/{ => options}/options.proto | 0 .../funny-proto+name.proto | 0 tests/testperson.pb | 3 - 43 files changed, 132 insertions(+), 162 deletions(-) create mode 100644 tests/SConstruct rename tests/{ => alltypes}/alltypes.options (100%) rename tests/{ => alltypes}/alltypes.proto (100%) rename tests/{test_decode3.c => alltypes/decode_alltypes.c} (100%) rename tests/{test_encode3.c => alltypes/encode_alltypes.c} (100%) rename tests/{bc_alltypes.pb.c => backwards_compatibility/alltypes_legacy.c} (100%) rename tests/{bc_alltypes.pb.h => backwards_compatibility/alltypes_legacy.h} (100%) rename tests/{bc_decode.c => backwards_compatibility/decode_legacy.c} (100%) rename tests/{bc_encode.c => backwards_compatibility/encode_legacy.c} (100%) create mode 100644 tests/basic_buffer/SConscript rename tests/{test_decode1.c => basic_buffer/decode_buffer.c} (100%) rename tests/{test_encode1.c => basic_buffer/encode_buffer.c} (100%) rename tests/{test_decode2.c => basic_stream/decode_stream.c} (100%) rename tests/{test_encode2.c => basic_stream/encode_stream.c} (100%) rename tests/{ => callbacks}/callbacks.proto (100%) rename tests/{test_decode_callbacks.c => callbacks/decode_callbacks.c} (100%) rename tests/{test_encode_callbacks.c => callbacks/encode_callbacks.c} (100%) create mode 100644 tests/common/SConscript rename tests/{ => common}/person.proto (100%) rename tests/{ => common}/unittestproto.proto (100%) rename tests/{ => common}/unittests.h (100%) create mode 100644 tests/decode_unittests/SConscript rename tests/{ => decode_unittests}/decode_unittests.c (100%) create mode 100644 tests/encode_unittests/SConscript rename tests/{ => encode_unittests}/encode_unittests.c (100%) rename tests/{test_decode_extensions.c => extensions/decode_extensions.c} (100%) rename tests/{test_encode_extensions.c => extensions/encode_extensions.c} (100%) rename tests/{ => extensions}/extensions.options (100%) rename tests/{ => extensions}/extensions.proto (100%) rename tests/{ => extra_fields}/alltypes_with_extra_fields.pb (100%) rename tests/{ => extra_fields}/person_with_extra_field.pb (100%) rename tests/{test_missing_fields.c => missing_fields/missing_fields.c} (100%) rename tests/{ => missing_fields}/missing_fields.proto (100%) create mode 100644 tests/multiple_files/callbacks.proto rename tests/{ => multiple_files}/callbacks2.proto (100%) rename tests/{ => multiple_files}/test_multiple_files.c (100%) rename tests/{ => no_messages}/no_messages.proto (100%) rename tests/{ => options}/options.expected (100%) rename tests/{ => options}/options.proto (100%) rename tests/{ => special_characters}/funny-proto+name.proto (100%) delete mode 100644 tests/testperson.pb diff --git a/.gitignore b/.gitignore index dec8b00..b83afef 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ *.pb *~ *.tar.gz +.sconsign.dblite julkaisu.txt docs/*.html docs/generator_flow.png @@ -18,22 +19,3 @@ example_avr_double/test_conversions example_unions/decode example_unions/encode generator/nanopb_pb2.pyc -tests/decode_unittests -tests/encode_unittests -tests/test_compiles -tests/test_decode1 -tests/test_decode2 -tests/test_decode3 -tests/test_decode3_buf -tests/test_decode_callbacks -tests/test_encode1 -tests/test_encode2 -tests/test_encode3 -tests/test_encode3_buf -tests/test_encode_callbacks -tests/test_missing_fields -tests/test_multiple_files -tests/bc_decode -tests/bc_encode -tests/breakpoints - 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 + scons -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 - -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/alltypes.options similarity index 100% rename from tests/alltypes.options rename to tests/alltypes/alltypes.options diff --git a/tests/alltypes.proto b/tests/alltypes/alltypes.proto similarity index 100% rename from tests/alltypes.proto rename to tests/alltypes/alltypes.proto diff --git a/tests/test_decode3.c b/tests/alltypes/decode_alltypes.c similarity index 100% rename from tests/test_decode3.c rename to tests/alltypes/decode_alltypes.c diff --git a/tests/test_encode3.c b/tests/alltypes/encode_alltypes.c similarity index 100% rename from tests/test_encode3.c rename to tests/alltypes/encode_alltypes.c diff --git a/tests/bc_alltypes.pb.c b/tests/backwards_compatibility/alltypes_legacy.c similarity index 100% rename from tests/bc_alltypes.pb.c rename to tests/backwards_compatibility/alltypes_legacy.c diff --git a/tests/bc_alltypes.pb.h b/tests/backwards_compatibility/alltypes_legacy.h similarity index 100% rename from tests/bc_alltypes.pb.h rename to tests/backwards_compatibility/alltypes_legacy.h diff --git a/tests/bc_decode.c b/tests/backwards_compatibility/decode_legacy.c similarity index 100% rename from tests/bc_decode.c rename to tests/backwards_compatibility/decode_legacy.c diff --git a/tests/bc_encode.c b/tests/backwards_compatibility/encode_legacy.c similarity index 100% rename from tests/bc_encode.c rename to tests/backwards_compatibility/encode_legacy.c 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/test_decode1.c b/tests/basic_buffer/decode_buffer.c similarity index 100% rename from tests/test_decode1.c rename to tests/basic_buffer/decode_buffer.c diff --git a/tests/test_encode1.c b/tests/basic_buffer/encode_buffer.c similarity index 100% rename from tests/test_encode1.c rename to tests/basic_buffer/encode_buffer.c diff --git a/tests/test_decode2.c b/tests/basic_stream/decode_stream.c similarity index 100% rename from tests/test_decode2.c rename to tests/basic_stream/decode_stream.c diff --git a/tests/test_encode2.c b/tests/basic_stream/encode_stream.c similarity index 100% rename from tests/test_encode2.c rename to tests/basic_stream/encode_stream.c diff --git a/tests/callbacks.proto b/tests/callbacks/callbacks.proto similarity index 100% rename from tests/callbacks.proto rename to tests/callbacks/callbacks.proto diff --git a/tests/test_decode_callbacks.c b/tests/callbacks/decode_callbacks.c similarity index 100% rename from tests/test_decode_callbacks.c rename to tests/callbacks/decode_callbacks.c diff --git a/tests/test_encode_callbacks.c b/tests/callbacks/encode_callbacks.c similarity index 100% rename from tests/test_encode_callbacks.c rename to tests/callbacks/encode_callbacks.c 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/person.proto b/tests/common/person.proto similarity index 100% rename from tests/person.proto rename to tests/common/person.proto diff --git a/tests/unittestproto.proto b/tests/common/unittestproto.proto similarity index 100% rename from tests/unittestproto.proto rename to tests/common/unittestproto.proto diff --git a/tests/unittests.h b/tests/common/unittests.h similarity index 100% rename from tests/unittests.h rename to tests/common/unittests.h 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.c b/tests/decode_unittests/decode_unittests.c similarity index 100% rename from tests/decode_unittests.c rename to tests/decode_unittests/decode_unittests.c 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.c b/tests/encode_unittests/encode_unittests.c similarity index 100% rename from tests/encode_unittests.c rename to tests/encode_unittests/encode_unittests.c diff --git a/tests/test_decode_extensions.c b/tests/extensions/decode_extensions.c similarity index 100% rename from tests/test_decode_extensions.c rename to tests/extensions/decode_extensions.c diff --git a/tests/test_encode_extensions.c b/tests/extensions/encode_extensions.c similarity index 100% rename from tests/test_encode_extensions.c rename to tests/extensions/encode_extensions.c diff --git a/tests/extensions.options b/tests/extensions/extensions.options similarity index 100% rename from tests/extensions.options rename to tests/extensions/extensions.options diff --git a/tests/extensions.proto b/tests/extensions/extensions.proto similarity index 100% rename from tests/extensions.proto rename to tests/extensions/extensions.proto diff --git a/tests/alltypes_with_extra_fields.pb b/tests/extra_fields/alltypes_with_extra_fields.pb similarity index 100% rename from tests/alltypes_with_extra_fields.pb rename to tests/extra_fields/alltypes_with_extra_fields.pb diff --git a/tests/person_with_extra_field.pb b/tests/extra_fields/person_with_extra_field.pb similarity index 100% rename from tests/person_with_extra_field.pb rename to tests/extra_fields/person_with_extra_field.pb diff --git a/tests/test_missing_fields.c b/tests/missing_fields/missing_fields.c similarity index 100% rename from tests/test_missing_fields.c rename to tests/missing_fields/missing_fields.c diff --git a/tests/missing_fields.proto b/tests/missing_fields/missing_fields.proto similarity index 100% rename from tests/missing_fields.proto rename to tests/missing_fields/missing_fields.proto 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/callbacks2.proto b/tests/multiple_files/callbacks2.proto similarity index 100% rename from tests/callbacks2.proto rename to tests/multiple_files/callbacks2.proto diff --git a/tests/test_multiple_files.c b/tests/multiple_files/test_multiple_files.c similarity index 100% rename from tests/test_multiple_files.c rename to tests/multiple_files/test_multiple_files.c diff --git a/tests/no_messages.proto b/tests/no_messages/no_messages.proto similarity index 100% rename from tests/no_messages.proto rename to tests/no_messages/no_messages.proto diff --git a/tests/options.expected b/tests/options/options.expected similarity index 100% rename from tests/options.expected rename to tests/options/options.expected diff --git a/tests/options.proto b/tests/options/options.proto similarity index 100% rename from tests/options.proto rename to tests/options/options.proto diff --git a/tests/funny-proto+name.proto b/tests/special_characters/funny-proto+name.proto similarity index 100% rename from tests/funny-proto+name.proto rename to tests/special_characters/funny-proto+name.proto 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 From 4dccf28ba9c212b232147fd3823554d04b30c392 Mon Sep 17 00:00:00 2001 From: Petteri Aimonen Date: Tue, 10 Sep 2013 11:34:57 +0300 Subject: [PATCH 02/10] Convert more test cases to scons --- tests/SConstruct | 72 +++----------------------- tests/alltypes/SConscript | 12 +++++ tests/cxx_main_program/SConscript | 20 +++++++ tests/site_scons/site_init.py | 86 +++++++++++++++++++++++++++++++ 4 files changed, 124 insertions(+), 66 deletions(-) create mode 100644 tests/alltypes/SConscript create mode 100644 tests/cxx_main_program/SConscript create mode 100644 tests/site_scons/site_init.py diff --git a/tests/SConstruct b/tests/SConstruct index 0ec1e54..b2d524c 100644 --- a/tests/SConstruct +++ b/tests/SConstruct @@ -1,77 +1,17 @@ env = DefaultEnvironment() +# Add the builders defined in site_init.py +add_nanopb_builders(env) + +# Path to the files shared by tests, and to the nanopb core. 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') +# Path for finding nanopb.proto +env.Append(PROTOCPATH = ['#../generator', '/usr/include', '.']) # 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/SConscript b/tests/alltypes/SConscript new file mode 100644 index 0000000..3c8adc4 --- /dev/null +++ b/tests/alltypes/SConscript @@ -0,0 +1,12 @@ +# Build and run a test that encodes and decodes a message that contains +# all of the Protocol Buffers data types. + +Import("env") + +env.NanopbProto("alltypes") +env.Program(["encode_alltypes.c", "alltypes.pb.c", "#common/pb_encode.o"]) +env.Program(["decode_alltypes.c", "alltypes.pb.c", "#common/pb_decode.o"]) + +env.RunTest("encode_alltypes") +env.RunTest(["decode_alltypes", "encode_alltypes.output"]) + diff --git a/tests/cxx_main_program/SConscript b/tests/cxx_main_program/SConscript new file mode 100644 index 0000000..b548231 --- /dev/null +++ b/tests/cxx_main_program/SConscript @@ -0,0 +1,20 @@ +# Run the alltypes test case, but compile it as C++ instead. +# In fact, compile the entire nanopb using C++ compiler. + +Import("env") + +# Copy the files to .cxx extension in order to force C++ build. +c = Copy("$TARGET", "$SOURCE") +Command("pb_encode.cxx", "#../pb_encode.c", c) +Command("pb_decode.cxx", "#../pb_decode.c", c) +Command("alltypes.pb.h", "#alltypes/alltypes.pb.h", c) +Command("alltypes.pb.cxx", "#alltypes/alltypes.pb.c", c) +Command("encode_alltypes.cxx", "#alltypes/encode_alltypes.c", c) +Command("decode_alltypes.cxx", "#alltypes/decode_alltypes.c", c) + +# Now build and run the test normally. +env.Program(["encode_alltypes.cxx", "alltypes.pb.cxx", "pb_encode.cxx"]) +env.Program(["decode_alltypes.cxx", "alltypes.pb.cxx", "pb_decode.cxx"]) + +env.RunTest("encode_alltypes") +env.RunTest(["decode_alltypes", "encode_alltypes.output"]) diff --git a/tests/site_scons/site_init.py b/tests/site_scons/site_init.py new file mode 100644 index 0000000..1383067 --- /dev/null +++ b/tests/site_scons/site_init.py @@ -0,0 +1,86 @@ +import subprocess +import sys + +def add_nanopb_builders(env): + '''Add the necessary builder commands for nanopb tests.''' + + # 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') + + # 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")) + env.SetDefault(NANOPB_FLAGS = '-q') + + # 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(target, source, env): + if len(source) > 1: + infile = open(str(source[1])) + else: + infile = None + + pipe = subprocess.Popen(str(source[0]), + stdin = infile, + stdout = open(str(target[0]), 'w'), + stderr = sys.stderr) + result = pipe.wait() + if result == 0: + print '\033[92m[ OK ]\033[0m Ran ' + str(source[0]) + else: + print '\033[91m[FAIL]\033[0m Program ' + str(source[0]) + ' returned ' + str(result) + return result + + run_test_builder = Builder(action = run_test, + 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: + print '\033[92m[ OK ]\033[0m Files equal: ' + str(source[0]) + ' and ' + str(source[1]) + return 0 + else: + print '\033[91m[FAIL]\033[0m Files differ: ' + str(source[0]) + ' and ' + str(source[1]) + return 1 + + compare_builder = Builder(action = compare_files, + suffix = '.equal') + env.Append(BUILDERS = {'Compare': compare_builder}) + + From e681dd0d75a4b6a7974cc898477f3a138f7872c2 Mon Sep 17 00:00:00 2001 From: Petteri Aimonen Date: Tue, 10 Sep 2013 12:39:39 +0300 Subject: [PATCH 03/10] Add an example pb_syshdr.h file for platforms without C99. This allows building the tests easily on Visual C++ in C mode. Also add checks to pb.h that the defined integer types are of the proper sizes. This may prevent some difficult to debug problems later.. --- compat/pb_syshdr.h | 71 ++++++++++++++++++++++++++++++++++++++++++++++ pb.h | 11 +++++++ tests/SConstruct | 7 +++++ 3 files changed, 89 insertions(+) create mode 100644 compat/pb_syshdr.h diff --git a/compat/pb_syshdr.h b/compat/pb_syshdr.h new file mode 100644 index 0000000..c170c8d --- /dev/null +++ b/compat/pb_syshdr.h @@ -0,0 +1,71 @@ +/* This is an example of a header file for platforms/compilers that do + * not come with stdint.h/stddef.h/stdbool.h/string.h. To use it, define + * PB_SYSTEM_HEADER as "pb_syshdr.h", including the quotes, and add the + * compat folder to your include path. + * + * It is very likely that you will need to customize this file to suit + * your platform. For any compiler that supports C99, this file should + * not be necessary. + */ + +#ifndef _PB_SYSHDR_H_ +#define _PB_SYSHDR_H_ + +/* stdint.h subset */ +/* You will need to modify these to match the word size of your platform. */ +typedef signed char int8_t; +typedef unsigned char uint8_t; +typedef signed short int16_t; +typedef unsigned short uint16_t; +typedef signed int int32_t; +typedef unsigned int uint32_t; +typedef signed long long int64_t; +typedef unsigned long long uint64_t; + +/* stddef.h subset */ +typedef uint32_t size_t; +#define offsetof(st, m) ((size_t)(&((st *)0)->m)) + +#ifndef NULL +#define NULL 0 +#endif + +/* stdbool.h subset */ +typedef int bool; +#define false 0 +#define true 1 + +/* string.h subset */ +/* Implementations are from the Public Domain C Library (PDCLib). */ +static size_t strlen( const char * s ) +{ + size_t rc = 0; + while ( s[rc] ) + { + ++rc; + } + return rc; +} + +static void * memcpy( void *s1, const void *s2, size_t n ) +{ + char * dest = (char *) s1; + const char * src = (const char *) s2; + while ( n-- ) + { + *dest++ = *src++; + } + return s1; +} + +static void * memset( void * s, int c, size_t n ) +{ + unsigned char * p = (unsigned char *) s; + while ( n-- ) + { + *p++ = (unsigned char) c; + } + return s; +} + +#endif diff --git a/pb.h b/pb.h index e3e68ce..c63b351 100644 --- a/pb.h +++ b/pb.h @@ -215,6 +215,17 @@ struct _pb_field_t { } pb_packed; PB_PACKED_STRUCT_END +/* Make sure that the standard integer types are of the expected sizes. + * All kinds of things may break otherwise.. atleast all fixed* types. */ +STATIC_ASSERT(sizeof(int8_t) == 1, INT8_T_WRONG_SIZE) +STATIC_ASSERT(sizeof(uint8_t) == 1, UINT8_T_WRONG_SIZE) +STATIC_ASSERT(sizeof(int16_t) == 2, INT16_T_WRONG_SIZE) +STATIC_ASSERT(sizeof(uint16_t) == 2, UINT16_T_WRONG_SIZE) +STATIC_ASSERT(sizeof(int32_t) == 4, INT32_T_WRONG_SIZE) +STATIC_ASSERT(sizeof(uint32_t) == 4, UINT32_T_WRONG_SIZE) +STATIC_ASSERT(sizeof(int64_t) == 8, INT64_T_WRONG_SIZE) +STATIC_ASSERT(sizeof(uint64_t) == 8, UINT64_T_WRONG_SIZE) + /* This structure is used for 'bytes' arrays. * It has the number of bytes in the beginning, and after that an array. * Note that actual structs used will have a different length of bytes array. diff --git a/tests/SConstruct b/tests/SConstruct index b2d524c..a690aff 100644 --- a/tests/SConstruct +++ b/tests/SConstruct @@ -12,6 +12,13 @@ env.Append(PROTOCPATH = ['#../generator', '/usr/include', '.']) # Define the include path to find nanopb.proto env.Append(PROTOCPATH = ['#../generator', '/usr/include', '.']) +# If the platform doesn't support C99, use our own header file instead. +conf = Configure(env) +if not conf.CheckCHeader('stdbool.h'): + conf.env.Append(CPPDEFINES = {'PB_SYSTEM_HEADER': '\\"pb_syshdr.h\\"'}) + conf.env.Append(CPPPATH = "#../compat") +env = conf.Finish() + # Now include the SConscript files from all subdirectories SConscript(Glob('*/SConscript'), exports = 'env') From f04ab838abd90fb70f7d6ef77fdacdf07f09ba4d Mon Sep 17 00:00:00 2001 From: Petteri Aimonen Date: Tue, 10 Sep 2013 17:44:32 +0300 Subject: [PATCH 04/10] Build fixes for Windows/Visual C++ --- compat/pb_syshdr.h | 23 ++++++++++ tests/SConstruct | 52 ++++++++++++++++++----- tests/alltypes/SConscript | 8 ++-- tests/alltypes/encode_alltypes.c | 26 ++++++------ tests/basic_buffer/SConscript | 8 ++-- tests/basic_buffer/decode_buffer.c | 11 +++-- tests/basic_buffer/encode_buffer.c | 11 +++-- tests/common/test_helpers.h | 17 ++++++++ tests/cxx_main_program/SConscript | 8 ++-- tests/decode_unittests/SConscript | 4 +- tests/decode_unittests/decode_unittests.c | 2 +- tests/encode_unittests/SConscript | 4 +- tests/site_scons/site_init.py | 16 +++++-- 13 files changed, 141 insertions(+), 49 deletions(-) create mode 100644 tests/common/test_helpers.h diff --git a/compat/pb_syshdr.h b/compat/pb_syshdr.h index c170c8d..b69a167 100644 --- a/compat/pb_syshdr.h +++ b/compat/pb_syshdr.h @@ -12,6 +12,9 @@ #define _PB_SYSHDR_H_ /* stdint.h subset */ +#ifdef HAVE_STDINT_H +#include +#else /* You will need to modify these to match the word size of your platform. */ typedef signed char int8_t; typedef unsigned char uint8_t; @@ -21,8 +24,13 @@ typedef signed int int32_t; typedef unsigned int uint32_t; typedef signed long long int64_t; typedef unsigned long long uint64_t; +#endif /* stddef.h subset */ +#ifdef HAVE_STDDEF_H +#include +#else + typedef uint32_t size_t; #define offsetof(st, m) ((size_t)(&((st *)0)->m)) @@ -30,12 +38,26 @@ typedef uint32_t size_t; #define NULL 0 #endif +#endif + /* stdbool.h subset */ +#ifdef HAVE_STDBOOL_H +#include +#else + +#ifndef __cplusplus typedef int bool; #define false 0 #define true 1 +#endif + +#endif /* string.h subset */ +#ifdef HAVE_STRING_H +#include +#else + /* Implementations are from the Public Domain C Library (PDCLib). */ static size_t strlen( const char * s ) { @@ -67,5 +89,6 @@ static void * memset( void * s, int c, size_t n ) } return s; } +#endif #endif diff --git a/tests/SConstruct b/tests/SConstruct index a690aff..8bbb31d 100644 --- a/tests/SConstruct +++ b/tests/SConstruct @@ -1,4 +1,5 @@ -env = DefaultEnvironment() +import os +env = Environment(ENV = {'PATH': os.environ['PATH']}) # Add the builders defined in site_init.py add_nanopb_builders(env) @@ -7,18 +8,49 @@ add_nanopb_builders(env) env.Append(CPPPATH = ["#../", "#common"]) # Path for finding nanopb.proto -env.Append(PROTOCPATH = ['#../generator', '/usr/include', '.']) +env.Append(PROTOCPATH = '#../generator') -# Define the include path to find nanopb.proto -env.Append(PROTOCPATH = ['#../generator', '/usr/include', '.']) +# Check the compilation environment, unless we are just cleaning up. +if not env.GetOption('clean'): + conf = Configure(env) -# If the platform doesn't support C99, use our own header file instead. -conf = Configure(env) -if not conf.CheckCHeader('stdbool.h'): - conf.env.Append(CPPDEFINES = {'PB_SYSTEM_HEADER': '\\"pb_syshdr.h\\"'}) - conf.env.Append(CPPPATH = "#../compat") -env = conf.Finish() + # If the platform doesn't support C99, use our own header file instead. + stdbool = conf.CheckCHeader('stdbool.h') + stdint = conf.CheckCHeader('stdint.h') + stddef = conf.CheckCHeader('stddef.h') + string = conf.CheckCHeader('string.h') + if not stdbool or not stdint or not stddef or not string: + conf.env.Append(CPPDEFINES = {'PB_SYSTEM_HEADER': '\\"pb_syshdr.h\\"'}) + conf.env.Append(CPPPATH = "#../compat") + + if stdbool: conf.env.Append(CPPDEFINES = {'HAVE_STDBOOL_H': 1}) + if stdint: conf.env.Append(CPPDEFINES = {'HAVE_STDINT_H': 1}) + if stddef: conf.env.Append(CPPDEFINES = {'HAVE_STDDEF_H': 1}) + if string: conf.env.Append(CPPDEFINES = {'HAVE_STRING_H': 1}) + + # Check if we can use pkg-config to find protobuf include path + status, output = conf.TryAction('pkg-config protobuf --variable=includedir > $TARGET') + if status: + conf.env.Append(PROTOCPATH = output.strip()) + else: + conf.env.Append(PROTOCPATH = '/usr/include') + + # End the config stuff + env = conf.Finish() +# Initialize the CCFLAGS according to the compiler +if 'cl' in env['CC']: + # Microsoft Visual C++ + + # Debug info on, warning level 2 for tests, warnings as errors + env.Append(CCFLAGS = '/Zi /W2 /WX') + env.Append(LINKFLAGS = '/DEBUG') + + # PB_RETURN_ERROR triggers C4127 because of while(0) + env.Append(CCFLAGS = '/wd4127') + + + # Now include the SConscript files from all subdirectories SConscript(Glob('*/SConscript'), exports = 'env') diff --git a/tests/alltypes/SConscript b/tests/alltypes/SConscript index 3c8adc4..8aa45b6 100644 --- a/tests/alltypes/SConscript +++ b/tests/alltypes/SConscript @@ -4,9 +4,9 @@ Import("env") env.NanopbProto("alltypes") -env.Program(["encode_alltypes.c", "alltypes.pb.c", "#common/pb_encode.o"]) -env.Program(["decode_alltypes.c", "alltypes.pb.c", "#common/pb_decode.o"]) +enc = env.Program(["encode_alltypes.c", "alltypes.pb.c", "#common/pb_encode.o"]) +dec = env.Program(["decode_alltypes.c", "alltypes.pb.c", "#common/pb_decode.o"]) -env.RunTest("encode_alltypes") -env.RunTest(["decode_alltypes", "encode_alltypes.output"]) +env.RunTest(enc) +env.RunTest([dec, "encode_alltypes.output"]) diff --git a/tests/alltypes/encode_alltypes.c b/tests/alltypes/encode_alltypes.c index 982ad3c..802e157 100644 --- a/tests/alltypes/encode_alltypes.c +++ b/tests/alltypes/encode_alltypes.c @@ -113,18 +113,20 @@ int main(int argc, char **argv) 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 */ + 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/basic_buffer/SConscript b/tests/basic_buffer/SConscript index 5b85e13..349fb14 100644 --- a/tests/basic_buffer/SConscript +++ b/tests/basic_buffer/SConscript @@ -2,11 +2,11 @@ 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"]) +enc = env.Program(["encode_buffer.c", "#common/person.pb.c", "#common/pb_encode.o"]) +dec = 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.RunTest(enc) +env.RunTest([dec, "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 index 56bbd8f..d231c91 100644 --- a/tests/basic_buffer/decode_buffer.c +++ b/tests/basic_buffer/decode_buffer.c @@ -9,6 +9,7 @@ #include #include #include "person.pb.h" +#include "test_helpers.h" /* This function is called once from main(), it handles the decoding and printing. */ @@ -59,9 +60,13 @@ bool print_person(pb_istream_t *stream) int main() { - /* Read the data into buffer */ uint8_t buffer[512]; - size_t count = fread(buffer, 1, sizeof(buffer), stdin); + pb_istream_t stream; + size_t count; + + /* Read the data into buffer */ + SET_BINARY_MODE(stdin); + count = fread(buffer, 1, sizeof(buffer), stdin); if (!feof(stdin)) { @@ -70,7 +75,7 @@ int main() } /* Construct a pb_istream_t for reading from the buffer */ - pb_istream_t stream = pb_istream_from_buffer(buffer, count); + stream = pb_istream_from_buffer(buffer, count); /* Decode and print out the stuff */ if (!print_person(&stream)) diff --git a/tests/basic_buffer/encode_buffer.c b/tests/basic_buffer/encode_buffer.c index 742c99f..d3e4f6e 100644 --- a/tests/basic_buffer/encode_buffer.c +++ b/tests/basic_buffer/encode_buffer.c @@ -6,9 +6,13 @@ #include #include #include "person.pb.h" +#include "test_helpers.h" int main() { + uint8_t buffer[512]; + pb_ostream_t stream; + /* Initialize the structure with constants */ Person person = {"Test Person 99", 99, true, "test@person.com", 3, {{"555-12345678", true, Person_PhoneType_MOBILE}, @@ -16,12 +20,13 @@ int main() {"1234-5678", true, Person_PhoneType_WORK}, }}; - uint8_t buffer[512]; - pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer)); + stream = pb_ostream_from_buffer(buffer, sizeof(buffer)); /* Now encode it and check if we succeeded. */ if (pb_encode(&stream, Person_fields, &person)) - { + { + /* Write the result data to stdout */ + SET_BINARY_MODE(stdout); fwrite(buffer, 1, stream.bytes_written, stdout); return 0; /* Success */ } diff --git a/tests/common/test_helpers.h b/tests/common/test_helpers.h new file mode 100644 index 0000000..f77760a --- /dev/null +++ b/tests/common/test_helpers.h @@ -0,0 +1,17 @@ +/* Compatibility helpers for the test programs. */ + +#ifndef _TEST_HELPERS_H_ +#define _TEST_HELPERS_H_ + +#ifdef _WIN32 +#include +#include +#define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY) + +#else +#define SET_BINARY_MODE(file) + +#endif + + +#endif diff --git a/tests/cxx_main_program/SConscript b/tests/cxx_main_program/SConscript index b548231..0d0a25c 100644 --- a/tests/cxx_main_program/SConscript +++ b/tests/cxx_main_program/SConscript @@ -13,8 +13,8 @@ Command("encode_alltypes.cxx", "#alltypes/encode_alltypes.c", c) Command("decode_alltypes.cxx", "#alltypes/decode_alltypes.c", c) # Now build and run the test normally. -env.Program(["encode_alltypes.cxx", "alltypes.pb.cxx", "pb_encode.cxx"]) -env.Program(["decode_alltypes.cxx", "alltypes.pb.cxx", "pb_decode.cxx"]) +enc = env.Program(["encode_alltypes.cxx", "alltypes.pb.cxx", "pb_encode.cxx"]) +dec = env.Program(["decode_alltypes.cxx", "alltypes.pb.cxx", "pb_decode.cxx"]) -env.RunTest("encode_alltypes") -env.RunTest(["decode_alltypes", "encode_alltypes.output"]) +env.RunTest(enc) +env.RunTest([dec, "encode_alltypes.output"]) diff --git a/tests/decode_unittests/SConscript b/tests/decode_unittests/SConscript index 860d773..5e0f840 100644 --- a/tests/decode_unittests/SConscript +++ b/tests/decode_unittests/SConscript @@ -1,4 +1,4 @@ Import('env') -env.Program(["decode_unittests.c", "#common/unittestproto.pb.c", "#common/pb_decode.o"]) -env.RunTest('decode_unittests') +p = env.Program(["decode_unittests.c", "#common/unittestproto.pb.c", "#common/pb_decode.o"]) +env.RunTest(p) diff --git a/tests/decode_unittests/decode_unittests.c b/tests/decode_unittests/decode_unittests.c index 6ad05f0..9c447a5 100644 --- a/tests/decode_unittests/decode_unittests.c +++ b/tests/decode_unittests/decode_unittests.c @@ -291,7 +291,7 @@ int main() { pb_istream_t s; - IntegerContainer dest = {}; + IntegerContainer dest = {{0}}; COMMENT("Testing pb_decode_delimited") TEST((s = S("\x09\x0A\x07\x0A\x05\x01\x02\x03\x04\x05"), diff --git a/tests/encode_unittests/SConscript b/tests/encode_unittests/SConscript index 0864a91..6a5ffcf 100644 --- a/tests/encode_unittests/SConscript +++ b/tests/encode_unittests/SConscript @@ -1,5 +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') +p = env.Program(["encode_unittests.c", "#common/unittestproto.pb.c", "#common/pb_encode.o"]) +env.RunTest(p) diff --git a/tests/site_scons/site_init.py b/tests/site_scons/site_init.py index 1383067..b69db64 100644 --- a/tests/site_scons/site_init.py +++ b/tests/site_scons/site_init.py @@ -1,6 +1,13 @@ import subprocess import sys +try: + # Make terminal colors work on windows + import colorama + colorama.init() +except ImportError: + pass + def add_nanopb_builders(env): '''Add the necessary builder commands for nanopb tests.''' @@ -14,6 +21,7 @@ def add_nanopb_builders(env): src_suffix = '.proto') env.Append(BUILDERS = {'Proto': proto_file_builder}) env.SetDefault(PROTOC = 'protoc') + env.SetDefault(PROTOCPATH = ['.']) # Build command for running nanopb generator import os.path @@ -50,9 +58,9 @@ def add_nanopb_builders(env): stderr = sys.stderr) result = pipe.wait() if result == 0: - print '\033[92m[ OK ]\033[0m Ran ' + str(source[0]) + print '\033[32m[ OK ]\033[0m Ran ' + str(source[0]) else: - print '\033[91m[FAIL]\033[0m Program ' + str(source[0]) + ' returned ' + str(result) + print '\033[31m[FAIL]\033[0m Program ' + str(source[0]) + ' returned ' + str(result) return result run_test_builder = Builder(action = run_test, @@ -73,10 +81,10 @@ def add_nanopb_builders(env): data1 = open(str(source[0]), 'rb').read() data2 = open(str(source[1]), 'rb').read() if data1 == data2: - print '\033[92m[ OK ]\033[0m Files equal: ' + str(source[0]) + ' and ' + str(source[1]) + print '\033[32m[ OK ]\033[0m Files equal: ' + str(source[0]) + ' and ' + str(source[1]) return 0 else: - print '\033[91m[FAIL]\033[0m Files differ: ' + str(source[0]) + ' and ' + str(source[1]) + print '\033[31m[FAIL]\033[0m Files differ: ' + str(source[0]) + ' and ' + str(source[1]) return 1 compare_builder = Builder(action = compare_files, From 696a01bf140e91661eae77663de99c78c95dcc73 Mon Sep 17 00:00:00 2001 From: Petteri Aimonen Date: Mon, 9 Sep 2013 10:53:04 +0300 Subject: [PATCH 05/10] Move the declarations of _pb_ostream_t and _pb_istream_t before first use. Otherwise Microsoft Visual C++ threats them as C++ classes instead of plain structs, forbidding use in C linkage functions. Thanks to Markus Schwarzenberg for the patch. Update issue 84 Status: Started --- pb_decode.h | 66 +++++++++++++++++++++++++-------------------------- pb_encode.h | 68 ++++++++++++++++++++++++++--------------------------- 2 files changed, 67 insertions(+), 67 deletions(-) diff --git a/pb_decode.h b/pb_decode.h index 3da3f76..98a64cc 100644 --- a/pb_decode.h +++ b/pb_decode.h @@ -12,6 +12,39 @@ extern "C" { #endif +/* Structure for defining custom input streams. You will need to provide + * a callback function to read the bytes from your storage, which can be + * for example a file or a network socket. + * + * The callback must conform to these rules: + * + * 1) Return false on IO errors. This will cause decoding to abort. + * 2) You can use state to store your own data (e.g. buffer pointer), + * and rely on pb_read to verify that no-body reads past bytes_left. + * 3) Your callback may be used with substreams, in which case bytes_left + * is different than from the main stream. Don't use bytes_left to compute + * any pointers. + */ +struct _pb_istream_t +{ +#ifdef PB_BUFFER_ONLY + /* Callback pointer is not used in buffer-only configuration. + * Having an int pointer here allows binary compatibility but + * gives an error if someone tries to assign callback function. + */ + int *callback; +#else + bool (*callback)(pb_istream_t *stream, uint8_t *buf, size_t count); +#endif + + void *state; /* Free field for use by callback implementation */ + size_t bytes_left; + +#ifndef PB_NO_ERRMSG + const char *errmsg; +#endif +}; + /*************************** * Main decoding functions * ***************************/ @@ -66,39 +99,6 @@ pb_istream_t pb_istream_from_buffer(uint8_t *buf, size_t bufsize); */ bool pb_read(pb_istream_t *stream, uint8_t *buf, size_t count); -/* Structure for defining custom input streams. You will need to provide - * a callback function to read the bytes from your storage, which can be - * for example a file or a network socket. - * - * The callback must conform to these rules: - * - * 1) Return false on IO errors. This will cause decoding to abort. - * 2) You can use state to store your own data (e.g. buffer pointer), - * and rely on pb_read to verify that no-body reads past bytes_left. - * 3) Your callback may be used with substreams, in which case bytes_left - * is different than from the main stream. Don't use bytes_left to compute - * any pointers. - */ -struct _pb_istream_t -{ -#ifdef PB_BUFFER_ONLY - /* Callback pointer is not used in buffer-only configuration. - * Having an int pointer here allows binary compatibility but - * gives an error if someone tries to assign callback function. - */ - int *callback; -#else - bool (*callback)(pb_istream_t *stream, uint8_t *buf, size_t count); -#endif - - void *state; /* Free field for use by callback implementation */ - size_t bytes_left; - -#ifndef PB_NO_ERRMSG - const char *errmsg; -#endif -}; - /************************************************ * Helper functions for writing field callbacks * diff --git a/pb_encode.h b/pb_encode.h index 04bdabe..3009820 100644 --- a/pb_encode.h +++ b/pb_encode.h @@ -12,6 +12,40 @@ extern "C" { #endif +/* Structure for defining custom output streams. You will need to provide + * a callback function to write the bytes to your storage, which can be + * for example a file or a network socket. + * + * The callback must conform to these rules: + * + * 1) Return false on IO errors. This will cause encoding to abort. + * 2) You can use state to store your own data (e.g. buffer pointer). + * 3) pb_write will update bytes_written after your callback runs. + * 4) Substreams will modify max_size and bytes_written. Don't use them + * to calculate any pointers. + */ +struct _pb_ostream_t +{ +#ifdef PB_BUFFER_ONLY + /* Callback pointer is not used in buffer-only configuration. + * Having an int pointer here allows binary compatibility but + * gives an error if someone tries to assign callback function. + * Also, NULL pointer marks a 'sizing stream' that does not + * write anything. + */ + int *callback; +#else + bool (*callback)(pb_ostream_t *stream, const uint8_t *buf, size_t count); +#endif + void *state; /* Free field for use by callback implementation. */ + size_t max_size; /* Limit number of output bytes written (or use SIZE_MAX). */ + size_t bytes_written; /* Number of bytes written so far. */ + +#ifndef PB_NO_ERRMSG + const char *errmsg; +#endif +}; + /*************************** * Main encoding functions * ***************************/ @@ -70,40 +104,6 @@ pb_ostream_t pb_ostream_from_buffer(uint8_t *buf, size_t bufsize); */ bool pb_write(pb_ostream_t *stream, const uint8_t *buf, size_t count); -/* Structure for defining custom output streams. You will need to provide - * a callback function to write the bytes to your storage, which can be - * for example a file or a network socket. - * - * The callback must conform to these rules: - * - * 1) Return false on IO errors. This will cause encoding to abort. - * 2) You can use state to store your own data (e.g. buffer pointer). - * 3) pb_write will update bytes_written after your callback runs. - * 4) Substreams will modify max_size and bytes_written. Don't use them - * to calculate any pointers. - */ -struct _pb_ostream_t -{ -#ifdef PB_BUFFER_ONLY - /* Callback pointer is not used in buffer-only configuration. - * Having an int pointer here allows binary compatibility but - * gives an error if someone tries to assign callback function. - * Also, NULL pointer marks a 'sizing stream' that does not - * write anything. - */ - int *callback; -#else - bool (*callback)(pb_ostream_t *stream, const uint8_t *buf, size_t count); -#endif - void *state; /* Free field for use by callback implementation. */ - size_t max_size; /* Limit number of output bytes written (or use SIZE_MAX). */ - size_t bytes_written; /* Number of bytes written so far. */ - -#ifndef PB_NO_ERRMSG - const char *errmsg; -#endif -}; - /************************************************ * Helper functions for writing field callbacks * From 0bbcb7b367998063637ee35c5d13716492cbf6a3 Mon Sep 17 00:00:00 2001 From: Petteri Aimonen Date: Tue, 10 Sep 2013 20:54:29 +0300 Subject: [PATCH 06/10] Compiler options for GCC, clang and tcc --- tests/SConstruct | 67 ++++++++++++++++++++++++++++++++++++----- tests/common/SConscript | 7 +++-- 2 files changed, 65 insertions(+), 9 deletions(-) diff --git a/tests/SConstruct b/tests/SConstruct index 8bbb31d..92cb0c6 100644 --- a/tests/SConstruct +++ b/tests/SConstruct @@ -1,5 +1,26 @@ +Help(''' +Type 'scons' to build and run all the available test cases. +It will automatically detect your platform and C compiler and +build appropriately. + +You can modify the behavious using following options: +CC Name of C compiler +CXX Name of C++ compiler +CCFLAGS Flags to pass to the C compiler +CXXFLAGS Flags to pass to the C++ compiler + +For example, for a clang build, use: +scons CC=clang CXX=clang++ +''') + import os -env = Environment(ENV = {'PATH': os.environ['PATH']}) +env = Environment(ENV = os.environ) + +# Allow overriding the compiler with scons CC=??? +if 'CC' in ARGUMENTS: env.Replace(CC = ARGUMENTS['CC']) +if 'CXX' in ARGUMENTS: env.Replace(CXX = ARGUMENTS['CXX']) +if 'CFLAGS' in ARGUMENTS: env.Append(CCFLAGS = ARGUMENTS['CFLAGS']) +if 'CXXFLAGS' in ARGUMENTS: env.Append(CCFLAGS = ARGUMENTS['CXXFLAGS']) # Add the builders defined in site_init.py add_nanopb_builders(env) @@ -34,22 +55,54 @@ if not env.GetOption('clean'): conf.env.Append(PROTOCPATH = output.strip()) else: conf.env.Append(PROTOCPATH = '/usr/include') - + + # Check if libmudflap is available (only with GCC) + if 'gcc' in env['CC']: + if conf.CheckLib('mudflap'): + conf.env.Append(CCFLAGS = '-fmudflap') + conf.env.Append(LINKFLAGS = '-lmudflap -fmudflap') + # End the config stuff env = conf.Finish() # Initialize the CCFLAGS according to the compiler -if 'cl' in env['CC']: +if 'gcc' in env['CC']: + # GNU Compiler Collection + + # Debug info, warnings as errors + env.Append(CFLAGS = '-ansi -g -O0 -Wall -Werror --coverage -fstack-protector-all') + env.Append(LINKFLAGS = '--coverage') + + # More strict checks on the nanopb core + env.Append(CORECFLAGS = '-pedantic -Wextra -Wcast-qual -Wlogical-op -Wconversion') +elif 'clang' in env['CC']: + # CLang + env.Append(CFLAGS = '-ansi -g -O0 -Wall -Werror') + env.Append(CORECFLAGS = '-pedantic -Wextra -Wcast-qual -Wconversion') +elif 'cl' in env['CC']: # Microsoft Visual C++ # Debug info on, warning level 2 for tests, warnings as errors - env.Append(CCFLAGS = '/Zi /W2 /WX') + env.Append(CFLAGS = '/Zi /W2 /WX') env.Append(LINKFLAGS = '/DEBUG') + # More strict checks on the nanopb core + env.Append(CORECFLAGS = '/W4 /Za') + # PB_RETURN_ERROR triggers C4127 because of while(0) - env.Append(CCFLAGS = '/wd4127') - - + env.Append(CFLAGS = '/wd4127') +elif 'tcc' in env['CC']: + # Tiny C Compiler + env.Append(CFLAGS = '-Wall -Werror -g') + +env.SetDefault(CORECFLAGS = '') + +if 'clang++' in env['CXX']: + env.Append(CXXFLAGS = '-g -O0 -Wall -Werror -Wextra -Wno-missing-field-initializers') +elif 'g++' in env['CXX']: + env.Append(CXXFLAGS = '-g -O0 -Wall -Werror -Wextra -Wno-missing-field-initializers') +elif 'cl' in env['CXX']: + env.Append(CXXFLAGS = '/Zi /W2 /WX') # Now include the SConscript files from all subdirectories SConscript(Glob('*/SConscript'), exports = 'env') diff --git a/tests/common/SConscript b/tests/common/SConscript index ef3cdca..8130c85 100644 --- a/tests/common/SConscript +++ b/tests/common/SConscript @@ -9,6 +9,9 @@ env.NanopbProto("unittestproto") 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") +# These are built using more strict warning flags. +strict = env.Clone() +strict.Append(CFLAGS = strict['CORECFLAGS']) +strict.Object("pb_decode.o", "#../pb_decode.c") +strict.Object("pb_encode.o", "#../pb_encode.c") From e2e9980627810fe0ee2b8f119bcf651f0f318a8a Mon Sep 17 00:00:00 2001 From: Petteri Aimonen Date: Tue, 10 Sep 2013 22:34:54 +0300 Subject: [PATCH 07/10] Move the rest of the tests to scons --- tests/backwards_compatibility/SConscript | 11 ++++++++++ .../backwards_compatibility/alltypes_legacy.c | 2 +- tests/backwards_compatibility/decode_legacy.c | 10 ++++----- tests/backwards_compatibility/encode_legacy.c | 8 +++---- tests/basic_stream/SConscript | 12 +++++++++++ tests/callbacks/SConscript | 14 +++++++++++++ tests/extensions/SConscript | 16 ++++++++++++++ tests/extra_fields/SConscript | 10 +++++++++ .../person_with_extra_field.expected | 14 +++++++++++++ tests/missing_fields/SConscript | 8 +++++++ tests/multiple_files/SConscript | 13 ++++++++++++ tests/multiple_files/test_multiple_files.c | 3 +-- tests/no_messages/SConscript | 7 +++++++ tests/options/SConscript | 9 ++++++++ tests/site_scons/site_init.py | 21 +++++++++++++++++-- tests/special_characters/SConscript | 7 +++++++ .../special_characters/funny-proto+name.proto | 0 17 files changed, 151 insertions(+), 14 deletions(-) create mode 100644 tests/backwards_compatibility/SConscript create mode 100644 tests/basic_stream/SConscript create mode 100644 tests/callbacks/SConscript create mode 100644 tests/extensions/SConscript create mode 100644 tests/extra_fields/SConscript create mode 100644 tests/extra_fields/person_with_extra_field.expected create mode 100644 tests/missing_fields/SConscript create mode 100644 tests/multiple_files/SConscript create mode 100644 tests/no_messages/SConscript create mode 100644 tests/options/SConscript create mode 100644 tests/special_characters/SConscript delete mode 100644 tests/special_characters/funny-proto+name.proto diff --git a/tests/backwards_compatibility/SConscript b/tests/backwards_compatibility/SConscript new file mode 100644 index 0000000..5fb978f --- /dev/null +++ b/tests/backwards_compatibility/SConscript @@ -0,0 +1,11 @@ +# Check that the old generated .pb.c/.pb.h files are still compatible with the +# current version of nanopb. + +Import("env") + +enc = env.Program(["encode_legacy.c", "alltypes_legacy.c", "#common/pb_encode.o"]) +dec = env.Program(["decode_legacy.c", "alltypes_legacy.c", "#common/pb_decode.o"]) + +env.RunTest(enc) +env.RunTest([dec, "encode_legacy.output"]) + diff --git a/tests/backwards_compatibility/alltypes_legacy.c b/tests/backwards_compatibility/alltypes_legacy.c index b144b1e..9134d5e 100644 --- a/tests/backwards_compatibility/alltypes_legacy.c +++ b/tests/backwards_compatibility/alltypes_legacy.c @@ -5,7 +5,7 @@ * incompatible changes made to the generator in future versions. */ -#include "bc_alltypes.pb.h" +#include "alltypes_legacy.h" const char SubMessage_substuff1_default[16] = "1"; const int32_t SubMessage_substuff2_default = 2; diff --git a/tests/backwards_compatibility/decode_legacy.c b/tests/backwards_compatibility/decode_legacy.c index b74172f..315b16e 100644 --- a/tests/backwards_compatibility/decode_legacy.c +++ b/tests/backwards_compatibility/decode_legacy.c @@ -1,16 +1,16 @@ /* 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. + * This is a backwards-compatibility test, using alltypes_legacy.h. + * It is similar to decode_alltypes, but duplicated in order to allow + * decode_alltypes to test any new features introduced later. * - * Run e.g. ./bc_encode | ./bc_decode + * Run e.g. ./encode_legacy | ./decode_legacy */ #include #include #include #include -#include "bc_alltypes.pb.h" +#include "alltypes_legacy.h" #define TEST(x) if (!(x)) { \ printf("Test " #x " failed.\n"); \ diff --git a/tests/backwards_compatibility/encode_legacy.c b/tests/backwards_compatibility/encode_legacy.c index e84f090..0e31309 100644 --- a/tests/backwards_compatibility/encode_legacy.c +++ b/tests/backwards_compatibility/encode_legacy.c @@ -1,14 +1,14 @@ /* 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. + * This is a backwards-compatibility test, using alltypes_legacy.h. + * It is similar to encode_alltypes, but duplicated in order to allow + * encode_alltypes to test any new features introduced later. */ #include #include #include #include -#include "bc_alltypes.pb.h" +#include "alltypes_legacy.h" int main(int argc, char **argv) { diff --git a/tests/basic_stream/SConscript b/tests/basic_stream/SConscript new file mode 100644 index 0000000..17382a9 --- /dev/null +++ b/tests/basic_stream/SConscript @@ -0,0 +1,12 @@ +# Build and run a basic round-trip test using direct stream encoding. + +Import("env") + +enc = env.Program(["encode_stream.c", "#common/person.pb.c", "#common/pb_encode.o"]) +dec = env.Program(["decode_stream.c", "#common/person.pb.c", "#common/pb_decode.o"]) + +env.RunTest(enc) +env.RunTest([dec, "encode_stream.output"]) +env.Decode(["encode_stream.output", "#common/person.proto"], MESSAGE = "Person") +env.Compare(["decode_stream.output", "encode_stream.decoded"]) + diff --git a/tests/callbacks/SConscript b/tests/callbacks/SConscript new file mode 100644 index 0000000..729fd65 --- /dev/null +++ b/tests/callbacks/SConscript @@ -0,0 +1,14 @@ +# Test the functionality of the callback fields. + +Import("env") + +env.NanopbProto("callbacks") +enc = env.Program(["encode_callbacks.c", "callbacks.pb.c", "#common/pb_encode.o"]) +dec = env.Program(["decode_callbacks.c", "callbacks.pb.c", "#common/pb_decode.o"]) + +env.RunTest(enc) +env.RunTest([dec, "encode_callbacks.output"]) + +env.Decode(["encode_callbacks.output", "callbacks.proto"], MESSAGE = "TestMessage") +env.Compare(["decode_callbacks.output", "encode_callbacks.decoded"]) + diff --git a/tests/extensions/SConscript b/tests/extensions/SConscript new file mode 100644 index 0000000..b48d6a6 --- /dev/null +++ b/tests/extensions/SConscript @@ -0,0 +1,16 @@ +# Test the support for extension fields. + +Import("env") + +# We use the files from the alltypes test case +incpath = env.Clone() +incpath.Append(PROTOCPATH = '#alltypes') +incpath.Append(CPPPATH = '#alltypes') + +incpath.NanopbProto("extensions") +enc = incpath.Program(["encode_extensions.c", "extensions.pb.c", "#alltypes/alltypes.pb.o", "#common/pb_encode.o"]) +dec = incpath.Program(["decode_extensions.c", "extensions.pb.c", "#alltypes/alltypes.pb.o", "#common/pb_decode.o"]) + +env.RunTest(enc) +env.RunTest([dec, "encode_extensions.output"]) + diff --git a/tests/extra_fields/SConscript b/tests/extra_fields/SConscript new file mode 100644 index 0000000..a6f0e75 --- /dev/null +++ b/tests/extra_fields/SConscript @@ -0,0 +1,10 @@ +# Test that the decoder properly handles unknown fields in the input. + +Import("env") + +dec = env.GetBuildPath('#basic_buffer/${PROGPREFIX}decode_buffer${PROGSUFFIX}') +env.RunTest('person_with_extra_field.output', [dec, "person_with_extra_field.pb"]) +env.Compare(["person_with_extra_field.output", "person_with_extra_field.expected"]) + +dec2 = env.GetBuildPath('#alltypes/${PROGPREFIX}decode_alltypes${PROGSUFFIX}') +env.RunTest('alltypes_with_extra_fields.output', [dec2, 'alltypes_with_extra_fields.pb']) diff --git a/tests/extra_fields/person_with_extra_field.expected b/tests/extra_fields/person_with_extra_field.expected new file mode 100644 index 0000000..da9c32d --- /dev/null +++ b/tests/extra_fields/person_with_extra_field.expected @@ -0,0 +1,14 @@ +name: "Test Person 99" +id: 99 +email: "test@person.com" +phone { + number: "555-12345678" + type: MOBILE +} +phone { + number: "99-2342" +} +phone { + number: "1234-5678" + type: WORK +} diff --git a/tests/missing_fields/SConscript b/tests/missing_fields/SConscript new file mode 100644 index 0000000..361b550 --- /dev/null +++ b/tests/missing_fields/SConscript @@ -0,0 +1,8 @@ +# Check that the decoder properly detects when required fields are missing. + +Import("env") + +env.NanopbProto("missing_fields") +test = env.Program(["missing_fields.c", "missing_fields.pb.c", "#common/pb_encode.o", "#common/pb_decode.o"]) +env.RunTest(test) + diff --git a/tests/multiple_files/SConscript b/tests/multiple_files/SConscript new file mode 100644 index 0000000..6b4f6b6 --- /dev/null +++ b/tests/multiple_files/SConscript @@ -0,0 +1,13 @@ +# Test that multiple .proto files don't cause name collisions. + +Import("env") + +incpath = env.Clone() +incpath.Append(PROTOCPATH = '#multiple_files') + +incpath.NanopbProto("callbacks") +incpath.NanopbProto("callbacks2") +test = incpath.Program(["test_multiple_files.c", "callbacks.pb.c", "callbacks2.pb.c"]) + +env.RunTest(test) + diff --git a/tests/multiple_files/test_multiple_files.c b/tests/multiple_files/test_multiple_files.c index cb4e16d..05722dc 100644 --- a/tests/multiple_files/test_multiple_files.c +++ b/tests/multiple_files/test_multiple_files.c @@ -1,6 +1,5 @@ /* - * Tests if still compile if typedefs are redfefined in STATIC_ASSERTS when - * proto file includes another poto file + * Tests if this still compiles when multiple .proto files are involved. */ #include diff --git a/tests/no_messages/SConscript b/tests/no_messages/SConscript new file mode 100644 index 0000000..6492e2c --- /dev/null +++ b/tests/no_messages/SConscript @@ -0,0 +1,7 @@ +# Test that a .proto file without any messages compiles fine. + +Import("env") + +env.NanopbProto("no_messages") +env.Object('no_messages.pb.c') + diff --git a/tests/options/SConscript b/tests/options/SConscript new file mode 100644 index 0000000..89a00fa --- /dev/null +++ b/tests/options/SConscript @@ -0,0 +1,9 @@ +# Test that the generator options work as expected. + +Import("env") + +env.NanopbProto("options") +env.Object('options.pb.c') + +env.Match(['options.pb.h', 'options.expected']) + diff --git a/tests/site_scons/site_init.py b/tests/site_scons/site_init.py index b69db64..86e5033 100644 --- a/tests/site_scons/site_init.py +++ b/tests/site_scons/site_init.py @@ -1,5 +1,6 @@ import subprocess import sys +import re try: # Make terminal colors work on windows @@ -13,8 +14,9 @@ def add_nanopb_builders(env): # 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]) + esc = env['ESCAPE'] + dirs = ' '.join(['-I' + esc(env.GetBuildPath(d)) for d in env['PROTOCPATH']]) + return '$PROTOC $PROTOCFLAGS %s -o%s %s' % (dirs, esc(str(target[0])), esc(str(source[0]))) proto_file_builder = Builder(generator = proto_actions, suffix = '.pb', @@ -91,4 +93,19 @@ def add_nanopb_builders(env): suffix = '.equal') env.Append(BUILDERS = {'Compare': compare_builder}) + # Build command that checks that each pattern in source2 is found in source1. + def match_files(target, source, env): + data = open(str(source[0]), 'rU').read() + patterns = open(str(source[1])) + for pattern in patterns: + if pattern.strip() and not re.search(pattern.strip(), data, re.MULTILINE): + print '\033[31m[FAIL]\033[0m Pattern not found in ' + str(source[0]) + ': ' + pattern + return 1 + else: + print '\033[32m[ OK ]\033[0m All patterns found in ' + str(source[0]) + return 0 + + match_builder = Builder(action = match_files, suffix = '.matched') + env.Append(BUILDERS = {'Match': match_builder}) + diff --git a/tests/special_characters/SConscript b/tests/special_characters/SConscript new file mode 100644 index 0000000..05dccae --- /dev/null +++ b/tests/special_characters/SConscript @@ -0,0 +1,7 @@ +# Test that special characters in .proto filenames work. + +Import('env') + +env.Proto("funny-proto+name has.characters.proto") +env.Nanopb("funny-proto+name has.characters.pb.c", "funny-proto+name has.characters.pb") +env.Object("funny-proto+name has.characters.pb.c") diff --git a/tests/special_characters/funny-proto+name.proto b/tests/special_characters/funny-proto+name.proto deleted file mode 100644 index e69de29..0000000 From b9f14bddf778a5ed27e3289b90a0657fec3e1a53 Mon Sep 17 00:00:00 2001 From: Petteri Aimonen Date: Wed, 11 Sep 2013 13:16:20 +0300 Subject: [PATCH 08/10] Make all the tests ANSI C compatible. --- tests/SConstruct | 10 +++--- tests/backwards_compatibility/encode_legacy.c | 32 ++++++++++-------- tests/basic_stream/decode_stream.c | 9 ++--- tests/basic_stream/encode_stream.c | 5 ++- tests/callbacks/decode_callbacks.c | 16 +++++---- tests/callbacks/encode_callbacks.c | 14 +++++--- tests/extensions/decode_extensions.c | 33 ++++++++++++++----- tests/extensions/encode_extensions.c | 26 +++++++++++---- tests/missing_fields/missing_fields.c | 9 ++--- .../funny-proto+name has.characters.proto | 0 10 files changed, 100 insertions(+), 54 deletions(-) create mode 100644 tests/special_characters/funny-proto+name has.characters.proto diff --git a/tests/SConstruct b/tests/SConstruct index 92cb0c6..26a513d 100644 --- a/tests/SConstruct +++ b/tests/SConstruct @@ -70,15 +70,15 @@ if 'gcc' in env['CC']: # GNU Compiler Collection # Debug info, warnings as errors - env.Append(CFLAGS = '-ansi -g -O0 -Wall -Werror --coverage -fstack-protector-all') + env.Append(CFLAGS = '-ansi -pedantic -g -O0 -Wall -Werror --coverage -fstack-protector-all') env.Append(LINKFLAGS = '--coverage') # More strict checks on the nanopb core - env.Append(CORECFLAGS = '-pedantic -Wextra -Wcast-qual -Wlogical-op -Wconversion') + env.Append(CORECFLAGS = '-Wextra -Wcast-qual -Wlogical-op -Wconversion') elif 'clang' in env['CC']: # CLang - env.Append(CFLAGS = '-ansi -g -O0 -Wall -Werror') - env.Append(CORECFLAGS = '-pedantic -Wextra -Wcast-qual -Wconversion') + env.Append(CFLAGS = '-ansi -pedantic -g -O0 -Wall -Werror') + env.Append(CORECFLAGS = ' -Wextra -Wcast-qual -Wconversion') elif 'cl' in env['CC']: # Microsoft Visual C++ @@ -87,7 +87,7 @@ elif 'cl' in env['CC']: env.Append(LINKFLAGS = '/DEBUG') # More strict checks on the nanopb core - env.Append(CORECFLAGS = '/W4 /Za') + env.Append(CORECFLAGS = '/W4') # PB_RETURN_ERROR triggers C4127 because of while(0) env.Append(CFLAGS = '/wd4127') diff --git a/tests/backwards_compatibility/encode_legacy.c b/tests/backwards_compatibility/encode_legacy.c index 0e31309..5c9d41b 100644 --- a/tests/backwards_compatibility/encode_legacy.c +++ b/tests/backwards_compatibility/encode_legacy.c @@ -9,6 +9,7 @@ #include #include #include "alltypes_legacy.h" +#include "test_helpers.h" int main(int argc, char **argv) { @@ -113,19 +114,22 @@ int main(int argc, char **argv) } 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 */ + + { + 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)) + { + SET_BINARY_MODE(stdout); + fwrite(buffer, 1, stream.bytes_written, stdout); + return 0; /* Success */ + } + else + { + fprintf(stderr, "Encoding failed!\n"); + return 1; /* Failure */ + } } } diff --git a/tests/basic_stream/decode_stream.c b/tests/basic_stream/decode_stream.c index 2142977..667bf3c 100644 --- a/tests/basic_stream/decode_stream.c +++ b/tests/basic_stream/decode_stream.c @@ -4,6 +4,7 @@ #include #include #include "person.pb.h" +#include "test_helpers.h" /* This function is called once from main(), it handles the decoding and printing. @@ -69,10 +70,10 @@ bool callback(pb_istream_t *stream, uint8_t *buf, size_t count) 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}; + pb_istream_t stream = {&callback, NULL, SIZE_MAX}; + stream.state = stdin; + SET_BINARY_MODE(stdin); + if (!print_person(&stream)) { printf("Parsing failed: %s\n", PB_GET_ERROR(&stream)); diff --git a/tests/basic_stream/encode_stream.c b/tests/basic_stream/encode_stream.c index fd25c6c..7f571c4 100644 --- a/tests/basic_stream/encode_stream.c +++ b/tests/basic_stream/encode_stream.c @@ -4,6 +4,7 @@ #include #include #include "person.pb.h" +#include "test_helpers.h" /* This binds the pb_ostream_t into the stdout stream */ bool streamcallback(pb_ostream_t *stream, const uint8_t *buf, size_t count) @@ -22,7 +23,9 @@ int main() }}; /* Prepare the stream, output goes directly to stdout */ - pb_ostream_t stream = {&streamcallback, stdout, SIZE_MAX, 0}; + pb_ostream_t stream = {&streamcallback, NULL, SIZE_MAX, 0}; + stream.state = stdout; + SET_BINARY_MODE(stdout); /* Now encode it and check if we succeeded. */ if (pb_encode(&stream, Person_fields, &person)) diff --git a/tests/callbacks/decode_callbacks.c b/tests/callbacks/decode_callbacks.c index b505692..c8daed2 100644 --- a/tests/callbacks/decode_callbacks.c +++ b/tests/callbacks/decode_callbacks.c @@ -5,6 +5,7 @@ #include #include #include "callbacks.pb.h" +#include "test_helpers.h" bool print_string(pb_istream_t *stream, const pb_field_t *field, void **arg) { @@ -50,21 +51,24 @@ bool print_fixed64(pb_istream_t *stream, const pb_field_t *field, void **arg) if (!pb_decode_fixed64(stream, &value)) return false; - printf((char*)*arg, (long long)value); + printf((char*)*arg, (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); - + size_t length; + pb_istream_t stream; /* 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 testmessage = {{{NULL}}}; + + SET_BINARY_MODE(stdin); + length = fread(buffer, 1, 1024, stdin); + stream = pb_istream_from_buffer(buffer, length); testmessage.submsg.stringvalue.funcs.decode = &print_string; testmessage.submsg.stringvalue.arg = "submsg {\n stringvalue: \"%s\"\n"; @@ -73,7 +77,7 @@ int main() 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.submsg.fixed64value.arg = " fixed64value: %ld\n}\n"; testmessage.stringvalue.funcs.decode = &print_string; testmessage.stringvalue.arg = "stringvalue: \"%s\"\n"; diff --git a/tests/callbacks/encode_callbacks.c b/tests/callbacks/encode_callbacks.c index 3bb6a45..6cb67b1 100644 --- a/tests/callbacks/encode_callbacks.c +++ b/tests/callbacks/encode_callbacks.c @@ -4,6 +4,7 @@ #include #include #include "callbacks.pb.h" +#include "test_helpers.h" bool encode_string(pb_ostream_t *stream, const pb_field_t *field, void * const *arg) { @@ -25,19 +26,21 @@ bool encode_int32(pb_ostream_t *stream, const pb_field_t *field, void * const *a bool encode_fixed32(pb_ostream_t *stream, const pb_field_t *field, void * const *arg) { + uint32_t value = 42; + 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) { + uint64_t value = 42; + if (!pb_encode_tag_for_field(stream, field)) return false; - uint64_t value = 42; return pb_encode_fixed64(stream, &value); } @@ -60,8 +63,10 @@ bool encode_repeatedstring(pb_ostream_t *stream, const pb_field_t *field, void * int main() { uint8_t buffer[1024]; - pb_ostream_t stream = pb_ostream_from_buffer(buffer, 1024); - TestMessage testmessage = {}; + pb_ostream_t stream; + TestMessage testmessage = {{{NULL}}}; + + stream = pb_ostream_from_buffer(buffer, 1024); testmessage.stringvalue.funcs.encode = &encode_string; testmessage.int32value.funcs.encode = &encode_int32; @@ -79,6 +84,7 @@ int main() if (!pb_encode(&stream, TestMessage_fields, &testmessage)) return 1; + SET_BINARY_MODE(stdout); if (fwrite(buffer, stream.bytes_written, 1, stdout) != 1) return 2; diff --git a/tests/extensions/decode_extensions.c b/tests/extensions/decode_extensions.c index ef6a022..f8ebbde 100644 --- a/tests/extensions/decode_extensions.c +++ b/tests/extensions/decode_extensions.c @@ -6,6 +6,7 @@ #include #include "alltypes.pb.h" #include "extensions.pb.h" +#include "test_helpers.h" #define TEST(x) if (!(x)) { \ printf("Test " #x " failed.\n"); \ @@ -15,25 +16,39 @@ 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 = {}; + size_t count; + pb_istream_t stream; + AllTypes alltypes = {0}; 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}; + pb_extension_t ext1; + ExtensionMessage extensionfield2; + pb_extension_t ext2; + + /* Read the message data */ + SET_BINARY_MODE(stdin); + count = fread(buffer, 1, sizeof(buffer), stdin); + stream = pb_istream_from_buffer(buffer, count); + + /* Add the extensions */ + alltypes.extensions = &ext1; + + ext1.type = &AllTypes_extensionfield1; + ext1.dest = &extensionfield1; ext1.next = &ext2; + ext2.type = &ExtensionMessage_AllTypes_extensionfield2; + ext2.dest = &extensionfield2; + ext2.next = NULL; + + /* Decode the message */ if (!pb_decode(&stream, AllTypes_fields, &alltypes)) { printf("Parsing failed: %s\n", PB_GET_ERROR(&stream)); return 1; } + /* Check that the extensions decoded properly */ TEST(extensionfield1 == 12345) TEST(strcmp(extensionfield2.test1, "test") == 0) TEST(extensionfield2.test2 == 54321) diff --git a/tests/extensions/encode_extensions.c b/tests/extensions/encode_extensions.c index 8857f14..dee3597 100644 --- a/tests/extensions/encode_extensions.c +++ b/tests/extensions/encode_extensions.c @@ -7,25 +7,37 @@ #include #include "alltypes.pb.h" #include "extensions.pb.h" +#include "test_helpers.h" int main(int argc, char **argv) { - AllTypes alltypes = {}; + uint8_t buffer[1024]; + pb_ostream_t stream; + AllTypes alltypes = {0}; int32_t extensionfield1 = 12345; - pb_extension_t ext1 = {&AllTypes_extensionfield1, &extensionfield1, NULL}; + pb_extension_t ext1; + ExtensionMessage extensionfield2 = {"test", 54321}; + pb_extension_t ext2; + + /* Set up the extensions */ alltypes.extensions = &ext1; - ExtensionMessage extensionfield2 = {"test", 54321}; - pb_extension_t ext2 = {&ExtensionMessage_AllTypes_extensionfield2, &extensionfield2, NULL}; + ext1.type = &AllTypes_extensionfield1; + ext1.dest = &extensionfield1; ext1.next = &ext2; - uint8_t buffer[1024]; - pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer)); + ext2.type = &ExtensionMessage_AllTypes_extensionfield2; + ext2.dest = &extensionfield2; + ext2.next = NULL; + + /* Set up the output stream */ + stream = pb_ostream_from_buffer(buffer, sizeof(buffer)); - /* Now encode it and check if we succeeded. */ + /* Now encode the message and check if we succeeded. */ if (pb_encode(&stream, AllTypes_fields, &alltypes)) { + SET_BINARY_MODE(stdout); fwrite(buffer, 1, stream.bytes_written, stdout); return 0; /* Success */ } diff --git a/tests/missing_fields/missing_fields.c b/tests/missing_fields/missing_fields.c index 2774184..b9a273a 100644 --- a/tests/missing_fields/missing_fields.c +++ b/tests/missing_fields/missing_fields.c @@ -7,12 +7,13 @@ int main() { - uint8_t buffer[512] = {}; + uint8_t buffer[512]; /* Create a message with one missing field */ { - MissingField msg = {}; + MissingField msg = {0}; pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer)); + if (!pb_encode(&stream, MissingField_fields, &msg)) { printf("Encode failed.\n"); @@ -22,7 +23,7 @@ int main() /* Test that it decodes properly if we don't require that field */ { - MissingField msg = {}; + MissingField msg = {0}; pb_istream_t stream = pb_istream_from_buffer(buffer, sizeof(buffer)); if (!pb_decode(&stream, MissingField_fields, &msg)) @@ -34,7 +35,7 @@ int main() /* Test that it does *not* decode properly if we require the field */ { - AllFields msg = {}; + AllFields msg = {0}; pb_istream_t stream = pb_istream_from_buffer(buffer, sizeof(buffer)); if (pb_decode(&stream, AllFields_fields, &msg)) diff --git a/tests/special_characters/funny-proto+name has.characters.proto b/tests/special_characters/funny-proto+name has.characters.proto new file mode 100644 index 0000000..e69de29 From d395768c8d3e63125c15950434fa255fb8c57717 Mon Sep 17 00:00:00 2001 From: Petteri Aimonen Date: Wed, 11 Sep 2013 13:42:56 +0300 Subject: [PATCH 09/10] Windows build fixes --- tests/alltypes/decode_alltypes.c | 11 ++++++++--- tests/alltypes/encode_alltypes.c | 2 ++ tests/callbacks/decode_callbacks.c | 2 +- tests/extensions/SConscript | 4 ++-- 4 files changed, 13 insertions(+), 6 deletions(-) diff --git a/tests/alltypes/decode_alltypes.c b/tests/alltypes/decode_alltypes.c index 55d025c..ee2e115 100644 --- a/tests/alltypes/decode_alltypes.c +++ b/tests/alltypes/decode_alltypes.c @@ -8,6 +8,7 @@ #include #include #include "alltypes.pb.h" +#include "test_helpers.h" #define TEST(x) if (!(x)) { \ printf("Test " #x " failed.\n"); \ @@ -176,15 +177,19 @@ bool check_alltypes(pb_istream_t *stream, int mode) int main(int argc, char **argv) { + uint8_t buffer[1024]; + size_t count; + pb_istream_t stream; + /* 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); + SET_BINARY_MODE(stdin); + 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); + stream = pb_istream_from_buffer(buffer, count); /* Decode and print out the stuff */ if (!check_alltypes(&stream, mode)) diff --git a/tests/alltypes/encode_alltypes.c b/tests/alltypes/encode_alltypes.c index 802e157..88fc10f 100644 --- a/tests/alltypes/encode_alltypes.c +++ b/tests/alltypes/encode_alltypes.c @@ -6,6 +6,7 @@ #include #include #include "alltypes.pb.h" +#include "test_helpers.h" int main(int argc, char **argv) { @@ -120,6 +121,7 @@ int main(int argc, char **argv) /* Now encode it and check if we succeeded. */ if (pb_encode(&stream, AllTypes_fields, &alltypes)) { + SET_BINARY_MODE(stdout); fwrite(buffer, 1, stream.bytes_written, stdout); return 0; /* Success */ } diff --git a/tests/callbacks/decode_callbacks.c b/tests/callbacks/decode_callbacks.c index c8daed2..45724d0 100644 --- a/tests/callbacks/decode_callbacks.c +++ b/tests/callbacks/decode_callbacks.c @@ -86,7 +86,7 @@ int main() 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.fixed64value.arg = "fixed64value: %ld\n"; testmessage.repeatedstring.funcs.decode = &print_string; testmessage.repeatedstring.arg = "repeatedstring: \"%s\"\n"; diff --git a/tests/extensions/SConscript b/tests/extensions/SConscript index b48d6a6..f632a9a 100644 --- a/tests/extensions/SConscript +++ b/tests/extensions/SConscript @@ -8,8 +8,8 @@ incpath.Append(PROTOCPATH = '#alltypes') incpath.Append(CPPPATH = '#alltypes') incpath.NanopbProto("extensions") -enc = incpath.Program(["encode_extensions.c", "extensions.pb.c", "#alltypes/alltypes.pb.o", "#common/pb_encode.o"]) -dec = incpath.Program(["decode_extensions.c", "extensions.pb.c", "#alltypes/alltypes.pb.o", "#common/pb_decode.o"]) +enc = incpath.Program(["encode_extensions.c", "extensions.pb.c", "#alltypes/alltypes.pb$OBJSUFFIX", "#common/pb_encode.o"]) +dec = incpath.Program(["decode_extensions.c", "extensions.pb.c", "#alltypes/alltypes.pb$OBJSUFFIX", "#common/pb_decode.o"]) env.RunTest(enc) env.RunTest([dec, "encode_extensions.output"]) From 9f93d39f728c3e87b0ab482aa604c5cad4b1c86e Mon Sep 17 00:00:00 2001 From: Petteri Aimonen Date: Wed, 11 Sep 2013 14:55:56 +0300 Subject: [PATCH 10/10] Add tests for different compilation options --- tests/buffer_only/SConscript | 23 +++++++ tests/cxx_main_program/SConscript | 12 ++-- tests/field_size_16/SConscript | 24 ++++++++ tests/field_size_16/alltypes.options | 3 + tests/field_size_16/alltypes.proto | 90 ++++++++++++++++++++++++++++ tests/field_size_32/SConscript | 24 ++++++++ tests/field_size_32/alltypes.options | 3 + tests/field_size_32/alltypes.proto | 90 ++++++++++++++++++++++++++++ tests/no_errmsg/SConscript | 23 +++++++ 9 files changed, 286 insertions(+), 6 deletions(-) create mode 100644 tests/buffer_only/SConscript create mode 100644 tests/field_size_16/SConscript create mode 100644 tests/field_size_16/alltypes.options create mode 100644 tests/field_size_16/alltypes.proto create mode 100644 tests/field_size_32/SConscript create mode 100644 tests/field_size_32/alltypes.options create mode 100644 tests/field_size_32/alltypes.proto create mode 100644 tests/no_errmsg/SConscript diff --git a/tests/buffer_only/SConscript b/tests/buffer_only/SConscript new file mode 100644 index 0000000..0770b2f --- /dev/null +++ b/tests/buffer_only/SConscript @@ -0,0 +1,23 @@ +# Run the alltypes test case, but compile with PB_BUFFER_ONLY=1 + +Import("env") + +# Take copy of the files for custom build. +c = Copy("$TARGET", "$SOURCE") +env.Command("pb_encode.c", "#../pb_encode.c", c) +env.Command("pb_decode.c", "#../pb_decode.c", c) +env.Command("alltypes.pb.h", "#alltypes/alltypes.pb.h", c) +env.Command("alltypes.pb.c", "#alltypes/alltypes.pb.c", c) +env.Command("encode_alltypes.c", "#alltypes/encode_alltypes.c", c) +env.Command("decode_alltypes.c", "#alltypes/decode_alltypes.c", c) + +# Define the compilation options +opts = env.Clone() +opts.Append(CPPDEFINES = {'PB_BUFFER_ONLY': 1}) + +# Now build and run the test normally. +enc = opts.Program(["encode_alltypes.c", "alltypes.pb.c", "pb_encode.c"]) +dec = opts.Program(["decode_alltypes.c", "alltypes.pb.c", "pb_decode.c"]) + +env.RunTest(enc) +env.RunTest([dec, "encode_alltypes.output"]) diff --git a/tests/cxx_main_program/SConscript b/tests/cxx_main_program/SConscript index 0d0a25c..055c5ae 100644 --- a/tests/cxx_main_program/SConscript +++ b/tests/cxx_main_program/SConscript @@ -5,12 +5,12 @@ Import("env") # Copy the files to .cxx extension in order to force C++ build. c = Copy("$TARGET", "$SOURCE") -Command("pb_encode.cxx", "#../pb_encode.c", c) -Command("pb_decode.cxx", "#../pb_decode.c", c) -Command("alltypes.pb.h", "#alltypes/alltypes.pb.h", c) -Command("alltypes.pb.cxx", "#alltypes/alltypes.pb.c", c) -Command("encode_alltypes.cxx", "#alltypes/encode_alltypes.c", c) -Command("decode_alltypes.cxx", "#alltypes/decode_alltypes.c", c) +env.Command("pb_encode.cxx", "#../pb_encode.c", c) +env.Command("pb_decode.cxx", "#../pb_decode.c", c) +env.Command("alltypes.pb.h", "#alltypes/alltypes.pb.h", c) +env.Command("alltypes.pb.cxx", "#alltypes/alltypes.pb.c", c) +env.Command("encode_alltypes.cxx", "#alltypes/encode_alltypes.c", c) +env.Command("decode_alltypes.cxx", "#alltypes/decode_alltypes.c", c) # Now build and run the test normally. enc = env.Program(["encode_alltypes.cxx", "alltypes.pb.cxx", "pb_encode.cxx"]) diff --git a/tests/field_size_16/SConscript b/tests/field_size_16/SConscript new file mode 100644 index 0000000..48d08e8 --- /dev/null +++ b/tests/field_size_16/SConscript @@ -0,0 +1,24 @@ +# Run the alltypes test case, but compile with PB_FIELD_16BIT=1. +# Also the .proto file has been modified to have high indexes. + +Import("env") + +# Take copy of the files for custom build. +c = Copy("$TARGET", "$SOURCE") +env.Command("pb_encode.c", "#../pb_encode.c", c) +env.Command("pb_decode.c", "#../pb_decode.c", c) +env.Command("encode_alltypes.c", "#alltypes/encode_alltypes.c", c) +env.Command("decode_alltypes.c", "#alltypes/decode_alltypes.c", c) + +env.NanopbProto("alltypes") + +# Define the compilation options +opts = env.Clone() +opts.Append(CPPDEFINES = {'PB_FIELD_16BIT': 1}) + +# Now build and run the test normally. +enc = opts.Program(["encode_alltypes.c", "alltypes.pb.c", "pb_encode.c"]) +dec = opts.Program(["decode_alltypes.c", "alltypes.pb.c", "pb_decode.c"]) + +env.RunTest(enc) +env.RunTest([dec, "encode_alltypes.output"]) diff --git a/tests/field_size_16/alltypes.options b/tests/field_size_16/alltypes.options new file mode 100644 index 0000000..b31e3cf --- /dev/null +++ b/tests/field_size_16/alltypes.options @@ -0,0 +1,3 @@ +* max_size:16 +* max_count:5 + diff --git a/tests/field_size_16/alltypes.proto b/tests/field_size_16/alltypes.proto new file mode 100644 index 0000000..b981760 --- /dev/null +++ b/tests/field_size_16/alltypes.proto @@ -0,0 +1,90 @@ +message SubMessage { + required string substuff1 = 1 [default = "1"]; + required int32 substuff2 = 2 [default = 2]; + optional fixed32 substuff3 = 65535 [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 = 10031; + repeated sfixed64 rep_sfixed64= 10032; + repeated double rep_double = 10033; + + repeated string rep_string = 10034; + repeated bytes rep_bytes = 10035; + repeated SubMessage rep_submsg = 10036; + repeated MyEnum rep_enum = 10037; + repeated EmptyMessage rep_emptymsg = 10038; + + optional int32 opt_int32 = 10041 [default = 4041]; + optional int64 opt_int64 = 10042 [default = 4042]; + optional uint32 opt_uint32 = 10043 [default = 4043]; + optional uint64 opt_uint64 = 10044 [default = 4044]; + optional sint32 opt_sint32 = 10045 [default = 4045]; + optional sint64 opt_sint64 = 10046 [default = 4046]; + optional bool opt_bool = 10047 [default = false]; + + optional fixed32 opt_fixed32 = 10048 [default = 4048]; + optional sfixed32 opt_sfixed32= 10049 [default = 4049]; + optional float opt_float = 10050 [default = 4050]; + + optional fixed64 opt_fixed64 = 10051 [default = 4051]; + optional sfixed64 opt_sfixed64= 10052 [default = 4052]; + optional double opt_double = 10053 [default = 4053]; + + optional string opt_string = 10054 [default = "4054"]; + optional bytes opt_bytes = 10055 [default = "4055"]; + optional SubMessage opt_submsg = 10056; + optional MyEnum opt_enum = 10057 [default = Second]; + optional EmptyMessage opt_emptymsg = 10058; + + // 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 = 10099; +} + diff --git a/tests/field_size_32/SConscript b/tests/field_size_32/SConscript new file mode 100644 index 0000000..a8584dc --- /dev/null +++ b/tests/field_size_32/SConscript @@ -0,0 +1,24 @@ +# Run the alltypes test case, but compile with PB_FIELD_32BIT=1. +# Also the .proto file has been modified to have high indexes. + +Import("env") + +# Take copy of the files for custom build. +c = Copy("$TARGET", "$SOURCE") +env.Command("pb_encode.c", "#../pb_encode.c", c) +env.Command("pb_decode.c", "#../pb_decode.c", c) +env.Command("encode_alltypes.c", "#alltypes/encode_alltypes.c", c) +env.Command("decode_alltypes.c", "#alltypes/decode_alltypes.c", c) + +env.NanopbProto("alltypes") + +# Define the compilation options +opts = env.Clone() +opts.Append(CPPDEFINES = {'PB_FIELD_32BIT': 1}) + +# Now build and run the test normally. +enc = opts.Program(["encode_alltypes.c", "alltypes.pb.c", "pb_encode.c"]) +dec = opts.Program(["decode_alltypes.c", "alltypes.pb.c", "pb_decode.c"]) + +env.RunTest(enc) +env.RunTest([dec, "encode_alltypes.output"]) diff --git a/tests/field_size_32/alltypes.options b/tests/field_size_32/alltypes.options new file mode 100644 index 0000000..b31e3cf --- /dev/null +++ b/tests/field_size_32/alltypes.options @@ -0,0 +1,3 @@ +* max_size:16 +* max_count:5 + diff --git a/tests/field_size_32/alltypes.proto b/tests/field_size_32/alltypes.proto new file mode 100644 index 0000000..3d1d856 --- /dev/null +++ b/tests/field_size_32/alltypes.proto @@ -0,0 +1,90 @@ +message SubMessage { + required string substuff1 = 1 [default = "1"]; + required int32 substuff2 = 2 [default = 2]; + optional fixed32 substuff3 = 12365535 [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 = 10031; + repeated sfixed64 rep_sfixed64= 10032; + repeated double rep_double = 10033; + + repeated string rep_string = 10034; + repeated bytes rep_bytes = 10035; + repeated SubMessage rep_submsg = 10036; + repeated MyEnum rep_enum = 10037; + repeated EmptyMessage rep_emptymsg = 10038; + + optional int32 opt_int32 = 10041 [default = 4041]; + optional int64 opt_int64 = 10042 [default = 4042]; + optional uint32 opt_uint32 = 10043 [default = 4043]; + optional uint64 opt_uint64 = 10044 [default = 4044]; + optional sint32 opt_sint32 = 10045 [default = 4045]; + optional sint64 opt_sint64 = 10046 [default = 4046]; + optional bool opt_bool = 10047 [default = false]; + + optional fixed32 opt_fixed32 = 10048 [default = 4048]; + optional sfixed32 opt_sfixed32= 10049 [default = 4049]; + optional float opt_float = 10050 [default = 4050]; + + optional fixed64 opt_fixed64 = 10051 [default = 4051]; + optional sfixed64 opt_sfixed64= 10052 [default = 4052]; + optional double opt_double = 10053 [default = 4053]; + + optional string opt_string = 10054 [default = "4054"]; + optional bytes opt_bytes = 10055 [default = "4055"]; + optional SubMessage opt_submsg = 10056; + optional MyEnum opt_enum = 10057 [default = Second]; + optional EmptyMessage opt_emptymsg = 10058; + + // 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 = 13432099; +} + diff --git a/tests/no_errmsg/SConscript b/tests/no_errmsg/SConscript new file mode 100644 index 0000000..870e894 --- /dev/null +++ b/tests/no_errmsg/SConscript @@ -0,0 +1,23 @@ +# Run the alltypes test case, but compile with PB_NO_ERRMSG=1 + +Import("env") + +# Take copy of the files for custom build. +c = Copy("$TARGET", "$SOURCE") +env.Command("pb_encode.c", "#../pb_encode.c", c) +env.Command("pb_decode.c", "#../pb_decode.c", c) +env.Command("alltypes.pb.h", "#alltypes/alltypes.pb.h", c) +env.Command("alltypes.pb.c", "#alltypes/alltypes.pb.c", c) +env.Command("encode_alltypes.c", "#alltypes/encode_alltypes.c", c) +env.Command("decode_alltypes.c", "#alltypes/decode_alltypes.c", c) + +# Define the compilation options +opts = env.Clone() +opts.Append(CPPDEFINES = {'PB_NO_ERRMSG': 1}) + +# Now build and run the test normally. +enc = opts.Program(["encode_alltypes.c", "alltypes.pb.c", "pb_encode.c"]) +dec = opts.Program(["decode_alltypes.c", "alltypes.pb.c", "pb_decode.c"]) + +env.RunTest(enc) +env.RunTest([dec, "encode_alltypes.output"])