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