1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc.  All rights reserved.
3 // http://code.google.com/p/protobuf/
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 <vector>
38 
39 #include <google/protobuf/compiler/importer.h>
40 #include <google/protobuf/unittest.pb.h>
41 #include <google/protobuf/unittest_custom_options.pb.h>
42 #include <google/protobuf/io/zero_copy_stream_impl.h>
43 #include <google/protobuf/descriptor.pb.h>
44 #include <google/protobuf/descriptor.h>
45 #include <google/protobuf/descriptor_database.h>
46 #include <google/protobuf/dynamic_message.h>
47 #include <google/protobuf/text_format.h>
48 #include <google/protobuf/stubs/strutil.h>
49 #include <google/protobuf/stubs/substitute.h>
50 
51 #include <google/protobuf/stubs/common.h>
52 #include <google/protobuf/testing/googletest.h>
53 #include <gtest/gtest.h>
54 
55 namespace google {
56 namespace protobuf {
57 
58 // Can't use an anonymous namespace here due to brokenness of Tru64 compiler.
59 namespace descriptor_unittest {
60 
61 // Some helpers to make assembling descriptors faster.
AddMessage(FileDescriptorProto * file,const string & name)62 DescriptorProto* AddMessage(FileDescriptorProto* file, const string& name) {
63   DescriptorProto* result = file->add_message_type();
64   result->set_name(name);
65   return result;
66 }
67 
AddNestedMessage(DescriptorProto * parent,const string & name)68 DescriptorProto* AddNestedMessage(DescriptorProto* parent, const string& name) {
69   DescriptorProto* result = parent->add_nested_type();
70   result->set_name(name);
71   return result;
72 }
73 
AddEnum(FileDescriptorProto * file,const string & name)74 EnumDescriptorProto* AddEnum(FileDescriptorProto* file, const string& name) {
75   EnumDescriptorProto* result = file->add_enum_type();
76   result->set_name(name);
77   return result;
78 }
79 
AddNestedEnum(DescriptorProto * parent,const string & name)80 EnumDescriptorProto* AddNestedEnum(DescriptorProto* parent,
81                                    const string& name) {
82   EnumDescriptorProto* result = parent->add_enum_type();
83   result->set_name(name);
84   return result;
85 }
86 
AddService(FileDescriptorProto * file,const string & name)87 ServiceDescriptorProto* AddService(FileDescriptorProto* file,
88                                    const string& name) {
89   ServiceDescriptorProto* result = file->add_service();
90   result->set_name(name);
91   return result;
92 }
93 
AddField(DescriptorProto * parent,const string & name,int number,FieldDescriptorProto::Label label,FieldDescriptorProto::Type type)94 FieldDescriptorProto* AddField(DescriptorProto* parent,
95                                const string& name, int number,
96                                FieldDescriptorProto::Label label,
97                                FieldDescriptorProto::Type type) {
98   FieldDescriptorProto* result = parent->add_field();
99   result->set_name(name);
100   result->set_number(number);
101   result->set_label(label);
102   result->set_type(type);
103   return result;
104 }
105 
AddExtension(FileDescriptorProto * file,const string & extendee,const string & name,int number,FieldDescriptorProto::Label label,FieldDescriptorProto::Type type)106 FieldDescriptorProto* AddExtension(FileDescriptorProto* file,
107                                    const string& extendee,
108                                    const string& name, int number,
109                                    FieldDescriptorProto::Label label,
110                                    FieldDescriptorProto::Type type) {
111   FieldDescriptorProto* result = file->add_extension();
112   result->set_name(name);
113   result->set_number(number);
114   result->set_label(label);
115   result->set_type(type);
116   result->set_extendee(extendee);
117   return result;
118 }
119 
AddNestedExtension(DescriptorProto * parent,const string & extendee,const string & name,int number,FieldDescriptorProto::Label label,FieldDescriptorProto::Type type)120 FieldDescriptorProto* AddNestedExtension(DescriptorProto* parent,
121                                          const string& extendee,
122                                          const string& name, int number,
123                                          FieldDescriptorProto::Label label,
124                                          FieldDescriptorProto::Type type) {
125   FieldDescriptorProto* result = parent->add_extension();
126   result->set_name(name);
127   result->set_number(number);
128   result->set_label(label);
129   result->set_type(type);
130   result->set_extendee(extendee);
131   return result;
132 }
133 
AddExtensionRange(DescriptorProto * parent,int start,int end)134 DescriptorProto::ExtensionRange* AddExtensionRange(DescriptorProto* parent,
135                                                    int start, int end) {
136   DescriptorProto::ExtensionRange* result = parent->add_extension_range();
137   result->set_start(start);
138   result->set_end(end);
139   return result;
140 }
141 
AddEnumValue(EnumDescriptorProto * enum_proto,const string & name,int number)142 EnumValueDescriptorProto* AddEnumValue(EnumDescriptorProto* enum_proto,
143                                        const string& name, int number) {
144   EnumValueDescriptorProto* result = enum_proto->add_value();
145   result->set_name(name);
146   result->set_number(number);
147   return result;
148 }
149 
AddMethod(ServiceDescriptorProto * service,const string & name,const string & input_type,const string & output_type)150 MethodDescriptorProto* AddMethod(ServiceDescriptorProto* service,
151                                  const string& name,
152                                  const string& input_type,
153                                  const string& output_type) {
154   MethodDescriptorProto* result = service->add_method();
155   result->set_name(name);
156   result->set_input_type(input_type);
157   result->set_output_type(output_type);
158   return result;
159 }
160 
161 // Empty enums technically aren't allowed.  We need to insert a dummy value
162 // into them.
AddEmptyEnum(FileDescriptorProto * file,const string & name)163 void AddEmptyEnum(FileDescriptorProto* file, const string& name) {
164   AddEnumValue(AddEnum(file, name), name + "_DUMMY", 1);
165 }
166 
167 // ===================================================================
168 
169 // Test simple files.
170 class FileDescriptorTest : public testing::Test {
171  protected:
SetUp()172   virtual void SetUp() {
173     // Build descriptors for the following definitions:
174     //
175     //   // in "foo.proto"
176     //   message FooMessage { extensions 1; }
177     //   enum FooEnum {FOO_ENUM_VALUE = 1;}
178     //   service FooService {}
179     //   extend FooMessage { optional int32 foo_extension = 1; }
180     //
181     //   // in "bar.proto"
182     //   package bar_package;
183     //   message BarMessage { extensions 1; }
184     //   enum BarEnum {BAR_ENUM_VALUE = 1;}
185     //   service BarService {}
186     //   extend BarMessage { optional int32 bar_extension = 1; }
187     //
188     // Also, we have an empty file "baz.proto".  This file's purpose is to
189     // make sure that even though it has the same package as foo.proto,
190     // searching it for members of foo.proto won't work.
191 
192     FileDescriptorProto foo_file;
193     foo_file.set_name("foo.proto");
194     AddExtensionRange(AddMessage(&foo_file, "FooMessage"), 1, 2);
195     AddEnumValue(AddEnum(&foo_file, "FooEnum"), "FOO_ENUM_VALUE", 1);
196     AddService(&foo_file, "FooService");
197     AddExtension(&foo_file, "FooMessage", "foo_extension", 1,
198                  FieldDescriptorProto::LABEL_OPTIONAL,
199                  FieldDescriptorProto::TYPE_INT32);
200 
201     FileDescriptorProto bar_file;
202     bar_file.set_name("bar.proto");
203     bar_file.set_package("bar_package");
204     bar_file.add_dependency("foo.proto");
205     AddExtensionRange(AddMessage(&bar_file, "BarMessage"), 1, 2);
206     AddEnumValue(AddEnum(&bar_file, "BarEnum"), "BAR_ENUM_VALUE", 1);
207     AddService(&bar_file, "BarService");
208     AddExtension(&bar_file, "bar_package.BarMessage", "bar_extension", 1,
209                  FieldDescriptorProto::LABEL_OPTIONAL,
210                  FieldDescriptorProto::TYPE_INT32);
211 
212     FileDescriptorProto baz_file;
213     baz_file.set_name("baz.proto");
214 
215     // Build the descriptors and get the pointers.
216     foo_file_ = pool_.BuildFile(foo_file);
217     ASSERT_TRUE(foo_file_ != NULL);
218 
219     bar_file_ = pool_.BuildFile(bar_file);
220     ASSERT_TRUE(bar_file_ != NULL);
221 
222     baz_file_ = pool_.BuildFile(baz_file);
223     ASSERT_TRUE(baz_file_ != NULL);
224 
225     ASSERT_EQ(1, foo_file_->message_type_count());
226     foo_message_ = foo_file_->message_type(0);
227     ASSERT_EQ(1, foo_file_->enum_type_count());
228     foo_enum_ = foo_file_->enum_type(0);
229     ASSERT_EQ(1, foo_enum_->value_count());
230     foo_enum_value_ = foo_enum_->value(0);
231     ASSERT_EQ(1, foo_file_->service_count());
232     foo_service_ = foo_file_->service(0);
233     ASSERT_EQ(1, foo_file_->extension_count());
234     foo_extension_ = foo_file_->extension(0);
235 
236     ASSERT_EQ(1, bar_file_->message_type_count());
237     bar_message_ = bar_file_->message_type(0);
238     ASSERT_EQ(1, bar_file_->enum_type_count());
239     bar_enum_ = bar_file_->enum_type(0);
240     ASSERT_EQ(1, bar_enum_->value_count());
241     bar_enum_value_ = bar_enum_->value(0);
242     ASSERT_EQ(1, bar_file_->service_count());
243     bar_service_ = bar_file_->service(0);
244     ASSERT_EQ(1, bar_file_->extension_count());
245     bar_extension_ = bar_file_->extension(0);
246   }
247 
248   DescriptorPool pool_;
249 
250   const FileDescriptor* foo_file_;
251   const FileDescriptor* bar_file_;
252   const FileDescriptor* baz_file_;
253 
254   const Descriptor*          foo_message_;
255   const EnumDescriptor*      foo_enum_;
256   const EnumValueDescriptor* foo_enum_value_;
257   const ServiceDescriptor*   foo_service_;
258   const FieldDescriptor*     foo_extension_;
259 
260   const Descriptor*          bar_message_;
261   const EnumDescriptor*      bar_enum_;
262   const EnumValueDescriptor* bar_enum_value_;
263   const ServiceDescriptor*   bar_service_;
264   const FieldDescriptor*     bar_extension_;
265 };
266 
TEST_F(FileDescriptorTest,Name)267 TEST_F(FileDescriptorTest, Name) {
268   EXPECT_EQ("foo.proto", foo_file_->name());
269   EXPECT_EQ("bar.proto", bar_file_->name());
270   EXPECT_EQ("baz.proto", baz_file_->name());
271 }
272 
TEST_F(FileDescriptorTest,Package)273 TEST_F(FileDescriptorTest, Package) {
274   EXPECT_EQ("", foo_file_->package());
275   EXPECT_EQ("bar_package", bar_file_->package());
276 }
277 
TEST_F(FileDescriptorTest,Dependencies)278 TEST_F(FileDescriptorTest, Dependencies) {
279   EXPECT_EQ(0, foo_file_->dependency_count());
280   EXPECT_EQ(1, bar_file_->dependency_count());
281   EXPECT_EQ(foo_file_, bar_file_->dependency(0));
282 }
283 
TEST_F(FileDescriptorTest,FindMessageTypeByName)284 TEST_F(FileDescriptorTest, FindMessageTypeByName) {
285   EXPECT_EQ(foo_message_, foo_file_->FindMessageTypeByName("FooMessage"));
286   EXPECT_EQ(bar_message_, bar_file_->FindMessageTypeByName("BarMessage"));
287 
288   EXPECT_TRUE(foo_file_->FindMessageTypeByName("BarMessage") == NULL);
289   EXPECT_TRUE(bar_file_->FindMessageTypeByName("FooMessage") == NULL);
290   EXPECT_TRUE(baz_file_->FindMessageTypeByName("FooMessage") == NULL);
291 
292   EXPECT_TRUE(foo_file_->FindMessageTypeByName("NoSuchMessage") == NULL);
293   EXPECT_TRUE(foo_file_->FindMessageTypeByName("FooEnum") == NULL);
294 }
295 
TEST_F(FileDescriptorTest,FindEnumTypeByName)296 TEST_F(FileDescriptorTest, FindEnumTypeByName) {
297   EXPECT_EQ(foo_enum_, foo_file_->FindEnumTypeByName("FooEnum"));
298   EXPECT_EQ(bar_enum_, bar_file_->FindEnumTypeByName("BarEnum"));
299 
300   EXPECT_TRUE(foo_file_->FindEnumTypeByName("BarEnum") == NULL);
301   EXPECT_TRUE(bar_file_->FindEnumTypeByName("FooEnum") == NULL);
302   EXPECT_TRUE(baz_file_->FindEnumTypeByName("FooEnum") == NULL);
303 
304   EXPECT_TRUE(foo_file_->FindEnumTypeByName("NoSuchEnum") == NULL);
305   EXPECT_TRUE(foo_file_->FindEnumTypeByName("FooMessage") == NULL);
306 }
307 
TEST_F(FileDescriptorTest,FindEnumValueByName)308 TEST_F(FileDescriptorTest, FindEnumValueByName) {
309   EXPECT_EQ(foo_enum_value_, foo_file_->FindEnumValueByName("FOO_ENUM_VALUE"));
310   EXPECT_EQ(bar_enum_value_, bar_file_->FindEnumValueByName("BAR_ENUM_VALUE"));
311 
312   EXPECT_TRUE(foo_file_->FindEnumValueByName("BAR_ENUM_VALUE") == NULL);
313   EXPECT_TRUE(bar_file_->FindEnumValueByName("FOO_ENUM_VALUE") == NULL);
314   EXPECT_TRUE(baz_file_->FindEnumValueByName("FOO_ENUM_VALUE") == NULL);
315 
316   EXPECT_TRUE(foo_file_->FindEnumValueByName("NO_SUCH_VALUE") == NULL);
317   EXPECT_TRUE(foo_file_->FindEnumValueByName("FooMessage") == NULL);
318 }
319 
TEST_F(FileDescriptorTest,FindServiceByName)320 TEST_F(FileDescriptorTest, FindServiceByName) {
321   EXPECT_EQ(foo_service_, foo_file_->FindServiceByName("FooService"));
322   EXPECT_EQ(bar_service_, bar_file_->FindServiceByName("BarService"));
323 
324   EXPECT_TRUE(foo_file_->FindServiceByName("BarService") == NULL);
325   EXPECT_TRUE(bar_file_->FindServiceByName("FooService") == NULL);
326   EXPECT_TRUE(baz_file_->FindServiceByName("FooService") == NULL);
327 
328   EXPECT_TRUE(foo_file_->FindServiceByName("NoSuchService") == NULL);
329   EXPECT_TRUE(foo_file_->FindServiceByName("FooMessage") == NULL);
330 }
331 
TEST_F(FileDescriptorTest,FindExtensionByName)332 TEST_F(FileDescriptorTest, FindExtensionByName) {
333   EXPECT_EQ(foo_extension_, foo_file_->FindExtensionByName("foo_extension"));
334   EXPECT_EQ(bar_extension_, bar_file_->FindExtensionByName("bar_extension"));
335 
336   EXPECT_TRUE(foo_file_->FindExtensionByName("bar_extension") == NULL);
337   EXPECT_TRUE(bar_file_->FindExtensionByName("foo_extension") == NULL);
338   EXPECT_TRUE(baz_file_->FindExtensionByName("foo_extension") == NULL);
339 
340   EXPECT_TRUE(foo_file_->FindExtensionByName("no_such_extension") == NULL);
341   EXPECT_TRUE(foo_file_->FindExtensionByName("FooMessage") == NULL);
342 }
343 
TEST_F(FileDescriptorTest,FindExtensionByNumber)344 TEST_F(FileDescriptorTest, FindExtensionByNumber) {
345   EXPECT_EQ(foo_extension_, pool_.FindExtensionByNumber(foo_message_, 1));
346   EXPECT_EQ(bar_extension_, pool_.FindExtensionByNumber(bar_message_, 1));
347 
348   EXPECT_TRUE(pool_.FindExtensionByNumber(foo_message_, 2) == NULL);
349 }
350 
TEST_F(FileDescriptorTest,BuildAgain)351 TEST_F(FileDescriptorTest, BuildAgain) {
352   // Test that if te call BuildFile again on the same input we get the same
353   // FileDescriptor back.
354   FileDescriptorProto file;
355   foo_file_->CopyTo(&file);
356   EXPECT_EQ(foo_file_, pool_.BuildFile(file));
357 
358   // But if we change the file then it won't work.
359   file.set_package("some.other.package");
360   EXPECT_TRUE(pool_.BuildFile(file) == NULL);
361 }
362 
363 // ===================================================================
364 
365 // Test simple flat messages and fields.
366 class DescriptorTest : public testing::Test {
367  protected:
SetUp()368   virtual void SetUp() {
369     // Build descriptors for the following definitions:
370     //
371     //   // in "foo.proto"
372     //   message TestForeign {}
373     //   enum TestEnum {}
374     //
375     //   message TestMessage {
376     //     required string      foo = 1;
377     //     optional TestEnum    bar = 6;
378     //     repeated TestForeign baz = 500000000;
379     //     optional group       qux = 15 {}
380     //   }
381     //
382     //   // in "bar.proto"
383     //   package corge.grault;
384     //   message TestMessage2 {
385     //     required string foo = 1;
386     //     required string bar = 2;
387     //     required string quux = 6;
388     //   }
389     //
390     // We cheat and use TestForeign as the type for qux rather than create
391     // an actual nested type.
392     //
393     // Since all primitive types (including string) use the same building
394     // code, there's no need to test each one individually.
395     //
396     // TestMessage2 is primarily here to test FindFieldByName and friends.
397     // All messages created from the same DescriptorPool share the same lookup
398     // table, so we need to insure that they don't interfere.
399 
400     FileDescriptorProto foo_file;
401     foo_file.set_name("foo.proto");
402     AddMessage(&foo_file, "TestForeign");
403     AddEmptyEnum(&foo_file, "TestEnum");
404 
405     DescriptorProto* message = AddMessage(&foo_file, "TestMessage");
406     AddField(message, "foo", 1,
407              FieldDescriptorProto::LABEL_REQUIRED,
408              FieldDescriptorProto::TYPE_STRING);
409     AddField(message, "bar", 6,
410              FieldDescriptorProto::LABEL_OPTIONAL,
411              FieldDescriptorProto::TYPE_ENUM)
412       ->set_type_name("TestEnum");
413     AddField(message, "baz", 500000000,
414              FieldDescriptorProto::LABEL_REPEATED,
415              FieldDescriptorProto::TYPE_MESSAGE)
416       ->set_type_name("TestForeign");
417     AddField(message, "qux", 15,
418              FieldDescriptorProto::LABEL_OPTIONAL,
419              FieldDescriptorProto::TYPE_GROUP)
420       ->set_type_name("TestForeign");
421 
422     FileDescriptorProto bar_file;
423     bar_file.set_name("bar.proto");
424     bar_file.set_package("corge.grault");
425 
426     DescriptorProto* message2 = AddMessage(&bar_file, "TestMessage2");
427     AddField(message2, "foo", 1,
428              FieldDescriptorProto::LABEL_REQUIRED,
429              FieldDescriptorProto::TYPE_STRING);
430     AddField(message2, "bar", 2,
431              FieldDescriptorProto::LABEL_REQUIRED,
432              FieldDescriptorProto::TYPE_STRING);
433     AddField(message2, "quux", 6,
434              FieldDescriptorProto::LABEL_REQUIRED,
435              FieldDescriptorProto::TYPE_STRING);
436 
437     // Build the descriptors and get the pointers.
438     foo_file_ = pool_.BuildFile(foo_file);
439     ASSERT_TRUE(foo_file_ != NULL);
440 
441     bar_file_ = pool_.BuildFile(bar_file);
442     ASSERT_TRUE(bar_file_ != NULL);
443 
444     ASSERT_EQ(1, foo_file_->enum_type_count());
445     enum_ = foo_file_->enum_type(0);
446 
447     ASSERT_EQ(2, foo_file_->message_type_count());
448     foreign_ = foo_file_->message_type(0);
449     message_ = foo_file_->message_type(1);
450 
451     ASSERT_EQ(4, message_->field_count());
452     foo_ = message_->field(0);
453     bar_ = message_->field(1);
454     baz_ = message_->field(2);
455     qux_ = message_->field(3);
456 
457     ASSERT_EQ(1, bar_file_->message_type_count());
458     message2_ = bar_file_->message_type(0);
459 
460     ASSERT_EQ(3, message2_->field_count());
461     foo2_  = message2_->field(0);
462     bar2_  = message2_->field(1);
463     quux2_ = message2_->field(2);
464   }
465 
466   DescriptorPool pool_;
467 
468   const FileDescriptor* foo_file_;
469   const FileDescriptor* bar_file_;
470 
471   const Descriptor* message_;
472   const Descriptor* message2_;
473   const Descriptor* foreign_;
474   const EnumDescriptor* enum_;
475 
476   const FieldDescriptor* foo_;
477   const FieldDescriptor* bar_;
478   const FieldDescriptor* baz_;
479   const FieldDescriptor* qux_;
480 
481   const FieldDescriptor* foo2_;
482   const FieldDescriptor* bar2_;
483   const FieldDescriptor* quux2_;
484 };
485 
TEST_F(DescriptorTest,Name)486 TEST_F(DescriptorTest, Name) {
487   EXPECT_EQ("TestMessage", message_->name());
488   EXPECT_EQ("TestMessage", message_->full_name());
489   EXPECT_EQ(foo_file_, message_->file());
490 
491   EXPECT_EQ("TestMessage2", message2_->name());
492   EXPECT_EQ("corge.grault.TestMessage2", message2_->full_name());
493   EXPECT_EQ(bar_file_, message2_->file());
494 }
495 
TEST_F(DescriptorTest,ContainingType)496 TEST_F(DescriptorTest, ContainingType) {
497   EXPECT_TRUE(message_->containing_type() == NULL);
498   EXPECT_TRUE(message2_->containing_type() == NULL);
499 }
500 
TEST_F(DescriptorTest,FieldsByIndex)501 TEST_F(DescriptorTest, FieldsByIndex) {
502   ASSERT_EQ(4, message_->field_count());
503   EXPECT_EQ(foo_, message_->field(0));
504   EXPECT_EQ(bar_, message_->field(1));
505   EXPECT_EQ(baz_, message_->field(2));
506   EXPECT_EQ(qux_, message_->field(3));
507 }
508 
TEST_F(DescriptorTest,FindFieldByName)509 TEST_F(DescriptorTest, FindFieldByName) {
510   // All messages in the same DescriptorPool share a single lookup table for
511   // fields.  So, in addition to testing that FindFieldByName finds the fields
512   // of the message, we need to test that it does *not* find the fields of
513   // *other* messages.
514 
515   EXPECT_EQ(foo_, message_->FindFieldByName("foo"));
516   EXPECT_EQ(bar_, message_->FindFieldByName("bar"));
517   EXPECT_EQ(baz_, message_->FindFieldByName("baz"));
518   EXPECT_EQ(qux_, message_->FindFieldByName("qux"));
519   EXPECT_TRUE(message_->FindFieldByName("no_such_field") == NULL);
520   EXPECT_TRUE(message_->FindFieldByName("quux") == NULL);
521 
522   EXPECT_EQ(foo2_ , message2_->FindFieldByName("foo" ));
523   EXPECT_EQ(bar2_ , message2_->FindFieldByName("bar" ));
524   EXPECT_EQ(quux2_, message2_->FindFieldByName("quux"));
525   EXPECT_TRUE(message2_->FindFieldByName("baz") == NULL);
526   EXPECT_TRUE(message2_->FindFieldByName("qux") == NULL);
527 }
528 
TEST_F(DescriptorTest,FindFieldByNumber)529 TEST_F(DescriptorTest, FindFieldByNumber) {
530   EXPECT_EQ(foo_, message_->FindFieldByNumber(1));
531   EXPECT_EQ(bar_, message_->FindFieldByNumber(6));
532   EXPECT_EQ(baz_, message_->FindFieldByNumber(500000000));
533   EXPECT_EQ(qux_, message_->FindFieldByNumber(15));
534   EXPECT_TRUE(message_->FindFieldByNumber(837592) == NULL);
535   EXPECT_TRUE(message_->FindFieldByNumber(2) == NULL);
536 
537   EXPECT_EQ(foo2_ , message2_->FindFieldByNumber(1));
538   EXPECT_EQ(bar2_ , message2_->FindFieldByNumber(2));
539   EXPECT_EQ(quux2_, message2_->FindFieldByNumber(6));
540   EXPECT_TRUE(message2_->FindFieldByNumber(15) == NULL);
541   EXPECT_TRUE(message2_->FindFieldByNumber(500000000) == NULL);
542 }
543 
TEST_F(DescriptorTest,FieldName)544 TEST_F(DescriptorTest, FieldName) {
545   EXPECT_EQ("foo", foo_->name());
546   EXPECT_EQ("bar", bar_->name());
547   EXPECT_EQ("baz", baz_->name());
548   EXPECT_EQ("qux", qux_->name());
549 }
550 
TEST_F(DescriptorTest,FieldFullName)551 TEST_F(DescriptorTest, FieldFullName) {
552   EXPECT_EQ("TestMessage.foo", foo_->full_name());
553   EXPECT_EQ("TestMessage.bar", bar_->full_name());
554   EXPECT_EQ("TestMessage.baz", baz_->full_name());
555   EXPECT_EQ("TestMessage.qux", qux_->full_name());
556 
557   EXPECT_EQ("corge.grault.TestMessage2.foo", foo2_->full_name());
558   EXPECT_EQ("corge.grault.TestMessage2.bar", bar2_->full_name());
559   EXPECT_EQ("corge.grault.TestMessage2.quux", quux2_->full_name());
560 }
561 
TEST_F(DescriptorTest,FieldFile)562 TEST_F(DescriptorTest, FieldFile) {
563   EXPECT_EQ(foo_file_, foo_->file());
564   EXPECT_EQ(foo_file_, bar_->file());
565   EXPECT_EQ(foo_file_, baz_->file());
566   EXPECT_EQ(foo_file_, qux_->file());
567 
568   EXPECT_EQ(bar_file_, foo2_->file());
569   EXPECT_EQ(bar_file_, bar2_->file());
570   EXPECT_EQ(bar_file_, quux2_->file());
571 }
572 
TEST_F(DescriptorTest,FieldIndex)573 TEST_F(DescriptorTest, FieldIndex) {
574   EXPECT_EQ(0, foo_->index());
575   EXPECT_EQ(1, bar_->index());
576   EXPECT_EQ(2, baz_->index());
577   EXPECT_EQ(3, qux_->index());
578 }
579 
TEST_F(DescriptorTest,FieldNumber)580 TEST_F(DescriptorTest, FieldNumber) {
581   EXPECT_EQ(        1, foo_->number());
582   EXPECT_EQ(        6, bar_->number());
583   EXPECT_EQ(500000000, baz_->number());
584   EXPECT_EQ(       15, qux_->number());
585 }
586 
TEST_F(DescriptorTest,FieldType)587 TEST_F(DescriptorTest, FieldType) {
588   EXPECT_EQ(FieldDescriptor::TYPE_STRING , foo_->type());
589   EXPECT_EQ(FieldDescriptor::TYPE_ENUM   , bar_->type());
590   EXPECT_EQ(FieldDescriptor::TYPE_MESSAGE, baz_->type());
591   EXPECT_EQ(FieldDescriptor::TYPE_GROUP  , qux_->type());
592 }
593 
TEST_F(DescriptorTest,FieldLabel)594 TEST_F(DescriptorTest, FieldLabel) {
595   EXPECT_EQ(FieldDescriptor::LABEL_REQUIRED, foo_->label());
596   EXPECT_EQ(FieldDescriptor::LABEL_OPTIONAL, bar_->label());
597   EXPECT_EQ(FieldDescriptor::LABEL_REPEATED, baz_->label());
598   EXPECT_EQ(FieldDescriptor::LABEL_OPTIONAL, qux_->label());
599 
600   EXPECT_TRUE (foo_->is_required());
601   EXPECT_FALSE(foo_->is_optional());
602   EXPECT_FALSE(foo_->is_repeated());
603 
604   EXPECT_FALSE(bar_->is_required());
605   EXPECT_TRUE (bar_->is_optional());
606   EXPECT_FALSE(bar_->is_repeated());
607 
608   EXPECT_FALSE(baz_->is_required());
609   EXPECT_FALSE(baz_->is_optional());
610   EXPECT_TRUE (baz_->is_repeated());
611 }
612 
TEST_F(DescriptorTest,FieldHasDefault)613 TEST_F(DescriptorTest, FieldHasDefault) {
614   EXPECT_FALSE(foo_->has_default_value());
615   EXPECT_FALSE(bar_->has_default_value());
616   EXPECT_FALSE(baz_->has_default_value());
617   EXPECT_FALSE(qux_->has_default_value());
618 }
619 
TEST_F(DescriptorTest,FieldContainingType)620 TEST_F(DescriptorTest, FieldContainingType) {
621   EXPECT_EQ(message_, foo_->containing_type());
622   EXPECT_EQ(message_, bar_->containing_type());
623   EXPECT_EQ(message_, baz_->containing_type());
624   EXPECT_EQ(message_, qux_->containing_type());
625 
626   EXPECT_EQ(message2_, foo2_ ->containing_type());
627   EXPECT_EQ(message2_, bar2_ ->containing_type());
628   EXPECT_EQ(message2_, quux2_->containing_type());
629 }
630 
TEST_F(DescriptorTest,FieldMessageType)631 TEST_F(DescriptorTest, FieldMessageType) {
632   EXPECT_TRUE(foo_->message_type() == NULL);
633   EXPECT_TRUE(bar_->message_type() == NULL);
634 
635   EXPECT_EQ(foreign_, baz_->message_type());
636   EXPECT_EQ(foreign_, qux_->message_type());
637 }
638 
TEST_F(DescriptorTest,FieldEnumType)639 TEST_F(DescriptorTest, FieldEnumType) {
640   EXPECT_TRUE(foo_->enum_type() == NULL);
641   EXPECT_TRUE(baz_->enum_type() == NULL);
642   EXPECT_TRUE(qux_->enum_type() == NULL);
643 
644   EXPECT_EQ(enum_, bar_->enum_type());
645 }
646 
647 // ===================================================================
648 
649 class StylizedFieldNamesTest : public testing::Test {
650  protected:
SetUp()651   void SetUp() {
652     FileDescriptorProto file;
653     file.set_name("foo.proto");
654 
655     AddExtensionRange(AddMessage(&file, "ExtendableMessage"), 1, 1000);
656 
657     DescriptorProto* message = AddMessage(&file, "TestMessage");
658     AddField(message, "foo_foo", 1,
659              FieldDescriptorProto::LABEL_OPTIONAL,
660              FieldDescriptorProto::TYPE_INT32);
661     AddField(message, "FooBar", 2,
662              FieldDescriptorProto::LABEL_OPTIONAL,
663              FieldDescriptorProto::TYPE_INT32);
664     AddField(message, "fooBaz", 3,
665              FieldDescriptorProto::LABEL_OPTIONAL,
666              FieldDescriptorProto::TYPE_INT32);
667     AddField(message, "fooFoo", 4,  // Camel-case conflict with foo_foo.
668              FieldDescriptorProto::LABEL_OPTIONAL,
669              FieldDescriptorProto::TYPE_INT32);
670     AddField(message, "foobar", 5,  // Lower-case conflict with FooBar.
671              FieldDescriptorProto::LABEL_OPTIONAL,
672              FieldDescriptorProto::TYPE_INT32);
673 
674     AddNestedExtension(message, "ExtendableMessage", "bar_foo", 1,
675                        FieldDescriptorProto::LABEL_OPTIONAL,
676                        FieldDescriptorProto::TYPE_INT32);
677     AddNestedExtension(message, "ExtendableMessage", "BarBar", 2,
678                        FieldDescriptorProto::LABEL_OPTIONAL,
679                        FieldDescriptorProto::TYPE_INT32);
680     AddNestedExtension(message, "ExtendableMessage", "BarBaz", 3,
681                        FieldDescriptorProto::LABEL_OPTIONAL,
682                        FieldDescriptorProto::TYPE_INT32);
683     AddNestedExtension(message, "ExtendableMessage", "barFoo", 4,  // Conflict
684                        FieldDescriptorProto::LABEL_OPTIONAL,
685                        FieldDescriptorProto::TYPE_INT32);
686     AddNestedExtension(message, "ExtendableMessage", "barbar", 5,  // Conflict
687                        FieldDescriptorProto::LABEL_OPTIONAL,
688                        FieldDescriptorProto::TYPE_INT32);
689 
690     AddExtension(&file, "ExtendableMessage", "baz_foo", 11,
691                  FieldDescriptorProto::LABEL_OPTIONAL,
692                  FieldDescriptorProto::TYPE_INT32);
693     AddExtension(&file, "ExtendableMessage", "BazBar", 12,
694                  FieldDescriptorProto::LABEL_OPTIONAL,
695                  FieldDescriptorProto::TYPE_INT32);
696     AddExtension(&file, "ExtendableMessage", "BazBaz", 13,
697                  FieldDescriptorProto::LABEL_OPTIONAL,
698                  FieldDescriptorProto::TYPE_INT32);
699     AddExtension(&file, "ExtendableMessage", "bazFoo", 14,  // Conflict
700                  FieldDescriptorProto::LABEL_OPTIONAL,
701                  FieldDescriptorProto::TYPE_INT32);
702     AddExtension(&file, "ExtendableMessage", "bazbar", 15,  // Conflict
703                  FieldDescriptorProto::LABEL_OPTIONAL,
704                  FieldDescriptorProto::TYPE_INT32);
705 
706     file_ = pool_.BuildFile(file);
707     ASSERT_TRUE(file_ != NULL);
708     ASSERT_EQ(2, file_->message_type_count());
709     message_ = file_->message_type(1);
710     ASSERT_EQ("TestMessage", message_->name());
711     ASSERT_EQ(5, message_->field_count());
712     ASSERT_EQ(5, message_->extension_count());
713     ASSERT_EQ(5, file_->extension_count());
714   }
715 
716   DescriptorPool pool_;
717   const FileDescriptor* file_;
718   const Descriptor* message_;
719 };
720 
TEST_F(StylizedFieldNamesTest,LowercaseName)721 TEST_F(StylizedFieldNamesTest, LowercaseName) {
722   EXPECT_EQ("foo_foo", message_->field(0)->lowercase_name());
723   EXPECT_EQ("foobar" , message_->field(1)->lowercase_name());
724   EXPECT_EQ("foobaz" , message_->field(2)->lowercase_name());
725   EXPECT_EQ("foofoo" , message_->field(3)->lowercase_name());
726   EXPECT_EQ("foobar" , message_->field(4)->lowercase_name());
727 
728   EXPECT_EQ("bar_foo", message_->extension(0)->lowercase_name());
729   EXPECT_EQ("barbar" , message_->extension(1)->lowercase_name());
730   EXPECT_EQ("barbaz" , message_->extension(2)->lowercase_name());
731   EXPECT_EQ("barfoo" , message_->extension(3)->lowercase_name());
732   EXPECT_EQ("barbar" , message_->extension(4)->lowercase_name());
733 
734   EXPECT_EQ("baz_foo", file_->extension(0)->lowercase_name());
735   EXPECT_EQ("bazbar" , file_->extension(1)->lowercase_name());
736   EXPECT_EQ("bazbaz" , file_->extension(2)->lowercase_name());
737   EXPECT_EQ("bazfoo" , file_->extension(3)->lowercase_name());
738   EXPECT_EQ("bazbar" , file_->extension(4)->lowercase_name());
739 }
740 
TEST_F(StylizedFieldNamesTest,CamelcaseName)741 TEST_F(StylizedFieldNamesTest, CamelcaseName) {
742   EXPECT_EQ("fooFoo", message_->field(0)->camelcase_name());
743   EXPECT_EQ("fooBar", message_->field(1)->camelcase_name());
744   EXPECT_EQ("fooBaz", message_->field(2)->camelcase_name());
745   EXPECT_EQ("fooFoo", message_->field(3)->camelcase_name());
746   EXPECT_EQ("foobar", message_->field(4)->camelcase_name());
747 
748   EXPECT_EQ("barFoo", message_->extension(0)->camelcase_name());
749   EXPECT_EQ("barBar", message_->extension(1)->camelcase_name());
750   EXPECT_EQ("barBaz", message_->extension(2)->camelcase_name());
751   EXPECT_EQ("barFoo", message_->extension(3)->camelcase_name());
752   EXPECT_EQ("barbar", message_->extension(4)->camelcase_name());
753 
754   EXPECT_EQ("bazFoo", file_->extension(0)->camelcase_name());
755   EXPECT_EQ("bazBar", file_->extension(1)->camelcase_name());
756   EXPECT_EQ("bazBaz", file_->extension(2)->camelcase_name());
757   EXPECT_EQ("bazFoo", file_->extension(3)->camelcase_name());
758   EXPECT_EQ("bazbar", file_->extension(4)->camelcase_name());
759 }
760 
TEST_F(StylizedFieldNamesTest,FindByLowercaseName)761 TEST_F(StylizedFieldNamesTest, FindByLowercaseName) {
762   EXPECT_EQ(message_->field(0),
763             message_->FindFieldByLowercaseName("foo_foo"));
764   EXPECT_EQ(message_->field(1),
765             message_->FindFieldByLowercaseName("foobar"));
766   EXPECT_EQ(message_->field(2),
767             message_->FindFieldByLowercaseName("foobaz"));
768   EXPECT_TRUE(message_->FindFieldByLowercaseName("FooBar") == NULL);
769   EXPECT_TRUE(message_->FindFieldByLowercaseName("fooBaz") == NULL);
770   EXPECT_TRUE(message_->FindFieldByLowercaseName("bar_foo") == NULL);
771   EXPECT_TRUE(message_->FindFieldByLowercaseName("nosuchfield") == NULL);
772 
773   EXPECT_EQ(message_->extension(0),
774             message_->FindExtensionByLowercaseName("bar_foo"));
775   EXPECT_EQ(message_->extension(1),
776             message_->FindExtensionByLowercaseName("barbar"));
777   EXPECT_EQ(message_->extension(2),
778             message_->FindExtensionByLowercaseName("barbaz"));
779   EXPECT_TRUE(message_->FindExtensionByLowercaseName("BarBar") == NULL);
780   EXPECT_TRUE(message_->FindExtensionByLowercaseName("barBaz") == NULL);
781   EXPECT_TRUE(message_->FindExtensionByLowercaseName("foo_foo") == NULL);
782   EXPECT_TRUE(message_->FindExtensionByLowercaseName("nosuchfield") == NULL);
783 
784   EXPECT_EQ(file_->extension(0),
785             file_->FindExtensionByLowercaseName("baz_foo"));
786   EXPECT_EQ(file_->extension(1),
787             file_->FindExtensionByLowercaseName("bazbar"));
788   EXPECT_EQ(file_->extension(2),
789             file_->FindExtensionByLowercaseName("bazbaz"));
790   EXPECT_TRUE(file_->FindExtensionByLowercaseName("BazBar") == NULL);
791   EXPECT_TRUE(file_->FindExtensionByLowercaseName("bazBaz") == NULL);
792   EXPECT_TRUE(file_->FindExtensionByLowercaseName("nosuchfield") == NULL);
793 }
794 
TEST_F(StylizedFieldNamesTest,FindByCamelcaseName)795 TEST_F(StylizedFieldNamesTest, FindByCamelcaseName) {
796   EXPECT_EQ(message_->field(0),
797             message_->FindFieldByCamelcaseName("fooFoo"));
798   EXPECT_EQ(message_->field(1),
799             message_->FindFieldByCamelcaseName("fooBar"));
800   EXPECT_EQ(message_->field(2),
801             message_->FindFieldByCamelcaseName("fooBaz"));
802   EXPECT_TRUE(message_->FindFieldByCamelcaseName("foo_foo") == NULL);
803   EXPECT_TRUE(message_->FindFieldByCamelcaseName("FooBar") == NULL);
804   EXPECT_TRUE(message_->FindFieldByCamelcaseName("barFoo") == NULL);
805   EXPECT_TRUE(message_->FindFieldByCamelcaseName("nosuchfield") == NULL);
806 
807   EXPECT_EQ(message_->extension(0),
808             message_->FindExtensionByCamelcaseName("barFoo"));
809   EXPECT_EQ(message_->extension(1),
810             message_->FindExtensionByCamelcaseName("barBar"));
811   EXPECT_EQ(message_->extension(2),
812             message_->FindExtensionByCamelcaseName("barBaz"));
813   EXPECT_TRUE(message_->FindExtensionByCamelcaseName("bar_foo") == NULL);
814   EXPECT_TRUE(message_->FindExtensionByCamelcaseName("BarBar") == NULL);
815   EXPECT_TRUE(message_->FindExtensionByCamelcaseName("fooFoo") == NULL);
816   EXPECT_TRUE(message_->FindExtensionByCamelcaseName("nosuchfield") == NULL);
817 
818   EXPECT_EQ(file_->extension(0),
819             file_->FindExtensionByCamelcaseName("bazFoo"));
820   EXPECT_EQ(file_->extension(1),
821             file_->FindExtensionByCamelcaseName("bazBar"));
822   EXPECT_EQ(file_->extension(2),
823             file_->FindExtensionByCamelcaseName("bazBaz"));
824   EXPECT_TRUE(file_->FindExtensionByCamelcaseName("baz_foo") == NULL);
825   EXPECT_TRUE(file_->FindExtensionByCamelcaseName("BazBar") == NULL);
826   EXPECT_TRUE(file_->FindExtensionByCamelcaseName("nosuchfield") == NULL);
827 }
828 
829 // ===================================================================
830 
831 // Test enum descriptors.
832 class EnumDescriptorTest : public testing::Test {
833  protected:
SetUp()834   virtual void SetUp() {
835     // Build descriptors for the following definitions:
836     //
837     //   // in "foo.proto"
838     //   enum TestEnum {
839     //     FOO = 1;
840     //     BAR = 2;
841     //   }
842     //
843     //   // in "bar.proto"
844     //   package corge.grault;
845     //   enum TestEnum2 {
846     //     FOO = 1;
847     //     BAZ = 3;
848     //   }
849     //
850     // TestEnum2 is primarily here to test FindValueByName and friends.
851     // All enums created from the same DescriptorPool share the same lookup
852     // table, so we need to insure that they don't interfere.
853 
854     // TestEnum
855     FileDescriptorProto foo_file;
856     foo_file.set_name("foo.proto");
857 
858     EnumDescriptorProto* enum_proto = AddEnum(&foo_file, "TestEnum");
859     AddEnumValue(enum_proto, "FOO", 1);
860     AddEnumValue(enum_proto, "BAR", 2);
861 
862     // TestEnum2
863     FileDescriptorProto bar_file;
864     bar_file.set_name("bar.proto");
865     bar_file.set_package("corge.grault");
866 
867     EnumDescriptorProto* enum2_proto = AddEnum(&bar_file, "TestEnum2");
868     AddEnumValue(enum2_proto, "FOO", 1);
869     AddEnumValue(enum2_proto, "BAZ", 3);
870 
871     // Build the descriptors and get the pointers.
872     foo_file_ = pool_.BuildFile(foo_file);
873     ASSERT_TRUE(foo_file_ != NULL);
874 
875     bar_file_ = pool_.BuildFile(bar_file);
876     ASSERT_TRUE(bar_file_ != NULL);
877 
878     ASSERT_EQ(1, foo_file_->enum_type_count());
879     enum_ = foo_file_->enum_type(0);
880 
881     ASSERT_EQ(2, enum_->value_count());
882     foo_ = enum_->value(0);
883     bar_ = enum_->value(1);
884 
885     ASSERT_EQ(1, bar_file_->enum_type_count());
886     enum2_ = bar_file_->enum_type(0);
887 
888     ASSERT_EQ(2, enum2_->value_count());
889     foo2_ = enum2_->value(0);
890     baz2_ = enum2_->value(1);
891   }
892 
893   DescriptorPool pool_;
894 
895   const FileDescriptor* foo_file_;
896   const FileDescriptor* bar_file_;
897 
898   const EnumDescriptor* enum_;
899   const EnumDescriptor* enum2_;
900 
901   const EnumValueDescriptor* foo_;
902   const EnumValueDescriptor* bar_;
903 
904   const EnumValueDescriptor* foo2_;
905   const EnumValueDescriptor* baz2_;
906 };
907 
TEST_F(EnumDescriptorTest,Name)908 TEST_F(EnumDescriptorTest, Name) {
909   EXPECT_EQ("TestEnum", enum_->name());
910   EXPECT_EQ("TestEnum", enum_->full_name());
911   EXPECT_EQ(foo_file_, enum_->file());
912 
913   EXPECT_EQ("TestEnum2", enum2_->name());
914   EXPECT_EQ("corge.grault.TestEnum2", enum2_->full_name());
915   EXPECT_EQ(bar_file_, enum2_->file());
916 }
917 
TEST_F(EnumDescriptorTest,ContainingType)918 TEST_F(EnumDescriptorTest, ContainingType) {
919   EXPECT_TRUE(enum_->containing_type() == NULL);
920   EXPECT_TRUE(enum2_->containing_type() == NULL);
921 }
922 
TEST_F(EnumDescriptorTest,ValuesByIndex)923 TEST_F(EnumDescriptorTest, ValuesByIndex) {
924   ASSERT_EQ(2, enum_->value_count());
925   EXPECT_EQ(foo_, enum_->value(0));
926   EXPECT_EQ(bar_, enum_->value(1));
927 }
928 
TEST_F(EnumDescriptorTest,FindValueByName)929 TEST_F(EnumDescriptorTest, FindValueByName) {
930   EXPECT_EQ(foo_ , enum_ ->FindValueByName("FOO"));
931   EXPECT_EQ(bar_ , enum_ ->FindValueByName("BAR"));
932   EXPECT_EQ(foo2_, enum2_->FindValueByName("FOO"));
933   EXPECT_EQ(baz2_, enum2_->FindValueByName("BAZ"));
934 
935   EXPECT_TRUE(enum_ ->FindValueByName("NO_SUCH_VALUE") == NULL);
936   EXPECT_TRUE(enum_ ->FindValueByName("BAZ"          ) == NULL);
937   EXPECT_TRUE(enum2_->FindValueByName("BAR"          ) == NULL);
938 }
939 
TEST_F(EnumDescriptorTest,FindValueByNumber)940 TEST_F(EnumDescriptorTest, FindValueByNumber) {
941   EXPECT_EQ(foo_ , enum_ ->FindValueByNumber(1));
942   EXPECT_EQ(bar_ , enum_ ->FindValueByNumber(2));
943   EXPECT_EQ(foo2_, enum2_->FindValueByNumber(1));
944   EXPECT_EQ(baz2_, enum2_->FindValueByNumber(3));
945 
946   EXPECT_TRUE(enum_ ->FindValueByNumber(416) == NULL);
947   EXPECT_TRUE(enum_ ->FindValueByNumber(3) == NULL);
948   EXPECT_TRUE(enum2_->FindValueByNumber(2) == NULL);
949 }
950 
TEST_F(EnumDescriptorTest,ValueName)951 TEST_F(EnumDescriptorTest, ValueName) {
952   EXPECT_EQ("FOO", foo_->name());
953   EXPECT_EQ("BAR", bar_->name());
954 }
955 
TEST_F(EnumDescriptorTest,ValueFullName)956 TEST_F(EnumDescriptorTest, ValueFullName) {
957   EXPECT_EQ("FOO", foo_->full_name());
958   EXPECT_EQ("BAR", bar_->full_name());
959   EXPECT_EQ("corge.grault.FOO", foo2_->full_name());
960   EXPECT_EQ("corge.grault.BAZ", baz2_->full_name());
961 }
962 
TEST_F(EnumDescriptorTest,ValueIndex)963 TEST_F(EnumDescriptorTest, ValueIndex) {
964   EXPECT_EQ(0, foo_->index());
965   EXPECT_EQ(1, bar_->index());
966 }
967 
TEST_F(EnumDescriptorTest,ValueNumber)968 TEST_F(EnumDescriptorTest, ValueNumber) {
969   EXPECT_EQ(1, foo_->number());
970   EXPECT_EQ(2, bar_->number());
971 }
972 
TEST_F(EnumDescriptorTest,ValueType)973 TEST_F(EnumDescriptorTest, ValueType) {
974   EXPECT_EQ(enum_ , foo_ ->type());
975   EXPECT_EQ(enum_ , bar_ ->type());
976   EXPECT_EQ(enum2_, foo2_->type());
977   EXPECT_EQ(enum2_, baz2_->type());
978 }
979 
980 // ===================================================================
981 
982 // Test service descriptors.
983 class ServiceDescriptorTest : public testing::Test {
984  protected:
SetUp()985   virtual void SetUp() {
986     // Build descriptors for the following messages and service:
987     //    // in "foo.proto"
988     //    message FooRequest  {}
989     //    message FooResponse {}
990     //    message BarRequest  {}
991     //    message BarResponse {}
992     //    message BazRequest  {}
993     //    message BazResponse {}
994     //
995     //    service TestService {
996     //      rpc Foo(FooRequest) returns (FooResponse);
997     //      rpc Bar(BarRequest) returns (BarResponse);
998     //    }
999     //
1000     //    // in "bar.proto"
1001     //    package corge.grault
1002     //    service TestService2 {
1003     //      rpc Foo(FooRequest) returns (FooResponse);
1004     //      rpc Baz(BazRequest) returns (BazResponse);
1005     //    }
1006 
1007     FileDescriptorProto foo_file;
1008     foo_file.set_name("foo.proto");
1009 
1010     AddMessage(&foo_file, "FooRequest");
1011     AddMessage(&foo_file, "FooResponse");
1012     AddMessage(&foo_file, "BarRequest");
1013     AddMessage(&foo_file, "BarResponse");
1014     AddMessage(&foo_file, "BazRequest");
1015     AddMessage(&foo_file, "BazResponse");
1016 
1017     ServiceDescriptorProto* service = AddService(&foo_file, "TestService");
1018     AddMethod(service, "Foo", "FooRequest", "FooResponse");
1019     AddMethod(service, "Bar", "BarRequest", "BarResponse");
1020 
1021     FileDescriptorProto bar_file;
1022     bar_file.set_name("bar.proto");
1023     bar_file.set_package("corge.grault");
1024     bar_file.add_dependency("foo.proto");
1025 
1026     ServiceDescriptorProto* service2 = AddService(&bar_file, "TestService2");
1027     AddMethod(service2, "Foo", "FooRequest", "FooResponse");
1028     AddMethod(service2, "Baz", "BazRequest", "BazResponse");
1029 
1030     // Build the descriptors and get the pointers.
1031     foo_file_ = pool_.BuildFile(foo_file);
1032     ASSERT_TRUE(foo_file_ != NULL);
1033 
1034     bar_file_ = pool_.BuildFile(bar_file);
1035     ASSERT_TRUE(bar_file_ != NULL);
1036 
1037     ASSERT_EQ(6, foo_file_->message_type_count());
1038     foo_request_  = foo_file_->message_type(0);
1039     foo_response_ = foo_file_->message_type(1);
1040     bar_request_  = foo_file_->message_type(2);
1041     bar_response_ = foo_file_->message_type(3);
1042     baz_request_  = foo_file_->message_type(4);
1043     baz_response_ = foo_file_->message_type(5);
1044 
1045     ASSERT_EQ(1, foo_file_->service_count());
1046     service_ = foo_file_->service(0);
1047 
1048     ASSERT_EQ(2, service_->method_count());
1049     foo_ = service_->method(0);
1050     bar_ = service_->method(1);
1051 
1052     ASSERT_EQ(1, bar_file_->service_count());
1053     service2_ = bar_file_->service(0);
1054 
1055     ASSERT_EQ(2, service2_->method_count());
1056     foo2_ = service2_->method(0);
1057     baz2_ = service2_->method(1);
1058   }
1059 
1060   DescriptorPool pool_;
1061 
1062   const FileDescriptor* foo_file_;
1063   const FileDescriptor* bar_file_;
1064 
1065   const Descriptor* foo_request_;
1066   const Descriptor* foo_response_;
1067   const Descriptor* bar_request_;
1068   const Descriptor* bar_response_;
1069   const Descriptor* baz_request_;
1070   const Descriptor* baz_response_;
1071 
1072   const ServiceDescriptor* service_;
1073   const ServiceDescriptor* service2_;
1074 
1075   const MethodDescriptor* foo_;
1076   const MethodDescriptor* bar_;
1077 
1078   const MethodDescriptor* foo2_;
1079   const MethodDescriptor* baz2_;
1080 };
1081 
TEST_F(ServiceDescriptorTest,Name)1082 TEST_F(ServiceDescriptorTest, Name) {
1083   EXPECT_EQ("TestService", service_->name());
1084   EXPECT_EQ("TestService", service_->full_name());
1085   EXPECT_EQ(foo_file_, service_->file());
1086 
1087   EXPECT_EQ("TestService2", service2_->name());
1088   EXPECT_EQ("corge.grault.TestService2", service2_->full_name());
1089   EXPECT_EQ(bar_file_, service2_->file());
1090 }
1091 
TEST_F(ServiceDescriptorTest,MethodsByIndex)1092 TEST_F(ServiceDescriptorTest, MethodsByIndex) {
1093   ASSERT_EQ(2, service_->method_count());
1094   EXPECT_EQ(foo_, service_->method(0));
1095   EXPECT_EQ(bar_, service_->method(1));
1096 }
1097 
TEST_F(ServiceDescriptorTest,FindMethodByName)1098 TEST_F(ServiceDescriptorTest, FindMethodByName) {
1099   EXPECT_EQ(foo_ , service_ ->FindMethodByName("Foo"));
1100   EXPECT_EQ(bar_ , service_ ->FindMethodByName("Bar"));
1101   EXPECT_EQ(foo2_, service2_->FindMethodByName("Foo"));
1102   EXPECT_EQ(baz2_, service2_->FindMethodByName("Baz"));
1103 
1104   EXPECT_TRUE(service_ ->FindMethodByName("NoSuchMethod") == NULL);
1105   EXPECT_TRUE(service_ ->FindMethodByName("Baz"         ) == NULL);
1106   EXPECT_TRUE(service2_->FindMethodByName("Bar"         ) == NULL);
1107 }
1108 
TEST_F(ServiceDescriptorTest,MethodName)1109 TEST_F(ServiceDescriptorTest, MethodName) {
1110   EXPECT_EQ("Foo", foo_->name());
1111   EXPECT_EQ("Bar", bar_->name());
1112 }
1113 
TEST_F(ServiceDescriptorTest,MethodFullName)1114 TEST_F(ServiceDescriptorTest, MethodFullName) {
1115   EXPECT_EQ("TestService.Foo", foo_->full_name());
1116   EXPECT_EQ("TestService.Bar", bar_->full_name());
1117   EXPECT_EQ("corge.grault.TestService2.Foo", foo2_->full_name());
1118   EXPECT_EQ("corge.grault.TestService2.Baz", baz2_->full_name());
1119 }
1120 
TEST_F(ServiceDescriptorTest,MethodIndex)1121 TEST_F(ServiceDescriptorTest, MethodIndex) {
1122   EXPECT_EQ(0, foo_->index());
1123   EXPECT_EQ(1, bar_->index());
1124 }
1125 
TEST_F(ServiceDescriptorTest,MethodParent)1126 TEST_F(ServiceDescriptorTest, MethodParent) {
1127   EXPECT_EQ(service_, foo_->service());
1128   EXPECT_EQ(service_, bar_->service());
1129 }
1130 
TEST_F(ServiceDescriptorTest,MethodInputType)1131 TEST_F(ServiceDescriptorTest, MethodInputType) {
1132   EXPECT_EQ(foo_request_, foo_->input_type());
1133   EXPECT_EQ(bar_request_, bar_->input_type());
1134 }
1135 
TEST_F(ServiceDescriptorTest,MethodOutputType)1136 TEST_F(ServiceDescriptorTest, MethodOutputType) {
1137   EXPECT_EQ(foo_response_, foo_->output_type());
1138   EXPECT_EQ(bar_response_, bar_->output_type());
1139 }
1140 
1141 // ===================================================================
1142 
1143 // Test nested types.
1144 class NestedDescriptorTest : public testing::Test {
1145  protected:
SetUp()1146   virtual void SetUp() {
1147     // Build descriptors for the following definitions:
1148     //
1149     //   // in "foo.proto"
1150     //   message TestMessage {
1151     //     message Foo {}
1152     //     message Bar {}
1153     //     enum Baz { A = 1; }
1154     //     enum Qux { B = 1; }
1155     //   }
1156     //
1157     //   // in "bar.proto"
1158     //   package corge.grault;
1159     //   message TestMessage2 {
1160     //     message Foo {}
1161     //     message Baz {}
1162     //     enum Qux  { A = 1; }
1163     //     enum Quux { C = 1; }
1164     //   }
1165     //
1166     // TestMessage2 is primarily here to test FindNestedTypeByName and friends.
1167     // All messages created from the same DescriptorPool share the same lookup
1168     // table, so we need to insure that they don't interfere.
1169     //
1170     // We add enum values to the enums in order to test searching for enum
1171     // values across a message's scope.
1172 
1173     FileDescriptorProto foo_file;
1174     foo_file.set_name("foo.proto");
1175 
1176     DescriptorProto* message = AddMessage(&foo_file, "TestMessage");
1177     AddNestedMessage(message, "Foo");
1178     AddNestedMessage(message, "Bar");
1179     EnumDescriptorProto* baz = AddNestedEnum(message, "Baz");
1180     AddEnumValue(baz, "A", 1);
1181     EnumDescriptorProto* qux = AddNestedEnum(message, "Qux");
1182     AddEnumValue(qux, "B", 1);
1183 
1184     FileDescriptorProto bar_file;
1185     bar_file.set_name("bar.proto");
1186     bar_file.set_package("corge.grault");
1187 
1188     DescriptorProto* message2 = AddMessage(&bar_file, "TestMessage2");
1189     AddNestedMessage(message2, "Foo");
1190     AddNestedMessage(message2, "Baz");
1191     EnumDescriptorProto* qux2 = AddNestedEnum(message2, "Qux");
1192     AddEnumValue(qux2, "A", 1);
1193     EnumDescriptorProto* quux2 = AddNestedEnum(message2, "Quux");
1194     AddEnumValue(quux2, "C", 1);
1195 
1196     // Build the descriptors and get the pointers.
1197     foo_file_ = pool_.BuildFile(foo_file);
1198     ASSERT_TRUE(foo_file_ != NULL);
1199 
1200     bar_file_ = pool_.BuildFile(bar_file);
1201     ASSERT_TRUE(bar_file_ != NULL);
1202 
1203     ASSERT_EQ(1, foo_file_->message_type_count());
1204     message_ = foo_file_->message_type(0);
1205 
1206     ASSERT_EQ(2, message_->nested_type_count());
1207     foo_ = message_->nested_type(0);
1208     bar_ = message_->nested_type(1);
1209 
1210     ASSERT_EQ(2, message_->enum_type_count());
1211     baz_ = message_->enum_type(0);
1212     qux_ = message_->enum_type(1);
1213 
1214     ASSERT_EQ(1, baz_->value_count());
1215     a_ = baz_->value(0);
1216     ASSERT_EQ(1, qux_->value_count());
1217     b_ = qux_->value(0);
1218 
1219     ASSERT_EQ(1, bar_file_->message_type_count());
1220     message2_ = bar_file_->message_type(0);
1221 
1222     ASSERT_EQ(2, message2_->nested_type_count());
1223     foo2_ = message2_->nested_type(0);
1224     baz2_ = message2_->nested_type(1);
1225 
1226     ASSERT_EQ(2, message2_->enum_type_count());
1227     qux2_ = message2_->enum_type(0);
1228     quux2_ = message2_->enum_type(1);
1229 
1230     ASSERT_EQ(1, qux2_->value_count());
1231     a2_ = qux2_->value(0);
1232     ASSERT_EQ(1, quux2_->value_count());
1233     c2_ = quux2_->value(0);
1234   }
1235 
1236   DescriptorPool pool_;
1237 
1238   const FileDescriptor* foo_file_;
1239   const FileDescriptor* bar_file_;
1240 
1241   const Descriptor* message_;
1242   const Descriptor* message2_;
1243 
1244   const Descriptor* foo_;
1245   const Descriptor* bar_;
1246   const EnumDescriptor* baz_;
1247   const EnumDescriptor* qux_;
1248   const EnumValueDescriptor* a_;
1249   const EnumValueDescriptor* b_;
1250 
1251   const Descriptor* foo2_;
1252   const Descriptor* baz2_;
1253   const EnumDescriptor* qux2_;
1254   const EnumDescriptor* quux2_;
1255   const EnumValueDescriptor* a2_;
1256   const EnumValueDescriptor* c2_;
1257 };
1258 
TEST_F(NestedDescriptorTest,MessageName)1259 TEST_F(NestedDescriptorTest, MessageName) {
1260   EXPECT_EQ("Foo", foo_ ->name());
1261   EXPECT_EQ("Bar", bar_ ->name());
1262   EXPECT_EQ("Foo", foo2_->name());
1263   EXPECT_EQ("Baz", baz2_->name());
1264 
1265   EXPECT_EQ("TestMessage.Foo", foo_->full_name());
1266   EXPECT_EQ("TestMessage.Bar", bar_->full_name());
1267   EXPECT_EQ("corge.grault.TestMessage2.Foo", foo2_->full_name());
1268   EXPECT_EQ("corge.grault.TestMessage2.Baz", baz2_->full_name());
1269 }
1270 
TEST_F(NestedDescriptorTest,MessageContainingType)1271 TEST_F(NestedDescriptorTest, MessageContainingType) {
1272   EXPECT_EQ(message_ , foo_ ->containing_type());
1273   EXPECT_EQ(message_ , bar_ ->containing_type());
1274   EXPECT_EQ(message2_, foo2_->containing_type());
1275   EXPECT_EQ(message2_, baz2_->containing_type());
1276 }
1277 
TEST_F(NestedDescriptorTest,NestedMessagesByIndex)1278 TEST_F(NestedDescriptorTest, NestedMessagesByIndex) {
1279   ASSERT_EQ(2, message_->nested_type_count());
1280   EXPECT_EQ(foo_, message_->nested_type(0));
1281   EXPECT_EQ(bar_, message_->nested_type(1));
1282 }
1283 
TEST_F(NestedDescriptorTest,FindFieldByNameDoesntFindNestedTypes)1284 TEST_F(NestedDescriptorTest, FindFieldByNameDoesntFindNestedTypes) {
1285   EXPECT_TRUE(message_->FindFieldByName("Foo") == NULL);
1286   EXPECT_TRUE(message_->FindFieldByName("Qux") == NULL);
1287   EXPECT_TRUE(message_->FindExtensionByName("Foo") == NULL);
1288   EXPECT_TRUE(message_->FindExtensionByName("Qux") == NULL);
1289 }
1290 
TEST_F(NestedDescriptorTest,FindNestedTypeByName)1291 TEST_F(NestedDescriptorTest, FindNestedTypeByName) {
1292   EXPECT_EQ(foo_ , message_ ->FindNestedTypeByName("Foo"));
1293   EXPECT_EQ(bar_ , message_ ->FindNestedTypeByName("Bar"));
1294   EXPECT_EQ(foo2_, message2_->FindNestedTypeByName("Foo"));
1295   EXPECT_EQ(baz2_, message2_->FindNestedTypeByName("Baz"));
1296 
1297   EXPECT_TRUE(message_ ->FindNestedTypeByName("NoSuchType") == NULL);
1298   EXPECT_TRUE(message_ ->FindNestedTypeByName("Baz"       ) == NULL);
1299   EXPECT_TRUE(message2_->FindNestedTypeByName("Bar"       ) == NULL);
1300 
1301   EXPECT_TRUE(message_->FindNestedTypeByName("Qux") == NULL);
1302 }
1303 
TEST_F(NestedDescriptorTest,EnumName)1304 TEST_F(NestedDescriptorTest, EnumName) {
1305   EXPECT_EQ("Baz" , baz_ ->name());
1306   EXPECT_EQ("Qux" , qux_ ->name());
1307   EXPECT_EQ("Qux" , qux2_->name());
1308   EXPECT_EQ("Quux", quux2_->name());
1309 
1310   EXPECT_EQ("TestMessage.Baz", baz_->full_name());
1311   EXPECT_EQ("TestMessage.Qux", qux_->full_name());
1312   EXPECT_EQ("corge.grault.TestMessage2.Qux" , qux2_ ->full_name());
1313   EXPECT_EQ("corge.grault.TestMessage2.Quux", quux2_->full_name());
1314 }
1315 
TEST_F(NestedDescriptorTest,EnumContainingType)1316 TEST_F(NestedDescriptorTest, EnumContainingType) {
1317   EXPECT_EQ(message_ , baz_  ->containing_type());
1318   EXPECT_EQ(message_ , qux_  ->containing_type());
1319   EXPECT_EQ(message2_, qux2_ ->containing_type());
1320   EXPECT_EQ(message2_, quux2_->containing_type());
1321 }
1322 
TEST_F(NestedDescriptorTest,NestedEnumsByIndex)1323 TEST_F(NestedDescriptorTest, NestedEnumsByIndex) {
1324   ASSERT_EQ(2, message_->nested_type_count());
1325   EXPECT_EQ(foo_, message_->nested_type(0));
1326   EXPECT_EQ(bar_, message_->nested_type(1));
1327 }
1328 
TEST_F(NestedDescriptorTest,FindEnumTypeByName)1329 TEST_F(NestedDescriptorTest, FindEnumTypeByName) {
1330   EXPECT_EQ(baz_  , message_ ->FindEnumTypeByName("Baz" ));
1331   EXPECT_EQ(qux_  , message_ ->FindEnumTypeByName("Qux" ));
1332   EXPECT_EQ(qux2_ , message2_->FindEnumTypeByName("Qux" ));
1333   EXPECT_EQ(quux2_, message2_->FindEnumTypeByName("Quux"));
1334 
1335   EXPECT_TRUE(message_ ->FindEnumTypeByName("NoSuchType") == NULL);
1336   EXPECT_TRUE(message_ ->FindEnumTypeByName("Quux"      ) == NULL);
1337   EXPECT_TRUE(message2_->FindEnumTypeByName("Baz"       ) == NULL);
1338 
1339   EXPECT_TRUE(message_->FindEnumTypeByName("Foo") == NULL);
1340 }
1341 
TEST_F(NestedDescriptorTest,FindEnumValueByName)1342 TEST_F(NestedDescriptorTest, FindEnumValueByName) {
1343   EXPECT_EQ(a_ , message_ ->FindEnumValueByName("A"));
1344   EXPECT_EQ(b_ , message_ ->FindEnumValueByName("B"));
1345   EXPECT_EQ(a2_, message2_->FindEnumValueByName("A"));
1346   EXPECT_EQ(c2_, message2_->FindEnumValueByName("C"));
1347 
1348   EXPECT_TRUE(message_ ->FindEnumValueByName("NO_SUCH_VALUE") == NULL);
1349   EXPECT_TRUE(message_ ->FindEnumValueByName("C"            ) == NULL);
1350   EXPECT_TRUE(message2_->FindEnumValueByName("B"            ) == NULL);
1351 
1352   EXPECT_TRUE(message_->FindEnumValueByName("Foo") == NULL);
1353 }
1354 
1355 // ===================================================================
1356 
1357 // Test extensions.
1358 class ExtensionDescriptorTest : public testing::Test {
1359  protected:
SetUp()1360   virtual void SetUp() {
1361     // Build descriptors for the following definitions:
1362     //
1363     //   enum Baz {}
1364     //   message Qux {}
1365     //
1366     //   message Foo {
1367     //     extensions 10 to 19;
1368     //     extensions 30 to 39;
1369     //   }
1370     //   extends Foo with optional int32 foo_int32 = 10;
1371     //   extends Foo with repeated TestEnum foo_enum = 19;
1372     //   message Bar {
1373     //     extends Foo with optional Qux foo_message = 30;
1374     //     // (using Qux as the group type)
1375     //     extends Foo with repeated group foo_group = 39;
1376     //   }
1377 
1378     FileDescriptorProto foo_file;
1379     foo_file.set_name("foo.proto");
1380 
1381     AddEmptyEnum(&foo_file, "Baz");
1382     AddMessage(&foo_file, "Qux");
1383 
1384     DescriptorProto* foo = AddMessage(&foo_file, "Foo");
1385     AddExtensionRange(foo, 10, 20);
1386     AddExtensionRange(foo, 30, 40);
1387 
1388     AddExtension(&foo_file, "Foo", "foo_int32", 10,
1389                  FieldDescriptorProto::LABEL_OPTIONAL,
1390                  FieldDescriptorProto::TYPE_INT32);
1391     AddExtension(&foo_file, "Foo", "foo_enum", 19,
1392                  FieldDescriptorProto::LABEL_REPEATED,
1393                  FieldDescriptorProto::TYPE_ENUM)
1394       ->set_type_name("Baz");
1395 
1396     DescriptorProto* bar = AddMessage(&foo_file, "Bar");
1397     AddNestedExtension(bar, "Foo", "foo_message", 30,
1398                        FieldDescriptorProto::LABEL_OPTIONAL,
1399                        FieldDescriptorProto::TYPE_MESSAGE)
1400       ->set_type_name("Qux");
1401     AddNestedExtension(bar, "Foo", "foo_group", 39,
1402                        FieldDescriptorProto::LABEL_REPEATED,
1403                        FieldDescriptorProto::TYPE_GROUP)
1404       ->set_type_name("Qux");
1405 
1406     // Build the descriptors and get the pointers.
1407     foo_file_ = pool_.BuildFile(foo_file);
1408     ASSERT_TRUE(foo_file_ != NULL);
1409 
1410     ASSERT_EQ(1, foo_file_->enum_type_count());
1411     baz_ = foo_file_->enum_type(0);
1412 
1413     ASSERT_EQ(3, foo_file_->message_type_count());
1414     qux_ = foo_file_->message_type(0);
1415     foo_ = foo_file_->message_type(1);
1416     bar_ = foo_file_->message_type(2);
1417   }
1418 
1419   DescriptorPool pool_;
1420 
1421   const FileDescriptor* foo_file_;
1422 
1423   const Descriptor* foo_;
1424   const Descriptor* bar_;
1425   const EnumDescriptor* baz_;
1426   const Descriptor* qux_;
1427 };
1428 
TEST_F(ExtensionDescriptorTest,ExtensionRanges)1429 TEST_F(ExtensionDescriptorTest, ExtensionRanges) {
1430   EXPECT_EQ(0, bar_->extension_range_count());
1431   ASSERT_EQ(2, foo_->extension_range_count());
1432 
1433   EXPECT_EQ(10, foo_->extension_range(0)->start);
1434   EXPECT_EQ(30, foo_->extension_range(1)->start);
1435 
1436   EXPECT_EQ(20, foo_->extension_range(0)->end);
1437   EXPECT_EQ(40, foo_->extension_range(1)->end);
1438 };
1439 
TEST_F(ExtensionDescriptorTest,Extensions)1440 TEST_F(ExtensionDescriptorTest, Extensions) {
1441   EXPECT_EQ(0, foo_->extension_count());
1442   ASSERT_EQ(2, foo_file_->extension_count());
1443   ASSERT_EQ(2, bar_->extension_count());
1444 
1445   EXPECT_TRUE(foo_file_->extension(0)->is_extension());
1446   EXPECT_TRUE(foo_file_->extension(1)->is_extension());
1447   EXPECT_TRUE(bar_->extension(0)->is_extension());
1448   EXPECT_TRUE(bar_->extension(1)->is_extension());
1449 
1450   EXPECT_EQ("foo_int32"  , foo_file_->extension(0)->name());
1451   EXPECT_EQ("foo_enum"   , foo_file_->extension(1)->name());
1452   EXPECT_EQ("foo_message", bar_->extension(0)->name());
1453   EXPECT_EQ("foo_group"  , bar_->extension(1)->name());
1454 
1455   EXPECT_EQ(10, foo_file_->extension(0)->number());
1456   EXPECT_EQ(19, foo_file_->extension(1)->number());
1457   EXPECT_EQ(30, bar_->extension(0)->number());
1458   EXPECT_EQ(39, bar_->extension(1)->number());
1459 
1460   EXPECT_EQ(FieldDescriptor::TYPE_INT32  , foo_file_->extension(0)->type());
1461   EXPECT_EQ(FieldDescriptor::TYPE_ENUM   , foo_file_->extension(1)->type());
1462   EXPECT_EQ(FieldDescriptor::TYPE_MESSAGE, bar_->extension(0)->type());
1463   EXPECT_EQ(FieldDescriptor::TYPE_GROUP  , bar_->extension(1)->type());
1464 
1465   EXPECT_EQ(baz_, foo_file_->extension(1)->enum_type());
1466   EXPECT_EQ(qux_, bar_->extension(0)->message_type());
1467   EXPECT_EQ(qux_, bar_->extension(1)->message_type());
1468 
1469   EXPECT_EQ(FieldDescriptor::LABEL_OPTIONAL, foo_file_->extension(0)->label());
1470   EXPECT_EQ(FieldDescriptor::LABEL_REPEATED, foo_file_->extension(1)->label());
1471   EXPECT_EQ(FieldDescriptor::LABEL_OPTIONAL, bar_->extension(0)->label());
1472   EXPECT_EQ(FieldDescriptor::LABEL_REPEATED, bar_->extension(1)->label());
1473 
1474   EXPECT_EQ(foo_, foo_file_->extension(0)->containing_type());
1475   EXPECT_EQ(foo_, foo_file_->extension(1)->containing_type());
1476   EXPECT_EQ(foo_, bar_->extension(0)->containing_type());
1477   EXPECT_EQ(foo_, bar_->extension(1)->containing_type());
1478 
1479   EXPECT_TRUE(foo_file_->extension(0)->extension_scope() == NULL);
1480   EXPECT_TRUE(foo_file_->extension(1)->extension_scope() == NULL);
1481   EXPECT_EQ(bar_, bar_->extension(0)->extension_scope());
1482   EXPECT_EQ(bar_, bar_->extension(1)->extension_scope());
1483 };
1484 
TEST_F(ExtensionDescriptorTest,IsExtensionNumber)1485 TEST_F(ExtensionDescriptorTest, IsExtensionNumber) {
1486   EXPECT_FALSE(foo_->IsExtensionNumber( 9));
1487   EXPECT_TRUE (foo_->IsExtensionNumber(10));
1488   EXPECT_TRUE (foo_->IsExtensionNumber(19));
1489   EXPECT_FALSE(foo_->IsExtensionNumber(20));
1490   EXPECT_FALSE(foo_->IsExtensionNumber(29));
1491   EXPECT_TRUE (foo_->IsExtensionNumber(30));
1492   EXPECT_TRUE (foo_->IsExtensionNumber(39));
1493   EXPECT_FALSE(foo_->IsExtensionNumber(40));
1494 }
1495 
TEST_F(ExtensionDescriptorTest,FindExtensionByName)1496 TEST_F(ExtensionDescriptorTest, FindExtensionByName) {
1497   // Note that FileDescriptor::FindExtensionByName() is tested by
1498   // FileDescriptorTest.
1499   ASSERT_EQ(2, bar_->extension_count());
1500 
1501   EXPECT_EQ(bar_->extension(0), bar_->FindExtensionByName("foo_message"));
1502   EXPECT_EQ(bar_->extension(1), bar_->FindExtensionByName("foo_group"  ));
1503 
1504   EXPECT_TRUE(bar_->FindExtensionByName("no_such_extension") == NULL);
1505   EXPECT_TRUE(foo_->FindExtensionByName("foo_int32") == NULL);
1506   EXPECT_TRUE(foo_->FindExtensionByName("foo_message") == NULL);
1507 }
1508 
TEST_F(ExtensionDescriptorTest,FindAllExtensions)1509 TEST_F(ExtensionDescriptorTest, FindAllExtensions) {
1510   vector<const FieldDescriptor*> extensions;
1511   pool_.FindAllExtensions(foo_, &extensions);
1512   ASSERT_EQ(4, extensions.size());
1513   EXPECT_EQ(10, extensions[0]->number());
1514   EXPECT_EQ(19, extensions[1]->number());
1515   EXPECT_EQ(30, extensions[2]->number());
1516   EXPECT_EQ(39, extensions[3]->number());
1517 }
1518 
1519 // ===================================================================
1520 
1521 class MiscTest : public testing::Test {
1522  protected:
1523   // Function which makes a field descriptor of the given type.
GetFieldDescriptorOfType(FieldDescriptor::Type type)1524   const FieldDescriptor* GetFieldDescriptorOfType(FieldDescriptor::Type type) {
1525     FileDescriptorProto file_proto;
1526     file_proto.set_name("foo.proto");
1527     AddEmptyEnum(&file_proto, "DummyEnum");
1528 
1529     DescriptorProto* message = AddMessage(&file_proto, "TestMessage");
1530     FieldDescriptorProto* field =
1531       AddField(message, "foo", 1, FieldDescriptorProto::LABEL_OPTIONAL,
1532                static_cast<FieldDescriptorProto::Type>(static_cast<int>(type)));
1533 
1534     if (type == FieldDescriptor::TYPE_MESSAGE ||
1535         type == FieldDescriptor::TYPE_GROUP) {
1536       field->set_type_name("TestMessage");
1537     } else if (type == FieldDescriptor::TYPE_ENUM) {
1538       field->set_type_name("DummyEnum");
1539     }
1540 
1541     // Build the descriptors and get the pointers.
1542     pool_.reset(new DescriptorPool());
1543     const FileDescriptor* file = pool_->BuildFile(file_proto);
1544 
1545     if (file != NULL &&
1546         file->message_type_count() == 1 &&
1547         file->message_type(0)->field_count() == 1) {
1548       return file->message_type(0)->field(0);
1549     } else {
1550       return NULL;
1551     }
1552   }
1553 
GetTypeNameForFieldType(FieldDescriptor::Type type)1554   const char* GetTypeNameForFieldType(FieldDescriptor::Type type) {
1555     const FieldDescriptor* field = GetFieldDescriptorOfType(type);
1556     return field != NULL ? field->type_name() : "";
1557   }
1558 
GetCppTypeForFieldType(FieldDescriptor::Type type)1559   FieldDescriptor::CppType GetCppTypeForFieldType(FieldDescriptor::Type type) {
1560     const FieldDescriptor* field = GetFieldDescriptorOfType(type);
1561     return field != NULL ? field->cpp_type() :
1562         static_cast<FieldDescriptor::CppType>(0);
1563   }
1564 
GetCppTypeNameForFieldType(FieldDescriptor::Type type)1565   const char* GetCppTypeNameForFieldType(FieldDescriptor::Type type) {
1566     const FieldDescriptor* field = GetFieldDescriptorOfType(type);
1567     return field != NULL ? field->cpp_type_name() : "";
1568   }
1569 
1570   scoped_ptr<DescriptorPool> pool_;
1571 };
1572 
TEST_F(MiscTest,TypeNames)1573 TEST_F(MiscTest, TypeNames) {
1574   // Test that correct type names are returned.
1575 
1576   typedef FieldDescriptor FD;  // avoid ugly line wrapping
1577 
1578   EXPECT_STREQ("double"  , GetTypeNameForFieldType(FD::TYPE_DOUBLE  ));
1579   EXPECT_STREQ("float"   , GetTypeNameForFieldType(FD::TYPE_FLOAT   ));
1580   EXPECT_STREQ("int64"   , GetTypeNameForFieldType(FD::TYPE_INT64   ));
1581   EXPECT_STREQ("uint64"  , GetTypeNameForFieldType(FD::TYPE_UINT64  ));
1582   EXPECT_STREQ("int32"   , GetTypeNameForFieldType(FD::TYPE_INT32   ));
1583   EXPECT_STREQ("fixed64" , GetTypeNameForFieldType(FD::TYPE_FIXED64 ));
1584   EXPECT_STREQ("fixed32" , GetTypeNameForFieldType(FD::TYPE_FIXED32 ));
1585   EXPECT_STREQ("bool"    , GetTypeNameForFieldType(FD::TYPE_BOOL    ));
1586   EXPECT_STREQ("string"  , GetTypeNameForFieldType(FD::TYPE_STRING  ));
1587   EXPECT_STREQ("group"   , GetTypeNameForFieldType(FD::TYPE_GROUP   ));
1588   EXPECT_STREQ("message" , GetTypeNameForFieldType(FD::TYPE_MESSAGE ));
1589   EXPECT_STREQ("bytes"   , GetTypeNameForFieldType(FD::TYPE_BYTES   ));
1590   EXPECT_STREQ("uint32"  , GetTypeNameForFieldType(FD::TYPE_UINT32  ));
1591   EXPECT_STREQ("enum"    , GetTypeNameForFieldType(FD::TYPE_ENUM    ));
1592   EXPECT_STREQ("sfixed32", GetTypeNameForFieldType(FD::TYPE_SFIXED32));
1593   EXPECT_STREQ("sfixed64", GetTypeNameForFieldType(FD::TYPE_SFIXED64));
1594   EXPECT_STREQ("sint32"  , GetTypeNameForFieldType(FD::TYPE_SINT32  ));
1595   EXPECT_STREQ("sint64"  , GetTypeNameForFieldType(FD::TYPE_SINT64  ));
1596 }
1597 
TEST_F(MiscTest,CppTypes)1598 TEST_F(MiscTest, CppTypes) {
1599   // Test that CPP types are assigned correctly.
1600 
1601   typedef FieldDescriptor FD;  // avoid ugly line wrapping
1602 
1603   EXPECT_EQ(FD::CPPTYPE_DOUBLE , GetCppTypeForFieldType(FD::TYPE_DOUBLE  ));
1604   EXPECT_EQ(FD::CPPTYPE_FLOAT  , GetCppTypeForFieldType(FD::TYPE_FLOAT   ));
1605   EXPECT_EQ(FD::CPPTYPE_INT64  , GetCppTypeForFieldType(FD::TYPE_INT64   ));
1606   EXPECT_EQ(FD::CPPTYPE_UINT64 , GetCppTypeForFieldType(FD::TYPE_UINT64  ));
1607   EXPECT_EQ(FD::CPPTYPE_INT32  , GetCppTypeForFieldType(FD::TYPE_INT32   ));
1608   EXPECT_EQ(FD::CPPTYPE_UINT64 , GetCppTypeForFieldType(FD::TYPE_FIXED64 ));
1609   EXPECT_EQ(FD::CPPTYPE_UINT32 , GetCppTypeForFieldType(FD::TYPE_FIXED32 ));
1610   EXPECT_EQ(FD::CPPTYPE_BOOL   , GetCppTypeForFieldType(FD::TYPE_BOOL    ));
1611   EXPECT_EQ(FD::CPPTYPE_STRING , GetCppTypeForFieldType(FD::TYPE_STRING  ));
1612   EXPECT_EQ(FD::CPPTYPE_MESSAGE, GetCppTypeForFieldType(FD::TYPE_GROUP   ));
1613   EXPECT_EQ(FD::CPPTYPE_MESSAGE, GetCppTypeForFieldType(FD::TYPE_MESSAGE ));
1614   EXPECT_EQ(FD::CPPTYPE_STRING , GetCppTypeForFieldType(FD::TYPE_BYTES   ));
1615   EXPECT_EQ(FD::CPPTYPE_UINT32 , GetCppTypeForFieldType(FD::TYPE_UINT32  ));
1616   EXPECT_EQ(FD::CPPTYPE_ENUM   , GetCppTypeForFieldType(FD::TYPE_ENUM    ));
1617   EXPECT_EQ(FD::CPPTYPE_INT32  , GetCppTypeForFieldType(FD::TYPE_SFIXED32));
1618   EXPECT_EQ(FD::CPPTYPE_INT64  , GetCppTypeForFieldType(FD::TYPE_SFIXED64));
1619   EXPECT_EQ(FD::CPPTYPE_INT32  , GetCppTypeForFieldType(FD::TYPE_SINT32  ));
1620   EXPECT_EQ(FD::CPPTYPE_INT64  , GetCppTypeForFieldType(FD::TYPE_SINT64  ));
1621 }
1622 
TEST_F(MiscTest,CppTypeNames)1623 TEST_F(MiscTest, CppTypeNames) {
1624   // Test that correct CPP type names are returned.
1625 
1626   typedef FieldDescriptor FD;  // avoid ugly line wrapping
1627 
1628   EXPECT_STREQ("double" , GetCppTypeNameForFieldType(FD::TYPE_DOUBLE  ));
1629   EXPECT_STREQ("float"  , GetCppTypeNameForFieldType(FD::TYPE_FLOAT   ));
1630   EXPECT_STREQ("int64"  , GetCppTypeNameForFieldType(FD::TYPE_INT64   ));
1631   EXPECT_STREQ("uint64" , GetCppTypeNameForFieldType(FD::TYPE_UINT64  ));
1632   EXPECT_STREQ("int32"  , GetCppTypeNameForFieldType(FD::TYPE_INT32   ));
1633   EXPECT_STREQ("uint64" , GetCppTypeNameForFieldType(FD::TYPE_FIXED64 ));
1634   EXPECT_STREQ("uint32" , GetCppTypeNameForFieldType(FD::TYPE_FIXED32 ));
1635   EXPECT_STREQ("bool"   , GetCppTypeNameForFieldType(FD::TYPE_BOOL    ));
1636   EXPECT_STREQ("string" , GetCppTypeNameForFieldType(FD::TYPE_STRING  ));
1637   EXPECT_STREQ("message", GetCppTypeNameForFieldType(FD::TYPE_GROUP   ));
1638   EXPECT_STREQ("message", GetCppTypeNameForFieldType(FD::TYPE_MESSAGE ));
1639   EXPECT_STREQ("string" , GetCppTypeNameForFieldType(FD::TYPE_BYTES   ));
1640   EXPECT_STREQ("uint32" , GetCppTypeNameForFieldType(FD::TYPE_UINT32  ));
1641   EXPECT_STREQ("enum"   , GetCppTypeNameForFieldType(FD::TYPE_ENUM    ));
1642   EXPECT_STREQ("int32"  , GetCppTypeNameForFieldType(FD::TYPE_SFIXED32));
1643   EXPECT_STREQ("int64"  , GetCppTypeNameForFieldType(FD::TYPE_SFIXED64));
1644   EXPECT_STREQ("int32"  , GetCppTypeNameForFieldType(FD::TYPE_SINT32  ));
1645   EXPECT_STREQ("int64"  , GetCppTypeNameForFieldType(FD::TYPE_SINT64  ));
1646 }
1647 
TEST_F(MiscTest,DefaultValues)1648 TEST_F(MiscTest, DefaultValues) {
1649   // Test that setting default values works.
1650   FileDescriptorProto file_proto;
1651   file_proto.set_name("foo.proto");
1652 
1653   EnumDescriptorProto* enum_type_proto = AddEnum(&file_proto, "DummyEnum");
1654   AddEnumValue(enum_type_proto, "A", 1);
1655   AddEnumValue(enum_type_proto, "B", 2);
1656 
1657   DescriptorProto* message_proto = AddMessage(&file_proto, "TestMessage");
1658 
1659   typedef FieldDescriptorProto FD;  // avoid ugly line wrapping
1660   const FD::Label label = FD::LABEL_OPTIONAL;
1661 
1662   // Create fields of every CPP type with default values.
1663   AddField(message_proto, "int32" , 1, label, FD::TYPE_INT32 )
1664     ->set_default_value("-1");
1665   AddField(message_proto, "int64" , 2, label, FD::TYPE_INT64 )
1666     ->set_default_value("-1000000000000");
1667   AddField(message_proto, "uint32", 3, label, FD::TYPE_UINT32)
1668     ->set_default_value("42");
1669   AddField(message_proto, "uint64", 4, label, FD::TYPE_UINT64)
1670     ->set_default_value("2000000000000");
1671   AddField(message_proto, "float" , 5, label, FD::TYPE_FLOAT )
1672     ->set_default_value("4.5");
1673   AddField(message_proto, "double", 6, label, FD::TYPE_DOUBLE)
1674     ->set_default_value("10e100");
1675   AddField(message_proto, "bool"  , 7, label, FD::TYPE_BOOL  )
1676     ->set_default_value("true");
1677   AddField(message_proto, "string", 8, label, FD::TYPE_STRING)
1678     ->set_default_value("hello");
1679   AddField(message_proto, "data"  , 9, label, FD::TYPE_BYTES )
1680     ->set_default_value("\\001\\002\\003");
1681 
1682   FieldDescriptorProto* enum_field =
1683     AddField(message_proto, "enum", 10, label, FD::TYPE_ENUM);
1684   enum_field->set_type_name("DummyEnum");
1685   enum_field->set_default_value("B");
1686 
1687   // Strings are allowed to have empty defaults.  (At one point, due to
1688   // a bug, empty defaults for strings were rejected.  Oops.)
1689   AddField(message_proto, "empty_string", 11, label, FD::TYPE_STRING)
1690     ->set_default_value("");
1691 
1692   // Add a second set of fields with implicit defalut values.
1693   AddField(message_proto, "implicit_int32" , 21, label, FD::TYPE_INT32 );
1694   AddField(message_proto, "implicit_int64" , 22, label, FD::TYPE_INT64 );
1695   AddField(message_proto, "implicit_uint32", 23, label, FD::TYPE_UINT32);
1696   AddField(message_proto, "implicit_uint64", 24, label, FD::TYPE_UINT64);
1697   AddField(message_proto, "implicit_float" , 25, label, FD::TYPE_FLOAT );
1698   AddField(message_proto, "implicit_double", 26, label, FD::TYPE_DOUBLE);
1699   AddField(message_proto, "implicit_bool"  , 27, label, FD::TYPE_BOOL  );
1700   AddField(message_proto, "implicit_string", 28, label, FD::TYPE_STRING);
1701   AddField(message_proto, "implicit_data"  , 29, label, FD::TYPE_BYTES );
1702   AddField(message_proto, "implicit_enum"  , 30, label, FD::TYPE_ENUM)
1703     ->set_type_name("DummyEnum");
1704 
1705   // Build it.
1706   DescriptorPool pool;
1707   const FileDescriptor* file = pool.BuildFile(file_proto);
1708   ASSERT_TRUE(file != NULL);
1709 
1710   ASSERT_EQ(1, file->enum_type_count());
1711   const EnumDescriptor* enum_type = file->enum_type(0);
1712   ASSERT_EQ(2, enum_type->value_count());
1713   const EnumValueDescriptor* enum_value_a = enum_type->value(0);
1714   const EnumValueDescriptor* enum_value_b = enum_type->value(1);
1715 
1716   ASSERT_EQ(1, file->message_type_count());
1717   const Descriptor* message = file->message_type(0);
1718 
1719   ASSERT_EQ(21, message->field_count());
1720 
1721   // Check the default values.
1722   ASSERT_TRUE(message->field(0)->has_default_value());
1723   ASSERT_TRUE(message->field(1)->has_default_value());
1724   ASSERT_TRUE(message->field(2)->has_default_value());
1725   ASSERT_TRUE(message->field(3)->has_default_value());
1726   ASSERT_TRUE(message->field(4)->has_default_value());
1727   ASSERT_TRUE(message->field(5)->has_default_value());
1728   ASSERT_TRUE(message->field(6)->has_default_value());
1729   ASSERT_TRUE(message->field(7)->has_default_value());
1730   ASSERT_TRUE(message->field(8)->has_default_value());
1731   ASSERT_TRUE(message->field(9)->has_default_value());
1732   ASSERT_TRUE(message->field(10)->has_default_value());
1733 
1734   EXPECT_EQ(-1              , message->field(0)->default_value_int32 ());
1735   EXPECT_EQ(-GOOGLE_ULONGLONG(1000000000000),
1736             message->field(1)->default_value_int64 ());
1737   EXPECT_EQ(42              , message->field(2)->default_value_uint32());
1738   EXPECT_EQ(GOOGLE_ULONGLONG(2000000000000),
1739             message->field(3)->default_value_uint64());
1740   EXPECT_EQ(4.5             , message->field(4)->default_value_float ());
1741   EXPECT_EQ(10e100          , message->field(5)->default_value_double());
1742   EXPECT_TRUE(                message->field(6)->default_value_bool  ());
1743   EXPECT_EQ("hello"         , message->field(7)->default_value_string());
1744   EXPECT_EQ("\001\002\003"  , message->field(8)->default_value_string());
1745   EXPECT_EQ(enum_value_b    , message->field(9)->default_value_enum  ());
1746   EXPECT_EQ(""              , message->field(10)->default_value_string());
1747 
1748   ASSERT_FALSE(message->field(11)->has_default_value());
1749   ASSERT_FALSE(message->field(12)->has_default_value());
1750   ASSERT_FALSE(message->field(13)->has_default_value());
1751   ASSERT_FALSE(message->field(14)->has_default_value());
1752   ASSERT_FALSE(message->field(15)->has_default_value());
1753   ASSERT_FALSE(message->field(16)->has_default_value());
1754   ASSERT_FALSE(message->field(17)->has_default_value());
1755   ASSERT_FALSE(message->field(18)->has_default_value());
1756   ASSERT_FALSE(message->field(19)->has_default_value());
1757   ASSERT_FALSE(message->field(20)->has_default_value());
1758 
1759   EXPECT_EQ(0    , message->field(11)->default_value_int32 ());
1760   EXPECT_EQ(0    , message->field(12)->default_value_int64 ());
1761   EXPECT_EQ(0    , message->field(13)->default_value_uint32());
1762   EXPECT_EQ(0    , message->field(14)->default_value_uint64());
1763   EXPECT_EQ(0.0f , message->field(15)->default_value_float ());
1764   EXPECT_EQ(0.0  , message->field(16)->default_value_double());
1765   EXPECT_FALSE(    message->field(17)->default_value_bool  ());
1766   EXPECT_EQ(""   , message->field(18)->default_value_string());
1767   EXPECT_EQ(""   , message->field(19)->default_value_string());
1768   EXPECT_EQ(enum_value_a, message->field(20)->default_value_enum());
1769 }
1770 
TEST_F(MiscTest,FieldOptions)1771 TEST_F(MiscTest, FieldOptions) {
1772   // Try setting field options.
1773 
1774   FileDescriptorProto file_proto;
1775   file_proto.set_name("foo.proto");
1776 
1777   DescriptorProto* message_proto = AddMessage(&file_proto, "TestMessage");
1778   AddField(message_proto, "foo", 1,
1779            FieldDescriptorProto::LABEL_OPTIONAL,
1780            FieldDescriptorProto::TYPE_INT32);
1781   FieldDescriptorProto* bar_proto =
1782     AddField(message_proto, "bar", 2,
1783              FieldDescriptorProto::LABEL_OPTIONAL,
1784              FieldDescriptorProto::TYPE_INT32);
1785 
1786   FieldOptions* options = bar_proto->mutable_options();
1787   options->set_ctype(FieldOptions::CORD);
1788 
1789   // Build the descriptors and get the pointers.
1790   DescriptorPool pool;
1791   const FileDescriptor* file = pool.BuildFile(file_proto);
1792   ASSERT_TRUE(file != NULL);
1793 
1794   ASSERT_EQ(1, file->message_type_count());
1795   const Descriptor* message = file->message_type(0);
1796 
1797   ASSERT_EQ(2, message->field_count());
1798   const FieldDescriptor* foo = message->field(0);
1799   const FieldDescriptor* bar = message->field(1);
1800 
1801   // "foo" had no options set, so it should return the default options.
1802   EXPECT_EQ(&FieldOptions::default_instance(), &foo->options());
1803 
1804   // "bar" had options set.
1805   EXPECT_NE(&FieldOptions::default_instance(), options);
1806   EXPECT_TRUE(bar->options().has_ctype());
1807   EXPECT_EQ(FieldOptions::CORD, bar->options().ctype());
1808 }
1809 
1810 // ===================================================================
1811 enum DescriptorPoolMode {
1812   NO_DATABASE,
1813   FALLBACK_DATABASE
1814 };
1815 
1816 class AllowUnknownDependenciesTest
1817     : public testing::TestWithParam<DescriptorPoolMode> {
1818  protected:
mode()1819   DescriptorPoolMode mode() {
1820     return GetParam();
1821    }
1822 
SetUp()1823   virtual void SetUp() {
1824     FileDescriptorProto foo_proto, bar_proto;
1825 
1826     switch (mode()) {
1827       case NO_DATABASE:
1828         pool_.reset(new DescriptorPool);
1829         break;
1830       case FALLBACK_DATABASE:
1831         pool_.reset(new DescriptorPool(&db_));
1832         break;
1833     }
1834 
1835     pool_->AllowUnknownDependencies();
1836 
1837     ASSERT_TRUE(TextFormat::ParseFromString(
1838       "name: 'foo.proto'"
1839       "dependency: 'bar.proto'"
1840       "dependency: 'baz.proto'"
1841       "message_type {"
1842       "  name: 'Foo'"
1843       "  field { name:'bar' number:1 label:LABEL_OPTIONAL type_name:'Bar' }"
1844       "  field { name:'baz' number:2 label:LABEL_OPTIONAL type_name:'Baz' }"
1845       "  field { name:'qux' number:3 label:LABEL_OPTIONAL"
1846       "    type_name: '.corge.Qux'"
1847       "    type: TYPE_ENUM"
1848       "    options {"
1849       "      uninterpreted_option {"
1850       "        name {"
1851       "          name_part: 'grault'"
1852       "          is_extension: true"
1853       "        }"
1854       "        positive_int_value: 1234"
1855       "      }"
1856       "    }"
1857       "  }"
1858       "}",
1859       &foo_proto));
1860     ASSERT_TRUE(TextFormat::ParseFromString(
1861       "name: 'bar.proto'"
1862       "message_type { name: 'Bar' }",
1863       &bar_proto));
1864 
1865     // Collect pointers to stuff.
1866     bar_file_ = BuildFile(bar_proto);
1867     ASSERT_TRUE(bar_file_ != NULL);
1868 
1869     ASSERT_EQ(1, bar_file_->message_type_count());
1870     bar_type_ = bar_file_->message_type(0);
1871 
1872     foo_file_ = BuildFile(foo_proto);
1873     ASSERT_TRUE(foo_file_ != NULL);
1874 
1875     ASSERT_EQ(1, foo_file_->message_type_count());
1876     foo_type_ = foo_file_->message_type(0);
1877 
1878     ASSERT_EQ(3, foo_type_->field_count());
1879     bar_field_ = foo_type_->field(0);
1880     baz_field_ = foo_type_->field(1);
1881     qux_field_ = foo_type_->field(2);
1882   }
1883 
BuildFile(const FileDescriptorProto & proto)1884   const FileDescriptor* BuildFile(const FileDescriptorProto& proto) {
1885     switch (mode()) {
1886       case NO_DATABASE:
1887         return pool_->BuildFile(proto);
1888         break;
1889       case FALLBACK_DATABASE: {
1890         EXPECT_TRUE(db_.Add(proto));
1891         return pool_->FindFileByName(proto.name());
1892       }
1893     }
1894     GOOGLE_LOG(FATAL) << "Can't get here.";
1895     return NULL;
1896   }
1897 
1898   const FileDescriptor* bar_file_;
1899   const Descriptor* bar_type_;
1900   const FileDescriptor* foo_file_;
1901   const Descriptor* foo_type_;
1902   const FieldDescriptor* bar_field_;
1903   const FieldDescriptor* baz_field_;
1904   const FieldDescriptor* qux_field_;
1905 
1906   SimpleDescriptorDatabase db_;        // used if in FALLBACK_DATABASE mode.
1907   scoped_ptr<DescriptorPool> pool_;
1908 };
1909 
TEST_P(AllowUnknownDependenciesTest,PlaceholderFile)1910 TEST_P(AllowUnknownDependenciesTest, PlaceholderFile) {
1911   ASSERT_EQ(2, foo_file_->dependency_count());
1912   EXPECT_EQ(bar_file_, foo_file_->dependency(0));
1913 
1914   const FileDescriptor* baz_file = foo_file_->dependency(1);
1915   EXPECT_EQ("baz.proto", baz_file->name());
1916   EXPECT_EQ(0, baz_file->message_type_count());
1917 
1918   // Placeholder files should not be findable.
1919   EXPECT_EQ(bar_file_, pool_->FindFileByName(bar_file_->name()));
1920   EXPECT_TRUE(pool_->FindFileByName(baz_file->name()) == NULL);
1921 }
1922 
TEST_P(AllowUnknownDependenciesTest,PlaceholderTypes)1923 TEST_P(AllowUnknownDependenciesTest, PlaceholderTypes) {
1924   ASSERT_EQ(FieldDescriptor::TYPE_MESSAGE, bar_field_->type());
1925   EXPECT_EQ(bar_type_, bar_field_->message_type());
1926 
1927   ASSERT_EQ(FieldDescriptor::TYPE_MESSAGE, baz_field_->type());
1928   const Descriptor* baz_type = baz_field_->message_type();
1929   EXPECT_EQ("Baz", baz_type->name());
1930   EXPECT_EQ("Baz", baz_type->full_name());
1931   EXPECT_EQ("Baz.placeholder.proto", baz_type->file()->name());
1932   EXPECT_EQ(0, baz_type->extension_range_count());
1933 
1934   ASSERT_EQ(FieldDescriptor::TYPE_ENUM, qux_field_->type());
1935   const EnumDescriptor* qux_type = qux_field_->enum_type();
1936   EXPECT_EQ("Qux", qux_type->name());
1937   EXPECT_EQ("corge.Qux", qux_type->full_name());
1938   EXPECT_EQ("corge.Qux.placeholder.proto", qux_type->file()->name());
1939 
1940   // Placeholder types should not be findable.
1941   EXPECT_EQ(bar_type_, pool_->FindMessageTypeByName(bar_type_->full_name()));
1942   EXPECT_TRUE(pool_->FindMessageTypeByName(baz_type->full_name()) == NULL);
1943   EXPECT_TRUE(pool_->FindEnumTypeByName(qux_type->full_name()) == NULL);
1944 }
1945 
TEST_P(AllowUnknownDependenciesTest,CopyTo)1946 TEST_P(AllowUnknownDependenciesTest, CopyTo) {
1947   // FieldDescriptor::CopyTo() should write non-fully-qualified type names
1948   // for placeholder types which were not originally fully-qualified.
1949   FieldDescriptorProto proto;
1950 
1951   // Bar is not a placeholder, so it is fully-qualified.
1952   bar_field_->CopyTo(&proto);
1953   EXPECT_EQ(".Bar", proto.type_name());
1954   EXPECT_EQ(FieldDescriptorProto::TYPE_MESSAGE, proto.type());
1955 
1956   // Baz is an unqualified placeholder.
1957   proto.Clear();
1958   baz_field_->CopyTo(&proto);
1959   EXPECT_EQ("Baz", proto.type_name());
1960   EXPECT_FALSE(proto.has_type());
1961 
1962   // Qux is a fully-qualified placeholder.
1963   proto.Clear();
1964   qux_field_->CopyTo(&proto);
1965   EXPECT_EQ(".corge.Qux", proto.type_name());
1966   EXPECT_EQ(FieldDescriptorProto::TYPE_ENUM, proto.type());
1967 }
1968 
TEST_P(AllowUnknownDependenciesTest,CustomOptions)1969 TEST_P(AllowUnknownDependenciesTest, CustomOptions) {
1970   // Qux should still have the uninterpreted option attached.
1971   ASSERT_EQ(1, qux_field_->options().uninterpreted_option_size());
1972   const UninterpretedOption& option =
1973     qux_field_->options().uninterpreted_option(0);
1974   ASSERT_EQ(1, option.name_size());
1975   EXPECT_EQ("grault", option.name(0).name_part());
1976 }
1977 
TEST_P(AllowUnknownDependenciesTest,UnknownExtendee)1978 TEST_P(AllowUnknownDependenciesTest, UnknownExtendee) {
1979   // Test that we can extend an unknown type.  This is slightly tricky because
1980   // it means that the placeholder type must have an extension range.
1981 
1982   FileDescriptorProto extension_proto;
1983 
1984   ASSERT_TRUE(TextFormat::ParseFromString(
1985     "name: 'extension.proto'"
1986     "extension { extendee: 'UnknownType' name:'some_extension' number:123"
1987     "            label:LABEL_OPTIONAL type:TYPE_INT32 }",
1988     &extension_proto));
1989   const FileDescriptor* file = BuildFile(extension_proto);
1990 
1991   ASSERT_TRUE(file != NULL);
1992 
1993   ASSERT_EQ(1, file->extension_count());
1994   const Descriptor* extendee = file->extension(0)->containing_type();
1995   EXPECT_EQ("UnknownType", extendee->name());
1996   ASSERT_EQ(1, extendee->extension_range_count());
1997   EXPECT_EQ(1, extendee->extension_range(0)->start);
1998   EXPECT_EQ(FieldDescriptor::kMaxNumber + 1, extendee->extension_range(0)->end);
1999 }
2000 
TEST_P(AllowUnknownDependenciesTest,CustomOption)2001 TEST_P(AllowUnknownDependenciesTest, CustomOption) {
2002   // Test that we can use a custom option without having parsed
2003   // descriptor.proto.
2004 
2005   FileDescriptorProto option_proto;
2006 
2007   ASSERT_TRUE(TextFormat::ParseFromString(
2008     "name: \"unknown_custom_options.proto\" "
2009     "dependency: \"google/protobuf/descriptor.proto\" "
2010     "extension { "
2011     "  extendee: \"google.protobuf.FileOptions\" "
2012     "  name: \"some_option\" "
2013     "  number: 123456 "
2014     "  label: LABEL_OPTIONAL "
2015     "  type: TYPE_INT32 "
2016     "} "
2017     "options { "
2018     "  uninterpreted_option { "
2019     "    name { "
2020     "      name_part: \"some_option\" "
2021     "      is_extension: true "
2022     "    } "
2023     "    positive_int_value: 1234 "
2024     "  } "
2025     "  uninterpreted_option { "
2026     "    name { "
2027     "      name_part: \"unknown_option\" "
2028     "      is_extension: true "
2029     "    } "
2030     "    positive_int_value: 1234 "
2031     "  } "
2032     "  uninterpreted_option { "
2033     "    name { "
2034     "      name_part: \"optimize_for\" "
2035     "      is_extension: false "
2036     "    } "
2037     "    identifier_value: \"SPEED\" "
2038     "  } "
2039     "}",
2040     &option_proto));
2041 
2042   const FileDescriptor* file = BuildFile(option_proto);
2043   ASSERT_TRUE(file != NULL);
2044 
2045   // Verify that no extension options were set, but they were left as
2046   // uninterpreted_options.
2047   vector<const FieldDescriptor*> fields;
2048   file->options().GetReflection()->ListFields(file->options(), &fields);
2049   ASSERT_EQ(2, fields.size());
2050   EXPECT_TRUE(file->options().has_optimize_for());
2051   EXPECT_EQ(2, file->options().uninterpreted_option_size());
2052 }
2053 
TEST_P(AllowUnknownDependenciesTest,UndeclaredDependencyTriggersBuildOfDependency)2054 TEST_P(AllowUnknownDependenciesTest,
2055        UndeclaredDependencyTriggersBuildOfDependency) {
2056   // Crazy case: suppose foo.proto refers to a symbol without declaring the
2057   // dependency that finds it. In the event that the pool is backed by a
2058   // DescriptorDatabase, the pool will attempt to find the symbol in the
2059   // database. If successful, it will build the undeclared dependency to verify
2060   // that the file does indeed contain the symbol. If that file fails to build,
2061   // then its descriptors must be rolled back. However, we still want foo.proto
2062   // to build successfully, since we are allowing unknown dependencies.
2063 
2064   FileDescriptorProto undeclared_dep_proto;
2065   // We make this file fail to build by giving it two fields with tag 1.
2066   ASSERT_TRUE(TextFormat::ParseFromString(
2067     "name: \"invalid_file_as_undeclared_dep.proto\" "
2068     "package: \"undeclared\" "
2069     "message_type: {  "
2070     "  name: \"Quux\"  "
2071     "  field { "
2072     "    name:'qux' number:1 label:LABEL_OPTIONAL type: TYPE_INT32 "
2073     "  }"
2074     "  field { "
2075     "    name:'quux' number:1 label:LABEL_OPTIONAL type: TYPE_INT64 "
2076     "  }"
2077     "}",
2078     &undeclared_dep_proto));
2079   // We can't use the BuildFile() helper because we don't actually want to build
2080   // it into the descriptor pool in the fallback database case: it just needs to
2081   // be sitting in the database so that it gets built during the building of
2082   // test.proto below.
2083   switch (mode()) {
2084     case NO_DATABASE: {
2085       ASSERT_TRUE(pool_->BuildFile(undeclared_dep_proto) == NULL);
2086       break;
2087     }
2088     case FALLBACK_DATABASE: {
2089       ASSERT_TRUE(db_.Add(undeclared_dep_proto));
2090     }
2091   }
2092 
2093   FileDescriptorProto test_proto;
2094   ASSERT_TRUE(TextFormat::ParseFromString(
2095     "name: \"test.proto\" "
2096     "message_type: { "
2097     "  name: \"Corge\" "
2098     "  field { "
2099     "    name:'quux' number:1 label: LABEL_OPTIONAL "
2100     "    type_name:'undeclared.Quux' type: TYPE_MESSAGE "
2101     "  }"
2102     "}",
2103     &test_proto));
2104 
2105   const FileDescriptor* file = BuildFile(test_proto);
2106   ASSERT_TRUE(file != NULL);
2107   GOOGLE_LOG(INFO) << file->DebugString();
2108 
2109   EXPECT_EQ(0, file->dependency_count());
2110   ASSERT_EQ(1, file->message_type_count());
2111   const Descriptor* corge_desc = file->message_type(0);
2112   ASSERT_EQ("Corge", corge_desc->name());
2113   ASSERT_EQ(1, corge_desc->field_count());
2114 
2115   const FieldDescriptor* quux_field = corge_desc->field(0);
2116   ASSERT_EQ(FieldDescriptor::TYPE_MESSAGE, quux_field->type());
2117   ASSERT_EQ("Quux", quux_field->message_type()->name());
2118   ASSERT_EQ("undeclared.Quux", quux_field->message_type()->full_name());
2119   EXPECT_EQ("undeclared.Quux.placeholder.proto",
2120             quux_field->message_type()->file()->name());
2121   // The place holder type should not be findable.
2122   ASSERT_TRUE(pool_->FindMessageTypeByName("undeclared.Quux") == NULL);
2123 }
2124 
2125 INSTANTIATE_TEST_CASE_P(DatabaseSource,
2126                         AllowUnknownDependenciesTest,
2127                         testing::Values(NO_DATABASE, FALLBACK_DATABASE));
2128 
2129 // ===================================================================
2130 
TEST(CustomOptions,OptionLocations)2131 TEST(CustomOptions, OptionLocations) {
2132   const Descriptor* message =
2133       protobuf_unittest::TestMessageWithCustomOptions::descriptor();
2134   const FileDescriptor* file = message->file();
2135   const FieldDescriptor* field = message->FindFieldByName("field1");
2136   const EnumDescriptor* enm = message->FindEnumTypeByName("AnEnum");
2137   // TODO(benjy): Support EnumValue options, once the compiler does.
2138   const ServiceDescriptor* service =
2139       file->FindServiceByName("TestServiceWithCustomOptions");
2140   const MethodDescriptor* method = service->FindMethodByName("Foo");
2141 
2142   EXPECT_EQ(GOOGLE_LONGLONG(9876543210),
2143             file->options().GetExtension(protobuf_unittest::file_opt1));
2144   EXPECT_EQ(-56,
2145             message->options().GetExtension(protobuf_unittest::message_opt1));
2146   EXPECT_EQ(GOOGLE_LONGLONG(8765432109),
2147             field->options().GetExtension(protobuf_unittest::field_opt1));
2148   EXPECT_EQ(42,  // Check that we get the default for an option we don't set.
2149             field->options().GetExtension(protobuf_unittest::field_opt2));
2150   EXPECT_EQ(-789,
2151             enm->options().GetExtension(protobuf_unittest::enum_opt1));
2152   EXPECT_EQ(123,
2153             enm->value(1)->options().GetExtension(
2154               protobuf_unittest::enum_value_opt1));
2155   EXPECT_EQ(GOOGLE_LONGLONG(-9876543210),
2156             service->options().GetExtension(protobuf_unittest::service_opt1));
2157   EXPECT_EQ(protobuf_unittest::METHODOPT1_VAL2,
2158             method->options().GetExtension(protobuf_unittest::method_opt1));
2159 
2160   // See that the regular options went through unscathed.
2161   EXPECT_TRUE(message->options().has_message_set_wire_format());
2162   EXPECT_EQ(FieldOptions::CORD, field->options().ctype());
2163 }
2164 
TEST(CustomOptions,OptionTypes)2165 TEST(CustomOptions, OptionTypes) {
2166   const MessageOptions* options = NULL;
2167 
2168   options =
2169       &protobuf_unittest::CustomOptionMinIntegerValues::descriptor()->options();
2170   EXPECT_FALSE(        options->GetExtension(protobuf_unittest::bool_opt));
2171   EXPECT_EQ(kint32min, options->GetExtension(protobuf_unittest::int32_opt));
2172   EXPECT_EQ(kint64min, options->GetExtension(protobuf_unittest::int64_opt));
2173   EXPECT_EQ(0        , options->GetExtension(protobuf_unittest::uint32_opt));
2174   EXPECT_EQ(0        , options->GetExtension(protobuf_unittest::uint64_opt));
2175   EXPECT_EQ(kint32min, options->GetExtension(protobuf_unittest::sint32_opt));
2176   EXPECT_EQ(kint64min, options->GetExtension(protobuf_unittest::sint64_opt));
2177   EXPECT_EQ(0        , options->GetExtension(protobuf_unittest::fixed32_opt));
2178   EXPECT_EQ(0        , options->GetExtension(protobuf_unittest::fixed64_opt));
2179   EXPECT_EQ(kint32min, options->GetExtension(protobuf_unittest::sfixed32_opt));
2180   EXPECT_EQ(kint64min, options->GetExtension(protobuf_unittest::sfixed64_opt));
2181 
2182   options =
2183       &protobuf_unittest::CustomOptionMaxIntegerValues::descriptor()->options();
2184   EXPECT_TRUE(          options->GetExtension(protobuf_unittest::bool_opt));
2185   EXPECT_EQ(kint32max , options->GetExtension(protobuf_unittest::int32_opt));
2186   EXPECT_EQ(kint64max , options->GetExtension(protobuf_unittest::int64_opt));
2187   EXPECT_EQ(kuint32max, options->GetExtension(protobuf_unittest::uint32_opt));
2188   EXPECT_EQ(kuint64max, options->GetExtension(protobuf_unittest::uint64_opt));
2189   EXPECT_EQ(kint32max , options->GetExtension(protobuf_unittest::sint32_opt));
2190   EXPECT_EQ(kint64max , options->GetExtension(protobuf_unittest::sint64_opt));
2191   EXPECT_EQ(kuint32max, options->GetExtension(protobuf_unittest::fixed32_opt));
2192   EXPECT_EQ(kuint64max, options->GetExtension(protobuf_unittest::fixed64_opt));
2193   EXPECT_EQ(kint32max , options->GetExtension(protobuf_unittest::sfixed32_opt));
2194   EXPECT_EQ(kint64max , options->GetExtension(protobuf_unittest::sfixed64_opt));
2195 
2196   options =
2197       &protobuf_unittest::CustomOptionOtherValues::descriptor()->options();
2198   EXPECT_EQ(-100, options->GetExtension(protobuf_unittest::int32_opt));
2199   EXPECT_FLOAT_EQ(12.3456789,
2200                   options->GetExtension(protobuf_unittest::float_opt));
2201   EXPECT_DOUBLE_EQ(1.234567890123456789,
2202                    options->GetExtension(protobuf_unittest::double_opt));
2203   EXPECT_EQ("Hello, \"World\"",
2204             options->GetExtension(protobuf_unittest::string_opt));
2205 
2206   EXPECT_EQ(string("Hello\0World", 11),
2207             options->GetExtension(protobuf_unittest::bytes_opt));
2208 
2209   EXPECT_EQ(protobuf_unittest::DummyMessageContainingEnum::TEST_OPTION_ENUM_TYPE2,
2210             options->GetExtension(protobuf_unittest::enum_opt));
2211 
2212   options =
2213       &protobuf_unittest::SettingRealsFromPositiveInts::descriptor()->options();
2214   EXPECT_FLOAT_EQ(12, options->GetExtension(protobuf_unittest::float_opt));
2215   EXPECT_DOUBLE_EQ(154, options->GetExtension(protobuf_unittest::double_opt));
2216 
2217   options =
2218       &protobuf_unittest::SettingRealsFromNegativeInts::descriptor()->options();
2219   EXPECT_FLOAT_EQ(-12, options->GetExtension(protobuf_unittest::float_opt));
2220   EXPECT_DOUBLE_EQ(-154, options->GetExtension(protobuf_unittest::double_opt));
2221 }
2222 
TEST(CustomOptions,ComplexExtensionOptions)2223 TEST(CustomOptions, ComplexExtensionOptions) {
2224   const MessageOptions* options =
2225       &protobuf_unittest::VariousComplexOptions::descriptor()->options();
2226   EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt1).foo(), 42);
2227   EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt1).
2228             GetExtension(protobuf_unittest::quux), 324);
2229   EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt1).
2230             GetExtension(protobuf_unittest::corge).qux(), 876);
2231   EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).baz(), 987);
2232   EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).
2233             GetExtension(protobuf_unittest::grault), 654);
2234   EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).bar().foo(),
2235             743);
2236   EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).bar().
2237             GetExtension(protobuf_unittest::quux), 1999);
2238   EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).bar().
2239             GetExtension(protobuf_unittest::corge).qux(), 2008);
2240   EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).
2241             GetExtension(protobuf_unittest::garply).foo(), 741);
2242   EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).
2243             GetExtension(protobuf_unittest::garply).
2244             GetExtension(protobuf_unittest::quux), 1998);
2245   EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).
2246             GetExtension(protobuf_unittest::garply).
2247             GetExtension(protobuf_unittest::corge).qux(), 2121);
2248   EXPECT_EQ(options->GetExtension(
2249       protobuf_unittest::ComplexOptionType2::ComplexOptionType4::complex_opt4).
2250             waldo(), 1971);
2251   EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).
2252             fred().waldo(), 321);
2253   EXPECT_EQ(9, options->GetExtension(protobuf_unittest::complex_opt3).qux());
2254   EXPECT_EQ(22, options->GetExtension(protobuf_unittest::complex_opt3).
2255                 complexoptiontype5().plugh());
2256   EXPECT_EQ(24, options->GetExtension(protobuf_unittest::complexopt6).xyzzy());
2257 }
2258 
TEST(CustomOptions,OptionsFromOtherFile)2259 TEST(CustomOptions, OptionsFromOtherFile) {
2260   // Test that to use a custom option, we only need to import the file
2261   // defining the option; we do not also have to import descriptor.proto.
2262   DescriptorPool pool;
2263 
2264   FileDescriptorProto file_proto;
2265   FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto);
2266   ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
2267 
2268   protobuf_unittest::TestMessageWithCustomOptions::descriptor()
2269     ->file()->CopyTo(&file_proto);
2270   ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
2271 
2272   ASSERT_TRUE(TextFormat::ParseFromString(
2273     "name: \"custom_options_import.proto\" "
2274     "package: \"protobuf_unittest\" "
2275     "dependency: \"google/protobuf/unittest_custom_options.proto\" "
2276     "options { "
2277     "  uninterpreted_option { "
2278     "    name { "
2279     "      name_part: \"file_opt1\" "
2280     "      is_extension: true "
2281     "    } "
2282     "    positive_int_value: 1234 "
2283     "  } "
2284     // Test a non-extension option too.  (At one point this failed due to a
2285     // bug.)
2286     "  uninterpreted_option { "
2287     "    name { "
2288     "      name_part: \"java_package\" "
2289     "      is_extension: false "
2290     "    } "
2291     "    string_value: \"foo\" "
2292     "  } "
2293     // Test that enum-typed options still work too.  (At one point this also
2294     // failed due to a bug.)
2295     "  uninterpreted_option { "
2296     "    name { "
2297     "      name_part: \"optimize_for\" "
2298     "      is_extension: false "
2299     "    } "
2300     "    identifier_value: \"SPEED\" "
2301     "  } "
2302     "}"
2303     ,
2304     &file_proto));
2305 
2306   const FileDescriptor* file = pool.BuildFile(file_proto);
2307   ASSERT_TRUE(file != NULL);
2308   EXPECT_EQ(1234, file->options().GetExtension(protobuf_unittest::file_opt1));
2309   EXPECT_TRUE(file->options().has_java_package());
2310   EXPECT_EQ("foo", file->options().java_package());
2311   EXPECT_TRUE(file->options().has_optimize_for());
2312   EXPECT_EQ(FileOptions::SPEED, file->options().optimize_for());
2313 }
2314 
TEST(CustomOptions,MessageOptionThreeFieldsSet)2315 TEST(CustomOptions, MessageOptionThreeFieldsSet) {
2316   // This tests a bug which previously existed in custom options parsing.  The
2317   // bug occurred when you defined a custom option with message type and then
2318   // set three fields of that option on a single definition (see the example
2319   // below).  The bug is a bit hard to explain, so check the change history if
2320   // you want to know more.
2321   DescriptorPool pool;
2322 
2323   FileDescriptorProto file_proto;
2324   FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto);
2325   ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
2326 
2327   protobuf_unittest::TestMessageWithCustomOptions::descriptor()
2328     ->file()->CopyTo(&file_proto);
2329   ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
2330 
2331   // The following represents the definition:
2332   //
2333   //   import "google/protobuf/unittest_custom_options.proto"
2334   //   package protobuf_unittest;
2335   //   message Foo {
2336   //     option (complex_opt1).foo  = 1234;
2337   //     option (complex_opt1).foo2 = 1234;
2338   //     option (complex_opt1).foo3 = 1234;
2339   //   }
2340   ASSERT_TRUE(TextFormat::ParseFromString(
2341     "name: \"custom_options_import.proto\" "
2342     "package: \"protobuf_unittest\" "
2343     "dependency: \"google/protobuf/unittest_custom_options.proto\" "
2344     "message_type { "
2345     "  name: \"Foo\" "
2346     "  options { "
2347     "    uninterpreted_option { "
2348     "      name { "
2349     "        name_part: \"complex_opt1\" "
2350     "        is_extension: true "
2351     "      } "
2352     "      name { "
2353     "        name_part: \"foo\" "
2354     "        is_extension: false "
2355     "      } "
2356     "      positive_int_value: 1234 "
2357     "    } "
2358     "    uninterpreted_option { "
2359     "      name { "
2360     "        name_part: \"complex_opt1\" "
2361     "        is_extension: true "
2362     "      } "
2363     "      name { "
2364     "        name_part: \"foo2\" "
2365     "        is_extension: false "
2366     "      } "
2367     "      positive_int_value: 1234 "
2368     "    } "
2369     "    uninterpreted_option { "
2370     "      name { "
2371     "        name_part: \"complex_opt1\" "
2372     "        is_extension: true "
2373     "      } "
2374     "      name { "
2375     "        name_part: \"foo3\" "
2376     "        is_extension: false "
2377     "      } "
2378     "      positive_int_value: 1234 "
2379     "    } "
2380     "  } "
2381     "}",
2382     &file_proto));
2383 
2384   const FileDescriptor* file = pool.BuildFile(file_proto);
2385   ASSERT_TRUE(file != NULL);
2386   ASSERT_EQ(1, file->message_type_count());
2387 
2388   const MessageOptions& options = file->message_type(0)->options();
2389   EXPECT_EQ(1234, options.GetExtension(protobuf_unittest::complex_opt1).foo());
2390 }
2391 
2392 // Check that aggregate options were parsed and saved correctly in
2393 // the appropriate descriptors.
TEST(CustomOptions,AggregateOptions)2394 TEST(CustomOptions, AggregateOptions) {
2395   const Descriptor* msg = protobuf_unittest::AggregateMessage::descriptor();
2396   const FileDescriptor* file = msg->file();
2397   const FieldDescriptor* field = msg->FindFieldByName("fieldname");
2398   const EnumDescriptor* enumd = file->FindEnumTypeByName("AggregateEnum");
2399   const EnumValueDescriptor* enumv = enumd->FindValueByName("VALUE");
2400   const ServiceDescriptor* service = file->FindServiceByName(
2401       "AggregateService");
2402   const MethodDescriptor* method = service->FindMethodByName("Method");
2403 
2404   // Tests for the different types of data embedded in fileopt
2405   const protobuf_unittest::Aggregate& file_options =
2406       file->options().GetExtension(protobuf_unittest::fileopt);
2407   EXPECT_EQ(100, file_options.i());
2408   EXPECT_EQ("FileAnnotation", file_options.s());
2409   EXPECT_EQ("NestedFileAnnotation", file_options.sub().s());
2410   EXPECT_EQ("FileExtensionAnnotation",
2411             file_options.file().GetExtension(protobuf_unittest::fileopt).s());
2412   EXPECT_EQ("EmbeddedMessageSetElement",
2413             file_options.mset().GetExtension(
2414                 protobuf_unittest::AggregateMessageSetElement
2415                 ::message_set_extension).s());
2416 
2417   // Simple tests for all the other types of annotations
2418   EXPECT_EQ("MessageAnnotation",
2419             msg->options().GetExtension(protobuf_unittest::msgopt).s());
2420   EXPECT_EQ("FieldAnnotation",
2421             field->options().GetExtension(protobuf_unittest::fieldopt).s());
2422   EXPECT_EQ("EnumAnnotation",
2423             enumd->options().GetExtension(protobuf_unittest::enumopt).s());
2424   EXPECT_EQ("EnumValueAnnotation",
2425             enumv->options().GetExtension(protobuf_unittest::enumvalopt).s());
2426   EXPECT_EQ("ServiceAnnotation",
2427             service->options().GetExtension(protobuf_unittest::serviceopt).s());
2428   EXPECT_EQ("MethodAnnotation",
2429             method->options().GetExtension(protobuf_unittest::methodopt).s());
2430 }
2431 
2432 // ===================================================================
2433 
2434 // The tests below trigger every unique call to AddError() in descriptor.cc,
2435 // in the order in which they appear in that file.  I'm using TextFormat here
2436 // to specify the input descriptors because building them using code would
2437 // be too bulky.
2438 
2439 class MockErrorCollector : public DescriptorPool::ErrorCollector {
2440  public:
MockErrorCollector()2441   MockErrorCollector() {}
~MockErrorCollector()2442   ~MockErrorCollector() {}
2443 
2444   string text_;
2445 
2446   // implements ErrorCollector ---------------------------------------
AddError(const string & filename,const string & element_name,const Message * descriptor,ErrorLocation location,const string & message)2447   void AddError(const string& filename,
2448                 const string& element_name, const Message* descriptor,
2449                 ErrorLocation location, const string& message) {
2450     const char* location_name = NULL;
2451     switch (location) {
2452       case NAME         : location_name = "NAME"         ; break;
2453       case NUMBER       : location_name = "NUMBER"       ; break;
2454       case TYPE         : location_name = "TYPE"         ; break;
2455       case EXTENDEE     : location_name = "EXTENDEE"     ; break;
2456       case DEFAULT_VALUE: location_name = "DEFAULT_VALUE"; break;
2457       case OPTION_NAME  : location_name = "OPTION_NAME"  ; break;
2458       case OPTION_VALUE : location_name = "OPTION_VALUE" ; break;
2459       case INPUT_TYPE   : location_name = "INPUT_TYPE"   ; break;
2460       case OUTPUT_TYPE  : location_name = "OUTPUT_TYPE"  ; break;
2461       case OTHER        : location_name = "OTHER"        ; break;
2462     }
2463 
2464     strings::SubstituteAndAppend(
2465       &text_, "$0: $1: $2: $3\n",
2466       filename, element_name, location_name, message);
2467   }
2468 };
2469 
2470 class ValidationErrorTest : public testing::Test {
2471  protected:
2472   // Parse file_text as a FileDescriptorProto in text format and add it
2473   // to the DescriptorPool.  Expect no errors.
BuildFile(const string & file_text)2474   void BuildFile(const string& file_text) {
2475     FileDescriptorProto file_proto;
2476     ASSERT_TRUE(TextFormat::ParseFromString(file_text, &file_proto));
2477     ASSERT_TRUE(pool_.BuildFile(file_proto) != NULL);
2478   }
2479 
2480   // Parse file_text as a FileDescriptorProto in text format and add it
2481   // to the DescriptorPool.  Expect errors to be produced which match the
2482   // given error text.
BuildFileWithErrors(const string & file_text,const string & expected_errors)2483   void BuildFileWithErrors(const string& file_text,
2484                            const string& expected_errors) {
2485     FileDescriptorProto file_proto;
2486     ASSERT_TRUE(TextFormat::ParseFromString(file_text, &file_proto));
2487 
2488     MockErrorCollector error_collector;
2489     EXPECT_TRUE(
2490       pool_.BuildFileCollectingErrors(file_proto, &error_collector) == NULL);
2491     EXPECT_EQ(expected_errors, error_collector.text_);
2492   }
2493 
2494   // Builds some already-parsed file in our test pool.
BuildFileInTestPool(const FileDescriptor * file)2495   void BuildFileInTestPool(const FileDescriptor* file) {
2496     FileDescriptorProto file_proto;
2497     file->CopyTo(&file_proto);
2498     ASSERT_TRUE(pool_.BuildFile(file_proto) != NULL);
2499   }
2500 
2501   // Build descriptor.proto in our test pool. This allows us to extend it in
2502   // the test pool, so we can test custom options.
BuildDescriptorMessagesInTestPool()2503   void BuildDescriptorMessagesInTestPool() {
2504     BuildFileInTestPool(DescriptorProto::descriptor()->file());
2505   }
2506 
2507   DescriptorPool pool_;
2508 };
2509 
TEST_F(ValidationErrorTest,AlreadyDefined)2510 TEST_F(ValidationErrorTest, AlreadyDefined) {
2511   BuildFileWithErrors(
2512     "name: \"foo.proto\" "
2513     "message_type { name: \"Foo\" }"
2514     "message_type { name: \"Foo\" }",
2515 
2516     "foo.proto: Foo: NAME: \"Foo\" is already defined.\n");
2517 }
2518 
TEST_F(ValidationErrorTest,AlreadyDefinedInPackage)2519 TEST_F(ValidationErrorTest, AlreadyDefinedInPackage) {
2520   BuildFileWithErrors(
2521     "name: \"foo.proto\" "
2522     "package: \"foo.bar\" "
2523     "message_type { name: \"Foo\" }"
2524     "message_type { name: \"Foo\" }",
2525 
2526     "foo.proto: foo.bar.Foo: NAME: \"Foo\" is already defined in "
2527       "\"foo.bar\".\n");
2528 }
2529 
TEST_F(ValidationErrorTest,AlreadyDefinedInOtherFile)2530 TEST_F(ValidationErrorTest, AlreadyDefinedInOtherFile) {
2531   BuildFile(
2532     "name: \"foo.proto\" "
2533     "message_type { name: \"Foo\" }");
2534 
2535   BuildFileWithErrors(
2536     "name: \"bar.proto\" "
2537     "message_type { name: \"Foo\" }",
2538 
2539     "bar.proto: Foo: NAME: \"Foo\" is already defined in file "
2540       "\"foo.proto\".\n");
2541 }
2542 
TEST_F(ValidationErrorTest,PackageAlreadyDefined)2543 TEST_F(ValidationErrorTest, PackageAlreadyDefined) {
2544   BuildFile(
2545     "name: \"foo.proto\" "
2546     "message_type { name: \"foo\" }");
2547   BuildFileWithErrors(
2548     "name: \"bar.proto\" "
2549     "package: \"foo.bar\"",
2550 
2551     "bar.proto: foo: NAME: \"foo\" is already defined (as something other "
2552       "than a package) in file \"foo.proto\".\n");
2553 }
2554 
TEST_F(ValidationErrorTest,EnumValueAlreadyDefinedInParent)2555 TEST_F(ValidationErrorTest, EnumValueAlreadyDefinedInParent) {
2556   BuildFileWithErrors(
2557     "name: \"foo.proto\" "
2558     "enum_type { name: \"Foo\" value { name: \"FOO\" number: 1 } } "
2559     "enum_type { name: \"Bar\" value { name: \"FOO\" number: 1 } } ",
2560 
2561     "foo.proto: FOO: NAME: \"FOO\" is already defined.\n"
2562     "foo.proto: FOO: NAME: Note that enum values use C++ scoping rules, "
2563       "meaning that enum values are siblings of their type, not children of "
2564       "it.  Therefore, \"FOO\" must be unique within the global scope, not "
2565       "just within \"Bar\".\n");
2566 }
2567 
TEST_F(ValidationErrorTest,EnumValueAlreadyDefinedInParentNonGlobal)2568 TEST_F(ValidationErrorTest, EnumValueAlreadyDefinedInParentNonGlobal) {
2569   BuildFileWithErrors(
2570     "name: \"foo.proto\" "
2571     "package: \"pkg\" "
2572     "enum_type { name: \"Foo\" value { name: \"FOO\" number: 1 } } "
2573     "enum_type { name: \"Bar\" value { name: \"FOO\" number: 1 } } ",
2574 
2575     "foo.proto: pkg.FOO: NAME: \"FOO\" is already defined in \"pkg\".\n"
2576     "foo.proto: pkg.FOO: NAME: Note that enum values use C++ scoping rules, "
2577       "meaning that enum values are siblings of their type, not children of "
2578       "it.  Therefore, \"FOO\" must be unique within \"pkg\", not just within "
2579       "\"Bar\".\n");
2580 }
2581 
TEST_F(ValidationErrorTest,MissingName)2582 TEST_F(ValidationErrorTest, MissingName) {
2583   BuildFileWithErrors(
2584     "name: \"foo.proto\" "
2585     "message_type { }",
2586 
2587     "foo.proto: : NAME: Missing name.\n");
2588 }
2589 
TEST_F(ValidationErrorTest,InvalidName)2590 TEST_F(ValidationErrorTest, InvalidName) {
2591   BuildFileWithErrors(
2592     "name: \"foo.proto\" "
2593     "message_type { name: \"$\" }",
2594 
2595     "foo.proto: $: NAME: \"$\" is not a valid identifier.\n");
2596 }
2597 
TEST_F(ValidationErrorTest,InvalidPackageName)2598 TEST_F(ValidationErrorTest, InvalidPackageName) {
2599   BuildFileWithErrors(
2600     "name: \"foo.proto\" "
2601     "package: \"foo.$\"",
2602 
2603     "foo.proto: foo.$: NAME: \"$\" is not a valid identifier.\n");
2604 }
2605 
TEST_F(ValidationErrorTest,MissingFileName)2606 TEST_F(ValidationErrorTest, MissingFileName) {
2607   BuildFileWithErrors(
2608     "",
2609 
2610     ": : OTHER: Missing field: FileDescriptorProto.name.\n");
2611 }
2612 
TEST_F(ValidationErrorTest,DupeDependency)2613 TEST_F(ValidationErrorTest, DupeDependency) {
2614   BuildFile("name: \"foo.proto\"");
2615   BuildFileWithErrors(
2616     "name: \"bar.proto\" "
2617     "dependency: \"foo.proto\" "
2618     "dependency: \"foo.proto\" ",
2619 
2620     "bar.proto: bar.proto: OTHER: Import \"foo.proto\" was listed twice.\n");
2621 }
2622 
TEST_F(ValidationErrorTest,UnknownDependency)2623 TEST_F(ValidationErrorTest, UnknownDependency) {
2624   BuildFileWithErrors(
2625     "name: \"bar.proto\" "
2626     "dependency: \"foo.proto\" ",
2627 
2628     "bar.proto: bar.proto: OTHER: Import \"foo.proto\" has not been loaded.\n");
2629 }
2630 
TEST_F(ValidationErrorTest,InvalidPublicDependencyIndex)2631 TEST_F(ValidationErrorTest, InvalidPublicDependencyIndex) {
2632   BuildFile("name: \"foo.proto\"");
2633   BuildFileWithErrors(
2634     "name: \"bar.proto\" "
2635     "dependency: \"foo.proto\" "
2636     "public_dependency: 1",
2637     "bar.proto: bar.proto: OTHER: Invalid public dependency index.\n");
2638 }
2639 
TEST_F(ValidationErrorTest,ForeignUnimportedPackageNoCrash)2640 TEST_F(ValidationErrorTest, ForeignUnimportedPackageNoCrash) {
2641   // Used to crash:  If we depend on a non-existent file and then refer to a
2642   // package defined in a file that we didn't import, and that package is
2643   // nested within a parent package which this file is also in, and we don't
2644   // include that parent package in the name (i.e. we do a relative lookup)...
2645   // Yes, really.
2646   BuildFile(
2647     "name: 'foo.proto' "
2648     "package: 'outer.foo' ");
2649   BuildFileWithErrors(
2650     "name: 'bar.proto' "
2651     "dependency: 'baz.proto' "
2652     "package: 'outer.bar' "
2653     "message_type { "
2654     "  name: 'Bar' "
2655     "  field { name:'bar' number:1 label:LABEL_OPTIONAL type_name:'foo.Foo' }"
2656     "}",
2657 
2658     "bar.proto: bar.proto: OTHER: Import \"baz.proto\" has not been loaded.\n"
2659     "bar.proto: outer.bar.Bar.bar: TYPE: \"outer.foo\" seems to be defined in "
2660       "\"foo.proto\", which is not imported by \"bar.proto\".  To use it here, "
2661       "please add the necessary import.\n");
2662 }
2663 
TEST_F(ValidationErrorTest,DupeFile)2664 TEST_F(ValidationErrorTest, DupeFile) {
2665   BuildFile(
2666     "name: \"foo.proto\" "
2667     "message_type { name: \"Foo\" }");
2668   // Note:  We should *not* get redundant errors about "Foo" already being
2669   //   defined.
2670   BuildFileWithErrors(
2671     "name: \"foo.proto\" "
2672     "message_type { name: \"Foo\" } "
2673     // Add another type so that the files aren't identical (in which case there
2674     // would be no error).
2675     "enum_type { name: \"Bar\" }",
2676 
2677     "foo.proto: foo.proto: OTHER: A file with this name is already in the "
2678       "pool.\n");
2679 }
2680 
TEST_F(ValidationErrorTest,FieldInExtensionRange)2681 TEST_F(ValidationErrorTest, FieldInExtensionRange) {
2682   BuildFileWithErrors(
2683     "name: \"foo.proto\" "
2684     "message_type {"
2685     "  name: \"Foo\""
2686     "  field { name: \"foo\" number:  9 label:LABEL_OPTIONAL type:TYPE_INT32 }"
2687     "  field { name: \"bar\" number: 10 label:LABEL_OPTIONAL type:TYPE_INT32 }"
2688     "  field { name: \"baz\" number: 19 label:LABEL_OPTIONAL type:TYPE_INT32 }"
2689     "  field { name: \"qux\" number: 20 label:LABEL_OPTIONAL type:TYPE_INT32 }"
2690     "  extension_range { start: 10 end: 20 }"
2691     "}",
2692 
2693     "foo.proto: Foo.bar: NUMBER: Extension range 10 to 19 includes field "
2694       "\"bar\" (10).\n"
2695     "foo.proto: Foo.baz: NUMBER: Extension range 10 to 19 includes field "
2696       "\"baz\" (19).\n");
2697 }
2698 
TEST_F(ValidationErrorTest,OverlappingExtensionRanges)2699 TEST_F(ValidationErrorTest, OverlappingExtensionRanges) {
2700   BuildFileWithErrors(
2701     "name: \"foo.proto\" "
2702     "message_type {"
2703     "  name: \"Foo\""
2704     "  extension_range { start: 10 end: 20 }"
2705     "  extension_range { start: 20 end: 30 }"
2706     "  extension_range { start: 19 end: 21 }"
2707     "}",
2708 
2709     "foo.proto: Foo: NUMBER: Extension range 19 to 20 overlaps with "
2710       "already-defined range 10 to 19.\n"
2711     "foo.proto: Foo: NUMBER: Extension range 19 to 20 overlaps with "
2712       "already-defined range 20 to 29.\n");
2713 }
2714 
TEST_F(ValidationErrorTest,InvalidDefaults)2715 TEST_F(ValidationErrorTest, InvalidDefaults) {
2716   BuildFileWithErrors(
2717     "name: \"foo.proto\" "
2718     "message_type {"
2719     "  name: \"Foo\""
2720 
2721     // Invalid number.
2722     "  field { name: \"foo\" number: 1 label: LABEL_OPTIONAL type: TYPE_INT32"
2723     "          default_value: \"abc\" }"
2724 
2725     // Empty default value.
2726     "  field { name: \"bar\" number: 2 label: LABEL_OPTIONAL type: TYPE_INT32"
2727     "          default_value: \"\" }"
2728 
2729     // Invalid boolean.
2730     "  field { name: \"baz\" number: 3 label: LABEL_OPTIONAL type: TYPE_BOOL"
2731     "          default_value: \"abc\" }"
2732 
2733     // Messages can't have defaults.
2734     "  field { name: \"qux\" number: 4 label: LABEL_OPTIONAL type: TYPE_MESSAGE"
2735     "          default_value: \"abc\" type_name: \"Foo\" }"
2736 
2737     // Same thing, but we don't know that this field has message type until
2738     // we look up the type name.
2739     "  field { name: \"quux\" number: 5 label: LABEL_OPTIONAL"
2740     "          default_value: \"abc\" type_name: \"Foo\" }"
2741 
2742     // Repeateds can't have defaults.
2743     "  field { name: \"corge\" number: 6 label: LABEL_REPEATED type: TYPE_INT32"
2744     "          default_value: \"1\" }"
2745     "}",
2746 
2747     "foo.proto: Foo.foo: DEFAULT_VALUE: Couldn't parse default value.\n"
2748     "foo.proto: Foo.bar: DEFAULT_VALUE: Couldn't parse default value.\n"
2749     "foo.proto: Foo.baz: DEFAULT_VALUE: Boolean default must be true or "
2750       "false.\n"
2751     "foo.proto: Foo.qux: DEFAULT_VALUE: Messages can't have default values.\n"
2752     "foo.proto: Foo.corge: DEFAULT_VALUE: Repeated fields can't have default "
2753       "values.\n"
2754     // This ends up being reported later because the error is detected at
2755     // cross-linking time.
2756     "foo.proto: Foo.quux: DEFAULT_VALUE: Messages can't have default "
2757       "values.\n");
2758 }
2759 
TEST_F(ValidationErrorTest,NegativeFieldNumber)2760 TEST_F(ValidationErrorTest, NegativeFieldNumber) {
2761   BuildFileWithErrors(
2762     "name: \"foo.proto\" "
2763     "message_type {"
2764     "  name: \"Foo\""
2765     "  field { name: \"foo\" number: -1 label:LABEL_OPTIONAL type:TYPE_INT32 }"
2766     "}",
2767 
2768     "foo.proto: Foo.foo: NUMBER: Field numbers must be positive integers.\n");
2769 }
2770 
TEST_F(ValidationErrorTest,HugeFieldNumber)2771 TEST_F(ValidationErrorTest, HugeFieldNumber) {
2772   BuildFileWithErrors(
2773     "name: \"foo.proto\" "
2774     "message_type {"
2775     "  name: \"Foo\""
2776     "  field { name: \"foo\" number: 0x70000000 "
2777     "          label:LABEL_OPTIONAL type:TYPE_INT32 }"
2778     "}",
2779 
2780     "foo.proto: Foo.foo: NUMBER: Field numbers cannot be greater than "
2781       "536870911.\n");
2782 }
2783 
TEST_F(ValidationErrorTest,ReservedFieldNumber)2784 TEST_F(ValidationErrorTest, ReservedFieldNumber) {
2785   BuildFileWithErrors(
2786     "name: \"foo.proto\" "
2787     "message_type {"
2788     "  name: \"Foo\""
2789     "  field {name:\"foo\" number: 18999 label:LABEL_OPTIONAL type:TYPE_INT32 }"
2790     "  field {name:\"bar\" number: 19000 label:LABEL_OPTIONAL type:TYPE_INT32 }"
2791     "  field {name:\"baz\" number: 19999 label:LABEL_OPTIONAL type:TYPE_INT32 }"
2792     "  field {name:\"qux\" number: 20000 label:LABEL_OPTIONAL type:TYPE_INT32 }"
2793     "}",
2794 
2795     "foo.proto: Foo.bar: NUMBER: Field numbers 19000 through 19999 are "
2796       "reserved for the protocol buffer library implementation.\n"
2797     "foo.proto: Foo.baz: NUMBER: Field numbers 19000 through 19999 are "
2798       "reserved for the protocol buffer library implementation.\n");
2799 }
2800 
TEST_F(ValidationErrorTest,ExtensionMissingExtendee)2801 TEST_F(ValidationErrorTest, ExtensionMissingExtendee) {
2802   BuildFileWithErrors(
2803     "name: \"foo.proto\" "
2804     "message_type {"
2805     "  name: \"Foo\""
2806     "  extension { name: \"foo\" number: 1 label: LABEL_OPTIONAL"
2807     "              type_name: \"Foo\" }"
2808     "}",
2809 
2810     "foo.proto: Foo.foo: EXTENDEE: FieldDescriptorProto.extendee not set for "
2811       "extension field.\n");
2812 }
2813 
TEST_F(ValidationErrorTest,NonExtensionWithExtendee)2814 TEST_F(ValidationErrorTest, NonExtensionWithExtendee) {
2815   BuildFileWithErrors(
2816     "name: \"foo.proto\" "
2817     "message_type {"
2818     "  name: \"Bar\""
2819     "  extension_range { start: 1 end: 2 }"
2820     "}"
2821     "message_type {"
2822     "  name: \"Foo\""
2823     "  field { name: \"foo\" number: 1 label: LABEL_OPTIONAL"
2824     "          type_name: \"Foo\" extendee: \"Bar\" }"
2825     "}",
2826 
2827     "foo.proto: Foo.foo: EXTENDEE: FieldDescriptorProto.extendee set for "
2828       "non-extension field.\n");
2829 }
2830 
TEST_F(ValidationErrorTest,FieldNumberConflict)2831 TEST_F(ValidationErrorTest, FieldNumberConflict) {
2832   BuildFileWithErrors(
2833     "name: \"foo.proto\" "
2834     "message_type {"
2835     "  name: \"Foo\""
2836     "  field { name: \"foo\" number: 1 label:LABEL_OPTIONAL type:TYPE_INT32 }"
2837     "  field { name: \"bar\" number: 1 label:LABEL_OPTIONAL type:TYPE_INT32 }"
2838     "}",
2839 
2840     "foo.proto: Foo.bar: NUMBER: Field number 1 has already been used in "
2841       "\"Foo\" by field \"foo\".\n");
2842 }
2843 
TEST_F(ValidationErrorTest,BadMessageSetExtensionType)2844 TEST_F(ValidationErrorTest, BadMessageSetExtensionType) {
2845   BuildFileWithErrors(
2846     "name: \"foo.proto\" "
2847     "message_type {"
2848     "  name: \"MessageSet\""
2849     "  options { message_set_wire_format: true }"
2850     "  extension_range { start: 4 end: 5 }"
2851     "}"
2852     "message_type {"
2853     "  name: \"Foo\""
2854     "  extension { name:\"foo\" number:4 label:LABEL_OPTIONAL type:TYPE_INT32"
2855     "              extendee: \"MessageSet\" }"
2856     "}",
2857 
2858     "foo.proto: Foo.foo: TYPE: Extensions of MessageSets must be optional "
2859       "messages.\n");
2860 }
2861 
TEST_F(ValidationErrorTest,BadMessageSetExtensionLabel)2862 TEST_F(ValidationErrorTest, BadMessageSetExtensionLabel) {
2863   BuildFileWithErrors(
2864     "name: \"foo.proto\" "
2865     "message_type {"
2866     "  name: \"MessageSet\""
2867     "  options { message_set_wire_format: true }"
2868     "  extension_range { start: 4 end: 5 }"
2869     "}"
2870     "message_type {"
2871     "  name: \"Foo\""
2872     "  extension { name:\"foo\" number:4 label:LABEL_REPEATED type:TYPE_MESSAGE"
2873     "              type_name: \"Foo\" extendee: \"MessageSet\" }"
2874     "}",
2875 
2876     "foo.proto: Foo.foo: TYPE: Extensions of MessageSets must be optional "
2877       "messages.\n");
2878 }
2879 
TEST_F(ValidationErrorTest,FieldInMessageSet)2880 TEST_F(ValidationErrorTest, FieldInMessageSet) {
2881   BuildFileWithErrors(
2882     "name: \"foo.proto\" "
2883     "message_type {"
2884     "  name: \"Foo\""
2885     "  options { message_set_wire_format: true }"
2886     "  field { name: \"foo\" number: 1 label:LABEL_OPTIONAL type:TYPE_INT32 }"
2887     "}",
2888 
2889     "foo.proto: Foo.foo: NAME: MessageSets cannot have fields, only "
2890       "extensions.\n");
2891 }
2892 
TEST_F(ValidationErrorTest,NegativeExtensionRangeNumber)2893 TEST_F(ValidationErrorTest, NegativeExtensionRangeNumber) {
2894   BuildFileWithErrors(
2895     "name: \"foo.proto\" "
2896     "message_type {"
2897     "  name: \"Foo\""
2898     "  extension_range { start: -10 end: -1 }"
2899     "}",
2900 
2901     "foo.proto: Foo: NUMBER: Extension numbers must be positive integers.\n");
2902 }
2903 
TEST_F(ValidationErrorTest,HugeExtensionRangeNumber)2904 TEST_F(ValidationErrorTest, HugeExtensionRangeNumber) {
2905   BuildFileWithErrors(
2906     "name: \"foo.proto\" "
2907     "message_type {"
2908     "  name: \"Foo\""
2909     "  extension_range { start: 1 end: 0x70000000 }"
2910     "}",
2911 
2912     "foo.proto: Foo: NUMBER: Extension numbers cannot be greater than "
2913       "536870911.\n");
2914 }
2915 
TEST_F(ValidationErrorTest,ExtensionRangeEndBeforeStart)2916 TEST_F(ValidationErrorTest, ExtensionRangeEndBeforeStart) {
2917   BuildFileWithErrors(
2918     "name: \"foo.proto\" "
2919     "message_type {"
2920     "  name: \"Foo\""
2921     "  extension_range { start: 10 end: 10 }"
2922     "  extension_range { start: 10 end: 5 }"
2923     "}",
2924 
2925     "foo.proto: Foo: NUMBER: Extension range end number must be greater than "
2926       "start number.\n"
2927     "foo.proto: Foo: NUMBER: Extension range end number must be greater than "
2928       "start number.\n");
2929 }
2930 
TEST_F(ValidationErrorTest,EmptyEnum)2931 TEST_F(ValidationErrorTest, EmptyEnum) {
2932   BuildFileWithErrors(
2933     "name: \"foo.proto\" "
2934     "enum_type { name: \"Foo\" }"
2935     // Also use the empty enum in a message to make sure there are no crashes
2936     // during validation (possible if the code attempts to derive a default
2937     // value for the field).
2938     "message_type {"
2939     "  name: \"Bar\""
2940     "  field { name: \"foo\" number: 1 label:LABEL_OPTIONAL type_name:\"Foo\" }"
2941     "  field { name: \"bar\" number: 2 label:LABEL_OPTIONAL type_name:\"Foo\" "
2942     "          default_value: \"NO_SUCH_VALUE\" }"
2943     "}",
2944 
2945     "foo.proto: Foo: NAME: Enums must contain at least one value.\n"
2946     "foo.proto: Bar.bar: DEFAULT_VALUE: Enum type \"Foo\" has no value named "
2947       "\"NO_SUCH_VALUE\".\n");
2948 }
2949 
TEST_F(ValidationErrorTest,UndefinedExtendee)2950 TEST_F(ValidationErrorTest, UndefinedExtendee) {
2951   BuildFileWithErrors(
2952     "name: \"foo.proto\" "
2953     "message_type {"
2954     "  name: \"Foo\""
2955     "  extension { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32"
2956     "              extendee: \"Bar\" }"
2957     "}",
2958 
2959     "foo.proto: Foo.foo: EXTENDEE: \"Bar\" is not defined.\n");
2960 }
2961 
TEST_F(ValidationErrorTest,NonMessageExtendee)2962 TEST_F(ValidationErrorTest, NonMessageExtendee) {
2963   BuildFileWithErrors(
2964     "name: \"foo.proto\" "
2965     "enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } }"
2966     "message_type {"
2967     "  name: \"Foo\""
2968     "  extension { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32"
2969     "              extendee: \"Bar\" }"
2970     "}",
2971 
2972     "foo.proto: Foo.foo: EXTENDEE: \"Bar\" is not a message type.\n");
2973 }
2974 
TEST_F(ValidationErrorTest,NotAnExtensionNumber)2975 TEST_F(ValidationErrorTest, NotAnExtensionNumber) {
2976   BuildFileWithErrors(
2977     "name: \"foo.proto\" "
2978     "message_type {"
2979     "  name: \"Bar\""
2980     "}"
2981     "message_type {"
2982     "  name: \"Foo\""
2983     "  extension { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32"
2984     "              extendee: \"Bar\" }"
2985     "}",
2986 
2987     "foo.proto: Foo.foo: NUMBER: \"Bar\" does not declare 1 as an extension "
2988       "number.\n");
2989 }
2990 
TEST_F(ValidationErrorTest,UndefinedFieldType)2991 TEST_F(ValidationErrorTest, UndefinedFieldType) {
2992   BuildFileWithErrors(
2993     "name: \"foo.proto\" "
2994     "message_type {"
2995     "  name: \"Foo\""
2996     "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }"
2997     "}",
2998 
2999     "foo.proto: Foo.foo: TYPE: \"Bar\" is not defined.\n");
3000 }
3001 
TEST_F(ValidationErrorTest,FieldTypeDefinedInUndeclaredDependency)3002 TEST_F(ValidationErrorTest, FieldTypeDefinedInUndeclaredDependency) {
3003   BuildFile(
3004     "name: \"bar.proto\" "
3005     "message_type { name: \"Bar\" } ");
3006 
3007   BuildFileWithErrors(
3008     "name: \"foo.proto\" "
3009     "message_type {"
3010     "  name: \"Foo\""
3011     "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }"
3012     "}",
3013     "foo.proto: Foo.foo: TYPE: \"Bar\" seems to be defined in \"bar.proto\", "
3014       "which is not imported by \"foo.proto\".  To use it here, please add the "
3015       "necessary import.\n");
3016 }
3017 
TEST_F(ValidationErrorTest,FieldTypeDefinedInIndirectDependency)3018 TEST_F(ValidationErrorTest, FieldTypeDefinedInIndirectDependency) {
3019   // Test for hidden dependencies.
3020   //
3021   // // bar.proto
3022   // message Bar{}
3023   //
3024   // // forward.proto
3025   // import "bar.proto"
3026   //
3027   // // foo.proto
3028   // import "forward.proto"
3029   // message Foo {
3030   //   optional Bar foo = 1;  // Error, needs to import bar.proto explicitly.
3031   // }
3032   //
3033   BuildFile(
3034     "name: \"bar.proto\" "
3035     "message_type { name: \"Bar\" }");
3036 
3037   BuildFile(
3038     "name: \"forward.proto\""
3039     "dependency: \"bar.proto\"");
3040 
3041   BuildFileWithErrors(
3042     "name: \"foo.proto\" "
3043     "dependency: \"forward.proto\" "
3044     "message_type {"
3045     "  name: \"Foo\""
3046     "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }"
3047     "}",
3048     "foo.proto: Foo.foo: TYPE: \"Bar\" seems to be defined in \"bar.proto\", "
3049       "which is not imported by \"foo.proto\".  To use it here, please add the "
3050       "necessary import.\n");
3051 }
3052 
TEST_F(ValidationErrorTest,FieldTypeDefinedInPublicDependency)3053 TEST_F(ValidationErrorTest, FieldTypeDefinedInPublicDependency) {
3054   // Test for public dependencies.
3055   //
3056   // // bar.proto
3057   // message Bar{}
3058   //
3059   // // forward.proto
3060   // import public "bar.proto"
3061   //
3062   // // foo.proto
3063   // import "forward.proto"
3064   // message Foo {
3065   //   optional Bar foo = 1;  // Correct. "bar.proto" is public imported into
3066   //                          // forward.proto, so when "foo.proto" imports
3067   //                          // "forward.proto", it imports "bar.proto" too.
3068   // }
3069   //
3070   BuildFile(
3071     "name: \"bar.proto\" "
3072     "message_type { name: \"Bar\" }");
3073 
3074   BuildFile(
3075     "name: \"forward.proto\""
3076     "dependency: \"bar.proto\" "
3077     "public_dependency: 0");
3078 
3079   BuildFile(
3080     "name: \"foo.proto\" "
3081     "dependency: \"forward.proto\" "
3082     "message_type {"
3083     "  name: \"Foo\""
3084     "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }"
3085     "}");
3086 }
3087 
TEST_F(ValidationErrorTest,FieldTypeDefinedInTransitivePublicDependency)3088 TEST_F(ValidationErrorTest, FieldTypeDefinedInTransitivePublicDependency) {
3089   // Test for public dependencies.
3090   //
3091   // // bar.proto
3092   // message Bar{}
3093   //
3094   // // forward.proto
3095   // import public "bar.proto"
3096   //
3097   // // forward2.proto
3098   // import public "forward.proto"
3099   //
3100   // // foo.proto
3101   // import "forward2.proto"
3102   // message Foo {
3103   //   optional Bar foo = 1;  // Correct, public imports are transitive.
3104   // }
3105   //
3106   BuildFile(
3107     "name: \"bar.proto\" "
3108     "message_type { name: \"Bar\" }");
3109 
3110   BuildFile(
3111     "name: \"forward.proto\""
3112     "dependency: \"bar.proto\" "
3113     "public_dependency: 0");
3114 
3115   BuildFile(
3116     "name: \"forward2.proto\""
3117     "dependency: \"forward.proto\" "
3118     "public_dependency: 0");
3119 
3120   BuildFile(
3121     "name: \"foo.proto\" "
3122     "dependency: \"forward2.proto\" "
3123     "message_type {"
3124     "  name: \"Foo\""
3125     "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }"
3126     "}");
3127 }
3128 
TEST_F(ValidationErrorTest,FieldTypeDefinedInPrivateDependencyOfPublicDependency)3129 TEST_F(ValidationErrorTest,
3130        FieldTypeDefinedInPrivateDependencyOfPublicDependency) {
3131   // Test for public dependencies.
3132   //
3133   // // bar.proto
3134   // message Bar{}
3135   //
3136   // // forward.proto
3137   // import "bar.proto"
3138   //
3139   // // forward2.proto
3140   // import public "forward.proto"
3141   //
3142   // // foo.proto
3143   // import "forward2.proto"
3144   // message Foo {
3145   //   optional Bar foo = 1;  // Error, the "bar.proto" is not public imported
3146   //                          // into "forward.proto", so will not be imported
3147   //                          // into either "forward2.proto" or "foo.proto".
3148   // }
3149   //
3150   BuildFile(
3151     "name: \"bar.proto\" "
3152     "message_type { name: \"Bar\" }");
3153 
3154   BuildFile(
3155     "name: \"forward.proto\""
3156     "dependency: \"bar.proto\"");
3157 
3158   BuildFile(
3159     "name: \"forward2.proto\""
3160     "dependency: \"forward.proto\" "
3161     "public_dependency: 0");
3162 
3163   BuildFileWithErrors(
3164     "name: \"foo.proto\" "
3165     "dependency: \"forward2.proto\" "
3166     "message_type {"
3167     "  name: \"Foo\""
3168     "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }"
3169     "}",
3170     "foo.proto: Foo.foo: TYPE: \"Bar\" seems to be defined in \"bar.proto\", "
3171       "which is not imported by \"foo.proto\".  To use it here, please add the "
3172       "necessary import.\n");
3173 }
3174 
3175 
TEST_F(ValidationErrorTest,SearchMostLocalFirst)3176 TEST_F(ValidationErrorTest, SearchMostLocalFirst) {
3177   // The following should produce an error that Bar.Baz is not defined:
3178   //   message Bar { message Baz {} }
3179   //   message Foo {
3180   //     message Bar {
3181   //       // Placing "message Baz{}" here, or removing Foo.Bar altogether,
3182   //       // would fix the error.
3183   //     }
3184   //     optional Bar.Baz baz = 1;
3185   //   }
3186   // An one point the lookup code incorrectly did not produce an error in this
3187   // case, because when looking for Bar.Baz, it would try "Foo.Bar.Baz" first,
3188   // fail, and ten try "Bar.Baz" and succeed, even though "Bar" should actually
3189   // refer to the inner Bar, not the outer one.
3190   BuildFileWithErrors(
3191     "name: \"foo.proto\" "
3192     "message_type {"
3193     "  name: \"Bar\""
3194     "  nested_type { name: \"Baz\" }"
3195     "}"
3196     "message_type {"
3197     "  name: \"Foo\""
3198     "  nested_type { name: \"Bar\" }"
3199     "  field { name:\"baz\" number:1 label:LABEL_OPTIONAL"
3200     "          type_name:\"Bar.Baz\" }"
3201     "}",
3202 
3203     "foo.proto: Foo.baz: TYPE: \"Bar.Baz\" is not defined.\n");
3204 }
3205 
TEST_F(ValidationErrorTest,SearchMostLocalFirst2)3206 TEST_F(ValidationErrorTest, SearchMostLocalFirst2) {
3207   // This test would find the most local "Bar" first, and does, but
3208   // proceeds to find the outer one because the inner one's not an
3209   // aggregate.
3210   BuildFile(
3211     "name: \"foo.proto\" "
3212     "message_type {"
3213     "  name: \"Bar\""
3214     "  nested_type { name: \"Baz\" }"
3215     "}"
3216     "message_type {"
3217     "  name: \"Foo\""
3218     "  field { name: \"Bar\" number:1 type:TYPE_BYTES } "
3219     "  field { name:\"baz\" number:2 label:LABEL_OPTIONAL"
3220     "          type_name:\"Bar.Baz\" }"
3221     "}");
3222 }
3223 
TEST_F(ValidationErrorTest,PackageOriginallyDeclaredInTransitiveDependent)3224 TEST_F(ValidationErrorTest, PackageOriginallyDeclaredInTransitiveDependent) {
3225   // Imagine we have the following:
3226   //
3227   // foo.proto:
3228   //   package foo.bar;
3229   // bar.proto:
3230   //   package foo.bar;
3231   //   import "foo.proto";
3232   //   message Bar {}
3233   // baz.proto:
3234   //   package foo;
3235   //   import "bar.proto"
3236   //   message Baz { optional bar.Bar qux = 1; }
3237   //
3238   // When validating baz.proto, we will look up "bar.Bar".  As part of this
3239   // lookup, we first lookup "bar" then try to find "Bar" within it.  "bar"
3240   // should resolve to "foo.bar".  Note, though, that "foo.bar" was originally
3241   // defined in foo.proto, which is not a direct dependency of baz.proto.  The
3242   // implementation of FindSymbol() normally only returns symbols in direct
3243   // dependencies, not indirect ones.  This test insures that this does not
3244   // prevent it from finding "foo.bar".
3245 
3246   BuildFile(
3247     "name: \"foo.proto\" "
3248     "package: \"foo.bar\" ");
3249   BuildFile(
3250     "name: \"bar.proto\" "
3251     "package: \"foo.bar\" "
3252     "dependency: \"foo.proto\" "
3253     "message_type { name: \"Bar\" }");
3254   BuildFile(
3255     "name: \"baz.proto\" "
3256     "package: \"foo\" "
3257     "dependency: \"bar.proto\" "
3258     "message_type { "
3259     "  name: \"Baz\" "
3260     "  field { name:\"qux\" number:1 label:LABEL_OPTIONAL "
3261     "          type_name:\"bar.Bar\" }"
3262     "}");
3263 }
3264 
TEST_F(ValidationErrorTest,FieldTypeNotAType)3265 TEST_F(ValidationErrorTest, FieldTypeNotAType) {
3266   BuildFileWithErrors(
3267     "name: \"foo.proto\" "
3268     "message_type {"
3269     "  name: \"Foo\""
3270     "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL "
3271     "          type_name:\".Foo.bar\" }"
3272     "  field { name:\"bar\" number:2 label:LABEL_OPTIONAL type:TYPE_INT32 }"
3273     "}",
3274 
3275     "foo.proto: Foo.foo: TYPE: \".Foo.bar\" is not a type.\n");
3276 }
3277 
TEST_F(ValidationErrorTest,RelativeFieldTypeNotAType)3278 TEST_F(ValidationErrorTest, RelativeFieldTypeNotAType) {
3279   BuildFileWithErrors(
3280     "name: \"foo.proto\" "
3281     "message_type {"
3282     "  nested_type {"
3283     "    name: \"Bar\""
3284     "    field { name:\"Baz\" number:2 label:LABEL_OPTIONAL type:TYPE_INT32 }"
3285     "  }"
3286     "  name: \"Foo\""
3287     "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL "
3288     "          type_name:\"Bar.Baz\" }"
3289     "}",
3290     "foo.proto: Foo.foo: TYPE: \"Bar.Baz\" is not a type.\n");
3291 }
3292 
TEST_F(ValidationErrorTest,FieldTypeMayBeItsName)3293 TEST_F(ValidationErrorTest, FieldTypeMayBeItsName) {
3294   BuildFile(
3295     "name: \"foo.proto\" "
3296     "message_type {"
3297     "  name: \"Bar\""
3298     "}"
3299     "message_type {"
3300     "  name: \"Foo\""
3301     "  field { name:\"Bar\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }"
3302     "}");
3303 }
3304 
TEST_F(ValidationErrorTest,EnumFieldTypeIsMessage)3305 TEST_F(ValidationErrorTest, EnumFieldTypeIsMessage) {
3306   BuildFileWithErrors(
3307     "name: \"foo.proto\" "
3308     "message_type { name: \"Bar\" } "
3309     "message_type {"
3310     "  name: \"Foo\""
3311     "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_ENUM"
3312     "          type_name:\"Bar\" }"
3313     "}",
3314 
3315     "foo.proto: Foo.foo: TYPE: \"Bar\" is not an enum type.\n");
3316 }
3317 
TEST_F(ValidationErrorTest,MessageFieldTypeIsEnum)3318 TEST_F(ValidationErrorTest, MessageFieldTypeIsEnum) {
3319   BuildFileWithErrors(
3320     "name: \"foo.proto\" "
3321     "enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } } "
3322     "message_type {"
3323     "  name: \"Foo\""
3324     "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_MESSAGE"
3325     "          type_name:\"Bar\" }"
3326     "}",
3327 
3328     "foo.proto: Foo.foo: TYPE: \"Bar\" is not a message type.\n");
3329 }
3330 
TEST_F(ValidationErrorTest,BadEnumDefaultValue)3331 TEST_F(ValidationErrorTest, BadEnumDefaultValue) {
3332   BuildFileWithErrors(
3333     "name: \"foo.proto\" "
3334     "enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } } "
3335     "message_type {"
3336     "  name: \"Foo\""
3337     "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\""
3338     "          default_value:\"NO_SUCH_VALUE\" }"
3339     "}",
3340 
3341     "foo.proto: Foo.foo: DEFAULT_VALUE: Enum type \"Bar\" has no value named "
3342       "\"NO_SUCH_VALUE\".\n");
3343 }
3344 
TEST_F(ValidationErrorTest,PrimitiveWithTypeName)3345 TEST_F(ValidationErrorTest, PrimitiveWithTypeName) {
3346   BuildFileWithErrors(
3347     "name: \"foo.proto\" "
3348     "message_type {"
3349     "  name: \"Foo\""
3350     "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32"
3351     "          type_name:\"Foo\" }"
3352     "}",
3353 
3354     "foo.proto: Foo.foo: TYPE: Field with primitive type has type_name.\n");
3355 }
3356 
TEST_F(ValidationErrorTest,NonPrimitiveWithoutTypeName)3357 TEST_F(ValidationErrorTest, NonPrimitiveWithoutTypeName) {
3358   BuildFileWithErrors(
3359     "name: \"foo.proto\" "
3360     "message_type {"
3361     "  name: \"Foo\""
3362     "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_MESSAGE }"
3363     "}",
3364 
3365     "foo.proto: Foo.foo: TYPE: Field with message or enum type missing "
3366       "type_name.\n");
3367 }
3368 
TEST_F(ValidationErrorTest,InputTypeNotDefined)3369 TEST_F(ValidationErrorTest, InputTypeNotDefined) {
3370   BuildFileWithErrors(
3371     "name: \"foo.proto\" "
3372     "message_type { name: \"Foo\" } "
3373     "service {"
3374     "  name: \"TestService\""
3375     "  method { name: \"A\" input_type: \"Bar\" output_type: \"Foo\" }"
3376     "}",
3377 
3378     "foo.proto: TestService.A: INPUT_TYPE: \"Bar\" is not defined.\n"
3379     );
3380 }
3381 
TEST_F(ValidationErrorTest,InputTypeNotAMessage)3382 TEST_F(ValidationErrorTest, InputTypeNotAMessage) {
3383   BuildFileWithErrors(
3384     "name: \"foo.proto\" "
3385     "message_type { name: \"Foo\" } "
3386     "enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } } "
3387     "service {"
3388     "  name: \"TestService\""
3389     "  method { name: \"A\" input_type: \"Bar\" output_type: \"Foo\" }"
3390     "}",
3391 
3392     "foo.proto: TestService.A: INPUT_TYPE: \"Bar\" is not a message type.\n"
3393     );
3394 }
3395 
TEST_F(ValidationErrorTest,OutputTypeNotDefined)3396 TEST_F(ValidationErrorTest, OutputTypeNotDefined) {
3397   BuildFileWithErrors(
3398     "name: \"foo.proto\" "
3399     "message_type { name: \"Foo\" } "
3400     "service {"
3401     "  name: \"TestService\""
3402     "  method { name: \"A\" input_type: \"Foo\" output_type: \"Bar\" }"
3403     "}",
3404 
3405     "foo.proto: TestService.A: OUTPUT_TYPE: \"Bar\" is not defined.\n"
3406     );
3407 }
3408 
TEST_F(ValidationErrorTest,OutputTypeNotAMessage)3409 TEST_F(ValidationErrorTest, OutputTypeNotAMessage) {
3410   BuildFileWithErrors(
3411     "name: \"foo.proto\" "
3412     "message_type { name: \"Foo\" } "
3413     "enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } } "
3414     "service {"
3415     "  name: \"TestService\""
3416     "  method { name: \"A\" input_type: \"Foo\" output_type: \"Bar\" }"
3417     "}",
3418 
3419     "foo.proto: TestService.A: OUTPUT_TYPE: \"Bar\" is not a message type.\n"
3420     );
3421 }
3422 
3423 
TEST_F(ValidationErrorTest,IllegalPackedField)3424 TEST_F(ValidationErrorTest, IllegalPackedField) {
3425   BuildFileWithErrors(
3426     "name: \"foo.proto\" "
3427     "message_type {\n"
3428     "  name: \"Foo\""
3429     "  field { name:\"packed_string\" number:1 label:LABEL_REPEATED "
3430     "          type:TYPE_STRING "
3431     "          options { uninterpreted_option {"
3432     "            name { name_part: \"packed\" is_extension: false }"
3433     "            identifier_value: \"true\" }}}\n"
3434     "  field { name:\"packed_message\" number:3 label:LABEL_REPEATED "
3435     "          type_name: \"Foo\""
3436     "          options { uninterpreted_option {"
3437     "            name { name_part: \"packed\" is_extension: false }"
3438     "            identifier_value: \"true\" }}}\n"
3439     "  field { name:\"optional_int32\" number: 4 label: LABEL_OPTIONAL "
3440     "          type:TYPE_INT32 "
3441     "          options { uninterpreted_option {"
3442     "            name { name_part: \"packed\" is_extension: false }"
3443     "            identifier_value: \"true\" }}}\n"
3444     "}",
3445 
3446     "foo.proto: Foo.packed_string: TYPE: [packed = true] can only be "
3447         "specified for repeated primitive fields.\n"
3448     "foo.proto: Foo.packed_message: TYPE: [packed = true] can only be "
3449         "specified for repeated primitive fields.\n"
3450     "foo.proto: Foo.optional_int32: TYPE: [packed = true] can only be "
3451         "specified for repeated primitive fields.\n"
3452         );
3453 }
3454 
TEST_F(ValidationErrorTest,OptionWrongType)3455 TEST_F(ValidationErrorTest, OptionWrongType) {
3456   BuildFileWithErrors(
3457     "name: \"foo.proto\" "
3458     "message_type { "
3459     "  name: \"TestMessage\" "
3460     "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_STRING "
3461     "          options { uninterpreted_option { name { name_part: \"ctype\" "
3462     "                                                  is_extension: false }"
3463     "                                           positive_int_value: 1 }"
3464     "          }"
3465     "  }"
3466     "}\n",
3467 
3468     "foo.proto: TestMessage.foo: OPTION_VALUE: Value must be identifier for "
3469     "enum-valued option \"google.protobuf.FieldOptions.ctype\".\n");
3470 }
3471 
TEST_F(ValidationErrorTest,OptionExtendsAtomicType)3472 TEST_F(ValidationErrorTest, OptionExtendsAtomicType) {
3473   BuildFileWithErrors(
3474     "name: \"foo.proto\" "
3475     "message_type { "
3476     "  name: \"TestMessage\" "
3477     "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_STRING "
3478     "          options { uninterpreted_option { name { name_part: \"ctype\" "
3479     "                                                  is_extension: false }"
3480     "                                           name { name_part: \"foo\" "
3481     "                                                  is_extension: true }"
3482     "                                           positive_int_value: 1 }"
3483     "          }"
3484     "  }"
3485     "}\n",
3486 
3487     "foo.proto: TestMessage.foo: OPTION_NAME: Option \"ctype\" is an "
3488     "atomic type, not a message.\n");
3489 }
3490 
TEST_F(ValidationErrorTest,DupOption)3491 TEST_F(ValidationErrorTest, DupOption) {
3492   BuildFileWithErrors(
3493     "name: \"foo.proto\" "
3494     "message_type { "
3495     "  name: \"TestMessage\" "
3496     "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_UINT32 "
3497     "          options { uninterpreted_option { name { name_part: \"ctype\" "
3498     "                                                  is_extension: false }"
3499     "                                           identifier_value: \"CORD\" }"
3500     "                    uninterpreted_option { name { name_part: \"ctype\" "
3501     "                                                  is_extension: false }"
3502     "                                           identifier_value: \"CORD\" }"
3503     "          }"
3504     "  }"
3505     "}\n",
3506 
3507     "foo.proto: TestMessage.foo: OPTION_NAME: Option \"ctype\" was "
3508     "already set.\n");
3509 }
3510 
TEST_F(ValidationErrorTest,InvalidOptionName)3511 TEST_F(ValidationErrorTest, InvalidOptionName) {
3512   BuildFileWithErrors(
3513     "name: \"foo.proto\" "
3514     "message_type { "
3515     "  name: \"TestMessage\" "
3516     "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_BOOL "
3517     "          options { uninterpreted_option { "
3518     "                      name { name_part: \"uninterpreted_option\" "
3519     "                             is_extension: false }"
3520     "                      positive_int_value: 1 "
3521     "                    }"
3522     "          }"
3523     "  }"
3524     "}\n",
3525 
3526     "foo.proto: TestMessage.foo: OPTION_NAME: Option must not use "
3527     "reserved name \"uninterpreted_option\".\n");
3528 }
3529 
TEST_F(ValidationErrorTest,RepeatedOption)3530 TEST_F(ValidationErrorTest, RepeatedOption) {
3531   BuildDescriptorMessagesInTestPool();
3532 
3533   BuildFileWithErrors(
3534     "name: \"foo.proto\" "
3535     "dependency: \"google/protobuf/descriptor.proto\" "
3536     "extension { name: \"foo\" number: 7672757 label: LABEL_REPEATED "
3537     "            type: TYPE_FLOAT extendee: \"google.protobuf.FileOptions\" }"
3538     "options { uninterpreted_option { name { name_part: \"foo\" "
3539     "                                        is_extension: true } "
3540     "                                 double_value: 1.2 } }",
3541 
3542     "foo.proto: foo.proto: OPTION_NAME: Option field \"(foo)\" is repeated. "
3543     "Repeated options are not supported.\n");
3544 }
3545 
TEST_F(ValidationErrorTest,CustomOptionConflictingFieldNumber)3546 TEST_F(ValidationErrorTest, CustomOptionConflictingFieldNumber) {
3547   BuildDescriptorMessagesInTestPool();
3548 
3549   BuildFileWithErrors(
3550     "name: \"foo.proto\" "
3551     "dependency: \"google/protobuf/descriptor.proto\" "
3552     "extension { name: \"foo1\" number: 7672757 label: LABEL_OPTIONAL "
3553     "            type: TYPE_INT32 extendee: \"google.protobuf.FieldOptions\" }"
3554     "extension { name: \"foo2\" number: 7672757 label: LABEL_OPTIONAL "
3555     "            type: TYPE_INT32 extendee: \"google.protobuf.FieldOptions\" }",
3556 
3557     "foo.proto: foo2: NUMBER: Extension number 7672757 has already been used "
3558     "in \"google.protobuf.FieldOptions\" by extension \"foo1\".\n");
3559 }
3560 
TEST_F(ValidationErrorTest,Int32OptionValueOutOfPositiveRange)3561 TEST_F(ValidationErrorTest, Int32OptionValueOutOfPositiveRange) {
3562   BuildDescriptorMessagesInTestPool();
3563 
3564   BuildFileWithErrors(
3565     "name: \"foo.proto\" "
3566     "dependency: \"google/protobuf/descriptor.proto\" "
3567     "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
3568     "            type: TYPE_INT32 extendee: \"google.protobuf.FileOptions\" }"
3569     "options { uninterpreted_option { name { name_part: \"foo\" "
3570     "                                        is_extension: true } "
3571     "                                 positive_int_value: 0x80000000 } "
3572     "}",
3573 
3574     "foo.proto: foo.proto: OPTION_VALUE: Value out of range "
3575     "for int32 option \"foo\".\n");
3576 }
3577 
TEST_F(ValidationErrorTest,Int32OptionValueOutOfNegativeRange)3578 TEST_F(ValidationErrorTest, Int32OptionValueOutOfNegativeRange) {
3579   BuildDescriptorMessagesInTestPool();
3580 
3581   BuildFileWithErrors(
3582     "name: \"foo.proto\" "
3583     "dependency: \"google/protobuf/descriptor.proto\" "
3584     "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
3585     "            type: TYPE_INT32 extendee: \"google.protobuf.FileOptions\" }"
3586     "options { uninterpreted_option { name { name_part: \"foo\" "
3587     "                                        is_extension: true } "
3588     "                                 negative_int_value: -0x80000001 } "
3589     "}",
3590 
3591     "foo.proto: foo.proto: OPTION_VALUE: Value out of range "
3592     "for int32 option \"foo\".\n");
3593 }
3594 
TEST_F(ValidationErrorTest,Int32OptionValueIsNotPositiveInt)3595 TEST_F(ValidationErrorTest, Int32OptionValueIsNotPositiveInt) {
3596   BuildDescriptorMessagesInTestPool();
3597 
3598   BuildFileWithErrors(
3599     "name: \"foo.proto\" "
3600     "dependency: \"google/protobuf/descriptor.proto\" "
3601     "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
3602     "            type: TYPE_INT32 extendee: \"google.protobuf.FileOptions\" }"
3603     "options { uninterpreted_option { name { name_part: \"foo\" "
3604     "                                        is_extension: true } "
3605     "                                 string_value: \"5\" } }",
3606 
3607     "foo.proto: foo.proto: OPTION_VALUE: Value must be integer "
3608     "for int32 option \"foo\".\n");
3609 }
3610 
TEST_F(ValidationErrorTest,Int64OptionValueOutOfRange)3611 TEST_F(ValidationErrorTest, Int64OptionValueOutOfRange) {
3612   BuildDescriptorMessagesInTestPool();
3613 
3614   BuildFileWithErrors(
3615     "name: \"foo.proto\" "
3616     "dependency: \"google/protobuf/descriptor.proto\" "
3617     "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
3618     "            type: TYPE_INT64 extendee: \"google.protobuf.FileOptions\" }"
3619     "options { uninterpreted_option { name { name_part: \"foo\" "
3620     "                                        is_extension: true } "
3621     "                                 positive_int_value: 0x8000000000000000 } "
3622     "}",
3623 
3624     "foo.proto: foo.proto: OPTION_VALUE: Value out of range "
3625     "for int64 option \"foo\".\n");
3626 }
3627 
TEST_F(ValidationErrorTest,Int64OptionValueIsNotPositiveInt)3628 TEST_F(ValidationErrorTest, Int64OptionValueIsNotPositiveInt) {
3629   BuildDescriptorMessagesInTestPool();
3630 
3631   BuildFileWithErrors(
3632     "name: \"foo.proto\" "
3633     "dependency: \"google/protobuf/descriptor.proto\" "
3634     "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
3635     "            type: TYPE_INT64 extendee: \"google.protobuf.FileOptions\" }"
3636     "options { uninterpreted_option { name { name_part: \"foo\" "
3637     "                                        is_extension: true } "
3638     "                                 identifier_value: \"5\" } }",
3639 
3640     "foo.proto: foo.proto: OPTION_VALUE: Value must be integer "
3641     "for int64 option \"foo\".\n");
3642 }
3643 
TEST_F(ValidationErrorTest,UInt32OptionValueOutOfRange)3644 TEST_F(ValidationErrorTest, UInt32OptionValueOutOfRange) {
3645   BuildDescriptorMessagesInTestPool();
3646 
3647   BuildFileWithErrors(
3648     "name: \"foo.proto\" "
3649     "dependency: \"google/protobuf/descriptor.proto\" "
3650     "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
3651     "            type: TYPE_UINT32 extendee: \"google.protobuf.FileOptions\" }"
3652     "options { uninterpreted_option { name { name_part: \"foo\" "
3653     "                                        is_extension: true } "
3654     "                                 positive_int_value: 0x100000000 } }",
3655 
3656     "foo.proto: foo.proto: OPTION_VALUE: Value out of range "
3657     "for uint32 option \"foo\".\n");
3658 }
3659 
TEST_F(ValidationErrorTest,UInt32OptionValueIsNotPositiveInt)3660 TEST_F(ValidationErrorTest, UInt32OptionValueIsNotPositiveInt) {
3661   BuildDescriptorMessagesInTestPool();
3662 
3663   BuildFileWithErrors(
3664     "name: \"foo.proto\" "
3665     "dependency: \"google/protobuf/descriptor.proto\" "
3666     "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
3667     "            type: TYPE_UINT32 extendee: \"google.protobuf.FileOptions\" }"
3668     "options { uninterpreted_option { name { name_part: \"foo\" "
3669     "                                        is_extension: true } "
3670     "                                 double_value: -5.6 } }",
3671 
3672     "foo.proto: foo.proto: OPTION_VALUE: Value must be non-negative integer "
3673     "for uint32 option \"foo\".\n");
3674 }
3675 
TEST_F(ValidationErrorTest,UInt64OptionValueIsNotPositiveInt)3676 TEST_F(ValidationErrorTest, UInt64OptionValueIsNotPositiveInt) {
3677   BuildDescriptorMessagesInTestPool();
3678 
3679   BuildFileWithErrors(
3680     "name: \"foo.proto\" "
3681     "dependency: \"google/protobuf/descriptor.proto\" "
3682     "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
3683     "            type: TYPE_UINT64 extendee: \"google.protobuf.FileOptions\" }"
3684     "options { uninterpreted_option { name { name_part: \"foo\" "
3685     "                                        is_extension: true } "
3686     "                                 negative_int_value: -5 } }",
3687 
3688     "foo.proto: foo.proto: OPTION_VALUE: Value must be non-negative integer "
3689     "for uint64 option \"foo\".\n");
3690 }
3691 
TEST_F(ValidationErrorTest,FloatOptionValueIsNotNumber)3692 TEST_F(ValidationErrorTest, FloatOptionValueIsNotNumber) {
3693   BuildDescriptorMessagesInTestPool();
3694 
3695   BuildFileWithErrors(
3696     "name: \"foo.proto\" "
3697     "dependency: \"google/protobuf/descriptor.proto\" "
3698     "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
3699     "            type: TYPE_FLOAT extendee: \"google.protobuf.FileOptions\" }"
3700     "options { uninterpreted_option { name { name_part: \"foo\" "
3701     "                                        is_extension: true } "
3702     "                                 string_value: \"bar\" } }",
3703 
3704     "foo.proto: foo.proto: OPTION_VALUE: Value must be number "
3705     "for float option \"foo\".\n");
3706 }
3707 
TEST_F(ValidationErrorTest,DoubleOptionValueIsNotNumber)3708 TEST_F(ValidationErrorTest, DoubleOptionValueIsNotNumber) {
3709   BuildDescriptorMessagesInTestPool();
3710 
3711   BuildFileWithErrors(
3712     "name: \"foo.proto\" "
3713     "dependency: \"google/protobuf/descriptor.proto\" "
3714     "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
3715     "            type: TYPE_DOUBLE extendee: \"google.protobuf.FileOptions\" }"
3716     "options { uninterpreted_option { name { name_part: \"foo\" "
3717     "                                        is_extension: true } "
3718     "                                 string_value: \"bar\" } }",
3719 
3720     "foo.proto: foo.proto: OPTION_VALUE: Value must be number "
3721     "for double option \"foo\".\n");
3722 }
3723 
TEST_F(ValidationErrorTest,BoolOptionValueIsNotTrueOrFalse)3724 TEST_F(ValidationErrorTest, BoolOptionValueIsNotTrueOrFalse) {
3725   BuildDescriptorMessagesInTestPool();
3726 
3727   BuildFileWithErrors(
3728     "name: \"foo.proto\" "
3729     "dependency: \"google/protobuf/descriptor.proto\" "
3730     "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
3731     "            type: TYPE_BOOL extendee: \"google.protobuf.FileOptions\" }"
3732     "options { uninterpreted_option { name { name_part: \"foo\" "
3733     "                                        is_extension: true } "
3734     "                                 identifier_value: \"bar\" } }",
3735 
3736     "foo.proto: foo.proto: OPTION_VALUE: Value must be \"true\" or \"false\" "
3737     "for boolean option \"foo\".\n");
3738 }
3739 
TEST_F(ValidationErrorTest,EnumOptionValueIsNotIdentifier)3740 TEST_F(ValidationErrorTest, EnumOptionValueIsNotIdentifier) {
3741   BuildDescriptorMessagesInTestPool();
3742 
3743   BuildFileWithErrors(
3744     "name: \"foo.proto\" "
3745     "dependency: \"google/protobuf/descriptor.proto\" "
3746     "enum_type { name: \"FooEnum\" value { name: \"BAR\" number: 1 } "
3747     "                              value { name: \"BAZ\" number: 2 } }"
3748     "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
3749     "            type: TYPE_ENUM type_name: \"FooEnum\" "
3750     "            extendee: \"google.protobuf.FileOptions\" }"
3751     "options { uninterpreted_option { name { name_part: \"foo\" "
3752     "                                        is_extension: true } "
3753     "                                 string_value: \"QUUX\" } }",
3754 
3755     "foo.proto: foo.proto: OPTION_VALUE: Value must be identifier for "
3756     "enum-valued option \"foo\".\n");
3757 }
3758 
TEST_F(ValidationErrorTest,EnumOptionValueIsNotEnumValueName)3759 TEST_F(ValidationErrorTest, EnumOptionValueIsNotEnumValueName) {
3760   BuildDescriptorMessagesInTestPool();
3761 
3762   BuildFileWithErrors(
3763     "name: \"foo.proto\" "
3764     "dependency: \"google/protobuf/descriptor.proto\" "
3765     "enum_type { name: \"FooEnum\" value { name: \"BAR\" number: 1 } "
3766     "                              value { name: \"BAZ\" number: 2 } }"
3767     "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
3768     "            type: TYPE_ENUM type_name: \"FooEnum\" "
3769     "            extendee: \"google.protobuf.FileOptions\" }"
3770     "options { uninterpreted_option { name { name_part: \"foo\" "
3771     "                                        is_extension: true } "
3772     "                                 identifier_value: \"QUUX\" } }",
3773 
3774     "foo.proto: foo.proto: OPTION_VALUE: Enum type \"FooEnum\" has no value "
3775     "named \"QUUX\" for option \"foo\".\n");
3776 }
3777 
TEST_F(ValidationErrorTest,EnumOptionValueIsSiblingEnumValueName)3778 TEST_F(ValidationErrorTest, EnumOptionValueIsSiblingEnumValueName) {
3779   BuildDescriptorMessagesInTestPool();
3780 
3781   BuildFileWithErrors(
3782     "name: \"foo.proto\" "
3783     "dependency: \"google/protobuf/descriptor.proto\" "
3784     "enum_type { name: \"FooEnum1\" value { name: \"BAR\" number: 1 } "
3785     "                               value { name: \"BAZ\" number: 2 } }"
3786     "enum_type { name: \"FooEnum2\" value { name: \"QUX\" number: 1 } "
3787     "                               value { name: \"QUUX\" number: 2 } }"
3788     "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
3789     "            type: TYPE_ENUM type_name: \"FooEnum1\" "
3790     "            extendee: \"google.protobuf.FileOptions\" }"
3791     "options { uninterpreted_option { name { name_part: \"foo\" "
3792     "                                        is_extension: true } "
3793     "                                 identifier_value: \"QUUX\" } }",
3794 
3795     "foo.proto: foo.proto: OPTION_VALUE: Enum type \"FooEnum1\" has no value "
3796     "named \"QUUX\" for option \"foo\". This appears to be a value from a "
3797     "sibling type.\n");
3798 }
3799 
TEST_F(ValidationErrorTest,StringOptionValueIsNotString)3800 TEST_F(ValidationErrorTest, StringOptionValueIsNotString) {
3801   BuildDescriptorMessagesInTestPool();
3802 
3803   BuildFileWithErrors(
3804     "name: \"foo.proto\" "
3805     "dependency: \"google/protobuf/descriptor.proto\" "
3806     "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
3807     "            type: TYPE_STRING extendee: \"google.protobuf.FileOptions\" }"
3808     "options { uninterpreted_option { name { name_part: \"foo\" "
3809     "                                        is_extension: true } "
3810     "                                 identifier_value: \"QUUX\" } }",
3811 
3812     "foo.proto: foo.proto: OPTION_VALUE: Value must be quoted string for "
3813     "string option \"foo\".\n");
3814 }
3815 
3816 // Helper function for tests that check for aggregate value parsing
3817 // errors.  The "value" argument is embedded inside the
3818 // "uninterpreted_option" portion of the result.
EmbedAggregateValue(const char * value)3819 static string EmbedAggregateValue(const char* value) {
3820   return strings::Substitute(
3821       "name: \"foo.proto\" "
3822       "dependency: \"google/protobuf/descriptor.proto\" "
3823       "message_type { name: \"Foo\" } "
3824       "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
3825       "            type: TYPE_MESSAGE type_name: \"Foo\" "
3826       "            extendee: \"google.protobuf.FileOptions\" }"
3827       "options { uninterpreted_option { name { name_part: \"foo\" "
3828       "                                        is_extension: true } "
3829       "                                 $0 } }",
3830       value);
3831 }
3832 
TEST_F(ValidationErrorTest,AggregateValueNotFound)3833 TEST_F(ValidationErrorTest, AggregateValueNotFound) {
3834   BuildDescriptorMessagesInTestPool();
3835 
3836   BuildFileWithErrors(
3837       EmbedAggregateValue("string_value: \"\""),
3838       "foo.proto: foo.proto: OPTION_VALUE: Option \"foo\" is a message. "
3839       "To set the entire message, use syntax like "
3840       "\"foo = { <proto text format> }\". To set fields within it, use "
3841       "syntax like \"foo.foo = value\".\n");
3842 }
3843 
TEST_F(ValidationErrorTest,AggregateValueParseError)3844 TEST_F(ValidationErrorTest, AggregateValueParseError) {
3845   BuildDescriptorMessagesInTestPool();
3846 
3847   BuildFileWithErrors(
3848       EmbedAggregateValue("aggregate_value: \"1+2\""),
3849       "foo.proto: foo.proto: OPTION_VALUE: Error while parsing option "
3850       "value for \"foo\": Expected identifier.\n");
3851 }
3852 
TEST_F(ValidationErrorTest,AggregateValueUnknownFields)3853 TEST_F(ValidationErrorTest, AggregateValueUnknownFields) {
3854   BuildDescriptorMessagesInTestPool();
3855 
3856   BuildFileWithErrors(
3857       EmbedAggregateValue("aggregate_value: \"x:100\""),
3858       "foo.proto: foo.proto: OPTION_VALUE: Error while parsing option "
3859       "value for \"foo\": Message type \"Foo\" has no field named \"x\".\n");
3860 }
3861 
TEST_F(ValidationErrorTest,NotLiteImportsLite)3862 TEST_F(ValidationErrorTest, NotLiteImportsLite) {
3863   BuildFile(
3864     "name: \"bar.proto\" "
3865     "options { optimize_for: LITE_RUNTIME } ");
3866 
3867   BuildFileWithErrors(
3868     "name: \"foo.proto\" "
3869     "dependency: \"bar.proto\" ",
3870 
3871     "foo.proto: foo.proto: OTHER: Files that do not use optimize_for = "
3872       "LITE_RUNTIME cannot import files which do use this option.  This file "
3873       "is not lite, but it imports \"bar.proto\" which is.\n");
3874 }
3875 
TEST_F(ValidationErrorTest,LiteExtendsNotLite)3876 TEST_F(ValidationErrorTest, LiteExtendsNotLite) {
3877   BuildFile(
3878     "name: \"bar.proto\" "
3879     "message_type: {"
3880     "  name: \"Bar\""
3881     "  extension_range { start: 1 end: 1000 }"
3882     "}");
3883 
3884   BuildFileWithErrors(
3885     "name: \"foo.proto\" "
3886     "dependency: \"bar.proto\" "
3887     "options { optimize_for: LITE_RUNTIME } "
3888     "extension { name: \"ext\" number: 123 label: LABEL_OPTIONAL "
3889     "            type: TYPE_INT32 extendee: \"Bar\" }",
3890 
3891     "foo.proto: ext: EXTENDEE: Extensions to non-lite types can only be "
3892       "declared in non-lite files.  Note that you cannot extend a non-lite "
3893       "type to contain a lite type, but the reverse is allowed.\n");
3894 }
3895 
TEST_F(ValidationErrorTest,NoLiteServices)3896 TEST_F(ValidationErrorTest, NoLiteServices) {
3897   BuildFileWithErrors(
3898     "name: \"foo.proto\" "
3899     "options {"
3900     "  optimize_for: LITE_RUNTIME"
3901     "  cc_generic_services: true"
3902     "  java_generic_services: true"
3903     "} "
3904     "service { name: \"Foo\" }",
3905 
3906     "foo.proto: Foo: NAME: Files with optimize_for = LITE_RUNTIME cannot "
3907     "define services unless you set both options cc_generic_services and "
3908     "java_generic_sevices to false.\n");
3909 
3910   BuildFile(
3911     "name: \"bar.proto\" "
3912     "options {"
3913     "  optimize_for: LITE_RUNTIME"
3914     "  cc_generic_services: false"
3915     "  java_generic_services: false"
3916     "} "
3917     "service { name: \"Bar\" }");
3918 }
3919 
TEST_F(ValidationErrorTest,RollbackAfterError)3920 TEST_F(ValidationErrorTest, RollbackAfterError) {
3921   // Build a file which contains every kind of construct but references an
3922   // undefined type.  All these constructs will be added to the symbol table
3923   // before the undefined type error is noticed.  The DescriptorPool will then
3924   // have to roll everything back.
3925   BuildFileWithErrors(
3926     "name: \"foo.proto\" "
3927     "message_type {"
3928     "  name: \"TestMessage\""
3929     "  field { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:1 }"
3930     "} "
3931     "enum_type {"
3932     "  name: \"TestEnum\""
3933     "  value { name:\"BAR\" number:1 }"
3934     "} "
3935     "service {"
3936     "  name: \"TestService\""
3937     "  method {"
3938     "    name: \"Baz\""
3939     "    input_type: \"NoSuchType\""    // error
3940     "    output_type: \"TestMessage\""
3941     "  }"
3942     "}",
3943 
3944     "foo.proto: TestService.Baz: INPUT_TYPE: \"NoSuchType\" is not defined.\n"
3945     );
3946 
3947   // Make sure that if we build the same file again with the error fixed,
3948   // it works.  If the above rollback was incomplete, then some symbols will
3949   // be left defined, and this second attempt will fail since it tries to
3950   // re-define the same symbols.
3951   BuildFile(
3952     "name: \"foo.proto\" "
3953     "message_type {"
3954     "  name: \"TestMessage\""
3955     "  field { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:1 }"
3956     "} "
3957     "enum_type {"
3958     "  name: \"TestEnum\""
3959     "  value { name:\"BAR\" number:1 }"
3960     "} "
3961     "service {"
3962     "  name: \"TestService\""
3963     "  method { name:\"Baz\""
3964     "           input_type:\"TestMessage\""
3965     "           output_type:\"TestMessage\" }"
3966     "}");
3967 }
3968 
TEST_F(ValidationErrorTest,ErrorsReportedToLogError)3969 TEST_F(ValidationErrorTest, ErrorsReportedToLogError) {
3970   // Test that errors are reported to GOOGLE_LOG(ERROR) if no error collector is
3971   // provided.
3972 
3973   FileDescriptorProto file_proto;
3974   ASSERT_TRUE(TextFormat::ParseFromString(
3975     "name: \"foo.proto\" "
3976     "message_type { name: \"Foo\" } "
3977     "message_type { name: \"Foo\" } ",
3978     &file_proto));
3979 
3980   vector<string> errors;
3981 
3982   {
3983     ScopedMemoryLog log;
3984     EXPECT_TRUE(pool_.BuildFile(file_proto) == NULL);
3985     errors = log.GetMessages(ERROR);
3986   }
3987 
3988   ASSERT_EQ(2, errors.size());
3989 
3990   EXPECT_EQ("Invalid proto descriptor for file \"foo.proto\":", errors[0]);
3991   EXPECT_EQ("  Foo: \"Foo\" is already defined.", errors[1]);
3992 }
3993 
TEST_F(ValidationErrorTest,DisallowEnumAlias)3994 TEST_F(ValidationErrorTest, DisallowEnumAlias) {
3995   BuildFileWithErrors(
3996     "name: \"foo.proto\" "
3997     "enum_type {"
3998     "  name: \"Bar\""
3999     "  value { name:\"ENUM_A\" number:0 }"
4000     "  value { name:\"ENUM_B\" number:0 }"
4001     "  options { allow_alias: false }"
4002     "}",
4003     "foo.proto: Bar: NUMBER: "
4004     "\"ENUM_B\" uses the same enum value as \"ENUM_A\". "
4005     "If this is intended, set 'option allow_alias = true;' to the enum "
4006     "definition.\n");
4007 }
4008 
4009 // ===================================================================
4010 // DescriptorDatabase
4011 
AddToDatabase(SimpleDescriptorDatabase * database,const char * file_text)4012 static void AddToDatabase(SimpleDescriptorDatabase* database,
4013                           const char* file_text) {
4014   FileDescriptorProto file_proto;
4015   EXPECT_TRUE(TextFormat::ParseFromString(file_text, &file_proto));
4016   database->Add(file_proto);
4017 }
4018 
4019 class DatabaseBackedPoolTest : public testing::Test {
4020  protected:
DatabaseBackedPoolTest()4021   DatabaseBackedPoolTest() {}
4022 
4023   SimpleDescriptorDatabase database_;
4024 
SetUp()4025   virtual void SetUp() {
4026     AddToDatabase(&database_,
4027       "name: 'foo.proto' "
4028       "message_type { name:'Foo' extension_range { start: 1 end: 100 } } "
4029       "enum_type { name:'TestEnum' value { name:'DUMMY' number:0 } } "
4030       "service { name:'TestService' } ");
4031     AddToDatabase(&database_,
4032       "name: 'bar.proto' "
4033       "dependency: 'foo.proto' "
4034       "message_type { name:'Bar' } "
4035       "extension { name:'foo_ext' extendee: '.Foo' number:5 "
4036       "            label:LABEL_OPTIONAL type:TYPE_INT32 } ");
4037     // Baz has an undeclared dependency on Foo.
4038     AddToDatabase(&database_,
4039       "name: 'baz.proto' "
4040       "message_type { "
4041       "  name:'Baz' "
4042       "  field { name:'foo' number:1 label:LABEL_OPTIONAL type_name:'Foo' } "
4043       "}");
4044   }
4045 
4046   // We can't inject a file containing errors into a DescriptorPool, so we
4047   // need an actual mock DescriptorDatabase to test errors.
4048   class ErrorDescriptorDatabase : public DescriptorDatabase {
4049    public:
ErrorDescriptorDatabase()4050     ErrorDescriptorDatabase() {}
~ErrorDescriptorDatabase()4051     ~ErrorDescriptorDatabase() {}
4052 
4053     // implements DescriptorDatabase ---------------------------------
FindFileByName(const string & filename,FileDescriptorProto * output)4054     bool FindFileByName(const string& filename,
4055                         FileDescriptorProto* output) {
4056       // error.proto and error2.proto cyclically import each other.
4057       if (filename == "error.proto") {
4058         output->Clear();
4059         output->set_name("error.proto");
4060         output->add_dependency("error2.proto");
4061         return true;
4062       } else if (filename == "error2.proto") {
4063         output->Clear();
4064         output->set_name("error2.proto");
4065         output->add_dependency("error.proto");
4066         return true;
4067       } else {
4068         return false;
4069       }
4070     }
FindFileContainingSymbol(const string & symbol_name,FileDescriptorProto * output)4071     bool FindFileContainingSymbol(const string& symbol_name,
4072                                   FileDescriptorProto* output) {
4073       return false;
4074     }
FindFileContainingExtension(const string & containing_type,int field_number,FileDescriptorProto * output)4075     bool FindFileContainingExtension(const string& containing_type,
4076                                      int field_number,
4077                                      FileDescriptorProto* output) {
4078       return false;
4079     }
4080   };
4081 
4082   // A DescriptorDatabase that counts how many times each method has been
4083   // called and forwards to some other DescriptorDatabase.
4084   class CallCountingDatabase : public DescriptorDatabase {
4085    public:
CallCountingDatabase(DescriptorDatabase * wrapped_db)4086     CallCountingDatabase(DescriptorDatabase* wrapped_db)
4087       : wrapped_db_(wrapped_db) {
4088       Clear();
4089     }
~CallCountingDatabase()4090     ~CallCountingDatabase() {}
4091 
4092     DescriptorDatabase* wrapped_db_;
4093 
4094     int call_count_;
4095 
Clear()4096     void Clear() {
4097       call_count_ = 0;
4098     }
4099 
4100     // implements DescriptorDatabase ---------------------------------
FindFileByName(const string & filename,FileDescriptorProto * output)4101     bool FindFileByName(const string& filename,
4102                         FileDescriptorProto* output) {
4103       ++call_count_;
4104       return wrapped_db_->FindFileByName(filename, output);
4105     }
FindFileContainingSymbol(const string & symbol_name,FileDescriptorProto * output)4106     bool FindFileContainingSymbol(const string& symbol_name,
4107                                   FileDescriptorProto* output) {
4108       ++call_count_;
4109       return wrapped_db_->FindFileContainingSymbol(symbol_name, output);
4110     }
FindFileContainingExtension(const string & containing_type,int field_number,FileDescriptorProto * output)4111     bool FindFileContainingExtension(const string& containing_type,
4112                                      int field_number,
4113                                      FileDescriptorProto* output) {
4114       ++call_count_;
4115       return wrapped_db_->FindFileContainingExtension(
4116         containing_type, field_number, output);
4117     }
4118   };
4119 
4120   // A DescriptorDatabase which falsely always returns foo.proto when searching
4121   // for any symbol or extension number.  This shouldn't cause the
4122   // DescriptorPool to reload foo.proto if it is already loaded.
4123   class FalsePositiveDatabase : public DescriptorDatabase {
4124    public:
FalsePositiveDatabase(DescriptorDatabase * wrapped_db)4125     FalsePositiveDatabase(DescriptorDatabase* wrapped_db)
4126       : wrapped_db_(wrapped_db) {}
~FalsePositiveDatabase()4127     ~FalsePositiveDatabase() {}
4128 
4129     DescriptorDatabase* wrapped_db_;
4130 
4131     // implements DescriptorDatabase ---------------------------------
FindFileByName(const string & filename,FileDescriptorProto * output)4132     bool FindFileByName(const string& filename,
4133                         FileDescriptorProto* output) {
4134       return wrapped_db_->FindFileByName(filename, output);
4135     }
FindFileContainingSymbol(const string & symbol_name,FileDescriptorProto * output)4136     bool FindFileContainingSymbol(const string& symbol_name,
4137                                   FileDescriptorProto* output) {
4138       return FindFileByName("foo.proto", output);
4139     }
FindFileContainingExtension(const string & containing_type,int field_number,FileDescriptorProto * output)4140     bool FindFileContainingExtension(const string& containing_type,
4141                                      int field_number,
4142                                      FileDescriptorProto* output) {
4143       return FindFileByName("foo.proto", output);
4144     }
4145   };
4146 };
4147 
TEST_F(DatabaseBackedPoolTest,FindFileByName)4148 TEST_F(DatabaseBackedPoolTest, FindFileByName) {
4149   DescriptorPool pool(&database_);
4150 
4151   const FileDescriptor* foo = pool.FindFileByName("foo.proto");
4152   ASSERT_TRUE(foo != NULL);
4153   EXPECT_EQ("foo.proto", foo->name());
4154   ASSERT_EQ(1, foo->message_type_count());
4155   EXPECT_EQ("Foo", foo->message_type(0)->name());
4156 
4157   EXPECT_EQ(foo, pool.FindFileByName("foo.proto"));
4158 
4159   EXPECT_TRUE(pool.FindFileByName("no_such_file.proto") == NULL);
4160 }
4161 
TEST_F(DatabaseBackedPoolTest,FindDependencyBeforeDependent)4162 TEST_F(DatabaseBackedPoolTest, FindDependencyBeforeDependent) {
4163   DescriptorPool pool(&database_);
4164 
4165   const FileDescriptor* foo = pool.FindFileByName("foo.proto");
4166   ASSERT_TRUE(foo != NULL);
4167   EXPECT_EQ("foo.proto", foo->name());
4168   ASSERT_EQ(1, foo->message_type_count());
4169   EXPECT_EQ("Foo", foo->message_type(0)->name());
4170 
4171   const FileDescriptor* bar = pool.FindFileByName("bar.proto");
4172   ASSERT_TRUE(bar != NULL);
4173   EXPECT_EQ("bar.proto", bar->name());
4174   ASSERT_EQ(1, bar->message_type_count());
4175   EXPECT_EQ("Bar", bar->message_type(0)->name());
4176 
4177   ASSERT_EQ(1, bar->dependency_count());
4178   EXPECT_EQ(foo, bar->dependency(0));
4179 }
4180 
TEST_F(DatabaseBackedPoolTest,FindDependentBeforeDependency)4181 TEST_F(DatabaseBackedPoolTest, FindDependentBeforeDependency) {
4182   DescriptorPool pool(&database_);
4183 
4184   const FileDescriptor* bar = pool.FindFileByName("bar.proto");
4185   ASSERT_TRUE(bar != NULL);
4186   EXPECT_EQ("bar.proto", bar->name());
4187   ASSERT_EQ(1, bar->message_type_count());
4188   ASSERT_EQ("Bar", bar->message_type(0)->name());
4189 
4190   const FileDescriptor* foo = pool.FindFileByName("foo.proto");
4191   ASSERT_TRUE(foo != NULL);
4192   EXPECT_EQ("foo.proto", foo->name());
4193   ASSERT_EQ(1, foo->message_type_count());
4194   ASSERT_EQ("Foo", foo->message_type(0)->name());
4195 
4196   ASSERT_EQ(1, bar->dependency_count());
4197   EXPECT_EQ(foo, bar->dependency(0));
4198 }
4199 
TEST_F(DatabaseBackedPoolTest,FindFileContainingSymbol)4200 TEST_F(DatabaseBackedPoolTest, FindFileContainingSymbol) {
4201   DescriptorPool pool(&database_);
4202 
4203   const FileDescriptor* file = pool.FindFileContainingSymbol("Foo");
4204   ASSERT_TRUE(file != NULL);
4205   EXPECT_EQ("foo.proto", file->name());
4206   EXPECT_EQ(file, pool.FindFileByName("foo.proto"));
4207 
4208   EXPECT_TRUE(pool.FindFileContainingSymbol("NoSuchSymbol") == NULL);
4209 }
4210 
TEST_F(DatabaseBackedPoolTest,FindMessageTypeByName)4211 TEST_F(DatabaseBackedPoolTest, FindMessageTypeByName) {
4212   DescriptorPool pool(&database_);
4213 
4214   const Descriptor* type = pool.FindMessageTypeByName("Foo");
4215   ASSERT_TRUE(type != NULL);
4216   EXPECT_EQ("Foo", type->name());
4217   EXPECT_EQ(type->file(), pool.FindFileByName("foo.proto"));
4218 
4219   EXPECT_TRUE(pool.FindMessageTypeByName("NoSuchType") == NULL);
4220 }
4221 
TEST_F(DatabaseBackedPoolTest,FindExtensionByNumber)4222 TEST_F(DatabaseBackedPoolTest, FindExtensionByNumber) {
4223   DescriptorPool pool(&database_);
4224 
4225   const Descriptor* foo = pool.FindMessageTypeByName("Foo");
4226   ASSERT_TRUE(foo != NULL);
4227 
4228   const FieldDescriptor* extension = pool.FindExtensionByNumber(foo, 5);
4229   ASSERT_TRUE(extension != NULL);
4230   EXPECT_EQ("foo_ext", extension->name());
4231   EXPECT_EQ(extension->file(), pool.FindFileByName("bar.proto"));
4232 
4233   EXPECT_TRUE(pool.FindExtensionByNumber(foo, 12) == NULL);
4234 }
4235 
TEST_F(DatabaseBackedPoolTest,FindAllExtensions)4236 TEST_F(DatabaseBackedPoolTest, FindAllExtensions) {
4237   DescriptorPool pool(&database_);
4238 
4239   const Descriptor* foo = pool.FindMessageTypeByName("Foo");
4240 
4241   for (int i = 0; i < 2; ++i) {
4242     // Repeat the lookup twice, to check that we get consistent
4243     // results despite the fallback database lookup mutating the pool.
4244     vector<const FieldDescriptor*> extensions;
4245     pool.FindAllExtensions(foo, &extensions);
4246     ASSERT_EQ(1, extensions.size());
4247     EXPECT_EQ(5, extensions[0]->number());
4248   }
4249 }
4250 
TEST_F(DatabaseBackedPoolTest,ErrorWithoutErrorCollector)4251 TEST_F(DatabaseBackedPoolTest, ErrorWithoutErrorCollector) {
4252   ErrorDescriptorDatabase error_database;
4253   DescriptorPool pool(&error_database);
4254 
4255   vector<string> errors;
4256 
4257   {
4258     ScopedMemoryLog log;
4259     EXPECT_TRUE(pool.FindFileByName("error.proto") == NULL);
4260     errors = log.GetMessages(ERROR);
4261   }
4262 
4263   EXPECT_FALSE(errors.empty());
4264 }
4265 
TEST_F(DatabaseBackedPoolTest,ErrorWithErrorCollector)4266 TEST_F(DatabaseBackedPoolTest, ErrorWithErrorCollector) {
4267   ErrorDescriptorDatabase error_database;
4268   MockErrorCollector error_collector;
4269   DescriptorPool pool(&error_database, &error_collector);
4270 
4271   EXPECT_TRUE(pool.FindFileByName("error.proto") == NULL);
4272   EXPECT_EQ(
4273     "error.proto: error.proto: OTHER: File recursively imports itself: "
4274       "error.proto -> error2.proto -> error.proto\n"
4275     "error2.proto: error2.proto: OTHER: Import \"error.proto\" was not "
4276       "found or had errors.\n"
4277     "error.proto: error.proto: OTHER: Import \"error2.proto\" was not "
4278       "found or had errors.\n",
4279     error_collector.text_);
4280 }
4281 
TEST_F(DatabaseBackedPoolTest,UndeclaredDependencyOnUnbuiltType)4282 TEST_F(DatabaseBackedPoolTest, UndeclaredDependencyOnUnbuiltType) {
4283   // Check that we find and report undeclared dependencies on types that exist
4284   // in the descriptor database but that have not not been built yet.
4285   MockErrorCollector error_collector;
4286   DescriptorPool pool(&database_, &error_collector);
4287   EXPECT_TRUE(pool.FindMessageTypeByName("Baz") == NULL);
4288   EXPECT_EQ(
4289     "baz.proto: Baz.foo: TYPE: \"Foo\" seems to be defined in \"foo.proto\", "
4290     "which is not imported by \"baz.proto\".  To use it here, please add "
4291     "the necessary import.\n",
4292     error_collector.text_);
4293 }
4294 
TEST_F(DatabaseBackedPoolTest,RollbackAfterError)4295 TEST_F(DatabaseBackedPoolTest, RollbackAfterError) {
4296   // Make sure that all traces of bad types are removed from the pool. This used
4297   // to be b/4529436, due to the fact that a symbol resolution failure could
4298   // potentially cause another file to be recursively built, which would trigger
4299   // a checkpoint _past_ possibly invalid symbols.
4300   // Baz is defined in the database, but the file is invalid because it is
4301   // missing a necessary import.
4302   DescriptorPool pool(&database_);
4303   EXPECT_TRUE(pool.FindMessageTypeByName("Baz") == NULL);
4304   // Make sure that searching again for the file or the type fails.
4305   EXPECT_TRUE(pool.FindFileByName("baz.proto") == NULL);
4306   EXPECT_TRUE(pool.FindMessageTypeByName("Baz") == NULL);
4307 }
4308 
TEST_F(DatabaseBackedPoolTest,UnittestProto)4309 TEST_F(DatabaseBackedPoolTest, UnittestProto) {
4310   // Try to load all of unittest.proto from a DescriptorDatabase.  This should
4311   // thoroughly test all paths through DescriptorBuilder to insure that there
4312   // are no deadlocking problems when pool_->mutex_ is non-NULL.
4313   const FileDescriptor* original_file =
4314     protobuf_unittest::TestAllTypes::descriptor()->file();
4315 
4316   DescriptorPoolDatabase database(*DescriptorPool::generated_pool());
4317   DescriptorPool pool(&database);
4318   const FileDescriptor* file_from_database =
4319     pool.FindFileByName(original_file->name());
4320 
4321   ASSERT_TRUE(file_from_database != NULL);
4322 
4323   FileDescriptorProto original_file_proto;
4324   original_file->CopyTo(&original_file_proto);
4325 
4326   FileDescriptorProto file_from_database_proto;
4327   file_from_database->CopyTo(&file_from_database_proto);
4328 
4329   EXPECT_EQ(original_file_proto.DebugString(),
4330             file_from_database_proto.DebugString());
4331 }
4332 
TEST_F(DatabaseBackedPoolTest,DoesntRetryDbUnnecessarily)4333 TEST_F(DatabaseBackedPoolTest, DoesntRetryDbUnnecessarily) {
4334   // Searching for a child of an existing descriptor should never fall back
4335   // to the DescriptorDatabase even if it isn't found, because we know all
4336   // children are already loaded.
4337   CallCountingDatabase call_counter(&database_);
4338   DescriptorPool pool(&call_counter);
4339 
4340   const FileDescriptor* file = pool.FindFileByName("foo.proto");
4341   ASSERT_TRUE(file != NULL);
4342   const Descriptor* foo = pool.FindMessageTypeByName("Foo");
4343   ASSERT_TRUE(foo != NULL);
4344   const EnumDescriptor* test_enum = pool.FindEnumTypeByName("TestEnum");
4345   ASSERT_TRUE(test_enum != NULL);
4346   const ServiceDescriptor* test_service = pool.FindServiceByName("TestService");
4347   ASSERT_TRUE(test_service != NULL);
4348 
4349   EXPECT_NE(0, call_counter.call_count_);
4350   call_counter.Clear();
4351 
4352   EXPECT_TRUE(foo->FindFieldByName("no_such_field") == NULL);
4353   EXPECT_TRUE(foo->FindExtensionByName("no_such_extension") == NULL);
4354   EXPECT_TRUE(foo->FindNestedTypeByName("NoSuchMessageType") == NULL);
4355   EXPECT_TRUE(foo->FindEnumTypeByName("NoSuchEnumType") == NULL);
4356   EXPECT_TRUE(foo->FindEnumValueByName("NO_SUCH_VALUE") == NULL);
4357   EXPECT_TRUE(test_enum->FindValueByName("NO_SUCH_VALUE") == NULL);
4358   EXPECT_TRUE(test_service->FindMethodByName("NoSuchMethod") == NULL);
4359 
4360   EXPECT_TRUE(file->FindMessageTypeByName("NoSuchMessageType") == NULL);
4361   EXPECT_TRUE(file->FindEnumTypeByName("NoSuchEnumType") == NULL);
4362   EXPECT_TRUE(file->FindEnumValueByName("NO_SUCH_VALUE") == NULL);
4363   EXPECT_TRUE(file->FindServiceByName("NO_SUCH_VALUE") == NULL);
4364   EXPECT_TRUE(file->FindExtensionByName("no_such_extension") == NULL);
4365 
4366   EXPECT_TRUE(pool.FindFileContainingSymbol("Foo.no.such.field") == NULL);
4367   EXPECT_TRUE(pool.FindFileContainingSymbol("Foo.no_such_field") == NULL);
4368   EXPECT_TRUE(pool.FindMessageTypeByName("Foo.NoSuchMessageType") == NULL);
4369   EXPECT_TRUE(pool.FindFieldByName("Foo.no_such_field") == NULL);
4370   EXPECT_TRUE(pool.FindExtensionByName("Foo.no_such_extension") == NULL);
4371   EXPECT_TRUE(pool.FindEnumTypeByName("Foo.NoSuchEnumType") == NULL);
4372   EXPECT_TRUE(pool.FindEnumValueByName("Foo.NO_SUCH_VALUE") == NULL);
4373   EXPECT_TRUE(pool.FindMethodByName("TestService.NoSuchMethod") == NULL);
4374 
4375   EXPECT_EQ(0, call_counter.call_count_);
4376 }
4377 
TEST_F(DatabaseBackedPoolTest,DoesntReloadFilesUncesessarily)4378 TEST_F(DatabaseBackedPoolTest, DoesntReloadFilesUncesessarily) {
4379   // If FindFileContainingSymbol() or FindFileContainingExtension() return a
4380   // file that is already in the DescriptorPool, it should not attempt to
4381   // reload the file.
4382   FalsePositiveDatabase false_positive_database(&database_);
4383   MockErrorCollector error_collector;
4384   DescriptorPool pool(&false_positive_database, &error_collector);
4385 
4386   // First make sure foo.proto is loaded.
4387   const Descriptor* foo = pool.FindMessageTypeByName("Foo");
4388   ASSERT_TRUE(foo != NULL);
4389 
4390   // Try inducing false positives.
4391   EXPECT_TRUE(pool.FindMessageTypeByName("NoSuchSymbol") == NULL);
4392   EXPECT_TRUE(pool.FindExtensionByNumber(foo, 22) == NULL);
4393 
4394   // No errors should have been reported.  (If foo.proto was incorrectly
4395   // loaded multiple times, errors would have been reported.)
4396   EXPECT_EQ("", error_collector.text_);
4397 }
4398 
TEST_F(DatabaseBackedPoolTest,DoesntReloadKnownBadFiles)4399 TEST_F(DatabaseBackedPoolTest, DoesntReloadKnownBadFiles) {
4400   ErrorDescriptorDatabase error_database;
4401   MockErrorCollector error_collector;
4402   DescriptorPool pool(&error_database, &error_collector);
4403 
4404   EXPECT_TRUE(pool.FindFileByName("error.proto") == NULL);
4405   error_collector.text_.clear();
4406   EXPECT_TRUE(pool.FindFileByName("error.proto") == NULL);
4407   EXPECT_EQ("", error_collector.text_);
4408 }
4409 
TEST_F(DatabaseBackedPoolTest,DoesntFallbackOnWrongType)4410 TEST_F(DatabaseBackedPoolTest, DoesntFallbackOnWrongType) {
4411   // If a lookup finds a symbol of the wrong type (e.g. we pass a type name
4412   // to FindFieldByName()), we should fail fast, without checking the fallback
4413   // database.
4414   CallCountingDatabase call_counter(&database_);
4415   DescriptorPool pool(&call_counter);
4416 
4417   const FileDescriptor* file = pool.FindFileByName("foo.proto");
4418   ASSERT_TRUE(file != NULL);
4419   const Descriptor* foo = pool.FindMessageTypeByName("Foo");
4420   ASSERT_TRUE(foo != NULL);
4421   const EnumDescriptor* test_enum = pool.FindEnumTypeByName("TestEnum");
4422   ASSERT_TRUE(test_enum != NULL);
4423 
4424   EXPECT_NE(0, call_counter.call_count_);
4425   call_counter.Clear();
4426 
4427   EXPECT_TRUE(pool.FindMessageTypeByName("TestEnum") == NULL);
4428   EXPECT_TRUE(pool.FindFieldByName("Foo") == NULL);
4429   EXPECT_TRUE(pool.FindExtensionByName("Foo") == NULL);
4430   EXPECT_TRUE(pool.FindEnumTypeByName("Foo") == NULL);
4431   EXPECT_TRUE(pool.FindEnumValueByName("Foo") == NULL);
4432   EXPECT_TRUE(pool.FindServiceByName("Foo") == NULL);
4433   EXPECT_TRUE(pool.FindMethodByName("Foo") == NULL);
4434 
4435   EXPECT_EQ(0, call_counter.call_count_);
4436 }
4437 
4438 // ===================================================================
4439 
4440 class AbortingErrorCollector : public DescriptorPool::ErrorCollector {
4441  public:
AbortingErrorCollector()4442   AbortingErrorCollector() {}
4443 
AddError(const string & filename,const string & element_name,const Message * message,ErrorLocation location,const string & error_message)4444   virtual void AddError(
4445       const string &filename,
4446       const string &element_name,
4447       const Message *message,
4448       ErrorLocation location,
4449       const string &error_message) {
4450     GOOGLE_LOG(FATAL) << "AddError() called unexpectedly: " << filename << ": "
4451                << error_message;
4452   }
4453  private:
4454   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(AbortingErrorCollector);
4455 };
4456 
4457 // A source tree containing only one file.
4458 class SingletonSourceTree : public compiler::SourceTree {
4459  public:
SingletonSourceTree(const string & filename,const string & contents)4460   SingletonSourceTree(const string& filename, const string& contents)
4461       : filename_(filename), contents_(contents) {}
4462 
Open(const string & filename)4463   virtual io::ZeroCopyInputStream* Open(const string& filename) {
4464     return filename == filename_ ?
4465         new io::ArrayInputStream(contents_.data(), contents_.size()) : NULL;
4466   }
4467 
4468  private:
4469   const string filename_;
4470   const string contents_;
4471 
4472   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SingletonSourceTree);
4473 };
4474 
4475 const char *const kSourceLocationTestInput =
4476   "syntax = \"proto2\";\n"
4477   "message A {\n"
4478   "  optional int32 a = 1;\n"
4479   "  message B {\n"
4480   "    required double b = 1;\n"
4481   "  }\n"
4482   "}\n"
4483   "enum Indecision {\n"
4484   "  YES   = 1;\n"
4485   "  NO    = 2;\n"
4486   "  MAYBE = 3;\n"
4487   "}\n"
4488   "service S {\n"
4489   "  rpc Method(A) returns (A.B);\n"
4490   // Put an empty line here to make the source location range match.
4491   "\n"
4492   "}\n";
4493 
4494 class SourceLocationTest : public testing::Test {
4495  public:
SourceLocationTest()4496   SourceLocationTest()
4497       : source_tree_("/test/test.proto", kSourceLocationTestInput),
4498         db_(&source_tree_),
4499         pool_(&db_, &collector_) {}
4500 
PrintSourceLocation(const SourceLocation & loc)4501   static string PrintSourceLocation(const SourceLocation &loc) {
4502     return strings::Substitute("$0:$1-$2:$3",
4503                                1 + loc.start_line,
4504                                1 + loc.start_column,
4505                                1 + loc.end_line,
4506                                1 + loc.end_column);
4507   }
4508 
4509  private:
4510   AbortingErrorCollector collector_;
4511   SingletonSourceTree source_tree_;
4512   compiler::SourceTreeDescriptorDatabase db_;
4513 
4514  protected:
4515   DescriptorPool pool_;
4516 };
4517 
4518 // TODO(adonovan): implement support for option fields and for
4519 // subparts of declarations.
4520 
TEST_F(SourceLocationTest,GetSourceLocation)4521 TEST_F(SourceLocationTest, GetSourceLocation) {
4522   SourceLocation loc;
4523 
4524   const FileDescriptor *file_desc =
4525       GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto"));
4526 
4527   const Descriptor *a_desc = file_desc->FindMessageTypeByName("A");
4528   EXPECT_TRUE(a_desc->GetSourceLocation(&loc));
4529   EXPECT_EQ("2:1-7:2", PrintSourceLocation(loc));
4530 
4531   const Descriptor *a_b_desc = a_desc->FindNestedTypeByName("B");
4532   EXPECT_TRUE(a_b_desc->GetSourceLocation(&loc));
4533   EXPECT_EQ("4:3-6:4", PrintSourceLocation(loc));
4534 
4535   const EnumDescriptor *e_desc = file_desc->FindEnumTypeByName("Indecision");
4536   EXPECT_TRUE(e_desc->GetSourceLocation(&loc));
4537   EXPECT_EQ("8:1-12:2", PrintSourceLocation(loc));
4538 
4539   const EnumValueDescriptor *yes_desc = e_desc->FindValueByName("YES");
4540   EXPECT_TRUE(yes_desc->GetSourceLocation(&loc));
4541   EXPECT_EQ("9:3-9:13", PrintSourceLocation(loc));
4542 
4543   const ServiceDescriptor *s_desc = file_desc->FindServiceByName("S");
4544   EXPECT_TRUE(s_desc->GetSourceLocation(&loc));
4545   EXPECT_EQ("13:1-16:2", PrintSourceLocation(loc));
4546 
4547   const MethodDescriptor *m_desc = s_desc->FindMethodByName("Method");
4548   EXPECT_TRUE(m_desc->GetSourceLocation(&loc));
4549   EXPECT_EQ("14:3-14:31", PrintSourceLocation(loc));
4550 
4551 }
4552 
4553 // Missing SourceCodeInfo doesn't cause crash:
TEST_F(SourceLocationTest,GetSourceLocation_MissingSourceCodeInfo)4554 TEST_F(SourceLocationTest, GetSourceLocation_MissingSourceCodeInfo) {
4555   SourceLocation loc;
4556 
4557   const FileDescriptor *file_desc =
4558       GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto"));
4559 
4560   FileDescriptorProto proto;
4561   file_desc->CopyTo(&proto);  // Note, this discards the SourceCodeInfo.
4562   EXPECT_FALSE(proto.has_source_code_info());
4563 
4564   DescriptorPool bad1_pool(&pool_);
4565   const FileDescriptor* bad1_file_desc =
4566       GOOGLE_CHECK_NOTNULL(bad1_pool.BuildFile(proto));
4567   const Descriptor *bad1_a_desc = bad1_file_desc->FindMessageTypeByName("A");
4568   EXPECT_FALSE(bad1_a_desc->GetSourceLocation(&loc));
4569 }
4570 
4571 // Corrupt SourceCodeInfo doesn't cause crash:
TEST_F(SourceLocationTest,GetSourceLocation_BogusSourceCodeInfo)4572 TEST_F(SourceLocationTest, GetSourceLocation_BogusSourceCodeInfo) {
4573   SourceLocation loc;
4574 
4575   const FileDescriptor *file_desc =
4576       GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto"));
4577 
4578   FileDescriptorProto proto;
4579   file_desc->CopyTo(&proto);  // Note, this discards the SourceCodeInfo.
4580   EXPECT_FALSE(proto.has_source_code_info());
4581   SourceCodeInfo_Location *loc_msg =
4582       proto.mutable_source_code_info()->add_location();
4583   loc_msg->add_path(1);
4584   loc_msg->add_path(2);
4585   loc_msg->add_path(3);
4586   loc_msg->add_span(4);
4587   loc_msg->add_span(5);
4588   loc_msg->add_span(6);
4589 
4590   DescriptorPool bad2_pool(&pool_);
4591   const FileDescriptor* bad2_file_desc =
4592       GOOGLE_CHECK_NOTNULL(bad2_pool.BuildFile(proto));
4593   const Descriptor *bad2_a_desc = bad2_file_desc->FindMessageTypeByName("A");
4594   EXPECT_FALSE(bad2_a_desc->GetSourceLocation(&loc));
4595 }
4596 
4597 // ===================================================================
4598 
4599 const char* const kCopySourceCodeInfoToTestInput =
4600   "syntax = \"proto2\";\n"
4601   "message Foo {}\n";
4602 
4603 // Required since source code information is not preserved by
4604 // FileDescriptorTest.
4605 class CopySourceCodeInfoToTest : public testing::Test {
4606  public:
CopySourceCodeInfoToTest()4607   CopySourceCodeInfoToTest()
4608       : source_tree_("/test/test.proto", kCopySourceCodeInfoToTestInput),
4609         db_(&source_tree_),
4610         pool_(&db_, &collector_) {}
4611 
4612  private:
4613   AbortingErrorCollector collector_;
4614   SingletonSourceTree source_tree_;
4615   compiler::SourceTreeDescriptorDatabase db_;
4616 
4617  protected:
4618   DescriptorPool pool_;
4619 };
4620 
TEST_F(CopySourceCodeInfoToTest,CopyTo_DoesNotCopySourceCodeInfo)4621 TEST_F(CopySourceCodeInfoToTest, CopyTo_DoesNotCopySourceCodeInfo) {
4622   const FileDescriptor* file_desc =
4623       GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto"));
4624   FileDescriptorProto file_desc_proto;
4625   ASSERT_FALSE(file_desc_proto.has_source_code_info());
4626 
4627   file_desc->CopyTo(&file_desc_proto);
4628   EXPECT_FALSE(file_desc_proto.has_source_code_info());
4629 }
4630 
TEST_F(CopySourceCodeInfoToTest,CopySourceCodeInfoTo)4631 TEST_F(CopySourceCodeInfoToTest, CopySourceCodeInfoTo) {
4632   const FileDescriptor* file_desc =
4633       GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto"));
4634   FileDescriptorProto file_desc_proto;
4635   ASSERT_FALSE(file_desc_proto.has_source_code_info());
4636 
4637   file_desc->CopySourceCodeInfoTo(&file_desc_proto);
4638   const SourceCodeInfo& info = file_desc_proto.source_code_info();
4639   ASSERT_EQ(3, info.location_size());
4640   // Get the Foo message location
4641   const SourceCodeInfo_Location& foo_location = info.location(1);
4642   ASSERT_EQ(2, foo_location.path_size());
4643   EXPECT_EQ(FileDescriptorProto::kMessageTypeFieldNumber, foo_location.path(0));
4644   EXPECT_EQ(0, foo_location.path(1));      // Foo is the first message defined
4645   ASSERT_EQ(3, foo_location.span_size());  // Foo spans one line
4646   EXPECT_EQ(1, foo_location.span(0));      // Foo is declared on line 1
4647   EXPECT_EQ(0, foo_location.span(1));      // Foo starts at column 0
4648   EXPECT_EQ(14, foo_location.span(2));     // Foo ends on column 14
4649 }
4650 
4651 // ===================================================================
4652 
4653 
4654 }  // namespace descriptor_unittest
4655 }  // namespace protobuf
4656 }  // namespace google
4657