Ported some tests.

pull/13171/head
Joshua Haberman 6 years ago
parent 0fed529ea1
commit 7ff8413a03
  1. 26
      BUILD
  2. 10
      CMakeLists.txt
  3. BIN
      google/protobuf/descriptor.pb
  4. 102
      tests/pb/test_decoder.cc
  5. 86
      tests/pb/test_decoder.proto
  6. 28
      tests/pb/test_encoder.cc
  7. 453
      tests/test_def.c
  8. 15
      upb/def.c
  9. 16
      upb/def.h

26
BUILD

@ -157,15 +157,6 @@ cc_test(
],
)
cc_test(
name = "test_def",
srcs = ["tests/test_def.c"],
deps = [
":upb_pb",
":upb_test",
],
)
cc_test(
name = "test_handlers",
srcs = ["tests/test_handlers.c"],
@ -187,7 +178,7 @@ cc_test(
cc_test(
name = "test_encoder",
srcs = ["tests/pb/test_encoder.cc"],
data = ["upb/descriptor/descriptor.pb"],
data = ["google/protobuf/descriptor.pb"],
deps = [
":upb_cc_bindings",
":upb_pb",
@ -413,6 +404,20 @@ py_binary(
srcs = ["tools/make_cmakelists.py"],
)
proto_library(
name = "descriptor_proto",
srcs = [
"google/protobuf/descriptor.proto",
],
)
genrule(
name = "copy_upb_descriptor_pb",
srcs = [":descriptor_proto"],
outs = ["generated/google/protobuf/descriptor.pb"],
cmd = "cp $< $@",
)
genrule(
name = "gen_cmakelists",
outs = ["generated/CMakeLists.txt"],
@ -477,6 +482,7 @@ generated_file_staleness_test(
name = "test_generated_files",
outs = [
"CMakeLists.txt",
"google/protobuf/descriptor.pb",
"google/protobuf/descriptor.upb.c",
"google/protobuf/descriptor.upb.h",
"tests/json/test.proto.pb",

@ -120,12 +120,6 @@ add_test(NAME test_varint COMMAND test_varint)
target_link_libraries(test_varint
upb_pb
upb_test)
add_executable(test_def
tests/test_def.c)
add_test(NAME test_def COMMAND test_def)
target_link_libraries(test_def
upb_pb
upb_test)
add_executable(test_handlers
tests/test_handlers.c)
add_test(NAME test_handlers COMMAND test_handlers)
@ -144,8 +138,8 @@ add_test(NAME test_encoder COMMAND test_encoder)
add_custom_command(
TARGET test_encoder POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy
${CMAKE_SOURCE_DIR}/upb/descriptor/descriptor.pb
${CMAKE_CURRENT_BINARY_DIR}/upb/descriptor/descriptor.pb)
${CMAKE_SOURCE_DIR}/google/protobuf/descriptor.pb
${CMAKE_CURRENT_BINARY_DIR}/google/protobuf/descriptor.pb)
target_link_libraries(test_encoder
upb_cc_bindings
upb_pb

Binary file not shown.

@ -399,107 +399,8 @@ void reg_str(upb_handlers *h, uint32_t num) {
ASSERT(h->SetStringHandler(f, UpbBind(value_string, new uint32_t(num))));
}
void AddField(upb_descriptortype_t descriptor_type, const std::string& name,
uint32_t fn, bool repeated, upb::MessageDef* md) {
// TODO: Fluent interface? ie.
// ASSERT(md->AddField(upb::BuildFieldDef()
// .SetName("f_message")
// .SetNumber(UPB_DESCRIPTOR_TYPE_MESSAGE)
// .SetDescriptorType(UPB_DESCRIPTOR_TYPE_MESSAGE)
// .SetMessageSubdef(md.get())));
upb::reffed_ptr<upb::FieldDef> f = upb::FieldDef::New();
ASSERT(f->set_name(name, NULL));
ASSERT(f->set_number(fn, NULL));
f->set_label(repeated ? UPB_LABEL_REPEATED : UPB_LABEL_OPTIONAL);
f->set_descriptor_type(descriptor_type);
ASSERT(md->AddField(f.get(), NULL));
}
void AddFieldsForType(upb_descriptortype_t descriptor_type,
const char* basename, upb::MessageDef* md) {
const upb_descriptortype_t t = descriptor_type;
AddField(t, std::string("f_") + basename, t, false, md);
AddField(t, std::string("r_") + basename, rep_fn(t), true, md);
}
upb::reffed_ptr<const upb::MessageDef> NewMessageDef() {
upb::reffed_ptr<upb::MessageDef> md = upb::MessageDef::New();
md->set_full_name("DecoderTest", NULL);
AddFieldsForType(UPB_DESCRIPTOR_TYPE_DOUBLE, "double", md.get());
AddFieldsForType(UPB_DESCRIPTOR_TYPE_FLOAT, "float", md.get());
AddFieldsForType(UPB_DESCRIPTOR_TYPE_INT64, "int64", md.get());
AddFieldsForType(UPB_DESCRIPTOR_TYPE_UINT64, "uint64", md.get());
AddFieldsForType(UPB_DESCRIPTOR_TYPE_INT32, "int32", md.get());
AddFieldsForType(UPB_DESCRIPTOR_TYPE_FIXED64, "fixed64", md.get());
AddFieldsForType(UPB_DESCRIPTOR_TYPE_FIXED32, "fixed32", md.get());
AddFieldsForType(UPB_DESCRIPTOR_TYPE_BOOL, "bool", md.get());
AddFieldsForType(UPB_DESCRIPTOR_TYPE_STRING, "string", md.get());
AddFieldsForType(UPB_DESCRIPTOR_TYPE_BYTES, "bytes", md.get());
AddFieldsForType(UPB_DESCRIPTOR_TYPE_UINT32, "uint32", md.get());
AddFieldsForType(UPB_DESCRIPTOR_TYPE_SFIXED32, "sfixed32", md.get());
AddFieldsForType(UPB_DESCRIPTOR_TYPE_SFIXED64, "sfixed64", md.get());
AddFieldsForType(UPB_DESCRIPTOR_TYPE_SINT32, "sint32", md.get());
AddFieldsForType(UPB_DESCRIPTOR_TYPE_SINT64, "sint64", md.get());
AddField(UPB_DESCRIPTOR_TYPE_STRING, "nop_field", 40, false, md.get());
upb::reffed_ptr<upb::FieldDef> f = upb::FieldDef::New();
ASSERT(f->set_name("f_message", NULL));
ASSERT(f->set_number(UPB_DESCRIPTOR_TYPE_MESSAGE, NULL));
f->set_descriptor_type(UPB_DESCRIPTOR_TYPE_MESSAGE);
ASSERT(f->set_message_subdef(md.get(), NULL));
ASSERT(md->AddField(f.get(), NULL));
f = upb::FieldDef::New();
ASSERT(f->set_name("r_message", NULL));
ASSERT(f->set_number(rep_fn(UPB_DESCRIPTOR_TYPE_MESSAGE), NULL));
f->set_label(UPB_LABEL_REPEATED);
f->set_descriptor_type(UPB_DESCRIPTOR_TYPE_MESSAGE);
ASSERT(f->set_message_subdef(md.get(), NULL));
ASSERT(md->AddField(f.get(), NULL));
f = upb::FieldDef::New();
ASSERT(f->set_name("f_group", NULL));
ASSERT(f->set_number(UPB_DESCRIPTOR_TYPE_GROUP, NULL));
f->set_descriptor_type(UPB_DESCRIPTOR_TYPE_GROUP);
ASSERT(f->set_message_subdef(md.get(), NULL));
ASSERT(md->AddField(f.get(), NULL));
f = upb::FieldDef::New();
ASSERT(f->set_name("r_group", NULL));
ASSERT(f->set_number(rep_fn(UPB_DESCRIPTOR_TYPE_GROUP), NULL));
f->set_label(UPB_LABEL_REPEATED);
f->set_descriptor_type(UPB_DESCRIPTOR_TYPE_GROUP);
ASSERT(f->set_message_subdef(md.get(), NULL));
ASSERT(md->AddField(f.get(), NULL));
upb::reffed_ptr<upb::EnumDef> e = upb::EnumDef::New();
ASSERT(e->AddValue("FOO", 1, NULL));
ASSERT(e->Freeze(NULL));
f = upb::FieldDef::New();
ASSERT(f->set_name("f_enum", NULL));
ASSERT(f->set_number(UPB_DESCRIPTOR_TYPE_ENUM, NULL));
f->set_descriptor_type(UPB_DESCRIPTOR_TYPE_ENUM);
ASSERT(f->set_enum_subdef(e.get(), NULL));
ASSERT(md->AddField(f.get(), NULL));
f = upb::FieldDef::New();
ASSERT(f->set_name("r_enum", NULL));
ASSERT(f->set_number(rep_fn(UPB_DESCRIPTOR_TYPE_ENUM), NULL));
f->set_label(UPB_LABEL_REPEATED);
f->set_descriptor_type(UPB_DESCRIPTOR_TYPE_ENUM);
ASSERT(f->set_enum_subdef(e.get(), NULL));
ASSERT(md->AddField(f.get(), NULL));
ASSERT(md->Freeze(NULL));
return md;
}
upb::reffed_ptr<const upb::Handlers> NewHandlers(TestMode mode) {
upb::reffed_ptr<upb::Handlers> h(upb::Handlers::New(NewMessageDef().get()));
if (mode == ALL_HANDLERS) {
@ -1277,6 +1178,7 @@ upb::reffed_ptr<const upb::pb::DecoderMethod> method =
void run_tests(bool use_jit) {
upb::reffed_ptr<const upb::pb::DecoderMethod> method;
upb::reffed_ptr<const upb::Handlers> handlers;
upb::SymbolTable symtab;
handlers = NewHandlers(test_mode);
global_handlers = handlers.get();

@ -0,0 +1,86 @@
syntax = "proto2";
enum TestEnum {
FOO = 1;
}
message DecoderTest {
optional double f_double = 1;
optional float f_float = 2;
optional int64 f_int64 = 3;
optional uint64 f_uint64 = 4;
optional int32 f_int32 = 5;
optional fixed64 f_fixed64 = 6;
optional fixed32 f_fixed32 = 7;
optional bool f_bool = 8;
optional string f_string = 9;
optional DecoderTest f_message = 11;
optional bytes f_bytes = 12;
optional uint32 f_uint32 = 13;
optional TestEnum f_enum = 14;
optional sfixed32 f_sfixed32 = 15;
optional sfixed64 f_sfixed64 = 16;
optional sint32 f_sint32 = 17;
optional sint64 f_sint64 = 18;
optional string nop_field = 40;
repeated double r_double = 536869912;
repeated float r_float = 536869913;
repeated int64 r_int64 = 536869914;
repeated uint64 r_uint64 = 536869915;
repeated int32 r_int32 = 536869916;
repeated fixed64 r_fixed64 = 536869917;
repeated fixed32 r_fixed32 = 536869918;
repeated bool r_bool = 536869919;
repeated string r_string = 536869920;
repeated DecoderTest r_message = 536869922;
repeated bytes r_bytes = 536869923;
repeated uint32 r_uint32 = 536869924;
repeated TestEnum r_enum = 536869925;
repeated sfixed32 r_sfixed32 = 536869926;
repeated sfixed64 r_sfixed64 = 536869927;
repeated sint32 r_sint32 = 536869928;
repeated sint64 r_sint64 = 536869929;
optional group F_group = 10 {
optional double f_double = 1;
optional float f_float = 2;
optional int64 f_int64 = 3;
optional uint64 f_uint64 = 4;
optional int32 f_int32 = 5;
optional fixed64 f_fixed64 = 6;
optional fixed32 f_fixed32 = 7;
optional bool f_bool = 8;
optional string f_string = 9;
optional DecoderTest f_message = 11;
optional bytes f_bytes = 12;
optional uint32 f_uint32 = 13;
optional TestEnum f_enum = 14;
optional sfixed32 f_sfixed32 = 15;
optional sfixed64 f_sfixed64 = 16;
optional sint32 f_sint32 = 17;
optional sint64 f_sint64 = 18;
}
optional group R_group = 536869921 {
optional double f_double = 1;
optional float f_float = 2;
optional int64 f_int64 = 3;
optional uint64 f_uint64 = 4;
optional int32 f_int32 = 5;
optional fixed64 f_fixed64 = 6;
optional fixed32 f_fixed32 = 7;
optional bool f_bool = 8;
optional string f_string = 9;
optional DecoderTest f_message = 11;
optional bytes f_bytes = 12;
optional uint32 f_uint32 = 13;
optional TestEnum f_enum = 14;
optional sfixed32 f_sfixed32 = 15;
optional sfixed64 f_sfixed64 = 16;
optional sint32 f_sint32 = 17;
optional sint64 f_sint64 = 18;
}
}

@ -2,10 +2,9 @@
#include "tests/test_util.h"
#include "tests/upb_test.h"
#include "upb/bindings/stdc++/string.h"
#include "upb/descriptor/descriptor.upbdefs.h"
#include "google/protobuf/descriptor.upb.h"
#include "upb/pb/decoder.h"
#include "upb/pb/encoder.h"
#include "upb/pb/glue.h"
std::string read_string(const char *filename) {
size_t len;
@ -18,16 +17,30 @@ std::string read_string(const char *filename) {
}
void test_pb_roundtrip() {
upb::reffed_ptr<const upb::MessageDef> md(
upbdefs::google::protobuf::FileDescriptorSet::get());
std::string input = read_string("google/protobuf/descriptor.pb");
upb::SymbolTable* symtab = upb::SymbolTable::New();
upb::Arena arena;
google_protobuf_FileDescriptorSet *set =
google_protobuf_FileDescriptorSet_parsenew(
upb_stringview_make(input.c_str(), input.size()), &arena);
ASSERT(set);
const upb_array *arr = google_protobuf_FileDescriptorSet_file(set);
const google_protobuf_FileDescriptorProto *file_proto =
static_cast<const google_protobuf_FileDescriptorProto *>(
upb_msgval_getptr(upb_array_get(arr, 0)));
upb::Status status;
bool ok = symtab->AddFile(file_proto, &status);
ASSERT(ok);
const upb::MessageDef *md =
symtab->LookupMessage("google.protobuf.FileDescriptorSet");
ASSERT(md);
upb::reffed_ptr<const upb::Handlers> encoder_handlers(
upb::pb::Encoder::NewHandlers(md.get()));
upb::pb::Encoder::NewHandlers(md));
upb::reffed_ptr<const upb::pb::DecoderMethod> method(
upb::pb::DecoderMethod::New(
upb::pb::DecoderMethodOptions(encoder_handlers.get())));
upb::InlinedEnvironment<512> env;
std::string input = read_string("upb/descriptor/descriptor.pb");
std::string output;
upb::StringSink string_sink(&output);
upb::pb::Encoder* encoder =
@ -35,9 +48,10 @@ void test_pb_roundtrip() {
string_sink.input());
upb::pb::Decoder* decoder =
upb::pb::Decoder::Create(&env, method.get(), encoder->input());
bool ok = upb::BufferSource::PutBuffer(input, decoder->input());
ok = upb::BufferSource::PutBuffer(input, decoder->input());
ASSERT(ok);
ASSERT(input == output);
upb::SymbolTable::Free(symtab);
}
extern "C" {

@ -1,453 +0,0 @@
/*
** Test of defs and symtab. There should be far more tests of edge conditions
** (like attempts to link defs that don't have required properties set).
*/
#include "tests/test_util.h"
#include "upb/def.h"
#include "upb/pb/glue.h"
#include "upb_test.h"
#include <stdlib.h>
#include <string.h>
const char *descriptor_file;
static void test_empty_symtab() {
upb_symtab *s = upb_symtab_new();
upb_symtab_iter i;
for (upb_symtab_begin(&i, s, UPB_DEF_ANY); !upb_symtab_done(&i);
upb_symtab_next(&i)) {
ASSERT(false); /* Should not get here. */
}
upb_symtab_free(s);
}
static void test_noreftracking() {
/* Reftracking is not required; clients can pass UPB_UNTRACKED_REF for owner. */
upb_msgdef *md = upb_msgdef_new(UPB_UNTRACKED_REF);
upb_msgdef_ref(md, UPB_UNTRACKED_REF);
/* Clients can mix tracked and untracked refs. */
upb_msgdef_ref(md, &md);
upb_msgdef_unref(md, UPB_UNTRACKED_REF);
upb_msgdef_unref(md, UPB_UNTRACKED_REF);
/* Call some random function on the messagedef to test that it is alive. */
ASSERT(!upb_msgdef_isfrozen(md));
upb_msgdef_unref(md, &md);
}
static upb_symtab *load_test_proto() {
upb_symtab *s = upb_symtab_new();
upb_status status = UPB_STATUS_INIT;
size_t len;
char *data = upb_readfile(descriptor_file, &len);
upb_filedef **files, **files_ptr;
ASSERT(s);
ASSERT(data);
files = upb_loaddescriptor(data, len, &files, &status);
ASSERT(files);
free(data);
files_ptr = files;
while (*files_ptr) {
bool ok;
ASSERT(!upb_filedef_isfrozen(*files_ptr));
ok = upb_symtab_addfile(s, *files_ptr, &status);
ASSERT(ok);
ASSERT(upb_filedef_isfrozen(*files_ptr));
upb_filedef_unref(*files_ptr, &files);
files_ptr++;
}
upb_gfree(files);
return s;
}
static void test_cycles() {
bool ok;
upb_symtab *s = load_test_proto();
const upb_msgdef *m;
const upb_fielddef *f;
const upb_def *def;
const upb_def *def2;
/* Test cycle detection by making a cyclic def's main refcount go to zero
* and then be incremented to one again. */
def = upb_symtab_lookup(s, "A");
upb_def_ref(def, &def);
ASSERT(def);
ASSERT(upb_def_isfrozen(def));
upb_symtab_free(s);
/* Message A has only one subfield: "optional B b = 1". */
m = upb_downcast_msgdef(def);
f = upb_msgdef_itof(m, 1);
ASSERT(f);
ASSERT(upb_fielddef_hassubdef(f));
ASSERT(upb_msgdef_ntofz(m, "b") == f);
ASSERT(upb_msgdef_ntof(m, "b", 1) == f);
def2 = upb_fielddef_subdef(f);
ASSERT(upb_downcast_msgdef(def2));
ok = strcmp(upb_def_fullname(def2), "B") == 0;
ASSERT(ok);
upb_def_ref(def2, &def2);
upb_def_unref(def, &def);
/* We know "def" is still alive because it's reachable from def2. */
ok = strcmp(upb_def_fullname(def), "A") == 0;
ASSERT(ok);
upb_def_unref(def2, &def2);
}
static void test_symbol_resolution() {
upb_status s = UPB_STATUS_INIT;
upb_def *defs[2];
upb_msgdef *m1;
upb_msgdef *m2;
upb_msgdef *m3;
upb_fielddef *m3_field1;
upb_fielddef *m3_field2;
upb_symtab *symtab = upb_symtab_new(&symtab);
ASSERT(symtab);
/* m1 has name "A.B.C" and no fields. We'll add it to the symtab now. */
m1 = upb_msgdef_new(&m1);
ASSERT(m1);
ASSERT_STATUS(upb_msgdef_setfullname(m1, "A.B.C", &s), &s);
ASSERT_STATUS(upb_symtab_add(symtab, (upb_def**)&m1, 1,
NULL, &s), &s);
/* m2 has name "D.E" and no fields. We'll add it in the same batch as m3
* below. */
m2 = upb_msgdef_new(&m2);
ASSERT(m2);
ASSERT_STATUS(upb_msgdef_setfullname(m2, "D.E", &s), &s);
/* m3 has name "F.G" and two fields, of type A.B.C and D.E respectively. We'll
* add it in the same batch as m2 above. */
m3 = upb_msgdef_new(&m3);
ASSERT(m3);
ASSERT_STATUS(upb_msgdef_setfullname(m3, "F.G", &s), &s);
m3_field1 = upb_fielddef_new(&m3_field1);
ASSERT_STATUS(upb_fielddef_setname(m3_field1, "field1", &s), &s);
ASSERT_STATUS(upb_fielddef_setnumber(m3_field1, 1, &s), &s);
upb_fielddef_setlabel(m3_field1, UPB_LABEL_OPTIONAL);
upb_fielddef_settype(m3_field1, UPB_TYPE_MESSAGE);
ASSERT_STATUS(upb_fielddef_setsubdefname(m3_field1, ".A.B.C", &s), &s);
ASSERT_STATUS(upb_msgdef_addfield(m3, m3_field1, NULL, &s), &s);
m3_field2 = upb_fielddef_new(&m3_field2);
ASSERT_STATUS(upb_fielddef_setname(m3_field2, "field2", &s), &s);
ASSERT_STATUS(upb_fielddef_setnumber(m3_field2, 2, &s), &s);
upb_fielddef_setlabel(m3_field2, UPB_LABEL_OPTIONAL);
upb_fielddef_settype(m3_field2, UPB_TYPE_MESSAGE);
ASSERT_STATUS(upb_fielddef_setsubdefname(m3_field2, ".D.E", &s), &s);
ASSERT_STATUS(upb_msgdef_addfield(m3, m3_field2, NULL, &s), &s);
defs[0] = upb_msgdef_upcast_mutable(m2);
defs[1] = upb_msgdef_upcast_mutable(m3);
ASSERT_STATUS(upb_symtab_add(symtab, defs, 2, NULL, &s), &s);
upb_fielddef_unref(m3_field2, &m3_field2);
upb_fielddef_unref(m3_field1, &m3_field1);
upb_msgdef_unref(m3, &m3);
upb_msgdef_unref(m2, &m2);
upb_msgdef_unref(m1, &m1);
upb_symtab_free(symtab);
}
static void test_fielddef_unref() {
bool ok;
upb_symtab *s = load_test_proto();
const upb_msgdef *md = upb_symtab_lookupmsg(s, "A");
const upb_fielddef *f = upb_msgdef_itof(md, 1);
upb_fielddef_ref(f, &f);
/* Unref symtab; now fielddef is the only thing keeping the msgdef alive. */
upb_symtab_free(s);
/* Check that md is still alive. */
ok = strcmp(upb_msgdef_fullname(md), "A") == 0;
ASSERT(ok);
/* Check that unref of fielddef frees the whole remaining graph. */
upb_fielddef_unref(f, &f);
}
static void test_fielddef() {
/* Test that we don't leak an unresolved subdef name. */
upb_fielddef *f1 = upb_fielddef_new(&f1);
upb_fielddef_settype(f1, UPB_TYPE_MESSAGE);
ASSERT(upb_fielddef_setsubdefname(f1, "YO", NULL));
upb_fielddef_unref(f1, &f1);
}
static upb_fielddef *newfield(
const char *name, int32_t num, uint8_t type, uint8_t label,
const char *type_name, void *owner) {
upb_fielddef *f = upb_fielddef_new(owner);
ASSERT(upb_fielddef_setname(f, name, NULL));
ASSERT(upb_fielddef_setnumber(f, num, NULL));
upb_fielddef_settype(f, type);
upb_fielddef_setlabel(f, label);
if (type_name) {
ASSERT(upb_fielddef_setsubdefname(f, type_name, NULL));
}
return f;
}
static upb_msgdef *upb_msgdef_newnamed(const char *name, void *owner) {
upb_msgdef *m = upb_msgdef_new(owner);
upb_msgdef_setfullname(m, name, NULL);
return m;
}
static void test_replacement_fails() {
bool ok;
upb_symtab *s = upb_symtab_new(&s);
upb_status status = UPB_STATUS_INIT;
upb_def *newdefs[2];
upb_msgdef *m = upb_msgdef_newnamed("MyMessage", &s);
upb_msgdef *m2 = upb_msgdef_newnamed("MyMessage", &s);
newdefs[0] = upb_msgdef_upcast_mutable(m);
newdefs[1] = upb_msgdef_upcast_mutable(m2);
ok = upb_symtab_add(s, newdefs, 2, &s, &status);
ASSERT(ok == false);
upb_status_clear(&status);
/* Adding just one is ok. */
ASSERT_STATUS(upb_symtab_add(s, newdefs, 1, &s, &status), &status);
/* Adding a conflicting one is not ok. */
newdefs[0] = upb_msgdef_upcast_mutable(m2);
ok = upb_symtab_add(s, newdefs, 1, &s, &status);
ASSERT(ok == false);
upb_symtab_free(s);
}
static void test_freeze_free() {
bool ok;
/* Test that freeze frees defs that were only being kept alive by virtue of
* sharing a group with other defs that are being frozen. */
upb_msgdef *m1 = upb_msgdef_newnamed("M1", &m1);
upb_msgdef *m2 = upb_msgdef_newnamed("M2", &m2);
upb_msgdef *m3 = upb_msgdef_newnamed("M3", &m3);
upb_msgdef *m4 = upb_msgdef_newnamed("M4", &m4);
upb_fielddef *f = upb_fielddef_new(&f);
/* Freeze M4 and make M1 point to it. */
upb_def_freeze((upb_def*const*)&m4, 1, NULL);
upb_fielddef_settype(f, UPB_TYPE_MESSAGE);
ASSERT(upb_fielddef_setnumber(f, 1, NULL));
ASSERT(upb_fielddef_setname(f, "foo", NULL));
ASSERT(upb_fielddef_setmsgsubdef(f, m4, NULL));
ASSERT(upb_msgdef_addfield(m1, f, &f, NULL));
/* After this unref, M1 is the only thing keeping M4 alive. */
upb_msgdef_unref(m4, &m4);
/* Force M1/M2/M3 into a single mutable refcounting group. */
f = upb_fielddef_new(&f);
upb_fielddef_settype(f, UPB_TYPE_MESSAGE);
ASSERT(upb_fielddef_setnumber(f, 1, NULL));
ASSERT(upb_fielddef_setname(f, "foo", NULL));
ASSERT(upb_fielddef_setmsgsubdef(f, m1, NULL));
ASSERT(upb_fielddef_setmsgsubdef(f, m2, NULL));
ASSERT(upb_fielddef_setmsgsubdef(f, m3, NULL));
/* Make M3 cyclic with itself. */
ASSERT(upb_msgdef_addfield(m3, f, &f, NULL));
/* These will be kept alive since they are in the same refcounting group as
* M3, which still has a ref. Note: this behavior is not guaranteed by the
* API, but true in practice with its current implementation. */
upb_msgdef_unref(m1, &m1);
upb_msgdef_unref(m2, &m2);
/* Test that they are still alive (NOT allowed by the API). */
ok = strcmp("M1", upb_msgdef_fullname(m1)) == 0;
ASSERT(ok);
ok = strcmp("M2", upb_msgdef_fullname(m2)) == 0;
ASSERT(ok);
/* Freeze M3. If the test leaked no memory, then freeing m1 and m2 was
* successful. */
ASSERT(upb_def_freeze((upb_def*const*)&m3, 1, NULL));
upb_msgdef_unref(m3, &m3);
}
static void test_partial_freeze() {
/* Test that freeze of only part of the graph correctly adjusts objects that
* point to the newly-frozen objects. */
upb_msgdef *m1 = upb_msgdef_newnamed("M1", &m1);
upb_msgdef *m2 = upb_msgdef_newnamed("M2", &m2);
upb_msgdef *m3 = upb_msgdef_newnamed("M3", &m3);
upb_fielddef *f1 = upb_fielddef_new(&f1);
upb_fielddef *f2 = upb_fielddef_new(&f2);
upb_def *defs[2];
defs[0] = upb_msgdef_upcast_mutable(m1);
defs[1] = upb_msgdef_upcast_mutable(m2);
upb_fielddef_settype(f1, UPB_TYPE_MESSAGE);
ASSERT(upb_fielddef_setnumber(f1, 1, NULL));
ASSERT(upb_fielddef_setname(f1, "f1", NULL));
ASSERT(upb_fielddef_setmsgsubdef(f1, m1, NULL));
upb_fielddef_settype(f2, UPB_TYPE_MESSAGE);
ASSERT(upb_fielddef_setnumber(f2, 2, NULL));
ASSERT(upb_fielddef_setname(f2, "f2", NULL));
ASSERT(upb_fielddef_setmsgsubdef(f2, m2, NULL));
ASSERT(upb_msgdef_addfield(m3, f1, &f1, NULL));
ASSERT(upb_msgdef_addfield(m3, f2, &f2, NULL));
/* Freeze M1 and M2, which should cause the group to be split
* and m3 (left mutable) to take references on m1 and m2. */
ASSERT(upb_def_freeze(defs, 2, NULL));
ASSERT(upb_msgdef_isfrozen(m1));
ASSERT(upb_msgdef_isfrozen(m2));
ASSERT(!upb_msgdef_isfrozen(m3));
upb_msgdef_unref(m1, &m1);
upb_msgdef_unref(m2, &m2);
upb_msgdef_unref(m3, &m3);
}
static void test_descriptor_flags() {
upb_msgdef *m = upb_msgdef_new(&m);
upb_status s = UPB_STATUS_INIT;
ASSERT(upb_msgdef_mapentry(m) == false);
upb_msgdef_setfullname(m, "TestMessage", &s);
ASSERT(upb_ok(&s));
upb_msgdef_setmapentry(m, true);
ASSERT(upb_msgdef_mapentry(m) == true);
upb_msgdef_unref(m, &m);
}
static void test_mapentry_check() {
upb_status s = UPB_STATUS_INIT;
upb_msgdef *m = upb_msgdef_new(&m);
upb_fielddef *f = upb_fielddef_new(&f);
upb_symtab *symtab = upb_symtab_new(&symtab);
upb_msgdef *subm = upb_msgdef_new(&subm);
upb_def *defs[2];
upb_msgdef_setfullname(m, "TestMessage", &s);
upb_fielddef_setname(f, "field1", &s);
upb_fielddef_setnumber(f, 1, &s);
upb_fielddef_setlabel(f, UPB_LABEL_OPTIONAL);
upb_fielddef_settype(f, UPB_TYPE_MESSAGE);
upb_fielddef_setsubdefname(f, ".MapEntry", &s);
upb_msgdef_addfield(m, f, &f, &s);
ASSERT(upb_ok(&s));
upb_msgdef_setfullname(subm, "MapEntry", &s);
upb_msgdef_setmapentry(subm, true);
defs[0] = upb_msgdef_upcast_mutable(m);
defs[1] = upb_msgdef_upcast_mutable(subm);
upb_symtab_add(symtab, defs, 2, NULL, &s);
/* Should not have succeeded: non-repeated field pointing to a MapEntry. */
ASSERT(!upb_ok(&s));
upb_status_clear(&s);
upb_fielddef_setlabel(f, UPB_LABEL_REPEATED);
upb_symtab_add(symtab, defs, 2, NULL, &s);
ASSERT(upb_ok(&s));
upb_symtab_free(symtab);
upb_msgdef_unref(subm, &subm);
upb_msgdef_unref(m, &m);
}
static void test_oneofs() {
upb_status s = UPB_STATUS_INIT;
bool ok = true;
upb_def *subm_defs[1];
upb_symtab *symtab = upb_symtab_new(&symtab);
upb_msgdef *subm = upb_msgdef_newnamed("SubMessage", &symtab);
upb_msgdef *m = upb_msgdef_newnamed("TestMessage", &symtab);
upb_oneofdef *o = upb_oneofdef_new(&o);
const upb_oneofdef *lookup_o;
const upb_fielddef *lookup_field;
upb_def *defs[1];
ASSERT(symtab != NULL);
/* Create a test message for fields to refer to. */
upb_msgdef_addfield(subm, newfield("field1", 1, UPB_TYPE_INT32,
UPB_LABEL_OPTIONAL, NULL, &symtab),
&symtab, NULL);
subm_defs[0] = upb_msgdef_upcast_mutable(subm);
ASSERT_STATUS(upb_symtab_add(symtab, subm_defs, 1, &symtab, &s), &s);
ASSERT(upb_msgdef_numoneofs(m) == 0);
ASSERT(upb_oneofdef_numfields(o) == 0);
ASSERT(upb_oneofdef_name(o) == NULL);
ok = upb_oneofdef_setname(o, "test_oneof", &s);
ASSERT_STATUS(ok, &s);
ok = upb_oneofdef_addfield(o, newfield("field1", 1, UPB_TYPE_INT32,
UPB_LABEL_OPTIONAL, NULL, &symtab),
&symtab, NULL);
ASSERT_STATUS(ok, &s);
ok = upb_oneofdef_addfield(o, newfield("field2", 2, UPB_TYPE_MESSAGE,
UPB_LABEL_OPTIONAL, ".SubMessage",
&symtab),
&symtab, NULL);
ASSERT_STATUS(ok, &s);
ok = upb_msgdef_addoneof(m, o, NULL, &s);
ASSERT_STATUS(ok, &s);
defs[0] = upb_msgdef_upcast_mutable(m);
ASSERT_STATUS(upb_symtab_add(symtab, defs, 1, &symtab, &s), &s);
ASSERT(upb_msgdef_numoneofs(m) == 1);
lookup_o = upb_msgdef_ntooz(m, "test_oneof");
ASSERT(lookup_o == o);
lookup_field = upb_oneofdef_ntofz(o, "field1");
ASSERT(lookup_field != NULL && upb_fielddef_number(lookup_field) == 1);
upb_symtab_free(symtab);
upb_oneofdef_unref(o, &o);
}
int run_tests(int argc, char *argv[]) {
if (argc < 2) {
fprintf(stderr, "Usage: test_def <test.proto.pb>\n");
return 1;
}
descriptor_file = argv[1];
test_empty_symtab();
test_cycles();
test_symbol_resolution();
test_fielddef();
test_fielddef_unref();
test_replacement_fails();
test_freeze_free();
test_partial_freeze();
test_noreftracking();
test_descriptor_flags();
test_mapentry_check();
test_oneofs();
return 0;
}

@ -1359,14 +1359,21 @@ static void count_types_in_msg(
size_t i;
arr = google_protobuf_DescriptorProto_nested_type(msg_proto);
for (i = 0; i < upb_array_size(arr); i++) {
count_types_in_msg(upb_msgval_getptr(upb_array_get(arr, i)), counts);
if (arr) {
for (i = 0; i < upb_array_size(arr); i++) {
count_types_in_msg(upb_msgval_getptr(upb_array_get(arr, i)), counts);
}
}
arr = google_protobuf_DescriptorProto_enum_type(msg_proto);
counts->enum_count += upb_array_size(arr);
if (arr) {
counts->enum_count += upb_array_size(arr);
}
arr = google_protobuf_DescriptorProto_extension(msg_proto);
counts->ext_count += upb_array_size(arr);
if (arr) {
counts->ext_count += upb_array_size(arr);
}
}
static void count_types_in_file(

@ -564,8 +564,6 @@ class upb::OneofDef {
upb_oneof_iter iter_;
};
iterator begin();
iterator end();
const_iterator begin() const;
const_iterator end() const;
@ -682,7 +680,8 @@ class upb::SymbolTable {
/* TODO: iteration? */
/* Adds the given serialized FileDescriptorProto to the pool. */
bool AddFile(const char *file, size_t len, Status *status);
bool AddFile(const google_protobuf_FileDescriptorProto *file_proto,
Status *status);
/* Adds the given serialized FileDescriptorSet to the pool. */
bool AddSet(const char *set, size_t len, Status *status);
@ -703,6 +702,7 @@ const upb_msgdef *upb_symtab_lookupmsg(const upb_symtab *s, const char *sym);
const upb_msgdef *upb_symtab_lookupmsg2(
const upb_symtab *s, const char *sym, size_t len);
const upb_enumdef *upb_symtab_lookupenum(const upb_symtab *s, const char *sym);
int upb_symtab_filecount(const upb_symtab *s);
bool upb_symtab_addfile(upb_symtab *s,
const google_protobuf_FileDescriptorProto* file,
upb_status *status);
@ -721,6 +721,10 @@ inline void SymbolTable::Free(SymbolTable* s) {
inline const MessageDef *SymbolTable::LookupMessage(const char *sym) const {
return upb_symtab_lookupmsg(this, sym);
}
inline bool SymbolTable::AddFile(
const google_protobuf_FileDescriptorProto *file_proto, Status *status) {
return upb_symtab_addfile(this, file_proto, status);
}
} /* namespace upb */
#endif
@ -767,9 +771,6 @@ inline const MessageDef* FieldDef::containing_type() const {
inline const OneofDef* FieldDef::containing_oneof() const {
return upb_fielddef_containingoneof(this);
}
inline void FieldDef::clear_json_name() {
upb_fielddef_clearjsonname(this);
}
inline bool FieldDef::IsSubMessage() const {
return upb_fielddef_issubmsg(this);
}
@ -994,9 +995,6 @@ inline const char* FileDef::phpprefix() const {
inline const char* FileDef::phpnamespace() const {
return upb_filedef_phpnamespace(this);
}
inline int FileDef::def_count() const {
return upb_filedef_defcount(this);
}
inline int FileDef::dependency_count() const {
return upb_filedef_depcount(this);
}

Loading…
Cancel
Save