| OLD | NEW |
| 1 // Protocol Buffers - Google's data interchange format | 1 // Protocol Buffers - Google's data interchange format |
| 2 // Copyright 2008 Google Inc. All rights reserved. | 2 // Copyright 2008 Google Inc. All rights reserved. |
| 3 // http://code.google.com/p/protobuf/ | 3 // https://developers.google.com/protocol-buffers/ |
| 4 // | 4 // |
| 5 // Redistribution and use in source and binary forms, with or without | 5 // Redistribution and use in source and binary forms, with or without |
| 6 // modification, are permitted provided that the following conditions are | 6 // modification, are permitted provided that the following conditions are |
| 7 // met: | 7 // met: |
| 8 // | 8 // |
| 9 // * Redistributions of source code must retain the above copyright | 9 // * Redistributions of source code must retain the above copyright |
| 10 // notice, this list of conditions and the following disclaimer. | 10 // notice, this list of conditions and the following disclaimer. |
| 11 // * Redistributions in binary form must reproduce the above | 11 // * Redistributions in binary form must reproduce the above |
| 12 // copyright notice, this list of conditions and the following disclaimer | 12 // copyright notice, this list of conditions and the following disclaimer |
| 13 // in the documentation and/or other materials provided with the | 13 // in the documentation and/or other materials provided with the |
| (...skipping 13 matching lines...) Expand all Loading... |
| 27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 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. | 29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 30 | 30 |
| 31 // Author: kenton@google.com (Kenton Varda) | 31 // Author: kenton@google.com (Kenton Varda) |
| 32 // Based on original Protocol Buffers design by | 32 // Based on original Protocol Buffers design by |
| 33 // Sanjay Ghemawat, Jeff Dean, and others. | 33 // Sanjay Ghemawat, Jeff Dean, and others. |
| 34 // | 34 // |
| 35 // This file makes extensive use of RFC 3092. :) | 35 // This file makes extensive use of RFC 3092. :) |
| 36 | 36 |
| 37 #include <memory> |
| 38 #ifndef _SHARED_PTR_H |
| 39 #include <google/protobuf/stubs/shared_ptr.h> |
| 40 #endif |
| 37 #include <vector> | 41 #include <vector> |
| 38 | 42 |
| 39 #include <google/protobuf/compiler/importer.h> | 43 #include <google/protobuf/compiler/importer.h> |
| 40 #include <google/protobuf/unittest.pb.h> | 44 #include <google/protobuf/unittest.pb.h> |
| 41 #include <google/protobuf/unittest_custom_options.pb.h> | 45 #include <google/protobuf/unittest_custom_options.pb.h> |
| 42 #include <google/protobuf/io/zero_copy_stream_impl.h> | 46 #include <google/protobuf/io/zero_copy_stream_impl.h> |
| 43 #include <google/protobuf/descriptor.pb.h> | 47 #include <google/protobuf/descriptor.pb.h> |
| 44 #include <google/protobuf/descriptor.h> | 48 #include <google/protobuf/descriptor.h> |
| 45 #include <google/protobuf/descriptor_database.h> | 49 #include <google/protobuf/descriptor_database.h> |
| 46 #include <google/protobuf/dynamic_message.h> | 50 #include <google/protobuf/dynamic_message.h> |
| 47 #include <google/protobuf/text_format.h> | 51 #include <google/protobuf/text_format.h> |
| 48 #include <google/protobuf/stubs/strutil.h> | 52 #include <google/protobuf/stubs/strutil.h> |
| 49 #include <google/protobuf/stubs/substitute.h> | 53 #include <google/protobuf/stubs/substitute.h> |
| 50 | 54 |
| 51 #include <google/protobuf/stubs/common.h> | 55 #include <google/protobuf/stubs/common.h> |
| 56 #include <google/protobuf/stubs/logging.h> |
| 57 #include <google/protobuf/stubs/scoped_ptr.h> |
| 52 #include <google/protobuf/testing/googletest.h> | 58 #include <google/protobuf/testing/googletest.h> |
| 53 #include <gtest/gtest.h> | 59 #include <gtest/gtest.h> |
| 54 | 60 |
| 55 namespace google { | 61 namespace google { |
| 56 namespace protobuf { | 62 namespace protobuf { |
| 57 | 63 |
| 58 // Can't use an anonymous namespace here due to brokenness of Tru64 compiler. | 64 // Can't use an anonymous namespace here due to brokenness of Tru64 compiler. |
| 59 namespace descriptor_unittest { | 65 namespace descriptor_unittest { |
| 60 | 66 |
| 61 // Some helpers to make assembling descriptors faster. | 67 // Some helpers to make assembling descriptors faster. |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 132 } | 138 } |
| 133 | 139 |
| 134 DescriptorProto::ExtensionRange* AddExtensionRange(DescriptorProto* parent, | 140 DescriptorProto::ExtensionRange* AddExtensionRange(DescriptorProto* parent, |
| 135 int start, int end) { | 141 int start, int end) { |
| 136 DescriptorProto::ExtensionRange* result = parent->add_extension_range(); | 142 DescriptorProto::ExtensionRange* result = parent->add_extension_range(); |
| 137 result->set_start(start); | 143 result->set_start(start); |
| 138 result->set_end(end); | 144 result->set_end(end); |
| 139 return result; | 145 return result; |
| 140 } | 146 } |
| 141 | 147 |
| 148 DescriptorProto::ReservedRange* AddReservedRange(DescriptorProto* parent, |
| 149 int start, int end) { |
| 150 DescriptorProto::ReservedRange* result = parent->add_reserved_range(); |
| 151 result->set_start(start); |
| 152 result->set_end(end); |
| 153 return result; |
| 154 } |
| 155 |
| 142 EnumValueDescriptorProto* AddEnumValue(EnumDescriptorProto* enum_proto, | 156 EnumValueDescriptorProto* AddEnumValue(EnumDescriptorProto* enum_proto, |
| 143 const string& name, int number) { | 157 const string& name, int number) { |
| 144 EnumValueDescriptorProto* result = enum_proto->add_value(); | 158 EnumValueDescriptorProto* result = enum_proto->add_value(); |
| 145 result->set_name(name); | 159 result->set_name(name); |
| 146 result->set_number(number); | 160 result->set_number(number); |
| 147 return result; | 161 return result; |
| 148 } | 162 } |
| 149 | 163 |
| 150 MethodDescriptorProto* AddMethod(ServiceDescriptorProto* service, | 164 MethodDescriptorProto* AddMethod(ServiceDescriptorProto* service, |
| 151 const string& name, | 165 const string& name, |
| 152 const string& input_type, | 166 const string& input_type, |
| 153 const string& output_type) { | 167 const string& output_type) { |
| 154 MethodDescriptorProto* result = service->add_method(); | 168 MethodDescriptorProto* result = service->add_method(); |
| 155 result->set_name(name); | 169 result->set_name(name); |
| 156 result->set_input_type(input_type); | 170 result->set_input_type(input_type); |
| 157 result->set_output_type(output_type); | 171 result->set_output_type(output_type); |
| 158 return result; | 172 return result; |
| 159 } | 173 } |
| 160 | 174 |
| 161 // Empty enums technically aren't allowed. We need to insert a dummy value | 175 // Empty enums technically aren't allowed. We need to insert a dummy value |
| 162 // into them. | 176 // into them. |
| 163 void AddEmptyEnum(FileDescriptorProto* file, const string& name) { | 177 void AddEmptyEnum(FileDescriptorProto* file, const string& name) { |
| 164 AddEnumValue(AddEnum(file, name), name + "_DUMMY", 1); | 178 AddEnumValue(AddEnum(file, name), name + "_DUMMY", 1); |
| 165 } | 179 } |
| 166 | 180 |
| 181 class MockErrorCollector : public DescriptorPool::ErrorCollector { |
| 182 public: |
| 183 MockErrorCollector() {} |
| 184 ~MockErrorCollector() {} |
| 185 |
| 186 string text_; |
| 187 string warning_text_; |
| 188 |
| 189 // implements ErrorCollector --------------------------------------- |
| 190 void AddError(const string& filename, |
| 191 const string& element_name, const Message* descriptor, |
| 192 ErrorLocation location, const string& message) { |
| 193 const char* location_name = NULL; |
| 194 switch (location) { |
| 195 case NAME : location_name = "NAME" ; break; |
| 196 case NUMBER : location_name = "NUMBER" ; break; |
| 197 case TYPE : location_name = "TYPE" ; break; |
| 198 case EXTENDEE : location_name = "EXTENDEE" ; break; |
| 199 case DEFAULT_VALUE: location_name = "DEFAULT_VALUE"; break; |
| 200 case OPTION_NAME : location_name = "OPTION_NAME" ; break; |
| 201 case OPTION_VALUE : location_name = "OPTION_VALUE" ; break; |
| 202 case INPUT_TYPE : location_name = "INPUT_TYPE" ; break; |
| 203 case OUTPUT_TYPE : location_name = "OUTPUT_TYPE" ; break; |
| 204 case OTHER : location_name = "OTHER" ; break; |
| 205 } |
| 206 |
| 207 strings::SubstituteAndAppend( |
| 208 &text_, "$0: $1: $2: $3\n", |
| 209 filename, element_name, location_name, message); |
| 210 } |
| 211 |
| 212 // implements ErrorCollector --------------------------------------- |
| 213 void AddWarning(const string& filename, const string& element_name, |
| 214 const Message* descriptor, ErrorLocation location, |
| 215 const string& message) { |
| 216 const char* location_name = NULL; |
| 217 switch (location) { |
| 218 case NAME : location_name = "NAME" ; break; |
| 219 case NUMBER : location_name = "NUMBER" ; break; |
| 220 case TYPE : location_name = "TYPE" ; break; |
| 221 case EXTENDEE : location_name = "EXTENDEE" ; break; |
| 222 case DEFAULT_VALUE: location_name = "DEFAULT_VALUE"; break; |
| 223 case OPTION_NAME : location_name = "OPTION_NAME" ; break; |
| 224 case OPTION_VALUE : location_name = "OPTION_VALUE" ; break; |
| 225 case INPUT_TYPE : location_name = "INPUT_TYPE" ; break; |
| 226 case OUTPUT_TYPE : location_name = "OUTPUT_TYPE" ; break; |
| 227 case OTHER : location_name = "OTHER" ; break; |
| 228 } |
| 229 |
| 230 strings::SubstituteAndAppend( |
| 231 &warning_text_, "$0: $1: $2: $3\n", |
| 232 filename, element_name, location_name, message); |
| 233 } |
| 234 }; |
| 235 |
| 167 // =================================================================== | 236 // =================================================================== |
| 168 | 237 |
| 169 // Test simple files. | 238 // Test simple files. |
| 170 class FileDescriptorTest : public testing::Test { | 239 class FileDescriptorTest : public testing::Test { |
| 171 protected: | 240 protected: |
| 172 virtual void SetUp() { | 241 virtual void SetUp() { |
| 173 // Build descriptors for the following definitions: | 242 // Build descriptors for the following definitions: |
| 174 // | 243 // |
| 175 // // in "foo.proto" | 244 // // in "foo.proto" |
| 176 // message FooMessage { extensions 1; } | 245 // message FooMessage { extensions 1; } |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 353 // FileDescriptor back. | 422 // FileDescriptor back. |
| 354 FileDescriptorProto file; | 423 FileDescriptorProto file; |
| 355 foo_file_->CopyTo(&file); | 424 foo_file_->CopyTo(&file); |
| 356 EXPECT_EQ(foo_file_, pool_.BuildFile(file)); | 425 EXPECT_EQ(foo_file_, pool_.BuildFile(file)); |
| 357 | 426 |
| 358 // But if we change the file then it won't work. | 427 // But if we change the file then it won't work. |
| 359 file.set_package("some.other.package"); | 428 file.set_package("some.other.package"); |
| 360 EXPECT_TRUE(pool_.BuildFile(file) == NULL); | 429 EXPECT_TRUE(pool_.BuildFile(file) == NULL); |
| 361 } | 430 } |
| 362 | 431 |
| 432 TEST_F(FileDescriptorTest, BuildAgainWithSyntax) { |
| 433 // Test that if te call BuildFile again on the same input we get the same |
| 434 // FileDescriptor back even if syntax param is specified. |
| 435 FileDescriptorProto proto_syntax2; |
| 436 proto_syntax2.set_name("foo_syntax2"); |
| 437 proto_syntax2.set_syntax("proto2"); |
| 438 |
| 439 const FileDescriptor* proto2_descriptor = pool_.BuildFile(proto_syntax2); |
| 440 EXPECT_TRUE(proto2_descriptor != NULL); |
| 441 EXPECT_EQ(proto2_descriptor, pool_.BuildFile(proto_syntax2)); |
| 442 |
| 443 FileDescriptorProto implicit_proto2; |
| 444 implicit_proto2.set_name("foo_implicit_syntax2"); |
| 445 |
| 446 const FileDescriptor* implicit_proto2_descriptor = |
| 447 pool_.BuildFile(implicit_proto2); |
| 448 EXPECT_TRUE(implicit_proto2_descriptor != NULL); |
| 449 // We get the same FileDescriptor back if syntax param is explicitly |
| 450 // specified. |
| 451 implicit_proto2.set_syntax("proto2"); |
| 452 EXPECT_EQ(implicit_proto2_descriptor, pool_.BuildFile(implicit_proto2)); |
| 453 |
| 454 FileDescriptorProto proto_syntax3; |
| 455 proto_syntax3.set_name("foo_syntax3"); |
| 456 proto_syntax3.set_syntax("proto3"); |
| 457 |
| 458 const FileDescriptor* proto3_descriptor = pool_.BuildFile(proto_syntax3); |
| 459 EXPECT_TRUE(proto3_descriptor != NULL); |
| 460 EXPECT_EQ(proto3_descriptor, pool_.BuildFile(proto_syntax3)); |
| 461 } |
| 462 |
| 463 TEST_F(FileDescriptorTest, Syntax) { |
| 464 FileDescriptorProto proto; |
| 465 proto.set_name("foo"); |
| 466 // Enable the test when we also populate the syntax for proto2. |
| 467 #if 0 |
| 468 { |
| 469 proto.set_syntax("proto2"); |
| 470 DescriptorPool pool; |
| 471 const FileDescriptor* file = pool.BuildFile(proto); |
| 472 EXPECT_TRUE(file != NULL); |
| 473 EXPECT_EQ(FileDescriptor::SYNTAX_PROTO2, file->syntax()); |
| 474 FileDescriptorProto other; |
| 475 file->CopyTo(&other); |
| 476 EXPECT_EQ("proto2", other.syntax()); |
| 477 } |
| 478 #endif |
| 479 { |
| 480 proto.set_syntax("proto3"); |
| 481 DescriptorPool pool; |
| 482 const FileDescriptor* file = pool.BuildFile(proto); |
| 483 EXPECT_TRUE(file != NULL); |
| 484 EXPECT_EQ(FileDescriptor::SYNTAX_PROTO3, file->syntax()); |
| 485 FileDescriptorProto other; |
| 486 file->CopyTo(&other); |
| 487 EXPECT_EQ("proto3", other.syntax()); |
| 488 } |
| 489 } |
| 490 |
| 363 // =================================================================== | 491 // =================================================================== |
| 364 | 492 |
| 365 // Test simple flat messages and fields. | 493 // Test simple flat messages and fields. |
| 366 class DescriptorTest : public testing::Test { | 494 class DescriptorTest : public testing::Test { |
| 367 protected: | 495 protected: |
| 368 virtual void SetUp() { | 496 virtual void SetUp() { |
| 369 // Build descriptors for the following definitions: | 497 // Build descriptors for the following definitions: |
| 370 // | 498 // |
| 371 // // in "foo.proto" | 499 // // in "foo.proto" |
| 372 // message TestForeign {} | 500 // message TestForeign {} |
| 373 // enum TestEnum {} | 501 // enum TestEnum {} |
| 374 // | 502 // |
| 375 // message TestMessage { | 503 // message TestMessage { |
| 376 // required string foo = 1; | 504 // required string foo = 1; |
| 377 // optional TestEnum bar = 6; | 505 // optional TestEnum bar = 6; |
| 378 // repeated TestForeign baz = 500000000; | 506 // repeated TestForeign baz = 500000000; |
| 379 // optional group qux = 15 {} | 507 // optional group qux = 15 {} |
| 380 // } | 508 // } |
| 381 // | 509 // |
| 382 // // in "bar.proto" | 510 // // in "bar.proto" |
| 383 // package corge.grault; | 511 // package corge.grault; |
| 384 // message TestMessage2 { | 512 // message TestMessage2 { |
| 385 // required string foo = 1; | 513 // required string foo = 1; |
| 386 // required string bar = 2; | 514 // required string bar = 2; |
| 387 // required string quux = 6; | 515 // required string quux = 6; |
| 388 // } | 516 // } |
| 389 // | 517 // |
| 518 // // in "map.proto" |
| 519 // message TestMessage3 { |
| 520 // map<int32, int32> map_int32_int32 = 1; |
| 521 // } |
| 522 // |
| 523 // // in "json.proto" |
| 524 // message TestMessage4 { |
| 525 // optional int32 field_name1 = 1; |
| 526 // optional int32 fieldName2 = 2; |
| 527 // optional int32 FieldName3 = 3; |
| 528 // optional int32 _field_name4 = 4; |
| 529 // optional int32 FIELD_NAME5 = 5; |
| 530 // optional int32 field_name6 = 6 [json_name = "@type"]; |
| 531 // } |
| 532 // |
| 390 // We cheat and use TestForeign as the type for qux rather than create | 533 // We cheat and use TestForeign as the type for qux rather than create |
| 391 // an actual nested type. | 534 // an actual nested type. |
| 392 // | 535 // |
| 393 // Since all primitive types (including string) use the same building | 536 // Since all primitive types (including string) use the same building |
| 394 // code, there's no need to test each one individually. | 537 // code, there's no need to test each one individually. |
| 395 // | 538 // |
| 396 // TestMessage2 is primarily here to test FindFieldByName and friends. | 539 // TestMessage2 is primarily here to test FindFieldByName and friends. |
| 397 // All messages created from the same DescriptorPool share the same lookup | 540 // All messages created from the same DescriptorPool share the same lookup |
| 398 // table, so we need to insure that they don't interfere. | 541 // table, so we need to insure that they don't interfere. |
| 399 | 542 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 427 AddField(message2, "foo", 1, | 570 AddField(message2, "foo", 1, |
| 428 FieldDescriptorProto::LABEL_REQUIRED, | 571 FieldDescriptorProto::LABEL_REQUIRED, |
| 429 FieldDescriptorProto::TYPE_STRING); | 572 FieldDescriptorProto::TYPE_STRING); |
| 430 AddField(message2, "bar", 2, | 573 AddField(message2, "bar", 2, |
| 431 FieldDescriptorProto::LABEL_REQUIRED, | 574 FieldDescriptorProto::LABEL_REQUIRED, |
| 432 FieldDescriptorProto::TYPE_STRING); | 575 FieldDescriptorProto::TYPE_STRING); |
| 433 AddField(message2, "quux", 6, | 576 AddField(message2, "quux", 6, |
| 434 FieldDescriptorProto::LABEL_REQUIRED, | 577 FieldDescriptorProto::LABEL_REQUIRED, |
| 435 FieldDescriptorProto::TYPE_STRING); | 578 FieldDescriptorProto::TYPE_STRING); |
| 436 | 579 |
| 580 FileDescriptorProto map_file; |
| 581 map_file.set_name("map.proto"); |
| 582 DescriptorProto* message3 = AddMessage(&map_file, "TestMessage3"); |
| 583 |
| 584 DescriptorProto* entry = AddNestedMessage(message3, "MapInt32Int32Entry"); |
| 585 AddField(entry, "key", 1, |
| 586 FieldDescriptorProto::LABEL_OPTIONAL, |
| 587 FieldDescriptorProto::TYPE_INT32); |
| 588 AddField(entry, "value", 2, |
| 589 FieldDescriptorProto::LABEL_OPTIONAL, |
| 590 FieldDescriptorProto::TYPE_INT32); |
| 591 entry->mutable_options()->set_map_entry(true); |
| 592 |
| 593 AddField(message3, "map_int32_int32", 1, |
| 594 FieldDescriptorProto::LABEL_REPEATED, |
| 595 FieldDescriptorProto::TYPE_MESSAGE) |
| 596 ->set_type_name("MapInt32Int32Entry"); |
| 597 |
| 598 FileDescriptorProto json_file; |
| 599 json_file.set_name("json.proto"); |
| 600 json_file.set_syntax("proto3"); |
| 601 DescriptorProto* message4 = AddMessage(&json_file, "TestMessage4"); |
| 602 AddField(message4, "field_name1", 1, |
| 603 FieldDescriptorProto::LABEL_OPTIONAL, |
| 604 FieldDescriptorProto::TYPE_INT32); |
| 605 AddField(message4, "fieldName2", 2, |
| 606 FieldDescriptorProto::LABEL_OPTIONAL, |
| 607 FieldDescriptorProto::TYPE_INT32); |
| 608 AddField(message4, "FieldName3", 3, |
| 609 FieldDescriptorProto::LABEL_OPTIONAL, |
| 610 FieldDescriptorProto::TYPE_INT32); |
| 611 AddField(message4, "_field_name4", 4, |
| 612 FieldDescriptorProto::LABEL_OPTIONAL, |
| 613 FieldDescriptorProto::TYPE_INT32); |
| 614 AddField(message4, "FIELD_NAME5", 5, |
| 615 FieldDescriptorProto::LABEL_OPTIONAL, |
| 616 FieldDescriptorProto::TYPE_INT32); |
| 617 AddField(message4, "field_name6", 6, |
| 618 FieldDescriptorProto::LABEL_OPTIONAL, |
| 619 FieldDescriptorProto::TYPE_INT32) |
| 620 ->set_json_name("@type"); |
| 621 |
| 437 // Build the descriptors and get the pointers. | 622 // Build the descriptors and get the pointers. |
| 438 foo_file_ = pool_.BuildFile(foo_file); | 623 foo_file_ = pool_.BuildFile(foo_file); |
| 439 ASSERT_TRUE(foo_file_ != NULL); | 624 ASSERT_TRUE(foo_file_ != NULL); |
| 440 | 625 |
| 441 bar_file_ = pool_.BuildFile(bar_file); | 626 bar_file_ = pool_.BuildFile(bar_file); |
| 442 ASSERT_TRUE(bar_file_ != NULL); | 627 ASSERT_TRUE(bar_file_ != NULL); |
| 443 | 628 |
| 629 map_file_ = pool_.BuildFile(map_file); |
| 630 ASSERT_TRUE(map_file_ != NULL); |
| 631 |
| 632 json_file_ = pool_.BuildFile(json_file); |
| 633 ASSERT_TRUE(json_file_ != NULL); |
| 634 |
| 444 ASSERT_EQ(1, foo_file_->enum_type_count()); | 635 ASSERT_EQ(1, foo_file_->enum_type_count()); |
| 445 enum_ = foo_file_->enum_type(0); | 636 enum_ = foo_file_->enum_type(0); |
| 446 | 637 |
| 447 ASSERT_EQ(2, foo_file_->message_type_count()); | 638 ASSERT_EQ(2, foo_file_->message_type_count()); |
| 448 foreign_ = foo_file_->message_type(0); | 639 foreign_ = foo_file_->message_type(0); |
| 449 message_ = foo_file_->message_type(1); | 640 message_ = foo_file_->message_type(1); |
| 450 | 641 |
| 451 ASSERT_EQ(4, message_->field_count()); | 642 ASSERT_EQ(4, message_->field_count()); |
| 452 foo_ = message_->field(0); | 643 foo_ = message_->field(0); |
| 453 bar_ = message_->field(1); | 644 bar_ = message_->field(1); |
| 454 baz_ = message_->field(2); | 645 baz_ = message_->field(2); |
| 455 qux_ = message_->field(3); | 646 qux_ = message_->field(3); |
| 456 | 647 |
| 457 ASSERT_EQ(1, bar_file_->message_type_count()); | 648 ASSERT_EQ(1, bar_file_->message_type_count()); |
| 458 message2_ = bar_file_->message_type(0); | 649 message2_ = bar_file_->message_type(0); |
| 459 | 650 |
| 460 ASSERT_EQ(3, message2_->field_count()); | 651 ASSERT_EQ(3, message2_->field_count()); |
| 461 foo2_ = message2_->field(0); | 652 foo2_ = message2_->field(0); |
| 462 bar2_ = message2_->field(1); | 653 bar2_ = message2_->field(1); |
| 463 quux2_ = message2_->field(2); | 654 quux2_ = message2_->field(2); |
| 655 |
| 656 ASSERT_EQ(1, map_file_->message_type_count()); |
| 657 message3_ = map_file_->message_type(0); |
| 658 |
| 659 ASSERT_EQ(1, message3_->field_count()); |
| 660 map_ = message3_->field(0); |
| 661 |
| 662 ASSERT_EQ(1, json_file_->message_type_count()); |
| 663 message4_ = json_file_->message_type(0); |
| 664 } |
| 665 |
| 666 void CopyWithJsonName(const Descriptor* message, DescriptorProto* proto) { |
| 667 message->CopyTo(proto); |
| 668 message->CopyJsonNameTo(proto); |
| 464 } | 669 } |
| 465 | 670 |
| 466 DescriptorPool pool_; | 671 DescriptorPool pool_; |
| 467 | 672 |
| 468 const FileDescriptor* foo_file_; | 673 const FileDescriptor* foo_file_; |
| 469 const FileDescriptor* bar_file_; | 674 const FileDescriptor* bar_file_; |
| 675 const FileDescriptor* map_file_; |
| 676 const FileDescriptor* json_file_; |
| 470 | 677 |
| 471 const Descriptor* message_; | 678 const Descriptor* message_; |
| 472 const Descriptor* message2_; | 679 const Descriptor* message2_; |
| 680 const Descriptor* message3_; |
| 681 const Descriptor* message4_; |
| 473 const Descriptor* foreign_; | 682 const Descriptor* foreign_; |
| 474 const EnumDescriptor* enum_; | 683 const EnumDescriptor* enum_; |
| 475 | 684 |
| 476 const FieldDescriptor* foo_; | 685 const FieldDescriptor* foo_; |
| 477 const FieldDescriptor* bar_; | 686 const FieldDescriptor* bar_; |
| 478 const FieldDescriptor* baz_; | 687 const FieldDescriptor* baz_; |
| 479 const FieldDescriptor* qux_; | 688 const FieldDescriptor* qux_; |
| 480 | 689 |
| 481 const FieldDescriptor* foo2_; | 690 const FieldDescriptor* foo2_; |
| 482 const FieldDescriptor* bar2_; | 691 const FieldDescriptor* bar2_; |
| 483 const FieldDescriptor* quux2_; | 692 const FieldDescriptor* quux2_; |
| 693 |
| 694 const FieldDescriptor* map_; |
| 484 }; | 695 }; |
| 485 | 696 |
| 486 TEST_F(DescriptorTest, Name) { | 697 TEST_F(DescriptorTest, Name) { |
| 487 EXPECT_EQ("TestMessage", message_->name()); | 698 EXPECT_EQ("TestMessage", message_->name()); |
| 488 EXPECT_EQ("TestMessage", message_->full_name()); | 699 EXPECT_EQ("TestMessage", message_->full_name()); |
| 489 EXPECT_EQ(foo_file_, message_->file()); | 700 EXPECT_EQ(foo_file_, message_->file()); |
| 490 | 701 |
| 491 EXPECT_EQ("TestMessage2", message2_->name()); | 702 EXPECT_EQ("TestMessage2", message2_->name()); |
| 492 EXPECT_EQ("corge.grault.TestMessage2", message2_->full_name()); | 703 EXPECT_EQ("corge.grault.TestMessage2", message2_->full_name()); |
| 493 EXPECT_EQ(bar_file_, message2_->file()); | 704 EXPECT_EQ(bar_file_, message2_->file()); |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 552 EXPECT_EQ("TestMessage.foo", foo_->full_name()); | 763 EXPECT_EQ("TestMessage.foo", foo_->full_name()); |
| 553 EXPECT_EQ("TestMessage.bar", bar_->full_name()); | 764 EXPECT_EQ("TestMessage.bar", bar_->full_name()); |
| 554 EXPECT_EQ("TestMessage.baz", baz_->full_name()); | 765 EXPECT_EQ("TestMessage.baz", baz_->full_name()); |
| 555 EXPECT_EQ("TestMessage.qux", qux_->full_name()); | 766 EXPECT_EQ("TestMessage.qux", qux_->full_name()); |
| 556 | 767 |
| 557 EXPECT_EQ("corge.grault.TestMessage2.foo", foo2_->full_name()); | 768 EXPECT_EQ("corge.grault.TestMessage2.foo", foo2_->full_name()); |
| 558 EXPECT_EQ("corge.grault.TestMessage2.bar", bar2_->full_name()); | 769 EXPECT_EQ("corge.grault.TestMessage2.bar", bar2_->full_name()); |
| 559 EXPECT_EQ("corge.grault.TestMessage2.quux", quux2_->full_name()); | 770 EXPECT_EQ("corge.grault.TestMessage2.quux", quux2_->full_name()); |
| 560 } | 771 } |
| 561 | 772 |
| 773 TEST_F(DescriptorTest, FieldJsonName) { |
| 774 EXPECT_EQ("fieldName1", message4_->field(0)->json_name()); |
| 775 EXPECT_EQ("fieldName2", message4_->field(1)->json_name()); |
| 776 EXPECT_EQ("fieldName3", message4_->field(2)->json_name()); |
| 777 EXPECT_EQ("fieldName4", message4_->field(3)->json_name()); |
| 778 EXPECT_EQ("fIELDNAME5", message4_->field(4)->json_name()); |
| 779 EXPECT_EQ("@type", message4_->field(5)->json_name()); |
| 780 |
| 781 DescriptorProto proto; |
| 782 message4_->CopyTo(&proto); |
| 783 ASSERT_EQ(6, proto.field_size()); |
| 784 EXPECT_FALSE(proto.field(0).has_json_name()); |
| 785 EXPECT_FALSE(proto.field(1).has_json_name()); |
| 786 EXPECT_FALSE(proto.field(2).has_json_name()); |
| 787 EXPECT_FALSE(proto.field(3).has_json_name()); |
| 788 EXPECT_FALSE(proto.field(4).has_json_name()); |
| 789 EXPECT_EQ("@type", proto.field(5).json_name()); |
| 790 |
| 791 proto.Clear(); |
| 792 CopyWithJsonName(message4_, &proto); |
| 793 ASSERT_EQ(6, proto.field_size()); |
| 794 EXPECT_EQ("fieldName1", proto.field(0).json_name()); |
| 795 EXPECT_EQ("fieldName2", proto.field(1).json_name()); |
| 796 EXPECT_EQ("fieldName3", proto.field(2).json_name()); |
| 797 EXPECT_EQ("fieldName4", proto.field(3).json_name()); |
| 798 EXPECT_EQ("fIELDNAME5", proto.field(4).json_name()); |
| 799 EXPECT_EQ("@type", proto.field(5).json_name()); |
| 800 } |
| 801 |
| 562 TEST_F(DescriptorTest, FieldFile) { | 802 TEST_F(DescriptorTest, FieldFile) { |
| 563 EXPECT_EQ(foo_file_, foo_->file()); | 803 EXPECT_EQ(foo_file_, foo_->file()); |
| 564 EXPECT_EQ(foo_file_, bar_->file()); | 804 EXPECT_EQ(foo_file_, bar_->file()); |
| 565 EXPECT_EQ(foo_file_, baz_->file()); | 805 EXPECT_EQ(foo_file_, baz_->file()); |
| 566 EXPECT_EQ(foo_file_, qux_->file()); | 806 EXPECT_EQ(foo_file_, qux_->file()); |
| 567 | 807 |
| 568 EXPECT_EQ(bar_file_, foo2_->file()); | 808 EXPECT_EQ(bar_file_, foo2_->file()); |
| 569 EXPECT_EQ(bar_file_, bar2_->file()); | 809 EXPECT_EQ(bar_file_, bar2_->file()); |
| 570 EXPECT_EQ(bar_file_, quux2_->file()); | 810 EXPECT_EQ(bar_file_, quux2_->file()); |
| 571 } | 811 } |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 603 | 843 |
| 604 EXPECT_FALSE(bar_->is_required()); | 844 EXPECT_FALSE(bar_->is_required()); |
| 605 EXPECT_TRUE (bar_->is_optional()); | 845 EXPECT_TRUE (bar_->is_optional()); |
| 606 EXPECT_FALSE(bar_->is_repeated()); | 846 EXPECT_FALSE(bar_->is_repeated()); |
| 607 | 847 |
| 608 EXPECT_FALSE(baz_->is_required()); | 848 EXPECT_FALSE(baz_->is_required()); |
| 609 EXPECT_FALSE(baz_->is_optional()); | 849 EXPECT_FALSE(baz_->is_optional()); |
| 610 EXPECT_TRUE (baz_->is_repeated()); | 850 EXPECT_TRUE (baz_->is_repeated()); |
| 611 } | 851 } |
| 612 | 852 |
| 853 TEST_F(DescriptorTest, IsMap) { |
| 854 EXPECT_TRUE(map_->is_map()); |
| 855 EXPECT_FALSE(baz_->is_map()); |
| 856 EXPECT_TRUE(map_->message_type()->options().map_entry()); |
| 857 } |
| 858 |
| 613 TEST_F(DescriptorTest, FieldHasDefault) { | 859 TEST_F(DescriptorTest, FieldHasDefault) { |
| 614 EXPECT_FALSE(foo_->has_default_value()); | 860 EXPECT_FALSE(foo_->has_default_value()); |
| 615 EXPECT_FALSE(bar_->has_default_value()); | 861 EXPECT_FALSE(bar_->has_default_value()); |
| 616 EXPECT_FALSE(baz_->has_default_value()); | 862 EXPECT_FALSE(baz_->has_default_value()); |
| 617 EXPECT_FALSE(qux_->has_default_value()); | 863 EXPECT_FALSE(qux_->has_default_value()); |
| 618 } | 864 } |
| 619 | 865 |
| 620 TEST_F(DescriptorTest, FieldContainingType) { | 866 TEST_F(DescriptorTest, FieldContainingType) { |
| 621 EXPECT_EQ(message_, foo_->containing_type()); | 867 EXPECT_EQ(message_, foo_->containing_type()); |
| 622 EXPECT_EQ(message_, bar_->containing_type()); | 868 EXPECT_EQ(message_, bar_->containing_type()); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 639 TEST_F(DescriptorTest, FieldEnumType) { | 885 TEST_F(DescriptorTest, FieldEnumType) { |
| 640 EXPECT_TRUE(foo_->enum_type() == NULL); | 886 EXPECT_TRUE(foo_->enum_type() == NULL); |
| 641 EXPECT_TRUE(baz_->enum_type() == NULL); | 887 EXPECT_TRUE(baz_->enum_type() == NULL); |
| 642 EXPECT_TRUE(qux_->enum_type() == NULL); | 888 EXPECT_TRUE(qux_->enum_type() == NULL); |
| 643 | 889 |
| 644 EXPECT_EQ(enum_, bar_->enum_type()); | 890 EXPECT_EQ(enum_, bar_->enum_type()); |
| 645 } | 891 } |
| 646 | 892 |
| 647 // =================================================================== | 893 // =================================================================== |
| 648 | 894 |
| 895 // Test simple flat messages and fields. |
| 896 class OneofDescriptorTest : public testing::Test { |
| 897 protected: |
| 898 virtual void SetUp() { |
| 899 // Build descriptors for the following definitions: |
| 900 // |
| 901 // package garply; |
| 902 // message TestOneof { |
| 903 // optional int32 a = 1; |
| 904 // oneof foo { |
| 905 // string b = 2; |
| 906 // TestOneof c = 3; |
| 907 // } |
| 908 // oneof bar { |
| 909 // float d = 4; |
| 910 // } |
| 911 // } |
| 912 |
| 913 FileDescriptorProto baz_file; |
| 914 baz_file.set_name("baz.proto"); |
| 915 baz_file.set_package("garply"); |
| 916 |
| 917 DescriptorProto* oneof_message = AddMessage(&baz_file, "TestOneof"); |
| 918 oneof_message->add_oneof_decl()->set_name("foo"); |
| 919 oneof_message->add_oneof_decl()->set_name("bar"); |
| 920 |
| 921 AddField(oneof_message, "a", 1, |
| 922 FieldDescriptorProto::LABEL_OPTIONAL, |
| 923 FieldDescriptorProto::TYPE_INT32); |
| 924 AddField(oneof_message, "b", 2, |
| 925 FieldDescriptorProto::LABEL_OPTIONAL, |
| 926 FieldDescriptorProto::TYPE_STRING); |
| 927 oneof_message->mutable_field(1)->set_oneof_index(0); |
| 928 AddField(oneof_message, "c", 3, |
| 929 FieldDescriptorProto::LABEL_OPTIONAL, |
| 930 FieldDescriptorProto::TYPE_MESSAGE); |
| 931 oneof_message->mutable_field(2)->set_oneof_index(0); |
| 932 oneof_message->mutable_field(2)->set_type_name("TestOneof"); |
| 933 |
| 934 AddField(oneof_message, "d", 4, |
| 935 FieldDescriptorProto::LABEL_OPTIONAL, |
| 936 FieldDescriptorProto::TYPE_FLOAT); |
| 937 oneof_message->mutable_field(3)->set_oneof_index(1); |
| 938 |
| 939 // Build the descriptors and get the pointers. |
| 940 baz_file_ = pool_.BuildFile(baz_file); |
| 941 ASSERT_TRUE(baz_file_ != NULL); |
| 942 |
| 943 ASSERT_EQ(1, baz_file_->message_type_count()); |
| 944 oneof_message_ = baz_file_->message_type(0); |
| 945 |
| 946 ASSERT_EQ(2, oneof_message_->oneof_decl_count()); |
| 947 oneof_ = oneof_message_->oneof_decl(0); |
| 948 oneof2_ = oneof_message_->oneof_decl(1); |
| 949 |
| 950 ASSERT_EQ(4, oneof_message_->field_count()); |
| 951 a_ = oneof_message_->field(0); |
| 952 b_ = oneof_message_->field(1); |
| 953 c_ = oneof_message_->field(2); |
| 954 d_ = oneof_message_->field(3); |
| 955 } |
| 956 |
| 957 DescriptorPool pool_; |
| 958 |
| 959 const FileDescriptor* baz_file_; |
| 960 |
| 961 const Descriptor* oneof_message_; |
| 962 |
| 963 const OneofDescriptor* oneof_; |
| 964 const OneofDescriptor* oneof2_; |
| 965 const FieldDescriptor* a_; |
| 966 const FieldDescriptor* b_; |
| 967 const FieldDescriptor* c_; |
| 968 const FieldDescriptor* d_; |
| 969 const FieldDescriptor* e_; |
| 970 const FieldDescriptor* f_; |
| 971 }; |
| 972 |
| 973 TEST_F(OneofDescriptorTest, Normal) { |
| 974 EXPECT_EQ("foo", oneof_->name()); |
| 975 EXPECT_EQ("garply.TestOneof.foo", oneof_->full_name()); |
| 976 EXPECT_EQ(0, oneof_->index()); |
| 977 ASSERT_EQ(2, oneof_->field_count()); |
| 978 EXPECT_EQ(b_, oneof_->field(0)); |
| 979 EXPECT_EQ(c_, oneof_->field(1)); |
| 980 EXPECT_TRUE(a_->containing_oneof() == NULL); |
| 981 EXPECT_EQ(oneof_, b_->containing_oneof()); |
| 982 EXPECT_EQ(oneof_, c_->containing_oneof()); |
| 983 } |
| 984 |
| 985 TEST_F(OneofDescriptorTest, FindByName) { |
| 986 EXPECT_EQ(oneof_, oneof_message_->FindOneofByName("foo")); |
| 987 EXPECT_EQ(oneof2_, oneof_message_->FindOneofByName("bar")); |
| 988 EXPECT_TRUE(oneof_message_->FindOneofByName("no_such_oneof") == NULL); |
| 989 } |
| 990 |
| 991 // =================================================================== |
| 992 |
| 649 class StylizedFieldNamesTest : public testing::Test { | 993 class StylizedFieldNamesTest : public testing::Test { |
| 650 protected: | 994 protected: |
| 651 void SetUp() { | 995 void SetUp() { |
| 652 FileDescriptorProto file; | 996 FileDescriptorProto file; |
| 653 file.set_name("foo.proto"); | 997 file.set_name("foo.proto"); |
| 654 | 998 |
| 655 AddExtensionRange(AddMessage(&file, "ExtendableMessage"), 1, 1000); | 999 AddExtensionRange(AddMessage(&file, "ExtendableMessage"), 1, 1000); |
| 656 | 1000 |
| 657 DescriptorProto* message = AddMessage(&file, "TestMessage"); | 1001 DescriptorProto* message = AddMessage(&file, "TestMessage"); |
| 658 AddField(message, "foo_foo", 1, | 1002 AddField(message, "foo_foo", 1, |
| (...skipping 850 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1509 TEST_F(ExtensionDescriptorTest, FindAllExtensions) { | 1853 TEST_F(ExtensionDescriptorTest, FindAllExtensions) { |
| 1510 vector<const FieldDescriptor*> extensions; | 1854 vector<const FieldDescriptor*> extensions; |
| 1511 pool_.FindAllExtensions(foo_, &extensions); | 1855 pool_.FindAllExtensions(foo_, &extensions); |
| 1512 ASSERT_EQ(4, extensions.size()); | 1856 ASSERT_EQ(4, extensions.size()); |
| 1513 EXPECT_EQ(10, extensions[0]->number()); | 1857 EXPECT_EQ(10, extensions[0]->number()); |
| 1514 EXPECT_EQ(19, extensions[1]->number()); | 1858 EXPECT_EQ(19, extensions[1]->number()); |
| 1515 EXPECT_EQ(30, extensions[2]->number()); | 1859 EXPECT_EQ(30, extensions[2]->number()); |
| 1516 EXPECT_EQ(39, extensions[3]->number()); | 1860 EXPECT_EQ(39, extensions[3]->number()); |
| 1517 } | 1861 } |
| 1518 | 1862 |
| 1863 TEST_F(ExtensionDescriptorTest, DuplicateFieldNumber) { |
| 1864 DescriptorPool pool; |
| 1865 FileDescriptorProto file_proto; |
| 1866 // Add "google/protobuf/descriptor.proto". |
| 1867 FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto); |
| 1868 ASSERT_TRUE(pool.BuildFile(file_proto) != NULL); |
| 1869 // Add "foo.proto": |
| 1870 // import "google/protobuf/descriptor.proto"; |
| 1871 // extend google.protobuf.FieldOptions { |
| 1872 // optional int32 option1 = 1000; |
| 1873 // } |
| 1874 file_proto.Clear(); |
| 1875 file_proto.set_name("foo.proto"); |
| 1876 file_proto.add_dependency("google/protobuf/descriptor.proto"); |
| 1877 AddExtension(&file_proto, "google.protobuf.FieldOptions", "option1", 1000, |
| 1878 FieldDescriptorProto::LABEL_OPTIONAL, |
| 1879 FieldDescriptorProto::TYPE_INT32); |
| 1880 ASSERT_TRUE(pool.BuildFile(file_proto) != NULL); |
| 1881 // Add "bar.proto": |
| 1882 // import "google/protobuf/descriptor.proto"; |
| 1883 // extend google.protobuf.FieldOptions { |
| 1884 // optional int32 option2 = 1000; |
| 1885 // } |
| 1886 file_proto.Clear(); |
| 1887 file_proto.set_name("bar.proto"); |
| 1888 file_proto.add_dependency("google/protobuf/descriptor.proto"); |
| 1889 AddExtension(&file_proto, "google.protobuf.FieldOptions", "option2", 1000, |
| 1890 FieldDescriptorProto::LABEL_OPTIONAL, |
| 1891 FieldDescriptorProto::TYPE_INT32); |
| 1892 // Currently we only generate a warning for conflicting extension numbers. |
| 1893 // TODO(xiaofeng): Change it to an error. |
| 1894 ASSERT_TRUE(pool.BuildFile(file_proto) != NULL); |
| 1895 } |
| 1896 |
| 1519 // =================================================================== | 1897 // =================================================================== |
| 1520 | 1898 |
| 1899 // Test reserved fields. |
| 1900 class ReservedDescriptorTest : public testing::Test { |
| 1901 protected: |
| 1902 virtual void SetUp() { |
| 1903 // Build descriptors for the following definitions: |
| 1904 // |
| 1905 // message Foo { |
| 1906 // reserved 2, 9 to 11, 15; |
| 1907 // reserved "foo", "bar"; |
| 1908 // } |
| 1909 |
| 1910 FileDescriptorProto foo_file; |
| 1911 foo_file.set_name("foo.proto"); |
| 1912 |
| 1913 DescriptorProto* foo = AddMessage(&foo_file, "Foo"); |
| 1914 AddReservedRange(foo, 2, 3); |
| 1915 AddReservedRange(foo, 9, 12); |
| 1916 AddReservedRange(foo, 15, 16); |
| 1917 |
| 1918 foo->add_reserved_name("foo"); |
| 1919 foo->add_reserved_name("bar"); |
| 1920 |
| 1921 // Build the descriptors and get the pointers. |
| 1922 foo_file_ = pool_.BuildFile(foo_file); |
| 1923 ASSERT_TRUE(foo_file_ != NULL); |
| 1924 |
| 1925 ASSERT_EQ(1, foo_file_->message_type_count()); |
| 1926 foo_ = foo_file_->message_type(0); |
| 1927 } |
| 1928 |
| 1929 DescriptorPool pool_; |
| 1930 const FileDescriptor* foo_file_; |
| 1931 const Descriptor* foo_; |
| 1932 }; |
| 1933 |
| 1934 TEST_F(ReservedDescriptorTest, ReservedRanges) { |
| 1935 ASSERT_EQ(3, foo_->reserved_range_count()); |
| 1936 |
| 1937 EXPECT_EQ(2, foo_->reserved_range(0)->start); |
| 1938 EXPECT_EQ(3, foo_->reserved_range(0)->end); |
| 1939 |
| 1940 EXPECT_EQ(9, foo_->reserved_range(1)->start); |
| 1941 EXPECT_EQ(12, foo_->reserved_range(1)->end); |
| 1942 |
| 1943 EXPECT_EQ(15, foo_->reserved_range(2)->start); |
| 1944 EXPECT_EQ(16, foo_->reserved_range(2)->end); |
| 1945 }; |
| 1946 |
| 1947 TEST_F(ReservedDescriptorTest, IsReservedNumber) { |
| 1948 EXPECT_FALSE(foo_->IsReservedNumber(1)); |
| 1949 EXPECT_TRUE (foo_->IsReservedNumber(2)); |
| 1950 EXPECT_FALSE(foo_->IsReservedNumber(3)); |
| 1951 EXPECT_FALSE(foo_->IsReservedNumber(8)); |
| 1952 EXPECT_TRUE (foo_->IsReservedNumber(9)); |
| 1953 EXPECT_TRUE (foo_->IsReservedNumber(10)); |
| 1954 EXPECT_TRUE (foo_->IsReservedNumber(11)); |
| 1955 EXPECT_FALSE(foo_->IsReservedNumber(12)); |
| 1956 EXPECT_FALSE(foo_->IsReservedNumber(13)); |
| 1957 EXPECT_FALSE(foo_->IsReservedNumber(14)); |
| 1958 EXPECT_TRUE (foo_->IsReservedNumber(15)); |
| 1959 EXPECT_FALSE(foo_->IsReservedNumber(16)); |
| 1960 }; |
| 1961 |
| 1962 TEST_F(ReservedDescriptorTest, ReservedNames) { |
| 1963 ASSERT_EQ(2, foo_->reserved_name_count()); |
| 1964 |
| 1965 EXPECT_EQ("foo", foo_->reserved_name(0)); |
| 1966 EXPECT_EQ("bar", foo_->reserved_name(1)); |
| 1967 }; |
| 1968 |
| 1969 TEST_F(ReservedDescriptorTest, IsReservedName) { |
| 1970 EXPECT_TRUE (foo_->IsReservedName("foo")); |
| 1971 EXPECT_TRUE (foo_->IsReservedName("bar")); |
| 1972 EXPECT_FALSE(foo_->IsReservedName("baz")); |
| 1973 }; |
| 1974 |
| 1975 // =================================================================== |
| 1976 |
| 1521 class MiscTest : public testing::Test { | 1977 class MiscTest : public testing::Test { |
| 1522 protected: | 1978 protected: |
| 1523 // Function which makes a field descriptor of the given type. | 1979 // Function which makes a field descriptor of the given type. |
| 1524 const FieldDescriptor* GetFieldDescriptorOfType(FieldDescriptor::Type type) { | 1980 const FieldDescriptor* GetFieldDescriptorOfType(FieldDescriptor::Type type) { |
| 1525 FileDescriptorProto file_proto; | 1981 FileDescriptorProto file_proto; |
| 1526 file_proto.set_name("foo.proto"); | 1982 file_proto.set_name("foo.proto"); |
| 1527 AddEmptyEnum(&file_proto, "DummyEnum"); | 1983 AddEmptyEnum(&file_proto, "DummyEnum"); |
| 1528 | 1984 |
| 1529 DescriptorProto* message = AddMessage(&file_proto, "TestMessage"); | 1985 DescriptorProto* message = AddMessage(&file_proto, "TestMessage"); |
| 1530 FieldDescriptorProto* field = | 1986 FieldDescriptorProto* field = |
| (...skipping 29 matching lines...) Expand all Loading... |
| 1560 const FieldDescriptor* field = GetFieldDescriptorOfType(type); | 2016 const FieldDescriptor* field = GetFieldDescriptorOfType(type); |
| 1561 return field != NULL ? field->cpp_type() : | 2017 return field != NULL ? field->cpp_type() : |
| 1562 static_cast<FieldDescriptor::CppType>(0); | 2018 static_cast<FieldDescriptor::CppType>(0); |
| 1563 } | 2019 } |
| 1564 | 2020 |
| 1565 const char* GetCppTypeNameForFieldType(FieldDescriptor::Type type) { | 2021 const char* GetCppTypeNameForFieldType(FieldDescriptor::Type type) { |
| 1566 const FieldDescriptor* field = GetFieldDescriptorOfType(type); | 2022 const FieldDescriptor* field = GetFieldDescriptorOfType(type); |
| 1567 return field != NULL ? field->cpp_type_name() : ""; | 2023 return field != NULL ? field->cpp_type_name() : ""; |
| 1568 } | 2024 } |
| 1569 | 2025 |
| 1570 scoped_ptr<DescriptorPool> pool_; | 2026 const Descriptor* GetMessageDescriptorForFieldType( |
| 2027 FieldDescriptor::Type type) { |
| 2028 const FieldDescriptor* field = GetFieldDescriptorOfType(type); |
| 2029 return field != NULL ? field->message_type() : NULL; |
| 2030 } |
| 2031 |
| 2032 const EnumDescriptor* GetEnumDescriptorForFieldType( |
| 2033 FieldDescriptor::Type type) { |
| 2034 const FieldDescriptor* field = GetFieldDescriptorOfType(type); |
| 2035 return field != NULL ? field->enum_type() : NULL; |
| 2036 } |
| 2037 |
| 2038 google::protobuf::scoped_ptr<DescriptorPool> pool_; |
| 1571 }; | 2039 }; |
| 1572 | 2040 |
| 1573 TEST_F(MiscTest, TypeNames) { | 2041 TEST_F(MiscTest, TypeNames) { |
| 1574 // Test that correct type names are returned. | 2042 // Test that correct type names are returned. |
| 1575 | 2043 |
| 1576 typedef FieldDescriptor FD; // avoid ugly line wrapping | 2044 typedef FieldDescriptor FD; // avoid ugly line wrapping |
| 1577 | 2045 |
| 1578 EXPECT_STREQ("double" , GetTypeNameForFieldType(FD::TYPE_DOUBLE )); | 2046 EXPECT_STREQ("double" , GetTypeNameForFieldType(FD::TYPE_DOUBLE )); |
| 1579 EXPECT_STREQ("float" , GetTypeNameForFieldType(FD::TYPE_FLOAT )); | 2047 EXPECT_STREQ("float" , GetTypeNameForFieldType(FD::TYPE_FLOAT )); |
| 1580 EXPECT_STREQ("int64" , GetTypeNameForFieldType(FD::TYPE_INT64 )); | 2048 EXPECT_STREQ("int64" , GetTypeNameForFieldType(FD::TYPE_INT64 )); |
| 1581 EXPECT_STREQ("uint64" , GetTypeNameForFieldType(FD::TYPE_UINT64 )); | 2049 EXPECT_STREQ("uint64" , GetTypeNameForFieldType(FD::TYPE_UINT64 )); |
| 1582 EXPECT_STREQ("int32" , GetTypeNameForFieldType(FD::TYPE_INT32 )); | 2050 EXPECT_STREQ("int32" , GetTypeNameForFieldType(FD::TYPE_INT32 )); |
| 1583 EXPECT_STREQ("fixed64" , GetTypeNameForFieldType(FD::TYPE_FIXED64 )); | 2051 EXPECT_STREQ("fixed64" , GetTypeNameForFieldType(FD::TYPE_FIXED64 )); |
| 1584 EXPECT_STREQ("fixed32" , GetTypeNameForFieldType(FD::TYPE_FIXED32 )); | 2052 EXPECT_STREQ("fixed32" , GetTypeNameForFieldType(FD::TYPE_FIXED32 )); |
| 1585 EXPECT_STREQ("bool" , GetTypeNameForFieldType(FD::TYPE_BOOL )); | 2053 EXPECT_STREQ("bool" , GetTypeNameForFieldType(FD::TYPE_BOOL )); |
| 1586 EXPECT_STREQ("string" , GetTypeNameForFieldType(FD::TYPE_STRING )); | 2054 EXPECT_STREQ("string" , GetTypeNameForFieldType(FD::TYPE_STRING )); |
| 1587 EXPECT_STREQ("group" , GetTypeNameForFieldType(FD::TYPE_GROUP )); | 2055 EXPECT_STREQ("group" , GetTypeNameForFieldType(FD::TYPE_GROUP )); |
| 1588 EXPECT_STREQ("message" , GetTypeNameForFieldType(FD::TYPE_MESSAGE )); | 2056 EXPECT_STREQ("message" , GetTypeNameForFieldType(FD::TYPE_MESSAGE )); |
| 1589 EXPECT_STREQ("bytes" , GetTypeNameForFieldType(FD::TYPE_BYTES )); | 2057 EXPECT_STREQ("bytes" , GetTypeNameForFieldType(FD::TYPE_BYTES )); |
| 1590 EXPECT_STREQ("uint32" , GetTypeNameForFieldType(FD::TYPE_UINT32 )); | 2058 EXPECT_STREQ("uint32" , GetTypeNameForFieldType(FD::TYPE_UINT32 )); |
| 1591 EXPECT_STREQ("enum" , GetTypeNameForFieldType(FD::TYPE_ENUM )); | 2059 EXPECT_STREQ("enum" , GetTypeNameForFieldType(FD::TYPE_ENUM )); |
| 1592 EXPECT_STREQ("sfixed32", GetTypeNameForFieldType(FD::TYPE_SFIXED32)); | 2060 EXPECT_STREQ("sfixed32", GetTypeNameForFieldType(FD::TYPE_SFIXED32)); |
| 1593 EXPECT_STREQ("sfixed64", GetTypeNameForFieldType(FD::TYPE_SFIXED64)); | 2061 EXPECT_STREQ("sfixed64", GetTypeNameForFieldType(FD::TYPE_SFIXED64)); |
| 1594 EXPECT_STREQ("sint32" , GetTypeNameForFieldType(FD::TYPE_SINT32 )); | 2062 EXPECT_STREQ("sint32" , GetTypeNameForFieldType(FD::TYPE_SINT32 )); |
| 1595 EXPECT_STREQ("sint64" , GetTypeNameForFieldType(FD::TYPE_SINT64 )); | 2063 EXPECT_STREQ("sint64" , GetTypeNameForFieldType(FD::TYPE_SINT64 )); |
| 1596 } | 2064 } |
| 1597 | 2065 |
| 2066 TEST_F(MiscTest, StaticTypeNames) { |
| 2067 // Test that correct type names are returned. |
| 2068 |
| 2069 typedef FieldDescriptor FD; // avoid ugly line wrapping |
| 2070 |
| 2071 EXPECT_STREQ("double" , FD::TypeName(FD::TYPE_DOUBLE )); |
| 2072 EXPECT_STREQ("float" , FD::TypeName(FD::TYPE_FLOAT )); |
| 2073 EXPECT_STREQ("int64" , FD::TypeName(FD::TYPE_INT64 )); |
| 2074 EXPECT_STREQ("uint64" , FD::TypeName(FD::TYPE_UINT64 )); |
| 2075 EXPECT_STREQ("int32" , FD::TypeName(FD::TYPE_INT32 )); |
| 2076 EXPECT_STREQ("fixed64" , FD::TypeName(FD::TYPE_FIXED64 )); |
| 2077 EXPECT_STREQ("fixed32" , FD::TypeName(FD::TYPE_FIXED32 )); |
| 2078 EXPECT_STREQ("bool" , FD::TypeName(FD::TYPE_BOOL )); |
| 2079 EXPECT_STREQ("string" , FD::TypeName(FD::TYPE_STRING )); |
| 2080 EXPECT_STREQ("group" , FD::TypeName(FD::TYPE_GROUP )); |
| 2081 EXPECT_STREQ("message" , FD::TypeName(FD::TYPE_MESSAGE )); |
| 2082 EXPECT_STREQ("bytes" , FD::TypeName(FD::TYPE_BYTES )); |
| 2083 EXPECT_STREQ("uint32" , FD::TypeName(FD::TYPE_UINT32 )); |
| 2084 EXPECT_STREQ("enum" , FD::TypeName(FD::TYPE_ENUM )); |
| 2085 EXPECT_STREQ("sfixed32", FD::TypeName(FD::TYPE_SFIXED32)); |
| 2086 EXPECT_STREQ("sfixed64", FD::TypeName(FD::TYPE_SFIXED64)); |
| 2087 EXPECT_STREQ("sint32" , FD::TypeName(FD::TYPE_SINT32 )); |
| 2088 EXPECT_STREQ("sint64" , FD::TypeName(FD::TYPE_SINT64 )); |
| 2089 } |
| 2090 |
| 1598 TEST_F(MiscTest, CppTypes) { | 2091 TEST_F(MiscTest, CppTypes) { |
| 1599 // Test that CPP types are assigned correctly. | 2092 // Test that CPP types are assigned correctly. |
| 1600 | 2093 |
| 1601 typedef FieldDescriptor FD; // avoid ugly line wrapping | 2094 typedef FieldDescriptor FD; // avoid ugly line wrapping |
| 1602 | 2095 |
| 1603 EXPECT_EQ(FD::CPPTYPE_DOUBLE , GetCppTypeForFieldType(FD::TYPE_DOUBLE )); | 2096 EXPECT_EQ(FD::CPPTYPE_DOUBLE , GetCppTypeForFieldType(FD::TYPE_DOUBLE )); |
| 1604 EXPECT_EQ(FD::CPPTYPE_FLOAT , GetCppTypeForFieldType(FD::TYPE_FLOAT )); | 2097 EXPECT_EQ(FD::CPPTYPE_FLOAT , GetCppTypeForFieldType(FD::TYPE_FLOAT )); |
| 1605 EXPECT_EQ(FD::CPPTYPE_INT64 , GetCppTypeForFieldType(FD::TYPE_INT64 )); | 2098 EXPECT_EQ(FD::CPPTYPE_INT64 , GetCppTypeForFieldType(FD::TYPE_INT64 )); |
| 1606 EXPECT_EQ(FD::CPPTYPE_UINT64 , GetCppTypeForFieldType(FD::TYPE_UINT64 )); | 2099 EXPECT_EQ(FD::CPPTYPE_UINT64 , GetCppTypeForFieldType(FD::TYPE_UINT64 )); |
| 1607 EXPECT_EQ(FD::CPPTYPE_INT32 , GetCppTypeForFieldType(FD::TYPE_INT32 )); | 2100 EXPECT_EQ(FD::CPPTYPE_INT32 , GetCppTypeForFieldType(FD::TYPE_INT32 )); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 1638 EXPECT_STREQ("message", GetCppTypeNameForFieldType(FD::TYPE_MESSAGE )); | 2131 EXPECT_STREQ("message", GetCppTypeNameForFieldType(FD::TYPE_MESSAGE )); |
| 1639 EXPECT_STREQ("string" , GetCppTypeNameForFieldType(FD::TYPE_BYTES )); | 2132 EXPECT_STREQ("string" , GetCppTypeNameForFieldType(FD::TYPE_BYTES )); |
| 1640 EXPECT_STREQ("uint32" , GetCppTypeNameForFieldType(FD::TYPE_UINT32 )); | 2133 EXPECT_STREQ("uint32" , GetCppTypeNameForFieldType(FD::TYPE_UINT32 )); |
| 1641 EXPECT_STREQ("enum" , GetCppTypeNameForFieldType(FD::TYPE_ENUM )); | 2134 EXPECT_STREQ("enum" , GetCppTypeNameForFieldType(FD::TYPE_ENUM )); |
| 1642 EXPECT_STREQ("int32" , GetCppTypeNameForFieldType(FD::TYPE_SFIXED32)); | 2135 EXPECT_STREQ("int32" , GetCppTypeNameForFieldType(FD::TYPE_SFIXED32)); |
| 1643 EXPECT_STREQ("int64" , GetCppTypeNameForFieldType(FD::TYPE_SFIXED64)); | 2136 EXPECT_STREQ("int64" , GetCppTypeNameForFieldType(FD::TYPE_SFIXED64)); |
| 1644 EXPECT_STREQ("int32" , GetCppTypeNameForFieldType(FD::TYPE_SINT32 )); | 2137 EXPECT_STREQ("int32" , GetCppTypeNameForFieldType(FD::TYPE_SINT32 )); |
| 1645 EXPECT_STREQ("int64" , GetCppTypeNameForFieldType(FD::TYPE_SINT64 )); | 2138 EXPECT_STREQ("int64" , GetCppTypeNameForFieldType(FD::TYPE_SINT64 )); |
| 1646 } | 2139 } |
| 1647 | 2140 |
| 2141 TEST_F(MiscTest, StaticCppTypeNames) { |
| 2142 // Test that correct CPP type names are returned. |
| 2143 |
| 2144 typedef FieldDescriptor FD; // avoid ugly line wrapping |
| 2145 |
| 2146 EXPECT_STREQ("int32" , FD::CppTypeName(FD::CPPTYPE_INT32 )); |
| 2147 EXPECT_STREQ("int64" , FD::CppTypeName(FD::CPPTYPE_INT64 )); |
| 2148 EXPECT_STREQ("uint32" , FD::CppTypeName(FD::CPPTYPE_UINT32 )); |
| 2149 EXPECT_STREQ("uint64" , FD::CppTypeName(FD::CPPTYPE_UINT64 )); |
| 2150 EXPECT_STREQ("double" , FD::CppTypeName(FD::CPPTYPE_DOUBLE )); |
| 2151 EXPECT_STREQ("float" , FD::CppTypeName(FD::CPPTYPE_FLOAT )); |
| 2152 EXPECT_STREQ("bool" , FD::CppTypeName(FD::CPPTYPE_BOOL )); |
| 2153 EXPECT_STREQ("enum" , FD::CppTypeName(FD::CPPTYPE_ENUM )); |
| 2154 EXPECT_STREQ("string" , FD::CppTypeName(FD::CPPTYPE_STRING )); |
| 2155 EXPECT_STREQ("message", FD::CppTypeName(FD::CPPTYPE_MESSAGE)); |
| 2156 } |
| 2157 |
| 2158 TEST_F(MiscTest, MessageType) { |
| 2159 // Test that message_type() is NULL for non-aggregate fields |
| 2160 |
| 2161 typedef FieldDescriptor FD; // avoid ugly line wrapping |
| 2162 |
| 2163 EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_DOUBLE )); |
| 2164 EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_FLOAT )); |
| 2165 EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_INT64 )); |
| 2166 EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_UINT64 )); |
| 2167 EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_INT32 )); |
| 2168 EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_FIXED64 )); |
| 2169 EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_FIXED32 )); |
| 2170 EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_BOOL )); |
| 2171 EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_STRING )); |
| 2172 EXPECT_TRUE(NULL != GetMessageDescriptorForFieldType(FD::TYPE_GROUP )); |
| 2173 EXPECT_TRUE(NULL != GetMessageDescriptorForFieldType(FD::TYPE_MESSAGE )); |
| 2174 EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_BYTES )); |
| 2175 EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_UINT32 )); |
| 2176 EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_ENUM )); |
| 2177 EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_SFIXED32)); |
| 2178 EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_SFIXED64)); |
| 2179 EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_SINT32 )); |
| 2180 EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_SINT64 )); |
| 2181 } |
| 2182 |
| 2183 TEST_F(MiscTest, EnumType) { |
| 2184 // Test that enum_type() is NULL for non-enum fields |
| 2185 |
| 2186 typedef FieldDescriptor FD; // avoid ugly line wrapping |
| 2187 |
| 2188 EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_DOUBLE )); |
| 2189 EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_FLOAT )); |
| 2190 EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_INT64 )); |
| 2191 EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_UINT64 )); |
| 2192 EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_INT32 )); |
| 2193 EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_FIXED64 )); |
| 2194 EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_FIXED32 )); |
| 2195 EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_BOOL )); |
| 2196 EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_STRING )); |
| 2197 EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_GROUP )); |
| 2198 EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_MESSAGE )); |
| 2199 EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_BYTES )); |
| 2200 EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_UINT32 )); |
| 2201 EXPECT_TRUE(NULL != GetEnumDescriptorForFieldType(FD::TYPE_ENUM )); |
| 2202 EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_SFIXED32)); |
| 2203 EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_SFIXED64)); |
| 2204 EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_SINT32 )); |
| 2205 EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_SINT64 )); |
| 2206 } |
| 2207 |
| 2208 |
| 1648 TEST_F(MiscTest, DefaultValues) { | 2209 TEST_F(MiscTest, DefaultValues) { |
| 1649 // Test that setting default values works. | 2210 // Test that setting default values works. |
| 1650 FileDescriptorProto file_proto; | 2211 FileDescriptorProto file_proto; |
| 1651 file_proto.set_name("foo.proto"); | 2212 file_proto.set_name("foo.proto"); |
| 1652 | 2213 |
| 1653 EnumDescriptorProto* enum_type_proto = AddEnum(&file_proto, "DummyEnum"); | 2214 EnumDescriptorProto* enum_type_proto = AddEnum(&file_proto, "DummyEnum"); |
| 1654 AddEnumValue(enum_type_proto, "A", 1); | 2215 AddEnumValue(enum_type_proto, "A", 1); |
| 1655 AddEnumValue(enum_type_proto, "B", 2); | 2216 AddEnumValue(enum_type_proto, "B", 2); |
| 1656 | 2217 |
| 1657 DescriptorProto* message_proto = AddMessage(&file_proto, "TestMessage"); | 2218 DescriptorProto* message_proto = AddMessage(&file_proto, "TestMessage"); |
| (...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1897 | 2458 |
| 1898 const FileDescriptor* bar_file_; | 2459 const FileDescriptor* bar_file_; |
| 1899 const Descriptor* bar_type_; | 2460 const Descriptor* bar_type_; |
| 1900 const FileDescriptor* foo_file_; | 2461 const FileDescriptor* foo_file_; |
| 1901 const Descriptor* foo_type_; | 2462 const Descriptor* foo_type_; |
| 1902 const FieldDescriptor* bar_field_; | 2463 const FieldDescriptor* bar_field_; |
| 1903 const FieldDescriptor* baz_field_; | 2464 const FieldDescriptor* baz_field_; |
| 1904 const FieldDescriptor* qux_field_; | 2465 const FieldDescriptor* qux_field_; |
| 1905 | 2466 |
| 1906 SimpleDescriptorDatabase db_; // used if in FALLBACK_DATABASE mode. | 2467 SimpleDescriptorDatabase db_; // used if in FALLBACK_DATABASE mode. |
| 1907 scoped_ptr<DescriptorPool> pool_; | 2468 google::protobuf::scoped_ptr<DescriptorPool> pool_; |
| 1908 }; | 2469 }; |
| 1909 | 2470 |
| 1910 TEST_P(AllowUnknownDependenciesTest, PlaceholderFile) { | 2471 TEST_P(AllowUnknownDependenciesTest, PlaceholderFile) { |
| 1911 ASSERT_EQ(2, foo_file_->dependency_count()); | 2472 ASSERT_EQ(2, foo_file_->dependency_count()); |
| 1912 EXPECT_EQ(bar_file_, foo_file_->dependency(0)); | 2473 EXPECT_EQ(bar_file_, foo_file_->dependency(0)); |
| 2474 EXPECT_FALSE(bar_file_->is_placeholder()); |
| 1913 | 2475 |
| 1914 const FileDescriptor* baz_file = foo_file_->dependency(1); | 2476 const FileDescriptor* baz_file = foo_file_->dependency(1); |
| 1915 EXPECT_EQ("baz.proto", baz_file->name()); | 2477 EXPECT_EQ("baz.proto", baz_file->name()); |
| 1916 EXPECT_EQ(0, baz_file->message_type_count()); | 2478 EXPECT_EQ(0, baz_file->message_type_count()); |
| 2479 EXPECT_TRUE(baz_file->is_placeholder()); |
| 1917 | 2480 |
| 1918 // Placeholder files should not be findable. | 2481 // Placeholder files should not be findable. |
| 1919 EXPECT_EQ(bar_file_, pool_->FindFileByName(bar_file_->name())); | 2482 EXPECT_EQ(bar_file_, pool_->FindFileByName(bar_file_->name())); |
| 1920 EXPECT_TRUE(pool_->FindFileByName(baz_file->name()) == NULL); | 2483 EXPECT_TRUE(pool_->FindFileByName(baz_file->name()) == NULL); |
| 2484 |
| 2485 // Copy*To should not crash for placeholder files. |
| 2486 FileDescriptorProto baz_file_proto; |
| 2487 baz_file->CopyTo(&baz_file_proto); |
| 2488 baz_file->CopySourceCodeInfoTo(&baz_file_proto); |
| 2489 EXPECT_FALSE(baz_file_proto.has_source_code_info()); |
| 1921 } | 2490 } |
| 1922 | 2491 |
| 1923 TEST_P(AllowUnknownDependenciesTest, PlaceholderTypes) { | 2492 TEST_P(AllowUnknownDependenciesTest, PlaceholderTypes) { |
| 1924 ASSERT_EQ(FieldDescriptor::TYPE_MESSAGE, bar_field_->type()); | 2493 ASSERT_EQ(FieldDescriptor::TYPE_MESSAGE, bar_field_->type()); |
| 1925 EXPECT_EQ(bar_type_, bar_field_->message_type()); | 2494 EXPECT_EQ(bar_type_, bar_field_->message_type()); |
| 2495 EXPECT_FALSE(bar_type_->is_placeholder()); |
| 1926 | 2496 |
| 1927 ASSERT_EQ(FieldDescriptor::TYPE_MESSAGE, baz_field_->type()); | 2497 ASSERT_EQ(FieldDescriptor::TYPE_MESSAGE, baz_field_->type()); |
| 1928 const Descriptor* baz_type = baz_field_->message_type(); | 2498 const Descriptor* baz_type = baz_field_->message_type(); |
| 1929 EXPECT_EQ("Baz", baz_type->name()); | 2499 EXPECT_EQ("Baz", baz_type->name()); |
| 1930 EXPECT_EQ("Baz", baz_type->full_name()); | 2500 EXPECT_EQ("Baz", baz_type->full_name()); |
| 1931 EXPECT_EQ("Baz.placeholder.proto", baz_type->file()->name()); | |
| 1932 EXPECT_EQ(0, baz_type->extension_range_count()); | 2501 EXPECT_EQ(0, baz_type->extension_range_count()); |
| 2502 EXPECT_TRUE(baz_type->is_placeholder()); |
| 1933 | 2503 |
| 1934 ASSERT_EQ(FieldDescriptor::TYPE_ENUM, qux_field_->type()); | 2504 ASSERT_EQ(FieldDescriptor::TYPE_ENUM, qux_field_->type()); |
| 1935 const EnumDescriptor* qux_type = qux_field_->enum_type(); | 2505 const EnumDescriptor* qux_type = qux_field_->enum_type(); |
| 1936 EXPECT_EQ("Qux", qux_type->name()); | 2506 EXPECT_EQ("Qux", qux_type->name()); |
| 1937 EXPECT_EQ("corge.Qux", qux_type->full_name()); | 2507 EXPECT_EQ("corge.Qux", qux_type->full_name()); |
| 1938 EXPECT_EQ("corge.Qux.placeholder.proto", qux_type->file()->name()); | 2508 EXPECT_TRUE(qux_type->is_placeholder()); |
| 1939 | 2509 |
| 1940 // Placeholder types should not be findable. | 2510 // Placeholder types should not be findable. |
| 1941 EXPECT_EQ(bar_type_, pool_->FindMessageTypeByName(bar_type_->full_name())); | 2511 EXPECT_EQ(bar_type_, pool_->FindMessageTypeByName(bar_type_->full_name())); |
| 1942 EXPECT_TRUE(pool_->FindMessageTypeByName(baz_type->full_name()) == NULL); | 2512 EXPECT_TRUE(pool_->FindMessageTypeByName(baz_type->full_name()) == NULL); |
| 1943 EXPECT_TRUE(pool_->FindEnumTypeByName(qux_type->full_name()) == NULL); | 2513 EXPECT_TRUE(pool_->FindEnumTypeByName(qux_type->full_name()) == NULL); |
| 1944 } | 2514 } |
| 1945 | 2515 |
| 1946 TEST_P(AllowUnknownDependenciesTest, CopyTo) { | 2516 TEST_P(AllowUnknownDependenciesTest, CopyTo) { |
| 1947 // FieldDescriptor::CopyTo() should write non-fully-qualified type names | 2517 // FieldDescriptor::CopyTo() should write non-fully-qualified type names |
| 1948 // for placeholder types which were not originally fully-qualified. | 2518 // for placeholder types which were not originally fully-qualified. |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1986 "extension { extendee: 'UnknownType' name:'some_extension' number:123" | 2556 "extension { extendee: 'UnknownType' name:'some_extension' number:123" |
| 1987 " label:LABEL_OPTIONAL type:TYPE_INT32 }", | 2557 " label:LABEL_OPTIONAL type:TYPE_INT32 }", |
| 1988 &extension_proto)); | 2558 &extension_proto)); |
| 1989 const FileDescriptor* file = BuildFile(extension_proto); | 2559 const FileDescriptor* file = BuildFile(extension_proto); |
| 1990 | 2560 |
| 1991 ASSERT_TRUE(file != NULL); | 2561 ASSERT_TRUE(file != NULL); |
| 1992 | 2562 |
| 1993 ASSERT_EQ(1, file->extension_count()); | 2563 ASSERT_EQ(1, file->extension_count()); |
| 1994 const Descriptor* extendee = file->extension(0)->containing_type(); | 2564 const Descriptor* extendee = file->extension(0)->containing_type(); |
| 1995 EXPECT_EQ("UnknownType", extendee->name()); | 2565 EXPECT_EQ("UnknownType", extendee->name()); |
| 2566 EXPECT_TRUE(extendee->is_placeholder()); |
| 1996 ASSERT_EQ(1, extendee->extension_range_count()); | 2567 ASSERT_EQ(1, extendee->extension_range_count()); |
| 1997 EXPECT_EQ(1, extendee->extension_range(0)->start); | 2568 EXPECT_EQ(1, extendee->extension_range(0)->start); |
| 1998 EXPECT_EQ(FieldDescriptor::kMaxNumber + 1, extendee->extension_range(0)->end); | 2569 EXPECT_EQ(FieldDescriptor::kMaxNumber + 1, extendee->extension_range(0)->end); |
| 1999 } | 2570 } |
| 2000 | 2571 |
| 2001 TEST_P(AllowUnknownDependenciesTest, CustomOption) { | 2572 TEST_P(AllowUnknownDependenciesTest, CustomOption) { |
| 2002 // Test that we can use a custom option without having parsed | 2573 // Test that we can use a custom option without having parsed |
| 2003 // descriptor.proto. | 2574 // descriptor.proto. |
| 2004 | 2575 |
| 2005 FileDescriptorProto option_proto; | 2576 FileDescriptorProto option_proto; |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2104 | 2675 |
| 2105 const FileDescriptor* file = BuildFile(test_proto); | 2676 const FileDescriptor* file = BuildFile(test_proto); |
| 2106 ASSERT_TRUE(file != NULL); | 2677 ASSERT_TRUE(file != NULL); |
| 2107 GOOGLE_LOG(INFO) << file->DebugString(); | 2678 GOOGLE_LOG(INFO) << file->DebugString(); |
| 2108 | 2679 |
| 2109 EXPECT_EQ(0, file->dependency_count()); | 2680 EXPECT_EQ(0, file->dependency_count()); |
| 2110 ASSERT_EQ(1, file->message_type_count()); | 2681 ASSERT_EQ(1, file->message_type_count()); |
| 2111 const Descriptor* corge_desc = file->message_type(0); | 2682 const Descriptor* corge_desc = file->message_type(0); |
| 2112 ASSERT_EQ("Corge", corge_desc->name()); | 2683 ASSERT_EQ("Corge", corge_desc->name()); |
| 2113 ASSERT_EQ(1, corge_desc->field_count()); | 2684 ASSERT_EQ(1, corge_desc->field_count()); |
| 2685 EXPECT_FALSE(corge_desc->is_placeholder()); |
| 2114 | 2686 |
| 2115 const FieldDescriptor* quux_field = corge_desc->field(0); | 2687 const FieldDescriptor* quux_field = corge_desc->field(0); |
| 2116 ASSERT_EQ(FieldDescriptor::TYPE_MESSAGE, quux_field->type()); | 2688 ASSERT_EQ(FieldDescriptor::TYPE_MESSAGE, quux_field->type()); |
| 2117 ASSERT_EQ("Quux", quux_field->message_type()->name()); | 2689 ASSERT_EQ("Quux", quux_field->message_type()->name()); |
| 2118 ASSERT_EQ("undeclared.Quux", quux_field->message_type()->full_name()); | 2690 ASSERT_EQ("undeclared.Quux", quux_field->message_type()->full_name()); |
| 2119 EXPECT_EQ("undeclared.Quux.placeholder.proto", | 2691 EXPECT_TRUE(quux_field->message_type()->is_placeholder()); |
| 2120 quux_field->message_type()->file()->name()); | |
| 2121 // The place holder type should not be findable. | 2692 // The place holder type should not be findable. |
| 2122 ASSERT_TRUE(pool_->FindMessageTypeByName("undeclared.Quux") == NULL); | 2693 ASSERT_TRUE(pool_->FindMessageTypeByName("undeclared.Quux") == NULL); |
| 2123 } | 2694 } |
| 2124 | 2695 |
| 2125 INSTANTIATE_TEST_CASE_P(DatabaseSource, | 2696 INSTANTIATE_TEST_CASE_P(DatabaseSource, |
| 2126 AllowUnknownDependenciesTest, | 2697 AllowUnknownDependenciesTest, |
| 2127 testing::Values(NO_DATABASE, FALLBACK_DATABASE)); | 2698 testing::Values(NO_DATABASE, FALLBACK_DATABASE)); |
| 2128 | 2699 |
| 2129 // =================================================================== | 2700 // =================================================================== |
| 2130 | 2701 |
| (...skipping 29 matching lines...) Expand all Loading... |
| 2160 // See that the regular options went through unscathed. | 2731 // See that the regular options went through unscathed. |
| 2161 EXPECT_TRUE(message->options().has_message_set_wire_format()); | 2732 EXPECT_TRUE(message->options().has_message_set_wire_format()); |
| 2162 EXPECT_EQ(FieldOptions::CORD, field->options().ctype()); | 2733 EXPECT_EQ(FieldOptions::CORD, field->options().ctype()); |
| 2163 } | 2734 } |
| 2164 | 2735 |
| 2165 TEST(CustomOptions, OptionTypes) { | 2736 TEST(CustomOptions, OptionTypes) { |
| 2166 const MessageOptions* options = NULL; | 2737 const MessageOptions* options = NULL; |
| 2167 | 2738 |
| 2168 options = | 2739 options = |
| 2169 &protobuf_unittest::CustomOptionMinIntegerValues::descriptor()->options(); | 2740 &protobuf_unittest::CustomOptionMinIntegerValues::descriptor()->options(); |
| 2170 EXPECT_FALSE( options->GetExtension(protobuf_unittest::bool_opt)); | 2741 EXPECT_EQ(false , options->GetExtension(protobuf_unittest::bool_opt)); |
| 2171 EXPECT_EQ(kint32min, options->GetExtension(protobuf_unittest::int32_opt)); | 2742 EXPECT_EQ(kint32min, options->GetExtension(protobuf_unittest::int32_opt)); |
| 2172 EXPECT_EQ(kint64min, options->GetExtension(protobuf_unittest::int64_opt)); | 2743 EXPECT_EQ(kint64min, options->GetExtension(protobuf_unittest::int64_opt)); |
| 2173 EXPECT_EQ(0 , options->GetExtension(protobuf_unittest::uint32_opt)); | 2744 EXPECT_EQ(0 , options->GetExtension(protobuf_unittest::uint32_opt)); |
| 2174 EXPECT_EQ(0 , options->GetExtension(protobuf_unittest::uint64_opt)); | 2745 EXPECT_EQ(0 , options->GetExtension(protobuf_unittest::uint64_opt)); |
| 2175 EXPECT_EQ(kint32min, options->GetExtension(protobuf_unittest::sint32_opt)); | 2746 EXPECT_EQ(kint32min, options->GetExtension(protobuf_unittest::sint32_opt)); |
| 2176 EXPECT_EQ(kint64min, options->GetExtension(protobuf_unittest::sint64_opt)); | 2747 EXPECT_EQ(kint64min, options->GetExtension(protobuf_unittest::sint64_opt)); |
| 2177 EXPECT_EQ(0 , options->GetExtension(protobuf_unittest::fixed32_opt)); | 2748 EXPECT_EQ(0 , options->GetExtension(protobuf_unittest::fixed32_opt)); |
| 2178 EXPECT_EQ(0 , options->GetExtension(protobuf_unittest::fixed64_opt)); | 2749 EXPECT_EQ(0 , options->GetExtension(protobuf_unittest::fixed64_opt)); |
| 2179 EXPECT_EQ(kint32min, options->GetExtension(protobuf_unittest::sfixed32_opt)); | 2750 EXPECT_EQ(kint32min, options->GetExtension(protobuf_unittest::sfixed32_opt)); |
| 2180 EXPECT_EQ(kint64min, options->GetExtension(protobuf_unittest::sfixed64_opt)); | 2751 EXPECT_EQ(kint64min, options->GetExtension(protobuf_unittest::sfixed64_opt)); |
| 2181 | 2752 |
| 2182 options = | 2753 options = |
| 2183 &protobuf_unittest::CustomOptionMaxIntegerValues::descriptor()->options(); | 2754 &protobuf_unittest::CustomOptionMaxIntegerValues::descriptor()->options(); |
| 2184 EXPECT_TRUE( options->GetExtension(protobuf_unittest::bool_opt)); | 2755 EXPECT_EQ(true , options->GetExtension(protobuf_unittest::bool_opt)); |
| 2185 EXPECT_EQ(kint32max , options->GetExtension(protobuf_unittest::int32_opt)); | 2756 EXPECT_EQ(kint32max , options->GetExtension(protobuf_unittest::int32_opt)); |
| 2186 EXPECT_EQ(kint64max , options->GetExtension(protobuf_unittest::int64_opt)); | 2757 EXPECT_EQ(kint64max , options->GetExtension(protobuf_unittest::int64_opt)); |
| 2187 EXPECT_EQ(kuint32max, options->GetExtension(protobuf_unittest::uint32_opt)); | 2758 EXPECT_EQ(kuint32max, options->GetExtension(protobuf_unittest::uint32_opt)); |
| 2188 EXPECT_EQ(kuint64max, options->GetExtension(protobuf_unittest::uint64_opt)); | 2759 EXPECT_EQ(kuint64max, options->GetExtension(protobuf_unittest::uint64_opt)); |
| 2189 EXPECT_EQ(kint32max , options->GetExtension(protobuf_unittest::sint32_opt)); | 2760 EXPECT_EQ(kint32max , options->GetExtension(protobuf_unittest::sint32_opt)); |
| 2190 EXPECT_EQ(kint64max , options->GetExtension(protobuf_unittest::sint64_opt)); | 2761 EXPECT_EQ(kint64max , options->GetExtension(protobuf_unittest::sint64_opt)); |
| 2191 EXPECT_EQ(kuint32max, options->GetExtension(protobuf_unittest::fixed32_opt)); | 2762 EXPECT_EQ(kuint32max, options->GetExtension(protobuf_unittest::fixed32_opt)); |
| 2192 EXPECT_EQ(kuint64max, options->GetExtension(protobuf_unittest::fixed64_opt)); | 2763 EXPECT_EQ(kuint64max, options->GetExtension(protobuf_unittest::fixed64_opt)); |
| 2193 EXPECT_EQ(kint32max , options->GetExtension(protobuf_unittest::sfixed32_opt)); | 2764 EXPECT_EQ(kint32max , options->GetExtension(protobuf_unittest::sfixed32_opt)); |
| 2194 EXPECT_EQ(kint64max , options->GetExtension(protobuf_unittest::sfixed64_opt)); | 2765 EXPECT_EQ(kint64max , options->GetExtension(protobuf_unittest::sfixed64_opt)); |
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2382 &file_proto)); | 2953 &file_proto)); |
| 2383 | 2954 |
| 2384 const FileDescriptor* file = pool.BuildFile(file_proto); | 2955 const FileDescriptor* file = pool.BuildFile(file_proto); |
| 2385 ASSERT_TRUE(file != NULL); | 2956 ASSERT_TRUE(file != NULL); |
| 2386 ASSERT_EQ(1, file->message_type_count()); | 2957 ASSERT_EQ(1, file->message_type_count()); |
| 2387 | 2958 |
| 2388 const MessageOptions& options = file->message_type(0)->options(); | 2959 const MessageOptions& options = file->message_type(0)->options(); |
| 2389 EXPECT_EQ(1234, options.GetExtension(protobuf_unittest::complex_opt1).foo()); | 2960 EXPECT_EQ(1234, options.GetExtension(protobuf_unittest::complex_opt1).foo()); |
| 2390 } | 2961 } |
| 2391 | 2962 |
| 2963 TEST(CustomOptions, MessageOptionRepeatedLeafFieldSet) { |
| 2964 // This test verifies that repeated fields in custom options can be |
| 2965 // given multiple values by repeating the option with a different value. |
| 2966 // This test checks repeated leaf values. Each repeated custom value |
| 2967 // appears in a different uninterpreted_option, which will be concatenated |
| 2968 // when they are merged into the final option value. |
| 2969 DescriptorPool pool; |
| 2970 |
| 2971 FileDescriptorProto file_proto; |
| 2972 FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto); |
| 2973 ASSERT_TRUE(pool.BuildFile(file_proto) != NULL); |
| 2974 |
| 2975 protobuf_unittest::TestMessageWithCustomOptions::descriptor() |
| 2976 ->file()->CopyTo(&file_proto); |
| 2977 ASSERT_TRUE(pool.BuildFile(file_proto) != NULL); |
| 2978 |
| 2979 // The following represents the definition: |
| 2980 // |
| 2981 // import "google/protobuf/unittest_custom_options.proto" |
| 2982 // package protobuf_unittest; |
| 2983 // message Foo { |
| 2984 // option (complex_opt1).foo4 = 12; |
| 2985 // option (complex_opt1).foo4 = 34; |
| 2986 // option (complex_opt1).foo4 = 56; |
| 2987 // } |
| 2988 ASSERT_TRUE(TextFormat::ParseFromString( |
| 2989 "name: \"custom_options_import.proto\" " |
| 2990 "package: \"protobuf_unittest\" " |
| 2991 "dependency: \"google/protobuf/unittest_custom_options.proto\" " |
| 2992 "message_type { " |
| 2993 " name: \"Foo\" " |
| 2994 " options { " |
| 2995 " uninterpreted_option { " |
| 2996 " name { " |
| 2997 " name_part: \"complex_opt1\" " |
| 2998 " is_extension: true " |
| 2999 " } " |
| 3000 " name { " |
| 3001 " name_part: \"foo4\" " |
| 3002 " is_extension: false " |
| 3003 " } " |
| 3004 " positive_int_value: 12 " |
| 3005 " } " |
| 3006 " uninterpreted_option { " |
| 3007 " name { " |
| 3008 " name_part: \"complex_opt1\" " |
| 3009 " is_extension: true " |
| 3010 " } " |
| 3011 " name { " |
| 3012 " name_part: \"foo4\" " |
| 3013 " is_extension: false " |
| 3014 " } " |
| 3015 " positive_int_value: 34 " |
| 3016 " } " |
| 3017 " uninterpreted_option { " |
| 3018 " name { " |
| 3019 " name_part: \"complex_opt1\" " |
| 3020 " is_extension: true " |
| 3021 " } " |
| 3022 " name { " |
| 3023 " name_part: \"foo4\" " |
| 3024 " is_extension: false " |
| 3025 " } " |
| 3026 " positive_int_value: 56 " |
| 3027 " } " |
| 3028 " } " |
| 3029 "}", |
| 3030 &file_proto)); |
| 3031 |
| 3032 const FileDescriptor* file = pool.BuildFile(file_proto); |
| 3033 ASSERT_TRUE(file != NULL); |
| 3034 ASSERT_EQ(1, file->message_type_count()); |
| 3035 |
| 3036 const MessageOptions& options = file->message_type(0)->options(); |
| 3037 EXPECT_EQ(3, options.GetExtension(protobuf_unittest::complex_opt1).foo4_size()
); |
| 3038 EXPECT_EQ(12, options.GetExtension(protobuf_unittest::complex_opt1).foo4(0)); |
| 3039 EXPECT_EQ(34, options.GetExtension(protobuf_unittest::complex_opt1).foo4(1)); |
| 3040 EXPECT_EQ(56, options.GetExtension(protobuf_unittest::complex_opt1).foo4(2)); |
| 3041 } |
| 3042 |
| 3043 TEST(CustomOptions, MessageOptionRepeatedMsgFieldSet) { |
| 3044 // This test verifies that repeated fields in custom options can be |
| 3045 // given multiple values by repeating the option with a different value. |
| 3046 // This test checks repeated message values. Each repeated custom value |
| 3047 // appears in a different uninterpreted_option, which will be concatenated |
| 3048 // when they are merged into the final option value. |
| 3049 DescriptorPool pool; |
| 3050 |
| 3051 FileDescriptorProto file_proto; |
| 3052 FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto); |
| 3053 ASSERT_TRUE(pool.BuildFile(file_proto) != NULL); |
| 3054 |
| 3055 protobuf_unittest::TestMessageWithCustomOptions::descriptor() |
| 3056 ->file()->CopyTo(&file_proto); |
| 3057 ASSERT_TRUE(pool.BuildFile(file_proto) != NULL); |
| 3058 |
| 3059 // The following represents the definition: |
| 3060 // |
| 3061 // import "google/protobuf/unittest_custom_options.proto" |
| 3062 // package protobuf_unittest; |
| 3063 // message Foo { |
| 3064 // option (complex_opt2).barney = {waldo: 1}; |
| 3065 // option (complex_opt2).barney = {waldo: 10}; |
| 3066 // option (complex_opt2).barney = {waldo: 100}; |
| 3067 // } |
| 3068 ASSERT_TRUE(TextFormat::ParseFromString( |
| 3069 "name: \"custom_options_import.proto\" " |
| 3070 "package: \"protobuf_unittest\" " |
| 3071 "dependency: \"google/protobuf/unittest_custom_options.proto\" " |
| 3072 "message_type { " |
| 3073 " name: \"Foo\" " |
| 3074 " options { " |
| 3075 " uninterpreted_option { " |
| 3076 " name { " |
| 3077 " name_part: \"complex_opt2\" " |
| 3078 " is_extension: true " |
| 3079 " } " |
| 3080 " name { " |
| 3081 " name_part: \"barney\" " |
| 3082 " is_extension: false " |
| 3083 " } " |
| 3084 " aggregate_value: \"waldo: 1\" " |
| 3085 " } " |
| 3086 " uninterpreted_option { " |
| 3087 " name { " |
| 3088 " name_part: \"complex_opt2\" " |
| 3089 " is_extension: true " |
| 3090 " } " |
| 3091 " name { " |
| 3092 " name_part: \"barney\" " |
| 3093 " is_extension: false " |
| 3094 " } " |
| 3095 " aggregate_value: \"waldo: 10\" " |
| 3096 " } " |
| 3097 " uninterpreted_option { " |
| 3098 " name { " |
| 3099 " name_part: \"complex_opt2\" " |
| 3100 " is_extension: true " |
| 3101 " } " |
| 3102 " name { " |
| 3103 " name_part: \"barney\" " |
| 3104 " is_extension: false " |
| 3105 " } " |
| 3106 " aggregate_value: \"waldo: 100\" " |
| 3107 " } " |
| 3108 " } " |
| 3109 "}", |
| 3110 &file_proto)); |
| 3111 |
| 3112 const FileDescriptor* file = pool.BuildFile(file_proto); |
| 3113 ASSERT_TRUE(file != NULL); |
| 3114 ASSERT_EQ(1, file->message_type_count()); |
| 3115 |
| 3116 const MessageOptions& options = file->message_type(0)->options(); |
| 3117 EXPECT_EQ(3, options.GetExtension( |
| 3118 protobuf_unittest::complex_opt2).barney_size()); |
| 3119 EXPECT_EQ(1,options.GetExtension( |
| 3120 protobuf_unittest::complex_opt2).barney(0).waldo()); |
| 3121 EXPECT_EQ(10, options.GetExtension( |
| 3122 protobuf_unittest::complex_opt2).barney(1).waldo()); |
| 3123 EXPECT_EQ(100, options.GetExtension( |
| 3124 protobuf_unittest::complex_opt2).barney(2).waldo()); |
| 3125 } |
| 3126 |
| 2392 // Check that aggregate options were parsed and saved correctly in | 3127 // Check that aggregate options were parsed and saved correctly in |
| 2393 // the appropriate descriptors. | 3128 // the appropriate descriptors. |
| 2394 TEST(CustomOptions, AggregateOptions) { | 3129 TEST(CustomOptions, AggregateOptions) { |
| 2395 const Descriptor* msg = protobuf_unittest::AggregateMessage::descriptor(); | 3130 const Descriptor* msg = protobuf_unittest::AggregateMessage::descriptor(); |
| 2396 const FileDescriptor* file = msg->file(); | 3131 const FileDescriptor* file = msg->file(); |
| 2397 const FieldDescriptor* field = msg->FindFieldByName("fieldname"); | 3132 const FieldDescriptor* field = msg->FindFieldByName("fieldname"); |
| 2398 const EnumDescriptor* enumd = file->FindEnumTypeByName("AggregateEnum"); | 3133 const EnumDescriptor* enumd = file->FindEnumTypeByName("AggregateEnum"); |
| 2399 const EnumValueDescriptor* enumv = enumd->FindValueByName("VALUE"); | 3134 const EnumValueDescriptor* enumv = enumd->FindValueByName("VALUE"); |
| 2400 const ServiceDescriptor* service = file->FindServiceByName( | 3135 const ServiceDescriptor* service = file->FindServiceByName( |
| 2401 "AggregateService"); | 3136 "AggregateService"); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 2422 EXPECT_EQ("EnumAnnotation", | 3157 EXPECT_EQ("EnumAnnotation", |
| 2423 enumd->options().GetExtension(protobuf_unittest::enumopt).s()); | 3158 enumd->options().GetExtension(protobuf_unittest::enumopt).s()); |
| 2424 EXPECT_EQ("EnumValueAnnotation", | 3159 EXPECT_EQ("EnumValueAnnotation", |
| 2425 enumv->options().GetExtension(protobuf_unittest::enumvalopt).s()); | 3160 enumv->options().GetExtension(protobuf_unittest::enumvalopt).s()); |
| 2426 EXPECT_EQ("ServiceAnnotation", | 3161 EXPECT_EQ("ServiceAnnotation", |
| 2427 service->options().GetExtension(protobuf_unittest::serviceopt).s()); | 3162 service->options().GetExtension(protobuf_unittest::serviceopt).s()); |
| 2428 EXPECT_EQ("MethodAnnotation", | 3163 EXPECT_EQ("MethodAnnotation", |
| 2429 method->options().GetExtension(protobuf_unittest::methodopt).s()); | 3164 method->options().GetExtension(protobuf_unittest::methodopt).s()); |
| 2430 } | 3165 } |
| 2431 | 3166 |
| 3167 TEST(CustomOptions, UnusedImportWarning) { |
| 3168 DescriptorPool pool; |
| 3169 |
| 3170 FileDescriptorProto file_proto; |
| 3171 FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto); |
| 3172 ASSERT_TRUE(pool.BuildFile(file_proto) != NULL); |
| 3173 |
| 3174 protobuf_unittest::TestMessageWithCustomOptions::descriptor() |
| 3175 ->file()->CopyTo(&file_proto); |
| 3176 ASSERT_TRUE(pool.BuildFile(file_proto) != NULL); |
| 3177 |
| 3178 pool.AddUnusedImportTrackFile("custom_options_import.proto"); |
| 3179 ASSERT_TRUE(TextFormat::ParseFromString( |
| 3180 "name: \"custom_options_import.proto\" " |
| 3181 "package: \"protobuf_unittest\" " |
| 3182 "dependency: \"google/protobuf/unittest_custom_options.proto\" ", |
| 3183 &file_proto)); |
| 3184 |
| 3185 MockErrorCollector error_collector; |
| 3186 EXPECT_TRUE(pool.BuildFileCollectingErrors(file_proto, &error_collector)); |
| 3187 EXPECT_EQ("", error_collector.warning_text_); |
| 3188 } |
| 3189 |
| 3190 // Verifies that proto files can correctly be parsed, even if the |
| 3191 // custom options defined in the file are incompatible with those |
| 3192 // compiled in the binary. See http://b/19276250. |
| 3193 TEST(CustomOptions, OptionsWithRequiredEnums) { |
| 3194 DescriptorPool pool; |
| 3195 |
| 3196 FileDescriptorProto file_proto; |
| 3197 MessageOptions::descriptor()->file()->CopyTo(&file_proto); |
| 3198 ASSERT_TRUE(pool.BuildFile(file_proto) != NULL); |
| 3199 |
| 3200 // Create a new file descriptor proto containing a subset of the |
| 3201 // messages defined in google/protobuf/unittest_custom_options.proto. |
| 3202 file_proto.Clear(); |
| 3203 file_proto.set_name("unittest_custom_options.proto"); |
| 3204 file_proto.set_package("protobuf_unittest"); |
| 3205 file_proto.add_dependency("google/protobuf/descriptor.proto"); |
| 3206 |
| 3207 // Add the "required_enum_opt" extension. |
| 3208 FieldDescriptorProto* extension = file_proto.add_extension(); |
| 3209 protobuf_unittest::OldOptionType::descriptor()->file() |
| 3210 ->FindExtensionByName("required_enum_opt")->CopyTo(extension); |
| 3211 |
| 3212 // Add a test message that uses the "required_enum_opt" option. |
| 3213 DescriptorProto* test_message_type = file_proto.add_message_type(); |
| 3214 protobuf_unittest::TestMessageWithRequiredEnumOption::descriptor() |
| 3215 ->CopyTo(test_message_type); |
| 3216 |
| 3217 // Instruct the extension to use NewOptionType instead of |
| 3218 // OldOptionType, and add the descriptor of NewOptionType. |
| 3219 extension->set_type_name(".protobuf_unittest.NewOptionType"); |
| 3220 DescriptorProto* new_option_type = file_proto.add_message_type(); |
| 3221 protobuf_unittest::NewOptionType::descriptor() |
| 3222 ->CopyTo(new_option_type); |
| 3223 |
| 3224 // Replace the value of the "required_enum_opt" option used in the |
| 3225 // test message with an enum value that only exists in NewOptionType. |
| 3226 ASSERT_TRUE(TextFormat::ParseFromString( |
| 3227 "uninterpreted_option { " |
| 3228 " name { " |
| 3229 " name_part: 'required_enum_opt' " |
| 3230 " is_extension: true " |
| 3231 " } " |
| 3232 " aggregate_value: 'value: NEW_VALUE' " |
| 3233 "}", |
| 3234 test_message_type->mutable_options())); |
| 3235 |
| 3236 // Add the file descriptor to the pool. |
| 3237 ASSERT_TRUE(pool.BuildFile(file_proto) != NULL); |
| 3238 |
| 3239 // Find the test message. |
| 3240 const Descriptor* test_message = pool.FindMessageTypeByName( |
| 3241 "protobuf_unittest.TestMessageWithRequiredEnumOption"); |
| 3242 ASSERT_TRUE(test_message != NULL); |
| 3243 |
| 3244 const MessageOptions& options = test_message->options(); |
| 3245 // Extract the "required_enum_opt" option. Since the binary does not |
| 3246 // know that the extension was updated, this will still return an |
| 3247 // OldOptionType message. |
| 3248 ASSERT_TRUE( |
| 3249 options.HasExtension(protobuf_unittest::required_enum_opt)); |
| 3250 const protobuf_unittest::OldOptionType& old_enum_opt = |
| 3251 options.GetExtension(protobuf_unittest::required_enum_opt); |
| 3252 |
| 3253 // Confirm that the required enum field is missing. |
| 3254 EXPECT_FALSE(old_enum_opt.IsInitialized()); |
| 3255 EXPECT_FALSE(old_enum_opt.has_value()); |
| 3256 |
| 3257 string buf; |
| 3258 // Verify that the required enum field does show up when the option |
| 3259 // is re-parsed as a NewOptionType message; |
| 3260 protobuf_unittest::NewOptionType new_enum_opt; |
| 3261 EXPECT_TRUE(old_enum_opt.AppendPartialToString(&buf)); |
| 3262 EXPECT_TRUE(new_enum_opt.ParseFromString(buf)); |
| 3263 EXPECT_EQ(protobuf_unittest::NewOptionType::NEW_VALUE, new_enum_opt.value()); |
| 3264 } |
| 3265 |
| 2432 // =================================================================== | 3266 // =================================================================== |
| 2433 | 3267 |
| 2434 // The tests below trigger every unique call to AddError() in descriptor.cc, | |
| 2435 // in the order in which they appear in that file. I'm using TextFormat here | |
| 2436 // to specify the input descriptors because building them using code would | |
| 2437 // be too bulky. | |
| 2438 | |
| 2439 class MockErrorCollector : public DescriptorPool::ErrorCollector { | |
| 2440 public: | |
| 2441 MockErrorCollector() {} | |
| 2442 ~MockErrorCollector() {} | |
| 2443 | |
| 2444 string text_; | |
| 2445 | |
| 2446 // implements ErrorCollector --------------------------------------- | |
| 2447 void AddError(const string& filename, | |
| 2448 const string& element_name, const Message* descriptor, | |
| 2449 ErrorLocation location, const string& message) { | |
| 2450 const char* location_name = NULL; | |
| 2451 switch (location) { | |
| 2452 case NAME : location_name = "NAME" ; break; | |
| 2453 case NUMBER : location_name = "NUMBER" ; break; | |
| 2454 case TYPE : location_name = "TYPE" ; break; | |
| 2455 case EXTENDEE : location_name = "EXTENDEE" ; break; | |
| 2456 case DEFAULT_VALUE: location_name = "DEFAULT_VALUE"; break; | |
| 2457 case OPTION_NAME : location_name = "OPTION_NAME" ; break; | |
| 2458 case OPTION_VALUE : location_name = "OPTION_VALUE" ; break; | |
| 2459 case INPUT_TYPE : location_name = "INPUT_TYPE" ; break; | |
| 2460 case OUTPUT_TYPE : location_name = "OUTPUT_TYPE" ; break; | |
| 2461 case OTHER : location_name = "OTHER" ; break; | |
| 2462 } | |
| 2463 | |
| 2464 strings::SubstituteAndAppend( | |
| 2465 &text_, "$0: $1: $2: $3\n", | |
| 2466 filename, element_name, location_name, message); | |
| 2467 } | |
| 2468 }; | |
| 2469 | |
| 2470 class ValidationErrorTest : public testing::Test { | 3268 class ValidationErrorTest : public testing::Test { |
| 2471 protected: | 3269 protected: |
| 2472 // Parse file_text as a FileDescriptorProto in text format and add it | 3270 // Parse file_text as a FileDescriptorProto in text format and add it |
| 2473 // to the DescriptorPool. Expect no errors. | 3271 // to the DescriptorPool. Expect no errors. |
| 2474 void BuildFile(const string& file_text) { | 3272 const FileDescriptor* BuildFile(const string& file_text) { |
| 2475 FileDescriptorProto file_proto; | 3273 FileDescriptorProto file_proto; |
| 2476 ASSERT_TRUE(TextFormat::ParseFromString(file_text, &file_proto)); | 3274 EXPECT_TRUE(TextFormat::ParseFromString(file_text, &file_proto)); |
| 2477 ASSERT_TRUE(pool_.BuildFile(file_proto) != NULL); | 3275 return GOOGLE_CHECK_NOTNULL(pool_.BuildFile(file_proto)); |
| 2478 } | 3276 } |
| 2479 | 3277 |
| 2480 // Parse file_text as a FileDescriptorProto in text format and add it | 3278 // Parse file_text as a FileDescriptorProto in text format and add it |
| 2481 // to the DescriptorPool. Expect errors to be produced which match the | 3279 // to the DescriptorPool. Expect errors to be produced which match the |
| 2482 // given error text. | 3280 // given error text. |
| 2483 void BuildFileWithErrors(const string& file_text, | 3281 void BuildFileWithErrors(const string& file_text, |
| 2484 const string& expected_errors) { | 3282 const string& expected_errors) { |
| 2485 FileDescriptorProto file_proto; | 3283 FileDescriptorProto file_proto; |
| 2486 ASSERT_TRUE(TextFormat::ParseFromString(file_text, &file_proto)); | 3284 ASSERT_TRUE(TextFormat::ParseFromString(file_text, &file_proto)); |
| 2487 | 3285 |
| 2488 MockErrorCollector error_collector; | 3286 MockErrorCollector error_collector; |
| 2489 EXPECT_TRUE( | 3287 EXPECT_TRUE( |
| 2490 pool_.BuildFileCollectingErrors(file_proto, &error_collector) == NULL); | 3288 pool_.BuildFileCollectingErrors(file_proto, &error_collector) == NULL); |
| 2491 EXPECT_EQ(expected_errors, error_collector.text_); | 3289 EXPECT_EQ(expected_errors, error_collector.text_); |
| 2492 } | 3290 } |
| 2493 | 3291 |
| 3292 // Parse file_text as a FileDescriptorProto in text format and add it |
| 3293 // to the DescriptorPool. Expect errors to be produced which match the |
| 3294 // given warning text. |
| 3295 void BuildFileWithWarnings(const string& file_text, |
| 3296 const string& expected_warnings) { |
| 3297 FileDescriptorProto file_proto; |
| 3298 ASSERT_TRUE(TextFormat::ParseFromString(file_text, &file_proto)); |
| 3299 |
| 3300 MockErrorCollector error_collector; |
| 3301 EXPECT_TRUE(pool_.BuildFileCollectingErrors(file_proto, &error_collector)); |
| 3302 EXPECT_EQ(expected_warnings, error_collector.warning_text_); |
| 3303 } |
| 3304 |
| 2494 // Builds some already-parsed file in our test pool. | 3305 // Builds some already-parsed file in our test pool. |
| 2495 void BuildFileInTestPool(const FileDescriptor* file) { | 3306 void BuildFileInTestPool(const FileDescriptor* file) { |
| 2496 FileDescriptorProto file_proto; | 3307 FileDescriptorProto file_proto; |
| 2497 file->CopyTo(&file_proto); | 3308 file->CopyTo(&file_proto); |
| 2498 ASSERT_TRUE(pool_.BuildFile(file_proto) != NULL); | 3309 ASSERT_TRUE(pool_.BuildFile(file_proto) != NULL); |
| 2499 } | 3310 } |
| 2500 | 3311 |
| 2501 // Build descriptor.proto in our test pool. This allows us to extend it in | 3312 // Build descriptor.proto in our test pool. This allows us to extend it in |
| 2502 // the test pool, so we can test custom options. | 3313 // the test pool, so we can test custom options. |
| 2503 void BuildDescriptorMessagesInTestPool() { | 3314 void BuildDescriptorMessagesInTestPool() { |
| (...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2705 " extension_range { start: 20 end: 30 }" | 3516 " extension_range { start: 20 end: 30 }" |
| 2706 " extension_range { start: 19 end: 21 }" | 3517 " extension_range { start: 19 end: 21 }" |
| 2707 "}", | 3518 "}", |
| 2708 | 3519 |
| 2709 "foo.proto: Foo: NUMBER: Extension range 19 to 20 overlaps with " | 3520 "foo.proto: Foo: NUMBER: Extension range 19 to 20 overlaps with " |
| 2710 "already-defined range 10 to 19.\n" | 3521 "already-defined range 10 to 19.\n" |
| 2711 "foo.proto: Foo: NUMBER: Extension range 19 to 20 overlaps with " | 3522 "foo.proto: Foo: NUMBER: Extension range 19 to 20 overlaps with " |
| 2712 "already-defined range 20 to 29.\n"); | 3523 "already-defined range 20 to 29.\n"); |
| 2713 } | 3524 } |
| 2714 | 3525 |
| 3526 TEST_F(ValidationErrorTest, ReservedFieldError) { |
| 3527 BuildFileWithErrors( |
| 3528 "name: \"foo.proto\" " |
| 3529 "message_type {" |
| 3530 " name: \"Foo\"" |
| 3531 " field { name: \"foo\" number: 15 label:LABEL_OPTIONAL type:TYPE_INT32 }" |
| 3532 " reserved_range { start: 10 end: 20 }" |
| 3533 "}", |
| 3534 |
| 3535 "foo.proto: Foo.foo: NUMBER: Field \"foo\" uses reserved number 15.\n"); |
| 3536 } |
| 3537 |
| 3538 TEST_F(ValidationErrorTest, ReservedExtensionRangeError) { |
| 3539 BuildFileWithErrors( |
| 3540 "name: \"foo.proto\" " |
| 3541 "message_type {" |
| 3542 " name: \"Foo\"" |
| 3543 " extension_range { start: 10 end: 20 }" |
| 3544 " reserved_range { start: 5 end: 15 }" |
| 3545 "}", |
| 3546 |
| 3547 "foo.proto: Foo: NUMBER: Extension range 10 to 19" |
| 3548 " overlaps with reserved range 5 to 14.\n"); |
| 3549 } |
| 3550 |
| 3551 TEST_F(ValidationErrorTest, ReservedExtensionRangeAdjacent) { |
| 3552 BuildFile( |
| 3553 "name: \"foo.proto\" " |
| 3554 "message_type {" |
| 3555 " name: \"Foo\"" |
| 3556 " extension_range { start: 10 end: 20 }" |
| 3557 " reserved_range { start: 5 end: 10 }" |
| 3558 "}"); |
| 3559 } |
| 3560 |
| 3561 TEST_F(ValidationErrorTest, ReservedRangeOverlap) { |
| 3562 BuildFileWithErrors( |
| 3563 "name: \"foo.proto\" " |
| 3564 "message_type {" |
| 3565 " name: \"Foo\"" |
| 3566 " reserved_range { start: 10 end: 20 }" |
| 3567 " reserved_range { start: 5 end: 15 }" |
| 3568 "}", |
| 3569 |
| 3570 "foo.proto: Foo: NUMBER: Reserved range 5 to 14" |
| 3571 " overlaps with already-defined range 10 to 19.\n"); |
| 3572 } |
| 3573 |
| 3574 TEST_F(ValidationErrorTest, ReservedNameError) { |
| 3575 BuildFileWithErrors( |
| 3576 "name: \"foo.proto\" " |
| 3577 "message_type {" |
| 3578 " name: \"Foo\"" |
| 3579 " field { name: \"foo\" number: 15 label:LABEL_OPTIONAL type:TYPE_INT32 }" |
| 3580 " field { name: \"bar\" number: 16 label:LABEL_OPTIONAL type:TYPE_INT32 }" |
| 3581 " field { name: \"baz\" number: 17 label:LABEL_OPTIONAL type:TYPE_INT32 }" |
| 3582 " reserved_name: \"foo\"" |
| 3583 " reserved_name: \"bar\"" |
| 3584 "}", |
| 3585 |
| 3586 "foo.proto: Foo.foo: NAME: Field name \"foo\" is reserved.\n" |
| 3587 "foo.proto: Foo.bar: NAME: Field name \"bar\" is reserved.\n"); |
| 3588 } |
| 3589 |
| 3590 TEST_F(ValidationErrorTest, ReservedNameRedundant) { |
| 3591 BuildFileWithErrors( |
| 3592 "name: \"foo.proto\" " |
| 3593 "message_type {" |
| 3594 " name: \"Foo\"" |
| 3595 " reserved_name: \"foo\"" |
| 3596 " reserved_name: \"foo\"" |
| 3597 "}", |
| 3598 |
| 3599 "foo.proto: foo: NAME: Field name \"foo\" is reserved multiple times.\n"); |
| 3600 } |
| 3601 |
| 3602 TEST_F(ValidationErrorTest, ReservedFieldsDebugString) { |
| 3603 const FileDescriptor* file = BuildFile( |
| 3604 "name: \"foo.proto\" " |
| 3605 "message_type {" |
| 3606 " name: \"Foo\"" |
| 3607 " reserved_name: \"foo\"" |
| 3608 " reserved_name: \"bar\"" |
| 3609 " reserved_range { start: 5 end: 6 }" |
| 3610 " reserved_range { start: 10 end: 20 }" |
| 3611 "}"); |
| 3612 |
| 3613 ASSERT_EQ( |
| 3614 "syntax = \"proto2\";\n\n" |
| 3615 "message Foo {\n" |
| 3616 " reserved 5, 10 to 19;\n" |
| 3617 " reserved \"foo\", \"bar\";\n" |
| 3618 "}\n\n", |
| 3619 file->DebugString()); |
| 3620 } |
| 3621 |
| 2715 TEST_F(ValidationErrorTest, InvalidDefaults) { | 3622 TEST_F(ValidationErrorTest, InvalidDefaults) { |
| 2716 BuildFileWithErrors( | 3623 BuildFileWithErrors( |
| 2717 "name: \"foo.proto\" " | 3624 "name: \"foo.proto\" " |
| 2718 "message_type {" | 3625 "message_type {" |
| 2719 " name: \"Foo\"" | 3626 " name: \"Foo\"" |
| 2720 | 3627 |
| 2721 // Invalid number. | 3628 // Invalid number. |
| 2722 " field { name: \"foo\" number: 1 label: LABEL_OPTIONAL type: TYPE_INT32" | 3629 " field { name: \"foo\" number: 1 label: LABEL_OPTIONAL type: TYPE_INT32" |
| 2723 " default_value: \"abc\" }" | 3630 " default_value: \"abc\" }" |
| 2724 | 3631 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 2737 // Same thing, but we don't know that this field has message type until | 3644 // Same thing, but we don't know that this field has message type until |
| 2738 // we look up the type name. | 3645 // we look up the type name. |
| 2739 " field { name: \"quux\" number: 5 label: LABEL_OPTIONAL" | 3646 " field { name: \"quux\" number: 5 label: LABEL_OPTIONAL" |
| 2740 " default_value: \"abc\" type_name: \"Foo\" }" | 3647 " default_value: \"abc\" type_name: \"Foo\" }" |
| 2741 | 3648 |
| 2742 // Repeateds can't have defaults. | 3649 // Repeateds can't have defaults. |
| 2743 " field { name: \"corge\" number: 6 label: LABEL_REPEATED type: TYPE_INT32" | 3650 " field { name: \"corge\" number: 6 label: LABEL_REPEATED type: TYPE_INT32" |
| 2744 " default_value: \"1\" }" | 3651 " default_value: \"1\" }" |
| 2745 "}", | 3652 "}", |
| 2746 | 3653 |
| 2747 "foo.proto: Foo.foo: DEFAULT_VALUE: Couldn't parse default value.\n" | 3654 "foo.proto: Foo.foo: DEFAULT_VALUE: Couldn't parse default value \"abc\".\n" |
| 2748 "foo.proto: Foo.bar: DEFAULT_VALUE: Couldn't parse default value.\n" | 3655 "foo.proto: Foo.bar: DEFAULT_VALUE: Couldn't parse default value \"\".\n" |
| 2749 "foo.proto: Foo.baz: DEFAULT_VALUE: Boolean default must be true or " | 3656 "foo.proto: Foo.baz: DEFAULT_VALUE: Boolean default must be true or " |
| 2750 "false.\n" | 3657 "false.\n" |
| 2751 "foo.proto: Foo.qux: DEFAULT_VALUE: Messages can't have default values.\n" | 3658 "foo.proto: Foo.qux: DEFAULT_VALUE: Messages can't have default values.\n" |
| 2752 "foo.proto: Foo.corge: DEFAULT_VALUE: Repeated fields can't have default " | 3659 "foo.proto: Foo.corge: DEFAULT_VALUE: Repeated fields can't have default " |
| 2753 "values.\n" | 3660 "values.\n" |
| 2754 // This ends up being reported later because the error is detected at | 3661 // This ends up being reported later because the error is detected at |
| 2755 // cross-linking time. | 3662 // cross-linking time. |
| 2756 "foo.proto: Foo.quux: DEFAULT_VALUE: Messages can't have default " | 3663 "foo.proto: Foo.quux: DEFAULT_VALUE: Messages can't have default " |
| 2757 "values.\n"); | 3664 "values.\n"); |
| 2758 } | 3665 } |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2821 "message_type {" | 3728 "message_type {" |
| 2822 " name: \"Foo\"" | 3729 " name: \"Foo\"" |
| 2823 " field { name: \"foo\" number: 1 label: LABEL_OPTIONAL" | 3730 " field { name: \"foo\" number: 1 label: LABEL_OPTIONAL" |
| 2824 " type_name: \"Foo\" extendee: \"Bar\" }" | 3731 " type_name: \"Foo\" extendee: \"Bar\" }" |
| 2825 "}", | 3732 "}", |
| 2826 | 3733 |
| 2827 "foo.proto: Foo.foo: EXTENDEE: FieldDescriptorProto.extendee set for " | 3734 "foo.proto: Foo.foo: EXTENDEE: FieldDescriptorProto.extendee set for " |
| 2828 "non-extension field.\n"); | 3735 "non-extension field.\n"); |
| 2829 } | 3736 } |
| 2830 | 3737 |
| 3738 TEST_F(ValidationErrorTest, FieldOneofIndexTooLarge) { |
| 3739 BuildFileWithErrors( |
| 3740 "name: \"foo.proto\" " |
| 3741 "message_type {" |
| 3742 " name: \"Foo\"" |
| 3743 " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32 " |
| 3744 " oneof_index: 1 }" |
| 3745 " field { name:\"dummy\" number:2 label:LABEL_OPTIONAL type:TYPE_INT32 " |
| 3746 " oneof_index: 0 }" |
| 3747 " oneof_decl { name:\"bar\" }" |
| 3748 "}", |
| 3749 |
| 3750 "foo.proto: Foo.foo: OTHER: FieldDescriptorProto.oneof_index 1 is out of " |
| 3751 "range for type \"Foo\".\n"); |
| 3752 } |
| 3753 |
| 3754 TEST_F(ValidationErrorTest, FieldOneofIndexNegative) { |
| 3755 BuildFileWithErrors( |
| 3756 "name: \"foo.proto\" " |
| 3757 "message_type {" |
| 3758 " name: \"Foo\"" |
| 3759 " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32 " |
| 3760 " oneof_index: -1 }" |
| 3761 " field { name:\"dummy\" number:2 label:LABEL_OPTIONAL type:TYPE_INT32 " |
| 3762 " oneof_index: 0 }" |
| 3763 " oneof_decl { name:\"bar\" }" |
| 3764 "}", |
| 3765 |
| 3766 "foo.proto: Foo.foo: OTHER: FieldDescriptorProto.oneof_index -1 is out of " |
| 3767 "range for type \"Foo\".\n"); |
| 3768 } |
| 3769 |
| 3770 TEST_F(ValidationErrorTest, OneofFieldsConsecutiveDefinition) { |
| 3771 // Fields belonging to the same oneof must be defined consecutively. |
| 3772 BuildFileWithErrors( |
| 3773 "name: \"foo.proto\" " |
| 3774 "message_type {" |
| 3775 " name: \"Foo\"" |
| 3776 " field { name:\"foo1\" number: 1 label:LABEL_OPTIONAL type:TYPE_INT32 " |
| 3777 " oneof_index: 0 }" |
| 3778 " field { name:\"bar\" number: 2 label:LABEL_OPTIONAL type:TYPE_INT32 }" |
| 3779 " field { name:\"foo2\" number: 3 label:LABEL_OPTIONAL type:TYPE_INT32 " |
| 3780 " oneof_index: 0 }" |
| 3781 " oneof_decl { name:\"foos\" }" |
| 3782 "}", |
| 3783 |
| 3784 "foo.proto: Foo.bar: OTHER: Fields in the same oneof must be defined " |
| 3785 "consecutively. \"bar\" cannot be defined before the completion of the " |
| 3786 "\"foos\" oneof definition.\n"); |
| 3787 |
| 3788 // Prevent interleaved fields, which belong to different oneofs. |
| 3789 BuildFileWithErrors( |
| 3790 "name: \"foo2.proto\" " |
| 3791 "message_type {" |
| 3792 " name: \"Foo2\"" |
| 3793 " field { name:\"foo1\" number: 1 label:LABEL_OPTIONAL type:TYPE_INT32 " |
| 3794 " oneof_index: 0 }" |
| 3795 " field { name:\"bar1\" number: 2 label:LABEL_OPTIONAL type:TYPE_INT32 " |
| 3796 " oneof_index: 1 }" |
| 3797 " field { name:\"foo2\" number: 3 label:LABEL_OPTIONAL type:TYPE_INT32 " |
| 3798 " oneof_index: 0 }" |
| 3799 " field { name:\"bar2\" number: 4 label:LABEL_OPTIONAL type:TYPE_INT32 " |
| 3800 " oneof_index: 1 }" |
| 3801 " oneof_decl { name:\"foos\" }" |
| 3802 " oneof_decl { name:\"bars\" }" |
| 3803 "}", |
| 3804 "foo2.proto: Foo2.bar1: OTHER: Fields in the same oneof must be defined " |
| 3805 "consecutively. \"bar1\" cannot be defined before the completion of the " |
| 3806 "\"foos\" oneof definition.\n" |
| 3807 "foo2.proto: Foo2.foo2: OTHER: Fields in the same oneof must be defined " |
| 3808 "consecutively. \"foo2\" cannot be defined before the completion of the " |
| 3809 "\"bars\" oneof definition.\n"); |
| 3810 |
| 3811 // Another case for normal fields and different oneof fields interleave. |
| 3812 BuildFileWithErrors( |
| 3813 "name: \"foo3.proto\" " |
| 3814 "message_type {" |
| 3815 " name: \"Foo3\"" |
| 3816 " field { name:\"foo1\" number: 1 label:LABEL_OPTIONAL type:TYPE_INT32 " |
| 3817 " oneof_index: 0 }" |
| 3818 " field { name:\"bar1\" number: 2 label:LABEL_OPTIONAL type:TYPE_INT32 " |
| 3819 " oneof_index: 1 }" |
| 3820 " field { name:\"baz\" number: 3 label:LABEL_OPTIONAL type:TYPE_INT32 }" |
| 3821 " field { name:\"foo2\" number: 4 label:LABEL_OPTIONAL type:TYPE_INT32 " |
| 3822 " oneof_index: 0 }" |
| 3823 " oneof_decl { name:\"foos\" }" |
| 3824 " oneof_decl { name:\"bars\" }" |
| 3825 "}", |
| 3826 "foo3.proto: Foo3.baz: OTHER: Fields in the same oneof must be defined " |
| 3827 "consecutively. \"baz\" cannot be defined before the completion of the " |
| 3828 "\"foos\" oneof definition.\n"); |
| 3829 } |
| 3830 |
| 2831 TEST_F(ValidationErrorTest, FieldNumberConflict) { | 3831 TEST_F(ValidationErrorTest, FieldNumberConflict) { |
| 2832 BuildFileWithErrors( | 3832 BuildFileWithErrors( |
| 2833 "name: \"foo.proto\" " | 3833 "name: \"foo.proto\" " |
| 2834 "message_type {" | 3834 "message_type {" |
| 2835 " name: \"Foo\"" | 3835 " name: \"Foo\"" |
| 2836 " field { name: \"foo\" number: 1 label:LABEL_OPTIONAL type:TYPE_INT32 }" | 3836 " field { name: \"foo\" number: 1 label:LABEL_OPTIONAL type:TYPE_INT32 }" |
| 2837 " field { name: \"bar\" number: 1 label:LABEL_OPTIONAL type:TYPE_INT32 }" | 3837 " field { name: \"bar\" number: 1 label:LABEL_OPTIONAL type:TYPE_INT32 }" |
| 2838 "}", | 3838 "}", |
| 2839 | 3839 |
| 2840 "foo.proto: Foo.bar: NUMBER: Field number 1 has already been used in " | 3840 "foo.proto: Foo.bar: NUMBER: Field number 1 has already been used in " |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2981 "message_type {" | 3981 "message_type {" |
| 2982 " name: \"Foo\"" | 3982 " name: \"Foo\"" |
| 2983 " extension { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32" | 3983 " extension { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32" |
| 2984 " extendee: \"Bar\" }" | 3984 " extendee: \"Bar\" }" |
| 2985 "}", | 3985 "}", |
| 2986 | 3986 |
| 2987 "foo.proto: Foo.foo: NUMBER: \"Bar\" does not declare 1 as an extension " | 3987 "foo.proto: Foo.foo: NUMBER: \"Bar\" does not declare 1 as an extension " |
| 2988 "number.\n"); | 3988 "number.\n"); |
| 2989 } | 3989 } |
| 2990 | 3990 |
| 3991 TEST_F(ValidationErrorTest, RequiredExtension) { |
| 3992 BuildFileWithErrors( |
| 3993 "name: \"foo.proto\" " |
| 3994 "message_type {" |
| 3995 " name: \"Bar\"" |
| 3996 " extension_range { start: 1000 end: 10000 }" |
| 3997 "}" |
| 3998 "message_type {" |
| 3999 " name: \"Foo\"" |
| 4000 " extension {" |
| 4001 " name:\"foo\"" |
| 4002 " number:1000" |
| 4003 " label:LABEL_REQUIRED" |
| 4004 " type:TYPE_INT32" |
| 4005 " extendee: \"Bar\"" |
| 4006 " }" |
| 4007 "}", |
| 4008 |
| 4009 "foo.proto: Foo.foo: TYPE: Message extensions cannot have required " |
| 4010 "fields.\n"); |
| 4011 } |
| 4012 |
| 2991 TEST_F(ValidationErrorTest, UndefinedFieldType) { | 4013 TEST_F(ValidationErrorTest, UndefinedFieldType) { |
| 2992 BuildFileWithErrors( | 4014 BuildFileWithErrors( |
| 2993 "name: \"foo.proto\" " | 4015 "name: \"foo.proto\" " |
| 2994 "message_type {" | 4016 "message_type {" |
| 2995 " name: \"Foo\"" | 4017 " name: \"Foo\"" |
| 2996 " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }" | 4018 " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }" |
| 2997 "}", | 4019 "}", |
| 2998 | 4020 |
| 2999 "foo.proto: Foo.foo: TYPE: \"Bar\" is not defined.\n"); | 4021 "foo.proto: Foo.foo: TYPE: \"Bar\" is not defined.\n"); |
| 3000 } | 4022 } |
| 3001 | 4023 |
| 4024 TEST_F(ValidationErrorTest, UndefinedFieldTypeWithDefault) { |
| 4025 // See b/12533582. Previously this failed because the default value was not |
| 4026 // accepted by the parser, which assumed an enum type, leading to an unclear |
| 4027 // error message. We want this input to yield a validation error instead, |
| 4028 // since the unknown type is the primary problem. |
| 4029 BuildFileWithErrors( |
| 4030 "name: \"foo.proto\" " |
| 4031 "message_type {" |
| 4032 " name: \"Foo\"" |
| 4033 " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"int\" " |
| 4034 " default_value:\"1\" }" |
| 4035 "}", |
| 4036 |
| 4037 "foo.proto: Foo.foo: TYPE: \"int\" is not defined.\n"); |
| 4038 } |
| 4039 |
| 4040 TEST_F(ValidationErrorTest, UndefinedNestedFieldType) { |
| 4041 BuildFileWithErrors( |
| 4042 "name: \"foo.proto\" " |
| 4043 "message_type {" |
| 4044 " name: \"Foo\"" |
| 4045 " nested_type { name:\"Baz\" }" |
| 4046 " field { name:\"foo\" number:1" |
| 4047 " label:LABEL_OPTIONAL" |
| 4048 " type_name:\"Foo.Baz.Bar\" }" |
| 4049 "}", |
| 4050 |
| 4051 "foo.proto: Foo.foo: TYPE: \"Foo.Baz.Bar\" is not defined.\n"); |
| 4052 } |
| 4053 |
| 3002 TEST_F(ValidationErrorTest, FieldTypeDefinedInUndeclaredDependency) { | 4054 TEST_F(ValidationErrorTest, FieldTypeDefinedInUndeclaredDependency) { |
| 3003 BuildFile( | 4055 BuildFile( |
| 3004 "name: \"bar.proto\" " | 4056 "name: \"bar.proto\" " |
| 3005 "message_type { name: \"Bar\" } "); | 4057 "message_type { name: \"Bar\" } "); |
| 3006 | 4058 |
| 3007 BuildFileWithErrors( | 4059 BuildFileWithErrors( |
| 3008 "name: \"foo.proto\" " | 4060 "name: \"foo.proto\" " |
| 3009 "message_type {" | 4061 "message_type {" |
| 3010 " name: \"Foo\"" | 4062 " name: \"Foo\"" |
| 3011 " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }" | 4063 " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }" |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3167 " name: \"Foo\"" | 4219 " name: \"Foo\"" |
| 3168 " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }" | 4220 " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }" |
| 3169 "}", | 4221 "}", |
| 3170 "foo.proto: Foo.foo: TYPE: \"Bar\" seems to be defined in \"bar.proto\", " | 4222 "foo.proto: Foo.foo: TYPE: \"Bar\" seems to be defined in \"bar.proto\", " |
| 3171 "which is not imported by \"foo.proto\". To use it here, please add the " | 4223 "which is not imported by \"foo.proto\". To use it here, please add the " |
| 3172 "necessary import.\n"); | 4224 "necessary import.\n"); |
| 3173 } | 4225 } |
| 3174 | 4226 |
| 3175 | 4227 |
| 3176 TEST_F(ValidationErrorTest, SearchMostLocalFirst) { | 4228 TEST_F(ValidationErrorTest, SearchMostLocalFirst) { |
| 3177 // The following should produce an error that Bar.Baz is not defined: | 4229 // The following should produce an error that Bar.Baz is resolved but |
| 4230 // not defined: |
| 3178 // message Bar { message Baz {} } | 4231 // message Bar { message Baz {} } |
| 3179 // message Foo { | 4232 // message Foo { |
| 3180 // message Bar { | 4233 // message Bar { |
| 3181 // // Placing "message Baz{}" here, or removing Foo.Bar altogether, | 4234 // // Placing "message Baz{}" here, or removing Foo.Bar altogether, |
| 3182 // // would fix the error. | 4235 // // would fix the error. |
| 3183 // } | 4236 // } |
| 3184 // optional Bar.Baz baz = 1; | 4237 // optional Bar.Baz baz = 1; |
| 3185 // } | 4238 // } |
| 3186 // An one point the lookup code incorrectly did not produce an error in this | 4239 // An one point the lookup code incorrectly did not produce an error in this |
| 3187 // case, because when looking for Bar.Baz, it would try "Foo.Bar.Baz" first, | 4240 // case, because when looking for Bar.Baz, it would try "Foo.Bar.Baz" first, |
| 3188 // fail, and ten try "Bar.Baz" and succeed, even though "Bar" should actually | 4241 // fail, and ten try "Bar.Baz" and succeed, even though "Bar" should actually |
| 3189 // refer to the inner Bar, not the outer one. | 4242 // refer to the inner Bar, not the outer one. |
| 3190 BuildFileWithErrors( | 4243 BuildFileWithErrors( |
| 3191 "name: \"foo.proto\" " | 4244 "name: \"foo.proto\" " |
| 3192 "message_type {" | 4245 "message_type {" |
| 3193 " name: \"Bar\"" | 4246 " name: \"Bar\"" |
| 3194 " nested_type { name: \"Baz\" }" | 4247 " nested_type { name: \"Baz\" }" |
| 3195 "}" | 4248 "}" |
| 3196 "message_type {" | 4249 "message_type {" |
| 3197 " name: \"Foo\"" | 4250 " name: \"Foo\"" |
| 3198 " nested_type { name: \"Bar\" }" | 4251 " nested_type { name: \"Bar\" }" |
| 3199 " field { name:\"baz\" number:1 label:LABEL_OPTIONAL" | 4252 " field { name:\"baz\" number:1 label:LABEL_OPTIONAL" |
| 3200 " type_name:\"Bar.Baz\" }" | 4253 " type_name:\"Bar.Baz\" }" |
| 3201 "}", | 4254 "}", |
| 3202 | 4255 |
| 3203 "foo.proto: Foo.baz: TYPE: \"Bar.Baz\" is not defined.\n"); | 4256 "foo.proto: Foo.baz: TYPE: \"Bar.Baz\" is resolved to \"Foo.Bar.Baz\"," |
| 4257 " which is not defined. The innermost scope is searched first in name " |
| 4258 "resolution. Consider using a leading '.'(i.e., \".Bar.Baz\") to start " |
| 4259 "from the outermost scope.\n"); |
| 3204 } | 4260 } |
| 3205 | 4261 |
| 3206 TEST_F(ValidationErrorTest, SearchMostLocalFirst2) { | 4262 TEST_F(ValidationErrorTest, SearchMostLocalFirst2) { |
| 3207 // This test would find the most local "Bar" first, and does, but | 4263 // This test would find the most local "Bar" first, and does, but |
| 3208 // proceeds to find the outer one because the inner one's not an | 4264 // proceeds to find the outer one because the inner one's not an |
| 3209 // aggregate. | 4265 // aggregate. |
| 3210 BuildFile( | 4266 BuildFile( |
| 3211 "name: \"foo.proto\" " | 4267 "name: \"foo.proto\" " |
| 3212 "message_type {" | 4268 "message_type {" |
| 3213 " name: \"Bar\"" | 4269 " name: \"Bar\"" |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3335 "message_type {" | 4391 "message_type {" |
| 3336 " name: \"Foo\"" | 4392 " name: \"Foo\"" |
| 3337 " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\"" | 4393 " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\"" |
| 3338 " default_value:\"NO_SUCH_VALUE\" }" | 4394 " default_value:\"NO_SUCH_VALUE\" }" |
| 3339 "}", | 4395 "}", |
| 3340 | 4396 |
| 3341 "foo.proto: Foo.foo: DEFAULT_VALUE: Enum type \"Bar\" has no value named " | 4397 "foo.proto: Foo.foo: DEFAULT_VALUE: Enum type \"Bar\" has no value named " |
| 3342 "\"NO_SUCH_VALUE\".\n"); | 4398 "\"NO_SUCH_VALUE\".\n"); |
| 3343 } | 4399 } |
| 3344 | 4400 |
| 4401 TEST_F(ValidationErrorTest, EnumDefaultValueIsInteger) { |
| 4402 BuildFileWithErrors( |
| 4403 "name: \"foo.proto\" " |
| 4404 "enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } } " |
| 4405 "message_type {" |
| 4406 " name: \"Foo\"" |
| 4407 " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\"" |
| 4408 " default_value:\"0\" }" |
| 4409 "}", |
| 4410 |
| 4411 "foo.proto: Foo.foo: DEFAULT_VALUE: Default value for an enum field must " |
| 4412 "be an identifier.\n"); |
| 4413 } |
| 4414 |
| 3345 TEST_F(ValidationErrorTest, PrimitiveWithTypeName) { | 4415 TEST_F(ValidationErrorTest, PrimitiveWithTypeName) { |
| 3346 BuildFileWithErrors( | 4416 BuildFileWithErrors( |
| 3347 "name: \"foo.proto\" " | 4417 "name: \"foo.proto\" " |
| 3348 "message_type {" | 4418 "message_type {" |
| 3349 " name: \"Foo\"" | 4419 " name: \"Foo\"" |
| 3350 " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32" | 4420 " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32" |
| 3351 " type_name:\"Foo\" }" | 4421 " type_name:\"Foo\" }" |
| 3352 "}", | 4422 "}", |
| 3353 | 4423 |
| 3354 "foo.proto: Foo.foo: TYPE: Field with primitive type has type_name.\n"); | 4424 "foo.proto: Foo.foo: TYPE: Field with primitive type has type_name.\n"); |
| 3355 } | 4425 } |
| 3356 | 4426 |
| 3357 TEST_F(ValidationErrorTest, NonPrimitiveWithoutTypeName) { | 4427 TEST_F(ValidationErrorTest, NonPrimitiveWithoutTypeName) { |
| 3358 BuildFileWithErrors( | 4428 BuildFileWithErrors( |
| 3359 "name: \"foo.proto\" " | 4429 "name: \"foo.proto\" " |
| 3360 "message_type {" | 4430 "message_type {" |
| 3361 " name: \"Foo\"" | 4431 " name: \"Foo\"" |
| 3362 " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_MESSAGE }" | 4432 " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_MESSAGE }" |
| 3363 "}", | 4433 "}", |
| 3364 | 4434 |
| 3365 "foo.proto: Foo.foo: TYPE: Field with message or enum type missing " | 4435 "foo.proto: Foo.foo: TYPE: Field with message or enum type missing " |
| 3366 "type_name.\n"); | 4436 "type_name.\n"); |
| 3367 } | 4437 } |
| 3368 | 4438 |
| 4439 TEST_F(ValidationErrorTest, OneofWithNoFields) { |
| 4440 BuildFileWithErrors( |
| 4441 "name: \"foo.proto\" " |
| 4442 "message_type {" |
| 4443 " name: \"Foo\"" |
| 4444 " oneof_decl { name:\"bar\" }" |
| 4445 "}", |
| 4446 |
| 4447 "foo.proto: Foo.bar: NAME: Oneof must have at least one field.\n"); |
| 4448 } |
| 4449 |
| 4450 TEST_F(ValidationErrorTest, OneofLabelMismatch) { |
| 4451 BuildFileWithErrors( |
| 4452 "name: \"foo.proto\" " |
| 4453 "message_type {" |
| 4454 " name: \"Foo\"" |
| 4455 " field { name:\"foo\" number:1 label:LABEL_REPEATED type:TYPE_INT32 " |
| 4456 " oneof_index:0 }" |
| 4457 " oneof_decl { name:\"bar\" }" |
| 4458 "}", |
| 4459 |
| 4460 "foo.proto: Foo.foo: NAME: Fields of oneofs must themselves have label " |
| 4461 "LABEL_OPTIONAL.\n"); |
| 4462 } |
| 4463 |
| 3369 TEST_F(ValidationErrorTest, InputTypeNotDefined) { | 4464 TEST_F(ValidationErrorTest, InputTypeNotDefined) { |
| 3370 BuildFileWithErrors( | 4465 BuildFileWithErrors( |
| 3371 "name: \"foo.proto\" " | 4466 "name: \"foo.proto\" " |
| 3372 "message_type { name: \"Foo\" } " | 4467 "message_type { name: \"Foo\" } " |
| 3373 "service {" | 4468 "service {" |
| 3374 " name: \"TestService\"" | 4469 " name: \"TestService\"" |
| 3375 " method { name: \"A\" input_type: \"Bar\" output_type: \"Foo\" }" | 4470 " method { name: \"A\" input_type: \"Bar\" output_type: \"Foo\" }" |
| 3376 "}", | 4471 "}", |
| 3377 | 4472 |
| 3378 "foo.proto: TestService.A: INPUT_TYPE: \"Bar\" is not defined.\n" | 4473 "foo.proto: TestService.A: INPUT_TYPE: \"Bar\" is not defined.\n" |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3520 " positive_int_value: 1 " | 4615 " positive_int_value: 1 " |
| 3521 " }" | 4616 " }" |
| 3522 " }" | 4617 " }" |
| 3523 " }" | 4618 " }" |
| 3524 "}\n", | 4619 "}\n", |
| 3525 | 4620 |
| 3526 "foo.proto: TestMessage.foo: OPTION_NAME: Option must not use " | 4621 "foo.proto: TestMessage.foo: OPTION_NAME: Option must not use " |
| 3527 "reserved name \"uninterpreted_option\".\n"); | 4622 "reserved name \"uninterpreted_option\".\n"); |
| 3528 } | 4623 } |
| 3529 | 4624 |
| 3530 TEST_F(ValidationErrorTest, RepeatedOption) { | 4625 TEST_F(ValidationErrorTest, RepeatedMessageOption) { |
| 3531 BuildDescriptorMessagesInTestPool(); | 4626 BuildDescriptorMessagesInTestPool(); |
| 3532 | 4627 |
| 3533 BuildFileWithErrors( | 4628 BuildFileWithErrors( |
| 3534 "name: \"foo.proto\" " | 4629 "name: \"foo.proto\" " |
| 3535 "dependency: \"google/protobuf/descriptor.proto\" " | 4630 "dependency: \"google/protobuf/descriptor.proto\" " |
| 3536 "extension { name: \"foo\" number: 7672757 label: LABEL_REPEATED " | 4631 "message_type: { name: \"Bar\" field: { " |
| 3537 " type: TYPE_FLOAT extendee: \"google.protobuf.FileOptions\" }" | 4632 " name: \"foo\" number: 1 label: LABEL_OPTIONAL type: TYPE_INT32 } " |
| 3538 "options { uninterpreted_option { name { name_part: \"foo\" " | 4633 "} " |
| 4634 "extension { name: \"bar\" number: 7672757 label: LABEL_REPEATED " |
| 4635 " type: TYPE_MESSAGE type_name: \"Bar\" " |
| 4636 " extendee: \"google.protobuf.FileOptions\" }" |
| 4637 "options { uninterpreted_option { name { name_part: \"bar\" " |
| 3539 " is_extension: true } " | 4638 " is_extension: true } " |
| 3540 " double_value: 1.2 } }", | 4639 " name { name_part: \"foo\" " |
| 4640 " is_extension: false } " |
| 4641 " positive_int_value: 1 } }", |
| 3541 | 4642 |
| 3542 "foo.proto: foo.proto: OPTION_NAME: Option field \"(foo)\" is repeated. " | 4643 "foo.proto: foo.proto: OPTION_NAME: Option field \"(bar)\" is a " |
| 3543 "Repeated options are not supported.\n"); | 4644 "repeated message. Repeated message options must be initialized " |
| 4645 "using an aggregate value.\n"); |
| 4646 } |
| 4647 |
| 4648 TEST_F(ValidationErrorTest, ResolveUndefinedOption) { |
| 4649 // The following should produce an eror that baz.bar is resolved but not |
| 4650 // defined. |
| 4651 // foo.proto: |
| 4652 // package baz |
| 4653 // import google/protobuf/descriptor.proto |
| 4654 // message Bar { optional int32 foo = 1; } |
| 4655 // extend FileOptions { optional Bar bar = 7672757; } |
| 4656 // |
| 4657 // qux.proto: |
| 4658 // package qux.baz |
| 4659 // option (baz.bar).foo = 1; |
| 4660 // |
| 4661 // Although "baz.bar" is already defined, the lookup code will try |
| 4662 // "qux.baz.bar", since it's the match from the innermost scope, which will |
| 4663 // cause a symbol not defined error. |
| 4664 BuildDescriptorMessagesInTestPool(); |
| 4665 |
| 4666 BuildFile( |
| 4667 "name: \"foo.proto\" " |
| 4668 "package: \"baz\" " |
| 4669 "dependency: \"google/protobuf/descriptor.proto\" " |
| 4670 "message_type: { name: \"Bar\" field: { " |
| 4671 " name: \"foo\" number: 1 label: LABEL_OPTIONAL type: TYPE_INT32 } " |
| 4672 "} " |
| 4673 "extension { name: \"bar\" number: 7672757 label: LABEL_OPTIONAL " |
| 4674 " type: TYPE_MESSAGE type_name: \"Bar\" " |
| 4675 " extendee: \"google.protobuf.FileOptions\" }"); |
| 4676 |
| 4677 BuildFileWithErrors( |
| 4678 "name: \"qux.proto\" " |
| 4679 "package: \"qux.baz\" " |
| 4680 "options { uninterpreted_option { name { name_part: \"baz.bar\" " |
| 4681 " is_extension: true } " |
| 4682 " name { name_part: \"foo\" " |
| 4683 " is_extension: false } " |
| 4684 " positive_int_value: 1 } }", |
| 4685 |
| 4686 "qux.proto: qux.proto: OPTION_NAME: Option \"(baz.bar)\" is resolved to " |
| 4687 "\"(qux.baz.bar)\"," |
| 4688 " which is not defined. The innermost scope is searched first in name " |
| 4689 "resolution. Consider using a leading '.'(i.e., \"(.baz.bar)\") to start " |
| 4690 "from the outermost scope.\n"); |
| 4691 } |
| 4692 |
| 4693 TEST_F(ValidationErrorTest, UnknownOption) { |
| 4694 BuildFileWithErrors( |
| 4695 "name: \"qux.proto\" " |
| 4696 "package: \"qux.baz\" " |
| 4697 "options { uninterpreted_option { name { name_part: \"baaz.bar\" " |
| 4698 " is_extension: true } " |
| 4699 " name { name_part: \"foo\" " |
| 4700 " is_extension: false } " |
| 4701 " positive_int_value: 1 } }", |
| 4702 |
| 4703 "qux.proto: qux.proto: OPTION_NAME: Option \"(baaz.bar)\" unknown.\n"); |
| 3544 } | 4704 } |
| 3545 | 4705 |
| 3546 TEST_F(ValidationErrorTest, CustomOptionConflictingFieldNumber) { | 4706 TEST_F(ValidationErrorTest, CustomOptionConflictingFieldNumber) { |
| 3547 BuildDescriptorMessagesInTestPool(); | 4707 BuildDescriptorMessagesInTestPool(); |
| 3548 | 4708 |
| 3549 BuildFileWithErrors( | 4709 BuildFileWithErrors( |
| 3550 "name: \"foo.proto\" " | 4710 "name: \"foo.proto\" " |
| 3551 "dependency: \"google/protobuf/descriptor.proto\" " | 4711 "dependency: \"google/protobuf/descriptor.proto\" " |
| 3552 "extension { name: \"foo1\" number: 7672757 label: LABEL_OPTIONAL " | 4712 "extension { name: \"foo1\" number: 7672757 label: LABEL_OPTIONAL " |
| 3553 " type: TYPE_INT32 extendee: \"google.protobuf.FieldOptions\" }" | 4713 " type: TYPE_INT32 extendee: \"google.protobuf.FieldOptions\" }" |
| (...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3806 "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL " | 4966 "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL " |
| 3807 " type: TYPE_STRING extendee: \"google.protobuf.FileOptions\" }" | 4967 " type: TYPE_STRING extendee: \"google.protobuf.FileOptions\" }" |
| 3808 "options { uninterpreted_option { name { name_part: \"foo\" " | 4968 "options { uninterpreted_option { name { name_part: \"foo\" " |
| 3809 " is_extension: true } " | 4969 " is_extension: true } " |
| 3810 " identifier_value: \"QUUX\" } }", | 4970 " identifier_value: \"QUUX\" } }", |
| 3811 | 4971 |
| 3812 "foo.proto: foo.proto: OPTION_VALUE: Value must be quoted string for " | 4972 "foo.proto: foo.proto: OPTION_VALUE: Value must be quoted string for " |
| 3813 "string option \"foo\".\n"); | 4973 "string option \"foo\".\n"); |
| 3814 } | 4974 } |
| 3815 | 4975 |
| 4976 TEST_F(ValidationErrorTest, DuplicateExtensionFieldNumber) { |
| 4977 BuildDescriptorMessagesInTestPool(); |
| 4978 |
| 4979 BuildFile( |
| 4980 "name: \"foo.proto\" " |
| 4981 "dependency: \"google/protobuf/descriptor.proto\" " |
| 4982 "extension { name: \"option1\" number: 1000 label: LABEL_OPTIONAL " |
| 4983 " type: TYPE_INT32 extendee: \"google.protobuf.FileOptions\" }"
); |
| 4984 |
| 4985 BuildFileWithWarnings( |
| 4986 "name: \"bar.proto\" " |
| 4987 "dependency: \"google/protobuf/descriptor.proto\" " |
| 4988 "extension { name: \"option2\" number: 1000 label: LABEL_OPTIONAL " |
| 4989 " type: TYPE_INT32 extendee: \"google.protobuf.FileOptions\" }"
, |
| 4990 "bar.proto: option2: NUMBER: Extension number 1000 has already been used " |
| 4991 "in \"google.protobuf.FileOptions\" by extension \"option1\" defined in " |
| 4992 "foo.proto.\n"); |
| 4993 } |
| 4994 |
| 3816 // Helper function for tests that check for aggregate value parsing | 4995 // Helper function for tests that check for aggregate value parsing |
| 3817 // errors. The "value" argument is embedded inside the | 4996 // errors. The "value" argument is embedded inside the |
| 3818 // "uninterpreted_option" portion of the result. | 4997 // "uninterpreted_option" portion of the result. |
| 3819 static string EmbedAggregateValue(const char* value) { | 4998 static string EmbedAggregateValue(const char* value) { |
| 3820 return strings::Substitute( | 4999 return strings::Substitute( |
| 3821 "name: \"foo.proto\" " | 5000 "name: \"foo.proto\" " |
| 3822 "dependency: \"google/protobuf/descriptor.proto\" " | 5001 "dependency: \"google/protobuf/descriptor.proto\" " |
| 3823 "message_type { name: \"Foo\" } " | 5002 "message_type { name: \"Foo\" } " |
| 3824 "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL " | 5003 "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL " |
| 3825 " type: TYPE_MESSAGE type_name: \"Foo\" " | 5004 " type: TYPE_MESSAGE type_name: \"Foo\" " |
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3991 EXPECT_EQ(" Foo: \"Foo\" is already defined.", errors[1]); | 5170 EXPECT_EQ(" Foo: \"Foo\" is already defined.", errors[1]); |
| 3992 } | 5171 } |
| 3993 | 5172 |
| 3994 TEST_F(ValidationErrorTest, DisallowEnumAlias) { | 5173 TEST_F(ValidationErrorTest, DisallowEnumAlias) { |
| 3995 BuildFileWithErrors( | 5174 BuildFileWithErrors( |
| 3996 "name: \"foo.proto\" " | 5175 "name: \"foo.proto\" " |
| 3997 "enum_type {" | 5176 "enum_type {" |
| 3998 " name: \"Bar\"" | 5177 " name: \"Bar\"" |
| 3999 " value { name:\"ENUM_A\" number:0 }" | 5178 " value { name:\"ENUM_A\" number:0 }" |
| 4000 " value { name:\"ENUM_B\" number:0 }" | 5179 " value { name:\"ENUM_B\" number:0 }" |
| 4001 " options { allow_alias: false }" | |
| 4002 "}", | 5180 "}", |
| 4003 "foo.proto: Bar: NUMBER: " | 5181 "foo.proto: Bar: NUMBER: " |
| 4004 "\"ENUM_B\" uses the same enum value as \"ENUM_A\". " | 5182 "\"ENUM_B\" uses the same enum value as \"ENUM_A\". " |
| 4005 "If this is intended, set 'option allow_alias = true;' to the enum " | 5183 "If this is intended, set 'option allow_alias = true;' to the enum " |
| 4006 "definition.\n"); | 5184 "definition.\n"); |
| 4007 } | 5185 } |
| 4008 | 5186 |
| 5187 TEST_F(ValidationErrorTest, AllowEnumAlias) { |
| 5188 BuildFile( |
| 5189 "name: \"foo.proto\" " |
| 5190 "enum_type {" |
| 5191 " name: \"Bar\"" |
| 5192 " value { name:\"ENUM_A\" number:0 }" |
| 5193 " value { name:\"ENUM_B\" number:0 }" |
| 5194 " options { allow_alias: true }" |
| 5195 "}"); |
| 5196 } |
| 5197 |
| 5198 TEST_F(ValidationErrorTest, UnusedImportWarning) { |
| 5199 pool_.AddUnusedImportTrackFile("bar.proto"); |
| 5200 BuildFile( |
| 5201 "name: \"bar.proto\" " |
| 5202 "message_type { name: \"Bar\" }"); |
| 5203 |
| 5204 pool_.AddUnusedImportTrackFile("base.proto"); |
| 5205 BuildFile( |
| 5206 "name: \"base.proto\" " |
| 5207 "message_type { name: \"Base\" }"); |
| 5208 |
| 5209 pool_.AddUnusedImportTrackFile("baz.proto"); |
| 5210 BuildFile( |
| 5211 "name: \"baz.proto\" " |
| 5212 "message_type { name: \"Baz\" }"); |
| 5213 |
| 5214 pool_.AddUnusedImportTrackFile("public.proto"); |
| 5215 BuildFile( |
| 5216 "name: \"public.proto\" " |
| 5217 "dependency: \"bar.proto\"" |
| 5218 "public_dependency: 0"); |
| 5219 |
| 5220 // // forward.proto |
| 5221 // import "base.proto" // No warning: Base message is used. |
| 5222 // import "bar.proto" // Will log a warning. |
| 5223 // import public "baz.proto" // No warning: Do not track import public. |
| 5224 // import "public.proto" // No warning: public.proto has import public. |
| 5225 // message Forward { |
| 5226 // optional Base base = 1; |
| 5227 // } |
| 5228 // |
| 5229 pool_.AddUnusedImportTrackFile("forward.proto"); |
| 5230 BuildFileWithWarnings( |
| 5231 "name: \"forward.proto\"" |
| 5232 "dependency: \"base.proto\"" |
| 5233 "dependency: \"bar.proto\"" |
| 5234 "dependency: \"baz.proto\"" |
| 5235 "dependency: \"public.proto\"" |
| 5236 "public_dependency: 2 " |
| 5237 "message_type {" |
| 5238 " name: \"Forward\"" |
| 5239 " field { name:\"base\" number:1 label:LABEL_OPTIONAL type_name:\"Base\" }" |
| 5240 "}", |
| 5241 "forward.proto: bar.proto: OTHER: Import bar.proto but not used.\n"); |
| 5242 } |
| 5243 |
| 5244 namespace { |
| 5245 void FillValidMapEntry(FileDescriptorProto* file_proto) { |
| 5246 ASSERT_TRUE(TextFormat::ParseFromString( |
| 5247 "name: 'foo.proto' " |
| 5248 "message_type { " |
| 5249 " name: 'Foo' " |
| 5250 " field { " |
| 5251 " name: 'foo_map' number: 1 label:LABEL_REPEATED " |
| 5252 " type_name: 'FooMapEntry' " |
| 5253 " } " |
| 5254 " nested_type { " |
| 5255 " name: 'FooMapEntry' " |
| 5256 " options { map_entry: true } " |
| 5257 " field { " |
| 5258 " name: 'key' number: 1 type:TYPE_INT32 label:LABEL_OPTIONAL " |
| 5259 " } " |
| 5260 " field { " |
| 5261 " name: 'value' number: 2 type:TYPE_INT32 label:LABEL_OPTIONAL " |
| 5262 " } " |
| 5263 " } " |
| 5264 "} " |
| 5265 "message_type { " |
| 5266 " name: 'Bar' " |
| 5267 " extension_range { start: 1 end: 10 }" |
| 5268 "} ", |
| 5269 file_proto)); |
| 5270 } |
| 5271 static const char* kMapEntryErrorMessage = |
| 5272 "foo.proto: Foo.foo_map: OTHER: map_entry should not be set explicitly. " |
| 5273 "Use map<KeyType, ValueType> instead.\n"; |
| 5274 static const char* kMapEntryKeyTypeErrorMessage = |
| 5275 "foo.proto: Foo.foo_map: TYPE: Key in map fields cannot be float/double, " |
| 5276 "bytes or message types.\n"; |
| 5277 |
| 5278 } // namespace |
| 5279 |
| 5280 TEST_F(ValidationErrorTest, MapEntryBase) { |
| 5281 FileDescriptorProto file_proto; |
| 5282 FillValidMapEntry(&file_proto); |
| 5283 BuildFile(file_proto.DebugString()); |
| 5284 } |
| 5285 |
| 5286 TEST_F(ValidationErrorTest, MapEntryExtensionRange) { |
| 5287 FileDescriptorProto file_proto; |
| 5288 FillValidMapEntry(&file_proto); |
| 5289 TextFormat::MergeFromString( |
| 5290 "extension_range { " |
| 5291 " start: 10 end: 20 " |
| 5292 "} ", |
| 5293 file_proto.mutable_message_type(0)->mutable_nested_type(0)); |
| 5294 BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage); |
| 5295 } |
| 5296 |
| 5297 TEST_F(ValidationErrorTest, MapEntryExtension) { |
| 5298 FileDescriptorProto file_proto; |
| 5299 FillValidMapEntry(&file_proto); |
| 5300 TextFormat::MergeFromString( |
| 5301 "extension { " |
| 5302 " name: 'foo_ext' extendee: '.Bar' number: 5" |
| 5303 "} ", |
| 5304 file_proto.mutable_message_type(0)->mutable_nested_type(0)); |
| 5305 BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage); |
| 5306 } |
| 5307 |
| 5308 TEST_F(ValidationErrorTest, MapEntryNestedType) { |
| 5309 FileDescriptorProto file_proto; |
| 5310 FillValidMapEntry(&file_proto); |
| 5311 TextFormat::MergeFromString( |
| 5312 "nested_type { " |
| 5313 " name: 'Bar' " |
| 5314 "} ", |
| 5315 file_proto.mutable_message_type(0)->mutable_nested_type(0)); |
| 5316 BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage); |
| 5317 } |
| 5318 |
| 5319 TEST_F(ValidationErrorTest, MapEntryEnumTypes) { |
| 5320 FileDescriptorProto file_proto; |
| 5321 FillValidMapEntry(&file_proto); |
| 5322 TextFormat::MergeFromString( |
| 5323 "enum_type { " |
| 5324 " name: 'BarEnum' " |
| 5325 " value { name: 'BAR_BAR' number:0 } " |
| 5326 "} ", |
| 5327 file_proto.mutable_message_type(0)->mutable_nested_type(0)); |
| 5328 BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage); |
| 5329 } |
| 5330 |
| 5331 TEST_F(ValidationErrorTest, MapEntryExtraField) { |
| 5332 FileDescriptorProto file_proto; |
| 5333 FillValidMapEntry(&file_proto); |
| 5334 TextFormat::MergeFromString( |
| 5335 "field { " |
| 5336 " name: 'other_field' " |
| 5337 " label: LABEL_OPTIONAL " |
| 5338 " type: TYPE_INT32 " |
| 5339 " number: 3 " |
| 5340 "} ", |
| 5341 file_proto.mutable_message_type(0)->mutable_nested_type(0)); |
| 5342 BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage); |
| 5343 } |
| 5344 |
| 5345 TEST_F(ValidationErrorTest, MapEntryMessageName) { |
| 5346 FileDescriptorProto file_proto; |
| 5347 FillValidMapEntry(&file_proto); |
| 5348 file_proto.mutable_message_type(0)->mutable_nested_type(0)->set_name( |
| 5349 "OtherMapEntry"); |
| 5350 file_proto.mutable_message_type(0)->mutable_field(0)->set_type_name( |
| 5351 "OtherMapEntry"); |
| 5352 BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage); |
| 5353 } |
| 5354 |
| 5355 TEST_F(ValidationErrorTest, MapEntryNoneRepeatedMapEntry) { |
| 5356 FileDescriptorProto file_proto; |
| 5357 FillValidMapEntry(&file_proto); |
| 5358 file_proto.mutable_message_type(0)->mutable_field(0)->set_label( |
| 5359 FieldDescriptorProto::LABEL_OPTIONAL); |
| 5360 BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage); |
| 5361 } |
| 5362 |
| 5363 TEST_F(ValidationErrorTest, MapEntryDifferentContainingType) { |
| 5364 FileDescriptorProto file_proto; |
| 5365 FillValidMapEntry(&file_proto); |
| 5366 // Move the nested MapEntry message into the top level, which should not pass |
| 5367 // the validation. |
| 5368 file_proto.mutable_message_type()->AddAllocated( |
| 5369 file_proto.mutable_message_type(0)->mutable_nested_type()->ReleaseLast()); |
| 5370 BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage); |
| 5371 } |
| 5372 |
| 5373 TEST_F(ValidationErrorTest, MapEntryKeyName) { |
| 5374 FileDescriptorProto file_proto; |
| 5375 FillValidMapEntry(&file_proto); |
| 5376 FieldDescriptorProto* key = file_proto.mutable_message_type(0) |
| 5377 ->mutable_nested_type(0) |
| 5378 ->mutable_field(0); |
| 5379 key->set_name("Key"); |
| 5380 BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage); |
| 5381 } |
| 5382 |
| 5383 TEST_F(ValidationErrorTest, MapEntryKeyLabel) { |
| 5384 FileDescriptorProto file_proto; |
| 5385 FillValidMapEntry(&file_proto); |
| 5386 FieldDescriptorProto* key = file_proto.mutable_message_type(0) |
| 5387 ->mutable_nested_type(0) |
| 5388 ->mutable_field(0); |
| 5389 key->set_label(FieldDescriptorProto::LABEL_REQUIRED); |
| 5390 BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage); |
| 5391 } |
| 5392 |
| 5393 TEST_F(ValidationErrorTest, MapEntryKeyNumber) { |
| 5394 FileDescriptorProto file_proto; |
| 5395 FillValidMapEntry(&file_proto); |
| 5396 FieldDescriptorProto* key = file_proto.mutable_message_type(0) |
| 5397 ->mutable_nested_type(0) |
| 5398 ->mutable_field(0); |
| 5399 key->set_number(3); |
| 5400 BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage); |
| 5401 } |
| 5402 |
| 5403 TEST_F(ValidationErrorTest, MapEntryValueName) { |
| 5404 FileDescriptorProto file_proto; |
| 5405 FillValidMapEntry(&file_proto); |
| 5406 FieldDescriptorProto* value = file_proto.mutable_message_type(0) |
| 5407 ->mutable_nested_type(0) |
| 5408 ->mutable_field(1); |
| 5409 value->set_name("Value"); |
| 5410 BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage); |
| 5411 } |
| 5412 |
| 5413 TEST_F(ValidationErrorTest, MapEntryValueLabel) { |
| 5414 FileDescriptorProto file_proto; |
| 5415 FillValidMapEntry(&file_proto); |
| 5416 FieldDescriptorProto* value = file_proto.mutable_message_type(0) |
| 5417 ->mutable_nested_type(0) |
| 5418 ->mutable_field(1); |
| 5419 value->set_label(FieldDescriptorProto::LABEL_REQUIRED); |
| 5420 BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage); |
| 5421 } |
| 5422 |
| 5423 TEST_F(ValidationErrorTest, MapEntryValueNumber) { |
| 5424 FileDescriptorProto file_proto; |
| 5425 FillValidMapEntry(&file_proto); |
| 5426 FieldDescriptorProto* value = file_proto.mutable_message_type(0) |
| 5427 ->mutable_nested_type(0) |
| 5428 ->mutable_field(1); |
| 5429 value->set_number(3); |
| 5430 BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage); |
| 5431 } |
| 5432 |
| 5433 TEST_F(ValidationErrorTest, MapEntryKeyTypeFloat) { |
| 5434 FileDescriptorProto file_proto; |
| 5435 FillValidMapEntry(&file_proto); |
| 5436 FieldDescriptorProto* key = file_proto.mutable_message_type(0) |
| 5437 ->mutable_nested_type(0) |
| 5438 ->mutable_field(0); |
| 5439 key->set_type(FieldDescriptorProto::TYPE_FLOAT); |
| 5440 BuildFileWithErrors(file_proto.DebugString(), kMapEntryKeyTypeErrorMessage); |
| 5441 } |
| 5442 |
| 5443 TEST_F(ValidationErrorTest, MapEntryKeyTypeDouble) { |
| 5444 FileDescriptorProto file_proto; |
| 5445 FillValidMapEntry(&file_proto); |
| 5446 FieldDescriptorProto* key = file_proto.mutable_message_type(0) |
| 5447 ->mutable_nested_type(0) |
| 5448 ->mutable_field(0); |
| 5449 key->set_type(FieldDescriptorProto::TYPE_DOUBLE); |
| 5450 BuildFileWithErrors(file_proto.DebugString(), kMapEntryKeyTypeErrorMessage); |
| 5451 } |
| 5452 |
| 5453 TEST_F(ValidationErrorTest, MapEntryKeyTypeBytes) { |
| 5454 FileDescriptorProto file_proto; |
| 5455 FillValidMapEntry(&file_proto); |
| 5456 FieldDescriptorProto* key = file_proto.mutable_message_type(0) |
| 5457 ->mutable_nested_type(0) |
| 5458 ->mutable_field(0); |
| 5459 key->set_type(FieldDescriptorProto::TYPE_BYTES); |
| 5460 BuildFileWithErrors(file_proto.DebugString(), kMapEntryKeyTypeErrorMessage); |
| 5461 } |
| 5462 |
| 5463 TEST_F(ValidationErrorTest, MapEntryKeyTypeEnum) { |
| 5464 FileDescriptorProto file_proto; |
| 5465 FillValidMapEntry(&file_proto); |
| 5466 FieldDescriptorProto* key = file_proto.mutable_message_type(0) |
| 5467 ->mutable_nested_type(0) |
| 5468 ->mutable_field(0); |
| 5469 key->clear_type(); |
| 5470 key->set_type_name("BarEnum"); |
| 5471 EnumDescriptorProto* enum_proto = file_proto.add_enum_type(); |
| 5472 enum_proto->set_name("BarEnum"); |
| 5473 EnumValueDescriptorProto* enum_value_proto = enum_proto->add_value(); |
| 5474 enum_value_proto->set_name("BAR_VALUE0"); |
| 5475 enum_value_proto->set_number(0); |
| 5476 BuildFileWithErrors(file_proto.DebugString(), |
| 5477 "foo.proto: Foo.foo_map: TYPE: Key in map fields cannot " |
| 5478 "be enum types.\n"); |
| 5479 // Enum keys are not allowed in proto3 as well. |
| 5480 // Get rid of extensions for proto3 to make it proto3 compatible. |
| 5481 file_proto.mutable_message_type()->RemoveLast(); |
| 5482 file_proto.set_syntax("proto3"); |
| 5483 BuildFileWithErrors(file_proto.DebugString(), |
| 5484 "foo.proto: Foo.foo_map: TYPE: Key in map fields cannot " |
| 5485 "be enum types.\n"); |
| 5486 } |
| 5487 |
| 5488 |
| 5489 TEST_F(ValidationErrorTest, MapEntryKeyTypeMessage) { |
| 5490 FileDescriptorProto file_proto; |
| 5491 FillValidMapEntry(&file_proto); |
| 5492 FieldDescriptorProto* key = file_proto.mutable_message_type(0) |
| 5493 ->mutable_nested_type(0) |
| 5494 ->mutable_field(0); |
| 5495 key->clear_type(); |
| 5496 key->set_type_name(".Bar"); |
| 5497 BuildFileWithErrors(file_proto.DebugString(), kMapEntryKeyTypeErrorMessage); |
| 5498 } |
| 5499 |
| 5500 TEST_F(ValidationErrorTest, MapEntryConflictsWithField) { |
| 5501 FileDescriptorProto file_proto; |
| 5502 FillValidMapEntry(&file_proto); |
| 5503 TextFormat::MergeFromString( |
| 5504 "field { " |
| 5505 " name: 'FooMapEntry' " |
| 5506 " type: TYPE_INT32 " |
| 5507 " label: LABEL_OPTIONAL " |
| 5508 " number: 100 " |
| 5509 "}", |
| 5510 file_proto.mutable_message_type(0)); |
| 5511 BuildFileWithErrors( |
| 5512 file_proto.DebugString(), |
| 5513 "foo.proto: Foo.FooMapEntry: NAME: \"FooMapEntry\" is already defined in " |
| 5514 "\"Foo\".\n" |
| 5515 "foo.proto: Foo.foo_map: TYPE: \"FooMapEntry\" is not defined.\n" |
| 5516 "foo.proto: Foo: NAME: Expanded map entry type FooMapEntry conflicts " |
| 5517 "with an existing field.\n"); |
| 5518 } |
| 5519 |
| 5520 TEST_F(ValidationErrorTest, MapEntryConflictsWithMessage) { |
| 5521 FileDescriptorProto file_proto; |
| 5522 FillValidMapEntry(&file_proto); |
| 5523 TextFormat::MergeFromString( |
| 5524 "nested_type { " |
| 5525 " name: 'FooMapEntry' " |
| 5526 "}", |
| 5527 file_proto.mutable_message_type(0)); |
| 5528 BuildFileWithErrors( |
| 5529 file_proto.DebugString(), |
| 5530 "foo.proto: Foo.FooMapEntry: NAME: \"FooMapEntry\" is already defined in " |
| 5531 "\"Foo\".\n" |
| 5532 "foo.proto: Foo: NAME: Expanded map entry type FooMapEntry conflicts " |
| 5533 "with an existing nested message type.\n"); |
| 5534 } |
| 5535 |
| 5536 TEST_F(ValidationErrorTest, MapEntryConflictsWithEnum) { |
| 5537 FileDescriptorProto file_proto; |
| 5538 FillValidMapEntry(&file_proto); |
| 5539 TextFormat::MergeFromString( |
| 5540 "enum_type { " |
| 5541 " name: 'FooMapEntry' " |
| 5542 " value { name: 'ENTRY_FOO' number: 0 }" |
| 5543 "}", |
| 5544 file_proto.mutable_message_type(0)); |
| 5545 BuildFileWithErrors( |
| 5546 file_proto.DebugString(), |
| 5547 "foo.proto: Foo.FooMapEntry: NAME: \"FooMapEntry\" is already defined in " |
| 5548 "\"Foo\".\n" |
| 5549 "foo.proto: Foo: NAME: Expanded map entry type FooMapEntry conflicts " |
| 5550 "with an existing enum type.\n"); |
| 5551 } |
| 5552 |
| 5553 TEST_F(ValidationErrorTest, MapEntryConflictsWithOneof) { |
| 5554 FileDescriptorProto file_proto; |
| 5555 FillValidMapEntry(&file_proto); |
| 5556 TextFormat::MergeFromString( |
| 5557 "oneof_decl { " |
| 5558 " name: 'FooMapEntry' " |
| 5559 "}" |
| 5560 "field { " |
| 5561 " name: 'int_field' " |
| 5562 " type: TYPE_INT32 " |
| 5563 " label: LABEL_OPTIONAL " |
| 5564 " oneof_index: 0 " |
| 5565 " number: 100 " |
| 5566 "} ", |
| 5567 file_proto.mutable_message_type(0)); |
| 5568 BuildFileWithErrors( |
| 5569 file_proto.DebugString(), |
| 5570 "foo.proto: Foo.FooMapEntry: NAME: \"FooMapEntry\" is already defined in " |
| 5571 "\"Foo\".\n" |
| 5572 "foo.proto: Foo.foo_map: TYPE: \"FooMapEntry\" is not defined.\n" |
| 5573 "foo.proto: Foo: NAME: Expanded map entry type FooMapEntry conflicts " |
| 5574 "with an existing oneof type.\n"); |
| 5575 } |
| 5576 |
| 5577 TEST_F(ValidationErrorTest, MapEntryUsesNoneZeroEnumDefaultValue) { |
| 5578 BuildFileWithErrors( |
| 5579 "name: \"foo.proto\" " |
| 5580 "enum_type {" |
| 5581 " name: \"Bar\"" |
| 5582 " value { name:\"ENUM_A\" number:1 }" |
| 5583 " value { name:\"ENUM_B\" number:2 }" |
| 5584 "}" |
| 5585 "message_type {" |
| 5586 " name: 'Foo' " |
| 5587 " field { " |
| 5588 " name: 'foo_map' number: 1 label:LABEL_REPEATED " |
| 5589 " type_name: 'FooMapEntry' " |
| 5590 " } " |
| 5591 " nested_type { " |
| 5592 " name: 'FooMapEntry' " |
| 5593 " options { map_entry: true } " |
| 5594 " field { " |
| 5595 " name: 'key' number: 1 type:TYPE_INT32 label:LABEL_OPTIONAL " |
| 5596 " } " |
| 5597 " field { " |
| 5598 " name: 'value' number: 2 type_name:\"Bar\" label:LABEL_OPTIONAL " |
| 5599 " } " |
| 5600 " } " |
| 5601 "}", |
| 5602 "foo.proto: Foo.foo_map: " |
| 5603 "TYPE: Enum value in map must define 0 as the first value.\n"); |
| 5604 } |
| 5605 |
| 5606 TEST_F(ValidationErrorTest, Proto3RequiredFields) { |
| 5607 BuildFileWithErrors( |
| 5608 "name: 'foo.proto' " |
| 5609 "syntax: 'proto3' " |
| 5610 "message_type { " |
| 5611 " name: 'Foo' " |
| 5612 " field { name:'foo' number:1 label:LABEL_REQUIRED type:TYPE_INT32 } " |
| 5613 "}", |
| 5614 "foo.proto: Foo.foo: OTHER: Required fields are not allowed in " |
| 5615 "proto3.\n"); |
| 5616 |
| 5617 // applied to nested types as well. |
| 5618 BuildFileWithErrors( |
| 5619 "name: 'foo.proto' " |
| 5620 "syntax: 'proto3' " |
| 5621 "message_type { " |
| 5622 " name: 'Foo' " |
| 5623 " nested_type { " |
| 5624 " name : 'Bar' " |
| 5625 " field { name:'bar' number:1 label:LABEL_REQUIRED type:TYPE_INT32 } " |
| 5626 " } " |
| 5627 "}", |
| 5628 "foo.proto: Foo.Bar.bar: OTHER: Required fields are not allowed in " |
| 5629 "proto3.\n"); |
| 5630 |
| 5631 // optional and repeated fields are OK. |
| 5632 BuildFile( |
| 5633 "name: 'foo.proto' " |
| 5634 "syntax: 'proto3' " |
| 5635 "message_type { " |
| 5636 " name: 'Foo' " |
| 5637 " field { name:'foo' number:1 label:LABEL_OPTIONAL type:TYPE_INT32 } " |
| 5638 " field { name:'bar' number:2 label:LABEL_REPEATED type:TYPE_INT32 } " |
| 5639 "}"); |
| 5640 } |
| 5641 |
| 5642 TEST_F(ValidationErrorTest, ValidateProto3DefaultValue) { |
| 5643 BuildFileWithErrors( |
| 5644 "name: 'foo.proto' " |
| 5645 "syntax: 'proto3' " |
| 5646 "message_type { " |
| 5647 " name: 'Foo' " |
| 5648 " field { name:'foo' number:1 label:LABEL_OPTIONAL type:TYPE_INT32 " |
| 5649 " default_value: '1' }" |
| 5650 "}", |
| 5651 "foo.proto: Foo.foo: OTHER: Explicit default values are not allowed in " |
| 5652 "proto3.\n"); |
| 5653 |
| 5654 BuildFileWithErrors( |
| 5655 "name: 'foo.proto' " |
| 5656 "syntax: 'proto3' " |
| 5657 "message_type { " |
| 5658 " name: 'Foo' " |
| 5659 " nested_type { " |
| 5660 " name : 'Bar' " |
| 5661 " field { name:'bar' number:1 label:LABEL_OPTIONAL type:TYPE_INT32 " |
| 5662 " default_value: '1' }" |
| 5663 " } " |
| 5664 "}", |
| 5665 "foo.proto: Foo.Bar.bar: OTHER: Explicit default values are not allowed " |
| 5666 "in proto3.\n"); |
| 5667 } |
| 5668 |
| 5669 TEST_F(ValidationErrorTest, ValidateProto3ExtensionRange) { |
| 5670 BuildFileWithErrors( |
| 5671 "name: 'foo.proto' " |
| 5672 "syntax: 'proto3' " |
| 5673 "message_type { " |
| 5674 " name: 'Foo' " |
| 5675 " field { name:'foo' number:1 label:LABEL_OPTIONAL type:TYPE_INT32 } " |
| 5676 " extension_range { start:10 end:100 } " |
| 5677 "}", |
| 5678 "foo.proto: Foo: OTHER: Extension ranges are not allowed in " |
| 5679 "proto3.\n"); |
| 5680 |
| 5681 BuildFileWithErrors( |
| 5682 "name: 'foo.proto' " |
| 5683 "syntax: 'proto3' " |
| 5684 "message_type { " |
| 5685 " name: 'Foo' " |
| 5686 " nested_type { " |
| 5687 " name : 'Bar' " |
| 5688 " field { name:'bar' number:1 label:LABEL_OPTIONAL type:TYPE_INT32 } " |
| 5689 " extension_range { start:10 end:100 } " |
| 5690 " } " |
| 5691 "}", |
| 5692 "foo.proto: Foo.Bar: OTHER: Extension ranges are not allowed in " |
| 5693 "proto3.\n"); |
| 5694 } |
| 5695 |
| 5696 TEST_F(ValidationErrorTest, ValidateProto3MessageSetWireFormat) { |
| 5697 BuildFileWithErrors( |
| 5698 "name: 'foo.proto' " |
| 5699 "syntax: 'proto3' " |
| 5700 "message_type { " |
| 5701 " name: 'Foo' " |
| 5702 " options { message_set_wire_format: true } " |
| 5703 "}", |
| 5704 "foo.proto: Foo: OTHER: MessageSet is not supported " |
| 5705 "in proto3.\n"); |
| 5706 } |
| 5707 |
| 5708 TEST_F(ValidationErrorTest, ValidateProto3Enum) { |
| 5709 BuildFileWithErrors( |
| 5710 "name: 'foo.proto' " |
| 5711 "syntax: 'proto3' " |
| 5712 "enum_type { " |
| 5713 " name: 'FooEnum' " |
| 5714 " value { name: 'FOO_FOO' number:1 } " |
| 5715 "}", |
| 5716 "foo.proto: FooEnum: OTHER: The first enum value must be " |
| 5717 "zero in proto3.\n"); |
| 5718 |
| 5719 BuildFileWithErrors( |
| 5720 "name: 'foo.proto' " |
| 5721 "syntax: 'proto3' " |
| 5722 "message_type { " |
| 5723 " name: 'Foo' " |
| 5724 " enum_type { " |
| 5725 " name: 'FooEnum' " |
| 5726 " value { name: 'FOO_FOO' number:1 } " |
| 5727 " } " |
| 5728 "}", |
| 5729 "foo.proto: Foo.FooEnum: OTHER: The first enum value must be " |
| 5730 "zero in proto3.\n"); |
| 5731 |
| 5732 // valid case. |
| 5733 BuildFile( |
| 5734 "name: 'foo.proto' " |
| 5735 "syntax: 'proto3' " |
| 5736 "enum_type { " |
| 5737 " name: 'FooEnum' " |
| 5738 " value { name: 'FOO_FOO' number:0 } " |
| 5739 "}"); |
| 5740 } |
| 5741 |
| 5742 TEST_F(ValidationErrorTest, ValidateProto3LiteRuntime) { |
| 5743 // Lite runtime is not supported in proto3. |
| 5744 BuildFileWithErrors( |
| 5745 "name: 'foo.proto' " |
| 5746 "syntax: 'proto3' " |
| 5747 "options { " |
| 5748 " optimize_for: LITE_RUNTIME " |
| 5749 "} ", |
| 5750 "foo.proto: foo.proto: OTHER: Lite runtime is not supported " |
| 5751 "in proto3.\n"); |
| 5752 } |
| 5753 |
| 5754 TEST_F(ValidationErrorTest, ValidateProto3Group) { |
| 5755 BuildFileWithErrors( |
| 5756 "name: 'foo.proto' " |
| 5757 "syntax: 'proto3' " |
| 5758 "message_type { " |
| 5759 " name: 'Foo' " |
| 5760 " nested_type { " |
| 5761 " name: 'FooGroup' " |
| 5762 " } " |
| 5763 " field { name:'foo_group' number: 1 label:LABEL_OPTIONAL " |
| 5764 " type: TYPE_GROUP type_name:'FooGroup' } " |
| 5765 "}", |
| 5766 "foo.proto: Foo.foo_group: TYPE: Groups are not supported in proto3 " |
| 5767 "syntax.\n"); |
| 5768 } |
| 5769 |
| 5770 |
| 5771 TEST_F(ValidationErrorTest, ValidateProto3EnumFromProto2) { |
| 5772 // Define an enum in a proto2 file. |
| 5773 BuildFile( |
| 5774 "name: 'foo.proto' " |
| 5775 "package: 'foo' " |
| 5776 "syntax: 'proto2' " |
| 5777 "enum_type { " |
| 5778 " name: 'FooEnum' " |
| 5779 " value { name: 'DEFAULT_OPTION' number:0 } " |
| 5780 "}"); |
| 5781 |
| 5782 // Now try to refer to it. (All tests in the fixture use the same pool, so we |
| 5783 // can refer to the enum above in this definition.) |
| 5784 BuildFileWithErrors( |
| 5785 "name: 'bar.proto' " |
| 5786 "dependency: 'foo.proto' " |
| 5787 "syntax: 'proto3' " |
| 5788 "message_type { " |
| 5789 " name: 'Foo' " |
| 5790 " field { name:'bar' number:1 label:LABEL_OPTIONAL type:TYPE_ENUM " |
| 5791 " type_name: 'foo.FooEnum' }" |
| 5792 "}", |
| 5793 "bar.proto: Foo.bar: TYPE: Enum type \"foo.FooEnum\" is not a proto3 " |
| 5794 "enum, but is used in \"Foo\" which is a proto3 message type.\n"); |
| 5795 } |
| 5796 |
| 5797 TEST_F(ValidationErrorTest, ValidateProto3Extension) { |
| 5798 // Valid for options. |
| 5799 DescriptorPool pool; |
| 5800 FileDescriptorProto file_proto; |
| 5801 // Add "google/protobuf/descriptor.proto". |
| 5802 FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto); |
| 5803 ASSERT_TRUE(pool.BuildFile(file_proto) != NULL); |
| 5804 // Add "foo.proto": |
| 5805 // import "google/protobuf/descriptor.proto"; |
| 5806 // extend google.protobuf.FieldOptions { |
| 5807 // optional int32 option1 = 1000; |
| 5808 // } |
| 5809 file_proto.Clear(); |
| 5810 file_proto.set_name("foo.proto"); |
| 5811 file_proto.set_syntax("proto3"); |
| 5812 file_proto.add_dependency("google/protobuf/descriptor.proto"); |
| 5813 AddExtension(&file_proto, "google.protobuf.FieldOptions", "option1", 1000, |
| 5814 FieldDescriptorProto::LABEL_OPTIONAL, |
| 5815 FieldDescriptorProto::TYPE_INT32); |
| 5816 ASSERT_TRUE(pool.BuildFile(file_proto) != NULL); |
| 5817 |
| 5818 // Copy and change the package of the descriptor.proto |
| 5819 BuildFile( |
| 5820 "name: 'google.protobuf.proto' " |
| 5821 "syntax: 'proto2' " |
| 5822 "message_type { " |
| 5823 " name: 'Container' extension_range { start: 1 end: 1000 } " |
| 5824 "}"); |
| 5825 BuildFileWithErrors( |
| 5826 "name: 'bar.proto' " |
| 5827 "syntax: 'proto3' " |
| 5828 "dependency: 'google.protobuf.proto' " |
| 5829 "extension { " |
| 5830 " name: 'bar' number: 1 label: LABEL_OPTIONAL type: TYPE_INT32 " |
| 5831 " extendee: 'Container' " |
| 5832 "}", |
| 5833 "bar.proto: bar: OTHER: Extensions in proto3 are only allowed for " |
| 5834 "defining options.\n"); |
| 5835 } |
| 5836 |
| 5837 // Test that field names that may conflict in JSON is not allowed by protoc. |
| 5838 TEST_F(ValidationErrorTest, ValidateProto3JsonName) { |
| 5839 // The comparison is case-insensitive. |
| 5840 BuildFileWithErrors( |
| 5841 "name: 'foo.proto' " |
| 5842 "syntax: 'proto3' " |
| 5843 "message_type {" |
| 5844 " name: 'Foo'" |
| 5845 " field { name:'name' number:1 label:LABEL_OPTIONAL type:TYPE_INT32 }" |
| 5846 " field { name:'Name' number:2 label:LABEL_OPTIONAL type:TYPE_INT32 }" |
| 5847 "}", |
| 5848 "foo.proto: Foo: OTHER: The JSON camcel-case name of field \"Name\" " |
| 5849 "conflicts with field \"name\". This is not allowed in proto3.\n"); |
| 5850 // Underscores are ignored. |
| 5851 BuildFileWithErrors( |
| 5852 "name: 'foo.proto' " |
| 5853 "syntax: 'proto3' " |
| 5854 "message_type {" |
| 5855 " name: 'Foo'" |
| 5856 " field { name:'ab' number:1 label:LABEL_OPTIONAL type:TYPE_INT32 }" |
| 5857 " field { name:'_a__b_' number:2 label:LABEL_OPTIONAL type:TYPE_INT32 }" |
| 5858 "}", |
| 5859 "foo.proto: Foo: OTHER: The JSON camcel-case name of field \"_a__b_\" " |
| 5860 "conflicts with field \"ab\". This is not allowed in proto3.\n"); |
| 5861 } |
| 5862 |
| 4009 // =================================================================== | 5863 // =================================================================== |
| 4010 // DescriptorDatabase | 5864 // DescriptorDatabase |
| 4011 | 5865 |
| 4012 static void AddToDatabase(SimpleDescriptorDatabase* database, | 5866 static void AddToDatabase(SimpleDescriptorDatabase* database, |
| 4013 const char* file_text) { | 5867 const char* file_text) { |
| 4014 FileDescriptorProto file_proto; | 5868 FileDescriptorProto file_proto; |
| 4015 EXPECT_TRUE(TextFormat::ParseFromString(file_text, &file_proto)); | 5869 EXPECT_TRUE(TextFormat::ParseFromString(file_text, &file_proto)); |
| 4016 database->Add(file_proto); | 5870 database->Add(file_proto); |
| 4017 } | 5871 } |
| 4018 | 5872 |
| (...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4321 ASSERT_TRUE(file_from_database != NULL); | 6175 ASSERT_TRUE(file_from_database != NULL); |
| 4322 | 6176 |
| 4323 FileDescriptorProto original_file_proto; | 6177 FileDescriptorProto original_file_proto; |
| 4324 original_file->CopyTo(&original_file_proto); | 6178 original_file->CopyTo(&original_file_proto); |
| 4325 | 6179 |
| 4326 FileDescriptorProto file_from_database_proto; | 6180 FileDescriptorProto file_from_database_proto; |
| 4327 file_from_database->CopyTo(&file_from_database_proto); | 6181 file_from_database->CopyTo(&file_from_database_proto); |
| 4328 | 6182 |
| 4329 EXPECT_EQ(original_file_proto.DebugString(), | 6183 EXPECT_EQ(original_file_proto.DebugString(), |
| 4330 file_from_database_proto.DebugString()); | 6184 file_from_database_proto.DebugString()); |
| 6185 |
| 6186 // Also verify that CopyTo() did not omit any information. |
| 6187 EXPECT_EQ(original_file->DebugString(), |
| 6188 file_from_database->DebugString()); |
| 4331 } | 6189 } |
| 4332 | 6190 |
| 4333 TEST_F(DatabaseBackedPoolTest, DoesntRetryDbUnnecessarily) { | 6191 TEST_F(DatabaseBackedPoolTest, DoesntRetryDbUnnecessarily) { |
| 4334 // Searching for a child of an existing descriptor should never fall back | 6192 // Searching for a child of an existing descriptor should never fall back |
| 4335 // to the DescriptorDatabase even if it isn't found, because we know all | 6193 // to the DescriptorDatabase even if it isn't found, because we know all |
| 4336 // children are already loaded. | 6194 // children are already loaded. |
| 4337 CallCountingDatabase call_counter(&database_); | 6195 CallCountingDatabase call_counter(&database_); |
| 4338 DescriptorPool pool(&call_counter); | 6196 DescriptorPool pool(&call_counter); |
| 4339 | 6197 |
| 4340 const FileDescriptor* file = pool.FindFileByName("foo.proto"); | 6198 const FileDescriptor* file = pool.FindFileByName("foo.proto"); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4389 | 6247 |
| 4390 // Try inducing false positives. | 6248 // Try inducing false positives. |
| 4391 EXPECT_TRUE(pool.FindMessageTypeByName("NoSuchSymbol") == NULL); | 6249 EXPECT_TRUE(pool.FindMessageTypeByName("NoSuchSymbol") == NULL); |
| 4392 EXPECT_TRUE(pool.FindExtensionByNumber(foo, 22) == NULL); | 6250 EXPECT_TRUE(pool.FindExtensionByNumber(foo, 22) == NULL); |
| 4393 | 6251 |
| 4394 // No errors should have been reported. (If foo.proto was incorrectly | 6252 // No errors should have been reported. (If foo.proto was incorrectly |
| 4395 // loaded multiple times, errors would have been reported.) | 6253 // loaded multiple times, errors would have been reported.) |
| 4396 EXPECT_EQ("", error_collector.text_); | 6254 EXPECT_EQ("", error_collector.text_); |
| 4397 } | 6255 } |
| 4398 | 6256 |
| 6257 // DescriptorDatabase that attempts to induce exponentially-bad performance |
| 6258 // in DescriptorPool. For every positive N, the database contains a file |
| 6259 // fileN.proto, which defines a message MessageN, which contains fields of |
| 6260 // type MessageK for all K in [0,N). Message0 is not defined anywhere |
| 6261 // (file0.proto exists, but is empty), so every other file and message type |
| 6262 // will fail to build. |
| 6263 // |
| 6264 // If the DescriptorPool is not careful to memoize errors, an attempt to |
| 6265 // build a descriptor for MessageN can require O(2^N) time. |
| 6266 class ExponentialErrorDatabase : public DescriptorDatabase { |
| 6267 public: |
| 6268 ExponentialErrorDatabase() {} |
| 6269 ~ExponentialErrorDatabase() {} |
| 6270 |
| 6271 // implements DescriptorDatabase --------------------------------- |
| 6272 bool FindFileByName(const string& filename, |
| 6273 FileDescriptorProto* output) { |
| 6274 int file_num = -1; |
| 6275 FullMatch(filename, "file", ".proto", &file_num); |
| 6276 if (file_num > -1) { |
| 6277 return PopulateFile(file_num, output); |
| 6278 } else { |
| 6279 return false; |
| 6280 } |
| 6281 } |
| 6282 bool FindFileContainingSymbol(const string& symbol_name, |
| 6283 FileDescriptorProto* output) { |
| 6284 int file_num = -1; |
| 6285 FullMatch(symbol_name, "Message", "", &file_num); |
| 6286 if (file_num > 0) { |
| 6287 return PopulateFile(file_num, output); |
| 6288 } else { |
| 6289 return false; |
| 6290 } |
| 6291 } |
| 6292 bool FindFileContainingExtension(const string& containing_type, |
| 6293 int field_number, |
| 6294 FileDescriptorProto* output) { |
| 6295 return false; |
| 6296 } |
| 6297 |
| 6298 private: |
| 6299 void FullMatch(const string& name, |
| 6300 const string& begin_with, |
| 6301 const string& end_with, |
| 6302 int* file_num) { |
| 6303 int begin_size = begin_with.size(); |
| 6304 int end_size = end_with.size(); |
| 6305 if (name.substr(0, begin_size) != begin_with || |
| 6306 name.substr(name.size()- end_size, end_size) != end_with) { |
| 6307 return; |
| 6308 } |
| 6309 safe_strto32(name.substr(begin_size, name.size() - end_size - begin_size), |
| 6310 file_num); |
| 6311 } |
| 6312 |
| 6313 bool PopulateFile(int file_num, FileDescriptorProto* output) { |
| 6314 using strings::Substitute; |
| 6315 GOOGLE_CHECK_GE(file_num, 0); |
| 6316 output->Clear(); |
| 6317 output->set_name(Substitute("file$0.proto", file_num)); |
| 6318 // file0.proto doesn't define Message0 |
| 6319 if (file_num > 0) { |
| 6320 DescriptorProto* message = output->add_message_type(); |
| 6321 message->set_name(Substitute("Message$0", file_num)); |
| 6322 for (int i = 0; i < file_num; ++i) { |
| 6323 output->add_dependency(Substitute("file$0.proto", i)); |
| 6324 FieldDescriptorProto* field = message->add_field(); |
| 6325 field->set_name(Substitute("field$0", i)); |
| 6326 field->set_number(i); |
| 6327 field->set_label(FieldDescriptorProto::LABEL_OPTIONAL); |
| 6328 field->set_type(FieldDescriptorProto::TYPE_MESSAGE); |
| 6329 field->set_type_name(Substitute("Message$0", i)); |
| 6330 } |
| 6331 } |
| 6332 return true; |
| 6333 } |
| 6334 }; |
| 6335 |
| 4399 TEST_F(DatabaseBackedPoolTest, DoesntReloadKnownBadFiles) { | 6336 TEST_F(DatabaseBackedPoolTest, DoesntReloadKnownBadFiles) { |
| 4400 ErrorDescriptorDatabase error_database; | 6337 ExponentialErrorDatabase error_database; |
| 4401 MockErrorCollector error_collector; | 6338 DescriptorPool pool(&error_database); |
| 4402 DescriptorPool pool(&error_database, &error_collector); | |
| 4403 | 6339 |
| 4404 EXPECT_TRUE(pool.FindFileByName("error.proto") == NULL); | 6340 GOOGLE_LOG(INFO) << "A timeout in this test probably indicates a real bug."; |
| 4405 error_collector.text_.clear(); | 6341 |
| 4406 EXPECT_TRUE(pool.FindFileByName("error.proto") == NULL); | 6342 EXPECT_TRUE(pool.FindFileByName("file40.proto") == NULL); |
| 4407 EXPECT_EQ("", error_collector.text_); | 6343 EXPECT_TRUE(pool.FindMessageTypeByName("Message40") == NULL); |
| 4408 } | 6344 } |
| 4409 | 6345 |
| 4410 TEST_F(DatabaseBackedPoolTest, DoesntFallbackOnWrongType) { | 6346 TEST_F(DatabaseBackedPoolTest, DoesntFallbackOnWrongType) { |
| 4411 // If a lookup finds a symbol of the wrong type (e.g. we pass a type name | 6347 // If a lookup finds a symbol of the wrong type (e.g. we pass a type name |
| 4412 // to FindFieldByName()), we should fail fast, without checking the fallback | 6348 // to FindFieldByName()), we should fail fast, without checking the fallback |
| 4413 // database. | 6349 // database. |
| 4414 CallCountingDatabase call_counter(&database_); | 6350 CallCountingDatabase call_counter(&database_); |
| 4415 DescriptorPool pool(&call_counter); | 6351 DescriptorPool pool(&call_counter); |
| 4416 | 6352 |
| 4417 const FileDescriptor* file = pool.FindFileByName("foo.proto"); | 6353 const FileDescriptor* file = pool.FindFileByName("foo.proto"); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 4440 class AbortingErrorCollector : public DescriptorPool::ErrorCollector { | 6376 class AbortingErrorCollector : public DescriptorPool::ErrorCollector { |
| 4441 public: | 6377 public: |
| 4442 AbortingErrorCollector() {} | 6378 AbortingErrorCollector() {} |
| 4443 | 6379 |
| 4444 virtual void AddError( | 6380 virtual void AddError( |
| 4445 const string &filename, | 6381 const string &filename, |
| 4446 const string &element_name, | 6382 const string &element_name, |
| 4447 const Message *message, | 6383 const Message *message, |
| 4448 ErrorLocation location, | 6384 ErrorLocation location, |
| 4449 const string &error_message) { | 6385 const string &error_message) { |
| 4450 GOOGLE_LOG(FATAL) << "AddError() called unexpectedly: " << filename << ": " | 6386 GOOGLE_LOG(FATAL) << "AddError() called unexpectedly: " << filename << " [" |
| 4451 << error_message; | 6387 << element_name << "]: " << error_message; |
| 4452 } | 6388 } |
| 4453 private: | 6389 private: |
| 4454 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(AbortingErrorCollector); | 6390 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(AbortingErrorCollector); |
| 4455 }; | 6391 }; |
| 4456 | 6392 |
| 4457 // A source tree containing only one file. | 6393 // A source tree containing only one file. |
| 4458 class SingletonSourceTree : public compiler::SourceTree { | 6394 class SingletonSourceTree : public compiler::SourceTree { |
| 4459 public: | 6395 public: |
| 4460 SingletonSourceTree(const string& filename, const string& contents) | 6396 SingletonSourceTree(const string& filename, const string& contents) |
| 4461 : filename_(filename), contents_(contents) {} | 6397 : filename_(filename), contents_(contents) {} |
| (...skipping 20 matching lines...) Expand all Loading... |
| 4482 "}\n" | 6418 "}\n" |
| 4483 "enum Indecision {\n" | 6419 "enum Indecision {\n" |
| 4484 " YES = 1;\n" | 6420 " YES = 1;\n" |
| 4485 " NO = 2;\n" | 6421 " NO = 2;\n" |
| 4486 " MAYBE = 3;\n" | 6422 " MAYBE = 3;\n" |
| 4487 "}\n" | 6423 "}\n" |
| 4488 "service S {\n" | 6424 "service S {\n" |
| 4489 " rpc Method(A) returns (A.B);\n" | 6425 " rpc Method(A) returns (A.B);\n" |
| 4490 // Put an empty line here to make the source location range match. | 6426 // Put an empty line here to make the source location range match. |
| 4491 "\n" | 6427 "\n" |
| 6428 "}\n" |
| 6429 "message MessageWithExtensions {\n" |
| 6430 " extensions 1000 to max;\n" |
| 6431 "}\n" |
| 6432 "extend MessageWithExtensions {\n" |
| 6433 " optional int32 int32_extension = 1001;\n" |
| 6434 "}\n" |
| 6435 "message C {\n" |
| 6436 " extend MessageWithExtensions {\n" |
| 6437 " optional C message_extension = 1002;\n" |
| 6438 " }\n" |
| 4492 "}\n"; | 6439 "}\n"; |
| 4493 | 6440 |
| 4494 class SourceLocationTest : public testing::Test { | 6441 class SourceLocationTest : public testing::Test { |
| 4495 public: | 6442 public: |
| 4496 SourceLocationTest() | 6443 SourceLocationTest() |
| 4497 : source_tree_("/test/test.proto", kSourceLocationTestInput), | 6444 : source_tree_("/test/test.proto", kSourceLocationTestInput), |
| 4498 db_(&source_tree_), | 6445 db_(&source_tree_), |
| 4499 pool_(&db_, &collector_) {} | 6446 pool_(&db_, &collector_) {} |
| 4500 | 6447 |
| 4501 static string PrintSourceLocation(const SourceLocation &loc) { | 6448 static string PrintSourceLocation(const SourceLocation &loc) { |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4543 const ServiceDescriptor *s_desc = file_desc->FindServiceByName("S"); | 6490 const ServiceDescriptor *s_desc = file_desc->FindServiceByName("S"); |
| 4544 EXPECT_TRUE(s_desc->GetSourceLocation(&loc)); | 6491 EXPECT_TRUE(s_desc->GetSourceLocation(&loc)); |
| 4545 EXPECT_EQ("13:1-16:2", PrintSourceLocation(loc)); | 6492 EXPECT_EQ("13:1-16:2", PrintSourceLocation(loc)); |
| 4546 | 6493 |
| 4547 const MethodDescriptor *m_desc = s_desc->FindMethodByName("Method"); | 6494 const MethodDescriptor *m_desc = s_desc->FindMethodByName("Method"); |
| 4548 EXPECT_TRUE(m_desc->GetSourceLocation(&loc)); | 6495 EXPECT_TRUE(m_desc->GetSourceLocation(&loc)); |
| 4549 EXPECT_EQ("14:3-14:31", PrintSourceLocation(loc)); | 6496 EXPECT_EQ("14:3-14:31", PrintSourceLocation(loc)); |
| 4550 | 6497 |
| 4551 } | 6498 } |
| 4552 | 6499 |
| 6500 TEST_F(SourceLocationTest, ExtensionSourceLocation) { |
| 6501 SourceLocation loc; |
| 6502 |
| 6503 const FileDescriptor *file_desc = |
| 6504 GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto")); |
| 6505 |
| 6506 const FieldDescriptor *int32_extension_desc = |
| 6507 file_desc->FindExtensionByName("int32_extension"); |
| 6508 EXPECT_TRUE(int32_extension_desc->GetSourceLocation(&loc)); |
| 6509 EXPECT_EQ("21:3-21:41", PrintSourceLocation(loc)); |
| 6510 |
| 6511 const Descriptor *c_desc = file_desc->FindMessageTypeByName("C"); |
| 6512 EXPECT_TRUE(c_desc->GetSourceLocation(&loc)); |
| 6513 EXPECT_EQ("23:1-27:2", PrintSourceLocation(loc)); |
| 6514 |
| 6515 const FieldDescriptor *message_extension_desc = |
| 6516 c_desc->FindExtensionByName("message_extension"); |
| 6517 EXPECT_TRUE(message_extension_desc->GetSourceLocation(&loc)); |
| 6518 EXPECT_EQ("25:5-25:41", PrintSourceLocation(loc)); |
| 6519 } |
| 6520 |
| 4553 // Missing SourceCodeInfo doesn't cause crash: | 6521 // Missing SourceCodeInfo doesn't cause crash: |
| 4554 TEST_F(SourceLocationTest, GetSourceLocation_MissingSourceCodeInfo) { | 6522 TEST_F(SourceLocationTest, GetSourceLocation_MissingSourceCodeInfo) { |
| 4555 SourceLocation loc; | 6523 SourceLocation loc; |
| 4556 | 6524 |
| 4557 const FileDescriptor *file_desc = | 6525 const FileDescriptor *file_desc = |
| 4558 GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto")); | 6526 GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto")); |
| 4559 | 6527 |
| 4560 FileDescriptorProto proto; | 6528 FileDescriptorProto proto; |
| 4561 file_desc->CopyTo(&proto); // Note, this discards the SourceCodeInfo. | 6529 file_desc->CopyTo(&proto); // Note, this discards the SourceCodeInfo. |
| 4562 EXPECT_FALSE(proto.has_source_code_info()); | 6530 EXPECT_FALSE(proto.has_source_code_info()); |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4629 } | 6597 } |
| 4630 | 6598 |
| 4631 TEST_F(CopySourceCodeInfoToTest, CopySourceCodeInfoTo) { | 6599 TEST_F(CopySourceCodeInfoToTest, CopySourceCodeInfoTo) { |
| 4632 const FileDescriptor* file_desc = | 6600 const FileDescriptor* file_desc = |
| 4633 GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto")); | 6601 GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto")); |
| 4634 FileDescriptorProto file_desc_proto; | 6602 FileDescriptorProto file_desc_proto; |
| 4635 ASSERT_FALSE(file_desc_proto.has_source_code_info()); | 6603 ASSERT_FALSE(file_desc_proto.has_source_code_info()); |
| 4636 | 6604 |
| 4637 file_desc->CopySourceCodeInfoTo(&file_desc_proto); | 6605 file_desc->CopySourceCodeInfoTo(&file_desc_proto); |
| 4638 const SourceCodeInfo& info = file_desc_proto.source_code_info(); | 6606 const SourceCodeInfo& info = file_desc_proto.source_code_info(); |
| 4639 ASSERT_EQ(3, info.location_size()); | 6607 ASSERT_EQ(4, info.location_size()); |
| 4640 // Get the Foo message location | 6608 // Get the Foo message location |
| 4641 const SourceCodeInfo_Location& foo_location = info.location(1); | 6609 const SourceCodeInfo_Location& foo_location = info.location(2); |
| 4642 ASSERT_EQ(2, foo_location.path_size()); | 6610 ASSERT_EQ(2, foo_location.path_size()); |
| 4643 EXPECT_EQ(FileDescriptorProto::kMessageTypeFieldNumber, foo_location.path(0)); | 6611 EXPECT_EQ(FileDescriptorProto::kMessageTypeFieldNumber, foo_location.path(0)); |
| 4644 EXPECT_EQ(0, foo_location.path(1)); // Foo is the first message defined | 6612 EXPECT_EQ(0, foo_location.path(1)); // Foo is the first message defined |
| 4645 ASSERT_EQ(3, foo_location.span_size()); // Foo spans one line | 6613 ASSERT_EQ(3, foo_location.span_size()); // Foo spans one line |
| 4646 EXPECT_EQ(1, foo_location.span(0)); // Foo is declared on line 1 | 6614 EXPECT_EQ(1, foo_location.span(0)); // Foo is declared on line 1 |
| 4647 EXPECT_EQ(0, foo_location.span(1)); // Foo starts at column 0 | 6615 EXPECT_EQ(0, foo_location.span(1)); // Foo starts at column 0 |
| 4648 EXPECT_EQ(14, foo_location.span(2)); // Foo ends on column 14 | 6616 EXPECT_EQ(14, foo_location.span(2)); // Foo ends on column 14 |
| 4649 } | 6617 } |
| 4650 | 6618 |
| 4651 // =================================================================== | 6619 // =================================================================== |
| 4652 | 6620 |
| 4653 | 6621 |
| 4654 } // namespace descriptor_unittest | 6622 } // namespace descriptor_unittest |
| 4655 } // namespace protobuf | 6623 } // namespace protobuf |
| 4656 } // namespace google | 6624 } // namespace google |
| OLD | NEW |