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