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