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