• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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