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