1 // Protocol Buffers - Google's data interchange format 2 // Copyright 2008 Google Inc. All rights reserved. 3 // https://developers.google.com/protocol-buffers/ 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 package com.google.protobuf; 32 33 import com.google.protobuf.Descriptors.EnumDescriptor; 34 import com.google.protobuf.Descriptors.FieldDescriptor; 35 import com.google.protobuf.Descriptors.OneofDescriptor; 36 import protobuf_unittest.UnittestProto.TestAllExtensions; 37 import protobuf_unittest.UnittestProto.TestAllTypes; 38 import protobuf_unittest.UnittestProto.TestEmptyMessage; 39 import protobuf_unittest.UnittestProto.TestPackedTypes; 40 41 import junit.framework.TestCase; 42 43 import java.util.Arrays; 44 45 /** 46 * Unit test for {@link DynamicMessage}. See also {@link MessageTest}, which 47 * tests some {@link DynamicMessage} functionality. 48 * 49 * @author kenton@google.com Kenton Varda 50 */ 51 public class DynamicMessageTest extends TestCase { 52 TestUtil.ReflectionTester reflectionTester = 53 new TestUtil.ReflectionTester(TestAllTypes.getDescriptor(), null); 54 55 TestUtil.ReflectionTester extensionsReflectionTester = 56 new TestUtil.ReflectionTester(TestAllExtensions.getDescriptor(), 57 TestUtil.getExtensionRegistry()); 58 TestUtil.ReflectionTester packedReflectionTester = 59 new TestUtil.ReflectionTester(TestPackedTypes.getDescriptor(), null); 60 testDynamicMessageAccessors()61 public void testDynamicMessageAccessors() throws Exception { 62 Message.Builder builder = 63 DynamicMessage.newBuilder(TestAllTypes.getDescriptor()); 64 reflectionTester.setAllFieldsViaReflection(builder); 65 Message message = builder.build(); 66 reflectionTester.assertAllFieldsSetViaReflection(message); 67 } 68 testSettersAfterBuild()69 public void testSettersAfterBuild() throws Exception { 70 Message.Builder builder = 71 DynamicMessage.newBuilder(TestAllTypes.getDescriptor()); 72 Message firstMessage = builder.build(); 73 // double build() 74 builder.build(); 75 // clear() after build() 76 builder.clear(); 77 // setters after build() 78 reflectionTester.setAllFieldsViaReflection(builder); 79 Message message = builder.build(); 80 reflectionTester.assertAllFieldsSetViaReflection(message); 81 // repeated setters after build() 82 reflectionTester.modifyRepeatedFieldsViaReflection(builder); 83 message = builder.build(); 84 reflectionTester.assertRepeatedFieldsModifiedViaReflection(message); 85 // firstMessage shouldn't have been modified. 86 reflectionTester.assertClearViaReflection(firstMessage); 87 } 88 testUnknownFields()89 public void testUnknownFields() throws Exception { 90 Message.Builder builder = 91 DynamicMessage.newBuilder(TestEmptyMessage.getDescriptor()); 92 builder.setUnknownFields(UnknownFieldSet.newBuilder() 93 .addField(1, UnknownFieldSet.Field.newBuilder().addVarint(1).build()) 94 .addField(2, UnknownFieldSet.Field.newBuilder().addFixed32(1).build()) 95 .build()); 96 Message message = builder.build(); 97 assertEquals(2, message.getUnknownFields().asMap().size()); 98 // clone() with unknown fields 99 Message.Builder newBuilder = builder.clone(); 100 assertEquals(2, newBuilder.getUnknownFields().asMap().size()); 101 // clear() with unknown fields 102 newBuilder.clear(); 103 assertTrue(newBuilder.getUnknownFields().asMap().isEmpty()); 104 // serialize/parse with unknown fields 105 newBuilder.mergeFrom(message.toByteString()); 106 assertEquals(2, newBuilder.getUnknownFields().asMap().size()); 107 } 108 testDynamicMessageSettersRejectNull()109 public void testDynamicMessageSettersRejectNull() throws Exception { 110 Message.Builder builder = 111 DynamicMessage.newBuilder(TestAllTypes.getDescriptor()); 112 reflectionTester.assertReflectionSettersRejectNull(builder); 113 } 114 testDynamicMessageExtensionAccessors()115 public void testDynamicMessageExtensionAccessors() throws Exception { 116 // We don't need to extensively test DynamicMessage's handling of 117 // extensions because, frankly, it doesn't do anything special with them. 118 // It treats them just like any other fields. 119 Message.Builder builder = 120 DynamicMessage.newBuilder(TestAllExtensions.getDescriptor()); 121 extensionsReflectionTester.setAllFieldsViaReflection(builder); 122 Message message = builder.build(); 123 extensionsReflectionTester.assertAllFieldsSetViaReflection(message); 124 } 125 testDynamicMessageExtensionSettersRejectNull()126 public void testDynamicMessageExtensionSettersRejectNull() throws Exception { 127 Message.Builder builder = 128 DynamicMessage.newBuilder(TestAllExtensions.getDescriptor()); 129 extensionsReflectionTester.assertReflectionSettersRejectNull(builder); 130 } 131 testDynamicMessageRepeatedSetters()132 public void testDynamicMessageRepeatedSetters() throws Exception { 133 Message.Builder builder = 134 DynamicMessage.newBuilder(TestAllTypes.getDescriptor()); 135 reflectionTester.setAllFieldsViaReflection(builder); 136 reflectionTester.modifyRepeatedFieldsViaReflection(builder); 137 Message message = builder.build(); 138 reflectionTester.assertRepeatedFieldsModifiedViaReflection(message); 139 } 140 testDynamicMessageRepeatedSettersRejectNull()141 public void testDynamicMessageRepeatedSettersRejectNull() throws Exception { 142 Message.Builder builder = 143 DynamicMessage.newBuilder(TestAllTypes.getDescriptor()); 144 reflectionTester.assertReflectionRepeatedSettersRejectNull(builder); 145 } 146 testDynamicMessageDefaults()147 public void testDynamicMessageDefaults() throws Exception { 148 reflectionTester.assertClearViaReflection( 149 DynamicMessage.getDefaultInstance(TestAllTypes.getDescriptor())); 150 reflectionTester.assertClearViaReflection( 151 DynamicMessage.newBuilder(TestAllTypes.getDescriptor()).build()); 152 } 153 testDynamicMessageSerializedSize()154 public void testDynamicMessageSerializedSize() throws Exception { 155 TestAllTypes message = TestUtil.getAllSet(); 156 157 Message.Builder dynamicBuilder = 158 DynamicMessage.newBuilder(TestAllTypes.getDescriptor()); 159 reflectionTester.setAllFieldsViaReflection(dynamicBuilder); 160 Message dynamicMessage = dynamicBuilder.build(); 161 162 assertEquals(message.getSerializedSize(), 163 dynamicMessage.getSerializedSize()); 164 } 165 testDynamicMessageSerialization()166 public void testDynamicMessageSerialization() throws Exception { 167 Message.Builder builder = 168 DynamicMessage.newBuilder(TestAllTypes.getDescriptor()); 169 reflectionTester.setAllFieldsViaReflection(builder); 170 Message message = builder.build(); 171 172 ByteString rawBytes = message.toByteString(); 173 TestAllTypes message2 = TestAllTypes.parseFrom(rawBytes); 174 175 TestUtil.assertAllFieldsSet(message2); 176 177 // In fact, the serialized forms should be exactly the same, byte-for-byte. 178 assertEquals(TestUtil.getAllSet().toByteString(), rawBytes); 179 } 180 testDynamicMessageParsing()181 public void testDynamicMessageParsing() throws Exception { 182 TestAllTypes.Builder builder = TestAllTypes.newBuilder(); 183 TestUtil.setAllFields(builder); 184 TestAllTypes message = builder.build(); 185 186 ByteString rawBytes = message.toByteString(); 187 188 Message message2 = 189 DynamicMessage.parseFrom(TestAllTypes.getDescriptor(), rawBytes); 190 reflectionTester.assertAllFieldsSetViaReflection(message2); 191 192 // Test Parser interface. 193 Message message3 = message2.getParserForType().parseFrom(rawBytes); 194 reflectionTester.assertAllFieldsSetViaReflection(message3); 195 } 196 testDynamicMessageExtensionParsing()197 public void testDynamicMessageExtensionParsing() throws Exception { 198 ByteString rawBytes = TestUtil.getAllExtensionsSet().toByteString(); 199 Message message = DynamicMessage.parseFrom( 200 TestAllExtensions.getDescriptor(), rawBytes, 201 TestUtil.getExtensionRegistry()); 202 extensionsReflectionTester.assertAllFieldsSetViaReflection(message); 203 204 // Test Parser interface. 205 Message message2 = message.getParserForType().parseFrom( 206 rawBytes, TestUtil.getExtensionRegistry()); 207 extensionsReflectionTester.assertAllFieldsSetViaReflection(message2); 208 } 209 testDynamicMessagePackedSerialization()210 public void testDynamicMessagePackedSerialization() throws Exception { 211 Message.Builder builder = 212 DynamicMessage.newBuilder(TestPackedTypes.getDescriptor()); 213 packedReflectionTester.setPackedFieldsViaReflection(builder); 214 Message message = builder.build(); 215 216 ByteString rawBytes = message.toByteString(); 217 TestPackedTypes message2 = TestPackedTypes.parseFrom(rawBytes); 218 219 TestUtil.assertPackedFieldsSet(message2); 220 221 // In fact, the serialized forms should be exactly the same, byte-for-byte. 222 assertEquals(TestUtil.getPackedSet().toByteString(), rawBytes); 223 } 224 testDynamicMessagePackedParsing()225 public void testDynamicMessagePackedParsing() throws Exception { 226 TestPackedTypes.Builder builder = TestPackedTypes.newBuilder(); 227 TestUtil.setPackedFields(builder); 228 TestPackedTypes message = builder.build(); 229 230 ByteString rawBytes = message.toByteString(); 231 232 Message message2 = 233 DynamicMessage.parseFrom(TestPackedTypes.getDescriptor(), rawBytes); 234 packedReflectionTester.assertPackedFieldsSetViaReflection(message2); 235 236 // Test Parser interface. 237 Message message3 = message2.getParserForType().parseFrom(rawBytes); 238 packedReflectionTester.assertPackedFieldsSetViaReflection(message3); 239 } 240 testDynamicMessageCopy()241 public void testDynamicMessageCopy() throws Exception { 242 TestAllTypes.Builder builder = TestAllTypes.newBuilder(); 243 TestUtil.setAllFields(builder); 244 TestAllTypes message = builder.build(); 245 246 DynamicMessage copy = DynamicMessage.newBuilder(message).build(); 247 reflectionTester.assertAllFieldsSetViaReflection(copy); 248 249 // Test oneof behavior 250 FieldDescriptor bytesField = 251 TestAllTypes.getDescriptor().findFieldByName("oneof_bytes"); 252 FieldDescriptor uint32Field = 253 TestAllTypes.getDescriptor().findFieldByName("oneof_uint32"); 254 assertTrue(copy.hasField(bytesField)); 255 assertFalse(copy.hasField(uint32Field)); 256 DynamicMessage copy2 = 257 DynamicMessage.newBuilder(message).setField(uint32Field, 123).build(); 258 assertFalse(copy2.hasField(bytesField)); 259 assertTrue(copy2.hasField(uint32Field)); 260 assertEquals(123, copy2.getField(uint32Field)); 261 } 262 testToBuilder()263 public void testToBuilder() throws Exception { 264 DynamicMessage.Builder builder = 265 DynamicMessage.newBuilder(TestAllTypes.getDescriptor()); 266 reflectionTester.setAllFieldsViaReflection(builder); 267 int unknownFieldNum = 9; 268 long unknownFieldVal = 90; 269 builder.setUnknownFields(UnknownFieldSet.newBuilder() 270 .addField(unknownFieldNum, 271 UnknownFieldSet.Field.newBuilder() 272 .addVarint(unknownFieldVal).build()) 273 .build()); 274 DynamicMessage message = builder.build(); 275 276 DynamicMessage derived = message.toBuilder().build(); 277 reflectionTester.assertAllFieldsSetViaReflection(derived); 278 assertEquals(Arrays.asList(unknownFieldVal), 279 derived.getUnknownFields().getField(unknownFieldNum).getVarintList()); 280 } 281 testDynamicOneofMessage()282 public void testDynamicOneofMessage() throws Exception { 283 DynamicMessage.Builder builder = 284 DynamicMessage.newBuilder(TestAllTypes.getDescriptor()); 285 OneofDescriptor oneof = TestAllTypes.getDescriptor().getOneofs().get(0); 286 assertFalse(builder.hasOneof(oneof)); 287 assertSame(null, builder.getOneofFieldDescriptor(oneof)); 288 289 reflectionTester.setAllFieldsViaReflection(builder); 290 assertTrue(builder.hasOneof(oneof)); 291 FieldDescriptor field = oneof.getField(3); 292 assertSame(field, builder.getOneofFieldDescriptor(oneof)); 293 294 DynamicMessage message = builder.buildPartial(); 295 assertTrue(message.hasOneof(oneof)); 296 297 DynamicMessage.Builder mergedBuilder = 298 DynamicMessage.newBuilder(TestAllTypes.getDescriptor()); 299 FieldDescriptor mergedField = oneof.getField(0); 300 mergedBuilder.setField(mergedField, 123); 301 assertTrue(mergedBuilder.hasField(mergedField)); 302 mergedBuilder.mergeFrom(message); 303 assertTrue(mergedBuilder.hasField(field)); 304 assertFalse(mergedBuilder.hasField(mergedField)); 305 306 builder.clearOneof(oneof); 307 assertSame(null, builder.getOneofFieldDescriptor(oneof)); 308 message = builder.build(); 309 assertSame(null, message.getOneofFieldDescriptor(oneof)); 310 } 311 312 // Regression test for a bug that makes setField() not work for repeated 313 // enum fields. testSettersForRepeatedEnumField()314 public void testSettersForRepeatedEnumField() throws Exception { 315 DynamicMessage.Builder builder = 316 DynamicMessage.newBuilder(TestAllTypes.getDescriptor()); 317 FieldDescriptor repeatedEnumField = 318 TestAllTypes.getDescriptor().findFieldByName( 319 "repeated_nested_enum"); 320 EnumDescriptor enumDescriptor = TestAllTypes.NestedEnum.getDescriptor(); 321 builder.setField(repeatedEnumField, enumDescriptor.getValues()); 322 DynamicMessage message = builder.build(); 323 assertEquals( 324 enumDescriptor.getValues(), message.getField(repeatedEnumField)); 325 } 326 } 327