1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc.  All rights reserved.
3 // https://developers.google.com/protocol-buffers/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
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
14 // distribution.
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.
18 //
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.
30 
31 // Author: kenton@google.com (Kenton Varda)
32 //  Based on original Protocol Buffers design by
33 //  Sanjay Ghemawat, Jeff Dean, and others.
34 //
35 // This file makes extensive use of RFC 3092.  :)
36 
37 #include <memory>
38 #ifndef _SHARED_PTR_H
39 #include <google/protobuf/stubs/shared_ptr.h>
40 #endif
41 #include <vector>
42 
43 #include <google/protobuf/compiler/importer.h>
44 #include <google/protobuf/unittest.pb.h>
45 #include <google/protobuf/unittest_custom_options.pb.h>
46 #include <google/protobuf/io/zero_copy_stream_impl.h>
47 #include <google/protobuf/descriptor.pb.h>
48 #include <google/protobuf/descriptor.h>
49 #include <google/protobuf/descriptor_database.h>
50 #include <google/protobuf/dynamic_message.h>
51 #include <google/protobuf/text_format.h>
52 #include <google/protobuf/stubs/strutil.h>
53 #include <google/protobuf/stubs/substitute.h>
54 
55 #include <google/protobuf/stubs/common.h>
56 #include <google/protobuf/stubs/logging.h>
57 #include <google/protobuf/stubs/logging.h>
58 #include <google/protobuf/testing/googletest.h>
59 #include <gtest/gtest.h>
60 
61 namespace google {
62 namespace protobuf {
63 
64 // Can't use an anonymous namespace here due to brokenness of Tru64 compiler.
65 namespace descriptor_unittest {
66 
67 // Some helpers to make assembling descriptors faster.
AddMessage(FileDescriptorProto * file,const string & name)68 DescriptorProto* AddMessage(FileDescriptorProto* file, const string& name) {
69   DescriptorProto* result = file->add_message_type();
70   result->set_name(name);
71   return result;
72 }
73 
AddNestedMessage(DescriptorProto * parent,const string & name)74 DescriptorProto* AddNestedMessage(DescriptorProto* parent, const string& name) {
75   DescriptorProto* result = parent->add_nested_type();
76   result->set_name(name);
77   return result;
78 }
79 
AddEnum(FileDescriptorProto * file,const string & name)80 EnumDescriptorProto* AddEnum(FileDescriptorProto* file, const string& name) {
81   EnumDescriptorProto* result = file->add_enum_type();
82   result->set_name(name);
83   return result;
84 }
85 
AddNestedEnum(DescriptorProto * parent,const string & name)86 EnumDescriptorProto* AddNestedEnum(DescriptorProto* parent,
87                                    const string& name) {
88   EnumDescriptorProto* result = parent->add_enum_type();
89   result->set_name(name);
90   return result;
91 }
92 
AddService(FileDescriptorProto * file,const string & name)93 ServiceDescriptorProto* AddService(FileDescriptorProto* file,
94                                    const string& name) {
95   ServiceDescriptorProto* result = file->add_service();
96   result->set_name(name);
97   return result;
98 }
99 
AddField(DescriptorProto * parent,const string & name,int number,FieldDescriptorProto::Label label,FieldDescriptorProto::Type type)100 FieldDescriptorProto* AddField(DescriptorProto* parent,
101                                const string& name, int number,
102                                FieldDescriptorProto::Label label,
103                                FieldDescriptorProto::Type type) {
104   FieldDescriptorProto* result = parent->add_field();
105   result->set_name(name);
106   result->set_number(number);
107   result->set_label(label);
108   result->set_type(type);
109   return result;
110 }
111 
AddExtension(FileDescriptorProto * file,const string & extendee,const string & name,int number,FieldDescriptorProto::Label label,FieldDescriptorProto::Type type)112 FieldDescriptorProto* AddExtension(FileDescriptorProto* file,
113                                    const string& extendee,
114                                    const string& name, int number,
115                                    FieldDescriptorProto::Label label,
116                                    FieldDescriptorProto::Type type) {
117   FieldDescriptorProto* result = file->add_extension();
118   result->set_name(name);
119   result->set_number(number);
120   result->set_label(label);
121   result->set_type(type);
122   result->set_extendee(extendee);
123   return result;
124 }
125 
AddNestedExtension(DescriptorProto * parent,const string & extendee,const string & name,int number,FieldDescriptorProto::Label label,FieldDescriptorProto::Type type)126 FieldDescriptorProto* AddNestedExtension(DescriptorProto* parent,
127                                          const string& extendee,
128                                          const string& name, int number,
129                                          FieldDescriptorProto::Label label,
130                                          FieldDescriptorProto::Type type) {
131   FieldDescriptorProto* result = parent->add_extension();
132   result->set_name(name);
133   result->set_number(number);
134   result->set_label(label);
135   result->set_type(type);
136   result->set_extendee(extendee);
137   return result;
138 }
139 
AddExtensionRange(DescriptorProto * parent,int start,int end)140 DescriptorProto::ExtensionRange* AddExtensionRange(DescriptorProto* parent,
141                                                    int start, int end) {
142   DescriptorProto::ExtensionRange* result = parent->add_extension_range();
143   result->set_start(start);
144   result->set_end(end);
145   return result;
146 }
147 
AddReservedRange(DescriptorProto * parent,int start,int end)148 DescriptorProto::ReservedRange* AddReservedRange(DescriptorProto* parent,
149                                                  int start, int end) {
150   DescriptorProto::ReservedRange* result = parent->add_reserved_range();
151   result->set_start(start);
152   result->set_end(end);
153   return result;
154 }
155 
AddEnumValue(EnumDescriptorProto * enum_proto,const string & name,int number)156 EnumValueDescriptorProto* AddEnumValue(EnumDescriptorProto* enum_proto,
157                                        const string& name, int number) {
158   EnumValueDescriptorProto* result = enum_proto->add_value();
159   result->set_name(name);
160   result->set_number(number);
161   return result;
162 }
163 
AddMethod(ServiceDescriptorProto * service,const string & name,const string & input_type,const string & output_type)164 MethodDescriptorProto* AddMethod(ServiceDescriptorProto* service,
165                                  const string& name,
166                                  const string& input_type,
167                                  const string& output_type) {
168   MethodDescriptorProto* result = service->add_method();
169   result->set_name(name);
170   result->set_input_type(input_type);
171   result->set_output_type(output_type);
172   return result;
173 }
174 
175 // Empty enums technically aren't allowed.  We need to insert a dummy value
176 // into them.
AddEmptyEnum(FileDescriptorProto * file,const string & name)177 void AddEmptyEnum(FileDescriptorProto* file, const string& name) {
178   AddEnumValue(AddEnum(file, name), name + "_DUMMY", 1);
179 }
180 
181 class MockErrorCollector : public DescriptorPool::ErrorCollector {
182  public:
MockErrorCollector()183   MockErrorCollector() {}
~MockErrorCollector()184   ~MockErrorCollector() {}
185 
186   string text_;
187   string warning_text_;
188 
189   // implements ErrorCollector ---------------------------------------
AddError(const string & filename,const string & element_name,const Message * descriptor,ErrorLocation location,const string & message)190   void AddError(const string& filename,
191                 const string& element_name, const Message* descriptor,
192                 ErrorLocation location, const string& message) {
193     const char* location_name = NULL;
194     switch (location) {
195       case NAME         : location_name = "NAME"         ; break;
196       case NUMBER       : location_name = "NUMBER"       ; break;
197       case TYPE         : location_name = "TYPE"         ; break;
198       case EXTENDEE     : location_name = "EXTENDEE"     ; break;
199       case DEFAULT_VALUE: location_name = "DEFAULT_VALUE"; break;
200       case OPTION_NAME  : location_name = "OPTION_NAME"  ; break;
201       case OPTION_VALUE : location_name = "OPTION_VALUE" ; break;
202       case INPUT_TYPE   : location_name = "INPUT_TYPE"   ; break;
203       case OUTPUT_TYPE  : location_name = "OUTPUT_TYPE"  ; break;
204       case OTHER        : location_name = "OTHER"        ; break;
205     }
206 
207     strings::SubstituteAndAppend(
208       &text_, "$0: $1: $2: $3\n",
209       filename, element_name, location_name, message);
210   }
211 
212   // implements ErrorCollector ---------------------------------------
AddWarning(const string & filename,const string & element_name,const Message * descriptor,ErrorLocation location,const string & message)213   void AddWarning(const string& filename, const string& element_name,
214                   const Message* descriptor, ErrorLocation location,
215                   const string& message) {
216     const char* location_name = NULL;
217     switch (location) {
218       case NAME         : location_name = "NAME"         ; break;
219       case NUMBER       : location_name = "NUMBER"       ; break;
220       case TYPE         : location_name = "TYPE"         ; break;
221       case EXTENDEE     : location_name = "EXTENDEE"     ; break;
222       case DEFAULT_VALUE: location_name = "DEFAULT_VALUE"; break;
223       case OPTION_NAME  : location_name = "OPTION_NAME"  ; break;
224       case OPTION_VALUE : location_name = "OPTION_VALUE" ; break;
225       case INPUT_TYPE   : location_name = "INPUT_TYPE"   ; break;
226       case OUTPUT_TYPE  : location_name = "OUTPUT_TYPE"  ; break;
227       case OTHER        : location_name = "OTHER"        ; break;
228     }
229 
230     strings::SubstituteAndAppend(
231       &warning_text_, "$0: $1: $2: $3\n",
232       filename, element_name, location_name, message);
233   }
234 };
235 
236 // ===================================================================
237 
238 // Test simple files.
239 class FileDescriptorTest : public testing::Test {
240  protected:
SetUp()241   virtual void SetUp() {
242     // Build descriptors for the following definitions:
243     //
244     //   // in "foo.proto"
245     //   message FooMessage { extensions 1; }
246     //   enum FooEnum {FOO_ENUM_VALUE = 1;}
247     //   service FooService {}
248     //   extend FooMessage { optional int32 foo_extension = 1; }
249     //
250     //   // in "bar.proto"
251     //   package bar_package;
252     //   message BarMessage { extensions 1; }
253     //   enum BarEnum {BAR_ENUM_VALUE = 1;}
254     //   service BarService {}
255     //   extend BarMessage { optional int32 bar_extension = 1; }
256     //
257     // Also, we have an empty file "baz.proto".  This file's purpose is to
258     // make sure that even though it has the same package as foo.proto,
259     // searching it for members of foo.proto won't work.
260 
261     FileDescriptorProto foo_file;
262     foo_file.set_name("foo.proto");
263     AddExtensionRange(AddMessage(&foo_file, "FooMessage"), 1, 2);
264     AddEnumValue(AddEnum(&foo_file, "FooEnum"), "FOO_ENUM_VALUE", 1);
265     AddService(&foo_file, "FooService");
266     AddExtension(&foo_file, "FooMessage", "foo_extension", 1,
267                  FieldDescriptorProto::LABEL_OPTIONAL,
268                  FieldDescriptorProto::TYPE_INT32);
269 
270     FileDescriptorProto bar_file;
271     bar_file.set_name("bar.proto");
272     bar_file.set_package("bar_package");
273     bar_file.add_dependency("foo.proto");
274     AddExtensionRange(AddMessage(&bar_file, "BarMessage"), 1, 2);
275     AddEnumValue(AddEnum(&bar_file, "BarEnum"), "BAR_ENUM_VALUE", 1);
276     AddService(&bar_file, "BarService");
277     AddExtension(&bar_file, "bar_package.BarMessage", "bar_extension", 1,
278                  FieldDescriptorProto::LABEL_OPTIONAL,
279                  FieldDescriptorProto::TYPE_INT32);
280 
281     FileDescriptorProto baz_file;
282     baz_file.set_name("baz.proto");
283 
284     // Build the descriptors and get the pointers.
285     foo_file_ = pool_.BuildFile(foo_file);
286     ASSERT_TRUE(foo_file_ != NULL);
287 
288     bar_file_ = pool_.BuildFile(bar_file);
289     ASSERT_TRUE(bar_file_ != NULL);
290 
291     baz_file_ = pool_.BuildFile(baz_file);
292     ASSERT_TRUE(baz_file_ != NULL);
293 
294     ASSERT_EQ(1, foo_file_->message_type_count());
295     foo_message_ = foo_file_->message_type(0);
296     ASSERT_EQ(1, foo_file_->enum_type_count());
297     foo_enum_ = foo_file_->enum_type(0);
298     ASSERT_EQ(1, foo_enum_->value_count());
299     foo_enum_value_ = foo_enum_->value(0);
300     ASSERT_EQ(1, foo_file_->service_count());
301     foo_service_ = foo_file_->service(0);
302     ASSERT_EQ(1, foo_file_->extension_count());
303     foo_extension_ = foo_file_->extension(0);
304 
305     ASSERT_EQ(1, bar_file_->message_type_count());
306     bar_message_ = bar_file_->message_type(0);
307     ASSERT_EQ(1, bar_file_->enum_type_count());
308     bar_enum_ = bar_file_->enum_type(0);
309     ASSERT_EQ(1, bar_enum_->value_count());
310     bar_enum_value_ = bar_enum_->value(0);
311     ASSERT_EQ(1, bar_file_->service_count());
312     bar_service_ = bar_file_->service(0);
313     ASSERT_EQ(1, bar_file_->extension_count());
314     bar_extension_ = bar_file_->extension(0);
315   }
316 
317   DescriptorPool pool_;
318 
319   const FileDescriptor* foo_file_;
320   const FileDescriptor* bar_file_;
321   const FileDescriptor* baz_file_;
322 
323   const Descriptor*          foo_message_;
324   const EnumDescriptor*      foo_enum_;
325   const EnumValueDescriptor* foo_enum_value_;
326   const ServiceDescriptor*   foo_service_;
327   const FieldDescriptor*     foo_extension_;
328 
329   const Descriptor*          bar_message_;
330   const EnumDescriptor*      bar_enum_;
331   const EnumValueDescriptor* bar_enum_value_;
332   const ServiceDescriptor*   bar_service_;
333   const FieldDescriptor*     bar_extension_;
334 };
335 
TEST_F(FileDescriptorTest,Name)336 TEST_F(FileDescriptorTest, Name) {
337   EXPECT_EQ("foo.proto", foo_file_->name());
338   EXPECT_EQ("bar.proto", bar_file_->name());
339   EXPECT_EQ("baz.proto", baz_file_->name());
340 }
341 
TEST_F(FileDescriptorTest,Package)342 TEST_F(FileDescriptorTest, Package) {
343   EXPECT_EQ("", foo_file_->package());
344   EXPECT_EQ("bar_package", bar_file_->package());
345 }
346 
TEST_F(FileDescriptorTest,Dependencies)347 TEST_F(FileDescriptorTest, Dependencies) {
348   EXPECT_EQ(0, foo_file_->dependency_count());
349   EXPECT_EQ(1, bar_file_->dependency_count());
350   EXPECT_EQ(foo_file_, bar_file_->dependency(0));
351 }
352 
TEST_F(FileDescriptorTest,FindMessageTypeByName)353 TEST_F(FileDescriptorTest, FindMessageTypeByName) {
354   EXPECT_EQ(foo_message_, foo_file_->FindMessageTypeByName("FooMessage"));
355   EXPECT_EQ(bar_message_, bar_file_->FindMessageTypeByName("BarMessage"));
356 
357   EXPECT_TRUE(foo_file_->FindMessageTypeByName("BarMessage") == NULL);
358   EXPECT_TRUE(bar_file_->FindMessageTypeByName("FooMessage") == NULL);
359   EXPECT_TRUE(baz_file_->FindMessageTypeByName("FooMessage") == NULL);
360 
361   EXPECT_TRUE(foo_file_->FindMessageTypeByName("NoSuchMessage") == NULL);
362   EXPECT_TRUE(foo_file_->FindMessageTypeByName("FooEnum") == NULL);
363 }
364 
TEST_F(FileDescriptorTest,FindEnumTypeByName)365 TEST_F(FileDescriptorTest, FindEnumTypeByName) {
366   EXPECT_EQ(foo_enum_, foo_file_->FindEnumTypeByName("FooEnum"));
367   EXPECT_EQ(bar_enum_, bar_file_->FindEnumTypeByName("BarEnum"));
368 
369   EXPECT_TRUE(foo_file_->FindEnumTypeByName("BarEnum") == NULL);
370   EXPECT_TRUE(bar_file_->FindEnumTypeByName("FooEnum") == NULL);
371   EXPECT_TRUE(baz_file_->FindEnumTypeByName("FooEnum") == NULL);
372 
373   EXPECT_TRUE(foo_file_->FindEnumTypeByName("NoSuchEnum") == NULL);
374   EXPECT_TRUE(foo_file_->FindEnumTypeByName("FooMessage") == NULL);
375 }
376 
TEST_F(FileDescriptorTest,FindEnumValueByName)377 TEST_F(FileDescriptorTest, FindEnumValueByName) {
378   EXPECT_EQ(foo_enum_value_, foo_file_->FindEnumValueByName("FOO_ENUM_VALUE"));
379   EXPECT_EQ(bar_enum_value_, bar_file_->FindEnumValueByName("BAR_ENUM_VALUE"));
380 
381   EXPECT_TRUE(foo_file_->FindEnumValueByName("BAR_ENUM_VALUE") == NULL);
382   EXPECT_TRUE(bar_file_->FindEnumValueByName("FOO_ENUM_VALUE") == NULL);
383   EXPECT_TRUE(baz_file_->FindEnumValueByName("FOO_ENUM_VALUE") == NULL);
384 
385   EXPECT_TRUE(foo_file_->FindEnumValueByName("NO_SUCH_VALUE") == NULL);
386   EXPECT_TRUE(foo_file_->FindEnumValueByName("FooMessage") == NULL);
387 }
388 
TEST_F(FileDescriptorTest,FindServiceByName)389 TEST_F(FileDescriptorTest, FindServiceByName) {
390   EXPECT_EQ(foo_service_, foo_file_->FindServiceByName("FooService"));
391   EXPECT_EQ(bar_service_, bar_file_->FindServiceByName("BarService"));
392 
393   EXPECT_TRUE(foo_file_->FindServiceByName("BarService") == NULL);
394   EXPECT_TRUE(bar_file_->FindServiceByName("FooService") == NULL);
395   EXPECT_TRUE(baz_file_->FindServiceByName("FooService") == NULL);
396 
397   EXPECT_TRUE(foo_file_->FindServiceByName("NoSuchService") == NULL);
398   EXPECT_TRUE(foo_file_->FindServiceByName("FooMessage") == NULL);
399 }
400 
TEST_F(FileDescriptorTest,FindExtensionByName)401 TEST_F(FileDescriptorTest, FindExtensionByName) {
402   EXPECT_EQ(foo_extension_, foo_file_->FindExtensionByName("foo_extension"));
403   EXPECT_EQ(bar_extension_, bar_file_->FindExtensionByName("bar_extension"));
404 
405   EXPECT_TRUE(foo_file_->FindExtensionByName("bar_extension") == NULL);
406   EXPECT_TRUE(bar_file_->FindExtensionByName("foo_extension") == NULL);
407   EXPECT_TRUE(baz_file_->FindExtensionByName("foo_extension") == NULL);
408 
409   EXPECT_TRUE(foo_file_->FindExtensionByName("no_such_extension") == NULL);
410   EXPECT_TRUE(foo_file_->FindExtensionByName("FooMessage") == NULL);
411 }
412 
TEST_F(FileDescriptorTest,FindExtensionByNumber)413 TEST_F(FileDescriptorTest, FindExtensionByNumber) {
414   EXPECT_EQ(foo_extension_, pool_.FindExtensionByNumber(foo_message_, 1));
415   EXPECT_EQ(bar_extension_, pool_.FindExtensionByNumber(bar_message_, 1));
416 
417   EXPECT_TRUE(pool_.FindExtensionByNumber(foo_message_, 2) == NULL);
418 }
419 
TEST_F(FileDescriptorTest,BuildAgain)420 TEST_F(FileDescriptorTest, BuildAgain) {
421   // Test that if te call BuildFile again on the same input we get the same
422   // FileDescriptor back.
423   FileDescriptorProto file;
424   foo_file_->CopyTo(&file);
425   EXPECT_EQ(foo_file_, pool_.BuildFile(file));
426 
427   // But if we change the file then it won't work.
428   file.set_package("some.other.package");
429   EXPECT_TRUE(pool_.BuildFile(file) == NULL);
430 }
431 
TEST_F(FileDescriptorTest,BuildAgainWithSyntax)432 TEST_F(FileDescriptorTest, BuildAgainWithSyntax) {
433   // Test that if te call BuildFile again on the same input we get the same
434   // FileDescriptor back even if syntax param is specified.
435   FileDescriptorProto proto_syntax2;
436   proto_syntax2.set_name("foo_syntax2");
437   proto_syntax2.set_syntax("proto2");
438 
439   const FileDescriptor* proto2_descriptor = pool_.BuildFile(proto_syntax2);
440   EXPECT_TRUE(proto2_descriptor != NULL);
441   EXPECT_EQ(proto2_descriptor, pool_.BuildFile(proto_syntax2));
442 
443   FileDescriptorProto implicit_proto2;
444   implicit_proto2.set_name("foo_implicit_syntax2");
445 
446   const FileDescriptor* implicit_proto2_descriptor =
447       pool_.BuildFile(implicit_proto2);
448   EXPECT_TRUE(implicit_proto2_descriptor != NULL);
449   // We get the same FileDescriptor back if syntax param is explicitly
450   // specified.
451   implicit_proto2.set_syntax("proto2");
452   EXPECT_EQ(implicit_proto2_descriptor, pool_.BuildFile(implicit_proto2));
453 
454   FileDescriptorProto proto_syntax3;
455   proto_syntax3.set_name("foo_syntax3");
456   proto_syntax3.set_syntax("proto3");
457 
458   const FileDescriptor* proto3_descriptor = pool_.BuildFile(proto_syntax3);
459   EXPECT_TRUE(proto3_descriptor != NULL);
460   EXPECT_EQ(proto3_descriptor, pool_.BuildFile(proto_syntax3));
461 }
462 
TEST_F(FileDescriptorTest,Syntax)463 TEST_F(FileDescriptorTest, Syntax) {
464   FileDescriptorProto proto;
465   proto.set_name("foo");
466   // Enable the test when we also populate the syntax for proto2.
467 #if 0
468   {
469     proto.set_syntax("proto2");
470     DescriptorPool pool;
471     const FileDescriptor* file = pool.BuildFile(proto);
472     EXPECT_TRUE(file != NULL);
473     EXPECT_EQ(FileDescriptor::SYNTAX_PROTO2, file->syntax());
474     FileDescriptorProto other;
475     file->CopyTo(&other);
476     EXPECT_EQ("proto2", other.syntax());
477   }
478 #endif
479   {
480     proto.set_syntax("proto3");
481     DescriptorPool pool;
482     const FileDescriptor* file = pool.BuildFile(proto);
483     EXPECT_TRUE(file != NULL);
484     EXPECT_EQ(FileDescriptor::SYNTAX_PROTO3, file->syntax());
485     FileDescriptorProto other;
486     file->CopyTo(&other);
487     EXPECT_EQ("proto3", other.syntax());
488   }
489 }
490 
491 // ===================================================================
492 
493 // Test simple flat messages and fields.
494 class DescriptorTest : public testing::Test {
495  protected:
SetUp()496   virtual void SetUp() {
497     // Build descriptors for the following definitions:
498     //
499     //   // in "foo.proto"
500     //   message TestForeign {}
501     //   enum TestEnum {}
502     //
503     //   message TestMessage {
504     //     required string      foo = 1;
505     //     optional TestEnum    bar = 6;
506     //     repeated TestForeign baz = 500000000;
507     //     optional group       qux = 15 {}
508     //   }
509     //
510     //   // in "bar.proto"
511     //   package corge.grault;
512     //   message TestMessage2 {
513     //     required string foo = 1;
514     //     required string bar = 2;
515     //     required string quux = 6;
516     //   }
517     //
518     //   // in "map.proto"
519     //   message TestMessage3 {
520     //     map<int32, int32> map_int32_int32 = 1;
521     //   }
522     //
523     //   // in "json.proto"
524     //   message TestMessage4 {
525     //     optional int32 field_name1 = 1;
526     //     optional int32 fieldName2 = 2;
527     //     optional int32 FieldName3 = 3;
528     //     optional int32 _field_name4 = 4;
529     //     optional int32 FIELD_NAME5 = 5;
530     //     optional int32 field_name6 = 6 [json_name = "@type"];
531     //   }
532     //
533     // We cheat and use TestForeign as the type for qux rather than create
534     // an actual nested type.
535     //
536     // Since all primitive types (including string) use the same building
537     // code, there's no need to test each one individually.
538     //
539     // TestMessage2 is primarily here to test FindFieldByName and friends.
540     // All messages created from the same DescriptorPool share the same lookup
541     // table, so we need to insure that they don't interfere.
542 
543     FileDescriptorProto foo_file;
544     foo_file.set_name("foo.proto");
545     AddMessage(&foo_file, "TestForeign");
546     AddEmptyEnum(&foo_file, "TestEnum");
547 
548     DescriptorProto* message = AddMessage(&foo_file, "TestMessage");
549     AddField(message, "foo", 1,
550              FieldDescriptorProto::LABEL_REQUIRED,
551              FieldDescriptorProto::TYPE_STRING);
552     AddField(message, "bar", 6,
553              FieldDescriptorProto::LABEL_OPTIONAL,
554              FieldDescriptorProto::TYPE_ENUM)
555       ->set_type_name("TestEnum");
556     AddField(message, "baz", 500000000,
557              FieldDescriptorProto::LABEL_REPEATED,
558              FieldDescriptorProto::TYPE_MESSAGE)
559       ->set_type_name("TestForeign");
560     AddField(message, "qux", 15,
561              FieldDescriptorProto::LABEL_OPTIONAL,
562              FieldDescriptorProto::TYPE_GROUP)
563       ->set_type_name("TestForeign");
564 
565     FileDescriptorProto bar_file;
566     bar_file.set_name("bar.proto");
567     bar_file.set_package("corge.grault");
568 
569     DescriptorProto* message2 = AddMessage(&bar_file, "TestMessage2");
570     AddField(message2, "foo", 1,
571              FieldDescriptorProto::LABEL_REQUIRED,
572              FieldDescriptorProto::TYPE_STRING);
573     AddField(message2, "bar", 2,
574              FieldDescriptorProto::LABEL_REQUIRED,
575              FieldDescriptorProto::TYPE_STRING);
576     AddField(message2, "quux", 6,
577              FieldDescriptorProto::LABEL_REQUIRED,
578              FieldDescriptorProto::TYPE_STRING);
579 
580     FileDescriptorProto map_file;
581     map_file.set_name("map.proto");
582     DescriptorProto* message3 = AddMessage(&map_file, "TestMessage3");
583 
584     DescriptorProto* entry = AddNestedMessage(message3, "MapInt32Int32Entry");
585     AddField(entry, "key", 1,
586              FieldDescriptorProto::LABEL_OPTIONAL,
587              FieldDescriptorProto::TYPE_INT32);
588     AddField(entry, "value", 2,
589              FieldDescriptorProto::LABEL_OPTIONAL,
590              FieldDescriptorProto::TYPE_INT32);
591     entry->mutable_options()->set_map_entry(true);
592 
593     AddField(message3, "map_int32_int32", 1,
594              FieldDescriptorProto::LABEL_REPEATED,
595              FieldDescriptorProto::TYPE_MESSAGE)
596         ->set_type_name("MapInt32Int32Entry");
597 
598     FileDescriptorProto json_file;
599     json_file.set_name("json.proto");
600     json_file.set_syntax("proto3");
601     DescriptorProto* message4 = AddMessage(&json_file, "TestMessage4");
602     AddField(message4, "field_name1", 1,
603              FieldDescriptorProto::LABEL_OPTIONAL,
604              FieldDescriptorProto::TYPE_INT32);
605     AddField(message4, "fieldName2", 2,
606              FieldDescriptorProto::LABEL_OPTIONAL,
607              FieldDescriptorProto::TYPE_INT32);
608     AddField(message4, "FieldName3", 3,
609              FieldDescriptorProto::LABEL_OPTIONAL,
610              FieldDescriptorProto::TYPE_INT32);
611     AddField(message4, "_field_name4", 4,
612              FieldDescriptorProto::LABEL_OPTIONAL,
613              FieldDescriptorProto::TYPE_INT32);
614     AddField(message4, "FIELD_NAME5", 5,
615              FieldDescriptorProto::LABEL_OPTIONAL,
616              FieldDescriptorProto::TYPE_INT32);
617     AddField(message4, "field_name6", 6,
618              FieldDescriptorProto::LABEL_OPTIONAL,
619              FieldDescriptorProto::TYPE_INT32)
620         ->set_json_name("@type");
621 
622     // Build the descriptors and get the pointers.
623     foo_file_ = pool_.BuildFile(foo_file);
624     ASSERT_TRUE(foo_file_ != NULL);
625 
626     bar_file_ = pool_.BuildFile(bar_file);
627     ASSERT_TRUE(bar_file_ != NULL);
628 
629     map_file_ = pool_.BuildFile(map_file);
630     ASSERT_TRUE(map_file_ != NULL);
631 
632     json_file_ = pool_.BuildFile(json_file);
633     ASSERT_TRUE(json_file_ != NULL);
634 
635     ASSERT_EQ(1, foo_file_->enum_type_count());
636     enum_ = foo_file_->enum_type(0);
637 
638     ASSERT_EQ(2, foo_file_->message_type_count());
639     foreign_ = foo_file_->message_type(0);
640     message_ = foo_file_->message_type(1);
641 
642     ASSERT_EQ(4, message_->field_count());
643     foo_ = message_->field(0);
644     bar_ = message_->field(1);
645     baz_ = message_->field(2);
646     qux_ = message_->field(3);
647 
648     ASSERT_EQ(1, bar_file_->message_type_count());
649     message2_ = bar_file_->message_type(0);
650 
651     ASSERT_EQ(3, message2_->field_count());
652     foo2_  = message2_->field(0);
653     bar2_  = message2_->field(1);
654     quux2_ = message2_->field(2);
655 
656     ASSERT_EQ(1, map_file_->message_type_count());
657     message3_ = map_file_->message_type(0);
658 
659     ASSERT_EQ(1, message3_->field_count());
660     map_  = message3_->field(0);
661 
662     ASSERT_EQ(1, json_file_->message_type_count());
663     message4_ = json_file_->message_type(0);
664   }
665 
CopyWithJsonName(const Descriptor * message,DescriptorProto * proto)666   void CopyWithJsonName(const Descriptor* message, DescriptorProto* proto) {
667     message->CopyTo(proto);
668     message->CopyJsonNameTo(proto);
669   }
670 
671   DescriptorPool pool_;
672 
673   const FileDescriptor* foo_file_;
674   const FileDescriptor* bar_file_;
675   const FileDescriptor* map_file_;
676   const FileDescriptor* json_file_;
677 
678   const Descriptor* message_;
679   const Descriptor* message2_;
680   const Descriptor* message3_;
681   const Descriptor* message4_;
682   const Descriptor* foreign_;
683   const EnumDescriptor* enum_;
684 
685   const FieldDescriptor* foo_;
686   const FieldDescriptor* bar_;
687   const FieldDescriptor* baz_;
688   const FieldDescriptor* qux_;
689 
690   const FieldDescriptor* foo2_;
691   const FieldDescriptor* bar2_;
692   const FieldDescriptor* quux2_;
693 
694   const FieldDescriptor* map_;
695 };
696 
TEST_F(DescriptorTest,Name)697 TEST_F(DescriptorTest, Name) {
698   EXPECT_EQ("TestMessage", message_->name());
699   EXPECT_EQ("TestMessage", message_->full_name());
700   EXPECT_EQ(foo_file_, message_->file());
701 
702   EXPECT_EQ("TestMessage2", message2_->name());
703   EXPECT_EQ("corge.grault.TestMessage2", message2_->full_name());
704   EXPECT_EQ(bar_file_, message2_->file());
705 }
706 
TEST_F(DescriptorTest,ContainingType)707 TEST_F(DescriptorTest, ContainingType) {
708   EXPECT_TRUE(message_->containing_type() == NULL);
709   EXPECT_TRUE(message2_->containing_type() == NULL);
710 }
711 
TEST_F(DescriptorTest,FieldsByIndex)712 TEST_F(DescriptorTest, FieldsByIndex) {
713   ASSERT_EQ(4, message_->field_count());
714   EXPECT_EQ(foo_, message_->field(0));
715   EXPECT_EQ(bar_, message_->field(1));
716   EXPECT_EQ(baz_, message_->field(2));
717   EXPECT_EQ(qux_, message_->field(3));
718 }
719 
TEST_F(DescriptorTest,FindFieldByName)720 TEST_F(DescriptorTest, FindFieldByName) {
721   // All messages in the same DescriptorPool share a single lookup table for
722   // fields.  So, in addition to testing that FindFieldByName finds the fields
723   // of the message, we need to test that it does *not* find the fields of
724   // *other* messages.
725 
726   EXPECT_EQ(foo_, message_->FindFieldByName("foo"));
727   EXPECT_EQ(bar_, message_->FindFieldByName("bar"));
728   EXPECT_EQ(baz_, message_->FindFieldByName("baz"));
729   EXPECT_EQ(qux_, message_->FindFieldByName("qux"));
730   EXPECT_TRUE(message_->FindFieldByName("no_such_field") == NULL);
731   EXPECT_TRUE(message_->FindFieldByName("quux") == NULL);
732 
733   EXPECT_EQ(foo2_ , message2_->FindFieldByName("foo" ));
734   EXPECT_EQ(bar2_ , message2_->FindFieldByName("bar" ));
735   EXPECT_EQ(quux2_, message2_->FindFieldByName("quux"));
736   EXPECT_TRUE(message2_->FindFieldByName("baz") == NULL);
737   EXPECT_TRUE(message2_->FindFieldByName("qux") == NULL);
738 }
739 
TEST_F(DescriptorTest,FindFieldByNumber)740 TEST_F(DescriptorTest, FindFieldByNumber) {
741   EXPECT_EQ(foo_, message_->FindFieldByNumber(1));
742   EXPECT_EQ(bar_, message_->FindFieldByNumber(6));
743   EXPECT_EQ(baz_, message_->FindFieldByNumber(500000000));
744   EXPECT_EQ(qux_, message_->FindFieldByNumber(15));
745   EXPECT_TRUE(message_->FindFieldByNumber(837592) == NULL);
746   EXPECT_TRUE(message_->FindFieldByNumber(2) == NULL);
747 
748   EXPECT_EQ(foo2_ , message2_->FindFieldByNumber(1));
749   EXPECT_EQ(bar2_ , message2_->FindFieldByNumber(2));
750   EXPECT_EQ(quux2_, message2_->FindFieldByNumber(6));
751   EXPECT_TRUE(message2_->FindFieldByNumber(15) == NULL);
752   EXPECT_TRUE(message2_->FindFieldByNumber(500000000) == NULL);
753 }
754 
TEST_F(DescriptorTest,FieldName)755 TEST_F(DescriptorTest, FieldName) {
756   EXPECT_EQ("foo", foo_->name());
757   EXPECT_EQ("bar", bar_->name());
758   EXPECT_EQ("baz", baz_->name());
759   EXPECT_EQ("qux", qux_->name());
760 }
761 
TEST_F(DescriptorTest,FieldFullName)762 TEST_F(DescriptorTest, FieldFullName) {
763   EXPECT_EQ("TestMessage.foo", foo_->full_name());
764   EXPECT_EQ("TestMessage.bar", bar_->full_name());
765   EXPECT_EQ("TestMessage.baz", baz_->full_name());
766   EXPECT_EQ("TestMessage.qux", qux_->full_name());
767 
768   EXPECT_EQ("corge.grault.TestMessage2.foo", foo2_->full_name());
769   EXPECT_EQ("corge.grault.TestMessage2.bar", bar2_->full_name());
770   EXPECT_EQ("corge.grault.TestMessage2.quux", quux2_->full_name());
771 }
772 
TEST_F(DescriptorTest,FieldJsonName)773 TEST_F(DescriptorTest, FieldJsonName) {
774   EXPECT_EQ("fieldName1", message4_->field(0)->json_name());
775   EXPECT_EQ("fieldName2", message4_->field(1)->json_name());
776   EXPECT_EQ("fieldName3", message4_->field(2)->json_name());
777   EXPECT_EQ("fieldName4", message4_->field(3)->json_name());
778   EXPECT_EQ("fIELDNAME5", message4_->field(4)->json_name());
779   EXPECT_EQ("@type", message4_->field(5)->json_name());
780 
781   DescriptorProto proto;
782   message4_->CopyTo(&proto);
783   ASSERT_EQ(6, proto.field_size());
784   EXPECT_FALSE(proto.field(0).has_json_name());
785   EXPECT_FALSE(proto.field(1).has_json_name());
786   EXPECT_FALSE(proto.field(2).has_json_name());
787   EXPECT_FALSE(proto.field(3).has_json_name());
788   EXPECT_FALSE(proto.field(4).has_json_name());
789   EXPECT_EQ("@type", proto.field(5).json_name());
790 
791   proto.Clear();
792   CopyWithJsonName(message4_, &proto);
793   ASSERT_EQ(6, proto.field_size());
794   EXPECT_EQ("fieldName1", proto.field(0).json_name());
795   EXPECT_EQ("fieldName2", proto.field(1).json_name());
796   EXPECT_EQ("fieldName3", proto.field(2).json_name());
797   EXPECT_EQ("fieldName4", proto.field(3).json_name());
798   EXPECT_EQ("fIELDNAME5", proto.field(4).json_name());
799   EXPECT_EQ("@type", proto.field(5).json_name());
800 }
801 
TEST_F(DescriptorTest,FieldFile)802 TEST_F(DescriptorTest, FieldFile) {
803   EXPECT_EQ(foo_file_, foo_->file());
804   EXPECT_EQ(foo_file_, bar_->file());
805   EXPECT_EQ(foo_file_, baz_->file());
806   EXPECT_EQ(foo_file_, qux_->file());
807 
808   EXPECT_EQ(bar_file_, foo2_->file());
809   EXPECT_EQ(bar_file_, bar2_->file());
810   EXPECT_EQ(bar_file_, quux2_->file());
811 }
812 
TEST_F(DescriptorTest,FieldIndex)813 TEST_F(DescriptorTest, FieldIndex) {
814   EXPECT_EQ(0, foo_->index());
815   EXPECT_EQ(1, bar_->index());
816   EXPECT_EQ(2, baz_->index());
817   EXPECT_EQ(3, qux_->index());
818 }
819 
TEST_F(DescriptorTest,FieldNumber)820 TEST_F(DescriptorTest, FieldNumber) {
821   EXPECT_EQ(        1, foo_->number());
822   EXPECT_EQ(        6, bar_->number());
823   EXPECT_EQ(500000000, baz_->number());
824   EXPECT_EQ(       15, qux_->number());
825 }
826 
TEST_F(DescriptorTest,FieldType)827 TEST_F(DescriptorTest, FieldType) {
828   EXPECT_EQ(FieldDescriptor::TYPE_STRING , foo_->type());
829   EXPECT_EQ(FieldDescriptor::TYPE_ENUM   , bar_->type());
830   EXPECT_EQ(FieldDescriptor::TYPE_MESSAGE, baz_->type());
831   EXPECT_EQ(FieldDescriptor::TYPE_GROUP  , qux_->type());
832 }
833 
TEST_F(DescriptorTest,FieldLabel)834 TEST_F(DescriptorTest, FieldLabel) {
835   EXPECT_EQ(FieldDescriptor::LABEL_REQUIRED, foo_->label());
836   EXPECT_EQ(FieldDescriptor::LABEL_OPTIONAL, bar_->label());
837   EXPECT_EQ(FieldDescriptor::LABEL_REPEATED, baz_->label());
838   EXPECT_EQ(FieldDescriptor::LABEL_OPTIONAL, qux_->label());
839 
840   EXPECT_TRUE (foo_->is_required());
841   EXPECT_FALSE(foo_->is_optional());
842   EXPECT_FALSE(foo_->is_repeated());
843 
844   EXPECT_FALSE(bar_->is_required());
845   EXPECT_TRUE (bar_->is_optional());
846   EXPECT_FALSE(bar_->is_repeated());
847 
848   EXPECT_FALSE(baz_->is_required());
849   EXPECT_FALSE(baz_->is_optional());
850   EXPECT_TRUE (baz_->is_repeated());
851 }
852 
TEST_F(DescriptorTest,IsMap)853 TEST_F(DescriptorTest, IsMap) {
854   EXPECT_TRUE(map_->is_map());
855   EXPECT_FALSE(baz_->is_map());
856   EXPECT_TRUE(map_->message_type()->options().map_entry());
857 }
858 
TEST_F(DescriptorTest,FieldHasDefault)859 TEST_F(DescriptorTest, FieldHasDefault) {
860   EXPECT_FALSE(foo_->has_default_value());
861   EXPECT_FALSE(bar_->has_default_value());
862   EXPECT_FALSE(baz_->has_default_value());
863   EXPECT_FALSE(qux_->has_default_value());
864 }
865 
TEST_F(DescriptorTest,FieldContainingType)866 TEST_F(DescriptorTest, FieldContainingType) {
867   EXPECT_EQ(message_, foo_->containing_type());
868   EXPECT_EQ(message_, bar_->containing_type());
869   EXPECT_EQ(message_, baz_->containing_type());
870   EXPECT_EQ(message_, qux_->containing_type());
871 
872   EXPECT_EQ(message2_, foo2_ ->containing_type());
873   EXPECT_EQ(message2_, bar2_ ->containing_type());
874   EXPECT_EQ(message2_, quux2_->containing_type());
875 }
876 
TEST_F(DescriptorTest,FieldMessageType)877 TEST_F(DescriptorTest, FieldMessageType) {
878   EXPECT_TRUE(foo_->message_type() == NULL);
879   EXPECT_TRUE(bar_->message_type() == NULL);
880 
881   EXPECT_EQ(foreign_, baz_->message_type());
882   EXPECT_EQ(foreign_, qux_->message_type());
883 }
884 
TEST_F(DescriptorTest,FieldEnumType)885 TEST_F(DescriptorTest, FieldEnumType) {
886   EXPECT_TRUE(foo_->enum_type() == NULL);
887   EXPECT_TRUE(baz_->enum_type() == NULL);
888   EXPECT_TRUE(qux_->enum_type() == NULL);
889 
890   EXPECT_EQ(enum_, bar_->enum_type());
891 }
892 
893 // ===================================================================
894 
895 // Test simple flat messages and fields.
896 class OneofDescriptorTest : public testing::Test {
897  protected:
SetUp()898   virtual void SetUp() {
899     // Build descriptors for the following definitions:
900     //
901     //   package garply;
902     //   message TestOneof {
903     //     optional int32 a = 1;
904     //     oneof foo {
905     //       string b = 2;
906     //       TestOneof c = 3;
907     //     }
908     //     oneof bar {
909     //       float d = 4;
910     //     }
911     //   }
912 
913     FileDescriptorProto baz_file;
914     baz_file.set_name("baz.proto");
915     baz_file.set_package("garply");
916 
917     DescriptorProto* oneof_message = AddMessage(&baz_file, "TestOneof");
918     oneof_message->add_oneof_decl()->set_name("foo");
919     oneof_message->add_oneof_decl()->set_name("bar");
920 
921     AddField(oneof_message, "a", 1,
922              FieldDescriptorProto::LABEL_OPTIONAL,
923              FieldDescriptorProto::TYPE_INT32);
924     AddField(oneof_message, "b", 2,
925              FieldDescriptorProto::LABEL_OPTIONAL,
926              FieldDescriptorProto::TYPE_STRING);
927     oneof_message->mutable_field(1)->set_oneof_index(0);
928     AddField(oneof_message, "c", 3,
929              FieldDescriptorProto::LABEL_OPTIONAL,
930              FieldDescriptorProto::TYPE_MESSAGE);
931     oneof_message->mutable_field(2)->set_oneof_index(0);
932     oneof_message->mutable_field(2)->set_type_name("TestOneof");
933 
934     AddField(oneof_message, "d", 4,
935              FieldDescriptorProto::LABEL_OPTIONAL,
936              FieldDescriptorProto::TYPE_FLOAT);
937     oneof_message->mutable_field(3)->set_oneof_index(1);
938 
939     // Build the descriptors and get the pointers.
940     baz_file_ = pool_.BuildFile(baz_file);
941     ASSERT_TRUE(baz_file_ != NULL);
942 
943     ASSERT_EQ(1, baz_file_->message_type_count());
944     oneof_message_ = baz_file_->message_type(0);
945 
946     ASSERT_EQ(2, oneof_message_->oneof_decl_count());
947     oneof_ = oneof_message_->oneof_decl(0);
948     oneof2_ = oneof_message_->oneof_decl(1);
949 
950     ASSERT_EQ(4, oneof_message_->field_count());
951     a_ = oneof_message_->field(0);
952     b_ = oneof_message_->field(1);
953     c_ = oneof_message_->field(2);
954     d_ = oneof_message_->field(3);
955   }
956 
957   DescriptorPool pool_;
958 
959   const FileDescriptor* baz_file_;
960 
961   const Descriptor* oneof_message_;
962 
963   const OneofDescriptor* oneof_;
964   const OneofDescriptor* oneof2_;
965   const FieldDescriptor* a_;
966   const FieldDescriptor* b_;
967   const FieldDescriptor* c_;
968   const FieldDescriptor* d_;
969   const FieldDescriptor* e_;
970   const FieldDescriptor* f_;
971 };
972 
TEST_F(OneofDescriptorTest,Normal)973 TEST_F(OneofDescriptorTest, Normal) {
974   EXPECT_EQ("foo", oneof_->name());
975   EXPECT_EQ("garply.TestOneof.foo", oneof_->full_name());
976   EXPECT_EQ(0, oneof_->index());
977   ASSERT_EQ(2, oneof_->field_count());
978   EXPECT_EQ(b_, oneof_->field(0));
979   EXPECT_EQ(c_, oneof_->field(1));
980   EXPECT_TRUE(a_->containing_oneof() == NULL);
981   EXPECT_EQ(oneof_, b_->containing_oneof());
982   EXPECT_EQ(oneof_, c_->containing_oneof());
983 }
984 
TEST_F(OneofDescriptorTest,FindByName)985 TEST_F(OneofDescriptorTest, FindByName) {
986   EXPECT_EQ(oneof_, oneof_message_->FindOneofByName("foo"));
987   EXPECT_EQ(oneof2_, oneof_message_->FindOneofByName("bar"));
988   EXPECT_TRUE(oneof_message_->FindOneofByName("no_such_oneof") == NULL);
989 }
990 
991 // ===================================================================
992 
993 class StylizedFieldNamesTest : public testing::Test {
994  protected:
SetUp()995   void SetUp() {
996     FileDescriptorProto file;
997     file.set_name("foo.proto");
998 
999     AddExtensionRange(AddMessage(&file, "ExtendableMessage"), 1, 1000);
1000 
1001     DescriptorProto* message = AddMessage(&file, "TestMessage");
1002     AddField(message, "foo_foo", 1,
1003              FieldDescriptorProto::LABEL_OPTIONAL,
1004              FieldDescriptorProto::TYPE_INT32);
1005     AddField(message, "FooBar", 2,
1006              FieldDescriptorProto::LABEL_OPTIONAL,
1007              FieldDescriptorProto::TYPE_INT32);
1008     AddField(message, "fooBaz", 3,
1009              FieldDescriptorProto::LABEL_OPTIONAL,
1010              FieldDescriptorProto::TYPE_INT32);
1011     AddField(message, "fooFoo", 4,  // Camel-case conflict with foo_foo.
1012              FieldDescriptorProto::LABEL_OPTIONAL,
1013              FieldDescriptorProto::TYPE_INT32);
1014     AddField(message, "foobar", 5,  // Lower-case conflict with FooBar.
1015              FieldDescriptorProto::LABEL_OPTIONAL,
1016              FieldDescriptorProto::TYPE_INT32);
1017 
1018     AddNestedExtension(message, "ExtendableMessage", "bar_foo", 1,
1019                        FieldDescriptorProto::LABEL_OPTIONAL,
1020                        FieldDescriptorProto::TYPE_INT32);
1021     AddNestedExtension(message, "ExtendableMessage", "BarBar", 2,
1022                        FieldDescriptorProto::LABEL_OPTIONAL,
1023                        FieldDescriptorProto::TYPE_INT32);
1024     AddNestedExtension(message, "ExtendableMessage", "BarBaz", 3,
1025                        FieldDescriptorProto::LABEL_OPTIONAL,
1026                        FieldDescriptorProto::TYPE_INT32);
1027     AddNestedExtension(message, "ExtendableMessage", "barFoo", 4,  // Conflict
1028                        FieldDescriptorProto::LABEL_OPTIONAL,
1029                        FieldDescriptorProto::TYPE_INT32);
1030     AddNestedExtension(message, "ExtendableMessage", "barbar", 5,  // Conflict
1031                        FieldDescriptorProto::LABEL_OPTIONAL,
1032                        FieldDescriptorProto::TYPE_INT32);
1033 
1034     AddExtension(&file, "ExtendableMessage", "baz_foo", 11,
1035                  FieldDescriptorProto::LABEL_OPTIONAL,
1036                  FieldDescriptorProto::TYPE_INT32);
1037     AddExtension(&file, "ExtendableMessage", "BazBar", 12,
1038                  FieldDescriptorProto::LABEL_OPTIONAL,
1039                  FieldDescriptorProto::TYPE_INT32);
1040     AddExtension(&file, "ExtendableMessage", "BazBaz", 13,
1041                  FieldDescriptorProto::LABEL_OPTIONAL,
1042                  FieldDescriptorProto::TYPE_INT32);
1043     AddExtension(&file, "ExtendableMessage", "bazFoo", 14,  // Conflict
1044                  FieldDescriptorProto::LABEL_OPTIONAL,
1045                  FieldDescriptorProto::TYPE_INT32);
1046     AddExtension(&file, "ExtendableMessage", "bazbar", 15,  // Conflict
1047                  FieldDescriptorProto::LABEL_OPTIONAL,
1048                  FieldDescriptorProto::TYPE_INT32);
1049 
1050     file_ = pool_.BuildFile(file);
1051     ASSERT_TRUE(file_ != NULL);
1052     ASSERT_EQ(2, file_->message_type_count());
1053     message_ = file_->message_type(1);
1054     ASSERT_EQ("TestMessage", message_->name());
1055     ASSERT_EQ(5, message_->field_count());
1056     ASSERT_EQ(5, message_->extension_count());
1057     ASSERT_EQ(5, file_->extension_count());
1058   }
1059 
1060   DescriptorPool pool_;
1061   const FileDescriptor* file_;
1062   const Descriptor* message_;
1063 };
1064 
TEST_F(StylizedFieldNamesTest,LowercaseName)1065 TEST_F(StylizedFieldNamesTest, LowercaseName) {
1066   EXPECT_EQ("foo_foo", message_->field(0)->lowercase_name());
1067   EXPECT_EQ("foobar" , message_->field(1)->lowercase_name());
1068   EXPECT_EQ("foobaz" , message_->field(2)->lowercase_name());
1069   EXPECT_EQ("foofoo" , message_->field(3)->lowercase_name());
1070   EXPECT_EQ("foobar" , message_->field(4)->lowercase_name());
1071 
1072   EXPECT_EQ("bar_foo", message_->extension(0)->lowercase_name());
1073   EXPECT_EQ("barbar" , message_->extension(1)->lowercase_name());
1074   EXPECT_EQ("barbaz" , message_->extension(2)->lowercase_name());
1075   EXPECT_EQ("barfoo" , message_->extension(3)->lowercase_name());
1076   EXPECT_EQ("barbar" , message_->extension(4)->lowercase_name());
1077 
1078   EXPECT_EQ("baz_foo", file_->extension(0)->lowercase_name());
1079   EXPECT_EQ("bazbar" , file_->extension(1)->lowercase_name());
1080   EXPECT_EQ("bazbaz" , file_->extension(2)->lowercase_name());
1081   EXPECT_EQ("bazfoo" , file_->extension(3)->lowercase_name());
1082   EXPECT_EQ("bazbar" , file_->extension(4)->lowercase_name());
1083 }
1084 
TEST_F(StylizedFieldNamesTest,CamelcaseName)1085 TEST_F(StylizedFieldNamesTest, CamelcaseName) {
1086   EXPECT_EQ("fooFoo", message_->field(0)->camelcase_name());
1087   EXPECT_EQ("fooBar", message_->field(1)->camelcase_name());
1088   EXPECT_EQ("fooBaz", message_->field(2)->camelcase_name());
1089   EXPECT_EQ("fooFoo", message_->field(3)->camelcase_name());
1090   EXPECT_EQ("foobar", message_->field(4)->camelcase_name());
1091 
1092   EXPECT_EQ("barFoo", message_->extension(0)->camelcase_name());
1093   EXPECT_EQ("barBar", message_->extension(1)->camelcase_name());
1094   EXPECT_EQ("barBaz", message_->extension(2)->camelcase_name());
1095   EXPECT_EQ("barFoo", message_->extension(3)->camelcase_name());
1096   EXPECT_EQ("barbar", message_->extension(4)->camelcase_name());
1097 
1098   EXPECT_EQ("bazFoo", file_->extension(0)->camelcase_name());
1099   EXPECT_EQ("bazBar", file_->extension(1)->camelcase_name());
1100   EXPECT_EQ("bazBaz", file_->extension(2)->camelcase_name());
1101   EXPECT_EQ("bazFoo", file_->extension(3)->camelcase_name());
1102   EXPECT_EQ("bazbar", file_->extension(4)->camelcase_name());
1103 }
1104 
TEST_F(StylizedFieldNamesTest,FindByLowercaseName)1105 TEST_F(StylizedFieldNamesTest, FindByLowercaseName) {
1106   EXPECT_EQ(message_->field(0),
1107             message_->FindFieldByLowercaseName("foo_foo"));
1108   EXPECT_EQ(message_->field(1),
1109             message_->FindFieldByLowercaseName("foobar"));
1110   EXPECT_EQ(message_->field(2),
1111             message_->FindFieldByLowercaseName("foobaz"));
1112   EXPECT_TRUE(message_->FindFieldByLowercaseName("FooBar") == NULL);
1113   EXPECT_TRUE(message_->FindFieldByLowercaseName("fooBaz") == NULL);
1114   EXPECT_TRUE(message_->FindFieldByLowercaseName("bar_foo") == NULL);
1115   EXPECT_TRUE(message_->FindFieldByLowercaseName("nosuchfield") == NULL);
1116 
1117   EXPECT_EQ(message_->extension(0),
1118             message_->FindExtensionByLowercaseName("bar_foo"));
1119   EXPECT_EQ(message_->extension(1),
1120             message_->FindExtensionByLowercaseName("barbar"));
1121   EXPECT_EQ(message_->extension(2),
1122             message_->FindExtensionByLowercaseName("barbaz"));
1123   EXPECT_TRUE(message_->FindExtensionByLowercaseName("BarBar") == NULL);
1124   EXPECT_TRUE(message_->FindExtensionByLowercaseName("barBaz") == NULL);
1125   EXPECT_TRUE(message_->FindExtensionByLowercaseName("foo_foo") == NULL);
1126   EXPECT_TRUE(message_->FindExtensionByLowercaseName("nosuchfield") == NULL);
1127 
1128   EXPECT_EQ(file_->extension(0),
1129             file_->FindExtensionByLowercaseName("baz_foo"));
1130   EXPECT_EQ(file_->extension(1),
1131             file_->FindExtensionByLowercaseName("bazbar"));
1132   EXPECT_EQ(file_->extension(2),
1133             file_->FindExtensionByLowercaseName("bazbaz"));
1134   EXPECT_TRUE(file_->FindExtensionByLowercaseName("BazBar") == NULL);
1135   EXPECT_TRUE(file_->FindExtensionByLowercaseName("bazBaz") == NULL);
1136   EXPECT_TRUE(file_->FindExtensionByLowercaseName("nosuchfield") == NULL);
1137 }
1138 
TEST_F(StylizedFieldNamesTest,FindByCamelcaseName)1139 TEST_F(StylizedFieldNamesTest, FindByCamelcaseName) {
1140   EXPECT_EQ(message_->field(0),
1141             message_->FindFieldByCamelcaseName("fooFoo"));
1142   EXPECT_EQ(message_->field(1),
1143             message_->FindFieldByCamelcaseName("fooBar"));
1144   EXPECT_EQ(message_->field(2),
1145             message_->FindFieldByCamelcaseName("fooBaz"));
1146   EXPECT_TRUE(message_->FindFieldByCamelcaseName("foo_foo") == NULL);
1147   EXPECT_TRUE(message_->FindFieldByCamelcaseName("FooBar") == NULL);
1148   EXPECT_TRUE(message_->FindFieldByCamelcaseName("barFoo") == NULL);
1149   EXPECT_TRUE(message_->FindFieldByCamelcaseName("nosuchfield") == NULL);
1150 
1151   EXPECT_EQ(message_->extension(0),
1152             message_->FindExtensionByCamelcaseName("barFoo"));
1153   EXPECT_EQ(message_->extension(1),
1154             message_->FindExtensionByCamelcaseName("barBar"));
1155   EXPECT_EQ(message_->extension(2),
1156             message_->FindExtensionByCamelcaseName("barBaz"));
1157   EXPECT_TRUE(message_->FindExtensionByCamelcaseName("bar_foo") == NULL);
1158   EXPECT_TRUE(message_->FindExtensionByCamelcaseName("BarBar") == NULL);
1159   EXPECT_TRUE(message_->FindExtensionByCamelcaseName("fooFoo") == NULL);
1160   EXPECT_TRUE(message_->FindExtensionByCamelcaseName("nosuchfield") == NULL);
1161 
1162   EXPECT_EQ(file_->extension(0),
1163             file_->FindExtensionByCamelcaseName("bazFoo"));
1164   EXPECT_EQ(file_->extension(1),
1165             file_->FindExtensionByCamelcaseName("bazBar"));
1166   EXPECT_EQ(file_->extension(2),
1167             file_->FindExtensionByCamelcaseName("bazBaz"));
1168   EXPECT_TRUE(file_->FindExtensionByCamelcaseName("baz_foo") == NULL);
1169   EXPECT_TRUE(file_->FindExtensionByCamelcaseName("BazBar") == NULL);
1170   EXPECT_TRUE(file_->FindExtensionByCamelcaseName("nosuchfield") == NULL);
1171 }
1172 
1173 // ===================================================================
1174 
1175 // Test enum descriptors.
1176 class EnumDescriptorTest : public testing::Test {
1177  protected:
SetUp()1178   virtual void SetUp() {
1179     // Build descriptors for the following definitions:
1180     //
1181     //   // in "foo.proto"
1182     //   enum TestEnum {
1183     //     FOO = 1;
1184     //     BAR = 2;
1185     //   }
1186     //
1187     //   // in "bar.proto"
1188     //   package corge.grault;
1189     //   enum TestEnum2 {
1190     //     FOO = 1;
1191     //     BAZ = 3;
1192     //   }
1193     //
1194     // TestEnum2 is primarily here to test FindValueByName and friends.
1195     // All enums created from the same DescriptorPool share the same lookup
1196     // table, so we need to insure that they don't interfere.
1197 
1198     // TestEnum
1199     FileDescriptorProto foo_file;
1200     foo_file.set_name("foo.proto");
1201 
1202     EnumDescriptorProto* enum_proto = AddEnum(&foo_file, "TestEnum");
1203     AddEnumValue(enum_proto, "FOO", 1);
1204     AddEnumValue(enum_proto, "BAR", 2);
1205 
1206     // TestEnum2
1207     FileDescriptorProto bar_file;
1208     bar_file.set_name("bar.proto");
1209     bar_file.set_package("corge.grault");
1210 
1211     EnumDescriptorProto* enum2_proto = AddEnum(&bar_file, "TestEnum2");
1212     AddEnumValue(enum2_proto, "FOO", 1);
1213     AddEnumValue(enum2_proto, "BAZ", 3);
1214 
1215     // Build the descriptors and get the pointers.
1216     foo_file_ = pool_.BuildFile(foo_file);
1217     ASSERT_TRUE(foo_file_ != NULL);
1218 
1219     bar_file_ = pool_.BuildFile(bar_file);
1220     ASSERT_TRUE(bar_file_ != NULL);
1221 
1222     ASSERT_EQ(1, foo_file_->enum_type_count());
1223     enum_ = foo_file_->enum_type(0);
1224 
1225     ASSERT_EQ(2, enum_->value_count());
1226     foo_ = enum_->value(0);
1227     bar_ = enum_->value(1);
1228 
1229     ASSERT_EQ(1, bar_file_->enum_type_count());
1230     enum2_ = bar_file_->enum_type(0);
1231 
1232     ASSERT_EQ(2, enum2_->value_count());
1233     foo2_ = enum2_->value(0);
1234     baz2_ = enum2_->value(1);
1235   }
1236 
1237   DescriptorPool pool_;
1238 
1239   const FileDescriptor* foo_file_;
1240   const FileDescriptor* bar_file_;
1241 
1242   const EnumDescriptor* enum_;
1243   const EnumDescriptor* enum2_;
1244 
1245   const EnumValueDescriptor* foo_;
1246   const EnumValueDescriptor* bar_;
1247 
1248   const EnumValueDescriptor* foo2_;
1249   const EnumValueDescriptor* baz2_;
1250 };
1251 
TEST_F(EnumDescriptorTest,Name)1252 TEST_F(EnumDescriptorTest, Name) {
1253   EXPECT_EQ("TestEnum", enum_->name());
1254   EXPECT_EQ("TestEnum", enum_->full_name());
1255   EXPECT_EQ(foo_file_, enum_->file());
1256 
1257   EXPECT_EQ("TestEnum2", enum2_->name());
1258   EXPECT_EQ("corge.grault.TestEnum2", enum2_->full_name());
1259   EXPECT_EQ(bar_file_, enum2_->file());
1260 }
1261 
TEST_F(EnumDescriptorTest,ContainingType)1262 TEST_F(EnumDescriptorTest, ContainingType) {
1263   EXPECT_TRUE(enum_->containing_type() == NULL);
1264   EXPECT_TRUE(enum2_->containing_type() == NULL);
1265 }
1266 
TEST_F(EnumDescriptorTest,ValuesByIndex)1267 TEST_F(EnumDescriptorTest, ValuesByIndex) {
1268   ASSERT_EQ(2, enum_->value_count());
1269   EXPECT_EQ(foo_, enum_->value(0));
1270   EXPECT_EQ(bar_, enum_->value(1));
1271 }
1272 
TEST_F(EnumDescriptorTest,FindValueByName)1273 TEST_F(EnumDescriptorTest, FindValueByName) {
1274   EXPECT_EQ(foo_ , enum_ ->FindValueByName("FOO"));
1275   EXPECT_EQ(bar_ , enum_ ->FindValueByName("BAR"));
1276   EXPECT_EQ(foo2_, enum2_->FindValueByName("FOO"));
1277   EXPECT_EQ(baz2_, enum2_->FindValueByName("BAZ"));
1278 
1279   EXPECT_TRUE(enum_ ->FindValueByName("NO_SUCH_VALUE") == NULL);
1280   EXPECT_TRUE(enum_ ->FindValueByName("BAZ"          ) == NULL);
1281   EXPECT_TRUE(enum2_->FindValueByName("BAR"          ) == NULL);
1282 }
1283 
TEST_F(EnumDescriptorTest,FindValueByNumber)1284 TEST_F(EnumDescriptorTest, FindValueByNumber) {
1285   EXPECT_EQ(foo_ , enum_ ->FindValueByNumber(1));
1286   EXPECT_EQ(bar_ , enum_ ->FindValueByNumber(2));
1287   EXPECT_EQ(foo2_, enum2_->FindValueByNumber(1));
1288   EXPECT_EQ(baz2_, enum2_->FindValueByNumber(3));
1289 
1290   EXPECT_TRUE(enum_ ->FindValueByNumber(416) == NULL);
1291   EXPECT_TRUE(enum_ ->FindValueByNumber(3) == NULL);
1292   EXPECT_TRUE(enum2_->FindValueByNumber(2) == NULL);
1293 }
1294 
TEST_F(EnumDescriptorTest,ValueName)1295 TEST_F(EnumDescriptorTest, ValueName) {
1296   EXPECT_EQ("FOO", foo_->name());
1297   EXPECT_EQ("BAR", bar_->name());
1298 }
1299 
TEST_F(EnumDescriptorTest,ValueFullName)1300 TEST_F(EnumDescriptorTest, ValueFullName) {
1301   EXPECT_EQ("FOO", foo_->full_name());
1302   EXPECT_EQ("BAR", bar_->full_name());
1303   EXPECT_EQ("corge.grault.FOO", foo2_->full_name());
1304   EXPECT_EQ("corge.grault.BAZ", baz2_->full_name());
1305 }
1306 
TEST_F(EnumDescriptorTest,ValueIndex)1307 TEST_F(EnumDescriptorTest, ValueIndex) {
1308   EXPECT_EQ(0, foo_->index());
1309   EXPECT_EQ(1, bar_->index());
1310 }
1311 
TEST_F(EnumDescriptorTest,ValueNumber)1312 TEST_F(EnumDescriptorTest, ValueNumber) {
1313   EXPECT_EQ(1, foo_->number());
1314   EXPECT_EQ(2, bar_->number());
1315 }
1316 
TEST_F(EnumDescriptorTest,ValueType)1317 TEST_F(EnumDescriptorTest, ValueType) {
1318   EXPECT_EQ(enum_ , foo_ ->type());
1319   EXPECT_EQ(enum_ , bar_ ->type());
1320   EXPECT_EQ(enum2_, foo2_->type());
1321   EXPECT_EQ(enum2_, baz2_->type());
1322 }
1323 
1324 // ===================================================================
1325 
1326 // Test service descriptors.
1327 class ServiceDescriptorTest : public testing::Test {
1328  protected:
SetUp()1329   virtual void SetUp() {
1330     // Build descriptors for the following messages and service:
1331     //    // in "foo.proto"
1332     //    message FooRequest  {}
1333     //    message FooResponse {}
1334     //    message BarRequest  {}
1335     //    message BarResponse {}
1336     //    message BazRequest  {}
1337     //    message BazResponse {}
1338     //
1339     //    service TestService {
1340     //      rpc Foo(FooRequest) returns (FooResponse);
1341     //      rpc Bar(BarRequest) returns (BarResponse);
1342     //    }
1343     //
1344     //    // in "bar.proto"
1345     //    package corge.grault
1346     //    service TestService2 {
1347     //      rpc Foo(FooRequest) returns (FooResponse);
1348     //      rpc Baz(BazRequest) returns (BazResponse);
1349     //    }
1350 
1351     FileDescriptorProto foo_file;
1352     foo_file.set_name("foo.proto");
1353 
1354     AddMessage(&foo_file, "FooRequest");
1355     AddMessage(&foo_file, "FooResponse");
1356     AddMessage(&foo_file, "BarRequest");
1357     AddMessage(&foo_file, "BarResponse");
1358     AddMessage(&foo_file, "BazRequest");
1359     AddMessage(&foo_file, "BazResponse");
1360 
1361     ServiceDescriptorProto* service = AddService(&foo_file, "TestService");
1362     AddMethod(service, "Foo", "FooRequest", "FooResponse");
1363     AddMethod(service, "Bar", "BarRequest", "BarResponse");
1364 
1365     FileDescriptorProto bar_file;
1366     bar_file.set_name("bar.proto");
1367     bar_file.set_package("corge.grault");
1368     bar_file.add_dependency("foo.proto");
1369 
1370     ServiceDescriptorProto* service2 = AddService(&bar_file, "TestService2");
1371     AddMethod(service2, "Foo", "FooRequest", "FooResponse");
1372     AddMethod(service2, "Baz", "BazRequest", "BazResponse");
1373 
1374     // Build the descriptors and get the pointers.
1375     foo_file_ = pool_.BuildFile(foo_file);
1376     ASSERT_TRUE(foo_file_ != NULL);
1377 
1378     bar_file_ = pool_.BuildFile(bar_file);
1379     ASSERT_TRUE(bar_file_ != NULL);
1380 
1381     ASSERT_EQ(6, foo_file_->message_type_count());
1382     foo_request_  = foo_file_->message_type(0);
1383     foo_response_ = foo_file_->message_type(1);
1384     bar_request_  = foo_file_->message_type(2);
1385     bar_response_ = foo_file_->message_type(3);
1386     baz_request_  = foo_file_->message_type(4);
1387     baz_response_ = foo_file_->message_type(5);
1388 
1389     ASSERT_EQ(1, foo_file_->service_count());
1390     service_ = foo_file_->service(0);
1391 
1392     ASSERT_EQ(2, service_->method_count());
1393     foo_ = service_->method(0);
1394     bar_ = service_->method(1);
1395 
1396     ASSERT_EQ(1, bar_file_->service_count());
1397     service2_ = bar_file_->service(0);
1398 
1399     ASSERT_EQ(2, service2_->method_count());
1400     foo2_ = service2_->method(0);
1401     baz2_ = service2_->method(1);
1402   }
1403 
1404   DescriptorPool pool_;
1405 
1406   const FileDescriptor* foo_file_;
1407   const FileDescriptor* bar_file_;
1408 
1409   const Descriptor* foo_request_;
1410   const Descriptor* foo_response_;
1411   const Descriptor* bar_request_;
1412   const Descriptor* bar_response_;
1413   const Descriptor* baz_request_;
1414   const Descriptor* baz_response_;
1415 
1416   const ServiceDescriptor* service_;
1417   const ServiceDescriptor* service2_;
1418 
1419   const MethodDescriptor* foo_;
1420   const MethodDescriptor* bar_;
1421 
1422   const MethodDescriptor* foo2_;
1423   const MethodDescriptor* baz2_;
1424 };
1425 
TEST_F(ServiceDescriptorTest,Name)1426 TEST_F(ServiceDescriptorTest, Name) {
1427   EXPECT_EQ("TestService", service_->name());
1428   EXPECT_EQ("TestService", service_->full_name());
1429   EXPECT_EQ(foo_file_, service_->file());
1430 
1431   EXPECT_EQ("TestService2", service2_->name());
1432   EXPECT_EQ("corge.grault.TestService2", service2_->full_name());
1433   EXPECT_EQ(bar_file_, service2_->file());
1434 }
1435 
TEST_F(ServiceDescriptorTest,MethodsByIndex)1436 TEST_F(ServiceDescriptorTest, MethodsByIndex) {
1437   ASSERT_EQ(2, service_->method_count());
1438   EXPECT_EQ(foo_, service_->method(0));
1439   EXPECT_EQ(bar_, service_->method(1));
1440 }
1441 
TEST_F(ServiceDescriptorTest,FindMethodByName)1442 TEST_F(ServiceDescriptorTest, FindMethodByName) {
1443   EXPECT_EQ(foo_ , service_ ->FindMethodByName("Foo"));
1444   EXPECT_EQ(bar_ , service_ ->FindMethodByName("Bar"));
1445   EXPECT_EQ(foo2_, service2_->FindMethodByName("Foo"));
1446   EXPECT_EQ(baz2_, service2_->FindMethodByName("Baz"));
1447 
1448   EXPECT_TRUE(service_ ->FindMethodByName("NoSuchMethod") == NULL);
1449   EXPECT_TRUE(service_ ->FindMethodByName("Baz"         ) == NULL);
1450   EXPECT_TRUE(service2_->FindMethodByName("Bar"         ) == NULL);
1451 }
1452 
TEST_F(ServiceDescriptorTest,MethodName)1453 TEST_F(ServiceDescriptorTest, MethodName) {
1454   EXPECT_EQ("Foo", foo_->name());
1455   EXPECT_EQ("Bar", bar_->name());
1456 }
1457 
TEST_F(ServiceDescriptorTest,MethodFullName)1458 TEST_F(ServiceDescriptorTest, MethodFullName) {
1459   EXPECT_EQ("TestService.Foo", foo_->full_name());
1460   EXPECT_EQ("TestService.Bar", bar_->full_name());
1461   EXPECT_EQ("corge.grault.TestService2.Foo", foo2_->full_name());
1462   EXPECT_EQ("corge.grault.TestService2.Baz", baz2_->full_name());
1463 }
1464 
TEST_F(ServiceDescriptorTest,MethodIndex)1465 TEST_F(ServiceDescriptorTest, MethodIndex) {
1466   EXPECT_EQ(0, foo_->index());
1467   EXPECT_EQ(1, bar_->index());
1468 }
1469 
TEST_F(ServiceDescriptorTest,MethodParent)1470 TEST_F(ServiceDescriptorTest, MethodParent) {
1471   EXPECT_EQ(service_, foo_->service());
1472   EXPECT_EQ(service_, bar_->service());
1473 }
1474 
TEST_F(ServiceDescriptorTest,MethodInputType)1475 TEST_F(ServiceDescriptorTest, MethodInputType) {
1476   EXPECT_EQ(foo_request_, foo_->input_type());
1477   EXPECT_EQ(bar_request_, bar_->input_type());
1478 }
1479 
TEST_F(ServiceDescriptorTest,MethodOutputType)1480 TEST_F(ServiceDescriptorTest, MethodOutputType) {
1481   EXPECT_EQ(foo_response_, foo_->output_type());
1482   EXPECT_EQ(bar_response_, bar_->output_type());
1483 }
1484 
1485 // ===================================================================
1486 
1487 // Test nested types.
1488 class NestedDescriptorTest : public testing::Test {
1489  protected:
SetUp()1490   virtual void SetUp() {
1491     // Build descriptors for the following definitions:
1492     //
1493     //   // in "foo.proto"
1494     //   message TestMessage {
1495     //     message Foo {}
1496     //     message Bar {}
1497     //     enum Baz { A = 1; }
1498     //     enum Qux { B = 1; }
1499     //   }
1500     //
1501     //   // in "bar.proto"
1502     //   package corge.grault;
1503     //   message TestMessage2 {
1504     //     message Foo {}
1505     //     message Baz {}
1506     //     enum Qux  { A = 1; }
1507     //     enum Quux { C = 1; }
1508     //   }
1509     //
1510     // TestMessage2 is primarily here to test FindNestedTypeByName and friends.
1511     // All messages created from the same DescriptorPool share the same lookup
1512     // table, so we need to insure that they don't interfere.
1513     //
1514     // We add enum values to the enums in order to test searching for enum
1515     // values across a message's scope.
1516 
1517     FileDescriptorProto foo_file;
1518     foo_file.set_name("foo.proto");
1519 
1520     DescriptorProto* message = AddMessage(&foo_file, "TestMessage");
1521     AddNestedMessage(message, "Foo");
1522     AddNestedMessage(message, "Bar");
1523     EnumDescriptorProto* baz = AddNestedEnum(message, "Baz");
1524     AddEnumValue(baz, "A", 1);
1525     EnumDescriptorProto* qux = AddNestedEnum(message, "Qux");
1526     AddEnumValue(qux, "B", 1);
1527 
1528     FileDescriptorProto bar_file;
1529     bar_file.set_name("bar.proto");
1530     bar_file.set_package("corge.grault");
1531 
1532     DescriptorProto* message2 = AddMessage(&bar_file, "TestMessage2");
1533     AddNestedMessage(message2, "Foo");
1534     AddNestedMessage(message2, "Baz");
1535     EnumDescriptorProto* qux2 = AddNestedEnum(message2, "Qux");
1536     AddEnumValue(qux2, "A", 1);
1537     EnumDescriptorProto* quux2 = AddNestedEnum(message2, "Quux");
1538     AddEnumValue(quux2, "C", 1);
1539 
1540     // Build the descriptors and get the pointers.
1541     foo_file_ = pool_.BuildFile(foo_file);
1542     ASSERT_TRUE(foo_file_ != NULL);
1543 
1544     bar_file_ = pool_.BuildFile(bar_file);
1545     ASSERT_TRUE(bar_file_ != NULL);
1546 
1547     ASSERT_EQ(1, foo_file_->message_type_count());
1548     message_ = foo_file_->message_type(0);
1549 
1550     ASSERT_EQ(2, message_->nested_type_count());
1551     foo_ = message_->nested_type(0);
1552     bar_ = message_->nested_type(1);
1553 
1554     ASSERT_EQ(2, message_->enum_type_count());
1555     baz_ = message_->enum_type(0);
1556     qux_ = message_->enum_type(1);
1557 
1558     ASSERT_EQ(1, baz_->value_count());
1559     a_ = baz_->value(0);
1560     ASSERT_EQ(1, qux_->value_count());
1561     b_ = qux_->value(0);
1562 
1563     ASSERT_EQ(1, bar_file_->message_type_count());
1564     message2_ = bar_file_->message_type(0);
1565 
1566     ASSERT_EQ(2, message2_->nested_type_count());
1567     foo2_ = message2_->nested_type(0);
1568     baz2_ = message2_->nested_type(1);
1569 
1570     ASSERT_EQ(2, message2_->enum_type_count());
1571     qux2_ = message2_->enum_type(0);
1572     quux2_ = message2_->enum_type(1);
1573 
1574     ASSERT_EQ(1, qux2_->value_count());
1575     a2_ = qux2_->value(0);
1576     ASSERT_EQ(1, quux2_->value_count());
1577     c2_ = quux2_->value(0);
1578   }
1579 
1580   DescriptorPool pool_;
1581 
1582   const FileDescriptor* foo_file_;
1583   const FileDescriptor* bar_file_;
1584 
1585   const Descriptor* message_;
1586   const Descriptor* message2_;
1587 
1588   const Descriptor* foo_;
1589   const Descriptor* bar_;
1590   const EnumDescriptor* baz_;
1591   const EnumDescriptor* qux_;
1592   const EnumValueDescriptor* a_;
1593   const EnumValueDescriptor* b_;
1594 
1595   const Descriptor* foo2_;
1596   const Descriptor* baz2_;
1597   const EnumDescriptor* qux2_;
1598   const EnumDescriptor* quux2_;
1599   const EnumValueDescriptor* a2_;
1600   const EnumValueDescriptor* c2_;
1601 };
1602 
TEST_F(NestedDescriptorTest,MessageName)1603 TEST_F(NestedDescriptorTest, MessageName) {
1604   EXPECT_EQ("Foo", foo_ ->name());
1605   EXPECT_EQ("Bar", bar_ ->name());
1606   EXPECT_EQ("Foo", foo2_->name());
1607   EXPECT_EQ("Baz", baz2_->name());
1608 
1609   EXPECT_EQ("TestMessage.Foo", foo_->full_name());
1610   EXPECT_EQ("TestMessage.Bar", bar_->full_name());
1611   EXPECT_EQ("corge.grault.TestMessage2.Foo", foo2_->full_name());
1612   EXPECT_EQ("corge.grault.TestMessage2.Baz", baz2_->full_name());
1613 }
1614 
TEST_F(NestedDescriptorTest,MessageContainingType)1615 TEST_F(NestedDescriptorTest, MessageContainingType) {
1616   EXPECT_EQ(message_ , foo_ ->containing_type());
1617   EXPECT_EQ(message_ , bar_ ->containing_type());
1618   EXPECT_EQ(message2_, foo2_->containing_type());
1619   EXPECT_EQ(message2_, baz2_->containing_type());
1620 }
1621 
TEST_F(NestedDescriptorTest,NestedMessagesByIndex)1622 TEST_F(NestedDescriptorTest, NestedMessagesByIndex) {
1623   ASSERT_EQ(2, message_->nested_type_count());
1624   EXPECT_EQ(foo_, message_->nested_type(0));
1625   EXPECT_EQ(bar_, message_->nested_type(1));
1626 }
1627 
TEST_F(NestedDescriptorTest,FindFieldByNameDoesntFindNestedTypes)1628 TEST_F(NestedDescriptorTest, FindFieldByNameDoesntFindNestedTypes) {
1629   EXPECT_TRUE(message_->FindFieldByName("Foo") == NULL);
1630   EXPECT_TRUE(message_->FindFieldByName("Qux") == NULL);
1631   EXPECT_TRUE(message_->FindExtensionByName("Foo") == NULL);
1632   EXPECT_TRUE(message_->FindExtensionByName("Qux") == NULL);
1633 }
1634 
TEST_F(NestedDescriptorTest,FindNestedTypeByName)1635 TEST_F(NestedDescriptorTest, FindNestedTypeByName) {
1636   EXPECT_EQ(foo_ , message_ ->FindNestedTypeByName("Foo"));
1637   EXPECT_EQ(bar_ , message_ ->FindNestedTypeByName("Bar"));
1638   EXPECT_EQ(foo2_, message2_->FindNestedTypeByName("Foo"));
1639   EXPECT_EQ(baz2_, message2_->FindNestedTypeByName("Baz"));
1640 
1641   EXPECT_TRUE(message_ ->FindNestedTypeByName("NoSuchType") == NULL);
1642   EXPECT_TRUE(message_ ->FindNestedTypeByName("Baz"       ) == NULL);
1643   EXPECT_TRUE(message2_->FindNestedTypeByName("Bar"       ) == NULL);
1644 
1645   EXPECT_TRUE(message_->FindNestedTypeByName("Qux") == NULL);
1646 }
1647 
TEST_F(NestedDescriptorTest,EnumName)1648 TEST_F(NestedDescriptorTest, EnumName) {
1649   EXPECT_EQ("Baz" , baz_ ->name());
1650   EXPECT_EQ("Qux" , qux_ ->name());
1651   EXPECT_EQ("Qux" , qux2_->name());
1652   EXPECT_EQ("Quux", quux2_->name());
1653 
1654   EXPECT_EQ("TestMessage.Baz", baz_->full_name());
1655   EXPECT_EQ("TestMessage.Qux", qux_->full_name());
1656   EXPECT_EQ("corge.grault.TestMessage2.Qux" , qux2_ ->full_name());
1657   EXPECT_EQ("corge.grault.TestMessage2.Quux", quux2_->full_name());
1658 }
1659 
TEST_F(NestedDescriptorTest,EnumContainingType)1660 TEST_F(NestedDescriptorTest, EnumContainingType) {
1661   EXPECT_EQ(message_ , baz_  ->containing_type());
1662   EXPECT_EQ(message_ , qux_  ->containing_type());
1663   EXPECT_EQ(message2_, qux2_ ->containing_type());
1664   EXPECT_EQ(message2_, quux2_->containing_type());
1665 }
1666 
TEST_F(NestedDescriptorTest,NestedEnumsByIndex)1667 TEST_F(NestedDescriptorTest, NestedEnumsByIndex) {
1668   ASSERT_EQ(2, message_->nested_type_count());
1669   EXPECT_EQ(foo_, message_->nested_type(0));
1670   EXPECT_EQ(bar_, message_->nested_type(1));
1671 }
1672 
TEST_F(NestedDescriptorTest,FindEnumTypeByName)1673 TEST_F(NestedDescriptorTest, FindEnumTypeByName) {
1674   EXPECT_EQ(baz_  , message_ ->FindEnumTypeByName("Baz" ));
1675   EXPECT_EQ(qux_  , message_ ->FindEnumTypeByName("Qux" ));
1676   EXPECT_EQ(qux2_ , message2_->FindEnumTypeByName("Qux" ));
1677   EXPECT_EQ(quux2_, message2_->FindEnumTypeByName("Quux"));
1678 
1679   EXPECT_TRUE(message_ ->FindEnumTypeByName("NoSuchType") == NULL);
1680   EXPECT_TRUE(message_ ->FindEnumTypeByName("Quux"      ) == NULL);
1681   EXPECT_TRUE(message2_->FindEnumTypeByName("Baz"       ) == NULL);
1682 
1683   EXPECT_TRUE(message_->FindEnumTypeByName("Foo") == NULL);
1684 }
1685 
TEST_F(NestedDescriptorTest,FindEnumValueByName)1686 TEST_F(NestedDescriptorTest, FindEnumValueByName) {
1687   EXPECT_EQ(a_ , message_ ->FindEnumValueByName("A"));
1688   EXPECT_EQ(b_ , message_ ->FindEnumValueByName("B"));
1689   EXPECT_EQ(a2_, message2_->FindEnumValueByName("A"));
1690   EXPECT_EQ(c2_, message2_->FindEnumValueByName("C"));
1691 
1692   EXPECT_TRUE(message_ ->FindEnumValueByName("NO_SUCH_VALUE") == NULL);
1693   EXPECT_TRUE(message_ ->FindEnumValueByName("C"            ) == NULL);
1694   EXPECT_TRUE(message2_->FindEnumValueByName("B"            ) == NULL);
1695 
1696   EXPECT_TRUE(message_->FindEnumValueByName("Foo") == NULL);
1697 }
1698 
1699 // ===================================================================
1700 
1701 // Test extensions.
1702 class ExtensionDescriptorTest : public testing::Test {
1703  protected:
SetUp()1704   virtual void SetUp() {
1705     // Build descriptors for the following definitions:
1706     //
1707     //   enum Baz {}
1708     //   message Qux {}
1709     //
1710     //   message Foo {
1711     //     extensions 10 to 19;
1712     //     extensions 30 to 39;
1713     //   }
1714     //   extends Foo with optional int32 foo_int32 = 10;
1715     //   extends Foo with repeated TestEnum foo_enum = 19;
1716     //   message Bar {
1717     //     extends Foo with optional Qux foo_message = 30;
1718     //     // (using Qux as the group type)
1719     //     extends Foo with repeated group foo_group = 39;
1720     //   }
1721 
1722     FileDescriptorProto foo_file;
1723     foo_file.set_name("foo.proto");
1724 
1725     AddEmptyEnum(&foo_file, "Baz");
1726     AddMessage(&foo_file, "Qux");
1727 
1728     DescriptorProto* foo = AddMessage(&foo_file, "Foo");
1729     AddExtensionRange(foo, 10, 20);
1730     AddExtensionRange(foo, 30, 40);
1731 
1732     AddExtension(&foo_file, "Foo", "foo_int32", 10,
1733                  FieldDescriptorProto::LABEL_OPTIONAL,
1734                  FieldDescriptorProto::TYPE_INT32);
1735     AddExtension(&foo_file, "Foo", "foo_enum", 19,
1736                  FieldDescriptorProto::LABEL_REPEATED,
1737                  FieldDescriptorProto::TYPE_ENUM)
1738       ->set_type_name("Baz");
1739 
1740     DescriptorProto* bar = AddMessage(&foo_file, "Bar");
1741     AddNestedExtension(bar, "Foo", "foo_message", 30,
1742                        FieldDescriptorProto::LABEL_OPTIONAL,
1743                        FieldDescriptorProto::TYPE_MESSAGE)
1744       ->set_type_name("Qux");
1745     AddNestedExtension(bar, "Foo", "foo_group", 39,
1746                        FieldDescriptorProto::LABEL_REPEATED,
1747                        FieldDescriptorProto::TYPE_GROUP)
1748       ->set_type_name("Qux");
1749 
1750     // Build the descriptors and get the pointers.
1751     foo_file_ = pool_.BuildFile(foo_file);
1752     ASSERT_TRUE(foo_file_ != NULL);
1753 
1754     ASSERT_EQ(1, foo_file_->enum_type_count());
1755     baz_ = foo_file_->enum_type(0);
1756 
1757     ASSERT_EQ(3, foo_file_->message_type_count());
1758     qux_ = foo_file_->message_type(0);
1759     foo_ = foo_file_->message_type(1);
1760     bar_ = foo_file_->message_type(2);
1761   }
1762 
1763   DescriptorPool pool_;
1764 
1765   const FileDescriptor* foo_file_;
1766 
1767   const Descriptor* foo_;
1768   const Descriptor* bar_;
1769   const EnumDescriptor* baz_;
1770   const Descriptor* qux_;
1771 };
1772 
TEST_F(ExtensionDescriptorTest,ExtensionRanges)1773 TEST_F(ExtensionDescriptorTest, ExtensionRanges) {
1774   EXPECT_EQ(0, bar_->extension_range_count());
1775   ASSERT_EQ(2, foo_->extension_range_count());
1776 
1777   EXPECT_EQ(10, foo_->extension_range(0)->start);
1778   EXPECT_EQ(30, foo_->extension_range(1)->start);
1779 
1780   EXPECT_EQ(20, foo_->extension_range(0)->end);
1781   EXPECT_EQ(40, foo_->extension_range(1)->end);
1782 };
1783 
TEST_F(ExtensionDescriptorTest,Extensions)1784 TEST_F(ExtensionDescriptorTest, Extensions) {
1785   EXPECT_EQ(0, foo_->extension_count());
1786   ASSERT_EQ(2, foo_file_->extension_count());
1787   ASSERT_EQ(2, bar_->extension_count());
1788 
1789   EXPECT_TRUE(foo_file_->extension(0)->is_extension());
1790   EXPECT_TRUE(foo_file_->extension(1)->is_extension());
1791   EXPECT_TRUE(bar_->extension(0)->is_extension());
1792   EXPECT_TRUE(bar_->extension(1)->is_extension());
1793 
1794   EXPECT_EQ("foo_int32"  , foo_file_->extension(0)->name());
1795   EXPECT_EQ("foo_enum"   , foo_file_->extension(1)->name());
1796   EXPECT_EQ("foo_message", bar_->extension(0)->name());
1797   EXPECT_EQ("foo_group"  , bar_->extension(1)->name());
1798 
1799   EXPECT_EQ(10, foo_file_->extension(0)->number());
1800   EXPECT_EQ(19, foo_file_->extension(1)->number());
1801   EXPECT_EQ(30, bar_->extension(0)->number());
1802   EXPECT_EQ(39, bar_->extension(1)->number());
1803 
1804   EXPECT_EQ(FieldDescriptor::TYPE_INT32  , foo_file_->extension(0)->type());
1805   EXPECT_EQ(FieldDescriptor::TYPE_ENUM   , foo_file_->extension(1)->type());
1806   EXPECT_EQ(FieldDescriptor::TYPE_MESSAGE, bar_->extension(0)->type());
1807   EXPECT_EQ(FieldDescriptor::TYPE_GROUP  , bar_->extension(1)->type());
1808 
1809   EXPECT_EQ(baz_, foo_file_->extension(1)->enum_type());
1810   EXPECT_EQ(qux_, bar_->extension(0)->message_type());
1811   EXPECT_EQ(qux_, bar_->extension(1)->message_type());
1812 
1813   EXPECT_EQ(FieldDescriptor::LABEL_OPTIONAL, foo_file_->extension(0)->label());
1814   EXPECT_EQ(FieldDescriptor::LABEL_REPEATED, foo_file_->extension(1)->label());
1815   EXPECT_EQ(FieldDescriptor::LABEL_OPTIONAL, bar_->extension(0)->label());
1816   EXPECT_EQ(FieldDescriptor::LABEL_REPEATED, bar_->extension(1)->label());
1817 
1818   EXPECT_EQ(foo_, foo_file_->extension(0)->containing_type());
1819   EXPECT_EQ(foo_, foo_file_->extension(1)->containing_type());
1820   EXPECT_EQ(foo_, bar_->extension(0)->containing_type());
1821   EXPECT_EQ(foo_, bar_->extension(1)->containing_type());
1822 
1823   EXPECT_TRUE(foo_file_->extension(0)->extension_scope() == NULL);
1824   EXPECT_TRUE(foo_file_->extension(1)->extension_scope() == NULL);
1825   EXPECT_EQ(bar_, bar_->extension(0)->extension_scope());
1826   EXPECT_EQ(bar_, bar_->extension(1)->extension_scope());
1827 };
1828 
TEST_F(ExtensionDescriptorTest,IsExtensionNumber)1829 TEST_F(ExtensionDescriptorTest, IsExtensionNumber) {
1830   EXPECT_FALSE(foo_->IsExtensionNumber( 9));
1831   EXPECT_TRUE (foo_->IsExtensionNumber(10));
1832   EXPECT_TRUE (foo_->IsExtensionNumber(19));
1833   EXPECT_FALSE(foo_->IsExtensionNumber(20));
1834   EXPECT_FALSE(foo_->IsExtensionNumber(29));
1835   EXPECT_TRUE (foo_->IsExtensionNumber(30));
1836   EXPECT_TRUE (foo_->IsExtensionNumber(39));
1837   EXPECT_FALSE(foo_->IsExtensionNumber(40));
1838 }
1839 
TEST_F(ExtensionDescriptorTest,FindExtensionByName)1840 TEST_F(ExtensionDescriptorTest, FindExtensionByName) {
1841   // Note that FileDescriptor::FindExtensionByName() is tested by
1842   // FileDescriptorTest.
1843   ASSERT_EQ(2, bar_->extension_count());
1844 
1845   EXPECT_EQ(bar_->extension(0), bar_->FindExtensionByName("foo_message"));
1846   EXPECT_EQ(bar_->extension(1), bar_->FindExtensionByName("foo_group"  ));
1847 
1848   EXPECT_TRUE(bar_->FindExtensionByName("no_such_extension") == NULL);
1849   EXPECT_TRUE(foo_->FindExtensionByName("foo_int32") == NULL);
1850   EXPECT_TRUE(foo_->FindExtensionByName("foo_message") == NULL);
1851 }
1852 
TEST_F(ExtensionDescriptorTest,FindAllExtensions)1853 TEST_F(ExtensionDescriptorTest, FindAllExtensions) {
1854   vector<const FieldDescriptor*> extensions;
1855   pool_.FindAllExtensions(foo_, &extensions);
1856   ASSERT_EQ(4, extensions.size());
1857   EXPECT_EQ(10, extensions[0]->number());
1858   EXPECT_EQ(19, extensions[1]->number());
1859   EXPECT_EQ(30, extensions[2]->number());
1860   EXPECT_EQ(39, extensions[3]->number());
1861 }
1862 
TEST_F(ExtensionDescriptorTest,DuplicateFieldNumber)1863 TEST_F(ExtensionDescriptorTest, DuplicateFieldNumber) {
1864   DescriptorPool pool;
1865   FileDescriptorProto file_proto;
1866   // Add "google/protobuf/descriptor.proto".
1867   FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto);
1868   ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
1869   // Add "foo.proto":
1870   //   import "google/protobuf/descriptor.proto";
1871   //   extend google.protobuf.FieldOptions {
1872   //     optional int32 option1 = 1000;
1873   //   }
1874   file_proto.Clear();
1875   file_proto.set_name("foo.proto");
1876   file_proto.add_dependency("google/protobuf/descriptor.proto");
1877   AddExtension(&file_proto, "google.protobuf.FieldOptions", "option1", 1000,
1878                FieldDescriptorProto::LABEL_OPTIONAL,
1879                FieldDescriptorProto::TYPE_INT32);
1880   ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
1881   // Add "bar.proto":
1882   //   import "google/protobuf/descriptor.proto";
1883   //   extend google.protobuf.FieldOptions {
1884   //     optional int32 option2 = 1000;
1885   //   }
1886   file_proto.Clear();
1887   file_proto.set_name("bar.proto");
1888   file_proto.add_dependency("google/protobuf/descriptor.proto");
1889   AddExtension(&file_proto, "google.protobuf.FieldOptions", "option2", 1000,
1890                FieldDescriptorProto::LABEL_OPTIONAL,
1891                FieldDescriptorProto::TYPE_INT32);
1892   // Currently we only generate a warning for conflicting extension numbers.
1893   // TODO(xiaofeng): Change it to an error.
1894   ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
1895 }
1896 
1897 // ===================================================================
1898 
1899 // Test reserved fields.
1900 class ReservedDescriptorTest : public testing::Test {
1901  protected:
SetUp()1902   virtual void SetUp() {
1903     // Build descriptors for the following definitions:
1904     //
1905     //   message Foo {
1906     //     reserved 2, 9 to 11, 15;
1907     //     reserved "foo", "bar";
1908     //   }
1909 
1910     FileDescriptorProto foo_file;
1911     foo_file.set_name("foo.proto");
1912 
1913     DescriptorProto* foo = AddMessage(&foo_file, "Foo");
1914     AddReservedRange(foo, 2, 3);
1915     AddReservedRange(foo, 9, 12);
1916     AddReservedRange(foo, 15, 16);
1917 
1918     foo->add_reserved_name("foo");
1919     foo->add_reserved_name("bar");
1920 
1921     // Build the descriptors and get the pointers.
1922     foo_file_ = pool_.BuildFile(foo_file);
1923     ASSERT_TRUE(foo_file_ != NULL);
1924 
1925     ASSERT_EQ(1, foo_file_->message_type_count());
1926     foo_ = foo_file_->message_type(0);
1927   }
1928 
1929   DescriptorPool pool_;
1930   const FileDescriptor* foo_file_;
1931   const Descriptor* foo_;
1932 };
1933 
TEST_F(ReservedDescriptorTest,ReservedRanges)1934 TEST_F(ReservedDescriptorTest, ReservedRanges) {
1935   ASSERT_EQ(3, foo_->reserved_range_count());
1936 
1937   EXPECT_EQ(2, foo_->reserved_range(0)->start);
1938   EXPECT_EQ(3, foo_->reserved_range(0)->end);
1939 
1940   EXPECT_EQ(9, foo_->reserved_range(1)->start);
1941   EXPECT_EQ(12, foo_->reserved_range(1)->end);
1942 
1943   EXPECT_EQ(15, foo_->reserved_range(2)->start);
1944   EXPECT_EQ(16, foo_->reserved_range(2)->end);
1945 };
1946 
TEST_F(ReservedDescriptorTest,IsReservedNumber)1947 TEST_F(ReservedDescriptorTest, IsReservedNumber) {
1948   EXPECT_FALSE(foo_->IsReservedNumber(1));
1949   EXPECT_TRUE (foo_->IsReservedNumber(2));
1950   EXPECT_FALSE(foo_->IsReservedNumber(3));
1951   EXPECT_FALSE(foo_->IsReservedNumber(8));
1952   EXPECT_TRUE (foo_->IsReservedNumber(9));
1953   EXPECT_TRUE (foo_->IsReservedNumber(10));
1954   EXPECT_TRUE (foo_->IsReservedNumber(11));
1955   EXPECT_FALSE(foo_->IsReservedNumber(12));
1956   EXPECT_FALSE(foo_->IsReservedNumber(13));
1957   EXPECT_FALSE(foo_->IsReservedNumber(14));
1958   EXPECT_TRUE (foo_->IsReservedNumber(15));
1959   EXPECT_FALSE(foo_->IsReservedNumber(16));
1960 };
1961 
TEST_F(ReservedDescriptorTest,ReservedNames)1962 TEST_F(ReservedDescriptorTest, ReservedNames) {
1963   ASSERT_EQ(2, foo_->reserved_name_count());
1964 
1965   EXPECT_EQ("foo", foo_->reserved_name(0));
1966   EXPECT_EQ("bar", foo_->reserved_name(1));
1967 };
1968 
TEST_F(ReservedDescriptorTest,IsReservedName)1969 TEST_F(ReservedDescriptorTest, IsReservedName) {
1970   EXPECT_TRUE (foo_->IsReservedName("foo"));
1971   EXPECT_TRUE (foo_->IsReservedName("bar"));
1972   EXPECT_FALSE(foo_->IsReservedName("baz"));
1973 };
1974 
1975 // ===================================================================
1976 
1977 class MiscTest : public testing::Test {
1978  protected:
1979   // Function which makes a field descriptor of the given type.
GetFieldDescriptorOfType(FieldDescriptor::Type type)1980   const FieldDescriptor* GetFieldDescriptorOfType(FieldDescriptor::Type type) {
1981     FileDescriptorProto file_proto;
1982     file_proto.set_name("foo.proto");
1983     AddEmptyEnum(&file_proto, "DummyEnum");
1984 
1985     DescriptorProto* message = AddMessage(&file_proto, "TestMessage");
1986     FieldDescriptorProto* field =
1987       AddField(message, "foo", 1, FieldDescriptorProto::LABEL_OPTIONAL,
1988                static_cast<FieldDescriptorProto::Type>(static_cast<int>(type)));
1989 
1990     if (type == FieldDescriptor::TYPE_MESSAGE ||
1991         type == FieldDescriptor::TYPE_GROUP) {
1992       field->set_type_name("TestMessage");
1993     } else if (type == FieldDescriptor::TYPE_ENUM) {
1994       field->set_type_name("DummyEnum");
1995     }
1996 
1997     // Build the descriptors and get the pointers.
1998     pool_.reset(new DescriptorPool());
1999     const FileDescriptor* file = pool_->BuildFile(file_proto);
2000 
2001     if (file != NULL &&
2002         file->message_type_count() == 1 &&
2003         file->message_type(0)->field_count() == 1) {
2004       return file->message_type(0)->field(0);
2005     } else {
2006       return NULL;
2007     }
2008   }
2009 
GetTypeNameForFieldType(FieldDescriptor::Type type)2010   const char* GetTypeNameForFieldType(FieldDescriptor::Type type) {
2011     const FieldDescriptor* field = GetFieldDescriptorOfType(type);
2012     return field != NULL ? field->type_name() : "";
2013   }
2014 
GetCppTypeForFieldType(FieldDescriptor::Type type)2015   FieldDescriptor::CppType GetCppTypeForFieldType(FieldDescriptor::Type type) {
2016     const FieldDescriptor* field = GetFieldDescriptorOfType(type);
2017     return field != NULL ? field->cpp_type() :
2018         static_cast<FieldDescriptor::CppType>(0);
2019   }
2020 
GetCppTypeNameForFieldType(FieldDescriptor::Type type)2021   const char* GetCppTypeNameForFieldType(FieldDescriptor::Type type) {
2022     const FieldDescriptor* field = GetFieldDescriptorOfType(type);
2023     return field != NULL ? field->cpp_type_name() : "";
2024   }
2025 
GetMessageDescriptorForFieldType(FieldDescriptor::Type type)2026   const Descriptor* GetMessageDescriptorForFieldType(
2027       FieldDescriptor::Type type) {
2028     const FieldDescriptor* field = GetFieldDescriptorOfType(type);
2029     return field != NULL ? field->message_type() : NULL;
2030   }
2031 
GetEnumDescriptorForFieldType(FieldDescriptor::Type type)2032   const EnumDescriptor* GetEnumDescriptorForFieldType(
2033     FieldDescriptor::Type type) {
2034     const FieldDescriptor* field = GetFieldDescriptorOfType(type);
2035     return field != NULL ? field->enum_type() : NULL;
2036   }
2037 
2038   google::protobuf::scoped_ptr<DescriptorPool> pool_;
2039 };
2040 
TEST_F(MiscTest,TypeNames)2041 TEST_F(MiscTest, TypeNames) {
2042   // Test that correct type names are returned.
2043 
2044   typedef FieldDescriptor FD;  // avoid ugly line wrapping
2045 
2046   EXPECT_STREQ("double"  , GetTypeNameForFieldType(FD::TYPE_DOUBLE  ));
2047   EXPECT_STREQ("float"   , GetTypeNameForFieldType(FD::TYPE_FLOAT   ));
2048   EXPECT_STREQ("int64"   , GetTypeNameForFieldType(FD::TYPE_INT64   ));
2049   EXPECT_STREQ("uint64"  , GetTypeNameForFieldType(FD::TYPE_UINT64  ));
2050   EXPECT_STREQ("int32"   , GetTypeNameForFieldType(FD::TYPE_INT32   ));
2051   EXPECT_STREQ("fixed64" , GetTypeNameForFieldType(FD::TYPE_FIXED64 ));
2052   EXPECT_STREQ("fixed32" , GetTypeNameForFieldType(FD::TYPE_FIXED32 ));
2053   EXPECT_STREQ("bool"    , GetTypeNameForFieldType(FD::TYPE_BOOL    ));
2054   EXPECT_STREQ("string"  , GetTypeNameForFieldType(FD::TYPE_STRING  ));
2055   EXPECT_STREQ("group"   , GetTypeNameForFieldType(FD::TYPE_GROUP   ));
2056   EXPECT_STREQ("message" , GetTypeNameForFieldType(FD::TYPE_MESSAGE ));
2057   EXPECT_STREQ("bytes"   , GetTypeNameForFieldType(FD::TYPE_BYTES   ));
2058   EXPECT_STREQ("uint32"  , GetTypeNameForFieldType(FD::TYPE_UINT32  ));
2059   EXPECT_STREQ("enum"    , GetTypeNameForFieldType(FD::TYPE_ENUM    ));
2060   EXPECT_STREQ("sfixed32", GetTypeNameForFieldType(FD::TYPE_SFIXED32));
2061   EXPECT_STREQ("sfixed64", GetTypeNameForFieldType(FD::TYPE_SFIXED64));
2062   EXPECT_STREQ("sint32"  , GetTypeNameForFieldType(FD::TYPE_SINT32  ));
2063   EXPECT_STREQ("sint64"  , GetTypeNameForFieldType(FD::TYPE_SINT64  ));
2064 }
2065 
TEST_F(MiscTest,StaticTypeNames)2066 TEST_F(MiscTest, StaticTypeNames) {
2067   // Test that correct type names are returned.
2068 
2069   typedef FieldDescriptor FD;  // avoid ugly line wrapping
2070 
2071   EXPECT_STREQ("double"  , FD::TypeName(FD::TYPE_DOUBLE  ));
2072   EXPECT_STREQ("float"   , FD::TypeName(FD::TYPE_FLOAT   ));
2073   EXPECT_STREQ("int64"   , FD::TypeName(FD::TYPE_INT64   ));
2074   EXPECT_STREQ("uint64"  , FD::TypeName(FD::TYPE_UINT64  ));
2075   EXPECT_STREQ("int32"   , FD::TypeName(FD::TYPE_INT32   ));
2076   EXPECT_STREQ("fixed64" , FD::TypeName(FD::TYPE_FIXED64 ));
2077   EXPECT_STREQ("fixed32" , FD::TypeName(FD::TYPE_FIXED32 ));
2078   EXPECT_STREQ("bool"    , FD::TypeName(FD::TYPE_BOOL    ));
2079   EXPECT_STREQ("string"  , FD::TypeName(FD::TYPE_STRING  ));
2080   EXPECT_STREQ("group"   , FD::TypeName(FD::TYPE_GROUP   ));
2081   EXPECT_STREQ("message" , FD::TypeName(FD::TYPE_MESSAGE ));
2082   EXPECT_STREQ("bytes"   , FD::TypeName(FD::TYPE_BYTES   ));
2083   EXPECT_STREQ("uint32"  , FD::TypeName(FD::TYPE_UINT32  ));
2084   EXPECT_STREQ("enum"    , FD::TypeName(FD::TYPE_ENUM    ));
2085   EXPECT_STREQ("sfixed32", FD::TypeName(FD::TYPE_SFIXED32));
2086   EXPECT_STREQ("sfixed64", FD::TypeName(FD::TYPE_SFIXED64));
2087   EXPECT_STREQ("sint32"  , FD::TypeName(FD::TYPE_SINT32  ));
2088   EXPECT_STREQ("sint64"  , FD::TypeName(FD::TYPE_SINT64  ));
2089 }
2090 
TEST_F(MiscTest,CppTypes)2091 TEST_F(MiscTest, CppTypes) {
2092   // Test that CPP types are assigned correctly.
2093 
2094   typedef FieldDescriptor FD;  // avoid ugly line wrapping
2095 
2096   EXPECT_EQ(FD::CPPTYPE_DOUBLE , GetCppTypeForFieldType(FD::TYPE_DOUBLE  ));
2097   EXPECT_EQ(FD::CPPTYPE_FLOAT  , GetCppTypeForFieldType(FD::TYPE_FLOAT   ));
2098   EXPECT_EQ(FD::CPPTYPE_INT64  , GetCppTypeForFieldType(FD::TYPE_INT64   ));
2099   EXPECT_EQ(FD::CPPTYPE_UINT64 , GetCppTypeForFieldType(FD::TYPE_UINT64  ));
2100   EXPECT_EQ(FD::CPPTYPE_INT32  , GetCppTypeForFieldType(FD::TYPE_INT32   ));
2101   EXPECT_EQ(FD::CPPTYPE_UINT64 , GetCppTypeForFieldType(FD::TYPE_FIXED64 ));
2102   EXPECT_EQ(FD::CPPTYPE_UINT32 , GetCppTypeForFieldType(FD::TYPE_FIXED32 ));
2103   EXPECT_EQ(FD::CPPTYPE_BOOL   , GetCppTypeForFieldType(FD::TYPE_BOOL    ));
2104   EXPECT_EQ(FD::CPPTYPE_STRING , GetCppTypeForFieldType(FD::TYPE_STRING  ));
2105   EXPECT_EQ(FD::CPPTYPE_MESSAGE, GetCppTypeForFieldType(FD::TYPE_GROUP   ));
2106   EXPECT_EQ(FD::CPPTYPE_MESSAGE, GetCppTypeForFieldType(FD::TYPE_MESSAGE ));
2107   EXPECT_EQ(FD::CPPTYPE_STRING , GetCppTypeForFieldType(FD::TYPE_BYTES   ));
2108   EXPECT_EQ(FD::CPPTYPE_UINT32 , GetCppTypeForFieldType(FD::TYPE_UINT32  ));
2109   EXPECT_EQ(FD::CPPTYPE_ENUM   , GetCppTypeForFieldType(FD::TYPE_ENUM    ));
2110   EXPECT_EQ(FD::CPPTYPE_INT32  , GetCppTypeForFieldType(FD::TYPE_SFIXED32));
2111   EXPECT_EQ(FD::CPPTYPE_INT64  , GetCppTypeForFieldType(FD::TYPE_SFIXED64));
2112   EXPECT_EQ(FD::CPPTYPE_INT32  , GetCppTypeForFieldType(FD::TYPE_SINT32  ));
2113   EXPECT_EQ(FD::CPPTYPE_INT64  , GetCppTypeForFieldType(FD::TYPE_SINT64  ));
2114 }
2115 
TEST_F(MiscTest,CppTypeNames)2116 TEST_F(MiscTest, CppTypeNames) {
2117   // Test that correct CPP type names are returned.
2118 
2119   typedef FieldDescriptor FD;  // avoid ugly line wrapping
2120 
2121   EXPECT_STREQ("double" , GetCppTypeNameForFieldType(FD::TYPE_DOUBLE  ));
2122   EXPECT_STREQ("float"  , GetCppTypeNameForFieldType(FD::TYPE_FLOAT   ));
2123   EXPECT_STREQ("int64"  , GetCppTypeNameForFieldType(FD::TYPE_INT64   ));
2124   EXPECT_STREQ("uint64" , GetCppTypeNameForFieldType(FD::TYPE_UINT64  ));
2125   EXPECT_STREQ("int32"  , GetCppTypeNameForFieldType(FD::TYPE_INT32   ));
2126   EXPECT_STREQ("uint64" , GetCppTypeNameForFieldType(FD::TYPE_FIXED64 ));
2127   EXPECT_STREQ("uint32" , GetCppTypeNameForFieldType(FD::TYPE_FIXED32 ));
2128   EXPECT_STREQ("bool"   , GetCppTypeNameForFieldType(FD::TYPE_BOOL    ));
2129   EXPECT_STREQ("string" , GetCppTypeNameForFieldType(FD::TYPE_STRING  ));
2130   EXPECT_STREQ("message", GetCppTypeNameForFieldType(FD::TYPE_GROUP   ));
2131   EXPECT_STREQ("message", GetCppTypeNameForFieldType(FD::TYPE_MESSAGE ));
2132   EXPECT_STREQ("string" , GetCppTypeNameForFieldType(FD::TYPE_BYTES   ));
2133   EXPECT_STREQ("uint32" , GetCppTypeNameForFieldType(FD::TYPE_UINT32  ));
2134   EXPECT_STREQ("enum"   , GetCppTypeNameForFieldType(FD::TYPE_ENUM    ));
2135   EXPECT_STREQ("int32"  , GetCppTypeNameForFieldType(FD::TYPE_SFIXED32));
2136   EXPECT_STREQ("int64"  , GetCppTypeNameForFieldType(FD::TYPE_SFIXED64));
2137   EXPECT_STREQ("int32"  , GetCppTypeNameForFieldType(FD::TYPE_SINT32  ));
2138   EXPECT_STREQ("int64"  , GetCppTypeNameForFieldType(FD::TYPE_SINT64  ));
2139 }
2140 
TEST_F(MiscTest,StaticCppTypeNames)2141 TEST_F(MiscTest, StaticCppTypeNames) {
2142   // Test that correct CPP type names are returned.
2143 
2144   typedef FieldDescriptor FD;  // avoid ugly line wrapping
2145 
2146   EXPECT_STREQ("int32"  , FD::CppTypeName(FD::CPPTYPE_INT32  ));
2147   EXPECT_STREQ("int64"  , FD::CppTypeName(FD::CPPTYPE_INT64  ));
2148   EXPECT_STREQ("uint32" , FD::CppTypeName(FD::CPPTYPE_UINT32 ));
2149   EXPECT_STREQ("uint64" , FD::CppTypeName(FD::CPPTYPE_UINT64 ));
2150   EXPECT_STREQ("double" , FD::CppTypeName(FD::CPPTYPE_DOUBLE ));
2151   EXPECT_STREQ("float"  , FD::CppTypeName(FD::CPPTYPE_FLOAT  ));
2152   EXPECT_STREQ("bool"   , FD::CppTypeName(FD::CPPTYPE_BOOL   ));
2153   EXPECT_STREQ("enum"   , FD::CppTypeName(FD::CPPTYPE_ENUM   ));
2154   EXPECT_STREQ("string" , FD::CppTypeName(FD::CPPTYPE_STRING ));
2155   EXPECT_STREQ("message", FD::CppTypeName(FD::CPPTYPE_MESSAGE));
2156 }
2157 
TEST_F(MiscTest,MessageType)2158 TEST_F(MiscTest, MessageType) {
2159   // Test that message_type() is NULL for non-aggregate fields
2160 
2161   typedef FieldDescriptor FD;  // avoid ugly line wrapping
2162 
2163   EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_DOUBLE  ));
2164   EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_FLOAT   ));
2165   EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_INT64   ));
2166   EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_UINT64  ));
2167   EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_INT32   ));
2168   EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_FIXED64 ));
2169   EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_FIXED32 ));
2170   EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_BOOL    ));
2171   EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_STRING  ));
2172   EXPECT_TRUE(NULL != GetMessageDescriptorForFieldType(FD::TYPE_GROUP   ));
2173   EXPECT_TRUE(NULL != GetMessageDescriptorForFieldType(FD::TYPE_MESSAGE ));
2174   EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_BYTES   ));
2175   EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_UINT32  ));
2176   EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_ENUM    ));
2177   EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_SFIXED32));
2178   EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_SFIXED64));
2179   EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_SINT32  ));
2180   EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_SINT64  ));
2181 }
2182 
TEST_F(MiscTest,EnumType)2183 TEST_F(MiscTest, EnumType) {
2184   // Test that enum_type() is NULL for non-enum fields
2185 
2186   typedef FieldDescriptor FD;  // avoid ugly line wrapping
2187 
2188   EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_DOUBLE  ));
2189   EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_FLOAT   ));
2190   EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_INT64   ));
2191   EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_UINT64  ));
2192   EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_INT32   ));
2193   EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_FIXED64 ));
2194   EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_FIXED32 ));
2195   EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_BOOL    ));
2196   EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_STRING  ));
2197   EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_GROUP   ));
2198   EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_MESSAGE ));
2199   EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_BYTES   ));
2200   EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_UINT32  ));
2201   EXPECT_TRUE(NULL != GetEnumDescriptorForFieldType(FD::TYPE_ENUM    ));
2202   EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_SFIXED32));
2203   EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_SFIXED64));
2204   EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_SINT32  ));
2205   EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_SINT64  ));
2206 }
2207 
2208 
TEST_F(MiscTest,DefaultValues)2209 TEST_F(MiscTest, DefaultValues) {
2210   // Test that setting default values works.
2211   FileDescriptorProto file_proto;
2212   file_proto.set_name("foo.proto");
2213 
2214   EnumDescriptorProto* enum_type_proto = AddEnum(&file_proto, "DummyEnum");
2215   AddEnumValue(enum_type_proto, "A", 1);
2216   AddEnumValue(enum_type_proto, "B", 2);
2217 
2218   DescriptorProto* message_proto = AddMessage(&file_proto, "TestMessage");
2219 
2220   typedef FieldDescriptorProto FD;  // avoid ugly line wrapping
2221   const FD::Label label = FD::LABEL_OPTIONAL;
2222 
2223   // Create fields of every CPP type with default values.
2224   AddField(message_proto, "int32" , 1, label, FD::TYPE_INT32 )
2225     ->set_default_value("-1");
2226   AddField(message_proto, "int64" , 2, label, FD::TYPE_INT64 )
2227     ->set_default_value("-1000000000000");
2228   AddField(message_proto, "uint32", 3, label, FD::TYPE_UINT32)
2229     ->set_default_value("42");
2230   AddField(message_proto, "uint64", 4, label, FD::TYPE_UINT64)
2231     ->set_default_value("2000000000000");
2232   AddField(message_proto, "float" , 5, label, FD::TYPE_FLOAT )
2233     ->set_default_value("4.5");
2234   AddField(message_proto, "double", 6, label, FD::TYPE_DOUBLE)
2235     ->set_default_value("10e100");
2236   AddField(message_proto, "bool"  , 7, label, FD::TYPE_BOOL  )
2237     ->set_default_value("true");
2238   AddField(message_proto, "string", 8, label, FD::TYPE_STRING)
2239     ->set_default_value("hello");
2240   AddField(message_proto, "data"  , 9, label, FD::TYPE_BYTES )
2241     ->set_default_value("\\001\\002\\003");
2242 
2243   FieldDescriptorProto* enum_field =
2244     AddField(message_proto, "enum", 10, label, FD::TYPE_ENUM);
2245   enum_field->set_type_name("DummyEnum");
2246   enum_field->set_default_value("B");
2247 
2248   // Strings are allowed to have empty defaults.  (At one point, due to
2249   // a bug, empty defaults for strings were rejected.  Oops.)
2250   AddField(message_proto, "empty_string", 11, label, FD::TYPE_STRING)
2251     ->set_default_value("");
2252 
2253   // Add a second set of fields with implicit defalut values.
2254   AddField(message_proto, "implicit_int32" , 21, label, FD::TYPE_INT32 );
2255   AddField(message_proto, "implicit_int64" , 22, label, FD::TYPE_INT64 );
2256   AddField(message_proto, "implicit_uint32", 23, label, FD::TYPE_UINT32);
2257   AddField(message_proto, "implicit_uint64", 24, label, FD::TYPE_UINT64);
2258   AddField(message_proto, "implicit_float" , 25, label, FD::TYPE_FLOAT );
2259   AddField(message_proto, "implicit_double", 26, label, FD::TYPE_DOUBLE);
2260   AddField(message_proto, "implicit_bool"  , 27, label, FD::TYPE_BOOL  );
2261   AddField(message_proto, "implicit_string", 28, label, FD::TYPE_STRING);
2262   AddField(message_proto, "implicit_data"  , 29, label, FD::TYPE_BYTES );
2263   AddField(message_proto, "implicit_enum"  , 30, label, FD::TYPE_ENUM)
2264     ->set_type_name("DummyEnum");
2265 
2266   // Build it.
2267   DescriptorPool pool;
2268   const FileDescriptor* file = pool.BuildFile(file_proto);
2269   ASSERT_TRUE(file != NULL);
2270 
2271   ASSERT_EQ(1, file->enum_type_count());
2272   const EnumDescriptor* enum_type = file->enum_type(0);
2273   ASSERT_EQ(2, enum_type->value_count());
2274   const EnumValueDescriptor* enum_value_a = enum_type->value(0);
2275   const EnumValueDescriptor* enum_value_b = enum_type->value(1);
2276 
2277   ASSERT_EQ(1, file->message_type_count());
2278   const Descriptor* message = file->message_type(0);
2279 
2280   ASSERT_EQ(21, message->field_count());
2281 
2282   // Check the default values.
2283   ASSERT_TRUE(message->field(0)->has_default_value());
2284   ASSERT_TRUE(message->field(1)->has_default_value());
2285   ASSERT_TRUE(message->field(2)->has_default_value());
2286   ASSERT_TRUE(message->field(3)->has_default_value());
2287   ASSERT_TRUE(message->field(4)->has_default_value());
2288   ASSERT_TRUE(message->field(5)->has_default_value());
2289   ASSERT_TRUE(message->field(6)->has_default_value());
2290   ASSERT_TRUE(message->field(7)->has_default_value());
2291   ASSERT_TRUE(message->field(8)->has_default_value());
2292   ASSERT_TRUE(message->field(9)->has_default_value());
2293   ASSERT_TRUE(message->field(10)->has_default_value());
2294 
2295   EXPECT_EQ(-1              , message->field(0)->default_value_int32 ());
2296   EXPECT_EQ(-GOOGLE_ULONGLONG(1000000000000),
2297             message->field(1)->default_value_int64 ());
2298   EXPECT_EQ(42              , message->field(2)->default_value_uint32());
2299   EXPECT_EQ(GOOGLE_ULONGLONG(2000000000000),
2300             message->field(3)->default_value_uint64());
2301   EXPECT_EQ(4.5             , message->field(4)->default_value_float ());
2302   EXPECT_EQ(10e100          , message->field(5)->default_value_double());
2303   EXPECT_TRUE(                message->field(6)->default_value_bool  ());
2304   EXPECT_EQ("hello"         , message->field(7)->default_value_string());
2305   EXPECT_EQ("\001\002\003"  , message->field(8)->default_value_string());
2306   EXPECT_EQ(enum_value_b    , message->field(9)->default_value_enum  ());
2307   EXPECT_EQ(""              , message->field(10)->default_value_string());
2308 
2309   ASSERT_FALSE(message->field(11)->has_default_value());
2310   ASSERT_FALSE(message->field(12)->has_default_value());
2311   ASSERT_FALSE(message->field(13)->has_default_value());
2312   ASSERT_FALSE(message->field(14)->has_default_value());
2313   ASSERT_FALSE(message->field(15)->has_default_value());
2314   ASSERT_FALSE(message->field(16)->has_default_value());
2315   ASSERT_FALSE(message->field(17)->has_default_value());
2316   ASSERT_FALSE(message->field(18)->has_default_value());
2317   ASSERT_FALSE(message->field(19)->has_default_value());
2318   ASSERT_FALSE(message->field(20)->has_default_value());
2319 
2320   EXPECT_EQ(0    , message->field(11)->default_value_int32 ());
2321   EXPECT_EQ(0    , message->field(12)->default_value_int64 ());
2322   EXPECT_EQ(0    , message->field(13)->default_value_uint32());
2323   EXPECT_EQ(0    , message->field(14)->default_value_uint64());
2324   EXPECT_EQ(0.0f , message->field(15)->default_value_float ());
2325   EXPECT_EQ(0.0  , message->field(16)->default_value_double());
2326   EXPECT_FALSE(    message->field(17)->default_value_bool  ());
2327   EXPECT_EQ(""   , message->field(18)->default_value_string());
2328   EXPECT_EQ(""   , message->field(19)->default_value_string());
2329   EXPECT_EQ(enum_value_a, message->field(20)->default_value_enum());
2330 }
2331 
TEST_F(MiscTest,FieldOptions)2332 TEST_F(MiscTest, FieldOptions) {
2333   // Try setting field options.
2334 
2335   FileDescriptorProto file_proto;
2336   file_proto.set_name("foo.proto");
2337 
2338   DescriptorProto* message_proto = AddMessage(&file_proto, "TestMessage");
2339   AddField(message_proto, "foo", 1,
2340            FieldDescriptorProto::LABEL_OPTIONAL,
2341            FieldDescriptorProto::TYPE_INT32);
2342   FieldDescriptorProto* bar_proto =
2343     AddField(message_proto, "bar", 2,
2344              FieldDescriptorProto::LABEL_OPTIONAL,
2345              FieldDescriptorProto::TYPE_INT32);
2346 
2347   FieldOptions* options = bar_proto->mutable_options();
2348   options->set_ctype(FieldOptions::CORD);
2349 
2350   // Build the descriptors and get the pointers.
2351   DescriptorPool pool;
2352   const FileDescriptor* file = pool.BuildFile(file_proto);
2353   ASSERT_TRUE(file != NULL);
2354 
2355   ASSERT_EQ(1, file->message_type_count());
2356   const Descriptor* message = file->message_type(0);
2357 
2358   ASSERT_EQ(2, message->field_count());
2359   const FieldDescriptor* foo = message->field(0);
2360   const FieldDescriptor* bar = message->field(1);
2361 
2362   // "foo" had no options set, so it should return the default options.
2363   EXPECT_EQ(&FieldOptions::default_instance(), &foo->options());
2364 
2365   // "bar" had options set.
2366   EXPECT_NE(&FieldOptions::default_instance(), options);
2367   EXPECT_TRUE(bar->options().has_ctype());
2368   EXPECT_EQ(FieldOptions::CORD, bar->options().ctype());
2369 }
2370 
2371 // ===================================================================
2372 enum DescriptorPoolMode {
2373   NO_DATABASE,
2374   FALLBACK_DATABASE
2375 };
2376 
2377 class AllowUnknownDependenciesTest
2378     : public testing::TestWithParam<DescriptorPoolMode> {
2379  protected:
mode()2380   DescriptorPoolMode mode() {
2381     return GetParam();
2382    }
2383 
SetUp()2384   virtual void SetUp() {
2385     FileDescriptorProto foo_proto, bar_proto;
2386 
2387     switch (mode()) {
2388       case NO_DATABASE:
2389         pool_.reset(new DescriptorPool);
2390         break;
2391       case FALLBACK_DATABASE:
2392         pool_.reset(new DescriptorPool(&db_));
2393         break;
2394     }
2395 
2396     pool_->AllowUnknownDependencies();
2397 
2398     ASSERT_TRUE(TextFormat::ParseFromString(
2399       "name: 'foo.proto'"
2400       "dependency: 'bar.proto'"
2401       "dependency: 'baz.proto'"
2402       "message_type {"
2403       "  name: 'Foo'"
2404       "  field { name:'bar' number:1 label:LABEL_OPTIONAL type_name:'Bar' }"
2405       "  field { name:'baz' number:2 label:LABEL_OPTIONAL type_name:'Baz' }"
2406       "  field { name:'qux' number:3 label:LABEL_OPTIONAL"
2407       "    type_name: '.corge.Qux'"
2408       "    type: TYPE_ENUM"
2409       "    options {"
2410       "      uninterpreted_option {"
2411       "        name {"
2412       "          name_part: 'grault'"
2413       "          is_extension: true"
2414       "        }"
2415       "        positive_int_value: 1234"
2416       "      }"
2417       "    }"
2418       "  }"
2419       "}",
2420       &foo_proto));
2421     ASSERT_TRUE(TextFormat::ParseFromString(
2422       "name: 'bar.proto'"
2423       "message_type { name: 'Bar' }",
2424       &bar_proto));
2425 
2426     // Collect pointers to stuff.
2427     bar_file_ = BuildFile(bar_proto);
2428     ASSERT_TRUE(bar_file_ != NULL);
2429 
2430     ASSERT_EQ(1, bar_file_->message_type_count());
2431     bar_type_ = bar_file_->message_type(0);
2432 
2433     foo_file_ = BuildFile(foo_proto);
2434     ASSERT_TRUE(foo_file_ != NULL);
2435 
2436     ASSERT_EQ(1, foo_file_->message_type_count());
2437     foo_type_ = foo_file_->message_type(0);
2438 
2439     ASSERT_EQ(3, foo_type_->field_count());
2440     bar_field_ = foo_type_->field(0);
2441     baz_field_ = foo_type_->field(1);
2442     qux_field_ = foo_type_->field(2);
2443   }
2444 
BuildFile(const FileDescriptorProto & proto)2445   const FileDescriptor* BuildFile(const FileDescriptorProto& proto) {
2446     switch (mode()) {
2447       case NO_DATABASE:
2448         return pool_->BuildFile(proto);
2449         break;
2450       case FALLBACK_DATABASE: {
2451         EXPECT_TRUE(db_.Add(proto));
2452         return pool_->FindFileByName(proto.name());
2453       }
2454     }
2455     GOOGLE_LOG(FATAL) << "Can't get here.";
2456     return NULL;
2457   }
2458 
2459   const FileDescriptor* bar_file_;
2460   const Descriptor* bar_type_;
2461   const FileDescriptor* foo_file_;
2462   const Descriptor* foo_type_;
2463   const FieldDescriptor* bar_field_;
2464   const FieldDescriptor* baz_field_;
2465   const FieldDescriptor* qux_field_;
2466 
2467   SimpleDescriptorDatabase db_;        // used if in FALLBACK_DATABASE mode.
2468   google::protobuf::scoped_ptr<DescriptorPool> pool_;
2469 };
2470 
TEST_P(AllowUnknownDependenciesTest,PlaceholderFile)2471 TEST_P(AllowUnknownDependenciesTest, PlaceholderFile) {
2472   ASSERT_EQ(2, foo_file_->dependency_count());
2473   EXPECT_EQ(bar_file_, foo_file_->dependency(0));
2474   EXPECT_FALSE(bar_file_->is_placeholder());
2475 
2476   const FileDescriptor* baz_file = foo_file_->dependency(1);
2477   EXPECT_EQ("baz.proto", baz_file->name());
2478   EXPECT_EQ(0, baz_file->message_type_count());
2479   EXPECT_TRUE(baz_file->is_placeholder());
2480 
2481   // Placeholder files should not be findable.
2482   EXPECT_EQ(bar_file_, pool_->FindFileByName(bar_file_->name()));
2483   EXPECT_TRUE(pool_->FindFileByName(baz_file->name()) == NULL);
2484 
2485   // Copy*To should not crash for placeholder files.
2486   FileDescriptorProto baz_file_proto;
2487   baz_file->CopyTo(&baz_file_proto);
2488   baz_file->CopySourceCodeInfoTo(&baz_file_proto);
2489   EXPECT_FALSE(baz_file_proto.has_source_code_info());
2490 }
2491 
TEST_P(AllowUnknownDependenciesTest,PlaceholderTypes)2492 TEST_P(AllowUnknownDependenciesTest, PlaceholderTypes) {
2493   ASSERT_EQ(FieldDescriptor::TYPE_MESSAGE, bar_field_->type());
2494   EXPECT_EQ(bar_type_, bar_field_->message_type());
2495   EXPECT_FALSE(bar_type_->is_placeholder());
2496 
2497   ASSERT_EQ(FieldDescriptor::TYPE_MESSAGE, baz_field_->type());
2498   const Descriptor* baz_type = baz_field_->message_type();
2499   EXPECT_EQ("Baz", baz_type->name());
2500   EXPECT_EQ("Baz", baz_type->full_name());
2501   EXPECT_EQ(0, baz_type->extension_range_count());
2502   EXPECT_TRUE(baz_type->is_placeholder());
2503 
2504   ASSERT_EQ(FieldDescriptor::TYPE_ENUM, qux_field_->type());
2505   const EnumDescriptor* qux_type = qux_field_->enum_type();
2506   EXPECT_EQ("Qux", qux_type->name());
2507   EXPECT_EQ("corge.Qux", qux_type->full_name());
2508   EXPECT_TRUE(qux_type->is_placeholder());
2509 
2510   // Placeholder types should not be findable.
2511   EXPECT_EQ(bar_type_, pool_->FindMessageTypeByName(bar_type_->full_name()));
2512   EXPECT_TRUE(pool_->FindMessageTypeByName(baz_type->full_name()) == NULL);
2513   EXPECT_TRUE(pool_->FindEnumTypeByName(qux_type->full_name()) == NULL);
2514 }
2515 
TEST_P(AllowUnknownDependenciesTest,CopyTo)2516 TEST_P(AllowUnknownDependenciesTest, CopyTo) {
2517   // FieldDescriptor::CopyTo() should write non-fully-qualified type names
2518   // for placeholder types which were not originally fully-qualified.
2519   FieldDescriptorProto proto;
2520 
2521   // Bar is not a placeholder, so it is fully-qualified.
2522   bar_field_->CopyTo(&proto);
2523   EXPECT_EQ(".Bar", proto.type_name());
2524   EXPECT_EQ(FieldDescriptorProto::TYPE_MESSAGE, proto.type());
2525 
2526   // Baz is an unqualified placeholder.
2527   proto.Clear();
2528   baz_field_->CopyTo(&proto);
2529   EXPECT_EQ("Baz", proto.type_name());
2530   EXPECT_FALSE(proto.has_type());
2531 
2532   // Qux is a fully-qualified placeholder.
2533   proto.Clear();
2534   qux_field_->CopyTo(&proto);
2535   EXPECT_EQ(".corge.Qux", proto.type_name());
2536   EXPECT_EQ(FieldDescriptorProto::TYPE_ENUM, proto.type());
2537 }
2538 
TEST_P(AllowUnknownDependenciesTest,CustomOptions)2539 TEST_P(AllowUnknownDependenciesTest, CustomOptions) {
2540   // Qux should still have the uninterpreted option attached.
2541   ASSERT_EQ(1, qux_field_->options().uninterpreted_option_size());
2542   const UninterpretedOption& option =
2543     qux_field_->options().uninterpreted_option(0);
2544   ASSERT_EQ(1, option.name_size());
2545   EXPECT_EQ("grault", option.name(0).name_part());
2546 }
2547 
TEST_P(AllowUnknownDependenciesTest,UnknownExtendee)2548 TEST_P(AllowUnknownDependenciesTest, UnknownExtendee) {
2549   // Test that we can extend an unknown type.  This is slightly tricky because
2550   // it means that the placeholder type must have an extension range.
2551 
2552   FileDescriptorProto extension_proto;
2553 
2554   ASSERT_TRUE(TextFormat::ParseFromString(
2555     "name: 'extension.proto'"
2556     "extension { extendee: 'UnknownType' name:'some_extension' number:123"
2557     "            label:LABEL_OPTIONAL type:TYPE_INT32 }",
2558     &extension_proto));
2559   const FileDescriptor* file = BuildFile(extension_proto);
2560 
2561   ASSERT_TRUE(file != NULL);
2562 
2563   ASSERT_EQ(1, file->extension_count());
2564   const Descriptor* extendee = file->extension(0)->containing_type();
2565   EXPECT_EQ("UnknownType", extendee->name());
2566   EXPECT_TRUE(extendee->is_placeholder());
2567   ASSERT_EQ(1, extendee->extension_range_count());
2568   EXPECT_EQ(1, extendee->extension_range(0)->start);
2569   EXPECT_EQ(FieldDescriptor::kMaxNumber + 1, extendee->extension_range(0)->end);
2570 }
2571 
TEST_P(AllowUnknownDependenciesTest,CustomOption)2572 TEST_P(AllowUnknownDependenciesTest, CustomOption) {
2573   // Test that we can use a custom option without having parsed
2574   // descriptor.proto.
2575 
2576   FileDescriptorProto option_proto;
2577 
2578   ASSERT_TRUE(TextFormat::ParseFromString(
2579     "name: \"unknown_custom_options.proto\" "
2580     "dependency: \"google/protobuf/descriptor.proto\" "
2581     "extension { "
2582     "  extendee: \"google.protobuf.FileOptions\" "
2583     "  name: \"some_option\" "
2584     "  number: 123456 "
2585     "  label: LABEL_OPTIONAL "
2586     "  type: TYPE_INT32 "
2587     "} "
2588     "options { "
2589     "  uninterpreted_option { "
2590     "    name { "
2591     "      name_part: \"some_option\" "
2592     "      is_extension: true "
2593     "    } "
2594     "    positive_int_value: 1234 "
2595     "  } "
2596     "  uninterpreted_option { "
2597     "    name { "
2598     "      name_part: \"unknown_option\" "
2599     "      is_extension: true "
2600     "    } "
2601     "    positive_int_value: 1234 "
2602     "  } "
2603     "  uninterpreted_option { "
2604     "    name { "
2605     "      name_part: \"optimize_for\" "
2606     "      is_extension: false "
2607     "    } "
2608     "    identifier_value: \"SPEED\" "
2609     "  } "
2610     "}",
2611     &option_proto));
2612 
2613   const FileDescriptor* file = BuildFile(option_proto);
2614   ASSERT_TRUE(file != NULL);
2615 
2616   // Verify that no extension options were set, but they were left as
2617   // uninterpreted_options.
2618   vector<const FieldDescriptor*> fields;
2619   file->options().GetReflection()->ListFields(file->options(), &fields);
2620   ASSERT_EQ(2, fields.size());
2621   EXPECT_TRUE(file->options().has_optimize_for());
2622   EXPECT_EQ(2, file->options().uninterpreted_option_size());
2623 }
2624 
TEST_P(AllowUnknownDependenciesTest,UndeclaredDependencyTriggersBuildOfDependency)2625 TEST_P(AllowUnknownDependenciesTest,
2626        UndeclaredDependencyTriggersBuildOfDependency) {
2627   // Crazy case: suppose foo.proto refers to a symbol without declaring the
2628   // dependency that finds it. In the event that the pool is backed by a
2629   // DescriptorDatabase, the pool will attempt to find the symbol in the
2630   // database. If successful, it will build the undeclared dependency to verify
2631   // that the file does indeed contain the symbol. If that file fails to build,
2632   // then its descriptors must be rolled back. However, we still want foo.proto
2633   // to build successfully, since we are allowing unknown dependencies.
2634 
2635   FileDescriptorProto undeclared_dep_proto;
2636   // We make this file fail to build by giving it two fields with tag 1.
2637   ASSERT_TRUE(TextFormat::ParseFromString(
2638     "name: \"invalid_file_as_undeclared_dep.proto\" "
2639     "package: \"undeclared\" "
2640     "message_type: {  "
2641     "  name: \"Quux\"  "
2642     "  field { "
2643     "    name:'qux' number:1 label:LABEL_OPTIONAL type: TYPE_INT32 "
2644     "  }"
2645     "  field { "
2646     "    name:'quux' number:1 label:LABEL_OPTIONAL type: TYPE_INT64 "
2647     "  }"
2648     "}",
2649     &undeclared_dep_proto));
2650   // We can't use the BuildFile() helper because we don't actually want to build
2651   // it into the descriptor pool in the fallback database case: it just needs to
2652   // be sitting in the database so that it gets built during the building of
2653   // test.proto below.
2654   switch (mode()) {
2655     case NO_DATABASE: {
2656       ASSERT_TRUE(pool_->BuildFile(undeclared_dep_proto) == NULL);
2657       break;
2658     }
2659     case FALLBACK_DATABASE: {
2660       ASSERT_TRUE(db_.Add(undeclared_dep_proto));
2661     }
2662   }
2663 
2664   FileDescriptorProto test_proto;
2665   ASSERT_TRUE(TextFormat::ParseFromString(
2666     "name: \"test.proto\" "
2667     "message_type: { "
2668     "  name: \"Corge\" "
2669     "  field { "
2670     "    name:'quux' number:1 label: LABEL_OPTIONAL "
2671     "    type_name:'undeclared.Quux' type: TYPE_MESSAGE "
2672     "  }"
2673     "}",
2674     &test_proto));
2675 
2676   const FileDescriptor* file = BuildFile(test_proto);
2677   ASSERT_TRUE(file != NULL);
2678   GOOGLE_LOG(INFO) << file->DebugString();
2679 
2680   EXPECT_EQ(0, file->dependency_count());
2681   ASSERT_EQ(1, file->message_type_count());
2682   const Descriptor* corge_desc = file->message_type(0);
2683   ASSERT_EQ("Corge", corge_desc->name());
2684   ASSERT_EQ(1, corge_desc->field_count());
2685   EXPECT_FALSE(corge_desc->is_placeholder());
2686 
2687   const FieldDescriptor* quux_field = corge_desc->field(0);
2688   ASSERT_EQ(FieldDescriptor::TYPE_MESSAGE, quux_field->type());
2689   ASSERT_EQ("Quux", quux_field->message_type()->name());
2690   ASSERT_EQ("undeclared.Quux", quux_field->message_type()->full_name());
2691   EXPECT_TRUE(quux_field->message_type()->is_placeholder());
2692   // The place holder type should not be findable.
2693   ASSERT_TRUE(pool_->FindMessageTypeByName("undeclared.Quux") == NULL);
2694 }
2695 
2696 INSTANTIATE_TEST_CASE_P(DatabaseSource,
2697                         AllowUnknownDependenciesTest,
2698                         testing::Values(NO_DATABASE, FALLBACK_DATABASE));
2699 
2700 // ===================================================================
2701 
TEST(CustomOptions,OptionLocations)2702 TEST(CustomOptions, OptionLocations) {
2703   const Descriptor* message =
2704       protobuf_unittest::TestMessageWithCustomOptions::descriptor();
2705   const FileDescriptor* file = message->file();
2706   const FieldDescriptor* field = message->FindFieldByName("field1");
2707   const OneofDescriptor* oneof = message->FindOneofByName("AnOneof");
2708   const EnumDescriptor* enm = message->FindEnumTypeByName("AnEnum");
2709   // TODO(benjy): Support EnumValue options, once the compiler does.
2710   const ServiceDescriptor* service =
2711       file->FindServiceByName("TestServiceWithCustomOptions");
2712   const MethodDescriptor* method = service->FindMethodByName("Foo");
2713 
2714   EXPECT_EQ(GOOGLE_LONGLONG(9876543210),
2715             file->options().GetExtension(protobuf_unittest::file_opt1));
2716   EXPECT_EQ(-56,
2717             message->options().GetExtension(protobuf_unittest::message_opt1));
2718   EXPECT_EQ(GOOGLE_LONGLONG(8765432109),
2719             field->options().GetExtension(protobuf_unittest::field_opt1));
2720   EXPECT_EQ(42,  // Check that we get the default for an option we don't set.
2721             field->options().GetExtension(protobuf_unittest::field_opt2));
2722   EXPECT_EQ(-99,
2723             oneof->options().GetExtension(protobuf_unittest::oneof_opt1));
2724   EXPECT_EQ(-789,
2725             enm->options().GetExtension(protobuf_unittest::enum_opt1));
2726   EXPECT_EQ(123,
2727             enm->value(1)->options().GetExtension(
2728               protobuf_unittest::enum_value_opt1));
2729   EXPECT_EQ(GOOGLE_LONGLONG(-9876543210),
2730             service->options().GetExtension(protobuf_unittest::service_opt1));
2731   EXPECT_EQ(protobuf_unittest::METHODOPT1_VAL2,
2732             method->options().GetExtension(protobuf_unittest::method_opt1));
2733 
2734   // See that the regular options went through unscathed.
2735   EXPECT_TRUE(message->options().has_message_set_wire_format());
2736   EXPECT_EQ(FieldOptions::CORD, field->options().ctype());
2737 }
2738 
TEST(CustomOptions,OptionTypes)2739 TEST(CustomOptions, OptionTypes) {
2740   const MessageOptions* options = NULL;
2741 
2742   options =
2743       &protobuf_unittest::CustomOptionMinIntegerValues::descriptor()->options();
2744   EXPECT_EQ(false    , options->GetExtension(protobuf_unittest::bool_opt));
2745   EXPECT_EQ(kint32min, options->GetExtension(protobuf_unittest::int32_opt));
2746   EXPECT_EQ(kint64min, options->GetExtension(protobuf_unittest::int64_opt));
2747   EXPECT_EQ(0        , options->GetExtension(protobuf_unittest::uint32_opt));
2748   EXPECT_EQ(0        , options->GetExtension(protobuf_unittest::uint64_opt));
2749   EXPECT_EQ(kint32min, options->GetExtension(protobuf_unittest::sint32_opt));
2750   EXPECT_EQ(kint64min, options->GetExtension(protobuf_unittest::sint64_opt));
2751   EXPECT_EQ(0        , options->GetExtension(protobuf_unittest::fixed32_opt));
2752   EXPECT_EQ(0        , options->GetExtension(protobuf_unittest::fixed64_opt));
2753   EXPECT_EQ(kint32min, options->GetExtension(protobuf_unittest::sfixed32_opt));
2754   EXPECT_EQ(kint64min, options->GetExtension(protobuf_unittest::sfixed64_opt));
2755 
2756   options =
2757       &protobuf_unittest::CustomOptionMaxIntegerValues::descriptor()->options();
2758   EXPECT_EQ(true      , options->GetExtension(protobuf_unittest::bool_opt));
2759   EXPECT_EQ(kint32max , options->GetExtension(protobuf_unittest::int32_opt));
2760   EXPECT_EQ(kint64max , options->GetExtension(protobuf_unittest::int64_opt));
2761   EXPECT_EQ(kuint32max, options->GetExtension(protobuf_unittest::uint32_opt));
2762   EXPECT_EQ(kuint64max, options->GetExtension(protobuf_unittest::uint64_opt));
2763   EXPECT_EQ(kint32max , options->GetExtension(protobuf_unittest::sint32_opt));
2764   EXPECT_EQ(kint64max , options->GetExtension(protobuf_unittest::sint64_opt));
2765   EXPECT_EQ(kuint32max, options->GetExtension(protobuf_unittest::fixed32_opt));
2766   EXPECT_EQ(kuint64max, options->GetExtension(protobuf_unittest::fixed64_opt));
2767   EXPECT_EQ(kint32max , options->GetExtension(protobuf_unittest::sfixed32_opt));
2768   EXPECT_EQ(kint64max , options->GetExtension(protobuf_unittest::sfixed64_opt));
2769 
2770   options =
2771       &protobuf_unittest::CustomOptionOtherValues::descriptor()->options();
2772   EXPECT_EQ(-100, options->GetExtension(protobuf_unittest::int32_opt));
2773   EXPECT_FLOAT_EQ(12.3456789,
2774                   options->GetExtension(protobuf_unittest::float_opt));
2775   EXPECT_DOUBLE_EQ(1.234567890123456789,
2776                    options->GetExtension(protobuf_unittest::double_opt));
2777   EXPECT_EQ("Hello, \"World\"",
2778             options->GetExtension(protobuf_unittest::string_opt));
2779 
2780   EXPECT_EQ(string("Hello\0World", 11),
2781             options->GetExtension(protobuf_unittest::bytes_opt));
2782 
2783   EXPECT_EQ(protobuf_unittest::DummyMessageContainingEnum::TEST_OPTION_ENUM_TYPE2,
2784             options->GetExtension(protobuf_unittest::enum_opt));
2785 
2786   options =
2787       &protobuf_unittest::SettingRealsFromPositiveInts::descriptor()->options();
2788   EXPECT_FLOAT_EQ(12, options->GetExtension(protobuf_unittest::float_opt));
2789   EXPECT_DOUBLE_EQ(154, options->GetExtension(protobuf_unittest::double_opt));
2790 
2791   options =
2792       &protobuf_unittest::SettingRealsFromNegativeInts::descriptor()->options();
2793   EXPECT_FLOAT_EQ(-12, options->GetExtension(protobuf_unittest::float_opt));
2794   EXPECT_DOUBLE_EQ(-154, options->GetExtension(protobuf_unittest::double_opt));
2795 }
2796 
TEST(CustomOptions,ComplexExtensionOptions)2797 TEST(CustomOptions, ComplexExtensionOptions) {
2798   const MessageOptions* options =
2799       &protobuf_unittest::VariousComplexOptions::descriptor()->options();
2800   EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt1).foo(), 42);
2801   EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt1).
2802             GetExtension(protobuf_unittest::quux), 324);
2803   EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt1).
2804             GetExtension(protobuf_unittest::corge).qux(), 876);
2805   EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).baz(), 987);
2806   EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).
2807             GetExtension(protobuf_unittest::grault), 654);
2808   EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).bar().foo(),
2809             743);
2810   EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).bar().
2811             GetExtension(protobuf_unittest::quux), 1999);
2812   EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).bar().
2813             GetExtension(protobuf_unittest::corge).qux(), 2008);
2814   EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).
2815             GetExtension(protobuf_unittest::garply).foo(), 741);
2816   EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).
2817             GetExtension(protobuf_unittest::garply).
2818             GetExtension(protobuf_unittest::quux), 1998);
2819   EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).
2820             GetExtension(protobuf_unittest::garply).
2821             GetExtension(protobuf_unittest::corge).qux(), 2121);
2822   EXPECT_EQ(options->GetExtension(
2823       protobuf_unittest::ComplexOptionType2::ComplexOptionType4::complex_opt4).
2824             waldo(), 1971);
2825   EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).
2826             fred().waldo(), 321);
2827   EXPECT_EQ(9, options->GetExtension(protobuf_unittest::complex_opt3).qux());
2828   EXPECT_EQ(22, options->GetExtension(protobuf_unittest::complex_opt3).
2829                 complexoptiontype5().plugh());
2830   EXPECT_EQ(24, options->GetExtension(protobuf_unittest::complexopt6).xyzzy());
2831 }
2832 
TEST(CustomOptions,OptionsFromOtherFile)2833 TEST(CustomOptions, OptionsFromOtherFile) {
2834   // Test that to use a custom option, we only need to import the file
2835   // defining the option; we do not also have to import descriptor.proto.
2836   DescriptorPool pool;
2837 
2838   FileDescriptorProto file_proto;
2839   FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto);
2840   ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
2841 
2842   protobuf_unittest::TestMessageWithCustomOptions::descriptor()
2843     ->file()->CopyTo(&file_proto);
2844   ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
2845 
2846   ASSERT_TRUE(TextFormat::ParseFromString(
2847     "name: \"custom_options_import.proto\" "
2848     "package: \"protobuf_unittest\" "
2849     "dependency: \"google/protobuf/unittest_custom_options.proto\" "
2850     "options { "
2851     "  uninterpreted_option { "
2852     "    name { "
2853     "      name_part: \"file_opt1\" "
2854     "      is_extension: true "
2855     "    } "
2856     "    positive_int_value: 1234 "
2857     "  } "
2858     // Test a non-extension option too.  (At one point this failed due to a
2859     // bug.)
2860     "  uninterpreted_option { "
2861     "    name { "
2862     "      name_part: \"java_package\" "
2863     "      is_extension: false "
2864     "    } "
2865     "    string_value: \"foo\" "
2866     "  } "
2867     // Test that enum-typed options still work too.  (At one point this also
2868     // failed due to a bug.)
2869     "  uninterpreted_option { "
2870     "    name { "
2871     "      name_part: \"optimize_for\" "
2872     "      is_extension: false "
2873     "    } "
2874     "    identifier_value: \"SPEED\" "
2875     "  } "
2876     "}"
2877     ,
2878     &file_proto));
2879 
2880   const FileDescriptor* file = pool.BuildFile(file_proto);
2881   ASSERT_TRUE(file != NULL);
2882   EXPECT_EQ(1234, file->options().GetExtension(protobuf_unittest::file_opt1));
2883   EXPECT_TRUE(file->options().has_java_package());
2884   EXPECT_EQ("foo", file->options().java_package());
2885   EXPECT_TRUE(file->options().has_optimize_for());
2886   EXPECT_EQ(FileOptions::SPEED, file->options().optimize_for());
2887 }
2888 
TEST(CustomOptions,MessageOptionThreeFieldsSet)2889 TEST(CustomOptions, MessageOptionThreeFieldsSet) {
2890   // This tests a bug which previously existed in custom options parsing.  The
2891   // bug occurred when you defined a custom option with message type and then
2892   // set three fields of that option on a single definition (see the example
2893   // below).  The bug is a bit hard to explain, so check the change history if
2894   // you want to know more.
2895   DescriptorPool pool;
2896 
2897   FileDescriptorProto file_proto;
2898   FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto);
2899   ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
2900 
2901   protobuf_unittest::TestMessageWithCustomOptions::descriptor()
2902     ->file()->CopyTo(&file_proto);
2903   ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
2904 
2905   // The following represents the definition:
2906   //
2907   //   import "google/protobuf/unittest_custom_options.proto"
2908   //   package protobuf_unittest;
2909   //   message Foo {
2910   //     option (complex_opt1).foo  = 1234;
2911   //     option (complex_opt1).foo2 = 1234;
2912   //     option (complex_opt1).foo3 = 1234;
2913   //   }
2914   ASSERT_TRUE(TextFormat::ParseFromString(
2915     "name: \"custom_options_import.proto\" "
2916     "package: \"protobuf_unittest\" "
2917     "dependency: \"google/protobuf/unittest_custom_options.proto\" "
2918     "message_type { "
2919     "  name: \"Foo\" "
2920     "  options { "
2921     "    uninterpreted_option { "
2922     "      name { "
2923     "        name_part: \"complex_opt1\" "
2924     "        is_extension: true "
2925     "      } "
2926     "      name { "
2927     "        name_part: \"foo\" "
2928     "        is_extension: false "
2929     "      } "
2930     "      positive_int_value: 1234 "
2931     "    } "
2932     "    uninterpreted_option { "
2933     "      name { "
2934     "        name_part: \"complex_opt1\" "
2935     "        is_extension: true "
2936     "      } "
2937     "      name { "
2938     "        name_part: \"foo2\" "
2939     "        is_extension: false "
2940     "      } "
2941     "      positive_int_value: 1234 "
2942     "    } "
2943     "    uninterpreted_option { "
2944     "      name { "
2945     "        name_part: \"complex_opt1\" "
2946     "        is_extension: true "
2947     "      } "
2948     "      name { "
2949     "        name_part: \"foo3\" "
2950     "        is_extension: false "
2951     "      } "
2952     "      positive_int_value: 1234 "
2953     "    } "
2954     "  } "
2955     "}",
2956     &file_proto));
2957 
2958   const FileDescriptor* file = pool.BuildFile(file_proto);
2959   ASSERT_TRUE(file != NULL);
2960   ASSERT_EQ(1, file->message_type_count());
2961 
2962   const MessageOptions& options = file->message_type(0)->options();
2963   EXPECT_EQ(1234, options.GetExtension(protobuf_unittest::complex_opt1).foo());
2964 }
2965 
TEST(CustomOptions,MessageOptionRepeatedLeafFieldSet)2966 TEST(CustomOptions, MessageOptionRepeatedLeafFieldSet) {
2967   // This test verifies that repeated fields in custom options can be
2968   // given multiple values by repeating the option with a different value.
2969   // This test checks repeated leaf values. Each repeated custom value
2970   // appears in a different uninterpreted_option, which will be concatenated
2971   // when they are merged into the final option value.
2972   DescriptorPool pool;
2973 
2974   FileDescriptorProto file_proto;
2975   FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto);
2976   ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
2977 
2978   protobuf_unittest::TestMessageWithCustomOptions::descriptor()
2979     ->file()->CopyTo(&file_proto);
2980   ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
2981 
2982   // The following represents the definition:
2983   //
2984   //   import "google/protobuf/unittest_custom_options.proto"
2985   //   package protobuf_unittest;
2986   //   message Foo {
2987   //     option (complex_opt1).foo4 = 12;
2988   //     option (complex_opt1).foo4 = 34;
2989   //     option (complex_opt1).foo4 = 56;
2990   //   }
2991   ASSERT_TRUE(TextFormat::ParseFromString(
2992     "name: \"custom_options_import.proto\" "
2993     "package: \"protobuf_unittest\" "
2994     "dependency: \"google/protobuf/unittest_custom_options.proto\" "
2995     "message_type { "
2996     "  name: \"Foo\" "
2997     "  options { "
2998     "    uninterpreted_option { "
2999     "      name { "
3000     "        name_part: \"complex_opt1\" "
3001     "        is_extension: true "
3002     "      } "
3003     "      name { "
3004     "        name_part: \"foo4\" "
3005     "        is_extension: false "
3006     "      } "
3007     "      positive_int_value: 12 "
3008     "    } "
3009     "    uninterpreted_option { "
3010     "      name { "
3011     "        name_part: \"complex_opt1\" "
3012     "        is_extension: true "
3013     "      } "
3014     "      name { "
3015     "        name_part: \"foo4\" "
3016     "        is_extension: false "
3017     "      } "
3018     "      positive_int_value: 34 "
3019     "    } "
3020     "    uninterpreted_option { "
3021     "      name { "
3022     "        name_part: \"complex_opt1\" "
3023     "        is_extension: true "
3024     "      } "
3025     "      name { "
3026     "        name_part: \"foo4\" "
3027     "        is_extension: false "
3028     "      } "
3029     "      positive_int_value: 56 "
3030     "    } "
3031     "  } "
3032     "}",
3033     &file_proto));
3034 
3035   const FileDescriptor* file = pool.BuildFile(file_proto);
3036   ASSERT_TRUE(file != NULL);
3037   ASSERT_EQ(1, file->message_type_count());
3038 
3039   const MessageOptions& options = file->message_type(0)->options();
3040   EXPECT_EQ(3, options.GetExtension(protobuf_unittest::complex_opt1).foo4_size());
3041   EXPECT_EQ(12, options.GetExtension(protobuf_unittest::complex_opt1).foo4(0));
3042   EXPECT_EQ(34, options.GetExtension(protobuf_unittest::complex_opt1).foo4(1));
3043   EXPECT_EQ(56, options.GetExtension(protobuf_unittest::complex_opt1).foo4(2));
3044 }
3045 
TEST(CustomOptions,MessageOptionRepeatedMsgFieldSet)3046 TEST(CustomOptions, MessageOptionRepeatedMsgFieldSet) {
3047   // This test verifies that repeated fields in custom options can be
3048   // given multiple values by repeating the option with a different value.
3049   // This test checks repeated message values. Each repeated custom value
3050   // appears in a different uninterpreted_option, which will be concatenated
3051   // when they are merged into the final option value.
3052   DescriptorPool pool;
3053 
3054   FileDescriptorProto file_proto;
3055   FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto);
3056   ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
3057 
3058   protobuf_unittest::TestMessageWithCustomOptions::descriptor()
3059     ->file()->CopyTo(&file_proto);
3060   ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
3061 
3062   // The following represents the definition:
3063   //
3064   //   import "google/protobuf/unittest_custom_options.proto"
3065   //   package protobuf_unittest;
3066   //   message Foo {
3067   //     option (complex_opt2).barney = {waldo: 1};
3068   //     option (complex_opt2).barney = {waldo: 10};
3069   //     option (complex_opt2).barney = {waldo: 100};
3070   //   }
3071   ASSERT_TRUE(TextFormat::ParseFromString(
3072     "name: \"custom_options_import.proto\" "
3073     "package: \"protobuf_unittest\" "
3074     "dependency: \"google/protobuf/unittest_custom_options.proto\" "
3075     "message_type { "
3076     "  name: \"Foo\" "
3077     "  options { "
3078     "    uninterpreted_option { "
3079     "      name { "
3080     "        name_part: \"complex_opt2\" "
3081     "        is_extension: true "
3082     "      } "
3083     "      name { "
3084     "        name_part: \"barney\" "
3085     "        is_extension: false "
3086     "      } "
3087     "      aggregate_value: \"waldo: 1\" "
3088     "    } "
3089     "    uninterpreted_option { "
3090     "      name { "
3091     "        name_part: \"complex_opt2\" "
3092     "        is_extension: true "
3093     "      } "
3094     "      name { "
3095     "        name_part: \"barney\" "
3096     "        is_extension: false "
3097     "      } "
3098     "      aggregate_value: \"waldo: 10\" "
3099     "    } "
3100     "    uninterpreted_option { "
3101     "      name { "
3102     "        name_part: \"complex_opt2\" "
3103     "        is_extension: true "
3104     "      } "
3105     "      name { "
3106     "        name_part: \"barney\" "
3107     "        is_extension: false "
3108     "      } "
3109     "      aggregate_value: \"waldo: 100\" "
3110     "    } "
3111     "  } "
3112     "}",
3113     &file_proto));
3114 
3115   const FileDescriptor* file = pool.BuildFile(file_proto);
3116   ASSERT_TRUE(file != NULL);
3117   ASSERT_EQ(1, file->message_type_count());
3118 
3119   const MessageOptions& options = file->message_type(0)->options();
3120   EXPECT_EQ(3, options.GetExtension(
3121       protobuf_unittest::complex_opt2).barney_size());
3122   EXPECT_EQ(1,options.GetExtension(
3123       protobuf_unittest::complex_opt2).barney(0).waldo());
3124   EXPECT_EQ(10, options.GetExtension(
3125       protobuf_unittest::complex_opt2).barney(1).waldo());
3126   EXPECT_EQ(100, options.GetExtension(
3127       protobuf_unittest::complex_opt2).barney(2).waldo());
3128 }
3129 
3130 // Check that aggregate options were parsed and saved correctly in
3131 // the appropriate descriptors.
TEST(CustomOptions,AggregateOptions)3132 TEST(CustomOptions, AggregateOptions) {
3133   const Descriptor* msg = protobuf_unittest::AggregateMessage::descriptor();
3134   const FileDescriptor* file = msg->file();
3135   const FieldDescriptor* field = msg->FindFieldByName("fieldname");
3136   const EnumDescriptor* enumd = file->FindEnumTypeByName("AggregateEnum");
3137   const EnumValueDescriptor* enumv = enumd->FindValueByName("VALUE");
3138   const ServiceDescriptor* service = file->FindServiceByName(
3139       "AggregateService");
3140   const MethodDescriptor* method = service->FindMethodByName("Method");
3141 
3142   // Tests for the different types of data embedded in fileopt
3143   const protobuf_unittest::Aggregate& file_options =
3144       file->options().GetExtension(protobuf_unittest::fileopt);
3145   EXPECT_EQ(100, file_options.i());
3146   EXPECT_EQ("FileAnnotation", file_options.s());
3147   EXPECT_EQ("NestedFileAnnotation", file_options.sub().s());
3148   EXPECT_EQ("FileExtensionAnnotation",
3149             file_options.file().GetExtension(protobuf_unittest::fileopt).s());
3150   EXPECT_EQ("EmbeddedMessageSetElement",
3151             file_options.mset().GetExtension(
3152                 protobuf_unittest::AggregateMessageSetElement
3153                 ::message_set_extension).s());
3154 
3155   // Simple tests for all the other types of annotations
3156   EXPECT_EQ("MessageAnnotation",
3157             msg->options().GetExtension(protobuf_unittest::msgopt).s());
3158   EXPECT_EQ("FieldAnnotation",
3159             field->options().GetExtension(protobuf_unittest::fieldopt).s());
3160   EXPECT_EQ("EnumAnnotation",
3161             enumd->options().GetExtension(protobuf_unittest::enumopt).s());
3162   EXPECT_EQ("EnumValueAnnotation",
3163             enumv->options().GetExtension(protobuf_unittest::enumvalopt).s());
3164   EXPECT_EQ("ServiceAnnotation",
3165             service->options().GetExtension(protobuf_unittest::serviceopt).s());
3166   EXPECT_EQ("MethodAnnotation",
3167             method->options().GetExtension(protobuf_unittest::methodopt).s());
3168 }
3169 
TEST(CustomOptions,UnusedImportWarning)3170 TEST(CustomOptions, UnusedImportWarning) {
3171   DescriptorPool pool;
3172 
3173   FileDescriptorProto file_proto;
3174   FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto);
3175   ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
3176 
3177   protobuf_unittest::TestMessageWithCustomOptions::descriptor()
3178       ->file()->CopyTo(&file_proto);
3179   ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
3180 
3181   pool.AddUnusedImportTrackFile("custom_options_import.proto");
3182   ASSERT_TRUE(TextFormat::ParseFromString(
3183     "name: \"custom_options_import.proto\" "
3184     "package: \"protobuf_unittest\" "
3185     "dependency: \"google/protobuf/unittest_custom_options.proto\" ",
3186     &file_proto));
3187 
3188   MockErrorCollector error_collector;
3189   EXPECT_TRUE(pool.BuildFileCollectingErrors(file_proto, &error_collector));
3190   EXPECT_EQ("", error_collector.warning_text_);
3191 }
3192 
3193 // Verifies that proto files can correctly be parsed, even if the
3194 // custom options defined in the file are incompatible with those
3195 // compiled in the binary. See http://b/19276250.
TEST(CustomOptions,OptionsWithRequiredEnums)3196 TEST(CustomOptions, OptionsWithRequiredEnums) {
3197   DescriptorPool pool;
3198 
3199   FileDescriptorProto file_proto;
3200   MessageOptions::descriptor()->file()->CopyTo(&file_proto);
3201   ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
3202 
3203   // Create a new file descriptor proto containing a subset of the
3204   // messages defined in google/protobuf/unittest_custom_options.proto.
3205   file_proto.Clear();
3206   file_proto.set_name("unittest_custom_options.proto");
3207   file_proto.set_package("protobuf_unittest");
3208   file_proto.add_dependency("google/protobuf/descriptor.proto");
3209 
3210   // Add the "required_enum_opt" extension.
3211   FieldDescriptorProto* extension = file_proto.add_extension();
3212   protobuf_unittest::OldOptionType::descriptor()->file()
3213       ->FindExtensionByName("required_enum_opt")->CopyTo(extension);
3214 
3215   // Add a test message that uses the "required_enum_opt" option.
3216   DescriptorProto* test_message_type = file_proto.add_message_type();
3217   protobuf_unittest::TestMessageWithRequiredEnumOption::descriptor()
3218       ->CopyTo(test_message_type);
3219 
3220   // Instruct the extension to use NewOptionType instead of
3221   // OldOptionType, and add the descriptor of NewOptionType.
3222   extension->set_type_name(".protobuf_unittest.NewOptionType");
3223   DescriptorProto* new_option_type = file_proto.add_message_type();
3224   protobuf_unittest::NewOptionType::descriptor()
3225       ->CopyTo(new_option_type);
3226 
3227   // Replace the value of the "required_enum_opt" option used in the
3228   // test message with an enum value that only exists in NewOptionType.
3229   ASSERT_TRUE(TextFormat::ParseFromString(
3230       "uninterpreted_option { "
3231       "  name { "
3232       "    name_part: 'required_enum_opt' "
3233       "    is_extension: true "
3234       "  } "
3235       "  aggregate_value: 'value: NEW_VALUE' "
3236       "}",
3237       test_message_type->mutable_options()));
3238 
3239   // Add the file descriptor to the pool.
3240   ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
3241 
3242   // Find the test message.
3243   const Descriptor* test_message = pool.FindMessageTypeByName(
3244       "protobuf_unittest.TestMessageWithRequiredEnumOption");
3245   ASSERT_TRUE(test_message != NULL);
3246 
3247   const MessageOptions& options = test_message->options();
3248   // Extract the "required_enum_opt" option. Since the binary does not
3249   // know that the extension was updated, this will still return an
3250   // OldOptionType message.
3251   ASSERT_TRUE(
3252       options.HasExtension(protobuf_unittest::required_enum_opt));
3253   const protobuf_unittest::OldOptionType& old_enum_opt =
3254       options.GetExtension(protobuf_unittest::required_enum_opt);
3255 
3256   // Confirm that the required enum field is missing.
3257   EXPECT_FALSE(old_enum_opt.IsInitialized());
3258   EXPECT_FALSE(old_enum_opt.has_value());
3259 
3260   string buf;
3261   // Verify that the required enum field does show up when the option
3262   // is re-parsed as a NewOptionType message;
3263   protobuf_unittest::NewOptionType new_enum_opt;
3264   EXPECT_TRUE(old_enum_opt.AppendPartialToString(&buf));
3265   EXPECT_TRUE(new_enum_opt.ParseFromString(buf));
3266   EXPECT_EQ(protobuf_unittest::NewOptionType::NEW_VALUE, new_enum_opt.value());
3267 }
3268 
3269 // ===================================================================
3270 
3271 class ValidationErrorTest : public testing::Test {
3272  protected:
3273   // Parse file_text as a FileDescriptorProto in text format and add it
3274   // to the DescriptorPool.  Expect no errors.
BuildFile(const string & file_text)3275   const FileDescriptor* BuildFile(const string& file_text) {
3276     FileDescriptorProto file_proto;
3277     EXPECT_TRUE(TextFormat::ParseFromString(file_text, &file_proto));
3278     return GOOGLE_CHECK_NOTNULL(pool_.BuildFile(file_proto));
3279   }
3280 
3281   // Parse file_text as a FileDescriptorProto in text format and add it
3282   // to the DescriptorPool.  Expect errors to be produced which match the
3283   // given error text.
BuildFileWithErrors(const string & file_text,const string & expected_errors)3284   void BuildFileWithErrors(const string& file_text,
3285                            const string& expected_errors) {
3286     FileDescriptorProto file_proto;
3287     ASSERT_TRUE(TextFormat::ParseFromString(file_text, &file_proto));
3288 
3289     MockErrorCollector error_collector;
3290     EXPECT_TRUE(
3291       pool_.BuildFileCollectingErrors(file_proto, &error_collector) == NULL);
3292     EXPECT_EQ(expected_errors, error_collector.text_);
3293   }
3294 
3295   // Parse file_text as a FileDescriptorProto in text format and add it
3296   // to the DescriptorPool.  Expect errors to be produced which match the
3297   // given warning text.
BuildFileWithWarnings(const string & file_text,const string & expected_warnings)3298   void BuildFileWithWarnings(const string& file_text,
3299                              const string& expected_warnings) {
3300     FileDescriptorProto file_proto;
3301     ASSERT_TRUE(TextFormat::ParseFromString(file_text, &file_proto));
3302 
3303     MockErrorCollector error_collector;
3304     EXPECT_TRUE(pool_.BuildFileCollectingErrors(file_proto, &error_collector));
3305     EXPECT_EQ(expected_warnings, error_collector.warning_text_);
3306   }
3307 
3308   // Builds some already-parsed file in our test pool.
BuildFileInTestPool(const FileDescriptor * file)3309   void BuildFileInTestPool(const FileDescriptor* file) {
3310     FileDescriptorProto file_proto;
3311     file->CopyTo(&file_proto);
3312     ASSERT_TRUE(pool_.BuildFile(file_proto) != NULL);
3313   }
3314 
3315   // Build descriptor.proto in our test pool. This allows us to extend it in
3316   // the test pool, so we can test custom options.
BuildDescriptorMessagesInTestPool()3317   void BuildDescriptorMessagesInTestPool() {
3318     BuildFileInTestPool(DescriptorProto::descriptor()->file());
3319   }
3320 
3321   DescriptorPool pool_;
3322 };
3323 
TEST_F(ValidationErrorTest,AlreadyDefined)3324 TEST_F(ValidationErrorTest, AlreadyDefined) {
3325   BuildFileWithErrors(
3326     "name: \"foo.proto\" "
3327     "message_type { name: \"Foo\" }"
3328     "message_type { name: \"Foo\" }",
3329 
3330     "foo.proto: Foo: NAME: \"Foo\" is already defined.\n");
3331 }
3332 
TEST_F(ValidationErrorTest,AlreadyDefinedInPackage)3333 TEST_F(ValidationErrorTest, AlreadyDefinedInPackage) {
3334   BuildFileWithErrors(
3335     "name: \"foo.proto\" "
3336     "package: \"foo.bar\" "
3337     "message_type { name: \"Foo\" }"
3338     "message_type { name: \"Foo\" }",
3339 
3340     "foo.proto: foo.bar.Foo: NAME: \"Foo\" is already defined in "
3341       "\"foo.bar\".\n");
3342 }
3343 
TEST_F(ValidationErrorTest,AlreadyDefinedInOtherFile)3344 TEST_F(ValidationErrorTest, AlreadyDefinedInOtherFile) {
3345   BuildFile(
3346     "name: \"foo.proto\" "
3347     "message_type { name: \"Foo\" }");
3348 
3349   BuildFileWithErrors(
3350     "name: \"bar.proto\" "
3351     "message_type { name: \"Foo\" }",
3352 
3353     "bar.proto: Foo: NAME: \"Foo\" is already defined in file "
3354       "\"foo.proto\".\n");
3355 }
3356 
TEST_F(ValidationErrorTest,PackageAlreadyDefined)3357 TEST_F(ValidationErrorTest, PackageAlreadyDefined) {
3358   BuildFile(
3359     "name: \"foo.proto\" "
3360     "message_type { name: \"foo\" }");
3361   BuildFileWithErrors(
3362     "name: \"bar.proto\" "
3363     "package: \"foo.bar\"",
3364 
3365     "bar.proto: foo: NAME: \"foo\" is already defined (as something other "
3366       "than a package) in file \"foo.proto\".\n");
3367 }
3368 
TEST_F(ValidationErrorTest,EnumValueAlreadyDefinedInParent)3369 TEST_F(ValidationErrorTest, EnumValueAlreadyDefinedInParent) {
3370   BuildFileWithErrors(
3371     "name: \"foo.proto\" "
3372     "enum_type { name: \"Foo\" value { name: \"FOO\" number: 1 } } "
3373     "enum_type { name: \"Bar\" value { name: \"FOO\" number: 1 } } ",
3374 
3375     "foo.proto: FOO: NAME: \"FOO\" is already defined.\n"
3376     "foo.proto: FOO: NAME: Note that enum values use C++ scoping rules, "
3377       "meaning that enum values are siblings of their type, not children of "
3378       "it.  Therefore, \"FOO\" must be unique within the global scope, not "
3379       "just within \"Bar\".\n");
3380 }
3381 
TEST_F(ValidationErrorTest,EnumValueAlreadyDefinedInParentNonGlobal)3382 TEST_F(ValidationErrorTest, EnumValueAlreadyDefinedInParentNonGlobal) {
3383   BuildFileWithErrors(
3384     "name: \"foo.proto\" "
3385     "package: \"pkg\" "
3386     "enum_type { name: \"Foo\" value { name: \"FOO\" number: 1 } } "
3387     "enum_type { name: \"Bar\" value { name: \"FOO\" number: 1 } } ",
3388 
3389     "foo.proto: pkg.FOO: NAME: \"FOO\" is already defined in \"pkg\".\n"
3390     "foo.proto: pkg.FOO: NAME: Note that enum values use C++ scoping rules, "
3391       "meaning that enum values are siblings of their type, not children of "
3392       "it.  Therefore, \"FOO\" must be unique within \"pkg\", not just within "
3393       "\"Bar\".\n");
3394 }
3395 
TEST_F(ValidationErrorTest,MissingName)3396 TEST_F(ValidationErrorTest, MissingName) {
3397   BuildFileWithErrors(
3398     "name: \"foo.proto\" "
3399     "message_type { }",
3400 
3401     "foo.proto: : NAME: Missing name.\n");
3402 }
3403 
TEST_F(ValidationErrorTest,InvalidName)3404 TEST_F(ValidationErrorTest, InvalidName) {
3405   BuildFileWithErrors(
3406     "name: \"foo.proto\" "
3407     "message_type { name: \"$\" }",
3408 
3409     "foo.proto: $: NAME: \"$\" is not a valid identifier.\n");
3410 }
3411 
TEST_F(ValidationErrorTest,InvalidPackageName)3412 TEST_F(ValidationErrorTest, InvalidPackageName) {
3413   BuildFileWithErrors(
3414     "name: \"foo.proto\" "
3415     "package: \"foo.$\"",
3416 
3417     "foo.proto: foo.$: NAME: \"$\" is not a valid identifier.\n");
3418 }
3419 
TEST_F(ValidationErrorTest,MissingFileName)3420 TEST_F(ValidationErrorTest, MissingFileName) {
3421   BuildFileWithErrors(
3422     "",
3423 
3424     ": : OTHER: Missing field: FileDescriptorProto.name.\n");
3425 }
3426 
TEST_F(ValidationErrorTest,DupeDependency)3427 TEST_F(ValidationErrorTest, DupeDependency) {
3428   BuildFile("name: \"foo.proto\"");
3429   BuildFileWithErrors(
3430     "name: \"bar.proto\" "
3431     "dependency: \"foo.proto\" "
3432     "dependency: \"foo.proto\" ",
3433 
3434     "bar.proto: bar.proto: OTHER: Import \"foo.proto\" was listed twice.\n");
3435 }
3436 
TEST_F(ValidationErrorTest,UnknownDependency)3437 TEST_F(ValidationErrorTest, UnknownDependency) {
3438   BuildFileWithErrors(
3439     "name: \"bar.proto\" "
3440     "dependency: \"foo.proto\" ",
3441 
3442     "bar.proto: bar.proto: OTHER: Import \"foo.proto\" has not been loaded.\n");
3443 }
3444 
TEST_F(ValidationErrorTest,InvalidPublicDependencyIndex)3445 TEST_F(ValidationErrorTest, InvalidPublicDependencyIndex) {
3446   BuildFile("name: \"foo.proto\"");
3447   BuildFileWithErrors(
3448     "name: \"bar.proto\" "
3449     "dependency: \"foo.proto\" "
3450     "public_dependency: 1",
3451     "bar.proto: bar.proto: OTHER: Invalid public dependency index.\n");
3452 }
3453 
TEST_F(ValidationErrorTest,ForeignUnimportedPackageNoCrash)3454 TEST_F(ValidationErrorTest, ForeignUnimportedPackageNoCrash) {
3455   // Used to crash:  If we depend on a non-existent file and then refer to a
3456   // package defined in a file that we didn't import, and that package is
3457   // nested within a parent package which this file is also in, and we don't
3458   // include that parent package in the name (i.e. we do a relative lookup)...
3459   // Yes, really.
3460   BuildFile(
3461     "name: 'foo.proto' "
3462     "package: 'outer.foo' ");
3463   BuildFileWithErrors(
3464     "name: 'bar.proto' "
3465     "dependency: 'baz.proto' "
3466     "package: 'outer.bar' "
3467     "message_type { "
3468     "  name: 'Bar' "
3469     "  field { name:'bar' number:1 label:LABEL_OPTIONAL type_name:'foo.Foo' }"
3470     "}",
3471 
3472     "bar.proto: bar.proto: OTHER: Import \"baz.proto\" has not been loaded.\n"
3473     "bar.proto: outer.bar.Bar.bar: TYPE: \"outer.foo\" seems to be defined in "
3474       "\"foo.proto\", which is not imported by \"bar.proto\".  To use it here, "
3475       "please add the necessary import.\n");
3476 }
3477 
TEST_F(ValidationErrorTest,DupeFile)3478 TEST_F(ValidationErrorTest, DupeFile) {
3479   BuildFile(
3480     "name: \"foo.proto\" "
3481     "message_type { name: \"Foo\" }");
3482   // Note:  We should *not* get redundant errors about "Foo" already being
3483   //   defined.
3484   BuildFileWithErrors(
3485     "name: \"foo.proto\" "
3486     "message_type { name: \"Foo\" } "
3487     // Add another type so that the files aren't identical (in which case there
3488     // would be no error).
3489     "enum_type { name: \"Bar\" }",
3490 
3491     "foo.proto: foo.proto: OTHER: A file with this name is already in the "
3492       "pool.\n");
3493 }
3494 
TEST_F(ValidationErrorTest,FieldInExtensionRange)3495 TEST_F(ValidationErrorTest, FieldInExtensionRange) {
3496   BuildFileWithErrors(
3497     "name: \"foo.proto\" "
3498     "message_type {"
3499     "  name: \"Foo\""
3500     "  field { name: \"foo\" number:  9 label:LABEL_OPTIONAL type:TYPE_INT32 }"
3501     "  field { name: \"bar\" number: 10 label:LABEL_OPTIONAL type:TYPE_INT32 }"
3502     "  field { name: \"baz\" number: 19 label:LABEL_OPTIONAL type:TYPE_INT32 }"
3503     "  field { name: \"qux\" number: 20 label:LABEL_OPTIONAL type:TYPE_INT32 }"
3504     "  extension_range { start: 10 end: 20 }"
3505     "}",
3506 
3507     "foo.proto: Foo.bar: NUMBER: Extension range 10 to 19 includes field "
3508       "\"bar\" (10).\n"
3509     "foo.proto: Foo.baz: NUMBER: Extension range 10 to 19 includes field "
3510       "\"baz\" (19).\n");
3511 }
3512 
TEST_F(ValidationErrorTest,OverlappingExtensionRanges)3513 TEST_F(ValidationErrorTest, OverlappingExtensionRanges) {
3514   BuildFileWithErrors(
3515     "name: \"foo.proto\" "
3516     "message_type {"
3517     "  name: \"Foo\""
3518     "  extension_range { start: 10 end: 20 }"
3519     "  extension_range { start: 20 end: 30 }"
3520     "  extension_range { start: 19 end: 21 }"
3521     "}",
3522 
3523     "foo.proto: Foo: NUMBER: Extension range 19 to 20 overlaps with "
3524       "already-defined range 10 to 19.\n"
3525     "foo.proto: Foo: NUMBER: Extension range 19 to 20 overlaps with "
3526       "already-defined range 20 to 29.\n");
3527 }
3528 
TEST_F(ValidationErrorTest,ReservedFieldError)3529 TEST_F(ValidationErrorTest, ReservedFieldError) {
3530   BuildFileWithErrors(
3531     "name: \"foo.proto\" "
3532     "message_type {"
3533     "  name: \"Foo\""
3534     "  field { name: \"foo\" number: 15 label:LABEL_OPTIONAL type:TYPE_INT32 }"
3535     "  reserved_range { start: 10 end: 20 }"
3536     "}",
3537 
3538     "foo.proto: Foo.foo: NUMBER: Field \"foo\" uses reserved number 15.\n");
3539 }
3540 
TEST_F(ValidationErrorTest,ReservedExtensionRangeError)3541 TEST_F(ValidationErrorTest, ReservedExtensionRangeError) {
3542   BuildFileWithErrors(
3543     "name: \"foo.proto\" "
3544     "message_type {"
3545     "  name: \"Foo\""
3546     "  extension_range { start: 10 end: 20 }"
3547     "  reserved_range { start: 5 end: 15 }"
3548     "}",
3549 
3550     "foo.proto: Foo: NUMBER: Extension range 10 to 19"
3551     " overlaps with reserved range 5 to 14.\n");
3552 }
3553 
TEST_F(ValidationErrorTest,ReservedExtensionRangeAdjacent)3554 TEST_F(ValidationErrorTest, ReservedExtensionRangeAdjacent) {
3555   BuildFile(
3556     "name: \"foo.proto\" "
3557     "message_type {"
3558     "  name: \"Foo\""
3559     "  extension_range { start: 10 end: 20 }"
3560     "  reserved_range { start: 5 end: 10 }"
3561     "}");
3562 }
3563 
TEST_F(ValidationErrorTest,ReservedRangeOverlap)3564 TEST_F(ValidationErrorTest, ReservedRangeOverlap) {
3565   BuildFileWithErrors(
3566     "name: \"foo.proto\" "
3567     "message_type {"
3568     "  name: \"Foo\""
3569     "  reserved_range { start: 10 end: 20 }"
3570     "  reserved_range { start: 5 end: 15 }"
3571     "}",
3572 
3573     "foo.proto: Foo: NUMBER: Reserved range 5 to 14"
3574     " overlaps with already-defined range 10 to 19.\n");
3575 }
3576 
TEST_F(ValidationErrorTest,ReservedNameError)3577 TEST_F(ValidationErrorTest, ReservedNameError) {
3578   BuildFileWithErrors(
3579     "name: \"foo.proto\" "
3580     "message_type {"
3581     "  name: \"Foo\""
3582     "  field { name: \"foo\" number: 15 label:LABEL_OPTIONAL type:TYPE_INT32 }"
3583     "  field { name: \"bar\" number: 16 label:LABEL_OPTIONAL type:TYPE_INT32 }"
3584     "  field { name: \"baz\" number: 17 label:LABEL_OPTIONAL type:TYPE_INT32 }"
3585     "  reserved_name: \"foo\""
3586     "  reserved_name: \"bar\""
3587     "}",
3588 
3589     "foo.proto: Foo.foo: NAME: Field name \"foo\" is reserved.\n"
3590     "foo.proto: Foo.bar: NAME: Field name \"bar\" is reserved.\n");
3591 }
3592 
TEST_F(ValidationErrorTest,ReservedNameRedundant)3593 TEST_F(ValidationErrorTest, ReservedNameRedundant) {
3594   BuildFileWithErrors(
3595     "name: \"foo.proto\" "
3596     "message_type {"
3597     "  name: \"Foo\""
3598     "  reserved_name: \"foo\""
3599     "  reserved_name: \"foo\""
3600     "}",
3601 
3602     "foo.proto: foo: NAME: Field name \"foo\" is reserved multiple times.\n");
3603 }
3604 
TEST_F(ValidationErrorTest,ReservedFieldsDebugString)3605 TEST_F(ValidationErrorTest, ReservedFieldsDebugString) {
3606   const FileDescriptor* file = BuildFile(
3607     "name: \"foo.proto\" "
3608     "message_type {"
3609     "  name: \"Foo\""
3610     "  reserved_name: \"foo\""
3611     "  reserved_name: \"bar\""
3612     "  reserved_range { start: 5 end: 6 }"
3613     "  reserved_range { start: 10 end: 20 }"
3614     "}");
3615 
3616   ASSERT_EQ(
3617     "syntax = \"proto2\";\n\n"
3618     "message Foo {\n"
3619     "  reserved 5, 10 to 19;\n"
3620     "  reserved \"foo\", \"bar\";\n"
3621     "}\n\n",
3622     file->DebugString());
3623 }
3624 
TEST_F(ValidationErrorTest,InvalidDefaults)3625 TEST_F(ValidationErrorTest, InvalidDefaults) {
3626   BuildFileWithErrors(
3627     "name: \"foo.proto\" "
3628     "message_type {"
3629     "  name: \"Foo\""
3630 
3631     // Invalid number.
3632     "  field { name: \"foo\" number: 1 label: LABEL_OPTIONAL type: TYPE_INT32"
3633     "          default_value: \"abc\" }"
3634 
3635     // Empty default value.
3636     "  field { name: \"bar\" number: 2 label: LABEL_OPTIONAL type: TYPE_INT32"
3637     "          default_value: \"\" }"
3638 
3639     // Invalid boolean.
3640     "  field { name: \"baz\" number: 3 label: LABEL_OPTIONAL type: TYPE_BOOL"
3641     "          default_value: \"abc\" }"
3642 
3643     // Messages can't have defaults.
3644     "  field { name: \"qux\" number: 4 label: LABEL_OPTIONAL type: TYPE_MESSAGE"
3645     "          default_value: \"abc\" type_name: \"Foo\" }"
3646 
3647     // Same thing, but we don't know that this field has message type until
3648     // we look up the type name.
3649     "  field { name: \"quux\" number: 5 label: LABEL_OPTIONAL"
3650     "          default_value: \"abc\" type_name: \"Foo\" }"
3651 
3652     // Repeateds can't have defaults.
3653     "  field { name: \"corge\" number: 6 label: LABEL_REPEATED type: TYPE_INT32"
3654     "          default_value: \"1\" }"
3655     "}",
3656 
3657     "foo.proto: Foo.foo: DEFAULT_VALUE: Couldn't parse default value \"abc\".\n"
3658     "foo.proto: Foo.bar: DEFAULT_VALUE: Couldn't parse default value \"\".\n"
3659     "foo.proto: Foo.baz: DEFAULT_VALUE: Boolean default must be true or "
3660       "false.\n"
3661     "foo.proto: Foo.qux: DEFAULT_VALUE: Messages can't have default values.\n"
3662     "foo.proto: Foo.corge: DEFAULT_VALUE: Repeated fields can't have default "
3663       "values.\n"
3664     // This ends up being reported later because the error is detected at
3665     // cross-linking time.
3666     "foo.proto: Foo.quux: DEFAULT_VALUE: Messages can't have default "
3667       "values.\n");
3668 }
3669 
TEST_F(ValidationErrorTest,NegativeFieldNumber)3670 TEST_F(ValidationErrorTest, NegativeFieldNumber) {
3671   BuildFileWithErrors(
3672     "name: \"foo.proto\" "
3673     "message_type {"
3674     "  name: \"Foo\""
3675     "  field { name: \"foo\" number: -1 label:LABEL_OPTIONAL type:TYPE_INT32 }"
3676     "}",
3677 
3678     "foo.proto: Foo.foo: NUMBER: Field numbers must be positive integers.\n");
3679 }
3680 
TEST_F(ValidationErrorTest,HugeFieldNumber)3681 TEST_F(ValidationErrorTest, HugeFieldNumber) {
3682   BuildFileWithErrors(
3683     "name: \"foo.proto\" "
3684     "message_type {"
3685     "  name: \"Foo\""
3686     "  field { name: \"foo\" number: 0x70000000 "
3687     "          label:LABEL_OPTIONAL type:TYPE_INT32 }"
3688     "}",
3689 
3690     "foo.proto: Foo.foo: NUMBER: Field numbers cannot be greater than "
3691       "536870911.\n");
3692 }
3693 
TEST_F(ValidationErrorTest,ReservedFieldNumber)3694 TEST_F(ValidationErrorTest, ReservedFieldNumber) {
3695   BuildFileWithErrors(
3696     "name: \"foo.proto\" "
3697     "message_type {"
3698     "  name: \"Foo\""
3699     "  field {name:\"foo\" number: 18999 label:LABEL_OPTIONAL type:TYPE_INT32 }"
3700     "  field {name:\"bar\" number: 19000 label:LABEL_OPTIONAL type:TYPE_INT32 }"
3701     "  field {name:\"baz\" number: 19999 label:LABEL_OPTIONAL type:TYPE_INT32 }"
3702     "  field {name:\"qux\" number: 20000 label:LABEL_OPTIONAL type:TYPE_INT32 }"
3703     "}",
3704 
3705     "foo.proto: Foo.bar: NUMBER: Field numbers 19000 through 19999 are "
3706       "reserved for the protocol buffer library implementation.\n"
3707     "foo.proto: Foo.baz: NUMBER: Field numbers 19000 through 19999 are "
3708       "reserved for the protocol buffer library implementation.\n");
3709 }
3710 
TEST_F(ValidationErrorTest,ExtensionMissingExtendee)3711 TEST_F(ValidationErrorTest, ExtensionMissingExtendee) {
3712   BuildFileWithErrors(
3713     "name: \"foo.proto\" "
3714     "message_type {"
3715     "  name: \"Foo\""
3716     "  extension { name: \"foo\" number: 1 label: LABEL_OPTIONAL"
3717     "              type_name: \"Foo\" }"
3718     "}",
3719 
3720     "foo.proto: Foo.foo: EXTENDEE: FieldDescriptorProto.extendee not set for "
3721       "extension field.\n");
3722 }
3723 
TEST_F(ValidationErrorTest,NonExtensionWithExtendee)3724 TEST_F(ValidationErrorTest, NonExtensionWithExtendee) {
3725   BuildFileWithErrors(
3726     "name: \"foo.proto\" "
3727     "message_type {"
3728     "  name: \"Bar\""
3729     "  extension_range { start: 1 end: 2 }"
3730     "}"
3731     "message_type {"
3732     "  name: \"Foo\""
3733     "  field { name: \"foo\" number: 1 label: LABEL_OPTIONAL"
3734     "          type_name: \"Foo\" extendee: \"Bar\" }"
3735     "}",
3736 
3737     "foo.proto: Foo.foo: EXTENDEE: FieldDescriptorProto.extendee set for "
3738       "non-extension field.\n");
3739 }
3740 
TEST_F(ValidationErrorTest,FieldOneofIndexTooLarge)3741 TEST_F(ValidationErrorTest, FieldOneofIndexTooLarge) {
3742   BuildFileWithErrors(
3743     "name: \"foo.proto\" "
3744     "message_type {"
3745     "  name: \"Foo\""
3746     "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32 "
3747     "          oneof_index: 1 }"
3748     "  field { name:\"dummy\" number:2 label:LABEL_OPTIONAL type:TYPE_INT32 "
3749     "          oneof_index: 0 }"
3750     "  oneof_decl { name:\"bar\" }"
3751     "}",
3752 
3753     "foo.proto: Foo.foo: OTHER: FieldDescriptorProto.oneof_index 1 is out of "
3754       "range for type \"Foo\".\n");
3755 }
3756 
TEST_F(ValidationErrorTest,FieldOneofIndexNegative)3757 TEST_F(ValidationErrorTest, FieldOneofIndexNegative) {
3758   BuildFileWithErrors(
3759     "name: \"foo.proto\" "
3760     "message_type {"
3761     "  name: \"Foo\""
3762     "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32 "
3763     "          oneof_index: -1 }"
3764     "  field { name:\"dummy\" number:2 label:LABEL_OPTIONAL type:TYPE_INT32 "
3765     "          oneof_index: 0 }"
3766     "  oneof_decl { name:\"bar\" }"
3767     "}",
3768 
3769     "foo.proto: Foo.foo: OTHER: FieldDescriptorProto.oneof_index -1 is out of "
3770       "range for type \"Foo\".\n");
3771 }
3772 
TEST_F(ValidationErrorTest,OneofFieldsConsecutiveDefinition)3773 TEST_F(ValidationErrorTest, OneofFieldsConsecutiveDefinition) {
3774   // Fields belonging to the same oneof must be defined consecutively.
3775   BuildFileWithErrors(
3776       "name: \"foo.proto\" "
3777       "message_type {"
3778       "  name: \"Foo\""
3779       "  field { name:\"foo1\" number: 1 label:LABEL_OPTIONAL type:TYPE_INT32 "
3780       "          oneof_index: 0 }"
3781       "  field { name:\"bar\" number: 2 label:LABEL_OPTIONAL type:TYPE_INT32 }"
3782       "  field { name:\"foo2\" number: 3 label:LABEL_OPTIONAL type:TYPE_INT32 "
3783       "          oneof_index: 0 }"
3784       "  oneof_decl { name:\"foos\" }"
3785       "}",
3786 
3787       "foo.proto: Foo.bar: OTHER: Fields in the same oneof must be defined "
3788       "consecutively. \"bar\" cannot be defined before the completion of the "
3789       "\"foos\" oneof definition.\n");
3790 
3791   // Prevent interleaved fields, which belong to different oneofs.
3792   BuildFileWithErrors(
3793       "name: \"foo2.proto\" "
3794       "message_type {"
3795       "  name: \"Foo2\""
3796       "  field { name:\"foo1\" number: 1 label:LABEL_OPTIONAL type:TYPE_INT32 "
3797       "          oneof_index: 0 }"
3798       "  field { name:\"bar1\" number: 2 label:LABEL_OPTIONAL type:TYPE_INT32 "
3799       "          oneof_index: 1 }"
3800       "  field { name:\"foo2\" number: 3 label:LABEL_OPTIONAL type:TYPE_INT32 "
3801       "          oneof_index: 0 }"
3802       "  field { name:\"bar2\" number: 4 label:LABEL_OPTIONAL type:TYPE_INT32 "
3803       "          oneof_index: 1 }"
3804       "  oneof_decl { name:\"foos\" }"
3805       "  oneof_decl { name:\"bars\" }"
3806       "}",
3807       "foo2.proto: Foo2.bar1: OTHER: Fields in the same oneof must be defined "
3808       "consecutively. \"bar1\" cannot be defined before the completion of the "
3809       "\"foos\" oneof definition.\n"
3810       "foo2.proto: Foo2.foo2: OTHER: Fields in the same oneof must be defined "
3811       "consecutively. \"foo2\" cannot be defined before the completion of the "
3812       "\"bars\" oneof definition.\n");
3813 
3814   // Another case for normal fields and different oneof fields interleave.
3815   BuildFileWithErrors(
3816       "name: \"foo3.proto\" "
3817       "message_type {"
3818       "  name: \"Foo3\""
3819       "  field { name:\"foo1\" number: 1 label:LABEL_OPTIONAL type:TYPE_INT32 "
3820       "          oneof_index: 0 }"
3821       "  field { name:\"bar1\" number: 2 label:LABEL_OPTIONAL type:TYPE_INT32 "
3822       "          oneof_index: 1 }"
3823       "  field { name:\"baz\" number: 3 label:LABEL_OPTIONAL type:TYPE_INT32 }"
3824       "  field { name:\"foo2\" number: 4 label:LABEL_OPTIONAL type:TYPE_INT32 "
3825       "          oneof_index: 0 }"
3826       "  oneof_decl { name:\"foos\" }"
3827       "  oneof_decl { name:\"bars\" }"
3828       "}",
3829       "foo3.proto: Foo3.baz: OTHER: Fields in the same oneof must be defined "
3830       "consecutively. \"baz\" cannot be defined before the completion of the "
3831       "\"foos\" oneof definition.\n");
3832 }
3833 
TEST_F(ValidationErrorTest,FieldNumberConflict)3834 TEST_F(ValidationErrorTest, FieldNumberConflict) {
3835   BuildFileWithErrors(
3836     "name: \"foo.proto\" "
3837     "message_type {"
3838     "  name: \"Foo\""
3839     "  field { name: \"foo\" number: 1 label:LABEL_OPTIONAL type:TYPE_INT32 }"
3840     "  field { name: \"bar\" number: 1 label:LABEL_OPTIONAL type:TYPE_INT32 }"
3841     "}",
3842 
3843     "foo.proto: Foo.bar: NUMBER: Field number 1 has already been used in "
3844       "\"Foo\" by field \"foo\".\n");
3845 }
3846 
TEST_F(ValidationErrorTest,BadMessageSetExtensionType)3847 TEST_F(ValidationErrorTest, BadMessageSetExtensionType) {
3848   BuildFileWithErrors(
3849     "name: \"foo.proto\" "
3850     "message_type {"
3851     "  name: \"MessageSet\""
3852     "  options { message_set_wire_format: true }"
3853     "  extension_range { start: 4 end: 5 }"
3854     "}"
3855     "message_type {"
3856     "  name: \"Foo\""
3857     "  extension { name:\"foo\" number:4 label:LABEL_OPTIONAL type:TYPE_INT32"
3858     "              extendee: \"MessageSet\" }"
3859     "}",
3860 
3861     "foo.proto: Foo.foo: TYPE: Extensions of MessageSets must be optional "
3862       "messages.\n");
3863 }
3864 
TEST_F(ValidationErrorTest,BadMessageSetExtensionLabel)3865 TEST_F(ValidationErrorTest, BadMessageSetExtensionLabel) {
3866   BuildFileWithErrors(
3867     "name: \"foo.proto\" "
3868     "message_type {"
3869     "  name: \"MessageSet\""
3870     "  options { message_set_wire_format: true }"
3871     "  extension_range { start: 4 end: 5 }"
3872     "}"
3873     "message_type {"
3874     "  name: \"Foo\""
3875     "  extension { name:\"foo\" number:4 label:LABEL_REPEATED type:TYPE_MESSAGE"
3876     "              type_name: \"Foo\" extendee: \"MessageSet\" }"
3877     "}",
3878 
3879     "foo.proto: Foo.foo: TYPE: Extensions of MessageSets must be optional "
3880       "messages.\n");
3881 }
3882 
TEST_F(ValidationErrorTest,FieldInMessageSet)3883 TEST_F(ValidationErrorTest, FieldInMessageSet) {
3884   BuildFileWithErrors(
3885     "name: \"foo.proto\" "
3886     "message_type {"
3887     "  name: \"Foo\""
3888     "  options { message_set_wire_format: true }"
3889     "  field { name: \"foo\" number: 1 label:LABEL_OPTIONAL type:TYPE_INT32 }"
3890     "}",
3891 
3892     "foo.proto: Foo.foo: NAME: MessageSets cannot have fields, only "
3893       "extensions.\n");
3894 }
3895 
TEST_F(ValidationErrorTest,NegativeExtensionRangeNumber)3896 TEST_F(ValidationErrorTest, NegativeExtensionRangeNumber) {
3897   BuildFileWithErrors(
3898     "name: \"foo.proto\" "
3899     "message_type {"
3900     "  name: \"Foo\""
3901     "  extension_range { start: -10 end: -1 }"
3902     "}",
3903 
3904     "foo.proto: Foo: NUMBER: Extension numbers must be positive integers.\n");
3905 }
3906 
TEST_F(ValidationErrorTest,HugeExtensionRangeNumber)3907 TEST_F(ValidationErrorTest, HugeExtensionRangeNumber) {
3908   BuildFileWithErrors(
3909     "name: \"foo.proto\" "
3910     "message_type {"
3911     "  name: \"Foo\""
3912     "  extension_range { start: 1 end: 0x70000000 }"
3913     "}",
3914 
3915     "foo.proto: Foo: NUMBER: Extension numbers cannot be greater than "
3916       "536870911.\n");
3917 }
3918 
TEST_F(ValidationErrorTest,ExtensionRangeEndBeforeStart)3919 TEST_F(ValidationErrorTest, ExtensionRangeEndBeforeStart) {
3920   BuildFileWithErrors(
3921     "name: \"foo.proto\" "
3922     "message_type {"
3923     "  name: \"Foo\""
3924     "  extension_range { start: 10 end: 10 }"
3925     "  extension_range { start: 10 end: 5 }"
3926     "}",
3927 
3928     "foo.proto: Foo: NUMBER: Extension range end number must be greater than "
3929       "start number.\n"
3930     "foo.proto: Foo: NUMBER: Extension range end number must be greater than "
3931       "start number.\n");
3932 }
3933 
TEST_F(ValidationErrorTest,EmptyEnum)3934 TEST_F(ValidationErrorTest, EmptyEnum) {
3935   BuildFileWithErrors(
3936     "name: \"foo.proto\" "
3937     "enum_type { name: \"Foo\" }"
3938     // Also use the empty enum in a message to make sure there are no crashes
3939     // during validation (possible if the code attempts to derive a default
3940     // value for the field).
3941     "message_type {"
3942     "  name: \"Bar\""
3943     "  field { name: \"foo\" number: 1 label:LABEL_OPTIONAL type_name:\"Foo\" }"
3944     "  field { name: \"bar\" number: 2 label:LABEL_OPTIONAL type_name:\"Foo\" "
3945     "          default_value: \"NO_SUCH_VALUE\" }"
3946     "}",
3947 
3948     "foo.proto: Foo: NAME: Enums must contain at least one value.\n"
3949     "foo.proto: Bar.bar: DEFAULT_VALUE: Enum type \"Foo\" has no value named "
3950       "\"NO_SUCH_VALUE\".\n");
3951 }
3952 
TEST_F(ValidationErrorTest,UndefinedExtendee)3953 TEST_F(ValidationErrorTest, UndefinedExtendee) {
3954   BuildFileWithErrors(
3955     "name: \"foo.proto\" "
3956     "message_type {"
3957     "  name: \"Foo\""
3958     "  extension { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32"
3959     "              extendee: \"Bar\" }"
3960     "}",
3961 
3962     "foo.proto: Foo.foo: EXTENDEE: \"Bar\" is not defined.\n");
3963 }
3964 
TEST_F(ValidationErrorTest,NonMessageExtendee)3965 TEST_F(ValidationErrorTest, NonMessageExtendee) {
3966   BuildFileWithErrors(
3967     "name: \"foo.proto\" "
3968     "enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } }"
3969     "message_type {"
3970     "  name: \"Foo\""
3971     "  extension { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32"
3972     "              extendee: \"Bar\" }"
3973     "}",
3974 
3975     "foo.proto: Foo.foo: EXTENDEE: \"Bar\" is not a message type.\n");
3976 }
3977 
TEST_F(ValidationErrorTest,NotAnExtensionNumber)3978 TEST_F(ValidationErrorTest, NotAnExtensionNumber) {
3979   BuildFileWithErrors(
3980     "name: \"foo.proto\" "
3981     "message_type {"
3982     "  name: \"Bar\""
3983     "}"
3984     "message_type {"
3985     "  name: \"Foo\""
3986     "  extension { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32"
3987     "              extendee: \"Bar\" }"
3988     "}",
3989 
3990     "foo.proto: Foo.foo: NUMBER: \"Bar\" does not declare 1 as an extension "
3991       "number.\n");
3992 }
3993 
TEST_F(ValidationErrorTest,RequiredExtension)3994 TEST_F(ValidationErrorTest, RequiredExtension) {
3995   BuildFileWithErrors(
3996     "name: \"foo.proto\" "
3997     "message_type {"
3998     "  name: \"Bar\""
3999     "  extension_range { start: 1000 end: 10000 }"
4000     "}"
4001     "message_type {"
4002     "  name: \"Foo\""
4003     "  extension {"
4004     "    name:\"foo\""
4005     "    number:1000"
4006     "    label:LABEL_REQUIRED"
4007     "    type:TYPE_INT32"
4008     "    extendee: \"Bar\""
4009     "  }"
4010     "}",
4011 
4012     "foo.proto: Foo.foo: TYPE: Message extensions cannot have required "
4013     "fields.\n");
4014 }
4015 
TEST_F(ValidationErrorTest,UndefinedFieldType)4016 TEST_F(ValidationErrorTest, UndefinedFieldType) {
4017   BuildFileWithErrors(
4018     "name: \"foo.proto\" "
4019     "message_type {"
4020     "  name: \"Foo\""
4021     "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }"
4022     "}",
4023 
4024     "foo.proto: Foo.foo: TYPE: \"Bar\" is not defined.\n");
4025 }
4026 
TEST_F(ValidationErrorTest,UndefinedFieldTypeWithDefault)4027 TEST_F(ValidationErrorTest, UndefinedFieldTypeWithDefault) {
4028   // See b/12533582. Previously this failed because the default value was not
4029   // accepted by the parser, which assumed an enum type, leading to an unclear
4030   // error message. We want this input to yield a validation error instead,
4031   // since the unknown type is the primary problem.
4032   BuildFileWithErrors(
4033     "name: \"foo.proto\" "
4034     "message_type {"
4035     "  name: \"Foo\""
4036     "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"int\" "
4037     "          default_value:\"1\" }"
4038     "}",
4039 
4040     "foo.proto: Foo.foo: TYPE: \"int\" is not defined.\n");
4041 }
4042 
TEST_F(ValidationErrorTest,UndefinedNestedFieldType)4043 TEST_F(ValidationErrorTest, UndefinedNestedFieldType) {
4044   BuildFileWithErrors(
4045     "name: \"foo.proto\" "
4046     "message_type {"
4047     "  name: \"Foo\""
4048     "  nested_type { name:\"Baz\" }"
4049     "  field { name:\"foo\" number:1"
4050     "          label:LABEL_OPTIONAL"
4051     "          type_name:\"Foo.Baz.Bar\" }"
4052     "}",
4053 
4054     "foo.proto: Foo.foo: TYPE: \"Foo.Baz.Bar\" is not defined.\n");
4055 }
4056 
TEST_F(ValidationErrorTest,FieldTypeDefinedInUndeclaredDependency)4057 TEST_F(ValidationErrorTest, FieldTypeDefinedInUndeclaredDependency) {
4058   BuildFile(
4059     "name: \"bar.proto\" "
4060     "message_type { name: \"Bar\" } ");
4061 
4062   BuildFileWithErrors(
4063     "name: \"foo.proto\" "
4064     "message_type {"
4065     "  name: \"Foo\""
4066     "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }"
4067     "}",
4068     "foo.proto: Foo.foo: TYPE: \"Bar\" seems to be defined in \"bar.proto\", "
4069       "which is not imported by \"foo.proto\".  To use it here, please add the "
4070       "necessary import.\n");
4071 }
4072 
TEST_F(ValidationErrorTest,FieldTypeDefinedInIndirectDependency)4073 TEST_F(ValidationErrorTest, FieldTypeDefinedInIndirectDependency) {
4074   // Test for hidden dependencies.
4075   //
4076   // // bar.proto
4077   // message Bar{}
4078   //
4079   // // forward.proto
4080   // import "bar.proto"
4081   //
4082   // // foo.proto
4083   // import "forward.proto"
4084   // message Foo {
4085   //   optional Bar foo = 1;  // Error, needs to import bar.proto explicitly.
4086   // }
4087   //
4088   BuildFile(
4089     "name: \"bar.proto\" "
4090     "message_type { name: \"Bar\" }");
4091 
4092   BuildFile(
4093     "name: \"forward.proto\""
4094     "dependency: \"bar.proto\"");
4095 
4096   BuildFileWithErrors(
4097     "name: \"foo.proto\" "
4098     "dependency: \"forward.proto\" "
4099     "message_type {"
4100     "  name: \"Foo\""
4101     "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }"
4102     "}",
4103     "foo.proto: Foo.foo: TYPE: \"Bar\" seems to be defined in \"bar.proto\", "
4104       "which is not imported by \"foo.proto\".  To use it here, please add the "
4105       "necessary import.\n");
4106 }
4107 
TEST_F(ValidationErrorTest,FieldTypeDefinedInPublicDependency)4108 TEST_F(ValidationErrorTest, FieldTypeDefinedInPublicDependency) {
4109   // Test for public dependencies.
4110   //
4111   // // bar.proto
4112   // message Bar{}
4113   //
4114   // // forward.proto
4115   // import public "bar.proto"
4116   //
4117   // // foo.proto
4118   // import "forward.proto"
4119   // message Foo {
4120   //   optional Bar foo = 1;  // Correct. "bar.proto" is public imported into
4121   //                          // forward.proto, so when "foo.proto" imports
4122   //                          // "forward.proto", it imports "bar.proto" too.
4123   // }
4124   //
4125   BuildFile(
4126     "name: \"bar.proto\" "
4127     "message_type { name: \"Bar\" }");
4128 
4129   BuildFile(
4130     "name: \"forward.proto\""
4131     "dependency: \"bar.proto\" "
4132     "public_dependency: 0");
4133 
4134   BuildFile(
4135     "name: \"foo.proto\" "
4136     "dependency: \"forward.proto\" "
4137     "message_type {"
4138     "  name: \"Foo\""
4139     "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }"
4140     "}");
4141 }
4142 
TEST_F(ValidationErrorTest,FieldTypeDefinedInTransitivePublicDependency)4143 TEST_F(ValidationErrorTest, FieldTypeDefinedInTransitivePublicDependency) {
4144   // Test for public dependencies.
4145   //
4146   // // bar.proto
4147   // message Bar{}
4148   //
4149   // // forward.proto
4150   // import public "bar.proto"
4151   //
4152   // // forward2.proto
4153   // import public "forward.proto"
4154   //
4155   // // foo.proto
4156   // import "forward2.proto"
4157   // message Foo {
4158   //   optional Bar foo = 1;  // Correct, public imports are transitive.
4159   // }
4160   //
4161   BuildFile(
4162     "name: \"bar.proto\" "
4163     "message_type { name: \"Bar\" }");
4164 
4165   BuildFile(
4166     "name: \"forward.proto\""
4167     "dependency: \"bar.proto\" "
4168     "public_dependency: 0");
4169 
4170   BuildFile(
4171     "name: \"forward2.proto\""
4172     "dependency: \"forward.proto\" "
4173     "public_dependency: 0");
4174 
4175   BuildFile(
4176     "name: \"foo.proto\" "
4177     "dependency: \"forward2.proto\" "
4178     "message_type {"
4179     "  name: \"Foo\""
4180     "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }"
4181     "}");
4182 }
4183 
TEST_F(ValidationErrorTest,FieldTypeDefinedInPrivateDependencyOfPublicDependency)4184 TEST_F(ValidationErrorTest,
4185        FieldTypeDefinedInPrivateDependencyOfPublicDependency) {
4186   // Test for public dependencies.
4187   //
4188   // // bar.proto
4189   // message Bar{}
4190   //
4191   // // forward.proto
4192   // import "bar.proto"
4193   //
4194   // // forward2.proto
4195   // import public "forward.proto"
4196   //
4197   // // foo.proto
4198   // import "forward2.proto"
4199   // message Foo {
4200   //   optional Bar foo = 1;  // Error, the "bar.proto" is not public imported
4201   //                          // into "forward.proto", so will not be imported
4202   //                          // into either "forward2.proto" or "foo.proto".
4203   // }
4204   //
4205   BuildFile(
4206     "name: \"bar.proto\" "
4207     "message_type { name: \"Bar\" }");
4208 
4209   BuildFile(
4210     "name: \"forward.proto\""
4211     "dependency: \"bar.proto\"");
4212 
4213   BuildFile(
4214     "name: \"forward2.proto\""
4215     "dependency: \"forward.proto\" "
4216     "public_dependency: 0");
4217 
4218   BuildFileWithErrors(
4219     "name: \"foo.proto\" "
4220     "dependency: \"forward2.proto\" "
4221     "message_type {"
4222     "  name: \"Foo\""
4223     "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }"
4224     "}",
4225     "foo.proto: Foo.foo: TYPE: \"Bar\" seems to be defined in \"bar.proto\", "
4226       "which is not imported by \"foo.proto\".  To use it here, please add the "
4227       "necessary import.\n");
4228 }
4229 
4230 
TEST_F(ValidationErrorTest,SearchMostLocalFirst)4231 TEST_F(ValidationErrorTest, SearchMostLocalFirst) {
4232   // The following should produce an error that Bar.Baz is resolved but
4233   // not defined:
4234   //   message Bar { message Baz {} }
4235   //   message Foo {
4236   //     message Bar {
4237   //       // Placing "message Baz{}" here, or removing Foo.Bar altogether,
4238   //       // would fix the error.
4239   //     }
4240   //     optional Bar.Baz baz = 1;
4241   //   }
4242   // An one point the lookup code incorrectly did not produce an error in this
4243   // case, because when looking for Bar.Baz, it would try "Foo.Bar.Baz" first,
4244   // fail, and ten try "Bar.Baz" and succeed, even though "Bar" should actually
4245   // refer to the inner Bar, not the outer one.
4246   BuildFileWithErrors(
4247     "name: \"foo.proto\" "
4248     "message_type {"
4249     "  name: \"Bar\""
4250     "  nested_type { name: \"Baz\" }"
4251     "}"
4252     "message_type {"
4253     "  name: \"Foo\""
4254     "  nested_type { name: \"Bar\" }"
4255     "  field { name:\"baz\" number:1 label:LABEL_OPTIONAL"
4256     "          type_name:\"Bar.Baz\" }"
4257     "}",
4258 
4259     "foo.proto: Foo.baz: TYPE: \"Bar.Baz\" is resolved to \"Foo.Bar.Baz\","
4260     " which is not defined. The innermost scope is searched first in name "
4261     "resolution. Consider using a leading '.'(i.e., \".Bar.Baz\") to start "
4262     "from the outermost scope.\n");
4263 }
4264 
TEST_F(ValidationErrorTest,SearchMostLocalFirst2)4265 TEST_F(ValidationErrorTest, SearchMostLocalFirst2) {
4266   // This test would find the most local "Bar" first, and does, but
4267   // proceeds to find the outer one because the inner one's not an
4268   // aggregate.
4269   BuildFile(
4270     "name: \"foo.proto\" "
4271     "message_type {"
4272     "  name: \"Bar\""
4273     "  nested_type { name: \"Baz\" }"
4274     "}"
4275     "message_type {"
4276     "  name: \"Foo\""
4277     "  field { name: \"Bar\" number:1 type:TYPE_BYTES } "
4278     "  field { name:\"baz\" number:2 label:LABEL_OPTIONAL"
4279     "          type_name:\"Bar.Baz\" }"
4280     "}");
4281 }
4282 
TEST_F(ValidationErrorTest,PackageOriginallyDeclaredInTransitiveDependent)4283 TEST_F(ValidationErrorTest, PackageOriginallyDeclaredInTransitiveDependent) {
4284   // Imagine we have the following:
4285   //
4286   // foo.proto:
4287   //   package foo.bar;
4288   // bar.proto:
4289   //   package foo.bar;
4290   //   import "foo.proto";
4291   //   message Bar {}
4292   // baz.proto:
4293   //   package foo;
4294   //   import "bar.proto"
4295   //   message Baz { optional bar.Bar qux = 1; }
4296   //
4297   // When validating baz.proto, we will look up "bar.Bar".  As part of this
4298   // lookup, we first lookup "bar" then try to find "Bar" within it.  "bar"
4299   // should resolve to "foo.bar".  Note, though, that "foo.bar" was originally
4300   // defined in foo.proto, which is not a direct dependency of baz.proto.  The
4301   // implementation of FindSymbol() normally only returns symbols in direct
4302   // dependencies, not indirect ones.  This test insures that this does not
4303   // prevent it from finding "foo.bar".
4304 
4305   BuildFile(
4306     "name: \"foo.proto\" "
4307     "package: \"foo.bar\" ");
4308   BuildFile(
4309     "name: \"bar.proto\" "
4310     "package: \"foo.bar\" "
4311     "dependency: \"foo.proto\" "
4312     "message_type { name: \"Bar\" }");
4313   BuildFile(
4314     "name: \"baz.proto\" "
4315     "package: \"foo\" "
4316     "dependency: \"bar.proto\" "
4317     "message_type { "
4318     "  name: \"Baz\" "
4319     "  field { name:\"qux\" number:1 label:LABEL_OPTIONAL "
4320     "          type_name:\"bar.Bar\" }"
4321     "}");
4322 }
4323 
TEST_F(ValidationErrorTest,FieldTypeNotAType)4324 TEST_F(ValidationErrorTest, FieldTypeNotAType) {
4325   BuildFileWithErrors(
4326     "name: \"foo.proto\" "
4327     "message_type {"
4328     "  name: \"Foo\""
4329     "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL "
4330     "          type_name:\".Foo.bar\" }"
4331     "  field { name:\"bar\" number:2 label:LABEL_OPTIONAL type:TYPE_INT32 }"
4332     "}",
4333 
4334     "foo.proto: Foo.foo: TYPE: \".Foo.bar\" is not a type.\n");
4335 }
4336 
TEST_F(ValidationErrorTest,RelativeFieldTypeNotAType)4337 TEST_F(ValidationErrorTest, RelativeFieldTypeNotAType) {
4338   BuildFileWithErrors(
4339     "name: \"foo.proto\" "
4340     "message_type {"
4341     "  nested_type {"
4342     "    name: \"Bar\""
4343     "    field { name:\"Baz\" number:2 label:LABEL_OPTIONAL type:TYPE_INT32 }"
4344     "  }"
4345     "  name: \"Foo\""
4346     "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL "
4347     "          type_name:\"Bar.Baz\" }"
4348     "}",
4349     "foo.proto: Foo.foo: TYPE: \"Bar.Baz\" is not a type.\n");
4350 }
4351 
TEST_F(ValidationErrorTest,FieldTypeMayBeItsName)4352 TEST_F(ValidationErrorTest, FieldTypeMayBeItsName) {
4353   BuildFile(
4354     "name: \"foo.proto\" "
4355     "message_type {"
4356     "  name: \"Bar\""
4357     "}"
4358     "message_type {"
4359     "  name: \"Foo\""
4360     "  field { name:\"Bar\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }"
4361     "}");
4362 }
4363 
TEST_F(ValidationErrorTest,EnumFieldTypeIsMessage)4364 TEST_F(ValidationErrorTest, EnumFieldTypeIsMessage) {
4365   BuildFileWithErrors(
4366     "name: \"foo.proto\" "
4367     "message_type { name: \"Bar\" } "
4368     "message_type {"
4369     "  name: \"Foo\""
4370     "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_ENUM"
4371     "          type_name:\"Bar\" }"
4372     "}",
4373 
4374     "foo.proto: Foo.foo: TYPE: \"Bar\" is not an enum type.\n");
4375 }
4376 
TEST_F(ValidationErrorTest,MessageFieldTypeIsEnum)4377 TEST_F(ValidationErrorTest, MessageFieldTypeIsEnum) {
4378   BuildFileWithErrors(
4379     "name: \"foo.proto\" "
4380     "enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } } "
4381     "message_type {"
4382     "  name: \"Foo\""
4383     "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_MESSAGE"
4384     "          type_name:\"Bar\" }"
4385     "}",
4386 
4387     "foo.proto: Foo.foo: TYPE: \"Bar\" is not a message type.\n");
4388 }
4389 
TEST_F(ValidationErrorTest,BadEnumDefaultValue)4390 TEST_F(ValidationErrorTest, BadEnumDefaultValue) {
4391   BuildFileWithErrors(
4392     "name: \"foo.proto\" "
4393     "enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } } "
4394     "message_type {"
4395     "  name: \"Foo\""
4396     "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\""
4397     "          default_value:\"NO_SUCH_VALUE\" }"
4398     "}",
4399 
4400     "foo.proto: Foo.foo: DEFAULT_VALUE: Enum type \"Bar\" has no value named "
4401       "\"NO_SUCH_VALUE\".\n");
4402 }
4403 
TEST_F(ValidationErrorTest,EnumDefaultValueIsInteger)4404 TEST_F(ValidationErrorTest, EnumDefaultValueIsInteger) {
4405   BuildFileWithErrors(
4406     "name: \"foo.proto\" "
4407     "enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } } "
4408     "message_type {"
4409     "  name: \"Foo\""
4410     "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\""
4411     "          default_value:\"0\" }"
4412     "}",
4413 
4414     "foo.proto: Foo.foo: DEFAULT_VALUE: Default value for an enum field must "
4415     "be an identifier.\n");
4416 }
4417 
TEST_F(ValidationErrorTest,PrimitiveWithTypeName)4418 TEST_F(ValidationErrorTest, PrimitiveWithTypeName) {
4419   BuildFileWithErrors(
4420     "name: \"foo.proto\" "
4421     "message_type {"
4422     "  name: \"Foo\""
4423     "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32"
4424     "          type_name:\"Foo\" }"
4425     "}",
4426 
4427     "foo.proto: Foo.foo: TYPE: Field with primitive type has type_name.\n");
4428 }
4429 
TEST_F(ValidationErrorTest,NonPrimitiveWithoutTypeName)4430 TEST_F(ValidationErrorTest, NonPrimitiveWithoutTypeName) {
4431   BuildFileWithErrors(
4432     "name: \"foo.proto\" "
4433     "message_type {"
4434     "  name: \"Foo\""
4435     "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_MESSAGE }"
4436     "}",
4437 
4438     "foo.proto: Foo.foo: TYPE: Field with message or enum type missing "
4439       "type_name.\n");
4440 }
4441 
TEST_F(ValidationErrorTest,OneofWithNoFields)4442 TEST_F(ValidationErrorTest, OneofWithNoFields) {
4443   BuildFileWithErrors(
4444     "name: \"foo.proto\" "
4445     "message_type {"
4446     "  name: \"Foo\""
4447     "  oneof_decl { name:\"bar\" }"
4448     "}",
4449 
4450     "foo.proto: Foo.bar: NAME: Oneof must have at least one field.\n");
4451 }
4452 
TEST_F(ValidationErrorTest,OneofLabelMismatch)4453 TEST_F(ValidationErrorTest, OneofLabelMismatch) {
4454   BuildFileWithErrors(
4455     "name: \"foo.proto\" "
4456     "message_type {"
4457     "  name: \"Foo\""
4458     "  field { name:\"foo\" number:1 label:LABEL_REPEATED type:TYPE_INT32 "
4459     "          oneof_index:0 }"
4460     "  oneof_decl { name:\"bar\" }"
4461     "}",
4462 
4463     "foo.proto: Foo.foo: NAME: Fields of oneofs must themselves have label "
4464       "LABEL_OPTIONAL.\n");
4465 }
4466 
TEST_F(ValidationErrorTest,InputTypeNotDefined)4467 TEST_F(ValidationErrorTest, InputTypeNotDefined) {
4468   BuildFileWithErrors(
4469     "name: \"foo.proto\" "
4470     "message_type { name: \"Foo\" } "
4471     "service {"
4472     "  name: \"TestService\""
4473     "  method { name: \"A\" input_type: \"Bar\" output_type: \"Foo\" }"
4474     "}",
4475 
4476     "foo.proto: TestService.A: INPUT_TYPE: \"Bar\" is not defined.\n"
4477     );
4478 }
4479 
TEST_F(ValidationErrorTest,InputTypeNotAMessage)4480 TEST_F(ValidationErrorTest, InputTypeNotAMessage) {
4481   BuildFileWithErrors(
4482     "name: \"foo.proto\" "
4483     "message_type { name: \"Foo\" } "
4484     "enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } } "
4485     "service {"
4486     "  name: \"TestService\""
4487     "  method { name: \"A\" input_type: \"Bar\" output_type: \"Foo\" }"
4488     "}",
4489 
4490     "foo.proto: TestService.A: INPUT_TYPE: \"Bar\" is not a message type.\n"
4491     );
4492 }
4493 
TEST_F(ValidationErrorTest,OutputTypeNotDefined)4494 TEST_F(ValidationErrorTest, OutputTypeNotDefined) {
4495   BuildFileWithErrors(
4496     "name: \"foo.proto\" "
4497     "message_type { name: \"Foo\" } "
4498     "service {"
4499     "  name: \"TestService\""
4500     "  method { name: \"A\" input_type: \"Foo\" output_type: \"Bar\" }"
4501     "}",
4502 
4503     "foo.proto: TestService.A: OUTPUT_TYPE: \"Bar\" is not defined.\n"
4504     );
4505 }
4506 
TEST_F(ValidationErrorTest,OutputTypeNotAMessage)4507 TEST_F(ValidationErrorTest, OutputTypeNotAMessage) {
4508   BuildFileWithErrors(
4509     "name: \"foo.proto\" "
4510     "message_type { name: \"Foo\" } "
4511     "enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } } "
4512     "service {"
4513     "  name: \"TestService\""
4514     "  method { name: \"A\" input_type: \"Foo\" output_type: \"Bar\" }"
4515     "}",
4516 
4517     "foo.proto: TestService.A: OUTPUT_TYPE: \"Bar\" is not a message type.\n"
4518     );
4519 }
4520 
4521 
TEST_F(ValidationErrorTest,IllegalPackedField)4522 TEST_F(ValidationErrorTest, IllegalPackedField) {
4523   BuildFileWithErrors(
4524     "name: \"foo.proto\" "
4525     "message_type {\n"
4526     "  name: \"Foo\""
4527     "  field { name:\"packed_string\" number:1 label:LABEL_REPEATED "
4528     "          type:TYPE_STRING "
4529     "          options { uninterpreted_option {"
4530     "            name { name_part: \"packed\" is_extension: false }"
4531     "            identifier_value: \"true\" }}}\n"
4532     "  field { name:\"packed_message\" number:3 label:LABEL_REPEATED "
4533     "          type_name: \"Foo\""
4534     "          options { uninterpreted_option {"
4535     "            name { name_part: \"packed\" is_extension: false }"
4536     "            identifier_value: \"true\" }}}\n"
4537     "  field { name:\"optional_int32\" number: 4 label: LABEL_OPTIONAL "
4538     "          type:TYPE_INT32 "
4539     "          options { uninterpreted_option {"
4540     "            name { name_part: \"packed\" is_extension: false }"
4541     "            identifier_value: \"true\" }}}\n"
4542     "}",
4543 
4544     "foo.proto: Foo.packed_string: TYPE: [packed = true] can only be "
4545         "specified for repeated primitive fields.\n"
4546     "foo.proto: Foo.packed_message: TYPE: [packed = true] can only be "
4547         "specified for repeated primitive fields.\n"
4548     "foo.proto: Foo.optional_int32: TYPE: [packed = true] can only be "
4549         "specified for repeated primitive fields.\n"
4550         );
4551 }
4552 
TEST_F(ValidationErrorTest,OptionWrongType)4553 TEST_F(ValidationErrorTest, OptionWrongType) {
4554   BuildFileWithErrors(
4555     "name: \"foo.proto\" "
4556     "message_type { "
4557     "  name: \"TestMessage\" "
4558     "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_STRING "
4559     "          options { uninterpreted_option { name { name_part: \"ctype\" "
4560     "                                                  is_extension: false }"
4561     "                                           positive_int_value: 1 }"
4562     "          }"
4563     "  }"
4564     "}\n",
4565 
4566     "foo.proto: TestMessage.foo: OPTION_VALUE: Value must be identifier for "
4567     "enum-valued option \"google.protobuf.FieldOptions.ctype\".\n");
4568 }
4569 
TEST_F(ValidationErrorTest,OptionExtendsAtomicType)4570 TEST_F(ValidationErrorTest, OptionExtendsAtomicType) {
4571   BuildFileWithErrors(
4572     "name: \"foo.proto\" "
4573     "message_type { "
4574     "  name: \"TestMessage\" "
4575     "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_STRING "
4576     "          options { uninterpreted_option { name { name_part: \"ctype\" "
4577     "                                                  is_extension: false }"
4578     "                                           name { name_part: \"foo\" "
4579     "                                                  is_extension: true }"
4580     "                                           positive_int_value: 1 }"
4581     "          }"
4582     "  }"
4583     "}\n",
4584 
4585     "foo.proto: TestMessage.foo: OPTION_NAME: Option \"ctype\" is an "
4586     "atomic type, not a message.\n");
4587 }
4588 
TEST_F(ValidationErrorTest,DupOption)4589 TEST_F(ValidationErrorTest, DupOption) {
4590   BuildFileWithErrors(
4591     "name: \"foo.proto\" "
4592     "message_type { "
4593     "  name: \"TestMessage\" "
4594     "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_UINT32 "
4595     "          options { uninterpreted_option { name { name_part: \"ctype\" "
4596     "                                                  is_extension: false }"
4597     "                                           identifier_value: \"CORD\" }"
4598     "                    uninterpreted_option { name { name_part: \"ctype\" "
4599     "                                                  is_extension: false }"
4600     "                                           identifier_value: \"CORD\" }"
4601     "          }"
4602     "  }"
4603     "}\n",
4604 
4605     "foo.proto: TestMessage.foo: OPTION_NAME: Option \"ctype\" was "
4606     "already set.\n");
4607 }
4608 
TEST_F(ValidationErrorTest,InvalidOptionName)4609 TEST_F(ValidationErrorTest, InvalidOptionName) {
4610   BuildFileWithErrors(
4611     "name: \"foo.proto\" "
4612     "message_type { "
4613     "  name: \"TestMessage\" "
4614     "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_BOOL "
4615     "          options { uninterpreted_option { "
4616     "                      name { name_part: \"uninterpreted_option\" "
4617     "                             is_extension: false }"
4618     "                      positive_int_value: 1 "
4619     "                    }"
4620     "          }"
4621     "  }"
4622     "}\n",
4623 
4624     "foo.proto: TestMessage.foo: OPTION_NAME: Option must not use "
4625     "reserved name \"uninterpreted_option\".\n");
4626 }
4627 
TEST_F(ValidationErrorTest,RepeatedMessageOption)4628 TEST_F(ValidationErrorTest, RepeatedMessageOption) {
4629   BuildDescriptorMessagesInTestPool();
4630 
4631   BuildFileWithErrors(
4632     "name: \"foo.proto\" "
4633     "dependency: \"google/protobuf/descriptor.proto\" "
4634     "message_type: { name: \"Bar\" field: { "
4635     "  name: \"foo\" number: 1 label: LABEL_OPTIONAL type: TYPE_INT32 } "
4636     "} "
4637     "extension { name: \"bar\" number: 7672757 label: LABEL_REPEATED "
4638     "            type: TYPE_MESSAGE type_name: \"Bar\" "
4639     "            extendee: \"google.protobuf.FileOptions\" }"
4640     "options { uninterpreted_option { name { name_part: \"bar\" "
4641     "                                        is_extension: true } "
4642     "                                 name { name_part: \"foo\" "
4643     "                                        is_extension: false } "
4644     "                                 positive_int_value: 1 } }",
4645 
4646     "foo.proto: foo.proto: OPTION_NAME: Option field \"(bar)\" is a "
4647     "repeated message. Repeated message options must be initialized "
4648     "using an aggregate value.\n");
4649 }
4650 
TEST_F(ValidationErrorTest,ResolveUndefinedOption)4651 TEST_F(ValidationErrorTest, ResolveUndefinedOption) {
4652   // The following should produce an eror that baz.bar is resolved but not
4653   // defined.
4654   // foo.proto:
4655   //   package baz
4656   //   import google/protobuf/descriptor.proto
4657   //   message Bar { optional int32 foo = 1; }
4658   //   extend FileOptions { optional Bar bar = 7672757; }
4659   //
4660   // qux.proto:
4661   //   package qux.baz
4662   //   option (baz.bar).foo = 1;
4663   //
4664   // Although "baz.bar" is already defined, the lookup code will try
4665   // "qux.baz.bar", since it's the match from the innermost scope, which will
4666   // cause a symbol not defined error.
4667   BuildDescriptorMessagesInTestPool();
4668 
4669   BuildFile(
4670     "name: \"foo.proto\" "
4671     "package: \"baz\" "
4672     "dependency: \"google/protobuf/descriptor.proto\" "
4673     "message_type: { name: \"Bar\" field: { "
4674     "  name: \"foo\" number: 1 label: LABEL_OPTIONAL type: TYPE_INT32 } "
4675     "} "
4676     "extension { name: \"bar\" number: 7672757 label: LABEL_OPTIONAL "
4677     "            type: TYPE_MESSAGE type_name: \"Bar\" "
4678     "            extendee: \"google.protobuf.FileOptions\" }");
4679 
4680   BuildFileWithErrors(
4681     "name: \"qux.proto\" "
4682     "package: \"qux.baz\" "
4683     "options { uninterpreted_option { name { name_part: \"baz.bar\" "
4684     "                                        is_extension: true } "
4685     "                                 name { name_part: \"foo\" "
4686     "                                        is_extension: false } "
4687     "                                 positive_int_value: 1 } }",
4688 
4689     "qux.proto: qux.proto: OPTION_NAME: Option \"(baz.bar)\" is resolved to "
4690     "\"(qux.baz.bar)\","
4691     " which is not defined. The innermost scope is searched first in name "
4692     "resolution. Consider using a leading '.'(i.e., \"(.baz.bar)\") to start "
4693     "from the outermost scope.\n");
4694 }
4695 
TEST_F(ValidationErrorTest,UnknownOption)4696 TEST_F(ValidationErrorTest, UnknownOption) {
4697   BuildFileWithErrors(
4698     "name: \"qux.proto\" "
4699     "package: \"qux.baz\" "
4700     "options { uninterpreted_option { name { name_part: \"baaz.bar\" "
4701     "                                        is_extension: true } "
4702     "                                 name { name_part: \"foo\" "
4703     "                                        is_extension: false } "
4704     "                                 positive_int_value: 1 } }",
4705 
4706     "qux.proto: qux.proto: OPTION_NAME: Option \"(baaz.bar)\" unknown.\n");
4707 }
4708 
TEST_F(ValidationErrorTest,CustomOptionConflictingFieldNumber)4709 TEST_F(ValidationErrorTest, CustomOptionConflictingFieldNumber) {
4710   BuildDescriptorMessagesInTestPool();
4711 
4712   BuildFileWithErrors(
4713     "name: \"foo.proto\" "
4714     "dependency: \"google/protobuf/descriptor.proto\" "
4715     "extension { name: \"foo1\" number: 7672757 label: LABEL_OPTIONAL "
4716     "            type: TYPE_INT32 extendee: \"google.protobuf.FieldOptions\" }"
4717     "extension { name: \"foo2\" number: 7672757 label: LABEL_OPTIONAL "
4718     "            type: TYPE_INT32 extendee: \"google.protobuf.FieldOptions\" }",
4719 
4720     "foo.proto: foo2: NUMBER: Extension number 7672757 has already been used "
4721     "in \"google.protobuf.FieldOptions\" by extension \"foo1\".\n");
4722 }
4723 
TEST_F(ValidationErrorTest,Int32OptionValueOutOfPositiveRange)4724 TEST_F(ValidationErrorTest, Int32OptionValueOutOfPositiveRange) {
4725   BuildDescriptorMessagesInTestPool();
4726 
4727   BuildFileWithErrors(
4728     "name: \"foo.proto\" "
4729     "dependency: \"google/protobuf/descriptor.proto\" "
4730     "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
4731     "            type: TYPE_INT32 extendee: \"google.protobuf.FileOptions\" }"
4732     "options { uninterpreted_option { name { name_part: \"foo\" "
4733     "                                        is_extension: true } "
4734     "                                 positive_int_value: 0x80000000 } "
4735     "}",
4736 
4737     "foo.proto: foo.proto: OPTION_VALUE: Value out of range "
4738     "for int32 option \"foo\".\n");
4739 }
4740 
TEST_F(ValidationErrorTest,Int32OptionValueOutOfNegativeRange)4741 TEST_F(ValidationErrorTest, Int32OptionValueOutOfNegativeRange) {
4742   BuildDescriptorMessagesInTestPool();
4743 
4744   BuildFileWithErrors(
4745     "name: \"foo.proto\" "
4746     "dependency: \"google/protobuf/descriptor.proto\" "
4747     "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
4748     "            type: TYPE_INT32 extendee: \"google.protobuf.FileOptions\" }"
4749     "options { uninterpreted_option { name { name_part: \"foo\" "
4750     "                                        is_extension: true } "
4751     "                                 negative_int_value: -0x80000001 } "
4752     "}",
4753 
4754     "foo.proto: foo.proto: OPTION_VALUE: Value out of range "
4755     "for int32 option \"foo\".\n");
4756 }
4757 
TEST_F(ValidationErrorTest,Int32OptionValueIsNotPositiveInt)4758 TEST_F(ValidationErrorTest, Int32OptionValueIsNotPositiveInt) {
4759   BuildDescriptorMessagesInTestPool();
4760 
4761   BuildFileWithErrors(
4762     "name: \"foo.proto\" "
4763     "dependency: \"google/protobuf/descriptor.proto\" "
4764     "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
4765     "            type: TYPE_INT32 extendee: \"google.protobuf.FileOptions\" }"
4766     "options { uninterpreted_option { name { name_part: \"foo\" "
4767     "                                        is_extension: true } "
4768     "                                 string_value: \"5\" } }",
4769 
4770     "foo.proto: foo.proto: OPTION_VALUE: Value must be integer "
4771     "for int32 option \"foo\".\n");
4772 }
4773 
TEST_F(ValidationErrorTest,Int64OptionValueOutOfRange)4774 TEST_F(ValidationErrorTest, Int64OptionValueOutOfRange) {
4775   BuildDescriptorMessagesInTestPool();
4776 
4777   BuildFileWithErrors(
4778     "name: \"foo.proto\" "
4779     "dependency: \"google/protobuf/descriptor.proto\" "
4780     "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
4781     "            type: TYPE_INT64 extendee: \"google.protobuf.FileOptions\" }"
4782     "options { uninterpreted_option { name { name_part: \"foo\" "
4783     "                                        is_extension: true } "
4784     "                                 positive_int_value: 0x8000000000000000 } "
4785     "}",
4786 
4787     "foo.proto: foo.proto: OPTION_VALUE: Value out of range "
4788     "for int64 option \"foo\".\n");
4789 }
4790 
TEST_F(ValidationErrorTest,Int64OptionValueIsNotPositiveInt)4791 TEST_F(ValidationErrorTest, Int64OptionValueIsNotPositiveInt) {
4792   BuildDescriptorMessagesInTestPool();
4793 
4794   BuildFileWithErrors(
4795     "name: \"foo.proto\" "
4796     "dependency: \"google/protobuf/descriptor.proto\" "
4797     "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
4798     "            type: TYPE_INT64 extendee: \"google.protobuf.FileOptions\" }"
4799     "options { uninterpreted_option { name { name_part: \"foo\" "
4800     "                                        is_extension: true } "
4801     "                                 identifier_value: \"5\" } }",
4802 
4803     "foo.proto: foo.proto: OPTION_VALUE: Value must be integer "
4804     "for int64 option \"foo\".\n");
4805 }
4806 
TEST_F(ValidationErrorTest,UInt32OptionValueOutOfRange)4807 TEST_F(ValidationErrorTest, UInt32OptionValueOutOfRange) {
4808   BuildDescriptorMessagesInTestPool();
4809 
4810   BuildFileWithErrors(
4811     "name: \"foo.proto\" "
4812     "dependency: \"google/protobuf/descriptor.proto\" "
4813     "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
4814     "            type: TYPE_UINT32 extendee: \"google.protobuf.FileOptions\" }"
4815     "options { uninterpreted_option { name { name_part: \"foo\" "
4816     "                                        is_extension: true } "
4817     "                                 positive_int_value: 0x100000000 } }",
4818 
4819     "foo.proto: foo.proto: OPTION_VALUE: Value out of range "
4820     "for uint32 option \"foo\".\n");
4821 }
4822 
TEST_F(ValidationErrorTest,UInt32OptionValueIsNotPositiveInt)4823 TEST_F(ValidationErrorTest, UInt32OptionValueIsNotPositiveInt) {
4824   BuildDescriptorMessagesInTestPool();
4825 
4826   BuildFileWithErrors(
4827     "name: \"foo.proto\" "
4828     "dependency: \"google/protobuf/descriptor.proto\" "
4829     "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
4830     "            type: TYPE_UINT32 extendee: \"google.protobuf.FileOptions\" }"
4831     "options { uninterpreted_option { name { name_part: \"foo\" "
4832     "                                        is_extension: true } "
4833     "                                 double_value: -5.6 } }",
4834 
4835     "foo.proto: foo.proto: OPTION_VALUE: Value must be non-negative integer "
4836     "for uint32 option \"foo\".\n");
4837 }
4838 
TEST_F(ValidationErrorTest,UInt64OptionValueIsNotPositiveInt)4839 TEST_F(ValidationErrorTest, UInt64OptionValueIsNotPositiveInt) {
4840   BuildDescriptorMessagesInTestPool();
4841 
4842   BuildFileWithErrors(
4843     "name: \"foo.proto\" "
4844     "dependency: \"google/protobuf/descriptor.proto\" "
4845     "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
4846     "            type: TYPE_UINT64 extendee: \"google.protobuf.FileOptions\" }"
4847     "options { uninterpreted_option { name { name_part: \"foo\" "
4848     "                                        is_extension: true } "
4849     "                                 negative_int_value: -5 } }",
4850 
4851     "foo.proto: foo.proto: OPTION_VALUE: Value must be non-negative integer "
4852     "for uint64 option \"foo\".\n");
4853 }
4854 
TEST_F(ValidationErrorTest,FloatOptionValueIsNotNumber)4855 TEST_F(ValidationErrorTest, FloatOptionValueIsNotNumber) {
4856   BuildDescriptorMessagesInTestPool();
4857 
4858   BuildFileWithErrors(
4859     "name: \"foo.proto\" "
4860     "dependency: \"google/protobuf/descriptor.proto\" "
4861     "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
4862     "            type: TYPE_FLOAT extendee: \"google.protobuf.FileOptions\" }"
4863     "options { uninterpreted_option { name { name_part: \"foo\" "
4864     "                                        is_extension: true } "
4865     "                                 string_value: \"bar\" } }",
4866 
4867     "foo.proto: foo.proto: OPTION_VALUE: Value must be number "
4868     "for float option \"foo\".\n");
4869 }
4870 
TEST_F(ValidationErrorTest,DoubleOptionValueIsNotNumber)4871 TEST_F(ValidationErrorTest, DoubleOptionValueIsNotNumber) {
4872   BuildDescriptorMessagesInTestPool();
4873 
4874   BuildFileWithErrors(
4875     "name: \"foo.proto\" "
4876     "dependency: \"google/protobuf/descriptor.proto\" "
4877     "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
4878     "            type: TYPE_DOUBLE extendee: \"google.protobuf.FileOptions\" }"
4879     "options { uninterpreted_option { name { name_part: \"foo\" "
4880     "                                        is_extension: true } "
4881     "                                 string_value: \"bar\" } }",
4882 
4883     "foo.proto: foo.proto: OPTION_VALUE: Value must be number "
4884     "for double option \"foo\".\n");
4885 }
4886 
TEST_F(ValidationErrorTest,BoolOptionValueIsNotTrueOrFalse)4887 TEST_F(ValidationErrorTest, BoolOptionValueIsNotTrueOrFalse) {
4888   BuildDescriptorMessagesInTestPool();
4889 
4890   BuildFileWithErrors(
4891     "name: \"foo.proto\" "
4892     "dependency: \"google/protobuf/descriptor.proto\" "
4893     "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
4894     "            type: TYPE_BOOL extendee: \"google.protobuf.FileOptions\" }"
4895     "options { uninterpreted_option { name { name_part: \"foo\" "
4896     "                                        is_extension: true } "
4897     "                                 identifier_value: \"bar\" } }",
4898 
4899     "foo.proto: foo.proto: OPTION_VALUE: Value must be \"true\" or \"false\" "
4900     "for boolean option \"foo\".\n");
4901 }
4902 
TEST_F(ValidationErrorTest,EnumOptionValueIsNotIdentifier)4903 TEST_F(ValidationErrorTest, EnumOptionValueIsNotIdentifier) {
4904   BuildDescriptorMessagesInTestPool();
4905 
4906   BuildFileWithErrors(
4907     "name: \"foo.proto\" "
4908     "dependency: \"google/protobuf/descriptor.proto\" "
4909     "enum_type { name: \"FooEnum\" value { name: \"BAR\" number: 1 } "
4910     "                              value { name: \"BAZ\" number: 2 } }"
4911     "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
4912     "            type: TYPE_ENUM type_name: \"FooEnum\" "
4913     "            extendee: \"google.protobuf.FileOptions\" }"
4914     "options { uninterpreted_option { name { name_part: \"foo\" "
4915     "                                        is_extension: true } "
4916     "                                 string_value: \"QUUX\" } }",
4917 
4918     "foo.proto: foo.proto: OPTION_VALUE: Value must be identifier for "
4919     "enum-valued option \"foo\".\n");
4920 }
4921 
TEST_F(ValidationErrorTest,EnumOptionValueIsNotEnumValueName)4922 TEST_F(ValidationErrorTest, EnumOptionValueIsNotEnumValueName) {
4923   BuildDescriptorMessagesInTestPool();
4924 
4925   BuildFileWithErrors(
4926     "name: \"foo.proto\" "
4927     "dependency: \"google/protobuf/descriptor.proto\" "
4928     "enum_type { name: \"FooEnum\" value { name: \"BAR\" number: 1 } "
4929     "                              value { name: \"BAZ\" number: 2 } }"
4930     "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
4931     "            type: TYPE_ENUM type_name: \"FooEnum\" "
4932     "            extendee: \"google.protobuf.FileOptions\" }"
4933     "options { uninterpreted_option { name { name_part: \"foo\" "
4934     "                                        is_extension: true } "
4935     "                                 identifier_value: \"QUUX\" } }",
4936 
4937     "foo.proto: foo.proto: OPTION_VALUE: Enum type \"FooEnum\" has no value "
4938     "named \"QUUX\" for option \"foo\".\n");
4939 }
4940 
TEST_F(ValidationErrorTest,EnumOptionValueIsSiblingEnumValueName)4941 TEST_F(ValidationErrorTest, EnumOptionValueIsSiblingEnumValueName) {
4942   BuildDescriptorMessagesInTestPool();
4943 
4944   BuildFileWithErrors(
4945     "name: \"foo.proto\" "
4946     "dependency: \"google/protobuf/descriptor.proto\" "
4947     "enum_type { name: \"FooEnum1\" value { name: \"BAR\" number: 1 } "
4948     "                               value { name: \"BAZ\" number: 2 } }"
4949     "enum_type { name: \"FooEnum2\" value { name: \"QUX\" number: 1 } "
4950     "                               value { name: \"QUUX\" number: 2 } }"
4951     "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
4952     "            type: TYPE_ENUM type_name: \"FooEnum1\" "
4953     "            extendee: \"google.protobuf.FileOptions\" }"
4954     "options { uninterpreted_option { name { name_part: \"foo\" "
4955     "                                        is_extension: true } "
4956     "                                 identifier_value: \"QUUX\" } }",
4957 
4958     "foo.proto: foo.proto: OPTION_VALUE: Enum type \"FooEnum1\" has no value "
4959     "named \"QUUX\" for option \"foo\". This appears to be a value from a "
4960     "sibling type.\n");
4961 }
4962 
TEST_F(ValidationErrorTest,StringOptionValueIsNotString)4963 TEST_F(ValidationErrorTest, StringOptionValueIsNotString) {
4964   BuildDescriptorMessagesInTestPool();
4965 
4966   BuildFileWithErrors(
4967     "name: \"foo.proto\" "
4968     "dependency: \"google/protobuf/descriptor.proto\" "
4969     "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
4970     "            type: TYPE_STRING extendee: \"google.protobuf.FileOptions\" }"
4971     "options { uninterpreted_option { name { name_part: \"foo\" "
4972     "                                        is_extension: true } "
4973     "                                 identifier_value: \"QUUX\" } }",
4974 
4975     "foo.proto: foo.proto: OPTION_VALUE: Value must be quoted string for "
4976     "string option \"foo\".\n");
4977 }
4978 
TEST_F(ValidationErrorTest,DuplicateExtensionFieldNumber)4979 TEST_F(ValidationErrorTest, DuplicateExtensionFieldNumber) {
4980   BuildDescriptorMessagesInTestPool();
4981 
4982   BuildFile(
4983       "name: \"foo.proto\" "
4984       "dependency: \"google/protobuf/descriptor.proto\" "
4985       "extension { name: \"option1\" number: 1000 label: LABEL_OPTIONAL "
4986       "            type: TYPE_INT32 extendee: \"google.protobuf.FileOptions\" }");
4987 
4988   BuildFileWithWarnings(
4989       "name: \"bar.proto\" "
4990       "dependency: \"google/protobuf/descriptor.proto\" "
4991       "extension { name: \"option2\" number: 1000 label: LABEL_OPTIONAL "
4992       "            type: TYPE_INT32 extendee: \"google.protobuf.FileOptions\" }",
4993       "bar.proto: option2: NUMBER: Extension number 1000 has already been used "
4994       "in \"google.protobuf.FileOptions\" by extension \"option1\" defined in "
4995       "foo.proto.\n");
4996 }
4997 
4998 // Helper function for tests that check for aggregate value parsing
4999 // errors.  The "value" argument is embedded inside the
5000 // "uninterpreted_option" portion of the result.
EmbedAggregateValue(const char * value)5001 static string EmbedAggregateValue(const char* value) {
5002   return strings::Substitute(
5003       "name: \"foo.proto\" "
5004       "dependency: \"google/protobuf/descriptor.proto\" "
5005       "message_type { name: \"Foo\" } "
5006       "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
5007       "            type: TYPE_MESSAGE type_name: \"Foo\" "
5008       "            extendee: \"google.protobuf.FileOptions\" }"
5009       "options { uninterpreted_option { name { name_part: \"foo\" "
5010       "                                        is_extension: true } "
5011       "                                 $0 } }",
5012       value);
5013 }
5014 
TEST_F(ValidationErrorTest,AggregateValueNotFound)5015 TEST_F(ValidationErrorTest, AggregateValueNotFound) {
5016   BuildDescriptorMessagesInTestPool();
5017 
5018   BuildFileWithErrors(
5019       EmbedAggregateValue("string_value: \"\""),
5020       "foo.proto: foo.proto: OPTION_VALUE: Option \"foo\" is a message. "
5021       "To set the entire message, use syntax like "
5022       "\"foo = { <proto text format> }\". To set fields within it, use "
5023       "syntax like \"foo.foo = value\".\n");
5024 }
5025 
TEST_F(ValidationErrorTest,AggregateValueParseError)5026 TEST_F(ValidationErrorTest, AggregateValueParseError) {
5027   BuildDescriptorMessagesInTestPool();
5028 
5029   BuildFileWithErrors(
5030       EmbedAggregateValue("aggregate_value: \"1+2\""),
5031       "foo.proto: foo.proto: OPTION_VALUE: Error while parsing option "
5032       "value for \"foo\": Expected identifier, got: 1\n");
5033 }
5034 
TEST_F(ValidationErrorTest,AggregateValueUnknownFields)5035 TEST_F(ValidationErrorTest, AggregateValueUnknownFields) {
5036   BuildDescriptorMessagesInTestPool();
5037 
5038   BuildFileWithErrors(
5039       EmbedAggregateValue("aggregate_value: \"x:100\""),
5040       "foo.proto: foo.proto: OPTION_VALUE: Error while parsing option "
5041       "value for \"foo\": Message type \"Foo\" has no field named \"x\".\n");
5042 }
5043 
TEST_F(ValidationErrorTest,NotLiteImportsLite)5044 TEST_F(ValidationErrorTest, NotLiteImportsLite) {
5045   BuildFile(
5046     "name: \"bar.proto\" "
5047     "options { optimize_for: LITE_RUNTIME } ");
5048 
5049   BuildFileWithErrors(
5050     "name: \"foo.proto\" "
5051     "dependency: \"bar.proto\" ",
5052 
5053     "foo.proto: foo.proto: OTHER: Files that do not use optimize_for = "
5054       "LITE_RUNTIME cannot import files which do use this option.  This file "
5055       "is not lite, but it imports \"bar.proto\" which is.\n");
5056 }
5057 
TEST_F(ValidationErrorTest,LiteExtendsNotLite)5058 TEST_F(ValidationErrorTest, LiteExtendsNotLite) {
5059   BuildFile(
5060     "name: \"bar.proto\" "
5061     "message_type: {"
5062     "  name: \"Bar\""
5063     "  extension_range { start: 1 end: 1000 }"
5064     "}");
5065 
5066   BuildFileWithErrors(
5067     "name: \"foo.proto\" "
5068     "dependency: \"bar.proto\" "
5069     "options { optimize_for: LITE_RUNTIME } "
5070     "extension { name: \"ext\" number: 123 label: LABEL_OPTIONAL "
5071     "            type: TYPE_INT32 extendee: \"Bar\" }",
5072 
5073     "foo.proto: ext: EXTENDEE: Extensions to non-lite types can only be "
5074       "declared in non-lite files.  Note that you cannot extend a non-lite "
5075       "type to contain a lite type, but the reverse is allowed.\n");
5076 }
5077 
TEST_F(ValidationErrorTest,NoLiteServices)5078 TEST_F(ValidationErrorTest, NoLiteServices) {
5079   BuildFileWithErrors(
5080     "name: \"foo.proto\" "
5081     "options {"
5082     "  optimize_for: LITE_RUNTIME"
5083     "  cc_generic_services: true"
5084     "  java_generic_services: true"
5085     "} "
5086     "service { name: \"Foo\" }",
5087 
5088     "foo.proto: Foo: NAME: Files with optimize_for = LITE_RUNTIME cannot "
5089     "define services unless you set both options cc_generic_services and "
5090     "java_generic_sevices to false.\n");
5091 
5092   BuildFile(
5093     "name: \"bar.proto\" "
5094     "options {"
5095     "  optimize_for: LITE_RUNTIME"
5096     "  cc_generic_services: false"
5097     "  java_generic_services: false"
5098     "} "
5099     "service { name: \"Bar\" }");
5100 }
5101 
TEST_F(ValidationErrorTest,RollbackAfterError)5102 TEST_F(ValidationErrorTest, RollbackAfterError) {
5103   // Build a file which contains every kind of construct but references an
5104   // undefined type.  All these constructs will be added to the symbol table
5105   // before the undefined type error is noticed.  The DescriptorPool will then
5106   // have to roll everything back.
5107   BuildFileWithErrors(
5108     "name: \"foo.proto\" "
5109     "message_type {"
5110     "  name: \"TestMessage\""
5111     "  field { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:1 }"
5112     "} "
5113     "enum_type {"
5114     "  name: \"TestEnum\""
5115     "  value { name:\"BAR\" number:1 }"
5116     "} "
5117     "service {"
5118     "  name: \"TestService\""
5119     "  method {"
5120     "    name: \"Baz\""
5121     "    input_type: \"NoSuchType\""    // error
5122     "    output_type: \"TestMessage\""
5123     "  }"
5124     "}",
5125 
5126     "foo.proto: TestService.Baz: INPUT_TYPE: \"NoSuchType\" is not defined.\n"
5127     );
5128 
5129   // Make sure that if we build the same file again with the error fixed,
5130   // it works.  If the above rollback was incomplete, then some symbols will
5131   // be left defined, and this second attempt will fail since it tries to
5132   // re-define the same symbols.
5133   BuildFile(
5134     "name: \"foo.proto\" "
5135     "message_type {"
5136     "  name: \"TestMessage\""
5137     "  field { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:1 }"
5138     "} "
5139     "enum_type {"
5140     "  name: \"TestEnum\""
5141     "  value { name:\"BAR\" number:1 }"
5142     "} "
5143     "service {"
5144     "  name: \"TestService\""
5145     "  method { name:\"Baz\""
5146     "           input_type:\"TestMessage\""
5147     "           output_type:\"TestMessage\" }"
5148     "}");
5149 }
5150 
TEST_F(ValidationErrorTest,ErrorsReportedToLogError)5151 TEST_F(ValidationErrorTest, ErrorsReportedToLogError) {
5152   // Test that errors are reported to GOOGLE_LOG(ERROR) if no error collector is
5153   // provided.
5154 
5155   FileDescriptorProto file_proto;
5156   ASSERT_TRUE(TextFormat::ParseFromString(
5157     "name: \"foo.proto\" "
5158     "message_type { name: \"Foo\" } "
5159     "message_type { name: \"Foo\" } ",
5160     &file_proto));
5161 
5162   vector<string> errors;
5163 
5164   {
5165     ScopedMemoryLog log;
5166     EXPECT_TRUE(pool_.BuildFile(file_proto) == NULL);
5167     errors = log.GetMessages(ERROR);
5168   }
5169 
5170   ASSERT_EQ(2, errors.size());
5171 
5172   EXPECT_EQ("Invalid proto descriptor for file \"foo.proto\":", errors[0]);
5173   EXPECT_EQ("  Foo: \"Foo\" is already defined.", errors[1]);
5174 }
5175 
TEST_F(ValidationErrorTest,DisallowEnumAlias)5176 TEST_F(ValidationErrorTest, DisallowEnumAlias) {
5177   BuildFileWithErrors(
5178     "name: \"foo.proto\" "
5179     "enum_type {"
5180     "  name: \"Bar\""
5181     "  value { name:\"ENUM_A\" number:0 }"
5182     "  value { name:\"ENUM_B\" number:0 }"
5183     "}",
5184     "foo.proto: Bar: NUMBER: "
5185     "\"ENUM_B\" uses the same enum value as \"ENUM_A\". "
5186     "If this is intended, set 'option allow_alias = true;' to the enum "
5187     "definition.\n");
5188 }
5189 
TEST_F(ValidationErrorTest,AllowEnumAlias)5190 TEST_F(ValidationErrorTest, AllowEnumAlias) {
5191   BuildFile(
5192     "name: \"foo.proto\" "
5193     "enum_type {"
5194     "  name: \"Bar\""
5195     "  value { name:\"ENUM_A\" number:0 }"
5196     "  value { name:\"ENUM_B\" number:0 }"
5197     "  options { allow_alias: true }"
5198     "}");
5199 }
5200 
TEST_F(ValidationErrorTest,UnusedImportWarning)5201 TEST_F(ValidationErrorTest, UnusedImportWarning) {
5202   pool_.AddUnusedImportTrackFile("bar.proto");
5203   BuildFile(
5204     "name: \"bar.proto\" "
5205     "message_type { name: \"Bar\" }");
5206 
5207   pool_.AddUnusedImportTrackFile("base.proto");
5208   BuildFile(
5209     "name: \"base.proto\" "
5210     "message_type { name: \"Base\" }");
5211 
5212   pool_.AddUnusedImportTrackFile("baz.proto");
5213   BuildFile(
5214     "name: \"baz.proto\" "
5215     "message_type { name: \"Baz\" }");
5216 
5217   pool_.AddUnusedImportTrackFile("public.proto");
5218   BuildFile(
5219     "name: \"public.proto\" "
5220     "dependency: \"bar.proto\""
5221     "public_dependency: 0");
5222 
5223   // // forward.proto
5224   // import "base.proto"       // No warning: Base message is used.
5225   // import "bar.proto"        // Will log a warning.
5226   // import public "baz.proto" // No warning: Do not track import public.
5227   // import "public.proto"     // No warning: public.proto has import public.
5228   // message Forward {
5229   //   optional Base base = 1;
5230   // }
5231   //
5232   pool_.AddUnusedImportTrackFile("forward.proto");
5233   BuildFileWithWarnings(
5234     "name: \"forward.proto\""
5235     "dependency: \"base.proto\""
5236     "dependency: \"bar.proto\""
5237     "dependency: \"baz.proto\""
5238     "dependency: \"public.proto\""
5239     "public_dependency: 2 "
5240     "message_type {"
5241     "  name: \"Forward\""
5242     "  field { name:\"base\" number:1 label:LABEL_OPTIONAL type_name:\"Base\" }"
5243     "}",
5244     "forward.proto: bar.proto: OTHER: Import bar.proto but not used.\n");
5245 }
5246 
5247 namespace {
FillValidMapEntry(FileDescriptorProto * file_proto)5248 void FillValidMapEntry(FileDescriptorProto* file_proto) {
5249   ASSERT_TRUE(TextFormat::ParseFromString(
5250       "name: 'foo.proto' "
5251       "message_type { "
5252       "  name: 'Foo' "
5253       "  field { "
5254       "    name: 'foo_map' number: 1 label:LABEL_REPEATED "
5255       "    type_name: 'FooMapEntry' "
5256       "  } "
5257       "  nested_type { "
5258       "    name: 'FooMapEntry' "
5259       "    options {  map_entry: true } "
5260       "    field { "
5261       "      name: 'key' number: 1 type:TYPE_INT32 label:LABEL_OPTIONAL "
5262       "    } "
5263       "    field { "
5264       "      name: 'value' number: 2 type:TYPE_INT32 label:LABEL_OPTIONAL "
5265       "    } "
5266       "  } "
5267       "} "
5268       "message_type { "
5269       "  name: 'Bar' "
5270       "  extension_range { start: 1 end: 10 }"
5271       "} ",
5272       file_proto));
5273 }
5274 static const char* kMapEntryErrorMessage =
5275     "foo.proto: Foo.foo_map: OTHER: map_entry should not be set explicitly. "
5276     "Use map<KeyType, ValueType> instead.\n";
5277 static const char* kMapEntryKeyTypeErrorMessage =
5278     "foo.proto: Foo.foo_map: TYPE: Key in map fields cannot be float/double, "
5279     "bytes or message types.\n";
5280 
5281 }  // namespace
5282 
TEST_F(ValidationErrorTest,MapEntryBase)5283 TEST_F(ValidationErrorTest, MapEntryBase) {
5284   FileDescriptorProto file_proto;
5285   FillValidMapEntry(&file_proto);
5286   BuildFile(file_proto.DebugString());
5287 }
5288 
TEST_F(ValidationErrorTest,MapEntryExtensionRange)5289 TEST_F(ValidationErrorTest, MapEntryExtensionRange) {
5290   FileDescriptorProto file_proto;
5291   FillValidMapEntry(&file_proto);
5292   TextFormat::MergeFromString(
5293       "extension_range { "
5294       "  start: 10 end: 20 "
5295       "} ",
5296       file_proto.mutable_message_type(0)->mutable_nested_type(0));
5297   BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage);
5298 }
5299 
TEST_F(ValidationErrorTest,MapEntryExtension)5300 TEST_F(ValidationErrorTest, MapEntryExtension) {
5301   FileDescriptorProto file_proto;
5302   FillValidMapEntry(&file_proto);
5303   TextFormat::MergeFromString(
5304       "extension { "
5305       "  name: 'foo_ext' extendee: '.Bar' number: 5"
5306       "} ",
5307       file_proto.mutable_message_type(0)->mutable_nested_type(0));
5308   BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage);
5309 }
5310 
TEST_F(ValidationErrorTest,MapEntryNestedType)5311 TEST_F(ValidationErrorTest, MapEntryNestedType) {
5312   FileDescriptorProto file_proto;
5313   FillValidMapEntry(&file_proto);
5314   TextFormat::MergeFromString(
5315       "nested_type { "
5316       "  name: 'Bar' "
5317       "} ",
5318       file_proto.mutable_message_type(0)->mutable_nested_type(0));
5319   BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage);
5320 }
5321 
TEST_F(ValidationErrorTest,MapEntryEnumTypes)5322 TEST_F(ValidationErrorTest, MapEntryEnumTypes) {
5323   FileDescriptorProto file_proto;
5324   FillValidMapEntry(&file_proto);
5325   TextFormat::MergeFromString(
5326       "enum_type { "
5327       "  name: 'BarEnum' "
5328       "  value { name: 'BAR_BAR' number:0 } "
5329       "} ",
5330       file_proto.mutable_message_type(0)->mutable_nested_type(0));
5331   BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage);
5332 }
5333 
TEST_F(ValidationErrorTest,MapEntryExtraField)5334 TEST_F(ValidationErrorTest, MapEntryExtraField) {
5335   FileDescriptorProto file_proto;
5336   FillValidMapEntry(&file_proto);
5337   TextFormat::MergeFromString(
5338       "field { "
5339       "  name: 'other_field' "
5340       "  label: LABEL_OPTIONAL "
5341       "  type: TYPE_INT32 "
5342       "  number: 3 "
5343       "} ",
5344       file_proto.mutable_message_type(0)->mutable_nested_type(0));
5345   BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage);
5346 }
5347 
TEST_F(ValidationErrorTest,MapEntryMessageName)5348 TEST_F(ValidationErrorTest, MapEntryMessageName) {
5349   FileDescriptorProto file_proto;
5350   FillValidMapEntry(&file_proto);
5351   file_proto.mutable_message_type(0)->mutable_nested_type(0)->set_name(
5352       "OtherMapEntry");
5353   file_proto.mutable_message_type(0)->mutable_field(0)->set_type_name(
5354       "OtherMapEntry");
5355   BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage);
5356 }
5357 
TEST_F(ValidationErrorTest,MapEntryNoneRepeatedMapEntry)5358 TEST_F(ValidationErrorTest, MapEntryNoneRepeatedMapEntry) {
5359   FileDescriptorProto file_proto;
5360   FillValidMapEntry(&file_proto);
5361   file_proto.mutable_message_type(0)->mutable_field(0)->set_label(
5362       FieldDescriptorProto::LABEL_OPTIONAL);
5363   BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage);
5364 }
5365 
TEST_F(ValidationErrorTest,MapEntryDifferentContainingType)5366 TEST_F(ValidationErrorTest, MapEntryDifferentContainingType) {
5367   FileDescriptorProto file_proto;
5368   FillValidMapEntry(&file_proto);
5369   // Move the nested MapEntry message into the top level, which should not pass
5370   // the validation.
5371   file_proto.mutable_message_type()->AddAllocated(
5372       file_proto.mutable_message_type(0)->mutable_nested_type()->ReleaseLast());
5373   BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage);
5374 }
5375 
TEST_F(ValidationErrorTest,MapEntryKeyName)5376 TEST_F(ValidationErrorTest, MapEntryKeyName) {
5377   FileDescriptorProto file_proto;
5378   FillValidMapEntry(&file_proto);
5379   FieldDescriptorProto* key = file_proto.mutable_message_type(0)
5380       ->mutable_nested_type(0)
5381       ->mutable_field(0);
5382   key->set_name("Key");
5383   BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage);
5384 }
5385 
TEST_F(ValidationErrorTest,MapEntryKeyLabel)5386 TEST_F(ValidationErrorTest, MapEntryKeyLabel) {
5387   FileDescriptorProto file_proto;
5388   FillValidMapEntry(&file_proto);
5389   FieldDescriptorProto* key = file_proto.mutable_message_type(0)
5390       ->mutable_nested_type(0)
5391       ->mutable_field(0);
5392   key->set_label(FieldDescriptorProto::LABEL_REQUIRED);
5393   BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage);
5394 }
5395 
TEST_F(ValidationErrorTest,MapEntryKeyNumber)5396 TEST_F(ValidationErrorTest, MapEntryKeyNumber) {
5397   FileDescriptorProto file_proto;
5398   FillValidMapEntry(&file_proto);
5399   FieldDescriptorProto* key = file_proto.mutable_message_type(0)
5400       ->mutable_nested_type(0)
5401       ->mutable_field(0);
5402   key->set_number(3);
5403   BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage);
5404 }
5405 
TEST_F(ValidationErrorTest,MapEntryValueName)5406 TEST_F(ValidationErrorTest, MapEntryValueName) {
5407   FileDescriptorProto file_proto;
5408   FillValidMapEntry(&file_proto);
5409   FieldDescriptorProto* value = file_proto.mutable_message_type(0)
5410       ->mutable_nested_type(0)
5411       ->mutable_field(1);
5412   value->set_name("Value");
5413   BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage);
5414 }
5415 
TEST_F(ValidationErrorTest,MapEntryValueLabel)5416 TEST_F(ValidationErrorTest, MapEntryValueLabel) {
5417   FileDescriptorProto file_proto;
5418   FillValidMapEntry(&file_proto);
5419   FieldDescriptorProto* value = file_proto.mutable_message_type(0)
5420       ->mutable_nested_type(0)
5421       ->mutable_field(1);
5422   value->set_label(FieldDescriptorProto::LABEL_REQUIRED);
5423   BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage);
5424 }
5425 
TEST_F(ValidationErrorTest,MapEntryValueNumber)5426 TEST_F(ValidationErrorTest, MapEntryValueNumber) {
5427   FileDescriptorProto file_proto;
5428   FillValidMapEntry(&file_proto);
5429   FieldDescriptorProto* value = file_proto.mutable_message_type(0)
5430       ->mutable_nested_type(0)
5431       ->mutable_field(1);
5432   value->set_number(3);
5433   BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage);
5434 }
5435 
TEST_F(ValidationErrorTest,MapEntryKeyTypeFloat)5436 TEST_F(ValidationErrorTest, MapEntryKeyTypeFloat) {
5437   FileDescriptorProto file_proto;
5438   FillValidMapEntry(&file_proto);
5439   FieldDescriptorProto* key = file_proto.mutable_message_type(0)
5440       ->mutable_nested_type(0)
5441       ->mutable_field(0);
5442   key->set_type(FieldDescriptorProto::TYPE_FLOAT);
5443   BuildFileWithErrors(file_proto.DebugString(), kMapEntryKeyTypeErrorMessage);
5444 }
5445 
TEST_F(ValidationErrorTest,MapEntryKeyTypeDouble)5446 TEST_F(ValidationErrorTest, MapEntryKeyTypeDouble) {
5447   FileDescriptorProto file_proto;
5448   FillValidMapEntry(&file_proto);
5449   FieldDescriptorProto* key = file_proto.mutable_message_type(0)
5450       ->mutable_nested_type(0)
5451       ->mutable_field(0);
5452   key->set_type(FieldDescriptorProto::TYPE_DOUBLE);
5453   BuildFileWithErrors(file_proto.DebugString(), kMapEntryKeyTypeErrorMessage);
5454 }
5455 
TEST_F(ValidationErrorTest,MapEntryKeyTypeBytes)5456 TEST_F(ValidationErrorTest, MapEntryKeyTypeBytes) {
5457   FileDescriptorProto file_proto;
5458   FillValidMapEntry(&file_proto);
5459   FieldDescriptorProto* key = file_proto.mutable_message_type(0)
5460       ->mutable_nested_type(0)
5461       ->mutable_field(0);
5462   key->set_type(FieldDescriptorProto::TYPE_BYTES);
5463   BuildFileWithErrors(file_proto.DebugString(), kMapEntryKeyTypeErrorMessage);
5464 }
5465 
TEST_F(ValidationErrorTest,MapEntryKeyTypeEnum)5466 TEST_F(ValidationErrorTest, MapEntryKeyTypeEnum) {
5467   FileDescriptorProto file_proto;
5468   FillValidMapEntry(&file_proto);
5469   FieldDescriptorProto* key = file_proto.mutable_message_type(0)
5470       ->mutable_nested_type(0)
5471       ->mutable_field(0);
5472   key->clear_type();
5473   key->set_type_name("BarEnum");
5474   EnumDescriptorProto* enum_proto = file_proto.add_enum_type();
5475   enum_proto->set_name("BarEnum");
5476   EnumValueDescriptorProto* enum_value_proto = enum_proto->add_value();
5477   enum_value_proto->set_name("BAR_VALUE0");
5478   enum_value_proto->set_number(0);
5479   BuildFileWithErrors(file_proto.DebugString(),
5480                       "foo.proto: Foo.foo_map: TYPE: Key in map fields cannot "
5481                       "be enum types.\n");
5482   // Enum keys are not allowed in proto3 as well.
5483   // Get rid of extensions for proto3 to make it proto3 compatible.
5484   file_proto.mutable_message_type()->RemoveLast();
5485   file_proto.set_syntax("proto3");
5486   BuildFileWithErrors(file_proto.DebugString(),
5487                       "foo.proto: Foo.foo_map: TYPE: Key in map fields cannot "
5488                       "be enum types.\n");
5489 }
5490 
5491 
TEST_F(ValidationErrorTest,MapEntryKeyTypeMessage)5492 TEST_F(ValidationErrorTest, MapEntryKeyTypeMessage) {
5493   FileDescriptorProto file_proto;
5494   FillValidMapEntry(&file_proto);
5495   FieldDescriptorProto* key = file_proto.mutable_message_type(0)
5496       ->mutable_nested_type(0)
5497       ->mutable_field(0);
5498   key->clear_type();
5499   key->set_type_name(".Bar");
5500   BuildFileWithErrors(file_proto.DebugString(), kMapEntryKeyTypeErrorMessage);
5501 }
5502 
TEST_F(ValidationErrorTest,MapEntryConflictsWithField)5503 TEST_F(ValidationErrorTest, MapEntryConflictsWithField) {
5504   FileDescriptorProto file_proto;
5505   FillValidMapEntry(&file_proto);
5506   TextFormat::MergeFromString(
5507       "field { "
5508       "  name: 'FooMapEntry' "
5509       "  type: TYPE_INT32 "
5510       "  label: LABEL_OPTIONAL "
5511       "  number: 100 "
5512       "}",
5513       file_proto.mutable_message_type(0));
5514   BuildFileWithErrors(
5515       file_proto.DebugString(),
5516       "foo.proto: Foo.FooMapEntry: NAME: \"FooMapEntry\" is already defined in "
5517       "\"Foo\".\n"
5518       "foo.proto: Foo.foo_map: TYPE: \"FooMapEntry\" is not defined.\n"
5519       "foo.proto: Foo: NAME: Expanded map entry type FooMapEntry conflicts "
5520       "with an existing field.\n");
5521 }
5522 
TEST_F(ValidationErrorTest,MapEntryConflictsWithMessage)5523 TEST_F(ValidationErrorTest, MapEntryConflictsWithMessage) {
5524   FileDescriptorProto file_proto;
5525   FillValidMapEntry(&file_proto);
5526   TextFormat::MergeFromString(
5527       "nested_type { "
5528       "  name: 'FooMapEntry' "
5529       "}",
5530       file_proto.mutable_message_type(0));
5531   BuildFileWithErrors(
5532       file_proto.DebugString(),
5533       "foo.proto: Foo.FooMapEntry: NAME: \"FooMapEntry\" is already defined in "
5534       "\"Foo\".\n"
5535       "foo.proto: Foo: NAME: Expanded map entry type FooMapEntry conflicts "
5536       "with an existing nested message type.\n");
5537 }
5538 
TEST_F(ValidationErrorTest,MapEntryConflictsWithEnum)5539 TEST_F(ValidationErrorTest, MapEntryConflictsWithEnum) {
5540   FileDescriptorProto file_proto;
5541   FillValidMapEntry(&file_proto);
5542   TextFormat::MergeFromString(
5543       "enum_type { "
5544       "  name: 'FooMapEntry' "
5545       "  value { name: 'ENTRY_FOO' number: 0 }"
5546       "}",
5547       file_proto.mutable_message_type(0));
5548   BuildFileWithErrors(
5549       file_proto.DebugString(),
5550       "foo.proto: Foo.FooMapEntry: NAME: \"FooMapEntry\" is already defined in "
5551       "\"Foo\".\n"
5552       "foo.proto: Foo: NAME: Expanded map entry type FooMapEntry conflicts "
5553       "with an existing enum type.\n");
5554 }
5555 
TEST_F(ValidationErrorTest,MapEntryConflictsWithOneof)5556 TEST_F(ValidationErrorTest, MapEntryConflictsWithOneof) {
5557   FileDescriptorProto file_proto;
5558   FillValidMapEntry(&file_proto);
5559   TextFormat::MergeFromString(
5560       "oneof_decl { "
5561       "  name: 'FooMapEntry' "
5562       "}"
5563       "field { "
5564       "  name: 'int_field' "
5565       "  type: TYPE_INT32 "
5566       "  label: LABEL_OPTIONAL "
5567       "  oneof_index: 0 "
5568       "  number: 100 "
5569       "} ",
5570       file_proto.mutable_message_type(0));
5571   BuildFileWithErrors(
5572       file_proto.DebugString(),
5573       "foo.proto: Foo.FooMapEntry: NAME: \"FooMapEntry\" is already defined in "
5574       "\"Foo\".\n"
5575       "foo.proto: Foo.foo_map: TYPE: \"FooMapEntry\" is not defined.\n"
5576       "foo.proto: Foo: NAME: Expanded map entry type FooMapEntry conflicts "
5577       "with an existing oneof type.\n");
5578 }
5579 
TEST_F(ValidationErrorTest,MapEntryUsesNoneZeroEnumDefaultValue)5580 TEST_F(ValidationErrorTest, MapEntryUsesNoneZeroEnumDefaultValue) {
5581   BuildFileWithErrors(
5582     "name: \"foo.proto\" "
5583     "enum_type {"
5584     "  name: \"Bar\""
5585     "  value { name:\"ENUM_A\" number:1 }"
5586     "  value { name:\"ENUM_B\" number:2 }"
5587     "}"
5588     "message_type {"
5589     "  name: 'Foo' "
5590     "  field { "
5591     "    name: 'foo_map' number: 1 label:LABEL_REPEATED "
5592     "    type_name: 'FooMapEntry' "
5593     "  } "
5594     "  nested_type { "
5595     "    name: 'FooMapEntry' "
5596     "    options {  map_entry: true } "
5597     "    field { "
5598     "      name: 'key' number: 1 type:TYPE_INT32 label:LABEL_OPTIONAL "
5599     "    } "
5600     "    field { "
5601     "      name: 'value' number: 2 type_name:\"Bar\" label:LABEL_OPTIONAL "
5602     "    } "
5603     "  } "
5604     "}",
5605     "foo.proto: Foo.foo_map: "
5606     "TYPE: Enum value in map must define 0 as the first value.\n");
5607 }
5608 
TEST_F(ValidationErrorTest,Proto3RequiredFields)5609 TEST_F(ValidationErrorTest, Proto3RequiredFields) {
5610   BuildFileWithErrors(
5611       "name: 'foo.proto' "
5612       "syntax: 'proto3' "
5613       "message_type { "
5614       "  name: 'Foo' "
5615       "  field { name:'foo' number:1 label:LABEL_REQUIRED type:TYPE_INT32 } "
5616       "}",
5617       "foo.proto: Foo.foo: OTHER: Required fields are not allowed in "
5618       "proto3.\n");
5619 
5620   // applied to nested types as well.
5621   BuildFileWithErrors(
5622       "name: 'foo.proto' "
5623       "syntax: 'proto3' "
5624       "message_type { "
5625       "  name: 'Foo' "
5626       "  nested_type { "
5627       "    name : 'Bar' "
5628       "    field { name:'bar' number:1 label:LABEL_REQUIRED type:TYPE_INT32 } "
5629       "  } "
5630       "}",
5631       "foo.proto: Foo.Bar.bar: OTHER: Required fields are not allowed in "
5632       "proto3.\n");
5633 
5634   // optional and repeated fields are OK.
5635   BuildFile(
5636       "name: 'foo.proto' "
5637       "syntax: 'proto3' "
5638       "message_type { "
5639       "  name: 'Foo' "
5640       "  field { name:'foo' number:1 label:LABEL_OPTIONAL type:TYPE_INT32 } "
5641       "  field { name:'bar' number:2 label:LABEL_REPEATED type:TYPE_INT32 } "
5642       "}");
5643 }
5644 
TEST_F(ValidationErrorTest,ValidateProto3DefaultValue)5645 TEST_F(ValidationErrorTest, ValidateProto3DefaultValue) {
5646   BuildFileWithErrors(
5647       "name: 'foo.proto' "
5648       "syntax: 'proto3' "
5649       "message_type { "
5650       "  name: 'Foo' "
5651       "  field { name:'foo' number:1 label:LABEL_OPTIONAL type:TYPE_INT32 "
5652       "          default_value: '1' }"
5653       "}",
5654       "foo.proto: Foo.foo: OTHER: Explicit default values are not allowed in "
5655       "proto3.\n");
5656 
5657   BuildFileWithErrors(
5658       "name: 'foo.proto' "
5659       "syntax: 'proto3' "
5660       "message_type { "
5661       "  name: 'Foo' "
5662       "  nested_type { "
5663       "    name : 'Bar' "
5664       "    field { name:'bar' number:1 label:LABEL_OPTIONAL type:TYPE_INT32 "
5665       "            default_value: '1' }"
5666       "  } "
5667       "}",
5668       "foo.proto: Foo.Bar.bar: OTHER: Explicit default values are not allowed "
5669       "in proto3.\n");
5670 }
5671 
TEST_F(ValidationErrorTest,ValidateProto3ExtensionRange)5672 TEST_F(ValidationErrorTest, ValidateProto3ExtensionRange) {
5673   BuildFileWithErrors(
5674       "name: 'foo.proto' "
5675       "syntax: 'proto3' "
5676       "message_type { "
5677       "  name: 'Foo' "
5678       "  field { name:'foo' number:1 label:LABEL_OPTIONAL type:TYPE_INT32 } "
5679       "  extension_range { start:10 end:100 } "
5680       "}",
5681       "foo.proto: Foo: OTHER: Extension ranges are not allowed in "
5682       "proto3.\n");
5683 
5684   BuildFileWithErrors(
5685       "name: 'foo.proto' "
5686       "syntax: 'proto3' "
5687       "message_type { "
5688       "  name: 'Foo' "
5689       "  nested_type { "
5690       "    name : 'Bar' "
5691       "    field { name:'bar' number:1 label:LABEL_OPTIONAL type:TYPE_INT32 } "
5692       "    extension_range { start:10 end:100 } "
5693       "  } "
5694       "}",
5695       "foo.proto: Foo.Bar: OTHER: Extension ranges are not allowed in "
5696       "proto3.\n");
5697 }
5698 
TEST_F(ValidationErrorTest,ValidateProto3MessageSetWireFormat)5699 TEST_F(ValidationErrorTest, ValidateProto3MessageSetWireFormat) {
5700   BuildFileWithErrors(
5701       "name: 'foo.proto' "
5702       "syntax: 'proto3' "
5703       "message_type { "
5704       "  name: 'Foo' "
5705       "  options { message_set_wire_format: true } "
5706       "}",
5707       "foo.proto: Foo: OTHER: MessageSet is not supported "
5708       "in proto3.\n");
5709 }
5710 
TEST_F(ValidationErrorTest,ValidateProto3Enum)5711 TEST_F(ValidationErrorTest, ValidateProto3Enum) {
5712   BuildFileWithErrors(
5713       "name: 'foo.proto' "
5714       "syntax: 'proto3' "
5715       "enum_type { "
5716       "  name: 'FooEnum' "
5717       "  value { name: 'FOO_FOO' number:1 } "
5718       "}",
5719       "foo.proto: FooEnum: OTHER: The first enum value must be "
5720       "zero in proto3.\n");
5721 
5722   BuildFileWithErrors(
5723       "name: 'foo.proto' "
5724       "syntax: 'proto3' "
5725       "message_type { "
5726       "  name: 'Foo' "
5727       "  enum_type { "
5728       "    name: 'FooEnum' "
5729       "    value { name: 'FOO_FOO' number:1 } "
5730       "  } "
5731       "}",
5732       "foo.proto: Foo.FooEnum: OTHER: The first enum value must be "
5733       "zero in proto3.\n");
5734 
5735   // valid case.
5736   BuildFile(
5737       "name: 'foo.proto' "
5738       "syntax: 'proto3' "
5739       "enum_type { "
5740       "  name: 'FooEnum' "
5741       "  value { name: 'FOO_FOO' number:0 } "
5742       "}");
5743 }
5744 
TEST_F(ValidationErrorTest,ValidateProto3Group)5745 TEST_F(ValidationErrorTest, ValidateProto3Group) {
5746   BuildFileWithErrors(
5747       "name: 'foo.proto' "
5748       "syntax: 'proto3' "
5749       "message_type { "
5750       "  name: 'Foo' "
5751       "  nested_type { "
5752       "    name: 'FooGroup' "
5753       "  } "
5754       "  field { name:'foo_group' number: 1 label:LABEL_OPTIONAL "
5755       "          type: TYPE_GROUP type_name:'FooGroup' } "
5756       "}",
5757       "foo.proto: Foo.foo_group: TYPE: Groups are not supported in proto3 "
5758       "syntax.\n");
5759 }
5760 
5761 
TEST_F(ValidationErrorTest,ValidateProto3EnumFromProto2)5762 TEST_F(ValidationErrorTest, ValidateProto3EnumFromProto2) {
5763   // Define an enum in a proto2 file.
5764   BuildFile(
5765       "name: 'foo.proto' "
5766       "package: 'foo' "
5767       "syntax: 'proto2' "
5768       "enum_type { "
5769       "  name: 'FooEnum' "
5770       "  value { name: 'DEFAULT_OPTION' number:0 } "
5771       "}");
5772 
5773   // Now try to refer to it. (All tests in the fixture use the same pool, so we
5774   // can refer to the enum above in this definition.)
5775   BuildFileWithErrors(
5776       "name: 'bar.proto' "
5777       "dependency: 'foo.proto' "
5778       "syntax: 'proto3' "
5779       "message_type { "
5780       "  name: 'Foo' "
5781       "    field { name:'bar' number:1 label:LABEL_OPTIONAL type:TYPE_ENUM "
5782       "            type_name: 'foo.FooEnum' }"
5783       "}",
5784       "bar.proto: Foo.bar: TYPE: Enum type \"foo.FooEnum\" is not a proto3 "
5785       "enum, but is used in \"Foo\" which is a proto3 message type.\n");
5786 }
5787 
TEST_F(ValidationErrorTest,ValidateProto3Extension)5788 TEST_F(ValidationErrorTest, ValidateProto3Extension) {
5789   // Valid for options.
5790   DescriptorPool pool;
5791   FileDescriptorProto file_proto;
5792   // Add "google/protobuf/descriptor.proto".
5793   FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto);
5794   ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
5795   // Add "foo.proto":
5796   //   import "google/protobuf/descriptor.proto";
5797   //   extend google.protobuf.FieldOptions {
5798   //     optional int32 option1 = 1000;
5799   //   }
5800   file_proto.Clear();
5801   file_proto.set_name("foo.proto");
5802   file_proto.set_syntax("proto3");
5803   file_proto.add_dependency("google/protobuf/descriptor.proto");
5804   AddExtension(&file_proto, "google.protobuf.FieldOptions", "option1", 1000,
5805                FieldDescriptorProto::LABEL_OPTIONAL,
5806                FieldDescriptorProto::TYPE_INT32);
5807   ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
5808 
5809   // Copy and change the package of the descriptor.proto
5810   BuildFile(
5811       "name: 'google.protobuf.proto' "
5812       "syntax: 'proto2' "
5813       "message_type { "
5814       "  name: 'Container' extension_range { start: 1 end: 1000 } "
5815       "}");
5816   BuildFileWithErrors(
5817       "name: 'bar.proto' "
5818       "syntax: 'proto3' "
5819       "dependency: 'google.protobuf.proto' "
5820       "extension { "
5821       "  name: 'bar' number: 1 label: LABEL_OPTIONAL type: TYPE_INT32 "
5822       "  extendee: 'Container' "
5823       "}",
5824       "bar.proto: bar: OTHER: Extensions in proto3 are only allowed for "
5825       "defining options.\n");
5826 }
5827 
5828 // Test that field names that may conflict in JSON is not allowed by protoc.
TEST_F(ValidationErrorTest,ValidateProto3JsonName)5829 TEST_F(ValidationErrorTest, ValidateProto3JsonName) {
5830   // The comparison is case-insensitive.
5831   BuildFileWithErrors(
5832       "name: 'foo.proto' "
5833       "syntax: 'proto3' "
5834       "message_type {"
5835       "  name: 'Foo'"
5836       "  field { name:'name' number:1 label:LABEL_OPTIONAL type:TYPE_INT32 }"
5837       "  field { name:'Name' number:2 label:LABEL_OPTIONAL type:TYPE_INT32 }"
5838       "}",
5839       "foo.proto: Foo: OTHER: The JSON camel-case name of field \"Name\" "
5840       "conflicts with field \"name\". This is not allowed in proto3.\n");
5841   // Underscores are ignored.
5842   BuildFileWithErrors(
5843       "name: 'foo.proto' "
5844       "syntax: 'proto3' "
5845       "message_type {"
5846       "  name: 'Foo'"
5847       "  field { name:'ab' number:1 label:LABEL_OPTIONAL type:TYPE_INT32 }"
5848       "  field { name:'_a__b_' number:2 label:LABEL_OPTIONAL type:TYPE_INT32 }"
5849       "}",
5850       "foo.proto: Foo: OTHER: The JSON camel-case name of field \"_a__b_\" "
5851       "conflicts with field \"ab\". This is not allowed in proto3.\n");
5852 }
5853 
5854 // ===================================================================
5855 // DescriptorDatabase
5856 
AddToDatabase(SimpleDescriptorDatabase * database,const char * file_text)5857 static void AddToDatabase(SimpleDescriptorDatabase* database,
5858                           const char* file_text) {
5859   FileDescriptorProto file_proto;
5860   EXPECT_TRUE(TextFormat::ParseFromString(file_text, &file_proto));
5861   database->Add(file_proto);
5862 }
5863 
5864 class DatabaseBackedPoolTest : public testing::Test {
5865  protected:
DatabaseBackedPoolTest()5866   DatabaseBackedPoolTest() {}
5867 
5868   SimpleDescriptorDatabase database_;
5869 
SetUp()5870   virtual void SetUp() {
5871     AddToDatabase(&database_,
5872       "name: 'foo.proto' "
5873       "message_type { name:'Foo' extension_range { start: 1 end: 100 } } "
5874       "enum_type { name:'TestEnum' value { name:'DUMMY' number:0 } } "
5875       "service { name:'TestService' } ");
5876     AddToDatabase(&database_,
5877       "name: 'bar.proto' "
5878       "dependency: 'foo.proto' "
5879       "message_type { name:'Bar' } "
5880       "extension { name:'foo_ext' extendee: '.Foo' number:5 "
5881       "            label:LABEL_OPTIONAL type:TYPE_INT32 } ");
5882     // Baz has an undeclared dependency on Foo.
5883     AddToDatabase(&database_,
5884       "name: 'baz.proto' "
5885       "message_type { "
5886       "  name:'Baz' "
5887       "  field { name:'foo' number:1 label:LABEL_OPTIONAL type_name:'Foo' } "
5888       "}");
5889   }
5890 
5891   // We can't inject a file containing errors into a DescriptorPool, so we
5892   // need an actual mock DescriptorDatabase to test errors.
5893   class ErrorDescriptorDatabase : public DescriptorDatabase {
5894    public:
ErrorDescriptorDatabase()5895     ErrorDescriptorDatabase() {}
~ErrorDescriptorDatabase()5896     ~ErrorDescriptorDatabase() {}
5897 
5898     // implements DescriptorDatabase ---------------------------------
FindFileByName(const string & filename,FileDescriptorProto * output)5899     bool FindFileByName(const string& filename,
5900                         FileDescriptorProto* output) {
5901       // error.proto and error2.proto cyclically import each other.
5902       if (filename == "error.proto") {
5903         output->Clear();
5904         output->set_name("error.proto");
5905         output->add_dependency("error2.proto");
5906         return true;
5907       } else if (filename == "error2.proto") {
5908         output->Clear();
5909         output->set_name("error2.proto");
5910         output->add_dependency("error.proto");
5911         return true;
5912       } else {
5913         return false;
5914       }
5915     }
FindFileContainingSymbol(const string & symbol_name,FileDescriptorProto * output)5916     bool FindFileContainingSymbol(const string& symbol_name,
5917                                   FileDescriptorProto* output) {
5918       return false;
5919     }
FindFileContainingExtension(const string & containing_type,int field_number,FileDescriptorProto * output)5920     bool FindFileContainingExtension(const string& containing_type,
5921                                      int field_number,
5922                                      FileDescriptorProto* output) {
5923       return false;
5924     }
5925   };
5926 
5927   // A DescriptorDatabase that counts how many times each method has been
5928   // called and forwards to some other DescriptorDatabase.
5929   class CallCountingDatabase : public DescriptorDatabase {
5930    public:
CallCountingDatabase(DescriptorDatabase * wrapped_db)5931     CallCountingDatabase(DescriptorDatabase* wrapped_db)
5932       : wrapped_db_(wrapped_db) {
5933       Clear();
5934     }
~CallCountingDatabase()5935     ~CallCountingDatabase() {}
5936 
5937     DescriptorDatabase* wrapped_db_;
5938 
5939     int call_count_;
5940 
Clear()5941     void Clear() {
5942       call_count_ = 0;
5943     }
5944 
5945     // implements DescriptorDatabase ---------------------------------
FindFileByName(const string & filename,FileDescriptorProto * output)5946     bool FindFileByName(const string& filename,
5947                         FileDescriptorProto* output) {
5948       ++call_count_;
5949       return wrapped_db_->FindFileByName(filename, output);
5950     }
FindFileContainingSymbol(const string & symbol_name,FileDescriptorProto * output)5951     bool FindFileContainingSymbol(const string& symbol_name,
5952                                   FileDescriptorProto* output) {
5953       ++call_count_;
5954       return wrapped_db_->FindFileContainingSymbol(symbol_name, output);
5955     }
FindFileContainingExtension(const string & containing_type,int field_number,FileDescriptorProto * output)5956     bool FindFileContainingExtension(const string& containing_type,
5957                                      int field_number,
5958                                      FileDescriptorProto* output) {
5959       ++call_count_;
5960       return wrapped_db_->FindFileContainingExtension(
5961         containing_type, field_number, output);
5962     }
5963   };
5964 
5965   // A DescriptorDatabase which falsely always returns foo.proto when searching
5966   // for any symbol or extension number.  This shouldn't cause the
5967   // DescriptorPool to reload foo.proto if it is already loaded.
5968   class FalsePositiveDatabase : public DescriptorDatabase {
5969    public:
FalsePositiveDatabase(DescriptorDatabase * wrapped_db)5970     FalsePositiveDatabase(DescriptorDatabase* wrapped_db)
5971       : wrapped_db_(wrapped_db) {}
~FalsePositiveDatabase()5972     ~FalsePositiveDatabase() {}
5973 
5974     DescriptorDatabase* wrapped_db_;
5975 
5976     // implements DescriptorDatabase ---------------------------------
FindFileByName(const string & filename,FileDescriptorProto * output)5977     bool FindFileByName(const string& filename,
5978                         FileDescriptorProto* output) {
5979       return wrapped_db_->FindFileByName(filename, output);
5980     }
FindFileContainingSymbol(const string & symbol_name,FileDescriptorProto * output)5981     bool FindFileContainingSymbol(const string& symbol_name,
5982                                   FileDescriptorProto* output) {
5983       return FindFileByName("foo.proto", output);
5984     }
FindFileContainingExtension(const string & containing_type,int field_number,FileDescriptorProto * output)5985     bool FindFileContainingExtension(const string& containing_type,
5986                                      int field_number,
5987                                      FileDescriptorProto* output) {
5988       return FindFileByName("foo.proto", output);
5989     }
5990   };
5991 };
5992 
TEST_F(DatabaseBackedPoolTest,FindFileByName)5993 TEST_F(DatabaseBackedPoolTest, FindFileByName) {
5994   DescriptorPool pool(&database_);
5995 
5996   const FileDescriptor* foo = pool.FindFileByName("foo.proto");
5997   ASSERT_TRUE(foo != NULL);
5998   EXPECT_EQ("foo.proto", foo->name());
5999   ASSERT_EQ(1, foo->message_type_count());
6000   EXPECT_EQ("Foo", foo->message_type(0)->name());
6001 
6002   EXPECT_EQ(foo, pool.FindFileByName("foo.proto"));
6003 
6004   EXPECT_TRUE(pool.FindFileByName("no_such_file.proto") == NULL);
6005 }
6006 
TEST_F(DatabaseBackedPoolTest,FindDependencyBeforeDependent)6007 TEST_F(DatabaseBackedPoolTest, FindDependencyBeforeDependent) {
6008   DescriptorPool pool(&database_);
6009 
6010   const FileDescriptor* foo = pool.FindFileByName("foo.proto");
6011   ASSERT_TRUE(foo != NULL);
6012   EXPECT_EQ("foo.proto", foo->name());
6013   ASSERT_EQ(1, foo->message_type_count());
6014   EXPECT_EQ("Foo", foo->message_type(0)->name());
6015 
6016   const FileDescriptor* bar = pool.FindFileByName("bar.proto");
6017   ASSERT_TRUE(bar != NULL);
6018   EXPECT_EQ("bar.proto", bar->name());
6019   ASSERT_EQ(1, bar->message_type_count());
6020   EXPECT_EQ("Bar", bar->message_type(0)->name());
6021 
6022   ASSERT_EQ(1, bar->dependency_count());
6023   EXPECT_EQ(foo, bar->dependency(0));
6024 }
6025 
TEST_F(DatabaseBackedPoolTest,FindDependentBeforeDependency)6026 TEST_F(DatabaseBackedPoolTest, FindDependentBeforeDependency) {
6027   DescriptorPool pool(&database_);
6028 
6029   const FileDescriptor* bar = pool.FindFileByName("bar.proto");
6030   ASSERT_TRUE(bar != NULL);
6031   EXPECT_EQ("bar.proto", bar->name());
6032   ASSERT_EQ(1, bar->message_type_count());
6033   ASSERT_EQ("Bar", bar->message_type(0)->name());
6034 
6035   const FileDescriptor* foo = pool.FindFileByName("foo.proto");
6036   ASSERT_TRUE(foo != NULL);
6037   EXPECT_EQ("foo.proto", foo->name());
6038   ASSERT_EQ(1, foo->message_type_count());
6039   ASSERT_EQ("Foo", foo->message_type(0)->name());
6040 
6041   ASSERT_EQ(1, bar->dependency_count());
6042   EXPECT_EQ(foo, bar->dependency(0));
6043 }
6044 
TEST_F(DatabaseBackedPoolTest,FindFileContainingSymbol)6045 TEST_F(DatabaseBackedPoolTest, FindFileContainingSymbol) {
6046   DescriptorPool pool(&database_);
6047 
6048   const FileDescriptor* file = pool.FindFileContainingSymbol("Foo");
6049   ASSERT_TRUE(file != NULL);
6050   EXPECT_EQ("foo.proto", file->name());
6051   EXPECT_EQ(file, pool.FindFileByName("foo.proto"));
6052 
6053   EXPECT_TRUE(pool.FindFileContainingSymbol("NoSuchSymbol") == NULL);
6054 }
6055 
TEST_F(DatabaseBackedPoolTest,FindMessageTypeByName)6056 TEST_F(DatabaseBackedPoolTest, FindMessageTypeByName) {
6057   DescriptorPool pool(&database_);
6058 
6059   const Descriptor* type = pool.FindMessageTypeByName("Foo");
6060   ASSERT_TRUE(type != NULL);
6061   EXPECT_EQ("Foo", type->name());
6062   EXPECT_EQ(type->file(), pool.FindFileByName("foo.proto"));
6063 
6064   EXPECT_TRUE(pool.FindMessageTypeByName("NoSuchType") == NULL);
6065 }
6066 
TEST_F(DatabaseBackedPoolTest,FindExtensionByNumber)6067 TEST_F(DatabaseBackedPoolTest, FindExtensionByNumber) {
6068   DescriptorPool pool(&database_);
6069 
6070   const Descriptor* foo = pool.FindMessageTypeByName("Foo");
6071   ASSERT_TRUE(foo != NULL);
6072 
6073   const FieldDescriptor* extension = pool.FindExtensionByNumber(foo, 5);
6074   ASSERT_TRUE(extension != NULL);
6075   EXPECT_EQ("foo_ext", extension->name());
6076   EXPECT_EQ(extension->file(), pool.FindFileByName("bar.proto"));
6077 
6078   EXPECT_TRUE(pool.FindExtensionByNumber(foo, 12) == NULL);
6079 }
6080 
TEST_F(DatabaseBackedPoolTest,FindAllExtensions)6081 TEST_F(DatabaseBackedPoolTest, FindAllExtensions) {
6082   DescriptorPool pool(&database_);
6083 
6084   const Descriptor* foo = pool.FindMessageTypeByName("Foo");
6085 
6086   for (int i = 0; i < 2; ++i) {
6087     // Repeat the lookup twice, to check that we get consistent
6088     // results despite the fallback database lookup mutating the pool.
6089     vector<const FieldDescriptor*> extensions;
6090     pool.FindAllExtensions(foo, &extensions);
6091     ASSERT_EQ(1, extensions.size());
6092     EXPECT_EQ(5, extensions[0]->number());
6093   }
6094 }
6095 
TEST_F(DatabaseBackedPoolTest,ErrorWithoutErrorCollector)6096 TEST_F(DatabaseBackedPoolTest, ErrorWithoutErrorCollector) {
6097   ErrorDescriptorDatabase error_database;
6098   DescriptorPool pool(&error_database);
6099 
6100   vector<string> errors;
6101 
6102   {
6103     ScopedMemoryLog log;
6104     EXPECT_TRUE(pool.FindFileByName("error.proto") == NULL);
6105     errors = log.GetMessages(ERROR);
6106   }
6107 
6108   EXPECT_FALSE(errors.empty());
6109 }
6110 
TEST_F(DatabaseBackedPoolTest,ErrorWithErrorCollector)6111 TEST_F(DatabaseBackedPoolTest, ErrorWithErrorCollector) {
6112   ErrorDescriptorDatabase error_database;
6113   MockErrorCollector error_collector;
6114   DescriptorPool pool(&error_database, &error_collector);
6115 
6116   EXPECT_TRUE(pool.FindFileByName("error.proto") == NULL);
6117   EXPECT_EQ(
6118     "error.proto: error.proto: OTHER: File recursively imports itself: "
6119       "error.proto -> error2.proto -> error.proto\n"
6120     "error2.proto: error2.proto: OTHER: Import \"error.proto\" was not "
6121       "found or had errors.\n"
6122     "error.proto: error.proto: OTHER: Import \"error2.proto\" was not "
6123       "found or had errors.\n",
6124     error_collector.text_);
6125 }
6126 
TEST_F(DatabaseBackedPoolTest,UndeclaredDependencyOnUnbuiltType)6127 TEST_F(DatabaseBackedPoolTest, UndeclaredDependencyOnUnbuiltType) {
6128   // Check that we find and report undeclared dependencies on types that exist
6129   // in the descriptor database but that have not not been built yet.
6130   MockErrorCollector error_collector;
6131   DescriptorPool pool(&database_, &error_collector);
6132   EXPECT_TRUE(pool.FindMessageTypeByName("Baz") == NULL);
6133   EXPECT_EQ(
6134     "baz.proto: Baz.foo: TYPE: \"Foo\" seems to be defined in \"foo.proto\", "
6135     "which is not imported by \"baz.proto\".  To use it here, please add "
6136     "the necessary import.\n",
6137     error_collector.text_);
6138 }
6139 
TEST_F(DatabaseBackedPoolTest,RollbackAfterError)6140 TEST_F(DatabaseBackedPoolTest, RollbackAfterError) {
6141   // Make sure that all traces of bad types are removed from the pool. This used
6142   // to be b/4529436, due to the fact that a symbol resolution failure could
6143   // potentially cause another file to be recursively built, which would trigger
6144   // a checkpoint _past_ possibly invalid symbols.
6145   // Baz is defined in the database, but the file is invalid because it is
6146   // missing a necessary import.
6147   DescriptorPool pool(&database_);
6148   EXPECT_TRUE(pool.FindMessageTypeByName("Baz") == NULL);
6149   // Make sure that searching again for the file or the type fails.
6150   EXPECT_TRUE(pool.FindFileByName("baz.proto") == NULL);
6151   EXPECT_TRUE(pool.FindMessageTypeByName("Baz") == NULL);
6152 }
6153 
TEST_F(DatabaseBackedPoolTest,UnittestProto)6154 TEST_F(DatabaseBackedPoolTest, UnittestProto) {
6155   // Try to load all of unittest.proto from a DescriptorDatabase.  This should
6156   // thoroughly test all paths through DescriptorBuilder to insure that there
6157   // are no deadlocking problems when pool_->mutex_ is non-NULL.
6158   const FileDescriptor* original_file =
6159     protobuf_unittest::TestAllTypes::descriptor()->file();
6160 
6161   DescriptorPoolDatabase database(*DescriptorPool::generated_pool());
6162   DescriptorPool pool(&database);
6163   const FileDescriptor* file_from_database =
6164     pool.FindFileByName(original_file->name());
6165 
6166   ASSERT_TRUE(file_from_database != NULL);
6167 
6168   FileDescriptorProto original_file_proto;
6169   original_file->CopyTo(&original_file_proto);
6170 
6171   FileDescriptorProto file_from_database_proto;
6172   file_from_database->CopyTo(&file_from_database_proto);
6173 
6174   EXPECT_EQ(original_file_proto.DebugString(),
6175             file_from_database_proto.DebugString());
6176 
6177   // Also verify that CopyTo() did not omit any information.
6178   EXPECT_EQ(original_file->DebugString(),
6179             file_from_database->DebugString());
6180 }
6181 
TEST_F(DatabaseBackedPoolTest,DoesntRetryDbUnnecessarily)6182 TEST_F(DatabaseBackedPoolTest, DoesntRetryDbUnnecessarily) {
6183   // Searching for a child of an existing descriptor should never fall back
6184   // to the DescriptorDatabase even if it isn't found, because we know all
6185   // children are already loaded.
6186   CallCountingDatabase call_counter(&database_);
6187   DescriptorPool pool(&call_counter);
6188 
6189   const FileDescriptor* file = pool.FindFileByName("foo.proto");
6190   ASSERT_TRUE(file != NULL);
6191   const Descriptor* foo = pool.FindMessageTypeByName("Foo");
6192   ASSERT_TRUE(foo != NULL);
6193   const EnumDescriptor* test_enum = pool.FindEnumTypeByName("TestEnum");
6194   ASSERT_TRUE(test_enum != NULL);
6195   const ServiceDescriptor* test_service = pool.FindServiceByName("TestService");
6196   ASSERT_TRUE(test_service != NULL);
6197 
6198   EXPECT_NE(0, call_counter.call_count_);
6199   call_counter.Clear();
6200 
6201   EXPECT_TRUE(foo->FindFieldByName("no_such_field") == NULL);
6202   EXPECT_TRUE(foo->FindExtensionByName("no_such_extension") == NULL);
6203   EXPECT_TRUE(foo->FindNestedTypeByName("NoSuchMessageType") == NULL);
6204   EXPECT_TRUE(foo->FindEnumTypeByName("NoSuchEnumType") == NULL);
6205   EXPECT_TRUE(foo->FindEnumValueByName("NO_SUCH_VALUE") == NULL);
6206   EXPECT_TRUE(test_enum->FindValueByName("NO_SUCH_VALUE") == NULL);
6207   EXPECT_TRUE(test_service->FindMethodByName("NoSuchMethod") == NULL);
6208 
6209   EXPECT_TRUE(file->FindMessageTypeByName("NoSuchMessageType") == NULL);
6210   EXPECT_TRUE(file->FindEnumTypeByName("NoSuchEnumType") == NULL);
6211   EXPECT_TRUE(file->FindEnumValueByName("NO_SUCH_VALUE") == NULL);
6212   EXPECT_TRUE(file->FindServiceByName("NO_SUCH_VALUE") == NULL);
6213   EXPECT_TRUE(file->FindExtensionByName("no_such_extension") == NULL);
6214 
6215   EXPECT_TRUE(pool.FindFileContainingSymbol("Foo.no.such.field") == NULL);
6216   EXPECT_TRUE(pool.FindFileContainingSymbol("Foo.no_such_field") == NULL);
6217   EXPECT_TRUE(pool.FindMessageTypeByName("Foo.NoSuchMessageType") == NULL);
6218   EXPECT_TRUE(pool.FindFieldByName("Foo.no_such_field") == NULL);
6219   EXPECT_TRUE(pool.FindExtensionByName("Foo.no_such_extension") == NULL);
6220   EXPECT_TRUE(pool.FindEnumTypeByName("Foo.NoSuchEnumType") == NULL);
6221   EXPECT_TRUE(pool.FindEnumValueByName("Foo.NO_SUCH_VALUE") == NULL);
6222   EXPECT_TRUE(pool.FindMethodByName("TestService.NoSuchMethod") == NULL);
6223 
6224   EXPECT_EQ(0, call_counter.call_count_);
6225 }
6226 
TEST_F(DatabaseBackedPoolTest,DoesntReloadFilesUncesessarily)6227 TEST_F(DatabaseBackedPoolTest, DoesntReloadFilesUncesessarily) {
6228   // If FindFileContainingSymbol() or FindFileContainingExtension() return a
6229   // file that is already in the DescriptorPool, it should not attempt to
6230   // reload the file.
6231   FalsePositiveDatabase false_positive_database(&database_);
6232   MockErrorCollector error_collector;
6233   DescriptorPool pool(&false_positive_database, &error_collector);
6234 
6235   // First make sure foo.proto is loaded.
6236   const Descriptor* foo = pool.FindMessageTypeByName("Foo");
6237   ASSERT_TRUE(foo != NULL);
6238 
6239   // Try inducing false positives.
6240   EXPECT_TRUE(pool.FindMessageTypeByName("NoSuchSymbol") == NULL);
6241   EXPECT_TRUE(pool.FindExtensionByNumber(foo, 22) == NULL);
6242 
6243   // No errors should have been reported.  (If foo.proto was incorrectly
6244   // loaded multiple times, errors would have been reported.)
6245   EXPECT_EQ("", error_collector.text_);
6246 }
6247 
6248 // DescriptorDatabase that attempts to induce exponentially-bad performance
6249 // in DescriptorPool. For every positive N, the database contains a file
6250 // fileN.proto, which defines a message MessageN, which contains fields of
6251 // type MessageK for all K in [0,N). Message0 is not defined anywhere
6252 // (file0.proto exists, but is empty), so every other file and message type
6253 // will fail to build.
6254 //
6255 // If the DescriptorPool is not careful to memoize errors, an attempt to
6256 // build a descriptor for MessageN can require O(2^N) time.
6257 class ExponentialErrorDatabase : public DescriptorDatabase {
6258  public:
ExponentialErrorDatabase()6259   ExponentialErrorDatabase() {}
~ExponentialErrorDatabase()6260   ~ExponentialErrorDatabase() {}
6261 
6262   // implements DescriptorDatabase ---------------------------------
FindFileByName(const string & filename,FileDescriptorProto * output)6263   bool FindFileByName(const string& filename,
6264                       FileDescriptorProto* output) {
6265     int file_num = -1;
6266     FullMatch(filename, "file", ".proto", &file_num);
6267     if (file_num > -1) {
6268       return PopulateFile(file_num, output);
6269     } else {
6270       return false;
6271     }
6272   }
FindFileContainingSymbol(const string & symbol_name,FileDescriptorProto * output)6273   bool FindFileContainingSymbol(const string& symbol_name,
6274                                 FileDescriptorProto* output) {
6275     int file_num = -1;
6276     FullMatch(symbol_name, "Message", "", &file_num);
6277     if (file_num > 0) {
6278       return PopulateFile(file_num, output);
6279     } else {
6280       return false;
6281     }
6282   }
FindFileContainingExtension(const string & containing_type,int field_number,FileDescriptorProto * output)6283   bool FindFileContainingExtension(const string& containing_type,
6284                                    int field_number,
6285                                    FileDescriptorProto* output) {
6286     return false;
6287   }
6288 
6289  private:
FullMatch(const string & name,const string & begin_with,const string & end_with,int * file_num)6290   void FullMatch(const string& name,
6291                  const string& begin_with,
6292                  const string& end_with,
6293                  int* file_num) {
6294     int begin_size = begin_with.size();
6295     int end_size = end_with.size();
6296     if (name.substr(0, begin_size) != begin_with ||
6297         name.substr(name.size()- end_size, end_size) != end_with) {
6298       return;
6299     }
6300     safe_strto32(name.substr(begin_size, name.size() - end_size - begin_size),
6301                  file_num);
6302   }
6303 
PopulateFile(int file_num,FileDescriptorProto * output)6304   bool PopulateFile(int file_num, FileDescriptorProto* output) {
6305     using strings::Substitute;
6306     GOOGLE_CHECK_GE(file_num, 0);
6307     output->Clear();
6308     output->set_name(Substitute("file$0.proto", file_num));
6309     // file0.proto doesn't define Message0
6310     if (file_num > 0) {
6311       DescriptorProto* message = output->add_message_type();
6312       message->set_name(Substitute("Message$0", file_num));
6313       for (int i = 0; i < file_num; ++i) {
6314         output->add_dependency(Substitute("file$0.proto", i));
6315         FieldDescriptorProto* field = message->add_field();
6316         field->set_name(Substitute("field$0", i));
6317         field->set_number(i);
6318         field->set_label(FieldDescriptorProto::LABEL_OPTIONAL);
6319         field->set_type(FieldDescriptorProto::TYPE_MESSAGE);
6320         field->set_type_name(Substitute("Message$0", i));
6321       }
6322     }
6323     return true;
6324   }
6325 };
6326 
TEST_F(DatabaseBackedPoolTest,DoesntReloadKnownBadFiles)6327 TEST_F(DatabaseBackedPoolTest, DoesntReloadKnownBadFiles) {
6328   ExponentialErrorDatabase error_database;
6329   DescriptorPool pool(&error_database);
6330 
6331   GOOGLE_LOG(INFO) << "A timeout in this test probably indicates a real bug.";
6332 
6333   EXPECT_TRUE(pool.FindFileByName("file40.proto") == NULL);
6334   EXPECT_TRUE(pool.FindMessageTypeByName("Message40") == NULL);
6335 }
6336 
TEST_F(DatabaseBackedPoolTest,DoesntFallbackOnWrongType)6337 TEST_F(DatabaseBackedPoolTest, DoesntFallbackOnWrongType) {
6338   // If a lookup finds a symbol of the wrong type (e.g. we pass a type name
6339   // to FindFieldByName()), we should fail fast, without checking the fallback
6340   // database.
6341   CallCountingDatabase call_counter(&database_);
6342   DescriptorPool pool(&call_counter);
6343 
6344   const FileDescriptor* file = pool.FindFileByName("foo.proto");
6345   ASSERT_TRUE(file != NULL);
6346   const Descriptor* foo = pool.FindMessageTypeByName("Foo");
6347   ASSERT_TRUE(foo != NULL);
6348   const EnumDescriptor* test_enum = pool.FindEnumTypeByName("TestEnum");
6349   ASSERT_TRUE(test_enum != NULL);
6350 
6351   EXPECT_NE(0, call_counter.call_count_);
6352   call_counter.Clear();
6353 
6354   EXPECT_TRUE(pool.FindMessageTypeByName("TestEnum") == NULL);
6355   EXPECT_TRUE(pool.FindFieldByName("Foo") == NULL);
6356   EXPECT_TRUE(pool.FindExtensionByName("Foo") == NULL);
6357   EXPECT_TRUE(pool.FindEnumTypeByName("Foo") == NULL);
6358   EXPECT_TRUE(pool.FindEnumValueByName("Foo") == NULL);
6359   EXPECT_TRUE(pool.FindServiceByName("Foo") == NULL);
6360   EXPECT_TRUE(pool.FindMethodByName("Foo") == NULL);
6361 
6362   EXPECT_EQ(0, call_counter.call_count_);
6363 }
6364 
6365 // ===================================================================
6366 
6367 class AbortingErrorCollector : public DescriptorPool::ErrorCollector {
6368  public:
AbortingErrorCollector()6369   AbortingErrorCollector() {}
6370 
AddError(const string & filename,const string & element_name,const Message * message,ErrorLocation location,const string & error_message)6371   virtual void AddError(
6372       const string &filename,
6373       const string &element_name,
6374       const Message *message,
6375       ErrorLocation location,
6376       const string &error_message) {
6377     GOOGLE_LOG(FATAL) << "AddError() called unexpectedly: " << filename << " ["
6378                << element_name << "]: " << error_message;
6379   }
6380  private:
6381   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(AbortingErrorCollector);
6382 };
6383 
6384 // A source tree containing only one file.
6385 class SingletonSourceTree : public compiler::SourceTree {
6386  public:
SingletonSourceTree(const string & filename,const string & contents)6387   SingletonSourceTree(const string& filename, const string& contents)
6388       : filename_(filename), contents_(contents) {}
6389 
Open(const string & filename)6390   virtual io::ZeroCopyInputStream* Open(const string& filename) {
6391     return filename == filename_ ?
6392         new io::ArrayInputStream(contents_.data(), contents_.size()) : NULL;
6393   }
6394 
6395  private:
6396   const string filename_;
6397   const string contents_;
6398 
6399   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SingletonSourceTree);
6400 };
6401 
6402 const char *const kSourceLocationTestInput =
6403   "syntax = \"proto2\";\n"
6404   "message A {\n"
6405   "  optional int32 a = 1;\n"
6406   "  message B {\n"
6407   "    required double b = 1;\n"
6408   "  }\n"
6409   "}\n"
6410   "enum Indecision {\n"
6411   "  YES   = 1;\n"
6412   "  NO    = 2;\n"
6413   "  MAYBE = 3;\n"
6414   "}\n"
6415   "service S {\n"
6416   "  rpc Method(A) returns (A.B);\n"
6417   // Put an empty line here to make the source location range match.
6418   "\n"
6419   "}\n"
6420   "message MessageWithExtensions {\n"
6421   "  extensions 1000 to max;\n"
6422   "}\n"
6423   "extend MessageWithExtensions {\n"
6424   "  optional int32 int32_extension = 1001;\n"
6425   "}\n"
6426   "message C {\n"
6427   "  extend MessageWithExtensions {\n"
6428   "    optional C message_extension = 1002;\n"
6429   "  }\n"
6430   "}\n";
6431 
6432 class SourceLocationTest : public testing::Test {
6433  public:
SourceLocationTest()6434   SourceLocationTest()
6435       : source_tree_("/test/test.proto", kSourceLocationTestInput),
6436         db_(&source_tree_),
6437         pool_(&db_, &collector_) {}
6438 
PrintSourceLocation(const SourceLocation & loc)6439   static string PrintSourceLocation(const SourceLocation &loc) {
6440     return strings::Substitute("$0:$1-$2:$3",
6441                                1 + loc.start_line,
6442                                1 + loc.start_column,
6443                                1 + loc.end_line,
6444                                1 + loc.end_column);
6445   }
6446 
6447  private:
6448   AbortingErrorCollector collector_;
6449   SingletonSourceTree source_tree_;
6450   compiler::SourceTreeDescriptorDatabase db_;
6451 
6452  protected:
6453   DescriptorPool pool_;
6454 };
6455 
6456 // TODO(adonovan): implement support for option fields and for
6457 // subparts of declarations.
6458 
TEST_F(SourceLocationTest,GetSourceLocation)6459 TEST_F(SourceLocationTest, GetSourceLocation) {
6460   SourceLocation loc;
6461 
6462   const FileDescriptor *file_desc =
6463       GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto"));
6464 
6465   const Descriptor *a_desc = file_desc->FindMessageTypeByName("A");
6466   EXPECT_TRUE(a_desc->GetSourceLocation(&loc));
6467   EXPECT_EQ("2:1-7:2", PrintSourceLocation(loc));
6468 
6469   const Descriptor *a_b_desc = a_desc->FindNestedTypeByName("B");
6470   EXPECT_TRUE(a_b_desc->GetSourceLocation(&loc));
6471   EXPECT_EQ("4:3-6:4", PrintSourceLocation(loc));
6472 
6473   const EnumDescriptor *e_desc = file_desc->FindEnumTypeByName("Indecision");
6474   EXPECT_TRUE(e_desc->GetSourceLocation(&loc));
6475   EXPECT_EQ("8:1-12:2", PrintSourceLocation(loc));
6476 
6477   const EnumValueDescriptor *yes_desc = e_desc->FindValueByName("YES");
6478   EXPECT_TRUE(yes_desc->GetSourceLocation(&loc));
6479   EXPECT_EQ("9:3-9:13", PrintSourceLocation(loc));
6480 
6481   const ServiceDescriptor *s_desc = file_desc->FindServiceByName("S");
6482   EXPECT_TRUE(s_desc->GetSourceLocation(&loc));
6483   EXPECT_EQ("13:1-16:2", PrintSourceLocation(loc));
6484 
6485   const MethodDescriptor *m_desc = s_desc->FindMethodByName("Method");
6486   EXPECT_TRUE(m_desc->GetSourceLocation(&loc));
6487   EXPECT_EQ("14:3-14:31", PrintSourceLocation(loc));
6488 
6489 }
6490 
TEST_F(SourceLocationTest,ExtensionSourceLocation)6491 TEST_F(SourceLocationTest, ExtensionSourceLocation) {
6492   SourceLocation loc;
6493 
6494   const FileDescriptor *file_desc =
6495       GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto"));
6496 
6497   const FieldDescriptor *int32_extension_desc =
6498       file_desc->FindExtensionByName("int32_extension");
6499   EXPECT_TRUE(int32_extension_desc->GetSourceLocation(&loc));
6500   EXPECT_EQ("21:3-21:41", PrintSourceLocation(loc));
6501 
6502   const Descriptor *c_desc = file_desc->FindMessageTypeByName("C");
6503   EXPECT_TRUE(c_desc->GetSourceLocation(&loc));
6504   EXPECT_EQ("23:1-27:2", PrintSourceLocation(loc));
6505 
6506   const FieldDescriptor *message_extension_desc =
6507       c_desc->FindExtensionByName("message_extension");
6508   EXPECT_TRUE(message_extension_desc->GetSourceLocation(&loc));
6509   EXPECT_EQ("25:5-25:41", PrintSourceLocation(loc));
6510 }
6511 
6512 // Missing SourceCodeInfo doesn't cause crash:
TEST_F(SourceLocationTest,GetSourceLocation_MissingSourceCodeInfo)6513 TEST_F(SourceLocationTest, GetSourceLocation_MissingSourceCodeInfo) {
6514   SourceLocation loc;
6515 
6516   const FileDescriptor *file_desc =
6517       GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto"));
6518 
6519   FileDescriptorProto proto;
6520   file_desc->CopyTo(&proto);  // Note, this discards the SourceCodeInfo.
6521   EXPECT_FALSE(proto.has_source_code_info());
6522 
6523   DescriptorPool bad1_pool(&pool_);
6524   const FileDescriptor* bad1_file_desc =
6525       GOOGLE_CHECK_NOTNULL(bad1_pool.BuildFile(proto));
6526   const Descriptor *bad1_a_desc = bad1_file_desc->FindMessageTypeByName("A");
6527   EXPECT_FALSE(bad1_a_desc->GetSourceLocation(&loc));
6528 }
6529 
6530 // Corrupt SourceCodeInfo doesn't cause crash:
TEST_F(SourceLocationTest,GetSourceLocation_BogusSourceCodeInfo)6531 TEST_F(SourceLocationTest, GetSourceLocation_BogusSourceCodeInfo) {
6532   SourceLocation loc;
6533 
6534   const FileDescriptor *file_desc =
6535       GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto"));
6536 
6537   FileDescriptorProto proto;
6538   file_desc->CopyTo(&proto);  // Note, this discards the SourceCodeInfo.
6539   EXPECT_FALSE(proto.has_source_code_info());
6540   SourceCodeInfo_Location *loc_msg =
6541       proto.mutable_source_code_info()->add_location();
6542   loc_msg->add_path(1);
6543   loc_msg->add_path(2);
6544   loc_msg->add_path(3);
6545   loc_msg->add_span(4);
6546   loc_msg->add_span(5);
6547   loc_msg->add_span(6);
6548 
6549   DescriptorPool bad2_pool(&pool_);
6550   const FileDescriptor* bad2_file_desc =
6551       GOOGLE_CHECK_NOTNULL(bad2_pool.BuildFile(proto));
6552   const Descriptor *bad2_a_desc = bad2_file_desc->FindMessageTypeByName("A");
6553   EXPECT_FALSE(bad2_a_desc->GetSourceLocation(&loc));
6554 }
6555 
6556 // ===================================================================
6557 
6558 const char* const kCopySourceCodeInfoToTestInput =
6559   "syntax = \"proto2\";\n"
6560   "message Foo {}\n";
6561 
6562 // Required since source code information is not preserved by
6563 // FileDescriptorTest.
6564 class CopySourceCodeInfoToTest : public testing::Test {
6565  public:
CopySourceCodeInfoToTest()6566   CopySourceCodeInfoToTest()
6567       : source_tree_("/test/test.proto", kCopySourceCodeInfoToTestInput),
6568         db_(&source_tree_),
6569         pool_(&db_, &collector_) {}
6570 
6571  private:
6572   AbortingErrorCollector collector_;
6573   SingletonSourceTree source_tree_;
6574   compiler::SourceTreeDescriptorDatabase db_;
6575 
6576  protected:
6577   DescriptorPool pool_;
6578 };
6579 
TEST_F(CopySourceCodeInfoToTest,CopyTo_DoesNotCopySourceCodeInfo)6580 TEST_F(CopySourceCodeInfoToTest, CopyTo_DoesNotCopySourceCodeInfo) {
6581   const FileDescriptor* file_desc =
6582       GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto"));
6583   FileDescriptorProto file_desc_proto;
6584   ASSERT_FALSE(file_desc_proto.has_source_code_info());
6585 
6586   file_desc->CopyTo(&file_desc_proto);
6587   EXPECT_FALSE(file_desc_proto.has_source_code_info());
6588 }
6589 
TEST_F(CopySourceCodeInfoToTest,CopySourceCodeInfoTo)6590 TEST_F(CopySourceCodeInfoToTest, CopySourceCodeInfoTo) {
6591   const FileDescriptor* file_desc =
6592       GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto"));
6593   FileDescriptorProto file_desc_proto;
6594   ASSERT_FALSE(file_desc_proto.has_source_code_info());
6595 
6596   file_desc->CopySourceCodeInfoTo(&file_desc_proto);
6597   const SourceCodeInfo& info = file_desc_proto.source_code_info();
6598   ASSERT_EQ(4, info.location_size());
6599   // Get the Foo message location
6600   const SourceCodeInfo_Location& foo_location = info.location(2);
6601   ASSERT_EQ(2, foo_location.path_size());
6602   EXPECT_EQ(FileDescriptorProto::kMessageTypeFieldNumber, foo_location.path(0));
6603   EXPECT_EQ(0, foo_location.path(1));      // Foo is the first message defined
6604   ASSERT_EQ(3, foo_location.span_size());  // Foo spans one line
6605   EXPECT_EQ(1, foo_location.span(0));      // Foo is declared on line 1
6606   EXPECT_EQ(0, foo_location.span(1));      // Foo starts at column 0
6607   EXPECT_EQ(14, foo_location.span(2));     // Foo ends on column 14
6608 }
6609 
6610 // ===================================================================
6611 
6612 
6613 }  // namespace descriptor_unittest
6614 }  // namespace protobuf
6615 }  // namespace google
6616