1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 // http://code.google.com/p/protobuf/
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
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
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.
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.
31 package com.google.protobuf;
33 import com.google.protobuf.Descriptors.FieldDescriptor;
34 import protobuf_unittest.UnittestOptimizeFor.TestOptimizedForSize;
35 import protobuf_unittest.UnittestProto;
36 import protobuf_unittest.UnittestProto.ForeignMessage;
37 import protobuf_unittest.UnittestProto.TestAllExtensions;
38 import protobuf_unittest.UnittestProto.TestAllTypes;
39 import protobuf_unittest.UnittestProto.TestPackedTypes;
40 import protobuf_unittest.UnittestProto.TestRequired;
41 import protobuf_unittest.UnittestProto.TestRequiredForeign;
42 import protobuf_unittest.UnittestProto.TestUnpackedTypes;
44 import junit.framework.TestCase;
49 * Unit test for {@link AbstractMessage}.
51 * @author kenton@google.com Kenton Varda
53 public class AbstractMessageTest extends TestCase {
55 * Extends AbstractMessage and wraps some other message object. The methods
56 * of the Message interface which aren't explicitly implemented by
57 * AbstractMessage are forwarded to the wrapped object. This allows us to
58 * test that AbstractMessage's implementations work even if the wrapped
59 * object does not use them.
61 private static class AbstractMessageWrapper extends AbstractMessage {
62 private final Message wrappedMessage;
64 public AbstractMessageWrapper(Message wrappedMessage) {
65 this.wrappedMessage = wrappedMessage;
68 public Descriptors.Descriptor getDescriptorForType() {
69 return wrappedMessage.getDescriptorForType();
71 public AbstractMessageWrapper getDefaultInstanceForType() {
72 return new AbstractMessageWrapper(
73 wrappedMessage.getDefaultInstanceForType());
75 public Map<Descriptors.FieldDescriptor, Object> getAllFields() {
76 return wrappedMessage.getAllFields();
78 public boolean hasField(Descriptors.FieldDescriptor field) {
79 return wrappedMessage.hasField(field);
81 public Object getField(Descriptors.FieldDescriptor field) {
82 return wrappedMessage.getField(field);
84 public int getRepeatedFieldCount(Descriptors.FieldDescriptor field) {
85 return wrappedMessage.getRepeatedFieldCount(field);
87 public Object getRepeatedField(
88 Descriptors.FieldDescriptor field, int index) {
89 return wrappedMessage.getRepeatedField(field, index);
91 public UnknownFieldSet getUnknownFields() {
92 return wrappedMessage.getUnknownFields();
94 public Builder newBuilderForType() {
95 return new Builder(wrappedMessage.newBuilderForType());
97 public Builder toBuilder() {
98 return new Builder(wrappedMessage.toBuilder());
101 static class Builder extends AbstractMessage.Builder<Builder> {
102 private final Message.Builder wrappedBuilder;
104 public Builder(Message.Builder wrappedBuilder) {
105 this.wrappedBuilder = wrappedBuilder;
108 public AbstractMessageWrapper build() {
109 return new AbstractMessageWrapper(wrappedBuilder.build());
111 public AbstractMessageWrapper buildPartial() {
112 return new AbstractMessageWrapper(wrappedBuilder.buildPartial());
114 public Builder clone() {
115 return new Builder(wrappedBuilder.clone());
117 public boolean isInitialized() {
118 return clone().buildPartial().isInitialized();
120 public Descriptors.Descriptor getDescriptorForType() {
121 return wrappedBuilder.getDescriptorForType();
123 public AbstractMessageWrapper getDefaultInstanceForType() {
124 return new AbstractMessageWrapper(
125 wrappedBuilder.getDefaultInstanceForType());
127 public Map<Descriptors.FieldDescriptor, Object> getAllFields() {
128 return wrappedBuilder.getAllFields();
130 public Builder newBuilderForField(Descriptors.FieldDescriptor field) {
131 return new Builder(wrappedBuilder.newBuilderForField(field));
133 public boolean hasField(Descriptors.FieldDescriptor field) {
134 return wrappedBuilder.hasField(field);
136 public Object getField(Descriptors.FieldDescriptor field) {
137 return wrappedBuilder.getField(field);
139 public Builder setField(Descriptors.FieldDescriptor field, Object value) {
140 wrappedBuilder.setField(field, value);
143 public Builder clearField(Descriptors.FieldDescriptor field) {
144 wrappedBuilder.clearField(field);
147 public int getRepeatedFieldCount(Descriptors.FieldDescriptor field) {
148 return wrappedBuilder.getRepeatedFieldCount(field);
150 public Object getRepeatedField(
151 Descriptors.FieldDescriptor field, int index) {
152 return wrappedBuilder.getRepeatedField(field, index);
154 public Builder setRepeatedField(Descriptors.FieldDescriptor field,
155 int index, Object value) {
156 wrappedBuilder.setRepeatedField(field, index, value);
159 public Builder addRepeatedField(
160 Descriptors.FieldDescriptor field, Object value) {
161 wrappedBuilder.addRepeatedField(field, value);
164 public UnknownFieldSet getUnknownFields() {
165 return wrappedBuilder.getUnknownFields();
167 public Builder setUnknownFields(UnknownFieldSet unknownFields) {
168 wrappedBuilder.setUnknownFields(unknownFields);
172 public Message.Builder getFieldBuilder(FieldDescriptor field) {
173 return wrappedBuilder.getFieldBuilder(field);
176 public Parser<? extends Message> getParserForType() {
177 return wrappedMessage.getParserForType();
181 // =================================================================
183 TestUtil.ReflectionTester reflectionTester =
184 new TestUtil.ReflectionTester(TestAllTypes.getDescriptor(), null);
186 TestUtil.ReflectionTester extensionsReflectionTester =
187 new TestUtil.ReflectionTester(TestAllExtensions.getDescriptor(),
188 TestUtil.getExtensionRegistry());
190 public void testClear() throws Exception {
191 AbstractMessageWrapper message =
192 new AbstractMessageWrapper.Builder(
193 TestAllTypes.newBuilder(TestUtil.getAllSet()))
195 TestUtil.assertClear((TestAllTypes) message.wrappedMessage);
198 public void testCopy() throws Exception {
199 AbstractMessageWrapper message =
200 new AbstractMessageWrapper.Builder(TestAllTypes.newBuilder())
201 .mergeFrom(TestUtil.getAllSet()).build();
202 TestUtil.assertAllFieldsSet((TestAllTypes) message.wrappedMessage);
205 public void testSerializedSize() throws Exception {
206 TestAllTypes message = TestUtil.getAllSet();
207 Message abstractMessage = new AbstractMessageWrapper(TestUtil.getAllSet());
209 assertEquals(message.getSerializedSize(),
210 abstractMessage.getSerializedSize());
213 public void testSerialization() throws Exception {
214 Message abstractMessage = new AbstractMessageWrapper(TestUtil.getAllSet());
216 TestUtil.assertAllFieldsSet(
217 TestAllTypes.parseFrom(abstractMessage.toByteString()));
219 assertEquals(TestUtil.getAllSet().toByteString(),
220 abstractMessage.toByteString());
223 public void testParsing() throws Exception {
224 AbstractMessageWrapper.Builder builder =
225 new AbstractMessageWrapper.Builder(TestAllTypes.newBuilder());
226 AbstractMessageWrapper message =
227 builder.mergeFrom(TestUtil.getAllSet().toByteString()).build();
228 TestUtil.assertAllFieldsSet((TestAllTypes) message.wrappedMessage);
231 public void testParsingUninitialized() throws Exception {
232 TestRequiredForeign.Builder builder = TestRequiredForeign.newBuilder();
233 builder.getOptionalMessageBuilder().setDummy2(10);
234 ByteString bytes = builder.buildPartial().toByteString();
235 Message.Builder abstractMessageBuilder =
236 new AbstractMessageWrapper.Builder(TestRequiredForeign.newBuilder());
237 // mergeFrom() should not throw initialization error.
238 abstractMessageBuilder.mergeFrom(bytes).buildPartial();
240 abstractMessageBuilder.mergeFrom(bytes).build();
242 } catch (UninitializedMessageException ex) {
246 // test DynamicMessage directly.
247 Message.Builder dynamicMessageBuilder = DynamicMessage.newBuilder(
248 TestRequiredForeign.getDescriptor());
249 // mergeFrom() should not throw initialization error.
250 dynamicMessageBuilder.mergeFrom(bytes).buildPartial();
252 dynamicMessageBuilder.mergeFrom(bytes).build();
254 } catch (UninitializedMessageException ex) {
259 public void testPackedSerialization() throws Exception {
260 Message abstractMessage =
261 new AbstractMessageWrapper(TestUtil.getPackedSet());
263 TestUtil.assertPackedFieldsSet(
264 TestPackedTypes.parseFrom(abstractMessage.toByteString()));
266 assertEquals(TestUtil.getPackedSet().toByteString(),
267 abstractMessage.toByteString());
270 public void testPackedParsing() throws Exception {
271 AbstractMessageWrapper.Builder builder =
272 new AbstractMessageWrapper.Builder(TestPackedTypes.newBuilder());
273 AbstractMessageWrapper message =
274 builder.mergeFrom(TestUtil.getPackedSet().toByteString()).build();
275 TestUtil.assertPackedFieldsSet((TestPackedTypes) message.wrappedMessage);
278 public void testUnpackedSerialization() throws Exception {
279 Message abstractMessage =
280 new AbstractMessageWrapper(TestUtil.getUnpackedSet());
282 TestUtil.assertUnpackedFieldsSet(
283 TestUnpackedTypes.parseFrom(abstractMessage.toByteString()));
285 assertEquals(TestUtil.getUnpackedSet().toByteString(),
286 abstractMessage.toByteString());
289 public void testParsePackedToUnpacked() throws Exception {
290 AbstractMessageWrapper.Builder builder =
291 new AbstractMessageWrapper.Builder(TestUnpackedTypes.newBuilder());
292 AbstractMessageWrapper message =
293 builder.mergeFrom(TestUtil.getPackedSet().toByteString()).build();
294 TestUtil.assertUnpackedFieldsSet(
295 (TestUnpackedTypes) message.wrappedMessage);
298 public void testParseUnpackedToPacked() throws Exception {
299 AbstractMessageWrapper.Builder builder =
300 new AbstractMessageWrapper.Builder(TestPackedTypes.newBuilder());
301 AbstractMessageWrapper message =
302 builder.mergeFrom(TestUtil.getUnpackedSet().toByteString()).build();
303 TestUtil.assertPackedFieldsSet((TestPackedTypes) message.wrappedMessage);
306 public void testUnpackedParsing() throws Exception {
307 AbstractMessageWrapper.Builder builder =
308 new AbstractMessageWrapper.Builder(TestUnpackedTypes.newBuilder());
309 AbstractMessageWrapper message =
310 builder.mergeFrom(TestUtil.getUnpackedSet().toByteString()).build();
311 TestUtil.assertUnpackedFieldsSet(
312 (TestUnpackedTypes) message.wrappedMessage);
315 public void testOptimizedForSize() throws Exception {
316 // We're mostly only checking that this class was compiled successfully.
317 TestOptimizedForSize message =
318 TestOptimizedForSize.newBuilder().setI(1).build();
319 message = TestOptimizedForSize.parseFrom(message.toByteString());
320 assertEquals(2, message.getSerializedSize());
323 // -----------------------------------------------------------------
324 // Tests for isInitialized().
326 private static final TestRequired TEST_REQUIRED_UNINITIALIZED =
327 TestRequired.getDefaultInstance();
328 private static final TestRequired TEST_REQUIRED_INITIALIZED =
329 TestRequired.newBuilder().setA(1).setB(2).setC(3).build();
331 public void testIsInitialized() throws Exception {
332 TestRequired.Builder builder = TestRequired.newBuilder();
333 AbstractMessageWrapper.Builder abstractBuilder =
334 new AbstractMessageWrapper.Builder(builder);
336 assertFalse(abstractBuilder.isInitialized());
337 assertEquals("a, b, c", abstractBuilder.getInitializationErrorString());
339 assertFalse(abstractBuilder.isInitialized());
340 assertEquals("b, c", abstractBuilder.getInitializationErrorString());
342 assertFalse(abstractBuilder.isInitialized());
343 assertEquals("c", abstractBuilder.getInitializationErrorString());
345 assertTrue(abstractBuilder.isInitialized());
346 assertEquals("", abstractBuilder.getInitializationErrorString());
349 public void testForeignIsInitialized() throws Exception {
350 TestRequiredForeign.Builder builder = TestRequiredForeign.newBuilder();
351 AbstractMessageWrapper.Builder abstractBuilder =
352 new AbstractMessageWrapper.Builder(builder);
354 assertTrue(abstractBuilder.isInitialized());
355 assertEquals("", abstractBuilder.getInitializationErrorString());
357 builder.setOptionalMessage(TEST_REQUIRED_UNINITIALIZED);
358 assertFalse(abstractBuilder.isInitialized());
360 "optional_message.a, optional_message.b, optional_message.c",
361 abstractBuilder.getInitializationErrorString());
363 builder.setOptionalMessage(TEST_REQUIRED_INITIALIZED);
364 assertTrue(abstractBuilder.isInitialized());
365 assertEquals("", abstractBuilder.getInitializationErrorString());
367 builder.addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED);
368 assertFalse(abstractBuilder.isInitialized());
370 "repeated_message[0].a, repeated_message[0].b, repeated_message[0].c",
371 abstractBuilder.getInitializationErrorString());
373 builder.setRepeatedMessage(0, TEST_REQUIRED_INITIALIZED);
374 assertTrue(abstractBuilder.isInitialized());
375 assertEquals("", abstractBuilder.getInitializationErrorString());
378 // -----------------------------------------------------------------
379 // Tests for mergeFrom
381 static final TestAllTypes MERGE_SOURCE =
382 TestAllTypes.newBuilder()
384 .setOptionalString("foo")
385 .setOptionalForeignMessage(ForeignMessage.getDefaultInstance())
386 .addRepeatedString("bar")
389 static final TestAllTypes MERGE_DEST =
390 TestAllTypes.newBuilder()
392 .setOptionalString("baz")
393 .setOptionalForeignMessage(ForeignMessage.newBuilder().setC(3).build())
394 .addRepeatedString("qux")
397 static final String MERGE_RESULT_TEXT =
398 "optional_int32: 1\n" +
399 "optional_int64: 2\n" +
400 "optional_string: \"foo\"\n" +
401 "optional_foreign_message {\n" +
404 "repeated_string: \"qux\"\n" +
405 "repeated_string: \"bar\"\n";
407 public void testMergeFrom() throws Exception {
408 AbstractMessageWrapper result =
409 new AbstractMessageWrapper.Builder(
410 TestAllTypes.newBuilder(MERGE_DEST))
411 .mergeFrom(MERGE_SOURCE).build();
413 assertEquals(MERGE_RESULT_TEXT, result.toString());
416 // -----------------------------------------------------------------
417 // Tests for equals and hashCode
419 public void testEqualsAndHashCode() throws Exception {
420 TestAllTypes a = TestUtil.getAllSet();
421 TestAllTypes b = TestAllTypes.newBuilder().build();
422 TestAllTypes c = TestAllTypes.newBuilder(b).addRepeatedString("x").build();
423 TestAllTypes d = TestAllTypes.newBuilder(c).addRepeatedString("y").build();
424 TestAllExtensions e = TestUtil.getAllExtensionsSet();
425 TestAllExtensions f = TestAllExtensions.newBuilder(e)
426 .addExtension(UnittestProto.repeatedInt32Extension, 999).build();
428 checkEqualsIsConsistent(a);
429 checkEqualsIsConsistent(b);
430 checkEqualsIsConsistent(c);
431 checkEqualsIsConsistent(d);
432 checkEqualsIsConsistent(e);
433 checkEqualsIsConsistent(f);
455 // Deserializing into the TestEmptyMessage such that every field
456 // is an {@link UnknownFieldSet.Field}.
457 UnittestProto.TestEmptyMessage eUnknownFields =
458 UnittestProto.TestEmptyMessage.parseFrom(e.toByteArray());
459 UnittestProto.TestEmptyMessage fUnknownFields =
460 UnittestProto.TestEmptyMessage.parseFrom(f.toByteArray());
461 checkNotEqual(eUnknownFields, fUnknownFields);
462 checkEqualsIsConsistent(eUnknownFields);
463 checkEqualsIsConsistent(fUnknownFields);
465 // Subsequent reconstitutions should be identical
466 UnittestProto.TestEmptyMessage eUnknownFields2 =
467 UnittestProto.TestEmptyMessage.parseFrom(e.toByteArray());
468 checkEqualsIsConsistent(eUnknownFields, eUnknownFields2);
473 * Asserts that the given proto has symmetric equals and hashCode methods.
475 private void checkEqualsIsConsistent(Message message) {
476 // Object should be equal to itself.
477 assertEquals(message, message);
479 // Object should be equal to a dynamic copy of itself.
480 DynamicMessage dynamic = DynamicMessage.newBuilder(message).build();
481 checkEqualsIsConsistent(message, dynamic);
485 * Asserts that the given protos are equal and have the same hash code.
487 private void checkEqualsIsConsistent(Message message1, Message message2) {
488 assertEquals(message1, message2);
489 assertEquals(message2, message1);
490 assertEquals(message2.hashCode(), message1.hashCode());
494 * Asserts that the given protos are not equal and have different hash codes.
496 * @warning It's valid for non-equal objects to have the same hash code, so
497 * this test is stricter than it needs to be. However, this should happen
500 private void checkNotEqual(Message m1, Message m2) {
501 String equalsError = String.format("%s should not be equal to %s", m1, m2);
502 assertFalse(equalsError, m1.equals(m2));
503 assertFalse(equalsError, m2.equals(m1));
506 String.format("%s should have a different hash code from %s", m1, m2),
507 m1.hashCode() == m2.hashCode());