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