6789550c49c247cb14258b5d82b98a633f3598c3
[tools/dynpart-tools.git] /
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc.  All rights reserved.
3 // http://code.google.com/p/protobuf/
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.test;
32 import com.google.protobuf.*;
33
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;
44
45 import junit.framework.TestCase;
46
47 import java.util.Map;
48
49 /**
50  * Unit test for {@link AbstractMessage}.
51  *
52  * @author kenton@google.com Kenton Varda
53  */
54 public class AbstractMessageTest extends TestCase {
55   /**
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.
61    */
62   private static class AbstractMessageWrapper extends AbstractMessage {
63     private final Message wrappedMessage;
64
65     public AbstractMessageWrapper(Message wrappedMessage) {
66       this.wrappedMessage = wrappedMessage;
67     }
68
69     public Descriptors.Descriptor getDescriptorForType() {
70       return wrappedMessage.getDescriptorForType();
71     }
72     public AbstractMessageWrapper getDefaultInstanceForType() {
73       return new AbstractMessageWrapper(
74         wrappedMessage.getDefaultInstanceForType());
75     }
76     public Map<Descriptors.FieldDescriptor, Object> getAllFields() {
77       return wrappedMessage.getAllFields();
78     }
79     public boolean hasField(Descriptors.FieldDescriptor field) {
80       return wrappedMessage.hasField(field);
81     }
82     public Object getField(Descriptors.FieldDescriptor field) {
83       return wrappedMessage.getField(field);
84     }
85     public int getRepeatedFieldCount(Descriptors.FieldDescriptor field) {
86       return wrappedMessage.getRepeatedFieldCount(field);
87     }
88     public Object getRepeatedField(
89         Descriptors.FieldDescriptor field, int index) {
90       return wrappedMessage.getRepeatedField(field, index);
91     }
92     public UnknownFieldSet getUnknownFields() {
93       return wrappedMessage.getUnknownFields();
94     }
95     public Builder newBuilderForType() {
96       return new Builder(wrappedMessage.newBuilderForType());
97     }
98     public Builder toBuilder() {
99       return new Builder(wrappedMessage.toBuilder());
100     }
101
102     static class Builder extends AbstractMessage.Builder<Builder> {
103       private final Message.Builder wrappedBuilder;
104
105       public Builder(Message.Builder wrappedBuilder) {
106         this.wrappedBuilder = wrappedBuilder;
107       }
108
109       public AbstractMessageWrapper build() {
110         return new AbstractMessageWrapper(wrappedBuilder.build());
111       }
112       public AbstractMessageWrapper buildPartial() {
113         return new AbstractMessageWrapper(wrappedBuilder.buildPartial());
114       }
115       public Builder clone() {
116         return new Builder(wrappedBuilder.clone());
117       }
118       public boolean isInitialized() {
119         return clone().buildPartial().isInitialized();
120       }
121       public Descriptors.Descriptor getDescriptorForType() {
122         return wrappedBuilder.getDescriptorForType();
123       }
124       public AbstractMessageWrapper getDefaultInstanceForType() {
125         return new AbstractMessageWrapper(
126           wrappedBuilder.getDefaultInstanceForType());
127       }
128       public Map<Descriptors.FieldDescriptor, Object> getAllFields() {
129         return wrappedBuilder.getAllFields();
130       }
131       public Builder newBuilderForField(Descriptors.FieldDescriptor field) {
132         return new Builder(wrappedBuilder.newBuilderForField(field));
133       }
134       public boolean hasField(Descriptors.FieldDescriptor field) {
135         return wrappedBuilder.hasField(field);
136       }
137       public Object getField(Descriptors.FieldDescriptor field) {
138         return wrappedBuilder.getField(field);
139       }
140       public Builder setField(Descriptors.FieldDescriptor field, Object value) {
141         wrappedBuilder.setField(field, value);
142         return this;
143       }
144       public Builder clearField(Descriptors.FieldDescriptor field) {
145         wrappedBuilder.clearField(field);
146         return this;
147       }
148       public int getRepeatedFieldCount(Descriptors.FieldDescriptor field) {
149         return wrappedBuilder.getRepeatedFieldCount(field);
150       }
151       public Object getRepeatedField(
152           Descriptors.FieldDescriptor field, int index) {
153         return wrappedBuilder.getRepeatedField(field, index);
154       }
155       public Builder setRepeatedField(Descriptors.FieldDescriptor field,
156                                       int index, Object value) {
157         wrappedBuilder.setRepeatedField(field, index, value);
158         return this;
159       }
160       public Builder addRepeatedField(
161           Descriptors.FieldDescriptor field, Object value) {
162         wrappedBuilder.addRepeatedField(field, value);
163         return this;
164       }
165       public UnknownFieldSet getUnknownFields() {
166         return wrappedBuilder.getUnknownFields();
167       }
168       public Builder setUnknownFields(UnknownFieldSet unknownFields) {
169         wrappedBuilder.setUnknownFields(unknownFields);
170         return this;
171       }
172       @Override
173       public Message.Builder getFieldBuilder(FieldDescriptor field) {
174         return wrappedBuilder.getFieldBuilder(field);
175       }
176     }
177     public Parser<? extends Message> getParserForType() {
178       return wrappedMessage.getParserForType();
179     }
180   }
181
182   // =================================================================
183
184   TestUtil.ReflectionTester reflectionTester =
185     new TestUtil.ReflectionTester(TestAllTypes.getDescriptor(), null);
186
187   TestUtil.ReflectionTester extensionsReflectionTester =
188     new TestUtil.ReflectionTester(TestAllExtensions.getDescriptor(),
189                                   TestUtil.getExtensionRegistry());
190
191   public void testClear() throws Exception {
192     AbstractMessageWrapper message =
193       new AbstractMessageWrapper.Builder(
194           TestAllTypes.newBuilder(TestUtil.getAllSet()))
195         .clear().build();
196     TestUtil.assertClear((TestAllTypes) message.wrappedMessage);
197   }
198
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);
204   }
205
206   public void testSerializedSize() throws Exception {
207     TestAllTypes message = TestUtil.getAllSet();
208     Message abstractMessage = new AbstractMessageWrapper(TestUtil.getAllSet());
209
210     assertEquals(message.getSerializedSize(),
211                  abstractMessage.getSerializedSize());
212   }
213
214   public void testSerialization() throws Exception {
215     Message abstractMessage = new AbstractMessageWrapper(TestUtil.getAllSet());
216
217     TestUtil.assertAllFieldsSet(
218       TestAllTypes.parseFrom(abstractMessage.toByteString()));
219
220     assertEquals(TestUtil.getAllSet().toByteString(),
221                  abstractMessage.toByteString());
222   }
223
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);
230   }
231
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();
240     try {
241       abstractMessageBuilder.mergeFrom(bytes).build();
242       fail();
243     } catch (UninitializedMessageException ex) {
244       // pass
245     }
246
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();
252     try {
253       dynamicMessageBuilder.mergeFrom(bytes).build();
254       fail();
255     } catch (UninitializedMessageException ex) {
256       // pass
257     }
258   }
259
260   public void testPackedSerialization() throws Exception {
261     Message abstractMessage =
262         new AbstractMessageWrapper(TestUtil.getPackedSet());
263
264     TestUtil.assertPackedFieldsSet(
265       TestPackedTypes.parseFrom(abstractMessage.toByteString()));
266
267     assertEquals(TestUtil.getPackedSet().toByteString(),
268                  abstractMessage.toByteString());
269   }
270
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);
277   }
278
279   public void testUnpackedSerialization() throws Exception {
280     Message abstractMessage =
281       new AbstractMessageWrapper(TestUtil.getUnpackedSet());
282
283     TestUtil.assertUnpackedFieldsSet(
284       TestUnpackedTypes.parseFrom(abstractMessage.toByteString()));
285
286     assertEquals(TestUtil.getUnpackedSet().toByteString(),
287                  abstractMessage.toByteString());
288   }
289
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);
297   }
298
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);
305   }
306
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);
314   }
315
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());
322   }
323
324   // -----------------------------------------------------------------
325   // Tests for isInitialized().
326
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();
331
332   public void testIsInitialized() throws Exception {
333     TestRequired.Builder builder = TestRequired.newBuilder();
334     AbstractMessageWrapper.Builder abstractBuilder =
335       new AbstractMessageWrapper.Builder(builder);
336
337     assertFalse(abstractBuilder.isInitialized());
338     assertEquals("a, b, c", abstractBuilder.getInitializationErrorString());
339     builder.setA(1);
340     assertFalse(abstractBuilder.isInitialized());
341     assertEquals("b, c", abstractBuilder.getInitializationErrorString());
342     builder.setB(1);
343     assertFalse(abstractBuilder.isInitialized());
344     assertEquals("c", abstractBuilder.getInitializationErrorString());
345     builder.setC(1);
346     assertTrue(abstractBuilder.isInitialized());
347     assertEquals("", abstractBuilder.getInitializationErrorString());
348   }
349
350   public void testForeignIsInitialized() throws Exception {
351     TestRequiredForeign.Builder builder = TestRequiredForeign.newBuilder();
352     AbstractMessageWrapper.Builder abstractBuilder =
353       new AbstractMessageWrapper.Builder(builder);
354
355     assertTrue(abstractBuilder.isInitialized());
356     assertEquals("", abstractBuilder.getInitializationErrorString());
357
358     builder.setOptionalMessage(TEST_REQUIRED_UNINITIALIZED);
359     assertFalse(abstractBuilder.isInitialized());
360     assertEquals(
361         "optional_message.a, optional_message.b, optional_message.c",
362         abstractBuilder.getInitializationErrorString());
363
364     builder.setOptionalMessage(TEST_REQUIRED_INITIALIZED);
365     assertTrue(abstractBuilder.isInitialized());
366     assertEquals("", abstractBuilder.getInitializationErrorString());
367
368     builder.addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED);
369     assertFalse(abstractBuilder.isInitialized());
370     assertEquals(
371         "repeated_message[0].a, repeated_message[0].b, repeated_message[0].c",
372         abstractBuilder.getInitializationErrorString());
373
374     builder.setRepeatedMessage(0, TEST_REQUIRED_INITIALIZED);
375     assertTrue(abstractBuilder.isInitialized());
376     assertEquals("", abstractBuilder.getInitializationErrorString());
377   }
378
379   // -----------------------------------------------------------------
380   // Tests for mergeFrom
381
382   static final TestAllTypes MERGE_SOURCE =
383     TestAllTypes.newBuilder()
384       .setOptionalInt32(1)
385       .setOptionalString("foo")
386       .setOptionalForeignMessage(ForeignMessage.getDefaultInstance())
387       .addRepeatedString("bar")
388       .build();
389
390   static final TestAllTypes MERGE_DEST =
391     TestAllTypes.newBuilder()
392       .setOptionalInt64(2)
393       .setOptionalString("baz")
394       .setOptionalForeignMessage(ForeignMessage.newBuilder().setC(3).build())
395       .addRepeatedString("qux")
396       .build();
397
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" +
403       "  c: 3\n" +
404       "}\n" +
405       "repeated_string: \"qux\"\n" +
406       "repeated_string: \"bar\"\n";
407
408   public void testMergeFrom() throws Exception {
409     AbstractMessageWrapper result =
410       new AbstractMessageWrapper.Builder(
411         TestAllTypes.newBuilder(MERGE_DEST))
412       .mergeFrom(MERGE_SOURCE).build();
413
414     assertEquals(MERGE_RESULT_TEXT, result.toString());
415   }
416
417   // -----------------------------------------------------------------
418   // Tests for equals and hashCode
419
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();
428
429     checkEqualsIsConsistent(a);
430     checkEqualsIsConsistent(b);
431     checkEqualsIsConsistent(c);
432     checkEqualsIsConsistent(d);
433     checkEqualsIsConsistent(e);
434     checkEqualsIsConsistent(f);
435
436     checkNotEqual(a, b);
437     checkNotEqual(a, c);
438     checkNotEqual(a, d);
439     checkNotEqual(a, e);
440     checkNotEqual(a, f);
441
442     checkNotEqual(b, c);
443     checkNotEqual(b, d);
444     checkNotEqual(b, e);
445     checkNotEqual(b, f);
446
447     checkNotEqual(c, d);
448     checkNotEqual(c, e);
449     checkNotEqual(c, f);
450
451     checkNotEqual(d, e);
452     checkNotEqual(d, f);
453
454     checkNotEqual(e, f);
455
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);
465
466     // Subsequent reconstitutions should be identical
467     UnittestProto.TestEmptyMessage eUnknownFields2 =
468         UnittestProto.TestEmptyMessage.parseFrom(e.toByteArray());
469     checkEqualsIsConsistent(eUnknownFields, eUnknownFields2);
470   }
471
472
473   /**
474    * Asserts that the given proto has symmetric equals and hashCode methods.
475    */
476   private void checkEqualsIsConsistent(Message message) {
477     // Object should be equal to itself.
478     assertEquals(message, message);
479
480     // Object should be equal to a dynamic copy of itself.
481     DynamicMessage dynamic = DynamicMessage.newBuilder(message).build();
482     checkEqualsIsConsistent(message, dynamic);
483   }
484
485   /**
486    * Asserts that the given protos are equal and have the same hash code.
487    */
488   private void checkEqualsIsConsistent(Message message1, Message message2) {
489     assertEquals(message1, message2);
490     assertEquals(message2, message1);
491     assertEquals(message2.hashCode(), message1.hashCode());
492   }
493
494   /**
495    * Asserts that the given protos are not equal and have different hash codes.
496    *
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
499    *   relatively rarely.
500    */
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));
505
506     assertFalse(
507         String.format("%s should have a different hash code from %s", m1, m2),
508         m1.hashCode() == m2.hashCode());
509   }
510 }