| // 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 org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertFalse; |
| import static org.junit.Assert.assertNull; |
| |
| import com.google.protobuf.testing.Proto2TestingLite.Proto2EmptyLite; |
| import com.google.protobuf.testing.Proto2TestingLite.Proto2MessageLite; |
| import com.google.protobuf.testing.Proto2TestingLite.Proto2MessageLite.TestEnum; |
| import com.google.protobuf.testing.Proto2TestingLite.Proto2MessageLiteWithMaps; |
| import java.io.ByteArrayOutputStream; |
| import java.io.IOException; |
| import java.util.List; |
| import org.junit.Test; |
| |
| /** Base class for tests using {@link Proto2MessageLite}. */ |
| public abstract class AbstractProto2LiteSchemaTest extends AbstractSchemaTest<Proto2MessageLite> { |
| |
| @Override |
| protected Proto2MessageLiteFactory messageFactory() { |
| return new Proto2MessageLiteFactory(10, 20, 2, 2); |
| } |
| |
| @Test |
| public void mergeOptionalMessageFields() throws Exception { |
| Proto2MessageLite message1 = |
| newBuilder() |
| .setFieldMessage10(newBuilder().setFieldInt643(123).clearFieldInt325().build()) |
| .build(); |
| Proto2MessageLite message2 = |
| newBuilder() |
| .setFieldMessage10(newBuilder().clearFieldInt643().setFieldInt325(456).build()) |
| .build(); |
| Proto2MessageLite message3 = |
| newBuilder() |
| .setFieldMessage10(newBuilder().setFieldInt643(789).clearFieldInt325().build()) |
| .build(); |
| ByteArrayOutputStream output = new ByteArrayOutputStream(); |
| message1.writeTo(output); |
| message2.writeTo(output); |
| message3.writeTo(output); |
| byte[] data = output.toByteArray(); |
| |
| Proto2MessageLite merged = |
| ExperimentalSerializationUtil.fromByteArray(data, Proto2MessageLite.class); |
| assertEquals(789, merged.getFieldMessage10().getFieldInt643()); |
| assertEquals(456, merged.getFieldMessage10().getFieldInt325()); |
| } |
| |
| @Test |
| public void oneofFieldsShouldRoundtrip() throws IOException { |
| roundtrip("Field 53", newBuilder().setFieldDouble53(100).build()); |
| roundtrip("Field 54", newBuilder().setFieldFloat54(100).build()); |
| roundtrip("Field 55", newBuilder().setFieldInt6455(100).build()); |
| roundtrip("Field 56", newBuilder().setFieldUint6456(100L).build()); |
| roundtrip("Field 57", newBuilder().setFieldInt3257(100).build()); |
| roundtrip("Field 58", newBuilder().setFieldFixed6458(100).build()); |
| roundtrip("Field 59", newBuilder().setFieldFixed3259(100).build()); |
| roundtrip("Field 60", newBuilder().setFieldBool60(true).build()); |
| roundtrip("Field 61", newBuilder().setFieldString61(data().getString()).build()); |
| roundtrip( |
| "Field 62", newBuilder().setFieldMessage62(newBuilder().setFieldDouble1(100)).build()); |
| roundtrip("Field 63", newBuilder().setFieldBytes63(data().getBytes()).build()); |
| roundtrip("Field 64", newBuilder().setFieldUint3264(100).build()); |
| roundtrip("Field 65", newBuilder().setFieldSfixed3265(100).build()); |
| roundtrip("Field 66", newBuilder().setFieldSfixed6466(100).build()); |
| roundtrip("Field 67", newBuilder().setFieldSint3267(100).build()); |
| roundtrip("Field 68", newBuilder().setFieldSint6468(100).build()); |
| roundtrip( |
| "Field 69", |
| newBuilder() |
| .setFieldGroup69( |
| Proto2MessageLite.FieldGroup69.newBuilder().setFieldInt3270(data().getInt())) |
| .build()); |
| } |
| |
| private Proto2MessageLite.Builder newBuilder() { |
| return messageFactory().newMessage().toBuilder(); |
| } |
| |
| @Override |
| protected List<Proto2MessageLite> newMessagesMissingRequiredFields() { |
| return messageFactory().newMessagesMissingRequiredFields(); |
| } |
| |
| @Test |
| public void mapsShouldRoundtrip() throws IOException { |
| roundtrip( |
| "Proto2MessageLiteWithMaps", |
| new Proto2MessageLiteFactory(2, 10, 2, 2).newMessageWithMaps(), |
| Protobuf.getInstance().schemaFor(Proto2MessageLiteWithMaps.class)); |
| } |
| |
| @Test |
| public void unknownFieldsUnrecognized() throws Exception { |
| Proto2MessageLite expectedMessage = messageFactory().newMessage(); |
| byte[] serializedBytes = expectedMessage.toByteArray(); |
| Proto2EmptyLite empty = |
| ExperimentalSerializationUtil.fromByteArray(serializedBytes, Proto2EmptyLite.class); |
| |
| // Merge serialized bytes into an empty message, then reserialize and merge it to a new |
| // Proto2Message. Make sure the two messages equal. |
| byte[] roundtripBytes = ExperimentalSerializationUtil.toByteArray(empty); |
| Proto2MessageLite roundtripMessage = |
| ExperimentalSerializationUtil.fromByteArray(roundtripBytes, Proto2MessageLite.class); |
| assertEquals(expectedMessage, roundtripMessage); |
| } |
| |
| @Test |
| public void unknownEnum() throws IOException { |
| // Use unknown fields to hold invalid enum values. |
| UnknownFieldSetLite unknowns = UnknownFieldSetLite.newInstance(); |
| final int outOfRange = 1000; |
| assertNull(TestEnum.forNumber(outOfRange)); |
| unknowns.storeField( |
| WireFormat.makeTag( |
| Proto2MessageLite.FIELD_ENUM_13_FIELD_NUMBER, WireFormat.WIRETYPE_VARINT), |
| (long) outOfRange); |
| unknowns.storeField( |
| WireFormat.makeTag( |
| Proto2MessageLite.FIELD_ENUM_LIST_30_FIELD_NUMBER, WireFormat.WIRETYPE_VARINT), |
| (long) TestEnum.ONE_VALUE); |
| unknowns.storeField( |
| WireFormat.makeTag( |
| Proto2MessageLite.FIELD_ENUM_LIST_30_FIELD_NUMBER, WireFormat.WIRETYPE_VARINT), |
| (long) outOfRange); |
| unknowns.storeField( |
| WireFormat.makeTag( |
| Proto2MessageLite.FIELD_ENUM_LIST_30_FIELD_NUMBER, WireFormat.WIRETYPE_VARINT), |
| (long) TestEnum.TWO_VALUE); |
| |
| { |
| // Construct a packed enum list. |
| int packedSize = |
| CodedOutputStream.computeUInt32SizeNoTag(TestEnum.ONE_VALUE) |
| + CodedOutputStream.computeUInt32SizeNoTag(outOfRange) |
| + CodedOutputStream.computeUInt32SizeNoTag(TestEnum.ONE_VALUE); |
| ByteString.CodedBuilder packedBuilder = ByteString.newCodedBuilder(packedSize); |
| CodedOutputStream packedOut = packedBuilder.getCodedOutput(); |
| packedOut.writeEnumNoTag(TestEnum.ONE_VALUE); |
| packedOut.writeEnumNoTag(outOfRange); |
| packedOut.writeEnumNoTag(TestEnum.TWO_VALUE); |
| unknowns.storeField( |
| WireFormat.makeTag( |
| Proto2MessageLite.FIELD_ENUM_LIST_PACKED_44_FIELD_NUMBER, |
| WireFormat.WIRETYPE_LENGTH_DELIMITED), |
| packedBuilder.build()); |
| } |
| int size = unknowns.getSerializedSize(); |
| byte[] output = new byte[size]; |
| CodedOutputStream codedOutput = CodedOutputStream.newInstance(output); |
| unknowns.writeTo(codedOutput); |
| codedOutput.flush(); |
| |
| Proto2MessageLite parsed = |
| ExperimentalSerializationUtil.fromByteArray(output, Proto2MessageLite.class); |
| assertFalse("out-of-range singular enum should not be in message", parsed.hasFieldEnum13()); |
| assertEquals( |
| "out-of-range repeated enum should not be in message", 2, parsed.getFieldEnumList30Count()); |
| assertEquals(TestEnum.ONE, parsed.getFieldEnumList30(0)); |
| assertEquals(TestEnum.TWO, parsed.getFieldEnumList30(1)); |
| assertEquals( |
| "out-of-range packed repeated enum should not be in message", |
| 2, |
| parsed.getFieldEnumListPacked44Count()); |
| assertEquals(TestEnum.ONE, parsed.getFieldEnumListPacked44(0)); |
| assertEquals(TestEnum.TWO, parsed.getFieldEnumListPacked44(1)); |
| } |
| } |