aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPetteri Aimonen <jpa@git.mail.kapsi.fi>2013-09-11 16:13:19 +0300
committerPetteri Aimonen <jpa@git.mail.kapsi.fi>2013-09-11 16:13:19 +0300
commit61ad04afd5236e2a6a0d4b4f2caa3bab4a820c99 (patch)
treebeea1aa405bb022927fc0eb5b8f4982083b68458
parent5b9ad17dc2014d7506a7dde92281d8c36a1433e4 (diff)
parent9f93d39f728c3e87b0ab482aa604c5cad4b1c86e (diff)
Merge branch 'dev_tests_using_scons'
-rw-r--r--.gitignore20
-rw-r--r--compat/pb_syshdr.h94
-rw-r--r--pb.h11
-rw-r--r--tests/Makefile143
-rw-r--r--tests/SConstruct109
-rw-r--r--tests/alltypes/SConscript12
-rw-r--r--tests/alltypes/alltypes.options (renamed from tests/alltypes.options)0
-rw-r--r--tests/alltypes/alltypes.proto (renamed from tests/alltypes.proto)0
-rw-r--r--tests/alltypes/decode_alltypes.c (renamed from tests/test_decode3.c)11
-rw-r--r--tests/alltypes/encode_alltypes.c (renamed from tests/test_encode3.c)28
-rw-r--r--tests/backwards_compatibility/SConscript11
-rw-r--r--tests/backwards_compatibility/alltypes_legacy.c (renamed from tests/bc_alltypes.pb.c)2
-rw-r--r--tests/backwards_compatibility/alltypes_legacy.h (renamed from tests/bc_alltypes.pb.h)0
-rw-r--r--tests/backwards_compatibility/decode_legacy.c (renamed from tests/bc_decode.c)10
-rw-r--r--tests/backwards_compatibility/encode_legacy.c (renamed from tests/bc_encode.c)40
-rw-r--r--tests/basic_buffer/SConscript12
-rw-r--r--tests/basic_buffer/decode_buffer.c (renamed from tests/test_decode1.c)11
-rw-r--r--tests/basic_buffer/encode_buffer.c (renamed from tests/test_encode1.c)11
-rw-r--r--tests/basic_stream/SConscript12
-rw-r--r--tests/basic_stream/decode_stream.c (renamed from tests/test_decode2.c)9
-rw-r--r--tests/basic_stream/encode_stream.c (renamed from tests/test_encode2.c)5
-rw-r--r--tests/buffer_only/SConscript23
-rw-r--r--tests/callbacks/SConscript14
-rw-r--r--tests/callbacks/callbacks.proto (renamed from tests/callbacks.proto)0
-rw-r--r--tests/callbacks/decode_callbacks.c (renamed from tests/test_decode_callbacks.c)18
-rw-r--r--tests/callbacks/encode_callbacks.c (renamed from tests/test_encode_callbacks.c)14
-rw-r--r--tests/common/SConscript17
-rw-r--r--tests/common/person.proto (renamed from tests/person.proto)0
-rw-r--r--tests/common/test_helpers.h17
-rw-r--r--tests/common/unittestproto.proto (renamed from tests/unittestproto.proto)0
-rw-r--r--tests/common/unittests.h (renamed from tests/unittests.h)0
-rw-r--r--tests/cxx_main_program/SConscript20
-rw-r--r--tests/decode_unittests/SConscript4
-rw-r--r--tests/decode_unittests/decode_unittests.c (renamed from tests/decode_unittests.c)2
-rw-r--r--tests/encode_unittests/SConscript5
-rw-r--r--tests/encode_unittests/encode_unittests.c (renamed from tests/encode_unittests.c)0
-rw-r--r--tests/extensions/SConscript16
-rw-r--r--tests/extensions/decode_extensions.c58
-rw-r--r--tests/extensions/encode_extensions.c (renamed from tests/test_encode_extensions.c)26
-rw-r--r--tests/extensions/extensions.options (renamed from tests/extensions.options)0
-rw-r--r--tests/extensions/extensions.proto (renamed from tests/extensions.proto)0
-rw-r--r--tests/extra_fields/SConscript10
-rw-r--r--tests/extra_fields/alltypes_with_extra_fields.pb (renamed from tests/alltypes_with_extra_fields.pb)bin523 -> 523 bytes
-rw-r--r--tests/extra_fields/person_with_extra_field.expected14
-rw-r--r--tests/extra_fields/person_with_extra_field.pb (renamed from tests/person_with_extra_field.pb)bin90 -> 90 bytes
-rw-r--r--tests/field_size_16/SConscript24
-rw-r--r--tests/field_size_16/alltypes.options3
-rw-r--r--tests/field_size_16/alltypes.proto90
-rw-r--r--tests/field_size_32/SConscript24
-rw-r--r--tests/field_size_32/alltypes.options3
-rw-r--r--tests/field_size_32/alltypes.proto90
-rw-r--r--tests/missing_fields/SConscript8
-rw-r--r--tests/missing_fields/missing_fields.c (renamed from tests/test_missing_fields.c)9
-rw-r--r--tests/missing_fields/missing_fields.proto (renamed from tests/missing_fields.proto)0
-rw-r--r--tests/multiple_files/SConscript13
-rw-r--r--tests/multiple_files/callbacks.proto16
-rw-r--r--tests/multiple_files/callbacks2.proto (renamed from tests/callbacks2.proto)0
-rw-r--r--tests/multiple_files/test_multiple_files.c12
-rw-r--r--tests/no_errmsg/SConscript23
-rw-r--r--tests/no_messages/SConscript7
-rw-r--r--tests/no_messages/no_messages.proto (renamed from tests/no_messages.proto)0
-rw-r--r--tests/options/SConscript9
-rw-r--r--tests/options/options.expected (renamed from tests/options.expected)0
-rw-r--r--tests/options/options.proto (renamed from tests/options.proto)0
-rw-r--r--tests/site_scons/site_init.py111
-rw-r--r--tests/special_characters/SConscript7
-rw-r--r--tests/special_characters/funny-proto+name has.characters.proto (renamed from tests/funny-proto+name.proto)0
-rw-r--r--tests/test_decode_extensions.c43
-rw-r--r--tests/test_multiple_files.c13
-rw-r--r--tests/testperson.pb3
70 files changed, 1026 insertions, 291 deletions
diff --git a/.gitignore b/.gitignore
index dec8b00e..b83afeff 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/compat/pb_syshdr.h b/compat/pb_syshdr.h
new file mode 100644
index 00000000..b69a1671
--- /dev/null
+++ b/compat/pb_syshdr.h
@@ -0,0 +1,94 @@
+/* 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 */
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#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;
+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;
+#endif
+
+/* stddef.h subset */
+#ifdef HAVE_STDDEF_H
+#include <stddef.h>
+#else
+
+typedef uint32_t size_t;
+#define offsetof(st, m) ((size_t)(&((st *)0)->m))
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#endif
+
+/* stdbool.h subset */
+#ifdef HAVE_STDBOOL_H
+#include <stdbool.h>
+#else
+
+#ifndef __cplusplus
+typedef int bool;
+#define false 0
+#define true 1
+#endif
+
+#endif
+
+/* string.h subset */
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+
+/* 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
+
+#endif
diff --git a/pb.h b/pb.h
index e3e68ce5..c63b3514 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/Makefile b/tests/Makefile
index 9696b794..fb37e630 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -1,143 +1,6 @@
-CFLAGS=-ansi -Wall -Werror -I .. -g -O0
-DEPS=../pb_decode.h ../pb_encode.h ../pb.h person.pb.h \
- callbacks2.pb.h callbacks.pb.h unittests.h unittestproto.pb.h \
- alltypes.pb.h missing_fields.pb.h
-TESTS= decode_unittests encode_unittests \
- test_decode1 test_decode2 test_decode3 test_decode3_buf \
- test_encode1 test_encode2 test_encode3 test_encode3_buf \
- test_decode_callbacks test_encode_callbacks \
- test_missing_fields test_no_messages test_funny_name \
- test_multiple_files test_cxxcompile test_options \
- bc_encode bc_decode test_encode_extensions test_decode_extensions
-
-# More strict checks for the core part of nanopb
-CC_VERSION=$(shell $(CC) -v 2>&1)
-CFLAGS_CORE=
-ifneq (,$(findstring gcc,$(CC_VERSION)))
- CFLAGS_CORE=-pedantic -Wextra -Wcast-qual -Wlogical-op -Wconversion
- CFLAGS+=--coverage -fstack-protector-all
- LDFLAGS+=--coverage
-endif
-ifneq (,$(findstring clang,$(CC_VERSION)))
- CFLAGS_CORE=-pedantic -Wextra -Wcast-qual -Wconversion
-endif
-
-# Also use mudflap if it is available
-# To enable, run with make -B USE_MUDFLAP=y
-USE_MUDFLAP ?= n
-ifeq ($(USE_MUDFLAP),y)
- CFLAGS += -fmudflap
- LDFLAGS += -lmudflap -fmudflap
-endif
-
-all: breakpoints $(TESTS) run_unittests
+all:
+ scons
clean:
- rm -f $(TESTS) person.pb* alltypes.pb* *.o *.gcda *.gcno *.pb.h *.pb.c
-
-%.pb.o: %.pb.c %.pb.h
- $(CC) $(CFLAGS) $(CFLAGS_CORE) -c -o $@ $<
-
-%.o: %.c
-%.o: %.c $(DEPS)
- $(CC) $(CFLAGS) -c -o $@ $<
-
-pb_encode.o: ../pb_encode.c $(DEPS)
- $(CC) $(CFLAGS) $(CFLAGS_CORE) -c -o $@ $<
-pb_decode.o: ../pb_decode.c $(DEPS)
- $(CC) $(CFLAGS) $(CFLAGS_CORE) -c -o $@ $<
-
-# Test for compilability with c++ compiler
-
-pb_encode.cxx.o: ../pb_encode.c $(DEPS)
- $(CXX) $(CFLAGS) $(CFLAGS_CORE) -c -o $@ $<
-pb_decode.cxx.o: ../pb_decode.c $(DEPS)
- $(CXX) $(CFLAGS) $(CFLAGS_CORE) -c -o $@ $<
-
-# Test for PB_BUF_ONLY compilation option
-
-pb_encode.buf.o: ../pb_encode.c $(DEPS)
- $(CC) -DPB_BUFFER_ONLY $(CFLAGS) $(CFLAGS_CORE) -c -o $@ $<
-pb_decode.buf.o: ../pb_decode.c $(DEPS)
- $(CC) -DPB_BUFFER_ONLY $(CFLAGS) $(CFLAGS_CORE) -c -o $@ $<
-%.buf.o: %.c $(DEPS)
- $(CC) -DPB_BUFFER_ONLY $(CFLAGS) -c -o $@ $<
-test_encode3_buf: test_encode3.buf.o pb_encode.buf.o alltypes.pb.o
- $(CC) $(LDFLAGS) $^ -o $@
-test_decode3_buf: test_decode3.buf.o pb_decode.buf.o alltypes.pb.o
- $(CC) $(LDFLAGS) $^ -o $@
-
-test_cxxcompile: pb_encode.cxx.o pb_decode.cxx.o
-test_decode1: test_decode1.o pb_decode.o person.pb.o
-test_decode2: test_decode2.o pb_decode.o person.pb.o
-test_decode3: test_decode3.o pb_decode.o alltypes.pb.o
-test_encode1: test_encode1.o pb_encode.o person.pb.o
-test_encode2: test_encode2.o pb_encode.o person.pb.o
-test_encode3: test_encode3.o pb_encode.o alltypes.pb.o
-test_multiple_files: test_multiple_files.o pb_encode.o callbacks2.pb.o callbacks.pb.o
-test_decode_callbacks: test_decode_callbacks.o pb_decode.o callbacks.pb.o
-test_encode_callbacks: test_encode_callbacks.o pb_encode.o callbacks.pb.o
-test_missing_fields: test_missing_fields.o pb_encode.o pb_decode.o missing_fields.pb.o
-decode_unittests: decode_unittests.o pb_decode.o unittestproto.pb.o
-encode_unittests: encode_unittests.o pb_encode.o unittestproto.pb.o
-test_no_messages: no_messages.pb.h no_messages.pb.c no_messages.pb.o
-test_funny_name: funny-proto+name.pb.h funny-proto+name.pb.o
-bc_encode: bc_alltypes.pb.o pb_encode.o bc_encode.o
-bc_decode: bc_alltypes.pb.o pb_decode.o bc_decode.o
-test_encode_extensions: test_encode_extensions.c pb_encode.o alltypes.pb.o extensions.pb.o
-test_decode_extensions: test_decode_extensions.c pb_decode.o alltypes.pb.o extensions.pb.o
-
-%.pb: %.proto
- protoc -I. -I../generator -I/usr/include -o$@ $<
-
-%.pb.c %.pb.h: %.pb ../generator/nanopb_generator.py
- python ../generator/nanopb_generator.py $<
-
-breakpoints: ../*.c *.c
- grep -n 'return false;' $^ | cut -d: -f-2 | xargs -n 1 echo b > $@
-
-coverage: run_unittests
- gcov pb_encode.gcda
- gcov pb_decode.gcda
-
-run_unittests: $(TESTS)
- rm -f *.gcda
-
- ./decode_unittests > /dev/null
- ./encode_unittests > /dev/null
-
- [ "`./test_encode1 | ./test_decode1`" = \
- "`./test_encode1 | protoc --decode=Person -I. -I../generator -I/usr/include person.proto`" ]
-
- [ "`./test_encode2 | ./test_decode1`" = \
- "`./test_encode2 | protoc --decode=Person -I. -I../generator -I/usr/include person.proto`" ]
-
- [ "`./test_encode2 | ./test_decode2`" = \
- "`./test_encode2 | protoc --decode=Person -I. -I../generator -I/usr/include person.proto`" ]
-
- [ "`./test_decode2 < person_with_extra_field.pb`" = \
- "`./test_encode2 | ./test_decode2`" ]
-
- [ "`./test_encode_callbacks | ./test_decode_callbacks`" = \
- "`./test_encode_callbacks | protoc --decode=TestMessage callbacks.proto`" ]
-
- ./test_encode3 | ./test_decode3
- ./test_encode3 1 | ./test_decode3 1
- ./test_encode3 1 | protoc --decode=AllTypes -I. -I../generator -I/usr/include alltypes.proto >/dev/null
- ./test_encode3_buf 1 | ./test_decode3_buf 1
- ./test_decode3 < alltypes_with_extra_fields.pb
- ./bc_encode | ./bc_decode
- ./test_encode_extensions | ./test_decode_extensions
-
- ./test_missing_fields
-
-test_options: options.pb.h options.expected options.pb.o
- cat options.expected | while read -r p; do \
- if ! grep -q "$$p" $<; then \
- echo Expected: "$$p"; \
- exit 1; \
- fi \
- done
+ scons -c
-run_fuzztest: test_decode3
- bash -c 'ulimit -c unlimited; I=1; while true; do cat /dev/urandom | ./test_decode3 > /dev/null; I=$$(($$I+1)); echo -en "\r$$I"; done'
diff --git a/tests/SConstruct b/tests/SConstruct
new file mode 100644
index 00000000..26a513d5
--- /dev/null
+++ b/tests/SConstruct
@@ -0,0 +1,109 @@
+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 = 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)
+
+# Path to the files shared by tests, and to the nanopb core.
+env.Append(CPPPATH = ["#../", "#common"])
+
+# Path for finding nanopb.proto
+env.Append(PROTOCPATH = '#../generator')
+
+# 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.
+ 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')
+
+ # 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 'gcc' in env['CC']:
+ # GNU Compiler Collection
+
+ # Debug info, warnings as errors
+ 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 = '-Wextra -Wcast-qual -Wlogical-op -Wconversion')
+elif 'clang' in env['CC']:
+ # CLang
+ env.Append(CFLAGS = '-ansi -pedantic -g -O0 -Wall -Werror')
+ env.Append(CORECFLAGS = ' -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(CFLAGS = '/Zi /W2 /WX')
+ env.Append(LINKFLAGS = '/DEBUG')
+
+ # More strict checks on the nanopb core
+ env.Append(CORECFLAGS = '/W4')
+
+ # PB_RETURN_ERROR triggers C4127 because of while(0)
+ 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/alltypes/SConscript b/tests/alltypes/SConscript
new file mode 100644
index 00000000..8aa45b6b
--- /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")
+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(enc)
+env.RunTest([dec, "encode_alltypes.output"])
+
diff --git a/tests/alltypes.options b/tests/alltypes/alltypes.options
index b31e3cf0..b31e3cf0 100644
--- a/tests/alltypes.options
+++ b/tests/alltypes/alltypes.options
diff --git a/tests/alltypes.proto b/tests/alltypes/alltypes.proto
index a2cf8bbc..a2cf8bbc 100644
--- a/tests/alltypes.proto
+++ b/tests/alltypes/alltypes.proto
diff --git a/tests/test_decode3.c b/tests/alltypes/decode_alltypes.c
index 55d025c0..ee2e115c 100644
--- a/tests/test_decode3.c
+++ b/tests/alltypes/decode_alltypes.c
@@ -8,6 +8,7 @@
#include <stdlib.h>
#include <pb_decode.h>
#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/test_encode3.c b/tests/alltypes/encode_alltypes.c
index 982ad3c8..88fc10f0 100644
--- a/tests/test_encode3.c
+++ b/tests/alltypes/encode_alltypes.c
@@ -6,6 +6,7 @@
#include <string.h>
#include <pb_encode.h>
#include "alltypes.pb.h"
+#include "test_helpers.h"
int main(int argc, char **argv)
{
@@ -113,18 +114,21 @@ 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))
+ {
+ SET_BINARY_MODE(stdout);
+ 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/backwards_compatibility/SConscript b/tests/backwards_compatibility/SConscript
new file mode 100644
index 00000000..5fb978f3
--- /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/bc_alltypes.pb.c b/tests/backwards_compatibility/alltypes_legacy.c
index b144b1e3..9134d5e6 100644
--- a/tests/bc_alltypes.pb.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/bc_alltypes.pb.h b/tests/backwards_compatibility/alltypes_legacy.h
index 037b3478..037b3478 100644
--- a/tests/bc_alltypes.pb.h
+++ b/tests/backwards_compatibility/alltypes_legacy.h
diff --git a/tests/bc_decode.c b/tests/backwards_compatibility/decode_legacy.c
index b74172fd..315b16ef 100644
--- a/tests/bc_decode.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 <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <pb_decode.h>
-#include "bc_alltypes.pb.h"
+#include "alltypes_legacy.h"
#define TEST(x) if (!(x)) { \
printf("Test " #x " failed.\n"); \
diff --git a/tests/bc_encode.c b/tests/backwards_compatibility/encode_legacy.c
index e84f0908..5c9d41b3 100644
--- a/tests/bc_encode.c
+++ b/tests/backwards_compatibility/encode_legacy.c
@@ -1,14 +1,15 @@
/* 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pb_encode.h>
-#include "bc_alltypes.pb.h"
+#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_buffer/SConscript b/tests/basic_buffer/SConscript
new file mode 100644
index 00000000..349fb14f
--- /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")
+
+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(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/test_decode1.c b/tests/basic_buffer/decode_buffer.c
index 56bbd8f8..d231c916 100644
--- a/tests/test_decode1.c
+++ b/tests/basic_buffer/decode_buffer.c
@@ -9,6 +9,7 @@
#include <stdio.h>
#include <pb_decode.h>
#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/test_encode1.c b/tests/basic_buffer/encode_buffer.c
index 742c99f4..d3e4f6e6 100644
--- a/tests/test_encode1.c
+++ b/tests/basic_buffer/encode_buffer.c
@@ -6,9 +6,13 @@
#include <stdio.h>
#include <pb_encode.h>
#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/basic_stream/SConscript b/tests/basic_stream/SConscript
new file mode 100644
index 00000000..17382a98
--- /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/test_decode2.c b/tests/basic_stream/decode_stream.c
index 2142977e..667bf3c5 100644
--- a/tests/test_decode2.c
+++ b/tests/basic_stream/decode_stream.c
@@ -4,6 +4,7 @@
#include <stdio.h>
#include <pb_decode.h>
#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/test_encode2.c b/tests/basic_stream/encode_stream.c
index fd25c6cb..7f571c41 100644
--- a/tests/test_encode2.c
+++ b/tests/basic_stream/encode_stream.c
@@ -4,6 +4,7 @@
#include <stdio.h>
#include <pb_encode.h>
#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/buffer_only/SConscript b/tests/buffer_only/SConscript
new file mode 100644
index 00000000..0770b2fc
--- /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/callbacks/SConscript b/tests/callbacks/SConscript
new file mode 100644
index 00000000..729fd65f
--- /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/callbacks.proto b/tests/callbacks/callbacks.proto
index ccd1edd8..ccd1edd8 100644
--- a/tests/callbacks.proto
+++ b/tests/callbacks/callbacks.proto
diff --git a/tests/test_decode_callbacks.c b/tests/callbacks/decode_callbacks.c
index b5056923..45724d0b 100644
--- a/tests/test_decode_callbacks.c
+++ b/tests/callbacks/decode_callbacks.c
@@ -5,6 +5,7 @@
#include <stdio.h>
#include <pb_decode.h>
#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";
@@ -82,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/test_encode_callbacks.c b/tests/callbacks/encode_callbacks.c
index 3bb6a45e..6cb67b1e 100644
--- a/tests/test_encode_callbacks.c
+++ b/tests/callbacks/encode_callbacks.c
@@ -4,6 +4,7 @@
#include <string.h>
#include <pb_encode.h>
#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/common/SConscript b/tests/common/SConscript
new file mode 100644
index 00000000..8130c85a
--- /dev/null
+++ b/tests/common/SConscript
@@ -0,0 +1,17 @@
+# 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
+# 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")
+
diff --git a/tests/person.proto b/tests/common/person.proto
index dafcf934..dafcf934 100644
--- a/tests/person.proto
+++ b/tests/common/person.proto
diff --git a/tests/common/test_helpers.h b/tests/common/test_helpers.h
new file mode 100644
index 00000000..f77760a5
--- /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 <io.h>
+#include <fcntl.h>
+#define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)
+
+#else
+#define SET_BINARY_MODE(file)
+
+#endif
+
+
+#endif
diff --git a/tests/unittestproto.proto b/tests/common/unittestproto.proto
index 7024942e..7024942e 100644
--- a/tests/unittestproto.proto
+++ b/tests/common/unittestproto.proto
diff --git a/tests/unittests.h b/tests/common/unittests.h
index c2b470ad..c2b470ad 100644
--- a/tests/unittests.h
+++ b/tests/common/unittests.h
diff --git a/tests/cxx_main_program/SConscript b/tests/cxx_main_program/SConscript
new file mode 100644
index 00000000..055c5aee
--- /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")
+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"])
+dec = env.Program(["decode_alltypes.cxx", "alltypes.pb.cxx", "pb_decode.cxx"])
+
+env.RunTest(enc)
+env.RunTest([dec, "encode_alltypes.output"])
diff --git a/tests/decode_unittests/SConscript b/tests/decode_unittests/SConscript
new file mode 100644
index 00000000..5e0f8407
--- /dev/null
+++ b/tests/decode_unittests/SConscript
@@ -0,0 +1,4 @@
+Import('env')
+p = env.Program(["decode_unittests.c", "#common/unittestproto.pb.c", "#common/pb_decode.o"])
+env.RunTest(p)
+
diff --git a/tests/decode_unittests.c b/tests/decode_unittests/decode_unittests.c
index 6ad05f00..9c447a57 100644
--- a/tests/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
new file mode 100644
index 00000000..6a5ffcff
--- /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')
+p = env.Program(["encode_unittests.c", "#common/unittestproto.pb.c", "#common/pb_encode.o"])
+env.RunTest(p)
diff --git a/tests/encode_unittests.c b/tests/encode_unittests/encode_unittests.c
index c3634ac8..c3634ac8 100644
--- a/tests/encode_unittests.c
+++ b/tests/encode_unittests/encode_unittests.c
diff --git a/tests/extensions/SConscript b/tests/extensions/SConscript
new file mode 100644
index 00000000..f632a9ae
--- /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$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"])
+
diff --git a/tests/extensions/decode_extensions.c b/tests/extensions/decode_extensions.c
new file mode 100644
index 00000000..f8ebbde0
--- /dev/null
+++ b/tests/extensions/decode_extensions.c
@@ -0,0 +1,58 @@
+/* Test decoding of extension fields. */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <pb_decode.h>
+#include "alltypes.pb.h"
+#include "extensions.pb.h"
+#include "test_helpers.h"
+
+#define TEST(x) if (!(x)) { \
+ printf("Test " #x " failed.\n"); \
+ return 2; \
+ }
+
+int main(int argc, char **argv)
+{
+ uint8_t buffer[1024];
+ size_t count;
+ pb_istream_t stream;
+
+ AllTypes alltypes = {0};
+ int32_t extensionfield1;
+ 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)
+
+ return 0;
+}
+
diff --git a/tests/test_encode_extensions.c b/tests/extensions/encode_extensions.c
index 8857f148..dee3597d 100644
--- a/tests/test_encode_extensions.c
+++ b/tests/extensions/encode_extensions.c
@@ -7,25 +7,37 @@
#include <pb_encode.h>
#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/extensions.options b/tests/extensions/extensions.options
index a5cd61dd..a5cd61dd 100644
--- a/tests/extensions.options
+++ b/tests/extensions/extensions.options
diff --git a/tests/extensions.proto b/tests/extensions/extensions.proto
index d85e8193..d85e8193 100644
--- a/tests/extensions.proto
+++ b/tests/extensions/extensions.proto
diff --git a/tests/extra_fields/SConscript b/tests/extra_fields/SConscript
new file mode 100644
index 00000000..a6f0e751
--- /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/alltypes_with_extra_fields.pb b/tests/extra_fields/alltypes_with_extra_fields.pb
index f9f53941..f9f53941 100644
--- a/tests/alltypes_with_extra_fields.pb
+++ b/tests/extra_fields/alltypes_with_extra_fields.pb
Binary files differ
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 00000000..da9c32df
--- /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/person_with_extra_field.pb b/tests/extra_fields/person_with_extra_field.pb
index ced3057c..ced3057c 100644
--- a/tests/person_with_extra_field.pb
+++ b/tests/extra_fields/person_with_extra_field.pb
Binary files differ
diff --git a/tests/field_size_16/SConscript b/tests/field_size_16/SConscript
new file mode 100644
index 00000000..48d08e84
--- /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 00000000..b31e3cf0
--- /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 00000000..b981760d
--- /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 00000000..a8584dc0
--- /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 00000000..b31e3cf0
--- /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 00000000..3d1d856c
--- /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/missing_fields/SConscript b/tests/missing_fields/SConscript
new file mode 100644
index 00000000..361b5502
--- /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/test_missing_fields.c b/tests/missing_fields/missing_fields.c
index 27741847..b9a273a2 100644
--- a/tests/test_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/missing_fields.proto b/tests/missing_fields/missing_fields.proto
index cbb23ba1..cbb23ba1 100644
--- a/tests/missing_fields.proto
+++ b/tests/missing_fields/missing_fields.proto
diff --git a/tests/multiple_files/SConscript b/tests/multiple_files/SConscript
new file mode 100644
index 00000000..6b4f6b69
--- /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/callbacks.proto b/tests/multiple_files/callbacks.proto
new file mode 100644
index 00000000..ccd1edd8
--- /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
index 9a55e15a..9a55e15a 100644
--- a/tests/callbacks2.proto
+++ b/tests/multiple_files/callbacks2.proto
diff --git a/tests/multiple_files/test_multiple_files.c b/tests/multiple_files/test_multiple_files.c
new file mode 100644
index 00000000..05722dc5
--- /dev/null
+++ b/tests/multiple_files/test_multiple_files.c
@@ -0,0 +1,12 @@
+/*
+ * Tests if this still compiles when multiple .proto files are involved.
+ */
+
+#include <stdio.h>
+#include <pb_encode.h>
+#include "callbacks2.pb.h"
+
+int main()
+{
+ return 0;
+}
diff --git a/tests/no_errmsg/SConscript b/tests/no_errmsg/SConscript
new file mode 100644
index 00000000..870e8946
--- /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"])
diff --git a/tests/no_messages/SConscript b/tests/no_messages/SConscript
new file mode 100644
index 00000000..6492e2cf
--- /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/no_messages.proto b/tests/no_messages/no_messages.proto
index 279216b0..279216b0 100644
--- a/tests/no_messages.proto
+++ b/tests/no_messages/no_messages.proto
diff --git a/tests/options/SConscript b/tests/options/SConscript
new file mode 100644
index 00000000..89a00fa5
--- /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/options.expected b/tests/options/options.expected
index e6179a27..e6179a27 100644
--- a/tests/options.expected
+++ b/tests/options/options.expected
diff --git a/tests/options.proto b/tests/options/options.proto
index b5badcfd..b5badcfd 100644
--- a/tests/options.proto
+++ b/tests/options/options.proto
diff --git a/tests/site_scons/site_init.py b/tests/site_scons/site_init.py
new file mode 100644
index 00000000..86e50335
--- /dev/null
+++ b/tests/site_scons/site_init.py
@@ -0,0 +1,111 @@
+import subprocess
+import sys
+import re
+
+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.'''
+
+ # Build command for building .pb from .proto using protoc
+ def proto_actions(source, target, env, for_signature):
+ 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',
+ 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
+ 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[32m[ OK ]\033[0m Ran ' + str(source[0])
+ else:
+ print '\033[31m[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[32m[ OK ]\033[0m Files equal: ' + str(source[0]) + ' and ' + str(source[1])
+ return 0
+ else:
+ print '\033[31m[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})
+
+ # 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 00000000..05dccaee
--- /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/funny-proto+name.proto b/tests/special_characters/funny-proto+name has.characters.proto
index e69de29b..e69de29b 100644
--- a/tests/funny-proto+name.proto
+++ b/tests/special_characters/funny-proto+name has.characters.proto
diff --git a/tests/test_decode_extensions.c b/tests/test_decode_extensions.c
deleted file mode 100644
index ef6a0228..00000000
--- a/tests/test_decode_extensions.c
+++ /dev/null
@@ -1,43 +0,0 @@
-/* Test decoding of extension fields. */
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <pb_decode.h>
-#include "alltypes.pb.h"
-#include "extensions.pb.h"
-
-#define TEST(x) if (!(x)) { \
- printf("Test " #x " failed.\n"); \
- return 2; \
- }
-
-int main(int argc, char **argv)
-{
- uint8_t buffer[1024];
- size_t count = fread(buffer, 1, sizeof(buffer), stdin);
- pb_istream_t stream = pb_istream_from_buffer(buffer, count);
-
- AllTypes alltypes = {};
-
- int32_t extensionfield1;
- pb_extension_t ext1 = {&AllTypes_extensionfield1, &extensionfield1, NULL};
- alltypes.extensions = &ext1;
-
- ExtensionMessage extensionfield2 = {};
- pb_extension_t ext2 = {&ExtensionMessage_AllTypes_extensionfield2, &extensionfield2, NULL};
- ext1.next = &ext2;
-
- if (!pb_decode(&stream, AllTypes_fields, &alltypes))
- {
- printf("Parsing failed: %s\n", PB_GET_ERROR(&stream));
- return 1;
- }
-
- TEST(extensionfield1 == 12345)
- TEST(strcmp(extensionfield2.test1, "test") == 0)
- TEST(extensionfield2.test2 == 54321)
-
- return 0;
-}
-
diff --git a/tests/test_multiple_files.c b/tests/test_multiple_files.c
deleted file mode 100644
index cb4e16d3..00000000
--- a/tests/test_multiple_files.c
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * Tests if still compile if typedefs are redfefined in STATIC_ASSERTS when
- * proto file includes another poto file
- */
-
-#include <stdio.h>
-#include <pb_encode.h>
-#include "callbacks2.pb.h"
-
-int main()
-{
- return 0;
-}
diff --git a/tests/testperson.pb b/tests/testperson.pb
deleted file mode 100644
index d1eb8cfb..00000000
--- a/tests/testperson.pb
+++ /dev/null
@@ -1,3 +0,0 @@
-
- Test Person7foobar@foobar.com"
- 555-12345678 \ No newline at end of file