1 // Protocol Buffers - Google's data interchange format 2 // Copyright 2008 Google Inc. All rights reserved. 3 // https://developers.google.com/protocol-buffers/ 4 // 5 // Redistribution and use in source and binary forms, with or without 6 // modification, are permitted provided that the following conditions are 7 // met: 8 // 9 // * Redistributions of source code must retain the above copyright 10 // notice, this list of conditions and the following disclaimer. 11 // * Redistributions in binary form must reproduce the above 12 // copyright notice, this list of conditions and the following disclaimer 13 // in the documentation and/or other materials provided with the 14 // distribution. 15 // * Neither the name of Google Inc. nor the names of its 16 // contributors may be used to endorse or promote products derived from 17 // this software without specific prior written permission. 18 // 19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 31 package com.google.protobuf; 32 33 import static org.junit.Assert.assertEquals; 34 import static org.junit.Assert.assertFalse; 35 import static org.junit.Assert.assertNull; 36 37 import com.google.protobuf.testing.Proto2Testing.Proto2Empty; 38 import com.google.protobuf.testing.Proto2Testing.Proto2Message; 39 import com.google.protobuf.testing.Proto2Testing.Proto2Message.TestEnum; 40 import com.google.protobuf.testing.Proto2Testing.Proto2MessageWithMaps; 41 import java.io.ByteArrayOutputStream; 42 import java.io.IOException; 43 import java.util.List; 44 import org.junit.Test; 45 46 /** Base class for tests using {@link Proto2Message}. */ 47 public abstract class AbstractProto2SchemaTest extends AbstractSchemaTest<Proto2Message> { 48 49 @Override messageFactory()50 protected Proto2MessageFactory messageFactory() { 51 return new Proto2MessageFactory(10, 20, 2, 2); 52 } 53 54 @Test mergeOptionalMessageFields()55 public void mergeOptionalMessageFields() throws Exception { 56 Proto2Message message1 = 57 newBuilder() 58 .setFieldMessage10(newBuilder().setFieldInt643(123).clearFieldInt325().build()) 59 .build(); 60 Proto2Message message2 = 61 newBuilder() 62 .setFieldMessage10(newBuilder().clearFieldInt643().setFieldInt325(456).build()) 63 .build(); 64 Proto2Message message3 = 65 newBuilder() 66 .setFieldMessage10(newBuilder().setFieldInt643(789).clearFieldInt325().build()) 67 .build(); 68 ByteArrayOutputStream output = new ByteArrayOutputStream(); 69 message1.writeTo(output); 70 message2.writeTo(output); 71 message3.writeTo(output); 72 byte[] data = output.toByteArray(); 73 74 Proto2Message merged = ExperimentalSerializationUtil.fromByteArray(data, Proto2Message.class); 75 assertEquals(789, merged.getFieldMessage10().getFieldInt643()); 76 assertEquals(456, merged.getFieldMessage10().getFieldInt325()); 77 } 78 79 @Test oneofFieldsShouldRoundtrip()80 public void oneofFieldsShouldRoundtrip() throws IOException { 81 roundtrip("Field 53", newBuilder().setFieldDouble53(100).build()); 82 roundtrip("Field 54", newBuilder().setFieldFloat54(100).build()); 83 roundtrip("Field 55", newBuilder().setFieldInt6455(100).build()); 84 roundtrip("Field 56", newBuilder().setFieldUint6456(100L).build()); 85 roundtrip("Field 57", newBuilder().setFieldInt3257(100).build()); 86 roundtrip("Field 58", newBuilder().setFieldFixed6458(100).build()); 87 roundtrip("Field 59", newBuilder().setFieldFixed3259(100).build()); 88 roundtrip("Field 60", newBuilder().setFieldBool60(true).build()); 89 roundtrip("Field 61", newBuilder().setFieldString61(data().getString()).build()); 90 roundtrip( 91 "Field 62", newBuilder().setFieldMessage62(newBuilder().setFieldDouble1(100)).build()); 92 roundtrip("Field 63", newBuilder().setFieldBytes63(data().getBytes()).build()); 93 roundtrip("Field 64", newBuilder().setFieldUint3264(100).build()); 94 roundtrip("Field 65", newBuilder().setFieldSfixed3265(100).build()); 95 roundtrip("Field 66", newBuilder().setFieldSfixed6466(100).build()); 96 roundtrip("Field 67", newBuilder().setFieldSint3267(100).build()); 97 roundtrip("Field 68", newBuilder().setFieldSint6468(100).build()); 98 roundtrip( 99 "Field 69", 100 newBuilder() 101 .setFieldGroup69( 102 Proto2Message.FieldGroup69.newBuilder().setFieldInt3270(data().getInt())) 103 .build()); 104 } 105 newBuilder()106 private Proto2Message.Builder newBuilder() { 107 return messageFactory().newMessage().toBuilder(); 108 } 109 110 @Test mapsShouldRoundtrip()111 public void mapsShouldRoundtrip() throws IOException { 112 roundtrip( 113 "Proto2MessageWithMaps", 114 new Proto2MessageFactory(2, 10, 2, 2).newMessageWithMaps(), 115 Protobuf.getInstance().schemaFor(Proto2MessageWithMaps.class)); 116 } 117 118 @Test unknownFieldsUnrecognized()119 public void unknownFieldsUnrecognized() throws Exception { 120 Proto2Message expectedMessage = messageFactory().newMessage(); 121 byte[] serializedBytes = expectedMessage.toByteArray(); 122 Proto2Empty empty = 123 ExperimentalSerializationUtil.fromByteArray(serializedBytes, Proto2Empty.class); 124 125 // Merge serialized bytes into an empty message, then reserialize and merge it to a new 126 // Proto2Message. Make sure the two messages equal. 127 byte[] roundtripBytes = ExperimentalSerializationUtil.toByteArray(empty); 128 assertEquals(serializedBytes.length, roundtripBytes.length); 129 Proto2Message roundtripMessage = 130 ExperimentalSerializationUtil.fromByteArray(roundtripBytes, Proto2Message.class); 131 assertEquals(expectedMessage, roundtripMessage); 132 } 133 134 @Test unknownEnum()135 public void unknownEnum() throws IOException { 136 // Use unknown fields to hold invalid enum values. 137 UnknownFieldSetLite unknowns = UnknownFieldSetLite.newInstance(); 138 final int outOfRange = 1000; 139 assertNull(TestEnum.forNumber(outOfRange)); 140 unknowns.storeField( 141 WireFormat.makeTag(Proto2Message.FIELD_ENUM_13_FIELD_NUMBER, WireFormat.WIRETYPE_VARINT), 142 (long) outOfRange); 143 unknowns.storeField( 144 WireFormat.makeTag( 145 Proto2Message.FIELD_ENUM_LIST_30_FIELD_NUMBER, WireFormat.WIRETYPE_VARINT), 146 (long) TestEnum.ONE_VALUE); 147 unknowns.storeField( 148 WireFormat.makeTag( 149 Proto2Message.FIELD_ENUM_LIST_30_FIELD_NUMBER, WireFormat.WIRETYPE_VARINT), 150 (long) outOfRange); 151 unknowns.storeField( 152 WireFormat.makeTag( 153 Proto2Message.FIELD_ENUM_LIST_30_FIELD_NUMBER, WireFormat.WIRETYPE_VARINT), 154 (long) TestEnum.TWO_VALUE); 155 156 { 157 // Construct a packed enum list. 158 int packedSize = 159 CodedOutputStream.computeUInt32SizeNoTag(TestEnum.ONE_VALUE) 160 + CodedOutputStream.computeUInt32SizeNoTag(outOfRange) 161 + CodedOutputStream.computeUInt32SizeNoTag(TestEnum.ONE_VALUE); 162 ByteString.CodedBuilder packedBuilder = ByteString.newCodedBuilder(packedSize); 163 CodedOutputStream packedOut = packedBuilder.getCodedOutput(); 164 packedOut.writeEnumNoTag(TestEnum.ONE_VALUE); 165 packedOut.writeEnumNoTag(outOfRange); 166 packedOut.writeEnumNoTag(TestEnum.TWO_VALUE); 167 unknowns.storeField( 168 WireFormat.makeTag( 169 Proto2Message.FIELD_ENUM_LIST_PACKED_44_FIELD_NUMBER, 170 WireFormat.WIRETYPE_LENGTH_DELIMITED), 171 packedBuilder.build()); 172 } 173 int size = unknowns.getSerializedSize(); 174 byte[] output = new byte[size]; 175 CodedOutputStream codedOutput = CodedOutputStream.newInstance(output); 176 unknowns.writeTo(codedOutput); 177 codedOutput.flush(); 178 179 Proto2Message parsed = ExperimentalSerializationUtil.fromByteArray(output, Proto2Message.class); 180 assertFalse("out-of-range singular enum should not be in message", parsed.hasFieldEnum13()); 181 { 182 List<Long> singularEnum = 183 parsed 184 .getUnknownFields() 185 .getField(Proto2Message.FIELD_ENUM_13_FIELD_NUMBER) 186 .getVarintList(); 187 assertEquals(1, singularEnum.size()); 188 assertEquals((Long) (long) outOfRange, singularEnum.get(0)); 189 } 190 { 191 List<Long> repeatedEnum = 192 parsed 193 .getUnknownFields() 194 .getField(Proto2Message.FIELD_ENUM_LIST_30_FIELD_NUMBER) 195 .getVarintList(); 196 assertEquals(1, repeatedEnum.size()); 197 assertEquals((Long) (long) outOfRange, repeatedEnum.get(0)); 198 } 199 { 200 List<Long> packedRepeatedEnum = 201 parsed 202 .getUnknownFields() 203 .getField(Proto2Message.FIELD_ENUM_LIST_PACKED_44_FIELD_NUMBER) 204 .getVarintList(); 205 assertEquals(1, packedRepeatedEnum.size()); 206 assertEquals((Long) (long) outOfRange, packedRepeatedEnum.get(0)); 207 } 208 assertEquals( 209 "out-of-range repeated enum should not be in message", 2, parsed.getFieldEnumList30Count()); 210 assertEquals(TestEnum.ONE, parsed.getFieldEnumList30(0)); 211 assertEquals(TestEnum.TWO, parsed.getFieldEnumList30(1)); 212 assertEquals( 213 "out-of-range packed repeated enum should not be in message", 214 2, 215 parsed.getFieldEnumListPacked44Count()); 216 assertEquals(TestEnum.ONE, parsed.getFieldEnumListPacked44(0)); 217 assertEquals(TestEnum.TWO, parsed.getFieldEnumListPacked44(1)); 218 } 219 220 @Override newMessagesMissingRequiredFields()221 protected List<Proto2Message> newMessagesMissingRequiredFields() { 222 return messageFactory().newMessagesMissingRequiredFields(); 223 } 224 } 225