• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc.  All rights reserved.
3 //
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file or at
6 // https://developers.google.com/open-source/licenses/bsd
7 
8 package com.google.protobuf;
9 
10 import static com.google.common.truth.Truth.assertThat;
11 import static org.junit.Assert.assertThrows;
12 
13 import com.google.protobuf.Descriptors.EnumDescriptor;
14 import com.google.protobuf.Descriptors.FieldDescriptor;
15 import com.google.protobuf.Descriptors.OneofDescriptor;
16 import dynamicmessagetest.DynamicMessageTestProto.EmptyMessage;
17 import dynamicmessagetest.DynamicMessageTestProto.MessageWithMapFields;
18 import protobuf_unittest.UnittestMset.TestMessageSetExtension2;
19 import protobuf_unittest.UnittestProto;
20 import protobuf_unittest.UnittestProto.TestAllExtensions;
21 import protobuf_unittest.UnittestProto.TestAllTypes;
22 import protobuf_unittest.UnittestProto.TestAllTypes.NestedMessage;
23 import protobuf_unittest.UnittestProto.TestEmptyMessage;
24 import protobuf_unittest.UnittestProto.TestPackedTypes;
25 import proto2_wireformat_unittest.UnittestMsetWireFormat.TestMessageSet;
26 import java.util.ArrayList;
27 import org.junit.Test;
28 import org.junit.function.ThrowingRunnable;
29 import org.junit.runner.RunWith;
30 import org.junit.runners.JUnit4;
31 
32 /**
33  * Unit test for {@link DynamicMessage}. See also {@link MessageTest}, which tests some {@link
34  * DynamicMessage} functionality.
35  */
36 @RunWith(JUnit4.class)
37 public class DynamicMessageTest {
38   TestUtil.ReflectionTester reflectionTester =
39       new TestUtil.ReflectionTester(TestAllTypes.getDescriptor(), null);
40 
41   TestUtil.ReflectionTester extensionsReflectionTester =
42       new TestUtil.ReflectionTester(
43           TestAllExtensions.getDescriptor(), TestUtil.getFullExtensionRegistry());
44   TestUtil.ReflectionTester packedReflectionTester =
45       new TestUtil.ReflectionTester(TestPackedTypes.getDescriptor(), null);
46 
47   @Test
testDynamicMessageAccessors()48   public void testDynamicMessageAccessors() throws Exception {
49     Message.Builder builder = DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
50     reflectionTester.setAllFieldsViaReflection(builder);
51     Message message = builder.build();
52     reflectionTester.assertAllFieldsSetViaReflection(message);
53   }
54 
55   @Test
testSettersAfterBuild()56   public void testSettersAfterBuild() throws Exception {
57     Message.Builder builder = DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
58     Message firstMessage = builder.build();
59     // double build()
60     Message unused = builder.build();
61     // clear() after build()
62     builder.clear();
63     // setters after build()
64     reflectionTester.setAllFieldsViaReflection(builder);
65     Message message = builder.build();
66     reflectionTester.assertAllFieldsSetViaReflection(message);
67     // repeated setters after build()
68     reflectionTester.modifyRepeatedFieldsViaReflection(builder);
69     message = builder.build();
70     reflectionTester.assertRepeatedFieldsModifiedViaReflection(message);
71     // firstMessage shouldn't have been modified.
72     reflectionTester.assertClearViaReflection(firstMessage);
73   }
74 
75   @Test
testUnknownFields()76   public void testUnknownFields() throws Exception {
77     Message.Builder builder = DynamicMessage.newBuilder(TestEmptyMessage.getDescriptor());
78     builder.setUnknownFields(
79         UnknownFieldSet.newBuilder()
80             .addField(1, UnknownFieldSet.Field.newBuilder().addVarint(1).build())
81             .addField(2, UnknownFieldSet.Field.newBuilder().addFixed32(1).build())
82             .build());
83     Message message = builder.build();
84     assertThat(builder.getUnknownFields().asMap()).hasSize(2);
85     // clone() with unknown fields
86     Message.Builder newBuilder = builder.clone();
87     assertThat(newBuilder.getUnknownFields().asMap()).hasSize(2);
88     // clear() with unknown fields
89     newBuilder.clear();
90     assertThat(newBuilder.getUnknownFields().asMap()).isEmpty();
91     // serialize/parse with unknown fields
92     newBuilder.mergeFrom(message.toByteString());
93     assertThat(newBuilder.getUnknownFields().asMap()).hasSize(2);
94   }
95 
96   @Test
testDynamicMessageSettersRejectNull()97   public void testDynamicMessageSettersRejectNull() throws Exception {
98     Message.Builder builder = DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
99     reflectionTester.assertReflectionSettersRejectNull(builder);
100   }
101 
102   @Test
testDynamicMessageExtensionAccessors()103   public void testDynamicMessageExtensionAccessors() throws Exception {
104     // We don't need to extensively test DynamicMessage's handling of
105     // extensions because, frankly, it doesn't do anything special with them.
106     // It treats them just like any other fields.
107     Message.Builder builder = DynamicMessage.newBuilder(TestAllExtensions.getDescriptor());
108     extensionsReflectionTester.setAllFieldsViaReflection(builder);
109     Message message = builder.build();
110     extensionsReflectionTester.assertAllFieldsSetViaReflection(message);
111   }
112 
113   @Test
testDynamicMessageExtensionSettersRejectNull()114   public void testDynamicMessageExtensionSettersRejectNull() throws Exception {
115     Message.Builder builder = DynamicMessage.newBuilder(TestAllExtensions.getDescriptor());
116     extensionsReflectionTester.assertReflectionSettersRejectNull(builder);
117   }
118 
119   @Test
testDynamicMessageRepeatedSetters()120   public void testDynamicMessageRepeatedSetters() throws Exception {
121     Message.Builder builder = DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
122     reflectionTester.setAllFieldsViaReflection(builder);
123     reflectionTester.modifyRepeatedFieldsViaReflection(builder);
124     Message message = builder.build();
125     reflectionTester.assertRepeatedFieldsModifiedViaReflection(message);
126   }
127 
128   @Test
testDynamicMessageRepeatedSettersRejectNull()129   public void testDynamicMessageRepeatedSettersRejectNull() throws Exception {
130     Message.Builder builder = DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
131     reflectionTester.assertReflectionRepeatedSettersRejectNull(builder);
132   }
133 
134   @Test
testDynamicMessageDefaults()135   public void testDynamicMessageDefaults() throws Exception {
136     reflectionTester.assertClearViaReflection(
137         DynamicMessage.getDefaultInstance(TestAllTypes.getDescriptor()));
138     reflectionTester.assertClearViaReflection(
139         DynamicMessage.newBuilder(TestAllTypes.getDescriptor()).build());
140   }
141 
142   @Test
testDynamicMessageSerializedSize()143   public void testDynamicMessageSerializedSize() throws Exception {
144     TestAllTypes message = TestUtil.getAllSet();
145 
146     Message.Builder dynamicBuilder = DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
147     reflectionTester.setAllFieldsViaReflection(dynamicBuilder);
148     Message dynamicMessage = dynamicBuilder.build();
149 
150     assertThat(message.getSerializedSize()).isEqualTo(dynamicMessage.getSerializedSize());
151   }
152 
153   @Test
testDynamicMessageSerialization()154   public void testDynamicMessageSerialization() throws Exception {
155     Message.Builder builder = DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
156     reflectionTester.setAllFieldsViaReflection(builder);
157     Message message = builder.build();
158 
159     ByteString rawBytes = message.toByteString();
160     TestAllTypes message2 = TestAllTypes.parseFrom(rawBytes);
161 
162     TestUtil.assertAllFieldsSet(message2);
163 
164     // In fact, the serialized forms should be exactly the same, byte-for-byte.
165     assertThat(rawBytes).isEqualTo(TestUtil.getAllSet().toByteString());
166   }
167 
168   @Test
testDynamicMessageParsing()169   public void testDynamicMessageParsing() throws Exception {
170     TestAllTypes.Builder builder = TestAllTypes.newBuilder();
171     TestUtil.setAllFields(builder);
172     TestAllTypes message = builder.build();
173 
174     ByteString rawBytes = message.toByteString();
175 
176     Message message2 = DynamicMessage.parseFrom(TestAllTypes.getDescriptor(), rawBytes);
177     reflectionTester.assertAllFieldsSetViaReflection(message2);
178 
179     // Test Parser interface.
180     Message message3 = message2.getParserForType().parseFrom(rawBytes);
181     reflectionTester.assertAllFieldsSetViaReflection(message3);
182   }
183 
184   @Test
testDynamicMessageExtensionParsing()185   public void testDynamicMessageExtensionParsing() throws Exception {
186     ByteString rawBytes = TestUtil.getAllExtensionsSet().toByteString();
187     Message message =
188         DynamicMessage.parseFrom(
189             TestAllExtensions.getDescriptor(), rawBytes, TestUtil.getFullExtensionRegistry());
190     extensionsReflectionTester.assertAllFieldsSetViaReflection(message);
191 
192     // Test Parser interface.
193     Message message2 =
194         message.getParserForType().parseFrom(rawBytes, TestUtil.getExtensionRegistry());
195     extensionsReflectionTester.assertAllFieldsSetViaReflection(message2);
196   }
197 
198   @Test
testDynamicMessagePackedSerialization()199   public void testDynamicMessagePackedSerialization() throws Exception {
200     Message.Builder builder = DynamicMessage.newBuilder(TestPackedTypes.getDescriptor());
201     packedReflectionTester.setPackedFieldsViaReflection(builder);
202     Message message = builder.build();
203 
204     ByteString rawBytes = message.toByteString();
205     TestPackedTypes message2 = TestPackedTypes.parseFrom(rawBytes);
206 
207     TestUtil.assertPackedFieldsSet(message2);
208 
209     // In fact, the serialized forms should be exactly the same, byte-for-byte.
210     assertThat(rawBytes).isEqualTo(TestUtil.getPackedSet().toByteString());
211   }
212 
213   @Test
testDynamicMessagePackedEmptySerialization()214   public void testDynamicMessagePackedEmptySerialization() throws Exception {
215     Message message =
216         DynamicMessage.newBuilder(TestPackedTypes.getDescriptor())
217             .setField(
218                 TestPackedTypes.getDescriptor()
219                     .findFieldByNumber(TestPackedTypes.PACKED_INT64_FIELD_NUMBER),
220                 new ArrayList<Long>())
221             .build();
222 
223     assertThat(message.toByteString()).isEqualTo(ByteString.EMPTY);
224   }
225 
226   @Test
testDynamicMessagePackedParsing()227   public void testDynamicMessagePackedParsing() throws Exception {
228     TestPackedTypes.Builder builder = TestPackedTypes.newBuilder();
229     TestUtil.setPackedFields(builder);
230     TestPackedTypes message = builder.build();
231 
232     ByteString rawBytes = message.toByteString();
233 
234     Message message2 = DynamicMessage.parseFrom(TestPackedTypes.getDescriptor(), rawBytes);
235     packedReflectionTester.assertPackedFieldsSetViaReflection(message2);
236 
237     // Test Parser interface.
238     Message message3 = message2.getParserForType().parseFrom(rawBytes);
239     packedReflectionTester.assertPackedFieldsSetViaReflection(message3);
240   }
241 
242   @Test
testGetBuilderForExtensionField()243   public void testGetBuilderForExtensionField() {
244     DynamicMessage.Builder builder = DynamicMessage.newBuilder(TestAllExtensions.getDescriptor());
245     Message.Builder fieldBuilder =
246         builder.newBuilderForField(UnittestProto.optionalNestedMessageExtension.getDescriptor());
247     final int expected = 7432;
248     FieldDescriptor field =
249         NestedMessage.getDescriptor().findFieldByNumber(NestedMessage.BB_FIELD_NUMBER);
250     fieldBuilder.setField(field, expected);
251     assertThat(fieldBuilder.build().getField(field)).isEqualTo(expected);
252   }
253 
254   @Test
testDynamicMessageCopy()255   public void testDynamicMessageCopy() throws Exception {
256     TestAllTypes.Builder builder = TestAllTypes.newBuilder();
257     TestUtil.setAllFields(builder);
258     TestAllTypes message = builder.build();
259 
260     DynamicMessage copy = DynamicMessage.newBuilder(message).build();
261     reflectionTester.assertAllFieldsSetViaReflection(copy);
262 
263     // Test oneof behavior
264     FieldDescriptor bytesField = TestAllTypes.getDescriptor().findFieldByName("oneof_bytes");
265     FieldDescriptor uint32Field = TestAllTypes.getDescriptor().findFieldByName("oneof_uint32");
266     assertThat(copy.hasField(bytesField)).isTrue();
267     assertThat(copy.hasField(uint32Field)).isFalse();
268     DynamicMessage copy2 = DynamicMessage.newBuilder(message).setField(uint32Field, 123).build();
269     assertThat(copy2.hasField(bytesField)).isFalse();
270     assertThat(copy2.hasField(uint32Field)).isTrue();
271     assertThat(copy2.getField(uint32Field)).isEqualTo(123);
272   }
273 
274   @Test
testToBuilder()275   public void testToBuilder() throws Exception {
276     DynamicMessage.Builder builder = DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
277     reflectionTester.setAllFieldsViaReflection(builder);
278     int unknownFieldNum = 9;
279     long unknownFieldVal = 90;
280     builder.setUnknownFields(
281         UnknownFieldSet.newBuilder()
282             .addField(
283                 unknownFieldNum,
284                 UnknownFieldSet.Field.newBuilder().addVarint(unknownFieldVal).build())
285             .build());
286     DynamicMessage message = builder.build();
287 
288     DynamicMessage derived = message.toBuilder().build();
289     reflectionTester.assertAllFieldsSetViaReflection(derived);
290     assertThat(derived.getUnknownFields().getField(unknownFieldNum).getVarintList())
291         .containsExactly(unknownFieldVal);
292   }
293 
294   @Test
testDynamicOneofMessage()295   public void testDynamicOneofMessage() throws Exception {
296     DynamicMessage.Builder builder = DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
297     OneofDescriptor oneof = TestAllTypes.getDescriptor().getOneofs().get(0);
298     assertThat(builder.hasOneof(oneof)).isFalse();
299     assertThat(builder.getOneofFieldDescriptor(oneof)).isNull();
300 
301     reflectionTester.setAllFieldsViaReflection(builder);
302     assertThat(builder.hasOneof(oneof)).isTrue();
303     FieldDescriptor field = oneof.getField(3);
304     assertThat(builder.getOneofFieldDescriptor(oneof)).isSameInstanceAs(field);
305 
306     DynamicMessage message = builder.buildPartial();
307     assertThat(message.hasOneof(oneof)).isTrue();
308 
309     DynamicMessage.Builder mergedBuilder = DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
310     FieldDescriptor mergedField = oneof.getField(0);
311     mergedBuilder.setField(mergedField, 123);
312     assertThat(mergedBuilder.hasField(mergedField)).isTrue();
313     mergedBuilder.mergeFrom(message);
314     assertThat(mergedBuilder.hasField(field)).isTrue();
315     assertThat(mergedBuilder.hasField(mergedField)).isFalse();
316 
317     builder.clearOneof(oneof);
318     assertThat(builder.getOneofFieldDescriptor(oneof)).isNull();
319     message = builder.build();
320     assertThat(message.getOneofFieldDescriptor(oneof)).isNull();
321   }
322 
323   // Regression test for a bug that makes setField() not work for repeated
324   // enum fields.
325   @Test
testSettersForRepeatedEnumField()326   public void testSettersForRepeatedEnumField() throws Exception {
327     DynamicMessage.Builder builder = DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
328     FieldDescriptor repeatedEnumField =
329         TestAllTypes.getDescriptor().findFieldByName("repeated_nested_enum");
330     EnumDescriptor enumDescriptor = TestAllTypes.NestedEnum.getDescriptor();
331     builder.setField(repeatedEnumField, enumDescriptor.getValues());
332     DynamicMessage message = builder.build();
333     assertThat(message.getField(repeatedEnumField)).isEqualTo(enumDescriptor.getValues());
334   }
335 
336   @Test
testBuilderGetFieldBuilder_mapField_throwsUnsupportedOperationException()337   public void testBuilderGetFieldBuilder_mapField_throwsUnsupportedOperationException() {
338     final DynamicMessage.Builder builder =
339         DynamicMessage.newBuilder(MessageWithMapFields.getDescriptor());
340     final FieldDescriptor mapField =
341         MessageWithMapFields.getDescriptor().findFieldByName("string_message_map");
342 
343     Message.Builder entryBuilder = builder.newBuilderForField(mapField);
344     entryBuilder.setField(entryBuilder.getDescriptorForType().findFieldByNumber(1), "foo");
345     entryBuilder.setField(
346         entryBuilder.getDescriptorForType().findFieldByNumber(2),
347         EmptyMessage.getDefaultInstance());
348     builder.addRepeatedField(mapField, entryBuilder.build());
349 
350     assertThrows(
351         UnsupportedOperationException.class,
352         new ThrowingRunnable() {
353           @Override
354           public void run() throws Throwable {
355             builder.getFieldBuilder(mapField);
356           }
357         });
358   }
359 
360   @Test
testBuilderGetRepeatedFieldBuilder_mapField_throwsUnsupportedOperationException()361   public void testBuilderGetRepeatedFieldBuilder_mapField_throwsUnsupportedOperationException() {
362     final DynamicMessage.Builder builder =
363         DynamicMessage.newBuilder(MessageWithMapFields.getDescriptor());
364     final FieldDescriptor mapField =
365         MessageWithMapFields.getDescriptor().findFieldByName("string_message_map");
366 
367     Message.Builder entryBuilder = builder.newBuilderForField(mapField);
368     entryBuilder.setField(entryBuilder.getDescriptorForType().findFieldByNumber(1), "foo");
369     entryBuilder.setField(
370         entryBuilder.getDescriptorForType().findFieldByNumber(2),
371         EmptyMessage.getDefaultInstance());
372     builder.addRepeatedField(mapField, entryBuilder.build());
373 
374     assertThrows(
375         UnsupportedOperationException.class,
376         new ThrowingRunnable() {
377           @Override
378           public void run() throws Throwable {
379             builder.getFieldBuilder(mapField);
380           }
381         });
382   }
383 
384   @Test
serialize_lazyFieldInMessageSet()385   public void serialize_lazyFieldInMessageSet() throws Exception {
386     ExtensionRegistry extensionRegistry = ExtensionRegistry.newInstance();
387     extensionRegistry.add(TestMessageSetExtension2.messageSetExtension);
388     TestMessageSetExtension2 messageSetExtension =
389         TestMessageSetExtension2.newBuilder().setStr("foo").build();
390     // This is a valid serialization of the above message.
391     ByteString suboptimallySerializedMessageSetExtension =
392         messageSetExtension.toByteString().concat(messageSetExtension.toByteString());
393     DynamicMessage expectedMessage =
394         DynamicMessage.newBuilder(TestMessageSet.getDescriptor())
395             .setField(
396                 TestMessageSetExtension2.messageSetExtension.getDescriptor(), messageSetExtension)
397             .build();
398     // Constructed with a LazyField, for whom roundtripping the serialized form will shorten the
399     // encoded form.
400     // In particular, this checks matching between lazy field encoding size.
401     DynamicMessage complicatedlyBuiltMessage =
402         DynamicMessage.newBuilder(TestMessageSet.getDescriptor())
403             .setField(
404                 TestMessageSetExtension2.messageSetExtension.getDescriptor(),
405                 new LazyField(
406                     DynamicMessage.getDefaultInstance(TestMessageSetExtension2.getDescriptor()),
407                     extensionRegistry,
408                     suboptimallySerializedMessageSetExtension))
409             .build();
410 
411     DynamicMessage roundtrippedMessage =
412         DynamicMessage.newBuilder(TestMessageSet.getDescriptor())
413             .mergeFrom(complicatedlyBuiltMessage.toByteString(), extensionRegistry)
414             .build();
415 
416     assertThat(complicatedlyBuiltMessage).isEqualTo(expectedMessage);
417     assertThat(roundtrippedMessage).isEqualTo(expectedMessage);
418   }
419 }
420