| OLD | NEW |
| (Empty) |
| 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.test; | |
| 32 import com.google.protobuf.*; | |
| 33 | |
| 34 import com.google.protobuf.Descriptors.FieldDescriptor; | |
| 35 import protobuf_unittest.UnittestOptimizeFor.TestOptimizedForSize; | |
| 36 import protobuf_unittest.UnittestProto; | |
| 37 import protobuf_unittest.UnittestProto.ForeignMessage; | |
| 38 import protobuf_unittest.UnittestProto.TestAllExtensions; | |
| 39 import protobuf_unittest.UnittestProto.TestAllTypes; | |
| 40 import protobuf_unittest.UnittestProto.TestPackedTypes; | |
| 41 import protobuf_unittest.UnittestProto.TestRequired; | |
| 42 import protobuf_unittest.UnittestProto.TestRequiredForeign; | |
| 43 import protobuf_unittest.UnittestProto.TestUnpackedTypes; | |
| 44 | |
| 45 import junit.framework.TestCase; | |
| 46 | |
| 47 import java.util.Map; | |
| 48 | |
| 49 /** | |
| 50 * Unit test for {@link AbstractMessage}. | |
| 51 * | |
| 52 * @author kenton@google.com Kenton Varda | |
| 53 */ | |
| 54 public class AbstractMessageTest extends TestCase { | |
| 55 /** | |
| 56 * Extends AbstractMessage and wraps some other message object. The methods | |
| 57 * of the Message interface which aren't explicitly implemented by | |
| 58 * AbstractMessage are forwarded to the wrapped object. This allows us to | |
| 59 * test that AbstractMessage's implementations work even if the wrapped | |
| 60 * object does not use them. | |
| 61 */ | |
| 62 private static class AbstractMessageWrapper extends AbstractMessage { | |
| 63 private final Message wrappedMessage; | |
| 64 | |
| 65 public AbstractMessageWrapper(Message wrappedMessage) { | |
| 66 this.wrappedMessage = wrappedMessage; | |
| 67 } | |
| 68 | |
| 69 public Descriptors.Descriptor getDescriptorForType() { | |
| 70 return wrappedMessage.getDescriptorForType(); | |
| 71 } | |
| 72 public AbstractMessageWrapper getDefaultInstanceForType() { | |
| 73 return new AbstractMessageWrapper( | |
| 74 wrappedMessage.getDefaultInstanceForType()); | |
| 75 } | |
| 76 public Map<Descriptors.FieldDescriptor, Object> getAllFields() { | |
| 77 return wrappedMessage.getAllFields(); | |
| 78 } | |
| 79 public boolean hasField(Descriptors.FieldDescriptor field) { | |
| 80 return wrappedMessage.hasField(field); | |
| 81 } | |
| 82 public Object getField(Descriptors.FieldDescriptor field) { | |
| 83 return wrappedMessage.getField(field); | |
| 84 } | |
| 85 public int getRepeatedFieldCount(Descriptors.FieldDescriptor field) { | |
| 86 return wrappedMessage.getRepeatedFieldCount(field); | |
| 87 } | |
| 88 public Object getRepeatedField( | |
| 89 Descriptors.FieldDescriptor field, int index) { | |
| 90 return wrappedMessage.getRepeatedField(field, index); | |
| 91 } | |
| 92 public UnknownFieldSet getUnknownFields() { | |
| 93 return wrappedMessage.getUnknownFields(); | |
| 94 } | |
| 95 public Builder newBuilderForType() { | |
| 96 return new Builder(wrappedMessage.newBuilderForType()); | |
| 97 } | |
| 98 public Builder toBuilder() { | |
| 99 return new Builder(wrappedMessage.toBuilder()); | |
| 100 } | |
| 101 | |
| 102 static class Builder extends AbstractMessage.Builder<Builder> { | |
| 103 private final Message.Builder wrappedBuilder; | |
| 104 | |
| 105 public Builder(Message.Builder wrappedBuilder) { | |
| 106 this.wrappedBuilder = wrappedBuilder; | |
| 107 } | |
| 108 | |
| 109 public AbstractMessageWrapper build() { | |
| 110 return new AbstractMessageWrapper(wrappedBuilder.build()); | |
| 111 } | |
| 112 public AbstractMessageWrapper buildPartial() { | |
| 113 return new AbstractMessageWrapper(wrappedBuilder.buildPartial()); | |
| 114 } | |
| 115 public Builder clone() { | |
| 116 return new Builder(wrappedBuilder.clone()); | |
| 117 } | |
| 118 public boolean isInitialized() { | |
| 119 return clone().buildPartial().isInitialized(); | |
| 120 } | |
| 121 public Descriptors.Descriptor getDescriptorForType() { | |
| 122 return wrappedBuilder.getDescriptorForType(); | |
| 123 } | |
| 124 public AbstractMessageWrapper getDefaultInstanceForType() { | |
| 125 return new AbstractMessageWrapper( | |
| 126 wrappedBuilder.getDefaultInstanceForType()); | |
| 127 } | |
| 128 public Map<Descriptors.FieldDescriptor, Object> getAllFields() { | |
| 129 return wrappedBuilder.getAllFields(); | |
| 130 } | |
| 131 public Builder newBuilderForField(Descriptors.FieldDescriptor field) { | |
| 132 return new Builder(wrappedBuilder.newBuilderForField(field)); | |
| 133 } | |
| 134 public boolean hasField(Descriptors.FieldDescriptor field) { | |
| 135 return wrappedBuilder.hasField(field); | |
| 136 } | |
| 137 public Object getField(Descriptors.FieldDescriptor field) { | |
| 138 return wrappedBuilder.getField(field); | |
| 139 } | |
| 140 public Builder setField(Descriptors.FieldDescriptor field, Object value) { | |
| 141 wrappedBuilder.setField(field, value); | |
| 142 return this; | |
| 143 } | |
| 144 public Builder clearField(Descriptors.FieldDescriptor field) { | |
| 145 wrappedBuilder.clearField(field); | |
| 146 return this; | |
| 147 } | |
| 148 public int getRepeatedFieldCount(Descriptors.FieldDescriptor field) { | |
| 149 return wrappedBuilder.getRepeatedFieldCount(field); | |
| 150 } | |
| 151 public Object getRepeatedField( | |
| 152 Descriptors.FieldDescriptor field, int index) { | |
| 153 return wrappedBuilder.getRepeatedField(field, index); | |
| 154 } | |
| 155 public Builder setRepeatedField(Descriptors.FieldDescriptor field, | |
| 156 int index, Object value) { | |
| 157 wrappedBuilder.setRepeatedField(field, index, value); | |
| 158 return this; | |
| 159 } | |
| 160 public Builder addRepeatedField( | |
| 161 Descriptors.FieldDescriptor field, Object value) { | |
| 162 wrappedBuilder.addRepeatedField(field, value); | |
| 163 return this; | |
| 164 } | |
| 165 public UnknownFieldSet getUnknownFields() { | |
| 166 return wrappedBuilder.getUnknownFields(); | |
| 167 } | |
| 168 public Builder setUnknownFields(UnknownFieldSet unknownFields) { | |
| 169 wrappedBuilder.setUnknownFields(unknownFields); | |
| 170 return this; | |
| 171 } | |
| 172 @Override | |
| 173 public Message.Builder getFieldBuilder(FieldDescriptor field) { | |
| 174 return wrappedBuilder.getFieldBuilder(field); | |
| 175 } | |
| 176 } | |
| 177 public Parser<? extends Message> getParserForType() { | |
| 178 return wrappedMessage.getParserForType(); | |
| 179 } | |
| 180 } | |
| 181 | |
| 182 // ================================================================= | |
| 183 | |
| 184 TestUtil.ReflectionTester reflectionTester = | |
| 185 new TestUtil.ReflectionTester(TestAllTypes.getDescriptor(), null); | |
| 186 | |
| 187 TestUtil.ReflectionTester extensionsReflectionTester = | |
| 188 new TestUtil.ReflectionTester(TestAllExtensions.getDescriptor(), | |
| 189 TestUtil.getExtensionRegistry()); | |
| 190 | |
| 191 public void testClear() throws Exception { | |
| 192 AbstractMessageWrapper message = | |
| 193 new AbstractMessageWrapper.Builder( | |
| 194 TestAllTypes.newBuilder(TestUtil.getAllSet())) | |
| 195 .clear().build(); | |
| 196 TestUtil.assertClear((TestAllTypes) message.wrappedMessage); | |
| 197 } | |
| 198 | |
| 199 public void testCopy() throws Exception { | |
| 200 AbstractMessageWrapper message = | |
| 201 new AbstractMessageWrapper.Builder(TestAllTypes.newBuilder()) | |
| 202 .mergeFrom(TestUtil.getAllSet()).build(); | |
| 203 TestUtil.assertAllFieldsSet((TestAllTypes) message.wrappedMessage); | |
| 204 } | |
| 205 | |
| 206 public void testSerializedSize() throws Exception { | |
| 207 TestAllTypes message = TestUtil.getAllSet(); | |
| 208 Message abstractMessage = new AbstractMessageWrapper(TestUtil.getAllSet()); | |
| 209 | |
| 210 assertEquals(message.getSerializedSize(), | |
| 211 abstractMessage.getSerializedSize()); | |
| 212 } | |
| 213 | |
| 214 public void testSerialization() throws Exception { | |
| 215 Message abstractMessage = new AbstractMessageWrapper(TestUtil.getAllSet()); | |
| 216 | |
| 217 TestUtil.assertAllFieldsSet( | |
| 218 TestAllTypes.parseFrom(abstractMessage.toByteString())); | |
| 219 | |
| 220 assertEquals(TestUtil.getAllSet().toByteString(), | |
| 221 abstractMessage.toByteString()); | |
| 222 } | |
| 223 | |
| 224 public void testParsing() throws Exception { | |
| 225 AbstractMessageWrapper.Builder builder = | |
| 226 new AbstractMessageWrapper.Builder(TestAllTypes.newBuilder()); | |
| 227 AbstractMessageWrapper message = | |
| 228 builder.mergeFrom(TestUtil.getAllSet().toByteString()).build(); | |
| 229 TestUtil.assertAllFieldsSet((TestAllTypes) message.wrappedMessage); | |
| 230 } | |
| 231 | |
| 232 public void testParsingUninitialized() throws Exception { | |
| 233 TestRequiredForeign.Builder builder = TestRequiredForeign.newBuilder(); | |
| 234 builder.getOptionalMessageBuilder().setDummy2(10); | |
| 235 ByteString bytes = builder.buildPartial().toByteString(); | |
| 236 Message.Builder abstractMessageBuilder = | |
| 237 new AbstractMessageWrapper.Builder(TestRequiredForeign.newBuilder()); | |
| 238 // mergeFrom() should not throw initialization error. | |
| 239 abstractMessageBuilder.mergeFrom(bytes).buildPartial(); | |
| 240 try { | |
| 241 abstractMessageBuilder.mergeFrom(bytes).build(); | |
| 242 fail(); | |
| 243 } catch (UninitializedMessageException ex) { | |
| 244 // pass | |
| 245 } | |
| 246 | |
| 247 // test DynamicMessage directly. | |
| 248 Message.Builder dynamicMessageBuilder = DynamicMessage.newBuilder( | |
| 249 TestRequiredForeign.getDescriptor()); | |
| 250 // mergeFrom() should not throw initialization error. | |
| 251 dynamicMessageBuilder.mergeFrom(bytes).buildPartial(); | |
| 252 try { | |
| 253 dynamicMessageBuilder.mergeFrom(bytes).build(); | |
| 254 fail(); | |
| 255 } catch (UninitializedMessageException ex) { | |
| 256 // pass | |
| 257 } | |
| 258 } | |
| 259 | |
| 260 public void testPackedSerialization() throws Exception { | |
| 261 Message abstractMessage = | |
| 262 new AbstractMessageWrapper(TestUtil.getPackedSet()); | |
| 263 | |
| 264 TestUtil.assertPackedFieldsSet( | |
| 265 TestPackedTypes.parseFrom(abstractMessage.toByteString())); | |
| 266 | |
| 267 assertEquals(TestUtil.getPackedSet().toByteString(), | |
| 268 abstractMessage.toByteString()); | |
| 269 } | |
| 270 | |
| 271 public void testPackedParsing() throws Exception { | |
| 272 AbstractMessageWrapper.Builder builder = | |
| 273 new AbstractMessageWrapper.Builder(TestPackedTypes.newBuilder()); | |
| 274 AbstractMessageWrapper message = | |
| 275 builder.mergeFrom(TestUtil.getPackedSet().toByteString()).build(); | |
| 276 TestUtil.assertPackedFieldsSet((TestPackedTypes) message.wrappedMessage); | |
| 277 } | |
| 278 | |
| 279 public void testUnpackedSerialization() throws Exception { | |
| 280 Message abstractMessage = | |
| 281 new AbstractMessageWrapper(TestUtil.getUnpackedSet()); | |
| 282 | |
| 283 TestUtil.assertUnpackedFieldsSet( | |
| 284 TestUnpackedTypes.parseFrom(abstractMessage.toByteString())); | |
| 285 | |
| 286 assertEquals(TestUtil.getUnpackedSet().toByteString(), | |
| 287 abstractMessage.toByteString()); | |
| 288 } | |
| 289 | |
| 290 public void testParsePackedToUnpacked() throws Exception { | |
| 291 AbstractMessageWrapper.Builder builder = | |
| 292 new AbstractMessageWrapper.Builder(TestUnpackedTypes.newBuilder()); | |
| 293 AbstractMessageWrapper message = | |
| 294 builder.mergeFrom(TestUtil.getPackedSet().toByteString()).build(); | |
| 295 TestUtil.assertUnpackedFieldsSet( | |
| 296 (TestUnpackedTypes) message.wrappedMessage); | |
| 297 } | |
| 298 | |
| 299 public void testParseUnpackedToPacked() throws Exception { | |
| 300 AbstractMessageWrapper.Builder builder = | |
| 301 new AbstractMessageWrapper.Builder(TestPackedTypes.newBuilder()); | |
| 302 AbstractMessageWrapper message = | |
| 303 builder.mergeFrom(TestUtil.getUnpackedSet().toByteString()).build(); | |
| 304 TestUtil.assertPackedFieldsSet((TestPackedTypes) message.wrappedMessage); | |
| 305 } | |
| 306 | |
| 307 public void testUnpackedParsing() throws Exception { | |
| 308 AbstractMessageWrapper.Builder builder = | |
| 309 new AbstractMessageWrapper.Builder(TestUnpackedTypes.newBuilder()); | |
| 310 AbstractMessageWrapper message = | |
| 311 builder.mergeFrom(TestUtil.getUnpackedSet().toByteString()).build(); | |
| 312 TestUtil.assertUnpackedFieldsSet( | |
| 313 (TestUnpackedTypes) message.wrappedMessage); | |
| 314 } | |
| 315 | |
| 316 public void testOptimizedForSize() throws Exception { | |
| 317 // We're mostly only checking that this class was compiled successfully. | |
| 318 TestOptimizedForSize message = | |
| 319 TestOptimizedForSize.newBuilder().setI(1).build(); | |
| 320 message = TestOptimizedForSize.parseFrom(message.toByteString()); | |
| 321 assertEquals(2, message.getSerializedSize()); | |
| 322 } | |
| 323 | |
| 324 // ----------------------------------------------------------------- | |
| 325 // Tests for isInitialized(). | |
| 326 | |
| 327 private static final TestRequired TEST_REQUIRED_UNINITIALIZED = | |
| 328 TestRequired.getDefaultInstance(); | |
| 329 private static final TestRequired TEST_REQUIRED_INITIALIZED = | |
| 330 TestRequired.newBuilder().setA(1).setB(2).setC(3).build(); | |
| 331 | |
| 332 public void testIsInitialized() throws Exception { | |
| 333 TestRequired.Builder builder = TestRequired.newBuilder(); | |
| 334 AbstractMessageWrapper.Builder abstractBuilder = | |
| 335 new AbstractMessageWrapper.Builder(builder); | |
| 336 | |
| 337 assertFalse(abstractBuilder.isInitialized()); | |
| 338 assertEquals("a, b, c", abstractBuilder.getInitializationErrorString()); | |
| 339 builder.setA(1); | |
| 340 assertFalse(abstractBuilder.isInitialized()); | |
| 341 assertEquals("b, c", abstractBuilder.getInitializationErrorString()); | |
| 342 builder.setB(1); | |
| 343 assertFalse(abstractBuilder.isInitialized()); | |
| 344 assertEquals("c", abstractBuilder.getInitializationErrorString()); | |
| 345 builder.setC(1); | |
| 346 assertTrue(abstractBuilder.isInitialized()); | |
| 347 assertEquals("", abstractBuilder.getInitializationErrorString()); | |
| 348 } | |
| 349 | |
| 350 public void testForeignIsInitialized() throws Exception { | |
| 351 TestRequiredForeign.Builder builder = TestRequiredForeign.newBuilder(); | |
| 352 AbstractMessageWrapper.Builder abstractBuilder = | |
| 353 new AbstractMessageWrapper.Builder(builder); | |
| 354 | |
| 355 assertTrue(abstractBuilder.isInitialized()); | |
| 356 assertEquals("", abstractBuilder.getInitializationErrorString()); | |
| 357 | |
| 358 builder.setOptionalMessage(TEST_REQUIRED_UNINITIALIZED); | |
| 359 assertFalse(abstractBuilder.isInitialized()); | |
| 360 assertEquals( | |
| 361 "optional_message.a, optional_message.b, optional_message.c", | |
| 362 abstractBuilder.getInitializationErrorString()); | |
| 363 | |
| 364 builder.setOptionalMessage(TEST_REQUIRED_INITIALIZED); | |
| 365 assertTrue(abstractBuilder.isInitialized()); | |
| 366 assertEquals("", abstractBuilder.getInitializationErrorString()); | |
| 367 | |
| 368 builder.addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED); | |
| 369 assertFalse(abstractBuilder.isInitialized()); | |
| 370 assertEquals( | |
| 371 "repeated_message[0].a, repeated_message[0].b, repeated_message[0].c", | |
| 372 abstractBuilder.getInitializationErrorString()); | |
| 373 | |
| 374 builder.setRepeatedMessage(0, TEST_REQUIRED_INITIALIZED); | |
| 375 assertTrue(abstractBuilder.isInitialized()); | |
| 376 assertEquals("", abstractBuilder.getInitializationErrorString()); | |
| 377 } | |
| 378 | |
| 379 // ----------------------------------------------------------------- | |
| 380 // Tests for mergeFrom | |
| 381 | |
| 382 static final TestAllTypes MERGE_SOURCE = | |
| 383 TestAllTypes.newBuilder() | |
| 384 .setOptionalInt32(1) | |
| 385 .setOptionalString("foo") | |
| 386 .setOptionalForeignMessage(ForeignMessage.getDefaultInstance()) | |
| 387 .addRepeatedString("bar") | |
| 388 .build(); | |
| 389 | |
| 390 static final TestAllTypes MERGE_DEST = | |
| 391 TestAllTypes.newBuilder() | |
| 392 .setOptionalInt64(2) | |
| 393 .setOptionalString("baz") | |
| 394 .setOptionalForeignMessage(ForeignMessage.newBuilder().setC(3).build()) | |
| 395 .addRepeatedString("qux") | |
| 396 .build(); | |
| 397 | |
| 398 static final String MERGE_RESULT_TEXT = | |
| 399 "optional_int32: 1\n" + | |
| 400 "optional_int64: 2\n" + | |
| 401 "optional_string: \"foo\"\n" + | |
| 402 "optional_foreign_message {\n" + | |
| 403 " c: 3\n" + | |
| 404 "}\n" + | |
| 405 "repeated_string: \"qux\"\n" + | |
| 406 "repeated_string: \"bar\"\n"; | |
| 407 | |
| 408 public void testMergeFrom() throws Exception { | |
| 409 AbstractMessageWrapper result = | |
| 410 new AbstractMessageWrapper.Builder( | |
| 411 TestAllTypes.newBuilder(MERGE_DEST)) | |
| 412 .mergeFrom(MERGE_SOURCE).build(); | |
| 413 | |
| 414 assertEquals(MERGE_RESULT_TEXT, result.toString()); | |
| 415 } | |
| 416 | |
| 417 // ----------------------------------------------------------------- | |
| 418 // Tests for equals and hashCode | |
| 419 | |
| 420 public void testEqualsAndHashCode() throws Exception { | |
| 421 TestAllTypes a = TestUtil.getAllSet(); | |
| 422 TestAllTypes b = TestAllTypes.newBuilder().build(); | |
| 423 TestAllTypes c = TestAllTypes.newBuilder(b).addRepeatedString("x").build(); | |
| 424 TestAllTypes d = TestAllTypes.newBuilder(c).addRepeatedString("y").build(); | |
| 425 TestAllExtensions e = TestUtil.getAllExtensionsSet(); | |
| 426 TestAllExtensions f = TestAllExtensions.newBuilder(e) | |
| 427 .addExtension(UnittestProto.repeatedInt32Extension, 999).build(); | |
| 428 | |
| 429 checkEqualsIsConsistent(a); | |
| 430 checkEqualsIsConsistent(b); | |
| 431 checkEqualsIsConsistent(c); | |
| 432 checkEqualsIsConsistent(d); | |
| 433 checkEqualsIsConsistent(e); | |
| 434 checkEqualsIsConsistent(f); | |
| 435 | |
| 436 checkNotEqual(a, b); | |
| 437 checkNotEqual(a, c); | |
| 438 checkNotEqual(a, d); | |
| 439 checkNotEqual(a, e); | |
| 440 checkNotEqual(a, f); | |
| 441 | |
| 442 checkNotEqual(b, c); | |
| 443 checkNotEqual(b, d); | |
| 444 checkNotEqual(b, e); | |
| 445 checkNotEqual(b, f); | |
| 446 | |
| 447 checkNotEqual(c, d); | |
| 448 checkNotEqual(c, e); | |
| 449 checkNotEqual(c, f); | |
| 450 | |
| 451 checkNotEqual(d, e); | |
| 452 checkNotEqual(d, f); | |
| 453 | |
| 454 checkNotEqual(e, f); | |
| 455 | |
| 456 // Deserializing into the TestEmptyMessage such that every field | |
| 457 // is an {@link UnknownFieldSet.Field}. | |
| 458 UnittestProto.TestEmptyMessage eUnknownFields = | |
| 459 UnittestProto.TestEmptyMessage.parseFrom(e.toByteArray()); | |
| 460 UnittestProto.TestEmptyMessage fUnknownFields = | |
| 461 UnittestProto.TestEmptyMessage.parseFrom(f.toByteArray()); | |
| 462 checkNotEqual(eUnknownFields, fUnknownFields); | |
| 463 checkEqualsIsConsistent(eUnknownFields); | |
| 464 checkEqualsIsConsistent(fUnknownFields); | |
| 465 | |
| 466 // Subsequent reconstitutions should be identical | |
| 467 UnittestProto.TestEmptyMessage eUnknownFields2 = | |
| 468 UnittestProto.TestEmptyMessage.parseFrom(e.toByteArray()); | |
| 469 checkEqualsIsConsistent(eUnknownFields, eUnknownFields2); | |
| 470 } | |
| 471 | |
| 472 | |
| 473 /** | |
| 474 * Asserts that the given proto has symmetric equals and hashCode methods. | |
| 475 */ | |
| 476 private void checkEqualsIsConsistent(Message message) { | |
| 477 // Object should be equal to itself. | |
| 478 assertEquals(message, message); | |
| 479 | |
| 480 // Object should be equal to a dynamic copy of itself. | |
| 481 DynamicMessage dynamic = DynamicMessage.newBuilder(message).build(); | |
| 482 checkEqualsIsConsistent(message, dynamic); | |
| 483 } | |
| 484 | |
| 485 /** | |
| 486 * Asserts that the given protos are equal and have the same hash code. | |
| 487 */ | |
| 488 private void checkEqualsIsConsistent(Message message1, Message message2) { | |
| 489 assertEquals(message1, message2); | |
| 490 assertEquals(message2, message1); | |
| 491 assertEquals(message2.hashCode(), message1.hashCode()); | |
| 492 } | |
| 493 | |
| 494 /** | |
| 495 * Asserts that the given protos are not equal and have different hash codes. | |
| 496 * | |
| 497 * @warning It's valid for non-equal objects to have the same hash code, so | |
| 498 * this test is stricter than it needs to be. However, this should happen | |
| 499 * relatively rarely. | |
| 500 */ | |
| 501 private void checkNotEqual(Message m1, Message m2) { | |
| 502 String equalsError = String.format("%s should not be equal to %s", m1, m2); | |
| 503 assertFalse(equalsError, m1.equals(m2)); | |
| 504 assertFalse(equalsError, m2.equals(m1)); | |
| 505 | |
| 506 assertFalse( | |
| 507 String.format("%s should have a different hash code from %s", m1, m2), | |
| 508 m1.hashCode() == m2.hashCode()); | |
| 509 } | |
| 510 } | |
| OLD | NEW |