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