1
// Protocol Buffers - Google's data interchange format
2
// Copyright 2008 Google Inc. All rights reserved.
3
// http://code.google.com/p/protobuf/
5
// Redistribution and use in source and binary forms, with or without
6
// modification, are permitted provided that the following conditions are
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
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.
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.
31
// Author: kenton@google.com (Kenton Varda)
32
// Based on original Protocol Buffers design by
33
// Sanjay Ghemawat, Jeff Dean, and others.
35
// This file makes extensive use of RFC 3092. :)
39
#include <google/protobuf/descriptor.h>
40
#include <google/protobuf/descriptor_database.h>
41
#include <google/protobuf/dynamic_message.h>
42
#include <google/protobuf/descriptor.pb.h>
43
#include <google/protobuf/text_format.h>
44
#include <google/protobuf/unittest.pb.h>
45
#include <google/protobuf/unittest_custom_options.pb.h>
46
#include <google/protobuf/stubs/strutil.h>
47
#include <google/protobuf/stubs/substitute.h>
49
#include <google/protobuf/stubs/common.h>
50
#include <google/protobuf/testing/googletest.h>
51
#include <gtest/gtest.h>
56
// Can't use an anonymous namespace here due to brokenness of Tru64 compiler.
57
namespace descriptor_unittest {
59
// Some helpers to make assembling descriptors faster.
60
DescriptorProto* AddMessage(FileDescriptorProto* file, const string& name) {
61
DescriptorProto* result = file->add_message_type();
62
result->set_name(name);
66
DescriptorProto* AddNestedMessage(DescriptorProto* parent, const string& name) {
67
DescriptorProto* result = parent->add_nested_type();
68
result->set_name(name);
72
EnumDescriptorProto* AddEnum(FileDescriptorProto* file, const string& name) {
73
EnumDescriptorProto* result = file->add_enum_type();
74
result->set_name(name);
78
EnumDescriptorProto* AddNestedEnum(DescriptorProto* parent,
80
EnumDescriptorProto* result = parent->add_enum_type();
81
result->set_name(name);
85
ServiceDescriptorProto* AddService(FileDescriptorProto* file,
87
ServiceDescriptorProto* result = file->add_service();
88
result->set_name(name);
92
FieldDescriptorProto* AddField(DescriptorProto* parent,
93
const string& name, int number,
94
FieldDescriptorProto::Label label,
95
FieldDescriptorProto::Type type) {
96
FieldDescriptorProto* result = parent->add_field();
97
result->set_name(name);
98
result->set_number(number);
99
result->set_label(label);
100
result->set_type(type);
104
FieldDescriptorProto* AddExtension(FileDescriptorProto* file,
105
const string& extendee,
106
const string& name, int number,
107
FieldDescriptorProto::Label label,
108
FieldDescriptorProto::Type type) {
109
FieldDescriptorProto* result = file->add_extension();
110
result->set_name(name);
111
result->set_number(number);
112
result->set_label(label);
113
result->set_type(type);
114
result->set_extendee(extendee);
118
FieldDescriptorProto* AddNestedExtension(DescriptorProto* parent,
119
const string& extendee,
120
const string& name, int number,
121
FieldDescriptorProto::Label label,
122
FieldDescriptorProto::Type type) {
123
FieldDescriptorProto* result = parent->add_extension();
124
result->set_name(name);
125
result->set_number(number);
126
result->set_label(label);
127
result->set_type(type);
128
result->set_extendee(extendee);
132
DescriptorProto::ExtensionRange* AddExtensionRange(DescriptorProto* parent,
133
int start, int end) {
134
DescriptorProto::ExtensionRange* result = parent->add_extension_range();
135
result->set_start(start);
136
result->set_end(end);
140
EnumValueDescriptorProto* AddEnumValue(EnumDescriptorProto* enum_proto,
141
const string& name, int number) {
142
EnumValueDescriptorProto* result = enum_proto->add_value();
143
result->set_name(name);
144
result->set_number(number);
148
MethodDescriptorProto* AddMethod(ServiceDescriptorProto* service,
150
const string& input_type,
151
const string& output_type) {
152
MethodDescriptorProto* result = service->add_method();
153
result->set_name(name);
154
result->set_input_type(input_type);
155
result->set_output_type(output_type);
159
// Empty enums technically aren't allowed. We need to insert a dummy value
161
void AddEmptyEnum(FileDescriptorProto* file, const string& name) {
162
AddEnumValue(AddEnum(file, name), name + "_DUMMY", 1);
165
// ===================================================================
167
// Test simple files.
168
class FileDescriptorTest : public testing::Test {
170
virtual void SetUp() {
171
// Build descriptors for the following definitions:
174
// message FooMessage { extensions 1; }
175
// enum FooEnum {FOO_ENUM_VALUE = 1;}
176
// service FooService {}
177
// extend FooMessage { optional int32 foo_extension = 1; }
180
// package bar_package;
181
// message BarMessage { extensions 1; }
182
// enum BarEnum {BAR_ENUM_VALUE = 1;}
183
// service BarService {}
184
// extend BarMessage { optional int32 bar_extension = 1; }
186
// Also, we have an empty file "baz.proto". This file's purpose is to
187
// make sure that even though it has the same package as foo.proto,
188
// searching it for members of foo.proto won't work.
190
FileDescriptorProto foo_file;
191
foo_file.set_name("foo.proto");
192
AddExtensionRange(AddMessage(&foo_file, "FooMessage"), 1, 2);
193
AddEnumValue(AddEnum(&foo_file, "FooEnum"), "FOO_ENUM_VALUE", 1);
194
AddService(&foo_file, "FooService");
195
AddExtension(&foo_file, "FooMessage", "foo_extension", 1,
196
FieldDescriptorProto::LABEL_OPTIONAL,
197
FieldDescriptorProto::TYPE_INT32);
199
FileDescriptorProto bar_file;
200
bar_file.set_name("bar.proto");
201
bar_file.set_package("bar_package");
202
bar_file.add_dependency("foo.proto");
203
AddExtensionRange(AddMessage(&bar_file, "BarMessage"), 1, 2);
204
AddEnumValue(AddEnum(&bar_file, "BarEnum"), "BAR_ENUM_VALUE", 1);
205
AddService(&bar_file, "BarService");
206
AddExtension(&bar_file, "bar_package.BarMessage", "bar_extension", 1,
207
FieldDescriptorProto::LABEL_OPTIONAL,
208
FieldDescriptorProto::TYPE_INT32);
210
FileDescriptorProto baz_file;
211
baz_file.set_name("baz.proto");
213
// Build the descriptors and get the pointers.
214
foo_file_ = pool_.BuildFile(foo_file);
215
ASSERT_TRUE(foo_file_ != NULL);
217
bar_file_ = pool_.BuildFile(bar_file);
218
ASSERT_TRUE(bar_file_ != NULL);
220
baz_file_ = pool_.BuildFile(baz_file);
221
ASSERT_TRUE(baz_file_ != NULL);
223
ASSERT_EQ(1, foo_file_->message_type_count());
224
foo_message_ = foo_file_->message_type(0);
225
ASSERT_EQ(1, foo_file_->enum_type_count());
226
foo_enum_ = foo_file_->enum_type(0);
227
ASSERT_EQ(1, foo_enum_->value_count());
228
foo_enum_value_ = foo_enum_->value(0);
229
ASSERT_EQ(1, foo_file_->service_count());
230
foo_service_ = foo_file_->service(0);
231
ASSERT_EQ(1, foo_file_->extension_count());
232
foo_extension_ = foo_file_->extension(0);
234
ASSERT_EQ(1, bar_file_->message_type_count());
235
bar_message_ = bar_file_->message_type(0);
236
ASSERT_EQ(1, bar_file_->enum_type_count());
237
bar_enum_ = bar_file_->enum_type(0);
238
ASSERT_EQ(1, bar_enum_->value_count());
239
bar_enum_value_ = bar_enum_->value(0);
240
ASSERT_EQ(1, bar_file_->service_count());
241
bar_service_ = bar_file_->service(0);
242
ASSERT_EQ(1, bar_file_->extension_count());
243
bar_extension_ = bar_file_->extension(0);
246
DescriptorPool pool_;
248
const FileDescriptor* foo_file_;
249
const FileDescriptor* bar_file_;
250
const FileDescriptor* baz_file_;
252
const Descriptor* foo_message_;
253
const EnumDescriptor* foo_enum_;
254
const EnumValueDescriptor* foo_enum_value_;
255
const ServiceDescriptor* foo_service_;
256
const FieldDescriptor* foo_extension_;
258
const Descriptor* bar_message_;
259
const EnumDescriptor* bar_enum_;
260
const EnumValueDescriptor* bar_enum_value_;
261
const ServiceDescriptor* bar_service_;
262
const FieldDescriptor* bar_extension_;
265
TEST_F(FileDescriptorTest, Name) {
266
EXPECT_EQ("foo.proto", foo_file_->name());
267
EXPECT_EQ("bar.proto", bar_file_->name());
268
EXPECT_EQ("baz.proto", baz_file_->name());
271
TEST_F(FileDescriptorTest, Package) {
272
EXPECT_EQ("", foo_file_->package());
273
EXPECT_EQ("bar_package", bar_file_->package());
276
TEST_F(FileDescriptorTest, Dependencies) {
277
EXPECT_EQ(0, foo_file_->dependency_count());
278
EXPECT_EQ(1, bar_file_->dependency_count());
279
EXPECT_EQ(foo_file_, bar_file_->dependency(0));
282
TEST_F(FileDescriptorTest, FindMessageTypeByName) {
283
EXPECT_EQ(foo_message_, foo_file_->FindMessageTypeByName("FooMessage"));
284
EXPECT_EQ(bar_message_, bar_file_->FindMessageTypeByName("BarMessage"));
286
EXPECT_TRUE(foo_file_->FindMessageTypeByName("BarMessage") == NULL);
287
EXPECT_TRUE(bar_file_->FindMessageTypeByName("FooMessage") == NULL);
288
EXPECT_TRUE(baz_file_->FindMessageTypeByName("FooMessage") == NULL);
290
EXPECT_TRUE(foo_file_->FindMessageTypeByName("NoSuchMessage") == NULL);
291
EXPECT_TRUE(foo_file_->FindMessageTypeByName("FooEnum") == NULL);
294
TEST_F(FileDescriptorTest, FindEnumTypeByName) {
295
EXPECT_EQ(foo_enum_, foo_file_->FindEnumTypeByName("FooEnum"));
296
EXPECT_EQ(bar_enum_, bar_file_->FindEnumTypeByName("BarEnum"));
298
EXPECT_TRUE(foo_file_->FindEnumTypeByName("BarEnum") == NULL);
299
EXPECT_TRUE(bar_file_->FindEnumTypeByName("FooEnum") == NULL);
300
EXPECT_TRUE(baz_file_->FindEnumTypeByName("FooEnum") == NULL);
302
EXPECT_TRUE(foo_file_->FindEnumTypeByName("NoSuchEnum") == NULL);
303
EXPECT_TRUE(foo_file_->FindEnumTypeByName("FooMessage") == NULL);
306
TEST_F(FileDescriptorTest, FindEnumValueByName) {
307
EXPECT_EQ(foo_enum_value_, foo_file_->FindEnumValueByName("FOO_ENUM_VALUE"));
308
EXPECT_EQ(bar_enum_value_, bar_file_->FindEnumValueByName("BAR_ENUM_VALUE"));
310
EXPECT_TRUE(foo_file_->FindEnumValueByName("BAR_ENUM_VALUE") == NULL);
311
EXPECT_TRUE(bar_file_->FindEnumValueByName("FOO_ENUM_VALUE") == NULL);
312
EXPECT_TRUE(baz_file_->FindEnumValueByName("FOO_ENUM_VALUE") == NULL);
314
EXPECT_TRUE(foo_file_->FindEnumValueByName("NO_SUCH_VALUE") == NULL);
315
EXPECT_TRUE(foo_file_->FindEnumValueByName("FooMessage") == NULL);
318
TEST_F(FileDescriptorTest, FindServiceByName) {
319
EXPECT_EQ(foo_service_, foo_file_->FindServiceByName("FooService"));
320
EXPECT_EQ(bar_service_, bar_file_->FindServiceByName("BarService"));
322
EXPECT_TRUE(foo_file_->FindServiceByName("BarService") == NULL);
323
EXPECT_TRUE(bar_file_->FindServiceByName("FooService") == NULL);
324
EXPECT_TRUE(baz_file_->FindServiceByName("FooService") == NULL);
326
EXPECT_TRUE(foo_file_->FindServiceByName("NoSuchService") == NULL);
327
EXPECT_TRUE(foo_file_->FindServiceByName("FooMessage") == NULL);
330
TEST_F(FileDescriptorTest, FindExtensionByName) {
331
EXPECT_EQ(foo_extension_, foo_file_->FindExtensionByName("foo_extension"));
332
EXPECT_EQ(bar_extension_, bar_file_->FindExtensionByName("bar_extension"));
334
EXPECT_TRUE(foo_file_->FindExtensionByName("bar_extension") == NULL);
335
EXPECT_TRUE(bar_file_->FindExtensionByName("foo_extension") == NULL);
336
EXPECT_TRUE(baz_file_->FindExtensionByName("foo_extension") == NULL);
338
EXPECT_TRUE(foo_file_->FindExtensionByName("no_such_extension") == NULL);
339
EXPECT_TRUE(foo_file_->FindExtensionByName("FooMessage") == NULL);
342
TEST_F(FileDescriptorTest, FindExtensionByNumber) {
343
EXPECT_EQ(foo_extension_, pool_.FindExtensionByNumber(foo_message_, 1));
344
EXPECT_EQ(bar_extension_, pool_.FindExtensionByNumber(bar_message_, 1));
346
EXPECT_TRUE(pool_.FindExtensionByNumber(foo_message_, 2) == NULL);
349
TEST_F(FileDescriptorTest, BuildAgain) {
350
// Test that if te call BuildFile again on the same input we get the same
351
// FileDescriptor back.
352
FileDescriptorProto file;
353
foo_file_->CopyTo(&file);
354
EXPECT_EQ(foo_file_, pool_.BuildFile(file));
356
// But if we change the file then it won't work.
357
file.set_package("some.other.package");
358
EXPECT_TRUE(pool_.BuildFile(file) == NULL);
361
// ===================================================================
363
// Test simple flat messages and fields.
364
class DescriptorTest : public testing::Test {
366
virtual void SetUp() {
367
// Build descriptors for the following definitions:
370
// message TestForeign {}
373
// message TestMessage {
374
// required string foo = 1;
375
// optional TestEnum bar = 6;
376
// repeated TestForeign baz = 500000000;
377
// optional group qux = 15 {}
381
// package corge.grault;
382
// message TestMessage2 {
383
// required string foo = 1;
384
// required string bar = 2;
385
// required string quux = 6;
388
// We cheat and use TestForeign as the type for qux rather than create
389
// an actual nested type.
391
// Since all primitive types (including string) use the same building
392
// code, there's no need to test each one individually.
394
// TestMessage2 is primarily here to test FindFieldByName and friends.
395
// All messages created from the same DescriptorPool share the same lookup
396
// table, so we need to insure that they don't interfere.
398
FileDescriptorProto foo_file;
399
foo_file.set_name("foo.proto");
400
AddMessage(&foo_file, "TestForeign");
401
AddEmptyEnum(&foo_file, "TestEnum");
403
DescriptorProto* message = AddMessage(&foo_file, "TestMessage");
404
AddField(message, "foo", 1,
405
FieldDescriptorProto::LABEL_REQUIRED,
406
FieldDescriptorProto::TYPE_STRING);
407
AddField(message, "bar", 6,
408
FieldDescriptorProto::LABEL_OPTIONAL,
409
FieldDescriptorProto::TYPE_ENUM)
410
->set_type_name("TestEnum");
411
AddField(message, "baz", 500000000,
412
FieldDescriptorProto::LABEL_REPEATED,
413
FieldDescriptorProto::TYPE_MESSAGE)
414
->set_type_name("TestForeign");
415
AddField(message, "qux", 15,
416
FieldDescriptorProto::LABEL_OPTIONAL,
417
FieldDescriptorProto::TYPE_GROUP)
418
->set_type_name("TestForeign");
420
FileDescriptorProto bar_file;
421
bar_file.set_name("bar.proto");
422
bar_file.set_package("corge.grault");
424
DescriptorProto* message2 = AddMessage(&bar_file, "TestMessage2");
425
AddField(message2, "foo", 1,
426
FieldDescriptorProto::LABEL_REQUIRED,
427
FieldDescriptorProto::TYPE_STRING);
428
AddField(message2, "bar", 2,
429
FieldDescriptorProto::LABEL_REQUIRED,
430
FieldDescriptorProto::TYPE_STRING);
431
AddField(message2, "quux", 6,
432
FieldDescriptorProto::LABEL_REQUIRED,
433
FieldDescriptorProto::TYPE_STRING);
435
// Build the descriptors and get the pointers.
436
foo_file_ = pool_.BuildFile(foo_file);
437
ASSERT_TRUE(foo_file_ != NULL);
439
bar_file_ = pool_.BuildFile(bar_file);
440
ASSERT_TRUE(bar_file_ != NULL);
442
ASSERT_EQ(1, foo_file_->enum_type_count());
443
enum_ = foo_file_->enum_type(0);
445
ASSERT_EQ(2, foo_file_->message_type_count());
446
foreign_ = foo_file_->message_type(0);
447
message_ = foo_file_->message_type(1);
449
ASSERT_EQ(4, message_->field_count());
450
foo_ = message_->field(0);
451
bar_ = message_->field(1);
452
baz_ = message_->field(2);
453
qux_ = message_->field(3);
455
ASSERT_EQ(1, bar_file_->message_type_count());
456
message2_ = bar_file_->message_type(0);
458
ASSERT_EQ(3, message2_->field_count());
459
foo2_ = message2_->field(0);
460
bar2_ = message2_->field(1);
461
quux2_ = message2_->field(2);
464
DescriptorPool pool_;
466
const FileDescriptor* foo_file_;
467
const FileDescriptor* bar_file_;
469
const Descriptor* message_;
470
const Descriptor* message2_;
471
const Descriptor* foreign_;
472
const EnumDescriptor* enum_;
474
const FieldDescriptor* foo_;
475
const FieldDescriptor* bar_;
476
const FieldDescriptor* baz_;
477
const FieldDescriptor* qux_;
479
const FieldDescriptor* foo2_;
480
const FieldDescriptor* bar2_;
481
const FieldDescriptor* quux2_;
484
TEST_F(DescriptorTest, Name) {
485
EXPECT_EQ("TestMessage", message_->name());
486
EXPECT_EQ("TestMessage", message_->full_name());
487
EXPECT_EQ(foo_file_, message_->file());
489
EXPECT_EQ("TestMessage2", message2_->name());
490
EXPECT_EQ("corge.grault.TestMessage2", message2_->full_name());
491
EXPECT_EQ(bar_file_, message2_->file());
494
TEST_F(DescriptorTest, ContainingType) {
495
EXPECT_TRUE(message_->containing_type() == NULL);
496
EXPECT_TRUE(message2_->containing_type() == NULL);
499
TEST_F(DescriptorTest, FieldsByIndex) {
500
ASSERT_EQ(4, message_->field_count());
501
EXPECT_EQ(foo_, message_->field(0));
502
EXPECT_EQ(bar_, message_->field(1));
503
EXPECT_EQ(baz_, message_->field(2));
504
EXPECT_EQ(qux_, message_->field(3));
507
TEST_F(DescriptorTest, FindFieldByName) {
508
// All messages in the same DescriptorPool share a single lookup table for
509
// fields. So, in addition to testing that FindFieldByName finds the fields
510
// of the message, we need to test that it does *not* find the fields of
513
EXPECT_EQ(foo_, message_->FindFieldByName("foo"));
514
EXPECT_EQ(bar_, message_->FindFieldByName("bar"));
515
EXPECT_EQ(baz_, message_->FindFieldByName("baz"));
516
EXPECT_EQ(qux_, message_->FindFieldByName("qux"));
517
EXPECT_TRUE(message_->FindFieldByName("no_such_field") == NULL);
518
EXPECT_TRUE(message_->FindFieldByName("quux") == NULL);
520
EXPECT_EQ(foo2_ , message2_->FindFieldByName("foo" ));
521
EXPECT_EQ(bar2_ , message2_->FindFieldByName("bar" ));
522
EXPECT_EQ(quux2_, message2_->FindFieldByName("quux"));
523
EXPECT_TRUE(message2_->FindFieldByName("baz") == NULL);
524
EXPECT_TRUE(message2_->FindFieldByName("qux") == NULL);
527
TEST_F(DescriptorTest, FindFieldByNumber) {
528
EXPECT_EQ(foo_, message_->FindFieldByNumber(1));
529
EXPECT_EQ(bar_, message_->FindFieldByNumber(6));
530
EXPECT_EQ(baz_, message_->FindFieldByNumber(500000000));
531
EXPECT_EQ(qux_, message_->FindFieldByNumber(15));
532
EXPECT_TRUE(message_->FindFieldByNumber(837592) == NULL);
533
EXPECT_TRUE(message_->FindFieldByNumber(2) == NULL);
535
EXPECT_EQ(foo2_ , message2_->FindFieldByNumber(1));
536
EXPECT_EQ(bar2_ , message2_->FindFieldByNumber(2));
537
EXPECT_EQ(quux2_, message2_->FindFieldByNumber(6));
538
EXPECT_TRUE(message2_->FindFieldByNumber(15) == NULL);
539
EXPECT_TRUE(message2_->FindFieldByNumber(500000000) == NULL);
542
TEST_F(DescriptorTest, FieldName) {
543
EXPECT_EQ("foo", foo_->name());
544
EXPECT_EQ("bar", bar_->name());
545
EXPECT_EQ("baz", baz_->name());
546
EXPECT_EQ("qux", qux_->name());
549
TEST_F(DescriptorTest, FieldFullName) {
550
EXPECT_EQ("TestMessage.foo", foo_->full_name());
551
EXPECT_EQ("TestMessage.bar", bar_->full_name());
552
EXPECT_EQ("TestMessage.baz", baz_->full_name());
553
EXPECT_EQ("TestMessage.qux", qux_->full_name());
555
EXPECT_EQ("corge.grault.TestMessage2.foo", foo2_->full_name());
556
EXPECT_EQ("corge.grault.TestMessage2.bar", bar2_->full_name());
557
EXPECT_EQ("corge.grault.TestMessage2.quux", quux2_->full_name());
560
TEST_F(DescriptorTest, FieldFile) {
561
EXPECT_EQ(foo_file_, foo_->file());
562
EXPECT_EQ(foo_file_, bar_->file());
563
EXPECT_EQ(foo_file_, baz_->file());
564
EXPECT_EQ(foo_file_, qux_->file());
566
EXPECT_EQ(bar_file_, foo2_->file());
567
EXPECT_EQ(bar_file_, bar2_->file());
568
EXPECT_EQ(bar_file_, quux2_->file());
571
TEST_F(DescriptorTest, FieldIndex) {
572
EXPECT_EQ(0, foo_->index());
573
EXPECT_EQ(1, bar_->index());
574
EXPECT_EQ(2, baz_->index());
575
EXPECT_EQ(3, qux_->index());
578
TEST_F(DescriptorTest, FieldNumber) {
579
EXPECT_EQ( 1, foo_->number());
580
EXPECT_EQ( 6, bar_->number());
581
EXPECT_EQ(500000000, baz_->number());
582
EXPECT_EQ( 15, qux_->number());
585
TEST_F(DescriptorTest, FieldType) {
586
EXPECT_EQ(FieldDescriptor::TYPE_STRING , foo_->type());
587
EXPECT_EQ(FieldDescriptor::TYPE_ENUM , bar_->type());
588
EXPECT_EQ(FieldDescriptor::TYPE_MESSAGE, baz_->type());
589
EXPECT_EQ(FieldDescriptor::TYPE_GROUP , qux_->type());
592
TEST_F(DescriptorTest, FieldLabel) {
593
EXPECT_EQ(FieldDescriptor::LABEL_REQUIRED, foo_->label());
594
EXPECT_EQ(FieldDescriptor::LABEL_OPTIONAL, bar_->label());
595
EXPECT_EQ(FieldDescriptor::LABEL_REPEATED, baz_->label());
596
EXPECT_EQ(FieldDescriptor::LABEL_OPTIONAL, qux_->label());
598
EXPECT_TRUE (foo_->is_required());
599
EXPECT_FALSE(foo_->is_optional());
600
EXPECT_FALSE(foo_->is_repeated());
602
EXPECT_FALSE(bar_->is_required());
603
EXPECT_TRUE (bar_->is_optional());
604
EXPECT_FALSE(bar_->is_repeated());
606
EXPECT_FALSE(baz_->is_required());
607
EXPECT_FALSE(baz_->is_optional());
608
EXPECT_TRUE (baz_->is_repeated());
611
TEST_F(DescriptorTest, FieldHasDefault) {
612
EXPECT_FALSE(foo_->has_default_value());
613
EXPECT_FALSE(bar_->has_default_value());
614
EXPECT_FALSE(baz_->has_default_value());
615
EXPECT_FALSE(qux_->has_default_value());
618
TEST_F(DescriptorTest, FieldContainingType) {
619
EXPECT_EQ(message_, foo_->containing_type());
620
EXPECT_EQ(message_, bar_->containing_type());
621
EXPECT_EQ(message_, baz_->containing_type());
622
EXPECT_EQ(message_, qux_->containing_type());
624
EXPECT_EQ(message2_, foo2_ ->containing_type());
625
EXPECT_EQ(message2_, bar2_ ->containing_type());
626
EXPECT_EQ(message2_, quux2_->containing_type());
629
TEST_F(DescriptorTest, FieldMessageType) {
630
EXPECT_TRUE(foo_->message_type() == NULL);
631
EXPECT_TRUE(bar_->message_type() == NULL);
633
EXPECT_EQ(foreign_, baz_->message_type());
634
EXPECT_EQ(foreign_, qux_->message_type());
637
TEST_F(DescriptorTest, FieldEnumType) {
638
EXPECT_TRUE(foo_->enum_type() == NULL);
639
EXPECT_TRUE(baz_->enum_type() == NULL);
640
EXPECT_TRUE(qux_->enum_type() == NULL);
642
EXPECT_EQ(enum_, bar_->enum_type());
645
// ===================================================================
647
class StylizedFieldNamesTest : public testing::Test {
650
FileDescriptorProto file;
651
file.set_name("foo.proto");
653
AddExtensionRange(AddMessage(&file, "ExtendableMessage"), 1, 1000);
655
DescriptorProto* message = AddMessage(&file, "TestMessage");
656
AddField(message, "foo_foo", 1,
657
FieldDescriptorProto::LABEL_OPTIONAL,
658
FieldDescriptorProto::TYPE_INT32);
659
AddField(message, "FooBar", 2,
660
FieldDescriptorProto::LABEL_OPTIONAL,
661
FieldDescriptorProto::TYPE_INT32);
662
AddField(message, "fooBaz", 3,
663
FieldDescriptorProto::LABEL_OPTIONAL,
664
FieldDescriptorProto::TYPE_INT32);
665
AddField(message, "fooFoo", 4, // Camel-case conflict with foo_foo.
666
FieldDescriptorProto::LABEL_OPTIONAL,
667
FieldDescriptorProto::TYPE_INT32);
668
AddField(message, "foobar", 5, // Lower-case conflict with FooBar.
669
FieldDescriptorProto::LABEL_OPTIONAL,
670
FieldDescriptorProto::TYPE_INT32);
672
AddNestedExtension(message, "ExtendableMessage", "bar_foo", 1,
673
FieldDescriptorProto::LABEL_OPTIONAL,
674
FieldDescriptorProto::TYPE_INT32);
675
AddNestedExtension(message, "ExtendableMessage", "BarBar", 2,
676
FieldDescriptorProto::LABEL_OPTIONAL,
677
FieldDescriptorProto::TYPE_INT32);
678
AddNestedExtension(message, "ExtendableMessage", "BarBaz", 3,
679
FieldDescriptorProto::LABEL_OPTIONAL,
680
FieldDescriptorProto::TYPE_INT32);
681
AddNestedExtension(message, "ExtendableMessage", "barFoo", 4, // Conflict
682
FieldDescriptorProto::LABEL_OPTIONAL,
683
FieldDescriptorProto::TYPE_INT32);
684
AddNestedExtension(message, "ExtendableMessage", "barbar", 5, // Conflict
685
FieldDescriptorProto::LABEL_OPTIONAL,
686
FieldDescriptorProto::TYPE_INT32);
688
AddExtension(&file, "ExtendableMessage", "baz_foo", 11,
689
FieldDescriptorProto::LABEL_OPTIONAL,
690
FieldDescriptorProto::TYPE_INT32);
691
AddExtension(&file, "ExtendableMessage", "BazBar", 12,
692
FieldDescriptorProto::LABEL_OPTIONAL,
693
FieldDescriptorProto::TYPE_INT32);
694
AddExtension(&file, "ExtendableMessage", "BazBaz", 13,
695
FieldDescriptorProto::LABEL_OPTIONAL,
696
FieldDescriptorProto::TYPE_INT32);
697
AddExtension(&file, "ExtendableMessage", "bazFoo", 14, // Conflict
698
FieldDescriptorProto::LABEL_OPTIONAL,
699
FieldDescriptorProto::TYPE_INT32);
700
AddExtension(&file, "ExtendableMessage", "bazbar", 15, // Conflict
701
FieldDescriptorProto::LABEL_OPTIONAL,
702
FieldDescriptorProto::TYPE_INT32);
704
file_ = pool_.BuildFile(file);
705
ASSERT_TRUE(file_ != NULL);
706
ASSERT_EQ(2, file_->message_type_count());
707
message_ = file_->message_type(1);
708
ASSERT_EQ("TestMessage", message_->name());
709
ASSERT_EQ(5, message_->field_count());
710
ASSERT_EQ(5, message_->extension_count());
711
ASSERT_EQ(5, file_->extension_count());
714
DescriptorPool pool_;
715
const FileDescriptor* file_;
716
const Descriptor* message_;
719
TEST_F(StylizedFieldNamesTest, LowercaseName) {
720
EXPECT_EQ("foo_foo", message_->field(0)->lowercase_name());
721
EXPECT_EQ("foobar" , message_->field(1)->lowercase_name());
722
EXPECT_EQ("foobaz" , message_->field(2)->lowercase_name());
723
EXPECT_EQ("foofoo" , message_->field(3)->lowercase_name());
724
EXPECT_EQ("foobar" , message_->field(4)->lowercase_name());
726
EXPECT_EQ("bar_foo", message_->extension(0)->lowercase_name());
727
EXPECT_EQ("barbar" , message_->extension(1)->lowercase_name());
728
EXPECT_EQ("barbaz" , message_->extension(2)->lowercase_name());
729
EXPECT_EQ("barfoo" , message_->extension(3)->lowercase_name());
730
EXPECT_EQ("barbar" , message_->extension(4)->lowercase_name());
732
EXPECT_EQ("baz_foo", file_->extension(0)->lowercase_name());
733
EXPECT_EQ("bazbar" , file_->extension(1)->lowercase_name());
734
EXPECT_EQ("bazbaz" , file_->extension(2)->lowercase_name());
735
EXPECT_EQ("bazfoo" , file_->extension(3)->lowercase_name());
736
EXPECT_EQ("bazbar" , file_->extension(4)->lowercase_name());
739
TEST_F(StylizedFieldNamesTest, CamelcaseName) {
740
EXPECT_EQ("fooFoo", message_->field(0)->camelcase_name());
741
EXPECT_EQ("fooBar", message_->field(1)->camelcase_name());
742
EXPECT_EQ("fooBaz", message_->field(2)->camelcase_name());
743
EXPECT_EQ("fooFoo", message_->field(3)->camelcase_name());
744
EXPECT_EQ("foobar", message_->field(4)->camelcase_name());
746
EXPECT_EQ("barFoo", message_->extension(0)->camelcase_name());
747
EXPECT_EQ("barBar", message_->extension(1)->camelcase_name());
748
EXPECT_EQ("barBaz", message_->extension(2)->camelcase_name());
749
EXPECT_EQ("barFoo", message_->extension(3)->camelcase_name());
750
EXPECT_EQ("barbar", message_->extension(4)->camelcase_name());
752
EXPECT_EQ("bazFoo", file_->extension(0)->camelcase_name());
753
EXPECT_EQ("bazBar", file_->extension(1)->camelcase_name());
754
EXPECT_EQ("bazBaz", file_->extension(2)->camelcase_name());
755
EXPECT_EQ("bazFoo", file_->extension(3)->camelcase_name());
756
EXPECT_EQ("bazbar", file_->extension(4)->camelcase_name());
759
TEST_F(StylizedFieldNamesTest, FindByLowercaseName) {
760
EXPECT_EQ(message_->field(0),
761
message_->FindFieldByLowercaseName("foo_foo"));
762
EXPECT_EQ(message_->field(1),
763
message_->FindFieldByLowercaseName("foobar"));
764
EXPECT_EQ(message_->field(2),
765
message_->FindFieldByLowercaseName("foobaz"));
766
EXPECT_TRUE(message_->FindFieldByLowercaseName("FooBar") == NULL);
767
EXPECT_TRUE(message_->FindFieldByLowercaseName("fooBaz") == NULL);
768
EXPECT_TRUE(message_->FindFieldByLowercaseName("bar_foo") == NULL);
769
EXPECT_TRUE(message_->FindFieldByLowercaseName("nosuchfield") == NULL);
771
EXPECT_EQ(message_->extension(0),
772
message_->FindExtensionByLowercaseName("bar_foo"));
773
EXPECT_EQ(message_->extension(1),
774
message_->FindExtensionByLowercaseName("barbar"));
775
EXPECT_EQ(message_->extension(2),
776
message_->FindExtensionByLowercaseName("barbaz"));
777
EXPECT_TRUE(message_->FindExtensionByLowercaseName("BarBar") == NULL);
778
EXPECT_TRUE(message_->FindExtensionByLowercaseName("barBaz") == NULL);
779
EXPECT_TRUE(message_->FindExtensionByLowercaseName("foo_foo") == NULL);
780
EXPECT_TRUE(message_->FindExtensionByLowercaseName("nosuchfield") == NULL);
782
EXPECT_EQ(file_->extension(0),
783
file_->FindExtensionByLowercaseName("baz_foo"));
784
EXPECT_EQ(file_->extension(1),
785
file_->FindExtensionByLowercaseName("bazbar"));
786
EXPECT_EQ(file_->extension(2),
787
file_->FindExtensionByLowercaseName("bazbaz"));
788
EXPECT_TRUE(file_->FindExtensionByLowercaseName("BazBar") == NULL);
789
EXPECT_TRUE(file_->FindExtensionByLowercaseName("bazBaz") == NULL);
790
EXPECT_TRUE(file_->FindExtensionByLowercaseName("nosuchfield") == NULL);
793
TEST_F(StylizedFieldNamesTest, FindByCamelcaseName) {
794
EXPECT_EQ(message_->field(0),
795
message_->FindFieldByCamelcaseName("fooFoo"));
796
EXPECT_EQ(message_->field(1),
797
message_->FindFieldByCamelcaseName("fooBar"));
798
EXPECT_EQ(message_->field(2),
799
message_->FindFieldByCamelcaseName("fooBaz"));
800
EXPECT_TRUE(message_->FindFieldByCamelcaseName("foo_foo") == NULL);
801
EXPECT_TRUE(message_->FindFieldByCamelcaseName("FooBar") == NULL);
802
EXPECT_TRUE(message_->FindFieldByCamelcaseName("barFoo") == NULL);
803
EXPECT_TRUE(message_->FindFieldByCamelcaseName("nosuchfield") == NULL);
805
EXPECT_EQ(message_->extension(0),
806
message_->FindExtensionByCamelcaseName("barFoo"));
807
EXPECT_EQ(message_->extension(1),
808
message_->FindExtensionByCamelcaseName("barBar"));
809
EXPECT_EQ(message_->extension(2),
810
message_->FindExtensionByCamelcaseName("barBaz"));
811
EXPECT_TRUE(message_->FindExtensionByCamelcaseName("bar_foo") == NULL);
812
EXPECT_TRUE(message_->FindExtensionByCamelcaseName("BarBar") == NULL);
813
EXPECT_TRUE(message_->FindExtensionByCamelcaseName("fooFoo") == NULL);
814
EXPECT_TRUE(message_->FindExtensionByCamelcaseName("nosuchfield") == NULL);
816
EXPECT_EQ(file_->extension(0),
817
file_->FindExtensionByCamelcaseName("bazFoo"));
818
EXPECT_EQ(file_->extension(1),
819
file_->FindExtensionByCamelcaseName("bazBar"));
820
EXPECT_EQ(file_->extension(2),
821
file_->FindExtensionByCamelcaseName("bazBaz"));
822
EXPECT_TRUE(file_->FindExtensionByCamelcaseName("baz_foo") == NULL);
823
EXPECT_TRUE(file_->FindExtensionByCamelcaseName("BazBar") == NULL);
824
EXPECT_TRUE(file_->FindExtensionByCamelcaseName("nosuchfield") == NULL);
827
// ===================================================================
829
// Test enum descriptors.
830
class EnumDescriptorTest : public testing::Test {
832
virtual void SetUp() {
833
// Build descriptors for the following definitions:
842
// package corge.grault;
848
// TestEnum2 is primarily here to test FindValueByName and friends.
849
// All enums created from the same DescriptorPool share the same lookup
850
// table, so we need to insure that they don't interfere.
853
FileDescriptorProto foo_file;
854
foo_file.set_name("foo.proto");
856
EnumDescriptorProto* enum_proto = AddEnum(&foo_file, "TestEnum");
857
AddEnumValue(enum_proto, "FOO", 1);
858
AddEnumValue(enum_proto, "BAR", 2);
861
FileDescriptorProto bar_file;
862
bar_file.set_name("bar.proto");
863
bar_file.set_package("corge.grault");
865
EnumDescriptorProto* enum2_proto = AddEnum(&bar_file, "TestEnum2");
866
AddEnumValue(enum2_proto, "FOO", 1);
867
AddEnumValue(enum2_proto, "BAZ", 3);
869
// Build the descriptors and get the pointers.
870
foo_file_ = pool_.BuildFile(foo_file);
871
ASSERT_TRUE(foo_file_ != NULL);
873
bar_file_ = pool_.BuildFile(bar_file);
874
ASSERT_TRUE(bar_file_ != NULL);
876
ASSERT_EQ(1, foo_file_->enum_type_count());
877
enum_ = foo_file_->enum_type(0);
879
ASSERT_EQ(2, enum_->value_count());
880
foo_ = enum_->value(0);
881
bar_ = enum_->value(1);
883
ASSERT_EQ(1, bar_file_->enum_type_count());
884
enum2_ = bar_file_->enum_type(0);
886
ASSERT_EQ(2, enum2_->value_count());
887
foo2_ = enum2_->value(0);
888
baz2_ = enum2_->value(1);
891
DescriptorPool pool_;
893
const FileDescriptor* foo_file_;
894
const FileDescriptor* bar_file_;
896
const EnumDescriptor* enum_;
897
const EnumDescriptor* enum2_;
899
const EnumValueDescriptor* foo_;
900
const EnumValueDescriptor* bar_;
902
const EnumValueDescriptor* foo2_;
903
const EnumValueDescriptor* baz2_;
906
TEST_F(EnumDescriptorTest, Name) {
907
EXPECT_EQ("TestEnum", enum_->name());
908
EXPECT_EQ("TestEnum", enum_->full_name());
909
EXPECT_EQ(foo_file_, enum_->file());
911
EXPECT_EQ("TestEnum2", enum2_->name());
912
EXPECT_EQ("corge.grault.TestEnum2", enum2_->full_name());
913
EXPECT_EQ(bar_file_, enum2_->file());
916
TEST_F(EnumDescriptorTest, ContainingType) {
917
EXPECT_TRUE(enum_->containing_type() == NULL);
918
EXPECT_TRUE(enum2_->containing_type() == NULL);
921
TEST_F(EnumDescriptorTest, ValuesByIndex) {
922
ASSERT_EQ(2, enum_->value_count());
923
EXPECT_EQ(foo_, enum_->value(0));
924
EXPECT_EQ(bar_, enum_->value(1));
927
TEST_F(EnumDescriptorTest, FindValueByName) {
928
EXPECT_EQ(foo_ , enum_ ->FindValueByName("FOO"));
929
EXPECT_EQ(bar_ , enum_ ->FindValueByName("BAR"));
930
EXPECT_EQ(foo2_, enum2_->FindValueByName("FOO"));
931
EXPECT_EQ(baz2_, enum2_->FindValueByName("BAZ"));
933
EXPECT_TRUE(enum_ ->FindValueByName("NO_SUCH_VALUE") == NULL);
934
EXPECT_TRUE(enum_ ->FindValueByName("BAZ" ) == NULL);
935
EXPECT_TRUE(enum2_->FindValueByName("BAR" ) == NULL);
938
TEST_F(EnumDescriptorTest, FindValueByNumber) {
939
EXPECT_EQ(foo_ , enum_ ->FindValueByNumber(1));
940
EXPECT_EQ(bar_ , enum_ ->FindValueByNumber(2));
941
EXPECT_EQ(foo2_, enum2_->FindValueByNumber(1));
942
EXPECT_EQ(baz2_, enum2_->FindValueByNumber(3));
944
EXPECT_TRUE(enum_ ->FindValueByNumber(416) == NULL);
945
EXPECT_TRUE(enum_ ->FindValueByNumber(3) == NULL);
946
EXPECT_TRUE(enum2_->FindValueByNumber(2) == NULL);
949
TEST_F(EnumDescriptorTest, ValueName) {
950
EXPECT_EQ("FOO", foo_->name());
951
EXPECT_EQ("BAR", bar_->name());
954
TEST_F(EnumDescriptorTest, ValueFullName) {
955
EXPECT_EQ("FOO", foo_->full_name());
956
EXPECT_EQ("BAR", bar_->full_name());
957
EXPECT_EQ("corge.grault.FOO", foo2_->full_name());
958
EXPECT_EQ("corge.grault.BAZ", baz2_->full_name());
961
TEST_F(EnumDescriptorTest, ValueIndex) {
962
EXPECT_EQ(0, foo_->index());
963
EXPECT_EQ(1, bar_->index());
966
TEST_F(EnumDescriptorTest, ValueNumber) {
967
EXPECT_EQ(1, foo_->number());
968
EXPECT_EQ(2, bar_->number());
971
TEST_F(EnumDescriptorTest, ValueType) {
972
EXPECT_EQ(enum_ , foo_ ->type());
973
EXPECT_EQ(enum_ , bar_ ->type());
974
EXPECT_EQ(enum2_, foo2_->type());
975
EXPECT_EQ(enum2_, baz2_->type());
978
// ===================================================================
980
// Test service descriptors.
981
class ServiceDescriptorTest : public testing::Test {
983
virtual void SetUp() {
984
// Build descriptors for the following messages and service:
986
// message FooRequest {}
987
// message FooResponse {}
988
// message BarRequest {}
989
// message BarResponse {}
990
// message BazRequest {}
991
// message BazResponse {}
993
// service TestService {
994
// rpc Foo(FooRequest) returns (FooResponse);
995
// rpc Bar(BarRequest) returns (BarResponse);
999
// package corge.grault
1000
// service TestService2 {
1001
// rpc Foo(FooRequest) returns (FooResponse);
1002
// rpc Baz(BazRequest) returns (BazResponse);
1005
FileDescriptorProto foo_file;
1006
foo_file.set_name("foo.proto");
1008
AddMessage(&foo_file, "FooRequest");
1009
AddMessage(&foo_file, "FooResponse");
1010
AddMessage(&foo_file, "BarRequest");
1011
AddMessage(&foo_file, "BarResponse");
1012
AddMessage(&foo_file, "BazRequest");
1013
AddMessage(&foo_file, "BazResponse");
1015
ServiceDescriptorProto* service = AddService(&foo_file, "TestService");
1016
AddMethod(service, "Foo", "FooRequest", "FooResponse");
1017
AddMethod(service, "Bar", "BarRequest", "BarResponse");
1019
FileDescriptorProto bar_file;
1020
bar_file.set_name("bar.proto");
1021
bar_file.set_package("corge.grault");
1022
bar_file.add_dependency("foo.proto");
1024
ServiceDescriptorProto* service2 = AddService(&bar_file, "TestService2");
1025
AddMethod(service2, "Foo", "FooRequest", "FooResponse");
1026
AddMethod(service2, "Baz", "BazRequest", "BazResponse");
1028
// Build the descriptors and get the pointers.
1029
foo_file_ = pool_.BuildFile(foo_file);
1030
ASSERT_TRUE(foo_file_ != NULL);
1032
bar_file_ = pool_.BuildFile(bar_file);
1033
ASSERT_TRUE(bar_file_ != NULL);
1035
ASSERT_EQ(6, foo_file_->message_type_count());
1036
foo_request_ = foo_file_->message_type(0);
1037
foo_response_ = foo_file_->message_type(1);
1038
bar_request_ = foo_file_->message_type(2);
1039
bar_response_ = foo_file_->message_type(3);
1040
baz_request_ = foo_file_->message_type(4);
1041
baz_response_ = foo_file_->message_type(5);
1043
ASSERT_EQ(1, foo_file_->service_count());
1044
service_ = foo_file_->service(0);
1046
ASSERT_EQ(2, service_->method_count());
1047
foo_ = service_->method(0);
1048
bar_ = service_->method(1);
1050
ASSERT_EQ(1, bar_file_->service_count());
1051
service2_ = bar_file_->service(0);
1053
ASSERT_EQ(2, service2_->method_count());
1054
foo2_ = service2_->method(0);
1055
baz2_ = service2_->method(1);
1058
DescriptorPool pool_;
1060
const FileDescriptor* foo_file_;
1061
const FileDescriptor* bar_file_;
1063
const Descriptor* foo_request_;
1064
const Descriptor* foo_response_;
1065
const Descriptor* bar_request_;
1066
const Descriptor* bar_response_;
1067
const Descriptor* baz_request_;
1068
const Descriptor* baz_response_;
1070
const ServiceDescriptor* service_;
1071
const ServiceDescriptor* service2_;
1073
const MethodDescriptor* foo_;
1074
const MethodDescriptor* bar_;
1076
const MethodDescriptor* foo2_;
1077
const MethodDescriptor* baz2_;
1080
TEST_F(ServiceDescriptorTest, Name) {
1081
EXPECT_EQ("TestService", service_->name());
1082
EXPECT_EQ("TestService", service_->full_name());
1083
EXPECT_EQ(foo_file_, service_->file());
1085
EXPECT_EQ("TestService2", service2_->name());
1086
EXPECT_EQ("corge.grault.TestService2", service2_->full_name());
1087
EXPECT_EQ(bar_file_, service2_->file());
1090
TEST_F(ServiceDescriptorTest, MethodsByIndex) {
1091
ASSERT_EQ(2, service_->method_count());
1092
EXPECT_EQ(foo_, service_->method(0));
1093
EXPECT_EQ(bar_, service_->method(1));
1096
TEST_F(ServiceDescriptorTest, FindMethodByName) {
1097
EXPECT_EQ(foo_ , service_ ->FindMethodByName("Foo"));
1098
EXPECT_EQ(bar_ , service_ ->FindMethodByName("Bar"));
1099
EXPECT_EQ(foo2_, service2_->FindMethodByName("Foo"));
1100
EXPECT_EQ(baz2_, service2_->FindMethodByName("Baz"));
1102
EXPECT_TRUE(service_ ->FindMethodByName("NoSuchMethod") == NULL);
1103
EXPECT_TRUE(service_ ->FindMethodByName("Baz" ) == NULL);
1104
EXPECT_TRUE(service2_->FindMethodByName("Bar" ) == NULL);
1107
TEST_F(ServiceDescriptorTest, MethodName) {
1108
EXPECT_EQ("Foo", foo_->name());
1109
EXPECT_EQ("Bar", bar_->name());
1112
TEST_F(ServiceDescriptorTest, MethodFullName) {
1113
EXPECT_EQ("TestService.Foo", foo_->full_name());
1114
EXPECT_EQ("TestService.Bar", bar_->full_name());
1115
EXPECT_EQ("corge.grault.TestService2.Foo", foo2_->full_name());
1116
EXPECT_EQ("corge.grault.TestService2.Baz", baz2_->full_name());
1119
TEST_F(ServiceDescriptorTest, MethodIndex) {
1120
EXPECT_EQ(0, foo_->index());
1121
EXPECT_EQ(1, bar_->index());
1124
TEST_F(ServiceDescriptorTest, MethodParent) {
1125
EXPECT_EQ(service_, foo_->service());
1126
EXPECT_EQ(service_, bar_->service());
1129
TEST_F(ServiceDescriptorTest, MethodInputType) {
1130
EXPECT_EQ(foo_request_, foo_->input_type());
1131
EXPECT_EQ(bar_request_, bar_->input_type());
1134
TEST_F(ServiceDescriptorTest, MethodOutputType) {
1135
EXPECT_EQ(foo_response_, foo_->output_type());
1136
EXPECT_EQ(bar_response_, bar_->output_type());
1139
// ===================================================================
1141
// Test nested types.
1142
class NestedDescriptorTest : public testing::Test {
1144
virtual void SetUp() {
1145
// Build descriptors for the following definitions:
1147
// // in "foo.proto"
1148
// message TestMessage {
1151
// enum Baz { A = 1; }
1152
// enum Qux { B = 1; }
1155
// // in "bar.proto"
1156
// package corge.grault;
1157
// message TestMessage2 {
1160
// enum Qux { A = 1; }
1161
// enum Quux { C = 1; }
1164
// TestMessage2 is primarily here to test FindNestedTypeByName and friends.
1165
// All messages created from the same DescriptorPool share the same lookup
1166
// table, so we need to insure that they don't interfere.
1168
// We add enum values to the enums in order to test searching for enum
1169
// values across a message's scope.
1171
FileDescriptorProto foo_file;
1172
foo_file.set_name("foo.proto");
1174
DescriptorProto* message = AddMessage(&foo_file, "TestMessage");
1175
AddNestedMessage(message, "Foo");
1176
AddNestedMessage(message, "Bar");
1177
EnumDescriptorProto* baz = AddNestedEnum(message, "Baz");
1178
AddEnumValue(baz, "A", 1);
1179
EnumDescriptorProto* qux = AddNestedEnum(message, "Qux");
1180
AddEnumValue(qux, "B", 1);
1182
FileDescriptorProto bar_file;
1183
bar_file.set_name("bar.proto");
1184
bar_file.set_package("corge.grault");
1186
DescriptorProto* message2 = AddMessage(&bar_file, "TestMessage2");
1187
AddNestedMessage(message2, "Foo");
1188
AddNestedMessage(message2, "Baz");
1189
EnumDescriptorProto* qux2 = AddNestedEnum(message2, "Qux");
1190
AddEnumValue(qux2, "A", 1);
1191
EnumDescriptorProto* quux2 = AddNestedEnum(message2, "Quux");
1192
AddEnumValue(quux2, "C", 1);
1194
// Build the descriptors and get the pointers.
1195
foo_file_ = pool_.BuildFile(foo_file);
1196
ASSERT_TRUE(foo_file_ != NULL);
1198
bar_file_ = pool_.BuildFile(bar_file);
1199
ASSERT_TRUE(bar_file_ != NULL);
1201
ASSERT_EQ(1, foo_file_->message_type_count());
1202
message_ = foo_file_->message_type(0);
1204
ASSERT_EQ(2, message_->nested_type_count());
1205
foo_ = message_->nested_type(0);
1206
bar_ = message_->nested_type(1);
1208
ASSERT_EQ(2, message_->enum_type_count());
1209
baz_ = message_->enum_type(0);
1210
qux_ = message_->enum_type(1);
1212
ASSERT_EQ(1, baz_->value_count());
1213
a_ = baz_->value(0);
1214
ASSERT_EQ(1, qux_->value_count());
1215
b_ = qux_->value(0);
1217
ASSERT_EQ(1, bar_file_->message_type_count());
1218
message2_ = bar_file_->message_type(0);
1220
ASSERT_EQ(2, message2_->nested_type_count());
1221
foo2_ = message2_->nested_type(0);
1222
baz2_ = message2_->nested_type(1);
1224
ASSERT_EQ(2, message2_->enum_type_count());
1225
qux2_ = message2_->enum_type(0);
1226
quux2_ = message2_->enum_type(1);
1228
ASSERT_EQ(1, qux2_->value_count());
1229
a2_ = qux2_->value(0);
1230
ASSERT_EQ(1, quux2_->value_count());
1231
c2_ = quux2_->value(0);
1234
DescriptorPool pool_;
1236
const FileDescriptor* foo_file_;
1237
const FileDescriptor* bar_file_;
1239
const Descriptor* message_;
1240
const Descriptor* message2_;
1242
const Descriptor* foo_;
1243
const Descriptor* bar_;
1244
const EnumDescriptor* baz_;
1245
const EnumDescriptor* qux_;
1246
const EnumValueDescriptor* a_;
1247
const EnumValueDescriptor* b_;
1249
const Descriptor* foo2_;
1250
const Descriptor* baz2_;
1251
const EnumDescriptor* qux2_;
1252
const EnumDescriptor* quux2_;
1253
const EnumValueDescriptor* a2_;
1254
const EnumValueDescriptor* c2_;
1257
TEST_F(NestedDescriptorTest, MessageName) {
1258
EXPECT_EQ("Foo", foo_ ->name());
1259
EXPECT_EQ("Bar", bar_ ->name());
1260
EXPECT_EQ("Foo", foo2_->name());
1261
EXPECT_EQ("Baz", baz2_->name());
1263
EXPECT_EQ("TestMessage.Foo", foo_->full_name());
1264
EXPECT_EQ("TestMessage.Bar", bar_->full_name());
1265
EXPECT_EQ("corge.grault.TestMessage2.Foo", foo2_->full_name());
1266
EXPECT_EQ("corge.grault.TestMessage2.Baz", baz2_->full_name());
1269
TEST_F(NestedDescriptorTest, MessageContainingType) {
1270
EXPECT_EQ(message_ , foo_ ->containing_type());
1271
EXPECT_EQ(message_ , bar_ ->containing_type());
1272
EXPECT_EQ(message2_, foo2_->containing_type());
1273
EXPECT_EQ(message2_, baz2_->containing_type());
1276
TEST_F(NestedDescriptorTest, NestedMessagesByIndex) {
1277
ASSERT_EQ(2, message_->nested_type_count());
1278
EXPECT_EQ(foo_, message_->nested_type(0));
1279
EXPECT_EQ(bar_, message_->nested_type(1));
1282
TEST_F(NestedDescriptorTest, FindFieldByNameDoesntFindNestedTypes) {
1283
EXPECT_TRUE(message_->FindFieldByName("Foo") == NULL);
1284
EXPECT_TRUE(message_->FindFieldByName("Qux") == NULL);
1285
EXPECT_TRUE(message_->FindExtensionByName("Foo") == NULL);
1286
EXPECT_TRUE(message_->FindExtensionByName("Qux") == NULL);
1289
TEST_F(NestedDescriptorTest, FindNestedTypeByName) {
1290
EXPECT_EQ(foo_ , message_ ->FindNestedTypeByName("Foo"));
1291
EXPECT_EQ(bar_ , message_ ->FindNestedTypeByName("Bar"));
1292
EXPECT_EQ(foo2_, message2_->FindNestedTypeByName("Foo"));
1293
EXPECT_EQ(baz2_, message2_->FindNestedTypeByName("Baz"));
1295
EXPECT_TRUE(message_ ->FindNestedTypeByName("NoSuchType") == NULL);
1296
EXPECT_TRUE(message_ ->FindNestedTypeByName("Baz" ) == NULL);
1297
EXPECT_TRUE(message2_->FindNestedTypeByName("Bar" ) == NULL);
1299
EXPECT_TRUE(message_->FindNestedTypeByName("Qux") == NULL);
1302
TEST_F(NestedDescriptorTest, EnumName) {
1303
EXPECT_EQ("Baz" , baz_ ->name());
1304
EXPECT_EQ("Qux" , qux_ ->name());
1305
EXPECT_EQ("Qux" , qux2_->name());
1306
EXPECT_EQ("Quux", quux2_->name());
1308
EXPECT_EQ("TestMessage.Baz", baz_->full_name());
1309
EXPECT_EQ("TestMessage.Qux", qux_->full_name());
1310
EXPECT_EQ("corge.grault.TestMessage2.Qux" , qux2_ ->full_name());
1311
EXPECT_EQ("corge.grault.TestMessage2.Quux", quux2_->full_name());
1314
TEST_F(NestedDescriptorTest, EnumContainingType) {
1315
EXPECT_EQ(message_ , baz_ ->containing_type());
1316
EXPECT_EQ(message_ , qux_ ->containing_type());
1317
EXPECT_EQ(message2_, qux2_ ->containing_type());
1318
EXPECT_EQ(message2_, quux2_->containing_type());
1321
TEST_F(NestedDescriptorTest, NestedEnumsByIndex) {
1322
ASSERT_EQ(2, message_->nested_type_count());
1323
EXPECT_EQ(foo_, message_->nested_type(0));
1324
EXPECT_EQ(bar_, message_->nested_type(1));
1327
TEST_F(NestedDescriptorTest, FindEnumTypeByName) {
1328
EXPECT_EQ(baz_ , message_ ->FindEnumTypeByName("Baz" ));
1329
EXPECT_EQ(qux_ , message_ ->FindEnumTypeByName("Qux" ));
1330
EXPECT_EQ(qux2_ , message2_->FindEnumTypeByName("Qux" ));
1331
EXPECT_EQ(quux2_, message2_->FindEnumTypeByName("Quux"));
1333
EXPECT_TRUE(message_ ->FindEnumTypeByName("NoSuchType") == NULL);
1334
EXPECT_TRUE(message_ ->FindEnumTypeByName("Quux" ) == NULL);
1335
EXPECT_TRUE(message2_->FindEnumTypeByName("Baz" ) == NULL);
1337
EXPECT_TRUE(message_->FindEnumTypeByName("Foo") == NULL);
1340
TEST_F(NestedDescriptorTest, FindEnumValueByName) {
1341
EXPECT_EQ(a_ , message_ ->FindEnumValueByName("A"));
1342
EXPECT_EQ(b_ , message_ ->FindEnumValueByName("B"));
1343
EXPECT_EQ(a2_, message2_->FindEnumValueByName("A"));
1344
EXPECT_EQ(c2_, message2_->FindEnumValueByName("C"));
1346
EXPECT_TRUE(message_ ->FindEnumValueByName("NO_SUCH_VALUE") == NULL);
1347
EXPECT_TRUE(message_ ->FindEnumValueByName("C" ) == NULL);
1348
EXPECT_TRUE(message2_->FindEnumValueByName("B" ) == NULL);
1350
EXPECT_TRUE(message_->FindEnumValueByName("Foo") == NULL);
1353
// ===================================================================
1356
class ExtensionDescriptorTest : public testing::Test {
1358
virtual void SetUp() {
1359
// Build descriptors for the following definitions:
1365
// extensions 10 to 19;
1366
// extensions 30 to 39;
1368
// extends Foo with optional int32 foo_int32 = 10;
1369
// extends Foo with repeated TestEnum foo_enum = 19;
1371
// extends Foo with optional Qux foo_message = 30;
1372
// // (using Qux as the group type)
1373
// extends Foo with repeated group foo_group = 39;
1376
FileDescriptorProto foo_file;
1377
foo_file.set_name("foo.proto");
1379
AddEmptyEnum(&foo_file, "Baz");
1380
AddMessage(&foo_file, "Qux");
1382
DescriptorProto* foo = AddMessage(&foo_file, "Foo");
1383
AddExtensionRange(foo, 10, 20);
1384
AddExtensionRange(foo, 30, 40);
1386
AddExtension(&foo_file, "Foo", "foo_int32", 10,
1387
FieldDescriptorProto::LABEL_OPTIONAL,
1388
FieldDescriptorProto::TYPE_INT32);
1389
AddExtension(&foo_file, "Foo", "foo_enum", 19,
1390
FieldDescriptorProto::LABEL_REPEATED,
1391
FieldDescriptorProto::TYPE_ENUM)
1392
->set_type_name("Baz");
1394
DescriptorProto* bar = AddMessage(&foo_file, "Bar");
1395
AddNestedExtension(bar, "Foo", "foo_message", 30,
1396
FieldDescriptorProto::LABEL_OPTIONAL,
1397
FieldDescriptorProto::TYPE_MESSAGE)
1398
->set_type_name("Qux");
1399
AddNestedExtension(bar, "Foo", "foo_group", 39,
1400
FieldDescriptorProto::LABEL_REPEATED,
1401
FieldDescriptorProto::TYPE_GROUP)
1402
->set_type_name("Qux");
1404
// Build the descriptors and get the pointers.
1405
foo_file_ = pool_.BuildFile(foo_file);
1406
ASSERT_TRUE(foo_file_ != NULL);
1408
ASSERT_EQ(1, foo_file_->enum_type_count());
1409
baz_ = foo_file_->enum_type(0);
1411
ASSERT_EQ(3, foo_file_->message_type_count());
1412
qux_ = foo_file_->message_type(0);
1413
foo_ = foo_file_->message_type(1);
1414
bar_ = foo_file_->message_type(2);
1417
DescriptorPool pool_;
1419
const FileDescriptor* foo_file_;
1421
const Descriptor* foo_;
1422
const Descriptor* bar_;
1423
const EnumDescriptor* baz_;
1424
const Descriptor* qux_;
1427
TEST_F(ExtensionDescriptorTest, ExtensionRanges) {
1428
EXPECT_EQ(0, bar_->extension_range_count());
1429
ASSERT_EQ(2, foo_->extension_range_count());
1431
EXPECT_EQ(10, foo_->extension_range(0)->start);
1432
EXPECT_EQ(30, foo_->extension_range(1)->start);
1434
EXPECT_EQ(20, foo_->extension_range(0)->end);
1435
EXPECT_EQ(40, foo_->extension_range(1)->end);
1438
TEST_F(ExtensionDescriptorTest, Extensions) {
1439
EXPECT_EQ(0, foo_->extension_count());
1440
ASSERT_EQ(2, foo_file_->extension_count());
1441
ASSERT_EQ(2, bar_->extension_count());
1443
EXPECT_TRUE(foo_file_->extension(0)->is_extension());
1444
EXPECT_TRUE(foo_file_->extension(1)->is_extension());
1445
EXPECT_TRUE(bar_->extension(0)->is_extension());
1446
EXPECT_TRUE(bar_->extension(1)->is_extension());
1448
EXPECT_EQ("foo_int32" , foo_file_->extension(0)->name());
1449
EXPECT_EQ("foo_enum" , foo_file_->extension(1)->name());
1450
EXPECT_EQ("foo_message", bar_->extension(0)->name());
1451
EXPECT_EQ("foo_group" , bar_->extension(1)->name());
1453
EXPECT_EQ(10, foo_file_->extension(0)->number());
1454
EXPECT_EQ(19, foo_file_->extension(1)->number());
1455
EXPECT_EQ(30, bar_->extension(0)->number());
1456
EXPECT_EQ(39, bar_->extension(1)->number());
1458
EXPECT_EQ(FieldDescriptor::TYPE_INT32 , foo_file_->extension(0)->type());
1459
EXPECT_EQ(FieldDescriptor::TYPE_ENUM , foo_file_->extension(1)->type());
1460
EXPECT_EQ(FieldDescriptor::TYPE_MESSAGE, bar_->extension(0)->type());
1461
EXPECT_EQ(FieldDescriptor::TYPE_GROUP , bar_->extension(1)->type());
1463
EXPECT_EQ(baz_, foo_file_->extension(1)->enum_type());
1464
EXPECT_EQ(qux_, bar_->extension(0)->message_type());
1465
EXPECT_EQ(qux_, bar_->extension(1)->message_type());
1467
EXPECT_EQ(FieldDescriptor::LABEL_OPTIONAL, foo_file_->extension(0)->label());
1468
EXPECT_EQ(FieldDescriptor::LABEL_REPEATED, foo_file_->extension(1)->label());
1469
EXPECT_EQ(FieldDescriptor::LABEL_OPTIONAL, bar_->extension(0)->label());
1470
EXPECT_EQ(FieldDescriptor::LABEL_REPEATED, bar_->extension(1)->label());
1472
EXPECT_EQ(foo_, foo_file_->extension(0)->containing_type());
1473
EXPECT_EQ(foo_, foo_file_->extension(1)->containing_type());
1474
EXPECT_EQ(foo_, bar_->extension(0)->containing_type());
1475
EXPECT_EQ(foo_, bar_->extension(1)->containing_type());
1477
EXPECT_TRUE(foo_file_->extension(0)->extension_scope() == NULL);
1478
EXPECT_TRUE(foo_file_->extension(1)->extension_scope() == NULL);
1479
EXPECT_EQ(bar_, bar_->extension(0)->extension_scope());
1480
EXPECT_EQ(bar_, bar_->extension(1)->extension_scope());
1483
TEST_F(ExtensionDescriptorTest, IsExtensionNumber) {
1484
EXPECT_FALSE(foo_->IsExtensionNumber( 9));
1485
EXPECT_TRUE (foo_->IsExtensionNumber(10));
1486
EXPECT_TRUE (foo_->IsExtensionNumber(19));
1487
EXPECT_FALSE(foo_->IsExtensionNumber(20));
1488
EXPECT_FALSE(foo_->IsExtensionNumber(29));
1489
EXPECT_TRUE (foo_->IsExtensionNumber(30));
1490
EXPECT_TRUE (foo_->IsExtensionNumber(39));
1491
EXPECT_FALSE(foo_->IsExtensionNumber(40));
1494
TEST_F(ExtensionDescriptorTest, FindExtensionByName) {
1495
// Note that FileDescriptor::FindExtensionByName() is tested by
1496
// FileDescriptorTest.
1497
ASSERT_EQ(2, bar_->extension_count());
1499
EXPECT_EQ(bar_->extension(0), bar_->FindExtensionByName("foo_message"));
1500
EXPECT_EQ(bar_->extension(1), bar_->FindExtensionByName("foo_group" ));
1502
EXPECT_TRUE(bar_->FindExtensionByName("no_such_extension") == NULL);
1503
EXPECT_TRUE(foo_->FindExtensionByName("foo_int32") == NULL);
1504
EXPECT_TRUE(foo_->FindExtensionByName("foo_message") == NULL);
1507
TEST_F(ExtensionDescriptorTest, FindAllExtensions) {
1508
vector<const FieldDescriptor*> extensions;
1509
pool_.FindAllExtensions(foo_, &extensions);
1510
ASSERT_EQ(4, extensions.size());
1511
EXPECT_EQ(10, extensions[0]->number());
1512
EXPECT_EQ(19, extensions[1]->number());
1513
EXPECT_EQ(30, extensions[2]->number());
1514
EXPECT_EQ(39, extensions[3]->number());
1517
// ===================================================================
1519
class MiscTest : public testing::Test {
1521
// Function which makes a field of the given type just to find out what its
1523
FieldDescriptor::CppType GetCppTypeForFieldType(FieldDescriptor::Type type) {
1524
FileDescriptorProto file_proto;
1525
file_proto.set_name("foo.proto");
1526
AddEmptyEnum(&file_proto, "DummyEnum");
1528
DescriptorProto* message = AddMessage(&file_proto, "TestMessage");
1529
FieldDescriptorProto* field =
1530
AddField(message, "foo", 1, FieldDescriptorProto::LABEL_OPTIONAL,
1531
static_cast<FieldDescriptorProto::Type>(static_cast<int>(type)));
1533
if (type == FieldDescriptor::TYPE_MESSAGE ||
1534
type == FieldDescriptor::TYPE_GROUP) {
1535
field->set_type_name("TestMessage");
1536
} else if (type == FieldDescriptor::TYPE_ENUM) {
1537
field->set_type_name("DummyEnum");
1540
// Build the descriptors and get the pointers.
1541
DescriptorPool pool;
1542
const FileDescriptor* file = pool.BuildFile(file_proto);
1545
file->message_type_count() == 1 &&
1546
file->message_type(0)->field_count() == 1) {
1547
return file->message_type(0)->field(0)->cpp_type();
1549
return static_cast<FieldDescriptor::CppType>(0);
1554
TEST_F(MiscTest, CppTypes) {
1555
// Test that CPP types are assigned correctly.
1557
typedef FieldDescriptor FD; // avoid ugly line wrapping
1559
EXPECT_EQ(FD::CPPTYPE_DOUBLE , GetCppTypeForFieldType(FD::TYPE_DOUBLE ));
1560
EXPECT_EQ(FD::CPPTYPE_FLOAT , GetCppTypeForFieldType(FD::TYPE_FLOAT ));
1561
EXPECT_EQ(FD::CPPTYPE_INT64 , GetCppTypeForFieldType(FD::TYPE_INT64 ));
1562
EXPECT_EQ(FD::CPPTYPE_UINT64 , GetCppTypeForFieldType(FD::TYPE_UINT64 ));
1563
EXPECT_EQ(FD::CPPTYPE_INT32 , GetCppTypeForFieldType(FD::TYPE_INT32 ));
1564
EXPECT_EQ(FD::CPPTYPE_UINT64 , GetCppTypeForFieldType(FD::TYPE_FIXED64 ));
1565
EXPECT_EQ(FD::CPPTYPE_UINT32 , GetCppTypeForFieldType(FD::TYPE_FIXED32 ));
1566
EXPECT_EQ(FD::CPPTYPE_BOOL , GetCppTypeForFieldType(FD::TYPE_BOOL ));
1567
EXPECT_EQ(FD::CPPTYPE_STRING , GetCppTypeForFieldType(FD::TYPE_STRING ));
1568
EXPECT_EQ(FD::CPPTYPE_MESSAGE, GetCppTypeForFieldType(FD::TYPE_GROUP ));
1569
EXPECT_EQ(FD::CPPTYPE_MESSAGE, GetCppTypeForFieldType(FD::TYPE_MESSAGE ));
1570
EXPECT_EQ(FD::CPPTYPE_STRING , GetCppTypeForFieldType(FD::TYPE_BYTES ));
1571
EXPECT_EQ(FD::CPPTYPE_UINT32 , GetCppTypeForFieldType(FD::TYPE_UINT32 ));
1572
EXPECT_EQ(FD::CPPTYPE_ENUM , GetCppTypeForFieldType(FD::TYPE_ENUM ));
1573
EXPECT_EQ(FD::CPPTYPE_INT32 , GetCppTypeForFieldType(FD::TYPE_SFIXED32));
1574
EXPECT_EQ(FD::CPPTYPE_INT64 , GetCppTypeForFieldType(FD::TYPE_SFIXED64));
1575
EXPECT_EQ(FD::CPPTYPE_INT32 , GetCppTypeForFieldType(FD::TYPE_SINT32 ));
1576
EXPECT_EQ(FD::CPPTYPE_INT64 , GetCppTypeForFieldType(FD::TYPE_SINT64 ));
1579
TEST_F(MiscTest, DefaultValues) {
1580
// Test that setting default values works.
1581
FileDescriptorProto file_proto;
1582
file_proto.set_name("foo.proto");
1584
EnumDescriptorProto* enum_type_proto = AddEnum(&file_proto, "DummyEnum");
1585
AddEnumValue(enum_type_proto, "A", 1);
1586
AddEnumValue(enum_type_proto, "B", 2);
1588
DescriptorProto* message_proto = AddMessage(&file_proto, "TestMessage");
1590
typedef FieldDescriptorProto FD; // avoid ugly line wrapping
1591
const FD::Label label = FD::LABEL_OPTIONAL;
1593
// Create fields of every CPP type with default values.
1594
AddField(message_proto, "int32" , 1, label, FD::TYPE_INT32 )
1595
->set_default_value("-1");
1596
AddField(message_proto, "int64" , 2, label, FD::TYPE_INT64 )
1597
->set_default_value("-1000000000000");
1598
AddField(message_proto, "uint32", 3, label, FD::TYPE_UINT32)
1599
->set_default_value("42");
1600
AddField(message_proto, "uint64", 4, label, FD::TYPE_UINT64)
1601
->set_default_value("2000000000000");
1602
AddField(message_proto, "float" , 5, label, FD::TYPE_FLOAT )
1603
->set_default_value("4.5");
1604
AddField(message_proto, "double", 6, label, FD::TYPE_DOUBLE)
1605
->set_default_value("10e100");
1606
AddField(message_proto, "bool" , 7, label, FD::TYPE_BOOL )
1607
->set_default_value("true");
1608
AddField(message_proto, "string", 8, label, FD::TYPE_STRING)
1609
->set_default_value("hello");
1610
AddField(message_proto, "data" , 9, label, FD::TYPE_BYTES )
1611
->set_default_value("\\001\\002\\003");
1613
FieldDescriptorProto* enum_field =
1614
AddField(message_proto, "enum", 10, label, FD::TYPE_ENUM);
1615
enum_field->set_type_name("DummyEnum");
1616
enum_field->set_default_value("B");
1618
// Strings are allowed to have empty defaults. (At one point, due to
1619
// a bug, empty defaults for strings were rejected. Oops.)
1620
AddField(message_proto, "empty_string", 11, label, FD::TYPE_STRING)
1621
->set_default_value("");
1623
// Add a second set of fields with implicit defalut values.
1624
AddField(message_proto, "implicit_int32" , 21, label, FD::TYPE_INT32 );
1625
AddField(message_proto, "implicit_int64" , 22, label, FD::TYPE_INT64 );
1626
AddField(message_proto, "implicit_uint32", 23, label, FD::TYPE_UINT32);
1627
AddField(message_proto, "implicit_uint64", 24, label, FD::TYPE_UINT64);
1628
AddField(message_proto, "implicit_float" , 25, label, FD::TYPE_FLOAT );
1629
AddField(message_proto, "implicit_double", 26, label, FD::TYPE_DOUBLE);
1630
AddField(message_proto, "implicit_bool" , 27, label, FD::TYPE_BOOL );
1631
AddField(message_proto, "implicit_string", 28, label, FD::TYPE_STRING);
1632
AddField(message_proto, "implicit_data" , 29, label, FD::TYPE_BYTES );
1633
AddField(message_proto, "implicit_enum" , 30, label, FD::TYPE_ENUM)
1634
->set_type_name("DummyEnum");
1637
DescriptorPool pool;
1638
const FileDescriptor* file = pool.BuildFile(file_proto);
1639
ASSERT_TRUE(file != NULL);
1641
ASSERT_EQ(1, file->enum_type_count());
1642
const EnumDescriptor* enum_type = file->enum_type(0);
1643
ASSERT_EQ(2, enum_type->value_count());
1644
const EnumValueDescriptor* enum_value_a = enum_type->value(0);
1645
const EnumValueDescriptor* enum_value_b = enum_type->value(1);
1647
ASSERT_EQ(1, file->message_type_count());
1648
const Descriptor* message = file->message_type(0);
1650
ASSERT_EQ(21, message->field_count());
1652
// Check the default values.
1653
ASSERT_TRUE(message->field(0)->has_default_value());
1654
ASSERT_TRUE(message->field(1)->has_default_value());
1655
ASSERT_TRUE(message->field(2)->has_default_value());
1656
ASSERT_TRUE(message->field(3)->has_default_value());
1657
ASSERT_TRUE(message->field(4)->has_default_value());
1658
ASSERT_TRUE(message->field(5)->has_default_value());
1659
ASSERT_TRUE(message->field(6)->has_default_value());
1660
ASSERT_TRUE(message->field(7)->has_default_value());
1661
ASSERT_TRUE(message->field(8)->has_default_value());
1662
ASSERT_TRUE(message->field(9)->has_default_value());
1663
ASSERT_TRUE(message->field(10)->has_default_value());
1665
EXPECT_EQ(-1 , message->field(0)->default_value_int32 ());
1666
EXPECT_EQ(-GOOGLE_ULONGLONG(1000000000000),
1667
message->field(1)->default_value_int64 ());
1668
EXPECT_EQ(42 , message->field(2)->default_value_uint32());
1669
EXPECT_EQ(GOOGLE_ULONGLONG(2000000000000),
1670
message->field(3)->default_value_uint64());
1671
EXPECT_EQ(4.5 , message->field(4)->default_value_float ());
1672
EXPECT_EQ(10e100 , message->field(5)->default_value_double());
1673
EXPECT_EQ(true , message->field(6)->default_value_bool ());
1674
EXPECT_EQ("hello" , message->field(7)->default_value_string());
1675
EXPECT_EQ("\001\002\003" , message->field(8)->default_value_string());
1676
EXPECT_EQ(enum_value_b , message->field(9)->default_value_enum ());
1677
EXPECT_EQ("" , message->field(10)->default_value_string());
1679
ASSERT_FALSE(message->field(11)->has_default_value());
1680
ASSERT_FALSE(message->field(12)->has_default_value());
1681
ASSERT_FALSE(message->field(13)->has_default_value());
1682
ASSERT_FALSE(message->field(14)->has_default_value());
1683
ASSERT_FALSE(message->field(15)->has_default_value());
1684
ASSERT_FALSE(message->field(16)->has_default_value());
1685
ASSERT_FALSE(message->field(17)->has_default_value());
1686
ASSERT_FALSE(message->field(18)->has_default_value());
1687
ASSERT_FALSE(message->field(19)->has_default_value());
1688
ASSERT_FALSE(message->field(20)->has_default_value());
1690
EXPECT_EQ(0 , message->field(11)->default_value_int32 ());
1691
EXPECT_EQ(0 , message->field(12)->default_value_int64 ());
1692
EXPECT_EQ(0 , message->field(13)->default_value_uint32());
1693
EXPECT_EQ(0 , message->field(14)->default_value_uint64());
1694
EXPECT_EQ(0.0f , message->field(15)->default_value_float ());
1695
EXPECT_EQ(0.0 , message->field(16)->default_value_double());
1696
EXPECT_EQ(false, message->field(17)->default_value_bool ());
1697
EXPECT_EQ("" , message->field(18)->default_value_string());
1698
EXPECT_EQ("" , message->field(19)->default_value_string());
1699
EXPECT_EQ(enum_value_a, message->field(20)->default_value_enum());
1702
TEST_F(MiscTest, FieldOptions) {
1703
// Try setting field options.
1705
FileDescriptorProto file_proto;
1706
file_proto.set_name("foo.proto");
1708
DescriptorProto* message_proto = AddMessage(&file_proto, "TestMessage");
1709
AddField(message_proto, "foo", 1,
1710
FieldDescriptorProto::LABEL_OPTIONAL,
1711
FieldDescriptorProto::TYPE_INT32);
1712
FieldDescriptorProto* bar_proto =
1713
AddField(message_proto, "bar", 2,
1714
FieldDescriptorProto::LABEL_OPTIONAL,
1715
FieldDescriptorProto::TYPE_INT32);
1717
FieldOptions* options = bar_proto->mutable_options();
1718
options->set_ctype(FieldOptions::CORD);
1720
// Build the descriptors and get the pointers.
1721
DescriptorPool pool;
1722
const FileDescriptor* file = pool.BuildFile(file_proto);
1723
ASSERT_TRUE(file != NULL);
1725
ASSERT_EQ(1, file->message_type_count());
1726
const Descriptor* message = file->message_type(0);
1728
ASSERT_EQ(2, message->field_count());
1729
const FieldDescriptor* foo = message->field(0);
1730
const FieldDescriptor* bar = message->field(1);
1732
// "foo" had no options set, so it should return the default options.
1733
EXPECT_EQ(&FieldOptions::default_instance(), &foo->options());
1735
// "bar" had options set.
1736
EXPECT_NE(&FieldOptions::default_instance(), options);
1737
EXPECT_TRUE(bar->options().has_ctype());
1738
EXPECT_EQ(FieldOptions::CORD, bar->options().ctype());
1741
// ===================================================================
1743
class AllowUnknownDependenciesTest : public testing::Test {
1745
virtual void SetUp() {
1746
FileDescriptorProto foo_proto, bar_proto;
1748
pool_.AllowUnknownDependencies();
1750
ASSERT_TRUE(TextFormat::ParseFromString(
1752
"dependency: 'bar.proto'"
1753
"dependency: 'baz.proto'"
1756
" field { name:'bar' number:1 label:LABEL_OPTIONAL type_name:'Bar' }"
1757
" field { name:'baz' number:2 label:LABEL_OPTIONAL type_name:'Baz' }"
1758
" field { name:'qux' number:3 label:LABEL_OPTIONAL"
1759
" type_name: '.corge.Qux'"
1762
" uninterpreted_option {"
1764
" name_part: 'grault'"
1765
" is_extension: true"
1767
" positive_int_value: 1234"
1773
ASSERT_TRUE(TextFormat::ParseFromString(
1775
"message_type { name: 'Bar' }",
1778
// Collect pointers to stuff.
1779
bar_file_ = pool_.BuildFile(bar_proto);
1780
ASSERT_TRUE(bar_file_ != NULL);
1782
ASSERT_EQ(1, bar_file_->message_type_count());
1783
bar_type_ = bar_file_->message_type(0);
1785
foo_file_ = pool_.BuildFile(foo_proto);
1786
ASSERT_TRUE(foo_file_ != NULL);
1788
ASSERT_EQ(1, foo_file_->message_type_count());
1789
foo_type_ = foo_file_->message_type(0);
1791
ASSERT_EQ(3, foo_type_->field_count());
1792
bar_field_ = foo_type_->field(0);
1793
baz_field_ = foo_type_->field(1);
1794
qux_field_ = foo_type_->field(2);
1797
const FileDescriptor* bar_file_;
1798
const Descriptor* bar_type_;
1799
const FileDescriptor* foo_file_;
1800
const Descriptor* foo_type_;
1801
const FieldDescriptor* bar_field_;
1802
const FieldDescriptor* baz_field_;
1803
const FieldDescriptor* qux_field_;
1805
DescriptorPool pool_;
1808
TEST_F(AllowUnknownDependenciesTest, PlaceholderFile) {
1809
ASSERT_EQ(2, foo_file_->dependency_count());
1810
EXPECT_EQ(bar_file_, foo_file_->dependency(0));
1812
const FileDescriptor* baz_file = foo_file_->dependency(1);
1813
EXPECT_EQ("baz.proto", baz_file->name());
1814
EXPECT_EQ(0, baz_file->message_type_count());
1816
// Placeholder files should not be findable.
1817
EXPECT_EQ(bar_file_, pool_.FindFileByName(bar_file_->name()));
1818
EXPECT_TRUE(pool_.FindFileByName(baz_file->name()) == NULL);
1821
TEST_F(AllowUnknownDependenciesTest, PlaceholderTypes) {
1822
ASSERT_EQ(FieldDescriptor::TYPE_MESSAGE, bar_field_->type());
1823
EXPECT_EQ(bar_type_, bar_field_->message_type());
1825
ASSERT_EQ(FieldDescriptor::TYPE_MESSAGE, baz_field_->type());
1826
const Descriptor* baz_type = baz_field_->message_type();
1827
EXPECT_EQ("Baz", baz_type->name());
1828
EXPECT_EQ("Baz", baz_type->full_name());
1829
EXPECT_EQ("Baz.placeholder.proto", baz_type->file()->name());
1830
EXPECT_EQ(0, baz_type->extension_range_count());
1832
ASSERT_EQ(FieldDescriptor::TYPE_ENUM, qux_field_->type());
1833
const EnumDescriptor* qux_type = qux_field_->enum_type();
1834
EXPECT_EQ("Qux", qux_type->name());
1835
EXPECT_EQ("corge.Qux", qux_type->full_name());
1836
EXPECT_EQ("corge.Qux.placeholder.proto", qux_type->file()->name());
1838
// Placeholder types should not be findable.
1839
EXPECT_EQ(bar_type_, pool_.FindMessageTypeByName(bar_type_->full_name()));
1840
EXPECT_TRUE(pool_.FindMessageTypeByName(baz_type->full_name()) == NULL);
1841
EXPECT_TRUE(pool_.FindEnumTypeByName(qux_type->full_name()) == NULL);
1844
TEST_F(AllowUnknownDependenciesTest, CopyTo) {
1845
// FieldDescriptor::CopyTo() should write non-fully-qualified type names
1846
// for placeholder types which were not originally fully-qualified.
1847
FieldDescriptorProto proto;
1849
// Bar is not a placeholder, so it is fully-qualified.
1850
bar_field_->CopyTo(&proto);
1851
EXPECT_EQ(".Bar", proto.type_name());
1852
EXPECT_EQ(FieldDescriptorProto::TYPE_MESSAGE, proto.type());
1854
// Baz is an unqualified placeholder.
1856
baz_field_->CopyTo(&proto);
1857
EXPECT_EQ("Baz", proto.type_name());
1858
EXPECT_FALSE(proto.has_type());
1860
// Qux is a fully-qualified placeholder.
1862
qux_field_->CopyTo(&proto);
1863
EXPECT_EQ(".corge.Qux", proto.type_name());
1864
EXPECT_EQ(FieldDescriptorProto::TYPE_ENUM, proto.type());
1867
TEST_F(AllowUnknownDependenciesTest, CustomOptions) {
1868
// Qux should still have the uninterpreted option attached.
1869
ASSERT_EQ(1, qux_field_->options().uninterpreted_option_size());
1870
const UninterpretedOption& option =
1871
qux_field_->options().uninterpreted_option(0);
1872
ASSERT_EQ(1, option.name_size());
1873
EXPECT_EQ("grault", option.name(0).name_part());
1876
TEST_F(AllowUnknownDependenciesTest, UnknownExtendee) {
1877
// Test that we can extend an unknown type. This is slightly tricky because
1878
// it means that the placeholder type must have an extension range.
1880
FileDescriptorProto extension_proto;
1882
ASSERT_TRUE(TextFormat::ParseFromString(
1883
"name: 'extension.proto'"
1884
"extension { extendee: 'UnknownType' name:'some_extension' number:123"
1885
" label:LABEL_OPTIONAL type:TYPE_INT32 }",
1887
const FileDescriptor* file = pool_.BuildFile(extension_proto);
1889
ASSERT_TRUE(file != NULL);
1891
ASSERT_EQ(1, file->extension_count());
1892
const Descriptor* extendee = file->extension(0)->containing_type();
1893
EXPECT_EQ("UnknownType", extendee->name());
1894
ASSERT_EQ(1, extendee->extension_range_count());
1895
EXPECT_EQ(1, extendee->extension_range(0)->start);
1896
EXPECT_EQ(FieldDescriptor::kMaxNumber + 1, extendee->extension_range(0)->end);
1899
TEST_F(AllowUnknownDependenciesTest, CustomOption) {
1900
// Test that we can use a custom option without having parsed
1901
// descriptor.proto.
1903
FileDescriptorProto option_proto;
1905
ASSERT_TRUE(TextFormat::ParseFromString(
1906
"name: \"unknown_custom_options.proto\" "
1907
"dependency: \"google/protobuf/descriptor.proto\" "
1909
" extendee: \"google.protobuf.FileOptions\" "
1910
" name: \"some_option\" "
1912
" label: LABEL_OPTIONAL "
1913
" type: TYPE_INT32 "
1916
" uninterpreted_option { "
1918
" name_part: \"some_option\" "
1919
" is_extension: true "
1921
" positive_int_value: 1234 "
1923
" uninterpreted_option { "
1925
" name_part: \"unknown_option\" "
1926
" is_extension: true "
1928
" positive_int_value: 1234 "
1930
" uninterpreted_option { "
1932
" name_part: \"optimize_for\" "
1933
" is_extension: false "
1935
" identifier_value: \"SPEED\" "
1940
const FileDescriptor* file = pool_.BuildFile(option_proto);
1941
ASSERT_TRUE(file != NULL);
1943
// Verify that no extension options were set, but they were left as
1944
// uninterpreted_options.
1945
vector<const FieldDescriptor*> fields;
1946
file->options().GetReflection()->ListFields(file->options(), &fields);
1947
ASSERT_EQ(2, fields.size());
1948
EXPECT_TRUE(file->options().has_optimize_for());
1949
EXPECT_EQ(2, file->options().uninterpreted_option_size());
1952
// ===================================================================
1954
TEST(CustomOptions, OptionLocations) {
1955
const Descriptor* message =
1956
protobuf_unittest::TestMessageWithCustomOptions::descriptor();
1957
const FileDescriptor* file = message->file();
1958
const FieldDescriptor* field = message->FindFieldByName("field1");
1959
const EnumDescriptor* enm = message->FindEnumTypeByName("AnEnum");
1960
// TODO(benjy): Support EnumValue options, once the compiler does.
1961
const ServiceDescriptor* service =
1962
file->FindServiceByName("TestServiceWithCustomOptions");
1963
const MethodDescriptor* method = service->FindMethodByName("Foo");
1965
EXPECT_EQ(GOOGLE_LONGLONG(9876543210),
1966
file->options().GetExtension(protobuf_unittest::file_opt1));
1968
message->options().GetExtension(protobuf_unittest::message_opt1));
1969
EXPECT_EQ(GOOGLE_LONGLONG(8765432109),
1970
field->options().GetExtension(protobuf_unittest::field_opt1));
1971
EXPECT_EQ(42, // Check that we get the default for an option we don't set.
1972
field->options().GetExtension(protobuf_unittest::field_opt2));
1974
enm->options().GetExtension(protobuf_unittest::enum_opt1));
1976
enm->value(1)->options().GetExtension(
1977
protobuf_unittest::enum_value_opt1));
1978
EXPECT_EQ(GOOGLE_LONGLONG(-9876543210),
1979
service->options().GetExtension(protobuf_unittest::service_opt1));
1980
EXPECT_EQ(protobuf_unittest::METHODOPT1_VAL2,
1981
method->options().GetExtension(protobuf_unittest::method_opt1));
1983
// See that the regular options went through unscathed.
1984
EXPECT_TRUE(message->options().has_message_set_wire_format());
1985
EXPECT_EQ(FieldOptions::CORD, field->options().ctype());
1988
TEST(CustomOptions, OptionTypes) {
1989
const MessageOptions* options = NULL;
1992
&protobuf_unittest::CustomOptionMinIntegerValues::descriptor()->options();
1993
EXPECT_EQ(false , options->GetExtension(protobuf_unittest::bool_opt));
1994
EXPECT_EQ(kint32min, options->GetExtension(protobuf_unittest::int32_opt));
1995
EXPECT_EQ(kint64min, options->GetExtension(protobuf_unittest::int64_opt));
1996
EXPECT_EQ(0 , options->GetExtension(protobuf_unittest::uint32_opt));
1997
EXPECT_EQ(0 , options->GetExtension(protobuf_unittest::uint64_opt));
1998
EXPECT_EQ(kint32min, options->GetExtension(protobuf_unittest::sint32_opt));
1999
EXPECT_EQ(kint64min, options->GetExtension(protobuf_unittest::sint64_opt));
2000
EXPECT_EQ(0 , options->GetExtension(protobuf_unittest::fixed32_opt));
2001
EXPECT_EQ(0 , options->GetExtension(protobuf_unittest::fixed64_opt));
2002
EXPECT_EQ(kint32min, options->GetExtension(protobuf_unittest::sfixed32_opt));
2003
EXPECT_EQ(kint64min, options->GetExtension(protobuf_unittest::sfixed64_opt));
2006
&protobuf_unittest::CustomOptionMaxIntegerValues::descriptor()->options();
2007
EXPECT_EQ(true , options->GetExtension(protobuf_unittest::bool_opt));
2008
EXPECT_EQ(kint32max , options->GetExtension(protobuf_unittest::int32_opt));
2009
EXPECT_EQ(kint64max , options->GetExtension(protobuf_unittest::int64_opt));
2010
EXPECT_EQ(kuint32max, options->GetExtension(protobuf_unittest::uint32_opt));
2011
EXPECT_EQ(kuint64max, options->GetExtension(protobuf_unittest::uint64_opt));
2012
EXPECT_EQ(kint32max , options->GetExtension(protobuf_unittest::sint32_opt));
2013
EXPECT_EQ(kint64max , options->GetExtension(protobuf_unittest::sint64_opt));
2014
EXPECT_EQ(kuint32max, options->GetExtension(protobuf_unittest::fixed32_opt));
2015
EXPECT_EQ(kuint64max, options->GetExtension(protobuf_unittest::fixed64_opt));
2016
EXPECT_EQ(kint32max , options->GetExtension(protobuf_unittest::sfixed32_opt));
2017
EXPECT_EQ(kint64max , options->GetExtension(protobuf_unittest::sfixed64_opt));
2020
&protobuf_unittest::CustomOptionOtherValues::descriptor()->options();
2021
EXPECT_EQ(-100, options->GetExtension(protobuf_unittest::int32_opt));
2022
EXPECT_FLOAT_EQ(12.3456789,
2023
options->GetExtension(protobuf_unittest::float_opt));
2024
EXPECT_DOUBLE_EQ(1.234567890123456789,
2025
options->GetExtension(protobuf_unittest::double_opt));
2026
EXPECT_EQ("Hello, \"World\"",
2027
options->GetExtension(protobuf_unittest::string_opt));
2029
EXPECT_EQ(string("Hello\0World", 11),
2030
options->GetExtension(protobuf_unittest::bytes_opt));
2032
EXPECT_EQ(protobuf_unittest::DummyMessageContainingEnum::TEST_OPTION_ENUM_TYPE2,
2033
options->GetExtension(protobuf_unittest::enum_opt));
2036
&protobuf_unittest::SettingRealsFromPositiveInts::descriptor()->options();
2037
EXPECT_FLOAT_EQ(12, options->GetExtension(protobuf_unittest::float_opt));
2038
EXPECT_DOUBLE_EQ(154, options->GetExtension(protobuf_unittest::double_opt));
2041
&protobuf_unittest::SettingRealsFromNegativeInts::descriptor()->options();
2042
EXPECT_FLOAT_EQ(-12, options->GetExtension(protobuf_unittest::float_opt));
2043
EXPECT_DOUBLE_EQ(-154, options->GetExtension(protobuf_unittest::double_opt));
2046
TEST(CustomOptions, ComplexExtensionOptions) {
2047
const MessageOptions* options =
2048
&protobuf_unittest::VariousComplexOptions::descriptor()->options();
2049
EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt1).foo(), 42);
2050
EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt1).
2051
GetExtension(protobuf_unittest::quux), 324);
2052
EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt1).
2053
GetExtension(protobuf_unittest::corge).qux(), 876);
2054
EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).baz(), 987);
2055
EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).
2056
GetExtension(protobuf_unittest::grault), 654);
2057
EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).bar().foo(),
2059
EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).bar().
2060
GetExtension(protobuf_unittest::quux), 1999);
2061
EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).bar().
2062
GetExtension(protobuf_unittest::corge).qux(), 2008);
2063
EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).
2064
GetExtension(protobuf_unittest::garply).foo(), 741);
2065
EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).
2066
GetExtension(protobuf_unittest::garply).
2067
GetExtension(protobuf_unittest::quux), 1998);
2068
EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).
2069
GetExtension(protobuf_unittest::garply).
2070
GetExtension(protobuf_unittest::corge).qux(), 2121);
2071
EXPECT_EQ(options->GetExtension(
2072
protobuf_unittest::ComplexOptionType2::ComplexOptionType4::complex_opt4).
2074
EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).
2075
fred().waldo(), 321);
2076
EXPECT_EQ(9, options->GetExtension(protobuf_unittest::complex_opt3).qux());
2077
EXPECT_EQ(22, options->GetExtension(protobuf_unittest::complex_opt3).
2078
complexoptiontype5().plugh());
2079
EXPECT_EQ(24, options->GetExtension(protobuf_unittest::complexopt6).xyzzy());
2082
TEST(CustomOptions, OptionsFromOtherFile) {
2083
// Test that to use a custom option, we only need to import the file
2084
// defining the option; we do not also have to import descriptor.proto.
2085
DescriptorPool pool;
2087
FileDescriptorProto file_proto;
2088
FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto);
2089
ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
2091
protobuf_unittest::TestMessageWithCustomOptions::descriptor()
2092
->file()->CopyTo(&file_proto);
2093
ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
2095
ASSERT_TRUE(TextFormat::ParseFromString(
2096
"name: \"custom_options_import.proto\" "
2097
"package: \"protobuf_unittest\" "
2098
"dependency: \"google/protobuf/unittest_custom_options.proto\" "
2100
" uninterpreted_option { "
2102
" name_part: \"file_opt1\" "
2103
" is_extension: true "
2105
" positive_int_value: 1234 "
2107
// Test a non-extension option too. (At one point this failed due to a
2109
" uninterpreted_option { "
2111
" name_part: \"java_package\" "
2112
" is_extension: false "
2114
" string_value: \"foo\" "
2116
// Test that enum-typed options still work too. (At one point this also
2117
// failed due to a bug.)
2118
" uninterpreted_option { "
2120
" name_part: \"optimize_for\" "
2121
" is_extension: false "
2123
" identifier_value: \"SPEED\" "
2129
const FileDescriptor* file = pool.BuildFile(file_proto);
2130
ASSERT_TRUE(file != NULL);
2131
EXPECT_EQ(1234, file->options().GetExtension(protobuf_unittest::file_opt1));
2132
EXPECT_TRUE(file->options().has_java_package());
2133
EXPECT_EQ("foo", file->options().java_package());
2134
EXPECT_TRUE(file->options().has_optimize_for());
2135
EXPECT_EQ(FileOptions::SPEED, file->options().optimize_for());
2138
TEST(CustomOptions, MessageOptionThreeFieldsSet) {
2139
// This tests a bug which previously existed in custom options parsing. The
2140
// bug occurred when you defined a custom option with message type and then
2141
// set three fields of that option on a single definition (see the example
2142
// below). The bug is a bit hard to explain, so check the change history if
2143
// you want to know more.
2144
DescriptorPool pool;
2146
FileDescriptorProto file_proto;
2147
FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto);
2148
ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
2150
protobuf_unittest::TestMessageWithCustomOptions::descriptor()
2151
->file()->CopyTo(&file_proto);
2152
ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
2154
// The following represents the definition:
2156
// import "google/protobuf/unittest_custom_options.proto"
2157
// package protobuf_unittest;
2159
// option (complex_opt1).foo = 1234;
2160
// option (complex_opt1).foo2 = 1234;
2161
// option (complex_opt1).foo3 = 1234;
2163
ASSERT_TRUE(TextFormat::ParseFromString(
2164
"name: \"custom_options_import.proto\" "
2165
"package: \"protobuf_unittest\" "
2166
"dependency: \"google/protobuf/unittest_custom_options.proto\" "
2170
" uninterpreted_option { "
2172
" name_part: \"complex_opt1\" "
2173
" is_extension: true "
2176
" name_part: \"foo\" "
2177
" is_extension: false "
2179
" positive_int_value: 1234 "
2181
" uninterpreted_option { "
2183
" name_part: \"complex_opt1\" "
2184
" is_extension: true "
2187
" name_part: \"foo2\" "
2188
" is_extension: false "
2190
" positive_int_value: 1234 "
2192
" uninterpreted_option { "
2194
" name_part: \"complex_opt1\" "
2195
" is_extension: true "
2198
" name_part: \"foo3\" "
2199
" is_extension: false "
2201
" positive_int_value: 1234 "
2207
const FileDescriptor* file = pool.BuildFile(file_proto);
2208
ASSERT_TRUE(file != NULL);
2209
ASSERT_EQ(1, file->message_type_count());
2211
const MessageOptions& options = file->message_type(0)->options();
2212
EXPECT_EQ(1234, options.GetExtension(protobuf_unittest::complex_opt1).foo());
2216
// ===================================================================
2218
// The tests below trigger every unique call to AddError() in descriptor.cc,
2219
// in the order in which they appear in that file. I'm using TextFormat here
2220
// to specify the input descriptors because building them using code would
2223
class MockErrorCollector : public DescriptorPool::ErrorCollector {
2225
MockErrorCollector() {}
2226
~MockErrorCollector() {}
2230
// implements ErrorCollector ---------------------------------------
2231
void AddError(const string& filename,
2232
const string& element_name, const Message* descriptor,
2233
ErrorLocation location, const string& message) {
2234
const char* location_name = NULL;
2236
case NAME : location_name = "NAME" ; break;
2237
case NUMBER : location_name = "NUMBER" ; break;
2238
case TYPE : location_name = "TYPE" ; break;
2239
case EXTENDEE : location_name = "EXTENDEE" ; break;
2240
case DEFAULT_VALUE: location_name = "DEFAULT_VALUE"; break;
2241
case OPTION_NAME : location_name = "OPTION_NAME" ; break;
2242
case OPTION_VALUE : location_name = "OPTION_VALUE" ; break;
2243
case INPUT_TYPE : location_name = "INPUT_TYPE" ; break;
2244
case OUTPUT_TYPE : location_name = "OUTPUT_TYPE" ; break;
2245
case OTHER : location_name = "OTHER" ; break;
2248
strings::SubstituteAndAppend(
2249
&text_, "$0: $1: $2: $3\n",
2250
filename, element_name, location_name, message);
2254
class ValidationErrorTest : public testing::Test {
2256
// Parse file_text as a FileDescriptorProto in text format and add it
2257
// to the DescriptorPool. Expect no errors.
2258
void BuildFile(const string& file_text) {
2259
FileDescriptorProto file_proto;
2260
ASSERT_TRUE(TextFormat::ParseFromString(file_text, &file_proto));
2261
ASSERT_TRUE(pool_.BuildFile(file_proto) != NULL);
2264
// Parse file_text as a FileDescriptorProto in text format and add it
2265
// to the DescriptorPool. Expect errors to be produced which match the
2266
// given error text.
2267
void BuildFileWithErrors(const string& file_text,
2268
const string& expected_errors) {
2269
FileDescriptorProto file_proto;
2270
ASSERT_TRUE(TextFormat::ParseFromString(file_text, &file_proto));
2272
MockErrorCollector error_collector;
2274
pool_.BuildFileCollectingErrors(file_proto, &error_collector) == NULL);
2275
EXPECT_EQ(expected_errors, error_collector.text_);
2278
// Builds some already-parsed file in our test pool.
2279
void BuildFileInTestPool(const FileDescriptor* file) {
2280
FileDescriptorProto file_proto;
2281
file->CopyTo(&file_proto);
2282
ASSERT_TRUE(pool_.BuildFile(file_proto) != NULL);
2285
// Build descriptor.proto in our test pool. This allows us to extend it in
2286
// the test pool, so we can test custom options.
2287
void BuildDescriptorMessagesInTestPool() {
2288
BuildFileInTestPool(DescriptorProto::descriptor()->file());
2291
DescriptorPool pool_;
2294
TEST_F(ValidationErrorTest, AlreadyDefined) {
2295
BuildFileWithErrors(
2296
"name: \"foo.proto\" "
2297
"message_type { name: \"Foo\" }"
2298
"message_type { name: \"Foo\" }",
2300
"foo.proto: Foo: NAME: \"Foo\" is already defined.\n");
2303
TEST_F(ValidationErrorTest, AlreadyDefinedInPackage) {
2304
BuildFileWithErrors(
2305
"name: \"foo.proto\" "
2306
"package: \"foo.bar\" "
2307
"message_type { name: \"Foo\" }"
2308
"message_type { name: \"Foo\" }",
2310
"foo.proto: foo.bar.Foo: NAME: \"Foo\" is already defined in "
2314
TEST_F(ValidationErrorTest, AlreadyDefinedInOtherFile) {
2316
"name: \"foo.proto\" "
2317
"message_type { name: \"Foo\" }");
2319
BuildFileWithErrors(
2320
"name: \"bar.proto\" "
2321
"message_type { name: \"Foo\" }",
2323
"bar.proto: Foo: NAME: \"Foo\" is already defined in file "
2324
"\"foo.proto\".\n");
2327
TEST_F(ValidationErrorTest, PackageAlreadyDefined) {
2329
"name: \"foo.proto\" "
2330
"message_type { name: \"foo\" }");
2331
BuildFileWithErrors(
2332
"name: \"bar.proto\" "
2333
"package: \"foo.bar\"",
2335
"bar.proto: foo: NAME: \"foo\" is already defined (as something other "
2336
"than a package) in file \"foo.proto\".\n");
2339
TEST_F(ValidationErrorTest, EnumValueAlreadyDefinedInParent) {
2340
BuildFileWithErrors(
2341
"name: \"foo.proto\" "
2342
"enum_type { name: \"Foo\" value { name: \"FOO\" number: 1 } } "
2343
"enum_type { name: \"Bar\" value { name: \"FOO\" number: 1 } } ",
2345
"foo.proto: FOO: NAME: \"FOO\" is already defined.\n"
2346
"foo.proto: FOO: NAME: Note that enum values use C++ scoping rules, "
2347
"meaning that enum values are siblings of their type, not children of "
2348
"it. Therefore, \"FOO\" must be unique within the global scope, not "
2349
"just within \"Bar\".\n");
2352
TEST_F(ValidationErrorTest, EnumValueAlreadyDefinedInParentNonGlobal) {
2353
BuildFileWithErrors(
2354
"name: \"foo.proto\" "
2356
"enum_type { name: \"Foo\" value { name: \"FOO\" number: 1 } } "
2357
"enum_type { name: \"Bar\" value { name: \"FOO\" number: 1 } } ",
2359
"foo.proto: pkg.FOO: NAME: \"FOO\" is already defined in \"pkg\".\n"
2360
"foo.proto: pkg.FOO: NAME: Note that enum values use C++ scoping rules, "
2361
"meaning that enum values are siblings of their type, not children of "
2362
"it. Therefore, \"FOO\" must be unique within \"pkg\", not just within "
2366
TEST_F(ValidationErrorTest, MissingName) {
2367
BuildFileWithErrors(
2368
"name: \"foo.proto\" "
2371
"foo.proto: : NAME: Missing name.\n");
2374
TEST_F(ValidationErrorTest, InvalidName) {
2375
BuildFileWithErrors(
2376
"name: \"foo.proto\" "
2377
"message_type { name: \"$\" }",
2379
"foo.proto: $: NAME: \"$\" is not a valid identifier.\n");
2382
TEST_F(ValidationErrorTest, InvalidPackageName) {
2383
BuildFileWithErrors(
2384
"name: \"foo.proto\" "
2385
"package: \"foo.$\"",
2387
"foo.proto: foo.$: NAME: \"$\" is not a valid identifier.\n");
2390
TEST_F(ValidationErrorTest, MissingFileName) {
2391
BuildFileWithErrors(
2394
": : OTHER: Missing field: FileDescriptorProto.name.\n");
2397
TEST_F(ValidationErrorTest, DupeDependency) {
2398
BuildFile("name: \"foo.proto\"");
2399
BuildFileWithErrors(
2400
"name: \"bar.proto\" "
2401
"dependency: \"foo.proto\" "
2402
"dependency: \"foo.proto\" ",
2404
"bar.proto: bar.proto: OTHER: Import \"foo.proto\" was listed twice.\n");
2407
TEST_F(ValidationErrorTest, UnknownDependency) {
2408
BuildFileWithErrors(
2409
"name: \"bar.proto\" "
2410
"dependency: \"foo.proto\" ",
2412
"bar.proto: bar.proto: OTHER: Import \"foo.proto\" has not been loaded.\n");
2415
TEST_F(ValidationErrorTest, ForeignUnimportedPackageNoCrash) {
2416
// Used to crash: If we depend on a non-existent file and then refer to a
2417
// package defined in a file that we didn't import, and that package is
2418
// nested within a parent package which this file is also in, and we don't
2419
// include that parent package in the name (i.e. we do a relative lookup)...
2422
"name: 'foo.proto' "
2423
"package: 'outer.foo' ");
2424
BuildFileWithErrors(
2425
"name: 'bar.proto' "
2426
"dependency: 'baz.proto' "
2427
"package: 'outer.bar' "
2430
" field { name:'bar' number:1 label:LABEL_OPTIONAL type_name:'foo.Foo' }"
2433
"bar.proto: bar.proto: OTHER: Import \"baz.proto\" has not been loaded.\n"
2434
"bar.proto: outer.bar.Bar.bar: TYPE: \"outer.foo\" seems to be defined in "
2435
"\"foo.proto\", which is not imported by \"bar.proto\". To use it here, "
2436
"please add the necessary import.\n");
2439
TEST_F(ValidationErrorTest, DupeFile) {
2441
"name: \"foo.proto\" "
2442
"message_type { name: \"Foo\" }");
2443
// Note: We should *not* get redundant errors about "Foo" already being
2445
BuildFileWithErrors(
2446
"name: \"foo.proto\" "
2447
"message_type { name: \"Foo\" } "
2448
// Add another type so that the files aren't identical (in which case there
2449
// would be no error).
2450
"enum_type { name: \"Bar\" }",
2452
"foo.proto: foo.proto: OTHER: A file with this name is already in the "
2456
TEST_F(ValidationErrorTest, FieldInExtensionRange) {
2457
BuildFileWithErrors(
2458
"name: \"foo.proto\" "
2461
" field { name: \"foo\" number: 9 label:LABEL_OPTIONAL type:TYPE_INT32 }"
2462
" field { name: \"bar\" number: 10 label:LABEL_OPTIONAL type:TYPE_INT32 }"
2463
" field { name: \"baz\" number: 19 label:LABEL_OPTIONAL type:TYPE_INT32 }"
2464
" field { name: \"qux\" number: 20 label:LABEL_OPTIONAL type:TYPE_INT32 }"
2465
" extension_range { start: 10 end: 20 }"
2468
"foo.proto: Foo.bar: NUMBER: Extension range 10 to 19 includes field "
2470
"foo.proto: Foo.baz: NUMBER: Extension range 10 to 19 includes field "
2474
TEST_F(ValidationErrorTest, OverlappingExtensionRanges) {
2475
BuildFileWithErrors(
2476
"name: \"foo.proto\" "
2479
" extension_range { start: 10 end: 20 }"
2480
" extension_range { start: 20 end: 30 }"
2481
" extension_range { start: 19 end: 21 }"
2484
"foo.proto: Foo: NUMBER: Extension range 19 to 20 overlaps with "
2485
"already-defined range 10 to 19.\n"
2486
"foo.proto: Foo: NUMBER: Extension range 19 to 20 overlaps with "
2487
"already-defined range 20 to 29.\n");
2490
TEST_F(ValidationErrorTest, InvalidDefaults) {
2491
BuildFileWithErrors(
2492
"name: \"foo.proto\" "
2497
" field { name: \"foo\" number: 1 label: LABEL_OPTIONAL type: TYPE_INT32"
2498
" default_value: \"abc\" }"
2500
// Empty default value.
2501
" field { name: \"bar\" number: 2 label: LABEL_OPTIONAL type: TYPE_INT32"
2502
" default_value: \"\" }"
2505
" field { name: \"baz\" number: 3 label: LABEL_OPTIONAL type: TYPE_BOOL"
2506
" default_value: \"abc\" }"
2508
// Messages can't have defaults.
2509
" field { name: \"qux\" number: 4 label: LABEL_OPTIONAL type: TYPE_MESSAGE"
2510
" default_value: \"abc\" type_name: \"Foo\" }"
2512
// Same thing, but we don't know that this field has message type until
2513
// we look up the type name.
2514
" field { name: \"quux\" number: 5 label: LABEL_OPTIONAL"
2515
" default_value: \"abc\" type_name: \"Foo\" }"
2517
// Repeateds can't have defaults.
2518
" field { name: \"corge\" number: 6 label: LABEL_REPEATED type: TYPE_INT32"
2519
" default_value: \"1\" }"
2522
"foo.proto: Foo.foo: DEFAULT_VALUE: Couldn't parse default value.\n"
2523
"foo.proto: Foo.bar: DEFAULT_VALUE: Couldn't parse default value.\n"
2524
"foo.proto: Foo.baz: DEFAULT_VALUE: Boolean default must be true or "
2526
"foo.proto: Foo.qux: DEFAULT_VALUE: Messages can't have default values.\n"
2527
"foo.proto: Foo.corge: DEFAULT_VALUE: Repeated fields can't have default "
2529
// This ends up being reported later because the error is detected at
2530
// cross-linking time.
2531
"foo.proto: Foo.quux: DEFAULT_VALUE: Messages can't have default "
2535
TEST_F(ValidationErrorTest, NegativeFieldNumber) {
2536
BuildFileWithErrors(
2537
"name: \"foo.proto\" "
2540
" field { name: \"foo\" number: -1 label:LABEL_OPTIONAL type:TYPE_INT32 }"
2543
"foo.proto: Foo.foo: NUMBER: Field numbers must be positive integers.\n");
2546
TEST_F(ValidationErrorTest, HugeFieldNumber) {
2547
BuildFileWithErrors(
2548
"name: \"foo.proto\" "
2551
" field { name: \"foo\" number: 0x70000000 "
2552
" label:LABEL_OPTIONAL type:TYPE_INT32 }"
2555
"foo.proto: Foo.foo: NUMBER: Field numbers cannot be greater than "
2559
TEST_F(ValidationErrorTest, ReservedFieldNumber) {
2560
BuildFileWithErrors(
2561
"name: \"foo.proto\" "
2564
" field {name:\"foo\" number: 18999 label:LABEL_OPTIONAL type:TYPE_INT32 }"
2565
" field {name:\"bar\" number: 19000 label:LABEL_OPTIONAL type:TYPE_INT32 }"
2566
" field {name:\"baz\" number: 19999 label:LABEL_OPTIONAL type:TYPE_INT32 }"
2567
" field {name:\"qux\" number: 20000 label:LABEL_OPTIONAL type:TYPE_INT32 }"
2570
"foo.proto: Foo.bar: NUMBER: Field numbers 19000 through 19999 are "
2571
"reserved for the protocol buffer library implementation.\n"
2572
"foo.proto: Foo.baz: NUMBER: Field numbers 19000 through 19999 are "
2573
"reserved for the protocol buffer library implementation.\n");
2576
TEST_F(ValidationErrorTest, ExtensionMissingExtendee) {
2577
BuildFileWithErrors(
2578
"name: \"foo.proto\" "
2581
" extension { name: \"foo\" number: 1 label: LABEL_OPTIONAL"
2582
" type_name: \"Foo\" }"
2585
"foo.proto: Foo.foo: EXTENDEE: FieldDescriptorProto.extendee not set for "
2586
"extension field.\n");
2589
TEST_F(ValidationErrorTest, NonExtensionWithExtendee) {
2590
BuildFileWithErrors(
2591
"name: \"foo.proto\" "
2594
" extension_range { start: 1 end: 2 }"
2598
" field { name: \"foo\" number: 1 label: LABEL_OPTIONAL"
2599
" type_name: \"Foo\" extendee: \"Bar\" }"
2602
"foo.proto: Foo.foo: EXTENDEE: FieldDescriptorProto.extendee set for "
2603
"non-extension field.\n");
2606
TEST_F(ValidationErrorTest, FieldNumberConflict) {
2607
BuildFileWithErrors(
2608
"name: \"foo.proto\" "
2611
" field { name: \"foo\" number: 1 label:LABEL_OPTIONAL type:TYPE_INT32 }"
2612
" field { name: \"bar\" number: 1 label:LABEL_OPTIONAL type:TYPE_INT32 }"
2615
"foo.proto: Foo.bar: NUMBER: Field number 1 has already been used in "
2616
"\"Foo\" by field \"foo\".\n");
2619
TEST_F(ValidationErrorTest, BadMessageSetExtensionType) {
2620
BuildFileWithErrors(
2621
"name: \"foo.proto\" "
2623
" name: \"MessageSet\""
2624
" options { message_set_wire_format: true }"
2625
" extension_range { start: 4 end: 5 }"
2629
" extension { name:\"foo\" number:4 label:LABEL_OPTIONAL type:TYPE_INT32"
2630
" extendee: \"MessageSet\" }"
2633
"foo.proto: Foo.foo: TYPE: Extensions of MessageSets must be optional "
2637
TEST_F(ValidationErrorTest, BadMessageSetExtensionLabel) {
2638
BuildFileWithErrors(
2639
"name: \"foo.proto\" "
2641
" name: \"MessageSet\""
2642
" options { message_set_wire_format: true }"
2643
" extension_range { start: 4 end: 5 }"
2647
" extension { name:\"foo\" number:4 label:LABEL_REPEATED type:TYPE_MESSAGE"
2648
" type_name: \"Foo\" extendee: \"MessageSet\" }"
2651
"foo.proto: Foo.foo: TYPE: Extensions of MessageSets must be optional "
2655
TEST_F(ValidationErrorTest, FieldInMessageSet) {
2656
BuildFileWithErrors(
2657
"name: \"foo.proto\" "
2660
" options { message_set_wire_format: true }"
2661
" field { name: \"foo\" number: 1 label:LABEL_OPTIONAL type:TYPE_INT32 }"
2664
"foo.proto: Foo.foo: NAME: MessageSets cannot have fields, only "
2668
TEST_F(ValidationErrorTest, NegativeExtensionRangeNumber) {
2669
BuildFileWithErrors(
2670
"name: \"foo.proto\" "
2673
" extension_range { start: -10 end: -1 }"
2676
"foo.proto: Foo: NUMBER: Extension numbers must be positive integers.\n");
2679
TEST_F(ValidationErrorTest, HugeExtensionRangeNumber) {
2680
BuildFileWithErrors(
2681
"name: \"foo.proto\" "
2684
" extension_range { start: 1 end: 0x70000000 }"
2687
"foo.proto: Foo: NUMBER: Extension numbers cannot be greater than "
2691
TEST_F(ValidationErrorTest, ExtensionRangeEndBeforeStart) {
2692
BuildFileWithErrors(
2693
"name: \"foo.proto\" "
2696
" extension_range { start: 10 end: 10 }"
2697
" extension_range { start: 10 end: 5 }"
2700
"foo.proto: Foo: NUMBER: Extension range end number must be greater than "
2702
"foo.proto: Foo: NUMBER: Extension range end number must be greater than "
2706
TEST_F(ValidationErrorTest, EmptyEnum) {
2707
BuildFileWithErrors(
2708
"name: \"foo.proto\" "
2709
"enum_type { name: \"Foo\" }"
2710
// Also use the empty enum in a message to make sure there are no crashes
2711
// during validation (possible if the code attempts to derive a default
2712
// value for the field).
2715
" field { name: \"foo\" number: 1 label:LABEL_OPTIONAL type_name:\"Foo\" }"
2716
" field { name: \"bar\" number: 2 label:LABEL_OPTIONAL type_name:\"Foo\" "
2717
" default_value: \"NO_SUCH_VALUE\" }"
2720
"foo.proto: Foo: NAME: Enums must contain at least one value.\n"
2721
"foo.proto: Bar.bar: DEFAULT_VALUE: Enum type \"Foo\" has no value named "
2722
"\"NO_SUCH_VALUE\".\n");
2725
TEST_F(ValidationErrorTest, UndefinedExtendee) {
2726
BuildFileWithErrors(
2727
"name: \"foo.proto\" "
2730
" extension { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32"
2731
" extendee: \"Bar\" }"
2734
"foo.proto: Foo.foo: EXTENDEE: \"Bar\" is not defined.\n");
2737
TEST_F(ValidationErrorTest, NonMessageExtendee) {
2738
BuildFileWithErrors(
2739
"name: \"foo.proto\" "
2740
"enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } }"
2743
" extension { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32"
2744
" extendee: \"Bar\" }"
2747
"foo.proto: Foo.foo: EXTENDEE: \"Bar\" is not a message type.\n");
2750
TEST_F(ValidationErrorTest, NotAnExtensionNumber) {
2751
BuildFileWithErrors(
2752
"name: \"foo.proto\" "
2758
" extension { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32"
2759
" extendee: \"Bar\" }"
2762
"foo.proto: Foo.foo: NUMBER: \"Bar\" does not declare 1 as an extension "
2766
TEST_F(ValidationErrorTest, UndefinedFieldType) {
2767
BuildFileWithErrors(
2768
"name: \"foo.proto\" "
2771
" field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }"
2774
"foo.proto: Foo.foo: TYPE: \"Bar\" is not defined.\n");
2777
TEST_F(ValidationErrorTest, FieldTypeDefinedInUndeclaredDependency) {
2779
"name: \"bar.proto\" "
2780
"message_type { name: \"Bar\" } ");
2782
BuildFileWithErrors(
2783
"name: \"foo.proto\" "
2786
" field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }"
2788
"foo.proto: Foo.foo: TYPE: \"Bar\" seems to be defined in \"bar.proto\", "
2789
"which is not imported by \"foo.proto\". To use it here, please add the "
2790
"necessary import.\n");
2793
TEST_F(ValidationErrorTest, SearchMostLocalFirst) {
2794
// The following should produce an error that Bar.Baz is not defined:
2795
// message Bar { message Baz {} }
2798
// // Placing "message Baz{}" here, or removing Foo.Bar altogether,
2799
// // would fix the error.
2801
// optional Bar.Baz baz = 1;
2803
// An one point the lookup code incorrectly did not produce an error in this
2804
// case, because when looking for Bar.Baz, it would try "Foo.Bar.Baz" first,
2805
// fail, and ten try "Bar.Baz" and succeed, even though "Bar" should actually
2806
// refer to the inner Bar, not the outer one.
2807
BuildFileWithErrors(
2808
"name: \"foo.proto\" "
2811
" nested_type { name: \"Baz\" }"
2815
" nested_type { name: \"Bar\" }"
2816
" field { name:\"baz\" number:1 label:LABEL_OPTIONAL"
2817
" type_name:\"Bar.Baz\" }"
2820
"foo.proto: Foo.baz: TYPE: \"Bar.Baz\" is not defined.\n");
2823
TEST_F(ValidationErrorTest, SearchMostLocalFirst2) {
2824
// This test would find the most local "Bar" first, and does, but
2825
// proceeds to find the outer one because the inner one's not an
2828
"name: \"foo.proto\" "
2831
" nested_type { name: \"Baz\" }"
2835
" field { name: \"Bar\" number:1 type:TYPE_BYTES } "
2836
" field { name:\"baz\" number:2 label:LABEL_OPTIONAL"
2837
" type_name:\"Bar.Baz\" }"
2841
TEST_F(ValidationErrorTest, PackageOriginallyDeclaredInTransitiveDependent) {
2842
// Imagine we have the following:
2848
// import "foo.proto";
2852
// import "bar.proto"
2853
// message Baz { optional bar.Bar qux = 1; }
2855
// When validating baz.proto, we will look up "bar.Bar". As part of this
2856
// lookup, we first lookup "bar" then try to find "Bar" within it. "bar"
2857
// should resolve to "foo.bar". Note, though, that "foo.bar" was originally
2858
// defined in foo.proto, which is not a direct dependency of baz.proto. The
2859
// implementation of FindSymbol() normally only returns symbols in direct
2860
// dependencies, not indirect ones. This test insures that this does not
2861
// prevent it from finding "foo.bar".
2864
"name: \"foo.proto\" "
2865
"package: \"foo.bar\" ");
2867
"name: \"bar.proto\" "
2868
"package: \"foo.bar\" "
2869
"dependency: \"foo.proto\" "
2870
"message_type { name: \"Bar\" }");
2872
"name: \"baz.proto\" "
2874
"dependency: \"bar.proto\" "
2877
" field { name:\"qux\" number:1 label:LABEL_OPTIONAL "
2878
" type_name:\"bar.Bar\" }"
2882
TEST_F(ValidationErrorTest, FieldTypeNotAType) {
2883
BuildFileWithErrors(
2884
"name: \"foo.proto\" "
2887
" field { name:\"foo\" number:1 label:LABEL_OPTIONAL "
2888
" type_name:\".Foo.bar\" }"
2889
" field { name:\"bar\" number:2 label:LABEL_OPTIONAL type:TYPE_INT32 }"
2892
"foo.proto: Foo.foo: TYPE: \".Foo.bar\" is not a type.\n");
2895
TEST_F(ValidationErrorTest, RelativeFieldTypeNotAType) {
2896
BuildFileWithErrors(
2897
"name: \"foo.proto\" "
2901
" field { name:\"Baz\" number:2 label:LABEL_OPTIONAL type:TYPE_INT32 }"
2904
" field { name:\"foo\" number:1 label:LABEL_OPTIONAL "
2905
" type_name:\"Bar.Baz\" }"
2907
"foo.proto: Foo.foo: TYPE: \"Bar.Baz\" is not a type.\n");
2910
TEST_F(ValidationErrorTest, FieldTypeMayBeItsName) {
2912
"name: \"foo.proto\" "
2918
" field { name:\"Bar\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }"
2922
TEST_F(ValidationErrorTest, EnumFieldTypeIsMessage) {
2923
BuildFileWithErrors(
2924
"name: \"foo.proto\" "
2925
"message_type { name: \"Bar\" } "
2928
" field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_ENUM"
2929
" type_name:\"Bar\" }"
2932
"foo.proto: Foo.foo: TYPE: \"Bar\" is not an enum type.\n");
2935
TEST_F(ValidationErrorTest, MessageFieldTypeIsEnum) {
2936
BuildFileWithErrors(
2937
"name: \"foo.proto\" "
2938
"enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } } "
2941
" field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_MESSAGE"
2942
" type_name:\"Bar\" }"
2945
"foo.proto: Foo.foo: TYPE: \"Bar\" is not a message type.\n");
2948
TEST_F(ValidationErrorTest, BadEnumDefaultValue) {
2949
BuildFileWithErrors(
2950
"name: \"foo.proto\" "
2951
"enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } } "
2954
" field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\""
2955
" default_value:\"NO_SUCH_VALUE\" }"
2958
"foo.proto: Foo.foo: DEFAULT_VALUE: Enum type \"Bar\" has no value named "
2959
"\"NO_SUCH_VALUE\".\n");
2962
TEST_F(ValidationErrorTest, PrimitiveWithTypeName) {
2963
BuildFileWithErrors(
2964
"name: \"foo.proto\" "
2967
" field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32"
2968
" type_name:\"Foo\" }"
2971
"foo.proto: Foo.foo: TYPE: Field with primitive type has type_name.\n");
2974
TEST_F(ValidationErrorTest, NonPrimitiveWithoutTypeName) {
2975
BuildFileWithErrors(
2976
"name: \"foo.proto\" "
2979
" field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_MESSAGE }"
2982
"foo.proto: Foo.foo: TYPE: Field with message or enum type missing "
2986
TEST_F(ValidationErrorTest, InputTypeNotDefined) {
2987
BuildFileWithErrors(
2988
"name: \"foo.proto\" "
2989
"message_type { name: \"Foo\" } "
2991
" name: \"TestService\""
2992
" method { name: \"A\" input_type: \"Bar\" output_type: \"Foo\" }"
2995
"foo.proto: TestService.A: INPUT_TYPE: \"Bar\" is not defined.\n");
2998
TEST_F(ValidationErrorTest, InputTypeNotAMessage) {
2999
BuildFileWithErrors(
3000
"name: \"foo.proto\" "
3001
"message_type { name: \"Foo\" } "
3002
"enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } } "
3004
" name: \"TestService\""
3005
" method { name: \"A\" input_type: \"Bar\" output_type: \"Foo\" }"
3008
"foo.proto: TestService.A: INPUT_TYPE: \"Bar\" is not a message type.\n");
3011
TEST_F(ValidationErrorTest, OutputTypeNotDefined) {
3012
BuildFileWithErrors(
3013
"name: \"foo.proto\" "
3014
"message_type { name: \"Foo\" } "
3016
" name: \"TestService\""
3017
" method { name: \"A\" input_type: \"Foo\" output_type: \"Bar\" }"
3020
"foo.proto: TestService.A: OUTPUT_TYPE: \"Bar\" is not defined.\n");
3023
TEST_F(ValidationErrorTest, OutputTypeNotAMessage) {
3024
BuildFileWithErrors(
3025
"name: \"foo.proto\" "
3026
"message_type { name: \"Foo\" } "
3027
"enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } } "
3029
" name: \"TestService\""
3030
" method { name: \"A\" input_type: \"Foo\" output_type: \"Bar\" }"
3033
"foo.proto: TestService.A: OUTPUT_TYPE: \"Bar\" is not a message type.\n");
3036
TEST_F(ValidationErrorTest, IllegalPackedField) {
3037
BuildFileWithErrors(
3038
"name: \"foo.proto\" "
3041
" field { name:\"packed_string\" number:1 label:LABEL_REPEATED "
3042
" type:TYPE_STRING "
3043
" options { uninterpreted_option {"
3044
" name { name_part: \"packed\" is_extension: false }"
3045
" identifier_value: \"true\" }}}\n"
3046
" field { name:\"packed_message\" number:3 label:LABEL_REPEATED "
3047
" type_name: \"Foo\""
3048
" options { uninterpreted_option {"
3049
" name { name_part: \"packed\" is_extension: false }"
3050
" identifier_value: \"true\" }}}\n"
3051
" field { name:\"optional_int32\" number: 4 label: LABEL_OPTIONAL "
3053
" options { uninterpreted_option {"
3054
" name { name_part: \"packed\" is_extension: false }"
3055
" identifier_value: \"true\" }}}\n"
3058
"foo.proto: Foo.packed_string: TYPE: [packed = true] can only be "
3059
"specified for repeated primitive fields.\n"
3060
"foo.proto: Foo.packed_message: TYPE: [packed = true] can only be "
3061
"specified for repeated primitive fields.\n"
3062
"foo.proto: Foo.optional_int32: TYPE: [packed = true] can only be "
3063
"specified for repeated primitive fields.\n"
3067
TEST_F(ValidationErrorTest, OptionWrongType) {
3068
BuildFileWithErrors(
3069
"name: \"foo.proto\" "
3071
" name: \"TestMessage\" "
3072
" field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_STRING "
3073
" options { uninterpreted_option { name { name_part: \"ctype\" "
3074
" is_extension: false }"
3075
" positive_int_value: 1 }"
3080
"foo.proto: TestMessage.foo: OPTION_VALUE: Value must be identifier for "
3081
"enum-valued option \"google.protobuf.FieldOptions.ctype\".\n");
3084
TEST_F(ValidationErrorTest, OptionExtendsAtomicType) {
3085
BuildFileWithErrors(
3086
"name: \"foo.proto\" "
3088
" name: \"TestMessage\" "
3089
" field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_STRING "
3090
" options { uninterpreted_option { name { name_part: \"ctype\" "
3091
" is_extension: false }"
3092
" name { name_part: \"foo\" "
3093
" is_extension: true }"
3094
" positive_int_value: 1 }"
3099
"foo.proto: TestMessage.foo: OPTION_NAME: Option \"ctype\" is an "
3100
"atomic type, not a message.\n");
3103
TEST_F(ValidationErrorTest, DupOption) {
3104
BuildFileWithErrors(
3105
"name: \"foo.proto\" "
3107
" name: \"TestMessage\" "
3108
" field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_UINT32 "
3109
" options { uninterpreted_option { name { name_part: \"ctype\" "
3110
" is_extension: false }"
3111
" identifier_value: \"CORD\" }"
3112
" uninterpreted_option { name { name_part: \"ctype\" "
3113
" is_extension: false }"
3114
" identifier_value: \"CORD\" }"
3119
"foo.proto: TestMessage.foo: OPTION_NAME: Option \"ctype\" was "
3123
TEST_F(ValidationErrorTest, InvalidOptionName) {
3124
BuildFileWithErrors(
3125
"name: \"foo.proto\" "
3127
" name: \"TestMessage\" "
3128
" field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_BOOL "
3129
" options { uninterpreted_option { "
3130
" name { name_part: \"uninterpreted_option\" "
3131
" is_extension: false }"
3132
" positive_int_value: 1 "
3138
"foo.proto: TestMessage.foo: OPTION_NAME: Option must not use "
3139
"reserved name \"uninterpreted_option\".\n");
3142
TEST_F(ValidationErrorTest, RepeatedOption) {
3143
BuildDescriptorMessagesInTestPool();
3145
BuildFileWithErrors(
3146
"name: \"foo.proto\" "
3147
"dependency: \"google/protobuf/descriptor.proto\" "
3148
"extension { name: \"foo\" number: 7672757 label: LABEL_REPEATED "
3149
" type: TYPE_FLOAT extendee: \"google.protobuf.FileOptions\" }"
3150
"options { uninterpreted_option { name { name_part: \"foo\" "
3151
" is_extension: true } "
3152
" double_value: 1.2 } }",
3154
"foo.proto: foo.proto: OPTION_NAME: Option field \"(foo)\" is repeated. "
3155
"Repeated options are not supported.\n");
3158
TEST_F(ValidationErrorTest, CustomOptionConflictingFieldNumber) {
3159
BuildDescriptorMessagesInTestPool();
3161
BuildFileWithErrors(
3162
"name: \"foo.proto\" "
3163
"dependency: \"google/protobuf/descriptor.proto\" "
3164
"extension { name: \"foo1\" number: 7672757 label: LABEL_OPTIONAL "
3165
" type: TYPE_INT32 extendee: \"google.protobuf.FieldOptions\" }"
3166
"extension { name: \"foo2\" number: 7672757 label: LABEL_OPTIONAL "
3167
" type: TYPE_INT32 extendee: \"google.protobuf.FieldOptions\" }",
3169
"foo.proto: foo2: NUMBER: Extension number 7672757 has already been used "
3170
"in \"google.protobuf.FieldOptions\" by extension \"foo1\".\n");
3173
TEST_F(ValidationErrorTest, Int32OptionValueOutOfPositiveRange) {
3174
BuildDescriptorMessagesInTestPool();
3176
BuildFileWithErrors(
3177
"name: \"foo.proto\" "
3178
"dependency: \"google/protobuf/descriptor.proto\" "
3179
"extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
3180
" type: TYPE_INT32 extendee: \"google.protobuf.FileOptions\" }"
3181
"options { uninterpreted_option { name { name_part: \"foo\" "
3182
" is_extension: true } "
3183
" positive_int_value: 0x80000000 } "
3186
"foo.proto: foo.proto: OPTION_VALUE: Value out of range "
3187
"for int32 option \"foo\".\n");
3190
TEST_F(ValidationErrorTest, Int32OptionValueOutOfNegativeRange) {
3191
BuildDescriptorMessagesInTestPool();
3193
BuildFileWithErrors(
3194
"name: \"foo.proto\" "
3195
"dependency: \"google/protobuf/descriptor.proto\" "
3196
"extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
3197
" type: TYPE_INT32 extendee: \"google.protobuf.FileOptions\" }"
3198
"options { uninterpreted_option { name { name_part: \"foo\" "
3199
" is_extension: true } "
3200
" negative_int_value: -0x80000001 } "
3203
"foo.proto: foo.proto: OPTION_VALUE: Value out of range "
3204
"for int32 option \"foo\".\n");
3207
TEST_F(ValidationErrorTest, Int32OptionValueIsNotPositiveInt) {
3208
BuildDescriptorMessagesInTestPool();
3210
BuildFileWithErrors(
3211
"name: \"foo.proto\" "
3212
"dependency: \"google/protobuf/descriptor.proto\" "
3213
"extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
3214
" type: TYPE_INT32 extendee: \"google.protobuf.FileOptions\" }"
3215
"options { uninterpreted_option { name { name_part: \"foo\" "
3216
" is_extension: true } "
3217
" string_value: \"5\" } }",
3219
"foo.proto: foo.proto: OPTION_VALUE: Value must be integer "
3220
"for int32 option \"foo\".\n");
3223
TEST_F(ValidationErrorTest, Int64OptionValueOutOfRange) {
3224
BuildDescriptorMessagesInTestPool();
3226
BuildFileWithErrors(
3227
"name: \"foo.proto\" "
3228
"dependency: \"google/protobuf/descriptor.proto\" "
3229
"extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
3230
" type: TYPE_INT64 extendee: \"google.protobuf.FileOptions\" }"
3231
"options { uninterpreted_option { name { name_part: \"foo\" "
3232
" is_extension: true } "
3233
" positive_int_value: 0x8000000000000000 } "
3236
"foo.proto: foo.proto: OPTION_VALUE: Value out of range "
3237
"for int64 option \"foo\".\n");
3240
TEST_F(ValidationErrorTest, Int64OptionValueIsNotPositiveInt) {
3241
BuildDescriptorMessagesInTestPool();
3243
BuildFileWithErrors(
3244
"name: \"foo.proto\" "
3245
"dependency: \"google/protobuf/descriptor.proto\" "
3246
"extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
3247
" type: TYPE_INT64 extendee: \"google.protobuf.FileOptions\" }"
3248
"options { uninterpreted_option { name { name_part: \"foo\" "
3249
" is_extension: true } "
3250
" identifier_value: \"5\" } }",
3252
"foo.proto: foo.proto: OPTION_VALUE: Value must be integer "
3253
"for int64 option \"foo\".\n");
3256
TEST_F(ValidationErrorTest, UInt32OptionValueOutOfRange) {
3257
BuildDescriptorMessagesInTestPool();
3259
BuildFileWithErrors(
3260
"name: \"foo.proto\" "
3261
"dependency: \"google/protobuf/descriptor.proto\" "
3262
"extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
3263
" type: TYPE_UINT32 extendee: \"google.protobuf.FileOptions\" }"
3264
"options { uninterpreted_option { name { name_part: \"foo\" "
3265
" is_extension: true } "
3266
" positive_int_value: 0x100000000 } }",
3268
"foo.proto: foo.proto: OPTION_VALUE: Value out of range "
3269
"for uint32 option \"foo\".\n");
3272
TEST_F(ValidationErrorTest, UInt32OptionValueIsNotPositiveInt) {
3273
BuildDescriptorMessagesInTestPool();
3275
BuildFileWithErrors(
3276
"name: \"foo.proto\" "
3277
"dependency: \"google/protobuf/descriptor.proto\" "
3278
"extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
3279
" type: TYPE_UINT32 extendee: \"google.protobuf.FileOptions\" }"
3280
"options { uninterpreted_option { name { name_part: \"foo\" "
3281
" is_extension: true } "
3282
" double_value: -5.6 } }",
3284
"foo.proto: foo.proto: OPTION_VALUE: Value must be non-negative integer "
3285
"for uint32 option \"foo\".\n");
3288
TEST_F(ValidationErrorTest, UInt64OptionValueIsNotPositiveInt) {
3289
BuildDescriptorMessagesInTestPool();
3291
BuildFileWithErrors(
3292
"name: \"foo.proto\" "
3293
"dependency: \"google/protobuf/descriptor.proto\" "
3294
"extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
3295
" type: TYPE_UINT64 extendee: \"google.protobuf.FileOptions\" }"
3296
"options { uninterpreted_option { name { name_part: \"foo\" "
3297
" is_extension: true } "
3298
" negative_int_value: -5 } }",
3300
"foo.proto: foo.proto: OPTION_VALUE: Value must be non-negative integer "
3301
"for uint64 option \"foo\".\n");
3304
TEST_F(ValidationErrorTest, FloatOptionValueIsNotNumber) {
3305
BuildDescriptorMessagesInTestPool();
3307
BuildFileWithErrors(
3308
"name: \"foo.proto\" "
3309
"dependency: \"google/protobuf/descriptor.proto\" "
3310
"extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
3311
" type: TYPE_FLOAT extendee: \"google.protobuf.FileOptions\" }"
3312
"options { uninterpreted_option { name { name_part: \"foo\" "
3313
" is_extension: true } "
3314
" string_value: \"bar\" } }",
3316
"foo.proto: foo.proto: OPTION_VALUE: Value must be number "
3317
"for float option \"foo\".\n");
3320
TEST_F(ValidationErrorTest, DoubleOptionValueIsNotNumber) {
3321
BuildDescriptorMessagesInTestPool();
3323
BuildFileWithErrors(
3324
"name: \"foo.proto\" "
3325
"dependency: \"google/protobuf/descriptor.proto\" "
3326
"extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
3327
" type: TYPE_DOUBLE extendee: \"google.protobuf.FileOptions\" }"
3328
"options { uninterpreted_option { name { name_part: \"foo\" "
3329
" is_extension: true } "
3330
" string_value: \"bar\" } }",
3332
"foo.proto: foo.proto: OPTION_VALUE: Value must be number "
3333
"for double option \"foo\".\n");
3336
TEST_F(ValidationErrorTest, BoolOptionValueIsNotTrueOrFalse) {
3337
BuildDescriptorMessagesInTestPool();
3339
BuildFileWithErrors(
3340
"name: \"foo.proto\" "
3341
"dependency: \"google/protobuf/descriptor.proto\" "
3342
"extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
3343
" type: TYPE_BOOL extendee: \"google.protobuf.FileOptions\" }"
3344
"options { uninterpreted_option { name { name_part: \"foo\" "
3345
" is_extension: true } "
3346
" identifier_value: \"bar\" } }",
3348
"foo.proto: foo.proto: OPTION_VALUE: Value must be \"true\" or \"false\" "
3349
"for boolean option \"foo\".\n");
3352
TEST_F(ValidationErrorTest, EnumOptionValueIsNotIdentifier) {
3353
BuildDescriptorMessagesInTestPool();
3355
BuildFileWithErrors(
3356
"name: \"foo.proto\" "
3357
"dependency: \"google/protobuf/descriptor.proto\" "
3358
"enum_type { name: \"FooEnum\" value { name: \"BAR\" number: 1 } "
3359
" value { name: \"BAZ\" number: 2 } }"
3360
"extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
3361
" type: TYPE_ENUM type_name: \"FooEnum\" "
3362
" extendee: \"google.protobuf.FileOptions\" }"
3363
"options { uninterpreted_option { name { name_part: \"foo\" "
3364
" is_extension: true } "
3365
" string_value: \"QUUX\" } }",
3367
"foo.proto: foo.proto: OPTION_VALUE: Value must be identifier for "
3368
"enum-valued option \"foo\".\n");
3371
TEST_F(ValidationErrorTest, EnumOptionValueIsNotEnumValueName) {
3372
BuildDescriptorMessagesInTestPool();
3374
BuildFileWithErrors(
3375
"name: \"foo.proto\" "
3376
"dependency: \"google/protobuf/descriptor.proto\" "
3377
"enum_type { name: \"FooEnum\" value { name: \"BAR\" number: 1 } "
3378
" value { name: \"BAZ\" number: 2 } }"
3379
"extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
3380
" type: TYPE_ENUM type_name: \"FooEnum\" "
3381
" extendee: \"google.protobuf.FileOptions\" }"
3382
"options { uninterpreted_option { name { name_part: \"foo\" "
3383
" is_extension: true } "
3384
" identifier_value: \"QUUX\" } }",
3386
"foo.proto: foo.proto: OPTION_VALUE: Enum type \"FooEnum\" has no value "
3387
"named \"QUUX\" for option \"foo\".\n");
3390
TEST_F(ValidationErrorTest, EnumOptionValueIsSiblingEnumValueName) {
3391
BuildDescriptorMessagesInTestPool();
3393
BuildFileWithErrors(
3394
"name: \"foo.proto\" "
3395
"dependency: \"google/protobuf/descriptor.proto\" "
3396
"enum_type { name: \"FooEnum1\" value { name: \"BAR\" number: 1 } "
3397
" value { name: \"BAZ\" number: 2 } }"
3398
"enum_type { name: \"FooEnum2\" value { name: \"QUX\" number: 1 } "
3399
" value { name: \"QUUX\" number: 2 } }"
3400
"extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
3401
" type: TYPE_ENUM type_name: \"FooEnum1\" "
3402
" extendee: \"google.protobuf.FileOptions\" }"
3403
"options { uninterpreted_option { name { name_part: \"foo\" "
3404
" is_extension: true } "
3405
" identifier_value: \"QUUX\" } }",
3407
"foo.proto: foo.proto: OPTION_VALUE: Enum type \"FooEnum1\" has no value "
3408
"named \"QUUX\" for option \"foo\". This appears to be a value from a "
3412
TEST_F(ValidationErrorTest, StringOptionValueIsNotString) {
3413
BuildDescriptorMessagesInTestPool();
3415
BuildFileWithErrors(
3416
"name: \"foo.proto\" "
3417
"dependency: \"google/protobuf/descriptor.proto\" "
3418
"extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL "
3419
" type: TYPE_STRING extendee: \"google.protobuf.FileOptions\" }"
3420
"options { uninterpreted_option { name { name_part: \"foo\" "
3421
" is_extension: true } "
3422
" identifier_value: \"QUUX\" } }",
3424
"foo.proto: foo.proto: OPTION_VALUE: Value must be quoted string for "
3425
"string option \"foo\".\n");
3428
TEST_F(ValidationErrorTest, TryingToSetMessageValuedOption) {
3429
BuildDescriptorMessagesInTestPool();
3431
BuildFileWithErrors(
3432
"name: \"foo.proto\" "
3433
"dependency: \"google/protobuf/descriptor.proto\" "
3435
" name: \"TestMessage\" "
3436
" field { name:\"baz\" number:1 label:LABEL_OPTIONAL type:TYPE_STRING }"
3438
"extension { name: \"bar\" number: 7672757 label: LABEL_OPTIONAL "
3439
" type: TYPE_MESSAGE type_name: \"TestMessage\" "
3440
" extendee: \"google.protobuf.FileOptions\" }"
3441
"options { uninterpreted_option { name { name_part: \"bar\" "
3442
" is_extension: true } "
3443
" identifier_value: \"QUUX\" } }",
3445
"foo.proto: foo.proto: OPTION_NAME: Option field \"(bar)\" cannot be of "
3449
TEST_F(ValidationErrorTest, NotLiteImportsLite) {
3451
"name: \"bar.proto\" "
3452
"options { optimize_for: LITE_RUNTIME } ");
3454
BuildFileWithErrors(
3455
"name: \"foo.proto\" "
3456
"dependency: \"bar.proto\" ",
3458
"foo.proto: foo.proto: OTHER: Files that do not use optimize_for = "
3459
"LITE_RUNTIME cannot import files which do use this option. This file "
3460
"is not lite, but it imports \"bar.proto\" which is.\n");
3463
TEST_F(ValidationErrorTest, LiteExtendsNotLite) {
3465
"name: \"bar.proto\" "
3468
" extension_range { start: 1 end: 1000 }"
3471
BuildFileWithErrors(
3472
"name: \"foo.proto\" "
3473
"dependency: \"bar.proto\" "
3474
"options { optimize_for: LITE_RUNTIME } "
3475
"extension { name: \"ext\" number: 123 label: LABEL_OPTIONAL "
3476
" type: TYPE_INT32 extendee: \"Bar\" }",
3478
"foo.proto: ext: EXTENDEE: Extensions to non-lite types can only be "
3479
"declared in non-lite files. Note that you cannot extend a non-lite "
3480
"type to contain a lite type, but the reverse is allowed.\n");
3483
TEST_F(ValidationErrorTest, NoLiteServices) {
3484
BuildFileWithErrors(
3485
"name: \"foo.proto\" "
3486
"options { optimize_for: LITE_RUNTIME } "
3487
"service { name: \"Foo\" }",
3489
"foo.proto: Foo: NAME: Files with optimize_for = LITE_RUNTIME cannot "
3490
"define services unless you set both options cc_generic_services and "
3491
"java_generic_sevices to false.\n");
3494
"name: \"bar.proto\" "
3496
" optimize_for: LITE_RUNTIME"
3497
" cc_generic_services: false"
3498
" java_generic_services: false"
3500
"service { name: \"Foo\" }");
3503
TEST_F(ValidationErrorTest, RollbackAfterError) {
3504
// Build a file which contains every kind of construct but references an
3505
// undefined type. All these constructs will be added to the symbol table
3506
// before the undefined type error is noticed. The DescriptorPool will then
3507
// have to roll everything back.
3508
BuildFileWithErrors(
3509
"name: \"foo.proto\" "
3511
" name: \"TestMessage\""
3512
" field { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:1 }"
3515
" name: \"TestEnum\""
3516
" value { name:\"BAR\" number:1 }"
3519
" name: \"TestService\""
3522
" input_type: \"NoSuchType\"" // error
3523
" output_type: \"TestMessage\""
3527
"foo.proto: TestService.Baz: INPUT_TYPE: \"NoSuchType\" is not defined.\n");
3529
// Make sure that if we build the same file again with the error fixed,
3530
// it works. If the above rollback was incomplete, then some symbols will
3531
// be left defined, and this second attempt will fail since it tries to
3532
// re-define the same symbols.
3534
"name: \"foo.proto\" "
3536
" name: \"TestMessage\""
3537
" field { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:1 }"
3540
" name: \"TestEnum\""
3541
" value { name:\"BAR\" number:1 }"
3544
" name: \"TestService\""
3545
" method { name:\"Baz\""
3546
" input_type:\"TestMessage\""
3547
" output_type:\"TestMessage\" }"
3551
TEST_F(ValidationErrorTest, ErrorsReportedToLogError) {
3552
// Test that errors are reported to GOOGLE_LOG(ERROR) if no error collector is
3555
FileDescriptorProto file_proto;
3556
ASSERT_TRUE(TextFormat::ParseFromString(
3557
"name: \"foo.proto\" "
3558
"message_type { name: \"Foo\" } "
3559
"message_type { name: \"Foo\" } ",
3562
vector<string> errors;
3565
ScopedMemoryLog log;
3566
EXPECT_TRUE(pool_.BuildFile(file_proto) == NULL);
3567
errors = log.GetMessages(ERROR);
3570
ASSERT_EQ(2, errors.size());
3572
EXPECT_EQ("Invalid proto descriptor for file \"foo.proto\":", errors[0]);
3573
EXPECT_EQ(" Foo: \"Foo\" is already defined.", errors[1]);
3576
// ===================================================================
3577
// DescriptorDatabase
3579
static void AddToDatabase(SimpleDescriptorDatabase* database,
3580
const char* file_text) {
3581
FileDescriptorProto file_proto;
3582
EXPECT_TRUE(TextFormat::ParseFromString(file_text, &file_proto));
3583
database->Add(file_proto);
3586
class DatabaseBackedPoolTest : public testing::Test {
3588
DatabaseBackedPoolTest() {}
3590
SimpleDescriptorDatabase database_;
3592
virtual void SetUp() {
3593
AddToDatabase(&database_,
3594
"name: \"foo.proto\" "
3595
"message_type { name:\"Foo\" extension_range { start: 1 end: 100 } } "
3596
"enum_type { name:\"TestEnum\" value { name:\"DUMMY\" number:0 } } "
3597
"service { name:\"TestService\" } ");
3598
AddToDatabase(&database_,
3599
"name: \"bar.proto\" "
3600
"dependency: \"foo.proto\" "
3601
"message_type { name:\"Bar\" } "
3602
"extension { name:\"foo_ext\" extendee: \".Foo\" number:5 "
3603
" label:LABEL_OPTIONAL type:TYPE_INT32 } ");
3606
// We can't inject a file containing errors into a DescriptorPool, so we
3607
// need an actual mock DescriptorDatabase to test errors.
3608
class ErrorDescriptorDatabase : public DescriptorDatabase {
3610
ErrorDescriptorDatabase() {}
3611
~ErrorDescriptorDatabase() {}
3613
// implements DescriptorDatabase ---------------------------------
3614
bool FindFileByName(const string& filename,
3615
FileDescriptorProto* output) {
3616
// error.proto and error2.proto cyclically import each other.
3617
if (filename == "error.proto") {
3619
output->set_name("error.proto");
3620
output->add_dependency("error2.proto");
3622
} else if (filename == "error2.proto") {
3624
output->set_name("error2.proto");
3625
output->add_dependency("error.proto");
3631
bool FindFileContainingSymbol(const string& symbol_name,
3632
FileDescriptorProto* output) {
3635
bool FindFileContainingExtension(const string& containing_type,
3637
FileDescriptorProto* output) {
3642
// A DescriptorDatabase that counts how many times each method has been
3643
// called and forwards to some other DescriptorDatabase.
3644
class CallCountingDatabase : public DescriptorDatabase {
3646
CallCountingDatabase(DescriptorDatabase* wrapped_db)
3647
: wrapped_db_(wrapped_db) {
3650
~CallCountingDatabase() {}
3652
DescriptorDatabase* wrapped_db_;
3660
// implements DescriptorDatabase ---------------------------------
3661
bool FindFileByName(const string& filename,
3662
FileDescriptorProto* output) {
3664
return wrapped_db_->FindFileByName(filename, output);
3666
bool FindFileContainingSymbol(const string& symbol_name,
3667
FileDescriptorProto* output) {
3669
return wrapped_db_->FindFileContainingSymbol(symbol_name, output);
3671
bool FindFileContainingExtension(const string& containing_type,
3673
FileDescriptorProto* output) {
3675
return wrapped_db_->FindFileContainingExtension(
3676
containing_type, field_number, output);
3680
// A DescriptorDatabase which falsely always returns foo.proto when searching
3681
// for any symbol or extension number. This shouldn't cause the
3682
// DescriptorPool to reload foo.proto if it is already loaded.
3683
class FalsePositiveDatabase : public DescriptorDatabase {
3685
FalsePositiveDatabase(DescriptorDatabase* wrapped_db)
3686
: wrapped_db_(wrapped_db) {}
3687
~FalsePositiveDatabase() {}
3689
DescriptorDatabase* wrapped_db_;
3691
// implements DescriptorDatabase ---------------------------------
3692
bool FindFileByName(const string& filename,
3693
FileDescriptorProto* output) {
3694
return wrapped_db_->FindFileByName(filename, output);
3696
bool FindFileContainingSymbol(const string& symbol_name,
3697
FileDescriptorProto* output) {
3698
return FindFileByName("foo.proto", output);
3700
bool FindFileContainingExtension(const string& containing_type,
3702
FileDescriptorProto* output) {
3703
return FindFileByName("foo.proto", output);
3708
TEST_F(DatabaseBackedPoolTest, FindFileByName) {
3709
DescriptorPool pool(&database_);
3711
const FileDescriptor* foo = pool.FindFileByName("foo.proto");
3712
ASSERT_TRUE(foo != NULL);
3713
EXPECT_EQ("foo.proto", foo->name());
3714
ASSERT_EQ(1, foo->message_type_count());
3715
EXPECT_EQ("Foo", foo->message_type(0)->name());
3717
EXPECT_EQ(foo, pool.FindFileByName("foo.proto"));
3719
EXPECT_TRUE(pool.FindFileByName("no_such_file.proto") == NULL);
3722
TEST_F(DatabaseBackedPoolTest, FindDependencyBeforeDependent) {
3723
DescriptorPool pool(&database_);
3725
const FileDescriptor* foo = pool.FindFileByName("foo.proto");
3726
ASSERT_TRUE(foo != NULL);
3727
EXPECT_EQ("foo.proto", foo->name());
3728
ASSERT_EQ(1, foo->message_type_count());
3729
EXPECT_EQ("Foo", foo->message_type(0)->name());
3731
const FileDescriptor* bar = pool.FindFileByName("bar.proto");
3732
ASSERT_TRUE(bar != NULL);
3733
EXPECT_EQ("bar.proto", bar->name());
3734
ASSERT_EQ(1, bar->message_type_count());
3735
EXPECT_EQ("Bar", bar->message_type(0)->name());
3737
ASSERT_EQ(1, bar->dependency_count());
3738
EXPECT_EQ(foo, bar->dependency(0));
3741
TEST_F(DatabaseBackedPoolTest, FindDependentBeforeDependency) {
3742
DescriptorPool pool(&database_);
3744
const FileDescriptor* bar = pool.FindFileByName("bar.proto");
3745
ASSERT_TRUE(bar != NULL);
3746
EXPECT_EQ("bar.proto", bar->name());
3747
ASSERT_EQ(1, bar->message_type_count());
3748
ASSERT_EQ("Bar", bar->message_type(0)->name());
3750
const FileDescriptor* foo = pool.FindFileByName("foo.proto");
3751
ASSERT_TRUE(foo != NULL);
3752
EXPECT_EQ("foo.proto", foo->name());
3753
ASSERT_EQ(1, foo->message_type_count());
3754
ASSERT_EQ("Foo", foo->message_type(0)->name());
3756
ASSERT_EQ(1, bar->dependency_count());
3757
EXPECT_EQ(foo, bar->dependency(0));
3760
TEST_F(DatabaseBackedPoolTest, FindFileContainingSymbol) {
3761
DescriptorPool pool(&database_);
3763
const FileDescriptor* file = pool.FindFileContainingSymbol("Foo");
3764
ASSERT_TRUE(file != NULL);
3765
EXPECT_EQ("foo.proto", file->name());
3766
EXPECT_EQ(file, pool.FindFileByName("foo.proto"));
3768
EXPECT_TRUE(pool.FindFileContainingSymbol("NoSuchSymbol") == NULL);
3771
TEST_F(DatabaseBackedPoolTest, FindMessageTypeByName) {
3772
DescriptorPool pool(&database_);
3774
const Descriptor* type = pool.FindMessageTypeByName("Foo");
3775
ASSERT_TRUE(type != NULL);
3776
EXPECT_EQ("Foo", type->name());
3777
EXPECT_EQ(type->file(), pool.FindFileByName("foo.proto"));
3779
EXPECT_TRUE(pool.FindMessageTypeByName("NoSuchType") == NULL);
3782
TEST_F(DatabaseBackedPoolTest, FindExtensionByNumber) {
3783
DescriptorPool pool(&database_);
3785
const Descriptor* foo = pool.FindMessageTypeByName("Foo");
3786
ASSERT_TRUE(foo != NULL);
3788
const FieldDescriptor* extension = pool.FindExtensionByNumber(foo, 5);
3789
ASSERT_TRUE(extension != NULL);
3790
EXPECT_EQ("foo_ext", extension->name());
3791
EXPECT_EQ(extension->file(), pool.FindFileByName("bar.proto"));
3793
EXPECT_TRUE(pool.FindExtensionByNumber(foo, 12) == NULL);
3796
TEST_F(DatabaseBackedPoolTest, FindAllExtensions) {
3797
DescriptorPool pool(&database_);
3799
const Descriptor* foo = pool.FindMessageTypeByName("Foo");
3801
for (int i = 0; i < 2; ++i) {
3802
// Repeat the lookup twice, to check that we get consistent
3803
// results despite the fallback database lookup mutating the pool.
3804
vector<const FieldDescriptor*> extensions;
3805
pool.FindAllExtensions(foo, &extensions);
3806
ASSERT_EQ(1, extensions.size());
3807
EXPECT_EQ(5, extensions[0]->number());
3811
TEST_F(DatabaseBackedPoolTest, ErrorWithoutErrorCollector) {
3812
ErrorDescriptorDatabase error_database;
3813
DescriptorPool pool(&error_database);
3815
vector<string> errors;
3818
ScopedMemoryLog log;
3819
EXPECT_TRUE(pool.FindFileByName("error.proto") == NULL);
3820
errors = log.GetMessages(ERROR);
3823
EXPECT_FALSE(errors.empty());
3826
TEST_F(DatabaseBackedPoolTest, ErrorWithErrorCollector) {
3827
ErrorDescriptorDatabase error_database;
3828
MockErrorCollector error_collector;
3829
DescriptorPool pool(&error_database, &error_collector);
3831
EXPECT_TRUE(pool.FindFileByName("error.proto") == NULL);
3833
"error.proto: error.proto: OTHER: File recursively imports itself: "
3834
"error.proto -> error2.proto -> error.proto\n"
3835
"error2.proto: error2.proto: OTHER: Import \"error.proto\" was not "
3836
"found or had errors.\n"
3837
"error.proto: error.proto: OTHER: Import \"error2.proto\" was not "
3838
"found or had errors.\n",
3839
error_collector.text_);
3842
TEST_F(DatabaseBackedPoolTest, UnittestProto) {
3843
// Try to load all of unittest.proto from a DescriptorDatabase. This should
3844
// thoroughly test all paths through DescriptorBuilder to insure that there
3845
// are no deadlocking problems when pool_->mutex_ is non-NULL.
3846
const FileDescriptor* original_file =
3847
protobuf_unittest::TestAllTypes::descriptor()->file();
3849
DescriptorPoolDatabase database(*DescriptorPool::generated_pool());
3850
DescriptorPool pool(&database);
3851
const FileDescriptor* file_from_database =
3852
pool.FindFileByName(original_file->name());
3854
ASSERT_TRUE(file_from_database != NULL);
3856
FileDescriptorProto original_file_proto;
3857
original_file->CopyTo(&original_file_proto);
3859
FileDescriptorProto file_from_database_proto;
3860
file_from_database->CopyTo(&file_from_database_proto);
3862
EXPECT_EQ(original_file_proto.DebugString(),
3863
file_from_database_proto.DebugString());
3866
TEST_F(DatabaseBackedPoolTest, DoesntRetryDbUnnecessarily) {
3867
// Searching for a child of an existing descriptor should never fall back
3868
// to the DescriptorDatabase even if it isn't found, because we know all
3869
// children are already loaded.
3870
CallCountingDatabase call_counter(&database_);
3871
DescriptorPool pool(&call_counter);
3873
const FileDescriptor* file = pool.FindFileByName("foo.proto");
3874
ASSERT_TRUE(file != NULL);
3875
const Descriptor* foo = pool.FindMessageTypeByName("Foo");
3876
ASSERT_TRUE(foo != NULL);
3877
const EnumDescriptor* test_enum = pool.FindEnumTypeByName("TestEnum");
3878
ASSERT_TRUE(test_enum != NULL);
3879
const ServiceDescriptor* test_service = pool.FindServiceByName("TestService");
3880
ASSERT_TRUE(test_service != NULL);
3882
EXPECT_NE(0, call_counter.call_count_);
3883
call_counter.Clear();
3885
EXPECT_TRUE(foo->FindFieldByName("no_such_field") == NULL);
3886
EXPECT_TRUE(foo->FindExtensionByName("no_such_extension") == NULL);
3887
EXPECT_TRUE(foo->FindNestedTypeByName("NoSuchMessageType") == NULL);
3888
EXPECT_TRUE(foo->FindEnumTypeByName("NoSuchEnumType") == NULL);
3889
EXPECT_TRUE(foo->FindEnumValueByName("NO_SUCH_VALUE") == NULL);
3890
EXPECT_TRUE(test_enum->FindValueByName("NO_SUCH_VALUE") == NULL);
3891
EXPECT_TRUE(test_service->FindMethodByName("NoSuchMethod") == NULL);
3893
EXPECT_TRUE(file->FindMessageTypeByName("NoSuchMessageType") == NULL);
3894
EXPECT_TRUE(file->FindEnumTypeByName("NoSuchEnumType") == NULL);
3895
EXPECT_TRUE(file->FindEnumValueByName("NO_SUCH_VALUE") == NULL);
3896
EXPECT_TRUE(file->FindServiceByName("NO_SUCH_VALUE") == NULL);
3897
EXPECT_TRUE(file->FindExtensionByName("no_such_extension") == NULL);
3898
EXPECT_EQ(0, call_counter.call_count_);
3901
TEST_F(DatabaseBackedPoolTest, DoesntReloadFilesUncesessarily) {
3902
// If FindFileContainingSymbol() or FindFileContainingExtension() return a
3903
// file that is already in the DescriptorPool, it should not attempt to
3905
FalsePositiveDatabase false_positive_database(&database_);
3906
MockErrorCollector error_collector;
3907
DescriptorPool pool(&false_positive_database, &error_collector);
3909
// First make sure foo.proto is loaded.
3910
const Descriptor* foo = pool.FindMessageTypeByName("Foo");
3911
ASSERT_TRUE(foo != NULL);
3913
// Try inducing false positives.
3914
EXPECT_TRUE(pool.FindMessageTypeByName("NoSuchSymbol") == NULL);
3915
EXPECT_TRUE(pool.FindExtensionByNumber(foo, 22) == NULL);
3917
// No errors should have been reported. (If foo.proto was incorrectly
3918
// loaded multiple times, errors would have been reported.)
3919
EXPECT_EQ("", error_collector.text_);
3922
TEST_F(DatabaseBackedPoolTest, DoesntReloadKnownBadFiles) {
3923
ErrorDescriptorDatabase error_database;
3924
MockErrorCollector error_collector;
3925
DescriptorPool pool(&error_database, &error_collector);
3927
EXPECT_TRUE(pool.FindFileByName("error.proto") == NULL);
3928
error_collector.text_.clear();
3929
EXPECT_TRUE(pool.FindFileByName("error.proto") == NULL);
3930
EXPECT_EQ("", error_collector.text_);
3933
TEST_F(DatabaseBackedPoolTest, DoesntFallbackOnWrongType) {
3934
// If a lookup finds a symbol of the wrong type (e.g. we pass a type name
3935
// to FindFieldByName()), we should fail fast, without checking the fallback
3937
CallCountingDatabase call_counter(&database_);
3938
DescriptorPool pool(&call_counter);
3940
const FileDescriptor* file = pool.FindFileByName("foo.proto");
3941
ASSERT_TRUE(file != NULL);
3942
const Descriptor* foo = pool.FindMessageTypeByName("Foo");
3943
ASSERT_TRUE(foo != NULL);
3944
const EnumDescriptor* test_enum = pool.FindEnumTypeByName("TestEnum");
3945
ASSERT_TRUE(test_enum != NULL);
3947
EXPECT_NE(0, call_counter.call_count_);
3948
call_counter.Clear();
3950
EXPECT_TRUE(pool.FindMessageTypeByName("TestEnum") == NULL);
3951
EXPECT_TRUE(pool.FindFieldByName("Foo") == NULL);
3952
EXPECT_TRUE(pool.FindExtensionByName("Foo") == NULL);
3953
EXPECT_TRUE(pool.FindEnumTypeByName("Foo") == NULL);
3954
EXPECT_TRUE(pool.FindEnumValueByName("Foo") == NULL);
3955
EXPECT_TRUE(pool.FindServiceByName("Foo") == NULL);
3956
EXPECT_TRUE(pool.FindMethodByName("Foo") == NULL);
3958
EXPECT_EQ(0, call_counter.call_count_);
3961
// ===================================================================
3964
} // namespace descriptor_unittest
3965
} // namespace protobuf
3966
} // namespace google