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 protobuf_unittest.UnittestProto.ForeignMessage; 34 import protobuf_unittest.UnittestProto.TestAllExtensions; 35 import protobuf_unittest.UnittestProto.TestAllTypes; 36 import protobuf_unittest.UnittestProto.TestRequired; 37 import protobuf_unittest.UnittestProto.TestRequiredForeign; 38 import java.util.List; 39 import junit.framework.TestCase; 40 41 /** 42 * Misc. unit tests for message operations that apply to both generated and dynamic messages. 43 * 44 * @author kenton@google.com Kenton Varda 45 */ 46 public class MessageTest extends TestCase { 47 // ================================================================= 48 // Message-merging tests. 49 50 static final TestAllTypes MERGE_SOURCE = 51 TestAllTypes.newBuilder() 52 .setOptionalInt32(1) 53 .setOptionalString("foo") 54 .setOptionalForeignMessage(ForeignMessage.getDefaultInstance()) 55 .addRepeatedString("bar") 56 .build(); 57 58 static final TestAllTypes MERGE_DEST = 59 TestAllTypes.newBuilder() 60 .setOptionalInt64(2) 61 .setOptionalString("baz") 62 .setOptionalForeignMessage(ForeignMessage.newBuilder().setC(3).build()) 63 .addRepeatedString("qux") 64 .build(); 65 66 static final String MERGE_RESULT_TEXT = 67 "" 68 + "optional_int32: 1\n" 69 + "optional_int64: 2\n" 70 + "optional_string: \"foo\"\n" 71 + "optional_foreign_message {\n" 72 + " c: 3\n" 73 + "}\n" 74 + "repeated_string: \"qux\"\n" 75 + "repeated_string: \"bar\"\n"; 76 testParsingWithNullExtensionRegistry()77 public void testParsingWithNullExtensionRegistry() throws Exception { 78 try { 79 TestAllTypes.parseFrom(new byte[] {}, null); 80 fail(); 81 } catch (NullPointerException expected) { 82 } 83 } 84 testMergeFrom()85 public void testMergeFrom() throws Exception { 86 TestAllTypes result = TestAllTypes.newBuilder(MERGE_DEST).mergeFrom(MERGE_SOURCE).build(); 87 88 assertEquals(MERGE_RESULT_TEXT, result.toString()); 89 } 90 91 /** 92 * Test merging a DynamicMessage into a GeneratedMessage. As long as they have the same 93 * descriptor, this should work, but it is an entirely different code path. 94 */ testMergeFromDynamic()95 public void testMergeFromDynamic() throws Exception { 96 TestAllTypes result = 97 TestAllTypes.newBuilder(MERGE_DEST) 98 .mergeFrom(DynamicMessage.newBuilder(MERGE_SOURCE).build()) 99 .build(); 100 101 assertEquals(MERGE_RESULT_TEXT, result.toString()); 102 } 103 104 /** Test merging two DynamicMessages. */ testDynamicMergeFrom()105 public void testDynamicMergeFrom() throws Exception { 106 DynamicMessage result = 107 DynamicMessage.newBuilder(MERGE_DEST) 108 .mergeFrom(DynamicMessage.newBuilder(MERGE_SOURCE).build()) 109 .build(); 110 111 assertEquals(MERGE_RESULT_TEXT, result.toString()); 112 } 113 114 // ================================================================= 115 // Required-field-related tests. 116 117 private static final TestRequired TEST_REQUIRED_UNINITIALIZED = TestRequired.getDefaultInstance(); 118 private static final TestRequired TEST_REQUIRED_INITIALIZED = 119 TestRequired.newBuilder().setA(1).setB(2).setC(3).build(); 120 testRequired()121 public void testRequired() throws Exception { 122 TestRequired.Builder builder = TestRequired.newBuilder(); 123 124 assertFalse(builder.isInitialized()); 125 builder.setA(1); 126 assertFalse(builder.isInitialized()); 127 builder.setB(1); 128 assertFalse(builder.isInitialized()); 129 builder.setC(1); 130 assertTrue(builder.isInitialized()); 131 } 132 testRequiredForeign()133 public void testRequiredForeign() throws Exception { 134 TestRequiredForeign.Builder builder = TestRequiredForeign.newBuilder(); 135 136 assertTrue(builder.isInitialized()); 137 138 builder.setOptionalMessage(TEST_REQUIRED_UNINITIALIZED); 139 assertFalse(builder.isInitialized()); 140 141 builder.setOptionalMessage(TEST_REQUIRED_INITIALIZED); 142 assertTrue(builder.isInitialized()); 143 144 builder.addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED); 145 assertFalse(builder.isInitialized()); 146 147 builder.setRepeatedMessage(0, TEST_REQUIRED_INITIALIZED); 148 assertTrue(builder.isInitialized()); 149 } 150 testRequiredExtension()151 public void testRequiredExtension() throws Exception { 152 TestAllExtensions.Builder builder = TestAllExtensions.newBuilder(); 153 154 assertTrue(builder.isInitialized()); 155 156 builder.setExtension(TestRequired.single, TEST_REQUIRED_UNINITIALIZED); 157 assertFalse(builder.isInitialized()); 158 159 builder.setExtension(TestRequired.single, TEST_REQUIRED_INITIALIZED); 160 assertTrue(builder.isInitialized()); 161 162 builder.addExtension(TestRequired.multi, TEST_REQUIRED_UNINITIALIZED); 163 assertFalse(builder.isInitialized()); 164 165 builder.setExtension(TestRequired.multi, 0, TEST_REQUIRED_INITIALIZED); 166 assertTrue(builder.isInitialized()); 167 } 168 testRequiredDynamic()169 public void testRequiredDynamic() throws Exception { 170 Descriptors.Descriptor descriptor = TestRequired.getDescriptor(); 171 DynamicMessage.Builder builder = DynamicMessage.newBuilder(descriptor); 172 173 assertFalse(builder.isInitialized()); 174 builder.setField(descriptor.findFieldByName("a"), 1); 175 assertFalse(builder.isInitialized()); 176 builder.setField(descriptor.findFieldByName("b"), 1); 177 assertFalse(builder.isInitialized()); 178 builder.setField(descriptor.findFieldByName("c"), 1); 179 assertTrue(builder.isInitialized()); 180 } 181 testRequiredDynamicForeign()182 public void testRequiredDynamicForeign() throws Exception { 183 Descriptors.Descriptor descriptor = TestRequiredForeign.getDescriptor(); 184 DynamicMessage.Builder builder = DynamicMessage.newBuilder(descriptor); 185 186 assertTrue(builder.isInitialized()); 187 188 builder.setField(descriptor.findFieldByName("optional_message"), TEST_REQUIRED_UNINITIALIZED); 189 assertFalse(builder.isInitialized()); 190 191 builder.setField(descriptor.findFieldByName("optional_message"), TEST_REQUIRED_INITIALIZED); 192 assertTrue(builder.isInitialized()); 193 194 builder.addRepeatedField( 195 descriptor.findFieldByName("repeated_message"), TEST_REQUIRED_UNINITIALIZED); 196 assertFalse(builder.isInitialized()); 197 198 builder.setRepeatedField( 199 descriptor.findFieldByName("repeated_message"), 0, TEST_REQUIRED_INITIALIZED); 200 assertTrue(builder.isInitialized()); 201 } 202 testUninitializedException()203 public void testUninitializedException() throws Exception { 204 try { 205 TestRequired.newBuilder().build(); 206 fail("Should have thrown an exception."); 207 } catch (UninitializedMessageException e) { 208 assertEquals("Message missing required fields: a, b, c", e.getMessage()); 209 } 210 } 211 testBuildPartial()212 public void testBuildPartial() throws Exception { 213 // We're mostly testing that no exception is thrown. 214 TestRequired message = TestRequired.newBuilder().buildPartial(); 215 assertFalse(message.isInitialized()); 216 } 217 testNestedUninitializedException()218 public void testNestedUninitializedException() throws Exception { 219 try { 220 TestRequiredForeign.newBuilder() 221 .setOptionalMessage(TEST_REQUIRED_UNINITIALIZED) 222 .addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED) 223 .addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED) 224 .build(); 225 fail("Should have thrown an exception."); 226 } catch (UninitializedMessageException e) { 227 assertEquals( 228 "Message missing required fields: " 229 + "optional_message.a, " 230 + "optional_message.b, " 231 + "optional_message.c, " 232 + "repeated_message[0].a, " 233 + "repeated_message[0].b, " 234 + "repeated_message[0].c, " 235 + "repeated_message[1].a, " 236 + "repeated_message[1].b, " 237 + "repeated_message[1].c", 238 e.getMessage()); 239 } 240 } 241 testBuildNestedPartial()242 public void testBuildNestedPartial() throws Exception { 243 // We're mostly testing that no exception is thrown. 244 TestRequiredForeign message = 245 TestRequiredForeign.newBuilder() 246 .setOptionalMessage(TEST_REQUIRED_UNINITIALIZED) 247 .addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED) 248 .addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED) 249 .buildPartial(); 250 assertFalse(message.isInitialized()); 251 } 252 testParseUnititialized()253 public void testParseUnititialized() throws Exception { 254 try { 255 TestRequired.parseFrom(ByteString.EMPTY); 256 fail("Should have thrown an exception."); 257 } catch (InvalidProtocolBufferException e) { 258 assertEquals("Message missing required fields: a, b, c", e.getMessage()); 259 } 260 } 261 testParseNestedUnititialized()262 public void testParseNestedUnititialized() throws Exception { 263 ByteString data = 264 TestRequiredForeign.newBuilder() 265 .setOptionalMessage(TEST_REQUIRED_UNINITIALIZED) 266 .addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED) 267 .addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED) 268 .buildPartial() 269 .toByteString(); 270 271 try { 272 TestRequiredForeign.parseFrom(data); 273 fail("Should have thrown an exception."); 274 } catch (InvalidProtocolBufferException e) { 275 assertEquals( 276 "Message missing required fields: " 277 + "optional_message.a, " 278 + "optional_message.b, " 279 + "optional_message.c, " 280 + "repeated_message[0].a, " 281 + "repeated_message[0].b, " 282 + "repeated_message[0].c, " 283 + "repeated_message[1].a, " 284 + "repeated_message[1].b, " 285 + "repeated_message[1].c", 286 e.getMessage()); 287 } 288 } 289 testDynamicUninitializedException()290 public void testDynamicUninitializedException() throws Exception { 291 try { 292 DynamicMessage.newBuilder(TestRequired.getDescriptor()).build(); 293 fail("Should have thrown an exception."); 294 } catch (UninitializedMessageException e) { 295 assertEquals("Message missing required fields: a, b, c", e.getMessage()); 296 } 297 } 298 testDynamicBuildPartial()299 public void testDynamicBuildPartial() throws Exception { 300 // We're mostly testing that no exception is thrown. 301 DynamicMessage message = DynamicMessage.newBuilder(TestRequired.getDescriptor()).buildPartial(); 302 assertFalse(message.isInitialized()); 303 } 304 testDynamicParseUnititialized()305 public void testDynamicParseUnititialized() throws Exception { 306 try { 307 Descriptors.Descriptor descriptor = TestRequired.getDescriptor(); 308 DynamicMessage.parseFrom(descriptor, ByteString.EMPTY); 309 fail("Should have thrown an exception."); 310 } catch (InvalidProtocolBufferException e) { 311 assertEquals("Message missing required fields: a, b, c", e.getMessage()); 312 } 313 } 314 315 /** Test reading unset repeated message from DynamicMessage. */ testDynamicRepeatedMessageNull()316 public void testDynamicRepeatedMessageNull() throws Exception { 317 TestRequired.getDescriptor(); 318 DynamicMessage result = 319 DynamicMessage.newBuilder(TestAllTypes.getDescriptor()) 320 .mergeFrom(DynamicMessage.newBuilder(MERGE_SOURCE).build()) 321 .build(); 322 323 assertTrue( 324 result.getField(result.getDescriptorForType().findFieldByName("repeated_foreign_message")) 325 instanceof List<?>); 326 assertEquals( 327 0, 328 result.getRepeatedFieldCount( 329 result.getDescriptorForType().findFieldByName("repeated_foreign_message"))); 330 } 331 332 /** Test reading repeated message from DynamicMessage. */ testDynamicRepeatedMessageNotNull()333 public void testDynamicRepeatedMessageNotNull() throws Exception { 334 TestAllTypes repeatedNested = 335 TestAllTypes.newBuilder() 336 .setOptionalInt32(1) 337 .setOptionalString("foo") 338 .setOptionalForeignMessage(ForeignMessage.getDefaultInstance()) 339 .addRepeatedString("bar") 340 .addRepeatedForeignMessage(ForeignMessage.getDefaultInstance()) 341 .addRepeatedForeignMessage(ForeignMessage.getDefaultInstance()) 342 .build(); 343 TestRequired.getDescriptor(); 344 DynamicMessage result = 345 DynamicMessage.newBuilder(TestAllTypes.getDescriptor()) 346 .mergeFrom(DynamicMessage.newBuilder(repeatedNested).build()) 347 .build(); 348 349 assertTrue( 350 result.getField(result.getDescriptorForType().findFieldByName("repeated_foreign_message")) 351 instanceof List<?>); 352 assertEquals( 353 2, 354 result.getRepeatedFieldCount( 355 result.getDescriptorForType().findFieldByName("repeated_foreign_message"))); 356 } 357 } 358