aboutsummaryrefslogtreecommitdiffhomepage
path: root/java/core/src/test/java/com/google/protobuf
diff options
context:
space:
mode:
authorGravatar Jisi Liu <jisi.liu@gmail.com>2016-01-29 13:51:05 -0800
committerGravatar Jisi Liu <jisi.liu@gmail.com>2016-01-29 13:51:05 -0800
commit5221dcbe479ed765d8103ed7601c69b6d8d6ca4f (patch)
treed48fed101cf2fc21e07d3034cc4e01c81f00bac2 /java/core/src/test/java/com/google/protobuf
parentcb3f428810456dbb31211ed421401b90fb3b6586 (diff)
Integrate from google internal.
Java files are moved to un-do the hack in the prevous commit, which moved the java files to the original position for integration.
Diffstat (limited to 'java/core/src/test/java/com/google/protobuf')
-rw-r--r--java/core/src/test/java/com/google/protobuf/AbstractMessageTest.java527
-rw-r--r--java/core/src/test/java/com/google/protobuf/AnyTest.java92
-rw-r--r--java/core/src/test/java/com/google/protobuf/BooleanArrayListTest.java469
-rw-r--r--java/core/src/test/java/com/google/protobuf/BoundedByteStringTest.java101
-rw-r--r--java/core/src/test/java/com/google/protobuf/ByteStringTest.java760
-rw-r--r--java/core/src/test/java/com/google/protobuf/CheckUtf8Test.java140
-rw-r--r--java/core/src/test/java/com/google/protobuf/CodedInputStreamTest.java769
-rw-r--r--java/core/src/test/java/com/google/protobuf/CodedOutputStreamTest.java546
-rw-r--r--java/core/src/test/java/com/google/protobuf/DeprecatedFieldTest.java80
-rw-r--r--java/core/src/test/java/com/google/protobuf/DescriptorsTest.java765
-rw-r--r--java/core/src/test/java/com/google/protobuf/DoubleArrayListTest.java473
-rw-r--r--java/core/src/test/java/com/google/protobuf/DynamicMessageTest.java326
-rw-r--r--java/core/src/test/java/com/google/protobuf/FieldPresenceTest.java373
-rw-r--r--java/core/src/test/java/com/google/protobuf/FloatArrayListTest.java473
-rw-r--r--java/core/src/test/java/com/google/protobuf/ForceFieldBuildersPreRun.java48
-rw-r--r--java/core/src/test/java/com/google/protobuf/GeneratedMessageTest.java1661
-rw-r--r--java/core/src/test/java/com/google/protobuf/IntArrayListTest.java473
-rw-r--r--java/core/src/test/java/com/google/protobuf/IsValidUtf8Test.java183
-rw-r--r--java/core/src/test/java/com/google/protobuf/IsValidUtf8TestUtil.java420
-rw-r--r--java/core/src/test/java/com/google/protobuf/LazyFieldLiteTest.java271
-rw-r--r--java/core/src/test/java/com/google/protobuf/LazyFieldTest.java121
-rw-r--r--java/core/src/test/java/com/google/protobuf/LazyMessageLiteTest.java307
-rw-r--r--java/core/src/test/java/com/google/protobuf/LazyStringArrayListTest.java362
-rw-r--r--java/core/src/test/java/com/google/protobuf/LazyStringEndToEndTest.java132
-rw-r--r--java/core/src/test/java/com/google/protobuf/LiteEqualsAndHashTest.java108
-rw-r--r--java/core/src/test/java/com/google/protobuf/LiteTest.java1462
-rw-r--r--java/core/src/test/java/com/google/protobuf/LiteralByteStringTest.java495
-rw-r--r--java/core/src/test/java/com/google/protobuf/LongArrayListTest.java473
-rw-r--r--java/core/src/test/java/com/google/protobuf/MapForProto2LiteTest.java458
-rw-r--r--java/core/src/test/java/com/google/protobuf/MapForProto2Test.java684
-rw-r--r--java/core/src/test/java/com/google/protobuf/MapTest.java783
-rw-r--r--java/core/src/test/java/com/google/protobuf/MessageTest.java353
-rw-r--r--java/core/src/test/java/com/google/protobuf/NestedBuildersTest.java185
-rw-r--r--java/core/src/test/java/com/google/protobuf/NioByteStringTest.java545
-rw-r--r--java/core/src/test/java/com/google/protobuf/ParseExceptionsTest.java212
-rw-r--r--java/core/src/test/java/com/google/protobuf/ParserTest.java377
-rw-r--r--java/core/src/test/java/com/google/protobuf/ProtobufArrayListTest.java303
-rw-r--r--java/core/src/test/java/com/google/protobuf/RepeatedFieldBuilderTest.java190
-rw-r--r--java/core/src/test/java/com/google/protobuf/RopeByteStringSubstringTest.java127
-rw-r--r--java/core/src/test/java/com/google/protobuf/RopeByteStringTest.java189
-rw-r--r--java/core/src/test/java/com/google/protobuf/ServiceTest.java320
-rw-r--r--java/core/src/test/java/com/google/protobuf/SingleFieldBuilderTest.java155
-rw-r--r--java/core/src/test/java/com/google/protobuf/SmallSortedMapTest.java420
-rw-r--r--java/core/src/test/java/com/google/protobuf/TestBadIdentifiers.java96
-rw-r--r--java/core/src/test/java/com/google/protobuf/TestUtil.java4275
-rw-r--r--java/core/src/test/java/com/google/protobuf/TextFormatTest.java1021
-rw-r--r--java/core/src/test/java/com/google/protobuf/UnknownEnumValueTest.java255
-rw-r--r--java/core/src/test/java/com/google/protobuf/UnknownFieldSetLiteTest.java368
-rw-r--r--java/core/src/test/java/com/google/protobuf/UnknownFieldSetTest.java653
-rw-r--r--java/core/src/test/java/com/google/protobuf/UnmodifiableLazyStringListTest.java227
-rw-r--r--java/core/src/test/java/com/google/protobuf/WellKnownTypesTest.java65
-rw-r--r--java/core/src/test/java/com/google/protobuf/WireFormatTest.java606
52 files changed, 25277 insertions, 0 deletions
diff --git a/java/core/src/test/java/com/google/protobuf/AbstractMessageTest.java b/java/core/src/test/java/com/google/protobuf/AbstractMessageTest.java
new file mode 100644
index 00000000..d964ef59
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/AbstractMessageTest.java
@@ -0,0 +1,527 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// 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 com.google.protobuf.Descriptors.FieldDescriptor;
+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;
+ }
+ @Override
+ public Message.Builder getFieldBuilder(FieldDescriptor field) {
+ return wrappedBuilder.getFieldBuilder(field);
+ }
+ }
+ public Parser<? extends Message> getParserForType() {
+ return wrappedMessage.getParserForType();
+ }
+ }
+
+ // =================================================================
+
+ 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 testParsingUninitialized() throws Exception {
+ TestRequiredForeign.Builder builder = TestRequiredForeign.newBuilder();
+ builder.getOptionalMessageBuilder().setDummy2(10);
+ ByteString bytes = builder.buildPartial().toByteString();
+ Message.Builder abstractMessageBuilder =
+ new AbstractMessageWrapper.Builder(TestRequiredForeign.newBuilder());
+ // mergeFrom() should not throw initialization error.
+ abstractMessageBuilder.mergeFrom(bytes).buildPartial();
+ try {
+ abstractMessageBuilder.mergeFrom(bytes).build();
+ fail();
+ } catch (UninitializedMessageException ex) {
+ // pass
+ }
+
+ // test DynamicMessage directly.
+ Message.Builder dynamicMessageBuilder = DynamicMessage.newBuilder(
+ TestRequiredForeign.getDescriptor());
+ // mergeFrom() should not throw initialization error.
+ dynamicMessageBuilder.mergeFrom(bytes).buildPartial();
+ try {
+ dynamicMessageBuilder.mergeFrom(bytes).build();
+ fail();
+ } catch (UninitializedMessageException ex) {
+ // pass
+ }
+ }
+
+ 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());
+ assertEquals("a, b, c", abstractBuilder.getInitializationErrorString());
+ builder.setA(1);
+ assertFalse(abstractBuilder.isInitialized());
+ assertEquals("b, c", abstractBuilder.getInitializationErrorString());
+ builder.setB(1);
+ assertFalse(abstractBuilder.isInitialized());
+ assertEquals("c", abstractBuilder.getInitializationErrorString());
+ builder.setC(1);
+ assertTrue(abstractBuilder.isInitialized());
+ assertEquals("", abstractBuilder.getInitializationErrorString());
+ }
+
+ public void testForeignIsInitialized() throws Exception {
+ TestRequiredForeign.Builder builder = TestRequiredForeign.newBuilder();
+ AbstractMessageWrapper.Builder abstractBuilder =
+ new AbstractMessageWrapper.Builder(builder);
+
+ assertTrue(abstractBuilder.isInitialized());
+ assertEquals("", abstractBuilder.getInitializationErrorString());
+
+ builder.setOptionalMessage(TEST_REQUIRED_UNINITIALIZED);
+ assertFalse(abstractBuilder.isInitialized());
+ assertEquals(
+ "optional_message.a, optional_message.b, optional_message.c",
+ abstractBuilder.getInitializationErrorString());
+
+ builder.setOptionalMessage(TEST_REQUIRED_INITIALIZED);
+ assertTrue(abstractBuilder.isInitialized());
+ assertEquals("", abstractBuilder.getInitializationErrorString());
+
+ builder.addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED);
+ assertFalse(abstractBuilder.isInitialized());
+ assertEquals(
+ "repeated_message[0].a, repeated_message[0].b, repeated_message[0].c",
+ abstractBuilder.getInitializationErrorString());
+
+ builder.setRepeatedMessage(0, TEST_REQUIRED_INITIALIZED);
+ assertTrue(abstractBuilder.isInitialized());
+ assertEquals("", abstractBuilder.getInitializationErrorString());
+ }
+
+ // -----------------------------------------------------------------
+ // 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 symmetric 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());
+ }
+
+ public void testCheckByteStringIsUtf8OnUtf8() {
+ ByteString byteString = ByteString.copyFromUtf8("some text");
+ AbstractMessageLite.checkByteStringIsUtf8(byteString);
+ // No exception thrown.
+ }
+
+ public void testCheckByteStringIsUtf8OnNonUtf8() {
+ ByteString byteString =
+ ByteString.copyFrom(new byte[]{(byte) 0x80}); // A lone continuation byte.
+ try {
+ AbstractMessageLite.checkByteStringIsUtf8(byteString);
+ fail("Expected AbstractMessageLite.checkByteStringIsUtf8 to throw IllegalArgumentException");
+ } catch (IllegalArgumentException exception) {
+ assertEquals("Byte string is not UTF-8.", exception.getMessage());
+ }
+ }
+
+}
diff --git a/java/core/src/test/java/com/google/protobuf/AnyTest.java b/java/core/src/test/java/com/google/protobuf/AnyTest.java
new file mode 100644
index 00000000..e169f69d
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/AnyTest.java
@@ -0,0 +1,92 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// 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 any_test.AnyTestProto.TestAny;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+
+import junit.framework.TestCase;
+
+/**
+ * Unit tests for Any message.
+ */
+public class AnyTest extends TestCase {
+ public void testAnyGeneratedApi() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TestUtil.setAllFields(builder);
+ TestAllTypes message = builder.build();
+
+ TestAny container = TestAny.newBuilder()
+ .setValue(Any.pack(message)).build();
+
+ assertTrue(container.getValue().is(TestAllTypes.class));
+ assertFalse(container.getValue().is(TestAny.class));
+
+ TestAllTypes result = container.getValue().unpack(TestAllTypes.class);
+ TestUtil.assertAllFieldsSet(result);
+
+
+ // Unpacking to a wrong type will throw an exception.
+ try {
+ TestAny wrongMessage = container.getValue().unpack(TestAny.class);
+ fail("Exception is expected.");
+ } catch (InvalidProtocolBufferException e) {
+ // expected.
+ }
+
+ // Test that unpacking throws an exception if parsing fails.
+ TestAny.Builder containerBuilder = container.toBuilder();
+ containerBuilder.getValueBuilder().setValue(
+ ByteString.copyFrom(new byte[]{0x11}));
+ container = containerBuilder.build();
+ try {
+ TestAllTypes parsingFailed = container.getValue().unpack(TestAllTypes.class);
+ fail("Exception is expected.");
+ } catch (InvalidProtocolBufferException e) {
+ // expected.
+ }
+ }
+
+ public void testCachedUnpackResult() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TestUtil.setAllFields(builder);
+ TestAllTypes message = builder.build();
+
+ TestAny container = TestAny.newBuilder()
+ .setValue(Any.pack(message)).build();
+
+ assertTrue(container.getValue().is(TestAllTypes.class));
+
+ TestAllTypes result1 = container.getValue().unpack(TestAllTypes.class);
+ TestAllTypes result2 = container.getValue().unpack(TestAllTypes.class);
+ assertTrue(result1 == result2);
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/BooleanArrayListTest.java b/java/core/src/test/java/com/google/protobuf/BooleanArrayListTest.java
new file mode 100644
index 00000000..b8ad1fe4
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/BooleanArrayListTest.java
@@ -0,0 +1,469 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// 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 static java.util.Arrays.asList;
+
+import junit.framework.TestCase;
+
+import java.util.Collections;
+import java.util.ConcurrentModificationException;
+import java.util.Iterator;
+
+/**
+ * Tests for {@link BooleanArrayList}.
+ *
+ * @author dweis@google.com (Daniel Weis)
+ */
+public class BooleanArrayListTest extends TestCase {
+
+ private static final BooleanArrayList UNARY_LIST = newImmutableBooleanArrayList(true);
+ private static final BooleanArrayList TERTIARY_LIST =
+ newImmutableBooleanArrayList(true, true, false);
+
+ private BooleanArrayList list;
+
+ @Override
+ protected void setUp() throws Exception {
+ list = new BooleanArrayList();
+ }
+
+ public void testEmptyListReturnsSameInstance() {
+ assertSame(BooleanArrayList.emptyList(), BooleanArrayList.emptyList());
+ }
+
+ public void testEmptyListIsImmutable() {
+ assertImmutable(BooleanArrayList.emptyList());
+ }
+
+ public void testMakeImmutable() {
+ list.addBoolean(true);
+ list.addBoolean(false);
+ list.addBoolean(true);
+ list.addBoolean(true);
+ list.makeImmutable();
+ assertImmutable(list);
+ }
+
+ public void testCopyConstructor() {
+ BooleanArrayList copy = new BooleanArrayList(TERTIARY_LIST);
+ assertEquals(TERTIARY_LIST, copy);
+
+ copy = new BooleanArrayList(BooleanArrayList.emptyList());
+ assertEquals(BooleanArrayList.emptyList(), copy);
+
+ copy = new BooleanArrayList(asList(false, false, true));
+ assertEquals(asList(false, false, true), copy);
+
+ copy = new BooleanArrayList(Collections.<Boolean>emptyList());
+ assertEquals(BooleanArrayList.emptyList(), copy);
+ }
+
+ public void testModificationWithIteration() {
+ list.addAll(asList(true, false, false, true));
+ Iterator<Boolean> iterator = list.iterator();
+ assertEquals(4, list.size());
+ assertEquals(true, (boolean) list.get(0));
+ assertEquals(true, (boolean) iterator.next());
+ list.set(0, true);
+ assertEquals(false, (boolean) iterator.next());
+
+ list.remove(0);
+ try {
+ iterator.next();
+ fail();
+ } catch (ConcurrentModificationException e) {
+ // expected
+ }
+
+ iterator = list.iterator();
+ list.add(0, false);
+ try {
+ iterator.next();
+ fail();
+ } catch (ConcurrentModificationException e) {
+ // expected
+ }
+ }
+
+ public void testGet() {
+ assertEquals(true, (boolean) TERTIARY_LIST.get(0));
+ assertEquals(true, (boolean) TERTIARY_LIST.get(1));
+ assertEquals(false, (boolean) TERTIARY_LIST.get(2));
+
+ try {
+ TERTIARY_LIST.get(-1);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ TERTIARY_LIST.get(3);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testGetInt() {
+ assertEquals(true, TERTIARY_LIST.getBoolean(0));
+ assertEquals(true, TERTIARY_LIST.getBoolean(1));
+ assertEquals(false, TERTIARY_LIST.getBoolean(2));
+
+ try {
+ TERTIARY_LIST.get(-1);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ TERTIARY_LIST.get(3);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testSize() {
+ assertEquals(0, BooleanArrayList.emptyList().size());
+ assertEquals(1, UNARY_LIST.size());
+ assertEquals(3, TERTIARY_LIST.size());
+
+ list.addBoolean(true);
+ list.addBoolean(false);
+ list.addBoolean(false);
+ list.addBoolean(false);
+ assertEquals(4, list.size());
+
+ list.remove(0);
+ assertEquals(3, list.size());
+
+ list.add(true);
+ assertEquals(4, list.size());
+ }
+
+ public void testSet() {
+ list.addBoolean(false);
+ list.addBoolean(false);
+
+ assertEquals(false, (boolean) list.set(0, true));
+ assertEquals(true, list.getBoolean(0));
+
+ assertEquals(false, (boolean) list.set(1, false));
+ assertEquals(false, list.getBoolean(1));
+
+ try {
+ list.set(-1, true);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ list.set(2, false);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testSetInt() {
+ list.addBoolean(true);
+ list.addBoolean(true);
+
+ assertEquals(true, list.setBoolean(0, false));
+ assertEquals(false, list.getBoolean(0));
+
+ assertEquals(true, list.setBoolean(1, false));
+ assertEquals(false, list.getBoolean(1));
+
+ try {
+ list.setBoolean(-1, false);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ list.setBoolean(2, true);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testAdd() {
+ assertEquals(0, list.size());
+
+ assertTrue(list.add(true));
+ assertEquals(asList(true), list);
+
+ assertTrue(list.add(false));
+ list.add(0, false);
+ assertEquals(asList(false, true, false), list);
+
+ list.add(0, false);
+ list.add(0, true);
+ // Force a resize by getting up to 11 elements.
+ for (int i = 0; i < 6; i++) {
+ list.add(true);
+ }
+ assertEquals(asList(true, false, false, true, false, true, true, true, true, true, true), list);
+
+ try {
+ list.add(-1, false);
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ list.add(4, true);
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testAddInt() {
+ assertEquals(0, list.size());
+
+ list.addBoolean(true);
+ assertEquals(asList(true), list);
+
+ list.addBoolean(false);
+ assertEquals(asList(true, false), list);
+ }
+
+ public void testAddAll() {
+ assertEquals(0, list.size());
+
+ assertTrue(list.addAll(Collections.singleton(false)));
+ assertEquals(1, list.size());
+ assertEquals(false, (boolean) list.get(0));
+ assertEquals(false, list.getBoolean(0));
+
+ assertTrue(list.addAll(asList(true, false, false, false, true)));
+ assertEquals(asList(false, true, false, false, false, true), list);
+
+ assertTrue(list.addAll(TERTIARY_LIST));
+ assertEquals(asList(false, true, false, false, false, true, true, true, false), list);
+
+ assertFalse(list.addAll(Collections.<Boolean>emptyList()));
+ assertFalse(list.addAll(BooleanArrayList.emptyList()));
+ }
+
+ public void testRemove() {
+ list.addAll(TERTIARY_LIST);
+ assertEquals(true, (boolean) list.remove(0));
+ assertEquals(asList(true, false), list);
+
+ assertTrue(list.remove(Boolean.TRUE));
+ assertEquals(asList(false), list);
+
+ assertFalse(list.remove(Boolean.TRUE));
+ assertEquals(asList(false), list);
+
+ assertEquals(false, (boolean) list.remove(0));
+ assertEquals(asList(), list);
+
+ try {
+ list.remove(-1);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ list.remove(0);
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ private void assertImmutable(BooleanArrayList list) {
+ try {
+ list.add(false);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.add(0, true);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(Collections.<Boolean>emptyList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(Collections.singletonList(false));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(new BooleanArrayList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(UNARY_LIST);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(0, Collections.singleton(true));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(0, UNARY_LIST);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(0, Collections.<Boolean>emptyList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addBoolean(true);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.clear();
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.remove(1);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.remove(new Object());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.removeAll(Collections.<Boolean>emptyList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.removeAll(Collections.singleton(Boolean.TRUE));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.removeAll(UNARY_LIST);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.retainAll(Collections.<Boolean>emptyList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.retainAll(Collections.singleton(Boolean.TRUE));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.retainAll(UNARY_LIST);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.set(0, true);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.setBoolean(0, false);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ }
+
+ private static BooleanArrayList newImmutableBooleanArrayList(boolean... elements) {
+ BooleanArrayList list = new BooleanArrayList();
+ for (boolean element : elements) {
+ list.addBoolean(element);
+ }
+ list.makeImmutable();
+ return list;
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/BoundedByteStringTest.java b/java/core/src/test/java/com/google/protobuf/BoundedByteStringTest.java
new file mode 100644
index 00000000..7a8a0a5e
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/BoundedByteStringTest.java
@@ -0,0 +1,101 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// 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 java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.UnsupportedEncodingException;
+
+
+/**
+ * This class tests {@link BoundedByteString}, which extends {@link LiteralByteString},
+ * by inheriting the tests from {@link LiteralByteStringTest}. The only method which
+ * is strange enough that it needs to be overridden here is {@link #testToString()}.
+ *
+ * @author carlanton@google.com (Carl Haverl)
+ */
+public class BoundedByteStringTest extends LiteralByteStringTest {
+
+ @Override
+ protected void setUp() throws Exception {
+ classUnderTest = "BoundedByteString";
+ byte[] sourceBytes = ByteStringTest.getTestBytes(2341, 11337766L);
+ int from = 100;
+ int to = sourceBytes.length - 100;
+ stringUnderTest = ByteString.copyFrom(sourceBytes).substring(from, to);
+ referenceBytes = new byte[to - from];
+ System.arraycopy(sourceBytes, from, referenceBytes, 0, to - from);
+ expectedHashCode = 727575887;
+ }
+
+ @Override
+ public void testToString() throws UnsupportedEncodingException {
+ String testString = "I love unicode \u1234\u5678 characters";
+ ByteString unicode = ByteString.wrap(testString.getBytes(Internal.UTF_8));
+ ByteString chopped = unicode.substring(2, unicode.size() - 6);
+ assertEquals(classUnderTest + ".substring() must have the expected type",
+ classUnderTest, getActualClassName(chopped));
+
+ String roundTripString = chopped.toString(UTF_8);
+ assertEquals(classUnderTest + " unicode bytes must match",
+ testString.substring(2, testString.length() - 6), roundTripString);
+ }
+
+ @Override
+ public void testCharsetToString() {
+ String testString = "I love unicode \u1234\u5678 characters";
+ ByteString unicode = ByteString.wrap(testString.getBytes(Internal.UTF_8));
+ ByteString chopped = unicode.substring(2, unicode.size() - 6);
+ assertEquals(classUnderTest + ".substring() must have the expected type",
+ classUnderTest, getActualClassName(chopped));
+
+ String roundTripString = chopped.toString(Internal.UTF_8);
+ assertEquals(classUnderTest + " unicode bytes must match",
+ testString.substring(2, testString.length() - 6), roundTripString);
+ }
+
+ @Override
+ public void testJavaSerialization() throws Exception {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(out);
+ oos.writeObject(stringUnderTest);
+ oos.close();
+ byte[] pickled = out.toByteArray();
+ InputStream in = new ByteArrayInputStream(pickled);
+ ObjectInputStream ois = new ObjectInputStream(in);
+ Object o = ois.readObject();
+ assertTrue("Didn't get a ByteString back", o instanceof ByteString);
+ assertEquals("Should get an equal ByteString back", stringUnderTest, o);
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/ByteStringTest.java b/java/core/src/test/java/com/google/protobuf/ByteStringTest.java
new file mode 100644
index 00000000..5267c160
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/ByteStringTest.java
@@ -0,0 +1,760 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// 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 com.google.protobuf.ByteString.Output;
+
+import junit.framework.TestCase;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.Random;
+
+/**
+ * Test methods with implementations in {@link ByteString}, plus do some top-level "integration"
+ * tests.
+ *
+ * @author carlanton@google.com (Carl Haverl)
+ */
+public class ByteStringTest extends TestCase {
+
+ private static final Charset UTF_16 = Charset.forName("UTF-16");
+
+ static byte[] getTestBytes(int size, long seed) {
+ Random random = new Random(seed);
+ byte[] result = new byte[size];
+ random.nextBytes(result);
+ return result;
+ }
+
+ private byte[] getTestBytes(int size) {
+ return getTestBytes(size, 445566L);
+ }
+
+ private byte[] getTestBytes() {
+ return getTestBytes(1000);
+ }
+
+ // Compare the entire left array with a subset of the right array.
+ private boolean isArrayRange(byte[] left, byte[] right, int rightOffset, int length) {
+ boolean stillEqual = (left.length == length);
+ for (int i = 0; (stillEqual && i < length); ++i) {
+ stillEqual = (left[i] == right[rightOffset + i]);
+ }
+ return stillEqual;
+ }
+
+ // Returns true only if the given two arrays have identical contents.
+ private boolean isArray(byte[] left, byte[] right) {
+ return left.length == right.length && isArrayRange(left, right, 0, left.length);
+ }
+
+ public void testSubstring_BeginIndex() {
+ byte[] bytes = getTestBytes();
+ ByteString substring = ByteString.copyFrom(bytes).substring(500);
+ assertTrue("substring must contain the tail of the string",
+ isArrayRange(substring.toByteArray(), bytes, 500, bytes.length - 500));
+ }
+
+ public void testCopyFrom_BytesOffsetSize() {
+ byte[] bytes = getTestBytes();
+ ByteString byteString = ByteString.copyFrom(bytes, 500, 200);
+ assertTrue("copyFrom sub-range must contain the expected bytes",
+ isArrayRange(byteString.toByteArray(), bytes, 500, 200));
+ }
+
+ public void testCopyFrom_Bytes() {
+ byte[] bytes = getTestBytes();
+ ByteString byteString = ByteString.copyFrom(bytes);
+ assertTrue("copyFrom must contain the expected bytes",
+ isArray(byteString.toByteArray(), bytes));
+ }
+
+ public void testCopyFrom_ByteBufferSize() {
+ byte[] bytes = getTestBytes();
+ ByteBuffer byteBuffer = ByteBuffer.allocate(bytes.length);
+ byteBuffer.put(bytes);
+ byteBuffer.position(500);
+ ByteString byteString = ByteString.copyFrom(byteBuffer, 200);
+ assertTrue("copyFrom byteBuffer sub-range must contain the expected bytes",
+ isArrayRange(byteString.toByteArray(), bytes, 500, 200));
+ }
+
+ public void testCopyFrom_ByteBuffer() {
+ byte[] bytes = getTestBytes();
+ ByteBuffer byteBuffer = ByteBuffer.allocate(bytes.length);
+ byteBuffer.put(bytes);
+ byteBuffer.position(500);
+ ByteString byteString = ByteString.copyFrom(byteBuffer);
+ assertTrue("copyFrom byteBuffer sub-range must contain the expected bytes",
+ isArrayRange(byteString.toByteArray(), bytes, 500, bytes.length - 500));
+ }
+
+ public void testCopyFrom_StringEncoding() {
+ String testString = "I love unicode \u1234\u5678 characters";
+ ByteString byteString = ByteString.copyFrom(testString, UTF_16);
+ byte[] testBytes = testString.getBytes(UTF_16);
+ assertTrue("copyFrom string must respect the charset",
+ isArrayRange(byteString.toByteArray(), testBytes, 0, testBytes.length));
+ }
+
+ public void testCopyFrom_Utf8() {
+ String testString = "I love unicode \u1234\u5678 characters";
+ ByteString byteString = ByteString.copyFromUtf8(testString);
+ byte[] testBytes = testString.getBytes(Internal.UTF_8);
+ assertTrue("copyFromUtf8 string must respect the charset",
+ isArrayRange(byteString.toByteArray(), testBytes, 0, testBytes.length));
+ }
+
+ public void testCopyFrom_Iterable() {
+ byte[] testBytes = getTestBytes(77777, 113344L);
+ final List<ByteString> pieces = makeConcretePieces(testBytes);
+ // Call copyFrom() on a Collection
+ ByteString byteString = ByteString.copyFrom(pieces);
+ assertTrue("copyFrom a List must contain the expected bytes",
+ isArrayRange(byteString.toByteArray(), testBytes, 0, testBytes.length));
+ // Call copyFrom on an iteration that's not a collection
+ ByteString byteStringAlt = ByteString.copyFrom(new Iterable<ByteString>() {
+ @Override
+ public Iterator<ByteString> iterator() {
+ return pieces.iterator();
+ }
+ });
+ assertEquals("copyFrom from an Iteration must contain the expected bytes",
+ byteString, byteStringAlt);
+ }
+
+ public void testCopyTo_TargetOffset() {
+ byte[] bytes = getTestBytes();
+ ByteString byteString = ByteString.copyFrom(bytes);
+ byte[] target = new byte[bytes.length + 1000];
+ byteString.copyTo(target, 400);
+ assertTrue("copyFrom byteBuffer sub-range must contain the expected bytes",
+ isArrayRange(bytes, target, 400, bytes.length));
+ }
+
+ public void testReadFrom_emptyStream() throws IOException {
+ ByteString byteString =
+ ByteString.readFrom(new ByteArrayInputStream(new byte[0]));
+ assertSame("reading an empty stream must result in the EMPTY constant "
+ + "byte string", ByteString.EMPTY, byteString);
+ }
+
+ public void testReadFrom_smallStream() throws IOException {
+ assertReadFrom(getTestBytes(10));
+ }
+
+ public void testReadFrom_mutating() throws IOException {
+ byte[] capturedArray = null;
+ EvilInputStream eis = new EvilInputStream();
+ ByteString byteString = ByteString.readFrom(eis);
+
+ capturedArray = eis.capturedArray;
+ byte[] originalValue = byteString.toByteArray();
+ for (int x = 0; x < capturedArray.length; ++x) {
+ capturedArray[x] = (byte) 0;
+ }
+
+ byte[] newValue = byteString.toByteArray();
+ assertTrue("copyFrom byteBuffer must not grant access to underlying array",
+ Arrays.equals(originalValue, newValue));
+ }
+
+ // Tests sizes that are near the rope copy-out threshold.
+ public void testReadFrom_mediumStream() throws IOException {
+ assertReadFrom(getTestBytes(ByteString.CONCATENATE_BY_COPY_SIZE - 1));
+ assertReadFrom(getTestBytes(ByteString.CONCATENATE_BY_COPY_SIZE));
+ assertReadFrom(getTestBytes(ByteString.CONCATENATE_BY_COPY_SIZE + 1));
+ assertReadFrom(getTestBytes(200));
+ }
+
+ // Tests sizes that are over multi-segment rope threshold.
+ public void testReadFrom_largeStream() throws IOException {
+ assertReadFrom(getTestBytes(0x100));
+ assertReadFrom(getTestBytes(0x101));
+ assertReadFrom(getTestBytes(0x110));
+ assertReadFrom(getTestBytes(0x1000));
+ assertReadFrom(getTestBytes(0x1001));
+ assertReadFrom(getTestBytes(0x1010));
+ assertReadFrom(getTestBytes(0x10000));
+ assertReadFrom(getTestBytes(0x10001));
+ assertReadFrom(getTestBytes(0x10010));
+ }
+
+ // Tests sizes that are near the read buffer size.
+ public void testReadFrom_byteBoundaries() throws IOException {
+ final int min = ByteString.MIN_READ_FROM_CHUNK_SIZE;
+ final int max = ByteString.MAX_READ_FROM_CHUNK_SIZE;
+
+ assertReadFrom(getTestBytes(min - 1));
+ assertReadFrom(getTestBytes(min));
+ assertReadFrom(getTestBytes(min + 1));
+
+ assertReadFrom(getTestBytes(min * 2 - 1));
+ assertReadFrom(getTestBytes(min * 2));
+ assertReadFrom(getTestBytes(min * 2 + 1));
+
+ assertReadFrom(getTestBytes(min * 4 - 1));
+ assertReadFrom(getTestBytes(min * 4));
+ assertReadFrom(getTestBytes(min * 4 + 1));
+
+ assertReadFrom(getTestBytes(min * 8 - 1));
+ assertReadFrom(getTestBytes(min * 8));
+ assertReadFrom(getTestBytes(min * 8 + 1));
+
+ assertReadFrom(getTestBytes(max - 1));
+ assertReadFrom(getTestBytes(max));
+ assertReadFrom(getTestBytes(max + 1));
+
+ assertReadFrom(getTestBytes(max * 2 - 1));
+ assertReadFrom(getTestBytes(max * 2));
+ assertReadFrom(getTestBytes(max * 2 + 1));
+ }
+
+ // Tests that IOExceptions propagate through ByteString.readFrom().
+ public void testReadFrom_IOExceptions() {
+ try {
+ ByteString.readFrom(new FailStream());
+ fail("readFrom must throw the underlying IOException");
+
+ } catch (IOException e) {
+ assertEquals("readFrom must throw the expected exception",
+ "synthetic failure", e.getMessage());
+ }
+ }
+
+ // Tests that ByteString.readFrom works with streams that don't
+ // always fill their buffers.
+ public void testReadFrom_reluctantStream() throws IOException {
+ final byte[] data = getTestBytes(0x1000);
+
+ ByteString byteString = ByteString.readFrom(new ReluctantStream(data));
+ assertTrue("readFrom byte stream must contain the expected bytes",
+ isArray(byteString.toByteArray(), data));
+
+ // Same test as above, but with some specific chunk sizes.
+ assertReadFromReluctantStream(data, 100);
+ assertReadFromReluctantStream(data, 248);
+ assertReadFromReluctantStream(data, 249);
+ assertReadFromReluctantStream(data, 250);
+ assertReadFromReluctantStream(data, 251);
+ assertReadFromReluctantStream(data, 0x1000);
+ assertReadFromReluctantStream(data, 0x1001);
+ }
+
+ // Fails unless ByteString.readFrom reads the bytes correctly from a
+ // reluctant stream with the given chunkSize parameter.
+ private void assertReadFromReluctantStream(byte[] bytes, int chunkSize)
+ throws IOException {
+ ByteString b = ByteString.readFrom(new ReluctantStream(bytes), chunkSize);
+ assertTrue("readFrom byte stream must contain the expected bytes",
+ isArray(b.toByteArray(), bytes));
+ }
+
+ // Tests that ByteString.readFrom works with streams that implement
+ // available().
+ public void testReadFrom_available() throws IOException {
+ final byte[] data = getTestBytes(0x1001);
+
+ ByteString byteString = ByteString.readFrom(new AvailableStream(data));
+ assertTrue("readFrom byte stream must contain the expected bytes",
+ isArray(byteString.toByteArray(), data));
+ }
+
+ // Fails unless ByteString.readFrom reads the bytes correctly.
+ private void assertReadFrom(byte[] bytes) throws IOException {
+ ByteString byteString =
+ ByteString.readFrom(new ByteArrayInputStream(bytes));
+ assertTrue("readFrom byte stream must contain the expected bytes",
+ isArray(byteString.toByteArray(), bytes));
+ }
+
+ // A stream that fails when read.
+ private static final class FailStream extends InputStream {
+ @Override public int read() throws IOException {
+ throw new IOException("synthetic failure");
+ }
+ }
+
+ // A stream that simulates blocking by only producing 250 characters
+ // per call to read(byte[]).
+ private static class ReluctantStream extends InputStream {
+ protected final byte[] data;
+ protected int pos = 0;
+
+ public ReluctantStream(byte[] data) {
+ this.data = data;
+ }
+
+ @Override public int read() {
+ if (pos == data.length) {
+ return -1;
+ } else {
+ return data[pos++];
+ }
+ }
+
+ @Override public int read(byte[] buf) {
+ return read(buf, 0, buf.length);
+ }
+
+ @Override public int read(byte[] buf, int offset, int size) {
+ if (pos == data.length) {
+ return -1;
+ }
+ int count = Math.min(Math.min(size, data.length - pos), 250);
+ System.arraycopy(data, pos, buf, offset, count);
+ pos += count;
+ return count;
+ }
+ }
+
+ // Same as above, but also implements available().
+ private static final class AvailableStream extends ReluctantStream {
+ public AvailableStream(byte[] data) {
+ super(data);
+ }
+
+ @Override public int available() {
+ return Math.min(250, data.length - pos);
+ }
+ }
+
+ // A stream which exposes the byte array passed into read(byte[], int, int).
+ private static class EvilInputStream extends InputStream {
+ public byte[] capturedArray = null;
+
+ @Override
+ public int read(byte[] buf, int off, int len) {
+ if (capturedArray != null) {
+ return -1;
+ } else {
+ capturedArray = buf;
+ for (int x = 0; x < len; ++x) {
+ buf[x] = (byte) x;
+ }
+ return len;
+ }
+ }
+
+ @Override
+ public int read() {
+ // Purposefully do nothing.
+ return -1;
+ }
+ }
+
+ // A stream which exposes the byte array passed into write(byte[], int, int).
+ private static class EvilOutputStream extends OutputStream {
+ public byte[] capturedArray = null;
+
+ @Override
+ public void write(byte[] buf, int off, int len) {
+ if (capturedArray == null) {
+ capturedArray = buf;
+ }
+ }
+
+ @Override
+ public void write(int ignored) {
+ // Purposefully do nothing.
+ }
+ }
+
+ public void testToStringUtf8() {
+ String testString = "I love unicode \u1234\u5678 characters";
+ byte[] testBytes = testString.getBytes(Internal.UTF_8);
+ ByteString byteString = ByteString.copyFrom(testBytes);
+ assertEquals("copyToStringUtf8 must respect the charset",
+ testString, byteString.toStringUtf8());
+ }
+
+ public void testNewOutput_InitialCapacity() throws IOException {
+ byte[] bytes = getTestBytes();
+ ByteString.Output output = ByteString.newOutput(bytes.length + 100);
+ output.write(bytes);
+ ByteString byteString = output.toByteString();
+ assertTrue(
+ "String built from newOutput(int) must contain the expected bytes",
+ isArrayRange(bytes, byteString.toByteArray(), 0, bytes.length));
+ }
+
+ // Test newOutput() using a variety of buffer sizes and a variety of (fixed)
+ // write sizes
+ public void testNewOutput_ArrayWrite() {
+ byte[] bytes = getTestBytes();
+ int length = bytes.length;
+ int[] bufferSizes = {128, 256, length / 2, length - 1, length, length + 1,
+ 2 * length, 3 * length};
+ int[] writeSizes = {1, 4, 5, 7, 23, bytes.length};
+
+ for (int bufferSize : bufferSizes) {
+ for (int writeSize : writeSizes) {
+ // Test writing the entire output writeSize bytes at a time.
+ ByteString.Output output = ByteString.newOutput(bufferSize);
+ for (int i = 0; i < length; i += writeSize) {
+ output.write(bytes, i, Math.min(writeSize, length - i));
+ }
+ ByteString byteString = output.toByteString();
+ assertTrue("String built from newOutput() must contain the expected bytes",
+ isArrayRange(bytes, byteString.toByteArray(), 0, bytes.length));
+ }
+ }
+ }
+
+ // Test newOutput() using a variety of buffer sizes, but writing all the
+ // characters using write(byte);
+ public void testNewOutput_WriteChar() {
+ byte[] bytes = getTestBytes();
+ int length = bytes.length;
+ int[] bufferSizes = {0, 1, 128, 256, length / 2,
+ length - 1, length, length + 1,
+ 2 * length, 3 * length};
+ for (int bufferSize : bufferSizes) {
+ ByteString.Output output = ByteString.newOutput(bufferSize);
+ for (byte byteValue : bytes) {
+ output.write(byteValue);
+ }
+ ByteString byteString = output.toByteString();
+ assertTrue("String built from newOutput() must contain the expected bytes",
+ isArrayRange(bytes, byteString.toByteArray(), 0, bytes.length));
+ }
+ }
+
+ // Test newOutput() in which we write the bytes using a variety of methods
+ // and sizes, and in which we repeatedly call toByteString() in the middle.
+ public void testNewOutput_Mixed() {
+ Random rng = new Random(1);
+ byte[] bytes = getTestBytes();
+ int length = bytes.length;
+ int[] bufferSizes = {0, 1, 128, 256, length / 2,
+ length - 1, length, length + 1,
+ 2 * length, 3 * length};
+
+ for (int bufferSize : bufferSizes) {
+ // Test writing the entire output using a mixture of write sizes and
+ // methods;
+ ByteString.Output output = ByteString.newOutput(bufferSize);
+ int position = 0;
+ while (position < bytes.length) {
+ if (rng.nextBoolean()) {
+ int count = 1 + rng.nextInt(bytes.length - position);
+ output.write(bytes, position, count);
+ position += count;
+ } else {
+ output.write(bytes[position]);
+ position++;
+ }
+ assertEquals("size() returns the right value", position, output.size());
+ assertTrue("newOutput() substring must have correct bytes",
+ isArrayRange(output.toByteString().toByteArray(),
+ bytes, 0, position));
+ }
+ ByteString byteString = output.toByteString();
+ assertTrue("String built from newOutput() must contain the expected bytes",
+ isArrayRange(bytes, byteString.toByteArray(), 0, bytes.length));
+ }
+ }
+
+ public void testNewOutputEmpty() {
+ // Make sure newOutput() correctly builds empty byte strings
+ ByteString byteString = ByteString.newOutput().toByteString();
+ assertEquals(ByteString.EMPTY, byteString);
+ }
+
+ public void testNewOutput_Mutating() throws IOException {
+ Output os = ByteString.newOutput(5);
+ os.write(new byte[] {1, 2, 3, 4, 5});
+ EvilOutputStream eos = new EvilOutputStream();
+ os.writeTo(eos);
+ byte[] capturedArray = eos.capturedArray;
+ ByteString byteString = os.toByteString();
+ byte[] oldValue = byteString.toByteArray();
+ Arrays.fill(capturedArray, (byte) 0);
+ byte[] newValue = byteString.toByteArray();
+ assertTrue("Output must not provide access to the underlying byte array",
+ Arrays.equals(oldValue, newValue));
+ }
+
+ public void testNewCodedBuilder() throws IOException {
+ byte[] bytes = getTestBytes();
+ ByteString.CodedBuilder builder = ByteString.newCodedBuilder(bytes.length);
+ builder.getCodedOutput().writeRawBytes(bytes);
+ ByteString byteString = builder.build();
+ assertTrue("String built from newCodedBuilder() must contain the expected bytes",
+ isArrayRange(bytes, byteString.toByteArray(), 0, bytes.length));
+ }
+
+ public void testSubstringParity() {
+ byte[] bigBytes = getTestBytes(2048 * 1024, 113344L);
+ int start = 512 * 1024 - 3333;
+ int end = 512 * 1024 + 7777;
+ ByteString concreteSubstring = ByteString.copyFrom(bigBytes).substring(start, end);
+ boolean ok = true;
+ for (int i = start; ok && i < end; ++i) {
+ ok = (bigBytes[i] == concreteSubstring.byteAt(i - start));
+ }
+ assertTrue("Concrete substring didn't capture the right bytes", ok);
+
+ ByteString literalString = ByteString.copyFrom(bigBytes, start, end - start);
+ assertTrue("Substring must be equal to literal string",
+ concreteSubstring.equals(literalString));
+ assertEquals("Substring must have same hashcode as literal string",
+ literalString.hashCode(), concreteSubstring.hashCode());
+ }
+
+ public void testCompositeSubstring() {
+ byte[] referenceBytes = getTestBytes(77748, 113344L);
+
+ List<ByteString> pieces = makeConcretePieces(referenceBytes);
+ ByteString listString = ByteString.copyFrom(pieces);
+
+ int from = 1000;
+ int to = 40000;
+ ByteString compositeSubstring = listString.substring(from, to);
+ byte[] substringBytes = compositeSubstring.toByteArray();
+ boolean stillEqual = true;
+ for (int i = 0; stillEqual && i < to - from; ++i) {
+ stillEqual = referenceBytes[from + i] == substringBytes[i];
+ }
+ assertTrue("Substring must return correct bytes", stillEqual);
+
+ stillEqual = true;
+ for (int i = 0; stillEqual && i < to - from; ++i) {
+ stillEqual = referenceBytes[from + i] == compositeSubstring.byteAt(i);
+ }
+ assertTrue("Substring must support byteAt() correctly", stillEqual);
+
+ ByteString literalSubstring = ByteString.copyFrom(referenceBytes, from, to - from);
+ assertTrue("Composite substring must equal a literal substring over the same bytes",
+ compositeSubstring.equals(literalSubstring));
+ assertTrue("Literal substring must equal a composite substring over the same bytes",
+ literalSubstring.equals(compositeSubstring));
+
+ assertEquals("We must get the same hashcodes for composite and literal substrings",
+ literalSubstring.hashCode(), compositeSubstring.hashCode());
+
+ assertFalse("We can't be equal to a proper substring",
+ compositeSubstring.equals(literalSubstring.substring(0, literalSubstring.size() - 1)));
+ }
+
+ public void testCopyFromList() {
+ byte[] referenceBytes = getTestBytes(77748, 113344L);
+ ByteString literalString = ByteString.copyFrom(referenceBytes);
+
+ List<ByteString> pieces = makeConcretePieces(referenceBytes);
+ ByteString listString = ByteString.copyFrom(pieces);
+
+ assertTrue("Composite string must be equal to literal string",
+ listString.equals(literalString));
+ assertEquals("Composite string must have same hashcode as literal string",
+ literalString.hashCode(), listString.hashCode());
+ }
+
+ public void testConcat() {
+ byte[] referenceBytes = getTestBytes(77748, 113344L);
+ ByteString literalString = ByteString.copyFrom(referenceBytes);
+
+ List<ByteString> pieces = makeConcretePieces(referenceBytes);
+
+ Iterator<ByteString> iter = pieces.iterator();
+ ByteString concatenatedString = iter.next();
+ while (iter.hasNext()) {
+ concatenatedString = concatenatedString.concat(iter.next());
+ }
+
+ assertTrue("Concatenated string must be equal to literal string",
+ concatenatedString.equals(literalString));
+ assertEquals("Concatenated string must have same hashcode as literal string",
+ literalString.hashCode(), concatenatedString.hashCode());
+ }
+
+ /**
+ * Test the Rope implementation can deal with Empty nodes, even though we
+ * guard against them. See also {@link LiteralByteStringTest#testConcat_empty()}.
+ */
+ public void testConcat_empty() {
+ byte[] referenceBytes = getTestBytes(7748, 113344L);
+ ByteString literalString = ByteString.copyFrom(referenceBytes);
+
+ ByteString duo = RopeByteString.newInstanceForTest(literalString, literalString);
+ ByteString temp = RopeByteString.newInstanceForTest(
+ RopeByteString.newInstanceForTest(literalString, ByteString.EMPTY),
+ RopeByteString.newInstanceForTest(ByteString.EMPTY, literalString));
+ ByteString quintet = RopeByteString.newInstanceForTest(temp, ByteString.EMPTY);
+
+ assertTrue("String with concatenated nulls must equal simple concatenate",
+ duo.equals(quintet));
+ assertEquals("String with concatenated nulls have same hashcode as simple concatenate",
+ duo.hashCode(), quintet.hashCode());
+
+ ByteString.ByteIterator duoIter = duo.iterator();
+ ByteString.ByteIterator quintetIter = quintet.iterator();
+ boolean stillEqual = true;
+ while (stillEqual && quintetIter.hasNext()) {
+ stillEqual = (duoIter.nextByte() == quintetIter.nextByte());
+ }
+ assertTrue("We must get the same characters by iterating", stillEqual);
+ assertFalse("Iterator must be exhausted", duoIter.hasNext());
+ try {
+ duoIter.nextByte();
+ fail("Should have thrown an exception.");
+ } catch (NoSuchElementException e) {
+ // This is success
+ }
+ try {
+ quintetIter.nextByte();
+ fail("Should have thrown an exception.");
+ } catch (NoSuchElementException e) {
+ // This is success
+ }
+
+ // Test that even if we force empty strings in as rope leaves in this
+ // configuration, we always get a (possibly Bounded) LiteralByteString
+ // for a length 1 substring.
+ //
+ // It is possible, using the testing factory method to create deeply nested
+ // trees of empty leaves, to make a string that will fail this test.
+ for (int i = 1; i < duo.size(); ++i) {
+ assertTrue("Substrings of size() < 2 must not be RopeByteStrings",
+ duo.substring(i - 1, i) instanceof ByteString.LeafByteString);
+ }
+ for (int i = 1; i < quintet.size(); ++i) {
+ assertTrue("Substrings of size() < 2 must not be RopeByteStrings",
+ quintet.substring(i - 1, i) instanceof ByteString.LeafByteString);
+ }
+ }
+
+ public void testStartsWith() {
+ byte[] bytes = getTestBytes(1000, 1234L);
+ ByteString string = ByteString.copyFrom(bytes);
+ ByteString prefix = ByteString.copyFrom(bytes, 0, 500);
+ ByteString suffix = ByteString.copyFrom(bytes, 400, 600);
+ assertTrue(string.startsWith(ByteString.EMPTY));
+ assertTrue(string.startsWith(string));
+ assertTrue(string.startsWith(prefix));
+ assertFalse(string.startsWith(suffix));
+ assertFalse(prefix.startsWith(suffix));
+ assertFalse(suffix.startsWith(prefix));
+ assertFalse(ByteString.EMPTY.startsWith(prefix));
+ assertTrue(ByteString.EMPTY.startsWith(ByteString.EMPTY));
+ }
+
+ public void testEndsWith() {
+ byte[] bytes = getTestBytes(1000, 1234L);
+ ByteString string = ByteString.copyFrom(bytes);
+ ByteString prefix = ByteString.copyFrom(bytes, 0, 500);
+ ByteString suffix = ByteString.copyFrom(bytes, 400, 600);
+ assertTrue(string.endsWith(ByteString.EMPTY));
+ assertTrue(string.endsWith(string));
+ assertTrue(string.endsWith(suffix));
+ assertFalse(string.endsWith(prefix));
+ assertFalse(suffix.endsWith(prefix));
+ assertFalse(prefix.endsWith(suffix));
+ assertFalse(ByteString.EMPTY.endsWith(suffix));
+ assertTrue(ByteString.EMPTY.endsWith(ByteString.EMPTY));
+ }
+
+ static List<ByteString> makeConcretePieces(byte[] referenceBytes) {
+ List<ByteString> pieces = new ArrayList<ByteString>();
+ // Starting length should be small enough that we'll do some concatenating by
+ // copying if we just concatenate all these pieces together.
+ for (int start = 0, length = 16; start < referenceBytes.length; start += length) {
+ length = (length << 1) - 1;
+ if (start + length > referenceBytes.length) {
+ length = referenceBytes.length - start;
+ }
+ pieces.add(ByteString.copyFrom(referenceBytes, start, length));
+ }
+ return pieces;
+ }
+
+ private byte[] substringUsingWriteTo(
+ ByteString data, int offset, int length) throws IOException {
+ ByteArrayOutputStream output = new ByteArrayOutputStream();
+ data.writeTo(output, offset, length);
+ return output.toByteArray();
+ }
+
+ public void testWriteToOutputStream() throws Exception {
+ // Choose a size large enough so when two ByteStrings are concatenated they
+ // won't be merged into one byte array due to some optimizations.
+ final int dataSize = ByteString.CONCATENATE_BY_COPY_SIZE + 1;
+ byte[] data1 = new byte[dataSize];
+ for (int i = 0; i < data1.length; i++) {
+ data1[i] = (byte) 1;
+ }
+ data1[1] = (byte) 11;
+ // Test LiteralByteString.writeTo(OutputStream,int,int)
+ ByteString left = ByteString.wrap(data1);
+ byte[] result = substringUsingWriteTo(left, 1, 1);
+ assertEquals(1, result.length);
+ assertEquals((byte) 11, result[0]);
+
+ byte[] data2 = new byte[dataSize];
+ for (int i = 0; i < data1.length; i++) {
+ data2[i] = (byte) 2;
+ }
+ ByteString right = ByteString.wrap(data2);
+ // Concatenate two ByteStrings to create a RopeByteString.
+ ByteString root = left.concat(right);
+ // Make sure we are actually testing a RopeByteString with a simple tree
+ // structure.
+ assertEquals(1, root.getTreeDepth());
+ // Write parts of the left node.
+ result = substringUsingWriteTo(root, 0, dataSize);
+ assertEquals(dataSize, result.length);
+ assertEquals((byte) 1, result[0]);
+ assertEquals((byte) 1, result[dataSize - 1]);
+ // Write parts of the right node.
+ result = substringUsingWriteTo(root, dataSize, dataSize);
+ assertEquals(dataSize, result.length);
+ assertEquals((byte) 2, result[0]);
+ assertEquals((byte) 2, result[dataSize - 1]);
+ // Write a segment of bytes that runs across both nodes.
+ result = substringUsingWriteTo(root, dataSize / 2, dataSize);
+ assertEquals(dataSize, result.length);
+ assertEquals((byte) 1, result[0]);
+ assertEquals((byte) 1, result[dataSize - dataSize / 2 - 1]);
+ assertEquals((byte) 2, result[dataSize - dataSize / 2]);
+ assertEquals((byte) 2, result[dataSize - 1]);
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/CheckUtf8Test.java b/java/core/src/test/java/com/google/protobuf/CheckUtf8Test.java
new file mode 100644
index 00000000..3d6381c9
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/CheckUtf8Test.java
@@ -0,0 +1,140 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// 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 proto2_test_check_utf8.TestCheckUtf8.BytesWrapper;
+import proto2_test_check_utf8.TestCheckUtf8.StringWrapper;
+import proto2_test_check_utf8_size.TestCheckUtf8Size.BytesWrapperSize;
+import proto2_test_check_utf8_size.TestCheckUtf8Size.StringWrapperSize;
+import junit.framework.TestCase;
+
+/**
+ * Test that protos generated with file option java_string_check_utf8 do in
+ * fact perform appropriate UTF-8 checks.
+ *
+ * @author jbaum@google.com (Jacob Butcher)
+ */
+public class CheckUtf8Test extends TestCase {
+
+ private static final String UTF8_BYTE_STRING_TEXT = "some text";
+ private static final ByteString UTF8_BYTE_STRING =
+ ByteString.copyFromUtf8(UTF8_BYTE_STRING_TEXT);
+ private static final ByteString NON_UTF8_BYTE_STRING =
+ ByteString.copyFrom(new byte[]{(byte) 0x80}); // A lone continuation byte.
+
+ public void testBuildRequiredStringWithGoodUtf8() throws Exception {
+ assertEquals(UTF8_BYTE_STRING_TEXT,
+ StringWrapper.newBuilder().setReqBytes(UTF8_BYTE_STRING).getReq());
+ }
+
+ public void testParseRequiredStringWithGoodUtf8() throws Exception {
+ ByteString serialized =
+ BytesWrapper.newBuilder().setReq(UTF8_BYTE_STRING).build().toByteString();
+ assertEquals(UTF8_BYTE_STRING_TEXT, StringWrapper.parser().parseFrom(serialized).getReq());
+ }
+
+ public void testBuildRequiredStringWithBadUtf8() throws Exception {
+ try {
+ StringWrapper.newBuilder().setReqBytes(NON_UTF8_BYTE_STRING);
+ fail("Expected IllegalArgumentException for non UTF-8 byte string.");
+ } catch (IllegalArgumentException exception) {
+ assertEquals("Byte string is not UTF-8.", exception.getMessage());
+ }
+ }
+
+ public void testBuildOptionalStringWithBadUtf8() throws Exception {
+ try {
+ StringWrapper.newBuilder().setOptBytes(NON_UTF8_BYTE_STRING);
+ fail("Expected IllegalArgumentException for non UTF-8 byte string.");
+ } catch (IllegalArgumentException exception) {
+ assertEquals("Byte string is not UTF-8.", exception.getMessage());
+ }
+ }
+
+ public void testBuildRepeatedStringWithBadUtf8() throws Exception {
+ try {
+ StringWrapper.newBuilder().addRepBytes(NON_UTF8_BYTE_STRING);
+ fail("Expected IllegalArgumentException for non UTF-8 byte string.");
+ } catch (IllegalArgumentException exception) {
+ assertEquals("Byte string is not UTF-8.", exception.getMessage());
+ }
+ }
+
+ public void testParseRequiredStringWithBadUtf8() throws Exception {
+ ByteString serialized =
+ BytesWrapper.newBuilder().setReq(NON_UTF8_BYTE_STRING).build().toByteString();
+ try {
+ StringWrapper.parser().parseFrom(serialized);
+ fail("Expected InvalidProtocolBufferException for non UTF-8 byte string.");
+ } catch (InvalidProtocolBufferException exception) {
+ assertEquals("Protocol message had invalid UTF-8.", exception.getMessage());
+ }
+ }
+
+ public void testBuildRequiredStringWithBadUtf8Size() throws Exception {
+ try {
+ StringWrapperSize.newBuilder().setReqBytes(NON_UTF8_BYTE_STRING);
+ fail("Expected IllegalArgumentException for non UTF-8 byte string.");
+ } catch (IllegalArgumentException exception) {
+ assertEquals("Byte string is not UTF-8.", exception.getMessage());
+ }
+ }
+
+ public void testBuildOptionalStringWithBadUtf8Size() throws Exception {
+ try {
+ StringWrapperSize.newBuilder().setOptBytes(NON_UTF8_BYTE_STRING);
+ fail("Expected IllegalArgumentException for non UTF-8 byte string.");
+ } catch (IllegalArgumentException exception) {
+ assertEquals("Byte string is not UTF-8.", exception.getMessage());
+ }
+ }
+
+ public void testBuildRepeatedStringWithBadUtf8Size() throws Exception {
+ try {
+ StringWrapperSize.newBuilder().addRepBytes(NON_UTF8_BYTE_STRING);
+ fail("Expected IllegalArgumentException for non UTF-8 byte string.");
+ } catch (IllegalArgumentException exception) {
+ assertEquals("Byte string is not UTF-8.", exception.getMessage());
+ }
+ }
+
+ public void testParseRequiredStringWithBadUtf8Size() throws Exception {
+ ByteString serialized =
+ BytesWrapperSize.newBuilder().setReq(NON_UTF8_BYTE_STRING).build().toByteString();
+ try {
+ StringWrapperSize.parser().parseFrom(serialized);
+ fail("Expected InvalidProtocolBufferException for non UTF-8 byte string.");
+ } catch (InvalidProtocolBufferException exception) {
+ assertEquals("Protocol message had invalid UTF-8.", exception.getMessage());
+ }
+ }
+
+}
diff --git a/java/core/src/test/java/com/google/protobuf/CodedInputStreamTest.java b/java/core/src/test/java/com/google/protobuf/CodedInputStreamTest.java
new file mode 100644
index 00000000..18d8142c
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/CodedInputStreamTest.java
@@ -0,0 +1,769 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// 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.UnittestProto.BoolMessage;
+import protobuf_unittest.UnittestProto.Int32Message;
+import protobuf_unittest.UnittestProto.Int64Message;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.TestRecursiveMessage;
+
+import junit.framework.TestCase;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+
+/**
+ * Unit test for {@link CodedInputStream}.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public class CodedInputStreamTest extends TestCase {
+ /**
+ * Helper to construct a byte array from a bunch of bytes. The inputs are
+ * actually ints so that I can use hex notation and not get stupid errors
+ * about precision.
+ */
+ private byte[] bytes(int... bytesAsInts) {
+ byte[] bytes = new byte[bytesAsInts.length];
+ for (int i = 0; i < bytesAsInts.length; i++) {
+ bytes[i] = (byte) bytesAsInts[i];
+ }
+ return bytes;
+ }
+
+ /**
+ * An InputStream which limits the number of bytes it reads at a time.
+ * We use this to make sure that CodedInputStream doesn't screw up when
+ * reading in small blocks.
+ */
+ private static final class SmallBlockInputStream extends FilterInputStream {
+ private final int blockSize;
+
+ public SmallBlockInputStream(byte[] data, int blockSize) {
+ this(new ByteArrayInputStream(data), blockSize);
+ }
+
+ public SmallBlockInputStream(InputStream in, int blockSize) {
+ super(in);
+ this.blockSize = blockSize;
+ }
+
+ public int read(byte[] b) throws IOException {
+ return super.read(b, 0, Math.min(b.length, blockSize));
+ }
+
+ public int read(byte[] b, int off, int len) throws IOException {
+ return super.read(b, off, Math.min(len, blockSize));
+ }
+ }
+
+ private void assertDataConsumed(byte[] data, CodedInputStream input)
+ throws IOException {
+ assertEquals(data.length, input.getTotalBytesRead());
+ assertTrue(input.isAtEnd());
+ }
+
+ /**
+ * Parses the given bytes using readRawVarint32() and readRawVarint64() and
+ * checks that the result matches the given value.
+ */
+ private void assertReadVarint(byte[] data, long value) throws Exception {
+ CodedInputStream input = CodedInputStream.newInstance(data);
+ assertEquals((int) value, input.readRawVarint32());
+ assertDataConsumed(data, input);
+
+ input = CodedInputStream.newInstance(data);
+ assertEquals(value, input.readRawVarint64());
+ assertDataConsumed(data, input);
+
+ input = CodedInputStream.newInstance(data);
+ assertEquals(value, input.readRawVarint64SlowPath());
+ assertDataConsumed(data, input);
+
+ input = CodedInputStream.newInstance(data);
+ assertTrue(input.skipField(WireFormat.WIRETYPE_VARINT));
+ assertDataConsumed(data, input);
+
+ // Try different block sizes.
+ for (int blockSize = 1; blockSize <= 16; blockSize *= 2) {
+ input = CodedInputStream.newInstance(
+ new SmallBlockInputStream(data, blockSize));
+ assertEquals((int) value, input.readRawVarint32());
+ assertDataConsumed(data, input);
+
+ input = CodedInputStream.newInstance(
+ new SmallBlockInputStream(data, blockSize));
+ assertEquals(value, input.readRawVarint64());
+ assertDataConsumed(data, input);
+
+ input = CodedInputStream.newInstance(
+ new SmallBlockInputStream(data, blockSize));
+ assertEquals(value, input.readRawVarint64SlowPath());
+ assertDataConsumed(data, input);
+
+ input = CodedInputStream.newInstance(
+ new SmallBlockInputStream(data, blockSize));
+ assertTrue(input.skipField(WireFormat.WIRETYPE_VARINT));
+ assertDataConsumed(data, input);
+ }
+
+ // Try reading direct from an InputStream. We want to verify that it
+ // doesn't read past the end of the input, so we copy to a new, bigger
+ // array first.
+ byte[] longerData = new byte[data.length + 1];
+ System.arraycopy(data, 0, longerData, 0, data.length);
+ InputStream rawInput = new ByteArrayInputStream(longerData);
+ assertEquals((int) value, CodedInputStream.readRawVarint32(rawInput));
+ assertEquals(1, rawInput.available());
+ }
+
+ /**
+ * Parses the given bytes using readRawVarint32() and readRawVarint64() and
+ * expects them to fail with an InvalidProtocolBufferException whose
+ * description matches the given one.
+ */
+ private void assertReadVarintFailure(
+ InvalidProtocolBufferException expected, byte[] data)
+ throws Exception {
+ CodedInputStream input = CodedInputStream.newInstance(data);
+ try {
+ input.readRawVarint32();
+ fail("Should have thrown an exception.");
+ } catch (InvalidProtocolBufferException e) {
+ assertEquals(expected.getMessage(), e.getMessage());
+ }
+
+ input = CodedInputStream.newInstance(data);
+ try {
+ input.readRawVarint64();
+ fail("Should have thrown an exception.");
+ } catch (InvalidProtocolBufferException e) {
+ assertEquals(expected.getMessage(), e.getMessage());
+ }
+
+ input = CodedInputStream.newInstance(data);
+ try {
+ input.readRawVarint64SlowPath();
+ fail("Should have thrown an exception.");
+ } catch (InvalidProtocolBufferException e) {
+ assertEquals(expected.getMessage(), e.getMessage());
+ }
+
+ // Make sure we get the same error when reading direct from an InputStream.
+ try {
+ CodedInputStream.readRawVarint32(new ByteArrayInputStream(data));
+ fail("Should have thrown an exception.");
+ } catch (InvalidProtocolBufferException e) {
+ assertEquals(expected.getMessage(), e.getMessage());
+ }
+ }
+
+ /** Tests readRawVarint32() and readRawVarint64(). */
+ public void testReadVarint() throws Exception {
+ assertReadVarint(bytes(0x00), 0);
+ assertReadVarint(bytes(0x01), 1);
+ assertReadVarint(bytes(0x7f), 127);
+ // 14882
+ assertReadVarint(bytes(0xa2, 0x74), (0x22 << 0) | (0x74 << 7));
+ // 2961488830
+ assertReadVarint(bytes(0xbe, 0xf7, 0x92, 0x84, 0x0b),
+ (0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) |
+ (0x0bL << 28));
+
+ // 64-bit
+ // 7256456126
+ assertReadVarint(bytes(0xbe, 0xf7, 0x92, 0x84, 0x1b),
+ (0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) |
+ (0x1bL << 28));
+ // 41256202580718336
+ assertReadVarint(
+ bytes(0x80, 0xe6, 0xeb, 0x9c, 0xc3, 0xc9, 0xa4, 0x49),
+ (0x00 << 0) | (0x66 << 7) | (0x6b << 14) | (0x1c << 21) |
+ (0x43L << 28) | (0x49L << 35) | (0x24L << 42) | (0x49L << 49));
+ // 11964378330978735131
+ assertReadVarint(
+ bytes(0x9b, 0xa8, 0xf9, 0xc2, 0xbb, 0xd6, 0x80, 0x85, 0xa6, 0x01),
+ (0x1b << 0) | (0x28 << 7) | (0x79 << 14) | (0x42 << 21) |
+ (0x3bL << 28) | (0x56L << 35) | (0x00L << 42) |
+ (0x05L << 49) | (0x26L << 56) | (0x01L << 63));
+
+ // Failures
+ assertReadVarintFailure(
+ InvalidProtocolBufferException.malformedVarint(),
+ bytes(0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x00));
+ assertReadVarintFailure(
+ InvalidProtocolBufferException.truncatedMessage(),
+ bytes(0x80));
+ }
+
+ /**
+ * Parses the given bytes using readRawLittleEndian32() and checks
+ * that the result matches the given value.
+ */
+ private void assertReadLittleEndian32(byte[] data, int value)
+ throws Exception {
+ CodedInputStream input = CodedInputStream.newInstance(data);
+ assertEquals(value, input.readRawLittleEndian32());
+ assertTrue(input.isAtEnd());
+
+ // Try different block sizes.
+ for (int blockSize = 1; blockSize <= 16; blockSize *= 2) {
+ input = CodedInputStream.newInstance(
+ new SmallBlockInputStream(data, blockSize));
+ assertEquals(value, input.readRawLittleEndian32());
+ assertTrue(input.isAtEnd());
+ }
+ }
+
+ /**
+ * Parses the given bytes using readRawLittleEndian64() and checks
+ * that the result matches the given value.
+ */
+ private void assertReadLittleEndian64(byte[] data, long value)
+ throws Exception {
+ CodedInputStream input = CodedInputStream.newInstance(data);
+ assertEquals(value, input.readRawLittleEndian64());
+ assertTrue(input.isAtEnd());
+
+ // Try different block sizes.
+ for (int blockSize = 1; blockSize <= 16; blockSize *= 2) {
+ input = CodedInputStream.newInstance(
+ new SmallBlockInputStream(data, blockSize));
+ assertEquals(value, input.readRawLittleEndian64());
+ assertTrue(input.isAtEnd());
+ }
+ }
+
+ /** Tests readRawLittleEndian32() and readRawLittleEndian64(). */
+ public void testReadLittleEndian() throws Exception {
+ assertReadLittleEndian32(bytes(0x78, 0x56, 0x34, 0x12), 0x12345678);
+ assertReadLittleEndian32(bytes(0xf0, 0xde, 0xbc, 0x9a), 0x9abcdef0);
+
+ assertReadLittleEndian64(
+ bytes(0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12),
+ 0x123456789abcdef0L);
+ assertReadLittleEndian64(
+ bytes(0x78, 0x56, 0x34, 0x12, 0xf0, 0xde, 0xbc, 0x9a),
+ 0x9abcdef012345678L);
+ }
+
+ /** Test decodeZigZag32() and decodeZigZag64(). */
+ public void testDecodeZigZag() throws Exception {
+ assertEquals( 0, CodedInputStream.decodeZigZag32(0));
+ assertEquals(-1, CodedInputStream.decodeZigZag32(1));
+ assertEquals( 1, CodedInputStream.decodeZigZag32(2));
+ assertEquals(-2, CodedInputStream.decodeZigZag32(3));
+ assertEquals(0x3FFFFFFF, CodedInputStream.decodeZigZag32(0x7FFFFFFE));
+ assertEquals(0xC0000000, CodedInputStream.decodeZigZag32(0x7FFFFFFF));
+ assertEquals(0x7FFFFFFF, CodedInputStream.decodeZigZag32(0xFFFFFFFE));
+ assertEquals(0x80000000, CodedInputStream.decodeZigZag32(0xFFFFFFFF));
+
+ assertEquals( 0, CodedInputStream.decodeZigZag64(0));
+ assertEquals(-1, CodedInputStream.decodeZigZag64(1));
+ assertEquals( 1, CodedInputStream.decodeZigZag64(2));
+ assertEquals(-2, CodedInputStream.decodeZigZag64(3));
+ assertEquals(0x000000003FFFFFFFL,
+ CodedInputStream.decodeZigZag64(0x000000007FFFFFFEL));
+ assertEquals(0xFFFFFFFFC0000000L,
+ CodedInputStream.decodeZigZag64(0x000000007FFFFFFFL));
+ assertEquals(0x000000007FFFFFFFL,
+ CodedInputStream.decodeZigZag64(0x00000000FFFFFFFEL));
+ assertEquals(0xFFFFFFFF80000000L,
+ CodedInputStream.decodeZigZag64(0x00000000FFFFFFFFL));
+ assertEquals(0x7FFFFFFFFFFFFFFFL,
+ CodedInputStream.decodeZigZag64(0xFFFFFFFFFFFFFFFEL));
+ assertEquals(0x8000000000000000L,
+ CodedInputStream.decodeZigZag64(0xFFFFFFFFFFFFFFFFL));
+ }
+
+ /** Tests reading and parsing a whole message with every field type. */
+ public void testReadWholeMessage() throws Exception {
+ TestAllTypes message = TestUtil.getAllSet();
+
+ byte[] rawBytes = message.toByteArray();
+ assertEquals(rawBytes.length, message.getSerializedSize());
+
+ TestAllTypes message2 = TestAllTypes.parseFrom(rawBytes);
+ TestUtil.assertAllFieldsSet(message2);
+
+ // Try different block sizes.
+ for (int blockSize = 1; blockSize < 256; blockSize *= 2) {
+ message2 = TestAllTypes.parseFrom(
+ new SmallBlockInputStream(rawBytes, blockSize));
+ TestUtil.assertAllFieldsSet(message2);
+ }
+ }
+
+ /** Tests skipField(). */
+ public void testSkipWholeMessage() throws Exception {
+ TestAllTypes message = TestUtil.getAllSet();
+ byte[] rawBytes = message.toByteArray();
+
+ // Create two parallel inputs. Parse one as unknown fields while using
+ // skipField() to skip each field on the other. Expect the same tags.
+ CodedInputStream input1 = CodedInputStream.newInstance(rawBytes);
+ CodedInputStream input2 = CodedInputStream.newInstance(rawBytes);
+ UnknownFieldSet.Builder unknownFields = UnknownFieldSet.newBuilder();
+
+ while (true) {
+ int tag = input1.readTag();
+ assertEquals(tag, input2.readTag());
+ if (tag == 0) {
+ break;
+ }
+ unknownFields.mergeFieldFrom(tag, input1);
+ input2.skipField(tag);
+ }
+ }
+
+
+ /**
+ * Test that a bug in skipRawBytes() has been fixed: if the skip skips
+ * exactly up to a limit, this should not break things.
+ */
+ public void testSkipRawBytesBug() throws Exception {
+ byte[] rawBytes = new byte[] { 1, 2 };
+ CodedInputStream input = CodedInputStream.newInstance(rawBytes);
+
+ int limit = input.pushLimit(1);
+ input.skipRawBytes(1);
+ input.popLimit(limit);
+ assertEquals(2, input.readRawByte());
+ }
+
+ /**
+ * Test that a bug in skipRawBytes() has been fixed: if the skip skips
+ * past the end of a buffer with a limit that has been set past the end of
+ * that buffer, this should not break things.
+ */
+ public void testSkipRawBytesPastEndOfBufferWithLimit() throws Exception {
+ byte[] rawBytes = new byte[] { 1, 2, 3, 4, 5 };
+ CodedInputStream input = CodedInputStream.newInstance(
+ new SmallBlockInputStream(rawBytes, 3));
+
+ int limit = input.pushLimit(4);
+ // In order to expose the bug we need to read at least one byte to prime the
+ // buffer inside the CodedInputStream.
+ assertEquals(1, input.readRawByte());
+ // Skip to the end of the limit.
+ input.skipRawBytes(3);
+ assertTrue(input.isAtEnd());
+ input.popLimit(limit);
+ assertEquals(5, input.readRawByte());
+ }
+
+ public void testReadHugeBlob() throws Exception {
+ // Allocate and initialize a 1MB blob.
+ byte[] blob = new byte[1 << 20];
+ for (int i = 0; i < blob.length; i++) {
+ blob[i] = (byte) i;
+ }
+
+ // Make a message containing it.
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TestUtil.setAllFields(builder);
+ builder.setOptionalBytes(ByteString.copyFrom(blob));
+ TestAllTypes message = builder.build();
+
+ // Serialize and parse it. Make sure to parse from an InputStream, not
+ // directly from a ByteString, so that CodedInputStream uses buffered
+ // reading.
+ TestAllTypes message2 =
+ TestAllTypes.parseFrom(message.toByteString().newInput());
+
+ assertEquals(message.getOptionalBytes(), message2.getOptionalBytes());
+
+ // Make sure all the other fields were parsed correctly.
+ TestAllTypes message3 = TestAllTypes.newBuilder(message2)
+ .setOptionalBytes(TestUtil.getAllSet().getOptionalBytes())
+ .build();
+ TestUtil.assertAllFieldsSet(message3);
+ }
+
+ public void testReadMaliciouslyLargeBlob() throws Exception {
+ ByteString.Output rawOutput = ByteString.newOutput();
+ CodedOutputStream output = CodedOutputStream.newInstance(rawOutput);
+
+ int tag = WireFormat.makeTag(1, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+ output.writeRawVarint32(tag);
+ output.writeRawVarint32(0x7FFFFFFF);
+ output.writeRawBytes(new byte[32]); // Pad with a few random bytes.
+ output.flush();
+
+ CodedInputStream input = rawOutput.toByteString().newCodedInput();
+ assertEquals(tag, input.readTag());
+
+ try {
+ input.readBytes();
+ fail("Should have thrown an exception!");
+ } catch (InvalidProtocolBufferException e) {
+ // success.
+ }
+ }
+
+ private TestRecursiveMessage makeRecursiveMessage(int depth) {
+ if (depth == 0) {
+ return TestRecursiveMessage.newBuilder().setI(5).build();
+ } else {
+ return TestRecursiveMessage.newBuilder()
+ .setA(makeRecursiveMessage(depth - 1)).build();
+ }
+ }
+
+ private void assertMessageDepth(TestRecursiveMessage message, int depth) {
+ if (depth == 0) {
+ assertFalse(message.hasA());
+ assertEquals(5, message.getI());
+ } else {
+ assertTrue(message.hasA());
+ assertMessageDepth(message.getA(), depth - 1);
+ }
+ }
+
+ public void testMaliciousRecursion() throws Exception {
+ ByteString data100 = makeRecursiveMessage(100).toByteString();
+ ByteString data101 = makeRecursiveMessage(101).toByteString();
+
+ assertMessageDepth(TestRecursiveMessage.parseFrom(data100), 100);
+
+ try {
+ TestRecursiveMessage.parseFrom(data101);
+ fail("Should have thrown an exception!");
+ } catch (InvalidProtocolBufferException e) {
+ // success.
+ }
+
+ CodedInputStream input = data100.newCodedInput();
+ input.setRecursionLimit(8);
+ try {
+ TestRecursiveMessage.parseFrom(input);
+ fail("Should have thrown an exception!");
+ } catch (InvalidProtocolBufferException e) {
+ // success.
+ }
+ }
+
+ private void checkSizeLimitExceeded(InvalidProtocolBufferException e) {
+ assertEquals(
+ InvalidProtocolBufferException.sizeLimitExceeded().getMessage(),
+ e.getMessage());
+ }
+
+ public void testSizeLimit() throws Exception {
+ CodedInputStream input = CodedInputStream.newInstance(
+ new SmallBlockInputStream(
+ TestUtil.getAllSet().toByteString().newInput(), 16));
+ input.setSizeLimit(16);
+
+ try {
+ TestAllTypes.parseFrom(input);
+ fail("Should have thrown an exception!");
+ } catch (InvalidProtocolBufferException expected) {
+ checkSizeLimitExceeded(expected);
+ }
+ }
+
+ public void testResetSizeCounter() throws Exception {
+ CodedInputStream input = CodedInputStream.newInstance(
+ new SmallBlockInputStream(new byte[256], 8));
+ input.setSizeLimit(16);
+ input.readRawBytes(16);
+ assertEquals(16, input.getTotalBytesRead());
+
+ try {
+ input.readRawByte();
+ fail("Should have thrown an exception!");
+ } catch (InvalidProtocolBufferException expected) {
+ checkSizeLimitExceeded(expected);
+ }
+
+ input.resetSizeCounter();
+ assertEquals(0, input.getTotalBytesRead());
+ input.readRawByte(); // No exception thrown.
+ input.resetSizeCounter();
+ assertEquals(0, input.getTotalBytesRead());
+ input.readRawBytes(16);
+ assertEquals(16, input.getTotalBytesRead());
+ input.resetSizeCounter();
+
+ try {
+ input.readRawBytes(17); // Hits limit again.
+ fail("Should have thrown an exception!");
+ } catch (InvalidProtocolBufferException expected) {
+ checkSizeLimitExceeded(expected);
+ }
+ }
+
+ public void testSizeLimitMultipleMessages() throws Exception {
+ byte[] bytes = new byte[256];
+ for (int i = 0; i < bytes.length; i++) {
+ bytes[i] = (byte) i;
+ }
+ CodedInputStream input = CodedInputStream.newInstance(
+ new SmallBlockInputStream(bytes, 7));
+ input.setSizeLimit(16);
+ for (int i = 0; i < 256 / 16; i++) {
+ byte[] message = input.readRawBytes(16);
+ for (int j = 0; j < message.length; j++) {
+ assertEquals(i * 16 + j, message[j] & 0xff);
+ }
+ assertEquals(16, input.getTotalBytesRead());
+ input.resetSizeCounter();
+ assertEquals(0, input.getTotalBytesRead());
+ }
+ }
+
+ /**
+ * Tests that if we readString invalid UTF-8 bytes, no exception
+ * is thrown. Instead, the invalid bytes are replaced with the Unicode
+ * "replacement character" U+FFFD.
+ */
+ public void testReadStringInvalidUtf8() throws Exception {
+ ByteString.Output rawOutput = ByteString.newOutput();
+ CodedOutputStream output = CodedOutputStream.newInstance(rawOutput);
+
+ int tag = WireFormat.makeTag(1, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+ output.writeRawVarint32(tag);
+ output.writeRawVarint32(1);
+ output.writeRawBytes(new byte[] { (byte) 0x80 });
+ output.flush();
+
+ CodedInputStream input = rawOutput.toByteString().newCodedInput();
+ assertEquals(tag, input.readTag());
+ String text = input.readString();
+ assertEquals(0xfffd, text.charAt(0));
+ }
+
+ /**
+ * Tests that if we readStringRequireUtf8 invalid UTF-8 bytes, an
+ * InvalidProtocolBufferException is thrown.
+ */
+ public void testReadStringRequireUtf8InvalidUtf8() throws Exception {
+ ByteString.Output rawOutput = ByteString.newOutput();
+ CodedOutputStream output = CodedOutputStream.newInstance(rawOutput);
+
+ int tag = WireFormat.makeTag(1, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+ output.writeRawVarint32(tag);
+ output.writeRawVarint32(1);
+ output.writeRawBytes(new byte[] { (byte) 0x80 });
+ output.flush();
+
+ CodedInputStream input = rawOutput.toByteString().newCodedInput();
+ assertEquals(tag, input.readTag());
+ try {
+ input.readStringRequireUtf8();
+ fail("Expected invalid UTF-8 exception.");
+ } catch (InvalidProtocolBufferException exception) {
+ assertEquals("Protocol message had invalid UTF-8.", exception.getMessage());
+ }
+ }
+
+ public void testReadFromSlice() throws Exception {
+ byte[] bytes = bytes(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
+ CodedInputStream in = CodedInputStream.newInstance(bytes, 3, 5);
+ assertEquals(0, in.getTotalBytesRead());
+ for (int i = 3; i < 8; i++) {
+ assertEquals(i, in.readRawByte());
+ assertEquals(i - 2, in.getTotalBytesRead());
+ }
+ // eof
+ assertEquals(0, in.readTag());
+ assertEquals(5, in.getTotalBytesRead());
+ }
+
+ public void testInvalidTag() throws Exception {
+ // Any tag number which corresponds to field number zero is invalid and
+ // should throw InvalidProtocolBufferException.
+ for (int i = 0; i < 8; i++) {
+ try {
+ CodedInputStream.newInstance(bytes(i)).readTag();
+ fail("Should have thrown an exception.");
+ } catch (InvalidProtocolBufferException e) {
+ assertEquals(InvalidProtocolBufferException.invalidTag().getMessage(),
+ e.getMessage());
+ }
+ }
+ }
+
+ public void testReadByteArray() throws Exception {
+ ByteString.Output rawOutput = ByteString.newOutput();
+ CodedOutputStream output = CodedOutputStream.newInstance(rawOutput);
+ // Zero-sized bytes field.
+ output.writeRawVarint32(0);
+ // One one-byte bytes field
+ output.writeRawVarint32(1);
+ output.writeRawBytes(new byte[] { (byte) 23 });
+ // Another one-byte bytes field
+ output.writeRawVarint32(1);
+ output.writeRawBytes(new byte[] { (byte) 45 });
+ // A bytes field large enough that won't fit into the 4K buffer.
+ final int bytesLength = 16 * 1024;
+ byte[] bytes = new byte[bytesLength];
+ bytes[0] = (byte) 67;
+ bytes[bytesLength - 1] = (byte) 89;
+ output.writeRawVarint32(bytesLength);
+ output.writeRawBytes(bytes);
+
+ output.flush();
+ CodedInputStream inputStream = rawOutput.toByteString().newCodedInput();
+
+ byte[] result = inputStream.readByteArray();
+ assertEquals(0, result.length);
+ result = inputStream.readByteArray();
+ assertEquals(1, result.length);
+ assertEquals((byte) 23, result[0]);
+ result = inputStream.readByteArray();
+ assertEquals(1, result.length);
+ assertEquals((byte) 45, result[0]);
+ result = inputStream.readByteArray();
+ assertEquals(bytesLength, result.length);
+ assertEquals((byte) 67, result[0]);
+ assertEquals((byte) 89, result[bytesLength - 1]);
+ }
+
+ public void testReadByteBuffer() throws Exception {
+ ByteString.Output rawOutput = ByteString.newOutput();
+ CodedOutputStream output = CodedOutputStream.newInstance(rawOutput);
+ // Zero-sized bytes field.
+ output.writeRawVarint32(0);
+ // One one-byte bytes field
+ output.writeRawVarint32(1);
+ output.writeRawBytes(new byte[]{(byte) 23});
+ // Another one-byte bytes field
+ output.writeRawVarint32(1);
+ output.writeRawBytes(new byte[]{(byte) 45});
+ // A bytes field large enough that won't fit into the 4K buffer.
+ final int bytesLength = 16 * 1024;
+ byte[] bytes = new byte[bytesLength];
+ bytes[0] = (byte) 67;
+ bytes[bytesLength - 1] = (byte) 89;
+ output.writeRawVarint32(bytesLength);
+ output.writeRawBytes(bytes);
+
+ output.flush();
+ CodedInputStream inputStream = rawOutput.toByteString().newCodedInput();
+
+ ByteBuffer result = inputStream.readByteBuffer();
+ assertEquals(0, result.capacity());
+ result = inputStream.readByteBuffer();
+ assertEquals(1, result.capacity());
+ assertEquals((byte) 23, result.get());
+ result = inputStream.readByteBuffer();
+ assertEquals(1, result.capacity());
+ assertEquals((byte) 45, result.get());
+ result = inputStream.readByteBuffer();
+ assertEquals(bytesLength, result.capacity());
+ assertEquals((byte) 67, result.get());
+ result.position(bytesLength - 1);
+ assertEquals((byte) 89, result.get());
+ }
+
+ public void testReadByteBufferAliasing() throws Exception {
+ ByteArrayOutputStream byteArrayStream = new ByteArrayOutputStream();
+ CodedOutputStream output = CodedOutputStream.newInstance(byteArrayStream);
+ // Zero-sized bytes field.
+ output.writeRawVarint32(0);
+ // One one-byte bytes field
+ output.writeRawVarint32(1);
+ output.writeRawBytes(new byte[]{(byte) 23});
+ // Another one-byte bytes field
+ output.writeRawVarint32(1);
+ output.writeRawBytes(new byte[]{(byte) 45});
+ // A bytes field large enough that won't fit into the 4K buffer.
+ final int bytesLength = 16 * 1024;
+ byte[] bytes = new byte[bytesLength];
+ bytes[0] = (byte) 67;
+ bytes[bytesLength - 1] = (byte) 89;
+ output.writeRawVarint32(bytesLength);
+ output.writeRawBytes(bytes);
+ output.flush();
+ byte[] data = byteArrayStream.toByteArray();
+
+ // Without aliasing
+ CodedInputStream inputStream = CodedInputStream.newInstance(data);
+ ByteBuffer result = inputStream.readByteBuffer();
+ assertEquals(0, result.capacity());
+ result = inputStream.readByteBuffer();
+ assertTrue(result.array() != data);
+ assertEquals(1, result.capacity());
+ assertEquals((byte) 23, result.get());
+ result = inputStream.readByteBuffer();
+ assertTrue(result.array() != data);
+ assertEquals(1, result.capacity());
+ assertEquals((byte) 45, result.get());
+ result = inputStream.readByteBuffer();
+ assertTrue(result.array() != data);
+ assertEquals(bytesLength, result.capacity());
+ assertEquals((byte) 67, result.get());
+ result.position(bytesLength - 1);
+ assertEquals((byte) 89, result.get());
+
+ // Enable aliasing
+ inputStream = CodedInputStream.newInstance(data);
+ inputStream.enableAliasing(true);
+ result = inputStream.readByteBuffer();
+ assertEquals(0, result.capacity());
+ result = inputStream.readByteBuffer();
+ assertTrue(result.array() == data);
+ assertEquals(1, result.capacity());
+ assertEquals((byte) 23, result.get());
+ result = inputStream.readByteBuffer();
+ assertTrue(result.array() == data);
+ assertEquals(1, result.capacity());
+ assertEquals((byte) 45, result.get());
+ result = inputStream.readByteBuffer();
+ assertTrue(result.array() == data);
+ assertEquals(bytesLength, result.capacity());
+ assertEquals((byte) 67, result.get());
+ result.position(bytesLength - 1);
+ assertEquals((byte) 89, result.get());
+ }
+
+ public void testCompatibleTypes() throws Exception {
+ long data = 0x100000000L;
+ Int64Message message = Int64Message.newBuilder().setData(data).build();
+ ByteString serialized = message.toByteString();
+
+ // Test int64(long) is compatible with bool(boolean)
+ BoolMessage msg2 = BoolMessage.parseFrom(serialized);
+ assertTrue(msg2.getData());
+
+ // Test int64(long) is compatible with int32(int)
+ Int32Message msg3 = Int32Message.parseFrom(serialized);
+ assertEquals((int) data, msg3.getData());
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/CodedOutputStreamTest.java b/java/core/src/test/java/com/google/protobuf/CodedOutputStreamTest.java
new file mode 100644
index 00000000..6018ea55
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/CodedOutputStreamTest.java
@@ -0,0 +1,546 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// 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.UnittestProto.SparseEnumMessage;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.TestPackedTypes;
+import protobuf_unittest.UnittestProto.TestSparseEnum;
+
+import junit.framework.TestCase;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Unit test for {@link CodedOutputStream}.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public class CodedOutputStreamTest extends TestCase {
+ /**
+ * Helper to construct a byte array from a bunch of bytes. The inputs are
+ * actually ints so that I can use hex notation and not get stupid errors
+ * about precision.
+ */
+ private byte[] bytes(int... bytesAsInts) {
+ byte[] bytes = new byte[bytesAsInts.length];
+ for (int i = 0; i < bytesAsInts.length; i++) {
+ bytes[i] = (byte) bytesAsInts[i];
+ }
+ return bytes;
+ }
+
+ /** Arrays.asList() does not work with arrays of primitives. :( */
+ private List<Byte> toList(byte[] bytes) {
+ List<Byte> result = new ArrayList<Byte>();
+ for (byte b : bytes) {
+ result.add(b);
+ }
+ return result;
+ }
+
+ private void assertEqualBytes(byte[] a, byte[] b) {
+ assertEquals(toList(a), toList(b));
+ }
+
+ /**
+ * Writes the given value using writeRawVarint32() and writeRawVarint64() and
+ * checks that the result matches the given bytes.
+ */
+ private void assertWriteVarint(byte[] data, long value) throws Exception {
+ // Only test 32-bit write if the value fits into an int.
+ if (value == (int) value) {
+ ByteArrayOutputStream rawOutput = new ByteArrayOutputStream();
+ CodedOutputStream output = CodedOutputStream.newInstance(rawOutput);
+ output.writeRawVarint32((int) value);
+ output.flush();
+ assertEqualBytes(data, rawOutput.toByteArray());
+
+ // Also try computing size.
+ assertEquals(data.length,
+ CodedOutputStream.computeRawVarint32Size((int) value));
+ }
+
+ {
+ ByteArrayOutputStream rawOutput = new ByteArrayOutputStream();
+ CodedOutputStream output = CodedOutputStream.newInstance(rawOutput);
+ output.writeRawVarint64(value);
+ output.flush();
+ assertEqualBytes(data, rawOutput.toByteArray());
+
+ // Also try computing size.
+ assertEquals(data.length,
+ CodedOutputStream.computeRawVarint64Size(value));
+ }
+
+ // Try different block sizes.
+ for (int blockSize = 1; blockSize <= 16; blockSize *= 2) {
+ // Only test 32-bit write if the value fits into an int.
+ if (value == (int) value) {
+ ByteArrayOutputStream rawOutput = new ByteArrayOutputStream();
+ CodedOutputStream output =
+ CodedOutputStream.newInstance(rawOutput, blockSize);
+ output.writeRawVarint32((int) value);
+ output.flush();
+ assertEqualBytes(data, rawOutput.toByteArray());
+ }
+
+ {
+ ByteArrayOutputStream rawOutput = new ByteArrayOutputStream();
+ CodedOutputStream output =
+ CodedOutputStream.newInstance(rawOutput, blockSize);
+ output.writeRawVarint64(value);
+ output.flush();
+ assertEqualBytes(data, rawOutput.toByteArray());
+ }
+ }
+ }
+
+ private void assertVarintRoundTrip(long value) throws Exception {
+ {
+ ByteArrayOutputStream rawOutput = new ByteArrayOutputStream();
+ CodedOutputStream output = CodedOutputStream.newInstance(rawOutput);
+ output.writeRawVarint64(value);
+ output.flush();
+ byte[] bytes = rawOutput.toByteArray();
+ assertEquals(bytes.length, CodedOutputStream.computeRawVarint64Size(value));
+ CodedInputStream input = CodedInputStream.newInstance(new ByteArrayInputStream(bytes));
+ assertEquals(value, input.readRawVarint64());
+ }
+
+ if (value == (int) value) {
+ ByteArrayOutputStream rawOutput = new ByteArrayOutputStream();
+ CodedOutputStream output = CodedOutputStream.newInstance(rawOutput);
+ output.writeRawVarint32((int) value);
+ output.flush();
+ byte[] bytes = rawOutput.toByteArray();
+ assertEquals(bytes.length, CodedOutputStream.computeRawVarint32Size((int) value));
+ CodedInputStream input = CodedInputStream.newInstance(new ByteArrayInputStream(bytes));
+ assertEquals(value, input.readRawVarint32());
+ }
+ }
+
+ /** Checks that invariants are maintained for varint round trip input and output. */
+ public void testVarintRoundTrips() throws Exception {
+ assertVarintRoundTrip(0L);
+ for (int bits = 0; bits < 64; bits++) {
+ long value = 1L << bits;
+ assertVarintRoundTrip(value);
+ assertVarintRoundTrip(value + 1);
+ assertVarintRoundTrip(value - 1);
+ assertVarintRoundTrip(-value);
+ }
+ }
+
+ /** Tests writeRawVarint32() and writeRawVarint64(). */
+ public void testWriteVarint() throws Exception {
+ assertWriteVarint(bytes(0x00), 0);
+ assertWriteVarint(bytes(0x01), 1);
+ assertWriteVarint(bytes(0x7f), 127);
+ // 14882
+ assertWriteVarint(bytes(0xa2, 0x74), (0x22 << 0) | (0x74 << 7));
+ // 2961488830
+ assertWriteVarint(bytes(0xbe, 0xf7, 0x92, 0x84, 0x0b),
+ (0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) |
+ (0x0bL << 28));
+
+ // 64-bit
+ // 7256456126
+ assertWriteVarint(bytes(0xbe, 0xf7, 0x92, 0x84, 0x1b),
+ (0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) |
+ (0x1bL << 28));
+ // 41256202580718336
+ assertWriteVarint(
+ bytes(0x80, 0xe6, 0xeb, 0x9c, 0xc3, 0xc9, 0xa4, 0x49),
+ (0x00 << 0) | (0x66 << 7) | (0x6b << 14) | (0x1c << 21) |
+ (0x43L << 28) | (0x49L << 35) | (0x24L << 42) | (0x49L << 49));
+ // 11964378330978735131
+ assertWriteVarint(
+ bytes(0x9b, 0xa8, 0xf9, 0xc2, 0xbb, 0xd6, 0x80, 0x85, 0xa6, 0x01),
+ (0x1b << 0) | (0x28 << 7) | (0x79 << 14) | (0x42 << 21) |
+ (0x3bL << 28) | (0x56L << 35) | (0x00L << 42) |
+ (0x05L << 49) | (0x26L << 56) | (0x01L << 63));
+ }
+
+ /**
+ * Parses the given bytes using writeRawLittleEndian32() and checks
+ * that the result matches the given value.
+ */
+ private void assertWriteLittleEndian32(byte[] data, int value)
+ throws Exception {
+ ByteArrayOutputStream rawOutput = new ByteArrayOutputStream();
+ CodedOutputStream output = CodedOutputStream.newInstance(rawOutput);
+ output.writeRawLittleEndian32(value);
+ output.flush();
+ assertEqualBytes(data, rawOutput.toByteArray());
+
+ // Try different block sizes.
+ for (int blockSize = 1; blockSize <= 16; blockSize *= 2) {
+ rawOutput = new ByteArrayOutputStream();
+ output = CodedOutputStream.newInstance(rawOutput, blockSize);
+ output.writeRawLittleEndian32(value);
+ output.flush();
+ assertEqualBytes(data, rawOutput.toByteArray());
+ }
+ }
+
+ /**
+ * Parses the given bytes using writeRawLittleEndian64() and checks
+ * that the result matches the given value.
+ */
+ private void assertWriteLittleEndian64(byte[] data, long value)
+ throws Exception {
+ ByteArrayOutputStream rawOutput = new ByteArrayOutputStream();
+ CodedOutputStream output = CodedOutputStream.newInstance(rawOutput);
+ output.writeRawLittleEndian64(value);
+ output.flush();
+ assertEqualBytes(data, rawOutput.toByteArray());
+
+ // Try different block sizes.
+ for (int blockSize = 1; blockSize <= 16; blockSize *= 2) {
+ rawOutput = new ByteArrayOutputStream();
+ output = CodedOutputStream.newInstance(rawOutput, blockSize);
+ output.writeRawLittleEndian64(value);
+ output.flush();
+ assertEqualBytes(data, rawOutput.toByteArray());
+ }
+ }
+
+ /** Tests writeRawLittleEndian32() and writeRawLittleEndian64(). */
+ public void testWriteLittleEndian() throws Exception {
+ assertWriteLittleEndian32(bytes(0x78, 0x56, 0x34, 0x12), 0x12345678);
+ assertWriteLittleEndian32(bytes(0xf0, 0xde, 0xbc, 0x9a), 0x9abcdef0);
+
+ assertWriteLittleEndian64(
+ bytes(0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12),
+ 0x123456789abcdef0L);
+ assertWriteLittleEndian64(
+ bytes(0x78, 0x56, 0x34, 0x12, 0xf0, 0xde, 0xbc, 0x9a),
+ 0x9abcdef012345678L);
+ }
+
+ /** Test encodeZigZag32() and encodeZigZag64(). */
+ public void testEncodeZigZag() throws Exception {
+ assertEquals(0, CodedOutputStream.encodeZigZag32( 0));
+ assertEquals(1, CodedOutputStream.encodeZigZag32(-1));
+ assertEquals(2, CodedOutputStream.encodeZigZag32( 1));
+ assertEquals(3, CodedOutputStream.encodeZigZag32(-2));
+ assertEquals(0x7FFFFFFE, CodedOutputStream.encodeZigZag32(0x3FFFFFFF));
+ assertEquals(0x7FFFFFFF, CodedOutputStream.encodeZigZag32(0xC0000000));
+ assertEquals(0xFFFFFFFE, CodedOutputStream.encodeZigZag32(0x7FFFFFFF));
+ assertEquals(0xFFFFFFFF, CodedOutputStream.encodeZigZag32(0x80000000));
+
+ assertEquals(0, CodedOutputStream.encodeZigZag64( 0));
+ assertEquals(1, CodedOutputStream.encodeZigZag64(-1));
+ assertEquals(2, CodedOutputStream.encodeZigZag64( 1));
+ assertEquals(3, CodedOutputStream.encodeZigZag64(-2));
+ assertEquals(0x000000007FFFFFFEL,
+ CodedOutputStream.encodeZigZag64(0x000000003FFFFFFFL));
+ assertEquals(0x000000007FFFFFFFL,
+ CodedOutputStream.encodeZigZag64(0xFFFFFFFFC0000000L));
+ assertEquals(0x00000000FFFFFFFEL,
+ CodedOutputStream.encodeZigZag64(0x000000007FFFFFFFL));
+ assertEquals(0x00000000FFFFFFFFL,
+ CodedOutputStream.encodeZigZag64(0xFFFFFFFF80000000L));
+ assertEquals(0xFFFFFFFFFFFFFFFEL,
+ CodedOutputStream.encodeZigZag64(0x7FFFFFFFFFFFFFFFL));
+ assertEquals(0xFFFFFFFFFFFFFFFFL,
+ CodedOutputStream.encodeZigZag64(0x8000000000000000L));
+
+ // Some easier-to-verify round-trip tests. The inputs (other than 0, 1, -1)
+ // were chosen semi-randomly via keyboard bashing.
+ assertEquals(0,
+ CodedOutputStream.encodeZigZag32(CodedInputStream.decodeZigZag32(0)));
+ assertEquals(1,
+ CodedOutputStream.encodeZigZag32(CodedInputStream.decodeZigZag32(1)));
+ assertEquals(-1,
+ CodedOutputStream.encodeZigZag32(CodedInputStream.decodeZigZag32(-1)));
+ assertEquals(14927,
+ CodedOutputStream.encodeZigZag32(CodedInputStream.decodeZigZag32(14927)));
+ assertEquals(-3612,
+ CodedOutputStream.encodeZigZag32(CodedInputStream.decodeZigZag32(-3612)));
+
+ assertEquals(0,
+ CodedOutputStream.encodeZigZag64(CodedInputStream.decodeZigZag64(0)));
+ assertEquals(1,
+ CodedOutputStream.encodeZigZag64(CodedInputStream.decodeZigZag64(1)));
+ assertEquals(-1,
+ CodedOutputStream.encodeZigZag64(CodedInputStream.decodeZigZag64(-1)));
+ assertEquals(14927,
+ CodedOutputStream.encodeZigZag64(CodedInputStream.decodeZigZag64(14927)));
+ assertEquals(-3612,
+ CodedOutputStream.encodeZigZag64(CodedInputStream.decodeZigZag64(-3612)));
+
+ assertEquals(856912304801416L,
+ CodedOutputStream.encodeZigZag64(
+ CodedInputStream.decodeZigZag64(
+ 856912304801416L)));
+ assertEquals(-75123905439571256L,
+ CodedOutputStream.encodeZigZag64(
+ CodedInputStream.decodeZigZag64(
+ -75123905439571256L)));
+ }
+
+ /** Tests writing a whole message with every field type. */
+ public void testWriteWholeMessage() throws Exception {
+ TestAllTypes message = TestUtil.getAllSet();
+
+ byte[] rawBytes = message.toByteArray();
+ assertEqualBytes(TestUtil.getGoldenMessage().toByteArray(), rawBytes);
+
+ // Try different block sizes.
+ for (int blockSize = 1; blockSize < 256; blockSize *= 2) {
+ ByteArrayOutputStream rawOutput = new ByteArrayOutputStream();
+ CodedOutputStream output =
+ CodedOutputStream.newInstance(rawOutput, blockSize);
+ message.writeTo(output);
+ output.flush();
+ assertEqualBytes(rawBytes, rawOutput.toByteArray());
+ }
+ }
+
+ /** Tests writing a whole message with every packed field type. Ensures the
+ * wire format of packed fields is compatible with C++. */
+ public void testWriteWholePackedFieldsMessage() throws Exception {
+ TestPackedTypes message = TestUtil.getPackedSet();
+
+ byte[] rawBytes = message.toByteArray();
+ assertEqualBytes(TestUtil.getGoldenPackedFieldsMessage().toByteArray(),
+ rawBytes);
+ }
+
+ /** Test writing a message containing a negative enum value. This used to
+ * fail because the size was not properly computed as a sign-extended varint.
+ */
+ public void testWriteMessageWithNegativeEnumValue() throws Exception {
+ SparseEnumMessage message = SparseEnumMessage.newBuilder()
+ .setSparseEnum(TestSparseEnum.SPARSE_E) .build();
+ assertTrue(message.getSparseEnum().getNumber() < 0);
+ byte[] rawBytes = message.toByteArray();
+ SparseEnumMessage message2 = SparseEnumMessage.parseFrom(rawBytes);
+ assertEquals(TestSparseEnum.SPARSE_E, message2.getSparseEnum());
+ }
+
+ /** Test getTotalBytesWritten() */
+ public void testGetTotalBytesWritten() throws Exception {
+ final int BUFFER_SIZE = 4 * 1024;
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream(BUFFER_SIZE);
+ CodedOutputStream codedStream = CodedOutputStream.newInstance(outputStream);
+ byte[] value = "abcde".getBytes(Internal.UTF_8);
+ for (int i = 0; i < 1024; ++i) {
+ codedStream.writeRawBytes(value, 0, value.length);
+ }
+ String string =
+ "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz";
+ // Ensure we take the slower fast path.
+ assertTrue(CodedOutputStream.computeRawVarint32Size(string.length())
+ != CodedOutputStream.computeRawVarint32Size(string.length() * Utf8.MAX_BYTES_PER_CHAR));
+
+ codedStream.writeStringNoTag(string);
+ int stringSize = CodedOutputStream.computeStringSizeNoTag(string);
+
+ // Make sure we have written more bytes than the buffer could hold. This is
+ // to make the test complete.
+ assertTrue(codedStream.getTotalBytesWritten() > BUFFER_SIZE);
+
+ // Verify that the total bytes written is correct
+ assertEquals((value.length * 1024) + stringSize, codedStream.getTotalBytesWritten());
+ }
+
+ // TODO(dweis): Write a comprehensive test suite for CodedOutputStream that covers more than just
+ // this case.
+ public void testWriteStringNoTag_fastpath() throws Exception {
+ int bufferSize = 153;
+ String threeBytesPer = "\u0981";
+ String string = threeBytesPer;
+ for (int i = 0; i < 50; i++) {
+ string += threeBytesPer;
+ }
+ // These checks ensure we will tickle the slower fast path.
+ assertEquals(1, CodedOutputStream.computeRawVarint32Size(string.length()));
+ assertEquals(
+ 2, CodedOutputStream.computeRawVarint32Size(string.length() * Utf8.MAX_BYTES_PER_CHAR));
+ assertEquals(bufferSize, string.length() * Utf8.MAX_BYTES_PER_CHAR);
+
+ CodedOutputStream output =
+ CodedOutputStream.newInstance(ByteBuffer.allocate(bufferSize), bufferSize);
+ output.writeStringNoTag(string);
+ }
+
+ public void testWriteToByteBuffer() throws Exception {
+ final int bufferSize = 16 * 1024;
+ ByteBuffer buffer = ByteBuffer.allocate(bufferSize);
+ CodedOutputStream codedStream = CodedOutputStream.newInstance(buffer);
+ // Write raw bytes into the ByteBuffer.
+ final int length1 = 5000;
+ for (int i = 0; i < length1; i++) {
+ codedStream.writeRawByte((byte) 1);
+ }
+ final int length2 = 8 * 1024;
+ byte[] data = new byte[length2];
+ for (int i = 0; i < length2; i++) {
+ data[i] = (byte) 2;
+ }
+ codedStream.writeRawBytes(data);
+ final int length3 = bufferSize - length1 - length2;
+ for (int i = 0; i < length3; i++) {
+ codedStream.writeRawByte((byte) 3);
+ }
+ codedStream.flush();
+
+ // Check that data is correctly written to the ByteBuffer.
+ assertEquals(0, buffer.remaining());
+ buffer.flip();
+ for (int i = 0; i < length1; i++) {
+ assertEquals((byte) 1, buffer.get());
+ }
+ for (int i = 0; i < length2; i++) {
+ assertEquals((byte) 2, buffer.get());
+ }
+ for (int i = 0; i < length3; i++) {
+ assertEquals((byte) 3, buffer.get());
+ }
+ }
+
+ public void testWriteByteBuffer() throws Exception {
+ byte[] value = "abcde".getBytes(Internal.UTF_8);
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ CodedOutputStream codedStream = CodedOutputStream.newInstance(outputStream);
+ ByteBuffer byteBuffer = ByteBuffer.wrap(value, 0, 1);
+ // This will actually write 5 bytes into the CodedOutputStream as the
+ // ByteBuffer's capacity() is 5.
+ codedStream.writeRawBytes(byteBuffer);
+ // The above call shouldn't affect the ByteBuffer's state.
+ assertEquals(0, byteBuffer.position());
+ assertEquals(1, byteBuffer.limit());
+
+ // The correct way to write part of an array using ByteBuffer.
+ codedStream.writeRawBytes(ByteBuffer.wrap(value, 2, 1).slice());
+
+ codedStream.flush();
+ byte[] result = outputStream.toByteArray();
+ assertEquals(6, result.length);
+ for (int i = 0; i < 5; i++) {
+ assertEquals(value[i], result[i]);
+ }
+ assertEquals(value[2], result[5]);
+ }
+
+ public void testWriteByteArrayWithOffsets() throws Exception {
+ byte[] fullArray = bytes(0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88);
+ byte[] destination = new byte[4];
+ CodedOutputStream codedStream = CodedOutputStream.newInstance(destination);
+ codedStream.writeByteArrayNoTag(fullArray, 2, 2);
+ assertEqualBytes(bytes(0x02, 0x33, 0x44, 0x00), destination);
+ assertEquals(3, codedStream.getTotalBytesWritten());
+ }
+
+ public void testSerializeInvalidUtf8() throws Exception {
+ String[] invalidStrings = new String[] {
+ newString(Character.MIN_HIGH_SURROGATE),
+ "foobar" + newString(Character.MIN_HIGH_SURROGATE),
+ newString(Character.MIN_LOW_SURROGATE),
+ "foobar" + newString(Character.MIN_LOW_SURROGATE),
+ newString(Character.MIN_HIGH_SURROGATE, Character.MIN_HIGH_SURROGATE)
+ };
+
+ CodedOutputStream outputWithStream = CodedOutputStream.newInstance(new ByteArrayOutputStream());
+ CodedOutputStream outputWithArray = CodedOutputStream.newInstance(new byte[10000]);
+ for (String s : invalidStrings) {
+ // TODO(dweis): These should all fail; instead they are corrupting data.
+ CodedOutputStream.computeStringSizeNoTag(s);
+ outputWithStream.writeStringNoTag(s);
+ outputWithArray.writeStringNoTag(s);
+ }
+ }
+
+ private static String newString(char... chars) {
+ return new String(chars);
+ }
+
+ /** Regression test for https://github.com/google/protobuf/issues/292 */
+ public void testCorrectExceptionThrowWhenEncodingStringsWithoutEnoughSpace() throws Exception {
+ String testCase = "Foooooooo";
+ assertEquals(CodedOutputStream.computeRawVarint32Size(testCase.length()),
+ CodedOutputStream.computeRawVarint32Size(testCase.length() * 3));
+ assertEquals(11, CodedOutputStream.computeStringSize(1, testCase));
+ // Tag is one byte, varint describing string length is 1 byte, string length is 9 bytes.
+ // An array of size 1 will cause a failure when trying to write the varint.
+ for (int i = 0; i < 11; i++) {
+ CodedOutputStream output = CodedOutputStream.newInstance(new byte[i]);
+ try {
+ output.writeString(1, testCase);
+ fail("Should have thrown an out of space exception");
+ } catch (CodedOutputStream.OutOfSpaceException expected) {}
+ }
+ }
+
+ public void testDifferentStringLengths() throws Exception {
+ // Test string serialization roundtrip using strings of the following lengths,
+ // with ASCII and Unicode characters requiring different UTF-8 byte counts per
+ // char, hence causing the length delimiter varint to sometimes require more
+ // bytes for the Unicode strings than the ASCII string of the same length.
+ int[] lengths = new int[] {
+ 0,
+ 1,
+ (1 << 4) - 1, // 1 byte for ASCII and Unicode
+ (1 << 7) - 1, // 1 byte for ASCII, 2 bytes for Unicode
+ (1 << 11) - 1, // 2 bytes for ASCII and Unicode
+ (1 << 14) - 1, // 2 bytes for ASCII, 3 bytes for Unicode
+ (1 << 17) - 1, // 3 bytes for ASCII and Unicode
+ };
+ for (int i : lengths) {
+ testEncodingOfString('q', i); // 1 byte per char
+ testEncodingOfString('\u07FF', i); // 2 bytes per char
+ testEncodingOfString('\u0981', i); // 3 bytes per char
+ }
+ }
+
+ private void testEncodingOfString(char c, int length) throws Exception {
+ String fullString = fullString(c, length);
+ TestAllTypes testAllTypes = TestAllTypes.newBuilder()
+ .setOptionalString(fullString)
+ .build();
+ assertEquals(
+ fullString, TestAllTypes.parseFrom(testAllTypes.toByteArray()).getOptionalString());
+ }
+
+ private String fullString(char c, int length) {
+ char[] result = new char[length];
+ Arrays.fill(result, c);
+ return new String(result);
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/DeprecatedFieldTest.java b/java/core/src/test/java/com/google/protobuf/DeprecatedFieldTest.java
new file mode 100644
index 00000000..e7905f79
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/DeprecatedFieldTest.java
@@ -0,0 +1,80 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// 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.UnittestProto.TestDeprecatedFields;
+
+import junit.framework.TestCase;
+
+import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.Method;
+/**
+ * Test field deprecation
+ *
+ * @author birdo@google.com (Roberto Scaramuzzi)
+ */
+public class DeprecatedFieldTest extends TestCase {
+ private String[] deprecatedGetterNames = {
+ "hasDeprecatedInt32",
+ "getDeprecatedInt32"};
+
+ private String[] deprecatedBuilderGetterNames = {
+ "hasDeprecatedInt32",
+ "getDeprecatedInt32",
+ "clearDeprecatedInt32"};
+
+ private String[] deprecatedBuilderSetterNames = {
+ "setDeprecatedInt32"};
+
+ public void testDeprecatedField() throws Exception {
+ Class<?> deprecatedFields = TestDeprecatedFields.class;
+ Class<?> deprecatedFieldsBuilder = TestDeprecatedFields.Builder.class;
+ for (String name : deprecatedGetterNames) {
+ Method method = deprecatedFields.getMethod(name);
+ assertTrue("Method " + name + " should be deprecated",
+ isDeprecated(method));
+ }
+ for (String name : deprecatedBuilderGetterNames) {
+ Method method = deprecatedFieldsBuilder.getMethod(name);
+ assertTrue("Method " + name + " should be deprecated",
+ isDeprecated(method));
+ }
+ for (String name : deprecatedBuilderSetterNames) {
+ Method method = deprecatedFieldsBuilder.getMethod(name, int.class);
+ assertTrue("Method " + name + " should be deprecated",
+ isDeprecated(method));
+ }
+ }
+
+ private boolean isDeprecated(AnnotatedElement annotated) {
+ return annotated.isAnnotationPresent(Deprecated.class);
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/DescriptorsTest.java b/java/core/src/test/java/com/google/protobuf/DescriptorsTest.java
new file mode 100644
index 00000000..82ff34af
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/DescriptorsTest.java
@@ -0,0 +1,765 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// 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 com.google.protobuf.DescriptorProtos.DescriptorProto;
+import com.google.protobuf.DescriptorProtos.EnumDescriptorProto;
+import com.google.protobuf.DescriptorProtos.EnumValueDescriptorProto;
+import com.google.protobuf.DescriptorProtos.FieldDescriptorProto;
+import com.google.protobuf.DescriptorProtos.FileDescriptorProto;
+import com.google.protobuf.Descriptors.Descriptor;
+import com.google.protobuf.Descriptors.DescriptorValidationException;
+import com.google.protobuf.Descriptors.EnumDescriptor;
+import com.google.protobuf.Descriptors.EnumValueDescriptor;
+import com.google.protobuf.Descriptors.FieldDescriptor;
+import com.google.protobuf.Descriptors.FileDescriptor;
+import com.google.protobuf.Descriptors.MethodDescriptor;
+import com.google.protobuf.Descriptors.OneofDescriptor;
+import com.google.protobuf.Descriptors.ServiceDescriptor;
+import com.google.protobuf.test.UnittestImport;
+import com.google.protobuf.test.UnittestImport.ImportEnum;
+import com.google.protobuf.test.UnittestImport.ImportEnumForMap;
+import protobuf_unittest.TestCustomOptions;
+import protobuf_unittest.UnittestCustomOptions;
+import protobuf_unittest.UnittestProto;
+import protobuf_unittest.UnittestProto.ForeignEnum;
+import protobuf_unittest.UnittestProto.ForeignMessage;
+import protobuf_unittest.UnittestProto.TestAllExtensions;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.TestExtremeDefaultValues;
+import protobuf_unittest.UnittestProto.TestMultipleExtensionRanges;
+import protobuf_unittest.UnittestProto.TestRequired;
+import protobuf_unittest.UnittestProto.TestReservedFields;
+import protobuf_unittest.UnittestProto.TestService;
+
+import junit.framework.TestCase;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Unit test for {@link Descriptors}.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public class DescriptorsTest extends TestCase {
+
+ // Regression test for bug where referencing a FieldDescriptor.Type value
+ // before a FieldDescriptorProto.Type value would yield a
+ // ExceptionInInitializerError.
+ @SuppressWarnings("unused")
+ private static final Object STATIC_INIT_TEST = FieldDescriptor.Type.BOOL;
+
+ public void testFieldTypeEnumMapping() throws Exception {
+ assertEquals(FieldDescriptor.Type.values().length,
+ FieldDescriptorProto.Type.values().length);
+ for (FieldDescriptor.Type type : FieldDescriptor.Type.values()) {
+ FieldDescriptorProto.Type protoType = type.toProto();
+ assertEquals("TYPE_" + type.name(), protoType.name());
+ assertEquals(type, FieldDescriptor.Type.valueOf(protoType));
+ }
+ }
+
+ public void testFileDescriptor() throws Exception {
+ FileDescriptor file = UnittestProto.getDescriptor();
+
+ assertEquals("google/protobuf/unittest.proto", file.getName());
+ assertEquals("protobuf_unittest", file.getPackage());
+
+ assertEquals("UnittestProto", file.getOptions().getJavaOuterClassname());
+ assertEquals("google/protobuf/unittest.proto",
+ file.toProto().getName());
+
+ assertEquals(Arrays.asList(UnittestImport.getDescriptor()),
+ file.getDependencies());
+
+ Descriptor messageType = TestAllTypes.getDescriptor();
+ assertEquals(messageType, file.getMessageTypes().get(0));
+ assertEquals(messageType, file.findMessageTypeByName("TestAllTypes"));
+ assertNull(file.findMessageTypeByName("NoSuchType"));
+ assertNull(file.findMessageTypeByName("protobuf_unittest.TestAllTypes"));
+ for (int i = 0; i < file.getMessageTypes().size(); i++) {
+ assertEquals(i, file.getMessageTypes().get(i).getIndex());
+ }
+
+ EnumDescriptor enumType = ForeignEnum.getDescriptor();
+ assertEquals(enumType, file.getEnumTypes().get(0));
+ assertEquals(enumType, file.findEnumTypeByName("ForeignEnum"));
+ assertNull(file.findEnumTypeByName("NoSuchType"));
+ assertNull(file.findEnumTypeByName("protobuf_unittest.ForeignEnum"));
+ assertEquals(Arrays.asList(ImportEnum.getDescriptor(),
+ ImportEnumForMap.getDescriptor()),
+ UnittestImport.getDescriptor().getEnumTypes());
+ for (int i = 0; i < file.getEnumTypes().size(); i++) {
+ assertEquals(i, file.getEnumTypes().get(i).getIndex());
+ }
+
+ ServiceDescriptor service = TestService.getDescriptor();
+ assertEquals(service, file.getServices().get(0));
+ assertEquals(service, file.findServiceByName("TestService"));
+ assertNull(file.findServiceByName("NoSuchType"));
+ assertNull(file.findServiceByName("protobuf_unittest.TestService"));
+ assertEquals(Collections.emptyList(),
+ UnittestImport.getDescriptor().getServices());
+ for (int i = 0; i < file.getServices().size(); i++) {
+ assertEquals(i, file.getServices().get(i).getIndex());
+ }
+
+ FieldDescriptor extension =
+ UnittestProto.optionalInt32Extension.getDescriptor();
+ assertEquals(extension, file.getExtensions().get(0));
+ assertEquals(extension,
+ file.findExtensionByName("optional_int32_extension"));
+ assertNull(file.findExtensionByName("no_such_ext"));
+ assertNull(file.findExtensionByName(
+ "protobuf_unittest.optional_int32_extension"));
+ assertEquals(Collections.emptyList(),
+ UnittestImport.getDescriptor().getExtensions());
+ for (int i = 0; i < file.getExtensions().size(); i++) {
+ assertEquals(i, file.getExtensions().get(i).getIndex());
+ }
+ }
+
+ public void testDescriptor() throws Exception {
+ Descriptor messageType = TestAllTypes.getDescriptor();
+ Descriptor nestedType = TestAllTypes.NestedMessage.getDescriptor();
+
+ assertEquals("TestAllTypes", messageType.getName());
+ assertEquals("protobuf_unittest.TestAllTypes", messageType.getFullName());
+ assertEquals(UnittestProto.getDescriptor(), messageType.getFile());
+ assertNull(messageType.getContainingType());
+ assertEquals(DescriptorProtos.MessageOptions.getDefaultInstance(),
+ messageType.getOptions());
+ assertEquals("TestAllTypes", messageType.toProto().getName());
+
+ assertEquals("NestedMessage", nestedType.getName());
+ assertEquals("protobuf_unittest.TestAllTypes.NestedMessage",
+ nestedType.getFullName());
+ assertEquals(UnittestProto.getDescriptor(), nestedType.getFile());
+ assertEquals(messageType, nestedType.getContainingType());
+
+ FieldDescriptor field = messageType.getFields().get(0);
+ assertEquals("optional_int32", field.getName());
+ assertEquals(field, messageType.findFieldByName("optional_int32"));
+ assertNull(messageType.findFieldByName("no_such_field"));
+ assertEquals(field, messageType.findFieldByNumber(1));
+ assertNull(messageType.findFieldByNumber(571283));
+ for (int i = 0; i < messageType.getFields().size(); i++) {
+ assertEquals(i, messageType.getFields().get(i).getIndex());
+ }
+
+ assertEquals(nestedType, messageType.getNestedTypes().get(0));
+ assertEquals(nestedType, messageType.findNestedTypeByName("NestedMessage"));
+ assertNull(messageType.findNestedTypeByName("NoSuchType"));
+ for (int i = 0; i < messageType.getNestedTypes().size(); i++) {
+ assertEquals(i, messageType.getNestedTypes().get(i).getIndex());
+ }
+
+ EnumDescriptor enumType = TestAllTypes.NestedEnum.getDescriptor();
+ assertEquals(enumType, messageType.getEnumTypes().get(0));
+ assertEquals(enumType, messageType.findEnumTypeByName("NestedEnum"));
+ assertNull(messageType.findEnumTypeByName("NoSuchType"));
+ for (int i = 0; i < messageType.getEnumTypes().size(); i++) {
+ assertEquals(i, messageType.getEnumTypes().get(i).getIndex());
+ }
+ }
+
+ public void testFieldDescriptor() throws Exception {
+ Descriptor messageType = TestAllTypes.getDescriptor();
+ FieldDescriptor primitiveField =
+ messageType.findFieldByName("optional_int32");
+ FieldDescriptor enumField =
+ messageType.findFieldByName("optional_nested_enum");
+ FieldDescriptor messageField =
+ messageType.findFieldByName("optional_foreign_message");
+ FieldDescriptor cordField =
+ messageType.findFieldByName("optional_cord");
+ FieldDescriptor extension =
+ UnittestProto.optionalInt32Extension.getDescriptor();
+ FieldDescriptor nestedExtension = TestRequired.single.getDescriptor();
+
+ assertEquals("optional_int32", primitiveField.getName());
+ assertEquals("protobuf_unittest.TestAllTypes.optional_int32",
+ primitiveField.getFullName());
+ assertEquals(1, primitiveField.getNumber());
+ assertEquals(messageType, primitiveField.getContainingType());
+ assertEquals(UnittestProto.getDescriptor(), primitiveField.getFile());
+ assertEquals(FieldDescriptor.Type.INT32, primitiveField.getType());
+ assertEquals(FieldDescriptor.JavaType.INT, primitiveField.getJavaType());
+ assertEquals(DescriptorProtos.FieldOptions.getDefaultInstance(),
+ primitiveField.getOptions());
+ assertFalse(primitiveField.isExtension());
+ assertEquals("optional_int32", primitiveField.toProto().getName());
+
+ assertEquals("optional_nested_enum", enumField.getName());
+ assertEquals(FieldDescriptor.Type.ENUM, enumField.getType());
+ assertEquals(FieldDescriptor.JavaType.ENUM, enumField.getJavaType());
+ assertEquals(TestAllTypes.NestedEnum.getDescriptor(),
+ enumField.getEnumType());
+
+ assertEquals("optional_foreign_message", messageField.getName());
+ assertEquals(FieldDescriptor.Type.MESSAGE, messageField.getType());
+ assertEquals(FieldDescriptor.JavaType.MESSAGE, messageField.getJavaType());
+ assertEquals(ForeignMessage.getDescriptor(), messageField.getMessageType());
+
+ assertEquals("optional_cord", cordField.getName());
+ assertEquals(FieldDescriptor.Type.STRING, cordField.getType());
+ assertEquals(FieldDescriptor.JavaType.STRING, cordField.getJavaType());
+ assertEquals(DescriptorProtos.FieldOptions.CType.CORD,
+ cordField.getOptions().getCtype());
+
+ assertEquals("optional_int32_extension", extension.getName());
+ assertEquals("protobuf_unittest.optional_int32_extension",
+ extension.getFullName());
+ assertEquals(1, extension.getNumber());
+ assertEquals(TestAllExtensions.getDescriptor(),
+ extension.getContainingType());
+ assertEquals(UnittestProto.getDescriptor(), extension.getFile());
+ assertEquals(FieldDescriptor.Type.INT32, extension.getType());
+ assertEquals(FieldDescriptor.JavaType.INT, extension.getJavaType());
+ assertEquals(DescriptorProtos.FieldOptions.getDefaultInstance(),
+ extension.getOptions());
+ assertTrue(extension.isExtension());
+ assertEquals(null, extension.getExtensionScope());
+ assertEquals("optional_int32_extension", extension.toProto().getName());
+
+ assertEquals("single", nestedExtension.getName());
+ assertEquals("protobuf_unittest.TestRequired.single",
+ nestedExtension.getFullName());
+ assertEquals(TestRequired.getDescriptor(),
+ nestedExtension.getExtensionScope());
+ }
+
+ public void testFieldDescriptorLabel() throws Exception {
+ FieldDescriptor requiredField =
+ TestRequired.getDescriptor().findFieldByName("a");
+ FieldDescriptor optionalField =
+ TestAllTypes.getDescriptor().findFieldByName("optional_int32");
+ FieldDescriptor repeatedField =
+ TestAllTypes.getDescriptor().findFieldByName("repeated_int32");
+
+ assertTrue(requiredField.isRequired());
+ assertFalse(requiredField.isRepeated());
+ assertFalse(optionalField.isRequired());
+ assertFalse(optionalField.isRepeated());
+ assertFalse(repeatedField.isRequired());
+ assertTrue(repeatedField.isRepeated());
+ }
+
+ public void testFieldDescriptorJsonName() throws Exception {
+ FieldDescriptor requiredField = TestRequired.getDescriptor().findFieldByName("a");
+ FieldDescriptor optionalField = TestAllTypes.getDescriptor().findFieldByName("optional_int32");
+ FieldDescriptor repeatedField = TestAllTypes.getDescriptor().findFieldByName("repeated_int32");
+ assertEquals("a", requiredField.getJsonName());
+ assertEquals("optionalInt32", optionalField.getJsonName());
+ assertEquals("repeatedInt32", repeatedField.getJsonName());
+ }
+
+ public void testFieldDescriptorDefault() throws Exception {
+ Descriptor d = TestAllTypes.getDescriptor();
+ assertFalse(d.findFieldByName("optional_int32").hasDefaultValue());
+ assertEquals(0, d.findFieldByName("optional_int32").getDefaultValue());
+ assertTrue(d.findFieldByName("default_int32").hasDefaultValue());
+ assertEquals(41, d.findFieldByName("default_int32").getDefaultValue());
+
+ d = TestExtremeDefaultValues.getDescriptor();
+ assertEquals(
+ ByteString.copyFrom(
+ "\0\001\007\b\f\n\r\t\013\\\'\"\u00fe".getBytes(Internal.ISO_8859_1)),
+ d.findFieldByName("escaped_bytes").getDefaultValue());
+ assertEquals(-1, d.findFieldByName("large_uint32").getDefaultValue());
+ assertEquals(-1L, d.findFieldByName("large_uint64").getDefaultValue());
+ }
+
+ public void testEnumDescriptor() throws Exception {
+ EnumDescriptor enumType = ForeignEnum.getDescriptor();
+ EnumDescriptor nestedType = TestAllTypes.NestedEnum.getDescriptor();
+
+ assertEquals("ForeignEnum", enumType.getName());
+ assertEquals("protobuf_unittest.ForeignEnum", enumType.getFullName());
+ assertEquals(UnittestProto.getDescriptor(), enumType.getFile());
+ assertNull(enumType.getContainingType());
+ assertEquals(DescriptorProtos.EnumOptions.getDefaultInstance(),
+ enumType.getOptions());
+
+ assertEquals("NestedEnum", nestedType.getName());
+ assertEquals("protobuf_unittest.TestAllTypes.NestedEnum",
+ nestedType.getFullName());
+ assertEquals(UnittestProto.getDescriptor(), nestedType.getFile());
+ assertEquals(TestAllTypes.getDescriptor(), nestedType.getContainingType());
+
+ EnumValueDescriptor value = ForeignEnum.FOREIGN_FOO.getValueDescriptor();
+ assertEquals(value, enumType.getValues().get(0));
+ assertEquals("FOREIGN_FOO", value.getName());
+ assertEquals("FOREIGN_FOO", value.toString());
+ assertEquals(4, value.getNumber());
+ assertEquals(value, enumType.findValueByName("FOREIGN_FOO"));
+ assertEquals(value, enumType.findValueByNumber(4));
+ assertNull(enumType.findValueByName("NO_SUCH_VALUE"));
+ for (int i = 0; i < enumType.getValues().size(); i++) {
+ assertEquals(i, enumType.getValues().get(i).getIndex());
+ }
+ }
+
+ public void testServiceDescriptor() throws Exception {
+ ServiceDescriptor service = TestService.getDescriptor();
+
+ assertEquals("TestService", service.getName());
+ assertEquals("protobuf_unittest.TestService", service.getFullName());
+ assertEquals(UnittestProto.getDescriptor(), service.getFile());
+
+
+ MethodDescriptor fooMethod = service.getMethods().get(0);
+ assertEquals("Foo", fooMethod.getName());
+ assertEquals(UnittestProto.FooRequest.getDescriptor(),
+ fooMethod.getInputType());
+ assertEquals(UnittestProto.FooResponse.getDescriptor(),
+ fooMethod.getOutputType());
+ assertEquals(fooMethod, service.findMethodByName("Foo"));
+
+ MethodDescriptor barMethod = service.getMethods().get(1);
+ assertEquals("Bar", barMethod.getName());
+ assertEquals(UnittestProto.BarRequest.getDescriptor(),
+ barMethod.getInputType());
+ assertEquals(UnittestProto.BarResponse.getDescriptor(),
+ barMethod.getOutputType());
+ assertEquals(barMethod, service.findMethodByName("Bar"));
+
+ assertNull(service.findMethodByName("NoSuchMethod"));
+
+ for (int i = 0; i < service.getMethods().size(); i++) {
+ assertEquals(i, service.getMethods().get(i).getIndex());
+ }
+ }
+
+
+ public void testCustomOptions() throws Exception {
+ // Get the descriptor indirectly from a dependent proto class. This is to
+ // ensure that when a proto class is loaded, custom options defined in its
+ // dependencies are also properly initialized.
+ Descriptor descriptor =
+ TestCustomOptions.TestMessageWithCustomOptionsContainer.getDescriptor()
+ .findFieldByName("field").getMessageType();
+
+ assertTrue(
+ descriptor.getOptions().hasExtension(UnittestCustomOptions.messageOpt1));
+ assertEquals(Integer.valueOf(-56),
+ descriptor.getOptions().getExtension(UnittestCustomOptions.messageOpt1));
+
+ FieldDescriptor field = descriptor.findFieldByName("field1");
+ assertNotNull(field);
+
+ assertTrue(
+ field.getOptions().hasExtension(UnittestCustomOptions.fieldOpt1));
+ assertEquals(Long.valueOf(8765432109L),
+ field.getOptions().getExtension(UnittestCustomOptions.fieldOpt1));
+
+ EnumDescriptor enumType =
+ UnittestCustomOptions.TestMessageWithCustomOptions.AnEnum.getDescriptor();
+
+ assertTrue(
+ enumType.getOptions().hasExtension(UnittestCustomOptions.enumOpt1));
+ assertEquals(Integer.valueOf(-789),
+ enumType.getOptions().getExtension(UnittestCustomOptions.enumOpt1));
+
+ ServiceDescriptor service =
+ UnittestCustomOptions.TestServiceWithCustomOptions.getDescriptor();
+
+ assertTrue(
+ service.getOptions().hasExtension(UnittestCustomOptions.serviceOpt1));
+ assertEquals(Long.valueOf(-9876543210L),
+ service.getOptions().getExtension(UnittestCustomOptions.serviceOpt1));
+
+ MethodDescriptor method = service.findMethodByName("Foo");
+ assertNotNull(method);
+
+ assertTrue(
+ method.getOptions().hasExtension(UnittestCustomOptions.methodOpt1));
+ assertEquals(UnittestCustomOptions.MethodOpt1.METHODOPT1_VAL2,
+ method.getOptions().getExtension(UnittestCustomOptions.methodOpt1));
+ }
+
+ /**
+ * Test that the FieldDescriptor.Type enum is the same as the
+ * WireFormat.FieldType enum.
+ */
+ public void testFieldTypeTablesMatch() throws Exception {
+ FieldDescriptor.Type[] values1 = FieldDescriptor.Type.values();
+ WireFormat.FieldType[] values2 = WireFormat.FieldType.values();
+
+ assertEquals(values1.length, values2.length);
+
+ for (int i = 0; i < values1.length; i++) {
+ assertEquals(values1[i].toString(), values2[i].toString());
+ }
+ }
+
+ /**
+ * Test that the FieldDescriptor.JavaType enum is the same as the
+ * WireFormat.JavaType enum.
+ */
+ public void testJavaTypeTablesMatch() throws Exception {
+ FieldDescriptor.JavaType[] values1 = FieldDescriptor.JavaType.values();
+ WireFormat.JavaType[] values2 = WireFormat.JavaType.values();
+
+ assertEquals(values1.length, values2.length);
+
+ for (int i = 0; i < values1.length; i++) {
+ assertEquals(values1[i].toString(), values2[i].toString());
+ }
+ }
+
+ public void testEnormousDescriptor() throws Exception {
+ // The descriptor for this file is larger than 64k, yet it did not cause
+ // a compiler error due to an over-long string literal.
+ assertTrue(
+ UnittestEnormousDescriptor.getDescriptor()
+ .toProto().getSerializedSize() > 65536);
+ }
+
+ /**
+ * Tests that the DescriptorValidationException works as intended.
+ */
+ public void testDescriptorValidatorException() throws Exception {
+ FileDescriptorProto fileDescriptorProto = FileDescriptorProto.newBuilder()
+ .setName("foo.proto")
+ .addMessageType(DescriptorProto.newBuilder()
+ .setName("Foo")
+ .addField(FieldDescriptorProto.newBuilder()
+ .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
+ .setType(FieldDescriptorProto.Type.TYPE_INT32)
+ .setName("foo")
+ .setNumber(1)
+ .setDefaultValue("invalid")
+ .build())
+ .build())
+ .build();
+ try {
+ Descriptors.FileDescriptor.buildFrom(fileDescriptorProto,
+ new FileDescriptor[0]);
+ fail("DescriptorValidationException expected");
+ } catch (DescriptorValidationException e) {
+ // Expected; check that the error message contains some useful hints
+ assertTrue(e.getMessage().indexOf("foo") != -1);
+ assertTrue(e.getMessage().indexOf("Foo") != -1);
+ assertTrue(e.getMessage().indexOf("invalid") != -1);
+ assertTrue(e.getCause() instanceof NumberFormatException);
+ assertTrue(e.getCause().getMessage().indexOf("invalid") != -1);
+ }
+ }
+
+ /**
+ * Tests the translate/crosslink for an example where a message field's name
+ * and type name are the same.
+ */
+ public void testDescriptorComplexCrosslink() throws Exception {
+ FileDescriptorProto fileDescriptorProto = FileDescriptorProto.newBuilder()
+ .setName("foo.proto")
+ .addMessageType(DescriptorProto.newBuilder()
+ .setName("Foo")
+ .addField(FieldDescriptorProto.newBuilder()
+ .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
+ .setType(FieldDescriptorProto.Type.TYPE_INT32)
+ .setName("foo")
+ .setNumber(1)
+ .build())
+ .build())
+ .addMessageType(DescriptorProto.newBuilder()
+ .setName("Bar")
+ .addField(FieldDescriptorProto.newBuilder()
+ .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
+ .setTypeName("Foo")
+ .setName("Foo")
+ .setNumber(1)
+ .build())
+ .build())
+ .build();
+ // translate and crosslink
+ FileDescriptor file =
+ Descriptors.FileDescriptor.buildFrom(fileDescriptorProto,
+ new FileDescriptor[0]);
+ // verify resulting descriptors
+ assertNotNull(file);
+ List<Descriptor> msglist = file.getMessageTypes();
+ assertNotNull(msglist);
+ assertTrue(msglist.size() == 2);
+ boolean barFound = false;
+ for (Descriptor desc : msglist) {
+ if (desc.getName().equals("Bar")) {
+ barFound = true;
+ assertNotNull(desc.getFields());
+ List<FieldDescriptor> fieldlist = desc.getFields();
+ assertNotNull(fieldlist);
+ assertTrue(fieldlist.size() == 1);
+ assertTrue(fieldlist.get(0).getType() == FieldDescriptor.Type.MESSAGE);
+ assertTrue(fieldlist.get(0).getMessageType().getName().equals("Foo"));
+ }
+ }
+ assertTrue(barFound);
+ }
+
+ public void testDependencyOrder() throws Exception {
+ FileDescriptorProto fooProto = FileDescriptorProto.newBuilder()
+ .setName("foo.proto").build();
+ FileDescriptorProto barProto = FileDescriptorProto.newBuilder()
+ .setName("bar.proto")
+ .addDependency("foo.proto")
+ .build();
+ FileDescriptorProto bazProto = FileDescriptorProto.newBuilder()
+ .setName("baz.proto")
+ .addDependency("foo.proto")
+ .addDependency("bar.proto")
+ .addPublicDependency(0)
+ .addPublicDependency(1)
+ .build();
+ FileDescriptor fooFile = Descriptors.FileDescriptor.buildFrom(fooProto,
+ new FileDescriptor[0]);
+ FileDescriptor barFile = Descriptors.FileDescriptor.buildFrom(barProto,
+ new FileDescriptor[] {fooFile});
+
+ // Items in the FileDescriptor array can be in any order.
+ Descriptors.FileDescriptor.buildFrom(bazProto,
+ new FileDescriptor[] {fooFile, barFile});
+ Descriptors.FileDescriptor.buildFrom(bazProto,
+ new FileDescriptor[] {barFile, fooFile});
+ }
+
+ public void testInvalidPublicDependency() throws Exception {
+ FileDescriptorProto fooProto = FileDescriptorProto.newBuilder()
+ .setName("foo.proto").build();
+ FileDescriptorProto barProto = FileDescriptorProto.newBuilder()
+ .setName("boo.proto")
+ .addDependency("foo.proto")
+ .addPublicDependency(1) // Error, should be 0.
+ .build();
+ FileDescriptor fooFile = Descriptors.FileDescriptor.buildFrom(fooProto,
+ new FileDescriptor[0]);
+ try {
+ Descriptors.FileDescriptor.buildFrom(barProto,
+ new FileDescriptor[] {fooFile});
+ fail("DescriptorValidationException expected");
+ } catch (DescriptorValidationException e) {
+ assertTrue(
+ e.getMessage().indexOf("Invalid public dependency index.") != -1);
+ }
+ }
+
+ public void testHiddenDependency() throws Exception {
+ FileDescriptorProto barProto = FileDescriptorProto.newBuilder()
+ .setName("bar.proto")
+ .addMessageType(DescriptorProto.newBuilder().setName("Bar"))
+ .build();
+ FileDescriptorProto forwardProto = FileDescriptorProto.newBuilder()
+ .setName("forward.proto")
+ .addDependency("bar.proto")
+ .build();
+ FileDescriptorProto fooProto = FileDescriptorProto.newBuilder()
+ .setName("foo.proto")
+ .addDependency("forward.proto")
+ .addMessageType(DescriptorProto.newBuilder()
+ .setName("Foo")
+ .addField(FieldDescriptorProto.newBuilder()
+ .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
+ .setTypeName("Bar")
+ .setName("bar")
+ .setNumber(1)))
+ .build();
+ FileDescriptor barFile = Descriptors.FileDescriptor.buildFrom(
+ barProto, new FileDescriptor[0]);
+ FileDescriptor forwardFile = Descriptors.FileDescriptor.buildFrom(
+ forwardProto, new FileDescriptor[] {barFile});
+
+ try {
+ Descriptors.FileDescriptor.buildFrom(
+ fooProto, new FileDescriptor[] {forwardFile});
+ fail("DescriptorValidationException expected");
+ } catch (DescriptorValidationException e) {
+ assertTrue(e.getMessage().indexOf("Bar") != -1);
+ assertTrue(e.getMessage().indexOf("is not defined") != -1);
+ }
+ }
+
+ public void testPublicDependency() throws Exception {
+ FileDescriptorProto barProto = FileDescriptorProto.newBuilder()
+ .setName("bar.proto")
+ .addMessageType(DescriptorProto.newBuilder().setName("Bar"))
+ .build();
+ FileDescriptorProto forwardProto = FileDescriptorProto.newBuilder()
+ .setName("forward.proto")
+ .addDependency("bar.proto")
+ .addPublicDependency(0)
+ .build();
+ FileDescriptorProto fooProto = FileDescriptorProto.newBuilder()
+ .setName("foo.proto")
+ .addDependency("forward.proto")
+ .addMessageType(DescriptorProto.newBuilder()
+ .setName("Foo")
+ .addField(FieldDescriptorProto.newBuilder()
+ .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
+ .setTypeName("Bar")
+ .setName("bar")
+ .setNumber(1)))
+ .build();
+ FileDescriptor barFile = Descriptors.FileDescriptor.buildFrom(
+ barProto, new FileDescriptor[0]);
+ FileDescriptor forwardFile = Descriptors.FileDescriptor.buildFrom(
+ forwardProto, new FileDescriptor[]{barFile});
+ Descriptors.FileDescriptor.buildFrom(
+ fooProto, new FileDescriptor[] {forwardFile});
+ }
+
+ /**
+ * Tests the translate/crosslink for an example with a more complex namespace
+ * referencing.
+ */
+ public void testComplexNamespacePublicDependency() throws Exception {
+ FileDescriptorProto fooProto = FileDescriptorProto.newBuilder()
+ .setName("bar.proto")
+ .setPackage("a.b.c.d.bar.shared")
+ .addEnumType(EnumDescriptorProto.newBuilder()
+ .setName("MyEnum")
+ .addValue(EnumValueDescriptorProto.newBuilder()
+ .setName("BLAH")
+ .setNumber(1)))
+ .build();
+ FileDescriptorProto barProto = FileDescriptorProto.newBuilder()
+ .setName("foo.proto")
+ .addDependency("bar.proto")
+ .setPackage("a.b.c.d.foo.shared")
+ .addMessageType(DescriptorProto.newBuilder()
+ .setName("MyMessage")
+ .addField(FieldDescriptorProto.newBuilder()
+ .setLabel(FieldDescriptorProto.Label.LABEL_REPEATED)
+ .setTypeName("bar.shared.MyEnum")
+ .setName("MyField")
+ .setNumber(1)))
+ .build();
+ // translate and crosslink
+ FileDescriptor fooFile = Descriptors.FileDescriptor.buildFrom(
+ fooProto, new FileDescriptor[0]);
+ FileDescriptor barFile = Descriptors.FileDescriptor.buildFrom(
+ barProto, new FileDescriptor[]{fooFile});
+ // verify resulting descriptors
+ assertNotNull(barFile);
+ List<Descriptor> msglist = barFile.getMessageTypes();
+ assertNotNull(msglist);
+ assertTrue(msglist.size() == 1);
+ Descriptor desc = msglist.get(0);
+ if (desc.getName().equals("MyMessage")) {
+ assertNotNull(desc.getFields());
+ List<FieldDescriptor> fieldlist = desc.getFields();
+ assertNotNull(fieldlist);
+ assertTrue(fieldlist.size() == 1);
+ FieldDescriptor field = fieldlist.get(0);
+ assertTrue(field.getType() == FieldDescriptor.Type.ENUM);
+ assertTrue(field.getEnumType().getName().equals("MyEnum"));
+ assertTrue(field.getEnumType().getFile().getName().equals("bar.proto"));
+ assertTrue(field.getEnumType().getFile().getPackage().equals(
+ "a.b.c.d.bar.shared"));
+ }
+ }
+
+ public void testOneofDescriptor() throws Exception {
+ Descriptor messageType = TestAllTypes.getDescriptor();
+ FieldDescriptor field =
+ messageType.findFieldByName("oneof_nested_message");
+ OneofDescriptor oneofDescriptor = field.getContainingOneof();
+ assertNotNull(oneofDescriptor);
+ assertSame(oneofDescriptor, messageType.getOneofs().get(0));
+ assertEquals("oneof_field", oneofDescriptor.getName());
+
+ assertEquals(4, oneofDescriptor.getFieldCount());
+ assertSame(oneofDescriptor.getField(1), field);
+
+ assertEquals(4, oneofDescriptor.getFields().size());
+ assertEquals(oneofDescriptor.getFields().get(1), field);
+ }
+
+ public void testMessageDescriptorExtensions() throws Exception {
+ assertFalse(TestAllTypes.getDescriptor().isExtendable());
+ assertTrue(TestAllExtensions.getDescriptor().isExtendable());
+ assertTrue(TestMultipleExtensionRanges.getDescriptor().isExtendable());
+
+ assertFalse(TestAllTypes.getDescriptor().isExtensionNumber(3));
+ assertTrue(TestAllExtensions.getDescriptor().isExtensionNumber(3));
+ assertTrue(TestMultipleExtensionRanges.getDescriptor().isExtensionNumber(42));
+ assertFalse(TestMultipleExtensionRanges.getDescriptor().isExtensionNumber(43));
+ assertFalse(TestMultipleExtensionRanges.getDescriptor().isExtensionNumber(4142));
+ assertTrue(TestMultipleExtensionRanges.getDescriptor().isExtensionNumber(4143));
+ }
+
+ public void testReservedFields() {
+ Descriptor d = TestReservedFields.getDescriptor();
+ assertTrue(d.isReservedNumber(2));
+ assertFalse(d.isReservedNumber(8));
+ assertTrue(d.isReservedNumber(9));
+ assertTrue(d.isReservedNumber(10));
+ assertTrue(d.isReservedNumber(11));
+ assertFalse(d.isReservedNumber(12));
+ assertFalse(d.isReservedName("foo"));
+ assertTrue(d.isReservedName("bar"));
+ assertTrue(d.isReservedName("baz"));
+ }
+
+ public void testToString() {
+ assertEquals("protobuf_unittest.TestAllTypes.optional_uint64",
+ UnittestProto.TestAllTypes.getDescriptor().findFieldByNumber(
+ UnittestProto.TestAllTypes.OPTIONAL_UINT64_FIELD_NUMBER).toString());
+ }
+
+ public void testPackedEnumField() throws Exception {
+ FileDescriptorProto fileDescriptorProto = FileDescriptorProto.newBuilder()
+ .setName("foo.proto")
+ .addEnumType(EnumDescriptorProto.newBuilder()
+ .setName("Enum")
+ .addValue(EnumValueDescriptorProto.newBuilder()
+ .setName("FOO")
+ .setNumber(1)
+ .build())
+ .build())
+ .addMessageType(DescriptorProto.newBuilder()
+ .setName("Message")
+ .addField(FieldDescriptorProto.newBuilder()
+ .setName("foo")
+ .setTypeName("Enum")
+ .setNumber(1)
+ .setLabel(FieldDescriptorProto.Label.LABEL_REPEATED)
+ .setOptions(DescriptorProtos.FieldOptions.newBuilder()
+ .setPacked(true)
+ .build())
+ .build())
+ .build())
+ .build();
+ Descriptors.FileDescriptor.buildFrom(
+ fileDescriptorProto, new FileDescriptor[0]);
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/DoubleArrayListTest.java b/java/core/src/test/java/com/google/protobuf/DoubleArrayListTest.java
new file mode 100644
index 00000000..d3deaa07
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/DoubleArrayListTest.java
@@ -0,0 +1,473 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// 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 static java.util.Arrays.asList;
+
+import junit.framework.TestCase;
+
+import java.util.Collections;
+import java.util.ConcurrentModificationException;
+import java.util.Iterator;
+
+/**
+ * Tests for {@link DoubleArrayList}.
+ *
+ * @author dweis@google.com (Daniel Weis)
+ */
+public class DoubleArrayListTest extends TestCase {
+
+ private static final DoubleArrayList UNARY_LIST = newImmutableDoubleArrayList(1);
+ private static final DoubleArrayList TERTIARY_LIST =
+ newImmutableDoubleArrayList(1, 2, 3);
+
+ private DoubleArrayList list;
+
+ @Override
+ protected void setUp() throws Exception {
+ list = new DoubleArrayList();
+ }
+
+ public void testEmptyListReturnsSameInstance() {
+ assertSame(DoubleArrayList.emptyList(), DoubleArrayList.emptyList());
+ }
+
+ public void testEmptyListIsImmutable() {
+ assertImmutable(DoubleArrayList.emptyList());
+ }
+
+ public void testMakeImmutable() {
+ list.addDouble(2);
+ list.addDouble(4);
+ list.addDouble(6);
+ list.addDouble(8);
+ list.makeImmutable();
+ assertImmutable(list);
+ }
+
+ public void testCopyConstructor() {
+ DoubleArrayList copy = new DoubleArrayList(TERTIARY_LIST);
+ assertEquals(TERTIARY_LIST, copy);
+
+ copy = new DoubleArrayList(DoubleArrayList.emptyList());
+ assertEquals(DoubleArrayList.emptyList(), copy);
+
+ copy = new DoubleArrayList(asList(1D, 2D, 3D));
+ assertEquals(asList(1D, 2D, 3D), copy);
+
+ copy = new DoubleArrayList(Collections.<Double>emptyList());
+ assertEquals(DoubleArrayList.emptyList(), copy);
+ }
+
+ public void testModificationWithIteration() {
+ list.addAll(asList(1D, 2D, 3D, 4D));
+ Iterator<Double> iterator = list.iterator();
+ assertEquals(4, list.size());
+ assertEquals(1D, (double) list.get(0));
+ assertEquals(1D, (double) iterator.next());
+ list.set(0, 1D);
+ assertEquals(2D, (double) iterator.next());
+
+ list.remove(0);
+ try {
+ iterator.next();
+ fail();
+ } catch (ConcurrentModificationException e) {
+ // expected
+ }
+
+ iterator = list.iterator();
+ list.add(0, 0D);
+ try {
+ iterator.next();
+ fail();
+ } catch (ConcurrentModificationException e) {
+ // expected
+ }
+ }
+
+ public void testGet() {
+ assertEquals(1D, (double) TERTIARY_LIST.get(0));
+ assertEquals(2D, (double) TERTIARY_LIST.get(1));
+ assertEquals(3D, (double) TERTIARY_LIST.get(2));
+
+ try {
+ TERTIARY_LIST.get(-1);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ TERTIARY_LIST.get(3);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testGetInt() {
+ assertEquals(1D, TERTIARY_LIST.getDouble(0));
+ assertEquals(2D, TERTIARY_LIST.getDouble(1));
+ assertEquals(3D, TERTIARY_LIST.getDouble(2));
+
+ try {
+ TERTIARY_LIST.get(-1);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ TERTIARY_LIST.get(3);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testSize() {
+ assertEquals(0, DoubleArrayList.emptyList().size());
+ assertEquals(1, UNARY_LIST.size());
+ assertEquals(3, TERTIARY_LIST.size());
+
+ list.addDouble(2);
+ list.addDouble(4);
+ list.addDouble(6);
+ list.addDouble(8);
+ assertEquals(4, list.size());
+
+ list.remove(0);
+ assertEquals(3, list.size());
+
+ list.add(16D);
+ assertEquals(4, list.size());
+ }
+
+ public void testSet() {
+ list.addDouble(2);
+ list.addDouble(4);
+
+ assertEquals(2D, (double) list.set(0, 0D));
+ assertEquals(0D, list.getDouble(0));
+
+ assertEquals(4D, (double) list.set(1, 0D));
+ assertEquals(0D, list.getDouble(1));
+
+ try {
+ list.set(-1, 0D);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ list.set(2, 0D);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testSetInt() {
+ list.addDouble(2);
+ list.addDouble(4);
+
+ assertEquals(2D, list.setDouble(0, 0));
+ assertEquals(0D, list.getDouble(0));
+
+ assertEquals(4D, list.setDouble(1, 0));
+ assertEquals(0D, list.getDouble(1));
+
+ try {
+ list.setDouble(-1, 0);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ list.setDouble(2, 0);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testAdd() {
+ assertEquals(0, list.size());
+
+ assertTrue(list.add(2D));
+ assertEquals(asList(2D), list);
+
+ assertTrue(list.add(3D));
+ list.add(0, 4D);
+ assertEquals(asList(4D, 2D, 3D), list);
+
+ list.add(0, 1D);
+ list.add(0, 0D);
+ // Force a resize by getting up to 11 elements.
+ for (int i = 0; i < 6; i++) {
+ list.add(Double.valueOf(5 + i));
+ }
+ assertEquals(asList(0D, 1D, 4D, 2D, 3D, 5D, 6D, 7D, 8D, 9D, 10D), list);
+
+ try {
+ list.add(-1, 5D);
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ list.add(4, 5D);
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testAddInt() {
+ assertEquals(0, list.size());
+
+ list.addDouble(2);
+ assertEquals(asList(2D), list);
+
+ list.addDouble(3);
+ assertEquals(asList(2D, 3D), list);
+ }
+
+ public void testAddAll() {
+ assertEquals(0, list.size());
+
+ assertTrue(list.addAll(Collections.singleton(1D)));
+ assertEquals(1, list.size());
+ assertEquals(1D, (double) list.get(0));
+ assertEquals(1D, list.getDouble(0));
+
+ assertTrue(list.addAll(asList(2D, 3D, 4D, 5D, 6D)));
+ assertEquals(asList(1D, 2D, 3D, 4D, 5D, 6D), list);
+
+ assertTrue(list.addAll(TERTIARY_LIST));
+ assertEquals(asList(1D, 2D, 3D, 4D, 5D, 6D, 1D, 2D, 3D), list);
+
+ assertFalse(list.addAll(Collections.<Double>emptyList()));
+ assertFalse(list.addAll(DoubleArrayList.emptyList()));
+ }
+
+ public void testRemove() {
+ list.addAll(TERTIARY_LIST);
+ assertEquals(1D, (double) list.remove(0));
+ assertEquals(asList(2D, 3D), list);
+
+ assertTrue(list.remove(Double.valueOf(3)));
+ assertEquals(asList(2D), list);
+
+ assertFalse(list.remove(Double.valueOf(3)));
+ assertEquals(asList(2D), list);
+
+ assertEquals(2D, (double) list.remove(0));
+ assertEquals(asList(), list);
+
+ try {
+ list.remove(-1);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ list.remove(0);
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ private void assertImmutable(DoubleArrayList list) {
+ if (list.contains(1D)) {
+ throw new RuntimeException("Cannot test the immutability of lists that contain 1.");
+ }
+
+ try {
+ list.add(1D);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.add(0, 1D);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(Collections.<Double>emptyList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(Collections.singletonList(1D));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(new DoubleArrayList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(UNARY_LIST);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(0, Collections.singleton(1D));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(0, UNARY_LIST);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(0, Collections.<Double>emptyList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addDouble(0);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.clear();
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.remove(1);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.remove(new Object());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.removeAll(Collections.<Double>emptyList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.removeAll(Collections.singleton(1D));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.removeAll(UNARY_LIST);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.retainAll(Collections.<Double>emptyList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.retainAll(Collections.singleton(1D));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.retainAll(UNARY_LIST);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.set(0, 0D);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.setDouble(0, 0);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ }
+
+ private static DoubleArrayList newImmutableDoubleArrayList(double... elements) {
+ DoubleArrayList list = new DoubleArrayList();
+ for (double element : elements) {
+ list.addDouble(element);
+ }
+ list.makeImmutable();
+ return list;
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/DynamicMessageTest.java b/java/core/src/test/java/com/google/protobuf/DynamicMessageTest.java
new file mode 100644
index 00000000..55144e7c
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/DynamicMessageTest.java
@@ -0,0 +1,326 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// 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 com.google.protobuf.Descriptors.EnumDescriptor;
+import com.google.protobuf.Descriptors.FieldDescriptor;
+import com.google.protobuf.Descriptors.OneofDescriptor;
+
+import protobuf_unittest.UnittestProto.TestAllExtensions;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.TestEmptyMessage;
+import protobuf_unittest.UnittestProto.TestPackedTypes;
+
+import junit.framework.TestCase;
+import java.util.Arrays;
+
+/**
+ * Unit test for {@link DynamicMessage}. See also {@link MessageTest}, which
+ * tests some {@link DynamicMessage} functionality.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public class DynamicMessageTest extends TestCase {
+ TestUtil.ReflectionTester reflectionTester =
+ new TestUtil.ReflectionTester(TestAllTypes.getDescriptor(), null);
+
+ TestUtil.ReflectionTester extensionsReflectionTester =
+ new TestUtil.ReflectionTester(TestAllExtensions.getDescriptor(),
+ TestUtil.getExtensionRegistry());
+ TestUtil.ReflectionTester packedReflectionTester =
+ new TestUtil.ReflectionTester(TestPackedTypes.getDescriptor(), null);
+
+ public void testDynamicMessageAccessors() throws Exception {
+ Message.Builder builder =
+ DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
+ reflectionTester.setAllFieldsViaReflection(builder);
+ Message message = builder.build();
+ reflectionTester.assertAllFieldsSetViaReflection(message);
+ }
+
+ public void testSettersAfterBuild() throws Exception {
+ Message.Builder builder =
+ DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
+ Message firstMessage = builder.build();
+ // double build()
+ builder.build();
+ // clear() after build()
+ builder.clear();
+ // setters after build()
+ reflectionTester.setAllFieldsViaReflection(builder);
+ Message message = builder.build();
+ reflectionTester.assertAllFieldsSetViaReflection(message);
+ // repeated setters after build()
+ reflectionTester.modifyRepeatedFieldsViaReflection(builder);
+ message = builder.build();
+ reflectionTester.assertRepeatedFieldsModifiedViaReflection(message);
+ // firstMessage shouldn't have been modified.
+ reflectionTester.assertClearViaReflection(firstMessage);
+ }
+
+ public void testUnknownFields() throws Exception {
+ Message.Builder builder =
+ DynamicMessage.newBuilder(TestEmptyMessage.getDescriptor());
+ builder.setUnknownFields(UnknownFieldSet.newBuilder()
+ .addField(1, UnknownFieldSet.Field.newBuilder().addVarint(1).build())
+ .addField(2, UnknownFieldSet.Field.newBuilder().addFixed32(1).build())
+ .build());
+ Message message = builder.build();
+ assertEquals(2, message.getUnknownFields().asMap().size());
+ // clone() with unknown fields
+ Message.Builder newBuilder = builder.clone();
+ assertEquals(2, newBuilder.getUnknownFields().asMap().size());
+ // clear() with unknown fields
+ newBuilder.clear();
+ assertTrue(newBuilder.getUnknownFields().asMap().isEmpty());
+ // serialize/parse with unknown fields
+ newBuilder.mergeFrom(message.toByteString());
+ assertEquals(2, newBuilder.getUnknownFields().asMap().size());
+ }
+
+ public void testDynamicMessageSettersRejectNull() throws Exception {
+ Message.Builder builder =
+ DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
+ reflectionTester.assertReflectionSettersRejectNull(builder);
+ }
+
+ public void testDynamicMessageExtensionAccessors() throws Exception {
+ // We don't need to extensively test DynamicMessage's handling of
+ // extensions because, frankly, it doesn't do anything special with them.
+ // It treats them just like any other fields.
+ Message.Builder builder =
+ DynamicMessage.newBuilder(TestAllExtensions.getDescriptor());
+ extensionsReflectionTester.setAllFieldsViaReflection(builder);
+ Message message = builder.build();
+ extensionsReflectionTester.assertAllFieldsSetViaReflection(message);
+ }
+
+ public void testDynamicMessageExtensionSettersRejectNull() throws Exception {
+ Message.Builder builder =
+ DynamicMessage.newBuilder(TestAllExtensions.getDescriptor());
+ extensionsReflectionTester.assertReflectionSettersRejectNull(builder);
+ }
+
+ public void testDynamicMessageRepeatedSetters() throws Exception {
+ Message.Builder builder =
+ DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
+ reflectionTester.setAllFieldsViaReflection(builder);
+ reflectionTester.modifyRepeatedFieldsViaReflection(builder);
+ Message message = builder.build();
+ reflectionTester.assertRepeatedFieldsModifiedViaReflection(message);
+ }
+
+ public void testDynamicMessageRepeatedSettersRejectNull() throws Exception {
+ Message.Builder builder =
+ DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
+ reflectionTester.assertReflectionRepeatedSettersRejectNull(builder);
+ }
+
+ public void testDynamicMessageDefaults() throws Exception {
+ reflectionTester.assertClearViaReflection(
+ DynamicMessage.getDefaultInstance(TestAllTypes.getDescriptor()));
+ reflectionTester.assertClearViaReflection(
+ DynamicMessage.newBuilder(TestAllTypes.getDescriptor()).build());
+ }
+
+ public void testDynamicMessageSerializedSize() throws Exception {
+ TestAllTypes message = TestUtil.getAllSet();
+
+ Message.Builder dynamicBuilder =
+ DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
+ reflectionTester.setAllFieldsViaReflection(dynamicBuilder);
+ Message dynamicMessage = dynamicBuilder.build();
+
+ assertEquals(message.getSerializedSize(),
+ dynamicMessage.getSerializedSize());
+ }
+
+ public void testDynamicMessageSerialization() throws Exception {
+ Message.Builder builder =
+ DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
+ reflectionTester.setAllFieldsViaReflection(builder);
+ Message message = builder.build();
+
+ ByteString rawBytes = message.toByteString();
+ TestAllTypes message2 = TestAllTypes.parseFrom(rawBytes);
+
+ TestUtil.assertAllFieldsSet(message2);
+
+ // In fact, the serialized forms should be exactly the same, byte-for-byte.
+ assertEquals(TestUtil.getAllSet().toByteString(), rawBytes);
+ }
+
+ public void testDynamicMessageParsing() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TestUtil.setAllFields(builder);
+ TestAllTypes message = builder.build();
+
+ ByteString rawBytes = message.toByteString();
+
+ Message message2 =
+ DynamicMessage.parseFrom(TestAllTypes.getDescriptor(), rawBytes);
+ reflectionTester.assertAllFieldsSetViaReflection(message2);
+
+ // Test Parser interface.
+ Message message3 = message2.getParserForType().parseFrom(rawBytes);
+ reflectionTester.assertAllFieldsSetViaReflection(message3);
+ }
+
+ public void testDynamicMessageExtensionParsing() throws Exception {
+ ByteString rawBytes = TestUtil.getAllExtensionsSet().toByteString();
+ Message message = DynamicMessage.parseFrom(
+ TestAllExtensions.getDescriptor(), rawBytes,
+ TestUtil.getExtensionRegistry());
+ extensionsReflectionTester.assertAllFieldsSetViaReflection(message);
+
+ // Test Parser interface.
+ Message message2 = message.getParserForType().parseFrom(
+ rawBytes, TestUtil.getExtensionRegistry());
+ extensionsReflectionTester.assertAllFieldsSetViaReflection(message2);
+ }
+
+ public void testDynamicMessagePackedSerialization() throws Exception {
+ Message.Builder builder =
+ DynamicMessage.newBuilder(TestPackedTypes.getDescriptor());
+ packedReflectionTester.setPackedFieldsViaReflection(builder);
+ Message message = builder.build();
+
+ ByteString rawBytes = message.toByteString();
+ TestPackedTypes message2 = TestPackedTypes.parseFrom(rawBytes);
+
+ TestUtil.assertPackedFieldsSet(message2);
+
+ // In fact, the serialized forms should be exactly the same, byte-for-byte.
+ assertEquals(TestUtil.getPackedSet().toByteString(), rawBytes);
+ }
+
+ public void testDynamicMessagePackedParsing() throws Exception {
+ TestPackedTypes.Builder builder = TestPackedTypes.newBuilder();
+ TestUtil.setPackedFields(builder);
+ TestPackedTypes message = builder.build();
+
+ ByteString rawBytes = message.toByteString();
+
+ Message message2 =
+ DynamicMessage.parseFrom(TestPackedTypes.getDescriptor(), rawBytes);
+ packedReflectionTester.assertPackedFieldsSetViaReflection(message2);
+
+ // Test Parser interface.
+ Message message3 = message2.getParserForType().parseFrom(rawBytes);
+ packedReflectionTester.assertPackedFieldsSetViaReflection(message3);
+ }
+
+ public void testDynamicMessageCopy() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TestUtil.setAllFields(builder);
+ TestAllTypes message = builder.build();
+
+ DynamicMessage copy = DynamicMessage.newBuilder(message).build();
+ reflectionTester.assertAllFieldsSetViaReflection(copy);
+
+ // Test oneof behavior
+ FieldDescriptor bytesField =
+ TestAllTypes.getDescriptor().findFieldByName("oneof_bytes");
+ FieldDescriptor uint32Field =
+ TestAllTypes.getDescriptor().findFieldByName("oneof_uint32");
+ assertTrue(copy.hasField(bytesField));
+ assertFalse(copy.hasField(uint32Field));
+ DynamicMessage copy2 =
+ DynamicMessage.newBuilder(message).setField(uint32Field, 123).build();
+ assertFalse(copy2.hasField(bytesField));
+ assertTrue(copy2.hasField(uint32Field));
+ assertEquals(123, copy2.getField(uint32Field));
+ }
+
+ public void testToBuilder() throws Exception {
+ DynamicMessage.Builder builder =
+ DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
+ reflectionTester.setAllFieldsViaReflection(builder);
+ int unknownFieldNum = 9;
+ long unknownFieldVal = 90;
+ builder.setUnknownFields(UnknownFieldSet.newBuilder()
+ .addField(unknownFieldNum,
+ UnknownFieldSet.Field.newBuilder()
+ .addVarint(unknownFieldVal).build())
+ .build());
+ DynamicMessage message = builder.build();
+
+ DynamicMessage derived = message.toBuilder().build();
+ reflectionTester.assertAllFieldsSetViaReflection(derived);
+ assertEquals(Arrays.asList(unknownFieldVal),
+ derived.getUnknownFields().getField(unknownFieldNum).getVarintList());
+ }
+
+ public void testDynamicOneofMessage() throws Exception {
+ DynamicMessage.Builder builder =
+ DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
+ OneofDescriptor oneof = TestAllTypes.getDescriptor().getOneofs().get(0);
+ assertFalse(builder.hasOneof(oneof));
+ assertSame(null, builder.getOneofFieldDescriptor(oneof));
+
+ reflectionTester.setAllFieldsViaReflection(builder);
+ assertTrue(builder.hasOneof(oneof));
+ FieldDescriptor field = oneof.getField(3);
+ assertSame(field, builder.getOneofFieldDescriptor(oneof));
+
+ DynamicMessage message = builder.buildPartial();
+ assertTrue(message.hasOneof(oneof));
+
+ DynamicMessage.Builder mergedBuilder =
+ DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
+ FieldDescriptor mergedField = oneof.getField(0);
+ mergedBuilder.setField(mergedField, 123);
+ assertTrue(mergedBuilder.hasField(mergedField));
+ mergedBuilder.mergeFrom(message);
+ assertTrue(mergedBuilder.hasField(field));
+ assertFalse(mergedBuilder.hasField(mergedField));
+
+ builder.clearOneof(oneof);
+ assertSame(null, builder.getOneofFieldDescriptor(oneof));
+ message = builder.build();
+ assertSame(null, message.getOneofFieldDescriptor(oneof));
+ }
+
+ // Regression test for a bug that makes setField() not work for repeated
+ // enum fields.
+ public void testSettersForRepeatedEnumField() throws Exception {
+ DynamicMessage.Builder builder =
+ DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
+ FieldDescriptor repeatedEnumField =
+ TestAllTypes.getDescriptor().findFieldByName(
+ "repeated_nested_enum");
+ EnumDescriptor enumDescriptor = TestAllTypes.NestedEnum.getDescriptor();
+ builder.setField(repeatedEnumField, enumDescriptor.getValues());
+ DynamicMessage message = builder.build();
+ assertEquals(
+ enumDescriptor.getValues(), message.getField(repeatedEnumField));
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/FieldPresenceTest.java b/java/core/src/test/java/com/google/protobuf/FieldPresenceTest.java
new file mode 100644
index 00000000..eaeec0b8
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/FieldPresenceTest.java
@@ -0,0 +1,373 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// 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 com.google.protobuf.Descriptors.Descriptor;
+import com.google.protobuf.Descriptors.FieldDescriptor;
+import com.google.protobuf.FieldPresenceTestProto.TestAllTypes;
+import com.google.protobuf.FieldPresenceTestProto.TestOptionalFieldsOnly;
+import com.google.protobuf.FieldPresenceTestProto.TestRepeatedFieldsOnly;
+import protobuf_unittest.UnittestProto;
+
+import junit.framework.TestCase;
+
+/**
+ * Unit tests for protos that doesn't support field presence test for optional
+ * non-message fields.
+ */
+public class FieldPresenceTest extends TestCase {
+ private static boolean hasMethod(Class clazz, String name) {
+ try {
+ if (clazz.getMethod(name, new Class[]{}) != null) {
+ return true;
+ } else {
+ return false;
+ }
+ } catch (NoSuchMethodException e) {
+ return false;
+ }
+ }
+
+ private static boolean isHasMethodRemoved(
+ Class classWithFieldPresence,
+ Class classWithoutFieldPresence,
+ String camelName) {
+ return hasMethod(classWithFieldPresence, "get" + camelName)
+ && hasMethod(classWithFieldPresence, "has" + camelName)
+ && hasMethod(classWithoutFieldPresence, "get" + camelName)
+ && !hasMethod(classWithoutFieldPresence, "has" + camelName);
+ }
+
+ public void testHasMethod() {
+ // Optional non-message fields don't have a hasFoo() method generated.
+ assertTrue(isHasMethodRemoved(
+ UnittestProto.TestAllTypes.class,
+ TestAllTypes.class,
+ "OptionalInt32"));
+ assertTrue(isHasMethodRemoved(
+ UnittestProto.TestAllTypes.class,
+ TestAllTypes.class,
+ "OptionalString"));
+ assertTrue(isHasMethodRemoved(
+ UnittestProto.TestAllTypes.class,
+ TestAllTypes.class,
+ "OptionalBytes"));
+ assertTrue(isHasMethodRemoved(
+ UnittestProto.TestAllTypes.class,
+ TestAllTypes.class,
+ "OptionalNestedEnum"));
+
+ assertTrue(isHasMethodRemoved(
+ UnittestProto.TestAllTypes.Builder.class,
+ TestAllTypes.Builder.class,
+ "OptionalInt32"));
+ assertTrue(isHasMethodRemoved(
+ UnittestProto.TestAllTypes.Builder.class,
+ TestAllTypes.Builder.class,
+ "OptionalString"));
+ assertTrue(isHasMethodRemoved(
+ UnittestProto.TestAllTypes.Builder.class,
+ TestAllTypes.Builder.class,
+ "OptionalBytes"));
+ assertTrue(isHasMethodRemoved(
+ UnittestProto.TestAllTypes.Builder.class,
+ TestAllTypes.Builder.class,
+ "OptionalNestedEnum"));
+
+ // message fields still have the hasFoo() method generated.
+ assertFalse(TestAllTypes.newBuilder().build().hasOptionalNestedMessage());
+ assertFalse(TestAllTypes.newBuilder().hasOptionalNestedMessage());
+
+ // oneof fields don't have hasFoo() methods (even for message types).
+ assertTrue(isHasMethodRemoved(
+ UnittestProto.TestAllTypes.class,
+ TestAllTypes.class,
+ "OneofUint32"));
+ assertTrue(isHasMethodRemoved(
+ UnittestProto.TestAllTypes.class,
+ TestAllTypes.class,
+ "OneofString"));
+ assertTrue(isHasMethodRemoved(
+ UnittestProto.TestAllTypes.class,
+ TestAllTypes.class,
+ "OneofBytes"));
+ assertTrue(isHasMethodRemoved(
+ UnittestProto.TestAllTypes.class,
+ TestAllTypes.class,
+ "OneofNestedMessage"));
+
+ assertTrue(isHasMethodRemoved(
+ UnittestProto.TestAllTypes.Builder.class,
+ TestAllTypes.Builder.class,
+ "OneofUint32"));
+ assertTrue(isHasMethodRemoved(
+ UnittestProto.TestAllTypes.Builder.class,
+ TestAllTypes.Builder.class,
+ "OneofString"));
+ assertTrue(isHasMethodRemoved(
+ UnittestProto.TestAllTypes.Builder.class,
+ TestAllTypes.Builder.class,
+ "OneofBytes"));
+ assertTrue(isHasMethodRemoved(
+ UnittestProto.TestAllTypes.Builder.class,
+ TestAllTypes.Builder.class,
+ "OneofNestedMessage"));
+ }
+
+ public void testOneofEquals() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TestAllTypes message1 = builder.build();
+ // Set message2's oneof_uint32 field to defalut value. The two
+ // messages should be different when check with oneof case.
+ builder.setOneofUint32(0);
+ TestAllTypes message2 = builder.build();
+ assertFalse(message1.equals(message2));
+ }
+
+ public void testFieldPresence() {
+ // Optional non-message fields set to their default value are treated the
+ // same way as not set.
+
+ // Serialization will ignore such fields.
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ builder.setOptionalInt32(0);
+ builder.setOptionalString("");
+ builder.setOptionalBytes(ByteString.EMPTY);
+ builder.setOptionalNestedEnum(TestAllTypes.NestedEnum.FOO);
+ TestAllTypes message = builder.build();
+ assertEquals(0, message.getSerializedSize());
+
+ // mergeFrom() will ignore such fields.
+ TestAllTypes.Builder a = TestAllTypes.newBuilder();
+ a.setOptionalInt32(1);
+ a.setOptionalString("x");
+ a.setOptionalBytes(ByteString.copyFromUtf8("y"));
+ a.setOptionalNestedEnum(TestAllTypes.NestedEnum.BAR);
+ TestAllTypes.Builder b = TestAllTypes.newBuilder();
+ b.setOptionalInt32(0);
+ b.setOptionalString("");
+ b.setOptionalBytes(ByteString.EMPTY);
+ b.setOptionalNestedEnum(TestAllTypes.NestedEnum.FOO);
+ a.mergeFrom(b.build());
+ message = a.build();
+ assertEquals(1, message.getOptionalInt32());
+ assertEquals("x", message.getOptionalString());
+ assertEquals(ByteString.copyFromUtf8("y"), message.getOptionalBytes());
+ assertEquals(TestAllTypes.NestedEnum.BAR, message.getOptionalNestedEnum());
+
+ // equals()/hashCode() should produce the same results.
+ TestAllTypes empty = TestAllTypes.newBuilder().build();
+ message = builder.build();
+ assertTrue(empty.equals(message));
+ assertTrue(message.equals(empty));
+ assertEquals(empty.hashCode(), message.hashCode());
+ }
+
+ public void testFieldPresenceByReflection() {
+ Descriptor descriptor = TestAllTypes.getDescriptor();
+ FieldDescriptor optionalInt32Field = descriptor.findFieldByName("optional_int32");
+ FieldDescriptor optionalStringField = descriptor.findFieldByName("optional_string");
+ FieldDescriptor optionalBytesField = descriptor.findFieldByName("optional_bytes");
+ FieldDescriptor optionalNestedEnumField = descriptor.findFieldByName("optional_nested_enum");
+
+ // Field not present.
+ TestAllTypes message = TestAllTypes.newBuilder().build();
+ assertFalse(message.hasField(optionalInt32Field));
+ assertFalse(message.hasField(optionalStringField));
+ assertFalse(message.hasField(optionalBytesField));
+ assertFalse(message.hasField(optionalNestedEnumField));
+ assertEquals(0, message.getAllFields().size());
+
+ // Field set to default value is seen as not present.
+ message = TestAllTypes.newBuilder()
+ .setOptionalInt32(0)
+ .setOptionalString("")
+ .setOptionalBytes(ByteString.EMPTY)
+ .setOptionalNestedEnum(TestAllTypes.NestedEnum.FOO)
+ .build();
+ assertFalse(message.hasField(optionalInt32Field));
+ assertFalse(message.hasField(optionalStringField));
+ assertFalse(message.hasField(optionalBytesField));
+ assertFalse(message.hasField(optionalNestedEnumField));
+ assertEquals(0, message.getAllFields().size());
+
+ // Field set to non-default value is seen as present.
+ message = TestAllTypes.newBuilder()
+ .setOptionalInt32(1)
+ .setOptionalString("x")
+ .setOptionalBytes(ByteString.copyFromUtf8("y"))
+ .setOptionalNestedEnum(TestAllTypes.NestedEnum.BAR)
+ .build();
+ assertTrue(message.hasField(optionalInt32Field));
+ assertTrue(message.hasField(optionalStringField));
+ assertTrue(message.hasField(optionalBytesField));
+ assertTrue(message.hasField(optionalNestedEnumField));
+ assertEquals(4, message.getAllFields().size());
+ }
+
+ public void testMessageField() {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ assertFalse(builder.hasOptionalNestedMessage());
+ assertFalse(builder.build().hasOptionalNestedMessage());
+
+ TestAllTypes.NestedMessage.Builder nestedBuilder =
+ builder.getOptionalNestedMessageBuilder();
+ assertTrue(builder.hasOptionalNestedMessage());
+ assertTrue(builder.build().hasOptionalNestedMessage());
+
+ nestedBuilder.setValue(1);
+ assertEquals(1, builder.build().getOptionalNestedMessage().getValue());
+
+ builder.clearOptionalNestedMessage();
+ assertFalse(builder.hasOptionalNestedMessage());
+ assertFalse(builder.build().hasOptionalNestedMessage());
+
+ // Unlike non-message fields, if we set a message field to its default value (i.e.,
+ // default instance), the field should be seen as present.
+ builder.setOptionalNestedMessage(TestAllTypes.NestedMessage.getDefaultInstance());
+ assertTrue(builder.hasOptionalNestedMessage());
+ assertTrue(builder.build().hasOptionalNestedMessage());
+ }
+
+ public void testSerializeAndParse() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ builder.setOptionalInt32(1234);
+ builder.setOptionalString("hello");
+ builder.setOptionalNestedMessage(TestAllTypes.NestedMessage.getDefaultInstance());
+ // Set an oneof field to its default value and expect it to be serialized (i.e.,
+ // an oneof field set to the default value should be treated as present).
+ builder.setOneofInt32(0);
+ ByteString data = builder.build().toByteString();
+
+ TestAllTypes message = TestAllTypes.parseFrom(data);
+ assertEquals(1234, message.getOptionalInt32());
+ assertEquals("hello", message.getOptionalString());
+ // Fields not set will have the default value.
+ assertEquals(ByteString.EMPTY, message.getOptionalBytes());
+ assertEquals(TestAllTypes.NestedEnum.FOO, message.getOptionalNestedEnum());
+ // The message field is set despite that it's set with a default instance.
+ assertTrue(message.hasOptionalNestedMessage());
+ assertEquals(0, message.getOptionalNestedMessage().getValue());
+ // The oneof field set to its default value is also present.
+ assertEquals(
+ TestAllTypes.OneofFieldCase.ONEOF_INT32, message.getOneofFieldCase());
+ }
+
+ // Regression test for b/16173397
+ // Make sure we haven't screwed up the code generation for repeated fields.
+ public void testRepeatedFields() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ builder.setOptionalInt32(1234);
+ builder.setOptionalString("hello");
+ builder.setOptionalNestedMessage(TestAllTypes.NestedMessage.getDefaultInstance());
+ builder.addRepeatedInt32(4321);
+ builder.addRepeatedString("world");
+ builder.addRepeatedNestedMessage(TestAllTypes.NestedMessage.getDefaultInstance());
+ ByteString data = builder.build().toByteString();
+
+ TestOptionalFieldsOnly optionalOnlyMessage = TestOptionalFieldsOnly.parseFrom(data);
+ assertEquals(1234, optionalOnlyMessage.getOptionalInt32());
+ assertEquals("hello", optionalOnlyMessage.getOptionalString());
+ assertTrue(optionalOnlyMessage.hasOptionalNestedMessage());
+ assertEquals(0, optionalOnlyMessage.getOptionalNestedMessage().getValue());
+
+ TestRepeatedFieldsOnly repeatedOnlyMessage = TestRepeatedFieldsOnly.parseFrom(data);
+ assertEquals(1, repeatedOnlyMessage.getRepeatedInt32Count());
+ assertEquals(4321, repeatedOnlyMessage.getRepeatedInt32(0));
+ assertEquals(1, repeatedOnlyMessage.getRepeatedStringCount());
+ assertEquals("world", repeatedOnlyMessage.getRepeatedString(0));
+ assertEquals(1, repeatedOnlyMessage.getRepeatedNestedMessageCount());
+ assertEquals(0, repeatedOnlyMessage.getRepeatedNestedMessage(0).getValue());
+ }
+
+ public void testIsInitialized() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+
+ // Test optional proto2 message fields.
+ UnittestProto.TestRequired.Builder proto2Builder =
+ builder.getOptionalProto2MessageBuilder();
+ assertFalse(builder.isInitialized());
+ assertFalse(builder.buildPartial().isInitialized());
+
+ proto2Builder.setA(1).setB(2).setC(3);
+ assertTrue(builder.isInitialized());
+ assertTrue(builder.buildPartial().isInitialized());
+
+ // Test oneof proto2 message fields.
+ proto2Builder = builder.getOneofProto2MessageBuilder();
+ assertFalse(builder.isInitialized());
+ assertFalse(builder.buildPartial().isInitialized());
+
+ proto2Builder.setA(1).setB(2).setC(3);
+ assertTrue(builder.isInitialized());
+ assertTrue(builder.buildPartial().isInitialized());
+
+ // Test repeated proto2 message fields.
+ proto2Builder = builder.addRepeatedProto2MessageBuilder();
+ assertFalse(builder.isInitialized());
+ assertFalse(builder.buildPartial().isInitialized());
+
+ proto2Builder.setA(1).setB(2).setC(3);
+ assertTrue(builder.isInitialized());
+ assertTrue(builder.buildPartial().isInitialized());
+ }
+
+
+ // Test that unknown fields are dropped.
+ public void testUnknownFields() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ builder.setOptionalInt32(1234);
+ builder.addRepeatedInt32(5678);
+ TestAllTypes message = builder.build();
+ ByteString data = message.toByteString();
+
+ TestOptionalFieldsOnly optionalOnlyMessage =
+ TestOptionalFieldsOnly.parseFrom(data);
+ // UnknownFieldSet should be empty.
+ assertEquals(
+ 0, optionalOnlyMessage.getUnknownFields().toByteString().size());
+ assertEquals(1234, optionalOnlyMessage.getOptionalInt32());
+ message = TestAllTypes.parseFrom(optionalOnlyMessage.toByteString());
+ assertEquals(1234, message.getOptionalInt32());
+ // The repeated field is discarded because it's unknown to the optional-only
+ // message.
+ assertEquals(0, message.getRepeatedInt32Count());
+
+ DynamicMessage dynamicOptionalOnlyMessage =
+ DynamicMessage.getDefaultInstance(
+ TestOptionalFieldsOnly.getDescriptor())
+ .getParserForType().parseFrom(data);
+ assertEquals(
+ 0, dynamicOptionalOnlyMessage.getUnknownFields().toByteString().size());
+ assertEquals(optionalOnlyMessage.toByteString(),
+ dynamicOptionalOnlyMessage.toByteString());
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/FloatArrayListTest.java b/java/core/src/test/java/com/google/protobuf/FloatArrayListTest.java
new file mode 100644
index 00000000..a5e65424
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/FloatArrayListTest.java
@@ -0,0 +1,473 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// 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 static java.util.Arrays.asList;
+
+import junit.framework.TestCase;
+
+import java.util.Collections;
+import java.util.ConcurrentModificationException;
+import java.util.Iterator;
+
+/**
+ * Tests for {@link FloatArrayList}.
+ *
+ * @author dweis@google.com (Daniel Weis)
+ */
+public class FloatArrayListTest extends TestCase {
+
+ private static final FloatArrayList UNARY_LIST = newImmutableFloatArrayList(1);
+ private static final FloatArrayList TERTIARY_LIST =
+ newImmutableFloatArrayList(1, 2, 3);
+
+ private FloatArrayList list;
+
+ @Override
+ protected void setUp() throws Exception {
+ list = new FloatArrayList();
+ }
+
+ public void testEmptyListReturnsSameInstance() {
+ assertSame(FloatArrayList.emptyList(), FloatArrayList.emptyList());
+ }
+
+ public void testEmptyListIsImmutable() {
+ assertImmutable(FloatArrayList.emptyList());
+ }
+
+ public void testMakeImmutable() {
+ list.addFloat(2);
+ list.addFloat(4);
+ list.addFloat(6);
+ list.addFloat(8);
+ list.makeImmutable();
+ assertImmutable(list);
+ }
+
+ public void testCopyConstructor() {
+ FloatArrayList copy = new FloatArrayList(TERTIARY_LIST);
+ assertEquals(TERTIARY_LIST, copy);
+
+ copy = new FloatArrayList(FloatArrayList.emptyList());
+ assertEquals(FloatArrayList.emptyList(), copy);
+
+ copy = new FloatArrayList(asList(1F, 2F, 3F));
+ assertEquals(asList(1F, 2F, 3F), copy);
+
+ copy = new FloatArrayList(Collections.<Float>emptyList());
+ assertEquals(FloatArrayList.emptyList(), copy);
+ }
+
+ public void testModificationWithIteration() {
+ list.addAll(asList(1F, 2F, 3F, 4F));
+ Iterator<Float> iterator = list.iterator();
+ assertEquals(4, list.size());
+ assertEquals(1F, (float) list.get(0));
+ assertEquals(1F, (float) iterator.next());
+ list.set(0, 1F);
+ assertEquals(2F, (float) iterator.next());
+
+ list.remove(0);
+ try {
+ iterator.next();
+ fail();
+ } catch (ConcurrentModificationException e) {
+ // expected
+ }
+
+ iterator = list.iterator();
+ list.add(0, 0F);
+ try {
+ iterator.next();
+ fail();
+ } catch (ConcurrentModificationException e) {
+ // expected
+ }
+ }
+
+ public void testGet() {
+ assertEquals(1F, (float) TERTIARY_LIST.get(0));
+ assertEquals(2F, (float) TERTIARY_LIST.get(1));
+ assertEquals(3F, (float) TERTIARY_LIST.get(2));
+
+ try {
+ TERTIARY_LIST.get(-1);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ TERTIARY_LIST.get(3);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testGetFloat() {
+ assertEquals(1F, TERTIARY_LIST.getFloat(0));
+ assertEquals(2F, TERTIARY_LIST.getFloat(1));
+ assertEquals(3F, TERTIARY_LIST.getFloat(2));
+
+ try {
+ TERTIARY_LIST.get(-1);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ TERTIARY_LIST.get(3);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testSize() {
+ assertEquals(0, FloatArrayList.emptyList().size());
+ assertEquals(1, UNARY_LIST.size());
+ assertEquals(3, TERTIARY_LIST.size());
+
+ list.addFloat(2);
+ list.addFloat(4);
+ list.addFloat(6);
+ list.addFloat(8);
+ assertEquals(4, list.size());
+
+ list.remove(0);
+ assertEquals(3, list.size());
+
+ list.add(16F);
+ assertEquals(4, list.size());
+ }
+
+ public void testSet() {
+ list.addFloat(2);
+ list.addFloat(4);
+
+ assertEquals(2F, (float) list.set(0, 0F));
+ assertEquals(0F, list.getFloat(0));
+
+ assertEquals(4F, (float) list.set(1, 0F));
+ assertEquals(0F, list.getFloat(1));
+
+ try {
+ list.set(-1, 0F);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ list.set(2, 0F);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testSetFloat() {
+ list.addFloat(2);
+ list.addFloat(4);
+
+ assertEquals(2F, list.setFloat(0, 0));
+ assertEquals(0F, list.getFloat(0));
+
+ assertEquals(4F, list.setFloat(1, 0));
+ assertEquals(0F, list.getFloat(1));
+
+ try {
+ list.setFloat(-1, 0);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ list.setFloat(2, 0);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testAdd() {
+ assertEquals(0, list.size());
+
+ assertTrue(list.add(2F));
+ assertEquals(asList(2F), list);
+
+ assertTrue(list.add(3F));
+ list.add(0, 4F);
+ assertEquals(asList(4F, 2F, 3F), list);
+
+ list.add(0, 1F);
+ list.add(0, 0F);
+ // Force a resize by getting up to 11 elements.
+ for (int i = 0; i < 6; i++) {
+ list.add(Float.valueOf(5 + i));
+ }
+ assertEquals(asList(0F, 1F, 4F, 2F, 3F, 5F, 6F, 7F, 8F, 9F, 10F), list);
+
+ try {
+ list.add(-1, 5F);
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ list.add(4, 5F);
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testAddFloat() {
+ assertEquals(0, list.size());
+
+ list.addFloat(2);
+ assertEquals(asList(2F), list);
+
+ list.addFloat(3);
+ assertEquals(asList(2F, 3F), list);
+ }
+
+ public void testAddAll() {
+ assertEquals(0, list.size());
+
+ assertTrue(list.addAll(Collections.singleton(1F)));
+ assertEquals(1, list.size());
+ assertEquals(1F, (float) list.get(0));
+ assertEquals(1F, list.getFloat(0));
+
+ assertTrue(list.addAll(asList(2F, 3F, 4F, 5F, 6F)));
+ assertEquals(asList(1F, 2F, 3F, 4F, 5F, 6F), list);
+
+ assertTrue(list.addAll(TERTIARY_LIST));
+ assertEquals(asList(1F, 2F, 3F, 4F, 5F, 6F, 1F, 2F, 3F), list);
+
+ assertFalse(list.addAll(Collections.<Float>emptyList()));
+ assertFalse(list.addAll(FloatArrayList.emptyList()));
+ }
+
+ public void testRemove() {
+ list.addAll(TERTIARY_LIST);
+ assertEquals(1F, (float) list.remove(0));
+ assertEquals(asList(2F, 3F), list);
+
+ assertTrue(list.remove(Float.valueOf(3)));
+ assertEquals(asList(2F), list);
+
+ assertFalse(list.remove(Float.valueOf(3)));
+ assertEquals(asList(2F), list);
+
+ assertEquals(2F, (float) list.remove(0));
+ assertEquals(asList(), list);
+
+ try {
+ list.remove(-1);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ list.remove(0);
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ private void assertImmutable(FloatArrayList list) {
+ if (list.contains(1F)) {
+ throw new RuntimeException("Cannot test the immutability of lists that contain 1.");
+ }
+
+ try {
+ list.add(1F);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.add(0, 1F);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(Collections.<Float>emptyList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(Collections.singletonList(1F));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(new FloatArrayList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(UNARY_LIST);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(0, Collections.singleton(1F));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(0, UNARY_LIST);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(0, Collections.<Float>emptyList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addFloat(0);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.clear();
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.remove(1);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.remove(new Object());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.removeAll(Collections.<Float>emptyList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.removeAll(Collections.singleton(1F));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.removeAll(UNARY_LIST);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.retainAll(Collections.<Float>emptyList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.retainAll(Collections.singleton(1F));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.retainAll(UNARY_LIST);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.set(0, 0F);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.setFloat(0, 0);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ }
+
+ private static FloatArrayList newImmutableFloatArrayList(int... elements) {
+ FloatArrayList list = new FloatArrayList();
+ for (int element : elements) {
+ list.addFloat(element);
+ }
+ list.makeImmutable();
+ return list;
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/ForceFieldBuildersPreRun.java b/java/core/src/test/java/com/google/protobuf/ForceFieldBuildersPreRun.java
new file mode 100644
index 00000000..a92ba374
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/ForceFieldBuildersPreRun.java
@@ -0,0 +1,48 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// 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;
+
+/**
+ * A prerun for a test suite that allows running the full protocol buffer
+ * tests in a mode that disables the optimization for not using
+ * {@link RepeatedFieldBuilder} and {@link SingleFieldBuilder} until they are
+ * requested. This allows us to run all the tests through both code paths
+ * and ensures that both code paths produce identical results.
+ *
+ * @author jonp@google.com (Jon Perlow)
+ */
+public class ForceFieldBuildersPreRun implements Runnable {
+
+ //@Override (Java 1.6 override semantics, but we must support 1.5)
+ public void run() {
+ GeneratedMessage.enableAlwaysUseFieldBuildersForTesting();
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/GeneratedMessageTest.java b/java/core/src/test/java/com/google/protobuf/GeneratedMessageTest.java
new file mode 100644
index 00000000..70812b95
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/GeneratedMessageTest.java
@@ -0,0 +1,1661 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// 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 com.google.protobuf.Descriptors.Descriptor;
+import com.google.protobuf.Descriptors.FieldDescriptor;
+import com.google.protobuf.UnittestLite.TestAllExtensionsLite;
+import com.google.protobuf.test.UnittestImport;
+import protobuf_unittest.EnumWithNoOuter;
+import protobuf_unittest.MessageWithNoOuter;
+import protobuf_unittest.MultipleFilesTestProto;
+import protobuf_unittest.NestedExtension.MyNestedExtension;
+import protobuf_unittest.NestedExtensionLite.MyNestedExtensionLite;
+import protobuf_unittest.NonNestedExtension;
+import protobuf_unittest.NonNestedExtension.MessageToBeExtended;
+import protobuf_unittest.NonNestedExtension.MyNonNestedExtension;
+import protobuf_unittest.NonNestedExtensionLite;
+import protobuf_unittest.NonNestedExtensionLite.MessageLiteToBeExtended;
+import protobuf_unittest.NonNestedExtensionLite.MyNonNestedExtensionLite;
+import protobuf_unittest.OuterClassNameTest2OuterClass;
+import protobuf_unittest.OuterClassNameTest3OuterClass;
+import protobuf_unittest.OuterClassNameTestOuterClass;
+import protobuf_unittest.ServiceWithNoOuter;
+import protobuf_unittest.UnittestOptimizeFor.TestOptimizedForSize;
+import protobuf_unittest.UnittestOptimizeFor.TestOptionalOptimizedForSize;
+import protobuf_unittest.UnittestOptimizeFor.TestRequiredOptimizedForSize;
+import protobuf_unittest.UnittestProto;
+import protobuf_unittest.UnittestProto.ForeignEnum;
+import protobuf_unittest.UnittestProto.ForeignMessage;
+import protobuf_unittest.UnittestProto.ForeignMessageOrBuilder;
+import protobuf_unittest.UnittestProto.NestedTestAllTypes;
+import protobuf_unittest.UnittestProto.TestAllExtensions;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.TestAllTypes.NestedMessage;
+import protobuf_unittest.UnittestProto.TestAllTypesOrBuilder;
+import protobuf_unittest.UnittestProto.TestExtremeDefaultValues;
+import protobuf_unittest.UnittestProto.TestOneof2;
+import protobuf_unittest.UnittestProto.TestPackedTypes;
+import protobuf_unittest.UnittestProto.TestUnpackedTypes;
+
+import junit.framework.TestCase;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Unit test for generated messages and generated code. See also
+ * {@link MessageTest}, which tests some generated message functionality.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public class GeneratedMessageTest extends TestCase {
+ TestUtil.ReflectionTester reflectionTester =
+ new TestUtil.ReflectionTester(TestAllTypes.getDescriptor(), null);
+
+ public void testDefaultInstance() throws Exception {
+ assertSame(TestAllTypes.getDefaultInstance(),
+ TestAllTypes.getDefaultInstance().getDefaultInstanceForType());
+ assertSame(TestAllTypes.getDefaultInstance(),
+ TestAllTypes.newBuilder().getDefaultInstanceForType());
+ }
+
+ public void testMessageOrBuilder() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TestUtil.setAllFields(builder);
+ TestAllTypes message = builder.build();
+ TestUtil.assertAllFieldsSet(message);
+ }
+
+ public void testUsingBuilderMultipleTimes() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ // primitive field scalar and repeated
+ builder.setOptionalSfixed64(100);
+ builder.addRepeatedInt32(100);
+ // enum field scalar and repeated
+ builder.setOptionalImportEnum(UnittestImport.ImportEnum.IMPORT_BAR);
+ builder.addRepeatedImportEnum(UnittestImport.ImportEnum.IMPORT_BAR);
+ // proto field scalar and repeated
+ builder.setOptionalForeignMessage(ForeignMessage.newBuilder().setC(1));
+ builder.addRepeatedForeignMessage(ForeignMessage.newBuilder().setC(1));
+
+ TestAllTypes value1 = builder.build();
+
+ assertEquals(100, value1.getOptionalSfixed64());
+ assertEquals(100, value1.getRepeatedInt32(0));
+ assertEquals(UnittestImport.ImportEnum.IMPORT_BAR,
+ value1.getOptionalImportEnum());
+ assertEquals(UnittestImport.ImportEnum.IMPORT_BAR,
+ value1.getRepeatedImportEnum(0));
+ assertEquals(1, value1.getOptionalForeignMessage().getC());
+ assertEquals(1, value1.getRepeatedForeignMessage(0).getC());
+
+ // Make sure that builder didn't update previously created values
+ builder.setOptionalSfixed64(200);
+ builder.setRepeatedInt32(0, 200);
+ builder.setOptionalImportEnum(UnittestImport.ImportEnum.IMPORT_FOO);
+ builder.setRepeatedImportEnum(0, UnittestImport.ImportEnum.IMPORT_FOO);
+ builder.setOptionalForeignMessage(ForeignMessage.newBuilder().setC(2));
+ builder.setRepeatedForeignMessage(0, ForeignMessage.newBuilder().setC(2));
+
+ TestAllTypes value2 = builder.build();
+
+ // Make sure value1 didn't change.
+ assertEquals(100, value1.getOptionalSfixed64());
+ assertEquals(100, value1.getRepeatedInt32(0));
+ assertEquals(UnittestImport.ImportEnum.IMPORT_BAR,
+ value1.getOptionalImportEnum());
+ assertEquals(UnittestImport.ImportEnum.IMPORT_BAR,
+ value1.getRepeatedImportEnum(0));
+ assertEquals(1, value1.getOptionalForeignMessage().getC());
+ assertEquals(1, value1.getRepeatedForeignMessage(0).getC());
+
+ // Make sure value2 is correct
+ assertEquals(200, value2.getOptionalSfixed64());
+ assertEquals(200, value2.getRepeatedInt32(0));
+ assertEquals(UnittestImport.ImportEnum.IMPORT_FOO,
+ value2.getOptionalImportEnum());
+ assertEquals(UnittestImport.ImportEnum.IMPORT_FOO,
+ value2.getRepeatedImportEnum(0));
+ assertEquals(2, value2.getOptionalForeignMessage().getC());
+ assertEquals(2, value2.getRepeatedForeignMessage(0).getC());
+ }
+
+ public void testProtosShareRepeatedArraysIfDidntChange() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ builder.addRepeatedInt32(100);
+ builder.addRepeatedForeignMessage(ForeignMessage.getDefaultInstance());
+
+ TestAllTypes value1 = builder.build();
+ TestAllTypes value2 = value1.toBuilder().build();
+
+ assertSame(value1.getRepeatedInt32List(), value2.getRepeatedInt32List());
+ assertSame(value1.getRepeatedForeignMessageList(),
+ value2.getRepeatedForeignMessageList());
+ }
+
+ public void testRepeatedArraysAreImmutable() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ builder.addRepeatedInt32(100);
+ builder.addRepeatedImportEnum(UnittestImport.ImportEnum.IMPORT_BAR);
+ builder.addRepeatedForeignMessage(ForeignMessage.getDefaultInstance());
+ assertIsUnmodifiable(builder.getRepeatedInt32List());
+ assertIsUnmodifiable(builder.getRepeatedImportEnumList());
+ assertIsUnmodifiable(builder.getRepeatedForeignMessageList());
+ assertIsUnmodifiable(builder.getRepeatedFloatList());
+
+
+ TestAllTypes value = builder.build();
+ assertIsUnmodifiable(value.getRepeatedInt32List());
+ assertIsUnmodifiable(value.getRepeatedImportEnumList());
+ assertIsUnmodifiable(value.getRepeatedForeignMessageList());
+ assertIsUnmodifiable(value.getRepeatedFloatList());
+ }
+
+ public void testParsedMessagesAreImmutable() throws Exception {
+ TestAllTypes value = TestAllTypes.parser().parseFrom(TestUtil.getAllSet().toByteString());
+ assertIsUnmodifiable(value.getRepeatedInt32List());
+ assertIsUnmodifiable(value.getRepeatedInt64List());
+ assertIsUnmodifiable(value.getRepeatedUint32List());
+ assertIsUnmodifiable(value.getRepeatedUint64List());
+ assertIsUnmodifiable(value.getRepeatedSint32List());
+ assertIsUnmodifiable(value.getRepeatedSint64List());
+ assertIsUnmodifiable(value.getRepeatedFixed32List());
+ assertIsUnmodifiable(value.getRepeatedFixed64List());
+ assertIsUnmodifiable(value.getRepeatedSfixed32List());
+ assertIsUnmodifiable(value.getRepeatedSfixed64List());
+ assertIsUnmodifiable(value.getRepeatedFloatList());
+ assertIsUnmodifiable(value.getRepeatedDoubleList());
+ assertIsUnmodifiable(value.getRepeatedBoolList());
+ assertIsUnmodifiable(value.getRepeatedStringList());
+ assertIsUnmodifiable(value.getRepeatedBytesList());
+ assertIsUnmodifiable(value.getRepeatedGroupList());
+ assertIsUnmodifiable(value.getRepeatedNestedMessageList());
+ assertIsUnmodifiable(value.getRepeatedForeignMessageList());
+ assertIsUnmodifiable(value.getRepeatedImportMessageList());
+ assertIsUnmodifiable(value.getRepeatedNestedEnumList());
+ assertIsUnmodifiable(value.getRepeatedForeignEnumList());
+ assertIsUnmodifiable(value.getRepeatedImportEnumList());
+ }
+
+ private void assertIsUnmodifiable(List<?> list) {
+ if (list == Collections.emptyList()) {
+ // OKAY -- Need to check this b/c EmptyList allows you to call clear.
+ } else {
+ try {
+ list.clear();
+ fail("List wasn't immutable");
+ } catch (UnsupportedOperationException e) {
+ // good
+ }
+ }
+ }
+
+ public void testSettersRejectNull() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ try {
+ builder.setOptionalString(null);
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.setOptionalBytes(null);
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.setOptionalNestedMessage((TestAllTypes.NestedMessage) null);
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.setOptionalNestedMessage(
+ (TestAllTypes.NestedMessage.Builder) null);
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.setOptionalNestedEnum(null);
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.addRepeatedString(null);
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.addRepeatedBytes(null);
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.addRepeatedNestedMessage((TestAllTypes.NestedMessage) null);
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.addRepeatedNestedMessage(
+ (TestAllTypes.NestedMessage.Builder) null);
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.addRepeatedNestedEnum(null);
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ }
+
+ public void testRepeatedSetters() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TestUtil.setAllFields(builder);
+ TestUtil.modifyRepeatedFields(builder);
+ TestAllTypes message = builder.build();
+ TestUtil.assertRepeatedFieldsModified(message);
+ }
+
+ public void testRepeatedSettersRejectNull() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+
+ builder.addRepeatedString("one");
+ builder.addRepeatedString("two");
+ try {
+ builder.setRepeatedString(1, null);
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+
+ builder.addRepeatedBytes(TestUtil.toBytes("one"));
+ builder.addRepeatedBytes(TestUtil.toBytes("two"));
+ try {
+ builder.setRepeatedBytes(1, null);
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+
+ builder.addRepeatedNestedMessage(
+ TestAllTypes.NestedMessage.newBuilder().setBb(218).build());
+ builder.addRepeatedNestedMessage(
+ TestAllTypes.NestedMessage.newBuilder().setBb(456).build());
+ try {
+ builder.setRepeatedNestedMessage(1, (TestAllTypes.NestedMessage) null);
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.setRepeatedNestedMessage(
+ 1, (TestAllTypes.NestedMessage.Builder) null);
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+
+ builder.addRepeatedNestedEnum(TestAllTypes.NestedEnum.FOO);
+ builder.addRepeatedNestedEnum(TestAllTypes.NestedEnum.BAR);
+ try {
+ builder.setRepeatedNestedEnum(1, null);
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ }
+
+ public void testRepeatedAppend() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+
+ builder.addAllRepeatedInt32(Arrays.asList(1, 2, 3, 4));
+ builder.addAllRepeatedForeignEnum(Arrays.asList(ForeignEnum.FOREIGN_BAZ));
+
+ ForeignMessage foreignMessage =
+ ForeignMessage.newBuilder().setC(12).build();
+ builder.addAllRepeatedForeignMessage(Arrays.asList(foreignMessage));
+
+ TestAllTypes message = builder.build();
+ assertEquals(message.getRepeatedInt32List(), Arrays.asList(1, 2, 3, 4));
+ assertEquals(message.getRepeatedForeignEnumList(),
+ Arrays.asList(ForeignEnum.FOREIGN_BAZ));
+ assertEquals(1, message.getRepeatedForeignMessageCount());
+ assertEquals(12, message.getRepeatedForeignMessage(0).getC());
+ }
+
+ public void testRepeatedAppendRejectsNull() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+
+ ForeignMessage foreignMessage =
+ ForeignMessage.newBuilder().setC(12).build();
+ try {
+ builder.addAllRepeatedForeignMessage(
+ Arrays.asList(foreignMessage, (ForeignMessage) null));
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+
+ try {
+ builder.addAllRepeatedForeignEnum(
+ Arrays.asList(ForeignEnum.FOREIGN_BAZ, null));
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+
+ try {
+ builder.addAllRepeatedString(Arrays.asList("one", null));
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+
+ try {
+ builder.addAllRepeatedBytes(Arrays.asList(TestUtil.toBytes("one"), null));
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ }
+
+ public void testRepeatedAppendIterateOnlyOnce() throws Exception {
+ // Create a Iterable that can only be iterated once.
+ Iterable<String> stringIterable = new Iterable<String>() {
+ private boolean called = false;
+ @Override
+ public Iterator<String> iterator() {
+ if (called) {
+ throw new IllegalStateException();
+ }
+ called = true;
+ return Arrays.asList("one", "two", "three").iterator();
+ }
+ };
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ builder.addAllRepeatedString(stringIterable);
+ assertEquals(3, builder.getRepeatedStringCount());
+ assertEquals("one", builder.getRepeatedString(0));
+ assertEquals("two", builder.getRepeatedString(1));
+ assertEquals("three", builder.getRepeatedString(2));
+
+ try {
+ builder.addAllRepeatedString(stringIterable);
+ fail("Exception was not thrown");
+ } catch (IllegalStateException e) {
+ // We expect this exception.
+ }
+ }
+
+ public void testMergeFromOtherRejectsNull() throws Exception {
+ try {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ builder.mergeFrom((TestAllTypes) null);
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ }
+
+ public void testSettingForeignMessageUsingBuilder() throws Exception {
+ TestAllTypes message = TestAllTypes.newBuilder()
+ // Pass builder for foreign message instance.
+ .setOptionalForeignMessage(ForeignMessage.newBuilder().setC(123))
+ .build();
+ TestAllTypes expectedMessage = TestAllTypes.newBuilder()
+ // Create expected version passing foreign message instance explicitly.
+ .setOptionalForeignMessage(
+ ForeignMessage.newBuilder().setC(123).build())
+ .build();
+ // TODO(ngd): Upgrade to using real #equals method once implemented
+ assertEquals(expectedMessage.toString(), message.toString());
+ }
+
+ public void testSettingRepeatedForeignMessageUsingBuilder() throws Exception {
+ TestAllTypes message = TestAllTypes.newBuilder()
+ // Pass builder for foreign message instance.
+ .addRepeatedForeignMessage(ForeignMessage.newBuilder().setC(456))
+ .build();
+ TestAllTypes expectedMessage = TestAllTypes.newBuilder()
+ // Create expected version passing foreign message instance explicitly.
+ .addRepeatedForeignMessage(
+ ForeignMessage.newBuilder().setC(456).build())
+ .build();
+ assertEquals(expectedMessage.toString(), message.toString());
+ }
+
+ public void testDefaults() throws Exception {
+ TestUtil.assertClear(TestAllTypes.getDefaultInstance());
+ TestUtil.assertClear(TestAllTypes.newBuilder().build());
+
+ TestExtremeDefaultValues message =
+ TestExtremeDefaultValues.getDefaultInstance();
+ assertEquals("\u1234", message.getUtf8String());
+ assertEquals(Double.POSITIVE_INFINITY, message.getInfDouble());
+ assertEquals(Double.NEGATIVE_INFINITY, message.getNegInfDouble());
+ assertTrue(Double.isNaN(message.getNanDouble()));
+ assertEquals(Float.POSITIVE_INFINITY, message.getInfFloat());
+ assertEquals(Float.NEGATIVE_INFINITY, message.getNegInfFloat());
+ assertTrue(Float.isNaN(message.getNanFloat()));
+ assertEquals("? ? ?? ?? ??? ??/ ??-", message.getCppTrigraph());
+ }
+
+ public void testClear() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TestUtil.assertClear(builder);
+ TestUtil.setAllFields(builder);
+ builder.clear();
+ TestUtil.assertClear(builder);
+ }
+
+ public void testReflectionGetters() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TestUtil.setAllFields(builder);
+ reflectionTester.assertAllFieldsSetViaReflection(builder);
+
+ TestAllTypes message = builder.build();
+ reflectionTester.assertAllFieldsSetViaReflection(message);
+ }
+
+ public void testReflectionSetters() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ reflectionTester.setAllFieldsViaReflection(builder);
+ TestUtil.assertAllFieldsSet(builder);
+
+ TestAllTypes message = builder.build();
+ TestUtil.assertAllFieldsSet(message);
+ }
+
+ public void testReflectionSettersRejectNull() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ reflectionTester.assertReflectionSettersRejectNull(builder);
+ }
+
+ public void testReflectionRepeatedSetters() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ reflectionTester.setAllFieldsViaReflection(builder);
+ reflectionTester.modifyRepeatedFieldsViaReflection(builder);
+ TestUtil.assertRepeatedFieldsModified(builder);
+
+ TestAllTypes message = builder.build();
+ TestUtil.assertRepeatedFieldsModified(message);
+ }
+
+ public void testReflectionRepeatedSettersRejectNull() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ reflectionTester.assertReflectionRepeatedSettersRejectNull(builder);
+ }
+
+ public void testReflectionDefaults() throws Exception {
+ reflectionTester.assertClearViaReflection(
+ TestAllTypes.getDefaultInstance());
+ reflectionTester.assertClearViaReflection(
+ TestAllTypes.newBuilder().build());
+ }
+
+ public void testReflectionGetOneof() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ reflectionTester.setAllFieldsViaReflection(builder);
+ Descriptors.OneofDescriptor oneof =
+ TestAllTypes.getDescriptor().getOneofs().get(0);
+ Descriptors.FieldDescriptor field =
+ TestAllTypes.getDescriptor().findFieldByName("oneof_bytes");
+ assertSame(field, builder.getOneofFieldDescriptor(oneof));
+
+ TestAllTypes message = builder.build();
+ assertSame(field, message.getOneofFieldDescriptor(oneof));
+ }
+
+ public void testReflectionClearOneof() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ reflectionTester.setAllFieldsViaReflection(builder);
+ Descriptors.OneofDescriptor oneof =
+ TestAllTypes.getDescriptor().getOneofs().get(0);
+ Descriptors.FieldDescriptor field =
+ TestAllTypes.getDescriptor().findFieldByName("oneof_bytes");
+
+ assertTrue(builder.hasOneof(oneof));
+ assertTrue(builder.hasField(field));
+ builder.clearOneof(oneof);
+ assertFalse(builder.hasOneof(oneof));
+ assertFalse(builder.hasField(field));
+ }
+
+ public void testEnumInterface() throws Exception {
+ assertTrue(TestAllTypes.getDefaultInstance().getDefaultNestedEnum()
+ instanceof ProtocolMessageEnum);
+ }
+
+ public void testEnumMap() throws Exception {
+ Internal.EnumLiteMap<ForeignEnum> map = ForeignEnum.internalGetValueMap();
+
+ for (ForeignEnum value : ForeignEnum.values()) {
+ assertEquals(value, map.findValueByNumber(value.getNumber()));
+ }
+
+ assertTrue(map.findValueByNumber(12345) == null);
+ }
+
+ public void testParsePackedToUnpacked() throws Exception {
+ TestUnpackedTypes.Builder builder = TestUnpackedTypes.newBuilder();
+ TestUnpackedTypes message =
+ builder.mergeFrom(TestUtil.getPackedSet().toByteString()).build();
+ TestUtil.assertUnpackedFieldsSet(message);
+ }
+
+ public void testParseUnpackedToPacked() throws Exception {
+ TestPackedTypes.Builder builder = TestPackedTypes.newBuilder();
+ TestPackedTypes message =
+ builder.mergeFrom(TestUtil.getUnpackedSet().toByteString()).build();
+ TestUtil.assertPackedFieldsSet(message);
+ }
+
+ // =================================================================
+ // Extensions.
+
+ TestUtil.ReflectionTester extensionsReflectionTester =
+ new TestUtil.ReflectionTester(TestAllExtensions.getDescriptor(),
+ TestUtil.getExtensionRegistry());
+
+ public void testExtensionMessageOrBuilder() throws Exception {
+ TestAllExtensions.Builder builder = TestAllExtensions.newBuilder();
+ TestUtil.setAllExtensions(builder);
+ TestAllExtensions message = builder.build();
+ TestUtil.assertAllExtensionsSet(message);
+ }
+
+ public void testExtensionRepeatedSetters() throws Exception {
+ TestAllExtensions.Builder builder = TestAllExtensions.newBuilder();
+ TestUtil.setAllExtensions(builder);
+ TestUtil.modifyRepeatedExtensions(builder);
+ TestAllExtensions message = builder.build();
+ TestUtil.assertRepeatedExtensionsModified(message);
+ }
+
+ public void testExtensionDefaults() throws Exception {
+ TestUtil.assertExtensionsClear(TestAllExtensions.getDefaultInstance());
+ TestUtil.assertExtensionsClear(TestAllExtensions.newBuilder().build());
+ }
+
+ public void testExtensionReflectionGetters() throws Exception {
+ TestAllExtensions.Builder builder = TestAllExtensions.newBuilder();
+ TestUtil.setAllExtensions(builder);
+ extensionsReflectionTester.assertAllFieldsSetViaReflection(builder);
+
+ TestAllExtensions message = builder.build();
+ extensionsReflectionTester.assertAllFieldsSetViaReflection(message);
+ }
+
+ public void testExtensionReflectionSetters() throws Exception {
+ TestAllExtensions.Builder builder = TestAllExtensions.newBuilder();
+ extensionsReflectionTester.setAllFieldsViaReflection(builder);
+ TestUtil.assertAllExtensionsSet(builder);
+
+ TestAllExtensions message = builder.build();
+ TestUtil.assertAllExtensionsSet(message);
+ }
+
+ public void testExtensionReflectionSettersRejectNull() throws Exception {
+ TestAllExtensions.Builder builder = TestAllExtensions.newBuilder();
+ extensionsReflectionTester.assertReflectionSettersRejectNull(builder);
+ }
+
+ public void testExtensionReflectionRepeatedSetters() throws Exception {
+ TestAllExtensions.Builder builder = TestAllExtensions.newBuilder();
+ extensionsReflectionTester.setAllFieldsViaReflection(builder);
+ extensionsReflectionTester.modifyRepeatedFieldsViaReflection(builder);
+ TestUtil.assertRepeatedExtensionsModified(builder);
+
+ TestAllExtensions message = builder.build();
+ TestUtil.assertRepeatedExtensionsModified(message);
+ }
+
+ public void testExtensionReflectionRepeatedSettersRejectNull()
+ throws Exception {
+ TestAllExtensions.Builder builder = TestAllExtensions.newBuilder();
+ extensionsReflectionTester.assertReflectionRepeatedSettersRejectNull(
+ builder);
+ }
+
+ public void testExtensionReflectionDefaults() throws Exception {
+ extensionsReflectionTester.assertClearViaReflection(
+ TestAllExtensions.getDefaultInstance());
+ extensionsReflectionTester.assertClearViaReflection(
+ TestAllExtensions.newBuilder().build());
+ }
+
+ public void testClearExtension() throws Exception {
+ // clearExtension() is not actually used in TestUtil, so try it manually.
+ assertFalse(
+ TestAllExtensions.newBuilder()
+ .setExtension(UnittestProto.optionalInt32Extension, 1)
+ .clearExtension(UnittestProto.optionalInt32Extension)
+ .hasExtension(UnittestProto.optionalInt32Extension));
+ assertEquals(0,
+ TestAllExtensions.newBuilder()
+ .addExtension(UnittestProto.repeatedInt32Extension, 1)
+ .clearExtension(UnittestProto.repeatedInt32Extension)
+ .getExtensionCount(UnittestProto.repeatedInt32Extension));
+ }
+
+ public void testExtensionCopy() throws Exception {
+ TestAllExtensions original = TestUtil.getAllExtensionsSet();
+ TestAllExtensions copy = TestAllExtensions.newBuilder(original).build();
+ TestUtil.assertAllExtensionsSet(copy);
+ }
+
+ public void testExtensionMergeFrom() throws Exception {
+ TestAllExtensions original =
+ TestAllExtensions.newBuilder()
+ .setExtension(UnittestProto.optionalInt32Extension, 1).build();
+ TestAllExtensions merged =
+ TestAllExtensions.newBuilder().mergeFrom(original).build();
+ assertTrue(merged.hasExtension(UnittestProto.optionalInt32Extension));
+ assertEquals(
+ 1, (int) merged.getExtension(UnittestProto.optionalInt32Extension));
+ }
+
+ // =================================================================
+ // Lite Extensions.
+
+ // We test lite extensions directly because they have a separate
+ // implementation from full extensions. In contrast, we do not test
+ // lite fields directly since they are implemented exactly the same as
+ // regular fields.
+
+ public void testLiteExtensionMessageOrBuilder() throws Exception {
+ TestAllExtensionsLite.Builder builder = TestAllExtensionsLite.newBuilder();
+ TestUtil.setAllExtensions(builder);
+ TestUtil.assertAllExtensionsSet(builder);
+
+ TestAllExtensionsLite message = builder.build();
+ TestUtil.assertAllExtensionsSet(message);
+ }
+
+ public void testLiteExtensionRepeatedSetters() throws Exception {
+ TestAllExtensionsLite.Builder builder = TestAllExtensionsLite.newBuilder();
+ TestUtil.setAllExtensions(builder);
+ TestUtil.modifyRepeatedExtensions(builder);
+ TestUtil.assertRepeatedExtensionsModified(builder);
+
+ TestAllExtensionsLite message = builder.build();
+ TestUtil.assertRepeatedExtensionsModified(message);
+ }
+
+ public void testLiteExtensionDefaults() throws Exception {
+ TestUtil.assertExtensionsClear(TestAllExtensionsLite.getDefaultInstance());
+ TestUtil.assertExtensionsClear(TestAllExtensionsLite.newBuilder().build());
+ }
+
+ public void testClearLiteExtension() throws Exception {
+ // clearExtension() is not actually used in TestUtil, so try it manually.
+ assertFalse(
+ TestAllExtensionsLite.newBuilder()
+ .setExtension(UnittestLite.optionalInt32ExtensionLite, 1)
+ .clearExtension(UnittestLite.optionalInt32ExtensionLite)
+ .hasExtension(UnittestLite.optionalInt32ExtensionLite));
+ assertEquals(0,
+ TestAllExtensionsLite.newBuilder()
+ .addExtension(UnittestLite.repeatedInt32ExtensionLite, 1)
+ .clearExtension(UnittestLite.repeatedInt32ExtensionLite)
+ .getExtensionCount(UnittestLite.repeatedInt32ExtensionLite));
+ }
+
+ public void testLiteExtensionCopy() throws Exception {
+ TestAllExtensionsLite original = TestUtil.getAllLiteExtensionsSet();
+ TestAllExtensionsLite copy =
+ TestAllExtensionsLite.newBuilder(original).build();
+ TestUtil.assertAllExtensionsSet(copy);
+ }
+
+ public void testLiteExtensionMergeFrom() throws Exception {
+ TestAllExtensionsLite original =
+ TestAllExtensionsLite.newBuilder()
+ .setExtension(UnittestLite.optionalInt32ExtensionLite, 1).build();
+ TestAllExtensionsLite merged =
+ TestAllExtensionsLite.newBuilder().mergeFrom(original).build();
+ assertTrue(merged.hasExtension(UnittestLite.optionalInt32ExtensionLite));
+ assertEquals(
+ 1, (int) merged.getExtension(UnittestLite.optionalInt32ExtensionLite));
+ }
+
+ // =================================================================
+ // multiple_files_test
+
+ // Test that custom options of an file level enum are properly initialized.
+ // This test needs to be put before any other access to MultipleFilesTestProto
+ // or messages defined in multiple_files_test.proto because the class loading
+ // order affects initialization process of custom options.
+ public void testEnumValueOptionsInMultipleFilesMode() throws Exception {
+ assertEquals(12345, EnumWithNoOuter.FOO.getValueDescriptor().getOptions()
+ .getExtension(MultipleFilesTestProto.enumValueOption).intValue());
+ }
+
+ public void testMultipleFilesOption() throws Exception {
+ // We mostly just want to check that things compile.
+ MessageWithNoOuter message =
+ MessageWithNoOuter.newBuilder()
+ .setNested(MessageWithNoOuter.NestedMessage.newBuilder().setI(1))
+ .addForeign(TestAllTypes.newBuilder().setOptionalInt32(1))
+ .setNestedEnum(MessageWithNoOuter.NestedEnum.BAZ)
+ .setForeignEnum(EnumWithNoOuter.BAR)
+ .build();
+ assertEquals(message, MessageWithNoOuter.parseFrom(message.toByteString()));
+
+ assertEquals(MultipleFilesTestProto.getDescriptor(),
+ MessageWithNoOuter.getDescriptor().getFile());
+
+ Descriptors.FieldDescriptor field =
+ MessageWithNoOuter.getDescriptor().findFieldByName("foreign_enum");
+ assertEquals(EnumWithNoOuter.BAR.getValueDescriptor(),
+ message.getField(field));
+
+ assertEquals(MultipleFilesTestProto.getDescriptor(),
+ ServiceWithNoOuter.getDescriptor().getFile());
+
+ assertFalse(
+ TestAllExtensions.getDefaultInstance().hasExtension(
+ MultipleFilesTestProto.extensionWithOuter));
+ }
+
+ public void testOptionalFieldWithRequiredSubfieldsOptimizedForSize()
+ throws Exception {
+ TestOptionalOptimizedForSize message =
+ TestOptionalOptimizedForSize.getDefaultInstance();
+ assertTrue(message.isInitialized());
+
+ message = TestOptionalOptimizedForSize.newBuilder().setO(
+ TestRequiredOptimizedForSize.newBuilder().buildPartial()
+ ).buildPartial();
+ assertFalse(message.isInitialized());
+
+ message = TestOptionalOptimizedForSize.newBuilder().setO(
+ TestRequiredOptimizedForSize.newBuilder().setX(5).buildPartial()
+ ).buildPartial();
+ assertTrue(message.isInitialized());
+ }
+
+ public void testUninitializedExtensionInOptimizedForSize()
+ throws Exception {
+ TestOptimizedForSize.Builder builder = TestOptimizedForSize.newBuilder();
+ builder.setExtension(TestOptimizedForSize.testExtension2,
+ TestRequiredOptimizedForSize.newBuilder().buildPartial());
+ assertFalse(builder.isInitialized());
+ assertFalse(builder.buildPartial().isInitialized());
+
+ builder = TestOptimizedForSize.newBuilder();
+ builder.setExtension(TestOptimizedForSize.testExtension2,
+ TestRequiredOptimizedForSize.newBuilder().setX(10).buildPartial());
+ assertTrue(builder.isInitialized());
+ assertTrue(builder.buildPartial().isInitialized());
+ }
+
+ public void testToBuilder() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TestUtil.setAllFields(builder);
+ TestAllTypes message = builder.build();
+ TestUtil.assertAllFieldsSet(message);
+ TestUtil.assertAllFieldsSet(message.toBuilder().build());
+ }
+
+ public void testFieldConstantValues() throws Exception {
+ assertEquals(TestAllTypes.NestedMessage.BB_FIELD_NUMBER, 1);
+ assertEquals(TestAllTypes.OPTIONAL_INT32_FIELD_NUMBER, 1);
+ assertEquals(TestAllTypes.OPTIONALGROUP_FIELD_NUMBER, 16);
+ assertEquals(TestAllTypes.OPTIONAL_NESTED_MESSAGE_FIELD_NUMBER, 18);
+ assertEquals(TestAllTypes.OPTIONAL_NESTED_ENUM_FIELD_NUMBER, 21);
+ assertEquals(TestAllTypes.REPEATED_INT32_FIELD_NUMBER, 31);
+ assertEquals(TestAllTypes.REPEATEDGROUP_FIELD_NUMBER, 46);
+ assertEquals(TestAllTypes.REPEATED_NESTED_MESSAGE_FIELD_NUMBER, 48);
+ assertEquals(TestAllTypes.REPEATED_NESTED_ENUM_FIELD_NUMBER, 51);
+ }
+
+ public void testExtensionConstantValues() throws Exception {
+ assertEquals(UnittestProto.TestRequired.SINGLE_FIELD_NUMBER, 1000);
+ assertEquals(UnittestProto.TestRequired.MULTI_FIELD_NUMBER, 1001);
+ assertEquals(UnittestProto.OPTIONAL_INT32_EXTENSION_FIELD_NUMBER, 1);
+ assertEquals(UnittestProto.OPTIONALGROUP_EXTENSION_FIELD_NUMBER, 16);
+ assertEquals(
+ UnittestProto.OPTIONAL_NESTED_MESSAGE_EXTENSION_FIELD_NUMBER, 18);
+ assertEquals(UnittestProto.OPTIONAL_NESTED_ENUM_EXTENSION_FIELD_NUMBER, 21);
+ assertEquals(UnittestProto.REPEATED_INT32_EXTENSION_FIELD_NUMBER, 31);
+ assertEquals(UnittestProto.REPEATEDGROUP_EXTENSION_FIELD_NUMBER, 46);
+ assertEquals(
+ UnittestProto.REPEATED_NESTED_MESSAGE_EXTENSION_FIELD_NUMBER, 48);
+ assertEquals(UnittestProto.REPEATED_NESTED_ENUM_EXTENSION_FIELD_NUMBER, 51);
+ }
+
+ public void testRecursiveMessageDefaultInstance() throws Exception {
+ UnittestProto.TestRecursiveMessage message =
+ UnittestProto.TestRecursiveMessage.getDefaultInstance();
+ assertTrue(message != null);
+ assertNotNull(message.getA());
+ assertTrue(message.getA() == message);
+ }
+
+ public void testSerialize() throws Exception {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TestUtil.setAllFields(builder);
+ TestAllTypes expected = builder.build();
+ ObjectOutputStream out = new ObjectOutputStream(baos);
+ try {
+ out.writeObject(expected);
+ } finally {
+ out.close();
+ }
+ ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+ ObjectInputStream in = new ObjectInputStream(bais);
+ TestAllTypes actual = (TestAllTypes) in.readObject();
+ assertEquals(expected, actual);
+ }
+
+ public void testSerializePartial() throws Exception {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TestAllTypes expected = builder.buildPartial();
+ ObjectOutputStream out = new ObjectOutputStream(baos);
+ try {
+ out.writeObject(expected);
+ } finally {
+ out.close();
+ }
+ ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+ ObjectInputStream in = new ObjectInputStream(bais);
+ TestAllTypes actual = (TestAllTypes) in.readObject();
+ assertEquals(expected, actual);
+ }
+
+ public void testEnumValues() {
+ assertEquals(
+ TestAllTypes.NestedEnum.BAR.getNumber(),
+ TestAllTypes.NestedEnum.BAR_VALUE);
+ assertEquals(
+ TestAllTypes.NestedEnum.BAZ.getNumber(),
+ TestAllTypes.NestedEnum.BAZ_VALUE);
+ assertEquals(
+ TestAllTypes.NestedEnum.FOO.getNumber(),
+ TestAllTypes.NestedEnum.FOO_VALUE);
+ }
+
+ public void testNonNestedExtensionInitialization() {
+ assertTrue(NonNestedExtension.nonNestedExtension
+ .getMessageDefaultInstance() instanceof MyNonNestedExtension);
+ assertEquals("nonNestedExtension",
+ NonNestedExtension.nonNestedExtension.getDescriptor().getName());
+ }
+
+ public void testNestedExtensionInitialization() {
+ assertTrue(MyNestedExtension.recursiveExtension.getMessageDefaultInstance()
+ instanceof MessageToBeExtended);
+ assertEquals("recursiveExtension",
+ MyNestedExtension.recursiveExtension.getDescriptor().getName());
+ }
+
+ public void testNonNestedExtensionLiteInitialization() {
+ assertTrue(NonNestedExtensionLite.nonNestedExtensionLite
+ .getMessageDefaultInstance() instanceof MyNonNestedExtensionLite);
+ }
+
+ public void testNestedExtensionLiteInitialization() {
+ assertTrue(MyNestedExtensionLite.recursiveExtensionLite
+ .getMessageDefaultInstance() instanceof MessageLiteToBeExtended);
+ }
+
+ public void testInvalidations() throws Exception {
+ GeneratedMessage.enableAlwaysUseFieldBuildersForTesting();
+ TestAllTypes.NestedMessage nestedMessage1 =
+ TestAllTypes.NestedMessage.newBuilder().build();
+ TestAllTypes.NestedMessage nestedMessage2 =
+ TestAllTypes.NestedMessage.newBuilder().build();
+
+ // Set all three flavors (enum, primitive, message and singular/repeated)
+ // and verify no invalidations fired
+ TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent();
+
+ TestAllTypes.Builder builder = (TestAllTypes.Builder)
+ ((GeneratedMessage) TestAllTypes.getDefaultInstance()).
+ newBuilderForType(mockParent);
+ builder.setOptionalInt32(1);
+ builder.setOptionalNestedEnum(TestAllTypes.NestedEnum.BAR);
+ builder.setOptionalNestedMessage(nestedMessage1);
+ builder.addRepeatedInt32(1);
+ builder.addRepeatedNestedEnum(TestAllTypes.NestedEnum.BAR);
+ builder.addRepeatedNestedMessage(nestedMessage1);
+ assertEquals(0, mockParent.getInvalidationCount());
+
+ // Now tell it we want changes and make sure it's only fired once
+ // And do this for each flavor
+
+ // primitive single
+ builder.buildPartial();
+ builder.setOptionalInt32(2);
+ builder.setOptionalInt32(3);
+ assertEquals(1, mockParent.getInvalidationCount());
+
+ // enum single
+ builder.buildPartial();
+ builder.setOptionalNestedEnum(TestAllTypes.NestedEnum.BAZ);
+ builder.setOptionalNestedEnum(TestAllTypes.NestedEnum.BAR);
+ assertEquals(2, mockParent.getInvalidationCount());
+
+ // message single
+ builder.buildPartial();
+ builder.setOptionalNestedMessage(nestedMessage2);
+ builder.setOptionalNestedMessage(nestedMessage1);
+ assertEquals(3, mockParent.getInvalidationCount());
+
+ // primitive repeated
+ builder.buildPartial();
+ builder.addRepeatedInt32(2);
+ builder.addRepeatedInt32(3);
+ assertEquals(4, mockParent.getInvalidationCount());
+
+ // enum repeated
+ builder.buildPartial();
+ builder.addRepeatedNestedEnum(TestAllTypes.NestedEnum.BAZ);
+ builder.addRepeatedNestedEnum(TestAllTypes.NestedEnum.BAZ);
+ assertEquals(5, mockParent.getInvalidationCount());
+
+ // message repeated
+ builder.buildPartial();
+ builder.addRepeatedNestedMessage(nestedMessage2);
+ builder.addRepeatedNestedMessage(nestedMessage1);
+ assertEquals(6, mockParent.getInvalidationCount());
+
+ }
+
+ public void testInvalidations_Extensions() throws Exception {
+ TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent();
+
+ TestAllExtensions.Builder builder = (TestAllExtensions.Builder)
+ ((GeneratedMessage) TestAllExtensions.getDefaultInstance()).
+ newBuilderForType(mockParent);
+
+ builder.addExtension(UnittestProto.repeatedInt32Extension, 1);
+ builder.setExtension(UnittestProto.repeatedInt32Extension, 0, 2);
+ builder.clearExtension(UnittestProto.repeatedInt32Extension);
+ assertEquals(0, mockParent.getInvalidationCount());
+
+ // Now tell it we want changes and make sure it's only fired once
+ builder.buildPartial();
+ builder.addExtension(UnittestProto.repeatedInt32Extension, 2);
+ builder.addExtension(UnittestProto.repeatedInt32Extension, 3);
+ assertEquals(1, mockParent.getInvalidationCount());
+
+ builder.buildPartial();
+ builder.setExtension(UnittestProto.repeatedInt32Extension, 0, 4);
+ builder.setExtension(UnittestProto.repeatedInt32Extension, 1, 5);
+ assertEquals(2, mockParent.getInvalidationCount());
+
+ builder.buildPartial();
+ builder.clearExtension(UnittestProto.repeatedInt32Extension);
+ builder.clearExtension(UnittestProto.repeatedInt32Extension);
+ assertEquals(3, mockParent.getInvalidationCount());
+ }
+
+ public void testBaseMessageOrBuilder() {
+ // Mostly just makes sure the base interface exists and has some methods.
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TestAllTypes message = builder.buildPartial();
+ TestAllTypesOrBuilder builderAsInterface = (TestAllTypesOrBuilder) builder;
+ TestAllTypesOrBuilder messageAsInterface = (TestAllTypesOrBuilder) message;
+
+ assertEquals(
+ messageAsInterface.getDefaultBool(),
+ messageAsInterface.getDefaultBool());
+ assertEquals(
+ messageAsInterface.getOptionalDouble(),
+ messageAsInterface.getOptionalDouble());
+ }
+
+ public void testMessageOrBuilderGetters() {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+
+ // single fields
+ assertSame(ForeignMessage.getDefaultInstance(),
+ builder.getOptionalForeignMessageOrBuilder());
+ ForeignMessage.Builder subBuilder =
+ builder.getOptionalForeignMessageBuilder();
+ assertSame(subBuilder, builder.getOptionalForeignMessageOrBuilder());
+
+ // repeated fields
+ ForeignMessage m0 = ForeignMessage.newBuilder().buildPartial();
+ ForeignMessage m1 = ForeignMessage.newBuilder().buildPartial();
+ ForeignMessage m2 = ForeignMessage.newBuilder().buildPartial();
+ builder.addRepeatedForeignMessage(m0);
+ builder.addRepeatedForeignMessage(m1);
+ builder.addRepeatedForeignMessage(m2);
+ assertSame(m0, builder.getRepeatedForeignMessageOrBuilder(0));
+ assertSame(m1, builder.getRepeatedForeignMessageOrBuilder(1));
+ assertSame(m2, builder.getRepeatedForeignMessageOrBuilder(2));
+ ForeignMessage.Builder b0 = builder.getRepeatedForeignMessageBuilder(0);
+ ForeignMessage.Builder b1 = builder.getRepeatedForeignMessageBuilder(1);
+ assertSame(b0, builder.getRepeatedForeignMessageOrBuilder(0));
+ assertSame(b1, builder.getRepeatedForeignMessageOrBuilder(1));
+ assertSame(m2, builder.getRepeatedForeignMessageOrBuilder(2));
+
+ List<? extends ForeignMessageOrBuilder> messageOrBuilderList =
+ builder.getRepeatedForeignMessageOrBuilderList();
+ assertSame(b0, messageOrBuilderList.get(0));
+ assertSame(b1, messageOrBuilderList.get(1));
+ assertSame(m2, messageOrBuilderList.get(2));
+ }
+
+ public void testGetFieldBuilder() {
+ Descriptor descriptor = TestAllTypes.getDescriptor();
+
+ FieldDescriptor fieldDescriptor =
+ descriptor.findFieldByName("optional_nested_message");
+ FieldDescriptor foreignFieldDescriptor =
+ descriptor.findFieldByName("optional_foreign_message");
+ FieldDescriptor importFieldDescriptor =
+ descriptor.findFieldByName("optional_import_message");
+
+ // Mutate the message with new field builder
+ // Mutate nested message
+ TestAllTypes.Builder builder1 = TestAllTypes.newBuilder();
+ Message.Builder fieldBuilder1 = builder1.newBuilderForField(fieldDescriptor)
+ .mergeFrom((Message) builder1.getField(fieldDescriptor));
+ FieldDescriptor subFieldDescriptor1 =
+ fieldBuilder1.getDescriptorForType().findFieldByName("bb");
+ fieldBuilder1.setField(subFieldDescriptor1, 1);
+ builder1.setField(fieldDescriptor, fieldBuilder1.build());
+
+ // Mutate foreign message
+ Message.Builder foreignFieldBuilder1 = builder1.newBuilderForField(
+ foreignFieldDescriptor)
+ .mergeFrom((Message) builder1.getField(foreignFieldDescriptor));
+ FieldDescriptor subForeignFieldDescriptor1 =
+ foreignFieldBuilder1.getDescriptorForType().findFieldByName("c");
+ foreignFieldBuilder1.setField(subForeignFieldDescriptor1, 2);
+ builder1.setField(foreignFieldDescriptor, foreignFieldBuilder1.build());
+
+ // Mutate import message
+ Message.Builder importFieldBuilder1 = builder1.newBuilderForField(
+ importFieldDescriptor)
+ .mergeFrom((Message) builder1.getField(importFieldDescriptor));
+ FieldDescriptor subImportFieldDescriptor1 =
+ importFieldBuilder1.getDescriptorForType().findFieldByName("d");
+ importFieldBuilder1.setField(subImportFieldDescriptor1, 3);
+ builder1.setField(importFieldDescriptor, importFieldBuilder1.build());
+
+ Message newMessage1 = builder1.build();
+
+ // Mutate the message with existing field builder
+ // Mutate nested message
+ TestAllTypes.Builder builder2 = TestAllTypes.newBuilder();
+ Message.Builder fieldBuilder2 = builder2.getFieldBuilder(fieldDescriptor);
+ FieldDescriptor subFieldDescriptor2 =
+ fieldBuilder2.getDescriptorForType().findFieldByName("bb");
+ fieldBuilder2.setField(subFieldDescriptor2, 1);
+ builder2.setField(fieldDescriptor, fieldBuilder2.build());
+
+ // Mutate foreign message
+ Message.Builder foreignFieldBuilder2 = builder2.newBuilderForField(
+ foreignFieldDescriptor)
+ .mergeFrom((Message) builder2.getField(foreignFieldDescriptor));
+ FieldDescriptor subForeignFieldDescriptor2 =
+ foreignFieldBuilder2.getDescriptorForType().findFieldByName("c");
+ foreignFieldBuilder2.setField(subForeignFieldDescriptor2, 2);
+ builder2.setField(foreignFieldDescriptor, foreignFieldBuilder2.build());
+
+ // Mutate import message
+ Message.Builder importFieldBuilder2 = builder2.newBuilderForField(
+ importFieldDescriptor)
+ .mergeFrom((Message) builder2.getField(importFieldDescriptor));
+ FieldDescriptor subImportFieldDescriptor2 =
+ importFieldBuilder2.getDescriptorForType().findFieldByName("d");
+ importFieldBuilder2.setField(subImportFieldDescriptor2, 3);
+ builder2.setField(importFieldDescriptor, importFieldBuilder2.build());
+
+ Message newMessage2 = builder2.build();
+
+ // These two messages should be equal.
+ assertEquals(newMessage1, newMessage2);
+ }
+
+ public void testGetFieldBuilderWithInitializedValue() {
+ Descriptor descriptor = TestAllTypes.getDescriptor();
+ FieldDescriptor fieldDescriptor =
+ descriptor.findFieldByName("optional_nested_message");
+
+ // Before setting field, builder is initialized by default value.
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ NestedMessage.Builder fieldBuilder =
+ (NestedMessage.Builder) builder.getFieldBuilder(fieldDescriptor);
+ assertEquals(0, fieldBuilder.getBb());
+
+ // Setting field value with new field builder instance.
+ builder = TestAllTypes.newBuilder();
+ NestedMessage.Builder newFieldBuilder =
+ builder.getOptionalNestedMessageBuilder();
+ newFieldBuilder.setBb(2);
+ // Then get the field builder instance by getFieldBuilder().
+ fieldBuilder =
+ (NestedMessage.Builder) builder.getFieldBuilder(fieldDescriptor);
+ // It should contain new value.
+ assertEquals(2, fieldBuilder.getBb());
+ // These two builder should be equal.
+ assertSame(fieldBuilder, newFieldBuilder);
+ }
+
+ public void testGetFieldBuilderNotSupportedException() {
+ Descriptor descriptor = TestAllTypes.getDescriptor();
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ try {
+ builder.getFieldBuilder(descriptor.findFieldByName("optional_int32"));
+ fail("Exception was not thrown");
+ } catch (UnsupportedOperationException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.getFieldBuilder(
+ descriptor.findFieldByName("optional_nested_enum"));
+ fail("Exception was not thrown");
+ } catch (UnsupportedOperationException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.getFieldBuilder(descriptor.findFieldByName("repeated_int32"));
+ fail("Exception was not thrown");
+ } catch (UnsupportedOperationException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.getFieldBuilder(
+ descriptor.findFieldByName("repeated_nested_enum"));
+ fail("Exception was not thrown");
+ } catch (UnsupportedOperationException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.getFieldBuilder(
+ descriptor.findFieldByName("repeated_nested_message"));
+ fail("Exception was not thrown");
+ } catch (UnsupportedOperationException e) {
+ // We expect this exception.
+ }
+ }
+
+ // Test that when the default outer class name conflicts with another type
+ // defined in the proto the compiler will append a suffix to avoid the
+ // conflict.
+ public void testConflictingOuterClassName() {
+ // We just need to make sure we can refer to the outer class with the
+ // expected name. There is nothing else to test.
+ OuterClassNameTestOuterClass.OuterClassNameTest message =
+ OuterClassNameTestOuterClass.OuterClassNameTest.newBuilder().build();
+ assertTrue(message.getDescriptorForType() ==
+ OuterClassNameTestOuterClass.OuterClassNameTest.getDescriptor());
+
+ OuterClassNameTest2OuterClass.TestMessage2.NestedMessage.OuterClassNameTest2
+ message2 = OuterClassNameTest2OuterClass.TestMessage2.NestedMessage
+ .OuterClassNameTest2.newBuilder().build();
+ assertEquals(0, message2.getSerializedSize());
+
+ OuterClassNameTest3OuterClass.TestMessage3.NestedMessage.OuterClassNameTest3
+ enumValue = OuterClassNameTest3OuterClass.TestMessage3.NestedMessage
+ .OuterClassNameTest3.DUMMY_VALUE;
+ assertEquals(1, enumValue.getNumber());
+ }
+
+ // =================================================================
+ // oneof generated code test
+ public void testOneofEnumCase() throws Exception {
+ TestOneof2 message = TestOneof2.newBuilder()
+ .setFooInt(123).setFooString("foo").setFooCord("bar").build();
+ TestUtil.assertAtMostOneFieldSetOneof(message);
+ }
+
+ public void testClearOneof() throws Exception {
+ TestOneof2.Builder builder = TestOneof2.newBuilder().setFooInt(123);
+ assertEquals(TestOneof2.FooCase.FOO_INT, builder.getFooCase());
+ builder.clearFoo();
+ assertEquals(TestOneof2.FooCase.FOO_NOT_SET, builder.getFooCase());
+ }
+
+ public void testSetOneofClearsOthers() throws Exception {
+ TestOneof2.Builder builder = TestOneof2.newBuilder();
+ TestOneof2 message =
+ builder.setFooInt(123).setFooString("foo").buildPartial();
+ assertTrue(message.hasFooString());
+ TestUtil.assertAtMostOneFieldSetOneof(message);
+
+ message = builder.setFooCord("bar").buildPartial();
+ assertTrue(message.hasFooCord());
+ TestUtil.assertAtMostOneFieldSetOneof(message);
+
+ message = builder.setFooStringPiece("baz").buildPartial();
+ assertTrue(message.hasFooStringPiece());
+ TestUtil.assertAtMostOneFieldSetOneof(message);
+
+ message = builder.setFooBytes(TestUtil.toBytes("qux")).buildPartial();
+ assertTrue(message.hasFooBytes());
+ TestUtil.assertAtMostOneFieldSetOneof(message);
+
+ message = builder.setFooEnum(TestOneof2.NestedEnum.FOO).buildPartial();
+ assertTrue(message.hasFooEnum());
+ TestUtil.assertAtMostOneFieldSetOneof(message);
+
+ message = builder.setFooMessage(
+ TestOneof2.NestedMessage.newBuilder().setQuxInt(234).build()).buildPartial();
+ assertTrue(message.hasFooMessage());
+ TestUtil.assertAtMostOneFieldSetOneof(message);
+
+ message = builder.setFooInt(123).buildPartial();
+ assertTrue(message.hasFooInt());
+ TestUtil.assertAtMostOneFieldSetOneof(message);
+ }
+
+ public void testOneofTypes() throws Exception {
+ // Primitive
+ {
+ TestOneof2.Builder builder = TestOneof2.newBuilder();
+ assertEquals(builder.getFooInt(), 0);
+ assertFalse(builder.hasFooInt());
+ assertTrue(builder.setFooInt(123).hasFooInt());
+ assertEquals(builder.getFooInt(), 123);
+ TestOneof2 message = builder.buildPartial();
+ assertTrue(message.hasFooInt());
+ assertEquals(message.getFooInt(), 123);
+
+ assertFalse(builder.clearFooInt().hasFooInt());
+ TestOneof2 message2 = builder.build();
+ assertFalse(message2.hasFooInt());
+ assertEquals(message2.getFooInt(), 0);
+ }
+
+ // Enum
+ {
+ TestOneof2.Builder builder = TestOneof2.newBuilder();
+ assertEquals(builder.getFooEnum(), TestOneof2.NestedEnum.FOO);
+ assertTrue(builder.setFooEnum(TestOneof2.NestedEnum.BAR).hasFooEnum());
+ assertEquals(builder.getFooEnum(), TestOneof2.NestedEnum.BAR);
+ TestOneof2 message = builder.buildPartial();
+ assertTrue(message.hasFooEnum());
+ assertEquals(message.getFooEnum(), TestOneof2.NestedEnum.BAR);
+
+ assertFalse(builder.clearFooEnum().hasFooEnum());
+ TestOneof2 message2 = builder.build();
+ assertFalse(message2.hasFooEnum());
+ assertEquals(message2.getFooEnum(), TestOneof2.NestedEnum.FOO);
+ }
+
+ // String
+ {
+ TestOneof2.Builder builder = TestOneof2.newBuilder();
+ assertEquals(builder.getFooString(), "");
+ builder.setFooString("foo");
+ assertTrue(builder.hasFooString());
+ assertEquals(builder.getFooString(), "foo");
+ TestOneof2 message = builder.buildPartial();
+ assertTrue(message.hasFooString());
+ assertEquals(message.getFooString(), "foo");
+ assertEquals(message.getFooStringBytes(), TestUtil.toBytes("foo"));
+
+ assertFalse(builder.clearFooString().hasFooString());
+ TestOneof2 message2 = builder.buildPartial();
+ assertFalse(message2.hasFooString());
+ assertEquals(message2.getFooString(), "");
+ assertEquals(message2.getFooStringBytes(), TestUtil.toBytes(""));
+
+ // Get method should not change the oneof value.
+ builder.setFooInt(123);
+ assertEquals(builder.getFooString(), "");
+ assertEquals(builder.getFooStringBytes(), TestUtil.toBytes(""));
+ assertEquals(123, builder.getFooInt());
+
+ message = builder.build();
+ assertEquals(message.getFooString(), "");
+ assertEquals(message.getFooStringBytes(), TestUtil.toBytes(""));
+ assertEquals(123, message.getFooInt());
+ }
+
+ // Cord
+ {
+ TestOneof2.Builder builder = TestOneof2.newBuilder();
+ assertEquals(builder.getFooCord(), "");
+ builder.setFooCord("foo");
+ assertTrue(builder.hasFooCord());
+ assertEquals(builder.getFooCord(), "foo");
+ TestOneof2 message = builder.buildPartial();
+ assertTrue(message.hasFooCord());
+ assertEquals(message.getFooCord(), "foo");
+ assertEquals(message.getFooCordBytes(), TestUtil.toBytes("foo"));
+
+ assertFalse(builder.clearFooCord().hasFooCord());
+ TestOneof2 message2 = builder.build();
+ assertFalse(message2.hasFooCord());
+ assertEquals(message2.getFooCord(), "");
+ assertEquals(message2.getFooCordBytes(), TestUtil.toBytes(""));
+ }
+
+ // StringPiece
+ {
+ TestOneof2.Builder builder = TestOneof2.newBuilder();
+ assertEquals(builder.getFooStringPiece(), "");
+ builder.setFooStringPiece("foo");
+ assertTrue(builder.hasFooStringPiece());
+ assertEquals(builder.getFooStringPiece(), "foo");
+ TestOneof2 message = builder.buildPartial();
+ assertTrue(message.hasFooStringPiece());
+ assertEquals(message.getFooStringPiece(), "foo");
+ assertEquals(message.getFooStringPieceBytes(), TestUtil.toBytes("foo"));
+
+ assertFalse(builder.clearFooStringPiece().hasFooStringPiece());
+ TestOneof2 message2 = builder.build();
+ assertFalse(message2.hasFooStringPiece());
+ assertEquals(message2.getFooStringPiece(), "");
+ assertEquals(message2.getFooStringPieceBytes(), TestUtil.toBytes(""));
+ }
+
+ // Message
+ {
+ // set
+ TestOneof2.Builder builder = TestOneof2.newBuilder();
+ assertEquals(builder.getFooMessage().getQuxInt(), 0);
+ builder.setFooMessage(
+ TestOneof2.NestedMessage.newBuilder().setQuxInt(234).build());
+ assertTrue(builder.hasFooMessage());
+ assertEquals(builder.getFooMessage().getQuxInt(), 234);
+ TestOneof2 message = builder.buildPartial();
+ assertTrue(message.hasFooMessage());
+ assertEquals(message.getFooMessage().getQuxInt(), 234);
+
+ // clear
+ assertFalse(builder.clearFooMessage().hasFooString());
+ message = builder.build();
+ assertFalse(message.hasFooMessage());
+ assertEquals(message.getFooMessage().getQuxInt(), 0);
+
+ // nested builder
+ builder = TestOneof2.newBuilder();
+ assertSame(builder.getFooMessageOrBuilder(),
+ TestOneof2.NestedMessage.getDefaultInstance());
+ assertFalse(builder.hasFooMessage());
+ builder.getFooMessageBuilder().setQuxInt(123);
+ assertTrue(builder.hasFooMessage());
+ assertEquals(builder.getFooMessage().getQuxInt(), 123);
+ message = builder.build();
+ assertTrue(message.hasFooMessage());
+ assertEquals(message.getFooMessage().getQuxInt(), 123);
+ }
+
+ // LazyMessage is tested in LazyMessageLiteTest.java
+ }
+
+ public void testOneofMerge() throws Exception {
+ // Primitive Type
+ {
+ TestOneof2.Builder builder = TestOneof2.newBuilder();
+ TestOneof2 message = builder.setFooInt(123).build();
+ TestOneof2 message2 = TestOneof2.newBuilder().mergeFrom(message).build();
+ assertTrue(message2.hasFooInt());
+ assertEquals(message2.getFooInt(), 123);
+ }
+
+ // String
+ {
+ TestOneof2.Builder builder = TestOneof2.newBuilder();
+ TestOneof2 message = builder.setFooString("foo").build();
+ TestOneof2 message2 = TestOneof2.newBuilder().mergeFrom(message).build();
+ assertTrue(message2.hasFooString());
+ assertEquals(message2.getFooString(), "foo");
+ }
+
+ // Enum
+ {
+ TestOneof2.Builder builder = TestOneof2.newBuilder();
+ TestOneof2 message = builder.setFooEnum(TestOneof2.NestedEnum.BAR).build();
+ TestOneof2 message2 = TestOneof2.newBuilder().mergeFrom(message).build();
+ assertTrue(message2.hasFooEnum());
+ assertEquals(message2.getFooEnum(), TestOneof2.NestedEnum.BAR);
+ }
+
+ // Message
+ {
+ TestOneof2.Builder builder = TestOneof2.newBuilder();
+ TestOneof2 message = builder.setFooMessage(
+ TestOneof2.NestedMessage.newBuilder().setQuxInt(234).build()).build();
+ TestOneof2 message2 = TestOneof2.newBuilder().mergeFrom(message).build();
+ assertTrue(message2.hasFooMessage());
+ assertEquals(message2.getFooMessage().getQuxInt(), 234);
+ }
+ }
+
+ public void testOneofSerialization() throws Exception {
+ // Primitive Type
+ {
+ TestOneof2.Builder builder = TestOneof2.newBuilder();
+ TestOneof2 message = builder.setFooInt(123).build();
+ ByteString serialized = message.toByteString();
+ TestOneof2 message2 = TestOneof2.parseFrom(serialized);
+ assertTrue(message2.hasFooInt());
+ assertEquals(message2.getFooInt(), 123);
+ }
+
+ // String
+ {
+ TestOneof2.Builder builder = TestOneof2.newBuilder();
+ TestOneof2 message = builder.setFooString("foo").build();
+ ByteString serialized = message.toByteString();
+ TestOneof2 message2 = TestOneof2.parseFrom(serialized);
+ assertTrue(message2.hasFooString());
+ assertEquals(message2.getFooString(), "foo");
+ }
+
+ // Enum
+ {
+ TestOneof2.Builder builder = TestOneof2.newBuilder();
+ TestOneof2 message = builder.setFooEnum(TestOneof2.NestedEnum.BAR).build();
+ ByteString serialized = message.toByteString();
+ TestOneof2 message2 = TestOneof2.parseFrom(serialized);
+ assertTrue(message2.hasFooEnum());
+ assertEquals(message2.getFooEnum(), TestOneof2.NestedEnum.BAR);
+ }
+
+ // Message
+ {
+ TestOneof2.Builder builder = TestOneof2.newBuilder();
+ TestOneof2 message = builder.setFooMessage(
+ TestOneof2.NestedMessage.newBuilder().setQuxInt(234).build()).build();
+ ByteString serialized = message.toByteString();
+ TestOneof2 message2 = TestOneof2.parseFrom(serialized);
+ assertTrue(message2.hasFooMessage());
+ assertEquals(message2.getFooMessage().getQuxInt(), 234);
+ }
+ }
+
+ public void testOneofNestedBuilderOnChangePropagation() {
+ NestedTestAllTypes.Builder parentBuilder = NestedTestAllTypes.newBuilder();
+ TestAllTypes.Builder builder = parentBuilder.getPayloadBuilder();
+ builder.getOneofNestedMessageBuilder();
+ assertTrue(builder.hasOneofNestedMessage());
+ assertTrue(parentBuilder.hasPayload());
+ NestedTestAllTypes message = parentBuilder.build();
+ assertTrue(message.hasPayload());
+ assertTrue(message.getPayload().hasOneofNestedMessage());
+ }
+
+ public void testGetRepeatedFieldBuilder() {
+ Descriptor descriptor = TestAllTypes.getDescriptor();
+
+ FieldDescriptor fieldDescriptor =
+ descriptor.findFieldByName("repeated_nested_message");
+ FieldDescriptor foreignFieldDescriptor =
+ descriptor.findFieldByName("repeated_foreign_message");
+ FieldDescriptor importFieldDescriptor =
+ descriptor.findFieldByName("repeated_import_message");
+
+ // Mutate the message with new field builder
+ // Mutate nested message
+ TestAllTypes.Builder builder1 = TestAllTypes.newBuilder();
+ Message.Builder fieldBuilder1 = builder1.newBuilderForField(
+ fieldDescriptor);
+ FieldDescriptor subFieldDescriptor1 =
+ fieldBuilder1.getDescriptorForType().findFieldByName("bb");
+ fieldBuilder1.setField(subFieldDescriptor1, 1);
+ builder1.addRepeatedField(fieldDescriptor, fieldBuilder1.build());
+
+ // Mutate foreign message
+ Message.Builder foreignFieldBuilder1 = builder1.newBuilderForField(
+ foreignFieldDescriptor);
+ FieldDescriptor subForeignFieldDescriptor1 =
+ foreignFieldBuilder1.getDescriptorForType().findFieldByName("c");
+ foreignFieldBuilder1.setField(subForeignFieldDescriptor1, 2);
+ builder1.addRepeatedField(foreignFieldDescriptor,
+ foreignFieldBuilder1.build());
+
+ // Mutate import message
+ Message.Builder importFieldBuilder1 = builder1.newBuilderForField(
+ importFieldDescriptor);
+ FieldDescriptor subImportFieldDescriptor1 =
+ importFieldBuilder1.getDescriptorForType().findFieldByName("d");
+ importFieldBuilder1.setField(subImportFieldDescriptor1, 3);
+ builder1.addRepeatedField(importFieldDescriptor,
+ importFieldBuilder1.build());
+
+ Message newMessage1 = builder1.build();
+
+ // Mutate the message with existing field builder
+ // Mutate nested message
+ TestAllTypes.Builder builder2 = TestAllTypes.newBuilder();
+ builder2.addRepeatedNestedMessageBuilder();
+ Message.Builder fieldBuilder2 = builder2.getRepeatedFieldBuilder(
+ fieldDescriptor, 0);
+ FieldDescriptor subFieldDescriptor2 =
+ fieldBuilder2.getDescriptorForType().findFieldByName("bb");
+ fieldBuilder2.setField(subFieldDescriptor2, 1);
+
+ // Mutate foreign message
+ Message.Builder foreignFieldBuilder2 = builder2.newBuilderForField(
+ foreignFieldDescriptor);
+ FieldDescriptor subForeignFieldDescriptor2 =
+ foreignFieldBuilder2.getDescriptorForType().findFieldByName("c");
+ foreignFieldBuilder2.setField(subForeignFieldDescriptor2, 2);
+ builder2.addRepeatedField(foreignFieldDescriptor,
+ foreignFieldBuilder2.build());
+
+ // Mutate import message
+ Message.Builder importFieldBuilder2 = builder2.newBuilderForField(
+ importFieldDescriptor);
+ FieldDescriptor subImportFieldDescriptor2 =
+ importFieldBuilder2.getDescriptorForType().findFieldByName("d");
+ importFieldBuilder2.setField(subImportFieldDescriptor2, 3);
+ builder2.addRepeatedField(importFieldDescriptor,
+ importFieldBuilder2.build());
+
+ Message newMessage2 = builder2.build();
+
+ // These two messages should be equal.
+ assertEquals(newMessage1, newMessage2);
+ }
+
+ public void testGetRepeatedFieldBuilderWithInitializedValue() {
+ Descriptor descriptor = TestAllTypes.getDescriptor();
+ FieldDescriptor fieldDescriptor =
+ descriptor.findFieldByName("repeated_nested_message");
+
+ // Before setting field, builder is initialized by default value.
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ builder.addRepeatedNestedMessageBuilder();
+ NestedMessage.Builder fieldBuilder =
+ (NestedMessage.Builder) builder.getRepeatedFieldBuilder(fieldDescriptor, 0);
+ assertEquals(0, fieldBuilder.getBb());
+
+ // Setting field value with new field builder instance.
+ builder = TestAllTypes.newBuilder();
+ NestedMessage.Builder newFieldBuilder =
+ builder.addRepeatedNestedMessageBuilder();
+ newFieldBuilder.setBb(2);
+ // Then get the field builder instance by getRepeatedFieldBuilder().
+ fieldBuilder =
+ (NestedMessage.Builder) builder.getRepeatedFieldBuilder(fieldDescriptor, 0);
+ // It should contain new value.
+ assertEquals(2, fieldBuilder.getBb());
+ // These two builder should be equal.
+ assertSame(fieldBuilder, newFieldBuilder);
+ }
+
+ public void testGetRepeatedFieldBuilderNotSupportedException() {
+ Descriptor descriptor = TestAllTypes.getDescriptor();
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ try {
+ builder.getRepeatedFieldBuilder(descriptor.findFieldByName("repeated_int32"), 0);
+ fail("Exception was not thrown");
+ } catch (UnsupportedOperationException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.getRepeatedFieldBuilder(
+ descriptor.findFieldByName("repeated_nested_enum"), 0);
+ fail("Exception was not thrown");
+ } catch (UnsupportedOperationException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.getRepeatedFieldBuilder(descriptor.findFieldByName("optional_int32"), 0);
+ fail("Exception was not thrown");
+ } catch (UnsupportedOperationException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.getRepeatedFieldBuilder(
+ descriptor.findFieldByName("optional_nested_enum"), 0);
+ fail("Exception was not thrown");
+ } catch (UnsupportedOperationException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.getRepeatedFieldBuilder(
+ descriptor.findFieldByName("optional_nested_message"), 0);
+ fail("Exception was not thrown");
+ } catch (UnsupportedOperationException e) {
+ // We expect this exception.
+ }
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/IntArrayListTest.java b/java/core/src/test/java/com/google/protobuf/IntArrayListTest.java
new file mode 100644
index 00000000..3733eb30
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/IntArrayListTest.java
@@ -0,0 +1,473 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// 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 static java.util.Arrays.asList;
+
+import junit.framework.TestCase;
+
+import java.util.Collections;
+import java.util.ConcurrentModificationException;
+import java.util.Iterator;
+
+/**
+ * Tests for {@link IntArrayList}.
+ *
+ * @author dweis@google.com (Daniel Weis)
+ */
+public class IntArrayListTest extends TestCase {
+
+ private static final IntArrayList UNARY_LIST = newImmutableIntArrayList(1);
+ private static final IntArrayList TERTIARY_LIST =
+ newImmutableIntArrayList(1, 2, 3);
+
+ private IntArrayList list;
+
+ @Override
+ protected void setUp() throws Exception {
+ list = new IntArrayList();
+ }
+
+ public void testEmptyListReturnsSameInstance() {
+ assertSame(IntArrayList.emptyList(), IntArrayList.emptyList());
+ }
+
+ public void testEmptyListIsImmutable() {
+ assertImmutable(IntArrayList.emptyList());
+ }
+
+ public void testMakeImmutable() {
+ list.addInt(2);
+ list.addInt(4);
+ list.addInt(6);
+ list.addInt(8);
+ list.makeImmutable();
+ assertImmutable(list);
+ }
+
+ public void testCopyConstructor() {
+ IntArrayList copy = new IntArrayList(TERTIARY_LIST);
+ assertEquals(TERTIARY_LIST, copy);
+
+ copy = new IntArrayList(IntArrayList.emptyList());
+ assertEquals(IntArrayList.emptyList(), copy);
+
+ copy = new IntArrayList(asList(1, 2, 3));
+ assertEquals(asList(1, 2, 3), copy);
+
+ copy = new IntArrayList(Collections.<Integer>emptyList());
+ assertEquals(IntArrayList.emptyList(), copy);
+ }
+
+ public void testModificationWithIteration() {
+ list.addAll(asList(1, 2, 3, 4));
+ Iterator<Integer> iterator = list.iterator();
+ assertEquals(4, list.size());
+ assertEquals(1, (int) list.get(0));
+ assertEquals(1, (int) iterator.next());
+ list.set(0, 1);
+ assertEquals(2, (int) iterator.next());
+
+ list.remove(0);
+ try {
+ iterator.next();
+ fail();
+ } catch (ConcurrentModificationException e) {
+ // expected
+ }
+
+ iterator = list.iterator();
+ list.add(0, 0);
+ try {
+ iterator.next();
+ fail();
+ } catch (ConcurrentModificationException e) {
+ // expected
+ }
+ }
+
+ public void testGet() {
+ assertEquals(1, (int) TERTIARY_LIST.get(0));
+ assertEquals(2, (int) TERTIARY_LIST.get(1));
+ assertEquals(3, (int) TERTIARY_LIST.get(2));
+
+ try {
+ TERTIARY_LIST.get(-1);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ TERTIARY_LIST.get(3);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testGetInt() {
+ assertEquals(1, TERTIARY_LIST.getInt(0));
+ assertEquals(2, TERTIARY_LIST.getInt(1));
+ assertEquals(3, TERTIARY_LIST.getInt(2));
+
+ try {
+ TERTIARY_LIST.get(-1);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ TERTIARY_LIST.get(3);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testSize() {
+ assertEquals(0, IntArrayList.emptyList().size());
+ assertEquals(1, UNARY_LIST.size());
+ assertEquals(3, TERTIARY_LIST.size());
+
+ list.addInt(2);
+ list.addInt(4);
+ list.addInt(6);
+ list.addInt(8);
+ assertEquals(4, list.size());
+
+ list.remove(0);
+ assertEquals(3, list.size());
+
+ list.add(16);
+ assertEquals(4, list.size());
+ }
+
+ public void testSet() {
+ list.addInt(2);
+ list.addInt(4);
+
+ assertEquals(2, (int) list.set(0, 0));
+ assertEquals(0, list.getInt(0));
+
+ assertEquals(4, (int) list.set(1, 0));
+ assertEquals(0, list.getInt(1));
+
+ try {
+ list.set(-1, 0);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ list.set(2, 0);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testSetInt() {
+ list.addInt(2);
+ list.addInt(4);
+
+ assertEquals(2, list.setInt(0, 0));
+ assertEquals(0, list.getInt(0));
+
+ assertEquals(4, list.setInt(1, 0));
+ assertEquals(0, list.getInt(1));
+
+ try {
+ list.setInt(-1, 0);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ list.setInt(2, 0);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testAdd() {
+ assertEquals(0, list.size());
+
+ assertTrue(list.add(2));
+ assertEquals(asList(2), list);
+
+ assertTrue(list.add(3));
+ list.add(0, 4);
+ assertEquals(asList(4, 2, 3), list);
+
+ list.add(0, 1);
+ list.add(0, 0);
+ // Force a resize by getting up to 11 elements.
+ for (int i = 0; i < 6; i++) {
+ list.add(5 + i);
+ }
+ assertEquals(asList(0, 1, 4, 2, 3, 5, 6, 7, 8, 9, 10), list);
+
+ try {
+ list.add(-1, 5);
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ list.add(4, 5);
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testAddInt() {
+ assertEquals(0, list.size());
+
+ list.addInt(2);
+ assertEquals(asList(2), list);
+
+ list.addInt(3);
+ assertEquals(asList(2, 3), list);
+ }
+
+ public void testAddAll() {
+ assertEquals(0, list.size());
+
+ assertTrue(list.addAll(Collections.singleton(1)));
+ assertEquals(1, list.size());
+ assertEquals(1, (int) list.get(0));
+ assertEquals(1, list.getInt(0));
+
+ assertTrue(list.addAll(asList(2, 3, 4, 5, 6)));
+ assertEquals(asList(1, 2, 3, 4, 5, 6), list);
+
+ assertTrue(list.addAll(TERTIARY_LIST));
+ assertEquals(asList(1, 2, 3, 4, 5, 6, 1, 2, 3), list);
+
+ assertFalse(list.addAll(Collections.<Integer>emptyList()));
+ assertFalse(list.addAll(IntArrayList.emptyList()));
+ }
+
+ public void testRemove() {
+ list.addAll(TERTIARY_LIST);
+ assertEquals(1, (int) list.remove(0));
+ assertEquals(asList(2, 3), list);
+
+ assertTrue(list.remove(Integer.valueOf(3)));
+ assertEquals(asList(2), list);
+
+ assertFalse(list.remove(Integer.valueOf(3)));
+ assertEquals(asList(2), list);
+
+ assertEquals(2, (int) list.remove(0));
+ assertEquals(asList(), list);
+
+ try {
+ list.remove(-1);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ list.remove(0);
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ private void assertImmutable(IntArrayList list) {
+ if (list.contains(1)) {
+ throw new RuntimeException("Cannot test the immutability of lists that contain 1.");
+ }
+
+ try {
+ list.add(1);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.add(0, 1);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(Collections.<Integer>emptyList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(Collections.singletonList(1));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(new IntArrayList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(UNARY_LIST);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(0, Collections.singleton(1));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(0, UNARY_LIST);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(0, Collections.<Integer>emptyList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addInt(0);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.clear();
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.remove(1);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.remove(new Object());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.removeAll(Collections.<Integer>emptyList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.removeAll(Collections.singleton(1));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.removeAll(UNARY_LIST);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.retainAll(Collections.<Integer>emptyList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.retainAll(Collections.singleton(1));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.retainAll(UNARY_LIST);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.set(0, 0);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.setInt(0, 0);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ }
+
+ private static IntArrayList newImmutableIntArrayList(int... elements) {
+ IntArrayList list = new IntArrayList();
+ for (int element : elements) {
+ list.addInt(element);
+ }
+ list.makeImmutable();
+ return list;
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/IsValidUtf8Test.java b/java/core/src/test/java/com/google/protobuf/IsValidUtf8Test.java
new file mode 100644
index 00000000..8751baae
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/IsValidUtf8Test.java
@@ -0,0 +1,183 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// 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 com.google.protobuf.IsValidUtf8TestUtil.Shard;
+
+import junit.framework.TestCase;
+
+import java.io.UnsupportedEncodingException;
+
+/**
+ * Tests cases for {@link ByteString#isValidUtf8()}. This includes three
+ * brute force tests that actually test every permutation of one byte, two byte,
+ * and three byte sequences to ensure that the method produces the right result
+ * for every possible byte encoding where "right" means it's consistent with
+ * java's UTF-8 string encoding/decoding such that the method returns true for
+ * any sequence that will round trip when converted to a String and then back to
+ * bytes and will return false for any sequence that will not round trip.
+ * See also {@link IsValidUtf8FourByteTest}. It also includes some
+ * other more targeted tests.
+ *
+ * @author jonp@google.com (Jon Perlow)
+ * @author martinrb@google.com (Martin Buchholz)
+ */
+public class IsValidUtf8Test extends TestCase {
+
+ /**
+ * Tests that round tripping of all two byte permutations work.
+ */
+ public void testIsValidUtf8_1Byte() throws UnsupportedEncodingException {
+ IsValidUtf8TestUtil.testBytes(1,
+ IsValidUtf8TestUtil.EXPECTED_ONE_BYTE_ROUNDTRIPPABLE_COUNT);
+ }
+
+ /**
+ * Tests that round tripping of all two byte permutations work.
+ */
+ public void testIsValidUtf8_2Bytes() throws UnsupportedEncodingException {
+ IsValidUtf8TestUtil.testBytes(2,
+ IsValidUtf8TestUtil.EXPECTED_TWO_BYTE_ROUNDTRIPPABLE_COUNT);
+ }
+
+ /**
+ * Tests that round tripping of all three byte permutations work.
+ */
+ public void testIsValidUtf8_3Bytes() throws UnsupportedEncodingException {
+ // Travis' OOM killer doesn't like this test
+ if (System.getenv("TRAVIS") == null) {
+ IsValidUtf8TestUtil.testBytes(3,
+ IsValidUtf8TestUtil.EXPECTED_THREE_BYTE_ROUNDTRIPPABLE_COUNT);
+ }
+ }
+
+ /**
+ * Tests that round tripping of a sample of four byte permutations work.
+ * All permutations are prohibitively expensive to test for automated runs;
+ * {@link IsValidUtf8FourByteTest} is used for full coverage. This method
+ * tests specific four-byte cases.
+ */
+ public void testIsValidUtf8_4BytesSamples()
+ throws UnsupportedEncodingException {
+ // Valid 4 byte.
+ assertValidUtf8(0xF0, 0xA4, 0xAD, 0xA2);
+
+ // Bad trailing bytes
+ assertInvalidUtf8(0xF0, 0xA4, 0xAD, 0x7F);
+ assertInvalidUtf8(0xF0, 0xA4, 0xAD, 0xC0);
+
+ // Special cases for byte2
+ assertInvalidUtf8(0xF0, 0x8F, 0xAD, 0xA2);
+ assertInvalidUtf8(0xF4, 0x90, 0xAD, 0xA2);
+ }
+
+ /**
+ * Tests some hard-coded test cases.
+ */
+ public void testSomeSequences() {
+ // Empty
+ assertTrue(asBytes("").isValidUtf8());
+
+ // One-byte characters, including control characters
+ assertTrue(asBytes("\u0000abc\u007f").isValidUtf8());
+
+ // Two-byte characters
+ assertTrue(asBytes("\u00a2\u00a2").isValidUtf8());
+
+ // Three-byte characters
+ assertTrue(asBytes("\u020ac\u020ac").isValidUtf8());
+
+ // Four-byte characters
+ assertTrue(asBytes("\u024B62\u024B62").isValidUtf8());
+
+ // Mixed string
+ assertTrue(
+ asBytes("a\u020ac\u00a2b\\u024B62u020acc\u00a2de\u024B62")
+ .isValidUtf8());
+
+ // Not a valid string
+ assertInvalidUtf8(-1, 0, -1, 0);
+ }
+
+ private byte[] toByteArray(int... bytes) {
+ byte[] realBytes = new byte[bytes.length];
+ for (int i = 0; i < bytes.length; i++) {
+ realBytes[i] = (byte) bytes[i];
+ }
+ return realBytes;
+ }
+
+ private ByteString toByteString(int... bytes) {
+ return ByteString.copyFrom(toByteArray(bytes));
+ }
+
+ private void assertValidUtf8(int[] bytes, boolean not) {
+ byte[] realBytes = toByteArray(bytes);
+ assertTrue(not ^ Utf8.isValidUtf8(realBytes));
+ assertTrue(not ^ Utf8.isValidUtf8(realBytes, 0, bytes.length));
+ ByteString lit = ByteString.copyFrom(realBytes);
+ ByteString sub = lit.substring(0, bytes.length);
+ assertTrue(not ^ lit.isValidUtf8());
+ assertTrue(not ^ sub.isValidUtf8());
+ ByteString[] ropes = {
+ RopeByteString.newInstanceForTest(ByteString.EMPTY, lit),
+ RopeByteString.newInstanceForTest(ByteString.EMPTY, sub),
+ RopeByteString.newInstanceForTest(lit, ByteString.EMPTY),
+ RopeByteString.newInstanceForTest(sub, ByteString.EMPTY),
+ RopeByteString.newInstanceForTest(sub, lit)
+ };
+ for (ByteString rope : ropes) {
+ assertTrue(not ^ rope.isValidUtf8());
+ }
+ }
+
+ private void assertValidUtf8(int... bytes) {
+ assertValidUtf8(bytes, false);
+ }
+
+ private void assertInvalidUtf8(int... bytes) {
+ assertValidUtf8(bytes, true);
+ }
+
+ private static ByteString asBytes(String s) {
+ return ByteString.copyFromUtf8(s);
+ }
+
+ public void testShardsHaveExpectedRoundTrippables() {
+ // A sanity check.
+ int actual = 0;
+ for (Shard shard : IsValidUtf8TestUtil.FOUR_BYTE_SHARDS) {
+ actual += shard.expected;
+ }
+ assertEquals(IsValidUtf8TestUtil.EXPECTED_FOUR_BYTE_ROUNDTRIPPABLE_COUNT,
+ actual);
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/IsValidUtf8TestUtil.java b/java/core/src/test/java/com/google/protobuf/IsValidUtf8TestUtil.java
new file mode 100644
index 00000000..321669f3
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/IsValidUtf8TestUtil.java
@@ -0,0 +1,420 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// 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 static junit.framework.Assert.*;
+
+import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CharsetEncoder;
+import java.nio.charset.CoderResult;
+import java.nio.charset.CodingErrorAction;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Random;
+import java.util.logging.Logger;
+
+/**
+ * Shared testing code for {@link IsValidUtf8Test} and
+ * {@link IsValidUtf8FourByteTest}.
+ *
+ * @author jonp@google.com (Jon Perlow)
+ * @author martinrb@google.com (Martin Buchholz)
+ */
+class IsValidUtf8TestUtil {
+ private static Logger logger = Logger.getLogger(
+ IsValidUtf8TestUtil.class.getName());
+
+ // 128 - [chars 0x0000 to 0x007f]
+ static long ONE_BYTE_ROUNDTRIPPABLE_CHARACTERS = 0x007f - 0x0000 + 1;
+
+ // 128
+ static long EXPECTED_ONE_BYTE_ROUNDTRIPPABLE_COUNT =
+ ONE_BYTE_ROUNDTRIPPABLE_CHARACTERS;
+
+ // 1920 [chars 0x0080 to 0x07FF]
+ static long TWO_BYTE_ROUNDTRIPPABLE_CHARACTERS = 0x07FF - 0x0080 + 1;
+
+ // 18,304
+ static long EXPECTED_TWO_BYTE_ROUNDTRIPPABLE_COUNT =
+ // Both bytes are one byte characters
+ (long) Math.pow(EXPECTED_ONE_BYTE_ROUNDTRIPPABLE_COUNT, 2) +
+ // The possible number of two byte characters
+ TWO_BYTE_ROUNDTRIPPABLE_CHARACTERS;
+
+ // 2048
+ static long THREE_BYTE_SURROGATES = 2 * 1024;
+
+ // 61,440 [chars 0x0800 to 0xFFFF, minus surrogates]
+ static long THREE_BYTE_ROUNDTRIPPABLE_CHARACTERS =
+ 0xFFFF - 0x0800 + 1 - THREE_BYTE_SURROGATES;
+
+ // 2,650,112
+ static long EXPECTED_THREE_BYTE_ROUNDTRIPPABLE_COUNT =
+ // All one byte characters
+ (long) Math.pow(EXPECTED_ONE_BYTE_ROUNDTRIPPABLE_COUNT, 3) +
+ // One two byte character and a one byte character
+ 2 * TWO_BYTE_ROUNDTRIPPABLE_CHARACTERS *
+ ONE_BYTE_ROUNDTRIPPABLE_CHARACTERS +
+ // Three byte characters
+ THREE_BYTE_ROUNDTRIPPABLE_CHARACTERS;
+
+ // 1,048,576 [chars 0x10000L to 0x10FFFF]
+ static long FOUR_BYTE_ROUNDTRIPPABLE_CHARACTERS = 0x10FFFF - 0x10000L + 1;
+
+ // 289,571,839
+ static long EXPECTED_FOUR_BYTE_ROUNDTRIPPABLE_COUNT =
+ // All one byte characters
+ (long) Math.pow(EXPECTED_ONE_BYTE_ROUNDTRIPPABLE_COUNT, 4) +
+ // One and three byte characters
+ 2 * THREE_BYTE_ROUNDTRIPPABLE_CHARACTERS *
+ ONE_BYTE_ROUNDTRIPPABLE_CHARACTERS +
+ // Two two byte characters
+ TWO_BYTE_ROUNDTRIPPABLE_CHARACTERS * TWO_BYTE_ROUNDTRIPPABLE_CHARACTERS +
+ // Permutations of one and two byte characters
+ 3 * TWO_BYTE_ROUNDTRIPPABLE_CHARACTERS *
+ ONE_BYTE_ROUNDTRIPPABLE_CHARACTERS *
+ ONE_BYTE_ROUNDTRIPPABLE_CHARACTERS +
+ // Four byte characters
+ FOUR_BYTE_ROUNDTRIPPABLE_CHARACTERS;
+
+ static class Shard {
+ final long index;
+ final long start;
+ final long lim;
+ final long expected;
+
+
+ public Shard(long index, long start, long lim, long expected) {
+ assertTrue(start < lim);
+ this.index = index;
+ this.start = start;
+ this.lim = lim;
+ this.expected = expected;
+ }
+ }
+
+ static final long[] FOUR_BYTE_SHARDS_EXPECTED_ROUNTRIPPABLES =
+ generateFourByteShardsExpectedRunnables();
+
+ private static long[] generateFourByteShardsExpectedRunnables() {
+ long[] expected = new long[128];
+
+ // 0-63 are all 5300224
+ for (int i = 0; i <= 63; i++) {
+ expected[i] = 5300224;
+ }
+
+ // 97-111 are all 2342912
+ for (int i = 97; i <= 111; i++) {
+ expected[i] = 2342912;
+ }
+
+ // 113-117 are all 1048576
+ for (int i = 113; i <= 117; i++) {
+ expected[i] = 1048576;
+ }
+
+ // One offs
+ expected[112] = 786432;
+ expected[118] = 786432;
+ expected[119] = 1048576;
+ expected[120] = 458752;
+ expected[121] = 524288;
+ expected[122] = 65536;
+
+ // Anything not assigned was the default 0.
+ return expected;
+ }
+
+ static final List<Shard> FOUR_BYTE_SHARDS = generateFourByteShards(
+ 128, FOUR_BYTE_SHARDS_EXPECTED_ROUNTRIPPABLES);
+
+
+ private static List<Shard> generateFourByteShards(
+ int numShards, long[] expected) {
+ assertEquals(numShards, expected.length);
+ List<Shard> shards = new ArrayList<Shard>(numShards);
+ long LIM = 1L << 32;
+ long increment = LIM / numShards;
+ assertTrue(LIM % numShards == 0);
+ for (int i = 0; i < numShards; i++) {
+ shards.add(new Shard(i,
+ increment * i,
+ increment * (i + 1),
+ expected[i]));
+ }
+ return shards;
+ }
+
+ /**
+ * Helper to run the loop to test all the permutations for the number of bytes
+ * specified.
+ *
+ * @param numBytes the number of bytes in the byte array
+ * @param expectedCount the expected number of roundtrippable permutations
+ */
+ static void testBytes(int numBytes, long expectedCount)
+ throws UnsupportedEncodingException {
+ testBytes(numBytes, expectedCount, 0, -1);
+ }
+
+ /**
+ * Helper to run the loop to test all the permutations for the number of bytes
+ * specified. This overload is useful for debugging to get the loop to start
+ * at a certain character.
+ *
+ * @param numBytes the number of bytes in the byte array
+ * @param expectedCount the expected number of roundtrippable permutations
+ * @param start the starting bytes encoded as a long as big-endian
+ * @param lim the limit of bytes to process encoded as a long as big-endian,
+ * or -1 to mean the max limit for numBytes
+ */
+ static void testBytes(int numBytes, long expectedCount, long start, long lim)
+ throws UnsupportedEncodingException {
+ Random rnd = new Random();
+ byte[] bytes = new byte[numBytes];
+
+ if (lim == -1) {
+ lim = 1L << (numBytes * 8);
+ }
+ long count = 0;
+ long countRoundTripped = 0;
+ for (long byteChar = start; byteChar < lim; byteChar++) {
+ long tmpByteChar = byteChar;
+ for (int i = 0; i < numBytes; i++) {
+ bytes[bytes.length - i - 1] = (byte) tmpByteChar;
+ tmpByteChar = tmpByteChar >> 8;
+ }
+ ByteString bs = ByteString.copyFrom(bytes);
+ boolean isRoundTrippable = bs.isValidUtf8();
+ String s = new String(bytes, Internal.UTF_8);
+ byte[] bytesReencoded = s.getBytes(Internal.UTF_8);
+ boolean bytesEqual = Arrays.equals(bytes, bytesReencoded);
+
+ if (bytesEqual != isRoundTrippable) {
+ outputFailure(byteChar, bytes, bytesReencoded);
+ }
+
+ // Check agreement with static Utf8 methods.
+ assertEquals(isRoundTrippable, Utf8.isValidUtf8(bytes));
+ assertEquals(isRoundTrippable, Utf8.isValidUtf8(bytes, 0, numBytes));
+
+ // Test partial sequences.
+ // Partition numBytes into three segments (not necessarily non-empty).
+ int i = rnd.nextInt(numBytes);
+ int j = rnd.nextInt(numBytes);
+ if (j < i) {
+ int tmp = i; i = j; j = tmp;
+ }
+ int state1 = Utf8.partialIsValidUtf8(Utf8.COMPLETE, bytes, 0, i);
+ int state2 = Utf8.partialIsValidUtf8(state1, bytes, i, j);
+ int state3 = Utf8.partialIsValidUtf8(state2, bytes, j, numBytes);
+ if (isRoundTrippable != (state3 == Utf8.COMPLETE)) {
+ System.out.printf("state=%04x %04x %04x i=%d j=%d%n",
+ state1, state2, state3, i, j);
+ outputFailure(byteChar, bytes, bytesReencoded);
+ }
+ assertEquals(isRoundTrippable, (state3 == Utf8.COMPLETE));
+
+ // Test ropes built out of small partial sequences
+ ByteString rope = RopeByteString.newInstanceForTest(
+ bs.substring(0, i),
+ RopeByteString.newInstanceForTest(
+ bs.substring(i, j),
+ bs.substring(j, numBytes)));
+ assertSame(RopeByteString.class, rope.getClass());
+
+ ByteString[] byteStrings = { bs, bs.substring(0, numBytes), rope };
+ for (ByteString x : byteStrings) {
+ assertEquals(isRoundTrippable,
+ x.isValidUtf8());
+ assertEquals(state3,
+ x.partialIsValidUtf8(Utf8.COMPLETE, 0, numBytes));
+
+ assertEquals(state1,
+ x.partialIsValidUtf8(Utf8.COMPLETE, 0, i));
+ assertEquals(state1,
+ x.substring(0, i).partialIsValidUtf8(Utf8.COMPLETE, 0, i));
+ assertEquals(state2,
+ x.partialIsValidUtf8(state1, i, j - i));
+ assertEquals(state2,
+ x.substring(i, j).partialIsValidUtf8(state1, 0, j - i));
+ assertEquals(state3,
+ x.partialIsValidUtf8(state2, j, numBytes - j));
+ assertEquals(state3,
+ x.substring(j, numBytes)
+ .partialIsValidUtf8(state2, 0, numBytes - j));
+ }
+
+ // ByteString reduplication should not affect its UTF-8 validity.
+ ByteString ropeADope =
+ RopeByteString.newInstanceForTest(bs, bs.substring(0, numBytes));
+ assertEquals(isRoundTrippable, ropeADope.isValidUtf8());
+
+ if (isRoundTrippable) {
+ countRoundTripped++;
+ }
+ count++;
+ if (byteChar != 0 && byteChar % 1000000L == 0) {
+ logger.info("Processed " + (byteChar / 1000000L) +
+ " million characters");
+ }
+ }
+ logger.info("Round tripped " + countRoundTripped + " of " + count);
+ assertEquals(expectedCount, countRoundTripped);
+ }
+
+ /**
+ * Variation of {@link #testBytes} that does less allocation using the
+ * low-level encoders/decoders directly. Checked in because it's useful for
+ * debugging when trying to process bytes faster, but since it doesn't use the
+ * actual String class, it's possible for incompatibilities to develop
+ * (although unlikely).
+ *
+ * @param numBytes the number of bytes in the byte array
+ * @param expectedCount the expected number of roundtrippable permutations
+ * @param start the starting bytes encoded as a long as big-endian
+ * @param lim the limit of bytes to process encoded as a long as big-endian,
+ * or -1 to mean the max limit for numBytes
+ */
+ void testBytesUsingByteBuffers(
+ int numBytes, long expectedCount, long start, long lim)
+ throws UnsupportedEncodingException {
+ CharsetDecoder decoder = Internal.UTF_8.newDecoder()
+ .onMalformedInput(CodingErrorAction.REPLACE)
+ .onUnmappableCharacter(CodingErrorAction.REPLACE);
+ CharsetEncoder encoder = Internal.UTF_8.newEncoder()
+ .onMalformedInput(CodingErrorAction.REPLACE)
+ .onUnmappableCharacter(CodingErrorAction.REPLACE);
+ byte[] bytes = new byte[numBytes];
+ int maxChars = (int) (decoder.maxCharsPerByte() * numBytes) + 1;
+ char[] charsDecoded =
+ new char[(int) (decoder.maxCharsPerByte() * numBytes) + 1];
+ int maxBytes = (int) (encoder.maxBytesPerChar() * maxChars) + 1;
+ byte[] bytesReencoded = new byte[maxBytes];
+
+ ByteBuffer bb = ByteBuffer.wrap(bytes);
+ CharBuffer cb = CharBuffer.wrap(charsDecoded);
+ ByteBuffer bbReencoded = ByteBuffer.wrap(bytesReencoded);
+ if (lim == -1) {
+ lim = 1L << (numBytes * 8);
+ }
+ long count = 0;
+ long countRoundTripped = 0;
+ for (long byteChar = start; byteChar < lim; byteChar++) {
+ bb.rewind();
+ bb.limit(bytes.length);
+ cb.rewind();
+ cb.limit(charsDecoded.length);
+ bbReencoded.rewind();
+ bbReencoded.limit(bytesReencoded.length);
+ encoder.reset();
+ decoder.reset();
+ long tmpByteChar = byteChar;
+ for (int i = 0; i < bytes.length; i++) {
+ bytes[bytes.length - i - 1] = (byte) tmpByteChar;
+ tmpByteChar = tmpByteChar >> 8;
+ }
+ boolean isRoundTrippable = ByteString.copyFrom(bytes).isValidUtf8();
+ CoderResult result = decoder.decode(bb, cb, true);
+ assertFalse(result.isError());
+ result = decoder.flush(cb);
+ assertFalse(result.isError());
+
+ int charLen = cb.position();
+ cb.rewind();
+ cb.limit(charLen);
+ result = encoder.encode(cb, bbReencoded, true);
+ assertFalse(result.isError());
+ result = encoder.flush(bbReencoded);
+ assertFalse(result.isError());
+
+ boolean bytesEqual = true;
+ int bytesLen = bbReencoded.position();
+ if (bytesLen != numBytes) {
+ bytesEqual = false;
+ } else {
+ for (int i = 0; i < numBytes; i++) {
+ if (bytes[i] != bytesReencoded[i]) {
+ bytesEqual = false;
+ break;
+ }
+ }
+ }
+ if (bytesEqual != isRoundTrippable) {
+ outputFailure(byteChar, bytes, bytesReencoded, bytesLen);
+ }
+
+ count++;
+ if (isRoundTrippable) {
+ countRoundTripped++;
+ }
+ if (byteChar != 0 && byteChar % 1000000 == 0) {
+ logger.info("Processed " + (byteChar / 1000000) +
+ " million characters");
+ }
+ }
+ logger.info("Round tripped " + countRoundTripped + " of " + count);
+ assertEquals(expectedCount, countRoundTripped);
+ }
+
+ private static void outputFailure(long byteChar, byte[] bytes, byte[] after) {
+ outputFailure(byteChar, bytes, after, after.length);
+ }
+
+ private static void outputFailure(long byteChar, byte[] bytes, byte[] after,
+ int len) {
+ fail("Failure: (" + Long.toHexString(byteChar) + ") " +
+ toHexString(bytes) + " => " + toHexString(after, len));
+ }
+
+ private static String toHexString(byte[] b) {
+ return toHexString(b, b.length);
+ }
+
+ private static String toHexString(byte[] b, int len) {
+ StringBuilder s = new StringBuilder();
+ s.append("\"");
+ for (int i = 0; i < len; i++) {
+ if (i > 0) {
+ s.append(" ");
+ }
+ s.append(String.format("%02x", b[i] & 0xFF));
+ }
+ s.append("\"");
+ return s.toString();
+ }
+
+}
diff --git a/java/core/src/test/java/com/google/protobuf/LazyFieldLiteTest.java b/java/core/src/test/java/com/google/protobuf/LazyFieldLiteTest.java
new file mode 100644
index 00000000..211b5697
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/LazyFieldLiteTest.java
@@ -0,0 +1,271 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// 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 static protobuf_unittest.UnittestProto.optionalInt32Extension;
+import static protobuf_unittest.UnittestProto.optionalInt64Extension;
+
+import protobuf_unittest.UnittestProto.TestAllExtensions;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+
+import java.io.IOException;
+import junit.framework.TestCase;
+
+/**
+ * Unit test for {@link LazyFieldLite}.
+ *
+ * @author xiangl@google.com (Xiang Li)
+ */
+public class LazyFieldLiteTest extends TestCase {
+
+ public void testGetValue() {
+ MessageLite message = TestUtil.getAllSet();
+ LazyFieldLite lazyField = createLazyFieldLiteFromMessage(message);
+ assertEquals(message, lazyField.getValue(TestAllTypes.getDefaultInstance()));
+ changeValue(lazyField);
+ assertNotEqual(message, lazyField.getValue(TestAllTypes.getDefaultInstance()));
+ }
+
+ public void testGetValueEx() throws Exception {
+ TestAllExtensions message = TestUtil.getAllExtensionsSet();
+ LazyFieldLite lazyField = createLazyFieldLiteFromMessage(message);
+ assertEquals(message, lazyField.getValue(TestAllExtensions.getDefaultInstance()));
+ changeValue(lazyField);
+ assertNotEqual(message, lazyField.getValue(TestAllExtensions.getDefaultInstance()));
+ }
+
+ public void testSetValue() {
+ MessageLite message = TestUtil.getAllSet();
+ LazyFieldLite lazyField = createLazyFieldLiteFromMessage(message);
+ changeValue(lazyField);
+ assertNotEqual(message, lazyField.getValue(TestAllTypes.getDefaultInstance()));
+ message = lazyField.getValue(TestAllTypes.getDefaultInstance());
+ changeValue(lazyField);
+ assertEquals(message, lazyField.getValue(TestAllTypes.getDefaultInstance()));
+ }
+
+ public void testSetValueEx() throws Exception {
+ TestAllExtensions message = TestUtil.getAllExtensionsSet();
+ LazyFieldLite lazyField = createLazyFieldLiteFromMessage(message);
+ changeValue(lazyField);
+ assertNotEqual(message, lazyField.getValue(TestAllExtensions.getDefaultInstance()));
+ MessageLite value = lazyField.getValue(TestAllExtensions.getDefaultInstance());
+ changeValue(lazyField);
+ assertEquals(value, lazyField.getValue(TestAllExtensions.getDefaultInstance()));
+ }
+
+ public void testGetSerializedSize() {
+ MessageLite message = TestUtil.getAllSet();
+ LazyFieldLite lazyField = createLazyFieldLiteFromMessage(message);
+ assertEquals(message.getSerializedSize(), lazyField.getSerializedSize());
+ changeValue(lazyField);
+ assertNotEqual(message.getSerializedSize(), lazyField.getSerializedSize());
+ }
+
+ public void testGetSerializedSizeEx() throws Exception {
+ TestAllExtensions message = TestUtil.getAllExtensionsSet();
+ LazyFieldLite lazyField = createLazyFieldLiteFromMessage(message);
+ assertEquals(message.getSerializedSize(), lazyField.getSerializedSize());
+ changeValue(lazyField);
+ assertNotEqual(message.getSerializedSize(), lazyField.getSerializedSize());
+ }
+
+ public void testGetByteString() {
+ MessageLite message = TestUtil.getAllSet();
+ LazyFieldLite lazyField = createLazyFieldLiteFromMessage(message);
+ assertEquals(message.toByteString(), lazyField.toByteString());
+ changeValue(lazyField);
+ assertNotEqual(message.toByteString(), lazyField.toByteString());
+ }
+
+ public void testGetByteStringEx() throws Exception {
+ TestAllExtensions message = TestUtil.getAllExtensionsSet();
+ LazyFieldLite lazyField = createLazyFieldLiteFromMessage(message);
+ assertEquals(message.toByteString(), lazyField.toByteString());
+ changeValue(lazyField);
+ assertNotEqual(message.toByteString(), lazyField.toByteString());
+ }
+
+ public void testMergeExtensions() throws Exception {
+ TestAllExtensions message = TestUtil.getAllExtensionsSet();
+ LazyFieldLite original = createLazyFieldLiteFromMessage(message);
+ LazyFieldLite merged = new LazyFieldLite();
+ merged.merge(original);
+ TestAllExtensions value = (TestAllExtensions) merged.getValue(
+ TestAllExtensions.getDefaultInstance());
+ assertEquals(message, value);
+ }
+
+ public void testEmptyLazyField() throws Exception {
+ LazyFieldLite field = new LazyFieldLite();
+ assertEquals(0, field.getSerializedSize());
+ assertEquals(ByteString.EMPTY, field.toByteString());
+ }
+
+ public void testInvalidProto() throws Exception {
+ // Silently fails and uses the default instance.
+ LazyFieldLite field = new LazyFieldLite(
+ TestUtil.getExtensionRegistry(), ByteString.copyFromUtf8("invalid"));
+ assertEquals(
+ TestAllTypes.getDefaultInstance(), field.getValue(TestAllTypes.getDefaultInstance()));
+ assertEquals(0, field.getSerializedSize());
+ assertEquals(ByteString.EMPTY, field.toByteString());
+ }
+
+ public void testMergeBeforeParsing() throws Exception {
+ TestAllTypes message1 = TestAllTypes.newBuilder().setOptionalInt32(1).build();
+ LazyFieldLite field1 = createLazyFieldLiteFromMessage(message1);
+ TestAllTypes message2 = TestAllTypes.newBuilder().setOptionalInt64(2).build();
+ LazyFieldLite field2 = createLazyFieldLiteFromMessage(message2);
+
+ field1.merge(field2);
+ TestAllTypes expected =
+ TestAllTypes.newBuilder().setOptionalInt32(1).setOptionalInt64(2).build();
+ assertEquals(expected, field1.getValue(TestAllTypes.getDefaultInstance()));
+ }
+
+ public void testMergeOneNotParsed() throws Exception {
+ // Test a few different paths that involve one message that was not parsed.
+ TestAllTypes message1 = TestAllTypes.newBuilder().setOptionalInt32(1).build();
+ TestAllTypes message2 = TestAllTypes.newBuilder().setOptionalInt64(2).build();
+ TestAllTypes expected =
+ TestAllTypes.newBuilder().setOptionalInt32(1).setOptionalInt64(2).build();
+
+ LazyFieldLite field1 = LazyFieldLite.fromValue(message1);
+ field1.getValue(TestAllTypes.getDefaultInstance()); // Force parsing.
+ LazyFieldLite field2 = createLazyFieldLiteFromMessage(message2);
+ field1.merge(field2);
+ assertEquals(expected, field1.getValue(TestAllTypes.getDefaultInstance()));
+
+ // Now reverse which one is parsed first.
+ field1 = LazyFieldLite.fromValue(message1);
+ field2 = createLazyFieldLiteFromMessage(message2);
+ field2.getValue(TestAllTypes.getDefaultInstance()); // Force parsing.
+ field1.merge(field2);
+ assertEquals(expected, field1.getValue(TestAllTypes.getDefaultInstance()));
+ }
+
+ public void testMergeInvalid() throws Exception {
+ // Test a few different paths that involve one message that was not parsed.
+ TestAllTypes message = TestAllTypes.newBuilder().setOptionalInt32(1).build();
+ LazyFieldLite valid = LazyFieldLite.fromValue(message);
+ LazyFieldLite invalid = new LazyFieldLite(
+ TestUtil.getExtensionRegistry(), ByteString.copyFromUtf8("invalid"));
+ invalid.merge(valid);
+
+ // We swallow the exception and just use the set field.
+ assertEquals(message, invalid.getValue(TestAllTypes.getDefaultInstance()));
+ }
+
+ public void testMergeKeepsExtensionsWhenPossible() throws Exception {
+ // In this test we attempt to only use the empty registry, which will strip out all extensions
+ // when serializing and then parsing. We verify that each code path will attempt to not
+ // serialize and parse a message that was set directly without going through the
+ // extensionRegistry.
+ TestAllExtensions messageWithExtensions =
+ TestAllExtensions.newBuilder().setExtension(optionalInt32Extension, 42).build();
+ TestAllExtensions emptyMessage = TestAllExtensions.newBuilder().build();
+
+ ExtensionRegistryLite emptyRegistry = ExtensionRegistryLite.getEmptyRegistry();
+
+ LazyFieldLite field = LazyFieldLite.fromValue(messageWithExtensions);
+ field.merge(createLazyFieldLiteFromMessage(emptyRegistry, emptyMessage));
+ assertEquals(messageWithExtensions, field.getValue(TestAllExtensions.getDefaultInstance()));
+
+ // Now reverse the order of the merging.
+ field = createLazyFieldLiteFromMessage(emptyRegistry, emptyMessage);
+ field.merge(LazyFieldLite.fromValue(messageWithExtensions));
+ assertEquals(messageWithExtensions, field.getValue(TestAllExtensions.getDefaultInstance()));
+
+ // Now try parsing the empty field first.
+ field = LazyFieldLite.fromValue(messageWithExtensions);
+ LazyFieldLite other = createLazyFieldLiteFromMessage(emptyRegistry, emptyMessage);
+ other.getValue(TestAllExtensions.getDefaultInstance()); // Force parsing.
+ field.merge(other);
+ assertEquals(messageWithExtensions, field.getValue(TestAllExtensions.getDefaultInstance()));
+
+ // And again reverse.
+ field = createLazyFieldLiteFromMessage(emptyRegistry, emptyMessage);
+ field.getValue(TestAllExtensions.getDefaultInstance()); // Force parsing.
+ other = LazyFieldLite.fromValue(messageWithExtensions);
+ field.merge(other);
+ assertEquals(messageWithExtensions, field.getValue(TestAllExtensions.getDefaultInstance()));
+ }
+
+ public void testMergeMightLoseExtensions() throws Exception {
+ // Test that we don't know about the extensions when parsing.
+ TestAllExtensions message1 =
+ TestAllExtensions.newBuilder().setExtension(optionalInt32Extension, 1).build();
+ TestAllExtensions message2 =
+ TestAllExtensions.newBuilder().setExtension(optionalInt64Extension, 2L).build();
+
+ LazyFieldLite field = LazyFieldLite.fromValue(message1);
+ field.merge(LazyFieldLite.fromValue(message2));
+
+ // We lose the extensions from message 2 because we have to serialize it and then parse it
+ // again, using the empty registry this time.
+ TestAllExtensions value =
+ (TestAllExtensions) field.getValue(TestAllExtensions.getDefaultInstance());
+ assertTrue(value.hasExtension(optionalInt32Extension));
+ assertEquals(Integer.valueOf(1), value.getExtension(optionalInt32Extension));
+ assertFalse(value.hasExtension(optionalInt64Extension));
+
+ // The field is still there, it is just unknown.
+ assertTrue(value.getUnknownFields()
+ .hasField(optionalInt64Extension.getDescriptor().getNumber()));
+ }
+
+
+ // Help methods.
+
+ private LazyFieldLite createLazyFieldLiteFromMessage(MessageLite message) {
+ return createLazyFieldLiteFromMessage(TestUtil.getExtensionRegistry(), message);
+ }
+
+ private LazyFieldLite createLazyFieldLiteFromMessage(
+ ExtensionRegistryLite extensionRegistry, MessageLite message) {
+ ByteString bytes = message.toByteString();
+ return new LazyFieldLite(extensionRegistry, bytes);
+ }
+
+ private void changeValue(LazyFieldLite lazyField) {
+ TestAllTypes.Builder builder = TestUtil.getAllSet().toBuilder();
+ builder.addRepeatedBool(true);
+ MessageLite newMessage = builder.build();
+ lazyField.setValue(newMessage);
+ }
+
+ private void assertNotEqual(Object unexpected, Object actual) {
+ assertFalse(unexpected == actual
+ || (unexpected != null && unexpected.equals(actual)));
+ }
+
+}
diff --git a/java/core/src/test/java/com/google/protobuf/LazyFieldTest.java b/java/core/src/test/java/com/google/protobuf/LazyFieldTest.java
new file mode 100644
index 00000000..2b900065
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/LazyFieldTest.java
@@ -0,0 +1,121 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// 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.UnittestProto.TestAllExtensions;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+
+import java.io.IOException;
+import junit.framework.TestCase;
+
+/**
+ * Unit test for {@link LazyField}.
+ *
+ * @author xiangl@google.com (Xiang Li)
+ */
+public class LazyFieldTest extends TestCase {
+ public void testHashCode() {
+ MessageLite message = TestUtil.getAllSet();
+ LazyField lazyField =
+ createLazyFieldFromMessage(message);
+ assertEquals(message.hashCode(), lazyField.hashCode());
+ lazyField.getValue();
+ assertEquals(message.hashCode(), lazyField.hashCode());
+ changeValue(lazyField);
+ // make sure two messages have different hash code
+ assertNotEqual(message.hashCode(), lazyField.hashCode());
+ }
+
+ public void testHashCodeEx() throws Exception {
+ TestAllExtensions message = TestUtil.getAllExtensionsSet();
+ LazyField lazyField = createLazyFieldFromMessage(message);
+ assertEquals(message.hashCode(), lazyField.hashCode());
+ lazyField.getValue();
+ assertEquals(message.hashCode(), lazyField.hashCode());
+ changeValue(lazyField);
+ // make sure two messages have different hash code
+ assertNotEqual(message.hashCode(), lazyField.hashCode());
+ }
+
+ public void testGetValue() {
+ MessageLite message = TestUtil.getAllSet();
+ LazyField lazyField = createLazyFieldFromMessage(message);
+ assertEquals(message, lazyField.getValue());
+ changeValue(lazyField);
+ assertNotEqual(message, lazyField.getValue());
+ }
+
+ public void testGetValueEx() throws Exception {
+ TestAllExtensions message = TestUtil.getAllExtensionsSet();
+ LazyField lazyField = createLazyFieldFromMessage(message);
+ assertEquals(message, lazyField.getValue());
+ changeValue(lazyField);
+ assertNotEqual(message, lazyField.getValue());
+ }
+
+ public void testEqualsObject() {
+ MessageLite message = TestUtil.getAllSet();
+ LazyField lazyField = createLazyFieldFromMessage(message);
+ assertTrue(lazyField.equals(message));
+ changeValue(lazyField);
+ assertFalse(lazyField.equals(message));
+ assertFalse(message.equals(lazyField.getValue()));
+ }
+
+ public void testEqualsObjectEx() throws Exception {
+ TestAllExtensions message = TestUtil.getAllExtensionsSet();
+ LazyField lazyField = createLazyFieldFromMessage(message);
+ assertTrue(lazyField.equals(message));
+ changeValue(lazyField);
+ assertFalse(lazyField.equals(message));
+ assertFalse(message.equals(lazyField.getValue()));
+ }
+
+ // Help methods.
+
+ private LazyField createLazyFieldFromMessage(MessageLite message) {
+ ByteString bytes = message.toByteString();
+ return new LazyField(message.getDefaultInstanceForType(),
+ TestUtil.getExtensionRegistry(), bytes);
+ }
+
+ private void changeValue(LazyField lazyField) {
+ TestAllTypes.Builder builder = TestUtil.getAllSet().toBuilder();
+ builder.addRepeatedBool(true);
+ MessageLite newMessage = builder.build();
+ lazyField.setValue(newMessage);
+ }
+
+ private void assertNotEqual(Object unexpected, Object actual) {
+ assertFalse(unexpected == actual
+ || (unexpected != null && unexpected.equals(actual)));
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/LazyMessageLiteTest.java b/java/core/src/test/java/com/google/protobuf/LazyMessageLiteTest.java
new file mode 100644
index 00000000..afe0fffd
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/LazyMessageLiteTest.java
@@ -0,0 +1,307 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// 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.LazyFieldsLite.LazyExtension;
+import protobuf_unittest.LazyFieldsLite.LazyInnerMessageLite;
+import protobuf_unittest.LazyFieldsLite.LazyMessageLite;
+import protobuf_unittest.LazyFieldsLite.LazyNestedInnerMessageLite;
+
+import junit.framework.TestCase;
+
+import java.util.ArrayList;
+
+/**
+ * Unit test for messages with lazy fields.
+ *
+ * @author niwasaki@google.com (Naoki Iwasaki)
+ */
+public class LazyMessageLiteTest extends TestCase {
+
+ private Parser<LazyInnerMessageLite> originalLazyInnerMessageLiteParser;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ public void testSetValues() {
+ LazyNestedInnerMessageLite nested = LazyNestedInnerMessageLite.newBuilder()
+ .setNum(3)
+ .build();
+ LazyInnerMessageLite inner = LazyInnerMessageLite.newBuilder()
+ .setNum(2)
+ .setNested(nested)
+ .build();
+ LazyMessageLite outer = LazyMessageLite.newBuilder()
+ .setNum(1)
+ .setInner(inner)
+ .setOneofNum(123)
+ .setOneofInner(inner)
+ .build();
+
+ assertEquals(1, outer.getNum());
+ assertEquals(421, outer.getNumWithDefault());
+
+ assertEquals(2, outer.getInner().getNum());
+ assertEquals(42, outer.getInner().getNumWithDefault());
+
+ assertEquals(3, outer.getInner().getNested().getNum());
+ assertEquals(4, outer.getInner().getNested().getNumWithDefault());
+
+ assertFalse(outer.hasOneofNum());
+ assertTrue(outer.hasOneofInner());
+
+ assertEquals(2, outer.getOneofInner().getNum());
+ assertEquals(42, outer.getOneofInner().getNumWithDefault());
+ assertEquals(3, outer.getOneofInner().getNested().getNum());
+ assertEquals(4, outer.getOneofInner().getNested().getNumWithDefault());
+ }
+
+ public void testSetRepeatedValues() {
+ LazyMessageLite outer = LazyMessageLite.newBuilder()
+ .setNum(1)
+ .addRepeatedInner(LazyInnerMessageLite.newBuilder().setNum(119))
+ .addRepeatedInner(LazyInnerMessageLite.newBuilder().setNum(122))
+ .build();
+
+ assertEquals(1, outer.getNum());
+ assertEquals(2, outer.getRepeatedInnerCount());
+ assertEquals(119, outer.getRepeatedInner(0).getNum());
+ assertEquals(122, outer.getRepeatedInner(1).getNum());
+ }
+
+ public void testAddAll() {
+ ArrayList<LazyInnerMessageLite> inners = new ArrayList<LazyInnerMessageLite>();
+ int count = 4;
+ for (int i = 0; i < count; i++) {
+ LazyInnerMessageLite inner = LazyInnerMessageLite.newBuilder()
+ .setNum(i)
+ .build();
+ inners.add(inner);
+ }
+
+ LazyMessageLite outer = LazyMessageLite.newBuilder()
+ .addAllRepeatedInner(inners)
+ .build();
+ assertEquals(count, outer.getRepeatedInnerCount());
+ for (int i = 0; i < count; i++) {
+ assertEquals(i, outer.getRepeatedInner(i).getNum());
+ }
+ }
+
+ public void testGetDefaultValues() {
+ LazyMessageLite outer = LazyMessageLite.newBuilder()
+ .build();
+
+ assertEquals(0, outer.getNum());
+ assertEquals(421, outer.getNumWithDefault());
+
+ assertEquals(0, outer.getInner().getNum());
+ assertEquals(42, outer.getInner().getNumWithDefault());
+
+ assertEquals(0, outer.getInner().getNested().getNum());
+ assertEquals(4, outer.getInner().getNested().getNumWithDefault());
+
+ assertEquals(0, outer.getOneofNum());
+
+ assertEquals(0, outer.getOneofInner().getNum());
+ assertEquals(42, outer.getOneofInner().getNumWithDefault());
+ assertEquals(0, outer.getOneofInner().getNested().getNum());
+ assertEquals(4, outer.getOneofInner().getNested().getNumWithDefault());
+ }
+
+ public void testClearValues() {
+ LazyInnerMessageLite inner = LazyInnerMessageLite.newBuilder()
+ .setNum(115)
+ .build();
+
+ LazyMessageLite.Builder outerBuilder = LazyMessageLite.newBuilder();
+
+ assertEquals(0, outerBuilder.build().getNum());
+
+
+ // Set/Clear num
+ outerBuilder.setNum(100);
+
+ assertEquals(100, outerBuilder.build().getNum());
+ assertEquals(421, outerBuilder.build().getNumWithDefault());
+ assertFalse(outerBuilder.build().hasInner());
+
+ outerBuilder.clearNum();
+
+ assertEquals(0, outerBuilder.build().getNum());
+ assertEquals(421, outerBuilder.build().getNumWithDefault());
+ assertFalse(outerBuilder.build().hasInner());
+
+
+ // Set/Clear all
+ outerBuilder.setNum(100)
+ .setInner(inner)
+ .addRepeatedInner(LazyInnerMessageLite.newBuilder().setNum(119))
+ .addRepeatedInner(LazyInnerMessageLite.newBuilder().setNum(122))
+ .setOneofInner(LazyInnerMessageLite.newBuilder().setNum(123));
+
+ LazyMessageLite outer = outerBuilder.build();
+ assertEquals(100, outer.getNum());
+ assertEquals(421, outer.getNumWithDefault());
+ assertTrue(outer.hasInner());
+ assertEquals(115, outer.getInner().getNum());
+ assertEquals(2, outer.getRepeatedInnerCount());
+ assertEquals(119, outer.getRepeatedInner(0).getNum());
+ assertEquals(122, outer.getRepeatedInner(1).getNum());
+ assertTrue(outer.hasOneofInner());
+ assertEquals(123, outer.getOneofInner().getNum());
+
+ outerBuilder.clear();
+
+ outer = outerBuilder.build();
+
+ assertEquals(0, outer.getNum());
+ assertEquals(421, outer.getNumWithDefault());
+ assertFalse(outer.hasInner());
+ assertEquals(0, outer.getRepeatedInnerCount());
+ assertFalse(outer.hasOneofInner());
+ assertEquals(0, outer.getOneofInner().getNum());
+ }
+
+ public void testMergeValues() {
+ LazyMessageLite outerBase = LazyMessageLite.newBuilder()
+ .setNumWithDefault(122)
+ .build();
+
+ LazyInnerMessageLite innerMerging = LazyInnerMessageLite.newBuilder()
+ .setNum(115)
+ .build();
+ LazyMessageLite outerMerging = LazyMessageLite.newBuilder()
+ .setNum(119)
+ .setInner(innerMerging)
+ .setOneofInner(innerMerging)
+ .build();
+
+ LazyMessageLite merged = LazyMessageLite
+ .newBuilder(outerBase)
+ .mergeFrom(outerMerging)
+ .build();
+ assertEquals(119, merged.getNum());
+ assertEquals(122, merged.getNumWithDefault());
+ assertEquals(115, merged.getInner().getNum());
+ assertEquals(42, merged.getInner().getNumWithDefault());
+ assertEquals(115, merged.getOneofInner().getNum());
+ assertEquals(42, merged.getOneofInner().getNumWithDefault());
+ }
+
+ public void testMergeDefaultValues() {
+ LazyInnerMessageLite innerBase = LazyInnerMessageLite.newBuilder()
+ .setNum(115)
+ .build();
+ LazyMessageLite outerBase = LazyMessageLite.newBuilder()
+ .setNum(119)
+ .setNumWithDefault(122)
+ .setInner(innerBase)
+ .setOneofInner(innerBase)
+ .build();
+
+ LazyMessageLite outerMerging = LazyMessageLite.newBuilder()
+ .build();
+
+ LazyMessageLite merged = LazyMessageLite
+ .newBuilder(outerBase)
+ .mergeFrom(outerMerging)
+ .build();
+ // Merging default-instance shouldn't overwrite values in the base message.
+ assertEquals(119, merged.getNum());
+ assertEquals(122, merged.getNumWithDefault());
+ assertEquals(115, merged.getInner().getNum());
+ assertEquals(42, merged.getInner().getNumWithDefault());
+ assertEquals(115, merged.getOneofInner().getNum());
+ assertEquals(42, merged.getOneofInner().getNumWithDefault());
+ }
+
+ public void testSerialize() throws InvalidProtocolBufferException {
+ LazyNestedInnerMessageLite nested = LazyNestedInnerMessageLite.newBuilder()
+ .setNum(3)
+ .build();
+ LazyInnerMessageLite inner = LazyInnerMessageLite.newBuilder()
+ .setNum(2)
+ .setNested(nested)
+ .build();
+ LazyMessageLite outer = LazyMessageLite.newBuilder()
+ .setNum(1)
+ .setInner(inner)
+ .setOneofInner(inner)
+ .build();
+
+ ByteString bytes = outer.toByteString();
+ assertEquals(bytes.size(), outer.getSerializedSize());
+
+ LazyMessageLite deserialized = LazyMessageLite.parseFrom(bytes);
+
+ assertEquals(1, deserialized.getNum());
+ assertEquals(421, deserialized.getNumWithDefault());
+
+ assertEquals(2, deserialized.getInner().getNum());
+ assertEquals(42, deserialized.getInner().getNumWithDefault());
+
+ assertEquals(3, deserialized.getInner().getNested().getNum());
+ assertEquals(4, deserialized.getInner().getNested().getNumWithDefault());
+
+ assertEquals(2, deserialized.getOneofInner().getNum());
+ assertEquals(42, deserialized.getOneofInner().getNumWithDefault());
+ assertEquals(3, deserialized.getOneofInner().getNested().getNum());
+ assertEquals(4, deserialized.getOneofInner().getNested().getNumWithDefault());
+
+ assertEquals(bytes, deserialized.toByteString());
+ }
+
+ public void testExtensions() throws Exception {
+ LazyInnerMessageLite.Builder innerBuilder = LazyInnerMessageLite.newBuilder();
+ innerBuilder.setExtension(
+ LazyExtension.extension, LazyExtension.newBuilder()
+ .setName("name").build());
+ assertTrue(innerBuilder.hasExtension(LazyExtension.extension));
+ assertEquals("name", innerBuilder.getExtension(LazyExtension.extension).getName());
+
+ LazyInnerMessageLite innerMessage = innerBuilder.build();
+ assertTrue(innerMessage.hasExtension(LazyExtension.extension));
+ assertEquals("name", innerMessage.getExtension(LazyExtension.extension).getName());
+
+ LazyMessageLite lite = LazyMessageLite.newBuilder()
+ .setInner(innerMessage).build();
+ assertTrue(lite.getInner().hasExtension(LazyExtension.extension));
+ assertEquals("name", lite.getInner().getExtension(LazyExtension.extension).getName());
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/LazyStringArrayListTest.java b/java/core/src/test/java/com/google/protobuf/LazyStringArrayListTest.java
new file mode 100644
index 00000000..0f42ac50
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/LazyStringArrayListTest.java
@@ -0,0 +1,362 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// 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 static java.util.Arrays.asList;
+
+import junit.framework.TestCase;
+
+import java.util.ArrayList;
+import java.util.ConcurrentModificationException;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Tests for {@link LazyStringArrayList}.
+ *
+ * @author jonp@google.com (Jon Perlow)
+ */
+public class LazyStringArrayListTest extends TestCase {
+
+ private static String STRING_A = "A";
+ private static String STRING_B = "B";
+ private static String STRING_C = "C";
+
+ private static ByteString BYTE_STRING_A = ByteString.copyFromUtf8("A");
+ private static ByteString BYTE_STRING_B = ByteString.copyFromUtf8("B");
+ private static ByteString BYTE_STRING_C = ByteString.copyFromUtf8("C");
+
+ public void testJustStrings() {
+ LazyStringArrayList list = new LazyStringArrayList();
+ list.add(STRING_A);
+ list.add(STRING_B);
+ list.add(STRING_C);
+
+ assertEquals(3, list.size());
+ assertSame(STRING_A, list.get(0));
+ assertSame(STRING_B, list.get(1));
+ assertSame(STRING_C, list.get(2));
+
+ list.set(1, STRING_C);
+ assertSame(STRING_C, list.get(1));
+
+ list.remove(1);
+ assertSame(STRING_A, list.get(0));
+ assertSame(STRING_C, list.get(1));
+
+ List<ByteString> byteStringList = list.asByteStringList();
+ assertEquals(BYTE_STRING_A, byteStringList.get(0));
+ assertEquals(BYTE_STRING_C, byteStringList.get(1));
+
+ // Underlying list should be transformed.
+ assertSame(byteStringList.get(0), list.getByteString(0));
+ assertSame(byteStringList.get(1), list.getByteString(1));
+ }
+
+ public void testJustByteString() {
+ LazyStringArrayList list = new LazyStringArrayList();
+ list.add(BYTE_STRING_A);
+ list.add(BYTE_STRING_B);
+ list.add(BYTE_STRING_C);
+
+ assertEquals(3, list.size());
+ assertSame(BYTE_STRING_A, list.getByteString(0));
+ assertSame(BYTE_STRING_B, list.getByteString(1));
+ assertSame(BYTE_STRING_C, list.getByteString(2));
+
+ list.remove(1);
+ assertSame(BYTE_STRING_A, list.getByteString(0));
+ assertSame(BYTE_STRING_C, list.getByteString(1));
+
+ List<ByteString> byteStringList = list.asByteStringList();
+ assertSame(BYTE_STRING_A, byteStringList.get(0));
+ assertSame(BYTE_STRING_C, byteStringList.get(1));
+ }
+
+ public void testConversionBackAndForth() {
+ LazyStringArrayList list = new LazyStringArrayList();
+ list.add(STRING_A);
+ list.add(BYTE_STRING_B);
+ list.add(BYTE_STRING_C);
+
+ // String a should be the same because it was originally a string
+ assertSame(STRING_A, list.get(0));
+
+ // String b and c should be different because the string has to be computed
+ // from the ByteString
+ String bPrime = list.get(1);
+ assertNotSame(STRING_B, bPrime);
+ assertEquals(STRING_B, bPrime);
+ String cPrime = list.get(2);
+ assertNotSame(STRING_C, cPrime);
+ assertEquals(STRING_C, cPrime);
+
+ // String c and c should stay the same once cached.
+ assertSame(bPrime, list.get(1));
+ assertSame(cPrime, list.get(2));
+
+ // ByteString needs to be computed from string for both a and b
+ ByteString aPrimeByteString = list.getByteString(0);
+ assertEquals(BYTE_STRING_A, aPrimeByteString);
+ ByteString bPrimeByteString = list.getByteString(1);
+ assertNotSame(BYTE_STRING_B, bPrimeByteString);
+ assertEquals(BYTE_STRING_B, list.getByteString(1));
+
+ // Once cached, ByteString should stay cached.
+ assertSame(aPrimeByteString, list.getByteString(0));
+ assertSame(bPrimeByteString, list.getByteString(1));
+ }
+
+ public void testCopyConstructorCopiesByReference() {
+ LazyStringArrayList list1 = new LazyStringArrayList();
+ list1.add(STRING_A);
+ list1.add(BYTE_STRING_B);
+ list1.add(BYTE_STRING_C);
+
+ LazyStringArrayList list2 = new LazyStringArrayList(list1);
+ assertEquals(3, list2.size());
+ assertSame(STRING_A, list2.get(0));
+ assertSame(BYTE_STRING_B, list2.getByteString(1));
+ assertSame(BYTE_STRING_C, list2.getByteString(2));
+ }
+
+ public void testListCopyConstructor() {
+ List<String> list1 = new ArrayList<String>();
+ list1.add(STRING_A);
+ list1.add(STRING_B);
+ list1.add(STRING_C);
+
+ LazyStringArrayList list2 = new LazyStringArrayList(list1);
+ assertEquals(3, list2.size());
+ assertSame(STRING_A, list2.get(0));
+ assertSame(STRING_B, list2.get(1));
+ assertSame(STRING_C, list2.get(2));
+ }
+
+ public void testAddAllCopiesByReferenceIfPossible() {
+ LazyStringArrayList list1 = new LazyStringArrayList();
+ list1.add(STRING_A);
+ list1.add(BYTE_STRING_B);
+ list1.add(BYTE_STRING_C);
+
+ LazyStringArrayList list2 = new LazyStringArrayList();
+ list2.addAll(list1);
+
+ assertEquals(3, list2.size());
+ assertSame(STRING_A, list2.get(0));
+ assertSame(BYTE_STRING_B, list2.getByteString(1));
+ assertSame(BYTE_STRING_C, list2.getByteString(2));
+ }
+
+ public void testModificationWithIteration() {
+ LazyStringArrayList list = new LazyStringArrayList();
+ list.addAll(asList(STRING_A, STRING_B, STRING_C));
+ Iterator<String> iterator = list.iterator();
+ assertEquals(3, list.size());
+ assertEquals(STRING_A, list.get(0));
+ assertEquals(STRING_A, iterator.next());
+
+ // Does not structurally modify.
+ iterator = list.iterator();
+ list.set(0, STRING_B);
+ iterator.next();
+
+ list.remove(0);
+ try {
+ iterator.next();
+ fail();
+ } catch (ConcurrentModificationException e) {
+ // expected
+ }
+
+ iterator = list.iterator();
+ list.add(0, STRING_C);
+ try {
+ iterator.next();
+ fail();
+ } catch (ConcurrentModificationException e) {
+ // expected
+ }
+ }
+
+ public void testMakeImmutable() {
+ LazyStringArrayList list = new LazyStringArrayList();
+ list.add(STRING_A);
+ list.add(STRING_B);
+ list.add(STRING_C);
+ list.makeImmutable();
+ assertGenericListImmutable(list, STRING_A);
+
+ // LazyStringArrayList has extra methods not covered in the generic
+ // assertion.
+
+ try {
+ list.add(BYTE_STRING_A.toByteArray());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.add(BYTE_STRING_A);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAllByteArray(asList(BYTE_STRING_A.toByteArray()));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAllByteString(asList(BYTE_STRING_A));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.mergeFrom(new LazyStringArrayList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.set(0, BYTE_STRING_A.toByteArray());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.set(0, BYTE_STRING_A);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ }
+
+ public void testImmutabilityPropagation() {
+ LazyStringArrayList list = new LazyStringArrayList();
+ list.add(STRING_A);
+ list.makeImmutable();
+
+ assertGenericListImmutable(list.asByteStringList(), BYTE_STRING_A);
+
+ // Arrays use reference equality so need to retrieve the underlying value
+ // to properly test deep immutability.
+ List<byte[]> byteArrayList = list.asByteArrayList();
+ assertGenericListImmutable(byteArrayList, byteArrayList.get(0));
+ }
+
+ private static <T> void assertGenericListImmutable(List<T> list, T value) {
+ try {
+ list.add(value);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.add(0, value);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(asList(value));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(0, asList(value));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.clear();
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.remove(0);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.remove(value);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.removeAll(asList(value));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.retainAll(asList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.retainAll(asList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.set(0, value);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/LazyStringEndToEndTest.java b/java/core/src/test/java/com/google/protobuf/LazyStringEndToEndTest.java
new file mode 100644
index 00000000..0ef414aa
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/LazyStringEndToEndTest.java
@@ -0,0 +1,132 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// 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.UnittestProto;
+
+import junit.framework.TestCase;
+
+import java.io.IOException;
+
+/**
+ * Tests to make sure the lazy conversion of UTF8-encoded byte arrays to
+ * strings works correctly.
+ *
+ * @author jonp@google.com (Jon Perlow)
+ */
+public class LazyStringEndToEndTest extends TestCase {
+
+ private static ByteString TEST_ALL_TYPES_SERIALIZED_WITH_ILLEGAL_UTF8 =
+ ByteString.copyFrom(new byte[] {
+ 114, 4, -1, 0, -1, 0, -30, 2, 4, -1,
+ 0, -1, 0, -30, 2, 4, -1, 0, -1, 0, });
+
+ private ByteString encodedTestAllTypes;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ this.encodedTestAllTypes = UnittestProto.TestAllTypes.newBuilder()
+ .setOptionalString("foo")
+ .addRepeatedString("bar")
+ .addRepeatedString("baz")
+ .build()
+ .toByteString();
+ }
+
+ /**
+ * Tests that an invalid UTF8 string will roundtrip through a parse
+ * and serialization.
+ */
+ public void testParseAndSerialize() throws InvalidProtocolBufferException {
+ UnittestProto.TestAllTypes tV2 = UnittestProto.TestAllTypes.parseFrom(
+ TEST_ALL_TYPES_SERIALIZED_WITH_ILLEGAL_UTF8);
+ ByteString bytes = tV2.toByteString();
+ assertEquals(TEST_ALL_TYPES_SERIALIZED_WITH_ILLEGAL_UTF8, bytes);
+
+ tV2.getOptionalString();
+ bytes = tV2.toByteString();
+ assertEquals(TEST_ALL_TYPES_SERIALIZED_WITH_ILLEGAL_UTF8, bytes);
+ }
+
+ public void testParseAndWrite() throws IOException {
+ UnittestProto.TestAllTypes tV2 = UnittestProto.TestAllTypes.parseFrom(
+ TEST_ALL_TYPES_SERIALIZED_WITH_ILLEGAL_UTF8);
+ byte[] sink = new byte[TEST_ALL_TYPES_SERIALIZED_WITH_ILLEGAL_UTF8.size()];
+ CodedOutputStream outputStream = CodedOutputStream.newInstance(sink);
+ tV2.writeTo(outputStream);
+ outputStream.flush();
+ assertEquals(
+ TEST_ALL_TYPES_SERIALIZED_WITH_ILLEGAL_UTF8,
+ ByteString.copyFrom(sink));
+ }
+
+ public void testCaching() {
+ String a = "a";
+ String b = "b";
+ String c = "c";
+ UnittestProto.TestAllTypes proto = UnittestProto.TestAllTypes.newBuilder()
+ .setOptionalString(a)
+ .addRepeatedString(b)
+ .addRepeatedString(c)
+ .build();
+
+ // String should be the one we passed it.
+ assertSame(a, proto.getOptionalString());
+ assertSame(b, proto.getRepeatedString(0));
+ assertSame(c, proto.getRepeatedString(1));
+
+
+ // Ensure serialization keeps strings cached.
+ proto.toByteString();
+
+ // And now the string should stay cached.
+ assertSame(a, proto.getOptionalString());
+ assertSame(b, proto.getRepeatedString(0));
+ assertSame(c, proto.getRepeatedString(1));
+ }
+
+ public void testNoStringCachingIfOnlyBytesAccessed() throws Exception {
+ UnittestProto.TestAllTypes proto =
+ UnittestProto.TestAllTypes.parseFrom(encodedTestAllTypes);
+ ByteString optional = proto.getOptionalStringBytes();
+ assertSame(optional, proto.getOptionalStringBytes());
+ assertSame(optional, proto.toBuilder().getOptionalStringBytes());
+
+ ByteString repeated0 = proto.getRepeatedStringBytes(0);
+ ByteString repeated1 = proto.getRepeatedStringBytes(1);
+ assertSame(repeated0, proto.getRepeatedStringBytes(0));
+ assertSame(repeated1, proto.getRepeatedStringBytes(1));
+ assertSame(repeated0, proto.toBuilder().getRepeatedStringBytes(0));
+ assertSame(repeated1, proto.toBuilder().getRepeatedStringBytes(1));
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/LiteEqualsAndHashTest.java b/java/core/src/test/java/com/google/protobuf/LiteEqualsAndHashTest.java
new file mode 100644
index 00000000..035917c8
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/LiteEqualsAndHashTest.java
@@ -0,0 +1,108 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// 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.lite_equals_and_hash.LiteEqualsAndHash.Bar;
+import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash.BarPrime;
+import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash.Foo;
+
+import junit.framework.TestCase;
+
+/**
+ * Test generate equal and hash methods for the lite runtime.
+ *
+ * @author pbogle@google.com Phil Bogle
+ */
+public class LiteEqualsAndHashTest extends TestCase {
+
+ public void testEquals() throws Exception {
+ // Since the generated equals and hashCode methods for lite messages are a
+ // mostly complete subset of those for regular messages, we can mostly assume
+ // that the generated methods are already thoroughly tested by the regular tests.
+
+ // This test mostly just verifies is that a proto with
+ // optimize_for = LITE_RUNTIME and java_generates_equals_and_hash_compiles
+ // correctly when linked only against the lite library.
+
+ // We do however do some basic testing to make sure that equals is actually
+ // overriden to test for value equality rather than simple object equality.
+
+ // Check that two identical objs are equal.
+ Foo foo1a = Foo.newBuilder()
+ .setValue(1)
+ .addBar(Bar.newBuilder().setName("foo1"))
+ .build();
+ Foo foo1b = Foo.newBuilder()
+ .setValue(1)
+ .addBar(Bar.newBuilder().setName("foo1"))
+ .build();
+ Foo foo2 = Foo.newBuilder()
+ .setValue(1)
+ .addBar(Bar.newBuilder().setName("foo2"))
+ .build();
+
+ // Check that equals is doing value rather than object equality.
+ assertEquals(foo1a, foo1b);
+ assertEquals(foo1a.hashCode(), foo1b.hashCode());
+
+ // Check that a diffeent object is not equal.
+ assertFalse(foo1a.equals(foo2));
+
+ // Check that two objects which have different types but the same field values are not
+ // considered to be equal.
+ Bar bar = Bar.newBuilder().setName("bar").build();
+ BarPrime barPrime = BarPrime.newBuilder().setName("bar").build();
+ assertFalse(bar.equals(barPrime));
+ }
+
+ public void testEqualsAndHashCodeWithUnknownFields() throws InvalidProtocolBufferException {
+ Foo fooWithOnlyValue = Foo.newBuilder()
+ .setValue(1)
+ .build();
+
+ Foo fooWithValueAndExtension = fooWithOnlyValue.toBuilder()
+ .setValue(1)
+ .setExtension(Bar.fooExt, Bar.newBuilder()
+ .setName("name")
+ .build())
+ .build();
+
+ Foo fooWithValueAndUnknownFields = Foo.parseFrom(fooWithValueAndExtension.toByteArray());
+
+ assertEqualsAndHashCodeAreFalse(fooWithOnlyValue, fooWithValueAndUnknownFields);
+ assertEqualsAndHashCodeAreFalse(fooWithValueAndExtension, fooWithValueAndUnknownFields);
+ }
+
+ private void assertEqualsAndHashCodeAreFalse(Object o1, Object o2) {
+ assertFalse(o1.equals(o2));
+ assertFalse(o1.hashCode() == o2.hashCode());
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/LiteTest.java b/java/core/src/test/java/com/google/protobuf/LiteTest.java
new file mode 100644
index 00000000..b1f298ff
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/LiteTest.java
@@ -0,0 +1,1462 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// 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 static java.util.Collections.emptyList;
+import static java.util.Collections.singletonList;
+
+import com.google.protobuf.UnittestLite;
+import com.google.protobuf.UnittestLite.ForeignEnumLite;
+import com.google.protobuf.UnittestLite.ForeignMessageLite;
+import com.google.protobuf.UnittestLite.TestAllExtensionsLite;
+import com.google.protobuf.UnittestLite.TestAllTypesLite;
+import com.google.protobuf.UnittestLite.TestAllTypesLite.NestedMessage;
+import com.google.protobuf.UnittestLite.TestAllTypesLite.OneofFieldCase;
+import com.google.protobuf.UnittestLite.TestAllTypesLite.OptionalGroup;
+import com.google.protobuf.UnittestLite.TestAllTypesLite.RepeatedGroup;
+import com.google.protobuf.UnittestLite.TestAllTypesLiteOrBuilder;
+import com.google.protobuf.UnittestLite.TestNestedExtensionLite;
+
+import junit.framework.TestCase;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
+/**
+ * Test lite runtime.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public class LiteTest extends TestCase {
+ public void setUp() throws Exception {
+ // Test that nested extensions are initialized correctly even if the outer
+ // class has not been accessed directly. This was once a bug with lite
+ // messages.
+ //
+ // We put this in setUp() rather than in its own test method because we
+ // need to make sure it runs before any actual tests.
+ assertTrue(TestNestedExtensionLite.nestedExtension != null);
+ }
+
+ public void testLite() throws Exception {
+ // Since lite messages are a subset of regular messages, we can mostly
+ // assume that the functionality of lite messages is already thoroughly
+ // tested by the regular tests. All this test really verifies is that
+ // a proto with optimize_for = LITE_RUNTIME compiles correctly when
+ // linked only against the lite library. That is all tested at compile
+ // time, leaving not much to do in this method. Let's just do some random
+ // stuff to make sure the lite message is actually here and usable.
+
+ TestAllTypesLite message =
+ TestAllTypesLite.newBuilder()
+ .setOptionalInt32(123)
+ .addRepeatedString("hello")
+ .setOptionalNestedMessage(
+ TestAllTypesLite.NestedMessage.newBuilder().setBb(7))
+ .build();
+
+ ByteString data = message.toByteString();
+
+ TestAllTypesLite message2 = TestAllTypesLite.parseFrom(data);
+
+ assertEquals(123, message2.getOptionalInt32());
+ assertEquals(1, message2.getRepeatedStringCount());
+ assertEquals("hello", message2.getRepeatedString(0));
+ assertEquals(7, message2.getOptionalNestedMessage().getBb());
+ }
+
+ public void testLiteExtensions() throws Exception {
+ // TODO(kenton): Unlike other features of the lite library, extensions are
+ // implemented completely differently from the regular library. We
+ // should probably test them more thoroughly.
+
+ TestAllExtensionsLite message =
+ TestAllExtensionsLite.newBuilder()
+ .setExtension(UnittestLite.optionalInt32ExtensionLite, 123)
+ .addExtension(UnittestLite.repeatedStringExtensionLite, "hello")
+ .setExtension(UnittestLite.optionalNestedEnumExtensionLite,
+ TestAllTypesLite.NestedEnum.BAZ)
+ .setExtension(UnittestLite.optionalNestedMessageExtensionLite,
+ TestAllTypesLite.NestedMessage.newBuilder().setBb(7).build())
+ .build();
+
+ // Test copying a message, since coping extensions actually does use a
+ // different code path between lite and regular libraries, and as of this
+ // writing, parsing hasn't been implemented yet.
+ TestAllExtensionsLite message2 = message.toBuilder().build();
+
+ assertEquals(123, (int) message2.getExtension(
+ UnittestLite.optionalInt32ExtensionLite));
+ assertEquals(1, message2.getExtensionCount(
+ UnittestLite.repeatedStringExtensionLite));
+ assertEquals(1, message2.getExtension(
+ UnittestLite.repeatedStringExtensionLite).size());
+ assertEquals("hello", message2.getExtension(
+ UnittestLite.repeatedStringExtensionLite, 0));
+ assertEquals(TestAllTypesLite.NestedEnum.BAZ, message2.getExtension(
+ UnittestLite.optionalNestedEnumExtensionLite));
+ assertEquals(7, message2.getExtension(
+ UnittestLite.optionalNestedMessageExtensionLite).getBb());
+ }
+
+ public void testSerialize() throws Exception {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ TestAllTypesLite expected =
+ TestAllTypesLite.newBuilder()
+ .setOptionalInt32(123)
+ .addRepeatedString("hello")
+ .setOptionalNestedMessage(
+ TestAllTypesLite.NestedMessage.newBuilder().setBb(7))
+ .build();
+ ObjectOutputStream out = new ObjectOutputStream(baos);
+ try {
+ out.writeObject(expected);
+ } finally {
+ out.close();
+ }
+ ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+ ObjectInputStream in = new ObjectInputStream(bais);
+ TestAllTypesLite actual = (TestAllTypesLite) in.readObject();
+ assertEquals(expected.getOptionalInt32(), actual.getOptionalInt32());
+ assertEquals(expected.getRepeatedStringCount(),
+ actual.getRepeatedStringCount());
+ assertEquals(expected.getRepeatedString(0),
+ actual.getRepeatedString(0));
+ assertEquals(expected.getOptionalNestedMessage().getBb(),
+ actual.getOptionalNestedMessage().getBb());
+ }
+
+ public void testClone() {
+ TestAllTypesLite.Builder expected = TestAllTypesLite.newBuilder()
+ .setOptionalInt32(123);
+ assertEquals(
+ expected.getOptionalInt32(), expected.clone().getOptionalInt32());
+
+ TestAllExtensionsLite.Builder expected2 = TestAllExtensionsLite.newBuilder()
+ .setExtension(UnittestLite.optionalInt32ExtensionLite, 123);
+ assertEquals(
+ expected2.getExtension(UnittestLite.optionalInt32ExtensionLite),
+ expected2.clone().getExtension(UnittestLite.optionalInt32ExtensionLite));
+ }
+
+ public void testAddAll() {
+ try {
+ TestAllTypesLite.newBuilder()
+ .addAllRepeatedBytes(null);
+ fail();
+ } catch (NullPointerException e) {
+ // expected.
+ }
+ }
+
+ public void testSanityCopyOnWrite() throws InvalidProtocolBufferException {
+ // Since builders are implemented as a thin wrapper around a message
+ // instance, we attempt to verify that we can't cause the builder to modify
+ // a produced message.
+
+ TestAllTypesLite.Builder builder = TestAllTypesLite.newBuilder();
+ TestAllTypesLite message = builder.build();
+ TestAllTypesLite messageAfterBuild;
+ builder.setOptionalBool(true);
+ assertEquals(false, message.getOptionalBool());
+ assertEquals(true, builder.getOptionalBool());
+ messageAfterBuild = builder.build();
+ assertEquals(true, messageAfterBuild.getOptionalBool());
+ assertEquals(false, message.getOptionalBool());
+ builder.clearOptionalBool();
+ assertEquals(false, builder.getOptionalBool());
+ assertEquals(true, messageAfterBuild.getOptionalBool());
+
+ message = builder.build();
+ builder.setOptionalBytes(ByteString.copyFromUtf8("hi"));
+ assertEquals(ByteString.EMPTY, message.getOptionalBytes());
+ assertEquals(ByteString.copyFromUtf8("hi"), builder.getOptionalBytes());
+ messageAfterBuild = builder.build();
+ assertEquals(
+ ByteString.copyFromUtf8("hi"), messageAfterBuild.getOptionalBytes());
+ assertEquals(ByteString.EMPTY, message.getOptionalBytes());
+ builder.clearOptionalBytes();
+ assertEquals(ByteString.EMPTY, builder.getOptionalBytes());
+ assertEquals(
+ ByteString.copyFromUtf8("hi"), messageAfterBuild.getOptionalBytes());
+
+ message = builder.build();
+ builder.setOptionalCord("hi");
+ assertEquals("", message.getOptionalCord());
+ assertEquals("hi", builder.getOptionalCord());
+ messageAfterBuild = builder.build();
+ assertEquals("hi", messageAfterBuild.getOptionalCord());
+ assertEquals("", message.getOptionalCord());
+ builder.clearOptionalCord();
+ assertEquals("", builder.getOptionalCord());
+ assertEquals("hi", messageAfterBuild.getOptionalCord());
+
+ message = builder.build();
+ builder.setOptionalCordBytes(ByteString.copyFromUtf8("no"));
+ assertEquals(ByteString.EMPTY, message.getOptionalCordBytes());
+ assertEquals(ByteString.copyFromUtf8("no"), builder.getOptionalCordBytes());
+ messageAfterBuild = builder.build();
+ assertEquals(
+ ByteString.copyFromUtf8("no"),
+ messageAfterBuild.getOptionalCordBytes());
+ assertEquals(ByteString.EMPTY, message.getOptionalCordBytes());
+ builder.clearOptionalCord();
+ assertEquals(ByteString.EMPTY, builder.getOptionalCordBytes());
+ assertEquals(
+ ByteString.copyFromUtf8("no"),
+ messageAfterBuild.getOptionalCordBytes());
+
+ message = builder.build();
+ builder.setOptionalDouble(1);
+ assertEquals(0D, message.getOptionalDouble());
+ assertEquals(1D, builder.getOptionalDouble());
+ messageAfterBuild = builder.build();
+ assertEquals(1D, messageAfterBuild.getOptionalDouble());
+ assertEquals(0D, message.getOptionalDouble());
+ builder.clearOptionalDouble();
+ assertEquals(0D, builder.getOptionalDouble());
+ assertEquals(1D, messageAfterBuild.getOptionalDouble());
+
+ message = builder.build();
+ builder.setOptionalFixed32(1);
+ assertEquals(0, message.getOptionalFixed32());
+ assertEquals(1, builder.getOptionalFixed32());
+ messageAfterBuild = builder.build();
+ assertEquals(1, messageAfterBuild.getOptionalFixed32());
+ assertEquals(0, message.getOptionalFixed32());
+ builder.clearOptionalFixed32();
+ assertEquals(0, builder.getOptionalFixed32());
+ assertEquals(1, messageAfterBuild.getOptionalFixed32());
+
+ message = builder.build();
+ builder.setOptionalFixed64(1);
+ assertEquals(0L, message.getOptionalFixed64());
+ assertEquals(1L, builder.getOptionalFixed64());
+ messageAfterBuild = builder.build();
+ assertEquals(1L, messageAfterBuild.getOptionalFixed64());
+ assertEquals(0L, message.getOptionalFixed64());
+ builder.clearOptionalFixed64();
+ assertEquals(0L, builder.getOptionalFixed64());
+ assertEquals(1L, messageAfterBuild.getOptionalFixed64());
+
+ message = builder.build();
+ builder.setOptionalFloat(1);
+ assertEquals(0F, message.getOptionalFloat());
+ assertEquals(1F, builder.getOptionalFloat());
+ messageAfterBuild = builder.build();
+ assertEquals(1F, messageAfterBuild.getOptionalFloat());
+ assertEquals(0F, message.getOptionalFloat());
+ builder.clearOptionalFloat();
+ assertEquals(0F, builder.getOptionalFloat());
+ assertEquals(1F, messageAfterBuild.getOptionalFloat());
+
+ message = builder.build();
+ builder.setOptionalForeignEnum(ForeignEnumLite.FOREIGN_LITE_BAR);
+ assertEquals(
+ ForeignEnumLite.FOREIGN_LITE_FOO, message.getOptionalForeignEnum());
+ assertEquals(
+ ForeignEnumLite.FOREIGN_LITE_BAR, builder.getOptionalForeignEnum());
+ messageAfterBuild = builder.build();
+ assertEquals(
+ ForeignEnumLite.FOREIGN_LITE_BAR,
+ messageAfterBuild.getOptionalForeignEnum());
+ assertEquals(
+ ForeignEnumLite.FOREIGN_LITE_FOO, message.getOptionalForeignEnum());
+ builder.clearOptionalForeignEnum();
+ assertEquals(
+ ForeignEnumLite.FOREIGN_LITE_FOO, builder.getOptionalForeignEnum());
+ assertEquals(
+ ForeignEnumLite.FOREIGN_LITE_BAR,
+ messageAfterBuild.getOptionalForeignEnum());
+
+ message = builder.build();
+ ForeignMessageLite foreignMessage = ForeignMessageLite.newBuilder()
+ .setC(1)
+ .build();
+ builder.setOptionalForeignMessage(foreignMessage);
+ assertEquals(
+ ForeignMessageLite.getDefaultInstance(),
+ message.getOptionalForeignMessage());
+ assertEquals(foreignMessage, builder.getOptionalForeignMessage());
+ messageAfterBuild = builder.build();
+ assertEquals(foreignMessage, messageAfterBuild.getOptionalForeignMessage());
+ assertEquals(
+ ForeignMessageLite.getDefaultInstance(),
+ message.getOptionalForeignMessage());
+ builder.clearOptionalForeignMessage();
+ assertEquals(
+ ForeignMessageLite.getDefaultInstance(),
+ builder.getOptionalForeignMessage());
+ assertEquals(foreignMessage, messageAfterBuild.getOptionalForeignMessage());
+
+ message = builder.build();
+ ForeignMessageLite.Builder foreignMessageBuilder =
+ ForeignMessageLite.newBuilder()
+ .setC(3);
+ builder.setOptionalForeignMessage(foreignMessageBuilder);
+ assertEquals(
+ ForeignMessageLite.getDefaultInstance(),
+ message.getOptionalForeignMessage());
+ // LITE_RUNTIME doesn't implement equals so we compare on a property and
+ // ensure the property isn't set on foreignMessage.
+ assertEquals(3, builder.getOptionalForeignMessage().getC());
+ messageAfterBuild = builder.build();
+ assertEquals(3, messageAfterBuild.getOptionalForeignMessage().getC());
+ assertEquals(
+ ForeignMessageLite.getDefaultInstance(),
+ message.getOptionalForeignMessage());
+ builder.clearOptionalForeignMessage();
+ assertEquals(
+ ForeignMessageLite.getDefaultInstance(),
+ builder.getOptionalForeignMessage());
+ assertEquals(3, messageAfterBuild.getOptionalForeignMessage().getC());
+
+ message = builder.build();
+ OptionalGroup optionalGroup = OptionalGroup.newBuilder()
+ .setA(1)
+ .build();
+ builder.setOptionalGroup(optionalGroup);
+ assertEquals(
+ OptionalGroup.getDefaultInstance(), message.getOptionalGroup());
+ assertEquals(optionalGroup, builder.getOptionalGroup());
+ messageAfterBuild = builder.build();
+ assertEquals(optionalGroup, messageAfterBuild.getOptionalGroup());
+ assertEquals(
+ OptionalGroup.getDefaultInstance(), message.getOptionalGroup());
+ builder.clearOptionalGroup();
+ assertEquals(
+ OptionalGroup.getDefaultInstance(), builder.getOptionalGroup());
+ assertEquals(optionalGroup, messageAfterBuild.getOptionalGroup());
+
+ message = builder.build();
+ OptionalGroup.Builder optionalGroupBuilder = OptionalGroup.newBuilder()
+ .setA(3);
+ builder.setOptionalGroup(optionalGroupBuilder);
+ assertEquals(
+ OptionalGroup.getDefaultInstance(), message.getOptionalGroup());
+ // LITE_RUNTIME doesn't implement equals so we compare on a property and
+ // ensure the property isn't set on optionalGroup.
+ assertEquals(3, builder.getOptionalGroup().getA());
+ messageAfterBuild = builder.build();
+ assertEquals(3, messageAfterBuild.getOptionalGroup().getA());
+ assertEquals(
+ OptionalGroup.getDefaultInstance(), message.getOptionalGroup());
+ builder.clearOptionalGroup();
+ assertEquals(
+ OptionalGroup.getDefaultInstance(), builder.getOptionalGroup());
+ assertEquals(3, messageAfterBuild.getOptionalGroup().getA());
+
+ message = builder.build();
+ builder.setOptionalInt32(1);
+ assertEquals(0, message.getOptionalInt32());
+ assertEquals(1, builder.getOptionalInt32());
+ messageAfterBuild = builder.build();
+ assertEquals(1, messageAfterBuild.getOptionalInt32());
+ assertEquals(0, message.getOptionalInt32());
+ builder.clearOptionalInt32();
+ assertEquals(0, builder.getOptionalInt32());
+ assertEquals(1, messageAfterBuild.getOptionalInt32());
+
+ message = builder.build();
+ builder.setOptionalInt64(1);
+ assertEquals(0L, message.getOptionalInt64());
+ assertEquals(1L, builder.getOptionalInt64());
+ messageAfterBuild = builder.build();
+ assertEquals(1L, messageAfterBuild.getOptionalInt64());
+ assertEquals(0L, message.getOptionalInt64());
+ builder.clearOptionalInt64();
+ assertEquals(0L, builder.getOptionalInt64());
+ assertEquals(1L, messageAfterBuild.getOptionalInt64());
+
+ message = builder.build();
+ NestedMessage nestedMessage = NestedMessage.newBuilder()
+ .setBb(1)
+ .build();
+ builder.setOptionalLazyMessage(nestedMessage);
+ assertEquals(
+ NestedMessage.getDefaultInstance(),
+ message.getOptionalLazyMessage());
+ assertEquals(nestedMessage, builder.getOptionalLazyMessage());
+ messageAfterBuild = builder.build();
+ assertEquals(nestedMessage, messageAfterBuild.getOptionalLazyMessage());
+ assertEquals(
+ NestedMessage.getDefaultInstance(),
+ message.getOptionalLazyMessage());
+ builder.clearOptionalLazyMessage();
+ assertEquals(
+ NestedMessage.getDefaultInstance(), builder.getOptionalLazyMessage());
+ assertEquals(nestedMessage, messageAfterBuild.getOptionalLazyMessage());
+
+ message = builder.build();
+ NestedMessage.Builder nestedMessageBuilder =
+ NestedMessage.newBuilder()
+ .setBb(3);
+ builder.setOptionalLazyMessage(nestedMessageBuilder);
+ assertEquals(
+ NestedMessage.getDefaultInstance(),
+ message.getOptionalLazyMessage());
+ // LITE_RUNTIME doesn't implement equals so we compare on a property.
+ assertEquals(3, builder.getOptionalLazyMessage().getBb());
+ messageAfterBuild = builder.build();
+ assertEquals(3, messageAfterBuild.getOptionalLazyMessage().getBb());
+ assertEquals(
+ NestedMessage.getDefaultInstance(),
+ message.getOptionalLazyMessage());
+ builder.clearOptionalLazyMessage();
+ assertEquals(
+ NestedMessage.getDefaultInstance(), builder.getOptionalLazyMessage());
+ assertEquals(3, messageAfterBuild.getOptionalLazyMessage().getBb());
+
+ message = builder.build();
+ builder.setOptionalSfixed32(1);
+ assertEquals(0, message.getOptionalSfixed32());
+ assertEquals(1, builder.getOptionalSfixed32());
+ messageAfterBuild = builder.build();
+ assertEquals(1, messageAfterBuild.getOptionalSfixed32());
+ assertEquals(0, message.getOptionalSfixed32());
+ builder.clearOptionalSfixed32();
+ assertEquals(0, builder.getOptionalSfixed32());
+ assertEquals(1, messageAfterBuild.getOptionalSfixed32());
+
+ message = builder.build();
+ builder.setOptionalSfixed64(1);
+ assertEquals(0L, message.getOptionalSfixed64());
+ assertEquals(1L, builder.getOptionalSfixed64());
+ messageAfterBuild = builder.build();
+ assertEquals(1L, messageAfterBuild.getOptionalSfixed64());
+ assertEquals(0L, message.getOptionalSfixed64());
+ builder.clearOptionalSfixed64();
+ assertEquals(0L, builder.getOptionalSfixed64());
+ assertEquals(1L, messageAfterBuild.getOptionalSfixed64());
+
+ message = builder.build();
+ builder.setOptionalSint32(1);
+ assertEquals(0, message.getOptionalSint32());
+ assertEquals(1, builder.getOptionalSint32());
+ messageAfterBuild = builder.build();
+ assertEquals(1, messageAfterBuild.getOptionalSint32());
+ builder.clearOptionalSint32();
+ assertEquals(0, builder.getOptionalSint32());
+ assertEquals(1, messageAfterBuild.getOptionalSint32());
+
+ message = builder.build();
+ builder.setOptionalSint64(1);
+ assertEquals(0L, message.getOptionalSint64());
+ assertEquals(1L, builder.getOptionalSint64());
+ messageAfterBuild = builder.build();
+ assertEquals(1L, messageAfterBuild.getOptionalSint64());
+ assertEquals(0L, message.getOptionalSint64());
+ builder.clearOptionalSint64();
+ assertEquals(0L, builder.getOptionalSint64());
+ assertEquals(1L, messageAfterBuild.getOptionalSint64());
+
+ message = builder.build();
+ builder.setOptionalString("hi");
+ assertEquals("", message.getOptionalString());
+ assertEquals("hi", builder.getOptionalString());
+ messageAfterBuild = builder.build();
+ assertEquals("hi", messageAfterBuild.getOptionalString());
+ assertEquals("", message.getOptionalString());
+ builder.clearOptionalString();
+ assertEquals("", builder.getOptionalString());
+ assertEquals("hi", messageAfterBuild.getOptionalString());
+
+ message = builder.build();
+ builder.setOptionalStringBytes(ByteString.copyFromUtf8("no"));
+ assertEquals(ByteString.EMPTY, message.getOptionalStringBytes());
+ assertEquals(
+ ByteString.copyFromUtf8("no"), builder.getOptionalStringBytes());
+ messageAfterBuild = builder.build();
+ assertEquals(
+ ByteString.copyFromUtf8("no"),
+ messageAfterBuild.getOptionalStringBytes());
+ assertEquals(ByteString.EMPTY, message.getOptionalStringBytes());
+ builder.clearOptionalString();
+ assertEquals(ByteString.EMPTY, builder.getOptionalStringBytes());
+ assertEquals(
+ ByteString.copyFromUtf8("no"),
+ messageAfterBuild.getOptionalStringBytes());
+
+ message = builder.build();
+ builder.setOptionalStringPiece("hi");
+ assertEquals("", message.getOptionalStringPiece());
+ assertEquals("hi", builder.getOptionalStringPiece());
+ messageAfterBuild = builder.build();
+ assertEquals("hi", messageAfterBuild.getOptionalStringPiece());
+ assertEquals("", message.getOptionalStringPiece());
+ builder.clearOptionalStringPiece();
+ assertEquals("", builder.getOptionalStringPiece());
+ assertEquals("hi", messageAfterBuild.getOptionalStringPiece());
+
+ message = builder.build();
+ builder.setOptionalStringPieceBytes(ByteString.copyFromUtf8("no"));
+ assertEquals(ByteString.EMPTY, message.getOptionalStringPieceBytes());
+ assertEquals(
+ ByteString.copyFromUtf8("no"), builder.getOptionalStringPieceBytes());
+ messageAfterBuild = builder.build();
+ assertEquals(
+ ByteString.copyFromUtf8("no"),
+ messageAfterBuild.getOptionalStringPieceBytes());
+ assertEquals(ByteString.EMPTY, message.getOptionalStringPieceBytes());
+ builder.clearOptionalStringPiece();
+ assertEquals(ByteString.EMPTY, builder.getOptionalStringPieceBytes());
+ assertEquals(
+ ByteString.copyFromUtf8("no"),
+ messageAfterBuild.getOptionalStringPieceBytes());
+
+ message = builder.build();
+ builder.setOptionalUint32(1);
+ assertEquals(0, message.getOptionalUint32());
+ assertEquals(1, builder.getOptionalUint32());
+ messageAfterBuild = builder.build();
+ assertEquals(1, messageAfterBuild.getOptionalUint32());
+ assertEquals(0, message.getOptionalUint32());
+ builder.clearOptionalUint32();
+ assertEquals(0, builder.getOptionalUint32());
+ assertEquals(1, messageAfterBuild.getOptionalUint32());
+
+ message = builder.build();
+ builder.setOptionalUint64(1);
+ assertEquals(0L, message.getOptionalUint64());
+ assertEquals(1L, builder.getOptionalUint64());
+ messageAfterBuild = builder.build();
+ assertEquals(1L, messageAfterBuild.getOptionalUint64());
+ assertEquals(0L, message.getOptionalUint64());
+ builder.clearOptionalUint64();
+ assertEquals(0L, builder.getOptionalUint64());
+ assertEquals(1L, messageAfterBuild.getOptionalUint64());
+
+ message = builder.build();
+ builder.addAllRepeatedBool(singletonList(true));
+ assertEquals(emptyList(), message.getRepeatedBoolList());
+ assertEquals(singletonList(true), builder.getRepeatedBoolList());
+ assertEquals(emptyList(), message.getRepeatedBoolList());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedBool();
+ assertEquals(emptyList(), builder.getRepeatedBoolList());
+ assertEquals(singletonList(true), messageAfterBuild.getRepeatedBoolList());
+
+ message = builder.build();
+ builder.addAllRepeatedBytes(singletonList(ByteString.copyFromUtf8("hi")));
+ assertEquals(emptyList(), message.getRepeatedBytesList());
+ assertEquals(
+ singletonList(ByteString.copyFromUtf8("hi")),
+ builder.getRepeatedBytesList());
+ assertEquals(emptyList(), message.getRepeatedBytesList());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedBytes();
+ assertEquals(emptyList(), builder.getRepeatedBytesList());
+ assertEquals(
+ singletonList(ByteString.copyFromUtf8("hi")),
+ messageAfterBuild.getRepeatedBytesList());
+
+ message = builder.build();
+ builder.addAllRepeatedCord(singletonList("hi"));
+ assertEquals(emptyList(), message.getRepeatedCordList());
+ assertEquals(singletonList("hi"), builder.getRepeatedCordList());
+ assertEquals(emptyList(), message.getRepeatedCordList());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedCord();
+ assertEquals(emptyList(), builder.getRepeatedCordList());
+ assertEquals(singletonList("hi"), messageAfterBuild.getRepeatedCordList());
+
+ message = builder.build();
+ builder.addAllRepeatedDouble(singletonList(1D));
+ assertEquals(emptyList(), message.getRepeatedDoubleList());
+ assertEquals(singletonList(1D), builder.getRepeatedDoubleList());
+ assertEquals(emptyList(), message.getRepeatedDoubleList());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedDouble();
+ assertEquals(emptyList(), builder.getRepeatedDoubleList());
+ assertEquals(singletonList(1D), messageAfterBuild.getRepeatedDoubleList());
+
+ message = builder.build();
+ builder.addAllRepeatedFixed32(singletonList(1));
+ assertEquals(emptyList(), message.getRepeatedFixed32List());
+ assertEquals(singletonList(1), builder.getRepeatedFixed32List());
+ assertEquals(emptyList(), message.getRepeatedFixed32List());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedFixed32();
+ assertEquals(emptyList(), builder.getRepeatedFixed32List());
+ assertEquals(singletonList(1), messageAfterBuild.getRepeatedFixed32List());
+
+ message = builder.build();
+ builder.addAllRepeatedFixed64(singletonList(1L));
+ assertEquals(emptyList(), message.getRepeatedFixed64List());
+ assertEquals(singletonList(1L), builder.getRepeatedFixed64List());
+ assertEquals(emptyList(), message.getRepeatedFixed64List());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedFixed64();
+ assertEquals(emptyList(), builder.getRepeatedFixed64List());
+ assertEquals(singletonList(1L), messageAfterBuild.getRepeatedFixed64List());
+
+ message = builder.build();
+ builder.addAllRepeatedFloat(singletonList(1F));
+ assertEquals(emptyList(), message.getRepeatedFloatList());
+ assertEquals(singletonList(1F), builder.getRepeatedFloatList());
+ assertEquals(emptyList(), message.getRepeatedFloatList());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedFloat();
+ assertEquals(emptyList(), builder.getRepeatedFloatList());
+ assertEquals(singletonList(1F), messageAfterBuild.getRepeatedFloatList());
+
+ message = builder.build();
+ builder.addAllRepeatedForeignEnum(
+ singletonList(ForeignEnumLite.FOREIGN_LITE_BAR));
+ assertEquals(emptyList(), message.getRepeatedForeignEnumList());
+ assertEquals(
+ singletonList(ForeignEnumLite.FOREIGN_LITE_BAR),
+ builder.getRepeatedForeignEnumList());
+ assertEquals(emptyList(), message.getRepeatedForeignEnumList());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedForeignEnum();
+ assertEquals(emptyList(), builder.getRepeatedForeignEnumList());
+ assertEquals(
+ singletonList(ForeignEnumLite.FOREIGN_LITE_BAR),
+ messageAfterBuild.getRepeatedForeignEnumList());
+
+ message = builder.build();
+ builder.addAllRepeatedForeignMessage(singletonList(foreignMessage));
+ assertEquals(emptyList(), message.getRepeatedForeignMessageList());
+ assertEquals(
+ singletonList(foreignMessage), builder.getRepeatedForeignMessageList());
+ assertEquals(emptyList(), message.getRepeatedForeignMessageList());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedForeignMessage();
+ assertEquals(emptyList(), builder.getRepeatedForeignMessageList());
+ assertEquals(
+ singletonList(foreignMessage),
+ messageAfterBuild.getRepeatedForeignMessageList());
+
+ message = builder.build();
+ builder.addAllRepeatedGroup(
+ singletonList(RepeatedGroup.getDefaultInstance()));
+ assertEquals(emptyList(), message.getRepeatedGroupList());
+ assertEquals(
+ singletonList(RepeatedGroup.getDefaultInstance()),
+ builder.getRepeatedGroupList());
+ assertEquals(emptyList(), message.getRepeatedGroupList());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedGroup();
+ assertEquals(emptyList(), builder.getRepeatedGroupList());
+ assertEquals(
+ singletonList(RepeatedGroup.getDefaultInstance()),
+ messageAfterBuild.getRepeatedGroupList());
+
+ message = builder.build();
+ builder.addAllRepeatedInt32(singletonList(1));
+ assertEquals(emptyList(), message.getRepeatedInt32List());
+ assertEquals(singletonList(1), builder.getRepeatedInt32List());
+ assertEquals(emptyList(), message.getRepeatedInt32List());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedInt32();
+ assertEquals(emptyList(), builder.getRepeatedInt32List());
+ assertEquals(singletonList(1), messageAfterBuild.getRepeatedInt32List());
+
+ message = builder.build();
+ builder.addAllRepeatedInt64(singletonList(1L));
+ assertEquals(emptyList(), message.getRepeatedInt64List());
+ assertEquals(singletonList(1L), builder.getRepeatedInt64List());
+ assertEquals(emptyList(), message.getRepeatedInt64List());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedInt64();
+ assertEquals(emptyList(), builder.getRepeatedInt64List());
+ assertEquals(singletonList(1L), messageAfterBuild.getRepeatedInt64List());
+
+ message = builder.build();
+ builder.addAllRepeatedLazyMessage(singletonList(nestedMessage));
+ assertEquals(emptyList(), message.getRepeatedLazyMessageList());
+ assertEquals(
+ singletonList(nestedMessage), builder.getRepeatedLazyMessageList());
+ assertEquals(emptyList(), message.getRepeatedLazyMessageList());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedLazyMessage();
+ assertEquals(emptyList(), builder.getRepeatedLazyMessageList());
+ assertEquals(
+ singletonList(nestedMessage),
+ messageAfterBuild.getRepeatedLazyMessageList());
+
+ message = builder.build();
+ builder.addAllRepeatedSfixed32(singletonList(1));
+ assertEquals(emptyList(), message.getRepeatedSfixed32List());
+ assertEquals(singletonList(1), builder.getRepeatedSfixed32List());
+ assertEquals(emptyList(), message.getRepeatedSfixed32List());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedSfixed32();
+ assertEquals(emptyList(), builder.getRepeatedSfixed32List());
+ assertEquals(singletonList(1), messageAfterBuild.getRepeatedSfixed32List());
+
+ message = builder.build();
+ builder.addAllRepeatedSfixed64(singletonList(1L));
+ assertEquals(emptyList(), message.getRepeatedSfixed64List());
+ assertEquals(singletonList(1L), builder.getRepeatedSfixed64List());
+ assertEquals(emptyList(), message.getRepeatedSfixed64List());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedSfixed64();
+ assertEquals(emptyList(), builder.getRepeatedSfixed64List());
+ assertEquals(
+ singletonList(1L), messageAfterBuild.getRepeatedSfixed64List());
+
+ message = builder.build();
+ builder.addAllRepeatedSint32(singletonList(1));
+ assertEquals(emptyList(), message.getRepeatedSint32List());
+ assertEquals(singletonList(1), builder.getRepeatedSint32List());
+ assertEquals(emptyList(), message.getRepeatedSint32List());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedSint32();
+ assertEquals(emptyList(), builder.getRepeatedSint32List());
+ assertEquals(singletonList(1), messageAfterBuild.getRepeatedSint32List());
+
+ message = builder.build();
+ builder.addAllRepeatedSint64(singletonList(1L));
+ assertEquals(emptyList(), message.getRepeatedSint64List());
+ assertEquals(singletonList(1L), builder.getRepeatedSint64List());
+ assertEquals(emptyList(), message.getRepeatedSint64List());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedSint64();
+ assertEquals(emptyList(), builder.getRepeatedSint64List());
+ assertEquals(singletonList(1L), messageAfterBuild.getRepeatedSint64List());
+
+ message = builder.build();
+ builder.addAllRepeatedString(singletonList("hi"));
+ assertEquals(emptyList(), message.getRepeatedStringList());
+ assertEquals(singletonList("hi"), builder.getRepeatedStringList());
+ assertEquals(emptyList(), message.getRepeatedStringList());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedString();
+ assertEquals(emptyList(), builder.getRepeatedStringList());
+ assertEquals(
+ singletonList("hi"), messageAfterBuild.getRepeatedStringList());
+
+ message = builder.build();
+ builder.addAllRepeatedStringPiece(singletonList("hi"));
+ assertEquals(emptyList(), message.getRepeatedStringPieceList());
+ assertEquals(singletonList("hi"), builder.getRepeatedStringPieceList());
+ assertEquals(emptyList(), message.getRepeatedStringPieceList());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedStringPiece();
+ assertEquals(emptyList(), builder.getRepeatedStringPieceList());
+ assertEquals(
+ singletonList("hi"), messageAfterBuild.getRepeatedStringPieceList());
+
+ message = builder.build();
+ builder.addAllRepeatedUint32(singletonList(1));
+ assertEquals(emptyList(), message.getRepeatedUint32List());
+ assertEquals(singletonList(1), builder.getRepeatedUint32List());
+ assertEquals(emptyList(), message.getRepeatedUint32List());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedUint32();
+ assertEquals(emptyList(), builder.getRepeatedUint32List());
+ assertEquals(singletonList(1), messageAfterBuild.getRepeatedUint32List());
+
+ message = builder.build();
+ builder.addAllRepeatedUint64(singletonList(1L));
+ assertEquals(emptyList(), message.getRepeatedUint64List());
+ assertEquals(singletonList(1L), builder.getRepeatedUint64List());
+ assertEquals(emptyList(), message.getRepeatedUint64List());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedUint64();
+ assertEquals(emptyList(), builder.getRepeatedUint64List());
+ assertEquals(singletonList(1L), messageAfterBuild.getRepeatedUint64List());
+
+ message = builder.build();
+ builder.addRepeatedBool(true);
+ assertEquals(emptyList(), message.getRepeatedBoolList());
+ assertEquals(singletonList(true), builder.getRepeatedBoolList());
+ assertEquals(emptyList(), message.getRepeatedBoolList());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedBool();
+ assertEquals(emptyList(), builder.getRepeatedBoolList());
+ assertEquals(singletonList(true), messageAfterBuild.getRepeatedBoolList());
+
+ message = builder.build();
+ builder.addRepeatedBytes(ByteString.copyFromUtf8("hi"));
+ assertEquals(emptyList(), message.getRepeatedBytesList());
+ assertEquals(
+ singletonList(ByteString.copyFromUtf8("hi")),
+ builder.getRepeatedBytesList());
+ assertEquals(emptyList(), message.getRepeatedBytesList());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedBytes();
+ assertEquals(emptyList(), builder.getRepeatedBytesList());
+ assertEquals(
+ singletonList(ByteString.copyFromUtf8("hi")),
+ messageAfterBuild.getRepeatedBytesList());
+
+ message = builder.build();
+ builder.addRepeatedCord("hi");
+ assertEquals(emptyList(), message.getRepeatedCordList());
+ assertEquals(singletonList("hi"), builder.getRepeatedCordList());
+ assertEquals(emptyList(), message.getRepeatedCordList());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedCord();
+ assertEquals(emptyList(), builder.getRepeatedCordList());
+ assertEquals(singletonList("hi"), messageAfterBuild.getRepeatedCordList());
+
+ message = builder.build();
+ builder.addRepeatedDouble(1D);
+ assertEquals(emptyList(), message.getRepeatedDoubleList());
+ assertEquals(singletonList(1D), builder.getRepeatedDoubleList());
+ assertEquals(emptyList(), message.getRepeatedDoubleList());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedDouble();
+ assertEquals(emptyList(), builder.getRepeatedDoubleList());
+ assertEquals(singletonList(1D), messageAfterBuild.getRepeatedDoubleList());
+
+ message = builder.build();
+ builder.addRepeatedFixed32(1);
+ assertEquals(emptyList(), message.getRepeatedFixed32List());
+ assertEquals(singletonList(1), builder.getRepeatedFixed32List());
+ assertEquals(emptyList(), message.getRepeatedFixed32List());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedFixed32();
+ assertEquals(emptyList(), builder.getRepeatedFixed32List());
+ assertEquals(singletonList(1), messageAfterBuild.getRepeatedFixed32List());
+
+ message = builder.build();
+ builder.addRepeatedFixed64(1L);
+ assertEquals(emptyList(), message.getRepeatedFixed64List());
+ assertEquals(singletonList(1L), builder.getRepeatedFixed64List());
+ assertEquals(emptyList(), message.getRepeatedFixed64List());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedFixed64();
+ assertEquals(emptyList(), builder.getRepeatedFixed64List());
+ assertEquals(singletonList(1L), messageAfterBuild.getRepeatedFixed64List());
+
+ message = builder.build();
+ builder.addRepeatedFloat(1F);
+ assertEquals(emptyList(), message.getRepeatedFloatList());
+ assertEquals(singletonList(1F), builder.getRepeatedFloatList());
+ assertEquals(emptyList(), message.getRepeatedFloatList());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedFloat();
+ assertEquals(emptyList(), builder.getRepeatedFloatList());
+ assertEquals(singletonList(1F), messageAfterBuild.getRepeatedFloatList());
+
+ message = builder.build();
+ builder.addRepeatedForeignEnum(ForeignEnumLite.FOREIGN_LITE_BAR);
+ assertEquals(emptyList(), message.getRepeatedForeignEnumList());
+ assertEquals(
+ singletonList(ForeignEnumLite.FOREIGN_LITE_BAR),
+ builder.getRepeatedForeignEnumList());
+ assertEquals(emptyList(), message.getRepeatedForeignEnumList());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedForeignEnum();
+ assertEquals(emptyList(), builder.getRepeatedForeignEnumList());
+ assertEquals(
+ singletonList(ForeignEnumLite.FOREIGN_LITE_BAR),
+ messageAfterBuild.getRepeatedForeignEnumList());
+
+ message = builder.build();
+ builder.addRepeatedForeignMessage(foreignMessage);
+ assertEquals(emptyList(), message.getRepeatedForeignMessageList());
+ assertEquals(
+ singletonList(foreignMessage), builder.getRepeatedForeignMessageList());
+ assertEquals(emptyList(), message.getRepeatedForeignMessageList());
+ messageAfterBuild = builder.build();
+ builder.removeRepeatedForeignMessage(0);
+ assertEquals(emptyList(), builder.getRepeatedForeignMessageList());
+ assertEquals(
+ singletonList(foreignMessage),
+ messageAfterBuild.getRepeatedForeignMessageList());
+
+ message = builder.build();
+ builder.addRepeatedGroup(RepeatedGroup.getDefaultInstance());
+ assertEquals(emptyList(), message.getRepeatedGroupList());
+ assertEquals(
+ singletonList(RepeatedGroup.getDefaultInstance()),
+ builder.getRepeatedGroupList());
+ assertEquals(emptyList(), message.getRepeatedGroupList());
+ messageAfterBuild = builder.build();
+ builder.removeRepeatedGroup(0);
+ assertEquals(emptyList(), builder.getRepeatedGroupList());
+ assertEquals(
+ singletonList(RepeatedGroup.getDefaultInstance()),
+ messageAfterBuild.getRepeatedGroupList());
+
+ message = builder.build();
+ builder.addRepeatedInt32(1);
+ assertEquals(emptyList(), message.getRepeatedInt32List());
+ assertEquals(singletonList(1), builder.getRepeatedInt32List());
+ assertEquals(emptyList(), message.getRepeatedInt32List());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedInt32();
+ assertEquals(emptyList(), builder.getRepeatedInt32List());
+ assertEquals(singletonList(1), messageAfterBuild.getRepeatedInt32List());
+
+ message = builder.build();
+ builder.addRepeatedInt64(1L);
+ assertEquals(emptyList(), message.getRepeatedInt64List());
+ assertEquals(singletonList(1L), builder.getRepeatedInt64List());
+ assertEquals(emptyList(), message.getRepeatedInt64List());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedInt64();
+ assertEquals(emptyList(), builder.getRepeatedInt64List());
+ assertEquals(singletonList(1L), messageAfterBuild.getRepeatedInt64List());
+
+ message = builder.build();
+ builder.addRepeatedLazyMessage(nestedMessage);
+ assertEquals(emptyList(), message.getRepeatedLazyMessageList());
+ assertEquals(
+ singletonList(nestedMessage), builder.getRepeatedLazyMessageList());
+ assertEquals(emptyList(), message.getRepeatedLazyMessageList());
+ messageAfterBuild = builder.build();
+ builder.removeRepeatedLazyMessage(0);
+ assertEquals(emptyList(), builder.getRepeatedLazyMessageList());
+ assertEquals(
+ singletonList(nestedMessage),
+ messageAfterBuild.getRepeatedLazyMessageList());
+
+ message = builder.build();
+ builder.addRepeatedSfixed32(1);
+ assertEquals(emptyList(), message.getRepeatedSfixed32List());
+ assertEquals(singletonList(1), builder.getRepeatedSfixed32List());
+ assertEquals(emptyList(), message.getRepeatedSfixed32List());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedSfixed32();
+ assertEquals(emptyList(), builder.getRepeatedSfixed32List());
+ assertEquals(singletonList(1), messageAfterBuild.getRepeatedSfixed32List());
+
+ message = builder.build();
+ builder.addRepeatedSfixed64(1L);
+ assertEquals(emptyList(), message.getRepeatedSfixed64List());
+ assertEquals(singletonList(1L), builder.getRepeatedSfixed64List());
+ assertEquals(emptyList(), message.getRepeatedSfixed64List());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedSfixed64();
+ assertEquals(emptyList(), builder.getRepeatedSfixed64List());
+ assertEquals(
+ singletonList(1L), messageAfterBuild.getRepeatedSfixed64List());
+
+ message = builder.build();
+ builder.addRepeatedSint32(1);
+ assertEquals(emptyList(), message.getRepeatedSint32List());
+ assertEquals(singletonList(1), builder.getRepeatedSint32List());
+ assertEquals(emptyList(), message.getRepeatedSint32List());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedSint32();
+ assertEquals(emptyList(), builder.getRepeatedSint32List());
+ assertEquals(singletonList(1), messageAfterBuild.getRepeatedSint32List());
+
+ message = builder.build();
+ builder.addRepeatedSint64(1L);
+ assertEquals(emptyList(), message.getRepeatedSint64List());
+ assertEquals(singletonList(1L), builder.getRepeatedSint64List());
+ assertEquals(emptyList(), message.getRepeatedSint64List());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedSint64();
+ assertEquals(emptyList(), builder.getRepeatedSint64List());
+ assertEquals(singletonList(1L), messageAfterBuild.getRepeatedSint64List());
+
+ message = builder.build();
+ builder.addRepeatedString("hi");
+ assertEquals(emptyList(), message.getRepeatedStringList());
+ assertEquals(singletonList("hi"), builder.getRepeatedStringList());
+ assertEquals(emptyList(), message.getRepeatedStringList());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedString();
+ assertEquals(emptyList(), builder.getRepeatedStringList());
+ assertEquals(
+ singletonList("hi"), messageAfterBuild.getRepeatedStringList());
+
+ message = builder.build();
+ builder.addRepeatedStringPiece("hi");
+ assertEquals(emptyList(), message.getRepeatedStringPieceList());
+ assertEquals(singletonList("hi"), builder.getRepeatedStringPieceList());
+ assertEquals(emptyList(), message.getRepeatedStringPieceList());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedStringPiece();
+ assertEquals(emptyList(), builder.getRepeatedStringPieceList());
+ assertEquals(
+ singletonList("hi"), messageAfterBuild.getRepeatedStringPieceList());
+
+ message = builder.build();
+ builder.addRepeatedUint32(1);
+ assertEquals(emptyList(), message.getRepeatedUint32List());
+ assertEquals(singletonList(1), builder.getRepeatedUint32List());
+ assertEquals(emptyList(), message.getRepeatedUint32List());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedUint32();
+ assertEquals(emptyList(), builder.getRepeatedUint32List());
+ assertEquals(singletonList(1), messageAfterBuild.getRepeatedUint32List());
+
+ message = builder.build();
+ builder.addRepeatedUint64(1L);
+ assertEquals(emptyList(), message.getRepeatedUint64List());
+ assertEquals(singletonList(1L), builder.getRepeatedUint64List());
+ assertEquals(emptyList(), message.getRepeatedUint64List());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedUint64();
+ assertEquals(emptyList(), builder.getRepeatedUint64List());
+ assertEquals(singletonList(1L), messageAfterBuild.getRepeatedUint64List());
+
+ message = builder.build();
+ builder.addRepeatedBool(true);
+ messageAfterBuild = builder.build();
+ assertEquals(0, message.getRepeatedBoolCount());
+ builder.setRepeatedBool(0, false);
+ assertEquals(true, messageAfterBuild.getRepeatedBool(0));
+ assertEquals(false, builder.getRepeatedBool(0));
+ builder.clearRepeatedBool();
+
+ message = builder.build();
+ builder.addRepeatedBytes(ByteString.copyFromUtf8("hi"));
+ messageAfterBuild = builder.build();
+ assertEquals(0, message.getRepeatedBytesCount());
+ builder.setRepeatedBytes(0, ByteString.EMPTY);
+ assertEquals(
+ ByteString.copyFromUtf8("hi"), messageAfterBuild.getRepeatedBytes(0));
+ assertEquals(ByteString.EMPTY, builder.getRepeatedBytes(0));
+ builder.clearRepeatedBytes();
+
+ message = builder.build();
+ builder.addRepeatedCord("hi");
+ messageAfterBuild = builder.build();
+ assertEquals(0, message.getRepeatedCordCount());
+ builder.setRepeatedCord(0, "");
+ assertEquals("hi", messageAfterBuild.getRepeatedCord(0));
+ assertEquals("", builder.getRepeatedCord(0));
+ builder.clearRepeatedCord();
+ message = builder.build();
+
+ builder.addRepeatedCordBytes(ByteString.copyFromUtf8("hi"));
+ messageAfterBuild = builder.build();
+ assertEquals(0, message.getRepeatedCordCount());
+ builder.setRepeatedCord(0, "");
+ assertEquals(
+ ByteString.copyFromUtf8("hi"), messageAfterBuild.getRepeatedCordBytes(0));
+ assertEquals(ByteString.EMPTY, builder.getRepeatedCordBytes(0));
+ builder.clearRepeatedCord();
+
+ message = builder.build();
+ builder.addRepeatedDouble(1D);
+ messageAfterBuild = builder.build();
+ assertEquals(0, message.getRepeatedDoubleCount());
+ builder.setRepeatedDouble(0, 0D);
+ assertEquals(1D, messageAfterBuild.getRepeatedDouble(0));
+ assertEquals(0D, builder.getRepeatedDouble(0));
+ builder.clearRepeatedDouble();
+
+ message = builder.build();
+ builder.addRepeatedFixed32(1);
+ messageAfterBuild = builder.build();
+ assertEquals(0, message.getRepeatedFixed32Count());
+ builder.setRepeatedFixed32(0, 0);
+ assertEquals(1, messageAfterBuild.getRepeatedFixed32(0));
+ assertEquals(0, builder.getRepeatedFixed32(0));
+ builder.clearRepeatedFixed32();
+
+ message = builder.build();
+ builder.addRepeatedFixed64(1L);
+ messageAfterBuild = builder.build();
+ assertEquals(0, message.getRepeatedFixed64Count());
+ builder.setRepeatedFixed64(0, 0L);
+ assertEquals(1L, messageAfterBuild.getRepeatedFixed64(0));
+ assertEquals(0L, builder.getRepeatedFixed64(0));
+ builder.clearRepeatedFixed64();
+
+ message = builder.build();
+ builder.addRepeatedFloat(1F);
+ messageAfterBuild = builder.build();
+ assertEquals(0, message.getRepeatedFloatCount());
+ builder.setRepeatedFloat(0, 0F);
+ assertEquals(1F, messageAfterBuild.getRepeatedFloat(0));
+ assertEquals(0F, builder.getRepeatedFloat(0));
+ builder.clearRepeatedFloat();
+
+ message = builder.build();
+ builder.addRepeatedForeignEnum(ForeignEnumLite.FOREIGN_LITE_BAR);
+ messageAfterBuild = builder.build();
+ assertEquals(0, message.getRepeatedForeignEnumCount());
+ builder.setRepeatedForeignEnum(0, ForeignEnumLite.FOREIGN_LITE_FOO);
+ assertEquals(
+ ForeignEnumLite.FOREIGN_LITE_BAR,
+ messageAfterBuild.getRepeatedForeignEnum(0));
+ assertEquals(
+ ForeignEnumLite.FOREIGN_LITE_FOO, builder.getRepeatedForeignEnum(0));
+ builder.clearRepeatedForeignEnum();
+
+ message = builder.build();
+ builder.addRepeatedForeignMessage(foreignMessage);
+ messageAfterBuild = builder.build();
+ assertEquals(0, message.getRepeatedForeignMessageCount());
+ builder.setRepeatedForeignMessage(
+ 0, ForeignMessageLite.getDefaultInstance());
+ assertEquals(
+ foreignMessage, messageAfterBuild.getRepeatedForeignMessage(0));
+ assertEquals(
+ ForeignMessageLite.getDefaultInstance(),
+ builder.getRepeatedForeignMessage(0));
+ builder.clearRepeatedForeignMessage();
+
+ message = builder.build();
+ builder.addRepeatedForeignMessage(foreignMessageBuilder);
+ messageAfterBuild = builder.build();
+ assertEquals(0, message.getRepeatedForeignMessageCount());
+ builder.setRepeatedForeignMessage(
+ 0, ForeignMessageLite.getDefaultInstance());
+ // LITE_RUNTIME doesn't implement equals so we compare on a property.
+ assertEquals(3, messageAfterBuild.getRepeatedForeignMessage(0).getC());
+ assertEquals(
+ ForeignMessageLite.getDefaultInstance(),
+ builder.getRepeatedForeignMessage(0));
+ builder.clearRepeatedForeignMessage();
+
+ message = builder.build();
+ builder.addRepeatedForeignMessage(0, foreignMessage);
+ messageAfterBuild = builder.build();
+ assertEquals(0, message.getRepeatedForeignMessageCount());
+ builder.setRepeatedForeignMessage(0, foreignMessageBuilder);
+ assertEquals(
+ foreignMessage, messageAfterBuild.getRepeatedForeignMessage(0));
+ // LITE_RUNTIME doesn't implement equals so we compare on a property.
+ assertEquals(3, builder.getRepeatedForeignMessage(0).getC());
+ builder.clearRepeatedForeignMessage();
+
+ message = builder.build();
+ RepeatedGroup repeatedGroup = RepeatedGroup.newBuilder()
+ .setA(1)
+ .build();
+ builder.addRepeatedGroup(repeatedGroup);
+ messageAfterBuild = builder.build();
+ assertEquals(0, message.getRepeatedGroupCount());
+ builder.setRepeatedGroup(0, RepeatedGroup.getDefaultInstance());
+ assertEquals(repeatedGroup, messageAfterBuild.getRepeatedGroup(0));
+ assertEquals(
+ RepeatedGroup.getDefaultInstance(), builder.getRepeatedGroup(0));
+ builder.clearRepeatedGroup();
+
+ message = builder.build();
+ builder.addRepeatedGroup(0, repeatedGroup);
+ messageAfterBuild = builder.build();
+ assertEquals(0, message.getRepeatedGroupCount());
+ builder.setRepeatedGroup(0, RepeatedGroup.getDefaultInstance());
+ assertEquals(repeatedGroup, messageAfterBuild.getRepeatedGroup(0));
+ assertEquals(
+ RepeatedGroup.getDefaultInstance(), builder.getRepeatedGroup(0));
+ builder.clearRepeatedGroup();
+
+ message = builder.build();
+ RepeatedGroup.Builder repeatedGroupBuilder = RepeatedGroup.newBuilder()
+ .setA(3);
+ builder.addRepeatedGroup(repeatedGroupBuilder);
+ messageAfterBuild = builder.build();
+ assertEquals(0, message.getRepeatedGroupCount());
+ builder.setRepeatedGroup(0, RepeatedGroup.getDefaultInstance());
+ // LITE_RUNTIME doesn't implement equals so we compare on a property and
+ // ensure the property isn't set on repeatedGroup.
+ assertEquals(3, messageAfterBuild.getRepeatedGroup(0).getA());
+ assertEquals(
+ RepeatedGroup.getDefaultInstance(), builder.getRepeatedGroup(0));
+ builder.clearRepeatedGroup();
+
+ message = builder.build();
+ builder.addRepeatedGroup(0, repeatedGroupBuilder);
+ messageAfterBuild = builder.build();
+ assertEquals(0, message.getRepeatedGroupCount());
+ builder.setRepeatedGroup(0, RepeatedGroup.getDefaultInstance());
+ // LITE_RUNTIME doesn't implement equals so we compare on a property and
+ // ensure the property isn't set on repeatedGroup.
+ assertEquals(3, messageAfterBuild.getRepeatedGroup(0).getA());
+ assertEquals(
+ RepeatedGroup.getDefaultInstance(), builder.getRepeatedGroup(0));
+ builder.clearRepeatedGroup();
+
+ message = builder.build();
+ builder.addRepeatedInt32(1);
+ messageAfterBuild = builder.build();
+ assertEquals(0, message.getRepeatedInt32Count());
+ builder.setRepeatedInt32(0, 0);
+ assertEquals(1, messageAfterBuild.getRepeatedInt32(0));
+ assertEquals(0, builder.getRepeatedInt32(0));
+ builder.clearRepeatedInt32();
+
+ message = builder.build();
+ builder.addRepeatedInt64(1L);
+ messageAfterBuild = builder.build();
+ assertEquals(0L, message.getRepeatedInt64Count());
+ builder.setRepeatedInt64(0, 0L);
+ assertEquals(1L, messageAfterBuild.getRepeatedInt64(0));
+ assertEquals(0L, builder.getRepeatedInt64(0));
+ builder.clearRepeatedInt64();
+
+ message = builder.build();
+ builder.addRepeatedLazyMessage(nestedMessage);
+ messageAfterBuild = builder.build();
+ assertEquals(0, message.getRepeatedLazyMessageCount());
+ builder.setRepeatedLazyMessage(0, NestedMessage.getDefaultInstance());
+ assertEquals(nestedMessage, messageAfterBuild.getRepeatedLazyMessage(0));
+ assertEquals(
+ NestedMessage.getDefaultInstance(), builder.getRepeatedLazyMessage(0));
+ builder.clearRepeatedLazyMessage();
+
+ message = builder.build();
+ builder.addRepeatedLazyMessage(0, nestedMessage);
+ messageAfterBuild = builder.build();
+ assertEquals(0, message.getRepeatedLazyMessageCount());
+ builder.setRepeatedLazyMessage(0, NestedMessage.getDefaultInstance());
+ assertEquals(nestedMessage, messageAfterBuild.getRepeatedLazyMessage(0));
+ assertEquals(
+ NestedMessage.getDefaultInstance(), builder.getRepeatedLazyMessage(0));
+ builder.clearRepeatedLazyMessage();
+
+ message = builder.build();
+ builder.addRepeatedLazyMessage(nestedMessageBuilder);
+ messageAfterBuild = builder.build();
+ assertEquals(0, message.getRepeatedLazyMessageCount());
+ builder.setRepeatedLazyMessage(0, NestedMessage.getDefaultInstance());
+ // LITE_RUNTIME doesn't implement equals so we compare on a property and
+ // ensure the property isn't set on repeatedGroup.
+ assertEquals(3, messageAfterBuild.getRepeatedLazyMessage(0).getBb());
+ assertEquals(
+ NestedMessage.getDefaultInstance(), builder.getRepeatedLazyMessage(0));
+ builder.clearRepeatedLazyMessage();
+
+ message = builder.build();
+ builder.addRepeatedLazyMessage(0, nestedMessageBuilder);
+ messageAfterBuild = builder.build();
+ assertEquals(0, message.getRepeatedLazyMessageCount());
+ builder.setRepeatedLazyMessage(0, NestedMessage.getDefaultInstance());
+ // LITE_RUNTIME doesn't implement equals so we compare on a property and
+ // ensure the property isn't set on repeatedGroup.
+ assertEquals(3, messageAfterBuild.getRepeatedLazyMessage(0).getBb());
+ assertEquals(
+ NestedMessage.getDefaultInstance(), builder.getRepeatedLazyMessage(0));
+ builder.clearRepeatedLazyMessage();
+
+ message = builder.build();
+ builder.addRepeatedSfixed32(1);
+ messageAfterBuild = builder.build();
+ assertEquals(0, message.getRepeatedSfixed32Count());
+ builder.setRepeatedSfixed32(0, 0);
+ assertEquals(1, messageAfterBuild.getRepeatedSfixed32(0));
+ assertEquals(0, builder.getRepeatedSfixed32(0));
+ builder.clearRepeatedSfixed32();
+
+ message = builder.build();
+ builder.addRepeatedSfixed64(1L);
+ messageAfterBuild = builder.build();
+ assertEquals(0L, message.getRepeatedSfixed64Count());
+ builder.setRepeatedSfixed64(0, 0L);
+ assertEquals(1L, messageAfterBuild.getRepeatedSfixed64(0));
+ assertEquals(0L, builder.getRepeatedSfixed64(0));
+ builder.clearRepeatedSfixed64();
+
+ message = builder.build();
+ builder.addRepeatedSint32(1);
+ messageAfterBuild = builder.build();
+ assertEquals(0, message.getRepeatedSint32Count());
+ builder.setRepeatedSint32(0, 0);
+ assertEquals(1, messageAfterBuild.getRepeatedSint32(0));
+ assertEquals(0, builder.getRepeatedSint32(0));
+ builder.clearRepeatedSint32();
+
+ message = builder.build();
+ builder.addRepeatedSint64(1L);
+ messageAfterBuild = builder.build();
+ assertEquals(0L, message.getRepeatedSint64Count());
+ builder.setRepeatedSint64(0, 0L);
+ assertEquals(1L, messageAfterBuild.getRepeatedSint64(0));
+ assertEquals(0L, builder.getRepeatedSint64(0));
+ builder.clearRepeatedSint64();
+
+ message = builder.build();
+ builder.addRepeatedString("hi");
+ messageAfterBuild = builder.build();
+ assertEquals(0L, message.getRepeatedStringCount());
+ builder.setRepeatedString(0, "");
+ assertEquals("hi", messageAfterBuild.getRepeatedString(0));
+ assertEquals("", builder.getRepeatedString(0));
+ builder.clearRepeatedString();
+
+ message = builder.build();
+ builder.addRepeatedStringBytes(ByteString.copyFromUtf8("hi"));
+ messageAfterBuild = builder.build();
+ assertEquals(0L, message.getRepeatedStringCount());
+ builder.setRepeatedString(0, "");
+ assertEquals(
+ ByteString.copyFromUtf8("hi"),
+ messageAfterBuild.getRepeatedStringBytes(0));
+ assertEquals(ByteString.EMPTY, builder.getRepeatedStringBytes(0));
+ builder.clearRepeatedString();
+
+ message = builder.build();
+ builder.addRepeatedStringPiece("hi");
+ messageAfterBuild = builder.build();
+ assertEquals(0L, message.getRepeatedStringPieceCount());
+ builder.setRepeatedStringPiece(0, "");
+ assertEquals("hi", messageAfterBuild.getRepeatedStringPiece(0));
+ assertEquals("", builder.getRepeatedStringPiece(0));
+ builder.clearRepeatedStringPiece();
+
+ message = builder.build();
+ builder.addRepeatedStringPieceBytes(ByteString.copyFromUtf8("hi"));
+ messageAfterBuild = builder.build();
+ assertEquals(0L, message.getRepeatedStringPieceCount());
+ builder.setRepeatedStringPiece(0, "");
+ assertEquals(
+ ByteString.copyFromUtf8("hi"),
+ messageAfterBuild.getRepeatedStringPieceBytes(0));
+ assertEquals(ByteString.EMPTY, builder.getRepeatedStringPieceBytes(0));
+ builder.clearRepeatedStringPiece();
+
+ message = builder.build();
+ builder.addRepeatedUint32(1);
+ messageAfterBuild = builder.build();
+ assertEquals(0, message.getRepeatedUint32Count());
+ builder.setRepeatedUint32(0, 0);
+ assertEquals(1, messageAfterBuild.getRepeatedUint32(0));
+ assertEquals(0, builder.getRepeatedUint32(0));
+ builder.clearRepeatedUint32();
+
+ message = builder.build();
+ builder.addRepeatedUint64(1L);
+ messageAfterBuild = builder.build();
+ assertEquals(0L, message.getRepeatedUint64Count());
+ builder.setRepeatedUint64(0, 0L);
+ assertEquals(1L, messageAfterBuild.getRepeatedUint64(0));
+ assertEquals(0L, builder.getRepeatedUint64(0));
+ builder.clearRepeatedUint64();
+
+ message = builder.build();
+ assertEquals(0, message.getSerializedSize());
+ builder.mergeFrom(TestAllTypesLite.newBuilder()
+ .setOptionalBool(true)
+ .build());
+ assertEquals(0, message.getSerializedSize());
+ assertEquals(true, builder.build().getOptionalBool());
+ builder.clearOptionalBool();
+
+ message = builder.build();
+ assertEquals(0, message.getSerializedSize());
+ builder.mergeFrom(TestAllTypesLite.newBuilder()
+ .setOptionalBool(true)
+ .build());
+ assertEquals(0, message.getSerializedSize());
+ assertEquals(true, builder.build().getOptionalBool());
+ builder.clear();
+ assertEquals(0, builder.build().getSerializedSize());
+
+ message = builder.build();
+ assertEquals(0, message.getSerializedSize());
+ builder.mergeOptionalForeignMessage(foreignMessage);
+ assertEquals(0, message.getSerializedSize());
+ assertEquals(
+ foreignMessage.getC(),
+ builder.build().getOptionalForeignMessage().getC());
+ builder.clearOptionalForeignMessage();
+
+ message = builder.build();
+ assertEquals(0, message.getSerializedSize());
+ builder.mergeOptionalLazyMessage(nestedMessage);
+ assertEquals(0, message.getSerializedSize());
+ assertEquals(
+ nestedMessage.getBb(),
+ builder.build().getOptionalLazyMessage().getBb());
+ builder.clearOptionalLazyMessage();
+
+ message = builder.build();
+ builder.setOneofString("hi");
+ assertEquals(
+ OneofFieldCase.ONEOFFIELD_NOT_SET, message.getOneofFieldCase());
+ assertEquals(OneofFieldCase.ONEOF_STRING, builder.getOneofFieldCase());
+ assertEquals("hi", builder.getOneofString());
+ messageAfterBuild = builder.build();
+ assertEquals(
+ OneofFieldCase.ONEOF_STRING, messageAfterBuild.getOneofFieldCase());
+ assertEquals("hi", messageAfterBuild.getOneofString());
+ builder.setOneofUint32(1);
+ assertEquals(
+ OneofFieldCase.ONEOF_STRING, messageAfterBuild.getOneofFieldCase());
+ assertEquals("hi", messageAfterBuild.getOneofString());
+ assertEquals(OneofFieldCase.ONEOF_UINT32, builder.getOneofFieldCase());
+ assertEquals(1, builder.getOneofUint32());
+ TestAllTypesLiteOrBuilder messageOrBuilder = builder;
+ assertEquals(OneofFieldCase.ONEOF_UINT32, messageOrBuilder.getOneofFieldCase());
+
+ TestAllExtensionsLite.Builder extendableMessageBuilder =
+ TestAllExtensionsLite.newBuilder();
+ TestAllExtensionsLite extendableMessage = extendableMessageBuilder.build();
+ extendableMessageBuilder.setExtension(
+ UnittestLite.optionalInt32ExtensionLite, 1);
+ assertFalse(extendableMessage.hasExtension(
+ UnittestLite.optionalInt32ExtensionLite));
+ extendableMessage = extendableMessageBuilder.build();
+ assertEquals(
+ 1, (int) extendableMessageBuilder.getExtension(
+ UnittestLite.optionalInt32ExtensionLite));
+ assertEquals(
+ 1, (int) extendableMessage.getExtension(
+ UnittestLite.optionalInt32ExtensionLite));
+ extendableMessageBuilder.setExtension(
+ UnittestLite.optionalInt32ExtensionLite, 3);
+ assertEquals(
+ 3, (int) extendableMessageBuilder.getExtension(
+ UnittestLite.optionalInt32ExtensionLite));
+ assertEquals(
+ 1, (int) extendableMessage.getExtension(
+ UnittestLite.optionalInt32ExtensionLite));
+ extendableMessage = extendableMessageBuilder.build();
+ assertEquals(
+ 3, (int) extendableMessageBuilder.getExtension(
+ UnittestLite.optionalInt32ExtensionLite));
+ assertEquals(
+ 3, (int) extendableMessage.getExtension(
+ UnittestLite.optionalInt32ExtensionLite));
+
+ // No extension registry, so it should be in unknown fields.
+ extendableMessage =
+ TestAllExtensionsLite.parseFrom(extendableMessage.toByteArray());
+ assertFalse(extendableMessage.hasExtension(
+ UnittestLite.optionalInt32ExtensionLite));
+
+ extendableMessageBuilder = extendableMessage.toBuilder();
+ extendableMessageBuilder.mergeFrom(TestAllExtensionsLite.newBuilder()
+ .setExtension(UnittestLite.optionalFixed32ExtensionLite, 11)
+ .build());
+
+ extendableMessage = extendableMessageBuilder.build();
+ ExtensionRegistryLite registry = ExtensionRegistryLite.newInstance();
+ UnittestLite.registerAllExtensions(registry);
+ extendableMessage = TestAllExtensionsLite.parseFrom(
+ extendableMessage.toByteArray(), registry);
+
+ // The unknown field was preserved.
+ assertEquals(
+ 3, (int) extendableMessage.getExtension(
+ UnittestLite.optionalInt32ExtensionLite));
+ assertEquals(
+ 11, (int) extendableMessage.getExtension(
+ UnittestLite.optionalFixed32ExtensionLite));
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/LiteralByteStringTest.java b/java/core/src/test/java/com/google/protobuf/LiteralByteStringTest.java
new file mode 100644
index 00000000..68b55ceb
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/LiteralByteStringTest.java
@@ -0,0 +1,495 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// 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 junit.framework.TestCase;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.List;
+import java.util.NoSuchElementException;
+
+/**
+ * Test {@link LiteralByteString} by setting up a reference string in {@link #setUp()}.
+ * This class is designed to be extended for testing extensions of {@link LiteralByteString}
+ * such as {@link BoundedByteString}, see {@link BoundedByteStringTest}.
+ *
+ * @author carlanton@google.com (Carl Haverl)
+ */
+public class LiteralByteStringTest extends TestCase {
+ protected static final String UTF_8 = "UTF-8";
+
+ protected String classUnderTest;
+ protected byte[] referenceBytes;
+ protected ByteString stringUnderTest;
+ protected int expectedHashCode;
+
+ @Override
+ protected void setUp() throws Exception {
+ classUnderTest = "LiteralByteString";
+ referenceBytes = ByteStringTest.getTestBytes(1234, 11337766L);
+ stringUnderTest = ByteString.copyFrom(referenceBytes);
+ expectedHashCode = 331161852;
+ }
+
+ public void testExpectedType() {
+ String actualClassName = getActualClassName(stringUnderTest);
+ assertEquals(classUnderTest + " should match type exactly", classUnderTest, actualClassName);
+ }
+
+ protected String getActualClassName(Object object) {
+ return object.getClass().getSimpleName();
+ }
+
+ public void testByteAt() {
+ boolean stillEqual = true;
+ for (int i = 0; stillEqual && i < referenceBytes.length; ++i) {
+ stillEqual = (referenceBytes[i] == stringUnderTest.byteAt(i));
+ }
+ assertTrue(classUnderTest + " must capture the right bytes", stillEqual);
+ }
+
+ public void testByteIterator() {
+ boolean stillEqual = true;
+ ByteString.ByteIterator iter = stringUnderTest.iterator();
+ for (int i = 0; stillEqual && i < referenceBytes.length; ++i) {
+ stillEqual = (iter.hasNext() && referenceBytes[i] == iter.nextByte());
+ }
+ assertTrue(classUnderTest + " must capture the right bytes", stillEqual);
+ assertFalse(classUnderTest + " must have exhausted the itertor", iter.hasNext());
+
+ try {
+ iter.nextByte();
+ fail("Should have thrown an exception.");
+ } catch (NoSuchElementException e) {
+ // This is success
+ }
+ }
+
+ public void testByteIterable() {
+ boolean stillEqual = true;
+ int j = 0;
+ for (byte quantum : stringUnderTest) {
+ stillEqual = (referenceBytes[j] == quantum);
+ ++j;
+ }
+ assertTrue(classUnderTest + " must capture the right bytes as Bytes", stillEqual);
+ assertEquals(classUnderTest + " iterable character count", referenceBytes.length, j);
+ }
+
+ public void testSize() {
+ assertEquals(classUnderTest + " must have the expected size", referenceBytes.length,
+ stringUnderTest.size());
+ }
+
+ public void testGetTreeDepth() {
+ assertEquals(classUnderTest + " must have depth 0", 0, stringUnderTest.getTreeDepth());
+ }
+
+ public void testIsBalanced() {
+ assertTrue(classUnderTest + " is technically balanced", stringUnderTest.isBalanced());
+ }
+
+ public void testCopyTo_ByteArrayOffsetLength() {
+ int destinationOffset = 50;
+ int length = 100;
+ byte[] destination = new byte[destinationOffset + length];
+ int sourceOffset = 213;
+ stringUnderTest.copyTo(destination, sourceOffset, destinationOffset, length);
+ boolean stillEqual = true;
+ for (int i = 0; stillEqual && i < length; ++i) {
+ stillEqual = referenceBytes[i + sourceOffset] == destination[i + destinationOffset];
+ }
+ assertTrue(classUnderTest + ".copyTo(4 arg) must give the expected bytes", stillEqual);
+ }
+
+ public void testCopyTo_ByteArrayOffsetLengthErrors() {
+ int destinationOffset = 50;
+ int length = 100;
+ byte[] destination = new byte[destinationOffset + length];
+
+ try {
+ // Copy one too many bytes
+ stringUnderTest.copyTo(destination, stringUnderTest.size() + 1 - length,
+ destinationOffset, length);
+ fail("Should have thrown an exception when copying too many bytes of a "
+ + classUnderTest);
+ } catch (IndexOutOfBoundsException expected) {
+ // This is success
+ }
+
+ try {
+ // Copy with illegal negative sourceOffset
+ stringUnderTest.copyTo(destination, -1, destinationOffset, length);
+ fail("Should have thrown an exception when given a negative sourceOffset in "
+ + classUnderTest);
+ } catch (IndexOutOfBoundsException expected) {
+ // This is success
+ }
+
+ try {
+ // Copy with illegal negative destinationOffset
+ stringUnderTest.copyTo(destination, 0, -1, length);
+ fail("Should have thrown an exception when given a negative destinationOffset in "
+ + classUnderTest);
+ } catch (IndexOutOfBoundsException expected) {
+ // This is success
+ }
+
+ try {
+ // Copy with illegal negative size
+ stringUnderTest.copyTo(destination, 0, 0, -1);
+ fail("Should have thrown an exception when given a negative size in "
+ + classUnderTest);
+ } catch (IndexOutOfBoundsException expected) {
+ // This is success
+ }
+
+ try {
+ // Copy with illegal too-large sourceOffset
+ stringUnderTest.copyTo(destination, 2 * stringUnderTest.size(), 0, length);
+ fail("Should have thrown an exception when the destinationOffset is too large in "
+ + classUnderTest);
+ } catch (IndexOutOfBoundsException expected) {
+ // This is success
+ }
+
+ try {
+ // Copy with illegal too-large destinationOffset
+ stringUnderTest.copyTo(destination, 0, 2 * destination.length, length);
+ fail("Should have thrown an exception when the destinationOffset is too large in "
+ + classUnderTest);
+ } catch (IndexOutOfBoundsException expected) {
+ // This is success
+ }
+ }
+
+ public void testCopyTo_ByteBuffer() {
+ ByteBuffer myBuffer = ByteBuffer.allocate(referenceBytes.length);
+ stringUnderTest.copyTo(myBuffer);
+ assertTrue(classUnderTest + ".copyTo(ByteBuffer) must give back the same bytes",
+ Arrays.equals(referenceBytes, myBuffer.array()));
+ }
+
+ public void testMarkSupported() {
+ InputStream stream = stringUnderTest.newInput();
+ assertTrue(classUnderTest + ".newInput() must support marking", stream.markSupported());
+ }
+
+ public void testMarkAndReset() throws IOException {
+ int fraction = stringUnderTest.size() / 3;
+
+ InputStream stream = stringUnderTest.newInput();
+ stream.mark(stringUnderTest.size()); // First, mark() the end.
+
+ skipFully(stream, fraction); // Skip a large fraction, but not all.
+ int available = stream.available();
+ assertTrue(
+ classUnderTest + ": after skipping to the 'middle', half the bytes are available",
+ (stringUnderTest.size() - fraction) == available);
+ stream.reset();
+
+ skipFully(stream, stringUnderTest.size()); // Skip to the end.
+ available = stream.available();
+ assertTrue(
+ classUnderTest + ": after skipping to the end, no more bytes are available",
+ 0 == available);
+ }
+
+ /**
+ * Discards {@code n} bytes of data from the input stream. This method
+ * will block until the full amount has been skipped. Does not close the
+ * stream.
+ * <p>Copied from com.google.common.io.ByteStreams to avoid adding dependency.
+ *
+ * @param in the input stream to read from
+ * @param n the number of bytes to skip
+ * @throws EOFException if this stream reaches the end before skipping all
+ * the bytes
+ * @throws IOException if an I/O error occurs, or the stream does not
+ * support skipping
+ */
+ static void skipFully(InputStream in, long n) throws IOException {
+ long toSkip = n;
+ while (n > 0) {
+ long amt = in.skip(n);
+ if (amt == 0) {
+ // Force a blocking read to avoid infinite loop
+ if (in.read() == -1) {
+ long skipped = toSkip - n;
+ throw new EOFException("reached end of stream after skipping "
+ + skipped + " bytes; " + toSkip + " bytes expected");
+ }
+ n--;
+ } else {
+ n -= amt;
+ }
+ }
+ }
+
+ public void testAsReadOnlyByteBuffer() {
+ ByteBuffer byteBuffer = stringUnderTest.asReadOnlyByteBuffer();
+ byte[] roundTripBytes = new byte[referenceBytes.length];
+ assertTrue(byteBuffer.remaining() == referenceBytes.length);
+ assertTrue(byteBuffer.isReadOnly());
+ byteBuffer.get(roundTripBytes);
+ assertTrue(classUnderTest + ".asReadOnlyByteBuffer() must give back the same bytes",
+ Arrays.equals(referenceBytes, roundTripBytes));
+ }
+
+ public void testAsReadOnlyByteBufferList() {
+ List<ByteBuffer> byteBuffers = stringUnderTest.asReadOnlyByteBufferList();
+ int bytesSeen = 0;
+ byte[] roundTripBytes = new byte[referenceBytes.length];
+ for (ByteBuffer byteBuffer : byteBuffers) {
+ int thisLength = byteBuffer.remaining();
+ assertTrue(byteBuffer.isReadOnly());
+ assertTrue(bytesSeen + thisLength <= referenceBytes.length);
+ byteBuffer.get(roundTripBytes, bytesSeen, thisLength);
+ bytesSeen += thisLength;
+ }
+ assertTrue(bytesSeen == referenceBytes.length);
+ assertTrue(classUnderTest + ".asReadOnlyByteBufferTest() must give back the same bytes",
+ Arrays.equals(referenceBytes, roundTripBytes));
+ }
+
+ public void testToByteArray() {
+ byte[] roundTripBytes = stringUnderTest.toByteArray();
+ assertTrue(classUnderTest + ".toByteArray() must give back the same bytes",
+ Arrays.equals(referenceBytes, roundTripBytes));
+ }
+
+ public void testWriteTo() throws IOException {
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ stringUnderTest.writeTo(bos);
+ byte[] roundTripBytes = bos.toByteArray();
+ assertTrue(classUnderTest + ".writeTo() must give back the same bytes",
+ Arrays.equals(referenceBytes, roundTripBytes));
+ }
+
+ public void testWriteTo_mutating() throws IOException {
+ OutputStream os = new OutputStream() {
+ @Override
+ public void write(byte[] b, int off, int len) {
+ for (int x = 0; x < len; ++x) {
+ b[off + x] = (byte) 0;
+ }
+ }
+
+ @Override
+ public void write(int b) {
+ // Purposefully left blank.
+ }
+ };
+
+ stringUnderTest.writeTo(os);
+ byte[] newBytes = stringUnderTest.toByteArray();
+ assertTrue(classUnderTest + ".writeTo() must not grant access to underlying array",
+ Arrays.equals(referenceBytes, newBytes));
+ }
+
+ public void testNewOutput() throws IOException {
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ ByteString.Output output = ByteString.newOutput();
+ stringUnderTest.writeTo(output);
+ assertEquals("Output Size returns correct result",
+ output.size(), stringUnderTest.size());
+ output.writeTo(bos);
+ assertTrue("Output.writeTo() must give back the same bytes",
+ Arrays.equals(referenceBytes, bos.toByteArray()));
+
+ // write the output stream to itself! This should cause it to double
+ output.writeTo(output);
+ assertEquals("Writing an output stream to itself is successful",
+ stringUnderTest.concat(stringUnderTest), output.toByteString());
+
+ output.reset();
+ assertEquals("Output.reset() resets the output", 0, output.size());
+ assertEquals("Output.reset() resets the output",
+ ByteString.EMPTY, output.toByteString());
+ }
+
+ public void testToString() throws UnsupportedEncodingException {
+ String testString = "I love unicode \u1234\u5678 characters";
+ ByteString unicode = ByteString.wrap(testString.getBytes(Internal.UTF_8));
+ String roundTripString = unicode.toString(UTF_8);
+ assertEquals(classUnderTest + " unicode must match", testString, roundTripString);
+ }
+
+ public void testCharsetToString() {
+ String testString = "I love unicode \u1234\u5678 characters";
+ ByteString unicode = ByteString.wrap(testString.getBytes(Internal.UTF_8));
+ String roundTripString = unicode.toString(Internal.UTF_8);
+ assertEquals(classUnderTest + " unicode must match", testString, roundTripString);
+ }
+
+ public void testToString_returnsCanonicalEmptyString() {
+ assertSame(classUnderTest + " must be the same string references",
+ ByteString.EMPTY.toString(Internal.UTF_8),
+ ByteString.wrap(new byte[]{}).toString(Internal.UTF_8));
+ }
+
+ public void testToString_raisesException() {
+ try {
+ ByteString.EMPTY.toString("invalid");
+ fail("Should have thrown an exception.");
+ } catch (UnsupportedEncodingException expected) {
+ // This is success
+ }
+
+ try {
+ ByteString.wrap(referenceBytes).toString("invalid");
+ fail("Should have thrown an exception.");
+ } catch (UnsupportedEncodingException expected) {
+ // This is success
+ }
+ }
+
+ public void testEquals() {
+ assertEquals(classUnderTest + " must not equal null", false, stringUnderTest.equals(null));
+ assertEquals(classUnderTest + " must equal self", stringUnderTest, stringUnderTest);
+ assertFalse(classUnderTest + " must not equal the empty string",
+ stringUnderTest.equals(ByteString.EMPTY));
+ assertEquals(classUnderTest + " empty strings must be equal",
+ ByteString.wrap(new byte[]{}), stringUnderTest.substring(55, 55));
+ assertEquals(classUnderTest + " must equal another string with the same value",
+ stringUnderTest, ByteString.wrap(referenceBytes));
+
+ byte[] mungedBytes = new byte[referenceBytes.length];
+ System.arraycopy(referenceBytes, 0, mungedBytes, 0, referenceBytes.length);
+ mungedBytes[mungedBytes.length - 5] = (byte) (mungedBytes[mungedBytes.length - 5] ^ 0xFF);
+ assertFalse(classUnderTest + " must not equal every string with the same length",
+ stringUnderTest.equals(ByteString.wrap(mungedBytes)));
+ }
+
+ public void testHashCode() {
+ int hash = stringUnderTest.hashCode();
+ assertEquals(classUnderTest + " must have expected hashCode", expectedHashCode, hash);
+ }
+
+ public void testPeekCachedHashCode() {
+ assertEquals(classUnderTest + ".peekCachedHashCode() should return zero at first", 0,
+ stringUnderTest.peekCachedHashCode());
+ stringUnderTest.hashCode();
+ assertEquals(classUnderTest + ".peekCachedHashCode should return zero at first",
+ expectedHashCode, stringUnderTest.peekCachedHashCode());
+ }
+
+ public void testPartialHash() {
+ // partialHash() is more strenuously tested elsewhere by testing hashes of substrings.
+ // This test would fail if the expected hash were 1. It's not.
+ int hash = stringUnderTest.partialHash(stringUnderTest.size(), 0, stringUnderTest.size());
+ assertEquals(classUnderTest + ".partialHash() must yield expected hashCode",
+ expectedHashCode, hash);
+ }
+
+ public void testNewInput() throws IOException {
+ InputStream input = stringUnderTest.newInput();
+ assertEquals("InputStream.available() returns correct value",
+ stringUnderTest.size(), input.available());
+ boolean stillEqual = true;
+ for (byte referenceByte : referenceBytes) {
+ int expectedInt = (referenceByte & 0xFF);
+ stillEqual = (expectedInt == input.read());
+ }
+ assertEquals("InputStream.available() returns correct value",
+ 0, input.available());
+ assertTrue(classUnderTest + " must give the same bytes from the InputStream", stillEqual);
+ assertEquals(classUnderTest + " InputStream must now be exhausted", -1, input.read());
+ }
+
+ public void testNewInput_skip() throws IOException {
+ InputStream input = stringUnderTest.newInput();
+ int stringSize = stringUnderTest.size();
+ int nearEndIndex = stringSize * 2 / 3;
+ long skipped1 = input.skip(nearEndIndex);
+ assertEquals("InputStream.skip()", skipped1, nearEndIndex);
+ assertEquals("InputStream.available()",
+ stringSize - skipped1, input.available());
+ assertTrue("InputStream.mark() is available", input.markSupported());
+ input.mark(0);
+ assertEquals("InputStream.skip(), read()",
+ stringUnderTest.byteAt(nearEndIndex) & 0xFF, input.read());
+ assertEquals("InputStream.available()",
+ stringSize - skipped1 - 1, input.available());
+ long skipped2 = input.skip(stringSize);
+ assertEquals("InputStream.skip() incomplete",
+ skipped2, stringSize - skipped1 - 1);
+ assertEquals("InputStream.skip(), no more input", 0, input.available());
+ assertEquals("InputStream.skip(), no more input", -1, input.read());
+ input.reset();
+ assertEquals("InputStream.reset() succeded",
+ stringSize - skipped1, input.available());
+ assertEquals("InputStream.reset(), read()",
+ stringUnderTest.byteAt(nearEndIndex) & 0xFF, input.read());
+ }
+
+ public void testNewCodedInput() throws IOException {
+ CodedInputStream cis = stringUnderTest.newCodedInput();
+ byte[] roundTripBytes = cis.readRawBytes(referenceBytes.length);
+ assertTrue(classUnderTest + " must give the same bytes back from the CodedInputStream",
+ Arrays.equals(referenceBytes, roundTripBytes));
+ assertTrue(classUnderTest + " CodedInputStream must now be exhausted", cis.isAtEnd());
+ }
+
+ /**
+ * Make sure we keep things simple when concatenating with empty. See also
+ * {@link ByteStringTest#testConcat_empty()}.
+ */
+ public void testConcat_empty() {
+ assertSame(classUnderTest + " concatenated with empty must give " + classUnderTest,
+ stringUnderTest.concat(ByteString.EMPTY), stringUnderTest);
+ assertSame("empty concatenated with " + classUnderTest + " must give " + classUnderTest,
+ ByteString.EMPTY.concat(stringUnderTest), stringUnderTest);
+ }
+
+ public void testJavaSerialization() throws Exception {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(out);
+ oos.writeObject(stringUnderTest);
+ oos.close();
+ byte[] pickled = out.toByteArray();
+ InputStream in = new ByteArrayInputStream(pickled);
+ ObjectInputStream ois = new ObjectInputStream(in);
+ Object o = ois.readObject();
+ assertTrue("Didn't get a ByteString back", o instanceof ByteString);
+ assertEquals("Should get an equal ByteString back", stringUnderTest, o);
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/LongArrayListTest.java b/java/core/src/test/java/com/google/protobuf/LongArrayListTest.java
new file mode 100644
index 00000000..1bd094f7
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/LongArrayListTest.java
@@ -0,0 +1,473 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// 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 static java.util.Arrays.asList;
+
+import junit.framework.TestCase;
+
+import java.util.Collections;
+import java.util.ConcurrentModificationException;
+import java.util.Iterator;
+
+/**
+ * Tests for {@link LongArrayList}.
+ *
+ * @author dweis@google.com (Daniel Weis)
+ */
+public class LongArrayListTest extends TestCase {
+
+ private static final LongArrayList UNARY_LIST = newImmutableLongArrayList(1);
+ private static final LongArrayList TERTIARY_LIST =
+ newImmutableLongArrayList(1, 2, 3);
+
+ private LongArrayList list;
+
+ @Override
+ protected void setUp() throws Exception {
+ list = new LongArrayList();
+ }
+
+ public void testEmptyListReturnsSameInstance() {
+ assertSame(LongArrayList.emptyList(), LongArrayList.emptyList());
+ }
+
+ public void testEmptyListIsImmutable() {
+ assertImmutable(LongArrayList.emptyList());
+ }
+
+ public void testMakeImmutable() {
+ list.addLong(2);
+ list.addLong(4);
+ list.addLong(6);
+ list.addLong(8);
+ list.makeImmutable();
+ assertImmutable(list);
+ }
+
+ public void testCopyConstructor() {
+ LongArrayList copy = new LongArrayList(TERTIARY_LIST);
+ assertEquals(TERTIARY_LIST, copy);
+
+ copy = new LongArrayList(LongArrayList.emptyList());
+ assertEquals(LongArrayList.emptyList(), copy);
+
+ copy = new LongArrayList(asList(1L, 2L, 3L));
+ assertEquals(asList(1L, 2L, 3L), copy);
+
+ copy = new LongArrayList(Collections.<Long>emptyList());
+ assertEquals(LongArrayList.emptyList(), copy);
+ }
+
+ public void testModificationWithIteration() {
+ list.addAll(asList(1L, 2L, 3L, 4L));
+ Iterator<Long> iterator = list.iterator();
+ assertEquals(4, list.size());
+ assertEquals(1, (long) list.get(0));
+ assertEquals(1, (long) iterator.next());
+ list.set(0, 1L);
+ assertEquals(2, (long) iterator.next());
+
+ list.remove(0);
+ try {
+ iterator.next();
+ fail();
+ } catch (ConcurrentModificationException e) {
+ // expected
+ }
+
+ iterator = list.iterator();
+ list.add(0, 0L);
+ try {
+ iterator.next();
+ fail();
+ } catch (ConcurrentModificationException e) {
+ // expected
+ }
+ }
+
+ public void testGet() {
+ assertEquals(1, (long) TERTIARY_LIST.get(0));
+ assertEquals(2, (long) TERTIARY_LIST.get(1));
+ assertEquals(3, (long) TERTIARY_LIST.get(2));
+
+ try {
+ TERTIARY_LIST.get(-1);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ TERTIARY_LIST.get(3);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testGetLong() {
+ assertEquals(1, TERTIARY_LIST.getLong(0));
+ assertEquals(2, TERTIARY_LIST.getLong(1));
+ assertEquals(3, TERTIARY_LIST.getLong(2));
+
+ try {
+ TERTIARY_LIST.get(-1);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ TERTIARY_LIST.get(3);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testSize() {
+ assertEquals(0, LongArrayList.emptyList().size());
+ assertEquals(1, UNARY_LIST.size());
+ assertEquals(3, TERTIARY_LIST.size());
+
+ list.addLong(2);
+ list.addLong(4);
+ list.addLong(6);
+ list.addLong(8);
+ assertEquals(4, list.size());
+
+ list.remove(0);
+ assertEquals(3, list.size());
+
+ list.add(16L);
+ assertEquals(4, list.size());
+ }
+
+ public void testSet() {
+ list.addLong(2);
+ list.addLong(4);
+
+ assertEquals(2, (long) list.set(0, 0L));
+ assertEquals(0, list.getLong(0));
+
+ assertEquals(4, (long) list.set(1, 0L));
+ assertEquals(0, list.getLong(1));
+
+ try {
+ list.set(-1, 0L);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ list.set(2, 0L);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testSetLong() {
+ list.addLong(2);
+ list.addLong(4);
+
+ assertEquals(2, list.setLong(0, 0));
+ assertEquals(0, list.getLong(0));
+
+ assertEquals(4, list.setLong(1, 0));
+ assertEquals(0, list.getLong(1));
+
+ try {
+ list.setLong(-1, 0);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ list.setLong(2, 0);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testAdd() {
+ assertEquals(0, list.size());
+
+ assertTrue(list.add(2L));
+ assertEquals(asList(2L), list);
+
+ assertTrue(list.add(3L));
+ list.add(0, 4L);
+ assertEquals(asList(4L, 2L, 3L), list);
+
+ list.add(0, 1L);
+ list.add(0, 0L);
+ // Force a resize by getting up to 11 elements.
+ for (int i = 0; i < 6; i++) {
+ list.add(Long.valueOf(5 + i));
+ }
+ assertEquals(asList(0L, 1L, 4L, 2L, 3L, 5L, 6L, 7L, 8L, 9L, 10L), list);
+
+ try {
+ list.add(-1, 5L);
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ list.add(4, 5L);
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testAddLong() {
+ assertEquals(0, list.size());
+
+ list.addLong(2);
+ assertEquals(asList(2L), list);
+
+ list.addLong(3);
+ assertEquals(asList(2L, 3L), list);
+ }
+
+ public void testAddAll() {
+ assertEquals(0, list.size());
+
+ assertTrue(list.addAll(Collections.singleton(1L)));
+ assertEquals(1, list.size());
+ assertEquals(1, (long) list.get(0));
+ assertEquals(1, list.getLong(0));
+
+ assertTrue(list.addAll(asList(2L, 3L, 4L, 5L, 6L)));
+ assertEquals(asList(1L, 2L, 3L, 4L, 5L, 6L), list);
+
+ assertTrue(list.addAll(TERTIARY_LIST));
+ assertEquals(asList(1L, 2L, 3L, 4L, 5L, 6L, 1L, 2L, 3L), list);
+
+ assertFalse(list.addAll(Collections.<Long>emptyList()));
+ assertFalse(list.addAll(LongArrayList.emptyList()));
+ }
+
+ public void testRemove() {
+ list.addAll(TERTIARY_LIST);
+ assertEquals(1, (long) list.remove(0));
+ assertEquals(asList(2L, 3L), list);
+
+ assertTrue(list.remove(3L));
+ assertEquals(asList(2L), list);
+
+ assertFalse(list.remove(3L));
+ assertEquals(asList(2L), list);
+
+ assertEquals(2, (long) list.remove(0));
+ assertEquals(asList(), list);
+
+ try {
+ list.remove(-1);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ list.remove(0);
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ private void assertImmutable(LongArrayList list) {
+ if (list.contains(1L)) {
+ throw new RuntimeException("Cannot test the immutability of lists that contain 1.");
+ }
+
+ try {
+ list.add(1L);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.add(0, 1L);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(Collections.<Long>emptyList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(Collections.singletonList(1L));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(new LongArrayList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(UNARY_LIST);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(0, Collections.singleton(1L));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(0, UNARY_LIST);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(0, Collections.<Long>emptyList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addLong(0);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.clear();
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.remove(1);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.remove(new Object());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.removeAll(Collections.<Long>emptyList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.removeAll(Collections.singleton(1L));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.removeAll(UNARY_LIST);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.retainAll(Collections.<Long>emptyList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.retainAll(Collections.singleton(1L));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.retainAll(UNARY_LIST);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.set(0, 0L);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.setLong(0, 0);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ }
+
+ private static LongArrayList newImmutableLongArrayList(long... elements) {
+ LongArrayList list = new LongArrayList();
+ for (long element : elements) {
+ list.addLong(element);
+ }
+ list.makeImmutable();
+ return list;
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/MapForProto2LiteTest.java b/java/core/src/test/java/com/google/protobuf/MapForProto2LiteTest.java
new file mode 100644
index 00000000..3d8c9bc4
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/MapForProto2LiteTest.java
@@ -0,0 +1,458 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// 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 map_lite_test.MapForProto2TestProto.TestMap;
+import map_lite_test.MapForProto2TestProto.TestMap.MessageValue;
+import map_lite_test.MapForProto2TestProto.TestUnknownEnumValue;
+
+import junit.framework.TestCase;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Unit tests for map fields.
+ */
+public class MapForProto2LiteTest extends TestCase {
+ private void setMapValues(TestMap.Builder builder) {
+ builder.getMutableInt32ToInt32Field().put(1, 11);
+ builder.getMutableInt32ToInt32Field().put(2, 22);
+ builder.getMutableInt32ToInt32Field().put(3, 33);
+
+ builder.getMutableInt32ToStringField().put(1, "11");
+ builder.getMutableInt32ToStringField().put(2, "22");
+ builder.getMutableInt32ToStringField().put(3, "33");
+
+ builder.getMutableInt32ToBytesField().put(1, TestUtil.toBytes("11"));
+ builder.getMutableInt32ToBytesField().put(2, TestUtil.toBytes("22"));
+ builder.getMutableInt32ToBytesField().put(3, TestUtil.toBytes("33"));
+
+ builder.getMutableInt32ToEnumField().put(1, TestMap.EnumValue.FOO);
+ builder.getMutableInt32ToEnumField().put(2, TestMap.EnumValue.BAR);
+ builder.getMutableInt32ToEnumField().put(3, TestMap.EnumValue.BAZ);
+
+ builder.getMutableInt32ToMessageField().put(
+ 1, MessageValue.newBuilder().setValue(11).build());
+ builder.getMutableInt32ToMessageField().put(
+ 2, MessageValue.newBuilder().setValue(22).build());
+ builder.getMutableInt32ToMessageField().put(
+ 3, MessageValue.newBuilder().setValue(33).build());
+
+ builder.getMutableStringToInt32Field().put("1", 11);
+ builder.getMutableStringToInt32Field().put("2", 22);
+ builder.getMutableStringToInt32Field().put("3", 33);
+ }
+
+ private void copyMapValues(TestMap source, TestMap.Builder destination) {
+ destination
+ .putAllInt32ToInt32Field(source.getInt32ToInt32Field())
+ .putAllInt32ToStringField(source.getInt32ToStringField())
+ .putAllInt32ToBytesField(source.getInt32ToBytesField())
+ .putAllInt32ToEnumField(source.getInt32ToEnumField())
+ .putAllInt32ToMessageField(source.getInt32ToMessageField())
+ .putAllStringToInt32Field(source.getStringToInt32Field());
+ }
+
+ private void assertMapValuesSet(TestMap message) {
+ assertEquals(3, message.getInt32ToInt32Field().size());
+ assertEquals(11, message.getInt32ToInt32Field().get(1).intValue());
+ assertEquals(22, message.getInt32ToInt32Field().get(2).intValue());
+ assertEquals(33, message.getInt32ToInt32Field().get(3).intValue());
+
+ assertEquals(3, message.getInt32ToStringField().size());
+ assertEquals("11", message.getInt32ToStringField().get(1));
+ assertEquals("22", message.getInt32ToStringField().get(2));
+ assertEquals("33", message.getInt32ToStringField().get(3));
+
+ assertEquals(3, message.getInt32ToBytesField().size());
+ assertEquals(TestUtil.toBytes("11"), message.getInt32ToBytesField().get(1));
+ assertEquals(TestUtil.toBytes("22"), message.getInt32ToBytesField().get(2));
+ assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesField().get(3));
+
+ assertEquals(3, message.getInt32ToEnumField().size());
+ assertEquals(TestMap.EnumValue.FOO, message.getInt32ToEnumField().get(1));
+ assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(2));
+ assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumField().get(3));
+
+ assertEquals(3, message.getInt32ToMessageField().size());
+ assertEquals(11, message.getInt32ToMessageField().get(1).getValue());
+ assertEquals(22, message.getInt32ToMessageField().get(2).getValue());
+ assertEquals(33, message.getInt32ToMessageField().get(3).getValue());
+
+ assertEquals(3, message.getStringToInt32Field().size());
+ assertEquals(11, message.getStringToInt32Field().get("1").intValue());
+ assertEquals(22, message.getStringToInt32Field().get("2").intValue());
+ assertEquals(33, message.getStringToInt32Field().get("3").intValue());
+ }
+
+ private void updateMapValues(TestMap.Builder builder) {
+ builder.getMutableInt32ToInt32Field().put(1, 111);
+ builder.getMutableInt32ToInt32Field().remove(2);
+ builder.getMutableInt32ToInt32Field().put(4, 44);
+
+ builder.getMutableInt32ToStringField().put(1, "111");
+ builder.getMutableInt32ToStringField().remove(2);
+ builder.getMutableInt32ToStringField().put(4, "44");
+
+ builder.getMutableInt32ToBytesField().put(1, TestUtil.toBytes("111"));
+ builder.getMutableInt32ToBytesField().remove(2);
+ builder.getMutableInt32ToBytesField().put(4, TestUtil.toBytes("44"));
+
+ builder.getMutableInt32ToEnumField().put(1, TestMap.EnumValue.BAR);
+ builder.getMutableInt32ToEnumField().remove(2);
+ builder.getMutableInt32ToEnumField().put(4, TestMap.EnumValue.QUX);
+
+ builder.getMutableInt32ToMessageField().put(
+ 1, MessageValue.newBuilder().setValue(111).build());
+ builder.getMutableInt32ToMessageField().remove(2);
+ builder.getMutableInt32ToMessageField().put(
+ 4, MessageValue.newBuilder().setValue(44).build());
+
+ builder.getMutableStringToInt32Field().put("1", 111);
+ builder.getMutableStringToInt32Field().remove("2");
+ builder.getMutableStringToInt32Field().put("4", 44);
+ }
+
+ private void assertMapValuesUpdated(TestMap message) {
+ assertEquals(3, message.getInt32ToInt32Field().size());
+ assertEquals(111, message.getInt32ToInt32Field().get(1).intValue());
+ assertEquals(33, message.getInt32ToInt32Field().get(3).intValue());
+ assertEquals(44, message.getInt32ToInt32Field().get(4).intValue());
+
+ assertEquals(3, message.getInt32ToStringField().size());
+ assertEquals("111", message.getInt32ToStringField().get(1));
+ assertEquals("33", message.getInt32ToStringField().get(3));
+ assertEquals("44", message.getInt32ToStringField().get(4));
+
+ assertEquals(3, message.getInt32ToBytesField().size());
+ assertEquals(TestUtil.toBytes("111"), message.getInt32ToBytesField().get(1));
+ assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesField().get(3));
+ assertEquals(TestUtil.toBytes("44"), message.getInt32ToBytesField().get(4));
+
+ assertEquals(3, message.getInt32ToEnumField().size());
+ assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(1));
+ assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumField().get(3));
+ assertEquals(TestMap.EnumValue.QUX, message.getInt32ToEnumField().get(4));
+
+ assertEquals(3, message.getInt32ToMessageField().size());
+ assertEquals(111, message.getInt32ToMessageField().get(1).getValue());
+ assertEquals(33, message.getInt32ToMessageField().get(3).getValue());
+ assertEquals(44, message.getInt32ToMessageField().get(4).getValue());
+
+ assertEquals(3, message.getStringToInt32Field().size());
+ assertEquals(111, message.getStringToInt32Field().get("1").intValue());
+ assertEquals(33, message.getStringToInt32Field().get("3").intValue());
+ assertEquals(44, message.getStringToInt32Field().get("4").intValue());
+ }
+
+ private void assertMapValuesCleared(TestMap message) {
+ assertEquals(0, message.getInt32ToInt32Field().size());
+ assertEquals(0, message.getInt32ToStringField().size());
+ assertEquals(0, message.getInt32ToBytesField().size());
+ assertEquals(0, message.getInt32ToEnumField().size());
+ assertEquals(0, message.getInt32ToMessageField().size());
+ assertEquals(0, message.getStringToInt32Field().size());
+ }
+
+ public void testSanityCopyOnWrite() throws InvalidProtocolBufferException {
+ // Since builders are implemented as a thin wrapper around a message
+ // instance, we attempt to verify that we can't cause the builder to modify
+ // a produced message.
+
+ TestMap.Builder builder = TestMap.newBuilder();
+ TestMap message = builder.build();
+ Map<Integer, Integer> intMap = builder.getMutableInt32ToInt32Field();
+ intMap.put(1, 2);
+ assertTrue(message.getInt32ToInt32Field().isEmpty());
+ message = builder.build();
+ try {
+ intMap.put(2, 3);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ assertEquals(newMap(1, 2), message.getInt32ToInt32Field());
+ assertEquals(newMap(1, 2), builder.getInt32ToInt32Field());
+ builder.getMutableInt32ToInt32Field().put(2, 3);
+ assertEquals(newMap(1, 2), message.getInt32ToInt32Field());
+ assertEquals(newMap(1, 2, 2, 3), builder.getInt32ToInt32Field());
+ }
+
+ public void testMutableMapLifecycle() {
+ TestMap.Builder builder = TestMap.newBuilder();
+ Map<Integer, Integer> intMap = builder.getMutableInt32ToInt32Field();
+ intMap.put(1, 2);
+ assertEquals(newMap(1, 2), builder.build().getInt32ToInt32Field());
+ try {
+ intMap.put(2, 3);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ assertEquals(newMap(1, 2), builder.getInt32ToInt32Field());
+ builder.getMutableInt32ToInt32Field().put(2, 3);
+ assertEquals(newMap(1, 2, 2, 3), builder.getInt32ToInt32Field());
+
+ Map<Integer, TestMap.EnumValue> enumMap = builder.getMutableInt32ToEnumField();
+ enumMap.put(1, TestMap.EnumValue.BAR);
+ assertEquals(newMap(1, TestMap.EnumValue.BAR), builder.build().getInt32ToEnumField());
+ try {
+ enumMap.put(2, TestMap.EnumValue.FOO);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ assertEquals(newMap(1, TestMap.EnumValue.BAR), builder.getInt32ToEnumField());
+ builder.getMutableInt32ToEnumField().put(2, TestMap.EnumValue.FOO);
+ assertEquals(
+ newMap(1, TestMap.EnumValue.BAR, 2, TestMap.EnumValue.FOO),
+ builder.getInt32ToEnumField());
+
+ Map<Integer, String> stringMap = builder.getMutableInt32ToStringField();
+ stringMap.put(1, "1");
+ assertEquals(newMap(1, "1"), builder.build().getInt32ToStringField());
+ try {
+ stringMap.put(2, "2");
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ assertEquals(newMap(1, "1"), builder.getInt32ToStringField());
+ builder.getMutableInt32ToStringField().put(2, "2");
+ assertEquals(
+ newMap(1, "1", 2, "2"),
+ builder.getInt32ToStringField());
+
+ Map<Integer, TestMap.MessageValue> messageMap = builder.getMutableInt32ToMessageField();
+ messageMap.put(1, TestMap.MessageValue.getDefaultInstance());
+ assertEquals(newMap(1, TestMap.MessageValue.getDefaultInstance()),
+ builder.build().getInt32ToMessageField());
+ try {
+ messageMap.put(2, TestMap.MessageValue.getDefaultInstance());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ assertEquals(newMap(1, TestMap.MessageValue.getDefaultInstance()),
+ builder.getInt32ToMessageField());
+ builder.getMutableInt32ToMessageField().put(2, TestMap.MessageValue.getDefaultInstance());
+ assertEquals(
+ newMap(1, TestMap.MessageValue.getDefaultInstance(),
+ 2, TestMap.MessageValue.getDefaultInstance()),
+ builder.getInt32ToMessageField());
+ }
+
+ public void testMutableMapLifecycle_collections() {
+ TestMap.Builder builder = TestMap.newBuilder();
+ Map<Integer, Integer> intMap = builder.getMutableInt32ToInt32Field();
+ intMap.put(1, 2);
+ assertEquals(newMap(1, 2), builder.build().getInt32ToInt32Field());
+ try {
+ intMap.remove(2);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ try {
+ intMap.entrySet().remove(new Object());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ try {
+ intMap.entrySet().iterator().remove();
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ try {
+ intMap.keySet().remove(new Object());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ try {
+ intMap.values().remove(new Object());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ try {
+ intMap.values().iterator().remove();
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ assertEquals(newMap(1, 2), intMap);
+ assertEquals(newMap(1, 2), builder.getInt32ToInt32Field());
+ assertEquals(newMap(1, 2), builder.build().getInt32ToInt32Field());
+ }
+
+ public void testGettersAndSetters() throws Exception {
+ TestMap.Builder builder = TestMap.newBuilder();
+ TestMap message = builder.build();
+ assertMapValuesCleared(message);
+
+ builder = message.toBuilder();
+ setMapValues(builder);
+ message = builder.build();
+ assertMapValuesSet(message);
+
+ builder = message.toBuilder();
+ updateMapValues(builder);
+ message = builder.build();
+ assertMapValuesUpdated(message);
+
+ builder = message.toBuilder();
+ builder.clear();
+ message = builder.build();
+ assertMapValuesCleared(message);
+ }
+
+ public void testPutAll() throws Exception {
+ TestMap.Builder sourceBuilder = TestMap.newBuilder();
+ setMapValues(sourceBuilder);
+ TestMap source = sourceBuilder.build();
+
+ TestMap.Builder destination = TestMap.newBuilder();
+ copyMapValues(source, destination);
+ assertMapValuesSet(destination.build());
+ }
+
+ public void testSerializeAndParse() throws Exception {
+ TestMap.Builder builder = TestMap.newBuilder();
+ setMapValues(builder);
+ TestMap message = builder.build();
+ assertEquals(message.getSerializedSize(), message.toByteString().size());
+ message = TestMap.parser().parseFrom(message.toByteString());
+ assertMapValuesSet(message);
+
+ builder = message.toBuilder();
+ updateMapValues(builder);
+ message = builder.build();
+ assertEquals(message.getSerializedSize(), message.toByteString().size());
+ message = TestMap.parser().parseFrom(message.toByteString());
+ assertMapValuesUpdated(message);
+
+ builder = message.toBuilder();
+ builder.clear();
+ message = builder.build();
+ assertEquals(message.getSerializedSize(), message.toByteString().size());
+ message = TestMap.parser().parseFrom(message.toByteString());
+ assertMapValuesCleared(message);
+ }
+
+ public void testMergeFrom() throws Exception {
+ TestMap.Builder builder = TestMap.newBuilder();
+ setMapValues(builder);
+ TestMap message = builder.build();
+
+ TestMap.Builder other = TestMap.newBuilder();
+ other.mergeFrom(message);
+ assertMapValuesSet(other.build());
+ }
+
+ public void testEqualsAndHashCode() throws Exception {
+ // Test that generated equals() and hashCode() will disregard the order
+ // of map entries when comparing/hashing map fields.
+
+ // We can't control the order of elements in a HashMap. The best we can do
+ // here is to add elements in different order.
+ TestMap.Builder b1 = TestMap.newBuilder();
+ b1.getMutableInt32ToInt32Field().put(1, 2);
+ b1.getMutableInt32ToInt32Field().put(3, 4);
+ b1.getMutableInt32ToInt32Field().put(5, 6);
+ TestMap m1 = b1.build();
+
+ TestMap.Builder b2 = TestMap.newBuilder();
+ b2.getMutableInt32ToInt32Field().put(5, 6);
+ b2.getMutableInt32ToInt32Field().put(1, 2);
+ b2.getMutableInt32ToInt32Field().put(3, 4);
+ TestMap m2 = b2.build();
+
+ assertEquals(m1, m2);
+ assertEquals(m1.hashCode(), m2.hashCode());
+
+ // Make sure we did compare map fields.
+ b2.getMutableInt32ToInt32Field().put(1, 0);
+ m2 = b2.build();
+ assertFalse(m1.equals(m2));
+ // Don't check m1.hashCode() != m2.hashCode() because it's not guaranteed
+ // to be different.
+ }
+
+ public void testUnknownEnumValues() throws Exception {
+ TestUnknownEnumValue.Builder builder =
+ TestUnknownEnumValue.newBuilder();
+ builder.getMutableInt32ToInt32Field().put(1, 1);
+ builder.getMutableInt32ToInt32Field().put(2, 54321);
+ ByteString data = builder.build().toByteString();
+
+ TestMap message = TestMap.parseFrom(data);
+ // Entries with unknown enum values will be stored into UnknownFieldSet so
+ // there is only one entry in the map.
+ assertEquals(1, message.getInt32ToEnumField().size());
+ assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(1));
+ // Serializing and parsing should preserve the unknown entry.
+ data = message.toByteString();
+ TestUnknownEnumValue messageWithUnknownEnums =
+ TestUnknownEnumValue.parseFrom(data);
+ assertEquals(2, messageWithUnknownEnums.getInt32ToInt32Field().size());
+ assertEquals(1, messageWithUnknownEnums.getInt32ToInt32Field().get(1).intValue());
+ assertEquals(54321, messageWithUnknownEnums.getInt32ToInt32Field().get(2).intValue());
+ }
+
+
+ public void testIterationOrder() throws Exception {
+ TestMap.Builder builder = TestMap.newBuilder();
+ setMapValues(builder);
+ TestMap message = builder.build();
+
+ assertEquals(Arrays.asList("1", "2", "3"),
+ new ArrayList<String>(message.getStringToInt32Field().keySet()));
+ }
+
+ private static <K, V> Map<K, V> newMap(K key1, V value1) {
+ Map<K, V> map = new HashMap<K, V>();
+ map.put(key1, value1);
+ return map;
+ }
+
+ private static <K, V> Map<K, V> newMap(K key1, V value1, K key2, V value2) {
+ Map<K, V> map = new HashMap<K, V>();
+ map.put(key1, value1);
+ map.put(key2, value2);
+ return map;
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/MapForProto2Test.java b/java/core/src/test/java/com/google/protobuf/MapForProto2Test.java
new file mode 100644
index 00000000..1fa3cbdb
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/MapForProto2Test.java
@@ -0,0 +1,684 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// 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 com.google.protobuf.Descriptors.FieldDescriptor;
+import map_test.MapForProto2TestProto.TestMap;
+import map_test.MapForProto2TestProto.TestMap.MessageValue;
+import map_test.MapForProto2TestProto.TestMap.MessageWithRequiredFields;
+import map_test.MapForProto2TestProto.TestRecursiveMap;
+import map_test.MapForProto2TestProto.TestUnknownEnumValue;
+
+import junit.framework.TestCase;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Unit tests for map fields in proto2 protos.
+ */
+public class MapForProto2Test extends TestCase {
+ private void setMapValues(TestMap.Builder builder) {
+ builder.getMutableInt32ToInt32Field().put(1, 11);
+ builder.getMutableInt32ToInt32Field().put(2, 22);
+ builder.getMutableInt32ToInt32Field().put(3, 33);
+
+ builder.getMutableInt32ToStringField().put(1, "11");
+ builder.getMutableInt32ToStringField().put(2, "22");
+ builder.getMutableInt32ToStringField().put(3, "33");
+
+ builder.getMutableInt32ToBytesField().put(1, TestUtil.toBytes("11"));
+ builder.getMutableInt32ToBytesField().put(2, TestUtil.toBytes("22"));
+ builder.getMutableInt32ToBytesField().put(3, TestUtil.toBytes("33"));
+
+ builder.getMutableInt32ToEnumField().put(1, TestMap.EnumValue.FOO);
+ builder.getMutableInt32ToEnumField().put(2, TestMap.EnumValue.BAR);
+ builder.getMutableInt32ToEnumField().put(3, TestMap.EnumValue.BAZ);
+
+ builder.getMutableInt32ToMessageField().put(
+ 1, MessageValue.newBuilder().setValue(11).build());
+ builder.getMutableInt32ToMessageField().put(
+ 2, MessageValue.newBuilder().setValue(22).build());
+ builder.getMutableInt32ToMessageField().put(
+ 3, MessageValue.newBuilder().setValue(33).build());
+
+ builder.getMutableStringToInt32Field().put("1", 11);
+ builder.getMutableStringToInt32Field().put("2", 22);
+ builder.getMutableStringToInt32Field().put("3", 33);
+ }
+
+ private void copyMapValues(TestMap source, TestMap.Builder destination) {
+ destination
+ .putAllInt32ToInt32Field(source.getInt32ToInt32Field())
+ .putAllInt32ToStringField(source.getInt32ToStringField())
+ .putAllInt32ToBytesField(source.getInt32ToBytesField())
+ .putAllInt32ToEnumField(source.getInt32ToEnumField())
+ .putAllInt32ToMessageField(source.getInt32ToMessageField())
+ .putAllStringToInt32Field(source.getStringToInt32Field());
+ }
+
+ private void assertMapValuesSet(TestMap message) {
+ assertEquals(3, message.getInt32ToInt32Field().size());
+ assertEquals(11, message.getInt32ToInt32Field().get(1).intValue());
+ assertEquals(22, message.getInt32ToInt32Field().get(2).intValue());
+ assertEquals(33, message.getInt32ToInt32Field().get(3).intValue());
+
+ assertEquals(3, message.getInt32ToStringField().size());
+ assertEquals("11", message.getInt32ToStringField().get(1));
+ assertEquals("22", message.getInt32ToStringField().get(2));
+ assertEquals("33", message.getInt32ToStringField().get(3));
+
+ assertEquals(3, message.getInt32ToBytesField().size());
+ assertEquals(TestUtil.toBytes("11"), message.getInt32ToBytesField().get(1));
+ assertEquals(TestUtil.toBytes("22"), message.getInt32ToBytesField().get(2));
+ assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesField().get(3));
+
+ assertEquals(3, message.getInt32ToEnumField().size());
+ assertEquals(TestMap.EnumValue.FOO, message.getInt32ToEnumField().get(1));
+ assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(2));
+ assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumField().get(3));
+
+ assertEquals(3, message.getInt32ToMessageField().size());
+ assertEquals(11, message.getInt32ToMessageField().get(1).getValue());
+ assertEquals(22, message.getInt32ToMessageField().get(2).getValue());
+ assertEquals(33, message.getInt32ToMessageField().get(3).getValue());
+
+ assertEquals(3, message.getStringToInt32Field().size());
+ assertEquals(11, message.getStringToInt32Field().get("1").intValue());
+ assertEquals(22, message.getStringToInt32Field().get("2").intValue());
+ assertEquals(33, message.getStringToInt32Field().get("3").intValue());
+ }
+
+ private void updateMapValues(TestMap.Builder builder) {
+ builder.getMutableInt32ToInt32Field().put(1, 111);
+ builder.getMutableInt32ToInt32Field().remove(2);
+ builder.getMutableInt32ToInt32Field().put(4, 44);
+
+ builder.getMutableInt32ToStringField().put(1, "111");
+ builder.getMutableInt32ToStringField().remove(2);
+ builder.getMutableInt32ToStringField().put(4, "44");
+
+ builder.getMutableInt32ToBytesField().put(1, TestUtil.toBytes("111"));
+ builder.getMutableInt32ToBytesField().remove(2);
+ builder.getMutableInt32ToBytesField().put(4, TestUtil.toBytes("44"));
+
+ builder.getMutableInt32ToEnumField().put(1, TestMap.EnumValue.BAR);
+ builder.getMutableInt32ToEnumField().remove(2);
+ builder.getMutableInt32ToEnumField().put(4, TestMap.EnumValue.QUX);
+
+ builder.getMutableInt32ToMessageField().put(
+ 1, MessageValue.newBuilder().setValue(111).build());
+ builder.getMutableInt32ToMessageField().remove(2);
+ builder.getMutableInt32ToMessageField().put(
+ 4, MessageValue.newBuilder().setValue(44).build());
+
+ builder.getMutableStringToInt32Field().put("1", 111);
+ builder.getMutableStringToInt32Field().remove("2");
+ builder.getMutableStringToInt32Field().put("4", 44);
+ }
+
+ private void assertMapValuesUpdated(TestMap message) {
+ assertEquals(3, message.getInt32ToInt32Field().size());
+ assertEquals(111, message.getInt32ToInt32Field().get(1).intValue());
+ assertEquals(33, message.getInt32ToInt32Field().get(3).intValue());
+ assertEquals(44, message.getInt32ToInt32Field().get(4).intValue());
+
+ assertEquals(3, message.getInt32ToStringField().size());
+ assertEquals("111", message.getInt32ToStringField().get(1));
+ assertEquals("33", message.getInt32ToStringField().get(3));
+ assertEquals("44", message.getInt32ToStringField().get(4));
+
+ assertEquals(3, message.getInt32ToBytesField().size());
+ assertEquals(TestUtil.toBytes("111"), message.getInt32ToBytesField().get(1));
+ assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesField().get(3));
+ assertEquals(TestUtil.toBytes("44"), message.getInt32ToBytesField().get(4));
+
+ assertEquals(3, message.getInt32ToEnumField().size());
+ assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(1));
+ assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumField().get(3));
+ assertEquals(TestMap.EnumValue.QUX, message.getInt32ToEnumField().get(4));
+
+ assertEquals(3, message.getInt32ToMessageField().size());
+ assertEquals(111, message.getInt32ToMessageField().get(1).getValue());
+ assertEquals(33, message.getInt32ToMessageField().get(3).getValue());
+ assertEquals(44, message.getInt32ToMessageField().get(4).getValue());
+
+ assertEquals(3, message.getStringToInt32Field().size());
+ assertEquals(111, message.getStringToInt32Field().get("1").intValue());
+ assertEquals(33, message.getStringToInt32Field().get("3").intValue());
+ assertEquals(44, message.getStringToInt32Field().get("4").intValue());
+ }
+
+ private void assertMapValuesCleared(TestMap message) {
+ assertEquals(0, message.getInt32ToInt32Field().size());
+ assertEquals(0, message.getInt32ToStringField().size());
+ assertEquals(0, message.getInt32ToBytesField().size());
+ assertEquals(0, message.getInt32ToEnumField().size());
+ assertEquals(0, message.getInt32ToMessageField().size());
+ assertEquals(0, message.getStringToInt32Field().size());
+ }
+
+ public void testMutableMapLifecycle() {
+ TestMap.Builder builder = TestMap.newBuilder();
+ Map<Integer, Integer> intMap = builder.getMutableInt32ToInt32Field();
+ intMap.put(1, 2);
+ assertEquals(newMap(1, 2), builder.build().getInt32ToInt32Field());
+ try {
+ intMap.put(2, 3);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ assertEquals(newMap(1, 2), builder.getInt32ToInt32Field());
+ builder.getMutableInt32ToInt32Field().put(2, 3);
+ assertEquals(newMap(1, 2, 2, 3), builder.getInt32ToInt32Field());
+
+ Map<Integer, TestMap.EnumValue> enumMap = builder.getMutableInt32ToEnumField();
+ enumMap.put(1, TestMap.EnumValue.BAR);
+ assertEquals(newMap(1, TestMap.EnumValue.BAR), builder.build().getInt32ToEnumField());
+ try {
+ enumMap.put(2, TestMap.EnumValue.FOO);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ assertEquals(newMap(1, TestMap.EnumValue.BAR), builder.getInt32ToEnumField());
+ builder.getMutableInt32ToEnumField().put(2, TestMap.EnumValue.FOO);
+ assertEquals(
+ newMap(1, TestMap.EnumValue.BAR, 2, TestMap.EnumValue.FOO),
+ builder.getInt32ToEnumField());
+
+ Map<Integer, String> stringMap = builder.getMutableInt32ToStringField();
+ stringMap.put(1, "1");
+ assertEquals(newMap(1, "1"), builder.build().getInt32ToStringField());
+ try {
+ stringMap.put(2, "2");
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ assertEquals(newMap(1, "1"), builder.getInt32ToStringField());
+ builder.getMutableInt32ToStringField().put(2, "2");
+ assertEquals(
+ newMap(1, "1", 2, "2"),
+ builder.getInt32ToStringField());
+
+ Map<Integer, TestMap.MessageValue> messageMap = builder.getMutableInt32ToMessageField();
+ messageMap.put(1, TestMap.MessageValue.getDefaultInstance());
+ assertEquals(newMap(1, TestMap.MessageValue.getDefaultInstance()),
+ builder.build().getInt32ToMessageField());
+ try {
+ messageMap.put(2, TestMap.MessageValue.getDefaultInstance());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ assertEquals(newMap(1, TestMap.MessageValue.getDefaultInstance()),
+ builder.getInt32ToMessageField());
+ builder.getMutableInt32ToMessageField().put(2, TestMap.MessageValue.getDefaultInstance());
+ assertEquals(
+ newMap(1, TestMap.MessageValue.getDefaultInstance(),
+ 2, TestMap.MessageValue.getDefaultInstance()),
+ builder.getInt32ToMessageField());
+ }
+
+ public void testMutableMapLifecycle_collections() {
+ TestMap.Builder builder = TestMap.newBuilder();
+ Map<Integer, Integer> intMap = builder.getMutableInt32ToInt32Field();
+ intMap.put(1, 2);
+ assertEquals(newMap(1, 2), builder.build().getInt32ToInt32Field());
+ try {
+ intMap.remove(2);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ try {
+ intMap.entrySet().remove(new Object());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ try {
+ intMap.entrySet().iterator().remove();
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ try {
+ intMap.keySet().remove(new Object());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ try {
+ intMap.values().remove(new Object());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ try {
+ intMap.values().iterator().remove();
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ assertEquals(newMap(1, 2), intMap);
+ assertEquals(newMap(1, 2), builder.getInt32ToInt32Field());
+ assertEquals(newMap(1, 2), builder.build().getInt32ToInt32Field());
+ }
+
+ public void testGettersAndSetters() throws Exception {
+ TestMap.Builder builder = TestMap.newBuilder();
+ TestMap message = builder.build();
+ assertMapValuesCleared(message);
+
+ builder = message.toBuilder();
+ setMapValues(builder);
+ message = builder.build();
+ assertMapValuesSet(message);
+
+ builder = message.toBuilder();
+ updateMapValues(builder);
+ message = builder.build();
+ assertMapValuesUpdated(message);
+
+ builder = message.toBuilder();
+ builder.clear();
+ message = builder.build();
+ assertMapValuesCleared(message);
+ }
+
+ public void testPutAll() throws Exception {
+ TestMap.Builder sourceBuilder = TestMap.newBuilder();
+ setMapValues(sourceBuilder);
+ TestMap source = sourceBuilder.build();
+
+ TestMap.Builder destination = TestMap.newBuilder();
+ copyMapValues(source, destination);
+ assertMapValuesSet(destination.build());
+ }
+
+ public void testSerializeAndParse() throws Exception {
+ TestMap.Builder builder = TestMap.newBuilder();
+ setMapValues(builder);
+ TestMap message = builder.build();
+ assertEquals(message.getSerializedSize(), message.toByteString().size());
+ message = TestMap.parser().parseFrom(message.toByteString());
+ assertMapValuesSet(message);
+
+ builder = message.toBuilder();
+ updateMapValues(builder);
+ message = builder.build();
+ assertEquals(message.getSerializedSize(), message.toByteString().size());
+ message = TestMap.parser().parseFrom(message.toByteString());
+ assertMapValuesUpdated(message);
+
+ builder = message.toBuilder();
+ builder.clear();
+ message = builder.build();
+ assertEquals(message.getSerializedSize(), message.toByteString().size());
+ message = TestMap.parser().parseFrom(message.toByteString());
+ assertMapValuesCleared(message);
+ }
+
+ public void testMergeFrom() throws Exception {
+ TestMap.Builder builder = TestMap.newBuilder();
+ setMapValues(builder);
+ TestMap message = builder.build();
+
+ TestMap.Builder other = TestMap.newBuilder();
+ other.mergeFrom(message);
+ assertMapValuesSet(other.build());
+ }
+
+ public void testEqualsAndHashCode() throws Exception {
+ // Test that generated equals() and hashCode() will disregard the order
+ // of map entries when comparing/hashing map fields.
+
+ // We can't control the order of elements in a HashMap. The best we can do
+ // here is to add elements in different order.
+ TestMap.Builder b1 = TestMap.newBuilder();
+ b1.getMutableInt32ToInt32Field().put(1, 2);
+ b1.getMutableInt32ToInt32Field().put(3, 4);
+ b1.getMutableInt32ToInt32Field().put(5, 6);
+ TestMap m1 = b1.build();
+
+ TestMap.Builder b2 = TestMap.newBuilder();
+ b2.getMutableInt32ToInt32Field().put(5, 6);
+ b2.getMutableInt32ToInt32Field().put(1, 2);
+ b2.getMutableInt32ToInt32Field().put(3, 4);
+ TestMap m2 = b2.build();
+
+ assertEquals(m1, m2);
+ assertEquals(m1.hashCode(), m2.hashCode());
+
+ // Make sure we did compare map fields.
+ b2.getMutableInt32ToInt32Field().put(1, 0);
+ m2 = b2.build();
+ assertFalse(m1.equals(m2));
+ // Don't check m1.hashCode() != m2.hashCode() because it's not guaranteed
+ // to be different.
+ }
+
+
+ // The following methods are used to test reflection API.
+
+ private static FieldDescriptor f(String name) {
+ return TestMap.getDescriptor().findFieldByName(name);
+ }
+
+ private static Object getFieldValue(Message mapEntry, String name) {
+ FieldDescriptor field = mapEntry.getDescriptorForType().findFieldByName(name);
+ return mapEntry.getField(field);
+ }
+
+ private static Message.Builder setFieldValue(
+ Message.Builder mapEntry, String name, Object value) {
+ FieldDescriptor field = mapEntry.getDescriptorForType().findFieldByName(name);
+ mapEntry.setField(field, value);
+ return mapEntry;
+ }
+
+ private static void assertHasMapValues(Message message, String name, Map<?, ?> values) {
+ FieldDescriptor field = f(name);
+ for (Object entry : (List<?>) message.getField(field)) {
+ Message mapEntry = (Message) entry;
+ Object key = getFieldValue(mapEntry, "key");
+ Object value = getFieldValue(mapEntry, "value");
+ assertTrue(values.containsKey(key));
+ assertEquals(value, values.get(key));
+ }
+ assertEquals(values.size(), message.getRepeatedFieldCount(field));
+ for (int i = 0; i < message.getRepeatedFieldCount(field); i++) {
+ Message mapEntry = (Message) message.getRepeatedField(field, i);
+ Object key = getFieldValue(mapEntry, "key");
+ Object value = getFieldValue(mapEntry, "value");
+ assertTrue(values.containsKey(key));
+ assertEquals(value, values.get(key));
+ }
+ }
+
+ private static <KeyType, ValueType>
+ Message newMapEntry(Message.Builder builder, String name, KeyType key, ValueType value) {
+ FieldDescriptor field = builder.getDescriptorForType().findFieldByName(name);
+ Message.Builder entryBuilder = builder.newBuilderForField(field);
+ FieldDescriptor keyField = entryBuilder.getDescriptorForType().findFieldByName("key");
+ FieldDescriptor valueField = entryBuilder.getDescriptorForType().findFieldByName("value");
+ entryBuilder.setField(keyField, key);
+ entryBuilder.setField(valueField, value);
+ return entryBuilder.build();
+ }
+
+ private static void setMapValues(Message.Builder builder, String name, Map<?, ?> values) {
+ List<Message> entryList = new ArrayList<Message>();
+ for (Map.Entry<?, ?> entry : values.entrySet()) {
+ entryList.add(newMapEntry(builder, name, entry.getKey(), entry.getValue()));
+ }
+ FieldDescriptor field = builder.getDescriptorForType().findFieldByName(name);
+ builder.setField(field, entryList);
+ }
+
+ private static <KeyType, ValueType>
+ Map<KeyType, ValueType> mapForValues(
+ KeyType key1, ValueType value1, KeyType key2, ValueType value2) {
+ Map<KeyType, ValueType> map = new HashMap<KeyType, ValueType>();
+ map.put(key1, value1);
+ map.put(key2, value2);
+ return map;
+ }
+
+ public void testReflectionApi() throws Exception {
+ // In reflection API, map fields are just repeated message fields.
+ TestMap.Builder builder = TestMap.newBuilder();
+ builder.getMutableInt32ToInt32Field().put(1, 2);
+ builder.getMutableInt32ToInt32Field().put(3, 4);
+ builder.getMutableInt32ToMessageField().put(
+ 11, MessageValue.newBuilder().setValue(22).build());
+ builder.getMutableInt32ToMessageField().put(
+ 33, MessageValue.newBuilder().setValue(44).build());
+ TestMap message = builder.build();
+
+ // Test getField(), getRepeatedFieldCount(), getRepeatedField().
+ assertHasMapValues(message, "int32_to_int32_field",
+ mapForValues(1, 2, 3, 4));
+ assertHasMapValues(message, "int32_to_message_field",
+ mapForValues(
+ 11, MessageValue.newBuilder().setValue(22).build(),
+ 33, MessageValue.newBuilder().setValue(44).build()));
+
+ // Test clearField()
+ builder.clearField(f("int32_to_int32_field"));
+ builder.clearField(f("int32_to_message_field"));
+ message = builder.build();
+ assertEquals(0, message.getInt32ToInt32Field().size());
+ assertEquals(0, message.getInt32ToMessageField().size());
+
+ // Test setField()
+ setMapValues(builder, "int32_to_int32_field",
+ mapForValues(11, 22, 33, 44));
+ setMapValues(builder, "int32_to_message_field",
+ mapForValues(
+ 111, MessageValue.newBuilder().setValue(222).build(),
+ 333, MessageValue.newBuilder().setValue(444).build()));
+ message = builder.build();
+ assertEquals(22, message.getInt32ToInt32Field().get(11).intValue());
+ assertEquals(44, message.getInt32ToInt32Field().get(33).intValue());
+ assertEquals(222, message.getInt32ToMessageField().get(111).getValue());
+ assertEquals(444, message.getInt32ToMessageField().get(333).getValue());
+
+ // Test addRepeatedField
+ builder.addRepeatedField(f("int32_to_int32_field"),
+ newMapEntry(builder, "int32_to_int32_field", 55, 66));
+ builder.addRepeatedField(f("int32_to_message_field"),
+ newMapEntry(builder, "int32_to_message_field", 555,
+ MessageValue.newBuilder().setValue(666).build()));
+ message = builder.build();
+ assertEquals(66, message.getInt32ToInt32Field().get(55).intValue());
+ assertEquals(666, message.getInt32ToMessageField().get(555).getValue());
+
+ // Test addRepeatedField (overriding existing values)
+ builder.addRepeatedField(f("int32_to_int32_field"),
+ newMapEntry(builder, "int32_to_int32_field", 55, 55));
+ builder.addRepeatedField(f("int32_to_message_field"),
+ newMapEntry(builder, "int32_to_message_field", 555,
+ MessageValue.newBuilder().setValue(555).build()));
+ message = builder.build();
+ assertEquals(55, message.getInt32ToInt32Field().get(55).intValue());
+ assertEquals(555, message.getInt32ToMessageField().get(555).getValue());
+
+ // Test setRepeatedField
+ for (int i = 0; i < builder.getRepeatedFieldCount(f("int32_to_int32_field")); i++) {
+ Message mapEntry = (Message) builder.getRepeatedField(f("int32_to_int32_field"), i);
+ int oldKey = ((Integer) getFieldValue(mapEntry, "key")).intValue();
+ int oldValue = ((Integer) getFieldValue(mapEntry, "value")).intValue();
+ // Swap key with value for each entry.
+ Message.Builder mapEntryBuilder = mapEntry.toBuilder();
+ setFieldValue(mapEntryBuilder, "key", oldValue);
+ setFieldValue(mapEntryBuilder, "value", oldKey);
+ builder.setRepeatedField(f("int32_to_int32_field"), i, mapEntryBuilder.build());
+ }
+ message = builder.build();
+ assertEquals(11, message.getInt32ToInt32Field().get(22).intValue());
+ assertEquals(33, message.getInt32ToInt32Field().get(44).intValue());
+ assertEquals(55, message.getInt32ToInt32Field().get(55).intValue());
+ }
+
+ public void testTextFormat() throws Exception {
+ TestMap.Builder builder = TestMap.newBuilder();
+ setMapValues(builder);
+ TestMap message = builder.build();
+
+ String textData = TextFormat.printToString(message);
+
+ builder = TestMap.newBuilder();
+ TextFormat.merge(textData, builder);
+ message = builder.build();
+
+ assertMapValuesSet(message);
+ }
+
+ public void testDynamicMessage() throws Exception {
+ TestMap.Builder builder = TestMap.newBuilder();
+ setMapValues(builder);
+ TestMap message = builder.build();
+
+ Message dynamicDefaultInstance =
+ DynamicMessage.getDefaultInstance(TestMap.getDescriptor());
+ Message dynamicMessage = dynamicDefaultInstance
+ .newBuilderForType().mergeFrom(message.toByteString()).build();
+
+ assertEquals(message, dynamicMessage);
+ assertEquals(message.hashCode(), dynamicMessage.hashCode());
+ }
+
+ public void testReflectionEqualsAndHashCode() throws Exception {
+ // Test that generated equals() and hashCode() will disregard the order
+ // of map entries when comparing/hashing map fields.
+
+ // We use DynamicMessage to test reflection based equals()/hashCode().
+ Message dynamicDefaultInstance =
+ DynamicMessage.getDefaultInstance(TestMap.getDescriptor());
+ FieldDescriptor field = f("int32_to_int32_field");
+
+ Message.Builder b1 = dynamicDefaultInstance.newBuilderForType();
+ b1.addRepeatedField(field, newMapEntry(b1, "int32_to_int32_field", 1, 2));
+ b1.addRepeatedField(field, newMapEntry(b1, "int32_to_int32_field", 3, 4));
+ b1.addRepeatedField(field, newMapEntry(b1, "int32_to_int32_field", 5, 6));
+ Message m1 = b1.build();
+
+ Message.Builder b2 = dynamicDefaultInstance.newBuilderForType();
+ b2.addRepeatedField(field, newMapEntry(b2, "int32_to_int32_field", 5, 6));
+ b2.addRepeatedField(field, newMapEntry(b2, "int32_to_int32_field", 1, 2));
+ b2.addRepeatedField(field, newMapEntry(b2, "int32_to_int32_field", 3, 4));
+ Message m2 = b2.build();
+
+ assertEquals(m1, m2);
+ assertEquals(m1.hashCode(), m2.hashCode());
+
+ // Make sure we did compare map fields.
+ b2.setRepeatedField(field, 0, newMapEntry(b1, "int32_to_int32_field", 0, 0));
+ m2 = b2.build();
+ assertFalse(m1.equals(m2));
+ // Don't check m1.hashCode() != m2.hashCode() because it's not guaranteed
+ // to be different.
+ }
+
+ public void testUnknownEnumValues() throws Exception {
+ TestUnknownEnumValue.Builder builder =
+ TestUnknownEnumValue.newBuilder();
+ builder.getMutableInt32ToInt32Field().put(1, 1);
+ builder.getMutableInt32ToInt32Field().put(2, 54321);
+ ByteString data = builder.build().toByteString();
+
+ TestMap message = TestMap.parseFrom(data);
+ // Entries with unknown enum values will be stored into UnknownFieldSet so
+ // there is only one entry in the map.
+ assertEquals(1, message.getInt32ToEnumField().size());
+ assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(1));
+ // UnknownFieldSet should not be empty.
+ assertFalse(message.getUnknownFields().asMap().isEmpty());
+ // Serializing and parsing should preserve the unknown entry.
+ data = message.toByteString();
+ TestUnknownEnumValue messageWithUnknownEnums =
+ TestUnknownEnumValue.parseFrom(data);
+ assertEquals(2, messageWithUnknownEnums.getInt32ToInt32Field().size());
+ assertEquals(1, messageWithUnknownEnums.getInt32ToInt32Field().get(1).intValue());
+ assertEquals(54321, messageWithUnknownEnums.getInt32ToInt32Field().get(2).intValue());
+ }
+
+
+ public void testRequiredMessage() throws Exception {
+ TestMap.Builder builder = TestMap.newBuilder();
+ builder.getMutableRequiredMessageMap().put(0,
+ MessageWithRequiredFields.newBuilder().buildPartial());
+ TestMap message = builder.buildPartial();
+ assertFalse(message.isInitialized());
+
+ builder.getMutableRequiredMessageMap().put(0,
+ MessageWithRequiredFields.newBuilder().setValue(1).build());
+ message = builder.build();
+ assertTrue(message.isInitialized());
+ }
+
+ public void testRecursiveMap() throws Exception {
+ TestRecursiveMap.Builder builder = TestRecursiveMap.newBuilder();
+ builder.getMutableRecursiveMapField().put(
+ 1, TestRecursiveMap.newBuilder().setValue(2).build());
+ builder.getMutableRecursiveMapField().put(
+ 3, TestRecursiveMap.newBuilder().setValue(4).build());
+ ByteString data = builder.build().toByteString();
+
+ TestRecursiveMap message = TestRecursiveMap.parseFrom(data);
+ assertEquals(2, message.getRecursiveMapField().get(1).getValue());
+ assertEquals(4, message.getRecursiveMapField().get(3).getValue());
+ }
+
+ public void testIterationOrder() throws Exception {
+ TestMap.Builder builder = TestMap.newBuilder();
+ setMapValues(builder);
+ TestMap message = builder.build();
+
+ assertEquals(Arrays.asList("1", "2", "3"),
+ new ArrayList<String>(message.getStringToInt32Field().keySet()));
+ }
+
+ // Regression test for b/20494788
+ public void testMapInitializationOrder() throws Exception {
+ assertEquals("RedactAllTypes", map_test.RedactAllTypes
+ .getDefaultInstance().getDescriptorForType().getName());
+
+ map_test.Message1.Builder builder =
+ map_test.Message1.newBuilder();
+ builder.getMutableMapField().put("key", true);
+ map_test.Message1 message = builder.build();
+ Message mapEntry = (Message) message.getRepeatedField(
+ message.getDescriptorForType().findFieldByName("map_field"), 0);
+ assertEquals(2, mapEntry.getAllFields().size());
+ }
+
+ private static <K, V> Map<K, V> newMap(K key1, V value1) {
+ Map<K, V> map = new HashMap<K, V>();
+ map.put(key1, value1);
+ return map;
+ }
+
+ private static <K, V> Map<K, V> newMap(K key1, V value1, K key2, V value2) {
+ Map<K, V> map = new HashMap<K, V>();
+ map.put(key1, value1);
+ map.put(key2, value2);
+ return map;
+ }
+}
+
diff --git a/java/core/src/test/java/com/google/protobuf/MapTest.java b/java/core/src/test/java/com/google/protobuf/MapTest.java
new file mode 100644
index 00000000..0e5c1284
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/MapTest.java
@@ -0,0 +1,783 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// 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 com.google.protobuf.Descriptors.Descriptor;
+import com.google.protobuf.Descriptors.EnumDescriptor;
+import com.google.protobuf.Descriptors.EnumValueDescriptor;
+import com.google.protobuf.Descriptors.FieldDescriptor;
+import map_test.MapTestProto.TestMap;
+import map_test.MapTestProto.TestMap.MessageValue;
+import map_test.MapTestProto.TestOnChangeEventPropagation;
+
+import junit.framework.TestCase;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Unit tests for map fields.
+ */
+public class MapTest extends TestCase {
+ private void setMapValues(TestMap.Builder builder) {
+ builder.getMutableInt32ToInt32Field().put(1, 11);
+ builder.getMutableInt32ToInt32Field().put(2, 22);
+ builder.getMutableInt32ToInt32Field().put(3, 33);
+
+ builder.getMutableInt32ToStringField().put(1, "11");
+ builder.getMutableInt32ToStringField().put(2, "22");
+ builder.getMutableInt32ToStringField().put(3, "33");
+
+ builder.getMutableInt32ToBytesField().put(1, TestUtil.toBytes("11"));
+ builder.getMutableInt32ToBytesField().put(2, TestUtil.toBytes("22"));
+ builder.getMutableInt32ToBytesField().put(3, TestUtil.toBytes("33"));
+
+ builder.getMutableInt32ToEnumField().put(1, TestMap.EnumValue.FOO);
+ builder.getMutableInt32ToEnumField().put(2, TestMap.EnumValue.BAR);
+ builder.getMutableInt32ToEnumField().put(3, TestMap.EnumValue.BAZ);
+
+ builder.getMutableInt32ToMessageField().put(
+ 1, MessageValue.newBuilder().setValue(11).build());
+ builder.getMutableInt32ToMessageField().put(
+ 2, MessageValue.newBuilder().setValue(22).build());
+ builder.getMutableInt32ToMessageField().put(
+ 3, MessageValue.newBuilder().setValue(33).build());
+
+ builder.getMutableStringToInt32Field().put("1", 11);
+ builder.getMutableStringToInt32Field().put("2", 22);
+ builder.getMutableStringToInt32Field().put("3", 33);
+ }
+
+ private void copyMapValues(TestMap source, TestMap.Builder destination) {
+ destination
+ .putAllInt32ToInt32Field(source.getInt32ToInt32Field())
+ .putAllInt32ToStringField(source.getInt32ToStringField())
+ .putAllInt32ToBytesField(source.getInt32ToBytesField())
+ .putAllInt32ToEnumField(source.getInt32ToEnumField())
+ .putAllInt32ToMessageField(source.getInt32ToMessageField())
+ .putAllStringToInt32Field(source.getStringToInt32Field());
+ }
+
+ private void assertMapValuesSet(TestMap message) {
+ assertEquals(3, message.getInt32ToInt32Field().size());
+ assertEquals(11, message.getInt32ToInt32Field().get(1).intValue());
+ assertEquals(22, message.getInt32ToInt32Field().get(2).intValue());
+ assertEquals(33, message.getInt32ToInt32Field().get(3).intValue());
+
+ assertEquals(3, message.getInt32ToStringField().size());
+ assertEquals("11", message.getInt32ToStringField().get(1));
+ assertEquals("22", message.getInt32ToStringField().get(2));
+ assertEquals("33", message.getInt32ToStringField().get(3));
+
+ assertEquals(3, message.getInt32ToBytesField().size());
+ assertEquals(TestUtil.toBytes("11"), message.getInt32ToBytesField().get(1));
+ assertEquals(TestUtil.toBytes("22"), message.getInt32ToBytesField().get(2));
+ assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesField().get(3));
+
+ assertEquals(3, message.getInt32ToEnumField().size());
+ assertEquals(TestMap.EnumValue.FOO, message.getInt32ToEnumField().get(1));
+ assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(2));
+ assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumField().get(3));
+
+ assertEquals(3, message.getInt32ToMessageField().size());
+ assertEquals(11, message.getInt32ToMessageField().get(1).getValue());
+ assertEquals(22, message.getInt32ToMessageField().get(2).getValue());
+ assertEquals(33, message.getInt32ToMessageField().get(3).getValue());
+
+ assertEquals(3, message.getStringToInt32Field().size());
+ assertEquals(11, message.getStringToInt32Field().get("1").intValue());
+ assertEquals(22, message.getStringToInt32Field().get("2").intValue());
+ assertEquals(33, message.getStringToInt32Field().get("3").intValue());
+ }
+
+ private void updateMapValues(TestMap.Builder builder) {
+ builder.getMutableInt32ToInt32Field().put(1, 111);
+ builder.getMutableInt32ToInt32Field().remove(2);
+ builder.getMutableInt32ToInt32Field().put(4, 44);
+
+ builder.getMutableInt32ToStringField().put(1, "111");
+ builder.getMutableInt32ToStringField().remove(2);
+ builder.getMutableInt32ToStringField().put(4, "44");
+
+ builder.getMutableInt32ToBytesField().put(1, TestUtil.toBytes("111"));
+ builder.getMutableInt32ToBytesField().remove(2);
+ builder.getMutableInt32ToBytesField().put(4, TestUtil.toBytes("44"));
+
+ builder.getMutableInt32ToEnumField().put(1, TestMap.EnumValue.BAR);
+ builder.getMutableInt32ToEnumField().remove(2);
+ builder.getMutableInt32ToEnumField().put(4, TestMap.EnumValue.QUX);
+
+ builder.getMutableInt32ToMessageField().put(
+ 1, MessageValue.newBuilder().setValue(111).build());
+ builder.getMutableInt32ToMessageField().remove(2);
+ builder.getMutableInt32ToMessageField().put(
+ 4, MessageValue.newBuilder().setValue(44).build());
+
+ builder.getMutableStringToInt32Field().put("1", 111);
+ builder.getMutableStringToInt32Field().remove("2");
+ builder.getMutableStringToInt32Field().put("4", 44);
+ }
+
+ private void assertMapValuesUpdated(TestMap message) {
+ assertEquals(3, message.getInt32ToInt32Field().size());
+ assertEquals(111, message.getInt32ToInt32Field().get(1).intValue());
+ assertEquals(33, message.getInt32ToInt32Field().get(3).intValue());
+ assertEquals(44, message.getInt32ToInt32Field().get(4).intValue());
+
+ assertEquals(3, message.getInt32ToStringField().size());
+ assertEquals("111", message.getInt32ToStringField().get(1));
+ assertEquals("33", message.getInt32ToStringField().get(3));
+ assertEquals("44", message.getInt32ToStringField().get(4));
+
+ assertEquals(3, message.getInt32ToBytesField().size());
+ assertEquals(TestUtil.toBytes("111"), message.getInt32ToBytesField().get(1));
+ assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesField().get(3));
+ assertEquals(TestUtil.toBytes("44"), message.getInt32ToBytesField().get(4));
+
+ assertEquals(3, message.getInt32ToEnumField().size());
+ assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(1));
+ assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumField().get(3));
+ assertEquals(TestMap.EnumValue.QUX, message.getInt32ToEnumField().get(4));
+
+ assertEquals(3, message.getInt32ToMessageField().size());
+ assertEquals(111, message.getInt32ToMessageField().get(1).getValue());
+ assertEquals(33, message.getInt32ToMessageField().get(3).getValue());
+ assertEquals(44, message.getInt32ToMessageField().get(4).getValue());
+
+ assertEquals(3, message.getStringToInt32Field().size());
+ assertEquals(111, message.getStringToInt32Field().get("1").intValue());
+ assertEquals(33, message.getStringToInt32Field().get("3").intValue());
+ assertEquals(44, message.getStringToInt32Field().get("4").intValue());
+ }
+
+ private void assertMapValuesCleared(TestMap message) {
+ assertEquals(0, message.getInt32ToInt32Field().size());
+ assertEquals(0, message.getInt32ToStringField().size());
+ assertEquals(0, message.getInt32ToBytesField().size());
+ assertEquals(0, message.getInt32ToEnumField().size());
+ assertEquals(0, message.getInt32ToMessageField().size());
+ assertEquals(0, message.getStringToInt32Field().size());
+ }
+
+ public void testMutableMapLifecycle() {
+ TestMap.Builder builder = TestMap.newBuilder();
+ Map<Integer, Integer> intMap = builder.getMutableInt32ToInt32Field();
+ intMap.put(1, 2);
+ assertEquals(newMap(1, 2), builder.build().getInt32ToInt32Field());
+ try {
+ intMap.put(2, 3);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ assertEquals(newMap(1, 2), builder.getInt32ToInt32Field());
+ builder.getMutableInt32ToInt32Field().put(2, 3);
+ assertEquals(newMap(1, 2, 2, 3), builder.getInt32ToInt32Field());
+
+ Map<Integer, TestMap.EnumValue> enumMap = builder.getMutableInt32ToEnumField();
+ enumMap.put(1, TestMap.EnumValue.BAR);
+ assertEquals(newMap(1, TestMap.EnumValue.BAR), builder.build().getInt32ToEnumField());
+ try {
+ enumMap.put(2, TestMap.EnumValue.FOO);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ assertEquals(newMap(1, TestMap.EnumValue.BAR), builder.getInt32ToEnumField());
+ builder.getMutableInt32ToEnumField().put(2, TestMap.EnumValue.FOO);
+ assertEquals(
+ newMap(1, TestMap.EnumValue.BAR, 2, TestMap.EnumValue.FOO),
+ builder.getInt32ToEnumField());
+
+ Map<Integer, String> stringMap = builder.getMutableInt32ToStringField();
+ stringMap.put(1, "1");
+ assertEquals(newMap(1, "1"), builder.build().getInt32ToStringField());
+ try {
+ stringMap.put(2, "2");
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ assertEquals(newMap(1, "1"), builder.getInt32ToStringField());
+ builder.getMutableInt32ToStringField().put(2, "2");
+ assertEquals(
+ newMap(1, "1", 2, "2"),
+ builder.getInt32ToStringField());
+
+ Map<Integer, TestMap.MessageValue> messageMap = builder.getMutableInt32ToMessageField();
+ messageMap.put(1, TestMap.MessageValue.getDefaultInstance());
+ assertEquals(newMap(1, TestMap.MessageValue.getDefaultInstance()),
+ builder.build().getInt32ToMessageField());
+ try {
+ messageMap.put(2, TestMap.MessageValue.getDefaultInstance());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ assertEquals(newMap(1, TestMap.MessageValue.getDefaultInstance()),
+ builder.getInt32ToMessageField());
+ builder.getMutableInt32ToMessageField().put(2, TestMap.MessageValue.getDefaultInstance());
+ assertEquals(
+ newMap(1, TestMap.MessageValue.getDefaultInstance(),
+ 2, TestMap.MessageValue.getDefaultInstance()),
+ builder.getInt32ToMessageField());
+ }
+
+ public void testMutableMapLifecycle_collections() {
+ TestMap.Builder builder = TestMap.newBuilder();
+ Map<Integer, Integer> intMap = builder.getMutableInt32ToInt32Field();
+ intMap.put(1, 2);
+ assertEquals(newMap(1, 2), builder.build().getInt32ToInt32Field());
+ try {
+ intMap.remove(2);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ try {
+ intMap.entrySet().remove(new Object());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ try {
+ intMap.entrySet().iterator().remove();
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ try {
+ intMap.keySet().remove(new Object());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ try {
+ intMap.values().remove(new Object());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ try {
+ intMap.values().iterator().remove();
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ assertEquals(newMap(1, 2), intMap);
+ assertEquals(newMap(1, 2), builder.getInt32ToInt32Field());
+ assertEquals(newMap(1, 2), builder.build().getInt32ToInt32Field());
+ }
+
+ public void testGettersAndSetters() throws Exception {
+ TestMap.Builder builder = TestMap.newBuilder();
+ TestMap message = builder.build();
+ assertMapValuesCleared(message);
+
+ builder = message.toBuilder();
+ setMapValues(builder);
+ message = builder.build();
+ assertMapValuesSet(message);
+
+ builder = message.toBuilder();
+ updateMapValues(builder);
+ message = builder.build();
+ assertMapValuesUpdated(message);
+
+ builder = message.toBuilder();
+ builder.clear();
+ message = builder.build();
+ assertMapValuesCleared(message);
+ }
+
+ public void testPutAll() throws Exception {
+ TestMap.Builder sourceBuilder = TestMap.newBuilder();
+ setMapValues(sourceBuilder);
+ TestMap source = sourceBuilder.build();
+
+ TestMap.Builder destination = TestMap.newBuilder();
+ copyMapValues(source, destination);
+ assertMapValuesSet(destination.build());
+ }
+
+ public void testPutAllForUnknownEnumValues() throws Exception {
+ TestMap.Builder sourceBuilder = TestMap.newBuilder();
+ sourceBuilder.getMutableInt32ToEnumFieldValue().put(0, 0);
+ sourceBuilder.getMutableInt32ToEnumFieldValue().put(1, 1);
+ sourceBuilder.getMutableInt32ToEnumFieldValue().put(2, 1000); // unknown value.
+ TestMap source = sourceBuilder.build();
+
+ TestMap.Builder destinationBuilder = TestMap.newBuilder();
+ destinationBuilder.putAllInt32ToEnumFieldValue(source.getInt32ToEnumFieldValue());
+ TestMap destination = destinationBuilder.build();
+
+ assertEquals(0, destination.getInt32ToEnumFieldValue().get(0).intValue());
+ assertEquals(1, destination.getInt32ToEnumFieldValue().get(1).intValue());
+ assertEquals(1000, destination.getInt32ToEnumFieldValue().get(2).intValue());
+ }
+
+ public void testSerializeAndParse() throws Exception {
+ TestMap.Builder builder = TestMap.newBuilder();
+ setMapValues(builder);
+ TestMap message = builder.build();
+ assertEquals(message.getSerializedSize(), message.toByteString().size());
+ message = TestMap.parser().parseFrom(message.toByteString());
+ assertMapValuesSet(message);
+
+ builder = message.toBuilder();
+ updateMapValues(builder);
+ message = builder.build();
+ assertEquals(message.getSerializedSize(), message.toByteString().size());
+ message = TestMap.parser().parseFrom(message.toByteString());
+ assertMapValuesUpdated(message);
+
+ builder = message.toBuilder();
+ builder.clear();
+ message = builder.build();
+ assertEquals(message.getSerializedSize(), message.toByteString().size());
+ message = TestMap.parser().parseFrom(message.toByteString());
+ assertMapValuesCleared(message);
+ }
+
+ public void testMergeFrom() throws Exception {
+ TestMap.Builder builder = TestMap.newBuilder();
+ setMapValues(builder);
+ TestMap message = builder.build();
+
+ TestMap.Builder other = TestMap.newBuilder();
+ other.mergeFrom(message);
+ assertMapValuesSet(other.build());
+ }
+
+ public void testEqualsAndHashCode() throws Exception {
+ // Test that generated equals() and hashCode() will disregard the order
+ // of map entries when comparing/hashing map fields.
+
+ // We can't control the order of elements in a HashMap. The best we can do
+ // here is to add elements in different order.
+ TestMap.Builder b1 = TestMap.newBuilder();
+ b1.getMutableInt32ToInt32Field().put(1, 2);
+ b1.getMutableInt32ToInt32Field().put(3, 4);
+ b1.getMutableInt32ToInt32Field().put(5, 6);
+ TestMap m1 = b1.build();
+
+ TestMap.Builder b2 = TestMap.newBuilder();
+ b2.getMutableInt32ToInt32Field().put(5, 6);
+ b2.getMutableInt32ToInt32Field().put(1, 2);
+ b2.getMutableInt32ToInt32Field().put(3, 4);
+ TestMap m2 = b2.build();
+
+ assertEquals(m1, m2);
+ assertEquals(m1.hashCode(), m2.hashCode());
+
+ // Make sure we did compare map fields.
+ b2.getMutableInt32ToInt32Field().put(1, 0);
+ m2 = b2.build();
+ assertFalse(m1.equals(m2));
+ // Don't check m1.hashCode() != m2.hashCode() because it's not guaranteed
+ // to be different.
+
+ // Regression test for b/18549190: if a map is a subset of the other map,
+ // equals() should return false.
+ b2.getMutableInt32ToInt32Field().remove(1);
+ m2 = b2.build();
+ assertFalse(m1.equals(m2));
+ assertFalse(m2.equals(m1));
+ }
+
+ public void testNestedBuilderOnChangeEventPropagation() {
+ TestOnChangeEventPropagation.Builder parent =
+ TestOnChangeEventPropagation.newBuilder();
+ parent.getOptionalMessageBuilder().getMutableInt32ToInt32Field().put(1, 2);
+ TestOnChangeEventPropagation message = parent.build();
+ assertEquals(2, message.getOptionalMessage().getInt32ToInt32Field().get(1).intValue());
+
+ // Make a change using nested builder.
+ parent.getOptionalMessageBuilder().getMutableInt32ToInt32Field().put(1, 3);
+
+ // Should be able to observe the change.
+ message = parent.build();
+ assertEquals(3, message.getOptionalMessage().getInt32ToInt32Field().get(1).intValue());
+
+ // Make another change using mergeFrom()
+ TestMap.Builder other = TestMap.newBuilder();
+ other.getMutableInt32ToInt32Field().put(1, 4);
+ parent.getOptionalMessageBuilder().mergeFrom(other.build());
+
+ // Should be able to observe the change.
+ message = parent.build();
+ assertEquals(4, message.getOptionalMessage().getInt32ToInt32Field().get(1).intValue());
+
+ // Make yet another change by clearing the nested builder.
+ parent.getOptionalMessageBuilder().clear();
+
+ // Should be able to observe the change.
+ message = parent.build();
+ assertEquals(0, message.getOptionalMessage().getInt32ToInt32Field().size());
+ }
+
+ public void testNestedBuilderOnChangeEventPropagationReflection() {
+ FieldDescriptor intMapField = f("int32_to_int32_field");
+ // Create an outer message builder with nested builder.
+ TestOnChangeEventPropagation.Builder parentBuilder =
+ TestOnChangeEventPropagation.newBuilder();
+ TestMap.Builder testMapBuilder = parentBuilder.getOptionalMessageBuilder();
+
+ // Create a map entry message.
+ TestMap.Builder entryBuilder = TestMap.newBuilder();
+ entryBuilder.getMutableInt32ToInt32Field().put(1, 1);
+
+ // Put the entry into the nested builder.
+ testMapBuilder.addRepeatedField(
+ intMapField, entryBuilder.getRepeatedField(intMapField, 0));
+
+ // Should be able to observe the change.
+ TestOnChangeEventPropagation message = parentBuilder.build();
+ assertEquals(1, message.getOptionalMessage().getInt32ToInt32Field().size());
+
+ // Change the entry value.
+ entryBuilder.getMutableInt32ToInt32Field().put(1, 4);
+ testMapBuilder = parentBuilder.getOptionalMessageBuilder();
+ testMapBuilder.setRepeatedField(
+ intMapField, 0, entryBuilder.getRepeatedField(intMapField, 0));
+
+ // Should be able to observe the change.
+ message = parentBuilder.build();
+ assertEquals(4,
+ message.getOptionalMessage().getInt32ToInt32Field().get(1).intValue());
+
+ // Clear the nested builder.
+ testMapBuilder = parentBuilder.getOptionalMessageBuilder();
+ testMapBuilder.clearField(intMapField);
+
+ // Should be able to observe the change.
+ message = parentBuilder.build();
+ assertEquals(0, message.getOptionalMessage().getInt32ToInt32Field().size());
+ }
+
+ // The following methods are used to test reflection API.
+
+ private static FieldDescriptor f(String name) {
+ return TestMap.getDescriptor().findFieldByName(name);
+ }
+
+ private static Object getFieldValue(Message mapEntry, String name) {
+ FieldDescriptor field = mapEntry.getDescriptorForType().findFieldByName(name);
+ return mapEntry.getField(field);
+ }
+
+ private static Message.Builder setFieldValue(
+ Message.Builder mapEntry, String name, Object value) {
+ FieldDescriptor field = mapEntry.getDescriptorForType().findFieldByName(name);
+ mapEntry.setField(field, value);
+ return mapEntry;
+ }
+
+ private static void assertHasMapValues(Message message, String name, Map<?, ?> values) {
+ FieldDescriptor field = f(name);
+ for (Object entry : (List<?>) message.getField(field)) {
+ Message mapEntry = (Message) entry;
+ Object key = getFieldValue(mapEntry, "key");
+ Object value = getFieldValue(mapEntry, "value");
+ assertTrue(values.containsKey(key));
+ assertEquals(value, values.get(key));
+ }
+ assertEquals(values.size(), message.getRepeatedFieldCount(field));
+ for (int i = 0; i < message.getRepeatedFieldCount(field); i++) {
+ Message mapEntry = (Message) message.getRepeatedField(field, i);
+ Object key = getFieldValue(mapEntry, "key");
+ Object value = getFieldValue(mapEntry, "value");
+ assertTrue(values.containsKey(key));
+ assertEquals(value, values.get(key));
+ }
+ }
+
+ private static <KeyType, ValueType>
+ Message newMapEntry(Message.Builder builder, String name, KeyType key, ValueType value) {
+ FieldDescriptor field = builder.getDescriptorForType().findFieldByName(name);
+ Message.Builder entryBuilder = builder.newBuilderForField(field);
+ FieldDescriptor keyField = entryBuilder.getDescriptorForType().findFieldByName("key");
+ FieldDescriptor valueField = entryBuilder.getDescriptorForType().findFieldByName("value");
+ entryBuilder.setField(keyField, key);
+ entryBuilder.setField(valueField, value);
+ return entryBuilder.build();
+ }
+
+ private static void setMapValues(Message.Builder builder, String name, Map<?, ?> values) {
+ List<Message> entryList = new ArrayList<Message>();
+ for (Map.Entry<?, ?> entry : values.entrySet()) {
+ entryList.add(newMapEntry(builder, name, entry.getKey(), entry.getValue()));
+ }
+ FieldDescriptor field = builder.getDescriptorForType().findFieldByName(name);
+ builder.setField(field, entryList);
+ }
+
+ private static <KeyType, ValueType>
+ Map<KeyType, ValueType> mapForValues(
+ KeyType key1, ValueType value1, KeyType key2, ValueType value2) {
+ Map<KeyType, ValueType> map = new HashMap<KeyType, ValueType>();
+ map.put(key1, value1);
+ map.put(key2, value2);
+ return map;
+ }
+
+ public void testReflectionApi() throws Exception {
+ // In reflection API, map fields are just repeated message fields.
+ TestMap.Builder builder = TestMap.newBuilder();
+ builder.getMutableInt32ToInt32Field().put(1, 2);
+ builder.getMutableInt32ToInt32Field().put(3, 4);
+ builder.getMutableInt32ToMessageField().put(
+ 11, MessageValue.newBuilder().setValue(22).build());
+ builder.getMutableInt32ToMessageField().put(
+ 33, MessageValue.newBuilder().setValue(44).build());
+ TestMap message = builder.build();
+
+ // Test getField(), getRepeatedFieldCount(), getRepeatedField().
+ assertHasMapValues(message, "int32_to_int32_field",
+ mapForValues(1, 2, 3, 4));
+ assertHasMapValues(message, "int32_to_message_field",
+ mapForValues(
+ 11, MessageValue.newBuilder().setValue(22).build(),
+ 33, MessageValue.newBuilder().setValue(44).build()));
+
+ // Test clearField()
+ builder.clearField(f("int32_to_int32_field"));
+ builder.clearField(f("int32_to_message_field"));
+ message = builder.build();
+ assertEquals(0, message.getInt32ToInt32Field().size());
+ assertEquals(0, message.getInt32ToMessageField().size());
+
+ // Test setField()
+ setMapValues(builder, "int32_to_int32_field",
+ mapForValues(11, 22, 33, 44));
+ setMapValues(builder, "int32_to_message_field",
+ mapForValues(
+ 111, MessageValue.newBuilder().setValue(222).build(),
+ 333, MessageValue.newBuilder().setValue(444).build()));
+ message = builder.build();
+ assertEquals(22, message.getInt32ToInt32Field().get(11).intValue());
+ assertEquals(44, message.getInt32ToInt32Field().get(33).intValue());
+ assertEquals(222, message.getInt32ToMessageField().get(111).getValue());
+ assertEquals(444, message.getInt32ToMessageField().get(333).getValue());
+
+ // Test addRepeatedField
+ builder.addRepeatedField(f("int32_to_int32_field"),
+ newMapEntry(builder, "int32_to_int32_field", 55, 66));
+ builder.addRepeatedField(f("int32_to_message_field"),
+ newMapEntry(builder, "int32_to_message_field", 555,
+ MessageValue.newBuilder().setValue(666).build()));
+ message = builder.build();
+ assertEquals(66, message.getInt32ToInt32Field().get(55).intValue());
+ assertEquals(666, message.getInt32ToMessageField().get(555).getValue());
+
+ // Test addRepeatedField (overriding existing values)
+ builder.addRepeatedField(f("int32_to_int32_field"),
+ newMapEntry(builder, "int32_to_int32_field", 55, 55));
+ builder.addRepeatedField(f("int32_to_message_field"),
+ newMapEntry(builder, "int32_to_message_field", 555,
+ MessageValue.newBuilder().setValue(555).build()));
+ message = builder.build();
+ assertEquals(55, message.getInt32ToInt32Field().get(55).intValue());
+ assertEquals(555, message.getInt32ToMessageField().get(555).getValue());
+
+ // Test setRepeatedField
+ for (int i = 0; i < builder.getRepeatedFieldCount(f("int32_to_int32_field")); i++) {
+ Message mapEntry = (Message) builder.getRepeatedField(f("int32_to_int32_field"), i);
+ int oldKey = ((Integer) getFieldValue(mapEntry, "key")).intValue();
+ int oldValue = ((Integer) getFieldValue(mapEntry, "value")).intValue();
+ // Swap key with value for each entry.
+ Message.Builder mapEntryBuilder = mapEntry.toBuilder();
+ setFieldValue(mapEntryBuilder, "key", oldValue);
+ setFieldValue(mapEntryBuilder, "value", oldKey);
+ builder.setRepeatedField(f("int32_to_int32_field"), i, mapEntryBuilder.build());
+ }
+ message = builder.build();
+ assertEquals(11, message.getInt32ToInt32Field().get(22).intValue());
+ assertEquals(33, message.getInt32ToInt32Field().get(44).intValue());
+ assertEquals(55, message.getInt32ToInt32Field().get(55).intValue());
+ }
+
+ public void testTextFormat() throws Exception {
+ TestMap.Builder builder = TestMap.newBuilder();
+ setMapValues(builder);
+ TestMap message = builder.build();
+
+ String textData = TextFormat.printToString(message);
+
+ builder = TestMap.newBuilder();
+ TextFormat.merge(textData, builder);
+ message = builder.build();
+
+ assertMapValuesSet(message);
+ }
+
+ public void testDynamicMessage() throws Exception {
+ TestMap.Builder builder = TestMap.newBuilder();
+ setMapValues(builder);
+ TestMap message = builder.build();
+
+ Message dynamicDefaultInstance =
+ DynamicMessage.getDefaultInstance(TestMap.getDescriptor());
+ Message dynamicMessage = dynamicDefaultInstance
+ .newBuilderForType().mergeFrom(message.toByteString()).build();
+
+ assertEquals(message, dynamicMessage);
+ assertEquals(message.hashCode(), dynamicMessage.hashCode());
+ }
+
+ public void testReflectionEqualsAndHashCode() throws Exception {
+ // Test that generated equals() and hashCode() will disregard the order
+ // of map entries when comparing/hashing map fields.
+
+ // We use DynamicMessage to test reflection based equals()/hashCode().
+ Message dynamicDefaultInstance =
+ DynamicMessage.getDefaultInstance(TestMap.getDescriptor());
+ FieldDescriptor field = f("int32_to_int32_field");
+
+ Message.Builder b1 = dynamicDefaultInstance.newBuilderForType();
+ b1.addRepeatedField(field, newMapEntry(b1, "int32_to_int32_field", 1, 2));
+ b1.addRepeatedField(field, newMapEntry(b1, "int32_to_int32_field", 3, 4));
+ b1.addRepeatedField(field, newMapEntry(b1, "int32_to_int32_field", 5, 6));
+ Message m1 = b1.build();
+
+ Message.Builder b2 = dynamicDefaultInstance.newBuilderForType();
+ b2.addRepeatedField(field, newMapEntry(b2, "int32_to_int32_field", 5, 6));
+ b2.addRepeatedField(field, newMapEntry(b2, "int32_to_int32_field", 1, 2));
+ b2.addRepeatedField(field, newMapEntry(b2, "int32_to_int32_field", 3, 4));
+ Message m2 = b2.build();
+
+ assertEquals(m1, m2);
+ assertEquals(m1.hashCode(), m2.hashCode());
+
+ // Make sure we did compare map fields.
+ b2.setRepeatedField(field, 0, newMapEntry(b1, "int32_to_int32_field", 0, 0));
+ m2 = b2.build();
+ assertFalse(m1.equals(m2));
+ // Don't check m1.hashCode() != m2.hashCode() because it's not guaranteed
+ // to be different.
+ }
+
+ public void testUnknownEnumValues() throws Exception {
+ TestMap.Builder builder = TestMap.newBuilder();
+ builder.getMutableInt32ToEnumFieldValue().put(0, 0);
+ builder.getMutableInt32ToEnumFieldValue().put(1, 1);
+ builder.getMutableInt32ToEnumFieldValue().put(2, 1000); // unknown value.
+ TestMap message = builder.build();
+
+ assertEquals(TestMap.EnumValue.FOO,
+ message.getInt32ToEnumField().get(0));
+ assertEquals(TestMap.EnumValue.BAR,
+ message.getInt32ToEnumField().get(1));
+ assertEquals(TestMap.EnumValue.UNRECOGNIZED,
+ message.getInt32ToEnumField().get(2));
+ assertEquals(1000, message.getInt32ToEnumFieldValue().get(2).intValue());
+
+ // Unknown enum values should be preserved after:
+ // 1. Serialization and parsing.
+ // 2. toBuild().
+ // 3. mergeFrom().
+ message = TestMap.parseFrom(message.toByteString());
+ assertEquals(1000, message.getInt32ToEnumFieldValue().get(2).intValue());
+ builder = message.toBuilder();
+ assertEquals(1000, builder.getInt32ToEnumFieldValue().get(2).intValue());
+ builder = TestMap.newBuilder().mergeFrom(message);
+ assertEquals(1000, builder.getInt32ToEnumFieldValue().get(2).intValue());
+
+ // hashCode()/equals() should take unknown enum values into account.
+ builder.getMutableInt32ToEnumFieldValue().put(2, 1001);
+ TestMap message2 = builder.build();
+ assertFalse(message.hashCode() == message2.hashCode());
+ assertFalse(message.equals(message2));
+ // Unknown values will be converted to UNRECOGNIZED so the resulted enum map
+ // should be the same.
+ assertTrue(message.getInt32ToEnumField().equals(message2.getInt32ToEnumField()));
+ }
+
+ public void testUnknownEnumValuesInReflectionApi() throws Exception {
+ Descriptor descriptor = TestMap.getDescriptor();
+ EnumDescriptor enumDescriptor = TestMap.EnumValue.getDescriptor();
+ FieldDescriptor field = descriptor.findFieldByName("int32_to_enum_field");
+
+ Map<Integer, Integer> data = new HashMap<Integer, Integer>();
+ data.put(0, 0);
+ data.put(1, 1);
+ data.put(2, 1000); // unknown value.
+
+ TestMap.Builder builder = TestMap.newBuilder();
+ for (Map.Entry<Integer, Integer> entry : data.entrySet()) {
+ builder.getMutableInt32ToEnumFieldValue().put(entry.getKey(), entry.getValue());
+ }
+
+ // Try to read unknown enum values using reflection API.
+ for (int i = 0; i < builder.getRepeatedFieldCount(field); i++) {
+ Message mapEntry = (Message) builder.getRepeatedField(field, i);
+ int key = ((Integer) getFieldValue(mapEntry, "key")).intValue();
+ int value = ((EnumValueDescriptor) getFieldValue(mapEntry, "value")).getNumber();
+ assertEquals(data.get(key).intValue(), value);
+ Message.Builder mapEntryBuilder = mapEntry.toBuilder();
+ // Increase the value by 1.
+ setFieldValue(mapEntryBuilder, "value",
+ enumDescriptor.findValueByNumberCreatingIfUnknown(value + 1));
+ builder.setRepeatedField(field, i, mapEntryBuilder.build());
+ }
+
+ // Verify that enum values have been successfully updated.
+ TestMap message = builder.build();
+ for (Map.Entry<Integer, Integer> entry : message.getInt32ToEnumFieldValue().entrySet()) {
+ assertEquals(data.get(entry.getKey()) + 1, entry.getValue().intValue());
+ }
+ }
+
+ public void testIterationOrder() throws Exception {
+ TestMap.Builder builder = TestMap.newBuilder();
+ setMapValues(builder);
+ TestMap message = builder.build();
+
+ assertEquals(Arrays.asList("1", "2", "3"),
+ new ArrayList<String>(message.getStringToInt32Field().keySet()));
+ }
+
+ private static <K, V> Map<K, V> newMap(K key1, V value1) {
+ Map<K, V> map = new HashMap<K, V>();
+ map.put(key1, value1);
+ return map;
+ }
+
+ private static <K, V> Map<K, V> newMap(K key1, V value1, K key2, V value2) {
+ Map<K, V> map = new HashMap<K, V>();
+ map.put(key1, value1);
+ map.put(key2, value2);
+ return map;
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/MessageTest.java b/java/core/src/test/java/com/google/protobuf/MessageTest.java
new file mode 100644
index 00000000..abcd3a1d
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/MessageTest.java
@@ -0,0 +1,353 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// 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.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.TestAllExtensions;
+import protobuf_unittest.UnittestProto.TestRequired;
+import protobuf_unittest.UnittestProto.TestRequiredForeign;
+import protobuf_unittest.UnittestProto.ForeignMessage;
+
+import junit.framework.TestCase;
+
+import java.util.List;
+
+/**
+ * Misc. unit tests for message operations that apply to both generated
+ * and dynamic messages.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public class MessageTest extends TestCase {
+ // =================================================================
+ // Message-merging tests.
+
+ 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 {
+ TestAllTypes result =
+ TestAllTypes.newBuilder(MERGE_DEST)
+ .mergeFrom(MERGE_SOURCE).build();
+
+ assertEquals(MERGE_RESULT_TEXT, result.toString());
+ }
+
+ /**
+ * Test merging a DynamicMessage into a GeneratedMessage. As long as they
+ * have the same descriptor, this should work, but it is an entirely different
+ * code path.
+ */
+ public void testMergeFromDynamic() throws Exception {
+ TestAllTypes result =
+ TestAllTypes.newBuilder(MERGE_DEST)
+ .mergeFrom(DynamicMessage.newBuilder(MERGE_SOURCE).build())
+ .build();
+
+ assertEquals(MERGE_RESULT_TEXT, result.toString());
+ }
+
+ /** Test merging two DynamicMessages. */
+ public void testDynamicMergeFrom() throws Exception {
+ DynamicMessage result =
+ DynamicMessage.newBuilder(MERGE_DEST)
+ .mergeFrom(DynamicMessage.newBuilder(MERGE_SOURCE).build())
+ .build();
+
+ assertEquals(MERGE_RESULT_TEXT, result.toString());
+ }
+
+ // =================================================================
+ // Required-field-related tests.
+
+ 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 testRequired() throws Exception {
+ TestRequired.Builder builder = TestRequired.newBuilder();
+
+ assertFalse(builder.isInitialized());
+ builder.setA(1);
+ assertFalse(builder.isInitialized());
+ builder.setB(1);
+ assertFalse(builder.isInitialized());
+ builder.setC(1);
+ assertTrue(builder.isInitialized());
+ }
+
+ public void testRequiredForeign() throws Exception {
+ TestRequiredForeign.Builder builder = TestRequiredForeign.newBuilder();
+
+ assertTrue(builder.isInitialized());
+
+ builder.setOptionalMessage(TEST_REQUIRED_UNINITIALIZED);
+ assertFalse(builder.isInitialized());
+
+ builder.setOptionalMessage(TEST_REQUIRED_INITIALIZED);
+ assertTrue(builder.isInitialized());
+
+ builder.addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED);
+ assertFalse(builder.isInitialized());
+
+ builder.setRepeatedMessage(0, TEST_REQUIRED_INITIALIZED);
+ assertTrue(builder.isInitialized());
+ }
+
+ public void testRequiredExtension() throws Exception {
+ TestAllExtensions.Builder builder = TestAllExtensions.newBuilder();
+
+ assertTrue(builder.isInitialized());
+
+ builder.setExtension(TestRequired.single, TEST_REQUIRED_UNINITIALIZED);
+ assertFalse(builder.isInitialized());
+
+ builder.setExtension(TestRequired.single, TEST_REQUIRED_INITIALIZED);
+ assertTrue(builder.isInitialized());
+
+ builder.addExtension(TestRequired.multi, TEST_REQUIRED_UNINITIALIZED);
+ assertFalse(builder.isInitialized());
+
+ builder.setExtension(TestRequired.multi, 0, TEST_REQUIRED_INITIALIZED);
+ assertTrue(builder.isInitialized());
+ }
+
+ public void testRequiredDynamic() throws Exception {
+ Descriptors.Descriptor descriptor = TestRequired.getDescriptor();
+ DynamicMessage.Builder builder = DynamicMessage.newBuilder(descriptor);
+
+ assertFalse(builder.isInitialized());
+ builder.setField(descriptor.findFieldByName("a"), 1);
+ assertFalse(builder.isInitialized());
+ builder.setField(descriptor.findFieldByName("b"), 1);
+ assertFalse(builder.isInitialized());
+ builder.setField(descriptor.findFieldByName("c"), 1);
+ assertTrue(builder.isInitialized());
+ }
+
+ public void testRequiredDynamicForeign() throws Exception {
+ Descriptors.Descriptor descriptor = TestRequiredForeign.getDescriptor();
+ DynamicMessage.Builder builder = DynamicMessage.newBuilder(descriptor);
+
+ assertTrue(builder.isInitialized());
+
+ builder.setField(descriptor.findFieldByName("optional_message"),
+ TEST_REQUIRED_UNINITIALIZED);
+ assertFalse(builder.isInitialized());
+
+ builder.setField(descriptor.findFieldByName("optional_message"),
+ TEST_REQUIRED_INITIALIZED);
+ assertTrue(builder.isInitialized());
+
+ builder.addRepeatedField(descriptor.findFieldByName("repeated_message"),
+ TEST_REQUIRED_UNINITIALIZED);
+ assertFalse(builder.isInitialized());
+
+ builder.setRepeatedField(descriptor.findFieldByName("repeated_message"), 0,
+ TEST_REQUIRED_INITIALIZED);
+ assertTrue(builder.isInitialized());
+ }
+
+ public void testUninitializedException() throws Exception {
+ try {
+ TestRequired.newBuilder().build();
+ fail("Should have thrown an exception.");
+ } catch (UninitializedMessageException e) {
+ assertEquals("Message missing required fields: a, b, c", e.getMessage());
+ }
+ }
+
+ public void testBuildPartial() throws Exception {
+ // We're mostly testing that no exception is thrown.
+ TestRequired message = TestRequired.newBuilder().buildPartial();
+ assertFalse(message.isInitialized());
+ }
+
+ public void testNestedUninitializedException() throws Exception {
+ try {
+ TestRequiredForeign.newBuilder()
+ .setOptionalMessage(TEST_REQUIRED_UNINITIALIZED)
+ .addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED)
+ .addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED)
+ .build();
+ fail("Should have thrown an exception.");
+ } catch (UninitializedMessageException e) {
+ assertEquals(
+ "Message missing required fields: " +
+ "optional_message.a, " +
+ "optional_message.b, " +
+ "optional_message.c, " +
+ "repeated_message[0].a, " +
+ "repeated_message[0].b, " +
+ "repeated_message[0].c, " +
+ "repeated_message[1].a, " +
+ "repeated_message[1].b, " +
+ "repeated_message[1].c",
+ e.getMessage());
+ }
+ }
+
+ public void testBuildNestedPartial() throws Exception {
+ // We're mostly testing that no exception is thrown.
+ TestRequiredForeign message =
+ TestRequiredForeign.newBuilder()
+ .setOptionalMessage(TEST_REQUIRED_UNINITIALIZED)
+ .addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED)
+ .addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED)
+ .buildPartial();
+ assertFalse(message.isInitialized());
+ }
+
+ public void testParseUnititialized() throws Exception {
+ try {
+ TestRequired.parseFrom(ByteString.EMPTY);
+ fail("Should have thrown an exception.");
+ } catch (InvalidProtocolBufferException e) {
+ assertEquals("Message missing required fields: a, b, c", e.getMessage());
+ }
+ }
+
+ public void testParseNestedUnititialized() throws Exception {
+ ByteString data =
+ TestRequiredForeign.newBuilder()
+ .setOptionalMessage(TEST_REQUIRED_UNINITIALIZED)
+ .addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED)
+ .addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED)
+ .buildPartial().toByteString();
+
+ try {
+ TestRequiredForeign.parseFrom(data);
+ fail("Should have thrown an exception.");
+ } catch (InvalidProtocolBufferException e) {
+ assertEquals(
+ "Message missing required fields: " +
+ "optional_message.a, " +
+ "optional_message.b, " +
+ "optional_message.c, " +
+ "repeated_message[0].a, " +
+ "repeated_message[0].b, " +
+ "repeated_message[0].c, " +
+ "repeated_message[1].a, " +
+ "repeated_message[1].b, " +
+ "repeated_message[1].c",
+ e.getMessage());
+ }
+ }
+
+ public void testDynamicUninitializedException() throws Exception {
+ try {
+ DynamicMessage.newBuilder(TestRequired.getDescriptor()).build();
+ fail("Should have thrown an exception.");
+ } catch (UninitializedMessageException e) {
+ assertEquals("Message missing required fields: a, b, c", e.getMessage());
+ }
+ }
+
+ public void testDynamicBuildPartial() throws Exception {
+ // We're mostly testing that no exception is thrown.
+ DynamicMessage message =
+ DynamicMessage.newBuilder(TestRequired.getDescriptor())
+ .buildPartial();
+ assertFalse(message.isInitialized());
+ }
+
+ public void testDynamicParseUnititialized() throws Exception {
+ try {
+ Descriptors.Descriptor descriptor = TestRequired.getDescriptor();
+ DynamicMessage.parseFrom(descriptor, ByteString.EMPTY);
+ fail("Should have thrown an exception.");
+ } catch (InvalidProtocolBufferException e) {
+ assertEquals("Message missing required fields: a, b, c", e.getMessage());
+ }
+ }
+
+ /** Test reading unset repeated message from DynamicMessage. */
+ public void testDynamicRepeatedMessageNull() throws Exception {
+ Descriptors.Descriptor descriptor = TestRequired.getDescriptor();
+ DynamicMessage result =
+ DynamicMessage.newBuilder(TestAllTypes.getDescriptor())
+ .mergeFrom(DynamicMessage.newBuilder(MERGE_SOURCE).build())
+ .build();
+
+ assertTrue(result.getField(result.getDescriptorForType()
+ .findFieldByName("repeated_foreign_message")) instanceof List<?>);
+ assertEquals(result.getRepeatedFieldCount(result.getDescriptorForType()
+ .findFieldByName("repeated_foreign_message")), 0);
+ }
+
+ /** Test reading repeated message from DynamicMessage. */
+ public void testDynamicRepeatedMessageNotNull() throws Exception {
+
+ TestAllTypes REPEATED_NESTED =
+ TestAllTypes.newBuilder()
+ .setOptionalInt32(1)
+ .setOptionalString("foo")
+ .setOptionalForeignMessage(ForeignMessage.getDefaultInstance())
+ .addRepeatedString("bar")
+ .addRepeatedForeignMessage(ForeignMessage.getDefaultInstance())
+ .addRepeatedForeignMessage(ForeignMessage.getDefaultInstance())
+ .build();
+ Descriptors.Descriptor descriptor = TestRequired.getDescriptor();
+ DynamicMessage result =
+ DynamicMessage.newBuilder(TestAllTypes.getDescriptor())
+ .mergeFrom(DynamicMessage.newBuilder(REPEATED_NESTED).build())
+ .build();
+
+ assertTrue(result.getField(result.getDescriptorForType()
+ .findFieldByName("repeated_foreign_message")) instanceof List<?>);
+ assertEquals(result.getRepeatedFieldCount(result.getDescriptorForType()
+ .findFieldByName("repeated_foreign_message")), 2);
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/NestedBuildersTest.java b/java/core/src/test/java/com/google/protobuf/NestedBuildersTest.java
new file mode 100644
index 00000000..23653126
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/NestedBuildersTest.java
@@ -0,0 +1,185 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// 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.Vehicle;
+import protobuf_unittest.Wheel;
+
+import junit.framework.TestCase;
+
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ * Test cases that exercise end-to-end use cases involving
+ * {@link SingleFieldBuilder} and {@link RepeatedFieldBuilder}.
+ *
+ * @author jonp@google.com (Jon Perlow)
+ */
+public class NestedBuildersTest extends TestCase {
+
+ public void testMessagesAndBuilders() {
+ Vehicle.Builder vehicleBuilder = Vehicle.newBuilder();
+ vehicleBuilder.addWheelBuilder()
+ .setRadius(4)
+ .setWidth(1);
+ vehicleBuilder.addWheelBuilder()
+ .setRadius(4)
+ .setWidth(2);
+ vehicleBuilder.addWheelBuilder()
+ .setRadius(4)
+ .setWidth(3);
+ vehicleBuilder.addWheelBuilder()
+ .setRadius(4)
+ .setWidth(4);
+ vehicleBuilder.getEngineBuilder()
+ .setLiters(10);
+
+ Vehicle vehicle = vehicleBuilder.build();
+ assertEquals(4, vehicle.getWheelCount());
+ for (int i = 0; i < 4; i++) {
+ Wheel wheel = vehicle.getWheel(i);
+ assertEquals(4, wheel.getRadius());
+ assertEquals(i + 1, wheel.getWidth());
+ }
+ assertEquals(10, vehicle.getEngine().getLiters());
+
+ for (int i = 0; i < 4; i++) {
+ vehicleBuilder.getWheelBuilder(i)
+ .setRadius(5)
+ .setWidth(i + 10);
+ }
+ vehicleBuilder.getEngineBuilder().setLiters(20);
+
+ vehicle = vehicleBuilder.build();
+ for (int i = 0; i < 4; i++) {
+ Wheel wheel = vehicle.getWheel(i);
+ assertEquals(5, wheel.getRadius());
+ assertEquals(i + 10, wheel.getWidth());
+ }
+ assertEquals(20, vehicle.getEngine().getLiters());
+ assertTrue(vehicle.hasEngine());
+ }
+
+ public void testMessagesAreCached() {
+ Vehicle.Builder vehicleBuilder = Vehicle.newBuilder();
+ vehicleBuilder.addWheelBuilder()
+ .setRadius(1)
+ .setWidth(2);
+ vehicleBuilder.addWheelBuilder()
+ .setRadius(3)
+ .setWidth(4);
+ vehicleBuilder.addWheelBuilder()
+ .setRadius(5)
+ .setWidth(6);
+ vehicleBuilder.addWheelBuilder()
+ .setRadius(7)
+ .setWidth(8);
+
+ // Make sure messages are cached.
+ List<Wheel> wheels = new ArrayList<Wheel>(vehicleBuilder.getWheelList());
+ for (int i = 0; i < wheels.size(); i++) {
+ assertSame(wheels.get(i), vehicleBuilder.getWheel(i));
+ }
+
+ // Now get builders and check they didn't change.
+ for (int i = 0; i < wheels.size(); i++) {
+ vehicleBuilder.getWheel(i);
+ }
+ for (int i = 0; i < wheels.size(); i++) {
+ assertSame(wheels.get(i), vehicleBuilder.getWheel(i));
+ }
+
+ // Change just one
+ vehicleBuilder.getWheelBuilder(3)
+ .setRadius(20).setWidth(20);
+
+ // Now get wheels and check that only that one changed
+ for (int i = 0; i < wheels.size(); i++) {
+ if (i < 3) {
+ assertSame(wheels.get(i), vehicleBuilder.getWheel(i));
+ } else {
+ assertNotSame(wheels.get(i), vehicleBuilder.getWheel(i));
+ }
+ }
+ }
+
+ public void testRemove_WithNestedBuilders() {
+ Vehicle.Builder vehicleBuilder = Vehicle.newBuilder();
+ vehicleBuilder.addWheelBuilder()
+ .setRadius(1)
+ .setWidth(1);
+ vehicleBuilder.addWheelBuilder()
+ .setRadius(2)
+ .setWidth(2);
+ vehicleBuilder.removeWheel(0);
+
+ assertEquals(1, vehicleBuilder.getWheelCount());
+ assertEquals(2, vehicleBuilder.getWheel(0).getRadius());
+ }
+
+ public void testRemove_WithNestedMessages() {
+ Vehicle.Builder vehicleBuilder = Vehicle.newBuilder();
+ vehicleBuilder.addWheel(Wheel.newBuilder()
+ .setRadius(1)
+ .setWidth(1));
+ vehicleBuilder.addWheel(Wheel.newBuilder()
+ .setRadius(2)
+ .setWidth(2));
+ vehicleBuilder.removeWheel(0);
+
+ assertEquals(1, vehicleBuilder.getWheelCount());
+ assertEquals(2, vehicleBuilder.getWheel(0).getRadius());
+ }
+
+ public void testMerge() {
+ Vehicle vehicle1 = Vehicle.newBuilder()
+ .addWheel(Wheel.newBuilder().setRadius(1).build())
+ .addWheel(Wheel.newBuilder().setRadius(2).build())
+ .build();
+
+ Vehicle vehicle2 = Vehicle.newBuilder()
+ .mergeFrom(vehicle1)
+ .build();
+ // List should be the same -- no allocation
+ assertSame(vehicle1.getWheelList(), vehicle2.getWheelList());
+
+ Vehicle vehicle3 = vehicle1.toBuilder().build();
+ assertSame(vehicle1.getWheelList(), vehicle3.getWheelList());
+ }
+
+ public void testGettingBuilderMarksFieldAsHaving() {
+ Vehicle.Builder vehicleBuilder = Vehicle.newBuilder();
+ vehicleBuilder.getEngineBuilder();
+ Vehicle vehicle = vehicleBuilder.buildPartial();
+ assertTrue(vehicle.hasEngine());
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/NioByteStringTest.java b/java/core/src/test/java/com/google/protobuf/NioByteStringTest.java
new file mode 100644
index 00000000..e40a3662
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/NioByteStringTest.java
@@ -0,0 +1,545 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// 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 static com.google.protobuf.Internal.UTF_8;
+
+import junit.framework.TestCase;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.UnsupportedEncodingException;
+import java.nio.BufferOverflowException;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.List;
+import java.util.NoSuchElementException;
+
+/**
+ * Tests for {@link NioByteString}.
+ */
+public class NioByteStringTest extends TestCase {
+ private static final ByteString EMPTY = new NioByteString(ByteBuffer.wrap(new byte[0]));
+ private static final String CLASSNAME = NioByteString.class.getSimpleName();
+ private static final byte[] BYTES = ByteStringTest.getTestBytes(1234, 11337766L);
+ private static final int EXPECTED_HASH = ByteString.wrap(BYTES).hashCode();
+ private static final ByteBuffer BUFFER = ByteBuffer.wrap(BYTES.clone());
+ private static final ByteString TEST_STRING = new NioByteString(BUFFER);
+
+ public void testExpectedType() {
+ String actualClassName = getActualClassName(TEST_STRING);
+ assertEquals(CLASSNAME + " should match type exactly", CLASSNAME, actualClassName);
+ }
+
+ protected String getActualClassName(Object object) {
+ String actualClassName = object.getClass().getName();
+ actualClassName = actualClassName.substring(actualClassName.lastIndexOf('.') + 1);
+ return actualClassName;
+ }
+
+ public void testByteAt() {
+ boolean stillEqual = true;
+ for (int i = 0; stillEqual && i < BYTES.length; ++i) {
+ stillEqual = (BYTES[i] == TEST_STRING.byteAt(i));
+ }
+ assertTrue(CLASSNAME + " must capture the right bytes", stillEqual);
+ }
+
+ public void testByteIterator() {
+ boolean stillEqual = true;
+ ByteString.ByteIterator iter = TEST_STRING.iterator();
+ for (int i = 0; stillEqual && i < BYTES.length; ++i) {
+ stillEqual = (iter.hasNext() && BYTES[i] == iter.nextByte());
+ }
+ assertTrue(CLASSNAME + " must capture the right bytes", stillEqual);
+ assertFalse(CLASSNAME + " must have exhausted the itertor", iter.hasNext());
+
+ try {
+ iter.nextByte();
+ fail("Should have thrown an exception.");
+ } catch (NoSuchElementException e) {
+ // This is success
+ }
+ }
+
+ public void testByteIterable() {
+ boolean stillEqual = true;
+ int j = 0;
+ for (byte quantum : TEST_STRING) {
+ stillEqual = (BYTES[j] == quantum);
+ ++j;
+ }
+ assertTrue(CLASSNAME + " must capture the right bytes as Bytes", stillEqual);
+ assertEquals(CLASSNAME + " iterable character count", BYTES.length, j);
+ }
+
+ public void testSize() {
+ assertEquals(CLASSNAME + " must have the expected size", BYTES.length,
+ TEST_STRING.size());
+ }
+
+ public void testGetTreeDepth() {
+ assertEquals(CLASSNAME + " must have depth 0", 0, TEST_STRING.getTreeDepth());
+ }
+
+ public void testIsBalanced() {
+ assertTrue(CLASSNAME + " is technically balanced", TEST_STRING.isBalanced());
+ }
+
+ public void testCopyTo_ByteArrayOffsetLength() {
+ int destinationOffset = 50;
+ int length = 100;
+ byte[] destination = new byte[destinationOffset + length];
+ int sourceOffset = 213;
+ TEST_STRING.copyTo(destination, sourceOffset, destinationOffset, length);
+ boolean stillEqual = true;
+ for (int i = 0; stillEqual && i < length; ++i) {
+ stillEqual = BYTES[i + sourceOffset] == destination[i + destinationOffset];
+ }
+ assertTrue(CLASSNAME + ".copyTo(4 arg) must give the expected bytes", stillEqual);
+ }
+
+ public void testCopyTo_ByteArrayOffsetLengthErrors() {
+ int destinationOffset = 50;
+ int length = 100;
+ byte[] destination = new byte[destinationOffset + length];
+
+ try {
+ // Copy one too many bytes
+ TEST_STRING.copyTo(destination, TEST_STRING.size() + 1 - length,
+ destinationOffset, length);
+ fail("Should have thrown an exception when copying too many bytes of a "
+ + CLASSNAME);
+ } catch (IndexOutOfBoundsException expected) {
+ // This is success
+ }
+
+ try {
+ // Copy with illegal negative sourceOffset
+ TEST_STRING.copyTo(destination, -1, destinationOffset, length);
+ fail("Should have thrown an exception when given a negative sourceOffset in "
+ + CLASSNAME);
+ } catch (IndexOutOfBoundsException expected) {
+ // This is success
+ }
+
+ try {
+ // Copy with illegal negative destinationOffset
+ TEST_STRING.copyTo(destination, 0, -1, length);
+ fail("Should have thrown an exception when given a negative destinationOffset in "
+ + CLASSNAME);
+ } catch (IndexOutOfBoundsException expected) {
+ // This is success
+ }
+
+ try {
+ // Copy with illegal negative size
+ TEST_STRING.copyTo(destination, 0, 0, -1);
+ fail("Should have thrown an exception when given a negative size in "
+ + CLASSNAME);
+ } catch (IndexOutOfBoundsException expected) {
+ // This is success
+ }
+
+ try {
+ // Copy with illegal too-large sourceOffset
+ TEST_STRING.copyTo(destination, 2 * TEST_STRING.size(), 0, length);
+ fail("Should have thrown an exception when the destinationOffset is too large in "
+ + CLASSNAME);
+ } catch (IndexOutOfBoundsException expected) {
+ // This is success
+ }
+
+ try {
+ // Copy with illegal too-large destinationOffset
+ TEST_STRING.copyTo(destination, 0, 2 * destination.length, length);
+ fail("Should have thrown an exception when the destinationOffset is too large in "
+ + CLASSNAME);
+ } catch (IndexOutOfBoundsException expected) {
+ // This is success
+ }
+ }
+
+ public void testCopyTo_ByteBuffer() {
+ // Same length.
+ ByteBuffer myBuffer = ByteBuffer.allocate(BYTES.length);
+ TEST_STRING.copyTo(myBuffer);
+ myBuffer.flip();
+ assertEquals(CLASSNAME + ".copyTo(ByteBuffer) must give back the same bytes",
+ BUFFER, myBuffer);
+
+ // Target buffer bigger than required.
+ myBuffer = ByteBuffer.allocate(TEST_STRING.size() + 1);
+ TEST_STRING.copyTo(myBuffer);
+ myBuffer.flip();
+ assertEquals(BUFFER, myBuffer);
+
+ // Target buffer has no space.
+ myBuffer = ByteBuffer.allocate(0);
+ try {
+ TEST_STRING.copyTo(myBuffer);
+ fail("Should have thrown an exception when target ByteBuffer has insufficient capacity");
+ } catch (BufferOverflowException e) {
+ // Expected.
+ }
+
+ // Target buffer too small.
+ myBuffer = ByteBuffer.allocate(1);
+ try {
+ TEST_STRING.copyTo(myBuffer);
+ fail("Should have thrown an exception when target ByteBuffer has insufficient capacity");
+ } catch (BufferOverflowException e) {
+ // Expected.
+ }
+ }
+
+ public void testMarkSupported() {
+ InputStream stream = TEST_STRING.newInput();
+ assertTrue(CLASSNAME + ".newInput() must support marking", stream.markSupported());
+ }
+
+ public void testMarkAndReset() throws IOException {
+ int fraction = TEST_STRING.size() / 3;
+
+ InputStream stream = TEST_STRING.newInput();
+ stream.mark(TEST_STRING.size()); // First, mark() the end.
+
+ skipFully(stream, fraction); // Skip a large fraction, but not all.
+ assertEquals(
+ CLASSNAME + ": after skipping to the 'middle', half the bytes are available",
+ (TEST_STRING.size() - fraction), stream.available());
+ stream.reset();
+ assertEquals(
+ CLASSNAME + ": after resetting, all bytes are available",
+ TEST_STRING.size(), stream.available());
+
+ skipFully(stream, TEST_STRING.size()); // Skip to the end.
+ assertEquals(
+ CLASSNAME + ": after skipping to the end, no more bytes are available",
+ 0, stream.available());
+ }
+
+ /**
+ * Discards {@code n} bytes of data from the input stream. This method
+ * will block until the full amount has been skipped. Does not close the
+ * stream.
+ * <p>Copied from com.google.common.io.ByteStreams to avoid adding dependency.
+ *
+ * @param in the input stream to read from
+ * @param n the number of bytes to skip
+ * @throws EOFException if this stream reaches the end before skipping all
+ * the bytes
+ * @throws IOException if an I/O error occurs, or the stream does not
+ * support skipping
+ */
+ static void skipFully(InputStream in, long n) throws IOException {
+ long toSkip = n;
+ while (n > 0) {
+ long amt = in.skip(n);
+ if (amt == 0) {
+ // Force a blocking read to avoid infinite loop
+ if (in.read() == -1) {
+ long skipped = toSkip - n;
+ throw new EOFException("reached end of stream after skipping "
+ + skipped + " bytes; " + toSkip + " bytes expected");
+ }
+ n--;
+ } else {
+ n -= amt;
+ }
+ }
+ }
+
+ public void testAsReadOnlyByteBuffer() {
+ ByteBuffer byteBuffer = TEST_STRING.asReadOnlyByteBuffer();
+ byte[] roundTripBytes = new byte[BYTES.length];
+ assertTrue(byteBuffer.remaining() == BYTES.length);
+ assertTrue(byteBuffer.isReadOnly());
+ byteBuffer.get(roundTripBytes);
+ assertTrue(CLASSNAME + ".asReadOnlyByteBuffer() must give back the same bytes",
+ Arrays.equals(BYTES, roundTripBytes));
+ }
+
+ public void testAsReadOnlyByteBufferList() {
+ List<ByteBuffer> byteBuffers = TEST_STRING.asReadOnlyByteBufferList();
+ int bytesSeen = 0;
+ byte[] roundTripBytes = new byte[BYTES.length];
+ for (ByteBuffer byteBuffer : byteBuffers) {
+ int thisLength = byteBuffer.remaining();
+ assertTrue(byteBuffer.isReadOnly());
+ assertTrue(bytesSeen + thisLength <= BYTES.length);
+ byteBuffer.get(roundTripBytes, bytesSeen, thisLength);
+ bytesSeen += thisLength;
+ }
+ assertTrue(bytesSeen == BYTES.length);
+ assertTrue(CLASSNAME + ".asReadOnlyByteBufferTest() must give back the same bytes",
+ Arrays.equals(BYTES, roundTripBytes));
+ }
+
+ public void testToByteArray() {
+ byte[] roundTripBytes = TEST_STRING.toByteArray();
+ assertTrue(CLASSNAME + ".toByteArray() must give back the same bytes",
+ Arrays.equals(BYTES, roundTripBytes));
+ }
+
+ public void testWriteTo() throws IOException {
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ TEST_STRING.writeTo(bos);
+ byte[] roundTripBytes = bos.toByteArray();
+ assertTrue(CLASSNAME + ".writeTo() must give back the same bytes",
+ Arrays.equals(BYTES, roundTripBytes));
+ }
+
+ public void testNewOutput() throws IOException {
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ ByteString.Output output = ByteString.newOutput();
+ TEST_STRING.writeTo(output);
+ assertEquals("Output Size returns correct result",
+ output.size(), TEST_STRING.size());
+ output.writeTo(bos);
+ assertTrue("Output.writeTo() must give back the same bytes",
+ Arrays.equals(BYTES, bos.toByteArray()));
+
+ // write the output stream to itself! This should cause it to double
+ output.writeTo(output);
+ assertEquals("Writing an output stream to itself is successful",
+ TEST_STRING.concat(TEST_STRING), output.toByteString());
+
+ output.reset();
+ assertEquals("Output.reset() resets the output", 0, output.size());
+ assertEquals("Output.reset() resets the output",
+ EMPTY, output.toByteString());
+ }
+
+ public void testToString() {
+ String testString = "I love unicode \u1234\u5678 characters";
+ ByteString unicode = forString(testString);
+ String roundTripString = unicode.toString(UTF_8);
+ assertEquals(CLASSNAME + " unicode must match", testString, roundTripString);
+ }
+
+ public void testCharsetToString() {
+ String testString = "I love unicode \u1234\u5678 characters";
+ ByteString unicode = forString(testString);
+ String roundTripString = unicode.toString(UTF_8);
+ assertEquals(CLASSNAME + " unicode must match", testString, roundTripString);
+ }
+
+ public void testToString_returnsCanonicalEmptyString() {
+ assertSame(CLASSNAME + " must be the same string references",
+ EMPTY.toString(UTF_8),
+ new NioByteString(ByteBuffer.wrap(new byte[0])).toString(UTF_8));
+ }
+
+ public void testToString_raisesException() {
+ try {
+ EMPTY.toString("invalid");
+ fail("Should have thrown an exception.");
+ } catch (UnsupportedEncodingException expected) {
+ // This is success
+ }
+
+ try {
+ TEST_STRING.toString("invalid");
+ fail("Should have thrown an exception.");
+ } catch (UnsupportedEncodingException expected) {
+ // This is success
+ }
+ }
+
+ public void testEquals() {
+ assertEquals(CLASSNAME + " must not equal null", false, TEST_STRING.equals(null));
+ assertEquals(CLASSNAME + " must equal self", TEST_STRING, TEST_STRING);
+ assertFalse(CLASSNAME + " must not equal the empty string",
+ TEST_STRING.equals(EMPTY));
+ assertEquals(CLASSNAME + " empty strings must be equal",
+ EMPTY, TEST_STRING.substring(55, 55));
+ assertEquals(CLASSNAME + " must equal another string with the same value",
+ TEST_STRING, new NioByteString(BUFFER));
+
+ byte[] mungedBytes = mungedBytes();
+ assertFalse(CLASSNAME + " must not equal every string with the same length",
+ TEST_STRING.equals(new NioByteString(ByteBuffer.wrap(mungedBytes))));
+ }
+
+ public void testEqualsLiteralByteString() {
+ ByteString literal = ByteString.copyFrom(BYTES);
+ assertEquals(CLASSNAME + " must equal LiteralByteString with same value", literal,
+ TEST_STRING);
+ assertEquals(CLASSNAME + " must equal LiteralByteString with same value", TEST_STRING,
+ literal);
+ assertFalse(CLASSNAME + " must not equal the empty string",
+ TEST_STRING.equals(ByteString.EMPTY));
+ assertEquals(CLASSNAME + " empty strings must be equal",
+ ByteString.EMPTY, TEST_STRING.substring(55, 55));
+
+ literal = ByteString.copyFrom(mungedBytes());
+ assertFalse(CLASSNAME + " must not equal every LiteralByteString with the same length",
+ TEST_STRING.equals(literal));
+ assertFalse(CLASSNAME + " must not equal every LiteralByteString with the same length",
+ literal.equals(TEST_STRING));
+ }
+
+ public void testEqualsRopeByteString() {
+ ByteString p1 = ByteString.copyFrom(BYTES, 0, 5);
+ ByteString p2 = ByteString.copyFrom(BYTES, 5, BYTES.length - 5);
+ ByteString rope = p1.concat(p2);
+
+ assertEquals(CLASSNAME + " must equal RopeByteString with same value", rope,
+ TEST_STRING);
+ assertEquals(CLASSNAME + " must equal RopeByteString with same value", TEST_STRING,
+ rope);
+ assertFalse(CLASSNAME + " must not equal the empty string",
+ TEST_STRING.equals(ByteString.EMPTY.concat(ByteString.EMPTY)));
+ assertEquals(CLASSNAME + " empty strings must be equal",
+ ByteString.EMPTY.concat(ByteString.EMPTY), TEST_STRING.substring(55, 55));
+
+ byte[] mungedBytes = mungedBytes();
+ p1 = ByteString.copyFrom(mungedBytes, 0, 5);
+ p2 = ByteString.copyFrom(mungedBytes, 5, mungedBytes.length - 5);
+ rope = p1.concat(p2);
+ assertFalse(CLASSNAME + " must not equal every RopeByteString with the same length",
+ TEST_STRING.equals(rope));
+ assertFalse(CLASSNAME + " must not equal every RopeByteString with the same length",
+ rope.equals(TEST_STRING));
+ }
+
+ private byte[] mungedBytes() {
+ byte[] mungedBytes = new byte[BYTES.length];
+ System.arraycopy(BYTES, 0, mungedBytes, 0, BYTES.length);
+ mungedBytes[mungedBytes.length - 5] = (byte) (mungedBytes[mungedBytes.length - 5] ^ 0xFF);
+ return mungedBytes;
+ }
+
+ public void testHashCode() {
+ int hash = TEST_STRING.hashCode();
+ assertEquals(CLASSNAME + " must have expected hashCode", EXPECTED_HASH, hash);
+ }
+
+ public void testPeekCachedHashCode() {
+ ByteString newString = new NioByteString(BUFFER);
+ assertEquals(CLASSNAME + ".peekCachedHashCode() should return zero at first", 0,
+ newString.peekCachedHashCode());
+ newString.hashCode();
+ assertEquals(CLASSNAME + ".peekCachedHashCode should return zero at first",
+ EXPECTED_HASH, newString.peekCachedHashCode());
+ }
+
+ public void testPartialHash() {
+ // partialHash() is more strenuously tested elsewhere by testing hashes of substrings.
+ // This test would fail if the expected hash were 1. It's not.
+ int hash = TEST_STRING.partialHash(TEST_STRING.size(), 0, TEST_STRING.size());
+ assertEquals(CLASSNAME + ".partialHash() must yield expected hashCode",
+ EXPECTED_HASH, hash);
+ }
+
+ public void testNewInput() throws IOException {
+ InputStream input = TEST_STRING.newInput();
+ assertEquals("InputStream.available() returns correct value",
+ TEST_STRING.size(), input.available());
+ boolean stillEqual = true;
+ for (byte referenceByte : BYTES) {
+ int expectedInt = (referenceByte & 0xFF);
+ stillEqual = (expectedInt == input.read());
+ }
+ assertEquals("InputStream.available() returns correct value",
+ 0, input.available());
+ assertTrue(CLASSNAME + " must give the same bytes from the InputStream", stillEqual);
+ assertEquals(CLASSNAME + " InputStream must now be exhausted", -1, input.read());
+ }
+
+ public void testNewInput_skip() throws IOException {
+ InputStream input = TEST_STRING.newInput();
+ int stringSize = TEST_STRING.size();
+ int nearEndIndex = stringSize * 2 / 3;
+ long skipped1 = input.skip(nearEndIndex);
+ assertEquals("InputStream.skip()", skipped1, nearEndIndex);
+ assertEquals("InputStream.available()",
+ stringSize - skipped1, input.available());
+ assertTrue("InputStream.mark() is available", input.markSupported());
+ input.mark(0);
+ assertEquals("InputStream.skip(), read()",
+ TEST_STRING.byteAt(nearEndIndex) & 0xFF, input.read());
+ assertEquals("InputStream.available()",
+ stringSize - skipped1 - 1, input.available());
+ long skipped2 = input.skip(stringSize);
+ assertEquals("InputStream.skip() incomplete",
+ skipped2, stringSize - skipped1 - 1);
+ assertEquals("InputStream.skip(), no more input", 0, input.available());
+ assertEquals("InputStream.skip(), no more input", -1, input.read());
+ input.reset();
+ assertEquals("InputStream.reset() succeded",
+ stringSize - skipped1, input.available());
+ assertEquals("InputStream.reset(), read()",
+ TEST_STRING.byteAt(nearEndIndex) & 0xFF, input.read());
+ }
+
+ public void testNewCodedInput() throws IOException {
+ CodedInputStream cis = TEST_STRING.newCodedInput();
+ byte[] roundTripBytes = cis.readRawBytes(BYTES.length);
+ assertTrue(CLASSNAME + " must give the same bytes back from the CodedInputStream",
+ Arrays.equals(BYTES, roundTripBytes));
+ assertTrue(CLASSNAME + " CodedInputStream must now be exhausted", cis.isAtEnd());
+ }
+
+ /**
+ * Make sure we keep things simple when concatenating with empty. See also
+ * {@link ByteStringTest#testConcat_empty()}.
+ */
+ public void testConcat_empty() {
+ assertSame(CLASSNAME + " concatenated with empty must give " + CLASSNAME,
+ TEST_STRING.concat(EMPTY), TEST_STRING);
+ assertSame("empty concatenated with " + CLASSNAME + " must give " + CLASSNAME,
+ EMPTY.concat(TEST_STRING), TEST_STRING);
+ }
+
+ public void testJavaSerialization() throws Exception {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(out);
+ oos.writeObject(TEST_STRING);
+ oos.close();
+ byte[] pickled = out.toByteArray();
+ InputStream in = new ByteArrayInputStream(pickled);
+ ObjectInputStream ois = new ObjectInputStream(in);
+ Object o = ois.readObject();
+ assertTrue("Didn't get a ByteString back", o instanceof ByteString);
+ assertEquals("Should get an equal ByteString back", TEST_STRING, o);
+ }
+
+ private static ByteString forString(String str) {
+ return new NioByteString(ByteBuffer.wrap(str.getBytes(UTF_8)));
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/ParseExceptionsTest.java b/java/core/src/test/java/com/google/protobuf/ParseExceptionsTest.java
new file mode 100644
index 00000000..03593413
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/ParseExceptionsTest.java
@@ -0,0 +1,212 @@
+package com.google.protobuf;
+
+import com.google.protobuf.DescriptorProtos.DescriptorProto;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+/**
+ * Tests the exceptions thrown when parsing from a stream. The methods on the {@link Parser}
+ * interface are specified to only throw {@link InvalidProtocolBufferException}. But we really want
+ * to distinguish between invalid protos vs. actual I/O errors (like failures reading from a
+ * socket, etc.). So, when we're not using the parser directly, an {@link IOException} should be
+ * thrown where appropriate, instead of always an {@link InvalidProtocolBufferException}.
+ *
+ * @author jh@squareup.com (Joshua Humphries)
+ */
+public class ParseExceptionsTest {
+
+// disable for now for update the maven local repo.
+// private interface ParseTester {
+// DescriptorProto parse(InputStream in) throws IOException;
+// }
+//
+// private byte serializedProto[];
+//
+// private void setup() {
+// serializedProto = DescriptorProto.getDescriptor().toProto().toByteArray();
+// }
+//
+// private void setupDelimited() {
+// ByteArrayOutputStream bos = new ByteArrayOutputStream();
+// try {
+// DescriptorProto.getDescriptor().toProto().writeDelimitedTo(bos);
+// } catch (IOException e) {
+// fail("Exception not expected: " + e);
+// }
+// serializedProto = bos.toByteArray();
+// }
+//
+// @Test public void message_parseFrom_InputStream() {
+// setup();
+// verifyExceptions(new ParseTester() {
+// public DescriptorProto parse(InputStream in) throws IOException {
+// return DescriptorProto.parseFrom(in);
+// }
+// });
+// }
+//
+// @Test public void message_parseFrom_InputStreamAndExtensionRegistry() {
+// setup();
+// verifyExceptions(new ParseTester() {
+// public DescriptorProto parse(InputStream in) throws IOException {
+// return DescriptorProto.parseFrom(in, ExtensionRegistry.newInstance());
+// }
+// });
+// }
+//
+// @Test public void message_parseFrom_CodedInputStream() {
+// setup();
+// verifyExceptions(new ParseTester() {
+// public DescriptorProto parse(InputStream in) throws IOException {
+// return DescriptorProto.parseFrom(CodedInputStream.newInstance(in));
+// }
+// });
+// }
+//
+// @Test public void message_parseFrom_CodedInputStreamAndExtensionRegistry() {
+// setup();
+// verifyExceptions(new ParseTester() {
+// public DescriptorProto parse(InputStream in) throws IOException {
+// return DescriptorProto.parseFrom(CodedInputStream.newInstance(in),
+// ExtensionRegistry.newInstance());
+// }
+// });
+// }
+//
+// @Test public void message_parseDelimitedFrom_InputStream() {
+// setupDelimited();
+// verifyExceptions(new ParseTester() {
+// public DescriptorProto parse(InputStream in) throws IOException {
+// return DescriptorProto.parseDelimitedFrom(in);
+// }
+// });
+// }
+//
+// @Test public void message_parseDelimitedFrom_InputStreamAndExtensionRegistry() {
+// setupDelimited();
+// verifyExceptions(new ParseTester() {
+// public DescriptorProto parse(InputStream in) throws IOException {
+// return DescriptorProto.parseDelimitedFrom(in, ExtensionRegistry.newInstance());
+// }
+// });
+// }
+//
+// @Test public void messageBuilder_mergeFrom_InputStream() {
+// setup();
+// verifyExceptions(new ParseTester() {
+// public DescriptorProto parse(InputStream in) throws IOException {
+// return DescriptorProto.newBuilder().mergeFrom(in).build();
+// }
+// });
+// }
+//
+// @Test public void messageBuilder_mergeFrom_InputStreamAndExtensionRegistry() {
+// setup();
+// verifyExceptions(new ParseTester() {
+// public DescriptorProto parse(InputStream in) throws IOException {
+// return DescriptorProto.newBuilder().mergeFrom(in, ExtensionRegistry.newInstance()).build();
+// }
+// });
+// }
+//
+// @Test public void messageBuilder_mergeFrom_CodedInputStream() {
+// setup();
+// verifyExceptions(new ParseTester() {
+// public DescriptorProto parse(InputStream in) throws IOException {
+// return DescriptorProto.newBuilder().mergeFrom(CodedInputStream.newInstance(in)).build();
+// }
+// });
+// }
+//
+// @Test public void messageBuilder_mergeFrom_CodedInputStreamAndExtensionRegistry() {
+// setup();
+// verifyExceptions(new ParseTester() {
+// public DescriptorProto parse(InputStream in) throws IOException {
+// return DescriptorProto.newBuilder()
+// .mergeFrom(CodedInputStream.newInstance(in), ExtensionRegistry.newInstance()).build();
+// }
+// });
+// }
+//
+// @Test public void messageBuilder_mergeDelimitedFrom_InputStream() {
+// setupDelimited();
+// verifyExceptions(new ParseTester() {
+// public DescriptorProto parse(InputStream in) throws IOException {
+// DescriptorProto.Builder builder = DescriptorProto.newBuilder();
+// builder.mergeDelimitedFrom(in);
+// return builder.build();
+// }
+// });
+// }
+//
+// @Test public void messageBuilder_mergeDelimitedFrom_InputStreamAndExtensionRegistry() {
+// setupDelimited();
+// verifyExceptions(new ParseTester() {
+// public DescriptorProto parse(InputStream in) throws IOException {
+// DescriptorProto.Builder builder = DescriptorProto.newBuilder();
+// builder.mergeDelimitedFrom(in, ExtensionRegistry.newInstance());
+// return builder.build();
+// }
+// });
+// }
+//
+// private void verifyExceptions(ParseTester parseTester) {
+// // No exception
+// try {
+// assertEquals(DescriptorProto.getDescriptor().toProto(),
+// parseTester.parse(new ByteArrayInputStream(serializedProto)));
+// } catch (IOException e) {
+// fail("No exception expected: " + e);
+// }
+//
+// // IOException
+// try {
+// // using a "broken" stream that will throw part-way through reading the message
+// parseTester.parse(broken(new ByteArrayInputStream(serializedProto)));
+// fail("IOException expected but not thrown");
+// } catch (IOException e) {
+// assertFalse(e instanceof InvalidProtocolBufferException);
+// }
+//
+// // InvalidProtocolBufferException
+// try {
+// // make the serialized proto invalid
+// for (int i = 0; i < 50; i++) {
+// serializedProto[i] = -1;
+// }
+// parseTester.parse(new ByteArrayInputStream(serializedProto));
+// fail("InvalidProtocolBufferException expected but not thrown");
+// } catch (IOException e) {
+// assertTrue(e instanceof InvalidProtocolBufferException);
+// }
+// }
+//
+// private InputStream broken(InputStream i) {
+// return new FilterInputStream(i) {
+// int count = 0;
+//
+// @Override public int read() throws IOException {
+// if (count++ >= 50) {
+// throw new IOException("I'm broken!");
+// }
+// return super.read();
+// }
+//
+// @Override public int read(byte b[], int off, int len) throws IOException {
+// if ((count += len) >= 50) {
+// throw new IOException("I'm broken!");
+// }
+// return super.read(b, off, len);
+// }
+// };
+// }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/ParserTest.java b/java/core/src/test/java/com/google/protobuf/ParserTest.java
new file mode 100644
index 00000000..5a92bacf
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/ParserTest.java
@@ -0,0 +1,377 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// 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 com.google.protobuf.UnittestLite.TestAllTypesLite;
+import com.google.protobuf.UnittestLite.TestPackedExtensionsLite;
+import com.google.protobuf.UnittestLite.TestParsingMergeLite;
+import protobuf_unittest.UnittestOptimizeFor.TestOptimizedForSize;
+import protobuf_unittest.UnittestOptimizeFor.TestRequiredOptimizedForSize;
+import protobuf_unittest.UnittestOptimizeFor;
+import protobuf_unittest.UnittestProto.ForeignMessage;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.TestEmptyMessage;
+import protobuf_unittest.UnittestProto.TestParsingMerge;
+import protobuf_unittest.UnittestProto.TestRequired;
+import protobuf_unittest.UnittestProto;
+
+import junit.framework.TestCase;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * Unit test for {@link Parser}.
+ *
+ * @author liujisi@google.com (Pherl Liu)
+ */
+public class ParserTest extends TestCase {
+ public void testGeneratedMessageParserSingleton() throws Exception {
+ for (int i = 0; i < 10; i++) {
+ assertEquals(TestAllTypes.parser(), TestUtil.getAllSet().getParserForType());
+ }
+ }
+
+ private void assertRoundTripEquals(MessageLite message,
+ ExtensionRegistryLite registry)
+ throws Exception {
+ final byte[] data = message.toByteArray();
+ final int offset = 20;
+ final int length = data.length;
+ final int padding = 30;
+ Parser<? extends MessageLite> parser = message.getParserForType();
+ assertMessageEquals(message, parser.parseFrom(data, registry));
+ assertMessageEquals(message, parser.parseFrom(
+ generatePaddingArray(data, offset, padding),
+ offset, length, registry));
+ assertMessageEquals(message, parser.parseFrom(
+ message.toByteString(), registry));
+ assertMessageEquals(message, parser.parseFrom(
+ new ByteArrayInputStream(data), registry));
+ assertMessageEquals(message, parser.parseFrom(
+ CodedInputStream.newInstance(data), registry));
+ }
+
+ @SuppressWarnings("unchecked")
+ private void assertRoundTripEquals(MessageLite message) throws Exception {
+ final byte[] data = message.toByteArray();
+ final int offset = 20;
+ final int length = data.length;
+ final int padding = 30;
+
+ Parser<MessageLite> parser =
+ (Parser<MessageLite>) message.getParserForType();
+ assertMessageEquals(message, parser.parseFrom(data));
+ assertMessageEquals(message, parser.parseFrom(
+ generatePaddingArray(data, offset, padding),
+ offset, length));
+ assertMessageEquals(message, parser.parseFrom(message.toByteString()));
+ assertMessageEquals(message, parser.parseFrom(
+ new ByteArrayInputStream(data)));
+ assertMessageEquals(message, parser.parseFrom(
+ CodedInputStream.newInstance(data)));
+ }
+
+ private void assertMessageEquals(
+ MessageLite expected, MessageLite actual)
+ throws Exception {
+ if (expected instanceof Message) {
+ assertEquals(expected, actual);
+ } else {
+ assertEquals(expected.toByteString(), actual.toByteString());
+ }
+ }
+
+ private byte[] generatePaddingArray(byte[] data, int offset, int padding) {
+ byte[] result = new byte[offset + data.length + padding];
+ System.arraycopy(data, 0, result, offset, data.length);
+ return result;
+ }
+
+ public void testNormalMessage() throws Exception {
+ assertRoundTripEquals(TestUtil.getAllSet());
+ }
+
+
+ public void testParsePartial() throws Exception {
+ assertParsePartial(TestRequired.parser(), TestRequired.newBuilder().setA(1).buildPartial());
+ }
+
+ private <T extends MessageLite> void assertParsePartial(
+ Parser<T> parser, T partialMessage) throws Exception {
+ final String errorString =
+ "Should throw exceptions when the parsed message isn't initialized.";
+
+ // parsePartialFrom should pass.
+ byte[] data = partialMessage.toByteArray();
+ assertEquals(partialMessage, parser.parsePartialFrom(data));
+ assertEquals(partialMessage, parser.parsePartialFrom(
+ partialMessage.toByteString()));
+ assertEquals(partialMessage, parser.parsePartialFrom(
+ new ByteArrayInputStream(data)));
+ assertEquals(partialMessage, parser.parsePartialFrom(
+ CodedInputStream.newInstance(data)));
+
+ // parseFrom(ByteArray)
+ try {
+ parser.parseFrom(partialMessage.toByteArray());
+ fail(errorString);
+ } catch (InvalidProtocolBufferException e) {
+ // pass.
+ }
+
+ // parseFrom(ByteString)
+ try {
+ parser.parseFrom(partialMessage.toByteString());
+ fail(errorString);
+ } catch (InvalidProtocolBufferException e) {
+ // pass.
+ }
+
+ // parseFrom(InputStream)
+ try {
+ parser.parseFrom(new ByteArrayInputStream(partialMessage.toByteArray()));
+ fail(errorString);
+ } catch (IOException e) {
+ // pass.
+ }
+
+ // parseFrom(CodedInputStream)
+ try {
+ parser.parseFrom(CodedInputStream.newInstance(
+ partialMessage.toByteArray()));
+ fail(errorString);
+ } catch (IOException e) {
+ // pass.
+ }
+ }
+
+ public void testParseExtensions() throws Exception {
+ assertRoundTripEquals(TestUtil.getAllExtensionsSet(),
+ TestUtil.getExtensionRegistry());
+ assertRoundTripEquals(TestUtil.getAllLiteExtensionsSet(),
+ TestUtil.getExtensionRegistryLite());
+ }
+
+ public void testParsePacked() throws Exception {
+ assertRoundTripEquals(TestUtil.getPackedSet());
+ assertRoundTripEquals(TestUtil.getPackedExtensionsSet(),
+ TestUtil.getExtensionRegistry());
+ assertRoundTripEquals(TestUtil.getLitePackedExtensionsSet(),
+ TestUtil.getExtensionRegistryLite());
+ }
+
+ public void testParseDelimitedTo() throws Exception {
+ // Write normal Message.
+ TestAllTypes normalMessage = TestUtil.getAllSet();
+ ByteArrayOutputStream output = new ByteArrayOutputStream();
+ normalMessage.writeDelimitedTo(output);
+
+ // Write MessageLite with packed extension fields.
+ TestPackedExtensionsLite packedMessage =
+ TestUtil.getLitePackedExtensionsSet();
+ packedMessage.writeDelimitedTo(output);
+
+ InputStream input = new ByteArrayInputStream(output.toByteArray());
+ assertMessageEquals(
+ normalMessage,
+ normalMessage.getParserForType().parseDelimitedFrom(input));
+ assertMessageEquals(
+ packedMessage,
+ packedMessage.getParserForType().parseDelimitedFrom(
+ input, TestUtil.getExtensionRegistryLite()));
+ }
+
+ public void testParseUnknownFields() throws Exception {
+ // All fields will be treated as unknown fields in emptyMessage.
+ TestEmptyMessage emptyMessage =
+ TestEmptyMessage.parser().parseFrom(TestUtil.getAllSet().toByteString());
+ assertEquals(
+ TestUtil.getAllSet().toByteString(),
+ emptyMessage.toByteString());
+ }
+
+
+ public void testOptimizeForSize() throws Exception {
+ TestOptimizedForSize.Builder builder = TestOptimizedForSize.newBuilder();
+ builder.setI(12).setMsg(ForeignMessage.newBuilder().setC(34).build());
+ builder.setExtension(TestOptimizedForSize.testExtension, 56);
+ builder.setExtension(TestOptimizedForSize.testExtension2,
+ TestRequiredOptimizedForSize.newBuilder().setX(78).build());
+
+ TestOptimizedForSize message = builder.build();
+ ExtensionRegistry registry = ExtensionRegistry.newInstance();
+ UnittestOptimizeFor.registerAllExtensions(registry);
+
+ assertRoundTripEquals(message, registry);
+ }
+
+ /** Helper method for {@link #testParsingMerge()}.*/
+ private void assertMessageMerged(TestAllTypes allTypes)
+ throws Exception {
+ assertEquals(3, allTypes.getOptionalInt32());
+ assertEquals(2, allTypes.getOptionalInt64());
+ assertEquals("hello", allTypes.getOptionalString());
+ }
+
+ /** Helper method for {@link #testParsingMergeLite()}.*/
+ private void assertMessageMerged(TestAllTypesLite allTypes)
+ throws Exception {
+ assertEquals(3, allTypes.getOptionalInt32());
+ assertEquals(2, allTypes.getOptionalInt64());
+ assertEquals("hello", allTypes.getOptionalString());
+ }
+
+ public void testParsingMerge() throws Exception {
+ // Build messages.
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TestAllTypes msg1 = builder.setOptionalInt32(1).build();
+ builder.clear();
+ TestAllTypes msg2 = builder.setOptionalInt64(2).build();
+ builder.clear();
+ TestAllTypes msg3 = builder.setOptionalInt32(3)
+ .setOptionalString("hello").build();
+
+ // Build groups.
+ TestParsingMerge.RepeatedFieldsGenerator.Group1 optionalG1 =
+ TestParsingMerge.RepeatedFieldsGenerator.Group1.newBuilder()
+ .setField1(msg1).build();
+ TestParsingMerge.RepeatedFieldsGenerator.Group1 optionalG2 =
+ TestParsingMerge.RepeatedFieldsGenerator.Group1.newBuilder()
+ .setField1(msg2).build();
+ TestParsingMerge.RepeatedFieldsGenerator.Group1 optionalG3 =
+ TestParsingMerge.RepeatedFieldsGenerator.Group1.newBuilder()
+ .setField1(msg3).build();
+ TestParsingMerge.RepeatedFieldsGenerator.Group2 repeatedG1 =
+ TestParsingMerge.RepeatedFieldsGenerator.Group2.newBuilder()
+ .setField1(msg1).build();
+ TestParsingMerge.RepeatedFieldsGenerator.Group2 repeatedG2 =
+ TestParsingMerge.RepeatedFieldsGenerator.Group2.newBuilder()
+ .setField1(msg2).build();
+ TestParsingMerge.RepeatedFieldsGenerator.Group2 repeatedG3 =
+ TestParsingMerge.RepeatedFieldsGenerator.Group2.newBuilder()
+ .setField1(msg3).build();
+
+ // Assign and serialize RepeatedFieldsGenerator.
+ ByteString data = TestParsingMerge.RepeatedFieldsGenerator.newBuilder()
+ .addField1(msg1).addField1(msg2).addField1(msg3)
+ .addField2(msg1).addField2(msg2).addField2(msg3)
+ .addField3(msg1).addField3(msg2).addField3(msg3)
+ .addGroup1(optionalG1).addGroup1(optionalG2).addGroup1(optionalG3)
+ .addGroup2(repeatedG1).addGroup2(repeatedG2).addGroup2(repeatedG3)
+ .addExt1(msg1).addExt1(msg2).addExt1(msg3)
+ .addExt2(msg1).addExt2(msg2).addExt2(msg3)
+ .build().toByteString();
+
+ // Parse TestParsingMerge.
+ ExtensionRegistry registry = ExtensionRegistry.newInstance();
+ UnittestProto.registerAllExtensions(registry);
+ TestParsingMerge parsingMerge = TestParsingMerge.parser().parseFrom(data, registry);
+
+ // Required and optional fields should be merged.
+ assertMessageMerged(parsingMerge.getRequiredAllTypes());
+ assertMessageMerged(parsingMerge.getOptionalAllTypes());
+ assertMessageMerged(
+ parsingMerge.getOptionalGroup().getOptionalGroupAllTypes());
+ assertMessageMerged(parsingMerge.getExtension(
+ TestParsingMerge.optionalExt));
+
+ // Repeated fields should not be merged.
+ assertEquals(3, parsingMerge.getRepeatedAllTypesCount());
+ assertEquals(3, parsingMerge.getRepeatedGroupCount());
+ assertEquals(3, parsingMerge.getExtensionCount(
+ TestParsingMerge.repeatedExt));
+ }
+
+ public void testParsingMergeLite() throws Exception {
+ // Build messages.
+ TestAllTypesLite.Builder builder =
+ TestAllTypesLite.newBuilder();
+ TestAllTypesLite msg1 = builder.setOptionalInt32(1).build();
+ builder.clear();
+ TestAllTypesLite msg2 = builder.setOptionalInt64(2).build();
+ builder.clear();
+ TestAllTypesLite msg3 = builder.setOptionalInt32(3)
+ .setOptionalString("hello").build();
+
+ // Build groups.
+ TestParsingMergeLite.RepeatedFieldsGenerator.Group1 optionalG1 =
+ TestParsingMergeLite.RepeatedFieldsGenerator.Group1.newBuilder()
+ .setField1(msg1).build();
+ TestParsingMergeLite.RepeatedFieldsGenerator.Group1 optionalG2 =
+ TestParsingMergeLite.RepeatedFieldsGenerator.Group1.newBuilder()
+ .setField1(msg2).build();
+ TestParsingMergeLite.RepeatedFieldsGenerator.Group1 optionalG3 =
+ TestParsingMergeLite.RepeatedFieldsGenerator.Group1.newBuilder()
+ .setField1(msg3).build();
+ TestParsingMergeLite.RepeatedFieldsGenerator.Group2 repeatedG1 =
+ TestParsingMergeLite.RepeatedFieldsGenerator.Group2.newBuilder()
+ .setField1(msg1).build();
+ TestParsingMergeLite.RepeatedFieldsGenerator.Group2 repeatedG2 =
+ TestParsingMergeLite.RepeatedFieldsGenerator.Group2.newBuilder()
+ .setField1(msg2).build();
+ TestParsingMergeLite.RepeatedFieldsGenerator.Group2 repeatedG3 =
+ TestParsingMergeLite.RepeatedFieldsGenerator.Group2.newBuilder()
+ .setField1(msg3).build();
+
+ // Assign and serialize RepeatedFieldsGenerator.
+ ByteString data = TestParsingMergeLite.RepeatedFieldsGenerator.newBuilder()
+ .addField1(msg1).addField1(msg2).addField1(msg3)
+ .addField2(msg1).addField2(msg2).addField2(msg3)
+ .addField3(msg1).addField3(msg2).addField3(msg3)
+ .addGroup1(optionalG1).addGroup1(optionalG2).addGroup1(optionalG3)
+ .addGroup2(repeatedG1).addGroup2(repeatedG2).addGroup2(repeatedG3)
+ .addExt1(msg1).addExt1(msg2).addExt1(msg3)
+ .addExt2(msg1).addExt2(msg2).addExt2(msg3)
+ .build().toByteString();
+
+ // Parse TestParsingMergeLite.
+ ExtensionRegistry registry = ExtensionRegistry.newInstance();
+ UnittestLite.registerAllExtensions(registry);
+ TestParsingMergeLite parsingMerge = TestParsingMergeLite.parser().parseFrom(data, registry);
+
+ // Required and optional fields should be merged.
+ assertMessageMerged(parsingMerge.getRequiredAllTypes());
+ assertMessageMerged(parsingMerge.getOptionalAllTypes());
+ assertMessageMerged(
+ parsingMerge.getOptionalGroup().getOptionalGroupAllTypes());
+ assertMessageMerged(parsingMerge.getExtension(
+ TestParsingMergeLite.optionalExt));
+
+ // Repeated fields should not be merged.
+ assertEquals(3, parsingMerge.getRepeatedAllTypesCount());
+ assertEquals(3, parsingMerge.getRepeatedGroupCount());
+ assertEquals(3, parsingMerge.getExtensionCount(
+ TestParsingMergeLite.repeatedExt));
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/ProtobufArrayListTest.java b/java/core/src/test/java/com/google/protobuf/ProtobufArrayListTest.java
new file mode 100644
index 00000000..245c3dee
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/ProtobufArrayListTest.java
@@ -0,0 +1,303 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// 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 static java.util.Arrays.asList;
+
+import junit.framework.TestCase;
+
+import java.util.Collections;
+import java.util.ConcurrentModificationException;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Tests for {@link ProtobufArrayList}.
+ */
+public class ProtobufArrayListTest extends TestCase {
+
+ private static final ProtobufArrayList<Integer> UNARY_LIST = newImmutableProtoArrayList(1);
+ private static final ProtobufArrayList<Integer> TERTIARY_LIST =
+ newImmutableProtoArrayList(1, 2, 3);
+
+ private ProtobufArrayList<Integer> list;
+
+ @Override
+ protected void setUp() throws Exception {
+ list = new ProtobufArrayList<Integer>();
+ }
+
+ public void testEmptyListReturnsSameInstance() {
+ assertSame(ProtobufArrayList.emptyList(), ProtobufArrayList.emptyList());
+ }
+
+ public void testEmptyListIsImmutable() {
+ assertImmutable(ProtobufArrayList.<Integer>emptyList());
+ }
+
+ public void testCopyConstructor() {
+ ProtobufArrayList<Integer> copy = new ProtobufArrayList<Integer>(TERTIARY_LIST);
+ assertEquals(TERTIARY_LIST, copy);
+
+ copy = new ProtobufArrayList<Integer>(IntArrayList.emptyList());
+ assertEquals(ProtobufArrayList.emptyList(), copy);
+
+ copy = new ProtobufArrayList<Integer>(asList(1, 2, 3));
+ assertEquals(asList(1, 2, 3), copy);
+
+ copy = new ProtobufArrayList<Integer>(Collections.<Integer>emptyList());
+ assertEquals(ProtobufArrayList.emptyList(), copy);
+ }
+
+ public void testModificationWithIteration() {
+ list.addAll(asList(1, 2, 3, 4));
+ Iterator<Integer> iterator = list.iterator();
+ assertEquals(4, list.size());
+ assertEquals(1, (int) list.get(0));
+ assertEquals(1, (int) iterator.next());
+
+ list.remove(0);
+ try {
+ iterator.next();
+ fail();
+ } catch (ConcurrentModificationException e) {
+ // expected
+ }
+
+ iterator = list.iterator();
+ list.set(0, 1);
+ try {
+ iterator.next();
+ fail();
+ } catch (ConcurrentModificationException e) {
+ // expected
+ }
+
+ iterator = list.iterator();
+ list.add(0, 0);
+ try {
+ iterator.next();
+ fail();
+ } catch (ConcurrentModificationException e) {
+ // expected
+ }
+ }
+
+ public void testMakeImmutable() {
+ list.add(2);
+ list.add(4);
+ list.add(6);
+ list.add(8);
+ list.makeImmutable();
+ assertImmutable(list);
+ }
+
+ public void testRemove() {
+ list.add(2);
+ list.add(4);
+ list.add(6);
+
+ list.remove(1);
+ assertEquals(asList(2, 6), list);
+
+ list.remove(1);
+ assertEquals(asList(2), list);
+
+ list.remove(0);
+ assertEquals(asList(), list);
+ }
+
+ public void testGet() {
+ list.add(2);
+ list.add(6);
+
+ assertEquals(2, (int) list.get(0));
+ assertEquals(6, (int) list.get(1));
+ }
+
+ public void testSet() {
+ list.add(2);
+ list.add(6);
+
+ list.set(0, 1);
+ assertEquals(1, (int) list.get(0));
+ list.set(1, 2);
+ assertEquals(2, (int) list.get(1));
+ }
+
+ private void assertImmutable(List<Integer> list) {
+ if (list.contains(1)) {
+ throw new RuntimeException("Cannot test the immutability of lists that contain 1.");
+ }
+
+ try {
+ list.add(1);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.add(0, 1);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(Collections.<Integer>emptyList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(Collections.singletonList(1));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(new ProtobufArrayList<Integer>());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(UNARY_LIST);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(0, Collections.singleton(1));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(0, UNARY_LIST);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(0, Collections.<Integer>emptyList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.clear();
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.remove(1);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.remove(new Object());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.removeAll(Collections.emptyList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.removeAll(Collections.singleton(1));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.removeAll(UNARY_LIST);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.retainAll(Collections.emptyList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.retainAll(Collections.singleton(1));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.retainAll(UNARY_LIST);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.set(0, 0);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ }
+
+ private static ProtobufArrayList<Integer> newImmutableProtoArrayList(int... elements) {
+ ProtobufArrayList<Integer> list = new ProtobufArrayList<Integer>();
+ for (int element : elements) {
+ list.add(element);
+ }
+ list.makeImmutable();
+ return list;
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/RepeatedFieldBuilderTest.java b/java/core/src/test/java/com/google/protobuf/RepeatedFieldBuilderTest.java
new file mode 100644
index 00000000..49d52321
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/RepeatedFieldBuilderTest.java
@@ -0,0 +1,190 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// 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.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.TestAllTypesOrBuilder;
+
+import junit.framework.TestCase;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Tests for {@link RepeatedFieldBuilder}. This tests basic functionality.
+ * More extensive testing is provided via other tests that exercise the
+ * builder.
+ *
+ * @author jonp@google.com (Jon Perlow)
+ */
+public class RepeatedFieldBuilderTest extends TestCase {
+
+ public void testBasicUse() {
+ TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent();
+ RepeatedFieldBuilder<TestAllTypes, TestAllTypes.Builder,
+ TestAllTypesOrBuilder> builder = newRepeatedFieldBuilder(mockParent);
+ builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(0).build());
+ builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(1).build());
+ assertEquals(0, builder.getMessage(0).getOptionalInt32());
+ assertEquals(1, builder.getMessage(1).getOptionalInt32());
+
+ List<TestAllTypes> list = builder.build();
+ assertEquals(2, list.size());
+ assertEquals(0, list.get(0).getOptionalInt32());
+ assertEquals(1, list.get(1).getOptionalInt32());
+ assertIsUnmodifiable(list);
+
+ // Make sure it doesn't change.
+ List<TestAllTypes> list2 = builder.build();
+ assertSame(list, list2);
+ assertEquals(0, mockParent.getInvalidationCount());
+ }
+
+ public void testGoingBackAndForth() {
+ TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent();
+ RepeatedFieldBuilder<TestAllTypes, TestAllTypes.Builder,
+ TestAllTypesOrBuilder> builder = newRepeatedFieldBuilder(mockParent);
+ builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(0).build());
+ builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(1).build());
+ assertEquals(0, builder.getMessage(0).getOptionalInt32());
+ assertEquals(1, builder.getMessage(1).getOptionalInt32());
+
+ // Convert to list
+ List<TestAllTypes> list = builder.build();
+ assertEquals(2, list.size());
+ assertEquals(0, list.get(0).getOptionalInt32());
+ assertEquals(1, list.get(1).getOptionalInt32());
+ assertIsUnmodifiable(list);
+
+ // Update 0th item
+ assertEquals(0, mockParent.getInvalidationCount());
+ builder.getBuilder(0).setOptionalString("foo");
+ assertEquals(1, mockParent.getInvalidationCount());
+ list = builder.build();
+ assertEquals(2, list.size());
+ assertEquals(0, list.get(0).getOptionalInt32());
+ assertEquals("foo", list.get(0).getOptionalString());
+ assertEquals(1, list.get(1).getOptionalInt32());
+ assertIsUnmodifiable(list);
+ assertEquals(1, mockParent.getInvalidationCount());
+ }
+
+ public void testVariousMethods() {
+ TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent();
+ RepeatedFieldBuilder<TestAllTypes, TestAllTypes.Builder,
+ TestAllTypesOrBuilder> builder = newRepeatedFieldBuilder(mockParent);
+ builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(1).build());
+ builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(2).build());
+ builder.addBuilder(0, TestAllTypes.getDefaultInstance())
+ .setOptionalInt32(0);
+ builder.addBuilder(TestAllTypes.getDefaultInstance()).setOptionalInt32(3);
+
+ assertEquals(0, builder.getMessage(0).getOptionalInt32());
+ assertEquals(1, builder.getMessage(1).getOptionalInt32());
+ assertEquals(2, builder.getMessage(2).getOptionalInt32());
+ assertEquals(3, builder.getMessage(3).getOptionalInt32());
+
+ assertEquals(0, mockParent.getInvalidationCount());
+ List<TestAllTypes> messages = builder.build();
+ assertEquals(4, messages.size());
+ assertSame(messages, builder.build()); // expect same list
+
+ // Remove a message.
+ builder.remove(2);
+ assertEquals(1, mockParent.getInvalidationCount());
+ assertEquals(3, builder.getCount());
+ assertEquals(0, builder.getMessage(0).getOptionalInt32());
+ assertEquals(1, builder.getMessage(1).getOptionalInt32());
+ assertEquals(3, builder.getMessage(2).getOptionalInt32());
+
+ // Remove a builder.
+ builder.remove(0);
+ assertEquals(1, mockParent.getInvalidationCount());
+ assertEquals(2, builder.getCount());
+ assertEquals(1, builder.getMessage(0).getOptionalInt32());
+ assertEquals(3, builder.getMessage(1).getOptionalInt32());
+
+ // Test clear.
+ builder.clear();
+ assertEquals(1, mockParent.getInvalidationCount());
+ assertEquals(0, builder.getCount());
+ assertTrue(builder.isEmpty());
+ }
+
+ public void testLists() {
+ TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent();
+ RepeatedFieldBuilder<TestAllTypes, TestAllTypes.Builder,
+ TestAllTypesOrBuilder> builder = newRepeatedFieldBuilder(mockParent);
+ builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(1).build());
+ builder.addMessage(0,
+ TestAllTypes.newBuilder().setOptionalInt32(0).build());
+ assertEquals(0, builder.getMessage(0).getOptionalInt32());
+ assertEquals(1, builder.getMessage(1).getOptionalInt32());
+
+ // Use list of builders.
+ List<TestAllTypes.Builder> builders = builder.getBuilderList();
+ assertEquals(0, builders.get(0).getOptionalInt32());
+ assertEquals(1, builders.get(1).getOptionalInt32());
+ builders.get(0).setOptionalInt32(10);
+ builders.get(1).setOptionalInt32(11);
+
+ // Use list of protos
+ List<TestAllTypes> protos = builder.getMessageList();
+ assertEquals(10, protos.get(0).getOptionalInt32());
+ assertEquals(11, protos.get(1).getOptionalInt32());
+
+ // Add an item to the builders and verify it's updated in both
+ builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(12).build());
+ assertEquals(3, builders.size());
+ assertEquals(3, protos.size());
+ }
+
+ private void assertIsUnmodifiable(List<?> list) {
+ if (list == Collections.emptyList()) {
+ // OKAY -- Need to check this b/c EmptyList allows you to call clear.
+ } else {
+ try {
+ list.clear();
+ fail("List wasn't immutable");
+ } catch (UnsupportedOperationException e) {
+ // good
+ }
+ }
+ }
+
+ private RepeatedFieldBuilder<TestAllTypes, TestAllTypes.Builder,
+ TestAllTypesOrBuilder>
+ newRepeatedFieldBuilder(GeneratedMessage.BuilderParent parent) {
+ return new RepeatedFieldBuilder<TestAllTypes, TestAllTypes.Builder,
+ TestAllTypesOrBuilder>(Collections.<TestAllTypes>emptyList(), false,
+ parent, false);
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/RopeByteStringSubstringTest.java b/java/core/src/test/java/com/google/protobuf/RopeByteStringSubstringTest.java
new file mode 100644
index 00000000..dc56f2e9
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/RopeByteStringSubstringTest.java
@@ -0,0 +1,127 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// 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 java.io.UnsupportedEncodingException;
+import java.util.Iterator;
+
+/**
+ * This class tests {@link RopeByteString#substring(int, int)} by inheriting the tests from
+ * {@link LiteralByteStringTest}. Only a couple of methods are overridden.
+ *
+ * @author carlanton@google.com (Carl Haverl)
+ */
+public class RopeByteStringSubstringTest extends LiteralByteStringTest {
+
+ @Override
+ protected void setUp() throws Exception {
+ classUnderTest = "RopeByteString";
+ byte[] sourceBytes = ByteStringTest.getTestBytes(22341, 22337766L);
+ Iterator<ByteString> iter = ByteStringTest.makeConcretePieces(sourceBytes).iterator();
+ ByteString sourceString = iter.next();
+ while (iter.hasNext()) {
+ sourceString = sourceString.concat(iter.next());
+ }
+
+ int from = 1130;
+ int to = sourceBytes.length - 5555;
+ stringUnderTest = sourceString.substring(from, to);
+ referenceBytes = new byte[to - from];
+ System.arraycopy(sourceBytes, from, referenceBytes, 0, to - from);
+ expectedHashCode = -1259260680;
+ }
+
+ @Override
+ public void testGetTreeDepth() {
+ assertEquals(classUnderTest + " must have the expected tree depth",
+ 3, stringUnderTest.getTreeDepth());
+ }
+
+ @Override
+ public void testToString() throws UnsupportedEncodingException {
+ String sourceString = "I love unicode \u1234\u5678 characters";
+ ByteString sourceByteString = ByteString.copyFromUtf8(sourceString);
+ int copies = 250;
+
+ // By building the RopeByteString by concatenating, this is actually a fairly strenuous test.
+ StringBuilder builder = new StringBuilder(copies * sourceString.length());
+ ByteString unicode = ByteString.EMPTY;
+ for (int i = 0; i < copies; ++i) {
+ builder.append(sourceString);
+ unicode = RopeByteString.concatenate(unicode, sourceByteString);
+ }
+ String testString = builder.toString();
+
+ // Do the substring part
+ testString = testString.substring(2, testString.length() - 6);
+ unicode = unicode.substring(2, unicode.size() - 6);
+
+ assertEquals(classUnderTest + " from string must have the expected type",
+ classUnderTest, getActualClassName(unicode));
+ String roundTripString = unicode.toString(UTF_8);
+ assertEquals(classUnderTest + " unicode bytes must match",
+ testString, roundTripString);
+ ByteString flatString = ByteString.copyFromUtf8(testString);
+ assertEquals(classUnderTest + " string must equal the flat string", flatString, unicode);
+ assertEquals(classUnderTest + " string must must have same hashCode as the flat string",
+ flatString.hashCode(), unicode.hashCode());
+ }
+
+ @Override
+ public void testCharsetToString() {
+ String sourceString = "I love unicode \u1234\u5678 characters";
+ ByteString sourceByteString = ByteString.copyFromUtf8(sourceString);
+ int copies = 250;
+
+ // By building the RopeByteString by concatenating, this is actually a fairly strenuous test.
+ StringBuilder builder = new StringBuilder(copies * sourceString.length());
+ ByteString unicode = ByteString.EMPTY;
+ for (int i = 0; i < copies; ++i) {
+ builder.append(sourceString);
+ unicode = RopeByteString.concatenate(unicode, sourceByteString);
+ }
+ String testString = builder.toString();
+
+ // Do the substring part
+ testString = testString.substring(2, testString.length() - 6);
+ unicode = unicode.substring(2, unicode.size() - 6);
+
+ assertEquals(classUnderTest + " from string must have the expected type",
+ classUnderTest, getActualClassName(unicode));
+ String roundTripString = unicode.toString(Internal.UTF_8);
+ assertEquals(classUnderTest + " unicode bytes must match",
+ testString, roundTripString);
+ ByteString flatString = ByteString.copyFromUtf8(testString);
+ assertEquals(classUnderTest + " string must equal the flat string", flatString, unicode);
+ assertEquals(classUnderTest + " string must must have same hashCode as the flat string",
+ flatString.hashCode(), unicode.hashCode());
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/RopeByteStringTest.java b/java/core/src/test/java/com/google/protobuf/RopeByteStringTest.java
new file mode 100644
index 00000000..4ec3a409
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/RopeByteStringTest.java
@@ -0,0 +1,189 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// 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 java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.Arrays;
+import java.util.Iterator;
+
+/**
+ * This class tests {@link RopeByteString} by inheriting the tests from
+ * {@link LiteralByteStringTest}. Only a couple of methods are overridden.
+ *
+ * <p>A full test of the result of {@link RopeByteString#substring(int, int)} is found in the
+ * separate class {@link RopeByteStringSubstringTest}.
+ *
+ * @author carlanton@google.com (Carl Haverl)
+ */
+public class RopeByteStringTest extends LiteralByteStringTest {
+
+ @Override
+ protected void setUp() throws Exception {
+ classUnderTest = "RopeByteString";
+ referenceBytes = ByteStringTest.getTestBytes(22341, 22337766L);
+ Iterator<ByteString> iter = ByteStringTest.makeConcretePieces(referenceBytes).iterator();
+ stringUnderTest = iter.next();
+ while (iter.hasNext()) {
+ stringUnderTest = stringUnderTest.concat(iter.next());
+ }
+ expectedHashCode = -1214197238;
+ }
+
+ @Override
+ public void testGetTreeDepth() {
+ assertEquals(classUnderTest + " must have the expected tree depth",
+ 4, stringUnderTest.getTreeDepth());
+ }
+
+ public void testBalance() {
+ int numberOfPieces = 10000;
+ int pieceSize = 64;
+ byte[] testBytes = ByteStringTest.getTestBytes(numberOfPieces * pieceSize, 113377L);
+
+ // Build up a big ByteString from smaller pieces to force a rebalance
+ ByteString concatenated = ByteString.EMPTY;
+ for (int i = 0; i < numberOfPieces; ++i) {
+ concatenated = concatenated.concat(ByteString.copyFrom(testBytes, i * pieceSize, pieceSize));
+ }
+
+ assertEquals(classUnderTest + " from string must have the expected type",
+ classUnderTest, getActualClassName(concatenated));
+ assertTrue(classUnderTest + " underlying bytes must match after balancing",
+ Arrays.equals(testBytes, concatenated.toByteArray()));
+ ByteString testString = ByteString.copyFrom(testBytes);
+ assertTrue(classUnderTest + " balanced string must equal flat string",
+ concatenated.equals(testString));
+ assertTrue(classUnderTest + " flat string must equal balanced string",
+ testString.equals(concatenated));
+ assertEquals(classUnderTest + " balanced string must have same hash code as flat string",
+ testString.hashCode(), concatenated.hashCode());
+ }
+
+ @Override
+ public void testToString() throws UnsupportedEncodingException {
+ String sourceString = "I love unicode \u1234\u5678 characters";
+ ByteString sourceByteString = ByteString.copyFromUtf8(sourceString);
+ int copies = 250;
+
+ // By building the RopeByteString by concatenating, this is actually a fairly strenuous test.
+ StringBuilder builder = new StringBuilder(copies * sourceString.length());
+ ByteString unicode = ByteString.EMPTY;
+ for (int i = 0; i < copies; ++i) {
+ builder.append(sourceString);
+ unicode = RopeByteString.concatenate(unicode, sourceByteString);
+ }
+ String testString = builder.toString();
+
+ assertEquals(classUnderTest + " from string must have the expected type",
+ classUnderTest, getActualClassName(unicode));
+ String roundTripString = unicode.toString(UTF_8);
+ assertEquals(classUnderTest + " unicode bytes must match",
+ testString, roundTripString);
+ ByteString flatString = ByteString.copyFromUtf8(testString);
+ assertEquals(classUnderTest + " string must equal the flat string", flatString, unicode);
+ assertEquals(classUnderTest + " string must must have same hashCode as the flat string",
+ flatString.hashCode(), unicode.hashCode());
+ }
+
+ @Override
+ public void testCharsetToString() {
+ String sourceString = "I love unicode \u1234\u5678 characters";
+ ByteString sourceByteString = ByteString.copyFromUtf8(sourceString);
+ int copies = 250;
+
+ // By building the RopeByteString by concatenating, this is actually a fairly strenuous test.
+ StringBuilder builder = new StringBuilder(copies * sourceString.length());
+ ByteString unicode = ByteString.EMPTY;
+ for (int i = 0; i < copies; ++i) {
+ builder.append(sourceString);
+ unicode = RopeByteString.concatenate(unicode, sourceByteString);
+ }
+ String testString = builder.toString();
+
+ assertEquals(classUnderTest + " from string must have the expected type",
+ classUnderTest, getActualClassName(unicode));
+ String roundTripString = unicode.toString(Internal.UTF_8);
+ assertEquals(classUnderTest + " unicode bytes must match",
+ testString, roundTripString);
+ ByteString flatString = ByteString.copyFromUtf8(testString);
+ assertEquals(classUnderTest + " string must equal the flat string", flatString, unicode);
+ assertEquals(classUnderTest + " string must must have same hashCode as the flat string",
+ flatString.hashCode(), unicode.hashCode());
+ }
+
+ @Override
+ public void testToString_returnsCanonicalEmptyString() {
+ RopeByteString ropeByteString =
+ RopeByteString.newInstanceForTest(ByteString.EMPTY, ByteString.EMPTY);
+ assertSame(classUnderTest + " must be the same string references",
+ ByteString.EMPTY.toString(Internal.UTF_8), ropeByteString.toString(Internal.UTF_8));
+ }
+
+ @Override
+ public void testToString_raisesException() {
+ try {
+ ByteString byteString =
+ RopeByteString.newInstanceForTest(ByteString.EMPTY, ByteString.EMPTY);
+ byteString.toString("invalid");
+ fail("Should have thrown an exception.");
+ } catch (UnsupportedEncodingException expected) {
+ // This is success
+ }
+
+ try {
+ ByteString byteString = RopeByteString.concatenate(ByteString.copyFromUtf8("foo"),
+ ByteString.copyFromUtf8("bar"));
+ byteString.toString("invalid");
+ fail("Should have thrown an exception.");
+ } catch (UnsupportedEncodingException expected) {
+ // This is success
+ }
+ }
+
+ @Override
+ public void testJavaSerialization() throws Exception {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(out);
+ oos.writeObject(stringUnderTest);
+ oos.close();
+ byte[] pickled = out.toByteArray();
+ InputStream in = new ByteArrayInputStream(pickled);
+ ObjectInputStream ois = new ObjectInputStream(in);
+ Object o = ois.readObject();
+ assertTrue("Didn't get a ByteString back", o instanceof ByteString);
+ assertEquals("Should get an equal ByteString back", stringUnderTest, o);
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/ServiceTest.java b/java/core/src/test/java/com/google/protobuf/ServiceTest.java
new file mode 100644
index 00000000..ff980d66
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/ServiceTest.java
@@ -0,0 +1,320 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// 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 com.google.protobuf.Descriptors.FileDescriptor;
+import com.google.protobuf.Descriptors.MethodDescriptor;
+import google.protobuf.no_generic_services_test.UnittestNoGenericServices;
+import protobuf_unittest.MessageWithNoOuter;
+import protobuf_unittest.ServiceWithNoOuter;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.TestService;
+import protobuf_unittest.UnittestProto.FooRequest;
+import protobuf_unittest.UnittestProto.FooResponse;
+import protobuf_unittest.UnittestProto.BarRequest;
+import protobuf_unittest.UnittestProto.BarResponse;
+
+import org.easymock.classextension.EasyMock;
+import org.easymock.classextension.IMocksControl;
+import org.easymock.IArgumentMatcher;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests services and stubs.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public class ServiceTest extends TestCase {
+ private IMocksControl control;
+ private RpcController mockController;
+
+ private final Descriptors.MethodDescriptor fooDescriptor =
+ TestService.getDescriptor().getMethods().get(0);
+ private final Descriptors.MethodDescriptor barDescriptor =
+ TestService.getDescriptor().getMethods().get(1);
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ control = EasyMock.createStrictControl();
+ mockController = control.createMock(RpcController.class);
+ }
+
+ // =================================================================
+
+ /** Tests Service.callMethod(). */
+ public void testCallMethod() throws Exception {
+ FooRequest fooRequest = FooRequest.newBuilder().build();
+ BarRequest barRequest = BarRequest.newBuilder().build();
+ MockCallback<Message> fooCallback = new MockCallback<Message>();
+ MockCallback<Message> barCallback = new MockCallback<Message>();
+ TestService mockService = control.createMock(TestService.class);
+
+ mockService.foo(EasyMock.same(mockController), EasyMock.same(fooRequest),
+ this.<FooResponse>wrapsCallback(fooCallback));
+ mockService.bar(EasyMock.same(mockController), EasyMock.same(barRequest),
+ this.<BarResponse>wrapsCallback(barCallback));
+ control.replay();
+
+ mockService.callMethod(fooDescriptor, mockController,
+ fooRequest, fooCallback);
+ mockService.callMethod(barDescriptor, mockController,
+ barRequest, barCallback);
+ control.verify();
+ }
+
+ /** Tests Service.get{Request,Response}Prototype(). */
+ public void testGetPrototype() throws Exception {
+ TestService mockService = control.createMock(TestService.class);
+
+ assertSame(mockService.getRequestPrototype(fooDescriptor),
+ FooRequest.getDefaultInstance());
+ assertSame(mockService.getResponsePrototype(fooDescriptor),
+ FooResponse.getDefaultInstance());
+ assertSame(mockService.getRequestPrototype(barDescriptor),
+ BarRequest.getDefaultInstance());
+ assertSame(mockService.getResponsePrototype(barDescriptor),
+ BarResponse.getDefaultInstance());
+ }
+
+ /** Tests generated stubs. */
+ public void testStub() throws Exception {
+ FooRequest fooRequest = FooRequest.newBuilder().build();
+ BarRequest barRequest = BarRequest.newBuilder().build();
+ MockCallback<FooResponse> fooCallback = new MockCallback<FooResponse>();
+ MockCallback<BarResponse> barCallback = new MockCallback<BarResponse>();
+ RpcChannel mockChannel = control.createMock(RpcChannel.class);
+ TestService stub = TestService.newStub(mockChannel);
+
+ mockChannel.callMethod(
+ EasyMock.same(fooDescriptor),
+ EasyMock.same(mockController),
+ EasyMock.same(fooRequest),
+ EasyMock.same(FooResponse.getDefaultInstance()),
+ this.<Message>wrapsCallback(fooCallback));
+ mockChannel.callMethod(
+ EasyMock.same(barDescriptor),
+ EasyMock.same(mockController),
+ EasyMock.same(barRequest),
+ EasyMock.same(BarResponse.getDefaultInstance()),
+ this.<Message>wrapsCallback(barCallback));
+ control.replay();
+
+ stub.foo(mockController, fooRequest, fooCallback);
+ stub.bar(mockController, barRequest, barCallback);
+ control.verify();
+ }
+
+ /** Tests generated blocking stubs. */
+ public void testBlockingStub() throws Exception {
+ FooRequest fooRequest = FooRequest.newBuilder().build();
+ BarRequest barRequest = BarRequest.newBuilder().build();
+ BlockingRpcChannel mockChannel =
+ control.createMock(BlockingRpcChannel.class);
+ TestService.BlockingInterface stub =
+ TestService.newBlockingStub(mockChannel);
+
+ FooResponse fooResponse = FooResponse.newBuilder().build();
+ BarResponse barResponse = BarResponse.newBuilder().build();
+
+ EasyMock.expect(mockChannel.callBlockingMethod(
+ EasyMock.same(fooDescriptor),
+ EasyMock.same(mockController),
+ EasyMock.same(fooRequest),
+ EasyMock.same(FooResponse.getDefaultInstance()))).andReturn(fooResponse);
+ EasyMock.expect(mockChannel.callBlockingMethod(
+ EasyMock.same(barDescriptor),
+ EasyMock.same(mockController),
+ EasyMock.same(barRequest),
+ EasyMock.same(BarResponse.getDefaultInstance()))).andReturn(barResponse);
+ control.replay();
+
+ assertSame(fooResponse, stub.foo(mockController, fooRequest));
+ assertSame(barResponse, stub.bar(mockController, barRequest));
+ control.verify();
+ }
+
+ public void testNewReflectiveService() {
+ ServiceWithNoOuter.Interface impl =
+ control.createMock(ServiceWithNoOuter.Interface.class);
+ RpcController controller = control.createMock(RpcController.class);
+ Service service = ServiceWithNoOuter.newReflectiveService(impl);
+
+ MethodDescriptor fooMethod =
+ ServiceWithNoOuter.getDescriptor().findMethodByName("Foo");
+ MessageWithNoOuter request = MessageWithNoOuter.getDefaultInstance();
+ RpcCallback<Message> callback = new RpcCallback<Message>() {
+ public void run(Message parameter) {
+ // No reason this should be run.
+ fail();
+ }
+ };
+ RpcCallback<TestAllTypes> specializedCallback =
+ RpcUtil.specializeCallback(callback);
+
+ impl.foo(EasyMock.same(controller), EasyMock.same(request),
+ EasyMock.same(specializedCallback));
+ EasyMock.expectLastCall();
+
+ control.replay();
+
+ service.callMethod(fooMethod, controller, request, callback);
+
+ control.verify();
+ }
+
+ public void testNewReflectiveBlockingService() throws ServiceException {
+ ServiceWithNoOuter.BlockingInterface impl =
+ control.createMock(ServiceWithNoOuter.BlockingInterface.class);
+ RpcController controller = control.createMock(RpcController.class);
+ BlockingService service =
+ ServiceWithNoOuter.newReflectiveBlockingService(impl);
+
+ MethodDescriptor fooMethod =
+ ServiceWithNoOuter.getDescriptor().findMethodByName("Foo");
+ MessageWithNoOuter request = MessageWithNoOuter.getDefaultInstance();
+
+ TestAllTypes expectedResponse = TestAllTypes.getDefaultInstance();
+ EasyMock.expect(impl.foo(EasyMock.same(controller), EasyMock.same(request)))
+ .andReturn(expectedResponse);
+
+ control.replay();
+
+ Message response =
+ service.callBlockingMethod(fooMethod, controller, request);
+ assertEquals(expectedResponse, response);
+
+ control.verify();
+ }
+
+ public void testNoGenericServices() throws Exception {
+ // Non-services should be usable.
+ UnittestNoGenericServices.TestMessage message =
+ UnittestNoGenericServices.TestMessage.newBuilder()
+ .setA(123)
+ .setExtension(UnittestNoGenericServices.testExtension, 456)
+ .build();
+ assertEquals(123, message.getA());
+ assertEquals(1, UnittestNoGenericServices.TestEnum.FOO.getNumber());
+
+ // Build a list of the class names nested in UnittestNoGenericServices.
+ String outerName = "google.protobuf.no_generic_services_test." +
+ "UnittestNoGenericServices";
+ Class<?> outerClass = Class.forName(outerName);
+
+ Set<String> innerClassNames = new HashSet<String>();
+ for (Class<?> innerClass : outerClass.getClasses()) {
+ String fullName = innerClass.getName();
+ // Figure out the unqualified name of the inner class.
+ // Note: Surprisingly, the full name of an inner class will be separated
+ // from the outer class name by a '$' rather than a '.'. This is not
+ // mentioned in the documentation for java.lang.Class. I don't want to
+ // make assumptions, so I'm just going to accept any character as the
+ // separator.
+ assertTrue(fullName.startsWith(outerName));
+
+ if (!Service.class.isAssignableFrom(innerClass) &&
+ !Message.class.isAssignableFrom(innerClass) &&
+ !ProtocolMessageEnum.class.isAssignableFrom(innerClass)) {
+ // Ignore any classes not generated by the base code generator.
+ continue;
+ }
+
+ innerClassNames.add(fullName.substring(outerName.length() + 1));
+ }
+
+ // No service class should have been generated.
+ assertTrue(innerClassNames.contains("TestMessage"));
+ assertTrue(innerClassNames.contains("TestEnum"));
+ assertFalse(innerClassNames.contains("TestService"));
+
+ // But descriptors are there.
+ FileDescriptor file = UnittestNoGenericServices.getDescriptor();
+ assertEquals(1, file.getServices().size());
+ assertEquals("TestService", file.getServices().get(0).getName());
+ assertEquals(1, file.getServices().get(0).getMethods().size());
+ assertEquals("Foo",
+ file.getServices().get(0).getMethods().get(0).getName());
+ }
+
+ // =================================================================
+
+ /**
+ * wrapsCallback() is an EasyMock argument predicate. wrapsCallback(c)
+ * matches a callback if calling that callback causes c to be called.
+ * In other words, c wraps the given callback.
+ */
+ private <Type extends Message> RpcCallback<Type> wrapsCallback(
+ MockCallback<?> callback) {
+ EasyMock.reportMatcher(new WrapsCallback(callback));
+ return null;
+ }
+
+ /** The parameter to wrapsCallback() must be a MockCallback. */
+ private static class MockCallback<Type extends Message>
+ implements RpcCallback<Type> {
+ private boolean called = false;
+
+ public boolean isCalled() { return called; }
+
+ public void reset() { called = false; }
+ public void run(Type message) { called = true; }
+ }
+
+ /** Implementation of the wrapsCallback() argument matcher. */
+ private static class WrapsCallback implements IArgumentMatcher {
+ private MockCallback<?> callback;
+
+ public WrapsCallback(MockCallback<?> callback) {
+ this.callback = callback;
+ }
+
+ @SuppressWarnings("unchecked")
+ public boolean matches(Object actual) {
+ if (!(actual instanceof RpcCallback)) {
+ return false;
+ }
+ RpcCallback actualCallback = (RpcCallback)actual;
+
+ callback.reset();
+ actualCallback.run(null);
+ return callback.isCalled();
+ }
+
+ public void appendTo(StringBuffer buffer) {
+ buffer.append("wrapsCallback(mockCallback)");
+ }
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/SingleFieldBuilderTest.java b/java/core/src/test/java/com/google/protobuf/SingleFieldBuilderTest.java
new file mode 100644
index 00000000..58b80007
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/SingleFieldBuilderTest.java
@@ -0,0 +1,155 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// 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.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.TestAllTypesOrBuilder;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests for {@link SingleFieldBuilder}. This tests basic functionality.
+ * More extensive testing is provided via other tests that exercise the
+ * builder.
+ *
+ * @author jonp@google.com (Jon Perlow)
+ */
+public class SingleFieldBuilderTest extends TestCase {
+
+ public void testBasicUseAndInvalidations() {
+ TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent();
+ SingleFieldBuilder<TestAllTypes, TestAllTypes.Builder,
+ TestAllTypesOrBuilder> builder =
+ new SingleFieldBuilder<TestAllTypes, TestAllTypes.Builder,
+ TestAllTypesOrBuilder>(
+ TestAllTypes.getDefaultInstance(),
+ mockParent,
+ false);
+ assertSame(TestAllTypes.getDefaultInstance(), builder.getMessage());
+ assertEquals(TestAllTypes.getDefaultInstance(),
+ builder.getBuilder().buildPartial());
+ assertEquals(0, mockParent.getInvalidationCount());
+
+ builder.getBuilder().setOptionalInt32(10);
+ assertEquals(0, mockParent.getInvalidationCount());
+ TestAllTypes message = builder.build();
+ assertEquals(10, message.getOptionalInt32());
+
+ // Test that we receive invalidations now that build has been called.
+ assertEquals(0, mockParent.getInvalidationCount());
+ builder.getBuilder().setOptionalInt32(20);
+ assertEquals(1, mockParent.getInvalidationCount());
+
+ // Test that we don't keep getting invalidations on every change
+ builder.getBuilder().setOptionalInt32(30);
+ assertEquals(1, mockParent.getInvalidationCount());
+
+ }
+
+ public void testSetMessage() {
+ TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent();
+ SingleFieldBuilder<TestAllTypes, TestAllTypes.Builder,
+ TestAllTypesOrBuilder> builder =
+ new SingleFieldBuilder<TestAllTypes, TestAllTypes.Builder,
+ TestAllTypesOrBuilder>(
+ TestAllTypes.getDefaultInstance(),
+ mockParent,
+ false);
+ builder.setMessage(TestAllTypes.newBuilder().setOptionalInt32(0).build());
+ assertEquals(0, builder.getMessage().getOptionalInt32());
+
+ // Update message using the builder
+ builder.getBuilder().setOptionalInt32(1);
+ assertEquals(0, mockParent.getInvalidationCount());
+ assertEquals(1, builder.getBuilder().getOptionalInt32());
+ assertEquals(1, builder.getMessage().getOptionalInt32());
+ builder.build();
+ builder.getBuilder().setOptionalInt32(2);
+ assertEquals(2, builder.getBuilder().getOptionalInt32());
+ assertEquals(2, builder.getMessage().getOptionalInt32());
+
+ // Make sure message stays cached
+ assertSame(builder.getMessage(), builder.getMessage());
+ }
+
+ public void testClear() {
+ TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent();
+ SingleFieldBuilder<TestAllTypes, TestAllTypes.Builder,
+ TestAllTypesOrBuilder> builder =
+ new SingleFieldBuilder<TestAllTypes, TestAllTypes.Builder,
+ TestAllTypesOrBuilder>(
+ TestAllTypes.getDefaultInstance(),
+ mockParent,
+ false);
+ builder.setMessage(TestAllTypes.newBuilder().setOptionalInt32(0).build());
+ assertNotSame(TestAllTypes.getDefaultInstance(), builder.getMessage());
+ builder.clear();
+ assertSame(TestAllTypes.getDefaultInstance(), builder.getMessage());
+
+ builder.getBuilder().setOptionalInt32(1);
+ assertNotSame(TestAllTypes.getDefaultInstance(), builder.getMessage());
+ builder.clear();
+ assertSame(TestAllTypes.getDefaultInstance(), builder.getMessage());
+ }
+
+ public void testMerge() {
+ TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent();
+ SingleFieldBuilder<TestAllTypes, TestAllTypes.Builder,
+ TestAllTypesOrBuilder> builder =
+ new SingleFieldBuilder<TestAllTypes, TestAllTypes.Builder,
+ TestAllTypesOrBuilder>(
+ TestAllTypes.getDefaultInstance(),
+ mockParent,
+ false);
+
+ // Merge into default field.
+ builder.mergeFrom(TestAllTypes.getDefaultInstance());
+ assertSame(TestAllTypes.getDefaultInstance(), builder.getMessage());
+
+ // Merge into non-default field on existing builder.
+ builder.getBuilder().setOptionalInt32(2);
+ builder.mergeFrom(TestAllTypes.newBuilder()
+ .setOptionalDouble(4.0)
+ .buildPartial());
+ assertEquals(2, builder.getMessage().getOptionalInt32());
+ assertEquals(4.0, builder.getMessage().getOptionalDouble());
+
+ // Merge into non-default field on existing message
+ builder.setMessage(TestAllTypes.newBuilder()
+ .setOptionalInt32(10)
+ .buildPartial());
+ builder.mergeFrom(TestAllTypes.newBuilder()
+ .setOptionalDouble(5.0)
+ .buildPartial());
+ assertEquals(10, builder.getMessage().getOptionalInt32());
+ assertEquals(5.0, builder.getMessage().getOptionalDouble());
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/SmallSortedMapTest.java b/java/core/src/test/java/com/google/protobuf/SmallSortedMapTest.java
new file mode 100644
index 00000000..366086d3
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/SmallSortedMapTest.java
@@ -0,0 +1,420 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// 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 junit.framework.TestCase;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+
+/**
+ * @author darick@google.com Darick Tong
+ */
+public class SmallSortedMapTest extends TestCase {
+ // java.util.AbstractMap.SimpleEntry is private in JDK 1.5. We re-implement it
+ // here for JDK 1.5 users.
+ private static class SimpleEntry<K, V> implements Map.Entry<K, V> {
+ private final K key;
+ private V value;
+
+ SimpleEntry(K key, V value) {
+ this.key = key;
+ this.value = value;
+ }
+
+ public K getKey() {
+ return key;
+ }
+
+ public V getValue() {
+ return value;
+ }
+
+ public V setValue(V value) {
+ V oldValue = this.value;
+ this.value = value;
+ return oldValue;
+ }
+
+ private static boolean eq(Object o1, Object o2) {
+ return o1 == null ? o2 == null : o1.equals(o2);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof Map.Entry))
+ return false;
+ Map.Entry e = (Map.Entry) o;
+ return eq(key, e.getKey()) && eq(value, e.getValue());
+ }
+
+ @Override
+ public int hashCode() {
+ return ((key == null) ? 0 : key.hashCode()) ^
+ ((value == null) ? 0 : value.hashCode());
+ }
+ }
+
+ public void testPutAndGetArrayEntriesOnly() {
+ runPutAndGetTest(3);
+ }
+
+ public void testPutAndGetOverflowEntries() {
+ runPutAndGetTest(6);
+ }
+
+ private void runPutAndGetTest(int numElements) {
+ // Test with even and odd arraySize
+ SmallSortedMap<Integer, Integer> map1 =
+ SmallSortedMap.newInstanceForTest(3);
+ SmallSortedMap<Integer, Integer> map2 =
+ SmallSortedMap.newInstanceForTest(4);
+ SmallSortedMap<Integer, Integer> map3 =
+ SmallSortedMap.newInstanceForTest(3);
+ SmallSortedMap<Integer, Integer> map4 =
+ SmallSortedMap.newInstanceForTest(4);
+
+ // Test with puts in ascending order.
+ for (int i = 0; i < numElements; i++) {
+ assertNull(map1.put(i, i + 1));
+ assertNull(map2.put(i, i + 1));
+ }
+ // Test with puts in descending order.
+ for (int i = numElements - 1; i >= 0; i--) {
+ assertNull(map3.put(i, i + 1));
+ assertNull(map4.put(i, i + 1));
+ }
+
+ assertEquals(Math.min(3, numElements), map1.getNumArrayEntries());
+ assertEquals(Math.min(4, numElements), map2.getNumArrayEntries());
+ assertEquals(Math.min(3, numElements), map3.getNumArrayEntries());
+ assertEquals(Math.min(4, numElements), map4.getNumArrayEntries());
+
+ List<SmallSortedMap<Integer, Integer>> allMaps =
+ new ArrayList<SmallSortedMap<Integer, Integer>>();
+ allMaps.add(map1);
+ allMaps.add(map2);
+ allMaps.add(map3);
+ allMaps.add(map4);
+
+ for (SmallSortedMap<Integer, Integer> map : allMaps) {
+ assertEquals(numElements, map.size());
+ for (int i = 0; i < numElements; i++) {
+ assertEquals(new Integer(i + 1), map.get(i));
+ }
+ }
+
+ assertEquals(map1, map2);
+ assertEquals(map2, map3);
+ assertEquals(map3, map4);
+ }
+
+ public void testReplacingPut() {
+ SmallSortedMap<Integer, Integer> map = SmallSortedMap.newInstanceForTest(3);
+ for (int i = 0; i < 6; i++) {
+ assertNull(map.put(i, i + 1));
+ assertNull(map.remove(i + 1));
+ }
+ for (int i = 0; i < 6; i++) {
+ assertEquals(new Integer(i + 1), map.put(i, i + 2));
+ }
+ }
+
+ public void testRemove() {
+ SmallSortedMap<Integer, Integer> map = SmallSortedMap.newInstanceForTest(3);
+ for (int i = 0; i < 6; i++) {
+ assertNull(map.put(i, i + 1));
+ assertNull(map.remove(i + 1));
+ }
+
+ assertEquals(3, map.getNumArrayEntries());
+ assertEquals(3, map.getNumOverflowEntries());
+ assertEquals(6, map.size());
+ assertEquals(makeSortedKeySet(0, 1, 2, 3, 4, 5), map.keySet());
+
+ assertEquals(new Integer(2), map.remove(1));
+ assertEquals(3, map.getNumArrayEntries());
+ assertEquals(2, map.getNumOverflowEntries());
+ assertEquals(5, map.size());
+ assertEquals(makeSortedKeySet(0, 2, 3, 4, 5), map.keySet());
+
+ assertEquals(new Integer(5), map.remove(4));
+ assertEquals(3, map.getNumArrayEntries());
+ assertEquals(1, map.getNumOverflowEntries());
+ assertEquals(4, map.size());
+ assertEquals(makeSortedKeySet(0, 2, 3, 5), map.keySet());
+
+ assertEquals(new Integer(4), map.remove(3));
+ assertEquals(3, map.getNumArrayEntries());
+ assertEquals(0, map.getNumOverflowEntries());
+ assertEquals(3, map.size());
+ assertEquals(makeSortedKeySet(0, 2, 5), map.keySet());
+
+ assertNull(map.remove(3));
+ assertEquals(3, map.getNumArrayEntries());
+ assertEquals(0, map.getNumOverflowEntries());
+ assertEquals(3, map.size());
+
+ assertEquals(new Integer(1), map.remove(0));
+ assertEquals(2, map.getNumArrayEntries());
+ assertEquals(0, map.getNumOverflowEntries());
+ assertEquals(2, map.size());
+ }
+
+ public void testClear() {
+ SmallSortedMap<Integer, Integer> map = SmallSortedMap.newInstanceForTest(3);
+ for (int i = 0; i < 6; i++) {
+ assertNull(map.put(i, i + 1));
+ }
+ map.clear();
+ assertEquals(0, map.getNumArrayEntries());
+ assertEquals(0, map.getNumOverflowEntries());
+ assertEquals(0, map.size());
+ }
+
+ public void testGetArrayEntryAndOverflowEntries() {
+ SmallSortedMap<Integer, Integer> map = SmallSortedMap.newInstanceForTest(3);
+ for (int i = 0; i < 6; i++) {
+ assertNull(map.put(i, i + 1));
+ }
+ assertEquals(3, map.getNumArrayEntries());
+ for (int i = 0; i < 3; i++) {
+ Map.Entry<Integer, Integer> entry = map.getArrayEntryAt(i);
+ assertEquals(new Integer(i), entry.getKey());
+ assertEquals(new Integer(i + 1), entry.getValue());
+ }
+ Iterator<Map.Entry<Integer, Integer>> it =
+ map.getOverflowEntries().iterator();
+ for (int i = 3; i < 6; i++) {
+ assertTrue(it.hasNext());
+ Map.Entry<Integer, Integer> entry = it.next();
+ assertEquals(new Integer(i), entry.getKey());
+ assertEquals(new Integer(i + 1), entry.getValue());
+ }
+ assertFalse(it.hasNext());
+ }
+
+ public void testEntrySetContains() {
+ SmallSortedMap<Integer, Integer> map = SmallSortedMap.newInstanceForTest(3);
+ for (int i = 0; i < 6; i++) {
+ assertNull(map.put(i, i + 1));
+ }
+ Set<Map.Entry<Integer, Integer>> entrySet = map.entrySet();
+ for (int i = 0; i < 6; i++) {
+ assertTrue(
+ entrySet.contains(new SimpleEntry<Integer, Integer>(i, i + 1)));
+ assertFalse(
+ entrySet.contains(new SimpleEntry<Integer, Integer>(i, i)));
+ }
+ }
+
+ public void testEntrySetAdd() {
+ SmallSortedMap<Integer, Integer> map = SmallSortedMap.newInstanceForTest(3);
+ Set<Map.Entry<Integer, Integer>> entrySet = map.entrySet();
+ for (int i = 0; i < 6; i++) {
+ Map.Entry<Integer, Integer> entry =
+ new SimpleEntry<Integer, Integer>(i, i + 1);
+ assertTrue(entrySet.add(entry));
+ assertFalse(entrySet.add(entry));
+ }
+ for (int i = 0; i < 6; i++) {
+ assertEquals(new Integer(i + 1), map.get(i));
+ }
+ assertEquals(3, map.getNumArrayEntries());
+ assertEquals(3, map.getNumOverflowEntries());
+ assertEquals(6, map.size());
+ }
+
+ public void testEntrySetRemove() {
+ SmallSortedMap<Integer, Integer> map = SmallSortedMap.newInstanceForTest(3);
+ Set<Map.Entry<Integer, Integer>> entrySet = map.entrySet();
+ for (int i = 0; i < 6; i++) {
+ assertNull(map.put(i, i + 1));
+ }
+ for (int i = 0; i < 6; i++) {
+ Map.Entry<Integer, Integer> entry =
+ new SimpleEntry<Integer, Integer>(i, i + 1);
+ assertTrue(entrySet.remove(entry));
+ assertFalse(entrySet.remove(entry));
+ }
+ assertTrue(map.isEmpty());
+ assertEquals(0, map.getNumArrayEntries());
+ assertEquals(0, map.getNumOverflowEntries());
+ assertEquals(0, map.size());
+ }
+
+ public void testEntrySetClear() {
+ SmallSortedMap<Integer, Integer> map = SmallSortedMap.newInstanceForTest(3);
+ for (int i = 0; i < 6; i++) {
+ assertNull(map.put(i, i + 1));
+ }
+ map.entrySet().clear();
+ assertTrue(map.isEmpty());
+ assertEquals(0, map.getNumArrayEntries());
+ assertEquals(0, map.getNumOverflowEntries());
+ assertEquals(0, map.size());
+ }
+
+ public void testEntrySetIteratorNext() {
+ SmallSortedMap<Integer, Integer> map = SmallSortedMap.newInstanceForTest(3);
+ for (int i = 0; i < 6; i++) {
+ assertNull(map.put(i, i + 1));
+ }
+ Iterator<Map.Entry<Integer, Integer>> it = map.entrySet().iterator();
+ for (int i = 0; i < 6; i++) {
+ assertTrue(it.hasNext());
+ Map.Entry<Integer, Integer> entry = it.next();
+ assertEquals(new Integer(i), entry.getKey());
+ assertEquals(new Integer(i + 1), entry.getValue());
+ }
+ assertFalse(it.hasNext());
+ }
+
+ public void testEntrySetIteratorRemove() {
+ SmallSortedMap<Integer, Integer> map = SmallSortedMap.newInstanceForTest(3);
+ for (int i = 0; i < 6; i++) {
+ assertNull(map.put(i, i + 1));
+ }
+ Iterator<Map.Entry<Integer, Integer>> it = map.entrySet().iterator();
+ for (int i = 0; i < 6; i++) {
+ assertTrue(map.containsKey(i));
+ it.next();
+ it.remove();
+ assertFalse(map.containsKey(i));
+ assertEquals(6 - i - 1, map.size());
+ }
+ }
+
+ public void testMapEntryModification() {
+ SmallSortedMap<Integer, Integer> map = SmallSortedMap.newInstanceForTest(3);
+ for (int i = 0; i < 6; i++) {
+ assertNull(map.put(i, i + 1));
+ }
+ Iterator<Map.Entry<Integer, Integer>> it = map.entrySet().iterator();
+ for (int i = 0; i < 6; i++) {
+ Map.Entry<Integer, Integer> entry = it.next();
+ entry.setValue(i + 23);
+ }
+ for (int i = 0; i < 6; i++) {
+ assertEquals(new Integer(i + 23), map.get(i));
+ }
+ }
+
+ public void testMakeImmutable() {
+ SmallSortedMap<Integer, Integer> map = SmallSortedMap.newInstanceForTest(3);
+ for (int i = 0; i < 6; i++) {
+ assertNull(map.put(i, i + 1));
+ }
+ map.makeImmutable();
+ assertEquals(new Integer(1), map.get(0));
+ assertEquals(6, map.size());
+
+ try {
+ map.put(23, 23);
+ fail("Expected UnsupportedOperationException");
+ } catch (UnsupportedOperationException expected) {
+ }
+
+ Map<Integer, Integer> other = new HashMap<Integer, Integer>();
+ other.put(23, 23);
+ try {
+ map.putAll(other);
+ fail("Expected UnsupportedOperationException");
+ } catch (UnsupportedOperationException expected) {
+ }
+
+ try {
+ map.remove(0);
+ fail("Expected UnsupportedOperationException");
+ } catch (UnsupportedOperationException expected) {
+ }
+
+ try {
+ map.clear();
+ fail("Expected UnsupportedOperationException");
+ } catch (UnsupportedOperationException expected) {
+ }
+
+ Set<Map.Entry<Integer, Integer>> entrySet = map.entrySet();
+ try {
+ entrySet.clear();
+ fail("Expected UnsupportedOperationException");
+ } catch (UnsupportedOperationException expected) {
+ }
+
+ Iterator<Map.Entry<Integer, Integer>> it = entrySet.iterator();
+ while (it.hasNext()) {
+ Map.Entry<Integer, Integer> entry = it.next();
+ try {
+ entry.setValue(0);
+ fail("Expected UnsupportedOperationException");
+ } catch (UnsupportedOperationException expected) {
+ }
+ try {
+ it.remove();
+ fail("Expected UnsupportedOperationException");
+ } catch (UnsupportedOperationException expected) {
+ }
+ }
+
+ Set<Integer> keySet = map.keySet();
+ try {
+ keySet.clear();
+ fail("Expected UnsupportedOperationException");
+ } catch (UnsupportedOperationException expected) {
+ }
+
+ Iterator<Integer> keys = keySet.iterator();
+ while (keys.hasNext()) {
+ Integer key = keys.next();
+ try {
+ keySet.remove(key);
+ fail("Expected UnsupportedOperationException");
+ } catch (UnsupportedOperationException expected) {
+ }
+ try {
+ keys.remove();
+ fail("Expected UnsupportedOperationException");
+ } catch (UnsupportedOperationException expected) {
+ }
+ }
+ }
+
+ private Set<Integer> makeSortedKeySet(Integer... keys) {
+ return new TreeSet<Integer>(Arrays.<Integer>asList(keys));
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/TestBadIdentifiers.java b/java/core/src/test/java/com/google/protobuf/TestBadIdentifiers.java
new file mode 100644
index 00000000..2c60fe0e
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/TestBadIdentifiers.java
@@ -0,0 +1,96 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// 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 junit.framework.TestCase;
+
+/**
+ * Tests that proto2 api generation doesn't cause compile errors when
+ * compiling protocol buffers that have names that would otherwise conflict
+ * if not fully qualified (like @Deprecated and @Override).
+ *
+ * @author jonp@google.com (Jon Perlow)
+ */
+public class TestBadIdentifiers extends TestCase {
+
+ public void testCompilation() {
+ // If this compiles, it means the generation was correct.
+ TestBadIdentifiersProto.Deprecated.newBuilder();
+ TestBadIdentifiersProto.Override.newBuilder();
+ }
+
+ public void testGetDescriptor() {
+ Descriptors.FileDescriptor fileDescriptor =
+ TestBadIdentifiersProto.getDescriptor();
+ String descriptorField = TestBadIdentifiersProto.Descriptor
+ .getDefaultInstance().getDescriptor();
+ Descriptors.Descriptor protoDescriptor = TestBadIdentifiersProto.Descriptor
+ .getDefaultInstance().getDescriptorForType();
+ String nestedDescriptorField = TestBadIdentifiersProto.Descriptor
+ .NestedDescriptor.getDefaultInstance().getDescriptor();
+ Descriptors.Descriptor nestedProtoDescriptor = TestBadIdentifiersProto
+ .Descriptor.NestedDescriptor.getDefaultInstance()
+ .getDescriptorForType();
+ }
+
+ public void testConflictingFieldNames() throws Exception {
+ TestBadIdentifiersProto.TestConflictingFieldNames message =
+ TestBadIdentifiersProto.TestConflictingFieldNames.getDefaultInstance();
+ // Make sure generated accessors are properly named.
+ assertEquals(0, message.getInt32Field1Count());
+ assertEquals(0, message.getEnumField2Count());
+ assertEquals(0, message.getStringField3Count());
+ assertEquals(0, message.getBytesField4Count());
+ assertEquals(0, message.getMessageField5Count());
+
+ assertEquals(0, message.getInt32FieldCount11());
+ assertEquals(0, message.getEnumFieldCount12().getNumber());
+ assertEquals("", message.getStringFieldCount13());
+ assertEquals(ByteString.EMPTY, message.getBytesFieldCount14());
+ assertEquals(0, message.getMessageFieldCount15().getSerializedSize());
+
+ assertEquals(0, message.getInt32Field21Count());
+ assertEquals(0, message.getEnumField22Count());
+ assertEquals(0, message.getStringField23Count());
+ assertEquals(0, message.getBytesField24Count());
+ assertEquals(0, message.getMessageField25Count());
+
+ assertEquals(0, message.getInt32Field1List().size());
+ assertEquals(0, message.getInt32FieldList31());
+
+ assertEquals(0, message.getInt64FieldCount());
+ assertEquals(0L, message.getExtension(
+ TestBadIdentifiersProto.TestConflictingFieldNames.int64FieldCount).longValue());
+ assertEquals(0L, message.getExtension(
+ TestBadIdentifiersProto.TestConflictingFieldNames.int64FieldList).longValue());
+
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/TestUtil.java b/java/core/src/test/java/com/google/protobuf/TestUtil.java
new file mode 100644
index 00000000..01acb884
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/TestUtil.java
@@ -0,0 +1,4275 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// 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.UnittestProto;
+import com.google.protobuf.UnittestLite;
+
+// The static imports are to avoid 100+ char lines. The following is roughly equivalent to
+// import static protobuf_unittest.UnittestProto.*;
+import static protobuf_unittest.UnittestProto.defaultInt32Extension;
+import static protobuf_unittest.UnittestProto.defaultInt64Extension;
+import static protobuf_unittest.UnittestProto.defaultUint32Extension;
+import static protobuf_unittest.UnittestProto.defaultUint64Extension;
+import static protobuf_unittest.UnittestProto.defaultSint32Extension;
+import static protobuf_unittest.UnittestProto.defaultSint64Extension;
+import static protobuf_unittest.UnittestProto.defaultFixed32Extension;
+import static protobuf_unittest.UnittestProto.defaultFixed64Extension;
+import static protobuf_unittest.UnittestProto.defaultSfixed32Extension;
+import static protobuf_unittest.UnittestProto.defaultSfixed64Extension;
+import static protobuf_unittest.UnittestProto.defaultFloatExtension;
+import static protobuf_unittest.UnittestProto.defaultDoubleExtension;
+import static protobuf_unittest.UnittestProto.defaultBoolExtension;
+import static protobuf_unittest.UnittestProto.defaultStringExtension;
+import static protobuf_unittest.UnittestProto.defaultBytesExtension;
+import static protobuf_unittest.UnittestProto.defaultNestedEnumExtension;
+import static protobuf_unittest.UnittestProto.defaultForeignEnumExtension;
+import static protobuf_unittest.UnittestProto.defaultImportEnumExtension;
+import static protobuf_unittest.UnittestProto.defaultStringPieceExtension;
+import static protobuf_unittest.UnittestProto.defaultCordExtension;
+
+import static protobuf_unittest.UnittestProto.oneofUint32Extension;
+import static protobuf_unittest.UnittestProto.oneofNestedMessageExtension;
+import static protobuf_unittest.UnittestProto.oneofStringExtension;
+import static protobuf_unittest.UnittestProto.oneofBytesExtension;
+
+import static protobuf_unittest.UnittestProto.optionalInt32Extension;
+import static protobuf_unittest.UnittestProto.optionalInt64Extension;
+import static protobuf_unittest.UnittestProto.optionalUint32Extension;
+import static protobuf_unittest.UnittestProto.optionalUint64Extension;
+import static protobuf_unittest.UnittestProto.optionalSint32Extension;
+import static protobuf_unittest.UnittestProto.optionalSint64Extension;
+import static protobuf_unittest.UnittestProto.optionalFixed32Extension;
+import static protobuf_unittest.UnittestProto.optionalFixed64Extension;
+import static protobuf_unittest.UnittestProto.optionalSfixed32Extension;
+import static protobuf_unittest.UnittestProto.optionalSfixed64Extension;
+import static protobuf_unittest.UnittestProto.optionalFloatExtension;
+import static protobuf_unittest.UnittestProto.optionalDoubleExtension;
+import static protobuf_unittest.UnittestProto.optionalBoolExtension;
+import static protobuf_unittest.UnittestProto.optionalStringExtension;
+import static protobuf_unittest.UnittestProto.optionalBytesExtension;
+import static protobuf_unittest.UnittestProto.optionalGroupExtension;
+import static protobuf_unittest.UnittestProto.optionalCordExtension;
+import static protobuf_unittest.UnittestProto.optionalForeignEnumExtension;
+import static protobuf_unittest.UnittestProto.optionalForeignMessageExtension;
+import static protobuf_unittest.UnittestProto.optionalImportEnumExtension;
+import static protobuf_unittest.UnittestProto.optionalImportMessageExtension;
+import static protobuf_unittest.UnittestProto.optionalNestedEnumExtension;
+import static protobuf_unittest.UnittestProto.optionalNestedMessageExtension;
+import static protobuf_unittest.UnittestProto.optionalPublicImportMessageExtension;
+import static protobuf_unittest.UnittestProto.optionalLazyMessageExtension;
+import static protobuf_unittest.UnittestProto.optionalStringPieceExtension;
+
+import static protobuf_unittest.UnittestProto.repeatedInt32Extension;
+import static protobuf_unittest.UnittestProto.repeatedInt64Extension;
+import static protobuf_unittest.UnittestProto.repeatedUint32Extension;
+import static protobuf_unittest.UnittestProto.repeatedUint64Extension;
+import static protobuf_unittest.UnittestProto.repeatedSint32Extension;
+import static protobuf_unittest.UnittestProto.repeatedSint64Extension;
+import static protobuf_unittest.UnittestProto.repeatedFixed32Extension;
+import static protobuf_unittest.UnittestProto.repeatedFixed64Extension;
+import static protobuf_unittest.UnittestProto.repeatedSfixed32Extension;
+import static protobuf_unittest.UnittestProto.repeatedSfixed64Extension;
+import static protobuf_unittest.UnittestProto.repeatedFloatExtension;
+import static protobuf_unittest.UnittestProto.repeatedDoubleExtension;
+import static protobuf_unittest.UnittestProto.repeatedBoolExtension;
+import static protobuf_unittest.UnittestProto.repeatedStringExtension;
+import static protobuf_unittest.UnittestProto.repeatedBytesExtension;
+import static protobuf_unittest.UnittestProto.repeatedGroupExtension;
+import static protobuf_unittest.UnittestProto.repeatedNestedMessageExtension;
+import static protobuf_unittest.UnittestProto.repeatedForeignMessageExtension;
+import static protobuf_unittest.UnittestProto.repeatedImportMessageExtension;
+import static protobuf_unittest.UnittestProto.repeatedLazyMessageExtension;
+import static protobuf_unittest.UnittestProto.repeatedNestedEnumExtension;
+import static protobuf_unittest.UnittestProto.repeatedForeignEnumExtension;
+import static protobuf_unittest.UnittestProto.repeatedImportEnumExtension;
+import static protobuf_unittest.UnittestProto.repeatedStringPieceExtension;
+import static protobuf_unittest.UnittestProto.repeatedCordExtension;
+
+import static protobuf_unittest.UnittestProto.OptionalGroup_extension;
+import static protobuf_unittest.UnittestProto.RepeatedGroup_extension;
+
+import static protobuf_unittest.UnittestProto.packedInt32Extension;
+import static protobuf_unittest.UnittestProto.packedInt64Extension;
+import static protobuf_unittest.UnittestProto.packedUint32Extension;
+import static protobuf_unittest.UnittestProto.packedUint64Extension;
+import static protobuf_unittest.UnittestProto.packedSint32Extension;
+import static protobuf_unittest.UnittestProto.packedSint64Extension;
+import static protobuf_unittest.UnittestProto.packedFixed32Extension;
+import static protobuf_unittest.UnittestProto.packedFixed64Extension;
+import static protobuf_unittest.UnittestProto.packedSfixed32Extension;
+import static protobuf_unittest.UnittestProto.packedSfixed64Extension;
+import static protobuf_unittest.UnittestProto.packedFloatExtension;
+import static protobuf_unittest.UnittestProto.packedDoubleExtension;
+import static protobuf_unittest.UnittestProto.packedBoolExtension;
+import static protobuf_unittest.UnittestProto.packedEnumExtension;
+
+import static com.google.protobuf.UnittestLite.defaultInt32ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultInt64ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultUint32ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultUint64ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultSint32ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultSint64ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultFixed32ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultFixed64ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultSfixed32ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultSfixed64ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultFloatExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultDoubleExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultBoolExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultStringExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultBytesExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultNestedEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultForeignEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultImportEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultStringPieceExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultCordExtensionLite;
+
+import static com.google.protobuf.UnittestLite.oneofUint32ExtensionLite;
+import static com.google.protobuf.UnittestLite.oneofNestedMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.oneofStringExtensionLite;
+import static com.google.protobuf.UnittestLite.oneofBytesExtensionLite;
+
+import static com.google.protobuf.UnittestLite.optionalInt32ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalInt64ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalUint32ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalUint64ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalSint32ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalSint64ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalFixed32ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalFixed64ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalSfixed32ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalSfixed64ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalFloatExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalDoubleExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalBoolExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalStringExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalBytesExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalGroupExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalNestedMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalForeignEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalForeignMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalImportEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalImportMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalNestedEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalPublicImportMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalLazyMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalStringPieceExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalCordExtensionLite;
+
+import static com.google.protobuf.UnittestLite.repeatedInt32ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedInt64ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedUint32ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedUint64ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedSint32ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedSint64ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedFixed32ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedFixed64ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedSfixed32ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedSfixed64ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedFloatExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedDoubleExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedBoolExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedStringExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedBytesExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedGroupExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedNestedMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedForeignMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedImportMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedLazyMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedNestedEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedForeignEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedImportEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedStringPieceExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedCordExtensionLite;
+
+import static com.google.protobuf.UnittestLite.OptionalGroup_extension_lite;
+import static com.google.protobuf.UnittestLite.RepeatedGroup_extension_lite;
+
+import static com.google.protobuf.UnittestLite.packedInt32ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedInt64ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedUint32ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedUint64ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedSint32ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedSint64ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedFixed32ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedFixed64ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedSfixed32ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedSfixed64ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedFloatExtensionLite;
+import static com.google.protobuf.UnittestLite.packedDoubleExtensionLite;
+import static com.google.protobuf.UnittestLite.packedBoolExtensionLite;
+import static com.google.protobuf.UnittestLite.packedEnumExtensionLite;
+
+import protobuf_unittest.UnittestProto.TestAllExtensions;
+import protobuf_unittest.UnittestProto.TestAllExtensionsOrBuilder;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.TestAllTypesOrBuilder;
+import protobuf_unittest.UnittestProto.TestOneof2;
+import protobuf_unittest.UnittestProto.TestPackedExtensions;
+import protobuf_unittest.UnittestProto.TestPackedTypes;
+import protobuf_unittest.UnittestProto.TestUnpackedTypes;
+import protobuf_unittest.UnittestProto.ForeignMessage;
+import protobuf_unittest.UnittestProto.ForeignEnum;
+import com.google.protobuf.test.UnittestImport.ImportEnum;
+import com.google.protobuf.test.UnittestImport.ImportMessage;
+import com.google.protobuf.test.UnittestImportPublic.PublicImportMessage;
+
+import com.google.protobuf.UnittestLite.TestAllTypesLite;
+import com.google.protobuf.UnittestLite.TestAllExtensionsLite;
+import com.google.protobuf.UnittestLite.TestAllExtensionsLiteOrBuilder;
+import com.google.protobuf.UnittestLite.TestPackedExtensionsLite;
+import com.google.protobuf.UnittestLite.ForeignMessageLite;
+import com.google.protobuf.UnittestLite.ForeignEnumLite;
+import com.google.protobuf.UnittestImportLite.ImportEnumLite;
+import com.google.protobuf.UnittestImportLite.ImportMessageLite;
+import com.google.protobuf.UnittestImportPublicLite.PublicImportMessageLite;
+
+import junit.framework.Assert;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+
+/**
+ * Contains methods for setting all fields of {@code TestAllTypes} to
+ * some values as well as checking that all the fields are set to those values.
+ * These are useful for testing various protocol message features, e.g.
+ * set all fields of a message, serialize it, parse it, and check that all
+ * fields are set.
+ *
+ * <p>This code is not to be used outside of {@code com.google.protobuf} and
+ * subpackages.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public final class TestUtil {
+ private TestUtil() {}
+
+ /** Helper to convert a String to ByteString. */
+ static ByteString toBytes(String str) {
+ return ByteString.copyFrom(str.getBytes(Internal.UTF_8));
+ }
+
+ /**
+ * Get a {@code TestAllTypes} with all fields set as they would be by
+ * {@link #setAllFields(TestAllTypes.Builder)}.
+ */
+ public static TestAllTypes getAllSet() {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ setAllFields(builder);
+ return builder.build();
+ }
+
+ /**
+ * Get a {@code TestAllTypes.Builder} with all fields set as they would be by
+ * {@link #setAllFields(TestAllTypes.Builder)}.
+ */
+ public static TestAllTypes.Builder getAllSetBuilder() {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ setAllFields(builder);
+ return builder;
+ }
+
+ /**
+ * Get a {@code TestAllTypesLite.Builder} with all fields set as they would be by
+ * {@link #setAllFields(TestAllTypesLite.Builder)}.
+ */
+ public static TestAllTypesLite.Builder getAllLiteSetBuilder() {
+ TestAllTypesLite.Builder builder = TestAllTypesLite.newBuilder();
+ setAllFields(builder);
+ return builder;
+ }
+
+ /**
+ * Get a {@code TestAllExtensions} with all fields set as they would be by
+ * {@link #setAllExtensions(TestAllExtensions.Builder)}.
+ */
+ public static TestAllExtensions getAllExtensionsSet() {
+ TestAllExtensions.Builder builder = TestAllExtensions.newBuilder();
+ setAllExtensions(builder);
+ return builder.build();
+ }
+
+ public static TestAllExtensionsLite getAllLiteExtensionsSet() {
+ TestAllExtensionsLite.Builder builder = TestAllExtensionsLite.newBuilder();
+ setAllExtensions(builder);
+ return builder.build();
+ }
+
+ public static TestPackedTypes getPackedSet() {
+ TestPackedTypes.Builder builder = TestPackedTypes.newBuilder();
+ setPackedFields(builder);
+ return builder.build();
+ }
+
+ public static TestUnpackedTypes getUnpackedSet() {
+ TestUnpackedTypes.Builder builder = TestUnpackedTypes.newBuilder();
+ setUnpackedFields(builder);
+ return builder.build();
+ }
+
+ public static TestPackedExtensions getPackedExtensionsSet() {
+ TestPackedExtensions.Builder builder = TestPackedExtensions.newBuilder();
+ setPackedExtensions(builder);
+ return builder.build();
+ }
+
+ public static TestPackedExtensionsLite getLitePackedExtensionsSet() {
+ TestPackedExtensionsLite.Builder builder =
+ TestPackedExtensionsLite.newBuilder();
+ setPackedExtensions(builder);
+ return builder.build();
+ }
+
+ /**
+ * Set every field of {@code builder} to the values expected by
+ * {@code assertAllFieldsSet()}.
+ */
+ public static void setAllFields(TestAllTypesLite.Builder builder) {
+ builder.setOptionalInt32 (101);
+ builder.setOptionalInt64 (102);
+ builder.setOptionalUint32 (103);
+ builder.setOptionalUint64 (104);
+ builder.setOptionalSint32 (105);
+ builder.setOptionalSint64 (106);
+ builder.setOptionalFixed32 (107);
+ builder.setOptionalFixed64 (108);
+ builder.setOptionalSfixed32(109);
+ builder.setOptionalSfixed64(110);
+ builder.setOptionalFloat (111);
+ builder.setOptionalDouble (112);
+ builder.setOptionalBool (true);
+ builder.setOptionalString ("115");
+ builder.setOptionalBytes (toBytes("116"));
+
+ builder.setOptionalGroup(
+ TestAllTypesLite.OptionalGroup.newBuilder().setA(117).build());
+ builder.setOptionalNestedMessage(
+ TestAllTypesLite.NestedMessage.newBuilder().setBb(118).build());
+ builder.setOptionalForeignMessage(
+ ForeignMessageLite.newBuilder().setC(119).build());
+ builder.setOptionalImportMessage(
+ ImportMessageLite.newBuilder().setD(120).build());
+ builder.setOptionalPublicImportMessage(
+ PublicImportMessageLite.newBuilder().setE(126).build());
+ builder.setOptionalLazyMessage(
+ TestAllTypesLite.NestedMessage.newBuilder().setBb(127).build());
+
+ builder.setOptionalNestedEnum (TestAllTypesLite.NestedEnum.BAZ);
+ builder.setOptionalForeignEnum(ForeignEnumLite.FOREIGN_LITE_BAZ);
+ builder.setOptionalImportEnum (ImportEnumLite.IMPORT_LITE_BAZ);
+
+ builder.setOptionalStringPiece("124");
+ builder.setOptionalCord("125");
+
+ // -----------------------------------------------------------------
+
+ builder.addRepeatedInt32 (201);
+ builder.addRepeatedInt64 (202);
+ builder.addRepeatedUint32 (203);
+ builder.addRepeatedUint64 (204);
+ builder.addRepeatedSint32 (205);
+ builder.addRepeatedSint64 (206);
+ builder.addRepeatedFixed32 (207);
+ builder.addRepeatedFixed64 (208);
+ builder.addRepeatedSfixed32(209);
+ builder.addRepeatedSfixed64(210);
+ builder.addRepeatedFloat (211);
+ builder.addRepeatedDouble (212);
+ builder.addRepeatedBool (true);
+ builder.addRepeatedString ("215");
+ builder.addRepeatedBytes (toBytes("216"));
+
+ builder.addRepeatedGroup(
+ TestAllTypesLite.RepeatedGroup.newBuilder().setA(217).build());
+ builder.addRepeatedNestedMessage(
+ TestAllTypesLite.NestedMessage.newBuilder().setBb(218).build());
+ builder.addRepeatedForeignMessage(
+ ForeignMessageLite.newBuilder().setC(219).build());
+ builder.addRepeatedImportMessage(
+ ImportMessageLite.newBuilder().setD(220).build());
+ builder.addRepeatedLazyMessage(
+ TestAllTypesLite.NestedMessage.newBuilder().setBb(227).build());
+
+ builder.addRepeatedNestedEnum (TestAllTypesLite.NestedEnum.BAR);
+ builder.addRepeatedForeignEnum(ForeignEnumLite.FOREIGN_LITE_BAR);
+ builder.addRepeatedImportEnum (ImportEnumLite.IMPORT_LITE_BAR);
+
+ builder.addRepeatedStringPiece("224");
+ builder.addRepeatedCord("225");
+
+ // Add a second one of each field.
+ builder.addRepeatedInt32 (301);
+ builder.addRepeatedInt64 (302);
+ builder.addRepeatedUint32 (303);
+ builder.addRepeatedUint64 (304);
+ builder.addRepeatedSint32 (305);
+ builder.addRepeatedSint64 (306);
+ builder.addRepeatedFixed32 (307);
+ builder.addRepeatedFixed64 (308);
+ builder.addRepeatedSfixed32(309);
+ builder.addRepeatedSfixed64(310);
+ builder.addRepeatedFloat (311);
+ builder.addRepeatedDouble (312);
+ builder.addRepeatedBool (false);
+ builder.addRepeatedString ("315");
+ builder.addRepeatedBytes (toBytes("316"));
+
+ builder.addRepeatedGroup(
+ TestAllTypesLite.RepeatedGroup.newBuilder().setA(317).build());
+ builder.addRepeatedNestedMessage(
+ TestAllTypesLite.NestedMessage.newBuilder().setBb(318).build());
+ builder.addRepeatedForeignMessage(
+ ForeignMessageLite.newBuilder().setC(319).build());
+ builder.addRepeatedImportMessage(
+ ImportMessageLite.newBuilder().setD(320).build());
+ builder.addRepeatedLazyMessage(
+ TestAllTypesLite.NestedMessage.newBuilder().setBb(327).build());
+
+ builder.addRepeatedNestedEnum (TestAllTypesLite.NestedEnum.BAZ);
+ builder.addRepeatedForeignEnum(ForeignEnumLite.FOREIGN_LITE_BAZ);
+ builder.addRepeatedImportEnum (ImportEnumLite.IMPORT_LITE_BAZ);
+
+ builder.addRepeatedStringPiece("324");
+ builder.addRepeatedCord("325");
+
+ // -----------------------------------------------------------------
+
+ builder.setDefaultInt32 (401);
+ builder.setDefaultInt64 (402);
+ builder.setDefaultUint32 (403);
+ builder.setDefaultUint64 (404);
+ builder.setDefaultSint32 (405);
+ builder.setDefaultSint64 (406);
+ builder.setDefaultFixed32 (407);
+ builder.setDefaultFixed64 (408);
+ builder.setDefaultSfixed32(409);
+ builder.setDefaultSfixed64(410);
+ builder.setDefaultFloat (411);
+ builder.setDefaultDouble (412);
+ builder.setDefaultBool (false);
+ builder.setDefaultString ("415");
+ builder.setDefaultBytes (toBytes("416"));
+
+ builder.setDefaultNestedEnum (TestAllTypesLite.NestedEnum.FOO);
+ builder.setDefaultForeignEnum(ForeignEnumLite.FOREIGN_LITE_FOO);
+ builder.setDefaultImportEnum (ImportEnumLite.IMPORT_LITE_FOO);
+
+ builder.setDefaultStringPiece("424");
+ builder.setDefaultCord("425");
+
+ builder.setOneofUint32(601);
+ builder.setOneofNestedMessage(
+ TestAllTypesLite.NestedMessage.newBuilder().setBb(602).build());
+ builder.setOneofString("603");
+ builder.setOneofBytes(toBytes("604"));
+ }
+
+ /**
+ * Set every field of {@code message} to the values expected by
+ * {@code assertAllFieldsSet()}.
+ */
+ public static void setAllFields(TestAllTypes.Builder message) {
+ message.setOptionalInt32 (101);
+ message.setOptionalInt64 (102);
+ message.setOptionalUint32 (103);
+ message.setOptionalUint64 (104);
+ message.setOptionalSint32 (105);
+ message.setOptionalSint64 (106);
+ message.setOptionalFixed32 (107);
+ message.setOptionalFixed64 (108);
+ message.setOptionalSfixed32(109);
+ message.setOptionalSfixed64(110);
+ message.setOptionalFloat (111);
+ message.setOptionalDouble (112);
+ message.setOptionalBool (true);
+ message.setOptionalString ("115");
+ message.setOptionalBytes (toBytes("116"));
+
+ message.setOptionalGroup(
+ TestAllTypes.OptionalGroup.newBuilder().setA(117).build());
+ message.setOptionalNestedMessage(
+ TestAllTypes.NestedMessage.newBuilder().setBb(118).build());
+ message.setOptionalForeignMessage(
+ ForeignMessage.newBuilder().setC(119).build());
+ message.setOptionalImportMessage(
+ ImportMessage.newBuilder().setD(120).build());
+ message.setOptionalPublicImportMessage(
+ PublicImportMessage.newBuilder().setE(126).build());
+ message.setOptionalLazyMessage(
+ TestAllTypes.NestedMessage.newBuilder().setBb(127).build());
+
+ message.setOptionalNestedEnum (TestAllTypes.NestedEnum.BAZ);
+ message.setOptionalForeignEnum(ForeignEnum.FOREIGN_BAZ);
+ message.setOptionalImportEnum (ImportEnum.IMPORT_BAZ);
+
+ message.setOptionalStringPiece("124");
+ message.setOptionalCord("125");
+
+ // -----------------------------------------------------------------
+
+ message.addRepeatedInt32 (201);
+ message.addRepeatedInt64 (202);
+ message.addRepeatedUint32 (203);
+ message.addRepeatedUint64 (204);
+ message.addRepeatedSint32 (205);
+ message.addRepeatedSint64 (206);
+ message.addRepeatedFixed32 (207);
+ message.addRepeatedFixed64 (208);
+ message.addRepeatedSfixed32(209);
+ message.addRepeatedSfixed64(210);
+ message.addRepeatedFloat (211);
+ message.addRepeatedDouble (212);
+ message.addRepeatedBool (true);
+ message.addRepeatedString ("215");
+ message.addRepeatedBytes (toBytes("216"));
+
+ message.addRepeatedGroup(
+ TestAllTypes.RepeatedGroup.newBuilder().setA(217).build());
+ message.addRepeatedNestedMessage(
+ TestAllTypes.NestedMessage.newBuilder().setBb(218).build());
+ message.addRepeatedForeignMessage(
+ ForeignMessage.newBuilder().setC(219).build());
+ message.addRepeatedImportMessage(
+ ImportMessage.newBuilder().setD(220).build());
+ message.addRepeatedLazyMessage(
+ TestAllTypes.NestedMessage.newBuilder().setBb(227).build());
+
+ message.addRepeatedNestedEnum (TestAllTypes.NestedEnum.BAR);
+ message.addRepeatedForeignEnum(ForeignEnum.FOREIGN_BAR);
+ message.addRepeatedImportEnum (ImportEnum.IMPORT_BAR);
+
+ message.addRepeatedStringPiece("224");
+ message.addRepeatedCord("225");
+
+ // Add a second one of each field.
+ message.addRepeatedInt32 (301);
+ message.addRepeatedInt64 (302);
+ message.addRepeatedUint32 (303);
+ message.addRepeatedUint64 (304);
+ message.addRepeatedSint32 (305);
+ message.addRepeatedSint64 (306);
+ message.addRepeatedFixed32 (307);
+ message.addRepeatedFixed64 (308);
+ message.addRepeatedSfixed32(309);
+ message.addRepeatedSfixed64(310);
+ message.addRepeatedFloat (311);
+ message.addRepeatedDouble (312);
+ message.addRepeatedBool (false);
+ message.addRepeatedString ("315");
+ message.addRepeatedBytes (toBytes("316"));
+
+ message.addRepeatedGroup(
+ TestAllTypes.RepeatedGroup.newBuilder().setA(317).build());
+ message.addRepeatedNestedMessage(
+ TestAllTypes.NestedMessage.newBuilder().setBb(318).build());
+ message.addRepeatedForeignMessage(
+ ForeignMessage.newBuilder().setC(319).build());
+ message.addRepeatedImportMessage(
+ ImportMessage.newBuilder().setD(320).build());
+ message.addRepeatedLazyMessage(
+ TestAllTypes.NestedMessage.newBuilder().setBb(327).build());
+
+ message.addRepeatedNestedEnum (TestAllTypes.NestedEnum.BAZ);
+ message.addRepeatedForeignEnum(ForeignEnum.FOREIGN_BAZ);
+ message.addRepeatedImportEnum (ImportEnum.IMPORT_BAZ);
+
+ message.addRepeatedStringPiece("324");
+ message.addRepeatedCord("325");
+
+ // -----------------------------------------------------------------
+
+ message.setDefaultInt32 (401);
+ message.setDefaultInt64 (402);
+ message.setDefaultUint32 (403);
+ message.setDefaultUint64 (404);
+ message.setDefaultSint32 (405);
+ message.setDefaultSint64 (406);
+ message.setDefaultFixed32 (407);
+ message.setDefaultFixed64 (408);
+ message.setDefaultSfixed32(409);
+ message.setDefaultSfixed64(410);
+ message.setDefaultFloat (411);
+ message.setDefaultDouble (412);
+ message.setDefaultBool (false);
+ message.setDefaultString ("415");
+ message.setDefaultBytes (toBytes("416"));
+
+ message.setDefaultNestedEnum (TestAllTypes.NestedEnum.FOO);
+ message.setDefaultForeignEnum(ForeignEnum.FOREIGN_FOO);
+ message.setDefaultImportEnum (ImportEnum.IMPORT_FOO);
+
+ message.setDefaultStringPiece("424");
+ message.setDefaultCord("425");
+
+ message.setOneofUint32(601);
+ message.setOneofNestedMessage(
+ TestAllTypes.NestedMessage.newBuilder().setBb(602).build());
+ message.setOneofString("603");
+ message.setOneofBytes(toBytes("604"));
+ }
+
+ // -------------------------------------------------------------------
+
+ /**
+ * Modify the repeated fields of {@code message} to contain the values
+ * expected by {@code assertRepeatedFieldsModified()}.
+ */
+ public static void modifyRepeatedFields(TestAllTypes.Builder message) {
+ message.setRepeatedInt32 (1, 501);
+ message.setRepeatedInt64 (1, 502);
+ message.setRepeatedUint32 (1, 503);
+ message.setRepeatedUint64 (1, 504);
+ message.setRepeatedSint32 (1, 505);
+ message.setRepeatedSint64 (1, 506);
+ message.setRepeatedFixed32 (1, 507);
+ message.setRepeatedFixed64 (1, 508);
+ message.setRepeatedSfixed32(1, 509);
+ message.setRepeatedSfixed64(1, 510);
+ message.setRepeatedFloat (1, 511);
+ message.setRepeatedDouble (1, 512);
+ message.setRepeatedBool (1, true);
+ message.setRepeatedString (1, "515");
+ message.setRepeatedBytes (1, toBytes("516"));
+
+ message.setRepeatedGroup(1,
+ TestAllTypes.RepeatedGroup.newBuilder().setA(517).build());
+ message.setRepeatedNestedMessage(1,
+ TestAllTypes.NestedMessage.newBuilder().setBb(518).build());
+ message.setRepeatedForeignMessage(1,
+ ForeignMessage.newBuilder().setC(519).build());
+ message.setRepeatedImportMessage(1,
+ ImportMessage.newBuilder().setD(520).build());
+ message.setRepeatedLazyMessage(1,
+ TestAllTypes.NestedMessage.newBuilder().setBb(527).build());
+
+ message.setRepeatedNestedEnum (1, TestAllTypes.NestedEnum.FOO);
+ message.setRepeatedForeignEnum(1, ForeignEnum.FOREIGN_FOO);
+ message.setRepeatedImportEnum (1, ImportEnum.IMPORT_FOO);
+
+ message.setRepeatedStringPiece(1, "524");
+ message.setRepeatedCord(1, "525");
+ }
+
+ // -------------------------------------------------------------------
+
+ /**
+ * Assert (using {@code junit.framework.Assert}} that all fields of
+ * {@code message} are set to the values assigned by {@code setAllFields}.
+ */
+ public static void assertAllFieldsSet(TestAllTypesOrBuilder message) {
+ Assert.assertTrue(message.hasOptionalInt32 ());
+ Assert.assertTrue(message.hasOptionalInt64 ());
+ Assert.assertTrue(message.hasOptionalUint32 ());
+ Assert.assertTrue(message.hasOptionalUint64 ());
+ Assert.assertTrue(message.hasOptionalSint32 ());
+ Assert.assertTrue(message.hasOptionalSint64 ());
+ Assert.assertTrue(message.hasOptionalFixed32 ());
+ Assert.assertTrue(message.hasOptionalFixed64 ());
+ Assert.assertTrue(message.hasOptionalSfixed32());
+ Assert.assertTrue(message.hasOptionalSfixed64());
+ Assert.assertTrue(message.hasOptionalFloat ());
+ Assert.assertTrue(message.hasOptionalDouble ());
+ Assert.assertTrue(message.hasOptionalBool ());
+ Assert.assertTrue(message.hasOptionalString ());
+ Assert.assertTrue(message.hasOptionalBytes ());
+
+ Assert.assertTrue(message.hasOptionalGroup ());
+ Assert.assertTrue(message.hasOptionalNestedMessage ());
+ Assert.assertTrue(message.hasOptionalForeignMessage());
+ Assert.assertTrue(message.hasOptionalImportMessage ());
+
+ Assert.assertTrue(message.getOptionalGroup ().hasA());
+ Assert.assertTrue(message.getOptionalNestedMessage ().hasBb());
+ Assert.assertTrue(message.getOptionalForeignMessage().hasC());
+ Assert.assertTrue(message.getOptionalImportMessage ().hasD());
+
+ Assert.assertTrue(message.hasOptionalNestedEnum ());
+ Assert.assertTrue(message.hasOptionalForeignEnum());
+ Assert.assertTrue(message.hasOptionalImportEnum ());
+
+ Assert.assertTrue(message.hasOptionalStringPiece());
+ Assert.assertTrue(message.hasOptionalCord());
+
+ Assert.assertEquals(101 , message.getOptionalInt32 ());
+ Assert.assertEquals(102 , message.getOptionalInt64 ());
+ Assert.assertEquals(103 , message.getOptionalUint32 ());
+ Assert.assertEquals(104 , message.getOptionalUint64 ());
+ Assert.assertEquals(105 , message.getOptionalSint32 ());
+ Assert.assertEquals(106 , message.getOptionalSint64 ());
+ Assert.assertEquals(107 , message.getOptionalFixed32 ());
+ Assert.assertEquals(108 , message.getOptionalFixed64 ());
+ Assert.assertEquals(109 , message.getOptionalSfixed32());
+ Assert.assertEquals(110 , message.getOptionalSfixed64());
+ Assert.assertEquals(111 , message.getOptionalFloat (), 0.0);
+ Assert.assertEquals(112 , message.getOptionalDouble (), 0.0);
+ Assert.assertEquals(true , message.getOptionalBool ());
+ Assert.assertEquals("115", message.getOptionalString ());
+ Assert.assertEquals(toBytes("116"), message.getOptionalBytes());
+
+ Assert.assertEquals(117, message.getOptionalGroup ().getA());
+ Assert.assertEquals(118, message.getOptionalNestedMessage ().getBb());
+ Assert.assertEquals(119, message.getOptionalForeignMessage ().getC());
+ Assert.assertEquals(120, message.getOptionalImportMessage ().getD());
+ Assert.assertEquals(126, message.getOptionalPublicImportMessage().getE());
+ Assert.assertEquals(127, message.getOptionalLazyMessage ().getBb());
+
+ Assert.assertEquals(TestAllTypes.NestedEnum.BAZ, message.getOptionalNestedEnum());
+ Assert.assertEquals(ForeignEnum.FOREIGN_BAZ, message.getOptionalForeignEnum());
+ Assert.assertEquals(ImportEnum.IMPORT_BAZ, message.getOptionalImportEnum());
+
+ Assert.assertEquals("124", message.getOptionalStringPiece());
+ Assert.assertEquals("125", message.getOptionalCord());
+
+ // -----------------------------------------------------------------
+
+ Assert.assertEquals(2, message.getRepeatedInt32Count ());
+ Assert.assertEquals(2, message.getRepeatedInt64Count ());
+ Assert.assertEquals(2, message.getRepeatedUint32Count ());
+ Assert.assertEquals(2, message.getRepeatedUint64Count ());
+ Assert.assertEquals(2, message.getRepeatedSint32Count ());
+ Assert.assertEquals(2, message.getRepeatedSint64Count ());
+ Assert.assertEquals(2, message.getRepeatedFixed32Count ());
+ Assert.assertEquals(2, message.getRepeatedFixed64Count ());
+ Assert.assertEquals(2, message.getRepeatedSfixed32Count());
+ Assert.assertEquals(2, message.getRepeatedSfixed64Count());
+ Assert.assertEquals(2, message.getRepeatedFloatCount ());
+ Assert.assertEquals(2, message.getRepeatedDoubleCount ());
+ Assert.assertEquals(2, message.getRepeatedBoolCount ());
+ Assert.assertEquals(2, message.getRepeatedStringCount ());
+ Assert.assertEquals(2, message.getRepeatedBytesCount ());
+
+ Assert.assertEquals(2, message.getRepeatedGroupCount ());
+ Assert.assertEquals(2, message.getRepeatedNestedMessageCount ());
+ Assert.assertEquals(2, message.getRepeatedForeignMessageCount());
+ Assert.assertEquals(2, message.getRepeatedImportMessageCount ());
+ Assert.assertEquals(2, message.getRepeatedLazyMessageCount ());
+ Assert.assertEquals(2, message.getRepeatedNestedEnumCount ());
+ Assert.assertEquals(2, message.getRepeatedForeignEnumCount ());
+ Assert.assertEquals(2, message.getRepeatedImportEnumCount ());
+
+ Assert.assertEquals(2, message.getRepeatedStringPieceCount());
+ Assert.assertEquals(2, message.getRepeatedCordCount());
+
+ Assert.assertEquals(201 , message.getRepeatedInt32 (0));
+ Assert.assertEquals(202 , message.getRepeatedInt64 (0));
+ Assert.assertEquals(203 , message.getRepeatedUint32 (0));
+ Assert.assertEquals(204 , message.getRepeatedUint64 (0));
+ Assert.assertEquals(205 , message.getRepeatedSint32 (0));
+ Assert.assertEquals(206 , message.getRepeatedSint64 (0));
+ Assert.assertEquals(207 , message.getRepeatedFixed32 (0));
+ Assert.assertEquals(208 , message.getRepeatedFixed64 (0));
+ Assert.assertEquals(209 , message.getRepeatedSfixed32(0));
+ Assert.assertEquals(210 , message.getRepeatedSfixed64(0));
+ Assert.assertEquals(211 , message.getRepeatedFloat (0), 0.0);
+ Assert.assertEquals(212 , message.getRepeatedDouble (0), 0.0);
+ Assert.assertEquals(true , message.getRepeatedBool (0));
+ Assert.assertEquals("215", message.getRepeatedString (0));
+ Assert.assertEquals(toBytes("216"), message.getRepeatedBytes(0));
+
+ Assert.assertEquals(217, message.getRepeatedGroup (0).getA());
+ Assert.assertEquals(218, message.getRepeatedNestedMessage (0).getBb());
+ Assert.assertEquals(219, message.getRepeatedForeignMessage(0).getC());
+ Assert.assertEquals(220, message.getRepeatedImportMessage (0).getD());
+ Assert.assertEquals(227, message.getRepeatedLazyMessage (0).getBb());
+
+ Assert.assertEquals(TestAllTypes.NestedEnum.BAR, message.getRepeatedNestedEnum (0));
+ Assert.assertEquals(ForeignEnum.FOREIGN_BAR, message.getRepeatedForeignEnum(0));
+ Assert.assertEquals(ImportEnum.IMPORT_BAR, message.getRepeatedImportEnum(0));
+
+ Assert.assertEquals("224", message.getRepeatedStringPiece(0));
+ Assert.assertEquals("225", message.getRepeatedCord(0));
+
+ Assert.assertEquals(301 , message.getRepeatedInt32 (1));
+ Assert.assertEquals(302 , message.getRepeatedInt64 (1));
+ Assert.assertEquals(303 , message.getRepeatedUint32 (1));
+ Assert.assertEquals(304 , message.getRepeatedUint64 (1));
+ Assert.assertEquals(305 , message.getRepeatedSint32 (1));
+ Assert.assertEquals(306 , message.getRepeatedSint64 (1));
+ Assert.assertEquals(307 , message.getRepeatedFixed32 (1));
+ Assert.assertEquals(308 , message.getRepeatedFixed64 (1));
+ Assert.assertEquals(309 , message.getRepeatedSfixed32(1));
+ Assert.assertEquals(310 , message.getRepeatedSfixed64(1));
+ Assert.assertEquals(311 , message.getRepeatedFloat (1), 0.0);
+ Assert.assertEquals(312 , message.getRepeatedDouble (1), 0.0);
+ Assert.assertEquals(false, message.getRepeatedBool (1));
+ Assert.assertEquals("315", message.getRepeatedString (1));
+ Assert.assertEquals(toBytes("316"), message.getRepeatedBytes(1));
+
+ Assert.assertEquals(317, message.getRepeatedGroup (1).getA());
+ Assert.assertEquals(318, message.getRepeatedNestedMessage (1).getBb());
+ Assert.assertEquals(319, message.getRepeatedForeignMessage(1).getC());
+ Assert.assertEquals(320, message.getRepeatedImportMessage (1).getD());
+ Assert.assertEquals(327, message.getRepeatedLazyMessage (1).getBb());
+
+ Assert.assertEquals(TestAllTypes.NestedEnum.BAZ, message.getRepeatedNestedEnum (1));
+ Assert.assertEquals(ForeignEnum.FOREIGN_BAZ, message.getRepeatedForeignEnum(1));
+ Assert.assertEquals(ImportEnum.IMPORT_BAZ, message.getRepeatedImportEnum(1));
+
+ Assert.assertEquals("324", message.getRepeatedStringPiece(1));
+ Assert.assertEquals("325", message.getRepeatedCord(1));
+
+ // -----------------------------------------------------------------
+
+ Assert.assertTrue(message.hasDefaultInt32 ());
+ Assert.assertTrue(message.hasDefaultInt64 ());
+ Assert.assertTrue(message.hasDefaultUint32 ());
+ Assert.assertTrue(message.hasDefaultUint64 ());
+ Assert.assertTrue(message.hasDefaultSint32 ());
+ Assert.assertTrue(message.hasDefaultSint64 ());
+ Assert.assertTrue(message.hasDefaultFixed32 ());
+ Assert.assertTrue(message.hasDefaultFixed64 ());
+ Assert.assertTrue(message.hasDefaultSfixed32());
+ Assert.assertTrue(message.hasDefaultSfixed64());
+ Assert.assertTrue(message.hasDefaultFloat ());
+ Assert.assertTrue(message.hasDefaultDouble ());
+ Assert.assertTrue(message.hasDefaultBool ());
+ Assert.assertTrue(message.hasDefaultString ());
+ Assert.assertTrue(message.hasDefaultBytes ());
+
+ Assert.assertTrue(message.hasDefaultNestedEnum ());
+ Assert.assertTrue(message.hasDefaultForeignEnum());
+ Assert.assertTrue(message.hasDefaultImportEnum ());
+
+ Assert.assertTrue(message.hasDefaultStringPiece());
+ Assert.assertTrue(message.hasDefaultCord());
+
+ Assert.assertEquals(401 , message.getDefaultInt32 ());
+ Assert.assertEquals(402 , message.getDefaultInt64 ());
+ Assert.assertEquals(403 , message.getDefaultUint32 ());
+ Assert.assertEquals(404 , message.getDefaultUint64 ());
+ Assert.assertEquals(405 , message.getDefaultSint32 ());
+ Assert.assertEquals(406 , message.getDefaultSint64 ());
+ Assert.assertEquals(407 , message.getDefaultFixed32 ());
+ Assert.assertEquals(408 , message.getDefaultFixed64 ());
+ Assert.assertEquals(409 , message.getDefaultSfixed32());
+ Assert.assertEquals(410 , message.getDefaultSfixed64());
+ Assert.assertEquals(411 , message.getDefaultFloat (), 0.0);
+ Assert.assertEquals(412 , message.getDefaultDouble (), 0.0);
+ Assert.assertEquals(false, message.getDefaultBool ());
+ Assert.assertEquals("415", message.getDefaultString ());
+ Assert.assertEquals(toBytes("416"), message.getDefaultBytes());
+
+ Assert.assertEquals(TestAllTypes.NestedEnum.FOO, message.getDefaultNestedEnum ());
+ Assert.assertEquals(ForeignEnum.FOREIGN_FOO, message.getDefaultForeignEnum());
+ Assert.assertEquals(ImportEnum.IMPORT_FOO, message.getDefaultImportEnum());
+
+ Assert.assertEquals("424", message.getDefaultStringPiece());
+ Assert.assertEquals("425", message.getDefaultCord());
+
+ Assert.assertEquals(TestAllTypes.OneofFieldCase.ONEOF_BYTES, message.getOneofFieldCase());
+ Assert.assertFalse(message.hasOneofUint32());
+ Assert.assertFalse(message.hasOneofNestedMessage());
+ Assert.assertFalse(message.hasOneofString());
+ Assert.assertTrue(message.hasOneofBytes());
+
+ Assert.assertEquals(toBytes("604"), message.getOneofBytes());
+ }
+
+ // -------------------------------------------------------------------
+ /**
+ * Assert (using {@code junit.framework.Assert}} that all fields of
+ * {@code message} are cleared, and that getting the fields returns their
+ * default values.
+ */
+ public static void assertClear(TestAllTypesOrBuilder message) {
+ // hasBlah() should initially be false for all optional fields.
+ Assert.assertFalse(message.hasOptionalInt32 ());
+ Assert.assertFalse(message.hasOptionalInt64 ());
+ Assert.assertFalse(message.hasOptionalUint32 ());
+ Assert.assertFalse(message.hasOptionalUint64 ());
+ Assert.assertFalse(message.hasOptionalSint32 ());
+ Assert.assertFalse(message.hasOptionalSint64 ());
+ Assert.assertFalse(message.hasOptionalFixed32 ());
+ Assert.assertFalse(message.hasOptionalFixed64 ());
+ Assert.assertFalse(message.hasOptionalSfixed32());
+ Assert.assertFalse(message.hasOptionalSfixed64());
+ Assert.assertFalse(message.hasOptionalFloat ());
+ Assert.assertFalse(message.hasOptionalDouble ());
+ Assert.assertFalse(message.hasOptionalBool ());
+ Assert.assertFalse(message.hasOptionalString ());
+ Assert.assertFalse(message.hasOptionalBytes ());
+
+ Assert.assertFalse(message.hasOptionalGroup ());
+ Assert.assertFalse(message.hasOptionalNestedMessage ());
+ Assert.assertFalse(message.hasOptionalForeignMessage());
+ Assert.assertFalse(message.hasOptionalImportMessage ());
+
+ Assert.assertFalse(message.hasOptionalNestedEnum ());
+ Assert.assertFalse(message.hasOptionalForeignEnum());
+ Assert.assertFalse(message.hasOptionalImportEnum ());
+
+ Assert.assertFalse(message.hasOptionalStringPiece());
+ Assert.assertFalse(message.hasOptionalCord());
+
+ // Optional fields without defaults are set to zero or something like it.
+ Assert.assertEquals(0 , message.getOptionalInt32 ());
+ Assert.assertEquals(0 , message.getOptionalInt64 ());
+ Assert.assertEquals(0 , message.getOptionalUint32 ());
+ Assert.assertEquals(0 , message.getOptionalUint64 ());
+ Assert.assertEquals(0 , message.getOptionalSint32 ());
+ Assert.assertEquals(0 , message.getOptionalSint64 ());
+ Assert.assertEquals(0 , message.getOptionalFixed32 ());
+ Assert.assertEquals(0 , message.getOptionalFixed64 ());
+ Assert.assertEquals(0 , message.getOptionalSfixed32());
+ Assert.assertEquals(0 , message.getOptionalSfixed64());
+ Assert.assertEquals(0 , message.getOptionalFloat (), 0.0);
+ Assert.assertEquals(0 , message.getOptionalDouble (), 0.0);
+ Assert.assertEquals(false, message.getOptionalBool ());
+ Assert.assertEquals("" , message.getOptionalString ());
+ Assert.assertEquals(ByteString.EMPTY, message.getOptionalBytes());
+
+ // Embedded messages should also be clear.
+ Assert.assertFalse(message.getOptionalGroup ().hasA());
+ Assert.assertFalse(message.getOptionalNestedMessage ().hasBb());
+ Assert.assertFalse(message.getOptionalForeignMessage ().hasC());
+ Assert.assertFalse(message.getOptionalImportMessage ().hasD());
+ Assert.assertFalse(message.getOptionalPublicImportMessage().hasE());
+ Assert.assertFalse(message.getOptionalLazyMessage ().hasBb());
+
+ Assert.assertEquals(0, message.getOptionalGroup ().getA());
+ Assert.assertEquals(0, message.getOptionalNestedMessage ().getBb());
+ Assert.assertEquals(0, message.getOptionalForeignMessage ().getC());
+ Assert.assertEquals(0, message.getOptionalImportMessage ().getD());
+ Assert.assertEquals(0, message.getOptionalPublicImportMessage().getE());
+ Assert.assertEquals(0, message.getOptionalLazyMessage ().getBb());
+
+ // Enums without defaults are set to the first value in the enum.
+ Assert.assertEquals(TestAllTypes.NestedEnum.FOO, message.getOptionalNestedEnum ());
+ Assert.assertEquals(ForeignEnum.FOREIGN_FOO, message.getOptionalForeignEnum());
+ Assert.assertEquals(ImportEnum.IMPORT_FOO, message.getOptionalImportEnum());
+
+ Assert.assertEquals("", message.getOptionalStringPiece());
+ Assert.assertEquals("", message.getOptionalCord());
+
+ // Repeated fields are empty.
+ Assert.assertEquals(0, message.getRepeatedInt32Count ());
+ Assert.assertEquals(0, message.getRepeatedInt64Count ());
+ Assert.assertEquals(0, message.getRepeatedUint32Count ());
+ Assert.assertEquals(0, message.getRepeatedUint64Count ());
+ Assert.assertEquals(0, message.getRepeatedSint32Count ());
+ Assert.assertEquals(0, message.getRepeatedSint64Count ());
+ Assert.assertEquals(0, message.getRepeatedFixed32Count ());
+ Assert.assertEquals(0, message.getRepeatedFixed64Count ());
+ Assert.assertEquals(0, message.getRepeatedSfixed32Count());
+ Assert.assertEquals(0, message.getRepeatedSfixed64Count());
+ Assert.assertEquals(0, message.getRepeatedFloatCount ());
+ Assert.assertEquals(0, message.getRepeatedDoubleCount ());
+ Assert.assertEquals(0, message.getRepeatedBoolCount ());
+ Assert.assertEquals(0, message.getRepeatedStringCount ());
+ Assert.assertEquals(0, message.getRepeatedBytesCount ());
+
+ Assert.assertEquals(0, message.getRepeatedGroupCount ());
+ Assert.assertEquals(0, message.getRepeatedNestedMessageCount ());
+ Assert.assertEquals(0, message.getRepeatedForeignMessageCount());
+ Assert.assertEquals(0, message.getRepeatedImportMessageCount ());
+ Assert.assertEquals(0, message.getRepeatedLazyMessageCount ());
+ Assert.assertEquals(0, message.getRepeatedNestedEnumCount ());
+ Assert.assertEquals(0, message.getRepeatedForeignEnumCount ());
+ Assert.assertEquals(0, message.getRepeatedImportEnumCount ());
+
+ Assert.assertEquals(0, message.getRepeatedStringPieceCount());
+ Assert.assertEquals(0, message.getRepeatedCordCount());
+
+ // hasBlah() should also be false for all default fields.
+ Assert.assertFalse(message.hasDefaultInt32 ());
+ Assert.assertFalse(message.hasDefaultInt64 ());
+ Assert.assertFalse(message.hasDefaultUint32 ());
+ Assert.assertFalse(message.hasDefaultUint64 ());
+ Assert.assertFalse(message.hasDefaultSint32 ());
+ Assert.assertFalse(message.hasDefaultSint64 ());
+ Assert.assertFalse(message.hasDefaultFixed32 ());
+ Assert.assertFalse(message.hasDefaultFixed64 ());
+ Assert.assertFalse(message.hasDefaultSfixed32());
+ Assert.assertFalse(message.hasDefaultSfixed64());
+ Assert.assertFalse(message.hasDefaultFloat ());
+ Assert.assertFalse(message.hasDefaultDouble ());
+ Assert.assertFalse(message.hasDefaultBool ());
+ Assert.assertFalse(message.hasDefaultString ());
+ Assert.assertFalse(message.hasDefaultBytes ());
+
+ Assert.assertFalse(message.hasDefaultNestedEnum ());
+ Assert.assertFalse(message.hasDefaultForeignEnum());
+ Assert.assertFalse(message.hasDefaultImportEnum ());
+
+ Assert.assertFalse(message.hasDefaultStringPiece());
+ Assert.assertFalse(message.hasDefaultCord());
+
+ // Fields with defaults have their default values (duh).
+ Assert.assertEquals( 41 , message.getDefaultInt32 ());
+ Assert.assertEquals( 42 , message.getDefaultInt64 ());
+ Assert.assertEquals( 43 , message.getDefaultUint32 ());
+ Assert.assertEquals( 44 , message.getDefaultUint64 ());
+ Assert.assertEquals(-45 , message.getDefaultSint32 ());
+ Assert.assertEquals( 46 , message.getDefaultSint64 ());
+ Assert.assertEquals( 47 , message.getDefaultFixed32 ());
+ Assert.assertEquals( 48 , message.getDefaultFixed64 ());
+ Assert.assertEquals( 49 , message.getDefaultSfixed32());
+ Assert.assertEquals(-50 , message.getDefaultSfixed64());
+ Assert.assertEquals( 51.5 , message.getDefaultFloat (), 0.0);
+ Assert.assertEquals( 52e3 , message.getDefaultDouble (), 0.0);
+ Assert.assertEquals(true , message.getDefaultBool ());
+ Assert.assertEquals("hello", message.getDefaultString ());
+ Assert.assertEquals(toBytes("world"), message.getDefaultBytes());
+
+ Assert.assertEquals(TestAllTypes.NestedEnum.BAR, message.getDefaultNestedEnum ());
+ Assert.assertEquals(ForeignEnum.FOREIGN_BAR, message.getDefaultForeignEnum());
+ Assert.assertEquals(ImportEnum.IMPORT_BAR, message.getDefaultImportEnum());
+
+ Assert.assertEquals("abc", message.getDefaultStringPiece());
+ Assert.assertEquals("123", message.getDefaultCord());
+
+ Assert.assertFalse(message.hasOneofUint32());
+ Assert.assertFalse(message.hasOneofNestedMessage());
+ Assert.assertFalse(message.hasOneofString());
+ Assert.assertFalse(message.hasOneofBytes());
+ }
+
+ // -------------------------------------------------------------------
+
+ /**
+ * Assert (using {@code junit.framework.Assert}} that all fields of
+ * {@code message} are set to the values assigned by {@code setAllFields}
+ * followed by {@code modifyRepeatedFields}.
+ */
+ public static void assertRepeatedFieldsModified(
+ TestAllTypesOrBuilder message) {
+ // ModifyRepeatedFields only sets the second repeated element of each
+ // field. In addition to verifying this, we also verify that the first
+ // element and size were *not* modified.
+ Assert.assertEquals(2, message.getRepeatedInt32Count ());
+ Assert.assertEquals(2, message.getRepeatedInt64Count ());
+ Assert.assertEquals(2, message.getRepeatedUint32Count ());
+ Assert.assertEquals(2, message.getRepeatedUint64Count ());
+ Assert.assertEquals(2, message.getRepeatedSint32Count ());
+ Assert.assertEquals(2, message.getRepeatedSint64Count ());
+ Assert.assertEquals(2, message.getRepeatedFixed32Count ());
+ Assert.assertEquals(2, message.getRepeatedFixed64Count ());
+ Assert.assertEquals(2, message.getRepeatedSfixed32Count());
+ Assert.assertEquals(2, message.getRepeatedSfixed64Count());
+ Assert.assertEquals(2, message.getRepeatedFloatCount ());
+ Assert.assertEquals(2, message.getRepeatedDoubleCount ());
+ Assert.assertEquals(2, message.getRepeatedBoolCount ());
+ Assert.assertEquals(2, message.getRepeatedStringCount ());
+ Assert.assertEquals(2, message.getRepeatedBytesCount ());
+
+ Assert.assertEquals(2, message.getRepeatedGroupCount ());
+ Assert.assertEquals(2, message.getRepeatedNestedMessageCount ());
+ Assert.assertEquals(2, message.getRepeatedForeignMessageCount());
+ Assert.assertEquals(2, message.getRepeatedImportMessageCount ());
+ Assert.assertEquals(2, message.getRepeatedLazyMessageCount ());
+ Assert.assertEquals(2, message.getRepeatedNestedEnumCount ());
+ Assert.assertEquals(2, message.getRepeatedForeignEnumCount ());
+ Assert.assertEquals(2, message.getRepeatedImportEnumCount ());
+
+ Assert.assertEquals(2, message.getRepeatedStringPieceCount());
+ Assert.assertEquals(2, message.getRepeatedCordCount());
+
+ Assert.assertEquals(201 , message.getRepeatedInt32 (0));
+ Assert.assertEquals(202L , message.getRepeatedInt64 (0));
+ Assert.assertEquals(203 , message.getRepeatedUint32 (0));
+ Assert.assertEquals(204L , message.getRepeatedUint64 (0));
+ Assert.assertEquals(205 , message.getRepeatedSint32 (0));
+ Assert.assertEquals(206L , message.getRepeatedSint64 (0));
+ Assert.assertEquals(207 , message.getRepeatedFixed32 (0));
+ Assert.assertEquals(208L , message.getRepeatedFixed64 (0));
+ Assert.assertEquals(209 , message.getRepeatedSfixed32(0));
+ Assert.assertEquals(210L , message.getRepeatedSfixed64(0));
+ Assert.assertEquals(211F , message.getRepeatedFloat (0));
+ Assert.assertEquals(212D , message.getRepeatedDouble (0));
+ Assert.assertEquals(true , message.getRepeatedBool (0));
+ Assert.assertEquals("215", message.getRepeatedString (0));
+ Assert.assertEquals(toBytes("216"), message.getRepeatedBytes(0));
+
+ Assert.assertEquals(217, message.getRepeatedGroup (0).getA());
+ Assert.assertEquals(218, message.getRepeatedNestedMessage (0).getBb());
+ Assert.assertEquals(219, message.getRepeatedForeignMessage(0).getC());
+ Assert.assertEquals(220, message.getRepeatedImportMessage (0).getD());
+ Assert.assertEquals(227, message.getRepeatedLazyMessage (0).getBb());
+
+ Assert.assertEquals(TestAllTypes.NestedEnum.BAR, message.getRepeatedNestedEnum (0));
+ Assert.assertEquals(ForeignEnum.FOREIGN_BAR, message.getRepeatedForeignEnum(0));
+ Assert.assertEquals(ImportEnum.IMPORT_BAR, message.getRepeatedImportEnum(0));
+
+ Assert.assertEquals("224", message.getRepeatedStringPiece(0));
+ Assert.assertEquals("225", message.getRepeatedCord(0));
+
+ // Actually verify the second (modified) elements now.
+ Assert.assertEquals(501 , message.getRepeatedInt32 (1));
+ Assert.assertEquals(502L , message.getRepeatedInt64 (1));
+ Assert.assertEquals(503 , message.getRepeatedUint32 (1));
+ Assert.assertEquals(504L , message.getRepeatedUint64 (1));
+ Assert.assertEquals(505 , message.getRepeatedSint32 (1));
+ Assert.assertEquals(506L , message.getRepeatedSint64 (1));
+ Assert.assertEquals(507 , message.getRepeatedFixed32 (1));
+ Assert.assertEquals(508L , message.getRepeatedFixed64 (1));
+ Assert.assertEquals(509 , message.getRepeatedSfixed32(1));
+ Assert.assertEquals(510L , message.getRepeatedSfixed64(1));
+ Assert.assertEquals(511F , message.getRepeatedFloat (1));
+ Assert.assertEquals(512D , message.getRepeatedDouble (1));
+ Assert.assertEquals(true , message.getRepeatedBool (1));
+ Assert.assertEquals("515", message.getRepeatedString (1));
+ Assert.assertEquals(toBytes("516"), message.getRepeatedBytes(1));
+
+ Assert.assertEquals(517, message.getRepeatedGroup (1).getA());
+ Assert.assertEquals(518, message.getRepeatedNestedMessage (1).getBb());
+ Assert.assertEquals(519, message.getRepeatedForeignMessage(1).getC());
+ Assert.assertEquals(520, message.getRepeatedImportMessage (1).getD());
+ Assert.assertEquals(527, message.getRepeatedLazyMessage (1).getBb());
+
+ Assert.assertEquals(TestAllTypes.NestedEnum.FOO, message.getRepeatedNestedEnum (1));
+ Assert.assertEquals(ForeignEnum.FOREIGN_FOO, message.getRepeatedForeignEnum(1));
+ Assert.assertEquals(ImportEnum.IMPORT_FOO, message.getRepeatedImportEnum(1));
+
+ Assert.assertEquals("524", message.getRepeatedStringPiece(1));
+ Assert.assertEquals("525", message.getRepeatedCord(1));
+ }
+
+ /**
+ * Set every field of {@code message} to a unique value.
+ */
+ public static void setPackedFields(TestPackedTypes.Builder message) {
+ message.addPackedInt32 (601);
+ message.addPackedInt64 (602);
+ message.addPackedUint32 (603);
+ message.addPackedUint64 (604);
+ message.addPackedSint32 (605);
+ message.addPackedSint64 (606);
+ message.addPackedFixed32 (607);
+ message.addPackedFixed64 (608);
+ message.addPackedSfixed32(609);
+ message.addPackedSfixed64(610);
+ message.addPackedFloat (611);
+ message.addPackedDouble (612);
+ message.addPackedBool (true);
+ message.addPackedEnum (ForeignEnum.FOREIGN_BAR);
+ // Add a second one of each field.
+ message.addPackedInt32 (701);
+ message.addPackedInt64 (702);
+ message.addPackedUint32 (703);
+ message.addPackedUint64 (704);
+ message.addPackedSint32 (705);
+ message.addPackedSint64 (706);
+ message.addPackedFixed32 (707);
+ message.addPackedFixed64 (708);
+ message.addPackedSfixed32(709);
+ message.addPackedSfixed64(710);
+ message.addPackedFloat (711);
+ message.addPackedDouble (712);
+ message.addPackedBool (false);
+ message.addPackedEnum (ForeignEnum.FOREIGN_BAZ);
+ }
+
+ /**
+ * Set every field of {@code message} to a unique value. Must correspond with
+ * the values applied by {@code setPackedFields}.
+ */
+ public static void setUnpackedFields(TestUnpackedTypes.Builder message) {
+ message.addUnpackedInt32 (601);
+ message.addUnpackedInt64 (602);
+ message.addUnpackedUint32 (603);
+ message.addUnpackedUint64 (604);
+ message.addUnpackedSint32 (605);
+ message.addUnpackedSint64 (606);
+ message.addUnpackedFixed32 (607);
+ message.addUnpackedFixed64 (608);
+ message.addUnpackedSfixed32(609);
+ message.addUnpackedSfixed64(610);
+ message.addUnpackedFloat (611);
+ message.addUnpackedDouble (612);
+ message.addUnpackedBool (true);
+ message.addUnpackedEnum (ForeignEnum.FOREIGN_BAR);
+ // Add a second one of each field.
+ message.addUnpackedInt32 (701);
+ message.addUnpackedInt64 (702);
+ message.addUnpackedUint32 (703);
+ message.addUnpackedUint64 (704);
+ message.addUnpackedSint32 (705);
+ message.addUnpackedSint64 (706);
+ message.addUnpackedFixed32 (707);
+ message.addUnpackedFixed64 (708);
+ message.addUnpackedSfixed32(709);
+ message.addUnpackedSfixed64(710);
+ message.addUnpackedFloat (711);
+ message.addUnpackedDouble (712);
+ message.addUnpackedBool (false);
+ message.addUnpackedEnum (ForeignEnum.FOREIGN_BAZ);
+ }
+
+ /**
+ * Assert (using {@code junit.framework.Assert}} that all fields of
+ * {@code message} are set to the values assigned by {@code setPackedFields}.
+ */
+ public static void assertPackedFieldsSet(TestPackedTypes message) {
+ Assert.assertEquals(2, message.getPackedInt32Count ());
+ Assert.assertEquals(2, message.getPackedInt64Count ());
+ Assert.assertEquals(2, message.getPackedUint32Count ());
+ Assert.assertEquals(2, message.getPackedUint64Count ());
+ Assert.assertEquals(2, message.getPackedSint32Count ());
+ Assert.assertEquals(2, message.getPackedSint64Count ());
+ Assert.assertEquals(2, message.getPackedFixed32Count ());
+ Assert.assertEquals(2, message.getPackedFixed64Count ());
+ Assert.assertEquals(2, message.getPackedSfixed32Count());
+ Assert.assertEquals(2, message.getPackedSfixed64Count());
+ Assert.assertEquals(2, message.getPackedFloatCount ());
+ Assert.assertEquals(2, message.getPackedDoubleCount ());
+ Assert.assertEquals(2, message.getPackedBoolCount ());
+ Assert.assertEquals(2, message.getPackedEnumCount ());
+ Assert.assertEquals(601 , message.getPackedInt32 (0));
+ Assert.assertEquals(602 , message.getPackedInt64 (0));
+ Assert.assertEquals(603 , message.getPackedUint32 (0));
+ Assert.assertEquals(604 , message.getPackedUint64 (0));
+ Assert.assertEquals(605 , message.getPackedSint32 (0));
+ Assert.assertEquals(606 , message.getPackedSint64 (0));
+ Assert.assertEquals(607 , message.getPackedFixed32 (0));
+ Assert.assertEquals(608 , message.getPackedFixed64 (0));
+ Assert.assertEquals(609 , message.getPackedSfixed32(0));
+ Assert.assertEquals(610 , message.getPackedSfixed64(0));
+ Assert.assertEquals(611 , message.getPackedFloat (0), 0.0);
+ Assert.assertEquals(612 , message.getPackedDouble (0), 0.0);
+ Assert.assertEquals(true , message.getPackedBool (0));
+ Assert.assertEquals(ForeignEnum.FOREIGN_BAR, message.getPackedEnum(0));
+ Assert.assertEquals(701 , message.getPackedInt32 (1));
+ Assert.assertEquals(702 , message.getPackedInt64 (1));
+ Assert.assertEquals(703 , message.getPackedUint32 (1));
+ Assert.assertEquals(704 , message.getPackedUint64 (1));
+ Assert.assertEquals(705 , message.getPackedSint32 (1));
+ Assert.assertEquals(706 , message.getPackedSint64 (1));
+ Assert.assertEquals(707 , message.getPackedFixed32 (1));
+ Assert.assertEquals(708 , message.getPackedFixed64 (1));
+ Assert.assertEquals(709 , message.getPackedSfixed32(1));
+ Assert.assertEquals(710 , message.getPackedSfixed64(1));
+ Assert.assertEquals(711 , message.getPackedFloat (1), 0.0);
+ Assert.assertEquals(712 , message.getPackedDouble (1), 0.0);
+ Assert.assertEquals(false, message.getPackedBool (1));
+ Assert.assertEquals(ForeignEnum.FOREIGN_BAZ, message.getPackedEnum(1));
+ }
+
+ /**
+ * Assert (using {@code junit.framework.Assert}} that all fields of
+ * {@code message} are set to the values assigned by {@code setUnpackedFields}.
+ */
+ public static void assertUnpackedFieldsSet(TestUnpackedTypes message) {
+ Assert.assertEquals(2, message.getUnpackedInt32Count ());
+ Assert.assertEquals(2, message.getUnpackedInt64Count ());
+ Assert.assertEquals(2, message.getUnpackedUint32Count ());
+ Assert.assertEquals(2, message.getUnpackedUint64Count ());
+ Assert.assertEquals(2, message.getUnpackedSint32Count ());
+ Assert.assertEquals(2, message.getUnpackedSint64Count ());
+ Assert.assertEquals(2, message.getUnpackedFixed32Count ());
+ Assert.assertEquals(2, message.getUnpackedFixed64Count ());
+ Assert.assertEquals(2, message.getUnpackedSfixed32Count());
+ Assert.assertEquals(2, message.getUnpackedSfixed64Count());
+ Assert.assertEquals(2, message.getUnpackedFloatCount ());
+ Assert.assertEquals(2, message.getUnpackedDoubleCount ());
+ Assert.assertEquals(2, message.getUnpackedBoolCount ());
+ Assert.assertEquals(2, message.getUnpackedEnumCount ());
+ Assert.assertEquals(601 , message.getUnpackedInt32 (0));
+ Assert.assertEquals(602 , message.getUnpackedInt64 (0));
+ Assert.assertEquals(603 , message.getUnpackedUint32 (0));
+ Assert.assertEquals(604 , message.getUnpackedUint64 (0));
+ Assert.assertEquals(605 , message.getUnpackedSint32 (0));
+ Assert.assertEquals(606 , message.getUnpackedSint64 (0));
+ Assert.assertEquals(607 , message.getUnpackedFixed32 (0));
+ Assert.assertEquals(608 , message.getUnpackedFixed64 (0));
+ Assert.assertEquals(609 , message.getUnpackedSfixed32(0));
+ Assert.assertEquals(610 , message.getUnpackedSfixed64(0));
+ Assert.assertEquals(611 , message.getUnpackedFloat (0), 0.0);
+ Assert.assertEquals(612 , message.getUnpackedDouble (0), 0.0);
+ Assert.assertEquals(true , message.getUnpackedBool (0));
+ Assert.assertEquals(ForeignEnum.FOREIGN_BAR, message.getUnpackedEnum(0));
+ Assert.assertEquals(701 , message.getUnpackedInt32 (1));
+ Assert.assertEquals(702 , message.getUnpackedInt64 (1));
+ Assert.assertEquals(703 , message.getUnpackedUint32 (1));
+ Assert.assertEquals(704 , message.getUnpackedUint64 (1));
+ Assert.assertEquals(705 , message.getUnpackedSint32 (1));
+ Assert.assertEquals(706 , message.getUnpackedSint64 (1));
+ Assert.assertEquals(707 , message.getUnpackedFixed32 (1));
+ Assert.assertEquals(708 , message.getUnpackedFixed64 (1));
+ Assert.assertEquals(709 , message.getUnpackedSfixed32(1));
+ Assert.assertEquals(710 , message.getUnpackedSfixed64(1));
+ Assert.assertEquals(711 , message.getUnpackedFloat (1), 0.0);
+ Assert.assertEquals(712 , message.getUnpackedDouble (1), 0.0);
+ Assert.assertEquals(false, message.getUnpackedBool (1));
+ Assert.assertEquals(ForeignEnum.FOREIGN_BAZ, message.getUnpackedEnum(1));
+ }
+
+ // ===================================================================
+ // Like above, but for extensions
+
+ // Java gets confused with things like assertEquals(int, Integer): it can't
+ // decide whether to call assertEquals(int, int) or assertEquals(Object,
+ // Object). So we define these methods to help it.
+ private static void assertEqualsExactType(int a, int b) {
+ Assert.assertEquals(a, b);
+ }
+ private static void assertEqualsExactType(long a, long b) {
+ Assert.assertEquals(a, b);
+ }
+ private static void assertEqualsExactType(float a, float b) {
+ Assert.assertEquals(a, b, 0.0);
+ }
+ private static void assertEqualsExactType(double a, double b) {
+ Assert.assertEquals(a, b, 0.0);
+ }
+ private static void assertEqualsExactType(boolean a, boolean b) {
+ Assert.assertEquals(a, b);
+ }
+ private static void assertEqualsExactType(String a, String b) {
+ Assert.assertEquals(a, b);
+ }
+ private static void assertEqualsExactType(ByteString a, ByteString b) {
+ Assert.assertEquals(a, b);
+ }
+ private static void assertEqualsExactType(TestAllTypes.NestedEnum a,
+ TestAllTypes.NestedEnum b) {
+ Assert.assertEquals(a, b);
+ }
+ private static void assertEqualsExactType(ForeignEnum a, ForeignEnum b) {
+ Assert.assertEquals(a, b);
+ }
+ private static void assertEqualsExactType(ImportEnum a, ImportEnum b) {
+ Assert.assertEquals(a, b);
+ }
+ private static void assertEqualsExactType(TestAllTypesLite.NestedEnum a,
+ TestAllTypesLite.NestedEnum b) {
+ Assert.assertEquals(a, b);
+ }
+ private static void assertEqualsExactType(ForeignEnumLite a,
+ ForeignEnumLite b) {
+ Assert.assertEquals(a, b);
+ }
+ private static void assertEqualsExactType(ImportEnumLite a,
+ ImportEnumLite b) {
+ Assert.assertEquals(a, b);
+ }
+
+ /**
+ * Get an unmodifiable {@link ExtensionRegistry} containing all the
+ * extensions of {@code TestAllExtensions}.
+ */
+ public static ExtensionRegistry getExtensionRegistry() {
+ ExtensionRegistry registry = ExtensionRegistry.newInstance();
+ registerAllExtensions(registry);
+ return registry.getUnmodifiable();
+ }
+
+ public static ExtensionRegistryLite getExtensionRegistryLite() {
+ ExtensionRegistryLite registry = ExtensionRegistryLite.newInstance();
+ registerAllExtensionsLite(registry);
+ return registry.getUnmodifiable();
+ }
+
+ /**
+ * Register all of {@code TestAllExtensions}'s extensions with the
+ * given {@link ExtensionRegistry}.
+ */
+ public static void registerAllExtensions(ExtensionRegistry registry) {
+ UnittestProto.registerAllExtensions(registry);
+ registerAllExtensionsLite(registry);
+ }
+
+ public static void registerAllExtensionsLite(ExtensionRegistryLite registry) {
+ UnittestLite.registerAllExtensions(registry);
+ }
+
+ /**
+ * Set every field of {@code message} to the values expected by
+ * {@code assertAllExtensionsSet()}.
+ */
+ public static void setAllExtensions(TestAllExtensions.Builder message) {
+ message.setExtension(optionalInt32Extension , 101);
+ message.setExtension(optionalInt64Extension , 102L);
+ message.setExtension(optionalUint32Extension , 103);
+ message.setExtension(optionalUint64Extension , 104L);
+ message.setExtension(optionalSint32Extension , 105);
+ message.setExtension(optionalSint64Extension , 106L);
+ message.setExtension(optionalFixed32Extension , 107);
+ message.setExtension(optionalFixed64Extension , 108L);
+ message.setExtension(optionalSfixed32Extension, 109);
+ message.setExtension(optionalSfixed64Extension, 110L);
+ message.setExtension(optionalFloatExtension , 111F);
+ message.setExtension(optionalDoubleExtension , 112D);
+ message.setExtension(optionalBoolExtension , true);
+ message.setExtension(optionalStringExtension , "115");
+ message.setExtension(optionalBytesExtension , toBytes("116"));
+
+ message.setExtension(optionalGroupExtension,
+ OptionalGroup_extension.newBuilder().setA(117).build());
+ message.setExtension(optionalNestedMessageExtension,
+ TestAllTypes.NestedMessage.newBuilder().setBb(118).build());
+ message.setExtension(optionalForeignMessageExtension,
+ ForeignMessage.newBuilder().setC(119).build());
+ message.setExtension(optionalImportMessageExtension,
+ ImportMessage.newBuilder().setD(120).build());
+ message.setExtension(optionalPublicImportMessageExtension,
+ PublicImportMessage.newBuilder().setE(126).build());
+ message.setExtension(optionalLazyMessageExtension,
+ TestAllTypes.NestedMessage.newBuilder().setBb(127).build());
+
+ message.setExtension(optionalNestedEnumExtension, TestAllTypes.NestedEnum.BAZ);
+ message.setExtension(optionalForeignEnumExtension, ForeignEnum.FOREIGN_BAZ);
+ message.setExtension(optionalImportEnumExtension, ImportEnum.IMPORT_BAZ);
+
+ message.setExtension(optionalStringPieceExtension, "124");
+ message.setExtension(optionalCordExtension, "125");
+
+ // -----------------------------------------------------------------
+
+ message.addExtension(repeatedInt32Extension , 201);
+ message.addExtension(repeatedInt64Extension , 202L);
+ message.addExtension(repeatedUint32Extension , 203);
+ message.addExtension(repeatedUint64Extension , 204L);
+ message.addExtension(repeatedSint32Extension , 205);
+ message.addExtension(repeatedSint64Extension , 206L);
+ message.addExtension(repeatedFixed32Extension , 207);
+ message.addExtension(repeatedFixed64Extension , 208L);
+ message.addExtension(repeatedSfixed32Extension, 209);
+ message.addExtension(repeatedSfixed64Extension, 210L);
+ message.addExtension(repeatedFloatExtension , 211F);
+ message.addExtension(repeatedDoubleExtension , 212D);
+ message.addExtension(repeatedBoolExtension , true);
+ message.addExtension(repeatedStringExtension , "215");
+ message.addExtension(repeatedBytesExtension , toBytes("216"));
+
+ message.addExtension(repeatedGroupExtension,
+ RepeatedGroup_extension.newBuilder().setA(217).build());
+ message.addExtension(repeatedNestedMessageExtension,
+ TestAllTypes.NestedMessage.newBuilder().setBb(218).build());
+ message.addExtension(repeatedForeignMessageExtension,
+ ForeignMessage.newBuilder().setC(219).build());
+ message.addExtension(repeatedImportMessageExtension,
+ ImportMessage.newBuilder().setD(220).build());
+ message.addExtension(repeatedLazyMessageExtension,
+ TestAllTypes.NestedMessage.newBuilder().setBb(227).build());
+
+ message.addExtension(repeatedNestedEnumExtension, TestAllTypes.NestedEnum.BAR);
+ message.addExtension(repeatedForeignEnumExtension, ForeignEnum.FOREIGN_BAR);
+ message.addExtension(repeatedImportEnumExtension, ImportEnum.IMPORT_BAR);
+
+ message.addExtension(repeatedStringPieceExtension, "224");
+ message.addExtension(repeatedCordExtension, "225");
+
+ // Add a second one of each field.
+ message.addExtension(repeatedInt32Extension , 301);
+ message.addExtension(repeatedInt64Extension , 302L);
+ message.addExtension(repeatedUint32Extension , 303);
+ message.addExtension(repeatedUint64Extension , 304L);
+ message.addExtension(repeatedSint32Extension , 305);
+ message.addExtension(repeatedSint64Extension , 306L);
+ message.addExtension(repeatedFixed32Extension , 307);
+ message.addExtension(repeatedFixed64Extension , 308L);
+ message.addExtension(repeatedSfixed32Extension, 309);
+ message.addExtension(repeatedSfixed64Extension, 310L);
+ message.addExtension(repeatedFloatExtension , 311F);
+ message.addExtension(repeatedDoubleExtension , 312D);
+ message.addExtension(repeatedBoolExtension , false);
+ message.addExtension(repeatedStringExtension , "315");
+ message.addExtension(repeatedBytesExtension , toBytes("316"));
+
+ message.addExtension(repeatedGroupExtension,
+ RepeatedGroup_extension.newBuilder().setA(317).build());
+ message.addExtension(repeatedNestedMessageExtension,
+ TestAllTypes.NestedMessage.newBuilder().setBb(318).build());
+ message.addExtension(repeatedForeignMessageExtension,
+ ForeignMessage.newBuilder().setC(319).build());
+ message.addExtension(repeatedImportMessageExtension,
+ ImportMessage.newBuilder().setD(320).build());
+ message.addExtension(repeatedLazyMessageExtension,
+ TestAllTypes.NestedMessage.newBuilder().setBb(327).build());
+
+ message.addExtension(repeatedNestedEnumExtension, TestAllTypes.NestedEnum.BAZ);
+ message.addExtension(repeatedForeignEnumExtension, ForeignEnum.FOREIGN_BAZ);
+ message.addExtension(repeatedImportEnumExtension, ImportEnum.IMPORT_BAZ);
+
+ message.addExtension(repeatedStringPieceExtension, "324");
+ message.addExtension(repeatedCordExtension, "325");
+
+ // -----------------------------------------------------------------
+
+ message.setExtension(defaultInt32Extension , 401);
+ message.setExtension(defaultInt64Extension , 402L);
+ message.setExtension(defaultUint32Extension , 403);
+ message.setExtension(defaultUint64Extension , 404L);
+ message.setExtension(defaultSint32Extension , 405);
+ message.setExtension(defaultSint64Extension , 406L);
+ message.setExtension(defaultFixed32Extension , 407);
+ message.setExtension(defaultFixed64Extension , 408L);
+ message.setExtension(defaultSfixed32Extension, 409);
+ message.setExtension(defaultSfixed64Extension, 410L);
+ message.setExtension(defaultFloatExtension , 411F);
+ message.setExtension(defaultDoubleExtension , 412D);
+ message.setExtension(defaultBoolExtension , false);
+ message.setExtension(defaultStringExtension , "415");
+ message.setExtension(defaultBytesExtension , toBytes("416"));
+
+ message.setExtension(defaultNestedEnumExtension, TestAllTypes.NestedEnum.FOO);
+ message.setExtension(defaultForeignEnumExtension, ForeignEnum.FOREIGN_FOO);
+ message.setExtension(defaultImportEnumExtension, ImportEnum.IMPORT_FOO);
+
+ message.setExtension(defaultStringPieceExtension, "424");
+ message.setExtension(defaultCordExtension, "425");
+
+ message.setExtension(oneofUint32Extension, 601);
+ message.setExtension(oneofNestedMessageExtension,
+ TestAllTypes.NestedMessage.newBuilder().setBb(602).build());
+ message.setExtension(oneofStringExtension, "603");
+ message.setExtension(oneofBytesExtension, toBytes("604"));
+ }
+
+ // -------------------------------------------------------------------
+
+ /**
+ * Modify the repeated extensions of {@code message} to contain the values
+ * expected by {@code assertRepeatedExtensionsModified()}.
+ */
+ public static void modifyRepeatedExtensions(
+ TestAllExtensions.Builder message) {
+ message.setExtension(repeatedInt32Extension , 1, 501);
+ message.setExtension(repeatedInt64Extension , 1, 502L);
+ message.setExtension(repeatedUint32Extension , 1, 503);
+ message.setExtension(repeatedUint64Extension , 1, 504L);
+ message.setExtension(repeatedSint32Extension , 1, 505);
+ message.setExtension(repeatedSint64Extension , 1, 506L);
+ message.setExtension(repeatedFixed32Extension , 1, 507);
+ message.setExtension(repeatedFixed64Extension , 1, 508L);
+ message.setExtension(repeatedSfixed32Extension, 1, 509);
+ message.setExtension(repeatedSfixed64Extension, 1, 510L);
+ message.setExtension(repeatedFloatExtension , 1, 511F);
+ message.setExtension(repeatedDoubleExtension , 1, 512D);
+ message.setExtension(repeatedBoolExtension , 1, true);
+ message.setExtension(repeatedStringExtension , 1, "515");
+ message.setExtension(repeatedBytesExtension , 1, toBytes("516"));
+
+ message.setExtension(repeatedGroupExtension, 1,
+ RepeatedGroup_extension.newBuilder().setA(517).build());
+ message.setExtension(repeatedNestedMessageExtension, 1,
+ TestAllTypes.NestedMessage.newBuilder().setBb(518).build());
+ message.setExtension(repeatedForeignMessageExtension, 1,
+ ForeignMessage.newBuilder().setC(519).build());
+ message.setExtension(repeatedImportMessageExtension, 1,
+ ImportMessage.newBuilder().setD(520).build());
+ message.setExtension(repeatedLazyMessageExtension, 1,
+ TestAllTypes.NestedMessage.newBuilder().setBb(527).build());
+
+ message.setExtension(repeatedNestedEnumExtension , 1, TestAllTypes.NestedEnum.FOO);
+ message.setExtension(repeatedForeignEnumExtension, 1, ForeignEnum.FOREIGN_FOO);
+ message.setExtension(repeatedImportEnumExtension , 1, ImportEnum.IMPORT_FOO);
+
+ message.setExtension(repeatedStringPieceExtension, 1, "524");
+ message.setExtension(repeatedCordExtension, 1, "525");
+ }
+
+ // -------------------------------------------------------------------
+
+ /**
+ * Assert (using {@code junit.framework.Assert}} that all extensions of
+ * {@code message} are set to the values assigned by {@code setAllExtensions}.
+ */
+ public static void assertAllExtensionsSet(
+ TestAllExtensionsOrBuilder message) {
+ Assert.assertTrue(message.hasExtension(optionalInt32Extension ));
+ Assert.assertTrue(message.hasExtension(optionalInt64Extension ));
+ Assert.assertTrue(message.hasExtension(optionalUint32Extension ));
+ Assert.assertTrue(message.hasExtension(optionalUint64Extension ));
+ Assert.assertTrue(message.hasExtension(optionalSint32Extension ));
+ Assert.assertTrue(message.hasExtension(optionalSint64Extension ));
+ Assert.assertTrue(message.hasExtension(optionalFixed32Extension ));
+ Assert.assertTrue(message.hasExtension(optionalFixed64Extension ));
+ Assert.assertTrue(message.hasExtension(optionalSfixed32Extension));
+ Assert.assertTrue(message.hasExtension(optionalSfixed64Extension));
+ Assert.assertTrue(message.hasExtension(optionalFloatExtension ));
+ Assert.assertTrue(message.hasExtension(optionalDoubleExtension ));
+ Assert.assertTrue(message.hasExtension(optionalBoolExtension ));
+ Assert.assertTrue(message.hasExtension(optionalStringExtension ));
+ Assert.assertTrue(message.hasExtension(optionalBytesExtension ));
+
+ Assert.assertTrue(message.hasExtension(optionalGroupExtension ));
+ Assert.assertTrue(message.hasExtension(optionalNestedMessageExtension ));
+ Assert.assertTrue(message.hasExtension(optionalForeignMessageExtension));
+ Assert.assertTrue(message.hasExtension(optionalImportMessageExtension ));
+
+ Assert.assertTrue(message.getExtension(optionalGroupExtension ).hasA());
+ Assert.assertTrue(message.getExtension(optionalNestedMessageExtension ).hasBb());
+ Assert.assertTrue(message.getExtension(optionalForeignMessageExtension).hasC());
+ Assert.assertTrue(message.getExtension(optionalImportMessageExtension ).hasD());
+
+ Assert.assertTrue(message.hasExtension(optionalNestedEnumExtension ));
+ Assert.assertTrue(message.hasExtension(optionalForeignEnumExtension));
+ Assert.assertTrue(message.hasExtension(optionalImportEnumExtension ));
+
+ Assert.assertTrue(message.hasExtension(optionalStringPieceExtension));
+ Assert.assertTrue(message.hasExtension(optionalCordExtension));
+
+ assertEqualsExactType(101 , message.getExtension(optionalInt32Extension ));
+ assertEqualsExactType(102L , message.getExtension(optionalInt64Extension ));
+ assertEqualsExactType(103 , message.getExtension(optionalUint32Extension ));
+ assertEqualsExactType(104L , message.getExtension(optionalUint64Extension ));
+ assertEqualsExactType(105 , message.getExtension(optionalSint32Extension ));
+ assertEqualsExactType(106L , message.getExtension(optionalSint64Extension ));
+ assertEqualsExactType(107 , message.getExtension(optionalFixed32Extension ));
+ assertEqualsExactType(108L , message.getExtension(optionalFixed64Extension ));
+ assertEqualsExactType(109 , message.getExtension(optionalSfixed32Extension));
+ assertEqualsExactType(110L , message.getExtension(optionalSfixed64Extension));
+ assertEqualsExactType(111F , message.getExtension(optionalFloatExtension ));
+ assertEqualsExactType(112D , message.getExtension(optionalDoubleExtension ));
+ assertEqualsExactType(true , message.getExtension(optionalBoolExtension ));
+ assertEqualsExactType("115", message.getExtension(optionalStringExtension ));
+ assertEqualsExactType(toBytes("116"), message.getExtension(optionalBytesExtension));
+
+ assertEqualsExactType(117, message.getExtension(optionalGroupExtension ).getA());
+ assertEqualsExactType(118, message.getExtension(optionalNestedMessageExtension ).getBb());
+ assertEqualsExactType(119, message.getExtension(optionalForeignMessageExtension ).getC());
+ assertEqualsExactType(120, message.getExtension(optionalImportMessageExtension ).getD());
+ assertEqualsExactType(126, message.getExtension(optionalPublicImportMessageExtension).getE());
+ assertEqualsExactType(127, message.getExtension(optionalLazyMessageExtension ).getBb());
+
+ assertEqualsExactType(TestAllTypes.NestedEnum.BAZ,
+ message.getExtension(optionalNestedEnumExtension));
+ assertEqualsExactType(ForeignEnum.FOREIGN_BAZ,
+ message.getExtension(optionalForeignEnumExtension));
+ assertEqualsExactType(ImportEnum.IMPORT_BAZ,
+ message.getExtension(optionalImportEnumExtension));
+
+ assertEqualsExactType("124", message.getExtension(optionalStringPieceExtension));
+ assertEqualsExactType("125", message.getExtension(optionalCordExtension));
+
+ // -----------------------------------------------------------------
+
+ Assert.assertEquals(2, message.getExtensionCount(repeatedInt32Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedInt64Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedUint32Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedUint64Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedSint32Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedSint64Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedFixed32Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedFixed64Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedSfixed32Extension));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedSfixed64Extension));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedFloatExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedDoubleExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedBoolExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedStringExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedBytesExtension ));
+
+ Assert.assertEquals(2, message.getExtensionCount(repeatedGroupExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedNestedMessageExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedForeignMessageExtension));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedImportMessageExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedLazyMessageExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedNestedEnumExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedForeignEnumExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedImportEnumExtension ));
+
+ Assert.assertEquals(2, message.getExtensionCount(repeatedStringPieceExtension));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedCordExtension));
+
+ assertEqualsExactType(201 , message.getExtension(repeatedInt32Extension , 0));
+ assertEqualsExactType(202L , message.getExtension(repeatedInt64Extension , 0));
+ assertEqualsExactType(203 , message.getExtension(repeatedUint32Extension , 0));
+ assertEqualsExactType(204L , message.getExtension(repeatedUint64Extension , 0));
+ assertEqualsExactType(205 , message.getExtension(repeatedSint32Extension , 0));
+ assertEqualsExactType(206L , message.getExtension(repeatedSint64Extension , 0));
+ assertEqualsExactType(207 , message.getExtension(repeatedFixed32Extension , 0));
+ assertEqualsExactType(208L , message.getExtension(repeatedFixed64Extension , 0));
+ assertEqualsExactType(209 , message.getExtension(repeatedSfixed32Extension, 0));
+ assertEqualsExactType(210L , message.getExtension(repeatedSfixed64Extension, 0));
+ assertEqualsExactType(211F , message.getExtension(repeatedFloatExtension , 0));
+ assertEqualsExactType(212D , message.getExtension(repeatedDoubleExtension , 0));
+ assertEqualsExactType(true , message.getExtension(repeatedBoolExtension , 0));
+ assertEqualsExactType("215", message.getExtension(repeatedStringExtension , 0));
+ assertEqualsExactType(toBytes("216"), message.getExtension(repeatedBytesExtension, 0));
+
+ assertEqualsExactType(217, message.getExtension(repeatedGroupExtension , 0).getA());
+ assertEqualsExactType(218, message.getExtension(repeatedNestedMessageExtension , 0).getBb());
+ assertEqualsExactType(219, message.getExtension(repeatedForeignMessageExtension, 0).getC());
+ assertEqualsExactType(220, message.getExtension(repeatedImportMessageExtension , 0).getD());
+ assertEqualsExactType(227, message.getExtension(repeatedLazyMessageExtension , 0).getBb());
+
+ assertEqualsExactType(TestAllTypes.NestedEnum.BAR,
+ message.getExtension(repeatedNestedEnumExtension, 0));
+ assertEqualsExactType(ForeignEnum.FOREIGN_BAR,
+ message.getExtension(repeatedForeignEnumExtension, 0));
+ assertEqualsExactType(ImportEnum.IMPORT_BAR,
+ message.getExtension(repeatedImportEnumExtension, 0));
+
+ assertEqualsExactType("224", message.getExtension(repeatedStringPieceExtension, 0));
+ assertEqualsExactType("225", message.getExtension(repeatedCordExtension, 0));
+
+ assertEqualsExactType(301 , message.getExtension(repeatedInt32Extension , 1));
+ assertEqualsExactType(302L , message.getExtension(repeatedInt64Extension , 1));
+ assertEqualsExactType(303 , message.getExtension(repeatedUint32Extension , 1));
+ assertEqualsExactType(304L , message.getExtension(repeatedUint64Extension , 1));
+ assertEqualsExactType(305 , message.getExtension(repeatedSint32Extension , 1));
+ assertEqualsExactType(306L , message.getExtension(repeatedSint64Extension , 1));
+ assertEqualsExactType(307 , message.getExtension(repeatedFixed32Extension , 1));
+ assertEqualsExactType(308L , message.getExtension(repeatedFixed64Extension , 1));
+ assertEqualsExactType(309 , message.getExtension(repeatedSfixed32Extension, 1));
+ assertEqualsExactType(310L , message.getExtension(repeatedSfixed64Extension, 1));
+ assertEqualsExactType(311F , message.getExtension(repeatedFloatExtension , 1));
+ assertEqualsExactType(312D , message.getExtension(repeatedDoubleExtension , 1));
+ assertEqualsExactType(false, message.getExtension(repeatedBoolExtension , 1));
+ assertEqualsExactType("315", message.getExtension(repeatedStringExtension , 1));
+ assertEqualsExactType(toBytes("316"), message.getExtension(repeatedBytesExtension, 1));
+
+ assertEqualsExactType(317, message.getExtension(repeatedGroupExtension , 1).getA());
+ assertEqualsExactType(318, message.getExtension(repeatedNestedMessageExtension , 1).getBb());
+ assertEqualsExactType(319, message.getExtension(repeatedForeignMessageExtension, 1).getC());
+ assertEqualsExactType(320, message.getExtension(repeatedImportMessageExtension , 1).getD());
+ assertEqualsExactType(327, message.getExtension(repeatedLazyMessageExtension , 1).getBb());
+
+ assertEqualsExactType(TestAllTypes.NestedEnum.BAZ,
+ message.getExtension(repeatedNestedEnumExtension, 1));
+ assertEqualsExactType(ForeignEnum.FOREIGN_BAZ,
+ message.getExtension(repeatedForeignEnumExtension, 1));
+ assertEqualsExactType(ImportEnum.IMPORT_BAZ,
+ message.getExtension(repeatedImportEnumExtension, 1));
+
+ assertEqualsExactType("324", message.getExtension(repeatedStringPieceExtension, 1));
+ assertEqualsExactType("325", message.getExtension(repeatedCordExtension, 1));
+
+ // -----------------------------------------------------------------
+
+ Assert.assertTrue(message.hasExtension(defaultInt32Extension ));
+ Assert.assertTrue(message.hasExtension(defaultInt64Extension ));
+ Assert.assertTrue(message.hasExtension(defaultUint32Extension ));
+ Assert.assertTrue(message.hasExtension(defaultUint64Extension ));
+ Assert.assertTrue(message.hasExtension(defaultSint32Extension ));
+ Assert.assertTrue(message.hasExtension(defaultSint64Extension ));
+ Assert.assertTrue(message.hasExtension(defaultFixed32Extension ));
+ Assert.assertTrue(message.hasExtension(defaultFixed64Extension ));
+ Assert.assertTrue(message.hasExtension(defaultSfixed32Extension));
+ Assert.assertTrue(message.hasExtension(defaultSfixed64Extension));
+ Assert.assertTrue(message.hasExtension(defaultFloatExtension ));
+ Assert.assertTrue(message.hasExtension(defaultDoubleExtension ));
+ Assert.assertTrue(message.hasExtension(defaultBoolExtension ));
+ Assert.assertTrue(message.hasExtension(defaultStringExtension ));
+ Assert.assertTrue(message.hasExtension(defaultBytesExtension ));
+
+ Assert.assertTrue(message.hasExtension(defaultNestedEnumExtension ));
+ Assert.assertTrue(message.hasExtension(defaultForeignEnumExtension));
+ Assert.assertTrue(message.hasExtension(defaultImportEnumExtension ));
+
+ Assert.assertTrue(message.hasExtension(defaultStringPieceExtension));
+ Assert.assertTrue(message.hasExtension(defaultCordExtension));
+
+ assertEqualsExactType(401 , message.getExtension(defaultInt32Extension ));
+ assertEqualsExactType(402L , message.getExtension(defaultInt64Extension ));
+ assertEqualsExactType(403 , message.getExtension(defaultUint32Extension ));
+ assertEqualsExactType(404L , message.getExtension(defaultUint64Extension ));
+ assertEqualsExactType(405 , message.getExtension(defaultSint32Extension ));
+ assertEqualsExactType(406L , message.getExtension(defaultSint64Extension ));
+ assertEqualsExactType(407 , message.getExtension(defaultFixed32Extension ));
+ assertEqualsExactType(408L , message.getExtension(defaultFixed64Extension ));
+ assertEqualsExactType(409 , message.getExtension(defaultSfixed32Extension));
+ assertEqualsExactType(410L , message.getExtension(defaultSfixed64Extension));
+ assertEqualsExactType(411F , message.getExtension(defaultFloatExtension ));
+ assertEqualsExactType(412D , message.getExtension(defaultDoubleExtension ));
+ assertEqualsExactType(false, message.getExtension(defaultBoolExtension ));
+ assertEqualsExactType("415", message.getExtension(defaultStringExtension ));
+ assertEqualsExactType(toBytes("416"), message.getExtension(defaultBytesExtension));
+
+ assertEqualsExactType(TestAllTypes.NestedEnum.FOO,
+ message.getExtension(defaultNestedEnumExtension ));
+ assertEqualsExactType(ForeignEnum.FOREIGN_FOO,
+ message.getExtension(defaultForeignEnumExtension));
+ assertEqualsExactType(ImportEnum.IMPORT_FOO,
+ message.getExtension(defaultImportEnumExtension));
+
+ assertEqualsExactType("424", message.getExtension(defaultStringPieceExtension));
+ assertEqualsExactType("425", message.getExtension(defaultCordExtension));
+
+ Assert.assertTrue(message.hasExtension(oneofBytesExtension));
+
+ assertEqualsExactType(toBytes("604"), message.getExtension(oneofBytesExtension));
+ }
+
+ // -------------------------------------------------------------------
+
+ /**
+ * Assert (using {@code junit.framework.Assert}} that all extensions of
+ * {@code message} are cleared, and that getting the extensions returns their
+ * default values.
+ */
+ public static void assertExtensionsClear(TestAllExtensionsOrBuilder message) {
+ // hasBlah() should initially be false for all optional fields.
+ Assert.assertFalse(message.hasExtension(optionalInt32Extension ));
+ Assert.assertFalse(message.hasExtension(optionalInt64Extension ));
+ Assert.assertFalse(message.hasExtension(optionalUint32Extension ));
+ Assert.assertFalse(message.hasExtension(optionalUint64Extension ));
+ Assert.assertFalse(message.hasExtension(optionalSint32Extension ));
+ Assert.assertFalse(message.hasExtension(optionalSint64Extension ));
+ Assert.assertFalse(message.hasExtension(optionalFixed32Extension ));
+ Assert.assertFalse(message.hasExtension(optionalFixed64Extension ));
+ Assert.assertFalse(message.hasExtension(optionalSfixed32Extension));
+ Assert.assertFalse(message.hasExtension(optionalSfixed64Extension));
+ Assert.assertFalse(message.hasExtension(optionalFloatExtension ));
+ Assert.assertFalse(message.hasExtension(optionalDoubleExtension ));
+ Assert.assertFalse(message.hasExtension(optionalBoolExtension ));
+ Assert.assertFalse(message.hasExtension(optionalStringExtension ));
+ Assert.assertFalse(message.hasExtension(optionalBytesExtension ));
+
+ Assert.assertFalse(message.hasExtension(optionalGroupExtension ));
+ Assert.assertFalse(message.hasExtension(optionalNestedMessageExtension ));
+ Assert.assertFalse(message.hasExtension(optionalForeignMessageExtension));
+ Assert.assertFalse(message.hasExtension(optionalImportMessageExtension ));
+
+ Assert.assertFalse(message.hasExtension(optionalNestedEnumExtension ));
+ Assert.assertFalse(message.hasExtension(optionalForeignEnumExtension));
+ Assert.assertFalse(message.hasExtension(optionalImportEnumExtension ));
+
+ Assert.assertFalse(message.hasExtension(optionalStringPieceExtension));
+ Assert.assertFalse(message.hasExtension(optionalCordExtension));
+
+ // Optional fields without defaults are set to zero or something like it.
+ assertEqualsExactType(0 , message.getExtension(optionalInt32Extension ));
+ assertEqualsExactType(0L , message.getExtension(optionalInt64Extension ));
+ assertEqualsExactType(0 , message.getExtension(optionalUint32Extension ));
+ assertEqualsExactType(0L , message.getExtension(optionalUint64Extension ));
+ assertEqualsExactType(0 , message.getExtension(optionalSint32Extension ));
+ assertEqualsExactType(0L , message.getExtension(optionalSint64Extension ));
+ assertEqualsExactType(0 , message.getExtension(optionalFixed32Extension ));
+ assertEqualsExactType(0L , message.getExtension(optionalFixed64Extension ));
+ assertEqualsExactType(0 , message.getExtension(optionalSfixed32Extension));
+ assertEqualsExactType(0L , message.getExtension(optionalSfixed64Extension));
+ assertEqualsExactType(0F , message.getExtension(optionalFloatExtension ));
+ assertEqualsExactType(0D , message.getExtension(optionalDoubleExtension ));
+ assertEqualsExactType(false, message.getExtension(optionalBoolExtension ));
+ assertEqualsExactType("" , message.getExtension(optionalStringExtension ));
+ assertEqualsExactType(ByteString.EMPTY, message.getExtension(optionalBytesExtension));
+
+ // Embedded messages should also be clear.
+ Assert.assertFalse(message.getExtension(optionalGroupExtension ).hasA());
+ Assert.assertFalse(message.getExtension(optionalNestedMessageExtension ).hasBb());
+ Assert.assertFalse(message.getExtension(optionalForeignMessageExtension).hasC());
+ Assert.assertFalse(message.getExtension(optionalImportMessageExtension ).hasD());
+
+ assertEqualsExactType(0, message.getExtension(optionalGroupExtension ).getA());
+ assertEqualsExactType(0, message.getExtension(optionalNestedMessageExtension ).getBb());
+ assertEqualsExactType(0, message.getExtension(optionalForeignMessageExtension).getC());
+ assertEqualsExactType(0, message.getExtension(optionalImportMessageExtension ).getD());
+
+ // Enums without defaults are set to the first value in the enum.
+ assertEqualsExactType(TestAllTypes.NestedEnum.FOO,
+ message.getExtension(optionalNestedEnumExtension ));
+ assertEqualsExactType(ForeignEnum.FOREIGN_FOO,
+ message.getExtension(optionalForeignEnumExtension));
+ assertEqualsExactType(ImportEnum.IMPORT_FOO,
+ message.getExtension(optionalImportEnumExtension));
+
+ assertEqualsExactType("", message.getExtension(optionalStringPieceExtension));
+ assertEqualsExactType("", message.getExtension(optionalCordExtension));
+
+ // Repeated fields are empty.
+ Assert.assertEquals(0, message.getExtensionCount(repeatedInt32Extension ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedInt64Extension ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedUint32Extension ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedUint64Extension ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedSint32Extension ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedSint64Extension ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedFixed32Extension ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedFixed64Extension ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedSfixed32Extension));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedSfixed64Extension));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedFloatExtension ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedDoubleExtension ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedBoolExtension ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedStringExtension ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedBytesExtension ));
+
+ Assert.assertEquals(0, message.getExtensionCount(repeatedGroupExtension ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedNestedMessageExtension ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedForeignMessageExtension));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedImportMessageExtension ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedLazyMessageExtension ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedNestedEnumExtension ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedForeignEnumExtension ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedImportEnumExtension ));
+
+ Assert.assertEquals(0, message.getExtensionCount(repeatedStringPieceExtension));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedCordExtension));
+
+ // Repeated fields are empty via getExtension().size().
+ Assert.assertEquals(0, message.getExtension(repeatedInt32Extension ).size());
+ Assert.assertEquals(0, message.getExtension(repeatedInt64Extension ).size());
+ Assert.assertEquals(0, message.getExtension(repeatedUint32Extension ).size());
+ Assert.assertEquals(0, message.getExtension(repeatedUint64Extension ).size());
+ Assert.assertEquals(0, message.getExtension(repeatedSint32Extension ).size());
+ Assert.assertEquals(0, message.getExtension(repeatedSint64Extension ).size());
+ Assert.assertEquals(0, message.getExtension(repeatedFixed32Extension ).size());
+ Assert.assertEquals(0, message.getExtension(repeatedFixed64Extension ).size());
+ Assert.assertEquals(0, message.getExtension(repeatedSfixed32Extension).size());
+ Assert.assertEquals(0, message.getExtension(repeatedSfixed64Extension).size());
+ Assert.assertEquals(0, message.getExtension(repeatedFloatExtension ).size());
+ Assert.assertEquals(0, message.getExtension(repeatedDoubleExtension ).size());
+ Assert.assertEquals(0, message.getExtension(repeatedBoolExtension ).size());
+ Assert.assertEquals(0, message.getExtension(repeatedStringExtension ).size());
+ Assert.assertEquals(0, message.getExtension(repeatedBytesExtension ).size());
+
+ Assert.assertEquals(0, message.getExtension(repeatedGroupExtension ).size());
+ Assert.assertEquals(0, message.getExtension(repeatedNestedMessageExtension ).size());
+ Assert.assertEquals(0, message.getExtension(repeatedForeignMessageExtension).size());
+ Assert.assertEquals(0, message.getExtension(repeatedImportMessageExtension ).size());
+ Assert.assertEquals(0, message.getExtension(repeatedLazyMessageExtension ).size());
+ Assert.assertEquals(0, message.getExtension(repeatedNestedEnumExtension ).size());
+ Assert.assertEquals(0, message.getExtension(repeatedForeignEnumExtension ).size());
+ Assert.assertEquals(0, message.getExtension(repeatedImportEnumExtension ).size());
+
+ Assert.assertEquals(0, message.getExtension(repeatedStringPieceExtension).size());
+ Assert.assertEquals(0, message.getExtension(repeatedCordExtension).size());
+
+ // hasBlah() should also be false for all default fields.
+ Assert.assertFalse(message.hasExtension(defaultInt32Extension ));
+ Assert.assertFalse(message.hasExtension(defaultInt64Extension ));
+ Assert.assertFalse(message.hasExtension(defaultUint32Extension ));
+ Assert.assertFalse(message.hasExtension(defaultUint64Extension ));
+ Assert.assertFalse(message.hasExtension(defaultSint32Extension ));
+ Assert.assertFalse(message.hasExtension(defaultSint64Extension ));
+ Assert.assertFalse(message.hasExtension(defaultFixed32Extension ));
+ Assert.assertFalse(message.hasExtension(defaultFixed64Extension ));
+ Assert.assertFalse(message.hasExtension(defaultSfixed32Extension));
+ Assert.assertFalse(message.hasExtension(defaultSfixed64Extension));
+ Assert.assertFalse(message.hasExtension(defaultFloatExtension ));
+ Assert.assertFalse(message.hasExtension(defaultDoubleExtension ));
+ Assert.assertFalse(message.hasExtension(defaultBoolExtension ));
+ Assert.assertFalse(message.hasExtension(defaultStringExtension ));
+ Assert.assertFalse(message.hasExtension(defaultBytesExtension ));
+
+ Assert.assertFalse(message.hasExtension(defaultNestedEnumExtension ));
+ Assert.assertFalse(message.hasExtension(defaultForeignEnumExtension));
+ Assert.assertFalse(message.hasExtension(defaultImportEnumExtension ));
+
+ Assert.assertFalse(message.hasExtension(defaultStringPieceExtension));
+ Assert.assertFalse(message.hasExtension(defaultCordExtension));
+
+ // Fields with defaults have their default values (duh).
+ assertEqualsExactType( 41 , message.getExtension(defaultInt32Extension ));
+ assertEqualsExactType( 42L , message.getExtension(defaultInt64Extension ));
+ assertEqualsExactType( 43 , message.getExtension(defaultUint32Extension ));
+ assertEqualsExactType( 44L , message.getExtension(defaultUint64Extension ));
+ assertEqualsExactType(-45 , message.getExtension(defaultSint32Extension ));
+ assertEqualsExactType( 46L , message.getExtension(defaultSint64Extension ));
+ assertEqualsExactType( 47 , message.getExtension(defaultFixed32Extension ));
+ assertEqualsExactType( 48L , message.getExtension(defaultFixed64Extension ));
+ assertEqualsExactType( 49 , message.getExtension(defaultSfixed32Extension));
+ assertEqualsExactType(-50L , message.getExtension(defaultSfixed64Extension));
+ assertEqualsExactType( 51.5F , message.getExtension(defaultFloatExtension ));
+ assertEqualsExactType( 52e3D , message.getExtension(defaultDoubleExtension ));
+ assertEqualsExactType(true , message.getExtension(defaultBoolExtension ));
+ assertEqualsExactType("hello", message.getExtension(defaultStringExtension ));
+ assertEqualsExactType(toBytes("world"), message.getExtension(defaultBytesExtension));
+
+ assertEqualsExactType(TestAllTypes.NestedEnum.BAR,
+ message.getExtension(defaultNestedEnumExtension ));
+ assertEqualsExactType(ForeignEnum.FOREIGN_BAR,
+ message.getExtension(defaultForeignEnumExtension));
+ assertEqualsExactType(ImportEnum.IMPORT_BAR,
+ message.getExtension(defaultImportEnumExtension));
+
+ assertEqualsExactType("abc", message.getExtension(defaultStringPieceExtension));
+ assertEqualsExactType("123", message.getExtension(defaultCordExtension));
+
+ Assert.assertFalse(message.hasExtension(oneofUint32Extension));
+ Assert.assertFalse(message.hasExtension(oneofNestedMessageExtension));
+ Assert.assertFalse(message.hasExtension(oneofStringExtension));
+ Assert.assertFalse(message.hasExtension(oneofBytesExtension));
+ }
+
+ // -------------------------------------------------------------------
+
+ /**
+ * Assert (using {@code junit.framework.Assert}} that all extensions of
+ * {@code message} are set to the values assigned by {@code setAllExtensions}
+ * followed by {@code modifyRepeatedExtensions}.
+ */
+ public static void assertRepeatedExtensionsModified(
+ TestAllExtensionsOrBuilder message) {
+ // ModifyRepeatedFields only sets the second repeated element of each
+ // field. In addition to verifying this, we also verify that the first
+ // element and size were *not* modified.
+ Assert.assertEquals(2, message.getExtensionCount(repeatedInt32Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedInt64Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedUint32Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedUint64Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedSint32Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedSint64Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedFixed32Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedFixed64Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedSfixed32Extension));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedSfixed64Extension));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedFloatExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedDoubleExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedBoolExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedStringExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedBytesExtension ));
+
+ Assert.assertEquals(2, message.getExtensionCount(repeatedGroupExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedNestedMessageExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedForeignMessageExtension));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedImportMessageExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedLazyMessageExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedNestedEnumExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedForeignEnumExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedImportEnumExtension ));
+
+ Assert.assertEquals(2, message.getExtensionCount(repeatedStringPieceExtension));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedCordExtension));
+
+ assertEqualsExactType(201 , message.getExtension(repeatedInt32Extension , 0));
+ assertEqualsExactType(202L , message.getExtension(repeatedInt64Extension , 0));
+ assertEqualsExactType(203 , message.getExtension(repeatedUint32Extension , 0));
+ assertEqualsExactType(204L , message.getExtension(repeatedUint64Extension , 0));
+ assertEqualsExactType(205 , message.getExtension(repeatedSint32Extension , 0));
+ assertEqualsExactType(206L , message.getExtension(repeatedSint64Extension , 0));
+ assertEqualsExactType(207 , message.getExtension(repeatedFixed32Extension , 0));
+ assertEqualsExactType(208L , message.getExtension(repeatedFixed64Extension , 0));
+ assertEqualsExactType(209 , message.getExtension(repeatedSfixed32Extension, 0));
+ assertEqualsExactType(210L , message.getExtension(repeatedSfixed64Extension, 0));
+ assertEqualsExactType(211F , message.getExtension(repeatedFloatExtension , 0));
+ assertEqualsExactType(212D , message.getExtension(repeatedDoubleExtension , 0));
+ assertEqualsExactType(true , message.getExtension(repeatedBoolExtension , 0));
+ assertEqualsExactType("215", message.getExtension(repeatedStringExtension , 0));
+ assertEqualsExactType(toBytes("216"), message.getExtension(repeatedBytesExtension, 0));
+
+ assertEqualsExactType(217, message.getExtension(repeatedGroupExtension , 0).getA());
+ assertEqualsExactType(218, message.getExtension(repeatedNestedMessageExtension , 0).getBb());
+ assertEqualsExactType(219, message.getExtension(repeatedForeignMessageExtension, 0).getC());
+ assertEqualsExactType(220, message.getExtension(repeatedImportMessageExtension , 0).getD());
+ assertEqualsExactType(227, message.getExtension(repeatedLazyMessageExtension , 0).getBb());
+
+ assertEqualsExactType(TestAllTypes.NestedEnum.BAR,
+ message.getExtension(repeatedNestedEnumExtension, 0));
+ assertEqualsExactType(ForeignEnum.FOREIGN_BAR,
+ message.getExtension(repeatedForeignEnumExtension, 0));
+ assertEqualsExactType(ImportEnum.IMPORT_BAR,
+ message.getExtension(repeatedImportEnumExtension, 0));
+
+ assertEqualsExactType("224", message.getExtension(repeatedStringPieceExtension, 0));
+ assertEqualsExactType("225", message.getExtension(repeatedCordExtension, 0));
+
+ // Actually verify the second (modified) elements now.
+ assertEqualsExactType(501 , message.getExtension(repeatedInt32Extension , 1));
+ assertEqualsExactType(502L , message.getExtension(repeatedInt64Extension , 1));
+ assertEqualsExactType(503 , message.getExtension(repeatedUint32Extension , 1));
+ assertEqualsExactType(504L , message.getExtension(repeatedUint64Extension , 1));
+ assertEqualsExactType(505 , message.getExtension(repeatedSint32Extension , 1));
+ assertEqualsExactType(506L , message.getExtension(repeatedSint64Extension , 1));
+ assertEqualsExactType(507 , message.getExtension(repeatedFixed32Extension , 1));
+ assertEqualsExactType(508L , message.getExtension(repeatedFixed64Extension , 1));
+ assertEqualsExactType(509 , message.getExtension(repeatedSfixed32Extension, 1));
+ assertEqualsExactType(510L , message.getExtension(repeatedSfixed64Extension, 1));
+ assertEqualsExactType(511F , message.getExtension(repeatedFloatExtension , 1));
+ assertEqualsExactType(512D , message.getExtension(repeatedDoubleExtension , 1));
+ assertEqualsExactType(true , message.getExtension(repeatedBoolExtension , 1));
+ assertEqualsExactType("515", message.getExtension(repeatedStringExtension , 1));
+ assertEqualsExactType(toBytes("516"), message.getExtension(repeatedBytesExtension, 1));
+
+ assertEqualsExactType(517, message.getExtension(repeatedGroupExtension , 1).getA());
+ assertEqualsExactType(518, message.getExtension(repeatedNestedMessageExtension , 1).getBb());
+ assertEqualsExactType(519, message.getExtension(repeatedForeignMessageExtension, 1).getC());
+ assertEqualsExactType(520, message.getExtension(repeatedImportMessageExtension , 1).getD());
+ assertEqualsExactType(527, message.getExtension(repeatedLazyMessageExtension , 1).getBb());
+
+ assertEqualsExactType(TestAllTypes.NestedEnum.FOO,
+ message.getExtension(repeatedNestedEnumExtension, 1));
+ assertEqualsExactType(ForeignEnum.FOREIGN_FOO,
+ message.getExtension(repeatedForeignEnumExtension, 1));
+ assertEqualsExactType(ImportEnum.IMPORT_FOO,
+ message.getExtension(repeatedImportEnumExtension, 1));
+
+ assertEqualsExactType("524", message.getExtension(repeatedStringPieceExtension, 1));
+ assertEqualsExactType("525", message.getExtension(repeatedCordExtension, 1));
+ }
+
+ public static void setPackedExtensions(TestPackedExtensions.Builder message) {
+ message.addExtension(packedInt32Extension , 601);
+ message.addExtension(packedInt64Extension , 602L);
+ message.addExtension(packedUint32Extension , 603);
+ message.addExtension(packedUint64Extension , 604L);
+ message.addExtension(packedSint32Extension , 605);
+ message.addExtension(packedSint64Extension , 606L);
+ message.addExtension(packedFixed32Extension , 607);
+ message.addExtension(packedFixed64Extension , 608L);
+ message.addExtension(packedSfixed32Extension, 609);
+ message.addExtension(packedSfixed64Extension, 610L);
+ message.addExtension(packedFloatExtension , 611F);
+ message.addExtension(packedDoubleExtension , 612D);
+ message.addExtension(packedBoolExtension , true);
+ message.addExtension(packedEnumExtension, ForeignEnum.FOREIGN_BAR);
+ // Add a second one of each field.
+ message.addExtension(packedInt32Extension , 701);
+ message.addExtension(packedInt64Extension , 702L);
+ message.addExtension(packedUint32Extension , 703);
+ message.addExtension(packedUint64Extension , 704L);
+ message.addExtension(packedSint32Extension , 705);
+ message.addExtension(packedSint64Extension , 706L);
+ message.addExtension(packedFixed32Extension , 707);
+ message.addExtension(packedFixed64Extension , 708L);
+ message.addExtension(packedSfixed32Extension, 709);
+ message.addExtension(packedSfixed64Extension, 710L);
+ message.addExtension(packedFloatExtension , 711F);
+ message.addExtension(packedDoubleExtension , 712D);
+ message.addExtension(packedBoolExtension , false);
+ message.addExtension(packedEnumExtension, ForeignEnum.FOREIGN_BAZ);
+ }
+
+ public static void assertPackedExtensionsSet(TestPackedExtensions message) {
+ Assert.assertEquals(2, message.getExtensionCount(packedInt32Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(packedInt64Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(packedUint32Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(packedUint64Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(packedSint32Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(packedSint64Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(packedFixed32Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(packedFixed64Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(packedSfixed32Extension));
+ Assert.assertEquals(2, message.getExtensionCount(packedSfixed64Extension));
+ Assert.assertEquals(2, message.getExtensionCount(packedFloatExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(packedDoubleExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(packedBoolExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(packedEnumExtension));
+ assertEqualsExactType(601 , message.getExtension(packedInt32Extension , 0));
+ assertEqualsExactType(602L , message.getExtension(packedInt64Extension , 0));
+ assertEqualsExactType(603 , message.getExtension(packedUint32Extension , 0));
+ assertEqualsExactType(604L , message.getExtension(packedUint64Extension , 0));
+ assertEqualsExactType(605 , message.getExtension(packedSint32Extension , 0));
+ assertEqualsExactType(606L , message.getExtension(packedSint64Extension , 0));
+ assertEqualsExactType(607 , message.getExtension(packedFixed32Extension , 0));
+ assertEqualsExactType(608L , message.getExtension(packedFixed64Extension , 0));
+ assertEqualsExactType(609 , message.getExtension(packedSfixed32Extension, 0));
+ assertEqualsExactType(610L , message.getExtension(packedSfixed64Extension, 0));
+ assertEqualsExactType(611F , message.getExtension(packedFloatExtension , 0));
+ assertEqualsExactType(612D , message.getExtension(packedDoubleExtension , 0));
+ assertEqualsExactType(true , message.getExtension(packedBoolExtension , 0));
+ assertEqualsExactType(ForeignEnum.FOREIGN_BAR,
+ message.getExtension(packedEnumExtension, 0));
+ assertEqualsExactType(701 , message.getExtension(packedInt32Extension , 1));
+ assertEqualsExactType(702L , message.getExtension(packedInt64Extension , 1));
+ assertEqualsExactType(703 , message.getExtension(packedUint32Extension , 1));
+ assertEqualsExactType(704L , message.getExtension(packedUint64Extension , 1));
+ assertEqualsExactType(705 , message.getExtension(packedSint32Extension , 1));
+ assertEqualsExactType(706L , message.getExtension(packedSint64Extension , 1));
+ assertEqualsExactType(707 , message.getExtension(packedFixed32Extension , 1));
+ assertEqualsExactType(708L , message.getExtension(packedFixed64Extension , 1));
+ assertEqualsExactType(709 , message.getExtension(packedSfixed32Extension, 1));
+ assertEqualsExactType(710L , message.getExtension(packedSfixed64Extension, 1));
+ assertEqualsExactType(711F , message.getExtension(packedFloatExtension , 1));
+ assertEqualsExactType(712D , message.getExtension(packedDoubleExtension , 1));
+ assertEqualsExactType(false, message.getExtension(packedBoolExtension , 1));
+ assertEqualsExactType(ForeignEnum.FOREIGN_BAZ,
+ message.getExtension(packedEnumExtension, 1));
+ }
+
+ // ===================================================================
+ // Lite extensions
+
+ /**
+ * Set every field of {@code message} to the values expected by
+ * {@code assertAllExtensionsSet()}.
+ */
+ public static void setAllExtensions(TestAllExtensionsLite.Builder message) {
+ message.setExtension(optionalInt32ExtensionLite , 101);
+ message.setExtension(optionalInt64ExtensionLite , 102L);
+ message.setExtension(optionalUint32ExtensionLite , 103);
+ message.setExtension(optionalUint64ExtensionLite , 104L);
+ message.setExtension(optionalSint32ExtensionLite , 105);
+ message.setExtension(optionalSint64ExtensionLite , 106L);
+ message.setExtension(optionalFixed32ExtensionLite , 107);
+ message.setExtension(optionalFixed64ExtensionLite , 108L);
+ message.setExtension(optionalSfixed32ExtensionLite, 109);
+ message.setExtension(optionalSfixed64ExtensionLite, 110L);
+ message.setExtension(optionalFloatExtensionLite , 111F);
+ message.setExtension(optionalDoubleExtensionLite , 112D);
+ message.setExtension(optionalBoolExtensionLite , true);
+ message.setExtension(optionalStringExtensionLite , "115");
+ message.setExtension(optionalBytesExtensionLite , toBytes("116"));
+
+ message.setExtension(optionalGroupExtensionLite,
+ OptionalGroup_extension_lite.newBuilder().setA(117).build());
+ message.setExtension(optionalNestedMessageExtensionLite,
+ TestAllTypesLite.NestedMessage.newBuilder().setBb(118).build());
+ message.setExtension(optionalForeignMessageExtensionLite,
+ ForeignMessageLite.newBuilder().setC(119).build());
+ message.setExtension(optionalImportMessageExtensionLite,
+ ImportMessageLite.newBuilder().setD(120).build());
+ message.setExtension(optionalPublicImportMessageExtensionLite,
+ PublicImportMessageLite.newBuilder().setE(126).build());
+ message.setExtension(optionalLazyMessageExtensionLite,
+ TestAllTypesLite.NestedMessage.newBuilder().setBb(127).build());
+
+ message.setExtension(optionalNestedEnumExtensionLite, TestAllTypesLite.NestedEnum.BAZ);
+ message.setExtension(optionalForeignEnumExtensionLite, ForeignEnumLite.FOREIGN_LITE_BAZ);
+ message.setExtension(optionalImportEnumExtensionLite, ImportEnumLite.IMPORT_LITE_BAZ);
+
+ message.setExtension(optionalStringPieceExtensionLite, "124");
+ message.setExtension(optionalCordExtensionLite, "125");
+
+ // -----------------------------------------------------------------
+
+ message.addExtension(repeatedInt32ExtensionLite , 201);
+ message.addExtension(repeatedInt64ExtensionLite , 202L);
+ message.addExtension(repeatedUint32ExtensionLite , 203);
+ message.addExtension(repeatedUint64ExtensionLite , 204L);
+ message.addExtension(repeatedSint32ExtensionLite , 205);
+ message.addExtension(repeatedSint64ExtensionLite , 206L);
+ message.addExtension(repeatedFixed32ExtensionLite , 207);
+ message.addExtension(repeatedFixed64ExtensionLite , 208L);
+ message.addExtension(repeatedSfixed32ExtensionLite, 209);
+ message.addExtension(repeatedSfixed64ExtensionLite, 210L);
+ message.addExtension(repeatedFloatExtensionLite , 211F);
+ message.addExtension(repeatedDoubleExtensionLite , 212D);
+ message.addExtension(repeatedBoolExtensionLite , true);
+ message.addExtension(repeatedStringExtensionLite , "215");
+ message.addExtension(repeatedBytesExtensionLite , toBytes("216"));
+
+ message.addExtension(repeatedGroupExtensionLite,
+ RepeatedGroup_extension_lite.newBuilder().setA(217).build());
+ message.addExtension(repeatedNestedMessageExtensionLite,
+ TestAllTypesLite.NestedMessage.newBuilder().setBb(218).build());
+ message.addExtension(repeatedForeignMessageExtensionLite,
+ ForeignMessageLite.newBuilder().setC(219).build());
+ message.addExtension(repeatedImportMessageExtensionLite,
+ ImportMessageLite.newBuilder().setD(220).build());
+ message.addExtension(repeatedLazyMessageExtensionLite,
+ TestAllTypesLite.NestedMessage.newBuilder().setBb(227).build());
+
+ message.addExtension(repeatedNestedEnumExtensionLite, TestAllTypesLite.NestedEnum.BAR);
+ message.addExtension(repeatedForeignEnumExtensionLite, ForeignEnumLite.FOREIGN_LITE_BAR);
+ message.addExtension(repeatedImportEnumExtensionLite, ImportEnumLite.IMPORT_LITE_BAR);
+
+ message.addExtension(repeatedStringPieceExtensionLite, "224");
+ message.addExtension(repeatedCordExtensionLite, "225");
+
+ // Add a second one of each field.
+ message.addExtension(repeatedInt32ExtensionLite , 301);
+ message.addExtension(repeatedInt64ExtensionLite , 302L);
+ message.addExtension(repeatedUint32ExtensionLite , 303);
+ message.addExtension(repeatedUint64ExtensionLite , 304L);
+ message.addExtension(repeatedSint32ExtensionLite , 305);
+ message.addExtension(repeatedSint64ExtensionLite , 306L);
+ message.addExtension(repeatedFixed32ExtensionLite , 307);
+ message.addExtension(repeatedFixed64ExtensionLite , 308L);
+ message.addExtension(repeatedSfixed32ExtensionLite, 309);
+ message.addExtension(repeatedSfixed64ExtensionLite, 310L);
+ message.addExtension(repeatedFloatExtensionLite , 311F);
+ message.addExtension(repeatedDoubleExtensionLite , 312D);
+ message.addExtension(repeatedBoolExtensionLite , false);
+ message.addExtension(repeatedStringExtensionLite , "315");
+ message.addExtension(repeatedBytesExtensionLite , toBytes("316"));
+
+ message.addExtension(repeatedGroupExtensionLite,
+ RepeatedGroup_extension_lite.newBuilder().setA(317).build());
+ message.addExtension(repeatedNestedMessageExtensionLite,
+ TestAllTypesLite.NestedMessage.newBuilder().setBb(318).build());
+ message.addExtension(repeatedForeignMessageExtensionLite,
+ ForeignMessageLite.newBuilder().setC(319).build());
+ message.addExtension(repeatedImportMessageExtensionLite,
+ ImportMessageLite.newBuilder().setD(320).build());
+ message.addExtension(repeatedLazyMessageExtensionLite,
+ TestAllTypesLite.NestedMessage.newBuilder().setBb(327).build());
+
+ message.addExtension(repeatedNestedEnumExtensionLite, TestAllTypesLite.NestedEnum.BAZ);
+ message.addExtension(repeatedForeignEnumExtensionLite, ForeignEnumLite.FOREIGN_LITE_BAZ);
+ message.addExtension(repeatedImportEnumExtensionLite, ImportEnumLite.IMPORT_LITE_BAZ);
+
+ message.addExtension(repeatedStringPieceExtensionLite, "324");
+ message.addExtension(repeatedCordExtensionLite, "325");
+
+ // -----------------------------------------------------------------
+
+ message.setExtension(defaultInt32ExtensionLite , 401);
+ message.setExtension(defaultInt64ExtensionLite , 402L);
+ message.setExtension(defaultUint32ExtensionLite , 403);
+ message.setExtension(defaultUint64ExtensionLite , 404L);
+ message.setExtension(defaultSint32ExtensionLite , 405);
+ message.setExtension(defaultSint64ExtensionLite , 406L);
+ message.setExtension(defaultFixed32ExtensionLite , 407);
+ message.setExtension(defaultFixed64ExtensionLite , 408L);
+ message.setExtension(defaultSfixed32ExtensionLite, 409);
+ message.setExtension(defaultSfixed64ExtensionLite, 410L);
+ message.setExtension(defaultFloatExtensionLite , 411F);
+ message.setExtension(defaultDoubleExtensionLite , 412D);
+ message.setExtension(defaultBoolExtensionLite , false);
+ message.setExtension(defaultStringExtensionLite , "415");
+ message.setExtension(defaultBytesExtensionLite , toBytes("416"));
+
+ message.setExtension(defaultNestedEnumExtensionLite, TestAllTypesLite.NestedEnum.FOO);
+ message.setExtension(defaultForeignEnumExtensionLite, ForeignEnumLite.FOREIGN_LITE_FOO);
+ message.setExtension(defaultImportEnumExtensionLite, ImportEnumLite.IMPORT_LITE_FOO);
+
+ message.setExtension(defaultStringPieceExtensionLite, "424");
+ message.setExtension(defaultCordExtensionLite, "425");
+
+ message.setExtension(oneofUint32ExtensionLite, 601);
+ message.setExtension(oneofNestedMessageExtensionLite,
+ TestAllTypesLite.NestedMessage.newBuilder().setBb(602).build());
+ message.setExtension(oneofStringExtensionLite, "603");
+ message.setExtension(oneofBytesExtensionLite, toBytes("604"));
+ }
+
+ // -------------------------------------------------------------------
+
+ /**
+ * Modify the repeated extensions of {@code message} to contain the values
+ * expected by {@code assertRepeatedExtensionsModified()}.
+ */
+ public static void modifyRepeatedExtensions(
+ TestAllExtensionsLite.Builder message) {
+ message.setExtension(repeatedInt32ExtensionLite , 1, 501);
+ message.setExtension(repeatedInt64ExtensionLite , 1, 502L);
+ message.setExtension(repeatedUint32ExtensionLite , 1, 503);
+ message.setExtension(repeatedUint64ExtensionLite , 1, 504L);
+ message.setExtension(repeatedSint32ExtensionLite , 1, 505);
+ message.setExtension(repeatedSint64ExtensionLite , 1, 506L);
+ message.setExtension(repeatedFixed32ExtensionLite , 1, 507);
+ message.setExtension(repeatedFixed64ExtensionLite , 1, 508L);
+ message.setExtension(repeatedSfixed32ExtensionLite, 1, 509);
+ message.setExtension(repeatedSfixed64ExtensionLite, 1, 510L);
+ message.setExtension(repeatedFloatExtensionLite , 1, 511F);
+ message.setExtension(repeatedDoubleExtensionLite , 1, 512D);
+ message.setExtension(repeatedBoolExtensionLite , 1, true);
+ message.setExtension(repeatedStringExtensionLite , 1, "515");
+ message.setExtension(repeatedBytesExtensionLite , 1, toBytes("516"));
+
+ message.setExtension(repeatedGroupExtensionLite, 1,
+ RepeatedGroup_extension_lite.newBuilder().setA(517).build());
+ message.setExtension(repeatedNestedMessageExtensionLite, 1,
+ TestAllTypesLite.NestedMessage.newBuilder().setBb(518).build());
+ message.setExtension(repeatedForeignMessageExtensionLite, 1,
+ ForeignMessageLite.newBuilder().setC(519).build());
+ message.setExtension(repeatedImportMessageExtensionLite, 1,
+ ImportMessageLite.newBuilder().setD(520).build());
+ message.setExtension(repeatedLazyMessageExtensionLite, 1,
+ TestAllTypesLite.NestedMessage.newBuilder().setBb(527).build());
+
+ message.setExtension(repeatedNestedEnumExtensionLite , 1, TestAllTypesLite.NestedEnum.FOO);
+ message.setExtension(repeatedForeignEnumExtensionLite, 1, ForeignEnumLite.FOREIGN_LITE_FOO);
+ message.setExtension(repeatedImportEnumExtensionLite , 1, ImportEnumLite.IMPORT_LITE_FOO);
+
+ message.setExtension(repeatedStringPieceExtensionLite, 1, "524");
+ message.setExtension(repeatedCordExtensionLite, 1, "525");
+ }
+
+ // -------------------------------------------------------------------
+
+ /**
+ * Assert (using {@code junit.framework.Assert}} that all extensions of
+ * {@code message} are set to the values assigned by {@code setAllExtensions}.
+ */
+ public static void assertAllExtensionsSet(
+ TestAllExtensionsLiteOrBuilder message) {
+ Assert.assertTrue(message.hasExtension(optionalInt32ExtensionLite ));
+ Assert.assertTrue(message.hasExtension(optionalInt64ExtensionLite ));
+ Assert.assertTrue(message.hasExtension(optionalUint32ExtensionLite ));
+ Assert.assertTrue(message.hasExtension(optionalUint64ExtensionLite ));
+ Assert.assertTrue(message.hasExtension(optionalSint32ExtensionLite ));
+ Assert.assertTrue(message.hasExtension(optionalSint64ExtensionLite ));
+ Assert.assertTrue(message.hasExtension(optionalFixed32ExtensionLite ));
+ Assert.assertTrue(message.hasExtension(optionalFixed64ExtensionLite ));
+ Assert.assertTrue(message.hasExtension(optionalSfixed32ExtensionLite));
+ Assert.assertTrue(message.hasExtension(optionalSfixed64ExtensionLite));
+ Assert.assertTrue(message.hasExtension(optionalFloatExtensionLite ));
+ Assert.assertTrue(message.hasExtension(optionalDoubleExtensionLite ));
+ Assert.assertTrue(message.hasExtension(optionalBoolExtensionLite ));
+ Assert.assertTrue(message.hasExtension(optionalStringExtensionLite ));
+ Assert.assertTrue(message.hasExtension(optionalBytesExtensionLite ));
+
+ Assert.assertTrue(message.hasExtension(optionalGroupExtensionLite ));
+ Assert.assertTrue(message.hasExtension(optionalNestedMessageExtensionLite ));
+ Assert.assertTrue(message.hasExtension(optionalForeignMessageExtensionLite));
+ Assert.assertTrue(message.hasExtension(optionalImportMessageExtensionLite ));
+
+ Assert.assertTrue(message.getExtension(optionalGroupExtensionLite ).hasA());
+ Assert.assertTrue(message.getExtension(optionalNestedMessageExtensionLite ).hasBb());
+ Assert.assertTrue(message.getExtension(optionalForeignMessageExtensionLite).hasC());
+ Assert.assertTrue(message.getExtension(optionalImportMessageExtensionLite ).hasD());
+
+ Assert.assertTrue(message.hasExtension(optionalNestedEnumExtensionLite ));
+ Assert.assertTrue(message.hasExtension(optionalForeignEnumExtensionLite));
+ Assert.assertTrue(message.hasExtension(optionalImportEnumExtensionLite ));
+
+ Assert.assertTrue(message.hasExtension(optionalStringPieceExtensionLite));
+ Assert.assertTrue(message.hasExtension(optionalCordExtensionLite));
+
+ assertEqualsExactType(101 , message.getExtension(optionalInt32ExtensionLite ));
+ assertEqualsExactType(102L , message.getExtension(optionalInt64ExtensionLite ));
+ assertEqualsExactType(103 , message.getExtension(optionalUint32ExtensionLite ));
+ assertEqualsExactType(104L , message.getExtension(optionalUint64ExtensionLite ));
+ assertEqualsExactType(105 , message.getExtension(optionalSint32ExtensionLite ));
+ assertEqualsExactType(106L , message.getExtension(optionalSint64ExtensionLite ));
+ assertEqualsExactType(107 , message.getExtension(optionalFixed32ExtensionLite ));
+ assertEqualsExactType(108L , message.getExtension(optionalFixed64ExtensionLite ));
+ assertEqualsExactType(109 , message.getExtension(optionalSfixed32ExtensionLite));
+ assertEqualsExactType(110L , message.getExtension(optionalSfixed64ExtensionLite));
+ assertEqualsExactType(111F , message.getExtension(optionalFloatExtensionLite ));
+ assertEqualsExactType(112D , message.getExtension(optionalDoubleExtensionLite ));
+ assertEqualsExactType(true , message.getExtension(optionalBoolExtensionLite ));
+ assertEqualsExactType("115", message.getExtension(optionalStringExtensionLite ));
+ assertEqualsExactType(toBytes("116"), message.getExtension(optionalBytesExtensionLite));
+
+ assertEqualsExactType(117, message.getExtension(optionalGroupExtensionLite ).getA());
+ assertEqualsExactType(118, message.getExtension(optionalNestedMessageExtensionLite ).getBb());
+ assertEqualsExactType(119, message.getExtension(optionalForeignMessageExtensionLite).getC());
+ assertEqualsExactType(120, message.getExtension(optionalImportMessageExtensionLite ).getD());
+ assertEqualsExactType(126, message.getExtension(
+ optionalPublicImportMessageExtensionLite).getE());
+ assertEqualsExactType(127, message.getExtension(optionalLazyMessageExtensionLite).getBb());
+
+ assertEqualsExactType(TestAllTypesLite.NestedEnum.BAZ,
+ message.getExtension(optionalNestedEnumExtensionLite));
+ assertEqualsExactType(ForeignEnumLite.FOREIGN_LITE_BAZ,
+ message.getExtension(optionalForeignEnumExtensionLite));
+ assertEqualsExactType(ImportEnumLite.IMPORT_LITE_BAZ,
+ message.getExtension(optionalImportEnumExtensionLite));
+
+ assertEqualsExactType("124", message.getExtension(optionalStringPieceExtensionLite));
+ assertEqualsExactType("125", message.getExtension(optionalCordExtensionLite));
+
+ // -----------------------------------------------------------------
+
+ Assert.assertEquals(2, message.getExtensionCount(repeatedInt32ExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedInt64ExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedUint32ExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedUint64ExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedSint32ExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedSint64ExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedFixed32ExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedFixed64ExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedSfixed32ExtensionLite));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedSfixed64ExtensionLite));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedFloatExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedDoubleExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedBoolExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedStringExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedBytesExtensionLite ));
+
+ Assert.assertEquals(2, message.getExtensionCount(repeatedGroupExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedNestedMessageExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedForeignMessageExtensionLite));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedImportMessageExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedLazyMessageExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedNestedEnumExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedForeignEnumExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedImportEnumExtensionLite ));
+
+ Assert.assertEquals(2, message.getExtensionCount(repeatedStringPieceExtensionLite));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedCordExtensionLite));
+
+ assertEqualsExactType(201 , message.getExtension(repeatedInt32ExtensionLite , 0));
+ assertEqualsExactType(202L , message.getExtension(repeatedInt64ExtensionLite , 0));
+ assertEqualsExactType(203 , message.getExtension(repeatedUint32ExtensionLite , 0));
+ assertEqualsExactType(204L , message.getExtension(repeatedUint64ExtensionLite , 0));
+ assertEqualsExactType(205 , message.getExtension(repeatedSint32ExtensionLite , 0));
+ assertEqualsExactType(206L , message.getExtension(repeatedSint64ExtensionLite , 0));
+ assertEqualsExactType(207 , message.getExtension(repeatedFixed32ExtensionLite , 0));
+ assertEqualsExactType(208L , message.getExtension(repeatedFixed64ExtensionLite , 0));
+ assertEqualsExactType(209 , message.getExtension(repeatedSfixed32ExtensionLite, 0));
+ assertEqualsExactType(210L , message.getExtension(repeatedSfixed64ExtensionLite, 0));
+ assertEqualsExactType(211F , message.getExtension(repeatedFloatExtensionLite , 0));
+ assertEqualsExactType(212D , message.getExtension(repeatedDoubleExtensionLite , 0));
+ assertEqualsExactType(true , message.getExtension(repeatedBoolExtensionLite , 0));
+ assertEqualsExactType("215", message.getExtension(repeatedStringExtensionLite , 0));
+ assertEqualsExactType(toBytes("216"), message.getExtension(repeatedBytesExtensionLite, 0));
+
+ assertEqualsExactType(217, message.getExtension(repeatedGroupExtensionLite ,0).getA());
+ assertEqualsExactType(218, message.getExtension(repeatedNestedMessageExtensionLite ,0).getBb());
+ assertEqualsExactType(219, message.getExtension(repeatedForeignMessageExtensionLite,0).getC());
+ assertEqualsExactType(220, message.getExtension(repeatedImportMessageExtensionLite ,0).getD());
+ assertEqualsExactType(227, message.getExtension(repeatedLazyMessageExtensionLite ,0).getBb());
+
+ assertEqualsExactType(TestAllTypesLite.NestedEnum.BAR,
+ message.getExtension(repeatedNestedEnumExtensionLite, 0));
+ assertEqualsExactType(ForeignEnumLite.FOREIGN_LITE_BAR,
+ message.getExtension(repeatedForeignEnumExtensionLite, 0));
+ assertEqualsExactType(ImportEnumLite.IMPORT_LITE_BAR,
+ message.getExtension(repeatedImportEnumExtensionLite, 0));
+
+ assertEqualsExactType("224", message.getExtension(repeatedStringPieceExtensionLite, 0));
+ assertEqualsExactType("225", message.getExtension(repeatedCordExtensionLite, 0));
+
+ assertEqualsExactType(301 , message.getExtension(repeatedInt32ExtensionLite , 1));
+ assertEqualsExactType(302L , message.getExtension(repeatedInt64ExtensionLite , 1));
+ assertEqualsExactType(303 , message.getExtension(repeatedUint32ExtensionLite , 1));
+ assertEqualsExactType(304L , message.getExtension(repeatedUint64ExtensionLite , 1));
+ assertEqualsExactType(305 , message.getExtension(repeatedSint32ExtensionLite , 1));
+ assertEqualsExactType(306L , message.getExtension(repeatedSint64ExtensionLite , 1));
+ assertEqualsExactType(307 , message.getExtension(repeatedFixed32ExtensionLite , 1));
+ assertEqualsExactType(308L , message.getExtension(repeatedFixed64ExtensionLite , 1));
+ assertEqualsExactType(309 , message.getExtension(repeatedSfixed32ExtensionLite, 1));
+ assertEqualsExactType(310L , message.getExtension(repeatedSfixed64ExtensionLite, 1));
+ assertEqualsExactType(311F , message.getExtension(repeatedFloatExtensionLite , 1));
+ assertEqualsExactType(312D , message.getExtension(repeatedDoubleExtensionLite , 1));
+ assertEqualsExactType(false, message.getExtension(repeatedBoolExtensionLite , 1));
+ assertEqualsExactType("315", message.getExtension(repeatedStringExtensionLite , 1));
+ assertEqualsExactType(toBytes("316"), message.getExtension(repeatedBytesExtensionLite, 1));
+
+ assertEqualsExactType(317, message.getExtension(repeatedGroupExtensionLite ,1).getA());
+ assertEqualsExactType(318, message.getExtension(repeatedNestedMessageExtensionLite ,1).getBb());
+ assertEqualsExactType(319, message.getExtension(repeatedForeignMessageExtensionLite,1).getC());
+ assertEqualsExactType(320, message.getExtension(repeatedImportMessageExtensionLite ,1).getD());
+ assertEqualsExactType(327, message.getExtension(repeatedLazyMessageExtensionLite ,1).getBb());
+
+ assertEqualsExactType(TestAllTypesLite.NestedEnum.BAZ,
+ message.getExtension(repeatedNestedEnumExtensionLite, 1));
+ assertEqualsExactType(ForeignEnumLite.FOREIGN_LITE_BAZ,
+ message.getExtension(repeatedForeignEnumExtensionLite, 1));
+ assertEqualsExactType(ImportEnumLite.IMPORT_LITE_BAZ,
+ message.getExtension(repeatedImportEnumExtensionLite, 1));
+
+ assertEqualsExactType("324", message.getExtension(repeatedStringPieceExtensionLite, 1));
+ assertEqualsExactType("325", message.getExtension(repeatedCordExtensionLite, 1));
+
+ // -----------------------------------------------------------------
+
+ Assert.assertTrue(message.hasExtension(defaultInt32ExtensionLite ));
+ Assert.assertTrue(message.hasExtension(defaultInt64ExtensionLite ));
+ Assert.assertTrue(message.hasExtension(defaultUint32ExtensionLite ));
+ Assert.assertTrue(message.hasExtension(defaultUint64ExtensionLite ));
+ Assert.assertTrue(message.hasExtension(defaultSint32ExtensionLite ));
+ Assert.assertTrue(message.hasExtension(defaultSint64ExtensionLite ));
+ Assert.assertTrue(message.hasExtension(defaultFixed32ExtensionLite ));
+ Assert.assertTrue(message.hasExtension(defaultFixed64ExtensionLite ));
+ Assert.assertTrue(message.hasExtension(defaultSfixed32ExtensionLite));
+ Assert.assertTrue(message.hasExtension(defaultSfixed64ExtensionLite));
+ Assert.assertTrue(message.hasExtension(defaultFloatExtensionLite ));
+ Assert.assertTrue(message.hasExtension(defaultDoubleExtensionLite ));
+ Assert.assertTrue(message.hasExtension(defaultBoolExtensionLite ));
+ Assert.assertTrue(message.hasExtension(defaultStringExtensionLite ));
+ Assert.assertTrue(message.hasExtension(defaultBytesExtensionLite ));
+
+ Assert.assertTrue(message.hasExtension(defaultNestedEnumExtensionLite ));
+ Assert.assertTrue(message.hasExtension(defaultForeignEnumExtensionLite));
+ Assert.assertTrue(message.hasExtension(defaultImportEnumExtensionLite ));
+
+ Assert.assertTrue(message.hasExtension(defaultStringPieceExtensionLite));
+ Assert.assertTrue(message.hasExtension(defaultCordExtensionLite));
+
+ assertEqualsExactType(401 , message.getExtension(defaultInt32ExtensionLite ));
+ assertEqualsExactType(402L , message.getExtension(defaultInt64ExtensionLite ));
+ assertEqualsExactType(403 , message.getExtension(defaultUint32ExtensionLite ));
+ assertEqualsExactType(404L , message.getExtension(defaultUint64ExtensionLite ));
+ assertEqualsExactType(405 , message.getExtension(defaultSint32ExtensionLite ));
+ assertEqualsExactType(406L , message.getExtension(defaultSint64ExtensionLite ));
+ assertEqualsExactType(407 , message.getExtension(defaultFixed32ExtensionLite ));
+ assertEqualsExactType(408L , message.getExtension(defaultFixed64ExtensionLite ));
+ assertEqualsExactType(409 , message.getExtension(defaultSfixed32ExtensionLite));
+ assertEqualsExactType(410L , message.getExtension(defaultSfixed64ExtensionLite));
+ assertEqualsExactType(411F , message.getExtension(defaultFloatExtensionLite ));
+ assertEqualsExactType(412D , message.getExtension(defaultDoubleExtensionLite ));
+ assertEqualsExactType(false, message.getExtension(defaultBoolExtensionLite ));
+ assertEqualsExactType("415", message.getExtension(defaultStringExtensionLite ));
+ assertEqualsExactType(toBytes("416"), message.getExtension(defaultBytesExtensionLite));
+
+ assertEqualsExactType(TestAllTypesLite.NestedEnum.FOO,
+ message.getExtension(defaultNestedEnumExtensionLite ));
+ assertEqualsExactType(ForeignEnumLite.FOREIGN_LITE_FOO,
+ message.getExtension(defaultForeignEnumExtensionLite));
+ assertEqualsExactType(ImportEnumLite.IMPORT_LITE_FOO,
+ message.getExtension(defaultImportEnumExtensionLite));
+
+ assertEqualsExactType("424", message.getExtension(defaultStringPieceExtensionLite));
+ assertEqualsExactType("425", message.getExtension(defaultCordExtensionLite));
+
+ Assert.assertTrue(message.hasExtension(oneofBytesExtensionLite));
+
+ assertEqualsExactType(toBytes("604"), message.getExtension(oneofBytesExtensionLite));
+ }
+
+ // -------------------------------------------------------------------
+
+ /**
+ * Assert (using {@code junit.framework.Assert}} that all extensions of
+ * {@code message} are cleared, and that getting the extensions returns their
+ * default values.
+ */
+ public static void assertExtensionsClear(
+ TestAllExtensionsLiteOrBuilder message) {
+ // hasBlah() should initially be false for all optional fields.
+ Assert.assertFalse(message.hasExtension(optionalInt32ExtensionLite ));
+ Assert.assertFalse(message.hasExtension(optionalInt64ExtensionLite ));
+ Assert.assertFalse(message.hasExtension(optionalUint32ExtensionLite ));
+ Assert.assertFalse(message.hasExtension(optionalUint64ExtensionLite ));
+ Assert.assertFalse(message.hasExtension(optionalSint32ExtensionLite ));
+ Assert.assertFalse(message.hasExtension(optionalSint64ExtensionLite ));
+ Assert.assertFalse(message.hasExtension(optionalFixed32ExtensionLite ));
+ Assert.assertFalse(message.hasExtension(optionalFixed64ExtensionLite ));
+ Assert.assertFalse(message.hasExtension(optionalSfixed32ExtensionLite));
+ Assert.assertFalse(message.hasExtension(optionalSfixed64ExtensionLite));
+ Assert.assertFalse(message.hasExtension(optionalFloatExtensionLite ));
+ Assert.assertFalse(message.hasExtension(optionalDoubleExtensionLite ));
+ Assert.assertFalse(message.hasExtension(optionalBoolExtensionLite ));
+ Assert.assertFalse(message.hasExtension(optionalStringExtensionLite ));
+ Assert.assertFalse(message.hasExtension(optionalBytesExtensionLite ));
+
+ Assert.assertFalse(message.hasExtension(optionalGroupExtensionLite ));
+ Assert.assertFalse(message.hasExtension(optionalNestedMessageExtensionLite ));
+ Assert.assertFalse(message.hasExtension(optionalForeignMessageExtensionLite ));
+ Assert.assertFalse(message.hasExtension(optionalImportMessageExtensionLite ));
+ Assert.assertFalse(message.hasExtension(optionalPublicImportMessageExtensionLite));
+ Assert.assertFalse(message.hasExtension(optionalLazyMessageExtensionLite ));
+
+ Assert.assertFalse(message.hasExtension(optionalNestedEnumExtensionLite ));
+ Assert.assertFalse(message.hasExtension(optionalForeignEnumExtensionLite));
+ Assert.assertFalse(message.hasExtension(optionalImportEnumExtensionLite ));
+
+ Assert.assertFalse(message.hasExtension(optionalStringPieceExtensionLite));
+ Assert.assertFalse(message.hasExtension(optionalCordExtensionLite));
+
+ // Optional fields without defaults are set to zero or something like it.
+ assertEqualsExactType(0 , message.getExtension(optionalInt32ExtensionLite ));
+ assertEqualsExactType(0L , message.getExtension(optionalInt64ExtensionLite ));
+ assertEqualsExactType(0 , message.getExtension(optionalUint32ExtensionLite ));
+ assertEqualsExactType(0L , message.getExtension(optionalUint64ExtensionLite ));
+ assertEqualsExactType(0 , message.getExtension(optionalSint32ExtensionLite ));
+ assertEqualsExactType(0L , message.getExtension(optionalSint64ExtensionLite ));
+ assertEqualsExactType(0 , message.getExtension(optionalFixed32ExtensionLite ));
+ assertEqualsExactType(0L , message.getExtension(optionalFixed64ExtensionLite ));
+ assertEqualsExactType(0 , message.getExtension(optionalSfixed32ExtensionLite));
+ assertEqualsExactType(0L , message.getExtension(optionalSfixed64ExtensionLite));
+ assertEqualsExactType(0F , message.getExtension(optionalFloatExtensionLite ));
+ assertEqualsExactType(0D , message.getExtension(optionalDoubleExtensionLite ));
+ assertEqualsExactType(false, message.getExtension(optionalBoolExtensionLite ));
+ assertEqualsExactType("" , message.getExtension(optionalStringExtensionLite ));
+ assertEqualsExactType(ByteString.EMPTY, message.getExtension(optionalBytesExtensionLite));
+
+ // Embedded messages should also be clear.
+ Assert.assertFalse(message.getExtension(optionalGroupExtensionLite ).hasA());
+ Assert.assertFalse(message.getExtension(optionalNestedMessageExtensionLite ).hasBb());
+ Assert.assertFalse(message.getExtension(optionalForeignMessageExtensionLite ).hasC());
+ Assert.assertFalse(message.getExtension(optionalImportMessageExtensionLite ).hasD());
+ Assert.assertFalse(message.getExtension(optionalPublicImportMessageExtensionLite).hasE());
+ Assert.assertFalse(message.getExtension(optionalLazyMessageExtensionLite ).hasBb());
+
+ assertEqualsExactType(0, message.getExtension(optionalGroupExtensionLite ).getA());
+ assertEqualsExactType(0, message.getExtension(optionalNestedMessageExtensionLite ).getBb());
+ assertEqualsExactType(0, message.getExtension(optionalForeignMessageExtensionLite).getC());
+ assertEqualsExactType(0, message.getExtension(optionalImportMessageExtensionLite ).getD());
+ assertEqualsExactType(0, message.getExtension(
+ optionalPublicImportMessageExtensionLite).getE());
+ assertEqualsExactType(0, message.getExtension(optionalLazyMessageExtensionLite ).getBb());
+
+ // Enums without defaults are set to the first value in the enum.
+ assertEqualsExactType(TestAllTypesLite.NestedEnum.FOO,
+ message.getExtension(optionalNestedEnumExtensionLite ));
+ assertEqualsExactType(ForeignEnumLite.FOREIGN_LITE_FOO,
+ message.getExtension(optionalForeignEnumExtensionLite));
+ assertEqualsExactType(ImportEnumLite.IMPORT_LITE_FOO,
+ message.getExtension(optionalImportEnumExtensionLite));
+
+ assertEqualsExactType("", message.getExtension(optionalStringPieceExtensionLite));
+ assertEqualsExactType("", message.getExtension(optionalCordExtensionLite));
+
+ // Repeated fields are empty.
+ Assert.assertEquals(0, message.getExtensionCount(repeatedInt32ExtensionLite ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedInt64ExtensionLite ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedUint32ExtensionLite ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedUint64ExtensionLite ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedSint32ExtensionLite ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedSint64ExtensionLite ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedFixed32ExtensionLite ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedFixed64ExtensionLite ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedSfixed32ExtensionLite));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedSfixed64ExtensionLite));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedFloatExtensionLite ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedDoubleExtensionLite ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedBoolExtensionLite ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedStringExtensionLite ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedBytesExtensionLite ));
+
+ Assert.assertEquals(0, message.getExtensionCount(repeatedGroupExtensionLite ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedNestedMessageExtensionLite ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedForeignMessageExtensionLite));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedImportMessageExtensionLite ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedLazyMessageExtensionLite ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedNestedEnumExtensionLite ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedForeignEnumExtensionLite ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedImportEnumExtensionLite ));
+
+ Assert.assertEquals(0, message.getExtensionCount(repeatedStringPieceExtensionLite));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedCordExtensionLite));
+
+ // hasBlah() should also be false for all default fields.
+ Assert.assertFalse(message.hasExtension(defaultInt32ExtensionLite ));
+ Assert.assertFalse(message.hasExtension(defaultInt64ExtensionLite ));
+ Assert.assertFalse(message.hasExtension(defaultUint32ExtensionLite ));
+ Assert.assertFalse(message.hasExtension(defaultUint64ExtensionLite ));
+ Assert.assertFalse(message.hasExtension(defaultSint32ExtensionLite ));
+ Assert.assertFalse(message.hasExtension(defaultSint64ExtensionLite ));
+ Assert.assertFalse(message.hasExtension(defaultFixed32ExtensionLite ));
+ Assert.assertFalse(message.hasExtension(defaultFixed64ExtensionLite ));
+ Assert.assertFalse(message.hasExtension(defaultSfixed32ExtensionLite));
+ Assert.assertFalse(message.hasExtension(defaultSfixed64ExtensionLite));
+ Assert.assertFalse(message.hasExtension(defaultFloatExtensionLite ));
+ Assert.assertFalse(message.hasExtension(defaultDoubleExtensionLite ));
+ Assert.assertFalse(message.hasExtension(defaultBoolExtensionLite ));
+ Assert.assertFalse(message.hasExtension(defaultStringExtensionLite ));
+ Assert.assertFalse(message.hasExtension(defaultBytesExtensionLite ));
+
+ Assert.assertFalse(message.hasExtension(defaultNestedEnumExtensionLite ));
+ Assert.assertFalse(message.hasExtension(defaultForeignEnumExtensionLite));
+ Assert.assertFalse(message.hasExtension(defaultImportEnumExtensionLite ));
+
+ Assert.assertFalse(message.hasExtension(defaultStringPieceExtensionLite));
+ Assert.assertFalse(message.hasExtension(defaultCordExtensionLite));
+
+ // Fields with defaults have their default values (duh).
+ assertEqualsExactType( 41 , message.getExtension(defaultInt32ExtensionLite ));
+ assertEqualsExactType( 42L , message.getExtension(defaultInt64ExtensionLite ));
+ assertEqualsExactType( 43 , message.getExtension(defaultUint32ExtensionLite ));
+ assertEqualsExactType( 44L , message.getExtension(defaultUint64ExtensionLite ));
+ assertEqualsExactType(-45 , message.getExtension(defaultSint32ExtensionLite ));
+ assertEqualsExactType( 46L , message.getExtension(defaultSint64ExtensionLite ));
+ assertEqualsExactType( 47 , message.getExtension(defaultFixed32ExtensionLite ));
+ assertEqualsExactType( 48L , message.getExtension(defaultFixed64ExtensionLite ));
+ assertEqualsExactType( 49 , message.getExtension(defaultSfixed32ExtensionLite));
+ assertEqualsExactType(-50L , message.getExtension(defaultSfixed64ExtensionLite));
+ assertEqualsExactType( 51.5F , message.getExtension(defaultFloatExtensionLite ));
+ assertEqualsExactType( 52e3D , message.getExtension(defaultDoubleExtensionLite ));
+ assertEqualsExactType(true , message.getExtension(defaultBoolExtensionLite ));
+ assertEqualsExactType("hello", message.getExtension(defaultStringExtensionLite ));
+ assertEqualsExactType(toBytes("world"), message.getExtension(defaultBytesExtensionLite));
+
+ assertEqualsExactType(TestAllTypesLite.NestedEnum.BAR,
+ message.getExtension(defaultNestedEnumExtensionLite ));
+ assertEqualsExactType(ForeignEnumLite.FOREIGN_LITE_BAR,
+ message.getExtension(defaultForeignEnumExtensionLite));
+ assertEqualsExactType(ImportEnumLite.IMPORT_LITE_BAR,
+ message.getExtension(defaultImportEnumExtensionLite));
+
+ assertEqualsExactType("abc", message.getExtension(defaultStringPieceExtensionLite));
+ assertEqualsExactType("123", message.getExtension(defaultCordExtensionLite));
+
+ Assert.assertFalse(message.hasExtension(oneofUint32ExtensionLite));
+ Assert.assertFalse(message.hasExtension(oneofNestedMessageExtensionLite));
+ Assert.assertFalse(message.hasExtension(oneofStringExtensionLite));
+ Assert.assertFalse(message.hasExtension(oneofBytesExtensionLite));
+ }
+
+ // -------------------------------------------------------------------
+
+ /**
+ * Assert (using {@code junit.framework.Assert}} that all extensions of
+ * {@code message} are set to the values assigned by {@code setAllExtensions}
+ * followed by {@code modifyRepeatedExtensions}.
+ */
+ public static void assertRepeatedExtensionsModified(
+ TestAllExtensionsLiteOrBuilder message) {
+ // ModifyRepeatedFields only sets the second repeated element of each
+ // field. In addition to verifying this, we also verify that the first
+ // element and size were *not* modified.
+ Assert.assertEquals(2, message.getExtensionCount(repeatedInt32ExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedInt64ExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedUint32ExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedUint64ExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedSint32ExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedSint64ExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedFixed32ExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedFixed64ExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedSfixed32ExtensionLite));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedSfixed64ExtensionLite));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedFloatExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedDoubleExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedBoolExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedStringExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedBytesExtensionLite ));
+
+ Assert.assertEquals(2, message.getExtensionCount(repeatedGroupExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedNestedMessageExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedForeignMessageExtensionLite));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedImportMessageExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedLazyMessageExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedNestedEnumExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedForeignEnumExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedImportEnumExtensionLite ));
+
+ Assert.assertEquals(2, message.getExtensionCount(repeatedStringPieceExtensionLite));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedCordExtensionLite));
+
+ assertEqualsExactType(201 , message.getExtension(repeatedInt32ExtensionLite , 0));
+ assertEqualsExactType(202L , message.getExtension(repeatedInt64ExtensionLite , 0));
+ assertEqualsExactType(203 , message.getExtension(repeatedUint32ExtensionLite , 0));
+ assertEqualsExactType(204L , message.getExtension(repeatedUint64ExtensionLite , 0));
+ assertEqualsExactType(205 , message.getExtension(repeatedSint32ExtensionLite , 0));
+ assertEqualsExactType(206L , message.getExtension(repeatedSint64ExtensionLite , 0));
+ assertEqualsExactType(207 , message.getExtension(repeatedFixed32ExtensionLite , 0));
+ assertEqualsExactType(208L , message.getExtension(repeatedFixed64ExtensionLite , 0));
+ assertEqualsExactType(209 , message.getExtension(repeatedSfixed32ExtensionLite, 0));
+ assertEqualsExactType(210L , message.getExtension(repeatedSfixed64ExtensionLite, 0));
+ assertEqualsExactType(211F , message.getExtension(repeatedFloatExtensionLite , 0));
+ assertEqualsExactType(212D , message.getExtension(repeatedDoubleExtensionLite , 0));
+ assertEqualsExactType(true , message.getExtension(repeatedBoolExtensionLite , 0));
+ assertEqualsExactType("215", message.getExtension(repeatedStringExtensionLite , 0));
+ assertEqualsExactType(toBytes("216"), message.getExtension(repeatedBytesExtensionLite, 0));
+
+ assertEqualsExactType(217, message.getExtension(repeatedGroupExtensionLite ,0).getA());
+ assertEqualsExactType(218, message.getExtension(repeatedNestedMessageExtensionLite ,0).getBb());
+ assertEqualsExactType(219, message.getExtension(repeatedForeignMessageExtensionLite,0).getC());
+ assertEqualsExactType(220, message.getExtension(repeatedImportMessageExtensionLite ,0).getD());
+ assertEqualsExactType(227, message.getExtension(repeatedLazyMessageExtensionLite ,0).getBb());
+
+ assertEqualsExactType(TestAllTypesLite.NestedEnum.BAR,
+ message.getExtension(repeatedNestedEnumExtensionLite, 0));
+ assertEqualsExactType(ForeignEnumLite.FOREIGN_LITE_BAR,
+ message.getExtension(repeatedForeignEnumExtensionLite, 0));
+ assertEqualsExactType(ImportEnumLite.IMPORT_LITE_BAR,
+ message.getExtension(repeatedImportEnumExtensionLite, 0));
+
+ assertEqualsExactType("224", message.getExtension(repeatedStringPieceExtensionLite, 0));
+ assertEqualsExactType("225", message.getExtension(repeatedCordExtensionLite, 0));
+
+ // Actually verify the second (modified) elements now.
+ assertEqualsExactType(501 , message.getExtension(repeatedInt32ExtensionLite , 1));
+ assertEqualsExactType(502L , message.getExtension(repeatedInt64ExtensionLite , 1));
+ assertEqualsExactType(503 , message.getExtension(repeatedUint32ExtensionLite , 1));
+ assertEqualsExactType(504L , message.getExtension(repeatedUint64ExtensionLite , 1));
+ assertEqualsExactType(505 , message.getExtension(repeatedSint32ExtensionLite , 1));
+ assertEqualsExactType(506L , message.getExtension(repeatedSint64ExtensionLite , 1));
+ assertEqualsExactType(507 , message.getExtension(repeatedFixed32ExtensionLite , 1));
+ assertEqualsExactType(508L , message.getExtension(repeatedFixed64ExtensionLite , 1));
+ assertEqualsExactType(509 , message.getExtension(repeatedSfixed32ExtensionLite, 1));
+ assertEqualsExactType(510L , message.getExtension(repeatedSfixed64ExtensionLite, 1));
+ assertEqualsExactType(511F , message.getExtension(repeatedFloatExtensionLite , 1));
+ assertEqualsExactType(512D , message.getExtension(repeatedDoubleExtensionLite , 1));
+ assertEqualsExactType(true , message.getExtension(repeatedBoolExtensionLite , 1));
+ assertEqualsExactType("515", message.getExtension(repeatedStringExtensionLite , 1));
+ assertEqualsExactType(toBytes("516"), message.getExtension(repeatedBytesExtensionLite, 1));
+
+ assertEqualsExactType(517, message.getExtension(repeatedGroupExtensionLite ,1).getA());
+ assertEqualsExactType(518, message.getExtension(repeatedNestedMessageExtensionLite ,1).getBb());
+ assertEqualsExactType(519, message.getExtension(repeatedForeignMessageExtensionLite,1).getC());
+ assertEqualsExactType(520, message.getExtension(repeatedImportMessageExtensionLite ,1).getD());
+ assertEqualsExactType(527, message.getExtension(repeatedLazyMessageExtensionLite ,1).getBb());
+
+ assertEqualsExactType(TestAllTypesLite.NestedEnum.FOO,
+ message.getExtension(repeatedNestedEnumExtensionLite, 1));
+ assertEqualsExactType(ForeignEnumLite.FOREIGN_LITE_FOO,
+ message.getExtension(repeatedForeignEnumExtensionLite, 1));
+ assertEqualsExactType(ImportEnumLite.IMPORT_LITE_FOO,
+ message.getExtension(repeatedImportEnumExtensionLite, 1));
+
+ assertEqualsExactType("524", message.getExtension(repeatedStringPieceExtensionLite, 1));
+ assertEqualsExactType("525", message.getExtension(repeatedCordExtensionLite, 1));
+ }
+
+ public static void setPackedExtensions(TestPackedExtensionsLite.Builder message) {
+ message.addExtension(packedInt32ExtensionLite , 601);
+ message.addExtension(packedInt64ExtensionLite , 602L);
+ message.addExtension(packedUint32ExtensionLite , 603);
+ message.addExtension(packedUint64ExtensionLite , 604L);
+ message.addExtension(packedSint32ExtensionLite , 605);
+ message.addExtension(packedSint64ExtensionLite , 606L);
+ message.addExtension(packedFixed32ExtensionLite , 607);
+ message.addExtension(packedFixed64ExtensionLite , 608L);
+ message.addExtension(packedSfixed32ExtensionLite, 609);
+ message.addExtension(packedSfixed64ExtensionLite, 610L);
+ message.addExtension(packedFloatExtensionLite , 611F);
+ message.addExtension(packedDoubleExtensionLite , 612D);
+ message.addExtension(packedBoolExtensionLite , true);
+ message.addExtension(packedEnumExtensionLite, ForeignEnumLite.FOREIGN_LITE_BAR);
+ // Add a second one of each field.
+ message.addExtension(packedInt32ExtensionLite , 701);
+ message.addExtension(packedInt64ExtensionLite , 702L);
+ message.addExtension(packedUint32ExtensionLite , 703);
+ message.addExtension(packedUint64ExtensionLite , 704L);
+ message.addExtension(packedSint32ExtensionLite , 705);
+ message.addExtension(packedSint64ExtensionLite , 706L);
+ message.addExtension(packedFixed32ExtensionLite , 707);
+ message.addExtension(packedFixed64ExtensionLite , 708L);
+ message.addExtension(packedSfixed32ExtensionLite, 709);
+ message.addExtension(packedSfixed64ExtensionLite, 710L);
+ message.addExtension(packedFloatExtensionLite , 711F);
+ message.addExtension(packedDoubleExtensionLite , 712D);
+ message.addExtension(packedBoolExtensionLite , false);
+ message.addExtension(packedEnumExtensionLite, ForeignEnumLite.FOREIGN_LITE_BAZ);
+ }
+
+ public static void assertPackedExtensionsSet(TestPackedExtensionsLite message) {
+ Assert.assertEquals(2, message.getExtensionCount(packedInt32ExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(packedInt64ExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(packedUint32ExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(packedUint64ExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(packedSint32ExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(packedSint64ExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(packedFixed32ExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(packedFixed64ExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(packedSfixed32ExtensionLite));
+ Assert.assertEquals(2, message.getExtensionCount(packedSfixed64ExtensionLite));
+ Assert.assertEquals(2, message.getExtensionCount(packedFloatExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(packedDoubleExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(packedBoolExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(packedEnumExtensionLite));
+ assertEqualsExactType(601 , message.getExtension(packedInt32ExtensionLite , 0));
+ assertEqualsExactType(602L , message.getExtension(packedInt64ExtensionLite , 0));
+ assertEqualsExactType(603 , message.getExtension(packedUint32ExtensionLite , 0));
+ assertEqualsExactType(604L , message.getExtension(packedUint64ExtensionLite , 0));
+ assertEqualsExactType(605 , message.getExtension(packedSint32ExtensionLite , 0));
+ assertEqualsExactType(606L , message.getExtension(packedSint64ExtensionLite , 0));
+ assertEqualsExactType(607 , message.getExtension(packedFixed32ExtensionLite , 0));
+ assertEqualsExactType(608L , message.getExtension(packedFixed64ExtensionLite , 0));
+ assertEqualsExactType(609 , message.getExtension(packedSfixed32ExtensionLite, 0));
+ assertEqualsExactType(610L , message.getExtension(packedSfixed64ExtensionLite, 0));
+ assertEqualsExactType(611F , message.getExtension(packedFloatExtensionLite , 0));
+ assertEqualsExactType(612D , message.getExtension(packedDoubleExtensionLite , 0));
+ assertEqualsExactType(true , message.getExtension(packedBoolExtensionLite , 0));
+ assertEqualsExactType(ForeignEnumLite.FOREIGN_LITE_BAR,
+ message.getExtension(packedEnumExtensionLite, 0));
+ assertEqualsExactType(701 , message.getExtension(packedInt32ExtensionLite , 1));
+ assertEqualsExactType(702L , message.getExtension(packedInt64ExtensionLite , 1));
+ assertEqualsExactType(703 , message.getExtension(packedUint32ExtensionLite , 1));
+ assertEqualsExactType(704L , message.getExtension(packedUint64ExtensionLite , 1));
+ assertEqualsExactType(705 , message.getExtension(packedSint32ExtensionLite , 1));
+ assertEqualsExactType(706L , message.getExtension(packedSint64ExtensionLite , 1));
+ assertEqualsExactType(707 , message.getExtension(packedFixed32ExtensionLite , 1));
+ assertEqualsExactType(708L , message.getExtension(packedFixed64ExtensionLite , 1));
+ assertEqualsExactType(709 , message.getExtension(packedSfixed32ExtensionLite, 1));
+ assertEqualsExactType(710L , message.getExtension(packedSfixed64ExtensionLite, 1));
+ assertEqualsExactType(711F , message.getExtension(packedFloatExtensionLite , 1));
+ assertEqualsExactType(712D , message.getExtension(packedDoubleExtensionLite , 1));
+ assertEqualsExactType(false, message.getExtension(packedBoolExtensionLite , 1));
+ assertEqualsExactType(ForeignEnumLite.FOREIGN_LITE_BAZ,
+ message.getExtension(packedEnumExtensionLite, 1));
+ }
+
+ // ===================================================================
+ // oneof
+ public static void setOneof(TestOneof2.Builder message) {
+ message.setFooLazyMessage(
+ TestOneof2.NestedMessage.newBuilder().setQuxInt(100).build());
+ message.setBarString("101");
+ message.setBazInt(102);
+ message.setBazString("103");
+ }
+
+ public static void assertOneofSet(TestOneof2 message) {
+ Assert.assertTrue(message.hasFooLazyMessage ());
+ Assert.assertTrue(message.getFooLazyMessage().hasQuxInt());
+
+ Assert.assertTrue(message.hasBarString());
+ Assert.assertTrue(message.hasBazInt ());
+ Assert.assertTrue(message.hasBazString());
+
+ Assert.assertEquals(100 , message.getFooLazyMessage().getQuxInt());
+ Assert.assertEquals("101", message.getBarString ());
+ Assert.assertEquals(102 , message.getBazInt ());
+ Assert.assertEquals("103", message.getBazString ());
+ }
+
+ public static void assertAtMostOneFieldSetOneof(TestOneof2 message) {
+ int count = 0;
+ if (message.hasFooInt()) { ++count; }
+ if (message.hasFooString()) { ++count; }
+ if (message.hasFooCord()) { ++count; }
+ if (message.hasFooStringPiece()) { ++count; }
+ if (message.hasFooBytes()) { ++count; }
+ if (message.hasFooEnum()) { ++count; }
+ if (message.hasFooMessage()) { ++count; }
+ if (message.hasFooGroup()) { ++count; }
+ if (message.hasFooLazyMessage()) { ++count; }
+ Assert.assertTrue(count <= 1);
+
+ count = 0;
+ if (message.hasBarInt()) { ++count; }
+ if (message.hasBarString()) { ++count; }
+ if (message.hasBarCord()) { ++count; }
+ if (message.hasBarStringPiece()) { ++count; }
+ if (message.hasBarBytes()) { ++count; }
+ if (message.hasBarEnum()) { ++count; }
+ Assert.assertTrue(count <= 1);
+
+ switch (message.getFooCase()) {
+ case FOO_INT:
+ Assert.assertTrue(message.hasFooInt());
+ break;
+ case FOO_STRING:
+ Assert.assertTrue(message.hasFooString());
+ break;
+ case FOO_CORD:
+ Assert.assertTrue(message.hasFooCord());
+ break;
+ case FOO_BYTES:
+ Assert.assertTrue(message.hasFooBytes());
+ break;
+ case FOO_ENUM:
+ Assert.assertTrue(message.hasFooEnum());
+ break;
+ case FOO_MESSAGE:
+ Assert.assertTrue(message.hasFooMessage());
+ break;
+ case FOOGROUP:
+ Assert.assertTrue(message.hasFooGroup());
+ break;
+ case FOO_LAZY_MESSAGE:
+ Assert.assertTrue(message.hasFooLazyMessage());
+ break;
+ case FOO_NOT_SET:
+ break;
+ }
+ }
+
+ // =================================================================
+
+ /**
+ * Performs the same things that the methods of {@code TestUtil} do, but
+ * via the reflection interface. This is its own class because it needs
+ * to know what descriptor to use.
+ */
+ public static class ReflectionTester {
+ private final Descriptors.Descriptor baseDescriptor;
+ private final ExtensionRegistry extensionRegistry;
+
+ private final Descriptors.FileDescriptor file;
+ private final Descriptors.FileDescriptor importFile;
+ private final Descriptors.FileDescriptor publicImportFile;
+
+ private final Descriptors.Descriptor optionalGroup;
+ private final Descriptors.Descriptor repeatedGroup;
+ private final Descriptors.Descriptor nestedMessage;
+ private final Descriptors.Descriptor foreignMessage;
+ private final Descriptors.Descriptor importMessage;
+ private final Descriptors.Descriptor publicImportMessage;
+
+ private final Descriptors.FieldDescriptor groupA;
+ private final Descriptors.FieldDescriptor repeatedGroupA;
+ private final Descriptors.FieldDescriptor nestedB;
+ private final Descriptors.FieldDescriptor foreignC;
+ private final Descriptors.FieldDescriptor importD;
+ private final Descriptors.FieldDescriptor importE;
+
+ private final Descriptors.EnumDescriptor nestedEnum;
+ private final Descriptors.EnumDescriptor foreignEnum;
+ private final Descriptors.EnumDescriptor importEnum;
+
+ private final Descriptors.EnumValueDescriptor nestedFoo;
+ private final Descriptors.EnumValueDescriptor nestedBar;
+ private final Descriptors.EnumValueDescriptor nestedBaz;
+ private final Descriptors.EnumValueDescriptor foreignFoo;
+ private final Descriptors.EnumValueDescriptor foreignBar;
+ private final Descriptors.EnumValueDescriptor foreignBaz;
+ private final Descriptors.EnumValueDescriptor importFoo;
+ private final Descriptors.EnumValueDescriptor importBar;
+ private final Descriptors.EnumValueDescriptor importBaz;
+
+ /**
+ * Construct a {@code ReflectionTester} that will expect messages using
+ * the given descriptor.
+ *
+ * Normally {@code baseDescriptor} should be a descriptor for the type
+ * {@code TestAllTypes}, defined in
+ * {@code google/protobuf/unittest.proto}. However, if
+ * {@code extensionRegistry} is non-null, then {@code baseDescriptor} should
+ * be for {@code TestAllExtensions} instead, and instead of reading and
+ * writing normal fields, the tester will read and write extensions.
+ * All of {@code TestAllExtensions}' extensions must be registered in the
+ * registry.
+ */
+ public ReflectionTester(Descriptors.Descriptor baseDescriptor,
+ ExtensionRegistry extensionRegistry) {
+ this.baseDescriptor = baseDescriptor;
+ this.extensionRegistry = extensionRegistry;
+
+ this.file = baseDescriptor.getFile();
+ Assert.assertEquals(1, file.getDependencies().size());
+ this.importFile = file.getDependencies().get(0);
+ this.publicImportFile = importFile.getDependencies().get(0);
+
+ Descriptors.Descriptor testAllTypes;
+ if (baseDescriptor.getName() == "TestAllTypes") {
+ testAllTypes = baseDescriptor;
+ } else {
+ testAllTypes = file.findMessageTypeByName("TestAllTypes");
+ Assert.assertNotNull(testAllTypes);
+ }
+
+ if (extensionRegistry == null) {
+ // Use testAllTypes, rather than baseDescriptor, to allow
+ // initialization using TestPackedTypes descriptors. These objects
+ // won't be used by the methods for packed fields.
+ this.optionalGroup =
+ testAllTypes.findNestedTypeByName("OptionalGroup");
+ this.repeatedGroup =
+ testAllTypes.findNestedTypeByName("RepeatedGroup");
+ } else {
+ this.optionalGroup =
+ file.findMessageTypeByName("OptionalGroup_extension");
+ this.repeatedGroup =
+ file.findMessageTypeByName("RepeatedGroup_extension");
+ }
+ this.nestedMessage = testAllTypes.findNestedTypeByName("NestedMessage");
+ this.foreignMessage = file.findMessageTypeByName("ForeignMessage");
+ this.importMessage = importFile.findMessageTypeByName("ImportMessage");
+ this.publicImportMessage = publicImportFile.findMessageTypeByName(
+ "PublicImportMessage");
+
+ this.nestedEnum = testAllTypes.findEnumTypeByName("NestedEnum");
+ this.foreignEnum = file.findEnumTypeByName("ForeignEnum");
+ this.importEnum = importFile.findEnumTypeByName("ImportEnum");
+
+ Assert.assertNotNull(optionalGroup );
+ Assert.assertNotNull(repeatedGroup );
+ Assert.assertNotNull(nestedMessage );
+ Assert.assertNotNull(foreignMessage);
+ Assert.assertNotNull(importMessage );
+ Assert.assertNotNull(nestedEnum );
+ Assert.assertNotNull(foreignEnum );
+ Assert.assertNotNull(importEnum );
+
+ this.nestedB = nestedMessage .findFieldByName("bb");
+ this.foreignC = foreignMessage.findFieldByName("c");
+ this.importD = importMessage .findFieldByName("d");
+ this.importE = publicImportMessage.findFieldByName("e");
+ this.nestedFoo = nestedEnum.findValueByName("FOO");
+ this.nestedBar = nestedEnum.findValueByName("BAR");
+ this.nestedBaz = nestedEnum.findValueByName("BAZ");
+ this.foreignFoo = foreignEnum.findValueByName("FOREIGN_FOO");
+ this.foreignBar = foreignEnum.findValueByName("FOREIGN_BAR");
+ this.foreignBaz = foreignEnum.findValueByName("FOREIGN_BAZ");
+ this.importFoo = importEnum.findValueByName("IMPORT_FOO");
+ this.importBar = importEnum.findValueByName("IMPORT_BAR");
+ this.importBaz = importEnum.findValueByName("IMPORT_BAZ");
+
+ this.groupA = optionalGroup.findFieldByName("a");
+ this.repeatedGroupA = repeatedGroup.findFieldByName("a");
+
+ Assert.assertNotNull(groupA );
+ Assert.assertNotNull(repeatedGroupA);
+ Assert.assertNotNull(nestedB );
+ Assert.assertNotNull(foreignC );
+ Assert.assertNotNull(importD );
+ Assert.assertNotNull(importE );
+ Assert.assertNotNull(nestedFoo );
+ Assert.assertNotNull(nestedBar );
+ Assert.assertNotNull(nestedBaz );
+ Assert.assertNotNull(foreignFoo );
+ Assert.assertNotNull(foreignBar );
+ Assert.assertNotNull(foreignBaz );
+ Assert.assertNotNull(importFoo );
+ Assert.assertNotNull(importBar );
+ Assert.assertNotNull(importBaz );
+ }
+
+ /**
+ * Shorthand to get a FieldDescriptor for a field of unittest::TestAllTypes.
+ */
+ private Descriptors.FieldDescriptor f(String name) {
+ Descriptors.FieldDescriptor result;
+ if (extensionRegistry == null) {
+ result = baseDescriptor.findFieldByName(name);
+ } else {
+ result = file.findExtensionByName(name + "_extension");
+ }
+ Assert.assertNotNull(result);
+ return result;
+ }
+
+ /**
+ * Calls {@code parent.newBuilderForField()} or uses the
+ * {@code ExtensionRegistry} to find an appropriate builder, depending
+ * on what type is being tested.
+ */
+ private Message.Builder newBuilderForField(
+ Message.Builder parent, Descriptors.FieldDescriptor field) {
+ if (extensionRegistry == null) {
+ return parent.newBuilderForField(field);
+ } else {
+ ExtensionRegistry.ExtensionInfo extension =
+ extensionRegistry.findImmutableExtensionByNumber(
+ field.getContainingType(), field.getNumber());
+ Assert.assertNotNull(extension);
+ Assert.assertNotNull(extension.defaultInstance);
+ return extension.defaultInstance.newBuilderForType();
+ }
+ }
+
+ // -------------------------------------------------------------------
+
+ /**
+ * Set every field of {@code message} to the values expected by
+ * {@code assertAllFieldsSet()}, using the {@link Message.Builder}
+ * reflection interface.
+ */
+ void setAllFieldsViaReflection(Message.Builder message) {
+ message.setField(f("optional_int32" ), 101 );
+ message.setField(f("optional_int64" ), 102L);
+ message.setField(f("optional_uint32" ), 103 );
+ message.setField(f("optional_uint64" ), 104L);
+ message.setField(f("optional_sint32" ), 105 );
+ message.setField(f("optional_sint64" ), 106L);
+ message.setField(f("optional_fixed32" ), 107 );
+ message.setField(f("optional_fixed64" ), 108L);
+ message.setField(f("optional_sfixed32"), 109 );
+ message.setField(f("optional_sfixed64"), 110L);
+ message.setField(f("optional_float" ), 111F);
+ message.setField(f("optional_double" ), 112D);
+ message.setField(f("optional_bool" ), true);
+ message.setField(f("optional_string" ), "115");
+ message.setField(f("optional_bytes" ), toBytes("116"));
+
+ message.setField(f("optionalgroup"),
+ newBuilderForField(message, f("optionalgroup"))
+ .setField(groupA, 117).build());
+ message.setField(f("optional_nested_message"),
+ newBuilderForField(message, f("optional_nested_message"))
+ .setField(nestedB, 118).build());
+ message.setField(f("optional_foreign_message"),
+ newBuilderForField(message, f("optional_foreign_message"))
+ .setField(foreignC, 119).build());
+ message.setField(f("optional_import_message"),
+ newBuilderForField(message, f("optional_import_message"))
+ .setField(importD, 120).build());
+ message.setField(f("optional_public_import_message"),
+ newBuilderForField(message, f("optional_public_import_message"))
+ .setField(importE, 126).build());
+ message.setField(f("optional_lazy_message"),
+ newBuilderForField(message, f("optional_lazy_message"))
+ .setField(nestedB, 127).build());
+
+ message.setField(f("optional_nested_enum" ), nestedBaz);
+ message.setField(f("optional_foreign_enum"), foreignBaz);
+ message.setField(f("optional_import_enum" ), importBaz);
+
+ message.setField(f("optional_string_piece" ), "124");
+ message.setField(f("optional_cord" ), "125");
+
+ // -----------------------------------------------------------------
+
+ message.addRepeatedField(f("repeated_int32" ), 201 );
+ message.addRepeatedField(f("repeated_int64" ), 202L);
+ message.addRepeatedField(f("repeated_uint32" ), 203 );
+ message.addRepeatedField(f("repeated_uint64" ), 204L);
+ message.addRepeatedField(f("repeated_sint32" ), 205 );
+ message.addRepeatedField(f("repeated_sint64" ), 206L);
+ message.addRepeatedField(f("repeated_fixed32" ), 207 );
+ message.addRepeatedField(f("repeated_fixed64" ), 208L);
+ message.addRepeatedField(f("repeated_sfixed32"), 209 );
+ message.addRepeatedField(f("repeated_sfixed64"), 210L);
+ message.addRepeatedField(f("repeated_float" ), 211F);
+ message.addRepeatedField(f("repeated_double" ), 212D);
+ message.addRepeatedField(f("repeated_bool" ), true);
+ message.addRepeatedField(f("repeated_string" ), "215");
+ message.addRepeatedField(f("repeated_bytes" ), toBytes("216"));
+
+ message.addRepeatedField(f("repeatedgroup"),
+ newBuilderForField(message, f("repeatedgroup"))
+ .setField(repeatedGroupA, 217).build());
+ message.addRepeatedField(f("repeated_nested_message"),
+ newBuilderForField(message, f("repeated_nested_message"))
+ .setField(nestedB, 218).build());
+ message.addRepeatedField(f("repeated_foreign_message"),
+ newBuilderForField(message, f("repeated_foreign_message"))
+ .setField(foreignC, 219).build());
+ message.addRepeatedField(f("repeated_import_message"),
+ newBuilderForField(message, f("repeated_import_message"))
+ .setField(importD, 220).build());
+ message.addRepeatedField(f("repeated_lazy_message"),
+ newBuilderForField(message, f("repeated_lazy_message"))
+ .setField(nestedB, 227).build());
+
+ message.addRepeatedField(f("repeated_nested_enum" ), nestedBar);
+ message.addRepeatedField(f("repeated_foreign_enum"), foreignBar);
+ message.addRepeatedField(f("repeated_import_enum" ), importBar);
+
+ message.addRepeatedField(f("repeated_string_piece" ), "224");
+ message.addRepeatedField(f("repeated_cord" ), "225");
+
+ // Add a second one of each field.
+ message.addRepeatedField(f("repeated_int32" ), 301 );
+ message.addRepeatedField(f("repeated_int64" ), 302L);
+ message.addRepeatedField(f("repeated_uint32" ), 303 );
+ message.addRepeatedField(f("repeated_uint64" ), 304L);
+ message.addRepeatedField(f("repeated_sint32" ), 305 );
+ message.addRepeatedField(f("repeated_sint64" ), 306L);
+ message.addRepeatedField(f("repeated_fixed32" ), 307 );
+ message.addRepeatedField(f("repeated_fixed64" ), 308L);
+ message.addRepeatedField(f("repeated_sfixed32"), 309 );
+ message.addRepeatedField(f("repeated_sfixed64"), 310L);
+ message.addRepeatedField(f("repeated_float" ), 311F);
+ message.addRepeatedField(f("repeated_double" ), 312D);
+ message.addRepeatedField(f("repeated_bool" ), false);
+ message.addRepeatedField(f("repeated_string" ), "315");
+ message.addRepeatedField(f("repeated_bytes" ), toBytes("316"));
+
+ message.addRepeatedField(f("repeatedgroup"),
+ newBuilderForField(message, f("repeatedgroup"))
+ .setField(repeatedGroupA, 317).build());
+ message.addRepeatedField(f("repeated_nested_message"),
+ newBuilderForField(message, f("repeated_nested_message"))
+ .setField(nestedB, 318).build());
+ message.addRepeatedField(f("repeated_foreign_message"),
+ newBuilderForField(message, f("repeated_foreign_message"))
+ .setField(foreignC, 319).build());
+ message.addRepeatedField(f("repeated_import_message"),
+ newBuilderForField(message, f("repeated_import_message"))
+ .setField(importD, 320).build());
+ message.addRepeatedField(f("repeated_lazy_message"),
+ newBuilderForField(message, f("repeated_lazy_message"))
+ .setField(nestedB, 327).build());
+
+ message.addRepeatedField(f("repeated_nested_enum" ), nestedBaz);
+ message.addRepeatedField(f("repeated_foreign_enum"), foreignBaz);
+ message.addRepeatedField(f("repeated_import_enum" ), importBaz);
+
+ message.addRepeatedField(f("repeated_string_piece" ), "324");
+ message.addRepeatedField(f("repeated_cord" ), "325");
+
+ // -----------------------------------------------------------------
+
+ message.setField(f("default_int32" ), 401 );
+ message.setField(f("default_int64" ), 402L);
+ message.setField(f("default_uint32" ), 403 );
+ message.setField(f("default_uint64" ), 404L);
+ message.setField(f("default_sint32" ), 405 );
+ message.setField(f("default_sint64" ), 406L);
+ message.setField(f("default_fixed32" ), 407 );
+ message.setField(f("default_fixed64" ), 408L);
+ message.setField(f("default_sfixed32"), 409 );
+ message.setField(f("default_sfixed64"), 410L);
+ message.setField(f("default_float" ), 411F);
+ message.setField(f("default_double" ), 412D);
+ message.setField(f("default_bool" ), false);
+ message.setField(f("default_string" ), "415");
+ message.setField(f("default_bytes" ), toBytes("416"));
+
+ message.setField(f("default_nested_enum" ), nestedFoo);
+ message.setField(f("default_foreign_enum"), foreignFoo);
+ message.setField(f("default_import_enum" ), importFoo);
+
+ message.setField(f("default_string_piece" ), "424");
+ message.setField(f("default_cord" ), "425");
+
+ message.setField(f("oneof_uint32" ), 601);
+ message.setField(f("oneof_nested_message"),
+ newBuilderForField(message, f("oneof_nested_message"))
+ .setField(nestedB, 602).build());
+ message.setField(f("oneof_string" ), "603");
+ message.setField(f("oneof_bytes" ), toBytes("604"));
+ }
+
+ // -------------------------------------------------------------------
+
+ /**
+ * Modify the repeated fields of {@code message} to contain the values
+ * expected by {@code assertRepeatedFieldsModified()}, using the
+ * {@link Message.Builder} reflection interface.
+ */
+ void modifyRepeatedFieldsViaReflection(Message.Builder message) {
+ message.setRepeatedField(f("repeated_int32" ), 1, 501 );
+ message.setRepeatedField(f("repeated_int64" ), 1, 502L);
+ message.setRepeatedField(f("repeated_uint32" ), 1, 503 );
+ message.setRepeatedField(f("repeated_uint64" ), 1, 504L);
+ message.setRepeatedField(f("repeated_sint32" ), 1, 505 );
+ message.setRepeatedField(f("repeated_sint64" ), 1, 506L);
+ message.setRepeatedField(f("repeated_fixed32" ), 1, 507 );
+ message.setRepeatedField(f("repeated_fixed64" ), 1, 508L);
+ message.setRepeatedField(f("repeated_sfixed32"), 1, 509 );
+ message.setRepeatedField(f("repeated_sfixed64"), 1, 510L);
+ message.setRepeatedField(f("repeated_float" ), 1, 511F);
+ message.setRepeatedField(f("repeated_double" ), 1, 512D);
+ message.setRepeatedField(f("repeated_bool" ), 1, true);
+ message.setRepeatedField(f("repeated_string" ), 1, "515");
+ message.setRepeatedField(f("repeated_bytes" ), 1, toBytes("516"));
+
+ message.setRepeatedField(f("repeatedgroup"), 1,
+ newBuilderForField(message, f("repeatedgroup"))
+ .setField(repeatedGroupA, 517).build());
+ message.setRepeatedField(f("repeated_nested_message"), 1,
+ newBuilderForField(message, f("repeated_nested_message"))
+ .setField(nestedB, 518).build());
+ message.setRepeatedField(f("repeated_foreign_message"), 1,
+ newBuilderForField(message, f("repeated_foreign_message"))
+ .setField(foreignC, 519).build());
+ message.setRepeatedField(f("repeated_import_message"), 1,
+ newBuilderForField(message, f("repeated_import_message"))
+ .setField(importD, 520).build());
+ message.setRepeatedField(f("repeated_lazy_message"), 1,
+ newBuilderForField(message, f("repeated_lazy_message"))
+ .setField(nestedB, 527).build());
+
+ message.setRepeatedField(f("repeated_nested_enum" ), 1, nestedFoo);
+ message.setRepeatedField(f("repeated_foreign_enum"), 1, foreignFoo);
+ message.setRepeatedField(f("repeated_import_enum" ), 1, importFoo);
+
+ message.setRepeatedField(f("repeated_string_piece"), 1, "524");
+ message.setRepeatedField(f("repeated_cord"), 1, "525");
+ }
+
+ // -------------------------------------------------------------------
+
+ /**
+ * Assert (using {@code junit.framework.Assert}} that all fields of
+ * {@code message} are set to the values assigned by {@code setAllFields},
+ * using the {@link Message} reflection interface.
+ */
+ public void assertAllFieldsSetViaReflection(MessageOrBuilder message) {
+ Assert.assertTrue(message.hasField(f("optional_int32" )));
+ Assert.assertTrue(message.hasField(f("optional_int64" )));
+ Assert.assertTrue(message.hasField(f("optional_uint32" )));
+ Assert.assertTrue(message.hasField(f("optional_uint64" )));
+ Assert.assertTrue(message.hasField(f("optional_sint32" )));
+ Assert.assertTrue(message.hasField(f("optional_sint64" )));
+ Assert.assertTrue(message.hasField(f("optional_fixed32" )));
+ Assert.assertTrue(message.hasField(f("optional_fixed64" )));
+ Assert.assertTrue(message.hasField(f("optional_sfixed32")));
+ Assert.assertTrue(message.hasField(f("optional_sfixed64")));
+ Assert.assertTrue(message.hasField(f("optional_float" )));
+ Assert.assertTrue(message.hasField(f("optional_double" )));
+ Assert.assertTrue(message.hasField(f("optional_bool" )));
+ Assert.assertTrue(message.hasField(f("optional_string" )));
+ Assert.assertTrue(message.hasField(f("optional_bytes" )));
+
+ Assert.assertTrue(message.hasField(f("optionalgroup" )));
+ Assert.assertTrue(message.hasField(f("optional_nested_message" )));
+ Assert.assertTrue(message.hasField(f("optional_foreign_message")));
+ Assert.assertTrue(message.hasField(f("optional_import_message" )));
+
+ Assert.assertTrue(
+ ((Message)message.getField(f("optionalgroup"))).hasField(groupA));
+ Assert.assertTrue(
+ ((Message)message.getField(f("optional_nested_message")))
+ .hasField(nestedB));
+ Assert.assertTrue(
+ ((Message)message.getField(f("optional_foreign_message")))
+ .hasField(foreignC));
+ Assert.assertTrue(
+ ((Message)message.getField(f("optional_import_message")))
+ .hasField(importD));
+
+ Assert.assertTrue(message.hasField(f("optional_nested_enum" )));
+ Assert.assertTrue(message.hasField(f("optional_foreign_enum")));
+ Assert.assertTrue(message.hasField(f("optional_import_enum" )));
+
+ Assert.assertTrue(message.hasField(f("optional_string_piece")));
+ Assert.assertTrue(message.hasField(f("optional_cord")));
+
+ Assert.assertEquals(101 , message.getField(f("optional_int32" )));
+ Assert.assertEquals(102L , message.getField(f("optional_int64" )));
+ Assert.assertEquals(103 , message.getField(f("optional_uint32" )));
+ Assert.assertEquals(104L , message.getField(f("optional_uint64" )));
+ Assert.assertEquals(105 , message.getField(f("optional_sint32" )));
+ Assert.assertEquals(106L , message.getField(f("optional_sint64" )));
+ Assert.assertEquals(107 , message.getField(f("optional_fixed32" )));
+ Assert.assertEquals(108L , message.getField(f("optional_fixed64" )));
+ Assert.assertEquals(109 , message.getField(f("optional_sfixed32")));
+ Assert.assertEquals(110L , message.getField(f("optional_sfixed64")));
+ Assert.assertEquals(111F , message.getField(f("optional_float" )));
+ Assert.assertEquals(112D , message.getField(f("optional_double" )));
+ Assert.assertEquals(true , message.getField(f("optional_bool" )));
+ Assert.assertEquals("115", message.getField(f("optional_string" )));
+ Assert.assertEquals(toBytes("116"), message.getField(f("optional_bytes")));
+
+ Assert.assertEquals(117,
+ ((Message)message.getField(f("optionalgroup"))).getField(groupA));
+ Assert.assertEquals(118,
+ ((Message)message.getField(f("optional_nested_message")))
+ .getField(nestedB));
+ Assert.assertEquals(119,
+ ((Message)message.getField(f("optional_foreign_message")))
+ .getField(foreignC));
+ Assert.assertEquals(120,
+ ((Message)message.getField(f("optional_import_message")))
+ .getField(importD));
+ Assert.assertEquals(126,
+ ((Message)message.getField(f("optional_public_import_message")))
+ .getField(importE));
+ Assert.assertEquals(127,
+ ((Message)message.getField(f("optional_lazy_message")))
+ .getField(nestedB));
+
+ Assert.assertEquals( nestedBaz, message.getField(f("optional_nested_enum" )));
+ Assert.assertEquals(foreignBaz, message.getField(f("optional_foreign_enum")));
+ Assert.assertEquals( importBaz, message.getField(f("optional_import_enum" )));
+
+ Assert.assertEquals("124", message.getField(f("optional_string_piece")));
+ Assert.assertEquals("125", message.getField(f("optional_cord")));
+
+ // -----------------------------------------------------------------
+
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_int32" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_int64" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_uint32" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_uint64" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_sint32" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_sint64" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_fixed32" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_fixed64" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_sfixed32")));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_sfixed64")));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_float" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_double" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_bool" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_string" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_bytes" )));
+
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeatedgroup" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_nested_message" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_foreign_message")));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_import_message" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_lazy_message" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_nested_enum" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_foreign_enum" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_import_enum" )));
+
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_string_piece")));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_cord")));
+
+ Assert.assertEquals(201 , message.getRepeatedField(f("repeated_int32" ), 0));
+ Assert.assertEquals(202L , message.getRepeatedField(f("repeated_int64" ), 0));
+ Assert.assertEquals(203 , message.getRepeatedField(f("repeated_uint32" ), 0));
+ Assert.assertEquals(204L , message.getRepeatedField(f("repeated_uint64" ), 0));
+ Assert.assertEquals(205 , message.getRepeatedField(f("repeated_sint32" ), 0));
+ Assert.assertEquals(206L , message.getRepeatedField(f("repeated_sint64" ), 0));
+ Assert.assertEquals(207 , message.getRepeatedField(f("repeated_fixed32" ), 0));
+ Assert.assertEquals(208L , message.getRepeatedField(f("repeated_fixed64" ), 0));
+ Assert.assertEquals(209 , message.getRepeatedField(f("repeated_sfixed32"), 0));
+ Assert.assertEquals(210L , message.getRepeatedField(f("repeated_sfixed64"), 0));
+ Assert.assertEquals(211F , message.getRepeatedField(f("repeated_float" ), 0));
+ Assert.assertEquals(212D , message.getRepeatedField(f("repeated_double" ), 0));
+ Assert.assertEquals(true , message.getRepeatedField(f("repeated_bool" ), 0));
+ Assert.assertEquals("215", message.getRepeatedField(f("repeated_string" ), 0));
+ Assert.assertEquals(toBytes("216"), message.getRepeatedField(f("repeated_bytes"), 0));
+
+ Assert.assertEquals(217,
+ ((Message)message.getRepeatedField(f("repeatedgroup"), 0))
+ .getField(repeatedGroupA));
+ Assert.assertEquals(218,
+ ((Message)message.getRepeatedField(f("repeated_nested_message"), 0))
+ .getField(nestedB));
+ Assert.assertEquals(219,
+ ((Message)message.getRepeatedField(f("repeated_foreign_message"), 0))
+ .getField(foreignC));
+ Assert.assertEquals(220,
+ ((Message)message.getRepeatedField(f("repeated_import_message"), 0))
+ .getField(importD));
+ Assert.assertEquals(227,
+ ((Message)message.getRepeatedField(f("repeated_lazy_message"), 0))
+ .getField(nestedB));
+
+ Assert.assertEquals( nestedBar, message.getRepeatedField(f("repeated_nested_enum" ),0));
+ Assert.assertEquals(foreignBar, message.getRepeatedField(f("repeated_foreign_enum"),0));
+ Assert.assertEquals( importBar, message.getRepeatedField(f("repeated_import_enum" ),0));
+
+ Assert.assertEquals("224", message.getRepeatedField(f("repeated_string_piece"), 0));
+ Assert.assertEquals("225", message.getRepeatedField(f("repeated_cord"), 0));
+
+ Assert.assertEquals(301 , message.getRepeatedField(f("repeated_int32" ), 1));
+ Assert.assertEquals(302L , message.getRepeatedField(f("repeated_int64" ), 1));
+ Assert.assertEquals(303 , message.getRepeatedField(f("repeated_uint32" ), 1));
+ Assert.assertEquals(304L , message.getRepeatedField(f("repeated_uint64" ), 1));
+ Assert.assertEquals(305 , message.getRepeatedField(f("repeated_sint32" ), 1));
+ Assert.assertEquals(306L , message.getRepeatedField(f("repeated_sint64" ), 1));
+ Assert.assertEquals(307 , message.getRepeatedField(f("repeated_fixed32" ), 1));
+ Assert.assertEquals(308L , message.getRepeatedField(f("repeated_fixed64" ), 1));
+ Assert.assertEquals(309 , message.getRepeatedField(f("repeated_sfixed32"), 1));
+ Assert.assertEquals(310L , message.getRepeatedField(f("repeated_sfixed64"), 1));
+ Assert.assertEquals(311F , message.getRepeatedField(f("repeated_float" ), 1));
+ Assert.assertEquals(312D , message.getRepeatedField(f("repeated_double" ), 1));
+ Assert.assertEquals(false, message.getRepeatedField(f("repeated_bool" ), 1));
+ Assert.assertEquals("315", message.getRepeatedField(f("repeated_string" ), 1));
+ Assert.assertEquals(toBytes("316"), message.getRepeatedField(f("repeated_bytes"), 1));
+
+ Assert.assertEquals(317,
+ ((Message)message.getRepeatedField(f("repeatedgroup"), 1))
+ .getField(repeatedGroupA));
+ Assert.assertEquals(318,
+ ((Message)message.getRepeatedField(f("repeated_nested_message"), 1))
+ .getField(nestedB));
+ Assert.assertEquals(319,
+ ((Message)message.getRepeatedField(f("repeated_foreign_message"), 1))
+ .getField(foreignC));
+ Assert.assertEquals(320,
+ ((Message)message.getRepeatedField(f("repeated_import_message"), 1))
+ .getField(importD));
+ Assert.assertEquals(327,
+ ((Message)message.getRepeatedField(f("repeated_lazy_message"), 1))
+ .getField(nestedB));
+
+ Assert.assertEquals( nestedBaz, message.getRepeatedField(f("repeated_nested_enum" ),1));
+ Assert.assertEquals(foreignBaz, message.getRepeatedField(f("repeated_foreign_enum"),1));
+ Assert.assertEquals( importBaz, message.getRepeatedField(f("repeated_import_enum" ),1));
+
+ Assert.assertEquals("324", message.getRepeatedField(f("repeated_string_piece"), 1));
+ Assert.assertEquals("325", message.getRepeatedField(f("repeated_cord"), 1));
+
+ // -----------------------------------------------------------------
+
+ Assert.assertTrue(message.hasField(f("default_int32" )));
+ Assert.assertTrue(message.hasField(f("default_int64" )));
+ Assert.assertTrue(message.hasField(f("default_uint32" )));
+ Assert.assertTrue(message.hasField(f("default_uint64" )));
+ Assert.assertTrue(message.hasField(f("default_sint32" )));
+ Assert.assertTrue(message.hasField(f("default_sint64" )));
+ Assert.assertTrue(message.hasField(f("default_fixed32" )));
+ Assert.assertTrue(message.hasField(f("default_fixed64" )));
+ Assert.assertTrue(message.hasField(f("default_sfixed32")));
+ Assert.assertTrue(message.hasField(f("default_sfixed64")));
+ Assert.assertTrue(message.hasField(f("default_float" )));
+ Assert.assertTrue(message.hasField(f("default_double" )));
+ Assert.assertTrue(message.hasField(f("default_bool" )));
+ Assert.assertTrue(message.hasField(f("default_string" )));
+ Assert.assertTrue(message.hasField(f("default_bytes" )));
+
+ Assert.assertTrue(message.hasField(f("default_nested_enum" )));
+ Assert.assertTrue(message.hasField(f("default_foreign_enum")));
+ Assert.assertTrue(message.hasField(f("default_import_enum" )));
+
+ Assert.assertTrue(message.hasField(f("default_string_piece")));
+ Assert.assertTrue(message.hasField(f("default_cord")));
+
+ Assert.assertEquals(401 , message.getField(f("default_int32" )));
+ Assert.assertEquals(402L , message.getField(f("default_int64" )));
+ Assert.assertEquals(403 , message.getField(f("default_uint32" )));
+ Assert.assertEquals(404L , message.getField(f("default_uint64" )));
+ Assert.assertEquals(405 , message.getField(f("default_sint32" )));
+ Assert.assertEquals(406L , message.getField(f("default_sint64" )));
+ Assert.assertEquals(407 , message.getField(f("default_fixed32" )));
+ Assert.assertEquals(408L , message.getField(f("default_fixed64" )));
+ Assert.assertEquals(409 , message.getField(f("default_sfixed32")));
+ Assert.assertEquals(410L , message.getField(f("default_sfixed64")));
+ Assert.assertEquals(411F , message.getField(f("default_float" )));
+ Assert.assertEquals(412D , message.getField(f("default_double" )));
+ Assert.assertEquals(false, message.getField(f("default_bool" )));
+ Assert.assertEquals("415", message.getField(f("default_string" )));
+ Assert.assertEquals(toBytes("416"), message.getField(f("default_bytes")));
+
+ Assert.assertEquals( nestedFoo, message.getField(f("default_nested_enum" )));
+ Assert.assertEquals(foreignFoo, message.getField(f("default_foreign_enum")));
+ Assert.assertEquals( importFoo, message.getField(f("default_import_enum" )));
+
+ Assert.assertEquals("424", message.getField(f("default_string_piece")));
+ Assert.assertEquals("425", message.getField(f("default_cord")));
+
+ Assert.assertTrue(message.hasField(f("oneof_bytes")));
+ Assert.assertEquals(toBytes("604"), message.getField(f("oneof_bytes")));
+
+ if (extensionRegistry == null) {
+ Assert.assertFalse(message.hasField(f("oneof_uint32")));
+ Assert.assertFalse(message.hasField(f("oneof_nested_message")));
+ Assert.assertFalse(message.hasField(f("oneof_string")));
+ } else {
+ Assert.assertTrue(message.hasField(f("oneof_uint32")));
+ Assert.assertTrue(message.hasField(f("oneof_nested_message")));
+ Assert.assertTrue(message.hasField(f("oneof_string")));
+ Assert.assertEquals(601, message.getField(f("oneof_uint32")));
+ Assert.assertEquals(602,
+ ((MessageOrBuilder) message.getField(f("oneof_nested_message")))
+ .getField(nestedB));
+ Assert.assertEquals("603", message.getField(f("oneof_string")));
+ }
+ }
+
+ // -------------------------------------------------------------------
+
+ /**
+ * Assert (using {@code junit.framework.Assert}} that all fields of
+ * {@code message} are cleared, and that getting the fields returns their
+ * default values, using the {@link Message} reflection interface.
+ */
+ public void assertClearViaReflection(MessageOrBuilder message) {
+ // has_blah() should initially be false for all optional fields.
+ Assert.assertFalse(message.hasField(f("optional_int32" )));
+ Assert.assertFalse(message.hasField(f("optional_int64" )));
+ Assert.assertFalse(message.hasField(f("optional_uint32" )));
+ Assert.assertFalse(message.hasField(f("optional_uint64" )));
+ Assert.assertFalse(message.hasField(f("optional_sint32" )));
+ Assert.assertFalse(message.hasField(f("optional_sint64" )));
+ Assert.assertFalse(message.hasField(f("optional_fixed32" )));
+ Assert.assertFalse(message.hasField(f("optional_fixed64" )));
+ Assert.assertFalse(message.hasField(f("optional_sfixed32")));
+ Assert.assertFalse(message.hasField(f("optional_sfixed64")));
+ Assert.assertFalse(message.hasField(f("optional_float" )));
+ Assert.assertFalse(message.hasField(f("optional_double" )));
+ Assert.assertFalse(message.hasField(f("optional_bool" )));
+ Assert.assertFalse(message.hasField(f("optional_string" )));
+ Assert.assertFalse(message.hasField(f("optional_bytes" )));
+
+ Assert.assertFalse(message.hasField(f("optionalgroup" )));
+ Assert.assertFalse(message.hasField(f("optional_nested_message" )));
+ Assert.assertFalse(message.hasField(f("optional_foreign_message")));
+ Assert.assertFalse(message.hasField(f("optional_import_message" )));
+
+ Assert.assertFalse(message.hasField(f("optional_nested_enum" )));
+ Assert.assertFalse(message.hasField(f("optional_foreign_enum")));
+ Assert.assertFalse(message.hasField(f("optional_import_enum" )));
+
+ Assert.assertFalse(message.hasField(f("optional_string_piece")));
+ Assert.assertFalse(message.hasField(f("optional_cord")));
+
+ // Optional fields without defaults are set to zero or something like it.
+ Assert.assertEquals(0 , message.getField(f("optional_int32" )));
+ Assert.assertEquals(0L , message.getField(f("optional_int64" )));
+ Assert.assertEquals(0 , message.getField(f("optional_uint32" )));
+ Assert.assertEquals(0L , message.getField(f("optional_uint64" )));
+ Assert.assertEquals(0 , message.getField(f("optional_sint32" )));
+ Assert.assertEquals(0L , message.getField(f("optional_sint64" )));
+ Assert.assertEquals(0 , message.getField(f("optional_fixed32" )));
+ Assert.assertEquals(0L , message.getField(f("optional_fixed64" )));
+ Assert.assertEquals(0 , message.getField(f("optional_sfixed32")));
+ Assert.assertEquals(0L , message.getField(f("optional_sfixed64")));
+ Assert.assertEquals(0F , message.getField(f("optional_float" )));
+ Assert.assertEquals(0D , message.getField(f("optional_double" )));
+ Assert.assertEquals(false, message.getField(f("optional_bool" )));
+ Assert.assertEquals("" , message.getField(f("optional_string" )));
+ Assert.assertEquals(ByteString.EMPTY, message.getField(f("optional_bytes")));
+
+ // Embedded messages should also be clear.
+ Assert.assertFalse(
+ ((Message)message.getField(f("optionalgroup"))).hasField(groupA));
+ Assert.assertFalse(
+ ((Message)message.getField(f("optional_nested_message")))
+ .hasField(nestedB));
+ Assert.assertFalse(
+ ((Message)message.getField(f("optional_foreign_message")))
+ .hasField(foreignC));
+ Assert.assertFalse(
+ ((Message)message.getField(f("optional_import_message")))
+ .hasField(importD));
+ Assert.assertFalse(
+ ((Message)message.getField(f("optional_public_import_message")))
+ .hasField(importE));
+ Assert.assertFalse(
+ ((Message)message.getField(f("optional_lazy_message")))
+ .hasField(nestedB));
+
+ Assert.assertEquals(0,
+ ((Message)message.getField(f("optionalgroup"))).getField(groupA));
+ Assert.assertEquals(0,
+ ((Message)message.getField(f("optional_nested_message")))
+ .getField(nestedB));
+ Assert.assertEquals(0,
+ ((Message)message.getField(f("optional_foreign_message")))
+ .getField(foreignC));
+ Assert.assertEquals(0,
+ ((Message)message.getField(f("optional_import_message")))
+ .getField(importD));
+ Assert.assertEquals(0,
+ ((Message)message.getField(f("optional_public_import_message")))
+ .getField(importE));
+ Assert.assertEquals(0,
+ ((Message)message.getField(f("optional_lazy_message")))
+ .getField(nestedB));
+
+ // Enums without defaults are set to the first value in the enum.
+ Assert.assertEquals( nestedFoo, message.getField(f("optional_nested_enum" )));
+ Assert.assertEquals(foreignFoo, message.getField(f("optional_foreign_enum")));
+ Assert.assertEquals( importFoo, message.getField(f("optional_import_enum" )));
+
+ Assert.assertEquals("", message.getField(f("optional_string_piece")));
+ Assert.assertEquals("", message.getField(f("optional_cord")));
+
+ // Repeated fields are empty.
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_int32" )));
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_int64" )));
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_uint32" )));
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_uint64" )));
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_sint32" )));
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_sint64" )));
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_fixed32" )));
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_fixed64" )));
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_sfixed32")));
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_sfixed64")));
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_float" )));
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_double" )));
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_bool" )));
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_string" )));
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_bytes" )));
+
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeatedgroup" )));
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_nested_message" )));
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_foreign_message")));
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_import_message" )));
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_lazy_message" )));
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_nested_enum" )));
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_foreign_enum" )));
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_import_enum" )));
+
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_string_piece")));
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_cord")));
+
+ // has_blah() should also be false for all default fields.
+ Assert.assertFalse(message.hasField(f("default_int32" )));
+ Assert.assertFalse(message.hasField(f("default_int64" )));
+ Assert.assertFalse(message.hasField(f("default_uint32" )));
+ Assert.assertFalse(message.hasField(f("default_uint64" )));
+ Assert.assertFalse(message.hasField(f("default_sint32" )));
+ Assert.assertFalse(message.hasField(f("default_sint64" )));
+ Assert.assertFalse(message.hasField(f("default_fixed32" )));
+ Assert.assertFalse(message.hasField(f("default_fixed64" )));
+ Assert.assertFalse(message.hasField(f("default_sfixed32")));
+ Assert.assertFalse(message.hasField(f("default_sfixed64")));
+ Assert.assertFalse(message.hasField(f("default_float" )));
+ Assert.assertFalse(message.hasField(f("default_double" )));
+ Assert.assertFalse(message.hasField(f("default_bool" )));
+ Assert.assertFalse(message.hasField(f("default_string" )));
+ Assert.assertFalse(message.hasField(f("default_bytes" )));
+
+ Assert.assertFalse(message.hasField(f("default_nested_enum" )));
+ Assert.assertFalse(message.hasField(f("default_foreign_enum")));
+ Assert.assertFalse(message.hasField(f("default_import_enum" )));
+
+ Assert.assertFalse(message.hasField(f("default_string_piece" )));
+ Assert.assertFalse(message.hasField(f("default_cord" )));
+
+ // Fields with defaults have their default values (duh).
+ Assert.assertEquals( 41 , message.getField(f("default_int32" )));
+ Assert.assertEquals( 42L , message.getField(f("default_int64" )));
+ Assert.assertEquals( 43 , message.getField(f("default_uint32" )));
+ Assert.assertEquals( 44L , message.getField(f("default_uint64" )));
+ Assert.assertEquals(-45 , message.getField(f("default_sint32" )));
+ Assert.assertEquals( 46L , message.getField(f("default_sint64" )));
+ Assert.assertEquals( 47 , message.getField(f("default_fixed32" )));
+ Assert.assertEquals( 48L , message.getField(f("default_fixed64" )));
+ Assert.assertEquals( 49 , message.getField(f("default_sfixed32")));
+ Assert.assertEquals(-50L , message.getField(f("default_sfixed64")));
+ Assert.assertEquals( 51.5F , message.getField(f("default_float" )));
+ Assert.assertEquals( 52e3D , message.getField(f("default_double" )));
+ Assert.assertEquals(true , message.getField(f("default_bool" )));
+ Assert.assertEquals("hello", message.getField(f("default_string" )));
+ Assert.assertEquals(toBytes("world"), message.getField(f("default_bytes")));
+
+ Assert.assertEquals( nestedBar, message.getField(f("default_nested_enum" )));
+ Assert.assertEquals(foreignBar, message.getField(f("default_foreign_enum")));
+ Assert.assertEquals( importBar, message.getField(f("default_import_enum" )));
+
+ Assert.assertEquals("abc", message.getField(f("default_string_piece")));
+ Assert.assertEquals("123", message.getField(f("default_cord")));
+
+ Assert.assertFalse(message.hasField(f("oneof_uint32")));
+ Assert.assertFalse(message.hasField(f("oneof_nested_message")));
+ Assert.assertFalse(message.hasField(f("oneof_string")));
+ Assert.assertFalse(message.hasField(f("oneof_bytes")));
+
+ Assert.assertEquals(0, message.getField(f("oneof_uint32")));
+ Assert.assertEquals("", message.getField(f("oneof_string")));
+ Assert.assertEquals(toBytes(""), message.getField(f("oneof_bytes")));
+ }
+
+
+ // ---------------------------------------------------------------
+
+ public void assertRepeatedFieldsModifiedViaReflection(
+ MessageOrBuilder message) {
+ // ModifyRepeatedFields only sets the second repeated element of each
+ // field. In addition to verifying this, we also verify that the first
+ // element and size were *not* modified.
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_int32" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_int64" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_uint32" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_uint64" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_sint32" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_sint64" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_fixed32" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_fixed64" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_sfixed32")));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_sfixed64")));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_float" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_double" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_bool" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_string" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_bytes" )));
+
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeatedgroup" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_nested_message" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_foreign_message")));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_import_message" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_lazy_message" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_nested_enum" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_foreign_enum" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_import_enum" )));
+
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_string_piece")));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_cord")));
+
+ Assert.assertEquals(201 , message.getRepeatedField(f("repeated_int32" ), 0));
+ Assert.assertEquals(202L , message.getRepeatedField(f("repeated_int64" ), 0));
+ Assert.assertEquals(203 , message.getRepeatedField(f("repeated_uint32" ), 0));
+ Assert.assertEquals(204L , message.getRepeatedField(f("repeated_uint64" ), 0));
+ Assert.assertEquals(205 , message.getRepeatedField(f("repeated_sint32" ), 0));
+ Assert.assertEquals(206L , message.getRepeatedField(f("repeated_sint64" ), 0));
+ Assert.assertEquals(207 , message.getRepeatedField(f("repeated_fixed32" ), 0));
+ Assert.assertEquals(208L , message.getRepeatedField(f("repeated_fixed64" ), 0));
+ Assert.assertEquals(209 , message.getRepeatedField(f("repeated_sfixed32"), 0));
+ Assert.assertEquals(210L , message.getRepeatedField(f("repeated_sfixed64"), 0));
+ Assert.assertEquals(211F , message.getRepeatedField(f("repeated_float" ), 0));
+ Assert.assertEquals(212D , message.getRepeatedField(f("repeated_double" ), 0));
+ Assert.assertEquals(true , message.getRepeatedField(f("repeated_bool" ), 0));
+ Assert.assertEquals("215", message.getRepeatedField(f("repeated_string" ), 0));
+ Assert.assertEquals(toBytes("216"), message.getRepeatedField(f("repeated_bytes"), 0));
+
+ Assert.assertEquals(217,
+ ((Message)message.getRepeatedField(f("repeatedgroup"), 0))
+ .getField(repeatedGroupA));
+ Assert.assertEquals(218,
+ ((Message)message.getRepeatedField(f("repeated_nested_message"), 0))
+ .getField(nestedB));
+ Assert.assertEquals(219,
+ ((Message)message.getRepeatedField(f("repeated_foreign_message"), 0))
+ .getField(foreignC));
+ Assert.assertEquals(220,
+ ((Message)message.getRepeatedField(f("repeated_import_message"), 0))
+ .getField(importD));
+ Assert.assertEquals(227,
+ ((Message)message.getRepeatedField(f("repeated_lazy_message"), 0))
+ .getField(nestedB));
+
+ Assert.assertEquals( nestedBar, message.getRepeatedField(f("repeated_nested_enum" ),0));
+ Assert.assertEquals(foreignBar, message.getRepeatedField(f("repeated_foreign_enum"),0));
+ Assert.assertEquals( importBar, message.getRepeatedField(f("repeated_import_enum" ),0));
+
+ Assert.assertEquals("224", message.getRepeatedField(f("repeated_string_piece"), 0));
+ Assert.assertEquals("225", message.getRepeatedField(f("repeated_cord"), 0));
+
+ Assert.assertEquals(501 , message.getRepeatedField(f("repeated_int32" ), 1));
+ Assert.assertEquals(502L , message.getRepeatedField(f("repeated_int64" ), 1));
+ Assert.assertEquals(503 , message.getRepeatedField(f("repeated_uint32" ), 1));
+ Assert.assertEquals(504L , message.getRepeatedField(f("repeated_uint64" ), 1));
+ Assert.assertEquals(505 , message.getRepeatedField(f("repeated_sint32" ), 1));
+ Assert.assertEquals(506L , message.getRepeatedField(f("repeated_sint64" ), 1));
+ Assert.assertEquals(507 , message.getRepeatedField(f("repeated_fixed32" ), 1));
+ Assert.assertEquals(508L , message.getRepeatedField(f("repeated_fixed64" ), 1));
+ Assert.assertEquals(509 , message.getRepeatedField(f("repeated_sfixed32"), 1));
+ Assert.assertEquals(510L , message.getRepeatedField(f("repeated_sfixed64"), 1));
+ Assert.assertEquals(511F , message.getRepeatedField(f("repeated_float" ), 1));
+ Assert.assertEquals(512D , message.getRepeatedField(f("repeated_double" ), 1));
+ Assert.assertEquals(true , message.getRepeatedField(f("repeated_bool" ), 1));
+ Assert.assertEquals("515", message.getRepeatedField(f("repeated_string" ), 1));
+ Assert.assertEquals(toBytes("516"), message.getRepeatedField(f("repeated_bytes"), 1));
+
+ Assert.assertEquals(517,
+ ((Message)message.getRepeatedField(f("repeatedgroup"), 1))
+ .getField(repeatedGroupA));
+ Assert.assertEquals(518,
+ ((Message)message.getRepeatedField(f("repeated_nested_message"), 1))
+ .getField(nestedB));
+ Assert.assertEquals(519,
+ ((Message)message.getRepeatedField(f("repeated_foreign_message"), 1))
+ .getField(foreignC));
+ Assert.assertEquals(520,
+ ((Message)message.getRepeatedField(f("repeated_import_message"), 1))
+ .getField(importD));
+ Assert.assertEquals(527,
+ ((Message)message.getRepeatedField(f("repeated_lazy_message"), 1))
+ .getField(nestedB));
+
+ Assert.assertEquals( nestedFoo, message.getRepeatedField(f("repeated_nested_enum" ),1));
+ Assert.assertEquals(foreignFoo, message.getRepeatedField(f("repeated_foreign_enum"),1));
+ Assert.assertEquals( importFoo, message.getRepeatedField(f("repeated_import_enum" ),1));
+
+ Assert.assertEquals("524", message.getRepeatedField(f("repeated_string_piece"), 1));
+ Assert.assertEquals("525", message.getRepeatedField(f("repeated_cord"), 1));
+ }
+
+ public void setPackedFieldsViaReflection(Message.Builder message) {
+ message.addRepeatedField(f("packed_int32" ), 601 );
+ message.addRepeatedField(f("packed_int64" ), 602L);
+ message.addRepeatedField(f("packed_uint32" ), 603 );
+ message.addRepeatedField(f("packed_uint64" ), 604L);
+ message.addRepeatedField(f("packed_sint32" ), 605 );
+ message.addRepeatedField(f("packed_sint64" ), 606L);
+ message.addRepeatedField(f("packed_fixed32" ), 607 );
+ message.addRepeatedField(f("packed_fixed64" ), 608L);
+ message.addRepeatedField(f("packed_sfixed32"), 609 );
+ message.addRepeatedField(f("packed_sfixed64"), 610L);
+ message.addRepeatedField(f("packed_float" ), 611F);
+ message.addRepeatedField(f("packed_double" ), 612D);
+ message.addRepeatedField(f("packed_bool" ), true);
+ message.addRepeatedField(f("packed_enum" ), foreignBar);
+ // Add a second one of each field.
+ message.addRepeatedField(f("packed_int32" ), 701 );
+ message.addRepeatedField(f("packed_int64" ), 702L);
+ message.addRepeatedField(f("packed_uint32" ), 703 );
+ message.addRepeatedField(f("packed_uint64" ), 704L);
+ message.addRepeatedField(f("packed_sint32" ), 705 );
+ message.addRepeatedField(f("packed_sint64" ), 706L);
+ message.addRepeatedField(f("packed_fixed32" ), 707 );
+ message.addRepeatedField(f("packed_fixed64" ), 708L);
+ message.addRepeatedField(f("packed_sfixed32"), 709 );
+ message.addRepeatedField(f("packed_sfixed64"), 710L);
+ message.addRepeatedField(f("packed_float" ), 711F);
+ message.addRepeatedField(f("packed_double" ), 712D);
+ message.addRepeatedField(f("packed_bool" ), false);
+ message.addRepeatedField(f("packed_enum" ), foreignBaz);
+ }
+
+ public void assertPackedFieldsSetViaReflection(MessageOrBuilder message) {
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_int32" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_int64" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_uint32" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_uint64" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_sint32" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_sint64" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_fixed32" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_fixed64" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_sfixed32")));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_sfixed64")));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_float" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_double" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_bool" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_enum" )));
+ Assert.assertEquals(601 , message.getRepeatedField(f("packed_int32" ), 0));
+ Assert.assertEquals(602L , message.getRepeatedField(f("packed_int64" ), 0));
+ Assert.assertEquals(603 , message.getRepeatedField(f("packed_uint32" ), 0));
+ Assert.assertEquals(604L , message.getRepeatedField(f("packed_uint64" ), 0));
+ Assert.assertEquals(605 , message.getRepeatedField(f("packed_sint32" ), 0));
+ Assert.assertEquals(606L , message.getRepeatedField(f("packed_sint64" ), 0));
+ Assert.assertEquals(607 , message.getRepeatedField(f("packed_fixed32" ), 0));
+ Assert.assertEquals(608L , message.getRepeatedField(f("packed_fixed64" ), 0));
+ Assert.assertEquals(609 , message.getRepeatedField(f("packed_sfixed32"), 0));
+ Assert.assertEquals(610L , message.getRepeatedField(f("packed_sfixed64"), 0));
+ Assert.assertEquals(611F , message.getRepeatedField(f("packed_float" ), 0));
+ Assert.assertEquals(612D , message.getRepeatedField(f("packed_double" ), 0));
+ Assert.assertEquals(true , message.getRepeatedField(f("packed_bool" ), 0));
+ Assert.assertEquals(foreignBar, message.getRepeatedField(f("packed_enum" ),0));
+ Assert.assertEquals(701 , message.getRepeatedField(f("packed_int32" ), 1));
+ Assert.assertEquals(702L , message.getRepeatedField(f("packed_int64" ), 1));
+ Assert.assertEquals(703 , message.getRepeatedField(f("packed_uint32" ), 1));
+ Assert.assertEquals(704L , message.getRepeatedField(f("packed_uint64" ), 1));
+ Assert.assertEquals(705 , message.getRepeatedField(f("packed_sint32" ), 1));
+ Assert.assertEquals(706L , message.getRepeatedField(f("packed_sint64" ), 1));
+ Assert.assertEquals(707 , message.getRepeatedField(f("packed_fixed32" ), 1));
+ Assert.assertEquals(708L , message.getRepeatedField(f("packed_fixed64" ), 1));
+ Assert.assertEquals(709 , message.getRepeatedField(f("packed_sfixed32"), 1));
+ Assert.assertEquals(710L , message.getRepeatedField(f("packed_sfixed64"), 1));
+ Assert.assertEquals(711F , message.getRepeatedField(f("packed_float" ), 1));
+ Assert.assertEquals(712D , message.getRepeatedField(f("packed_double" ), 1));
+ Assert.assertEquals(false, message.getRepeatedField(f("packed_bool" ), 1));
+ Assert.assertEquals(foreignBaz, message.getRepeatedField(f("packed_enum" ),1));
+ }
+
+ /**
+ * Verifies that the reflection setters for the given.Builder object throw a
+ * NullPointerException if they are passed a null value. Uses Assert to throw an
+ * appropriate assertion failure, if the condition is not verified.
+ */
+ public void assertReflectionSettersRejectNull(Message.Builder builder)
+ throws Exception {
+ try {
+ builder.setField(f("optional_string"), null);
+ Assert.fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.setField(f("optional_bytes"), null);
+ Assert.fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.setField(f("optional_nested_enum"), null);
+ Assert.fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.setField(f("optional_nested_message"),
+ (TestAllTypes.NestedMessage) null);
+ Assert.fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.setField(f("optional_nested_message"),
+ (TestAllTypes.NestedMessage.Builder) null);
+ Assert.fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+
+ try {
+ builder.addRepeatedField(f("repeated_string"), null);
+ Assert.fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.addRepeatedField(f("repeated_bytes"), null);
+ Assert.fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.addRepeatedField(f("repeated_nested_enum"), null);
+ Assert.fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.addRepeatedField(f("repeated_nested_message"), null);
+ Assert.fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ }
+
+ /**
+ * Verifies that the reflection repeated setters for the given Builder object throw a
+ * NullPointerException if they are passed a null value. Uses Assert to throw an appropriate
+ * assertion failure, if the condition is not verified.
+ */
+ public void assertReflectionRepeatedSettersRejectNull(Message.Builder builder)
+ throws Exception {
+ builder.addRepeatedField(f("repeated_string"), "one");
+ try {
+ builder.setRepeatedField(f("repeated_string"), 0, null);
+ Assert.fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+
+ builder.addRepeatedField(f("repeated_bytes"), toBytes("one"));
+ try {
+ builder.setRepeatedField(f("repeated_bytes"), 0, null);
+ Assert.fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+
+ builder.addRepeatedField(f("repeated_nested_enum"), nestedBaz);
+ try {
+ builder.setRepeatedField(f("repeated_nested_enum"), 0, null);
+ Assert.fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+
+ builder.addRepeatedField(
+ f("repeated_nested_message"),
+ TestAllTypes.NestedMessage.newBuilder().setBb(218).build());
+ try {
+ builder.setRepeatedField(f("repeated_nested_message"), 0, null);
+ Assert.fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ }
+ }
+
+ /**
+ * @param filePath The path relative to
+ * {@link #getTestDataDir}.
+ */
+ public static String readTextFromFile(String filePath) {
+ return readBytesFromFile(filePath).toStringUtf8();
+ }
+
+ private static File getTestDataDir() {
+ // Search each parent directory looking for "src/google/protobuf".
+ File ancestor = new File(".");
+ try {
+ ancestor = ancestor.getCanonicalFile();
+ } catch (IOException e) {
+ throw new RuntimeException(
+ "Couldn't get canonical name of working directory.", e);
+ }
+ while (ancestor != null && ancestor.exists()) {
+ if (new File(ancestor, "src/google/protobuf").exists()) {
+ return new File(ancestor, "src/google/protobuf/testdata");
+ }
+ ancestor = ancestor.getParentFile();
+ }
+
+ throw new RuntimeException(
+ "Could not find golden files. This test must be run from within the " +
+ "protobuf source package so that it can read test data files from the " +
+ "C++ source tree.");
+ }
+
+ /**
+ * @param filename The path relative to
+ * {@link #getTestDataDir}.
+ */
+ public static ByteString readBytesFromFile(String filename) {
+ File fullPath = new File(getTestDataDir(), filename);
+ try {
+ RandomAccessFile file = new RandomAccessFile(fullPath, "r");
+ byte[] content = new byte[(int) file.length()];
+ file.readFully(content);
+ return ByteString.copyFrom(content);
+ } catch (IOException e) {
+ // Throw a RuntimeException here so that we can call this function from
+ // static initializers.
+ throw new IllegalArgumentException(
+ "Couldn't read file: " + fullPath.getPath(), e);
+ }
+ }
+
+ /**
+ * Get the bytes of the "golden message". This is a serialized TestAllTypes
+ * with all fields set as they would be by
+ * {@link #setAllFields(TestAllTypes.Builder)}, but it is loaded from a file
+ * on disk rather than generated dynamically. The file is actually generated
+ * by C++ code, so testing against it verifies compatibility with C++.
+ */
+ public static ByteString getGoldenMessage() {
+ if (goldenMessage == null) {
+ goldenMessage = readBytesFromFile("golden_message_oneof_implemented");
+ }
+ return goldenMessage;
+ }
+ private static ByteString goldenMessage = null;
+
+ /**
+ * Get the bytes of the "golden packed fields message". This is a serialized
+ * TestPackedTypes with all fields set as they would be by
+ * {@link #setPackedFields(TestPackedTypes.Builder)}, but it is loaded from a
+ * file on disk rather than generated dynamically. The file is actually
+ * generated by C++ code, so testing against it verifies compatibility with
+ * C++.
+ */
+ public static ByteString getGoldenPackedFieldsMessage() {
+ if (goldenPackedFieldsMessage == null) {
+ goldenPackedFieldsMessage =
+ readBytesFromFile("golden_packed_fields_message");
+ }
+ return goldenPackedFieldsMessage;
+ }
+ private static ByteString goldenPackedFieldsMessage = null;
+
+ /**
+ * Mock implementation of {@link GeneratedMessage.BuilderParent} for testing.
+ *
+ * @author jonp@google.com (Jon Perlow)
+ */
+ public static class MockBuilderParent
+ implements GeneratedMessage.BuilderParent {
+
+ private int invalidations;
+
+ //@Override (Java 1.6 override semantics, but we must support 1.5)
+ public void markDirty() {
+ invalidations++;
+ }
+
+ public int getInvalidationCount() {
+ return invalidations;
+ }
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/TextFormatTest.java b/java/core/src/test/java/com/google/protobuf/TextFormatTest.java
new file mode 100644
index 00000000..1df4fad7
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/TextFormatTest.java
@@ -0,0 +1,1021 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// 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 com.google.protobuf.Descriptors.FieldDescriptor;
+import com.google.protobuf.TextFormat.Parser.SingularOverwritePolicy;
+import protobuf_unittest.UnittestMset.TestMessageSetExtension1;
+import protobuf_unittest.UnittestMset.TestMessageSetExtension2;
+import protobuf_unittest.UnittestProto.OneString;
+import protobuf_unittest.UnittestProto.TestAllExtensions;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.TestAllTypes.NestedMessage;
+import protobuf_unittest.UnittestProto.TestEmptyMessage;
+import protobuf_unittest.UnittestProto.TestOneof2;
+import proto2_wireformat_unittest.UnittestMsetWireFormat.TestMessageSet;
+
+import junit.framework.TestCase;
+
+import java.io.StringReader;
+
+/**
+ * Test case for {@link TextFormat}.
+ *
+ * TODO(wenboz): ExtensionTest and rest of text_format_unittest.cc.
+ *
+ * @author wenboz@google.com (Wenbo Zhu)
+ */
+public class TextFormatTest extends TestCase {
+
+ // A basic string with different escapable characters for testing.
+ private final static String kEscapeTestString =
+ "\"A string with ' characters \n and \r newlines and \t tabs and \001 "
+ + "slashes \\";
+
+ // A representation of the above string with all the characters escaped.
+ private final static String kEscapeTestStringEscaped =
+ "\\\"A string with \\' characters \\n and \\r newlines "
+ + "and \\t tabs and \\001 slashes \\\\";
+
+ private static String allFieldsSetText = TestUtil.readTextFromFile(
+ "text_format_unittest_data_oneof_implemented.txt");
+ private static String allExtensionsSetText = TestUtil.readTextFromFile(
+ "text_format_unittest_extensions_data.txt");
+
+ private static String exoticText =
+ "repeated_int32: -1\n" +
+ "repeated_int32: -2147483648\n" +
+ "repeated_int64: -1,\n" +
+ "repeated_int64: -9223372036854775808\n" +
+ "repeated_uint32: 4294967295\n" +
+ "repeated_uint32: 2147483648\n" +
+ "repeated_uint64: 18446744073709551615\n" +
+ "repeated_uint64: 9223372036854775808\n" +
+ "repeated_double: 123.0\n" +
+ "repeated_double: 123.5\n" +
+ "repeated_double: 0.125\n" +
+ "repeated_double: .125\n" +
+ "repeated_double: -.125\n" +
+ "repeated_double: 1.23E17\n" +
+ "repeated_double: 1.23E+17\n" +
+ "repeated_double: -1.23e-17\n" +
+ "repeated_double: .23e+17\n" +
+ "repeated_double: -.23E17\n" +
+ "repeated_double: 1.235E22\n" +
+ "repeated_double: 1.235E-18\n" +
+ "repeated_double: 123.456789\n" +
+ "repeated_double: Infinity\n" +
+ "repeated_double: -Infinity\n" +
+ "repeated_double: NaN\n" +
+ "repeated_string: \"\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\"" +
+ "\\341\\210\\264\"\n" +
+ "repeated_bytes: \"\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\"\\376\"\n";
+
+ private static String canonicalExoticText =
+ exoticText.replace(": .", ": 0.").replace(": -.", ": -0.") // short-form double
+ .replace("23e", "23E").replace("E+", "E").replace("0.23E17", "2.3E16").replace(",", "");
+
+ private String messageSetText =
+ "[protobuf_unittest.TestMessageSetExtension1] {\n" +
+ " i: 123\n" +
+ "}\n" +
+ "[protobuf_unittest.TestMessageSetExtension2] {\n" +
+ " str: \"foo\"\n" +
+ "}\n";
+
+ private String messageSetTextWithRepeatedExtension =
+ "[protobuf_unittest.TestMessageSetExtension1] {\n" +
+ " i: 123\n" +
+ "}\n" +
+ "[protobuf_unittest.TestMessageSetExtension1] {\n" +
+ " i: 456\n" +
+ "}\n";
+
+
+ private final TextFormat.Parser parserWithOverwriteForbidden =
+ TextFormat.Parser.newBuilder()
+ .setSingularOverwritePolicy(
+ SingularOverwritePolicy.FORBID_SINGULAR_OVERWRITES)
+ .build();
+
+ private final TextFormat.Parser defaultParser =
+ TextFormat.Parser.newBuilder().build();
+
+ /** Print TestAllTypes and compare with golden file. */
+ public void testPrintMessage() throws Exception {
+ String javaText = TextFormat.printToString(TestUtil.getAllSet());
+
+ // Java likes to add a trailing ".0" to floats and doubles. C printf
+ // (with %g format) does not. Our golden files are used for both
+ // C++ and Java TextFormat classes, so we need to conform.
+ javaText = javaText.replace(".0\n", "\n");
+
+ assertEquals(allFieldsSetText, javaText);
+ }
+
+ /** Print TestAllTypes as Builder and compare with golden file. */
+ public void testPrintMessageBuilder() throws Exception {
+ String javaText = TextFormat.printToString(TestUtil.getAllSetBuilder());
+
+ // Java likes to add a trailing ".0" to floats and doubles. C printf
+ // (with %g format) does not. Our golden files are used for both
+ // C++ and Java TextFormat classes, so we need to conform.
+ javaText = javaText.replace(".0\n", "\n");
+
+ assertEquals(allFieldsSetText, javaText);
+ }
+
+ /** Print TestAllExtensions and compare with golden file. */
+ public void testPrintExtensions() throws Exception {
+ String javaText = TextFormat.printToString(TestUtil.getAllExtensionsSet());
+
+ // Java likes to add a trailing ".0" to floats and doubles. C printf
+ // (with %g format) does not. Our golden files are used for both
+ // C++ and Java TextFormat classes, so we need to conform.
+ javaText = javaText.replace(".0\n", "\n");
+
+ assertEquals(allExtensionsSetText, javaText);
+ }
+
+ // Creates an example unknown field set.
+ private UnknownFieldSet makeUnknownFieldSet() {
+ return UnknownFieldSet.newBuilder()
+ .addField(5,
+ UnknownFieldSet.Field.newBuilder()
+ .addVarint(1)
+ .addFixed32(2)
+ .addFixed64(3)
+ .addLengthDelimited(ByteString.copyFromUtf8("4"))
+ .addGroup(
+ UnknownFieldSet.newBuilder()
+ .addField(10,
+ UnknownFieldSet.Field.newBuilder()
+ .addVarint(5)
+ .build())
+ .build())
+ .build())
+ .addField(8,
+ UnknownFieldSet.Field.newBuilder()
+ .addVarint(1)
+ .addVarint(2)
+ .addVarint(3)
+ .build())
+ .addField(15,
+ UnknownFieldSet.Field.newBuilder()
+ .addVarint(0xABCDEF1234567890L)
+ .addFixed32(0xABCD1234)
+ .addFixed64(0xABCDEF1234567890L)
+ .build())
+ .build();
+ }
+
+ public void testPrintUnknownFields() throws Exception {
+ // Test printing of unknown fields in a message.
+
+ TestEmptyMessage message =
+ TestEmptyMessage.newBuilder()
+ .setUnknownFields(makeUnknownFieldSet())
+ .build();
+
+ assertEquals(
+ "5: 1\n" +
+ "5: 0x00000002\n" +
+ "5: 0x0000000000000003\n" +
+ "5: \"4\"\n" +
+ "5 {\n" +
+ " 10: 5\n" +
+ "}\n" +
+ "8: 1\n" +
+ "8: 2\n" +
+ "8: 3\n" +
+ "15: 12379813812177893520\n" +
+ "15: 0xabcd1234\n" +
+ "15: 0xabcdef1234567890\n",
+ TextFormat.printToString(message));
+ }
+
+ public void testPrintField() throws Exception {
+ final FieldDescriptor dataField =
+ OneString.getDescriptor().findFieldByName("data");
+ assertEquals(
+ "data: \"test data\"\n",
+ TextFormat.printFieldToString(dataField, "test data"));
+
+ final FieldDescriptor optionalField =
+ TestAllTypes.getDescriptor().findFieldByName("optional_nested_message");
+ final Object value = NestedMessage.newBuilder().setBb(42).build();
+
+ assertEquals(
+ "optional_nested_message {\n bb: 42\n}\n",
+ TextFormat.printFieldToString(optionalField, value));
+ }
+
+ /**
+ * Helper to construct a ByteString from a String containing only 8-bit
+ * characters. The characters are converted directly to bytes, *not*
+ * encoded using UTF-8.
+ */
+ private ByteString bytes(String str) {
+ return ByteString.copyFrom(str.getBytes(Internal.ISO_8859_1));
+ }
+
+ /**
+ * Helper to construct a ByteString from a bunch of bytes. The inputs are
+ * actually ints so that I can use hex notation and not get stupid errors
+ * about precision.
+ */
+ private ByteString bytes(int... bytesAsInts) {
+ byte[] bytes = new byte[bytesAsInts.length];
+ for (int i = 0; i < bytesAsInts.length; i++) {
+ bytes[i] = (byte) bytesAsInts[i];
+ }
+ return ByteString.copyFrom(bytes);
+ }
+
+ public void testPrintExotic() throws Exception {
+ Message message = TestAllTypes.newBuilder()
+ // Signed vs. unsigned numbers.
+ .addRepeatedInt32 (-1)
+ .addRepeatedUint32(-1)
+ .addRepeatedInt64 (-1)
+ .addRepeatedUint64(-1)
+
+ .addRepeatedInt32 (1 << 31)
+ .addRepeatedUint32(1 << 31)
+ .addRepeatedInt64 (1L << 63)
+ .addRepeatedUint64(1L << 63)
+
+ // Floats of various precisions and exponents.
+ .addRepeatedDouble(123)
+ .addRepeatedDouble(123.5)
+ .addRepeatedDouble(0.125)
+ .addRepeatedDouble(.125)
+ .addRepeatedDouble(-.125)
+ .addRepeatedDouble(123e15)
+ .addRepeatedDouble(123e15)
+ .addRepeatedDouble(-1.23e-17)
+ .addRepeatedDouble(.23e17)
+ .addRepeatedDouble(-23e15)
+ .addRepeatedDouble(123.5e20)
+ .addRepeatedDouble(123.5e-20)
+ .addRepeatedDouble(123.456789)
+ .addRepeatedDouble(Double.POSITIVE_INFINITY)
+ .addRepeatedDouble(Double.NEGATIVE_INFINITY)
+ .addRepeatedDouble(Double.NaN)
+
+ // Strings and bytes that needing escaping.
+ .addRepeatedString("\0\001\007\b\f\n\r\t\013\\\'\"\u1234")
+ .addRepeatedBytes(bytes("\0\001\007\b\f\n\r\t\013\\\'\"\u00fe"))
+ .build();
+
+ assertEquals(canonicalExoticText, message.toString());
+ }
+
+ public void testPrintMessageSet() throws Exception {
+ TestMessageSet messageSet =
+ TestMessageSet.newBuilder()
+ .setExtension(
+ TestMessageSetExtension1.messageSetExtension,
+ TestMessageSetExtension1.newBuilder().setI(123).build())
+ .setExtension(
+ TestMessageSetExtension2.messageSetExtension,
+ TestMessageSetExtension2.newBuilder().setStr("foo").build())
+ .build();
+
+ assertEquals(messageSetText, messageSet.toString());
+ }
+
+ // =================================================================
+
+ public void testParse() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TextFormat.merge(allFieldsSetText, builder);
+ TestUtil.assertAllFieldsSet(builder.build());
+ }
+
+ public void testParseReader() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TextFormat.merge(new StringReader(allFieldsSetText), builder);
+ TestUtil.assertAllFieldsSet(builder.build());
+ }
+
+ public void testParseExtensions() throws Exception {
+ TestAllExtensions.Builder builder = TestAllExtensions.newBuilder();
+ TextFormat.merge(allExtensionsSetText,
+ TestUtil.getExtensionRegistry(),
+ builder);
+ TestUtil.assertAllExtensionsSet(builder.build());
+ }
+
+ public void testParseCompatibility() throws Exception {
+ String original = "repeated_float: inf\n" +
+ "repeated_float: -inf\n" +
+ "repeated_float: nan\n" +
+ "repeated_float: inff\n" +
+ "repeated_float: -inff\n" +
+ "repeated_float: nanf\n" +
+ "repeated_float: 1.0f\n" +
+ "repeated_float: infinityf\n" +
+ "repeated_float: -Infinityf\n" +
+ "repeated_double: infinity\n" +
+ "repeated_double: -infinity\n" +
+ "repeated_double: nan\n";
+ String canonical = "repeated_float: Infinity\n" +
+ "repeated_float: -Infinity\n" +
+ "repeated_float: NaN\n" +
+ "repeated_float: Infinity\n" +
+ "repeated_float: -Infinity\n" +
+ "repeated_float: NaN\n" +
+ "repeated_float: 1.0\n" +
+ "repeated_float: Infinity\n" +
+ "repeated_float: -Infinity\n" +
+ "repeated_double: Infinity\n" +
+ "repeated_double: -Infinity\n" +
+ "repeated_double: NaN\n";
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TextFormat.merge(original, builder);
+ assertEquals(canonical, builder.build().toString());
+ }
+
+ public void testParseExotic() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TextFormat.merge(exoticText, builder);
+
+ // Too lazy to check things individually. Don't try to debug this
+ // if testPrintExotic() is failing.
+ assertEquals(canonicalExoticText, builder.build().toString());
+ }
+
+ public void testParseMessageSet() throws Exception {
+ ExtensionRegistry extensionRegistry = ExtensionRegistry.newInstance();
+ extensionRegistry.add(TestMessageSetExtension1.messageSetExtension);
+ extensionRegistry.add(TestMessageSetExtension2.messageSetExtension);
+
+ TestMessageSet.Builder builder = TestMessageSet.newBuilder();
+ TextFormat.merge(messageSetText, extensionRegistry, builder);
+ TestMessageSet messageSet = builder.build();
+
+ assertTrue(messageSet.hasExtension(
+ TestMessageSetExtension1.messageSetExtension));
+ assertEquals(123, messageSet.getExtension(
+ TestMessageSetExtension1.messageSetExtension).getI());
+ assertTrue(messageSet.hasExtension(
+ TestMessageSetExtension2.messageSetExtension));
+ assertEquals("foo", messageSet.getExtension(
+ TestMessageSetExtension2.messageSetExtension).getStr());
+
+ builder = TestMessageSet.newBuilder();
+ TextFormat.merge(messageSetTextWithRepeatedExtension, extensionRegistry,
+ builder);
+ messageSet = builder.build();
+ assertEquals(456, messageSet.getExtension(
+ TestMessageSetExtension1.messageSetExtension).getI());
+ }
+
+ public void testParseMessageSetWithOverwriteForbidden() throws Exception {
+ ExtensionRegistry extensionRegistry = ExtensionRegistry.newInstance();
+ extensionRegistry.add(TestMessageSetExtension1.messageSetExtension);
+ extensionRegistry.add(TestMessageSetExtension2.messageSetExtension);
+
+ TestMessageSet.Builder builder = TestMessageSet.newBuilder();
+ parserWithOverwriteForbidden.merge(
+ messageSetText, extensionRegistry, builder);
+ TestMessageSet messageSet = builder.build();
+ assertEquals(123, messageSet.getExtension(
+ TestMessageSetExtension1.messageSetExtension).getI());
+ assertEquals("foo", messageSet.getExtension(
+ TestMessageSetExtension2.messageSetExtension).getStr());
+
+ builder = TestMessageSet.newBuilder();
+ try {
+ parserWithOverwriteForbidden.merge(
+ messageSetTextWithRepeatedExtension, extensionRegistry, builder);
+ fail("expected parse exception");
+ } catch (TextFormat.ParseException e) {
+ assertEquals("6:1: Non-repeated field "
+ + "\"protobuf_unittest.TestMessageSetExtension1.message_set_extension\""
+ + " cannot be overwritten.",
+ e.getMessage());
+ }
+ }
+
+ public void testParseNumericEnum() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TextFormat.merge("optional_nested_enum: 2", builder);
+ assertEquals(TestAllTypes.NestedEnum.BAR, builder.getOptionalNestedEnum());
+ }
+
+ public void testParseAngleBrackets() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TextFormat.merge("OptionalGroup: < a: 1 >", builder);
+ assertTrue(builder.hasOptionalGroup());
+ assertEquals(1, builder.getOptionalGroup().getA());
+ }
+
+ public void testParseComment() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TextFormat.merge(
+ "# this is a comment\n" +
+ "optional_int32: 1 # another comment\n" +
+ "optional_int64: 2\n" +
+ "# EOF comment", builder);
+ assertEquals(1, builder.getOptionalInt32());
+ assertEquals(2, builder.getOptionalInt64());
+ }
+
+ private void assertParseError(String error, String text) {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ try {
+ TextFormat.merge(text, TestUtil.getExtensionRegistry(), builder);
+ fail("Expected parse exception.");
+ } catch (TextFormat.ParseException e) {
+ assertEquals(error, e.getMessage());
+ }
+ }
+
+
+ private void assertParseErrorWithOverwriteForbidden(String error,
+ String text) {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ try {
+ parserWithOverwriteForbidden.merge(
+ text, TestUtil.getExtensionRegistry(), builder);
+ fail("Expected parse exception.");
+ } catch (TextFormat.ParseException e) {
+ assertEquals(error, e.getMessage());
+ }
+ }
+
+ private TestAllTypes assertParseSuccessWithOverwriteForbidden(
+ String text) throws TextFormat.ParseException {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ parserWithOverwriteForbidden.merge(
+ text, TestUtil.getExtensionRegistry(), builder);
+ return builder.build();
+ }
+
+ public void testParseErrors() throws Exception {
+ assertParseError(
+ "1:16: Expected \":\".",
+ "optional_int32 123");
+ assertParseError(
+ "1:23: Expected identifier. Found '?'",
+ "optional_nested_enum: ?");
+ assertParseError(
+ "1:18: Couldn't parse integer: Number must be positive: -1",
+ "optional_uint32: -1");
+ assertParseError(
+ "1:17: Couldn't parse integer: Number out of range for 32-bit signed " +
+ "integer: 82301481290849012385230157",
+ "optional_int32: 82301481290849012385230157");
+ assertParseError(
+ "1:16: Expected \"true\" or \"false\".",
+ "optional_bool: maybe");
+ assertParseError(
+ "1:16: Expected \"true\" or \"false\".",
+ "optional_bool: 2");
+ assertParseError(
+ "1:18: Expected string.",
+ "optional_string: 123");
+ assertParseError(
+ "1:18: String missing ending quote.",
+ "optional_string: \"ueoauaoe");
+ assertParseError(
+ "1:18: String missing ending quote.",
+ "optional_string: \"ueoauaoe\n" +
+ "optional_int32: 123");
+ assertParseError(
+ "1:18: Invalid escape sequence: '\\z'",
+ "optional_string: \"\\z\"");
+ assertParseError(
+ "1:18: String missing ending quote.",
+ "optional_string: \"ueoauaoe\n" +
+ "optional_int32: 123");
+ assertParseError(
+ "1:2: Extension \"nosuchext\" not found in the ExtensionRegistry.",
+ "[nosuchext]: 123");
+ assertParseError(
+ "1:20: Extension \"protobuf_unittest.optional_int32_extension\" does " +
+ "not extend message type \"protobuf_unittest.TestAllTypes\".",
+ "[protobuf_unittest.optional_int32_extension]: 123");
+ assertParseError(
+ "1:1: Message type \"protobuf_unittest.TestAllTypes\" has no field " +
+ "named \"nosuchfield\".",
+ "nosuchfield: 123");
+ assertParseError(
+ "1:21: Expected \">\".",
+ "OptionalGroup < a: 1");
+ assertParseError(
+ "1:23: Enum type \"protobuf_unittest.TestAllTypes.NestedEnum\" has no " +
+ "value named \"NO_SUCH_VALUE\".",
+ "optional_nested_enum: NO_SUCH_VALUE");
+ assertParseError(
+ "1:23: Enum type \"protobuf_unittest.TestAllTypes.NestedEnum\" has no " +
+ "value with number 123.",
+ "optional_nested_enum: 123");
+
+ // Delimiters must match.
+ assertParseError(
+ "1:22: Expected identifier. Found '}'",
+ "OptionalGroup < a: 1 }");
+ assertParseError(
+ "1:22: Expected identifier. Found '>'",
+ "OptionalGroup { a: 1 >");
+ }
+
+ // =================================================================
+
+ public void testEscape() throws Exception {
+ // Escape sequences.
+ assertEquals("\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\"\\177",
+ TextFormat.escapeBytes(bytes("\0\001\007\b\f\n\r\t\013\\\'\"\177")));
+ assertEquals("\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\"\\177",
+ TextFormat.escapeText("\0\001\007\b\f\n\r\t\013\\\'\"\177"));
+ assertEquals(bytes("\0\001\007\b\f\n\r\t\013\\\'\""),
+ TextFormat.unescapeBytes("\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\""));
+ assertEquals("\0\001\007\b\f\n\r\t\013\\\'\"",
+ TextFormat.unescapeText("\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\""));
+ assertEquals(kEscapeTestStringEscaped,
+ TextFormat.escapeText(kEscapeTestString));
+ assertEquals(kEscapeTestString,
+ TextFormat.unescapeText(kEscapeTestStringEscaped));
+
+ // Unicode handling.
+ assertEquals("\\341\\210\\264", TextFormat.escapeText("\u1234"));
+ assertEquals("\\341\\210\\264",
+ TextFormat.escapeBytes(bytes(0xe1, 0x88, 0xb4)));
+ assertEquals("\u1234", TextFormat.unescapeText("\\341\\210\\264"));
+ assertEquals(bytes(0xe1, 0x88, 0xb4),
+ TextFormat.unescapeBytes("\\341\\210\\264"));
+ assertEquals("\u1234", TextFormat.unescapeText("\\xe1\\x88\\xb4"));
+ assertEquals(bytes(0xe1, 0x88, 0xb4),
+ TextFormat.unescapeBytes("\\xe1\\x88\\xb4"));
+
+ // Handling of strings with unescaped Unicode characters > 255.
+ final String zh = "\u9999\u6e2f\u4e0a\u6d77\ud84f\udf80\u8c50\u9280\u884c";
+ ByteString zhByteString = ByteString.copyFromUtf8(zh);
+ assertEquals(zhByteString, TextFormat.unescapeBytes(zh));
+
+ // Errors.
+ try {
+ TextFormat.unescapeText("\\x");
+ fail("Should have thrown an exception.");
+ } catch (TextFormat.InvalidEscapeSequenceException e) {
+ // success
+ }
+
+ try {
+ TextFormat.unescapeText("\\z");
+ fail("Should have thrown an exception.");
+ } catch (TextFormat.InvalidEscapeSequenceException e) {
+ // success
+ }
+
+ try {
+ TextFormat.unescapeText("\\");
+ fail("Should have thrown an exception.");
+ } catch (TextFormat.InvalidEscapeSequenceException e) {
+ // success
+ }
+ }
+
+ public void testParseInteger() throws Exception {
+ assertEquals( 0, TextFormat.parseInt32( "0"));
+ assertEquals( 1, TextFormat.parseInt32( "1"));
+ assertEquals( -1, TextFormat.parseInt32( "-1"));
+ assertEquals( 12345, TextFormat.parseInt32( "12345"));
+ assertEquals( -12345, TextFormat.parseInt32( "-12345"));
+ assertEquals( 2147483647, TextFormat.parseInt32( "2147483647"));
+ assertEquals(-2147483648, TextFormat.parseInt32("-2147483648"));
+
+ assertEquals( 0, TextFormat.parseUInt32( "0"));
+ assertEquals( 1, TextFormat.parseUInt32( "1"));
+ assertEquals( 12345, TextFormat.parseUInt32( "12345"));
+ assertEquals( 2147483647, TextFormat.parseUInt32("2147483647"));
+ assertEquals((int) 2147483648L, TextFormat.parseUInt32("2147483648"));
+ assertEquals((int) 4294967295L, TextFormat.parseUInt32("4294967295"));
+
+ assertEquals( 0L, TextFormat.parseInt64( "0"));
+ assertEquals( 1L, TextFormat.parseInt64( "1"));
+ assertEquals( -1L, TextFormat.parseInt64( "-1"));
+ assertEquals( 12345L, TextFormat.parseInt64( "12345"));
+ assertEquals( -12345L, TextFormat.parseInt64( "-12345"));
+ assertEquals( 2147483647L, TextFormat.parseInt64( "2147483647"));
+ assertEquals(-2147483648L, TextFormat.parseInt64("-2147483648"));
+ assertEquals( 4294967295L, TextFormat.parseInt64( "4294967295"));
+ assertEquals( 4294967296L, TextFormat.parseInt64( "4294967296"));
+ assertEquals(9223372036854775807L,
+ TextFormat.parseInt64("9223372036854775807"));
+ assertEquals(-9223372036854775808L,
+ TextFormat.parseInt64("-9223372036854775808"));
+
+ assertEquals( 0L, TextFormat.parseUInt64( "0"));
+ assertEquals( 1L, TextFormat.parseUInt64( "1"));
+ assertEquals( 12345L, TextFormat.parseUInt64( "12345"));
+ assertEquals( 2147483647L, TextFormat.parseUInt64( "2147483647"));
+ assertEquals( 4294967295L, TextFormat.parseUInt64( "4294967295"));
+ assertEquals( 4294967296L, TextFormat.parseUInt64( "4294967296"));
+ assertEquals(9223372036854775807L,
+ TextFormat.parseUInt64("9223372036854775807"));
+ assertEquals(-9223372036854775808L,
+ TextFormat.parseUInt64("9223372036854775808"));
+ assertEquals(-1L, TextFormat.parseUInt64("18446744073709551615"));
+
+ // Hex
+ assertEquals(0x1234abcd, TextFormat.parseInt32("0x1234abcd"));
+ assertEquals(-0x1234abcd, TextFormat.parseInt32("-0x1234abcd"));
+ assertEquals(-1, TextFormat.parseUInt64("0xffffffffffffffff"));
+ assertEquals(0x7fffffffffffffffL,
+ TextFormat.parseInt64("0x7fffffffffffffff"));
+
+ // Octal
+ assertEquals(01234567, TextFormat.parseInt32("01234567"));
+
+ // Out-of-range
+ try {
+ TextFormat.parseInt32("2147483648");
+ fail("Should have thrown an exception.");
+ } catch (NumberFormatException e) {
+ // success
+ }
+
+ try {
+ TextFormat.parseInt32("-2147483649");
+ fail("Should have thrown an exception.");
+ } catch (NumberFormatException e) {
+ // success
+ }
+
+ try {
+ TextFormat.parseUInt32("4294967296");
+ fail("Should have thrown an exception.");
+ } catch (NumberFormatException e) {
+ // success
+ }
+
+ try {
+ TextFormat.parseUInt32("-1");
+ fail("Should have thrown an exception.");
+ } catch (NumberFormatException e) {
+ // success
+ }
+
+ try {
+ TextFormat.parseInt64("9223372036854775808");
+ fail("Should have thrown an exception.");
+ } catch (NumberFormatException e) {
+ // success
+ }
+
+ try {
+ TextFormat.parseInt64("-9223372036854775809");
+ fail("Should have thrown an exception.");
+ } catch (NumberFormatException e) {
+ // success
+ }
+
+ try {
+ TextFormat.parseUInt64("18446744073709551616");
+ fail("Should have thrown an exception.");
+ } catch (NumberFormatException e) {
+ // success
+ }
+
+ try {
+ TextFormat.parseUInt64("-1");
+ fail("Should have thrown an exception.");
+ } catch (NumberFormatException e) {
+ // success
+ }
+
+ // Not a number.
+ try {
+ TextFormat.parseInt32("abcd");
+ fail("Should have thrown an exception.");
+ } catch (NumberFormatException e) {
+ // success
+ }
+ }
+
+ public void testParseString() throws Exception {
+ final String zh = "\u9999\u6e2f\u4e0a\u6d77\ud84f\udf80\u8c50\u9280\u884c";
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TextFormat.merge("optional_string: \"" + zh + "\"", builder);
+ assertEquals(zh, builder.getOptionalString());
+ }
+
+ public void testParseLongString() throws Exception {
+ String longText =
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890";
+
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TextFormat.merge("optional_string: \"" + longText + "\"", builder);
+ assertEquals(longText, builder.getOptionalString());
+ }
+
+ public void testParseBoolean() throws Exception {
+ String goodText =
+ "repeated_bool: t repeated_bool : 0\n" +
+ "repeated_bool :f repeated_bool:1";
+ String goodTextCanonical =
+ "repeated_bool: true\n" +
+ "repeated_bool: false\n" +
+ "repeated_bool: false\n" +
+ "repeated_bool: true\n";
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TextFormat.merge(goodText, builder);
+ assertEquals(goodTextCanonical, builder.build().toString());
+
+ try {
+ TestAllTypes.Builder badBuilder = TestAllTypes.newBuilder();
+ TextFormat.merge("optional_bool:2", badBuilder);
+ fail("Should have thrown an exception.");
+ } catch (TextFormat.ParseException e) {
+ // success
+ }
+ try {
+ TestAllTypes.Builder badBuilder = TestAllTypes.newBuilder();
+ TextFormat.merge("optional_bool: foo", badBuilder);
+ fail("Should have thrown an exception.");
+ } catch (TextFormat.ParseException e) {
+ // success
+ }
+ }
+
+ public void testParseAdjacentStringLiterals() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TextFormat.merge("optional_string: \"foo\" 'corge' \"grault\"", builder);
+ assertEquals("foocorgegrault", builder.getOptionalString());
+ }
+
+ public void testPrintFieldValue() throws Exception {
+ assertPrintFieldValue("\"Hello\"", "Hello", "repeated_string");
+ assertPrintFieldValue("123.0", 123f, "repeated_float");
+ assertPrintFieldValue("123.0", 123d, "repeated_double");
+ assertPrintFieldValue("123", 123, "repeated_int32");
+ assertPrintFieldValue("123", 123L, "repeated_int64");
+ assertPrintFieldValue("true", true, "repeated_bool");
+ assertPrintFieldValue("4294967295", 0xFFFFFFFF, "repeated_uint32");
+ assertPrintFieldValue("18446744073709551615", 0xFFFFFFFFFFFFFFFFL,
+ "repeated_uint64");
+ assertPrintFieldValue("\"\\001\\002\\003\"",
+ ByteString.copyFrom(new byte[] {1, 2, 3}), "repeated_bytes");
+ }
+
+ private void assertPrintFieldValue(String expect, Object value,
+ String fieldName) throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ StringBuilder sb = new StringBuilder();
+ TextFormat.printFieldValue(
+ TestAllTypes.getDescriptor().findFieldByName(fieldName),
+ value, sb);
+ assertEquals(expect, sb.toString());
+ }
+
+ public void testShortDebugString() {
+ assertEquals("optional_nested_message { bb: 42 } repeated_int32: 1"
+ + " repeated_uint32: 2",
+ TextFormat.shortDebugString(TestAllTypes.newBuilder()
+ .addRepeatedInt32(1)
+ .addRepeatedUint32(2)
+ .setOptionalNestedMessage(
+ NestedMessage.newBuilder().setBb(42).build())
+ .build()));
+ }
+
+ public void testShortDebugString_field() {
+ final FieldDescriptor dataField =
+ OneString.getDescriptor().findFieldByName("data");
+ assertEquals(
+ "data: \"test data\"",
+ TextFormat.shortDebugString(dataField, "test data"));
+
+ final FieldDescriptor optionalField =
+ TestAllTypes.getDescriptor().findFieldByName("optional_nested_message");
+ final Object value = NestedMessage.newBuilder().setBb(42).build();
+
+ assertEquals(
+ "optional_nested_message { bb: 42 }",
+ TextFormat.shortDebugString(optionalField, value));
+ }
+
+ public void testShortDebugString_unknown() {
+ assertEquals("5: 1 5: 0x00000002 5: 0x0000000000000003 5: \"4\" 5 { 10: 5 }"
+ + " 8: 1 8: 2 8: 3 15: 12379813812177893520 15: 0xabcd1234 15:"
+ + " 0xabcdef1234567890",
+ TextFormat.shortDebugString(makeUnknownFieldSet()));
+ }
+
+ public void testPrintToUnicodeString() throws Exception {
+ assertEquals(
+ "optional_string: \"abc\u3042efg\"\n" +
+ "optional_bytes: \"\\343\\201\\202\"\n" +
+ "repeated_string: \"\u3093XYZ\"\n",
+ TextFormat.printToUnicodeString(TestAllTypes.newBuilder()
+ .setOptionalString("abc\u3042efg")
+ .setOptionalBytes(bytes(0xe3, 0x81, 0x82))
+ .addRepeatedString("\u3093XYZ")
+ .build()));
+
+ // Double quotes and backslashes should be escaped
+ assertEquals(
+ "optional_string: \"a\\\\bc\\\"ef\\\"g\"\n",
+ TextFormat.printToUnicodeString(TestAllTypes.newBuilder()
+ .setOptionalString("a\\bc\"ef\"g")
+ .build()));
+
+ // Test escaping roundtrip
+ TestAllTypes message = TestAllTypes.newBuilder()
+ .setOptionalString("a\\bc\\\"ef\"g")
+ .build();
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TextFormat.merge(TextFormat.printToUnicodeString(message), builder);
+ assertEquals(message.getOptionalString(), builder.getOptionalString());
+ }
+
+ public void testPrintToUnicodeStringWithNewlines() throws Exception {
+ // No newlines at start and end
+ assertEquals("optional_string: \"test newlines\\n\\nin\\nstring\"\n",
+ TextFormat.printToUnicodeString(TestAllTypes.newBuilder()
+ .setOptionalString("test newlines\n\nin\nstring")
+ .build()));
+
+ // Newlines at start and end
+ assertEquals("optional_string: \"\\ntest\\nnewlines\\n\\nin\\nstring\\n\"\n",
+ TextFormat.printToUnicodeString(TestAllTypes.newBuilder()
+ .setOptionalString("\ntest\nnewlines\n\nin\nstring\n")
+ .build()));
+
+ // Strings with 0, 1 and 2 newlines.
+ assertEquals("optional_string: \"\"\n",
+ TextFormat.printToUnicodeString(TestAllTypes.newBuilder()
+ .setOptionalString("")
+ .build()));
+ assertEquals("optional_string: \"\\n\"\n",
+ TextFormat.printToUnicodeString(TestAllTypes.newBuilder()
+ .setOptionalString("\n")
+ .build()));
+ assertEquals("optional_string: \"\\n\\n\"\n",
+ TextFormat.printToUnicodeString(TestAllTypes.newBuilder()
+ .setOptionalString("\n\n")
+ .build()));
+
+ // Test escaping roundtrip
+ TestAllTypes message = TestAllTypes.newBuilder()
+ .setOptionalString("\ntest\nnewlines\n\nin\nstring\n")
+ .build();
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TextFormat.merge(TextFormat.printToUnicodeString(message), builder);
+ assertEquals(message.getOptionalString(), builder.getOptionalString());
+ }
+
+ public void testPrintToUnicodeString_unknown() {
+ assertEquals(
+ "1: \"\\343\\201\\202\"\n",
+ TextFormat.printToUnicodeString(UnknownFieldSet.newBuilder()
+ .addField(1,
+ UnknownFieldSet.Field.newBuilder()
+ .addLengthDelimited(bytes(0xe3, 0x81, 0x82)).build())
+ .build()));
+ }
+
+
+ public void testParseNonRepeatedFields() throws Exception {
+ assertParseSuccessWithOverwriteForbidden(
+ "repeated_int32: 1\n" +
+ "repeated_int32: 2\n");
+ assertParseSuccessWithOverwriteForbidden(
+ "RepeatedGroup { a: 1 }\n" +
+ "RepeatedGroup { a: 2 }\n");
+ assertParseSuccessWithOverwriteForbidden(
+ "repeated_nested_message { bb: 1 }\n" +
+ "repeated_nested_message { bb: 2 }\n");
+ assertParseErrorWithOverwriteForbidden(
+ "3:17: Non-repeated field " +
+ "\"protobuf_unittest.TestAllTypes.optional_int32\" " +
+ "cannot be overwritten.",
+ "optional_int32: 1\n" +
+ "optional_bool: true\n" +
+ "optional_int32: 1\n");
+ assertParseErrorWithOverwriteForbidden(
+ "2:17: Non-repeated field " +
+ "\"protobuf_unittest.TestAllTypes.optionalgroup\" " +
+ "cannot be overwritten.",
+ "OptionalGroup { a: 1 }\n" +
+ "OptionalGroup { }\n");
+ assertParseErrorWithOverwriteForbidden(
+ "2:33: Non-repeated field " +
+ "\"protobuf_unittest.TestAllTypes.optional_nested_message\" " +
+ "cannot be overwritten.",
+ "optional_nested_message { }\n" +
+ "optional_nested_message { bb: 3 }\n");
+ assertParseErrorWithOverwriteForbidden(
+ "2:16: Non-repeated field " +
+ "\"protobuf_unittest.TestAllTypes.default_int32\" " +
+ "cannot be overwritten.",
+ "default_int32: 41\n" + // the default value
+ "default_int32: 41\n");
+ assertParseErrorWithOverwriteForbidden(
+ "2:17: Non-repeated field " +
+ "\"protobuf_unittest.TestAllTypes.default_string\" " +
+ "cannot be overwritten.",
+ "default_string: \"zxcv\"\n" +
+ "default_string: \"asdf\"\n");
+ }
+
+ public void testParseShortRepeatedFormOfRepeatedFields() throws Exception {
+ assertParseSuccessWithOverwriteForbidden("repeated_foreign_enum: [FOREIGN_FOO, FOREIGN_BAR]");
+ assertParseSuccessWithOverwriteForbidden("repeated_int32: [ 1, 2 ]\n");
+ assertParseSuccessWithOverwriteForbidden("RepeatedGroup [{ a: 1 },{ a: 2 }]\n");
+ assertParseSuccessWithOverwriteForbidden("repeated_nested_message [{ bb: 1 }, { bb: 2 }]\n");
+ }
+
+ public void testParseShortRepeatedFormOfNonRepeatedFields() throws Exception {
+ assertParseErrorWithOverwriteForbidden(
+ "1:17: Couldn't parse integer: For input string: \"[\"",
+ "optional_int32: [1]\n");
+ }
+
+ // =======================================================================
+ // test oneof
+
+ public void testOneofTextFormat() throws Exception {
+ TestOneof2.Builder builder = TestOneof2.newBuilder();
+ TestUtil.setOneof(builder);
+ TestOneof2 message = builder.build();
+ TestOneof2.Builder dest = TestOneof2.newBuilder();
+ TextFormat.merge(TextFormat.printToUnicodeString(message), dest);
+ TestUtil.assertOneofSet(dest.build());
+ }
+
+ public void testOneofOverwriteForbidden() throws Exception {
+ String input = "foo_string: \"stringvalue\" foo_int: 123";
+ TestOneof2.Builder builder = TestOneof2.newBuilder();
+ try {
+ parserWithOverwriteForbidden.merge(
+ input, TestUtil.getExtensionRegistry(), builder);
+ fail("Expected parse exception.");
+ } catch (TextFormat.ParseException e) {
+ assertEquals("1:36: Field \"protobuf_unittest.TestOneof2.foo_int\""
+ + " is specified along with field \"protobuf_unittest.TestOneof2.foo_string\","
+ + " another member of oneof \"foo\".", e.getMessage());
+ }
+ }
+
+ public void testOneofOverwriteAllowed() throws Exception {
+ String input = "foo_string: \"stringvalue\" foo_int: 123";
+ TestOneof2.Builder builder = TestOneof2.newBuilder();
+ defaultParser.merge(input, TestUtil.getExtensionRegistry(), builder);
+ // Only the last value sticks.
+ TestOneof2 oneof = builder.build();
+ assertFalse(oneof.hasFooString());
+ assertTrue(oneof.hasFooInt());
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/UnknownEnumValueTest.java b/java/core/src/test/java/com/google/protobuf/UnknownEnumValueTest.java
new file mode 100644
index 00000000..8f45976f
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/UnknownEnumValueTest.java
@@ -0,0 +1,255 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// 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 com.google.protobuf.Descriptors.Descriptor;
+import com.google.protobuf.Descriptors.EnumDescriptor;
+import com.google.protobuf.Descriptors.EnumValueDescriptor;
+import com.google.protobuf.Descriptors.FieldDescriptor;
+import com.google.protobuf.FieldPresenceTestProto.TestAllTypes;
+import com.google.protobuf.TextFormat.ParseException;
+
+import junit.framework.TestCase;
+
+/**
+ * Unit tests for protos that keep unknown enum values rather than discard
+ * them as unknown fields.
+ */
+public class UnknownEnumValueTest extends TestCase {
+ public void testUnknownEnumValues() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ builder.setOptionalNestedEnumValue(4321);
+ builder.addRepeatedNestedEnumValue(5432);
+ builder.addPackedNestedEnumValue(6543);
+ TestAllTypes message = builder.build();
+ assertEquals(4321, message.getOptionalNestedEnumValue());
+ assertEquals(5432, message.getRepeatedNestedEnumValue(0));
+ assertEquals(5432, message.getRepeatedNestedEnumValueList().get(0).intValue());
+ assertEquals(6543, message.getPackedNestedEnumValue(0));
+ // Returns UNRECOGNIZED if an enum type is requested.
+ assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, message.getOptionalNestedEnum());
+ assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, message.getRepeatedNestedEnum(0));
+ assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, message.getRepeatedNestedEnumList().get(0));
+ assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, message.getPackedNestedEnum(0));
+
+ // Test serialization and parsing.
+ ByteString data = message.toByteString();
+ message = TestAllTypes.parseFrom(data);
+ assertEquals(4321, message.getOptionalNestedEnumValue());
+ assertEquals(5432, message.getRepeatedNestedEnumValue(0));
+ assertEquals(5432, message.getRepeatedNestedEnumValueList().get(0).intValue());
+ assertEquals(6543, message.getPackedNestedEnumValue(0));
+ // Returns UNRECOGNIZED if an enum type is requested.
+ assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, message.getOptionalNestedEnum());
+ assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, message.getRepeatedNestedEnum(0));
+ assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, message.getRepeatedNestedEnumList().get(0));
+ assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, message.getPackedNestedEnum(0));
+
+ // Test toBuilder().
+ builder = message.toBuilder();
+ assertEquals(4321, builder.getOptionalNestedEnumValue());
+ assertEquals(5432, builder.getRepeatedNestedEnumValue(0));
+ assertEquals(5432, builder.getRepeatedNestedEnumValueList().get(0).intValue());
+ assertEquals(6543, builder.getPackedNestedEnumValue(0));
+ // Returns UNRECOGNIZED if an enum type is requested.
+ assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, builder.getOptionalNestedEnum());
+ assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, builder.getRepeatedNestedEnum(0));
+ assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, builder.getRepeatedNestedEnumList().get(0));
+ assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, builder.getPackedNestedEnum(0));
+
+ // Test mergeFrom().
+ builder = TestAllTypes.newBuilder().mergeFrom(message);
+ assertEquals(4321, builder.getOptionalNestedEnumValue());
+ assertEquals(5432, builder.getRepeatedNestedEnumValue(0));
+ assertEquals(5432, builder.getRepeatedNestedEnumValueList().get(0).intValue());
+ assertEquals(6543, builder.getPackedNestedEnumValue(0));
+ // Returns UNRECOGNIZED if an enum type is requested.
+ assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, builder.getOptionalNestedEnum());
+ assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, builder.getRepeatedNestedEnum(0));
+ assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, builder.getRepeatedNestedEnumList().get(0));
+ assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, builder.getPackedNestedEnum(0));
+
+ // Test equals() and hashCode()
+ TestAllTypes sameMessage = builder.build();
+ assertEquals(message, sameMessage);
+ assertEquals(message.hashCode(), sameMessage.hashCode());
+
+ // Getting the numeric value of UNRECOGNIZED will throw an exception.
+ try {
+ TestAllTypes.NestedEnum.UNRECOGNIZED.getNumber();
+ fail("Exception is expected.");
+ } catch (IllegalArgumentException e) {
+ // Expected.
+ }
+
+ // Setting an enum field to an UNRECOGNIZED value will throw an exception.
+ try {
+ builder.setOptionalNestedEnum(builder.getOptionalNestedEnum());
+ fail("Exception is expected.");
+ } catch (IllegalArgumentException e) {
+ // Expected.
+ }
+ try {
+ builder.addRepeatedNestedEnum(builder.getOptionalNestedEnum());
+ fail("Exception is expected.");
+ } catch (IllegalArgumentException e) {
+ // Expected.
+ }
+ }
+
+ public void testUnknownEnumValueInReflectionApi() throws Exception {
+ Descriptor descriptor = TestAllTypes.getDescriptor();
+ FieldDescriptor optionalNestedEnumField = descriptor.findFieldByName("optional_nested_enum");
+ FieldDescriptor repeatedNestedEnumField = descriptor.findFieldByName("repeated_nested_enum");
+ FieldDescriptor packedNestedEnumField = descriptor.findFieldByName("packed_nested_enum");
+ EnumDescriptor enumType = TestAllTypes.NestedEnum.getDescriptor();
+
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ builder.setField(optionalNestedEnumField,
+ enumType.findValueByNumberCreatingIfUnknown(4321));
+ builder.addRepeatedField(repeatedNestedEnumField,
+ enumType.findValueByNumberCreatingIfUnknown(5432));
+ builder.addRepeatedField(packedNestedEnumField,
+ enumType.findValueByNumberCreatingIfUnknown(6543));
+ TestAllTypes message = builder.build();
+
+ // Getters will return unknown enum values as EnumValueDescriptor.
+ EnumValueDescriptor unknown4321 =
+ (EnumValueDescriptor) message.getField(optionalNestedEnumField);
+ EnumValueDescriptor unknown5432 =
+ (EnumValueDescriptor) message.getRepeatedField(repeatedNestedEnumField, 0);
+ EnumValueDescriptor unknown6543 =
+ (EnumValueDescriptor) message.getRepeatedField(packedNestedEnumField, 0);
+ assertEquals(4321, unknown4321.getNumber());
+ assertEquals(5432, unknown5432.getNumber());
+ assertEquals(6543, unknown6543.getNumber());
+
+ // Unknown EnumValueDescriptor will map to UNRECOGNIZED.
+ assertEquals(
+ TestAllTypes.NestedEnum.valueOf(unknown4321),
+ TestAllTypes.NestedEnum.UNRECOGNIZED);
+ assertEquals(
+ TestAllTypes.NestedEnum.valueOf(unknown5432),
+ TestAllTypes.NestedEnum.UNRECOGNIZED);
+ assertEquals(
+ TestAllTypes.NestedEnum.valueOf(unknown6543),
+ TestAllTypes.NestedEnum.UNRECOGNIZED);
+
+ // Setters also accept unknown EnumValueDescriptor.
+ builder.setField(optionalNestedEnumField, unknown6543);
+ builder.setRepeatedField(repeatedNestedEnumField, 0, unknown4321);
+ builder.setRepeatedField(packedNestedEnumField, 0, unknown5432);
+ message = builder.build();
+ // Like other descriptors, unknown EnumValueDescriptor can be compared by
+ // object identity.
+ assertTrue(unknown6543 == message.getField(optionalNestedEnumField));
+ assertTrue(unknown4321 == message.getRepeatedField(repeatedNestedEnumField, 0));
+ assertTrue(unknown5432 == message.getRepeatedField(packedNestedEnumField, 0));
+ }
+
+ public void testUnknownEnumValueWithDynamicMessage() throws Exception {
+ Descriptor descriptor = TestAllTypes.getDescriptor();
+ FieldDescriptor optionalNestedEnumField = descriptor.findFieldByName("optional_nested_enum");
+ FieldDescriptor repeatedNestedEnumField = descriptor.findFieldByName("repeated_nested_enum");
+ FieldDescriptor packedNestedEnumField = descriptor.findFieldByName("packed_nested_enum");
+ EnumDescriptor enumType = TestAllTypes.NestedEnum.getDescriptor();
+
+ Message dynamicMessageDefaultInstance = DynamicMessage.getDefaultInstance(descriptor);
+
+ Message.Builder builder = dynamicMessageDefaultInstance.newBuilderForType();
+ builder.setField(optionalNestedEnumField,
+ enumType.findValueByNumberCreatingIfUnknown(4321));
+ builder.addRepeatedField(repeatedNestedEnumField,
+ enumType.findValueByNumberCreatingIfUnknown(5432));
+ builder.addRepeatedField(packedNestedEnumField,
+ enumType.findValueByNumberCreatingIfUnknown(6543));
+ Message message = builder.build();
+ assertEquals(4321,
+ ((EnumValueDescriptor) message.getField(optionalNestedEnumField)).getNumber());
+ assertEquals(5432,
+ ((EnumValueDescriptor) message.getRepeatedField(repeatedNestedEnumField, 0)).getNumber());
+ assertEquals(6543,
+ ((EnumValueDescriptor) message.getRepeatedField(packedNestedEnumField, 0)).getNumber());
+
+ // Test reflection based serialization/parsing implementation.
+ ByteString data = message.toByteString();
+ message = dynamicMessageDefaultInstance
+ .newBuilderForType()
+ .mergeFrom(data)
+ .build();
+ assertEquals(4321,
+ ((EnumValueDescriptor) message.getField(optionalNestedEnumField)).getNumber());
+ assertEquals(5432,
+ ((EnumValueDescriptor) message.getRepeatedField(repeatedNestedEnumField, 0)).getNumber());
+ assertEquals(6543,
+ ((EnumValueDescriptor) message.getRepeatedField(packedNestedEnumField, 0)).getNumber());
+
+ // Test reflection based equals()/hashCode().
+ builder = dynamicMessageDefaultInstance.newBuilderForType();
+ builder.setField(optionalNestedEnumField,
+ enumType.findValueByNumberCreatingIfUnknown(4321));
+ builder.addRepeatedField(repeatedNestedEnumField,
+ enumType.findValueByNumberCreatingIfUnknown(5432));
+ builder.addRepeatedField(packedNestedEnumField,
+ enumType.findValueByNumberCreatingIfUnknown(6543));
+ Message sameMessage = builder.build();
+ assertEquals(message, sameMessage);
+ assertEquals(message.hashCode(), sameMessage.hashCode());
+ builder.setField(optionalNestedEnumField,
+ enumType.findValueByNumberCreatingIfUnknown(0));
+ Message differentMessage = builder.build();
+ assertFalse(message.equals(differentMessage));
+ }
+
+ public void testUnknownEnumValuesInTextFormat() {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ builder.setOptionalNestedEnumValue(4321);
+ builder.addRepeatedNestedEnumValue(5432);
+ builder.addPackedNestedEnumValue(6543);
+ TestAllTypes message = builder.build();
+
+ // We can print a message with unknown enum values.
+ String textData = TextFormat.printToString(message);
+ assertEquals(
+ "optional_nested_enum: UNKNOWN_ENUM_VALUE_NestedEnum_4321\n"
+ + "repeated_nested_enum: UNKNOWN_ENUM_VALUE_NestedEnum_5432\n"
+ + "packed_nested_enum: UNKNOWN_ENUM_VALUE_NestedEnum_6543\n", textData);
+
+ // Parsing unknown enum values will fail just like parsing other kinds of
+ // unknown fields.
+ try {
+ TextFormat.merge(textData, builder);
+ fail();
+ } catch (ParseException e) {
+ // expected.
+ }
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/UnknownFieldSetLiteTest.java b/java/core/src/test/java/com/google/protobuf/UnknownFieldSetLiteTest.java
new file mode 100644
index 00000000..dc987379
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/UnknownFieldSetLiteTest.java
@@ -0,0 +1,368 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// 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 com.google.protobuf.UnittestLite.TestAllExtensionsLite;
+import com.google.protobuf.UnittestLite.TestAllTypesLite;
+import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash;
+import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash.Bar;
+import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash.Foo;
+
+import junit.framework.TestCase;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+/**
+ * Tests for {@link UnknownFieldSetLite}.
+ *
+ * @author dweis@google.com (Daniel Weis)
+ */
+public class UnknownFieldSetLiteTest extends TestCase {
+
+ public void testNoDataIsDefaultInstance() {
+ assertSame(
+ UnknownFieldSetLite.getDefaultInstance(),
+ UnknownFieldSetLite.newBuilder()
+ .build());
+ }
+
+ public void testBuilderReuse() throws IOException {
+ UnknownFieldSetLite.Builder builder = UnknownFieldSetLite.newBuilder();
+ builder.mergeVarintField(10, 2);
+ builder.build();
+
+ try {
+ builder.build();
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // Expected.
+ }
+
+ try {
+ builder.mergeFieldFrom(0, CodedInputStream.newInstance(new byte[0]));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // Expected.
+ }
+
+ try {
+ builder.mergeVarintField(5, 1);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // Expected.
+ }
+ }
+
+ public void testBuilderReuse_empty() {
+ UnknownFieldSetLite.Builder builder = UnknownFieldSetLite.newBuilder();
+ builder.build();
+ builder.build();
+ }
+
+ public void testDefaultInstance() {
+ UnknownFieldSetLite unknownFields = UnknownFieldSetLite.getDefaultInstance();
+
+ assertEquals(0, unknownFields.getSerializedSize());
+ assertEquals(ByteString.EMPTY, toByteString(unknownFields));
+ }
+
+ public void testMergeFieldFrom() throws IOException {
+ Foo foo = Foo.newBuilder()
+ .setValue(2)
+ .build();
+
+ CodedInputStream input = CodedInputStream.newInstance(foo.toByteArray());
+
+ UnknownFieldSetLite instance = UnknownFieldSetLite.newInstance();
+ instance.mergeFieldFrom(input.readTag(), input);
+
+ assertEquals(foo.toByteString(), toByteString(instance));
+ }
+
+ public void testSerializedSize() throws IOException {
+ Foo foo = Foo.newBuilder()
+ .setValue(2)
+ .build();
+
+ CodedInputStream input = CodedInputStream.newInstance(foo.toByteArray());
+
+ UnknownFieldSetLite instance = UnknownFieldSetLite.newInstance();
+ instance.mergeFieldFrom(input.readTag(), input);
+
+ assertEquals(foo.toByteString().size(), instance.getSerializedSize());
+ }
+
+ public void testMergeVarintField() throws IOException {
+ UnknownFieldSetLite unknownFields = UnknownFieldSetLite.newInstance();
+ unknownFields.mergeVarintField(10, 2);
+
+ CodedInputStream input =
+ CodedInputStream.newInstance(toByteString(unknownFields).toByteArray());
+
+ int tag = input.readTag();
+ assertEquals(10, WireFormat.getTagFieldNumber(tag));
+ assertEquals(WireFormat.WIRETYPE_VARINT, WireFormat.getTagWireType(tag));
+ assertEquals(2, input.readUInt64());
+ assertTrue(input.isAtEnd());
+ }
+
+ public void testMergeVarintField_negative() throws IOException {
+ UnknownFieldSetLite builder = UnknownFieldSetLite.newInstance();
+ builder.mergeVarintField(10, -6);
+
+ CodedInputStream input =
+ CodedInputStream.newInstance(toByteString(builder).toByteArray());
+
+ int tag = input.readTag();
+ assertEquals(10, WireFormat.getTagFieldNumber(tag));
+ assertEquals(WireFormat.WIRETYPE_VARINT, WireFormat.getTagWireType(tag));
+ assertEquals(-6, input.readUInt64());
+ assertTrue(input.isAtEnd());
+ }
+
+ public void testEqualsAndHashCode() {
+ UnknownFieldSetLite unknownFields1 = UnknownFieldSetLite.newInstance();
+ unknownFields1.mergeVarintField(10, 2);
+
+ UnknownFieldSetLite unknownFields2 = UnknownFieldSetLite.newInstance();
+ unknownFields2.mergeVarintField(10, 2);
+
+ assertEquals(unknownFields1, unknownFields2);
+ assertEquals(unknownFields1.hashCode(), unknownFields2.hashCode());
+ assertFalse(unknownFields1.equals(UnknownFieldSetLite.getDefaultInstance()));
+ assertFalse(unknownFields1.hashCode() == UnknownFieldSetLite.getDefaultInstance().hashCode());
+ }
+
+ public void testMutableCopyOf() throws IOException {
+ UnknownFieldSetLite unknownFields = UnknownFieldSetLite.newInstance();
+ unknownFields.mergeVarintField(10, 2);
+ unknownFields = UnknownFieldSetLite.mutableCopyOf(unknownFields, unknownFields);
+ unknownFields.checkMutable();
+
+ CodedInputStream input =
+ CodedInputStream.newInstance(toByteString(unknownFields).toByteArray());
+
+ int tag = input.readTag();
+ assertEquals(10, WireFormat.getTagFieldNumber(tag));
+ assertEquals(WireFormat.WIRETYPE_VARINT, WireFormat.getTagWireType(tag));
+ assertEquals(2, input.readUInt64());
+ assertFalse(input.isAtEnd());
+ input.readTag();
+ assertEquals(10, WireFormat.getTagFieldNumber(tag));
+ assertEquals(WireFormat.WIRETYPE_VARINT, WireFormat.getTagWireType(tag));
+ assertEquals(2, input.readUInt64());
+ assertTrue(input.isAtEnd());
+ }
+
+ public void testMutableCopyOf_empty() {
+ UnknownFieldSetLite unknownFields = UnknownFieldSetLite.mutableCopyOf(
+ UnknownFieldSetLite.getDefaultInstance(), UnknownFieldSetLite.getDefaultInstance());
+ unknownFields.checkMutable();
+
+ assertEquals(0, unknownFields.getSerializedSize());
+ assertEquals(ByteString.EMPTY, toByteString(unknownFields));
+ }
+
+ public void testRoundTrips() throws InvalidProtocolBufferException {
+ Foo foo = Foo.newBuilder()
+ .setValue(1)
+ .setExtension(Bar.fooExt, Bar.newBuilder()
+ .setName("name")
+ .build())
+ .setExtension(LiteEqualsAndHash.varint, 22)
+ .setExtension(LiteEqualsAndHash.fixed32, 44)
+ .setExtension(LiteEqualsAndHash.fixed64, 66L)
+ .setExtension(LiteEqualsAndHash.myGroup, LiteEqualsAndHash.MyGroup.newBuilder()
+ .setGroupValue("value")
+ .build())
+ .build();
+
+ Foo copy = Foo.parseFrom(foo.toByteArray());
+
+ assertEquals(foo.getSerializedSize(), copy.getSerializedSize());
+ assertFalse(foo.equals(copy));
+
+ Foo secondCopy = Foo.parseFrom(foo.toByteArray());
+ assertEquals(copy, secondCopy);
+
+ ExtensionRegistryLite extensionRegistry = ExtensionRegistryLite.newInstance();
+ LiteEqualsAndHash.registerAllExtensions(extensionRegistry);
+ Foo copyOfCopy = Foo.parseFrom(copy.toByteArray(), extensionRegistry);
+
+ assertEquals(foo, copyOfCopy);
+ }
+
+ public void testMalformedBytes() throws Exception {
+ try {
+ Foo.parseFrom("this is a malformed protocol buffer".getBytes(Internal.UTF_8));
+ fail();
+ } catch (InvalidProtocolBufferException e) {
+ // Expected.
+ }
+ }
+
+ public void testMissingStartGroupTag() throws IOException {
+ ByteString.Output byteStringOutput = ByteString.newOutput();
+ CodedOutputStream output = CodedOutputStream.newInstance(byteStringOutput);
+ output.writeGroupNoTag(Foo.newBuilder().setValue(11).build());
+ output.writeTag(100, WireFormat.WIRETYPE_END_GROUP);
+ output.flush();
+
+ try {
+ Foo.parseFrom(byteStringOutput.toByteString());
+ fail();
+ } catch (InvalidProtocolBufferException e) {
+ // Expected.
+ }
+ }
+
+ public void testMissingEndGroupTag() throws IOException {
+ ByteString.Output byteStringOutput = ByteString.newOutput();
+ CodedOutputStream output = CodedOutputStream.newInstance(byteStringOutput);
+ output.writeTag(100, WireFormat.WIRETYPE_START_GROUP);
+ output.writeGroupNoTag(Foo.newBuilder().setValue(11).build());
+ output.flush();
+
+ try {
+ Foo.parseFrom(byteStringOutput.toByteString());
+ fail();
+ } catch (InvalidProtocolBufferException e) {
+ // Expected.
+ }
+ }
+
+ public void testMismatchingGroupTags() throws IOException {
+ ByteString.Output byteStringOutput = ByteString.newOutput();
+ CodedOutputStream output = CodedOutputStream.newInstance(byteStringOutput);
+ output.writeTag(100, WireFormat.WIRETYPE_START_GROUP);
+ output.writeGroupNoTag(Foo.newBuilder().setValue(11).build());
+ output.writeTag(101, WireFormat.WIRETYPE_END_GROUP);
+ output.flush();
+
+ try {
+ Foo.parseFrom(byteStringOutput.toByteString());
+ fail();
+ } catch (InvalidProtocolBufferException e) {
+ // Expected.
+ }
+ }
+
+ public void testTruncatedInput() {
+ Foo foo = Foo.newBuilder()
+ .setValue(1)
+ .setExtension(Bar.fooExt, Bar.newBuilder()
+ .setName("name")
+ .build())
+ .setExtension(LiteEqualsAndHash.varint, 22)
+ .setExtension(LiteEqualsAndHash.myGroup, LiteEqualsAndHash.MyGroup.newBuilder()
+ .setGroupValue("value")
+ .build())
+ .build();
+
+ try {
+ Foo.parseFrom(foo.toByteString().substring(0, foo.toByteString().size() - 10));
+ fail();
+ } catch (InvalidProtocolBufferException e) {
+ // Expected.
+ }
+ }
+
+ public void testMakeImmutable() throws Exception {
+ UnknownFieldSetLite unknownFields = UnknownFieldSetLite.newInstance();
+ unknownFields.makeImmutable();
+
+ try {
+ unknownFields.mergeVarintField(1, 1);
+ fail();
+ } catch (UnsupportedOperationException expected) {}
+
+ try {
+ unknownFields.mergeLengthDelimitedField(2, ByteString.copyFromUtf8("hello"));
+ fail();
+ } catch (UnsupportedOperationException expected) {}
+
+ try {
+ unknownFields.mergeFieldFrom(1, CodedInputStream.newInstance(new byte[0]));
+ fail();
+ } catch (UnsupportedOperationException expected) {}
+ }
+
+ public void testEndToEnd() throws Exception {
+ TestAllTypesLite testAllTypes = TestAllTypesLite.getDefaultInstance();
+ try {
+ testAllTypes.unknownFields.checkMutable();
+ fail();
+ } catch (UnsupportedOperationException expected) {}
+
+ testAllTypes = TestAllTypesLite.parseFrom(new byte[0]);
+ try {
+ testAllTypes.unknownFields.checkMutable();
+ fail();
+ } catch (UnsupportedOperationException expected) {}
+
+ testAllTypes = TestAllTypesLite.newBuilder().build();
+ try {
+ testAllTypes.unknownFields.checkMutable();
+ fail();
+ } catch (UnsupportedOperationException expected) {}
+
+ testAllTypes = TestAllTypesLite.newBuilder()
+ .setDefaultBool(true)
+ .build();
+ try {
+ testAllTypes.unknownFields.checkMutable();
+ fail();
+ } catch (UnsupportedOperationException expected) {}
+
+ TestAllExtensionsLite testAllExtensions = TestAllExtensionsLite.newBuilder()
+ .mergeFrom(TestAllExtensionsLite.newBuilder()
+ .setExtension(UnittestLite.optionalInt32ExtensionLite, 2)
+ .build().toByteArray())
+ .build();
+ try {
+ testAllExtensions.unknownFields.checkMutable();
+ fail();
+ } catch (UnsupportedOperationException expected) {}
+ }
+
+ private ByteString toByteString(UnknownFieldSetLite unknownFields) {
+ ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+ CodedOutputStream output = CodedOutputStream.newInstance(byteArrayOutputStream);
+ try {
+ unknownFields.writeTo(output);
+ output.flush();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ return ByteString.copyFrom(byteArrayOutputStream.toByteArray());
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/UnknownFieldSetTest.java b/java/core/src/test/java/com/google/protobuf/UnknownFieldSetTest.java
new file mode 100644
index 00000000..8c9dcafe
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/UnknownFieldSetTest.java
@@ -0,0 +1,653 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// 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.UnittestProto;
+import protobuf_unittest.UnittestProto.ForeignEnum;
+import protobuf_unittest.UnittestProto.TestAllExtensions;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.TestEmptyMessage;
+import protobuf_unittest.UnittestProto.TestEmptyMessageWithExtensions;
+import protobuf_unittest.UnittestProto.TestPackedExtensions;
+import protobuf_unittest.UnittestProto.TestPackedTypes;
+
+import junit.framework.TestCase;
+
+import java.util.Arrays;
+import java.util.Map;
+
+/**
+ * Tests related to unknown field handling.
+ *
+ * @author kenton@google.com (Kenton Varda)
+ */
+public class UnknownFieldSetTest extends TestCase {
+ public void setUp() throws Exception {
+ descriptor = TestAllTypes.getDescriptor();
+ allFields = TestUtil.getAllSet();
+ allFieldsData = allFields.toByteString();
+ emptyMessage = TestEmptyMessage.parseFrom(allFieldsData);
+ unknownFields = emptyMessage.getUnknownFields();
+ }
+
+ UnknownFieldSet.Field getField(String name) {
+ Descriptors.FieldDescriptor field = descriptor.findFieldByName(name);
+ assertNotNull(field);
+ return unknownFields.getField(field.getNumber());
+ }
+
+ // Constructs a protocol buffer which contains fields with all the same
+ // numbers as allFieldsData except that each field is some other wire
+ // type.
+ ByteString getBizarroData() throws Exception {
+ UnknownFieldSet.Builder bizarroFields = UnknownFieldSet.newBuilder();
+
+ UnknownFieldSet.Field varintField =
+ UnknownFieldSet.Field.newBuilder().addVarint(1).build();
+ UnknownFieldSet.Field fixed32Field =
+ UnknownFieldSet.Field.newBuilder().addFixed32(1).build();
+
+ for (Map.Entry<Integer, UnknownFieldSet.Field> entry :
+ unknownFields.asMap().entrySet()) {
+ if (entry.getValue().getVarintList().isEmpty()) {
+ // Original field is not a varint, so use a varint.
+ bizarroFields.addField(entry.getKey(), varintField);
+ } else {
+ // Original field *is* a varint, so use something else.
+ bizarroFields.addField(entry.getKey(), fixed32Field);
+ }
+ }
+
+ return bizarroFields.build().toByteString();
+ }
+
+ Descriptors.Descriptor descriptor;
+ TestAllTypes allFields;
+ ByteString allFieldsData;
+
+ // An empty message that has been parsed from allFieldsData. So, it has
+ // unknown fields of every type.
+ TestEmptyMessage emptyMessage;
+ UnknownFieldSet unknownFields;
+
+ // =================================================================
+
+ public void testVarint() throws Exception {
+ UnknownFieldSet.Field field = getField("optional_int32");
+ assertEquals(1, field.getVarintList().size());
+ assertEquals(allFields.getOptionalInt32(),
+ (long) field.getVarintList().get(0));
+ }
+
+ public void testFixed32() throws Exception {
+ UnknownFieldSet.Field field = getField("optional_fixed32");
+ assertEquals(1, field.getFixed32List().size());
+ assertEquals(allFields.getOptionalFixed32(),
+ (int) field.getFixed32List().get(0));
+ }
+
+ public void testFixed64() throws Exception {
+ UnknownFieldSet.Field field = getField("optional_fixed64");
+ assertEquals(1, field.getFixed64List().size());
+ assertEquals(allFields.getOptionalFixed64(),
+ (long) field.getFixed64List().get(0));
+ }
+
+ public void testLengthDelimited() throws Exception {
+ UnknownFieldSet.Field field = getField("optional_bytes");
+ assertEquals(1, field.getLengthDelimitedList().size());
+ assertEquals(allFields.getOptionalBytes(),
+ field.getLengthDelimitedList().get(0));
+ }
+
+ public void testGroup() throws Exception {
+ Descriptors.FieldDescriptor nestedFieldDescriptor =
+ TestAllTypes.OptionalGroup.getDescriptor().findFieldByName("a");
+ assertNotNull(nestedFieldDescriptor);
+
+ UnknownFieldSet.Field field = getField("optionalgroup");
+ assertEquals(1, field.getGroupList().size());
+
+ UnknownFieldSet group = field.getGroupList().get(0);
+ assertEquals(1, group.asMap().size());
+ assertTrue(group.hasField(nestedFieldDescriptor.getNumber()));
+
+ UnknownFieldSet.Field nestedField =
+ group.getField(nestedFieldDescriptor.getNumber());
+ assertEquals(1, nestedField.getVarintList().size());
+ assertEquals(allFields.getOptionalGroup().getA(),
+ (long) nestedField.getVarintList().get(0));
+ }
+
+ public void testSerialize() throws Exception {
+ // Check that serializing the UnknownFieldSet produces the original data
+ // again.
+ ByteString data = emptyMessage.toByteString();
+ assertEquals(allFieldsData, data);
+ }
+
+ public void testCopyFrom() throws Exception {
+ TestEmptyMessage message =
+ TestEmptyMessage.newBuilder().mergeFrom(emptyMessage).build();
+
+ assertEquals(emptyMessage.toString(), message.toString());
+ }
+
+ public void testMergeFrom() throws Exception {
+ TestEmptyMessage source =
+ TestEmptyMessage.newBuilder()
+ .setUnknownFields(
+ UnknownFieldSet.newBuilder()
+ .addField(2,
+ UnknownFieldSet.Field.newBuilder()
+ .addVarint(2).build())
+ .addField(3,
+ UnknownFieldSet.Field.newBuilder()
+ .addVarint(4).build())
+ .build())
+ .build();
+ TestEmptyMessage destination =
+ TestEmptyMessage.newBuilder()
+ .setUnknownFields(
+ UnknownFieldSet.newBuilder()
+ .addField(1,
+ UnknownFieldSet.Field.newBuilder()
+ .addVarint(1).build())
+ .addField(3,
+ UnknownFieldSet.Field.newBuilder()
+ .addVarint(3).build())
+ .build())
+ .mergeFrom(source)
+ .build();
+
+ assertEquals(
+ "1: 1\n" +
+ "2: 2\n" +
+ "3: 3\n" +
+ "3: 4\n",
+ destination.toString());
+ }
+
+ public void testClear() throws Exception {
+ UnknownFieldSet fields =
+ UnknownFieldSet.newBuilder().mergeFrom(unknownFields).clear().build();
+ assertTrue(fields.asMap().isEmpty());
+ }
+
+ public void testClearMessage() throws Exception {
+ TestEmptyMessage message =
+ TestEmptyMessage.newBuilder().mergeFrom(emptyMessage).clear().build();
+ assertEquals(0, message.getSerializedSize());
+ }
+
+ public void testClearField() throws Exception {
+ int fieldNumber = unknownFields.asMap().keySet().iterator().next();
+ UnknownFieldSet fields =
+ UnknownFieldSet.newBuilder().mergeFrom(unknownFields).clearField(fieldNumber).build();
+ assertFalse(fields.hasField(fieldNumber));
+ }
+
+ public void testParseKnownAndUnknown() throws Exception {
+ // Test mixing known and unknown fields when parsing.
+
+ UnknownFieldSet fields =
+ UnknownFieldSet.newBuilder(unknownFields)
+ .addField(123456,
+ UnknownFieldSet.Field.newBuilder().addVarint(654321).build())
+ .build();
+
+ ByteString data = fields.toByteString();
+ TestAllTypes destination = TestAllTypes.parseFrom(data);
+
+ TestUtil.assertAllFieldsSet(destination);
+ assertEquals(1, destination.getUnknownFields().asMap().size());
+
+ UnknownFieldSet.Field field =
+ destination.getUnknownFields().getField(123456);
+ assertEquals(1, field.getVarintList().size());
+ assertEquals(654321, (long) field.getVarintList().get(0));
+ }
+
+ public void testWrongTypeTreatedAsUnknown() throws Exception {
+ // Test that fields of the wrong wire type are treated like unknown fields
+ // when parsing.
+
+ ByteString bizarroData = getBizarroData();
+ TestAllTypes allTypesMessage = TestAllTypes.parseFrom(bizarroData);
+ TestEmptyMessage emptyMessage = TestEmptyMessage.parseFrom(bizarroData);
+
+ // All fields should have been interpreted as unknown, so the debug strings
+ // should be the same.
+ assertEquals(emptyMessage.toString(), allTypesMessage.toString());
+ }
+
+ public void testUnknownExtensions() throws Exception {
+ // Make sure fields are properly parsed to the UnknownFieldSet even when
+ // they are declared as extension numbers.
+
+ TestEmptyMessageWithExtensions message =
+ TestEmptyMessageWithExtensions.parseFrom(allFieldsData);
+
+ assertEquals(unknownFields.asMap().size(),
+ message.getUnknownFields().asMap().size());
+ assertEquals(allFieldsData, message.toByteString());
+ }
+
+ public void testWrongExtensionTypeTreatedAsUnknown() throws Exception {
+ // Test that fields of the wrong wire type are treated like unknown fields
+ // when parsing extensions.
+
+ ByteString bizarroData = getBizarroData();
+ TestAllExtensions allExtensionsMessage =
+ TestAllExtensions.parseFrom(bizarroData);
+ TestEmptyMessage emptyMessage = TestEmptyMessage.parseFrom(bizarroData);
+
+ // All fields should have been interpreted as unknown, so the debug strings
+ // should be the same.
+ assertEquals(emptyMessage.toString(),
+ allExtensionsMessage.toString());
+ }
+
+ public void testParseUnknownEnumValue() throws Exception {
+ Descriptors.FieldDescriptor singularField =
+ TestAllTypes.getDescriptor().findFieldByName("optional_nested_enum");
+ Descriptors.FieldDescriptor repeatedField =
+ TestAllTypes.getDescriptor().findFieldByName("repeated_nested_enum");
+ assertNotNull(singularField);
+ assertNotNull(repeatedField);
+
+ ByteString data =
+ UnknownFieldSet.newBuilder()
+ .addField(singularField.getNumber(),
+ UnknownFieldSet.Field.newBuilder()
+ .addVarint(TestAllTypes.NestedEnum.BAR.getNumber())
+ .addVarint(5) // not valid
+ .build())
+ .addField(repeatedField.getNumber(),
+ UnknownFieldSet.Field.newBuilder()
+ .addVarint(TestAllTypes.NestedEnum.FOO.getNumber())
+ .addVarint(4) // not valid
+ .addVarint(TestAllTypes.NestedEnum.BAZ.getNumber())
+ .addVarint(6) // not valid
+ .build())
+ .build()
+ .toByteString();
+
+ {
+ TestAllTypes message = TestAllTypes.parseFrom(data);
+ assertEquals(TestAllTypes.NestedEnum.BAR,
+ message.getOptionalNestedEnum());
+ assertEquals(
+ Arrays.asList(TestAllTypes.NestedEnum.FOO, TestAllTypes.NestedEnum.BAZ),
+ message.getRepeatedNestedEnumList());
+ assertEquals(Arrays.asList(5L),
+ message.getUnknownFields()
+ .getField(singularField.getNumber())
+ .getVarintList());
+ assertEquals(Arrays.asList(4L, 6L),
+ message.getUnknownFields()
+ .getField(repeatedField.getNumber())
+ .getVarintList());
+ }
+
+ {
+ TestAllExtensions message =
+ TestAllExtensions.parseFrom(data, TestUtil.getExtensionRegistry());
+ assertEquals(TestAllTypes.NestedEnum.BAR,
+ message.getExtension(UnittestProto.optionalNestedEnumExtension));
+ assertEquals(
+ Arrays.asList(TestAllTypes.NestedEnum.FOO, TestAllTypes.NestedEnum.BAZ),
+ message.getExtension(UnittestProto.repeatedNestedEnumExtension));
+ assertEquals(Arrays.asList(5L),
+ message.getUnknownFields()
+ .getField(singularField.getNumber())
+ .getVarintList());
+ assertEquals(Arrays.asList(4L, 6L),
+ message.getUnknownFields()
+ .getField(repeatedField.getNumber())
+ .getVarintList());
+ }
+ }
+
+ public void testLargeVarint() throws Exception {
+ ByteString data =
+ UnknownFieldSet.newBuilder()
+ .addField(1,
+ UnknownFieldSet.Field.newBuilder()
+ .addVarint(0x7FFFFFFFFFFFFFFFL)
+ .build())
+ .build()
+ .toByteString();
+ UnknownFieldSet parsed = UnknownFieldSet.parseFrom(data);
+ UnknownFieldSet.Field field = parsed.getField(1);
+ assertEquals(1, field.getVarintList().size());
+ assertEquals(0x7FFFFFFFFFFFFFFFL, (long)field.getVarintList().get(0));
+ }
+
+ public void testEqualsAndHashCode() {
+ UnknownFieldSet.Field fixed32Field =
+ UnknownFieldSet.Field.newBuilder()
+ .addFixed32(1)
+ .build();
+ UnknownFieldSet.Field fixed64Field =
+ UnknownFieldSet.Field.newBuilder()
+ .addFixed64(1)
+ .build();
+ UnknownFieldSet.Field varIntField =
+ UnknownFieldSet.Field.newBuilder()
+ .addVarint(1)
+ .build();
+ UnknownFieldSet.Field lengthDelimitedField =
+ UnknownFieldSet.Field.newBuilder()
+ .addLengthDelimited(ByteString.EMPTY)
+ .build();
+ UnknownFieldSet.Field groupField =
+ UnknownFieldSet.Field.newBuilder()
+ .addGroup(unknownFields)
+ .build();
+
+ UnknownFieldSet a =
+ UnknownFieldSet.newBuilder()
+ .addField(1, fixed32Field)
+ .build();
+ UnknownFieldSet b =
+ UnknownFieldSet.newBuilder()
+ .addField(1, fixed64Field)
+ .build();
+ UnknownFieldSet c =
+ UnknownFieldSet.newBuilder()
+ .addField(1, varIntField)
+ .build();
+ UnknownFieldSet d =
+ UnknownFieldSet.newBuilder()
+ .addField(1, lengthDelimitedField)
+ .build();
+ UnknownFieldSet e =
+ UnknownFieldSet.newBuilder()
+ .addField(1, groupField)
+ .build();
+
+ checkEqualsIsConsistent(a);
+ checkEqualsIsConsistent(b);
+ checkEqualsIsConsistent(c);
+ checkEqualsIsConsistent(d);
+ checkEqualsIsConsistent(e);
+
+ checkNotEqual(a, b);
+ checkNotEqual(a, c);
+ checkNotEqual(a, d);
+ checkNotEqual(a, e);
+ checkNotEqual(b, c);
+ checkNotEqual(b, d);
+ checkNotEqual(b, e);
+ checkNotEqual(c, d);
+ checkNotEqual(c, e);
+ checkNotEqual(d, e);
+ }
+
+ /**
+ * Asserts that the given field sets 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(UnknownFieldSet s1, UnknownFieldSet s2) {
+ String equalsError = String.format("%s should not be equal to %s", s1, s2);
+ assertFalse(equalsError, s1.equals(s2));
+ assertFalse(equalsError, s2.equals(s1));
+
+ assertFalse(
+ String.format("%s should have a different hash code from %s", s1, s2),
+ s1.hashCode() == s2.hashCode());
+ }
+
+ /**
+ * Asserts that the given field sets are equal and have identical hash codes.
+ */
+ private void checkEqualsIsConsistent(UnknownFieldSet set) {
+ // Object should be equal to itself.
+ assertEquals(set, set);
+
+ // Object should be equal to a copy of itself.
+ UnknownFieldSet copy = UnknownFieldSet.newBuilder(set).build();
+ assertEquals(set, copy);
+ assertEquals(copy, set);
+ assertEquals(set.hashCode(), copy.hashCode());
+ }
+
+ // =================================================================
+
+ public void testSerializeLite() throws Exception {
+ UnittestLite.TestEmptyMessageLite emptyMessageLite =
+ UnittestLite.TestEmptyMessageLite.parseFrom(allFieldsData);
+ assertEquals(allFieldsData.size(), emptyMessageLite.getSerializedSize());
+ ByteString data = emptyMessageLite.toByteString();
+ TestAllTypes message = TestAllTypes.parseFrom(data);
+ TestUtil.assertAllFieldsSet(message);
+ assertEquals(allFieldsData, data);
+ }
+
+ public void testAllExtensionsLite() throws Exception {
+ TestAllExtensions allExtensions = TestUtil.getAllExtensionsSet();
+ ByteString allExtensionsData = allExtensions.toByteString();
+ UnittestLite.TestEmptyMessageLite emptyMessageLite =
+ UnittestLite.TestEmptyMessageLite.parser().parseFrom(allExtensionsData);
+ ByteString data = emptyMessageLite.toByteString();
+ TestAllExtensions message =
+ TestAllExtensions.parseFrom(data, TestUtil.getExtensionRegistry());
+ TestUtil.assertAllExtensionsSet(message);
+ assertEquals(allExtensionsData, data);
+ }
+
+ public void testAllPackedFieldsLite() throws Exception {
+ TestPackedTypes allPackedFields = TestUtil.getPackedSet();
+ ByteString allPackedData = allPackedFields.toByteString();
+ UnittestLite.TestEmptyMessageLite emptyMessageLite =
+ UnittestLite.TestEmptyMessageLite.parseFrom(allPackedData);
+ ByteString data = emptyMessageLite.toByteString();
+ TestPackedTypes message =
+ TestPackedTypes.parseFrom(data, TestUtil.getExtensionRegistry());
+ TestUtil.assertPackedFieldsSet(message);
+ assertEquals(allPackedData, data);
+ }
+
+ public void testAllPackedExtensionsLite() throws Exception {
+ TestPackedExtensions allPackedExtensions = TestUtil.getPackedExtensionsSet();
+ ByteString allPackedExtensionsData = allPackedExtensions.toByteString();
+ UnittestLite.TestEmptyMessageLite emptyMessageLite =
+ UnittestLite.TestEmptyMessageLite.parseFrom(allPackedExtensionsData);
+ ByteString data = emptyMessageLite.toByteString();
+ TestPackedExtensions message =
+ TestPackedExtensions.parseFrom(data, TestUtil.getExtensionRegistry());
+ TestUtil.assertPackedExtensionsSet(message);
+ assertEquals(allPackedExtensionsData, data);
+ }
+
+ public void testCopyFromLite() throws Exception {
+ UnittestLite.TestEmptyMessageLite emptyMessageLite =
+ UnittestLite.TestEmptyMessageLite.parseFrom(allFieldsData);
+ UnittestLite.TestEmptyMessageLite emptyMessageLite2 =
+ UnittestLite.TestEmptyMessageLite.newBuilder()
+ .mergeFrom(emptyMessageLite).build();
+ assertEquals(emptyMessageLite.toByteString(), emptyMessageLite2.toByteString());
+ }
+
+ public void testMergeFromLite() throws Exception {
+ TestAllTypes message1 = TestAllTypes.newBuilder()
+ .setOptionalInt32(1)
+ .setOptionalString("foo")
+ .addRepeatedString("bar")
+ .setOptionalNestedEnum(TestAllTypes.NestedEnum.BAZ)
+ .build();
+
+ TestAllTypes message2 = TestAllTypes.newBuilder()
+ .setOptionalInt64(2)
+ .setOptionalString("baz")
+ .addRepeatedString("qux")
+ .setOptionalForeignEnum(ForeignEnum.FOREIGN_BAZ)
+ .build();
+
+ ByteString data1 = message1.toByteString();
+ UnittestLite.TestEmptyMessageLite emptyMessageLite1 =
+ UnittestLite.TestEmptyMessageLite.parseFrom(data1);
+ ByteString data2 = message2.toByteString();
+ UnittestLite.TestEmptyMessageLite emptyMessageLite2 =
+ UnittestLite.TestEmptyMessageLite.parseFrom(data2);
+
+ message1 = TestAllTypes.newBuilder(message1).mergeFrom(message2).build();
+ emptyMessageLite1 = UnittestLite.TestEmptyMessageLite.newBuilder(emptyMessageLite1)
+ .mergeFrom(emptyMessageLite2).build();
+
+ data1 = emptyMessageLite1.toByteString();
+ message2 = TestAllTypes.parseFrom(data1);
+
+ assertEquals(message1, message2);
+ }
+
+ public void testWrongTypeTreatedAsUnknownLite() throws Exception {
+ // Test that fields of the wrong wire type are treated like unknown fields
+ // when parsing.
+
+ ByteString bizarroData = getBizarroData();
+ TestAllTypes allTypesMessage = TestAllTypes.parseFrom(bizarroData);
+ UnittestLite.TestEmptyMessageLite emptyMessageLite =
+ UnittestLite.TestEmptyMessageLite.parseFrom(bizarroData);
+ ByteString data = emptyMessageLite.toByteString();
+ TestAllTypes allTypesMessage2 = TestAllTypes.parseFrom(data);
+
+ assertEquals(allTypesMessage.toString(), allTypesMessage2.toString());
+ }
+
+ public void testUnknownExtensionsLite() throws Exception {
+ // Make sure fields are properly parsed to the UnknownFieldSet even when
+ // they are declared as extension numbers.
+
+ UnittestLite.TestEmptyMessageWithExtensionsLite message =
+ UnittestLite.TestEmptyMessageWithExtensionsLite.parseFrom(allFieldsData);
+
+ assertEquals(allFieldsData, message.toByteString());
+ }
+
+ public void testWrongExtensionTypeTreatedAsUnknownLite() throws Exception {
+ // Test that fields of the wrong wire type are treated like unknown fields
+ // when parsing extensions.
+
+ ByteString bizarroData = getBizarroData();
+ TestAllExtensions allExtensionsMessage =
+ TestAllExtensions.parseFrom(bizarroData);
+ UnittestLite.TestEmptyMessageLite emptyMessageLite =
+ UnittestLite.TestEmptyMessageLite.parseFrom(bizarroData);
+
+ // All fields should have been interpreted as unknown, so the byte strings
+ // should be the same.
+ assertEquals(emptyMessageLite.toByteString(),
+ allExtensionsMessage.toByteString());
+ }
+
+ public void testParseUnknownEnumValueLite() throws Exception {
+ Descriptors.FieldDescriptor singularField =
+ TestAllTypes.getDescriptor().findFieldByName("optional_nested_enum");
+ Descriptors.FieldDescriptor repeatedField =
+ TestAllTypes.getDescriptor().findFieldByName("repeated_nested_enum");
+ assertNotNull(singularField);
+ assertNotNull(repeatedField);
+
+ ByteString data =
+ UnknownFieldSet.newBuilder()
+ .addField(singularField.getNumber(),
+ UnknownFieldSet.Field.newBuilder()
+ .addVarint(TestAllTypes.NestedEnum.BAR.getNumber())
+ .addVarint(5) // not valid
+ .build())
+ .addField(repeatedField.getNumber(),
+ UnknownFieldSet.Field.newBuilder()
+ .addVarint(TestAllTypes.NestedEnum.FOO.getNumber())
+ .addVarint(4) // not valid
+ .addVarint(TestAllTypes.NestedEnum.BAZ.getNumber())
+ .addVarint(6) // not valid
+ .build())
+ .build()
+ .toByteString();
+
+ UnittestLite.TestEmptyMessageLite emptyMessageLite =
+ UnittestLite.TestEmptyMessageLite.parseFrom(data);
+ data = emptyMessageLite.toByteString();
+
+ {
+ TestAllTypes message = TestAllTypes.parseFrom(data);
+ assertEquals(TestAllTypes.NestedEnum.BAR,
+ message.getOptionalNestedEnum());
+ assertEquals(
+ Arrays.asList(TestAllTypes.NestedEnum.FOO, TestAllTypes.NestedEnum.BAZ),
+ message.getRepeatedNestedEnumList());
+ assertEquals(Arrays.asList(5L),
+ message.getUnknownFields()
+ .getField(singularField.getNumber())
+ .getVarintList());
+ assertEquals(Arrays.asList(4L, 6L),
+ message.getUnknownFields()
+ .getField(repeatedField.getNumber())
+ .getVarintList());
+ }
+
+ {
+ TestAllExtensions message =
+ TestAllExtensions.parseFrom(data, TestUtil.getExtensionRegistry());
+ assertEquals(TestAllTypes.NestedEnum.BAR,
+ message.getExtension(UnittestProto.optionalNestedEnumExtension));
+ assertEquals(
+ Arrays.asList(TestAllTypes.NestedEnum.FOO, TestAllTypes.NestedEnum.BAZ),
+ message.getExtension(UnittestProto.repeatedNestedEnumExtension));
+ assertEquals(Arrays.asList(5L),
+ message.getUnknownFields()
+ .getField(singularField.getNumber())
+ .getVarintList());
+ assertEquals(Arrays.asList(4L, 6L),
+ message.getUnknownFields()
+ .getField(repeatedField.getNumber())
+ .getVarintList());
+ }
+ }
+
+ public void testClearLite() throws Exception {
+ UnittestLite.TestEmptyMessageLite emptyMessageLite1 =
+ UnittestLite.TestEmptyMessageLite.parseFrom(allFieldsData);
+ UnittestLite.TestEmptyMessageLite emptyMessageLite2 =
+ UnittestLite.TestEmptyMessageLite.newBuilder()
+ .mergeFrom(emptyMessageLite1).clear().build();
+ assertEquals(0, emptyMessageLite2.getSerializedSize());
+ ByteString data = emptyMessageLite2.toByteString();
+ assertEquals(0, data.size());
+ }
+
+}
diff --git a/java/core/src/test/java/com/google/protobuf/UnmodifiableLazyStringListTest.java b/java/core/src/test/java/com/google/protobuf/UnmodifiableLazyStringListTest.java
new file mode 100644
index 00000000..b1c75fc3
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/UnmodifiableLazyStringListTest.java
@@ -0,0 +1,227 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// 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 junit.framework.TestCase;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+
+/**
+ * Tests for {@link UnmodifiableLazyStringList}.
+ *
+ * @author jonp@google.com (Jon Perlow)
+ */
+public class UnmodifiableLazyStringListTest extends TestCase {
+
+ private static String STRING_A = "A";
+ private static String STRING_B = "B";
+ private static String STRING_C = "C";
+
+ private static ByteString BYTE_STRING_A = ByteString.copyFromUtf8("A");
+ private static ByteString BYTE_STRING_B = ByteString.copyFromUtf8("B");
+ private static ByteString BYTE_STRING_C = ByteString.copyFromUtf8("C");
+
+ public void testReadOnlyMethods() {
+ LazyStringArrayList rawList = createSampleList();
+ UnmodifiableLazyStringList list = new UnmodifiableLazyStringList(rawList);
+ assertEquals(3, list.size());
+ assertSame(STRING_A, list.get(0));
+ assertSame(STRING_B, list.get(1));
+ assertSame(STRING_C, list.get(2));
+ assertEquals(BYTE_STRING_A, list.getByteString(0));
+ assertEquals(BYTE_STRING_B, list.getByteString(1));
+ assertEquals(BYTE_STRING_C, list.getByteString(2));
+
+ List<ByteString> byteStringList = list.asByteStringList();
+ assertSame(list.getByteString(0), byteStringList.get(0));
+ assertSame(list.getByteString(1), byteStringList.get(1));
+ assertSame(list.getByteString(2), byteStringList.get(2));
+ }
+
+ public void testModifyMethods() {
+ LazyStringArrayList rawList = createSampleList();
+ UnmodifiableLazyStringList list = new UnmodifiableLazyStringList(rawList);
+
+ try {
+ list.remove(0);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ assertEquals(3, list.size());
+
+ try {
+ list.add(STRING_B);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ assertEquals(3, list.size());
+
+ try {
+ list.set(1, STRING_B);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ assertEquals(3, list.size());
+
+ List<ByteString> byteStringList = list.asByteStringList();
+ try {
+ byteStringList.remove(0);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ assertEquals(3, list.size());
+ assertEquals(3, byteStringList.size());
+
+ try {
+ byteStringList.add(BYTE_STRING_B);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ assertEquals(3, list.size());
+ assertEquals(3, byteStringList.size());
+
+ try {
+ byteStringList.set(1, BYTE_STRING_B);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ assertEquals(3, list.size());
+ assertEquals(3, byteStringList.size());
+ }
+
+ public void testIterator() {
+ LazyStringArrayList rawList = createSampleList();
+ UnmodifiableLazyStringList list = new UnmodifiableLazyStringList(rawList);
+
+ Iterator<String> iter = list.iterator();
+ int count = 0;
+ while (iter.hasNext()) {
+ iter.next();
+ count++;
+ try {
+ iter.remove();
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ }
+ assertEquals(3, count);
+
+ List<ByteString> byteStringList = list.asByteStringList();
+ Iterator<ByteString> byteIter = byteStringList.iterator();
+ count = 0;
+ while (byteIter.hasNext()) {
+ byteIter.next();
+ count++;
+ try {
+ byteIter.remove();
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ }
+ assertEquals(3, count);
+ }
+
+ public void testListIterator() {
+ LazyStringArrayList rawList = createSampleList();
+ UnmodifiableLazyStringList list = new UnmodifiableLazyStringList(rawList);
+
+ ListIterator<String> iter = list.listIterator();
+ int count = 0;
+ while (iter.hasNext()) {
+ iter.next();
+ count++;
+ try {
+ iter.remove();
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ try {
+ iter.set("bar");
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ try {
+ iter.add("bar");
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ }
+ assertEquals(3, count);
+
+ List<ByteString> byteStringList = list.asByteStringList();
+ ListIterator<ByteString> byteIter = byteStringList.listIterator();
+ count = 0;
+ while (byteIter.hasNext()) {
+ byteIter.next();
+ count++;
+ try {
+ byteIter.remove();
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ try {
+ byteIter.set(BYTE_STRING_A);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ try {
+ byteIter.add(BYTE_STRING_A);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ }
+ assertEquals(3, count);
+ }
+
+ private LazyStringArrayList createSampleList() {
+ LazyStringArrayList rawList = new LazyStringArrayList();
+ rawList.add(STRING_A);
+ rawList.add(STRING_B);
+ rawList.add(STRING_C);
+ return rawList;
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/WellKnownTypesTest.java b/java/core/src/test/java/com/google/protobuf/WellKnownTypesTest.java
new file mode 100644
index 00000000..982e200f
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/WellKnownTypesTest.java
@@ -0,0 +1,65 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// 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 com.google.protobuf.Descriptors.Descriptor;
+import com.google.protobuf.Descriptors.EnumDescriptor;
+import com.google.protobuf.Descriptors.EnumValueDescriptor;
+import com.google.protobuf.Descriptors.FieldDescriptor;
+import com.google.protobuf.test.TestWellKnownTypes;
+
+import junit.framework.TestCase;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * This test ensures that well-known types are included in protobuf Java
+ * runtime library.
+ */
+public class WellKnownTypesTest extends TestCase {
+ public void testWellKnownTypes() {
+ // The test passes if it compiles.
+ TestWellKnownTypes message = TestWellKnownTypes.newBuilder().build();
+ assertEquals(0, message.getAnyField().getSerializedSize());
+ assertEquals(0, message.getApiField().getSerializedSize());
+ assertEquals(0, message.getDurationField().getSerializedSize());
+ assertEquals(0, message.getEmptyField().getSerializedSize());
+ assertEquals(0, message.getFieldMaskField().getSerializedSize());
+ assertEquals(0, message.getSourceContextField().getSerializedSize());
+ assertEquals(0, message.getStructField().getSerializedSize());
+ assertEquals(0, message.getTimestampField().getSerializedSize());
+ assertEquals(0, message.getTypeField().getSerializedSize());
+ assertEquals(0, message.getInt32Field().getSerializedSize());
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/WireFormatTest.java b/java/core/src/test/java/com/google/protobuf/WireFormatTest.java
new file mode 100644
index 00000000..0175005d
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/WireFormatTest.java
@@ -0,0 +1,606 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// 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 junit.framework.TestCase;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.util.List;
+
+import protobuf_unittest.UnittestProto;
+import protobuf_unittest.UnittestProto.TestAllExtensions;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.TestFieldOrderings;
+import protobuf_unittest.UnittestProto.TestOneof2;
+import protobuf_unittest.UnittestProto.TestOneofBackwardsCompatible;
+import protobuf_unittest.UnittestProto.TestPackedExtensions;
+import protobuf_unittest.UnittestProto.TestPackedTypes;
+import protobuf_unittest.UnittestMset.RawMessageSet;
+import protobuf_unittest.UnittestMset.TestMessageSetExtension1;
+import protobuf_unittest.UnittestMset.TestMessageSetExtension2;
+import proto2_wireformat_unittest.UnittestMsetWireFormat.TestMessageSet;
+import com.google.protobuf.UnittestLite.TestAllExtensionsLite;
+import com.google.protobuf.UnittestLite.TestPackedExtensionsLite;
+
+/**
+ * Tests related to parsing and serialization.
+ *
+ * @author kenton@google.com (Kenton Varda)
+ */
+public class WireFormatTest extends TestCase {
+ public void testSerialization() throws Exception {
+ TestAllTypes message = TestUtil.getAllSet();
+
+ ByteString rawBytes = message.toByteString();
+ assertEquals(rawBytes.size(), message.getSerializedSize());
+
+ TestAllTypes message2 = TestAllTypes.parseFrom(rawBytes);
+
+ TestUtil.assertAllFieldsSet(message2);
+ }
+
+ public void testSerializationPacked() throws Exception {
+ TestPackedTypes message = TestUtil.getPackedSet();
+
+ ByteString rawBytes = message.toByteString();
+ assertEquals(rawBytes.size(), message.getSerializedSize());
+
+ TestPackedTypes message2 = TestPackedTypes.parseFrom(rawBytes);
+
+ TestUtil.assertPackedFieldsSet(message2);
+ }
+
+ public void testSerializeExtensions() throws Exception {
+ // TestAllTypes and TestAllExtensions should have compatible wire formats,
+ // so if we serialize a TestAllExtensions then parse it as TestAllTypes
+ // it should work.
+
+ TestAllExtensions message = TestUtil.getAllExtensionsSet();
+ ByteString rawBytes = message.toByteString();
+ assertEquals(rawBytes.size(), message.getSerializedSize());
+
+ TestAllTypes message2 = TestAllTypes.parseFrom(rawBytes);
+
+ TestUtil.assertAllFieldsSet(message2);
+ }
+
+ public void testSerializePackedExtensions() throws Exception {
+ // TestPackedTypes and TestPackedExtensions should have compatible wire
+ // formats; check that they serialize to the same string.
+ TestPackedExtensions message = TestUtil.getPackedExtensionsSet();
+ ByteString rawBytes = message.toByteString();
+
+ TestPackedTypes message2 = TestUtil.getPackedSet();
+ ByteString rawBytes2 = message2.toByteString();
+
+ assertEquals(rawBytes, rawBytes2);
+ }
+
+ public void testSerializationPackedWithoutGetSerializedSize()
+ throws Exception {
+ // Write directly to an OutputStream, without invoking getSerializedSize()
+ // This used to be a bug where the size of a packed field was incorrect,
+ // since getSerializedSize() was never invoked.
+ TestPackedTypes message = TestUtil.getPackedSet();
+
+ // Directly construct a CodedOutputStream around the actual OutputStream,
+ // in case writeTo(OutputStream output) invokes getSerializedSize();
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ CodedOutputStream codedOutput = CodedOutputStream.newInstance(outputStream);
+
+ message.writeTo(codedOutput);
+
+ codedOutput.flush();
+
+ TestPackedTypes message2 = TestPackedTypes.parseFrom(
+ outputStream.toByteArray());
+
+ TestUtil.assertPackedFieldsSet(message2);
+ }
+
+ public void testSerializeExtensionsLite() throws Exception {
+ // TestAllTypes and TestAllExtensions should have compatible wire formats,
+ // so if we serialize a TestAllExtensions then parse it as TestAllTypes
+ // it should work.
+
+ TestAllExtensionsLite message = TestUtil.getAllLiteExtensionsSet();
+ ByteString rawBytes = message.toByteString();
+ assertEquals(rawBytes.size(), message.getSerializedSize());
+
+ TestAllTypes message2 = TestAllTypes.parseFrom(rawBytes);
+
+ TestUtil.assertAllFieldsSet(message2);
+ }
+
+ public void testSerializePackedExtensionsLite() throws Exception {
+ // TestPackedTypes and TestPackedExtensions should have compatible wire
+ // formats; check that they serialize to the same string.
+ TestPackedExtensionsLite message = TestUtil.getLitePackedExtensionsSet();
+ ByteString rawBytes = message.toByteString();
+
+ TestPackedTypes message2 = TestUtil.getPackedSet();
+ ByteString rawBytes2 = message2.toByteString();
+
+ assertEquals(rawBytes, rawBytes2);
+ }
+
+ public void testParseExtensions() throws Exception {
+ // TestAllTypes and TestAllExtensions should have compatible wire formats,
+ // so if we serialize a TestAllTypes then parse it as TestAllExtensions
+ // it should work.
+
+ TestAllTypes message = TestUtil.getAllSet();
+ ByteString rawBytes = message.toByteString();
+
+ ExtensionRegistry registry = TestUtil.getExtensionRegistry();
+
+ TestAllExtensions message2 =
+ TestAllExtensions.parseFrom(rawBytes, registry);
+
+ TestUtil.assertAllExtensionsSet(message2);
+ }
+
+ public void testParsePackedExtensions() throws Exception {
+ // Ensure that packed extensions can be properly parsed.
+ TestPackedExtensions message = TestUtil.getPackedExtensionsSet();
+ ByteString rawBytes = message.toByteString();
+
+ ExtensionRegistry registry = TestUtil.getExtensionRegistry();
+
+ TestPackedExtensions message2 =
+ TestPackedExtensions.parseFrom(rawBytes, registry);
+
+ TestUtil.assertPackedExtensionsSet(message2);
+ }
+
+ public void testParseExtensionsLite() throws Exception {
+ // TestAllTypes and TestAllExtensions should have compatible wire formats,
+ // so if we serialize a TestAllTypes then parse it as TestAllExtensions
+ // it should work.
+
+ TestAllTypes message = TestUtil.getAllSet();
+ ByteString rawBytes = message.toByteString();
+
+ ExtensionRegistryLite registry_lite = TestUtil.getExtensionRegistryLite();
+
+ TestAllExtensionsLite message2 =
+ TestAllExtensionsLite.parseFrom(rawBytes, registry_lite);
+
+ TestUtil.assertAllExtensionsSet(message2);
+
+ // Try again using a full extension registry.
+ ExtensionRegistry registry = TestUtil.getExtensionRegistry();
+
+ TestAllExtensionsLite message3 =
+ TestAllExtensionsLite.parseFrom(rawBytes, registry);
+
+ TestUtil.assertAllExtensionsSet(message3);
+ }
+
+ public void testParsePackedExtensionsLite() throws Exception {
+ // Ensure that packed extensions can be properly parsed.
+ TestPackedExtensionsLite message = TestUtil.getLitePackedExtensionsSet();
+ ByteString rawBytes = message.toByteString();
+
+ ExtensionRegistryLite registry = TestUtil.getExtensionRegistryLite();
+
+ TestPackedExtensionsLite message2 =
+ TestPackedExtensionsLite.parseFrom(rawBytes, registry);
+
+ TestUtil.assertPackedExtensionsSet(message2);
+ }
+
+ public void testExtensionsSerializedSize() throws Exception {
+ assertNotSame(TestUtil.getAllSet().getSerializedSize(),
+ TestUtil.getAllExtensionsSet().getSerializedSize());
+ }
+
+ public void testSerializeDelimited() throws Exception {
+ ByteArrayOutputStream output = new ByteArrayOutputStream();
+ TestUtil.getAllSet().writeDelimitedTo(output);
+ output.write(12);
+ TestUtil.getPackedSet().writeDelimitedTo(output);
+ output.write(34);
+
+ ByteArrayInputStream input = new ByteArrayInputStream(output.toByteArray());
+
+ TestUtil.assertAllFieldsSet(TestAllTypes.parseDelimitedFrom(input));
+ assertEquals(12, input.read());
+ TestUtil.assertPackedFieldsSet(TestPackedTypes.parseDelimitedFrom(input));
+ assertEquals(34, input.read());
+ assertEquals(-1, input.read());
+
+ // We're at EOF, so parsing again should return null.
+ assertTrue(TestAllTypes.parseDelimitedFrom(input) == null);
+ }
+
+ private void assertFieldsInOrder(ByteString data) throws Exception {
+ CodedInputStream input = data.newCodedInput();
+ int previousTag = 0;
+
+ while (true) {
+ int tag = input.readTag();
+ if (tag == 0) {
+ break;
+ }
+
+ assertTrue(tag > previousTag);
+ previousTag = tag;
+ input.skipField(tag);
+ }
+ }
+
+ public void testInterleavedFieldsAndExtensions() throws Exception {
+ // Tests that fields are written in order even when extension ranges
+ // are interleaved with field numbers.
+ ByteString data =
+ TestFieldOrderings.newBuilder()
+ .setMyInt(1)
+ .setMyString("foo")
+ .setMyFloat(1.0F)
+ .setExtension(UnittestProto.myExtensionInt, 23)
+ .setExtension(UnittestProto.myExtensionString, "bar")
+ .build().toByteString();
+ assertFieldsInOrder(data);
+
+ Descriptors.Descriptor descriptor = TestFieldOrderings.getDescriptor();
+ ByteString dynamic_data =
+ DynamicMessage.newBuilder(TestFieldOrderings.getDescriptor())
+ .setField(descriptor.findFieldByName("my_int"), 1L)
+ .setField(descriptor.findFieldByName("my_string"), "foo")
+ .setField(descriptor.findFieldByName("my_float"), 1.0F)
+ .setField(UnittestProto.myExtensionInt.getDescriptor(), 23)
+ .setField(UnittestProto.myExtensionString.getDescriptor(), "bar")
+ .build().toByteString();
+ assertFieldsInOrder(dynamic_data);
+ }
+
+ private ExtensionRegistry getTestFieldOrderingsRegistry() {
+ ExtensionRegistry result = ExtensionRegistry.newInstance();
+ result.add(UnittestProto.myExtensionInt);
+ result.add(UnittestProto.myExtensionString);
+ return result;
+ }
+
+ public void testParseMultipleExtensionRanges() throws Exception {
+ // Make sure we can parse a message that contains multiple extensions
+ // ranges.
+ TestFieldOrderings source =
+ TestFieldOrderings.newBuilder()
+ .setMyInt(1)
+ .setMyString("foo")
+ .setMyFloat(1.0F)
+ .setExtension(UnittestProto.myExtensionInt, 23)
+ .setExtension(UnittestProto.myExtensionString, "bar")
+ .build();
+ TestFieldOrderings dest =
+ TestFieldOrderings.parseFrom(source.toByteString(),
+ getTestFieldOrderingsRegistry());
+ assertEquals(source, dest);
+ }
+
+ public void testParseMultipleExtensionRangesDynamic() throws Exception {
+ // Same as above except with DynamicMessage.
+ Descriptors.Descriptor descriptor = TestFieldOrderings.getDescriptor();
+ DynamicMessage source =
+ DynamicMessage.newBuilder(TestFieldOrderings.getDescriptor())
+ .setField(descriptor.findFieldByName("my_int"), 1L)
+ .setField(descriptor.findFieldByName("my_string"), "foo")
+ .setField(descriptor.findFieldByName("my_float"), 1.0F)
+ .setField(UnittestProto.myExtensionInt.getDescriptor(), 23)
+ .setField(UnittestProto.myExtensionString.getDescriptor(), "bar")
+ .build();
+ DynamicMessage dest =
+ DynamicMessage.parseFrom(descriptor, source.toByteString(),
+ getTestFieldOrderingsRegistry());
+ assertEquals(source, dest);
+ }
+
+ private static final int UNKNOWN_TYPE_ID = 1550055;
+ private static final int TYPE_ID_1 =
+ TestMessageSetExtension1.getDescriptor().getExtensions().get(0).getNumber();
+ private static final int TYPE_ID_2 =
+ TestMessageSetExtension2.getDescriptor().getExtensions().get(0).getNumber();
+
+ public void testSerializeMessageSetEagerly() throws Exception {
+ testSerializeMessageSetWithFlag(true);
+ }
+
+ public void testSerializeMessageSetNotEagerly() throws Exception {
+ testSerializeMessageSetWithFlag(false);
+ }
+
+ private void testSerializeMessageSetWithFlag(boolean eagerParsing)
+ throws Exception {
+ ExtensionRegistryLite.setEagerlyParseMessageSets(eagerParsing);
+ // Set up a TestMessageSet with two known messages and an unknown one.
+ TestMessageSet messageSet =
+ TestMessageSet.newBuilder()
+ .setExtension(
+ TestMessageSetExtension1.messageSetExtension,
+ TestMessageSetExtension1.newBuilder().setI(123).build())
+ .setExtension(
+ TestMessageSetExtension2.messageSetExtension,
+ TestMessageSetExtension2.newBuilder().setStr("foo").build())
+ .setUnknownFields(
+ UnknownFieldSet.newBuilder()
+ .addField(UNKNOWN_TYPE_ID,
+ UnknownFieldSet.Field.newBuilder()
+ .addLengthDelimited(ByteString.copyFromUtf8("bar"))
+ .build())
+ .build())
+ .build();
+
+ ByteString data = messageSet.toByteString();
+
+ // Parse back using RawMessageSet and check the contents.
+ RawMessageSet raw = RawMessageSet.parseFrom(data);
+
+ assertTrue(raw.getUnknownFields().asMap().isEmpty());
+
+ assertEquals(3, raw.getItemCount());
+ assertEquals(TYPE_ID_1, raw.getItem(0).getTypeId());
+ assertEquals(TYPE_ID_2, raw.getItem(1).getTypeId());
+ assertEquals(UNKNOWN_TYPE_ID, raw.getItem(2).getTypeId());
+
+ TestMessageSetExtension1 message1 =
+ TestMessageSetExtension1.parseFrom(
+ raw.getItem(0).getMessage().toByteArray());
+ assertEquals(123, message1.getI());
+
+ TestMessageSetExtension2 message2 =
+ TestMessageSetExtension2.parseFrom(
+ raw.getItem(1).getMessage().toByteArray());
+ assertEquals("foo", message2.getStr());
+
+ assertEquals("bar", raw.getItem(2).getMessage().toStringUtf8());
+ }
+
+ public void testParseMessageSetEagerly() throws Exception {
+ testParseMessageSetWithFlag(true);
+ }
+
+ public void testParseMessageSetNotEagerly()throws Exception {
+ testParseMessageSetWithFlag(false);
+ }
+
+ private void testParseMessageSetWithFlag(boolean eagerParsing)
+ throws Exception {
+ ExtensionRegistryLite.setEagerlyParseMessageSets(eagerParsing);
+ ExtensionRegistry extensionRegistry = ExtensionRegistry.newInstance();
+ extensionRegistry.add(TestMessageSetExtension1.messageSetExtension);
+ extensionRegistry.add(TestMessageSetExtension2.messageSetExtension);
+
+ // Set up a RawMessageSet with two known messages and an unknown one.
+ RawMessageSet raw =
+ RawMessageSet.newBuilder()
+ .addItem(
+ RawMessageSet.Item.newBuilder()
+ .setTypeId(TYPE_ID_1)
+ .setMessage(
+ TestMessageSetExtension1.newBuilder()
+ .setI(123)
+ .build().toByteString())
+ .build())
+ .addItem(
+ RawMessageSet.Item.newBuilder()
+ .setTypeId(TYPE_ID_2)
+ .setMessage(
+ TestMessageSetExtension2.newBuilder()
+ .setStr("foo")
+ .build().toByteString())
+ .build())
+ .addItem(
+ RawMessageSet.Item.newBuilder()
+ .setTypeId(UNKNOWN_TYPE_ID)
+ .setMessage(ByteString.copyFromUtf8("bar"))
+ .build())
+ .build();
+
+ ByteString data = raw.toByteString();
+
+ // Parse as a TestMessageSet and check the contents.
+ TestMessageSet messageSet =
+ TestMessageSet.parseFrom(data, extensionRegistry);
+
+ assertEquals(123, messageSet.getExtension(
+ TestMessageSetExtension1.messageSetExtension).getI());
+ assertEquals("foo", messageSet.getExtension(
+ TestMessageSetExtension2.messageSetExtension).getStr());
+
+ // Check for unknown field with type LENGTH_DELIMITED,
+ // number UNKNOWN_TYPE_ID, and contents "bar".
+ UnknownFieldSet unknownFields = messageSet.getUnknownFields();
+ assertEquals(1, unknownFields.asMap().size());
+ assertTrue(unknownFields.hasField(UNKNOWN_TYPE_ID));
+
+ UnknownFieldSet.Field field = unknownFields.getField(UNKNOWN_TYPE_ID);
+ assertEquals(1, field.getLengthDelimitedList().size());
+ assertEquals("bar", field.getLengthDelimitedList().get(0).toStringUtf8());
+ }
+
+ public void testParseMessageSetExtensionEagerly() throws Exception {
+ testParseMessageSetExtensionWithFlag(true);
+ }
+
+ public void testParseMessageSetExtensionNotEagerly() throws Exception {
+ testParseMessageSetExtensionWithFlag(false);
+ }
+
+ private void testParseMessageSetExtensionWithFlag(boolean eagerParsing)
+ throws Exception {
+ ExtensionRegistryLite.setEagerlyParseMessageSets(eagerParsing);
+ ExtensionRegistry extensionRegistry = ExtensionRegistry.newInstance();
+ extensionRegistry.add(TestMessageSetExtension1.messageSetExtension);
+
+ // Set up a RawMessageSet with a known messages.
+ int TYPE_ID_1 =
+ TestMessageSetExtension1
+ .getDescriptor().getExtensions().get(0).getNumber();
+ RawMessageSet raw =
+ RawMessageSet.newBuilder()
+ .addItem(
+ RawMessageSet.Item.newBuilder()
+ .setTypeId(TYPE_ID_1)
+ .setMessage(
+ TestMessageSetExtension1.newBuilder()
+ .setI(123)
+ .build().toByteString())
+ .build())
+ .build();
+
+ ByteString data = raw.toByteString();
+
+ // Parse as a TestMessageSet and check the contents.
+ TestMessageSet messageSet =
+ TestMessageSet.parseFrom(data, extensionRegistry);
+ assertEquals(123, messageSet.getExtension(
+ TestMessageSetExtension1.messageSetExtension).getI());
+ }
+
+ public void testMergeLazyMessageSetExtensionEagerly() throws Exception {
+ testMergeLazyMessageSetExtensionWithFlag(true);
+ }
+
+ public void testMergeLazyMessageSetExtensionNotEagerly() throws Exception {
+ testMergeLazyMessageSetExtensionWithFlag(false);
+ }
+
+ private void testMergeLazyMessageSetExtensionWithFlag(boolean eagerParsing)
+ throws Exception {
+ ExtensionRegistryLite.setEagerlyParseMessageSets(eagerParsing);
+ ExtensionRegistry extensionRegistry = ExtensionRegistry.newInstance();
+ extensionRegistry.add(TestMessageSetExtension1.messageSetExtension);
+
+ // Set up a RawMessageSet with a known messages.
+ int TYPE_ID_1 =
+ TestMessageSetExtension1
+ .getDescriptor().getExtensions().get(0).getNumber();
+ RawMessageSet raw =
+ RawMessageSet.newBuilder()
+ .addItem(
+ RawMessageSet.Item.newBuilder()
+ .setTypeId(TYPE_ID_1)
+ .setMessage(
+ TestMessageSetExtension1.newBuilder()
+ .setI(123)
+ .build().toByteString())
+ .build())
+ .build();
+
+ ByteString data = raw.toByteString();
+
+ // Parse as a TestMessageSet and store value into lazy field
+ TestMessageSet messageSet =
+ TestMessageSet.parseFrom(data, extensionRegistry);
+ // Merge lazy field check the contents.
+ messageSet =
+ messageSet.toBuilder().mergeFrom(data, extensionRegistry).build();
+ assertEquals(123, messageSet.getExtension(
+ TestMessageSetExtension1.messageSetExtension).getI());
+ }
+
+ public void testMergeMessageSetExtensionEagerly() throws Exception {
+ testMergeMessageSetExtensionWithFlag(true);
+ }
+
+ public void testMergeMessageSetExtensionNotEagerly() throws Exception {
+ testMergeMessageSetExtensionWithFlag(false);
+ }
+
+ private void testMergeMessageSetExtensionWithFlag(boolean eagerParsing)
+ throws Exception {
+ ExtensionRegistryLite.setEagerlyParseMessageSets(eagerParsing);
+ ExtensionRegistry extensionRegistry = ExtensionRegistry.newInstance();
+ extensionRegistry.add(TestMessageSetExtension1.messageSetExtension);
+
+ // Set up a RawMessageSet with a known messages.
+ int TYPE_ID_1 =
+ TestMessageSetExtension1
+ .getDescriptor().getExtensions().get(0).getNumber();
+ RawMessageSet raw =
+ RawMessageSet.newBuilder()
+ .addItem(
+ RawMessageSet.Item.newBuilder()
+ .setTypeId(TYPE_ID_1)
+ .setMessage(
+ TestMessageSetExtension1.newBuilder()
+ .setI(123)
+ .build().toByteString())
+ .build())
+ .build();
+
+ // Serialize RawMessageSet unnormally (message value before type id)
+ ByteString.CodedBuilder out = ByteString.newCodedBuilder(
+ raw.getSerializedSize());
+ CodedOutputStream output = out.getCodedOutput();
+ List<RawMessageSet.Item> items = raw.getItemList();
+ for (int i = 0; i < items.size(); i++) {
+ RawMessageSet.Item item = items.get(i);
+ output.writeTag(1, WireFormat.WIRETYPE_START_GROUP);
+ output.writeBytes(3, item.getMessage());
+ output.writeInt32(2, item.getTypeId());
+ output.writeTag(1, WireFormat.WIRETYPE_END_GROUP);
+ }
+ ByteString data = out.build();
+
+ // Merge bytes into TestMessageSet and check the contents.
+ TestMessageSet messageSet =
+ TestMessageSet.newBuilder().mergeFrom(data, extensionRegistry).build();
+ assertEquals(123, messageSet.getExtension(
+ TestMessageSetExtension1.messageSetExtension).getI());
+ }
+
+ // ================================================================
+ // oneof
+ public void testOneofWireFormat() throws Exception {
+ TestOneof2.Builder builder = TestOneof2.newBuilder();
+ TestUtil.setOneof(builder);
+ TestOneof2 message = builder.build();
+ ByteString rawBytes = message.toByteString();
+
+ assertEquals(rawBytes.size(), message.getSerializedSize());
+
+ TestOneof2 message2 = TestOneof2.parseFrom(rawBytes);
+ TestUtil.assertOneofSet(message2);
+ }
+
+ public void testOneofOnlyLastSet() throws Exception {
+ TestOneofBackwardsCompatible source = TestOneofBackwardsCompatible
+ .newBuilder().setFooInt(100).setFooString("101").build();
+
+ ByteString rawBytes = source.toByteString();
+ TestOneof2 message = TestOneof2.parseFrom(rawBytes);
+ assertFalse(message.hasFooInt());
+ assertTrue(message.hasFooString());
+ }
+}