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