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