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