1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 // https://developers.google.com/protocol-buffers/
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
9 // * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 // * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
15 // * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 // Author: kenton@google.com (Kenton Varda)
32 // Based on original Protocol Buffers design by
33 // Sanjay Ghemawat, Jeff Dean, and others.
35 // This file makes extensive use of RFC 3092. :)
39 #include <google/protobuf/compiler/importer.h>
40 #include <google/protobuf/unittest.pb.h>
41 #include <google/protobuf/unittest_custom_options.pb.h>
42 #include <google/protobuf/io/zero_copy_stream_impl.h>
43 #include <google/protobuf/descriptor.pb.h>
44 #include <google/protobuf/descriptor.h>
45 #include <google/protobuf/descriptor_database.h>
46 #include <google/protobuf/dynamic_message.h>
47 #include <google/protobuf/text_format.h>
48 #include <google/protobuf/stubs/strutil.h>
49 #include <google/protobuf/stubs/substitute.h>
51 #include <google/protobuf/stubs/common.h>
52 #include <google/protobuf/testing/googletest.h>
53 #include <gtest/gtest.h>
58 // Can't use an anonymous namespace here due to brokenness of Tru64 compiler.
59 namespace descriptor_unittest {
61 // Some helpers to make assembling descriptors faster.
62 DescriptorProto* AddMessage(FileDescriptorProto* file, const string& name) {
63 DescriptorProto* result = file->add_message_type();
64 result->set_name(name);
68 DescriptorProto* AddNestedMessage(DescriptorProto* parent, const string& name) {
69 DescriptorProto* result = parent->add_nested_type();
70 result->set_name(name);
74 EnumDescriptorProto* AddEnum(FileDescriptorProto* file, const string& name) {
75 EnumDescriptorProto* result = file->add_enum_type();
76 result->set_name(name);
80 EnumDescriptorProto* AddNestedEnum(DescriptorProto* parent,
82 EnumDescriptorProto* result = parent->add_enum_type();
83 result->set_name(name);
87 ServiceDescriptorProto* AddService(FileDescriptorProto* file,
89 ServiceDescriptorProto* result = file->add_service();
90 result->set_name(name);
94 FieldDescriptorProto* AddField(DescriptorProto* parent,
95 const string& name, int number,
96 FieldDescriptorProto::Label label,
97 FieldDescriptorProto::Type type) {
98 FieldDescriptorProto* result = parent->add_field();
99 result->set_name(name);
100 result->set_number(number);
101 result->set_label(label);
102 result->set_type(type);
106 FieldDescriptorProto* AddExtension(FileDescriptorProto* file,
107 const string& extendee,
108 const string& name, int number,
109 FieldDescriptorProto::Label label,
110 FieldDescriptorProto::Type type) {
111 FieldDescriptorProto* result = file->add_extension();
112 result->set_name(name);
113 result->set_number(number);
114 result->set_label(label);
115 result->set_type(type);
116 result->set_extendee(extendee);
120 FieldDescriptorProto* AddNestedExtension(DescriptorProto* parent,
121 const string& extendee,
122 const string& name, int number,
123 FieldDescriptorProto::Label label,
124 FieldDescriptorProto::Type type) {
125 FieldDescriptorProto* result = parent->add_extension();
126 result->set_name(name);
127 result->set_number(number);
128 result->set_label(label);
129 result->set_type(type);
130 result->set_extendee(extendee);
134 DescriptorProto::ExtensionRange* AddExtensionRange(DescriptorProto* parent,
135 int start, int end) {
136 DescriptorProto::ExtensionRange* result = parent->add_extension_range();
137 result->set_start(start);
138 result->set_end(end);
142 EnumValueDescriptorProto* AddEnumValue(EnumDescriptorProto* enum_proto,
143 const string& name, int number) {
144 EnumValueDescriptorProto* result = enum_proto->add_value();
145 result->set_name(name);
146 result->set_number(number);
150 MethodDescriptorProto* AddMethod(ServiceDescriptorProto* service,
152 const string& input_type,
153 const string& output_type) {
154 MethodDescriptorProto* result = service->add_method();
155 result->set_name(name);
156 result->set_input_type(input_type);
157 result->set_output_type(output_type);
161 // Empty enums technically aren't allowed. We need to insert a dummy value
163 void AddEmptyEnum(FileDescriptorProto* file, const string& name) {
164 AddEnumValue(AddEnum(file, name), name + "_DUMMY", 1);
167 // ===================================================================
169 // Test simple files.
170 class FileDescriptorTest : public testing::Test {
172 virtual void SetUp() {
173 // Build descriptors for the following definitions:
176 // message FooMessage { extensions 1; }
177 // enum FooEnum {FOO_ENUM_VALUE = 1;}
178 // service FooService {}
179 // extend FooMessage { optional int32 foo_extension = 1; }
182 // package bar_package;
183 // message BarMessage { extensions 1; }
184 // enum BarEnum {BAR_ENUM_VALUE = 1;}
185 // service BarService {}
186 // extend BarMessage { optional int32 bar_extension = 1; }
188 // Also, we have an empty file "baz.proto". This file's purpose is to
189 // make sure that even though it has the same package as foo.proto,
190 // searching it for members of foo.proto won't work.
192 FileDescriptorProto foo_file;
193 foo_file.set_name("foo.proto");
194 AddExtensionRange(AddMessage(&foo_file, "FooMessage"), 1, 2);
195 AddEnumValue(AddEnum(&foo_file, "FooEnum"), "FOO_ENUM_VALUE", 1);
196 AddService(&foo_file, "FooService");
197 AddExtension(&foo_file, "FooMessage", "foo_extension", 1,
198 FieldDescriptorProto::LABEL_OPTIONAL,
199 FieldDescriptorProto::TYPE_INT32);
201 FileDescriptorProto bar_file;
202 bar_file.set_name("bar.proto");
203 bar_file.set_package("bar_package");
204 bar_file.add_dependency("foo.proto");
205 AddExtensionRange(AddMessage(&bar_file, "BarMessage"), 1, 2);
206 AddEnumValue(AddEnum(&bar_file, "BarEnum"), "BAR_ENUM_VALUE", 1);
207 AddService(&bar_file, "BarService");
208 AddExtension(&bar_file, "bar_package.BarMessage", "bar_extension", 1,
209 FieldDescriptorProto::LABEL_OPTIONAL,
210 FieldDescriptorProto::TYPE_INT32);
212 FileDescriptorProto baz_file;
213 baz_file.set_name("baz.proto");
215 // Build the descriptors and get the pointers.
216 foo_file_ = pool_.BuildFile(foo_file);
217 ASSERT_TRUE(foo_file_ != NULL);
219 bar_file_ = pool_.BuildFile(bar_file);
220 ASSERT_TRUE(bar_file_ != NULL);
222 baz_file_ = pool_.BuildFile(baz_file);
223 ASSERT_TRUE(baz_file_ != NULL);
225 ASSERT_EQ(1, foo_file_->message_type_count());
226 foo_message_ = foo_file_->message_type(0);
227 ASSERT_EQ(1, foo_file_->enum_type_count());
228 foo_enum_ = foo_file_->enum_type(0);
229 ASSERT_EQ(1, foo_enum_->value_count());
230 foo_enum_value_ = foo_enum_->value(0);
231 ASSERT_EQ(1, foo_file_->service_count());
232 foo_service_ = foo_file_->service(0);
233 ASSERT_EQ(1, foo_file_->extension_count());
234 foo_extension_ = foo_file_->extension(0);
236 ASSERT_EQ(1, bar_file_->message_type_count());
237 bar_message_ = bar_file_->message_type(0);
238 ASSERT_EQ(1, bar_file_->enum_type_count());
239 bar_enum_ = bar_file_->enum_type(0);
240 ASSERT_EQ(1, bar_enum_->value_count());
241 bar_enum_value_ = bar_enum_->value(0);
242 ASSERT_EQ(1, bar_file_->service_count());
243 bar_service_ = bar_file_->service(0);
244 ASSERT_EQ(1, bar_file_->extension_count());
245 bar_extension_ = bar_file_->extension(0);
248 DescriptorPool pool_;
250 const FileDescriptor* foo_file_;
251 const FileDescriptor* bar_file_;
252 const FileDescriptor* baz_file_;
254 const Descriptor* foo_message_;
255 const EnumDescriptor* foo_enum_;
256 const EnumValueDescriptor* foo_enum_value_;
257 const ServiceDescriptor* foo_service_;
258 const FieldDescriptor* foo_extension_;
260 const Descriptor* bar_message_;
261 const EnumDescriptor* bar_enum_;
262 const EnumValueDescriptor* bar_enum_value_;
263 const ServiceDescriptor* bar_service_;
264 const FieldDescriptor* bar_extension_;
267 TEST_F(FileDescriptorTest, Name) {
268 EXPECT_EQ("foo.proto", foo_file_->name());
269 EXPECT_EQ("bar.proto", bar_file_->name());
270 EXPECT_EQ("baz.proto", baz_file_->name());
273 TEST_F(FileDescriptorTest, Package) {
274 EXPECT_EQ("", foo_file_->package());
275 EXPECT_EQ("bar_package", bar_file_->package());
278 TEST_F(FileDescriptorTest, Dependencies) {
279 EXPECT_EQ(0, foo_file_->dependency_count());
280 EXPECT_EQ(1, bar_file_->dependency_count());
281 EXPECT_EQ(foo_file_, bar_file_->dependency(0));
284 TEST_F(FileDescriptorTest, FindMessageTypeByName) {
285 EXPECT_EQ(foo_message_, foo_file_->FindMessageTypeByName("FooMessage"));
286 EXPECT_EQ(bar_message_, bar_file_->FindMessageTypeByName("BarMessage"));
288 EXPECT_TRUE(foo_file_->FindMessageTypeByName("BarMessage") == NULL);
289 EXPECT_TRUE(bar_file_->FindMessageTypeByName("FooMessage") == NULL);
290 EXPECT_TRUE(baz_file_->FindMessageTypeByName("FooMessage") == NULL);
292 EXPECT_TRUE(foo_file_->FindMessageTypeByName("NoSuchMessage") == NULL);
293 EXPECT_TRUE(foo_file_->FindMessageTypeByName("FooEnum") == NULL);
296 TEST_F(FileDescriptorTest, FindEnumTypeByName) {
297 EXPECT_EQ(foo_enum_, foo_file_->FindEnumTypeByName("FooEnum"));
298 EXPECT_EQ(bar_enum_, bar_file_->FindEnumTypeByName("BarEnum"));
300 EXPECT_TRUE(foo_file_->FindEnumTypeByName("BarEnum") == NULL);
301 EXPECT_TRUE(bar_file_->FindEnumTypeByName("FooEnum") == NULL);
302 EXPECT_TRUE(baz_file_->FindEnumTypeByName("FooEnum") == NULL);
304 EXPECT_TRUE(foo_file_->FindEnumTypeByName("NoSuchEnum") == NULL);
305 EXPECT_TRUE(foo_file_->FindEnumTypeByName("FooMessage") == NULL);
308 TEST_F(FileDescriptorTest, FindEnumValueByName) {
309 EXPECT_EQ(foo_enum_value_, foo_file_->FindEnumValueByName("FOO_ENUM_VALUE"));
310 EXPECT_EQ(bar_enum_value_, bar_file_->FindEnumValueByName("BAR_ENUM_VALUE"));
312 EXPECT_TRUE(foo_file_->FindEnumValueByName("BAR_ENUM_VALUE") == NULL);
313 EXPECT_TRUE(bar_file_->FindEnumValueByName("FOO_ENUM_VALUE") == NULL);
314 EXPECT_TRUE(baz_file_->FindEnumValueByName("FOO_ENUM_VALUE") == NULL);
316 EXPECT_TRUE(foo_file_->FindEnumValueByName("NO_SUCH_VALUE") == NULL);
317 EXPECT_TRUE(foo_file_->FindEnumValueByName("FooMessage") == NULL);
320 TEST_F(FileDescriptorTest, FindServiceByName) {
321 EXPECT_EQ(foo_service_, foo_file_->FindServiceByName("FooService"));
322 EXPECT_EQ(bar_service_, bar_file_->FindServiceByName("BarService"));
324 EXPECT_TRUE(foo_file_->FindServiceByName("BarService") == NULL);
325 EXPECT_TRUE(bar_file_->FindServiceByName("FooService") == NULL);
326 EXPECT_TRUE(baz_file_->FindServiceByName("FooService") == NULL);
328 EXPECT_TRUE(foo_file_->FindServiceByName("NoSuchService") == NULL);
329 EXPECT_TRUE(foo_file_->FindServiceByName("FooMessage") == NULL);
332 TEST_F(FileDescriptorTest, FindExtensionByName) {
333 EXPECT_EQ(foo_extension_, foo_file_->FindExtensionByName("foo_extension"));
334 EXPECT_EQ(bar_extension_, bar_file_->FindExtensionByName("bar_extension"));
336 EXPECT_TRUE(foo_file_->FindExtensionByName("bar_extension") == NULL);
337 EXPECT_TRUE(bar_file_->FindExtensionByName("foo_extension") == NULL);
338 EXPECT_TRUE(baz_file_->FindExtensionByName("foo_extension") == NULL);
340 EXPECT_TRUE(foo_file_->FindExtensionByName("no_such_extension") == NULL);
341 EXPECT_TRUE(foo_file_->FindExtensionByName("FooMessage") == NULL);
344 TEST_F(FileDescriptorTest, FindExtensionByNumber) {
345 EXPECT_EQ(foo_extension_, pool_.FindExtensionByNumber(foo_message_, 1));
346 EXPECT_EQ(bar_extension_, pool_.FindExtensionByNumber(bar_message_, 1));
348 EXPECT_TRUE(pool_.FindExtensionByNumber(foo_message_, 2) == NULL);
351 TEST_F(FileDescriptorTest, BuildAgain) {
352 // Test that if te call BuildFile again on the same input we get the same
353 // FileDescriptor back.
354 FileDescriptorProto file;
355 foo_file_->CopyTo(&file);
356 EXPECT_EQ(foo_file_, pool_.BuildFile(file));
358 // But if we change the file then it won't work.
359 file.set_package("some.other.package");
360 EXPECT_TRUE(pool_.BuildFile(file) == NULL);
363 // ===================================================================
365 // Test simple flat messages and fields.
366 class DescriptorTest : public testing::Test {
368 virtual void SetUp() {
369 // Build descriptors for the following definitions:
372 // message TestForeign {}
375 // message TestMessage {
376 // required string foo = 1;
377 // optional TestEnum bar = 6;
378 // repeated TestForeign baz = 500000000;
379 // optional group qux = 15 {}
383 // package corge.grault;
384 // message TestMessage2 {
385 // required string foo = 1;
386 // required string bar = 2;
387 // required string quux = 6;
390 // We cheat and use TestForeign as the type for qux rather than create
391 // an actual nested type.
393 // Since all primitive types (including string) use the same building
394 // code, there's no need to test each one individually.
396 // TestMessage2 is primarily here to test FindFieldByName and friends.
397 // All messages created from the same DescriptorPool share the same lookup
398 // table, so we need to insure that they don't interfere.
400 FileDescriptorProto foo_file;
401 foo_file.set_name("foo.proto");
402 AddMessage(&foo_file, "TestForeign");
403 AddEmptyEnum(&foo_file, "TestEnum");
405 DescriptorProto* message = AddMessage(&foo_file, "TestMessage");
406 AddField(message, "foo", 1,
407 FieldDescriptorProto::LABEL_REQUIRED,
408 FieldDescriptorProto::TYPE_STRING);
409 AddField(message, "bar", 6,
410 FieldDescriptorProto::LABEL_OPTIONAL,
411 FieldDescriptorProto::TYPE_ENUM)
412 ->set_type_name("TestEnum");
413 AddField(message, "baz", 500000000,
414 FieldDescriptorProto::LABEL_REPEATED,
415 FieldDescriptorProto::TYPE_MESSAGE)
416 ->set_type_name("TestForeign");
417 AddField(message, "qux", 15,
418 FieldDescriptorProto::LABEL_OPTIONAL,
419 FieldDescriptorProto::TYPE_GROUP)
420 ->set_type_name("TestForeign");
422 FileDescriptorProto bar_file;
423 bar_file.set_name("bar.proto");
424 bar_file.set_package("corge.grault");
426 DescriptorProto* message2 = AddMessage(&bar_file, "TestMessage2");
427 AddField(message2, "foo", 1,
428 FieldDescriptorProto::LABEL_REQUIRED,
429 FieldDescriptorProto::TYPE_STRING);
430 AddField(message2, "bar", 2,
431 FieldDescriptorProto::LABEL_REQUIRED,
432 FieldDescriptorProto::TYPE_STRING);
433 AddField(message2, "quux", 6,
434 FieldDescriptorProto::LABEL_REQUIRED,
435 FieldDescriptorProto::TYPE_STRING);
437 // Build the descriptors and get the pointers.
438 foo_file_ = pool_.BuildFile(foo_file);
439 ASSERT_TRUE(foo_file_ != NULL);
441 bar_file_ = pool_.BuildFile(bar_file);
442 ASSERT_TRUE(bar_file_ != NULL);
444 ASSERT_EQ(1, foo_file_->enum_type_count());
445 enum_ = foo_file_->enum_type(0);
447 ASSERT_EQ(2, foo_file_->message_type_count());
448 foreign_ = foo_file_->message_type(0);
449 message_ = foo_file_->message_type(1);
451 ASSERT_EQ(4, message_->field_count());
452 foo_ = message_->field(0);
453 bar_ = message_->field(1);
454 baz_ = message_->field(2);
455 qux_ = message_->field(3);
457 ASSERT_EQ(1, bar_file_->message_type_count());
458 message2_ = bar_file_->message_type(0);
460 ASSERT_EQ(3, message2_->field_count());
461 foo2_ = message2_->field(0);
462 bar2_ = message2_->field(1);
463 quux2_ = message2_->field(2);
466 DescriptorPool pool_;
468 const FileDescriptor* foo_file_;
469 const FileDescriptor* bar_file_;
471 const Descriptor* message_;
472 const Descriptor* message2_;
473 const Descriptor* foreign_;
474 const EnumDescriptor* enum_;
476 const FieldDescriptor* foo_;
477 const FieldDescriptor* bar_;
478 const FieldDescriptor* baz_;
479 const FieldDescriptor* qux_;
481 const FieldDescriptor* foo2_;
482 const FieldDescriptor* bar2_;
483 const FieldDescriptor* quux2_;
486 TEST_F(DescriptorTest, Name) {
487 EXPECT_EQ("TestMessage", message_->name());
488 EXPECT_EQ("TestMessage", message_->full_name());
489 EXPECT_EQ(foo_file_, message_->file());
491 EXPECT_EQ("TestMessage2", message2_->name());
492 EXPECT_EQ("corge.grault.TestMessage2", message2_->full_name());
493 EXPECT_EQ(bar_file_, message2_->file());
496 TEST_F(DescriptorTest, ContainingType) {
497 EXPECT_TRUE(message_->containing_type() == NULL);
498 EXPECT_TRUE(message2_->containing_type() == NULL);
501 TEST_F(DescriptorTest, FieldsByIndex) {
502 ASSERT_EQ(4, message_->field_count());
503 EXPECT_EQ(foo_, message_->field(0));
504 EXPECT_EQ(bar_, message_->field(1));
505 EXPECT_EQ(baz_, message_->field(2));
506 EXPECT_EQ(qux_, message_->field(3));
509 TEST_F(DescriptorTest, FindFieldByName) {
510 // All messages in the same DescriptorPool share a single lookup table for
511 // fields. So, in addition to testing that FindFieldByName finds the fields
512 // of the message, we need to test that it does *not* find the fields of
515 EXPECT_EQ(foo_, message_->FindFieldByName("foo"));
516 EXPECT_EQ(bar_, message_->FindFieldByName("bar"));
517 EXPECT_EQ(baz_, message_->FindFieldByName("baz"));
518 EXPECT_EQ(qux_, message_->FindFieldByName("qux"));
519 EXPECT_TRUE(message_->FindFieldByName("no_such_field") == NULL);
520 EXPECT_TRUE(message_->FindFieldByName("quux") == NULL);
522 EXPECT_EQ(foo2_ , message2_->FindFieldByName("foo" ));
523 EXPECT_EQ(bar2_ , message2_->FindFieldByName("bar" ));
524 EXPECT_EQ(quux2_, message2_->FindFieldByName("quux"));
525 EXPECT_TRUE(message2_->FindFieldByName("baz") == NULL);
526 EXPECT_TRUE(message2_->FindFieldByName("qux") == NULL);
529 TEST_F(DescriptorTest, FindFieldByNumber) {
530 EXPECT_EQ(foo_, message_->FindFieldByNumber(1));
531 EXPECT_EQ(bar_, message_->FindFieldByNumber(6));
532 EXPECT_EQ(baz_, message_->FindFieldByNumber(500000000));
533 EXPECT_EQ(qux_, message_->FindFieldByNumber(15));
534 EXPECT_TRUE(message_->FindFieldByNumber(837592) == NULL);
535 EXPECT_TRUE(message_->FindFieldByNumber(2) == NULL);
537 EXPECT_EQ(foo2_ , message2_->FindFieldByNumber(1));
538 EXPECT_EQ(bar2_ , message2_->FindFieldByNumber(2));
539 EXPECT_EQ(quux2_, message2_->FindFieldByNumber(6));
540 EXPECT_TRUE(message2_->FindFieldByNumber(15) == NULL);
541 EXPECT_TRUE(message2_->FindFieldByNumber(500000000) == NULL);
544 TEST_F(DescriptorTest, FieldName) {
545 EXPECT_EQ("foo", foo_->name());
546 EXPECT_EQ("bar", bar_->name());
547 EXPECT_EQ("baz", baz_->name());
548 EXPECT_EQ("qux", qux_->name());
551 TEST_F(DescriptorTest, FieldFullName) {
552 EXPECT_EQ("TestMessage.foo", foo_->full_name());
553 EXPECT_EQ("TestMessage.bar", bar_->full_name());
554 EXPECT_EQ("TestMessage.baz", baz_->full_name());
555 EXPECT_EQ("TestMessage.qux", qux_->full_name());
557 EXPECT_EQ("corge.grault.TestMessage2.foo", foo2_->full_name());
558 EXPECT_EQ("corge.grault.TestMessage2.bar", bar2_->full_name());
559 EXPECT_EQ("corge.grault.TestMessage2.quux", quux2_->full_name());
562 TEST_F(DescriptorTest, FieldFile) {
563 EXPECT_EQ(foo_file_, foo_->file());
564 EXPECT_EQ(foo_file_, bar_->file());
565 EXPECT_EQ(foo_file_, baz_->file());
566 EXPECT_EQ(foo_file_, qux_->file());
568 EXPECT_EQ(bar_file_, foo2_->file());
569 EXPECT_EQ(bar_file_, bar2_->file());
570 EXPECT_EQ(bar_file_, quux2_->file());
573 TEST_F(DescriptorTest, FieldIndex) {
574 EXPECT_EQ(0, foo_->index());
575 EXPECT_EQ(1, bar_->index());
576 EXPECT_EQ(2, baz_->index());
577 EXPECT_EQ(3, qux_->index());
580 TEST_F(DescriptorTest, FieldNumber) {
581 EXPECT_EQ( 1, foo_->number());
582 EXPECT_EQ( 6, bar_->number());
583 EXPECT_EQ(500000000, baz_->number());
584 EXPECT_EQ( 15, qux_->number());
587 TEST_F(DescriptorTest, FieldType) {
588 EXPECT_EQ(FieldDescriptor::TYPE_STRING , foo_->type());
589 EXPECT_EQ(FieldDescriptor::TYPE_ENUM , bar_->type());
590 EXPECT_EQ(FieldDescriptor::TYPE_MESSAGE, baz_->type());
591 EXPECT_EQ(FieldDescriptor::TYPE_GROUP , qux_->type());
594 TEST_F(DescriptorTest, FieldLabel) {
595 EXPECT_EQ(FieldDescriptor::LABEL_REQUIRED, foo_->label());
596 EXPECT_EQ(FieldDescriptor::LABEL_OPTIONAL, bar_->label());
597 EXPECT_EQ(FieldDescriptor::LABEL_REPEATED, baz_->label());
598 EXPECT_EQ(FieldDescriptor::LABEL_OPTIONAL, qux_->label());
600 EXPECT_TRUE (foo_->is_required());
601 EXPECT_FALSE(foo_->is_optional());
602 EXPECT_FALSE(foo_->is_repeated());
604 EXPECT_FALSE(bar_->is_required());
605 EXPECT_TRUE (bar_->is_optional());
606 EXPECT_FALSE(bar_->is_repeated());
608 EXPECT_FALSE(baz_->is_required());
609 EXPECT_FALSE(baz_->is_optional());
610 EXPECT_TRUE (baz_->is_repeated());
613 TEST_F(DescriptorTest, FieldHasDefault) {
614 EXPECT_FALSE(foo_->has_default_value());
615 EXPECT_FALSE(bar_->has_default_value());
616 EXPECT_FALSE(baz_->has_default_value());
617 EXPECT_FALSE(qux_->has_default_value());
620 TEST_F(DescriptorTest, FieldContainingType) {
621 EXPECT_EQ(message_, foo_->containing_type());
622 EXPECT_EQ(message_, bar_->containing_type());
623 EXPECT_EQ(message_, baz_->containing_type());
624 EXPECT_EQ(message_, qux_->containing_type());
626 EXPECT_EQ(message2_, foo2_ ->containing_type());
627 EXPECT_EQ(message2_, bar2_ ->containing_type());
628 EXPECT_EQ(message2_, quux2_->containing_type());
631 TEST_F(DescriptorTest, FieldMessageType) {
632 EXPECT_TRUE(foo_->message_type() == NULL);
633 EXPECT_TRUE(bar_->message_type() == NULL);
635 EXPECT_EQ(foreign_, baz_->message_type());
636 EXPECT_EQ(foreign_, qux_->message_type());
639 TEST_F(DescriptorTest, FieldEnumType) {
640 EXPECT_TRUE(foo_->enum_type() == NULL);
641 EXPECT_TRUE(baz_->enum_type() == NULL);
642 EXPECT_TRUE(qux_->enum_type() == NULL);
644 EXPECT_EQ(enum_, bar_->enum_type());
647 // ===================================================================
649 // Test simple flat messages and fields.
650 class OneofDescriptorTest : public testing::Test {
652 virtual void SetUp() {
653 // Build descriptors for the following definitions:
656 // message TestOneof {
657 // optional int32 a = 1;
667 FileDescriptorProto baz_file;
668 baz_file.set_name("baz.proto");
669 baz_file.set_package("garply");
671 DescriptorProto* oneof_message = AddMessage(&baz_file, "TestOneof");
672 oneof_message->add_oneof_decl()->set_name("foo");
673 oneof_message->add_oneof_decl()->set_name("bar");
675 AddField(oneof_message, "a", 1,
676 FieldDescriptorProto::LABEL_OPTIONAL,
677 FieldDescriptorProto::TYPE_INT32);
678 AddField(oneof_message, "b", 2,
679 FieldDescriptorProto::LABEL_OPTIONAL,
680 FieldDescriptorProto::TYPE_STRING);
681 oneof_message->mutable_field(1)->set_oneof_index(0);
682 AddField(oneof_message, "c", 3,
683 FieldDescriptorProto::LABEL_OPTIONAL,
684 FieldDescriptorProto::TYPE_MESSAGE);
685 oneof_message->mutable_field(2)->set_oneof_index(0);
686 oneof_message->mutable_field(2)->set_type_name("TestOneof");
688 AddField(oneof_message, "d", 4,
689 FieldDescriptorProto::LABEL_OPTIONAL,
690 FieldDescriptorProto::TYPE_FLOAT);
691 oneof_message->mutable_field(3)->set_oneof_index(1);
693 // Build the descriptors and get the pointers.
694 baz_file_ = pool_.BuildFile(baz_file);
695 ASSERT_TRUE(baz_file_ != NULL);
697 ASSERT_EQ(1, baz_file_->message_type_count());
698 oneof_message_ = baz_file_->message_type(0);
700 ASSERT_EQ(2, oneof_message_->oneof_decl_count());
701 oneof_ = oneof_message_->oneof_decl(0);
702 oneof2_ = oneof_message_->oneof_decl(1);
704 ASSERT_EQ(4, oneof_message_->field_count());
705 a_ = oneof_message_->field(0);
706 b_ = oneof_message_->field(1);
707 c_ = oneof_message_->field(2);
708 d_ = oneof_message_->field(3);
711 DescriptorPool pool_;
713 const FileDescriptor* baz_file_;
715 const Descriptor* oneof_message_;
717 const OneofDescriptor* oneof_;
718 const OneofDescriptor* oneof2_;
719 const FieldDescriptor* a_;
720 const FieldDescriptor* b_;
721 const FieldDescriptor* c_;
722 const FieldDescriptor* d_;
723 const FieldDescriptor* e_;
724 const FieldDescriptor* f_;
727 TEST_F(OneofDescriptorTest, Normal) {
728 EXPECT_EQ("foo", oneof_->name());
729 EXPECT_EQ("garply.TestOneof.foo", oneof_->full_name());
730 EXPECT_EQ(0, oneof_->index());
731 ASSERT_EQ(2, oneof_->field_count());
732 EXPECT_EQ(b_, oneof_->field(0));
733 EXPECT_EQ(c_, oneof_->field(1));
734 EXPECT_TRUE(a_->containing_oneof() == NULL);
735 EXPECT_EQ(oneof_, b_->containing_oneof());
736 EXPECT_EQ(oneof_, c_->containing_oneof());
739 TEST_F(OneofDescriptorTest, FindByName) {
740 EXPECT_EQ(oneof_, oneof_message_->FindOneofByName("foo"));
741 EXPECT_EQ(oneof2_, oneof_message_->FindOneofByName("bar"));
742 EXPECT_TRUE(oneof_message_->FindOneofByName("no_such_oneof") == NULL);
745 // ===================================================================
747 class StylizedFieldNamesTest : public testing::Test {
750 FileDescriptorProto file;
751 file.set_name("foo.proto");
753 AddExtensionRange(AddMessage(&file, "ExtendableMessage"), 1, 1000);
755 DescriptorProto* message = AddMessage(&file, "TestMessage");
756 AddField(message, "foo_foo", 1,
757 FieldDescriptorProto::LABEL_OPTIONAL,
758 FieldDescriptorProto::TYPE_INT32);
759 AddField(message, "FooBar", 2,
760 FieldDescriptorProto::LABEL_OPTIONAL,
761 FieldDescriptorProto::TYPE_INT32);
762 AddField(message, "fooBaz", 3,
763 FieldDescriptorProto::LABEL_OPTIONAL,
764 FieldDescriptorProto::TYPE_INT32);
765 AddField(message, "fooFoo", 4, // Camel-case conflict with foo_foo.
766 FieldDescriptorProto::LABEL_OPTIONAL,
767 FieldDescriptorProto::TYPE_INT32);
768 AddField(message, "foobar", 5, // Lower-case conflict with FooBar.
769 FieldDescriptorProto::LABEL_OPTIONAL,
770 FieldDescriptorProto::TYPE_INT32);
772 AddNestedExtension(message, "ExtendableMessage", "bar_foo", 1,
773 FieldDescriptorProto::LABEL_OPTIONAL,
774 FieldDescriptorProto::TYPE_INT32);
775 AddNestedExtension(message, "ExtendableMessage", "BarBar", 2,
776 FieldDescriptorProto::LABEL_OPTIONAL,
777 FieldDescriptorProto::TYPE_INT32);
778 AddNestedExtension(message, "ExtendableMessage", "BarBaz", 3,
779 FieldDescriptorProto::LABEL_OPTIONAL,
780 FieldDescriptorProto::TYPE_INT32);
781 AddNestedExtension(message, "ExtendableMessage", "barFoo", 4, // Conflict
782 FieldDescriptorProto::LABEL_OPTIONAL,
783 FieldDescriptorProto::TYPE_INT32);
784 AddNestedExtension(message, "ExtendableMessage", "barbar", 5, // Conflict
785 FieldDescriptorProto::LABEL_OPTIONAL,
786 FieldDescriptorProto::TYPE_INT32);
788 AddExtension(&file, "ExtendableMessage", "baz_foo", 11,
789 FieldDescriptorProto::LABEL_OPTIONAL,
790 FieldDescriptorProto::TYPE_INT32);
791 AddExtension(&file, "ExtendableMessage", "BazBar", 12,
792 FieldDescriptorProto::LABEL_OPTIONAL,
793 FieldDescriptorProto::TYPE_INT32);
794 AddExtension(&file, "ExtendableMessage", "BazBaz", 13,
795 FieldDescriptorProto::LABEL_OPTIONAL,
796 FieldDescriptorProto::TYPE_INT32);
797 AddExtension(&file, "ExtendableMessage", "bazFoo", 14, // Conflict
798 FieldDescriptorProto::LABEL_OPTIONAL,
799 FieldDescriptorProto::TYPE_INT32);
800 AddExtension(&file, "ExtendableMessage", "bazbar", 15, // Conflict
801 FieldDescriptorProto::LABEL_OPTIONAL,
802 FieldDescriptorProto::TYPE_INT32);
804 file_ = pool_.BuildFile(file);
805 ASSERT_TRUE(file_ != NULL);
806 ASSERT_EQ(2, file_->message_type_count());
807 message_ = file_->message_type(1);
808 ASSERT_EQ("TestMessage", message_->name());
809 ASSERT_EQ(5, message_->field_count());
810 ASSERT_EQ(5, message_->extension_count());
811 ASSERT_EQ(5, file_->extension_count());
814 DescriptorPool pool_;
815 const FileDescriptor* file_;
816 const Descriptor* message_;
819 TEST_F(StylizedFieldNamesTest, LowercaseName) {
820 EXPECT_EQ("foo_foo", message_->field(0)->lowercase_name());
821 EXPECT_EQ("foobar" , message_->field(1)->lowercase_name());
822 EXPECT_EQ("foobaz" , message_->field(2)->lowercase_name());
823 EXPECT_EQ("foofoo" , message_->field(3)->lowercase_name());
824 EXPECT_EQ("foobar" , message_->field(4)->lowercase_name());
826 EXPECT_EQ("bar_foo", message_->extension(0)->lowercase_name());
827 EXPECT_EQ("barbar" , message_->extension(1)->lowercase_name());
828 EXPECT_EQ("barbaz" , message_->extension(2)->lowercase_name());
829 EXPECT_EQ("barfoo" , message_->extension(3)->lowercase_name());
830 EXPECT_EQ("barbar" , message_->extension(4)->lowercase_name());
832 EXPECT_EQ("baz_foo", file_->extension(0)->lowercase_name());
833 EXPECT_EQ("bazbar" , file_->extension(1)->lowercase_name());
834 EXPECT_EQ("bazbaz" , file_->extension(2)->lowercase_name());
835 EXPECT_EQ("bazfoo" , file_->extension(3)->lowercase_name());
836 EXPECT_EQ("bazbar" , file_->extension(4)->lowercase_name());
839 TEST_F(StylizedFieldNamesTest, CamelcaseName) {
840 EXPECT_EQ("fooFoo", message_->field(0)->camelcase_name());
841 EXPECT_EQ("fooBar", message_->field(1)->camelcase_name());
842 EXPECT_EQ("fooBaz", message_->field(2)->camelcase_name());
843 EXPECT_EQ("fooFoo", message_->field(3)->camelcase_name());
844 EXPECT_EQ("foobar", message_->field(4)->camelcase_name());
846 EXPECT_EQ("barFoo", message_->extension(0)->camelcase_name());
847 EXPECT_EQ("barBar", message_->extension(1)->camelcase_name());
848 EXPECT_EQ("barBaz", message_->extension(2)->camelcase_name());
849 EXPECT_EQ("barFoo", message_->extension(3)->camelcase_name());
850 EXPECT_EQ("barbar", message_->extension(4)->camelcase_name());
852 EXPECT_EQ("bazFoo", file_->extension(0)->camelcase_name());
853 EXPECT_EQ("bazBar", file_->extension(1)->camelcase_name());
854 EXPECT_EQ("bazBaz", file_->extension(2)->camelcase_name());
855 EXPECT_EQ("bazFoo", file_->extension(3)->camelcase_name());
856 EXPECT_EQ("bazbar", file_->extension(4)->camelcase_name());
859 TEST_F(StylizedFieldNamesTest, FindByLowercaseName) {
860 EXPECT_EQ(message_->field(0),
861 message_->FindFieldByLowercaseName("foo_foo"));
862 EXPECT_EQ(message_->field(1),
863 message_->FindFieldByLowercaseName("foobar"));
864 EXPECT_EQ(message_->field(2),
865 message_->FindFieldByLowercaseName("foobaz"));
866 EXPECT_TRUE(message_->FindFieldByLowercaseName("FooBar") == NULL);
867 EXPECT_TRUE(message_->FindFieldByLowercaseName("fooBaz") == NULL);
868 EXPECT_TRUE(message_->FindFieldByLowercaseName("bar_foo") == NULL);
869 EXPECT_TRUE(message_->FindFieldByLowercaseName("nosuchfield") == NULL);
871 EXPECT_EQ(message_->extension(0),
872 message_->FindExtensionByLowercaseName("bar_foo"));
873 EXPECT_EQ(message_->extension(1),
874 message_->FindExtensionByLowercaseName("barbar"));
875 EXPECT_EQ(message_->extension(2),
876 message_->FindExtensionByLowercaseName("barbaz"));
877 EXPECT_TRUE(message_->FindExtensionByLowercaseName("BarBar") == NULL);
878 EXPECT_TRUE(message_->FindExtensionByLowercaseName("barBaz") == NULL);
879 EXPECT_TRUE(message_->FindExtensionByLowercaseName("foo_foo") == NULL);
880 EXPECT_TRUE(message_->FindExtensionByLowercaseName("nosuchfield") == NULL);
882 EXPECT_EQ(file_->extension(0),
883 file_->FindExtensionByLowercaseName("baz_foo"));
884 EXPECT_EQ(file_->extension(1),
885 file_->FindExtensionByLowercaseName("bazbar"));
886 EXPECT_EQ(file_->extension(2),
887 file_->FindExtensionByLowercaseName("bazbaz"));
888 EXPECT_TRUE(file_->FindExtensionByLowercaseName("BazBar") == NULL);
889 EXPECT_TRUE(file_->FindExtensionByLowercaseName("bazBaz") == NULL);
890 EXPECT_TRUE(file_->FindExtensionByLowercaseName("nosuchfield") == NULL);
893 TEST_F(StylizedFieldNamesTest, FindByCamelcaseName) {
894 EXPECT_EQ(message_->field(0),
895 message_->FindFieldByCamelcaseName("fooFoo"));
896 EXPECT_EQ(message_->field(1),
897 message_->FindFieldByCamelcaseName("fooBar"));
898 EXPECT_EQ(message_->field(2),
899 message_->FindFieldByCamelcaseName("fooBaz"));
900 EXPECT_TRUE(message_->FindFieldByCamelcaseName("foo_foo") == NULL);
901 EXPECT_TRUE(message_->FindFieldByCamelcaseName("FooBar") == NULL);
902 EXPECT_TRUE(message_->FindFieldByCamelcaseName("barFoo") == NULL);
903 EXPECT_TRUE(message_->FindFieldByCamelcaseName("nosuchfield") == NULL);
905 EXPECT_EQ(message_->extension(0),
906 message_->FindExtensionByCamelcaseName("barFoo"));
907 EXPECT_EQ(message_->extension(1),
908 message_->FindExtensionByCamelcaseName("barBar"));
909 EXPECT_EQ(message_->extension(2),
910 message_->FindExtensionByCamelcaseName("barBaz"));
911 EXPECT_TRUE(message_->FindExtensionByCamelcaseName("bar_foo") == NULL);
912 EXPECT_TRUE(message_->FindExtensionByCamelcaseName("BarBar") == NULL);
913 EXPECT_TRUE(message_->FindExtensionByCamelcaseName("fooFoo") == NULL);
914 EXPECT_TRUE(message_->FindExtensionByCamelcaseName("nosuchfield") == NULL);
916 EXPECT_EQ(file_->extension(0),
917 file_->FindExtensionByCamelcaseName("bazFoo"));
918 EXPECT_EQ(file_->extension(1),
919 file_->FindExtensionByCamelcaseName("bazBar"));
920 EXPECT_EQ(file_->extension(2),
921 file_->FindExtensionByCamelcaseName("bazBaz"));
922 EXPECT_TRUE(file_->FindExtensionByCamelcaseName("baz_foo") == NULL);
923 EXPECT_TRUE(file_->FindExtensionByCamelcaseName("BazBar") == NULL);
924 EXPECT_TRUE(file_->FindExtensionByCamelcaseName("nosuchfield") == NULL);
927 // ===================================================================
929 // Test enum descriptors.
930 class EnumDescriptorTest : public testing::Test {
932 virtual void SetUp() {
933 // Build descriptors for the following definitions:
942 // package corge.grault;
948 // TestEnum2 is primarily here to test FindValueByName and friends.
949 // All enums created from the same DescriptorPool share the same lookup
950 // table, so we need to insure that they don't interfere.
953 FileDescriptorProto foo_file;
954 foo_file.set_name("foo.proto");
956 EnumDescriptorProto* enum_proto = AddEnum(&foo_file, "TestEnum");
957 AddEnumValue(enum_proto, "FOO", 1);
958 AddEnumValue(enum_proto, "BAR", 2);
961 FileDescriptorProto bar_file;
962 bar_file.set_name("bar.proto");
963 bar_file.set_package("corge.grault");
965 EnumDescriptorProto* enum2_proto = AddEnum(&bar_file, "TestEnum2");
966 AddEnumValue(enum2_proto, "FOO", 1);
967 AddEnumValue(enum2_proto, "BAZ", 3);
969 // Build the descriptors and get the pointers.
970 foo_file_ = pool_.BuildFile(foo_file);
971 ASSERT_TRUE(foo_file_ != NULL);
973 bar_file_ = pool_.BuildFile(bar_file);
974 ASSERT_TRUE(bar_file_ != NULL);
976 ASSERT_EQ(1, foo_file_->enum_type_count());
977 enum_ = foo_file_->enum_type(0);
979 ASSERT_EQ(2, enum_->value_count());
980 foo_ = enum_->value(0);
981 bar_ = enum_->value(1);
983 ASSERT_EQ(1, bar_file_->enum_type_count());
984 enum2_ = bar_file_->enum_type(0);
986 ASSERT_EQ(2, enum2_->value_count());
987 foo2_ = enum2_->value(0);
988 baz2_ = enum2_->value(1);
991 DescriptorPool pool_;
993 const FileDescriptor* foo_file_;
994 const FileDescriptor* bar_file_;
996 const EnumDescriptor* enum_;
997 const EnumDescriptor* enum2_;
999 const EnumValueDescriptor* foo_;
1000 const EnumValueDescriptor* bar_;
1002 const EnumValueDescriptor* foo2_;
1003 const EnumValueDescriptor* baz2_;
1006 TEST_F(EnumDescriptorTest, Name) {
1007 EXPECT_EQ("TestEnum", enum_->name());
1008 EXPECT_EQ("TestEnum", enum_->full_name());
1009 EXPECT_EQ(foo_file_, enum_->file());
1011 EXPECT_EQ("TestEnum2", enum2_->name());
1012 EXPECT_EQ("corge.grault.TestEnum2", enum2_->full_name());
1013 EXPECT_EQ(bar_file_, enum2_->file());
1016 TEST_F(EnumDescriptorTest, ContainingType) {
1017 EXPECT_TRUE(enum_->containing_type() == NULL);
1018 EXPECT_TRUE(enum2_->containing_type() == NULL);
1021 TEST_F(EnumDescriptorTest, ValuesByIndex) {
1022 ASSERT_EQ(2, enum_->value_count());
1023 EXPECT_EQ(foo_, enum_->value(0));
1024 EXPECT_EQ(bar_, enum_->value(1));
1027 TEST_F(EnumDescriptorTest, FindValueByName) {
1028 EXPECT_EQ(foo_ , enum_ ->FindValueByName("FOO"));
1029 EXPECT_EQ(bar_ , enum_ ->FindValueByName("BAR"));
1030 EXPECT_EQ(foo2_, enum2_->FindValueByName("FOO"));
1031 EXPECT_EQ(baz2_, enum2_->FindValueByName("BAZ"));
1033 EXPECT_TRUE(enum_ ->FindValueByName("NO_SUCH_VALUE") == NULL);
1034 EXPECT_TRUE(enum_ ->FindValueByName("BAZ" ) == NULL);
1035 EXPECT_TRUE(enum2_->FindValueByName("BAR" ) == NULL);
1038 TEST_F(EnumDescriptorTest, FindValueByNumber) {
1039 EXPECT_EQ(foo_ , enum_ ->FindValueByNumber(1));
1040 EXPECT_EQ(bar_ , enum_ ->FindValueByNumber(2));
1041 EXPECT_EQ(foo2_, enum2_->FindValueByNumber(1));
1042 EXPECT_EQ(baz2_, enum2_->FindValueByNumber(3));
1044 EXPECT_TRUE(enum_ ->FindValueByNumber(416) == NULL);
1045 EXPECT_TRUE(enum_ ->FindValueByNumber(3) == NULL);
1046 EXPECT_TRUE(enum2_->FindValueByNumber(2) == NULL);
1049 TEST_F(EnumDescriptorTest, ValueName) {
1050 EXPECT_EQ("FOO", foo_->name());
1051 EXPECT_EQ("BAR", bar_->name());
1054 TEST_F(EnumDescriptorTest, ValueFullName) {
1055 EXPECT_EQ("FOO", foo_->full_name());
1056 EXPECT_EQ("BAR", bar_->full_name());
1057 EXPECT_EQ("corge.grault.FOO", foo2_->full_name());
1058 EXPECT_EQ("corge.grault.BAZ", baz2_->full_name());
1061 TEST_F(EnumDescriptorTest, ValueIndex) {
1062 EXPECT_EQ(0, foo_->index());
1063 EXPECT_EQ(1, bar_->index());
1066 TEST_F(EnumDescriptorTest, ValueNumber) {
1067 EXPECT_EQ(1, foo_->number());
1068 EXPECT_EQ(2, bar_->number());
1071 TEST_F(EnumDescriptorTest, ValueType) {
1072 EXPECT_EQ(enum_ , foo_ ->type());
1073 EXPECT_EQ(enum_ , bar_ ->type());
1074 EXPECT_EQ(enum2_, foo2_->type());
1075 EXPECT_EQ(enum2_, baz2_->type());
1078 // ===================================================================
1080 // Test service descriptors.
1081 class ServiceDescriptorTest : public testing::Test {
1083 virtual void SetUp() {
1084 // Build descriptors for the following messages and service:
1085 // // in "foo.proto"
1086 // message FooRequest {}
1087 // message FooResponse {}
1088 // message BarRequest {}
1089 // message BarResponse {}
1090 // message BazRequest {}
1091 // message BazResponse {}
1093 // service TestService {
1094 // rpc Foo(FooRequest) returns (FooResponse);
1095 // rpc Bar(BarRequest) returns (BarResponse);
1098 // // in "bar.proto"
1099 // package corge.grault
1100 // service TestService2 {
1101 // rpc Foo(FooRequest) returns (FooResponse);
1102 // rpc Baz(BazRequest) returns (BazResponse);
1105 FileDescriptorProto foo_file;
1106 foo_file.set_name("foo.proto");
1108 AddMessage(&foo_file, "FooRequest");
1109 AddMessage(&foo_file, "FooResponse");
1110 AddMessage(&foo_file, "BarRequest");
1111 AddMessage(&foo_file, "BarResponse");
1112 AddMessage(&foo_file, "BazRequest");
1113 AddMessage(&foo_file, "BazResponse");
1115 ServiceDescriptorProto* service = AddService(&foo_file, "TestService");
1116 AddMethod(service, "Foo", "FooRequest", "FooResponse");
1117 AddMethod(service, "Bar", "BarRequest", "BarResponse");
1119 FileDescriptorProto bar_file;
1120 bar_file.set_name("bar.proto");
1121 bar_file.set_package("corge.grault");
1122 bar_file.add_dependency("foo.proto");
1124 ServiceDescriptorProto* service2 = AddService(&bar_file, "TestService2");
1125 AddMethod(service2, "Foo", "FooRequest", "FooResponse");
1126 AddMethod(service2, "Baz", "BazRequest", "BazResponse");
1128 // Build the descriptors and get the pointers.
1129 foo_file_ = pool_.BuildFile(foo_file);
1130 ASSERT_TRUE(foo_file_ != NULL);
1132 bar_file_ = pool_.BuildFile(bar_file);
1133 ASSERT_TRUE(bar_file_ != NULL);
1135 ASSERT_EQ(6, foo_file_->message_type_count());
1136 foo_request_ = foo_file_->message_type(0);
1137 foo_response_ = foo_file_->message_type(1);
1138 bar_request_ = foo_file_->message_type(2);
1139 bar_response_ = foo_file_->message_type(3);
1140 baz_request_ = foo_file_->message_type(4);
1141 baz_response_ = foo_file_->message_type(5);
1143 ASSERT_EQ(1, foo_file_->service_count());
1144 service_ = foo_file_->service(0);
1146 ASSERT_EQ(2, service_->method_count());
1147 foo_ = service_->method(0);
1148 bar_ = service_->method(1);
1150 ASSERT_EQ(1, bar_file_->service_count());
1151 service2_ = bar_file_->service(0);
1153 ASSERT_EQ(2, service2_->method_count());
1154 foo2_ = service2_->method(0);
1155 baz2_ = service2_->method(1);
1158 DescriptorPool pool_;
1160 const FileDescriptor* foo_file_;
1161 const FileDescriptor* bar_file_;
1163 const Descriptor* foo_request_;
1164 const Descriptor* foo_response_;
1165 const Descriptor* bar_request_;
1166 const Descriptor* bar_response_;
1167 const Descriptor* baz_request_;
1168 const Descriptor* baz_response_;
1170 const ServiceDescriptor* service_;
1171 const ServiceDescriptor* service2_;
1173 const MethodDescriptor* foo_;
1174 const MethodDescriptor* bar_;
1176 const MethodDescriptor* foo2_;
1177 const MethodDescriptor* baz2_;
1180 TEST_F(ServiceDescriptorTest, Name) {
1181 EXPECT_EQ("TestService", service_->name());
1182 EXPECT_EQ("TestService", service_->full_name());
1183 EXPECT_EQ(foo_file_, service_->file());
1185 EXPECT_EQ("TestService2", service2_->name());
1186 EXPECT_EQ("corge.grault.TestService2", service2_->full_name());
1187 EXPECT_EQ(bar_file_, service2_->file());
1190 TEST_F(ServiceDescriptorTest, MethodsByIndex) {
1191 ASSERT_EQ(2, service_->method_count());
1192 EXPECT_EQ(foo_, service_->method(0));
1193 EXPECT_EQ(bar_, service_->method(1));
1196 TEST_F(ServiceDescriptorTest, FindMethodByName) {
1197 EXPECT_EQ(foo_ , service_ ->FindMethodByName("Foo"));
1198 EXPECT_EQ(bar_ , service_ ->FindMethodByName("Bar"));
1199 EXPECT_EQ(foo2_, service2_->FindMethodByName("Foo"));
1200 EXPECT_EQ(baz2_, service2_->FindMethodByName("Baz"));
1202 EXPECT_TRUE(service_ ->FindMethodByName("NoSuchMethod") == NULL);
1203 EXPECT_TRUE(service_ ->FindMethodByName("Baz" ) == NULL);
1204 EXPECT_TRUE(service2_->FindMethodByName("Bar" ) == NULL);
1207 TEST_F(ServiceDescriptorTest, MethodName) {
1208 EXPECT_EQ("Foo", foo_->name());
1209 EXPECT_EQ("Bar", bar_->name());
1212 TEST_F(ServiceDescriptorTest, MethodFullName) {
1213 EXPECT_EQ("TestService.Foo", foo_->full_name());
1214 EXPECT_EQ("TestService.Bar", bar_->full_name());
1215 EXPECT_EQ("corge.grault.TestService2.Foo", foo2_->full_name());
1216 EXPECT_EQ("corge.grault.TestService2.Baz", baz2_->full_name());
1219 TEST_F(ServiceDescriptorTest, MethodIndex) {
1220 EXPECT_EQ(0, foo_->index());
1221 EXPECT_EQ(1, bar_->index());
1224 TEST_F(ServiceDescriptorTest, MethodParent) {
1225 EXPECT_EQ(service_, foo_->service());
1226 EXPECT_EQ(service_, bar_->service());
1229 TEST_F(ServiceDescriptorTest, MethodInputType) {
1230 EXPECT_EQ(foo_request_, foo_->input_type());
1231 EXPECT_EQ(bar_request_, bar_->input_type());
1234 TEST_F(ServiceDescriptorTest, MethodOutputType) {
1235 EXPECT_EQ(foo_response_, foo_->output_type());
1236 EXPECT_EQ(bar_response_, bar_->output_type());
1239 // ===================================================================
1241 // Test nested types.
1242 class NestedDescriptorTest : public testing::Test {
1244 virtual void SetUp() {
1245 // Build descriptors for the following definitions:
1247 // // in "foo.proto"
1248 // message TestMessage {
1251 // enum Baz { A = 1; }
1252 // enum Qux { B = 1; }
1255 // // in "bar.proto"
1256 // package corge.grault;
1257 // message TestMessage2 {
1260 // enum Qux { A = 1; }
1261 // enum Quux { C = 1; }
1264 // TestMessage2 is primarily here to test FindNestedTypeByName and friends.
1265 // All messages created from the same DescriptorPool share the same lookup
1266 // table, so we need to insure that they don't interfere.
1268 // We add enum values to the enums in order to test searching for enum
1269 // values across a message's scope.
1271 FileDescriptorProto foo_file;
1272 foo_file.set_name("foo.proto");
1274 DescriptorProto* message = AddMessage(&foo_file, "TestMessage");
1275 AddNestedMessage(message, "Foo");
1276 AddNestedMessage(message, "Bar");
1277 EnumDescriptorProto* baz = AddNestedEnum(message, "Baz");
1278 AddEnumValue(baz, "A", 1);
1279 EnumDescriptorProto* qux = AddNestedEnum(message, "Qux");
1280 AddEnumValue(qux, "B", 1);
1282 FileDescriptorProto bar_file;
1283 bar_file.set_name("bar.proto");
1284 bar_file.set_package("corge.grault");
1286 DescriptorProto* message2 = AddMessage(&bar_file, "TestMessage2");
1287 AddNestedMessage(message2, "Foo");
1288 AddNestedMessage(message2, "Baz");
1289 EnumDescriptorProto* qux2 = AddNestedEnum(message2, "Qux");
1290 AddEnumValue(qux2, "A", 1);
1291 EnumDescriptorProto* quux2 = AddNestedEnum(message2, "Quux");
1292 AddEnumValue(quux2, "C", 1);
1294 // Build the descriptors and get the pointers.
1295 foo_file_ = pool_.BuildFile(foo_file);
1296 ASSERT_TRUE(foo_file_ != NULL);
1298 bar_file_ = pool_.BuildFile(bar_file);
1299 ASSERT_TRUE(bar_file_ != NULL);
1301 ASSERT_EQ(1, foo_file_->message_type_count());
1302 message_ = foo_file_->message_type(0);
1304 ASSERT_EQ(2, message_->nested_type_count());
1305 foo_ = message_->nested_type(0);
1306 bar_ = message_->nested_type(1);
1308 ASSERT_EQ(2, message_->enum_type_count());
1309 baz_ = message_->enum_type(0);
1310 qux_ = message_->enum_type(1);
1312 ASSERT_EQ(1, baz_->value_count());
1313 a_ = baz_->value(0);
1314 ASSERT_EQ(1, qux_->value_count());
1315 b_ = qux_->value(0);
1317 ASSERT_EQ(1, bar_file_->message_type_count());
1318 message2_ = bar_file_->message_type(0);
1320 ASSERT_EQ(2, message2_->nested_type_count());
1321 foo2_ = message2_->nested_type(0);
1322 baz2_ = message2_->nested_type(1);
1324 ASSERT_EQ(2, message2_->enum_type_count());
1325 qux2_ = message2_->enum_type(0);
1326 quux2_ = message2_->enum_type(1);
1328 ASSERT_EQ(1, qux2_->value_count());
1329 a2_ = qux2_->value(0);
1330 ASSERT_EQ(1, quux2_->value_count());
1331 c2_ = quux2_->value(0);
1334 DescriptorPool pool_;
1336 const FileDescriptor* foo_file_;
1337 const FileDescriptor* bar_file_;
1339 const Descriptor* message_;
1340 const Descriptor* message2_;
1342 const Descriptor* foo_;
1343 const Descriptor* bar_;
1344 const EnumDescriptor* baz_;
1345 const EnumDescriptor* qux_;
1346 const EnumValueDescriptor* a_;
1347 const EnumValueDescriptor* b_;
1349 const Descriptor* foo2_;
1350 const Descriptor* baz2_;
1351 const EnumDescriptor* qux2_;
1352 const EnumDescriptor* quux2_;
1353 const EnumValueDescriptor* a2_;
1354 const EnumValueDescriptor* c2_;
1357 TEST_F(NestedDescriptorTest, MessageName) {
1358 EXPECT_EQ("Foo", foo_ ->name());
1359 EXPECT_EQ("Bar", bar_ ->name());
1360 EXPECT_EQ("Foo", foo2_->name());
1361 EXPECT_EQ("Baz", baz2_->name());
1363 EXPECT_EQ("TestMessage.Foo", foo_->full_name());
1364 EXPECT_EQ("TestMessage.Bar", bar_->full_name());
1365 EXPECT_EQ("corge.grault.TestMessage2.Foo", foo2_->full_name());
1366 EXPECT_EQ("corge.grault.TestMessage2.Baz", baz2_->full_name());
1369 TEST_F(NestedDescriptorTest, MessageContainingType) {
1370 EXPECT_EQ(message_ , foo_ ->containing_type());
1371 EXPECT_EQ(message_ , bar_ ->containing_type());
1372 EXPECT_EQ(message2_, foo2_->containing_type());
1373 EXPECT_EQ(message2_, baz2_->containing_type());
1376 TEST_F(NestedDescriptorTest, NestedMessagesByIndex) {
1377 ASSERT_EQ(2, message_->nested_type_count());
1378 EXPECT_EQ(foo_, message_->nested_type(0));
1379 EXPECT_EQ(bar_, message_->nested_type(1));
1382 TEST_F(NestedDescriptorTest, FindFieldByNameDoesntFindNestedTypes) {
1383 EXPECT_TRUE(message_->FindFieldByName("Foo") == NULL);
1384 EXPECT_TRUE(message_->FindFieldByName("Qux") == NULL);
1385 EXPECT_TRUE(message_->FindExtensionByName("Foo") == NULL);
1386 EXPECT_TRUE(message_->FindExtensionByName("Qux") == NULL);
1389 TEST_F(NestedDescriptorTest, FindNestedTypeByName) {
1390 EXPECT_EQ(foo_ , message_ ->FindNestedTypeByName("Foo"));
1391 EXPECT_EQ(bar_ , message_ ->FindNestedTypeByName("Bar"));
1392 EXPECT_EQ(foo2_, message2_->FindNestedTypeByName("Foo"));
1393 EXPECT_EQ(baz2_, message2_->FindNestedTypeByName("Baz"));
1395 EXPECT_TRUE(message_ ->FindNestedTypeByName("NoSuchType") == NULL);
1396 EXPECT_TRUE(message_ ->FindNestedTypeByName("Baz" ) == NULL);
1397 EXPECT_TRUE(message2_->FindNestedTypeByName("Bar" ) == NULL);
1399 EXPECT_TRUE(message_->FindNestedTypeByName("Qux") == NULL);
1402 TEST_F(NestedDescriptorTest, EnumName) {
1403 EXPECT_EQ("Baz" , baz_ ->name());
1404 EXPECT_EQ("Qux" , qux_ ->name());
1405 EXPECT_EQ("Qux" , qux2_->name());
1406 EXPECT_EQ("Quux", quux2_->name());
1408 EXPECT_EQ("TestMessage.Baz", baz_->full_name());
1409 EXPECT_EQ("TestMessage.Qux", qux_->full_name());
1410 EXPECT_EQ("corge.grault.TestMessage2.Qux" , qux2_ ->full_name());
1411 EXPECT_EQ("corge.grault.TestMessage2.Quux", quux2_->full_name());
1414 TEST_F(NestedDescriptorTest, EnumContainingType) {
1415 EXPECT_EQ(message_ , baz_ ->containing_type());
1416 EXPECT_EQ(message_ , qux_ ->containing_type());
1417 EXPECT_EQ(message2_, qux2_ ->containing_type());
1418 EXPECT_EQ(message2_, quux2_->containing_type());
1421 TEST_F(NestedDescriptorTest, NestedEnumsByIndex) {
1422 ASSERT_EQ(2, message_->nested_type_count());
1423 EXPECT_EQ(foo_, message_->nested_type(0));
1424 EXPECT_EQ(bar_, message_->nested_type(1));
1427 TEST_F(NestedDescriptorTest, FindEnumTypeByName) {
1428 EXPECT_EQ(baz_ , message_ ->FindEnumTypeByName("Baz" ));
1429 EXPECT_EQ(qux_ , message_ ->FindEnumTypeByName("Qux" ));
1430 EXPECT_EQ(qux2_ , message2_->FindEnumTypeByName("Qux" ));
1431 EXPECT_EQ(quux2_, message2_->FindEnumTypeByName("Quux"));
1433 EXPECT_TRUE(message_ ->FindEnumTypeByName("NoSuchType") == NULL);
1434 EXPECT_TRUE(message_ ->FindEnumTypeByName("Quux" ) == NULL);
1435 EXPECT_TRUE(message2_->FindEnumTypeByName("Baz" ) == NULL);
1437 EXPECT_TRUE(message_->FindEnumTypeByName("Foo") == NULL);
1440 TEST_F(NestedDescriptorTest, FindEnumValueByName) {
1441 EXPECT_EQ(a_ , message_ ->FindEnumValueByName("A"));
1442 EXPECT_EQ(b_ , message_ ->FindEnumValueByName("B"));
1443 EXPECT_EQ(a2_, message2_->FindEnumValueByName("A"));
1444 EXPECT_EQ(c2_, message2_->FindEnumValueByName("C"));
1446 EXPECT_TRUE(message_ ->FindEnumValueByName("NO_SUCH_VALUE") == NULL);
1447 EXPECT_TRUE(message_ ->FindEnumValueByName("C" ) == NULL);
1448 EXPECT_TRUE(message2_->FindEnumValueByName("B" ) == NULL);
1450 EXPECT_TRUE(message_->FindEnumValueByName("Foo") == NULL);
1453 // ===================================================================
1456 class ExtensionDescriptorTest : public testing::Test {
1458 virtual void SetUp() {
1459 // Build descriptors for the following definitions:
1465 // extensions 10 to 19;
1466 // extensions 30 to 39;
1468 // extends Foo with optional int32 foo_int32 = 10;
1469 // extends Foo with repeated TestEnum foo_enum = 19;
1471 // extends Foo with optional Qux foo_message = 30;
1472 // // (using Qux as the group type)
1473 // extends Foo with repeated group foo_group = 39;
1476 FileDescriptorProto foo_file;
1477 foo_file.set_name("foo.proto");
1479 AddEmptyEnum(&foo_file, "Baz");
1480 AddMessage(&foo_file, "Qux");
1482 DescriptorProto* foo = AddMessage(&foo_file, "Foo");
1483 AddExtensionRange(foo, 10, 20);
1484 AddExtensionRange(foo, 30, 40);
1486 AddExtension(&foo_file, "Foo", "foo_int32", 10,
1487 FieldDescriptorProto::LABEL_OPTIONAL,
1488 FieldDescriptorProto::TYPE_INT32);
1489 AddExtension(&foo_file, "Foo", "foo_enum", 19,
1490 FieldDescriptorProto::LABEL_REPEATED,
1491 FieldDescriptorProto::TYPE_ENUM)
1492 ->set_type_name("Baz");
1494 DescriptorProto* bar = AddMessage(&foo_file, "Bar");
1495 AddNestedExtension(bar, "Foo", "foo_message", 30,
1496 FieldDescriptorProto::LABEL_OPTIONAL,
1497 FieldDescriptorProto::TYPE_MESSAGE)
1498 ->set_type_name("Qux");
1499 AddNestedExtension(bar, "Foo", "foo_group", 39,
1500 FieldDescriptorProto::LABEL_REPEATED,
1501 FieldDescriptorProto::TYPE_GROUP)
1502 ->set_type_name("Qux");
1504 // Build the descriptors and get the pointers.
1505 foo_file_ = pool_.BuildFile(foo_file);
1506 ASSERT_TRUE(foo_file_ != NULL);
1508 ASSERT_EQ(1, foo_file_->enum_type_count());
1509 baz_ = foo_file_->enum_type(0);
1511 ASSERT_EQ(3, foo_file_->message_type_count());
1512 qux_ = foo_file_->message_type(0);
1513 foo_ = foo_file_->message_type(1);
1514 bar_ = foo_file_->message_type(2);
1517 DescriptorPool pool_;
1519 const FileDescriptor* foo_file_;
1521 const Descriptor* foo_;
1522 const Descriptor* bar_;
1523 const EnumDescriptor* baz_;
1524 const Descriptor* qux_;
1527 TEST_F(ExtensionDescriptorTest, ExtensionRanges) {
1528 EXPECT_EQ(0, bar_->extension_range_count());
1529 ASSERT_EQ(2, foo_->extension_range_count());
1531 EXPECT_EQ(10, foo_->extension_range(0)->start);
1532 EXPECT_EQ(30, foo_->extension_range(1)->start);
1534 EXPECT_EQ(20, foo_->extension_range(0)->end);
1535 EXPECT_EQ(40, foo_->extension_range(1)->end);
1538 TEST_F(ExtensionDescriptorTest, Extensions) {
1539 EXPECT_EQ(0, foo_->extension_count());
1540 ASSERT_EQ(2, foo_file_->extension_count());
1541 ASSERT_EQ(2, bar_->extension_count());
1543 EXPECT_TRUE(foo_file_->extension(0)->is_extension());
1544 EXPECT_TRUE(foo_file_->extension(1)->is_extension());
1545 EXPECT_TRUE(bar_->extension(0)->is_extension());
1546 EXPECT_TRUE(bar_->extension(1)->is_extension());
1548 EXPECT_EQ("foo_int32" , foo_file_->extension(0)->name());
1549 EXPECT_EQ("foo_enum" , foo_file_->extension(1)->name());
1550 EXPECT_EQ("foo_message", bar_->extension(0)->name());
1551 EXPECT_EQ("foo_group" , bar_->extension(1)->name());
1553 EXPECT_EQ(10, foo_file_->extension(0)->number());
1554 EXPECT_EQ(19, foo_file_->extension(1)->number());
1555 EXPECT_EQ(30, bar_->extension(0)->number());
1556 EXPECT_EQ(39, bar_->extension(1)->number());
1558 EXPECT_EQ(FieldDescriptor::TYPE_INT32 , foo_file_->extension(0)->type());
1559 EXPECT_EQ(FieldDescriptor::TYPE_ENUM , foo_file_->extension(1)->type());
1560 EXPECT_EQ(FieldDescriptor::TYPE_MESSAGE, bar_->extension(0)->type());
1561 EXPECT_EQ(FieldDescriptor::TYPE_GROUP , bar_->extension(1)->type());
1563 EXPECT_EQ(baz_, foo_file_->extension(1)->enum_type());
1564 EXPECT_EQ(qux_, bar_->extension(0)->message_type());
1565 EXPECT_EQ(qux_, bar_->extension(1)->message_type());
1567 EXPECT_EQ(FieldDescriptor::LABEL_OPTIONAL, foo_file_->extension(0)->label());
1568 EXPECT_EQ(FieldDescriptor::LABEL_REPEATED, foo_file_->extension(1)->label());
1569 EXPECT_EQ(FieldDescriptor::LABEL_OPTIONAL, bar_->extension(0)->label());
1570 EXPECT_EQ(FieldDescriptor::LABEL_REPEATED, bar_->extension(1)->label());
1572 EXPECT_EQ(foo_, foo_file_->extension(0)->containing_type());
1573 EXPECT_EQ(foo_, foo_file_->extension(1)->containing_type());
1574 EXPECT_EQ(foo_, bar_->extension(0)->containing_type());
1575 EXPECT_EQ(foo_, bar_->extension(1)->containing_type());
1577 EXPECT_TRUE(foo_file_->extension(0)->extension_scope() == NULL);
1578 EXPECT_TRUE(foo_file_->extension(1)->extension_scope() == NULL);
1579 EXPECT_EQ(bar_, bar_->extension(0)->extension_scope());
1580 EXPECT_EQ(bar_, bar_->extension(1)->extension_scope());
1583 TEST_F(ExtensionDescriptorTest, IsExtensionNumber) {
1584 EXPECT_FALSE(foo_->IsExtensionNumber( 9));
1585 EXPECT_TRUE (foo_->IsExtensionNumber(10));
1586 EXPECT_TRUE (foo_->IsExtensionNumber(19));
1587 EXPECT_FALSE(foo_->IsExtensionNumber(20));
1588 EXPECT_FALSE(foo_->IsExtensionNumber(29));
1589 EXPECT_TRUE (foo_->IsExtensionNumber(30));
1590 EXPECT_TRUE (foo_->IsExtensionNumber(39));
1591 EXPECT_FALSE(foo_->IsExtensionNumber(40));
1594 TEST_F(ExtensionDescriptorTest, FindExtensionByName) {
1595 // Note that FileDescriptor::FindExtensionByName() is tested by
1596 // FileDescriptorTest.
1597 ASSERT_EQ(2, bar_->extension_count());
1599 EXPECT_EQ(bar_->extension(0), bar_->FindExtensionByName("foo_message"));
1600 EXPECT_EQ(bar_->extension(1), bar_->FindExtensionByName("foo_group" ));
1602 EXPECT_TRUE(bar_->FindExtensionByName("no_such_extension") == NULL);
1603 EXPECT_TRUE(foo_->FindExtensionByName("foo_int32") == NULL);
1604 EXPECT_TRUE(foo_->FindExtensionByName("foo_message") == NULL);
1607 TEST_F(ExtensionDescriptorTest, FindAllExtensions) {
1608 vector<const FieldDescriptor*> extensions;
1609 pool_.FindAllExtensions(foo_, &extensions);
1610 ASSERT_EQ(4, extensions.size());
1611 EXPECT_EQ(10, extensions[0]->number());
1612 EXPECT_EQ(19, extensions[1]->number());
1613 EXPECT_EQ(30, extensions[2]->number());
1614 EXPECT_EQ(39, extensions[3]->number());
1617 TEST_F(ExtensionDescriptorTest, DuplicateFieldNumber) {
1618 DescriptorPool pool;
1619 FileDescriptorProto file_proto;
1620 // Add "google/protobuf/descriptor.proto".
1621 FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto);
1622 ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
1624 // import "google/protobuf/descriptor.proto";
1625 // extend google.protobuf.FieldOptions {
1626 // optional int32 option1 = 1000;
1629 file_proto.set_name("foo.proto");
1630 file_proto.add_dependency("google/protobuf/descriptor.proto");
1631 AddExtension(&file_proto, "google.protobuf.FieldOptions", "option1", 1000,
1632 FieldDescriptorProto::LABEL_OPTIONAL,
1633 FieldDescriptorProto::TYPE_INT32);
1634 ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
1636 // import "google/protobuf/descriptor.proto";
1637 // extend google.protobuf.FieldOptions {
1638 // optional int32 option2 = 1000;
1641 file_proto.set_name("bar.proto");
1642 file_proto.add_dependency("google/protobuf/descriptor.proto");
1643 AddExtension(&file_proto, "google.protobuf.FieldOptions", "option2", 1000,
1644 FieldDescriptorProto::LABEL_OPTIONAL,
1645 FieldDescriptorProto::TYPE_INT32);
1646 // Currently we only generate a warning for conflicting extension numbers.
1647 // TODO(xiaofeng): Change it to an error.
1648 ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
1651 // ===================================================================
1653 class MiscTest : public testing::Test {
1655 // Function which makes a field descriptor of the given type.
1656 const FieldDescriptor* GetFieldDescriptorOfType(FieldDescriptor::Type type) {
1657 FileDescriptorProto file_proto;
1658 file_proto.set_name("foo.proto");
1659 AddEmptyEnum(&file_proto, "DummyEnum");
1661 DescriptorProto* message = AddMessage(&file_proto, "TestMessage");
1662 FieldDescriptorProto* field =
1663 AddField(message, "foo", 1, FieldDescriptorProto::LABEL_OPTIONAL,
1664 static_cast<FieldDescriptorProto::Type>(static_cast<int>(type)));
1666 if (type == FieldDescriptor::TYPE_MESSAGE ||
1667 type == FieldDescriptor::TYPE_GROUP) {
1668 field->set_type_name("TestMessage");
1669 } else if (type == FieldDescriptor::TYPE_ENUM) {
1670 field->set_type_name("DummyEnum");
1673 // Build the descriptors and get the pointers.
1674 pool_.reset(new DescriptorPool());
1675 const FileDescriptor* file = pool_->BuildFile(file_proto);
1678 file->message_type_count() == 1 &&
1679 file->message_type(0)->field_count() == 1) {
1680 return file->message_type(0)->field(0);
1686 const char* GetTypeNameForFieldType(FieldDescriptor::Type type) {
1687 const FieldDescriptor* field = GetFieldDescriptorOfType(type);
1688 return field != NULL ? field->type_name() : "";
1691 FieldDescriptor::CppType GetCppTypeForFieldType(FieldDescriptor::Type type) {
1692 const FieldDescriptor* field = GetFieldDescriptorOfType(type);
1693 return field != NULL ? field->cpp_type() :
1694 static_cast<FieldDescriptor::CppType>(0);
1697 const char* GetCppTypeNameForFieldType(FieldDescriptor::Type type) {
1698 const FieldDescriptor* field = GetFieldDescriptorOfType(type);
1699 return field != NULL ? field->cpp_type_name() : "";
1702 const Descriptor* GetMessageDescriptorForFieldType(
1703 FieldDescriptor::Type type) {
1704 const FieldDescriptor* field = GetFieldDescriptorOfType(type);
1705 return field != NULL ? field->message_type() : NULL;
1708 const EnumDescriptor* GetEnumDescriptorForFieldType(
1709 FieldDescriptor::Type type) {
1710 const FieldDescriptor* field = GetFieldDescriptorOfType(type);
1711 return field != NULL ? field->enum_type() : NULL;
1714 scoped_ptr<DescriptorPool> pool_;
1717 TEST_F(MiscTest, TypeNames) {
1718 // Test that correct type names are returned.
1720 typedef FieldDescriptor FD; // avoid ugly line wrapping
1722 EXPECT_STREQ("double" , GetTypeNameForFieldType(FD::TYPE_DOUBLE ));
1723 EXPECT_STREQ("float" , GetTypeNameForFieldType(FD::TYPE_FLOAT ));
1724 EXPECT_STREQ("int64" , GetTypeNameForFieldType(FD::TYPE_INT64 ));
1725 EXPECT_STREQ("uint64" , GetTypeNameForFieldType(FD::TYPE_UINT64 ));
1726 EXPECT_STREQ("int32" , GetTypeNameForFieldType(FD::TYPE_INT32 ));
1727 EXPECT_STREQ("fixed64" , GetTypeNameForFieldType(FD::TYPE_FIXED64 ));
1728 EXPECT_STREQ("fixed32" , GetTypeNameForFieldType(FD::TYPE_FIXED32 ));
1729 EXPECT_STREQ("bool" , GetTypeNameForFieldType(FD::TYPE_BOOL ));
1730 EXPECT_STREQ("string" , GetTypeNameForFieldType(FD::TYPE_STRING ));
1731 EXPECT_STREQ("group" , GetTypeNameForFieldType(FD::TYPE_GROUP ));
1732 EXPECT_STREQ("message" , GetTypeNameForFieldType(FD::TYPE_MESSAGE ));
1733 EXPECT_STREQ("bytes" , GetTypeNameForFieldType(FD::TYPE_BYTES ));
1734 EXPECT_STREQ("uint32" , GetTypeNameForFieldType(FD::TYPE_UINT32 ));
1735 EXPECT_STREQ("enum" , GetTypeNameForFieldType(FD::TYPE_ENUM ));
1736 EXPECT_STREQ("sfixed32", GetTypeNameForFieldType(FD::TYPE_SFIXED32));
1737 EXPECT_STREQ("sfixed64", GetTypeNameForFieldType(FD::TYPE_SFIXED64));
1738 EXPECT_STREQ("sint32" , GetTypeNameForFieldType(FD::TYPE_SINT32 ));
1739 EXPECT_STREQ("sint64" , GetTypeNameForFieldType(FD::TYPE_SINT64 ));
1742 TEST_F(MiscTest, StaticTypeNames) {
1743 // Test that correct type names are returned.
1745 typedef FieldDescriptor FD; // avoid ugly line wrapping
1747 EXPECT_STREQ("double" , FD::TypeName(FD::TYPE_DOUBLE ));
1748 EXPECT_STREQ("float" , FD::TypeName(FD::TYPE_FLOAT ));
1749 EXPECT_STREQ("int64" , FD::TypeName(FD::TYPE_INT64 ));
1750 EXPECT_STREQ("uint64" , FD::TypeName(FD::TYPE_UINT64 ));
1751 EXPECT_STREQ("int32" , FD::TypeName(FD::TYPE_INT32 ));
1752 EXPECT_STREQ("fixed64" , FD::TypeName(FD::TYPE_FIXED64 ));
1753 EXPECT_STREQ("fixed32" , FD::TypeName(FD::TYPE_FIXED32 ));
1754 EXPECT_STREQ("bool" , FD::TypeName(FD::TYPE_BOOL ));
1755 EXPECT_STREQ("string" , FD::TypeName(FD::TYPE_STRING ));
1756 EXPECT_STREQ("group" , FD::TypeName(FD::TYPE_GROUP ));
1757 EXPECT_STREQ("message" , FD::TypeName(FD::TYPE_MESSAGE ));
1758 EXPECT_STREQ("bytes" , FD::TypeName(FD::TYPE_BYTES ));
1759 EXPECT_STREQ("uint32" , FD::TypeName(FD::TYPE_UINT32 ));
1760 EXPECT_STREQ("enum" , FD::TypeName(FD::TYPE_ENUM ));
1761 EXPECT_STREQ("sfixed32", FD::TypeName(FD::TYPE_SFIXED32));
1762 EXPECT_STREQ("sfixed64", FD::TypeName(FD::TYPE_SFIXED64));
1763 EXPECT_STREQ("sint32" , FD::TypeName(FD::TYPE_SINT32 ));
1764 EXPECT_STREQ("sint64" , FD::TypeName(FD::TYPE_SINT64 ));
1767 TEST_F(MiscTest, CppTypes) {
1768 // Test that CPP types are assigned correctly.
1770 typedef FieldDescriptor FD; // avoid ugly line wrapping
1772 EXPECT_EQ(FD::CPPTYPE_DOUBLE , GetCppTypeForFieldType(FD::TYPE_DOUBLE ));
1773 EXPECT_EQ(FD::CPPTYPE_FLOAT , GetCppTypeForFieldType(FD::TYPE_FLOAT ));
1774 EXPECT_EQ(FD::CPPTYPE_INT64 , GetCppTypeForFieldType(FD::TYPE_INT64 ));
1775 EXPECT_EQ(FD::CPPTYPE_UINT64 , GetCppTypeForFieldType(FD::TYPE_UINT64 ));
1776 EXPECT_EQ(FD::CPPTYPE_INT32 , GetCppTypeForFieldType(FD::TYPE_INT32 ));
1777 EXPECT_EQ(FD::CPPTYPE_UINT64 , GetCppTypeForFieldType(FD::TYPE_FIXED64 ));
1778 EXPECT_EQ(FD::CPPTYPE_UINT32 , GetCppTypeForFieldType(FD::TYPE_FIXED32 ));
1779 EXPECT_EQ(FD::CPPTYPE_BOOL , GetCppTypeForFieldType(FD::TYPE_BOOL ));
1780 EXPECT_EQ(FD::CPPTYPE_STRING , GetCppTypeForFieldType(FD::TYPE_STRING ));
1781 EXPECT_EQ(FD::CPPTYPE_MESSAGE, GetCppTypeForFieldType(FD::TYPE_GROUP ));
1782 EXPECT_EQ(FD::CPPTYPE_MESSAGE, GetCppTypeForFieldType(FD::TYPE_MESSAGE ));
1783 EXPECT_EQ(FD::CPPTYPE_STRING , GetCppTypeForFieldType(FD::TYPE_BYTES ));
1784 EXPECT_EQ(FD::CPPTYPE_UINT32 , GetCppTypeForFieldType(FD::TYPE_UINT32 ));
1785 EXPECT_EQ(FD::CPPTYPE_ENUM , GetCppTypeForFieldType(FD::TYPE_ENUM ));
1786 EXPECT_EQ(FD::CPPTYPE_INT32 , GetCppTypeForFieldType(FD::TYPE_SFIXED32));
1787 EXPECT_EQ(FD::CPPTYPE_INT64 , GetCppTypeForFieldType(FD::TYPE_SFIXED64));
1788 EXPECT_EQ(FD::CPPTYPE_INT32 , GetCppTypeForFieldType(FD::TYPE_SINT32 ));
1789 EXPECT_EQ(FD::CPPTYPE_INT64 , GetCppTypeForFieldType(FD::TYPE_SINT64 ));
1792 TEST_F(MiscTest, CppTypeNames) {
1793 // Test that correct CPP type names are returned.
1795 typedef FieldDescriptor FD; // avoid ugly line wrapping
1797 EXPECT_STREQ("double" , GetCppTypeNameForFieldType(FD::TYPE_DOUBLE ));
1798 EXPECT_STREQ("float" , GetCppTypeNameForFieldType(FD::TYPE_FLOAT ));
1799 EXPECT_STREQ("int64" , GetCppTypeNameForFieldType(FD::TYPE_INT64 ));
1800 EXPECT_STREQ("uint64" , GetCppTypeNameForFieldType(FD::TYPE_UINT64 ));
1801 EXPECT_STREQ("int32" , GetCppTypeNameForFieldType(FD::TYPE_INT32 ));
1802 EXPECT_STREQ("uint64" , GetCppTypeNameForFieldType(FD::TYPE_FIXED64 ));
1803 EXPECT_STREQ("uint32" , GetCppTypeNameForFieldType(FD::TYPE_FIXED32 ));
1804 EXPECT_STREQ("bool" , GetCppTypeNameForFieldType(FD::TYPE_BOOL ));
1805 EXPECT_STREQ("string" , GetCppTypeNameForFieldType(FD::TYPE_STRING ));
1806 EXPECT_STREQ("message", GetCppTypeNameForFieldType(FD::TYPE_GROUP ));
1807 EXPECT_STREQ("message", GetCppTypeNameForFieldType(FD::TYPE_MESSAGE ));
1808 EXPECT_STREQ("string" , GetCppTypeNameForFieldType(FD::TYPE_BYTES ));
1809 EXPECT_STREQ("uint32" , GetCppTypeNameForFieldType(FD::TYPE_UINT32 ));
1810 EXPECT_STREQ("enum" , GetCppTypeNameForFieldType(FD::TYPE_ENUM ));
1811 EXPECT_STREQ("int32" , GetCppTypeNameForFieldType(FD::TYPE_SFIXED32));
1812 EXPECT_STREQ("int64" , GetCppTypeNameForFieldType(FD::TYPE_SFIXED64));
1813 EXPECT_STREQ("int32" , GetCppTypeNameForFieldType(FD::TYPE_SINT32 ));
1814 EXPECT_STREQ("int64" , GetCppTypeNameForFieldType(FD::TYPE_SINT64 ));
1817 TEST_F(MiscTest, StaticCppTypeNames) {
1818 // Test that correct CPP type names are returned.
1820 typedef FieldDescriptor FD; // avoid ugly line wrapping
1822 EXPECT_STREQ("int32" , FD::CppTypeName(FD::CPPTYPE_INT32 ));
1823 EXPECT_STREQ("int64" , FD::CppTypeName(FD::CPPTYPE_INT64 ));
1824 EXPECT_STREQ("uint32" , FD::CppTypeName(FD::CPPTYPE_UINT32 ));
1825 EXPECT_STREQ("uint64" , FD::CppTypeName(FD::CPPTYPE_UINT64 ));
1826 EXPECT_STREQ("double" , FD::CppTypeName(FD::CPPTYPE_DOUBLE ));
1827 EXPECT_STREQ("float" , FD::CppTypeName(FD::CPPTYPE_FLOAT ));
1828 EXPECT_STREQ("bool" , FD::CppTypeName(FD::CPPTYPE_BOOL ));
1829 EXPECT_STREQ("enum" , FD::CppTypeName(FD::CPPTYPE_ENUM ));
1830 EXPECT_STREQ("string" , FD::CppTypeName(FD::CPPTYPE_STRING ));
1831 EXPECT_STREQ("message", FD::CppTypeName(FD::CPPTYPE_MESSAGE));
1834 TEST_F(MiscTest, MessageType) {
1835 // Test that message_type() is NULL for non-aggregate fields
1837 typedef FieldDescriptor FD; // avoid ugly line wrapping
1839 EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_DOUBLE ));
1840 EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_FLOAT ));
1841 EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_INT64 ));
1842 EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_UINT64 ));
1843 EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_INT32 ));
1844 EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_FIXED64 ));
1845 EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_FIXED32 ));
1846 EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_BOOL ));
1847 EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_STRING ));
1848 EXPECT_TRUE(NULL != GetMessageDescriptorForFieldType(FD::TYPE_GROUP ));
1849 EXPECT_TRUE(NULL != GetMessageDescriptorForFieldType(FD::TYPE_MESSAGE ));
1850 EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_BYTES ));
1851 EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_UINT32 ));
1852 EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_ENUM ));
1853 EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_SFIXED32));
1854 EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_SFIXED64));
1855 EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_SINT32 ));
1856 EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_SINT64 ));
1859 TEST_F(MiscTest, EnumType) {
1860 // Test that enum_type() is NULL for non-enum fields
1862 typedef FieldDescriptor FD; // avoid ugly line wrapping
1864 EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_DOUBLE ));
1865 EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_FLOAT ));
1866 EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_INT64 ));
1867 EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_UINT64 ));
1868 EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_INT32 ));
1869 EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_FIXED64 ));
1870 EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_FIXED32 ));
1871 EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_BOOL ));
1872 EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_STRING ));
1873 EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_GROUP ));
1874 EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_MESSAGE ));
1875 EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_BYTES ));
1876 EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_UINT32 ));
1877 EXPECT_TRUE(NULL != GetEnumDescriptorForFieldType(FD::TYPE_ENUM ));
1878 EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_SFIXED32));
1879 EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_SFIXED64));
1880 EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_SINT32 ));
1881 EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_SINT64 ));
1885 TEST_F(MiscTest, DefaultValues) {
1886 // Test that setting default values works.
1887 FileDescriptorProto file_proto;
1888 file_proto.set_name("foo.proto");
1890 EnumDescriptorProto* enum_type_proto = AddEnum(&file_proto, "DummyEnum");
1891 AddEnumValue(enum_type_proto, "A", 1);
1892 AddEnumValue(enum_type_proto, "B", 2);
1894 DescriptorProto* message_proto = AddMessage(&file_proto, "TestMessage");
1896 typedef FieldDescriptorProto FD; // avoid ugly line wrapping
1897 const FD::Label label = FD::LABEL_OPTIONAL;
1899 // Create fields of every CPP type with default values.
1900 AddField(message_proto, "int32" , 1, label, FD::TYPE_INT32 )
1901 ->set_default_value("-1");
1902 AddField(message_proto, "int64" , 2, label, FD::TYPE_INT64 )
1903 ->set_default_value("-1000000000000");
1904 AddField(message_proto, "uint32", 3, label, FD::TYPE_UINT32)
1905 ->set_default_value("42");
1906 AddField(message_proto, "uint64", 4, label, FD::TYPE_UINT64)
1907 ->set_default_value("2000000000000");
1908 AddField(message_proto, "float" , 5, label, FD::TYPE_FLOAT )
1909 ->set_default_value("4.5");
1910 AddField(message_proto, "double", 6, label, FD::TYPE_DOUBLE)
1911 ->set_default_value("10e100");
1912 AddField(message_proto, "bool" , 7, label, FD::TYPE_BOOL )
1913 ->set_default_value("true");
1914 AddField(message_proto, "string", 8, label, FD::TYPE_STRING)
1915 ->set_default_value("hello");
1916 AddField(message_proto, "data" , 9, label, FD::TYPE_BYTES )
1917 ->set_default_value("\\001\\002\\003");
1919 FieldDescriptorProto* enum_field =
1920 AddField(message_proto, "enum", 10, label, FD::TYPE_ENUM);
1921 enum_field->set_type_name("DummyEnum");
1922 enum_field->set_default_value("B");
1924 // Strings are allowed to have empty defaults. (At one point, due to
1925 // a bug, empty defaults for strings were rejected. Oops.)
1926 AddField(message_proto, "empty_string", 11, label, FD::TYPE_STRING)
1927 ->set_default_value("");
1929 // Add a second set of fields with implicit defalut values.
1930 AddField(message_proto, "implicit_int32" , 21, label, FD::TYPE_INT32 );
1931 AddField(message_proto, "implicit_int64" , 22, label, FD::TYPE_INT64 );
1932 AddField(message_proto, "implicit_uint32", 23, label, FD::TYPE_UINT32);
1933 AddField(message_proto, "implicit_uint64", 24, label, FD::TYPE_UINT64);
1934 AddField(message_proto, "implicit_float" , 25, label, FD::TYPE_FLOAT );
1935 AddField(message_proto, "implicit_double", 26, label, FD::TYPE_DOUBLE);
1936 AddField(message_proto, "implicit_bool" , 27, label, FD::TYPE_BOOL );
1937 AddField(message_proto, "implicit_string", 28, label, FD::TYPE_STRING);
1938 AddField(message_proto, "implicit_data" , 29, label, FD::TYPE_BYTES );
1939 AddField(message_proto, "implicit_enum" , 30, label, FD::TYPE_ENUM)
1940 ->set_type_name("DummyEnum");
1943 DescriptorPool pool;
1944 const FileDescriptor* file = pool.BuildFile(file_proto);
1945 ASSERT_TRUE(file != NULL);
1947 ASSERT_EQ(1, file->enum_type_count());
1948 const EnumDescriptor* enum_type = file->enum_type(0);
1949 ASSERT_EQ(2, enum_type->value_count());
1950 const EnumValueDescriptor* enum_value_a = enum_type->value(0);
1951 const EnumValueDescriptor* enum_value_b = enum_type->value(1);
1953 ASSERT_EQ(1, file->message_type_count());
1954 const Descriptor* message = file->message_type(0);
1956 ASSERT_EQ(21, message->field_count());
1958 // Check the default values.
1959 ASSERT_TRUE(message->field(0)->has_default_value());
1960 ASSERT_TRUE(message->field(1)->has_default_value());
1961 ASSERT_TRUE(message->field(2)->has_default_value());
1962 ASSERT_TRUE(message->field(3)->has_default_value());
1963 ASSERT_TRUE(message->field(4)->has_default_value());
1964 ASSERT_TRUE(message->field(5)->has_default_value());
1965 ASSERT_TRUE(message->field(6)->has_default_value());
1966 ASSERT_TRUE(message->field(7)->has_default_value());
1967 ASSERT_TRUE(message->field(8)->has_default_value());
1968 ASSERT_TRUE(message->field(9)->has_default_value());
1969 ASSERT_TRUE(message->field(10)->has_default_value());
1971 EXPECT_EQ(-1 , message->field(0)->default_value_int32 ());
1972 EXPECT_EQ(-GOOGLE_ULONGLONG(1000000000000),
1973 message->field(1)->default_value_int64 ());
1974 EXPECT_EQ(42 , message->field(2)->default_value_uint32());
1975 EXPECT_EQ(GOOGLE_ULONGLONG(2000000000000),
1976 message->field(3)->default_value_uint64());
1977 EXPECT_EQ(4.5 , message->field(4)->default_value_float ());
1978 EXPECT_EQ(10e100 , message->field(5)->default_value_double());
1979 EXPECT_TRUE( message->field(6)->default_value_bool ());
1980 EXPECT_EQ("hello" , message->field(7)->default_value_string());
1981 EXPECT_EQ("\001\002\003" , message->field(8)->default_value_string());
1982 EXPECT_EQ(enum_value_b , message->field(9)->default_value_enum ());
1983 EXPECT_EQ("" , message->field(10)->default_value_string());
1985 ASSERT_FALSE(message->field(11)->has_default_value());
1986 ASSERT_FALSE(message->field(12)->has_default_value());
1987 ASSERT_FALSE(message->field(13)->has_default_value());
1988 ASSERT_FALSE(message->field(14)->has_default_value());
1989 ASSERT_FALSE(message->field(15)->has_default_value());
1990 ASSERT_FALSE(message->field(16)->has_default_value());
1991 ASSERT_FALSE(message->field(17)->has_default_value());
1992 ASSERT_FALSE(message->field(18)->has_default_value());
1993 ASSERT_FALSE(message->field(19)->has_default_value());
1994 ASSERT_FALSE(message->field(20)->has_default_value());
1996 EXPECT_EQ(0 , message->field(11)->default_value_int32 ());
1997 EXPECT_EQ(0 , message->field(12)->default_value_int64 ());
1998 EXPECT_EQ(0 , message->field(13)->default_value_uint32());
1999 EXPECT_EQ(0 , message->field(14)->default_value_uint64());
2000 EXPECT_EQ(0.0f , message->field(15)->default_value_float ());
2001 EXPECT_EQ(0.0 , message->field(16)->default_value_double());
2002 EXPECT_FALSE( message->field(17)->default_value_bool ());
2003 EXPECT_EQ("" , message->field(18)->default_value_string());
2004 EXPECT_EQ("" , message->field(19)->default_value_string());
2005 EXPECT_EQ(enum_value_a, message->field(20)->default_value_enum());
2008 TEST_F(MiscTest, FieldOptions) {
2009 // Try setting field options.
2011 FileDescriptorProto file_proto;
2012 file_proto.set_name("foo.proto");
2014 DescriptorProto* message_proto = AddMessage(&file_proto, "TestMessage");
2015 AddField(message_proto, "foo", 1,
2016 FieldDescriptorProto::LABEL_OPTIONAL,
2017 FieldDescriptorProto::TYPE_INT32);
2018 FieldDescriptorProto* bar_proto =
2019 AddField(message_proto, "bar", 2,
2020 FieldDescriptorProto::LABEL_OPTIONAL,
2021 FieldDescriptorProto::TYPE_INT32);
2023 FieldOptions* options = bar_proto->mutable_options();
2024 options->set_ctype(FieldOptions::CORD);
2026 // Build the descriptors and get the pointers.
2027 DescriptorPool pool;
2028 const FileDescriptor* file = pool.BuildFile(file_proto);
2029 ASSERT_TRUE(file != NULL);
2031 ASSERT_EQ(1, file->message_type_count());
2032 const Descriptor* message = file->message_type(0);
2034 ASSERT_EQ(2, message->field_count());
2035 const FieldDescriptor* foo = message->field(0);
2036 const FieldDescriptor* bar = message->field(1);
2038 // "foo" had no options set, so it should return the default options.
2039 EXPECT_EQ(&FieldOptions::default_instance(), &foo->options());
2041 // "bar" had options set.
2042 EXPECT_NE(&FieldOptions::default_instance(), options);
2043 EXPECT_TRUE(bar->options().has_ctype());
2044 EXPECT_EQ(FieldOptions::CORD, bar->options().ctype());
2047 // ===================================================================
2048 enum DescriptorPoolMode {
2053 class AllowUnknownDependenciesTest
2054 : public testing::TestWithParam<DescriptorPoolMode> {
2056 DescriptorPoolMode mode() {
2060 virtual void SetUp() {
2061 FileDescriptorProto foo_proto, bar_proto;
2065 pool_.reset(new DescriptorPool);
2067 case FALLBACK_DATABASE:
2068 pool_.reset(new DescriptorPool(&db_));
2072 pool_->AllowUnknownDependencies();
2074 ASSERT_TRUE(TextFormat::ParseFromString(
2076 "dependency: 'bar.proto'"
2077 "dependency: 'baz.proto'"
2080 " field { name:'bar' number:1 label:LABEL_OPTIONAL type_name:'Bar' }"
2081 " field { name:'baz' number:2 label:LABEL_OPTIONAL type_name:'Baz' }"
2082 " field { name:'qux' number:3 label:LABEL_OPTIONAL"
2083 " type_name: '.corge.Qux'"
2086 " uninterpreted_option {"
2088 " name_part: 'grault'"
2089 " is_extension: true"
2091 " positive_int_value: 1234"
2097 ASSERT_TRUE(TextFormat::ParseFromString(
2099 "message_type { name: 'Bar' }",
2102 // Collect pointers to stuff.
2103 bar_file_ = BuildFile(bar_proto);
2104 ASSERT_TRUE(bar_file_ != NULL);
2106 ASSERT_EQ(1, bar_file_->message_type_count());
2107 bar_type_ = bar_file_->message_type(0);
2109 foo_file_ = BuildFile(foo_proto);
2110 ASSERT_TRUE(foo_file_ != NULL);
2112 ASSERT_EQ(1, foo_file_->message_type_count());
2113 foo_type_ = foo_file_->message_type(0);
2115 ASSERT_EQ(3, foo_type_->field_count());
2116 bar_field_ = foo_type_->field(0);
2117 baz_field_ = foo_type_->field(1);
2118 qux_field_ = foo_type_->field(2);
2121 const FileDescriptor* BuildFile(const FileDescriptorProto& proto) {
2124 return pool_->BuildFile(proto);
2126 case FALLBACK_DATABASE: {
2127 EXPECT_TRUE(db_.Add(proto));
2128 return pool_->FindFileByName(proto.name());
2131 GOOGLE_LOG(FATAL) << "Can't get here.";
2135 const FileDescriptor* bar_file_;
2136 const Descriptor* bar_type_;
2137 const FileDescriptor* foo_file_;
2138 const Descriptor* foo_type_;
2139 const FieldDescriptor* bar_field_;
2140 const FieldDescriptor* baz_field_;
2141 const FieldDescriptor* qux_field_;
2143 SimpleDescriptorDatabase db_; // used if in FALLBACK_DATABASE mode.
2144 scoped_ptr<DescriptorPool> pool_;
2147 TEST_P(AllowUnknownDependenciesTest, PlaceholderFile) {
2148 ASSERT_EQ(2, foo_file_->dependency_count());
2149 EXPECT_EQ(bar_file_, foo_file_->dependency(0));
2150 EXPECT_FALSE(bar_file_->is_placeholder());
2152 const FileDescriptor* baz_file = foo_file_->dependency(1);
2153 EXPECT_EQ("baz.proto", baz_file->name());
2154 EXPECT_EQ(0, baz_file->message_type_count());
2155 EXPECT_TRUE(baz_file->is_placeholder());
2157 // Placeholder files should not be findable.
2158 EXPECT_EQ(bar_file_, pool_->FindFileByName(bar_file_->name()));
2159 EXPECT_TRUE(pool_->FindFileByName(baz_file->name()) == NULL);
2162 TEST_P(AllowUnknownDependenciesTest, PlaceholderTypes) {
2163 ASSERT_EQ(FieldDescriptor::TYPE_MESSAGE, bar_field_->type());
2164 EXPECT_EQ(bar_type_, bar_field_->message_type());
2165 EXPECT_FALSE(bar_type_->is_placeholder());
2167 ASSERT_EQ(FieldDescriptor::TYPE_MESSAGE, baz_field_->type());
2168 const Descriptor* baz_type = baz_field_->message_type();
2169 EXPECT_EQ("Baz", baz_type->name());
2170 EXPECT_EQ("Baz", baz_type->full_name());
2171 EXPECT_EQ(0, baz_type->extension_range_count());
2172 EXPECT_TRUE(baz_type->is_placeholder());
2174 ASSERT_EQ(FieldDescriptor::TYPE_ENUM, qux_field_->type());
2175 const EnumDescriptor* qux_type = qux_field_->enum_type();
2176 EXPECT_EQ("Qux", qux_type->name());
2177 EXPECT_EQ("corge.Qux", qux_type->full_name());
2178 EXPECT_TRUE(qux_type->is_placeholder());
2180 // Placeholder types should not be findable.
2181 EXPECT_EQ(bar_type_, pool_->FindMessageTypeByName(bar_type_->full_name()));
2182 EXPECT_TRUE(pool_->FindMessageTypeByName(baz_type->full_name()) == NULL);
2183 EXPECT_TRUE(pool_->FindEnumTypeByName(qux_type->full_name()) == NULL);
2186 TEST_P(AllowUnknownDependenciesTest, CopyTo) {
2187 // FieldDescriptor::CopyTo() should write non-fully-qualified type names
2188 // for placeholder types which were not originally fully-qualified.
2189 FieldDescriptorProto proto;
2191 // Bar is not a placeholder, so it is fully-qualified.
2192 bar_field_->CopyTo(&proto);
2193 EXPECT_EQ(".Bar", proto.type_name());
2194 EXPECT_EQ(FieldDescriptorProto::TYPE_MESSAGE, proto.type());
2196 // Baz is an unqualified placeholder.
2198 baz_field_->CopyTo(&proto);
2199 EXPECT_EQ("Baz", proto.type_name());
2200 EXPECT_FALSE(proto.has_type());
2202 // Qux is a fully-qualified placeholder.
2204 qux_field_->CopyTo(&proto);
2205 EXPECT_EQ(".corge.Qux", proto.type_name());
2206 EXPECT_EQ(FieldDescriptorProto::TYPE_ENUM, proto.type());
2209 TEST_P(AllowUnknownDependenciesTest, CustomOptions) {
2210 // Qux should still have the uninterpreted option attached.
2211 ASSERT_EQ(1, qux_field_->options().uninterpreted_option_size());
2212 const UninterpretedOption& option =
2213 qux_field_->options().uninterpreted_option(0);
2214 ASSERT_EQ(1, option.name_size());
2215 EXPECT_EQ("grault", option.name(0).name_part());
2218 TEST_P(AllowUnknownDependenciesTest, UnknownExtendee) {
2219 // Test that we can extend an unknown type. This is slightly tricky because
2220 // it means that the placeholder type must have an extension range.
2222 FileDescriptorProto extension_proto;
2224 ASSERT_TRUE(TextFormat::ParseFromString(
2225 "name: 'extension.proto'"
2226 "extension { extendee: 'UnknownType' name:'some_extension' number:123"
2227 " label:LABEL_OPTIONAL type:TYPE_INT32 }",
2229 const FileDescriptor* file = BuildFile(extension_proto);
2231 ASSERT_TRUE(file != NULL);
2233 ASSERT_EQ(1, file->extension_count());
2234 const Descriptor* extendee = file->extension(0)->containing_type();
2235 EXPECT_EQ("UnknownType", extendee->name());
2236 EXPECT_TRUE(extendee->is_placeholder());
2237 ASSERT_EQ(1, extendee->extension_range_count());
2238 EXPECT_EQ(1, extendee->extension_range(0)->start);
2239 EXPECT_EQ(FieldDescriptor::kMaxNumber + 1, extendee->extension_range(0)->end);
2242 TEST_P(AllowUnknownDependenciesTest, CustomOption) {
2243 // Test that we can use a custom option without having parsed
2244 // descriptor.proto.
2246 FileDescriptorProto option_proto;
2248 ASSERT_TRUE(TextFormat::ParseFromString(
2249 "name: \"unknown_custom_options.proto\" "
2250 "dependency: \"google/protobuf/descriptor.proto\" "
2252 " extendee: \"google.protobuf.FileOptions\" "
2253 " name: \"some_option\" "
2255 " label: LABEL_OPTIONAL "
2256 " type: TYPE_INT32 "
2259 " uninterpreted_option { "
2261 " name_part: \"some_option\" "
2262 " is_extension: true "
2264 " positive_int_value: 1234 "
2266 " uninterpreted_option { "
2268 " name_part: \"unknown_option\" "
2269 " is_extension: true "
2271 " positive_int_value: 1234 "
2273 " uninterpreted_option { "
2275 " name_part: \"optimize_for\" "
2276 " is_extension: false "
2278 " identifier_value: \"SPEED\" "
2283 const FileDescriptor* file = BuildFile(option_proto);
2284 ASSERT_TRUE(file != NULL);
2286 // Verify that no extension options were set, but they were left as
2287 // uninterpreted_options.
2288 vector<const FieldDescriptor*> fields;
2289 file->options().GetReflection()->ListFields(file->options(), &fields);
2290 ASSERT_EQ(2, fields.size());
2291 EXPECT_TRUE(file->options().has_optimize_for());
2292 EXPECT_EQ(2, file->options().uninterpreted_option_size());
2295 TEST_P(AllowUnknownDependenciesTest,
2296 UndeclaredDependencyTriggersBuildOfDependency) {
2297 // Crazy case: suppose foo.proto refers to a symbol without declaring the
2298 // dependency that finds it. In the event that the pool is backed by a
2299 // DescriptorDatabase, the pool will attempt to find the symbol in the
2300 // database. If successful, it will build the undeclared dependency to verify
2301 // that the file does indeed contain the symbol. If that file fails to build,
2302 // then its descriptors must be rolled back. However, we still want foo.proto
2303 // to build successfully, since we are allowing unknown dependencies.
2305 FileDescriptorProto undeclared_dep_proto;
2306 // We make this file fail to build by giving it two fields with tag 1.
2307 ASSERT_TRUE(TextFormat::ParseFromString(
2308 "name: \"invalid_file_as_undeclared_dep.proto\" "
2309 "package: \"undeclared\" "
2313 " name:'qux' number:1 label:LABEL_OPTIONAL type: TYPE_INT32 "
2316 " name:'quux' number:1 label:LABEL_OPTIONAL type: TYPE_INT64 "
2319 &undeclared_dep_proto));
2320 // We can't use the BuildFile() helper because we don't actually want to build
2321 // it into the descriptor pool in the fallback database case: it just needs to
2322 // be sitting in the database so that it gets built during the building of
2323 // test.proto below.
2326 ASSERT_TRUE(pool_->BuildFile(undeclared_dep_proto) == NULL);
2329 case FALLBACK_DATABASE: {
2330 ASSERT_TRUE(db_.Add(undeclared_dep_proto));
2334 FileDescriptorProto test_proto;
2335 ASSERT_TRUE(TextFormat::ParseFromString(
2336 "name: \"test.proto\" "
2340 " name:'quux' number:1 label: LABEL_OPTIONAL "
2341 " type_name:'undeclared.Quux' type: TYPE_MESSAGE "
2346 const FileDescriptor* file = BuildFile(test_proto);
2347 ASSERT_TRUE(file != NULL);
2348 GOOGLE_LOG(INFO) << file->DebugString();
2350 EXPECT_EQ(0, file->dependency_count());
2351 ASSERT_EQ(1, file->message_type_count());
2352 const Descriptor* corge_desc = file->message_type(0);
2353 ASSERT_EQ("Corge", corge_desc->name());
2354 ASSERT_EQ(1, corge_desc->field_count());
2355 EXPECT_FALSE(corge_desc->is_placeholder());
2357 const FieldDescriptor* quux_field = corge_desc->field(0);
2358 ASSERT_EQ(FieldDescriptor::TYPE_MESSAGE, quux_field->type());
2359 ASSERT_EQ("Quux", quux_field->message_type()->name());
2360 ASSERT_EQ("undeclared.Quux", quux_field->message_type()->full_name());
2361 EXPECT_TRUE(quux_field->message_type()->is_placeholder());
2362 // The place holder type should not be findable.
2363 ASSERT_TRUE(pool_->FindMessageTypeByName("undeclared.Quux") == NULL);
2366 INSTANTIATE_TEST_CASE_P(DatabaseSource,
2367 AllowUnknownDependenciesTest,
2368 testing::Values(NO_DATABASE, FALLBACK_DATABASE));
2370 // ===================================================================
2372 TEST(CustomOptions, OptionLocations) {
2373 const Descriptor* message =
2374 protobuf_unittest::TestMessageWithCustomOptions::descriptor();
2375 const FileDescriptor* file = message->file();
2376 const FieldDescriptor* field = message->FindFieldByName("field1");
2377 const EnumDescriptor* enm = message->FindEnumTypeByName("AnEnum");
2378 // TODO(benjy): Support EnumValue options, once the compiler does.
2379 const ServiceDescriptor* service =
2380 file->FindServiceByName("TestServiceWithCustomOptions");
2381 const MethodDescriptor* method = service->FindMethodByName("Foo");
2383 EXPECT_EQ(GOOGLE_LONGLONG(9876543210),
2384 file->options().GetExtension(protobuf_unittest::file_opt1));
2386 message->options().GetExtension(protobuf_unittest::message_opt1));
2387 EXPECT_EQ(GOOGLE_LONGLONG(8765432109),
2388 field->options().GetExtension(protobuf_unittest::field_opt1));
2389 EXPECT_EQ(42, // Check that we get the default for an option we don't set.
2390 field->options().GetExtension(protobuf_unittest::field_opt2));
2392 enm->options().GetExtension(protobuf_unittest::enum_opt1));
2394 enm->value(1)->options().GetExtension(
2395 protobuf_unittest::enum_value_opt1));
2396 EXPECT_EQ(GOOGLE_LONGLONG(-9876543210),
2397 service->options().GetExtension(protobuf_unittest::service_opt1));
2398 EXPECT_EQ(protobuf_unittest::METHODOPT1_VAL2,
2399 method->options().GetExtension(protobuf_unittest::method_opt1));
2401 // See that the regular options went through unscathed.
2402 EXPECT_TRUE(message->options().has_message_set_wire_format());
2403 EXPECT_EQ(FieldOptions::CORD, field->options().ctype());
2406 TEST(CustomOptions, OptionTypes) {
2407 const MessageOptions* options = NULL;
2410 &protobuf_unittest::CustomOptionMinIntegerValues::descriptor()->options();
2411 EXPECT_EQ(false , options->GetExtension(protobuf_unittest::bool_opt));
2412 EXPECT_EQ(kint32min, options->GetExtension(protobuf_unittest::int32_opt));
2413 EXPECT_EQ(kint64min, options->GetExtension(protobuf_unittest::int64_opt));
2414 EXPECT_EQ(0 , options->GetExtension(protobuf_unittest::uint32_opt));
2415 EXPECT_EQ(0 , options->GetExtension(protobuf_unittest::uint64_opt));
2416 EXPECT_EQ(kint32min, options->GetExtension(protobuf_unittest::sint32_opt));
2417 EXPECT_EQ(kint64min, options->GetExtension(protobuf_unittest::sint64_opt));
2418 EXPECT_EQ(0 , options->GetExtension(protobuf_unittest::fixed32_opt));
2419 EXPECT_EQ(0 , options->GetExtension(protobuf_unittest::fixed64_opt));
2420 EXPECT_EQ(kint32min, options->GetExtension(protobuf_unittest::sfixed32_opt));
2421 EXPECT_EQ(kint64min, options->GetExtension(protobuf_unittest::sfixed64_opt));
2424 &protobuf_unittest::CustomOptionMaxIntegerValues::descriptor()->options();
2425 EXPECT_EQ(true , options->GetExtension(protobuf_unittest::bool_opt));
2426 EXPECT_EQ(kint32max , options->GetExtension(protobuf_unittest::int32_opt));
2427 EXPECT_EQ(kint64max , options->GetExtension(protobuf_unittest::int64_opt));
2428 EXPECT_EQ(kuint32max, options->GetExtension(protobuf_unittest::uint32_opt));
2429 EXPECT_EQ(kuint64max, options->GetExtension(protobuf_unittest::uint64_opt));
2430 EXPECT_EQ(kint32max , options->GetExtension(protobuf_unittest::sint32_opt));
2431 EXPECT_EQ(kint64max , options->GetExtension(protobuf_unittest::sint64_opt));
2432 EXPECT_EQ(kuint32max, options->GetExtension(protobuf_unittest::fixed32_opt));
2433 EXPECT_EQ(kuint64max, options->GetExtension(protobuf_unittest::fixed64_opt));
2434 EXPECT_EQ(kint32max , options->GetExtension(protobuf_unittest::sfixed32_opt));
2435 EXPECT_EQ(kint64max , options->GetExtension(protobuf_unittest::sfixed64_opt));
2438 &protobuf_unittest::CustomOptionOtherValues::descriptor()->options();
2439 EXPECT_EQ(-100, options->GetExtension(protobuf_unittest::int32_opt));
2440 EXPECT_FLOAT_EQ(12.3456789,
2441 options->GetExtension(protobuf_unittest::float_opt));
2442 EXPECT_DOUBLE_EQ(1.234567890123456789,
2443 options->GetExtension(protobuf_unittest::double_opt));
2444 EXPECT_EQ("Hello, \"World\"",
2445 options->GetExtension(protobuf_unittest::string_opt));
2447 EXPECT_EQ(string("Hello\0World", 11),
2448 options->GetExtension(protobuf_unittest::bytes_opt));
2450 EXPECT_EQ(protobuf_unittest::DummyMessageContainingEnum::TEST_OPTION_ENUM_TYPE2,
2451 options->GetExtension(protobuf_unittest::enum_opt));
2454 &protobuf_unittest::SettingRealsFromPositiveInts::descriptor()->options();
2455 EXPECT_FLOAT_EQ(12, options->GetExtension(protobuf_unittest::float_opt));
2456 EXPECT_DOUBLE_EQ(154, options->GetExtension(protobuf_unittest::double_opt));
2459 &protobuf_unittest::SettingRealsFromNegativeInts::descriptor()->options();
2460 EXPECT_FLOAT_EQ(-12, options->GetExtension(protobuf_unittest::float_opt));
2461 EXPECT_DOUBLE_EQ(-154, options->GetExtension(protobuf_unittest::double_opt));
2464 TEST(CustomOptions, ComplexExtensionOptions) {
2465 const MessageOptions* options =
2466 &protobuf_unittest::VariousComplexOptions::descriptor()->options();
2467 EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt1).foo(), 42);
2468 EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt1).
2469 GetExtension(protobuf_unittest::quux), 324);
2470 EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt1).
2471 GetExtension(protobuf_unittest::corge).qux(), 876);
2472 EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).baz(), 987);
2473 EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).
2474 GetExtension(protobuf_unittest::grault), 654);
2475 EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).bar().foo(),
2477 EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).bar().
2478 GetExtension(protobuf_unittest::quux), 1999);
2479 EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).bar().
2480 GetExtension(protobuf_unittest::corge).qux(), 2008);
2481 EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).
2482 GetExtension(protobuf_unittest::garply).foo(), 741);
2483 EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).
2484 GetExtension(protobuf_unittest::garply).
2485 GetExtension(protobuf_unittest::quux), 1998);
2486 EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).
2487 GetExtension(protobuf_unittest::garply).
2488 GetExtension(protobuf_unittest::corge).qux(), 2121);
2489 EXPECT_EQ(options->GetExtension(
2490 protobuf_unittest::ComplexOptionType2::ComplexOptionType4::complex_opt4).
2492 EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).
2493 fred().waldo(), 321);
2494 EXPECT_EQ(9, options->GetExtension(protobuf_unittest::complex_opt3).qux());
2495 EXPECT_EQ(22, options->GetExtension(protobuf_unittest::complex_opt3).
2496 complexoptiontype5().plugh());
2497 EXPECT_EQ(24, options->GetExtension(protobuf_unittest::complexopt6).xyzzy());
2500 TEST(CustomOptions, OptionsFromOtherFile) {
2501 // Test that to use a custom option, we only need to import the file
2502 // defining the option; we do not also have to import descriptor.proto.
2503 DescriptorPool pool;
2505 FileDescriptorProto file_proto;
2506 FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto);
2507 ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
2509 protobuf_unittest::TestMessageWithCustomOptions::descriptor()
2510 ->file()->CopyTo(&file_proto);
2511 ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
2513 ASSERT_TRUE(TextFormat::ParseFromString(
2514 "name: \"custom_options_import.proto\" "
2515 "package: \"protobuf_unittest\" "
2516 "dependency: \"google/protobuf/unittest_custom_options.proto\" "
2518 " uninterpreted_option { "
2520 " name_part: \"file_opt1\" "
2521 " is_extension: true "
2523 " positive_int_value: 1234 "
2525 // Test a non-extension option too. (At one point this failed due to a
2527 " uninterpreted_option { "
2529 " name_part: \"java_package\" "
2530 " is_extension: false "
2532 " string_value: \"foo\" "
2534 // Test that enum-typed options still work too. (At one point this also
2535 // failed due to a bug.)
2536 " uninterpreted_option { "
2538 " name_part: \"optimize_for\" "
2539 " is_extension: false "
2541 " identifier_value: \"SPEED\" "
2547 const FileDescriptor* file = pool.BuildFile(file_proto);
2548 ASSERT_TRUE(file != NULL);
2549 EXPECT_EQ(1234, file->options().GetExtension(protobuf_unittest::file_opt1));
2550 EXPECT_TRUE(file->options().has_java_package());
2551 EXPECT_EQ("foo", file->options().java_package());
2552 EXPECT_TRUE(file->options().has_optimize_for());
2553 EXPECT_EQ(FileOptions::SPEED, file->options().optimize_for());
2556 TEST(CustomOptions, MessageOptionThreeFieldsSet) {
2557 // This tests a bug which previously existed in custom options parsing. The
2558 // bug occurred when you defined a custom option with message type and then
2559 // set three fields of that option on a single definition (see the example
2560 // below). The bug is a bit hard to explain, so check the change history if
2561 // you want to know more.
2562 DescriptorPool pool;
2564 FileDescriptorProto file_proto;
2565 FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto);
2566 ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
2568 protobuf_unittest::TestMessageWithCustomOptions::descriptor()
2569 ->file()->CopyTo(&file_proto);
2570 ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
2572 // The following represents the definition:
2574 // import "google/protobuf/unittest_custom_options.proto"
2575 // package protobuf_unittest;
2577 // option (complex_opt1).foo = 1234;
2578 // option (complex_opt1).foo2 = 1234;
2579 // option (complex_opt1).foo3 = 1234;
2581 ASSERT_TRUE(TextFormat::ParseFromString(
2582 "name: \"custom_options_import.proto\" "
2583 "package: \"protobuf_unittest\" "
2584 "dependency: \"google/protobuf/unittest_custom_options.proto\" "
2588 " uninterpreted_option { "
2590 " name_part: \"complex_opt1\" "
2591 " is_extension: true "
2594 " name_part: \"foo\" "
2595 " is_extension: false "
2597 " positive_int_value: 1234 "
2599 " uninterpreted_option { "
2601 " name_part: \"complex_opt1\" "
2602 " is_extension: true "
2605 " name_part: \"foo2\" "
2606 " is_extension: false "
2608 " positive_int_value: 1234 "
2610 " uninterpreted_option { "
2612 " name_part: \"complex_opt1\" "
2613 " is_extension: true "
2616 " name_part: \"foo3\" "
2617 " is_extension: false "
2619 " positive_int_value: 1234 "
2625 const FileDescriptor* file = pool.BuildFile(file_proto);
2626 ASSERT_TRUE(file != NULL);
2627 ASSERT_EQ(1, file->message_type_count());
2629 const MessageOptions& options = file->message_type(0)->options();
2630 EXPECT_EQ(1234, options.GetExtension(protobuf_unittest::complex_opt1).foo());
2633 TEST(CustomOptions, MessageOptionRepeatedLeafFieldSet) {
2634 // This test verifies that repeated fields in custom options can be
2635 // given multiple values by repeating the option with a different value.
2636 // This test checks repeated leaf values. Each repeated custom value
2637 // appears in a different uninterpreted_option, which will be concatenated
2638 // when they are merged into the final option value.
2639 DescriptorPool pool;
2641 FileDescriptorProto file_proto;
2642 FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto);
2643 ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
2645 protobuf_unittest::TestMessageWithCustomOptions::descriptor()
2646 ->file()->CopyTo(&file_proto);
2647 ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
2649 // The following represents the definition:
2651 // import "google/protobuf/unittest_custom_options.proto"
2652 // package protobuf_unittest;
2654 // option (complex_opt1).foo4 = 12;
2655 // option (complex_opt1).foo4 = 34;
2656 // option (complex_opt1).foo4 = 56;
2658 ASSERT_TRUE(TextFormat::ParseFromString(
2659 "name: \"custom_options_import.proto\" "
2660 "package: \"protobuf_unittest\" "
2661 "dependency: \"google/protobuf/unittest_custom_options.proto\" "
2665 " uninterpreted_option { "
2667 " name_part: \"complex_opt1\" "
2668 " is_extension: true "
2671 " name_part: \"foo4\" "
2672 " is_extension: false "
2674 " positive_int_value: 12 "
2676 " uninterpreted_option { "
2678 " name_part: \"complex_opt1\" "
2679 " is_extension: true "
2682 " name_part: \"foo4\" "
2683 " is_extension: false "
2685 " positive_int_value: 34 "
2687 " uninterpreted_option { "
2689 " name_part: \"complex_opt1\" "
2690 " is_extension: true "
2693 " name_part: \"foo4\" "
2694 " is_extension: false "
2696 " positive_int_value: 56 "
2702 const FileDescriptor* file = pool.BuildFile(file_proto);
2703 ASSERT_TRUE(file != NULL);
2704 ASSERT_EQ(1, file->message_type_count());
2706 const MessageOptions& options = file->message_type(0)->options();
2707 EXPECT_EQ(3, options.GetExtension(protobuf_unittest::complex_opt1).foo4_size());
2708 EXPECT_EQ(12, options.GetExtension(protobuf_unittest::complex_opt1).foo4(0));
2709 EXPECT_EQ(34, options.GetExtension(protobuf_unittest::complex_opt1).foo4(1));
2710 EXPECT_EQ(56, options.GetExtension(protobuf_unittest::complex_opt1).foo4(2));
2713 TEST(CustomOptions, MessageOptionRepeatedMsgFieldSet) {
2714 // This test verifies that repeated fields in custom options can be
2715 // given multiple values by repeating the option with a different value.
2716 // This test checks repeated message values. Each repeated custom value
2717 // appears in a different uninterpreted_option, which will be concatenated
2718 // when they are merged into the final option value.
2719 DescriptorPool pool;
2721 FileDescriptorProto file_proto;
2722 FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto);
2723 ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
2725 protobuf_unittest::TestMessageWithCustomOptions::descriptor()
2726 ->file()->CopyTo(&file_proto);
2727 ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
2729 // The following represents the definition:
2731 // import "google/protobuf/unittest_custom_options.proto"
2732 // package protobuf_unittest;
2734 // option (complex_opt2).barney = {waldo: 1};
2735 // option (complex_opt2).barney = {waldo: 10};
2736 // option (complex_opt2).barney = {waldo: 100};
2738 ASSERT_TRUE(TextFormat::ParseFromString(
2739 "name: \"custom_options_import.proto\" "
2740 "package: \"protobuf_unittest\" "
2741 "dependency: \"google/protobuf/unittest_custom_options.proto\" "
2745 " uninterpreted_option { "
2747 " name_part: \"complex_opt2\" "
2748 " is_extension: true "
2751 " name_part: \"barney\" "
2752 " is_extension: false "
2754 " aggregate_value: \"waldo: 1\" "
2756 " uninterpreted_option { "
2758 " name_part: \"complex_opt2\" "
2759 " is_extension: true "
2762 " name_part: \"barney\" "
2763 " is_extension: false "
2765 " aggregate_value: \"waldo: 10\" "
2767 " uninterpreted_option { "
2769 " name_part: \"complex_opt2\" "
2770 " is_extension: true "
2773 " name_part: \"barney\" "
2774 " is_extension: false "
2776 " aggregate_value: \"waldo: 100\" "
2782 const FileDescriptor* file = pool.BuildFile(file_proto);
2783 ASSERT_TRUE(file != NULL);
2784 ASSERT_EQ(1, file->message_type_count());
2786 const MessageOptions& options = file->message_type(0)->options();
2787 EXPECT_EQ(3, options.GetExtension(
2788 protobuf_unittest::complex_opt2).barney_size());
2789 EXPECT_EQ(1,options.GetExtension(
2790 protobuf_unittest::complex_opt2).barney(0).waldo());
2791 EXPECT_EQ(10, options.GetExtension(
2792 protobuf_unittest::complex_opt2).barney(1).waldo());
2793 EXPECT_EQ(100, options.GetExtension(
2794 protobuf_unittest::complex_opt2).barney(2).waldo());
2797 // Check that aggregate options were parsed and saved correctly in
2798 // the appropriate descriptors.
2799 TEST(CustomOptions, AggregateOptions) {
2800 const Descriptor* msg = protobuf_unittest::AggregateMessage::descriptor();
2801 const FileDescriptor* file = msg->file();
2802 const FieldDescriptor* field = msg->FindFieldByName("fieldname");
2803 const EnumDescriptor* enumd = file->FindEnumTypeByName("AggregateEnum");
2804 const EnumValueDescriptor* enumv = enumd->FindValueByName("VALUE");
2805 const ServiceDescriptor* service = file->FindServiceByName(
2806 "AggregateService");
2807 const MethodDescriptor* method = service->FindMethodByName("Method");
2809 // Tests for the different types of data embedded in fileopt
2810 const protobuf_unittest::Aggregate& file_options =
2811 file->options().GetExtension(protobuf_unittest::fileopt);
2812 EXPECT_EQ(100, file_options.i());
2813 EXPECT_EQ("FileAnnotation", file_options.s());
2814 EXPECT_EQ("NestedFileAnnotation", file_options.sub().s());
2815 EXPECT_EQ("FileExtensionAnnotation",
2816 file_options.file().GetExtension(protobuf_unittest::fileopt).s());
2817 EXPECT_EQ("EmbeddedMessageSetElement",
2818 file_options.mset().GetExtension(
2819 protobuf_unittest::AggregateMessageSetElement
2820 ::message_set_extension).s());
2822 // Simple tests for all the other types of annotations
2823 EXPECT_EQ("MessageAnnotation",
2824 msg->options().GetExtension(protobuf_unittest::msgopt).s());
2825 EXPECT_EQ("FieldAnnotation",
2826 field->options().GetExtension(protobuf_unittest::fieldopt).s());
2827 EXPECT_EQ("EnumAnnotation",
2828 enumd->options().GetExtension(protobuf_unittest::enumopt).s());
2829 EXPECT_EQ("EnumValueAnnotation",
2830 enumv->options().GetExtension(protobuf_unittest::enumvalopt).s());
2831 EXPECT_EQ("ServiceAnnotation",
2832 service->options().GetExtension(protobuf_unittest::serviceopt).s());
2833 EXPECT_EQ("MethodAnnotation",
2834 method->options().GetExtension(protobuf_unittest::methodopt).s());
2837 TEST(CustomOptions, UnusedImportWarning) {
2838 DescriptorPool pool;
2840 FileDescriptorProto file_proto;
2841 FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto);
2842 ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
2844 protobuf_unittest::TestMessageWithCustomOptions::descriptor()
2845 ->file()->CopyTo(&file_proto);
2846 ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
2849 pool.AddUnusedImportTrackFile("custom_options_import.proto");
2850 ASSERT_TRUE(TextFormat::ParseFromString(
2851 "name: \"custom_options_import.proto\" "
2852 "package: \"protobuf_unittest\" "
2853 "dependency: \"google/protobuf/unittest_custom_options.proto\" ",
2855 pool.BuildFile(file_proto);
2858 // ===================================================================
2860 // The tests below trigger every unique call to AddError() in descriptor.cc,
2861 // in the order in which they appear in that file. I'm using TextFormat here
2862 // to specify the input descriptors because building them using code would
2865 class MockErrorCollector : public DescriptorPool::ErrorCollector {
2867 MockErrorCollector() {}
2868 ~MockErrorCollector() {}
2871 string warning_text_;
2873 // implements ErrorCollector ---------------------------------------
2874 void AddError(const string& filename,
2875 const string& element_name, const Message* descriptor,
2876 ErrorLocation location, const string& message) {
2877 const char* location_name = NULL;
2879 case NAME : location_name = "NAME" ; break;
2880 case NUMBER : location_name = "NUMBER" ; break;
2881 case TYPE : location_name = "TYPE" ; break;
2882 case EXTENDEE : location_name = "EXTENDEE" ; break;
2883 case DEFAULT_VALUE: location_name = "DEFAULT_VALUE"; break;
2884 case OPTION_NAME : location_name = "OPTION_NAME" ; break;
2885 case OPTION_VALUE : location_name = "OPTION_VALUE" ; break;
2886 case INPUT_TYPE : location_name = "INPUT_TYPE" ; break;
2887 case OUTPUT_TYPE : location_name = "OUTPUT_TYPE" ; break;
2888 case OTHER : location_name = "OTHER" ; break;
2891 strings::SubstituteAndAppend(
2892 &text_, "$0: $1: $2: $3\n",
2893 filename, element_name, location_name, message);
2896 // implements ErrorCollector ---------------------------------------
2897 void AddWarning(const string& filename, const string& element_name,
2898 const Message* descriptor, ErrorLocation location,
2899 const string& message) {
2900 const char* location_name = NULL;
2902 case NAME : location_name = "NAME" ; break;
2903 case NUMBER : location_name = "NUMBER" ; break;
2904 case TYPE : location_name = "TYPE" ; break;
2905 case EXTENDEE : location_name = "EXTENDEE" ; break;
2906 case DEFAULT_VALUE: location_name = "DEFAULT_VALUE"; break;
2907 case OPTION_NAME : location_name = "OPTION_NAME" ; break;
2908 case OPTION_VALUE : location_name = "OPTION_VALUE" ; break;
2909 case INPUT_TYPE : location_name = "INPUT_TYPE" ; break;
2910 case OUTPUT_TYPE : location_name = "OUTPUT_TYPE" ; break;
2911 case OTHER : location_name = "OTHER" ; break;
2914 strings::SubstituteAndAppend(
2915 &warning_text_, "$0: $1: $2: $3\n",
2916 filename, element_name, location_name, message);
2920 class ValidationErrorTest : public testing::Test {
2922 // Parse file_text as a FileDescriptorProto in text format and add it
2923 // to the DescriptorPool. Expect no errors.
2924 void BuildFile(const string& file_text) {
2925 FileDescriptorProto file_proto;
2926 ASSERT_TRUE(TextFormat::ParseFromString(file_text, &file_proto));
2927 ASSERT_TRUE(pool_.BuildFile(file_proto) != NULL);
2930 // Parse file_text as a FileDescriptorProto in text format and add it
2931 // to the DescriptorPool. Expect errors to be produced which match the
2932 // given error text.
2933 void BuildFileWithErrors(const string& file_text,
2934 const string& expected_errors) {
2935 FileDescriptorProto file_proto;
2936 ASSERT_TRUE(TextFormat::ParseFromString(file_text, &file_proto));
2938 MockErrorCollector error_collector;
2940 pool_.BuildFileCollectingErrors(file_proto, &error_collector) == NULL);
2941 EXPECT_EQ(expected_errors, error_collector.text_);
2944 // Parse file_text as a FileDescriptorProto in text format and add it
2945 // to the DescriptorPool. Expect errors to be produced which match the
2946 // given warning text.
2947 void BuildFileWithWarnings(const string& file_text,
2948 const string& expected_warnings) {
2949 FileDescriptorProto file_proto;
2950 ASSERT_TRUE(TextFormat::ParseFromString(file_text, &file_proto));
2952 MockErrorCollector error_collector;
2953 EXPECT_TRUE(pool_.BuildFileCollectingErrors(file_proto, &error_collector));
2954 EXPECT_EQ(expected_warnings, error_collector.warning_text_);
2957 // Builds some already-parsed file in our test pool.
2958 void BuildFileInTestPool(const FileDescriptor* file) {
2959 FileDescriptorProto file_proto;
2960 file->CopyTo(&file_proto);
2961 ASSERT_TRUE(pool_.BuildFile(file_proto) != NULL);
2964 // Build descriptor.proto in our test pool. This allows us to extend it in
2965 // the test pool, so we can test custom options.
2966 void BuildDescriptorMessagesInTestPool() {
2967 BuildFileInTestPool(DescriptorProto::descriptor()->file());
2970 DescriptorPool pool_;
2973 TEST_F(ValidationErrorTest, AlreadyDefined) {
2974 BuildFileWithErrors(
2975 "name: \"foo.proto\" "
2976 "message_type { name: \"Foo\" }"
2977 "message_type { name: \"Foo\" }",
2979 "foo.proto: Foo: NAME: \"Foo\" is already defined.\n");
2982 TEST_F(ValidationErrorTest, AlreadyDefinedInPackage) {
2983 BuildFileWithErrors(
2984 "name: \"foo.proto\" "
2985 "package: \"foo.bar\" "
2986 "message_type { name: \"Foo\" }"
2987 "message_type { name: \"Foo\" }",
2989 "foo.proto: foo.bar.Foo: NAME: \"Foo\" is already defined in "
2993 TEST_F(ValidationErrorTest, AlreadyDefinedInOtherFile) {
2995 "name: \"foo.proto\" "
2996 "message_type { name: \"Foo\" }");
2998 BuildFileWithErrors(
2999 "name: \"bar.proto\" "
3000 "message_type { name: \"Foo\" }",
3002 "bar.proto: Foo: NAME: \"Foo\" is already defined in file "
3003 "\"foo.proto\".\n");
3006 TEST_F(ValidationErrorTest, PackageAlreadyDefined) {
3008 "name: \"foo.proto\" "
3009 "message_type { name: \"foo\" }");
3010 BuildFileWithErrors(
3011 "name: \"bar.proto\" "
3012 "package: \"foo.bar\"",
3014 "bar.proto: foo: NAME: \"foo\" is already defined (as something other "
3015 "than a package) in file \"foo.proto\".\n");
3018 TEST_F(ValidationErrorTest, EnumValueAlreadyDefinedInParent) {
3019 BuildFileWithErrors(
3020 "name: \"foo.proto\" "
3021 "enum_type { name: \"Foo\" value { name: \"FOO\" number: 1 } } "
3022 "enum_type { name: \"Bar\" value { name: \"FOO\" number: 1 } } ",
3024 "foo.proto: FOO: NAME: \"FOO\" is already defined.\n"
3025 "foo.proto: FOO: NAME: Note that enum values use C++ scoping rules, "
3026 "meaning that enum values are siblings of their type, not children of "
3027 "it. Therefore, \"FOO\" must be unique within the global scope, not "
3028 "just within \"Bar\".\n");
3031 TEST_F(ValidationErrorTest, EnumValueAlreadyDefinedInParentNonGlobal) {
3032 BuildFileWithErrors(
3033 "name: \"foo.proto\" "
3035 "enum_type { name: \"Foo\" value { name: \"FOO\" number: 1 } } "
3036 "enum_type { name: \"Bar\" value { name: \"FOO\" number: 1 } } ",
3038 "foo.proto: pkg.FOO: NAME: \"FOO\" is already defined in \"pkg\".\n"
3039 "foo.proto: pkg.FOO: NAME: Note that enum values use C++ scoping rules, "
3040 "meaning that enum values are siblings of their type, not children of "
3041 "it. Therefore, \"FOO\" must be unique within \"pkg\", not just within "
3045 TEST_F(ValidationErrorTest, MissingName) {
3046 BuildFileWithErrors(
3047 "name: \"foo.proto\" "
3050 "foo.proto: : NAME: Missing name.\n");
3053 TEST_F(ValidationErrorTest, InvalidName) {
3054 BuildFileWithErrors(
3055 "name: \"foo.proto\" "
3056 "message_type { name: \"$\" }",
3058 "foo.proto: $: NAME: \"$\" is not a valid identifier.\n");
3061 TEST_F(ValidationErrorTest, InvalidPackageName) {
3062 BuildFileWithErrors(
3063 "name: \"foo.proto\" "
3064 "package: \"foo.$\"",
3066 "foo.proto: foo.$: NAME: \"$\" is not a valid identifier.\n");
3069 TEST_F(ValidationErrorTest, MissingFileName) {
3070 BuildFileWithErrors(
3073 ": : OTHER: Missing field: FileDescriptorProto.name.\n");
3076 TEST_F(ValidationErrorTest, DupeDependency) {
3077 BuildFile("name: \"foo.proto\"");
3078 BuildFileWithErrors(
3079 "name: \"bar.proto\" "
3080 "dependency: \"foo.proto\" "
3081 "dependency: \"foo.proto\" ",
3083 "bar.proto: bar.proto: OTHER: Import \"foo.proto\" was listed twice.\n");
3086 TEST_F(ValidationErrorTest, UnknownDependency) {
3087 BuildFileWithErrors(
3088 "name: \"bar.proto\" "
3089 "dependency: \"foo.proto\" ",
3091 "bar.proto: bar.proto: OTHER: Import \"foo.proto\" has not been loaded.\n");
3094 TEST_F(ValidationErrorTest, InvalidPublicDependencyIndex) {
3095 BuildFile("name: \"foo.proto\"");
3096 BuildFileWithErrors(
3097 "name: \"bar.proto\" "
3098 "dependency: \"foo.proto\" "
3099 "public_dependency: 1",
3100 "bar.proto: bar.proto: OTHER: Invalid public dependency index.\n");
3103 TEST_F(ValidationErrorTest, ForeignUnimportedPackageNoCrash) {
3104 // Used to crash: If we depend on a non-existent file and then refer to a
3105 // package defined in a file that we didn't import, and that package is
3106 // nested within a parent package which this file is also in, and we don't
3107 // include that parent package in the name (i.e. we do a relative lookup)...
3110 "name: 'foo.proto' "
3111 "package: 'outer.foo' ");
3112 BuildFileWithErrors(
3113 "name: 'bar.proto' "
3114 "dependency: 'baz.proto' "
3115 "package: 'outer.bar' "
3118 " field { name:'bar' number:1 label:LABEL_OPTIONAL type_name:'foo.Foo' }"
3121 "bar.proto: bar.proto: OTHER: Import \"baz.proto\" has not been loaded.\n"
3122 "bar.proto: outer.bar.Bar.bar: TYPE: \"outer.foo\" seems to be defined in "
3123 "\"foo.proto\", which is not imported by \"bar.proto\". To use it here, "
3124 "please add the necessary import.\n");
3127 TEST_F(ValidationErrorTest, DupeFile) {
3129 "name: \"foo.proto\" "
3130 "message_type { name: \"Foo\" }");
3131 // Note: We should *not* get redundant errors about "Foo" already being
3133 BuildFileWithErrors(
3134 "name: \"foo.proto\" "
3135 "message_type { name: \"Foo\" } "
3136 // Add another type so that the files aren't identical (in which case there
3137 // would be no error).
3138 "enum_type { name: \"Bar\" }",
3140 "foo.proto: foo.proto: OTHER: A file with this name is already in the "
3144 TEST_F(ValidationErrorTest, FieldInExtensionRange) {
3145 BuildFileWithErrors(
3146 "name: \"foo.proto\" "
3149 " field { name: \"foo\" number: 9 label:LABEL_OPTIONAL type:TYPE_INT32 }"
3150 " field { name: \"bar\" number: 10 label:LABEL_OPTIONAL type:TYPE_INT32 }"
3151 " field { name: \"baz\" number: 19 label:LABEL_OPTIONAL type:TYPE_INT32 }"
3152 " field { name: \"qux\" number: 20 label:LABEL_OPTIONAL type:TYPE_INT32 }"
3153 " extension_range { start: 10 end: 20 }"
3156 "foo.proto: Foo.bar: NUMBER: Extension range 10 to 19 includes field "
3158 "foo.proto: Foo.baz: NUMBER: Extension range 10 to 19 includes field "
3162 TEST_F(ValidationErrorTest, OverlappingExtensionRanges) {
3163 BuildFileWithErrors(
3164 "name: \"foo.proto\" "
3167 " extension_range { start: 10 end: 20 }"
3168 " extension_range { start: 20 end: 30 }"
3169 " extension_range { start: 19 end: 21 }"
3172 "foo.proto: Foo: NUMBER: Extension range 19 to 20 overlaps with "
3173 "already-defined range 10 to 19.\n"
3174 "foo.proto: Foo: NUMBER: Extension range 19 to 20 overlaps with "
3175 "already-defined range 20 to 29.\n");
3178 TEST_F(ValidationErrorTest, InvalidDefaults) {
3179 BuildFileWithErrors(
3180 "name: \"foo.proto\" "
3185 " field { name: \"foo\" number: 1 label: LABEL_OPTIONAL type: TYPE_INT32"
3186 " default_value: \"abc\" }"
3188 // Empty default value.
3189 " field { name: \"bar\" number: 2 label: LABEL_OPTIONAL type: TYPE_INT32"
3190 " default_value: \"\" }"
3193 " field { name: \"baz\" number: 3 label: LABEL_OPTIONAL type: TYPE_BOOL"
3194 " default_value: \"abc\" }"
3196 // Messages can't have defaults.
3197 " field { name: \"qux\" number: 4 label: LABEL_OPTIONAL type: TYPE_MESSAGE"
3198 " default_value: \"abc\" type_name: \"Foo\" }"
3200 // Same thing, but we don't know that this field has message type until
3201 // we look up the type name.
3202 " field { name: \"quux\" number: 5 label: LABEL_OPTIONAL"
3203 " default_value: \"abc\" type_name: \"Foo\" }"
3205 // Repeateds can't have defaults.
3206 " field { name: \"corge\" number: 6 label: LABEL_REPEATED type: TYPE_INT32"
3207 " default_value: \"1\" }"
3210 "foo.proto: Foo.foo: DEFAULT_VALUE: Couldn't parse default value \"abc\".\n"
3211 "foo.proto: Foo.bar: DEFAULT_VALUE: Couldn't parse default value \"\".\n"
3212 "foo.proto: Foo.baz: DEFAULT_VALUE: Boolean default must be true or "
3214 "foo.proto: Foo.qux: DEFAULT_VALUE: Messages can't have default values.\n"
3215 "foo.proto: Foo.corge: DEFAULT_VALUE: Repeated fields can't have default "
3217 // This ends up being reported later because the error is detected at
3218 // cross-linking time.
3219 "foo.proto: Foo.quux: DEFAULT_VALUE: Messages can't have default "
3223 TEST_F(ValidationErrorTest, NegativeFieldNumber) {
3224 BuildFileWithErrors(
3225 "name: \"foo.proto\" "
3228 " field { name: \"foo\" number: -1 label:LABEL_OPTIONAL type:TYPE_INT32 }"
3231 "foo.proto: Foo.foo: NUMBER: Field numbers must be positive integers.\n");
3234 TEST_F(ValidationErrorTest, HugeFieldNumber) {
3235 BuildFileWithErrors(
3236 "name: \"foo.proto\" "
3239 " field { name: \"foo\" number: 0x70000000 "
3240 " label:LABEL_OPTIONAL type:TYPE_INT32 }"
3243 "foo.proto: Foo.foo: NUMBER: Field numbers cannot be greater than "
3247 TEST_F(ValidationErrorTest, ReservedFieldNumber) {
3248 BuildFileWithErrors(
3249 "name: \"foo.proto\" "
3252 " field {name:\"foo\" number: 18999 label:LABEL_OPTIONAL type:TYPE_INT32 }"
3253 " field {name:\"bar\" number: 19000 label:LABEL_OPTIONAL type:TYPE_INT32 }"
3254 " field {name:\"baz\" number: 19999 label:LABEL_OPTIONAL type:TYPE_INT32 }"
3255 " field {name:\"qux\" number: 20000 label:LABEL_OPTIONAL type:TYPE_INT32 }"
3258 "foo.proto: Foo.bar: NUMBER: Field numbers 19000 through 19999 are "
3259 "reserved for the protocol buffer library implementation.\n"
3260 "foo.proto: Foo.baz: NUMBER: Field numbers 19000 through 19999 are "
3261 "reserved for the protocol buffer library implementation.\n");
3264 TEST_F(ValidationErrorTest, ExtensionMissingExtendee) {
3265 BuildFileWithErrors(
3266 "name: \"foo.proto\" "
3269 " extension { name: \"foo\" number: 1 label: LABEL_OPTIONAL"
3270 " type_name: \"Foo\" }"
3273 "foo.proto: Foo.foo: EXTENDEE: FieldDescriptorProto.extendee not set for "
3274 "extension field.\n");
3277 TEST_F(ValidationErrorTest, NonExtensionWithExtendee) {
3278 BuildFileWithErrors(
3279 "name: \"foo.proto\" "
3282 " extension_range { start: 1 end: 2 }"
3286 " field { name: \"foo\" number: 1 label: LABEL_OPTIONAL"
3287 " type_name: \"Foo\" extendee: \"Bar\" }"
3290 "foo.proto: Foo.foo: EXTENDEE: FieldDescriptorProto.extendee set for "
3291 "non-extension field.\n");
3294 TEST_F(ValidationErrorTest, FieldOneofIndexTooLarge) {
3295 BuildFileWithErrors(
3296 "name: \"foo.proto\" "
3299 " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32 "
3301 " field { name:\"dummy\" number:2 label:LABEL_OPTIONAL type:TYPE_INT32 "
3303 " oneof_decl { name:\"bar\" }"
3306 "foo.proto: Foo.foo: OTHER: FieldDescriptorProto.oneof_index 1 is out of "
3307 "range for type \"Foo\".\n");
3310 TEST_F(ValidationErrorTest, FieldOneofIndexNegative) {
3311 BuildFileWithErrors(
3312 "name: \"foo.proto\" "
3315 " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32 "
3316 " oneof_index: -1 }"
3317 " field { name:\"dummy\" number:2 label:LABEL_OPTIONAL type:TYPE_INT32 "
3319 " oneof_decl { name:\"bar\" }"
3322 "foo.proto: Foo.foo: OTHER: FieldDescriptorProto.oneof_index -1 is out of "
3323 "range for type \"Foo\".\n");
3326 TEST_F(ValidationErrorTest, FieldNumberConflict) {
3327 BuildFileWithErrors(
3328 "name: \"foo.proto\" "
3331 " field { name: \"foo\" number: 1 label:LABEL_OPTIONAL type:TYPE_INT32 }"
3332 " field { name: \"bar\" number: 1 label:LABEL_OPTIONAL type:TYPE_INT32 }"
3335 "foo.proto: Foo.bar: NUMBER: Field number 1 has already been used in "
3336 "\"Foo\" by field \"foo\".\n");
3339 TEST_F(ValidationErrorTest, BadMessageSetExtensionType) {
3340 BuildFileWithErrors(
3341 "name: \"foo.proto\" "
3343 " name: \"MessageSet\""
3344 " options { message_set_wire_format: true }"
3345 " extension_range { start: 4 end: 5 }"
3349 " extension { name:\"foo\" number:4 label:LABEL_OPTIONAL type:TYPE_INT32"
3350 " extendee: \"MessageSet\" }"
3353 "foo.proto: Foo.foo: TYPE: Extensions of MessageSets must be optional "
3357 TEST_F(ValidationErrorTest, BadMessageSetExtensionLabel) {
3358 BuildFileWithErrors(
3359 "name: \"foo.proto\" "
3361 " name: \"MessageSet\""
3362 " options { message_set_wire_format: true }"
3363 " extension_range { start: 4 end: 5 }"
3367 " extension { name:\"foo\" number:4 label:LABEL_REPEATED type:TYPE_MESSAGE"
3368 " type_name: \"Foo\" extendee: \"MessageSet\" }"
3371 "foo.proto: Foo.foo: TYPE: Extensions of MessageSets must be optional "
3375 TEST_F(ValidationErrorTest, FieldInMessageSet) {
3376 BuildFileWithErrors(
3377 "name: \"foo.proto\" "
3380 " options { message_set_wire_format: true }"
3381 " field { name: \"foo\" number: 1 label:LABEL_OPTIONAL type:TYPE_INT32 }"
3384 "foo.proto: Foo.foo: NAME: MessageSets cannot have fields, only "
3388 TEST_F(ValidationErrorTest, NegativeExtensionRangeNumber) {
3389 BuildFileWithErrors(
3390 "name: \"foo.proto\" "
3393 " extension_range { start: -10 end: -1 }"
3396 "foo.proto: Foo: NUMBER: Extension numbers must be positive integers.\n");
3399 TEST_F(ValidationErrorTest, HugeExtensionRangeNumber) {
3400 BuildFileWithErrors(
3401 "name: \"foo.proto\" "
3404 " extension_range { start: 1 end: 0x70000000 }"
3407 "foo.proto: Foo: NUMBER: Extension numbers cannot be greater than "
3411 TEST_F(ValidationErrorTest, ExtensionRangeEndBeforeStart) {
3412 BuildFileWithErrors(
3413 "name: \"foo.proto\" "
3416 " extension_range { start: 10 end: 10 }"
3417 " extension_range { start: 10 end: 5 }"
3420 "foo.proto: Foo: NUMBER: Extension range end number must be greater than "
3422 "foo.proto: Foo: NUMBER: Extension range end number must be greater than "
3426 TEST_F(ValidationErrorTest, EmptyEnum) {
3427 BuildFileWithErrors(
3428 "name: \"foo.proto\" "
3429 "enum_type { name: \"Foo\" }"
3430 // Also use the empty enum in a message to make sure there are no crashes
3431 // during validation (possible if the code attempts to derive a default
3432 // value for the field).
3435 " field { name: \"foo\" number: 1 label:LABEL_OPTIONAL type_name:\"Foo\" }"
3436 " field { name: \"bar\" number: 2 label:LABEL_OPTIONAL type_name:\"Foo\" "
3437 " default_value: \"NO_SUCH_VALUE\" }"
3440 "foo.proto: Foo: NAME: Enums must contain at least one value.\n"
3441 "foo.proto: Bar.bar: DEFAULT_VALUE: Enum type \"Foo\" has no value named "
3442 "\"NO_SUCH_VALUE\".\n");
3445 TEST_F(ValidationErrorTest, UndefinedExtendee) {
3446 BuildFileWithErrors(
3447 "name: \"foo.proto\" "
3450 " extension { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32"
3451 " extendee: \"Bar\" }"
3454 "foo.proto: Foo.foo: EXTENDEE: \"Bar\" is not defined.\n");
3457 TEST_F(ValidationErrorTest, NonMessageExtendee) {
3458 BuildFileWithErrors(
3459 "name: \"foo.proto\" "
3460 "enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } }"
3463 " extension { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32"
3464 " extendee: \"Bar\" }"
3467 "foo.proto: Foo.foo: EXTENDEE: \"Bar\" is not a message type.\n");
3470 TEST_F(ValidationErrorTest, NotAnExtensionNumber) {
3471 BuildFileWithErrors(
3472 "name: \"foo.proto\" "
3478 " extension { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32"
3479 " extendee: \"Bar\" }"
3482 "foo.proto: Foo.foo: NUMBER: \"Bar\" does not declare 1 as an extension "
3486 TEST_F(ValidationErrorTest, RequiredExtension) {
3487 BuildFileWithErrors(
3488 "name: \"foo.proto\" "
3491 " extension_range { start: 1000 end: 10000 }"
3498 " label:LABEL_REQUIRED"
3500 " extendee: \"Bar\""
3504 "foo.proto: Foo.foo: TYPE: Message extensions cannot have required "
3508 TEST_F(ValidationErrorTest, UndefinedFieldType) {
3509 BuildFileWithErrors(
3510 "name: \"foo.proto\" "
3513 " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }"
3516 "foo.proto: Foo.foo: TYPE: \"Bar\" is not defined.\n");
3519 TEST_F(ValidationErrorTest, UndefinedFieldTypeWithDefault) {
3520 // See b/12533582. Previously this failed because the default value was not
3521 // accepted by the parser, which assumed an enum type, leading to an unclear
3522 // error message. We want this input to yield a validation error instead,
3523 // since the unknown type is the primary problem.
3524 BuildFileWithErrors(
3525 "name: \"foo.proto\" "
3528 " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"int\" "
3529 " default_value:\"1\" }"
3532 "foo.proto: Foo.foo: TYPE: \"int\" is not defined.\n");
3535 TEST_F(ValidationErrorTest, UndefinedNestedFieldType) {
3536 BuildFileWithErrors(
3537 "name: \"foo.proto\" "
3540 " nested_type { name:\"Baz\" }"
3541 " field { name:\"foo\" number:1"
3542 " label:LABEL_OPTIONAL"
3543 " type_name:\"Foo.Baz.Bar\" }"
3546 "foo.proto: Foo.foo: TYPE: \"Foo.Baz.Bar\" is not defined.\n");
3549 TEST_F(ValidationErrorTest, FieldTypeDefinedInUndeclaredDependency) {
3551 "name: \"bar.proto\" "
3552 "message_type { name: \"Bar\" } ");
3554 BuildFileWithErrors(
3555 "name: \"foo.proto\" "
3558 " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }"
3560 "foo.proto: Foo.foo: TYPE: \"Bar\" seems to be defined in \"bar.proto\", "
3561 "which is not imported by \"foo.proto\". To use it here, please add the "
3562 "necessary import.\n");
3565 TEST_F(ValidationErrorTest, FieldTypeDefinedInIndirectDependency) {
3566 // Test for hidden dependencies.
3572 // import "bar.proto"
3575 // import "forward.proto"
3577 // optional Bar foo = 1; // Error, needs to import bar.proto explicitly.
3581 "name: \"bar.proto\" "
3582 "message_type { name: \"Bar\" }");
3585 "name: \"forward.proto\""
3586 "dependency: \"bar.proto\"");
3588 BuildFileWithErrors(
3589 "name: \"foo.proto\" "
3590 "dependency: \"forward.proto\" "
3593 " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }"
3595 "foo.proto: Foo.foo: TYPE: \"Bar\" seems to be defined in \"bar.proto\", "
3596 "which is not imported by \"foo.proto\". To use it here, please add the "
3597 "necessary import.\n");
3600 TEST_F(ValidationErrorTest, FieldTypeDefinedInPublicDependency) {
3601 // Test for public dependencies.
3607 // import public "bar.proto"
3610 // import "forward.proto"
3612 // optional Bar foo = 1; // Correct. "bar.proto" is public imported into
3613 // // forward.proto, so when "foo.proto" imports
3614 // // "forward.proto", it imports "bar.proto" too.
3618 "name: \"bar.proto\" "
3619 "message_type { name: \"Bar\" }");
3622 "name: \"forward.proto\""
3623 "dependency: \"bar.proto\" "
3624 "public_dependency: 0");
3627 "name: \"foo.proto\" "
3628 "dependency: \"forward.proto\" "
3631 " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }"
3635 TEST_F(ValidationErrorTest, FieldTypeDefinedInTransitivePublicDependency) {
3636 // Test for public dependencies.
3642 // import public "bar.proto"
3644 // // forward2.proto
3645 // import public "forward.proto"
3648 // import "forward2.proto"
3650 // optional Bar foo = 1; // Correct, public imports are transitive.
3654 "name: \"bar.proto\" "
3655 "message_type { name: \"Bar\" }");
3658 "name: \"forward.proto\""
3659 "dependency: \"bar.proto\" "
3660 "public_dependency: 0");
3663 "name: \"forward2.proto\""
3664 "dependency: \"forward.proto\" "
3665 "public_dependency: 0");
3668 "name: \"foo.proto\" "
3669 "dependency: \"forward2.proto\" "
3672 " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }"
3676 TEST_F(ValidationErrorTest,
3677 FieldTypeDefinedInPrivateDependencyOfPublicDependency) {
3678 // Test for public dependencies.
3684 // import "bar.proto"
3686 // // forward2.proto
3687 // import public "forward.proto"
3690 // import "forward2.proto"
3692 // optional Bar foo = 1; // Error, the "bar.proto" is not public imported
3693 // // into "forward.proto", so will not be imported
3694 // // into either "forward2.proto" or "foo.proto".
3698 "name: \"bar.proto\" "
3699 "message_type { name: \"Bar\" }");
3702 "name: \"forward.proto\""
3703 "dependency: \"bar.proto\"");
3706 "name: \"forward2.proto\""
3707 "dependency: \"forward.proto\" "
3708 "public_dependency: 0");
3710 BuildFileWithErrors(
3711 "name: \"foo.proto\" "
3712 "dependency: \"forward2.proto\" "
3715 " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }"
3717 "foo.proto: Foo.foo: TYPE: \"Bar\" seems to be defined in \"bar.proto\", "
3718 "which is not imported by \"foo.proto\". To use it here, please add the "
3719 "necessary import.\n");
3723 TEST_F(ValidationErrorTest, SearchMostLocalFirst) {
3724 // The following should produce an error that Bar.Baz is resolved but
3726 // message Bar { message Baz {} }
3729 // // Placing "message Baz{}" here, or removing Foo.Bar altogether,
3730 // // would fix the error.
3732 // optional Bar.Baz baz = 1;
3734 // An one point the lookup code incorrectly did not produce an error in this
3735 // case, because when looking for Bar.Baz, it would try "Foo.Bar.Baz" first,
3736 // fail, and ten try "Bar.Baz" and succeed, even though "Bar" should actually
3737 // refer to the inner Bar, not the outer one.
3738 BuildFileWithErrors(
3739 "name: \"foo.proto\" "
3742 " nested_type { name: \"Baz\" }"
3746 " nested_type { name: \"Bar\" }"
3747 " field { name:\"baz\" number:1 label:LABEL_OPTIONAL"
3748 " type_name:\"Bar.Baz\" }"
3751 "foo.proto: Foo.baz: TYPE: \"Bar.Baz\" is resolved to \"Foo.Bar.Baz\","
3752 " which is not defined. The innermost scope is searched first in name "
3753 "resolution. Consider using a leading '.'(i.e., \".Bar.Baz\") to start "
3754 "from the outermost scope.\n");
3757 TEST_F(ValidationErrorTest, SearchMostLocalFirst2) {
3758 // This test would find the most local "Bar" first, and does, but
3759 // proceeds to find the outer one because the inner one's not an
3762 "name: \"foo.proto\" "
3765 " nested_type { name: \"Baz\" }"
3769 " field { name: \"Bar\" number:1 type:TYPE_BYTES } "
3770 " field { name:\"baz\" number:2 label:LABEL_OPTIONAL"
3771 " type_name:\"Bar.Baz\" }"
3775 TEST_F(ValidationErrorTest, PackageOriginallyDeclaredInTransitiveDependent) {
3776 // Imagine we have the following:
3782 // import "foo.proto";
3786 // import "bar.proto"
3787 // message Baz { optional bar.Bar qux = 1; }
3789 // When validating baz.proto, we will look up "bar.Bar". As part of this
3790 // lookup, we first lookup "bar" then try to find "Bar" within it. "bar"
3791 // should resolve to "foo.bar". Note, though, that "foo.bar" was originally
3792 // defined in foo.proto, which is not a direct dependency of baz.proto. The
3793 // implementation of FindSymbol() normally only returns symbols in direct
3794 // dependencies, not indirect ones. This test insures that this does not
3795 // prevent it from finding "foo.bar".
3798 "name: \"foo.proto\" "
3799 "package: \"foo.bar\" ");
3801 "name: \"bar.proto\" "
3802 "package: \"foo.bar\" "
3803 "dependency: \"foo.proto\" "
3804 "message_type { name: \"Bar\" }");
3806 "name: \"baz.proto\" "
3808 "dependency: \"bar.proto\" "
3811 " field { name:\"qux\" number:1 label:LABEL_OPTIONAL "
3812 " type_name:\"bar.Bar\" }"
3816 TEST_F(ValidationErrorTest, FieldTypeNotAType) {
3817 BuildFileWithErrors(
3818 "name: \"foo.proto\" "
3821 " field { name:\"foo\" number:1 label:LABEL_OPTIONAL "
3822 " type_name:\".Foo.bar\" }"
3823 " field { name:\"bar\" number:2 label:LABEL_OPTIONAL type:TYPE_INT32 }"
3826 "foo.proto: Foo.foo: TYPE: \".Foo.bar\" is not a type.\n");
3829 TEST_F(ValidationErrorTest, RelativeFieldTypeNotAType) {
3830 BuildFileWithErrors(
3831 "name: \"foo.proto\" "
3835 " field { name:\"Baz\" number:2 label:LABEL_OPTIONAL type:TYPE_INT32 }"
3838 " field { name:\"foo\" number:1 label:LABEL_OPTIONAL "
3839 " type_name:\"Bar.Baz\" }"
3841 "foo.proto: Foo.foo: TYPE: \"Bar.Baz\" is not a type.\n");
3844 TEST_F(ValidationErrorTest, FieldTypeMayBeItsName) {
3846 "name: \"foo.proto\" "
3852 " field { name:\"Bar\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }"
3856 TEST_F(ValidationErrorTest, EnumFieldTypeIsMessage) {
3857 BuildFileWithErrors(
3858 "name: \"foo.proto\" "
3859 "message_type { name: \"Bar\" } "
3862 " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_ENUM"
3863 " type_name:\"Bar\" }"
3866 "foo.proto: Foo.foo: TYPE: \"Bar\" is not an enum type.\n");
3869 TEST_F(ValidationErrorTest, MessageFieldTypeIsEnum) {
3870 BuildFileWithErrors(
3871 "name: \"foo.proto\" "
3872 "enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } } "
3875 " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_MESSAGE"
3876 " type_name:\"Bar\" }"
3879 "foo.proto: Foo.foo: TYPE: \"Bar\" is not a message type.\n");
3882 TEST_F(ValidationErrorTest, BadEnumDefaultValue) {
3883 BuildFileWithErrors(
3884 "name: \"foo.proto\" "
3885 "enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } } "
3888 " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\""
3889 " default_value:\"NO_SUCH_VALUE\" }"
3892 "foo.proto: Foo.foo: DEFAULT_VALUE: Enum type \"Bar\" has no value named "
3893 "\"NO_SUCH_VALUE\".\n");
3896 TEST_F(ValidationErrorTest, EnumDefaultValueIsInteger) {
3897 BuildFileWithErrors(
3898 "name: \"foo.proto\" "
3899 "enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } } "
3902 " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\""
3903 " default_value:\"0\" }"
3906 "foo.proto: Foo.foo: DEFAULT_VALUE: Default value for an enum field must "
3907 "be an identifier.\n");
3910 TEST_F(ValidationErrorTest, PrimitiveWithTypeName) {
3911 BuildFileWithErrors(
3912 "name: \"foo.proto\" "
3915 " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32"
3916 " type_name:\"Foo\" }"
3919 "foo.proto: Foo.foo: TYPE: Field with primitive type has type_name.\n");
3922 TEST_F(ValidationErrorTest, NonPrimitiveWithoutTypeName) {
3923 BuildFileWithErrors(
3924 "name: \"foo.proto\" "
3927 " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_MESSAGE }"
3930 "foo.proto: Foo.foo: TYPE: Field with message or enum type missing "
3934 TEST_F(ValidationErrorTest, OneofWithNoFields) {
3935 BuildFileWithErrors(
3936 "name: \"foo.proto\" "
3939 " oneof_decl { name:\"bar\" }"
3942 "foo.proto: Foo.bar: NAME: Oneof must have at least one field.\n");
3945 TEST_F(ValidationErrorTest, OneofLabelMismatch) {
3946 BuildFileWithErrors(
3947 "name: \"foo.proto\" "
3950 " field { name:\"foo\" number:1 label:LABEL_REPEATED type:TYPE_INT32 "
3952 " oneof_decl { name:\"bar\" }"
3955 "foo.proto: Foo.foo: NAME: Fields of oneofs must themselves have label "
3956 "LABEL_OPTIONAL.\n");
3959 TEST_F(ValidationErrorTest, InputTypeNotDefined) {
3960 BuildFileWithErrors(
3961 "name: \"foo.proto\" "
3962 "message_type { name: \"Foo\" } "
3964 " name: \"TestService\""
3965 " method { name: \"A\" input_type: \"Bar\" output_type: \"Foo\" }"
3968 "foo.proto: TestService.A: INPUT_TYPE: \"Bar\" is not defined.\n"
3972 TEST_F(ValidationErrorTest, InputTypeNotAMessage) {
3973 BuildFileWithErrors(
3974 "name: \"foo.proto\" "
3975 "message_type { name: \"Foo\" } "
3976 "enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } } "
3978 " name: \"TestService\""
3979 " method { name: \"A\" input_type: \"Bar\" output_type: \"Foo\" }"
3982 "foo.proto: TestService.A: INPUT_TYPE: \"Bar\" is not a message type.\n"
3986 TEST_F(ValidationErrorTest, OutputTypeNotDefined) {
3987 BuildFileWithErrors(
3988 "name: \"foo.proto\" "
3989 "message_type { name: \"Foo\" } "
3991 " name: \"TestService\""
3992 " method { name: \"A\" input_type: \"Foo\" output_type: \"Bar\" }"
3995 "foo.proto: TestService.A: OUTPUT_TYPE: \"Bar\" is not defined.\n"
3999 TEST_F(ValidationErrorTest, OutputTypeNotAMessage) {
4000 BuildFileWithErrors(
4001 "name: \"foo.proto\" "
4002 "message_type { name: \"Foo\" } "
4003 "enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } } "
4005 " name: \"TestService\""
4006 " method { name: \"A\" input_type: \"Foo\" output_type: \"Bar\" }"
4009 "foo.proto: TestService.A: OUTPUT_TYPE: \"Bar\" is not a message type.\n"
4014 TEST_F(ValidationErrorTest, IllegalPackedField) {
4015 BuildFileWithErrors(
4016 "name: \"foo.proto\" "
4019 " field { name:\"packed_string\" number:1 label:LABEL_REPEATED "
4020 " type:TYPE_STRING "
4021 " options { uninterpreted_option {"
4022 " name { name_part: \"packed\" is_extension: false }"
4023 " identifier_value: \"true\" }}}\n"
4024 " field { name:\"packed_message\" number:3 label:LABEL_REPEATED "
4025 " type_name: \"Foo\""
4026 " options { uninterpreted_option {"
4027 " name { name_part: \"packed\" is_extension: false }"
4028 " identifier_value: \"true\" }}}\n"
4029 " field { name:\"optional_int32\" number: 4 label: LABEL_OPTIONAL "
4031 " options { uninterpreted_option {"
4032 " name { name_part: \"packed\" is_extension: false }"
4033 " identifier_value: \"true\" }}}\n"
4036 "foo.proto: Foo.packed_string: TYPE: [packed = true] can only be "
4037 "specified for repeated primitive fields.\n"
4038 "foo.proto: Foo.packed_message: TYPE: [packed = true] can only be "
4039 "specified for repeated primitive fields.\n"
4040 "foo.proto: Foo.optional_int32: TYPE: [packed = true] can only be "
4041 "specified for repeated primitive fields.\n"
4045 TEST_F(ValidationErrorTest, OptionWrongType) {
4046 BuildFileWithErrors(
4047 "name: \"foo.proto\" "
4049 " name: \"TestMessage\" "
4050 " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_STRING "
4051 " options { uninterpreted_option { name { name_part: \"ctype\" "
4052 " is_extension: false }"
4053 " positive_int_value: 1 }"
4058 "foo.proto: TestMessage.foo: OPTION_VALUE: Value must be identifier for "
4059 "enum-valued option \"google.protobuf.FieldOptions.ctype\".\n");
4062 TEST_F(ValidationErrorTest, OptionExtendsAtomicType) {
4063 BuildFileWithErrors(
4064 "name: \"foo.proto\" "
4066 " name: \"TestMessage\" "
4067 " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_STRING "
4068 " options { uninterpreted_option { name { name_part: \"ctype\" "
4069 " is_extension: false }"
4070 " name { name_part: \"foo\" "
4071 " is_extension: true }"
4072 " positive_int_value: 1 }"
4077 "foo.proto: TestMessage.foo: OPTION_NAME: Option \"ctype\" is an "
4078 "atomic type, not a message.\n");
4081 TEST_F(ValidationErrorTest, DupOption) {
4082 BuildFileWithErrors(
4083 "name: \"foo.proto\" "
4085 " name: \"TestMessage\" "
4086 " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_UINT32 "
4087 " options { uninterpreted_option { name { name_part: \"ctype\" "
4088 " is_extension: false }"
4089 " identifier_value: \"CORD\" }"
4090 " uninterpreted_option { name { name_part: \"ctype\" "
4091 " is_extension: false }"
4092 " identifier_value: \"CORD\" }"
4097 "foo.proto: TestMessage.foo: OPTION_NAME: Option \"ctype\" was "
4101 TEST_F(ValidationErrorTest, InvalidOptionName) {
4102 BuildFileWithErrors(
4103 "name: \"foo.proto\" "
4105 " name: \"TestMessage\" "
4106 " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_BOOL "
4107 " options { uninterpreted_option { "
4108 " name { name_part: \"uninterpreted_option\" "
4109 " is_extension: false }"
4110 " positive_int_value: 1 "
4116 "foo.proto: TestMessage.foo: OPTION_NAME: Option must not use "
4117 "reserved name \"uninterpreted_option\".\n");
4120 TEST_F(ValidationErrorTest, RepeatedMessageOption) {
4121 BuildDescriptorMessagesInTestPool();
4123 BuildFileWithErrors(
4124 "name: \"foo.proto\" "
4125 "dependency: \"google/protobuf/descriptor.proto\" "
4126 "message_type: { name: \"Bar\" field: { "
4127 " name: \"foo\" number: 1 label: LABEL_OPTIONAL type: TYPE_INT32 } "
4129 "extension { name: \"bar\" number: 7672757 label: LABEL_REPEATED "
4130 " type: TYPE_MESSAGE type_name: \"Bar\" "
4131 " extendee: \"google.protobuf.FileOptions\" }"
4132 "options { uninterpreted_option { name { name_part: \"bar\" "
4133 " is_extension: true } "
4134 " name { name_part: \"foo\" "
4135 " is_extension: false } "
4136 " positive_int_value: 1 } }",
4138 "foo.proto: foo.proto: OPTION_NAME: Option field \"(bar)\" is a "
4139 "repeated message. Repeated message options must be initialized "
4140 "using an aggregate value.\n");
4143 TEST_F(ValidationErrorTest, ResolveUndefinedOption) {
4144 // The following should produce an eror that baz.bar is resolved but not
4148 // import google/protobuf/descriptor.proto
4149 // message Bar { optional int32 foo = 1; }
4150 // extend FileOptions { optional Bar bar = 7672757; }
4154 // option (baz.bar).foo = 1;
4156 // Although "baz.bar" is already defined, the lookup code will try
4157 // "qux.baz.bar", since it's the match from the innermost scope, which will
4158 // cause a symbol not defined error.
4159 BuildDescriptorMessagesInTestPool();
4162 "name: \"foo.proto\" "
4164 "dependency: \"google/protobuf/descriptor.proto\" "
4165 "message_type: { name: \"Bar\" field: { "
4166 " name: \"foo\" number: 1 label: LABEL_OPTIONAL type: TYPE_INT32 } "
4168 "extension { name: \"bar\" number: 7672757 label: LABEL_OPTIONAL "
4169 " type: TYPE_MESSAGE type_name: \"Bar\" "
4170 " extendee: \"google.protobuf.FileOptions\" }");
4172 BuildFileWithErrors(
4173 "name: \"qux.proto\" "
4174 "package: \"qux.baz\" "
4175 "options { uninterpreted_option { name { name_part: \"baz.bar\" "
4176 " is_extension: true } "
4177 " name { name_part: \"foo\" "
4178 " is_extension: false } "
4179 " positive_int_value: 1 } }",
4181 "qux.proto: qux.proto: OPTION_NAME: Option \"(baz.bar)\" is resolved to "
4182 "\"(qux.baz.bar)\","
4183 " which is not defined. The innermost scope is searched first in name "
4184 "resolution. Consider using a leading '.'(i.e., \"(.baz.bar)\") to start "
4185 "from the outermost scope.\n");
4188 TEST_F(ValidationErrorTest, UnknownOption) {
4189 BuildFileWithErrors(
4190 "name: \"qux.proto\" "
4191 "package: \"qux.baz\" "
4192 "options { uninterpreted_option { name { name_part: \"baaz.bar\" "
4193 " is_extension: true } "
4194 " name { name_part: \"foo\" "
4195 " is_extension: false } "
4196 " positive_int_value: 1 } }",
4198 "qux.proto: qux.proto: OPTION_NAME: Option \"(baaz.bar)\" unknown.\n");
4201 TEST_F(ValidationErrorTest, CustomOptionConflictingFieldNumber) {
4202 BuildDescriptorMessagesInTestPool();
4204 BuildFileWithErrors(
4205 "name: \"foo.proto\" "
4206 "dependency: \"google/protobuf/descriptor.proto\" "
4207 "extension { name: \"foo1\" number: 7672757 label: LABEL_OPTIONAL "
4208 " type: TYPE_INT32 extendee: \"google.protobuf.FieldOptions\" }"
4209 "extension { name: \"foo2\" number: 7672757 label: LABEL_OPTIONAL "
4210 " type: TYPE_INT32 extendee: \"google.protobuf.FieldOptions\" }",
4212 "foo.proto: foo2: NUMBER: Extension number 7672757 has already been used "
4213 "in \"google.protobuf.FieldOptions\" by extension \"foo1\".\n");
4216 TEST_F(ValidationErrorTest, Int32OptionValueOutOfPositiveRange) {
4217 BuildDescriptorMessagesInTestPool();
4219 BuildFileWithErrors(
4220 "name: \"foo.proto\" "
4221 "dependency: \"google/protobuf/descriptor.proto\" "
4222 "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
4223 " type: TYPE_INT32 extendee: \"google.protobuf.FileOptions\" }"
4224 "options { uninterpreted_option { name { name_part: \"foo\" "
4225 " is_extension: true } "
4226 " positive_int_value: 0x80000000 } "
4229 "foo.proto: foo.proto: OPTION_VALUE: Value out of range "
4230 "for int32 option \"foo\".\n");
4233 TEST_F(ValidationErrorTest, Int32OptionValueOutOfNegativeRange) {
4234 BuildDescriptorMessagesInTestPool();
4236 BuildFileWithErrors(
4237 "name: \"foo.proto\" "
4238 "dependency: \"google/protobuf/descriptor.proto\" "
4239 "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
4240 " type: TYPE_INT32 extendee: \"google.protobuf.FileOptions\" }"
4241 "options { uninterpreted_option { name { name_part: \"foo\" "
4242 " is_extension: true } "
4243 " negative_int_value: -0x80000001 } "
4246 "foo.proto: foo.proto: OPTION_VALUE: Value out of range "
4247 "for int32 option \"foo\".\n");
4250 TEST_F(ValidationErrorTest, Int32OptionValueIsNotPositiveInt) {
4251 BuildDescriptorMessagesInTestPool();
4253 BuildFileWithErrors(
4254 "name: \"foo.proto\" "
4255 "dependency: \"google/protobuf/descriptor.proto\" "
4256 "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
4257 " type: TYPE_INT32 extendee: \"google.protobuf.FileOptions\" }"
4258 "options { uninterpreted_option { name { name_part: \"foo\" "
4259 " is_extension: true } "
4260 " string_value: \"5\" } }",
4262 "foo.proto: foo.proto: OPTION_VALUE: Value must be integer "
4263 "for int32 option \"foo\".\n");
4266 TEST_F(ValidationErrorTest, Int64OptionValueOutOfRange) {
4267 BuildDescriptorMessagesInTestPool();
4269 BuildFileWithErrors(
4270 "name: \"foo.proto\" "
4271 "dependency: \"google/protobuf/descriptor.proto\" "
4272 "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
4273 " type: TYPE_INT64 extendee: \"google.protobuf.FileOptions\" }"
4274 "options { uninterpreted_option { name { name_part: \"foo\" "
4275 " is_extension: true } "
4276 " positive_int_value: 0x8000000000000000 } "
4279 "foo.proto: foo.proto: OPTION_VALUE: Value out of range "
4280 "for int64 option \"foo\".\n");
4283 TEST_F(ValidationErrorTest, Int64OptionValueIsNotPositiveInt) {
4284 BuildDescriptorMessagesInTestPool();
4286 BuildFileWithErrors(
4287 "name: \"foo.proto\" "
4288 "dependency: \"google/protobuf/descriptor.proto\" "
4289 "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
4290 " type: TYPE_INT64 extendee: \"google.protobuf.FileOptions\" }"
4291 "options { uninterpreted_option { name { name_part: \"foo\" "
4292 " is_extension: true } "
4293 " identifier_value: \"5\" } }",
4295 "foo.proto: foo.proto: OPTION_VALUE: Value must be integer "
4296 "for int64 option \"foo\".\n");
4299 TEST_F(ValidationErrorTest, UInt32OptionValueOutOfRange) {
4300 BuildDescriptorMessagesInTestPool();
4302 BuildFileWithErrors(
4303 "name: \"foo.proto\" "
4304 "dependency: \"google/protobuf/descriptor.proto\" "
4305 "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
4306 " type: TYPE_UINT32 extendee: \"google.protobuf.FileOptions\" }"
4307 "options { uninterpreted_option { name { name_part: \"foo\" "
4308 " is_extension: true } "
4309 " positive_int_value: 0x100000000 } }",
4311 "foo.proto: foo.proto: OPTION_VALUE: Value out of range "
4312 "for uint32 option \"foo\".\n");
4315 TEST_F(ValidationErrorTest, UInt32OptionValueIsNotPositiveInt) {
4316 BuildDescriptorMessagesInTestPool();
4318 BuildFileWithErrors(
4319 "name: \"foo.proto\" "
4320 "dependency: \"google/protobuf/descriptor.proto\" "
4321 "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
4322 " type: TYPE_UINT32 extendee: \"google.protobuf.FileOptions\" }"
4323 "options { uninterpreted_option { name { name_part: \"foo\" "
4324 " is_extension: true } "
4325 " double_value: -5.6 } }",
4327 "foo.proto: foo.proto: OPTION_VALUE: Value must be non-negative integer "
4328 "for uint32 option \"foo\".\n");
4331 TEST_F(ValidationErrorTest, UInt64OptionValueIsNotPositiveInt) {
4332 BuildDescriptorMessagesInTestPool();
4334 BuildFileWithErrors(
4335 "name: \"foo.proto\" "
4336 "dependency: \"google/protobuf/descriptor.proto\" "
4337 "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
4338 " type: TYPE_UINT64 extendee: \"google.protobuf.FileOptions\" }"
4339 "options { uninterpreted_option { name { name_part: \"foo\" "
4340 " is_extension: true } "
4341 " negative_int_value: -5 } }",
4343 "foo.proto: foo.proto: OPTION_VALUE: Value must be non-negative integer "
4344 "for uint64 option \"foo\".\n");
4347 TEST_F(ValidationErrorTest, FloatOptionValueIsNotNumber) {
4348 BuildDescriptorMessagesInTestPool();
4350 BuildFileWithErrors(
4351 "name: \"foo.proto\" "
4352 "dependency: \"google/protobuf/descriptor.proto\" "
4353 "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
4354 " type: TYPE_FLOAT extendee: \"google.protobuf.FileOptions\" }"
4355 "options { uninterpreted_option { name { name_part: \"foo\" "
4356 " is_extension: true } "
4357 " string_value: \"bar\" } }",
4359 "foo.proto: foo.proto: OPTION_VALUE: Value must be number "
4360 "for float option \"foo\".\n");
4363 TEST_F(ValidationErrorTest, DoubleOptionValueIsNotNumber) {
4364 BuildDescriptorMessagesInTestPool();
4366 BuildFileWithErrors(
4367 "name: \"foo.proto\" "
4368 "dependency: \"google/protobuf/descriptor.proto\" "
4369 "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
4370 " type: TYPE_DOUBLE extendee: \"google.protobuf.FileOptions\" }"
4371 "options { uninterpreted_option { name { name_part: \"foo\" "
4372 " is_extension: true } "
4373 " string_value: \"bar\" } }",
4375 "foo.proto: foo.proto: OPTION_VALUE: Value must be number "
4376 "for double option \"foo\".\n");
4379 TEST_F(ValidationErrorTest, BoolOptionValueIsNotTrueOrFalse) {
4380 BuildDescriptorMessagesInTestPool();
4382 BuildFileWithErrors(
4383 "name: \"foo.proto\" "
4384 "dependency: \"google/protobuf/descriptor.proto\" "
4385 "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
4386 " type: TYPE_BOOL extendee: \"google.protobuf.FileOptions\" }"
4387 "options { uninterpreted_option { name { name_part: \"foo\" "
4388 " is_extension: true } "
4389 " identifier_value: \"bar\" } }",
4391 "foo.proto: foo.proto: OPTION_VALUE: Value must be \"true\" or \"false\" "
4392 "for boolean option \"foo\".\n");
4395 TEST_F(ValidationErrorTest, EnumOptionValueIsNotIdentifier) {
4396 BuildDescriptorMessagesInTestPool();
4398 BuildFileWithErrors(
4399 "name: \"foo.proto\" "
4400 "dependency: \"google/protobuf/descriptor.proto\" "
4401 "enum_type { name: \"FooEnum\" value { name: \"BAR\" number: 1 } "
4402 " value { name: \"BAZ\" number: 2 } }"
4403 "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
4404 " type: TYPE_ENUM type_name: \"FooEnum\" "
4405 " extendee: \"google.protobuf.FileOptions\" }"
4406 "options { uninterpreted_option { name { name_part: \"foo\" "
4407 " is_extension: true } "
4408 " string_value: \"QUUX\" } }",
4410 "foo.proto: foo.proto: OPTION_VALUE: Value must be identifier for "
4411 "enum-valued option \"foo\".\n");
4414 TEST_F(ValidationErrorTest, EnumOptionValueIsNotEnumValueName) {
4415 BuildDescriptorMessagesInTestPool();
4417 BuildFileWithErrors(
4418 "name: \"foo.proto\" "
4419 "dependency: \"google/protobuf/descriptor.proto\" "
4420 "enum_type { name: \"FooEnum\" value { name: \"BAR\" number: 1 } "
4421 " value { name: \"BAZ\" number: 2 } }"
4422 "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
4423 " type: TYPE_ENUM type_name: \"FooEnum\" "
4424 " extendee: \"google.protobuf.FileOptions\" }"
4425 "options { uninterpreted_option { name { name_part: \"foo\" "
4426 " is_extension: true } "
4427 " identifier_value: \"QUUX\" } }",
4429 "foo.proto: foo.proto: OPTION_VALUE: Enum type \"FooEnum\" has no value "
4430 "named \"QUUX\" for option \"foo\".\n");
4433 TEST_F(ValidationErrorTest, EnumOptionValueIsSiblingEnumValueName) {
4434 BuildDescriptorMessagesInTestPool();
4436 BuildFileWithErrors(
4437 "name: \"foo.proto\" "
4438 "dependency: \"google/protobuf/descriptor.proto\" "
4439 "enum_type { name: \"FooEnum1\" value { name: \"BAR\" number: 1 } "
4440 " value { name: \"BAZ\" number: 2 } }"
4441 "enum_type { name: \"FooEnum2\" value { name: \"QUX\" number: 1 } "
4442 " value { name: \"QUUX\" number: 2 } }"
4443 "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
4444 " type: TYPE_ENUM type_name: \"FooEnum1\" "
4445 " extendee: \"google.protobuf.FileOptions\" }"
4446 "options { uninterpreted_option { name { name_part: \"foo\" "
4447 " is_extension: true } "
4448 " identifier_value: \"QUUX\" } }",
4450 "foo.proto: foo.proto: OPTION_VALUE: Enum type \"FooEnum1\" has no value "
4451 "named \"QUUX\" for option \"foo\". This appears to be a value from a "
4455 TEST_F(ValidationErrorTest, StringOptionValueIsNotString) {
4456 BuildDescriptorMessagesInTestPool();
4458 BuildFileWithErrors(
4459 "name: \"foo.proto\" "
4460 "dependency: \"google/protobuf/descriptor.proto\" "
4461 "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
4462 " type: TYPE_STRING extendee: \"google.protobuf.FileOptions\" }"
4463 "options { uninterpreted_option { name { name_part: \"foo\" "
4464 " is_extension: true } "
4465 " identifier_value: \"QUUX\" } }",
4467 "foo.proto: foo.proto: OPTION_VALUE: Value must be quoted string for "
4468 "string option \"foo\".\n");
4471 TEST_F(ValidationErrorTest, DuplicateExtensionFieldNumber) {
4472 BuildDescriptorMessagesInTestPool();
4475 "name: \"foo.proto\" "
4476 "dependency: \"google/protobuf/descriptor.proto\" "
4477 "extension { name: \"option1\" number: 1000 label: LABEL_OPTIONAL "
4478 " type: TYPE_INT32 extendee: \"google.protobuf.FileOptions\" }");
4480 BuildFileWithWarnings(
4481 "name: \"bar.proto\" "
4482 "dependency: \"google/protobuf/descriptor.proto\" "
4483 "extension { name: \"option2\" number: 1000 label: LABEL_OPTIONAL "
4484 " type: TYPE_INT32 extendee: \"google.protobuf.FileOptions\" }",
4485 "bar.proto: option2: NUMBER: Extension number 1000 has already been used "
4486 "in \"google.protobuf.FileOptions\" by extension \"option1\" defined in "
4490 // Helper function for tests that check for aggregate value parsing
4491 // errors. The "value" argument is embedded inside the
4492 // "uninterpreted_option" portion of the result.
4493 static string EmbedAggregateValue(const char* value) {
4494 return strings::Substitute(
4495 "name: \"foo.proto\" "
4496 "dependency: \"google/protobuf/descriptor.proto\" "
4497 "message_type { name: \"Foo\" } "
4498 "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
4499 " type: TYPE_MESSAGE type_name: \"Foo\" "
4500 " extendee: \"google.protobuf.FileOptions\" }"
4501 "options { uninterpreted_option { name { name_part: \"foo\" "
4502 " is_extension: true } "
4507 TEST_F(ValidationErrorTest, AggregateValueNotFound) {
4508 BuildDescriptorMessagesInTestPool();
4510 BuildFileWithErrors(
4511 EmbedAggregateValue("string_value: \"\""),
4512 "foo.proto: foo.proto: OPTION_VALUE: Option \"foo\" is a message. "
4513 "To set the entire message, use syntax like "
4514 "\"foo = { <proto text format> }\". To set fields within it, use "
4515 "syntax like \"foo.foo = value\".\n");
4518 TEST_F(ValidationErrorTest, AggregateValueParseError) {
4519 BuildDescriptorMessagesInTestPool();
4521 BuildFileWithErrors(
4522 EmbedAggregateValue("aggregate_value: \"1+2\""),
4523 "foo.proto: foo.proto: OPTION_VALUE: Error while parsing option "
4524 "value for \"foo\": Expected identifier.\n");
4527 TEST_F(ValidationErrorTest, AggregateValueUnknownFields) {
4528 BuildDescriptorMessagesInTestPool();
4530 BuildFileWithErrors(
4531 EmbedAggregateValue("aggregate_value: \"x:100\""),
4532 "foo.proto: foo.proto: OPTION_VALUE: Error while parsing option "
4533 "value for \"foo\": Message type \"Foo\" has no field named \"x\".\n");
4536 TEST_F(ValidationErrorTest, NotLiteImportsLite) {
4538 "name: \"bar.proto\" "
4539 "options { optimize_for: LITE_RUNTIME } ");
4541 BuildFileWithErrors(
4542 "name: \"foo.proto\" "
4543 "dependency: \"bar.proto\" ",
4545 "foo.proto: foo.proto: OTHER: Files that do not use optimize_for = "
4546 "LITE_RUNTIME cannot import files which do use this option. This file "
4547 "is not lite, but it imports \"bar.proto\" which is.\n");
4550 TEST_F(ValidationErrorTest, LiteExtendsNotLite) {
4552 "name: \"bar.proto\" "
4555 " extension_range { start: 1 end: 1000 }"
4558 BuildFileWithErrors(
4559 "name: \"foo.proto\" "
4560 "dependency: \"bar.proto\" "
4561 "options { optimize_for: LITE_RUNTIME } "
4562 "extension { name: \"ext\" number: 123 label: LABEL_OPTIONAL "
4563 " type: TYPE_INT32 extendee: \"Bar\" }",
4565 "foo.proto: ext: EXTENDEE: Extensions to non-lite types can only be "
4566 "declared in non-lite files. Note that you cannot extend a non-lite "
4567 "type to contain a lite type, but the reverse is allowed.\n");
4570 TEST_F(ValidationErrorTest, NoLiteServices) {
4571 BuildFileWithErrors(
4572 "name: \"foo.proto\" "
4574 " optimize_for: LITE_RUNTIME"
4575 " cc_generic_services: true"
4576 " java_generic_services: true"
4578 "service { name: \"Foo\" }",
4580 "foo.proto: Foo: NAME: Files with optimize_for = LITE_RUNTIME cannot "
4581 "define services unless you set both options cc_generic_services and "
4582 "java_generic_sevices to false.\n");
4585 "name: \"bar.proto\" "
4587 " optimize_for: LITE_RUNTIME"
4588 " cc_generic_services: false"
4589 " java_generic_services: false"
4591 "service { name: \"Bar\" }");
4594 TEST_F(ValidationErrorTest, RollbackAfterError) {
4595 // Build a file which contains every kind of construct but references an
4596 // undefined type. All these constructs will be added to the symbol table
4597 // before the undefined type error is noticed. The DescriptorPool will then
4598 // have to roll everything back.
4599 BuildFileWithErrors(
4600 "name: \"foo.proto\" "
4602 " name: \"TestMessage\""
4603 " field { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:1 }"
4606 " name: \"TestEnum\""
4607 " value { name:\"BAR\" number:1 }"
4610 " name: \"TestService\""
4613 " input_type: \"NoSuchType\"" // error
4614 " output_type: \"TestMessage\""
4618 "foo.proto: TestService.Baz: INPUT_TYPE: \"NoSuchType\" is not defined.\n"
4621 // Make sure that if we build the same file again with the error fixed,
4622 // it works. If the above rollback was incomplete, then some symbols will
4623 // be left defined, and this second attempt will fail since it tries to
4624 // re-define the same symbols.
4626 "name: \"foo.proto\" "
4628 " name: \"TestMessage\""
4629 " field { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:1 }"
4632 " name: \"TestEnum\""
4633 " value { name:\"BAR\" number:1 }"
4636 " name: \"TestService\""
4637 " method { name:\"Baz\""
4638 " input_type:\"TestMessage\""
4639 " output_type:\"TestMessage\" }"
4643 TEST_F(ValidationErrorTest, ErrorsReportedToLogError) {
4644 // Test that errors are reported to GOOGLE_LOG(ERROR) if no error collector is
4647 FileDescriptorProto file_proto;
4648 ASSERT_TRUE(TextFormat::ParseFromString(
4649 "name: \"foo.proto\" "
4650 "message_type { name: \"Foo\" } "
4651 "message_type { name: \"Foo\" } ",
4654 vector<string> errors;
4657 ScopedMemoryLog log;
4658 EXPECT_TRUE(pool_.BuildFile(file_proto) == NULL);
4659 errors = log.GetMessages(ERROR);
4662 ASSERT_EQ(2, errors.size());
4664 EXPECT_EQ("Invalid proto descriptor for file \"foo.proto\":", errors[0]);
4665 EXPECT_EQ(" Foo: \"Foo\" is already defined.", errors[1]);
4668 TEST_F(ValidationErrorTest, DisallowEnumAlias) {
4669 BuildFileWithErrors(
4670 "name: \"foo.proto\" "
4673 " value { name:\"ENUM_A\" number:0 }"
4674 " value { name:\"ENUM_B\" number:0 }"
4676 "foo.proto: Bar: NUMBER: "
4677 "\"ENUM_B\" uses the same enum value as \"ENUM_A\". "
4678 "If this is intended, set 'option allow_alias = true;' to the enum "
4682 TEST_F(ValidationErrorTest, AllowEnumAlias) {
4684 "name: \"foo.proto\" "
4687 " value { name:\"ENUM_A\" number:0 }"
4688 " value { name:\"ENUM_B\" number:0 }"
4689 " options { allow_alias: true }"
4693 TEST_F(ValidationErrorTest, UnusedImportWarning) {
4695 pool_.AddUnusedImportTrackFile("bar.proto");
4697 "name: \"bar.proto\" "
4698 "message_type { name: \"Bar\" }");
4700 pool_.AddUnusedImportTrackFile("base.proto");
4702 "name: \"base.proto\" "
4703 "message_type { name: \"Base\" }");
4705 pool_.AddUnusedImportTrackFile("baz.proto");
4707 "name: \"baz.proto\" "
4708 "message_type { name: \"Baz\" }");
4710 pool_.AddUnusedImportTrackFile("public.proto");
4712 "name: \"public.proto\" "
4713 "dependency: \"bar.proto\""
4714 "public_dependency: 0");
4717 // import "base.proto" // No warning: Base message is used.
4718 // import "bar.proto" // Will log a warning.
4719 // import public "baz.proto" // No warning: Do not track import public.
4720 // import "public.proto" // No warning: public.proto has import public.
4721 // message Forward {
4722 // optional Base base = 1;
4725 pool_.AddUnusedImportTrackFile("forward.proto");
4727 "name: \"forward.proto\""
4728 "dependency: \"base.proto\""
4729 "dependency: \"bar.proto\""
4730 "dependency: \"baz.proto\""
4731 "dependency: \"public.proto\""
4732 "public_dependency: 2 "
4734 " name: \"Forward\""
4735 " field { name:\"base\" number:1 label:LABEL_OPTIONAL type_name:\"Base\" }"
4740 // ===================================================================
4741 // DescriptorDatabase
4743 static void AddToDatabase(SimpleDescriptorDatabase* database,
4744 const char* file_text) {
4745 FileDescriptorProto file_proto;
4746 EXPECT_TRUE(TextFormat::ParseFromString(file_text, &file_proto));
4747 database->Add(file_proto);
4750 class DatabaseBackedPoolTest : public testing::Test {
4752 DatabaseBackedPoolTest() {}
4754 SimpleDescriptorDatabase database_;
4756 virtual void SetUp() {
4757 AddToDatabase(&database_,
4758 "name: 'foo.proto' "
4759 "message_type { name:'Foo' extension_range { start: 1 end: 100 } } "
4760 "enum_type { name:'TestEnum' value { name:'DUMMY' number:0 } } "
4761 "service { name:'TestService' } ");
4762 AddToDatabase(&database_,
4763 "name: 'bar.proto' "
4764 "dependency: 'foo.proto' "
4765 "message_type { name:'Bar' } "
4766 "extension { name:'foo_ext' extendee: '.Foo' number:5 "
4767 " label:LABEL_OPTIONAL type:TYPE_INT32 } ");
4768 // Baz has an undeclared dependency on Foo.
4769 AddToDatabase(&database_,
4770 "name: 'baz.proto' "
4773 " field { name:'foo' number:1 label:LABEL_OPTIONAL type_name:'Foo' } "
4777 // We can't inject a file containing errors into a DescriptorPool, so we
4778 // need an actual mock DescriptorDatabase to test errors.
4779 class ErrorDescriptorDatabase : public DescriptorDatabase {
4781 ErrorDescriptorDatabase() {}
4782 ~ErrorDescriptorDatabase() {}
4784 // implements DescriptorDatabase ---------------------------------
4785 bool FindFileByName(const string& filename,
4786 FileDescriptorProto* output) {
4787 // error.proto and error2.proto cyclically import each other.
4788 if (filename == "error.proto") {
4790 output->set_name("error.proto");
4791 output->add_dependency("error2.proto");
4793 } else if (filename == "error2.proto") {
4795 output->set_name("error2.proto");
4796 output->add_dependency("error.proto");
4802 bool FindFileContainingSymbol(const string& symbol_name,
4803 FileDescriptorProto* output) {
4806 bool FindFileContainingExtension(const string& containing_type,
4808 FileDescriptorProto* output) {
4813 // A DescriptorDatabase that counts how many times each method has been
4814 // called and forwards to some other DescriptorDatabase.
4815 class CallCountingDatabase : public DescriptorDatabase {
4817 CallCountingDatabase(DescriptorDatabase* wrapped_db)
4818 : wrapped_db_(wrapped_db) {
4821 ~CallCountingDatabase() {}
4823 DescriptorDatabase* wrapped_db_;
4831 // implements DescriptorDatabase ---------------------------------
4832 bool FindFileByName(const string& filename,
4833 FileDescriptorProto* output) {
4835 return wrapped_db_->FindFileByName(filename, output);
4837 bool FindFileContainingSymbol(const string& symbol_name,
4838 FileDescriptorProto* output) {
4840 return wrapped_db_->FindFileContainingSymbol(symbol_name, output);
4842 bool FindFileContainingExtension(const string& containing_type,
4844 FileDescriptorProto* output) {
4846 return wrapped_db_->FindFileContainingExtension(
4847 containing_type, field_number, output);
4851 // A DescriptorDatabase which falsely always returns foo.proto when searching
4852 // for any symbol or extension number. This shouldn't cause the
4853 // DescriptorPool to reload foo.proto if it is already loaded.
4854 class FalsePositiveDatabase : public DescriptorDatabase {
4856 FalsePositiveDatabase(DescriptorDatabase* wrapped_db)
4857 : wrapped_db_(wrapped_db) {}
4858 ~FalsePositiveDatabase() {}
4860 DescriptorDatabase* wrapped_db_;
4862 // implements DescriptorDatabase ---------------------------------
4863 bool FindFileByName(const string& filename,
4864 FileDescriptorProto* output) {
4865 return wrapped_db_->FindFileByName(filename, output);
4867 bool FindFileContainingSymbol(const string& symbol_name,
4868 FileDescriptorProto* output) {
4869 return FindFileByName("foo.proto", output);
4871 bool FindFileContainingExtension(const string& containing_type,
4873 FileDescriptorProto* output) {
4874 return FindFileByName("foo.proto", output);
4879 TEST_F(DatabaseBackedPoolTest, FindFileByName) {
4880 DescriptorPool pool(&database_);
4882 const FileDescriptor* foo = pool.FindFileByName("foo.proto");
4883 ASSERT_TRUE(foo != NULL);
4884 EXPECT_EQ("foo.proto", foo->name());
4885 ASSERT_EQ(1, foo->message_type_count());
4886 EXPECT_EQ("Foo", foo->message_type(0)->name());
4888 EXPECT_EQ(foo, pool.FindFileByName("foo.proto"));
4890 EXPECT_TRUE(pool.FindFileByName("no_such_file.proto") == NULL);
4893 TEST_F(DatabaseBackedPoolTest, FindDependencyBeforeDependent) {
4894 DescriptorPool pool(&database_);
4896 const FileDescriptor* foo = pool.FindFileByName("foo.proto");
4897 ASSERT_TRUE(foo != NULL);
4898 EXPECT_EQ("foo.proto", foo->name());
4899 ASSERT_EQ(1, foo->message_type_count());
4900 EXPECT_EQ("Foo", foo->message_type(0)->name());
4902 const FileDescriptor* bar = pool.FindFileByName("bar.proto");
4903 ASSERT_TRUE(bar != NULL);
4904 EXPECT_EQ("bar.proto", bar->name());
4905 ASSERT_EQ(1, bar->message_type_count());
4906 EXPECT_EQ("Bar", bar->message_type(0)->name());
4908 ASSERT_EQ(1, bar->dependency_count());
4909 EXPECT_EQ(foo, bar->dependency(0));
4912 TEST_F(DatabaseBackedPoolTest, FindDependentBeforeDependency) {
4913 DescriptorPool pool(&database_);
4915 const FileDescriptor* bar = pool.FindFileByName("bar.proto");
4916 ASSERT_TRUE(bar != NULL);
4917 EXPECT_EQ("bar.proto", bar->name());
4918 ASSERT_EQ(1, bar->message_type_count());
4919 ASSERT_EQ("Bar", bar->message_type(0)->name());
4921 const FileDescriptor* foo = pool.FindFileByName("foo.proto");
4922 ASSERT_TRUE(foo != NULL);
4923 EXPECT_EQ("foo.proto", foo->name());
4924 ASSERT_EQ(1, foo->message_type_count());
4925 ASSERT_EQ("Foo", foo->message_type(0)->name());
4927 ASSERT_EQ(1, bar->dependency_count());
4928 EXPECT_EQ(foo, bar->dependency(0));
4931 TEST_F(DatabaseBackedPoolTest, FindFileContainingSymbol) {
4932 DescriptorPool pool(&database_);
4934 const FileDescriptor* file = pool.FindFileContainingSymbol("Foo");
4935 ASSERT_TRUE(file != NULL);
4936 EXPECT_EQ("foo.proto", file->name());
4937 EXPECT_EQ(file, pool.FindFileByName("foo.proto"));
4939 EXPECT_TRUE(pool.FindFileContainingSymbol("NoSuchSymbol") == NULL);
4942 TEST_F(DatabaseBackedPoolTest, FindMessageTypeByName) {
4943 DescriptorPool pool(&database_);
4945 const Descriptor* type = pool.FindMessageTypeByName("Foo");
4946 ASSERT_TRUE(type != NULL);
4947 EXPECT_EQ("Foo", type->name());
4948 EXPECT_EQ(type->file(), pool.FindFileByName("foo.proto"));
4950 EXPECT_TRUE(pool.FindMessageTypeByName("NoSuchType") == NULL);
4953 TEST_F(DatabaseBackedPoolTest, FindExtensionByNumber) {
4954 DescriptorPool pool(&database_);
4956 const Descriptor* foo = pool.FindMessageTypeByName("Foo");
4957 ASSERT_TRUE(foo != NULL);
4959 const FieldDescriptor* extension = pool.FindExtensionByNumber(foo, 5);
4960 ASSERT_TRUE(extension != NULL);
4961 EXPECT_EQ("foo_ext", extension->name());
4962 EXPECT_EQ(extension->file(), pool.FindFileByName("bar.proto"));
4964 EXPECT_TRUE(pool.FindExtensionByNumber(foo, 12) == NULL);
4967 TEST_F(DatabaseBackedPoolTest, FindAllExtensions) {
4968 DescriptorPool pool(&database_);
4970 const Descriptor* foo = pool.FindMessageTypeByName("Foo");
4972 for (int i = 0; i < 2; ++i) {
4973 // Repeat the lookup twice, to check that we get consistent
4974 // results despite the fallback database lookup mutating the pool.
4975 vector<const FieldDescriptor*> extensions;
4976 pool.FindAllExtensions(foo, &extensions);
4977 ASSERT_EQ(1, extensions.size());
4978 EXPECT_EQ(5, extensions[0]->number());
4982 TEST_F(DatabaseBackedPoolTest, ErrorWithoutErrorCollector) {
4983 ErrorDescriptorDatabase error_database;
4984 DescriptorPool pool(&error_database);
4986 vector<string> errors;
4989 ScopedMemoryLog log;
4990 EXPECT_TRUE(pool.FindFileByName("error.proto") == NULL);
4991 errors = log.GetMessages(ERROR);
4994 EXPECT_FALSE(errors.empty());
4997 TEST_F(DatabaseBackedPoolTest, ErrorWithErrorCollector) {
4998 ErrorDescriptorDatabase error_database;
4999 MockErrorCollector error_collector;
5000 DescriptorPool pool(&error_database, &error_collector);
5002 EXPECT_TRUE(pool.FindFileByName("error.proto") == NULL);
5004 "error.proto: error.proto: OTHER: File recursively imports itself: "
5005 "error.proto -> error2.proto -> error.proto\n"
5006 "error2.proto: error2.proto: OTHER: Import \"error.proto\" was not "
5007 "found or had errors.\n"
5008 "error.proto: error.proto: OTHER: Import \"error2.proto\" was not "
5009 "found or had errors.\n",
5010 error_collector.text_);
5013 TEST_F(DatabaseBackedPoolTest, UndeclaredDependencyOnUnbuiltType) {
5014 // Check that we find and report undeclared dependencies on types that exist
5015 // in the descriptor database but that have not not been built yet.
5016 MockErrorCollector error_collector;
5017 DescriptorPool pool(&database_, &error_collector);
5018 EXPECT_TRUE(pool.FindMessageTypeByName("Baz") == NULL);
5020 "baz.proto: Baz.foo: TYPE: \"Foo\" seems to be defined in \"foo.proto\", "
5021 "which is not imported by \"baz.proto\". To use it here, please add "
5022 "the necessary import.\n",
5023 error_collector.text_);
5026 TEST_F(DatabaseBackedPoolTest, RollbackAfterError) {
5027 // Make sure that all traces of bad types are removed from the pool. This used
5028 // to be b/4529436, due to the fact that a symbol resolution failure could
5029 // potentially cause another file to be recursively built, which would trigger
5030 // a checkpoint _past_ possibly invalid symbols.
5031 // Baz is defined in the database, but the file is invalid because it is
5032 // missing a necessary import.
5033 DescriptorPool pool(&database_);
5034 EXPECT_TRUE(pool.FindMessageTypeByName("Baz") == NULL);
5035 // Make sure that searching again for the file or the type fails.
5036 EXPECT_TRUE(pool.FindFileByName("baz.proto") == NULL);
5037 EXPECT_TRUE(pool.FindMessageTypeByName("Baz") == NULL);
5040 TEST_F(DatabaseBackedPoolTest, UnittestProto) {
5041 // Try to load all of unittest.proto from a DescriptorDatabase. This should
5042 // thoroughly test all paths through DescriptorBuilder to insure that there
5043 // are no deadlocking problems when pool_->mutex_ is non-NULL.
5044 const FileDescriptor* original_file =
5045 protobuf_unittest::TestAllTypes::descriptor()->file();
5047 DescriptorPoolDatabase database(*DescriptorPool::generated_pool());
5048 DescriptorPool pool(&database);
5049 const FileDescriptor* file_from_database =
5050 pool.FindFileByName(original_file->name());
5052 ASSERT_TRUE(file_from_database != NULL);
5054 FileDescriptorProto original_file_proto;
5055 original_file->CopyTo(&original_file_proto);
5057 FileDescriptorProto file_from_database_proto;
5058 file_from_database->CopyTo(&file_from_database_proto);
5060 EXPECT_EQ(original_file_proto.DebugString(),
5061 file_from_database_proto.DebugString());
5063 // Also verify that CopyTo() did not omit any information.
5064 EXPECT_EQ(original_file->DebugString(),
5065 file_from_database->DebugString());
5068 TEST_F(DatabaseBackedPoolTest, DoesntRetryDbUnnecessarily) {
5069 // Searching for a child of an existing descriptor should never fall back
5070 // to the DescriptorDatabase even if it isn't found, because we know all
5071 // children are already loaded.
5072 CallCountingDatabase call_counter(&database_);
5073 DescriptorPool pool(&call_counter);
5075 const FileDescriptor* file = pool.FindFileByName("foo.proto");
5076 ASSERT_TRUE(file != NULL);
5077 const Descriptor* foo = pool.FindMessageTypeByName("Foo");
5078 ASSERT_TRUE(foo != NULL);
5079 const EnumDescriptor* test_enum = pool.FindEnumTypeByName("TestEnum");
5080 ASSERT_TRUE(test_enum != NULL);
5081 const ServiceDescriptor* test_service = pool.FindServiceByName("TestService");
5082 ASSERT_TRUE(test_service != NULL);
5084 EXPECT_NE(0, call_counter.call_count_);
5085 call_counter.Clear();
5087 EXPECT_TRUE(foo->FindFieldByName("no_such_field") == NULL);
5088 EXPECT_TRUE(foo->FindExtensionByName("no_such_extension") == NULL);
5089 EXPECT_TRUE(foo->FindNestedTypeByName("NoSuchMessageType") == NULL);
5090 EXPECT_TRUE(foo->FindEnumTypeByName("NoSuchEnumType") == NULL);
5091 EXPECT_TRUE(foo->FindEnumValueByName("NO_SUCH_VALUE") == NULL);
5092 EXPECT_TRUE(test_enum->FindValueByName("NO_SUCH_VALUE") == NULL);
5093 EXPECT_TRUE(test_service->FindMethodByName("NoSuchMethod") == NULL);
5095 EXPECT_TRUE(file->FindMessageTypeByName("NoSuchMessageType") == NULL);
5096 EXPECT_TRUE(file->FindEnumTypeByName("NoSuchEnumType") == NULL);
5097 EXPECT_TRUE(file->FindEnumValueByName("NO_SUCH_VALUE") == NULL);
5098 EXPECT_TRUE(file->FindServiceByName("NO_SUCH_VALUE") == NULL);
5099 EXPECT_TRUE(file->FindExtensionByName("no_such_extension") == NULL);
5101 EXPECT_TRUE(pool.FindFileContainingSymbol("Foo.no.such.field") == NULL);
5102 EXPECT_TRUE(pool.FindFileContainingSymbol("Foo.no_such_field") == NULL);
5103 EXPECT_TRUE(pool.FindMessageTypeByName("Foo.NoSuchMessageType") == NULL);
5104 EXPECT_TRUE(pool.FindFieldByName("Foo.no_such_field") == NULL);
5105 EXPECT_TRUE(pool.FindExtensionByName("Foo.no_such_extension") == NULL);
5106 EXPECT_TRUE(pool.FindEnumTypeByName("Foo.NoSuchEnumType") == NULL);
5107 EXPECT_TRUE(pool.FindEnumValueByName("Foo.NO_SUCH_VALUE") == NULL);
5108 EXPECT_TRUE(pool.FindMethodByName("TestService.NoSuchMethod") == NULL);
5110 EXPECT_EQ(0, call_counter.call_count_);
5113 TEST_F(DatabaseBackedPoolTest, DoesntReloadFilesUncesessarily) {
5114 // If FindFileContainingSymbol() or FindFileContainingExtension() return a
5115 // file that is already in the DescriptorPool, it should not attempt to
5117 FalsePositiveDatabase false_positive_database(&database_);
5118 MockErrorCollector error_collector;
5119 DescriptorPool pool(&false_positive_database, &error_collector);
5121 // First make sure foo.proto is loaded.
5122 const Descriptor* foo = pool.FindMessageTypeByName("Foo");
5123 ASSERT_TRUE(foo != NULL);
5125 // Try inducing false positives.
5126 EXPECT_TRUE(pool.FindMessageTypeByName("NoSuchSymbol") == NULL);
5127 EXPECT_TRUE(pool.FindExtensionByNumber(foo, 22) == NULL);
5129 // No errors should have been reported. (If foo.proto was incorrectly
5130 // loaded multiple times, errors would have been reported.)
5131 EXPECT_EQ("", error_collector.text_);
5134 // DescriptorDatabase that attempts to induce exponentially-bad performance
5135 // in DescriptorPool. For every positive N, the database contains a file
5136 // fileN.proto, which defines a message MessageN, which contains fields of
5137 // type MessageK for all K in [0,N). Message0 is not defined anywhere
5138 // (file0.proto exists, but is empty), so every other file and message type
5139 // will fail to build.
5141 // If the DescriptorPool is not careful to memoize errors, an attempt to
5142 // build a descriptor for MessageN can require O(2^N) time.
5143 class ExponentialErrorDatabase : public DescriptorDatabase {
5145 ExponentialErrorDatabase() {}
5146 ~ExponentialErrorDatabase() {}
5148 // implements DescriptorDatabase ---------------------------------
5149 bool FindFileByName(const string& filename,
5150 FileDescriptorProto* output) {
5152 FullMatch(filename, "file", ".proto", &file_num);
5153 if (file_num > -1) {
5154 return PopulateFile(file_num, output);
5159 bool FindFileContainingSymbol(const string& symbol_name,
5160 FileDescriptorProto* output) {
5162 FullMatch(symbol_name, "Message", "", &file_num);
5164 return PopulateFile(file_num, output);
5169 bool FindFileContainingExtension(const string& containing_type,
5171 FileDescriptorProto* output) {
5176 void FullMatch(const string& name,
5177 const string& begin_with,
5178 const string& end_with,
5180 int begin_size = begin_with.size();
5181 int end_size = end_with.size();
5182 if (name.substr(0, begin_size) != begin_with ||
5183 name.substr(name.size()- end_size, end_size) != end_with) {
5186 safe_strto32(name.substr(begin_size, name.size() - end_size - begin_size),
5190 bool PopulateFile(int file_num, FileDescriptorProto* output) {
5191 using strings::Substitute;
5192 GOOGLE_CHECK_GE(file_num, 0);
5194 output->set_name(Substitute("file$0.proto", file_num));
5195 // file0.proto doesn't define Message0
5197 DescriptorProto* message = output->add_message_type();
5198 message->set_name(Substitute("Message$0", file_num));
5199 for (int i = 0; i < file_num; ++i) {
5200 output->add_dependency(Substitute("file$0.proto", i));
5201 FieldDescriptorProto* field = message->add_field();
5202 field->set_name(Substitute("field$0", i));
5203 field->set_number(i);
5204 field->set_label(FieldDescriptorProto::LABEL_OPTIONAL);
5205 field->set_type(FieldDescriptorProto::TYPE_MESSAGE);
5206 field->set_type_name(Substitute("Message$0", i));
5213 TEST_F(DatabaseBackedPoolTest, DoesntReloadKnownBadFiles) {
5214 ExponentialErrorDatabase error_database;
5215 DescriptorPool pool(&error_database);
5217 GOOGLE_LOG(INFO) << "A timeout in this test probably indicates a real bug.";
5219 EXPECT_TRUE(pool.FindFileByName("file40.proto") == NULL);
5220 EXPECT_TRUE(pool.FindMessageTypeByName("Message40") == NULL);
5223 TEST_F(DatabaseBackedPoolTest, DoesntFallbackOnWrongType) {
5224 // If a lookup finds a symbol of the wrong type (e.g. we pass a type name
5225 // to FindFieldByName()), we should fail fast, without checking the fallback
5227 CallCountingDatabase call_counter(&database_);
5228 DescriptorPool pool(&call_counter);
5230 const FileDescriptor* file = pool.FindFileByName("foo.proto");
5231 ASSERT_TRUE(file != NULL);
5232 const Descriptor* foo = pool.FindMessageTypeByName("Foo");
5233 ASSERT_TRUE(foo != NULL);
5234 const EnumDescriptor* test_enum = pool.FindEnumTypeByName("TestEnum");
5235 ASSERT_TRUE(test_enum != NULL);
5237 EXPECT_NE(0, call_counter.call_count_);
5238 call_counter.Clear();
5240 EXPECT_TRUE(pool.FindMessageTypeByName("TestEnum") == NULL);
5241 EXPECT_TRUE(pool.FindFieldByName("Foo") == NULL);
5242 EXPECT_TRUE(pool.FindExtensionByName("Foo") == NULL);
5243 EXPECT_TRUE(pool.FindEnumTypeByName("Foo") == NULL);
5244 EXPECT_TRUE(pool.FindEnumValueByName("Foo") == NULL);
5245 EXPECT_TRUE(pool.FindServiceByName("Foo") == NULL);
5246 EXPECT_TRUE(pool.FindMethodByName("Foo") == NULL);
5248 EXPECT_EQ(0, call_counter.call_count_);
5251 // ===================================================================
5253 class AbortingErrorCollector : public DescriptorPool::ErrorCollector {
5255 AbortingErrorCollector() {}
5257 virtual void AddError(
5258 const string &filename,
5259 const string &element_name,
5260 const Message *message,
5261 ErrorLocation location,
5262 const string &error_message) {
5263 GOOGLE_LOG(FATAL) << "AddError() called unexpectedly: " << filename << ": "
5267 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(AbortingErrorCollector);
5270 // A source tree containing only one file.
5271 class SingletonSourceTree : public compiler::SourceTree {
5273 SingletonSourceTree(const string& filename, const string& contents)
5274 : filename_(filename), contents_(contents) {}
5276 virtual io::ZeroCopyInputStream* Open(const string& filename) {
5277 return filename == filename_ ?
5278 new io::ArrayInputStream(contents_.data(), contents_.size()) : NULL;
5282 const string filename_;
5283 const string contents_;
5285 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SingletonSourceTree);
5288 const char *const kSourceLocationTestInput =
5289 "syntax = \"proto2\";\n"
5291 " optional int32 a = 1;\n"
5293 " required double b = 1;\n"
5296 "enum Indecision {\n"
5302 " rpc Method(A) returns (A.B);\n"
5303 // Put an empty line here to make the source location range match.
5306 "message MessageWithExtensions {\n"
5307 " extensions 1000 to max;\n"
5309 "extend MessageWithExtensions {\n"
5310 " optional int32 int32_extension = 1001;\n"
5313 " extend MessageWithExtensions {\n"
5314 " optional C message_extension = 1002;\n"
5318 class SourceLocationTest : public testing::Test {
5320 SourceLocationTest()
5321 : source_tree_("/test/test.proto", kSourceLocationTestInput),
5323 pool_(&db_, &collector_) {}
5325 static string PrintSourceLocation(const SourceLocation &loc) {
5326 return strings::Substitute("$0:$1-$2:$3",
5328 1 + loc.start_column,
5330 1 + loc.end_column);
5334 AbortingErrorCollector collector_;
5335 SingletonSourceTree source_tree_;
5336 compiler::SourceTreeDescriptorDatabase db_;
5339 DescriptorPool pool_;
5342 // TODO(adonovan): implement support for option fields and for
5343 // subparts of declarations.
5345 TEST_F(SourceLocationTest, GetSourceLocation) {
5348 const FileDescriptor *file_desc =
5349 GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto"));
5351 const Descriptor *a_desc = file_desc->FindMessageTypeByName("A");
5352 EXPECT_TRUE(a_desc->GetSourceLocation(&loc));
5353 EXPECT_EQ("2:1-7:2", PrintSourceLocation(loc));
5355 const Descriptor *a_b_desc = a_desc->FindNestedTypeByName("B");
5356 EXPECT_TRUE(a_b_desc->GetSourceLocation(&loc));
5357 EXPECT_EQ("4:3-6:4", PrintSourceLocation(loc));
5359 const EnumDescriptor *e_desc = file_desc->FindEnumTypeByName("Indecision");
5360 EXPECT_TRUE(e_desc->GetSourceLocation(&loc));
5361 EXPECT_EQ("8:1-12:2", PrintSourceLocation(loc));
5363 const EnumValueDescriptor *yes_desc = e_desc->FindValueByName("YES");
5364 EXPECT_TRUE(yes_desc->GetSourceLocation(&loc));
5365 EXPECT_EQ("9:3-9:13", PrintSourceLocation(loc));
5367 const ServiceDescriptor *s_desc = file_desc->FindServiceByName("S");
5368 EXPECT_TRUE(s_desc->GetSourceLocation(&loc));
5369 EXPECT_EQ("13:1-16:2", PrintSourceLocation(loc));
5371 const MethodDescriptor *m_desc = s_desc->FindMethodByName("Method");
5372 EXPECT_TRUE(m_desc->GetSourceLocation(&loc));
5373 EXPECT_EQ("14:3-14:31", PrintSourceLocation(loc));
5377 TEST_F(SourceLocationTest, ExtensionSourceLocation) {
5380 const FileDescriptor *file_desc =
5381 GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto"));
5383 const FieldDescriptor *int32_extension_desc =
5384 file_desc->FindExtensionByName("int32_extension");
5385 EXPECT_TRUE(int32_extension_desc->GetSourceLocation(&loc));
5386 EXPECT_EQ("21:3-21:41", PrintSourceLocation(loc));
5388 const Descriptor *c_desc = file_desc->FindMessageTypeByName("C");
5389 EXPECT_TRUE(c_desc->GetSourceLocation(&loc));
5390 EXPECT_EQ("23:1-27:2", PrintSourceLocation(loc));
5392 const FieldDescriptor *message_extension_desc =
5393 c_desc->FindExtensionByName("message_extension");
5394 EXPECT_TRUE(message_extension_desc->GetSourceLocation(&loc));
5395 EXPECT_EQ("25:5-25:41", PrintSourceLocation(loc));
5398 // Missing SourceCodeInfo doesn't cause crash:
5399 TEST_F(SourceLocationTest, GetSourceLocation_MissingSourceCodeInfo) {
5402 const FileDescriptor *file_desc =
5403 GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto"));
5405 FileDescriptorProto proto;
5406 file_desc->CopyTo(&proto); // Note, this discards the SourceCodeInfo.
5407 EXPECT_FALSE(proto.has_source_code_info());
5409 DescriptorPool bad1_pool(&pool_);
5410 const FileDescriptor* bad1_file_desc =
5411 GOOGLE_CHECK_NOTNULL(bad1_pool.BuildFile(proto));
5412 const Descriptor *bad1_a_desc = bad1_file_desc->FindMessageTypeByName("A");
5413 EXPECT_FALSE(bad1_a_desc->GetSourceLocation(&loc));
5416 // Corrupt SourceCodeInfo doesn't cause crash:
5417 TEST_F(SourceLocationTest, GetSourceLocation_BogusSourceCodeInfo) {
5420 const FileDescriptor *file_desc =
5421 GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto"));
5423 FileDescriptorProto proto;
5424 file_desc->CopyTo(&proto); // Note, this discards the SourceCodeInfo.
5425 EXPECT_FALSE(proto.has_source_code_info());
5426 SourceCodeInfo_Location *loc_msg =
5427 proto.mutable_source_code_info()->add_location();
5428 loc_msg->add_path(1);
5429 loc_msg->add_path(2);
5430 loc_msg->add_path(3);
5431 loc_msg->add_span(4);
5432 loc_msg->add_span(5);
5433 loc_msg->add_span(6);
5435 DescriptorPool bad2_pool(&pool_);
5436 const FileDescriptor* bad2_file_desc =
5437 GOOGLE_CHECK_NOTNULL(bad2_pool.BuildFile(proto));
5438 const Descriptor *bad2_a_desc = bad2_file_desc->FindMessageTypeByName("A");
5439 EXPECT_FALSE(bad2_a_desc->GetSourceLocation(&loc));
5442 // ===================================================================
5444 const char* const kCopySourceCodeInfoToTestInput =
5445 "syntax = \"proto2\";\n"
5448 // Required since source code information is not preserved by
5449 // FileDescriptorTest.
5450 class CopySourceCodeInfoToTest : public testing::Test {
5452 CopySourceCodeInfoToTest()
5453 : source_tree_("/test/test.proto", kCopySourceCodeInfoToTestInput),
5455 pool_(&db_, &collector_) {}
5458 AbortingErrorCollector collector_;
5459 SingletonSourceTree source_tree_;
5460 compiler::SourceTreeDescriptorDatabase db_;
5463 DescriptorPool pool_;
5466 TEST_F(CopySourceCodeInfoToTest, CopyTo_DoesNotCopySourceCodeInfo) {
5467 const FileDescriptor* file_desc =
5468 GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto"));
5469 FileDescriptorProto file_desc_proto;
5470 ASSERT_FALSE(file_desc_proto.has_source_code_info());
5472 file_desc->CopyTo(&file_desc_proto);
5473 EXPECT_FALSE(file_desc_proto.has_source_code_info());
5476 TEST_F(CopySourceCodeInfoToTest, CopySourceCodeInfoTo) {
5477 const FileDescriptor* file_desc =
5478 GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto"));
5479 FileDescriptorProto file_desc_proto;
5480 ASSERT_FALSE(file_desc_proto.has_source_code_info());
5482 file_desc->CopySourceCodeInfoTo(&file_desc_proto);
5483 const SourceCodeInfo& info = file_desc_proto.source_code_info();
5484 ASSERT_EQ(3, info.location_size());
5485 // Get the Foo message location
5486 const SourceCodeInfo_Location& foo_location = info.location(1);
5487 ASSERT_EQ(2, foo_location.path_size());
5488 EXPECT_EQ(FileDescriptorProto::kMessageTypeFieldNumber, foo_location.path(0));
5489 EXPECT_EQ(0, foo_location.path(1)); // Foo is the first message defined
5490 ASSERT_EQ(3, foo_location.span_size()); // Foo spans one line
5491 EXPECT_EQ(1, foo_location.span(0)); // Foo is declared on line 1
5492 EXPECT_EQ(0, foo_location.span(1)); // Foo starts at column 0
5493 EXPECT_EQ(14, foo_location.span(2)); // Foo ends on column 14
5496 // ===================================================================
5499 } // namespace descriptor_unittest
5500 } // namespace protobuf
5501 } // namespace google