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