• 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/any.pb.h>
42 #include <google/protobuf/compiler/importer.h>
43 #include <google/protobuf/compiler/parser.h>
44 #include <google/protobuf/unittest.pb.h>
45 #include <google/protobuf/unittest_custom_options.pb.h>
46 #include <google/protobuf/stubs/common.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/logging.h>
62 #include <google/protobuf/stubs/substitute.h>
63 
64 
65 #include <google/protobuf/port_def.inc>
66 
67 namespace google {
68 namespace protobuf {
69 
70 // Can't use an anonymous namespace here due to brokenness of Tru64 compiler.
71 namespace descriptor_unittest {
72 
73 // Some helpers to make assembling descriptors faster.
AddMessage(FileDescriptorProto * file,const std::string & name)74 DescriptorProto* AddMessage(FileDescriptorProto* file,
75                             const std::string& name) {
76   DescriptorProto* result = file->add_message_type();
77   result->set_name(name);
78   return result;
79 }
80 
AddNestedMessage(DescriptorProto * parent,const std::string & name)81 DescriptorProto* AddNestedMessage(DescriptorProto* parent,
82                                   const std::string& name) {
83   DescriptorProto* result = parent->add_nested_type();
84   result->set_name(name);
85   return result;
86 }
87 
AddEnum(FileDescriptorProto * file,const std::string & name)88 EnumDescriptorProto* AddEnum(FileDescriptorProto* file,
89                              const std::string& name) {
90   EnumDescriptorProto* result = file->add_enum_type();
91   result->set_name(name);
92   return result;
93 }
94 
AddNestedEnum(DescriptorProto * parent,const std::string & name)95 EnumDescriptorProto* AddNestedEnum(DescriptorProto* parent,
96                                    const std::string& name) {
97   EnumDescriptorProto* result = parent->add_enum_type();
98   result->set_name(name);
99   return result;
100 }
101 
AddService(FileDescriptorProto * file,const std::string & name)102 ServiceDescriptorProto* AddService(FileDescriptorProto* file,
103                                    const std::string& name) {
104   ServiceDescriptorProto* result = file->add_service();
105   result->set_name(name);
106   return result;
107 }
108 
AddField(DescriptorProto * parent,const std::string & name,int number,FieldDescriptorProto::Label label,FieldDescriptorProto::Type type)109 FieldDescriptorProto* AddField(DescriptorProto* parent, const std::string& name,
110                                int number, FieldDescriptorProto::Label label,
111                                FieldDescriptorProto::Type type) {
112   FieldDescriptorProto* result = parent->add_field();
113   result->set_name(name);
114   result->set_number(number);
115   result->set_label(label);
116   result->set_type(type);
117   return result;
118 }
119 
AddExtension(FileDescriptorProto * file,const std::string & extendee,const std::string & name,int number,FieldDescriptorProto::Label label,FieldDescriptorProto::Type type)120 FieldDescriptorProto* AddExtension(FileDescriptorProto* file,
121                                    const std::string& extendee,
122                                    const std::string& name, int number,
123                                    FieldDescriptorProto::Label label,
124                                    FieldDescriptorProto::Type type) {
125   FieldDescriptorProto* result = file->add_extension();
126   result->set_name(name);
127   result->set_number(number);
128   result->set_label(label);
129   result->set_type(type);
130   result->set_extendee(extendee);
131   return result;
132 }
133 
AddNestedExtension(DescriptorProto * parent,const std::string & extendee,const std::string & name,int number,FieldDescriptorProto::Label label,FieldDescriptorProto::Type type)134 FieldDescriptorProto* AddNestedExtension(DescriptorProto* parent,
135                                          const std::string& extendee,
136                                          const std::string& name, int number,
137                                          FieldDescriptorProto::Label label,
138                                          FieldDescriptorProto::Type type) {
139   FieldDescriptorProto* result = parent->add_extension();
140   result->set_name(name);
141   result->set_number(number);
142   result->set_label(label);
143   result->set_type(type);
144   result->set_extendee(extendee);
145   return result;
146 }
147 
AddExtensionRange(DescriptorProto * parent,int start,int end)148 DescriptorProto::ExtensionRange* AddExtensionRange(DescriptorProto* parent,
149                                                    int start, int end) {
150   DescriptorProto::ExtensionRange* result = parent->add_extension_range();
151   result->set_start(start);
152   result->set_end(end);
153   return result;
154 }
155 
AddReservedRange(DescriptorProto * parent,int start,int end)156 DescriptorProto::ReservedRange* AddReservedRange(DescriptorProto* parent,
157                                                  int start, int end) {
158   DescriptorProto::ReservedRange* result = parent->add_reserved_range();
159   result->set_start(start);
160   result->set_end(end);
161   return result;
162 }
163 
AddReservedRange(EnumDescriptorProto * parent,int start,int end)164 EnumDescriptorProto::EnumReservedRange* AddReservedRange(
165     EnumDescriptorProto* parent, int start, int end) {
166   EnumDescriptorProto::EnumReservedRange* result = parent->add_reserved_range();
167   result->set_start(start);
168   result->set_end(end);
169   return result;
170 }
171 
AddEnumValue(EnumDescriptorProto * enum_proto,const std::string & name,int number)172 EnumValueDescriptorProto* AddEnumValue(EnumDescriptorProto* enum_proto,
173                                        const std::string& name, int number) {
174   EnumValueDescriptorProto* result = enum_proto->add_value();
175   result->set_name(name);
176   result->set_number(number);
177   return result;
178 }
179 
AddMethod(ServiceDescriptorProto * service,const std::string & name,const std::string & input_type,const std::string & output_type)180 MethodDescriptorProto* AddMethod(ServiceDescriptorProto* service,
181                                  const std::string& name,
182                                  const std::string& input_type,
183                                  const std::string& output_type) {
184   MethodDescriptorProto* result = service->add_method();
185   result->set_name(name);
186   result->set_input_type(input_type);
187   result->set_output_type(output_type);
188   return result;
189 }
190 
191 // Empty enums technically aren't allowed.  We need to insert a dummy value
192 // into them.
AddEmptyEnum(FileDescriptorProto * file,const std::string & name)193 void AddEmptyEnum(FileDescriptorProto* file, const std::string& name) {
194   AddEnumValue(AddEnum(file, name), name + "_DUMMY", 1);
195 }
196 
197 class MockErrorCollector : public DescriptorPool::ErrorCollector {
198  public:
MockErrorCollector()199   MockErrorCollector() {}
~MockErrorCollector()200   ~MockErrorCollector() {}
201 
202   std::string text_;
203   std::string warning_text_;
204 
205   // implements ErrorCollector ---------------------------------------
AddError(const std::string & filename,const std::string & element_name,const Message * descriptor,ErrorLocation location,const std::string & message)206   void AddError(const std::string& filename, const std::string& element_name,
207                 const Message* descriptor, ErrorLocation location,
208                 const std::string& message) {
209     const char* location_name = nullptr;
210     switch (location) {
211       case NAME:
212         location_name = "NAME";
213         break;
214       case NUMBER:
215         location_name = "NUMBER";
216         break;
217       case TYPE:
218         location_name = "TYPE";
219         break;
220       case EXTENDEE:
221         location_name = "EXTENDEE";
222         break;
223       case DEFAULT_VALUE:
224         location_name = "DEFAULT_VALUE";
225         break;
226       case OPTION_NAME:
227         location_name = "OPTION_NAME";
228         break;
229       case OPTION_VALUE:
230         location_name = "OPTION_VALUE";
231         break;
232       case INPUT_TYPE:
233         location_name = "INPUT_TYPE";
234         break;
235       case OUTPUT_TYPE:
236         location_name = "OUTPUT_TYPE";
237         break;
238       case IMPORT:
239         location_name = "IMPORT";
240         break;
241       case OTHER:
242         location_name = "OTHER";
243         break;
244     }
245 
246     strings::SubstituteAndAppend(&text_, "$0: $1: $2: $3\n", filename,
247                               element_name, location_name, message);
248   }
249 
250   // implements ErrorCollector ---------------------------------------
AddWarning(const std::string & filename,const std::string & element_name,const Message * descriptor,ErrorLocation location,const std::string & message)251   void AddWarning(const std::string& filename, const std::string& element_name,
252                   const Message* descriptor, ErrorLocation location,
253                   const std::string& message) {
254     const char* location_name = nullptr;
255     switch (location) {
256       case NAME:
257         location_name = "NAME";
258         break;
259       case NUMBER:
260         location_name = "NUMBER";
261         break;
262       case TYPE:
263         location_name = "TYPE";
264         break;
265       case EXTENDEE:
266         location_name = "EXTENDEE";
267         break;
268       case DEFAULT_VALUE:
269         location_name = "DEFAULT_VALUE";
270         break;
271       case OPTION_NAME:
272         location_name = "OPTION_NAME";
273         break;
274       case OPTION_VALUE:
275         location_name = "OPTION_VALUE";
276         break;
277       case INPUT_TYPE:
278         location_name = "INPUT_TYPE";
279         break;
280       case OUTPUT_TYPE:
281         location_name = "OUTPUT_TYPE";
282         break;
283       case IMPORT:
284         location_name = "IMPORT";
285         break;
286       case OTHER:
287         location_name = "OTHER";
288         break;
289     }
290 
291     strings::SubstituteAndAppend(&warning_text_, "$0: $1: $2: $3\n", filename,
292                               element_name, location_name, 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 we 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   // We have to import the Any dependency.
3152   FileDescriptorProto any_proto;
3153   google::protobuf::Any::descriptor()->file()->CopyTo(&any_proto);
3154   ASSERT_TRUE(pool.BuildFile(any_proto) != nullptr);
3155 
3156   protobuf_unittest::TestMessageWithCustomOptions::descriptor()->file()->CopyTo(
3157       &file_proto);
3158   ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr);
3159 
3160   ASSERT_TRUE(TextFormat::ParseFromString(
3161       "name: \"custom_options_import.proto\" "
3162       "package: \"protobuf_unittest\" "
3163       "dependency: \"google/protobuf/unittest_custom_options.proto\" "
3164       "options { "
3165       "  uninterpreted_option { "
3166       "    name { "
3167       "      name_part: \"file_opt1\" "
3168       "      is_extension: true "
3169       "    } "
3170       "    positive_int_value: 1234 "
3171       "  } "
3172       // Test a non-extension option too.  (At one point this failed due to a
3173       // bug.)
3174       "  uninterpreted_option { "
3175       "    name { "
3176       "      name_part: \"java_package\" "
3177       "      is_extension: false "
3178       "    } "
3179       "    string_value: \"foo\" "
3180       "  } "
3181       // Test that enum-typed options still work too.  (At one point this also
3182       // failed due to a bug.)
3183       "  uninterpreted_option { "
3184       "    name { "
3185       "      name_part: \"optimize_for\" "
3186       "      is_extension: false "
3187       "    } "
3188       "    identifier_value: \"SPEED\" "
3189       "  } "
3190       "}",
3191       &file_proto));
3192 
3193   const FileDescriptor* file = pool.BuildFile(file_proto);
3194   ASSERT_TRUE(file != nullptr);
3195   EXPECT_EQ(1234, file->options().GetExtension(protobuf_unittest::file_opt1));
3196   EXPECT_TRUE(file->options().has_java_package());
3197   EXPECT_EQ("foo", file->options().java_package());
3198   EXPECT_TRUE(file->options().has_optimize_for());
3199   EXPECT_EQ(FileOptions::SPEED, file->options().optimize_for());
3200 }
3201 
TEST(CustomOptions,MessageOptionThreeFieldsSet)3202 TEST(CustomOptions, MessageOptionThreeFieldsSet) {
3203   // This tests a bug which previously existed in custom options parsing.  The
3204   // bug occurred when you defined a custom option with message type and then
3205   // set three fields of that option on a single definition (see the example
3206   // below).  The bug is a bit hard to explain, so check the change history if
3207   // you want to know more.
3208   DescriptorPool pool;
3209 
3210   FileDescriptorProto file_proto;
3211   FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto);
3212   ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr);
3213 
3214   FileDescriptorProto any_proto;
3215   google::protobuf::Any::descriptor()->file()->CopyTo(&any_proto);
3216   ASSERT_TRUE(pool.BuildFile(any_proto) != nullptr);
3217 
3218   protobuf_unittest::TestMessageWithCustomOptions::descriptor()->file()->CopyTo(
3219       &file_proto);
3220   ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr);
3221 
3222   // The following represents the definition:
3223   //
3224   //   import "google/protobuf/unittest_custom_options.proto"
3225   //   package protobuf_unittest;
3226   //   message Foo {
3227   //     option (complex_opt1).foo  = 1234;
3228   //     option (complex_opt1).foo2 = 1234;
3229   //     option (complex_opt1).foo3 = 1234;
3230   //   }
3231   ASSERT_TRUE(TextFormat::ParseFromString(
3232       "name: \"custom_options_import.proto\" "
3233       "package: \"protobuf_unittest\" "
3234       "dependency: \"google/protobuf/unittest_custom_options.proto\" "
3235       "message_type { "
3236       "  name: \"Foo\" "
3237       "  options { "
3238       "    uninterpreted_option { "
3239       "      name { "
3240       "        name_part: \"complex_opt1\" "
3241       "        is_extension: true "
3242       "      } "
3243       "      name { "
3244       "        name_part: \"foo\" "
3245       "        is_extension: false "
3246       "      } "
3247       "      positive_int_value: 1234 "
3248       "    } "
3249       "    uninterpreted_option { "
3250       "      name { "
3251       "        name_part: \"complex_opt1\" "
3252       "        is_extension: true "
3253       "      } "
3254       "      name { "
3255       "        name_part: \"foo2\" "
3256       "        is_extension: false "
3257       "      } "
3258       "      positive_int_value: 1234 "
3259       "    } "
3260       "    uninterpreted_option { "
3261       "      name { "
3262       "        name_part: \"complex_opt1\" "
3263       "        is_extension: true "
3264       "      } "
3265       "      name { "
3266       "        name_part: \"foo3\" "
3267       "        is_extension: false "
3268       "      } "
3269       "      positive_int_value: 1234 "
3270       "    } "
3271       "  } "
3272       "}",
3273       &file_proto));
3274 
3275   const FileDescriptor* file = pool.BuildFile(file_proto);
3276   ASSERT_TRUE(file != nullptr);
3277   ASSERT_EQ(1, file->message_type_count());
3278 
3279   const MessageOptions& options = file->message_type(0)->options();
3280   EXPECT_EQ(1234, options.GetExtension(protobuf_unittest::complex_opt1).foo());
3281 }
3282 
TEST(CustomOptions,MessageOptionRepeatedLeafFieldSet)3283 TEST(CustomOptions, MessageOptionRepeatedLeafFieldSet) {
3284   // This test verifies that repeated fields in custom options can be
3285   // given multiple values by repeating the option with a different value.
3286   // This test checks repeated leaf values. Each repeated custom value
3287   // appears in a different uninterpreted_option, which will be concatenated
3288   // when they are merged into the final option value.
3289   DescriptorPool pool;
3290 
3291   FileDescriptorProto file_proto;
3292   FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto);
3293   ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr);
3294 
3295   FileDescriptorProto any_proto;
3296   google::protobuf::Any::descriptor()->file()->CopyTo(&any_proto);
3297   ASSERT_TRUE(pool.BuildFile(any_proto) != nullptr);
3298 
3299   protobuf_unittest::TestMessageWithCustomOptions::descriptor()->file()->CopyTo(
3300       &file_proto);
3301   ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr);
3302 
3303   // The following represents the definition:
3304   //
3305   //   import "google/protobuf/unittest_custom_options.proto"
3306   //   package protobuf_unittest;
3307   //   message Foo {
3308   //     option (complex_opt1).foo4 = 12;
3309   //     option (complex_opt1).foo4 = 34;
3310   //     option (complex_opt1).foo4 = 56;
3311   //   }
3312   ASSERT_TRUE(TextFormat::ParseFromString(
3313       "name: \"custom_options_import.proto\" "
3314       "package: \"protobuf_unittest\" "
3315       "dependency: \"google/protobuf/unittest_custom_options.proto\" "
3316       "message_type { "
3317       "  name: \"Foo\" "
3318       "  options { "
3319       "    uninterpreted_option { "
3320       "      name { "
3321       "        name_part: \"complex_opt1\" "
3322       "        is_extension: true "
3323       "      } "
3324       "      name { "
3325       "        name_part: \"foo4\" "
3326       "        is_extension: false "
3327       "      } "
3328       "      positive_int_value: 12 "
3329       "    } "
3330       "    uninterpreted_option { "
3331       "      name { "
3332       "        name_part: \"complex_opt1\" "
3333       "        is_extension: true "
3334       "      } "
3335       "      name { "
3336       "        name_part: \"foo4\" "
3337       "        is_extension: false "
3338       "      } "
3339       "      positive_int_value: 34 "
3340       "    } "
3341       "    uninterpreted_option { "
3342       "      name { "
3343       "        name_part: \"complex_opt1\" "
3344       "        is_extension: true "
3345       "      } "
3346       "      name { "
3347       "        name_part: \"foo4\" "
3348       "        is_extension: false "
3349       "      } "
3350       "      positive_int_value: 56 "
3351       "    } "
3352       "  } "
3353       "}",
3354       &file_proto));
3355 
3356   const FileDescriptor* file = pool.BuildFile(file_proto);
3357   ASSERT_TRUE(file != nullptr);
3358   ASSERT_EQ(1, file->message_type_count());
3359 
3360   const MessageOptions& options = file->message_type(0)->options();
3361   EXPECT_EQ(3, options.GetExtension(protobuf_unittest::complex_opt1).foo4_size());
3362   EXPECT_EQ(12, options.GetExtension(protobuf_unittest::complex_opt1).foo4(0));
3363   EXPECT_EQ(34, options.GetExtension(protobuf_unittest::complex_opt1).foo4(1));
3364   EXPECT_EQ(56, options.GetExtension(protobuf_unittest::complex_opt1).foo4(2));
3365 }
3366 
TEST(CustomOptions,MessageOptionRepeatedMsgFieldSet)3367 TEST(CustomOptions, MessageOptionRepeatedMsgFieldSet) {
3368   // This test verifies that repeated fields in custom options can be
3369   // given multiple values by repeating the option with a different value.
3370   // This test checks repeated message values. Each repeated custom value
3371   // appears in a different uninterpreted_option, which will be concatenated
3372   // when they are merged into the final option value.
3373   DescriptorPool pool;
3374 
3375   FileDescriptorProto file_proto;
3376   FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto);
3377   ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr);
3378 
3379   FileDescriptorProto any_proto;
3380   google::protobuf::Any::descriptor()->file()->CopyTo(&any_proto);
3381   ASSERT_TRUE(pool.BuildFile(any_proto) != nullptr);
3382 
3383   protobuf_unittest::TestMessageWithCustomOptions::descriptor()->file()->CopyTo(
3384       &file_proto);
3385   ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr);
3386 
3387   // The following represents the definition:
3388   //
3389   //   import "google/protobuf/unittest_custom_options.proto"
3390   //   package protobuf_unittest;
3391   //   message Foo {
3392   //     option (complex_opt2).barney = {waldo: 1};
3393   //     option (complex_opt2).barney = {waldo: 10};
3394   //     option (complex_opt2).barney = {waldo: 100};
3395   //   }
3396   ASSERT_TRUE(TextFormat::ParseFromString(
3397       "name: \"custom_options_import.proto\" "
3398       "package: \"protobuf_unittest\" "
3399       "dependency: \"google/protobuf/unittest_custom_options.proto\" "
3400       "message_type { "
3401       "  name: \"Foo\" "
3402       "  options { "
3403       "    uninterpreted_option { "
3404       "      name { "
3405       "        name_part: \"complex_opt2\" "
3406       "        is_extension: true "
3407       "      } "
3408       "      name { "
3409       "        name_part: \"barney\" "
3410       "        is_extension: false "
3411       "      } "
3412       "      aggregate_value: \"waldo: 1\" "
3413       "    } "
3414       "    uninterpreted_option { "
3415       "      name { "
3416       "        name_part: \"complex_opt2\" "
3417       "        is_extension: true "
3418       "      } "
3419       "      name { "
3420       "        name_part: \"barney\" "
3421       "        is_extension: false "
3422       "      } "
3423       "      aggregate_value: \"waldo: 10\" "
3424       "    } "
3425       "    uninterpreted_option { "
3426       "      name { "
3427       "        name_part: \"complex_opt2\" "
3428       "        is_extension: true "
3429       "      } "
3430       "      name { "
3431       "        name_part: \"barney\" "
3432       "        is_extension: false "
3433       "      } "
3434       "      aggregate_value: \"waldo: 100\" "
3435       "    } "
3436       "  } "
3437       "}",
3438       &file_proto));
3439 
3440   const FileDescriptor* file = pool.BuildFile(file_proto);
3441   ASSERT_TRUE(file != nullptr);
3442   ASSERT_EQ(1, file->message_type_count());
3443 
3444   const MessageOptions& options = file->message_type(0)->options();
3445   EXPECT_EQ(3,
3446             options.GetExtension(protobuf_unittest::complex_opt2).barney_size());
3447   EXPECT_EQ(
3448       1, options.GetExtension(protobuf_unittest::complex_opt2).barney(0).waldo());
3449   EXPECT_EQ(
3450       10,
3451       options.GetExtension(protobuf_unittest::complex_opt2).barney(1).waldo());
3452   EXPECT_EQ(
3453       100,
3454       options.GetExtension(protobuf_unittest::complex_opt2).barney(2).waldo());
3455 }
3456 
3457 // Check that aggregate options were parsed and saved correctly in
3458 // the appropriate descriptors.
TEST(CustomOptions,AggregateOptions)3459 TEST(CustomOptions, AggregateOptions) {
3460   const Descriptor* msg = protobuf_unittest::AggregateMessage::descriptor();
3461   const FileDescriptor* file = msg->file();
3462   const FieldDescriptor* field = msg->FindFieldByName("fieldname");
3463   const EnumDescriptor* enumd = file->FindEnumTypeByName("AggregateEnum");
3464   const EnumValueDescriptor* enumv = enumd->FindValueByName("VALUE");
3465   const ServiceDescriptor* service =
3466       file->FindServiceByName("AggregateService");
3467   const MethodDescriptor* method = service->FindMethodByName("Method");
3468 
3469   // Tests for the different types of data embedded in fileopt
3470   const protobuf_unittest::Aggregate& file_options =
3471       file->options().GetExtension(protobuf_unittest::fileopt);
3472   EXPECT_EQ(100, file_options.i());
3473   EXPECT_EQ("FileAnnotation", file_options.s());
3474   EXPECT_EQ("NestedFileAnnotation", file_options.sub().s());
3475   EXPECT_EQ("FileExtensionAnnotation",
3476             file_options.file().GetExtension(protobuf_unittest::fileopt).s());
3477   EXPECT_EQ("EmbeddedMessageSetElement",
3478             file_options.mset()
3479                 .GetExtension(protobuf_unittest::AggregateMessageSetElement ::
3480                                   message_set_extension)
3481                 .s());
3482 
3483   protobuf_unittest::AggregateMessageSetElement any_payload;
3484   ASSERT_TRUE(file_options.any().UnpackTo(&any_payload));
3485   EXPECT_EQ("EmbeddedMessageSetElement", any_payload.s());
3486 
3487   // Simple tests for all the other types of annotations
3488   EXPECT_EQ("MessageAnnotation",
3489             msg->options().GetExtension(protobuf_unittest::msgopt).s());
3490   EXPECT_EQ("FieldAnnotation",
3491             field->options().GetExtension(protobuf_unittest::fieldopt).s());
3492   EXPECT_EQ("EnumAnnotation",
3493             enumd->options().GetExtension(protobuf_unittest::enumopt).s());
3494   EXPECT_EQ("EnumValueAnnotation",
3495             enumv->options().GetExtension(protobuf_unittest::enumvalopt).s());
3496   EXPECT_EQ("ServiceAnnotation",
3497             service->options().GetExtension(protobuf_unittest::serviceopt).s());
3498   EXPECT_EQ("MethodAnnotation",
3499             method->options().GetExtension(protobuf_unittest::methodopt).s());
3500 }
3501 
TEST(CustomOptions,UnusedImportError)3502 TEST(CustomOptions, UnusedImportError) {
3503   DescriptorPool pool;
3504 
3505   FileDescriptorProto file_proto;
3506   FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto);
3507   ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr);
3508 
3509   FileDescriptorProto any_proto;
3510   google::protobuf::Any::descriptor()->file()->CopyTo(&any_proto);
3511   ASSERT_TRUE(pool.BuildFile(any_proto) != nullptr);
3512 
3513   protobuf_unittest::TestMessageWithCustomOptions::descriptor()->file()->CopyTo(
3514       &file_proto);
3515   ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr);
3516 
3517   pool.AddUnusedImportTrackFile("custom_options_import.proto", true);
3518   ASSERT_TRUE(TextFormat::ParseFromString(
3519       "name: \"custom_options_import.proto\" "
3520       "package: \"protobuf_unittest\" "
3521       "dependency: \"google/protobuf/unittest_custom_options.proto\" ",
3522       &file_proto));
3523 
3524   MockErrorCollector error_collector;
3525   EXPECT_FALSE(pool.BuildFileCollectingErrors(file_proto, &error_collector));
3526   EXPECT_EQ(
3527       "custom_options_import.proto: "
3528       "google/protobuf/unittest_custom_options.proto: IMPORT: Import "
3529       "google/protobuf/unittest_custom_options.proto is unused.\n",
3530       error_collector.text_);
3531 }
3532 
3533 // Verifies that proto files can correctly be parsed, even if the
3534 // custom options defined in the file are incompatible with those
3535 // compiled in the binary. See http://b/19276250.
TEST(CustomOptions,OptionsWithIncompatibleDescriptors)3536 TEST(CustomOptions, OptionsWithIncompatibleDescriptors) {
3537   DescriptorPool pool;
3538 
3539   FileDescriptorProto file_proto;
3540   MessageOptions::descriptor()->file()->CopyTo(&file_proto);
3541   ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr);
3542 
3543   // Create a new file descriptor proto containing a subset of the
3544   // messages defined in google/protobuf/unittest_custom_options.proto.
3545   file_proto.Clear();
3546   file_proto.set_name("unittest_custom_options.proto");
3547   file_proto.set_package("protobuf_unittest");
3548   file_proto.add_dependency("google/protobuf/descriptor.proto");
3549 
3550   // Add the "required_enum_opt" extension.
3551   FieldDescriptorProto* extension = file_proto.add_extension();
3552   protobuf_unittest::OldOptionType::descriptor()
3553       ->file()
3554       ->FindExtensionByName("required_enum_opt")
3555       ->CopyTo(extension);
3556 
3557   // Add a test message that uses the "required_enum_opt" option.
3558   DescriptorProto* test_message_type = file_proto.add_message_type();
3559   protobuf_unittest::TestMessageWithRequiredEnumOption::descriptor()->CopyTo(
3560       test_message_type);
3561 
3562   // Instruct the extension to use NewOptionType instead of
3563   // OldOptionType, and add the descriptor of NewOptionType.
3564   extension->set_type_name(".protobuf_unittest.NewOptionType");
3565   DescriptorProto* new_option_type = file_proto.add_message_type();
3566   protobuf_unittest::NewOptionType::descriptor()->CopyTo(new_option_type);
3567 
3568   // Replace the value of the "required_enum_opt" option used in the
3569   // test message with an enum value that only exists in NewOptionType.
3570   ASSERT_TRUE(
3571       TextFormat::ParseFromString("uninterpreted_option { "
3572                                   "  name { "
3573                                   "    name_part: 'required_enum_opt' "
3574                                   "    is_extension: true "
3575                                   "  } "
3576                                   "  aggregate_value: 'value: NEW_VALUE'"
3577                                   "}",
3578                                   test_message_type->mutable_options()));
3579 
3580   // Adding the file descriptor to the pool should fail.
3581   EXPECT_TRUE(pool.BuildFile(file_proto) == nullptr);
3582 }
3583 
3584 // Test that FileDescriptor::DebugString() formats custom options correctly.
TEST(CustomOptions,DebugString)3585 TEST(CustomOptions, DebugString) {
3586   DescriptorPool pool;
3587 
3588   FileDescriptorProto file_proto;
3589   MessageOptions::descriptor()->file()->CopyTo(&file_proto);
3590   ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr);
3591 
3592   // Add "foo.proto":
3593   //   import "google/protobuf/descriptor.proto";
3594   //   package "protobuf_unittest";
3595   //   option (protobuf_unittest.cc_option1) = 1;
3596   //   option (protobuf_unittest.cc_option2) = 2;
3597   //   extend google.protobuf.FieldOptions {
3598   //     optional int32 cc_option1 = 7736974;
3599   //     optional int32 cc_option2 = 7736975;
3600   //   }
3601   ASSERT_TRUE(TextFormat::ParseFromString(
3602       "name: \"foo.proto\" "
3603       "package: \"protobuf_unittest\" "
3604       "dependency: \"google/protobuf/descriptor.proto\" "
3605       "options { "
3606       "  uninterpreted_option { "
3607       "    name { "
3608       "      name_part: \"protobuf_unittest.cc_option1\" "
3609       "      is_extension: true "
3610       "    } "
3611       "    positive_int_value: 1 "
3612       "  } "
3613       "  uninterpreted_option { "
3614       "    name { "
3615       "      name_part: \"protobuf_unittest.cc_option2\" "
3616       "      is_extension: true "
3617       "    } "
3618       "    positive_int_value: 2 "
3619       "  } "
3620       "} "
3621       "extension { "
3622       "  name: \"cc_option1\" "
3623       "  extendee: \".google.protobuf.FileOptions\" "
3624       // This field number is intentionally chosen to be the same as
3625       // (.fileopt1) defined in unittest_custom_options.proto (linked
3626       // in this test binary). This is to test whether we are messing
3627       // generated pool with custom descriptor pools when dealing with
3628       // custom options.
3629       "  number: 7736974 "
3630       "  label: LABEL_OPTIONAL "
3631       "  type: TYPE_INT32 "
3632       "}"
3633       "extension { "
3634       "  name: \"cc_option2\" "
3635       "  extendee: \".google.protobuf.FileOptions\" "
3636       "  number: 7736975 "
3637       "  label: LABEL_OPTIONAL "
3638       "  type: TYPE_INT32 "
3639       "}",
3640       &file_proto));
3641   const FileDescriptor* descriptor = pool.BuildFile(file_proto);
3642   ASSERT_TRUE(descriptor != nullptr);
3643 
3644   EXPECT_EQ(2, descriptor->extension_count());
3645 
3646   ASSERT_EQ(
3647       "syntax = \"proto2\";\n"
3648       "\n"
3649       "import \"google/protobuf/descriptor.proto\";\n"
3650       "package protobuf_unittest;\n"
3651       "\n"
3652       "option (.protobuf_unittest.cc_option1) = 1;\n"
3653       "option (.protobuf_unittest.cc_option2) = 2;\n"
3654       "\n"
3655       "extend .google.protobuf.FileOptions {\n"
3656       "  optional int32 cc_option1 = 7736974;\n"
3657       "  optional int32 cc_option2 = 7736975;\n"
3658       "}\n"
3659       "\n",
3660       descriptor->DebugString());
3661 }
3662 
3663 // ===================================================================
3664 
3665 class ValidationErrorTest : public testing::Test {
3666  protected:
3667   // Parse file_text as a FileDescriptorProto in text format and add it
3668   // to the DescriptorPool.  Expect no errors.
BuildFile(const std::string & file_text)3669   const FileDescriptor* BuildFile(const std::string& file_text) {
3670     FileDescriptorProto file_proto;
3671     EXPECT_TRUE(TextFormat::ParseFromString(file_text, &file_proto));
3672     return GOOGLE_CHECK_NOTNULL(pool_.BuildFile(file_proto));
3673   }
3674 
3675   // Parse file_text as a FileDescriptorProto in text format and add it
3676   // to the DescriptorPool.  Expect errors to be produced which match the
3677   // given error text.
BuildFileWithErrors(const std::string & file_text,const std::string & expected_errors)3678   void BuildFileWithErrors(const std::string& file_text,
3679                            const std::string& expected_errors) {
3680     FileDescriptorProto file_proto;
3681     ASSERT_TRUE(TextFormat::ParseFromString(file_text, &file_proto));
3682 
3683     MockErrorCollector error_collector;
3684     EXPECT_TRUE(pool_.BuildFileCollectingErrors(file_proto, &error_collector) ==
3685                 nullptr);
3686     EXPECT_EQ(expected_errors, error_collector.text_);
3687   }
3688 
3689   // Parse file_text as a FileDescriptorProto in text format and add it
3690   // to the DescriptorPool.  Expect errors to be produced which match the
3691   // given warning text.
BuildFileWithWarnings(const std::string & file_text,const std::string & expected_warnings)3692   void BuildFileWithWarnings(const std::string& file_text,
3693                              const std::string& expected_warnings) {
3694     FileDescriptorProto file_proto;
3695     ASSERT_TRUE(TextFormat::ParseFromString(file_text, &file_proto));
3696 
3697     MockErrorCollector error_collector;
3698     EXPECT_TRUE(pool_.BuildFileCollectingErrors(file_proto, &error_collector));
3699     EXPECT_EQ(expected_warnings, error_collector.warning_text_);
3700   }
3701 
3702   // Builds some already-parsed file in our test pool.
BuildFileInTestPool(const FileDescriptor * file)3703   void BuildFileInTestPool(const FileDescriptor* file) {
3704     FileDescriptorProto file_proto;
3705     file->CopyTo(&file_proto);
3706     ASSERT_TRUE(pool_.BuildFile(file_proto) != nullptr);
3707   }
3708 
3709   // Build descriptor.proto in our test pool. This allows us to extend it in
3710   // the test pool, so we can test custom options.
BuildDescriptorMessagesInTestPool()3711   void BuildDescriptorMessagesInTestPool() {
3712     BuildFileInTestPool(DescriptorProto::descriptor()->file());
3713   }
3714 
3715   DescriptorPool pool_;
3716 };
3717 
TEST_F(ValidationErrorTest,AlreadyDefined)3718 TEST_F(ValidationErrorTest, AlreadyDefined) {
3719   BuildFileWithErrors(
3720       "name: \"foo.proto\" "
3721       "message_type { name: \"Foo\" }"
3722       "message_type { name: \"Foo\" }",
3723 
3724       "foo.proto: Foo: NAME: \"Foo\" is already defined.\n");
3725 }
3726 
TEST_F(ValidationErrorTest,AlreadyDefinedInPackage)3727 TEST_F(ValidationErrorTest, AlreadyDefinedInPackage) {
3728   BuildFileWithErrors(
3729       "name: \"foo.proto\" "
3730       "package: \"foo.bar\" "
3731       "message_type { name: \"Foo\" }"
3732       "message_type { name: \"Foo\" }",
3733 
3734       "foo.proto: foo.bar.Foo: NAME: \"Foo\" is already defined in "
3735       "\"foo.bar\".\n");
3736 }
3737 
TEST_F(ValidationErrorTest,AlreadyDefinedInOtherFile)3738 TEST_F(ValidationErrorTest, AlreadyDefinedInOtherFile) {
3739   BuildFile(
3740       "name: \"foo.proto\" "
3741       "message_type { name: \"Foo\" }");
3742 
3743   BuildFileWithErrors(
3744       "name: \"bar.proto\" "
3745       "message_type { name: \"Foo\" }",
3746 
3747       "bar.proto: Foo: NAME: \"Foo\" is already defined in file "
3748       "\"foo.proto\".\n");
3749 }
3750 
TEST_F(ValidationErrorTest,PackageAlreadyDefined)3751 TEST_F(ValidationErrorTest, PackageAlreadyDefined) {
3752   BuildFile(
3753       "name: \"foo.proto\" "
3754       "message_type { name: \"foo\" }");
3755   BuildFileWithErrors(
3756       "name: \"bar.proto\" "
3757       "package: \"foo.bar\"",
3758 
3759       "bar.proto: foo: NAME: \"foo\" is already defined (as something other "
3760       "than a package) in file \"foo.proto\".\n");
3761 }
3762 
TEST_F(ValidationErrorTest,EnumValueAlreadyDefinedInParent)3763 TEST_F(ValidationErrorTest, EnumValueAlreadyDefinedInParent) {
3764   BuildFileWithErrors(
3765       "name: \"foo.proto\" "
3766       "enum_type { name: \"Foo\" value { name: \"FOO\" number: 1 } } "
3767       "enum_type { name: \"Bar\" value { name: \"FOO\" number: 1 } } ",
3768 
3769       "foo.proto: FOO: NAME: \"FOO\" is already defined.\n"
3770       "foo.proto: FOO: NAME: Note that enum values use C++ scoping rules, "
3771       "meaning that enum values are siblings of their type, not children of "
3772       "it.  Therefore, \"FOO\" must be unique within the global scope, not "
3773       "just within \"Bar\".\n");
3774 }
3775 
TEST_F(ValidationErrorTest,EnumValueAlreadyDefinedInParentNonGlobal)3776 TEST_F(ValidationErrorTest, EnumValueAlreadyDefinedInParentNonGlobal) {
3777   BuildFileWithErrors(
3778       "name: \"foo.proto\" "
3779       "package: \"pkg\" "
3780       "enum_type { name: \"Foo\" value { name: \"FOO\" number: 1 } } "
3781       "enum_type { name: \"Bar\" value { name: \"FOO\" number: 1 } } ",
3782 
3783       "foo.proto: pkg.FOO: NAME: \"FOO\" is already defined in \"pkg\".\n"
3784       "foo.proto: pkg.FOO: NAME: Note that enum values use C++ scoping rules, "
3785       "meaning that enum values are siblings of their type, not children of "
3786       "it.  Therefore, \"FOO\" must be unique within \"pkg\", not just within "
3787       "\"Bar\".\n");
3788 }
3789 
TEST_F(ValidationErrorTest,MissingName)3790 TEST_F(ValidationErrorTest, MissingName) {
3791   BuildFileWithErrors(
3792       "name: \"foo.proto\" "
3793       "message_type { }",
3794 
3795       "foo.proto: : NAME: Missing name.\n");
3796 }
3797 
TEST_F(ValidationErrorTest,InvalidName)3798 TEST_F(ValidationErrorTest, InvalidName) {
3799   BuildFileWithErrors(
3800       "name: \"foo.proto\" "
3801       "message_type { name: \"$\" }",
3802 
3803       "foo.proto: $: NAME: \"$\" is not a valid identifier.\n");
3804 }
3805 
TEST_F(ValidationErrorTest,InvalidPackageName)3806 TEST_F(ValidationErrorTest, InvalidPackageName) {
3807   BuildFileWithErrors(
3808       "name: \"foo.proto\" "
3809       "package: \"foo.$\"",
3810 
3811       "foo.proto: foo.$: NAME: \"$\" is not a valid identifier.\n");
3812 }
3813 
TEST_F(ValidationErrorTest,MissingFileName)3814 TEST_F(ValidationErrorTest, MissingFileName) {
3815   BuildFileWithErrors("",
3816 
3817                       ": : OTHER: Missing field: FileDescriptorProto.name.\n");
3818 }
3819 
TEST_F(ValidationErrorTest,DupeDependency)3820 TEST_F(ValidationErrorTest, DupeDependency) {
3821   BuildFile("name: \"foo.proto\"");
3822   BuildFileWithErrors(
3823       "name: \"bar.proto\" "
3824       "dependency: \"foo.proto\" "
3825       "dependency: \"foo.proto\" ",
3826 
3827       "bar.proto: foo.proto: IMPORT: Import \"foo.proto\" was listed twice.\n");
3828 }
3829 
TEST_F(ValidationErrorTest,UnknownDependency)3830 TEST_F(ValidationErrorTest, UnknownDependency) {
3831   BuildFileWithErrors(
3832       "name: \"bar.proto\" "
3833       "dependency: \"foo.proto\" ",
3834 
3835       "bar.proto: foo.proto: IMPORT: Import \"foo.proto\" has not been "
3836       "loaded.\n");
3837 }
3838 
TEST_F(ValidationErrorTest,InvalidPublicDependencyIndex)3839 TEST_F(ValidationErrorTest, InvalidPublicDependencyIndex) {
3840   BuildFile("name: \"foo.proto\"");
3841   BuildFileWithErrors(
3842       "name: \"bar.proto\" "
3843       "dependency: \"foo.proto\" "
3844       "public_dependency: 1",
3845       "bar.proto: bar.proto: OTHER: Invalid public dependency index.\n");
3846 }
3847 
TEST_F(ValidationErrorTest,ForeignUnimportedPackageNoCrash)3848 TEST_F(ValidationErrorTest, ForeignUnimportedPackageNoCrash) {
3849   // Used to crash:  If we depend on a non-existent file and then refer to a
3850   // package defined in a file that we didn't import, and that package is
3851   // nested within a parent package which this file is also in, and we don't
3852   // include that parent package in the name (i.e. we do a relative lookup)...
3853   // Yes, really.
3854   BuildFile(
3855       "name: 'foo.proto' "
3856       "package: 'outer.foo' ");
3857   BuildFileWithErrors(
3858       "name: 'bar.proto' "
3859       "dependency: 'baz.proto' "
3860       "package: 'outer.bar' "
3861       "message_type { "
3862       "  name: 'Bar' "
3863       "  field { name:'bar' number:1 label:LABEL_OPTIONAL type_name:'foo.Foo' }"
3864       "}",
3865 
3866       "bar.proto: baz.proto: IMPORT: Import \"baz.proto\" has not been "
3867       "loaded.\n"
3868       "bar.proto: outer.bar.Bar.bar: TYPE: \"outer.foo\" seems to be defined "
3869       "in "
3870       "\"foo.proto\", which is not imported by \"bar.proto\".  To use it here, "
3871       "please add the necessary import.\n");
3872 }
3873 
TEST_F(ValidationErrorTest,DupeFile)3874 TEST_F(ValidationErrorTest, DupeFile) {
3875   BuildFile(
3876       "name: \"foo.proto\" "
3877       "message_type { name: \"Foo\" }");
3878   // Note:  We should *not* get redundant errors about "Foo" already being
3879   //   defined.
3880   BuildFileWithErrors(
3881       "name: \"foo.proto\" "
3882       "message_type { name: \"Foo\" } "
3883       // Add another type so that the files aren't identical (in which case
3884       // there would be no error).
3885       "enum_type { name: \"Bar\" }",
3886 
3887       "foo.proto: foo.proto: OTHER: A file with this name is already in the "
3888       "pool.\n");
3889 }
3890 
TEST_F(ValidationErrorTest,FieldInExtensionRange)3891 TEST_F(ValidationErrorTest, FieldInExtensionRange) {
3892   BuildFileWithErrors(
3893       "name: \"foo.proto\" "
3894       "message_type {"
3895       "  name: \"Foo\""
3896       "  field { name: \"foo\" number:  9 label:LABEL_OPTIONAL type:TYPE_INT32 "
3897       "}"
3898       "  field { name: \"bar\" number: 10 label:LABEL_OPTIONAL type:TYPE_INT32 "
3899       "}"
3900       "  field { name: \"baz\" number: 19 label:LABEL_OPTIONAL type:TYPE_INT32 "
3901       "}"
3902       "  field { name: \"qux\" number: 20 label:LABEL_OPTIONAL type:TYPE_INT32 "
3903       "}"
3904       "  extension_range { start: 10 end: 20 }"
3905       "}",
3906 
3907       "foo.proto: Foo.bar: NUMBER: Extension range 10 to 19 includes field "
3908       "\"bar\" (10).\n"
3909       "foo.proto: Foo.baz: NUMBER: Extension range 10 to 19 includes field "
3910       "\"baz\" (19).\n");
3911 }
3912 
TEST_F(ValidationErrorTest,OverlappingExtensionRanges)3913 TEST_F(ValidationErrorTest, OverlappingExtensionRanges) {
3914   BuildFileWithErrors(
3915       "name: \"foo.proto\" "
3916       "message_type {"
3917       "  name: \"Foo\""
3918       "  extension_range { start: 10 end: 20 }"
3919       "  extension_range { start: 20 end: 30 }"
3920       "  extension_range { start: 19 end: 21 }"
3921       "}",
3922 
3923       "foo.proto: Foo: NUMBER: Extension range 19 to 20 overlaps with "
3924       "already-defined range 10 to 19.\n"
3925       "foo.proto: Foo: NUMBER: Extension range 19 to 20 overlaps with "
3926       "already-defined range 20 to 29.\n");
3927 }
3928 
TEST_F(ValidationErrorTest,ReservedFieldError)3929 TEST_F(ValidationErrorTest, ReservedFieldError) {
3930   BuildFileWithErrors(
3931       "name: \"foo.proto\" "
3932       "message_type {"
3933       "  name: \"Foo\""
3934       "  field { name: \"foo\" number: 15 label:LABEL_OPTIONAL type:TYPE_INT32 "
3935       "}"
3936       "  reserved_range { start: 10 end: 20 }"
3937       "}",
3938 
3939       "foo.proto: Foo.foo: NUMBER: Field \"foo\" uses reserved number 15.\n");
3940 }
3941 
TEST_F(ValidationErrorTest,ReservedExtensionRangeError)3942 TEST_F(ValidationErrorTest, ReservedExtensionRangeError) {
3943   BuildFileWithErrors(
3944       "name: \"foo.proto\" "
3945       "message_type {"
3946       "  name: \"Foo\""
3947       "  extension_range { start: 10 end: 20 }"
3948       "  reserved_range { start: 5 end: 15 }"
3949       "}",
3950 
3951       "foo.proto: Foo: NUMBER: Extension range 10 to 19"
3952       " overlaps with reserved range 5 to 14.\n");
3953 }
3954 
TEST_F(ValidationErrorTest,ReservedExtensionRangeAdjacent)3955 TEST_F(ValidationErrorTest, ReservedExtensionRangeAdjacent) {
3956   BuildFile(
3957       "name: \"foo.proto\" "
3958       "message_type {"
3959       "  name: \"Foo\""
3960       "  extension_range { start: 10 end: 20 }"
3961       "  reserved_range { start: 5 end: 10 }"
3962       "}");
3963 }
3964 
TEST_F(ValidationErrorTest,ReservedRangeOverlap)3965 TEST_F(ValidationErrorTest, ReservedRangeOverlap) {
3966   BuildFileWithErrors(
3967       "name: \"foo.proto\" "
3968       "message_type {"
3969       "  name: \"Foo\""
3970       "  reserved_range { start: 10 end: 20 }"
3971       "  reserved_range { start: 5 end: 15 }"
3972       "}",
3973 
3974       "foo.proto: Foo: NUMBER: Reserved range 5 to 14"
3975       " overlaps with already-defined range 10 to 19.\n");
3976 }
3977 
TEST_F(ValidationErrorTest,ReservedNameError)3978 TEST_F(ValidationErrorTest, ReservedNameError) {
3979   BuildFileWithErrors(
3980       "name: \"foo.proto\" "
3981       "message_type {"
3982       "  name: \"Foo\""
3983       "  field { name: \"foo\" number: 15 label:LABEL_OPTIONAL type:TYPE_INT32 "
3984       "}"
3985       "  field { name: \"bar\" number: 16 label:LABEL_OPTIONAL type:TYPE_INT32 "
3986       "}"
3987       "  field { name: \"baz\" number: 17 label:LABEL_OPTIONAL type:TYPE_INT32 "
3988       "}"
3989       "  reserved_name: \"foo\""
3990       "  reserved_name: \"bar\""
3991       "}",
3992 
3993       "foo.proto: Foo.foo: NAME: Field name \"foo\" is reserved.\n"
3994       "foo.proto: Foo.bar: NAME: Field name \"bar\" is reserved.\n");
3995 }
3996 
TEST_F(ValidationErrorTest,ReservedNameRedundant)3997 TEST_F(ValidationErrorTest, ReservedNameRedundant) {
3998   BuildFileWithErrors(
3999       "name: \"foo.proto\" "
4000       "message_type {"
4001       "  name: \"Foo\""
4002       "  reserved_name: \"foo\""
4003       "  reserved_name: \"foo\""
4004       "}",
4005 
4006       "foo.proto: foo: NAME: Field name \"foo\" is reserved multiple times.\n");
4007 }
4008 
TEST_F(ValidationErrorTest,ReservedFieldsDebugString)4009 TEST_F(ValidationErrorTest, ReservedFieldsDebugString) {
4010   const FileDescriptor* file = BuildFile(
4011       "name: \"foo.proto\" "
4012       "message_type {"
4013       "  name: \"Foo\""
4014       "  reserved_name: \"foo\""
4015       "  reserved_name: \"bar\""
4016       "  reserved_range { start: 5 end: 6 }"
4017       "  reserved_range { start: 10 end: 20 }"
4018       "}");
4019 
4020   ASSERT_EQ(
4021       "syntax = \"proto2\";\n\n"
4022       "message Foo {\n"
4023       "  reserved 5, 10 to 19;\n"
4024       "  reserved \"foo\", \"bar\";\n"
4025       "}\n\n",
4026       file->DebugString());
4027 }
4028 
TEST_F(ValidationErrorTest,EnumReservedFieldError)4029 TEST_F(ValidationErrorTest, EnumReservedFieldError) {
4030   BuildFileWithErrors(
4031       "name: \"foo.proto\" "
4032       "enum_type {"
4033       "  name: \"Foo\""
4034       "  value { name:\"BAR\" number:15 }"
4035       "  reserved_range { start: 10 end: 20 }"
4036       "}",
4037 
4038       "foo.proto: BAR: NUMBER: Enum value \"BAR\" uses reserved number 15.\n");
4039 }
4040 
TEST_F(ValidationErrorTest,EnumNegativeReservedFieldError)4041 TEST_F(ValidationErrorTest, EnumNegativeReservedFieldError) {
4042   BuildFileWithErrors(
4043       "name: \"foo.proto\" "
4044       "enum_type {"
4045       "  name: \"Foo\""
4046       "  value { name:\"BAR\" number:-15 }"
4047       "  reserved_range { start: -20 end: -10 }"
4048       "}",
4049 
4050       "foo.proto: BAR: NUMBER: Enum value \"BAR\" uses reserved number -15.\n");
4051 }
4052 
TEST_F(ValidationErrorTest,EnumReservedRangeOverlap)4053 TEST_F(ValidationErrorTest, EnumReservedRangeOverlap) {
4054   BuildFileWithErrors(
4055       "name: \"foo.proto\" "
4056       "enum_type {"
4057       "  name: \"Foo\""
4058       "  value { name:\"BAR\" number:0 }"
4059       "  reserved_range { start: 10 end: 20 }"
4060       "  reserved_range { start: 5 end: 15 }"
4061       "}",
4062 
4063       "foo.proto: Foo: NUMBER: Reserved range 5 to 15"
4064       " overlaps with already-defined range 10 to 20.\n");
4065 }
4066 
TEST_F(ValidationErrorTest,EnumReservedRangeOverlapByOne)4067 TEST_F(ValidationErrorTest, EnumReservedRangeOverlapByOne) {
4068   BuildFileWithErrors(
4069       "name: \"foo.proto\" "
4070       "enum_type {"
4071       "  name: \"Foo\""
4072       "  value { name:\"BAR\" number:0 }"
4073       "  reserved_range { start: 10 end: 20 }"
4074       "  reserved_range { start: 5 end: 10 }"
4075       "}",
4076 
4077       "foo.proto: Foo: NUMBER: Reserved range 5 to 10"
4078       " overlaps with already-defined range 10 to 20.\n");
4079 }
4080 
TEST_F(ValidationErrorTest,EnumNegativeReservedRangeOverlap)4081 TEST_F(ValidationErrorTest, EnumNegativeReservedRangeOverlap) {
4082   BuildFileWithErrors(
4083       "name: \"foo.proto\" "
4084       "enum_type {"
4085       "  name: \"Foo\""
4086       "  value { name:\"BAR\" number:0 }"
4087       "  reserved_range { start: -20 end: -10 }"
4088       "  reserved_range { start: -15 end: -5 }"
4089       "}",
4090 
4091       "foo.proto: Foo: NUMBER: Reserved range -15 to -5"
4092       " overlaps with already-defined range -20 to -10.\n");
4093 }
4094 
TEST_F(ValidationErrorTest,EnumMixedReservedRangeOverlap)4095 TEST_F(ValidationErrorTest, EnumMixedReservedRangeOverlap) {
4096   BuildFileWithErrors(
4097       "name: \"foo.proto\" "
4098       "enum_type {"
4099       "  name: \"Foo\""
4100       "  value { name:\"BAR\" number:20 }"
4101       "  reserved_range { start: -20 end: 10 }"
4102       "  reserved_range { start: -15 end: 5 }"
4103       "}",
4104 
4105       "foo.proto: Foo: NUMBER: Reserved range -15 to 5"
4106       " overlaps with already-defined range -20 to 10.\n");
4107 }
4108 
TEST_F(ValidationErrorTest,EnumMixedReservedRangeOverlap2)4109 TEST_F(ValidationErrorTest, EnumMixedReservedRangeOverlap2) {
4110   BuildFileWithErrors(
4111       "name: \"foo.proto\" "
4112       "enum_type {"
4113       "  name: \"Foo\""
4114       "  value { name:\"BAR\" number:20 }"
4115       "  reserved_range { start: -20 end: 10 }"
4116       "  reserved_range { start: 10 end: 10 }"
4117       "}",
4118 
4119       "foo.proto: Foo: NUMBER: Reserved range 10 to 10"
4120       " overlaps with already-defined range -20 to 10.\n");
4121 }
4122 
TEST_F(ValidationErrorTest,EnumReservedRangeStartGreaterThanEnd)4123 TEST_F(ValidationErrorTest, EnumReservedRangeStartGreaterThanEnd) {
4124   BuildFileWithErrors(
4125       "name: \"foo.proto\" "
4126       "enum_type {"
4127       "  name: \"Foo\""
4128       "  value { name:\"BAR\" number:20 }"
4129       "  reserved_range { start: 11 end: 10 }"
4130       "}",
4131 
4132       "foo.proto: Foo: NUMBER: Reserved range end number must be greater"
4133       " than start number.\n");
4134 }
4135 
TEST_F(ValidationErrorTest,EnumReservedNameError)4136 TEST_F(ValidationErrorTest, EnumReservedNameError) {
4137   BuildFileWithErrors(
4138       "name: \"foo.proto\" "
4139       "enum_type {"
4140       "  name: \"Foo\""
4141       "  value { name:\"FOO\" number:15 }"
4142       "  value { name:\"BAR\" number:15 }"
4143       "  reserved_name: \"FOO\""
4144       "  reserved_name: \"BAR\""
4145       "}",
4146 
4147       "foo.proto: FOO: NAME: Enum value \"FOO\" is reserved.\n"
4148       "foo.proto: BAR: NAME: Enum value \"BAR\" is reserved.\n");
4149 }
4150 
TEST_F(ValidationErrorTest,EnumReservedNameRedundant)4151 TEST_F(ValidationErrorTest, EnumReservedNameRedundant) {
4152   BuildFileWithErrors(
4153       "name: \"foo.proto\" "
4154       "enum_type {"
4155       "  name: \"Foo\""
4156       "  value { name:\"FOO\" number:15 }"
4157       "  reserved_name: \"foo\""
4158       "  reserved_name: \"foo\""
4159       "}",
4160 
4161       "foo.proto: foo: NAME: Enum value \"foo\" is reserved multiple times.\n");
4162 }
4163 
TEST_F(ValidationErrorTest,EnumReservedFieldsDebugString)4164 TEST_F(ValidationErrorTest, EnumReservedFieldsDebugString) {
4165   const FileDescriptor* file = BuildFile(
4166       "name: \"foo.proto\" "
4167       "enum_type {"
4168       "  name: \"Foo\""
4169       "  value { name:\"FOO\" number:3 }"
4170       "  reserved_name: \"foo\""
4171       "  reserved_name: \"bar\""
4172       "  reserved_range { start: -6 end: -6 }"
4173       "  reserved_range { start: -5 end: -4 }"
4174       "  reserved_range { start: -1 end: 1 }"
4175       "  reserved_range { start: 5 end: 5 }"
4176       "  reserved_range { start: 10 end: 19 }"
4177       "}");
4178 
4179   ASSERT_EQ(
4180       "syntax = \"proto2\";\n\n"
4181       "enum Foo {\n"
4182       "  FOO = 3;\n"
4183       "  reserved -6, -5 to -4, -1 to 1, 5, 10 to 19;\n"
4184       "  reserved \"foo\", \"bar\";\n"
4185       "}\n\n",
4186       file->DebugString());
4187 }
4188 
TEST_F(ValidationErrorTest,InvalidDefaults)4189 TEST_F(ValidationErrorTest, InvalidDefaults) {
4190   BuildFileWithErrors(
4191       "name: \"foo.proto\" "
4192       "message_type {"
4193       "  name: \"Foo\""
4194 
4195       // Invalid number.
4196       "  field { name: \"foo\" number: 1 label: LABEL_OPTIONAL type: TYPE_INT32"
4197       "          default_value: \"abc\" }"
4198 
4199       // Empty default value.
4200       "  field { name: \"bar\" number: 2 label: LABEL_OPTIONAL type: TYPE_INT32"
4201       "          default_value: \"\" }"
4202 
4203       // Invalid boolean.
4204       "  field { name: \"baz\" number: 3 label: LABEL_OPTIONAL type: TYPE_BOOL"
4205       "          default_value: \"abc\" }"
4206 
4207       // Messages can't have defaults.
4208       "  field { name: \"qux\" number: 4 label: LABEL_OPTIONAL type: "
4209       "TYPE_MESSAGE"
4210       "          default_value: \"abc\" type_name: \"Foo\" }"
4211 
4212       // Same thing, but we don't know that this field has message type until
4213       // we look up the type name.
4214       "  field { name: \"quux\" number: 5 label: LABEL_OPTIONAL"
4215       "          default_value: \"abc\" type_name: \"Foo\" }"
4216 
4217       // Repeateds can't have defaults.
4218       "  field { name: \"corge\" number: 6 label: LABEL_REPEATED type: "
4219       "TYPE_INT32"
4220       "          default_value: \"1\" }"
4221       "}",
4222 
4223       "foo.proto: Foo.foo: DEFAULT_VALUE: Couldn't parse default value "
4224       "\"abc\".\n"
4225       "foo.proto: Foo.bar: DEFAULT_VALUE: Couldn't parse default value \"\".\n"
4226       "foo.proto: Foo.baz: DEFAULT_VALUE: Boolean default must be true or "
4227       "false.\n"
4228       "foo.proto: Foo.qux: DEFAULT_VALUE: Messages can't have default values.\n"
4229       "foo.proto: Foo.corge: DEFAULT_VALUE: Repeated fields can't have default "
4230       "values.\n"
4231       // This ends up being reported later because the error is detected at
4232       // cross-linking time.
4233       "foo.proto: Foo.quux: DEFAULT_VALUE: Messages can't have default "
4234       "values.\n");
4235 }
4236 
TEST_F(ValidationErrorTest,NegativeFieldNumber)4237 TEST_F(ValidationErrorTest, NegativeFieldNumber) {
4238   BuildFileWithErrors(
4239       "name: \"foo.proto\" "
4240       "message_type {"
4241       "  name: \"Foo\""
4242       "  field { name: \"foo\" number: -1 label:LABEL_OPTIONAL type:TYPE_INT32 "
4243       "}"
4244       "}",
4245 
4246       "foo.proto: Foo.foo: NUMBER: Field numbers must be positive integers.\n");
4247 }
4248 
TEST_F(ValidationErrorTest,HugeFieldNumber)4249 TEST_F(ValidationErrorTest, HugeFieldNumber) {
4250   BuildFileWithErrors(
4251       "name: \"foo.proto\" "
4252       "message_type {"
4253       "  name: \"Foo\""
4254       "  field { name: \"foo\" number: 0x70000000 "
4255       "          label:LABEL_OPTIONAL type:TYPE_INT32 }"
4256       "}",
4257 
4258       "foo.proto: Foo.foo: NUMBER: Field numbers cannot be greater than "
4259       "536870911.\n");
4260 }
4261 
TEST_F(ValidationErrorTest,ReservedFieldNumber)4262 TEST_F(ValidationErrorTest, ReservedFieldNumber) {
4263   BuildFileWithErrors(
4264       "name: \"foo.proto\" "
4265       "message_type {"
4266       "  name: \"Foo\""
4267       "  field {name:\"foo\" number: 18999 label:LABEL_OPTIONAL "
4268       "type:TYPE_INT32 }"
4269       "  field {name:\"bar\" number: 19000 label:LABEL_OPTIONAL "
4270       "type:TYPE_INT32 }"
4271       "  field {name:\"baz\" number: 19999 label:LABEL_OPTIONAL "
4272       "type:TYPE_INT32 }"
4273       "  field {name:\"qux\" number: 20000 label:LABEL_OPTIONAL "
4274       "type:TYPE_INT32 }"
4275       "}",
4276 
4277       "foo.proto: Foo.bar: NUMBER: Field numbers 19000 through 19999 are "
4278       "reserved for the protocol buffer library implementation.\n"
4279       "foo.proto: Foo.baz: NUMBER: Field numbers 19000 through 19999 are "
4280       "reserved for the protocol buffer library implementation.\n");
4281 }
4282 
TEST_F(ValidationErrorTest,ExtensionMissingExtendee)4283 TEST_F(ValidationErrorTest, ExtensionMissingExtendee) {
4284   BuildFileWithErrors(
4285       "name: \"foo.proto\" "
4286       "message_type {"
4287       "  name: \"Foo\""
4288       "  extension { name: \"foo\" number: 1 label: LABEL_OPTIONAL"
4289       "              type_name: \"Foo\" }"
4290       "}",
4291 
4292       "foo.proto: Foo.foo: EXTENDEE: FieldDescriptorProto.extendee not set for "
4293       "extension field.\n");
4294 }
4295 
TEST_F(ValidationErrorTest,NonExtensionWithExtendee)4296 TEST_F(ValidationErrorTest, NonExtensionWithExtendee) {
4297   BuildFileWithErrors(
4298       "name: \"foo.proto\" "
4299       "message_type {"
4300       "  name: \"Bar\""
4301       "  extension_range { start: 1 end: 2 }"
4302       "}"
4303       "message_type {"
4304       "  name: \"Foo\""
4305       "  field { name: \"foo\" number: 1 label: LABEL_OPTIONAL"
4306       "          type_name: \"Foo\" extendee: \"Bar\" }"
4307       "}",
4308 
4309       "foo.proto: Foo.foo: EXTENDEE: FieldDescriptorProto.extendee set for "
4310       "non-extension field.\n");
4311 }
4312 
TEST_F(ValidationErrorTest,FieldOneofIndexTooLarge)4313 TEST_F(ValidationErrorTest, FieldOneofIndexTooLarge) {
4314   BuildFileWithErrors(
4315       "name: \"foo.proto\" "
4316       "message_type {"
4317       "  name: \"Foo\""
4318       "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32 "
4319       "          oneof_index: 1 }"
4320       "  field { name:\"dummy\" number:2 label:LABEL_OPTIONAL type:TYPE_INT32 "
4321       "          oneof_index: 0 }"
4322       "  oneof_decl { name:\"bar\" }"
4323       "}",
4324 
4325       "foo.proto: Foo.foo: TYPE: FieldDescriptorProto.oneof_index 1 is out of "
4326       "range for type \"Foo\".\n");
4327 }
4328 
TEST_F(ValidationErrorTest,FieldOneofIndexNegative)4329 TEST_F(ValidationErrorTest, FieldOneofIndexNegative) {
4330   BuildFileWithErrors(
4331       "name: \"foo.proto\" "
4332       "message_type {"
4333       "  name: \"Foo\""
4334       "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32 "
4335       "          oneof_index: -1 }"
4336       "  field { name:\"dummy\" number:2 label:LABEL_OPTIONAL type:TYPE_INT32 "
4337       "          oneof_index: 0 }"
4338       "  oneof_decl { name:\"bar\" }"
4339       "}",
4340 
4341       "foo.proto: Foo.foo: TYPE: FieldDescriptorProto.oneof_index -1 is out "
4342       "of "
4343       "range for type \"Foo\".\n");
4344 }
4345 
TEST_F(ValidationErrorTest,OneofFieldsConsecutiveDefinition)4346 TEST_F(ValidationErrorTest, OneofFieldsConsecutiveDefinition) {
4347   // Fields belonging to the same oneof must be defined consecutively.
4348   BuildFileWithErrors(
4349       "name: \"foo.proto\" "
4350       "message_type {"
4351       "  name: \"Foo\""
4352       "  field { name:\"foo1\" number: 1 label:LABEL_OPTIONAL type:TYPE_INT32 "
4353       "          oneof_index: 0 }"
4354       "  field { name:\"bar\" number: 2 label:LABEL_OPTIONAL type:TYPE_INT32 }"
4355       "  field { name:\"foo2\" number: 3 label:LABEL_OPTIONAL type:TYPE_INT32 "
4356       "          oneof_index: 0 }"
4357       "  oneof_decl { name:\"foos\" }"
4358       "}",
4359 
4360       "foo.proto: Foo.bar: TYPE: Fields in the same oneof must be defined "
4361       "consecutively. \"bar\" cannot be defined before the completion of the "
4362       "\"foos\" oneof definition.\n");
4363 
4364   // Prevent interleaved fields, which belong to different oneofs.
4365   BuildFileWithErrors(
4366       "name: \"foo2.proto\" "
4367       "message_type {"
4368       "  name: \"Foo2\""
4369       "  field { name:\"foo1\" number: 1 label:LABEL_OPTIONAL type:TYPE_INT32 "
4370       "          oneof_index: 0 }"
4371       "  field { name:\"bar1\" number: 2 label:LABEL_OPTIONAL type:TYPE_INT32 "
4372       "          oneof_index: 1 }"
4373       "  field { name:\"foo2\" number: 3 label:LABEL_OPTIONAL type:TYPE_INT32 "
4374       "          oneof_index: 0 }"
4375       "  field { name:\"bar2\" number: 4 label:LABEL_OPTIONAL type:TYPE_INT32 "
4376       "          oneof_index: 1 }"
4377       "  oneof_decl { name:\"foos\" }"
4378       "  oneof_decl { name:\"bars\" }"
4379       "}",
4380       "foo2.proto: Foo2.bar1: TYPE: Fields in the same oneof must be defined "
4381       "consecutively. \"bar1\" cannot be defined before the completion of the "
4382       "\"foos\" oneof definition.\n"
4383       "foo2.proto: Foo2.foo2: TYPE: Fields in the same oneof must be defined "
4384       "consecutively. \"foo2\" cannot be defined before the completion of the "
4385       "\"bars\" oneof definition.\n");
4386 
4387   // Another case for normal fields and different oneof fields interleave.
4388   BuildFileWithErrors(
4389       "name: \"foo3.proto\" "
4390       "message_type {"
4391       "  name: \"Foo3\""
4392       "  field { name:\"foo1\" number: 1 label:LABEL_OPTIONAL type:TYPE_INT32 "
4393       "          oneof_index: 0 }"
4394       "  field { name:\"bar1\" number: 2 label:LABEL_OPTIONAL type:TYPE_INT32 "
4395       "          oneof_index: 1 }"
4396       "  field { name:\"baz\" number: 3 label:LABEL_OPTIONAL type:TYPE_INT32 }"
4397       "  field { name:\"foo2\" number: 4 label:LABEL_OPTIONAL type:TYPE_INT32 "
4398       "          oneof_index: 0 }"
4399       "  oneof_decl { name:\"foos\" }"
4400       "  oneof_decl { name:\"bars\" }"
4401       "}",
4402       "foo3.proto: Foo3.baz: TYPE: Fields in the same oneof must be defined "
4403       "consecutively. \"baz\" cannot be defined before the completion of the "
4404       "\"foos\" oneof definition.\n");
4405 }
4406 
TEST_F(ValidationErrorTest,FieldNumberConflict)4407 TEST_F(ValidationErrorTest, FieldNumberConflict) {
4408   BuildFileWithErrors(
4409       "name: \"foo.proto\" "
4410       "message_type {"
4411       "  name: \"Foo\""
4412       "  field { name: \"foo\" number: 1 label:LABEL_OPTIONAL type:TYPE_INT32 }"
4413       "  field { name: \"bar\" number: 1 label:LABEL_OPTIONAL type:TYPE_INT32 }"
4414       "}",
4415 
4416       "foo.proto: Foo.bar: NUMBER: Field number 1 has already been used in "
4417       "\"Foo\" by field \"foo\".\n");
4418 }
4419 
TEST_F(ValidationErrorTest,BadMessageSetExtensionType)4420 TEST_F(ValidationErrorTest, BadMessageSetExtensionType) {
4421   BuildFileWithErrors(
4422       "name: \"foo.proto\" "
4423       "message_type {"
4424       "  name: \"MessageSet\""
4425       "  options { message_set_wire_format: true }"
4426       "  extension_range { start: 4 end: 5 }"
4427       "}"
4428       "message_type {"
4429       "  name: \"Foo\""
4430       "  extension { name:\"foo\" number:4 label:LABEL_OPTIONAL type:TYPE_INT32"
4431       "              extendee: \"MessageSet\" }"
4432       "}",
4433 
4434       "foo.proto: Foo.foo: TYPE: Extensions of MessageSets must be optional "
4435       "messages.\n");
4436 }
4437 
TEST_F(ValidationErrorTest,BadMessageSetExtensionLabel)4438 TEST_F(ValidationErrorTest, BadMessageSetExtensionLabel) {
4439   BuildFileWithErrors(
4440       "name: \"foo.proto\" "
4441       "message_type {"
4442       "  name: \"MessageSet\""
4443       "  options { message_set_wire_format: true }"
4444       "  extension_range { start: 4 end: 5 }"
4445       "}"
4446       "message_type {"
4447       "  name: \"Foo\""
4448       "  extension { name:\"foo\" number:4 label:LABEL_REPEATED "
4449       "type:TYPE_MESSAGE"
4450       "              type_name: \"Foo\" extendee: \"MessageSet\" }"
4451       "}",
4452 
4453       "foo.proto: Foo.foo: TYPE: Extensions of MessageSets must be optional "
4454       "messages.\n");
4455 }
4456 
TEST_F(ValidationErrorTest,FieldInMessageSet)4457 TEST_F(ValidationErrorTest, FieldInMessageSet) {
4458   BuildFileWithErrors(
4459       "name: \"foo.proto\" "
4460       "message_type {"
4461       "  name: \"Foo\""
4462       "  options { message_set_wire_format: true }"
4463       "  field { name: \"foo\" number: 1 label:LABEL_OPTIONAL type:TYPE_INT32 }"
4464       "}",
4465 
4466       "foo.proto: Foo.foo: NAME: MessageSets cannot have fields, only "
4467       "extensions.\n");
4468 }
4469 
TEST_F(ValidationErrorTest,NegativeExtensionRangeNumber)4470 TEST_F(ValidationErrorTest, NegativeExtensionRangeNumber) {
4471   BuildFileWithErrors(
4472       "name: \"foo.proto\" "
4473       "message_type {"
4474       "  name: \"Foo\""
4475       "  extension_range { start: -10 end: -1 }"
4476       "}",
4477 
4478       "foo.proto: Foo: NUMBER: Extension numbers must be positive integers.\n");
4479 }
4480 
TEST_F(ValidationErrorTest,HugeExtensionRangeNumber)4481 TEST_F(ValidationErrorTest, HugeExtensionRangeNumber) {
4482   BuildFileWithErrors(
4483       "name: \"foo.proto\" "
4484       "message_type {"
4485       "  name: \"Foo\""
4486       "  extension_range { start: 1 end: 0x70000000 }"
4487       "}",
4488 
4489       "foo.proto: Foo: NUMBER: Extension numbers cannot be greater than "
4490       "536870911.\n");
4491 }
4492 
TEST_F(ValidationErrorTest,ExtensionRangeEndBeforeStart)4493 TEST_F(ValidationErrorTest, ExtensionRangeEndBeforeStart) {
4494   BuildFileWithErrors(
4495       "name: \"foo.proto\" "
4496       "message_type {"
4497       "  name: \"Foo\""
4498       "  extension_range { start: 10 end: 10 }"
4499       "  extension_range { start: 10 end: 5 }"
4500       "}",
4501 
4502       "foo.proto: Foo: NUMBER: Extension range end number must be greater than "
4503       "start number.\n"
4504       "foo.proto: Foo: NUMBER: Extension range end number must be greater than "
4505       "start number.\n");
4506 }
4507 
TEST_F(ValidationErrorTest,EmptyEnum)4508 TEST_F(ValidationErrorTest, EmptyEnum) {
4509   BuildFileWithErrors(
4510       "name: \"foo.proto\" "
4511       "enum_type { name: \"Foo\" }"
4512       // Also use the empty enum in a message to make sure there are no crashes
4513       // during validation (possible if the code attempts to derive a default
4514       // value for the field).
4515       "message_type {"
4516       "  name: \"Bar\""
4517       "  field { name: \"foo\" number: 1 label:LABEL_OPTIONAL "
4518       "type_name:\"Foo\" }"
4519       "  field { name: \"bar\" number: 2 label:LABEL_OPTIONAL "
4520       "type_name:\"Foo\" "
4521       "          default_value: \"NO_SUCH_VALUE\" }"
4522       "}",
4523 
4524       "foo.proto: Foo: NAME: Enums must contain at least one value.\n"
4525       "foo.proto: Bar.bar: DEFAULT_VALUE: Enum type \"Foo\" has no value named "
4526       "\"NO_SUCH_VALUE\".\n");
4527 }
4528 
TEST_F(ValidationErrorTest,UndefinedExtendee)4529 TEST_F(ValidationErrorTest, UndefinedExtendee) {
4530   BuildFileWithErrors(
4531       "name: \"foo.proto\" "
4532       "message_type {"
4533       "  name: \"Foo\""
4534       "  extension { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32"
4535       "              extendee: \"Bar\" }"
4536       "}",
4537 
4538       "foo.proto: Foo.foo: EXTENDEE: \"Bar\" is not defined.\n");
4539 }
4540 
TEST_F(ValidationErrorTest,NonMessageExtendee)4541 TEST_F(ValidationErrorTest, NonMessageExtendee) {
4542   BuildFileWithErrors(
4543       "name: \"foo.proto\" "
4544       "enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } }"
4545       "message_type {"
4546       "  name: \"Foo\""
4547       "  extension { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32"
4548       "              extendee: \"Bar\" }"
4549       "}",
4550 
4551       "foo.proto: Foo.foo: EXTENDEE: \"Bar\" is not a message type.\n");
4552 }
4553 
TEST_F(ValidationErrorTest,NotAnExtensionNumber)4554 TEST_F(ValidationErrorTest, NotAnExtensionNumber) {
4555   BuildFileWithErrors(
4556       "name: \"foo.proto\" "
4557       "message_type {"
4558       "  name: \"Bar\""
4559       "}"
4560       "message_type {"
4561       "  name: \"Foo\""
4562       "  extension { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32"
4563       "              extendee: \"Bar\" }"
4564       "}",
4565 
4566       "foo.proto: Foo.foo: NUMBER: \"Bar\" does not declare 1 as an extension "
4567       "number.\n");
4568 }
4569 
TEST_F(ValidationErrorTest,RequiredExtension)4570 TEST_F(ValidationErrorTest, RequiredExtension) {
4571   BuildFileWithErrors(
4572       "name: \"foo.proto\" "
4573       "message_type {"
4574       "  name: \"Bar\""
4575       "  extension_range { start: 1000 end: 10000 }"
4576       "}"
4577       "message_type {"
4578       "  name: \"Foo\""
4579       "  extension {"
4580       "    name:\"foo\""
4581       "    number:1000"
4582       "    label:LABEL_REQUIRED"
4583       "    type:TYPE_INT32"
4584       "    extendee: \"Bar\""
4585       "  }"
4586       "}",
4587 
4588       "foo.proto: Foo.foo: TYPE: The extension Foo.foo cannot be required.\n");
4589 }
4590 
TEST_F(ValidationErrorTest,UndefinedFieldType)4591 TEST_F(ValidationErrorTest, UndefinedFieldType) {
4592   BuildFileWithErrors(
4593       "name: \"foo.proto\" "
4594       "message_type {"
4595       "  name: \"Foo\""
4596       "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }"
4597       "}",
4598 
4599       "foo.proto: Foo.foo: TYPE: \"Bar\" is not defined.\n");
4600 }
4601 
TEST_F(ValidationErrorTest,UndefinedFieldTypeWithDefault)4602 TEST_F(ValidationErrorTest, UndefinedFieldTypeWithDefault) {
4603   // See b/12533582. Previously this failed because the default value was not
4604   // accepted by the parser, which assumed an enum type, leading to an unclear
4605   // error message. We want this input to yield a validation error instead,
4606   // since the unknown type is the primary problem.
4607   BuildFileWithErrors(
4608       "name: \"foo.proto\" "
4609       "message_type {"
4610       "  name: \"Foo\""
4611       "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"int\" "
4612       "          default_value:\"1\" }"
4613       "}",
4614 
4615       "foo.proto: Foo.foo: TYPE: \"int\" is not defined.\n");
4616 }
4617 
TEST_F(ValidationErrorTest,UndefinedNestedFieldType)4618 TEST_F(ValidationErrorTest, UndefinedNestedFieldType) {
4619   BuildFileWithErrors(
4620       "name: \"foo.proto\" "
4621       "message_type {"
4622       "  name: \"Foo\""
4623       "  nested_type { name:\"Baz\" }"
4624       "  field { name:\"foo\" number:1"
4625       "          label:LABEL_OPTIONAL"
4626       "          type_name:\"Foo.Baz.Bar\" }"
4627       "}",
4628 
4629       "foo.proto: Foo.foo: TYPE: \"Foo.Baz.Bar\" is not defined.\n");
4630 }
4631 
TEST_F(ValidationErrorTest,FieldTypeDefinedInUndeclaredDependency)4632 TEST_F(ValidationErrorTest, FieldTypeDefinedInUndeclaredDependency) {
4633   BuildFile(
4634       "name: \"bar.proto\" "
4635       "message_type { name: \"Bar\" } ");
4636 
4637   BuildFileWithErrors(
4638       "name: \"foo.proto\" "
4639       "message_type {"
4640       "  name: \"Foo\""
4641       "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }"
4642       "}",
4643       "foo.proto: Foo.foo: TYPE: \"Bar\" seems to be defined in \"bar.proto\", "
4644       "which is not imported by \"foo.proto\".  To use it here, please add the "
4645       "necessary import.\n");
4646 }
4647 
TEST_F(ValidationErrorTest,FieldTypeDefinedInIndirectDependency)4648 TEST_F(ValidationErrorTest, FieldTypeDefinedInIndirectDependency) {
4649   // Test for hidden dependencies.
4650   //
4651   // // bar.proto
4652   // message Bar{}
4653   //
4654   // // forward.proto
4655   // import "bar.proto"
4656   //
4657   // // foo.proto
4658   // import "forward.proto"
4659   // message Foo {
4660   //   optional Bar foo = 1;  // Error, needs to import bar.proto explicitly.
4661   // }
4662   //
4663   BuildFile(
4664       "name: \"bar.proto\" "
4665       "message_type { name: \"Bar\" }");
4666 
4667   BuildFile(
4668       "name: \"forward.proto\""
4669       "dependency: \"bar.proto\"");
4670 
4671   BuildFileWithErrors(
4672       "name: \"foo.proto\" "
4673       "dependency: \"forward.proto\" "
4674       "message_type {"
4675       "  name: \"Foo\""
4676       "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }"
4677       "}",
4678       "foo.proto: Foo.foo: TYPE: \"Bar\" seems to be defined in \"bar.proto\", "
4679       "which is not imported by \"foo.proto\".  To use it here, please add the "
4680       "necessary import.\n");
4681 }
4682 
TEST_F(ValidationErrorTest,FieldTypeDefinedInPublicDependency)4683 TEST_F(ValidationErrorTest, FieldTypeDefinedInPublicDependency) {
4684   // Test for public dependencies.
4685   //
4686   // // bar.proto
4687   // message Bar{}
4688   //
4689   // // forward.proto
4690   // import public "bar.proto"
4691   //
4692   // // foo.proto
4693   // import "forward.proto"
4694   // message Foo {
4695   //   optional Bar foo = 1;  // Correct. "bar.proto" is public imported into
4696   //                          // forward.proto, so when "foo.proto" imports
4697   //                          // "forward.proto", it imports "bar.proto" too.
4698   // }
4699   //
4700   BuildFile(
4701       "name: \"bar.proto\" "
4702       "message_type { name: \"Bar\" }");
4703 
4704   BuildFile(
4705       "name: \"forward.proto\""
4706       "dependency: \"bar.proto\" "
4707       "public_dependency: 0");
4708 
4709   BuildFile(
4710       "name: \"foo.proto\" "
4711       "dependency: \"forward.proto\" "
4712       "message_type {"
4713       "  name: \"Foo\""
4714       "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }"
4715       "}");
4716 }
4717 
TEST_F(ValidationErrorTest,FieldTypeDefinedInTransitivePublicDependency)4718 TEST_F(ValidationErrorTest, FieldTypeDefinedInTransitivePublicDependency) {
4719   // Test for public dependencies.
4720   //
4721   // // bar.proto
4722   // message Bar{}
4723   //
4724   // // forward.proto
4725   // import public "bar.proto"
4726   //
4727   // // forward2.proto
4728   // import public "forward.proto"
4729   //
4730   // // foo.proto
4731   // import "forward2.proto"
4732   // message Foo {
4733   //   optional Bar foo = 1;  // Correct, public imports are transitive.
4734   // }
4735   //
4736   BuildFile(
4737       "name: \"bar.proto\" "
4738       "message_type { name: \"Bar\" }");
4739 
4740   BuildFile(
4741       "name: \"forward.proto\""
4742       "dependency: \"bar.proto\" "
4743       "public_dependency: 0");
4744 
4745   BuildFile(
4746       "name: \"forward2.proto\""
4747       "dependency: \"forward.proto\" "
4748       "public_dependency: 0");
4749 
4750   BuildFile(
4751       "name: \"foo.proto\" "
4752       "dependency: \"forward2.proto\" "
4753       "message_type {"
4754       "  name: \"Foo\""
4755       "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }"
4756       "}");
4757 }
4758 
TEST_F(ValidationErrorTest,FieldTypeDefinedInPrivateDependencyOfPublicDependency)4759 TEST_F(ValidationErrorTest,
4760        FieldTypeDefinedInPrivateDependencyOfPublicDependency) {
4761   // Test for public dependencies.
4762   //
4763   // // bar.proto
4764   // message Bar{}
4765   //
4766   // // forward.proto
4767   // import "bar.proto"
4768   //
4769   // // forward2.proto
4770   // import public "forward.proto"
4771   //
4772   // // foo.proto
4773   // import "forward2.proto"
4774   // message Foo {
4775   //   optional Bar foo = 1;  // Error, the "bar.proto" is not public imported
4776   //                          // into "forward.proto", so will not be imported
4777   //                          // into either "forward2.proto" or "foo.proto".
4778   // }
4779   //
4780   BuildFile(
4781       "name: \"bar.proto\" "
4782       "message_type { name: \"Bar\" }");
4783 
4784   BuildFile(
4785       "name: \"forward.proto\""
4786       "dependency: \"bar.proto\"");
4787 
4788   BuildFile(
4789       "name: \"forward2.proto\""
4790       "dependency: \"forward.proto\" "
4791       "public_dependency: 0");
4792 
4793   BuildFileWithErrors(
4794       "name: \"foo.proto\" "
4795       "dependency: \"forward2.proto\" "
4796       "message_type {"
4797       "  name: \"Foo\""
4798       "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }"
4799       "}",
4800       "foo.proto: Foo.foo: TYPE: \"Bar\" seems to be defined in \"bar.proto\", "
4801       "which is not imported by \"foo.proto\".  To use it here, please add the "
4802       "necessary import.\n");
4803 }
4804 
4805 
TEST_F(ValidationErrorTest,SearchMostLocalFirst)4806 TEST_F(ValidationErrorTest, SearchMostLocalFirst) {
4807   // The following should produce an error that Bar.Baz is resolved but
4808   // not defined:
4809   //   message Bar { message Baz {} }
4810   //   message Foo {
4811   //     message Bar {
4812   //       // Placing "message Baz{}" here, or removing Foo.Bar altogether,
4813   //       // would fix the error.
4814   //     }
4815   //     optional Bar.Baz baz = 1;
4816   //   }
4817   // An one point the lookup code incorrectly did not produce an error in this
4818   // case, because when looking for Bar.Baz, it would try "Foo.Bar.Baz" first,
4819   // fail, and ten try "Bar.Baz" and succeed, even though "Bar" should actually
4820   // refer to the inner Bar, not the outer one.
4821   BuildFileWithErrors(
4822       "name: \"foo.proto\" "
4823       "message_type {"
4824       "  name: \"Bar\""
4825       "  nested_type { name: \"Baz\" }"
4826       "}"
4827       "message_type {"
4828       "  name: \"Foo\""
4829       "  nested_type { name: \"Bar\" }"
4830       "  field { name:\"baz\" number:1 label:LABEL_OPTIONAL"
4831       "          type_name:\"Bar.Baz\" }"
4832       "}",
4833 
4834       "foo.proto: Foo.baz: TYPE: \"Bar.Baz\" is resolved to \"Foo.Bar.Baz\","
4835       " which is not defined. The innermost scope is searched first in name "
4836       "resolution. Consider using a leading '.'(i.e., \".Bar.Baz\") to start "
4837       "from the outermost scope.\n");
4838 }
4839 
TEST_F(ValidationErrorTest,SearchMostLocalFirst2)4840 TEST_F(ValidationErrorTest, SearchMostLocalFirst2) {
4841   // This test would find the most local "Bar" first, and does, but
4842   // proceeds to find the outer one because the inner one's not an
4843   // aggregate.
4844   BuildFile(
4845       "name: \"foo.proto\" "
4846       "message_type {"
4847       "  name: \"Bar\""
4848       "  nested_type { name: \"Baz\" }"
4849       "}"
4850       "message_type {"
4851       "  name: \"Foo\""
4852       "  field { name: \"Bar\" number:1 type:TYPE_BYTES } "
4853       "  field { name:\"baz\" number:2 label:LABEL_OPTIONAL"
4854       "          type_name:\"Bar.Baz\" }"
4855       "}");
4856 }
4857 
TEST_F(ValidationErrorTest,PackageOriginallyDeclaredInTransitiveDependent)4858 TEST_F(ValidationErrorTest, PackageOriginallyDeclaredInTransitiveDependent) {
4859   // Imagine we have the following:
4860   //
4861   // foo.proto:
4862   //   package foo.bar;
4863   // bar.proto:
4864   //   package foo.bar;
4865   //   import "foo.proto";
4866   //   message Bar {}
4867   // baz.proto:
4868   //   package foo;
4869   //   import "bar.proto"
4870   //   message Baz { optional bar.Bar qux = 1; }
4871   //
4872   // When validating baz.proto, we will look up "bar.Bar".  As part of this
4873   // lookup, we first lookup "bar" then try to find "Bar" within it.  "bar"
4874   // should resolve to "foo.bar".  Note, though, that "foo.bar" was originally
4875   // defined in foo.proto, which is not a direct dependency of baz.proto.  The
4876   // implementation of FindSymbol() normally only returns symbols in direct
4877   // dependencies, not indirect ones.  This test insures that this does not
4878   // prevent it from finding "foo.bar".
4879 
4880   BuildFile(
4881       "name: \"foo.proto\" "
4882       "package: \"foo.bar\" ");
4883   BuildFile(
4884       "name: \"bar.proto\" "
4885       "package: \"foo.bar\" "
4886       "dependency: \"foo.proto\" "
4887       "message_type { name: \"Bar\" }");
4888   BuildFile(
4889       "name: \"baz.proto\" "
4890       "package: \"foo\" "
4891       "dependency: \"bar.proto\" "
4892       "message_type { "
4893       "  name: \"Baz\" "
4894       "  field { name:\"qux\" number:1 label:LABEL_OPTIONAL "
4895       "          type_name:\"bar.Bar\" }"
4896       "}");
4897 }
4898 
TEST_F(ValidationErrorTest,FieldTypeNotAType)4899 TEST_F(ValidationErrorTest, FieldTypeNotAType) {
4900   BuildFileWithErrors(
4901       "name: \"foo.proto\" "
4902       "message_type {"
4903       "  name: \"Foo\""
4904       "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL "
4905       "          type_name:\".Foo.bar\" }"
4906       "  field { name:\"bar\" number:2 label:LABEL_OPTIONAL type:TYPE_INT32 }"
4907       "}",
4908 
4909       "foo.proto: Foo.foo: TYPE: \".Foo.bar\" is not a type.\n");
4910 }
4911 
TEST_F(ValidationErrorTest,RelativeFieldTypeNotAType)4912 TEST_F(ValidationErrorTest, RelativeFieldTypeNotAType) {
4913   BuildFileWithErrors(
4914       "name: \"foo.proto\" "
4915       "message_type {"
4916       "  nested_type {"
4917       "    name: \"Bar\""
4918       "    field { name:\"Baz\" number:2 label:LABEL_OPTIONAL type:TYPE_INT32 }"
4919       "  }"
4920       "  name: \"Foo\""
4921       "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL "
4922       "          type_name:\"Bar.Baz\" }"
4923       "}",
4924       "foo.proto: Foo.foo: TYPE: \"Bar.Baz\" is not a type.\n");
4925 }
4926 
TEST_F(ValidationErrorTest,FieldTypeMayBeItsName)4927 TEST_F(ValidationErrorTest, FieldTypeMayBeItsName) {
4928   BuildFile(
4929       "name: \"foo.proto\" "
4930       "message_type {"
4931       "  name: \"Bar\""
4932       "}"
4933       "message_type {"
4934       "  name: \"Foo\""
4935       "  field { name:\"Bar\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }"
4936       "}");
4937 }
4938 
TEST_F(ValidationErrorTest,EnumFieldTypeIsMessage)4939 TEST_F(ValidationErrorTest, EnumFieldTypeIsMessage) {
4940   BuildFileWithErrors(
4941       "name: \"foo.proto\" "
4942       "message_type { name: \"Bar\" } "
4943       "message_type {"
4944       "  name: \"Foo\""
4945       "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_ENUM"
4946       "          type_name:\"Bar\" }"
4947       "}",
4948 
4949       "foo.proto: Foo.foo: TYPE: \"Bar\" is not an enum type.\n");
4950 }
4951 
TEST_F(ValidationErrorTest,MessageFieldTypeIsEnum)4952 TEST_F(ValidationErrorTest, MessageFieldTypeIsEnum) {
4953   BuildFileWithErrors(
4954       "name: \"foo.proto\" "
4955       "enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } } "
4956       "message_type {"
4957       "  name: \"Foo\""
4958       "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_MESSAGE"
4959       "          type_name:\"Bar\" }"
4960       "}",
4961 
4962       "foo.proto: Foo.foo: TYPE: \"Bar\" is not a message type.\n");
4963 }
4964 
TEST_F(ValidationErrorTest,BadEnumDefaultValue)4965 TEST_F(ValidationErrorTest, BadEnumDefaultValue) {
4966   BuildFileWithErrors(
4967       "name: \"foo.proto\" "
4968       "enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } } "
4969       "message_type {"
4970       "  name: \"Foo\""
4971       "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\""
4972       "          default_value:\"NO_SUCH_VALUE\" }"
4973       "}",
4974 
4975       "foo.proto: Foo.foo: DEFAULT_VALUE: Enum type \"Bar\" has no value named "
4976       "\"NO_SUCH_VALUE\".\n");
4977 }
4978 
TEST_F(ValidationErrorTest,EnumDefaultValueIsInteger)4979 TEST_F(ValidationErrorTest, EnumDefaultValueIsInteger) {
4980   BuildFileWithErrors(
4981       "name: \"foo.proto\" "
4982       "enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } } "
4983       "message_type {"
4984       "  name: \"Foo\""
4985       "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\""
4986       "          default_value:\"0\" }"
4987       "}",
4988 
4989       "foo.proto: Foo.foo: DEFAULT_VALUE: Default value for an enum field must "
4990       "be an identifier.\n");
4991 }
4992 
TEST_F(ValidationErrorTest,PrimitiveWithTypeName)4993 TEST_F(ValidationErrorTest, PrimitiveWithTypeName) {
4994   BuildFileWithErrors(
4995       "name: \"foo.proto\" "
4996       "message_type {"
4997       "  name: \"Foo\""
4998       "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32"
4999       "          type_name:\"Foo\" }"
5000       "}",
5001 
5002       "foo.proto: Foo.foo: TYPE: Field with primitive type has type_name.\n");
5003 }
5004 
TEST_F(ValidationErrorTest,NonPrimitiveWithoutTypeName)5005 TEST_F(ValidationErrorTest, NonPrimitiveWithoutTypeName) {
5006   BuildFileWithErrors(
5007       "name: \"foo.proto\" "
5008       "message_type {"
5009       "  name: \"Foo\""
5010       "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_MESSAGE }"
5011       "}",
5012 
5013       "foo.proto: Foo.foo: TYPE: Field with message or enum type missing "
5014       "type_name.\n");
5015 }
5016 
TEST_F(ValidationErrorTest,OneofWithNoFields)5017 TEST_F(ValidationErrorTest, OneofWithNoFields) {
5018   BuildFileWithErrors(
5019       "name: \"foo.proto\" "
5020       "message_type {"
5021       "  name: \"Foo\""
5022       "  oneof_decl { name:\"bar\" }"
5023       "}",
5024 
5025       "foo.proto: Foo.bar: NAME: Oneof must have at least one field.\n");
5026 }
5027 
TEST_F(ValidationErrorTest,OneofLabelMismatch)5028 TEST_F(ValidationErrorTest, OneofLabelMismatch) {
5029   BuildFileWithErrors(
5030       "name: \"foo.proto\" "
5031       "message_type {"
5032       "  name: \"Foo\""
5033       "  field { name:\"foo\" number:1 label:LABEL_REPEATED type:TYPE_INT32 "
5034       "          oneof_index:0 }"
5035       "  oneof_decl { name:\"bar\" }"
5036       "}",
5037 
5038       "foo.proto: Foo.foo: NAME: Fields of oneofs must themselves have label "
5039       "LABEL_OPTIONAL.\n");
5040 }
5041 
TEST_F(ValidationErrorTest,InputTypeNotDefined)5042 TEST_F(ValidationErrorTest, InputTypeNotDefined) {
5043   BuildFileWithErrors(
5044       "name: \"foo.proto\" "
5045       "message_type { name: \"Foo\" } "
5046       "service {"
5047       "  name: \"TestService\""
5048       "  method { name: \"A\" input_type: \"Bar\" output_type: \"Foo\" }"
5049       "}",
5050 
5051       "foo.proto: TestService.A: INPUT_TYPE: \"Bar\" is not defined.\n"
5052   );
5053 }
5054 
TEST_F(ValidationErrorTest,InputTypeNotAMessage)5055 TEST_F(ValidationErrorTest, InputTypeNotAMessage) {
5056   BuildFileWithErrors(
5057       "name: \"foo.proto\" "
5058       "message_type { name: \"Foo\" } "
5059       "enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } } "
5060       "service {"
5061       "  name: \"TestService\""
5062       "  method { name: \"A\" input_type: \"Bar\" output_type: \"Foo\" }"
5063       "}",
5064 
5065       "foo.proto: TestService.A: INPUT_TYPE: \"Bar\" is not a message type.\n"
5066   );
5067 }
5068 
TEST_F(ValidationErrorTest,OutputTypeNotDefined)5069 TEST_F(ValidationErrorTest, OutputTypeNotDefined) {
5070   BuildFileWithErrors(
5071       "name: \"foo.proto\" "
5072       "message_type { name: \"Foo\" } "
5073       "service {"
5074       "  name: \"TestService\""
5075       "  method { name: \"A\" input_type: \"Foo\" output_type: \"Bar\" }"
5076       "}",
5077 
5078       "foo.proto: TestService.A: OUTPUT_TYPE: \"Bar\" is not defined.\n"
5079   );
5080 }
5081 
TEST_F(ValidationErrorTest,OutputTypeNotAMessage)5082 TEST_F(ValidationErrorTest, OutputTypeNotAMessage) {
5083   BuildFileWithErrors(
5084       "name: \"foo.proto\" "
5085       "message_type { name: \"Foo\" } "
5086       "enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } } "
5087       "service {"
5088       "  name: \"TestService\""
5089       "  method { name: \"A\" input_type: \"Foo\" output_type: \"Bar\" }"
5090       "}",
5091 
5092       "foo.proto: TestService.A: OUTPUT_TYPE: \"Bar\" is not a message type.\n"
5093   );
5094 }
5095 
5096 
TEST_F(ValidationErrorTest,IllegalPackedField)5097 TEST_F(ValidationErrorTest, IllegalPackedField) {
5098   BuildFileWithErrors(
5099       "name: \"foo.proto\" "
5100       "message_type {\n"
5101       "  name: \"Foo\""
5102       "  field { name:\"packed_string\" number:1 label:LABEL_REPEATED "
5103       "          type:TYPE_STRING "
5104       "          options { uninterpreted_option {"
5105       "            name { name_part: \"packed\" is_extension: false }"
5106       "            identifier_value: \"true\" }}}\n"
5107       "  field { name:\"packed_message\" number:3 label:LABEL_REPEATED "
5108       "          type_name: \"Foo\""
5109       "          options { uninterpreted_option {"
5110       "            name { name_part: \"packed\" is_extension: false }"
5111       "            identifier_value: \"true\" }}}\n"
5112       "  field { name:\"optional_int32\" number: 4 label: LABEL_OPTIONAL "
5113       "          type:TYPE_INT32 "
5114       "          options { uninterpreted_option {"
5115       "            name { name_part: \"packed\" is_extension: false }"
5116       "            identifier_value: \"true\" }}}\n"
5117       "}",
5118 
5119       "foo.proto: Foo.packed_string: TYPE: [packed = true] can only be "
5120       "specified for repeated primitive fields.\n"
5121       "foo.proto: Foo.packed_message: TYPE: [packed = true] can only be "
5122       "specified for repeated primitive fields.\n"
5123       "foo.proto: Foo.optional_int32: TYPE: [packed = true] can only be "
5124       "specified for repeated primitive fields.\n");
5125 }
5126 
TEST_F(ValidationErrorTest,OptionWrongType)5127 TEST_F(ValidationErrorTest, OptionWrongType) {
5128   BuildFileWithErrors(
5129       "name: \"foo.proto\" "
5130       "message_type { "
5131       "  name: \"TestMessage\" "
5132       "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_STRING "
5133       "          options { uninterpreted_option { name { name_part: \"ctype\" "
5134       "                                                  is_extension: false }"
5135       "                                           positive_int_value: 1 }"
5136       "          }"
5137       "  }"
5138       "}\n",
5139 
5140       "foo.proto: TestMessage.foo: OPTION_VALUE: Value must be identifier for "
5141       "enum-valued option \"google.protobuf.FieldOptions.ctype\".\n");
5142 }
5143 
TEST_F(ValidationErrorTest,OptionExtendsAtomicType)5144 TEST_F(ValidationErrorTest, OptionExtendsAtomicType) {
5145   BuildFileWithErrors(
5146       "name: \"foo.proto\" "
5147       "message_type { "
5148       "  name: \"TestMessage\" "
5149       "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_STRING "
5150       "          options { uninterpreted_option { name { name_part: \"ctype\" "
5151       "                                                  is_extension: false }"
5152       "                                           name { name_part: \"foo\" "
5153       "                                                  is_extension: true }"
5154       "                                           positive_int_value: 1 }"
5155       "          }"
5156       "  }"
5157       "}\n",
5158 
5159       "foo.proto: TestMessage.foo: OPTION_NAME: Option \"ctype\" is an "
5160       "atomic type, not a message.\n");
5161 }
5162 
TEST_F(ValidationErrorTest,DupOption)5163 TEST_F(ValidationErrorTest, DupOption) {
5164   BuildFileWithErrors(
5165       "name: \"foo.proto\" "
5166       "message_type { "
5167       "  name: \"TestMessage\" "
5168       "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_UINT32 "
5169       "          options { uninterpreted_option { name { name_part: \"ctype\" "
5170       "                                                  is_extension: false }"
5171       "                                           identifier_value: \"CORD\" }"
5172       "                    uninterpreted_option { name { name_part: \"ctype\" "
5173       "                                                  is_extension: false }"
5174       "                                           identifier_value: \"CORD\" }"
5175       "          }"
5176       "  }"
5177       "}\n",
5178 
5179       "foo.proto: TestMessage.foo: OPTION_NAME: Option \"ctype\" was "
5180       "already set.\n");
5181 }
5182 
TEST_F(ValidationErrorTest,InvalidOptionName)5183 TEST_F(ValidationErrorTest, InvalidOptionName) {
5184   BuildFileWithErrors(
5185       "name: \"foo.proto\" "
5186       "message_type { "
5187       "  name: \"TestMessage\" "
5188       "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_BOOL "
5189       "          options { uninterpreted_option { "
5190       "                      name { name_part: \"uninterpreted_option\" "
5191       "                             is_extension: false }"
5192       "                      positive_int_value: 1 "
5193       "                    }"
5194       "          }"
5195       "  }"
5196       "}\n",
5197 
5198       "foo.proto: TestMessage.foo: OPTION_NAME: Option must not use "
5199       "reserved name \"uninterpreted_option\".\n");
5200 }
5201 
TEST_F(ValidationErrorTest,RepeatedMessageOption)5202 TEST_F(ValidationErrorTest, RepeatedMessageOption) {
5203   BuildDescriptorMessagesInTestPool();
5204 
5205   BuildFileWithErrors(
5206       "name: \"foo.proto\" "
5207       "dependency: \"google/protobuf/descriptor.proto\" "
5208       "message_type: { name: \"Bar\" field: { "
5209       "  name: \"foo\" number: 1 label: LABEL_OPTIONAL type: TYPE_INT32 } "
5210       "} "
5211       "extension { name: \"bar\" number: 7672757 label: LABEL_REPEATED "
5212       "            type: TYPE_MESSAGE type_name: \"Bar\" "
5213       "            extendee: \"google.protobuf.FileOptions\" }"
5214       "options { uninterpreted_option { name { name_part: \"bar\" "
5215       "                                        is_extension: true } "
5216       "                                 name { name_part: \"foo\" "
5217       "                                        is_extension: false } "
5218       "                                 positive_int_value: 1 } }",
5219 
5220       "foo.proto: foo.proto: OPTION_NAME: Option field \"(bar)\" is a "
5221       "repeated message. Repeated message options must be initialized "
5222       "using an aggregate value.\n");
5223 }
5224 
TEST_F(ValidationErrorTest,ResolveUndefinedOption)5225 TEST_F(ValidationErrorTest, ResolveUndefinedOption) {
5226   // The following should produce an error that baz.bar is resolved but not
5227   // defined.
5228   // foo.proto:
5229   //   package baz
5230   //   import google/protobuf/descriptor.proto
5231   //   message Bar { optional int32 foo = 1; }
5232   //   extend FileOptions { optional Bar bar = 7672757; }
5233   //
5234   // qux.proto:
5235   //   package qux.baz
5236   //   option (baz.bar).foo = 1;
5237   //
5238   // Although "baz.bar" is already defined, the lookup code will try
5239   // "qux.baz.bar", since it's the match from the innermost scope, which will
5240   // cause a symbol not defined error.
5241   BuildDescriptorMessagesInTestPool();
5242 
5243   BuildFile(
5244       "name: \"foo.proto\" "
5245       "package: \"baz\" "
5246       "dependency: \"google/protobuf/descriptor.proto\" "
5247       "message_type: { name: \"Bar\" field: { "
5248       "  name: \"foo\" number: 1 label: LABEL_OPTIONAL type: TYPE_INT32 } "
5249       "} "
5250       "extension { name: \"bar\" number: 7672757 label: LABEL_OPTIONAL "
5251       "            type: TYPE_MESSAGE type_name: \"Bar\" "
5252       "            extendee: \"google.protobuf.FileOptions\" }");
5253 
5254   BuildFileWithErrors(
5255       "name: \"qux.proto\" "
5256       "package: \"qux.baz\" "
5257       "options { uninterpreted_option { name { name_part: \"baz.bar\" "
5258       "                                        is_extension: true } "
5259       "                                 name { name_part: \"foo\" "
5260       "                                        is_extension: false } "
5261       "                                 positive_int_value: 1 } }",
5262 
5263       "qux.proto: qux.proto: OPTION_NAME: Option \"(baz.bar)\" is resolved to "
5264       "\"(qux.baz.bar)\","
5265       " which is not defined. The innermost scope is searched first in name "
5266       "resolution. Consider using a leading '.'(i.e., \"(.baz.bar)\") to start "
5267       "from the outermost scope.\n");
5268 }
5269 
TEST_F(ValidationErrorTest,UnknownOption)5270 TEST_F(ValidationErrorTest, UnknownOption) {
5271   BuildFileWithErrors(
5272       "name: \"qux.proto\" "
5273       "package: \"qux.baz\" "
5274       "options { uninterpreted_option { name { name_part: \"baaz.bar\" "
5275       "                                        is_extension: true } "
5276       "                                 name { name_part: \"foo\" "
5277       "                                        is_extension: false } "
5278       "                                 positive_int_value: 1 } }",
5279 
5280       "qux.proto: qux.proto: OPTION_NAME: Option \"(baaz.bar)\" unknown. "
5281       "Ensure "
5282       "that your proto definition file imports the proto which defines the "
5283       "option.\n");
5284 }
5285 
TEST_F(ValidationErrorTest,CustomOptionConflictingFieldNumber)5286 TEST_F(ValidationErrorTest, CustomOptionConflictingFieldNumber) {
5287   BuildDescriptorMessagesInTestPool();
5288 
5289   BuildFileWithErrors(
5290       "name: \"foo.proto\" "
5291       "dependency: \"google/protobuf/descriptor.proto\" "
5292       "extension { name: \"foo1\" number: 7672757 label: LABEL_OPTIONAL "
5293       "            type: TYPE_INT32 extendee: \"google.protobuf.FieldOptions\" }"
5294       "extension { name: \"foo2\" number: 7672757 label: LABEL_OPTIONAL "
5295       "            type: TYPE_INT32 extendee: \"google.protobuf.FieldOptions\" }",
5296 
5297       "foo.proto: foo2: NUMBER: Extension number 7672757 has already been used "
5298       "in \"google.protobuf.FieldOptions\" by extension \"foo1\".\n");
5299 }
5300 
TEST_F(ValidationErrorTest,Int32OptionValueOutOfPositiveRange)5301 TEST_F(ValidationErrorTest, Int32OptionValueOutOfPositiveRange) {
5302   BuildDescriptorMessagesInTestPool();
5303 
5304   BuildFileWithErrors(
5305       "name: \"foo.proto\" "
5306       "dependency: \"google/protobuf/descriptor.proto\" "
5307       "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
5308       "            type: TYPE_INT32 extendee: \"google.protobuf.FileOptions\" }"
5309       "options { uninterpreted_option { name { name_part: \"foo\" "
5310       "                                        is_extension: true } "
5311       "                                 positive_int_value: 0x80000000 } "
5312       "}",
5313 
5314       "foo.proto: foo.proto: OPTION_VALUE: Value out of range "
5315       "for int32 option \"foo\".\n");
5316 }
5317 
TEST_F(ValidationErrorTest,Int32OptionValueOutOfNegativeRange)5318 TEST_F(ValidationErrorTest, Int32OptionValueOutOfNegativeRange) {
5319   BuildDescriptorMessagesInTestPool();
5320 
5321   BuildFileWithErrors(
5322       "name: \"foo.proto\" "
5323       "dependency: \"google/protobuf/descriptor.proto\" "
5324       "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
5325       "            type: TYPE_INT32 extendee: \"google.protobuf.FileOptions\" }"
5326       "options { uninterpreted_option { name { name_part: \"foo\" "
5327       "                                        is_extension: true } "
5328       "                                 negative_int_value: -0x80000001 } "
5329       "}",
5330 
5331       "foo.proto: foo.proto: OPTION_VALUE: Value out of range "
5332       "for int32 option \"foo\".\n");
5333 }
5334 
TEST_F(ValidationErrorTest,Int32OptionValueIsNotPositiveInt)5335 TEST_F(ValidationErrorTest, Int32OptionValueIsNotPositiveInt) {
5336   BuildDescriptorMessagesInTestPool();
5337 
5338   BuildFileWithErrors(
5339       "name: \"foo.proto\" "
5340       "dependency: \"google/protobuf/descriptor.proto\" "
5341       "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
5342       "            type: TYPE_INT32 extendee: \"google.protobuf.FileOptions\" }"
5343       "options { uninterpreted_option { name { name_part: \"foo\" "
5344       "                                        is_extension: true } "
5345       "                                 string_value: \"5\" } }",
5346 
5347       "foo.proto: foo.proto: OPTION_VALUE: Value must be integer "
5348       "for int32 option \"foo\".\n");
5349 }
5350 
TEST_F(ValidationErrorTest,Int64OptionValueOutOfRange)5351 TEST_F(ValidationErrorTest, Int64OptionValueOutOfRange) {
5352   BuildDescriptorMessagesInTestPool();
5353 
5354   BuildFileWithErrors(
5355       "name: \"foo.proto\" "
5356       "dependency: \"google/protobuf/descriptor.proto\" "
5357       "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
5358       "            type: TYPE_INT64 extendee: \"google.protobuf.FileOptions\" }"
5359       "options { uninterpreted_option { name { name_part: \"foo\" "
5360       "                                        is_extension: true } "
5361       "                                 positive_int_value: 0x8000000000000000 "
5362       "} "
5363       "}",
5364 
5365       "foo.proto: foo.proto: OPTION_VALUE: Value out of range "
5366       "for int64 option \"foo\".\n");
5367 }
5368 
TEST_F(ValidationErrorTest,Int64OptionValueIsNotPositiveInt)5369 TEST_F(ValidationErrorTest, Int64OptionValueIsNotPositiveInt) {
5370   BuildDescriptorMessagesInTestPool();
5371 
5372   BuildFileWithErrors(
5373       "name: \"foo.proto\" "
5374       "dependency: \"google/protobuf/descriptor.proto\" "
5375       "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
5376       "            type: TYPE_INT64 extendee: \"google.protobuf.FileOptions\" }"
5377       "options { uninterpreted_option { name { name_part: \"foo\" "
5378       "                                        is_extension: true } "
5379       "                                 identifier_value: \"5\" } }",
5380 
5381       "foo.proto: foo.proto: OPTION_VALUE: Value must be integer "
5382       "for int64 option \"foo\".\n");
5383 }
5384 
TEST_F(ValidationErrorTest,UInt32OptionValueOutOfRange)5385 TEST_F(ValidationErrorTest, UInt32OptionValueOutOfRange) {
5386   BuildDescriptorMessagesInTestPool();
5387 
5388   BuildFileWithErrors(
5389       "name: \"foo.proto\" "
5390       "dependency: \"google/protobuf/descriptor.proto\" "
5391       "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
5392       "            type: TYPE_UINT32 extendee: \"google.protobuf.FileOptions\" }"
5393       "options { uninterpreted_option { name { name_part: \"foo\" "
5394       "                                        is_extension: true } "
5395       "                                 positive_int_value: 0x100000000 } }",
5396 
5397       "foo.proto: foo.proto: OPTION_VALUE: Value out of range "
5398       "for uint32 option \"foo\".\n");
5399 }
5400 
TEST_F(ValidationErrorTest,UInt32OptionValueIsNotPositiveInt)5401 TEST_F(ValidationErrorTest, UInt32OptionValueIsNotPositiveInt) {
5402   BuildDescriptorMessagesInTestPool();
5403 
5404   BuildFileWithErrors(
5405       "name: \"foo.proto\" "
5406       "dependency: \"google/protobuf/descriptor.proto\" "
5407       "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
5408       "            type: TYPE_UINT32 extendee: \"google.protobuf.FileOptions\" }"
5409       "options { uninterpreted_option { name { name_part: \"foo\" "
5410       "                                        is_extension: true } "
5411       "                                 double_value: -5.6 } }",
5412 
5413       "foo.proto: foo.proto: OPTION_VALUE: Value must be non-negative integer "
5414       "for uint32 option \"foo\".\n");
5415 }
5416 
TEST_F(ValidationErrorTest,UInt64OptionValueIsNotPositiveInt)5417 TEST_F(ValidationErrorTest, UInt64OptionValueIsNotPositiveInt) {
5418   BuildDescriptorMessagesInTestPool();
5419 
5420   BuildFileWithErrors(
5421       "name: \"foo.proto\" "
5422       "dependency: \"google/protobuf/descriptor.proto\" "
5423       "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
5424       "            type: TYPE_UINT64 extendee: \"google.protobuf.FileOptions\" }"
5425       "options { uninterpreted_option { name { name_part: \"foo\" "
5426       "                                        is_extension: true } "
5427       "                                 negative_int_value: -5 } }",
5428 
5429       "foo.proto: foo.proto: OPTION_VALUE: Value must be non-negative integer "
5430       "for uint64 option \"foo\".\n");
5431 }
5432 
TEST_F(ValidationErrorTest,FloatOptionValueIsNotNumber)5433 TEST_F(ValidationErrorTest, FloatOptionValueIsNotNumber) {
5434   BuildDescriptorMessagesInTestPool();
5435 
5436   BuildFileWithErrors(
5437       "name: \"foo.proto\" "
5438       "dependency: \"google/protobuf/descriptor.proto\" "
5439       "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
5440       "            type: TYPE_FLOAT extendee: \"google.protobuf.FileOptions\" }"
5441       "options { uninterpreted_option { name { name_part: \"foo\" "
5442       "                                        is_extension: true } "
5443       "                                 string_value: \"bar\" } }",
5444 
5445       "foo.proto: foo.proto: OPTION_VALUE: Value must be number "
5446       "for float option \"foo\".\n");
5447 }
5448 
TEST_F(ValidationErrorTest,DoubleOptionValueIsNotNumber)5449 TEST_F(ValidationErrorTest, DoubleOptionValueIsNotNumber) {
5450   BuildDescriptorMessagesInTestPool();
5451 
5452   BuildFileWithErrors(
5453       "name: \"foo.proto\" "
5454       "dependency: \"google/protobuf/descriptor.proto\" "
5455       "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
5456       "            type: TYPE_DOUBLE extendee: \"google.protobuf.FileOptions\" }"
5457       "options { uninterpreted_option { name { name_part: \"foo\" "
5458       "                                        is_extension: true } "
5459       "                                 string_value: \"bar\" } }",
5460 
5461       "foo.proto: foo.proto: OPTION_VALUE: Value must be number "
5462       "for double option \"foo\".\n");
5463 }
5464 
TEST_F(ValidationErrorTest,BoolOptionValueIsNotTrueOrFalse)5465 TEST_F(ValidationErrorTest, BoolOptionValueIsNotTrueOrFalse) {
5466   BuildDescriptorMessagesInTestPool();
5467 
5468   BuildFileWithErrors(
5469       "name: \"foo.proto\" "
5470       "dependency: \"google/protobuf/descriptor.proto\" "
5471       "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
5472       "            type: TYPE_BOOL extendee: \"google.protobuf.FileOptions\" }"
5473       "options { uninterpreted_option { name { name_part: \"foo\" "
5474       "                                        is_extension: true } "
5475       "                                 identifier_value: \"bar\" } }",
5476 
5477       "foo.proto: foo.proto: OPTION_VALUE: Value must be \"true\" or \"false\" "
5478       "for boolean option \"foo\".\n");
5479 }
5480 
TEST_F(ValidationErrorTest,EnumOptionValueIsNotIdentifier)5481 TEST_F(ValidationErrorTest, EnumOptionValueIsNotIdentifier) {
5482   BuildDescriptorMessagesInTestPool();
5483 
5484   BuildFileWithErrors(
5485       "name: \"foo.proto\" "
5486       "dependency: \"google/protobuf/descriptor.proto\" "
5487       "enum_type { name: \"FooEnum\" value { name: \"BAR\" number: 1 } "
5488       "                              value { name: \"BAZ\" number: 2 } }"
5489       "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
5490       "            type: TYPE_ENUM type_name: \"FooEnum\" "
5491       "            extendee: \"google.protobuf.FileOptions\" }"
5492       "options { uninterpreted_option { name { name_part: \"foo\" "
5493       "                                        is_extension: true } "
5494       "                                 string_value: \"QUUX\" } }",
5495 
5496       "foo.proto: foo.proto: OPTION_VALUE: Value must be identifier for "
5497       "enum-valued option \"foo\".\n");
5498 }
5499 
TEST_F(ValidationErrorTest,EnumOptionValueIsNotEnumValueName)5500 TEST_F(ValidationErrorTest, EnumOptionValueIsNotEnumValueName) {
5501   BuildDescriptorMessagesInTestPool();
5502 
5503   BuildFileWithErrors(
5504       "name: \"foo.proto\" "
5505       "dependency: \"google/protobuf/descriptor.proto\" "
5506       "enum_type { name: \"FooEnum\" value { name: \"BAR\" number: 1 } "
5507       "                              value { name: \"BAZ\" number: 2 } }"
5508       "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
5509       "            type: TYPE_ENUM type_name: \"FooEnum\" "
5510       "            extendee: \"google.protobuf.FileOptions\" }"
5511       "options { uninterpreted_option { name { name_part: \"foo\" "
5512       "                                        is_extension: true } "
5513       "                                 identifier_value: \"QUUX\" } }",
5514 
5515       "foo.proto: foo.proto: OPTION_VALUE: Enum type \"FooEnum\" has no value "
5516       "named \"QUUX\" for option \"foo\".\n");
5517 }
5518 
TEST_F(ValidationErrorTest,EnumOptionValueIsSiblingEnumValueName)5519 TEST_F(ValidationErrorTest, EnumOptionValueIsSiblingEnumValueName) {
5520   BuildDescriptorMessagesInTestPool();
5521 
5522   BuildFileWithErrors(
5523       "name: \"foo.proto\" "
5524       "dependency: \"google/protobuf/descriptor.proto\" "
5525       "enum_type { name: \"FooEnum1\" value { name: \"BAR\" number: 1 } "
5526       "                               value { name: \"BAZ\" number: 2 } }"
5527       "enum_type { name: \"FooEnum2\" value { name: \"QUX\" number: 1 } "
5528       "                               value { name: \"QUUX\" number: 2 } }"
5529       "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
5530       "            type: TYPE_ENUM type_name: \"FooEnum1\" "
5531       "            extendee: \"google.protobuf.FileOptions\" }"
5532       "options { uninterpreted_option { name { name_part: \"foo\" "
5533       "                                        is_extension: true } "
5534       "                                 identifier_value: \"QUUX\" } }",
5535 
5536       "foo.proto: foo.proto: OPTION_VALUE: Enum type \"FooEnum1\" has no value "
5537       "named \"QUUX\" for option \"foo\". This appears to be a value from a "
5538       "sibling type.\n");
5539 }
5540 
TEST_F(ValidationErrorTest,StringOptionValueIsNotString)5541 TEST_F(ValidationErrorTest, StringOptionValueIsNotString) {
5542   BuildDescriptorMessagesInTestPool();
5543 
5544   BuildFileWithErrors(
5545       "name: \"foo.proto\" "
5546       "dependency: \"google/protobuf/descriptor.proto\" "
5547       "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
5548       "            type: TYPE_STRING extendee: \"google.protobuf.FileOptions\" }"
5549       "options { uninterpreted_option { name { name_part: \"foo\" "
5550       "                                        is_extension: true } "
5551       "                                 identifier_value: \"QUUX\" } }",
5552 
5553       "foo.proto: foo.proto: OPTION_VALUE: Value must be quoted string "
5554       "for "
5555       "string option \"foo\".\n");
5556 }
5557 
TEST_F(ValidationErrorTest,JsonNameOptionOnExtensions)5558 TEST_F(ValidationErrorTest, JsonNameOptionOnExtensions) {
5559   BuildFileWithErrors(
5560       "name: \"foo.proto\" "
5561       "package: \"foo\" "
5562       "message_type {"
5563       "  name: \"Foo\""
5564       "  extension_range { start: 10 end: 20 }"
5565       "}"
5566       "extension {"
5567       "  name: \"value\""
5568       "  number: 10"
5569       "  label: LABEL_OPTIONAL"
5570       "  type: TYPE_INT32"
5571       "  extendee: \"foo.Foo\""
5572       "  json_name: \"myName\""
5573       "}",
5574       "foo.proto: foo.value: OPTION_NAME: option json_name is not allowed on "
5575       "extension fields.\n");
5576 }
5577 
TEST_F(ValidationErrorTest,DuplicateExtensionFieldNumber)5578 TEST_F(ValidationErrorTest, DuplicateExtensionFieldNumber) {
5579   BuildDescriptorMessagesInTestPool();
5580 
5581   BuildFile(
5582       "name: \"foo.proto\" "
5583       "dependency: \"google/protobuf/descriptor.proto\" "
5584       "extension { name: \"option1\" number: 1000 label: LABEL_OPTIONAL "
5585       "            type: TYPE_INT32 extendee: \"google.protobuf.FileOptions\" }");
5586 
5587   BuildFileWithWarnings(
5588       "name: \"bar.proto\" "
5589       "dependency: \"google/protobuf/descriptor.proto\" "
5590       "extension { name: \"option2\" number: 1000 label: LABEL_OPTIONAL "
5591       "            type: TYPE_INT32 extendee: \"google.protobuf.FileOptions\" }",
5592       "bar.proto: option2: NUMBER: Extension number 1000 has already been used "
5593       "in \"google.protobuf.FileOptions\" by extension \"option1\" defined in "
5594       "foo.proto.\n");
5595 }
5596 
5597 // Helper function for tests that check for aggregate value parsing
5598 // errors.  The "value" argument is embedded inside the
5599 // "uninterpreted_option" portion of the result.
EmbedAggregateValue(const char * value)5600 static std::string EmbedAggregateValue(const char* value) {
5601   return strings::Substitute(
5602       "name: \"foo.proto\" "
5603       "dependency: \"google/protobuf/descriptor.proto\" "
5604       "message_type { name: \"Foo\" } "
5605       "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
5606       "            type: TYPE_MESSAGE type_name: \"Foo\" "
5607       "            extendee: \"google.protobuf.FileOptions\" }"
5608       "options { uninterpreted_option { name { name_part: \"foo\" "
5609       "                                        is_extension: true } "
5610       "                                 $0 } }",
5611       value);
5612 }
5613 
TEST_F(ValidationErrorTest,AggregateValueNotFound)5614 TEST_F(ValidationErrorTest, AggregateValueNotFound) {
5615   BuildDescriptorMessagesInTestPool();
5616 
5617   BuildFileWithErrors(
5618       EmbedAggregateValue("string_value: \"\""),
5619       "foo.proto: foo.proto: OPTION_VALUE: Option \"foo\" is a message. "
5620       "To set the entire message, use syntax like "
5621       "\"foo = { <proto text format> }\". To set fields within it, use "
5622       "syntax like \"foo.foo = value\".\n");
5623 }
5624 
TEST_F(ValidationErrorTest,AggregateValueParseError)5625 TEST_F(ValidationErrorTest, AggregateValueParseError) {
5626   BuildDescriptorMessagesInTestPool();
5627 
5628   BuildFileWithErrors(
5629       EmbedAggregateValue("aggregate_value: \"1+2\""),
5630       "foo.proto: foo.proto: OPTION_VALUE: Error while parsing option "
5631       "value for \"foo\": Expected identifier, got: 1\n");
5632 }
5633 
TEST_F(ValidationErrorTest,AggregateValueUnknownFields)5634 TEST_F(ValidationErrorTest, AggregateValueUnknownFields) {
5635   BuildDescriptorMessagesInTestPool();
5636 
5637   BuildFileWithErrors(
5638       EmbedAggregateValue("aggregate_value: \"x:100\""),
5639       "foo.proto: foo.proto: OPTION_VALUE: Error while parsing option "
5640       "value for \"foo\": Message type \"Foo\" has no field named \"x\".\n");
5641 }
5642 
TEST_F(ValidationErrorTest,NotLiteImportsLite)5643 TEST_F(ValidationErrorTest, NotLiteImportsLite) {
5644   BuildFile(
5645       "name: \"bar.proto\" "
5646       "options { optimize_for: LITE_RUNTIME } ");
5647 
5648   BuildFileWithErrors(
5649       "name: \"foo.proto\" "
5650       "dependency: \"bar.proto\" ",
5651 
5652       "foo.proto: bar.proto: IMPORT: Files that do not use optimize_for = "
5653       "LITE_RUNTIME cannot import files which do use this option.  This file "
5654       "is not lite, but it imports \"bar.proto\" which is.\n");
5655 }
5656 
TEST_F(ValidationErrorTest,LiteExtendsNotLite)5657 TEST_F(ValidationErrorTest, LiteExtendsNotLite) {
5658   BuildFile(
5659       "name: \"bar.proto\" "
5660       "message_type: {"
5661       "  name: \"Bar\""
5662       "  extension_range { start: 1 end: 1000 }"
5663       "}");
5664 
5665   BuildFileWithErrors(
5666       "name: \"foo.proto\" "
5667       "dependency: \"bar.proto\" "
5668       "options { optimize_for: LITE_RUNTIME } "
5669       "extension { name: \"ext\" number: 123 label: LABEL_OPTIONAL "
5670       "            type: TYPE_INT32 extendee: \"Bar\" }",
5671 
5672       "foo.proto: ext: EXTENDEE: Extensions to non-lite types can only be "
5673       "declared in non-lite files.  Note that you cannot extend a non-lite "
5674       "type to contain a lite type, but the reverse is allowed.\n");
5675 }
5676 
TEST_F(ValidationErrorTest,NoLiteServices)5677 TEST_F(ValidationErrorTest, NoLiteServices) {
5678   BuildFileWithErrors(
5679       "name: \"foo.proto\" "
5680       "options {"
5681       "  optimize_for: LITE_RUNTIME"
5682       "  cc_generic_services: true"
5683       "  java_generic_services: true"
5684       "} "
5685       "service { name: \"Foo\" }",
5686 
5687       "foo.proto: Foo: NAME: Files with optimize_for = LITE_RUNTIME cannot "
5688       "define services unless you set both options cc_generic_services and "
5689       "java_generic_services to false.\n");
5690 
5691   BuildFile(
5692       "name: \"bar.proto\" "
5693       "options {"
5694       "  optimize_for: LITE_RUNTIME"
5695       "  cc_generic_services: false"
5696       "  java_generic_services: false"
5697       "} "
5698       "service { name: \"Bar\" }");
5699 }
5700 
TEST_F(ValidationErrorTest,RollbackAfterError)5701 TEST_F(ValidationErrorTest, RollbackAfterError) {
5702   // Build a file which contains every kind of construct but references an
5703   // undefined type.  All these constructs will be added to the symbol table
5704   // before the undefined type error is noticed.  The DescriptorPool will then
5705   // have to roll everything back.
5706   BuildFileWithErrors(
5707       "name: \"foo.proto\" "
5708       "message_type {"
5709       "  name: \"TestMessage\""
5710       "  field { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:1 }"
5711       "} "
5712       "enum_type {"
5713       "  name: \"TestEnum\""
5714       "  value { name:\"BAR\" number:1 }"
5715       "} "
5716       "service {"
5717       "  name: \"TestService\""
5718       "  method {"
5719       "    name: \"Baz\""
5720       "    input_type: \"NoSuchType\""  // error
5721       "    output_type: \"TestMessage\""
5722       "  }"
5723       "}",
5724 
5725       "foo.proto: TestService.Baz: INPUT_TYPE: \"NoSuchType\" is not defined.\n"
5726   );
5727 
5728   // Make sure that if we build the same file again with the error fixed,
5729   // it works.  If the above rollback was incomplete, then some symbols will
5730   // be left defined, and this second attempt will fail since it tries to
5731   // re-define the same symbols.
5732   BuildFile(
5733       "name: \"foo.proto\" "
5734       "message_type {"
5735       "  name: \"TestMessage\""
5736       "  field { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:1 }"
5737       "} "
5738       "enum_type {"
5739       "  name: \"TestEnum\""
5740       "  value { name:\"BAR\" number:1 }"
5741       "} "
5742       "service {"
5743       "  name: \"TestService\""
5744       "  method { name:\"Baz\""
5745       "           input_type:\"TestMessage\""
5746       "           output_type:\"TestMessage\" }"
5747       "}");
5748 }
5749 
TEST_F(ValidationErrorTest,ErrorsReportedToLogError)5750 TEST_F(ValidationErrorTest, ErrorsReportedToLogError) {
5751   // Test that errors are reported to GOOGLE_LOG(ERROR) if no error collector is
5752   // provided.
5753 
5754   FileDescriptorProto file_proto;
5755   ASSERT_TRUE(
5756       TextFormat::ParseFromString("name: \"foo.proto\" "
5757                                   "message_type { name: \"Foo\" } "
5758                                   "message_type { name: \"Foo\" } ",
5759                                   &file_proto));
5760 
5761   std::vector<std::string> errors;
5762 
5763   {
5764     ScopedMemoryLog log;
5765     EXPECT_TRUE(pool_.BuildFile(file_proto) == nullptr);
5766     errors = log.GetMessages(ERROR);
5767   }
5768 
5769   ASSERT_EQ(2, errors.size());
5770 
5771   EXPECT_EQ("Invalid proto descriptor for file \"foo.proto\":", errors[0]);
5772   EXPECT_EQ("  Foo: \"Foo\" is already defined.", errors[1]);
5773 }
5774 
TEST_F(ValidationErrorTest,DisallowEnumAlias)5775 TEST_F(ValidationErrorTest, DisallowEnumAlias) {
5776   BuildFileWithErrors(
5777       "name: \"foo.proto\" "
5778       "enum_type {"
5779       "  name: \"Bar\""
5780       "  value { name:\"ENUM_A\" number:0 }"
5781       "  value { name:\"ENUM_B\" number:0 }"
5782       "}",
5783       "foo.proto: Bar: NUMBER: "
5784       "\"ENUM_B\" uses the same enum value as \"ENUM_A\". "
5785       "If this is intended, set 'option allow_alias = true;' to the enum "
5786       "definition.\n");
5787 }
5788 
TEST_F(ValidationErrorTest,AllowEnumAlias)5789 TEST_F(ValidationErrorTest, AllowEnumAlias) {
5790   BuildFile(
5791       "name: \"foo.proto\" "
5792       "enum_type {"
5793       "  name: \"Bar\""
5794       "  value { name:\"ENUM_A\" number:0 }"
5795       "  value { name:\"ENUM_B\" number:0 }"
5796       "  options { allow_alias: true }"
5797       "}");
5798 }
5799 
TEST_F(ValidationErrorTest,UnusedImportWarning)5800 TEST_F(ValidationErrorTest, UnusedImportWarning) {
5801   pool_.AddUnusedImportTrackFile("bar.proto");
5802   BuildFile(
5803       "name: \"bar.proto\" "
5804       "message_type { name: \"Bar\" }");
5805 
5806   pool_.AddUnusedImportTrackFile("base.proto");
5807   BuildFile(
5808       "name: \"base.proto\" "
5809       "message_type { name: \"Base\" }");
5810 
5811   pool_.AddUnusedImportTrackFile("baz.proto");
5812   BuildFile(
5813       "name: \"baz.proto\" "
5814       "message_type { name: \"Baz\" }");
5815 
5816   pool_.AddUnusedImportTrackFile("public.proto");
5817   BuildFile(
5818       "name: \"public.proto\" "
5819       "dependency: \"bar.proto\""
5820       "public_dependency: 0");
5821 
5822   // // forward.proto
5823   // import "base.proto"       // No warning: Base message is used.
5824   // import "bar.proto"        // Will log a warning.
5825   // import public "baz.proto" // No warning: Do not track import public.
5826   // import "public.proto"     // No warning: public.proto has import public.
5827   // message Forward {
5828   //   optional Base base = 1;
5829   // }
5830   //
5831   pool_.AddUnusedImportTrackFile("forward.proto");
5832   BuildFileWithWarnings(
5833       "name: \"forward.proto\""
5834       "dependency: \"base.proto\""
5835       "dependency: \"bar.proto\""
5836       "dependency: \"baz.proto\""
5837       "dependency: \"public.proto\""
5838       "public_dependency: 2 "
5839       "message_type {"
5840       "  name: \"Forward\""
5841       "  field { name:\"base\" number:1 label:LABEL_OPTIONAL "
5842       "type_name:\"Base\" }"
5843       "}",
5844       "forward.proto: bar.proto: IMPORT: Import bar.proto is unused.\n");
5845 }
5846 
5847 namespace {
FillValidMapEntry(FileDescriptorProto * file_proto)5848 void FillValidMapEntry(FileDescriptorProto* file_proto) {
5849   ASSERT_TRUE(TextFormat::ParseFromString(
5850       "name: 'foo.proto' "
5851       "message_type { "
5852       "  name: 'Foo' "
5853       "  field { "
5854       "    name: 'foo_map' number: 1 label:LABEL_REPEATED "
5855       "    type_name: 'FooMapEntry' "
5856       "  } "
5857       "  nested_type { "
5858       "    name: 'FooMapEntry' "
5859       "    options {  map_entry: true } "
5860       "    field { "
5861       "      name: 'key' number: 1 type:TYPE_INT32 label:LABEL_OPTIONAL "
5862       "    } "
5863       "    field { "
5864       "      name: 'value' number: 2 type:TYPE_INT32 label:LABEL_OPTIONAL "
5865       "    } "
5866       "  } "
5867       "} "
5868       "message_type { "
5869       "  name: 'Bar' "
5870       "  extension_range { start: 1 end: 10 }"
5871       "} ",
5872       file_proto));
5873 }
5874 static const char* kMapEntryErrorMessage =
5875     "foo.proto: Foo.foo_map: TYPE: map_entry should not be set explicitly. "
5876     "Use map<KeyType, ValueType> instead.\n";
5877 static const char* kMapEntryKeyTypeErrorMessage =
5878     "foo.proto: Foo.foo_map: TYPE: Key in map fields cannot be float/double, "
5879     "bytes or message types.\n";
5880 
5881 }  // namespace
5882 
TEST_F(ValidationErrorTest,MapEntryBase)5883 TEST_F(ValidationErrorTest, MapEntryBase) {
5884   FileDescriptorProto file_proto;
5885   FillValidMapEntry(&file_proto);
5886   BuildFile(file_proto.DebugString());
5887 }
5888 
TEST_F(ValidationErrorTest,MapEntryExtensionRange)5889 TEST_F(ValidationErrorTest, MapEntryExtensionRange) {
5890   FileDescriptorProto file_proto;
5891   FillValidMapEntry(&file_proto);
5892   TextFormat::MergeFromString(
5893       "extension_range { "
5894       "  start: 10 end: 20 "
5895       "} ",
5896       file_proto.mutable_message_type(0)->mutable_nested_type(0));
5897   BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage);
5898 }
5899 
TEST_F(ValidationErrorTest,MapEntryExtension)5900 TEST_F(ValidationErrorTest, MapEntryExtension) {
5901   FileDescriptorProto file_proto;
5902   FillValidMapEntry(&file_proto);
5903   TextFormat::MergeFromString(
5904       "extension { "
5905       "  name: 'foo_ext' extendee: '.Bar' number: 5"
5906       "} ",
5907       file_proto.mutable_message_type(0)->mutable_nested_type(0));
5908   BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage);
5909 }
5910 
TEST_F(ValidationErrorTest,MapEntryNestedType)5911 TEST_F(ValidationErrorTest, MapEntryNestedType) {
5912   FileDescriptorProto file_proto;
5913   FillValidMapEntry(&file_proto);
5914   TextFormat::MergeFromString(
5915       "nested_type { "
5916       "  name: 'Bar' "
5917       "} ",
5918       file_proto.mutable_message_type(0)->mutable_nested_type(0));
5919   BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage);
5920 }
5921 
TEST_F(ValidationErrorTest,MapEntryEnumTypes)5922 TEST_F(ValidationErrorTest, MapEntryEnumTypes) {
5923   FileDescriptorProto file_proto;
5924   FillValidMapEntry(&file_proto);
5925   TextFormat::MergeFromString(
5926       "enum_type { "
5927       "  name: 'BarEnum' "
5928       "  value { name: 'BAR_BAR' number:0 } "
5929       "} ",
5930       file_proto.mutable_message_type(0)->mutable_nested_type(0));
5931   BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage);
5932 }
5933 
TEST_F(ValidationErrorTest,MapEntryExtraField)5934 TEST_F(ValidationErrorTest, MapEntryExtraField) {
5935   FileDescriptorProto file_proto;
5936   FillValidMapEntry(&file_proto);
5937   TextFormat::MergeFromString(
5938       "field { "
5939       "  name: 'other_field' "
5940       "  label: LABEL_OPTIONAL "
5941       "  type: TYPE_INT32 "
5942       "  number: 3 "
5943       "} ",
5944       file_proto.mutable_message_type(0)->mutable_nested_type(0));
5945   BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage);
5946 }
5947 
TEST_F(ValidationErrorTest,MapEntryMessageName)5948 TEST_F(ValidationErrorTest, MapEntryMessageName) {
5949   FileDescriptorProto file_proto;
5950   FillValidMapEntry(&file_proto);
5951   file_proto.mutable_message_type(0)->mutable_nested_type(0)->set_name(
5952       "OtherMapEntry");
5953   file_proto.mutable_message_type(0)->mutable_field(0)->set_type_name(
5954       "OtherMapEntry");
5955   BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage);
5956 }
5957 
TEST_F(ValidationErrorTest,MapEntryNoneRepeatedMapEntry)5958 TEST_F(ValidationErrorTest, MapEntryNoneRepeatedMapEntry) {
5959   FileDescriptorProto file_proto;
5960   FillValidMapEntry(&file_proto);
5961   file_proto.mutable_message_type(0)->mutable_field(0)->set_label(
5962       FieldDescriptorProto::LABEL_OPTIONAL);
5963   BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage);
5964 }
5965 
TEST_F(ValidationErrorTest,MapEntryDifferentContainingType)5966 TEST_F(ValidationErrorTest, MapEntryDifferentContainingType) {
5967   FileDescriptorProto file_proto;
5968   FillValidMapEntry(&file_proto);
5969   // Move the nested MapEntry message into the top level, which should not pass
5970   // the validation.
5971   file_proto.mutable_message_type()->AddAllocated(
5972       file_proto.mutable_message_type(0)->mutable_nested_type()->ReleaseLast());
5973   BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage);
5974 }
5975 
TEST_F(ValidationErrorTest,MapEntryKeyName)5976 TEST_F(ValidationErrorTest, MapEntryKeyName) {
5977   FileDescriptorProto file_proto;
5978   FillValidMapEntry(&file_proto);
5979   FieldDescriptorProto* key =
5980       file_proto.mutable_message_type(0)->mutable_nested_type(0)->mutable_field(
5981           0);
5982   key->set_name("Key");
5983   BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage);
5984 }
5985 
TEST_F(ValidationErrorTest,MapEntryKeyLabel)5986 TEST_F(ValidationErrorTest, MapEntryKeyLabel) {
5987   FileDescriptorProto file_proto;
5988   FillValidMapEntry(&file_proto);
5989   FieldDescriptorProto* key =
5990       file_proto.mutable_message_type(0)->mutable_nested_type(0)->mutable_field(
5991           0);
5992   key->set_label(FieldDescriptorProto::LABEL_REQUIRED);
5993   BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage);
5994 }
5995 
TEST_F(ValidationErrorTest,MapEntryKeyNumber)5996 TEST_F(ValidationErrorTest, MapEntryKeyNumber) {
5997   FileDescriptorProto file_proto;
5998   FillValidMapEntry(&file_proto);
5999   FieldDescriptorProto* key =
6000       file_proto.mutable_message_type(0)->mutable_nested_type(0)->mutable_field(
6001           0);
6002   key->set_number(3);
6003   BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage);
6004 }
6005 
TEST_F(ValidationErrorTest,MapEntryValueName)6006 TEST_F(ValidationErrorTest, MapEntryValueName) {
6007   FileDescriptorProto file_proto;
6008   FillValidMapEntry(&file_proto);
6009   FieldDescriptorProto* value =
6010       file_proto.mutable_message_type(0)->mutable_nested_type(0)->mutable_field(
6011           1);
6012   value->set_name("Value");
6013   BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage);
6014 }
6015 
TEST_F(ValidationErrorTest,MapEntryValueLabel)6016 TEST_F(ValidationErrorTest, MapEntryValueLabel) {
6017   FileDescriptorProto file_proto;
6018   FillValidMapEntry(&file_proto);
6019   FieldDescriptorProto* value =
6020       file_proto.mutable_message_type(0)->mutable_nested_type(0)->mutable_field(
6021           1);
6022   value->set_label(FieldDescriptorProto::LABEL_REQUIRED);
6023   BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage);
6024 }
6025 
TEST_F(ValidationErrorTest,MapEntryValueNumber)6026 TEST_F(ValidationErrorTest, MapEntryValueNumber) {
6027   FileDescriptorProto file_proto;
6028   FillValidMapEntry(&file_proto);
6029   FieldDescriptorProto* value =
6030       file_proto.mutable_message_type(0)->mutable_nested_type(0)->mutable_field(
6031           1);
6032   value->set_number(3);
6033   BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage);
6034 }
6035 
TEST_F(ValidationErrorTest,MapEntryKeyTypeFloat)6036 TEST_F(ValidationErrorTest, MapEntryKeyTypeFloat) {
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_type(FieldDescriptorProto::TYPE_FLOAT);
6043   BuildFileWithErrors(file_proto.DebugString(), kMapEntryKeyTypeErrorMessage);
6044 }
6045 
TEST_F(ValidationErrorTest,MapEntryKeyTypeDouble)6046 TEST_F(ValidationErrorTest, MapEntryKeyTypeDouble) {
6047   FileDescriptorProto file_proto;
6048   FillValidMapEntry(&file_proto);
6049   FieldDescriptorProto* key =
6050       file_proto.mutable_message_type(0)->mutable_nested_type(0)->mutable_field(
6051           0);
6052   key->set_type(FieldDescriptorProto::TYPE_DOUBLE);
6053   BuildFileWithErrors(file_proto.DebugString(), kMapEntryKeyTypeErrorMessage);
6054 }
6055 
TEST_F(ValidationErrorTest,MapEntryKeyTypeBytes)6056 TEST_F(ValidationErrorTest, MapEntryKeyTypeBytes) {
6057   FileDescriptorProto file_proto;
6058   FillValidMapEntry(&file_proto);
6059   FieldDescriptorProto* key =
6060       file_proto.mutable_message_type(0)->mutable_nested_type(0)->mutable_field(
6061           0);
6062   key->set_type(FieldDescriptorProto::TYPE_BYTES);
6063   BuildFileWithErrors(file_proto.DebugString(), kMapEntryKeyTypeErrorMessage);
6064 }
6065 
TEST_F(ValidationErrorTest,MapEntryKeyTypeEnum)6066 TEST_F(ValidationErrorTest, MapEntryKeyTypeEnum) {
6067   FileDescriptorProto file_proto;
6068   FillValidMapEntry(&file_proto);
6069   FieldDescriptorProto* key =
6070       file_proto.mutable_message_type(0)->mutable_nested_type(0)->mutable_field(
6071           0);
6072   key->clear_type();
6073   key->set_type_name("BarEnum");
6074   EnumDescriptorProto* enum_proto = file_proto.add_enum_type();
6075   enum_proto->set_name("BarEnum");
6076   EnumValueDescriptorProto* enum_value_proto = enum_proto->add_value();
6077   enum_value_proto->set_name("BAR_VALUE0");
6078   enum_value_proto->set_number(0);
6079   BuildFileWithErrors(file_proto.DebugString(),
6080                       "foo.proto: Foo.foo_map: TYPE: Key in map fields cannot "
6081                       "be enum types.\n");
6082   // Enum keys are not allowed in proto3 as well.
6083   // Get rid of extensions for proto3 to make it proto3 compatible.
6084   file_proto.mutable_message_type()->RemoveLast();
6085   file_proto.set_syntax("proto3");
6086   BuildFileWithErrors(file_proto.DebugString(),
6087                       "foo.proto: Foo.foo_map: TYPE: Key in map fields cannot "
6088                       "be enum types.\n");
6089 }
6090 
TEST_F(ValidationErrorTest,MapEntryKeyTypeMessage)6091 TEST_F(ValidationErrorTest, MapEntryKeyTypeMessage) {
6092   FileDescriptorProto file_proto;
6093   FillValidMapEntry(&file_proto);
6094   FieldDescriptorProto* key =
6095       file_proto.mutable_message_type(0)->mutable_nested_type(0)->mutable_field(
6096           0);
6097   key->clear_type();
6098   key->set_type_name(".Bar");
6099   BuildFileWithErrors(file_proto.DebugString(), kMapEntryKeyTypeErrorMessage);
6100 }
6101 
TEST_F(ValidationErrorTest,MapEntryConflictsWithField)6102 TEST_F(ValidationErrorTest, MapEntryConflictsWithField) {
6103   FileDescriptorProto file_proto;
6104   FillValidMapEntry(&file_proto);
6105   TextFormat::MergeFromString(
6106       "field { "
6107       "  name: 'FooMapEntry' "
6108       "  type: TYPE_INT32 "
6109       "  label: LABEL_OPTIONAL "
6110       "  number: 100 "
6111       "}",
6112       file_proto.mutable_message_type(0));
6113   BuildFileWithErrors(
6114       file_proto.DebugString(),
6115       "foo.proto: Foo.FooMapEntry: NAME: \"FooMapEntry\" is already defined in "
6116       "\"Foo\".\n"
6117       "foo.proto: Foo.foo_map: TYPE: \"FooMapEntry\" is not defined.\n"
6118       "foo.proto: Foo: NAME: Expanded map entry type FooMapEntry conflicts "
6119       "with an existing field.\n");
6120 }
6121 
TEST_F(ValidationErrorTest,MapEntryConflictsWithMessage)6122 TEST_F(ValidationErrorTest, MapEntryConflictsWithMessage) {
6123   FileDescriptorProto file_proto;
6124   FillValidMapEntry(&file_proto);
6125   TextFormat::MergeFromString(
6126       "nested_type { "
6127       "  name: 'FooMapEntry' "
6128       "}",
6129       file_proto.mutable_message_type(0));
6130   BuildFileWithErrors(
6131       file_proto.DebugString(),
6132       "foo.proto: Foo.FooMapEntry: NAME: \"FooMapEntry\" is already defined in "
6133       "\"Foo\".\n"
6134       "foo.proto: Foo: NAME: Expanded map entry type FooMapEntry conflicts "
6135       "with an existing nested message type.\n");
6136 }
6137 
TEST_F(ValidationErrorTest,MapEntryConflictsWithEnum)6138 TEST_F(ValidationErrorTest, MapEntryConflictsWithEnum) {
6139   FileDescriptorProto file_proto;
6140   FillValidMapEntry(&file_proto);
6141   TextFormat::MergeFromString(
6142       "enum_type { "
6143       "  name: 'FooMapEntry' "
6144       "  value { name: 'ENTRY_FOO' number: 0 }"
6145       "}",
6146       file_proto.mutable_message_type(0));
6147   BuildFileWithErrors(
6148       file_proto.DebugString(),
6149       "foo.proto: Foo.FooMapEntry: NAME: \"FooMapEntry\" is already defined in "
6150       "\"Foo\".\n"
6151       "foo.proto: Foo: NAME: Expanded map entry type FooMapEntry conflicts "
6152       "with an existing enum type.\n");
6153 }
6154 
TEST_F(ValidationErrorTest,EnumValuesConflictWithDifferentCasing)6155 TEST_F(ValidationErrorTest, EnumValuesConflictWithDifferentCasing) {
6156   BuildFileWithErrors(
6157       "syntax: 'proto3'"
6158       "name: 'foo.proto' "
6159       "enum_type {"
6160       "  name: 'FooEnum' "
6161       "  value { name: 'BAR' number: 0 }"
6162       "  value { name: 'bar' number: 1 }"
6163       "}",
6164       "foo.proto: bar: NAME: Enum name bar has the same name as BAR "
6165       "if you ignore case and strip out the enum name prefix (if any). "
6166       "This is error-prone and can lead to undefined behavior. "
6167       "Please avoid doing this. If you are using allow_alias, please assign "
6168       "the same numeric value to both enums.\n");
6169 
6170   // Not an error because both enums are mapped to the same value.
6171   BuildFile(
6172       "syntax: 'proto3'"
6173       "name: 'foo.proto' "
6174       "enum_type {"
6175       "  name: 'FooEnum' "
6176       "  options { allow_alias: true }"
6177       "  value { name: 'UNKNOWN' number: 0 }"
6178       "  value { name: 'BAR' number: 1 }"
6179       "  value { name: 'bar' number: 1 }"
6180       "}");
6181 }
6182 
TEST_F(ValidationErrorTest,EnumValuesConflictWhenPrefixesStripped)6183 TEST_F(ValidationErrorTest, EnumValuesConflictWhenPrefixesStripped) {
6184   BuildFileWithErrors(
6185       "syntax: 'proto3'"
6186       "name: 'foo.proto' "
6187       "enum_type {"
6188       "  name: 'FooEnum' "
6189       "  value { name: 'FOO_ENUM_BAZ' number: 0 }"
6190       "  value { name: 'BAZ' number: 1 }"
6191       "}",
6192       "foo.proto: BAZ: NAME: Enum name BAZ has the same name as FOO_ENUM_BAZ "
6193       "if you ignore case and strip out the enum name prefix (if any). "
6194       "This is error-prone and can lead to undefined behavior. "
6195       "Please avoid doing this. If you are using allow_alias, please assign "
6196       "the same numeric value to both enums.\n");
6197 
6198   BuildFileWithErrors(
6199       "syntax: 'proto3'"
6200       "name: 'foo.proto' "
6201       "enum_type {"
6202       "  name: 'FooEnum' "
6203       "  value { name: 'FOOENUM_BAZ' number: 0 }"
6204       "  value { name: 'BAZ' number: 1 }"
6205       "}",
6206       "foo.proto: BAZ: NAME: Enum name BAZ has the same name as FOOENUM_BAZ "
6207       "if you ignore case and strip out the enum name prefix (if any). "
6208       "This is error-prone and can lead to undefined behavior. "
6209       "Please avoid doing this. If you are using allow_alias, please assign "
6210       "the same numeric value to both enums.\n");
6211 
6212   BuildFileWithErrors(
6213       "syntax: 'proto3'"
6214       "name: 'foo.proto' "
6215       "enum_type {"
6216       "  name: 'FooEnum' "
6217       "  value { name: 'FOO_ENUM_BAR_BAZ' number: 0 }"
6218       "  value { name: 'BAR__BAZ' number: 1 }"
6219       "}",
6220       "foo.proto: BAR__BAZ: NAME: Enum name BAR__BAZ has the same name as "
6221       "FOO_ENUM_BAR_BAZ if you ignore case and strip out the enum name prefix "
6222       "(if any). This is error-prone and can lead to undefined behavior. "
6223       "Please avoid doing this. If you are using allow_alias, please assign "
6224       "the same numeric value to both enums.\n");
6225 
6226   BuildFileWithErrors(
6227       "syntax: 'proto3'"
6228       "name: 'foo.proto' "
6229       "enum_type {"
6230       "  name: 'FooEnum' "
6231       "  value { name: 'FOO_ENUM__BAR_BAZ' number: 0 }"
6232       "  value { name: 'BAR_BAZ' number: 1 }"
6233       "}",
6234       "foo.proto: BAR_BAZ: NAME: Enum name BAR_BAZ has the same name as "
6235       "FOO_ENUM__BAR_BAZ if you ignore case and strip out the enum name prefix "
6236       "(if any). This is error-prone and can lead to undefined behavior. "
6237       "Please avoid doing this. If you are using allow_alias, please assign "
6238       "the same numeric value to both enums.\n");
6239 
6240   // This isn't an error because the underscore will cause the PascalCase to
6241   // differ by case (BarBaz vs. Barbaz).
6242   BuildFile(
6243       "syntax: 'proto3'"
6244       "name: 'foo.proto' "
6245       "enum_type {"
6246       "  name: 'FooEnum' "
6247       "  value { name: 'BAR_BAZ' number: 0 }"
6248       "  value { name: 'BARBAZ' number: 1 }"
6249       "}");
6250 }
6251 
TEST_F(ValidationErrorTest,MapEntryConflictsWithOneof)6252 TEST_F(ValidationErrorTest, MapEntryConflictsWithOneof) {
6253   FileDescriptorProto file_proto;
6254   FillValidMapEntry(&file_proto);
6255   TextFormat::MergeFromString(
6256       "oneof_decl { "
6257       "  name: 'FooMapEntry' "
6258       "}"
6259       "field { "
6260       "  name: 'int_field' "
6261       "  type: TYPE_INT32 "
6262       "  label: LABEL_OPTIONAL "
6263       "  oneof_index: 0 "
6264       "  number: 100 "
6265       "} ",
6266       file_proto.mutable_message_type(0));
6267   BuildFileWithErrors(
6268       file_proto.DebugString(),
6269       "foo.proto: Foo.FooMapEntry: NAME: \"FooMapEntry\" is already defined in "
6270       "\"Foo\".\n"
6271       "foo.proto: Foo.foo_map: TYPE: \"FooMapEntry\" is not defined.\n"
6272       "foo.proto: Foo: NAME: Expanded map entry type FooMapEntry conflicts "
6273       "with an existing oneof type.\n");
6274 }
6275 
TEST_F(ValidationErrorTest,MapEntryUsesNoneZeroEnumDefaultValue)6276 TEST_F(ValidationErrorTest, MapEntryUsesNoneZeroEnumDefaultValue) {
6277   BuildFileWithErrors(
6278       "name: \"foo.proto\" "
6279       "enum_type {"
6280       "  name: \"Bar\""
6281       "  value { name:\"ENUM_A\" number:1 }"
6282       "  value { name:\"ENUM_B\" number:2 }"
6283       "}"
6284       "message_type {"
6285       "  name: 'Foo' "
6286       "  field { "
6287       "    name: 'foo_map' number: 1 label:LABEL_REPEATED "
6288       "    type_name: 'FooMapEntry' "
6289       "  } "
6290       "  nested_type { "
6291       "    name: 'FooMapEntry' "
6292       "    options {  map_entry: true } "
6293       "    field { "
6294       "      name: 'key' number: 1 type:TYPE_INT32 label:LABEL_OPTIONAL "
6295       "    } "
6296       "    field { "
6297       "      name: 'value' number: 2 type_name:\"Bar\" label:LABEL_OPTIONAL "
6298       "    } "
6299       "  } "
6300       "}",
6301       "foo.proto: Foo.foo_map: "
6302       "TYPE: Enum value in map must define 0 as the first value.\n");
6303 }
6304 
TEST_F(ValidationErrorTest,Proto3RequiredFields)6305 TEST_F(ValidationErrorTest, Proto3RequiredFields) {
6306   BuildFileWithErrors(
6307       "name: 'foo.proto' "
6308       "syntax: 'proto3' "
6309       "message_type { "
6310       "  name: 'Foo' "
6311       "  field { name:'foo' number:1 label:LABEL_REQUIRED type:TYPE_INT32 } "
6312       "}",
6313       "foo.proto: Foo.foo: TYPE: Required fields are not allowed in "
6314       "proto3.\n");
6315 
6316   // applied to nested types as well.
6317   BuildFileWithErrors(
6318       "name: 'foo.proto' "
6319       "syntax: 'proto3' "
6320       "message_type { "
6321       "  name: 'Foo' "
6322       "  nested_type { "
6323       "    name : 'Bar' "
6324       "    field { name:'bar' number:1 label:LABEL_REQUIRED type:TYPE_INT32 } "
6325       "  } "
6326       "}",
6327       "foo.proto: Foo.Bar.bar: TYPE: Required fields are not allowed in "
6328       "proto3.\n");
6329 
6330   // optional and repeated fields are OK.
6331   BuildFile(
6332       "name: 'foo.proto' "
6333       "syntax: 'proto3' "
6334       "message_type { "
6335       "  name: 'Foo' "
6336       "  field { name:'foo' number:1 label:LABEL_OPTIONAL type:TYPE_INT32 } "
6337       "  field { name:'bar' number:2 label:LABEL_REPEATED type:TYPE_INT32 } "
6338       "}");
6339 }
6340 
TEST_F(ValidationErrorTest,ValidateProto3DefaultValue)6341 TEST_F(ValidationErrorTest, ValidateProto3DefaultValue) {
6342   BuildFileWithErrors(
6343       "name: 'foo.proto' "
6344       "syntax: 'proto3' "
6345       "message_type { "
6346       "  name: 'Foo' "
6347       "  field { name:'foo' number:1 label:LABEL_OPTIONAL type:TYPE_INT32 "
6348       "          default_value: '1' }"
6349       "}",
6350       "foo.proto: Foo.foo: DEFAULT_VALUE: Explicit default values are not "
6351       "allowed in proto3.\n");
6352 
6353   BuildFileWithErrors(
6354       "name: 'foo.proto' "
6355       "syntax: 'proto3' "
6356       "message_type { "
6357       "  name: 'Foo' "
6358       "  nested_type { "
6359       "    name : 'Bar' "
6360       "    field { name:'bar' number:1 label:LABEL_OPTIONAL type:TYPE_INT32 "
6361       "            default_value: '1' }"
6362       "  } "
6363       "}",
6364       "foo.proto: Foo.Bar.bar: DEFAULT_VALUE: Explicit default values are not "
6365       "allowed in proto3.\n");
6366 }
6367 
TEST_F(ValidationErrorTest,ValidateProto3ExtensionRange)6368 TEST_F(ValidationErrorTest, ValidateProto3ExtensionRange) {
6369   BuildFileWithErrors(
6370       "name: 'foo.proto' "
6371       "syntax: 'proto3' "
6372       "message_type { "
6373       "  name: 'Foo' "
6374       "  field { name:'foo' number:1 label:LABEL_OPTIONAL type:TYPE_INT32 } "
6375       "  extension_range { start:10 end:100 } "
6376       "}",
6377       "foo.proto: Foo: NUMBER: Extension ranges are not allowed in "
6378       "proto3.\n");
6379 
6380   BuildFileWithErrors(
6381       "name: 'foo.proto' "
6382       "syntax: 'proto3' "
6383       "message_type { "
6384       "  name: 'Foo' "
6385       "  nested_type { "
6386       "    name : 'Bar' "
6387       "    field { name:'bar' number:1 label:LABEL_OPTIONAL type:TYPE_INT32 } "
6388       "    extension_range { start:10 end:100 } "
6389       "  } "
6390       "}",
6391       "foo.proto: Foo.Bar: NUMBER: Extension ranges are not allowed in "
6392       "proto3.\n");
6393 }
6394 
TEST_F(ValidationErrorTest,ValidateProto3MessageSetWireFormat)6395 TEST_F(ValidationErrorTest, ValidateProto3MessageSetWireFormat) {
6396   BuildFileWithErrors(
6397       "name: 'foo.proto' "
6398       "syntax: 'proto3' "
6399       "message_type { "
6400       "  name: 'Foo' "
6401       "  options { message_set_wire_format: true } "
6402       "}",
6403       "foo.proto: Foo: NAME: MessageSet is not supported "
6404       "in proto3.\n");
6405 }
6406 
TEST_F(ValidationErrorTest,ValidateProto3Enum)6407 TEST_F(ValidationErrorTest, ValidateProto3Enum) {
6408   BuildFileWithErrors(
6409       "name: 'foo.proto' "
6410       "syntax: 'proto3' "
6411       "enum_type { "
6412       "  name: 'FooEnum' "
6413       "  value { name: 'FOO_FOO' number:1 } "
6414       "}",
6415       "foo.proto: FooEnum: NUMBER: The first enum value must be "
6416       "zero in proto3.\n");
6417 
6418   BuildFileWithErrors(
6419       "name: 'foo.proto' "
6420       "syntax: 'proto3' "
6421       "message_type { "
6422       "  name: 'Foo' "
6423       "  enum_type { "
6424       "    name: 'FooEnum' "
6425       "    value { name: 'FOO_FOO' number:1 } "
6426       "  } "
6427       "}",
6428       "foo.proto: Foo.FooEnum: NUMBER: The first enum value must be "
6429       "zero in proto3.\n");
6430 
6431   // valid case.
6432   BuildFile(
6433       "name: 'foo.proto' "
6434       "syntax: 'proto3' "
6435       "enum_type { "
6436       "  name: 'FooEnum' "
6437       "  value { name: 'FOO_FOO' number:0 } "
6438       "}");
6439 }
6440 
TEST_F(ValidationErrorTest,ValidateProto3Group)6441 TEST_F(ValidationErrorTest, ValidateProto3Group) {
6442   BuildFileWithErrors(
6443       "name: 'foo.proto' "
6444       "syntax: 'proto3' "
6445       "message_type { "
6446       "  name: 'Foo' "
6447       "  nested_type { "
6448       "    name: 'FooGroup' "
6449       "  } "
6450       "  field { name:'foo_group' number: 1 label:LABEL_OPTIONAL "
6451       "          type: TYPE_GROUP type_name:'FooGroup' } "
6452       "}",
6453       "foo.proto: Foo.foo_group: TYPE: Groups are not supported in proto3 "
6454       "syntax.\n");
6455 }
6456 
6457 
TEST_F(ValidationErrorTest,ValidateProto3EnumFromProto2)6458 TEST_F(ValidationErrorTest, ValidateProto3EnumFromProto2) {
6459   // Define an enum in a proto2 file.
6460   BuildFile(
6461       "name: 'foo.proto' "
6462       "package: 'foo' "
6463       "syntax: 'proto2' "
6464       "enum_type { "
6465       "  name: 'FooEnum' "
6466       "  value { name: 'DEFAULT_OPTION' number:0 } "
6467       "}");
6468 
6469   // Now try to refer to it. (All tests in the fixture use the same pool, so we
6470   // can refer to the enum above in this definition.)
6471   BuildFileWithErrors(
6472       "name: 'bar.proto' "
6473       "dependency: 'foo.proto' "
6474       "syntax: 'proto3' "
6475       "message_type { "
6476       "  name: 'Foo' "
6477       "    field { name:'bar' number:1 label:LABEL_OPTIONAL type:TYPE_ENUM "
6478       "            type_name: 'foo.FooEnum' }"
6479       "}",
6480       "bar.proto: Foo.bar: TYPE: Enum type \"foo.FooEnum\" is not a proto3 "
6481       "enum, but is used in \"Foo\" which is a proto3 message type.\n");
6482 }
6483 
TEST_F(ValidationErrorTest,ValidateProto3Extension)6484 TEST_F(ValidationErrorTest, ValidateProto3Extension) {
6485   // Valid for options.
6486   DescriptorPool pool;
6487   FileDescriptorProto file_proto;
6488   // Add "google/protobuf/descriptor.proto".
6489   FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto);
6490   ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr);
6491   // Add "foo.proto":
6492   //   import "google/protobuf/descriptor.proto";
6493   //   extend google.protobuf.FieldOptions {
6494   //     optional int32 option1 = 1000;
6495   //   }
6496   file_proto.Clear();
6497   file_proto.set_name("foo.proto");
6498   file_proto.set_syntax("proto3");
6499   file_proto.add_dependency("google/protobuf/descriptor.proto");
6500   AddExtension(&file_proto, "google.protobuf.FieldOptions", "option1", 1000,
6501                FieldDescriptorProto::LABEL_OPTIONAL,
6502                FieldDescriptorProto::TYPE_INT32);
6503   ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr);
6504 
6505   // Copy and change the package of the descriptor.proto
6506   BuildFile(
6507       "name: 'google.protobuf.proto' "
6508       "syntax: 'proto2' "
6509       "message_type { "
6510       "  name: 'Container' extension_range { start: 1 end: 1000 } "
6511       "}");
6512   BuildFileWithErrors(
6513       "name: 'bar.proto' "
6514       "syntax: 'proto3' "
6515       "dependency: 'google.protobuf.proto' "
6516       "extension { "
6517       "  name: 'bar' number: 1 label: LABEL_OPTIONAL type: TYPE_INT32 "
6518       "  extendee: 'Container' "
6519       "}",
6520       "bar.proto: bar: EXTENDEE: Extensions in proto3 are only allowed for "
6521       "defining options.\n");
6522 }
6523 
6524 // Test that field names that may conflict in JSON is not allowed by protoc.
TEST_F(ValidationErrorTest,ValidateProto3JsonName)6525 TEST_F(ValidationErrorTest, ValidateProto3JsonName) {
6526   // The comparison is case-insensitive.
6527   BuildFileWithErrors(
6528       "name: 'foo.proto' "
6529       "syntax: 'proto3' "
6530       "message_type {"
6531       "  name: 'Foo'"
6532       "  field { name:'name' number:1 label:LABEL_OPTIONAL type:TYPE_INT32 }"
6533       "  field { name:'Name' number:2 label:LABEL_OPTIONAL type:TYPE_INT32 }"
6534       "}",
6535       "foo.proto: Foo: NAME: The JSON camel-case name of field \"Name\" "
6536       "conflicts with field \"name\". This is not allowed in proto3.\n");
6537   // Underscores are ignored.
6538   BuildFileWithErrors(
6539       "name: 'foo.proto' "
6540       "syntax: 'proto3' "
6541       "message_type {"
6542       "  name: 'Foo'"
6543       "  field { name:'ab' number:1 label:LABEL_OPTIONAL type:TYPE_INT32 }"
6544       "  field { name:'_a__b_' number:2 label:LABEL_OPTIONAL type:TYPE_INT32 }"
6545       "}",
6546       "foo.proto: Foo: NAME: The JSON camel-case name of field \"_a__b_\" "
6547       "conflicts with field \"ab\". This is not allowed in proto3.\n");
6548 }
6549 
6550 
TEST_F(ValidationErrorTest,UnusedImportWithOtherError)6551 TEST_F(ValidationErrorTest, UnusedImportWithOtherError) {
6552   BuildFile(
6553       "name: 'bar.proto' "
6554       "message_type {"
6555       "  name: 'Bar'"
6556       "}");
6557 
6558   pool_.AddUnusedImportTrackFile("foo.proto", true);
6559   BuildFileWithErrors(
6560       "name: 'foo.proto' "
6561       "dependency: 'bar.proto' "
6562       "message_type {"
6563       "  name: 'Foo'"
6564       "  extension { name:'foo' number:1 label:LABEL_OPTIONAL type:TYPE_INT32"
6565       "              extendee: 'Baz' }"
6566       "}",
6567 
6568       // Should not also contain unused import error.
6569       "foo.proto: Foo.foo: EXTENDEE: \"Baz\" is not defined.\n");
6570 }
6571 
6572 
6573 // ===================================================================
6574 // DescriptorDatabase
6575 
AddToDatabase(SimpleDescriptorDatabase * database,const char * file_text)6576 static void AddToDatabase(SimpleDescriptorDatabase* database,
6577                           const char* file_text) {
6578   FileDescriptorProto file_proto;
6579   EXPECT_TRUE(TextFormat::ParseFromString(file_text, &file_proto));
6580   database->Add(file_proto);
6581 }
6582 
6583 class DatabaseBackedPoolTest : public testing::Test {
6584  protected:
DatabaseBackedPoolTest()6585   DatabaseBackedPoolTest() {}
6586 
6587   SimpleDescriptorDatabase database_;
6588 
SetUp()6589   virtual void SetUp() {
6590     AddToDatabase(
6591         &database_,
6592         "name: 'foo.proto' "
6593         "message_type { name:'Foo' extension_range { start: 1 end: 100 } } "
6594         "enum_type { name:'TestEnum' value { name:'DUMMY' number:0 } } "
6595         "service { name:'TestService' } ");
6596     AddToDatabase(&database_,
6597                   "name: 'bar.proto' "
6598                   "dependency: 'foo.proto' "
6599                   "message_type { name:'Bar' } "
6600                   "extension { name:'foo_ext' extendee: '.Foo' number:5 "
6601                   "            label:LABEL_OPTIONAL type:TYPE_INT32 } ");
6602     // Baz has an undeclared dependency on Foo.
6603     AddToDatabase(
6604         &database_,
6605         "name: 'baz.proto' "
6606         "message_type { "
6607         "  name:'Baz' "
6608         "  field { name:'foo' number:1 label:LABEL_OPTIONAL type_name:'Foo' } "
6609         "}");
6610   }
6611 
6612   // We can't inject a file containing errors into a DescriptorPool, so we
6613   // need an actual mock DescriptorDatabase to test errors.
6614   class ErrorDescriptorDatabase : public DescriptorDatabase {
6615    public:
ErrorDescriptorDatabase()6616     ErrorDescriptorDatabase() {}
~ErrorDescriptorDatabase()6617     ~ErrorDescriptorDatabase() {}
6618 
6619     // implements DescriptorDatabase ---------------------------------
FindFileByName(const std::string & filename,FileDescriptorProto * output)6620     bool FindFileByName(const std::string& filename,
6621                         FileDescriptorProto* output) {
6622       // error.proto and error2.proto cyclically import each other.
6623       if (filename == "error.proto") {
6624         output->Clear();
6625         output->set_name("error.proto");
6626         output->add_dependency("error2.proto");
6627         return true;
6628       } else if (filename == "error2.proto") {
6629         output->Clear();
6630         output->set_name("error2.proto");
6631         output->add_dependency("error.proto");
6632         return true;
6633       } else {
6634         return false;
6635       }
6636     }
FindFileContainingSymbol(const std::string & symbol_name,FileDescriptorProto * output)6637     bool FindFileContainingSymbol(const std::string& symbol_name,
6638                                   FileDescriptorProto* output) {
6639       return false;
6640     }
FindFileContainingExtension(const std::string & containing_type,int field_number,FileDescriptorProto * output)6641     bool FindFileContainingExtension(const std::string& containing_type,
6642                                      int field_number,
6643                                      FileDescriptorProto* output) {
6644       return false;
6645     }
6646   };
6647 
6648   // A DescriptorDatabase that counts how many times each method has been
6649   // called and forwards to some other DescriptorDatabase.
6650   class CallCountingDatabase : public DescriptorDatabase {
6651    public:
CallCountingDatabase(DescriptorDatabase * wrapped_db)6652     CallCountingDatabase(DescriptorDatabase* wrapped_db)
6653         : wrapped_db_(wrapped_db) {
6654       Clear();
6655     }
~CallCountingDatabase()6656     ~CallCountingDatabase() {}
6657 
6658     DescriptorDatabase* wrapped_db_;
6659 
6660     int call_count_;
6661 
Clear()6662     void Clear() { call_count_ = 0; }
6663 
6664     // implements DescriptorDatabase ---------------------------------
FindFileByName(const std::string & filename,FileDescriptorProto * output)6665     bool FindFileByName(const std::string& filename,
6666                         FileDescriptorProto* output) {
6667       ++call_count_;
6668       return wrapped_db_->FindFileByName(filename, output);
6669     }
FindFileContainingSymbol(const std::string & symbol_name,FileDescriptorProto * output)6670     bool FindFileContainingSymbol(const std::string& symbol_name,
6671                                   FileDescriptorProto* output) {
6672       ++call_count_;
6673       return wrapped_db_->FindFileContainingSymbol(symbol_name, output);
6674     }
FindFileContainingExtension(const std::string & containing_type,int field_number,FileDescriptorProto * output)6675     bool FindFileContainingExtension(const std::string& containing_type,
6676                                      int field_number,
6677                                      FileDescriptorProto* output) {
6678       ++call_count_;
6679       return wrapped_db_->FindFileContainingExtension(containing_type,
6680                                                       field_number, output);
6681     }
6682   };
6683 
6684   // A DescriptorDatabase which falsely always returns foo.proto when searching
6685   // for any symbol or extension number.  This shouldn't cause the
6686   // DescriptorPool to reload foo.proto if it is already loaded.
6687   class FalsePositiveDatabase : public DescriptorDatabase {
6688    public:
FalsePositiveDatabase(DescriptorDatabase * wrapped_db)6689     FalsePositiveDatabase(DescriptorDatabase* wrapped_db)
6690         : wrapped_db_(wrapped_db) {}
~FalsePositiveDatabase()6691     ~FalsePositiveDatabase() {}
6692 
6693     DescriptorDatabase* wrapped_db_;
6694 
6695     // implements DescriptorDatabase ---------------------------------
FindFileByName(const std::string & filename,FileDescriptorProto * output)6696     bool FindFileByName(const std::string& filename,
6697                         FileDescriptorProto* output) {
6698       return wrapped_db_->FindFileByName(filename, output);
6699     }
FindFileContainingSymbol(const std::string & symbol_name,FileDescriptorProto * output)6700     bool FindFileContainingSymbol(const std::string& symbol_name,
6701                                   FileDescriptorProto* output) {
6702       return FindFileByName("foo.proto", output);
6703     }
FindFileContainingExtension(const std::string & containing_type,int field_number,FileDescriptorProto * output)6704     bool FindFileContainingExtension(const std::string& containing_type,
6705                                      int field_number,
6706                                      FileDescriptorProto* output) {
6707       return FindFileByName("foo.proto", output);
6708     }
6709   };
6710 };
6711 
TEST_F(DatabaseBackedPoolTest,FindFileByName)6712 TEST_F(DatabaseBackedPoolTest, FindFileByName) {
6713   DescriptorPool pool(&database_);
6714 
6715   const FileDescriptor* foo = pool.FindFileByName("foo.proto");
6716   ASSERT_TRUE(foo != nullptr);
6717   EXPECT_EQ("foo.proto", foo->name());
6718   ASSERT_EQ(1, foo->message_type_count());
6719   EXPECT_EQ("Foo", foo->message_type(0)->name());
6720 
6721   EXPECT_EQ(foo, pool.FindFileByName("foo.proto"));
6722 
6723   EXPECT_TRUE(pool.FindFileByName("no_such_file.proto") == nullptr);
6724 }
6725 
TEST_F(DatabaseBackedPoolTest,FindDependencyBeforeDependent)6726 TEST_F(DatabaseBackedPoolTest, FindDependencyBeforeDependent) {
6727   DescriptorPool pool(&database_);
6728 
6729   const FileDescriptor* foo = pool.FindFileByName("foo.proto");
6730   ASSERT_TRUE(foo != nullptr);
6731   EXPECT_EQ("foo.proto", foo->name());
6732   ASSERT_EQ(1, foo->message_type_count());
6733   EXPECT_EQ("Foo", foo->message_type(0)->name());
6734 
6735   const FileDescriptor* bar = pool.FindFileByName("bar.proto");
6736   ASSERT_TRUE(bar != nullptr);
6737   EXPECT_EQ("bar.proto", bar->name());
6738   ASSERT_EQ(1, bar->message_type_count());
6739   EXPECT_EQ("Bar", bar->message_type(0)->name());
6740 
6741   ASSERT_EQ(1, bar->dependency_count());
6742   EXPECT_EQ(foo, bar->dependency(0));
6743 }
6744 
TEST_F(DatabaseBackedPoolTest,FindDependentBeforeDependency)6745 TEST_F(DatabaseBackedPoolTest, FindDependentBeforeDependency) {
6746   DescriptorPool pool(&database_);
6747 
6748   const FileDescriptor* bar = pool.FindFileByName("bar.proto");
6749   ASSERT_TRUE(bar != nullptr);
6750   EXPECT_EQ("bar.proto", bar->name());
6751   ASSERT_EQ(1, bar->message_type_count());
6752   ASSERT_EQ("Bar", bar->message_type(0)->name());
6753 
6754   const FileDescriptor* foo = pool.FindFileByName("foo.proto");
6755   ASSERT_TRUE(foo != nullptr);
6756   EXPECT_EQ("foo.proto", foo->name());
6757   ASSERT_EQ(1, foo->message_type_count());
6758   ASSERT_EQ("Foo", foo->message_type(0)->name());
6759 
6760   ASSERT_EQ(1, bar->dependency_count());
6761   EXPECT_EQ(foo, bar->dependency(0));
6762 }
6763 
TEST_F(DatabaseBackedPoolTest,FindFileContainingSymbol)6764 TEST_F(DatabaseBackedPoolTest, FindFileContainingSymbol) {
6765   DescriptorPool pool(&database_);
6766 
6767   const FileDescriptor* file = pool.FindFileContainingSymbol("Foo");
6768   ASSERT_TRUE(file != nullptr);
6769   EXPECT_EQ("foo.proto", file->name());
6770   EXPECT_EQ(file, pool.FindFileByName("foo.proto"));
6771 
6772   EXPECT_TRUE(pool.FindFileContainingSymbol("NoSuchSymbol") == nullptr);
6773 }
6774 
TEST_F(DatabaseBackedPoolTest,FindMessageTypeByName)6775 TEST_F(DatabaseBackedPoolTest, FindMessageTypeByName) {
6776   DescriptorPool pool(&database_);
6777 
6778   const Descriptor* type = pool.FindMessageTypeByName("Foo");
6779   ASSERT_TRUE(type != nullptr);
6780   EXPECT_EQ("Foo", type->name());
6781   EXPECT_EQ(type->file(), pool.FindFileByName("foo.proto"));
6782 
6783   EXPECT_TRUE(pool.FindMessageTypeByName("NoSuchType") == nullptr);
6784 }
6785 
TEST_F(DatabaseBackedPoolTest,FindExtensionByNumber)6786 TEST_F(DatabaseBackedPoolTest, FindExtensionByNumber) {
6787   DescriptorPool pool(&database_);
6788 
6789   const Descriptor* foo = pool.FindMessageTypeByName("Foo");
6790   ASSERT_TRUE(foo != nullptr);
6791 
6792   const FieldDescriptor* extension = pool.FindExtensionByNumber(foo, 5);
6793   ASSERT_TRUE(extension != nullptr);
6794   EXPECT_EQ("foo_ext", extension->name());
6795   EXPECT_EQ(extension->file(), pool.FindFileByName("bar.proto"));
6796 
6797   EXPECT_TRUE(pool.FindExtensionByNumber(foo, 12) == nullptr);
6798 }
6799 
TEST_F(DatabaseBackedPoolTest,FindAllExtensions)6800 TEST_F(DatabaseBackedPoolTest, FindAllExtensions) {
6801   DescriptorPool pool(&database_);
6802 
6803   const Descriptor* foo = pool.FindMessageTypeByName("Foo");
6804 
6805   for (int i = 0; i < 2; ++i) {
6806     // Repeat the lookup twice, to check that we get consistent
6807     // results despite the fallback database lookup mutating the pool.
6808     std::vector<const FieldDescriptor*> extensions;
6809     pool.FindAllExtensions(foo, &extensions);
6810     ASSERT_EQ(1, extensions.size());
6811     EXPECT_EQ(5, extensions[0]->number());
6812   }
6813 }
6814 
TEST_F(DatabaseBackedPoolTest,ErrorWithoutErrorCollector)6815 TEST_F(DatabaseBackedPoolTest, ErrorWithoutErrorCollector) {
6816   ErrorDescriptorDatabase error_database;
6817   DescriptorPool pool(&error_database);
6818 
6819   std::vector<std::string> errors;
6820 
6821   {
6822     ScopedMemoryLog log;
6823     EXPECT_TRUE(pool.FindFileByName("error.proto") == nullptr);
6824     errors = log.GetMessages(ERROR);
6825   }
6826 
6827   EXPECT_FALSE(errors.empty());
6828 }
6829 
TEST_F(DatabaseBackedPoolTest,ErrorWithErrorCollector)6830 TEST_F(DatabaseBackedPoolTest, ErrorWithErrorCollector) {
6831   ErrorDescriptorDatabase error_database;
6832   MockErrorCollector error_collector;
6833   DescriptorPool pool(&error_database, &error_collector);
6834 
6835   EXPECT_TRUE(pool.FindFileByName("error.proto") == nullptr);
6836   EXPECT_EQ(
6837       "error.proto: error2.proto: IMPORT: File recursively imports itself: "
6838       "error.proto -> error2.proto -> error.proto\n"
6839       "error2.proto: error.proto: IMPORT: Import \"error.proto\" was not "
6840       "found or had errors.\n"
6841       "error.proto: error2.proto: IMPORT: Import \"error2.proto\" was not "
6842       "found or had errors.\n",
6843       error_collector.text_);
6844 }
6845 
TEST_F(DatabaseBackedPoolTest,UndeclaredDependencyOnUnbuiltType)6846 TEST_F(DatabaseBackedPoolTest, UndeclaredDependencyOnUnbuiltType) {
6847   // Check that we find and report undeclared dependencies on types that exist
6848   // in the descriptor database but that have not not been built yet.
6849   MockErrorCollector error_collector;
6850   DescriptorPool pool(&database_, &error_collector);
6851   EXPECT_TRUE(pool.FindMessageTypeByName("Baz") == nullptr);
6852   EXPECT_EQ(
6853       "baz.proto: Baz.foo: TYPE: \"Foo\" seems to be defined in \"foo.proto\", "
6854       "which is not imported by \"baz.proto\".  To use it here, please add "
6855       "the necessary import.\n",
6856       error_collector.text_);
6857 }
6858 
TEST_F(DatabaseBackedPoolTest,RollbackAfterError)6859 TEST_F(DatabaseBackedPoolTest, RollbackAfterError) {
6860   // Make sure that all traces of bad types are removed from the pool. This used
6861   // to be b/4529436, due to the fact that a symbol resolution failure could
6862   // potentially cause another file to be recursively built, which would trigger
6863   // a checkpoint _past_ possibly invalid symbols.
6864   // Baz is defined in the database, but the file is invalid because it is
6865   // missing a necessary import.
6866   DescriptorPool pool(&database_);
6867   EXPECT_TRUE(pool.FindMessageTypeByName("Baz") == nullptr);
6868   // Make sure that searching again for the file or the type fails.
6869   EXPECT_TRUE(pool.FindFileByName("baz.proto") == nullptr);
6870   EXPECT_TRUE(pool.FindMessageTypeByName("Baz") == nullptr);
6871 }
6872 
TEST_F(DatabaseBackedPoolTest,UnittestProto)6873 TEST_F(DatabaseBackedPoolTest, UnittestProto) {
6874   // Try to load all of unittest.proto from a DescriptorDatabase.  This should
6875   // thoroughly test all paths through DescriptorBuilder to insure that there
6876   // are no deadlocking problems when pool_->mutex_ is non-null.
6877   const FileDescriptor* original_file =
6878       protobuf_unittest::TestAllTypes::descriptor()->file();
6879 
6880   DescriptorPoolDatabase database(*DescriptorPool::generated_pool());
6881   DescriptorPool pool(&database);
6882   const FileDescriptor* file_from_database =
6883       pool.FindFileByName(original_file->name());
6884 
6885   ASSERT_TRUE(file_from_database != nullptr);
6886 
6887   FileDescriptorProto original_file_proto;
6888   original_file->CopyTo(&original_file_proto);
6889 
6890   FileDescriptorProto file_from_database_proto;
6891   file_from_database->CopyTo(&file_from_database_proto);
6892 
6893   EXPECT_EQ(original_file_proto.DebugString(),
6894             file_from_database_proto.DebugString());
6895 
6896   // Also verify that CopyTo() did not omit any information.
6897   EXPECT_EQ(original_file->DebugString(), file_from_database->DebugString());
6898 }
6899 
TEST_F(DatabaseBackedPoolTest,DoesntRetryDbUnnecessarily)6900 TEST_F(DatabaseBackedPoolTest, DoesntRetryDbUnnecessarily) {
6901   // Searching for a child of an existing descriptor should never fall back
6902   // to the DescriptorDatabase even if it isn't found, because we know all
6903   // children are already loaded.
6904   CallCountingDatabase call_counter(&database_);
6905   DescriptorPool pool(&call_counter);
6906 
6907   const FileDescriptor* file = pool.FindFileByName("foo.proto");
6908   ASSERT_TRUE(file != nullptr);
6909   const Descriptor* foo = pool.FindMessageTypeByName("Foo");
6910   ASSERT_TRUE(foo != nullptr);
6911   const EnumDescriptor* test_enum = pool.FindEnumTypeByName("TestEnum");
6912   ASSERT_TRUE(test_enum != nullptr);
6913   const ServiceDescriptor* test_service = pool.FindServiceByName("TestService");
6914   ASSERT_TRUE(test_service != nullptr);
6915 
6916   EXPECT_NE(0, call_counter.call_count_);
6917   call_counter.Clear();
6918 
6919   EXPECT_TRUE(foo->FindFieldByName("no_such_field") == nullptr);
6920   EXPECT_TRUE(foo->FindExtensionByName("no_such_extension") == nullptr);
6921   EXPECT_TRUE(foo->FindNestedTypeByName("NoSuchMessageType") == nullptr);
6922   EXPECT_TRUE(foo->FindEnumTypeByName("NoSuchEnumType") == nullptr);
6923   EXPECT_TRUE(foo->FindEnumValueByName("NO_SUCH_VALUE") == nullptr);
6924   EXPECT_TRUE(test_enum->FindValueByName("NO_SUCH_VALUE") == nullptr);
6925   EXPECT_TRUE(test_service->FindMethodByName("NoSuchMethod") == nullptr);
6926 
6927   EXPECT_TRUE(file->FindMessageTypeByName("NoSuchMessageType") == nullptr);
6928   EXPECT_TRUE(file->FindEnumTypeByName("NoSuchEnumType") == nullptr);
6929   EXPECT_TRUE(file->FindEnumValueByName("NO_SUCH_VALUE") == nullptr);
6930   EXPECT_TRUE(file->FindServiceByName("NO_SUCH_VALUE") == nullptr);
6931   EXPECT_TRUE(file->FindExtensionByName("no_such_extension") == nullptr);
6932 
6933   EXPECT_TRUE(pool.FindFileContainingSymbol("Foo.no.such.field") == nullptr);
6934   EXPECT_TRUE(pool.FindFileContainingSymbol("Foo.no_such_field") == nullptr);
6935   EXPECT_TRUE(pool.FindMessageTypeByName("Foo.NoSuchMessageType") == nullptr);
6936   EXPECT_TRUE(pool.FindFieldByName("Foo.no_such_field") == nullptr);
6937   EXPECT_TRUE(pool.FindExtensionByName("Foo.no_such_extension") == nullptr);
6938   EXPECT_TRUE(pool.FindEnumTypeByName("Foo.NoSuchEnumType") == nullptr);
6939   EXPECT_TRUE(pool.FindEnumValueByName("Foo.NO_SUCH_VALUE") == nullptr);
6940   EXPECT_TRUE(pool.FindMethodByName("TestService.NoSuchMethod") == nullptr);
6941 
6942   EXPECT_EQ(0, call_counter.call_count_);
6943 }
6944 
TEST_F(DatabaseBackedPoolTest,DoesntReloadFilesUncesessarily)6945 TEST_F(DatabaseBackedPoolTest, DoesntReloadFilesUncesessarily) {
6946   // If FindFileContainingSymbol() or FindFileContainingExtension() return a
6947   // file that is already in the DescriptorPool, it should not attempt to
6948   // reload the file.
6949   FalsePositiveDatabase false_positive_database(&database_);
6950   MockErrorCollector error_collector;
6951   DescriptorPool pool(&false_positive_database, &error_collector);
6952 
6953   // First make sure foo.proto is loaded.
6954   const Descriptor* foo = pool.FindMessageTypeByName("Foo");
6955   ASSERT_TRUE(foo != nullptr);
6956 
6957   // Try inducing false positives.
6958   EXPECT_TRUE(pool.FindMessageTypeByName("NoSuchSymbol") == nullptr);
6959   EXPECT_TRUE(pool.FindExtensionByNumber(foo, 22) == nullptr);
6960 
6961   // No errors should have been reported.  (If foo.proto was incorrectly
6962   // loaded multiple times, errors would have been reported.)
6963   EXPECT_EQ("", error_collector.text_);
6964 }
6965 
6966 // DescriptorDatabase that attempts to induce exponentially-bad performance
6967 // in DescriptorPool. For every positive N, the database contains a file
6968 // fileN.proto, which defines a message MessageN, which contains fields of
6969 // type MessageK for all K in [0,N). Message0 is not defined anywhere
6970 // (file0.proto exists, but is empty), so every other file and message type
6971 // will fail to build.
6972 //
6973 // If the DescriptorPool is not careful to memoize errors, an attempt to
6974 // build a descriptor for MessageN can require O(2^N) time.
6975 class ExponentialErrorDatabase : public DescriptorDatabase {
6976  public:
ExponentialErrorDatabase()6977   ExponentialErrorDatabase() {}
~ExponentialErrorDatabase()6978   ~ExponentialErrorDatabase() {}
6979 
6980   // implements DescriptorDatabase ---------------------------------
FindFileByName(const std::string & filename,FileDescriptorProto * output)6981   bool FindFileByName(const std::string& filename,
6982                       FileDescriptorProto* output) {
6983     int file_num = -1;
6984     FullMatch(filename, "file", ".proto", &file_num);
6985     if (file_num > -1) {
6986       return PopulateFile(file_num, output);
6987     } else {
6988       return false;
6989     }
6990   }
FindFileContainingSymbol(const std::string & symbol_name,FileDescriptorProto * output)6991   bool FindFileContainingSymbol(const std::string& symbol_name,
6992                                 FileDescriptorProto* output) {
6993     int file_num = -1;
6994     FullMatch(symbol_name, "Message", "", &file_num);
6995     if (file_num > 0) {
6996       return PopulateFile(file_num, output);
6997     } else {
6998       return false;
6999     }
7000   }
FindFileContainingExtension(const std::string & containing_type,int field_number,FileDescriptorProto * output)7001   bool FindFileContainingExtension(const std::string& containing_type,
7002                                    int field_number,
7003                                    FileDescriptorProto* output) {
7004     return false;
7005   }
7006 
7007  private:
FullMatch(const std::string & name,const std::string & begin_with,const std::string & end_with,int * file_num)7008   void FullMatch(const std::string& name, const std::string& begin_with,
7009                  const std::string& end_with, int* file_num) {
7010     int begin_size = begin_with.size();
7011     int end_size = end_with.size();
7012     if (name.substr(0, begin_size) != begin_with ||
7013         name.substr(name.size() - end_size, end_size) != end_with) {
7014       return;
7015     }
7016     safe_strto32(
7017         name.substr(begin_size, name.size() - end_size - begin_size), file_num);
7018   }
7019 
PopulateFile(int file_num,FileDescriptorProto * output)7020   bool PopulateFile(int file_num, FileDescriptorProto* output) {
7021     GOOGLE_CHECK_GE(file_num, 0);
7022     output->Clear();
7023     output->set_name(strings::Substitute("file$0.proto", file_num));
7024     // file0.proto doesn't define Message0
7025     if (file_num > 0) {
7026       DescriptorProto* message = output->add_message_type();
7027       message->set_name(strings::Substitute("Message$0", file_num));
7028       for (int i = 0; i < file_num; ++i) {
7029         output->add_dependency(strings::Substitute("file$0.proto", i));
7030         FieldDescriptorProto* field = message->add_field();
7031         field->set_name(strings::Substitute("field$0", i));
7032         field->set_number(i);
7033         field->set_label(FieldDescriptorProto::LABEL_OPTIONAL);
7034         field->set_type(FieldDescriptorProto::TYPE_MESSAGE);
7035         field->set_type_name(strings::Substitute("Message$0", i));
7036       }
7037     }
7038     return true;
7039   }
7040 };
7041 
TEST_F(DatabaseBackedPoolTest,DoesntReloadKnownBadFiles)7042 TEST_F(DatabaseBackedPoolTest, DoesntReloadKnownBadFiles) {
7043   ExponentialErrorDatabase error_database;
7044   DescriptorPool pool(&error_database);
7045 
7046   GOOGLE_LOG(INFO) << "A timeout in this test probably indicates a real bug.";
7047 
7048   EXPECT_TRUE(pool.FindFileByName("file40.proto") == nullptr);
7049   EXPECT_TRUE(pool.FindMessageTypeByName("Message40") == nullptr);
7050 }
7051 
TEST_F(DatabaseBackedPoolTest,DoesntFallbackOnWrongType)7052 TEST_F(DatabaseBackedPoolTest, DoesntFallbackOnWrongType) {
7053   // If a lookup finds a symbol of the wrong type (e.g. we pass a type name
7054   // to FindFieldByName()), we should fail fast, without checking the fallback
7055   // database.
7056   CallCountingDatabase call_counter(&database_);
7057   DescriptorPool pool(&call_counter);
7058 
7059   const FileDescriptor* file = pool.FindFileByName("foo.proto");
7060   ASSERT_TRUE(file != nullptr);
7061   const Descriptor* foo = pool.FindMessageTypeByName("Foo");
7062   ASSERT_TRUE(foo != nullptr);
7063   const EnumDescriptor* test_enum = pool.FindEnumTypeByName("TestEnum");
7064   ASSERT_TRUE(test_enum != nullptr);
7065 
7066   EXPECT_NE(0, call_counter.call_count_);
7067   call_counter.Clear();
7068 
7069   EXPECT_TRUE(pool.FindMessageTypeByName("TestEnum") == nullptr);
7070   EXPECT_TRUE(pool.FindFieldByName("Foo") == nullptr);
7071   EXPECT_TRUE(pool.FindExtensionByName("Foo") == nullptr);
7072   EXPECT_TRUE(pool.FindEnumTypeByName("Foo") == nullptr);
7073   EXPECT_TRUE(pool.FindEnumValueByName("Foo") == nullptr);
7074   EXPECT_TRUE(pool.FindServiceByName("Foo") == nullptr);
7075   EXPECT_TRUE(pool.FindMethodByName("Foo") == nullptr);
7076 
7077   EXPECT_EQ(0, call_counter.call_count_);
7078 }
7079 
7080 // ===================================================================
7081 
7082 class AbortingErrorCollector : public DescriptorPool::ErrorCollector {
7083  public:
AbortingErrorCollector()7084   AbortingErrorCollector() {}
7085 
AddError(const std::string & filename,const std::string & element_name,const Message * message,ErrorLocation location,const std::string & error_message)7086   virtual void AddError(const std::string& filename,
7087                         const std::string& element_name, const Message* message,
7088                         ErrorLocation location,
7089                         const std::string& error_message) {
7090     GOOGLE_LOG(FATAL) << "AddError() called unexpectedly: " << filename << " ["
7091                << element_name << "]: " << error_message;
7092   }
7093 
7094  private:
7095   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(AbortingErrorCollector);
7096 };
7097 
7098 // A source tree containing only one file.
7099 class SingletonSourceTree : public compiler::SourceTree {
7100  public:
SingletonSourceTree(const std::string & filename,const std::string & contents)7101   SingletonSourceTree(const std::string& filename, const std::string& contents)
7102       : filename_(filename), contents_(contents) {}
7103 
Open(const std::string & filename)7104   virtual io::ZeroCopyInputStream* Open(const std::string& filename) {
7105     return filename == filename_
7106                ? new io::ArrayInputStream(contents_.data(), contents_.size())
7107                : nullptr;
7108   }
7109 
7110  private:
7111   const std::string filename_;
7112   const std::string contents_;
7113 
7114   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SingletonSourceTree);
7115 };
7116 
7117 const char* const kSourceLocationTestInput =
7118     "syntax = \"proto2\";\n"
7119     "option java_package = \"com.foo.bar\";\n"
7120     "option (test_file_opt) = \"foobar\";\n"
7121     "message A {\n"
7122     "  option (test_msg_opt) = \"foobar\";\n"
7123     "  optional int32 a = 1 [deprecated = true];\n"
7124     "  message B {\n"
7125     "    required double b = 1 [(test_field_opt) = \"foobar\"];\n"
7126     "  }\n"
7127     "  oneof c {\n"
7128     "    option (test_oneof_opt) = \"foobar\";\n"
7129     "    string d = 2;\n"
7130     "    string e = 3;\n"
7131     "    string f = 4;\n"
7132     "  }\n"
7133     "}\n"
7134     "enum Indecision {\n"
7135     "  option (test_enum_opt) = 21;\n"
7136     "  option (test_enum_opt) = 42;\n"
7137     "  option (test_enum_opt) = 63;\n"
7138     "  YES   = 1 [(test_enumval_opt).a = 100];\n"
7139     "  NO    = 2 [(test_enumval_opt) = {a:200}];\n"
7140     "  MAYBE = 3;\n"
7141     "}\n"
7142     "service S {\n"
7143     "  option (test_svc_opt) = {a:100};\n"
7144     "  option (test_svc_opt) = {a:200};\n"
7145     "  option (test_svc_opt) = {a:300};\n"
7146     "  rpc Method(A) returns (A.B);\n"
7147     // Put an empty line here to make the source location range match.
7148     "\n"
7149     "  rpc OtherMethod(A) returns (A) {\n"
7150     "    option deprecated = true;\n"
7151     "    option (test_method_opt) = \"foobar\";\n"
7152     "  }\n"
7153     "}\n"
7154     "message MessageWithExtensions {\n"
7155     "  extensions 1000 to 2000, 2001 to max [(test_ext_opt) = \"foobar\"];\n"
7156     "}\n"
7157     "extend MessageWithExtensions {\n"
7158     "  repeated int32 int32_extension = 1001 [packed=true];\n"
7159     "}\n"
7160     "message C {\n"
7161     "  extend MessageWithExtensions {\n"
7162     "    optional C message_extension = 1002;\n"
7163     "  }\n"
7164     "}\n"
7165     "import \"google/protobuf/descriptor.proto\";\n"
7166     "extend google.protobuf.FileOptions {\n"
7167     "  optional string test_file_opt = 10101;\n"
7168     "}\n"
7169     "extend google.protobuf.MessageOptions {\n"
7170     "  optional string test_msg_opt = 10101;\n"
7171     "}\n"
7172     "extend google.protobuf.FieldOptions {\n"
7173     "  optional string test_field_opt = 10101;\n"
7174     "}\n"
7175     "extend google.protobuf.EnumOptions {\n"
7176     "  repeated int32 test_enum_opt = 10101;\n"
7177     "}\n"
7178     "extend google.protobuf.EnumValueOptions {\n"
7179     "  optional A test_enumval_opt = 10101;\n"
7180     "}\n"
7181     "extend google.protobuf.ServiceOptions {\n"
7182     "  repeated A test_svc_opt = 10101;\n"
7183     "}\n"
7184     "extend google.protobuf.MethodOptions {\n"
7185     "  optional string test_method_opt = 10101;\n"
7186     "}\n"
7187     "extend google.protobuf.OneofOptions {\n"
7188     "  optional string test_oneof_opt = 10101;\n"
7189     "}\n"
7190     "extend google.protobuf.ExtensionRangeOptions {\n"
7191     "  optional string test_ext_opt = 10101;\n"
7192     "}\n";
7193 
7194 class SourceLocationTest : public testing::Test {
7195  public:
SourceLocationTest()7196   SourceLocationTest()
7197       : source_tree_("/test/test.proto", kSourceLocationTestInput),
7198         simple_db_(),
7199         source_tree_db_(&source_tree_),
7200         merged_db_(&simple_db_, &source_tree_db_),
7201         pool_(&merged_db_, &collector_) {
7202     // we need descriptor.proto to be accessible by the pool
7203     // since our test file imports it
7204     FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto_);
7205     simple_db_.Add(file_proto_);
7206   }
7207 
PrintSourceLocation(const SourceLocation & loc)7208   static std::string PrintSourceLocation(const SourceLocation& loc) {
7209     return strings::Substitute("$0:$1-$2:$3", 1 + loc.start_line,
7210                             1 + loc.start_column, 1 + loc.end_line,
7211                             1 + loc.end_column);
7212   }
7213 
7214  private:
7215   FileDescriptorProto file_proto_;
7216   AbortingErrorCollector collector_;
7217   SingletonSourceTree source_tree_;
7218   SimpleDescriptorDatabase simple_db_;  // contains descriptor.proto
7219   compiler::SourceTreeDescriptorDatabase source_tree_db_;  // loads test.proto
7220   MergedDescriptorDatabase merged_db_;  // combines above two dbs
7221 
7222  protected:
7223   DescriptorPool pool_;
7224 
7225   // tag number of all custom options in above test file
7226   static constexpr int kCustomOptionFieldNumber = 10101;
7227   // tag number of field "a" in message type "A" in above test file
7228   static constexpr int kAFieldNumber = 1;
7229 };
7230 
7231 // TODO(adonovan): implement support for option fields and for
7232 // subparts of declarations.
7233 
TEST_F(SourceLocationTest,GetSourceLocation)7234 TEST_F(SourceLocationTest, GetSourceLocation) {
7235   SourceLocation loc;
7236 
7237   const FileDescriptor* file_desc =
7238       GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto"));
7239 
7240   const Descriptor* a_desc = file_desc->FindMessageTypeByName("A");
7241   EXPECT_TRUE(a_desc->GetSourceLocation(&loc));
7242   EXPECT_EQ("4:1-16:2", PrintSourceLocation(loc));
7243 
7244   const Descriptor* a_b_desc = a_desc->FindNestedTypeByName("B");
7245   EXPECT_TRUE(a_b_desc->GetSourceLocation(&loc));
7246   EXPECT_EQ("7:3-9:4", PrintSourceLocation(loc));
7247 
7248   const EnumDescriptor* e_desc = file_desc->FindEnumTypeByName("Indecision");
7249   EXPECT_TRUE(e_desc->GetSourceLocation(&loc));
7250   EXPECT_EQ("17:1-24:2", PrintSourceLocation(loc));
7251 
7252   const EnumValueDescriptor* yes_desc = e_desc->FindValueByName("YES");
7253   EXPECT_TRUE(yes_desc->GetSourceLocation(&loc));
7254   EXPECT_EQ("21:3-21:42", PrintSourceLocation(loc));
7255 
7256   const ServiceDescriptor* s_desc = file_desc->FindServiceByName("S");
7257   EXPECT_TRUE(s_desc->GetSourceLocation(&loc));
7258   EXPECT_EQ("25:1-35:2", PrintSourceLocation(loc));
7259 
7260   const MethodDescriptor* m_desc = s_desc->FindMethodByName("Method");
7261   EXPECT_TRUE(m_desc->GetSourceLocation(&loc));
7262   EXPECT_EQ("29:3-29:31", PrintSourceLocation(loc));
7263 
7264 }
7265 
TEST_F(SourceLocationTest,ExtensionSourceLocation)7266 TEST_F(SourceLocationTest, ExtensionSourceLocation) {
7267   SourceLocation loc;
7268 
7269   const FileDescriptor* file_desc =
7270       GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto"));
7271 
7272   const FieldDescriptor* int32_extension_desc =
7273       file_desc->FindExtensionByName("int32_extension");
7274   EXPECT_TRUE(int32_extension_desc->GetSourceLocation(&loc));
7275   EXPECT_EQ("40:3-40:55", PrintSourceLocation(loc));
7276 
7277   const Descriptor* c_desc = file_desc->FindMessageTypeByName("C");
7278   EXPECT_TRUE(c_desc->GetSourceLocation(&loc));
7279   EXPECT_EQ("42:1-46:2", PrintSourceLocation(loc));
7280 
7281   const FieldDescriptor* message_extension_desc =
7282       c_desc->FindExtensionByName("message_extension");
7283   EXPECT_TRUE(message_extension_desc->GetSourceLocation(&loc));
7284   EXPECT_EQ("44:5-44:41", PrintSourceLocation(loc));
7285 }
TEST_F(SourceLocationTest,InterpretedOptionSourceLocation)7286 TEST_F(SourceLocationTest, InterpretedOptionSourceLocation) {
7287   // This one's a doozy. It checks every kind of option, including
7288   // extension range options.
7289 
7290   // We are verifying that the file's source info contains correct
7291   // info for interpreted options and that it does *not* contain
7292   // any info for corresponding uninterpreted option path.
7293 
7294   SourceLocation loc;
7295 
7296   const FileDescriptor* file_desc =
7297       GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto"));
7298 
7299   // File options
7300   {
7301     int path[] = {FileDescriptorProto::kOptionsFieldNumber,
7302                   FileOptions::kJavaPackageFieldNumber};
7303     int unint[] = {FileDescriptorProto::kOptionsFieldNumber,
7304                    FileOptions::kUninterpretedOptionFieldNumber, 0};
7305 
7306     std::vector<int> vpath(path, path + 2);
7307     EXPECT_TRUE(file_desc->GetSourceLocation(vpath, &loc));
7308     EXPECT_EQ("2:1-2:37", PrintSourceLocation(loc));
7309 
7310     std::vector<int> vunint(unint, unint + 3);
7311     EXPECT_FALSE(file_desc->GetSourceLocation(vunint, &loc));
7312   }
7313   {
7314     int path[] = {FileDescriptorProto::kOptionsFieldNumber,
7315                   kCustomOptionFieldNumber};
7316     int unint[] = {FileDescriptorProto::kOptionsFieldNumber,
7317                    FileOptions::kUninterpretedOptionFieldNumber, 1};
7318     std::vector<int> vpath(path, path + 2);
7319     EXPECT_TRUE(file_desc->GetSourceLocation(vpath, &loc));
7320     EXPECT_EQ("3:1-3:35", PrintSourceLocation(loc));
7321 
7322     std::vector<int> vunint(unint, unint + 3);
7323     EXPECT_FALSE(file_desc->GetSourceLocation(vunint, &loc));
7324   }
7325 
7326   // Message option
7327   {
7328     int path[] = {FileDescriptorProto::kMessageTypeFieldNumber, 0,
7329                   DescriptorProto::kOptionsFieldNumber,
7330                   kCustomOptionFieldNumber};
7331     int unint[] = {FileDescriptorProto::kMessageTypeFieldNumber, 0,
7332                    DescriptorProto::kOptionsFieldNumber,
7333                    MessageOptions::kUninterpretedOptionFieldNumber, 0};
7334     std::vector<int> vpath(path, path + 4);
7335     EXPECT_TRUE(file_desc->GetSourceLocation(vpath, &loc));
7336     EXPECT_EQ("5:3-5:36", PrintSourceLocation(loc));
7337 
7338     std::vector<int> vunint(unint, unint + 5);
7339     EXPECT_FALSE(file_desc->GetSourceLocation(vunint, &loc));
7340   }
7341 
7342   // Field option
7343   {
7344     int path[] = {FileDescriptorProto::kMessageTypeFieldNumber,
7345                   0,
7346                   DescriptorProto::kFieldFieldNumber,
7347                   0,
7348                   FieldDescriptorProto::kOptionsFieldNumber,
7349                   FieldOptions::kDeprecatedFieldNumber};
7350     int unint[] = {FileDescriptorProto::kMessageTypeFieldNumber,
7351                    0,
7352                    DescriptorProto::kFieldFieldNumber,
7353                    0,
7354                    FieldDescriptorProto::kOptionsFieldNumber,
7355                    FieldOptions::kUninterpretedOptionFieldNumber,
7356                    0};
7357     std::vector<int> vpath(path, path + 6);
7358     EXPECT_TRUE(file_desc->GetSourceLocation(vpath, &loc));
7359     EXPECT_EQ("6:25-6:42", PrintSourceLocation(loc));
7360 
7361     std::vector<int> vunint(unint, unint + 7);
7362     EXPECT_FALSE(file_desc->GetSourceLocation(vunint, &loc));
7363   }
7364 
7365   // Nested message option
7366   {
7367     int path[] = {
7368         FileDescriptorProto::kMessageTypeFieldNumber, 0,
7369         DescriptorProto::kNestedTypeFieldNumber,      0,
7370         DescriptorProto::kFieldFieldNumber,           0,
7371         FieldDescriptorProto::kOptionsFieldNumber,    kCustomOptionFieldNumber};
7372     int unint[] = {FileDescriptorProto::kMessageTypeFieldNumber,
7373                    0,
7374                    DescriptorProto::kNestedTypeFieldNumber,
7375                    0,
7376                    DescriptorProto::kFieldFieldNumber,
7377                    0,
7378                    FieldDescriptorProto::kOptionsFieldNumber,
7379                    FieldOptions::kUninterpretedOptionFieldNumber,
7380                    0};
7381     std::vector<int> vpath(path, path + 8);
7382     EXPECT_TRUE(file_desc->GetSourceLocation(vpath, &loc));
7383     EXPECT_EQ("8:28-8:55", PrintSourceLocation(loc));
7384 
7385     std::vector<int> vunint(unint, unint + 9);
7386     EXPECT_FALSE(file_desc->GetSourceLocation(vunint, &loc));
7387   }
7388 
7389   // One-of option
7390   {
7391     int path[] = {
7392         FileDescriptorProto::kMessageTypeFieldNumber, 0,
7393         DescriptorProto::kOneofDeclFieldNumber,       0,
7394         OneofDescriptorProto::kOptionsFieldNumber,    kCustomOptionFieldNumber};
7395     int unint[] = {FileDescriptorProto::kMessageTypeFieldNumber,
7396                    0,
7397                    DescriptorProto::kOneofDeclFieldNumber,
7398                    0,
7399                    OneofDescriptorProto::kOptionsFieldNumber,
7400                    OneofOptions::kUninterpretedOptionFieldNumber,
7401                    0};
7402     std::vector<int> vpath(path, path + 6);
7403     EXPECT_TRUE(file_desc->GetSourceLocation(vpath, &loc));
7404     EXPECT_EQ("11:5-11:40", PrintSourceLocation(loc));
7405 
7406     std::vector<int> vunint(unint, unint + 7);
7407     EXPECT_FALSE(file_desc->GetSourceLocation(vunint, &loc));
7408   }
7409 
7410   // Enum option, repeated options
7411   {
7412     int path[] = {FileDescriptorProto::kEnumTypeFieldNumber, 0,
7413                   EnumDescriptorProto::kOptionsFieldNumber,
7414                   kCustomOptionFieldNumber, 0};
7415     int unint[] = {FileDescriptorProto::kEnumTypeFieldNumber, 0,
7416                    EnumDescriptorProto::kOptionsFieldNumber,
7417                    EnumOptions::kUninterpretedOptionFieldNumber, 0};
7418     std::vector<int> vpath(path, path + 5);
7419     EXPECT_TRUE(file_desc->GetSourceLocation(vpath, &loc));
7420     EXPECT_EQ("18:3-18:31", PrintSourceLocation(loc));
7421 
7422     std::vector<int> vunint(unint, unint + 5);
7423     EXPECT_FALSE(file_desc->GetSourceLocation(vunint, &loc));
7424   }
7425   {
7426     int path[] = {FileDescriptorProto::kEnumTypeFieldNumber, 0,
7427                   EnumDescriptorProto::kOptionsFieldNumber,
7428                   kCustomOptionFieldNumber, 1};
7429     int unint[] = {FileDescriptorProto::kEnumTypeFieldNumber, 0,
7430                    EnumDescriptorProto::kOptionsFieldNumber,
7431                    EnumOptions::kUninterpretedOptionFieldNumber, 1};
7432     std::vector<int> vpath(path, path + 5);
7433     EXPECT_TRUE(file_desc->GetSourceLocation(vpath, &loc));
7434     EXPECT_EQ("19:3-19:31", PrintSourceLocation(loc));
7435 
7436     std::vector<int> vunint(unint, unint + 5);
7437     EXPECT_FALSE(file_desc->GetSourceLocation(vunint, &loc));
7438   }
7439   {
7440     int path[] = {FileDescriptorProto::kEnumTypeFieldNumber, 0,
7441                   EnumDescriptorProto::kOptionsFieldNumber,
7442                   kCustomOptionFieldNumber, 2};
7443     int unint[] = {FileDescriptorProto::kEnumTypeFieldNumber, 0,
7444                    EnumDescriptorProto::kOptionsFieldNumber,
7445                    OneofOptions::kUninterpretedOptionFieldNumber, 2};
7446     std::vector<int> vpath(path, path + 5);
7447     EXPECT_TRUE(file_desc->GetSourceLocation(vpath, &loc));
7448     EXPECT_EQ("20:3-20:31", PrintSourceLocation(loc));
7449 
7450     std::vector<int> vunint(unint, unint + 5);
7451     EXPECT_FALSE(file_desc->GetSourceLocation(vunint, &loc));
7452   }
7453 
7454   // Enum value options
7455   {
7456     // option w/ message type that directly sets field
7457     int path[] = {FileDescriptorProto::kEnumTypeFieldNumber,
7458                   0,
7459                   EnumDescriptorProto::kValueFieldNumber,
7460                   0,
7461                   EnumValueDescriptorProto::kOptionsFieldNumber,
7462                   kCustomOptionFieldNumber,
7463                   kAFieldNumber};
7464     int unint[] = {FileDescriptorProto::kEnumTypeFieldNumber,
7465                    0,
7466                    EnumDescriptorProto::kValueFieldNumber,
7467                    0,
7468                    EnumValueDescriptorProto::kOptionsFieldNumber,
7469                    EnumValueOptions::kUninterpretedOptionFieldNumber,
7470                    0};
7471     std::vector<int> vpath(path, path + 7);
7472     EXPECT_TRUE(file_desc->GetSourceLocation(vpath, &loc));
7473     EXPECT_EQ("21:14-21:40", PrintSourceLocation(loc));
7474 
7475     std::vector<int> vunint(unint, unint + 7);
7476     EXPECT_FALSE(file_desc->GetSourceLocation(vunint, &loc));
7477   }
7478   {
7479     int path[] = {FileDescriptorProto::kEnumTypeFieldNumber,
7480                   0,
7481                   EnumDescriptorProto::kValueFieldNumber,
7482                   1,
7483                   EnumValueDescriptorProto::kOptionsFieldNumber,
7484                   kCustomOptionFieldNumber};
7485     int unint[] = {FileDescriptorProto::kEnumTypeFieldNumber,
7486                    0,
7487                    EnumDescriptorProto::kValueFieldNumber,
7488                    1,
7489                    EnumValueDescriptorProto::kOptionsFieldNumber,
7490                    EnumValueOptions::kUninterpretedOptionFieldNumber,
7491                    0};
7492     std::vector<int> vpath(path, path + 6);
7493     EXPECT_TRUE(file_desc->GetSourceLocation(vpath, &loc));
7494     EXPECT_EQ("22:14-22:42", PrintSourceLocation(loc));
7495 
7496     std::vector<int> vunint(unint, unint + 7);
7497     EXPECT_FALSE(file_desc->GetSourceLocation(vunint, &loc));
7498   }
7499 
7500   // Service option, repeated options
7501   {
7502     int path[] = {FileDescriptorProto::kServiceFieldNumber, 0,
7503                   ServiceDescriptorProto::kOptionsFieldNumber,
7504                   kCustomOptionFieldNumber, 0};
7505     int unint[] = {FileDescriptorProto::kServiceFieldNumber, 0,
7506                    ServiceDescriptorProto::kOptionsFieldNumber,
7507                    ServiceOptions::kUninterpretedOptionFieldNumber, 0};
7508     std::vector<int> vpath(path, path + 5);
7509     EXPECT_TRUE(file_desc->GetSourceLocation(vpath, &loc));
7510     EXPECT_EQ("26:3-26:35", PrintSourceLocation(loc));
7511 
7512     std::vector<int> vunint(unint, unint + 5);
7513     EXPECT_FALSE(file_desc->GetSourceLocation(vunint, &loc));
7514   }
7515   {
7516     int path[] = {FileDescriptorProto::kServiceFieldNumber, 0,
7517                   ServiceDescriptorProto::kOptionsFieldNumber,
7518                   kCustomOptionFieldNumber, 1};
7519     int unint[] = {FileDescriptorProto::kServiceFieldNumber, 0,
7520                    ServiceDescriptorProto::kOptionsFieldNumber,
7521                    ServiceOptions::kUninterpretedOptionFieldNumber, 1};
7522     std::vector<int> vpath(path, path + 5);
7523     EXPECT_TRUE(file_desc->GetSourceLocation(vpath, &loc));
7524     EXPECT_EQ("27:3-27:35", PrintSourceLocation(loc));
7525 
7526     std::vector<int> vunint(unint, unint + 5);
7527     EXPECT_FALSE(file_desc->GetSourceLocation(vunint, &loc));
7528   }
7529   {
7530     int path[] = {FileDescriptorProto::kServiceFieldNumber, 0,
7531                   ServiceDescriptorProto::kOptionsFieldNumber,
7532                   kCustomOptionFieldNumber, 2};
7533     int unint[] = {FileDescriptorProto::kServiceFieldNumber, 0,
7534                    ServiceDescriptorProto::kOptionsFieldNumber,
7535                    ServiceOptions::kUninterpretedOptionFieldNumber, 2};
7536     std::vector<int> vpath(path, path + 5);
7537     EXPECT_TRUE(file_desc->GetSourceLocation(vpath, &loc));
7538     EXPECT_EQ("28:3-28:35", PrintSourceLocation(loc));
7539 
7540     std::vector<int> vunint(unint, unint + 5);
7541     EXPECT_FALSE(file_desc->GetSourceLocation(vunint, &loc));
7542   }
7543 
7544   // Method options
7545   {
7546     int path[] = {FileDescriptorProto::kServiceFieldNumber,
7547                   0,
7548                   ServiceDescriptorProto::kMethodFieldNumber,
7549                   1,
7550                   MethodDescriptorProto::kOptionsFieldNumber,
7551                   MethodOptions::kDeprecatedFieldNumber};
7552     int unint[] = {FileDescriptorProto::kServiceFieldNumber,
7553                    0,
7554                    ServiceDescriptorProto::kMethodFieldNumber,
7555                    1,
7556                    MethodDescriptorProto::kOptionsFieldNumber,
7557                    MethodOptions::kUninterpretedOptionFieldNumber,
7558                    0};
7559     std::vector<int> vpath(path, path + 6);
7560     EXPECT_TRUE(file_desc->GetSourceLocation(vpath, &loc));
7561     EXPECT_EQ("32:5-32:30", PrintSourceLocation(loc));
7562 
7563     std::vector<int> vunint(unint, unint + 7);
7564     EXPECT_FALSE(file_desc->GetSourceLocation(vunint, &loc));
7565   }
7566   {
7567     int path[] = {
7568         FileDescriptorProto::kServiceFieldNumber,   0,
7569         ServiceDescriptorProto::kMethodFieldNumber, 1,
7570         MethodDescriptorProto::kOptionsFieldNumber, kCustomOptionFieldNumber};
7571     int unint[] = {FileDescriptorProto::kServiceFieldNumber,
7572                    0,
7573                    ServiceDescriptorProto::kMethodFieldNumber,
7574                    1,
7575                    MethodDescriptorProto::kOptionsFieldNumber,
7576                    MethodOptions::kUninterpretedOptionFieldNumber,
7577                    1};
7578     std::vector<int> vpath(path, path + 6);
7579     EXPECT_TRUE(file_desc->GetSourceLocation(vpath, &loc));
7580     EXPECT_EQ("33:5-33:41", PrintSourceLocation(loc));
7581 
7582     std::vector<int> vunint(unint, unint + 7);
7583     EXPECT_FALSE(file_desc->GetSourceLocation(vunint, &loc));
7584   }
7585 
7586   // Extension range options
7587   {
7588     int path[] = {FileDescriptorProto::kMessageTypeFieldNumber, 1,
7589                   DescriptorProto::kExtensionRangeFieldNumber, 0,
7590                   DescriptorProto_ExtensionRange::kOptionsFieldNumber};
7591     std::vector<int> vpath(path, path + 5);
7592     EXPECT_TRUE(file_desc->GetSourceLocation(vpath, &loc));
7593     EXPECT_EQ("37:40-37:67", PrintSourceLocation(loc));
7594   }
7595   {
7596     int path[] = {FileDescriptorProto::kMessageTypeFieldNumber,
7597                   1,
7598                   DescriptorProto::kExtensionRangeFieldNumber,
7599                   0,
7600                   DescriptorProto_ExtensionRange::kOptionsFieldNumber,
7601                   kCustomOptionFieldNumber};
7602     int unint[] = {FileDescriptorProto::kMessageTypeFieldNumber,
7603                    1,
7604                    DescriptorProto::kExtensionRangeFieldNumber,
7605                    0,
7606                    DescriptorProto_ExtensionRange::kOptionsFieldNumber,
7607                    ExtensionRangeOptions::kUninterpretedOptionFieldNumber,
7608                    0};
7609     std::vector<int> vpath(path, path + 6);
7610     EXPECT_TRUE(file_desc->GetSourceLocation(vpath, &loc));
7611     EXPECT_EQ("37:41-37:66", PrintSourceLocation(loc));
7612 
7613     std::vector<int> vunint(unint, unint + 7);
7614     EXPECT_FALSE(file_desc->GetSourceLocation(vunint, &loc));
7615   }
7616   {
7617     int path[] = {FileDescriptorProto::kMessageTypeFieldNumber,
7618                   1,
7619                   DescriptorProto::kExtensionRangeFieldNumber,
7620                   1,
7621                   DescriptorProto_ExtensionRange::kOptionsFieldNumber,
7622                   kCustomOptionFieldNumber};
7623     int unint[] = {FileDescriptorProto::kMessageTypeFieldNumber,
7624                    1,
7625                    DescriptorProto::kExtensionRangeFieldNumber,
7626                    1,
7627                    DescriptorProto_ExtensionRange::kOptionsFieldNumber,
7628                    ExtensionRangeOptions::kUninterpretedOptionFieldNumber,
7629                    0};
7630     std::vector<int> vpath(path, path + 6);
7631     EXPECT_TRUE(file_desc->GetSourceLocation(vpath, &loc));
7632     EXPECT_EQ("37:41-37:66", PrintSourceLocation(loc));
7633 
7634     std::vector<int> vunint(unint, unint + 7);
7635     EXPECT_FALSE(file_desc->GetSourceLocation(vunint, &loc));
7636   }
7637 
7638   // Field option on extension
7639   {
7640     int path[] = {FileDescriptorProto::kExtensionFieldNumber, 0,
7641                   FieldDescriptorProto::kOptionsFieldNumber,
7642                   FieldOptions::kPackedFieldNumber};
7643     int unint[] = {FileDescriptorProto::kExtensionFieldNumber, 0,
7644                    FieldDescriptorProto::kOptionsFieldNumber,
7645                    FieldOptions::kUninterpretedOptionFieldNumber, 0};
7646     std::vector<int> vpath(path, path + 4);
7647     EXPECT_TRUE(file_desc->GetSourceLocation(vpath, &loc));
7648     EXPECT_EQ("40:42-40:53", PrintSourceLocation(loc));
7649 
7650     std::vector<int> vunint(unint, unint + 5);
7651     EXPECT_FALSE(file_desc->GetSourceLocation(vunint, &loc));
7652   }
7653 }
7654 
7655 // Missing SourceCodeInfo doesn't cause crash:
TEST_F(SourceLocationTest,GetSourceLocation_MissingSourceCodeInfo)7656 TEST_F(SourceLocationTest, GetSourceLocation_MissingSourceCodeInfo) {
7657   SourceLocation loc;
7658 
7659   const FileDescriptor* file_desc =
7660       GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto"));
7661 
7662   FileDescriptorProto proto;
7663   file_desc->CopyTo(&proto);  // Note, this discards the SourceCodeInfo.
7664   EXPECT_FALSE(proto.has_source_code_info());
7665 
7666   DescriptorPool bad1_pool(&pool_);
7667   const FileDescriptor* bad1_file_desc =
7668       GOOGLE_CHECK_NOTNULL(bad1_pool.BuildFile(proto));
7669   const Descriptor* bad1_a_desc = bad1_file_desc->FindMessageTypeByName("A");
7670   EXPECT_FALSE(bad1_a_desc->GetSourceLocation(&loc));
7671 }
7672 
7673 // Corrupt SourceCodeInfo doesn't cause crash:
TEST_F(SourceLocationTest,GetSourceLocation_BogusSourceCodeInfo)7674 TEST_F(SourceLocationTest, GetSourceLocation_BogusSourceCodeInfo) {
7675   SourceLocation loc;
7676 
7677   const FileDescriptor* file_desc =
7678       GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto"));
7679 
7680   FileDescriptorProto proto;
7681   file_desc->CopyTo(&proto);  // Note, this discards the SourceCodeInfo.
7682   EXPECT_FALSE(proto.has_source_code_info());
7683   SourceCodeInfo_Location* loc_msg =
7684       proto.mutable_source_code_info()->add_location();
7685   loc_msg->add_path(1);
7686   loc_msg->add_path(2);
7687   loc_msg->add_path(3);
7688   loc_msg->add_span(4);
7689   loc_msg->add_span(5);
7690   loc_msg->add_span(6);
7691 
7692   DescriptorPool bad2_pool(&pool_);
7693   const FileDescriptor* bad2_file_desc =
7694       GOOGLE_CHECK_NOTNULL(bad2_pool.BuildFile(proto));
7695   const Descriptor* bad2_a_desc = bad2_file_desc->FindMessageTypeByName("A");
7696   EXPECT_FALSE(bad2_a_desc->GetSourceLocation(&loc));
7697 }
7698 
7699 // ===================================================================
7700 
7701 const char* const kCopySourceCodeInfoToTestInput =
7702     "syntax = \"proto2\";\n"
7703     "message Foo {}\n";
7704 
7705 // Required since source code information is not preserved by
7706 // FileDescriptorTest.
7707 class CopySourceCodeInfoToTest : public testing::Test {
7708  public:
CopySourceCodeInfoToTest()7709   CopySourceCodeInfoToTest()
7710       : source_tree_("/test/test.proto", kCopySourceCodeInfoToTestInput),
7711         db_(&source_tree_),
7712         pool_(&db_, &collector_) {}
7713 
7714  private:
7715   AbortingErrorCollector collector_;
7716   SingletonSourceTree source_tree_;
7717   compiler::SourceTreeDescriptorDatabase db_;
7718 
7719  protected:
7720   DescriptorPool pool_;
7721 };
7722 
TEST_F(CopySourceCodeInfoToTest,CopyTo_DoesNotCopySourceCodeInfo)7723 TEST_F(CopySourceCodeInfoToTest, CopyTo_DoesNotCopySourceCodeInfo) {
7724   const FileDescriptor* file_desc =
7725       GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto"));
7726   FileDescriptorProto file_desc_proto;
7727   ASSERT_FALSE(file_desc_proto.has_source_code_info());
7728 
7729   file_desc->CopyTo(&file_desc_proto);
7730   EXPECT_FALSE(file_desc_proto.has_source_code_info());
7731 }
7732 
TEST_F(CopySourceCodeInfoToTest,CopySourceCodeInfoTo)7733 TEST_F(CopySourceCodeInfoToTest, CopySourceCodeInfoTo) {
7734   const FileDescriptor* file_desc =
7735       GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto"));
7736   FileDescriptorProto file_desc_proto;
7737   ASSERT_FALSE(file_desc_proto.has_source_code_info());
7738 
7739   file_desc->CopySourceCodeInfoTo(&file_desc_proto);
7740   const SourceCodeInfo& info = file_desc_proto.source_code_info();
7741   ASSERT_EQ(4, info.location_size());
7742   // Get the Foo message location
7743   const SourceCodeInfo_Location& foo_location = info.location(2);
7744   ASSERT_EQ(2, foo_location.path_size());
7745   EXPECT_EQ(FileDescriptorProto::kMessageTypeFieldNumber, foo_location.path(0));
7746   EXPECT_EQ(0, foo_location.path(1));      // Foo is the first message defined
7747   ASSERT_EQ(3, foo_location.span_size());  // Foo spans one line
7748   EXPECT_EQ(1, foo_location.span(0));      // Foo is declared on line 1
7749   EXPECT_EQ(0, foo_location.span(1));      // Foo starts at column 0
7750   EXPECT_EQ(14, foo_location.span(2));     // Foo ends on column 14
7751 }
7752 
7753 // ===================================================================
7754 
7755 class LazilyBuildDependenciesTest : public testing::Test {
7756  public:
LazilyBuildDependenciesTest()7757   LazilyBuildDependenciesTest() : pool_(&db_, nullptr) {
7758     pool_.InternalSetLazilyBuildDependencies();
7759   }
7760 
ParseProtoAndAddToDb(const char * proto)7761   void ParseProtoAndAddToDb(const char* proto) {
7762     FileDescriptorProto tmp;
7763     ASSERT_TRUE(TextFormat::ParseFromString(proto, &tmp));
7764     db_.Add(tmp);
7765   }
7766 
ParseProtoAndAddToDb(const std::string & proto)7767   void ParseProtoAndAddToDb(const std::string& proto) {
7768     FileDescriptorProto tmp;
7769     ASSERT_TRUE(TextFormat::ParseFromString(proto, &tmp));
7770     db_.Add(tmp);
7771   }
7772 
AddSimpleMessageProtoFileToDb(const char * file_name,const char * message_name)7773   void AddSimpleMessageProtoFileToDb(const char* file_name,
7774                                      const char* message_name) {
7775     ParseProtoAndAddToDb("name: '" + std::string(file_name) +
7776                          ".proto' "
7777                          "package: \"protobuf_unittest\" "
7778                          "message_type { "
7779                          "  name:'" +
7780                          std::string(message_name) +
7781                          "' "
7782                          "  field { name:'a' number:1 "
7783                          "  label:LABEL_OPTIONAL "
7784                          "  type_name:'int32' } "
7785                          "}");
7786   }
7787 
AddSimpleEnumProtoFileToDb(const char * file_name,const char * enum_name,const char * enum_value_name)7788   void AddSimpleEnumProtoFileToDb(const char* file_name, const char* enum_name,
7789                                   const char* enum_value_name) {
7790     ParseProtoAndAddToDb("name: '" + std::string(file_name) +
7791                          ".proto' "
7792                          "package: 'protobuf_unittest' "
7793                          "enum_type { "
7794                          "  name:'" +
7795                          std::string(enum_name) +
7796                          "' "
7797                          "  value { name:'" +
7798                          std::string(enum_value_name) +
7799                          "' number:1 } "
7800                          "}");
7801   }
7802 
7803  protected:
7804   SimpleDescriptorDatabase db_;
7805   DescriptorPool pool_;
7806 };
7807 
TEST_F(LazilyBuildDependenciesTest,Message)7808 TEST_F(LazilyBuildDependenciesTest, Message) {
7809   ParseProtoAndAddToDb(
7810       "name: 'foo.proto' "
7811       "package: 'protobuf_unittest' "
7812       "dependency: 'bar.proto' "
7813       "message_type { "
7814       "  name:'Foo' "
7815       "  field { name:'bar' number:1 label:LABEL_OPTIONAL "
7816       "type_name:'.protobuf_unittest.Bar' } "
7817       "}");
7818   AddSimpleMessageProtoFileToDb("bar", "Bar");
7819 
7820   // Verify neither has been built yet.
7821   EXPECT_FALSE(pool_.InternalIsFileLoaded("foo.proto"));
7822   EXPECT_FALSE(pool_.InternalIsFileLoaded("bar.proto"));
7823 
7824   const FileDescriptor* file = pool_.FindFileByName("foo.proto");
7825 
7826   // Verify only foo gets built when asking for foo.proto
7827   EXPECT_TRUE(file != nullptr);
7828   EXPECT_TRUE(pool_.InternalIsFileLoaded("foo.proto"));
7829   EXPECT_FALSE(pool_.InternalIsFileLoaded("bar.proto"));
7830 
7831   // Verify calling FindFieldBy* works when the type of the field was
7832   // not built at cross link time. Verify this doesn't build the file
7833   // the field's type is defined in, as well.
7834   const Descriptor* desc = file->FindMessageTypeByName("Foo");
7835   const FieldDescriptor* field = desc->FindFieldByName("bar");
7836   EXPECT_TRUE(field != nullptr);
7837   EXPECT_EQ(field, desc->FindFieldByNumber(1));
7838   EXPECT_EQ(field, desc->FindFieldByLowercaseName("bar"));
7839   EXPECT_EQ(field, desc->FindFieldByCamelcaseName("bar"));
7840   EXPECT_FALSE(pool_.InternalIsFileLoaded("bar.proto"));
7841 
7842   // Finally, verify that if we call message_type() on the field, we will
7843   // build the file where the message is defined, and get a valid descriptor
7844   EXPECT_TRUE(field->message_type() != nullptr);
7845   EXPECT_TRUE(pool_.InternalIsFileLoaded("bar.proto"));
7846 }
7847 
TEST_F(LazilyBuildDependenciesTest,Enum)7848 TEST_F(LazilyBuildDependenciesTest, Enum) {
7849   ParseProtoAndAddToDb(
7850       "name: 'foo.proto' "
7851       "package: 'protobuf_unittest' "
7852       "dependency: 'enum1.proto' "
7853       "dependency: 'enum2.proto' "
7854       "message_type { "
7855       "  name:'Lazy' "
7856       "  field { name:'enum1' number:1 label:LABEL_OPTIONAL "
7857       "type_name:'.protobuf_unittest.Enum1' } "
7858       "  field { name:'enum2' number:1 label:LABEL_OPTIONAL "
7859       "type_name:'.protobuf_unittest.Enum2' } "
7860       "}");
7861   AddSimpleEnumProtoFileToDb("enum1", "Enum1", "ENUM1");
7862   AddSimpleEnumProtoFileToDb("enum2", "Enum2", "ENUM2");
7863 
7864   const FileDescriptor* file = pool_.FindFileByName("foo.proto");
7865 
7866   // Verify calling enum_type() on a field whose definition is not
7867   // yet built will build the file and return a descriptor.
7868   EXPECT_FALSE(pool_.InternalIsFileLoaded("enum1.proto"));
7869   const Descriptor* desc = file->FindMessageTypeByName("Lazy");
7870   EXPECT_TRUE(desc != nullptr);
7871   const FieldDescriptor* field = desc->FindFieldByName("enum1");
7872   EXPECT_TRUE(field != nullptr);
7873   EXPECT_TRUE(field->enum_type() != nullptr);
7874   EXPECT_TRUE(pool_.InternalIsFileLoaded("enum1.proto"));
7875 
7876   // Verify calling default_value_enum() on a field whose definition is not
7877   // yet built will build the file and return a descriptor to the value.
7878   EXPECT_FALSE(pool_.InternalIsFileLoaded("enum2.proto"));
7879   field = desc->FindFieldByName("enum2");
7880   EXPECT_TRUE(field != nullptr);
7881   EXPECT_TRUE(field->default_value_enum() != nullptr);
7882   EXPECT_TRUE(pool_.InternalIsFileLoaded("enum2.proto"));
7883 }
7884 
TEST_F(LazilyBuildDependenciesTest,Type)7885 TEST_F(LazilyBuildDependenciesTest, Type) {
7886   ParseProtoAndAddToDb(
7887       "name: 'foo.proto' "
7888       "package: 'protobuf_unittest' "
7889       "dependency: 'message1.proto' "
7890       "dependency: 'message2.proto' "
7891       "dependency: 'enum1.proto' "
7892       "dependency: 'enum2.proto' "
7893       "message_type { "
7894       "  name:'Lazy' "
7895       "  field { name:'message1' number:1 label:LABEL_OPTIONAL "
7896       "type_name:'.protobuf_unittest.Message1' } "
7897       "  field { name:'message2' number:1 label:LABEL_OPTIONAL "
7898       "type_name:'.protobuf_unittest.Message2' } "
7899       "  field { name:'enum1' number:1 label:LABEL_OPTIONAL "
7900       "type_name:'.protobuf_unittest.Enum1' } "
7901       "  field { name:'enum2' number:1 label:LABEL_OPTIONAL "
7902       "type_name:'.protobuf_unittest.Enum2' } "
7903       "}");
7904   AddSimpleMessageProtoFileToDb("message1", "Message1");
7905   AddSimpleMessageProtoFileToDb("message2", "Message2");
7906   AddSimpleEnumProtoFileToDb("enum1", "Enum1", "ENUM1");
7907   AddSimpleEnumProtoFileToDb("enum2", "Enum2", "ENUM2");
7908 
7909   const FileDescriptor* file = pool_.FindFileByName("foo.proto");
7910 
7911   // Verify calling type() on a field that is a message type will
7912   // build the type defined in another file.
7913   EXPECT_FALSE(pool_.InternalIsFileLoaded("message1.proto"));
7914   const Descriptor* desc = file->FindMessageTypeByName("Lazy");
7915   EXPECT_TRUE(desc != nullptr);
7916   const FieldDescriptor* field = desc->FindFieldByName("message1");
7917   EXPECT_TRUE(field != nullptr);
7918   EXPECT_EQ(field->type(), FieldDescriptor::TYPE_MESSAGE);
7919   EXPECT_TRUE(pool_.InternalIsFileLoaded("message1.proto"));
7920 
7921   // Verify calling cpp_type() on a field that is a message type will
7922   // build the type defined in another file.
7923   EXPECT_FALSE(pool_.InternalIsFileLoaded("message2.proto"));
7924   field = desc->FindFieldByName("message2");
7925   EXPECT_TRUE(field != nullptr);
7926   EXPECT_EQ(field->cpp_type(), FieldDescriptor::CPPTYPE_MESSAGE);
7927   EXPECT_TRUE(pool_.InternalIsFileLoaded("message2.proto"));
7928 
7929   // Verify calling type() on a field that is an enum type will
7930   // build the type defined in another file.
7931   EXPECT_FALSE(pool_.InternalIsFileLoaded("enum1.proto"));
7932   field = desc->FindFieldByName("enum1");
7933   EXPECT_TRUE(field != nullptr);
7934   EXPECT_EQ(field->type(), FieldDescriptor::TYPE_ENUM);
7935   EXPECT_TRUE(pool_.InternalIsFileLoaded("enum1.proto"));
7936 
7937   // Verify calling cpp_type() on a field that is an enum type will
7938   // build the type defined in another file.
7939   EXPECT_FALSE(pool_.InternalIsFileLoaded("enum2.proto"));
7940   field = desc->FindFieldByName("enum2");
7941   EXPECT_TRUE(field != nullptr);
7942   EXPECT_EQ(field->cpp_type(), FieldDescriptor::CPPTYPE_ENUM);
7943   EXPECT_TRUE(pool_.InternalIsFileLoaded("enum2.proto"));
7944 }
7945 
TEST_F(LazilyBuildDependenciesTest,Extension)7946 TEST_F(LazilyBuildDependenciesTest, Extension) {
7947   ParseProtoAndAddToDb(
7948       "name: 'foo.proto' "
7949       "package: 'protobuf_unittest' "
7950       "dependency: 'bar.proto' "
7951       "dependency: 'baz.proto' "
7952       "extension { extendee: '.protobuf_unittest.Bar' name:'bar' number:11"
7953       "            label:LABEL_OPTIONAL type_name:'.protobuf_unittest.Baz' }");
7954   ParseProtoAndAddToDb(
7955       "name: 'bar.proto' "
7956       "package: 'protobuf_unittest' "
7957       "message_type { "
7958       "  name:'Bar' "
7959       "  extension_range { start: 10 end: 20 }"
7960       "}");
7961   AddSimpleMessageProtoFileToDb("baz", "Baz");
7962 
7963   // Verify none have been built yet.
7964   EXPECT_FALSE(pool_.InternalIsFileLoaded("foo.proto"));
7965   EXPECT_FALSE(pool_.InternalIsFileLoaded("bar.proto"));
7966   EXPECT_FALSE(pool_.InternalIsFileLoaded("baz.proto"));
7967 
7968   const FileDescriptor* file = pool_.FindFileByName("foo.proto");
7969 
7970   // Verify foo.bar gets loaded, and bar.proto gets loaded
7971   // to register the extension. baz.proto should not get loaded.
7972   EXPECT_TRUE(file != nullptr);
7973   EXPECT_TRUE(pool_.InternalIsFileLoaded("foo.proto"));
7974   EXPECT_TRUE(pool_.InternalIsFileLoaded("bar.proto"));
7975   EXPECT_FALSE(pool_.InternalIsFileLoaded("baz.proto"));
7976 }
7977 
TEST_F(LazilyBuildDependenciesTest,Service)7978 TEST_F(LazilyBuildDependenciesTest, Service) {
7979   ParseProtoAndAddToDb(
7980       "name: 'foo.proto' "
7981       "package: 'protobuf_unittest' "
7982       "dependency: 'message1.proto' "
7983       "dependency: 'message2.proto' "
7984       "dependency: 'message3.proto' "
7985       "dependency: 'message4.proto' "
7986       "service {"
7987       "  name: 'LazyService'"
7988       "  method { name: 'A' input_type:  '.protobuf_unittest.Message1' "
7989       "                     output_type: '.protobuf_unittest.Message2' }"
7990       "}");
7991   AddSimpleMessageProtoFileToDb("message1", "Message1");
7992   AddSimpleMessageProtoFileToDb("message2", "Message2");
7993   AddSimpleMessageProtoFileToDb("message3", "Message3");
7994   AddSimpleMessageProtoFileToDb("message4", "Message4");
7995 
7996   const FileDescriptor* file = pool_.FindFileByName("foo.proto");
7997 
7998   // Verify calling FindServiceByName or FindMethodByName doesn't build the
7999   // files defining the input and output type, and input_type() and
8000   // output_type() does indeed build the appropriate files.
8001   const ServiceDescriptor* service = file->FindServiceByName("LazyService");
8002   EXPECT_TRUE(service != nullptr);
8003   const MethodDescriptor* method = service->FindMethodByName("A");
8004   EXPECT_FALSE(pool_.InternalIsFileLoaded("message1.proto"));
8005   EXPECT_FALSE(pool_.InternalIsFileLoaded("message2.proto"));
8006   EXPECT_TRUE(method != nullptr);
8007   EXPECT_TRUE(method->input_type() != nullptr);
8008   EXPECT_TRUE(pool_.InternalIsFileLoaded("message1.proto"));
8009   EXPECT_FALSE(pool_.InternalIsFileLoaded("message2.proto"));
8010   EXPECT_TRUE(method->output_type() != nullptr);
8011   EXPECT_TRUE(pool_.InternalIsFileLoaded("message2.proto"));
8012 }
8013 
8014 
TEST_F(LazilyBuildDependenciesTest,GeneratedFile)8015 TEST_F(LazilyBuildDependenciesTest, GeneratedFile) {
8016   // Most testing is done with custom pools with lazy dependencies forced on,
8017   // do some sanity checking that lazy imports is on by default for the
8018   // generated pool, and do custom options testing with generated to
8019   // be able to use the GetExtension ids for the custom options.
8020 
8021   // Verify none of the files are loaded yet.
8022   EXPECT_FALSE(DescriptorPool::generated_pool()->InternalIsFileLoaded(
8023       "google/protobuf/unittest_lazy_dependencies.proto"));
8024   EXPECT_FALSE(DescriptorPool::generated_pool()->InternalIsFileLoaded(
8025       "google/protobuf/unittest_lazy_dependencies_custom_option.proto"));
8026   EXPECT_FALSE(DescriptorPool::generated_pool()->InternalIsFileLoaded(
8027       "google/protobuf/unittest_lazy_dependencies_enum.proto"));
8028 
8029   // Verify calling autogenerated function to get a descriptor in the base
8030   // file will build that file but none of it's imports. This verifies that
8031   // lazily_build_dependencies_ is set on the generated pool, and also that
8032   // the generated function "descriptor()" doesn't somehow subvert the laziness
8033   // by manually loading the dependencies or something.
8034   EXPECT_TRUE(protobuf_unittest::lazy_imports::ImportedMessage::descriptor() !=
8035               nullptr);
8036   EXPECT_TRUE(DescriptorPool::generated_pool()->InternalIsFileLoaded(
8037       "google/protobuf/unittest_lazy_dependencies.proto"));
8038   EXPECT_FALSE(DescriptorPool::generated_pool()->InternalIsFileLoaded(
8039       "google/protobuf/unittest_lazy_dependencies_custom_option.proto"));
8040   EXPECT_FALSE(DescriptorPool::generated_pool()->InternalIsFileLoaded(
8041       "google/protobuf/unittest_lazy_dependencies_enum.proto"));
8042 
8043   // Verify custom options work when defined in an import that isn't loaded,
8044   // and that a non-default value of a custom option doesn't load the file
8045   // where that enum is defined.
8046   const MessageOptions& options =
8047       protobuf_unittest::lazy_imports::MessageCustomOption::descriptor()
8048           ->options();
8049   protobuf_unittest::lazy_imports::LazyEnum custom_option_value =
8050       options.GetExtension(protobuf_unittest::lazy_imports::lazy_enum_option);
8051 
8052   EXPECT_FALSE(DescriptorPool::generated_pool()->InternalIsFileLoaded(
8053       "google/protobuf/unittest_lazy_dependencies_custom_option.proto"));
8054   EXPECT_FALSE(DescriptorPool::generated_pool()->InternalIsFileLoaded(
8055       "google/protobuf/unittest_lazy_dependencies_enum.proto"));
8056   EXPECT_EQ(custom_option_value, protobuf_unittest::lazy_imports::LAZY_ENUM_1);
8057 
8058   const MessageOptions& options2 =
8059       protobuf_unittest::lazy_imports::MessageCustomOption2::descriptor()
8060           ->options();
8061   custom_option_value =
8062       options2.GetExtension(protobuf_unittest::lazy_imports::lazy_enum_option);
8063 
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   EXPECT_EQ(custom_option_value, protobuf_unittest::lazy_imports::LAZY_ENUM_0);
8069 }
8070 
TEST_F(LazilyBuildDependenciesTest,Dependency)8071 TEST_F(LazilyBuildDependenciesTest, Dependency) {
8072   ParseProtoAndAddToDb(
8073       "name: 'foo.proto' "
8074       "package: 'protobuf_unittest' "
8075       "dependency: 'bar.proto' "
8076       "message_type { "
8077       "  name:'Foo' "
8078       "  field { name:'bar' number:1 label:LABEL_OPTIONAL "
8079       "type_name:'.protobuf_unittest.Bar' } "
8080       "}");
8081   ParseProtoAndAddToDb(
8082       "name: 'bar.proto' "
8083       "package: 'protobuf_unittest' "
8084       "dependency: 'baz.proto' "
8085       "message_type { "
8086       "  name:'Bar' "
8087       "  field { name:'baz' number:1 label:LABEL_OPTIONAL "
8088       "type_name:'.protobuf_unittest.Baz' } "
8089       "}");
8090   AddSimpleMessageProtoFileToDb("baz", "Baz");
8091 
8092   const FileDescriptor* foo_file = pool_.FindFileByName("foo.proto");
8093   EXPECT_TRUE(foo_file != nullptr);
8094   // As expected, requesting foo.proto shouldn't build it's dependencies
8095   EXPECT_TRUE(pool_.InternalIsFileLoaded("foo.proto"));
8096   EXPECT_FALSE(pool_.InternalIsFileLoaded("bar.proto"));
8097   EXPECT_FALSE(pool_.InternalIsFileLoaded("baz.proto"));
8098 
8099   // Verify calling dependency(N) will build the dependency, but
8100   // not that file's dependencies.
8101   const FileDescriptor* bar_file = foo_file->dependency(0);
8102   EXPECT_TRUE(bar_file != nullptr);
8103   EXPECT_TRUE(pool_.InternalIsFileLoaded("bar.proto"));
8104   EXPECT_FALSE(pool_.InternalIsFileLoaded("baz.proto"));
8105 }
8106 
8107 // ===================================================================
8108 
8109 
8110 }  // namespace descriptor_unittest
8111 }  // namespace protobuf
8112 }  // namespace google
8113