1// Protocol Buffers - Google's data interchange format 2// Copyright 2008 Google Inc. All rights reserved. 3// http://code.google.com/p/protobuf/ 4// 5// Redistribution and use in source and binary forms, with or without 6// modification, are permitted provided that the following conditions are 7// met: 8// 9// * Redistributions of source code must retain the above copyright 10// notice, this list of conditions and the following disclaimer. 11// * Redistributions in binary form must reproduce the above 12// copyright notice, this list of conditions and the following disclaimer 13// in the documentation and/or other materials provided with the 14// distribution. 15// * Neither the name of Google Inc. nor the names of its 16// contributors may be used to endorse or promote products derived from 17// this software without specific prior written permission. 18// 19// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 31// Author: kenton@google.com (Kenton Varda) 32// Based on original Protocol Buffers design by 33// Sanjay Ghemawat, Jeff Dean, and others. 34 35#include <google/protobuf/extension_set.h> 36#include <google/protobuf/unittest.pb.h> 37#include <google/protobuf/test_util.h> 38#include <google/protobuf/descriptor.pb.h> 39#include <google/protobuf/descriptor.h> 40#include <google/protobuf/dynamic_message.h> 41#include <google/protobuf/wire_format.h> 42#include <google/protobuf/io/coded_stream.h> 43#include <google/protobuf/io/zero_copy_stream_impl.h> 44 45#include <google/protobuf/stubs/common.h> 46#include <google/protobuf/stubs/strutil.h> 47#include <google/protobuf/testing/googletest.h> 48#include <gtest/gtest.h> 49#include <google/protobuf/stubs/stl_util-inl.h> 50 51namespace google { 52namespace protobuf { 53namespace internal { 54namespace { 55 56// This test closely mirrors google/protobuf/compiler/cpp/unittest.cc 57// except that it uses extensions rather than regular fields. 58 59TEST(ExtensionSetTest, Defaults) { 60 // Check that all default values are set correctly in the initial message. 61 unittest::TestAllExtensions message; 62 63 TestUtil::ExpectExtensionsClear(message); 64 65 // Messages should return pointers to default instances until first use. 66 // (This is not checked by ExpectClear() since it is not actually true after 67 // the fields have been set and then cleared.) 68 EXPECT_EQ(&unittest::OptionalGroup_extension::default_instance(), 69 &message.GetExtension(unittest::optionalgroup_extension)); 70 EXPECT_EQ(&unittest::TestAllTypes::NestedMessage::default_instance(), 71 &message.GetExtension(unittest::optional_nested_message_extension)); 72 EXPECT_EQ(&unittest::ForeignMessage::default_instance(), 73 &message.GetExtension( 74 unittest::optional_foreign_message_extension)); 75 EXPECT_EQ(&unittest_import::ImportMessage::default_instance(), 76 &message.GetExtension(unittest::optional_import_message_extension)); 77} 78 79TEST(ExtensionSetTest, Accessors) { 80 // Set every field to a unique value then go back and check all those 81 // values. 82 unittest::TestAllExtensions message; 83 84 TestUtil::SetAllExtensions(&message); 85 TestUtil::ExpectAllExtensionsSet(message); 86 87 TestUtil::ModifyRepeatedExtensions(&message); 88 TestUtil::ExpectRepeatedExtensionsModified(message); 89} 90 91TEST(ExtensionSetTest, Clear) { 92 // Set every field to a unique value, clear the message, then check that 93 // it is cleared. 94 unittest::TestAllExtensions message; 95 96 TestUtil::SetAllExtensions(&message); 97 message.Clear(); 98 TestUtil::ExpectExtensionsClear(message); 99 100 // Unlike with the defaults test, we do NOT expect that requesting embedded 101 // messages will return a pointer to the default instance. Instead, they 102 // should return the objects that were created when mutable_blah() was 103 // called. 104 EXPECT_NE(&unittest::OptionalGroup_extension::default_instance(), 105 &message.GetExtension(unittest::optionalgroup_extension)); 106 EXPECT_NE(&unittest::TestAllTypes::NestedMessage::default_instance(), 107 &message.GetExtension(unittest::optional_nested_message_extension)); 108 EXPECT_NE(&unittest::ForeignMessage::default_instance(), 109 &message.GetExtension( 110 unittest::optional_foreign_message_extension)); 111 EXPECT_NE(&unittest_import::ImportMessage::default_instance(), 112 &message.GetExtension(unittest::optional_import_message_extension)); 113 114 // Make sure setting stuff again after clearing works. (This takes slightly 115 // different code paths since the objects are reused.) 116 TestUtil::SetAllExtensions(&message); 117 TestUtil::ExpectAllExtensionsSet(message); 118} 119 120TEST(ExtensionSetTest, ClearOneField) { 121 // Set every field to a unique value, then clear one value and insure that 122 // only that one value is cleared. 123 unittest::TestAllExtensions message; 124 125 TestUtil::SetAllExtensions(&message); 126 int64 original_value = 127 message.GetExtension(unittest::optional_int64_extension); 128 129 // Clear the field and make sure it shows up as cleared. 130 message.ClearExtension(unittest::optional_int64_extension); 131 EXPECT_FALSE(message.HasExtension(unittest::optional_int64_extension)); 132 EXPECT_EQ(0, message.GetExtension(unittest::optional_int64_extension)); 133 134 // Other adjacent fields should not be cleared. 135 EXPECT_TRUE(message.HasExtension(unittest::optional_int32_extension)); 136 EXPECT_TRUE(message.HasExtension(unittest::optional_uint32_extension)); 137 138 // Make sure if we set it again, then all fields are set. 139 message.SetExtension(unittest::optional_int64_extension, original_value); 140 TestUtil::ExpectAllExtensionsSet(message); 141} 142 143TEST(ExtensionSetTest, CopyFrom) { 144 unittest::TestAllExtensions message1, message2; 145 string data; 146 147 TestUtil::SetAllExtensions(&message1); 148 message2.CopyFrom(message1); 149 TestUtil::ExpectAllExtensionsSet(message2); 150} 151 152TEST(ExtensionSetTest, CopyFromUpcasted) { 153 unittest::TestAllExtensions message1, message2; 154 string data; 155 const Message& upcasted_message = message1; 156 157 TestUtil::SetAllExtensions(&message1); 158 message2.CopyFrom(upcasted_message); 159 TestUtil::ExpectAllExtensionsSet(message2); 160} 161 162TEST(ExtensionSetTest, SwapWithEmpty) { 163 unittest::TestAllExtensions message1, message2; 164 TestUtil::SetAllExtensions(&message1); 165 166 TestUtil::ExpectAllExtensionsSet(message1); 167 TestUtil::ExpectExtensionsClear(message2); 168 message1.Swap(&message2); 169 TestUtil::ExpectAllExtensionsSet(message2); 170 TestUtil::ExpectExtensionsClear(message1); 171} 172 173TEST(ExtensionSetTest, SwapWithSelf) { 174 unittest::TestAllExtensions message; 175 TestUtil::SetAllExtensions(&message); 176 177 TestUtil::ExpectAllExtensionsSet(message); 178 message.Swap(&message); 179 TestUtil::ExpectAllExtensionsSet(message); 180} 181 182TEST(ExtensionSetTest, SerializationToArray) { 183 // Serialize as TestAllExtensions and parse as TestAllTypes to insure wire 184 // compatibility of extensions. 185 // 186 // This checks serialization to a flat array by explicitly reserving space in 187 // the string and calling the generated message's 188 // SerializeWithCachedSizesToArray. 189 unittest::TestAllExtensions source; 190 unittest::TestAllTypes destination; 191 TestUtil::SetAllExtensions(&source); 192 int size = source.ByteSize(); 193 string data; 194 data.resize(size); 195 uint8* target = reinterpret_cast<uint8*>(string_as_array(&data)); 196 uint8* end = source.SerializeWithCachedSizesToArray(target); 197 EXPECT_EQ(size, end - target); 198 EXPECT_TRUE(destination.ParseFromString(data)); 199 TestUtil::ExpectAllFieldsSet(destination); 200} 201 202TEST(ExtensionSetTest, SerializationToStream) { 203 // Serialize as TestAllExtensions and parse as TestAllTypes to insure wire 204 // compatibility of extensions. 205 // 206 // This checks serialization to an output stream by creating an array output 207 // stream that can only buffer 1 byte at a time - this prevents the message 208 // from ever jumping to the fast path, ensuring that serialization happens via 209 // the CodedOutputStream. 210 unittest::TestAllExtensions source; 211 unittest::TestAllTypes destination; 212 TestUtil::SetAllExtensions(&source); 213 int size = source.ByteSize(); 214 string data; 215 data.resize(size); 216 { 217 io::ArrayOutputStream array_stream(string_as_array(&data), size, 1); 218 io::CodedOutputStream output_stream(&array_stream); 219 source.SerializeWithCachedSizes(&output_stream); 220 ASSERT_FALSE(output_stream.HadError()); 221 } 222 EXPECT_TRUE(destination.ParseFromString(data)); 223 TestUtil::ExpectAllFieldsSet(destination); 224} 225 226TEST(ExtensionSetTest, PackedSerializationToArray) { 227 // Serialize as TestPackedExtensions and parse as TestPackedTypes to insure 228 // wire compatibility of extensions. 229 // 230 // This checks serialization to a flat array by explicitly reserving space in 231 // the string and calling the generated message's 232 // SerializeWithCachedSizesToArray. 233 unittest::TestPackedExtensions source; 234 unittest::TestPackedTypes destination; 235 TestUtil::SetPackedExtensions(&source); 236 int size = source.ByteSize(); 237 string data; 238 data.resize(size); 239 uint8* target = reinterpret_cast<uint8*>(string_as_array(&data)); 240 uint8* end = source.SerializeWithCachedSizesToArray(target); 241 EXPECT_EQ(size, end - target); 242 EXPECT_TRUE(destination.ParseFromString(data)); 243 TestUtil::ExpectPackedFieldsSet(destination); 244} 245 246TEST(ExtensionSetTest, PackedSerializationToStream) { 247 // Serialize as TestPackedExtensions and parse as TestPackedTypes to insure 248 // wire compatibility of extensions. 249 // 250 // This checks serialization to an output stream by creating an array output 251 // stream that can only buffer 1 byte at a time - this prevents the message 252 // from ever jumping to the fast path, ensuring that serialization happens via 253 // the CodedOutputStream. 254 unittest::TestPackedExtensions source; 255 unittest::TestPackedTypes destination; 256 TestUtil::SetPackedExtensions(&source); 257 int size = source.ByteSize(); 258 string data; 259 data.resize(size); 260 { 261 io::ArrayOutputStream array_stream(string_as_array(&data), size, 1); 262 io::CodedOutputStream output_stream(&array_stream); 263 source.SerializeWithCachedSizes(&output_stream); 264 ASSERT_FALSE(output_stream.HadError()); 265 } 266 EXPECT_TRUE(destination.ParseFromString(data)); 267 TestUtil::ExpectPackedFieldsSet(destination); 268} 269 270TEST(ExtensionSetTest, Parsing) { 271 // Serialize as TestAllTypes and parse as TestAllExtensions. 272 unittest::TestAllTypes source; 273 unittest::TestAllExtensions destination; 274 string data; 275 276 TestUtil::SetAllFields(&source); 277 source.SerializeToString(&data); 278 EXPECT_TRUE(destination.ParseFromString(data)); 279 TestUtil::ExpectAllExtensionsSet(destination); 280} 281 282TEST(ExtensionSetTest, PackedParsing) { 283 // Serialize as TestPackedTypes and parse as TestPackedExtensions. 284 unittest::TestPackedTypes source; 285 unittest::TestPackedExtensions destination; 286 string data; 287 288 TestUtil::SetPackedFields(&source); 289 source.SerializeToString(&data); 290 EXPECT_TRUE(destination.ParseFromString(data)); 291 TestUtil::ExpectPackedExtensionsSet(destination); 292} 293 294TEST(ExtensionSetTest, IsInitialized) { 295 // Test that IsInitialized() returns false if required fields in nested 296 // extensions are missing. 297 unittest::TestAllExtensions message; 298 299 EXPECT_TRUE(message.IsInitialized()); 300 301 message.MutableExtension(unittest::TestRequired::single); 302 EXPECT_FALSE(message.IsInitialized()); 303 304 message.MutableExtension(unittest::TestRequired::single)->set_a(1); 305 EXPECT_FALSE(message.IsInitialized()); 306 message.MutableExtension(unittest::TestRequired::single)->set_b(2); 307 EXPECT_FALSE(message.IsInitialized()); 308 message.MutableExtension(unittest::TestRequired::single)->set_c(3); 309 EXPECT_TRUE(message.IsInitialized()); 310 311 message.AddExtension(unittest::TestRequired::multi); 312 EXPECT_FALSE(message.IsInitialized()); 313 314 message.MutableExtension(unittest::TestRequired::multi, 0)->set_a(1); 315 EXPECT_FALSE(message.IsInitialized()); 316 message.MutableExtension(unittest::TestRequired::multi, 0)->set_b(2); 317 EXPECT_FALSE(message.IsInitialized()); 318 message.MutableExtension(unittest::TestRequired::multi, 0)->set_c(3); 319 EXPECT_TRUE(message.IsInitialized()); 320} 321 322TEST(ExtensionSetTest, MutableString) { 323 // Test the mutable string accessors. 324 unittest::TestAllExtensions message; 325 326 message.MutableExtension(unittest::optional_string_extension)->assign("foo"); 327 EXPECT_TRUE(message.HasExtension(unittest::optional_string_extension)); 328 EXPECT_EQ("foo", message.GetExtension(unittest::optional_string_extension)); 329 330 message.AddExtension(unittest::repeated_string_extension)->assign("bar"); 331 ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_string_extension)); 332 EXPECT_EQ("bar", 333 message.GetExtension(unittest::repeated_string_extension, 0)); 334} 335 336TEST(ExtensionSetTest, SpaceUsedExcludingSelf) { 337 // Scalar primitive extensions should increase the extension set size by a 338 // minimum of the size of the primitive type. 339#define TEST_SCALAR_EXTENSIONS_SPACE_USED(type, value) \ 340 do { \ 341 unittest::TestAllExtensions message; \ 342 const int base_size = message.SpaceUsed(); \ 343 message.SetExtension(unittest::optional_##type##_extension, value); \ 344 int min_expected_size = base_size + \ 345 sizeof(message.GetExtension(unittest::optional_##type##_extension)); \ 346 EXPECT_LE(min_expected_size, message.SpaceUsed()); \ 347 } while (0) 348 349 TEST_SCALAR_EXTENSIONS_SPACE_USED(int32 , 101); 350 TEST_SCALAR_EXTENSIONS_SPACE_USED(int64 , 102); 351 TEST_SCALAR_EXTENSIONS_SPACE_USED(uint32 , 103); 352 TEST_SCALAR_EXTENSIONS_SPACE_USED(uint64 , 104); 353 TEST_SCALAR_EXTENSIONS_SPACE_USED(sint32 , 105); 354 TEST_SCALAR_EXTENSIONS_SPACE_USED(sint64 , 106); 355 TEST_SCALAR_EXTENSIONS_SPACE_USED(fixed32 , 107); 356 TEST_SCALAR_EXTENSIONS_SPACE_USED(fixed64 , 108); 357 TEST_SCALAR_EXTENSIONS_SPACE_USED(sfixed32, 109); 358 TEST_SCALAR_EXTENSIONS_SPACE_USED(sfixed64, 110); 359 TEST_SCALAR_EXTENSIONS_SPACE_USED(float , 111); 360 TEST_SCALAR_EXTENSIONS_SPACE_USED(double , 112); 361 TEST_SCALAR_EXTENSIONS_SPACE_USED(bool , true); 362#undef TEST_SCALAR_EXTENSIONS_SPACE_USED 363 { 364 unittest::TestAllExtensions message; 365 const int base_size = message.SpaceUsed(); 366 message.SetExtension(unittest::optional_nested_enum_extension, 367 unittest::TestAllTypes::FOO); 368 int min_expected_size = base_size + 369 sizeof(message.GetExtension(unittest::optional_nested_enum_extension)); 370 EXPECT_LE(min_expected_size, message.SpaceUsed()); 371 } 372 { 373 // Strings may cause extra allocations depending on their length; ensure 374 // that gets included as well. 375 unittest::TestAllExtensions message; 376 const int base_size = message.SpaceUsed(); 377 const string s("this is a fairly large string that will cause some " 378 "allocation in order to store it in the extension"); 379 message.SetExtension(unittest::optional_string_extension, s); 380 int min_expected_size = base_size + s.length(); 381 EXPECT_LE(min_expected_size, message.SpaceUsed()); 382 } 383 { 384 // Messages also have additional allocation that need to be counted. 385 unittest::TestAllExtensions message; 386 const int base_size = message.SpaceUsed(); 387 unittest::ForeignMessage foreign; 388 foreign.set_c(42); 389 message.MutableExtension(unittest::optional_foreign_message_extension)-> 390 CopyFrom(foreign); 391 int min_expected_size = base_size + foreign.SpaceUsed(); 392 EXPECT_LE(min_expected_size, message.SpaceUsed()); 393 } 394 395 // Repeated primitive extensions will increase space used by at least a 396 // RepeatedField<T>, and will cause additional allocations when the array 397 // gets too big for the initial space. 398 // This macro: 399 // - Adds a value to the repeated extension, then clears it, establishing 400 // the base size. 401 // - Adds a small number of values, testing that it doesn't increase the 402 // SpaceUsed() 403 // - Adds a large number of values (requiring allocation in the repeated 404 // field), and ensures that that allocation is included in SpaceUsed() 405#define TEST_REPEATED_EXTENSIONS_SPACE_USED(type, cpptype, value) \ 406 do { \ 407 unittest::TestAllExtensions message; \ 408 const int base_size = message.SpaceUsed(); \ 409 int min_expected_size = sizeof(RepeatedField<cpptype>) + base_size; \ 410 message.AddExtension(unittest::repeated_##type##_extension, value); \ 411 message.ClearExtension(unittest::repeated_##type##_extension); \ 412 const int empty_repeated_field_size = message.SpaceUsed(); \ 413 EXPECT_LE(min_expected_size, empty_repeated_field_size) << #type; \ 414 message.AddExtension(unittest::repeated_##type##_extension, value); \ 415 message.AddExtension(unittest::repeated_##type##_extension, value); \ 416 EXPECT_EQ(empty_repeated_field_size, message.SpaceUsed()) << #type; \ 417 message.ClearExtension(unittest::repeated_##type##_extension); \ 418 for (int i = 0; i < 16; ++i) { \ 419 message.AddExtension(unittest::repeated_##type##_extension, value); \ 420 } \ 421 int expected_size = sizeof(cpptype) * 16 + empty_repeated_field_size; \ 422 EXPECT_EQ(expected_size, message.SpaceUsed()) << #type; \ 423 } while (0) 424 425 TEST_REPEATED_EXTENSIONS_SPACE_USED(int32 , int32 , 101); 426 TEST_REPEATED_EXTENSIONS_SPACE_USED(int64 , int64 , 102); 427 TEST_REPEATED_EXTENSIONS_SPACE_USED(uint32 , uint32, 103); 428 TEST_REPEATED_EXTENSIONS_SPACE_USED(uint64 , uint64, 104); 429 TEST_REPEATED_EXTENSIONS_SPACE_USED(sint32 , int32 , 105); 430 TEST_REPEATED_EXTENSIONS_SPACE_USED(sint64 , int64 , 106); 431 TEST_REPEATED_EXTENSIONS_SPACE_USED(fixed32 , uint32, 107); 432 TEST_REPEATED_EXTENSIONS_SPACE_USED(fixed64 , uint64, 108); 433 TEST_REPEATED_EXTENSIONS_SPACE_USED(sfixed32, int32 , 109); 434 TEST_REPEATED_EXTENSIONS_SPACE_USED(sfixed64, int64 , 110); 435 TEST_REPEATED_EXTENSIONS_SPACE_USED(float , float , 111); 436 TEST_REPEATED_EXTENSIONS_SPACE_USED(double , double, 112); 437 TEST_REPEATED_EXTENSIONS_SPACE_USED(bool , bool , true); 438 TEST_REPEATED_EXTENSIONS_SPACE_USED(nested_enum, int, 439 unittest::TestAllTypes::FOO); 440#undef TEST_REPEATED_EXTENSIONS_SPACE_USED 441 // Repeated strings 442 { 443 unittest::TestAllExtensions message; 444 const int base_size = message.SpaceUsed(); 445 int min_expected_size = sizeof(RepeatedPtrField<string>) + base_size; 446 const string value(256, 'x'); 447 // Once items are allocated, they may stick around even when cleared so 448 // without the hardcore memory management accessors there isn't a notion of 449 // the empty repeated field memory usage as there is with primitive types. 450 for (int i = 0; i < 16; ++i) { 451 message.AddExtension(unittest::repeated_string_extension, value); 452 } 453 min_expected_size += (sizeof(value) + value.size()) * 16; 454 EXPECT_LE(min_expected_size, message.SpaceUsed()); 455 } 456 // Repeated messages 457 { 458 unittest::TestAllExtensions message; 459 const int base_size = message.SpaceUsed(); 460 int min_expected_size = sizeof(RepeatedPtrField<unittest::ForeignMessage>) + 461 base_size; 462 unittest::ForeignMessage prototype; 463 prototype.set_c(2); 464 for (int i = 0; i < 16; ++i) { 465 message.AddExtension(unittest::repeated_foreign_message_extension)-> 466 CopyFrom(prototype); 467 } 468 min_expected_size += 16 * prototype.SpaceUsed(); 469 EXPECT_LE(min_expected_size, message.SpaceUsed()); 470 } 471} 472 473#ifdef GTEST_HAS_DEATH_TEST 474 475TEST(ExtensionSetTest, InvalidEnumDeath) { 476 unittest::TestAllExtensions message; 477 EXPECT_DEBUG_DEATH( 478 message.SetExtension(unittest::optional_foreign_enum_extension, 479 static_cast<unittest::ForeignEnum>(53)), 480 "IsValid"); 481} 482 483#endif // GTEST_HAS_DEATH_TEST 484 485TEST(ExtensionSetTest, DynamicExtensions) { 486 // Test adding a dynamic extension to a compiled-in message object. 487 488 FileDescriptorProto dynamic_proto; 489 dynamic_proto.set_name("dynamic_extensions_test.proto"); 490 dynamic_proto.add_dependency( 491 unittest::TestAllExtensions::descriptor()->file()->name()); 492 dynamic_proto.set_package("dynamic_extensions"); 493 494 // Copy the fields and nested types from TestDynamicExtensions into our new 495 // proto, converting the fields into extensions. 496 const Descriptor* template_descriptor = 497 unittest::TestDynamicExtensions::descriptor(); 498 DescriptorProto template_descriptor_proto; 499 template_descriptor->CopyTo(&template_descriptor_proto); 500 dynamic_proto.mutable_message_type()->MergeFrom( 501 template_descriptor_proto.nested_type()); 502 dynamic_proto.mutable_enum_type()->MergeFrom( 503 template_descriptor_proto.enum_type()); 504 dynamic_proto.mutable_extension()->MergeFrom( 505 template_descriptor_proto.field()); 506 507 // For each extension that we added... 508 for (int i = 0; i < dynamic_proto.extension_size(); i++) { 509 // Set its extendee to TestAllExtensions. 510 FieldDescriptorProto* extension = dynamic_proto.mutable_extension(i); 511 extension->set_extendee( 512 unittest::TestAllExtensions::descriptor()->full_name()); 513 514 // If the field refers to one of the types nested in TestDynamicExtensions, 515 // make it refer to the type in our dynamic proto instead. 516 string prefix = "." + template_descriptor->full_name() + "."; 517 if (extension->has_type_name()) { 518 string* type_name = extension->mutable_type_name(); 519 if (HasPrefixString(*type_name, prefix)) { 520 type_name->replace(0, prefix.size(), ".dynamic_extensions."); 521 } 522 } 523 } 524 525 // Now build the file, using the generated pool as an underlay. 526 DescriptorPool dynamic_pool(DescriptorPool::generated_pool()); 527 const FileDescriptor* file = dynamic_pool.BuildFile(dynamic_proto); 528 ASSERT_TRUE(file != NULL); 529 DynamicMessageFactory dynamic_factory(&dynamic_pool); 530 dynamic_factory.SetDelegateToGeneratedFactory(true); 531 532 // Construct a message that we can parse with the extensions we defined. 533 // Since the extensions were based off of the fields of TestDynamicExtensions, 534 // we can use that message to create this test message. 535 string data; 536 { 537 unittest::TestDynamicExtensions message; 538 message.set_scalar_extension(123); 539 message.set_enum_extension(unittest::FOREIGN_BAR); 540 message.set_dynamic_enum_extension( 541 unittest::TestDynamicExtensions::DYNAMIC_BAZ); 542 message.mutable_message_extension()->set_c(456); 543 message.mutable_dynamic_message_extension()->set_dynamic_field(789); 544 message.add_repeated_extension("foo"); 545 message.add_repeated_extension("bar"); 546 message.add_packed_extension(12); 547 message.add_packed_extension(-34); 548 message.add_packed_extension(56); 549 message.add_packed_extension(-78); 550 551 // Also add some unknown fields. 552 553 // An unknown enum value (for a known field). 554 message.mutable_unknown_fields()->AddVarint( 555 unittest::TestDynamicExtensions::kDynamicEnumExtensionFieldNumber, 556 12345); 557 // A regular unknown field. 558 message.mutable_unknown_fields()->AddLengthDelimited(54321, "unknown"); 559 560 message.SerializeToString(&data); 561 } 562 563 // Now we can parse this using our dynamic extension definitions... 564 unittest::TestAllExtensions message; 565 { 566 io::ArrayInputStream raw_input(data.data(), data.size()); 567 io::CodedInputStream input(&raw_input); 568 input.SetExtensionRegistry(&dynamic_pool, &dynamic_factory); 569 ASSERT_TRUE(message.ParseFromCodedStream(&input)); 570 ASSERT_TRUE(input.ConsumedEntireMessage()); 571 } 572 573 // Can we print it? 574 EXPECT_EQ( 575 "[dynamic_extensions.scalar_extension]: 123\n" 576 "[dynamic_extensions.enum_extension]: FOREIGN_BAR\n" 577 "[dynamic_extensions.dynamic_enum_extension]: DYNAMIC_BAZ\n" 578 "[dynamic_extensions.message_extension] {\n" 579 " c: 456\n" 580 "}\n" 581 "[dynamic_extensions.dynamic_message_extension] {\n" 582 " dynamic_field: 789\n" 583 "}\n" 584 "[dynamic_extensions.repeated_extension]: \"foo\"\n" 585 "[dynamic_extensions.repeated_extension]: \"bar\"\n" 586 "[dynamic_extensions.packed_extension]: 12\n" 587 "[dynamic_extensions.packed_extension]: -34\n" 588 "[dynamic_extensions.packed_extension]: 56\n" 589 "[dynamic_extensions.packed_extension]: -78\n" 590 "2002: 12345\n" 591 "54321: \"unknown\"\n", 592 message.DebugString()); 593 594 // Can we serialize it? 595 // (Don't use EXPECT_EQ because we don't want to dump raw binary data to the 596 // terminal on failure.) 597 EXPECT_TRUE(message.SerializeAsString() == data); 598 599 // What if we parse using the reflection-based parser? 600 { 601 unittest::TestAllExtensions message2; 602 io::ArrayInputStream raw_input(data.data(), data.size()); 603 io::CodedInputStream input(&raw_input); 604 input.SetExtensionRegistry(&dynamic_pool, &dynamic_factory); 605 ASSERT_TRUE(WireFormat::ParseAndMergePartial(&input, &message2)); 606 ASSERT_TRUE(input.ConsumedEntireMessage()); 607 EXPECT_EQ(message.DebugString(), message2.DebugString()); 608 } 609 610 // Are the embedded generated types actually using the generated objects? 611 { 612 const FieldDescriptor* message_extension = 613 file->FindExtensionByName("message_extension"); 614 ASSERT_TRUE(message_extension != NULL); 615 const Message& sub_message = 616 message.GetReflection()->GetMessage(message, message_extension); 617 const unittest::ForeignMessage* typed_sub_message = 618 dynamic_cast<const unittest::ForeignMessage*>(&sub_message); 619 ASSERT_TRUE(typed_sub_message != NULL); 620 EXPECT_EQ(456, typed_sub_message->c()); 621 } 622 623 // What does GetMessage() return for the embedded dynamic type if it isn't 624 // present? 625 { 626 const FieldDescriptor* dynamic_message_extension = 627 file->FindExtensionByName("dynamic_message_extension"); 628 ASSERT_TRUE(dynamic_message_extension != NULL); 629 const Message& parent = unittest::TestAllExtensions::default_instance(); 630 const Message& sub_message = 631 parent.GetReflection()->GetMessage(parent, dynamic_message_extension, 632 &dynamic_factory); 633 const Message* prototype = 634 dynamic_factory.GetPrototype(dynamic_message_extension->message_type()); 635 EXPECT_EQ(prototype, &sub_message); 636 } 637} 638 639} // namespace 640} // namespace internal 641} // namespace protobuf 642} // namespace google 643