Tests for callback fields

git-svn-id: https://svn.kapsi.fi/jpa/nanopb@974 e3a754e5-d11d-0410-8d38-ebb782a927b9
This commit is contained in:
Petteri Aimonen
2011-09-12 18:53:33 +00:00
parent 35814517ad
commit d4abb63c05
7 changed files with 109 additions and 3 deletions

View File

@@ -201,7 +201,7 @@ Decoding callbacks
bool (*decode)(pb_istream_t *stream, const pb_field_t *field, void *arg); bool (*decode)(pb_istream_t *stream, const pb_field_t *field, void *arg);
When decoding, the callback receives a length-limited substring that reads the contents of a single field. The field tag has already been read. When decoding, the callback receives a length-limited substring that reads the contents of a single field. The field tag has already been read. For *string* and *bytes*, the length value has already been parsed, and is available at *stream->bytes_left*.
The callback will be called multiple times for repeated fields. For packed fields, you can either read multiple values until the stream ends, or leave it to `pb_decode`_ to call your function over and over until all values have been read. The callback will be called multiple times for repeated fields. For packed fields, you can either read multiple values until the stream ends, or leave it to `pb_decode`_ to call your function over and over until all values have been read.

View File

@@ -1,6 +1,6 @@
CFLAGS=-ansi -Wall -Werror -I .. -g -O0 --coverage CFLAGS=-ansi -Wall -Werror -I .. -g -O0 --coverage
LDFLAGS=--coverage LDFLAGS=--coverage
DEPS=../pb_decode.h ../pb_encode.h ../pb.h person.pb.h unittests.h unittestproto.pb.h DEPS=../pb_decode.h ../pb_encode.h ../pb.h person.pb.h callbacks.pb.h unittests.h unittestproto.pb.h
TESTS=test_decode1 test_encode1 decode_unittests encode_unittests TESTS=test_decode1 test_encode1 decode_unittests encode_unittests
all: $(TESTS) run_unittests breakpoints all: $(TESTS) run_unittests breakpoints
@@ -19,6 +19,8 @@ pb_decode.o: ../pb_decode.c $(DEPS)
test_decode1: test_decode1.o pb_decode.o person.pb.o test_decode1: test_decode1.o pb_decode.o person.pb.o
test_encode1: test_encode1.o pb_encode.o person.pb.o test_encode1: test_encode1.o pb_encode.o person.pb.o
test_decode_callbacks: test_decode_callbacks.o pb_decode.o callbacks.pb.o
test_encode_callbacks: test_encode_callbacks.o pb_encode.o callbacks.pb.o
decode_unittests: decode_unittests.o pb_decode.o unittestproto.pb.o decode_unittests: decode_unittests.o pb_decode.o unittestproto.pb.o
encode_unittests: encode_unittests.o pb_encode.o unittestproto.pb.o encode_unittests: encode_unittests.o pb_encode.o unittestproto.pb.o
@@ -35,7 +37,7 @@ coverage: run_unittests
gcov pb_encode.gcda gcov pb_encode.gcda
gcov pb_decode.gcda gcov pb_decode.gcda
run_unittests: decode_unittests encode_unittests test_encode1 test_decode1 run_unittests: decode_unittests encode_unittests test_encode1 test_decode1 test_encode_callbacks test_decode_callbacks
rm -f *.gcda rm -f *.gcda
./decode_unittests > /dev/null ./decode_unittests > /dev/null
@@ -43,6 +45,9 @@ run_unittests: decode_unittests encode_unittests test_encode1 test_decode1
[ "`./test_encode1 | ./test_decode1`" = \ [ "`./test_encode1 | ./test_decode1`" = \
"`./test_encode1 | protoc --decode=Person -I. -I../generator -I/usr/include person.proto`" ] "`./test_encode1 | protoc --decode=Person -I. -I../generator -I/usr/include person.proto`" ]
[ "`./test_encode_callbacks | ./test_decode_callbacks`" = \
"`./test_encode_callbacks | protoc --decode=TestMessage callbacks.proto`" ]
run_fuzztest: test_decode1 run_fuzztest: test_decode1
bash -c 'I=1; while cat /dev/urandom | ./test_decode1 > /dev/null; do I=$$(($$I+1)); echo -en "\r$$I"; done' bash -c 'I=1; while cat /dev/urandom | ./test_decode1 > /dev/null; do I=$$(($$I+1)); echo -en "\r$$I"; done'

16
tests/callbacks.proto Normal file
View File

@@ -0,0 +1,16 @@
/* Todo: write tests for the rest of these fields, currently only stringvalue
* is tested.
*/
message SubMessage {
optional int32 int32value = 1;
}
message TestMessage {
optional string stringvalue = 1;
optional int32 int32value = 2;
optional fixed32 fixed32value = 3;
optional fixed64 fixed64value = 4;
optional SubMessage submsg = 5;
}

View File

@@ -1,3 +1,7 @@
/* A very simple decoding test case, using person.proto.
* Produces output compatible with protoc --decode.
*/
#include <stdio.h> #include <stdio.h>
#include <pb_decode.h> #include <pb_decode.h>
#include "person.pb.h" #include "person.pb.h"

View File

@@ -0,0 +1,44 @@
/* 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"
bool print_string(pb_istream_t *stream, const pb_field_t *field, void *arg)
{
uint8_t buffer[1024];
/* We could read block-by-block to avoid the large buffer... */
if (stream->bytes_left > sizeof(buffer))
return false;
if (!pb_read(stream, buffer, stream->bytes_left))
return false;
/* Print the string, in format comparable with protoc --decode. */
printf("%s: \"%s\"\n", (char*)arg, buffer);
return true;
}
int main()
{
uint8_t buffer[1024];
size_t length = fread(buffer, 1, 1024, stdin);
pb_istream_t stream = pb_istream_from_buffer(buffer, length);
/* Note: empty initializer list initializes the struct with all-0.
* This is recommended so that unused callbacks are set to NULL instead
* of crashing at runtime.
*/
TestMessage testmessage = {};
testmessage.stringvalue.funcs.decode = &print_string;
testmessage.stringvalue.arg = "stringvalue";
if (!pb_decode(&stream, TestMessage_fields, &testmessage))
return 1;
return 0;
}

View File

@@ -1,3 +1,7 @@
/* A very simple encoding test case using person.proto.
* Just puts constant data in the fields.
*/
#include <stdio.h> #include <stdio.h>
#include <pb_encode.h> #include <pb_encode.h>
#include "person.pb.h" #include "person.pb.h"

View File

@@ -0,0 +1,33 @@
/* Encoding testcase for callback fields */
#include <stdio.h>
#include <string.h>
#include <pb_encode.h>
#include "callbacks.pb.h"
bool encode_string(pb_ostream_t *stream, const pb_field_t *field, const void *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));
}
int main()
{
uint8_t buffer[1024];
pb_ostream_t stream = pb_ostream_from_buffer(buffer, 1024);
TestMessage testmessage = {};
testmessage.stringvalue.funcs.encode = &encode_string;
if (!pb_encode(&stream, TestMessage_fields, &testmessage))
return 1;
if (fwrite(buffer, stream.bytes_written, 1, stdout) != 1)
return 2;
return 0;
}