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