1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc.  All rights reserved.
3 // https://developers.google.com/protocol-buffers/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 //     * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 //     * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 //     * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 
31 // Author: kenton@google.com (Kenton Varda)
32 //  Based on original Protocol Buffers design by
33 //  Sanjay Ghemawat, Jeff Dean, and others.
34 //
35 // This file makes extensive use of RFC 3092.  :)
36 
37 #include <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 // Test simple flat messages and fields.
650 class OneofDescriptorTest : public testing::Test {
651  protected:
SetUp()652   virtual void SetUp() {
653     // Build descriptors for the following definitions:
654     //
655     //   package garply;
656     //   message TestOneof {
657     //     optional int32 a = 1;
658     //     oneof foo {
659     //       string b = 2;
660     //       TestOneof c = 3;
661     //     }
662     //     oneof bar {
663     //       float d = 4;
664     //     }
665     //   }
666 
667     FileDescriptorProto baz_file;
668     baz_file.set_name("baz.proto");
669     baz_file.set_package("garply");
670 
671     DescriptorProto* oneof_message = AddMessage(&baz_file, "TestOneof");
672     oneof_message->add_oneof_decl()->set_name("foo");
673     oneof_message->add_oneof_decl()->set_name("bar");
674 
675     AddField(oneof_message, "a", 1,
676              FieldDescriptorProto::LABEL_OPTIONAL,
677              FieldDescriptorProto::TYPE_INT32);
678     AddField(oneof_message, "b", 2,
679              FieldDescriptorProto::LABEL_OPTIONAL,
680              FieldDescriptorProto::TYPE_STRING);
681     oneof_message->mutable_field(1)->set_oneof_index(0);
682     AddField(oneof_message, "c", 3,
683              FieldDescriptorProto::LABEL_OPTIONAL,
684              FieldDescriptorProto::TYPE_MESSAGE);
685     oneof_message->mutable_field(2)->set_oneof_index(0);
686     oneof_message->mutable_field(2)->set_type_name("TestOneof");
687 
688     AddField(oneof_message, "d", 4,
689              FieldDescriptorProto::LABEL_OPTIONAL,
690              FieldDescriptorProto::TYPE_FLOAT);
691     oneof_message->mutable_field(3)->set_oneof_index(1);
692 
693     // Build the descriptors and get the pointers.
694     baz_file_ = pool_.BuildFile(baz_file);
695     ASSERT_TRUE(baz_file_ != NULL);
696 
697     ASSERT_EQ(1, baz_file_->message_type_count());
698     oneof_message_ = baz_file_->message_type(0);
699 
700     ASSERT_EQ(2, oneof_message_->oneof_decl_count());
701     oneof_ = oneof_message_->oneof_decl(0);
702     oneof2_ = oneof_message_->oneof_decl(1);
703 
704     ASSERT_EQ(4, oneof_message_->field_count());
705     a_ = oneof_message_->field(0);
706     b_ = oneof_message_->field(1);
707     c_ = oneof_message_->field(2);
708     d_ = oneof_message_->field(3);
709   }
710 
711   DescriptorPool pool_;
712 
713   const FileDescriptor* baz_file_;
714 
715   const Descriptor* oneof_message_;
716 
717   const OneofDescriptor* oneof_;
718   const OneofDescriptor* oneof2_;
719   const FieldDescriptor* a_;
720   const FieldDescriptor* b_;
721   const FieldDescriptor* c_;
722   const FieldDescriptor* d_;
723   const FieldDescriptor* e_;
724   const FieldDescriptor* f_;
725 };
726 
TEST_F(OneofDescriptorTest,Normal)727 TEST_F(OneofDescriptorTest, Normal) {
728   EXPECT_EQ("foo", oneof_->name());
729   EXPECT_EQ("garply.TestOneof.foo", oneof_->full_name());
730   EXPECT_EQ(0, oneof_->index());
731   ASSERT_EQ(2, oneof_->field_count());
732   EXPECT_EQ(b_, oneof_->field(0));
733   EXPECT_EQ(c_, oneof_->field(1));
734   EXPECT_TRUE(a_->containing_oneof() == NULL);
735   EXPECT_EQ(oneof_, b_->containing_oneof());
736   EXPECT_EQ(oneof_, c_->containing_oneof());
737 }
738 
TEST_F(OneofDescriptorTest,FindByName)739 TEST_F(OneofDescriptorTest, FindByName) {
740   EXPECT_EQ(oneof_, oneof_message_->FindOneofByName("foo"));
741   EXPECT_EQ(oneof2_, oneof_message_->FindOneofByName("bar"));
742   EXPECT_TRUE(oneof_message_->FindOneofByName("no_such_oneof") == NULL);
743 }
744 
745 // ===================================================================
746 
747 class StylizedFieldNamesTest : public testing::Test {
748  protected:
SetUp()749   void SetUp() {
750     FileDescriptorProto file;
751     file.set_name("foo.proto");
752 
753     AddExtensionRange(AddMessage(&file, "ExtendableMessage"), 1, 1000);
754 
755     DescriptorProto* message = AddMessage(&file, "TestMessage");
756     AddField(message, "foo_foo", 1,
757              FieldDescriptorProto::LABEL_OPTIONAL,
758              FieldDescriptorProto::TYPE_INT32);
759     AddField(message, "FooBar", 2,
760              FieldDescriptorProto::LABEL_OPTIONAL,
761              FieldDescriptorProto::TYPE_INT32);
762     AddField(message, "fooBaz", 3,
763              FieldDescriptorProto::LABEL_OPTIONAL,
764              FieldDescriptorProto::TYPE_INT32);
765     AddField(message, "fooFoo", 4,  // Camel-case conflict with foo_foo.
766              FieldDescriptorProto::LABEL_OPTIONAL,
767              FieldDescriptorProto::TYPE_INT32);
768     AddField(message, "foobar", 5,  // Lower-case conflict with FooBar.
769              FieldDescriptorProto::LABEL_OPTIONAL,
770              FieldDescriptorProto::TYPE_INT32);
771 
772     AddNestedExtension(message, "ExtendableMessage", "bar_foo", 1,
773                        FieldDescriptorProto::LABEL_OPTIONAL,
774                        FieldDescriptorProto::TYPE_INT32);
775     AddNestedExtension(message, "ExtendableMessage", "BarBar", 2,
776                        FieldDescriptorProto::LABEL_OPTIONAL,
777                        FieldDescriptorProto::TYPE_INT32);
778     AddNestedExtension(message, "ExtendableMessage", "BarBaz", 3,
779                        FieldDescriptorProto::LABEL_OPTIONAL,
780                        FieldDescriptorProto::TYPE_INT32);
781     AddNestedExtension(message, "ExtendableMessage", "barFoo", 4,  // Conflict
782                        FieldDescriptorProto::LABEL_OPTIONAL,
783                        FieldDescriptorProto::TYPE_INT32);
784     AddNestedExtension(message, "ExtendableMessage", "barbar", 5,  // Conflict
785                        FieldDescriptorProto::LABEL_OPTIONAL,
786                        FieldDescriptorProto::TYPE_INT32);
787 
788     AddExtension(&file, "ExtendableMessage", "baz_foo", 11,
789                  FieldDescriptorProto::LABEL_OPTIONAL,
790                  FieldDescriptorProto::TYPE_INT32);
791     AddExtension(&file, "ExtendableMessage", "BazBar", 12,
792                  FieldDescriptorProto::LABEL_OPTIONAL,
793                  FieldDescriptorProto::TYPE_INT32);
794     AddExtension(&file, "ExtendableMessage", "BazBaz", 13,
795                  FieldDescriptorProto::LABEL_OPTIONAL,
796                  FieldDescriptorProto::TYPE_INT32);
797     AddExtension(&file, "ExtendableMessage", "bazFoo", 14,  // Conflict
798                  FieldDescriptorProto::LABEL_OPTIONAL,
799                  FieldDescriptorProto::TYPE_INT32);
800     AddExtension(&file, "ExtendableMessage", "bazbar", 15,  // Conflict
801                  FieldDescriptorProto::LABEL_OPTIONAL,
802                  FieldDescriptorProto::TYPE_INT32);
803 
804     file_ = pool_.BuildFile(file);
805     ASSERT_TRUE(file_ != NULL);
806     ASSERT_EQ(2, file_->message_type_count());
807     message_ = file_->message_type(1);
808     ASSERT_EQ("TestMessage", message_->name());
809     ASSERT_EQ(5, message_->field_count());
810     ASSERT_EQ(5, message_->extension_count());
811     ASSERT_EQ(5, file_->extension_count());
812   }
813 
814   DescriptorPool pool_;
815   const FileDescriptor* file_;
816   const Descriptor* message_;
817 };
818 
TEST_F(StylizedFieldNamesTest,LowercaseName)819 TEST_F(StylizedFieldNamesTest, LowercaseName) {
820   EXPECT_EQ("foo_foo", message_->field(0)->lowercase_name());
821   EXPECT_EQ("foobar" , message_->field(1)->lowercase_name());
822   EXPECT_EQ("foobaz" , message_->field(2)->lowercase_name());
823   EXPECT_EQ("foofoo" , message_->field(3)->lowercase_name());
824   EXPECT_EQ("foobar" , message_->field(4)->lowercase_name());
825 
826   EXPECT_EQ("bar_foo", message_->extension(0)->lowercase_name());
827   EXPECT_EQ("barbar" , message_->extension(1)->lowercase_name());
828   EXPECT_EQ("barbaz" , message_->extension(2)->lowercase_name());
829   EXPECT_EQ("barfoo" , message_->extension(3)->lowercase_name());
830   EXPECT_EQ("barbar" , message_->extension(4)->lowercase_name());
831 
832   EXPECT_EQ("baz_foo", file_->extension(0)->lowercase_name());
833   EXPECT_EQ("bazbar" , file_->extension(1)->lowercase_name());
834   EXPECT_EQ("bazbaz" , file_->extension(2)->lowercase_name());
835   EXPECT_EQ("bazfoo" , file_->extension(3)->lowercase_name());
836   EXPECT_EQ("bazbar" , file_->extension(4)->lowercase_name());
837 }
838 
TEST_F(StylizedFieldNamesTest,CamelcaseName)839 TEST_F(StylizedFieldNamesTest, CamelcaseName) {
840   EXPECT_EQ("fooFoo", message_->field(0)->camelcase_name());
841   EXPECT_EQ("fooBar", message_->field(1)->camelcase_name());
842   EXPECT_EQ("fooBaz", message_->field(2)->camelcase_name());
843   EXPECT_EQ("fooFoo", message_->field(3)->camelcase_name());
844   EXPECT_EQ("foobar", message_->field(4)->camelcase_name());
845 
846   EXPECT_EQ("barFoo", message_->extension(0)->camelcase_name());
847   EXPECT_EQ("barBar", message_->extension(1)->camelcase_name());
848   EXPECT_EQ("barBaz", message_->extension(2)->camelcase_name());
849   EXPECT_EQ("barFoo", message_->extension(3)->camelcase_name());
850   EXPECT_EQ("barbar", message_->extension(4)->camelcase_name());
851 
852   EXPECT_EQ("bazFoo", file_->extension(0)->camelcase_name());
853   EXPECT_EQ("bazBar", file_->extension(1)->camelcase_name());
854   EXPECT_EQ("bazBaz", file_->extension(2)->camelcase_name());
855   EXPECT_EQ("bazFoo", file_->extension(3)->camelcase_name());
856   EXPECT_EQ("bazbar", file_->extension(4)->camelcase_name());
857 }
858 
TEST_F(StylizedFieldNamesTest,FindByLowercaseName)859 TEST_F(StylizedFieldNamesTest, FindByLowercaseName) {
860   EXPECT_EQ(message_->field(0),
861             message_->FindFieldByLowercaseName("foo_foo"));
862   EXPECT_EQ(message_->field(1),
863             message_->FindFieldByLowercaseName("foobar"));
864   EXPECT_EQ(message_->field(2),
865             message_->FindFieldByLowercaseName("foobaz"));
866   EXPECT_TRUE(message_->FindFieldByLowercaseName("FooBar") == NULL);
867   EXPECT_TRUE(message_->FindFieldByLowercaseName("fooBaz") == NULL);
868   EXPECT_TRUE(message_->FindFieldByLowercaseName("bar_foo") == NULL);
869   EXPECT_TRUE(message_->FindFieldByLowercaseName("nosuchfield") == NULL);
870 
871   EXPECT_EQ(message_->extension(0),
872             message_->FindExtensionByLowercaseName("bar_foo"));
873   EXPECT_EQ(message_->extension(1),
874             message_->FindExtensionByLowercaseName("barbar"));
875   EXPECT_EQ(message_->extension(2),
876             message_->FindExtensionByLowercaseName("barbaz"));
877   EXPECT_TRUE(message_->FindExtensionByLowercaseName("BarBar") == NULL);
878   EXPECT_TRUE(message_->FindExtensionByLowercaseName("barBaz") == NULL);
879   EXPECT_TRUE(message_->FindExtensionByLowercaseName("foo_foo") == NULL);
880   EXPECT_TRUE(message_->FindExtensionByLowercaseName("nosuchfield") == NULL);
881 
882   EXPECT_EQ(file_->extension(0),
883             file_->FindExtensionByLowercaseName("baz_foo"));
884   EXPECT_EQ(file_->extension(1),
885             file_->FindExtensionByLowercaseName("bazbar"));
886   EXPECT_EQ(file_->extension(2),
887             file_->FindExtensionByLowercaseName("bazbaz"));
888   EXPECT_TRUE(file_->FindExtensionByLowercaseName("BazBar") == NULL);
889   EXPECT_TRUE(file_->FindExtensionByLowercaseName("bazBaz") == NULL);
890   EXPECT_TRUE(file_->FindExtensionByLowercaseName("nosuchfield") == NULL);
891 }
892 
TEST_F(StylizedFieldNamesTest,FindByCamelcaseName)893 TEST_F(StylizedFieldNamesTest, FindByCamelcaseName) {
894   EXPECT_EQ(message_->field(0),
895             message_->FindFieldByCamelcaseName("fooFoo"));
896   EXPECT_EQ(message_->field(1),
897             message_->FindFieldByCamelcaseName("fooBar"));
898   EXPECT_EQ(message_->field(2),
899             message_->FindFieldByCamelcaseName("fooBaz"));
900   EXPECT_TRUE(message_->FindFieldByCamelcaseName("foo_foo") == NULL);
901   EXPECT_TRUE(message_->FindFieldByCamelcaseName("FooBar") == NULL);
902   EXPECT_TRUE(message_->FindFieldByCamelcaseName("barFoo") == NULL);
903   EXPECT_TRUE(message_->FindFieldByCamelcaseName("nosuchfield") == NULL);
904 
905   EXPECT_EQ(message_->extension(0),
906             message_->FindExtensionByCamelcaseName("barFoo"));
907   EXPECT_EQ(message_->extension(1),
908             message_->FindExtensionByCamelcaseName("barBar"));
909   EXPECT_EQ(message_->extension(2),
910             message_->FindExtensionByCamelcaseName("barBaz"));
911   EXPECT_TRUE(message_->FindExtensionByCamelcaseName("bar_foo") == NULL);
912   EXPECT_TRUE(message_->FindExtensionByCamelcaseName("BarBar") == NULL);
913   EXPECT_TRUE(message_->FindExtensionByCamelcaseName("fooFoo") == NULL);
914   EXPECT_TRUE(message_->FindExtensionByCamelcaseName("nosuchfield") == NULL);
915 
916   EXPECT_EQ(file_->extension(0),
917             file_->FindExtensionByCamelcaseName("bazFoo"));
918   EXPECT_EQ(file_->extension(1),
919             file_->FindExtensionByCamelcaseName("bazBar"));
920   EXPECT_EQ(file_->extension(2),
921             file_->FindExtensionByCamelcaseName("bazBaz"));
922   EXPECT_TRUE(file_->FindExtensionByCamelcaseName("baz_foo") == NULL);
923   EXPECT_TRUE(file_->FindExtensionByCamelcaseName("BazBar") == NULL);
924   EXPECT_TRUE(file_->FindExtensionByCamelcaseName("nosuchfield") == NULL);
925 }
926 
927 // ===================================================================
928 
929 // Test enum descriptors.
930 class EnumDescriptorTest : public testing::Test {
931  protected:
SetUp()932   virtual void SetUp() {
933     // Build descriptors for the following definitions:
934     //
935     //   // in "foo.proto"
936     //   enum TestEnum {
937     //     FOO = 1;
938     //     BAR = 2;
939     //   }
940     //
941     //   // in "bar.proto"
942     //   package corge.grault;
943     //   enum TestEnum2 {
944     //     FOO = 1;
945     //     BAZ = 3;
946     //   }
947     //
948     // TestEnum2 is primarily here to test FindValueByName and friends.
949     // All enums created from the same DescriptorPool share the same lookup
950     // table, so we need to insure that they don't interfere.
951 
952     // TestEnum
953     FileDescriptorProto foo_file;
954     foo_file.set_name("foo.proto");
955 
956     EnumDescriptorProto* enum_proto = AddEnum(&foo_file, "TestEnum");
957     AddEnumValue(enum_proto, "FOO", 1);
958     AddEnumValue(enum_proto, "BAR", 2);
959 
960     // TestEnum2
961     FileDescriptorProto bar_file;
962     bar_file.set_name("bar.proto");
963     bar_file.set_package("corge.grault");
964 
965     EnumDescriptorProto* enum2_proto = AddEnum(&bar_file, "TestEnum2");
966     AddEnumValue(enum2_proto, "FOO", 1);
967     AddEnumValue(enum2_proto, "BAZ", 3);
968 
969     // Build the descriptors and get the pointers.
970     foo_file_ = pool_.BuildFile(foo_file);
971     ASSERT_TRUE(foo_file_ != NULL);
972 
973     bar_file_ = pool_.BuildFile(bar_file);
974     ASSERT_TRUE(bar_file_ != NULL);
975 
976     ASSERT_EQ(1, foo_file_->enum_type_count());
977     enum_ = foo_file_->enum_type(0);
978 
979     ASSERT_EQ(2, enum_->value_count());
980     foo_ = enum_->value(0);
981     bar_ = enum_->value(1);
982 
983     ASSERT_EQ(1, bar_file_->enum_type_count());
984     enum2_ = bar_file_->enum_type(0);
985 
986     ASSERT_EQ(2, enum2_->value_count());
987     foo2_ = enum2_->value(0);
988     baz2_ = enum2_->value(1);
989   }
990 
991   DescriptorPool pool_;
992 
993   const FileDescriptor* foo_file_;
994   const FileDescriptor* bar_file_;
995 
996   const EnumDescriptor* enum_;
997   const EnumDescriptor* enum2_;
998 
999   const EnumValueDescriptor* foo_;
1000   const EnumValueDescriptor* bar_;
1001 
1002   const EnumValueDescriptor* foo2_;
1003   const EnumValueDescriptor* baz2_;
1004 };
1005 
TEST_F(EnumDescriptorTest,Name)1006 TEST_F(EnumDescriptorTest, Name) {
1007   EXPECT_EQ("TestEnum", enum_->name());
1008   EXPECT_EQ("TestEnum", enum_->full_name());
1009   EXPECT_EQ(foo_file_, enum_->file());
1010 
1011   EXPECT_EQ("TestEnum2", enum2_->name());
1012   EXPECT_EQ("corge.grault.TestEnum2", enum2_->full_name());
1013   EXPECT_EQ(bar_file_, enum2_->file());
1014 }
1015 
TEST_F(EnumDescriptorTest,ContainingType)1016 TEST_F(EnumDescriptorTest, ContainingType) {
1017   EXPECT_TRUE(enum_->containing_type() == NULL);
1018   EXPECT_TRUE(enum2_->containing_type() == NULL);
1019 }
1020 
TEST_F(EnumDescriptorTest,ValuesByIndex)1021 TEST_F(EnumDescriptorTest, ValuesByIndex) {
1022   ASSERT_EQ(2, enum_->value_count());
1023   EXPECT_EQ(foo_, enum_->value(0));
1024   EXPECT_EQ(bar_, enum_->value(1));
1025 }
1026 
TEST_F(EnumDescriptorTest,FindValueByName)1027 TEST_F(EnumDescriptorTest, FindValueByName) {
1028   EXPECT_EQ(foo_ , enum_ ->FindValueByName("FOO"));
1029   EXPECT_EQ(bar_ , enum_ ->FindValueByName("BAR"));
1030   EXPECT_EQ(foo2_, enum2_->FindValueByName("FOO"));
1031   EXPECT_EQ(baz2_, enum2_->FindValueByName("BAZ"));
1032 
1033   EXPECT_TRUE(enum_ ->FindValueByName("NO_SUCH_VALUE") == NULL);
1034   EXPECT_TRUE(enum_ ->FindValueByName("BAZ"          ) == NULL);
1035   EXPECT_TRUE(enum2_->FindValueByName("BAR"          ) == NULL);
1036 }
1037 
TEST_F(EnumDescriptorTest,FindValueByNumber)1038 TEST_F(EnumDescriptorTest, FindValueByNumber) {
1039   EXPECT_EQ(foo_ , enum_ ->FindValueByNumber(1));
1040   EXPECT_EQ(bar_ , enum_ ->FindValueByNumber(2));
1041   EXPECT_EQ(foo2_, enum2_->FindValueByNumber(1));
1042   EXPECT_EQ(baz2_, enum2_->FindValueByNumber(3));
1043 
1044   EXPECT_TRUE(enum_ ->FindValueByNumber(416) == NULL);
1045   EXPECT_TRUE(enum_ ->FindValueByNumber(3) == NULL);
1046   EXPECT_TRUE(enum2_->FindValueByNumber(2) == NULL);
1047 }
1048 
TEST_F(EnumDescriptorTest,ValueName)1049 TEST_F(EnumDescriptorTest, ValueName) {
1050   EXPECT_EQ("FOO", foo_->name());
1051   EXPECT_EQ("BAR", bar_->name());
1052 }
1053 
TEST_F(EnumDescriptorTest,ValueFullName)1054 TEST_F(EnumDescriptorTest, ValueFullName) {
1055   EXPECT_EQ("FOO", foo_->full_name());
1056   EXPECT_EQ("BAR", bar_->full_name());
1057   EXPECT_EQ("corge.grault.FOO", foo2_->full_name());
1058   EXPECT_EQ("corge.grault.BAZ", baz2_->full_name());
1059 }
1060 
TEST_F(EnumDescriptorTest,ValueIndex)1061 TEST_F(EnumDescriptorTest, ValueIndex) {
1062   EXPECT_EQ(0, foo_->index());
1063   EXPECT_EQ(1, bar_->index());
1064 }
1065 
TEST_F(EnumDescriptorTest,ValueNumber)1066 TEST_F(EnumDescriptorTest, ValueNumber) {
1067   EXPECT_EQ(1, foo_->number());
1068   EXPECT_EQ(2, bar_->number());
1069 }
1070 
TEST_F(EnumDescriptorTest,ValueType)1071 TEST_F(EnumDescriptorTest, ValueType) {
1072   EXPECT_EQ(enum_ , foo_ ->type());
1073   EXPECT_EQ(enum_ , bar_ ->type());
1074   EXPECT_EQ(enum2_, foo2_->type());
1075   EXPECT_EQ(enum2_, baz2_->type());
1076 }
1077 
1078 // ===================================================================
1079 
1080 // Test service descriptors.
1081 class ServiceDescriptorTest : public testing::Test {
1082  protected:
SetUp()1083   virtual void SetUp() {
1084     // Build descriptors for the following messages and service:
1085     //    // in "foo.proto"
1086     //    message FooRequest  {}
1087     //    message FooResponse {}
1088     //    message BarRequest  {}
1089     //    message BarResponse {}
1090     //    message BazRequest  {}
1091     //    message BazResponse {}
1092     //
1093     //    service TestService {
1094     //      rpc Foo(FooRequest) returns (FooResponse);
1095     //      rpc Bar(BarRequest) returns (BarResponse);
1096     //    }
1097     //
1098     //    // in "bar.proto"
1099     //    package corge.grault
1100     //    service TestService2 {
1101     //      rpc Foo(FooRequest) returns (FooResponse);
1102     //      rpc Baz(BazRequest) returns (BazResponse);
1103     //    }
1104 
1105     FileDescriptorProto foo_file;
1106     foo_file.set_name("foo.proto");
1107 
1108     AddMessage(&foo_file, "FooRequest");
1109     AddMessage(&foo_file, "FooResponse");
1110     AddMessage(&foo_file, "BarRequest");
1111     AddMessage(&foo_file, "BarResponse");
1112     AddMessage(&foo_file, "BazRequest");
1113     AddMessage(&foo_file, "BazResponse");
1114 
1115     ServiceDescriptorProto* service = AddService(&foo_file, "TestService");
1116     AddMethod(service, "Foo", "FooRequest", "FooResponse");
1117     AddMethod(service, "Bar", "BarRequest", "BarResponse");
1118 
1119     FileDescriptorProto bar_file;
1120     bar_file.set_name("bar.proto");
1121     bar_file.set_package("corge.grault");
1122     bar_file.add_dependency("foo.proto");
1123 
1124     ServiceDescriptorProto* service2 = AddService(&bar_file, "TestService2");
1125     AddMethod(service2, "Foo", "FooRequest", "FooResponse");
1126     AddMethod(service2, "Baz", "BazRequest", "BazResponse");
1127 
1128     // Build the descriptors and get the pointers.
1129     foo_file_ = pool_.BuildFile(foo_file);
1130     ASSERT_TRUE(foo_file_ != NULL);
1131 
1132     bar_file_ = pool_.BuildFile(bar_file);
1133     ASSERT_TRUE(bar_file_ != NULL);
1134 
1135     ASSERT_EQ(6, foo_file_->message_type_count());
1136     foo_request_  = foo_file_->message_type(0);
1137     foo_response_ = foo_file_->message_type(1);
1138     bar_request_  = foo_file_->message_type(2);
1139     bar_response_ = foo_file_->message_type(3);
1140     baz_request_  = foo_file_->message_type(4);
1141     baz_response_ = foo_file_->message_type(5);
1142 
1143     ASSERT_EQ(1, foo_file_->service_count());
1144     service_ = foo_file_->service(0);
1145 
1146     ASSERT_EQ(2, service_->method_count());
1147     foo_ = service_->method(0);
1148     bar_ = service_->method(1);
1149 
1150     ASSERT_EQ(1, bar_file_->service_count());
1151     service2_ = bar_file_->service(0);
1152 
1153     ASSERT_EQ(2, service2_->method_count());
1154     foo2_ = service2_->method(0);
1155     baz2_ = service2_->method(1);
1156   }
1157 
1158   DescriptorPool pool_;
1159 
1160   const FileDescriptor* foo_file_;
1161   const FileDescriptor* bar_file_;
1162 
1163   const Descriptor* foo_request_;
1164   const Descriptor* foo_response_;
1165   const Descriptor* bar_request_;
1166   const Descriptor* bar_response_;
1167   const Descriptor* baz_request_;
1168   const Descriptor* baz_response_;
1169 
1170   const ServiceDescriptor* service_;
1171   const ServiceDescriptor* service2_;
1172 
1173   const MethodDescriptor* foo_;
1174   const MethodDescriptor* bar_;
1175 
1176   const MethodDescriptor* foo2_;
1177   const MethodDescriptor* baz2_;
1178 };
1179 
TEST_F(ServiceDescriptorTest,Name)1180 TEST_F(ServiceDescriptorTest, Name) {
1181   EXPECT_EQ("TestService", service_->name());
1182   EXPECT_EQ("TestService", service_->full_name());
1183   EXPECT_EQ(foo_file_, service_->file());
1184 
1185   EXPECT_EQ("TestService2", service2_->name());
1186   EXPECT_EQ("corge.grault.TestService2", service2_->full_name());
1187   EXPECT_EQ(bar_file_, service2_->file());
1188 }
1189 
TEST_F(ServiceDescriptorTest,MethodsByIndex)1190 TEST_F(ServiceDescriptorTest, MethodsByIndex) {
1191   ASSERT_EQ(2, service_->method_count());
1192   EXPECT_EQ(foo_, service_->method(0));
1193   EXPECT_EQ(bar_, service_->method(1));
1194 }
1195 
TEST_F(ServiceDescriptorTest,FindMethodByName)1196 TEST_F(ServiceDescriptorTest, FindMethodByName) {
1197   EXPECT_EQ(foo_ , service_ ->FindMethodByName("Foo"));
1198   EXPECT_EQ(bar_ , service_ ->FindMethodByName("Bar"));
1199   EXPECT_EQ(foo2_, service2_->FindMethodByName("Foo"));
1200   EXPECT_EQ(baz2_, service2_->FindMethodByName("Baz"));
1201 
1202   EXPECT_TRUE(service_ ->FindMethodByName("NoSuchMethod") == NULL);
1203   EXPECT_TRUE(service_ ->FindMethodByName("Baz"         ) == NULL);
1204   EXPECT_TRUE(service2_->FindMethodByName("Bar"         ) == NULL);
1205 }
1206 
TEST_F(ServiceDescriptorTest,MethodName)1207 TEST_F(ServiceDescriptorTest, MethodName) {
1208   EXPECT_EQ("Foo", foo_->name());
1209   EXPECT_EQ("Bar", bar_->name());
1210 }
1211 
TEST_F(ServiceDescriptorTest,MethodFullName)1212 TEST_F(ServiceDescriptorTest, MethodFullName) {
1213   EXPECT_EQ("TestService.Foo", foo_->full_name());
1214   EXPECT_EQ("TestService.Bar", bar_->full_name());
1215   EXPECT_EQ("corge.grault.TestService2.Foo", foo2_->full_name());
1216   EXPECT_EQ("corge.grault.TestService2.Baz", baz2_->full_name());
1217 }
1218 
TEST_F(ServiceDescriptorTest,MethodIndex)1219 TEST_F(ServiceDescriptorTest, MethodIndex) {
1220   EXPECT_EQ(0, foo_->index());
1221   EXPECT_EQ(1, bar_->index());
1222 }
1223 
TEST_F(ServiceDescriptorTest,MethodParent)1224 TEST_F(ServiceDescriptorTest, MethodParent) {
1225   EXPECT_EQ(service_, foo_->service());
1226   EXPECT_EQ(service_, bar_->service());
1227 }
1228 
TEST_F(ServiceDescriptorTest,MethodInputType)1229 TEST_F(ServiceDescriptorTest, MethodInputType) {
1230   EXPECT_EQ(foo_request_, foo_->input_type());
1231   EXPECT_EQ(bar_request_, bar_->input_type());
1232 }
1233 
TEST_F(ServiceDescriptorTest,MethodOutputType)1234 TEST_F(ServiceDescriptorTest, MethodOutputType) {
1235   EXPECT_EQ(foo_response_, foo_->output_type());
1236   EXPECT_EQ(bar_response_, bar_->output_type());
1237 }
1238 
1239 // ===================================================================
1240 
1241 // Test nested types.
1242 class NestedDescriptorTest : public testing::Test {
1243  protected:
SetUp()1244   virtual void SetUp() {
1245     // Build descriptors for the following definitions:
1246     //
1247     //   // in "foo.proto"
1248     //   message TestMessage {
1249     //     message Foo {}
1250     //     message Bar {}
1251     //     enum Baz { A = 1; }
1252     //     enum Qux { B = 1; }
1253     //   }
1254     //
1255     //   // in "bar.proto"
1256     //   package corge.grault;
1257     //   message TestMessage2 {
1258     //     message Foo {}
1259     //     message Baz {}
1260     //     enum Qux  { A = 1; }
1261     //     enum Quux { C = 1; }
1262     //   }
1263     //
1264     // TestMessage2 is primarily here to test FindNestedTypeByName and friends.
1265     // All messages created from the same DescriptorPool share the same lookup
1266     // table, so we need to insure that they don't interfere.
1267     //
1268     // We add enum values to the enums in order to test searching for enum
1269     // values across a message's scope.
1270 
1271     FileDescriptorProto foo_file;
1272     foo_file.set_name("foo.proto");
1273 
1274     DescriptorProto* message = AddMessage(&foo_file, "TestMessage");
1275     AddNestedMessage(message, "Foo");
1276     AddNestedMessage(message, "Bar");
1277     EnumDescriptorProto* baz = AddNestedEnum(message, "Baz");
1278     AddEnumValue(baz, "A", 1);
1279     EnumDescriptorProto* qux = AddNestedEnum(message, "Qux");
1280     AddEnumValue(qux, "B", 1);
1281 
1282     FileDescriptorProto bar_file;
1283     bar_file.set_name("bar.proto");
1284     bar_file.set_package("corge.grault");
1285 
1286     DescriptorProto* message2 = AddMessage(&bar_file, "TestMessage2");
1287     AddNestedMessage(message2, "Foo");
1288     AddNestedMessage(message2, "Baz");
1289     EnumDescriptorProto* qux2 = AddNestedEnum(message2, "Qux");
1290     AddEnumValue(qux2, "A", 1);
1291     EnumDescriptorProto* quux2 = AddNestedEnum(message2, "Quux");
1292     AddEnumValue(quux2, "C", 1);
1293 
1294     // Build the descriptors and get the pointers.
1295     foo_file_ = pool_.BuildFile(foo_file);
1296     ASSERT_TRUE(foo_file_ != NULL);
1297 
1298     bar_file_ = pool_.BuildFile(bar_file);
1299     ASSERT_TRUE(bar_file_ != NULL);
1300 
1301     ASSERT_EQ(1, foo_file_->message_type_count());
1302     message_ = foo_file_->message_type(0);
1303 
1304     ASSERT_EQ(2, message_->nested_type_count());
1305     foo_ = message_->nested_type(0);
1306     bar_ = message_->nested_type(1);
1307 
1308     ASSERT_EQ(2, message_->enum_type_count());
1309     baz_ = message_->enum_type(0);
1310     qux_ = message_->enum_type(1);
1311 
1312     ASSERT_EQ(1, baz_->value_count());
1313     a_ = baz_->value(0);
1314     ASSERT_EQ(1, qux_->value_count());
1315     b_ = qux_->value(0);
1316 
1317     ASSERT_EQ(1, bar_file_->message_type_count());
1318     message2_ = bar_file_->message_type(0);
1319 
1320     ASSERT_EQ(2, message2_->nested_type_count());
1321     foo2_ = message2_->nested_type(0);
1322     baz2_ = message2_->nested_type(1);
1323 
1324     ASSERT_EQ(2, message2_->enum_type_count());
1325     qux2_ = message2_->enum_type(0);
1326     quux2_ = message2_->enum_type(1);
1327 
1328     ASSERT_EQ(1, qux2_->value_count());
1329     a2_ = qux2_->value(0);
1330     ASSERT_EQ(1, quux2_->value_count());
1331     c2_ = quux2_->value(0);
1332   }
1333 
1334   DescriptorPool pool_;
1335 
1336   const FileDescriptor* foo_file_;
1337   const FileDescriptor* bar_file_;
1338 
1339   const Descriptor* message_;
1340   const Descriptor* message2_;
1341 
1342   const Descriptor* foo_;
1343   const Descriptor* bar_;
1344   const EnumDescriptor* baz_;
1345   const EnumDescriptor* qux_;
1346   const EnumValueDescriptor* a_;
1347   const EnumValueDescriptor* b_;
1348 
1349   const Descriptor* foo2_;
1350   const Descriptor* baz2_;
1351   const EnumDescriptor* qux2_;
1352   const EnumDescriptor* quux2_;
1353   const EnumValueDescriptor* a2_;
1354   const EnumValueDescriptor* c2_;
1355 };
1356 
TEST_F(NestedDescriptorTest,MessageName)1357 TEST_F(NestedDescriptorTest, MessageName) {
1358   EXPECT_EQ("Foo", foo_ ->name());
1359   EXPECT_EQ("Bar", bar_ ->name());
1360   EXPECT_EQ("Foo", foo2_->name());
1361   EXPECT_EQ("Baz", baz2_->name());
1362 
1363   EXPECT_EQ("TestMessage.Foo", foo_->full_name());
1364   EXPECT_EQ("TestMessage.Bar", bar_->full_name());
1365   EXPECT_EQ("corge.grault.TestMessage2.Foo", foo2_->full_name());
1366   EXPECT_EQ("corge.grault.TestMessage2.Baz", baz2_->full_name());
1367 }
1368 
TEST_F(NestedDescriptorTest,MessageContainingType)1369 TEST_F(NestedDescriptorTest, MessageContainingType) {
1370   EXPECT_EQ(message_ , foo_ ->containing_type());
1371   EXPECT_EQ(message_ , bar_ ->containing_type());
1372   EXPECT_EQ(message2_, foo2_->containing_type());
1373   EXPECT_EQ(message2_, baz2_->containing_type());
1374 }
1375 
TEST_F(NestedDescriptorTest,NestedMessagesByIndex)1376 TEST_F(NestedDescriptorTest, NestedMessagesByIndex) {
1377   ASSERT_EQ(2, message_->nested_type_count());
1378   EXPECT_EQ(foo_, message_->nested_type(0));
1379   EXPECT_EQ(bar_, message_->nested_type(1));
1380 }
1381 
TEST_F(NestedDescriptorTest,FindFieldByNameDoesntFindNestedTypes)1382 TEST_F(NestedDescriptorTest, FindFieldByNameDoesntFindNestedTypes) {
1383   EXPECT_TRUE(message_->FindFieldByName("Foo") == NULL);
1384   EXPECT_TRUE(message_->FindFieldByName("Qux") == NULL);
1385   EXPECT_TRUE(message_->FindExtensionByName("Foo") == NULL);
1386   EXPECT_TRUE(message_->FindExtensionByName("Qux") == NULL);
1387 }
1388 
TEST_F(NestedDescriptorTest,FindNestedTypeByName)1389 TEST_F(NestedDescriptorTest, FindNestedTypeByName) {
1390   EXPECT_EQ(foo_ , message_ ->FindNestedTypeByName("Foo"));
1391   EXPECT_EQ(bar_ , message_ ->FindNestedTypeByName("Bar"));
1392   EXPECT_EQ(foo2_, message2_->FindNestedTypeByName("Foo"));
1393   EXPECT_EQ(baz2_, message2_->FindNestedTypeByName("Baz"));
1394 
1395   EXPECT_TRUE(message_ ->FindNestedTypeByName("NoSuchType") == NULL);
1396   EXPECT_TRUE(message_ ->FindNestedTypeByName("Baz"       ) == NULL);
1397   EXPECT_TRUE(message2_->FindNestedTypeByName("Bar"       ) == NULL);
1398 
1399   EXPECT_TRUE(message_->FindNestedTypeByName("Qux") == NULL);
1400 }
1401 
TEST_F(NestedDescriptorTest,EnumName)1402 TEST_F(NestedDescriptorTest, EnumName) {
1403   EXPECT_EQ("Baz" , baz_ ->name());
1404   EXPECT_EQ("Qux" , qux_ ->name());
1405   EXPECT_EQ("Qux" , qux2_->name());
1406   EXPECT_EQ("Quux", quux2_->name());
1407 
1408   EXPECT_EQ("TestMessage.Baz", baz_->full_name());
1409   EXPECT_EQ("TestMessage.Qux", qux_->full_name());
1410   EXPECT_EQ("corge.grault.TestMessage2.Qux" , qux2_ ->full_name());
1411   EXPECT_EQ("corge.grault.TestMessage2.Quux", quux2_->full_name());
1412 }
1413 
TEST_F(NestedDescriptorTest,EnumContainingType)1414 TEST_F(NestedDescriptorTest, EnumContainingType) {
1415   EXPECT_EQ(message_ , baz_  ->containing_type());
1416   EXPECT_EQ(message_ , qux_  ->containing_type());
1417   EXPECT_EQ(message2_, qux2_ ->containing_type());
1418   EXPECT_EQ(message2_, quux2_->containing_type());
1419 }
1420 
TEST_F(NestedDescriptorTest,NestedEnumsByIndex)1421 TEST_F(NestedDescriptorTest, NestedEnumsByIndex) {
1422   ASSERT_EQ(2, message_->nested_type_count());
1423   EXPECT_EQ(foo_, message_->nested_type(0));
1424   EXPECT_EQ(bar_, message_->nested_type(1));
1425 }
1426 
TEST_F(NestedDescriptorTest,FindEnumTypeByName)1427 TEST_F(NestedDescriptorTest, FindEnumTypeByName) {
1428   EXPECT_EQ(baz_  , message_ ->FindEnumTypeByName("Baz" ));
1429   EXPECT_EQ(qux_  , message_ ->FindEnumTypeByName("Qux" ));
1430   EXPECT_EQ(qux2_ , message2_->FindEnumTypeByName("Qux" ));
1431   EXPECT_EQ(quux2_, message2_->FindEnumTypeByName("Quux"));
1432 
1433   EXPECT_TRUE(message_ ->FindEnumTypeByName("NoSuchType") == NULL);
1434   EXPECT_TRUE(message_ ->FindEnumTypeByName("Quux"      ) == NULL);
1435   EXPECT_TRUE(message2_->FindEnumTypeByName("Baz"       ) == NULL);
1436 
1437   EXPECT_TRUE(message_->FindEnumTypeByName("Foo") == NULL);
1438 }
1439 
TEST_F(NestedDescriptorTest,FindEnumValueByName)1440 TEST_F(NestedDescriptorTest, FindEnumValueByName) {
1441   EXPECT_EQ(a_ , message_ ->FindEnumValueByName("A"));
1442   EXPECT_EQ(b_ , message_ ->FindEnumValueByName("B"));
1443   EXPECT_EQ(a2_, message2_->FindEnumValueByName("A"));
1444   EXPECT_EQ(c2_, message2_->FindEnumValueByName("C"));
1445 
1446   EXPECT_TRUE(message_ ->FindEnumValueByName("NO_SUCH_VALUE") == NULL);
1447   EXPECT_TRUE(message_ ->FindEnumValueByName("C"            ) == NULL);
1448   EXPECT_TRUE(message2_->FindEnumValueByName("B"            ) == NULL);
1449 
1450   EXPECT_TRUE(message_->FindEnumValueByName("Foo") == NULL);
1451 }
1452 
1453 // ===================================================================
1454 
1455 // Test extensions.
1456 class ExtensionDescriptorTest : public testing::Test {
1457  protected:
SetUp()1458   virtual void SetUp() {
1459     // Build descriptors for the following definitions:
1460     //
1461     //   enum Baz {}
1462     //   message Qux {}
1463     //
1464     //   message Foo {
1465     //     extensions 10 to 19;
1466     //     extensions 30 to 39;
1467     //   }
1468     //   extends Foo with optional int32 foo_int32 = 10;
1469     //   extends Foo with repeated TestEnum foo_enum = 19;
1470     //   message Bar {
1471     //     extends Foo with optional Qux foo_message = 30;
1472     //     // (using Qux as the group type)
1473     //     extends Foo with repeated group foo_group = 39;
1474     //   }
1475 
1476     FileDescriptorProto foo_file;
1477     foo_file.set_name("foo.proto");
1478 
1479     AddEmptyEnum(&foo_file, "Baz");
1480     AddMessage(&foo_file, "Qux");
1481 
1482     DescriptorProto* foo = AddMessage(&foo_file, "Foo");
1483     AddExtensionRange(foo, 10, 20);
1484     AddExtensionRange(foo, 30, 40);
1485 
1486     AddExtension(&foo_file, "Foo", "foo_int32", 10,
1487                  FieldDescriptorProto::LABEL_OPTIONAL,
1488                  FieldDescriptorProto::TYPE_INT32);
1489     AddExtension(&foo_file, "Foo", "foo_enum", 19,
1490                  FieldDescriptorProto::LABEL_REPEATED,
1491                  FieldDescriptorProto::TYPE_ENUM)
1492       ->set_type_name("Baz");
1493 
1494     DescriptorProto* bar = AddMessage(&foo_file, "Bar");
1495     AddNestedExtension(bar, "Foo", "foo_message", 30,
1496                        FieldDescriptorProto::LABEL_OPTIONAL,
1497                        FieldDescriptorProto::TYPE_MESSAGE)
1498       ->set_type_name("Qux");
1499     AddNestedExtension(bar, "Foo", "foo_group", 39,
1500                        FieldDescriptorProto::LABEL_REPEATED,
1501                        FieldDescriptorProto::TYPE_GROUP)
1502       ->set_type_name("Qux");
1503 
1504     // Build the descriptors and get the pointers.
1505     foo_file_ = pool_.BuildFile(foo_file);
1506     ASSERT_TRUE(foo_file_ != NULL);
1507 
1508     ASSERT_EQ(1, foo_file_->enum_type_count());
1509     baz_ = foo_file_->enum_type(0);
1510 
1511     ASSERT_EQ(3, foo_file_->message_type_count());
1512     qux_ = foo_file_->message_type(0);
1513     foo_ = foo_file_->message_type(1);
1514     bar_ = foo_file_->message_type(2);
1515   }
1516 
1517   DescriptorPool pool_;
1518 
1519   const FileDescriptor* foo_file_;
1520 
1521   const Descriptor* foo_;
1522   const Descriptor* bar_;
1523   const EnumDescriptor* baz_;
1524   const Descriptor* qux_;
1525 };
1526 
TEST_F(ExtensionDescriptorTest,ExtensionRanges)1527 TEST_F(ExtensionDescriptorTest, ExtensionRanges) {
1528   EXPECT_EQ(0, bar_->extension_range_count());
1529   ASSERT_EQ(2, foo_->extension_range_count());
1530 
1531   EXPECT_EQ(10, foo_->extension_range(0)->start);
1532   EXPECT_EQ(30, foo_->extension_range(1)->start);
1533 
1534   EXPECT_EQ(20, foo_->extension_range(0)->end);
1535   EXPECT_EQ(40, foo_->extension_range(1)->end);
1536 };
1537 
TEST_F(ExtensionDescriptorTest,Extensions)1538 TEST_F(ExtensionDescriptorTest, Extensions) {
1539   EXPECT_EQ(0, foo_->extension_count());
1540   ASSERT_EQ(2, foo_file_->extension_count());
1541   ASSERT_EQ(2, bar_->extension_count());
1542 
1543   EXPECT_TRUE(foo_file_->extension(0)->is_extension());
1544   EXPECT_TRUE(foo_file_->extension(1)->is_extension());
1545   EXPECT_TRUE(bar_->extension(0)->is_extension());
1546   EXPECT_TRUE(bar_->extension(1)->is_extension());
1547 
1548   EXPECT_EQ("foo_int32"  , foo_file_->extension(0)->name());
1549   EXPECT_EQ("foo_enum"   , foo_file_->extension(1)->name());
1550   EXPECT_EQ("foo_message", bar_->extension(0)->name());
1551   EXPECT_EQ("foo_group"  , bar_->extension(1)->name());
1552 
1553   EXPECT_EQ(10, foo_file_->extension(0)->number());
1554   EXPECT_EQ(19, foo_file_->extension(1)->number());
1555   EXPECT_EQ(30, bar_->extension(0)->number());
1556   EXPECT_EQ(39, bar_->extension(1)->number());
1557 
1558   EXPECT_EQ(FieldDescriptor::TYPE_INT32  , foo_file_->extension(0)->type());
1559   EXPECT_EQ(FieldDescriptor::TYPE_ENUM   , foo_file_->extension(1)->type());
1560   EXPECT_EQ(FieldDescriptor::TYPE_MESSAGE, bar_->extension(0)->type());
1561   EXPECT_EQ(FieldDescriptor::TYPE_GROUP  , bar_->extension(1)->type());
1562 
1563   EXPECT_EQ(baz_, foo_file_->extension(1)->enum_type());
1564   EXPECT_EQ(qux_, bar_->extension(0)->message_type());
1565   EXPECT_EQ(qux_, bar_->extension(1)->message_type());
1566 
1567   EXPECT_EQ(FieldDescriptor::LABEL_OPTIONAL, foo_file_->extension(0)->label());
1568   EXPECT_EQ(FieldDescriptor::LABEL_REPEATED, foo_file_->extension(1)->label());
1569   EXPECT_EQ(FieldDescriptor::LABEL_OPTIONAL, bar_->extension(0)->label());
1570   EXPECT_EQ(FieldDescriptor::LABEL_REPEATED, bar_->extension(1)->label());
1571 
1572   EXPECT_EQ(foo_, foo_file_->extension(0)->containing_type());
1573   EXPECT_EQ(foo_, foo_file_->extension(1)->containing_type());
1574   EXPECT_EQ(foo_, bar_->extension(0)->containing_type());
1575   EXPECT_EQ(foo_, bar_->extension(1)->containing_type());
1576 
1577   EXPECT_TRUE(foo_file_->extension(0)->extension_scope() == NULL);
1578   EXPECT_TRUE(foo_file_->extension(1)->extension_scope() == NULL);
1579   EXPECT_EQ(bar_, bar_->extension(0)->extension_scope());
1580   EXPECT_EQ(bar_, bar_->extension(1)->extension_scope());
1581 };
1582 
TEST_F(ExtensionDescriptorTest,IsExtensionNumber)1583 TEST_F(ExtensionDescriptorTest, IsExtensionNumber) {
1584   EXPECT_FALSE(foo_->IsExtensionNumber( 9));
1585   EXPECT_TRUE (foo_->IsExtensionNumber(10));
1586   EXPECT_TRUE (foo_->IsExtensionNumber(19));
1587   EXPECT_FALSE(foo_->IsExtensionNumber(20));
1588   EXPECT_FALSE(foo_->IsExtensionNumber(29));
1589   EXPECT_TRUE (foo_->IsExtensionNumber(30));
1590   EXPECT_TRUE (foo_->IsExtensionNumber(39));
1591   EXPECT_FALSE(foo_->IsExtensionNumber(40));
1592 }
1593 
TEST_F(ExtensionDescriptorTest,FindExtensionByName)1594 TEST_F(ExtensionDescriptorTest, FindExtensionByName) {
1595   // Note that FileDescriptor::FindExtensionByName() is tested by
1596   // FileDescriptorTest.
1597   ASSERT_EQ(2, bar_->extension_count());
1598 
1599   EXPECT_EQ(bar_->extension(0), bar_->FindExtensionByName("foo_message"));
1600   EXPECT_EQ(bar_->extension(1), bar_->FindExtensionByName("foo_group"  ));
1601 
1602   EXPECT_TRUE(bar_->FindExtensionByName("no_such_extension") == NULL);
1603   EXPECT_TRUE(foo_->FindExtensionByName("foo_int32") == NULL);
1604   EXPECT_TRUE(foo_->FindExtensionByName("foo_message") == NULL);
1605 }
1606 
TEST_F(ExtensionDescriptorTest,FindAllExtensions)1607 TEST_F(ExtensionDescriptorTest, FindAllExtensions) {
1608   vector<const FieldDescriptor*> extensions;
1609   pool_.FindAllExtensions(foo_, &extensions);
1610   ASSERT_EQ(4, extensions.size());
1611   EXPECT_EQ(10, extensions[0]->number());
1612   EXPECT_EQ(19, extensions[1]->number());
1613   EXPECT_EQ(30, extensions[2]->number());
1614   EXPECT_EQ(39, extensions[3]->number());
1615 }
1616 
TEST_F(ExtensionDescriptorTest,DuplicateFieldNumber)1617 TEST_F(ExtensionDescriptorTest, DuplicateFieldNumber) {
1618   DescriptorPool pool;
1619   FileDescriptorProto file_proto;
1620   // Add "google/protobuf/descriptor.proto".
1621   FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto);
1622   ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
1623   // Add "foo.proto":
1624   //   import "google/protobuf/descriptor.proto";
1625   //   extend google.protobuf.FieldOptions {
1626   //     optional int32 option1 = 1000;
1627   //   }
1628   file_proto.Clear();
1629   file_proto.set_name("foo.proto");
1630   file_proto.add_dependency("google/protobuf/descriptor.proto");
1631   AddExtension(&file_proto, "google.protobuf.FieldOptions", "option1", 1000,
1632                FieldDescriptorProto::LABEL_OPTIONAL,
1633                FieldDescriptorProto::TYPE_INT32);
1634   ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
1635   // Add "bar.proto":
1636   //   import "google/protobuf/descriptor.proto";
1637   //   extend google.protobuf.FieldOptions {
1638   //     optional int32 option2 = 1000;
1639   //   }
1640   file_proto.Clear();
1641   file_proto.set_name("bar.proto");
1642   file_proto.add_dependency("google/protobuf/descriptor.proto");
1643   AddExtension(&file_proto, "google.protobuf.FieldOptions", "option2", 1000,
1644                FieldDescriptorProto::LABEL_OPTIONAL,
1645                FieldDescriptorProto::TYPE_INT32);
1646   // Currently we only generate a warning for conflicting extension numbers.
1647   // TODO(xiaofeng): Change it to an error.
1648   ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
1649 }
1650 
1651 // ===================================================================
1652 
1653 class MiscTest : public testing::Test {
1654  protected:
1655   // Function which makes a field descriptor of the given type.
GetFieldDescriptorOfType(FieldDescriptor::Type type)1656   const FieldDescriptor* GetFieldDescriptorOfType(FieldDescriptor::Type type) {
1657     FileDescriptorProto file_proto;
1658     file_proto.set_name("foo.proto");
1659     AddEmptyEnum(&file_proto, "DummyEnum");
1660 
1661     DescriptorProto* message = AddMessage(&file_proto, "TestMessage");
1662     FieldDescriptorProto* field =
1663       AddField(message, "foo", 1, FieldDescriptorProto::LABEL_OPTIONAL,
1664                static_cast<FieldDescriptorProto::Type>(static_cast<int>(type)));
1665 
1666     if (type == FieldDescriptor::TYPE_MESSAGE ||
1667         type == FieldDescriptor::TYPE_GROUP) {
1668       field->set_type_name("TestMessage");
1669     } else if (type == FieldDescriptor::TYPE_ENUM) {
1670       field->set_type_name("DummyEnum");
1671     }
1672 
1673     // Build the descriptors and get the pointers.
1674     pool_.reset(new DescriptorPool());
1675     const FileDescriptor* file = pool_->BuildFile(file_proto);
1676 
1677     if (file != NULL &&
1678         file->message_type_count() == 1 &&
1679         file->message_type(0)->field_count() == 1) {
1680       return file->message_type(0)->field(0);
1681     } else {
1682       return NULL;
1683     }
1684   }
1685 
GetTypeNameForFieldType(FieldDescriptor::Type type)1686   const char* GetTypeNameForFieldType(FieldDescriptor::Type type) {
1687     const FieldDescriptor* field = GetFieldDescriptorOfType(type);
1688     return field != NULL ? field->type_name() : "";
1689   }
1690 
GetCppTypeForFieldType(FieldDescriptor::Type type)1691   FieldDescriptor::CppType GetCppTypeForFieldType(FieldDescriptor::Type type) {
1692     const FieldDescriptor* field = GetFieldDescriptorOfType(type);
1693     return field != NULL ? field->cpp_type() :
1694         static_cast<FieldDescriptor::CppType>(0);
1695   }
1696 
GetCppTypeNameForFieldType(FieldDescriptor::Type type)1697   const char* GetCppTypeNameForFieldType(FieldDescriptor::Type type) {
1698     const FieldDescriptor* field = GetFieldDescriptorOfType(type);
1699     return field != NULL ? field->cpp_type_name() : "";
1700   }
1701 
GetMessageDescriptorForFieldType(FieldDescriptor::Type type)1702   const Descriptor* GetMessageDescriptorForFieldType(
1703       FieldDescriptor::Type type) {
1704     const FieldDescriptor* field = GetFieldDescriptorOfType(type);
1705     return field != NULL ? field->message_type() : NULL;
1706   }
1707 
GetEnumDescriptorForFieldType(FieldDescriptor::Type type)1708   const EnumDescriptor* GetEnumDescriptorForFieldType(
1709     FieldDescriptor::Type type) {
1710     const FieldDescriptor* field = GetFieldDescriptorOfType(type);
1711     return field != NULL ? field->enum_type() : NULL;
1712   }
1713 
1714   scoped_ptr<DescriptorPool> pool_;
1715 };
1716 
TEST_F(MiscTest,TypeNames)1717 TEST_F(MiscTest, TypeNames) {
1718   // Test that correct type names are returned.
1719 
1720   typedef FieldDescriptor FD;  // avoid ugly line wrapping
1721 
1722   EXPECT_STREQ("double"  , GetTypeNameForFieldType(FD::TYPE_DOUBLE  ));
1723   EXPECT_STREQ("float"   , GetTypeNameForFieldType(FD::TYPE_FLOAT   ));
1724   EXPECT_STREQ("int64"   , GetTypeNameForFieldType(FD::TYPE_INT64   ));
1725   EXPECT_STREQ("uint64"  , GetTypeNameForFieldType(FD::TYPE_UINT64  ));
1726   EXPECT_STREQ("int32"   , GetTypeNameForFieldType(FD::TYPE_INT32   ));
1727   EXPECT_STREQ("fixed64" , GetTypeNameForFieldType(FD::TYPE_FIXED64 ));
1728   EXPECT_STREQ("fixed32" , GetTypeNameForFieldType(FD::TYPE_FIXED32 ));
1729   EXPECT_STREQ("bool"    , GetTypeNameForFieldType(FD::TYPE_BOOL    ));
1730   EXPECT_STREQ("string"  , GetTypeNameForFieldType(FD::TYPE_STRING  ));
1731   EXPECT_STREQ("group"   , GetTypeNameForFieldType(FD::TYPE_GROUP   ));
1732   EXPECT_STREQ("message" , GetTypeNameForFieldType(FD::TYPE_MESSAGE ));
1733   EXPECT_STREQ("bytes"   , GetTypeNameForFieldType(FD::TYPE_BYTES   ));
1734   EXPECT_STREQ("uint32"  , GetTypeNameForFieldType(FD::TYPE_UINT32  ));
1735   EXPECT_STREQ("enum"    , GetTypeNameForFieldType(FD::TYPE_ENUM    ));
1736   EXPECT_STREQ("sfixed32", GetTypeNameForFieldType(FD::TYPE_SFIXED32));
1737   EXPECT_STREQ("sfixed64", GetTypeNameForFieldType(FD::TYPE_SFIXED64));
1738   EXPECT_STREQ("sint32"  , GetTypeNameForFieldType(FD::TYPE_SINT32  ));
1739   EXPECT_STREQ("sint64"  , GetTypeNameForFieldType(FD::TYPE_SINT64  ));
1740 }
1741 
TEST_F(MiscTest,StaticTypeNames)1742 TEST_F(MiscTest, StaticTypeNames) {
1743   // Test that correct type names are returned.
1744 
1745   typedef FieldDescriptor FD;  // avoid ugly line wrapping
1746 
1747   EXPECT_STREQ("double"  , FD::TypeName(FD::TYPE_DOUBLE  ));
1748   EXPECT_STREQ("float"   , FD::TypeName(FD::TYPE_FLOAT   ));
1749   EXPECT_STREQ("int64"   , FD::TypeName(FD::TYPE_INT64   ));
1750   EXPECT_STREQ("uint64"  , FD::TypeName(FD::TYPE_UINT64  ));
1751   EXPECT_STREQ("int32"   , FD::TypeName(FD::TYPE_INT32   ));
1752   EXPECT_STREQ("fixed64" , FD::TypeName(FD::TYPE_FIXED64 ));
1753   EXPECT_STREQ("fixed32" , FD::TypeName(FD::TYPE_FIXED32 ));
1754   EXPECT_STREQ("bool"    , FD::TypeName(FD::TYPE_BOOL    ));
1755   EXPECT_STREQ("string"  , FD::TypeName(FD::TYPE_STRING  ));
1756   EXPECT_STREQ("group"   , FD::TypeName(FD::TYPE_GROUP   ));
1757   EXPECT_STREQ("message" , FD::TypeName(FD::TYPE_MESSAGE ));
1758   EXPECT_STREQ("bytes"   , FD::TypeName(FD::TYPE_BYTES   ));
1759   EXPECT_STREQ("uint32"  , FD::TypeName(FD::TYPE_UINT32  ));
1760   EXPECT_STREQ("enum"    , FD::TypeName(FD::TYPE_ENUM    ));
1761   EXPECT_STREQ("sfixed32", FD::TypeName(FD::TYPE_SFIXED32));
1762   EXPECT_STREQ("sfixed64", FD::TypeName(FD::TYPE_SFIXED64));
1763   EXPECT_STREQ("sint32"  , FD::TypeName(FD::TYPE_SINT32  ));
1764   EXPECT_STREQ("sint64"  , FD::TypeName(FD::TYPE_SINT64  ));
1765 }
1766 
TEST_F(MiscTest,CppTypes)1767 TEST_F(MiscTest, CppTypes) {
1768   // Test that CPP types are assigned correctly.
1769 
1770   typedef FieldDescriptor FD;  // avoid ugly line wrapping
1771 
1772   EXPECT_EQ(FD::CPPTYPE_DOUBLE , GetCppTypeForFieldType(FD::TYPE_DOUBLE  ));
1773   EXPECT_EQ(FD::CPPTYPE_FLOAT  , GetCppTypeForFieldType(FD::TYPE_FLOAT   ));
1774   EXPECT_EQ(FD::CPPTYPE_INT64  , GetCppTypeForFieldType(FD::TYPE_INT64   ));
1775   EXPECT_EQ(FD::CPPTYPE_UINT64 , GetCppTypeForFieldType(FD::TYPE_UINT64  ));
1776   EXPECT_EQ(FD::CPPTYPE_INT32  , GetCppTypeForFieldType(FD::TYPE_INT32   ));
1777   EXPECT_EQ(FD::CPPTYPE_UINT64 , GetCppTypeForFieldType(FD::TYPE_FIXED64 ));
1778   EXPECT_EQ(FD::CPPTYPE_UINT32 , GetCppTypeForFieldType(FD::TYPE_FIXED32 ));
1779   EXPECT_EQ(FD::CPPTYPE_BOOL   , GetCppTypeForFieldType(FD::TYPE_BOOL    ));
1780   EXPECT_EQ(FD::CPPTYPE_STRING , GetCppTypeForFieldType(FD::TYPE_STRING  ));
1781   EXPECT_EQ(FD::CPPTYPE_MESSAGE, GetCppTypeForFieldType(FD::TYPE_GROUP   ));
1782   EXPECT_EQ(FD::CPPTYPE_MESSAGE, GetCppTypeForFieldType(FD::TYPE_MESSAGE ));
1783   EXPECT_EQ(FD::CPPTYPE_STRING , GetCppTypeForFieldType(FD::TYPE_BYTES   ));
1784   EXPECT_EQ(FD::CPPTYPE_UINT32 , GetCppTypeForFieldType(FD::TYPE_UINT32  ));
1785   EXPECT_EQ(FD::CPPTYPE_ENUM   , GetCppTypeForFieldType(FD::TYPE_ENUM    ));
1786   EXPECT_EQ(FD::CPPTYPE_INT32  , GetCppTypeForFieldType(FD::TYPE_SFIXED32));
1787   EXPECT_EQ(FD::CPPTYPE_INT64  , GetCppTypeForFieldType(FD::TYPE_SFIXED64));
1788   EXPECT_EQ(FD::CPPTYPE_INT32  , GetCppTypeForFieldType(FD::TYPE_SINT32  ));
1789   EXPECT_EQ(FD::CPPTYPE_INT64  , GetCppTypeForFieldType(FD::TYPE_SINT64  ));
1790 }
1791 
TEST_F(MiscTest,CppTypeNames)1792 TEST_F(MiscTest, CppTypeNames) {
1793   // Test that correct CPP type names are returned.
1794 
1795   typedef FieldDescriptor FD;  // avoid ugly line wrapping
1796 
1797   EXPECT_STREQ("double" , GetCppTypeNameForFieldType(FD::TYPE_DOUBLE  ));
1798   EXPECT_STREQ("float"  , GetCppTypeNameForFieldType(FD::TYPE_FLOAT   ));
1799   EXPECT_STREQ("int64"  , GetCppTypeNameForFieldType(FD::TYPE_INT64   ));
1800   EXPECT_STREQ("uint64" , GetCppTypeNameForFieldType(FD::TYPE_UINT64  ));
1801   EXPECT_STREQ("int32"  , GetCppTypeNameForFieldType(FD::TYPE_INT32   ));
1802   EXPECT_STREQ("uint64" , GetCppTypeNameForFieldType(FD::TYPE_FIXED64 ));
1803   EXPECT_STREQ("uint32" , GetCppTypeNameForFieldType(FD::TYPE_FIXED32 ));
1804   EXPECT_STREQ("bool"   , GetCppTypeNameForFieldType(FD::TYPE_BOOL    ));
1805   EXPECT_STREQ("string" , GetCppTypeNameForFieldType(FD::TYPE_STRING  ));
1806   EXPECT_STREQ("message", GetCppTypeNameForFieldType(FD::TYPE_GROUP   ));
1807   EXPECT_STREQ("message", GetCppTypeNameForFieldType(FD::TYPE_MESSAGE ));
1808   EXPECT_STREQ("string" , GetCppTypeNameForFieldType(FD::TYPE_BYTES   ));
1809   EXPECT_STREQ("uint32" , GetCppTypeNameForFieldType(FD::TYPE_UINT32  ));
1810   EXPECT_STREQ("enum"   , GetCppTypeNameForFieldType(FD::TYPE_ENUM    ));
1811   EXPECT_STREQ("int32"  , GetCppTypeNameForFieldType(FD::TYPE_SFIXED32));
1812   EXPECT_STREQ("int64"  , GetCppTypeNameForFieldType(FD::TYPE_SFIXED64));
1813   EXPECT_STREQ("int32"  , GetCppTypeNameForFieldType(FD::TYPE_SINT32  ));
1814   EXPECT_STREQ("int64"  , GetCppTypeNameForFieldType(FD::TYPE_SINT64  ));
1815 }
1816 
TEST_F(MiscTest,StaticCppTypeNames)1817 TEST_F(MiscTest, StaticCppTypeNames) {
1818   // Test that correct CPP type names are returned.
1819 
1820   typedef FieldDescriptor FD;  // avoid ugly line wrapping
1821 
1822   EXPECT_STREQ("int32"  , FD::CppTypeName(FD::CPPTYPE_INT32  ));
1823   EXPECT_STREQ("int64"  , FD::CppTypeName(FD::CPPTYPE_INT64  ));
1824   EXPECT_STREQ("uint32" , FD::CppTypeName(FD::CPPTYPE_UINT32 ));
1825   EXPECT_STREQ("uint64" , FD::CppTypeName(FD::CPPTYPE_UINT64 ));
1826   EXPECT_STREQ("double" , FD::CppTypeName(FD::CPPTYPE_DOUBLE ));
1827   EXPECT_STREQ("float"  , FD::CppTypeName(FD::CPPTYPE_FLOAT  ));
1828   EXPECT_STREQ("bool"   , FD::CppTypeName(FD::CPPTYPE_BOOL   ));
1829   EXPECT_STREQ("enum"   , FD::CppTypeName(FD::CPPTYPE_ENUM   ));
1830   EXPECT_STREQ("string" , FD::CppTypeName(FD::CPPTYPE_STRING ));
1831   EXPECT_STREQ("message", FD::CppTypeName(FD::CPPTYPE_MESSAGE));
1832 }
1833 
TEST_F(MiscTest,MessageType)1834 TEST_F(MiscTest, MessageType) {
1835   // Test that message_type() is NULL for non-aggregate fields
1836 
1837   typedef FieldDescriptor FD;  // avoid ugly line wrapping
1838 
1839   EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_DOUBLE  ));
1840   EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_FLOAT   ));
1841   EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_INT64   ));
1842   EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_UINT64  ));
1843   EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_INT32   ));
1844   EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_FIXED64 ));
1845   EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_FIXED32 ));
1846   EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_BOOL    ));
1847   EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_STRING  ));
1848   EXPECT_TRUE(NULL != GetMessageDescriptorForFieldType(FD::TYPE_GROUP   ));
1849   EXPECT_TRUE(NULL != GetMessageDescriptorForFieldType(FD::TYPE_MESSAGE ));
1850   EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_BYTES   ));
1851   EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_UINT32  ));
1852   EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_ENUM    ));
1853   EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_SFIXED32));
1854   EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_SFIXED64));
1855   EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_SINT32  ));
1856   EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_SINT64  ));
1857 }
1858 
TEST_F(MiscTest,EnumType)1859 TEST_F(MiscTest, EnumType) {
1860   // Test that enum_type() is NULL for non-enum fields
1861 
1862   typedef FieldDescriptor FD;  // avoid ugly line wrapping
1863 
1864   EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_DOUBLE  ));
1865   EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_FLOAT   ));
1866   EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_INT64   ));
1867   EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_UINT64  ));
1868   EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_INT32   ));
1869   EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_FIXED64 ));
1870   EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_FIXED32 ));
1871   EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_BOOL    ));
1872   EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_STRING  ));
1873   EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_GROUP   ));
1874   EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_MESSAGE ));
1875   EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_BYTES   ));
1876   EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_UINT32  ));
1877   EXPECT_TRUE(NULL != GetEnumDescriptorForFieldType(FD::TYPE_ENUM    ));
1878   EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_SFIXED32));
1879   EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_SFIXED64));
1880   EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_SINT32  ));
1881   EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_SINT64  ));
1882 }
1883 
1884 
TEST_F(MiscTest,DefaultValues)1885 TEST_F(MiscTest, DefaultValues) {
1886   // Test that setting default values works.
1887   FileDescriptorProto file_proto;
1888   file_proto.set_name("foo.proto");
1889 
1890   EnumDescriptorProto* enum_type_proto = AddEnum(&file_proto, "DummyEnum");
1891   AddEnumValue(enum_type_proto, "A", 1);
1892   AddEnumValue(enum_type_proto, "B", 2);
1893 
1894   DescriptorProto* message_proto = AddMessage(&file_proto, "TestMessage");
1895 
1896   typedef FieldDescriptorProto FD;  // avoid ugly line wrapping
1897   const FD::Label label = FD::LABEL_OPTIONAL;
1898 
1899   // Create fields of every CPP type with default values.
1900   AddField(message_proto, "int32" , 1, label, FD::TYPE_INT32 )
1901     ->set_default_value("-1");
1902   AddField(message_proto, "int64" , 2, label, FD::TYPE_INT64 )
1903     ->set_default_value("-1000000000000");
1904   AddField(message_proto, "uint32", 3, label, FD::TYPE_UINT32)
1905     ->set_default_value("42");
1906   AddField(message_proto, "uint64", 4, label, FD::TYPE_UINT64)
1907     ->set_default_value("2000000000000");
1908   AddField(message_proto, "float" , 5, label, FD::TYPE_FLOAT )
1909     ->set_default_value("4.5");
1910   AddField(message_proto, "double", 6, label, FD::TYPE_DOUBLE)
1911     ->set_default_value("10e100");
1912   AddField(message_proto, "bool"  , 7, label, FD::TYPE_BOOL  )
1913     ->set_default_value("true");
1914   AddField(message_proto, "string", 8, label, FD::TYPE_STRING)
1915     ->set_default_value("hello");
1916   AddField(message_proto, "data"  , 9, label, FD::TYPE_BYTES )
1917     ->set_default_value("\\001\\002\\003");
1918 
1919   FieldDescriptorProto* enum_field =
1920     AddField(message_proto, "enum", 10, label, FD::TYPE_ENUM);
1921   enum_field->set_type_name("DummyEnum");
1922   enum_field->set_default_value("B");
1923 
1924   // Strings are allowed to have empty defaults.  (At one point, due to
1925   // a bug, empty defaults for strings were rejected.  Oops.)
1926   AddField(message_proto, "empty_string", 11, label, FD::TYPE_STRING)
1927     ->set_default_value("");
1928 
1929   // Add a second set of fields with implicit defalut values.
1930   AddField(message_proto, "implicit_int32" , 21, label, FD::TYPE_INT32 );
1931   AddField(message_proto, "implicit_int64" , 22, label, FD::TYPE_INT64 );
1932   AddField(message_proto, "implicit_uint32", 23, label, FD::TYPE_UINT32);
1933   AddField(message_proto, "implicit_uint64", 24, label, FD::TYPE_UINT64);
1934   AddField(message_proto, "implicit_float" , 25, label, FD::TYPE_FLOAT );
1935   AddField(message_proto, "implicit_double", 26, label, FD::TYPE_DOUBLE);
1936   AddField(message_proto, "implicit_bool"  , 27, label, FD::TYPE_BOOL  );
1937   AddField(message_proto, "implicit_string", 28, label, FD::TYPE_STRING);
1938   AddField(message_proto, "implicit_data"  , 29, label, FD::TYPE_BYTES );
1939   AddField(message_proto, "implicit_enum"  , 30, label, FD::TYPE_ENUM)
1940     ->set_type_name("DummyEnum");
1941 
1942   // Build it.
1943   DescriptorPool pool;
1944   const FileDescriptor* file = pool.BuildFile(file_proto);
1945   ASSERT_TRUE(file != NULL);
1946 
1947   ASSERT_EQ(1, file->enum_type_count());
1948   const EnumDescriptor* enum_type = file->enum_type(0);
1949   ASSERT_EQ(2, enum_type->value_count());
1950   const EnumValueDescriptor* enum_value_a = enum_type->value(0);
1951   const EnumValueDescriptor* enum_value_b = enum_type->value(1);
1952 
1953   ASSERT_EQ(1, file->message_type_count());
1954   const Descriptor* message = file->message_type(0);
1955 
1956   ASSERT_EQ(21, message->field_count());
1957 
1958   // Check the default values.
1959   ASSERT_TRUE(message->field(0)->has_default_value());
1960   ASSERT_TRUE(message->field(1)->has_default_value());
1961   ASSERT_TRUE(message->field(2)->has_default_value());
1962   ASSERT_TRUE(message->field(3)->has_default_value());
1963   ASSERT_TRUE(message->field(4)->has_default_value());
1964   ASSERT_TRUE(message->field(5)->has_default_value());
1965   ASSERT_TRUE(message->field(6)->has_default_value());
1966   ASSERT_TRUE(message->field(7)->has_default_value());
1967   ASSERT_TRUE(message->field(8)->has_default_value());
1968   ASSERT_TRUE(message->field(9)->has_default_value());
1969   ASSERT_TRUE(message->field(10)->has_default_value());
1970 
1971   EXPECT_EQ(-1              , message->field(0)->default_value_int32 ());
1972   EXPECT_EQ(-GOOGLE_ULONGLONG(1000000000000),
1973             message->field(1)->default_value_int64 ());
1974   EXPECT_EQ(42              , message->field(2)->default_value_uint32());
1975   EXPECT_EQ(GOOGLE_ULONGLONG(2000000000000),
1976             message->field(3)->default_value_uint64());
1977   EXPECT_EQ(4.5             , message->field(4)->default_value_float ());
1978   EXPECT_EQ(10e100          , message->field(5)->default_value_double());
1979   EXPECT_TRUE(                message->field(6)->default_value_bool  ());
1980   EXPECT_EQ("hello"         , message->field(7)->default_value_string());
1981   EXPECT_EQ("\001\002\003"  , message->field(8)->default_value_string());
1982   EXPECT_EQ(enum_value_b    , message->field(9)->default_value_enum  ());
1983   EXPECT_EQ(""              , message->field(10)->default_value_string());
1984 
1985   ASSERT_FALSE(message->field(11)->has_default_value());
1986   ASSERT_FALSE(message->field(12)->has_default_value());
1987   ASSERT_FALSE(message->field(13)->has_default_value());
1988   ASSERT_FALSE(message->field(14)->has_default_value());
1989   ASSERT_FALSE(message->field(15)->has_default_value());
1990   ASSERT_FALSE(message->field(16)->has_default_value());
1991   ASSERT_FALSE(message->field(17)->has_default_value());
1992   ASSERT_FALSE(message->field(18)->has_default_value());
1993   ASSERT_FALSE(message->field(19)->has_default_value());
1994   ASSERT_FALSE(message->field(20)->has_default_value());
1995 
1996   EXPECT_EQ(0    , message->field(11)->default_value_int32 ());
1997   EXPECT_EQ(0    , message->field(12)->default_value_int64 ());
1998   EXPECT_EQ(0    , message->field(13)->default_value_uint32());
1999   EXPECT_EQ(0    , message->field(14)->default_value_uint64());
2000   EXPECT_EQ(0.0f , message->field(15)->default_value_float ());
2001   EXPECT_EQ(0.0  , message->field(16)->default_value_double());
2002   EXPECT_FALSE(    message->field(17)->default_value_bool  ());
2003   EXPECT_EQ(""   , message->field(18)->default_value_string());
2004   EXPECT_EQ(""   , message->field(19)->default_value_string());
2005   EXPECT_EQ(enum_value_a, message->field(20)->default_value_enum());
2006 }
2007 
TEST_F(MiscTest,FieldOptions)2008 TEST_F(MiscTest, FieldOptions) {
2009   // Try setting field options.
2010 
2011   FileDescriptorProto file_proto;
2012   file_proto.set_name("foo.proto");
2013 
2014   DescriptorProto* message_proto = AddMessage(&file_proto, "TestMessage");
2015   AddField(message_proto, "foo", 1,
2016            FieldDescriptorProto::LABEL_OPTIONAL,
2017            FieldDescriptorProto::TYPE_INT32);
2018   FieldDescriptorProto* bar_proto =
2019     AddField(message_proto, "bar", 2,
2020              FieldDescriptorProto::LABEL_OPTIONAL,
2021              FieldDescriptorProto::TYPE_INT32);
2022 
2023   FieldOptions* options = bar_proto->mutable_options();
2024   options->set_ctype(FieldOptions::CORD);
2025 
2026   // Build the descriptors and get the pointers.
2027   DescriptorPool pool;
2028   const FileDescriptor* file = pool.BuildFile(file_proto);
2029   ASSERT_TRUE(file != NULL);
2030 
2031   ASSERT_EQ(1, file->message_type_count());
2032   const Descriptor* message = file->message_type(0);
2033 
2034   ASSERT_EQ(2, message->field_count());
2035   const FieldDescriptor* foo = message->field(0);
2036   const FieldDescriptor* bar = message->field(1);
2037 
2038   // "foo" had no options set, so it should return the default options.
2039   EXPECT_EQ(&FieldOptions::default_instance(), &foo->options());
2040 
2041   // "bar" had options set.
2042   EXPECT_NE(&FieldOptions::default_instance(), options);
2043   EXPECT_TRUE(bar->options().has_ctype());
2044   EXPECT_EQ(FieldOptions::CORD, bar->options().ctype());
2045 }
2046 
2047 // ===================================================================
2048 enum DescriptorPoolMode {
2049   NO_DATABASE,
2050   FALLBACK_DATABASE
2051 };
2052 
2053 class AllowUnknownDependenciesTest
2054     : public testing::TestWithParam<DescriptorPoolMode> {
2055  protected:
mode()2056   DescriptorPoolMode mode() {
2057     return GetParam();
2058    }
2059 
SetUp()2060   virtual void SetUp() {
2061     FileDescriptorProto foo_proto, bar_proto;
2062 
2063     switch (mode()) {
2064       case NO_DATABASE:
2065         pool_.reset(new DescriptorPool);
2066         break;
2067       case FALLBACK_DATABASE:
2068         pool_.reset(new DescriptorPool(&db_));
2069         break;
2070     }
2071 
2072     pool_->AllowUnknownDependencies();
2073 
2074     ASSERT_TRUE(TextFormat::ParseFromString(
2075       "name: 'foo.proto'"
2076       "dependency: 'bar.proto'"
2077       "dependency: 'baz.proto'"
2078       "message_type {"
2079       "  name: 'Foo'"
2080       "  field { name:'bar' number:1 label:LABEL_OPTIONAL type_name:'Bar' }"
2081       "  field { name:'baz' number:2 label:LABEL_OPTIONAL type_name:'Baz' }"
2082       "  field { name:'qux' number:3 label:LABEL_OPTIONAL"
2083       "    type_name: '.corge.Qux'"
2084       "    type: TYPE_ENUM"
2085       "    options {"
2086       "      uninterpreted_option {"
2087       "        name {"
2088       "          name_part: 'grault'"
2089       "          is_extension: true"
2090       "        }"
2091       "        positive_int_value: 1234"
2092       "      }"
2093       "    }"
2094       "  }"
2095       "}",
2096       &foo_proto));
2097     ASSERT_TRUE(TextFormat::ParseFromString(
2098       "name: 'bar.proto'"
2099       "message_type { name: 'Bar' }",
2100       &bar_proto));
2101 
2102     // Collect pointers to stuff.
2103     bar_file_ = BuildFile(bar_proto);
2104     ASSERT_TRUE(bar_file_ != NULL);
2105 
2106     ASSERT_EQ(1, bar_file_->message_type_count());
2107     bar_type_ = bar_file_->message_type(0);
2108 
2109     foo_file_ = BuildFile(foo_proto);
2110     ASSERT_TRUE(foo_file_ != NULL);
2111 
2112     ASSERT_EQ(1, foo_file_->message_type_count());
2113     foo_type_ = foo_file_->message_type(0);
2114 
2115     ASSERT_EQ(3, foo_type_->field_count());
2116     bar_field_ = foo_type_->field(0);
2117     baz_field_ = foo_type_->field(1);
2118     qux_field_ = foo_type_->field(2);
2119   }
2120 
BuildFile(const FileDescriptorProto & proto)2121   const FileDescriptor* BuildFile(const FileDescriptorProto& proto) {
2122     switch (mode()) {
2123       case NO_DATABASE:
2124         return pool_->BuildFile(proto);
2125         break;
2126       case FALLBACK_DATABASE: {
2127         EXPECT_TRUE(db_.Add(proto));
2128         return pool_->FindFileByName(proto.name());
2129       }
2130     }
2131     GOOGLE_LOG(FATAL) << "Can't get here.";
2132     return NULL;
2133   }
2134 
2135   const FileDescriptor* bar_file_;
2136   const Descriptor* bar_type_;
2137   const FileDescriptor* foo_file_;
2138   const Descriptor* foo_type_;
2139   const FieldDescriptor* bar_field_;
2140   const FieldDescriptor* baz_field_;
2141   const FieldDescriptor* qux_field_;
2142 
2143   SimpleDescriptorDatabase db_;        // used if in FALLBACK_DATABASE mode.
2144   scoped_ptr<DescriptorPool> pool_;
2145 };
2146 
TEST_P(AllowUnknownDependenciesTest,PlaceholderFile)2147 TEST_P(AllowUnknownDependenciesTest, PlaceholderFile) {
2148   ASSERT_EQ(2, foo_file_->dependency_count());
2149   EXPECT_EQ(bar_file_, foo_file_->dependency(0));
2150   EXPECT_FALSE(bar_file_->is_placeholder());
2151 
2152   const FileDescriptor* baz_file = foo_file_->dependency(1);
2153   EXPECT_EQ("baz.proto", baz_file->name());
2154   EXPECT_EQ(0, baz_file->message_type_count());
2155   EXPECT_TRUE(baz_file->is_placeholder());
2156 
2157   // Placeholder files should not be findable.
2158   EXPECT_EQ(bar_file_, pool_->FindFileByName(bar_file_->name()));
2159   EXPECT_TRUE(pool_->FindFileByName(baz_file->name()) == NULL);
2160 }
2161 
TEST_P(AllowUnknownDependenciesTest,PlaceholderTypes)2162 TEST_P(AllowUnknownDependenciesTest, PlaceholderTypes) {
2163   ASSERT_EQ(FieldDescriptor::TYPE_MESSAGE, bar_field_->type());
2164   EXPECT_EQ(bar_type_, bar_field_->message_type());
2165   EXPECT_FALSE(bar_type_->is_placeholder());
2166 
2167   ASSERT_EQ(FieldDescriptor::TYPE_MESSAGE, baz_field_->type());
2168   const Descriptor* baz_type = baz_field_->message_type();
2169   EXPECT_EQ("Baz", baz_type->name());
2170   EXPECT_EQ("Baz", baz_type->full_name());
2171   EXPECT_EQ(0, baz_type->extension_range_count());
2172   EXPECT_TRUE(baz_type->is_placeholder());
2173 
2174   ASSERT_EQ(FieldDescriptor::TYPE_ENUM, qux_field_->type());
2175   const EnumDescriptor* qux_type = qux_field_->enum_type();
2176   EXPECT_EQ("Qux", qux_type->name());
2177   EXPECT_EQ("corge.Qux", qux_type->full_name());
2178   EXPECT_TRUE(qux_type->is_placeholder());
2179 
2180   // Placeholder types should not be findable.
2181   EXPECT_EQ(bar_type_, pool_->FindMessageTypeByName(bar_type_->full_name()));
2182   EXPECT_TRUE(pool_->FindMessageTypeByName(baz_type->full_name()) == NULL);
2183   EXPECT_TRUE(pool_->FindEnumTypeByName(qux_type->full_name()) == NULL);
2184 }
2185 
TEST_P(AllowUnknownDependenciesTest,CopyTo)2186 TEST_P(AllowUnknownDependenciesTest, CopyTo) {
2187   // FieldDescriptor::CopyTo() should write non-fully-qualified type names
2188   // for placeholder types which were not originally fully-qualified.
2189   FieldDescriptorProto proto;
2190 
2191   // Bar is not a placeholder, so it is fully-qualified.
2192   bar_field_->CopyTo(&proto);
2193   EXPECT_EQ(".Bar", proto.type_name());
2194   EXPECT_EQ(FieldDescriptorProto::TYPE_MESSAGE, proto.type());
2195 
2196   // Baz is an unqualified placeholder.
2197   proto.Clear();
2198   baz_field_->CopyTo(&proto);
2199   EXPECT_EQ("Baz", proto.type_name());
2200   EXPECT_FALSE(proto.has_type());
2201 
2202   // Qux is a fully-qualified placeholder.
2203   proto.Clear();
2204   qux_field_->CopyTo(&proto);
2205   EXPECT_EQ(".corge.Qux", proto.type_name());
2206   EXPECT_EQ(FieldDescriptorProto::TYPE_ENUM, proto.type());
2207 }
2208 
TEST_P(AllowUnknownDependenciesTest,CustomOptions)2209 TEST_P(AllowUnknownDependenciesTest, CustomOptions) {
2210   // Qux should still have the uninterpreted option attached.
2211   ASSERT_EQ(1, qux_field_->options().uninterpreted_option_size());
2212   const UninterpretedOption& option =
2213     qux_field_->options().uninterpreted_option(0);
2214   ASSERT_EQ(1, option.name_size());
2215   EXPECT_EQ("grault", option.name(0).name_part());
2216 }
2217 
TEST_P(AllowUnknownDependenciesTest,UnknownExtendee)2218 TEST_P(AllowUnknownDependenciesTest, UnknownExtendee) {
2219   // Test that we can extend an unknown type.  This is slightly tricky because
2220   // it means that the placeholder type must have an extension range.
2221 
2222   FileDescriptorProto extension_proto;
2223 
2224   ASSERT_TRUE(TextFormat::ParseFromString(
2225     "name: 'extension.proto'"
2226     "extension { extendee: 'UnknownType' name:'some_extension' number:123"
2227     "            label:LABEL_OPTIONAL type:TYPE_INT32 }",
2228     &extension_proto));
2229   const FileDescriptor* file = BuildFile(extension_proto);
2230 
2231   ASSERT_TRUE(file != NULL);
2232 
2233   ASSERT_EQ(1, file->extension_count());
2234   const Descriptor* extendee = file->extension(0)->containing_type();
2235   EXPECT_EQ("UnknownType", extendee->name());
2236   EXPECT_TRUE(extendee->is_placeholder());
2237   ASSERT_EQ(1, extendee->extension_range_count());
2238   EXPECT_EQ(1, extendee->extension_range(0)->start);
2239   EXPECT_EQ(FieldDescriptor::kMaxNumber + 1, extendee->extension_range(0)->end);
2240 }
2241 
TEST_P(AllowUnknownDependenciesTest,CustomOption)2242 TEST_P(AllowUnknownDependenciesTest, CustomOption) {
2243   // Test that we can use a custom option without having parsed
2244   // descriptor.proto.
2245 
2246   FileDescriptorProto option_proto;
2247 
2248   ASSERT_TRUE(TextFormat::ParseFromString(
2249     "name: \"unknown_custom_options.proto\" "
2250     "dependency: \"google/protobuf/descriptor.proto\" "
2251     "extension { "
2252     "  extendee: \"google.protobuf.FileOptions\" "
2253     "  name: \"some_option\" "
2254     "  number: 123456 "
2255     "  label: LABEL_OPTIONAL "
2256     "  type: TYPE_INT32 "
2257     "} "
2258     "options { "
2259     "  uninterpreted_option { "
2260     "    name { "
2261     "      name_part: \"some_option\" "
2262     "      is_extension: true "
2263     "    } "
2264     "    positive_int_value: 1234 "
2265     "  } "
2266     "  uninterpreted_option { "
2267     "    name { "
2268     "      name_part: \"unknown_option\" "
2269     "      is_extension: true "
2270     "    } "
2271     "    positive_int_value: 1234 "
2272     "  } "
2273     "  uninterpreted_option { "
2274     "    name { "
2275     "      name_part: \"optimize_for\" "
2276     "      is_extension: false "
2277     "    } "
2278     "    identifier_value: \"SPEED\" "
2279     "  } "
2280     "}",
2281     &option_proto));
2282 
2283   const FileDescriptor* file = BuildFile(option_proto);
2284   ASSERT_TRUE(file != NULL);
2285 
2286   // Verify that no extension options were set, but they were left as
2287   // uninterpreted_options.
2288   vector<const FieldDescriptor*> fields;
2289   file->options().GetReflection()->ListFields(file->options(), &fields);
2290   ASSERT_EQ(2, fields.size());
2291   EXPECT_TRUE(file->options().has_optimize_for());
2292   EXPECT_EQ(2, file->options().uninterpreted_option_size());
2293 }
2294 
TEST_P(AllowUnknownDependenciesTest,UndeclaredDependencyTriggersBuildOfDependency)2295 TEST_P(AllowUnknownDependenciesTest,
2296        UndeclaredDependencyTriggersBuildOfDependency) {
2297   // Crazy case: suppose foo.proto refers to a symbol without declaring the
2298   // dependency that finds it. In the event that the pool is backed by a
2299   // DescriptorDatabase, the pool will attempt to find the symbol in the
2300   // database. If successful, it will build the undeclared dependency to verify
2301   // that the file does indeed contain the symbol. If that file fails to build,
2302   // then its descriptors must be rolled back. However, we still want foo.proto
2303   // to build successfully, since we are allowing unknown dependencies.
2304 
2305   FileDescriptorProto undeclared_dep_proto;
2306   // We make this file fail to build by giving it two fields with tag 1.
2307   ASSERT_TRUE(TextFormat::ParseFromString(
2308     "name: \"invalid_file_as_undeclared_dep.proto\" "
2309     "package: \"undeclared\" "
2310     "message_type: {  "
2311     "  name: \"Quux\"  "
2312     "  field { "
2313     "    name:'qux' number:1 label:LABEL_OPTIONAL type: TYPE_INT32 "
2314     "  }"
2315     "  field { "
2316     "    name:'quux' number:1 label:LABEL_OPTIONAL type: TYPE_INT64 "
2317     "  }"
2318     "}",
2319     &undeclared_dep_proto));
2320   // We can't use the BuildFile() helper because we don't actually want to build
2321   // it into the descriptor pool in the fallback database case: it just needs to
2322   // be sitting in the database so that it gets built during the building of
2323   // test.proto below.
2324   switch (mode()) {
2325     case NO_DATABASE: {
2326       ASSERT_TRUE(pool_->BuildFile(undeclared_dep_proto) == NULL);
2327       break;
2328     }
2329     case FALLBACK_DATABASE: {
2330       ASSERT_TRUE(db_.Add(undeclared_dep_proto));
2331     }
2332   }
2333 
2334   FileDescriptorProto test_proto;
2335   ASSERT_TRUE(TextFormat::ParseFromString(
2336     "name: \"test.proto\" "
2337     "message_type: { "
2338     "  name: \"Corge\" "
2339     "  field { "
2340     "    name:'quux' number:1 label: LABEL_OPTIONAL "
2341     "    type_name:'undeclared.Quux' type: TYPE_MESSAGE "
2342     "  }"
2343     "}",
2344     &test_proto));
2345 
2346   const FileDescriptor* file = BuildFile(test_proto);
2347   ASSERT_TRUE(file != NULL);
2348   GOOGLE_LOG(INFO) << file->DebugString();
2349 
2350   EXPECT_EQ(0, file->dependency_count());
2351   ASSERT_EQ(1, file->message_type_count());
2352   const Descriptor* corge_desc = file->message_type(0);
2353   ASSERT_EQ("Corge", corge_desc->name());
2354   ASSERT_EQ(1, corge_desc->field_count());
2355   EXPECT_FALSE(corge_desc->is_placeholder());
2356 
2357   const FieldDescriptor* quux_field = corge_desc->field(0);
2358   ASSERT_EQ(FieldDescriptor::TYPE_MESSAGE, quux_field->type());
2359   ASSERT_EQ("Quux", quux_field->message_type()->name());
2360   ASSERT_EQ("undeclared.Quux", quux_field->message_type()->full_name());
2361   EXPECT_TRUE(quux_field->message_type()->is_placeholder());
2362   // The place holder type should not be findable.
2363   ASSERT_TRUE(pool_->FindMessageTypeByName("undeclared.Quux") == NULL);
2364 }
2365 
2366 INSTANTIATE_TEST_CASE_P(DatabaseSource,
2367                         AllowUnknownDependenciesTest,
2368                         testing::Values(NO_DATABASE, FALLBACK_DATABASE));
2369 
2370 // ===================================================================
2371 
TEST(CustomOptions,OptionLocations)2372 TEST(CustomOptions, OptionLocations) {
2373   const Descriptor* message =
2374       protobuf_unittest::TestMessageWithCustomOptions::descriptor();
2375   const FileDescriptor* file = message->file();
2376   const FieldDescriptor* field = message->FindFieldByName("field1");
2377   const EnumDescriptor* enm = message->FindEnumTypeByName("AnEnum");
2378   // TODO(benjy): Support EnumValue options, once the compiler does.
2379   const ServiceDescriptor* service =
2380       file->FindServiceByName("TestServiceWithCustomOptions");
2381   const MethodDescriptor* method = service->FindMethodByName("Foo");
2382 
2383   EXPECT_EQ(GOOGLE_LONGLONG(9876543210),
2384             file->options().GetExtension(protobuf_unittest::file_opt1));
2385   EXPECT_EQ(-56,
2386             message->options().GetExtension(protobuf_unittest::message_opt1));
2387   EXPECT_EQ(GOOGLE_LONGLONG(8765432109),
2388             field->options().GetExtension(protobuf_unittest::field_opt1));
2389   EXPECT_EQ(42,  // Check that we get the default for an option we don't set.
2390             field->options().GetExtension(protobuf_unittest::field_opt2));
2391   EXPECT_EQ(-789,
2392             enm->options().GetExtension(protobuf_unittest::enum_opt1));
2393   EXPECT_EQ(123,
2394             enm->value(1)->options().GetExtension(
2395               protobuf_unittest::enum_value_opt1));
2396   EXPECT_EQ(GOOGLE_LONGLONG(-9876543210),
2397             service->options().GetExtension(protobuf_unittest::service_opt1));
2398   EXPECT_EQ(protobuf_unittest::METHODOPT1_VAL2,
2399             method->options().GetExtension(protobuf_unittest::method_opt1));
2400 
2401   // See that the regular options went through unscathed.
2402   EXPECT_TRUE(message->options().has_message_set_wire_format());
2403   EXPECT_EQ(FieldOptions::CORD, field->options().ctype());
2404 }
2405 
TEST(CustomOptions,OptionTypes)2406 TEST(CustomOptions, OptionTypes) {
2407   const MessageOptions* options = NULL;
2408 
2409   options =
2410       &protobuf_unittest::CustomOptionMinIntegerValues::descriptor()->options();
2411   EXPECT_EQ(false    , options->GetExtension(protobuf_unittest::bool_opt));
2412   EXPECT_EQ(kint32min, options->GetExtension(protobuf_unittest::int32_opt));
2413   EXPECT_EQ(kint64min, options->GetExtension(protobuf_unittest::int64_opt));
2414   EXPECT_EQ(0        , options->GetExtension(protobuf_unittest::uint32_opt));
2415   EXPECT_EQ(0        , options->GetExtension(protobuf_unittest::uint64_opt));
2416   EXPECT_EQ(kint32min, options->GetExtension(protobuf_unittest::sint32_opt));
2417   EXPECT_EQ(kint64min, options->GetExtension(protobuf_unittest::sint64_opt));
2418   EXPECT_EQ(0        , options->GetExtension(protobuf_unittest::fixed32_opt));
2419   EXPECT_EQ(0        , options->GetExtension(protobuf_unittest::fixed64_opt));
2420   EXPECT_EQ(kint32min, options->GetExtension(protobuf_unittest::sfixed32_opt));
2421   EXPECT_EQ(kint64min, options->GetExtension(protobuf_unittest::sfixed64_opt));
2422 
2423   options =
2424       &protobuf_unittest::CustomOptionMaxIntegerValues::descriptor()->options();
2425   EXPECT_EQ(true      , options->GetExtension(protobuf_unittest::bool_opt));
2426   EXPECT_EQ(kint32max , options->GetExtension(protobuf_unittest::int32_opt));
2427   EXPECT_EQ(kint64max , options->GetExtension(protobuf_unittest::int64_opt));
2428   EXPECT_EQ(kuint32max, options->GetExtension(protobuf_unittest::uint32_opt));
2429   EXPECT_EQ(kuint64max, options->GetExtension(protobuf_unittest::uint64_opt));
2430   EXPECT_EQ(kint32max , options->GetExtension(protobuf_unittest::sint32_opt));
2431   EXPECT_EQ(kint64max , options->GetExtension(protobuf_unittest::sint64_opt));
2432   EXPECT_EQ(kuint32max, options->GetExtension(protobuf_unittest::fixed32_opt));
2433   EXPECT_EQ(kuint64max, options->GetExtension(protobuf_unittest::fixed64_opt));
2434   EXPECT_EQ(kint32max , options->GetExtension(protobuf_unittest::sfixed32_opt));
2435   EXPECT_EQ(kint64max , options->GetExtension(protobuf_unittest::sfixed64_opt));
2436 
2437   options =
2438       &protobuf_unittest::CustomOptionOtherValues::descriptor()->options();
2439   EXPECT_EQ(-100, options->GetExtension(protobuf_unittest::int32_opt));
2440   EXPECT_FLOAT_EQ(12.3456789,
2441                   options->GetExtension(protobuf_unittest::float_opt));
2442   EXPECT_DOUBLE_EQ(1.234567890123456789,
2443                    options->GetExtension(protobuf_unittest::double_opt));
2444   EXPECT_EQ("Hello, \"World\"",
2445             options->GetExtension(protobuf_unittest::string_opt));
2446 
2447   EXPECT_EQ(string("Hello\0World", 11),
2448             options->GetExtension(protobuf_unittest::bytes_opt));
2449 
2450   EXPECT_EQ(protobuf_unittest::DummyMessageContainingEnum::TEST_OPTION_ENUM_TYPE2,
2451             options->GetExtension(protobuf_unittest::enum_opt));
2452 
2453   options =
2454       &protobuf_unittest::SettingRealsFromPositiveInts::descriptor()->options();
2455   EXPECT_FLOAT_EQ(12, options->GetExtension(protobuf_unittest::float_opt));
2456   EXPECT_DOUBLE_EQ(154, options->GetExtension(protobuf_unittest::double_opt));
2457 
2458   options =
2459       &protobuf_unittest::SettingRealsFromNegativeInts::descriptor()->options();
2460   EXPECT_FLOAT_EQ(-12, options->GetExtension(protobuf_unittest::float_opt));
2461   EXPECT_DOUBLE_EQ(-154, options->GetExtension(protobuf_unittest::double_opt));
2462 }
2463 
TEST(CustomOptions,ComplexExtensionOptions)2464 TEST(CustomOptions, ComplexExtensionOptions) {
2465   const MessageOptions* options =
2466       &protobuf_unittest::VariousComplexOptions::descriptor()->options();
2467   EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt1).foo(), 42);
2468   EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt1).
2469             GetExtension(protobuf_unittest::quux), 324);
2470   EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt1).
2471             GetExtension(protobuf_unittest::corge).qux(), 876);
2472   EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).baz(), 987);
2473   EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).
2474             GetExtension(protobuf_unittest::grault), 654);
2475   EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).bar().foo(),
2476             743);
2477   EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).bar().
2478             GetExtension(protobuf_unittest::quux), 1999);
2479   EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).bar().
2480             GetExtension(protobuf_unittest::corge).qux(), 2008);
2481   EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).
2482             GetExtension(protobuf_unittest::garply).foo(), 741);
2483   EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).
2484             GetExtension(protobuf_unittest::garply).
2485             GetExtension(protobuf_unittest::quux), 1998);
2486   EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).
2487             GetExtension(protobuf_unittest::garply).
2488             GetExtension(protobuf_unittest::corge).qux(), 2121);
2489   EXPECT_EQ(options->GetExtension(
2490       protobuf_unittest::ComplexOptionType2::ComplexOptionType4::complex_opt4).
2491             waldo(), 1971);
2492   EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).
2493             fred().waldo(), 321);
2494   EXPECT_EQ(9, options->GetExtension(protobuf_unittest::complex_opt3).qux());
2495   EXPECT_EQ(22, options->GetExtension(protobuf_unittest::complex_opt3).
2496                 complexoptiontype5().plugh());
2497   EXPECT_EQ(24, options->GetExtension(protobuf_unittest::complexopt6).xyzzy());
2498 }
2499 
TEST(CustomOptions,OptionsFromOtherFile)2500 TEST(CustomOptions, OptionsFromOtherFile) {
2501   // Test that to use a custom option, we only need to import the file
2502   // defining the option; we do not also have to import descriptor.proto.
2503   DescriptorPool pool;
2504 
2505   FileDescriptorProto file_proto;
2506   FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto);
2507   ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
2508 
2509   protobuf_unittest::TestMessageWithCustomOptions::descriptor()
2510     ->file()->CopyTo(&file_proto);
2511   ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
2512 
2513   ASSERT_TRUE(TextFormat::ParseFromString(
2514     "name: \"custom_options_import.proto\" "
2515     "package: \"protobuf_unittest\" "
2516     "dependency: \"google/protobuf/unittest_custom_options.proto\" "
2517     "options { "
2518     "  uninterpreted_option { "
2519     "    name { "
2520     "      name_part: \"file_opt1\" "
2521     "      is_extension: true "
2522     "    } "
2523     "    positive_int_value: 1234 "
2524     "  } "
2525     // Test a non-extension option too.  (At one point this failed due to a
2526     // bug.)
2527     "  uninterpreted_option { "
2528     "    name { "
2529     "      name_part: \"java_package\" "
2530     "      is_extension: false "
2531     "    } "
2532     "    string_value: \"foo\" "
2533     "  } "
2534     // Test that enum-typed options still work too.  (At one point this also
2535     // failed due to a bug.)
2536     "  uninterpreted_option { "
2537     "    name { "
2538     "      name_part: \"optimize_for\" "
2539     "      is_extension: false "
2540     "    } "
2541     "    identifier_value: \"SPEED\" "
2542     "  } "
2543     "}"
2544     ,
2545     &file_proto));
2546 
2547   const FileDescriptor* file = pool.BuildFile(file_proto);
2548   ASSERT_TRUE(file != NULL);
2549   EXPECT_EQ(1234, file->options().GetExtension(protobuf_unittest::file_opt1));
2550   EXPECT_TRUE(file->options().has_java_package());
2551   EXPECT_EQ("foo", file->options().java_package());
2552   EXPECT_TRUE(file->options().has_optimize_for());
2553   EXPECT_EQ(FileOptions::SPEED, file->options().optimize_for());
2554 }
2555 
TEST(CustomOptions,MessageOptionThreeFieldsSet)2556 TEST(CustomOptions, MessageOptionThreeFieldsSet) {
2557   // This tests a bug which previously existed in custom options parsing.  The
2558   // bug occurred when you defined a custom option with message type and then
2559   // set three fields of that option on a single definition (see the example
2560   // below).  The bug is a bit hard to explain, so check the change history if
2561   // you want to know more.
2562   DescriptorPool pool;
2563 
2564   FileDescriptorProto file_proto;
2565   FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto);
2566   ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
2567 
2568   protobuf_unittest::TestMessageWithCustomOptions::descriptor()
2569     ->file()->CopyTo(&file_proto);
2570   ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
2571 
2572   // The following represents the definition:
2573   //
2574   //   import "google/protobuf/unittest_custom_options.proto"
2575   //   package protobuf_unittest;
2576   //   message Foo {
2577   //     option (complex_opt1).foo  = 1234;
2578   //     option (complex_opt1).foo2 = 1234;
2579   //     option (complex_opt1).foo3 = 1234;
2580   //   }
2581   ASSERT_TRUE(TextFormat::ParseFromString(
2582     "name: \"custom_options_import.proto\" "
2583     "package: \"protobuf_unittest\" "
2584     "dependency: \"google/protobuf/unittest_custom_options.proto\" "
2585     "message_type { "
2586     "  name: \"Foo\" "
2587     "  options { "
2588     "    uninterpreted_option { "
2589     "      name { "
2590     "        name_part: \"complex_opt1\" "
2591     "        is_extension: true "
2592     "      } "
2593     "      name { "
2594     "        name_part: \"foo\" "
2595     "        is_extension: false "
2596     "      } "
2597     "      positive_int_value: 1234 "
2598     "    } "
2599     "    uninterpreted_option { "
2600     "      name { "
2601     "        name_part: \"complex_opt1\" "
2602     "        is_extension: true "
2603     "      } "
2604     "      name { "
2605     "        name_part: \"foo2\" "
2606     "        is_extension: false "
2607     "      } "
2608     "      positive_int_value: 1234 "
2609     "    } "
2610     "    uninterpreted_option { "
2611     "      name { "
2612     "        name_part: \"complex_opt1\" "
2613     "        is_extension: true "
2614     "      } "
2615     "      name { "
2616     "        name_part: \"foo3\" "
2617     "        is_extension: false "
2618     "      } "
2619     "      positive_int_value: 1234 "
2620     "    } "
2621     "  } "
2622     "}",
2623     &file_proto));
2624 
2625   const FileDescriptor* file = pool.BuildFile(file_proto);
2626   ASSERT_TRUE(file != NULL);
2627   ASSERT_EQ(1, file->message_type_count());
2628 
2629   const MessageOptions& options = file->message_type(0)->options();
2630   EXPECT_EQ(1234, options.GetExtension(protobuf_unittest::complex_opt1).foo());
2631 }
2632 
TEST(CustomOptions,MessageOptionRepeatedLeafFieldSet)2633 TEST(CustomOptions, MessageOptionRepeatedLeafFieldSet) {
2634   // This test verifies that repeated fields in custom options can be
2635   // given multiple values by repeating the option with a different value.
2636   // This test checks repeated leaf values. Each repeated custom value
2637   // appears in a different uninterpreted_option, which will be concatenated
2638   // when they are merged into the final option value.
2639   DescriptorPool pool;
2640 
2641   FileDescriptorProto file_proto;
2642   FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto);
2643   ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
2644 
2645   protobuf_unittest::TestMessageWithCustomOptions::descriptor()
2646     ->file()->CopyTo(&file_proto);
2647   ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
2648 
2649   // The following represents the definition:
2650   //
2651   //   import "google/protobuf/unittest_custom_options.proto"
2652   //   package protobuf_unittest;
2653   //   message Foo {
2654   //     option (complex_opt1).foo4 = 12;
2655   //     option (complex_opt1).foo4 = 34;
2656   //     option (complex_opt1).foo4 = 56;
2657   //   }
2658   ASSERT_TRUE(TextFormat::ParseFromString(
2659     "name: \"custom_options_import.proto\" "
2660     "package: \"protobuf_unittest\" "
2661     "dependency: \"google/protobuf/unittest_custom_options.proto\" "
2662     "message_type { "
2663     "  name: \"Foo\" "
2664     "  options { "
2665     "    uninterpreted_option { "
2666     "      name { "
2667     "        name_part: \"complex_opt1\" "
2668     "        is_extension: true "
2669     "      } "
2670     "      name { "
2671     "        name_part: \"foo4\" "
2672     "        is_extension: false "
2673     "      } "
2674     "      positive_int_value: 12 "
2675     "    } "
2676     "    uninterpreted_option { "
2677     "      name { "
2678     "        name_part: \"complex_opt1\" "
2679     "        is_extension: true "
2680     "      } "
2681     "      name { "
2682     "        name_part: \"foo4\" "
2683     "        is_extension: false "
2684     "      } "
2685     "      positive_int_value: 34 "
2686     "    } "
2687     "    uninterpreted_option { "
2688     "      name { "
2689     "        name_part: \"complex_opt1\" "
2690     "        is_extension: true "
2691     "      } "
2692     "      name { "
2693     "        name_part: \"foo4\" "
2694     "        is_extension: false "
2695     "      } "
2696     "      positive_int_value: 56 "
2697     "    } "
2698     "  } "
2699     "}",
2700     &file_proto));
2701 
2702   const FileDescriptor* file = pool.BuildFile(file_proto);
2703   ASSERT_TRUE(file != NULL);
2704   ASSERT_EQ(1, file->message_type_count());
2705 
2706   const MessageOptions& options = file->message_type(0)->options();
2707   EXPECT_EQ(3, options.GetExtension(protobuf_unittest::complex_opt1).foo4_size());
2708   EXPECT_EQ(12, options.GetExtension(protobuf_unittest::complex_opt1).foo4(0));
2709   EXPECT_EQ(34, options.GetExtension(protobuf_unittest::complex_opt1).foo4(1));
2710   EXPECT_EQ(56, options.GetExtension(protobuf_unittest::complex_opt1).foo4(2));
2711 }
2712 
TEST(CustomOptions,MessageOptionRepeatedMsgFieldSet)2713 TEST(CustomOptions, MessageOptionRepeatedMsgFieldSet) {
2714   // This test verifies that repeated fields in custom options can be
2715   // given multiple values by repeating the option with a different value.
2716   // This test checks repeated message values. Each repeated custom value
2717   // appears in a different uninterpreted_option, which will be concatenated
2718   // when they are merged into the final option value.
2719   DescriptorPool pool;
2720 
2721   FileDescriptorProto file_proto;
2722   FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto);
2723   ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
2724 
2725   protobuf_unittest::TestMessageWithCustomOptions::descriptor()
2726     ->file()->CopyTo(&file_proto);
2727   ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
2728 
2729   // The following represents the definition:
2730   //
2731   //   import "google/protobuf/unittest_custom_options.proto"
2732   //   package protobuf_unittest;
2733   //   message Foo {
2734   //     option (complex_opt2).barney = {waldo: 1};
2735   //     option (complex_opt2).barney = {waldo: 10};
2736   //     option (complex_opt2).barney = {waldo: 100};
2737   //   }
2738   ASSERT_TRUE(TextFormat::ParseFromString(
2739     "name: \"custom_options_import.proto\" "
2740     "package: \"protobuf_unittest\" "
2741     "dependency: \"google/protobuf/unittest_custom_options.proto\" "
2742     "message_type { "
2743     "  name: \"Foo\" "
2744     "  options { "
2745     "    uninterpreted_option { "
2746     "      name { "
2747     "        name_part: \"complex_opt2\" "
2748     "        is_extension: true "
2749     "      } "
2750     "      name { "
2751     "        name_part: \"barney\" "
2752     "        is_extension: false "
2753     "      } "
2754     "      aggregate_value: \"waldo: 1\" "
2755     "    } "
2756     "    uninterpreted_option { "
2757     "      name { "
2758     "        name_part: \"complex_opt2\" "
2759     "        is_extension: true "
2760     "      } "
2761     "      name { "
2762     "        name_part: \"barney\" "
2763     "        is_extension: false "
2764     "      } "
2765     "      aggregate_value: \"waldo: 10\" "
2766     "    } "
2767     "    uninterpreted_option { "
2768     "      name { "
2769     "        name_part: \"complex_opt2\" "
2770     "        is_extension: true "
2771     "      } "
2772     "      name { "
2773     "        name_part: \"barney\" "
2774     "        is_extension: false "
2775     "      } "
2776     "      aggregate_value: \"waldo: 100\" "
2777     "    } "
2778     "  } "
2779     "}",
2780     &file_proto));
2781 
2782   const FileDescriptor* file = pool.BuildFile(file_proto);
2783   ASSERT_TRUE(file != NULL);
2784   ASSERT_EQ(1, file->message_type_count());
2785 
2786   const MessageOptions& options = file->message_type(0)->options();
2787   EXPECT_EQ(3, options.GetExtension(
2788       protobuf_unittest::complex_opt2).barney_size());
2789   EXPECT_EQ(1,options.GetExtension(
2790       protobuf_unittest::complex_opt2).barney(0).waldo());
2791   EXPECT_EQ(10, options.GetExtension(
2792       protobuf_unittest::complex_opt2).barney(1).waldo());
2793   EXPECT_EQ(100, options.GetExtension(
2794       protobuf_unittest::complex_opt2).barney(2).waldo());
2795 }
2796 
2797 // Check that aggregate options were parsed and saved correctly in
2798 // the appropriate descriptors.
TEST(CustomOptions,AggregateOptions)2799 TEST(CustomOptions, AggregateOptions) {
2800   const Descriptor* msg = protobuf_unittest::AggregateMessage::descriptor();
2801   const FileDescriptor* file = msg->file();
2802   const FieldDescriptor* field = msg->FindFieldByName("fieldname");
2803   const EnumDescriptor* enumd = file->FindEnumTypeByName("AggregateEnum");
2804   const EnumValueDescriptor* enumv = enumd->FindValueByName("VALUE");
2805   const ServiceDescriptor* service = file->FindServiceByName(
2806       "AggregateService");
2807   const MethodDescriptor* method = service->FindMethodByName("Method");
2808 
2809   // Tests for the different types of data embedded in fileopt
2810   const protobuf_unittest::Aggregate& file_options =
2811       file->options().GetExtension(protobuf_unittest::fileopt);
2812   EXPECT_EQ(100, file_options.i());
2813   EXPECT_EQ("FileAnnotation", file_options.s());
2814   EXPECT_EQ("NestedFileAnnotation", file_options.sub().s());
2815   EXPECT_EQ("FileExtensionAnnotation",
2816             file_options.file().GetExtension(protobuf_unittest::fileopt).s());
2817   EXPECT_EQ("EmbeddedMessageSetElement",
2818             file_options.mset().GetExtension(
2819                 protobuf_unittest::AggregateMessageSetElement
2820                 ::message_set_extension).s());
2821 
2822   // Simple tests for all the other types of annotations
2823   EXPECT_EQ("MessageAnnotation",
2824             msg->options().GetExtension(protobuf_unittest::msgopt).s());
2825   EXPECT_EQ("FieldAnnotation",
2826             field->options().GetExtension(protobuf_unittest::fieldopt).s());
2827   EXPECT_EQ("EnumAnnotation",
2828             enumd->options().GetExtension(protobuf_unittest::enumopt).s());
2829   EXPECT_EQ("EnumValueAnnotation",
2830             enumv->options().GetExtension(protobuf_unittest::enumvalopt).s());
2831   EXPECT_EQ("ServiceAnnotation",
2832             service->options().GetExtension(protobuf_unittest::serviceopt).s());
2833   EXPECT_EQ("MethodAnnotation",
2834             method->options().GetExtension(protobuf_unittest::methodopt).s());
2835 }
2836 
TEST(CustomOptions,UnusedImportWarning)2837 TEST(CustomOptions, UnusedImportWarning) {
2838   DescriptorPool pool;
2839 
2840   FileDescriptorProto file_proto;
2841   FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto);
2842   ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
2843 
2844   protobuf_unittest::TestMessageWithCustomOptions::descriptor()
2845       ->file()->CopyTo(&file_proto);
2846   ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
2847 
2848 
2849   pool.AddUnusedImportTrackFile("custom_options_import.proto");
2850   ASSERT_TRUE(TextFormat::ParseFromString(
2851     "name: \"custom_options_import.proto\" "
2852     "package: \"protobuf_unittest\" "
2853     "dependency: \"google/protobuf/unittest_custom_options.proto\" ",
2854     &file_proto));
2855   pool.BuildFile(file_proto);
2856 }
2857 
2858 // ===================================================================
2859 
2860 // The tests below trigger every unique call to AddError() in descriptor.cc,
2861 // in the order in which they appear in that file.  I'm using TextFormat here
2862 // to specify the input descriptors because building them using code would
2863 // be too bulky.
2864 
2865 class MockErrorCollector : public DescriptorPool::ErrorCollector {
2866  public:
MockErrorCollector()2867   MockErrorCollector() {}
~MockErrorCollector()2868   ~MockErrorCollector() {}
2869 
2870   string text_;
2871   string warning_text_;
2872 
2873   // implements ErrorCollector ---------------------------------------
AddError(const string & filename,const string & element_name,const Message * descriptor,ErrorLocation location,const string & message)2874   void AddError(const string& filename,
2875                 const string& element_name, const Message* descriptor,
2876                 ErrorLocation location, const string& message) {
2877     const char* location_name = NULL;
2878     switch (location) {
2879       case NAME         : location_name = "NAME"         ; break;
2880       case NUMBER       : location_name = "NUMBER"       ; break;
2881       case TYPE         : location_name = "TYPE"         ; break;
2882       case EXTENDEE     : location_name = "EXTENDEE"     ; break;
2883       case DEFAULT_VALUE: location_name = "DEFAULT_VALUE"; break;
2884       case OPTION_NAME  : location_name = "OPTION_NAME"  ; break;
2885       case OPTION_VALUE : location_name = "OPTION_VALUE" ; break;
2886       case INPUT_TYPE   : location_name = "INPUT_TYPE"   ; break;
2887       case OUTPUT_TYPE  : location_name = "OUTPUT_TYPE"  ; break;
2888       case OTHER        : location_name = "OTHER"        ; break;
2889     }
2890 
2891     strings::SubstituteAndAppend(
2892       &text_, "$0: $1: $2: $3\n",
2893       filename, element_name, location_name, message);
2894   }
2895 
2896   // implements ErrorCollector ---------------------------------------
AddWarning(const string & filename,const string & element_name,const Message * descriptor,ErrorLocation location,const string & message)2897   void AddWarning(const string& filename, const string& element_name,
2898                   const Message* descriptor, ErrorLocation location,
2899                   const string& message) {
2900     const char* location_name = NULL;
2901     switch (location) {
2902       case NAME         : location_name = "NAME"         ; break;
2903       case NUMBER       : location_name = "NUMBER"       ; break;
2904       case TYPE         : location_name = "TYPE"         ; break;
2905       case EXTENDEE     : location_name = "EXTENDEE"     ; break;
2906       case DEFAULT_VALUE: location_name = "DEFAULT_VALUE"; break;
2907       case OPTION_NAME  : location_name = "OPTION_NAME"  ; break;
2908       case OPTION_VALUE : location_name = "OPTION_VALUE" ; break;
2909       case INPUT_TYPE   : location_name = "INPUT_TYPE"   ; break;
2910       case OUTPUT_TYPE  : location_name = "OUTPUT_TYPE"  ; break;
2911       case OTHER        : location_name = "OTHER"        ; break;
2912     }
2913 
2914     strings::SubstituteAndAppend(
2915       &warning_text_, "$0: $1: $2: $3\n",
2916       filename, element_name, location_name, message);
2917   }
2918 };
2919 
2920 class ValidationErrorTest : public testing::Test {
2921  protected:
2922   // Parse file_text as a FileDescriptorProto in text format and add it
2923   // to the DescriptorPool.  Expect no errors.
BuildFile(const string & file_text)2924   void BuildFile(const string& file_text) {
2925     FileDescriptorProto file_proto;
2926     ASSERT_TRUE(TextFormat::ParseFromString(file_text, &file_proto));
2927     ASSERT_TRUE(pool_.BuildFile(file_proto) != NULL);
2928   }
2929 
2930   // Parse file_text as a FileDescriptorProto in text format and add it
2931   // to the DescriptorPool.  Expect errors to be produced which match the
2932   // given error text.
BuildFileWithErrors(const string & file_text,const string & expected_errors)2933   void BuildFileWithErrors(const string& file_text,
2934                            const string& expected_errors) {
2935     FileDescriptorProto file_proto;
2936     ASSERT_TRUE(TextFormat::ParseFromString(file_text, &file_proto));
2937 
2938     MockErrorCollector error_collector;
2939     EXPECT_TRUE(
2940       pool_.BuildFileCollectingErrors(file_proto, &error_collector) == NULL);
2941     EXPECT_EQ(expected_errors, error_collector.text_);
2942   }
2943 
2944   // Parse file_text as a FileDescriptorProto in text format and add it
2945   // to the DescriptorPool.  Expect errors to be produced which match the
2946   // given warning text.
BuildFileWithWarnings(const string & file_text,const string & expected_warnings)2947   void BuildFileWithWarnings(const string& file_text,
2948                              const string& expected_warnings) {
2949     FileDescriptorProto file_proto;
2950     ASSERT_TRUE(TextFormat::ParseFromString(file_text, &file_proto));
2951 
2952     MockErrorCollector error_collector;
2953     EXPECT_TRUE(pool_.BuildFileCollectingErrors(file_proto, &error_collector));
2954     EXPECT_EQ(expected_warnings, error_collector.warning_text_);
2955   }
2956 
2957   // Builds some already-parsed file in our test pool.
BuildFileInTestPool(const FileDescriptor * file)2958   void BuildFileInTestPool(const FileDescriptor* file) {
2959     FileDescriptorProto file_proto;
2960     file->CopyTo(&file_proto);
2961     ASSERT_TRUE(pool_.BuildFile(file_proto) != NULL);
2962   }
2963 
2964   // Build descriptor.proto in our test pool. This allows us to extend it in
2965   // the test pool, so we can test custom options.
BuildDescriptorMessagesInTestPool()2966   void BuildDescriptorMessagesInTestPool() {
2967     BuildFileInTestPool(DescriptorProto::descriptor()->file());
2968   }
2969 
2970   DescriptorPool pool_;
2971 };
2972 
TEST_F(ValidationErrorTest,AlreadyDefined)2973 TEST_F(ValidationErrorTest, AlreadyDefined) {
2974   BuildFileWithErrors(
2975     "name: \"foo.proto\" "
2976     "message_type { name: \"Foo\" }"
2977     "message_type { name: \"Foo\" }",
2978 
2979     "foo.proto: Foo: NAME: \"Foo\" is already defined.\n");
2980 }
2981 
TEST_F(ValidationErrorTest,AlreadyDefinedInPackage)2982 TEST_F(ValidationErrorTest, AlreadyDefinedInPackage) {
2983   BuildFileWithErrors(
2984     "name: \"foo.proto\" "
2985     "package: \"foo.bar\" "
2986     "message_type { name: \"Foo\" }"
2987     "message_type { name: \"Foo\" }",
2988 
2989     "foo.proto: foo.bar.Foo: NAME: \"Foo\" is already defined in "
2990       "\"foo.bar\".\n");
2991 }
2992 
TEST_F(ValidationErrorTest,AlreadyDefinedInOtherFile)2993 TEST_F(ValidationErrorTest, AlreadyDefinedInOtherFile) {
2994   BuildFile(
2995     "name: \"foo.proto\" "
2996     "message_type { name: \"Foo\" }");
2997 
2998   BuildFileWithErrors(
2999     "name: \"bar.proto\" "
3000     "message_type { name: \"Foo\" }",
3001 
3002     "bar.proto: Foo: NAME: \"Foo\" is already defined in file "
3003       "\"foo.proto\".\n");
3004 }
3005 
TEST_F(ValidationErrorTest,PackageAlreadyDefined)3006 TEST_F(ValidationErrorTest, PackageAlreadyDefined) {
3007   BuildFile(
3008     "name: \"foo.proto\" "
3009     "message_type { name: \"foo\" }");
3010   BuildFileWithErrors(
3011     "name: \"bar.proto\" "
3012     "package: \"foo.bar\"",
3013 
3014     "bar.proto: foo: NAME: \"foo\" is already defined (as something other "
3015       "than a package) in file \"foo.proto\".\n");
3016 }
3017 
TEST_F(ValidationErrorTest,EnumValueAlreadyDefinedInParent)3018 TEST_F(ValidationErrorTest, EnumValueAlreadyDefinedInParent) {
3019   BuildFileWithErrors(
3020     "name: \"foo.proto\" "
3021     "enum_type { name: \"Foo\" value { name: \"FOO\" number: 1 } } "
3022     "enum_type { name: \"Bar\" value { name: \"FOO\" number: 1 } } ",
3023 
3024     "foo.proto: FOO: NAME: \"FOO\" is already defined.\n"
3025     "foo.proto: FOO: NAME: Note that enum values use C++ scoping rules, "
3026       "meaning that enum values are siblings of their type, not children of "
3027       "it.  Therefore, \"FOO\" must be unique within the global scope, not "
3028       "just within \"Bar\".\n");
3029 }
3030 
TEST_F(ValidationErrorTest,EnumValueAlreadyDefinedInParentNonGlobal)3031 TEST_F(ValidationErrorTest, EnumValueAlreadyDefinedInParentNonGlobal) {
3032   BuildFileWithErrors(
3033     "name: \"foo.proto\" "
3034     "package: \"pkg\" "
3035     "enum_type { name: \"Foo\" value { name: \"FOO\" number: 1 } } "
3036     "enum_type { name: \"Bar\" value { name: \"FOO\" number: 1 } } ",
3037 
3038     "foo.proto: pkg.FOO: NAME: \"FOO\" is already defined in \"pkg\".\n"
3039     "foo.proto: pkg.FOO: NAME: Note that enum values use C++ scoping rules, "
3040       "meaning that enum values are siblings of their type, not children of "
3041       "it.  Therefore, \"FOO\" must be unique within \"pkg\", not just within "
3042       "\"Bar\".\n");
3043 }
3044 
TEST_F(ValidationErrorTest,MissingName)3045 TEST_F(ValidationErrorTest, MissingName) {
3046   BuildFileWithErrors(
3047     "name: \"foo.proto\" "
3048     "message_type { }",
3049 
3050     "foo.proto: : NAME: Missing name.\n");
3051 }
3052 
TEST_F(ValidationErrorTest,InvalidName)3053 TEST_F(ValidationErrorTest, InvalidName) {
3054   BuildFileWithErrors(
3055     "name: \"foo.proto\" "
3056     "message_type { name: \"$\" }",
3057 
3058     "foo.proto: $: NAME: \"$\" is not a valid identifier.\n");
3059 }
3060 
TEST_F(ValidationErrorTest,InvalidPackageName)3061 TEST_F(ValidationErrorTest, InvalidPackageName) {
3062   BuildFileWithErrors(
3063     "name: \"foo.proto\" "
3064     "package: \"foo.$\"",
3065 
3066     "foo.proto: foo.$: NAME: \"$\" is not a valid identifier.\n");
3067 }
3068 
TEST_F(ValidationErrorTest,MissingFileName)3069 TEST_F(ValidationErrorTest, MissingFileName) {
3070   BuildFileWithErrors(
3071     "",
3072 
3073     ": : OTHER: Missing field: FileDescriptorProto.name.\n");
3074 }
3075 
TEST_F(ValidationErrorTest,DupeDependency)3076 TEST_F(ValidationErrorTest, DupeDependency) {
3077   BuildFile("name: \"foo.proto\"");
3078   BuildFileWithErrors(
3079     "name: \"bar.proto\" "
3080     "dependency: \"foo.proto\" "
3081     "dependency: \"foo.proto\" ",
3082 
3083     "bar.proto: bar.proto: OTHER: Import \"foo.proto\" was listed twice.\n");
3084 }
3085 
TEST_F(ValidationErrorTest,UnknownDependency)3086 TEST_F(ValidationErrorTest, UnknownDependency) {
3087   BuildFileWithErrors(
3088     "name: \"bar.proto\" "
3089     "dependency: \"foo.proto\" ",
3090 
3091     "bar.proto: bar.proto: OTHER: Import \"foo.proto\" has not been loaded.\n");
3092 }
3093 
TEST_F(ValidationErrorTest,InvalidPublicDependencyIndex)3094 TEST_F(ValidationErrorTest, InvalidPublicDependencyIndex) {
3095   BuildFile("name: \"foo.proto\"");
3096   BuildFileWithErrors(
3097     "name: \"bar.proto\" "
3098     "dependency: \"foo.proto\" "
3099     "public_dependency: 1",
3100     "bar.proto: bar.proto: OTHER: Invalid public dependency index.\n");
3101 }
3102 
TEST_F(ValidationErrorTest,ForeignUnimportedPackageNoCrash)3103 TEST_F(ValidationErrorTest, ForeignUnimportedPackageNoCrash) {
3104   // Used to crash:  If we depend on a non-existent file and then refer to a
3105   // package defined in a file that we didn't import, and that package is
3106   // nested within a parent package which this file is also in, and we don't
3107   // include that parent package in the name (i.e. we do a relative lookup)...
3108   // Yes, really.
3109   BuildFile(
3110     "name: 'foo.proto' "
3111     "package: 'outer.foo' ");
3112   BuildFileWithErrors(
3113     "name: 'bar.proto' "
3114     "dependency: 'baz.proto' "
3115     "package: 'outer.bar' "
3116     "message_type { "
3117     "  name: 'Bar' "
3118     "  field { name:'bar' number:1 label:LABEL_OPTIONAL type_name:'foo.Foo' }"
3119     "}",
3120 
3121     "bar.proto: bar.proto: OTHER: Import \"baz.proto\" has not been loaded.\n"
3122     "bar.proto: outer.bar.Bar.bar: TYPE: \"outer.foo\" seems to be defined in "
3123       "\"foo.proto\", which is not imported by \"bar.proto\".  To use it here, "
3124       "please add the necessary import.\n");
3125 }
3126 
TEST_F(ValidationErrorTest,DupeFile)3127 TEST_F(ValidationErrorTest, DupeFile) {
3128   BuildFile(
3129     "name: \"foo.proto\" "
3130     "message_type { name: \"Foo\" }");
3131   // Note:  We should *not* get redundant errors about "Foo" already being
3132   //   defined.
3133   BuildFileWithErrors(
3134     "name: \"foo.proto\" "
3135     "message_type { name: \"Foo\" } "
3136     // Add another type so that the files aren't identical (in which case there
3137     // would be no error).
3138     "enum_type { name: \"Bar\" }",
3139 
3140     "foo.proto: foo.proto: OTHER: A file with this name is already in the "
3141       "pool.\n");
3142 }
3143 
TEST_F(ValidationErrorTest,FieldInExtensionRange)3144 TEST_F(ValidationErrorTest, FieldInExtensionRange) {
3145   BuildFileWithErrors(
3146     "name: \"foo.proto\" "
3147     "message_type {"
3148     "  name: \"Foo\""
3149     "  field { name: \"foo\" number:  9 label:LABEL_OPTIONAL type:TYPE_INT32 }"
3150     "  field { name: \"bar\" number: 10 label:LABEL_OPTIONAL type:TYPE_INT32 }"
3151     "  field { name: \"baz\" number: 19 label:LABEL_OPTIONAL type:TYPE_INT32 }"
3152     "  field { name: \"qux\" number: 20 label:LABEL_OPTIONAL type:TYPE_INT32 }"
3153     "  extension_range { start: 10 end: 20 }"
3154     "}",
3155 
3156     "foo.proto: Foo.bar: NUMBER: Extension range 10 to 19 includes field "
3157       "\"bar\" (10).\n"
3158     "foo.proto: Foo.baz: NUMBER: Extension range 10 to 19 includes field "
3159       "\"baz\" (19).\n");
3160 }
3161 
TEST_F(ValidationErrorTest,OverlappingExtensionRanges)3162 TEST_F(ValidationErrorTest, OverlappingExtensionRanges) {
3163   BuildFileWithErrors(
3164     "name: \"foo.proto\" "
3165     "message_type {"
3166     "  name: \"Foo\""
3167     "  extension_range { start: 10 end: 20 }"
3168     "  extension_range { start: 20 end: 30 }"
3169     "  extension_range { start: 19 end: 21 }"
3170     "}",
3171 
3172     "foo.proto: Foo: NUMBER: Extension range 19 to 20 overlaps with "
3173       "already-defined range 10 to 19.\n"
3174     "foo.proto: Foo: NUMBER: Extension range 19 to 20 overlaps with "
3175       "already-defined range 20 to 29.\n");
3176 }
3177 
TEST_F(ValidationErrorTest,InvalidDefaults)3178 TEST_F(ValidationErrorTest, InvalidDefaults) {
3179   BuildFileWithErrors(
3180     "name: \"foo.proto\" "
3181     "message_type {"
3182     "  name: \"Foo\""
3183 
3184     // Invalid number.
3185     "  field { name: \"foo\" number: 1 label: LABEL_OPTIONAL type: TYPE_INT32"
3186     "          default_value: \"abc\" }"
3187 
3188     // Empty default value.
3189     "  field { name: \"bar\" number: 2 label: LABEL_OPTIONAL type: TYPE_INT32"
3190     "          default_value: \"\" }"
3191 
3192     // Invalid boolean.
3193     "  field { name: \"baz\" number: 3 label: LABEL_OPTIONAL type: TYPE_BOOL"
3194     "          default_value: \"abc\" }"
3195 
3196     // Messages can't have defaults.
3197     "  field { name: \"qux\" number: 4 label: LABEL_OPTIONAL type: TYPE_MESSAGE"
3198     "          default_value: \"abc\" type_name: \"Foo\" }"
3199 
3200     // Same thing, but we don't know that this field has message type until
3201     // we look up the type name.
3202     "  field { name: \"quux\" number: 5 label: LABEL_OPTIONAL"
3203     "          default_value: \"abc\" type_name: \"Foo\" }"
3204 
3205     // Repeateds can't have defaults.
3206     "  field { name: \"corge\" number: 6 label: LABEL_REPEATED type: TYPE_INT32"
3207     "          default_value: \"1\" }"
3208     "}",
3209 
3210     "foo.proto: Foo.foo: DEFAULT_VALUE: Couldn't parse default value \"abc\".\n"
3211     "foo.proto: Foo.bar: DEFAULT_VALUE: Couldn't parse default value \"\".\n"
3212     "foo.proto: Foo.baz: DEFAULT_VALUE: Boolean default must be true or "
3213       "false.\n"
3214     "foo.proto: Foo.qux: DEFAULT_VALUE: Messages can't have default values.\n"
3215     "foo.proto: Foo.corge: DEFAULT_VALUE: Repeated fields can't have default "
3216       "values.\n"
3217     // This ends up being reported later because the error is detected at
3218     // cross-linking time.
3219     "foo.proto: Foo.quux: DEFAULT_VALUE: Messages can't have default "
3220       "values.\n");
3221 }
3222 
TEST_F(ValidationErrorTest,NegativeFieldNumber)3223 TEST_F(ValidationErrorTest, NegativeFieldNumber) {
3224   BuildFileWithErrors(
3225     "name: \"foo.proto\" "
3226     "message_type {"
3227     "  name: \"Foo\""
3228     "  field { name: \"foo\" number: -1 label:LABEL_OPTIONAL type:TYPE_INT32 }"
3229     "}",
3230 
3231     "foo.proto: Foo.foo: NUMBER: Field numbers must be positive integers.\n");
3232 }
3233 
TEST_F(ValidationErrorTest,HugeFieldNumber)3234 TEST_F(ValidationErrorTest, HugeFieldNumber) {
3235   BuildFileWithErrors(
3236     "name: \"foo.proto\" "
3237     "message_type {"
3238     "  name: \"Foo\""
3239     "  field { name: \"foo\" number: 0x70000000 "
3240     "          label:LABEL_OPTIONAL type:TYPE_INT32 }"
3241     "}",
3242 
3243     "foo.proto: Foo.foo: NUMBER: Field numbers cannot be greater than "
3244       "536870911.\n");
3245 }
3246 
TEST_F(ValidationErrorTest,ReservedFieldNumber)3247 TEST_F(ValidationErrorTest, ReservedFieldNumber) {
3248   BuildFileWithErrors(
3249     "name: \"foo.proto\" "
3250     "message_type {"
3251     "  name: \"Foo\""
3252     "  field {name:\"foo\" number: 18999 label:LABEL_OPTIONAL type:TYPE_INT32 }"
3253     "  field {name:\"bar\" number: 19000 label:LABEL_OPTIONAL type:TYPE_INT32 }"
3254     "  field {name:\"baz\" number: 19999 label:LABEL_OPTIONAL type:TYPE_INT32 }"
3255     "  field {name:\"qux\" number: 20000 label:LABEL_OPTIONAL type:TYPE_INT32 }"
3256     "}",
3257 
3258     "foo.proto: Foo.bar: NUMBER: Field numbers 19000 through 19999 are "
3259       "reserved for the protocol buffer library implementation.\n"
3260     "foo.proto: Foo.baz: NUMBER: Field numbers 19000 through 19999 are "
3261       "reserved for the protocol buffer library implementation.\n");
3262 }
3263 
TEST_F(ValidationErrorTest,ExtensionMissingExtendee)3264 TEST_F(ValidationErrorTest, ExtensionMissingExtendee) {
3265   BuildFileWithErrors(
3266     "name: \"foo.proto\" "
3267     "message_type {"
3268     "  name: \"Foo\""
3269     "  extension { name: \"foo\" number: 1 label: LABEL_OPTIONAL"
3270     "              type_name: \"Foo\" }"
3271     "}",
3272 
3273     "foo.proto: Foo.foo: EXTENDEE: FieldDescriptorProto.extendee not set for "
3274       "extension field.\n");
3275 }
3276 
TEST_F(ValidationErrorTest,NonExtensionWithExtendee)3277 TEST_F(ValidationErrorTest, NonExtensionWithExtendee) {
3278   BuildFileWithErrors(
3279     "name: \"foo.proto\" "
3280     "message_type {"
3281     "  name: \"Bar\""
3282     "  extension_range { start: 1 end: 2 }"
3283     "}"
3284     "message_type {"
3285     "  name: \"Foo\""
3286     "  field { name: \"foo\" number: 1 label: LABEL_OPTIONAL"
3287     "          type_name: \"Foo\" extendee: \"Bar\" }"
3288     "}",
3289 
3290     "foo.proto: Foo.foo: EXTENDEE: FieldDescriptorProto.extendee set for "
3291       "non-extension field.\n");
3292 }
3293 
TEST_F(ValidationErrorTest,FieldOneofIndexTooLarge)3294 TEST_F(ValidationErrorTest, FieldOneofIndexTooLarge) {
3295   BuildFileWithErrors(
3296     "name: \"foo.proto\" "
3297     "message_type {"
3298     "  name: \"Foo\""
3299     "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32 "
3300     "          oneof_index: 1 }"
3301     "  field { name:\"dummy\" number:2 label:LABEL_OPTIONAL type:TYPE_INT32 "
3302     "          oneof_index: 0 }"
3303     "  oneof_decl { name:\"bar\" }"
3304     "}",
3305 
3306     "foo.proto: Foo.foo: OTHER: FieldDescriptorProto.oneof_index 1 is out of "
3307       "range for type \"Foo\".\n");
3308 }
3309 
TEST_F(ValidationErrorTest,FieldOneofIndexNegative)3310 TEST_F(ValidationErrorTest, FieldOneofIndexNegative) {
3311   BuildFileWithErrors(
3312     "name: \"foo.proto\" "
3313     "message_type {"
3314     "  name: \"Foo\""
3315     "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32 "
3316     "          oneof_index: -1 }"
3317     "  field { name:\"dummy\" number:2 label:LABEL_OPTIONAL type:TYPE_INT32 "
3318     "          oneof_index: 0 }"
3319     "  oneof_decl { name:\"bar\" }"
3320     "}",
3321 
3322     "foo.proto: Foo.foo: OTHER: FieldDescriptorProto.oneof_index -1 is out of "
3323       "range for type \"Foo\".\n");
3324 }
3325 
TEST_F(ValidationErrorTest,FieldNumberConflict)3326 TEST_F(ValidationErrorTest, FieldNumberConflict) {
3327   BuildFileWithErrors(
3328     "name: \"foo.proto\" "
3329     "message_type {"
3330     "  name: \"Foo\""
3331     "  field { name: \"foo\" number: 1 label:LABEL_OPTIONAL type:TYPE_INT32 }"
3332     "  field { name: \"bar\" number: 1 label:LABEL_OPTIONAL type:TYPE_INT32 }"
3333     "}",
3334 
3335     "foo.proto: Foo.bar: NUMBER: Field number 1 has already been used in "
3336       "\"Foo\" by field \"foo\".\n");
3337 }
3338 
TEST_F(ValidationErrorTest,BadMessageSetExtensionType)3339 TEST_F(ValidationErrorTest, BadMessageSetExtensionType) {
3340   BuildFileWithErrors(
3341     "name: \"foo.proto\" "
3342     "message_type {"
3343     "  name: \"MessageSet\""
3344     "  options { message_set_wire_format: true }"
3345     "  extension_range { start: 4 end: 5 }"
3346     "}"
3347     "message_type {"
3348     "  name: \"Foo\""
3349     "  extension { name:\"foo\" number:4 label:LABEL_OPTIONAL type:TYPE_INT32"
3350     "              extendee: \"MessageSet\" }"
3351     "}",
3352 
3353     "foo.proto: Foo.foo: TYPE: Extensions of MessageSets must be optional "
3354       "messages.\n");
3355 }
3356 
TEST_F(ValidationErrorTest,BadMessageSetExtensionLabel)3357 TEST_F(ValidationErrorTest, BadMessageSetExtensionLabel) {
3358   BuildFileWithErrors(
3359     "name: \"foo.proto\" "
3360     "message_type {"
3361     "  name: \"MessageSet\""
3362     "  options { message_set_wire_format: true }"
3363     "  extension_range { start: 4 end: 5 }"
3364     "}"
3365     "message_type {"
3366     "  name: \"Foo\""
3367     "  extension { name:\"foo\" number:4 label:LABEL_REPEATED type:TYPE_MESSAGE"
3368     "              type_name: \"Foo\" extendee: \"MessageSet\" }"
3369     "}",
3370 
3371     "foo.proto: Foo.foo: TYPE: Extensions of MessageSets must be optional "
3372       "messages.\n");
3373 }
3374 
TEST_F(ValidationErrorTest,FieldInMessageSet)3375 TEST_F(ValidationErrorTest, FieldInMessageSet) {
3376   BuildFileWithErrors(
3377     "name: \"foo.proto\" "
3378     "message_type {"
3379     "  name: \"Foo\""
3380     "  options { message_set_wire_format: true }"
3381     "  field { name: \"foo\" number: 1 label:LABEL_OPTIONAL type:TYPE_INT32 }"
3382     "}",
3383 
3384     "foo.proto: Foo.foo: NAME: MessageSets cannot have fields, only "
3385       "extensions.\n");
3386 }
3387 
TEST_F(ValidationErrorTest,NegativeExtensionRangeNumber)3388 TEST_F(ValidationErrorTest, NegativeExtensionRangeNumber) {
3389   BuildFileWithErrors(
3390     "name: \"foo.proto\" "
3391     "message_type {"
3392     "  name: \"Foo\""
3393     "  extension_range { start: -10 end: -1 }"
3394     "}",
3395 
3396     "foo.proto: Foo: NUMBER: Extension numbers must be positive integers.\n");
3397 }
3398 
TEST_F(ValidationErrorTest,HugeExtensionRangeNumber)3399 TEST_F(ValidationErrorTest, HugeExtensionRangeNumber) {
3400   BuildFileWithErrors(
3401     "name: \"foo.proto\" "
3402     "message_type {"
3403     "  name: \"Foo\""
3404     "  extension_range { start: 1 end: 0x70000000 }"
3405     "}",
3406 
3407     "foo.proto: Foo: NUMBER: Extension numbers cannot be greater than "
3408       "536870911.\n");
3409 }
3410 
TEST_F(ValidationErrorTest,ExtensionRangeEndBeforeStart)3411 TEST_F(ValidationErrorTest, ExtensionRangeEndBeforeStart) {
3412   BuildFileWithErrors(
3413     "name: \"foo.proto\" "
3414     "message_type {"
3415     "  name: \"Foo\""
3416     "  extension_range { start: 10 end: 10 }"
3417     "  extension_range { start: 10 end: 5 }"
3418     "}",
3419 
3420     "foo.proto: Foo: NUMBER: Extension range end number must be greater than "
3421       "start number.\n"
3422     "foo.proto: Foo: NUMBER: Extension range end number must be greater than "
3423       "start number.\n");
3424 }
3425 
TEST_F(ValidationErrorTest,EmptyEnum)3426 TEST_F(ValidationErrorTest, EmptyEnum) {
3427   BuildFileWithErrors(
3428     "name: \"foo.proto\" "
3429     "enum_type { name: \"Foo\" }"
3430     // Also use the empty enum in a message to make sure there are no crashes
3431     // during validation (possible if the code attempts to derive a default
3432     // value for the field).
3433     "message_type {"
3434     "  name: \"Bar\""
3435     "  field { name: \"foo\" number: 1 label:LABEL_OPTIONAL type_name:\"Foo\" }"
3436     "  field { name: \"bar\" number: 2 label:LABEL_OPTIONAL type_name:\"Foo\" "
3437     "          default_value: \"NO_SUCH_VALUE\" }"
3438     "}",
3439 
3440     "foo.proto: Foo: NAME: Enums must contain at least one value.\n"
3441     "foo.proto: Bar.bar: DEFAULT_VALUE: Enum type \"Foo\" has no value named "
3442       "\"NO_SUCH_VALUE\".\n");
3443 }
3444 
TEST_F(ValidationErrorTest,UndefinedExtendee)3445 TEST_F(ValidationErrorTest, UndefinedExtendee) {
3446   BuildFileWithErrors(
3447     "name: \"foo.proto\" "
3448     "message_type {"
3449     "  name: \"Foo\""
3450     "  extension { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32"
3451     "              extendee: \"Bar\" }"
3452     "}",
3453 
3454     "foo.proto: Foo.foo: EXTENDEE: \"Bar\" is not defined.\n");
3455 }
3456 
TEST_F(ValidationErrorTest,NonMessageExtendee)3457 TEST_F(ValidationErrorTest, NonMessageExtendee) {
3458   BuildFileWithErrors(
3459     "name: \"foo.proto\" "
3460     "enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } }"
3461     "message_type {"
3462     "  name: \"Foo\""
3463     "  extension { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32"
3464     "              extendee: \"Bar\" }"
3465     "}",
3466 
3467     "foo.proto: Foo.foo: EXTENDEE: \"Bar\" is not a message type.\n");
3468 }
3469 
TEST_F(ValidationErrorTest,NotAnExtensionNumber)3470 TEST_F(ValidationErrorTest, NotAnExtensionNumber) {
3471   BuildFileWithErrors(
3472     "name: \"foo.proto\" "
3473     "message_type {"
3474     "  name: \"Bar\""
3475     "}"
3476     "message_type {"
3477     "  name: \"Foo\""
3478     "  extension { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32"
3479     "              extendee: \"Bar\" }"
3480     "}",
3481 
3482     "foo.proto: Foo.foo: NUMBER: \"Bar\" does not declare 1 as an extension "
3483       "number.\n");
3484 }
3485 
TEST_F(ValidationErrorTest,RequiredExtension)3486 TEST_F(ValidationErrorTest, RequiredExtension) {
3487   BuildFileWithErrors(
3488     "name: \"foo.proto\" "
3489     "message_type {"
3490     "  name: \"Bar\""
3491     "  extension_range { start: 1000 end: 10000 }"
3492     "}"
3493     "message_type {"
3494     "  name: \"Foo\""
3495     "  extension {"
3496     "    name:\"foo\""
3497     "    number:1000"
3498     "    label:LABEL_REQUIRED"
3499     "    type:TYPE_INT32"
3500     "    extendee: \"Bar\""
3501     "  }"
3502     "}",
3503 
3504     "foo.proto: Foo.foo: TYPE: Message extensions cannot have required "
3505     "fields.\n");
3506 }
3507 
TEST_F(ValidationErrorTest,UndefinedFieldType)3508 TEST_F(ValidationErrorTest, UndefinedFieldType) {
3509   BuildFileWithErrors(
3510     "name: \"foo.proto\" "
3511     "message_type {"
3512     "  name: \"Foo\""
3513     "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }"
3514     "}",
3515 
3516     "foo.proto: Foo.foo: TYPE: \"Bar\" is not defined.\n");
3517 }
3518 
TEST_F(ValidationErrorTest,UndefinedFieldTypeWithDefault)3519 TEST_F(ValidationErrorTest, UndefinedFieldTypeWithDefault) {
3520   // See b/12533582. Previously this failed because the default value was not
3521   // accepted by the parser, which assumed an enum type, leading to an unclear
3522   // error message. We want this input to yield a validation error instead,
3523   // since the unknown type is the primary problem.
3524   BuildFileWithErrors(
3525     "name: \"foo.proto\" "
3526     "message_type {"
3527     "  name: \"Foo\""
3528     "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"int\" "
3529     "          default_value:\"1\" }"
3530     "}",
3531 
3532     "foo.proto: Foo.foo: TYPE: \"int\" is not defined.\n");
3533 }
3534 
TEST_F(ValidationErrorTest,UndefinedNestedFieldType)3535 TEST_F(ValidationErrorTest, UndefinedNestedFieldType) {
3536   BuildFileWithErrors(
3537     "name: \"foo.proto\" "
3538     "message_type {"
3539     "  name: \"Foo\""
3540     "  nested_type { name:\"Baz\" }"
3541     "  field { name:\"foo\" number:1"
3542     "          label:LABEL_OPTIONAL"
3543     "          type_name:\"Foo.Baz.Bar\" }"
3544     "}",
3545 
3546     "foo.proto: Foo.foo: TYPE: \"Foo.Baz.Bar\" is not defined.\n");
3547 }
3548 
TEST_F(ValidationErrorTest,FieldTypeDefinedInUndeclaredDependency)3549 TEST_F(ValidationErrorTest, FieldTypeDefinedInUndeclaredDependency) {
3550   BuildFile(
3551     "name: \"bar.proto\" "
3552     "message_type { name: \"Bar\" } ");
3553 
3554   BuildFileWithErrors(
3555     "name: \"foo.proto\" "
3556     "message_type {"
3557     "  name: \"Foo\""
3558     "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }"
3559     "}",
3560     "foo.proto: Foo.foo: TYPE: \"Bar\" seems to be defined in \"bar.proto\", "
3561       "which is not imported by \"foo.proto\".  To use it here, please add the "
3562       "necessary import.\n");
3563 }
3564 
TEST_F(ValidationErrorTest,FieldTypeDefinedInIndirectDependency)3565 TEST_F(ValidationErrorTest, FieldTypeDefinedInIndirectDependency) {
3566   // Test for hidden dependencies.
3567   //
3568   // // bar.proto
3569   // message Bar{}
3570   //
3571   // // forward.proto
3572   // import "bar.proto"
3573   //
3574   // // foo.proto
3575   // import "forward.proto"
3576   // message Foo {
3577   //   optional Bar foo = 1;  // Error, needs to import bar.proto explicitly.
3578   // }
3579   //
3580   BuildFile(
3581     "name: \"bar.proto\" "
3582     "message_type { name: \"Bar\" }");
3583 
3584   BuildFile(
3585     "name: \"forward.proto\""
3586     "dependency: \"bar.proto\"");
3587 
3588   BuildFileWithErrors(
3589     "name: \"foo.proto\" "
3590     "dependency: \"forward.proto\" "
3591     "message_type {"
3592     "  name: \"Foo\""
3593     "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }"
3594     "}",
3595     "foo.proto: Foo.foo: TYPE: \"Bar\" seems to be defined in \"bar.proto\", "
3596       "which is not imported by \"foo.proto\".  To use it here, please add the "
3597       "necessary import.\n");
3598 }
3599 
TEST_F(ValidationErrorTest,FieldTypeDefinedInPublicDependency)3600 TEST_F(ValidationErrorTest, FieldTypeDefinedInPublicDependency) {
3601   // Test for public dependencies.
3602   //
3603   // // bar.proto
3604   // message Bar{}
3605   //
3606   // // forward.proto
3607   // import public "bar.proto"
3608   //
3609   // // foo.proto
3610   // import "forward.proto"
3611   // message Foo {
3612   //   optional Bar foo = 1;  // Correct. "bar.proto" is public imported into
3613   //                          // forward.proto, so when "foo.proto" imports
3614   //                          // "forward.proto", it imports "bar.proto" too.
3615   // }
3616   //
3617   BuildFile(
3618     "name: \"bar.proto\" "
3619     "message_type { name: \"Bar\" }");
3620 
3621   BuildFile(
3622     "name: \"forward.proto\""
3623     "dependency: \"bar.proto\" "
3624     "public_dependency: 0");
3625 
3626   BuildFile(
3627     "name: \"foo.proto\" "
3628     "dependency: \"forward.proto\" "
3629     "message_type {"
3630     "  name: \"Foo\""
3631     "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }"
3632     "}");
3633 }
3634 
TEST_F(ValidationErrorTest,FieldTypeDefinedInTransitivePublicDependency)3635 TEST_F(ValidationErrorTest, FieldTypeDefinedInTransitivePublicDependency) {
3636   // Test for public dependencies.
3637   //
3638   // // bar.proto
3639   // message Bar{}
3640   //
3641   // // forward.proto
3642   // import public "bar.proto"
3643   //
3644   // // forward2.proto
3645   // import public "forward.proto"
3646   //
3647   // // foo.proto
3648   // import "forward2.proto"
3649   // message Foo {
3650   //   optional Bar foo = 1;  // Correct, public imports are transitive.
3651   // }
3652   //
3653   BuildFile(
3654     "name: \"bar.proto\" "
3655     "message_type { name: \"Bar\" }");
3656 
3657   BuildFile(
3658     "name: \"forward.proto\""
3659     "dependency: \"bar.proto\" "
3660     "public_dependency: 0");
3661 
3662   BuildFile(
3663     "name: \"forward2.proto\""
3664     "dependency: \"forward.proto\" "
3665     "public_dependency: 0");
3666 
3667   BuildFile(
3668     "name: \"foo.proto\" "
3669     "dependency: \"forward2.proto\" "
3670     "message_type {"
3671     "  name: \"Foo\""
3672     "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }"
3673     "}");
3674 }
3675 
TEST_F(ValidationErrorTest,FieldTypeDefinedInPrivateDependencyOfPublicDependency)3676 TEST_F(ValidationErrorTest,
3677        FieldTypeDefinedInPrivateDependencyOfPublicDependency) {
3678   // Test for public dependencies.
3679   //
3680   // // bar.proto
3681   // message Bar{}
3682   //
3683   // // forward.proto
3684   // import "bar.proto"
3685   //
3686   // // forward2.proto
3687   // import public "forward.proto"
3688   //
3689   // // foo.proto
3690   // import "forward2.proto"
3691   // message Foo {
3692   //   optional Bar foo = 1;  // Error, the "bar.proto" is not public imported
3693   //                          // into "forward.proto", so will not be imported
3694   //                          // into either "forward2.proto" or "foo.proto".
3695   // }
3696   //
3697   BuildFile(
3698     "name: \"bar.proto\" "
3699     "message_type { name: \"Bar\" }");
3700 
3701   BuildFile(
3702     "name: \"forward.proto\""
3703     "dependency: \"bar.proto\"");
3704 
3705   BuildFile(
3706     "name: \"forward2.proto\""
3707     "dependency: \"forward.proto\" "
3708     "public_dependency: 0");
3709 
3710   BuildFileWithErrors(
3711     "name: \"foo.proto\" "
3712     "dependency: \"forward2.proto\" "
3713     "message_type {"
3714     "  name: \"Foo\""
3715     "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }"
3716     "}",
3717     "foo.proto: Foo.foo: TYPE: \"Bar\" seems to be defined in \"bar.proto\", "
3718       "which is not imported by \"foo.proto\".  To use it here, please add the "
3719       "necessary import.\n");
3720 }
3721 
3722 
TEST_F(ValidationErrorTest,SearchMostLocalFirst)3723 TEST_F(ValidationErrorTest, SearchMostLocalFirst) {
3724   // The following should produce an error that Bar.Baz is resolved but
3725   // not defined:
3726   //   message Bar { message Baz {} }
3727   //   message Foo {
3728   //     message Bar {
3729   //       // Placing "message Baz{}" here, or removing Foo.Bar altogether,
3730   //       // would fix the error.
3731   //     }
3732   //     optional Bar.Baz baz = 1;
3733   //   }
3734   // An one point the lookup code incorrectly did not produce an error in this
3735   // case, because when looking for Bar.Baz, it would try "Foo.Bar.Baz" first,
3736   // fail, and ten try "Bar.Baz" and succeed, even though "Bar" should actually
3737   // refer to the inner Bar, not the outer one.
3738   BuildFileWithErrors(
3739     "name: \"foo.proto\" "
3740     "message_type {"
3741     "  name: \"Bar\""
3742     "  nested_type { name: \"Baz\" }"
3743     "}"
3744     "message_type {"
3745     "  name: \"Foo\""
3746     "  nested_type { name: \"Bar\" }"
3747     "  field { name:\"baz\" number:1 label:LABEL_OPTIONAL"
3748     "          type_name:\"Bar.Baz\" }"
3749     "}",
3750 
3751     "foo.proto: Foo.baz: TYPE: \"Bar.Baz\" is resolved to \"Foo.Bar.Baz\","
3752     " which is not defined. The innermost scope is searched first in name "
3753     "resolution. Consider using a leading '.'(i.e., \".Bar.Baz\") to start "
3754     "from the outermost scope.\n");
3755 }
3756 
TEST_F(ValidationErrorTest,SearchMostLocalFirst2)3757 TEST_F(ValidationErrorTest, SearchMostLocalFirst2) {
3758   // This test would find the most local "Bar" first, and does, but
3759   // proceeds to find the outer one because the inner one's not an
3760   // aggregate.
3761   BuildFile(
3762     "name: \"foo.proto\" "
3763     "message_type {"
3764     "  name: \"Bar\""
3765     "  nested_type { name: \"Baz\" }"
3766     "}"
3767     "message_type {"
3768     "  name: \"Foo\""
3769     "  field { name: \"Bar\" number:1 type:TYPE_BYTES } "
3770     "  field { name:\"baz\" number:2 label:LABEL_OPTIONAL"
3771     "          type_name:\"Bar.Baz\" }"
3772     "}");
3773 }
3774 
TEST_F(ValidationErrorTest,PackageOriginallyDeclaredInTransitiveDependent)3775 TEST_F(ValidationErrorTest, PackageOriginallyDeclaredInTransitiveDependent) {
3776   // Imagine we have the following:
3777   //
3778   // foo.proto:
3779   //   package foo.bar;
3780   // bar.proto:
3781   //   package foo.bar;
3782   //   import "foo.proto";
3783   //   message Bar {}
3784   // baz.proto:
3785   //   package foo;
3786   //   import "bar.proto"
3787   //   message Baz { optional bar.Bar qux = 1; }
3788   //
3789   // When validating baz.proto, we will look up "bar.Bar".  As part of this
3790   // lookup, we first lookup "bar" then try to find "Bar" within it.  "bar"
3791   // should resolve to "foo.bar".  Note, though, that "foo.bar" was originally
3792   // defined in foo.proto, which is not a direct dependency of baz.proto.  The
3793   // implementation of FindSymbol() normally only returns symbols in direct
3794   // dependencies, not indirect ones.  This test insures that this does not
3795   // prevent it from finding "foo.bar".
3796 
3797   BuildFile(
3798     "name: \"foo.proto\" "
3799     "package: \"foo.bar\" ");
3800   BuildFile(
3801     "name: \"bar.proto\" "
3802     "package: \"foo.bar\" "
3803     "dependency: \"foo.proto\" "
3804     "message_type { name: \"Bar\" }");
3805   BuildFile(
3806     "name: \"baz.proto\" "
3807     "package: \"foo\" "
3808     "dependency: \"bar.proto\" "
3809     "message_type { "
3810     "  name: \"Baz\" "
3811     "  field { name:\"qux\" number:1 label:LABEL_OPTIONAL "
3812     "          type_name:\"bar.Bar\" }"
3813     "}");
3814 }
3815 
TEST_F(ValidationErrorTest,FieldTypeNotAType)3816 TEST_F(ValidationErrorTest, FieldTypeNotAType) {
3817   BuildFileWithErrors(
3818     "name: \"foo.proto\" "
3819     "message_type {"
3820     "  name: \"Foo\""
3821     "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL "
3822     "          type_name:\".Foo.bar\" }"
3823     "  field { name:\"bar\" number:2 label:LABEL_OPTIONAL type:TYPE_INT32 }"
3824     "}",
3825 
3826     "foo.proto: Foo.foo: TYPE: \".Foo.bar\" is not a type.\n");
3827 }
3828 
TEST_F(ValidationErrorTest,RelativeFieldTypeNotAType)3829 TEST_F(ValidationErrorTest, RelativeFieldTypeNotAType) {
3830   BuildFileWithErrors(
3831     "name: \"foo.proto\" "
3832     "message_type {"
3833     "  nested_type {"
3834     "    name: \"Bar\""
3835     "    field { name:\"Baz\" number:2 label:LABEL_OPTIONAL type:TYPE_INT32 }"
3836     "  }"
3837     "  name: \"Foo\""
3838     "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL "
3839     "          type_name:\"Bar.Baz\" }"
3840     "}",
3841     "foo.proto: Foo.foo: TYPE: \"Bar.Baz\" is not a type.\n");
3842 }
3843 
TEST_F(ValidationErrorTest,FieldTypeMayBeItsName)3844 TEST_F(ValidationErrorTest, FieldTypeMayBeItsName) {
3845   BuildFile(
3846     "name: \"foo.proto\" "
3847     "message_type {"
3848     "  name: \"Bar\""
3849     "}"
3850     "message_type {"
3851     "  name: \"Foo\""
3852     "  field { name:\"Bar\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }"
3853     "}");
3854 }
3855 
TEST_F(ValidationErrorTest,EnumFieldTypeIsMessage)3856 TEST_F(ValidationErrorTest, EnumFieldTypeIsMessage) {
3857   BuildFileWithErrors(
3858     "name: \"foo.proto\" "
3859     "message_type { name: \"Bar\" } "
3860     "message_type {"
3861     "  name: \"Foo\""
3862     "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_ENUM"
3863     "          type_name:\"Bar\" }"
3864     "}",
3865 
3866     "foo.proto: Foo.foo: TYPE: \"Bar\" is not an enum type.\n");
3867 }
3868 
TEST_F(ValidationErrorTest,MessageFieldTypeIsEnum)3869 TEST_F(ValidationErrorTest, MessageFieldTypeIsEnum) {
3870   BuildFileWithErrors(
3871     "name: \"foo.proto\" "
3872     "enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } } "
3873     "message_type {"
3874     "  name: \"Foo\""
3875     "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_MESSAGE"
3876     "          type_name:\"Bar\" }"
3877     "}",
3878 
3879     "foo.proto: Foo.foo: TYPE: \"Bar\" is not a message type.\n");
3880 }
3881 
TEST_F(ValidationErrorTest,BadEnumDefaultValue)3882 TEST_F(ValidationErrorTest, BadEnumDefaultValue) {
3883   BuildFileWithErrors(
3884     "name: \"foo.proto\" "
3885     "enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } } "
3886     "message_type {"
3887     "  name: \"Foo\""
3888     "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\""
3889     "          default_value:\"NO_SUCH_VALUE\" }"
3890     "}",
3891 
3892     "foo.proto: Foo.foo: DEFAULT_VALUE: Enum type \"Bar\" has no value named "
3893       "\"NO_SUCH_VALUE\".\n");
3894 }
3895 
TEST_F(ValidationErrorTest,EnumDefaultValueIsInteger)3896 TEST_F(ValidationErrorTest, EnumDefaultValueIsInteger) {
3897   BuildFileWithErrors(
3898     "name: \"foo.proto\" "
3899     "enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } } "
3900     "message_type {"
3901     "  name: \"Foo\""
3902     "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\""
3903     "          default_value:\"0\" }"
3904     "}",
3905 
3906     "foo.proto: Foo.foo: DEFAULT_VALUE: Default value for an enum field must "
3907     "be an identifier.\n");
3908 }
3909 
TEST_F(ValidationErrorTest,PrimitiveWithTypeName)3910 TEST_F(ValidationErrorTest, PrimitiveWithTypeName) {
3911   BuildFileWithErrors(
3912     "name: \"foo.proto\" "
3913     "message_type {"
3914     "  name: \"Foo\""
3915     "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32"
3916     "          type_name:\"Foo\" }"
3917     "}",
3918 
3919     "foo.proto: Foo.foo: TYPE: Field with primitive type has type_name.\n");
3920 }
3921 
TEST_F(ValidationErrorTest,NonPrimitiveWithoutTypeName)3922 TEST_F(ValidationErrorTest, NonPrimitiveWithoutTypeName) {
3923   BuildFileWithErrors(
3924     "name: \"foo.proto\" "
3925     "message_type {"
3926     "  name: \"Foo\""
3927     "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_MESSAGE }"
3928     "}",
3929 
3930     "foo.proto: Foo.foo: TYPE: Field with message or enum type missing "
3931       "type_name.\n");
3932 }
3933 
TEST_F(ValidationErrorTest,OneofWithNoFields)3934 TEST_F(ValidationErrorTest, OneofWithNoFields) {
3935   BuildFileWithErrors(
3936     "name: \"foo.proto\" "
3937     "message_type {"
3938     "  name: \"Foo\""
3939     "  oneof_decl { name:\"bar\" }"
3940     "}",
3941 
3942     "foo.proto: Foo.bar: NAME: Oneof must have at least one field.\n");
3943 }
3944 
TEST_F(ValidationErrorTest,OneofLabelMismatch)3945 TEST_F(ValidationErrorTest, OneofLabelMismatch) {
3946   BuildFileWithErrors(
3947     "name: \"foo.proto\" "
3948     "message_type {"
3949     "  name: \"Foo\""
3950     "  field { name:\"foo\" number:1 label:LABEL_REPEATED type:TYPE_INT32 "
3951     "          oneof_index:0 }"
3952     "  oneof_decl { name:\"bar\" }"
3953     "}",
3954 
3955     "foo.proto: Foo.foo: NAME: Fields of oneofs must themselves have label "
3956       "LABEL_OPTIONAL.\n");
3957 }
3958 
TEST_F(ValidationErrorTest,InputTypeNotDefined)3959 TEST_F(ValidationErrorTest, InputTypeNotDefined) {
3960   BuildFileWithErrors(
3961     "name: \"foo.proto\" "
3962     "message_type { name: \"Foo\" } "
3963     "service {"
3964     "  name: \"TestService\""
3965     "  method { name: \"A\" input_type: \"Bar\" output_type: \"Foo\" }"
3966     "}",
3967 
3968     "foo.proto: TestService.A: INPUT_TYPE: \"Bar\" is not defined.\n"
3969     );
3970 }
3971 
TEST_F(ValidationErrorTest,InputTypeNotAMessage)3972 TEST_F(ValidationErrorTest, InputTypeNotAMessage) {
3973   BuildFileWithErrors(
3974     "name: \"foo.proto\" "
3975     "message_type { name: \"Foo\" } "
3976     "enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } } "
3977     "service {"
3978     "  name: \"TestService\""
3979     "  method { name: \"A\" input_type: \"Bar\" output_type: \"Foo\" }"
3980     "}",
3981 
3982     "foo.proto: TestService.A: INPUT_TYPE: \"Bar\" is not a message type.\n"
3983     );
3984 }
3985 
TEST_F(ValidationErrorTest,OutputTypeNotDefined)3986 TEST_F(ValidationErrorTest, OutputTypeNotDefined) {
3987   BuildFileWithErrors(
3988     "name: \"foo.proto\" "
3989     "message_type { name: \"Foo\" } "
3990     "service {"
3991     "  name: \"TestService\""
3992     "  method { name: \"A\" input_type: \"Foo\" output_type: \"Bar\" }"
3993     "}",
3994 
3995     "foo.proto: TestService.A: OUTPUT_TYPE: \"Bar\" is not defined.\n"
3996     );
3997 }
3998 
TEST_F(ValidationErrorTest,OutputTypeNotAMessage)3999 TEST_F(ValidationErrorTest, OutputTypeNotAMessage) {
4000   BuildFileWithErrors(
4001     "name: \"foo.proto\" "
4002     "message_type { name: \"Foo\" } "
4003     "enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } } "
4004     "service {"
4005     "  name: \"TestService\""
4006     "  method { name: \"A\" input_type: \"Foo\" output_type: \"Bar\" }"
4007     "}",
4008 
4009     "foo.proto: TestService.A: OUTPUT_TYPE: \"Bar\" is not a message type.\n"
4010     );
4011 }
4012 
4013 
TEST_F(ValidationErrorTest,IllegalPackedField)4014 TEST_F(ValidationErrorTest, IllegalPackedField) {
4015   BuildFileWithErrors(
4016     "name: \"foo.proto\" "
4017     "message_type {\n"
4018     "  name: \"Foo\""
4019     "  field { name:\"packed_string\" number:1 label:LABEL_REPEATED "
4020     "          type:TYPE_STRING "
4021     "          options { uninterpreted_option {"
4022     "            name { name_part: \"packed\" is_extension: false }"
4023     "            identifier_value: \"true\" }}}\n"
4024     "  field { name:\"packed_message\" number:3 label:LABEL_REPEATED "
4025     "          type_name: \"Foo\""
4026     "          options { uninterpreted_option {"
4027     "            name { name_part: \"packed\" is_extension: false }"
4028     "            identifier_value: \"true\" }}}\n"
4029     "  field { name:\"optional_int32\" number: 4 label: LABEL_OPTIONAL "
4030     "          type:TYPE_INT32 "
4031     "          options { uninterpreted_option {"
4032     "            name { name_part: \"packed\" is_extension: false }"
4033     "            identifier_value: \"true\" }}}\n"
4034     "}",
4035 
4036     "foo.proto: Foo.packed_string: TYPE: [packed = true] can only be "
4037         "specified for repeated primitive fields.\n"
4038     "foo.proto: Foo.packed_message: TYPE: [packed = true] can only be "
4039         "specified for repeated primitive fields.\n"
4040     "foo.proto: Foo.optional_int32: TYPE: [packed = true] can only be "
4041         "specified for repeated primitive fields.\n"
4042         );
4043 }
4044 
TEST_F(ValidationErrorTest,OptionWrongType)4045 TEST_F(ValidationErrorTest, OptionWrongType) {
4046   BuildFileWithErrors(
4047     "name: \"foo.proto\" "
4048     "message_type { "
4049     "  name: \"TestMessage\" "
4050     "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_STRING "
4051     "          options { uninterpreted_option { name { name_part: \"ctype\" "
4052     "                                                  is_extension: false }"
4053     "                                           positive_int_value: 1 }"
4054     "          }"
4055     "  }"
4056     "}\n",
4057 
4058     "foo.proto: TestMessage.foo: OPTION_VALUE: Value must be identifier for "
4059     "enum-valued option \"google.protobuf.FieldOptions.ctype\".\n");
4060 }
4061 
TEST_F(ValidationErrorTest,OptionExtendsAtomicType)4062 TEST_F(ValidationErrorTest, OptionExtendsAtomicType) {
4063   BuildFileWithErrors(
4064     "name: \"foo.proto\" "
4065     "message_type { "
4066     "  name: \"TestMessage\" "
4067     "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_STRING "
4068     "          options { uninterpreted_option { name { name_part: \"ctype\" "
4069     "                                                  is_extension: false }"
4070     "                                           name { name_part: \"foo\" "
4071     "                                                  is_extension: true }"
4072     "                                           positive_int_value: 1 }"
4073     "          }"
4074     "  }"
4075     "}\n",
4076 
4077     "foo.proto: TestMessage.foo: OPTION_NAME: Option \"ctype\" is an "
4078     "atomic type, not a message.\n");
4079 }
4080 
TEST_F(ValidationErrorTest,DupOption)4081 TEST_F(ValidationErrorTest, DupOption) {
4082   BuildFileWithErrors(
4083     "name: \"foo.proto\" "
4084     "message_type { "
4085     "  name: \"TestMessage\" "
4086     "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_UINT32 "
4087     "          options { uninterpreted_option { name { name_part: \"ctype\" "
4088     "                                                  is_extension: false }"
4089     "                                           identifier_value: \"CORD\" }"
4090     "                    uninterpreted_option { name { name_part: \"ctype\" "
4091     "                                                  is_extension: false }"
4092     "                                           identifier_value: \"CORD\" }"
4093     "          }"
4094     "  }"
4095     "}\n",
4096 
4097     "foo.proto: TestMessage.foo: OPTION_NAME: Option \"ctype\" was "
4098     "already set.\n");
4099 }
4100 
TEST_F(ValidationErrorTest,InvalidOptionName)4101 TEST_F(ValidationErrorTest, InvalidOptionName) {
4102   BuildFileWithErrors(
4103     "name: \"foo.proto\" "
4104     "message_type { "
4105     "  name: \"TestMessage\" "
4106     "  field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_BOOL "
4107     "          options { uninterpreted_option { "
4108     "                      name { name_part: \"uninterpreted_option\" "
4109     "                             is_extension: false }"
4110     "                      positive_int_value: 1 "
4111     "                    }"
4112     "          }"
4113     "  }"
4114     "}\n",
4115 
4116     "foo.proto: TestMessage.foo: OPTION_NAME: Option must not use "
4117     "reserved name \"uninterpreted_option\".\n");
4118 }
4119 
TEST_F(ValidationErrorTest,RepeatedMessageOption)4120 TEST_F(ValidationErrorTest, RepeatedMessageOption) {
4121   BuildDescriptorMessagesInTestPool();
4122 
4123   BuildFileWithErrors(
4124     "name: \"foo.proto\" "
4125     "dependency: \"google/protobuf/descriptor.proto\" "
4126     "message_type: { name: \"Bar\" field: { "
4127     "  name: \"foo\" number: 1 label: LABEL_OPTIONAL type: TYPE_INT32 } "
4128     "} "
4129     "extension { name: \"bar\" number: 7672757 label: LABEL_REPEATED "
4130     "            type: TYPE_MESSAGE type_name: \"Bar\" "
4131     "            extendee: \"google.protobuf.FileOptions\" }"
4132     "options { uninterpreted_option { name { name_part: \"bar\" "
4133     "                                        is_extension: true } "
4134     "                                 name { name_part: \"foo\" "
4135     "                                        is_extension: false } "
4136     "                                 positive_int_value: 1 } }",
4137 
4138     "foo.proto: foo.proto: OPTION_NAME: Option field \"(bar)\" is a "
4139     "repeated message. Repeated message options must be initialized "
4140     "using an aggregate value.\n");
4141 }
4142 
TEST_F(ValidationErrorTest,ResolveUndefinedOption)4143 TEST_F(ValidationErrorTest, ResolveUndefinedOption) {
4144   // The following should produce an eror that baz.bar is resolved but not
4145   // defined.
4146   // foo.proto:
4147   //   package baz
4148   //   import google/protobuf/descriptor.proto
4149   //   message Bar { optional int32 foo = 1; }
4150   //   extend FileOptions { optional Bar bar = 7672757; }
4151   //
4152   // qux.proto:
4153   //   package qux.baz
4154   //   option (baz.bar).foo = 1;
4155   //
4156   // Although "baz.bar" is already defined, the lookup code will try
4157   // "qux.baz.bar", since it's the match from the innermost scope, which will
4158   // cause a symbol not defined error.
4159   BuildDescriptorMessagesInTestPool();
4160 
4161   BuildFile(
4162     "name: \"foo.proto\" "
4163     "package: \"baz\" "
4164     "dependency: \"google/protobuf/descriptor.proto\" "
4165     "message_type: { name: \"Bar\" field: { "
4166     "  name: \"foo\" number: 1 label: LABEL_OPTIONAL type: TYPE_INT32 } "
4167     "} "
4168     "extension { name: \"bar\" number: 7672757 label: LABEL_OPTIONAL "
4169     "            type: TYPE_MESSAGE type_name: \"Bar\" "
4170     "            extendee: \"google.protobuf.FileOptions\" }");
4171 
4172   BuildFileWithErrors(
4173     "name: \"qux.proto\" "
4174     "package: \"qux.baz\" "
4175     "options { uninterpreted_option { name { name_part: \"baz.bar\" "
4176     "                                        is_extension: true } "
4177     "                                 name { name_part: \"foo\" "
4178     "                                        is_extension: false } "
4179     "                                 positive_int_value: 1 } }",
4180 
4181     "qux.proto: qux.proto: OPTION_NAME: Option \"(baz.bar)\" is resolved to "
4182     "\"(qux.baz.bar)\","
4183     " which is not defined. The innermost scope is searched first in name "
4184     "resolution. Consider using a leading '.'(i.e., \"(.baz.bar)\") to start "
4185     "from the outermost scope.\n");
4186 }
4187 
TEST_F(ValidationErrorTest,UnknownOption)4188 TEST_F(ValidationErrorTest, UnknownOption) {
4189   BuildFileWithErrors(
4190     "name: \"qux.proto\" "
4191     "package: \"qux.baz\" "
4192     "options { uninterpreted_option { name { name_part: \"baaz.bar\" "
4193     "                                        is_extension: true } "
4194     "                                 name { name_part: \"foo\" "
4195     "                                        is_extension: false } "
4196     "                                 positive_int_value: 1 } }",
4197 
4198     "qux.proto: qux.proto: OPTION_NAME: Option \"(baaz.bar)\" unknown.\n");
4199 }
4200 
TEST_F(ValidationErrorTest,CustomOptionConflictingFieldNumber)4201 TEST_F(ValidationErrorTest, CustomOptionConflictingFieldNumber) {
4202   BuildDescriptorMessagesInTestPool();
4203 
4204   BuildFileWithErrors(
4205     "name: \"foo.proto\" "
4206     "dependency: \"google/protobuf/descriptor.proto\" "
4207     "extension { name: \"foo1\" number: 7672757 label: LABEL_OPTIONAL "
4208     "            type: TYPE_INT32 extendee: \"google.protobuf.FieldOptions\" }"
4209     "extension { name: \"foo2\" number: 7672757 label: LABEL_OPTIONAL "
4210     "            type: TYPE_INT32 extendee: \"google.protobuf.FieldOptions\" }",
4211 
4212     "foo.proto: foo2: NUMBER: Extension number 7672757 has already been used "
4213     "in \"google.protobuf.FieldOptions\" by extension \"foo1\".\n");
4214 }
4215 
TEST_F(ValidationErrorTest,Int32OptionValueOutOfPositiveRange)4216 TEST_F(ValidationErrorTest, Int32OptionValueOutOfPositiveRange) {
4217   BuildDescriptorMessagesInTestPool();
4218 
4219   BuildFileWithErrors(
4220     "name: \"foo.proto\" "
4221     "dependency: \"google/protobuf/descriptor.proto\" "
4222     "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
4223     "            type: TYPE_INT32 extendee: \"google.protobuf.FileOptions\" }"
4224     "options { uninterpreted_option { name { name_part: \"foo\" "
4225     "                                        is_extension: true } "
4226     "                                 positive_int_value: 0x80000000 } "
4227     "}",
4228 
4229     "foo.proto: foo.proto: OPTION_VALUE: Value out of range "
4230     "for int32 option \"foo\".\n");
4231 }
4232 
TEST_F(ValidationErrorTest,Int32OptionValueOutOfNegativeRange)4233 TEST_F(ValidationErrorTest, Int32OptionValueOutOfNegativeRange) {
4234   BuildDescriptorMessagesInTestPool();
4235 
4236   BuildFileWithErrors(
4237     "name: \"foo.proto\" "
4238     "dependency: \"google/protobuf/descriptor.proto\" "
4239     "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
4240     "            type: TYPE_INT32 extendee: \"google.protobuf.FileOptions\" }"
4241     "options { uninterpreted_option { name { name_part: \"foo\" "
4242     "                                        is_extension: true } "
4243     "                                 negative_int_value: -0x80000001 } "
4244     "}",
4245 
4246     "foo.proto: foo.proto: OPTION_VALUE: Value out of range "
4247     "for int32 option \"foo\".\n");
4248 }
4249 
TEST_F(ValidationErrorTest,Int32OptionValueIsNotPositiveInt)4250 TEST_F(ValidationErrorTest, Int32OptionValueIsNotPositiveInt) {
4251   BuildDescriptorMessagesInTestPool();
4252 
4253   BuildFileWithErrors(
4254     "name: \"foo.proto\" "
4255     "dependency: \"google/protobuf/descriptor.proto\" "
4256     "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
4257     "            type: TYPE_INT32 extendee: \"google.protobuf.FileOptions\" }"
4258     "options { uninterpreted_option { name { name_part: \"foo\" "
4259     "                                        is_extension: true } "
4260     "                                 string_value: \"5\" } }",
4261 
4262     "foo.proto: foo.proto: OPTION_VALUE: Value must be integer "
4263     "for int32 option \"foo\".\n");
4264 }
4265 
TEST_F(ValidationErrorTest,Int64OptionValueOutOfRange)4266 TEST_F(ValidationErrorTest, Int64OptionValueOutOfRange) {
4267   BuildDescriptorMessagesInTestPool();
4268 
4269   BuildFileWithErrors(
4270     "name: \"foo.proto\" "
4271     "dependency: \"google/protobuf/descriptor.proto\" "
4272     "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
4273     "            type: TYPE_INT64 extendee: \"google.protobuf.FileOptions\" }"
4274     "options { uninterpreted_option { name { name_part: \"foo\" "
4275     "                                        is_extension: true } "
4276     "                                 positive_int_value: 0x8000000000000000 } "
4277     "}",
4278 
4279     "foo.proto: foo.proto: OPTION_VALUE: Value out of range "
4280     "for int64 option \"foo\".\n");
4281 }
4282 
TEST_F(ValidationErrorTest,Int64OptionValueIsNotPositiveInt)4283 TEST_F(ValidationErrorTest, Int64OptionValueIsNotPositiveInt) {
4284   BuildDescriptorMessagesInTestPool();
4285 
4286   BuildFileWithErrors(
4287     "name: \"foo.proto\" "
4288     "dependency: \"google/protobuf/descriptor.proto\" "
4289     "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
4290     "            type: TYPE_INT64 extendee: \"google.protobuf.FileOptions\" }"
4291     "options { uninterpreted_option { name { name_part: \"foo\" "
4292     "                                        is_extension: true } "
4293     "                                 identifier_value: \"5\" } }",
4294 
4295     "foo.proto: foo.proto: OPTION_VALUE: Value must be integer "
4296     "for int64 option \"foo\".\n");
4297 }
4298 
TEST_F(ValidationErrorTest,UInt32OptionValueOutOfRange)4299 TEST_F(ValidationErrorTest, UInt32OptionValueOutOfRange) {
4300   BuildDescriptorMessagesInTestPool();
4301 
4302   BuildFileWithErrors(
4303     "name: \"foo.proto\" "
4304     "dependency: \"google/protobuf/descriptor.proto\" "
4305     "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
4306     "            type: TYPE_UINT32 extendee: \"google.protobuf.FileOptions\" }"
4307     "options { uninterpreted_option { name { name_part: \"foo\" "
4308     "                                        is_extension: true } "
4309     "                                 positive_int_value: 0x100000000 } }",
4310 
4311     "foo.proto: foo.proto: OPTION_VALUE: Value out of range "
4312     "for uint32 option \"foo\".\n");
4313 }
4314 
TEST_F(ValidationErrorTest,UInt32OptionValueIsNotPositiveInt)4315 TEST_F(ValidationErrorTest, UInt32OptionValueIsNotPositiveInt) {
4316   BuildDescriptorMessagesInTestPool();
4317 
4318   BuildFileWithErrors(
4319     "name: \"foo.proto\" "
4320     "dependency: \"google/protobuf/descriptor.proto\" "
4321     "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
4322     "            type: TYPE_UINT32 extendee: \"google.protobuf.FileOptions\" }"
4323     "options { uninterpreted_option { name { name_part: \"foo\" "
4324     "                                        is_extension: true } "
4325     "                                 double_value: -5.6 } }",
4326 
4327     "foo.proto: foo.proto: OPTION_VALUE: Value must be non-negative integer "
4328     "for uint32 option \"foo\".\n");
4329 }
4330 
TEST_F(ValidationErrorTest,UInt64OptionValueIsNotPositiveInt)4331 TEST_F(ValidationErrorTest, UInt64OptionValueIsNotPositiveInt) {
4332   BuildDescriptorMessagesInTestPool();
4333 
4334   BuildFileWithErrors(
4335     "name: \"foo.proto\" "
4336     "dependency: \"google/protobuf/descriptor.proto\" "
4337     "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
4338     "            type: TYPE_UINT64 extendee: \"google.protobuf.FileOptions\" }"
4339     "options { uninterpreted_option { name { name_part: \"foo\" "
4340     "                                        is_extension: true } "
4341     "                                 negative_int_value: -5 } }",
4342 
4343     "foo.proto: foo.proto: OPTION_VALUE: Value must be non-negative integer "
4344     "for uint64 option \"foo\".\n");
4345 }
4346 
TEST_F(ValidationErrorTest,FloatOptionValueIsNotNumber)4347 TEST_F(ValidationErrorTest, FloatOptionValueIsNotNumber) {
4348   BuildDescriptorMessagesInTestPool();
4349 
4350   BuildFileWithErrors(
4351     "name: \"foo.proto\" "
4352     "dependency: \"google/protobuf/descriptor.proto\" "
4353     "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
4354     "            type: TYPE_FLOAT extendee: \"google.protobuf.FileOptions\" }"
4355     "options { uninterpreted_option { name { name_part: \"foo\" "
4356     "                                        is_extension: true } "
4357     "                                 string_value: \"bar\" } }",
4358 
4359     "foo.proto: foo.proto: OPTION_VALUE: Value must be number "
4360     "for float option \"foo\".\n");
4361 }
4362 
TEST_F(ValidationErrorTest,DoubleOptionValueIsNotNumber)4363 TEST_F(ValidationErrorTest, DoubleOptionValueIsNotNumber) {
4364   BuildDescriptorMessagesInTestPool();
4365 
4366   BuildFileWithErrors(
4367     "name: \"foo.proto\" "
4368     "dependency: \"google/protobuf/descriptor.proto\" "
4369     "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
4370     "            type: TYPE_DOUBLE extendee: \"google.protobuf.FileOptions\" }"
4371     "options { uninterpreted_option { name { name_part: \"foo\" "
4372     "                                        is_extension: true } "
4373     "                                 string_value: \"bar\" } }",
4374 
4375     "foo.proto: foo.proto: OPTION_VALUE: Value must be number "
4376     "for double option \"foo\".\n");
4377 }
4378 
TEST_F(ValidationErrorTest,BoolOptionValueIsNotTrueOrFalse)4379 TEST_F(ValidationErrorTest, BoolOptionValueIsNotTrueOrFalse) {
4380   BuildDescriptorMessagesInTestPool();
4381 
4382   BuildFileWithErrors(
4383     "name: \"foo.proto\" "
4384     "dependency: \"google/protobuf/descriptor.proto\" "
4385     "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
4386     "            type: TYPE_BOOL extendee: \"google.protobuf.FileOptions\" }"
4387     "options { uninterpreted_option { name { name_part: \"foo\" "
4388     "                                        is_extension: true } "
4389     "                                 identifier_value: \"bar\" } }",
4390 
4391     "foo.proto: foo.proto: OPTION_VALUE: Value must be \"true\" or \"false\" "
4392     "for boolean option \"foo\".\n");
4393 }
4394 
TEST_F(ValidationErrorTest,EnumOptionValueIsNotIdentifier)4395 TEST_F(ValidationErrorTest, EnumOptionValueIsNotIdentifier) {
4396   BuildDescriptorMessagesInTestPool();
4397 
4398   BuildFileWithErrors(
4399     "name: \"foo.proto\" "
4400     "dependency: \"google/protobuf/descriptor.proto\" "
4401     "enum_type { name: \"FooEnum\" value { name: \"BAR\" number: 1 } "
4402     "                              value { name: \"BAZ\" number: 2 } }"
4403     "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
4404     "            type: TYPE_ENUM type_name: \"FooEnum\" "
4405     "            extendee: \"google.protobuf.FileOptions\" }"
4406     "options { uninterpreted_option { name { name_part: \"foo\" "
4407     "                                        is_extension: true } "
4408     "                                 string_value: \"QUUX\" } }",
4409 
4410     "foo.proto: foo.proto: OPTION_VALUE: Value must be identifier for "
4411     "enum-valued option \"foo\".\n");
4412 }
4413 
TEST_F(ValidationErrorTest,EnumOptionValueIsNotEnumValueName)4414 TEST_F(ValidationErrorTest, EnumOptionValueIsNotEnumValueName) {
4415   BuildDescriptorMessagesInTestPool();
4416 
4417   BuildFileWithErrors(
4418     "name: \"foo.proto\" "
4419     "dependency: \"google/protobuf/descriptor.proto\" "
4420     "enum_type { name: \"FooEnum\" value { name: \"BAR\" number: 1 } "
4421     "                              value { name: \"BAZ\" number: 2 } }"
4422     "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
4423     "            type: TYPE_ENUM type_name: \"FooEnum\" "
4424     "            extendee: \"google.protobuf.FileOptions\" }"
4425     "options { uninterpreted_option { name { name_part: \"foo\" "
4426     "                                        is_extension: true } "
4427     "                                 identifier_value: \"QUUX\" } }",
4428 
4429     "foo.proto: foo.proto: OPTION_VALUE: Enum type \"FooEnum\" has no value "
4430     "named \"QUUX\" for option \"foo\".\n");
4431 }
4432 
TEST_F(ValidationErrorTest,EnumOptionValueIsSiblingEnumValueName)4433 TEST_F(ValidationErrorTest, EnumOptionValueIsSiblingEnumValueName) {
4434   BuildDescriptorMessagesInTestPool();
4435 
4436   BuildFileWithErrors(
4437     "name: \"foo.proto\" "
4438     "dependency: \"google/protobuf/descriptor.proto\" "
4439     "enum_type { name: \"FooEnum1\" value { name: \"BAR\" number: 1 } "
4440     "                               value { name: \"BAZ\" number: 2 } }"
4441     "enum_type { name: \"FooEnum2\" value { name: \"QUX\" number: 1 } "
4442     "                               value { name: \"QUUX\" number: 2 } }"
4443     "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
4444     "            type: TYPE_ENUM type_name: \"FooEnum1\" "
4445     "            extendee: \"google.protobuf.FileOptions\" }"
4446     "options { uninterpreted_option { name { name_part: \"foo\" "
4447     "                                        is_extension: true } "
4448     "                                 identifier_value: \"QUUX\" } }",
4449 
4450     "foo.proto: foo.proto: OPTION_VALUE: Enum type \"FooEnum1\" has no value "
4451     "named \"QUUX\" for option \"foo\". This appears to be a value from a "
4452     "sibling type.\n");
4453 }
4454 
TEST_F(ValidationErrorTest,StringOptionValueIsNotString)4455 TEST_F(ValidationErrorTest, StringOptionValueIsNotString) {
4456   BuildDescriptorMessagesInTestPool();
4457 
4458   BuildFileWithErrors(
4459     "name: \"foo.proto\" "
4460     "dependency: \"google/protobuf/descriptor.proto\" "
4461     "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
4462     "            type: TYPE_STRING extendee: \"google.protobuf.FileOptions\" }"
4463     "options { uninterpreted_option { name { name_part: \"foo\" "
4464     "                                        is_extension: true } "
4465     "                                 identifier_value: \"QUUX\" } }",
4466 
4467     "foo.proto: foo.proto: OPTION_VALUE: Value must be quoted string for "
4468     "string option \"foo\".\n");
4469 }
4470 
TEST_F(ValidationErrorTest,DuplicateExtensionFieldNumber)4471 TEST_F(ValidationErrorTest, DuplicateExtensionFieldNumber) {
4472   BuildDescriptorMessagesInTestPool();
4473 
4474   BuildFile(
4475       "name: \"foo.proto\" "
4476       "dependency: \"google/protobuf/descriptor.proto\" "
4477       "extension { name: \"option1\" number: 1000 label: LABEL_OPTIONAL "
4478       "            type: TYPE_INT32 extendee: \"google.protobuf.FileOptions\" }");
4479 
4480   BuildFileWithWarnings(
4481       "name: \"bar.proto\" "
4482       "dependency: \"google/protobuf/descriptor.proto\" "
4483       "extension { name: \"option2\" number: 1000 label: LABEL_OPTIONAL "
4484       "            type: TYPE_INT32 extendee: \"google.protobuf.FileOptions\" }",
4485       "bar.proto: option2: NUMBER: Extension number 1000 has already been used "
4486       "in \"google.protobuf.FileOptions\" by extension \"option1\" defined in "
4487       "foo.proto.\n");
4488 }
4489 
4490 // Helper function for tests that check for aggregate value parsing
4491 // errors.  The "value" argument is embedded inside the
4492 // "uninterpreted_option" portion of the result.
EmbedAggregateValue(const char * value)4493 static string EmbedAggregateValue(const char* value) {
4494   return strings::Substitute(
4495       "name: \"foo.proto\" "
4496       "dependency: \"google/protobuf/descriptor.proto\" "
4497       "message_type { name: \"Foo\" } "
4498       "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
4499       "            type: TYPE_MESSAGE type_name: \"Foo\" "
4500       "            extendee: \"google.protobuf.FileOptions\" }"
4501       "options { uninterpreted_option { name { name_part: \"foo\" "
4502       "                                        is_extension: true } "
4503       "                                 $0 } }",
4504       value);
4505 }
4506 
TEST_F(ValidationErrorTest,AggregateValueNotFound)4507 TEST_F(ValidationErrorTest, AggregateValueNotFound) {
4508   BuildDescriptorMessagesInTestPool();
4509 
4510   BuildFileWithErrors(
4511       EmbedAggregateValue("string_value: \"\""),
4512       "foo.proto: foo.proto: OPTION_VALUE: Option \"foo\" is a message. "
4513       "To set the entire message, use syntax like "
4514       "\"foo = { <proto text format> }\". To set fields within it, use "
4515       "syntax like \"foo.foo = value\".\n");
4516 }
4517 
TEST_F(ValidationErrorTest,AggregateValueParseError)4518 TEST_F(ValidationErrorTest, AggregateValueParseError) {
4519   BuildDescriptorMessagesInTestPool();
4520 
4521   BuildFileWithErrors(
4522       EmbedAggregateValue("aggregate_value: \"1+2\""),
4523       "foo.proto: foo.proto: OPTION_VALUE: Error while parsing option "
4524       "value for \"foo\": Expected identifier.\n");
4525 }
4526 
TEST_F(ValidationErrorTest,AggregateValueUnknownFields)4527 TEST_F(ValidationErrorTest, AggregateValueUnknownFields) {
4528   BuildDescriptorMessagesInTestPool();
4529 
4530   BuildFileWithErrors(
4531       EmbedAggregateValue("aggregate_value: \"x:100\""),
4532       "foo.proto: foo.proto: OPTION_VALUE: Error while parsing option "
4533       "value for \"foo\": Message type \"Foo\" has no field named \"x\".\n");
4534 }
4535 
TEST_F(ValidationErrorTest,NotLiteImportsLite)4536 TEST_F(ValidationErrorTest, NotLiteImportsLite) {
4537   BuildFile(
4538     "name: \"bar.proto\" "
4539     "options { optimize_for: LITE_RUNTIME } ");
4540 
4541   BuildFileWithErrors(
4542     "name: \"foo.proto\" "
4543     "dependency: \"bar.proto\" ",
4544 
4545     "foo.proto: foo.proto: OTHER: Files that do not use optimize_for = "
4546       "LITE_RUNTIME cannot import files which do use this option.  This file "
4547       "is not lite, but it imports \"bar.proto\" which is.\n");
4548 }
4549 
TEST_F(ValidationErrorTest,LiteExtendsNotLite)4550 TEST_F(ValidationErrorTest, LiteExtendsNotLite) {
4551   BuildFile(
4552     "name: \"bar.proto\" "
4553     "message_type: {"
4554     "  name: \"Bar\""
4555     "  extension_range { start: 1 end: 1000 }"
4556     "}");
4557 
4558   BuildFileWithErrors(
4559     "name: \"foo.proto\" "
4560     "dependency: \"bar.proto\" "
4561     "options { optimize_for: LITE_RUNTIME } "
4562     "extension { name: \"ext\" number: 123 label: LABEL_OPTIONAL "
4563     "            type: TYPE_INT32 extendee: \"Bar\" }",
4564 
4565     "foo.proto: ext: EXTENDEE: Extensions to non-lite types can only be "
4566       "declared in non-lite files.  Note that you cannot extend a non-lite "
4567       "type to contain a lite type, but the reverse is allowed.\n");
4568 }
4569 
TEST_F(ValidationErrorTest,NoLiteServices)4570 TEST_F(ValidationErrorTest, NoLiteServices) {
4571   BuildFileWithErrors(
4572     "name: \"foo.proto\" "
4573     "options {"
4574     "  optimize_for: LITE_RUNTIME"
4575     "  cc_generic_services: true"
4576     "  java_generic_services: true"
4577     "} "
4578     "service { name: \"Foo\" }",
4579 
4580     "foo.proto: Foo: NAME: Files with optimize_for = LITE_RUNTIME cannot "
4581     "define services unless you set both options cc_generic_services and "
4582     "java_generic_sevices to false.\n");
4583 
4584   BuildFile(
4585     "name: \"bar.proto\" "
4586     "options {"
4587     "  optimize_for: LITE_RUNTIME"
4588     "  cc_generic_services: false"
4589     "  java_generic_services: false"
4590     "} "
4591     "service { name: \"Bar\" }");
4592 }
4593 
TEST_F(ValidationErrorTest,RollbackAfterError)4594 TEST_F(ValidationErrorTest, RollbackAfterError) {
4595   // Build a file which contains every kind of construct but references an
4596   // undefined type.  All these constructs will be added to the symbol table
4597   // before the undefined type error is noticed.  The DescriptorPool will then
4598   // have to roll everything back.
4599   BuildFileWithErrors(
4600     "name: \"foo.proto\" "
4601     "message_type {"
4602     "  name: \"TestMessage\""
4603     "  field { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:1 }"
4604     "} "
4605     "enum_type {"
4606     "  name: \"TestEnum\""
4607     "  value { name:\"BAR\" number:1 }"
4608     "} "
4609     "service {"
4610     "  name: \"TestService\""
4611     "  method {"
4612     "    name: \"Baz\""
4613     "    input_type: \"NoSuchType\""    // error
4614     "    output_type: \"TestMessage\""
4615     "  }"
4616     "}",
4617 
4618     "foo.proto: TestService.Baz: INPUT_TYPE: \"NoSuchType\" is not defined.\n"
4619     );
4620 
4621   // Make sure that if we build the same file again with the error fixed,
4622   // it works.  If the above rollback was incomplete, then some symbols will
4623   // be left defined, and this second attempt will fail since it tries to
4624   // re-define the same symbols.
4625   BuildFile(
4626     "name: \"foo.proto\" "
4627     "message_type {"
4628     "  name: \"TestMessage\""
4629     "  field { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:1 }"
4630     "} "
4631     "enum_type {"
4632     "  name: \"TestEnum\""
4633     "  value { name:\"BAR\" number:1 }"
4634     "} "
4635     "service {"
4636     "  name: \"TestService\""
4637     "  method { name:\"Baz\""
4638     "           input_type:\"TestMessage\""
4639     "           output_type:\"TestMessage\" }"
4640     "}");
4641 }
4642 
TEST_F(ValidationErrorTest,ErrorsReportedToLogError)4643 TEST_F(ValidationErrorTest, ErrorsReportedToLogError) {
4644   // Test that errors are reported to GOOGLE_LOG(ERROR) if no error collector is
4645   // provided.
4646 
4647   FileDescriptorProto file_proto;
4648   ASSERT_TRUE(TextFormat::ParseFromString(
4649     "name: \"foo.proto\" "
4650     "message_type { name: \"Foo\" } "
4651     "message_type { name: \"Foo\" } ",
4652     &file_proto));
4653 
4654   vector<string> errors;
4655 
4656   {
4657     ScopedMemoryLog log;
4658     EXPECT_TRUE(pool_.BuildFile(file_proto) == NULL);
4659     errors = log.GetMessages(ERROR);
4660   }
4661 
4662   ASSERT_EQ(2, errors.size());
4663 
4664   EXPECT_EQ("Invalid proto descriptor for file \"foo.proto\":", errors[0]);
4665   EXPECT_EQ("  Foo: \"Foo\" is already defined.", errors[1]);
4666 }
4667 
TEST_F(ValidationErrorTest,DisallowEnumAlias)4668 TEST_F(ValidationErrorTest, DisallowEnumAlias) {
4669   BuildFileWithErrors(
4670     "name: \"foo.proto\" "
4671     "enum_type {"
4672     "  name: \"Bar\""
4673     "  value { name:\"ENUM_A\" number:0 }"
4674     "  value { name:\"ENUM_B\" number:0 }"
4675     "}",
4676     "foo.proto: Bar: NUMBER: "
4677     "\"ENUM_B\" uses the same enum value as \"ENUM_A\". "
4678     "If this is intended, set 'option allow_alias = true;' to the enum "
4679     "definition.\n");
4680 }
4681 
TEST_F(ValidationErrorTest,AllowEnumAlias)4682 TEST_F(ValidationErrorTest, AllowEnumAlias) {
4683   BuildFile(
4684     "name: \"foo.proto\" "
4685     "enum_type {"
4686     "  name: \"Bar\""
4687     "  value { name:\"ENUM_A\" number:0 }"
4688     "  value { name:\"ENUM_B\" number:0 }"
4689     "  options { allow_alias: true }"
4690     "}");
4691 }
4692 
TEST_F(ValidationErrorTest,UnusedImportWarning)4693 TEST_F(ValidationErrorTest, UnusedImportWarning) {
4694 
4695   pool_.AddUnusedImportTrackFile("bar.proto");
4696   BuildFile(
4697     "name: \"bar.proto\" "
4698     "message_type { name: \"Bar\" }");
4699 
4700   pool_.AddUnusedImportTrackFile("base.proto");
4701   BuildFile(
4702     "name: \"base.proto\" "
4703     "message_type { name: \"Base\" }");
4704 
4705   pool_.AddUnusedImportTrackFile("baz.proto");
4706   BuildFile(
4707     "name: \"baz.proto\" "
4708     "message_type { name: \"Baz\" }");
4709 
4710   pool_.AddUnusedImportTrackFile("public.proto");
4711   BuildFile(
4712     "name: \"public.proto\" "
4713     "dependency: \"bar.proto\""
4714     "public_dependency: 0");
4715 
4716   // // forward.proto
4717   // import "base.proto"       // No warning: Base message is used.
4718   // import "bar.proto"        // Will log a warning.
4719   // import public "baz.proto" // No warning: Do not track import public.
4720   // import "public.proto"     // No warning: public.proto has import public.
4721   // message Forward {
4722   //   optional Base base = 1;
4723   // }
4724   //
4725   pool_.AddUnusedImportTrackFile("forward.proto");
4726   BuildFile(
4727     "name: \"forward.proto\""
4728     "dependency: \"base.proto\""
4729     "dependency: \"bar.proto\""
4730     "dependency: \"baz.proto\""
4731     "dependency: \"public.proto\""
4732     "public_dependency: 2 "
4733     "message_type {"
4734     "  name: \"Forward\""
4735     "  field { name:\"base\" number:1 label:LABEL_OPTIONAL type_name:\"Base\" }"
4736     "}");
4737 }
4738 
4739 
4740 // ===================================================================
4741 // DescriptorDatabase
4742 
AddToDatabase(SimpleDescriptorDatabase * database,const char * file_text)4743 static void AddToDatabase(SimpleDescriptorDatabase* database,
4744                           const char* file_text) {
4745   FileDescriptorProto file_proto;
4746   EXPECT_TRUE(TextFormat::ParseFromString(file_text, &file_proto));
4747   database->Add(file_proto);
4748 }
4749 
4750 class DatabaseBackedPoolTest : public testing::Test {
4751  protected:
DatabaseBackedPoolTest()4752   DatabaseBackedPoolTest() {}
4753 
4754   SimpleDescriptorDatabase database_;
4755 
SetUp()4756   virtual void SetUp() {
4757     AddToDatabase(&database_,
4758       "name: 'foo.proto' "
4759       "message_type { name:'Foo' extension_range { start: 1 end: 100 } } "
4760       "enum_type { name:'TestEnum' value { name:'DUMMY' number:0 } } "
4761       "service { name:'TestService' } ");
4762     AddToDatabase(&database_,
4763       "name: 'bar.proto' "
4764       "dependency: 'foo.proto' "
4765       "message_type { name:'Bar' } "
4766       "extension { name:'foo_ext' extendee: '.Foo' number:5 "
4767       "            label:LABEL_OPTIONAL type:TYPE_INT32 } ");
4768     // Baz has an undeclared dependency on Foo.
4769     AddToDatabase(&database_,
4770       "name: 'baz.proto' "
4771       "message_type { "
4772       "  name:'Baz' "
4773       "  field { name:'foo' number:1 label:LABEL_OPTIONAL type_name:'Foo' } "
4774       "}");
4775   }
4776 
4777   // We can't inject a file containing errors into a DescriptorPool, so we
4778   // need an actual mock DescriptorDatabase to test errors.
4779   class ErrorDescriptorDatabase : public DescriptorDatabase {
4780    public:
ErrorDescriptorDatabase()4781     ErrorDescriptorDatabase() {}
~ErrorDescriptorDatabase()4782     ~ErrorDescriptorDatabase() {}
4783 
4784     // implements DescriptorDatabase ---------------------------------
FindFileByName(const string & filename,FileDescriptorProto * output)4785     bool FindFileByName(const string& filename,
4786                         FileDescriptorProto* output) {
4787       // error.proto and error2.proto cyclically import each other.
4788       if (filename == "error.proto") {
4789         output->Clear();
4790         output->set_name("error.proto");
4791         output->add_dependency("error2.proto");
4792         return true;
4793       } else if (filename == "error2.proto") {
4794         output->Clear();
4795         output->set_name("error2.proto");
4796         output->add_dependency("error.proto");
4797         return true;
4798       } else {
4799         return false;
4800       }
4801     }
FindFileContainingSymbol(const string & symbol_name,FileDescriptorProto * output)4802     bool FindFileContainingSymbol(const string& symbol_name,
4803                                   FileDescriptorProto* output) {
4804       return false;
4805     }
FindFileContainingExtension(const string & containing_type,int field_number,FileDescriptorProto * output)4806     bool FindFileContainingExtension(const string& containing_type,
4807                                      int field_number,
4808                                      FileDescriptorProto* output) {
4809       return false;
4810     }
4811   };
4812 
4813   // A DescriptorDatabase that counts how many times each method has been
4814   // called and forwards to some other DescriptorDatabase.
4815   class CallCountingDatabase : public DescriptorDatabase {
4816    public:
CallCountingDatabase(DescriptorDatabase * wrapped_db)4817     CallCountingDatabase(DescriptorDatabase* wrapped_db)
4818       : wrapped_db_(wrapped_db) {
4819       Clear();
4820     }
~CallCountingDatabase()4821     ~CallCountingDatabase() {}
4822 
4823     DescriptorDatabase* wrapped_db_;
4824 
4825     int call_count_;
4826 
Clear()4827     void Clear() {
4828       call_count_ = 0;
4829     }
4830 
4831     // implements DescriptorDatabase ---------------------------------
FindFileByName(const string & filename,FileDescriptorProto * output)4832     bool FindFileByName(const string& filename,
4833                         FileDescriptorProto* output) {
4834       ++call_count_;
4835       return wrapped_db_->FindFileByName(filename, output);
4836     }
FindFileContainingSymbol(const string & symbol_name,FileDescriptorProto * output)4837     bool FindFileContainingSymbol(const string& symbol_name,
4838                                   FileDescriptorProto* output) {
4839       ++call_count_;
4840       return wrapped_db_->FindFileContainingSymbol(symbol_name, output);
4841     }
FindFileContainingExtension(const string & containing_type,int field_number,FileDescriptorProto * output)4842     bool FindFileContainingExtension(const string& containing_type,
4843                                      int field_number,
4844                                      FileDescriptorProto* output) {
4845       ++call_count_;
4846       return wrapped_db_->FindFileContainingExtension(
4847         containing_type, field_number, output);
4848     }
4849   };
4850 
4851   // A DescriptorDatabase which falsely always returns foo.proto when searching
4852   // for any symbol or extension number.  This shouldn't cause the
4853   // DescriptorPool to reload foo.proto if it is already loaded.
4854   class FalsePositiveDatabase : public DescriptorDatabase {
4855    public:
FalsePositiveDatabase(DescriptorDatabase * wrapped_db)4856     FalsePositiveDatabase(DescriptorDatabase* wrapped_db)
4857       : wrapped_db_(wrapped_db) {}
~FalsePositiveDatabase()4858     ~FalsePositiveDatabase() {}
4859 
4860     DescriptorDatabase* wrapped_db_;
4861 
4862     // implements DescriptorDatabase ---------------------------------
FindFileByName(const string & filename,FileDescriptorProto * output)4863     bool FindFileByName(const string& filename,
4864                         FileDescriptorProto* output) {
4865       return wrapped_db_->FindFileByName(filename, output);
4866     }
FindFileContainingSymbol(const string & symbol_name,FileDescriptorProto * output)4867     bool FindFileContainingSymbol(const string& symbol_name,
4868                                   FileDescriptorProto* output) {
4869       return FindFileByName("foo.proto", output);
4870     }
FindFileContainingExtension(const string & containing_type,int field_number,FileDescriptorProto * output)4871     bool FindFileContainingExtension(const string& containing_type,
4872                                      int field_number,
4873                                      FileDescriptorProto* output) {
4874       return FindFileByName("foo.proto", output);
4875     }
4876   };
4877 };
4878 
TEST_F(DatabaseBackedPoolTest,FindFileByName)4879 TEST_F(DatabaseBackedPoolTest, FindFileByName) {
4880   DescriptorPool pool(&database_);
4881 
4882   const FileDescriptor* foo = pool.FindFileByName("foo.proto");
4883   ASSERT_TRUE(foo != NULL);
4884   EXPECT_EQ("foo.proto", foo->name());
4885   ASSERT_EQ(1, foo->message_type_count());
4886   EXPECT_EQ("Foo", foo->message_type(0)->name());
4887 
4888   EXPECT_EQ(foo, pool.FindFileByName("foo.proto"));
4889 
4890   EXPECT_TRUE(pool.FindFileByName("no_such_file.proto") == NULL);
4891 }
4892 
TEST_F(DatabaseBackedPoolTest,FindDependencyBeforeDependent)4893 TEST_F(DatabaseBackedPoolTest, FindDependencyBeforeDependent) {
4894   DescriptorPool pool(&database_);
4895 
4896   const FileDescriptor* foo = pool.FindFileByName("foo.proto");
4897   ASSERT_TRUE(foo != NULL);
4898   EXPECT_EQ("foo.proto", foo->name());
4899   ASSERT_EQ(1, foo->message_type_count());
4900   EXPECT_EQ("Foo", foo->message_type(0)->name());
4901 
4902   const FileDescriptor* bar = pool.FindFileByName("bar.proto");
4903   ASSERT_TRUE(bar != NULL);
4904   EXPECT_EQ("bar.proto", bar->name());
4905   ASSERT_EQ(1, bar->message_type_count());
4906   EXPECT_EQ("Bar", bar->message_type(0)->name());
4907 
4908   ASSERT_EQ(1, bar->dependency_count());
4909   EXPECT_EQ(foo, bar->dependency(0));
4910 }
4911 
TEST_F(DatabaseBackedPoolTest,FindDependentBeforeDependency)4912 TEST_F(DatabaseBackedPoolTest, FindDependentBeforeDependency) {
4913   DescriptorPool pool(&database_);
4914 
4915   const FileDescriptor* bar = pool.FindFileByName("bar.proto");
4916   ASSERT_TRUE(bar != NULL);
4917   EXPECT_EQ("bar.proto", bar->name());
4918   ASSERT_EQ(1, bar->message_type_count());
4919   ASSERT_EQ("Bar", bar->message_type(0)->name());
4920 
4921   const FileDescriptor* foo = pool.FindFileByName("foo.proto");
4922   ASSERT_TRUE(foo != NULL);
4923   EXPECT_EQ("foo.proto", foo->name());
4924   ASSERT_EQ(1, foo->message_type_count());
4925   ASSERT_EQ("Foo", foo->message_type(0)->name());
4926 
4927   ASSERT_EQ(1, bar->dependency_count());
4928   EXPECT_EQ(foo, bar->dependency(0));
4929 }
4930 
TEST_F(DatabaseBackedPoolTest,FindFileContainingSymbol)4931 TEST_F(DatabaseBackedPoolTest, FindFileContainingSymbol) {
4932   DescriptorPool pool(&database_);
4933 
4934   const FileDescriptor* file = pool.FindFileContainingSymbol("Foo");
4935   ASSERT_TRUE(file != NULL);
4936   EXPECT_EQ("foo.proto", file->name());
4937   EXPECT_EQ(file, pool.FindFileByName("foo.proto"));
4938 
4939   EXPECT_TRUE(pool.FindFileContainingSymbol("NoSuchSymbol") == NULL);
4940 }
4941 
TEST_F(DatabaseBackedPoolTest,FindMessageTypeByName)4942 TEST_F(DatabaseBackedPoolTest, FindMessageTypeByName) {
4943   DescriptorPool pool(&database_);
4944 
4945   const Descriptor* type = pool.FindMessageTypeByName("Foo");
4946   ASSERT_TRUE(type != NULL);
4947   EXPECT_EQ("Foo", type->name());
4948   EXPECT_EQ(type->file(), pool.FindFileByName("foo.proto"));
4949 
4950   EXPECT_TRUE(pool.FindMessageTypeByName("NoSuchType") == NULL);
4951 }
4952 
TEST_F(DatabaseBackedPoolTest,FindExtensionByNumber)4953 TEST_F(DatabaseBackedPoolTest, FindExtensionByNumber) {
4954   DescriptorPool pool(&database_);
4955 
4956   const Descriptor* foo = pool.FindMessageTypeByName("Foo");
4957   ASSERT_TRUE(foo != NULL);
4958 
4959   const FieldDescriptor* extension = pool.FindExtensionByNumber(foo, 5);
4960   ASSERT_TRUE(extension != NULL);
4961   EXPECT_EQ("foo_ext", extension->name());
4962   EXPECT_EQ(extension->file(), pool.FindFileByName("bar.proto"));
4963 
4964   EXPECT_TRUE(pool.FindExtensionByNumber(foo, 12) == NULL);
4965 }
4966 
TEST_F(DatabaseBackedPoolTest,FindAllExtensions)4967 TEST_F(DatabaseBackedPoolTest, FindAllExtensions) {
4968   DescriptorPool pool(&database_);
4969 
4970   const Descriptor* foo = pool.FindMessageTypeByName("Foo");
4971 
4972   for (int i = 0; i < 2; ++i) {
4973     // Repeat the lookup twice, to check that we get consistent
4974     // results despite the fallback database lookup mutating the pool.
4975     vector<const FieldDescriptor*> extensions;
4976     pool.FindAllExtensions(foo, &extensions);
4977     ASSERT_EQ(1, extensions.size());
4978     EXPECT_EQ(5, extensions[0]->number());
4979   }
4980 }
4981 
TEST_F(DatabaseBackedPoolTest,ErrorWithoutErrorCollector)4982 TEST_F(DatabaseBackedPoolTest, ErrorWithoutErrorCollector) {
4983   ErrorDescriptorDatabase error_database;
4984   DescriptorPool pool(&error_database);
4985 
4986   vector<string> errors;
4987 
4988   {
4989     ScopedMemoryLog log;
4990     EXPECT_TRUE(pool.FindFileByName("error.proto") == NULL);
4991     errors = log.GetMessages(ERROR);
4992   }
4993 
4994   EXPECT_FALSE(errors.empty());
4995 }
4996 
TEST_F(DatabaseBackedPoolTest,ErrorWithErrorCollector)4997 TEST_F(DatabaseBackedPoolTest, ErrorWithErrorCollector) {
4998   ErrorDescriptorDatabase error_database;
4999   MockErrorCollector error_collector;
5000   DescriptorPool pool(&error_database, &error_collector);
5001 
5002   EXPECT_TRUE(pool.FindFileByName("error.proto") == NULL);
5003   EXPECT_EQ(
5004     "error.proto: error.proto: OTHER: File recursively imports itself: "
5005       "error.proto -> error2.proto -> error.proto\n"
5006     "error2.proto: error2.proto: OTHER: Import \"error.proto\" was not "
5007       "found or had errors.\n"
5008     "error.proto: error.proto: OTHER: Import \"error2.proto\" was not "
5009       "found or had errors.\n",
5010     error_collector.text_);
5011 }
5012 
TEST_F(DatabaseBackedPoolTest,UndeclaredDependencyOnUnbuiltType)5013 TEST_F(DatabaseBackedPoolTest, UndeclaredDependencyOnUnbuiltType) {
5014   // Check that we find and report undeclared dependencies on types that exist
5015   // in the descriptor database but that have not not been built yet.
5016   MockErrorCollector error_collector;
5017   DescriptorPool pool(&database_, &error_collector);
5018   EXPECT_TRUE(pool.FindMessageTypeByName("Baz") == NULL);
5019   EXPECT_EQ(
5020     "baz.proto: Baz.foo: TYPE: \"Foo\" seems to be defined in \"foo.proto\", "
5021     "which is not imported by \"baz.proto\".  To use it here, please add "
5022     "the necessary import.\n",
5023     error_collector.text_);
5024 }
5025 
TEST_F(DatabaseBackedPoolTest,RollbackAfterError)5026 TEST_F(DatabaseBackedPoolTest, RollbackAfterError) {
5027   // Make sure that all traces of bad types are removed from the pool. This used
5028   // to be b/4529436, due to the fact that a symbol resolution failure could
5029   // potentially cause another file to be recursively built, which would trigger
5030   // a checkpoint _past_ possibly invalid symbols.
5031   // Baz is defined in the database, but the file is invalid because it is
5032   // missing a necessary import.
5033   DescriptorPool pool(&database_);
5034   EXPECT_TRUE(pool.FindMessageTypeByName("Baz") == NULL);
5035   // Make sure that searching again for the file or the type fails.
5036   EXPECT_TRUE(pool.FindFileByName("baz.proto") == NULL);
5037   EXPECT_TRUE(pool.FindMessageTypeByName("Baz") == NULL);
5038 }
5039 
TEST_F(DatabaseBackedPoolTest,UnittestProto)5040 TEST_F(DatabaseBackedPoolTest, UnittestProto) {
5041   // Try to load all of unittest.proto from a DescriptorDatabase.  This should
5042   // thoroughly test all paths through DescriptorBuilder to insure that there
5043   // are no deadlocking problems when pool_->mutex_ is non-NULL.
5044   const FileDescriptor* original_file =
5045     protobuf_unittest::TestAllTypes::descriptor()->file();
5046 
5047   DescriptorPoolDatabase database(*DescriptorPool::generated_pool());
5048   DescriptorPool pool(&database);
5049   const FileDescriptor* file_from_database =
5050     pool.FindFileByName(original_file->name());
5051 
5052   ASSERT_TRUE(file_from_database != NULL);
5053 
5054   FileDescriptorProto original_file_proto;
5055   original_file->CopyTo(&original_file_proto);
5056 
5057   FileDescriptorProto file_from_database_proto;
5058   file_from_database->CopyTo(&file_from_database_proto);
5059 
5060   EXPECT_EQ(original_file_proto.DebugString(),
5061             file_from_database_proto.DebugString());
5062 
5063   // Also verify that CopyTo() did not omit any information.
5064   EXPECT_EQ(original_file->DebugString(),
5065             file_from_database->DebugString());
5066 }
5067 
TEST_F(DatabaseBackedPoolTest,DoesntRetryDbUnnecessarily)5068 TEST_F(DatabaseBackedPoolTest, DoesntRetryDbUnnecessarily) {
5069   // Searching for a child of an existing descriptor should never fall back
5070   // to the DescriptorDatabase even if it isn't found, because we know all
5071   // children are already loaded.
5072   CallCountingDatabase call_counter(&database_);
5073   DescriptorPool pool(&call_counter);
5074 
5075   const FileDescriptor* file = pool.FindFileByName("foo.proto");
5076   ASSERT_TRUE(file != NULL);
5077   const Descriptor* foo = pool.FindMessageTypeByName("Foo");
5078   ASSERT_TRUE(foo != NULL);
5079   const EnumDescriptor* test_enum = pool.FindEnumTypeByName("TestEnum");
5080   ASSERT_TRUE(test_enum != NULL);
5081   const ServiceDescriptor* test_service = pool.FindServiceByName("TestService");
5082   ASSERT_TRUE(test_service != NULL);
5083 
5084   EXPECT_NE(0, call_counter.call_count_);
5085   call_counter.Clear();
5086 
5087   EXPECT_TRUE(foo->FindFieldByName("no_such_field") == NULL);
5088   EXPECT_TRUE(foo->FindExtensionByName("no_such_extension") == NULL);
5089   EXPECT_TRUE(foo->FindNestedTypeByName("NoSuchMessageType") == NULL);
5090   EXPECT_TRUE(foo->FindEnumTypeByName("NoSuchEnumType") == NULL);
5091   EXPECT_TRUE(foo->FindEnumValueByName("NO_SUCH_VALUE") == NULL);
5092   EXPECT_TRUE(test_enum->FindValueByName("NO_SUCH_VALUE") == NULL);
5093   EXPECT_TRUE(test_service->FindMethodByName("NoSuchMethod") == NULL);
5094 
5095   EXPECT_TRUE(file->FindMessageTypeByName("NoSuchMessageType") == NULL);
5096   EXPECT_TRUE(file->FindEnumTypeByName("NoSuchEnumType") == NULL);
5097   EXPECT_TRUE(file->FindEnumValueByName("NO_SUCH_VALUE") == NULL);
5098   EXPECT_TRUE(file->FindServiceByName("NO_SUCH_VALUE") == NULL);
5099   EXPECT_TRUE(file->FindExtensionByName("no_such_extension") == NULL);
5100 
5101   EXPECT_TRUE(pool.FindFileContainingSymbol("Foo.no.such.field") == NULL);
5102   EXPECT_TRUE(pool.FindFileContainingSymbol("Foo.no_such_field") == NULL);
5103   EXPECT_TRUE(pool.FindMessageTypeByName("Foo.NoSuchMessageType") == NULL);
5104   EXPECT_TRUE(pool.FindFieldByName("Foo.no_such_field") == NULL);
5105   EXPECT_TRUE(pool.FindExtensionByName("Foo.no_such_extension") == NULL);
5106   EXPECT_TRUE(pool.FindEnumTypeByName("Foo.NoSuchEnumType") == NULL);
5107   EXPECT_TRUE(pool.FindEnumValueByName("Foo.NO_SUCH_VALUE") == NULL);
5108   EXPECT_TRUE(pool.FindMethodByName("TestService.NoSuchMethod") == NULL);
5109 
5110   EXPECT_EQ(0, call_counter.call_count_);
5111 }
5112 
TEST_F(DatabaseBackedPoolTest,DoesntReloadFilesUncesessarily)5113 TEST_F(DatabaseBackedPoolTest, DoesntReloadFilesUncesessarily) {
5114   // If FindFileContainingSymbol() or FindFileContainingExtension() return a
5115   // file that is already in the DescriptorPool, it should not attempt to
5116   // reload the file.
5117   FalsePositiveDatabase false_positive_database(&database_);
5118   MockErrorCollector error_collector;
5119   DescriptorPool pool(&false_positive_database, &error_collector);
5120 
5121   // First make sure foo.proto is loaded.
5122   const Descriptor* foo = pool.FindMessageTypeByName("Foo");
5123   ASSERT_TRUE(foo != NULL);
5124 
5125   // Try inducing false positives.
5126   EXPECT_TRUE(pool.FindMessageTypeByName("NoSuchSymbol") == NULL);
5127   EXPECT_TRUE(pool.FindExtensionByNumber(foo, 22) == NULL);
5128 
5129   // No errors should have been reported.  (If foo.proto was incorrectly
5130   // loaded multiple times, errors would have been reported.)
5131   EXPECT_EQ("", error_collector.text_);
5132 }
5133 
5134 // DescriptorDatabase that attempts to induce exponentially-bad performance
5135 // in DescriptorPool. For every positive N, the database contains a file
5136 // fileN.proto, which defines a message MessageN, which contains fields of
5137 // type MessageK for all K in [0,N). Message0 is not defined anywhere
5138 // (file0.proto exists, but is empty), so every other file and message type
5139 // will fail to build.
5140 //
5141 // If the DescriptorPool is not careful to memoize errors, an attempt to
5142 // build a descriptor for MessageN can require O(2^N) time.
5143 class ExponentialErrorDatabase : public DescriptorDatabase {
5144  public:
ExponentialErrorDatabase()5145   ExponentialErrorDatabase() {}
~ExponentialErrorDatabase()5146   ~ExponentialErrorDatabase() {}
5147 
5148   // implements DescriptorDatabase ---------------------------------
FindFileByName(const string & filename,FileDescriptorProto * output)5149   bool FindFileByName(const string& filename,
5150                       FileDescriptorProto* output) {
5151     int file_num = -1;
5152     FullMatch(filename, "file", ".proto", &file_num);
5153     if (file_num > -1) {
5154       return PopulateFile(file_num, output);
5155     } else {
5156       return false;
5157     }
5158   }
FindFileContainingSymbol(const string & symbol_name,FileDescriptorProto * output)5159   bool FindFileContainingSymbol(const string& symbol_name,
5160                                 FileDescriptorProto* output) {
5161     int file_num = -1;
5162     FullMatch(symbol_name, "Message", "", &file_num);
5163     if (file_num > 0) {
5164       return PopulateFile(file_num, output);
5165     } else {
5166       return false;
5167     }
5168   }
FindFileContainingExtension(const string & containing_type,int field_number,FileDescriptorProto * output)5169   bool FindFileContainingExtension(const string& containing_type,
5170                                    int field_number,
5171                                    FileDescriptorProto* output) {
5172     return false;
5173   }
5174 
5175  private:
FullMatch(const string & name,const string & begin_with,const string & end_with,int * file_num)5176   void FullMatch(const string& name,
5177                  const string& begin_with,
5178                  const string& end_with,
5179                  int* file_num) {
5180     int begin_size = begin_with.size();
5181     int end_size = end_with.size();
5182     if (name.substr(0, begin_size) != begin_with ||
5183         name.substr(name.size()- end_size, end_size) != end_with) {
5184       return;
5185     }
5186     safe_strto32(name.substr(begin_size, name.size() - end_size - begin_size),
5187                  file_num);
5188   }
5189 
PopulateFile(int file_num,FileDescriptorProto * output)5190   bool PopulateFile(int file_num, FileDescriptorProto* output) {
5191     using strings::Substitute;
5192     GOOGLE_CHECK_GE(file_num, 0);
5193     output->Clear();
5194     output->set_name(Substitute("file$0.proto", file_num));
5195     // file0.proto doesn't define Message0
5196     if (file_num > 0) {
5197       DescriptorProto* message = output->add_message_type();
5198       message->set_name(Substitute("Message$0", file_num));
5199       for (int i = 0; i < file_num; ++i) {
5200         output->add_dependency(Substitute("file$0.proto", i));
5201         FieldDescriptorProto* field = message->add_field();
5202         field->set_name(Substitute("field$0", i));
5203         field->set_number(i);
5204         field->set_label(FieldDescriptorProto::LABEL_OPTIONAL);
5205         field->set_type(FieldDescriptorProto::TYPE_MESSAGE);
5206         field->set_type_name(Substitute("Message$0", i));
5207       }
5208     }
5209     return true;
5210   }
5211 };
5212 
TEST_F(DatabaseBackedPoolTest,DoesntReloadKnownBadFiles)5213 TEST_F(DatabaseBackedPoolTest, DoesntReloadKnownBadFiles) {
5214   ExponentialErrorDatabase error_database;
5215   DescriptorPool pool(&error_database);
5216 
5217   GOOGLE_LOG(INFO) << "A timeout in this test probably indicates a real bug.";
5218 
5219   EXPECT_TRUE(pool.FindFileByName("file40.proto") == NULL);
5220   EXPECT_TRUE(pool.FindMessageTypeByName("Message40") == NULL);
5221 }
5222 
TEST_F(DatabaseBackedPoolTest,DoesntFallbackOnWrongType)5223 TEST_F(DatabaseBackedPoolTest, DoesntFallbackOnWrongType) {
5224   // If a lookup finds a symbol of the wrong type (e.g. we pass a type name
5225   // to FindFieldByName()), we should fail fast, without checking the fallback
5226   // database.
5227   CallCountingDatabase call_counter(&database_);
5228   DescriptorPool pool(&call_counter);
5229 
5230   const FileDescriptor* file = pool.FindFileByName("foo.proto");
5231   ASSERT_TRUE(file != NULL);
5232   const Descriptor* foo = pool.FindMessageTypeByName("Foo");
5233   ASSERT_TRUE(foo != NULL);
5234   const EnumDescriptor* test_enum = pool.FindEnumTypeByName("TestEnum");
5235   ASSERT_TRUE(test_enum != NULL);
5236 
5237   EXPECT_NE(0, call_counter.call_count_);
5238   call_counter.Clear();
5239 
5240   EXPECT_TRUE(pool.FindMessageTypeByName("TestEnum") == NULL);
5241   EXPECT_TRUE(pool.FindFieldByName("Foo") == NULL);
5242   EXPECT_TRUE(pool.FindExtensionByName("Foo") == NULL);
5243   EXPECT_TRUE(pool.FindEnumTypeByName("Foo") == NULL);
5244   EXPECT_TRUE(pool.FindEnumValueByName("Foo") == NULL);
5245   EXPECT_TRUE(pool.FindServiceByName("Foo") == NULL);
5246   EXPECT_TRUE(pool.FindMethodByName("Foo") == NULL);
5247 
5248   EXPECT_EQ(0, call_counter.call_count_);
5249 }
5250 
5251 // ===================================================================
5252 
5253 class AbortingErrorCollector : public DescriptorPool::ErrorCollector {
5254  public:
AbortingErrorCollector()5255   AbortingErrorCollector() {}
5256 
AddError(const string & filename,const string & element_name,const Message * message,ErrorLocation location,const string & error_message)5257   virtual void AddError(
5258       const string &filename,
5259       const string &element_name,
5260       const Message *message,
5261       ErrorLocation location,
5262       const string &error_message) {
5263     GOOGLE_LOG(FATAL) << "AddError() called unexpectedly: " << filename << ": "
5264                << error_message;
5265   }
5266  private:
5267   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(AbortingErrorCollector);
5268 };
5269 
5270 // A source tree containing only one file.
5271 class SingletonSourceTree : public compiler::SourceTree {
5272  public:
SingletonSourceTree(const string & filename,const string & contents)5273   SingletonSourceTree(const string& filename, const string& contents)
5274       : filename_(filename), contents_(contents) {}
5275 
Open(const string & filename)5276   virtual io::ZeroCopyInputStream* Open(const string& filename) {
5277     return filename == filename_ ?
5278         new io::ArrayInputStream(contents_.data(), contents_.size()) : NULL;
5279   }
5280 
5281  private:
5282   const string filename_;
5283   const string contents_;
5284 
5285   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SingletonSourceTree);
5286 };
5287 
5288 const char *const kSourceLocationTestInput =
5289   "syntax = \"proto2\";\n"
5290   "message A {\n"
5291   "  optional int32 a = 1;\n"
5292   "  message B {\n"
5293   "    required double b = 1;\n"
5294   "  }\n"
5295   "}\n"
5296   "enum Indecision {\n"
5297   "  YES   = 1;\n"
5298   "  NO    = 2;\n"
5299   "  MAYBE = 3;\n"
5300   "}\n"
5301   "service S {\n"
5302   "  rpc Method(A) returns (A.B);\n"
5303   // Put an empty line here to make the source location range match.
5304   "\n"
5305   "}\n"
5306   "message MessageWithExtensions {\n"
5307   "  extensions 1000 to max;\n"
5308   "}\n"
5309   "extend MessageWithExtensions {\n"
5310   "  optional int32 int32_extension = 1001;\n"
5311   "}\n"
5312   "message C {\n"
5313   "  extend MessageWithExtensions {\n"
5314   "    optional C message_extension = 1002;\n"
5315   "  }\n"
5316   "}\n";
5317 
5318 class SourceLocationTest : public testing::Test {
5319  public:
SourceLocationTest()5320   SourceLocationTest()
5321       : source_tree_("/test/test.proto", kSourceLocationTestInput),
5322         db_(&source_tree_),
5323         pool_(&db_, &collector_) {}
5324 
PrintSourceLocation(const SourceLocation & loc)5325   static string PrintSourceLocation(const SourceLocation &loc) {
5326     return strings::Substitute("$0:$1-$2:$3",
5327                                1 + loc.start_line,
5328                                1 + loc.start_column,
5329                                1 + loc.end_line,
5330                                1 + loc.end_column);
5331   }
5332 
5333  private:
5334   AbortingErrorCollector collector_;
5335   SingletonSourceTree source_tree_;
5336   compiler::SourceTreeDescriptorDatabase db_;
5337 
5338  protected:
5339   DescriptorPool pool_;
5340 };
5341 
5342 // TODO(adonovan): implement support for option fields and for
5343 // subparts of declarations.
5344 
TEST_F(SourceLocationTest,GetSourceLocation)5345 TEST_F(SourceLocationTest, GetSourceLocation) {
5346   SourceLocation loc;
5347 
5348   const FileDescriptor *file_desc =
5349       GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto"));
5350 
5351   const Descriptor *a_desc = file_desc->FindMessageTypeByName("A");
5352   EXPECT_TRUE(a_desc->GetSourceLocation(&loc));
5353   EXPECT_EQ("2:1-7:2", PrintSourceLocation(loc));
5354 
5355   const Descriptor *a_b_desc = a_desc->FindNestedTypeByName("B");
5356   EXPECT_TRUE(a_b_desc->GetSourceLocation(&loc));
5357   EXPECT_EQ("4:3-6:4", PrintSourceLocation(loc));
5358 
5359   const EnumDescriptor *e_desc = file_desc->FindEnumTypeByName("Indecision");
5360   EXPECT_TRUE(e_desc->GetSourceLocation(&loc));
5361   EXPECT_EQ("8:1-12:2", PrintSourceLocation(loc));
5362 
5363   const EnumValueDescriptor *yes_desc = e_desc->FindValueByName("YES");
5364   EXPECT_TRUE(yes_desc->GetSourceLocation(&loc));
5365   EXPECT_EQ("9:3-9:13", PrintSourceLocation(loc));
5366 
5367   const ServiceDescriptor *s_desc = file_desc->FindServiceByName("S");
5368   EXPECT_TRUE(s_desc->GetSourceLocation(&loc));
5369   EXPECT_EQ("13:1-16:2", PrintSourceLocation(loc));
5370 
5371   const MethodDescriptor *m_desc = s_desc->FindMethodByName("Method");
5372   EXPECT_TRUE(m_desc->GetSourceLocation(&loc));
5373   EXPECT_EQ("14:3-14:31", PrintSourceLocation(loc));
5374 
5375 }
5376 
TEST_F(SourceLocationTest,ExtensionSourceLocation)5377 TEST_F(SourceLocationTest, ExtensionSourceLocation) {
5378   SourceLocation loc;
5379 
5380   const FileDescriptor *file_desc =
5381       GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto"));
5382 
5383   const FieldDescriptor *int32_extension_desc =
5384       file_desc->FindExtensionByName("int32_extension");
5385   EXPECT_TRUE(int32_extension_desc->GetSourceLocation(&loc));
5386   EXPECT_EQ("21:3-21:41", PrintSourceLocation(loc));
5387 
5388   const Descriptor *c_desc = file_desc->FindMessageTypeByName("C");
5389   EXPECT_TRUE(c_desc->GetSourceLocation(&loc));
5390   EXPECT_EQ("23:1-27:2", PrintSourceLocation(loc));
5391 
5392   const FieldDescriptor *message_extension_desc =
5393       c_desc->FindExtensionByName("message_extension");
5394   EXPECT_TRUE(message_extension_desc->GetSourceLocation(&loc));
5395   EXPECT_EQ("25:5-25:41", PrintSourceLocation(loc));
5396 }
5397 
5398 // Missing SourceCodeInfo doesn't cause crash:
TEST_F(SourceLocationTest,GetSourceLocation_MissingSourceCodeInfo)5399 TEST_F(SourceLocationTest, GetSourceLocation_MissingSourceCodeInfo) {
5400   SourceLocation loc;
5401 
5402   const FileDescriptor *file_desc =
5403       GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto"));
5404 
5405   FileDescriptorProto proto;
5406   file_desc->CopyTo(&proto);  // Note, this discards the SourceCodeInfo.
5407   EXPECT_FALSE(proto.has_source_code_info());
5408 
5409   DescriptorPool bad1_pool(&pool_);
5410   const FileDescriptor* bad1_file_desc =
5411       GOOGLE_CHECK_NOTNULL(bad1_pool.BuildFile(proto));
5412   const Descriptor *bad1_a_desc = bad1_file_desc->FindMessageTypeByName("A");
5413   EXPECT_FALSE(bad1_a_desc->GetSourceLocation(&loc));
5414 }
5415 
5416 // Corrupt SourceCodeInfo doesn't cause crash:
TEST_F(SourceLocationTest,GetSourceLocation_BogusSourceCodeInfo)5417 TEST_F(SourceLocationTest, GetSourceLocation_BogusSourceCodeInfo) {
5418   SourceLocation loc;
5419 
5420   const FileDescriptor *file_desc =
5421       GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto"));
5422 
5423   FileDescriptorProto proto;
5424   file_desc->CopyTo(&proto);  // Note, this discards the SourceCodeInfo.
5425   EXPECT_FALSE(proto.has_source_code_info());
5426   SourceCodeInfo_Location *loc_msg =
5427       proto.mutable_source_code_info()->add_location();
5428   loc_msg->add_path(1);
5429   loc_msg->add_path(2);
5430   loc_msg->add_path(3);
5431   loc_msg->add_span(4);
5432   loc_msg->add_span(5);
5433   loc_msg->add_span(6);
5434 
5435   DescriptorPool bad2_pool(&pool_);
5436   const FileDescriptor* bad2_file_desc =
5437       GOOGLE_CHECK_NOTNULL(bad2_pool.BuildFile(proto));
5438   const Descriptor *bad2_a_desc = bad2_file_desc->FindMessageTypeByName("A");
5439   EXPECT_FALSE(bad2_a_desc->GetSourceLocation(&loc));
5440 }
5441 
5442 // ===================================================================
5443 
5444 const char* const kCopySourceCodeInfoToTestInput =
5445   "syntax = \"proto2\";\n"
5446   "message Foo {}\n";
5447 
5448 // Required since source code information is not preserved by
5449 // FileDescriptorTest.
5450 class CopySourceCodeInfoToTest : public testing::Test {
5451  public:
CopySourceCodeInfoToTest()5452   CopySourceCodeInfoToTest()
5453       : source_tree_("/test/test.proto", kCopySourceCodeInfoToTestInput),
5454         db_(&source_tree_),
5455         pool_(&db_, &collector_) {}
5456 
5457  private:
5458   AbortingErrorCollector collector_;
5459   SingletonSourceTree source_tree_;
5460   compiler::SourceTreeDescriptorDatabase db_;
5461 
5462  protected:
5463   DescriptorPool pool_;
5464 };
5465 
TEST_F(CopySourceCodeInfoToTest,CopyTo_DoesNotCopySourceCodeInfo)5466 TEST_F(CopySourceCodeInfoToTest, CopyTo_DoesNotCopySourceCodeInfo) {
5467   const FileDescriptor* file_desc =
5468       GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto"));
5469   FileDescriptorProto file_desc_proto;
5470   ASSERT_FALSE(file_desc_proto.has_source_code_info());
5471 
5472   file_desc->CopyTo(&file_desc_proto);
5473   EXPECT_FALSE(file_desc_proto.has_source_code_info());
5474 }
5475 
TEST_F(CopySourceCodeInfoToTest,CopySourceCodeInfoTo)5476 TEST_F(CopySourceCodeInfoToTest, CopySourceCodeInfoTo) {
5477   const FileDescriptor* file_desc =
5478       GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto"));
5479   FileDescriptorProto file_desc_proto;
5480   ASSERT_FALSE(file_desc_proto.has_source_code_info());
5481 
5482   file_desc->CopySourceCodeInfoTo(&file_desc_proto);
5483   const SourceCodeInfo& info = file_desc_proto.source_code_info();
5484   ASSERT_EQ(3, info.location_size());
5485   // Get the Foo message location
5486   const SourceCodeInfo_Location& foo_location = info.location(1);
5487   ASSERT_EQ(2, foo_location.path_size());
5488   EXPECT_EQ(FileDescriptorProto::kMessageTypeFieldNumber, foo_location.path(0));
5489   EXPECT_EQ(0, foo_location.path(1));      // Foo is the first message defined
5490   ASSERT_EQ(3, foo_location.span_size());  // Foo spans one line
5491   EXPECT_EQ(1, foo_location.span(0));      // Foo is declared on line 1
5492   EXPECT_EQ(0, foo_location.span(1));      // Foo starts at column 0
5493   EXPECT_EQ(14, foo_location.span(2));     // Foo ends on column 14
5494 }
5495 
5496 // ===================================================================
5497 
5498 
5499 }  // namespace descriptor_unittest
5500 }  // namespace protobuf
5501 }  // namespace google
5502