summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/bindings/googlepb/test_vs_proto2.cc13
-rw-r--r--tests/json/test_json.cc110
-rw-r--r--tests/pb/test_decoder.cc51
-rw-r--r--tests/test_cpp.cc103
-rw-r--r--tests/test_def.c91
5 files changed, 334 insertions, 34 deletions
diff --git a/tests/bindings/googlepb/test_vs_proto2.cc b/tests/bindings/googlepb/test_vs_proto2.cc
index c89339a..8e68791 100644
--- a/tests/bindings/googlepb/test_vs_proto2.cc
+++ b/tests/bindings/googlepb/test_vs_proto2.cc
@@ -40,8 +40,8 @@ const unsigned char message2_data[] = {
void compare_metadata(const google::protobuf::Descriptor* d,
const upb::MessageDef *upb_md) {
ASSERT(d->field_count() == upb_md->field_count());
- for (upb::MessageDef::const_iterator i = upb_md->begin(); i != upb_md->end();
- ++i) {
+ for (upb::MessageDef::const_field_iterator i = upb_md->field_begin();
+ i != upb_md->field_end(); ++i) {
const upb::FieldDef* upb_f = *i;
const google::protobuf::FieldDescriptor *proto2_f =
d->FindFieldByNumber(upb_f->number());
@@ -77,13 +77,14 @@ void parse_and_compare(google::protobuf::Message *msg1,
cache.GetDecoderMethod(upb::pb::DecoderMethodOptions(protomsg_handlers)));
upb::Status status;
- upb::pb::Decoder decoder(decoder_method.get(), &status);
+ upb::Environment env;
+ env.ReportErrorsTo(&status);
upb::Sink protomsg_sink(protomsg_handlers, msg2);
-
- decoder.ResetOutput(&protomsg_sink);
+ upb::pb::Decoder* decoder =
+ upb::pb::Decoder::Create(&env, decoder_method.get(), &protomsg_sink);
msg2->Clear();
- bool ok = upb::BufferSource::PutBuffer(str, len, decoder.input());
+ bool ok = upb::BufferSource::PutBuffer(str, len, decoder->input());
if (!ok) {
fprintf(stderr, "error parsing: %s\n", status.error_message());
print_diff(*msg1, *msg2);
diff --git a/tests/json/test_json.cc b/tests/json/test_json.cc
index f1e2304..f2e26b8 100644
--- a/tests/json/test_json.cc
+++ b/tests/json/test_json.cc
@@ -85,6 +85,33 @@ static TestCase kTestRoundtripMessages[] = {
TEST("{\"optional_string\":\"\\uFFFF\"}"),
EXPECT("{\"optional_string\":\"\xEF\xBF\xBF\"}")
},
+ // map-field tests
+ {
+ TEST("{\"map_string_string\":{\"a\":\"value1\",\"b\":\"value2\","
+ "\"c\":\"value3\"}}"),
+ EXPECT_SAME
+ },
+ {
+ TEST("{\"map_int32_string\":{\"1\":\"value1\",\"-1\":\"value2\","
+ "\"1234\":\"value3\"}}"),
+ EXPECT_SAME
+ },
+ {
+ TEST("{\"map_bool_string\":{\"false\":\"value1\",\"true\":\"value2\"}}"),
+ EXPECT_SAME
+ },
+ {
+ TEST("{\"map_string_int32\":{\"asdf\":1234,\"jkl;\":-1}}"),
+ EXPECT_SAME
+ },
+ {
+ TEST("{\"map_string_bool\":{\"asdf\":true,\"jkl;\":false}}"),
+ EXPECT_SAME
+ },
+ {
+ TEST("{\"map_string_msg\":{\"asdf\":{\"foo\":42},\"jkl;\":{\"foo\":84}}}"),
+ EXPECT_SAME
+ },
TEST_SENTINEL
};
@@ -115,6 +142,53 @@ static const upb::MessageDef* BuildTestMessage(
submsg->set_full_name("SubMessage", &st);
AddField(submsg.get(), 1, "foo", UPB_TYPE_INT32, false);
+ // Create MapEntryStringString.
+ upb::reffed_ptr<upb::MessageDef> mapentry_string_string(
+ upb::MessageDef::New());
+ mapentry_string_string->set_full_name("MapEntry_String_String", &st);
+ mapentry_string_string->setmapentry(true);
+ AddField(mapentry_string_string.get(), 1, "key", UPB_TYPE_STRING, false);
+ AddField(mapentry_string_string.get(), 2, "value", UPB_TYPE_STRING, false);
+
+ // Create MapEntryInt32String.
+ upb::reffed_ptr<upb::MessageDef> mapentry_int32_string(
+ upb::MessageDef::New());
+ mapentry_int32_string->set_full_name("MapEntry_Int32_String", &st);
+ mapentry_int32_string->setmapentry(true);
+ AddField(mapentry_int32_string.get(), 1, "key", UPB_TYPE_INT32, false);
+ AddField(mapentry_int32_string.get(), 2, "value", UPB_TYPE_STRING, false);
+
+ // Create MapEntryBoolString.
+ upb::reffed_ptr<upb::MessageDef> mapentry_bool_string(
+ upb::MessageDef::New());
+ mapentry_bool_string->set_full_name("MapEntry_Bool_String", &st);
+ mapentry_bool_string->setmapentry(true);
+ AddField(mapentry_bool_string.get(), 1, "key", UPB_TYPE_BOOL, false);
+ AddField(mapentry_bool_string.get(), 2, "value", UPB_TYPE_STRING, false);
+
+ // Create MapEntryStringInt32.
+ upb::reffed_ptr<upb::MessageDef> mapentry_string_int32(
+ upb::MessageDef::New());
+ mapentry_string_int32->set_full_name("MapEntry_String_Int32", &st);
+ mapentry_string_int32->setmapentry(true);
+ AddField(mapentry_string_int32.get(), 1, "key", UPB_TYPE_STRING, false);
+ AddField(mapentry_string_int32.get(), 2, "value", UPB_TYPE_INT32, false);
+
+ // Create MapEntryStringBool.
+ upb::reffed_ptr<upb::MessageDef> mapentry_string_bool(upb::MessageDef::New());
+ mapentry_string_bool->set_full_name("MapEntry_String_Bool", &st);
+ mapentry_string_bool->setmapentry(true);
+ AddField(mapentry_string_bool.get(), 1, "key", UPB_TYPE_STRING, false);
+ AddField(mapentry_string_bool.get(), 2, "value", UPB_TYPE_BOOL, false);
+
+ // Create MapEntryStringMessage.
+ upb::reffed_ptr<upb::MessageDef> mapentry_string_msg(upb::MessageDef::New());
+ mapentry_string_msg->set_full_name("MapEntry_String_Message", &st);
+ mapentry_string_msg->setmapentry(true);
+ AddField(mapentry_string_msg.get(), 1, "key", UPB_TYPE_STRING, false);
+ AddField(mapentry_string_msg.get(), 2, "value", UPB_TYPE_MESSAGE, false,
+ upb::upcast(submsg.get()));
+
// Create MyEnum.
upb::reffed_ptr<upb::EnumDef> myenum(upb::EnumDef::New());
myenum->set_full_name("MyEnum", &st);
@@ -150,13 +224,33 @@ static const upb::MessageDef* BuildTestMessage(
AddField(md.get(), 19, "optional_enum", UPB_TYPE_ENUM, true,
upb::upcast(myenum.get()));
+ AddField(md.get(), 20, "map_string_string", UPB_TYPE_MESSAGE, true,
+ upb::upcast(mapentry_string_string.get()));
+ AddField(md.get(), 21, "map_int32_string", UPB_TYPE_MESSAGE, true,
+ upb::upcast(mapentry_int32_string.get()));
+ AddField(md.get(), 22, "map_bool_string", UPB_TYPE_MESSAGE, true,
+ upb::upcast(mapentry_bool_string.get()));
+ AddField(md.get(), 23, "map_string_int32", UPB_TYPE_MESSAGE, true,
+ upb::upcast(mapentry_string_int32.get()));
+ AddField(md.get(), 24, "map_string_bool", UPB_TYPE_MESSAGE, true,
+ upb::upcast(mapentry_string_bool.get()));
+ AddField(md.get(), 25, "map_string_msg", UPB_TYPE_MESSAGE, true,
+ upb::upcast(mapentry_string_msg.get()));
+
// Add both to our symtab.
- upb::Def* defs[3] = {
+ upb::Def* defs[9] = {
upb::upcast(submsg.ReleaseTo(&defs)),
upb::upcast(myenum.ReleaseTo(&defs)),
upb::upcast(md.ReleaseTo(&defs)),
+ upb::upcast(mapentry_string_string.ReleaseTo(&defs)),
+ upb::upcast(mapentry_int32_string.ReleaseTo(&defs)),
+ upb::upcast(mapentry_bool_string.ReleaseTo(&defs)),
+ upb::upcast(mapentry_string_int32.ReleaseTo(&defs)),
+ upb::upcast(mapentry_string_bool.ReleaseTo(&defs)),
+ upb::upcast(mapentry_string_msg.ReleaseTo(&defs)),
};
- symtab->Add(defs, 3, &defs, &st);
+ symtab->Add(defs, 9, &defs, &st);
+ ASSERT(st.ok());
// Return TestMessage.
return symtab->LookupMessage("TestMessage");
@@ -198,14 +292,14 @@ void test_json_roundtrip_message(const char* json_src,
const upb::Handlers* serialize_handlers,
int seam) {
upb::Status st;
- upb::json::Parser parser(&st);
- upb::json::Printer printer(serialize_handlers);
+ upb::Environment env;
+ env.ReportErrorsTo(&st);
StringSink data_sink;
+ upb::json::Printer* printer =
+ upb::json::Printer::Create(&env, serialize_handlers, data_sink.Sink());
+ upb::json::Parser* parser = upb::json::Parser::Create(&env, printer->input());
- parser.ResetOutput(printer.input());
- printer.ResetOutput(data_sink.Sink());
-
- upb::BytesSink* input = parser.input();
+ upb::BytesSink* input = parser->input();
void *sub;
size_t len = strlen(json_src);
size_t ofs = 0;
diff --git a/tests/pb/test_decoder.cc b/tests/pb/test_decoder.cc
index 3aea777..98926a6 100644
--- a/tests/pb/test_decoder.cc
+++ b/tests/pb/test_decoder.cc
@@ -64,6 +64,8 @@
(float)completed * 100 / total); \
}
+#define MAX_NESTING 64
+
uint32_t filter_hash = 0;
double completed;
double total;
@@ -210,7 +212,7 @@ string submsg(uint32_t fn, const string& buf) {
// using the closure depth to test that the stack of closures is properly
// handled.
-int closures[UPB_DECODER_MAX_NESTING];
+int closures[MAX_NESTING];
string output;
void indentbuf(string *buf, int depth) {
@@ -508,6 +510,15 @@ upb::reffed_ptr<const upb::Handlers> NewHandlers(TestMode mode) {
const upb::Handlers *global_handlers;
const upb::pb::DecoderMethod *global_method;
+upb::pb::Decoder* CreateDecoder(upb::Environment* env,
+ const upb::pb::DecoderMethod* method,
+ upb::Sink* sink) {
+ upb::pb::Decoder *ret = upb::pb::Decoder::Create(env, method, sink);
+ ASSERT(ret != NULL);
+ ret->set_max_nesting(MAX_NESTING);
+ return ret;
+}
+
uint32_t Hash(const string& proto, const string* expected_output, size_t seam1,
size_t seam2) {
uint32_t hash = MurmurHash2(proto.c_str(), proto.size(), 0);
@@ -545,19 +556,21 @@ static bool parse(upb::pb::Decoder* decoder, void* subc, const char* buf,
#define LINE(x) x "\n"
void run_decoder(const string& proto, const string* expected_output) {
upb::Status status;
- upb::pb::Decoder decoder(global_method, &status);
upb::Sink sink(global_handlers, &closures[0]);
- decoder.ResetOutput(&sink);
for (size_t i = 0; i < proto.size(); i++) {
for (size_t j = i; j < UPB_MIN(proto.size(), i + 5); j++) {
+ // TODO(haberman): hoist this again once the environment supports reset.
+ upb::Environment env;
+ env.ReportErrorsTo(&status);
+ upb::pb::Decoder *decoder = CreateDecoder(&env, global_method, &sink);
+
testhash = Hash(proto, expected_output, i, j);
if (filter_hash && testhash != filter_hash) continue;
if (test_mode != COUNT_ONLY) {
- decoder.Reset();
output.clear();
status.Clear();
size_t ofs = 0;
- upb::BytesSink* input = decoder.input();
+ upb::BytesSink* input = decoder->input();
void *sub;
if (filter_hash) {
@@ -576,9 +589,9 @@ void run_decoder(const string& proto, const string* expected_output) {
}
bool ok = input->Start(proto.size(), &sub) &&
- parse(&decoder, sub, proto.c_str(), 0, i, &ofs, &status) &&
- parse(&decoder, sub, proto.c_str(), i, j, &ofs, &status) &&
- parse(&decoder, sub, proto.c_str(), j, proto.size(), &ofs,
+ parse(decoder, sub, proto.c_str(), 0, i, &ofs, &status) &&
+ parse(decoder, sub, proto.c_str(), i, j, &ofs, &status) &&
+ parse(decoder, sub, proto.c_str(), j, proto.size(), &ofs,
&status) &&
ofs == proto.size();
@@ -852,7 +865,7 @@ void test_invalid() {
// Test exceeding the resource limit of stack depth.
string buf;
- for (int i = 0; i <= UPB_DECODER_MAX_NESTING; i++) {
+ for (int i = 0; i <= MAX_NESTING; i++) {
buf.assign(submsg(UPB_DESCRIPTOR_TYPE_MESSAGE, buf));
}
assert_does_not_parse(buf);
@@ -871,11 +884,12 @@ void test_valid() {
if (!filter_hash || filter_hash == testhash) {
testhash = emptyhash;
upb::Status status;
- upb::pb::Decoder decoder(global_method, &status);
+ upb::Environment env;
+ env.ReportErrorsTo(&status);
upb::Sink sink(global_handlers, &closures[0]);
- decoder.ResetOutput(&sink);
+ upb::pb::Decoder* decoder = CreateDecoder(&env, global_method, &sink);
output.clear();
- bool ok = upb::BufferSource::PutBuffer("", 0, decoder.input());
+ bool ok = upb::BufferSource::PutBuffer("", 0, decoder->input());
ASSERT(ok);
ASSERT(status.ok());
if (test_mode == ALL_HANDLERS) {
@@ -1076,7 +1090,7 @@ void test_valid() {
// Staying within the stack limit should work properly.
string buf;
string textbuf;
- int total = UPB_DECODER_MAX_NESTING - 1;
+ int total = MAX_NESTING - 1;
for (int i = 0; i < total; i++) {
buf.assign(submsg(UPB_DESCRIPTOR_TYPE_MESSAGE, buf));
indentbuf(&textbuf, i);
@@ -1135,11 +1149,12 @@ upb::reffed_ptr<const upb::pb::DecoderMethod> method =
{ NULL, 0 },
};
for (int i = 0; testdata[i].data; i++) {
+ upb::Environment env;
upb::Status status;
- upb::pb::Decoder decoder(method.get(), &status);
- upb::Sink sink(global_handlers, &closures[0]);
- decoder.ResetOutput(&sink);
- upb::BytesSink* input = decoder.input();
+ env.ReportErrorsTo(&status);
+ upb::Sink sink(method->dest_handlers(), &closures[0]);
+ upb::pb::Decoder* decoder = CreateDecoder(&env, method.get(), &sink);
+ upb::BytesSink* input = decoder->input();
void* subc;
ASSERT(input->Start(0, &subc));
size_t ofs = 0;
@@ -1182,7 +1197,7 @@ extern "C" {
int run_tests(int argc, char *argv[]) {
if (argc > 1)
filter_hash = strtol(argv[1], NULL, 16);
- for (int i = 0; i < UPB_DECODER_MAX_NESTING; i++) {
+ for (int i = 0; i < MAX_NESTING; i++) {
closures[i] = i;
}
diff --git a/tests/test_cpp.cc b/tests/test_cpp.cc
index 55bb4b3..c2de6c3 100644
--- a/tests/test_cpp.cc
+++ b/tests/test_cpp.cc
@@ -12,8 +12,10 @@
#include <iostream>
#include <set>
+#include <sstream>
#include "upb/def.h"
+#include "upb/env.h"
#include "upb/descriptor/reader.h"
#include "upb/handlers.h"
#include "upb/pb/decoder.h"
@@ -164,7 +166,7 @@ static void TestSymbolTable(const char *descriptor_file) {
#ifdef UPB_CXX11
// Test range-based for.
std::set<const upb::FieldDef*> fielddefs;
- for (const upb::FieldDef* f : *md.get()) {
+ for (const upb::FieldDef* f : md.get()->fields()) {
AssertInsert(&fielddefs, f);
ASSERT(f->containing_type() == md.get());
}
@@ -1117,6 +1119,103 @@ void TestHandlerDataDestruction() {
ASSERT(x == 0);
}
+void TestOneofs() {
+ upb::Status status;
+ upb::reffed_ptr<upb::MessageDef> md(upb::MessageDef::New());
+ upb::reffed_ptr<upb::OneofDef> o(upb::OneofDef::New());
+
+ o->set_name("test_oneof", &status);
+ ASSERT(status.ok());
+
+ for (int i = 0; i < 5; i++) {
+ std::ostringstream fieldname;
+ fieldname << "field_" << i;
+ upb::reffed_ptr<upb::FieldDef> f(upb::FieldDef::New());
+ f->set_name(fieldname.str(), &status);
+ ASSERT(status.ok());
+ f->set_type(UPB_TYPE_INT32);
+ f->set_number(i + 1, &status);
+ ASSERT(status.ok());
+ f->set_label(UPB_LABEL_OPTIONAL);
+
+ o->AddField(f.get(), &status);
+ ASSERT(status.ok());
+ }
+
+ md->AddOneof(o.get(), &status);
+ ASSERT(status.ok());
+
+ int field_count = 0;
+ for (upb::OneofDef::iterator it = o->begin(); it != o->end(); ++it) {
+ upb::FieldDef* f = *it;
+ ASSERT(f->type() == UPB_TYPE_INT32);
+ field_count++;
+ }
+ ASSERT(field_count == 5);
+
+ upb::MessageDef::oneof_iterator msg_it = md->oneof_begin();
+ ASSERT(msg_it != md->oneof_end());
+ ASSERT((*msg_it) == o.get());
+
+#ifdef UPB_CXX11
+ // Test range-based for on both fields and oneofs (with the iterator adaptor).
+ field_count = 0;
+ for (auto* field : md->fields()) {
+ UPB_UNUSED(field);
+ field_count++;
+ }
+ ASSERT(field_count == 5);
+
+ int oneof_count = 0;
+ for (auto* oneof : md->oneofs()) {
+ UPB_UNUSED(oneof);
+ oneof_count++;
+ }
+ ASSERT(oneof_count == 1);
+#endif // UPB_CXX11
+
+ // Test that we can add a new field to the oneof and that it becomes a member
+ // of the msgdef as well.
+ upb::reffed_ptr<upb::FieldDef> newf(upb::FieldDef::New());
+ newf->set_name("new_field_10", &status);
+ ASSERT(status.ok());
+ newf->set_number(10, &status);
+ ASSERT(status.ok());
+ newf->set_label(UPB_LABEL_OPTIONAL);
+ newf->set_type(UPB_TYPE_INT32);
+ o->AddField(newf.get(), &status);
+ ASSERT(status.ok());
+ ASSERT(newf->containing_type() == md.get());
+
+ // Test that we can add a new field to the msgdef first and then to the oneof.
+ upb::reffed_ptr<upb::FieldDef> newf2(upb::FieldDef::New());
+ newf2->set_name("new_field_11", &status);
+ ASSERT(status.ok());
+ newf2->set_number(11, &status);
+ ASSERT(status.ok());
+ newf2->set_label(UPB_LABEL_OPTIONAL);
+ newf2->set_type(UPB_TYPE_INT32);
+ md->AddField(newf2.get(), &status);
+ ASSERT(status.ok());
+ o->AddField(newf2.get(), &status);
+ ASSERT(status.ok());
+ ASSERT(newf2->containing_oneof() == o.get());
+
+ // Test that we cannot add REQUIRED or REPEATED fields to the oneof.
+ upb::reffed_ptr<upb::FieldDef> newf3(upb::FieldDef::New());
+ newf3->set_name("new_field_12", &status);
+ ASSERT(status.ok());
+ newf3->set_number(12, &status);
+ ASSERT(status.ok());
+ newf3->set_label(UPB_LABEL_REQUIRED);
+ newf3->set_type(UPB_TYPE_INT32);
+ o->AddField(newf3.get(), &status);
+ ASSERT(!status.ok());
+ newf->set_label(UPB_LABEL_REPEATED);
+ o->AddField(newf3.get(), &status);
+ ASSERT(!status.ok());
+}
+
extern "C" {
int run_tests(int argc, char *argv[]) {
@@ -1173,6 +1272,8 @@ int run_tests(int argc, char *argv[]) {
TestHandlerDataDestruction();
+ TestOneofs();
+
return 0;
}
diff --git a/tests/test_def.c b/tests/test_def.c
index dcf80c0..800d685 100644
--- a/tests/test_def.c
+++ b/tests/test_def.c
@@ -189,7 +189,9 @@ static upb_fielddef *newfield(
ASSERT(upb_fielddef_setnumber(f, num, NULL));
upb_fielddef_settype(f, type);
upb_fielddef_setlabel(f, label);
- ASSERT(upb_fielddef_setsubdefname(f, type_name, NULL));
+ if (type_name) {
+ ASSERT(upb_fielddef_setsubdefname(f, type_name, NULL));
+ }
return f;
}
@@ -342,6 +344,91 @@ static void test_descriptor_flags() {
upb_msgdef_unref(m2, &m2);
}
+static void test_mapentry_check() {
+ upb_status s = UPB_STATUS_INIT;
+
+ upb_msgdef *m = upb_msgdef_new(&m);
+ upb_msgdef_setfullname(m, "TestMessage", &s);
+ upb_fielddef *f = upb_fielddef_new(&f);
+ 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 *subm = upb_msgdef_new(&subm);
+ upb_msgdef_setfullname(subm, "MapEntry", &s);
+ upb_msgdef_setmapentry(subm, true);
+
+ upb_symtab *symtab = upb_symtab_new(&symtab);
+ upb_def *defs[] = {UPB_UPCAST(m), UPB_UPCAST(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_fielddef_setlabel(f, UPB_LABEL_REPEATED);
+ upb_symtab_add(symtab, defs, 2, NULL, &s);
+ ASSERT(upb_ok(&s));
+
+ upb_symtab_unref(symtab, &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_symtab *symtab = upb_symtab_new(&symtab);
+ ASSERT(symtab != NULL);
+
+ // Create a test message for fields to refer to.
+ upb_msgdef *subm = upb_msgdef_newnamed("SubMessage", &symtab);
+ upb_msgdef_addfield(subm, newfield("field1", 1, UPB_TYPE_INT32,
+ UPB_LABEL_OPTIONAL, NULL, &symtab),
+ &symtab, NULL);
+ upb_def *subm_defs[] = {UPB_UPCAST(subm)};
+ ASSERT_STATUS(upb_symtab_add(symtab, subm_defs, 1, &symtab, &s), &s);
+
+ upb_msgdef *m = upb_msgdef_newnamed("TestMessage", &symtab);
+ ASSERT(upb_msgdef_numoneofs(m) == 0);
+
+ upb_oneofdef *o = upb_oneofdef_new(&o);
+ 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);
+
+ upb_def *defs[] = {UPB_UPCAST(m)};
+ ASSERT_STATUS(upb_symtab_add(symtab, defs, 1, &symtab, &s), &s);
+
+ ASSERT(upb_msgdef_numoneofs(m) == 1);
+ const upb_oneofdef *lookup_o = upb_msgdef_ntooz(m, "test_oneof");
+ ASSERT(lookup_o == o);
+
+ const upb_fielddef *lookup_field = upb_oneofdef_ntofz(o, "field1");
+ ASSERT(lookup_field != NULL && upb_fielddef_number(lookup_field) == 1);
+
+ upb_symtab_unref(symtab, &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");
@@ -358,5 +445,7 @@ int run_tests(int argc, char *argv[]) {
test_partial_freeze();
test_noreftracking();
test_descriptor_flags();
+ test_mapentry_check();
+ test_oneofs();
return 0;
}
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback