mirror of
https://github.com/protobuf-c/protobuf-c.git
synced 2025-01-14 01:07:57 +08:00
add static init
add test code (beginnings of very thorough test) git-svn-id: https://protobuf-c.googlecode.com/svn/trunk@33 00440858-1255-0410-a3e6-75ea37f81c3a
This commit is contained in:
parent
8542d664b2
commit
ee774e97ad
9
TODO
9
TODO
@ -1,8 +1,15 @@
|
||||
- check over documentation again
|
||||
- handle unknown fields when packing
|
||||
- test code
|
||||
- ensure enums are 32-bit
|
||||
- make messages derive from ProtobufCMessage,
|
||||
which should have the unknown field array
|
||||
- make services derive from ProtobufCService;
|
||||
be usable with a cast.
|
||||
- provide example rpc
|
||||
- use size_t wherever appropriate in generated code, and in uses of that code (eg
|
||||
pack and unpack)
|
||||
|
||||
- ensure enums are 32-bit
|
||||
- support Group (whatever it is)
|
||||
- almost no code generator options are obeyed
|
||||
- ISSUE: strings may not contain NULs
|
||||
|
@ -1,5 +1,5 @@
|
||||
AC_INIT(src/google/protobuf-c/protobuf-c.h)
|
||||
PROTOBUF_C_VERSION=0.0
|
||||
PROTOBUF_C_VERSION=0.1
|
||||
|
||||
AM_INIT_AUTOMAKE(protobuf-c, $PROTOBUF_C_VERSION)
|
||||
PACKAGE=protobuf-c
|
||||
|
@ -33,6 +33,7 @@ void (*protobuf_c_out_of_memory) (void) = protobuf_c_out_of_memory_default;
|
||||
static void *system_alloc(void *allocator_data, size_t size)
|
||||
{
|
||||
void *rv;
|
||||
(void) allocator_data;
|
||||
if (size == 0)
|
||||
return NULL;
|
||||
rv = malloc (size);
|
||||
@ -43,6 +44,7 @@ static void *system_alloc(void *allocator_data, size_t size)
|
||||
|
||||
static void system_free (void *allocator_data, void *data)
|
||||
{
|
||||
(void) allocator_data;
|
||||
if (data)
|
||||
free (data);
|
||||
}
|
||||
@ -621,6 +623,7 @@ required_field_pack_to_buffer (const ProtobufCFieldDescriptor *field,
|
||||
break;
|
||||
case PROTOBUF_C_TYPE_INT32:
|
||||
case PROTOBUF_C_TYPE_UINT32:
|
||||
case PROTOBUF_C_TYPE_ENUM:
|
||||
scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
|
||||
rv += uint32_pack (*(uint32_t *) member, scratch + rv);
|
||||
buffer->append (buffer, rv, scratch);
|
||||
@ -780,7 +783,7 @@ int_range_lookup (unsigned n_ranges,
|
||||
{
|
||||
n = mid - start;
|
||||
}
|
||||
else if (value >= ranges[mid].start_value + (ranges[mid+1].orig_index-ranges[mid].orig_index))
|
||||
else if (value >= ranges[mid].start_value + (int)(ranges[mid+1].orig_index-ranges[mid].orig_index))
|
||||
{
|
||||
unsigned new_start = mid + 1;
|
||||
n = start + n - new_start;
|
||||
@ -795,7 +798,7 @@ int_range_lookup (unsigned n_ranges,
|
||||
unsigned range_size = ranges[start+1].orig_index - start_orig_index;
|
||||
|
||||
if (ranges[start].start_value <= value
|
||||
&& value < ranges[start].start_value + range_size)
|
||||
&& value < (int)(ranges[start].start_value + range_size))
|
||||
return (value - ranges[start].start_value) + start_orig_index;
|
||||
}
|
||||
return -1;
|
||||
@ -1011,9 +1014,9 @@ parse_required_member (ScannedMember *scanned_member,
|
||||
return 1;
|
||||
|
||||
case PROTOBUF_C_TYPE_ENUM:
|
||||
if (wire_type != PROTOBUF_C_WIRE_TYPE_32BIT)
|
||||
if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT)
|
||||
return 0;
|
||||
*(uint32_t*)member = parse_fixed_uint32 (data);
|
||||
*(uint32_t*)member = parse_uint32 (len, data);
|
||||
return 1;
|
||||
|
||||
case PROTOBUF_C_TYPE_STRING:
|
||||
@ -1159,7 +1162,7 @@ protobuf_c_message_unpack (const ProtobufCMessageDescriptor *desc,
|
||||
|
||||
while (rem > 0)
|
||||
{
|
||||
size_t tag;
|
||||
uint32_t tag;
|
||||
ProtobufCWireType wire_type;
|
||||
size_t used = parse_tag_and_wiretype (rem, at, &tag, &wire_type);
|
||||
const ProtobufCFieldDescriptor *field;
|
||||
@ -1230,7 +1233,7 @@ protobuf_c_message_unpack (const ProtobufCMessageDescriptor *desc,
|
||||
tmp.len = 4;
|
||||
break;
|
||||
}
|
||||
if (in_slab_index == (1<<(which_slab+4)))
|
||||
if (in_slab_index == (1U<<(which_slab+4)))
|
||||
{
|
||||
size_t size;
|
||||
in_slab_index = 0;
|
||||
@ -1278,7 +1281,7 @@ protobuf_c_message_unpack (const ProtobufCMessageDescriptor *desc,
|
||||
/* do real parsing */
|
||||
for (i_slab = 0; i_slab <= which_slab; i_slab++)
|
||||
{
|
||||
unsigned max = (i_slab == which_slab) ? in_slab_index : (1<<(i_slab+4));
|
||||
unsigned max = (i_slab == which_slab) ? in_slab_index : (1U<<(i_slab+4));
|
||||
ScannedMember *slab = scanned_member_slabs[i_slab];
|
||||
unsigned j;
|
||||
for (j = 0; j < max; j++)
|
||||
|
@ -106,7 +106,7 @@ typedef struct _ProtobufCFieldDescriptor ProtobufCFieldDescriptor;
|
||||
struct _ProtobufCFieldDescriptor
|
||||
{
|
||||
const char *name;
|
||||
int id;
|
||||
uint32_t id;
|
||||
ProtobufCLabel label;
|
||||
ProtobufCType type;
|
||||
unsigned quantifier_offset;
|
||||
|
@ -66,6 +66,10 @@ void BytesFieldGenerator::GenerateStructMembers(io::Printer* printer) const
|
||||
break;
|
||||
}
|
||||
}
|
||||
void BytesFieldGenerator::GenerateStaticInit(io::Printer* printer) const
|
||||
{
|
||||
printer->Print("{0,NULL}");
|
||||
}
|
||||
void BytesFieldGenerator::GenerateDescriptorInitializer(io::Printer* printer) const
|
||||
{
|
||||
GenerateDescriptorInitializerGeneric(printer, true, "BYTES", "NULL");
|
||||
|
@ -40,6 +40,7 @@ class BytesFieldGenerator : public FieldGenerator {
|
||||
// implements FieldGenerator ---------------------------------------
|
||||
void GenerateStructMembers(io::Printer* printer) const;
|
||||
void GenerateDescriptorInitializer(io::Printer* printer) const;
|
||||
void GenerateStaticInit(io::Printer* printer) const;
|
||||
|
||||
private:
|
||||
map<string, string> variables_;
|
||||
|
@ -71,6 +71,20 @@ void EnumFieldGenerator::GenerateStructMembers(io::Printer* printer) const
|
||||
break;
|
||||
}
|
||||
}
|
||||
void EnumFieldGenerator::GenerateStaticInit(io::Printer* printer) const
|
||||
{
|
||||
// TODO: use symbolic name
|
||||
switch (descriptor_->label()) {
|
||||
case FieldDescriptor::LABEL_REQUIRED:
|
||||
case FieldDescriptor::LABEL_OPTIONAL:
|
||||
printer->Print(variables_, "$default$");
|
||||
break;
|
||||
case FieldDescriptor::LABEL_REPEATED:
|
||||
// no support for default?
|
||||
printer->Print("0,NULL");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void EnumFieldGenerator::GenerateDescriptorInitializer(io::Printer* printer) const
|
||||
{
|
||||
|
@ -40,6 +40,7 @@ class EnumFieldGenerator : public FieldGenerator {
|
||||
// implements FieldGenerator ---------------------------------------
|
||||
void GenerateStructMembers(io::Printer* printer) const;
|
||||
void GenerateDescriptorInitializer(io::Printer* printer) const;
|
||||
void GenerateStaticInit(io::Printer* printer) const;
|
||||
|
||||
private:
|
||||
map<string, string> variables_;
|
||||
|
@ -48,6 +48,10 @@ class FieldGenerator {
|
||||
// Generate a static initializer for this field.
|
||||
virtual void GenerateDescriptorInitializer(io::Printer* printer) const = 0;
|
||||
|
||||
// Generate members to initialize this field from a static initializer
|
||||
virtual void GenerateStaticInit(io::Printer* printer) const = 0;
|
||||
|
||||
|
||||
protected:
|
||||
void GenerateDescriptorInitializerGeneric(io::Printer* printer,
|
||||
bool optional_uses_has,
|
||||
|
@ -127,6 +127,9 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
|
||||
for (int i = 0; i < file_->message_type_count(); i++) {
|
||||
message_generators_[i]->GenerateEnumDefinitions(printer);
|
||||
}
|
||||
for (int i = 0; i < file_->enum_type_count(); i++) {
|
||||
enum_generators_[i]->GenerateDefinition(printer);
|
||||
}
|
||||
|
||||
// Generate class definitions.
|
||||
printer->Print("\n/* --- messages --- */\n\n");
|
||||
@ -156,7 +159,7 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
|
||||
|
||||
printer->Print("\n/* --- descriptors --- */\n\n");
|
||||
for (int i = 0; i < file_->enum_type_count(); i++) {
|
||||
enum_generators_[i]->GenerateDefinition(printer);
|
||||
enum_generators_[i]->GenerateDescriptorDeclarations(printer);
|
||||
}
|
||||
for (int i = 0; i < file_->message_type_count(); i++) {
|
||||
message_generators_[i]->GenerateDescriptorDeclarations(printer);
|
||||
|
@ -98,6 +98,8 @@ GenerateStructDefinition(io::Printer* printer) {
|
||||
|
||||
std::map<string, string> vars;
|
||||
vars["classname"] = FullNameToC(descriptor_->full_name());
|
||||
vars["lcclassname"] = FullNameToLower(descriptor_->full_name());
|
||||
vars["ucclassname"] = FullNameToUpper(descriptor_->full_name());
|
||||
vars["field_count"] = SimpleItoa(descriptor_->field_count());
|
||||
if (dllexport_decl_.empty()) {
|
||||
vars["dllexport"] = "";
|
||||
@ -121,6 +123,16 @@ GenerateStructDefinition(io::Printer* printer) {
|
||||
printer->Print(vars, " /* private */\n");
|
||||
printer->Print(vars, " ProtobufCMessageUnknownFieldArray unknown_field_array;\n");
|
||||
printer->Print(vars, "};\n\n");
|
||||
|
||||
printer->Print(vars, "#define $ucclassname$__INIT \\\n"
|
||||
" { &$lcclassname$__descriptor");
|
||||
for (int i = 0; i < descriptor_->field_count(); i++) {
|
||||
const FieldDescriptor *field = descriptor_->field(i);
|
||||
printer->Print(", ");
|
||||
field_generators_.get(field).GenerateStaticInit(printer);
|
||||
}
|
||||
printer->Print(" }\n");
|
||||
|
||||
}
|
||||
|
||||
void MessageGenerator::
|
||||
|
@ -66,6 +66,9 @@ class MessageGenerator {
|
||||
// Generate definitions for this class and all its nested types.
|
||||
void GenerateStructDefinition(io::Printer* printer);
|
||||
|
||||
// Generate __INIT macro for populating this structure
|
||||
void GenerateStructStaticInitMacro(io::Printer* printer);
|
||||
|
||||
// Generate standard helper functions declarations for this message.
|
||||
void GenerateHelperFunctionDeclarations(io::Printer* printer);
|
||||
|
||||
|
@ -57,6 +57,18 @@ void MessageFieldGenerator::GenerateStructMembers(io::Printer* printer) const
|
||||
break;
|
||||
}
|
||||
}
|
||||
void MessageFieldGenerator::GenerateStaticInit(io::Printer* printer) const
|
||||
{
|
||||
switch (descriptor_->label()) {
|
||||
case FieldDescriptor::LABEL_REQUIRED:
|
||||
case FieldDescriptor::LABEL_OPTIONAL:
|
||||
printer->Print("NULL");
|
||||
break;
|
||||
case FieldDescriptor::LABEL_REPEATED:
|
||||
printer->Print("0,NULL");
|
||||
break;
|
||||
}
|
||||
}
|
||||
void MessageFieldGenerator::GenerateDescriptorInitializer(io::Printer* printer) const
|
||||
{
|
||||
string addr = "&" + FullNameToLower(descriptor_->message_type()->full_name()) + "__descriptor";
|
||||
|
@ -40,6 +40,7 @@ class MessageFieldGenerator : public FieldGenerator {
|
||||
// implements FieldGenerator ---------------------------------------
|
||||
void GenerateStructMembers(io::Printer* printer) const;
|
||||
void GenerateDescriptorInitializer(io::Printer* printer) const;
|
||||
void GenerateStaticInit(io::Printer* printer) const;
|
||||
|
||||
private:
|
||||
|
||||
|
@ -81,6 +81,18 @@ void PrimitiveFieldGenerator::GenerateStructMembers(io::Printer* printer) const
|
||||
break;
|
||||
}
|
||||
}
|
||||
void PrimitiveFieldGenerator::GenerateStaticInit(io::Printer* printer) const
|
||||
{
|
||||
switch (descriptor_->label()) {
|
||||
case FieldDescriptor::LABEL_REQUIRED:
|
||||
case FieldDescriptor::LABEL_OPTIONAL:
|
||||
printer->Print("0");
|
||||
break;
|
||||
case FieldDescriptor::LABEL_REPEATED:
|
||||
printer->Print("0,NULL");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void PrimitiveFieldGenerator::GenerateDescriptorInitializer(io::Printer* printer) const
|
||||
{
|
||||
|
@ -40,6 +40,7 @@ class PrimitiveFieldGenerator : public FieldGenerator {
|
||||
// implements FieldGenerator ---------------------------------------
|
||||
void GenerateStructMembers(io::Printer* printer) const;
|
||||
void GenerateDescriptorInitializer(io::Printer* printer) const;
|
||||
void GenerateStaticInit(io::Printer* printer) const;
|
||||
|
||||
private:
|
||||
|
||||
|
@ -63,6 +63,19 @@ void StringFieldGenerator::GenerateStructMembers(io::Printer* printer) const
|
||||
break;
|
||||
}
|
||||
}
|
||||
void StringFieldGenerator::GenerateStaticInit(io::Printer* printer) const
|
||||
{
|
||||
// TODO: no support for defaults?
|
||||
switch (descriptor_->label()) {
|
||||
case FieldDescriptor::LABEL_REQUIRED:
|
||||
case FieldDescriptor::LABEL_OPTIONAL:
|
||||
printer->Print("NULL");
|
||||
break;
|
||||
case FieldDescriptor::LABEL_REPEATED:
|
||||
printer->Print("0,NULL");
|
||||
break;
|
||||
}
|
||||
}
|
||||
void StringFieldGenerator::GenerateDescriptorInitializer(io::Printer* printer) const
|
||||
{
|
||||
GenerateDescriptorInitializerGeneric(printer, false, "STRING", "NULL");
|
||||
|
@ -40,6 +40,7 @@ class StringFieldGenerator : public FieldGenerator {
|
||||
// implements FieldGenerator ---------------------------------------
|
||||
void GenerateStructMembers(io::Printer* printer) const;
|
||||
void GenerateDescriptorInitializer(io::Printer* printer) const;
|
||||
void GenerateStaticInit(io::Printer* printer) const;
|
||||
|
||||
private:
|
||||
map<string, string> variables_;
|
||||
|
@ -1,17 +1,36 @@
|
||||
check_PROGRAMS = test-generated-code
|
||||
check_PROGRAMS = test-generated-code test-generated-code2
|
||||
noinst_PROGRAMS = cxx-generate-packed-data
|
||||
INCLUDES = -I$(srcdir)/..
|
||||
test_generated_code_SOURCES = \
|
||||
test-generated-code.c \
|
||||
generated-code/test.pb-c.c
|
||||
test_generated_code_LDADD = \
|
||||
../libprotobuf-c.la
|
||||
test_generated_code2_SOURCES = \
|
||||
test-generated-code2.c \
|
||||
generated-code/test-full.pb-c.c
|
||||
test_generated_code2_LDADD = \
|
||||
../libprotobuf-c.la
|
||||
cxx_generate_packed_data_SOURCES = \
|
||||
cxx-generate-packed-data.cc generated-code/test-full.pb.cc
|
||||
cxx_generate_packed_data_LDADD = -lprotobuf
|
||||
|
||||
generated-code/test.pb-c.c generated-code/test.pb-c.h: ../protoc-c $(srcdir)/test.proto
|
||||
rm -rf generated-code
|
||||
mkdir generated-code
|
||||
mkdir -p generated-code
|
||||
../protoc-c -I$(srcdir) --c_out=generated-code $(srcdir)/test.proto
|
||||
generated-code/test-full.pb-c.c generated-code/test-full.pb-c.h: ../protoc-c $(srcdir)/test-full.proto
|
||||
mkdir -p generated-code
|
||||
../protoc-c -I$(srcdir) --c_out=generated-code $(srcdir)/test-full.proto
|
||||
generated-code/test-full.pb.cc generated-code/test-full.pb.h: $(srcdir)/test-full.proto
|
||||
mkdir -p generated-code
|
||||
protoc -I$(srcdir) --cpp_out=generated-code $(srcdir)/test-full.proto
|
||||
generated-code/test-full-cxx-output.inc: cxx-generate-packed-data
|
||||
./cxx-generate-packed-data > generated-code/test-full-cxx-output.inc
|
||||
|
||||
BUILT_SOURCES = generated-code/test.pb-c.c generated-code/test.pb-c.h
|
||||
BUILT_SOURCES = generated-code/test.pb-c.c generated-code/test.pb-c.h \
|
||||
generated-code/test-full.pb-c.c generated-code/test-full.pb-c.h \
|
||||
generated-code/test-full.pb.cc generated-code/test-full.pb.h \
|
||||
generated-code/test-full-cxx-output.inc
|
||||
DISTCLEANFILES = $(BUILT_SOURCES)
|
||||
TESTS = test-generated-code
|
||||
EXTRA_DIST = test.proto
|
||||
TESTS = test-generated-code test-generated-code2
|
||||
EXTRA_DIST = test.proto test-full.proto
|
||||
|
57
src/test/cxx-generate-packed-data.cc
Normal file
57
src/test/cxx-generate-packed-data.cc
Normal file
@ -0,0 +1,57 @@
|
||||
/* generate byte arrays that match the constructs in test-generated-code2.c.
|
||||
* these are tested against eachother to make sure the c and c++ agree. */
|
||||
|
||||
#include "generated-code/test-full.pb.h"
|
||||
|
||||
using namespace foo;
|
||||
|
||||
static void
|
||||
dump_message_bytes(google::protobuf::Message *message,
|
||||
const char *label)
|
||||
{
|
||||
std::string rv;
|
||||
unsigned char *bytes;
|
||||
unsigned len;
|
||||
if (!message->SerializeToString(&rv))
|
||||
assert(0);
|
||||
bytes = (unsigned char *) rv.data();
|
||||
len = rv.size();
|
||||
printf ("static const uint8_t %s[%u] = { ", label, len);
|
||||
for (unsigned i = 0; i < len; i++) {
|
||||
if (i)
|
||||
printf (", ");
|
||||
printf ("0x%02x", bytes[i]);
|
||||
}
|
||||
printf (" };\n");
|
||||
}
|
||||
|
||||
static void
|
||||
dump_test_enum_small (void)
|
||||
{
|
||||
TestMessRequiredEnumSmall es;
|
||||
es.set_test(VALUE);
|
||||
dump_message_bytes(&es, "test_enum_small_VALUE");
|
||||
es.set_test(OTHER_VALUE);
|
||||
dump_message_bytes(&es, "test_enum_small_OTHER_VALUE");
|
||||
}
|
||||
static void
|
||||
dump_test_enum_big (void)
|
||||
{
|
||||
TestMessRequiredEnum eb;
|
||||
eb.set_test(VALUE0); dump_message_bytes(&eb, "test_enum_big_VALUE0");
|
||||
eb.set_test(VALUE127); dump_message_bytes(&eb, "test_enum_big_VALUE127");
|
||||
eb.set_test(VALUE128); dump_message_bytes(&eb, "test_enum_big_VALUE128");
|
||||
eb.set_test(VALUE16383); dump_message_bytes(&eb, "test_enum_big_VALUE16383");
|
||||
eb.set_test(VALUE16384); dump_message_bytes(&eb, "test_enum_big_VALUE16384");
|
||||
eb.set_test(VALUE2097151); dump_message_bytes(&eb, "test_enum_big_VALUE2097151");
|
||||
eb.set_test(VALUE2097152); dump_message_bytes(&eb, "test_enum_big_VALUE2097152");
|
||||
eb.set_test(VALUE268435455); dump_message_bytes(&eb, "test_enum_big_VALUE268435455");
|
||||
eb.set_test(VALUE268435456); dump_message_bytes(&eb, "test_enum_big_VALUE268435456");
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
dump_test_enum_small ();
|
||||
dump_test_enum_big ();
|
||||
return 0;
|
||||
}
|
143
src/test/test-full.proto
Normal file
143
src/test/test-full.proto
Normal file
@ -0,0 +1,143 @@
|
||||
package foo;
|
||||
|
||||
message SubMess {
|
||||
required int32 test = 4;
|
||||
};
|
||||
|
||||
enum TestEnumSmall {
|
||||
VALUE = 0;
|
||||
OTHER_VALUE = 1;
|
||||
}
|
||||
enum TestEnum {
|
||||
VALUE0 = 0;
|
||||
VALUE127 = 127;
|
||||
VALUE128 = 128;
|
||||
VALUE16383 = 16383;
|
||||
VALUE16384 = 16384;
|
||||
VALUE2097151 = 2097151;
|
||||
VALUE2097152 = 2097152;
|
||||
VALUE268435455 = 268435455;
|
||||
VALUE268435456 = 268435456;
|
||||
};
|
||||
|
||||
message TestFieldNo15 { // should use 1 byte header
|
||||
required string test = 15;
|
||||
}
|
||||
message TestFieldNo16 { // requires 2 byte header
|
||||
required string test = 16;
|
||||
}
|
||||
message TestFieldNo2047 { // should use 2 byte header
|
||||
required string test = 2047;
|
||||
}
|
||||
message TestFieldNo2048 { // requires 3 byte header
|
||||
required string test = 2048;
|
||||
}
|
||||
message TestFieldNo262143 { // should use 3 byte header
|
||||
required string test = 262143;
|
||||
}
|
||||
message TestFieldNo262144 { // requires 4 byte header
|
||||
required string test = 262144;
|
||||
}
|
||||
message TestFieldNo33554431 { // should use 4 byte header
|
||||
required string test = 33554431;
|
||||
}
|
||||
message TestFieldNo33554432 { // requires 5 byte header
|
||||
required string test = 33554432;
|
||||
}
|
||||
|
||||
message TestMess {
|
||||
repeated int32 test_int32 = 1;
|
||||
repeated sint32 test_sint32 = 2;
|
||||
repeated sfixed32 test_sfixed32 = 3;
|
||||
repeated int64 test_int64 = 4;
|
||||
repeated sint64 test_sint64 = 5;
|
||||
repeated sfixed64 test_sfixed64 = 6;
|
||||
repeated uint32 test_uint32 = 7;
|
||||
repeated fixed32 test_fixed32 = 8;
|
||||
repeated uint64 test_uint64 = 9;
|
||||
repeated fixed64 test_fixed64 = 10;
|
||||
repeated float test_float = 11;
|
||||
repeated double test_double = 12;
|
||||
repeated bool test_bool = 13;
|
||||
repeated TestEnumSmall test_enum_small = 14;
|
||||
repeated TestEnum test_enum = 15;
|
||||
repeated string test_string = 16;
|
||||
repeated bytes test_bytes = 17;
|
||||
repeated SubMess test_message = 18;
|
||||
}
|
||||
|
||||
message TestMessOptional {
|
||||
optional int32 test_int32 = 1;
|
||||
optional sint32 test_sint32 = 2;
|
||||
optional sfixed32 test_sfixed32 = 3;
|
||||
optional int64 test_int64 = 4;
|
||||
optional sint64 test_sint64 = 5;
|
||||
optional sfixed64 test_sfixed64 = 6;
|
||||
optional uint32 test_uint32 = 7;
|
||||
optional fixed32 test_fixed32 = 8;
|
||||
optional uint64 test_uint64 = 9;
|
||||
optional fixed64 test_fixed64 = 10;
|
||||
optional float test_float = 11;
|
||||
optional double test_double = 12;
|
||||
optional bool test_bool = 13;
|
||||
optional TestEnum test_enum = 14;
|
||||
optional string test_string = 15;
|
||||
optional bytes test_bytes = 16;
|
||||
optional SubMess test_message = 17;
|
||||
}
|
||||
|
||||
message TestMessRequiredInt32 {
|
||||
required int32 test = 42;
|
||||
}
|
||||
message TestMessRequiredSInt32 {
|
||||
required sint32 test = 43;
|
||||
}
|
||||
message TestMessRequiredSFixed32 {
|
||||
required sfixed32 test = 100;
|
||||
}
|
||||
message TestMessRequiredInt64 {
|
||||
required int64 test = 1;
|
||||
}
|
||||
message TestMessRequiredSInt64 {
|
||||
required sint64 test = 11;
|
||||
}
|
||||
message TestMessRequiredSFixed64 {
|
||||
required sfixed64 test = 12;
|
||||
}
|
||||
message TestMessRequiredUInt32 {
|
||||
required uint32 test = 1;
|
||||
}
|
||||
message TestMessRequiredFixed32 {
|
||||
required fixed32 test = 1;
|
||||
}
|
||||
message TestMessRequiredUInt64 {
|
||||
required uint64 test = 1;
|
||||
}
|
||||
message TestMessRequiredFixed64 {
|
||||
required fixed64 test = 1;
|
||||
}
|
||||
message TestMessRequiredFloat {
|
||||
required float test = 1;
|
||||
}
|
||||
message TestMessRequiredDouble {
|
||||
required double test = 1;
|
||||
}
|
||||
message TestMessRequiredBool {
|
||||
required bool test = 1;
|
||||
}
|
||||
message TestMessRequiredEnum {
|
||||
required TestEnum test = 1;
|
||||
}
|
||||
message TestMessRequiredEnumSmall {
|
||||
required TestEnumSmall test = 1;
|
||||
}
|
||||
message TestMessRequiredString {
|
||||
required string test = 1;
|
||||
}
|
||||
message TestMessRequiredBytes {
|
||||
required bytes test = 1;
|
||||
}
|
||||
message TestMessRequiredMessage {
|
||||
required SubMess test = 1;
|
||||
}
|
||||
|
186
src/test/test-generated-code2.c
Normal file
186
src/test/test-generated-code2.c
Normal file
@ -0,0 +1,186 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "generated-code/test-full.pb-c.h"
|
||||
#include "generated-code/test-full-cxx-output.inc"
|
||||
|
||||
/* ==== helper functions ==== */
|
||||
static protobuf_c_boolean
|
||||
are_bytes_equal (unsigned actual_len,
|
||||
const uint8_t *actual_data,
|
||||
unsigned expected_len,
|
||||
const uint8_t *expected_data)
|
||||
{
|
||||
if (actual_len != expected_len)
|
||||
return 0;
|
||||
return memcmp (actual_data, expected_data, actual_len) == 0;
|
||||
}
|
||||
#define TEST_VERSUS_STATIC_ARRAY(actual_len, actual_data, buf) \
|
||||
assert(are_bytes_equal(actual_len,actual_data, \
|
||||
sizeof(buf), buf))
|
||||
|
||||
/* rv is unpacked message */
|
||||
static void *
|
||||
test_compare_pack_methods (ProtobufCMessage *message,
|
||||
size_t *packed_len_out,
|
||||
uint8_t **packed_out)
|
||||
{
|
||||
unsigned char scratch[16];
|
||||
ProtobufCBufferSimple bs = PROTOBUF_C_BUFFER_SIMPLE_INIT (scratch);
|
||||
size_t siz1 = protobuf_c_message_get_packed_size (message);
|
||||
size_t siz2;
|
||||
size_t siz3 = protobuf_c_message_pack_to_buffer (message, &bs.base);
|
||||
void *packed1 = malloc (siz1);
|
||||
void *rv;
|
||||
assert (packed1 != NULL);
|
||||
assert (siz1 == siz3);
|
||||
siz2 = protobuf_c_message_pack (message, packed1);
|
||||
assert (siz1 == siz2);
|
||||
assert (bs.len == siz1);
|
||||
assert (memcmp (bs.data, packed1, siz1) == 0);
|
||||
rv = protobuf_c_message_unpack (message->descriptor, NULL, siz1, packed1);
|
||||
assert (rv != NULL);
|
||||
PROTOBUF_C_BUFFER_SIMPLE_CLEAR (&bs);
|
||||
*packed_len_out = siz1;
|
||||
*packed_out = packed1;
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* === the actual tests === */
|
||||
|
||||
static void test_enum_small (void)
|
||||
{
|
||||
Foo__TestMessRequiredEnumSmall small = FOO__TEST_MESS_REQUIRED_ENUM_SMALL__INIT;
|
||||
size_t len;
|
||||
uint8_t *data;
|
||||
Foo__TestMessRequiredEnumSmall *unpacked;
|
||||
|
||||
small.test = FOO__TEST_ENUM_SMALL__VALUE;
|
||||
unpacked = test_compare_pack_methods ((ProtobufCMessage*)&small, &len, &data);
|
||||
assert (unpacked->test == FOO__TEST_ENUM_SMALL__VALUE);
|
||||
foo__test_mess_required_enum_small__free_unpacked (unpacked, NULL);
|
||||
TEST_VERSUS_STATIC_ARRAY (len, data, test_enum_small_VALUE);
|
||||
free (data);
|
||||
|
||||
small.test = FOO__TEST_ENUM_SMALL__OTHER_VALUE;
|
||||
unpacked = test_compare_pack_methods ((ProtobufCMessage*)&small, &len, &data);
|
||||
assert (unpacked->test == FOO__TEST_ENUM_SMALL__OTHER_VALUE);
|
||||
foo__test_mess_required_enum_small__free_unpacked (unpacked, NULL);
|
||||
TEST_VERSUS_STATIC_ARRAY (len, data, test_enum_small_OTHER_VALUE);
|
||||
free (data);
|
||||
}
|
||||
|
||||
static void test_enum_big (void)
|
||||
{
|
||||
Foo__TestMessRequiredEnum big = FOO__TEST_MESS_REQUIRED_ENUM__INIT;
|
||||
size_t len;
|
||||
uint8_t *data;
|
||||
Foo__TestMessRequiredEnumSmall *unpacked;
|
||||
|
||||
#define DO_ONE_TEST(shortname, numeric_value, encoded_len) \
|
||||
do{ \
|
||||
big.test = FOO__TEST_ENUM__##shortname; \
|
||||
unpacked = test_compare_pack_methods ((ProtobufCMessage*)&big, &len, &data); \
|
||||
assert (unpacked->test == FOO__TEST_ENUM__##shortname); \
|
||||
foo__test_mess_required_enum__free_unpacked (unpacked, NULL); \
|
||||
TEST_VERSUS_STATIC_ARRAY (len, data, test_enum_big_##shortname); \
|
||||
assert (encoded_len + 1 == len); \
|
||||
assert (big.test == numeric_value); \
|
||||
free (data); \
|
||||
}while(0)
|
||||
|
||||
DO_ONE_TEST(VALUE0, 0, 1);
|
||||
DO_ONE_TEST(VALUE127, 127, 1);
|
||||
DO_ONE_TEST(VALUE128, 128, 2);
|
||||
DO_ONE_TEST(VALUE16383, 16383, 2);
|
||||
DO_ONE_TEST(VALUE16384, 16384, 3);
|
||||
DO_ONE_TEST(VALUE2097151, 2097151, 3);
|
||||
DO_ONE_TEST(VALUE2097152, 2097152, 4);
|
||||
DO_ONE_TEST(VALUE268435455, 268435455, 4);
|
||||
DO_ONE_TEST(VALUE268435456, 268435456, 5);
|
||||
|
||||
#undef DO_ONE_TEST
|
||||
}
|
||||
|
||||
/* === simple testing framework === */
|
||||
|
||||
typedef void (*TestFunc) (void);
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
TestFunc func;
|
||||
} Test;
|
||||
|
||||
static Test tests[] =
|
||||
{
|
||||
{ "small enums", test_enum_small },
|
||||
{ "big enums", test_enum_big },
|
||||
//{ "test field numbers", test_field_numbers },
|
||||
//{ "test repeated int32" ,test_repeated_int32 },
|
||||
//{ "test repeated sint32" ,test_repeated_sint32 },
|
||||
//{ "test repeated sfixed32" ,test_repeated_sfixed32 },
|
||||
//{ "test repeated int64" ,test_repeated_int64 },
|
||||
//{ "test repeated sint64" ,test_repeated_sint64 },
|
||||
//{ "test repeated sfixed64" ,test_repeated_sfixed64 },
|
||||
//{ "test repeated uint32" ,test_repeated_uint32 },
|
||||
//{ "test repeated fixed32" ,test_repeated_fixed32 },
|
||||
//{ "test repeated uint64" ,test_repeated_uint64 },
|
||||
//{ "test repeated fixed64" ,test_repeated_fixed64 },
|
||||
//{ "test repeated float" ,test_repeated_float },
|
||||
//{ "test repeated double" ,test_repeated_double },
|
||||
//{ "test repeated bool" ,test_repeated_bool },
|
||||
//{ "test repeated TestEnumSmall" ,test_repeated_TestEnumSmall },
|
||||
//{ "test repeated TestEnum" ,test_repeated_TestEnum },
|
||||
//{ "test repeated string" ,test_repeated_string },
|
||||
//{ "test repeated bytes" ,test_repeated_bytes },
|
||||
//{ "test repeated SubMess" ,test_repeated_SubMess },
|
||||
//{ "test optional int32" ,test_optional_int32 },
|
||||
//{ "test optional sint32" ,test_optional_sint32 },
|
||||
//{ "test optional sfixed32" ,test_optional_sfixed32 },
|
||||
//{ "test optional int64" ,test_optional_int64 },
|
||||
//{ "test optional sint64" ,test_optional_sint64 },
|
||||
//{ "test optional sfixed64" ,test_optional_sfixed64 },
|
||||
//{ "test optional uint32" ,test_optional_uint32 },
|
||||
//{ "test optional fixed32" ,test_optional_fixed32 },
|
||||
//{ "test optional uint64" ,test_optional_uint64 },
|
||||
//{ "test optional fixed64" ,test_optional_fixed64 },
|
||||
//{ "test optional float" ,test_optional_float },
|
||||
//{ "test optional double" ,test_optional_double },
|
||||
//{ "test optional bool" ,test_optional_bool },
|
||||
//{ "test optional TestEnumSmall" ,test_optional_TestEnumSmall },
|
||||
//{ "test optional TestEnum" ,test_optional_TestEnum },
|
||||
//{ "test optional string" ,test_optional_string },
|
||||
//{ "test optional bytes" ,test_optional_bytes },
|
||||
//{ "test optional SubMess" ,test_optional_SubMess },
|
||||
//{ "test required int32" ,test_required_int32 },
|
||||
//{ "test required sint32" ,test_required_sint32 },
|
||||
//{ "test required sfixed32" ,test_required_sfixed32 },
|
||||
//{ "test required int64" ,test_required_int64 },
|
||||
//{ "test required sint64" ,test_required_sint64 },
|
||||
//{ "test required sfixed64" ,test_required_sfixed64 },
|
||||
//{ "test required uint32" ,test_required_uint32 },
|
||||
//{ "test required fixed32" ,test_required_fixed32 },
|
||||
//{ "test required uint64" ,test_required_uint64 },
|
||||
//{ "test required fixed64" ,test_required_fixed64 },
|
||||
//{ "test required float" ,test_required_float },
|
||||
//{ "test required double" ,test_required_double },
|
||||
//{ "test required bool" ,test_required_bool },
|
||||
//{ "test required TestEnumSmall" ,test_required_TestEnumSmall },
|
||||
//{ "test required TestEnum" ,test_required_TestEnum },
|
||||
//{ "test required string" ,test_required_string },
|
||||
//{ "test required bytes" ,test_required_bytes },
|
||||
//{ "test required SubMess" ,test_required_SubMess },
|
||||
};
|
||||
#define n_tests (sizeof(tests)/sizeof(Test))
|
||||
|
||||
int main (int argc, char **argv)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < n_tests; i++)
|
||||
{
|
||||
fprintf (stderr, "Test: %s... ", tests[i].name);
|
||||
tests[i].func ();
|
||||
fprintf (stderr, " done.\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user