• 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 com.google.protobuf.Descriptors.Descriptor;
36 import com.google.protobuf.Descriptors.EnumDescriptor;
37 import com.google.protobuf.Descriptors.EnumValueDescriptor;
38 import com.google.protobuf.Descriptors.FieldDescriptor;
39 import map_test.MapTestProto.BizarroTestMap;
40 import map_test.MapTestProto.ReservedAsMapField;
41 import map_test.MapTestProto.ReservedAsMapFieldWithEnumValue;
42 import map_test.MapTestProto.TestMap;
43 import map_test.MapTestProto.TestMap.MessageValue;
44 import map_test.MapTestProto.TestMapOrBuilder;
45 import map_test.MapTestProto.TestOnChangeEventPropagation;
46 import java.io.ByteArrayOutputStream;
47 import java.io.IOException;
48 import java.util.ArrayList;
49 import java.util.Arrays;
50 import java.util.HashMap;
51 import java.util.List;
52 import java.util.Map;
53 import junit.framework.TestCase;
54 
55 /** Unit tests for map fields. */
56 public class MapTest extends TestCase {
57 
setMapValuesUsingMutableMap(TestMap.Builder builder)58   private void setMapValuesUsingMutableMap(TestMap.Builder builder) {
59     builder.getMutableInt32ToInt32Field().put(1, 11);
60     builder.getMutableInt32ToInt32Field().put(2, 22);
61     builder.getMutableInt32ToInt32Field().put(3, 33);
62   //
63     builder.getMutableInt32ToStringField().put(1, "11");
64     builder.getMutableInt32ToStringField().put(2, "22");
65     builder.getMutableInt32ToStringField().put(3, "33");
66   //
67     builder.getMutableInt32ToBytesField().put(1, TestUtil.toBytes("11"));
68     builder.getMutableInt32ToBytesField().put(2, TestUtil.toBytes("22"));
69     builder.getMutableInt32ToBytesField().put(3, TestUtil.toBytes("33"));
70   //
71     builder.getMutableInt32ToEnumField().put(1, TestMap.EnumValue.FOO);
72     builder.getMutableInt32ToEnumField().put(2, TestMap.EnumValue.BAR);
73     builder.getMutableInt32ToEnumField().put(3, TestMap.EnumValue.BAZ);
74   //
75     builder.getMutableInt32ToMessageField().put(
76         1, MessageValue.newBuilder().setValue(11).build());
77     builder.getMutableInt32ToMessageField().put(
78         2, MessageValue.newBuilder().setValue(22).build());
79     builder.getMutableInt32ToMessageField().put(
80         3, MessageValue.newBuilder().setValue(33).build());
81   //
82     builder.getMutableStringToInt32Field().put("1", 11);
83     builder.getMutableStringToInt32Field().put("2", 22);
84     builder.getMutableStringToInt32Field().put("3", 33);
85   }
86 
setMapValuesUsingAccessors(TestMap.Builder builder)87   private void setMapValuesUsingAccessors(TestMap.Builder builder) {
88     builder
89         .putInt32ToInt32Field(1, 11)
90         .putInt32ToInt32Field(2, 22)
91         .putInt32ToInt32Field(3, 33)
92         .putInt32ToStringField(1, "11")
93         .putInt32ToStringField(2, "22")
94         .putInt32ToStringField(3, "33")
95         .putInt32ToBytesField(1, TestUtil.toBytes("11"))
96         .putInt32ToBytesField(2, TestUtil.toBytes("22"))
97         .putInt32ToBytesField(3, TestUtil.toBytes("33"))
98         .putInt32ToEnumField(1, TestMap.EnumValue.FOO)
99         .putInt32ToEnumField(2, TestMap.EnumValue.BAR)
100         .putInt32ToEnumField(3, TestMap.EnumValue.BAZ)
101         .putInt32ToMessageField(1, MessageValue.newBuilder().setValue(11).build())
102         .putInt32ToMessageField(2, MessageValue.newBuilder().setValue(22).build())
103         .putInt32ToMessageField(3, MessageValue.newBuilder().setValue(33).build())
104         .putStringToInt32Field("1", 11)
105         .putStringToInt32Field("2", 22)
106         .putStringToInt32Field("3", 33);
107   }
108 
testSetMapValues()109   public void testSetMapValues() {
110     TestMap.Builder usingMutableMapBuilder = TestMap.newBuilder();
111     setMapValuesUsingMutableMap(usingMutableMapBuilder);
112     TestMap usingMutableMap = usingMutableMapBuilder.build();
113     assertMapValuesSet(usingMutableMap);
114 
115     TestMap.Builder usingAccessorsBuilder = TestMap.newBuilder();
116     setMapValuesUsingAccessors(usingAccessorsBuilder);
117     TestMap usingAccessors = usingAccessorsBuilder.build();
118     assertMapValuesSet(usingAccessors);
119 
120     assertEquals(usingAccessors, usingMutableMap);
121   }
122 
copyMapValues(TestMap source, TestMap.Builder destination)123   private void copyMapValues(TestMap source, TestMap.Builder destination) {
124     destination
125         .putAllInt32ToInt32Field(source.getInt32ToInt32Field())
126         .putAllInt32ToStringField(source.getInt32ToStringField())
127         .putAllInt32ToBytesField(source.getInt32ToBytesField())
128         .putAllInt32ToEnumField(source.getInt32ToEnumField())
129         .putAllInt32ToMessageField(source.getInt32ToMessageField())
130         .putAllStringToInt32Field(source.getStringToInt32Field());
131   }
132 
assertMapValuesSet(TestMap message)133   private void assertMapValuesSet(TestMap message) {
134     assertEquals(3, message.getInt32ToInt32Field().size());
135     assertEquals(11, message.getInt32ToInt32Field().get(1).intValue());
136     assertEquals(22, message.getInt32ToInt32Field().get(2).intValue());
137     assertEquals(33, message.getInt32ToInt32Field().get(3).intValue());
138 
139     assertEquals(3, message.getInt32ToStringField().size());
140     assertEquals("11", message.getInt32ToStringField().get(1));
141     assertEquals("22", message.getInt32ToStringField().get(2));
142     assertEquals("33", message.getInt32ToStringField().get(3));
143 
144     assertEquals(3, message.getInt32ToBytesField().size());
145     assertEquals(TestUtil.toBytes("11"), message.getInt32ToBytesField().get(1));
146     assertEquals(TestUtil.toBytes("22"), message.getInt32ToBytesField().get(2));
147     assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesField().get(3));
148 
149     assertEquals(3, message.getInt32ToEnumField().size());
150     assertEquals(TestMap.EnumValue.FOO, message.getInt32ToEnumField().get(1));
151     assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(2));
152     assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumField().get(3));
153 
154     assertEquals(3, message.getInt32ToMessageField().size());
155     assertEquals(11, message.getInt32ToMessageField().get(1).getValue());
156     assertEquals(22, message.getInt32ToMessageField().get(2).getValue());
157     assertEquals(33, message.getInt32ToMessageField().get(3).getValue());
158 
159     assertEquals(3, message.getStringToInt32Field().size());
160     assertEquals(11, message.getStringToInt32Field().get("1").intValue());
161     assertEquals(22, message.getStringToInt32Field().get("2").intValue());
162     assertEquals(33, message.getStringToInt32Field().get("3").intValue());
163   }
164 
updateMapValuesUsingMutableMap(TestMap.Builder builder)165   private void updateMapValuesUsingMutableMap(TestMap.Builder builder) {
166     builder.getMutableInt32ToInt32Field().put(1, 111);
167     builder.getMutableInt32ToInt32Field().remove(2);
168     builder.getMutableInt32ToInt32Field().put(4, 44);
169   //
170     builder.getMutableInt32ToStringField().put(1, "111");
171     builder.getMutableInt32ToStringField().remove(2);
172     builder.getMutableInt32ToStringField().put(4, "44");
173   //
174     builder.getMutableInt32ToBytesField().put(1, TestUtil.toBytes("111"));
175     builder.getMutableInt32ToBytesField().remove(2);
176     builder.getMutableInt32ToBytesField().put(4, TestUtil.toBytes("44"));
177   //
178     builder.getMutableInt32ToEnumField().put(1, TestMap.EnumValue.BAR);
179     builder.getMutableInt32ToEnumField().remove(2);
180     builder.getMutableInt32ToEnumField().put(4, TestMap.EnumValue.QUX);
181   //
182     builder.getMutableInt32ToMessageField().put(
183         1, MessageValue.newBuilder().setValue(111).build());
184     builder.getMutableInt32ToMessageField().remove(2);
185     builder.getMutableInt32ToMessageField().put(
186         4, MessageValue.newBuilder().setValue(44).build());
187   //
188     builder.getMutableStringToInt32Field().put("1", 111);
189     builder.getMutableStringToInt32Field().remove("2");
190     builder.getMutableStringToInt32Field().put("4", 44);
191   }
192 
updateMapValuesUsingAccessors(TestMap.Builder builder)193   private void updateMapValuesUsingAccessors(TestMap.Builder builder) {
194     builder
195         .putInt32ToInt32Field(1, 111)
196         .removeInt32ToInt32Field(2)
197         .putInt32ToInt32Field(4, 44)
198         .putInt32ToStringField(1, "111")
199         .removeInt32ToStringField(2)
200         .putInt32ToStringField(4, "44")
201         .putInt32ToBytesField(1, TestUtil.toBytes("111"))
202         .removeInt32ToBytesField(2)
203         .putInt32ToBytesField(4, TestUtil.toBytes("44"))
204         .putInt32ToEnumField(1, TestMap.EnumValue.BAR)
205         .removeInt32ToEnumField(2)
206         .putInt32ToEnumField(4, TestMap.EnumValue.QUX)
207         .putInt32ToMessageField(1, MessageValue.newBuilder().setValue(111).build())
208         .removeInt32ToMessageField(2)
209         .putInt32ToMessageField(4, MessageValue.newBuilder().setValue(44).build())
210         .putStringToInt32Field("1", 111)
211         .removeStringToInt32Field("2")
212         .putStringToInt32Field("4", 44);
213   }
214 
testUpdateMapValues()215   public void testUpdateMapValues() {
216     TestMap.Builder usingMutableMapBuilder = TestMap.newBuilder();
217     setMapValuesUsingMutableMap(usingMutableMapBuilder);
218     TestMap usingMutableMap = usingMutableMapBuilder.build();
219     assertMapValuesSet(usingMutableMap);
220 
221     TestMap.Builder usingAccessorsBuilder = TestMap.newBuilder();
222     setMapValuesUsingAccessors(usingAccessorsBuilder);
223     TestMap usingAccessors = usingAccessorsBuilder.build();
224     assertMapValuesSet(usingAccessors);
225 
226     assertEquals(usingAccessors, usingMutableMap);
227     //
228     usingMutableMapBuilder = usingMutableMap.toBuilder();
229     updateMapValuesUsingMutableMap(usingMutableMapBuilder);
230     usingMutableMap = usingMutableMapBuilder.build();
231     assertMapValuesUpdated(usingMutableMap);
232 
233     usingAccessorsBuilder = usingAccessors.toBuilder();
234     updateMapValuesUsingAccessors(usingAccessorsBuilder);
235     usingAccessors = usingAccessorsBuilder.build();
236     assertMapValuesUpdated(usingAccessors);
237 
238     assertEquals(usingAccessors, usingMutableMap);
239   }
240 
assertMapValuesUpdated(TestMap message)241   private void assertMapValuesUpdated(TestMap message) {
242     assertEquals(3, message.getInt32ToInt32Field().size());
243     assertEquals(111, message.getInt32ToInt32Field().get(1).intValue());
244     assertEquals(33, message.getInt32ToInt32Field().get(3).intValue());
245     assertEquals(44, message.getInt32ToInt32Field().get(4).intValue());
246 
247     assertEquals(3, message.getInt32ToStringField().size());
248     assertEquals("111", message.getInt32ToStringField().get(1));
249     assertEquals("33", message.getInt32ToStringField().get(3));
250     assertEquals("44", message.getInt32ToStringField().get(4));
251 
252     assertEquals(3, message.getInt32ToBytesField().size());
253     assertEquals(TestUtil.toBytes("111"), message.getInt32ToBytesField().get(1));
254     assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesField().get(3));
255     assertEquals(TestUtil.toBytes("44"), message.getInt32ToBytesField().get(4));
256 
257     assertEquals(3, message.getInt32ToEnumField().size());
258     assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(1));
259     assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumField().get(3));
260     assertEquals(TestMap.EnumValue.QUX, message.getInt32ToEnumField().get(4));
261 
262     assertEquals(3, message.getInt32ToMessageField().size());
263     assertEquals(111, message.getInt32ToMessageField().get(1).getValue());
264     assertEquals(33, message.getInt32ToMessageField().get(3).getValue());
265     assertEquals(44, message.getInt32ToMessageField().get(4).getValue());
266 
267     assertEquals(3, message.getStringToInt32Field().size());
268     assertEquals(111, message.getStringToInt32Field().get("1").intValue());
269     assertEquals(33, message.getStringToInt32Field().get("3").intValue());
270     assertEquals(44, message.getStringToInt32Field().get("4").intValue());
271   }
272 
assertMapValuesCleared(TestMapOrBuilder testMapOrBuilder)273   private void assertMapValuesCleared(TestMapOrBuilder testMapOrBuilder) {
274     assertEquals(0, testMapOrBuilder.getInt32ToInt32Field().size());
275     assertEquals(0, testMapOrBuilder.getInt32ToInt32FieldCount());
276     assertEquals(0, testMapOrBuilder.getInt32ToStringField().size());
277     assertEquals(0, testMapOrBuilder.getInt32ToStringFieldCount());
278     assertEquals(0, testMapOrBuilder.getInt32ToBytesField().size());
279     assertEquals(0, testMapOrBuilder.getInt32ToBytesFieldCount());
280     assertEquals(0, testMapOrBuilder.getInt32ToEnumField().size());
281     assertEquals(0, testMapOrBuilder.getInt32ToEnumFieldCount());
282     assertEquals(0, testMapOrBuilder.getInt32ToMessageField().size());
283     assertEquals(0, testMapOrBuilder.getInt32ToMessageFieldCount());
284     assertEquals(0, testMapOrBuilder.getStringToInt32Field().size());
285     assertEquals(0, testMapOrBuilder.getStringToInt32FieldCount());
286   }
287 
testGetMapIsImmutable()288   public void testGetMapIsImmutable() {
289     TestMap.Builder builder = TestMap.newBuilder();
290     assertMapsAreImmutable(builder);
291     assertMapsAreImmutable(builder.build());
292 
293     setMapValuesUsingAccessors(builder);
294     assertMapsAreImmutable(builder);
295     assertMapsAreImmutable(builder.build());
296   }
297 
assertMapsAreImmutable(TestMapOrBuilder testMapOrBuilder)298   private void assertMapsAreImmutable(TestMapOrBuilder testMapOrBuilder) {
299     assertImmutable(testMapOrBuilder.getInt32ToInt32Field(), 1, 2);
300     assertImmutable(testMapOrBuilder.getInt32ToStringField(), 1, "2");
301     assertImmutable(testMapOrBuilder.getInt32ToBytesField(), 1, TestUtil.toBytes("2"));
302     assertImmutable(testMapOrBuilder.getInt32ToEnumField(), 1, TestMap.EnumValue.FOO);
303     assertImmutable(
304         testMapOrBuilder.getInt32ToMessageField(), 1, MessageValue.getDefaultInstance());
305     assertImmutable(testMapOrBuilder.getStringToInt32Field(), "1", 2);
306   }
307 
assertImmutable(Map<K, V> map, K key, V value)308   private <K, V> void assertImmutable(Map<K, V> map, K key, V value) {
309     try {
310       map.put(key, value);
311       fail();
312     } catch (UnsupportedOperationException e) {
313       // expected
314     }
315   }
316 
testMutableMapLifecycle()317   public void testMutableMapLifecycle() {
318     TestMap.Builder builder = TestMap.newBuilder();
319     Map<Integer, Integer> intMap = builder.getMutableInt32ToInt32Field();
320     intMap.put(1, 2);
321     assertEquals(newMap(1, 2), builder.build().getInt32ToInt32Field());
322     try {
323       intMap.put(2, 3);
324       fail();
325     } catch (UnsupportedOperationException e) {
326       // expected
327     }
328     assertEquals(newMap(1, 2), builder.getInt32ToInt32Field());
329     builder.getMutableInt32ToInt32Field().put(2, 3);
330     assertEquals(newMap(1, 2, 2, 3), builder.getInt32ToInt32Field());
331   //
332     Map<Integer, TestMap.EnumValue> enumMap = builder.getMutableInt32ToEnumField();
333     enumMap.put(1, TestMap.EnumValue.BAR);
334     assertEquals(newMap(1, TestMap.EnumValue.BAR), builder.build().getInt32ToEnumField());
335     try {
336       enumMap.put(2, TestMap.EnumValue.FOO);
337       fail();
338     } catch (UnsupportedOperationException e) {
339       // expected
340     }
341     assertEquals(newMap(1, TestMap.EnumValue.BAR), builder.getInt32ToEnumField());
342     builder.getMutableInt32ToEnumField().put(2, TestMap.EnumValue.FOO);
343     assertEquals(
344         newMap(1, TestMap.EnumValue.BAR, 2, TestMap.EnumValue.FOO),
345         builder.getInt32ToEnumField());
346   //
347     Map<Integer, String> stringMap = builder.getMutableInt32ToStringField();
348     stringMap.put(1, "1");
349     assertEquals(newMap(1, "1"), builder.build().getInt32ToStringField());
350     try {
351       stringMap.put(2, "2");
352       fail();
353     } catch (UnsupportedOperationException e) {
354       // expected
355     }
356     assertEquals(newMap(1, "1"), builder.getInt32ToStringField());
357     builder.putInt32ToStringField(2, "2");
358     assertEquals(
359         newMap(1, "1", 2, "2"),
360         builder.getInt32ToStringField());
361   //
362     Map<Integer, TestMap.MessageValue> messageMap = builder.getMutableInt32ToMessageField();
363     messageMap.put(1, TestMap.MessageValue.getDefaultInstance());
364     assertEquals(newMap(1, TestMap.MessageValue.getDefaultInstance()),
365         builder.build().getInt32ToMessageField());
366     try {
367       messageMap.put(2, TestMap.MessageValue.getDefaultInstance());
368       fail();
369     } catch (UnsupportedOperationException e) {
370       // expected
371     }
372     assertEquals(newMap(1, TestMap.MessageValue.getDefaultInstance()),
373         builder.getInt32ToMessageField());
374     builder.putInt32ToMessageField(2, TestMap.MessageValue.getDefaultInstance());
375     assertEquals(
376         newMap(1, TestMap.MessageValue.getDefaultInstance(),
377             2, TestMap.MessageValue.getDefaultInstance()),
378         builder.getInt32ToMessageField());
379   }
380   //
testMutableMapLifecycle_collections()381   public void testMutableMapLifecycle_collections() {
382     TestMap.Builder builder = TestMap.newBuilder();
383     Map<Integer, Integer> intMap = builder.getMutableInt32ToInt32Field();
384     intMap.put(1, 2);
385     assertEquals(newMap(1, 2), builder.build().getInt32ToInt32Field());
386     try {
387       intMap.remove(2);
388       fail();
389     } catch (UnsupportedOperationException e) {
390       // expected
391     }
392     try {
393       intMap.entrySet().remove(new Object());
394       fail();
395     } catch (UnsupportedOperationException e) {
396       // expected
397     }
398     try {
399       intMap.entrySet().iterator().remove();
400       fail();
401     } catch (UnsupportedOperationException e) {
402       // expected
403     }
404     try {
405       intMap.keySet().remove(new Object());
406       fail();
407     } catch (UnsupportedOperationException e) {
408       // expected
409     }
410     try {
411       intMap.values().remove(new Object());
412       fail();
413     } catch (UnsupportedOperationException e) {
414       // expected
415     }
416     try {
417       intMap.values().iterator().remove();
418       fail();
419     } catch (UnsupportedOperationException e) {
420       // expected
421     }
422     assertEquals(newMap(1, 2), intMap);
423     assertEquals(newMap(1, 2), builder.getInt32ToInt32Field());
424     assertEquals(newMap(1, 2), builder.build().getInt32ToInt32Field());
425   }
426 
testGettersAndSetters()427   public void testGettersAndSetters() throws Exception {
428     TestMap.Builder builder = TestMap.newBuilder();
429     TestMap message = builder.build();
430     assertMapValuesCleared(message);
431 
432     builder = message.toBuilder();
433     setMapValuesUsingAccessors(builder);
434     message = builder.build();
435     assertMapValuesSet(message);
436 
437     builder = message.toBuilder();
438     updateMapValuesUsingAccessors(builder);
439     message = builder.build();
440     assertMapValuesUpdated(message);
441 
442     builder = message.toBuilder();
443     builder.clear();
444     assertMapValuesCleared(builder);
445     message = builder.build();
446     assertMapValuesCleared(message);
447   }
448 
testPutAll()449   public void testPutAll() throws Exception {
450     TestMap.Builder sourceBuilder = TestMap.newBuilder();
451     setMapValuesUsingAccessors(sourceBuilder);
452     TestMap source = sourceBuilder.build();
453     assertMapValuesSet(source);
454 
455     TestMap.Builder destination = TestMap.newBuilder();
456     copyMapValues(source, destination);
457     assertMapValuesSet(destination.build());
458   }
459 
testPutAllForUnknownEnumValues()460   public void testPutAllForUnknownEnumValues() throws Exception {
461     TestMap source =
462         TestMap.newBuilder()
463             .putAllInt32ToEnumFieldValue(
464                 newMap(
465                     0, 0,
466                     1, 1,
467                     2, 1000)) // unknown value.
468             .build();
469 
470     TestMap destination =
471         TestMap.newBuilder().putAllInt32ToEnumFieldValue(source.getInt32ToEnumFieldValue()).build();
472 
473     assertEquals(0, destination.getInt32ToEnumFieldValue().get(0).intValue());
474     assertEquals(1, destination.getInt32ToEnumFieldValue().get(1).intValue());
475     assertEquals(1000, destination.getInt32ToEnumFieldValue().get(2).intValue());
476     assertEquals(3, destination.getInt32ToEnumFieldCount());
477   }
478 
testPutForUnknownEnumValues()479   public void testPutForUnknownEnumValues() throws Exception {
480     TestMap message =
481         TestMap.newBuilder()
482             .putInt32ToEnumFieldValue(0, 0)
483             .putInt32ToEnumFieldValue(1, 1)
484             .putInt32ToEnumFieldValue(2, 1000) // unknown value.
485             .build();
486     assertEquals(0, message.getInt32ToEnumFieldValueOrThrow(0));
487     assertEquals(1, message.getInt32ToEnumFieldValueOrThrow(1));
488     assertEquals(1000, message.getInt32ToEnumFieldValueOrThrow(2));
489     assertEquals(3, message.getInt32ToEnumFieldCount());
490   }
491 
testPutChecksNullKeysAndValues()492   public void testPutChecksNullKeysAndValues() throws Exception {
493     TestMap.Builder builder = TestMap.newBuilder();
494 
495     try {
496       builder.putInt32ToStringField(1, null);
497       fail();
498     } catch (NullPointerException e) {
499       // expected.
500     }
501 
502     try {
503       builder.putInt32ToBytesField(1, null);
504       fail();
505     } catch (NullPointerException e) {
506       // expected.
507     }
508 
509     try {
510       builder.putInt32ToEnumField(1, null);
511       fail();
512     } catch (NullPointerException e) {
513       // expected.
514     }
515 
516     try {
517       builder.putInt32ToMessageField(1, null);
518       fail();
519     } catch (NullPointerException e) {
520       // expected.
521     }
522 
523     try {
524       builder.putStringToInt32Field(null, 1);
525       fail();
526     } catch (NullPointerException e) {
527       // expected.
528     }
529   }
530 
testSerializeAndParse()531   public void testSerializeAndParse() throws Exception {
532     TestMap.Builder builder = TestMap.newBuilder();
533     setMapValuesUsingAccessors(builder);
534     TestMap message = builder.build();
535     assertEquals(message.getSerializedSize(), message.toByteString().size());
536     message = TestMap.parser().parseFrom(message.toByteString());
537     assertMapValuesSet(message);
538 
539     builder = message.toBuilder();
540     updateMapValuesUsingAccessors(builder);
541     message = builder.build();
542     assertEquals(message.getSerializedSize(), message.toByteString().size());
543     message = TestMap.parser().parseFrom(message.toByteString());
544     assertMapValuesUpdated(message);
545 
546     builder = message.toBuilder();
547     builder.clear();
548     message = builder.build();
549     assertEquals(message.getSerializedSize(), message.toByteString().size());
550     message = TestMap.parser().parseFrom(message.toByteString());
551     assertMapValuesCleared(message);
552   }
553 
tryParseTestMap(BizarroTestMap bizarroMap)554   private TestMap tryParseTestMap(BizarroTestMap bizarroMap) throws IOException {
555     ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
556     CodedOutputStream output = CodedOutputStream.newInstance(byteArrayOutputStream);
557     bizarroMap.writeTo(output);
558     output.flush();
559     return TestMap.parser().parseFrom(ByteString.copyFrom(byteArrayOutputStream.toByteArray()));
560   }
561 
testParseError()562   public void testParseError() throws Exception {
563     ByteString bytes = TestUtil.toBytes("SOME BYTES");
564     String stringKey = "a string key";
565 
566     TestMap map =
567         tryParseTestMap(BizarroTestMap.newBuilder().putInt32ToInt32Field(5, bytes).build());
568     assertEquals(0, map.getInt32ToInt32FieldOrDefault(5, -1));
569 
570     map = tryParseTestMap(BizarroTestMap.newBuilder().putInt32ToStringField(stringKey, 5).build());
571     assertEquals("", map.getInt32ToStringFieldOrDefault(0, null));
572 
573     map = tryParseTestMap(BizarroTestMap.newBuilder().putInt32ToBytesField(stringKey, 5).build());
574     assertEquals(map.getInt32ToBytesFieldOrDefault(0, null), ByteString.EMPTY);
575 
576     map =
577         tryParseTestMap(BizarroTestMap.newBuilder().putInt32ToEnumField(stringKey, bytes).build());
578     assertEquals(TestMap.EnumValue.FOO, map.getInt32ToEnumFieldOrDefault(0, null));
579 
580     try {
581       tryParseTestMap(BizarroTestMap.newBuilder().putInt32ToMessageField(stringKey, bytes).build());
582       fail();
583     } catch (InvalidProtocolBufferException expected) {
584       assertTrue(expected.getUnfinishedMessage() instanceof TestMap);
585       map = (TestMap) expected.getUnfinishedMessage();
586       assertTrue(map.getInt32ToMessageField().isEmpty());
587     }
588 
589     map =
590         tryParseTestMap(
591             BizarroTestMap.newBuilder().putStringToInt32Field(stringKey, bytes).build());
592     assertEquals(0, map.getStringToInt32FieldOrDefault(stringKey, -1));
593   }
594 
testMergeFrom()595   public void testMergeFrom() throws Exception {
596     TestMap.Builder builder = TestMap.newBuilder();
597     setMapValuesUsingAccessors(builder);
598     TestMap message = builder.build();
599 
600     TestMap.Builder other = TestMap.newBuilder();
601     other.mergeFrom(message);
602     assertMapValuesSet(other.build());
603   }
604 
testEqualsAndHashCode()605   public void testEqualsAndHashCode() throws Exception {
606     // Test that generated equals() and hashCode() will disregard the order
607     // of map entries when comparing/hashing map fields.
608 
609     // We can't control the order of elements in a HashMap. The best we can do
610     // here is to add elements in different order.
611     TestMap m1 =
612         TestMap.newBuilder()
613             .putInt32ToInt32Field(1, 2)
614             .putInt32ToInt32Field(3, 4)
615             .putInt32ToInt32Field(5, 6)
616             .build();
617 
618     TestMap.Builder b2 =
619         TestMap.newBuilder()
620             .putInt32ToInt32Field(5, 6)
621             .putInt32ToInt32Field(1, 2)
622             .putInt32ToInt32Field(3, 4);
623     TestMap m2 = b2.build();
624 
625     assertEquals(m1, m2);
626     assertEquals(m1.hashCode(), m2.hashCode());
627 
628     // Make sure we did compare map fields.
629     b2.putInt32ToInt32Field(1, 0);
630     m2 = b2.build();
631     assertFalse(m1.equals(m2));
632     // Don't check m1.hashCode() != m2.hashCode() because it's not guaranteed
633     // to be different.
634 
635     // Regression test for b/18549190: if a map is a subset of the other map,
636     // equals() should return false.
637     b2.removeInt32ToInt32Field(1);
638     m2 = b2.build();
639     assertFalse(m1.equals(m2));
640     assertFalse(m2.equals(m1));
641   }
642 
testNestedBuilderOnChangeEventPropagation()643   public void testNestedBuilderOnChangeEventPropagation() {
644     TestOnChangeEventPropagation.Builder parent = TestOnChangeEventPropagation.newBuilder();
645     parent.getOptionalMessageBuilder().putInt32ToInt32Field(1, 2);
646     TestOnChangeEventPropagation message = parent.build();
647     assertEquals(2, message.getOptionalMessage().getInt32ToInt32Field().get(1).intValue());
648 
649     // Make a change using nested builder.
650     parent.getOptionalMessageBuilder().putInt32ToInt32Field(1, 3);
651 
652     // Should be able to observe the change.
653     message = parent.build();
654     assertEquals(3, message.getOptionalMessage().getInt32ToInt32Field().get(1).intValue());
655 
656     // Make another change using mergeFrom()
657     TestMap other = TestMap.newBuilder().putInt32ToInt32Field(1, 4).build();
658     parent.getOptionalMessageBuilder().mergeFrom(other);
659 
660     // Should be able to observe the change.
661     message = parent.build();
662     assertEquals(4, message.getOptionalMessage().getInt32ToInt32Field().get(1).intValue());
663 
664     // Make yet another change by clearing the nested builder.
665     parent.getOptionalMessageBuilder().clear();
666 
667     // Should be able to observe the change.
668     message = parent.build();
669     assertEquals(0, message.getOptionalMessage().getInt32ToInt32Field().size());
670   }
671 
testNestedBuilderOnChangeEventPropagationReflection()672   public void testNestedBuilderOnChangeEventPropagationReflection() {
673     FieldDescriptor intMapField = f("int32_to_int32_field");
674     // Create an outer message builder with nested builder.
675     TestOnChangeEventPropagation.Builder parentBuilder = TestOnChangeEventPropagation.newBuilder();
676     TestMap.Builder testMapBuilder = parentBuilder.getOptionalMessageBuilder();
677 
678     // Create a map entry message.
679     TestMap.Builder entryBuilder = TestMap.newBuilder().putInt32ToInt32Field(1, 1);
680 
681     // Put the entry into the nested builder.
682     testMapBuilder.addRepeatedField(intMapField, entryBuilder.getRepeatedField(intMapField, 0));
683 
684     // Should be able to observe the change.
685     TestOnChangeEventPropagation message = parentBuilder.build();
686     assertEquals(1, message.getOptionalMessage().getInt32ToInt32Field().size());
687 
688     // Change the entry value.
689     entryBuilder.putInt32ToInt32Field(1, 4);
690     testMapBuilder = parentBuilder.getOptionalMessageBuilder();
691     testMapBuilder.setRepeatedField(intMapField, 0, entryBuilder.getRepeatedField(intMapField, 0));
692 
693     // Should be able to observe the change.
694     message = parentBuilder.build();
695     assertEquals(4, message.getOptionalMessage().getInt32ToInt32Field().get(1).intValue());
696 
697     // Clear the nested builder.
698     testMapBuilder = parentBuilder.getOptionalMessageBuilder();
699     testMapBuilder.clearField(intMapField);
700 
701     // Should be able to observe the change.
702     message = parentBuilder.build();
703     assertEquals(0, message.getOptionalMessage().getInt32ToInt32Field().size());
704   }
705 
706   // The following methods are used to test reflection API.
707 
f(String name)708   private static FieldDescriptor f(String name) {
709     return TestMap.getDescriptor().findFieldByName(name);
710   }
711 
getFieldValue(Message mapEntry, String name)712   private static Object getFieldValue(Message mapEntry, String name) {
713     FieldDescriptor field = mapEntry.getDescriptorForType().findFieldByName(name);
714     return mapEntry.getField(field);
715   }
716 
setFieldValue( Message.Builder mapEntry, String name, Object value)717   private static Message.Builder setFieldValue(
718       Message.Builder mapEntry, String name, Object value) {
719     FieldDescriptor field = mapEntry.getDescriptorForType().findFieldByName(name);
720     mapEntry.setField(field, value);
721     return mapEntry;
722   }
723 
assertHasMapValues(Message message, String name, Map<?, ?> values)724   private static void assertHasMapValues(Message message, String name, Map<?, ?> values) {
725     FieldDescriptor field = f(name);
726     for (Object entry : (List<?>) message.getField(field)) {
727       Message mapEntry = (Message) entry;
728       Object key = getFieldValue(mapEntry, "key");
729       Object value = getFieldValue(mapEntry, "value");
730       assertTrue(values.containsKey(key));
731       assertEquals(value, values.get(key));
732     }
733     assertEquals(values.size(), message.getRepeatedFieldCount(field));
734     for (int i = 0; i < message.getRepeatedFieldCount(field); i++) {
735       Message mapEntry = (Message) message.getRepeatedField(field, i);
736       Object key = getFieldValue(mapEntry, "key");
737       Object value = getFieldValue(mapEntry, "value");
738       assertTrue(values.containsKey(key));
739       assertEquals(value, values.get(key));
740     }
741   }
742 
newMapEntry(Message.Builder builder, String name, K key, V value)743   private static <K, V> Message newMapEntry(Message.Builder builder, String name, K key, V value) {
744     FieldDescriptor field = builder.getDescriptorForType().findFieldByName(name);
745     Message.Builder entryBuilder = builder.newBuilderForField(field);
746     FieldDescriptor keyField = entryBuilder.getDescriptorForType().findFieldByName("key");
747     FieldDescriptor valueField = entryBuilder.getDescriptorForType().findFieldByName("value");
748     entryBuilder.setField(keyField, key);
749     entryBuilder.setField(valueField, value);
750     return entryBuilder.build();
751   }
752 
setMapValues(Message.Builder builder, String name, Map<?, ?> values)753   private static void setMapValues(Message.Builder builder, String name, Map<?, ?> values) {
754     List<Message> entryList = new ArrayList<>();
755     for (Map.Entry<?, ?> entry : values.entrySet()) {
756       entryList.add(newMapEntry(builder, name, entry.getKey(), entry.getValue()));
757     }
758     FieldDescriptor field = builder.getDescriptorForType().findFieldByName(name);
759     builder.setField(field, entryList);
760   }
761 
mapForValues(K key1, V value1, K key2, V value2)762   private static <K, V> Map<K, V> mapForValues(K key1, V value1, K key2, V value2) {
763     Map<K, V> map = new HashMap<>();
764     map.put(key1, value1);
765     map.put(key2, value2);
766     return map;
767   }
768 
testReflectionApi()769   public void testReflectionApi() throws Exception {
770     // In reflection API, map fields are just repeated message fields.
771     TestMap.Builder builder =
772         TestMap.newBuilder()
773             .putInt32ToInt32Field(1, 2)
774             .putInt32ToInt32Field(3, 4)
775             .putInt32ToMessageField(11, MessageValue.newBuilder().setValue(22).build())
776             .putInt32ToMessageField(33, MessageValue.newBuilder().setValue(44).build());
777     TestMap message = builder.build();
778 
779     // Test getField(), getRepeatedFieldCount(), getRepeatedField().
780     assertHasMapValues(message, "int32_to_int32_field", mapForValues(1, 2, 3, 4));
781     assertHasMapValues(
782         message,
783         "int32_to_message_field",
784         mapForValues(
785             11, MessageValue.newBuilder().setValue(22).build(),
786             33, MessageValue.newBuilder().setValue(44).build()));
787 
788     // Test clearField()
789     builder.clearField(f("int32_to_int32_field"));
790     builder.clearField(f("int32_to_message_field"));
791     message = builder.build();
792     assertEquals(0, message.getInt32ToInt32Field().size());
793     assertEquals(0, message.getInt32ToMessageField().size());
794 
795     // Test setField()
796     setMapValues(builder, "int32_to_int32_field", mapForValues(11, 22, 33, 44));
797     setMapValues(
798         builder,
799         "int32_to_message_field",
800         mapForValues(
801             111, MessageValue.newBuilder().setValue(222).build(),
802             333, MessageValue.newBuilder().setValue(444).build()));
803     message = builder.build();
804     assertEquals(22, message.getInt32ToInt32Field().get(11).intValue());
805     assertEquals(44, message.getInt32ToInt32Field().get(33).intValue());
806     assertEquals(222, message.getInt32ToMessageField().get(111).getValue());
807     assertEquals(444, message.getInt32ToMessageField().get(333).getValue());
808 
809     // Test addRepeatedField
810     builder.addRepeatedField(
811         f("int32_to_int32_field"), newMapEntry(builder, "int32_to_int32_field", 55, 66));
812     builder.addRepeatedField(
813         f("int32_to_message_field"),
814         newMapEntry(
815             builder,
816             "int32_to_message_field",
817             555,
818             MessageValue.newBuilder().setValue(666).build()));
819     message = builder.build();
820     assertEquals(66, message.getInt32ToInt32Field().get(55).intValue());
821     assertEquals(666, message.getInt32ToMessageField().get(555).getValue());
822 
823     // Test addRepeatedField (overriding existing values)
824     builder.addRepeatedField(
825         f("int32_to_int32_field"), newMapEntry(builder, "int32_to_int32_field", 55, 55));
826     builder.addRepeatedField(
827         f("int32_to_message_field"),
828         newMapEntry(
829             builder,
830             "int32_to_message_field",
831             555,
832             MessageValue.newBuilder().setValue(555).build()));
833     message = builder.build();
834     assertEquals(55, message.getInt32ToInt32Field().get(55).intValue());
835     assertEquals(555, message.getInt32ToMessageField().get(555).getValue());
836 
837     // Test setRepeatedField
838     for (int i = 0; i < builder.getRepeatedFieldCount(f("int32_to_int32_field")); i++) {
839       Message mapEntry = (Message) builder.getRepeatedField(f("int32_to_int32_field"), i);
840       int oldKey = ((Integer) getFieldValue(mapEntry, "key")).intValue();
841       int oldValue = ((Integer) getFieldValue(mapEntry, "value")).intValue();
842       // Swap key with value for each entry.
843       Message.Builder mapEntryBuilder = mapEntry.toBuilder();
844       setFieldValue(mapEntryBuilder, "key", oldValue);
845       setFieldValue(mapEntryBuilder, "value", oldKey);
846       builder.setRepeatedField(f("int32_to_int32_field"), i, mapEntryBuilder.build());
847     }
848     message = builder.build();
849     assertEquals(11, message.getInt32ToInt32Field().get(22).intValue());
850     assertEquals(33, message.getInt32ToInt32Field().get(44).intValue());
851     assertEquals(55, message.getInt32ToInt32Field().get(55).intValue());
852   }
853 
854   // See additional coverage in TextFormatTest.java.
testTextFormat()855   public void testTextFormat() throws Exception {
856     TestMap.Builder builder = TestMap.newBuilder();
857     setMapValuesUsingAccessors(builder);
858     TestMap message = builder.build();
859 
860     String textData = TextFormat.printer().printToString(message);
861 
862     builder = TestMap.newBuilder();
863     TextFormat.merge(textData, builder);
864     message = builder.build();
865 
866     assertMapValuesSet(message);
867   }
868 
testDynamicMessage()869   public void testDynamicMessage() throws Exception {
870     TestMap.Builder builder = TestMap.newBuilder();
871     setMapValuesUsingAccessors(builder);
872     TestMap message = builder.build();
873 
874     Message dynamicDefaultInstance = DynamicMessage.getDefaultInstance(TestMap.getDescriptor());
875     Message dynamicMessage =
876         dynamicDefaultInstance.newBuilderForType().mergeFrom(message.toByteString()).build();
877 
878     assertEquals(message, dynamicMessage);
879     assertEquals(message.hashCode(), dynamicMessage.hashCode());
880   }
881 
882   // Check that DynamicMessage handles map field serialization the same way as generated code
883   // regarding unset key and value field in a map entry.
testDynamicMessageUnsetKeyAndValue()884   public void testDynamicMessageUnsetKeyAndValue() throws Exception {
885     FieldDescriptor field = f("int32_to_int32_field");
886 
887     Message dynamicDefaultInstance = DynamicMessage.getDefaultInstance(TestMap.getDescriptor());
888     Message.Builder builder = dynamicDefaultInstance.newBuilderForType();
889     // Add an entry without key and value.
890     builder.addRepeatedField(field, builder.newBuilderForField(field).build());
891     Message message = builder.build();
892     ByteString bytes = message.toByteString();
893     // Parse it back to the same generated type.
894     Message generatedMessage = TestMap.parseFrom(bytes);
895     // Assert the serialized bytes are equivalent.
896     assertEquals(generatedMessage.toByteString(), bytes);
897   }
898 
testReflectionEqualsAndHashCode()899   public void testReflectionEqualsAndHashCode() throws Exception {
900     // Test that generated equals() and hashCode() will disregard the order
901     // of map entries when comparing/hashing map fields.
902 
903     // We use DynamicMessage to test reflection based equals()/hashCode().
904     Message dynamicDefaultInstance = DynamicMessage.getDefaultInstance(TestMap.getDescriptor());
905     FieldDescriptor field = f("int32_to_int32_field");
906 
907     Message.Builder b1 = dynamicDefaultInstance.newBuilderForType();
908     b1.addRepeatedField(field, newMapEntry(b1, "int32_to_int32_field", 1, 2));
909     b1.addRepeatedField(field, newMapEntry(b1, "int32_to_int32_field", 3, 4));
910     b1.addRepeatedField(field, newMapEntry(b1, "int32_to_int32_field", 5, 6));
911     Message m1 = b1.build();
912 
913     Message.Builder b2 = dynamicDefaultInstance.newBuilderForType();
914     b2.addRepeatedField(field, newMapEntry(b2, "int32_to_int32_field", 5, 6));
915     b2.addRepeatedField(field, newMapEntry(b2, "int32_to_int32_field", 1, 2));
916     b2.addRepeatedField(field, newMapEntry(b2, "int32_to_int32_field", 3, 4));
917     Message m2 = b2.build();
918 
919     assertEquals(m1, m2);
920     assertEquals(m1.hashCode(), m2.hashCode());
921 
922     // Make sure we did compare map fields.
923     b2.setRepeatedField(field, 0, newMapEntry(b1, "int32_to_int32_field", 0, 0));
924     m2 = b2.build();
925     assertFalse(m1.equals(m2));
926     // Don't check m1.hashCode() != m2.hashCode() because it's not guaranteed
927     // to be different.
928   }
929 
testUnknownEnumValues()930   public void testUnknownEnumValues() throws Exception {
931     TestMap.Builder builder =
932         TestMap.newBuilder()
933             .putAllInt32ToEnumFieldValue(
934                 newMap(
935                     0, 0,
936                     1, 1,
937                     2, 1000)); // unknown value.
938     TestMap message = builder.build();
939 
940     assertEquals(TestMap.EnumValue.FOO, message.getInt32ToEnumField().get(0));
941     assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(1));
942     assertEquals(TestMap.EnumValue.UNRECOGNIZED, message.getInt32ToEnumField().get(2));
943     assertEquals(1000, message.getInt32ToEnumFieldValue().get(2).intValue());
944 
945     // Unknown enum values should be preserved after:
946     //   1. Serialization and parsing.
947     //   2. toBuild().
948     //   3. mergeFrom().
949     message = TestMap.parseFrom(message.toByteString());
950     assertEquals(1000, message.getInt32ToEnumFieldValue().get(2).intValue());
951     builder = message.toBuilder();
952     assertEquals(1000, builder.getInt32ToEnumFieldValue().get(2).intValue());
953     builder = TestMap.newBuilder().mergeFrom(message);
954     assertEquals(1000, builder.getInt32ToEnumFieldValue().get(2).intValue());
955 
956     // hashCode()/equals() should take unknown enum values into account.
957     builder.putAllInt32ToEnumFieldValue(newMap(2, 1001));
958     TestMap message2 = builder.build();
959     assertFalse(message.hashCode() == message2.hashCode());
960     assertFalse(message.equals(message2));
961     // Unknown values will be converted to UNRECOGNIZED so the resulted enum map
962     // should be the same.
963     assertEquals(message2.getInt32ToEnumField(), message.getInt32ToEnumField());
964   }
965 
testUnknownEnumValuesInReflectionApi()966   public void testUnknownEnumValuesInReflectionApi() throws Exception {
967     Descriptor descriptor = TestMap.getDescriptor();
968     EnumDescriptor enumDescriptor = TestMap.EnumValue.getDescriptor();
969     FieldDescriptor field = descriptor.findFieldByName("int32_to_enum_field");
970 
971     Map<Integer, Integer> data =
972         newMap(
973             0, 0,
974             1, 1,
975             2, 1000); // unknown value
976 
977     TestMap.Builder builder = TestMap.newBuilder().putAllInt32ToEnumFieldValue(data);
978 
979     // Try to read unknown enum values using reflection API.
980     for (int i = 0; i < builder.getRepeatedFieldCount(field); i++) {
981       Message mapEntry = (Message) builder.getRepeatedField(field, i);
982       int key = ((Integer) getFieldValue(mapEntry, "key")).intValue();
983       int value = ((EnumValueDescriptor) getFieldValue(mapEntry, "value")).getNumber();
984       assertEquals(data.get(key).intValue(), value);
985       Message.Builder mapEntryBuilder = mapEntry.toBuilder();
986       // Increase the value by 1.
987       setFieldValue(
988           mapEntryBuilder, "value", enumDescriptor.findValueByNumberCreatingIfUnknown(value + 1));
989       builder.setRepeatedField(field, i, mapEntryBuilder.build());
990     }
991 
992     // Verify that enum values have been successfully updated.
993     TestMap message = builder.build();
994     for (Map.Entry<Integer, Integer> entry : message.getInt32ToEnumFieldValue().entrySet()) {
995       assertEquals(data.get(entry.getKey()) + 1, entry.getValue().intValue());
996     }
997   }
998 
testIterationOrder()999   public void testIterationOrder() throws Exception {
1000     TestMap.Builder builder = TestMap.newBuilder();
1001     setMapValuesUsingAccessors(builder);
1002     TestMap message = builder.build();
1003 
1004     assertEquals(
1005         Arrays.asList("1", "2", "3"), new ArrayList<>(message.getStringToInt32Field().keySet()));
1006   }
1007 
testGetMap()1008   public void testGetMap() {
1009     TestMap.Builder builder = TestMap.newBuilder();
1010     setMapValuesUsingAccessors(builder);
1011     TestMap message = builder.build();
1012     assertEquals(message.getStringToInt32Field(), message.getStringToInt32FieldMap());
1013     assertEquals(message.getInt32ToBytesField(), message.getInt32ToBytesFieldMap());
1014     assertEquals(message.getInt32ToEnumField(), message.getInt32ToEnumFieldMap());
1015     assertEquals(message.getInt32ToEnumFieldValue(), message.getInt32ToEnumFieldValueMap());
1016     assertEquals(message.getInt32ToMessageField(), message.getInt32ToMessageFieldMap());
1017   }
1018 
testContains()1019   public void testContains() {
1020     TestMap.Builder builder = TestMap.newBuilder();
1021     setMapValuesUsingAccessors(builder);
1022     assertMapContainsSetValues(builder);
1023     assertMapContainsSetValues(builder.build());
1024   }
1025 
assertMapContainsSetValues(TestMapOrBuilder testMapOrBuilder)1026   private void assertMapContainsSetValues(TestMapOrBuilder testMapOrBuilder) {
1027     assertTrue(testMapOrBuilder.containsInt32ToInt32Field(1));
1028     assertTrue(testMapOrBuilder.containsInt32ToInt32Field(2));
1029     assertTrue(testMapOrBuilder.containsInt32ToInt32Field(3));
1030     assertFalse(testMapOrBuilder.containsInt32ToInt32Field(-1));
1031 
1032     assertTrue(testMapOrBuilder.containsInt32ToStringField(1));
1033     assertTrue(testMapOrBuilder.containsInt32ToStringField(2));
1034     assertTrue(testMapOrBuilder.containsInt32ToStringField(3));
1035     assertFalse(testMapOrBuilder.containsInt32ToStringField(-1));
1036 
1037     assertTrue(testMapOrBuilder.containsInt32ToBytesField(1));
1038     assertTrue(testMapOrBuilder.containsInt32ToBytesField(2));
1039     assertTrue(testMapOrBuilder.containsInt32ToBytesField(3));
1040     assertFalse(testMapOrBuilder.containsInt32ToBytesField(-1));
1041 
1042     assertTrue(testMapOrBuilder.containsInt32ToEnumField(1));
1043     assertTrue(testMapOrBuilder.containsInt32ToEnumField(2));
1044     assertTrue(testMapOrBuilder.containsInt32ToEnumField(3));
1045     assertFalse(testMapOrBuilder.containsInt32ToEnumField(-1));
1046 
1047     assertTrue(testMapOrBuilder.containsInt32ToMessageField(1));
1048     assertTrue(testMapOrBuilder.containsInt32ToMessageField(2));
1049     assertTrue(testMapOrBuilder.containsInt32ToMessageField(3));
1050     assertFalse(testMapOrBuilder.containsInt32ToMessageField(-1));
1051 
1052     assertTrue(testMapOrBuilder.containsStringToInt32Field("1"));
1053     assertTrue(testMapOrBuilder.containsStringToInt32Field("2"));
1054     assertTrue(testMapOrBuilder.containsStringToInt32Field("3"));
1055     assertFalse(testMapOrBuilder.containsStringToInt32Field("-1"));
1056   }
1057 
testCount()1058   public void testCount() {
1059     TestMap.Builder builder = TestMap.newBuilder();
1060     assertMapCounts(0, builder);
1061 
1062     setMapValuesUsingAccessors(builder);
1063     assertMapCounts(3, builder);
1064 
1065     TestMap message = builder.build();
1066     assertMapCounts(3, message);
1067 
1068     builder = message.toBuilder().putInt32ToInt32Field(4, 44);
1069     assertEquals(4, builder.getInt32ToInt32FieldCount());
1070     assertEquals(4, builder.build().getInt32ToInt32FieldCount());
1071 
1072     // already present - should be unchanged
1073     builder.putInt32ToInt32Field(4, 44);
1074     assertEquals(4, builder.getInt32ToInt32FieldCount());
1075   }
1076 
assertMapCounts(int expectedCount, TestMapOrBuilder testMapOrBuilder)1077   private void assertMapCounts(int expectedCount, TestMapOrBuilder testMapOrBuilder) {
1078     assertEquals(expectedCount, testMapOrBuilder.getInt32ToInt32FieldCount());
1079     assertEquals(expectedCount, testMapOrBuilder.getInt32ToStringFieldCount());
1080     assertEquals(expectedCount, testMapOrBuilder.getInt32ToBytesFieldCount());
1081     assertEquals(expectedCount, testMapOrBuilder.getInt32ToEnumFieldCount());
1082     assertEquals(expectedCount, testMapOrBuilder.getInt32ToMessageFieldCount());
1083     assertEquals(expectedCount, testMapOrBuilder.getStringToInt32FieldCount());
1084   }
1085 
testGetOrDefault()1086   public void testGetOrDefault() {
1087     TestMap.Builder builder = TestMap.newBuilder();
1088     assertMapCounts(0, builder);
1089     setMapValuesUsingAccessors(builder);
1090     doTestGetOrDefault(builder);
1091     doTestGetOrDefault(builder.build());
1092   }
1093 
doTestGetOrDefault(TestMapOrBuilder testMapOrBuilder)1094   public void doTestGetOrDefault(TestMapOrBuilder testMapOrBuilder) {
1095     assertEquals(11, testMapOrBuilder.getInt32ToInt32FieldOrDefault(1, -11));
1096     assertEquals(-11, testMapOrBuilder.getInt32ToInt32FieldOrDefault(-1, -11));
1097 
1098     assertEquals("11", testMapOrBuilder.getInt32ToStringFieldOrDefault(1, "-11"));
1099     assertNull("-11", testMapOrBuilder.getInt32ToStringFieldOrDefault(-1, null));
1100 
1101     assertEquals(TestUtil.toBytes("11"), testMapOrBuilder.getInt32ToBytesFieldOrDefault(1, null));
1102     assertNull(testMapOrBuilder.getInt32ToBytesFieldOrDefault(-1, null));
1103 
1104     assertEquals(TestMap.EnumValue.FOO, testMapOrBuilder.getInt32ToEnumFieldOrDefault(1, null));
1105     assertNull(testMapOrBuilder.getInt32ToEnumFieldOrDefault(-1, null));
1106 
1107     assertEquals(
1108         TestMap.EnumValue.BAR.getNumber(),
1109         testMapOrBuilder.getInt32ToEnumFieldValueOrDefault(2, -1));
1110     assertEquals(-1, testMapOrBuilder.getInt32ToEnumFieldValueOrDefault(-1000, -1));
1111 
1112     assertEquals(
1113         MessageValue.newBuilder().setValue(11).build(),
1114         testMapOrBuilder.getInt32ToMessageFieldOrDefault(1, null));
1115     assertNull(testMapOrBuilder.getInt32ToMessageFieldOrDefault(-1, null));
1116 
1117     assertEquals(11, testMapOrBuilder.getStringToInt32FieldOrDefault("1", -11));
1118     assertEquals(-11, testMapOrBuilder.getStringToInt32FieldOrDefault("-1", -11));
1119 
1120     try {
1121       testMapOrBuilder.getStringToInt32FieldOrDefault(null, -11);
1122       fail();
1123     } catch (NullPointerException e) {
1124       // expected
1125     }
1126   }
1127 
testGetOrThrow()1128   public void testGetOrThrow() {
1129     TestMap.Builder builder = TestMap.newBuilder();
1130     assertMapCounts(0, builder);
1131     setMapValuesUsingAccessors(builder);
1132     doTestGetOrDefault(builder);
1133     doTestGetOrDefault(builder.build());
1134   }
1135 
doTestGetOrThrow(TestMapOrBuilder testMapOrBuilder)1136   public void doTestGetOrThrow(TestMapOrBuilder testMapOrBuilder) {
1137     assertEquals(11, testMapOrBuilder.getInt32ToInt32FieldOrThrow(1));
1138     try {
1139       testMapOrBuilder.getInt32ToInt32FieldOrThrow(-1);
1140       fail();
1141     } catch (IllegalArgumentException e) {
1142       // expected
1143     }
1144 
1145     assertEquals("11", testMapOrBuilder.getInt32ToStringFieldOrThrow(1));
1146 
1147     try {
1148       testMapOrBuilder.getInt32ToStringFieldOrThrow(-1);
1149       fail();
1150     } catch (IllegalArgumentException e) {
1151       // expected
1152     }
1153 
1154     assertEquals(TestUtil.toBytes("11"), testMapOrBuilder.getInt32ToBytesFieldOrThrow(1));
1155 
1156     try {
1157       testMapOrBuilder.getInt32ToBytesFieldOrThrow(-1);
1158       fail();
1159     } catch (IllegalArgumentException e) {
1160       // expected
1161     }
1162 
1163     assertEquals(TestMap.EnumValue.FOO, testMapOrBuilder.getInt32ToEnumFieldOrThrow(1));
1164     try {
1165       testMapOrBuilder.getInt32ToEnumFieldOrThrow(-1);
1166       fail();
1167     } catch (IllegalArgumentException e) {
1168       // expected
1169     }
1170 
1171     assertEquals(
1172         TestMap.EnumValue.BAR.getNumber(), testMapOrBuilder.getInt32ToEnumFieldValueOrThrow(2));
1173     try {
1174       testMapOrBuilder.getInt32ToEnumFieldValueOrThrow(-1);
1175       fail();
1176     } catch (IllegalArgumentException e) {
1177       // expected
1178     }
1179 
1180     assertEquals(
1181         MessageValue.newBuilder().setValue(11).build(),
1182         testMapOrBuilder.getInt32ToMessageFieldOrThrow(1));
1183     try {
1184       testMapOrBuilder.getInt32ToMessageFieldOrThrow(-1);
1185       fail();
1186     } catch (IllegalArgumentException e) {
1187       // expected
1188     }
1189 
1190     assertEquals(11, testMapOrBuilder.getStringToInt32FieldOrThrow("1"));
1191     try {
1192       testMapOrBuilder.getStringToInt32FieldOrThrow("-1");
1193       fail();
1194     } catch (IllegalArgumentException e) {
1195       // expected
1196     }
1197 
1198     try {
1199       testMapOrBuilder.getStringToInt32FieldOrThrow(null);
1200       fail();
1201     } catch (NullPointerException e) {
1202       // expected
1203     }
1204   }
1205 
testPut()1206   public void testPut() {
1207     TestMap.Builder builder = TestMap.newBuilder();
1208     builder.putInt32ToInt32Field(1, 11);
1209     assertEquals(11, builder.getInt32ToInt32FieldOrThrow(1));
1210 
1211     builder.putInt32ToStringField(1, "a");
1212     assertEquals("a", builder.getInt32ToStringFieldOrThrow(1));
1213     try {
1214       builder.putInt32ToStringField(1, null);
1215       fail();
1216     } catch (NullPointerException e) {
1217       // expected
1218     }
1219 
1220     builder.putInt32ToBytesField(1, TestUtil.toBytes("11"));
1221     assertEquals(TestUtil.toBytes("11"), builder.getInt32ToBytesFieldOrThrow(1));
1222     try {
1223       builder.putInt32ToBytesField(1, null);
1224       fail();
1225     } catch (NullPointerException e) {
1226       // expected
1227     }
1228 
1229     builder.putInt32ToEnumField(1, TestMap.EnumValue.FOO);
1230     assertEquals(TestMap.EnumValue.FOO, builder.getInt32ToEnumFieldOrThrow(1));
1231     try {
1232       builder.putInt32ToEnumField(1, null);
1233       fail();
1234     } catch (NullPointerException e) {
1235       // expected
1236     }
1237 
1238     builder.putInt32ToEnumFieldValue(1, TestMap.EnumValue.BAR.getNumber());
1239     assertEquals(TestMap.EnumValue.BAR.getNumber(), builder.getInt32ToEnumFieldValueOrThrow(1));
1240     builder.putInt32ToEnumFieldValue(1, -1);
1241     assertEquals(-1, builder.getInt32ToEnumFieldValueOrThrow(1));
1242     assertEquals(TestMap.EnumValue.UNRECOGNIZED, builder.getInt32ToEnumFieldOrThrow(1));
1243 
1244     builder.putStringToInt32Field("a", 1);
1245     assertEquals(1, builder.getStringToInt32FieldOrThrow("a"));
1246     try {
1247       builder.putStringToInt32Field(null, -1);
1248     } catch (NullPointerException e) {
1249       // expected
1250     }
1251   }
1252 
testRemove()1253   public void testRemove() {
1254     TestMap.Builder builder = TestMap.newBuilder();
1255     setMapValuesUsingAccessors(builder);
1256     assertEquals(11, builder.getInt32ToInt32FieldOrThrow(1));
1257     for (int times = 0; times < 2; times++) {
1258       builder.removeInt32ToInt32Field(1);
1259       assertEquals(-1, builder.getInt32ToInt32FieldOrDefault(1, -1));
1260     }
1261 
1262     assertEquals("11", builder.getInt32ToStringFieldOrThrow(1));
1263     for (int times = 0; times < 2; times++) {
1264       builder.removeInt32ToStringField(1);
1265       assertNull(builder.getInt32ToStringFieldOrDefault(1, null));
1266     }
1267 
1268     assertEquals(TestUtil.toBytes("11"), builder.getInt32ToBytesFieldOrThrow(1));
1269     for (int times = 0; times < 2; times++) {
1270       builder.removeInt32ToBytesField(1);
1271       assertNull(builder.getInt32ToBytesFieldOrDefault(1, null));
1272     }
1273 
1274     assertEquals(TestMap.EnumValue.FOO, builder.getInt32ToEnumFieldOrThrow(1));
1275     for (int times = 0; times < 2; times++) {
1276       builder.removeInt32ToEnumField(1);
1277       assertNull(builder.getInt32ToEnumFieldOrDefault(1, null));
1278     }
1279 
1280     assertEquals(11, builder.getStringToInt32FieldOrThrow("1"));
1281     for (int times = 0; times < 2; times++) {
1282       builder.removeStringToInt32Field("1");
1283       assertEquals(-1, builder.getStringToInt32FieldOrDefault("1", -1));
1284     }
1285 
1286     try {
1287       builder.removeStringToInt32Field(null);
1288       fail();
1289     } catch (NullPointerException e) {
1290       // expected
1291     }
1292   }
1293 
testReservedWordsFieldNames()1294   public void testReservedWordsFieldNames() {
1295     ReservedAsMapField.newBuilder().build();
1296     ReservedAsMapFieldWithEnumValue.newBuilder().build();
1297   }
1298 
testDeterministicSerialziation()1299   public void testDeterministicSerialziation() throws Exception {
1300     TestMap.Builder builder = TestMap.newBuilder();
1301     // int32->int32
1302     builder.putInt32ToInt32Field(5, 1);
1303     builder.putInt32ToInt32Field(1, 1);
1304     builder.putInt32ToInt32Field(4, 1);
1305     builder.putInt32ToInt32Field(-2, 1);
1306     builder.putInt32ToInt32Field(0, 1);
1307 
1308     // uint32->int32
1309     builder.putUint32ToInt32Field(5, 1);
1310     builder.putUint32ToInt32Field(1, 1);
1311     builder.putUint32ToInt32Field(4, 1);
1312     builder.putUint32ToInt32Field(-2, 1);
1313     builder.putUint32ToInt32Field(0, 1);
1314 
1315     // int64->int32
1316     builder.putInt64ToInt32Field(5L, 1);
1317     builder.putInt64ToInt32Field(1L, 1);
1318     builder.putInt64ToInt32Field(4L, 1);
1319     builder.putInt64ToInt32Field(-2L, 1);
1320     builder.putInt64ToInt32Field(0L, 1);
1321 
1322     // string->int32
1323     builder.putStringToInt32Field("baz", 1);
1324     builder.putStringToInt32Field("foo", 1);
1325     builder.putStringToInt32Field("bar", 1);
1326     builder.putStringToInt32Field("", 1);
1327     builder.putStringToInt32Field("hello", 1);
1328     builder.putStringToInt32Field("world", 1);
1329 
1330     TestMap message = builder.build();
1331     byte[] serialized = new byte[message.getSerializedSize()];
1332     CodedOutputStream output = CodedOutputStream.newInstance(serialized);
1333     output.useDeterministicSerialization();
1334     message.writeTo(output);
1335     output.flush();
1336 
1337     CodedInputStream input = CodedInputStream.newInstance(serialized);
1338     List<Integer> int32Keys = new ArrayList<>();
1339     List<Integer> uint32Keys = new ArrayList<>();
1340     List<Long> int64Keys = new ArrayList<>();
1341     List<String> stringKeys = new ArrayList<>();
1342     int tag;
1343     while (true) {
1344       tag = input.readTag();
1345       if (tag == 0) {
1346         break;
1347       }
1348       int length = input.readRawVarint32();
1349       int oldLimit = input.pushLimit(length);
1350       switch (WireFormat.getTagFieldNumber(tag)) {
1351         case TestMap.STRING_TO_INT32_FIELD_FIELD_NUMBER:
1352           stringKeys.add(readMapStringKey(input));
1353           break;
1354         case TestMap.INT32_TO_INT32_FIELD_FIELD_NUMBER:
1355           int32Keys.add(readMapIntegerKey(input));
1356           break;
1357         case TestMap.UINT32_TO_INT32_FIELD_FIELD_NUMBER:
1358           uint32Keys.add(readMapIntegerKey(input));
1359           break;
1360         case TestMap.INT64_TO_INT32_FIELD_FIELD_NUMBER:
1361           int64Keys.add(readMapLongKey(input));
1362           break;
1363         default:
1364           fail("Unexpected fields.");
1365       }
1366       input.popLimit(oldLimit);
1367     }
1368     assertEquals(Arrays.asList(-2, 0, 1, 4, 5), int32Keys);
1369     assertEquals(Arrays.asList(-2, 0, 1, 4, 5), uint32Keys);
1370     assertEquals(Arrays.asList(-2L, 0L, 1L, 4L, 5L), int64Keys);
1371     assertEquals(Arrays.asList("", "bar", "baz", "foo", "hello", "world"), stringKeys);
1372   }
1373 
testInitFromPartialDynamicMessage()1374   public void testInitFromPartialDynamicMessage() {
1375     FieldDescriptor fieldDescriptor =
1376         TestMap.getDescriptor().findFieldByNumber(TestMap.INT32_TO_MESSAGE_FIELD_FIELD_NUMBER);
1377     Descriptor mapEntryType = fieldDescriptor.getMessageType();
1378     FieldDescriptor keyField = mapEntryType.findFieldByNumber(1);
1379     FieldDescriptor valueField = mapEntryType.findFieldByNumber(2);
1380     DynamicMessage dynamicMessage =
1381         DynamicMessage.newBuilder(TestMap.getDescriptor())
1382             .addRepeatedField(
1383                 fieldDescriptor,
1384                 DynamicMessage.newBuilder(mapEntryType)
1385                     .setField(keyField, 10)
1386                     .setField(valueField, TestMap.MessageValue.newBuilder().setValue(10).build())
1387                     .build())
1388             .build();
1389     TestMap message = TestMap.newBuilder().mergeFrom(dynamicMessage).build();
1390     assertEquals(
1391         TestMap.MessageValue.newBuilder().setValue(10).build(),
1392         message.getInt32ToMessageFieldMap().get(10));
1393   }
1394 
testInitFromFullyDynamicMessage()1395   public void testInitFromFullyDynamicMessage() {
1396     FieldDescriptor fieldDescriptor =
1397         TestMap.getDescriptor().findFieldByNumber(TestMap.INT32_TO_MESSAGE_FIELD_FIELD_NUMBER);
1398     Descriptor mapEntryType = fieldDescriptor.getMessageType();
1399     FieldDescriptor keyField = mapEntryType.findFieldByNumber(1);
1400     FieldDescriptor valueField = mapEntryType.findFieldByNumber(2);
1401     DynamicMessage dynamicMessage =
1402         DynamicMessage.newBuilder(TestMap.getDescriptor())
1403             .addRepeatedField(
1404                 fieldDescriptor,
1405                 DynamicMessage.newBuilder(mapEntryType)
1406                     .setField(keyField, 10)
1407                     .setField(
1408                         valueField,
1409                         DynamicMessage.newBuilder(TestMap.MessageValue.getDescriptor())
1410                             .setField(
1411                                 TestMap.MessageValue.getDescriptor().findFieldByName("value"), 10)
1412                             .build())
1413                     .build())
1414             .build();
1415     TestMap message = TestMap.newBuilder().mergeFrom(dynamicMessage).build();
1416     assertEquals(
1417         TestMap.MessageValue.newBuilder().setValue(10).build(),
1418         message.getInt32ToMessageFieldMap().get(10));
1419   }
1420 
readMapIntegerKey(CodedInputStream input)1421   private int readMapIntegerKey(CodedInputStream input) throws IOException {
1422     int tag = input.readTag();
1423     assertEquals(WireFormat.makeTag(1, WireFormat.WIRETYPE_VARINT), tag);
1424     int ret = input.readInt32();
1425     // skip the value field.
1426     input.skipField(input.readTag());
1427     assertTrue(input.isAtEnd());
1428     return ret;
1429   }
1430 
readMapLongKey(CodedInputStream input)1431   private long readMapLongKey(CodedInputStream input) throws IOException {
1432     int tag = input.readTag();
1433     assertEquals(WireFormat.makeTag(1, WireFormat.WIRETYPE_VARINT), tag);
1434     long ret = input.readInt64();
1435     // skip the value field.
1436     input.skipField(input.readTag());
1437     assertTrue(input.isAtEnd());
1438     return ret;
1439   }
1440 
readMapStringKey(CodedInputStream input)1441   private String readMapStringKey(CodedInputStream input) throws IOException {
1442     int tag = input.readTag();
1443     assertEquals(WireFormat.makeTag(1, WireFormat.WIRETYPE_LENGTH_DELIMITED), tag);
1444     String ret = input.readString();
1445     // skip the value field.
1446     input.skipField(input.readTag());
1447     assertTrue(input.isAtEnd());
1448     return ret;
1449   }
1450 
newMap(K key1, V value1)1451   private static <K, V> Map<K, V> newMap(K key1, V value1) {
1452     Map<K, V> map = new HashMap<>();
1453     map.put(key1, value1);
1454     return map;
1455   }
1456 
newMap(K key1, V value1, K key2, V value2)1457   private static <K, V> Map<K, V> newMap(K key1, V value1, K key2, V value2) {
1458     Map<K, V> map = new HashMap<>();
1459     map.put(key1, value1);
1460     map.put(key2, value2);
1461     return map;
1462   }
1463 
newMap(K key1, V value1, K key2, V value2, K key3, V value3)1464   private static <K, V> Map<K, V> newMap(K key1, V value1, K key2, V value2, K key3, V value3) {
1465     Map<K, V> map = new HashMap<>();
1466     map.put(key1, value1);
1467     map.put(key2, value2);
1468     map.put(key3, value3);
1469     return map;
1470   }
1471 
testMap_withNulls()1472   public void testMap_withNulls() {
1473     TestMap.Builder builder = TestMap.newBuilder();
1474 
1475     try {
1476       builder.putStringToInt32Field(null, 3);
1477       fail();
1478     } catch (NullPointerException expected) {
1479     }
1480 
1481     try {
1482       builder.putAllStringToInt32Field(newMap(null, 3, "hi", 4));
1483       fail();
1484     } catch (NullPointerException expected) {
1485     }
1486 
1487     try {
1488       builder.putInt32ToMessageField(3, null);
1489       fail();
1490     } catch (NullPointerException expected) {
1491     }
1492 
1493     try {
1494       builder.putAllInt32ToMessageField(MapTest.<Integer, MessageValue>newMap(4, null, 5, null));
1495       fail();
1496     } catch (NullPointerException expected) {
1497     }
1498 
1499     try {
1500       builder.putAllInt32ToMessageField(null);
1501       fail();
1502     } catch (NullPointerException expected) {
1503     }
1504 
1505     assertArrayEquals(new byte[0], builder.build().toByteArray());
1506   }
1507 }
1508