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