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