Index: third_party/protobuf/java/src/test/java/com/google/protobuf/AbstractMessageTest.java |
diff --git a/third_party/protobuf/java/src/test/java/com/google/protobuf/AbstractMessageTest.java b/third_party/protobuf/java/src/test/java/com/google/protobuf/AbstractMessageTest.java |
new file mode 100644 |
index 0000000000000000000000000000000000000000..d53ce8d766eb610504da66693a6e5034779fbbd1 |
--- /dev/null |
+++ b/third_party/protobuf/java/src/test/java/com/google/protobuf/AbstractMessageTest.java |
@@ -0,0 +1,460 @@ |
+// Protocol Buffers - Google's data interchange format |
+// Copyright 2008 Google Inc. All rights reserved. |
+// http://code.google.com/p/protobuf/ |
+// |
+// Redistribution and use in source and binary forms, with or without |
+// modification, are permitted provided that the following conditions are |
+// met: |
+// |
+// * Redistributions of source code must retain the above copyright |
+// notice, this list of conditions and the following disclaimer. |
+// * Redistributions in binary form must reproduce the above |
+// copyright notice, this list of conditions and the following disclaimer |
+// in the documentation and/or other materials provided with the |
+// distribution. |
+// * Neither the name of Google Inc. nor the names of its |
+// contributors may be used to endorse or promote products derived from |
+// this software without specific prior written permission. |
+// |
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
+ |
+package com.google.protobuf; |
+ |
+import protobuf_unittest.UnittestOptimizeFor.TestOptimizedForSize; |
+import protobuf_unittest.UnittestProto; |
+import protobuf_unittest.UnittestProto.ForeignMessage; |
+import protobuf_unittest.UnittestProto.TestAllExtensions; |
+import protobuf_unittest.UnittestProto.TestAllTypes; |
+import protobuf_unittest.UnittestProto.TestPackedTypes; |
+import protobuf_unittest.UnittestProto.TestRequired; |
+import protobuf_unittest.UnittestProto.TestRequiredForeign; |
+import protobuf_unittest.UnittestProto.TestUnpackedTypes; |
+ |
+import junit.framework.TestCase; |
+ |
+import java.util.Map; |
+ |
+/** |
+ * Unit test for {@link AbstractMessage}. |
+ * |
+ * @author kenton@google.com Kenton Varda |
+ */ |
+public class AbstractMessageTest extends TestCase { |
+ /** |
+ * Extends AbstractMessage and wraps some other message object. The methods |
+ * of the Message interface which aren't explicitly implemented by |
+ * AbstractMessage are forwarded to the wrapped object. This allows us to |
+ * test that AbstractMessage's implementations work even if the wrapped |
+ * object does not use them. |
+ */ |
+ private static class AbstractMessageWrapper extends AbstractMessage { |
+ private final Message wrappedMessage; |
+ |
+ public AbstractMessageWrapper(Message wrappedMessage) { |
+ this.wrappedMessage = wrappedMessage; |
+ } |
+ |
+ public Descriptors.Descriptor getDescriptorForType() { |
+ return wrappedMessage.getDescriptorForType(); |
+ } |
+ public AbstractMessageWrapper getDefaultInstanceForType() { |
+ return new AbstractMessageWrapper( |
+ wrappedMessage.getDefaultInstanceForType()); |
+ } |
+ public Map<Descriptors.FieldDescriptor, Object> getAllFields() { |
+ return wrappedMessage.getAllFields(); |
+ } |
+ public boolean hasField(Descriptors.FieldDescriptor field) { |
+ return wrappedMessage.hasField(field); |
+ } |
+ public Object getField(Descriptors.FieldDescriptor field) { |
+ return wrappedMessage.getField(field); |
+ } |
+ public int getRepeatedFieldCount(Descriptors.FieldDescriptor field) { |
+ return wrappedMessage.getRepeatedFieldCount(field); |
+ } |
+ public Object getRepeatedField( |
+ Descriptors.FieldDescriptor field, int index) { |
+ return wrappedMessage.getRepeatedField(field, index); |
+ } |
+ public UnknownFieldSet getUnknownFields() { |
+ return wrappedMessage.getUnknownFields(); |
+ } |
+ public Builder newBuilderForType() { |
+ return new Builder(wrappedMessage.newBuilderForType()); |
+ } |
+ public Builder toBuilder() { |
+ return new Builder(wrappedMessage.toBuilder()); |
+ } |
+ |
+ static class Builder extends AbstractMessage.Builder<Builder> { |
+ private final Message.Builder wrappedBuilder; |
+ |
+ public Builder(Message.Builder wrappedBuilder) { |
+ this.wrappedBuilder = wrappedBuilder; |
+ } |
+ |
+ public AbstractMessageWrapper build() { |
+ return new AbstractMessageWrapper(wrappedBuilder.build()); |
+ } |
+ public AbstractMessageWrapper buildPartial() { |
+ return new AbstractMessageWrapper(wrappedBuilder.buildPartial()); |
+ } |
+ public Builder clone() { |
+ return new Builder(wrappedBuilder.clone()); |
+ } |
+ public boolean isInitialized() { |
+ return clone().buildPartial().isInitialized(); |
+ } |
+ public Descriptors.Descriptor getDescriptorForType() { |
+ return wrappedBuilder.getDescriptorForType(); |
+ } |
+ public AbstractMessageWrapper getDefaultInstanceForType() { |
+ return new AbstractMessageWrapper( |
+ wrappedBuilder.getDefaultInstanceForType()); |
+ } |
+ public Map<Descriptors.FieldDescriptor, Object> getAllFields() { |
+ return wrappedBuilder.getAllFields(); |
+ } |
+ public Builder newBuilderForField(Descriptors.FieldDescriptor field) { |
+ return new Builder(wrappedBuilder.newBuilderForField(field)); |
+ } |
+ public boolean hasField(Descriptors.FieldDescriptor field) { |
+ return wrappedBuilder.hasField(field); |
+ } |
+ public Object getField(Descriptors.FieldDescriptor field) { |
+ return wrappedBuilder.getField(field); |
+ } |
+ public Builder setField(Descriptors.FieldDescriptor field, Object value) { |
+ wrappedBuilder.setField(field, value); |
+ return this; |
+ } |
+ public Builder clearField(Descriptors.FieldDescriptor field) { |
+ wrappedBuilder.clearField(field); |
+ return this; |
+ } |
+ public int getRepeatedFieldCount(Descriptors.FieldDescriptor field) { |
+ return wrappedBuilder.getRepeatedFieldCount(field); |
+ } |
+ public Object getRepeatedField( |
+ Descriptors.FieldDescriptor field, int index) { |
+ return wrappedBuilder.getRepeatedField(field, index); |
+ } |
+ public Builder setRepeatedField(Descriptors.FieldDescriptor field, |
+ int index, Object value) { |
+ wrappedBuilder.setRepeatedField(field, index, value); |
+ return this; |
+ } |
+ public Builder addRepeatedField( |
+ Descriptors.FieldDescriptor field, Object value) { |
+ wrappedBuilder.addRepeatedField(field, value); |
+ return this; |
+ } |
+ public UnknownFieldSet getUnknownFields() { |
+ return wrappedBuilder.getUnknownFields(); |
+ } |
+ public Builder setUnknownFields(UnknownFieldSet unknownFields) { |
+ wrappedBuilder.setUnknownFields(unknownFields); |
+ return this; |
+ } |
+ } |
+ } |
+ |
+ // ================================================================= |
+ |
+ TestUtil.ReflectionTester reflectionTester = |
+ new TestUtil.ReflectionTester(TestAllTypes.getDescriptor(), null); |
+ |
+ TestUtil.ReflectionTester extensionsReflectionTester = |
+ new TestUtil.ReflectionTester(TestAllExtensions.getDescriptor(), |
+ TestUtil.getExtensionRegistry()); |
+ |
+ public void testClear() throws Exception { |
+ AbstractMessageWrapper message = |
+ new AbstractMessageWrapper.Builder( |
+ TestAllTypes.newBuilder(TestUtil.getAllSet())) |
+ .clear().build(); |
+ TestUtil.assertClear((TestAllTypes) message.wrappedMessage); |
+ } |
+ |
+ public void testCopy() throws Exception { |
+ AbstractMessageWrapper message = |
+ new AbstractMessageWrapper.Builder(TestAllTypes.newBuilder()) |
+ .mergeFrom(TestUtil.getAllSet()).build(); |
+ TestUtil.assertAllFieldsSet((TestAllTypes) message.wrappedMessage); |
+ } |
+ |
+ public void testSerializedSize() throws Exception { |
+ TestAllTypes message = TestUtil.getAllSet(); |
+ Message abstractMessage = new AbstractMessageWrapper(TestUtil.getAllSet()); |
+ |
+ assertEquals(message.getSerializedSize(), |
+ abstractMessage.getSerializedSize()); |
+ } |
+ |
+ public void testSerialization() throws Exception { |
+ Message abstractMessage = new AbstractMessageWrapper(TestUtil.getAllSet()); |
+ |
+ TestUtil.assertAllFieldsSet( |
+ TestAllTypes.parseFrom(abstractMessage.toByteString())); |
+ |
+ assertEquals(TestUtil.getAllSet().toByteString(), |
+ abstractMessage.toByteString()); |
+ } |
+ |
+ public void testParsing() throws Exception { |
+ AbstractMessageWrapper.Builder builder = |
+ new AbstractMessageWrapper.Builder(TestAllTypes.newBuilder()); |
+ AbstractMessageWrapper message = |
+ builder.mergeFrom(TestUtil.getAllSet().toByteString()).build(); |
+ TestUtil.assertAllFieldsSet((TestAllTypes) message.wrappedMessage); |
+ } |
+ |
+ public void testPackedSerialization() throws Exception { |
+ Message abstractMessage = |
+ new AbstractMessageWrapper(TestUtil.getPackedSet()); |
+ |
+ TestUtil.assertPackedFieldsSet( |
+ TestPackedTypes.parseFrom(abstractMessage.toByteString())); |
+ |
+ assertEquals(TestUtil.getPackedSet().toByteString(), |
+ abstractMessage.toByteString()); |
+ } |
+ |
+ public void testPackedParsing() throws Exception { |
+ AbstractMessageWrapper.Builder builder = |
+ new AbstractMessageWrapper.Builder(TestPackedTypes.newBuilder()); |
+ AbstractMessageWrapper message = |
+ builder.mergeFrom(TestUtil.getPackedSet().toByteString()).build(); |
+ TestUtil.assertPackedFieldsSet((TestPackedTypes) message.wrappedMessage); |
+ } |
+ |
+ public void testUnpackedSerialization() throws Exception { |
+ Message abstractMessage = |
+ new AbstractMessageWrapper(TestUtil.getUnpackedSet()); |
+ |
+ TestUtil.assertUnpackedFieldsSet( |
+ TestUnpackedTypes.parseFrom(abstractMessage.toByteString())); |
+ |
+ assertEquals(TestUtil.getUnpackedSet().toByteString(), |
+ abstractMessage.toByteString()); |
+ } |
+ |
+ public void testParsePackedToUnpacked() throws Exception { |
+ AbstractMessageWrapper.Builder builder = |
+ new AbstractMessageWrapper.Builder(TestUnpackedTypes.newBuilder()); |
+ AbstractMessageWrapper message = |
+ builder.mergeFrom(TestUtil.getPackedSet().toByteString()).build(); |
+ TestUtil.assertUnpackedFieldsSet( |
+ (TestUnpackedTypes) message.wrappedMessage); |
+ } |
+ |
+ public void testParseUnpackedToPacked() throws Exception { |
+ AbstractMessageWrapper.Builder builder = |
+ new AbstractMessageWrapper.Builder(TestPackedTypes.newBuilder()); |
+ AbstractMessageWrapper message = |
+ builder.mergeFrom(TestUtil.getUnpackedSet().toByteString()).build(); |
+ TestUtil.assertPackedFieldsSet((TestPackedTypes) message.wrappedMessage); |
+ } |
+ |
+ public void testUnpackedParsing() throws Exception { |
+ AbstractMessageWrapper.Builder builder = |
+ new AbstractMessageWrapper.Builder(TestUnpackedTypes.newBuilder()); |
+ AbstractMessageWrapper message = |
+ builder.mergeFrom(TestUtil.getUnpackedSet().toByteString()).build(); |
+ TestUtil.assertUnpackedFieldsSet( |
+ (TestUnpackedTypes) message.wrappedMessage); |
+ } |
+ |
+ public void testOptimizedForSize() throws Exception { |
+ // We're mostly only checking that this class was compiled successfully. |
+ TestOptimizedForSize message = |
+ TestOptimizedForSize.newBuilder().setI(1).build(); |
+ message = TestOptimizedForSize.parseFrom(message.toByteString()); |
+ assertEquals(2, message.getSerializedSize()); |
+ } |
+ |
+ // ----------------------------------------------------------------- |
+ // Tests for isInitialized(). |
+ |
+ private static final TestRequired TEST_REQUIRED_UNINITIALIZED = |
+ TestRequired.getDefaultInstance(); |
+ private static final TestRequired TEST_REQUIRED_INITIALIZED = |
+ TestRequired.newBuilder().setA(1).setB(2).setC(3).build(); |
+ |
+ public void testIsInitialized() throws Exception { |
+ TestRequired.Builder builder = TestRequired.newBuilder(); |
+ AbstractMessageWrapper.Builder abstractBuilder = |
+ new AbstractMessageWrapper.Builder(builder); |
+ |
+ assertFalse(abstractBuilder.isInitialized()); |
+ builder.setA(1); |
+ assertFalse(abstractBuilder.isInitialized()); |
+ builder.setB(1); |
+ assertFalse(abstractBuilder.isInitialized()); |
+ builder.setC(1); |
+ assertTrue(abstractBuilder.isInitialized()); |
+ } |
+ |
+ public void testForeignIsInitialized() throws Exception { |
+ TestRequiredForeign.Builder builder = TestRequiredForeign.newBuilder(); |
+ AbstractMessageWrapper.Builder abstractBuilder = |
+ new AbstractMessageWrapper.Builder(builder); |
+ |
+ assertTrue(abstractBuilder.isInitialized()); |
+ |
+ builder.setOptionalMessage(TEST_REQUIRED_UNINITIALIZED); |
+ assertFalse(abstractBuilder.isInitialized()); |
+ |
+ builder.setOptionalMessage(TEST_REQUIRED_INITIALIZED); |
+ assertTrue(abstractBuilder.isInitialized()); |
+ |
+ builder.addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED); |
+ assertFalse(abstractBuilder.isInitialized()); |
+ |
+ builder.setRepeatedMessage(0, TEST_REQUIRED_INITIALIZED); |
+ assertTrue(abstractBuilder.isInitialized()); |
+ } |
+ |
+ // ----------------------------------------------------------------- |
+ // Tests for mergeFrom |
+ |
+ static final TestAllTypes MERGE_SOURCE = |
+ TestAllTypes.newBuilder() |
+ .setOptionalInt32(1) |
+ .setOptionalString("foo") |
+ .setOptionalForeignMessage(ForeignMessage.getDefaultInstance()) |
+ .addRepeatedString("bar") |
+ .build(); |
+ |
+ static final TestAllTypes MERGE_DEST = |
+ TestAllTypes.newBuilder() |
+ .setOptionalInt64(2) |
+ .setOptionalString("baz") |
+ .setOptionalForeignMessage(ForeignMessage.newBuilder().setC(3).build()) |
+ .addRepeatedString("qux") |
+ .build(); |
+ |
+ static final String MERGE_RESULT_TEXT = |
+ "optional_int32: 1\n" + |
+ "optional_int64: 2\n" + |
+ "optional_string: \"foo\"\n" + |
+ "optional_foreign_message {\n" + |
+ " c: 3\n" + |
+ "}\n" + |
+ "repeated_string: \"qux\"\n" + |
+ "repeated_string: \"bar\"\n"; |
+ |
+ public void testMergeFrom() throws Exception { |
+ AbstractMessageWrapper result = |
+ new AbstractMessageWrapper.Builder( |
+ TestAllTypes.newBuilder(MERGE_DEST)) |
+ .mergeFrom(MERGE_SOURCE).build(); |
+ |
+ assertEquals(MERGE_RESULT_TEXT, result.toString()); |
+ } |
+ |
+ // ----------------------------------------------------------------- |
+ // Tests for equals and hashCode |
+ |
+ public void testEqualsAndHashCode() throws Exception { |
+ TestAllTypes a = TestUtil.getAllSet(); |
+ TestAllTypes b = TestAllTypes.newBuilder().build(); |
+ TestAllTypes c = TestAllTypes.newBuilder(b).addRepeatedString("x").build(); |
+ TestAllTypes d = TestAllTypes.newBuilder(c).addRepeatedString("y").build(); |
+ TestAllExtensions e = TestUtil.getAllExtensionsSet(); |
+ TestAllExtensions f = TestAllExtensions.newBuilder(e) |
+ .addExtension(UnittestProto.repeatedInt32Extension, 999).build(); |
+ |
+ checkEqualsIsConsistent(a); |
+ checkEqualsIsConsistent(b); |
+ checkEqualsIsConsistent(c); |
+ checkEqualsIsConsistent(d); |
+ checkEqualsIsConsistent(e); |
+ checkEqualsIsConsistent(f); |
+ |
+ checkNotEqual(a, b); |
+ checkNotEqual(a, c); |
+ checkNotEqual(a, d); |
+ checkNotEqual(a, e); |
+ checkNotEqual(a, f); |
+ |
+ checkNotEqual(b, c); |
+ checkNotEqual(b, d); |
+ checkNotEqual(b, e); |
+ checkNotEqual(b, f); |
+ |
+ checkNotEqual(c, d); |
+ checkNotEqual(c, e); |
+ checkNotEqual(c, f); |
+ |
+ checkNotEqual(d, e); |
+ checkNotEqual(d, f); |
+ |
+ checkNotEqual(e, f); |
+ |
+ // Deserializing into the TestEmptyMessage such that every field |
+ // is an {@link UnknownFieldSet.Field}. |
+ UnittestProto.TestEmptyMessage eUnknownFields = |
+ UnittestProto.TestEmptyMessage.parseFrom(e.toByteArray()); |
+ UnittestProto.TestEmptyMessage fUnknownFields = |
+ UnittestProto.TestEmptyMessage.parseFrom(f.toByteArray()); |
+ checkNotEqual(eUnknownFields, fUnknownFields); |
+ checkEqualsIsConsistent(eUnknownFields); |
+ checkEqualsIsConsistent(fUnknownFields); |
+ |
+ // Subsequent reconstitutions should be identical |
+ UnittestProto.TestEmptyMessage eUnknownFields2 = |
+ UnittestProto.TestEmptyMessage.parseFrom(e.toByteArray()); |
+ checkEqualsIsConsistent(eUnknownFields, eUnknownFields2); |
+ } |
+ |
+ |
+ /** |
+ * Asserts that the given proto has symetric equals and hashCode methods. |
+ */ |
+ private void checkEqualsIsConsistent(Message message) { |
+ // Object should be equal to itself. |
+ assertEquals(message, message); |
+ |
+ // Object should be equal to a dynamic copy of itself. |
+ DynamicMessage dynamic = DynamicMessage.newBuilder(message).build(); |
+ checkEqualsIsConsistent(message, dynamic); |
+ } |
+ |
+ /** |
+ * Asserts that the given protos are equal and have the same hash code. |
+ */ |
+ private void checkEqualsIsConsistent(Message message1, Message message2) { |
+ assertEquals(message1, message2); |
+ assertEquals(message2, message1); |
+ assertEquals(message2.hashCode(), message1.hashCode()); |
+ } |
+ |
+ /** |
+ * Asserts that the given protos are not equal and have different hash codes. |
+ * |
+ * @warning It's valid for non-equal objects to have the same hash code, so |
+ * this test is stricter than it needs to be. However, this should happen |
+ * relatively rarely. |
+ */ |
+ private void checkNotEqual(Message m1, Message m2) { |
+ String equalsError = String.format("%s should not be equal to %s", m1, m2); |
+ assertFalse(equalsError, m1.equals(m2)); |
+ assertFalse(equalsError, m2.equals(m1)); |
+ |
+ assertFalse( |
+ String.format("%s should have a different hash code from %s", m1, m2), |
+ m1.hashCode() == m2.hashCode()); |
+ } |
+} |