mirror of
https://github.com/sle118/squeezelite-esp32.git
synced 2025-12-20 14:38:26 +03:00
add nanopb (manual)
This commit is contained in:
21
components/spotify/cspot/bell/nanopb/tests/Makefile
Normal file
21
components/spotify/cspot/bell/nanopb/tests/Makefile
Normal file
@@ -0,0 +1,21 @@
|
||||
all:
|
||||
scons
|
||||
|
||||
clean:
|
||||
scons -c
|
||||
|
||||
coverage:
|
||||
rm -rf build coverage
|
||||
|
||||
# LCOV does not like the newer gcov format
|
||||
scons CC=gcc-4.6 CXX=gcc-4.6
|
||||
|
||||
# Collect the data
|
||||
mkdir build/coverage
|
||||
lcov --base-directory . --directory build/ --gcov-tool gcov-4.6 -c -o build/coverage/nanopb.info
|
||||
|
||||
# Remove the test code from results
|
||||
lcov -r build/coverage/nanopb.info '*tests*' -o build/coverage/nanopb.info
|
||||
|
||||
# Generate HTML
|
||||
genhtml -o build/coverage build/coverage/nanopb.info
|
||||
236
components/spotify/cspot/bell/nanopb/tests/SConstruct
Normal file
236
components/spotify/cspot/bell/nanopb/tests/SConstruct
Normal file
@@ -0,0 +1,236 @@
|
||||
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 behaviour using following options:
|
||||
BUILDDIR Directory to build into (default "build")
|
||||
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
|
||||
LINK Name of linker (usually same as CC)
|
||||
LINKFLAGS Flags to pass to linker
|
||||
LINKLIBS Flags to pass to linker after object files
|
||||
PROTOC Path to protoc binary
|
||||
PROTOCFLAGS Arguments to pass protoc
|
||||
NODEFARGS Do not add the default CCFLAGS
|
||||
NOVALGRIND Do not use valgrind for memory checks
|
||||
|
||||
For example, for a clang build, use:
|
||||
scons CC=clang CXX=clang++
|
||||
''')
|
||||
|
||||
import os
|
||||
import platform
|
||||
env = Environment(ENV = os.environ)
|
||||
|
||||
# Allow giving environment flags on command line.
|
||||
list_vars = ['CCFLAGS', 'CXXFLAGS', 'LINKFLAGS', 'LINKLIBS', 'PROTOCFLAGS']
|
||||
for var,val in ARGUMENTS.items():
|
||||
if var in list_vars:
|
||||
env.Append(**{var: val})
|
||||
else:
|
||||
env.Replace(**{var: val})
|
||||
|
||||
env.SetDefault(BUILDDIR = "build")
|
||||
env.SConsignFile(env['BUILDDIR'] + "/sconsign")
|
||||
env.Replace(CONFIGUREDIR = env['BUILDDIR'] + "/config")
|
||||
|
||||
# If a cross compilation platform is given, apply the environment settings
|
||||
# from site_scons/platforms/X/X.py
|
||||
if ARGUMENTS.get('PLATFORM'):
|
||||
platform_func = platforms.get(ARGUMENTS.get('PLATFORM'))
|
||||
if not platform_func:
|
||||
print("Supported platforms: " + str(platforms.keys()))
|
||||
raise Exception("Unsupported platform: " + ARGUMENTS.get('PLATFORM'))
|
||||
else:
|
||||
platform_func(env)
|
||||
|
||||
# Load nanopb generator build rules from site_scons/site_tools/nanopb.py
|
||||
env.Tool("nanopb")
|
||||
|
||||
# Limit memory usage. This is to catch problems like issue #338
|
||||
try:
|
||||
import resource
|
||||
soft, hard = resource.getrlimit(resourse.RLIMIT_AS)
|
||||
resource.setrlimit(resource.RLIMIT_AS, (100*1024*1024, hard))
|
||||
except:
|
||||
pass
|
||||
|
||||
# On Mac OS X, gcc is usually alias for clang.
|
||||
# To avoid problem with default options, use clang directly.
|
||||
if platform.system() == "Darwin" and 'CC' not in ARGUMENTS:
|
||||
env.Replace(CC = "clang", CXX = "clang++")
|
||||
|
||||
# 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'):
|
||||
def check_ccflags(context, flags, linkflags = ''):
|
||||
'''Check if given CCFLAGS are supported'''
|
||||
context.Message('Checking support for CCFLAGS="%s"... ' % flags)
|
||||
oldflags = context.env['CCFLAGS']
|
||||
oldlinkflags = context.env['LINKFLAGS']
|
||||
context.env.Append(CCFLAGS = flags)
|
||||
context.env.Append(LINKFLAGS = linkflags)
|
||||
result = context.TryCompile("int main() {return 0;}", '.c')
|
||||
context.env.Replace(CCFLAGS = oldflags)
|
||||
context.env.Replace(LINKFLAGS = oldlinkflags)
|
||||
context.Result(result)
|
||||
return result
|
||||
|
||||
def check_protocversion(context):
|
||||
context.Display("Checking protoc version... ")
|
||||
status, output = context.TryAction('$PROTOC --version > $TARGET')
|
||||
if status:
|
||||
context.Result(str(output.strip()))
|
||||
return str(output.strip())
|
||||
else:
|
||||
context.Display("error: %s\n" % output.strip())
|
||||
context.did_show_result = 1
|
||||
context.Result("unknown, assuming 3.6.1")
|
||||
return "3.6.1"
|
||||
|
||||
conf = Configure(env, custom_tests =
|
||||
{'CheckCCFLAGS': check_ccflags,
|
||||
'CheckProtocVersion': check_protocversion})
|
||||
|
||||
# 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')
|
||||
stdlib = conf.CheckCHeader('stdlib.h')
|
||||
limits = conf.CheckCHeader('limits.h')
|
||||
if not stdbool or not stdint or not stddef or not string or not limits:
|
||||
conf.env.Append(CPPDEFINES = {'PB_SYSTEM_HEADER': '\\"pb_syshdr.h\\"'})
|
||||
conf.env.Append(CPPPATH = "#../extra")
|
||||
conf.env.Append(SYSHDR = '\\"pb_syshdr.h\\"')
|
||||
|
||||
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})
|
||||
if stdlib: conf.env.Append(CPPDEFINES = {'HAVE_STDLIB_H': 1})
|
||||
if limits: conf.env.Append(CPPDEFINES = {'HAVE_LIMITS_H': 1})
|
||||
|
||||
# Check protoc version
|
||||
conf.env['PROTOC_VERSION'] = conf.CheckProtocVersion()
|
||||
|
||||
# Initialize compiler arguments with defaults, unless overridden on
|
||||
# command line.
|
||||
if not env.get('NODEFARGS'):
|
||||
# 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 = '-fmudflap')
|
||||
|
||||
# Check if we can use extra strict warning flags (only with GCC)
|
||||
extra = '-Wcast-qual -Wlogical-op -Wconversion'
|
||||
extra += ' -fstrict-aliasing -Wstrict-aliasing=1'
|
||||
extra += ' -Wmissing-prototypes -Wmissing-declarations -Wredundant-decls'
|
||||
extra += ' -Wstack-protector '
|
||||
if 'gcc' in env['CC']:
|
||||
if conf.CheckCCFLAGS(extra):
|
||||
conf.env.Append(CORECFLAGS = extra)
|
||||
|
||||
# Check if we can use undefined behaviour sanitizer (only with clang)
|
||||
# TODO: Fuzz test triggers the bool sanitizer, figure out whether to
|
||||
# modify the fuzz test or to keep ignoring the check.
|
||||
extra = '-fsanitize=undefined,integer -fno-sanitize-recover=undefined,integer '
|
||||
if 'clang' in env['CC']:
|
||||
if conf.CheckCCFLAGS(extra, linkflags = extra):
|
||||
conf.env.Append(CORECFLAGS = extra)
|
||||
conf.env.Append(LINKFLAGS = extra)
|
||||
|
||||
# End the config stuff
|
||||
env = conf.Finish()
|
||||
|
||||
if not env.get('NODEFARGS'):
|
||||
# Initialize the CCFLAGS according to the compiler
|
||||
if 'gcc' in env['CC']:
|
||||
# GNU Compiler Collection
|
||||
|
||||
# Debug info, warnings as errors
|
||||
env.Append(CFLAGS = '-g -Wall -Werror ')
|
||||
env.Append(CORECFLAGS = '-Wextra')
|
||||
|
||||
# Pedantic ANSI C. On AVR this doesn't work because we use large
|
||||
# enums in some of the tests.
|
||||
if env.get("EMBEDDED") != "AVR":
|
||||
env.Append(CFLAGS = '-ansi -pedantic')
|
||||
|
||||
# Profiling and coverage
|
||||
if not env.get("EMBEDDED"):
|
||||
env.Append(CFLAGS = '-fprofile-arcs -ftest-coverage ')
|
||||
env.Append(LINKFLAGS = '-g --coverage')
|
||||
|
||||
|
||||
# We currently need uint64_t anyway, even though ANSI C90 otherwise..
|
||||
env.Append(CFLAGS = '-Wno-long-long')
|
||||
elif 'clang' in env['CC']:
|
||||
# CLang
|
||||
env.Append(CFLAGS = '-ansi -g -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')
|
||||
|
||||
# Disable warning about sizeof(union{}) construct that is used in
|
||||
# message size macros, in e.g. multiple_files testcase. The C construct
|
||||
# itself is valid, but quite rare, which causes Visual C++ to give a warning
|
||||
# about it.
|
||||
env.Append(CFLAGS = '/wd4116')
|
||||
elif 'tcc' in env['CC']:
|
||||
# Tiny C Compiler
|
||||
env.Append(CFLAGS = '-Wall -Werror -g')
|
||||
|
||||
if 'clang' in env['CXX']:
|
||||
env.Append(CXXFLAGS = '-g -Wall -Werror -Wextra -Wno-missing-field-initializers')
|
||||
elif 'g++' in env['CXX'] or 'gcc' in env['CXX']:
|
||||
env.Append(CXXFLAGS = '-g -Wall -Werror -Wextra -Wno-missing-field-initializers')
|
||||
elif 'cl' in env['CXX']:
|
||||
env.Append(CXXFLAGS = '/Zi /W2 /WX /wd4116 /wd4127')
|
||||
|
||||
env.SetDefault(CORECFLAGS = '')
|
||||
|
||||
if not env.get("EMBEDDED") and not env.get("NOVALGRIND"):
|
||||
valgrind = env.WhereIs('valgrind')
|
||||
if valgrind:
|
||||
env.SetDefault(VALGRIND = valgrind)
|
||||
|
||||
# Make it possible to add commands to the end of linker line
|
||||
env.SetDefault(LINKLIBS = '')
|
||||
env.Replace(LINKCOM = env['LINKCOM'] + " $LINKLIBS")
|
||||
|
||||
# Place build files under separate folder
|
||||
import os.path
|
||||
env['VARIANT_DIR'] = env['BUILDDIR']
|
||||
env['BUILD'] = '#' + env['VARIANT_DIR']
|
||||
env['COMMON'] = '#' + env['VARIANT_DIR'] + '/common'
|
||||
|
||||
# Include common/SConscript first to make sure its exports are available
|
||||
# to other SConscripts.
|
||||
SConscript("common/SConscript", exports = 'env', variant_dir = env['VARIANT_DIR'] + '/common')
|
||||
|
||||
# Now include the SConscript files from all subdirectories
|
||||
for subdir in Glob('*/SConscript') + Glob('regression/*/SConscript'):
|
||||
if str(subdir).startswith("common/"): continue
|
||||
if str(subdir).startswith("common\\"): continue
|
||||
SConscript(subdir, exports = 'env', variant_dir = env['VARIANT_DIR'] + '/' + os.path.dirname(str(subdir)))
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
# 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", "alltypes.options"])
|
||||
enc = env.Program(["encode_alltypes.c", "alltypes.pb.c", "$COMMON/pb_encode.o", "$COMMON/pb_common.o"])
|
||||
dec = env.Program(["decode_alltypes.c", "alltypes.pb.c", "$COMMON/pb_decode.o", "$COMMON/pb_common.o"])
|
||||
|
||||
# Test the round-trip from nanopb encoder to nanopb decoder
|
||||
env.RunTest(enc)
|
||||
env.RunTest([dec, "encode_alltypes.output"])
|
||||
|
||||
# Re-encode the data using protoc, and check that the results from nanopb
|
||||
# match byte-per-byte to the protoc output.
|
||||
env.Decode("encode_alltypes.output.decoded",
|
||||
["encode_alltypes.output", "alltypes.proto"],
|
||||
MESSAGE='AllTypes')
|
||||
env.Encode("encode_alltypes.output.recoded",
|
||||
["encode_alltypes.output.decoded", "alltypes.proto"],
|
||||
MESSAGE='AllTypes')
|
||||
env.Compare(["encode_alltypes.output", "encode_alltypes.output.recoded"])
|
||||
|
||||
# Do the same checks with the optional fields present.
|
||||
env.RunTest("optionals.output", enc, ARGS = ['1'])
|
||||
env.RunTest("optionals.decout", [dec, "optionals.output"], ARGS = ['1'])
|
||||
env.Decode("optionals.output.decoded",
|
||||
["optionals.output", "alltypes.proto"],
|
||||
MESSAGE='AllTypes')
|
||||
env.Encode("optionals.output.recoded",
|
||||
["optionals.output.decoded", "alltypes.proto"],
|
||||
MESSAGE='AllTypes')
|
||||
env.Compare(["optionals.output", "optionals.output.recoded"])
|
||||
|
||||
# And for the _zero initializer
|
||||
env.RunTest("zeroinit.output", enc, ARGS = ['2'])
|
||||
env.RunTest("zeroinit.decout", [dec, "zeroinit.output"], ARGS = ['2'])
|
||||
env.Decode("zeroinit.output.decoded",
|
||||
["zeroinit.output", "alltypes.proto"],
|
||||
MESSAGE='AllTypes')
|
||||
env.Encode("zeroinit.output.recoded",
|
||||
["zeroinit.output.decoded", "alltypes.proto"],
|
||||
MESSAGE='AllTypes')
|
||||
env.Compare(["zeroinit.output", "zeroinit.output.recoded"])
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
* max_size:16
|
||||
* max_count:5
|
||||
*.*fbytes fixed_length:true max_size:4
|
||||
*.*farray fixed_count:true max_count:5
|
||||
*.*farray2 fixed_count:true max_count:3
|
||||
IntSizes.*int8 int_size:IS_8
|
||||
IntSizes.*int16 int_size:IS_16
|
||||
DescriptorSize8 descriptorsize:DS_8
|
||||
@@ -0,0 +1,166 @@
|
||||
syntax = "proto2";
|
||||
// package name placeholder
|
||||
|
||||
enum NonZeroBasedEnum {
|
||||
Two = 2;
|
||||
Three = 3;
|
||||
Four = 4;
|
||||
}
|
||||
|
||||
message SubMessage {
|
||||
required string substuff1 = 1 [default = "1"];
|
||||
required int32 substuff2 = 2 [default = 2];
|
||||
optional fixed32 substuff3 = 3 [default = 3];
|
||||
}
|
||||
|
||||
message EmptyMessage {
|
||||
|
||||
}
|
||||
|
||||
enum HugeEnum {
|
||||
Negative = -2147483647; /* protoc doesn't accept -2147483648 here */
|
||||
Positive = 2147483647;
|
||||
}
|
||||
|
||||
message Limits {
|
||||
required int32 int32_min = 1 [default = 2147483647];
|
||||
required int32 int32_max = 2 [default = -2147483647];
|
||||
required uint32 uint32_min = 3 [default = 4294967295];
|
||||
required uint32 uint32_max = 4 [default = 0];
|
||||
required int64 int64_min = 5 [default = 9223372036854775807];
|
||||
required int64 int64_max = 6 [default = -9223372036854775807];
|
||||
required uint64 uint64_min = 7 [default = 18446744073709551615];
|
||||
required uint64 uint64_max = 8 [default = 0];
|
||||
required HugeEnum enum_min = 9 [default = Positive];
|
||||
required HugeEnum enum_max = 10 [default = Negative];
|
||||
required int32 largetag = 65535 [default = 0];
|
||||
}
|
||||
|
||||
message IntSizes {
|
||||
required int32 req_int8 = 1 ;
|
||||
required uint32 req_uint8 = 2 ;
|
||||
required sint32 req_sint8 = 3 ;
|
||||
required int32 req_int16 = 4 ;
|
||||
required uint32 req_uint16 = 5 ;
|
||||
required sint32 req_sint16 = 6 ;
|
||||
}
|
||||
|
||||
message DescriptorSize8 {
|
||||
required int32 first = 1;
|
||||
required int32 second = 22222;
|
||||
}
|
||||
|
||||
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;
|
||||
required bytes req_fbytes = 19;
|
||||
|
||||
repeated int32 rep_int32 = 21 [packed = true];
|
||||
repeated int64 rep_int64 = 22 [packed = true];
|
||||
repeated uint32 rep_uint32 = 23 [packed = true];
|
||||
repeated uint64 rep_uint64 = 24 [packed = true];
|
||||
repeated sint32 rep_sint32 = 25 [packed = true];
|
||||
repeated sint64 rep_sint64 = 26 [packed = true];
|
||||
repeated bool rep_bool = 27 [packed = true];
|
||||
|
||||
repeated fixed32 rep_fixed32 = 28 [packed = true];
|
||||
repeated sfixed32 rep_sfixed32= 29 [packed = true];
|
||||
repeated float rep_float = 30 [packed = true];
|
||||
|
||||
repeated fixed64 rep_fixed64 = 31 [packed = true];
|
||||
repeated sfixed64 rep_sfixed64= 32 [packed = true];
|
||||
repeated double rep_double = 33 [packed = true];
|
||||
|
||||
repeated string rep_string = 34;
|
||||
repeated bytes rep_bytes = 35;
|
||||
repeated SubMessage rep_submsg = 36;
|
||||
repeated MyEnum rep_enum = 37 [packed = true];
|
||||
repeated EmptyMessage rep_emptymsg = 38;
|
||||
repeated bytes rep_fbytes = 39;
|
||||
repeated int32 rep_farray = 40 [packed = true];
|
||||
|
||||
optional int32 opt_int32 = 41 [default = 4041];
|
||||
optional int64 opt_int64 = 42 [default = 4042];
|
||||
optional uint32 opt_uint32 = 43 [default = 4043];
|
||||
optional uint64 opt_uint64 = 44 [default = 4044];
|
||||
optional sint32 opt_sint32 = 45 [default = 4045];
|
||||
optional sint64 opt_sint64 = 46 [default = 4046];
|
||||
optional bool opt_bool = 47 [default = false];
|
||||
|
||||
optional fixed32 opt_fixed32 = 48 [default = 4048];
|
||||
optional sfixed32 opt_sfixed32= 49 [default = 4049];
|
||||
optional float opt_float = 50 [default = 4050];
|
||||
|
||||
optional fixed64 opt_fixed64 = 51 [default = 4051];
|
||||
optional sfixed64 opt_sfixed64= 52 [default = 4052];
|
||||
optional double opt_double = 53 [default = 4053];
|
||||
|
||||
optional string opt_string = 54 [default = "4054"];
|
||||
optional bytes opt_bytes = 55 [default = "\x34\x5C\x00\xff"];
|
||||
optional SubMessage opt_submsg = 56;
|
||||
optional MyEnum opt_enum = 57 [default = Second];
|
||||
optional EmptyMessage opt_emptymsg = 58;
|
||||
optional bytes opt_fbytes = 59 [default = "4059"];
|
||||
|
||||
oneof oneof
|
||||
{
|
||||
SubMessage oneof_msg1 = 60;
|
||||
EmptyMessage oneof_msg2 = 61;
|
||||
SubMessage static_msg = 63;
|
||||
}
|
||||
|
||||
optional NonZeroBasedEnum opt_non_zero_based_enum = 62;
|
||||
|
||||
// Second fixed length array field to test the length check logic.
|
||||
repeated fixed32 rep_farray2 = 95 [packed = true];
|
||||
|
||||
// Check support for custom integer sizes
|
||||
required IntSizes req_intsizes = 96;
|
||||
|
||||
// Check support for 8-word descriptors
|
||||
required DescriptorSize8 req_ds8 = 97;
|
||||
|
||||
// Check that extreme integer values are handled correctly
|
||||
// Also checks support for 4-word descriptors
|
||||
required Limits req_limits = 98;
|
||||
|
||||
// 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 = 999;
|
||||
|
||||
|
||||
extensions 200 to 255;
|
||||
}
|
||||
|
||||
message TestExtension {
|
||||
extend AllTypes {
|
||||
optional TestExtension testextension = 250;
|
||||
}
|
||||
optional string strval = 1;
|
||||
}
|
||||
@@ -0,0 +1,332 @@
|
||||
/* Tests the decoding of all types.
|
||||
* This is the counterpart of test_encode3.
|
||||
* Run e.g. ./test_encode3 | ./test_decode3
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <pb_decode.h>
|
||||
#include "alltypes.pb.h"
|
||||
#include "unittests.h"
|
||||
#include "test_helpers.h"
|
||||
|
||||
/* This function is called once from main(), it handles
|
||||
the decoding and checks the fields. */
|
||||
bool check_alltypes(pb_istream_t *stream, int mode)
|
||||
{
|
||||
int status = 0;
|
||||
|
||||
/* Uses _init_default to just make sure that the macro works. */
|
||||
AllTypes alltypes = AllTypes_init_default;
|
||||
|
||||
/* Fill with garbage to better detect initialization errors */
|
||||
memset(&alltypes, 0xAA, sizeof(alltypes));
|
||||
alltypes.extensions = 0;
|
||||
|
||||
if (!pb_decode(stream, AllTypes_fields, &alltypes))
|
||||
return false;
|
||||
|
||||
if (mode == 0 || mode == 1)
|
||||
{
|
||||
TEST(alltypes.req_int32 == -1001);
|
||||
TEST(alltypes.req_int64 == -1002);
|
||||
TEST(alltypes.req_uint32 == 1003);
|
||||
TEST(alltypes.req_uint64 == 1004);
|
||||
TEST(alltypes.req_sint32 == -1005);
|
||||
TEST(alltypes.req_sint64 == -1006);
|
||||
TEST(alltypes.req_bool == true);
|
||||
|
||||
TEST(alltypes.req_fixed32 == 1008);
|
||||
TEST(alltypes.req_sfixed32 == -1009);
|
||||
TEST(alltypes.req_float == 1010.0f);
|
||||
|
||||
TEST(alltypes.req_fixed64 == 1011);
|
||||
TEST(alltypes.req_sfixed64 == -1012);
|
||||
TEST(alltypes.req_double == 1013.0f);
|
||||
|
||||
TEST(strcmp(alltypes.req_string, "1014") == 0);
|
||||
TEST(alltypes.req_bytes.size == 4);
|
||||
TEST(memcmp(alltypes.req_bytes.bytes, "1015", 4) == 0);
|
||||
TEST(strcmp(alltypes.req_submsg.substuff1, "1016") == 0);
|
||||
TEST(alltypes.req_submsg.substuff2 == 1016);
|
||||
TEST(alltypes.req_submsg.substuff3 == 3);
|
||||
TEST(alltypes.req_enum == MyEnum_Truth);
|
||||
TEST(memcmp(alltypes.req_fbytes, "1019", 4) == 0);
|
||||
|
||||
TEST(alltypes.rep_int32_count == 5 && alltypes.rep_int32[4] == -2001 && alltypes.rep_int32[0] == 0);
|
||||
TEST(alltypes.rep_int64_count == 5 && alltypes.rep_int64[4] == -2002 && alltypes.rep_int64[0] == 0);
|
||||
TEST(alltypes.rep_uint32_count == 5 && alltypes.rep_uint32[4] == 2003 && alltypes.rep_uint32[0] == 0);
|
||||
TEST(alltypes.rep_uint64_count == 5 && alltypes.rep_uint64[4] == 2004 && alltypes.rep_uint64[0] == 0);
|
||||
TEST(alltypes.rep_sint32_count == 5 && alltypes.rep_sint32[4] == -2005 && alltypes.rep_sint32[0] == 0);
|
||||
TEST(alltypes.rep_sint64_count == 5 && alltypes.rep_sint64[4] == -2006 && alltypes.rep_sint64[0] == 0);
|
||||
TEST(alltypes.rep_bool_count == 5 && alltypes.rep_bool[4] == true && alltypes.rep_bool[0] == false);
|
||||
|
||||
TEST(alltypes.rep_fixed32_count == 5 && alltypes.rep_fixed32[4] == 2008 && alltypes.rep_fixed32[0] == 0);
|
||||
TEST(alltypes.rep_sfixed32_count == 5 && alltypes.rep_sfixed32[4] == -2009 && alltypes.rep_sfixed32[0] == 0);
|
||||
TEST(alltypes.rep_float_count == 5 && alltypes.rep_float[4] == 2010.0f && alltypes.rep_float[0] == 0.0f);
|
||||
|
||||
TEST(alltypes.rep_fixed64_count == 5 && alltypes.rep_fixed64[4] == 2011 && alltypes.rep_fixed64[0] == 0);
|
||||
TEST(alltypes.rep_sfixed64_count == 5 && alltypes.rep_sfixed64[4] == -2012 && alltypes.rep_sfixed64[0] == 0);
|
||||
TEST(alltypes.rep_double_count == 5 && alltypes.rep_double[4] == 2013.0 && alltypes.rep_double[0] == 0.0);
|
||||
|
||||
TEST(alltypes.rep_string_count == 5 && strcmp(alltypes.rep_string[4], "2014") == 0 && alltypes.rep_string[0][0] == '\0');
|
||||
TEST(alltypes.rep_bytes_count == 5 && alltypes.rep_bytes[4].size == 4 && alltypes.rep_bytes[0].size == 0);
|
||||
TEST(memcmp(alltypes.rep_bytes[4].bytes, "2015", 4) == 0);
|
||||
|
||||
TEST(alltypes.rep_submsg_count == 5);
|
||||
TEST(strcmp(alltypes.rep_submsg[4].substuff1, "2016") == 0 && alltypes.rep_submsg[0].substuff1[0] == '\0');
|
||||
TEST(alltypes.rep_submsg[4].substuff2 == 2016 && alltypes.rep_submsg[0].substuff2 == 0);
|
||||
TEST(alltypes.rep_submsg[4].substuff3 == 2016 && alltypes.rep_submsg[0].substuff3 == 3);
|
||||
|
||||
TEST(alltypes.rep_enum_count == 5 && alltypes.rep_enum[4] == MyEnum_Truth && alltypes.rep_enum[0] == MyEnum_Zero);
|
||||
TEST(alltypes.rep_emptymsg_count == 5);
|
||||
TEST(alltypes.rep_fbytes_count == 5);
|
||||
TEST(alltypes.rep_fbytes[0][0] == 0 && alltypes.rep_fbytes[0][3] == 0);
|
||||
TEST(memcmp(alltypes.rep_fbytes[4], "2019", 4) == 0);
|
||||
|
||||
TEST(alltypes.rep_farray[0] == 0 && alltypes.rep_farray[4] == 2040);
|
||||
TEST(alltypes.rep_farray2[0] == 0 && alltypes.rep_farray2[2] == 2095);
|
||||
|
||||
TEST(alltypes.req_limits.int32_min == INT32_MIN);
|
||||
TEST(alltypes.req_limits.int32_max == INT32_MAX);
|
||||
TEST(alltypes.req_limits.uint32_min == 0);
|
||||
TEST(alltypes.req_limits.uint32_max == UINT32_MAX);
|
||||
TEST(alltypes.req_limits.int64_min == INT64_MIN);
|
||||
TEST(alltypes.req_limits.int64_max == INT64_MAX);
|
||||
TEST(alltypes.req_limits.uint64_min == 0);
|
||||
TEST(alltypes.req_limits.uint64_max == UINT64_MAX);
|
||||
TEST(alltypes.req_limits.enum_min == HugeEnum_Negative);
|
||||
TEST(alltypes.req_limits.enum_max == HugeEnum_Positive);
|
||||
TEST(alltypes.req_limits.largetag == 1001);
|
||||
|
||||
TEST(alltypes.req_ds8.first == 9991);
|
||||
TEST(alltypes.req_ds8.second == 9992);
|
||||
|
||||
TEST(alltypes.req_intsizes.req_int8 == -128);
|
||||
TEST(alltypes.req_intsizes.req_uint8 == 255);
|
||||
TEST(alltypes.req_intsizes.req_sint8 == -128);
|
||||
TEST(alltypes.req_intsizes.req_int16 == -32768);
|
||||
TEST(alltypes.req_intsizes.req_uint16 == 65535);
|
||||
TEST(alltypes.req_intsizes.req_sint16 == -32768);
|
||||
}
|
||||
|
||||
if (mode == 0)
|
||||
{
|
||||
/* Expect default values */
|
||||
TEST(alltypes.has_opt_int32 == false);
|
||||
TEST(alltypes.opt_int32 == 4041);
|
||||
TEST(alltypes.has_opt_int64 == false);
|
||||
TEST(alltypes.opt_int64 == 4042);
|
||||
TEST(alltypes.has_opt_uint32 == false);
|
||||
TEST(alltypes.opt_uint32 == 4043);
|
||||
TEST(alltypes.has_opt_uint64 == false);
|
||||
TEST(alltypes.opt_uint64 == 4044);
|
||||
TEST(alltypes.has_opt_sint32 == false);
|
||||
TEST(alltypes.opt_sint32 == 4045);
|
||||
TEST(alltypes.has_opt_sint64 == false);
|
||||
TEST(alltypes.opt_sint64 == 4046);
|
||||
TEST(alltypes.has_opt_bool == false);
|
||||
TEST(alltypes.opt_bool == false);
|
||||
|
||||
TEST(alltypes.has_opt_fixed32 == false);
|
||||
TEST(alltypes.opt_fixed32 == 4048);
|
||||
TEST(alltypes.has_opt_sfixed32 == false);
|
||||
TEST(alltypes.opt_sfixed32 == 4049);
|
||||
TEST(alltypes.has_opt_float == false);
|
||||
TEST(alltypes.opt_float == 4050.0f);
|
||||
|
||||
TEST(alltypes.has_opt_fixed64 == false);
|
||||
TEST(alltypes.opt_fixed64 == 4051);
|
||||
TEST(alltypes.has_opt_sfixed64 == false);
|
||||
TEST(alltypes.opt_sfixed64 == 4052);
|
||||
TEST(alltypes.has_opt_double == false);
|
||||
TEST(alltypes.opt_double == 4053.0);
|
||||
|
||||
TEST(alltypes.has_opt_string == false);
|
||||
TEST(strcmp(alltypes.opt_string, "4054") == 0);
|
||||
TEST(alltypes.has_opt_bytes == false);
|
||||
TEST(alltypes.opt_bytes.size == 4);
|
||||
TEST(memcmp(alltypes.opt_bytes.bytes, "\x34\x5C\x00\xff", 4) == 0);
|
||||
TEST(alltypes.has_opt_submsg == false);
|
||||
TEST(strcmp(alltypes.opt_submsg.substuff1, "1") == 0);
|
||||
TEST(alltypes.opt_submsg.substuff2 == 2);
|
||||
TEST(alltypes.opt_submsg.substuff3 == 3);
|
||||
TEST(alltypes.has_opt_enum == false);
|
||||
TEST(alltypes.opt_enum == MyEnum_Second);
|
||||
TEST(alltypes.has_opt_emptymsg == false);
|
||||
TEST(alltypes.has_opt_fbytes == false);
|
||||
TEST(memcmp(alltypes.opt_fbytes, "4059", 4) == 0);
|
||||
|
||||
TEST(alltypes.which_oneof == 0);
|
||||
|
||||
TEST(alltypes.has_opt_non_zero_based_enum == false);
|
||||
TEST(alltypes.opt_non_zero_based_enum == NonZeroBasedEnum_Two);
|
||||
}
|
||||
else if (mode == 1)
|
||||
{
|
||||
/* Expect filled-in values */
|
||||
TEST(alltypes.has_opt_int32 == true);
|
||||
TEST(alltypes.opt_int32 == 3041);
|
||||
TEST(alltypes.has_opt_int64 == true);
|
||||
TEST(alltypes.opt_int64 == 3042);
|
||||
TEST(alltypes.has_opt_uint32 == true);
|
||||
TEST(alltypes.opt_uint32 == 3043);
|
||||
TEST(alltypes.has_opt_uint64 == true);
|
||||
TEST(alltypes.opt_uint64 == 3044);
|
||||
TEST(alltypes.has_opt_sint32 == true);
|
||||
TEST(alltypes.opt_sint32 == 3045);
|
||||
TEST(alltypes.has_opt_sint64 == true);
|
||||
TEST(alltypes.opt_sint64 == 3046);
|
||||
TEST(alltypes.has_opt_bool == true);
|
||||
TEST(alltypes.opt_bool == true);
|
||||
|
||||
TEST(alltypes.has_opt_fixed32 == true);
|
||||
TEST(alltypes.opt_fixed32 == 3048);
|
||||
TEST(alltypes.has_opt_sfixed32 == true);
|
||||
TEST(alltypes.opt_sfixed32 == 3049);
|
||||
TEST(alltypes.has_opt_float == true);
|
||||
TEST(alltypes.opt_float == 3050.0f);
|
||||
|
||||
TEST(alltypes.has_opt_fixed64 == true);
|
||||
TEST(alltypes.opt_fixed64 == 3051);
|
||||
TEST(alltypes.has_opt_sfixed64 == true);
|
||||
TEST(alltypes.opt_sfixed64 == 3052);
|
||||
TEST(alltypes.has_opt_double == true);
|
||||
TEST(alltypes.opt_double == 3053.0);
|
||||
|
||||
TEST(alltypes.has_opt_string == true);
|
||||
TEST(strcmp(alltypes.opt_string, "3054") == 0);
|
||||
TEST(alltypes.has_opt_bytes == true);
|
||||
TEST(alltypes.opt_bytes.size == 4);
|
||||
TEST(memcmp(alltypes.opt_bytes.bytes, "3055", 4) == 0);
|
||||
TEST(alltypes.has_opt_submsg == true);
|
||||
TEST(strcmp(alltypes.opt_submsg.substuff1, "3056") == 0);
|
||||
TEST(alltypes.opt_submsg.substuff2 == 3056);
|
||||
TEST(alltypes.opt_submsg.substuff3 == 3);
|
||||
TEST(alltypes.has_opt_enum == true);
|
||||
TEST(alltypes.opt_enum == MyEnum_Truth);
|
||||
TEST(alltypes.has_opt_emptymsg == true);
|
||||
TEST(alltypes.has_opt_fbytes == true);
|
||||
TEST(memcmp(alltypes.opt_fbytes, "3059", 4) == 0);
|
||||
|
||||
TEST(alltypes.which_oneof == AllTypes_oneof_msg1_tag);
|
||||
TEST(strcmp(alltypes.oneof.oneof_msg1.substuff1, "4059") == 0);
|
||||
TEST(alltypes.oneof.oneof_msg1.substuff2 == 4059);
|
||||
TEST(alltypes.oneof.oneof_msg1.substuff3 == 3);
|
||||
|
||||
TEST(alltypes.has_opt_non_zero_based_enum == true);
|
||||
TEST(alltypes.opt_non_zero_based_enum == NonZeroBasedEnum_Three);
|
||||
}
|
||||
else if (mode == 2)
|
||||
{
|
||||
/* Expect zero values */
|
||||
TEST(alltypes.req_int32 == 0);
|
||||
TEST(alltypes.req_int64 == 0);
|
||||
TEST(alltypes.req_uint32 == 0);
|
||||
TEST(alltypes.req_uint64 == 0);
|
||||
TEST(alltypes.req_sint32 == 0);
|
||||
TEST(alltypes.req_sint64 == 0);
|
||||
TEST(alltypes.req_bool == false);
|
||||
|
||||
TEST(alltypes.req_fixed32 == 0);
|
||||
TEST(alltypes.req_sfixed32 == 0);
|
||||
TEST(alltypes.req_float == 0.0f);
|
||||
|
||||
TEST(alltypes.req_fixed64 == 0);
|
||||
TEST(alltypes.req_sfixed64 == 0);
|
||||
TEST(alltypes.req_double == 0.0f);
|
||||
|
||||
TEST(strcmp(alltypes.req_string, "") == 0);
|
||||
TEST(alltypes.req_bytes.size == 0);
|
||||
TEST(strcmp(alltypes.req_submsg.substuff1, "") == 0);
|
||||
TEST(alltypes.req_submsg.substuff2 == 0);
|
||||
TEST(alltypes.req_enum == MyEnum_Zero);
|
||||
|
||||
TEST(alltypes.rep_int32_count == 0);
|
||||
TEST(alltypes.rep_int64_count == 0);
|
||||
TEST(alltypes.rep_uint32_count == 0);
|
||||
TEST(alltypes.rep_uint64_count == 0);
|
||||
TEST(alltypes.rep_sint32_count == 0);
|
||||
TEST(alltypes.rep_sint64_count == 0);
|
||||
TEST(alltypes.rep_bool_count == 0);
|
||||
|
||||
TEST(alltypes.rep_fixed32_count == 0);
|
||||
TEST(alltypes.rep_sfixed32_count == 0);
|
||||
TEST(alltypes.rep_float_count == 0);
|
||||
|
||||
TEST(alltypes.rep_fixed64_count == 0);
|
||||
TEST(alltypes.rep_sfixed64_count == 0);
|
||||
TEST(alltypes.rep_double_count == 0);
|
||||
|
||||
TEST(alltypes.rep_string_count == 0);
|
||||
TEST(alltypes.rep_bytes_count == 0);
|
||||
|
||||
TEST(alltypes.rep_submsg_count == 0);
|
||||
|
||||
TEST(alltypes.rep_enum_count == 0);
|
||||
TEST(alltypes.rep_emptymsg_count == 0);
|
||||
TEST(alltypes.rep_fbytes_count == 0);
|
||||
TEST(alltypes.rep_farray[0] == 0 && alltypes.rep_farray[4] == 0);
|
||||
|
||||
TEST(alltypes.has_opt_int32 == false);
|
||||
TEST(alltypes.has_opt_int64 == false);
|
||||
TEST(alltypes.has_opt_uint32 == false);
|
||||
TEST(alltypes.has_opt_uint64 == false);
|
||||
TEST(alltypes.has_opt_sint32 == false);
|
||||
TEST(alltypes.has_opt_sint64 == false);
|
||||
TEST(alltypes.has_opt_bool == false);
|
||||
|
||||
TEST(alltypes.has_opt_fixed32 == false);
|
||||
TEST(alltypes.has_opt_sfixed32 == false);
|
||||
TEST(alltypes.has_opt_float == false);
|
||||
|
||||
TEST(alltypes.has_opt_fixed64 == false);
|
||||
TEST(alltypes.has_opt_sfixed64 == false);
|
||||
TEST(alltypes.has_opt_double == false);
|
||||
|
||||
TEST(alltypes.has_opt_string == false);
|
||||
TEST(alltypes.has_opt_bytes == false);
|
||||
TEST(alltypes.has_opt_submsg == false);
|
||||
TEST(alltypes.has_opt_enum == false);
|
||||
TEST(alltypes.has_opt_emptymsg == false);
|
||||
TEST(alltypes.has_opt_fbytes == false);
|
||||
|
||||
TEST(alltypes.which_oneof == 0);
|
||||
|
||||
TEST(alltypes.has_opt_non_zero_based_enum == false);
|
||||
}
|
||||
|
||||
TEST(alltypes.end == 1099);
|
||||
|
||||
return status == 0;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
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 */
|
||||
SET_BINARY_MODE(stdin);
|
||||
count = fread(buffer, 1, sizeof(buffer), stdin);
|
||||
|
||||
/* Construct a pb_istream_t for reading from the buffer */
|
||||
stream = pb_istream_from_buffer(buffer, count);
|
||||
|
||||
/* Decode and print out the stuff */
|
||||
if (!check_alltypes(&stream, mode))
|
||||
{
|
||||
printf("Parsing failed: %s\n", PB_GET_ERROR(&stream));
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,178 @@
|
||||
/* Attempts to test all the datatypes supported by ProtoBuf.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <pb_encode.h>
|
||||
#include "alltypes.pb.h"
|
||||
#include "test_helpers.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int mode = (argc > 1) ? atoi(argv[1]) : 0;
|
||||
|
||||
/* Initialize the structure with constants */
|
||||
AllTypes alltypes = AllTypes_init_zero;
|
||||
|
||||
if (mode == 0 || mode == 1)
|
||||
{
|
||||
alltypes.req_int32 = -1001;
|
||||
alltypes.req_int64 = -1002;
|
||||
alltypes.req_uint32 = 1003;
|
||||
alltypes.req_uint64 = 1004;
|
||||
alltypes.req_sint32 = -1005;
|
||||
alltypes.req_sint64 = -1006;
|
||||
alltypes.req_bool = true;
|
||||
|
||||
alltypes.req_fixed32 = 1008;
|
||||
alltypes.req_sfixed32 = -1009;
|
||||
alltypes.req_float = 1010.0f;
|
||||
|
||||
alltypes.req_fixed64 = 1011;
|
||||
alltypes.req_sfixed64 = -1012;
|
||||
alltypes.req_double = 1013.0;
|
||||
|
||||
strcpy(alltypes.req_string, "1014");
|
||||
alltypes.req_bytes.size = 4;
|
||||
memcpy(alltypes.req_bytes.bytes, "1015", 4);
|
||||
strcpy(alltypes.req_submsg.substuff1, "1016");
|
||||
alltypes.req_submsg.substuff2 = 1016;
|
||||
alltypes.req_enum = MyEnum_Truth;
|
||||
memcpy(alltypes.req_fbytes, "1019", 4);
|
||||
|
||||
alltypes.rep_int32_count = 5; alltypes.rep_int32[4] = -2001;
|
||||
alltypes.rep_int64_count = 5; alltypes.rep_int64[4] = -2002;
|
||||
alltypes.rep_uint32_count = 5; alltypes.rep_uint32[4] = 2003;
|
||||
alltypes.rep_uint64_count = 5; alltypes.rep_uint64[4] = 2004;
|
||||
alltypes.rep_sint32_count = 5; alltypes.rep_sint32[4] = -2005;
|
||||
alltypes.rep_sint64_count = 5; alltypes.rep_sint64[4] = -2006;
|
||||
alltypes.rep_bool_count = 5; alltypes.rep_bool[4] = true;
|
||||
|
||||
alltypes.rep_fixed32_count = 5; alltypes.rep_fixed32[4] = 2008;
|
||||
alltypes.rep_sfixed32_count = 5; alltypes.rep_sfixed32[4] = -2009;
|
||||
alltypes.rep_float_count = 5; alltypes.rep_float[4] = 2010.0f;
|
||||
|
||||
alltypes.rep_fixed64_count = 5; alltypes.rep_fixed64[4] = 2011;
|
||||
alltypes.rep_sfixed64_count = 5; alltypes.rep_sfixed64[4] = -2012;
|
||||
alltypes.rep_double_count = 5; alltypes.rep_double[4] = 2013.0;
|
||||
|
||||
alltypes.rep_string_count = 5; strcpy(alltypes.rep_string[4], "2014");
|
||||
alltypes.rep_bytes_count = 5; alltypes.rep_bytes[4].size = 4;
|
||||
memcpy(alltypes.rep_bytes[4].bytes, "2015", 4);
|
||||
|
||||
alltypes.rep_submsg_count = 5;
|
||||
strcpy(alltypes.rep_submsg[4].substuff1, "2016");
|
||||
alltypes.rep_submsg[4].substuff2 = 2016;
|
||||
alltypes.rep_submsg[4].has_substuff3 = true;
|
||||
alltypes.rep_submsg[4].substuff3 = 2016;
|
||||
|
||||
alltypes.rep_enum_count = 5; alltypes.rep_enum[4] = MyEnum_Truth;
|
||||
alltypes.rep_emptymsg_count = 5;
|
||||
|
||||
alltypes.rep_fbytes_count = 5;
|
||||
memcpy(alltypes.rep_fbytes[4], "2019", 4);
|
||||
|
||||
alltypes.rep_farray[4] = 2040;
|
||||
alltypes.rep_farray2[2] = 2095;
|
||||
|
||||
alltypes.req_limits.int32_min = INT32_MIN;
|
||||
alltypes.req_limits.int32_max = INT32_MAX;
|
||||
alltypes.req_limits.uint32_min = 0;
|
||||
alltypes.req_limits.uint32_max = UINT32_MAX;
|
||||
alltypes.req_limits.int64_min = INT64_MIN;
|
||||
alltypes.req_limits.int64_max = INT64_MAX;
|
||||
alltypes.req_limits.uint64_min = 0;
|
||||
alltypes.req_limits.uint64_max = UINT64_MAX;
|
||||
alltypes.req_limits.enum_min = HugeEnum_Negative;
|
||||
alltypes.req_limits.enum_max = HugeEnum_Positive;
|
||||
alltypes.req_limits.largetag = 1001;
|
||||
|
||||
alltypes.req_ds8.first = 9991;
|
||||
alltypes.req_ds8.second = 9992;
|
||||
|
||||
alltypes.req_intsizes.req_int8 = -128;
|
||||
alltypes.req_intsizes.req_uint8 = 255;
|
||||
alltypes.req_intsizes.req_sint8 = -128;
|
||||
alltypes.req_intsizes.req_int16 = -32768;
|
||||
alltypes.req_intsizes.req_uint16 = 65535;
|
||||
alltypes.req_intsizes.req_sint16 = -32768;
|
||||
}
|
||||
|
||||
if (mode == 1)
|
||||
{
|
||||
/* Fill in values for optional fields */
|
||||
alltypes.has_opt_int32 = true;
|
||||
alltypes.opt_int32 = 3041;
|
||||
alltypes.has_opt_int64 = true;
|
||||
alltypes.opt_int64 = 3042;
|
||||
alltypes.has_opt_uint32 = true;
|
||||
alltypes.opt_uint32 = 3043;
|
||||
alltypes.has_opt_uint64 = true;
|
||||
alltypes.opt_uint64 = 3044;
|
||||
alltypes.has_opt_sint32 = true;
|
||||
alltypes.opt_sint32 = 3045;
|
||||
alltypes.has_opt_sint64 = true;
|
||||
alltypes.opt_sint64 = 3046;
|
||||
alltypes.has_opt_bool = true;
|
||||
alltypes.opt_bool = true;
|
||||
|
||||
alltypes.has_opt_fixed32 = true;
|
||||
alltypes.opt_fixed32 = 3048;
|
||||
alltypes.has_opt_sfixed32 = true;
|
||||
alltypes.opt_sfixed32 = 3049;
|
||||
alltypes.has_opt_float = true;
|
||||
alltypes.opt_float = 3050.0f;
|
||||
|
||||
alltypes.has_opt_fixed64 = true;
|
||||
alltypes.opt_fixed64 = 3051;
|
||||
alltypes.has_opt_sfixed64 = true;
|
||||
alltypes.opt_sfixed64 = 3052;
|
||||
alltypes.has_opt_double = true;
|
||||
alltypes.opt_double = 3053.0;
|
||||
|
||||
alltypes.has_opt_string = true;
|
||||
strcpy(alltypes.opt_string, "3054");
|
||||
alltypes.has_opt_bytes = true;
|
||||
alltypes.opt_bytes.size = 4;
|
||||
memcpy(alltypes.opt_bytes.bytes, "3055", 4);
|
||||
alltypes.has_opt_submsg = true;
|
||||
strcpy(alltypes.opt_submsg.substuff1, "3056");
|
||||
alltypes.opt_submsg.substuff2 = 3056;
|
||||
alltypes.has_opt_enum = true;
|
||||
alltypes.opt_enum = MyEnum_Truth;
|
||||
alltypes.has_opt_emptymsg = true;
|
||||
alltypes.has_opt_fbytes = true;
|
||||
memcpy(alltypes.opt_fbytes, "3059", 4);
|
||||
|
||||
alltypes.which_oneof = AllTypes_oneof_msg1_tag;
|
||||
strcpy(alltypes.oneof.oneof_msg1.substuff1, "4059");
|
||||
alltypes.oneof.oneof_msg1.substuff2 = 4059;
|
||||
|
||||
alltypes.has_opt_non_zero_based_enum = true;
|
||||
alltypes.opt_non_zero_based_enum = NonZeroBasedEnum_Three;
|
||||
}
|
||||
|
||||
alltypes.end = 1099;
|
||||
|
||||
{
|
||||
uint8_t buffer[AllTypes_size];
|
||||
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 */
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
# Test the AllTypes encoding & decoding using callbacks for all fields.
|
||||
|
||||
Import("env", "malloc_env")
|
||||
|
||||
c = Copy("$TARGET", "$SOURCE")
|
||||
env.Command("alltypes.proto", "#alltypes/alltypes.proto", c)
|
||||
|
||||
env.NanopbProto(["alltypes", "alltypes.options"])
|
||||
enc = env.Program(["encode_alltypes_callback.c", "alltypes.pb.c", "$COMMON/pb_encode.o", "$COMMON/pb_common.o"])
|
||||
dec = env.Program(["decode_alltypes_callback.c", "alltypes.pb.c", "$COMMON/pb_decode.o", "$COMMON/pb_common.o"])
|
||||
|
||||
refdec = "$BUILD/alltypes/decode_alltypes$PROGSUFFIX"
|
||||
|
||||
# Encode and compare results
|
||||
env.RunTest(enc)
|
||||
env.RunTest("decode_alltypes.output", [refdec, "encode_alltypes_callback.output"])
|
||||
env.RunTest("decode_alltypes_callback.output", [dec, "encode_alltypes_callback.output"])
|
||||
|
||||
# Do the same thing with the optional fields present
|
||||
env.RunTest("optionals.output", enc, ARGS = ['1'])
|
||||
env.RunTest("optionals.refdecout", [refdec, "optionals.output"], ARGS = ['1'])
|
||||
env.RunTest("optionals.decout", [dec, "optionals.output"], ARGS = ['1'])
|
||||
|
||||
# Try with malloc support also
|
||||
mallocbin1 = malloc_env.Object("decode_with_malloc.o", "decode_alltypes_callback.c")
|
||||
mallocbin2 = malloc_env.Object("alltypes_malloc.pb.o", "alltypes.pb.c")
|
||||
mallocdec = malloc_env.Program("decode_with_malloc", [mallocbin1, mallocbin2, "$COMMON/pb_decode_with_malloc.o", "$COMMON/pb_common_with_malloc.o", "$COMMON/malloc_wrappers.o"])
|
||||
env.RunTest("decode_with_malloc.output", [mallocdec, "encode_alltypes_callback.output"])
|
||||
@@ -0,0 +1,10 @@
|
||||
# Generate all fields as callbacks.
|
||||
AllTypes.* type:FT_CALLBACK
|
||||
SubMessage.substuff1 max_size:16
|
||||
AllTypes.oneof no_unions:true
|
||||
DescriptorSize8 descriptorsize:DS_8
|
||||
|
||||
# With FT_CALLBACK, these options should get ignored
|
||||
*.*fbytes fixed_length:true max_size:4
|
||||
*.*farray fixed_count:true max_count:5
|
||||
|
||||
@@ -0,0 +1,492 @@
|
||||
/* Attempts to test all the datatypes supported by ProtoBuf when used as callback fields.
|
||||
* Note that normally there would be no reason to use callback fields for this,
|
||||
* because each encoder defined here only gives a single field.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <pb_decode.h>
|
||||
#include "alltypes.pb.h"
|
||||
#include "test_helpers.h"
|
||||
|
||||
#define TEST(x) if (!(x)) { \
|
||||
printf("Test %s failed (in field %d).\n", #x, field->tag); \
|
||||
return false; \
|
||||
}
|
||||
|
||||
static bool read_varint(pb_istream_t *stream, const pb_field_t *field, void **arg)
|
||||
{
|
||||
uint64_t value;
|
||||
if (!pb_decode_varint(stream, &value))
|
||||
return false;
|
||||
|
||||
TEST((int64_t)value == (intptr_t)*arg);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool read_svarint(pb_istream_t *stream, const pb_field_t *field, void **arg)
|
||||
{
|
||||
int64_t value;
|
||||
if (!pb_decode_svarint(stream, &value))
|
||||
return false;
|
||||
|
||||
TEST(value == (intptr_t)*arg);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool read_fixed32(pb_istream_t *stream, const pb_field_t *field, void **arg)
|
||||
{
|
||||
uint32_t value;
|
||||
if (!pb_decode_fixed32(stream, &value))
|
||||
return false;
|
||||
|
||||
TEST(value == *(uint32_t*)*arg);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool read_fixed64(pb_istream_t *stream, const pb_field_t *field, void **arg)
|
||||
{
|
||||
uint64_t value;
|
||||
if (!pb_decode_fixed64(stream, &value))
|
||||
return false;
|
||||
|
||||
TEST(value == *(uint64_t*)*arg);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool read_double(pb_istream_t *stream, const pb_field_t *field, void **arg)
|
||||
{
|
||||
#ifdef PB_CONVERT_DOUBLE_FLOAT
|
||||
if (sizeof(double) == sizeof(float))
|
||||
{
|
||||
float value;
|
||||
if (!pb_decode_double_as_float(stream, &value))
|
||||
return false;
|
||||
|
||||
TEST(memcmp(&value, *arg, sizeof(float)) == 0);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
uint64_t value;
|
||||
if (!pb_decode_fixed64(stream, &value))
|
||||
return false;
|
||||
|
||||
TEST(value == *(uint64_t*)*arg);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool read_string(pb_istream_t *stream, const pb_field_t *field, void **arg)
|
||||
{
|
||||
uint8_t buf[16] = {0};
|
||||
size_t len = stream->bytes_left;
|
||||
|
||||
if (len > sizeof(buf) - 1 || !pb_read(stream, buf, len))
|
||||
return false;
|
||||
|
||||
TEST(strcmp((char*)buf, *arg) == 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool read_submsg(pb_istream_t *stream, const pb_field_t *field, void **arg)
|
||||
{
|
||||
SubMessage submsg = {""};
|
||||
SubMessage *ref = *arg;
|
||||
|
||||
if (!pb_decode(stream, SubMessage_fields, &submsg))
|
||||
return false;
|
||||
|
||||
TEST(strcmp(submsg.substuff1, ref->substuff1) == 0);
|
||||
TEST(submsg.substuff2 == ref->substuff2);
|
||||
TEST(submsg.has_substuff3 == ref->has_substuff3);
|
||||
TEST(submsg.substuff3 == ref->substuff3);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool read_emptymsg(pb_istream_t *stream, const pb_field_t *field, void **arg)
|
||||
{
|
||||
EmptyMessage emptymsg = {0};
|
||||
return pb_decode(stream, EmptyMessage_fields, &emptymsg);
|
||||
}
|
||||
|
||||
static bool read_repeated_varint(pb_istream_t *stream, const pb_field_t *field, void **arg)
|
||||
{
|
||||
int32_t** expected = (int32_t**)arg;
|
||||
uint64_t value;
|
||||
if (!pb_decode_varint(stream, &value))
|
||||
return false;
|
||||
|
||||
TEST(*(*expected)++ == value);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool read_repeated_svarint(pb_istream_t *stream, const pb_field_t *field, void **arg)
|
||||
{
|
||||
int32_t** expected = (int32_t**)arg;
|
||||
int64_t value;
|
||||
if (!pb_decode_svarint(stream, &value))
|
||||
return false;
|
||||
|
||||
TEST(*(*expected)++ == value);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool read_repeated_fixed32(pb_istream_t *stream, const pb_field_t *field, void **arg)
|
||||
{
|
||||
uint32_t** expected = (uint32_t**)arg;
|
||||
uint32_t value;
|
||||
if (!pb_decode_fixed32(stream, &value))
|
||||
return false;
|
||||
|
||||
TEST(*(*expected)++ == value);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool read_repeated_fixed64(pb_istream_t *stream, const pb_field_t *field, void **arg)
|
||||
{
|
||||
uint64_t** expected = (uint64_t**)arg;
|
||||
uint64_t value;
|
||||
if (!pb_decode_fixed64(stream, &value))
|
||||
return false;
|
||||
|
||||
TEST(*(*expected)++ == value);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool read_repeated_double(pb_istream_t *stream, const pb_field_t *field, void **arg)
|
||||
{
|
||||
#ifdef PB_CONVERT_DOUBLE_FLOAT
|
||||
if (sizeof(double) == sizeof(float))
|
||||
{
|
||||
float** expectedf = (float**)arg;
|
||||
float value;
|
||||
if (!pb_decode_double_as_float(stream, &value))
|
||||
return false;
|
||||
|
||||
TEST(memcmp(&value, (*expectedf)++, sizeof(float)) == 0);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
uint64_t** expected = (uint64_t**)arg;
|
||||
uint64_t value;
|
||||
if (!pb_decode_fixed64(stream, &value))
|
||||
return false;
|
||||
|
||||
TEST(*(*expected)++ == value);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool read_repeated_string(pb_istream_t *stream, const pb_field_t *field, void **arg)
|
||||
{
|
||||
uint8_t*** expected = (uint8_t***)arg;
|
||||
uint8_t buf[16] = {0};
|
||||
size_t len = stream->bytes_left;
|
||||
|
||||
if (len > sizeof(buf) - 1 || !pb_read(stream, buf, len))
|
||||
return false;
|
||||
|
||||
TEST(strcmp((char*)*(*expected)++, (char*)buf) == 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool read_repeated_submsg(pb_istream_t *stream, const pb_field_t *field, void **arg)
|
||||
{
|
||||
SubMessage** expected = (SubMessage**)arg;
|
||||
SubMessage submsg = {""};
|
||||
if (!pb_decode(stream, SubMessage_fields, &submsg))
|
||||
return false;
|
||||
|
||||
TEST(strcmp(submsg.substuff1, (*expected)->substuff1) == 0);
|
||||
TEST(submsg.substuff2 == (*expected)->substuff2);
|
||||
TEST(submsg.has_substuff3 == (*expected)->has_substuff3);
|
||||
TEST(submsg.substuff3 == (*expected)->substuff3);
|
||||
(*expected)++;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool read_limits(pb_istream_t *stream, const pb_field_t *field, void **arg)
|
||||
{
|
||||
Limits decoded = {0};
|
||||
if (!pb_decode(stream, Limits_fields, &decoded))
|
||||
return false;
|
||||
|
||||
TEST(decoded.int32_min == INT32_MIN);
|
||||
TEST(decoded.int32_max == INT32_MAX);
|
||||
TEST(decoded.uint32_min == 0);
|
||||
TEST(decoded.uint32_max == UINT32_MAX);
|
||||
TEST(decoded.int64_min == INT64_MIN);
|
||||
TEST(decoded.int64_max == INT64_MAX);
|
||||
TEST(decoded.uint64_min == 0);
|
||||
TEST(decoded.uint64_max == UINT64_MAX);
|
||||
TEST(decoded.enum_min == HugeEnum_Negative);
|
||||
TEST(decoded.enum_max == HugeEnum_Positive);
|
||||
TEST(decoded.largetag == 1001);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* This function is called once from main(), it handles
|
||||
the decoding and checks the fields. */
|
||||
bool check_alltypes(pb_istream_t *stream, int mode)
|
||||
{
|
||||
/* Values for use from callbacks through pointers. */
|
||||
bool status;
|
||||
uint32_t req_fixed32 = 1008;
|
||||
int32_t req_sfixed32 = -1009;
|
||||
float req_float = 1010.0f;
|
||||
uint64_t req_fixed64 = 1011;
|
||||
int64_t req_sfixed64 = -1012;
|
||||
double req_double = 1013.0;
|
||||
SubMessage req_submsg = {"1016", 1016, false, 3};
|
||||
|
||||
int32_t rep_int32[5] = {0, 0, 0, 0, -2001};
|
||||
int32_t rep_int64[5] = {0, 0, 0, 0, -2002};
|
||||
int32_t rep_uint32[5] = {0, 0, 0, 0, 2003};
|
||||
int32_t rep_uint64[5] = {0, 0, 0, 0, 2004};
|
||||
int32_t rep_sint32[5] = {0, 0, 0, 0, -2005};
|
||||
int32_t rep_sint64[5] = {0, 0, 0, 0, -2006};
|
||||
int32_t rep_bool[5] = {false, false, false, false, true};
|
||||
uint32_t rep_fixed32[5] = {0, 0, 0, 0, 2008};
|
||||
int32_t rep_sfixed32[5] = {0, 0, 0, 0, -2009};
|
||||
float rep_float[5] = {0, 0, 0, 0, 2010.0f};
|
||||
uint64_t rep_fixed64[5] = {0, 0, 0, 0, 2011};
|
||||
int64_t rep_sfixed64[5] = {0, 0, 0, 0, -2012};
|
||||
double rep_double[5] = {0, 0, 0, 0, 2013.0};
|
||||
char* rep_string[5] = {"", "", "", "", "2014"};
|
||||
char* rep_bytes[5] = {"", "", "", "", "2015"};
|
||||
SubMessage rep_submsg[5] = {{"", 0, 0, 3},
|
||||
{"", 0, 0, 3},
|
||||
{"", 0, 0, 3},
|
||||
{"", 0, 0, 3},
|
||||
{"2016", 2016, true, 2016}};
|
||||
int32_t rep_enum[5] = {0, 0, 0, 0, MyEnum_Truth};
|
||||
|
||||
uint32_t opt_fixed32 = 3048;
|
||||
int32_t opt_sfixed32 = 3049;
|
||||
float opt_float = 3050.0f;
|
||||
uint64_t opt_fixed64 = 3051;
|
||||
int64_t opt_sfixed64 = 3052;
|
||||
double opt_double = 3053.0f;
|
||||
SubMessage opt_submsg = {"3056", 3056, false, 3};
|
||||
|
||||
SubMessage oneof_msg1 = {"4059", 4059, false, 3};
|
||||
|
||||
/* Bind callbacks for required fields */
|
||||
AllTypes alltypes = AllTypes_init_zero;
|
||||
|
||||
alltypes.req_int32.funcs.decode = &read_varint;
|
||||
alltypes.req_int32.arg = (void*)-1001;
|
||||
|
||||
alltypes.req_int64.funcs.decode = &read_varint;
|
||||
alltypes.req_int64.arg = (void*)-1002;
|
||||
|
||||
alltypes.req_uint32.funcs.decode = &read_varint;
|
||||
alltypes.req_uint32.arg = (void*)1003;
|
||||
|
||||
alltypes.req_uint32.funcs.decode = &read_varint;
|
||||
alltypes.req_uint32.arg = (void*)1003;
|
||||
|
||||
alltypes.req_uint64.funcs.decode = &read_varint;
|
||||
alltypes.req_uint64.arg = (void*)1004;
|
||||
|
||||
alltypes.req_sint32.funcs.decode = &read_svarint;
|
||||
alltypes.req_sint32.arg = (void*)-1005;
|
||||
|
||||
alltypes.req_sint64.funcs.decode = &read_svarint;
|
||||
alltypes.req_sint64.arg = (void*)-1006;
|
||||
|
||||
alltypes.req_bool.funcs.decode = &read_varint;
|
||||
alltypes.req_bool.arg = (void*)true;
|
||||
|
||||
alltypes.req_fixed32.funcs.decode = &read_fixed32;
|
||||
alltypes.req_fixed32.arg = &req_fixed32;
|
||||
|
||||
alltypes.req_sfixed32.funcs.decode = &read_fixed32;
|
||||
alltypes.req_sfixed32.arg = &req_sfixed32;
|
||||
|
||||
alltypes.req_float.funcs.decode = &read_fixed32;
|
||||
alltypes.req_float.arg = &req_float;
|
||||
|
||||
alltypes.req_fixed64.funcs.decode = &read_fixed64;
|
||||
alltypes.req_fixed64.arg = &req_fixed64;
|
||||
|
||||
alltypes.req_sfixed64.funcs.decode = &read_fixed64;
|
||||
alltypes.req_sfixed64.arg = &req_sfixed64;
|
||||
|
||||
alltypes.req_double.funcs.decode = &read_double;
|
||||
alltypes.req_double.arg = &req_double;
|
||||
|
||||
alltypes.req_string.funcs.decode = &read_string;
|
||||
alltypes.req_string.arg = "1014";
|
||||
|
||||
alltypes.req_bytes.funcs.decode = &read_string;
|
||||
alltypes.req_bytes.arg = "1015";
|
||||
|
||||
alltypes.req_submsg.funcs.decode = &read_submsg;
|
||||
alltypes.req_submsg.arg = &req_submsg;
|
||||
|
||||
alltypes.req_enum.funcs.decode = &read_varint;
|
||||
alltypes.req_enum.arg = (void*)MyEnum_Truth;
|
||||
|
||||
alltypes.req_emptymsg.funcs.decode = &read_emptymsg;
|
||||
|
||||
/* Bind callbacks for repeated fields */
|
||||
alltypes.rep_int32.funcs.decode = &read_repeated_varint;
|
||||
alltypes.rep_int32.arg = rep_int32;
|
||||
|
||||
alltypes.rep_int64.funcs.decode = &read_repeated_varint;
|
||||
alltypes.rep_int64.arg = rep_int64;
|
||||
|
||||
alltypes.rep_uint32.funcs.decode = &read_repeated_varint;
|
||||
alltypes.rep_uint32.arg = rep_uint32;
|
||||
|
||||
alltypes.rep_uint64.funcs.decode = &read_repeated_varint;
|
||||
alltypes.rep_uint64.arg = rep_uint64;
|
||||
|
||||
alltypes.rep_sint32.funcs.decode = &read_repeated_svarint;
|
||||
alltypes.rep_sint32.arg = rep_sint32;
|
||||
|
||||
alltypes.rep_sint64.funcs.decode = &read_repeated_svarint;
|
||||
alltypes.rep_sint64.arg = rep_sint64;
|
||||
|
||||
alltypes.rep_bool.funcs.decode = &read_repeated_varint;
|
||||
alltypes.rep_bool.arg = rep_bool;
|
||||
|
||||
alltypes.rep_fixed32.funcs.decode = &read_repeated_fixed32;
|
||||
alltypes.rep_fixed32.arg = rep_fixed32;
|
||||
|
||||
alltypes.rep_sfixed32.funcs.decode = &read_repeated_fixed32;
|
||||
alltypes.rep_sfixed32.arg = rep_sfixed32;
|
||||
|
||||
alltypes.rep_float.funcs.decode = &read_repeated_fixed32;
|
||||
alltypes.rep_float.arg = rep_float;
|
||||
|
||||
alltypes.rep_fixed64.funcs.decode = &read_repeated_fixed64;
|
||||
alltypes.rep_fixed64.arg = rep_fixed64;
|
||||
|
||||
alltypes.rep_sfixed64.funcs.decode = &read_repeated_fixed64;
|
||||
alltypes.rep_sfixed64.arg = rep_sfixed64;
|
||||
|
||||
alltypes.rep_double.funcs.decode = &read_repeated_double;
|
||||
alltypes.rep_double.arg = rep_double;
|
||||
|
||||
alltypes.rep_string.funcs.decode = &read_repeated_string;
|
||||
alltypes.rep_string.arg = rep_string;
|
||||
|
||||
alltypes.rep_bytes.funcs.decode = &read_repeated_string;
|
||||
alltypes.rep_bytes.arg = rep_bytes;
|
||||
|
||||
alltypes.rep_submsg.funcs.decode = &read_repeated_submsg;
|
||||
alltypes.rep_submsg.arg = rep_submsg;
|
||||
|
||||
alltypes.rep_enum.funcs.decode = &read_repeated_varint;
|
||||
alltypes.rep_enum.arg = rep_enum;
|
||||
|
||||
alltypes.rep_emptymsg.funcs.decode = &read_emptymsg;
|
||||
|
||||
alltypes.req_limits.funcs.decode = &read_limits;
|
||||
|
||||
alltypes.end.funcs.decode = &read_varint;
|
||||
alltypes.end.arg = (void*)1099;
|
||||
|
||||
/* Bind callbacks for optional fields */
|
||||
if (mode == 1)
|
||||
{
|
||||
alltypes.opt_int32.funcs.decode = &read_varint;
|
||||
alltypes.opt_int32.arg = (void*)3041;
|
||||
|
||||
alltypes.opt_int64.funcs.decode = &read_varint;
|
||||
alltypes.opt_int64.arg = (void*)3042;
|
||||
|
||||
alltypes.opt_uint32.funcs.decode = &read_varint;
|
||||
alltypes.opt_uint32.arg = (void*)3043;
|
||||
|
||||
alltypes.opt_uint64.funcs.decode = &read_varint;
|
||||
alltypes.opt_uint64.arg = (void*)3044;
|
||||
|
||||
alltypes.opt_sint32.funcs.decode = &read_svarint;
|
||||
alltypes.opt_sint32.arg = (void*)3045;
|
||||
|
||||
alltypes.opt_sint64.funcs.decode = &read_svarint;
|
||||
alltypes.opt_sint64.arg = (void*)3046;
|
||||
|
||||
alltypes.opt_bool.funcs.decode = &read_varint;
|
||||
alltypes.opt_bool.arg = (void*)true;
|
||||
|
||||
alltypes.opt_fixed32.funcs.decode = &read_fixed32;
|
||||
alltypes.opt_fixed32.arg = &opt_fixed32;
|
||||
|
||||
alltypes.opt_sfixed32.funcs.decode = &read_fixed32;
|
||||
alltypes.opt_sfixed32.arg = &opt_sfixed32;
|
||||
|
||||
alltypes.opt_float.funcs.decode = &read_fixed32;
|
||||
alltypes.opt_float.arg = &opt_float;
|
||||
|
||||
alltypes.opt_fixed64.funcs.decode = &read_fixed64;
|
||||
alltypes.opt_fixed64.arg = &opt_fixed64;
|
||||
|
||||
alltypes.opt_sfixed64.funcs.decode = &read_fixed64;
|
||||
alltypes.opt_sfixed64.arg = &opt_sfixed64;
|
||||
|
||||
alltypes.opt_double.funcs.decode = &read_double;
|
||||
alltypes.opt_double.arg = &opt_double;
|
||||
|
||||
alltypes.opt_string.funcs.decode = &read_string;
|
||||
alltypes.opt_string.arg = "3054";
|
||||
|
||||
alltypes.opt_bytes.funcs.decode = &read_string;
|
||||
alltypes.opt_bytes.arg = "3055";
|
||||
|
||||
alltypes.opt_submsg.funcs.decode = &read_submsg;
|
||||
alltypes.opt_submsg.arg = &opt_submsg;
|
||||
|
||||
alltypes.opt_enum.funcs.decode = &read_varint;
|
||||
alltypes.opt_enum.arg = (void*)MyEnum_Truth;
|
||||
|
||||
alltypes.opt_emptymsg.funcs.decode = &read_emptymsg;
|
||||
|
||||
alltypes.oneof_msg1.funcs.decode = &read_submsg;
|
||||
alltypes.oneof_msg1.arg = &oneof_msg1;
|
||||
|
||||
alltypes.opt_non_zero_based_enum.funcs.decode = &read_varint;
|
||||
alltypes.opt_non_zero_based_enum.arg = (void *)NonZeroBasedEnum_Three;
|
||||
}
|
||||
|
||||
status = pb_decode(stream, AllTypes_fields, &alltypes);
|
||||
|
||||
#ifdef PB_ENABLE_MALLOC
|
||||
/* Just to check for any interference between pb_release() and callback fields */
|
||||
pb_release(AllTypes_fields, &alltypes);
|
||||
#endif
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
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 */
|
||||
SET_BINARY_MODE(stdin);
|
||||
count = fread(buffer, 1, sizeof(buffer), stdin);
|
||||
|
||||
/* Construct a pb_istream_t for reading from the buffer */
|
||||
stream = pb_istream_from_buffer(buffer, count);
|
||||
|
||||
/* Decode and print out the stuff */
|
||||
if (!check_alltypes(&stream, mode))
|
||||
{
|
||||
printf("Parsing failed: %s\n", PB_GET_ERROR(&stream));
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,491 @@
|
||||
/* Attempts to test all the datatypes supported by ProtoBuf when used as callback fields.
|
||||
* Note that normally there would be no reason to use callback fields for this,
|
||||
* because each encoder defined here only gives a single field.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <pb_encode.h>
|
||||
#include "alltypes.pb.h"
|
||||
#include "test_helpers.h"
|
||||
|
||||
static bool write_varint(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
|
||||
{
|
||||
return pb_encode_tag_for_field(stream, field) &&
|
||||
pb_encode_varint(stream, (intptr_t)*arg);
|
||||
}
|
||||
|
||||
static bool write_svarint(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
|
||||
{
|
||||
return pb_encode_tag_for_field(stream, field) &&
|
||||
pb_encode_svarint(stream, (intptr_t)*arg);
|
||||
}
|
||||
|
||||
static bool write_fixed32(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
|
||||
{
|
||||
return pb_encode_tag_for_field(stream, field) &&
|
||||
pb_encode_fixed32(stream, *arg);
|
||||
}
|
||||
|
||||
static bool write_fixed64(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
|
||||
{
|
||||
return pb_encode_tag_for_field(stream, field) &&
|
||||
pb_encode_fixed64(stream, *arg);
|
||||
}
|
||||
|
||||
static bool write_double(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
|
||||
{
|
||||
#ifdef PB_CONVERT_DOUBLE_FLOAT
|
||||
if (sizeof(double) == sizeof(float))
|
||||
return pb_encode_tag_for_field(stream, field) &&
|
||||
pb_encode_float_as_double(stream, *(float*)*arg);
|
||||
#endif
|
||||
|
||||
return pb_encode_tag_for_field(stream, field) &&
|
||||
pb_encode_fixed64(stream, *arg);
|
||||
}
|
||||
|
||||
static bool write_string(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
|
||||
{
|
||||
return pb_encode_tag_for_field(stream, field) &&
|
||||
pb_encode_string(stream, *arg, strlen(*arg));
|
||||
}
|
||||
|
||||
static bool write_submsg(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
|
||||
{
|
||||
|
||||
return pb_encode_tag_for_field(stream, field) &&
|
||||
pb_encode_submessage(stream, SubMessage_fields, *arg);
|
||||
}
|
||||
|
||||
static bool write_emptymsg(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
|
||||
{
|
||||
EmptyMessage emptymsg = {0};
|
||||
return pb_encode_tag_for_field(stream, field) &&
|
||||
pb_encode_submessage(stream, EmptyMessage_fields, &emptymsg);
|
||||
}
|
||||
|
||||
static bool write_repeated_varint(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
|
||||
{
|
||||
return pb_encode_tag_for_field(stream, field) &&
|
||||
pb_encode_varint(stream, 0) &&
|
||||
pb_encode_tag_for_field(stream, field) &&
|
||||
pb_encode_varint(stream, 0) &&
|
||||
pb_encode_tag_for_field(stream, field) &&
|
||||
pb_encode_varint(stream, 0) &&
|
||||
pb_encode_tag_for_field(stream, field) &&
|
||||
pb_encode_varint(stream, 0) &&
|
||||
pb_encode_tag_for_field(stream, field) &&
|
||||
pb_encode_varint(stream, (intptr_t)*arg);
|
||||
}
|
||||
|
||||
static bool write_repeated_svarint(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
|
||||
{
|
||||
return pb_encode_tag_for_field(stream, field) &&
|
||||
pb_encode_svarint(stream, 0) &&
|
||||
pb_encode_tag_for_field(stream, field) &&
|
||||
pb_encode_svarint(stream, 0) &&
|
||||
pb_encode_tag_for_field(stream, field) &&
|
||||
pb_encode_svarint(stream, 0) &&
|
||||
pb_encode_tag_for_field(stream, field) &&
|
||||
pb_encode_svarint(stream, 0) &&
|
||||
pb_encode_tag_for_field(stream, field) &&
|
||||
pb_encode_svarint(stream, (intptr_t)*arg);
|
||||
}
|
||||
|
||||
static bool write_repeated_fixed32(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
|
||||
{
|
||||
uint32_t dummy = 0;
|
||||
|
||||
/* Make it a packed field */
|
||||
return pb_encode_tag(stream, PB_WT_STRING, field->tag) &&
|
||||
pb_encode_varint(stream, 5 * 4) && /* Number of bytes */
|
||||
pb_encode_fixed32(stream, &dummy) &&
|
||||
pb_encode_fixed32(stream, &dummy) &&
|
||||
pb_encode_fixed32(stream, &dummy) &&
|
||||
pb_encode_fixed32(stream, &dummy) &&
|
||||
pb_encode_fixed32(stream, *arg);
|
||||
}
|
||||
|
||||
static bool write_repeated_fixed64(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
|
||||
{
|
||||
uint64_t dummy = 0;
|
||||
|
||||
/* Make it a packed field */
|
||||
return pb_encode_tag(stream, PB_WT_STRING, field->tag) &&
|
||||
pb_encode_varint(stream, 5 * 8) && /* Number of bytes */
|
||||
pb_encode_fixed64(stream, &dummy) &&
|
||||
pb_encode_fixed64(stream, &dummy) &&
|
||||
pb_encode_fixed64(stream, &dummy) &&
|
||||
pb_encode_fixed64(stream, &dummy) &&
|
||||
pb_encode_fixed64(stream, *arg);
|
||||
}
|
||||
|
||||
static bool write_repeated_double(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
|
||||
{
|
||||
uint64_t dummy = 0;
|
||||
|
||||
#ifdef PB_CONVERT_DOUBLE_FLOAT
|
||||
if (sizeof(double) == sizeof(float))
|
||||
return pb_encode_tag(stream, PB_WT_STRING, field->tag) &&
|
||||
pb_encode_varint(stream, 5 * 8) && /* Number of bytes */
|
||||
pb_encode_float_as_double(stream, 0.0f) &&
|
||||
pb_encode_float_as_double(stream, 0.0f) &&
|
||||
pb_encode_float_as_double(stream, 0.0f) &&
|
||||
pb_encode_float_as_double(stream, 0.0f) &&
|
||||
pb_encode_float_as_double(stream, *(float*)*arg);
|
||||
#endif
|
||||
|
||||
/* Make it a packed field */
|
||||
return pb_encode_tag(stream, PB_WT_STRING, field->tag) &&
|
||||
pb_encode_varint(stream, 5 * 8) && /* Number of bytes */
|
||||
pb_encode_fixed64(stream, &dummy) &&
|
||||
pb_encode_fixed64(stream, &dummy) &&
|
||||
pb_encode_fixed64(stream, &dummy) &&
|
||||
pb_encode_fixed64(stream, &dummy) &&
|
||||
pb_encode_fixed64(stream, *arg);
|
||||
}
|
||||
|
||||
static bool write_repeated_string(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
|
||||
{
|
||||
return pb_encode_tag_for_field(stream, field) &&
|
||||
pb_encode_string(stream, 0, 0) &&
|
||||
pb_encode_tag_for_field(stream, field) &&
|
||||
pb_encode_string(stream, 0, 0) &&
|
||||
pb_encode_tag_for_field(stream, field) &&
|
||||
pb_encode_string(stream, 0, 0) &&
|
||||
pb_encode_tag_for_field(stream, field) &&
|
||||
pb_encode_string(stream, 0, 0) &&
|
||||
pb_encode_tag_for_field(stream, field) &&
|
||||
pb_encode_string(stream, *arg, strlen(*arg));
|
||||
}
|
||||
|
||||
static bool write_repeated_submsg(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
|
||||
{
|
||||
SubMessage dummy = {""};
|
||||
|
||||
return pb_encode_tag_for_field(stream, field) &&
|
||||
pb_encode_submessage(stream, SubMessage_fields, &dummy) &&
|
||||
pb_encode_tag_for_field(stream, field) &&
|
||||
pb_encode_submessage(stream, SubMessage_fields, &dummy) &&
|
||||
pb_encode_tag_for_field(stream, field) &&
|
||||
pb_encode_submessage(stream, SubMessage_fields, &dummy) &&
|
||||
pb_encode_tag_for_field(stream, field) &&
|
||||
pb_encode_submessage(stream, SubMessage_fields, &dummy) &&
|
||||
pb_encode_tag_for_field(stream, field) &&
|
||||
pb_encode_submessage(stream, SubMessage_fields, *arg);
|
||||
}
|
||||
|
||||
static bool write_limits(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
|
||||
{
|
||||
Limits limits = {0};
|
||||
limits.int32_min = INT32_MIN;
|
||||
limits.int32_max = INT32_MAX;
|
||||
limits.uint32_min = 0;
|
||||
limits.uint32_max = UINT32_MAX;
|
||||
limits.int64_min = INT64_MIN;
|
||||
limits.int64_max = INT64_MAX;
|
||||
limits.uint64_min = 0;
|
||||
limits.uint64_max = UINT64_MAX;
|
||||
limits.enum_min = HugeEnum_Negative;
|
||||
limits.enum_max = HugeEnum_Positive;
|
||||
limits.largetag = 1001;
|
||||
|
||||
return pb_encode_tag_for_field(stream, field) &&
|
||||
pb_encode_submessage(stream, Limits_fields, &limits);
|
||||
}
|
||||
|
||||
static bool write_ds8(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
|
||||
{
|
||||
DescriptorSize8 ds8 = {9991,9992};
|
||||
|
||||
return pb_encode_tag_for_field(stream, field) &&
|
||||
pb_encode_submessage(stream, DescriptorSize8_fields, &ds8);
|
||||
}
|
||||
|
||||
static bool write_intsizes(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
|
||||
{
|
||||
IntSizes intsizes = {-128, 255, -128, -32768, 65535, -32768};
|
||||
|
||||
return pb_encode_tag_for_field(stream, field) &&
|
||||
pb_encode_submessage(stream, IntSizes_fields, &intsizes);
|
||||
}
|
||||
|
||||
static bool write_repeated_emptymsg(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
|
||||
{
|
||||
EmptyMessage emptymsg = {0};
|
||||
return pb_encode_tag_for_field(stream, field) &&
|
||||
pb_encode_submessage(stream, EmptyMessage_fields, &emptymsg) &&
|
||||
pb_encode_tag_for_field(stream, field) &&
|
||||
pb_encode_submessage(stream, EmptyMessage_fields, &emptymsg) &&
|
||||
pb_encode_tag_for_field(stream, field) &&
|
||||
pb_encode_submessage(stream, EmptyMessage_fields, &emptymsg) &&
|
||||
pb_encode_tag_for_field(stream, field) &&
|
||||
pb_encode_submessage(stream, EmptyMessage_fields, &emptymsg) &&
|
||||
pb_encode_tag_for_field(stream, field) &&
|
||||
pb_encode_submessage(stream, EmptyMessage_fields, &emptymsg);
|
||||
}
|
||||
|
||||
static bool write_farray2(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
|
||||
{
|
||||
uint32_t dummy = 0;
|
||||
uint32_t value = (uint32_t)(intptr_t)*arg;
|
||||
|
||||
/* Make it a packed field */
|
||||
return pb_encode_tag(stream, PB_WT_STRING, field->tag) &&
|
||||
pb_encode_varint(stream, 3 * 4) && /* Number of bytes */
|
||||
pb_encode_fixed32(stream, &dummy) &&
|
||||
pb_encode_fixed32(stream, &dummy) &&
|
||||
pb_encode_fixed32(stream, &value);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int mode = (argc > 1) ? atoi(argv[1]) : 0;
|
||||
|
||||
/* Values for use from callbacks through pointers. */
|
||||
uint32_t req_fixed32 = 1008;
|
||||
int32_t req_sfixed32 = -1009;
|
||||
float req_float = 1010.0f;
|
||||
uint64_t req_fixed64 = 1011;
|
||||
int64_t req_sfixed64 = -1012;
|
||||
double req_double = 1013.0;
|
||||
SubMessage req_submsg = {"1016", 1016};
|
||||
|
||||
uint32_t rep_fixed32 = 2008;
|
||||
int32_t rep_sfixed32 = -2009;
|
||||
float rep_float = 2010.0f;
|
||||
uint64_t rep_fixed64 = 2011;
|
||||
int64_t rep_sfixed64 = -2012;
|
||||
double rep_double = 2013.0;
|
||||
SubMessage rep_submsg = {"2016", 2016, true, 2016};
|
||||
|
||||
uint32_t opt_fixed32 = 3048;
|
||||
int32_t opt_sfixed32 = 3049;
|
||||
float opt_float = 3050.0f;
|
||||
uint64_t opt_fixed64 = 3051;
|
||||
int64_t opt_sfixed64 = 3052;
|
||||
double opt_double = 3053.0f;
|
||||
SubMessage opt_submsg = {"3056", 3056};
|
||||
|
||||
SubMessage oneof_msg1 = {"4059", 4059};
|
||||
|
||||
/* Bind callbacks for required fields */
|
||||
AllTypes alltypes = {{{0}}};
|
||||
|
||||
alltypes.req_int32.funcs.encode = &write_varint;
|
||||
alltypes.req_int32.arg = (void*)-1001;
|
||||
|
||||
alltypes.req_int64.funcs.encode = &write_varint;
|
||||
alltypes.req_int64.arg = (void*)-1002;
|
||||
|
||||
alltypes.req_uint32.funcs.encode = &write_varint;
|
||||
alltypes.req_uint32.arg = (void*)1003;
|
||||
|
||||
alltypes.req_uint32.funcs.encode = &write_varint;
|
||||
alltypes.req_uint32.arg = (void*)1003;
|
||||
|
||||
alltypes.req_uint64.funcs.encode = &write_varint;
|
||||
alltypes.req_uint64.arg = (void*)1004;
|
||||
|
||||
alltypes.req_sint32.funcs.encode = &write_svarint;
|
||||
alltypes.req_sint32.arg = (void*)-1005;
|
||||
|
||||
alltypes.req_sint64.funcs.encode = &write_svarint;
|
||||
alltypes.req_sint64.arg = (void*)-1006;
|
||||
|
||||
alltypes.req_bool.funcs.encode = &write_varint;
|
||||
alltypes.req_bool.arg = (void*)true;
|
||||
|
||||
alltypes.req_fixed32.funcs.encode = &write_fixed32;
|
||||
alltypes.req_fixed32.arg = &req_fixed32;
|
||||
|
||||
alltypes.req_sfixed32.funcs.encode = &write_fixed32;
|
||||
alltypes.req_sfixed32.arg = &req_sfixed32;
|
||||
|
||||
alltypes.req_float.funcs.encode = &write_fixed32;
|
||||
alltypes.req_float.arg = &req_float;
|
||||
|
||||
alltypes.req_fixed64.funcs.encode = &write_fixed64;
|
||||
alltypes.req_fixed64.arg = &req_fixed64;
|
||||
|
||||
alltypes.req_sfixed64.funcs.encode = &write_fixed64;
|
||||
alltypes.req_sfixed64.arg = &req_sfixed64;
|
||||
|
||||
alltypes.req_double.funcs.encode = &write_double;
|
||||
alltypes.req_double.arg = &req_double;
|
||||
|
||||
alltypes.req_string.funcs.encode = &write_string;
|
||||
alltypes.req_string.arg = "1014";
|
||||
|
||||
alltypes.req_bytes.funcs.encode = &write_string;
|
||||
alltypes.req_bytes.arg = "1015";
|
||||
|
||||
alltypes.req_submsg.funcs.encode = &write_submsg;
|
||||
alltypes.req_submsg.arg = &req_submsg;
|
||||
|
||||
alltypes.req_enum.funcs.encode = &write_varint;
|
||||
alltypes.req_enum.arg = (void*)MyEnum_Truth;
|
||||
|
||||
alltypes.req_emptymsg.funcs.encode = &write_emptymsg;
|
||||
|
||||
alltypes.req_fbytes.funcs.encode = &write_string;
|
||||
alltypes.req_fbytes.arg = "1019";
|
||||
|
||||
/* Bind callbacks for repeated fields */
|
||||
alltypes.rep_int32.funcs.encode = &write_repeated_varint;
|
||||
alltypes.rep_int32.arg = (void*)-2001;
|
||||
|
||||
alltypes.rep_int64.funcs.encode = &write_repeated_varint;
|
||||
alltypes.rep_int64.arg = (void*)-2002;
|
||||
|
||||
alltypes.rep_uint32.funcs.encode = &write_repeated_varint;
|
||||
alltypes.rep_uint32.arg = (void*)2003;
|
||||
|
||||
alltypes.rep_uint64.funcs.encode = &write_repeated_varint;
|
||||
alltypes.rep_uint64.arg = (void*)2004;
|
||||
|
||||
alltypes.rep_sint32.funcs.encode = &write_repeated_svarint;
|
||||
alltypes.rep_sint32.arg = (void*)-2005;
|
||||
|
||||
alltypes.rep_sint64.funcs.encode = &write_repeated_svarint;
|
||||
alltypes.rep_sint64.arg = (void*)-2006;
|
||||
|
||||
alltypes.rep_bool.funcs.encode = &write_repeated_varint;
|
||||
alltypes.rep_bool.arg = (void*)true;
|
||||
|
||||
alltypes.rep_fixed32.funcs.encode = &write_repeated_fixed32;
|
||||
alltypes.rep_fixed32.arg = &rep_fixed32;
|
||||
|
||||
alltypes.rep_sfixed32.funcs.encode = &write_repeated_fixed32;
|
||||
alltypes.rep_sfixed32.arg = &rep_sfixed32;
|
||||
|
||||
alltypes.rep_float.funcs.encode = &write_repeated_fixed32;
|
||||
alltypes.rep_float.arg = &rep_float;
|
||||
|
||||
alltypes.rep_fixed64.funcs.encode = &write_repeated_fixed64;
|
||||
alltypes.rep_fixed64.arg = &rep_fixed64;
|
||||
|
||||
alltypes.rep_sfixed64.funcs.encode = &write_repeated_fixed64;
|
||||
alltypes.rep_sfixed64.arg = &rep_sfixed64;
|
||||
|
||||
alltypes.rep_double.funcs.encode = &write_repeated_double;
|
||||
alltypes.rep_double.arg = &rep_double;
|
||||
|
||||
alltypes.rep_string.funcs.encode = &write_repeated_string;
|
||||
alltypes.rep_string.arg = "2014";
|
||||
|
||||
alltypes.rep_bytes.funcs.encode = &write_repeated_string;
|
||||
alltypes.rep_bytes.arg = "2015";
|
||||
|
||||
alltypes.rep_submsg.funcs.encode = &write_repeated_submsg;
|
||||
alltypes.rep_submsg.arg = &rep_submsg;
|
||||
|
||||
alltypes.rep_enum.funcs.encode = &write_repeated_varint;
|
||||
alltypes.rep_enum.arg = (void*)MyEnum_Truth;
|
||||
|
||||
alltypes.rep_emptymsg.funcs.encode = &write_repeated_emptymsg;
|
||||
|
||||
alltypes.rep_fbytes.funcs.encode = &write_repeated_string;
|
||||
alltypes.rep_fbytes.arg = "2019";
|
||||
|
||||
alltypes.rep_farray.funcs.encode = &write_repeated_varint;
|
||||
alltypes.rep_farray.arg = (void*)2040;
|
||||
|
||||
alltypes.rep_farray2.funcs.encode = &write_farray2;
|
||||
alltypes.rep_farray2.arg = (void*)2095;
|
||||
|
||||
alltypes.req_limits.funcs.encode = &write_limits;
|
||||
|
||||
alltypes.req_ds8.funcs.encode = &write_ds8;
|
||||
|
||||
alltypes.req_intsizes.funcs.encode = &write_intsizes;
|
||||
|
||||
/* Bind callbacks for optional fields */
|
||||
if (mode != 0)
|
||||
{
|
||||
alltypes.opt_int32.funcs.encode = &write_varint;
|
||||
alltypes.opt_int32.arg = (void*)3041;
|
||||
|
||||
alltypes.opt_int64.funcs.encode = &write_varint;
|
||||
alltypes.opt_int64.arg = (void*)3042;
|
||||
|
||||
alltypes.opt_uint32.funcs.encode = &write_varint;
|
||||
alltypes.opt_uint32.arg = (void*)3043;
|
||||
|
||||
alltypes.opt_uint64.funcs.encode = &write_varint;
|
||||
alltypes.opt_uint64.arg = (void*)3044;
|
||||
|
||||
alltypes.opt_sint32.funcs.encode = &write_svarint;
|
||||
alltypes.opt_sint32.arg = (void*)3045;
|
||||
|
||||
alltypes.opt_sint64.funcs.encode = &write_svarint;
|
||||
alltypes.opt_sint64.arg = (void*)3046;
|
||||
|
||||
alltypes.opt_bool.funcs.encode = &write_varint;
|
||||
alltypes.opt_bool.arg = (void*)true;
|
||||
|
||||
alltypes.opt_fixed32.funcs.encode = &write_fixed32;
|
||||
alltypes.opt_fixed32.arg = &opt_fixed32;
|
||||
|
||||
alltypes.opt_sfixed32.funcs.encode = &write_fixed32;
|
||||
alltypes.opt_sfixed32.arg = &opt_sfixed32;
|
||||
|
||||
alltypes.opt_float.funcs.encode = &write_fixed32;
|
||||
alltypes.opt_float.arg = &opt_float;
|
||||
|
||||
alltypes.opt_fixed64.funcs.encode = &write_fixed64;
|
||||
alltypes.opt_fixed64.arg = &opt_fixed64;
|
||||
|
||||
alltypes.opt_sfixed64.funcs.encode = &write_fixed64;
|
||||
alltypes.opt_sfixed64.arg = &opt_sfixed64;
|
||||
|
||||
alltypes.opt_double.funcs.encode = &write_double;
|
||||
alltypes.opt_double.arg = &opt_double;
|
||||
|
||||
alltypes.opt_string.funcs.encode = &write_string;
|
||||
alltypes.opt_string.arg = "3054";
|
||||
|
||||
alltypes.opt_bytes.funcs.encode = &write_string;
|
||||
alltypes.opt_bytes.arg = "3055";
|
||||
|
||||
alltypes.opt_submsg.funcs.encode = &write_submsg;
|
||||
alltypes.opt_submsg.arg = &opt_submsg;
|
||||
|
||||
alltypes.opt_enum.funcs.encode = &write_varint;
|
||||
alltypes.opt_enum.arg = (void*)MyEnum_Truth;
|
||||
|
||||
alltypes.opt_emptymsg.funcs.encode = &write_emptymsg;
|
||||
|
||||
alltypes.opt_fbytes.funcs.encode = &write_string;
|
||||
alltypes.opt_fbytes.arg = "3059";
|
||||
|
||||
alltypes.oneof_msg1.funcs.encode = &write_submsg;
|
||||
alltypes.oneof_msg1.arg = &oneof_msg1;
|
||||
|
||||
alltypes.opt_non_zero_based_enum.funcs.encode = &write_varint;
|
||||
alltypes.opt_non_zero_based_enum.arg = (void *)NonZeroBasedEnum_Three;
|
||||
}
|
||||
|
||||
alltypes.end.funcs.encode = &write_varint;
|
||||
alltypes.end.arg = (void*)1099;
|
||||
|
||||
{
|
||||
uint8_t buffer[2048];
|
||||
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 */
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
# Encode the AllTypes message using pointers for all fields, and verify the
|
||||
# output against the normal AllTypes test case.
|
||||
|
||||
Import("env", "malloc_env")
|
||||
|
||||
c = Copy("$TARGET", "$SOURCE")
|
||||
env.Command("alltypes.proto", "#alltypes/alltypes.proto", c)
|
||||
|
||||
env.NanopbProto(["alltypes", "alltypes.options"])
|
||||
enc = malloc_env.Program(["encode_alltypes_pointer.c",
|
||||
"alltypes.pb.c",
|
||||
"$COMMON/pb_encode_with_malloc.o",
|
||||
"$COMMON/pb_common_with_malloc.o",
|
||||
"$COMMON/malloc_wrappers.o"])
|
||||
dec = malloc_env.Program(["decode_alltypes_pointer.c",
|
||||
"alltypes.pb.c",
|
||||
"$COMMON/pb_decode_with_malloc.o",
|
||||
"$COMMON/pb_common_with_malloc.o",
|
||||
"$COMMON/malloc_wrappers.o"])
|
||||
|
||||
# Encode and compare results to non-pointer alltypes test case
|
||||
env.RunTest(enc)
|
||||
env.Compare(["encode_alltypes_pointer.output", "$BUILD/alltypes/encode_alltypes.output"])
|
||||
|
||||
# Decode (under valgrind if available)
|
||||
kwargs = {}
|
||||
if env.get("VALGRIND"):
|
||||
kwargs['COMMAND'] = env['VALGRIND']
|
||||
kwargs['ARGS'] = ["-q", "--error-exitcode=99", dec[0].abspath]
|
||||
|
||||
env.RunTest("decode_alltypes.output", [dec, "encode_alltypes_pointer.output"], **kwargs)
|
||||
|
||||
# Do the same thing with the optional fields present
|
||||
env.RunTest("optionals.output", enc, ARGS = ['1'])
|
||||
env.Compare(["optionals.output", "$BUILD/alltypes/optionals.output"])
|
||||
|
||||
kwargs['ARGS'] = kwargs.get('ARGS', []) + ['1']
|
||||
env.RunTest("optionals.decout", [dec, "optionals.output"], **kwargs)
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
# Generate all fields as pointers.
|
||||
* type:FT_POINTER
|
||||
*.static_msg type:FT_STATIC
|
||||
SubMessage.substuff1 type:FT_STATIC max_size:8
|
||||
*.*fbytes fixed_length:true max_size:4
|
||||
*.*farray fixed_count:true max_count:5
|
||||
*.*farray2 fixed_count:true max_count:3
|
||||
IntSizes.*int8 int_size:IS_8
|
||||
IntSizes.*int16 int_size:IS_16
|
||||
DescriptorSize8 descriptorsize:DS_8
|
||||
|
||||
@@ -0,0 +1,200 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <pb_decode.h>
|
||||
#include "alltypes.pb.h"
|
||||
#include "test_helpers.h"
|
||||
#include "unittests.h"
|
||||
|
||||
/* This function is called once from main(), it handles
|
||||
the decoding and checks the fields. */
|
||||
bool check_alltypes(pb_istream_t *stream, int mode)
|
||||
{
|
||||
int status = 0;
|
||||
AllTypes alltypes;
|
||||
|
||||
/* Fill with garbage to better detect initialization errors */
|
||||
memset(&alltypes, 0xAA, sizeof(alltypes));
|
||||
alltypes.extensions = 0;
|
||||
|
||||
if (!pb_decode(stream, AllTypes_fields, &alltypes))
|
||||
return false;
|
||||
|
||||
TEST(alltypes.req_int32 && *alltypes.req_int32 == -1001);
|
||||
TEST(alltypes.req_int64 && *alltypes.req_int64 == -1002);
|
||||
TEST(alltypes.req_uint32 && *alltypes.req_uint32 == 1003);
|
||||
TEST(alltypes.req_uint64 && *alltypes.req_uint64 == 1004);
|
||||
TEST(alltypes.req_sint32 && *alltypes.req_sint32 == -1005);
|
||||
TEST(alltypes.req_sint64 && *alltypes.req_sint64 == -1006);
|
||||
TEST(alltypes.req_bool && *alltypes.req_bool == true);
|
||||
|
||||
TEST(alltypes.req_fixed32 && *alltypes.req_fixed32 == 1008);
|
||||
TEST(alltypes.req_sfixed32 && *alltypes.req_sfixed32 == -1009);
|
||||
TEST(alltypes.req_float && *alltypes.req_float == 1010.0f);
|
||||
|
||||
TEST(alltypes.req_fixed64 && *alltypes.req_fixed64 == 1011);
|
||||
TEST(alltypes.req_sfixed64 && *alltypes.req_sfixed64 == -1012);
|
||||
TEST(alltypes.req_double && *alltypes.req_double == 1013.0f);
|
||||
|
||||
TEST(alltypes.req_string && strcmp(alltypes.req_string, "1014") == 0);
|
||||
TEST(alltypes.req_bytes && alltypes.req_bytes->size == 4);
|
||||
TEST(alltypes.req_bytes && memcmp(&alltypes.req_bytes->bytes, "1015", 4) == 0);
|
||||
TEST(alltypes.req_submsg && strcmp(alltypes.req_submsg->substuff1, "1016") == 0);
|
||||
TEST(alltypes.req_submsg && alltypes.req_submsg->substuff2
|
||||
&& *alltypes.req_submsg->substuff2 == 1016);
|
||||
TEST(alltypes.req_enum && *alltypes.req_enum == MyEnum_Truth);
|
||||
TEST(alltypes.req_fbytes && memcmp(alltypes.req_fbytes, "1019", 4) == 0);
|
||||
|
||||
TEST(alltypes.rep_int32_count == 5 && alltypes.rep_int32[4] == -2001 && alltypes.rep_int32[0] == 0);
|
||||
TEST(alltypes.rep_int64_count == 5 && alltypes.rep_int64[4] == -2002 && alltypes.rep_int64[0] == 0);
|
||||
TEST(alltypes.rep_uint32_count == 5 && alltypes.rep_uint32[4] == 2003 && alltypes.rep_uint32[0] == 0);
|
||||
TEST(alltypes.rep_uint64_count == 5 && alltypes.rep_uint64[4] == 2004 && alltypes.rep_uint64[0] == 0);
|
||||
TEST(alltypes.rep_sint32_count == 5 && alltypes.rep_sint32[4] == -2005 && alltypes.rep_sint32[0] == 0);
|
||||
TEST(alltypes.rep_sint64_count == 5 && alltypes.rep_sint64[4] == -2006 && alltypes.rep_sint64[0] == 0);
|
||||
TEST(alltypes.rep_bool_count == 5 && alltypes.rep_bool[4] == true && alltypes.rep_bool[0] == false);
|
||||
|
||||
TEST(alltypes.rep_fixed32_count == 5 && alltypes.rep_fixed32[4] == 2008 && alltypes.rep_fixed32[0] == 0);
|
||||
TEST(alltypes.rep_sfixed32_count == 5 && alltypes.rep_sfixed32[4] == -2009 && alltypes.rep_sfixed32[0] == 0);
|
||||
TEST(alltypes.rep_float_count == 5 && alltypes.rep_float[4] == 2010.0f && alltypes.rep_float[0] == 0.0f);
|
||||
|
||||
TEST(alltypes.rep_fixed64_count == 5 && alltypes.rep_fixed64[4] == 2011 && alltypes.rep_fixed64[0] == 0);
|
||||
TEST(alltypes.rep_sfixed64_count == 5 && alltypes.rep_sfixed64[4] == -2012 && alltypes.rep_sfixed64[0] == 0);
|
||||
TEST(alltypes.rep_double_count == 5 && alltypes.rep_double[4] == 2013.0 && alltypes.rep_double[0] == 0.0);
|
||||
|
||||
TEST(alltypes.rep_string_count == 5 && strcmp(alltypes.rep_string[4], "2014") == 0 && alltypes.rep_string[0][0] == '\0');
|
||||
TEST(alltypes.rep_bytes_count == 5 && alltypes.rep_bytes[4]->size == 4 && alltypes.rep_bytes[0]->size == 0);
|
||||
TEST(memcmp(&alltypes.rep_bytes[4]->bytes, "2015", 4) == 0);
|
||||
|
||||
TEST(alltypes.rep_submsg_count == 5);
|
||||
TEST(strcmp(alltypes.rep_submsg[4].substuff1, "2016") == 0 && alltypes.rep_submsg[0].substuff1[0] == '\0');
|
||||
TEST(*alltypes.rep_submsg[4].substuff2 == 2016 && *alltypes.rep_submsg[0].substuff2 == 0);
|
||||
TEST(*alltypes.rep_submsg[4].substuff3 == 2016 && alltypes.rep_submsg[0].substuff3 == NULL);
|
||||
|
||||
TEST(alltypes.rep_enum_count == 5 && alltypes.rep_enum[4] == MyEnum_Truth && alltypes.rep_enum[0] == MyEnum_Zero);
|
||||
TEST(alltypes.rep_emptymsg_count == 5);
|
||||
TEST(alltypes.rep_fbytes_count == 5);
|
||||
TEST(alltypes.rep_fbytes[0][0] == 0 && alltypes.rep_fbytes[0][3] == 0);
|
||||
TEST(memcmp(alltypes.rep_fbytes[4], "2019", 4) == 0);
|
||||
TEST(alltypes.rep_farray && (*alltypes.rep_farray)[0] == 0 && (*alltypes.rep_farray)[4] == 2040);
|
||||
TEST(alltypes.rep_farray2 && (*alltypes.rep_farray2)[0] == 0 && (*alltypes.rep_farray2)[2] == 2095);
|
||||
|
||||
if (mode == 0)
|
||||
{
|
||||
/* Expect that optional values are not present */
|
||||
TEST(alltypes.opt_int32 == NULL);
|
||||
TEST(alltypes.opt_int64 == NULL);
|
||||
TEST(alltypes.opt_uint32 == NULL);
|
||||
TEST(alltypes.opt_uint64 == NULL);
|
||||
TEST(alltypes.opt_sint32 == NULL);
|
||||
TEST(alltypes.opt_sint64 == NULL);
|
||||
TEST(alltypes.opt_bool == NULL);
|
||||
|
||||
TEST(alltypes.opt_fixed32 == NULL);
|
||||
TEST(alltypes.opt_sfixed32 == NULL);
|
||||
TEST(alltypes.opt_float == NULL);
|
||||
TEST(alltypes.opt_fixed64 == NULL);
|
||||
TEST(alltypes.opt_sfixed64 == NULL);
|
||||
TEST(alltypes.opt_double == NULL);
|
||||
|
||||
TEST(alltypes.opt_string == NULL);
|
||||
TEST(alltypes.opt_bytes == NULL);
|
||||
TEST(alltypes.opt_submsg == NULL);
|
||||
TEST(alltypes.opt_enum == NULL);
|
||||
TEST(alltypes.opt_fbytes == NULL);
|
||||
|
||||
TEST(alltypes.which_oneof == 0);
|
||||
|
||||
TEST(alltypes.opt_non_zero_based_enum == NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Expect filled-in values */
|
||||
TEST(alltypes.opt_int32 && *alltypes.opt_int32 == 3041);
|
||||
TEST(alltypes.opt_int64 && *alltypes.opt_int64 == 3042);
|
||||
TEST(alltypes.opt_uint32 && *alltypes.opt_uint32 == 3043);
|
||||
TEST(alltypes.opt_uint64 && *alltypes.opt_uint64 == 3044);
|
||||
TEST(alltypes.opt_sint32 && *alltypes.opt_sint32 == 3045);
|
||||
TEST(alltypes.opt_sint64 && *alltypes.opt_sint64 == 3046);
|
||||
TEST(alltypes.opt_bool && *alltypes.opt_bool == true);
|
||||
|
||||
TEST(alltypes.opt_fixed32 && *alltypes.opt_fixed32 == 3048);
|
||||
TEST(alltypes.opt_sfixed32 && *alltypes.opt_sfixed32== 3049);
|
||||
TEST(alltypes.opt_float && *alltypes.opt_float == 3050.0f);
|
||||
TEST(alltypes.opt_fixed64 && *alltypes.opt_fixed64 == 3051);
|
||||
TEST(alltypes.opt_sfixed64 && *alltypes.opt_sfixed64== 3052);
|
||||
TEST(alltypes.opt_double && *alltypes.opt_double == 3053.0);
|
||||
|
||||
TEST(alltypes.opt_string && strcmp(alltypes.opt_string, "3054") == 0);
|
||||
TEST(alltypes.opt_bytes && alltypes.opt_bytes->size == 4);
|
||||
TEST(alltypes.opt_bytes && memcmp(&alltypes.opt_bytes->bytes, "3055", 4) == 0);
|
||||
TEST(alltypes.opt_submsg && strcmp(alltypes.opt_submsg->substuff1, "3056") == 0);
|
||||
TEST(alltypes.opt_submsg && *alltypes.opt_submsg->substuff2 == 3056);
|
||||
TEST(alltypes.opt_enum && *alltypes.opt_enum == MyEnum_Truth);
|
||||
TEST(alltypes.opt_emptymsg);
|
||||
TEST(alltypes.opt_fbytes && memcmp(alltypes.opt_fbytes, "3059", 4) == 0);
|
||||
|
||||
TEST(alltypes.which_oneof == AllTypes_oneof_msg1_tag);
|
||||
TEST(alltypes.oneof.oneof_msg1 && strcmp(alltypes.oneof.oneof_msg1->substuff1, "4059") == 0);
|
||||
TEST(alltypes.oneof.oneof_msg1->substuff2 && *alltypes.oneof.oneof_msg1->substuff2 == 4059);
|
||||
|
||||
TEST(alltypes.opt_non_zero_based_enum && *alltypes.opt_non_zero_based_enum == NonZeroBasedEnum_Three);
|
||||
}
|
||||
|
||||
TEST(alltypes.req_limits->int32_min && *alltypes.req_limits->int32_min == INT32_MIN);
|
||||
TEST(alltypes.req_limits->int32_max && *alltypes.req_limits->int32_max == INT32_MAX);
|
||||
TEST(alltypes.req_limits->uint32_min && *alltypes.req_limits->uint32_min == 0);
|
||||
TEST(alltypes.req_limits->uint32_max && *alltypes.req_limits->uint32_max == UINT32_MAX);
|
||||
TEST(alltypes.req_limits->int64_min && *alltypes.req_limits->int64_min == INT64_MIN);
|
||||
TEST(alltypes.req_limits->int64_max && *alltypes.req_limits->int64_max == INT64_MAX);
|
||||
TEST(alltypes.req_limits->uint64_min && *alltypes.req_limits->uint64_min == 0);
|
||||
TEST(alltypes.req_limits->uint64_max && *alltypes.req_limits->uint64_max == UINT64_MAX);
|
||||
TEST(alltypes.req_limits->enum_min && *alltypes.req_limits->enum_min == HugeEnum_Negative);
|
||||
TEST(alltypes.req_limits->enum_max && *alltypes.req_limits->enum_max == HugeEnum_Positive);
|
||||
TEST(alltypes.req_limits->largetag && *alltypes.req_limits->largetag == 1001);
|
||||
|
||||
TEST(alltypes.req_ds8);
|
||||
TEST(alltypes.req_ds8->first && *alltypes.req_ds8->first == 9991);
|
||||
TEST(alltypes.req_ds8->first && *alltypes.req_ds8->second == 9992);
|
||||
|
||||
TEST(alltypes.req_intsizes);
|
||||
TEST(*alltypes.req_intsizes->req_int8 == -128);
|
||||
TEST(*alltypes.req_intsizes->req_uint8 == 255);
|
||||
TEST(*alltypes.req_intsizes->req_sint8 == -128);
|
||||
TEST(*alltypes.req_intsizes->req_int16 == -32768);
|
||||
TEST(*alltypes.req_intsizes->req_uint16 == 65535);
|
||||
TEST(*alltypes.req_intsizes->req_sint16 == -32768);
|
||||
|
||||
TEST(alltypes.end && *alltypes.end == 1099);
|
||||
|
||||
pb_release(AllTypes_fields, &alltypes);
|
||||
|
||||
return status == 0;
|
||||
}
|
||||
|
||||
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 */
|
||||
SET_BINARY_MODE(stdin);
|
||||
count = fread(buffer, 1, sizeof(buffer), stdin);
|
||||
|
||||
/* Construct a pb_istream_t for reading from the buffer */
|
||||
stream = pb_istream_from_buffer(buffer, count);
|
||||
|
||||
/* Decode and verify the message */
|
||||
if (!check_alltypes(&stream, mode))
|
||||
{
|
||||
fprintf(stderr, "Test failed: %s\n", PB_GET_ERROR(&stream));
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,227 @@
|
||||
/* Attempts to test all the datatypes supported by ProtoBuf.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <pb_encode.h>
|
||||
#include "alltypes.pb.h"
|
||||
#include "test_helpers.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int mode = (argc > 1) ? atoi(argv[1]) : 0;
|
||||
|
||||
/* Values for required fields */
|
||||
int32_t req_int32 = -1001;
|
||||
int64_t req_int64 = -1002;
|
||||
uint32_t req_uint32 = 1003;
|
||||
uint64_t req_uint64 = 1004;
|
||||
int32_t req_sint32 = -1005;
|
||||
int64_t req_sint64 = -1006;
|
||||
bool req_bool = true;
|
||||
uint32_t req_fixed32 = 1008;
|
||||
int32_t req_sfixed32 = -1009;
|
||||
float req_float = 1010.0f;
|
||||
uint64_t req_fixed64 = 1011;
|
||||
int64_t req_sfixed64 = -1012;
|
||||
double req_double = 1013.0;
|
||||
char* req_string = "1014";
|
||||
PB_BYTES_ARRAY_T(4) req_bytes = {4, {'1', '0', '1', '5'}};
|
||||
static int32_t req_substuff = 1016;
|
||||
SubMessage req_submsg = {"1016", &req_substuff};
|
||||
MyEnum req_enum = MyEnum_Truth;
|
||||
EmptyMessage req_emptymsg = {0};
|
||||
pb_byte_t req_fbytes[4] = {'1', '0', '1', '9'};
|
||||
|
||||
int32_t end = 1099;
|
||||
|
||||
/* Values for repeated fields */
|
||||
int32_t rep_int32[5] = {0, 0, 0, 0, -2001};
|
||||
int64_t rep_int64[5] = {0, 0, 0, 0, -2002};
|
||||
uint32_t rep_uint32[5] = {0, 0, 0, 0, 2003};
|
||||
uint64_t rep_uint64[5] = {0, 0, 0, 0, 2004};
|
||||
int32_t rep_sint32[5] = {0, 0, 0, 0, -2005};
|
||||
int64_t rep_sint64[5] = {0, 0, 0, 0, -2006};
|
||||
bool rep_bool[5] = {false, false, false, false, true};
|
||||
uint32_t rep_fixed32[5] = {0, 0, 0, 0, 2008};
|
||||
int32_t rep_sfixed32[5] = {0, 0, 0, 0, -2009};
|
||||
float rep_float[5] = {0, 0, 0, 0, 2010.0f};
|
||||
uint64_t rep_fixed64[5] = {0, 0, 0, 0, 2011};
|
||||
int64_t rep_sfixed64[5] = {0, 0, 0, 0, -2012};
|
||||
double rep_double[5] = {0, 0, 0, 0, 2013.0f};
|
||||
char* rep_string[5] = {"", "", "", "", "2014"};
|
||||
static PB_BYTES_ARRAY_T(4) rep_bytes_4 = {4, {'2', '0', '1', '5'}};
|
||||
pb_bytes_array_t *rep_bytes[5]= {NULL, NULL, NULL, NULL, (pb_bytes_array_t*)&rep_bytes_4};
|
||||
static int32_t rep_sub2zero = 0;
|
||||
static int32_t rep_substuff2 = 2016;
|
||||
static uint32_t rep_substuff3 = 2016;
|
||||
SubMessage rep_submsg[5] = {{"", &rep_sub2zero},
|
||||
{"", &rep_sub2zero},
|
||||
{"", &rep_sub2zero},
|
||||
{"", &rep_sub2zero},
|
||||
{"2016", &rep_substuff2, &rep_substuff3}};
|
||||
MyEnum rep_enum[5] = {0, 0, 0, 0, MyEnum_Truth};
|
||||
EmptyMessage rep_emptymsg[5] = {{0}, {0}, {0}, {0}, {0}};
|
||||
pb_byte_t rep_fbytes[5][4] = {{0}, {0}, {0}, {0}, {'2', '0', '1', '9'}};
|
||||
int32_t rep_farray[5] = {0, 0, 0, 0, 2040};
|
||||
uint32_t rep_farray2[3] = {0, 0, 2095};
|
||||
|
||||
/* Values for optional fields */
|
||||
int32_t opt_int32 = 3041;
|
||||
int64_t opt_int64 = 3042;
|
||||
uint32_t opt_uint32 = 3043;
|
||||
uint64_t opt_uint64 = 3044;
|
||||
int32_t opt_sint32 = 3045;
|
||||
int64_t opt_sint64 = 3046;
|
||||
bool opt_bool = true;
|
||||
uint32_t opt_fixed32 = 3048;
|
||||
int32_t opt_sfixed32 = 3049;
|
||||
float opt_float = 3050.0f;
|
||||
uint64_t opt_fixed64 = 3051;
|
||||
int64_t opt_sfixed64 = 3052;
|
||||
double opt_double = 3053.0;
|
||||
char* opt_string = "3054";
|
||||
PB_BYTES_ARRAY_T(4) opt_bytes = {4, {'3', '0', '5', '5'}};
|
||||
static int32_t opt_substuff = 3056;
|
||||
SubMessage opt_submsg = {"3056", &opt_substuff};
|
||||
MyEnum opt_enum = MyEnum_Truth;
|
||||
EmptyMessage opt_emptymsg = {0};
|
||||
pb_byte_t opt_fbytes[4] = {'3', '0', '5', '9'};
|
||||
|
||||
static int32_t oneof_substuff = 4059;
|
||||
SubMessage oneof_msg1 = {"4059", &oneof_substuff};
|
||||
|
||||
NonZeroBasedEnum opt_non_zero_based_enum = NonZeroBasedEnum_Three;
|
||||
|
||||
/* Values for the Limits message. */
|
||||
static int32_t int32_min = INT32_MIN;
|
||||
static int32_t int32_max = INT32_MAX;
|
||||
static uint32_t uint32_min = 0;
|
||||
static uint32_t uint32_max = UINT32_MAX;
|
||||
static int64_t int64_min = INT64_MIN;
|
||||
static int64_t int64_max = INT64_MAX;
|
||||
static uint64_t uint64_min = 0;
|
||||
static uint64_t uint64_max = UINT64_MAX;
|
||||
static HugeEnum enum_min = HugeEnum_Negative;
|
||||
static HugeEnum enum_max = HugeEnum_Positive;
|
||||
static int32_t largetag = 1001;
|
||||
Limits req_limits = {&int32_min, &int32_max,
|
||||
&uint32_min, &uint32_max,
|
||||
&int64_min, &int64_max,
|
||||
&uint64_min, &uint64_max,
|
||||
&enum_min, &enum_max,
|
||||
&largetag};
|
||||
|
||||
/* Values for DescriptorSize8 message. */
|
||||
static int32_t first = 9991;
|
||||
static int32_t second = 9992;
|
||||
DescriptorSize8 req_ds8 = {&first, &second};
|
||||
|
||||
/* Values for IntSizes message. */
|
||||
static int8_t req_int8 = -128;
|
||||
static uint8_t req_uint8 = 255;
|
||||
static int8_t req_sint8 = -128;
|
||||
static int16_t req_int16 = -32768;
|
||||
static uint16_t req_uint16 = 65535;
|
||||
static int16_t req_sint16 = -32768;
|
||||
IntSizes req_intsizes = {&req_int8, &req_uint8, &req_sint8,
|
||||
&req_int16, &req_uint16, &req_sint16};
|
||||
|
||||
/* Initialize the message struct with pointers to the fields. */
|
||||
AllTypes alltypes = {0};
|
||||
|
||||
alltypes.req_int32 = &req_int32;
|
||||
alltypes.req_int64 = &req_int64;
|
||||
alltypes.req_uint32 = &req_uint32;
|
||||
alltypes.req_uint64 = &req_uint64;
|
||||
alltypes.req_sint32 = &req_sint32;
|
||||
alltypes.req_sint64 = &req_sint64;
|
||||
alltypes.req_bool = &req_bool;
|
||||
alltypes.req_fixed32 = &req_fixed32;
|
||||
alltypes.req_sfixed32 = &req_sfixed32;
|
||||
alltypes.req_float = &req_float;
|
||||
alltypes.req_fixed64 = &req_fixed64;
|
||||
alltypes.req_sfixed64 = &req_sfixed64;
|
||||
alltypes.req_double = &req_double;
|
||||
alltypes.req_string = req_string;
|
||||
alltypes.req_bytes = (pb_bytes_array_t*)&req_bytes;
|
||||
alltypes.req_submsg = &req_submsg;
|
||||
alltypes.req_enum = &req_enum;
|
||||
alltypes.req_emptymsg = &req_emptymsg;
|
||||
alltypes.req_fbytes = &req_fbytes;
|
||||
alltypes.req_limits = &req_limits;
|
||||
alltypes.req_ds8 = &req_ds8;
|
||||
alltypes.req_intsizes = &req_intsizes;
|
||||
|
||||
alltypes.rep_int32_count = 5; alltypes.rep_int32 = rep_int32;
|
||||
alltypes.rep_int64_count = 5; alltypes.rep_int64 = rep_int64;
|
||||
alltypes.rep_uint32_count = 5; alltypes.rep_uint32 = rep_uint32;
|
||||
alltypes.rep_uint64_count = 5; alltypes.rep_uint64 = rep_uint64;
|
||||
alltypes.rep_sint32_count = 5; alltypes.rep_sint32 = rep_sint32;
|
||||
alltypes.rep_sint64_count = 5; alltypes.rep_sint64 = rep_sint64;
|
||||
alltypes.rep_bool_count = 5; alltypes.rep_bool = rep_bool;
|
||||
alltypes.rep_fixed32_count = 5; alltypes.rep_fixed32 = rep_fixed32;
|
||||
alltypes.rep_sfixed32_count = 5; alltypes.rep_sfixed32 = rep_sfixed32;
|
||||
alltypes.rep_float_count = 5; alltypes.rep_float = rep_float;
|
||||
alltypes.rep_fixed64_count = 5; alltypes.rep_fixed64 = rep_fixed64;
|
||||
alltypes.rep_sfixed64_count = 5; alltypes.rep_sfixed64 = rep_sfixed64;
|
||||
alltypes.rep_double_count = 5; alltypes.rep_double = rep_double;
|
||||
alltypes.rep_string_count = 5; alltypes.rep_string = rep_string;
|
||||
alltypes.rep_bytes_count = 5; alltypes.rep_bytes = rep_bytes;
|
||||
alltypes.rep_submsg_count = 5; alltypes.rep_submsg = rep_submsg;
|
||||
alltypes.rep_enum_count = 5; alltypes.rep_enum = rep_enum;
|
||||
alltypes.rep_emptymsg_count = 5; alltypes.rep_emptymsg = rep_emptymsg;
|
||||
alltypes.rep_fbytes_count = 5; alltypes.rep_fbytes = rep_fbytes;
|
||||
alltypes.rep_farray = &rep_farray;
|
||||
alltypes.rep_farray2 = &rep_farray2;
|
||||
|
||||
if (mode != 0)
|
||||
{
|
||||
/* Fill in values for optional fields */
|
||||
alltypes.opt_int32 = &opt_int32;
|
||||
alltypes.opt_int64 = &opt_int64;
|
||||
alltypes.opt_uint32 = &opt_uint32;
|
||||
alltypes.opt_uint64 = &opt_uint64;
|
||||
alltypes.opt_sint32 = &opt_sint32;
|
||||
alltypes.opt_sint64 = &opt_sint64;
|
||||
alltypes.opt_bool = &opt_bool;
|
||||
alltypes.opt_fixed32 = &opt_fixed32;
|
||||
alltypes.opt_sfixed32 = &opt_sfixed32;
|
||||
alltypes.opt_float = &opt_float;
|
||||
alltypes.opt_fixed64 = &opt_fixed64;
|
||||
alltypes.opt_sfixed64 = &opt_sfixed64;
|
||||
alltypes.opt_double = &opt_double;
|
||||
alltypes.opt_string = opt_string;
|
||||
alltypes.opt_bytes = (pb_bytes_array_t*)&opt_bytes;
|
||||
alltypes.opt_submsg = &opt_submsg;
|
||||
alltypes.opt_enum = &opt_enum;
|
||||
alltypes.opt_emptymsg = &opt_emptymsg;
|
||||
alltypes.opt_fbytes = &opt_fbytes;
|
||||
|
||||
alltypes.which_oneof = AllTypes_oneof_msg1_tag;
|
||||
alltypes.oneof.oneof_msg1 = &oneof_msg1;
|
||||
|
||||
alltypes.opt_non_zero_based_enum = &opt_non_zero_based_enum;
|
||||
}
|
||||
|
||||
alltypes.end = &end;
|
||||
|
||||
{
|
||||
uint8_t buffer[4096];
|
||||
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 */
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
# Version of AllTypes test case for protobuf 3 file format.
|
||||
|
||||
Import("env")
|
||||
|
||||
env.NanopbProto(["alltypes", "alltypes.options"])
|
||||
enc = env.Program(["encode_alltypes.c", "alltypes.pb.c", "$COMMON/pb_encode.o", "$COMMON/pb_common.o"])
|
||||
dec = env.Program(["decode_alltypes.c", "alltypes.pb.c", "$COMMON/pb_decode.o", "$COMMON/pb_common.o"])
|
||||
|
||||
# Test the round-trip from nanopb encoder to nanopb decoder
|
||||
env.RunTest(enc)
|
||||
env.RunTest([dec, "encode_alltypes.output"])
|
||||
|
||||
# Re-encode the data using protoc, and check that the results from nanopb
|
||||
# match byte-per-byte to the protoc output.
|
||||
env.Decode("encode_alltypes.output.decoded",
|
||||
["encode_alltypes.output", "alltypes.proto"],
|
||||
MESSAGE='AllTypes')
|
||||
env.Encode("encode_alltypes.output.recoded",
|
||||
["encode_alltypes.output.decoded", "alltypes.proto"],
|
||||
MESSAGE='AllTypes')
|
||||
env.Compare(["encode_alltypes.output", "encode_alltypes.output.recoded"])
|
||||
|
||||
# Do the same checks with the optional fields present.
|
||||
env.RunTest("optionals.output", enc, ARGS = ['1'])
|
||||
env.RunTest("optionals.decout", [dec, "optionals.output"], ARGS = ['1'])
|
||||
env.Decode("optionals.output.decoded",
|
||||
["optionals.output", "alltypes.proto"],
|
||||
MESSAGE='AllTypes')
|
||||
env.Encode("optionals.output.recoded",
|
||||
["optionals.output.decoded", "alltypes.proto"],
|
||||
MESSAGE='AllTypes')
|
||||
env.Compare(["optionals.output", "optionals.output.recoded"])
|
||||
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
* max_size:16
|
||||
* max_count:5
|
||||
*.*fbytes fixed_length:true max_size:4
|
||||
*.req_limits proto3_singular_msgs:true
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
syntax = "proto3";
|
||||
// package name placeholder
|
||||
|
||||
message SubMessage {
|
||||
string substuff1 = 1;
|
||||
int32 substuff2 = 2;
|
||||
fixed32 substuff3 = 3;
|
||||
}
|
||||
|
||||
message EmptyMessage {
|
||||
|
||||
}
|
||||
|
||||
enum HugeEnum {
|
||||
HE_Zero = 0;
|
||||
Negative = -2147483647; /* protoc doesn't accept -2147483648 here */
|
||||
Positive = 2147483647;
|
||||
}
|
||||
|
||||
message Limits {
|
||||
int32 int32_min = 1;
|
||||
int32 int32_max = 2;
|
||||
uint32 uint32_min = 3;
|
||||
uint32 uint32_max = 4;
|
||||
int64 int64_min = 5;
|
||||
int64 int64_max = 6;
|
||||
uint64 uint64_min = 7;
|
||||
uint64 uint64_max = 8;
|
||||
HugeEnum enum_min = 9;
|
||||
HugeEnum enum_max = 10;
|
||||
}
|
||||
|
||||
enum MyEnum {
|
||||
Zero = 0;
|
||||
First = 1;
|
||||
Second = 2;
|
||||
Truth = 42;
|
||||
}
|
||||
|
||||
message AllTypes {
|
||||
int32 sng_int32 = 1;
|
||||
int64 sng_int64 = 2;
|
||||
uint32 sng_uint32 = 3;
|
||||
uint64 sng_uint64 = 4;
|
||||
sint32 sng_sint32 = 5;
|
||||
sint64 sng_sint64 = 6;
|
||||
bool sng_bool = 7;
|
||||
|
||||
fixed32 sng_fixed32 = 8;
|
||||
sfixed32 sng_sfixed32= 9;
|
||||
float sng_float = 10;
|
||||
|
||||
fixed64 sng_fixed64 = 11;
|
||||
sfixed64 sng_sfixed64= 12;
|
||||
double sng_double = 13;
|
||||
|
||||
string sng_string = 14;
|
||||
bytes sng_bytes = 15;
|
||||
SubMessage sng_submsg = 16;
|
||||
MyEnum sng_enum = 17;
|
||||
EmptyMessage sng_emptymsg = 18;
|
||||
bytes sng_fbytes = 19;
|
||||
|
||||
repeated int32 rep_int32 = 21 [packed = true];
|
||||
repeated int64 rep_int64 = 22 [packed = true];
|
||||
repeated uint32 rep_uint32 = 23 [packed = true];
|
||||
repeated uint64 rep_uint64 = 24 [packed = true];
|
||||
repeated sint32 rep_sint32 = 25 [packed = true];
|
||||
repeated sint64 rep_sint64 = 26 [packed = true];
|
||||
repeated bool rep_bool = 27 [packed = true];
|
||||
|
||||
repeated fixed32 rep_fixed32 = 28 [packed = true];
|
||||
repeated sfixed32 rep_sfixed32= 29 [packed = true];
|
||||
repeated float rep_float = 30 [packed = true];
|
||||
|
||||
repeated fixed64 rep_fixed64 = 31 [packed = true];
|
||||
repeated sfixed64 rep_sfixed64= 32 [packed = true];
|
||||
repeated double rep_double = 33 [packed = true];
|
||||
|
||||
repeated string rep_string = 34;
|
||||
repeated bytes rep_bytes = 35;
|
||||
repeated SubMessage rep_submsg = 36;
|
||||
repeated MyEnum rep_enum = 37 [packed = true];
|
||||
repeated EmptyMessage rep_emptymsg = 38;
|
||||
repeated bytes rep_fbytes = 39;
|
||||
|
||||
oneof oneof
|
||||
{
|
||||
SubMessage oneof_msg1 = 60;
|
||||
EmptyMessage oneof_msg2 = 61;
|
||||
SubMessage static_msg = 63;
|
||||
}
|
||||
|
||||
// Check that extreme integer values are handled correctly
|
||||
Limits req_limits = 98;
|
||||
|
||||
// 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.
|
||||
int32 end = 999;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,166 @@
|
||||
/* Tests the decoding of all types.
|
||||
* This is the counterpart of test_encode3.
|
||||
* Run e.g. ./test_encode3 | ./test_decode3
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <pb_decode.h>
|
||||
#include "alltypes.pb.h"
|
||||
#include "test_helpers.h"
|
||||
#include "unittests.h"
|
||||
|
||||
/* This function is called once from main(), it handles
|
||||
the decoding and checks the fields. */
|
||||
bool check_alltypes(pb_istream_t *stream, int mode)
|
||||
{
|
||||
int status = 0;
|
||||
AllTypes alltypes = AllTypes_init_zero;
|
||||
|
||||
/* Fill with garbage to better detect initialization errors */
|
||||
memset(&alltypes, 0xAA, sizeof(alltypes));
|
||||
|
||||
if (!pb_decode(stream, AllTypes_fields, &alltypes))
|
||||
return false;
|
||||
|
||||
TEST(alltypes.rep_int32_count == 5 && alltypes.rep_int32[4] == -2001 && alltypes.rep_int32[0] == 0);
|
||||
TEST(alltypes.rep_int64_count == 5 && alltypes.rep_int64[4] == -2002 && alltypes.rep_int64[0] == 0);
|
||||
TEST(alltypes.rep_uint32_count == 5 && alltypes.rep_uint32[4] == 2003 && alltypes.rep_uint32[0] == 0);
|
||||
TEST(alltypes.rep_uint64_count == 5 && alltypes.rep_uint64[4] == 2004 && alltypes.rep_uint64[0] == 0);
|
||||
TEST(alltypes.rep_sint32_count == 5 && alltypes.rep_sint32[4] == -2005 && alltypes.rep_sint32[0] == 0);
|
||||
TEST(alltypes.rep_sint64_count == 5 && alltypes.rep_sint64[4] == -2006 && alltypes.rep_sint64[0] == 0);
|
||||
TEST(alltypes.rep_bool_count == 5 && alltypes.rep_bool[4] == true && alltypes.rep_bool[0] == false);
|
||||
|
||||
TEST(alltypes.rep_fixed32_count == 5 && alltypes.rep_fixed32[4] == 2008 && alltypes.rep_fixed32[0] == 0);
|
||||
TEST(alltypes.rep_sfixed32_count == 5 && alltypes.rep_sfixed32[4] == -2009 && alltypes.rep_sfixed32[0] == 0);
|
||||
TEST(alltypes.rep_float_count == 5 && alltypes.rep_float[4] == 2010.0f && alltypes.rep_float[0] == 0.0f);
|
||||
|
||||
TEST(alltypes.rep_fixed64_count == 5 && alltypes.rep_fixed64[4] == 2011 && alltypes.rep_fixed64[0] == 0);
|
||||
TEST(alltypes.rep_sfixed64_count == 5 && alltypes.rep_sfixed64[4] == -2012 && alltypes.rep_sfixed64[0] == 0);
|
||||
TEST(alltypes.rep_double_count == 5 && alltypes.rep_double[4] == 2013.0 && alltypes.rep_double[0] == 0.0);
|
||||
|
||||
TEST(alltypes.rep_string_count == 5 && strcmp(alltypes.rep_string[4], "2014") == 0 && alltypes.rep_string[0][0] == '\0');
|
||||
TEST(alltypes.rep_bytes_count == 5 && alltypes.rep_bytes[4].size == 4 && alltypes.rep_bytes[0].size == 0);
|
||||
TEST(memcmp(alltypes.rep_bytes[4].bytes, "2015", 4) == 0);
|
||||
|
||||
TEST(alltypes.rep_submsg_count == 5);
|
||||
TEST(strcmp(alltypes.rep_submsg[4].substuff1, "2016") == 0 && alltypes.rep_submsg[0].substuff1[0] == '\0');
|
||||
TEST(alltypes.rep_submsg[4].substuff2 == 2016 && alltypes.rep_submsg[0].substuff2 == 0);
|
||||
TEST(alltypes.rep_submsg[4].substuff3 == 2016 && alltypes.rep_submsg[0].substuff3 == 0);
|
||||
|
||||
TEST(alltypes.rep_enum_count == 5 && alltypes.rep_enum[4] == MyEnum_Truth && alltypes.rep_enum[0] == MyEnum_Zero);
|
||||
TEST(alltypes.rep_emptymsg_count == 5);
|
||||
|
||||
TEST(alltypes.rep_fbytes_count == 5);
|
||||
TEST(alltypes.rep_fbytes[0][0] == 0 && alltypes.rep_fbytes[0][3] == 0);
|
||||
TEST(memcmp(alltypes.rep_fbytes[4], "2019", 4) == 0);
|
||||
|
||||
if (mode == 0)
|
||||
{
|
||||
/* Expect default values */
|
||||
TEST(alltypes.sng_int32 == 0);
|
||||
TEST(alltypes.sng_int64 == 0);
|
||||
TEST(alltypes.sng_uint32 == 0);
|
||||
TEST(alltypes.sng_uint64 == 0);
|
||||
TEST(alltypes.sng_sint32 == 0);
|
||||
TEST(alltypes.sng_sint64 == 0);
|
||||
TEST(alltypes.sng_bool == false);
|
||||
|
||||
TEST(alltypes.sng_fixed32 == 0);
|
||||
TEST(alltypes.sng_sfixed32 == 0);
|
||||
TEST(alltypes.sng_float == 0.0f);
|
||||
|
||||
TEST(alltypes.sng_fixed64 == 0);
|
||||
TEST(alltypes.sng_sfixed64 == 0);
|
||||
TEST(alltypes.sng_double == 0.0);
|
||||
|
||||
TEST(strcmp(alltypes.sng_string, "") == 0);
|
||||
TEST(alltypes.sng_bytes.size == 0);
|
||||
TEST(alltypes.has_sng_submsg == false);
|
||||
TEST(strcmp(alltypes.sng_submsg.substuff1, "") == 0);
|
||||
TEST(alltypes.sng_submsg.substuff2 == 0);
|
||||
TEST(alltypes.sng_submsg.substuff3 == 0);
|
||||
TEST(alltypes.sng_enum == MyEnum_Zero);
|
||||
TEST(alltypes.sng_fbytes[0] == 0 &&
|
||||
alltypes.sng_fbytes[1] == 0 &&
|
||||
alltypes.sng_fbytes[2] == 0 &&
|
||||
alltypes.sng_fbytes[3] == 0);
|
||||
|
||||
TEST(alltypes.which_oneof == 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Expect filled-in values */
|
||||
TEST(alltypes.sng_int32 == 3041);
|
||||
TEST(alltypes.sng_int64 == 3042);
|
||||
TEST(alltypes.sng_uint32 == 3043);
|
||||
TEST(alltypes.sng_uint64 == 3044);
|
||||
TEST(alltypes.sng_sint32 == 3045);
|
||||
TEST(alltypes.sng_sint64 == 3046);
|
||||
TEST(alltypes.sng_bool == true);
|
||||
|
||||
TEST(alltypes.sng_fixed32 == 3048);
|
||||
TEST(alltypes.sng_sfixed32 == 3049);
|
||||
TEST(alltypes.sng_float == 3050.0f);
|
||||
|
||||
TEST(alltypes.sng_fixed64 == 3051);
|
||||
TEST(alltypes.sng_sfixed64 == 3052);
|
||||
TEST(alltypes.sng_double == 3053.0);
|
||||
|
||||
TEST(strcmp(alltypes.sng_string, "3054") == 0);
|
||||
TEST(alltypes.sng_bytes.size == 4);
|
||||
TEST(memcmp(alltypes.sng_bytes.bytes, "3055", 4) == 0);
|
||||
TEST(alltypes.has_sng_submsg == true);
|
||||
TEST(strcmp(alltypes.sng_submsg.substuff1, "3056") == 0);
|
||||
TEST(alltypes.sng_submsg.substuff2 == 3056);
|
||||
TEST(alltypes.sng_submsg.substuff3 == 0);
|
||||
TEST(alltypes.sng_enum == MyEnum_Truth);
|
||||
TEST(memcmp(alltypes.sng_fbytes, "3059", 4) == 0);
|
||||
|
||||
TEST(alltypes.which_oneof == AllTypes_oneof_msg1_tag);
|
||||
TEST(strcmp(alltypes.oneof.oneof_msg1.substuff1, "4059") == 0);
|
||||
TEST(alltypes.oneof.oneof_msg1.substuff2 == 4059);
|
||||
}
|
||||
|
||||
TEST(alltypes.req_limits.int32_min == INT32_MIN);
|
||||
TEST(alltypes.req_limits.int32_max == INT32_MAX);
|
||||
TEST(alltypes.req_limits.uint32_min == 0);
|
||||
TEST(alltypes.req_limits.uint32_max == UINT32_MAX);
|
||||
TEST(alltypes.req_limits.int64_min == INT64_MIN);
|
||||
TEST(alltypes.req_limits.int64_max == INT64_MAX);
|
||||
TEST(alltypes.req_limits.uint64_min == 0);
|
||||
TEST(alltypes.req_limits.uint64_max == UINT64_MAX);
|
||||
TEST(alltypes.req_limits.enum_min == HugeEnum_Negative);
|
||||
TEST(alltypes.req_limits.enum_max == HugeEnum_Positive);
|
||||
|
||||
TEST(alltypes.end == 1099);
|
||||
|
||||
return status == 0;
|
||||
}
|
||||
|
||||
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 */
|
||||
SET_BINARY_MODE(stdin);
|
||||
count = fread(buffer, 1, sizeof(buffer), stdin);
|
||||
|
||||
/* Construct a pb_istream_t for reading from the buffer */
|
||||
stream = pb_istream_from_buffer(buffer, count);
|
||||
|
||||
/* Decode and print out the stuff */
|
||||
if (!check_alltypes(&stream, mode))
|
||||
{
|
||||
printf("Parsing failed: %s\n", PB_GET_ERROR(&stream));
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
/* Attempts to test all the datatypes supported by ProtoBuf3.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <pb_encode.h>
|
||||
#include "alltypes.pb.h"
|
||||
#include "test_helpers.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int mode = (argc > 1) ? atoi(argv[1]) : 0;
|
||||
|
||||
/* Initialize the structure with constants */
|
||||
AllTypes alltypes = AllTypes_init_zero;
|
||||
|
||||
alltypes.rep_int32_count = 5; alltypes.rep_int32[4] = -2001;
|
||||
alltypes.rep_int64_count = 5; alltypes.rep_int64[4] = -2002;
|
||||
alltypes.rep_uint32_count = 5; alltypes.rep_uint32[4] = 2003;
|
||||
alltypes.rep_uint64_count = 5; alltypes.rep_uint64[4] = 2004;
|
||||
alltypes.rep_sint32_count = 5; alltypes.rep_sint32[4] = -2005;
|
||||
alltypes.rep_sint64_count = 5; alltypes.rep_sint64[4] = -2006;
|
||||
alltypes.rep_bool_count = 5; alltypes.rep_bool[4] = true;
|
||||
|
||||
alltypes.rep_fixed32_count = 5; alltypes.rep_fixed32[4] = 2008;
|
||||
alltypes.rep_sfixed32_count = 5; alltypes.rep_sfixed32[4] = -2009;
|
||||
alltypes.rep_float_count = 5; alltypes.rep_float[4] = 2010.0f;
|
||||
|
||||
alltypes.rep_fixed64_count = 5; alltypes.rep_fixed64[4] = 2011;
|
||||
alltypes.rep_sfixed64_count = 5; alltypes.rep_sfixed64[4] = -2012;
|
||||
alltypes.rep_double_count = 5; alltypes.rep_double[4] = 2013.0;
|
||||
|
||||
alltypes.rep_string_count = 5; strcpy(alltypes.rep_string[4], "2014");
|
||||
alltypes.rep_bytes_count = 5; alltypes.rep_bytes[4].size = 4;
|
||||
memcpy(alltypes.rep_bytes[4].bytes, "2015", 4);
|
||||
|
||||
alltypes.rep_submsg_count = 5;
|
||||
strcpy(alltypes.rep_submsg[4].substuff1, "2016");
|
||||
alltypes.rep_submsg[4].substuff2 = 2016;
|
||||
alltypes.rep_submsg[4].substuff3 = 2016;
|
||||
|
||||
alltypes.rep_enum_count = 5; alltypes.rep_enum[4] = MyEnum_Truth;
|
||||
alltypes.rep_emptymsg_count = 5;
|
||||
|
||||
alltypes.rep_fbytes_count = 5;
|
||||
memcpy(alltypes.rep_fbytes[4], "2019", 4);
|
||||
|
||||
alltypes.req_limits.int32_min = INT32_MIN;
|
||||
alltypes.req_limits.int32_max = INT32_MAX;
|
||||
alltypes.req_limits.uint32_min = 0;
|
||||
alltypes.req_limits.uint32_max = UINT32_MAX;
|
||||
alltypes.req_limits.int64_min = INT64_MIN;
|
||||
alltypes.req_limits.int64_max = INT64_MAX;
|
||||
alltypes.req_limits.uint64_min = 0;
|
||||
alltypes.req_limits.uint64_max = UINT64_MAX;
|
||||
alltypes.req_limits.enum_min = HugeEnum_Negative;
|
||||
alltypes.req_limits.enum_max = HugeEnum_Positive;
|
||||
|
||||
if (mode != 0)
|
||||
{
|
||||
/* Fill in values for singular fields */
|
||||
alltypes.sng_int32 = 3041;
|
||||
alltypes.sng_int64 = 3042;
|
||||
alltypes.sng_uint32 = 3043;
|
||||
alltypes.sng_uint64 = 3044;
|
||||
alltypes.sng_sint32 = 3045;
|
||||
alltypes.sng_sint64 = 3046;
|
||||
alltypes.sng_bool = true;
|
||||
|
||||
alltypes.sng_fixed32 = 3048;
|
||||
alltypes.sng_sfixed32 = 3049;
|
||||
alltypes.sng_float = 3050.0f;
|
||||
|
||||
alltypes.sng_fixed64 = 3051;
|
||||
alltypes.sng_sfixed64 = 3052;
|
||||
alltypes.sng_double = 3053.0;
|
||||
|
||||
strcpy(alltypes.sng_string, "3054");
|
||||
alltypes.sng_bytes.size = 4;
|
||||
memcpy(alltypes.sng_bytes.bytes, "3055", 4);
|
||||
alltypes.has_sng_submsg = true;
|
||||
strcpy(alltypes.sng_submsg.substuff1, "3056");
|
||||
alltypes.sng_submsg.substuff2 = 3056;
|
||||
alltypes.sng_enum = MyEnum_Truth;
|
||||
memcpy(alltypes.sng_fbytes, "3059", 4);
|
||||
|
||||
alltypes.which_oneof = AllTypes_oneof_msg1_tag;
|
||||
strcpy(alltypes.oneof.oneof_msg1.substuff1, "4059");
|
||||
alltypes.oneof.oneof_msg1.substuff2 = 4059;
|
||||
}
|
||||
|
||||
alltypes.end = 1099;
|
||||
|
||||
{
|
||||
uint8_t buffer[AllTypes_size];
|
||||
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 */
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
# Test the AllTypes encoding & decoding using callbacks for all fields.
|
||||
|
||||
Import("env", "malloc_env")
|
||||
|
||||
c = Copy("$TARGET", "$SOURCE")
|
||||
env.Command("alltypes.proto", "#alltypes_proto3/alltypes.proto", c)
|
||||
|
||||
env.NanopbProto(["alltypes", "alltypes.options"])
|
||||
enc = env.Program(["encode_alltypes_callback.c", "alltypes.pb.c", "$COMMON/pb_encode.o", "$COMMON/pb_common.o"])
|
||||
dec = env.Program(["decode_alltypes_callback.c", "alltypes.pb.c", "$COMMON/pb_decode.o", "$COMMON/pb_common.o"])
|
||||
|
||||
refdec = "$BUILD/alltypes_proto3/decode_alltypes$PROGSUFFIX"
|
||||
|
||||
# Encode and compare results
|
||||
env.RunTest(enc)
|
||||
env.RunTest("decode_alltypes.output", [refdec, "encode_alltypes_callback.output"])
|
||||
env.RunTest("decode_alltypes_callback.output", [dec, "encode_alltypes_callback.output"])
|
||||
|
||||
# Do the same thing with the optional fields present
|
||||
env.RunTest("optionals.output", enc, ARGS = ['1'])
|
||||
env.RunTest("optionals.refdecout", [refdec, "optionals.output"], ARGS = ['1'])
|
||||
env.RunTest("optionals.decout", [dec, "optionals.output"], ARGS = ['1'])
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
# Generate all fields as callbacks.
|
||||
AllTypes.* type:FT_CALLBACK
|
||||
SubMessage.substuff1 max_size:16
|
||||
AllTypes.oneof no_unions:true
|
||||
|
||||
# With FT_CALLBACK, these options should get ignored
|
||||
*.*fbytes fixed_length:true max_size:4
|
||||
|
||||
@@ -0,0 +1,422 @@
|
||||
/* Attempts to test all the datatypes supported by ProtoBuf when used as callback fields.
|
||||
* Note that normally there would be no reason to use callback fields for this,
|
||||
* because each encoder defined here only gives a single field.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <pb_decode.h>
|
||||
#include "alltypes.pb.h"
|
||||
#include "test_helpers.h"
|
||||
|
||||
#define TEST(x) if (!(x)) { \
|
||||
printf("Test %s failed (in field %d).\n", #x, field->tag); \
|
||||
return false; \
|
||||
}
|
||||
|
||||
static bool read_varint(pb_istream_t *stream, const pb_field_t *field, void **arg)
|
||||
{
|
||||
uint64_t value;
|
||||
if (!pb_decode_varint(stream, &value))
|
||||
return false;
|
||||
|
||||
TEST((int64_t)value == (intptr_t)*arg);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool read_svarint(pb_istream_t *stream, const pb_field_t *field, void **arg)
|
||||
{
|
||||
int64_t value;
|
||||
if (!pb_decode_svarint(stream, &value))
|
||||
return false;
|
||||
|
||||
TEST(value == (intptr_t)*arg);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool read_fixed32(pb_istream_t *stream, const pb_field_t *field, void **arg)
|
||||
{
|
||||
uint32_t value;
|
||||
if (!pb_decode_fixed32(stream, &value))
|
||||
return false;
|
||||
|
||||
TEST(value == *(uint32_t*)*arg);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool read_fixed64(pb_istream_t *stream, const pb_field_t *field, void **arg)
|
||||
{
|
||||
uint64_t value;
|
||||
if (!pb_decode_fixed64(stream, &value))
|
||||
return false;
|
||||
|
||||
TEST(value == *(uint64_t*)*arg);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool read_double(pb_istream_t *stream, const pb_field_t *field, void **arg)
|
||||
{
|
||||
#ifdef PB_CONVERT_DOUBLE_FLOAT
|
||||
if (sizeof(double) == sizeof(float))
|
||||
{
|
||||
float value;
|
||||
if (!pb_decode_double_as_float(stream, &value))
|
||||
return false;
|
||||
|
||||
TEST(memcmp(&value, *arg, sizeof(float)) == 0);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
uint64_t value;
|
||||
if (!pb_decode_fixed64(stream, &value))
|
||||
return false;
|
||||
|
||||
TEST(value == *(uint64_t*)*arg);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool read_string(pb_istream_t *stream, const pb_field_t *field, void **arg)
|
||||
{
|
||||
uint8_t buf[16] = {0};
|
||||
size_t len = stream->bytes_left;
|
||||
|
||||
if (len > sizeof(buf) - 1 || !pb_read(stream, buf, len))
|
||||
return false;
|
||||
|
||||
TEST(strcmp((char*)buf, *arg) == 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool read_submsg(pb_istream_t *stream, const pb_field_t *field, void **arg)
|
||||
{
|
||||
SubMessage submsg = {""};
|
||||
SubMessage *ref = *arg;
|
||||
|
||||
if (!pb_decode(stream, SubMessage_fields, &submsg))
|
||||
return false;
|
||||
|
||||
TEST(strcmp(submsg.substuff1, ref->substuff1) == 0);
|
||||
TEST(submsg.substuff2 == ref->substuff2);
|
||||
TEST(submsg.substuff3 == ref->substuff3);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool read_emptymsg(pb_istream_t *stream, const pb_field_t *field, void **arg)
|
||||
{
|
||||
EmptyMessage emptymsg = {0};
|
||||
return pb_decode(stream, EmptyMessage_fields, &emptymsg);
|
||||
}
|
||||
|
||||
static bool read_repeated_varint(pb_istream_t *stream, const pb_field_t *field, void **arg)
|
||||
{
|
||||
int32_t** expected = (int32_t**)arg;
|
||||
uint64_t value;
|
||||
if (!pb_decode_varint(stream, &value))
|
||||
return false;
|
||||
|
||||
TEST(*(*expected)++ == value);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool read_repeated_svarint(pb_istream_t *stream, const pb_field_t *field, void **arg)
|
||||
{
|
||||
int32_t** expected = (int32_t**)arg;
|
||||
int64_t value;
|
||||
if (!pb_decode_svarint(stream, &value))
|
||||
return false;
|
||||
|
||||
TEST(*(*expected)++ == value);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool read_repeated_fixed32(pb_istream_t *stream, const pb_field_t *field, void **arg)
|
||||
{
|
||||
uint32_t** expected = (uint32_t**)arg;
|
||||
uint32_t value;
|
||||
if (!pb_decode_fixed32(stream, &value))
|
||||
return false;
|
||||
|
||||
TEST(*(*expected)++ == value);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool read_repeated_fixed64(pb_istream_t *stream, const pb_field_t *field, void **arg)
|
||||
{
|
||||
uint64_t** expected = (uint64_t**)arg;
|
||||
uint64_t value;
|
||||
if (!pb_decode_fixed64(stream, &value))
|
||||
return false;
|
||||
|
||||
TEST(*(*expected)++ == value);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool read_repeated_double(pb_istream_t *stream, const pb_field_t *field, void **arg)
|
||||
{
|
||||
#ifdef PB_CONVERT_DOUBLE_FLOAT
|
||||
if (sizeof(double) == sizeof(float))
|
||||
{
|
||||
float** expectedf = (float**)arg;
|
||||
float value;
|
||||
if (!pb_decode_double_as_float(stream, &value))
|
||||
return false;
|
||||
|
||||
TEST(memcmp(&value, (*expectedf)++, sizeof(float)) == 0);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
uint64_t** expected = (uint64_t**)arg;
|
||||
uint64_t value;
|
||||
if (!pb_decode_fixed64(stream, &value))
|
||||
return false;
|
||||
|
||||
TEST(*(*expected)++ == value);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool read_repeated_string(pb_istream_t *stream, const pb_field_t *field, void **arg)
|
||||
{
|
||||
uint8_t*** expected = (uint8_t***)arg;
|
||||
uint8_t buf[16] = {0};
|
||||
size_t len = stream->bytes_left;
|
||||
|
||||
if (len > sizeof(buf) - 1 || !pb_read(stream, buf, len))
|
||||
return false;
|
||||
|
||||
TEST(strcmp((char*)*(*expected)++, (char*)buf) == 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool read_repeated_submsg(pb_istream_t *stream, const pb_field_t *field, void **arg)
|
||||
{
|
||||
SubMessage** expected = (SubMessage**)arg;
|
||||
SubMessage submsg = {""};
|
||||
if (!pb_decode(stream, SubMessage_fields, &submsg))
|
||||
return false;
|
||||
|
||||
TEST(strcmp(submsg.substuff1, (*expected)->substuff1) == 0);
|
||||
TEST(submsg.substuff2 == (*expected)->substuff2);
|
||||
TEST(submsg.substuff3 == (*expected)->substuff3);
|
||||
(*expected)++;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool read_limits(pb_istream_t *stream, const pb_field_t *field, void **arg)
|
||||
{
|
||||
Limits decoded = {0};
|
||||
if (!pb_decode(stream, Limits_fields, &decoded))
|
||||
return false;
|
||||
|
||||
TEST(decoded.int32_min == INT32_MIN);
|
||||
TEST(decoded.int32_max == INT32_MAX);
|
||||
TEST(decoded.uint32_min == 0);
|
||||
TEST(decoded.uint32_max == UINT32_MAX);
|
||||
TEST(decoded.int64_min == INT64_MIN);
|
||||
TEST(decoded.int64_max == INT64_MAX);
|
||||
TEST(decoded.uint64_min == 0);
|
||||
TEST(decoded.uint64_max == UINT64_MAX);
|
||||
TEST(decoded.enum_min == HugeEnum_Negative);
|
||||
TEST(decoded.enum_max == HugeEnum_Positive);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* This function is called once from main(), it handles
|
||||
the decoding and checks the fields. */
|
||||
bool check_alltypes(pb_istream_t *stream, int mode)
|
||||
{
|
||||
/* Values for use from callbacks through pointers. */
|
||||
bool status;
|
||||
|
||||
int32_t rep_int32[5] = {0, 0, 0, 0, -2001};
|
||||
int32_t rep_int64[5] = {0, 0, 0, 0, -2002};
|
||||
int32_t rep_uint32[5] = {0, 0, 0, 0, 2003};
|
||||
int32_t rep_uint64[5] = {0, 0, 0, 0, 2004};
|
||||
int32_t rep_sint32[5] = {0, 0, 0, 0, -2005};
|
||||
int32_t rep_sint64[5] = {0, 0, 0, 0, -2006};
|
||||
int32_t rep_bool[5] = {false, false, false, false, true};
|
||||
uint32_t rep_fixed32[5] = {0, 0, 0, 0, 2008};
|
||||
int32_t rep_sfixed32[5] = {0, 0, 0, 0, -2009};
|
||||
float rep_float[5] = {0, 0, 0, 0, 2010.0f};
|
||||
uint64_t rep_fixed64[5] = {0, 0, 0, 0, 2011};
|
||||
int64_t rep_sfixed64[5] = {0, 0, 0, 0, -2012};
|
||||
double rep_double[5] = {0, 0, 0, 0, 2013.0};
|
||||
char* rep_string[5] = {"", "", "", "", "2014"};
|
||||
char* rep_bytes[5] = {"", "", "", "", "2015"};
|
||||
SubMessage rep_submsg[5] = {{"", 0, 0},
|
||||
{"", 0, 0},
|
||||
{"", 0, 0},
|
||||
{"", 0, 0},
|
||||
{"2016", 2016, 2016}};
|
||||
int32_t rep_enum[5] = {0, 0, 0, 0, MyEnum_Truth};
|
||||
|
||||
uint32_t sng_fixed32 = 3048;
|
||||
int32_t sng_sfixed32 = 3049;
|
||||
float sng_float = 3050.0f;
|
||||
uint64_t sng_fixed64 = 3051;
|
||||
int64_t sng_sfixed64 = 3052;
|
||||
double sng_double = 3053.0f;
|
||||
SubMessage sng_submsg = {"3056", 3056};
|
||||
|
||||
SubMessage oneof_msg1 = {"4059", 4059};
|
||||
|
||||
AllTypes alltypes = AllTypes_init_zero;
|
||||
|
||||
/* Bind callbacks for repeated fields */
|
||||
alltypes.rep_int32.funcs.decode = &read_repeated_varint;
|
||||
alltypes.rep_int32.arg = rep_int32;
|
||||
|
||||
alltypes.rep_int64.funcs.decode = &read_repeated_varint;
|
||||
alltypes.rep_int64.arg = rep_int64;
|
||||
|
||||
alltypes.rep_uint32.funcs.decode = &read_repeated_varint;
|
||||
alltypes.rep_uint32.arg = rep_uint32;
|
||||
|
||||
alltypes.rep_uint64.funcs.decode = &read_repeated_varint;
|
||||
alltypes.rep_uint64.arg = rep_uint64;
|
||||
|
||||
alltypes.rep_sint32.funcs.decode = &read_repeated_svarint;
|
||||
alltypes.rep_sint32.arg = rep_sint32;
|
||||
|
||||
alltypes.rep_sint64.funcs.decode = &read_repeated_svarint;
|
||||
alltypes.rep_sint64.arg = rep_sint64;
|
||||
|
||||
alltypes.rep_bool.funcs.decode = &read_repeated_varint;
|
||||
alltypes.rep_bool.arg = rep_bool;
|
||||
|
||||
alltypes.rep_fixed32.funcs.decode = &read_repeated_fixed32;
|
||||
alltypes.rep_fixed32.arg = rep_fixed32;
|
||||
|
||||
alltypes.rep_sfixed32.funcs.decode = &read_repeated_fixed32;
|
||||
alltypes.rep_sfixed32.arg = rep_sfixed32;
|
||||
|
||||
alltypes.rep_float.funcs.decode = &read_repeated_fixed32;
|
||||
alltypes.rep_float.arg = rep_float;
|
||||
|
||||
alltypes.rep_fixed64.funcs.decode = &read_repeated_fixed64;
|
||||
alltypes.rep_fixed64.arg = rep_fixed64;
|
||||
|
||||
alltypes.rep_sfixed64.funcs.decode = &read_repeated_fixed64;
|
||||
alltypes.rep_sfixed64.arg = rep_sfixed64;
|
||||
|
||||
alltypes.rep_double.funcs.decode = &read_repeated_double;
|
||||
alltypes.rep_double.arg = rep_double;
|
||||
|
||||
alltypes.rep_string.funcs.decode = &read_repeated_string;
|
||||
alltypes.rep_string.arg = rep_string;
|
||||
|
||||
alltypes.rep_bytes.funcs.decode = &read_repeated_string;
|
||||
alltypes.rep_bytes.arg = rep_bytes;
|
||||
|
||||
alltypes.rep_submsg.funcs.decode = &read_repeated_submsg;
|
||||
alltypes.rep_submsg.arg = rep_submsg;
|
||||
|
||||
alltypes.rep_enum.funcs.decode = &read_repeated_varint;
|
||||
alltypes.rep_enum.arg = rep_enum;
|
||||
|
||||
alltypes.rep_emptymsg.funcs.decode = &read_emptymsg;
|
||||
|
||||
alltypes.req_limits.funcs.decode = &read_limits;
|
||||
|
||||
alltypes.end.funcs.decode = &read_varint;
|
||||
alltypes.end.arg = (void*)1099;
|
||||
|
||||
/* Bind callbacks for optional fields */
|
||||
if (mode == 1)
|
||||
{
|
||||
alltypes.sng_int32.funcs.decode = &read_varint;
|
||||
alltypes.sng_int32.arg = (void*)3041;
|
||||
|
||||
alltypes.sng_int64.funcs.decode = &read_varint;
|
||||
alltypes.sng_int64.arg = (void*)3042;
|
||||
|
||||
alltypes.sng_uint32.funcs.decode = &read_varint;
|
||||
alltypes.sng_uint32.arg = (void*)3043;
|
||||
|
||||
alltypes.sng_uint64.funcs.decode = &read_varint;
|
||||
alltypes.sng_uint64.arg = (void*)3044;
|
||||
|
||||
alltypes.sng_sint32.funcs.decode = &read_svarint;
|
||||
alltypes.sng_sint32.arg = (void*)3045;
|
||||
|
||||
alltypes.sng_sint64.funcs.decode = &read_svarint;
|
||||
alltypes.sng_sint64.arg = (void*)3046;
|
||||
|
||||
alltypes.sng_bool.funcs.decode = &read_varint;
|
||||
alltypes.sng_bool.arg = (void*)true;
|
||||
|
||||
alltypes.sng_fixed32.funcs.decode = &read_fixed32;
|
||||
alltypes.sng_fixed32.arg = &sng_fixed32;
|
||||
|
||||
alltypes.sng_sfixed32.funcs.decode = &read_fixed32;
|
||||
alltypes.sng_sfixed32.arg = &sng_sfixed32;
|
||||
|
||||
alltypes.sng_float.funcs.decode = &read_fixed32;
|
||||
alltypes.sng_float.arg = &sng_float;
|
||||
|
||||
alltypes.sng_fixed64.funcs.decode = &read_fixed64;
|
||||
alltypes.sng_fixed64.arg = &sng_fixed64;
|
||||
|
||||
alltypes.sng_sfixed64.funcs.decode = &read_fixed64;
|
||||
alltypes.sng_sfixed64.arg = &sng_sfixed64;
|
||||
|
||||
alltypes.sng_double.funcs.decode = &read_double;
|
||||
alltypes.sng_double.arg = &sng_double;
|
||||
|
||||
alltypes.sng_string.funcs.decode = &read_string;
|
||||
alltypes.sng_string.arg = "3054";
|
||||
|
||||
alltypes.sng_bytes.funcs.decode = &read_string;
|
||||
alltypes.sng_bytes.arg = "3055";
|
||||
|
||||
alltypes.sng_submsg.funcs.decode = &read_submsg;
|
||||
alltypes.sng_submsg.arg = &sng_submsg;
|
||||
|
||||
alltypes.sng_enum.funcs.decode = &read_varint;
|
||||
alltypes.sng_enum.arg = (void*)MyEnum_Truth;
|
||||
|
||||
alltypes.sng_emptymsg.funcs.decode = &read_emptymsg;
|
||||
|
||||
alltypes.oneof_msg1.funcs.decode = &read_submsg;
|
||||
alltypes.oneof_msg1.arg = &oneof_msg1;
|
||||
}
|
||||
|
||||
status = pb_decode(stream, AllTypes_fields, &alltypes);
|
||||
|
||||
#ifdef PB_ENABLE_MALLOC
|
||||
/* Just to check for any interference between pb_release() and callback fields */
|
||||
pb_release(AllTypes_fields, &alltypes);
|
||||
#endif
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
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 */
|
||||
SET_BINARY_MODE(stdin);
|
||||
count = fread(buffer, 1, sizeof(buffer), stdin);
|
||||
|
||||
/* Construct a pb_istream_t for reading from the buffer */
|
||||
stream = pb_istream_from_buffer(buffer, count);
|
||||
|
||||
/* Decode and print out the stuff */
|
||||
if (!check_alltypes(&stream, mode))
|
||||
{
|
||||
printf("Parsing failed: %s\n", PB_GET_ERROR(&stream));
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,380 @@
|
||||
/* Attempts to test all the datatypes supported by ProtoBuf when used as callback fields.
|
||||
* Note that normally there would be no reason to use callback fields for this,
|
||||
* because each encoder defined here only gives a single field.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <pb_encode.h>
|
||||
#include "alltypes.pb.h"
|
||||
#include "test_helpers.h"
|
||||
|
||||
static bool write_varint(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
|
||||
{
|
||||
return pb_encode_tag_for_field(stream, field) &&
|
||||
pb_encode_varint(stream, (intptr_t)*arg);
|
||||
}
|
||||
|
||||
static bool write_svarint(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
|
||||
{
|
||||
return pb_encode_tag_for_field(stream, field) &&
|
||||
pb_encode_svarint(stream, (intptr_t)*arg);
|
||||
}
|
||||
|
||||
static bool write_fixed32(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
|
||||
{
|
||||
return pb_encode_tag_for_field(stream, field) &&
|
||||
pb_encode_fixed32(stream, *arg);
|
||||
}
|
||||
|
||||
static bool write_fixed64(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
|
||||
{
|
||||
return pb_encode_tag_for_field(stream, field) &&
|
||||
pb_encode_fixed64(stream, *arg);
|
||||
}
|
||||
|
||||
static bool write_double(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
|
||||
{
|
||||
#ifdef PB_CONVERT_DOUBLE_FLOAT
|
||||
if (sizeof(double) == sizeof(float))
|
||||
return pb_encode_tag_for_field(stream, field) &&
|
||||
pb_encode_float_as_double(stream, *(float*)*arg);
|
||||
#endif
|
||||
|
||||
return pb_encode_tag_for_field(stream, field) &&
|
||||
pb_encode_fixed64(stream, *arg);
|
||||
}
|
||||
|
||||
static bool write_string(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
|
||||
{
|
||||
return pb_encode_tag_for_field(stream, field) &&
|
||||
pb_encode_string(stream, *arg, strlen(*arg));
|
||||
}
|
||||
|
||||
static bool write_submsg(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
|
||||
{
|
||||
|
||||
return pb_encode_tag_for_field(stream, field) &&
|
||||
pb_encode_submessage(stream, SubMessage_fields, *arg);
|
||||
}
|
||||
|
||||
static bool write_emptymsg(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
|
||||
{
|
||||
EmptyMessage emptymsg = {0};
|
||||
return pb_encode_tag_for_field(stream, field) &&
|
||||
pb_encode_submessage(stream, EmptyMessage_fields, &emptymsg);
|
||||
}
|
||||
|
||||
static bool write_repeated_varint(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
|
||||
{
|
||||
return pb_encode_tag_for_field(stream, field) &&
|
||||
pb_encode_varint(stream, 0) &&
|
||||
pb_encode_tag_for_field(stream, field) &&
|
||||
pb_encode_varint(stream, 0) &&
|
||||
pb_encode_tag_for_field(stream, field) &&
|
||||
pb_encode_varint(stream, 0) &&
|
||||
pb_encode_tag_for_field(stream, field) &&
|
||||
pb_encode_varint(stream, 0) &&
|
||||
pb_encode_tag_for_field(stream, field) &&
|
||||
pb_encode_varint(stream, (intptr_t)*arg);
|
||||
}
|
||||
|
||||
static bool write_repeated_svarint(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
|
||||
{
|
||||
return pb_encode_tag_for_field(stream, field) &&
|
||||
pb_encode_svarint(stream, 0) &&
|
||||
pb_encode_tag_for_field(stream, field) &&
|
||||
pb_encode_svarint(stream, 0) &&
|
||||
pb_encode_tag_for_field(stream, field) &&
|
||||
pb_encode_svarint(stream, 0) &&
|
||||
pb_encode_tag_for_field(stream, field) &&
|
||||
pb_encode_svarint(stream, 0) &&
|
||||
pb_encode_tag_for_field(stream, field) &&
|
||||
pb_encode_svarint(stream, (intptr_t)*arg);
|
||||
}
|
||||
|
||||
static bool write_repeated_fixed32(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
|
||||
{
|
||||
uint32_t dummy = 0;
|
||||
|
||||
/* Make it a packed field */
|
||||
return pb_encode_tag(stream, PB_WT_STRING, field->tag) &&
|
||||
pb_encode_varint(stream, 5 * 4) && /* Number of bytes */
|
||||
pb_encode_fixed32(stream, &dummy) &&
|
||||
pb_encode_fixed32(stream, &dummy) &&
|
||||
pb_encode_fixed32(stream, &dummy) &&
|
||||
pb_encode_fixed32(stream, &dummy) &&
|
||||
pb_encode_fixed32(stream, *arg);
|
||||
}
|
||||
|
||||
static bool write_repeated_fixed64(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
|
||||
{
|
||||
uint64_t dummy = 0;
|
||||
|
||||
/* Make it a packed field */
|
||||
return pb_encode_tag(stream, PB_WT_STRING, field->tag) &&
|
||||
pb_encode_varint(stream, 5 * 8) && /* Number of bytes */
|
||||
pb_encode_fixed64(stream, &dummy) &&
|
||||
pb_encode_fixed64(stream, &dummy) &&
|
||||
pb_encode_fixed64(stream, &dummy) &&
|
||||
pb_encode_fixed64(stream, &dummy) &&
|
||||
pb_encode_fixed64(stream, *arg);
|
||||
}
|
||||
|
||||
static bool write_repeated_double(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
|
||||
{
|
||||
uint64_t dummy = 0;
|
||||
|
||||
#ifdef PB_CONVERT_DOUBLE_FLOAT
|
||||
if (sizeof(double) == sizeof(float))
|
||||
return pb_encode_tag(stream, PB_WT_STRING, field->tag) &&
|
||||
pb_encode_varint(stream, 5 * 8) && /* Number of bytes */
|
||||
pb_encode_float_as_double(stream, 0.0f) &&
|
||||
pb_encode_float_as_double(stream, 0.0f) &&
|
||||
pb_encode_float_as_double(stream, 0.0f) &&
|
||||
pb_encode_float_as_double(stream, 0.0f) &&
|
||||
pb_encode_float_as_double(stream, *(float*)*arg);
|
||||
#endif
|
||||
|
||||
/* Make it a packed field */
|
||||
return pb_encode_tag(stream, PB_WT_STRING, field->tag) &&
|
||||
pb_encode_varint(stream, 5 * 8) && /* Number of bytes */
|
||||
pb_encode_fixed64(stream, &dummy) &&
|
||||
pb_encode_fixed64(stream, &dummy) &&
|
||||
pb_encode_fixed64(stream, &dummy) &&
|
||||
pb_encode_fixed64(stream, &dummy) &&
|
||||
pb_encode_fixed64(stream, *arg);
|
||||
}
|
||||
|
||||
static bool write_repeated_string(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
|
||||
{
|
||||
return pb_encode_tag_for_field(stream, field) &&
|
||||
pb_encode_string(stream, 0, 0) &&
|
||||
pb_encode_tag_for_field(stream, field) &&
|
||||
pb_encode_string(stream, 0, 0) &&
|
||||
pb_encode_tag_for_field(stream, field) &&
|
||||
pb_encode_string(stream, 0, 0) &&
|
||||
pb_encode_tag_for_field(stream, field) &&
|
||||
pb_encode_string(stream, 0, 0) &&
|
||||
pb_encode_tag_for_field(stream, field) &&
|
||||
pb_encode_string(stream, *arg, strlen(*arg));
|
||||
}
|
||||
|
||||
static bool write_repeated_submsg(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
|
||||
{
|
||||
SubMessage dummy = {""};
|
||||
|
||||
return pb_encode_tag_for_field(stream, field) &&
|
||||
pb_encode_submessage(stream, SubMessage_fields, &dummy) &&
|
||||
pb_encode_tag_for_field(stream, field) &&
|
||||
pb_encode_submessage(stream, SubMessage_fields, &dummy) &&
|
||||
pb_encode_tag_for_field(stream, field) &&
|
||||
pb_encode_submessage(stream, SubMessage_fields, &dummy) &&
|
||||
pb_encode_tag_for_field(stream, field) &&
|
||||
pb_encode_submessage(stream, SubMessage_fields, &dummy) &&
|
||||
pb_encode_tag_for_field(stream, field) &&
|
||||
pb_encode_submessage(stream, SubMessage_fields, *arg);
|
||||
}
|
||||
|
||||
static bool write_limits(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
|
||||
{
|
||||
Limits limits = {0};
|
||||
limits.int32_min = INT32_MIN;
|
||||
limits.int32_max = INT32_MAX;
|
||||
limits.uint32_min = 0;
|
||||
limits.uint32_max = UINT32_MAX;
|
||||
limits.int64_min = INT64_MIN;
|
||||
limits.int64_max = INT64_MAX;
|
||||
limits.uint64_min = 0;
|
||||
limits.uint64_max = UINT64_MAX;
|
||||
limits.enum_min = HugeEnum_Negative;
|
||||
limits.enum_max = HugeEnum_Positive;
|
||||
|
||||
return pb_encode_tag_for_field(stream, field) &&
|
||||
pb_encode_submessage(stream, Limits_fields, &limits);
|
||||
}
|
||||
|
||||
static bool write_repeated_emptymsg(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
|
||||
{
|
||||
EmptyMessage emptymsg = {0};
|
||||
return pb_encode_tag_for_field(stream, field) &&
|
||||
pb_encode_submessage(stream, EmptyMessage_fields, &emptymsg) &&
|
||||
pb_encode_tag_for_field(stream, field) &&
|
||||
pb_encode_submessage(stream, EmptyMessage_fields, &emptymsg) &&
|
||||
pb_encode_tag_for_field(stream, field) &&
|
||||
pb_encode_submessage(stream, EmptyMessage_fields, &emptymsg) &&
|
||||
pb_encode_tag_for_field(stream, field) &&
|
||||
pb_encode_submessage(stream, EmptyMessage_fields, &emptymsg) &&
|
||||
pb_encode_tag_for_field(stream, field) &&
|
||||
pb_encode_submessage(stream, EmptyMessage_fields, &emptymsg);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int mode = (argc > 1) ? atoi(argv[1]) : 0;
|
||||
|
||||
/* Values for use from callbacks through pointers. */
|
||||
uint32_t rep_fixed32 = 2008;
|
||||
int32_t rep_sfixed32 = -2009;
|
||||
float rep_float = 2010.0f;
|
||||
uint64_t rep_fixed64 = 2011;
|
||||
int64_t rep_sfixed64 = -2012;
|
||||
double rep_double = 2013.0;
|
||||
SubMessage rep_submsg = {"2016", 2016, 2016};
|
||||
|
||||
uint32_t sng_fixed32 = 3048;
|
||||
int32_t sng_sfixed32 = 3049;
|
||||
float sng_float = 3050.0f;
|
||||
uint64_t sng_fixed64 = 3051;
|
||||
int64_t sng_sfixed64 = 3052;
|
||||
double sng_double = 3053.0f;
|
||||
SubMessage sng_submsg = {"3056", 3056};
|
||||
|
||||
SubMessage oneof_msg1 = {"4059", 4059};
|
||||
|
||||
AllTypes alltypes = AllTypes_init_zero;
|
||||
|
||||
/* Bind callbacks for repeated fields */
|
||||
alltypes.rep_int32.funcs.encode = &write_repeated_varint;
|
||||
alltypes.rep_int32.arg = (void*)-2001;
|
||||
|
||||
alltypes.rep_int64.funcs.encode = &write_repeated_varint;
|
||||
alltypes.rep_int64.arg = (void*)-2002;
|
||||
|
||||
alltypes.rep_uint32.funcs.encode = &write_repeated_varint;
|
||||
alltypes.rep_uint32.arg = (void*)2003;
|
||||
|
||||
alltypes.rep_uint64.funcs.encode = &write_repeated_varint;
|
||||
alltypes.rep_uint64.arg = (void*)2004;
|
||||
|
||||
alltypes.rep_sint32.funcs.encode = &write_repeated_svarint;
|
||||
alltypes.rep_sint32.arg = (void*)-2005;
|
||||
|
||||
alltypes.rep_sint64.funcs.encode = &write_repeated_svarint;
|
||||
alltypes.rep_sint64.arg = (void*)-2006;
|
||||
|
||||
alltypes.rep_bool.funcs.encode = &write_repeated_varint;
|
||||
alltypes.rep_bool.arg = (void*)true;
|
||||
|
||||
alltypes.rep_fixed32.funcs.encode = &write_repeated_fixed32;
|
||||
alltypes.rep_fixed32.arg = &rep_fixed32;
|
||||
|
||||
alltypes.rep_sfixed32.funcs.encode = &write_repeated_fixed32;
|
||||
alltypes.rep_sfixed32.arg = &rep_sfixed32;
|
||||
|
||||
alltypes.rep_float.funcs.encode = &write_repeated_fixed32;
|
||||
alltypes.rep_float.arg = &rep_float;
|
||||
|
||||
alltypes.rep_fixed64.funcs.encode = &write_repeated_fixed64;
|
||||
alltypes.rep_fixed64.arg = &rep_fixed64;
|
||||
|
||||
alltypes.rep_sfixed64.funcs.encode = &write_repeated_fixed64;
|
||||
alltypes.rep_sfixed64.arg = &rep_sfixed64;
|
||||
|
||||
alltypes.rep_double.funcs.encode = &write_repeated_double;
|
||||
alltypes.rep_double.arg = &rep_double;
|
||||
|
||||
alltypes.rep_string.funcs.encode = &write_repeated_string;
|
||||
alltypes.rep_string.arg = "2014";
|
||||
|
||||
alltypes.rep_bytes.funcs.encode = &write_repeated_string;
|
||||
alltypes.rep_bytes.arg = "2015";
|
||||
|
||||
alltypes.rep_submsg.funcs.encode = &write_repeated_submsg;
|
||||
alltypes.rep_submsg.arg = &rep_submsg;
|
||||
|
||||
alltypes.rep_enum.funcs.encode = &write_repeated_varint;
|
||||
alltypes.rep_enum.arg = (void*)MyEnum_Truth;
|
||||
|
||||
alltypes.rep_emptymsg.funcs.encode = &write_repeated_emptymsg;
|
||||
|
||||
alltypes.rep_fbytes.funcs.encode = &write_repeated_string;
|
||||
alltypes.rep_fbytes.arg = "2019";
|
||||
|
||||
alltypes.req_limits.funcs.encode = &write_limits;
|
||||
|
||||
/* Bind callbacks for singular fields */
|
||||
if (mode != 0)
|
||||
{
|
||||
alltypes.sng_int32.funcs.encode = &write_varint;
|
||||
alltypes.sng_int32.arg = (void*)3041;
|
||||
|
||||
alltypes.sng_int64.funcs.encode = &write_varint;
|
||||
alltypes.sng_int64.arg = (void*)3042;
|
||||
|
||||
alltypes.sng_uint32.funcs.encode = &write_varint;
|
||||
alltypes.sng_uint32.arg = (void*)3043;
|
||||
|
||||
alltypes.sng_uint64.funcs.encode = &write_varint;
|
||||
alltypes.sng_uint64.arg = (void*)3044;
|
||||
|
||||
alltypes.sng_sint32.funcs.encode = &write_svarint;
|
||||
alltypes.sng_sint32.arg = (void*)3045;
|
||||
|
||||
alltypes.sng_sint64.funcs.encode = &write_svarint;
|
||||
alltypes.sng_sint64.arg = (void*)3046;
|
||||
|
||||
alltypes.sng_bool.funcs.encode = &write_varint;
|
||||
alltypes.sng_bool.arg = (void*)true;
|
||||
|
||||
alltypes.sng_fixed32.funcs.encode = &write_fixed32;
|
||||
alltypes.sng_fixed32.arg = &sng_fixed32;
|
||||
|
||||
alltypes.sng_sfixed32.funcs.encode = &write_fixed32;
|
||||
alltypes.sng_sfixed32.arg = &sng_sfixed32;
|
||||
|
||||
alltypes.sng_float.funcs.encode = &write_fixed32;
|
||||
alltypes.sng_float.arg = &sng_float;
|
||||
|
||||
alltypes.sng_fixed64.funcs.encode = &write_fixed64;
|
||||
alltypes.sng_fixed64.arg = &sng_fixed64;
|
||||
|
||||
alltypes.sng_sfixed64.funcs.encode = &write_fixed64;
|
||||
alltypes.sng_sfixed64.arg = &sng_sfixed64;
|
||||
|
||||
alltypes.sng_double.funcs.encode = &write_double;
|
||||
alltypes.sng_double.arg = &sng_double;
|
||||
|
||||
alltypes.sng_string.funcs.encode = &write_string;
|
||||
alltypes.sng_string.arg = "3054";
|
||||
|
||||
alltypes.sng_bytes.funcs.encode = &write_string;
|
||||
alltypes.sng_bytes.arg = "3055";
|
||||
|
||||
alltypes.sng_submsg.funcs.encode = &write_submsg;
|
||||
alltypes.sng_submsg.arg = &sng_submsg;
|
||||
|
||||
alltypes.sng_enum.funcs.encode = &write_varint;
|
||||
alltypes.sng_enum.arg = (void*)MyEnum_Truth;
|
||||
|
||||
alltypes.sng_emptymsg.funcs.encode = &write_emptymsg;
|
||||
|
||||
alltypes.sng_fbytes.funcs.encode = &write_string;
|
||||
alltypes.sng_fbytes.arg = "3059";
|
||||
|
||||
alltypes.oneof_msg1.funcs.encode = &write_submsg;
|
||||
alltypes.oneof_msg1.arg = &oneof_msg1;
|
||||
}
|
||||
|
||||
alltypes.end.funcs.encode = &write_varint;
|
||||
alltypes.end.arg = (void*)1099;
|
||||
|
||||
{
|
||||
uint8_t buffer[2048];
|
||||
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 */
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
# Test anonymous_oneof generator option
|
||||
|
||||
Import('env')
|
||||
|
||||
# Anonymous oneofs are supported by clang and gcc
|
||||
if 'clang' in env['CC'] or 'gcc' in env['CC']:
|
||||
env2 = env.Clone()
|
||||
if '-pedantic' in env2['CFLAGS']:
|
||||
env2['CFLAGS'].remove('-pedantic')
|
||||
env2.NanopbProto('oneof')
|
||||
|
||||
dec = env2.Program(['decode_oneof.c',
|
||||
'oneof.pb.c',
|
||||
'$COMMON/pb_decode.o',
|
||||
'$COMMON/pb_common.o'])
|
||||
|
||||
env2.RunTest("message1.txt", [dec, '$BUILD/oneof/message1.pb'], ARGS = ['1'])
|
||||
env2.RunTest("message2.txt", [dec, '$BUILD/oneof/message2.pb'], ARGS = ['2'])
|
||||
env2.RunTest("message3.txt", [dec, '$BUILD/oneof/message3.pb'], ARGS = ['3'])
|
||||
@@ -0,0 +1,88 @@
|
||||
/* Decode a message using oneof fields */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <pb_decode.h>
|
||||
#include "oneof.pb.h"
|
||||
#include "test_helpers.h"
|
||||
#include "unittests.h"
|
||||
|
||||
/* Test the 'AnonymousOneOfMessage' */
|
||||
int test_oneof_1(pb_istream_t *stream, int option)
|
||||
{
|
||||
AnonymousOneOfMessage msg;
|
||||
int status = 0;
|
||||
|
||||
/* To better catch initialization errors */
|
||||
memset(&msg, 0xAA, sizeof(msg));
|
||||
|
||||
if (!pb_decode(stream, AnonymousOneOfMessage_fields, &msg))
|
||||
{
|
||||
printf("Decoding failed: %s\n", PB_GET_ERROR(stream));
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Check that the basic fields work normally */
|
||||
TEST(msg.prefix == 123);
|
||||
TEST(msg.suffix == 321);
|
||||
|
||||
/* Check that we got the right oneof according to command line */
|
||||
if (option == 1)
|
||||
{
|
||||
TEST(msg.which_values == AnonymousOneOfMessage_first_tag);
|
||||
TEST(msg.first == 999);
|
||||
}
|
||||
else if (option == 2)
|
||||
{
|
||||
TEST(msg.which_values == AnonymousOneOfMessage_second_tag);
|
||||
TEST(strcmp(msg.second, "abcd") == 0);
|
||||
}
|
||||
else if (option == 3)
|
||||
{
|
||||
TEST(msg.which_values == AnonymousOneOfMessage_third_tag);
|
||||
TEST(msg.third.array[0] == 1);
|
||||
TEST(msg.third.array[1] == 2);
|
||||
TEST(msg.third.array[2] == 3);
|
||||
TEST(msg.third.array[3] == 4);
|
||||
TEST(msg.third.array[4] == 5);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
uint8_t buffer[AnonymousOneOfMessage_size];
|
||||
size_t count;
|
||||
int option;
|
||||
|
||||
if (argc != 2)
|
||||
{
|
||||
fprintf(stderr, "Usage: decode_oneof [number]\n");
|
||||
return 1;
|
||||
}
|
||||
option = atoi(argv[1]);
|
||||
|
||||
SET_BINARY_MODE(stdin);
|
||||
count = fread(buffer, 1, sizeof(buffer), stdin);
|
||||
|
||||
if (!feof(stdin))
|
||||
{
|
||||
printf("Message does not fit in buffer\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
{
|
||||
int status = 0;
|
||||
pb_istream_t stream;
|
||||
|
||||
stream = pb_istream_from_buffer(buffer, count);
|
||||
status = test_oneof_1(&stream, option);
|
||||
|
||||
if (status != 0)
|
||||
return status;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
syntax = "proto2";
|
||||
|
||||
import 'nanopb.proto';
|
||||
|
||||
message SubMessage
|
||||
{
|
||||
repeated int32 array = 1 [(nanopb).max_count = 8];
|
||||
}
|
||||
|
||||
/* Oneof in a message with other fields */
|
||||
message AnonymousOneOfMessage
|
||||
{
|
||||
option (nanopb_msgopt).anonymous_oneof = true;
|
||||
required int32 prefix = 1;
|
||||
oneof values
|
||||
{
|
||||
int32 first = 5;
|
||||
string second = 6 [(nanopb).max_size = 8];
|
||||
SubMessage third = 7;
|
||||
}
|
||||
required int32 suffix = 99;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
# Test usage of Any type
|
||||
|
||||
Import("env")
|
||||
|
||||
incpath = env.Clone()
|
||||
incpath.Append(PROTOCPATH = '#any_type')
|
||||
incpath.Append(CPPPATH = '$BUILD/any_type')
|
||||
|
||||
incpath.NanopbProto("anytest")
|
||||
incpath.NanopbProto(["google/protobuf/any", "google/protobuf/any.options"])
|
||||
incpath.NanopbProto("google/protobuf/duration")
|
||||
|
||||
enc = incpath.Program(["encode_any.c", "anytest.pb.c", "google/protobuf/any.pb.c",
|
||||
"google/protobuf/duration.pb.c",
|
||||
"$COMMON/pb_encode.o", "$COMMON/pb_common.o"])
|
||||
|
||||
dec = incpath.Program(["decode_any.c", "anytest.pb.c", "google/protobuf/any.pb.c",
|
||||
"google/protobuf/duration.pb.c",
|
||||
"$COMMON/pb_decode.o", "$COMMON/pb_common.o"])
|
||||
|
||||
env.RunTest(enc)
|
||||
env.RunTest([dec, "encode_any.output"])
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
// This file is an example and test case on handling the Any type in nanopb.
|
||||
// The Any type is defined in Google-provided any.proto file:
|
||||
// message Any {
|
||||
// string type_url = 1;
|
||||
// bytes value = 2;
|
||||
// }
|
||||
//
|
||||
// The type_url field identifies the type of message, and the message data
|
||||
// is inside the bytes field.
|
||||
//
|
||||
// The encoding follows the basic format of protobuf and doesn't require
|
||||
// special support to handle. In this example, we just set maximum size for
|
||||
// the type_url and value fields, and then call pb_decode() again on the value.
|
||||
//
|
||||
// This does result in unnecessarily copying the data around, so for larger
|
||||
// values it is preferable to use callbacks on the fields instead.
|
||||
|
||||
syntax = "proto3";
|
||||
import "google/protobuf/any.proto";
|
||||
|
||||
message BaseMessage {
|
||||
int32 start = 1;
|
||||
google.protobuf.Any details = 2;
|
||||
int32 end = 3;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
#include <assert.h>
|
||||
#include <pb_decode.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "test_helpers.h"
|
||||
#include "anytest.pb.h"
|
||||
#include "google/protobuf/duration.pb.h"
|
||||
|
||||
int main()
|
||||
{
|
||||
BaseMessage msg = BaseMessage_init_zero;
|
||||
uint8_t buffer[256];
|
||||
pb_istream_t stream;
|
||||
size_t count;
|
||||
bool status;
|
||||
|
||||
/* Read the data into buffer */
|
||||
SET_BINARY_MODE(stdin);
|
||||
count = fread(buffer, 1, sizeof(buffer), stdin);
|
||||
stream = pb_istream_from_buffer(buffer, count);
|
||||
|
||||
/* Decode the base message */
|
||||
if (!pb_decode(&stream, BaseMessage_fields, &msg))
|
||||
{
|
||||
printf("Parsing failed: %s\n", PB_GET_ERROR(&stream));
|
||||
return 1;
|
||||
}
|
||||
|
||||
assert(msg.start == 1234);
|
||||
assert(msg.end == 5678);
|
||||
|
||||
/* Decode the Any message if we know the type */
|
||||
if (strcmp(msg.details.type_url, "type.googleapis.com/google.protobuf.Duration") == 0)
|
||||
{
|
||||
google_protobuf_Duration duration = google_protobuf_Duration_init_zero;
|
||||
stream = pb_istream_from_buffer(msg.details.value.bytes, msg.details.value.size);
|
||||
status = pb_decode(&stream, google_protobuf_Duration_fields, &duration);
|
||||
assert(status);
|
||||
assert(duration.seconds == 99999);
|
||||
assert(duration.nanos == 100);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Unknown Any type\n");
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
#include <assert.h>
|
||||
#include <pb_encode.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "test_helpers.h"
|
||||
#include "anytest.pb.h"
|
||||
#include "google/protobuf/duration.pb.h"
|
||||
|
||||
int main()
|
||||
{
|
||||
BaseMessage msg = BaseMessage_init_zero;
|
||||
google_protobuf_Duration duration = google_protobuf_Duration_init_zero;
|
||||
uint8_t buffer[256];
|
||||
pb_ostream_t stream;
|
||||
bool status;
|
||||
|
||||
msg.start = 1234;
|
||||
msg.end = 5678;
|
||||
|
||||
/* Fill in the Any message header */
|
||||
msg.has_details = true;
|
||||
strncpy(msg.details.type_url, "type.googleapis.com/google.protobuf.Duration", sizeof(msg.details.type_url));
|
||||
|
||||
/* Encode a Duration message inside the Any message. */
|
||||
duration.seconds = 99999;
|
||||
duration.nanos = 100;
|
||||
stream = pb_ostream_from_buffer(msg.details.value.bytes, sizeof(msg.details.value.bytes));
|
||||
status = pb_encode(&stream, google_protobuf_Duration_fields, &duration);
|
||||
assert(status);
|
||||
msg.details.value.size = stream.bytes_written;
|
||||
|
||||
/* Then encode the outer message */
|
||||
stream = pb_ostream_from_buffer(buffer, sizeof(buffer));
|
||||
if (pb_encode(&stream, BaseMessage_fields, &msg))
|
||||
{
|
||||
/* Write the result data to stdout */
|
||||
SET_BINARY_MODE(stdout);
|
||||
fwrite(buffer, 1, stream.bytes_written, stdout);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Encoding failed: %s\n", PB_GET_ERROR(&stream));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
google.protobuf.Any.type_url max_size:64
|
||||
google.protobuf.Any.value max_size:64
|
||||
@@ -0,0 +1,154 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package google.protobuf;
|
||||
|
||||
option csharp_namespace = "Google.Protobuf.WellKnownTypes";
|
||||
option go_package = "github.com/golang/protobuf/ptypes/any";
|
||||
option java_package = "com.google.protobuf";
|
||||
option java_outer_classname = "AnyProto";
|
||||
option java_multiple_files = true;
|
||||
option objc_class_prefix = "GPB";
|
||||
|
||||
// `Any` contains an arbitrary serialized protocol buffer message along with a
|
||||
// URL that describes the type of the serialized message.
|
||||
//
|
||||
// Protobuf library provides support to pack/unpack Any values in the form
|
||||
// of utility functions or additional generated methods of the Any type.
|
||||
//
|
||||
// Example 1: Pack and unpack a message in C++.
|
||||
//
|
||||
// Foo foo = ...;
|
||||
// Any any;
|
||||
// any.PackFrom(foo);
|
||||
// ...
|
||||
// if (any.UnpackTo(&foo)) {
|
||||
// ...
|
||||
// }
|
||||
//
|
||||
// Example 2: Pack and unpack a message in Java.
|
||||
//
|
||||
// Foo foo = ...;
|
||||
// Any any = Any.pack(foo);
|
||||
// ...
|
||||
// if (any.is(Foo.class)) {
|
||||
// foo = any.unpack(Foo.class);
|
||||
// }
|
||||
//
|
||||
// Example 3: Pack and unpack a message in Python.
|
||||
//
|
||||
// foo = Foo(...)
|
||||
// any = Any()
|
||||
// any.Pack(foo)
|
||||
// ...
|
||||
// if any.Is(Foo.DESCRIPTOR):
|
||||
// any.Unpack(foo)
|
||||
// ...
|
||||
//
|
||||
// Example 4: Pack and unpack a message in Go
|
||||
//
|
||||
// foo := &pb.Foo{...}
|
||||
// any, err := ptypes.MarshalAny(foo)
|
||||
// ...
|
||||
// foo := &pb.Foo{}
|
||||
// if err := ptypes.UnmarshalAny(any, foo); err != nil {
|
||||
// ...
|
||||
// }
|
||||
//
|
||||
// The pack methods provided by protobuf library will by default use
|
||||
// 'type.googleapis.com/full.type.name' as the type URL and the unpack
|
||||
// methods only use the fully qualified type name after the last '/'
|
||||
// in the type URL, for example "foo.bar.com/x/y.z" will yield type
|
||||
// name "y.z".
|
||||
//
|
||||
//
|
||||
// JSON
|
||||
// ====
|
||||
// The JSON representation of an `Any` value uses the regular
|
||||
// representation of the deserialized, embedded message, with an
|
||||
// additional field `@type` which contains the type URL. Example:
|
||||
//
|
||||
// package google.profile;
|
||||
// message Person {
|
||||
// string first_name = 1;
|
||||
// string last_name = 2;
|
||||
// }
|
||||
//
|
||||
// {
|
||||
// "@type": "type.googleapis.com/google.profile.Person",
|
||||
// "firstName": <string>,
|
||||
// "lastName": <string>
|
||||
// }
|
||||
//
|
||||
// If the embedded message type is well-known and has a custom JSON
|
||||
// representation, that representation will be embedded adding a field
|
||||
// `value` which holds the custom JSON in addition to the `@type`
|
||||
// field. Example (for message [google.protobuf.Duration][]):
|
||||
//
|
||||
// {
|
||||
// "@type": "type.googleapis.com/google.protobuf.Duration",
|
||||
// "value": "1.212s"
|
||||
// }
|
||||
//
|
||||
message Any {
|
||||
// A URL/resource name that uniquely identifies the type of the serialized
|
||||
// protocol buffer message. The last segment of the URL's path must represent
|
||||
// the fully qualified name of the type (as in
|
||||
// `path/google.protobuf.Duration`). The name should be in a canonical form
|
||||
// (e.g., leading "." is not accepted).
|
||||
//
|
||||
// In practice, teams usually precompile into the binary all types that they
|
||||
// expect it to use in the context of Any. However, for URLs which use the
|
||||
// scheme `http`, `https`, or no scheme, one can optionally set up a type
|
||||
// server that maps type URLs to message definitions as follows:
|
||||
//
|
||||
// * If no scheme is provided, `https` is assumed.
|
||||
// * An HTTP GET on the URL must yield a [google.protobuf.Type][]
|
||||
// value in binary format, or produce an error.
|
||||
// * Applications are allowed to cache lookup results based on the
|
||||
// URL, or have them precompiled into a binary to avoid any
|
||||
// lookup. Therefore, binary compatibility needs to be preserved
|
||||
// on changes to types. (Use versioned type names to manage
|
||||
// breaking changes.)
|
||||
//
|
||||
// Note: this functionality is not currently available in the official
|
||||
// protobuf release, and it is not used for type URLs beginning with
|
||||
// type.googleapis.com.
|
||||
//
|
||||
// Schemes other than `http`, `https` (or the empty scheme) might be
|
||||
// used with implementation specific semantics.
|
||||
//
|
||||
string type_url = 1;
|
||||
|
||||
// Must be a valid serialized protocol buffer of the above specified type.
|
||||
bytes value = 2;
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package google.protobuf;
|
||||
|
||||
option csharp_namespace = "Google.Protobuf.WellKnownTypes";
|
||||
option cc_enable_arenas = true;
|
||||
option go_package = "github.com/golang/protobuf/ptypes/duration";
|
||||
option java_package = "com.google.protobuf";
|
||||
option java_outer_classname = "DurationProto";
|
||||
option java_multiple_files = true;
|
||||
option objc_class_prefix = "GPB";
|
||||
|
||||
// A Duration represents a signed, fixed-length span of time represented
|
||||
// as a count of seconds and fractions of seconds at nanosecond
|
||||
// resolution. It is independent of any calendar and concepts like "day"
|
||||
// or "month". It is related to Timestamp in that the difference between
|
||||
// two Timestamp values is a Duration and it can be added or subtracted
|
||||
// from a Timestamp. Range is approximately +-10,000 years.
|
||||
//
|
||||
// # Examples
|
||||
//
|
||||
// Example 1: Compute Duration from two Timestamps in pseudo code.
|
||||
//
|
||||
// Timestamp start = ...;
|
||||
// Timestamp end = ...;
|
||||
// Duration duration = ...;
|
||||
//
|
||||
// duration.seconds = end.seconds - start.seconds;
|
||||
// duration.nanos = end.nanos - start.nanos;
|
||||
//
|
||||
// if (duration.seconds < 0 && duration.nanos > 0) {
|
||||
// duration.seconds += 1;
|
||||
// duration.nanos -= 1000000000;
|
||||
// } else if (durations.seconds > 0 && duration.nanos < 0) {
|
||||
// duration.seconds -= 1;
|
||||
// duration.nanos += 1000000000;
|
||||
// }
|
||||
//
|
||||
// Example 2: Compute Timestamp from Timestamp + Duration in pseudo code.
|
||||
//
|
||||
// Timestamp start = ...;
|
||||
// Duration duration = ...;
|
||||
// Timestamp end = ...;
|
||||
//
|
||||
// end.seconds = start.seconds + duration.seconds;
|
||||
// end.nanos = start.nanos + duration.nanos;
|
||||
//
|
||||
// if (end.nanos < 0) {
|
||||
// end.seconds -= 1;
|
||||
// end.nanos += 1000000000;
|
||||
// } else if (end.nanos >= 1000000000) {
|
||||
// end.seconds += 1;
|
||||
// end.nanos -= 1000000000;
|
||||
// }
|
||||
//
|
||||
// Example 3: Compute Duration from datetime.timedelta in Python.
|
||||
//
|
||||
// td = datetime.timedelta(days=3, minutes=10)
|
||||
// duration = Duration()
|
||||
// duration.FromTimedelta(td)
|
||||
//
|
||||
// # JSON Mapping
|
||||
//
|
||||
// In JSON format, the Duration type is encoded as a string rather than an
|
||||
// object, where the string ends in the suffix "s" (indicating seconds) and
|
||||
// is preceded by the number of seconds, with nanoseconds expressed as
|
||||
// fractional seconds. For example, 3 seconds with 0 nanoseconds should be
|
||||
// encoded in JSON format as "3s", while 3 seconds and 1 nanosecond should
|
||||
// be expressed in JSON format as "3.000000001s", and 3 seconds and 1
|
||||
// microsecond should be expressed in JSON format as "3.000001s".
|
||||
//
|
||||
//
|
||||
message Duration {
|
||||
|
||||
// Signed seconds of the span of time. Must be from -315,576,000,000
|
||||
// to +315,576,000,000 inclusive. Note: these bounds are computed from:
|
||||
// 60 sec/min * 60 min/hr * 24 hr/day * 365.25 days/year * 10000 years
|
||||
int64 seconds = 1;
|
||||
|
||||
// Signed fractions of a second at nanosecond resolution of the span
|
||||
// of time. Durations less than one second are represented with a 0
|
||||
// `seconds` field and a positive or negative `nanos` field. For durations
|
||||
// of one second or more, a non-zero value for the `nanos` field must be
|
||||
// of the same sign as the `seconds` field. Must be from -999,999,999
|
||||
// to +999,999,999 inclusive.
|
||||
int32 nanos = 2;
|
||||
}
|
||||
@@ -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", "$COMMON/pb_common.o"])
|
||||
dec = env.Program(["decode_legacy.c", "alltypes_legacy.c", "$COMMON/pb_decode.o", "$COMMON/pb_common.o"])
|
||||
|
||||
env.RunTest(enc)
|
||||
env.RunTest([dec, "encode_legacy.output"])
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
/* Automatically generated nanopb constant definitions */
|
||||
/* Generated by nanopb-0.4.0-dev */
|
||||
|
||||
#include "alltypes_legacy.h"
|
||||
|
||||
/* @@protoc_insertion_point(includes) */
|
||||
#if PB_PROTO_HEADER_VERSION != 40
|
||||
#error Regenerate this file with the current version of nanopb generator.
|
||||
#endif
|
||||
|
||||
pb_byte_t SubMessage_DEFAULT[] = {0x0a, 0x01, 0x31, 0x10, 0x02, 0x1d, 0x03, 0x00, 0x00, 0x00, 0x00};
|
||||
pb_byte_t EmptyMessage_DEFAULT[] = {0x00};
|
||||
pb_byte_t Limits_DEFAULT[] = {0x08, 0xff, 0xff, 0xff, 0xff, 0x07, 0x10, 0x81, 0x80, 0x80, 0x80, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x01, 0x18, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x20, 0x00, 0x28, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x30, 0x81, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x01, 0x38, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x40, 0x00, 0x48, 0xff, 0xff, 0xff, 0xff, 0x07, 0x50, 0x81, 0x80, 0x80, 0x80, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00};
|
||||
pb_byte_t AllTypes_DEFAULT[] = {0xc8, 0x02, 0xc9, 0x1f, 0xd0, 0x02, 0xca, 0x1f, 0xd8, 0x02, 0xcb, 0x1f, 0xe0, 0x02, 0xcc, 0x1f, 0xe8, 0x02, 0x9a, 0x3f, 0xf0, 0x02, 0x9c, 0x3f, 0xf8, 0x02, 0x00, 0x85, 0x03, 0xd0, 0x0f, 0x00, 0x00, 0x8d, 0x03, 0xd1, 0x0f, 0x00, 0x00, 0x95, 0x03, 0x00, 0x20, 0x7d, 0x45, 0x99, 0x03, 0xd3, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa1, 0x03, 0xd4, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa9, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0xaf, 0x40, 0xb2, 0x03, 0x04, 0x34, 0x30, 0x35, 0x34, 0xba, 0x03, 0x04, 0x34, 0x30, 0x35, 0x35, 0xc8, 0x03, 0x02, 0x00};
|
||||
|
||||
|
||||
PB_BIND(SubMessage, SubMessage, AUTO)
|
||||
|
||||
|
||||
PB_BIND(EmptyMessage, EmptyMessage, AUTO)
|
||||
|
||||
|
||||
PB_BIND(Limits, Limits, AUTO)
|
||||
|
||||
|
||||
PB_BIND(AllTypes, AllTypes, 2)
|
||||
|
||||
|
||||
|
||||
|
||||
#ifndef PB_CONVERT_DOUBLE_FLOAT
|
||||
/* On some platforms (such as AVR), double is really float.
|
||||
* Using double on these platforms is not directly supported
|
||||
* by nanopb, but see example_avr_double.
|
||||
* To get rid of this error, remove any double fields from your .proto.
|
||||
*/
|
||||
PB_STATIC_ASSERT(sizeof(double) == 8, DOUBLE_MUST_BE_8_BYTES)
|
||||
#endif
|
||||
|
||||
/* @@protoc_insertion_point(eof) */
|
||||
@@ -0,0 +1,348 @@
|
||||
/* Automatically generated nanopb header */
|
||||
/* Generated by nanopb-0.4.0-dev */
|
||||
|
||||
#ifndef PB_ALLTYPES_LEGACY_H_INCLUDED
|
||||
#define PB_ALLTYPES_LEGACY_H_INCLUDED
|
||||
#include <pb.h>
|
||||
|
||||
/* @@protoc_insertion_point(includes) */
|
||||
#if PB_PROTO_HEADER_VERSION != 40
|
||||
#error Regenerate this file with the current version of nanopb generator.
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Enum definitions */
|
||||
typedef enum _HugeEnum {
|
||||
HugeEnum_Negative = -2147483647,
|
||||
HugeEnum_Positive = 2147483647
|
||||
} HugeEnum;
|
||||
#define _HugeEnum_MIN HugeEnum_Negative
|
||||
#define _HugeEnum_MAX HugeEnum_Positive
|
||||
#define _HugeEnum_ARRAYSIZE ((HugeEnum)(HugeEnum_Positive+1))
|
||||
|
||||
typedef enum _MyEnum {
|
||||
MyEnum_Zero = 0,
|
||||
MyEnum_First = 1,
|
||||
MyEnum_Second = 2,
|
||||
MyEnum_Truth = 42
|
||||
} MyEnum;
|
||||
#define _MyEnum_MIN MyEnum_Zero
|
||||
#define _MyEnum_MAX MyEnum_Truth
|
||||
#define _MyEnum_ARRAYSIZE ((MyEnum)(MyEnum_Truth+1))
|
||||
|
||||
/* Struct definitions */
|
||||
typedef struct _EmptyMessage {
|
||||
char dummy_field;
|
||||
/* @@protoc_insertion_point(struct:EmptyMessage) */
|
||||
} EmptyMessage;
|
||||
|
||||
|
||||
typedef struct _Limits {
|
||||
int32_t int32_min;
|
||||
int32_t int32_max;
|
||||
uint32_t uint32_min;
|
||||
uint32_t uint32_max;
|
||||
int64_t int64_min;
|
||||
int64_t int64_max;
|
||||
uint64_t uint64_min;
|
||||
uint64_t uint64_max;
|
||||
HugeEnum enum_min;
|
||||
HugeEnum enum_max;
|
||||
/* @@protoc_insertion_point(struct:Limits) */
|
||||
} Limits;
|
||||
|
||||
|
||||
typedef struct _SubMessage {
|
||||
char substuff1[16];
|
||||
int32_t substuff2;
|
||||
bool has_substuff3;
|
||||
uint32_t substuff3;
|
||||
/* @@protoc_insertion_point(struct:SubMessage) */
|
||||
} SubMessage;
|
||||
|
||||
|
||||
typedef PB_BYTES_ARRAY_T(16) AllTypes_req_bytes_t;
|
||||
typedef PB_BYTES_ARRAY_T(16) AllTypes_rep_bytes_t;
|
||||
typedef PB_BYTES_ARRAY_T(16) AllTypes_opt_bytes_t;
|
||||
typedef struct _AllTypes {
|
||||
int32_t req_int32;
|
||||
int64_t req_int64;
|
||||
uint32_t req_uint32;
|
||||
uint64_t req_uint64;
|
||||
int32_t req_sint32;
|
||||
int64_t req_sint64;
|
||||
bool req_bool;
|
||||
uint32_t req_fixed32;
|
||||
int32_t req_sfixed32;
|
||||
float req_float;
|
||||
uint64_t req_fixed64;
|
||||
int64_t req_sfixed64;
|
||||
double req_double;
|
||||
char req_string[16];
|
||||
AllTypes_req_bytes_t req_bytes;
|
||||
SubMessage req_submsg;
|
||||
MyEnum req_enum;
|
||||
pb_size_t rep_int32_count;
|
||||
int32_t rep_int32[5];
|
||||
pb_size_t rep_int64_count;
|
||||
int64_t rep_int64[5];
|
||||
pb_size_t rep_uint32_count;
|
||||
uint32_t rep_uint32[5];
|
||||
pb_size_t rep_uint64_count;
|
||||
uint64_t rep_uint64[5];
|
||||
pb_size_t rep_sint32_count;
|
||||
int32_t rep_sint32[5];
|
||||
pb_size_t rep_sint64_count;
|
||||
int64_t rep_sint64[5];
|
||||
pb_size_t rep_bool_count;
|
||||
bool rep_bool[5];
|
||||
pb_size_t rep_fixed32_count;
|
||||
uint32_t rep_fixed32[5];
|
||||
pb_size_t rep_sfixed32_count;
|
||||
int32_t rep_sfixed32[5];
|
||||
pb_size_t rep_float_count;
|
||||
float rep_float[5];
|
||||
pb_size_t rep_fixed64_count;
|
||||
uint64_t rep_fixed64[5];
|
||||
pb_size_t rep_sfixed64_count;
|
||||
int64_t rep_sfixed64[5];
|
||||
pb_size_t rep_double_count;
|
||||
double rep_double[5];
|
||||
pb_size_t rep_string_count;
|
||||
char rep_string[5][16];
|
||||
pb_size_t rep_bytes_count;
|
||||
AllTypes_rep_bytes_t rep_bytes[5];
|
||||
pb_size_t rep_submsg_count;
|
||||
SubMessage rep_submsg[5];
|
||||
pb_size_t rep_enum_count;
|
||||
MyEnum rep_enum[5];
|
||||
bool has_opt_int32;
|
||||
int32_t opt_int32;
|
||||
bool has_opt_int64;
|
||||
int64_t opt_int64;
|
||||
bool has_opt_uint32;
|
||||
uint32_t opt_uint32;
|
||||
bool has_opt_uint64;
|
||||
uint64_t opt_uint64;
|
||||
bool has_opt_sint32;
|
||||
int32_t opt_sint32;
|
||||
bool has_opt_sint64;
|
||||
int64_t opt_sint64;
|
||||
bool has_opt_bool;
|
||||
bool opt_bool;
|
||||
bool has_opt_fixed32;
|
||||
uint32_t opt_fixed32;
|
||||
bool has_opt_sfixed32;
|
||||
int32_t opt_sfixed32;
|
||||
bool has_opt_float;
|
||||
float opt_float;
|
||||
bool has_opt_fixed64;
|
||||
uint64_t opt_fixed64;
|
||||
bool has_opt_sfixed64;
|
||||
int64_t opt_sfixed64;
|
||||
bool has_opt_double;
|
||||
double opt_double;
|
||||
bool has_opt_string;
|
||||
char opt_string[16];
|
||||
bool has_opt_bytes;
|
||||
AllTypes_opt_bytes_t opt_bytes;
|
||||
bool has_opt_submsg;
|
||||
SubMessage opt_submsg;
|
||||
bool has_opt_enum;
|
||||
MyEnum opt_enum;
|
||||
int32_t end;
|
||||
pb_extension_t *extensions;
|
||||
/* @@protoc_insertion_point(struct:AllTypes) */
|
||||
} AllTypes;
|
||||
|
||||
|
||||
/* Initializer values for message structs */
|
||||
#define SubMessage_init_default {"1", 2, false, 3u}
|
||||
#define EmptyMessage_init_default {0}
|
||||
#define Limits_init_default {2147483647, -2147483647, 4294967295u, 0u, 9223372036854775807ll, -9223372036854775807ll, 18446744073709551615ull, 0ull, HugeEnum_Positive, HugeEnum_Negative}
|
||||
#define AllTypes_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "", {0, {0}}, SubMessage_init_default, _MyEnum_MIN, 0, {0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0}, 0, {"", "", "", "", ""}, 0, {{0, {0}}, {0, {0}}, {0, {0}}, {0, {0}}, {0, {0}}}, 0, {SubMessage_init_default, SubMessage_init_default, SubMessage_init_default, SubMessage_init_default, SubMessage_init_default}, 0, {_MyEnum_MIN, _MyEnum_MIN, _MyEnum_MIN, _MyEnum_MIN, _MyEnum_MIN}, false, 4041, false, 4042ll, false, 4043u, false, 4044ull, false, 4045, false, 4046, false, false, false, 4048u, false, 4049, false, 4050, false, 4051ull, false, 4052ll, false, 4053, false, "4054", false, {4, {0x34,0x30,0x35,0x35}}, false, SubMessage_init_default, false, MyEnum_Second, 0, NULL}
|
||||
#define SubMessage_init_zero {"", 0, false, 0}
|
||||
#define EmptyMessage_init_zero {0}
|
||||
#define Limits_init_zero {0, 0, 0, 0, 0, 0, 0, 0, _HugeEnum_MIN, _HugeEnum_MIN}
|
||||
#define AllTypes_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "", {0, {0}}, SubMessage_init_zero, _MyEnum_MIN, 0, {0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0}, 0, {"", "", "", "", ""}, 0, {{0, {0}}, {0, {0}}, {0, {0}}, {0, {0}}, {0, {0}}}, 0, {SubMessage_init_zero, SubMessage_init_zero, SubMessage_init_zero, SubMessage_init_zero, SubMessage_init_zero}, 0, {_MyEnum_MIN, _MyEnum_MIN, _MyEnum_MIN, _MyEnum_MIN, _MyEnum_MIN}, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, "", false, {0, {0}}, false, SubMessage_init_zero, false, _MyEnum_MIN, 0, NULL}
|
||||
|
||||
/* Field tags (for use in manual encoding/decoding) */
|
||||
#define Limits_int32_min_tag 1
|
||||
#define Limits_int32_max_tag 2
|
||||
#define Limits_uint32_min_tag 3
|
||||
#define Limits_uint32_max_tag 4
|
||||
#define Limits_int64_min_tag 5
|
||||
#define Limits_int64_max_tag 6
|
||||
#define Limits_uint64_min_tag 7
|
||||
#define Limits_uint64_max_tag 8
|
||||
#define Limits_enum_min_tag 9
|
||||
#define Limits_enum_max_tag 10
|
||||
#define SubMessage_substuff1_tag 1
|
||||
#define SubMessage_substuff2_tag 2
|
||||
#define SubMessage_substuff3_tag 3
|
||||
#define AllTypes_req_int32_tag 1
|
||||
#define AllTypes_req_int64_tag 2
|
||||
#define AllTypes_req_uint32_tag 3
|
||||
#define AllTypes_req_uint64_tag 4
|
||||
#define AllTypes_req_sint32_tag 5
|
||||
#define AllTypes_req_sint64_tag 6
|
||||
#define AllTypes_req_bool_tag 7
|
||||
#define AllTypes_req_fixed32_tag 8
|
||||
#define AllTypes_req_sfixed32_tag 9
|
||||
#define AllTypes_req_float_tag 10
|
||||
#define AllTypes_req_fixed64_tag 11
|
||||
#define AllTypes_req_sfixed64_tag 12
|
||||
#define AllTypes_req_double_tag 13
|
||||
#define AllTypes_req_string_tag 14
|
||||
#define AllTypes_req_bytes_tag 15
|
||||
#define AllTypes_req_submsg_tag 16
|
||||
#define AllTypes_req_enum_tag 17
|
||||
#define AllTypes_rep_int32_tag 21
|
||||
#define AllTypes_rep_int64_tag 22
|
||||
#define AllTypes_rep_uint32_tag 23
|
||||
#define AllTypes_rep_uint64_tag 24
|
||||
#define AllTypes_rep_sint32_tag 25
|
||||
#define AllTypes_rep_sint64_tag 26
|
||||
#define AllTypes_rep_bool_tag 27
|
||||
#define AllTypes_rep_fixed32_tag 28
|
||||
#define AllTypes_rep_sfixed32_tag 29
|
||||
#define AllTypes_rep_float_tag 30
|
||||
#define AllTypes_rep_fixed64_tag 31
|
||||
#define AllTypes_rep_sfixed64_tag 32
|
||||
#define AllTypes_rep_double_tag 33
|
||||
#define AllTypes_rep_string_tag 34
|
||||
#define AllTypes_rep_bytes_tag 35
|
||||
#define AllTypes_rep_submsg_tag 36
|
||||
#define AllTypes_rep_enum_tag 37
|
||||
#define AllTypes_opt_int32_tag 41
|
||||
#define AllTypes_opt_int64_tag 42
|
||||
#define AllTypes_opt_uint32_tag 43
|
||||
#define AllTypes_opt_uint64_tag 44
|
||||
#define AllTypes_opt_sint32_tag 45
|
||||
#define AllTypes_opt_sint64_tag 46
|
||||
#define AllTypes_opt_bool_tag 47
|
||||
#define AllTypes_opt_fixed32_tag 48
|
||||
#define AllTypes_opt_sfixed32_tag 49
|
||||
#define AllTypes_opt_float_tag 50
|
||||
#define AllTypes_opt_fixed64_tag 51
|
||||
#define AllTypes_opt_sfixed64_tag 52
|
||||
#define AllTypes_opt_double_tag 53
|
||||
#define AllTypes_opt_string_tag 54
|
||||
#define AllTypes_opt_bytes_tag 55
|
||||
#define AllTypes_opt_submsg_tag 56
|
||||
#define AllTypes_opt_enum_tag 57
|
||||
#define AllTypes_end_tag 99
|
||||
|
||||
/* Struct field encoding specification for nanopb */
|
||||
#define SubMessage_FIELDLIST(X, a) \
|
||||
X(a, STATIC, REQUIRED, STRING, substuff1, 1) \
|
||||
X(a, STATIC, REQUIRED, INT32, substuff2, 2) \
|
||||
X(a, STATIC, OPTIONAL, FIXED32, substuff3, 3)
|
||||
#define SubMessage_CALLBACK NULL
|
||||
|
||||
#define EmptyMessage_FIELDLIST(X, a) \
|
||||
|
||||
#define EmptyMessage_CALLBACK NULL
|
||||
|
||||
#define Limits_FIELDLIST(X, a) \
|
||||
X(a, STATIC, REQUIRED, INT32, int32_min, 1) \
|
||||
X(a, STATIC, REQUIRED, INT32, int32_max, 2) \
|
||||
X(a, STATIC, REQUIRED, UINT32, uint32_min, 3) \
|
||||
X(a, STATIC, REQUIRED, UINT32, uint32_max, 4) \
|
||||
X(a, STATIC, REQUIRED, INT64, int64_min, 5) \
|
||||
X(a, STATIC, REQUIRED, INT64, int64_max, 6) \
|
||||
X(a, STATIC, REQUIRED, UINT64, uint64_min, 7) \
|
||||
X(a, STATIC, REQUIRED, UINT64, uint64_max, 8) \
|
||||
X(a, STATIC, REQUIRED, ENUM, enum_min, 9) \
|
||||
X(a, STATIC, REQUIRED, ENUM, enum_max, 10)
|
||||
#define Limits_CALLBACK NULL
|
||||
|
||||
#define AllTypes_FIELDLIST(X, a) \
|
||||
X(a, STATIC, REQUIRED, INT32, req_int32, 1) \
|
||||
X(a, STATIC, REQUIRED, INT64, req_int64, 2) \
|
||||
X(a, STATIC, REQUIRED, UINT32, req_uint32, 3) \
|
||||
X(a, STATIC, REQUIRED, UINT64, req_uint64, 4) \
|
||||
X(a, STATIC, REQUIRED, SINT32, req_sint32, 5) \
|
||||
X(a, STATIC, REQUIRED, SINT64, req_sint64, 6) \
|
||||
X(a, STATIC, REQUIRED, BOOL, req_bool, 7) \
|
||||
X(a, STATIC, REQUIRED, FIXED32, req_fixed32, 8) \
|
||||
X(a, STATIC, REQUIRED, SFIXED32, req_sfixed32, 9) \
|
||||
X(a, STATIC, REQUIRED, FLOAT, req_float, 10) \
|
||||
X(a, STATIC, REQUIRED, FIXED64, req_fixed64, 11) \
|
||||
X(a, STATIC, REQUIRED, SFIXED64, req_sfixed64, 12) \
|
||||
X(a, STATIC, REQUIRED, DOUBLE, req_double, 13) \
|
||||
X(a, STATIC, REQUIRED, STRING, req_string, 14) \
|
||||
X(a, STATIC, REQUIRED, BYTES, req_bytes, 15) \
|
||||
X(a, STATIC, REQUIRED, MESSAGE, req_submsg, 16) \
|
||||
X(a, STATIC, REQUIRED, UENUM, req_enum, 17) \
|
||||
X(a, STATIC, REPEATED, INT32, rep_int32, 21) \
|
||||
X(a, STATIC, REPEATED, INT64, rep_int64, 22) \
|
||||
X(a, STATIC, REPEATED, UINT32, rep_uint32, 23) \
|
||||
X(a, STATIC, REPEATED, UINT64, rep_uint64, 24) \
|
||||
X(a, STATIC, REPEATED, SINT32, rep_sint32, 25) \
|
||||
X(a, STATIC, REPEATED, SINT64, rep_sint64, 26) \
|
||||
X(a, STATIC, REPEATED, BOOL, rep_bool, 27) \
|
||||
X(a, STATIC, REPEATED, FIXED32, rep_fixed32, 28) \
|
||||
X(a, STATIC, REPEATED, SFIXED32, rep_sfixed32, 29) \
|
||||
X(a, STATIC, REPEATED, FLOAT, rep_float, 30) \
|
||||
X(a, STATIC, REPEATED, FIXED64, rep_fixed64, 31) \
|
||||
X(a, STATIC, REPEATED, SFIXED64, rep_sfixed64, 32) \
|
||||
X(a, STATIC, REPEATED, DOUBLE, rep_double, 33) \
|
||||
X(a, STATIC, REPEATED, STRING, rep_string, 34) \
|
||||
X(a, STATIC, REPEATED, BYTES, rep_bytes, 35) \
|
||||
X(a, STATIC, REPEATED, MESSAGE, rep_submsg, 36) \
|
||||
X(a, STATIC, REPEATED, UENUM, rep_enum, 37) \
|
||||
X(a, STATIC, OPTIONAL, INT32, opt_int32, 41) \
|
||||
X(a, STATIC, OPTIONAL, INT64, opt_int64, 42) \
|
||||
X(a, STATIC, OPTIONAL, UINT32, opt_uint32, 43) \
|
||||
X(a, STATIC, OPTIONAL, UINT64, opt_uint64, 44) \
|
||||
X(a, STATIC, OPTIONAL, SINT32, opt_sint32, 45) \
|
||||
X(a, STATIC, OPTIONAL, SINT64, opt_sint64, 46) \
|
||||
X(a, STATIC, OPTIONAL, BOOL, opt_bool, 47) \
|
||||
X(a, STATIC, OPTIONAL, FIXED32, opt_fixed32, 48) \
|
||||
X(a, STATIC, OPTIONAL, SFIXED32, opt_sfixed32, 49) \
|
||||
X(a, STATIC, OPTIONAL, FLOAT, opt_float, 50) \
|
||||
X(a, STATIC, OPTIONAL, FIXED64, opt_fixed64, 51) \
|
||||
X(a, STATIC, OPTIONAL, SFIXED64, opt_sfixed64, 52) \
|
||||
X(a, STATIC, OPTIONAL, DOUBLE, opt_double, 53) \
|
||||
X(a, STATIC, OPTIONAL, STRING, opt_string, 54) \
|
||||
X(a, STATIC, OPTIONAL, BYTES, opt_bytes, 55) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, opt_submsg, 56) \
|
||||
X(a, STATIC, OPTIONAL, UENUM, opt_enum, 57) \
|
||||
X(a, STATIC, REQUIRED, INT32, end, 99) \
|
||||
X(a, CALLBACK, OPTIONAL, EXTENSION, extensions, 200)
|
||||
#define AllTypes_CALLBACK pb_default_field_callback
|
||||
#define AllTypes_req_submsg_MSGTYPE SubMessage
|
||||
#define AllTypes_rep_submsg_MSGTYPE SubMessage
|
||||
#define AllTypes_opt_submsg_MSGTYPE SubMessage
|
||||
|
||||
extern const pb_msgdesc_t SubMessage_msg;
|
||||
extern pb_byte_t SubMessage_default[];
|
||||
extern const pb_msgdesc_t EmptyMessage_msg;
|
||||
extern pb_byte_t EmptyMessage_default[];
|
||||
extern const pb_msgdesc_t Limits_msg;
|
||||
extern pb_byte_t Limits_default[];
|
||||
extern const pb_msgdesc_t AllTypes_msg;
|
||||
extern pb_byte_t AllTypes_default[];
|
||||
|
||||
/* Defines for backwards compatibility with code written before nanopb-0.4.0 */
|
||||
#define SubMessage_fields &SubMessage_msg
|
||||
#define EmptyMessage_fields &EmptyMessage_msg
|
||||
#define Limits_fields &Limits_msg
|
||||
#define AllTypes_fields &AllTypes_msg
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define SubMessage_size 33
|
||||
#define EmptyMessage_size 0
|
||||
#define Limits_size 100
|
||||
#define AllTypes_size 1320
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
/* @@protoc_insertion_point(eof) */
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,3 @@
|
||||
* max_size:16
|
||||
* max_count:5
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
syntax = "proto2";
|
||||
|
||||
message SubMessage {
|
||||
required string substuff1 = 1 [default = "1"];
|
||||
required int32 substuff2 = 2 [default = 2];
|
||||
optional fixed32 substuff3 = 3 [default = 3];
|
||||
}
|
||||
|
||||
message EmptyMessage {
|
||||
|
||||
}
|
||||
|
||||
enum HugeEnum {
|
||||
Negative = -2147483647; /* protoc doesn't accept -2147483648 here */
|
||||
Positive = 2147483647;
|
||||
}
|
||||
|
||||
message Limits {
|
||||
required int32 int32_min = 1 [default = 2147483647];
|
||||
required int32 int32_max = 2 [default = -2147483647];
|
||||
required uint32 uint32_min = 3 [default = 4294967295];
|
||||
required uint32 uint32_max = 4 [default = 0];
|
||||
required int64 int64_min = 5 [default = 9223372036854775807];
|
||||
required int64 int64_max = 6 [default = -9223372036854775807];
|
||||
required uint64 uint64_min = 7 [default = 18446744073709551615];
|
||||
required uint64 uint64_max = 8 [default = 0];
|
||||
required HugeEnum enum_min = 9 [default = Positive];
|
||||
required HugeEnum enum_max = 10 [default = Negative];
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
|
||||
repeated int32 rep_int32 = 21 [packed = true];
|
||||
repeated int64 rep_int64 = 22 [packed = true];
|
||||
repeated uint32 rep_uint32 = 23 [packed = true];
|
||||
repeated uint64 rep_uint64 = 24 [packed = true];
|
||||
repeated sint32 rep_sint32 = 25 [packed = true];
|
||||
repeated sint64 rep_sint64 = 26 [packed = true];
|
||||
repeated bool rep_bool = 27 [packed = true];
|
||||
|
||||
repeated fixed32 rep_fixed32 = 28 [packed = true];
|
||||
repeated sfixed32 rep_sfixed32= 29 [packed = true];
|
||||
repeated float rep_float = 30 [packed = true];
|
||||
|
||||
repeated fixed64 rep_fixed64 = 31 [packed = true];
|
||||
repeated sfixed64 rep_sfixed64= 32 [packed = true];
|
||||
repeated double rep_double = 33 [packed = true];
|
||||
|
||||
repeated string rep_string = 34;
|
||||
repeated bytes rep_bytes = 35;
|
||||
repeated SubMessage rep_submsg = 36;
|
||||
repeated MyEnum rep_enum = 37 [packed = true];
|
||||
|
||||
optional int32 opt_int32 = 41 [default = 4041];
|
||||
optional int64 opt_int64 = 42 [default = 4042];
|
||||
optional uint32 opt_uint32 = 43 [default = 4043];
|
||||
optional uint64 opt_uint64 = 44 [default = 4044];
|
||||
optional sint32 opt_sint32 = 45 [default = 4045];
|
||||
optional sint64 opt_sint64 = 46 [default = 4046];
|
||||
optional bool opt_bool = 47 [default = false];
|
||||
|
||||
optional fixed32 opt_fixed32 = 48 [default = 4048];
|
||||
optional sfixed32 opt_sfixed32= 49 [default = 4049];
|
||||
optional float opt_float = 50 [default = 4050];
|
||||
|
||||
optional fixed64 opt_fixed64 = 51 [default = 4051];
|
||||
optional sfixed64 opt_sfixed64= 52 [default = 4052];
|
||||
optional double opt_double = 53 [default = 4053];
|
||||
|
||||
optional string opt_string = 54 [default = "4054"];
|
||||
optional bytes opt_bytes = 55 [default = "4055"];
|
||||
optional SubMessage opt_submsg = 56;
|
||||
optional MyEnum opt_enum = 57 [default = Second];
|
||||
|
||||
// Just to make sure that the size of the fields has been calculated
|
||||
// properly, i.e. otherwise a bug in last field might not be detected.
|
||||
required int32 end = 99;
|
||||
|
||||
|
||||
extensions 200 to 255;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,196 @@
|
||||
/* Tests the decoding of all types.
|
||||
* 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. ./encode_legacy | ./decode_legacy
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <pb_decode.h>
|
||||
#include "alltypes_legacy.h"
|
||||
#include "test_helpers.h"
|
||||
#include "unittests.h"
|
||||
|
||||
/* This function is called once from main(), it handles
|
||||
the decoding and checks the fields. */
|
||||
bool check_alltypes(pb_istream_t *stream, int mode)
|
||||
{
|
||||
AllTypes alltypes = {0};
|
||||
int status = 0;
|
||||
|
||||
if (!pb_decode(stream, AllTypes_fields, &alltypes))
|
||||
return false;
|
||||
|
||||
TEST(alltypes.req_int32 == -1001);
|
||||
TEST(alltypes.req_int64 == -1002);
|
||||
TEST(alltypes.req_uint32 == 1003);
|
||||
TEST(alltypes.req_uint64 == 1004);
|
||||
TEST(alltypes.req_sint32 == -1005);
|
||||
TEST(alltypes.req_sint64 == -1006);
|
||||
TEST(alltypes.req_bool == true);
|
||||
|
||||
TEST(alltypes.req_fixed32 == 1008);
|
||||
TEST(alltypes.req_sfixed32 == -1009);
|
||||
TEST(alltypes.req_float == 1010.0f);
|
||||
|
||||
TEST(alltypes.req_fixed64 == 1011);
|
||||
TEST(alltypes.req_sfixed64 == -1012);
|
||||
TEST(alltypes.req_double == 1013.0f);
|
||||
|
||||
TEST(strcmp(alltypes.req_string, "1014") == 0);
|
||||
TEST(alltypes.req_bytes.size == 4);
|
||||
TEST(memcmp(alltypes.req_bytes.bytes, "1015", 4) == 0);
|
||||
TEST(strcmp(alltypes.req_submsg.substuff1, "1016") == 0);
|
||||
TEST(alltypes.req_submsg.substuff2 == 1016);
|
||||
TEST(alltypes.req_submsg.substuff3 == 3);
|
||||
TEST(alltypes.req_enum == MyEnum_Truth);
|
||||
|
||||
TEST(alltypes.rep_int32_count == 5 && alltypes.rep_int32[4] == -2001 && alltypes.rep_int32[0] == 0);
|
||||
TEST(alltypes.rep_int64_count == 5 && alltypes.rep_int64[4] == -2002 && alltypes.rep_int64[0] == 0);
|
||||
TEST(alltypes.rep_uint32_count == 5 && alltypes.rep_uint32[4] == 2003 && alltypes.rep_uint32[0] == 0);
|
||||
TEST(alltypes.rep_uint64_count == 5 && alltypes.rep_uint64[4] == 2004 && alltypes.rep_uint64[0] == 0);
|
||||
TEST(alltypes.rep_sint32_count == 5 && alltypes.rep_sint32[4] == -2005 && alltypes.rep_sint32[0] == 0);
|
||||
TEST(alltypes.rep_sint64_count == 5 && alltypes.rep_sint64[4] == -2006 && alltypes.rep_sint64[0] == 0);
|
||||
TEST(alltypes.rep_bool_count == 5 && alltypes.rep_bool[4] == true && alltypes.rep_bool[0] == false);
|
||||
|
||||
TEST(alltypes.rep_fixed32_count == 5 && alltypes.rep_fixed32[4] == 2008 && alltypes.rep_fixed32[0] == 0);
|
||||
TEST(alltypes.rep_sfixed32_count == 5 && alltypes.rep_sfixed32[4] == -2009 && alltypes.rep_sfixed32[0] == 0);
|
||||
TEST(alltypes.rep_float_count == 5 && alltypes.rep_float[4] == 2010.0f && alltypes.rep_float[0] == 0.0f);
|
||||
|
||||
TEST(alltypes.rep_fixed64_count == 5 && alltypes.rep_fixed64[4] == 2011 && alltypes.rep_fixed64[0] == 0);
|
||||
TEST(alltypes.rep_sfixed64_count == 5 && alltypes.rep_sfixed64[4] == -2012 && alltypes.rep_sfixed64[0] == 0);
|
||||
TEST(alltypes.rep_double_count == 5 && alltypes.rep_double[4] == 2013.0 && alltypes.rep_double[0] == 0.0);
|
||||
|
||||
TEST(alltypes.rep_string_count == 5 && strcmp(alltypes.rep_string[4], "2014") == 0 && alltypes.rep_string[0][0] == '\0');
|
||||
TEST(alltypes.rep_bytes_count == 5 && alltypes.rep_bytes[4].size == 4 && alltypes.rep_bytes[0].size == 0);
|
||||
TEST(memcmp(alltypes.rep_bytes[4].bytes, "2015", 4) == 0);
|
||||
|
||||
TEST(alltypes.rep_submsg_count == 5);
|
||||
TEST(strcmp(alltypes.rep_submsg[4].substuff1, "2016") == 0 && alltypes.rep_submsg[0].substuff1[0] == '\0');
|
||||
TEST(alltypes.rep_submsg[4].substuff2 == 2016 && alltypes.rep_submsg[0].substuff2 == 0);
|
||||
TEST(alltypes.rep_submsg[4].substuff3 == 2016 && alltypes.rep_submsg[0].substuff3 == 3);
|
||||
|
||||
TEST(alltypes.rep_enum_count == 5 && alltypes.rep_enum[4] == MyEnum_Truth && alltypes.rep_enum[0] == MyEnum_Zero);
|
||||
|
||||
if (mode == 0)
|
||||
{
|
||||
/* Expect default values */
|
||||
TEST(alltypes.has_opt_int32 == false);
|
||||
TEST(alltypes.opt_int32 == 4041);
|
||||
TEST(alltypes.has_opt_int64 == false);
|
||||
TEST(alltypes.opt_int64 == 4042);
|
||||
TEST(alltypes.has_opt_uint32 == false);
|
||||
TEST(alltypes.opt_uint32 == 4043);
|
||||
TEST(alltypes.has_opt_uint64 == false);
|
||||
TEST(alltypes.opt_uint64 == 4044);
|
||||
TEST(alltypes.has_opt_sint32 == false);
|
||||
TEST(alltypes.opt_sint32 == 4045);
|
||||
TEST(alltypes.has_opt_sint64 == false);
|
||||
TEST(alltypes.opt_sint64 == 4046);
|
||||
TEST(alltypes.has_opt_bool == false);
|
||||
TEST(alltypes.opt_bool == false);
|
||||
|
||||
TEST(alltypes.has_opt_fixed32 == false);
|
||||
TEST(alltypes.opt_fixed32 == 4048);
|
||||
TEST(alltypes.has_opt_sfixed32 == false);
|
||||
TEST(alltypes.opt_sfixed32 == 4049);
|
||||
TEST(alltypes.has_opt_float == false);
|
||||
TEST(alltypes.opt_float == 4050.0f);
|
||||
|
||||
TEST(alltypes.has_opt_fixed64 == false);
|
||||
TEST(alltypes.opt_fixed64 == 4051);
|
||||
TEST(alltypes.has_opt_sfixed64 == false);
|
||||
TEST(alltypes.opt_sfixed64 == 4052);
|
||||
TEST(alltypes.has_opt_double == false);
|
||||
TEST(alltypes.opt_double == 4053.0);
|
||||
|
||||
TEST(alltypes.has_opt_string == false);
|
||||
TEST(strcmp(alltypes.opt_string, "4054") == 0);
|
||||
TEST(alltypes.has_opt_bytes == false);
|
||||
TEST(alltypes.opt_bytes.size == 4);
|
||||
TEST(memcmp(alltypes.opt_bytes.bytes, "4055", 4) == 0);
|
||||
TEST(alltypes.has_opt_submsg == false);
|
||||
TEST(strcmp(alltypes.opt_submsg.substuff1, "1") == 0);
|
||||
TEST(alltypes.opt_submsg.substuff2 == 2);
|
||||
TEST(alltypes.opt_submsg.substuff3 == 3);
|
||||
TEST(alltypes.has_opt_enum == false);
|
||||
TEST(alltypes.opt_enum == MyEnum_Second);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Expect filled-in values */
|
||||
TEST(alltypes.has_opt_int32 == true);
|
||||
TEST(alltypes.opt_int32 == 3041);
|
||||
TEST(alltypes.has_opt_int64 == true);
|
||||
TEST(alltypes.opt_int64 == 3042);
|
||||
TEST(alltypes.has_opt_uint32 == true);
|
||||
TEST(alltypes.opt_uint32 == 3043);
|
||||
TEST(alltypes.has_opt_uint64 == true);
|
||||
TEST(alltypes.opt_uint64 == 3044);
|
||||
TEST(alltypes.has_opt_sint32 == true);
|
||||
TEST(alltypes.opt_sint32 == 3045);
|
||||
TEST(alltypes.has_opt_sint64 == true);
|
||||
TEST(alltypes.opt_sint64 == 3046);
|
||||
TEST(alltypes.has_opt_bool == true);
|
||||
TEST(alltypes.opt_bool == true);
|
||||
|
||||
TEST(alltypes.has_opt_fixed32 == true);
|
||||
TEST(alltypes.opt_fixed32 == 3048);
|
||||
TEST(alltypes.has_opt_sfixed32 == true);
|
||||
TEST(alltypes.opt_sfixed32 == 3049);
|
||||
TEST(alltypes.has_opt_float == true);
|
||||
TEST(alltypes.opt_float == 3050.0f);
|
||||
|
||||
TEST(alltypes.has_opt_fixed64 == true);
|
||||
TEST(alltypes.opt_fixed64 == 3051);
|
||||
TEST(alltypes.has_opt_sfixed64 == true);
|
||||
TEST(alltypes.opt_sfixed64 == 3052);
|
||||
TEST(alltypes.has_opt_double == true);
|
||||
TEST(alltypes.opt_double == 3053.0);
|
||||
|
||||
TEST(alltypes.has_opt_string == true);
|
||||
TEST(strcmp(alltypes.opt_string, "3054") == 0);
|
||||
TEST(alltypes.has_opt_bytes == true);
|
||||
TEST(alltypes.opt_bytes.size == 4);
|
||||
TEST(memcmp(alltypes.opt_bytes.bytes, "3055", 4) == 0);
|
||||
TEST(alltypes.has_opt_submsg == true);
|
||||
TEST(strcmp(alltypes.opt_submsg.substuff1, "3056") == 0);
|
||||
TEST(alltypes.opt_submsg.substuff2 == 3056);
|
||||
TEST(alltypes.opt_submsg.substuff3 == 3);
|
||||
TEST(alltypes.has_opt_enum == true);
|
||||
TEST(alltypes.opt_enum == MyEnum_Truth);
|
||||
}
|
||||
|
||||
TEST(alltypes.end == 1099);
|
||||
|
||||
return status == 0;
|
||||
}
|
||||
|
||||
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 */
|
||||
SET_BINARY_MODE(stdin);
|
||||
count = fread(buffer, 1, sizeof(buffer), stdin);
|
||||
|
||||
/* Construct a pb_istream_t for reading from the buffer */
|
||||
stream = pb_istream_from_buffer(buffer, count);
|
||||
|
||||
/* Decode and print out the stuff */
|
||||
if (!check_alltypes(&stream, mode))
|
||||
{
|
||||
printf("Parsing failed: %s\n", PB_GET_ERROR(&stream));
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
/* Attempts to test all the datatypes supported by ProtoBuf.
|
||||
* 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 "alltypes_legacy.h"
|
||||
#include "test_helpers.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int mode = (argc > 1) ? atoi(argv[1]) : 0;
|
||||
|
||||
/* Initialize the structure with constants */
|
||||
AllTypes alltypes = {0};
|
||||
|
||||
alltypes.req_int32 = -1001;
|
||||
alltypes.req_int64 = -1002;
|
||||
alltypes.req_uint32 = 1003;
|
||||
alltypes.req_uint64 = 1004;
|
||||
alltypes.req_sint32 = -1005;
|
||||
alltypes.req_sint64 = -1006;
|
||||
alltypes.req_bool = true;
|
||||
|
||||
alltypes.req_fixed32 = 1008;
|
||||
alltypes.req_sfixed32 = -1009;
|
||||
alltypes.req_float = 1010.0f;
|
||||
|
||||
alltypes.req_fixed64 = 1011;
|
||||
alltypes.req_sfixed64 = -1012;
|
||||
alltypes.req_double = 1013.0;
|
||||
|
||||
strcpy(alltypes.req_string, "1014");
|
||||
alltypes.req_bytes.size = 4;
|
||||
memcpy(alltypes.req_bytes.bytes, "1015", 4);
|
||||
strcpy(alltypes.req_submsg.substuff1, "1016");
|
||||
alltypes.req_submsg.substuff2 = 1016;
|
||||
alltypes.req_enum = MyEnum_Truth;
|
||||
|
||||
alltypes.rep_int32_count = 5; alltypes.rep_int32[4] = -2001;
|
||||
alltypes.rep_int64_count = 5; alltypes.rep_int64[4] = -2002;
|
||||
alltypes.rep_uint32_count = 5; alltypes.rep_uint32[4] = 2003;
|
||||
alltypes.rep_uint64_count = 5; alltypes.rep_uint64[4] = 2004;
|
||||
alltypes.rep_sint32_count = 5; alltypes.rep_sint32[4] = -2005;
|
||||
alltypes.rep_sint64_count = 5; alltypes.rep_sint64[4] = -2006;
|
||||
alltypes.rep_bool_count = 5; alltypes.rep_bool[4] = true;
|
||||
|
||||
alltypes.rep_fixed32_count = 5; alltypes.rep_fixed32[4] = 2008;
|
||||
alltypes.rep_sfixed32_count = 5; alltypes.rep_sfixed32[4] = -2009;
|
||||
alltypes.rep_float_count = 5; alltypes.rep_float[4] = 2010.0f;
|
||||
|
||||
alltypes.rep_fixed64_count = 5; alltypes.rep_fixed64[4] = 2011;
|
||||
alltypes.rep_sfixed64_count = 5; alltypes.rep_sfixed64[4] = -2012;
|
||||
alltypes.rep_double_count = 5; alltypes.rep_double[4] = 2013.0;
|
||||
|
||||
alltypes.rep_string_count = 5; strcpy(alltypes.rep_string[4], "2014");
|
||||
alltypes.rep_bytes_count = 5; alltypes.rep_bytes[4].size = 4;
|
||||
memcpy(alltypes.rep_bytes[4].bytes, "2015", 4);
|
||||
|
||||
alltypes.rep_submsg_count = 5;
|
||||
strcpy(alltypes.rep_submsg[4].substuff1, "2016");
|
||||
alltypes.rep_submsg[4].substuff2 = 2016;
|
||||
alltypes.rep_submsg[4].has_substuff3 = true;
|
||||
alltypes.rep_submsg[4].substuff3 = 2016;
|
||||
|
||||
alltypes.rep_enum_count = 5; alltypes.rep_enum[4] = MyEnum_Truth;
|
||||
|
||||
if (mode != 0)
|
||||
{
|
||||
/* Fill in values for optional fields */
|
||||
alltypes.has_opt_int32 = true;
|
||||
alltypes.opt_int32 = 3041;
|
||||
alltypes.has_opt_int64 = true;
|
||||
alltypes.opt_int64 = 3042;
|
||||
alltypes.has_opt_uint32 = true;
|
||||
alltypes.opt_uint32 = 3043;
|
||||
alltypes.has_opt_uint64 = true;
|
||||
alltypes.opt_uint64 = 3044;
|
||||
alltypes.has_opt_sint32 = true;
|
||||
alltypes.opt_sint32 = 3045;
|
||||
alltypes.has_opt_sint64 = true;
|
||||
alltypes.opt_sint64 = 3046;
|
||||
alltypes.has_opt_bool = true;
|
||||
alltypes.opt_bool = true;
|
||||
|
||||
alltypes.has_opt_fixed32 = true;
|
||||
alltypes.opt_fixed32 = 3048;
|
||||
alltypes.has_opt_sfixed32 = true;
|
||||
alltypes.opt_sfixed32 = 3049;
|
||||
alltypes.has_opt_float = true;
|
||||
alltypes.opt_float = 3050.0f;
|
||||
|
||||
alltypes.has_opt_fixed64 = true;
|
||||
alltypes.opt_fixed64 = 3051;
|
||||
alltypes.has_opt_sfixed64 = true;
|
||||
alltypes.opt_sfixed64 = 3052;
|
||||
alltypes.has_opt_double = true;
|
||||
alltypes.opt_double = 3053.0;
|
||||
|
||||
alltypes.has_opt_string = true;
|
||||
strcpy(alltypes.opt_string, "3054");
|
||||
alltypes.has_opt_bytes = true;
|
||||
alltypes.opt_bytes.size = 4;
|
||||
memcpy(alltypes.opt_bytes.bytes, "3055", 4);
|
||||
alltypes.has_opt_submsg = true;
|
||||
strcpy(alltypes.opt_submsg.substuff1, "3056");
|
||||
alltypes.opt_submsg.substuff2 = 3056;
|
||||
alltypes.has_opt_enum = true;
|
||||
alltypes.opt_enum = MyEnum_Truth;
|
||||
}
|
||||
|
||||
alltypes.end = 1099;
|
||||
|
||||
{
|
||||
uint8_t buffer[1024];
|
||||
pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer));
|
||||
|
||||
/* Now encode it and check if we succeeded. */
|
||||
if (pb_encode(&stream, AllTypes_fields, &alltypes))
|
||||
{
|
||||
SET_BINARY_MODE(stdout);
|
||||
fwrite(buffer, 1, stream.bytes_written, stdout);
|
||||
return 0; /* Success */
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Encoding failed!\n");
|
||||
return 1; /* Failure */
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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", "$COMMON/pb_common.o"])
|
||||
dec = env.Program(["decode_buffer.c", "$COMMON/person.pb.c", "$COMMON/pb_decode.o", "$COMMON/pb_common.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"])
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
/* A very simple decoding test case, using person.proto.
|
||||
* Produces output compatible with protoc --decode.
|
||||
* Reads the encoded data from stdin and prints the values
|
||||
* to stdout as text.
|
||||
*
|
||||
* Run e.g. ./test_encode1 | ./test_decode1
|
||||
*/
|
||||
|
||||
#include <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. */
|
||||
bool print_person(pb_istream_t *stream)
|
||||
{
|
||||
int i;
|
||||
Person person = Person_init_zero;
|
||||
|
||||
if (!pb_decode(stream, Person_fields, &person))
|
||||
return false;
|
||||
|
||||
/* Now the decoding is done, rest is just to print stuff out. */
|
||||
|
||||
printf("name: \"%s\"\n", person.name);
|
||||
printf("id: %ld\n", (long)person.id);
|
||||
|
||||
if (person.has_email)
|
||||
printf("email: \"%s\"\n", person.email);
|
||||
|
||||
for (i = 0; i < person.phone_count; i++)
|
||||
{
|
||||
Person_PhoneNumber *phone = &person.phone[i];
|
||||
printf("phone {\n");
|
||||
printf(" number: \"%s\"\n", phone->number);
|
||||
|
||||
if (phone->has_type)
|
||||
{
|
||||
switch (phone->type)
|
||||
{
|
||||
case Person_PhoneType_WORK:
|
||||
printf(" type: WORK\n");
|
||||
break;
|
||||
|
||||
case Person_PhoneType_HOME:
|
||||
printf(" type: HOME\n");
|
||||
break;
|
||||
|
||||
case Person_PhoneType_MOBILE:
|
||||
printf(" type: MOBILE\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
printf("}\n");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
uint8_t buffer[Person_size];
|
||||
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))
|
||||
{
|
||||
printf("Message does not fit in buffer\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Construct a pb_istream_t for reading from the buffer */
|
||||
stream = pb_istream_from_buffer(buffer, count);
|
||||
|
||||
/* Decode and print out the stuff */
|
||||
if (!print_person(&stream))
|
||||
{
|
||||
printf("Parsing failed: %s\n", PB_GET_ERROR(&stream));
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/* A very simple encoding test case using person.proto.
|
||||
* Just puts constant data in the fields and encodes into
|
||||
* buffer, which is then written to stdout.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <pb_encode.h>
|
||||
#include "person.pb.h"
|
||||
#include "test_helpers.h"
|
||||
|
||||
int main()
|
||||
{
|
||||
uint8_t buffer[Person_size];
|
||||
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},
|
||||
{"99-2342", false, 0},
|
||||
{"1234-5678", true, Person_PhoneType_WORK},
|
||||
}};
|
||||
|
||||
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 */
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Encoding failed: %s\n", PB_GET_ERROR(&stream));
|
||||
return 1; /* Failure */
|
||||
}
|
||||
}
|
||||
@@ -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", "$COMMON/pb_common.o"])
|
||||
dec = env.Program(["decode_stream.c", "$COMMON/person.pb.c", "$COMMON/pb_decode.o", "$COMMON/pb_common.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"])
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
/* Same as test_decode1 but reads from stdin directly.
|
||||
*/
|
||||
|
||||
#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.
|
||||
Ugly copy-paste from test_decode1.c. */
|
||||
bool print_person(pb_istream_t *stream)
|
||||
{
|
||||
int i;
|
||||
Person person = Person_init_zero;
|
||||
|
||||
if (!pb_decode(stream, Person_fields, &person))
|
||||
return false;
|
||||
|
||||
/* Now the decoding is done, rest is just to print stuff out. */
|
||||
|
||||
printf("name: \"%s\"\n", person.name);
|
||||
printf("id: %ld\n", (long)person.id);
|
||||
|
||||
if (person.has_email)
|
||||
printf("email: \"%s\"\n", person.email);
|
||||
|
||||
for (i = 0; i < person.phone_count; i++)
|
||||
{
|
||||
Person_PhoneNumber *phone = &person.phone[i];
|
||||
printf("phone {\n");
|
||||
printf(" number: \"%s\"\n", phone->number);
|
||||
|
||||
if (phone->has_type)
|
||||
{
|
||||
switch (phone->type)
|
||||
{
|
||||
case Person_PhoneType_WORK:
|
||||
printf(" type: WORK\n");
|
||||
break;
|
||||
|
||||
case Person_PhoneType_HOME:
|
||||
printf(" type: HOME\n");
|
||||
break;
|
||||
|
||||
case Person_PhoneType_MOBILE:
|
||||
printf(" type: MOBILE\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
printf("}\n");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* This binds the pb_istream_t to stdin */
|
||||
bool callback(pb_istream_t *stream, uint8_t *buf, size_t count)
|
||||
{
|
||||
FILE *file = (FILE*)stream->state;
|
||||
size_t len = fread(buf, 1, count, file);
|
||||
|
||||
if (len == count)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
stream->bytes_left = 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
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));
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/* Same as test_encode1.c, except writes directly to stdout.
|
||||
*/
|
||||
|
||||
#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)
|
||||
{
|
||||
FILE *file = (FILE*) stream->state;
|
||||
return fwrite(buf, 1, count, file) == count;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
/* Initialize the structure with constants */
|
||||
Person person = {"Test Person 99", 99, true, "test@person.com",
|
||||
3, {{"555-12345678", true, Person_PhoneType_MOBILE},
|
||||
{"99-2342", false, 0},
|
||||
{"1234-5678", true, Person_PhoneType_WORK},
|
||||
}};
|
||||
|
||||
/* Prepare the stream, output goes directly to stdout */
|
||||
pb_ostream_t stream = {&streamcallback, 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))
|
||||
{
|
||||
return 0; /* Success */
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Encoding failed: %s\n", PB_GET_ERROR(&stream));
|
||||
return 1; /* Failure */
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
# 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("alltypes.pb.h", "$BUILD/alltypes/alltypes.pb.h", c)
|
||||
env.Command("alltypes.pb.c", "$BUILD/alltypes/alltypes.pb.c", c)
|
||||
env.Command("encode_alltypes.c", "$BUILD/alltypes/encode_alltypes.c", c)
|
||||
env.Command("decode_alltypes.c", "$BUILD/alltypes/decode_alltypes.c", c)
|
||||
|
||||
# Define the compilation options
|
||||
opts = env.Clone()
|
||||
opts.Append(CPPDEFINES = {'PB_BUFFER_ONLY': 1})
|
||||
|
||||
# Build new version of core
|
||||
strict = opts.Clone()
|
||||
strict.Append(CFLAGS = strict['CORECFLAGS'])
|
||||
strict.Object("pb_decode_bufonly.o", "$NANOPB/pb_decode.c")
|
||||
strict.Object("pb_encode_bufonly.o", "$NANOPB/pb_encode.c")
|
||||
strict.Object("pb_common_bufonly.o", "$NANOPB/pb_common.c")
|
||||
|
||||
# Now build and run the test normally.
|
||||
enc = opts.Program(["encode_alltypes.c", "alltypes.pb.c", "pb_encode_bufonly.o", "pb_common_bufonly.o"])
|
||||
dec = opts.Program(["decode_alltypes.c", "alltypes.pb.c", "pb_decode_bufonly.o", "pb_common_bufonly.o"])
|
||||
|
||||
env.RunTest(enc)
|
||||
env.RunTest([dec, "encode_alltypes.output"])
|
||||
@@ -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", "$COMMON/pb_common.o"])
|
||||
dec = env.Program(["decode_callbacks.c", "callbacks.pb.c", "$COMMON/pb_decode.o", "$COMMON/pb_common.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"])
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
syntax = "proto2";
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
/* Decoding testcase for callback fields.
|
||||
* Run e.g. ./test_encode_callbacks | ./test_decode_callbacks
|
||||
*/
|
||||
|
||||
#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)
|
||||
{
|
||||
uint8_t buffer[1024] = {0};
|
||||
|
||||
/* We could read block-by-block to avoid the large buffer... */
|
||||
if (stream->bytes_left > sizeof(buffer) - 1)
|
||||
return false;
|
||||
|
||||
if (!pb_read(stream, buffer, stream->bytes_left))
|
||||
return false;
|
||||
|
||||
/* Print the string, in format comparable with protoc --decode.
|
||||
* Format comes from the arg defined in main().
|
||||
*/
|
||||
printf((char*)*arg, buffer);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool print_int32(pb_istream_t *stream, const pb_field_t *field, void **arg)
|
||||
{
|
||||
uint64_t value;
|
||||
if (!pb_decode_varint(stream, &value))
|
||||
return false;
|
||||
|
||||
printf((char*)*arg, (long)value);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool print_fixed32(pb_istream_t *stream, const pb_field_t *field, void **arg)
|
||||
{
|
||||
uint32_t value;
|
||||
if (!pb_decode_fixed32(stream, &value))
|
||||
return false;
|
||||
|
||||
printf((char*)*arg, (long)value);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool print_fixed64(pb_istream_t *stream, const pb_field_t *field, void **arg)
|
||||
{
|
||||
uint64_t value;
|
||||
if (!pb_decode_fixed64(stream, &value))
|
||||
return false;
|
||||
|
||||
printf((char*)*arg, (long)value);
|
||||
return true;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
uint8_t buffer[1024];
|
||||
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 = {{{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";
|
||||
testmessage.submsg.int32value.funcs.decode = &print_int32;
|
||||
testmessage.submsg.int32value.arg = " int32value: %ld\n";
|
||||
testmessage.submsg.fixed32value.funcs.decode = &print_fixed32;
|
||||
testmessage.submsg.fixed32value.arg = " fixed32value: %ld\n";
|
||||
testmessage.submsg.fixed64value.funcs.decode = &print_fixed64;
|
||||
testmessage.submsg.fixed64value.arg = " fixed64value: %ld\n}\n";
|
||||
|
||||
testmessage.stringvalue.funcs.decode = &print_string;
|
||||
testmessage.stringvalue.arg = "stringvalue: \"%s\"\n";
|
||||
testmessage.int32value.funcs.decode = &print_int32;
|
||||
testmessage.int32value.arg = "int32value: %ld\n";
|
||||
testmessage.fixed32value.funcs.decode = &print_fixed32;
|
||||
testmessage.fixed32value.arg = "fixed32value: %ld\n";
|
||||
testmessage.fixed64value.funcs.decode = &print_fixed64;
|
||||
testmessage.fixed64value.arg = "fixed64value: %ld\n";
|
||||
testmessage.repeatedstring.funcs.decode = &print_string;
|
||||
testmessage.repeatedstring.arg = "repeatedstring: \"%s\"\n";
|
||||
|
||||
if (!pb_decode(&stream, TestMessage_fields, &testmessage))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
/* Encoding testcase for callback fields */
|
||||
|
||||
#include <stdio.h>
|
||||
#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)
|
||||
{
|
||||
char *str = "Hello world!";
|
||||
|
||||
if (!pb_encode_tag_for_field(stream, field))
|
||||
return false;
|
||||
|
||||
return pb_encode_string(stream, (uint8_t*)str, strlen(str));
|
||||
}
|
||||
|
||||
bool encode_int32(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
|
||||
{
|
||||
if (!pb_encode_tag_for_field(stream, field))
|
||||
return false;
|
||||
|
||||
return pb_encode_varint(stream, 42);
|
||||
}
|
||||
|
||||
bool encode_fixed32(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
|
||||
{
|
||||
uint32_t value = 42;
|
||||
|
||||
if (!pb_encode_tag_for_field(stream, field))
|
||||
return false;
|
||||
|
||||
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;
|
||||
|
||||
return pb_encode_fixed64(stream, &value);
|
||||
}
|
||||
|
||||
bool encode_repeatedstring(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
|
||||
{
|
||||
char *str[4] = {"Hello world!", "", "Test", "Test2"};
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
if (!pb_encode_tag_for_field(stream, field))
|
||||
return false;
|
||||
|
||||
if (!pb_encode_string(stream, (uint8_t*)str[i], strlen(str[i])))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
uint8_t buffer[1024];
|
||||
pb_ostream_t stream;
|
||||
TestMessage testmessage = {{{NULL}}};
|
||||
|
||||
stream = pb_ostream_from_buffer(buffer, 1024);
|
||||
|
||||
testmessage.stringvalue.funcs.encode = &encode_string;
|
||||
testmessage.int32value.funcs.encode = &encode_int32;
|
||||
testmessage.fixed32value.funcs.encode = &encode_fixed32;
|
||||
testmessage.fixed64value.funcs.encode = &encode_fixed64;
|
||||
|
||||
testmessage.has_submsg = true;
|
||||
testmessage.submsg.stringvalue.funcs.encode = &encode_string;
|
||||
testmessage.submsg.int32value.funcs.encode = &encode_int32;
|
||||
testmessage.submsg.fixed32value.funcs.encode = &encode_fixed32;
|
||||
testmessage.submsg.fixed64value.funcs.encode = &encode_fixed64;
|
||||
|
||||
testmessage.repeatedstring.funcs.encode = &encode_repeatedstring;
|
||||
|
||||
if (!pb_encode(&stream, TestMessage_fields, &testmessage))
|
||||
return 1;
|
||||
|
||||
SET_BINARY_MODE(stdout);
|
||||
if (fwrite(buffer, stream.bytes_written, 1, stdout) != 1)
|
||||
return 2;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
# Test comment inclusion from .proto to .pb.h
|
||||
|
||||
Import("env")
|
||||
|
||||
env.NanopbProto("comments")
|
||||
env.Object("comments.pb.c")
|
||||
env.Match(['comments.pb.h', 'comments.expected'])
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
Enum1Comment
|
||||
LeadingEnumComment
|
||||
ENUMVAL2.*TrailingEnumComment
|
||||
Message1Comment
|
||||
member2.*TrailingMemberComment
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
syntax = "proto2";
|
||||
|
||||
// Message1Comment
|
||||
message Message1
|
||||
{
|
||||
// LeadingMemberComment
|
||||
required int32 member1 = 1;
|
||||
required int32 member2 = 2; // TrailingMemberComment
|
||||
}
|
||||
|
||||
// Enum1Comment
|
||||
enum Enum1
|
||||
{
|
||||
// LeadingEnumComment
|
||||
ENUMVAL1 = 1;
|
||||
ENUMVAL2 = 2; // TrailingEnumComment
|
||||
}
|
||||
48
components/spotify/cspot/bell/nanopb/tests/common/SConscript
Normal file
48
components/spotify/cspot/bell/nanopb/tests/common/SConscript
Normal file
@@ -0,0 +1,48 @@
|
||||
# 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", "$NANOPB/pb_decode.c")
|
||||
strict.Object("pb_encode.o", "$NANOPB/pb_encode.c")
|
||||
strict.Object("pb_common.o", "$NANOPB/pb_common.c")
|
||||
|
||||
#-----------------------------------------------
|
||||
# Binaries of pb_decode etc. with malloc support
|
||||
# Uses malloc_wrappers.c to count allocations.
|
||||
malloc_env = env.Clone()
|
||||
malloc_env.Append(CPPDEFINES = {'PB_ENABLE_MALLOC': 1,
|
||||
'PB_SYSTEM_HEADER': '\\"malloc_wrappers_syshdr.h\\"'})
|
||||
malloc_env.Append(CPPPATH = ["$COMMON"])
|
||||
|
||||
if 'SYSHDR' in malloc_env:
|
||||
malloc_env.Append(CPPDEFINES = {'PB_OLD_SYSHDR': malloc_env['SYSHDR']})
|
||||
|
||||
# Disable libmudflap, because it will confuse valgrind
|
||||
# and other memory leak detection tools.
|
||||
if '-fmudflap' in env["CCFLAGS"]:
|
||||
malloc_env["CCFLAGS"].remove("-fmudflap")
|
||||
malloc_env["LINKFLAGS"].remove("-fmudflap")
|
||||
malloc_env["LIBS"].remove("mudflap")
|
||||
|
||||
malloc_strict = malloc_env.Clone()
|
||||
malloc_strict.Append(CFLAGS = malloc_strict['CORECFLAGS'])
|
||||
malloc_strict.Object("pb_decode_with_malloc.o", "$NANOPB/pb_decode.c")
|
||||
malloc_strict.Object("pb_encode_with_malloc.o", "$NANOPB/pb_encode.c")
|
||||
malloc_strict.Object("pb_common_with_malloc.o", "$NANOPB/pb_common.c")
|
||||
|
||||
malloc_env.Object("malloc_wrappers.o", "malloc_wrappers.c")
|
||||
malloc_env.Depends("$NANOPB/pb.h", ["malloc_wrappers_syshdr.h", "malloc_wrappers.h"])
|
||||
|
||||
Export("malloc_env")
|
||||
|
||||
@@ -0,0 +1,189 @@
|
||||
/* The wrapper functions in this file work like regular malloc() and free(),
|
||||
* but store check values before and after the allocation. This helps to catch
|
||||
* any buffer overrun errors in the test cases.
|
||||
*/
|
||||
|
||||
#include "malloc_wrappers.h"
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#define GUARD_SIZE (sizeof(size_t)*3)
|
||||
#define PREFIX_SIZE (sizeof(size_t)*2)
|
||||
#define CHECK1 ((size_t)0xDEADBEEF)
|
||||
#define CHECK2 ((size_t)0x600DCAFE)
|
||||
|
||||
#ifndef MAX_ALLOC_BYTES
|
||||
#define MAX_ALLOC_BYTES 16*1024*1024
|
||||
#endif
|
||||
|
||||
#ifndef DEBUG_MALLOC
|
||||
#define DEBUG_MALLOC 0
|
||||
#endif
|
||||
|
||||
static size_t g_alloc_count = 0;
|
||||
static size_t g_alloc_bytes = 0;
|
||||
static size_t g_max_alloc_bytes = MAX_ALLOC_BYTES;
|
||||
|
||||
#ifdef LLVMFUZZER
|
||||
/* LLVM libsanitizer has a realloc() implementation that always copies
|
||||
* the whole memory block, even if there would be space to expand it in
|
||||
* place. This gets pretty slow when fuzzing, so this wrapper limits the
|
||||
* realloc() calls by rounding allocation size upwards. Real world
|
||||
* realloc() implementations are hopefully smarter. */
|
||||
static size_t round_blocksize(size_t size)
|
||||
{
|
||||
if (size < 256)
|
||||
{
|
||||
return size;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (size + 1023) / 1024 * 1024;
|
||||
}
|
||||
}
|
||||
#else
|
||||
static size_t round_blocksize(size_t size)
|
||||
{
|
||||
return size;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Allocate memory and place check values before and after. */
|
||||
void* malloc_with_check(size_t size)
|
||||
{
|
||||
char *buf = NULL;
|
||||
|
||||
if (size <= g_max_alloc_bytes - g_alloc_bytes)
|
||||
{
|
||||
buf = malloc(round_blocksize(size + GUARD_SIZE));
|
||||
}
|
||||
|
||||
if (buf)
|
||||
{
|
||||
((size_t*)buf)[0] = size;
|
||||
((size_t*)buf)[1] = CHECK1;
|
||||
((size_t*)(buf + size))[2] = CHECK2;
|
||||
g_alloc_count++;
|
||||
g_alloc_bytes += size;
|
||||
if (DEBUG_MALLOC) fprintf(stderr, "Alloc 0x%04x/%u\n", (unsigned)(uintptr_t)(buf + PREFIX_SIZE), (unsigned)size);
|
||||
return buf + PREFIX_SIZE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (DEBUG_MALLOC) fprintf(stderr, "malloc(%u) failed\n", (unsigned)size);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Free memory allocated with malloc_with_check() and do the checks. */
|
||||
void free_with_check(void *mem)
|
||||
{
|
||||
if (mem)
|
||||
{
|
||||
char *buf = (char*)mem - PREFIX_SIZE;
|
||||
size_t size = ((size_t*)buf)[0];
|
||||
if (DEBUG_MALLOC) fprintf(stderr, "Release 0x%04x/%u\n", (unsigned)(uintptr_t)mem, (unsigned)size);
|
||||
assert(((size_t*)buf)[1] == CHECK1);
|
||||
assert(((size_t*)(buf + size))[2] == CHECK2);
|
||||
assert(g_alloc_count > 0);
|
||||
assert(g_alloc_bytes >= size);
|
||||
((size_t*)buf)[1] = 0;
|
||||
((size_t*)(buf + size))[2] = 0;
|
||||
g_alloc_count--;
|
||||
g_alloc_bytes -= size;
|
||||
free(buf);
|
||||
}
|
||||
}
|
||||
|
||||
/* Reallocate block and check / write guard values */
|
||||
void* realloc_with_check(void *ptr, size_t size)
|
||||
{
|
||||
if (!ptr && size)
|
||||
{
|
||||
/* Allocate new block and write guard values */
|
||||
return malloc_with_check(size);
|
||||
}
|
||||
else if (ptr && size)
|
||||
{
|
||||
/* Change block size */
|
||||
char *buf = (char*)ptr - PREFIX_SIZE;
|
||||
size_t oldsize = ((size_t*)buf)[0];
|
||||
assert(((size_t*)buf)[1] == CHECK1);
|
||||
assert(((size_t*)(buf + oldsize))[2] == CHECK2);
|
||||
assert(g_alloc_count > 0);
|
||||
assert(g_alloc_bytes >= oldsize);
|
||||
|
||||
if (size <= g_max_alloc_bytes - (g_alloc_bytes - oldsize))
|
||||
{
|
||||
size_t new_rounded = round_blocksize(size + GUARD_SIZE);
|
||||
size_t old_rounded = round_blocksize(oldsize + GUARD_SIZE);
|
||||
|
||||
if (new_rounded != old_rounded)
|
||||
{
|
||||
buf = realloc(buf, new_rounded);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
buf = NULL;
|
||||
}
|
||||
|
||||
if (!buf)
|
||||
{
|
||||
if (DEBUG_MALLOC) fprintf(stderr, "Realloc 0x%04x/%u to %u failed\n", (unsigned)(uintptr_t)ptr, (unsigned)oldsize, (unsigned)size);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
((size_t*)buf)[0] = size;
|
||||
((size_t*)buf)[1] = CHECK1;
|
||||
((size_t*)(buf + size))[2] = CHECK2;
|
||||
g_alloc_bytes -= oldsize;
|
||||
g_alloc_bytes += size;
|
||||
|
||||
if (DEBUG_MALLOC) fprintf(stderr, "Realloc 0x%04x/%u to 0x%04x/%u\n", (unsigned)(uintptr_t)ptr, (unsigned)oldsize, (unsigned)(uintptr_t)(buf + PREFIX_SIZE), (unsigned)size);
|
||||
return buf + PREFIX_SIZE;
|
||||
}
|
||||
else if (ptr && !size)
|
||||
{
|
||||
/* Deallocate */
|
||||
free_with_check(ptr);
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No action */
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return total number of allocations not yet released */
|
||||
size_t get_alloc_count()
|
||||
{
|
||||
return g_alloc_count;
|
||||
}
|
||||
|
||||
/* Return allocated size for a pointer returned from malloc(). */
|
||||
size_t get_allocation_size(const void *mem)
|
||||
{
|
||||
char *buf = (char*)mem - PREFIX_SIZE;
|
||||
return ((size_t*)buf)[0];
|
||||
}
|
||||
|
||||
/* Get total number of allocated bytes */
|
||||
size_t get_alloc_bytes()
|
||||
{
|
||||
return g_alloc_bytes;
|
||||
}
|
||||
|
||||
/* Set limit for allocation size */
|
||||
void set_max_alloc_bytes(size_t max_bytes)
|
||||
{
|
||||
g_max_alloc_bytes = max_bytes;
|
||||
}
|
||||
|
||||
size_t get_max_alloc_bytes()
|
||||
{
|
||||
return g_max_alloc_bytes;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
void* malloc_with_check(size_t size);
|
||||
void free_with_check(void *mem);
|
||||
void* realloc_with_check(void *ptr, size_t size);
|
||||
size_t get_alloc_count();
|
||||
size_t get_allocation_size(const void *mem);
|
||||
size_t get_alloc_bytes();
|
||||
void set_max_alloc_bytes(size_t max_bytes);
|
||||
size_t get_max_alloc_bytes();
|
||||
@@ -0,0 +1,15 @@
|
||||
/* This is just a wrapper in order to get our own malloc wrappers into nanopb core. */
|
||||
|
||||
#define pb_realloc(ptr,size) realloc_with_check(ptr,size)
|
||||
#define pb_free(ptr) free_with_check(ptr)
|
||||
|
||||
#ifdef PB_OLD_SYSHDR
|
||||
#include PB_OLD_SYSHDR
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#include <malloc_wrappers.h>
|
||||
@@ -0,0 +1,22 @@
|
||||
syntax = "proto2";
|
||||
|
||||
import "nanopb.proto";
|
||||
|
||||
message Person {
|
||||
required string name = 1 [(nanopb).max_size = 40];
|
||||
required int32 id = 2;
|
||||
optional string email = 3 [(nanopb).max_size = 40];
|
||||
|
||||
enum PhoneType {
|
||||
MOBILE = 0;
|
||||
HOME = 1;
|
||||
WORK = 2;
|
||||
}
|
||||
|
||||
message PhoneNumber {
|
||||
required string number = 1 [(nanopb).max_size = 40];
|
||||
optional PhoneType type = 2 [default = HOME];
|
||||
}
|
||||
|
||||
repeated PhoneNumber phone = 4 [(nanopb).max_count = 5];
|
||||
}
|
||||
@@ -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
|
||||
@@ -0,0 +1,43 @@
|
||||
syntax = "proto2";
|
||||
|
||||
import 'nanopb.proto';
|
||||
|
||||
message IntegerArray {
|
||||
repeated int32 data = 1 [(nanopb).max_count = 10];
|
||||
}
|
||||
|
||||
message FloatArray {
|
||||
repeated float data = 1 [(nanopb).max_count = 10];
|
||||
}
|
||||
|
||||
message StringMessage {
|
||||
required string data = 1 [(nanopb).max_length = 10];
|
||||
}
|
||||
|
||||
message BytesMessage {
|
||||
required bytes data = 1 [(nanopb).max_size = 16];
|
||||
}
|
||||
|
||||
message CallbackArray {
|
||||
// We cheat a bit and use this message for testing other types, too.
|
||||
// Nanopb does not care about the actual defined data type for callback
|
||||
// fields.
|
||||
repeated int32 data = 1;
|
||||
}
|
||||
|
||||
message IntegerContainer {
|
||||
required IntegerArray submsg = 1;
|
||||
}
|
||||
|
||||
message CallbackContainer {
|
||||
required CallbackArray submsg = 1;
|
||||
}
|
||||
|
||||
message CallbackContainerContainer {
|
||||
required CallbackContainer submsg = 1;
|
||||
}
|
||||
|
||||
message StringPointerContainer {
|
||||
repeated string rep_str = 1 [(nanopb).type = FT_POINTER];
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef UNITTESTS_SHORT_MSGS
|
||||
/* Short debug messages for platforms with limited memory */
|
||||
#define COMMENT(x) printf("\n----" x "----\n");
|
||||
#define TEST(x) \
|
||||
if (!(x)) { \
|
||||
fprintf(stderr, "FAIL: Line %d\n", __LINE__); \
|
||||
status = 1; \
|
||||
} else { \
|
||||
printf("OK: Line %d\n", __LINE__); \
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* Elaborate debug messages for normal development */
|
||||
#define COMMENT(x) printf("\n----" x "----\n");
|
||||
#define TEST(x) \
|
||||
if (!(x)) { \
|
||||
fprintf(stderr, "\033[31;1mFAILED:\033[22;39m %s:%d %s\n", __FILE__, __LINE__, #x); \
|
||||
status = 1; \
|
||||
} else { \
|
||||
printf("\033[32;1mOK:\033[22;39m %s\n", #x); \
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
# Test functions in pb_common.c
|
||||
|
||||
Import('env')
|
||||
p = env.Program(["common_unittests.c", "$BUILD/alltypes/alltypes.pb.c"])
|
||||
env.RunTest(p)
|
||||
@@ -0,0 +1,149 @@
|
||||
#define PB_VALIDATE_UTF8
|
||||
#include "pb_common.c"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "unittests.h"
|
||||
#include "../alltypes/alltypes.pb.h"
|
||||
|
||||
int main()
|
||||
{
|
||||
int status = 0;
|
||||
|
||||
{
|
||||
AllTypes msg;
|
||||
pb_field_iter_t iter;
|
||||
|
||||
COMMENT("Test field iterator logic on AllTypes");
|
||||
|
||||
TEST(pb_field_iter_begin(&iter, AllTypes_fields, &msg))
|
||||
|
||||
TEST(iter.tag == 1 && iter.pData == &msg.req_int32 && !iter.pSize)
|
||||
TEST(pb_field_iter_next(&iter) && iter.tag == 2 && iter.pData == &msg.req_int64 && !iter.pSize)
|
||||
TEST(pb_field_iter_next(&iter) && iter.tag == 3 && iter.pData == &msg.req_uint32 && !iter.pSize)
|
||||
TEST(pb_field_iter_next(&iter) && iter.tag == 4 && iter.pData == &msg.req_uint64 && !iter.pSize)
|
||||
TEST(pb_field_iter_next(&iter) && iter.tag == 5 && iter.pData == &msg.req_sint32 && !iter.pSize)
|
||||
TEST(pb_field_iter_next(&iter) && iter.tag == 6 && iter.pData == &msg.req_sint64 && !iter.pSize)
|
||||
TEST(pb_field_iter_next(&iter) && iter.tag == 7 && iter.pData == &msg.req_bool && !iter.pSize)
|
||||
TEST(pb_field_iter_next(&iter) && iter.tag == 8 && iter.pData == &msg.req_fixed32 && !iter.pSize)
|
||||
TEST(pb_field_iter_next(&iter) && iter.tag == 9 && iter.pData == &msg.req_sfixed32 && !iter.pSize)
|
||||
TEST(pb_field_iter_next(&iter) && iter.tag == 10 && iter.pData == &msg.req_float && !iter.pSize)
|
||||
TEST(pb_field_iter_next(&iter) && iter.tag == 11 && iter.pData == &msg.req_fixed64 && !iter.pSize)
|
||||
TEST(pb_field_iter_next(&iter) && iter.tag == 12 && iter.pData == &msg.req_sfixed64 && !iter.pSize)
|
||||
TEST(pb_field_iter_next(&iter) && iter.tag == 13 && iter.pData == &msg.req_double && !iter.pSize)
|
||||
TEST(pb_field_iter_next(&iter) && iter.tag == 14 && iter.pData == &msg.req_string && !iter.pSize)
|
||||
TEST(pb_field_iter_next(&iter) && iter.tag == 15 && iter.pData == &msg.req_bytes && !iter.pSize)
|
||||
TEST(pb_field_iter_next(&iter) && iter.tag == 16 && iter.pData == &msg.req_submsg && !iter.pSize
|
||||
&& iter.submsg_desc == SubMessage_fields)
|
||||
TEST(pb_field_iter_next(&iter) && iter.tag == 17 && iter.pData == &msg.req_enum && !iter.pSize)
|
||||
TEST(pb_field_iter_next(&iter) && iter.tag == 18 && iter.pData == &msg.req_emptymsg && !iter.pSize)
|
||||
TEST(pb_field_iter_next(&iter) && iter.tag == 19 && iter.pData == &msg.req_fbytes && !iter.pSize)
|
||||
TEST(iter.required_field_index == 18)
|
||||
TEST(iter.submessage_index == 2)
|
||||
|
||||
TEST(pb_field_iter_next(&iter) && iter.tag == 21 && iter.pData == &msg.rep_int32 && iter.pSize == &msg.rep_int32_count)
|
||||
TEST(pb_field_iter_next(&iter) && iter.tag == 22 && iter.pData == &msg.rep_int64 && iter.pSize == &msg.rep_int64_count)
|
||||
TEST(pb_field_iter_next(&iter) && iter.tag == 23 && iter.pData == &msg.rep_uint32 && iter.pSize == &msg.rep_uint32_count)
|
||||
TEST(pb_field_iter_next(&iter) && iter.tag == 24 && iter.pData == &msg.rep_uint64 && iter.pSize == &msg.rep_uint64_count)
|
||||
TEST(pb_field_iter_next(&iter) && iter.tag == 25 && iter.pData == &msg.rep_sint32 && iter.pSize == &msg.rep_sint32_count)
|
||||
TEST(pb_field_iter_next(&iter) && iter.tag == 26 && iter.pData == &msg.rep_sint64 && iter.pSize == &msg.rep_sint64_count)
|
||||
TEST(pb_field_iter_next(&iter) && iter.tag == 27 && iter.pData == &msg.rep_bool && iter.pSize == &msg.rep_bool_count)
|
||||
TEST(pb_field_iter_next(&iter) && iter.tag == 28 && iter.pData == &msg.rep_fixed32 && iter.pSize == &msg.rep_fixed32_count)
|
||||
TEST(pb_field_iter_next(&iter) && iter.tag == 29 && iter.pData == &msg.rep_sfixed32 && iter.pSize == &msg.rep_sfixed32_count)
|
||||
TEST(pb_field_iter_next(&iter) && iter.tag == 30 && iter.pData == &msg.rep_float && iter.pSize == &msg.rep_float_count)
|
||||
TEST(pb_field_iter_next(&iter) && iter.tag == 31 && iter.pData == &msg.rep_fixed64 && iter.pSize == &msg.rep_fixed64_count)
|
||||
TEST(pb_field_iter_next(&iter) && iter.tag == 32 && iter.pData == &msg.rep_sfixed64 && iter.pSize == &msg.rep_sfixed64_count)
|
||||
TEST(pb_field_iter_next(&iter) && iter.tag == 33 && iter.pData == &msg.rep_double && iter.pSize == &msg.rep_double_count)
|
||||
TEST(pb_field_iter_next(&iter) && iter.tag == 34 && iter.pData == &msg.rep_string && iter.pSize == &msg.rep_string_count)
|
||||
TEST(pb_field_iter_next(&iter) && iter.tag == 35 && iter.pData == &msg.rep_bytes && iter.pSize == &msg.rep_bytes_count)
|
||||
TEST(pb_field_iter_next(&iter) && iter.tag == 36 && iter.pData == &msg.rep_submsg && iter.pSize == &msg.rep_submsg_count)
|
||||
TEST(pb_field_iter_next(&iter) && iter.tag == 37 && iter.pData == &msg.rep_enum && iter.pSize == &msg.rep_enum_count)
|
||||
TEST(pb_field_iter_next(&iter) && iter.tag == 38 && iter.pData == &msg.rep_emptymsg && iter.pSize == &msg.rep_emptymsg_count)
|
||||
TEST(pb_field_iter_next(&iter) && iter.tag == 39 && iter.pData == &msg.rep_fbytes && iter.pSize == &msg.rep_fbytes_count)
|
||||
TEST(pb_field_iter_next(&iter) && iter.tag == 40 && iter.pData == &msg.rep_farray && iter.pSize == &iter.array_size && iter.array_size == 5)
|
||||
TEST(iter.required_field_index == 19)
|
||||
TEST(iter.submessage_index == 4)
|
||||
|
||||
TEST(pb_field_iter_next(&iter) && iter.tag == 41 && iter.pData == &msg.opt_int32 && iter.pSize == &msg.has_opt_int32 )
|
||||
TEST(pb_field_iter_next(&iter) && iter.tag == 42 && iter.pData == &msg.opt_int64 && iter.pSize == &msg.has_opt_int64 )
|
||||
TEST(pb_field_iter_next(&iter) && iter.tag == 43 && iter.pData == &msg.opt_uint32 && iter.pSize == &msg.has_opt_uint32 )
|
||||
TEST(pb_field_iter_next(&iter) && iter.tag == 44 && iter.pData == &msg.opt_uint64 && iter.pSize == &msg.has_opt_uint64 )
|
||||
TEST(pb_field_iter_next(&iter) && iter.tag == 45 && iter.pData == &msg.opt_sint32 && iter.pSize == &msg.has_opt_sint32 )
|
||||
TEST(pb_field_iter_next(&iter) && iter.tag == 46 && iter.pData == &msg.opt_sint64 && iter.pSize == &msg.has_opt_sint64 )
|
||||
TEST(pb_field_iter_next(&iter) && iter.tag == 47 && iter.pData == &msg.opt_bool && iter.pSize == &msg.has_opt_bool )
|
||||
TEST(pb_field_iter_next(&iter) && iter.tag == 48 && iter.pData == &msg.opt_fixed32 && iter.pSize == &msg.has_opt_fixed32 )
|
||||
TEST(pb_field_iter_next(&iter) && iter.tag == 49 && iter.pData == &msg.opt_sfixed32 && iter.pSize == &msg.has_opt_sfixed32)
|
||||
TEST(pb_field_iter_next(&iter) && iter.tag == 50 && iter.pData == &msg.opt_float && iter.pSize == &msg.has_opt_float )
|
||||
TEST(pb_field_iter_next(&iter) && iter.tag == 51 && iter.pData == &msg.opt_fixed64 && iter.pSize == &msg.has_opt_fixed64 )
|
||||
TEST(pb_field_iter_next(&iter) && iter.tag == 52 && iter.pData == &msg.opt_sfixed64 && iter.pSize == &msg.has_opt_sfixed64)
|
||||
TEST(pb_field_iter_next(&iter) && iter.tag == 53 && iter.pData == &msg.opt_double && iter.pSize == &msg.has_opt_double )
|
||||
TEST(pb_field_iter_next(&iter) && iter.tag == 54 && iter.pData == &msg.opt_string && iter.pSize == &msg.has_opt_string )
|
||||
TEST(pb_field_iter_next(&iter) && iter.tag == 55 && iter.pData == &msg.opt_bytes && iter.pSize == &msg.has_opt_bytes )
|
||||
TEST(pb_field_iter_next(&iter) && iter.tag == 56 && iter.pData == &msg.opt_submsg && iter.pSize == &msg.has_opt_submsg )
|
||||
TEST(pb_field_iter_next(&iter) && iter.tag == 57 && iter.pData == &msg.opt_enum && iter.pSize == &msg.has_opt_enum )
|
||||
TEST(pb_field_iter_next(&iter) && iter.tag == 58 && iter.pData == &msg.opt_emptymsg && iter.pSize == &msg.has_opt_emptymsg)
|
||||
TEST(pb_field_iter_next(&iter) && iter.tag == 59 && iter.pData == &msg.opt_fbytes && iter.pSize == &msg.has_opt_fbytes)
|
||||
TEST(iter.required_field_index == 19)
|
||||
TEST(iter.submessage_index == 6)
|
||||
|
||||
TEST(pb_field_iter_next(&iter) && iter.tag == 60 && iter.pData == &msg.oneof.oneof_msg1 && iter.pSize == &msg.which_oneof )
|
||||
TEST(pb_field_iter_next(&iter) && iter.tag == 61 && iter.pData == &msg.oneof.oneof_msg2 && iter.pSize == &msg.which_oneof )
|
||||
TEST(pb_field_iter_next(&iter) && iter.tag == 62 && iter.pData == &msg.opt_non_zero_based_enum && iter.pSize == &msg.has_opt_non_zero_based_enum)
|
||||
TEST(pb_field_iter_next(&iter) && iter.tag == 63 && iter.pData == &msg.oneof.static_msg && iter.pSize == &msg.which_oneof )
|
||||
TEST(iter.required_field_index == 19)
|
||||
TEST(iter.submessage_index == 8)
|
||||
|
||||
TEST(pb_field_iter_next(&iter) && iter.tag == 95 && iter.pData == &msg.rep_farray2 && iter.pSize == &iter.array_size && iter.array_size == 3)
|
||||
TEST(iter.required_field_index == 19)
|
||||
TEST(iter.submessage_index == 9)
|
||||
|
||||
TEST(pb_field_iter_next(&iter) && iter.tag == 96 && iter.pData == &msg.req_intsizes && !iter.pSize)
|
||||
TEST(iter.required_field_index == 19)
|
||||
TEST(iter.submessage_index == 9)
|
||||
|
||||
TEST(pb_field_iter_next(&iter) && iter.tag == 97 && iter.pData == &msg.req_ds8 && !iter.pSize)
|
||||
TEST(iter.required_field_index == 20)
|
||||
TEST(iter.submessage_index == 10)
|
||||
|
||||
TEST(pb_field_iter_next(&iter) && iter.tag == 98 && iter.pData == &msg.req_limits && !iter.pSize)
|
||||
TEST(iter.required_field_index == 21)
|
||||
TEST(iter.submessage_index == 11)
|
||||
|
||||
TEST(pb_field_iter_next(&iter) && iter.tag == 200 && iter.pData == &msg.extensions && !iter.pSize)
|
||||
TEST(iter.required_field_index == 22)
|
||||
TEST(iter.submessage_index == 12)
|
||||
|
||||
TEST(pb_field_iter_next(&iter) && iter.tag == 999 && iter.pData == &msg.end && !iter.pSize)
|
||||
TEST(iter.required_field_index == 22)
|
||||
TEST(iter.submessage_index == 12)
|
||||
|
||||
TEST(!pb_field_iter_next(&iter))
|
||||
|
||||
TEST(iter.tag == 1 && iter.pData == &msg.req_int32 && !iter.pSize)
|
||||
TEST(iter.required_field_index == 0)
|
||||
TEST(iter.submessage_index == 0)
|
||||
}
|
||||
|
||||
{
|
||||
COMMENT("Test pb_validate_utf8()");
|
||||
|
||||
TEST(pb_validate_utf8("abcdefg"));
|
||||
TEST(pb_validate_utf8("\xc3\xa4\xc3\xa4\x6b\x6b\xc3\xb6\x6e\x65\x6e\x0a"));
|
||||
TEST(!pb_validate_utf8("\xc3\xa4\xc3\xa4\x6b\x6b\xb6\xc3\x6e\x65\x6e\x0a"));
|
||||
TEST(pb_validate_utf8("\xed\x9f\xbf"));
|
||||
TEST(pb_validate_utf8("\xee\x80\x80"));
|
||||
TEST(pb_validate_utf8("\xef\xbf\xbd"));
|
||||
TEST(pb_validate_utf8("\xf4\x8f\xbf\xbf"));
|
||||
TEST(!pb_validate_utf8("a\x80z"));
|
||||
TEST(!pb_validate_utf8("a\xbfz"));
|
||||
TEST(!pb_validate_utf8("a\xfez"));
|
||||
TEST(!pb_validate_utf8("a\xffz"));
|
||||
TEST(!pb_validate_utf8("a\xc0\xafz"));
|
||||
TEST(!pb_validate_utf8("a\xef\xbf\xbez"));
|
||||
}
|
||||
|
||||
if (status != 0)
|
||||
fprintf(stdout, "\n\nSome tests FAILED!\n");
|
||||
|
||||
return status;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
Import('env')
|
||||
|
||||
import os
|
||||
|
||||
base_env = env.Clone()
|
||||
base_env.Replace(NANOPBFLAGS = '--cpp-descriptor')
|
||||
base_env.NanopbProtoCpp('message')
|
||||
|
||||
# not enabled for "c++03", which fails with "warning: offset of on non-POD type 'TestMessage'"
|
||||
# 'offsetof' in C++98 requires POD type, C++11 standard relaxes that to standard-layout class.
|
||||
# see: http://www.cplusplus.com/reference/cstddef/offsetof/
|
||||
for std in ["c++11", "c++14", "c++17", "c++20"]:
|
||||
e = base_env.Clone()
|
||||
e.Append(CXXFLAGS = '-std={}'.format(std))
|
||||
|
||||
# Make sure compiler supports this version of C++ before we actually run the
|
||||
# test.
|
||||
conf = Configure(e)
|
||||
compiler_valid = conf.CheckCXX() and conf.CheckCXXHeader('vector')
|
||||
e = conf.Finish()
|
||||
if not compiler_valid:
|
||||
print("Skipping {} test - compiler doesn't support it".format(std))
|
||||
continue
|
||||
|
||||
sources = [ 'cxx_callback_datatype.cpp', 'message.pb.cpp', '$NANOPB/pb_decode.c', '$NANOPB/pb_encode.c', '$NANOPB/pb_common.c' ]
|
||||
objects = [ e.Object('{}_{}'.format(os.path.basename(s), std), s) for s in sources ]
|
||||
p = e.Program(target = 'cxx_callback_datatype_{}'.format(std), source = objects)
|
||||
e.RunTest(p)
|
||||
@@ -0,0 +1,92 @@
|
||||
#include "message.pb.hpp"
|
||||
|
||||
#include <pb_encode.h>
|
||||
#include <pb_decode.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdio>
|
||||
|
||||
// See tests/alltypes_callback, tests/oneoff_callback and examples/network_server for more...
|
||||
bool TestMessage_submessages_callback(pb_istream_t *istream, pb_ostream_t *ostream, const pb_field_t *field)
|
||||
{
|
||||
if (ostream != NULL) {
|
||||
const std::vector<int> &v = *(const std::vector<int> *)field->pData;
|
||||
for (std::vector<int>::const_iterator i = v.begin(); i != v.end(); ++i) {
|
||||
if (!pb_encode_tag_for_field(ostream, field)) {
|
||||
return false;
|
||||
}
|
||||
SubMessage tmp;
|
||||
tmp.actual_value = *i;
|
||||
if (!pb_encode_submessage(ostream, SubMessage_fields, &tmp)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else if (istream != NULL) {
|
||||
std::vector<int> &v = *(std::vector<int> *)field->pData;
|
||||
SubMessage tmp;
|
||||
if (!pb_decode(istream, SubMessage_fields, &tmp)) {
|
||||
return false;
|
||||
}
|
||||
v.push_back(tmp.actual_value);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
bool TestMessage_callback(pb_istream_t *istream, pb_ostream_t *ostream, const pb_field_t *field)
|
||||
{
|
||||
if (field->tag == TestMessage_submessages_tag) {
|
||||
return TestMessage_submessages_callback(istream, ostream, field);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
int main() {
|
||||
std::vector<int> source;
|
||||
source.push_back(5);
|
||||
source.push_back(4);
|
||||
source.push_back(3);
|
||||
source.push_back(2);
|
||||
source.push_back(1);
|
||||
|
||||
|
||||
std::vector<uint8_t> serialized;
|
||||
pb_ostream_t sizestream = {0};
|
||||
pb_encode(&sizestream, TestMessage_fields, &source);
|
||||
serialized.resize(sizestream.bytes_written);
|
||||
pb_ostream_t outstream = pb_ostream_from_buffer(&serialized.front(), serialized.size());
|
||||
if (!pb_encode(&outstream, TestMessage_fields, &source)) {
|
||||
fprintf(stderr, "Failed to encode: %s\n", PB_GET_ERROR(&outstream));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
std::vector<int> destination;
|
||||
pb_istream_t instream = pb_istream_from_buffer(&serialized.front(), outstream.bytes_written);
|
||||
if (!pb_decode(&instream, TestMessage_fields, &destination)) {
|
||||
fprintf(stderr, "Failed to decode: %s\n", PB_GET_ERROR(&instream));
|
||||
return 2;
|
||||
}
|
||||
if (source != destination) {
|
||||
fprintf(stderr, "Result does not match\n");
|
||||
fprintf(stderr, "source(%d): ", (int)source.size());
|
||||
for (std::vector<int>::iterator i = source.begin(); i != source.end(); ++i)
|
||||
{
|
||||
fprintf(stderr, "%d, ", *i);
|
||||
}
|
||||
fprintf(stderr, "\nencoded(%d): ", (int)serialized.size());
|
||||
for (unsigned i = 0; i != std::min(serialized.size(), outstream.bytes_written); ++i) {
|
||||
fprintf(stderr, "0x%02x ", serialized[i]);
|
||||
}
|
||||
fprintf(stderr, "\ndestination(%d): ", (int)destination.size());
|
||||
for (std::vector<int>::iterator i = destination.begin(); i != destination.end(); ++i)
|
||||
{
|
||||
fprintf(stderr, "%d, ", *i);
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
return 3;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
syntax = "proto3";
|
||||
|
||||
import "nanopb.proto";
|
||||
|
||||
option(nanopb_fileopt).include = '<vector>';
|
||||
|
||||
message SubMessage {
|
||||
sint32 actual_value = 1;
|
||||
}
|
||||
|
||||
message TestMessage {
|
||||
// Instead of std::vector<SubMessage> callback handles wrapping/unwrapping of the int.
|
||||
repeated SubMessage submessages = 1 [(nanopb).callback_datatype = "std::vector<int>"];
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
# Test cxx descriptor functionality
|
||||
|
||||
Import('env')
|
||||
|
||||
base_env = env.Clone()
|
||||
base_env.Replace(NANOPBFLAGS = '--cpp-descriptor')
|
||||
base_env.NanopbProto('message')
|
||||
|
||||
for std in ["c++03", "c++11", "c++14", "c++17", "c++20"]:
|
||||
e = base_env.Clone()
|
||||
e.Append(CXXFLAGS = '-std={}'.format(std))
|
||||
|
||||
# Make sure compiler supports this version of C++ before we actually run the
|
||||
# test.
|
||||
conf = Configure(e)
|
||||
compiler_valid = conf.CheckCXX()
|
||||
e = conf.Finish()
|
||||
if not compiler_valid:
|
||||
print("Skipping {} test - compiler doesn't support it".format(std))
|
||||
continue
|
||||
|
||||
o1 = e.Object('message_descriptor_{}'.format(std), 'message_descriptor.cc')
|
||||
o2 = e.Object('message.pb_{}'.format(std), 'message.pb.c')
|
||||
p = e.Program([o1, o2])
|
||||
e.RunTest(p)
|
||||
@@ -0,0 +1,12 @@
|
||||
/* Test CPP descriptor generation */
|
||||
|
||||
syntax = "proto2";
|
||||
|
||||
import "nanopb.proto";
|
||||
|
||||
message MyEmptyMessage {
|
||||
}
|
||||
|
||||
message MyNonEmptyMessage {
|
||||
optional uint32 field = 1;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
#include <stdio.h>
|
||||
#include "message.pb.h"
|
||||
#include "unittests.h"
|
||||
|
||||
extern "C" int main() {
|
||||
using namespace nanopb;
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
static_assert(MessageDescriptor<MyEmptyMessage>::fields_array_length == 0,
|
||||
"Unexpected field length");
|
||||
static_assert(MessageDescriptor<MyNonEmptyMessage>::fields_array_length == 1,
|
||||
"Unexpected field length");
|
||||
#endif // C++11 & newer
|
||||
|
||||
int status = 0;
|
||||
|
||||
TEST(MessageDescriptor<MyEmptyMessage>::fields_array_length ==
|
||||
MyEmptyMessage_msg.field_count);
|
||||
TEST(MessageDescriptor<MyNonEmptyMessage>::fields_array_length ==
|
||||
MyNonEmptyMessage_msg.field_count);
|
||||
|
||||
TEST(MessageDescriptor<MyEmptyMessage>::fields() == MyEmptyMessage_fields);
|
||||
TEST(MessageDescriptor<MyNonEmptyMessage>::fields() ==
|
||||
MyNonEmptyMessage_fields);
|
||||
|
||||
if (status != 0) fprintf(stdout, "\n\nSome tests FAILED!\n");
|
||||
|
||||
return status;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
# Run the alltypes test case, but compile it as C++ instead.
|
||||
# In fact, compile the entire nanopb using C++ compiler.
|
||||
|
||||
Import("env")
|
||||
|
||||
# This is needed to get INT32_MIN etc. macros defined
|
||||
env = env.Clone()
|
||||
env.Append(CPPDEFINES = ['__STDC_LIMIT_MACROS'])
|
||||
|
||||
# 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("pb_common.cxx", "#../pb_common.c", c)
|
||||
env.Command("alltypes.pb.h", "$BUILD/alltypes/alltypes.pb.h", c)
|
||||
env.Command("alltypes.pb.cxx", "$BUILD/alltypes/alltypes.pb.c", c)
|
||||
env.Command("encode_alltypes.cxx", "$BUILD/alltypes/encode_alltypes.c", c)
|
||||
env.Command("decode_alltypes.cxx", "$BUILD/alltypes/decode_alltypes.c", c)
|
||||
|
||||
# Now build and run the test normally.
|
||||
enc = env.Program(["encode_alltypes.cxx", "alltypes.pb.cxx", "pb_encode.cxx", "pb_common.cxx"])
|
||||
dec = env.Program(["decode_alltypes.cxx", "alltypes.pb.cxx", "pb_decode.cxx", "pb_common.cxx"])
|
||||
|
||||
env.RunTest(enc)
|
||||
env.RunTest([dec, "encode_alltypes.output"])
|
||||
@@ -0,0 +1,11 @@
|
||||
Import("env")
|
||||
|
||||
# Encode cyclic messages with callback fields
|
||||
|
||||
c = Copy("$TARGET", "$SOURCE")
|
||||
env.Command("cyclic_callback.proto", "cyclic.proto", c)
|
||||
env.NanopbProto(["cyclic_callback", "cyclic_callback.options"])
|
||||
|
||||
enc_callback = env.Program(["encode_cyclic_callback.c", "cyclic_callback.pb.c", "$COMMON/pb_encode.o", "$COMMON/pb_common.o"])
|
||||
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
// Test structures with cyclic references.
|
||||
// These can only be handled in pointer/callback mode,
|
||||
// see associated .options files.
|
||||
|
||||
syntax = "proto2";
|
||||
|
||||
message TreeNode
|
||||
{
|
||||
optional int32 leaf = 1;
|
||||
optional TreeNode left = 2;
|
||||
optional TreeNode right = 3;
|
||||
}
|
||||
|
||||
message Dictionary
|
||||
{
|
||||
repeated KeyValuePair dictItem = 1;
|
||||
}
|
||||
|
||||
message KeyValuePair
|
||||
{
|
||||
required string key = 1;
|
||||
optional string stringValue = 2;
|
||||
optional int32 intValue = 3;
|
||||
optional Dictionary dictValue = 4;
|
||||
optional TreeNode treeValue = 5;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
TreeNode.left type:FT_CALLBACK
|
||||
TreeNode.right type:FT_CALLBACK
|
||||
|
||||
KeyValuePair.key max_size:8
|
||||
KeyValuePair.stringValue max_size:8
|
||||
KeyValuePair.treeValue type:FT_CALLBACK
|
||||
@@ -0,0 +1,148 @@
|
||||
/* This program parses an input string in a format a bit like JSON:
|
||||
* {'foobar': 1234, 'xyz': 'abc', 'tree': [[[1, 2], 3], [4, 5]]}
|
||||
* and encodes it as protobuf
|
||||
*
|
||||
* Note: The string parsing here is not in any way intended to be robust
|
||||
* nor safe against buffer overflows. It is just for this test.
|
||||
*/
|
||||
|
||||
#include <pb_encode.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "cyclic_callback.pb.h"
|
||||
|
||||
static char *find_end_of_item(char *p)
|
||||
{
|
||||
int depth = 0;
|
||||
do {
|
||||
if (*p == '[' || *p == '{') depth++;
|
||||
if (*p == ']' || *p == '}') depth--;
|
||||
p++;
|
||||
} while (depth > 0 || (*p != ',' && *p != '}'));
|
||||
|
||||
if (*p == '}')
|
||||
return p; /* End of parent dict */
|
||||
|
||||
p++;
|
||||
while (*p == ' ') p++;
|
||||
return p;
|
||||
}
|
||||
|
||||
/* Parse a tree in format [[1 2] 3] and encode it directly to protobuf */
|
||||
static bool encode_tree(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
|
||||
{
|
||||
TreeNode tree = TreeNode_init_zero;
|
||||
char *p = (char*)*arg;
|
||||
|
||||
if (*p == '[')
|
||||
{
|
||||
/* This is a tree branch */
|
||||
p++;
|
||||
tree.left.funcs.encode = encode_tree;
|
||||
tree.left.arg = p;
|
||||
|
||||
p = find_end_of_item(p);
|
||||
tree.right.funcs.encode = encode_tree;
|
||||
tree.right.arg = p;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This is a leaf node */
|
||||
tree.has_leaf = true;
|
||||
tree.leaf = atoi(p);
|
||||
}
|
||||
|
||||
return pb_encode_tag_for_field(stream, field) &&
|
||||
pb_encode_submessage(stream, TreeNode_fields, &tree);
|
||||
}
|
||||
|
||||
/* Parse a dictionary in format {'name': value} and encode it directly to protobuf */
|
||||
static bool encode_dictionary(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
|
||||
{
|
||||
int textlen;
|
||||
char *p = (char*)*arg;
|
||||
if (*p == '{') p++;
|
||||
while (*p != '}')
|
||||
{
|
||||
KeyValuePair pair = KeyValuePair_init_zero;
|
||||
|
||||
if (*p != '\'')
|
||||
PB_RETURN_ERROR(stream, "invalid key, missing quote");
|
||||
|
||||
p++; /* Starting quote of key */
|
||||
textlen = strchr(p, '\'') - p;
|
||||
strncpy(pair.key, p, textlen);
|
||||
pair.key[textlen] = 0;
|
||||
p += textlen + 2;
|
||||
|
||||
while (*p == ' ') p++;
|
||||
|
||||
if (*p == '[')
|
||||
{
|
||||
/* Value is a tree */
|
||||
pair.treeValue.funcs.encode = encode_tree;
|
||||
pair.treeValue.arg = p;
|
||||
}
|
||||
else if (*p == '\'')
|
||||
{
|
||||
/* Value is a string */
|
||||
pair.has_stringValue = true;
|
||||
p++;
|
||||
textlen = strchr(p, '\'') - p;
|
||||
strncpy(pair.stringValue, p, textlen);
|
||||
pair.stringValue[textlen] = 0;
|
||||
}
|
||||
else if (*p == '{')
|
||||
{
|
||||
/* Value is a dictionary */
|
||||
pair.has_dictValue = true;
|
||||
pair.dictValue.dictItem.funcs.encode = encode_dictionary;
|
||||
pair.dictValue.dictItem.arg = p;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Value is integer */
|
||||
pair.has_intValue = true;
|
||||
pair.intValue = atoi(p);
|
||||
}
|
||||
|
||||
p = find_end_of_item(p);
|
||||
|
||||
if (!pb_encode_tag_for_field(stream, field))
|
||||
return false;
|
||||
|
||||
if (!pb_encode_submessage(stream, KeyValuePair_fields, &pair))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
uint8_t buffer[256];
|
||||
pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer));
|
||||
Dictionary dict = Dictionary_init_zero;
|
||||
|
||||
if (argc <= 1)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s \"{'foobar': 1234, ...}\"\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
dict.dictItem.funcs.encode = encode_dictionary;
|
||||
dict.dictItem.arg = argv[1];
|
||||
|
||||
if (!pb_encode(&stream, Dictionary_fields, &dict))
|
||||
{
|
||||
fprintf(stderr, "Encoding error: %s\n", PB_GET_ERROR(&stream));
|
||||
return 1;
|
||||
}
|
||||
|
||||
fwrite(buffer, 1, stream.bytes_written, stdout);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
Import('env')
|
||||
p = env.Program(["decode_unittests.c", "$COMMON/unittestproto.pb.c"])
|
||||
env.RunTest(p)
|
||||
|
||||
@@ -0,0 +1,446 @@
|
||||
/* This includes the whole .c file to get access to static functions. */
|
||||
#define PB_ENABLE_MALLOC
|
||||
#include "pb_common.c"
|
||||
#include "pb_decode.c"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "unittests.h"
|
||||
#include "unittestproto.pb.h"
|
||||
|
||||
#define S(x) pb_istream_from_buffer((uint8_t*)x, sizeof(x) - 1)
|
||||
|
||||
bool stream_callback(pb_istream_t *stream, uint8_t *buf, size_t count)
|
||||
{
|
||||
if (stream->state != NULL)
|
||||
return false; /* Simulate error */
|
||||
|
||||
if (buf != NULL)
|
||||
memset(buf, 'x', count);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Verifies that the stream passed to callback matches the byte array pointed to by arg. */
|
||||
bool callback_check(pb_istream_t *stream, const pb_field_t *field, void **arg)
|
||||
{
|
||||
int i;
|
||||
uint8_t byte;
|
||||
pb_bytes_array_t *ref = (pb_bytes_array_t*) *arg;
|
||||
|
||||
for (i = 0; i < ref->size; i++)
|
||||
{
|
||||
if (!pb_read(stream, &byte, 1))
|
||||
return false;
|
||||
|
||||
if (byte != ref->bytes[i])
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int status = 0;
|
||||
|
||||
{
|
||||
uint8_t buffer1[] = "foobartest1234";
|
||||
uint8_t buffer2[sizeof(buffer1)];
|
||||
pb_istream_t stream = pb_istream_from_buffer(buffer1, sizeof(buffer1));
|
||||
|
||||
COMMENT("Test pb_read and pb_istream_t");
|
||||
TEST(pb_read(&stream, buffer2, 6))
|
||||
TEST(memcmp(buffer2, "foobar", 6) == 0)
|
||||
TEST(stream.bytes_left == sizeof(buffer1) - 6)
|
||||
TEST(pb_read(&stream, buffer2 + 6, stream.bytes_left))
|
||||
TEST(memcmp(buffer1, buffer2, sizeof(buffer1)) == 0)
|
||||
TEST(stream.bytes_left == 0)
|
||||
TEST(!pb_read(&stream, buffer2, 1))
|
||||
}
|
||||
|
||||
{
|
||||
uint8_t buffer[20];
|
||||
pb_istream_t stream = {&stream_callback, NULL, 20};
|
||||
|
||||
COMMENT("Test pb_read with custom callback");
|
||||
TEST(pb_read(&stream, buffer, 5))
|
||||
TEST(memcmp(buffer, "xxxxx", 5) == 0)
|
||||
TEST(!pb_read(&stream, buffer, 50))
|
||||
stream.state = (void*)1; /* Simulated error return from callback */
|
||||
TEST(!pb_read(&stream, buffer, 5))
|
||||
stream.state = NULL;
|
||||
TEST(pb_read(&stream, buffer, 15))
|
||||
}
|
||||
|
||||
{
|
||||
pb_istream_t s;
|
||||
uint64_t u;
|
||||
int64_t i;
|
||||
|
||||
COMMENT("Test pb_decode_varint");
|
||||
TEST((s = S("\x00"), pb_decode_varint(&s, &u) && u == 0));
|
||||
TEST((s = S("\x01"), pb_decode_varint(&s, &u) && u == 1));
|
||||
TEST((s = S("\xAC\x02"), pb_decode_varint(&s, &u) && u == 300));
|
||||
TEST((s = S("\xFF\xFF\xFF\xFF\x0F"), pb_decode_varint(&s, &u) && u == UINT32_MAX));
|
||||
TEST((s = S("\xFF\xFF\xFF\xFF\x0F"), pb_decode_varint(&s, (uint64_t*)&i) && i == UINT32_MAX));
|
||||
TEST((s = S("\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x01"),
|
||||
pb_decode_varint(&s, (uint64_t*)&i) && i == -1));
|
||||
TEST((s = S("\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x01"),
|
||||
pb_decode_varint(&s, &u) && u == UINT64_MAX));
|
||||
TEST((s = S("\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x01"),
|
||||
!pb_decode_varint(&s, &u)));
|
||||
}
|
||||
|
||||
{
|
||||
pb_istream_t s;
|
||||
uint32_t u;
|
||||
|
||||
COMMENT("Test pb_decode_varint32");
|
||||
TEST((s = S("\x00"), pb_decode_varint32(&s, &u) && u == 0));
|
||||
TEST((s = S("\x01"), pb_decode_varint32(&s, &u) && u == 1));
|
||||
TEST((s = S("\xAC\x02"), pb_decode_varint32(&s, &u) && u == 300));
|
||||
TEST((s = S("\xFF\xFF\xFF\xFF\x0F"), pb_decode_varint32(&s, &u) && u == UINT32_MAX));
|
||||
TEST((s = S("\xFF\xFF\xFF\xFF\x8F\x00"), pb_decode_varint32(&s, &u) && u == UINT32_MAX));
|
||||
TEST((s = S("\xFF\xFF\xFF\xFF\x10"), !pb_decode_varint32(&s, &u)));
|
||||
TEST((s = S("\xFF\xFF\xFF\xFF\x40"), !pb_decode_varint32(&s, &u)));
|
||||
TEST((s = S("\xFF\xFF\xFF\xFF\xFF\x01"), !pb_decode_varint32(&s, &u)));
|
||||
TEST((s = S("\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x80\x00"), !pb_decode_varint32(&s, &u)));
|
||||
}
|
||||
|
||||
{
|
||||
pb_istream_t s;
|
||||
COMMENT("Test pb_skip_varint");
|
||||
TEST((s = S("\x00""foobar"), pb_skip_varint(&s) && s.bytes_left == 6))
|
||||
TEST((s = S("\xAC\x02""foobar"), pb_skip_varint(&s) && s.bytes_left == 6))
|
||||
TEST((s = S("\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x01""foobar"),
|
||||
pb_skip_varint(&s) && s.bytes_left == 6))
|
||||
TEST((s = S("\xFF"), !pb_skip_varint(&s)))
|
||||
}
|
||||
|
||||
{
|
||||
pb_istream_t s;
|
||||
COMMENT("Test pb_skip_string")
|
||||
TEST((s = S("\x00""foobar"), pb_skip_string(&s) && s.bytes_left == 6))
|
||||
TEST((s = S("\x04""testfoobar"), pb_skip_string(&s) && s.bytes_left == 6))
|
||||
TEST((s = S("\x04"), !pb_skip_string(&s)))
|
||||
TEST((s = S("\xFF"), !pb_skip_string(&s)))
|
||||
}
|
||||
|
||||
{
|
||||
pb_istream_t s = S("\x01\x00");
|
||||
pb_field_iter_t f;
|
||||
uint32_t d;
|
||||
|
||||
f.type = PB_LTYPE_VARINT;
|
||||
f.data_size = sizeof(d);
|
||||
f.pData = &d;
|
||||
|
||||
COMMENT("Test pb_dec_varint using uint32_t")
|
||||
TEST(pb_dec_varint(&s, &f) && d == 1)
|
||||
|
||||
/* Verify that no more than data_size is written. */
|
||||
d = 0xFFFFFFFF;
|
||||
f.data_size = 1;
|
||||
TEST(pb_dec_varint(&s, &f) && (d == 0xFFFFFF00 || d == 0x00FFFFFF))
|
||||
}
|
||||
|
||||
{
|
||||
pb_istream_t s;
|
||||
pb_field_iter_t f;
|
||||
int32_t d;
|
||||
|
||||
f.type = PB_LTYPE_SVARINT;
|
||||
f.data_size = sizeof(d);
|
||||
f.pData = &d;
|
||||
|
||||
COMMENT("Test pb_dec_varint using sint32_t")
|
||||
TEST((s = S("\x01"), pb_dec_varint(&s, &f) && d == -1))
|
||||
TEST((s = S("\x02"), pb_dec_varint(&s, &f) && d == 1))
|
||||
TEST((s = S("\xfe\xff\xff\xff\x0f"), pb_dec_varint(&s, &f) && d == INT32_MAX))
|
||||
TEST((s = S("\xff\xff\xff\xff\x0f"), pb_dec_varint(&s, &f) && d == INT32_MIN))
|
||||
}
|
||||
|
||||
{
|
||||
pb_istream_t s;
|
||||
pb_field_iter_t f;
|
||||
int64_t d;
|
||||
|
||||
f.type = PB_LTYPE_SVARINT;
|
||||
f.data_size = sizeof(d);
|
||||
f.pData = &d;
|
||||
|
||||
COMMENT("Test pb_dec_varint using sint64_t")
|
||||
TEST((s = S("\x01"), pb_dec_varint(&s, &f) && d == -1))
|
||||
TEST((s = S("\x02"), pb_dec_varint(&s, &f) && d == 1))
|
||||
TEST((s = S("\xFE\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x01"), pb_dec_varint(&s, &f) && d == INT64_MAX))
|
||||
TEST((s = S("\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x01"), pb_dec_varint(&s, &f) && d == INT64_MIN))
|
||||
}
|
||||
|
||||
{
|
||||
pb_istream_t s;
|
||||
pb_field_iter_t f;
|
||||
int32_t d;
|
||||
|
||||
f.type = PB_LTYPE_SVARINT;
|
||||
f.data_size = sizeof(d);
|
||||
f.pData = &d;
|
||||
|
||||
COMMENT("Test pb_dec_varint overflow detection using sint32_t");
|
||||
TEST((s = S("\xfe\xff\xff\xff\x0f"), pb_dec_varint(&s, &f)));
|
||||
TEST((s = S("\xfe\xff\xff\xff\x10"), !pb_dec_varint(&s, &f)));
|
||||
TEST((s = S("\xff\xff\xff\xff\x0f"), pb_dec_varint(&s, &f)));
|
||||
TEST((s = S("\xff\xff\xff\xff\x10"), !pb_dec_varint(&s, &f)));
|
||||
}
|
||||
|
||||
{
|
||||
pb_istream_t s;
|
||||
pb_field_iter_t f;
|
||||
uint32_t d;
|
||||
|
||||
f.type = PB_LTYPE_UVARINT;
|
||||
f.data_size = sizeof(d);
|
||||
f.pData = &d;
|
||||
|
||||
COMMENT("Test pb_dec_varint using uint32_t")
|
||||
TEST((s = S("\x01"), pb_dec_varint(&s, &f) && d == 1))
|
||||
TEST((s = S("\x02"), pb_dec_varint(&s, &f) && d == 2))
|
||||
TEST((s = S("\xff\xff\xff\xff\x0f"), pb_dec_varint(&s, &f) && d == UINT32_MAX))
|
||||
}
|
||||
|
||||
{
|
||||
pb_istream_t s;
|
||||
pb_field_iter_t f;
|
||||
uint64_t d;
|
||||
|
||||
f.type = PB_LTYPE_UVARINT;
|
||||
f.data_size = sizeof(d);
|
||||
f.pData = &d;
|
||||
|
||||
COMMENT("Test pb_dec_varint using uint64_t")
|
||||
TEST((s = S("\x01"), pb_dec_varint(&s, &f) && d == 1))
|
||||
TEST((s = S("\x02"), pb_dec_varint(&s, &f) && d == 2))
|
||||
TEST((s = S("\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x01"), pb_dec_varint(&s, &f) && d == UINT64_MAX))
|
||||
}
|
||||
|
||||
{
|
||||
pb_istream_t s;
|
||||
pb_field_iter_t f;
|
||||
uint32_t d;
|
||||
|
||||
f.type = PB_LTYPE_UVARINT;
|
||||
f.data_size = sizeof(d);
|
||||
f.pData = &d;
|
||||
|
||||
COMMENT("Test pb_dec_varint overflow detection using uint32_t");
|
||||
TEST((s = S("\xff\xff\xff\xff\x0f"), pb_dec_varint(&s, &f)));
|
||||
TEST((s = S("\xff\xff\xff\xff\x10"), !pb_dec_varint(&s, &f)));
|
||||
}
|
||||
|
||||
{
|
||||
pb_istream_t s;
|
||||
float d;
|
||||
|
||||
COMMENT("Test pb_dec_fixed using float (failures here may be caused by imperfect rounding)")
|
||||
TEST((s = S("\x00\x00\x00\x00"), pb_decode_fixed32(&s, &d) && d == 0.0f))
|
||||
TEST((s = S("\x00\x00\xc6\x42"), pb_decode_fixed32(&s, &d) && d == 99.0f))
|
||||
TEST((s = S("\x4e\x61\x3c\xcb"), pb_decode_fixed32(&s, &d) && d == -12345678.0f))
|
||||
d = -12345678.0f;
|
||||
TEST((s = S("\x00"), !pb_decode_fixed32(&s, &d) && d == -12345678.0f))
|
||||
}
|
||||
|
||||
if (sizeof(double) == 8)
|
||||
{
|
||||
pb_istream_t s;
|
||||
double d;
|
||||
|
||||
COMMENT("Test pb_dec_fixed64 using double (failures here may be caused by imperfect rounding)")
|
||||
TEST((s = S("\x00\x00\x00\x00\x00\x00\x00\x00"), pb_decode_fixed64(&s, &d) && d == 0.0))
|
||||
TEST((s = S("\x00\x00\x00\x00\x00\xc0\x58\x40"), pb_decode_fixed64(&s, &d) && d == 99.0))
|
||||
TEST((s = S("\x00\x00\x00\xc0\x29\x8c\x67\xc1"), pb_decode_fixed64(&s, &d) && d == -12345678.0f))
|
||||
}
|
||||
|
||||
{
|
||||
pb_istream_t s;
|
||||
struct { pb_size_t size; uint8_t bytes[5]; } d;
|
||||
pb_field_iter_t f;
|
||||
|
||||
f.type = PB_LTYPE_BYTES;
|
||||
f.data_size = sizeof(d);
|
||||
f.pData = &d;
|
||||
|
||||
COMMENT("Test pb_dec_bytes")
|
||||
TEST((s = S("\x00"), pb_dec_bytes(&s, &f) && d.size == 0))
|
||||
TEST((s = S("\x01\xFF"), pb_dec_bytes(&s, &f) && d.size == 1 && d.bytes[0] == 0xFF))
|
||||
TEST((s = S("\x05xxxxx"), pb_dec_bytes(&s, &f) && d.size == 5))
|
||||
TEST((s = S("\x05xxxx"), !pb_dec_bytes(&s, &f)))
|
||||
|
||||
/* Note: the size limit on bytes-fields is not strictly obeyed, as
|
||||
* the compiler may add some padding to the struct. Using this padding
|
||||
* is not a very good thing to do, but it is difficult to avoid when
|
||||
* we use only a single uint8_t to store the size of the field.
|
||||
* Therefore this tests against a 10-byte string, while otherwise even
|
||||
* 6 bytes should error out.
|
||||
*/
|
||||
TEST((s = S("\x10xxxxxxxxxx"), !pb_dec_bytes(&s, &f)))
|
||||
}
|
||||
|
||||
{
|
||||
pb_istream_t s;
|
||||
pb_field_iter_t f;
|
||||
char d[5];
|
||||
|
||||
f.type = PB_LTYPE_STRING;
|
||||
f.data_size = sizeof(d);
|
||||
f.pData = &d;
|
||||
|
||||
COMMENT("Test pb_dec_string")
|
||||
TEST((s = S("\x00"), pb_dec_string(&s, &f) && d[0] == '\0'))
|
||||
TEST((s = S("\x04xyzz"), pb_dec_string(&s, &f) && strcmp(d, "xyzz") == 0))
|
||||
TEST((s = S("\x05xyzzy"), !pb_dec_string(&s, &f)))
|
||||
}
|
||||
|
||||
{
|
||||
pb_istream_t s;
|
||||
IntegerArray dest;
|
||||
|
||||
COMMENT("Testing pb_decode with repeated int32 field")
|
||||
TEST((s = S(""), pb_decode(&s, IntegerArray_fields, &dest) && dest.data_count == 0))
|
||||
TEST((s = S("\x08\x01\x08\x02"), pb_decode(&s, IntegerArray_fields, &dest)
|
||||
&& dest.data_count == 2 && dest.data[0] == 1 && dest.data[1] == 2))
|
||||
s = S("\x08\x01\x08\x02\x08\x03\x08\x04\x08\x05\x08\x06\x08\x07\x08\x08\x08\x09\x08\x0A");
|
||||
TEST(pb_decode(&s, IntegerArray_fields, &dest) && dest.data_count == 10 && dest.data[9] == 10)
|
||||
s = S("\x08\x01\x08\x02\x08\x03\x08\x04\x08\x05\x08\x06\x08\x07\x08\x08\x08\x09\x08\x0A\x08\x0B");
|
||||
TEST(!pb_decode(&s, IntegerArray_fields, &dest))
|
||||
}
|
||||
|
||||
{
|
||||
pb_istream_t s;
|
||||
IntegerArray dest;
|
||||
|
||||
COMMENT("Testing pb_decode with packed int32 field")
|
||||
TEST((s = S("\x0A\x00"), pb_decode(&s, IntegerArray_fields, &dest)
|
||||
&& dest.data_count == 0))
|
||||
TEST((s = S("\x0A\x01\x01"), pb_decode(&s, IntegerArray_fields, &dest)
|
||||
&& dest.data_count == 1 && dest.data[0] == 1))
|
||||
TEST((s = S("\x0A\x0A\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A"), pb_decode(&s, IntegerArray_fields, &dest)
|
||||
&& dest.data_count == 10 && dest.data[0] == 1 && dest.data[9] == 10))
|
||||
TEST((s = S("\x0A\x0B\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B"), !pb_decode(&s, IntegerArray_fields, &dest)))
|
||||
|
||||
/* Test invalid wire data */
|
||||
TEST((s = S("\x0A\xFF"), !pb_decode(&s, IntegerArray_fields, &dest)))
|
||||
TEST((s = S("\x0A\x01"), !pb_decode(&s, IntegerArray_fields, &dest)))
|
||||
}
|
||||
|
||||
{
|
||||
pb_istream_t s;
|
||||
IntegerArray dest;
|
||||
|
||||
COMMENT("Testing pb_decode with unknown fields")
|
||||
TEST((s = S("\x18\x0F\x08\x01"), pb_decode(&s, IntegerArray_fields, &dest)
|
||||
&& dest.data_count == 1 && dest.data[0] == 1))
|
||||
TEST((s = S("\x19\x00\x00\x00\x00\x00\x00\x00\x00\x08\x01"), pb_decode(&s, IntegerArray_fields, &dest)
|
||||
&& dest.data_count == 1 && dest.data[0] == 1))
|
||||
TEST((s = S("\x1A\x00\x08\x01"), pb_decode(&s, IntegerArray_fields, &dest)
|
||||
&& dest.data_count == 1 && dest.data[0] == 1))
|
||||
TEST((s = S("\x1B\x08\x01"), !pb_decode(&s, IntegerArray_fields, &dest)))
|
||||
TEST((s = S("\x1D\x00\x00\x00\x00\x08\x01"), pb_decode(&s, IntegerArray_fields, &dest)
|
||||
&& dest.data_count == 1 && dest.data[0] == 1))
|
||||
}
|
||||
|
||||
{
|
||||
pb_istream_t s;
|
||||
CallbackArray dest;
|
||||
struct { pb_size_t size; uint8_t bytes[10]; } ref;
|
||||
dest.data.funcs.decode = &callback_check;
|
||||
dest.data.arg = &ref;
|
||||
|
||||
COMMENT("Testing pb_decode with callbacks")
|
||||
/* Single varint */
|
||||
ref.size = 1; ref.bytes[0] = 0x55;
|
||||
TEST((s = S("\x08\x55"), pb_decode(&s, CallbackArray_fields, &dest)))
|
||||
/* Packed varint */
|
||||
ref.size = 3; ref.bytes[0] = ref.bytes[1] = ref.bytes[2] = 0x55;
|
||||
TEST((s = S("\x0A\x03\x55\x55\x55"), pb_decode(&s, CallbackArray_fields, &dest)))
|
||||
/* Packed varint with loop */
|
||||
ref.size = 1; ref.bytes[0] = 0x55;
|
||||
TEST((s = S("\x0A\x03\x55\x55\x55"), pb_decode(&s, CallbackArray_fields, &dest)))
|
||||
/* Single fixed32 */
|
||||
ref.size = 4; ref.bytes[0] = ref.bytes[1] = ref.bytes[2] = ref.bytes[3] = 0xAA;
|
||||
TEST((s = S("\x0D\xAA\xAA\xAA\xAA"), pb_decode(&s, CallbackArray_fields, &dest)))
|
||||
/* Single fixed64 */
|
||||
ref.size = 8; memset(ref.bytes, 0xAA, 8);
|
||||
TEST((s = S("\x09\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"), pb_decode(&s, CallbackArray_fields, &dest)))
|
||||
/* Unsupported field type */
|
||||
TEST((s = S("\x0B\x00"), !pb_decode(&s, CallbackArray_fields, &dest)))
|
||||
|
||||
/* Just make sure that our test function works */
|
||||
ref.size = 1; ref.bytes[0] = 0x56;
|
||||
TEST((s = S("\x08\x55"), !pb_decode(&s, CallbackArray_fields, &dest)))
|
||||
}
|
||||
|
||||
{
|
||||
pb_istream_t s;
|
||||
IntegerArray dest;
|
||||
|
||||
COMMENT("Testing pb_decode message termination")
|
||||
TEST((s = S(""), pb_decode(&s, IntegerArray_fields, &dest)))
|
||||
TEST((s = S("\x08\x01"), pb_decode(&s, IntegerArray_fields, &dest)))
|
||||
TEST((s = S("\x08"), !pb_decode(&s, IntegerArray_fields, &dest)))
|
||||
}
|
||||
|
||||
{
|
||||
pb_istream_t s;
|
||||
IntegerArray dest;
|
||||
|
||||
COMMENT("Testing pb_decode_ex null termination")
|
||||
|
||||
TEST((s = S("\x00"), pb_decode_ex(&s, IntegerArray_fields, &dest, PB_DECODE_NULLTERMINATED)))
|
||||
TEST((s = S("\x08\x01\x00"), pb_decode_ex(&s, IntegerArray_fields, &dest, PB_DECODE_NULLTERMINATED)))
|
||||
}
|
||||
|
||||
{
|
||||
pb_istream_t s;
|
||||
IntegerArray dest;
|
||||
|
||||
COMMENT("Testing pb_decode with invalid tag numbers")
|
||||
TEST((s = S("\x9f\xea"), !pb_decode(&s, IntegerArray_fields, &dest)));
|
||||
TEST((s = S("\x00"), !pb_decode(&s, IntegerArray_fields, &dest)));
|
||||
}
|
||||
|
||||
{
|
||||
pb_istream_t s;
|
||||
IntegerContainer dest = {{0}};
|
||||
|
||||
COMMENT("Testing pb_decode_delimited")
|
||||
TEST((s = S("\x09\x0A\x07\x0A\x05\x01\x02\x03\x04\x05"),
|
||||
pb_decode_delimited(&s, IntegerContainer_fields, &dest)) &&
|
||||
dest.submsg.data_count == 5)
|
||||
}
|
||||
|
||||
{
|
||||
pb_istream_t s = {0};
|
||||
void *data = NULL;
|
||||
|
||||
COMMENT("Testing allocate_field")
|
||||
TEST(allocate_field(&s, &data, 10, 10) && data != NULL);
|
||||
TEST(allocate_field(&s, &data, 10, 20) && data != NULL);
|
||||
|
||||
{
|
||||
void *oldvalue = data;
|
||||
size_t very_big = (size_t)-1;
|
||||
size_t somewhat_big = very_big / 2 + 1;
|
||||
size_t not_so_big = (size_t)1 << (4 * sizeof(size_t));
|
||||
|
||||
TEST(!allocate_field(&s, &data, very_big, 2) && data == oldvalue);
|
||||
TEST(!allocate_field(&s, &data, somewhat_big, 2) && data == oldvalue);
|
||||
TEST(!allocate_field(&s, &data, not_so_big, not_so_big) && data == oldvalue);
|
||||
}
|
||||
|
||||
pb_free(data);
|
||||
}
|
||||
|
||||
if (status != 0)
|
||||
fprintf(stdout, "\n\nSome tests FAILED!\n");
|
||||
|
||||
return status;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
Docker files
|
||||
------------
|
||||
|
||||
This folder contains docker files that are used in testing nanopb automatically
|
||||
on various platforms.
|
||||
|
||||
By default they take the newest master branch code from github.
|
||||
|
||||
To build tests for a single target, use for example:
|
||||
|
||||
docker build ubuntu1804
|
||||
|
||||
To build tests for all targets, use:
|
||||
|
||||
./build_all.sh
|
||||
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
#!/bin/bash -e
|
||||
|
||||
# Run all targets
|
||||
for file in `ls */Dockerfile`
|
||||
do echo -e "\n\n\n---------------------------------------- Building image for" $file " -------------------------------------------\n\n\n"
|
||||
docker build $(dirname $file)
|
||||
done
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
FROM ubuntu:bionic
|
||||
|
||||
RUN apt -y update
|
||||
RUN apt -y upgrade
|
||||
RUN apt -y dist-upgrade
|
||||
RUN apt -y autoremove
|
||||
RUN apt -y install --fix-missing
|
||||
RUN apt -y install apt-utils
|
||||
|
||||
RUN apt -y install git scons build-essential g++
|
||||
RUN apt -y install protobuf-compiler python3-protobuf python3
|
||||
|
||||
RUN git clone https://github.com/nanopb/nanopb.git
|
||||
RUN cd nanopb/tests && scons
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
FROM ubuntu:focal
|
||||
|
||||
RUN apt -y update
|
||||
RUN apt -y upgrade
|
||||
RUN apt -y dist-upgrade
|
||||
RUN apt -y autoremove
|
||||
RUN apt -y install --fix-missing
|
||||
RUN apt -y install apt-utils
|
||||
|
||||
RUN apt -y install git scons build-essential g++
|
||||
RUN apt -y install protobuf-compiler python3.8 python3-protobuf
|
||||
RUN update-alternatives --install /usr/bin/python python /usr/bin/python3.8 1 && update-alternatives --set python /usr/bin/python3.8
|
||||
|
||||
RUN git clone https://github.com/nanopb/nanopb.git
|
||||
RUN cd nanopb/tests && scons
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
# Run the alltypes test case, but compile with PB_ENCODE_ARRAYS_UNPACKED=1
|
||||
|
||||
Import("env")
|
||||
|
||||
# Take copy of the files for custom build.
|
||||
c = Copy("$TARGET", "$SOURCE")
|
||||
env.Command("alltypes.pb.h", "$BUILD/alltypes/alltypes.pb.h", c)
|
||||
env.Command("alltypes.pb.c", "$BUILD/alltypes/alltypes.pb.c", c)
|
||||
env.Command("encode_alltypes.c", "$BUILD/alltypes/encode_alltypes.c", c)
|
||||
env.Command("decode_alltypes.c", "$BUILD/alltypes/decode_alltypes.c", c)
|
||||
|
||||
# Define the compilation options
|
||||
opts = env.Clone()
|
||||
opts.Append(CPPDEFINES = {'PB_ENCODE_ARRAYS_UNPACKED': 1})
|
||||
|
||||
# Build new version of core
|
||||
strict = opts.Clone()
|
||||
strict.Append(CFLAGS = strict['CORECFLAGS'])
|
||||
strict.Object("pb_decode_unpacked.o", "$NANOPB/pb_decode.c")
|
||||
strict.Object("pb_encode_unpacked.o", "$NANOPB/pb_encode.c")
|
||||
strict.Object("pb_common_unpacked.o", "$NANOPB/pb_common.c")
|
||||
|
||||
# Now build and run the test normally.
|
||||
enc = opts.Program(["encode_alltypes.c", "alltypes.pb.c", "pb_encode_unpacked.o", "pb_common_unpacked.o"])
|
||||
dec = opts.Program(["decode_alltypes.c", "alltypes.pb.c", "pb_decode_unpacked.o", "pb_common_unpacked.o"])
|
||||
|
||||
env.RunTest(enc)
|
||||
env.RunTest([dec, "encode_alltypes.output"])
|
||||
@@ -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"])
|
||||
env.RunTest(p)
|
||||
@@ -0,0 +1,429 @@
|
||||
/* This includes the whole .c file to get access to static functions. */
|
||||
#include "pb_common.c"
|
||||
#include "pb_encode.c"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "unittests.h"
|
||||
#include "unittestproto.pb.h"
|
||||
|
||||
bool streamcallback(pb_ostream_t *stream, const uint8_t *buf, size_t count)
|
||||
{
|
||||
/* Allow only 'x' to be written */
|
||||
while (count--)
|
||||
{
|
||||
if (*buf++ != 'x')
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool fieldcallback(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
|
||||
{
|
||||
int value = 0x55;
|
||||
if (!pb_encode_tag_for_field(stream, field))
|
||||
return false;
|
||||
return pb_encode_varint(stream, value);
|
||||
}
|
||||
|
||||
bool crazyfieldcallback(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
|
||||
{
|
||||
/* This callback writes different amount of data the second time. */
|
||||
uint32_t *state = (uint32_t*)arg;
|
||||
*state <<= 8;
|
||||
if (!pb_encode_tag_for_field(stream, field))
|
||||
return false;
|
||||
return pb_encode_varint(stream, *state);
|
||||
}
|
||||
|
||||
/* Check that expression x writes data y.
|
||||
* Y is a string, which may contain null bytes. Null terminator is ignored.
|
||||
*/
|
||||
#define WRITES(x, y) \
|
||||
memset(buffer, 0xAA, sizeof(buffer)), \
|
||||
s = pb_ostream_from_buffer(buffer, sizeof(buffer)), \
|
||||
(x) && \
|
||||
memcmp(buffer, y, sizeof(y) - 1) == 0 && \
|
||||
buffer[sizeof(y) - 1] == 0xAA
|
||||
|
||||
int main()
|
||||
{
|
||||
int status = 0;
|
||||
|
||||
{
|
||||
uint8_t buffer1[] = "foobartest1234";
|
||||
uint8_t buffer2[sizeof(buffer1)];
|
||||
pb_ostream_t stream = pb_ostream_from_buffer(buffer2, sizeof(buffer1));
|
||||
|
||||
COMMENT("Test pb_write and pb_ostream_t");
|
||||
TEST(pb_write(&stream, buffer1, sizeof(buffer1)));
|
||||
TEST(memcmp(buffer1, buffer2, sizeof(buffer1)) == 0);
|
||||
TEST(!pb_write(&stream, buffer1, 1));
|
||||
TEST(stream.bytes_written == sizeof(buffer1));
|
||||
}
|
||||
|
||||
{
|
||||
uint8_t buffer1[] = "xxxxxxx";
|
||||
pb_ostream_t stream = {&streamcallback, 0, SIZE_MAX, 0};
|
||||
|
||||
COMMENT("Test pb_write with custom callback");
|
||||
TEST(pb_write(&stream, buffer1, 5));
|
||||
buffer1[0] = 'a';
|
||||
TEST(!pb_write(&stream, buffer1, 5));
|
||||
}
|
||||
|
||||
{
|
||||
uint8_t buffer[30];
|
||||
pb_ostream_t s;
|
||||
|
||||
COMMENT("Test pb_encode_varint")
|
||||
TEST(WRITES(pb_encode_varint(&s, 0), "\0"));
|
||||
TEST(WRITES(pb_encode_varint(&s, 1), "\1"));
|
||||
TEST(WRITES(pb_encode_varint(&s, 0x7F), "\x7F"));
|
||||
TEST(WRITES(pb_encode_varint(&s, 0x80), "\x80\x01"));
|
||||
TEST(WRITES(pb_encode_varint(&s, UINT32_MAX), "\xFF\xFF\xFF\xFF\x0F"));
|
||||
TEST(WRITES(pb_encode_varint(&s, UINT64_MAX), "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x01"));
|
||||
}
|
||||
|
||||
{
|
||||
uint8_t buffer[50];
|
||||
pb_ostream_t s;
|
||||
|
||||
COMMENT("Test pb_encode_varint 32-bit fast path")
|
||||
TEST(WRITES(pb_encode_varint(&s, 0x00000000), "\x00"));
|
||||
TEST(WRITES(pb_encode_varint(&s, 0x00000001), "\x01"));
|
||||
TEST(WRITES(pb_encode_varint(&s, 0x0000007F), "\x7F"));
|
||||
TEST(WRITES(pb_encode_varint(&s, 0x00000080), "\x80\x01"));
|
||||
TEST(WRITES(pb_encode_varint(&s, 0x00000191), "\x91\x03"));
|
||||
TEST(WRITES(pb_encode_varint(&s, 0x00003FFF), "\xFF\x7F"));
|
||||
TEST(WRITES(pb_encode_varint(&s, 0x00004000), "\x80\x80\x01"));
|
||||
TEST(WRITES(pb_encode_varint(&s, 0x0000D111), "\x91\xA2\x03"));
|
||||
TEST(WRITES(pb_encode_varint(&s, 0x001FFFFF), "\xFF\xFF\x7F"));
|
||||
TEST(WRITES(pb_encode_varint(&s, 0x00200000), "\x80\x80\x80\x01"));
|
||||
TEST(WRITES(pb_encode_varint(&s, 0x00711111), "\x91\xA2\xC4\x03"));
|
||||
TEST(WRITES(pb_encode_varint(&s, 0x0FFFFFFF), "\xFF\xFF\xFF\x7F"));
|
||||
TEST(WRITES(pb_encode_varint(&s, 0x10000000), "\x80\x80\x80\x80\x01"));
|
||||
TEST(WRITES(pb_encode_varint(&s, 0x31111111), "\x91\xA2\xC4\x88\x03"));
|
||||
TEST(WRITES(pb_encode_varint(&s, UINT32_MAX), "\xFF\xFF\xFF\xFF\x0F"));
|
||||
}
|
||||
|
||||
{
|
||||
uint8_t buffer[50];
|
||||
pb_ostream_t s;
|
||||
|
||||
COMMENT("Test pb_encode_svarint 32-bit fast path")
|
||||
TEST(WRITES(pb_encode_svarint(&s, (int32_t)0x00000000), "\x00"));
|
||||
TEST(WRITES(pb_encode_svarint(&s, (int32_t)0xFFFFFFFF), "\x01"));
|
||||
TEST(WRITES(pb_encode_svarint(&s, (int32_t)0x0000003F), "\x7E"));
|
||||
TEST(WRITES(pb_encode_svarint(&s, (int32_t)0xFFFFFFC0), "\x7F"));
|
||||
TEST(WRITES(pb_encode_svarint(&s, (int32_t)0x00000040), "\x80\x01"));
|
||||
TEST(WRITES(pb_encode_svarint(&s, (int32_t)0x00001FFF), "\xFE\x7F"));
|
||||
TEST(WRITES(pb_encode_svarint(&s, (int32_t)0xFFFFE000), "\xFF\x7F"));
|
||||
TEST(WRITES(pb_encode_svarint(&s, (int32_t)0x00002000), "\x80\x80\x01"));
|
||||
TEST(WRITES(pb_encode_svarint(&s, (int32_t)0x000FFFFF), "\xFE\xFF\x7F"));
|
||||
TEST(WRITES(pb_encode_svarint(&s, (int32_t)0xFFF00000), "\xFF\xFF\x7F"));
|
||||
TEST(WRITES(pb_encode_svarint(&s, (int32_t)0x00100000), "\x80\x80\x80\x01"));
|
||||
TEST(WRITES(pb_encode_svarint(&s, (int32_t)0x07FFFFFF), "\xFE\xFF\xFF\x7F"));
|
||||
TEST(WRITES(pb_encode_svarint(&s, (int32_t)0xF8000000), "\xFF\xFF\xFF\x7F"));
|
||||
TEST(WRITES(pb_encode_svarint(&s, (int32_t)0x08000000), "\x80\x80\x80\x80\x01"));
|
||||
TEST(WRITES(pb_encode_svarint(&s, (int32_t)0x7FFFFFFF), "\xFE\xFF\xFF\xFF\x0F"));
|
||||
TEST(WRITES(pb_encode_svarint(&s, (int32_t)0x80000000), "\xFF\xFF\xFF\xFF\x0F"));
|
||||
}
|
||||
|
||||
{
|
||||
uint8_t buffer[30];
|
||||
pb_ostream_t s;
|
||||
|
||||
COMMENT("Test pb_encode_tag")
|
||||
TEST(WRITES(pb_encode_tag(&s, PB_WT_STRING, 5), "\x2A"));
|
||||
TEST(WRITES(pb_encode_tag(&s, PB_WT_VARINT, 99), "\x98\x06"));
|
||||
}
|
||||
|
||||
{
|
||||
uint8_t buffer[30];
|
||||
pb_ostream_t s;
|
||||
pb_field_iter_t field;
|
||||
field.tag = 10;
|
||||
|
||||
COMMENT("Test pb_encode_tag_for_field")
|
||||
field.type = PB_LTYPE_SVARINT;
|
||||
TEST(WRITES(pb_encode_tag_for_field(&s, &field), "\x50"));
|
||||
|
||||
field.type = PB_LTYPE_FIXED64;
|
||||
TEST(WRITES(pb_encode_tag_for_field(&s, &field), "\x51"));
|
||||
|
||||
field.type = PB_LTYPE_STRING;
|
||||
TEST(WRITES(pb_encode_tag_for_field(&s, &field), "\x52"));
|
||||
|
||||
field.type = PB_LTYPE_FIXED32;
|
||||
TEST(WRITES(pb_encode_tag_for_field(&s, &field), "\x55"));
|
||||
}
|
||||
|
||||
{
|
||||
uint8_t buffer[30];
|
||||
pb_ostream_t s;
|
||||
|
||||
COMMENT("Test pb_encode_string")
|
||||
TEST(WRITES(pb_encode_string(&s, (const uint8_t*)"abcd", 4), "\x04""abcd"));
|
||||
TEST(WRITES(pb_encode_string(&s, (const uint8_t*)"abcd\x00", 5), "\x05""abcd\x00"));
|
||||
TEST(WRITES(pb_encode_string(&s, (const uint8_t*)"", 0), "\x00"));
|
||||
}
|
||||
|
||||
{
|
||||
uint8_t buffer[30];
|
||||
pb_ostream_t s;
|
||||
uint8_t value = 1;
|
||||
int32_t max = INT32_MAX;
|
||||
int32_t min = INT32_MIN;
|
||||
int64_t lmax = INT64_MAX;
|
||||
int64_t lmin = INT64_MIN;
|
||||
pb_field_iter_t field;
|
||||
|
||||
COMMENT("Test pb_enc_varint and pb_enc_svarint")
|
||||
field.type = PB_LTYPE_VARINT;
|
||||
field.data_size = sizeof(value);
|
||||
field.pData = &value;
|
||||
TEST(WRITES(pb_enc_varint(&s, &field), "\x01"));
|
||||
|
||||
field.type = PB_LTYPE_SVARINT;
|
||||
field.data_size = sizeof(max);
|
||||
field.pData = &max;
|
||||
TEST(WRITES(pb_enc_varint(&s, &field), "\xfe\xff\xff\xff\x0f"));
|
||||
|
||||
field.type = PB_LTYPE_SVARINT;
|
||||
field.data_size = sizeof(min);
|
||||
field.pData = &min;
|
||||
TEST(WRITES(pb_enc_varint(&s, &field), "\xff\xff\xff\xff\x0f"));
|
||||
|
||||
field.type = PB_LTYPE_SVARINT;
|
||||
field.data_size = sizeof(lmax);
|
||||
field.pData = &lmax;
|
||||
TEST(WRITES(pb_enc_varint(&s, &field), "\xFE\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x01"));
|
||||
|
||||
field.type = PB_LTYPE_SVARINT;
|
||||
field.data_size = sizeof(lmin);
|
||||
field.pData = &lmin;
|
||||
TEST(WRITES(pb_enc_varint(&s, &field), "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x01"));
|
||||
}
|
||||
|
||||
{
|
||||
uint8_t buffer[30];
|
||||
pb_ostream_t s;
|
||||
float fvalue;
|
||||
double dvalue;
|
||||
pb_field_iter_t field;
|
||||
|
||||
COMMENT("Test pb_enc_fixed using float")
|
||||
field.type = PB_LTYPE_FIXED32;
|
||||
field.data_size = sizeof(fvalue);
|
||||
field.pData = &fvalue;
|
||||
fvalue = 0.0f;
|
||||
TEST(WRITES(pb_enc_fixed(&s, &field), "\x00\x00\x00\x00"))
|
||||
fvalue = 99.0f;
|
||||
TEST(WRITES(pb_enc_fixed(&s, &field), "\x00\x00\xc6\x42"))
|
||||
fvalue = -12345678.0f;
|
||||
TEST(WRITES(pb_enc_fixed(&s, &field), "\x4e\x61\x3c\xcb"))
|
||||
|
||||
COMMENT("Test pb_enc_fixed using double")
|
||||
field.type = PB_LTYPE_FIXED64;
|
||||
field.data_size = sizeof(dvalue);
|
||||
field.pData = &dvalue;
|
||||
dvalue = 0.0;
|
||||
TEST(WRITES(pb_enc_fixed(&s, &field), "\x00\x00\x00\x00\x00\x00\x00\x00"))
|
||||
dvalue = 99.0;
|
||||
TEST(WRITES(pb_enc_fixed(&s, &field), "\x00\x00\x00\x00\x00\xc0\x58\x40"))
|
||||
dvalue = -12345678.0;
|
||||
TEST(WRITES(pb_enc_fixed(&s, &field), "\x00\x00\x00\xc0\x29\x8c\x67\xc1"))
|
||||
}
|
||||
|
||||
{
|
||||
uint8_t buffer[30];
|
||||
pb_ostream_t s;
|
||||
struct { pb_size_t size; uint8_t bytes[5]; } value = {5, {'x', 'y', 'z', 'z', 'y'}};
|
||||
pb_field_iter_t field;
|
||||
pb_field_iter_begin(&field, BytesMessage_fields, &value);
|
||||
|
||||
COMMENT("Test pb_enc_bytes")
|
||||
TEST(WRITES(pb_enc_bytes(&s, &field), "\x05xyzzy"))
|
||||
value.size = 0;
|
||||
TEST(WRITES(pb_enc_bytes(&s, &field), "\x00"))
|
||||
}
|
||||
|
||||
{
|
||||
uint8_t buffer[30];
|
||||
pb_ostream_t s;
|
||||
char value[30] = "xyzzy";
|
||||
pb_field_iter_t field;
|
||||
pb_field_iter_begin(&field, StringMessage_fields, &value);
|
||||
|
||||
COMMENT("Test pb_enc_string")
|
||||
TEST(WRITES(pb_enc_string(&s, &field), "\x05xyzzy"))
|
||||
value[0] = '\0';
|
||||
TEST(WRITES(pb_enc_string(&s, &field), "\x00"))
|
||||
memset(value, 'x', 10);
|
||||
value[10] = '\0';
|
||||
TEST(WRITES(pb_enc_string(&s, &field), "\x0Axxxxxxxxxx"))
|
||||
}
|
||||
|
||||
{
|
||||
uint8_t buffer[10];
|
||||
pb_ostream_t s;
|
||||
IntegerArray msg = {5, {1, 2, 3, 4, 5}};
|
||||
|
||||
COMMENT("Test pb_encode with int32 array")
|
||||
|
||||
TEST(WRITES(pb_encode(&s, IntegerArray_fields, &msg), "\x0A\x05\x01\x02\x03\x04\x05"))
|
||||
|
||||
msg.data_count = 0;
|
||||
TEST(WRITES(pb_encode(&s, IntegerArray_fields, &msg), ""))
|
||||
|
||||
msg.data_count = 10;
|
||||
TEST(!pb_encode(&s, IntegerArray_fields, &msg))
|
||||
}
|
||||
|
||||
{
|
||||
uint8_t buffer[10];
|
||||
pb_ostream_t s;
|
||||
FloatArray msg = {1, {99.0f}};
|
||||
|
||||
COMMENT("Test pb_encode with float array")
|
||||
|
||||
TEST(WRITES(pb_encode(&s, FloatArray_fields, &msg),
|
||||
"\x0A\x04\x00\x00\xc6\x42"))
|
||||
|
||||
msg.data_count = 0;
|
||||
TEST(WRITES(pb_encode(&s, FloatArray_fields, &msg), ""))
|
||||
|
||||
msg.data_count = 3;
|
||||
TEST(!pb_encode(&s, FloatArray_fields, &msg))
|
||||
}
|
||||
|
||||
{
|
||||
uint8_t buffer[50];
|
||||
pb_ostream_t s;
|
||||
FloatArray msg = {1, {99.0f}};
|
||||
|
||||
COMMENT("Test array size limit in pb_encode")
|
||||
|
||||
s = pb_ostream_from_buffer(buffer, sizeof(buffer));
|
||||
TEST((msg.data_count = 10) && pb_encode(&s, FloatArray_fields, &msg))
|
||||
|
||||
s = pb_ostream_from_buffer(buffer, sizeof(buffer));
|
||||
TEST((msg.data_count = 11) && !pb_encode(&s, FloatArray_fields, &msg))
|
||||
}
|
||||
|
||||
{
|
||||
uint8_t buffer[10];
|
||||
pb_ostream_t s;
|
||||
CallbackArray msg;
|
||||
|
||||
msg.data.funcs.encode = &fieldcallback;
|
||||
|
||||
COMMENT("Test pb_encode with callback field.")
|
||||
TEST(WRITES(pb_encode(&s, CallbackArray_fields, &msg), "\x08\x55"))
|
||||
}
|
||||
|
||||
{
|
||||
uint8_t buffer[10];
|
||||
pb_ostream_t s;
|
||||
IntegerContainer msg = {{5, {1,2,3,4,5}}};
|
||||
|
||||
COMMENT("Test pb_encode with packed array in a submessage.")
|
||||
TEST(WRITES(pb_encode(&s, IntegerContainer_fields, &msg),
|
||||
"\x0A\x07\x0A\x05\x01\x02\x03\x04\x05"))
|
||||
}
|
||||
|
||||
{
|
||||
uint8_t buffer[32];
|
||||
pb_ostream_t s;
|
||||
BytesMessage msg = {{3, "xyz"}};
|
||||
|
||||
COMMENT("Test pb_encode with bytes message.")
|
||||
TEST(WRITES(pb_encode(&s, BytesMessage_fields, &msg),
|
||||
"\x0A\x03xyz"))
|
||||
|
||||
msg.data.size = 17; /* More than maximum */
|
||||
TEST(!pb_encode(&s, BytesMessage_fields, &msg))
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
uint8_t buffer[20];
|
||||
pb_ostream_t s;
|
||||
IntegerContainer msg = {{5, {1,2,3,4,5}}};
|
||||
|
||||
COMMENT("Test pb_encode_delimited.")
|
||||
TEST(WRITES(pb_encode_delimited(&s, IntegerContainer_fields, &msg),
|
||||
"\x09\x0A\x07\x0A\x05\x01\x02\x03\x04\x05"))
|
||||
}
|
||||
|
||||
{
|
||||
IntegerContainer msg = {{5, {1,2,3,4,5}}};
|
||||
size_t size;
|
||||
|
||||
COMMENT("Test pb_get_encoded_size.")
|
||||
TEST(pb_get_encoded_size(&size, IntegerContainer_fields, &msg) &&
|
||||
size == 9);
|
||||
}
|
||||
|
||||
{
|
||||
uint8_t buffer[10];
|
||||
pb_ostream_t s;
|
||||
CallbackContainer msg;
|
||||
CallbackContainerContainer msg2;
|
||||
uint32_t state = 1;
|
||||
|
||||
msg.submsg.data.funcs.encode = &fieldcallback;
|
||||
msg2.submsg.submsg.data.funcs.encode = &fieldcallback;
|
||||
|
||||
COMMENT("Test pb_encode with callback field in a submessage.")
|
||||
TEST(WRITES(pb_encode(&s, CallbackContainer_fields, &msg), "\x0A\x02\x08\x55"))
|
||||
TEST(WRITES(pb_encode(&s, CallbackContainerContainer_fields, &msg2),
|
||||
"\x0A\x04\x0A\x02\x08\x55"))
|
||||
|
||||
/* Misbehaving callback: varying output between calls */
|
||||
msg.submsg.data.funcs.encode = &crazyfieldcallback;
|
||||
msg.submsg.data.arg = &state;
|
||||
msg2.submsg.submsg.data.funcs.encode = &crazyfieldcallback;
|
||||
msg2.submsg.submsg.data.arg = &state;
|
||||
|
||||
TEST(!pb_encode(&s, CallbackContainer_fields, &msg))
|
||||
state = 1;
|
||||
TEST(!pb_encode(&s, CallbackContainerContainer_fields, &msg2))
|
||||
}
|
||||
|
||||
{
|
||||
uint8_t buffer[StringMessage_size];
|
||||
pb_ostream_t s;
|
||||
StringMessage msg = {"0123456789"};
|
||||
|
||||
s = pb_ostream_from_buffer(buffer, sizeof(buffer));
|
||||
|
||||
COMMENT("Test that StringMessage_size is correct")
|
||||
|
||||
TEST(pb_encode(&s, StringMessage_fields, &msg));
|
||||
TEST(s.bytes_written == StringMessage_size);
|
||||
}
|
||||
|
||||
{
|
||||
uint8_t buffer[128];
|
||||
pb_ostream_t s;
|
||||
StringPointerContainer msg = StringPointerContainer_init_zero;
|
||||
char *strs[1] = {NULL};
|
||||
char zstr[] = "Z";
|
||||
|
||||
COMMENT("Test string pointer encoding.");
|
||||
|
||||
msg.rep_str = strs;
|
||||
msg.rep_str_count = 1;
|
||||
TEST(WRITES(pb_encode(&s, StringPointerContainer_fields, &msg), "\x0a\x00"))
|
||||
|
||||
strs[0] = zstr;
|
||||
TEST(WRITES(pb_encode(&s, StringPointerContainer_fields, &msg), "\x0a\x01Z"))
|
||||
}
|
||||
|
||||
if (status != 0)
|
||||
fprintf(stdout, "\n\nSome tests FAILED!\n");
|
||||
|
||||
return status;
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
# Test that different sizes of enum fields are properly encoded and decoded.
|
||||
|
||||
Import('env')
|
||||
|
||||
env.NanopbProto('enumminmax')
|
||||
|
||||
p = env.Program(["enumminmax_unittests.c",])
|
||||
env.RunTest(p)
|
||||
@@ -0,0 +1,22 @@
|
||||
/* Test out-of-order enum values.
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
enum Language {
|
||||
UNKNOWN = 0;
|
||||
ENGLISH_EN_GB = 12;
|
||||
ENGLISH_EN_US = 1;
|
||||
FRENCH_FR_FR = 2;
|
||||
ITALIAN_IT_IT = 3;
|
||||
GERMAN_DE_DE = 4;
|
||||
SPANISH_ES_AR = 13;
|
||||
SPANISH_ES_ES = 5;
|
||||
SPANISH_ES_MX = 14;
|
||||
SWEDISH_SV_SE = 6;
|
||||
DUTCH_NL_NL = 7;
|
||||
KOREAN_KO_KR = 8;
|
||||
JAPANESE_JA_JP = 9;
|
||||
CHINESE_SIMPLIFIED_ZH_CN = 10;
|
||||
CHINESE_TRADITIONAL_ZH_TW = 11;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
#include "unittests.h"
|
||||
#include "enumminmax.pb.h"
|
||||
|
||||
int main()
|
||||
{
|
||||
int status = 0;
|
||||
|
||||
COMMENT("Verify min/max on unsorted enum");
|
||||
{
|
||||
TEST(_Language_MIN == Language_UNKNOWN);
|
||||
TEST(_Language_MAX == Language_SPANISH_ES_MX);
|
||||
TEST(_Language_ARRAYSIZE == (Language_SPANISH_ES_MX+1));
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
# Test that different sizes of enum fields are properly encoded and decoded.
|
||||
|
||||
Import('env')
|
||||
|
||||
env.NanopbProto('enumsizes')
|
||||
|
||||
p = env.Program(["enumsizes_unittests.c",
|
||||
"enumsizes.pb.c",
|
||||
"$COMMON/pb_encode.o",
|
||||
"$COMMON/pb_decode.o",
|
||||
"$COMMON/pb_common.o"])
|
||||
env.RunTest(p)
|
||||
@@ -0,0 +1,86 @@
|
||||
/* Test handling of enums with different value ranges.
|
||||
* Depending on compiler and the packed_enum setting, the datatypes
|
||||
* for enums can be either signed or unsigned. In past this has caused
|
||||
* a bit of a problem for the encoder/decoder (issue #164).
|
||||
*/
|
||||
|
||||
syntax = "proto2";
|
||||
|
||||
import 'nanopb.proto';
|
||||
|
||||
option (nanopb_fileopt).long_names = false;
|
||||
|
||||
enum UnpackedUint8 {
|
||||
option (nanopb_enumopt).packed_enum = false;
|
||||
UU8_MIN = 0;
|
||||
UU8_MAX = 255;
|
||||
}
|
||||
|
||||
enum PackedUint8 {
|
||||
option (nanopb_enumopt).packed_enum = true;
|
||||
PU8_MIN = 0;
|
||||
PU8_MAX = 255;
|
||||
}
|
||||
|
||||
enum UnpackedInt8 {
|
||||
option (nanopb_enumopt).packed_enum = false;
|
||||
UI8_MIN = -128;
|
||||
UI8_MAX = 127;
|
||||
}
|
||||
|
||||
enum PackedInt8 {
|
||||
option (nanopb_enumopt).packed_enum = true;
|
||||
PI8_MIN = -128;
|
||||
PI8_MAX = 127;
|
||||
}
|
||||
|
||||
enum UnpackedUint16 {
|
||||
option (nanopb_enumopt).packed_enum = false;
|
||||
UU16_MIN = 0;
|
||||
UU16_MAX = 65535;
|
||||
}
|
||||
|
||||
enum PackedUint16 {
|
||||
option (nanopb_enumopt).packed_enum = true;
|
||||
PU16_MIN = 0;
|
||||
PU16_MAX = 65535;
|
||||
}
|
||||
|
||||
enum UnpackedInt16 {
|
||||
option (nanopb_enumopt).packed_enum = false;
|
||||
UI16_MIN = -32768;
|
||||
UI16_MAX = 32767;
|
||||
}
|
||||
|
||||
enum PackedInt16 {
|
||||
option (nanopb_enumopt).packed_enum = true;
|
||||
PI16_MIN = -32768;
|
||||
PI16_MAX = 32767;
|
||||
}
|
||||
|
||||
/* Protobuf supports enums up to 32 bits.
|
||||
* The 32 bit case is covered by HugeEnum in the alltypes test.
|
||||
*/
|
||||
|
||||
message PackedEnums {
|
||||
required PackedUint8 u8_min = 1;
|
||||
required PackedUint8 u8_max = 2;
|
||||
required PackedInt8 i8_min = 3;
|
||||
required PackedInt8 i8_max = 4;
|
||||
required PackedUint16 u16_min = 5;
|
||||
required PackedUint16 u16_max = 6;
|
||||
required PackedInt16 i16_min = 7;
|
||||
required PackedInt16 i16_max = 8;
|
||||
}
|
||||
|
||||
message UnpackedEnums {
|
||||
required UnpackedUint8 u8_min = 1;
|
||||
required UnpackedUint8 u8_max = 2;
|
||||
required UnpackedInt8 i8_min = 3;
|
||||
required UnpackedInt8 i8_max = 4;
|
||||
required UnpackedUint16 u16_min = 5;
|
||||
required UnpackedUint16 u16_max = 6;
|
||||
required UnpackedInt16 i16_min = 7;
|
||||
required UnpackedInt16 i16_max = 8;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <pb_decode.h>
|
||||
#include <pb_encode.h>
|
||||
#include "unittests.h"
|
||||
#include "enumsizes.pb.h"
|
||||
|
||||
int main()
|
||||
{
|
||||
int status = 0;
|
||||
|
||||
UnpackedEnums msg1 = {
|
||||
UU8_MIN, UU8_MAX,
|
||||
UI8_MIN, UI8_MAX,
|
||||
UU16_MIN, UU16_MAX,
|
||||
UI16_MIN, UI16_MAX,
|
||||
};
|
||||
|
||||
PackedEnums msg2;
|
||||
UnpackedEnums msg3;
|
||||
uint8_t buf[256];
|
||||
size_t msgsize;
|
||||
|
||||
COMMENT("Step 1: unpacked enums -> protobuf");
|
||||
{
|
||||
pb_ostream_t s = pb_ostream_from_buffer(buf, sizeof(buf));
|
||||
TEST(pb_encode(&s, UnpackedEnums_fields, &msg1));
|
||||
msgsize = s.bytes_written;
|
||||
}
|
||||
|
||||
COMMENT("Step 2: protobuf -> packed enums");
|
||||
{
|
||||
pb_istream_t s = pb_istream_from_buffer(buf, msgsize);
|
||||
TEST(pb_decode(&s, PackedEnums_fields, &msg2));
|
||||
|
||||
TEST(msg1.u8_min == (int)msg2.u8_min);
|
||||
TEST(msg1.u8_max == (int)msg2.u8_max);
|
||||
TEST(msg1.i8_min == (int)msg2.i8_min);
|
||||
TEST(msg1.i8_max == (int)msg2.i8_max);
|
||||
TEST(msg1.u16_min == (int)msg2.u16_min);
|
||||
TEST(msg1.u16_max == (int)msg2.u16_max);
|
||||
TEST(msg1.i16_min == (int)msg2.i16_min);
|
||||
TEST(msg1.i16_max == (int)msg2.i16_max);
|
||||
}
|
||||
|
||||
COMMENT("Step 3: packed enums -> protobuf");
|
||||
{
|
||||
pb_ostream_t s = pb_ostream_from_buffer(buf, sizeof(buf));
|
||||
TEST(pb_encode(&s, PackedEnums_fields, &msg2));
|
||||
msgsize = s.bytes_written;
|
||||
}
|
||||
|
||||
COMMENT("Step 4: protobuf -> unpacked enums");
|
||||
{
|
||||
pb_istream_t s = pb_istream_from_buffer(buf, msgsize);
|
||||
TEST(pb_decode(&s, UnpackedEnums_fields, &msg3));
|
||||
|
||||
TEST(msg1.u8_min == (int)msg3.u8_min);
|
||||
TEST(msg1.u8_max == (int)msg3.u8_max);
|
||||
TEST(msg1.i8_min == (int)msg3.i8_min);
|
||||
TEST(msg1.i8_max == (int)msg3.i8_max);
|
||||
TEST(msg1.u16_min == (int)msg2.u16_min);
|
||||
TEST(msg1.u16_max == (int)msg2.u16_max);
|
||||
TEST(msg1.i16_min == (int)msg2.i16_min);
|
||||
TEST(msg1.i16_max == (int)msg2.i16_max);
|
||||
}
|
||||
|
||||
if (status != 0)
|
||||
fprintf(stdout, "\n\nSome tests FAILED!\n");
|
||||
|
||||
return status;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
# Test enum to string functionality
|
||||
|
||||
Import('env')
|
||||
env.NanopbProto("enum.proto")
|
||||
p = env.Program(["enum_to_string.c", "enum.pb.c"])
|
||||
env.RunTest(p)
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
/* Test enum to string function generation */
|
||||
|
||||
syntax = "proto2";
|
||||
|
||||
import "nanopb.proto";
|
||||
|
||||
option (nanopb_fileopt).enum_to_string = true;
|
||||
|
||||
enum MyEnum {
|
||||
VALUE1 = 1;
|
||||
VALUE2 = 2;
|
||||
VALUE15 = 15;
|
||||
}
|
||||
|
||||
enum MyShortNameEnum {
|
||||
option (nanopb_enumopt).long_names = false;
|
||||
MSNE_VALUE256 = 256;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
#include <stdio.h>
|
||||
#include "unittests.h"
|
||||
#include "enum.pb.h"
|
||||
|
||||
int main()
|
||||
{
|
||||
int status = 0;
|
||||
TEST(strcmp(MyEnum_name(MyEnum_VALUE1), "VALUE1") == 0);
|
||||
TEST(strcmp(MyEnum_name(MyEnum_VALUE2), "VALUE2") == 0);
|
||||
TEST(strcmp(MyEnum_name(MyEnum_VALUE15), "VALUE15") == 0);
|
||||
TEST(strcmp(MyShortNameEnum_name(MSNE_VALUE256), "MSNE_VALUE256") == 0);
|
||||
TEST(strcmp(MyShortNameEnum_name(9999), "unknown") == 0);
|
||||
|
||||
if (status != 0)
|
||||
fprintf(stdout, "\n\nSome tests FAILED!\n");
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -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 = '$BUILD/alltypes')
|
||||
incpath.Append(CPPPATH = '$BUILD/alltypes')
|
||||
|
||||
incpath.NanopbProto(["extensions", "extensions.options"])
|
||||
enc = incpath.Program(["encode_extensions.c", "extensions.pb.c", "$BUILD/alltypes/alltypes.pb$OBJSUFFIX", "$COMMON/pb_encode.o", "$COMMON/pb_common.o"])
|
||||
dec = incpath.Program(["decode_extensions.c", "extensions.pb.c", "$BUILD/alltypes/alltypes.pb$OBJSUFFIX", "$COMMON/pb_decode.o", "$COMMON/pb_common.o"])
|
||||
|
||||
env.RunTest(enc)
|
||||
env.RunTest([dec, "encode_extensions.output"])
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
/* 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"
|
||||
#include "unittests.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
uint8_t buffer[1024];
|
||||
size_t count;
|
||||
pb_istream_t stream;
|
||||
int status = 0;
|
||||
|
||||
AllTypes alltypes = AllTypes_init_zero;
|
||||
int32_t extensionfield1;
|
||||
pb_extension_t ext1 = pb_extension_init_zero;
|
||||
ExtensionMessage extensionfield2 = ExtensionMessage_init_zero;
|
||||
pb_extension_t ext2 = pb_extension_init_zero;
|
||||
|
||||
/* 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(ext1.found)
|
||||
TEST(extensionfield1 == 12345)
|
||||
TEST(ext2.found)
|
||||
TEST(strcmp(extensionfield2.test1, "test") == 0)
|
||||
TEST(extensionfield2.test2 == 54321)
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
/* Tests extension fields.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <pb_encode.h>
|
||||
#include "alltypes.pb.h"
|
||||
#include "extensions.pb.h"
|
||||
#include "test_helpers.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
uint8_t buffer[1024];
|
||||
pb_ostream_t stream;
|
||||
|
||||
AllTypes alltypes = {0};
|
||||
int32_t extensionfield1 = 12345;
|
||||
pb_extension_t ext1 = pb_extension_init_zero;
|
||||
ExtensionMessage extensionfield2 = {"test", 54321};
|
||||
pb_extension_t ext2 = pb_extension_init_zero;
|
||||
|
||||
/* Set up 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;
|
||||
|
||||
/* Set up the output stream */
|
||||
stream = pb_ostream_from_buffer(buffer, sizeof(buffer));
|
||||
|
||||
/* 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 */
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Encoding failed: %s\n", PB_GET_ERROR(&stream));
|
||||
return 1; /* Failure */
|
||||
}
|
||||
|
||||
/* Check that the field tags are properly generated */
|
||||
(void)AllTypes_extensionfield1_tag;
|
||||
(void)ExtensionMessage_AllTypes_extensionfield2_tag;
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
* max_size:16
|
||||
@@ -0,0 +1,19 @@
|
||||
syntax = "proto2";
|
||||
|
||||
import 'alltypes.proto';
|
||||
|
||||
extend AllTypes {
|
||||
optional int32 AllTypes_extensionfield1 = 255 [default = 5];
|
||||
}
|
||||
|
||||
message ExtensionMessage {
|
||||
extend AllTypes {
|
||||
optional ExtensionMessage AllTypes_extensionfield2 = 254;
|
||||
// required ExtensionMessage AllTypes_extensionfield3 = 253; // No longer allowed by protobuf 3
|
||||
repeated ExtensionMessage AllTypes_extensionfield4 = 252;
|
||||
}
|
||||
|
||||
required string test1 = 1;
|
||||
required int32 test2 = 2;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
# Test that the decoder properly handles unknown fields in the input.
|
||||
|
||||
Import("env")
|
||||
|
||||
dec = env.GetBuildPath('$BUILD/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"])
|
||||
|
||||
dec = env.GetBuildPath('$BUILD/basic_stream/${PROGPREFIX}decode_stream${PROGSUFFIX}')
|
||||
env.RunTest('person_with_extra_field_stream.output', [dec, "person_with_extra_field.pb"])
|
||||
env.Compare(["person_with_extra_field_stream.output", "person_with_extra_field.expected"])
|
||||
|
||||
# This uses the backwards compatibility alltypes test, so that
|
||||
# alltypes_with_extra_fields.pb doesn't have to be remade so often.
|
||||
dec2 = env.GetBuildPath('$BUILD/backwards_compatibility/${PROGPREFIX}decode_legacy${PROGSUFFIX}')
|
||||
env.RunTest('alltypes_with_extra_fields.output', [dec2, 'alltypes_with_extra_fields.pb'])
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user