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.test;
32 import com.google.protobuf.*;
34 import com.google.protobuf.Descriptors.FieldDescriptor;
35 import protobuf_unittest.UnittestOptimizeFor.TestOptimizedForSize;
36 import protobuf_unittest.UnittestProto;
37 import protobuf_unittest.UnittestProto.ForeignMessage;
38 import protobuf_unittest.UnittestProto.TestAllExtensions;
39 import protobuf_unittest.UnittestProto.TestAllTypes;
40 import protobuf_unittest.UnittestProto.TestPackedTypes;
41 import protobuf_unittest.UnittestProto.TestRequired;
42 import protobuf_unittest.UnittestProto.TestRequiredForeign;
43 import protobuf_unittest.UnittestProto.TestUnpackedTypes;
45 import junit.framework.TestCase;
50 * Unit test for {@link AbstractMessage}.
52 * @author kenton@google.com Kenton Varda
54 public class AbstractMessageTest extends TestCase {
56 * Extends AbstractMessage and wraps some other message object. The methods
57 * of the Message interface which aren't explicitly implemented by
58 * AbstractMessage are forwarded to the wrapped object. This allows us to
59 * test that AbstractMessage's implementations work even if the wrapped
60 * object does not use them.
62 private static class AbstractMessageWrapper extends AbstractMessage {
63 private final Message wrappedMessage;
65 public AbstractMessageWrapper(Message wrappedMessage) {
66 this.wrappedMessage = wrappedMessage;
69 public Descriptors.Descriptor getDescriptorForType() {
70 return wrappedMessage.getDescriptorForType();
72 public AbstractMessageWrapper getDefaultInstanceForType() {
73 return new AbstractMessageWrapper(
74 wrappedMessage.getDefaultInstanceForType());
76 public Map<Descriptors.FieldDescriptor, Object> getAllFields() {
77 return wrappedMessage.getAllFields();
79 public boolean hasField(Descriptors.FieldDescriptor field) {
80 return wrappedMessage.hasField(field);
82 public Object getField(Descriptors.FieldDescriptor field) {
83 return wrappedMessage.getField(field);
85 public int getRepeatedFieldCount(Descriptors.FieldDescriptor field) {
86 return wrappedMessage.getRepeatedFieldCount(field);
88 public Object getRepeatedField(
89 Descriptors.FieldDescriptor field, int index) {
90 return wrappedMessage.getRepeatedField(field, index);
92 public UnknownFieldSet getUnknownFields() {
93 return wrappedMessage.getUnknownFields();
95 public Builder newBuilderForType() {
96 return new Builder(wrappedMessage.newBuilderForType());
98 public Builder toBuilder() {
99 return new Builder(wrappedMessage.toBuilder());
102 static class Builder extends AbstractMessage.Builder<Builder> {
103 private final Message.Builder wrappedBuilder;
105 public Builder(Message.Builder wrappedBuilder) {
106 this.wrappedBuilder = wrappedBuilder;
109 public AbstractMessageWrapper build() {
110 return new AbstractMessageWrapper(wrappedBuilder.build());
112 public AbstractMessageWrapper buildPartial() {
113 return new AbstractMessageWrapper(wrappedBuilder.buildPartial());
115 public Builder clone() {
116 return new Builder(wrappedBuilder.clone());
118 public boolean isInitialized() {
119 return clone().buildPartial().isInitialized();
121 public Descriptors.Descriptor getDescriptorForType() {
122 return wrappedBuilder.getDescriptorForType();
124 public AbstractMessageWrapper getDefaultInstanceForType() {
125 return new AbstractMessageWrapper(
126 wrappedBuilder.getDefaultInstanceForType());
128 public Map<Descriptors.FieldDescriptor, Object> getAllFields() {
129 return wrappedBuilder.getAllFields();
131 public Builder newBuilderForField(Descriptors.FieldDescriptor field) {
132 return new Builder(wrappedBuilder.newBuilderForField(field));
134 public boolean hasField(Descriptors.FieldDescriptor field) {
135 return wrappedBuilder.hasField(field);
137 public Object getField(Descriptors.FieldDescriptor field) {
138 return wrappedBuilder.getField(field);
140 public Builder setField(Descriptors.FieldDescriptor field, Object value) {
141 wrappedBuilder.setField(field, value);
144 public Builder clearField(Descriptors.FieldDescriptor field) {
145 wrappedBuilder.clearField(field);
148 public int getRepeatedFieldCount(Descriptors.FieldDescriptor field) {
149 return wrappedBuilder.getRepeatedFieldCount(field);
151 public Object getRepeatedField(
152 Descriptors.FieldDescriptor field, int index) {
153 return wrappedBuilder.getRepeatedField(field, index);
155 public Builder setRepeatedField(Descriptors.FieldDescriptor field,
156 int index, Object value) {
157 wrappedBuilder.setRepeatedField(field, index, value);
160 public Builder addRepeatedField(
161 Descriptors.FieldDescriptor field, Object value) {
162 wrappedBuilder.addRepeatedField(field, value);
165 public UnknownFieldSet getUnknownFields() {
166 return wrappedBuilder.getUnknownFields();
168 public Builder setUnknownFields(UnknownFieldSet unknownFields) {
169 wrappedBuilder.setUnknownFields(unknownFields);
173 public Message.Builder getFieldBuilder(FieldDescriptor field) {
174 return wrappedBuilder.getFieldBuilder(field);
177 public Parser<? extends Message> getParserForType() {
178 return wrappedMessage.getParserForType();
182 // =================================================================
184 TestUtil.ReflectionTester reflectionTester =
185 new TestUtil.ReflectionTester(TestAllTypes.getDescriptor(), null);
187 TestUtil.ReflectionTester extensionsReflectionTester =
188 new TestUtil.ReflectionTester(TestAllExtensions.getDescriptor(),
189 TestUtil.getExtensionRegistry());
191 public void testClear() throws Exception {
192 AbstractMessageWrapper message =
193 new AbstractMessageWrapper.Builder(
194 TestAllTypes.newBuilder(TestUtil.getAllSet()))
196 TestUtil.assertClear((TestAllTypes) message.wrappedMessage);
199 public void testCopy() throws Exception {
200 AbstractMessageWrapper message =
201 new AbstractMessageWrapper.Builder(TestAllTypes.newBuilder())
202 .mergeFrom(TestUtil.getAllSet()).build();
203 TestUtil.assertAllFieldsSet((TestAllTypes) message.wrappedMessage);
206 public void testSerializedSize() throws Exception {
207 TestAllTypes message = TestUtil.getAllSet();
208 Message abstractMessage = new AbstractMessageWrapper(TestUtil.getAllSet());
210 assertEquals(message.getSerializedSize(),
211 abstractMessage.getSerializedSize());
214 public void testSerialization() throws Exception {
215 Message abstractMessage = new AbstractMessageWrapper(TestUtil.getAllSet());
217 TestUtil.assertAllFieldsSet(
218 TestAllTypes.parseFrom(abstractMessage.toByteString()));
220 assertEquals(TestUtil.getAllSet().toByteString(),
221 abstractMessage.toByteString());
224 public void testParsing() throws Exception {
225 AbstractMessageWrapper.Builder builder =
226 new AbstractMessageWrapper.Builder(TestAllTypes.newBuilder());
227 AbstractMessageWrapper message =
228 builder.mergeFrom(TestUtil.getAllSet().toByteString()).build();
229 TestUtil.assertAllFieldsSet((TestAllTypes) message.wrappedMessage);
232 public void testParsingUninitialized() throws Exception {
233 TestRequiredForeign.Builder builder = TestRequiredForeign.newBuilder();
234 builder.getOptionalMessageBuilder().setDummy2(10);
235 ByteString bytes = builder.buildPartial().toByteString();
236 Message.Builder abstractMessageBuilder =
237 new AbstractMessageWrapper.Builder(TestRequiredForeign.newBuilder());
238 // mergeFrom() should not throw initialization error.
239 abstractMessageBuilder.mergeFrom(bytes).buildPartial();
241 abstractMessageBuilder.mergeFrom(bytes).build();
243 } catch (UninitializedMessageException ex) {
247 // test DynamicMessage directly.
248 Message.Builder dynamicMessageBuilder = DynamicMessage.newBuilder(
249 TestRequiredForeign.getDescriptor());
250 // mergeFrom() should not throw initialization error.
251 dynamicMessageBuilder.mergeFrom(bytes).buildPartial();
253 dynamicMessageBuilder.mergeFrom(bytes).build();
255 } catch (UninitializedMessageException ex) {
260 public void testPackedSerialization() throws Exception {
261 Message abstractMessage =
262 new AbstractMessageWrapper(TestUtil.getPackedSet());
264 TestUtil.assertPackedFieldsSet(
265 TestPackedTypes.parseFrom(abstractMessage.toByteString()));
267 assertEquals(TestUtil.getPackedSet().toByteString(),
268 abstractMessage.toByteString());
271 public void testPackedParsing() throws Exception {
272 AbstractMessageWrapper.Builder builder =
273 new AbstractMessageWrapper.Builder(TestPackedTypes.newBuilder());
274 AbstractMessageWrapper message =
275 builder.mergeFrom(TestUtil.getPackedSet().toByteString()).build();
276 TestUtil.assertPackedFieldsSet((TestPackedTypes) message.wrappedMessage);
279 public void testUnpackedSerialization() throws Exception {
280 Message abstractMessage =
281 new AbstractMessageWrapper(TestUtil.getUnpackedSet());
283 TestUtil.assertUnpackedFieldsSet(
284 TestUnpackedTypes.parseFrom(abstractMessage.toByteString()));
286 assertEquals(TestUtil.getUnpackedSet().toByteString(),
287 abstractMessage.toByteString());
290 public void testParsePackedToUnpacked() throws Exception {
291 AbstractMessageWrapper.Builder builder =
292 new AbstractMessageWrapper.Builder(TestUnpackedTypes.newBuilder());
293 AbstractMessageWrapper message =
294 builder.mergeFrom(TestUtil.getPackedSet().toByteString()).build();
295 TestUtil.assertUnpackedFieldsSet(
296 (TestUnpackedTypes) message.wrappedMessage);
299 public void testParseUnpackedToPacked() throws Exception {
300 AbstractMessageWrapper.Builder builder =
301 new AbstractMessageWrapper.Builder(TestPackedTypes.newBuilder());
302 AbstractMessageWrapper message =
303 builder.mergeFrom(TestUtil.getUnpackedSet().toByteString()).build();
304 TestUtil.assertPackedFieldsSet((TestPackedTypes) message.wrappedMessage);
307 public void testUnpackedParsing() throws Exception {
308 AbstractMessageWrapper.Builder builder =
309 new AbstractMessageWrapper.Builder(TestUnpackedTypes.newBuilder());
310 AbstractMessageWrapper message =
311 builder.mergeFrom(TestUtil.getUnpackedSet().toByteString()).build();
312 TestUtil.assertUnpackedFieldsSet(
313 (TestUnpackedTypes) message.wrappedMessage);
316 public void testOptimizedForSize() throws Exception {
317 // We're mostly only checking that this class was compiled successfully.
318 TestOptimizedForSize message =
319 TestOptimizedForSize.newBuilder().setI(1).build();
320 message = TestOptimizedForSize.parseFrom(message.toByteString());
321 assertEquals(2, message.getSerializedSize());
324 // -----------------------------------------------------------------
325 // Tests for isInitialized().
327 private static final TestRequired TEST_REQUIRED_UNINITIALIZED =
328 TestRequired.getDefaultInstance();
329 private static final TestRequired TEST_REQUIRED_INITIALIZED =
330 TestRequired.newBuilder().setA(1).setB(2).setC(3).build();
332 public void testIsInitialized() throws Exception {
333 TestRequired.Builder builder = TestRequired.newBuilder();
334 AbstractMessageWrapper.Builder abstractBuilder =
335 new AbstractMessageWrapper.Builder(builder);
337 assertFalse(abstractBuilder.isInitialized());
338 assertEquals("a, b, c", abstractBuilder.getInitializationErrorString());
340 assertFalse(abstractBuilder.isInitialized());
341 assertEquals("b, c", abstractBuilder.getInitializationErrorString());
343 assertFalse(abstractBuilder.isInitialized());
344 assertEquals("c", abstractBuilder.getInitializationErrorString());
346 assertTrue(abstractBuilder.isInitialized());
347 assertEquals("", abstractBuilder.getInitializationErrorString());
350 public void testForeignIsInitialized() throws Exception {
351 TestRequiredForeign.Builder builder = TestRequiredForeign.newBuilder();
352 AbstractMessageWrapper.Builder abstractBuilder =
353 new AbstractMessageWrapper.Builder(builder);
355 assertTrue(abstractBuilder.isInitialized());
356 assertEquals("", abstractBuilder.getInitializationErrorString());
358 builder.setOptionalMessage(TEST_REQUIRED_UNINITIALIZED);
359 assertFalse(abstractBuilder.isInitialized());
361 "optional_message.a, optional_message.b, optional_message.c",
362 abstractBuilder.getInitializationErrorString());
364 builder.setOptionalMessage(TEST_REQUIRED_INITIALIZED);
365 assertTrue(abstractBuilder.isInitialized());
366 assertEquals("", abstractBuilder.getInitializationErrorString());
368 builder.addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED);
369 assertFalse(abstractBuilder.isInitialized());
371 "repeated_message[0].a, repeated_message[0].b, repeated_message[0].c",
372 abstractBuilder.getInitializationErrorString());
374 builder.setRepeatedMessage(0, TEST_REQUIRED_INITIALIZED);
375 assertTrue(abstractBuilder.isInitialized());
376 assertEquals("", abstractBuilder.getInitializationErrorString());
379 // -----------------------------------------------------------------
380 // Tests for mergeFrom
382 static final TestAllTypes MERGE_SOURCE =
383 TestAllTypes.newBuilder()
385 .setOptionalString("foo")
386 .setOptionalForeignMessage(ForeignMessage.getDefaultInstance())
387 .addRepeatedString("bar")
390 static final TestAllTypes MERGE_DEST =
391 TestAllTypes.newBuilder()
393 .setOptionalString("baz")
394 .setOptionalForeignMessage(ForeignMessage.newBuilder().setC(3).build())
395 .addRepeatedString("qux")
398 static final String MERGE_RESULT_TEXT =
399 "optional_int32: 1\n" +
400 "optional_int64: 2\n" +
401 "optional_string: \"foo\"\n" +
402 "optional_foreign_message {\n" +
405 "repeated_string: \"qux\"\n" +
406 "repeated_string: \"bar\"\n";
408 public void testMergeFrom() throws Exception {
409 AbstractMessageWrapper result =
410 new AbstractMessageWrapper.Builder(
411 TestAllTypes.newBuilder(MERGE_DEST))
412 .mergeFrom(MERGE_SOURCE).build();
414 assertEquals(MERGE_RESULT_TEXT, result.toString());
417 // -----------------------------------------------------------------
418 // Tests for equals and hashCode
420 public void testEqualsAndHashCode() throws Exception {
421 TestAllTypes a = TestUtil.getAllSet();
422 TestAllTypes b = TestAllTypes.newBuilder().build();
423 TestAllTypes c = TestAllTypes.newBuilder(b).addRepeatedString("x").build();
424 TestAllTypes d = TestAllTypes.newBuilder(c).addRepeatedString("y").build();
425 TestAllExtensions e = TestUtil.getAllExtensionsSet();
426 TestAllExtensions f = TestAllExtensions.newBuilder(e)
427 .addExtension(UnittestProto.repeatedInt32Extension, 999).build();
429 checkEqualsIsConsistent(a);
430 checkEqualsIsConsistent(b);
431 checkEqualsIsConsistent(c);
432 checkEqualsIsConsistent(d);
433 checkEqualsIsConsistent(e);
434 checkEqualsIsConsistent(f);
456 // Deserializing into the TestEmptyMessage such that every field
457 // is an {@link UnknownFieldSet.Field}.
458 UnittestProto.TestEmptyMessage eUnknownFields =
459 UnittestProto.TestEmptyMessage.parseFrom(e.toByteArray());
460 UnittestProto.TestEmptyMessage fUnknownFields =
461 UnittestProto.TestEmptyMessage.parseFrom(f.toByteArray());
462 checkNotEqual(eUnknownFields, fUnknownFields);
463 checkEqualsIsConsistent(eUnknownFields);
464 checkEqualsIsConsistent(fUnknownFields);
466 // Subsequent reconstitutions should be identical
467 UnittestProto.TestEmptyMessage eUnknownFields2 =
468 UnittestProto.TestEmptyMessage.parseFrom(e.toByteArray());
469 checkEqualsIsConsistent(eUnknownFields, eUnknownFields2);
474 * Asserts that the given proto has symmetric equals and hashCode methods.
476 private void checkEqualsIsConsistent(Message message) {
477 // Object should be equal to itself.
478 assertEquals(message, message);
480 // Object should be equal to a dynamic copy of itself.
481 DynamicMessage dynamic = DynamicMessage.newBuilder(message).build();
482 checkEqualsIsConsistent(message, dynamic);
486 * Asserts that the given protos are equal and have the same hash code.
488 private void checkEqualsIsConsistent(Message message1, Message message2) {
489 assertEquals(message1, message2);
490 assertEquals(message2, message1);
491 assertEquals(message2.hashCode(), message1.hashCode());
495 * Asserts that the given protos are not equal and have different hash codes.
497 * @warning It's valid for non-equal objects to have the same hash code, so
498 * this test is stricter than it needs to be. However, this should happen
501 private void checkNotEqual(Message m1, Message m2) {
502 String equalsError = String.format("%s should not be equal to %s", m1, m2);
503 assertFalse(equalsError, m1.equals(m2));
504 assertFalse(equalsError, m2.equals(m1));
507 String.format("%s should have a different hash code from %s", m1, m2),
508 m1.hashCode() == m2.hashCode());