1 // Protocol Buffers - Google's data interchange format 2 // Copyright 2008 Google Inc. All rights reserved. 3 // 4 // Use of this source code is governed by a BSD-style 5 // license that can be found in the LICENSE file or at 6 // https://developers.google.com/open-source/licenses/bsd 7 8 package com.google.protobuf; 9 10 import static com.google.common.truth.Truth.assertThat; 11 import static com.google.common.truth.Truth.assertWithMessage; 12 13 import com.google.protobuf.testing.Proto2Testing.Proto2Empty; 14 import com.google.protobuf.testing.Proto2Testing.Proto2Message; 15 import com.google.protobuf.testing.Proto2Testing.Proto2Message.TestEnum; 16 import com.google.protobuf.testing.Proto2Testing.Proto2MessageWithMaps; 17 import java.io.ByteArrayOutputStream; 18 import java.io.IOException; 19 import java.util.List; 20 import org.junit.Test; 21 22 /** Base class for tests using {@link Proto2Message}. */ 23 public abstract class AbstractProto2SchemaTest extends AbstractSchemaTest<Proto2Message> { 24 25 @Override messageFactory()26 protected Proto2MessageFactory messageFactory() { 27 return new Proto2MessageFactory(10, 20, 2, 2); 28 } 29 30 @Test mergeOptionalMessageFields()31 public void mergeOptionalMessageFields() throws Exception { 32 Proto2Message message1 = 33 newBuilder() 34 .setFieldMessage10(newBuilder().setFieldInt643(123).clearFieldInt325().build()) 35 .build(); 36 Proto2Message message2 = 37 newBuilder() 38 .setFieldMessage10(newBuilder().clearFieldInt643().setFieldInt325(456).build()) 39 .build(); 40 Proto2Message message3 = 41 newBuilder() 42 .setFieldMessage10(newBuilder().setFieldInt643(789).clearFieldInt325().build()) 43 .build(); 44 ByteArrayOutputStream output = new ByteArrayOutputStream(); 45 message1.writeTo(output); 46 message2.writeTo(output); 47 message3.writeTo(output); 48 byte[] data = output.toByteArray(); 49 50 Proto2Message merged = ExperimentalSerializationUtil.fromByteArray(data, Proto2Message.class); 51 assertThat(merged.getFieldMessage10().getFieldInt643()).isEqualTo(789); 52 assertThat(merged.getFieldMessage10().getFieldInt325()).isEqualTo(456); 53 } 54 55 @Test oneofFieldsShouldRoundtrip()56 public void oneofFieldsShouldRoundtrip() throws IOException { 57 roundtrip("Field 53", newBuilder().setFieldDouble53(100).build()); 58 roundtrip("Field 54", newBuilder().setFieldFloat54(100).build()); 59 roundtrip("Field 55", newBuilder().setFieldInt6455(100).build()); 60 roundtrip("Field 56", newBuilder().setFieldUint6456(100L).build()); 61 roundtrip("Field 57", newBuilder().setFieldInt3257(100).build()); 62 roundtrip("Field 58", newBuilder().setFieldFixed6458(100).build()); 63 roundtrip("Field 59", newBuilder().setFieldFixed3259(100).build()); 64 roundtrip("Field 60", newBuilder().setFieldBool60(true).build()); 65 roundtrip("Field 61", newBuilder().setFieldString61(data().getString()).build()); 66 roundtrip( 67 "Field 62", newBuilder().setFieldMessage62(newBuilder().setFieldDouble1(100)).build()); 68 roundtrip("Field 63", newBuilder().setFieldBytes63(data().getBytes()).build()); 69 roundtrip("Field 64", newBuilder().setFieldUint3264(100).build()); 70 roundtrip("Field 65", newBuilder().setFieldSfixed3265(100).build()); 71 roundtrip("Field 66", newBuilder().setFieldSfixed6466(100).build()); 72 roundtrip("Field 67", newBuilder().setFieldSint3267(100).build()); 73 roundtrip("Field 68", newBuilder().setFieldSint6468(100).build()); 74 roundtrip( 75 "Field 69", 76 newBuilder() 77 .setFieldGroup69( 78 Proto2Message.FieldGroup69.newBuilder().setFieldInt3270(data().getInt())) 79 .build()); 80 } 81 newBuilder()82 private Proto2Message.Builder newBuilder() { 83 return messageFactory().newMessage().toBuilder(); 84 } 85 86 @Test mapsShouldRoundtrip()87 public void mapsShouldRoundtrip() throws IOException { 88 roundtrip( 89 "Proto2MessageWithMaps", 90 new Proto2MessageFactory(2, 10, 2, 2).newMessageWithMaps(), 91 Protobuf.getInstance().schemaFor(Proto2MessageWithMaps.class)); 92 } 93 94 @Test unknownFieldsUnrecognized()95 public void unknownFieldsUnrecognized() throws Exception { 96 Proto2Message expectedMessage = messageFactory().newMessage(); 97 byte[] serializedBytes = expectedMessage.toByteArray(); 98 Proto2Empty empty = 99 ExperimentalSerializationUtil.fromByteArray(serializedBytes, Proto2Empty.class); 100 101 // Merge serialized bytes into an empty message, then reserialize and merge it to a new 102 // Proto2Message. Make sure the two messages equal. 103 byte[] roundtripBytes = ExperimentalSerializationUtil.toByteArray(empty); 104 assertThat(serializedBytes).hasLength(roundtripBytes.length); 105 Proto2Message roundtripMessage = 106 ExperimentalSerializationUtil.fromByteArray(roundtripBytes, Proto2Message.class); 107 assertThat(roundtripMessage).isEqualTo(expectedMessage); 108 } 109 110 @Test unknownEnum()111 public void unknownEnum() throws IOException { 112 // Use unknown fields to hold invalid enum values. 113 UnknownFieldSetLite unknowns = UnknownFieldSetLite.newInstance(); 114 final int outOfRange = 1000; 115 assertThat(TestEnum.forNumber(outOfRange)).isNull(); 116 unknowns.storeField( 117 WireFormat.makeTag(Proto2Message.FIELD_ENUM_13_FIELD_NUMBER, WireFormat.WIRETYPE_VARINT), 118 (long) outOfRange); 119 unknowns.storeField( 120 WireFormat.makeTag( 121 Proto2Message.FIELD_ENUM_LIST_30_FIELD_NUMBER, WireFormat.WIRETYPE_VARINT), 122 (long) TestEnum.ONE_VALUE); 123 unknowns.storeField( 124 WireFormat.makeTag( 125 Proto2Message.FIELD_ENUM_LIST_30_FIELD_NUMBER, WireFormat.WIRETYPE_VARINT), 126 (long) outOfRange); 127 unknowns.storeField( 128 WireFormat.makeTag( 129 Proto2Message.FIELD_ENUM_LIST_30_FIELD_NUMBER, WireFormat.WIRETYPE_VARINT), 130 (long) TestEnum.TWO_VALUE); 131 132 { 133 // Construct a packed enum list. 134 int packedSize = 135 CodedOutputStream.computeUInt32SizeNoTag(TestEnum.ONE_VALUE) 136 + CodedOutputStream.computeUInt32SizeNoTag(outOfRange) 137 + CodedOutputStream.computeUInt32SizeNoTag(TestEnum.ONE_VALUE); 138 ByteString.CodedBuilder packedBuilder = ByteString.newCodedBuilder(packedSize); 139 CodedOutputStream packedOut = packedBuilder.getCodedOutput(); 140 packedOut.writeEnumNoTag(TestEnum.ONE_VALUE); 141 packedOut.writeEnumNoTag(outOfRange); 142 packedOut.writeEnumNoTag(TestEnum.TWO_VALUE); 143 unknowns.storeField( 144 WireFormat.makeTag( 145 Proto2Message.FIELD_ENUM_LIST_PACKED_44_FIELD_NUMBER, 146 WireFormat.WIRETYPE_LENGTH_DELIMITED), 147 packedBuilder.build()); 148 } 149 int size = unknowns.getSerializedSize(); 150 byte[] output = new byte[size]; 151 CodedOutputStream codedOutput = CodedOutputStream.newInstance(output); 152 unknowns.writeTo(codedOutput); 153 codedOutput.flush(); 154 155 Proto2Message parsed = ExperimentalSerializationUtil.fromByteArray(output, Proto2Message.class); 156 assertWithMessage("out-of-range singular enum should not be in message") 157 .that(parsed.hasFieldEnum13()) 158 .isFalse(); 159 { 160 List<Long> singularEnum = 161 parsed 162 .getUnknownFields() 163 .getField(Proto2Message.FIELD_ENUM_13_FIELD_NUMBER) 164 .getVarintList(); 165 assertThat(singularEnum).hasSize(1); 166 assertThat((Long) (long) outOfRange).isEqualTo(singularEnum.get(0)); 167 } 168 { 169 List<Long> repeatedEnum = 170 parsed 171 .getUnknownFields() 172 .getField(Proto2Message.FIELD_ENUM_LIST_30_FIELD_NUMBER) 173 .getVarintList(); 174 assertThat(repeatedEnum).hasSize(1); 175 assertThat((Long) (long) outOfRange).isEqualTo(repeatedEnum.get(0)); 176 } 177 { 178 List<Long> packedRepeatedEnum = 179 parsed 180 .getUnknownFields() 181 .getField(Proto2Message.FIELD_ENUM_LIST_PACKED_44_FIELD_NUMBER) 182 .getVarintList(); 183 assertThat(packedRepeatedEnum).hasSize(1); 184 assertThat((Long) (long) outOfRange).isEqualTo(packedRepeatedEnum.get(0)); 185 } 186 assertWithMessage("out-of-range repeated enum should not be in message") 187 .that(parsed.getFieldEnumList30Count()) 188 .isEqualTo(2); 189 assertThat(parsed.getFieldEnumList30(0)).isEqualTo(TestEnum.ONE); 190 assertThat(parsed.getFieldEnumList30(1)).isEqualTo(TestEnum.TWO); 191 assertWithMessage("out-of-range packed repeated enum should not be in message") 192 .that(parsed.getFieldEnumListPacked44Count()) 193 .isEqualTo(2); 194 assertThat(parsed.getFieldEnumListPacked44(0)).isEqualTo(TestEnum.ONE); 195 assertThat(parsed.getFieldEnumListPacked44(1)).isEqualTo(TestEnum.TWO); 196 } 197 198 @Override newMessagesMissingRequiredFields()199 protected List<Proto2Message> newMessagesMissingRequiredFields() { 200 return messageFactory().newMessagesMissingRequiredFields(); 201 } 202 } 203