• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc.  All rights reserved.
3 // https://developers.google.com/protocol-buffers/
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;
32 
33 import static org.junit.Assert.assertArrayEquals;
34 
35 import map_lite_test.MapTestProto.BizarroTestMap;
36 import map_lite_test.MapTestProto.TestMap;
37 import map_lite_test.MapTestProto.TestMap.MessageValue;
38 import map_lite_test.MapTestProto.TestMapOrBuilder;
39 import java.io.ByteArrayOutputStream;
40 import java.io.IOException;
41 import java.util.ArrayList;
42 import java.util.Arrays;
43 import java.util.HashMap;
44 import java.util.Map;
45 import junit.framework.TestCase;
46 
47 /** Unit tests for map fields. */
48 public final class MapLiteTest extends TestCase {
49 
setMapValues(TestMap.Builder builder)50   private void setMapValues(TestMap.Builder builder) {
51     builder
52         .putInt32ToInt32Field(1, 11)
53         .putInt32ToInt32Field(2, 22)
54         .putInt32ToInt32Field(3, 33)
55         .putInt32ToStringField(1, "11")
56         .putInt32ToStringField(2, "22")
57         .putInt32ToStringField(3, "33")
58         .putInt32ToBytesField(1, TestUtil.toBytes("11"))
59         .putInt32ToBytesField(2, TestUtil.toBytes("22"))
60         .putInt32ToBytesField(3, TestUtil.toBytes("33"))
61         .putInt32ToEnumField(1, TestMap.EnumValue.FOO)
62         .putInt32ToEnumField(2, TestMap.EnumValue.BAR)
63         .putInt32ToEnumField(3, TestMap.EnumValue.BAZ)
64         .putInt32ToMessageField(1, MessageValue.newBuilder().setValue(11).build())
65         .putInt32ToMessageField(2, MessageValue.newBuilder().setValue(22).build())
66         .putInt32ToMessageField(3, MessageValue.newBuilder().setValue(33).build())
67         .putStringToInt32Field("1", 11)
68         .putStringToInt32Field("2", 22)
69         .putStringToInt32Field("3", 33);
70   }
71 
testSetMapValues()72   public void testSetMapValues() {
73     TestMap.Builder usingMutableMapBuilder = TestMap.newBuilder();
74     setMapValues(usingMutableMapBuilder);
75     TestMap usingMutableMap = usingMutableMapBuilder.build();
76     assertMapValuesSet(usingMutableMap);
77 
78     TestMap.Builder usingAccessorsBuilder = TestMap.newBuilder();
79     setMapValues(usingAccessorsBuilder);
80     TestMap usingAccessors = usingAccessorsBuilder.build();
81     assertMapValuesSet(usingAccessors);
82     assertEquals(usingAccessors, usingMutableMap);
83   }
84 
copyMapValues(TestMap source, TestMap.Builder destination)85   private void copyMapValues(TestMap source, TestMap.Builder destination) {
86     destination
87         .putAllInt32ToInt32Field(source.getInt32ToInt32FieldMap())
88         .putAllInt32ToStringField(source.getInt32ToStringFieldMap())
89         .putAllInt32ToBytesField(source.getInt32ToBytesFieldMap())
90         .putAllInt32ToEnumField(source.getInt32ToEnumFieldMap())
91         .putAllInt32ToMessageField(source.getInt32ToMessageFieldMap())
92         .putAllStringToInt32Field(source.getStringToInt32FieldMap());
93   }
94 
assertMapValuesSet(TestMap message)95   private void assertMapValuesSet(TestMap message) {
96     assertEquals(3, message.getInt32ToInt32FieldMap().size());
97     assertEquals(11, message.getInt32ToInt32FieldMap().get(1).intValue());
98     assertEquals(22, message.getInt32ToInt32FieldMap().get(2).intValue());
99     assertEquals(33, message.getInt32ToInt32FieldMap().get(3).intValue());
100 
101     assertEquals(3, message.getInt32ToStringFieldMap().size());
102     assertEquals("11", message.getInt32ToStringFieldMap().get(1));
103     assertEquals("22", message.getInt32ToStringFieldMap().get(2));
104     assertEquals("33", message.getInt32ToStringFieldMap().get(3));
105 
106     assertEquals(3, message.getInt32ToBytesFieldMap().size());
107     assertEquals(TestUtil.toBytes("11"), message.getInt32ToBytesFieldMap().get(1));
108     assertEquals(TestUtil.toBytes("22"), message.getInt32ToBytesFieldMap().get(2));
109     assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesFieldMap().get(3));
110 
111     assertEquals(3, message.getInt32ToEnumFieldMap().size());
112     assertEquals(TestMap.EnumValue.FOO, message.getInt32ToEnumFieldMap().get(1));
113     assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumFieldMap().get(2));
114     assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumFieldMap().get(3));
115 
116     assertEquals(3, message.getInt32ToMessageFieldMap().size());
117     assertEquals(11, message.getInt32ToMessageFieldMap().get(1).getValue());
118     assertEquals(22, message.getInt32ToMessageFieldMap().get(2).getValue());
119     assertEquals(33, message.getInt32ToMessageFieldMap().get(3).getValue());
120 
121     assertEquals(3, message.getStringToInt32FieldMap().size());
122     assertEquals(11, message.getStringToInt32FieldMap().get("1").intValue());
123     assertEquals(22, message.getStringToInt32FieldMap().get("2").intValue());
124     assertEquals(33, message.getStringToInt32FieldMap().get("3").intValue());
125   }
126 
updateMapValues(TestMap.Builder builder)127   private void updateMapValues(TestMap.Builder builder) {
128     builder
129         .putInt32ToInt32Field(1, 111)
130         .removeInt32ToInt32Field(2)
131         .putInt32ToInt32Field(4, 44)
132         .putInt32ToStringField(1, "111")
133         .removeInt32ToStringField(2)
134         .putInt32ToStringField(4, "44")
135         .putInt32ToBytesField(1, TestUtil.toBytes("111"))
136         .removeInt32ToBytesField(2)
137         .putInt32ToBytesField(4, TestUtil.toBytes("44"))
138         .putInt32ToEnumField(1, TestMap.EnumValue.BAR)
139         .removeInt32ToEnumField(2)
140         .putInt32ToEnumField(4, TestMap.EnumValue.QUX)
141         .putInt32ToMessageField(1, MessageValue.newBuilder().setValue(111).build())
142         .removeInt32ToMessageField(2)
143         .putInt32ToMessageField(4, MessageValue.newBuilder().setValue(44).build())
144         .putStringToInt32Field("1", 111)
145         .removeStringToInt32Field("2")
146         .putStringToInt32Field("4", 44);
147   }
148 
testUpdateMapValues()149   public void testUpdateMapValues() {
150     TestMap.Builder mapBuilder = TestMap.newBuilder();
151     setMapValues(mapBuilder);
152     TestMap map = mapBuilder.build();
153     assertMapValuesSet(map);
154 
155     mapBuilder = map.toBuilder();
156     updateMapValues(mapBuilder);
157     map = mapBuilder.build();
158     assertMapValuesUpdated(map);
159   }
160 
assertMapValuesUpdated(TestMap message)161   private void assertMapValuesUpdated(TestMap message) {
162     assertEquals(3, message.getInt32ToInt32FieldMap().size());
163     assertEquals(111, message.getInt32ToInt32FieldMap().get(1).intValue());
164     assertEquals(33, message.getInt32ToInt32FieldMap().get(3).intValue());
165     assertEquals(44, message.getInt32ToInt32FieldMap().get(4).intValue());
166 
167     assertEquals(3, message.getInt32ToStringFieldMap().size());
168     assertEquals("111", message.getInt32ToStringFieldMap().get(1));
169     assertEquals("33", message.getInt32ToStringFieldMap().get(3));
170     assertEquals("44", message.getInt32ToStringFieldMap().get(4));
171 
172     assertEquals(3, message.getInt32ToBytesFieldMap().size());
173     assertEquals(TestUtil.toBytes("111"), message.getInt32ToBytesFieldMap().get(1));
174     assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesFieldMap().get(3));
175     assertEquals(TestUtil.toBytes("44"), message.getInt32ToBytesFieldMap().get(4));
176 
177     assertEquals(3, message.getInt32ToEnumFieldMap().size());
178     assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumFieldMap().get(1));
179     assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumFieldMap().get(3));
180     assertEquals(TestMap.EnumValue.QUX, message.getInt32ToEnumFieldMap().get(4));
181 
182     assertEquals(3, message.getInt32ToMessageFieldMap().size());
183     assertEquals(111, message.getInt32ToMessageFieldMap().get(1).getValue());
184     assertEquals(33, message.getInt32ToMessageFieldMap().get(3).getValue());
185     assertEquals(44, message.getInt32ToMessageFieldMap().get(4).getValue());
186 
187     assertEquals(3, message.getStringToInt32FieldMap().size());
188     assertEquals(111, message.getStringToInt32FieldMap().get("1").intValue());
189     assertEquals(33, message.getStringToInt32FieldMap().get("3").intValue());
190     assertEquals(44, message.getStringToInt32FieldMap().get("4").intValue());
191   }
192 
assertMapValuesCleared(TestMapOrBuilder testMapOrBuilder)193   private void assertMapValuesCleared(TestMapOrBuilder testMapOrBuilder) {
194     assertEquals(0, testMapOrBuilder.getInt32ToInt32Field().size());
195     assertEquals(0, testMapOrBuilder.getInt32ToInt32FieldCount());
196     assertEquals(0, testMapOrBuilder.getInt32ToStringField().size());
197     assertEquals(0, testMapOrBuilder.getInt32ToStringFieldCount());
198     assertEquals(0, testMapOrBuilder.getInt32ToBytesField().size());
199     assertEquals(0, testMapOrBuilder.getInt32ToBytesFieldCount());
200     assertEquals(0, testMapOrBuilder.getInt32ToEnumField().size());
201     assertEquals(0, testMapOrBuilder.getInt32ToEnumFieldCount());
202     assertEquals(0, testMapOrBuilder.getInt32ToMessageField().size());
203     assertEquals(0, testMapOrBuilder.getInt32ToMessageFieldCount());
204     assertEquals(0, testMapOrBuilder.getStringToInt32Field().size());
205     assertEquals(0, testMapOrBuilder.getStringToInt32FieldCount());
206   }
207 
testSanityCopyOnWrite()208   public void testSanityCopyOnWrite() throws InvalidProtocolBufferException {
209     // Since builders are implemented as a thin wrapper around a message
210     // instance, we attempt to verify that we can't cause the builder to modify
211     // a produced message.
212 
213     TestMap.Builder builder = TestMap.newBuilder();
214     TestMap message = builder.build();
215     builder.putInt32ToInt32Field(1, 2);
216     assertTrue(message.getInt32ToInt32FieldMap().isEmpty());
217     assertEquals(newMap(1, 2), builder.getInt32ToInt32FieldMap());
218     message = builder.build();
219     builder.putInt32ToInt32Field(2, 3);
220     assertEquals(newMap(1, 2), message.getInt32ToInt32FieldMap());
221     assertEquals(newMap(1, 2, 2, 3), builder.getInt32ToInt32FieldMap());
222   }
223 
testGetMapIsImmutable()224   public void testGetMapIsImmutable() {
225     TestMap.Builder builder = TestMap.newBuilder();
226     assertMapsAreImmutable(builder);
227     assertMapsAreImmutable(builder.build());
228 
229     setMapValues(builder);
230     assertMapsAreImmutable(builder);
231     assertMapsAreImmutable(builder.build());
232   }
233 
assertMapsAreImmutable(TestMapOrBuilder testMapOrBuilder)234   private void assertMapsAreImmutable(TestMapOrBuilder testMapOrBuilder) {
235     assertImmutable(testMapOrBuilder.getInt32ToInt32Field(), 1, 2);
236     assertImmutable(testMapOrBuilder.getInt32ToStringField(), 1, "2");
237     assertImmutable(testMapOrBuilder.getInt32ToBytesField(), 1, TestUtil.toBytes("2"));
238     assertImmutable(testMapOrBuilder.getInt32ToEnumField(), 1, TestMap.EnumValue.FOO);
239     assertImmutable(
240         testMapOrBuilder.getInt32ToMessageField(), 1, MessageValue.getDefaultInstance());
241     assertImmutable(testMapOrBuilder.getStringToInt32Field(), "1", 2);
242   }
243 
assertImmutable(Map<K, V> map, K key, V value)244   private <K, V> void assertImmutable(Map<K, V> map, K key, V value) {
245     try {
246       map.put(key, value);
247       fail();
248     } catch (UnsupportedOperationException e) {
249       // expected
250     }
251     if (!map.isEmpty()) {
252       try {
253         map.entrySet().remove(map.entrySet().iterator().next());
254         fail();
255       } catch (UnsupportedOperationException e) {
256         // expected
257       }
258     }
259   }
260 
testMapFieldClear()261   public void testMapFieldClear() {
262     TestMap.Builder builder = TestMap.newBuilder().putInt32ToInt32Field(1, 2);
263     builder.clearInt32ToInt32Field();
264     assertEquals(0, builder.getInt32ToInt32FieldCount());
265   }
266 
testMutableMapLifecycle()267   public void testMutableMapLifecycle() {
268     TestMap.Builder builder = TestMap.newBuilder().putInt32ToInt32Field(1, 2);
269     assertEquals(newMap(1, 2), builder.build().getInt32ToInt32FieldMap());
270     assertEquals(newMap(1, 2), builder.getInt32ToInt32FieldMap());
271     builder.putInt32ToInt32Field(2, 3);
272     assertEquals(newMap(1, 2, 2, 3), builder.getInt32ToInt32FieldMap());
273 
274     builder.putInt32ToEnumField(1, TestMap.EnumValue.BAR);
275     assertEquals(newMap(1, TestMap.EnumValue.BAR), builder.build().getInt32ToEnumFieldMap());
276     assertEquals(newMap(1, TestMap.EnumValue.BAR), builder.getInt32ToEnumFieldMap());
277     builder.putInt32ToEnumField(2, TestMap.EnumValue.FOO);
278     assertEquals(
279         newMap(1, TestMap.EnumValue.BAR, 2, TestMap.EnumValue.FOO),
280         builder.getInt32ToEnumFieldMap());
281 
282     builder.putInt32ToStringField(1, "1");
283     assertEquals(newMap(1, "1"), builder.build().getInt32ToStringFieldMap());
284     assertEquals(newMap(1, "1"), builder.getInt32ToStringFieldMap());
285     builder.putInt32ToStringField(2, "2");
286     assertEquals(newMap(1, "1", 2, "2"), builder.getInt32ToStringFieldMap());
287 
288     builder.putInt32ToMessageField(1, TestMap.MessageValue.getDefaultInstance());
289     assertEquals(
290         newMap(1, TestMap.MessageValue.getDefaultInstance()),
291         builder.build().getInt32ToMessageFieldMap());
292     assertEquals(
293         newMap(1, TestMap.MessageValue.getDefaultInstance()), builder.getInt32ToMessageFieldMap());
294     builder.putInt32ToMessageField(2, TestMap.MessageValue.getDefaultInstance());
295     assertEquals(
296         newMap(
297             1,
298             TestMap.MessageValue.getDefaultInstance(),
299             2,
300             TestMap.MessageValue.getDefaultInstance()),
301         builder.getInt32ToMessageFieldMap());
302   }
303 
testGettersAndSetters()304   public void testGettersAndSetters() throws Exception {
305     TestMap.Builder builder = TestMap.newBuilder();
306     TestMap message = builder.build();
307     assertMapValuesCleared(message);
308 
309     builder = message.toBuilder();
310     setMapValues(builder);
311     message = builder.build();
312     assertMapValuesSet(message);
313 
314     builder = message.toBuilder();
315     updateMapValues(builder);
316     message = builder.build();
317     assertMapValuesUpdated(message);
318 
319     builder = message.toBuilder();
320     builder.clear();
321     assertMapValuesCleared(builder);
322     message = builder.build();
323     assertMapValuesCleared(message);
324   }
325 
testPutAll()326   public void testPutAll() throws Exception {
327     TestMap.Builder sourceBuilder = TestMap.newBuilder();
328     setMapValues(sourceBuilder);
329     TestMap source = sourceBuilder.build();
330     assertMapValuesSet(source);
331 
332     TestMap.Builder destination = TestMap.newBuilder();
333     copyMapValues(source, destination);
334     assertMapValuesSet(destination.build());
335   }
336 
testPutAllForUnknownEnumValues()337   public void testPutAllForUnknownEnumValues() throws Exception {
338     TestMap.Builder sourceBuilder =
339         TestMap.newBuilder()
340             .putInt32ToEnumFieldValue(0, 0)
341             .putInt32ToEnumFieldValue(1, 1)
342             .putAllInt32ToEnumFieldValue(newMap(2, 1000)); // unknown value.
343     TestMap source = sourceBuilder.build();
344 
345     TestMap.Builder destinationBuilder = TestMap.newBuilder();
346     destinationBuilder.putAllInt32ToEnumFieldValue(source.getInt32ToEnumFieldValueMap());
347     TestMap destination = destinationBuilder.build();
348 
349     assertEquals(0, destination.getInt32ToEnumFieldValueMap().get(0).intValue());
350     assertEquals(1, destination.getInt32ToEnumFieldValueMap().get(1).intValue());
351     assertEquals(1000, destination.getInt32ToEnumFieldValueMap().get(2).intValue());
352     assertEquals(3, destination.getInt32ToEnumFieldCount());
353   }
354 
testPutForUnknownEnumValues()355   public void testPutForUnknownEnumValues() throws Exception {
356     TestMap.Builder builder =
357         TestMap.newBuilder()
358             .putInt32ToEnumFieldValue(0, 0)
359             .putInt32ToEnumFieldValue(1, 1)
360             .putInt32ToEnumFieldValue(2, 1000); // unknown value.
361     TestMap message = builder.build();
362 
363     assertEquals(0, message.getInt32ToEnumFieldValueOrThrow(0));
364     assertEquals(1, message.getInt32ToEnumFieldValueOrThrow(1));
365     assertEquals(1000, message.getInt32ToEnumFieldValueOrThrow(2));
366     assertEquals(3, message.getInt32ToEnumFieldCount());
367   }
368 
testPutChecksNullKeysAndValues()369   public void testPutChecksNullKeysAndValues() throws Exception {
370     TestMap.Builder builder = TestMap.newBuilder();
371 
372     try {
373       builder.putInt32ToStringField(1, null);
374       fail();
375     } catch (NullPointerException e) {
376       // expected.
377     }
378 
379     try {
380       builder.putInt32ToBytesField(1, null);
381       fail();
382     } catch (NullPointerException e) {
383       // expected.
384     }
385 
386     try {
387       builder.putInt32ToEnumField(1, null);
388       fail();
389     } catch (NullPointerException e) {
390       // expected.
391     }
392 
393     try {
394       builder.putInt32ToMessageField(1, null);
395       fail();
396     } catch (NullPointerException e) {
397       // expected.
398     }
399 
400     try {
401       builder.putStringToInt32Field(null, 1);
402       fail();
403     } catch (NullPointerException e) {
404       // expected.
405     }
406   }
407 
testSerializeAndParse()408   public void testSerializeAndParse() throws Exception {
409     TestMap.Builder builder = TestMap.newBuilder();
410     setMapValues(builder);
411     TestMap message = builder.build();
412     assertEquals(message.getSerializedSize(), message.toByteString().size());
413     message = TestMap.parser().parseFrom(message.toByteString());
414     assertMapValuesSet(message);
415 
416     builder = message.toBuilder();
417     updateMapValues(builder);
418     message = builder.build();
419     assertEquals(message.getSerializedSize(), message.toByteString().size());
420     message = TestMap.parser().parseFrom(message.toByteString());
421     assertMapValuesUpdated(message);
422 
423     builder = message.toBuilder();
424     builder.clear();
425     message = builder.build();
426     assertEquals(message.getSerializedSize(), message.toByteString().size());
427     message = TestMap.parser().parseFrom(message.toByteString());
428     assertMapValuesCleared(message);
429   }
430 
tryParseTestMap(BizarroTestMap bizarroMap)431   private TestMap tryParseTestMap(BizarroTestMap bizarroMap) throws IOException {
432     ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
433     CodedOutputStream output = CodedOutputStream.newInstance(byteArrayOutputStream);
434     bizarroMap.writeTo(output);
435     output.flush();
436     return TestMap.parser().parseFrom(ByteString.copyFrom(byteArrayOutputStream.toByteArray()));
437   }
438 
testParseError()439   public void testParseError() throws Exception {
440     ByteString bytes = TestUtil.toBytes("SOME BYTES");
441     String stringKey = "a string key";
442 
443     TestMap map =
444         tryParseTestMap(BizarroTestMap.newBuilder().putInt32ToInt32Field(5, bytes).build());
445     assertEquals(0, map.getInt32ToInt32FieldOrDefault(5, -1));
446 
447     map = tryParseTestMap(BizarroTestMap.newBuilder().putInt32ToStringField(stringKey, 5).build());
448     assertEquals("", map.getInt32ToStringFieldOrDefault(0, null));
449 
450     map = tryParseTestMap(BizarroTestMap.newBuilder().putInt32ToBytesField(stringKey, 5).build());
451     assertEquals(map.getInt32ToBytesFieldOrDefault(0, null), ByteString.EMPTY);
452 
453     map =
454         tryParseTestMap(BizarroTestMap.newBuilder().putInt32ToEnumField(stringKey, bytes).build());
455     assertEquals(TestMap.EnumValue.FOO, map.getInt32ToEnumFieldOrDefault(0, null));
456 
457     try {
458       tryParseTestMap(BizarroTestMap.newBuilder().putInt32ToMessageField(stringKey, bytes).build());
459       fail();
460     } catch (InvalidProtocolBufferException expected) {
461       assertTrue(expected.getUnfinishedMessage() instanceof TestMap);
462       map = (TestMap) expected.getUnfinishedMessage();
463       assertTrue(map.getInt32ToMessageFieldMap().isEmpty());
464     }
465 
466     map =
467         tryParseTestMap(
468             BizarroTestMap.newBuilder().putStringToInt32Field(stringKey, bytes).build());
469     assertEquals(0, map.getStringToInt32FieldOrDefault(stringKey, -1));
470   }
471 
testMergeFrom()472   public void testMergeFrom() throws Exception {
473     TestMap.Builder builder = TestMap.newBuilder();
474     setMapValues(builder);
475     TestMap message = builder.build();
476 
477     TestMap.Builder other = TestMap.newBuilder();
478     other.mergeFrom(message);
479     assertMapValuesSet(other.build());
480   }
481 
testEqualsAndHashCode()482   public void testEqualsAndHashCode() throws Exception {
483     // Test that generated equals() and hashCode() will disregard the order
484     // of map entries when comparing/hashing map fields.
485 
486     // We can't control the order of elements in a HashMap. The best we can do
487     // here is to add elements in different order.
488     TestMap.Builder b1 =
489         TestMap.newBuilder()
490             .putInt32ToInt32Field(1, 2)
491             .putInt32ToInt32Field(3, 4)
492             .putInt32ToInt32Field(5, 6);
493     TestMap m1 = b1.build();
494 
495     TestMap.Builder b2 =
496         TestMap.newBuilder()
497             .putInt32ToInt32Field(5, 6)
498             .putInt32ToInt32Field(1, 2)
499             .putInt32ToInt32Field(3, 4);
500     TestMap m2 = b2.build();
501 
502     assertEquals(m1, m2);
503     assertEquals(m1.hashCode(), m2.hashCode());
504 
505     // Make sure we did compare map fields.
506     b2.putInt32ToInt32Field(1, 0);
507     m2 = b2.build();
508     assertFalse(m1.equals(m2));
509     // Don't check m1.hashCode() != m2.hashCode() because it's not guaranteed
510     // to be different.
511 
512     // Regression test for b/18549190: if a map is a subset of the other map,
513     // equals() should return false.
514     b2.removeInt32ToInt32Field(1);
515     m2 = b2.build();
516     assertFalse(m1.equals(m2));
517     assertFalse(m2.equals(m1));
518   }
519 
testUnknownEnumValues()520   public void testUnknownEnumValues() throws Exception {
521     TestMap.Builder builder =
522         TestMap.newBuilder()
523             .putInt32ToEnumFieldValue(0, 0)
524             .putInt32ToEnumFieldValue(1, 1)
525             .putInt32ToEnumFieldValue(2, 1000); // unknown value.
526     TestMap message = builder.build();
527 
528     assertEquals(TestMap.EnumValue.FOO, message.getInt32ToEnumFieldMap().get(0));
529     assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumFieldMap().get(1));
530     assertEquals(TestMap.EnumValue.UNRECOGNIZED, message.getInt32ToEnumFieldMap().get(2));
531 
532     builder.putAllInt32ToEnumFieldValue(newMap(2, 1000)); // unknown value.
533     message = builder.build();
534     assertEquals(TestMap.EnumValue.UNRECOGNIZED, message.getInt32ToEnumFieldMap().get(2));
535 
536     // Unknown enum values should be preserved after:
537     //   1. Serialization and parsing.
538     //   2. toBuild().
539     //   3. mergeFrom().
540     message = TestMap.parseFrom(message.toByteString());
541     assertEquals(1000, message.getInt32ToEnumFieldValueMap().get(2).intValue());
542     builder = message.toBuilder();
543     assertEquals(1000, builder.getInt32ToEnumFieldValueMap().get(2).intValue());
544     builder = TestMap.newBuilder().mergeFrom(message);
545     assertEquals(1000, builder.getInt32ToEnumFieldValueMap().get(2).intValue());
546 
547     // hashCode()/equals() should take unknown enum values into account.
548     builder.putAllInt32ToEnumFieldValue(newMap(2, 1001));
549     TestMap message2 = builder.build();
550     assertFalse(message.hashCode() == message2.hashCode());
551     assertFalse(message.equals(message2));
552     // Unknown values will be converted to UNRECOGNIZED so the resulted enum map
553     // should be the same.
554     assertEquals(message2.getInt32ToEnumFieldMap(), message.getInt32ToEnumFieldMap());
555   }
556 
testIterationOrder()557   public void testIterationOrder() throws Exception {
558     TestMap.Builder builder = TestMap.newBuilder();
559     setMapValues(builder);
560     TestMap message = builder.build();
561 
562     assertEquals(
563         Arrays.asList("1", "2", "3"), new ArrayList<>(message.getStringToInt32FieldMap().keySet()));
564   }
565 
testGetMap()566   public void testGetMap() {
567     TestMap.Builder builder = TestMap.newBuilder();
568     setMapValues(builder);
569     TestMap message = builder.build();
570     assertEquals(message.getStringToInt32FieldMap(), message.getStringToInt32FieldMap());
571     assertEquals(message.getInt32ToBytesFieldMap(), message.getInt32ToBytesFieldMap());
572     assertEquals(message.getInt32ToEnumFieldMap(), message.getInt32ToEnumFieldMap());
573     assertEquals(message.getInt32ToEnumFieldValueMap(), message.getInt32ToEnumFieldValueMap());
574     assertEquals(message.getInt32ToMessageFieldMap(), message.getInt32ToMessageFieldMap());
575   }
576 
testContains()577   public void testContains() {
578     TestMap.Builder builder = TestMap.newBuilder();
579     setMapValues(builder);
580     assertMapContainsSetValues(builder);
581     assertMapContainsSetValues(builder.build());
582   }
583 
assertMapContainsSetValues(TestMapOrBuilder testMapOrBuilder)584   private void assertMapContainsSetValues(TestMapOrBuilder testMapOrBuilder) {
585     assertTrue(testMapOrBuilder.containsInt32ToInt32Field(1));
586     assertTrue(testMapOrBuilder.containsInt32ToInt32Field(2));
587     assertTrue(testMapOrBuilder.containsInt32ToInt32Field(3));
588     assertFalse(testMapOrBuilder.containsInt32ToInt32Field(-1));
589 
590     assertTrue(testMapOrBuilder.containsInt32ToStringField(1));
591     assertTrue(testMapOrBuilder.containsInt32ToStringField(2));
592     assertTrue(testMapOrBuilder.containsInt32ToStringField(3));
593     assertFalse(testMapOrBuilder.containsInt32ToStringField(-1));
594 
595     assertTrue(testMapOrBuilder.containsInt32ToBytesField(1));
596     assertTrue(testMapOrBuilder.containsInt32ToBytesField(2));
597     assertTrue(testMapOrBuilder.containsInt32ToBytesField(3));
598     assertFalse(testMapOrBuilder.containsInt32ToBytesField(-1));
599 
600     assertTrue(testMapOrBuilder.containsInt32ToEnumField(1));
601     assertTrue(testMapOrBuilder.containsInt32ToEnumField(2));
602     assertTrue(testMapOrBuilder.containsInt32ToEnumField(3));
603     assertFalse(testMapOrBuilder.containsInt32ToEnumField(-1));
604 
605     assertTrue(testMapOrBuilder.containsInt32ToMessageField(1));
606     assertTrue(testMapOrBuilder.containsInt32ToMessageField(2));
607     assertTrue(testMapOrBuilder.containsInt32ToMessageField(3));
608     assertFalse(testMapOrBuilder.containsInt32ToMessageField(-1));
609 
610     assertTrue(testMapOrBuilder.containsStringToInt32Field("1"));
611     assertTrue(testMapOrBuilder.containsStringToInt32Field("2"));
612     assertTrue(testMapOrBuilder.containsStringToInt32Field("3"));
613     assertFalse(testMapOrBuilder.containsStringToInt32Field("-1"));
614   }
615 
testCount()616   public void testCount() {
617     TestMap.Builder builder = TestMap.newBuilder();
618     assertMapCounts(0, builder);
619 
620     setMapValues(builder);
621     assertMapCounts(3, builder);
622 
623     TestMap message = builder.build();
624     assertMapCounts(3, message);
625 
626     builder = message.toBuilder().putInt32ToInt32Field(4, 44);
627     assertEquals(4, builder.getInt32ToInt32FieldCount());
628     assertEquals(4, builder.build().getInt32ToInt32FieldCount());
629 
630     // already present - should be unchanged
631     builder.putInt32ToInt32Field(4, 44);
632     assertEquals(4, builder.getInt32ToInt32FieldCount());
633   }
634 
assertMapCounts(int expectedCount, TestMapOrBuilder testMapOrBuilder)635   private void assertMapCounts(int expectedCount, TestMapOrBuilder testMapOrBuilder) {
636     assertEquals(expectedCount, testMapOrBuilder.getInt32ToInt32FieldCount());
637     assertEquals(expectedCount, testMapOrBuilder.getInt32ToStringFieldCount());
638     assertEquals(expectedCount, testMapOrBuilder.getInt32ToBytesFieldCount());
639     assertEquals(expectedCount, testMapOrBuilder.getInt32ToEnumFieldCount());
640     assertEquals(expectedCount, testMapOrBuilder.getInt32ToMessageFieldCount());
641     assertEquals(expectedCount, testMapOrBuilder.getStringToInt32FieldCount());
642   }
643 
testGetOrDefault()644   public void testGetOrDefault() {
645     TestMap.Builder builder = TestMap.newBuilder();
646     assertMapCounts(0, builder);
647     setMapValues(builder);
648     doTestGetOrDefault(builder);
649     doTestGetOrDefault(builder.build());
650   }
651 
doTestGetOrDefault(TestMapOrBuilder testMapOrBuilder)652   public void doTestGetOrDefault(TestMapOrBuilder testMapOrBuilder) {
653     assertEquals(11, testMapOrBuilder.getInt32ToInt32FieldOrDefault(1, -11));
654     assertEquals(-11, testMapOrBuilder.getInt32ToInt32FieldOrDefault(-1, -11));
655 
656     assertEquals("11", testMapOrBuilder.getInt32ToStringFieldOrDefault(1, "-11"));
657     assertNull("-11", testMapOrBuilder.getInt32ToStringFieldOrDefault(-1, null));
658 
659     assertEquals(TestUtil.toBytes("11"), testMapOrBuilder.getInt32ToBytesFieldOrDefault(1, null));
660     assertNull(testMapOrBuilder.getInt32ToBytesFieldOrDefault(-1, null));
661 
662     assertEquals(TestMap.EnumValue.FOO, testMapOrBuilder.getInt32ToEnumFieldOrDefault(1, null));
663     assertNull(testMapOrBuilder.getInt32ToEnumFieldOrDefault(-1, null));
664 
665     assertEquals(
666         TestMap.EnumValue.BAR.getNumber(),
667         testMapOrBuilder.getInt32ToEnumFieldValueOrDefault(2, -1));
668     assertEquals(-1, testMapOrBuilder.getInt32ToEnumFieldValueOrDefault(-1000, -1));
669 
670     assertEquals(
671         MessageValue.newBuilder().setValue(11).build(),
672         testMapOrBuilder.getInt32ToMessageFieldOrDefault(1, null));
673     assertNull(testMapOrBuilder.getInt32ToMessageFieldOrDefault(-1, null));
674 
675     assertEquals(11, testMapOrBuilder.getStringToInt32FieldOrDefault("1", -11));
676     assertEquals(-11, testMapOrBuilder.getStringToInt32FieldOrDefault("-1", -11));
677 
678     try {
679       testMapOrBuilder.getStringToInt32FieldOrDefault(null, -11);
680       fail();
681     } catch (NullPointerException e) {
682       // expected
683     }
684   }
685 
testGetOrThrow()686   public void testGetOrThrow() {
687     TestMap.Builder builder = TestMap.newBuilder();
688     assertMapCounts(0, builder);
689     setMapValues(builder);
690     doTestGetOrDefault(builder);
691     doTestGetOrDefault(builder.build());
692   }
693 
doTestGetOrThrow(TestMapOrBuilder testMapOrBuilder)694   public void doTestGetOrThrow(TestMapOrBuilder testMapOrBuilder) {
695     assertEquals(11, testMapOrBuilder.getInt32ToInt32FieldOrThrow(1));
696     try {
697       testMapOrBuilder.getInt32ToInt32FieldOrThrow(-1);
698       fail();
699     } catch (IllegalArgumentException e) {
700       // expected
701     }
702 
703     assertEquals("11", testMapOrBuilder.getInt32ToStringFieldOrThrow(1));
704 
705     try {
706       testMapOrBuilder.getInt32ToStringFieldOrThrow(-1);
707       fail();
708     } catch (IllegalArgumentException e) {
709       // expected
710     }
711 
712     assertEquals(TestUtil.toBytes("11"), testMapOrBuilder.getInt32ToBytesFieldOrThrow(1));
713 
714     try {
715       testMapOrBuilder.getInt32ToBytesFieldOrThrow(-1);
716       fail();
717     } catch (IllegalArgumentException e) {
718       // expected
719     }
720 
721     assertEquals(TestMap.EnumValue.FOO, testMapOrBuilder.getInt32ToEnumFieldOrThrow(1));
722     try {
723       testMapOrBuilder.getInt32ToEnumFieldOrThrow(-1);
724       fail();
725     } catch (IllegalArgumentException e) {
726       // expected
727     }
728 
729     assertEquals(
730         TestMap.EnumValue.BAR.getNumber(), testMapOrBuilder.getInt32ToEnumFieldValueOrThrow(2));
731     try {
732       testMapOrBuilder.getInt32ToEnumFieldValueOrThrow(-1);
733       fail();
734     } catch (IllegalArgumentException e) {
735       // expected
736     }
737 
738     assertEquals(
739         MessageValue.newBuilder().setValue(11).build(),
740         testMapOrBuilder.getInt32ToMessageFieldOrThrow(1));
741     try {
742       testMapOrBuilder.getInt32ToMessageFieldOrThrow(-1);
743       fail();
744     } catch (IllegalArgumentException e) {
745       // expected
746     }
747 
748     assertEquals(11, testMapOrBuilder.getStringToInt32FieldOrThrow("1"));
749     try {
750       testMapOrBuilder.getStringToInt32FieldOrThrow("-1");
751       fail();
752     } catch (IllegalArgumentException e) {
753       // expected
754     }
755 
756     try {
757       testMapOrBuilder.getStringToInt32FieldOrThrow(null);
758       fail();
759     } catch (NullPointerException e) {
760       // expected
761     }
762   }
763 
testPut()764   public void testPut() {
765     TestMap.Builder builder = TestMap.newBuilder();
766     builder.putInt32ToInt32Field(1, 11);
767     assertEquals(11, builder.getInt32ToInt32FieldOrThrow(1));
768 
769     builder.putInt32ToStringField(1, "a");
770     assertEquals("a", builder.getInt32ToStringFieldOrThrow(1));
771     try {
772       builder.putInt32ToStringField(1, null);
773       fail();
774     } catch (NullPointerException e) {
775       // expected
776     }
777 
778     builder.putInt32ToBytesField(1, TestUtil.toBytes("11"));
779     assertEquals(TestUtil.toBytes("11"), builder.getInt32ToBytesFieldOrThrow(1));
780     try {
781       builder.putInt32ToBytesField(1, null);
782       fail();
783     } catch (NullPointerException e) {
784       // expected
785     }
786 
787     builder.putInt32ToEnumField(1, TestMap.EnumValue.FOO);
788     assertEquals(TestMap.EnumValue.FOO, builder.getInt32ToEnumFieldOrThrow(1));
789     try {
790       builder.putInt32ToEnumField(1, null);
791       fail();
792     } catch (NullPointerException e) {
793       // expected
794     }
795 
796     builder.putStringToInt32Field("a", 1);
797     assertEquals(1, builder.getStringToInt32FieldOrThrow("a"));
798     try {
799       builder.putStringToInt32Field(null, -1);
800     } catch (NullPointerException e) {
801       // expected
802     }
803   }
804 
testRemove()805   public void testRemove() {
806     TestMap.Builder builder = TestMap.newBuilder();
807     setMapValues(builder);
808     assertEquals(11, builder.getInt32ToInt32FieldOrThrow(1));
809     for (int times = 0; times < 2; times++) {
810       builder.removeInt32ToInt32Field(1);
811       assertEquals(-1, builder.getInt32ToInt32FieldOrDefault(1, -1));
812     }
813 
814     assertEquals("11", builder.getInt32ToStringFieldOrThrow(1));
815     for (int times = 0; times < 2; times++) {
816       builder.removeInt32ToStringField(1);
817       assertNull(builder.getInt32ToStringFieldOrDefault(1, null));
818     }
819 
820     assertEquals(TestUtil.toBytes("11"), builder.getInt32ToBytesFieldOrThrow(1));
821     for (int times = 0; times < 2; times++) {
822       builder.removeInt32ToBytesField(1);
823       assertNull(builder.getInt32ToBytesFieldOrDefault(1, null));
824     }
825 
826     assertEquals(TestMap.EnumValue.FOO, builder.getInt32ToEnumFieldOrThrow(1));
827     for (int times = 0; times < 2; times++) {
828       builder.removeInt32ToEnumField(1);
829       assertNull(builder.getInt32ToEnumFieldOrDefault(1, null));
830     }
831 
832     assertEquals(11, builder.getStringToInt32FieldOrThrow("1"));
833     for (int times = 0; times < 2; times++) {
834       builder.removeStringToInt32Field("1");
835       assertEquals(-1, builder.getStringToInt32FieldOrDefault("1", -1));
836     }
837 
838     try {
839       builder.removeStringToInt32Field(null);
840       fail();
841     } catch (NullPointerException e) {
842       // expected
843     }
844   }
845 
newMap(K key1, V value1)846   private static <K, V> Map<K, V> newMap(K key1, V value1) {
847     Map<K, V> map = new HashMap<>();
848     map.put(key1, value1);
849     return map;
850   }
851 
newMap(K key1, V value1, K key2, V value2)852   private static <K, V> Map<K, V> newMap(K key1, V value1, K key2, V value2) {
853     Map<K, V> map = new HashMap<>();
854     map.put(key1, value1);
855     map.put(key2, value2);
856     return map;
857   }
858 
testMap_withNulls()859   public void testMap_withNulls() {
860     TestMap.Builder builder = TestMap.newBuilder();
861 
862     try {
863       builder.putStringToInt32Field(null, 3);
864       fail();
865     } catch (NullPointerException expected) {
866     }
867 
868     try {
869       builder.putAllStringToInt32Field(newMap(null, 3, "hi", 4));
870       fail();
871     } catch (NullPointerException expected) {
872     }
873 
874     try {
875       builder.putInt32ToMessageField(3, null);
876       fail();
877     } catch (NullPointerException expected) {
878     }
879 
880     try {
881       builder.putAllInt32ToMessageField(
882           MapLiteTest.<Integer, MessageValue>newMap(4, null, 5, null));
883       fail();
884     } catch (NullPointerException expected) {
885     }
886 
887     try {
888       builder.putAllInt32ToMessageField(null);
889       fail();
890     } catch (NullPointerException expected) {
891     }
892 
893     assertArrayEquals(new byte[0], builder.build().toByteArray());
894   }
895 }
896