1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 // http://code.google.com/p/protobuf/
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
9 // * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 // * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
15 // * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 // Author: kenton@google.com (Kenton Varda)
32 // Based on original Protocol Buffers design by
33 // Sanjay Ghemawat, Jeff Dean, and others.
35 #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>
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>
58 // This test closely mirrors google/protobuf/compiler/cpp/unittest.cc
59 // except that it uses extensions rather than regular fields.
61 TEST(ExtensionSetTest, Defaults) {
62 // Check that all default values are set correctly in the initial message.
63 unittest::TestAllExtensions message;
65 TestUtil::ExpectExtensionsClear(message);
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));
81 TEST(ExtensionSetTest, Accessors) {
82 // Set every field to a unique value then go back and check all those
84 unittest::TestAllExtensions message;
86 TestUtil::SetAllExtensions(&message);
87 TestUtil::ExpectAllExtensionsSet(message);
89 TestUtil::ModifyRepeatedExtensions(&message);
90 TestUtil::ExpectRepeatedExtensionsModified(message);
93 TEST(ExtensionSetTest, Clear) {
94 // Set every field to a unique value, clear the message, then check that
96 unittest::TestAllExtensions message;
98 TestUtil::SetAllExtensions(&message);
100 TestUtil::ExpectExtensionsClear(message);
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
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));
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);
122 TEST(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;
127 TestUtil::SetAllExtensions(&message);
128 int64 original_value =
129 message.GetExtension(unittest::optional_int64_extension);
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));
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));
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);
145 TEST(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,
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));
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());
167 // SetAllocatedExtension with a NULL parameter is equivalent to ClearExtenion.
168 message.SetAllocatedExtension(unittest::optional_foreign_message_extension,
170 EXPECT_FALSE(message.HasExtension(
171 unittest::optional_foreign_message_extension));
174 TEST(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,
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,
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;
207 TEST(ExtensionSetTest, CopyFrom) {
208 unittest::TestAllExtensions message1, message2;
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);
217 TEST(ExtensioSetTest, CopyFromPacked) {
218 unittest::TestPackedExtensions message1, message2;
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);
227 TEST(ExtensionSetTest, CopyFromUpcasted) {
228 unittest::TestAllExtensions message1, message2;
229 const Message& upcasted_message = message1;
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);
239 TEST(ExtensionSetTest, SwapWithEmpty) {
240 unittest::TestAllExtensions message1, message2;
241 TestUtil::SetAllExtensions(&message1);
243 TestUtil::ExpectAllExtensionsSet(message1);
244 TestUtil::ExpectExtensionsClear(message2);
245 message1.Swap(&message2);
246 TestUtil::ExpectAllExtensionsSet(message2);
247 TestUtil::ExpectExtensionsClear(message1);
250 TEST(ExtensionSetTest, SwapWithSelf) {
251 unittest::TestAllExtensions message;
252 TestUtil::SetAllExtensions(&message);
254 TestUtil::ExpectAllExtensionsSet(message);
255 message.Swap(&message);
256 TestUtil::ExpectAllExtensionsSet(message);
259 TEST(ExtensionSetTest, SerializationToArray) {
260 // Serialize as TestAllExtensions and parse as TestAllTypes to insure wire
261 // compatibility of extensions.
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();
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);
279 TEST(ExtensionSetTest, SerializationToStream) {
280 // Serialize as TestAllExtensions and parse as TestAllTypes to insure wire
281 // compatibility of extensions.
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();
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());
299 EXPECT_TRUE(destination.ParseFromString(data));
300 TestUtil::ExpectAllFieldsSet(destination);
303 TEST(ExtensionSetTest, PackedSerializationToArray) {
304 // Serialize as TestPackedExtensions and parse as TestPackedTypes to insure
305 // wire compatibility of extensions.
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();
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);
323 TEST(ExtensionSetTest, PackedSerializationToStream) {
324 // Serialize as TestPackedExtensions and parse as TestPackedTypes to insure
325 // wire compatibility of extensions.
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();
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());
343 EXPECT_TRUE(destination.ParseFromString(data));
344 TestUtil::ExpectPackedFieldsSet(destination);
347 TEST(ExtensionSetTest, Parsing) {
348 // Serialize as TestAllTypes and parse as TestAllExtensions.
349 unittest::TestAllTypes source;
350 unittest::TestAllExtensions destination;
353 TestUtil::SetAllFields(&source);
354 source.SerializeToString(&data);
355 EXPECT_TRUE(destination.ParseFromString(data));
356 TestUtil::ExpectAllExtensionsSet(destination);
359 TEST(ExtensionSetTest, PackedParsing) {
360 // Serialize as TestPackedTypes and parse as TestPackedExtensions.
361 unittest::TestPackedTypes source;
362 unittest::TestPackedExtensions destination;
365 TestUtil::SetPackedFields(&source);
366 source.SerializeToString(&data);
367 EXPECT_TRUE(destination.ParseFromString(data));
368 TestUtil::ExpectPackedExtensionsSet(destination);
371 TEST(ExtensionSetTest, IsInitialized) {
372 // Test that IsInitialized() returns false if required fields in nested
373 // extensions are missing.
374 unittest::TestAllExtensions message;
376 EXPECT_TRUE(message.IsInitialized());
378 message.MutableExtension(unittest::TestRequired::single);
379 EXPECT_FALSE(message.IsInitialized());
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());
388 message.AddExtension(unittest::TestRequired::multi);
389 EXPECT_FALSE(message.IsInitialized());
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());
399 TEST(ExtensionSetTest, MutableString) {
400 // Test the mutable string accessors.
401 unittest::TestAllExtensions message;
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));
407 message.AddExtension(unittest::repeated_string_extension)->assign("bar");
408 ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_string_extension));
410 message.GetExtension(unittest::repeated_string_extension, 0));
413 TEST(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) \
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()); \
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
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());
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());
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;
466 message.MutableExtension(unittest::optional_foreign_message_extension)->
468 int min_expected_size = base_size + foreign.SpaceUsed();
469 EXPECT_LE(min_expected_size, message.SpaceUsed());
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.
476 // - Adds a value to the repeated extension, then clears it, establishing
478 // - Adds a small number of values, testing that it doesn't increase the
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) \
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); \
498 int expected_size = sizeof(cpptype) * (16 - \
499 kMinRepeatedFieldAllocationSize) + empty_repeated_field_size; \
500 EXPECT_EQ(expected_size, message.SpaceUsed()) << #type; \
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
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);
531 min_expected_size += (sizeof(value) + value.size()) *
532 (16 - kMinRepeatedFieldAllocationSize);
533 EXPECT_LE(min_expected_size, message.SpaceUsed());
537 unittest::TestAllExtensions message;
538 const int base_size = message.SpaceUsed();
539 int min_expected_size = sizeof(RepeatedPtrField<unittest::ForeignMessage>) +
541 unittest::ForeignMessage prototype;
543 for (int i = 0; i < 16; ++i) {
544 message.AddExtension(unittest::repeated_foreign_message_extension)->
548 (16 - kMinRepeatedFieldAllocationSize) * prototype.SpaceUsed();
549 EXPECT_LE(min_expected_size, message.SpaceUsed());
553 #ifdef PROTOBUF_HAS_DEATH_TEST
555 TEST(ExtensionSetTest, InvalidEnumDeath) {
556 unittest::TestAllExtensions message;
558 message.SetExtension(unittest::optional_foreign_enum_extension,
559 static_cast<unittest::ForeignEnum>(53)),
563 #endif // PROTOBUF_HAS_DEATH_TEST
565 TEST(ExtensionSetTest, DynamicExtensions) {
566 // Test adding a dynamic extension to a compiled-in message object.
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");
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());
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());
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.");
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);
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.
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);
631 // Also add some unknown fields.
633 // An unknown enum value (for a known field).
634 message.mutable_unknown_fields()->AddVarint(
635 unittest::TestDynamicExtensions::kDynamicEnumExtensionFieldNumber,
637 // A regular unknown field.
638 message.mutable_unknown_fields()->AddLengthDelimited(54321, "unknown");
640 message.SerializeToString(&data);
643 // Now we can parse this using our dynamic extension definitions...
644 unittest::TestAllExtensions message;
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());
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"
661 "[dynamic_extensions.dynamic_message_extension] {\n"
662 " dynamic_field: 789\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"
671 "54321: \"unknown\"\n",
672 message.DebugString());
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);
679 // What if we parse using the reflection-based parser?
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());
690 // Are the embedded generated types actually using the generated objects?
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);
701 dynamic_cast<const unittest::ForeignMessage*>(&sub_message);
703 ASSERT_TRUE(typed_sub_message != NULL);
704 EXPECT_EQ(456, typed_sub_message->c());
707 // What does GetMessage() return for the embedded dynamic type if it isn't
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,
717 const Message* prototype =
718 dynamic_factory.GetPrototype(dynamic_message_extension->message_type());
719 EXPECT_EQ(prototype, &sub_message);
724 } // namespace internal
725 } // namespace protobuf
726 } // namespace google