• 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.getInt32ToInt32FieldMap())
126         .putAllInt32ToStringField(source.getInt32ToStringFieldMap())
127         .putAllInt32ToBytesField(source.getInt32ToBytesFieldMap())
128         .putAllInt32ToEnumField(source.getInt32ToEnumFieldMap())
129         .putAllInt32ToMessageField(source.getInt32ToMessageFieldMap())
130         .putAllStringToInt32Field(source.getStringToInt32FieldMap());
131   }
132 
assertMapValuesSet(TestMap message)133   private void assertMapValuesSet(TestMap message) {
134     assertEquals(3, message.getInt32ToInt32FieldMap().size());
135     assertEquals(11, message.getInt32ToInt32FieldMap().get(1).intValue());
136     assertEquals(22, message.getInt32ToInt32FieldMap().get(2).intValue());
137     assertEquals(33, message.getInt32ToInt32FieldMap().get(3).intValue());
138 
139     assertEquals(3, message.getInt32ToStringFieldMap().size());
140     assertEquals("11", message.getInt32ToStringFieldMap().get(1));
141     assertEquals("22", message.getInt32ToStringFieldMap().get(2));
142     assertEquals("33", message.getInt32ToStringFieldMap().get(3));
143 
144     assertEquals(3, message.getInt32ToBytesFieldMap().size());
145     assertEquals(TestUtil.toBytes("11"), message.getInt32ToBytesFieldMap().get(1));
146     assertEquals(TestUtil.toBytes("22"), message.getInt32ToBytesFieldMap().get(2));
147     assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesFieldMap().get(3));
148 
149     assertEquals(3, message.getInt32ToEnumFieldMap().size());
150     assertEquals(TestMap.EnumValue.FOO, message.getInt32ToEnumFieldMap().get(1));
151     assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumFieldMap().get(2));
152     assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumFieldMap().get(3));
153 
154     assertEquals(3, message.getInt32ToMessageFieldMap().size());
155     assertEquals(11, message.getInt32ToMessageFieldMap().get(1).getValue());
156     assertEquals(22, message.getInt32ToMessageFieldMap().get(2).getValue());
157     assertEquals(33, message.getInt32ToMessageFieldMap().get(3).getValue());
158 
159     assertEquals(3, message.getStringToInt32FieldMap().size());
160     assertEquals(11, message.getStringToInt32FieldMap().get("1").intValue());
161     assertEquals(22, message.getStringToInt32FieldMap().get("2").intValue());
162     assertEquals(33, message.getStringToInt32FieldMap().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.getInt32ToInt32FieldMap().size());
243     assertEquals(111, message.getInt32ToInt32FieldMap().get(1).intValue());
244     assertEquals(33, message.getInt32ToInt32FieldMap().get(3).intValue());
245     assertEquals(44, message.getInt32ToInt32FieldMap().get(4).intValue());
246 
247     assertEquals(3, message.getInt32ToStringFieldMap().size());
248     assertEquals("111", message.getInt32ToStringFieldMap().get(1));
249     assertEquals("33", message.getInt32ToStringFieldMap().get(3));
250     assertEquals("44", message.getInt32ToStringFieldMap().get(4));
251 
252     assertEquals(3, message.getInt32ToBytesFieldMap().size());
253     assertEquals(TestUtil.toBytes("111"), message.getInt32ToBytesFieldMap().get(1));
254     assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesFieldMap().get(3));
255     assertEquals(TestUtil.toBytes("44"), message.getInt32ToBytesFieldMap().get(4));
256 
257     assertEquals(3, message.getInt32ToEnumFieldMap().size());
258     assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumFieldMap().get(1));
259     assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumFieldMap().get(3));
260     assertEquals(TestMap.EnumValue.QUX, message.getInt32ToEnumFieldMap().get(4));
261 
262     assertEquals(3, message.getInt32ToMessageFieldMap().size());
263     assertEquals(111, message.getInt32ToMessageFieldMap().get(1).getValue());
264     assertEquals(33, message.getInt32ToMessageFieldMap().get(3).getValue());
265     assertEquals(44, message.getInt32ToMessageFieldMap().get(4).getValue());
266 
267     assertEquals(3, message.getStringToInt32FieldMap().size());
268     assertEquals(111, message.getStringToInt32FieldMap().get("1").intValue());
269     assertEquals(33, message.getStringToInt32FieldMap().get("3").intValue());
270     assertEquals(44, message.getStringToInt32FieldMap().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()
472             .putAllInt32ToEnumFieldValue(source.getInt32ToEnumFieldValueMap())
473             .build();
474 
475     assertEquals(0, destination.getInt32ToEnumFieldValueMap().get(0).intValue());
476     assertEquals(1, destination.getInt32ToEnumFieldValueMap().get(1).intValue());
477     assertEquals(1000, destination.getInt32ToEnumFieldValueMap().get(2).intValue());
478     assertEquals(3, destination.getInt32ToEnumFieldCount());
479   }
480 
testPutForUnknownEnumValues()481   public void testPutForUnknownEnumValues() throws Exception {
482     TestMap message =
483         TestMap.newBuilder()
484             .putInt32ToEnumFieldValue(0, 0)
485             .putInt32ToEnumFieldValue(1, 1)
486             .putInt32ToEnumFieldValue(2, 1000) // unknown value.
487             .build();
488     assertEquals(0, message.getInt32ToEnumFieldValueOrThrow(0));
489     assertEquals(1, message.getInt32ToEnumFieldValueOrThrow(1));
490     assertEquals(1000, message.getInt32ToEnumFieldValueOrThrow(2));
491     assertEquals(3, message.getInt32ToEnumFieldCount());
492   }
493 
testPutChecksNullKeysAndValues()494   public void testPutChecksNullKeysAndValues() throws Exception {
495     TestMap.Builder builder = TestMap.newBuilder();
496 
497     try {
498       builder.putInt32ToStringField(1, null);
499       fail();
500     } catch (NullPointerException e) {
501       // expected.
502     }
503 
504     try {
505       builder.putInt32ToBytesField(1, null);
506       fail();
507     } catch (NullPointerException e) {
508       // expected.
509     }
510 
511     try {
512       builder.putInt32ToEnumField(1, null);
513       fail();
514     } catch (NullPointerException e) {
515       // expected.
516     }
517 
518     try {
519       builder.putInt32ToMessageField(1, null);
520       fail();
521     } catch (NullPointerException e) {
522       // expected.
523     }
524 
525     try {
526       builder.putStringToInt32Field(null, 1);
527       fail();
528     } catch (NullPointerException e) {
529       // expected.
530     }
531   }
532 
testSerializeAndParse()533   public void testSerializeAndParse() throws Exception {
534     TestMap.Builder builder = TestMap.newBuilder();
535     setMapValuesUsingAccessors(builder);
536     TestMap message = builder.build();
537     assertEquals(message.getSerializedSize(), message.toByteString().size());
538     message = TestMap.parser().parseFrom(message.toByteString());
539     assertMapValuesSet(message);
540 
541     builder = message.toBuilder();
542     updateMapValuesUsingAccessors(builder);
543     message = builder.build();
544     assertEquals(message.getSerializedSize(), message.toByteString().size());
545     message = TestMap.parser().parseFrom(message.toByteString());
546     assertMapValuesUpdated(message);
547 
548     builder = message.toBuilder();
549     builder.clear();
550     message = builder.build();
551     assertEquals(message.getSerializedSize(), message.toByteString().size());
552     message = TestMap.parser().parseFrom(message.toByteString());
553     assertMapValuesCleared(message);
554   }
555 
tryParseTestMap(BizarroTestMap bizarroMap)556   private TestMap tryParseTestMap(BizarroTestMap bizarroMap) throws IOException {
557     ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
558     CodedOutputStream output = CodedOutputStream.newInstance(byteArrayOutputStream);
559     bizarroMap.writeTo(output);
560     output.flush();
561     return TestMap.parser().parseFrom(ByteString.copyFrom(byteArrayOutputStream.toByteArray()));
562   }
563 
testParseError()564   public void testParseError() throws Exception {
565     ByteString bytes = TestUtil.toBytes("SOME BYTES");
566     String stringKey = "a string key";
567 
568     TestMap map =
569         tryParseTestMap(BizarroTestMap.newBuilder().putInt32ToInt32Field(5, bytes).build());
570     assertEquals(0, map.getInt32ToInt32FieldOrDefault(5, -1));
571 
572     map = tryParseTestMap(BizarroTestMap.newBuilder().putInt32ToStringField(stringKey, 5).build());
573     assertEquals("", map.getInt32ToStringFieldOrDefault(0, null));
574 
575     map = tryParseTestMap(BizarroTestMap.newBuilder().putInt32ToBytesField(stringKey, 5).build());
576     assertEquals(map.getInt32ToBytesFieldOrDefault(0, null), ByteString.EMPTY);
577 
578     map =
579         tryParseTestMap(BizarroTestMap.newBuilder().putInt32ToEnumField(stringKey, bytes).build());
580     assertEquals(TestMap.EnumValue.FOO, map.getInt32ToEnumFieldOrDefault(0, null));
581 
582     try {
583       tryParseTestMap(BizarroTestMap.newBuilder().putInt32ToMessageField(stringKey, bytes).build());
584       fail();
585     } catch (InvalidProtocolBufferException expected) {
586       assertTrue(expected.getUnfinishedMessage() instanceof TestMap);
587       map = (TestMap) expected.getUnfinishedMessage();
588       assertTrue(map.getInt32ToMessageFieldMap().isEmpty());
589     }
590 
591     map =
592         tryParseTestMap(
593             BizarroTestMap.newBuilder().putStringToInt32Field(stringKey, bytes).build());
594     assertEquals(0, map.getStringToInt32FieldOrDefault(stringKey, -1));
595   }
596 
testMergeFrom()597   public void testMergeFrom() throws Exception {
598     TestMap.Builder builder = TestMap.newBuilder();
599     setMapValuesUsingAccessors(builder);
600     TestMap message = builder.build();
601 
602     TestMap.Builder other = TestMap.newBuilder();
603     other.mergeFrom(message);
604     assertMapValuesSet(other.build());
605   }
606 
testEqualsAndHashCode()607   public void testEqualsAndHashCode() throws Exception {
608     // Test that generated equals() and hashCode() will disregard the order
609     // of map entries when comparing/hashing map fields.
610 
611     // We can't control the order of elements in a HashMap. The best we can do
612     // here is to add elements in different order.
613     TestMap m1 =
614         TestMap.newBuilder()
615             .putInt32ToInt32Field(1, 2)
616             .putInt32ToInt32Field(3, 4)
617             .putInt32ToInt32Field(5, 6)
618             .build();
619 
620     TestMap.Builder b2 =
621         TestMap.newBuilder()
622             .putInt32ToInt32Field(5, 6)
623             .putInt32ToInt32Field(1, 2)
624             .putInt32ToInt32Field(3, 4);
625     TestMap m2 = b2.build();
626 
627     assertEquals(m1, m2);
628     assertEquals(m1.hashCode(), m2.hashCode());
629 
630     // Make sure we did compare map fields.
631     b2.putInt32ToInt32Field(1, 0);
632     m2 = b2.build();
633     assertFalse(m1.equals(m2));
634     // Don't check m1.hashCode() != m2.hashCode() because it's not guaranteed
635     // to be different.
636 
637     // Regression test for b/18549190: if a map is a subset of the other map,
638     // equals() should return false.
639     b2.removeInt32ToInt32Field(1);
640     m2 = b2.build();
641     assertFalse(m1.equals(m2));
642     assertFalse(m2.equals(m1));
643   }
644 
testNestedBuilderOnChangeEventPropagation()645   public void testNestedBuilderOnChangeEventPropagation() {
646     TestOnChangeEventPropagation.Builder parent = TestOnChangeEventPropagation.newBuilder();
647     parent.getOptionalMessageBuilder().putInt32ToInt32Field(1, 2);
648     TestOnChangeEventPropagation message = parent.build();
649     assertEquals(2, message.getOptionalMessage().getInt32ToInt32FieldMap().get(1).intValue());
650 
651     // Make a change using nested builder.
652     parent.getOptionalMessageBuilder().putInt32ToInt32Field(1, 3);
653 
654     // Should be able to observe the change.
655     message = parent.build();
656     assertEquals(3, message.getOptionalMessage().getInt32ToInt32FieldMap().get(1).intValue());
657 
658     // Make another change using mergeFrom()
659     TestMap other = TestMap.newBuilder().putInt32ToInt32Field(1, 4).build();
660     parent.getOptionalMessageBuilder().mergeFrom(other);
661 
662     // Should be able to observe the change.
663     message = parent.build();
664     assertEquals(4, message.getOptionalMessage().getInt32ToInt32FieldMap().get(1).intValue());
665 
666     // Make yet another change by clearing the nested builder.
667     parent.getOptionalMessageBuilder().clear();
668 
669     // Should be able to observe the change.
670     message = parent.build();
671     assertEquals(0, message.getOptionalMessage().getInt32ToInt32FieldMap().size());
672   }
673 
testNestedBuilderOnChangeEventPropagationReflection()674   public void testNestedBuilderOnChangeEventPropagationReflection() {
675     FieldDescriptor intMapField = f("int32_to_int32_field");
676     // Create an outer message builder with nested builder.
677     TestOnChangeEventPropagation.Builder parentBuilder = TestOnChangeEventPropagation.newBuilder();
678     TestMap.Builder testMapBuilder = parentBuilder.getOptionalMessageBuilder();
679 
680     // Create a map entry message.
681     TestMap.Builder entryBuilder = TestMap.newBuilder().putInt32ToInt32Field(1, 1);
682 
683     // Put the entry into the nested builder.
684     testMapBuilder.addRepeatedField(intMapField, entryBuilder.getRepeatedField(intMapField, 0));
685 
686     // Should be able to observe the change.
687     TestOnChangeEventPropagation message = parentBuilder.build();
688     assertEquals(1, message.getOptionalMessage().getInt32ToInt32FieldMap().size());
689 
690     // Change the entry value.
691     entryBuilder.putInt32ToInt32Field(1, 4);
692     testMapBuilder = parentBuilder.getOptionalMessageBuilder();
693     testMapBuilder.setRepeatedField(intMapField, 0, entryBuilder.getRepeatedField(intMapField, 0));
694 
695     // Should be able to observe the change.
696     message = parentBuilder.build();
697     assertEquals(4, message.getOptionalMessage().getInt32ToInt32FieldMap().get(1).intValue());
698 
699     // Clear the nested builder.
700     testMapBuilder = parentBuilder.getOptionalMessageBuilder();
701     testMapBuilder.clearField(intMapField);
702 
703     // Should be able to observe the change.
704     message = parentBuilder.build();
705     assertEquals(0, message.getOptionalMessage().getInt32ToInt32FieldMap().size());
706   }
707 
708   // The following methods are used to test reflection API.
709 
f(String name)710   private static FieldDescriptor f(String name) {
711     return TestMap.getDescriptor().findFieldByName(name);
712   }
713 
getFieldValue(Message mapEntry, String name)714   private static Object getFieldValue(Message mapEntry, String name) {
715     FieldDescriptor field = mapEntry.getDescriptorForType().findFieldByName(name);
716     return mapEntry.getField(field);
717   }
718 
setFieldValue( Message.Builder mapEntry, String name, Object value)719   private static Message.Builder setFieldValue(
720       Message.Builder mapEntry, String name, Object value) {
721     FieldDescriptor field = mapEntry.getDescriptorForType().findFieldByName(name);
722     mapEntry.setField(field, value);
723     return mapEntry;
724   }
725 
assertHasMapValues(Message message, String name, Map<?, ?> values)726   private static void assertHasMapValues(Message message, String name, Map<?, ?> values) {
727     FieldDescriptor field = f(name);
728     for (Object entry : (List<?>) message.getField(field)) {
729       Message mapEntry = (Message) entry;
730       Object key = getFieldValue(mapEntry, "key");
731       Object value = getFieldValue(mapEntry, "value");
732       assertTrue(values.containsKey(key));
733       assertEquals(value, values.get(key));
734     }
735     assertEquals(values.size(), message.getRepeatedFieldCount(field));
736     for (int i = 0; i < message.getRepeatedFieldCount(field); i++) {
737       Message mapEntry = (Message) message.getRepeatedField(field, i);
738       Object key = getFieldValue(mapEntry, "key");
739       Object value = getFieldValue(mapEntry, "value");
740       assertTrue(values.containsKey(key));
741       assertEquals(value, values.get(key));
742     }
743   }
744 
newMapEntry(Message.Builder builder, String name, K key, V value)745   private static <K, V> Message newMapEntry(Message.Builder builder, String name, K key, V value) {
746     FieldDescriptor field = builder.getDescriptorForType().findFieldByName(name);
747     Message.Builder entryBuilder = builder.newBuilderForField(field);
748     FieldDescriptor keyField = entryBuilder.getDescriptorForType().findFieldByName("key");
749     FieldDescriptor valueField = entryBuilder.getDescriptorForType().findFieldByName("value");
750     entryBuilder.setField(keyField, key);
751     entryBuilder.setField(valueField, value);
752     return entryBuilder.build();
753   }
754 
setMapValues(Message.Builder builder, String name, Map<?, ?> values)755   private static void setMapValues(Message.Builder builder, String name, Map<?, ?> values) {
756     List<Message> entryList = new ArrayList<>();
757     for (Map.Entry<?, ?> entry : values.entrySet()) {
758       entryList.add(newMapEntry(builder, name, entry.getKey(), entry.getValue()));
759     }
760     FieldDescriptor field = builder.getDescriptorForType().findFieldByName(name);
761     builder.setField(field, entryList);
762   }
763 
mapForValues(K key1, V value1, K key2, V value2)764   private static <K, V> Map<K, V> mapForValues(K key1, V value1, K key2, V value2) {
765     Map<K, V> map = new HashMap<>();
766     map.put(key1, value1);
767     map.put(key2, value2);
768     return map;
769   }
770 
testReflectionApi()771   public void testReflectionApi() throws Exception {
772     // In reflection API, map fields are just repeated message fields.
773     TestMap.Builder builder =
774         TestMap.newBuilder()
775             .putInt32ToInt32Field(1, 2)
776             .putInt32ToInt32Field(3, 4)
777             .putInt32ToMessageField(11, MessageValue.newBuilder().setValue(22).build())
778             .putInt32ToMessageField(33, MessageValue.newBuilder().setValue(44).build());
779     TestMap message = builder.build();
780 
781     // Test getField(), getRepeatedFieldCount(), getRepeatedField().
782     assertHasMapValues(message, "int32_to_int32_field", mapForValues(1, 2, 3, 4));
783     assertHasMapValues(
784         message,
785         "int32_to_message_field",
786         mapForValues(
787             11, MessageValue.newBuilder().setValue(22).build(),
788             33, MessageValue.newBuilder().setValue(44).build()));
789 
790     // Test clearField()
791     builder.clearField(f("int32_to_int32_field"));
792     builder.clearField(f("int32_to_message_field"));
793     message = builder.build();
794     assertEquals(0, message.getInt32ToInt32FieldMap().size());
795     assertEquals(0, message.getInt32ToMessageFieldMap().size());
796 
797     // Test setField()
798     setMapValues(builder, "int32_to_int32_field", mapForValues(11, 22, 33, 44));
799     setMapValues(
800         builder,
801         "int32_to_message_field",
802         mapForValues(
803             111, MessageValue.newBuilder().setValue(222).build(),
804             333, MessageValue.newBuilder().setValue(444).build()));
805     message = builder.build();
806     assertEquals(22, message.getInt32ToInt32FieldMap().get(11).intValue());
807     assertEquals(44, message.getInt32ToInt32FieldMap().get(33).intValue());
808     assertEquals(222, message.getInt32ToMessageFieldMap().get(111).getValue());
809     assertEquals(444, message.getInt32ToMessageFieldMap().get(333).getValue());
810 
811     // Test addRepeatedField
812     builder.addRepeatedField(
813         f("int32_to_int32_field"), newMapEntry(builder, "int32_to_int32_field", 55, 66));
814     builder.addRepeatedField(
815         f("int32_to_message_field"),
816         newMapEntry(
817             builder,
818             "int32_to_message_field",
819             555,
820             MessageValue.newBuilder().setValue(666).build()));
821     message = builder.build();
822     assertEquals(66, message.getInt32ToInt32FieldMap().get(55).intValue());
823     assertEquals(666, message.getInt32ToMessageFieldMap().get(555).getValue());
824 
825     // Test addRepeatedField (overriding existing values)
826     builder.addRepeatedField(
827         f("int32_to_int32_field"), newMapEntry(builder, "int32_to_int32_field", 55, 55));
828     builder.addRepeatedField(
829         f("int32_to_message_field"),
830         newMapEntry(
831             builder,
832             "int32_to_message_field",
833             555,
834             MessageValue.newBuilder().setValue(555).build()));
835     message = builder.build();
836     assertEquals(55, message.getInt32ToInt32FieldMap().get(55).intValue());
837     assertEquals(555, message.getInt32ToMessageFieldMap().get(555).getValue());
838 
839     // Test setRepeatedField
840     for (int i = 0; i < builder.getRepeatedFieldCount(f("int32_to_int32_field")); i++) {
841       Message mapEntry = (Message) builder.getRepeatedField(f("int32_to_int32_field"), i);
842       int oldKey = ((Integer) getFieldValue(mapEntry, "key")).intValue();
843       int oldValue = ((Integer) getFieldValue(mapEntry, "value")).intValue();
844       // Swap key with value for each entry.
845       Message.Builder mapEntryBuilder = mapEntry.toBuilder();
846       setFieldValue(mapEntryBuilder, "key", oldValue);
847       setFieldValue(mapEntryBuilder, "value", oldKey);
848       builder.setRepeatedField(f("int32_to_int32_field"), i, mapEntryBuilder.build());
849     }
850     message = builder.build();
851     assertEquals(11, message.getInt32ToInt32FieldMap().get(22).intValue());
852     assertEquals(33, message.getInt32ToInt32FieldMap().get(44).intValue());
853     assertEquals(55, message.getInt32ToInt32FieldMap().get(55).intValue());
854   }
855 
856   // See additional coverage in TextFormatTest.java.
testTextFormat()857   public void testTextFormat() throws Exception {
858     TestMap.Builder builder = TestMap.newBuilder();
859     setMapValuesUsingAccessors(builder);
860     TestMap message = builder.build();
861 
862     String textData = TextFormat.printer().printToString(message);
863 
864     builder = TestMap.newBuilder();
865     TextFormat.merge(textData, builder);
866     message = builder.build();
867 
868     assertMapValuesSet(message);
869   }
870 
testDynamicMessage()871   public void testDynamicMessage() throws Exception {
872     TestMap.Builder builder = TestMap.newBuilder();
873     setMapValuesUsingAccessors(builder);
874     TestMap message = builder.build();
875 
876     Message dynamicDefaultInstance = DynamicMessage.getDefaultInstance(TestMap.getDescriptor());
877     Message dynamicMessage =
878         dynamicDefaultInstance.newBuilderForType().mergeFrom(message.toByteString()).build();
879 
880     assertEquals(message, dynamicMessage);
881     assertEquals(message.hashCode(), dynamicMessage.hashCode());
882   }
883 
884   // Check that DynamicMessage handles map field serialization the same way as generated code
885   // regarding unset key and value field in a map entry.
testDynamicMessageUnsetKeyAndValue()886   public void testDynamicMessageUnsetKeyAndValue() throws Exception {
887     FieldDescriptor field = f("int32_to_int32_field");
888 
889     Message dynamicDefaultInstance = DynamicMessage.getDefaultInstance(TestMap.getDescriptor());
890     Message.Builder builder = dynamicDefaultInstance.newBuilderForType();
891     // Add an entry without key and value.
892     builder.addRepeatedField(field, builder.newBuilderForField(field).build());
893     Message message = builder.build();
894     ByteString bytes = message.toByteString();
895     // Parse it back to the same generated type.
896     Message generatedMessage = TestMap.parseFrom(bytes);
897     // Assert the serialized bytes are equivalent.
898     assertEquals(generatedMessage.toByteString(), bytes);
899   }
900 
testReflectionEqualsAndHashCode()901   public void testReflectionEqualsAndHashCode() throws Exception {
902     // Test that generated equals() and hashCode() will disregard the order
903     // of map entries when comparing/hashing map fields.
904 
905     // We use DynamicMessage to test reflection based equals()/hashCode().
906     Message dynamicDefaultInstance = DynamicMessage.getDefaultInstance(TestMap.getDescriptor());
907     FieldDescriptor field = f("int32_to_int32_field");
908 
909     Message.Builder b1 = dynamicDefaultInstance.newBuilderForType();
910     b1.addRepeatedField(field, newMapEntry(b1, "int32_to_int32_field", 1, 2));
911     b1.addRepeatedField(field, newMapEntry(b1, "int32_to_int32_field", 3, 4));
912     b1.addRepeatedField(field, newMapEntry(b1, "int32_to_int32_field", 5, 6));
913     Message m1 = b1.build();
914 
915     Message.Builder b2 = dynamicDefaultInstance.newBuilderForType();
916     b2.addRepeatedField(field, newMapEntry(b2, "int32_to_int32_field", 5, 6));
917     b2.addRepeatedField(field, newMapEntry(b2, "int32_to_int32_field", 1, 2));
918     b2.addRepeatedField(field, newMapEntry(b2, "int32_to_int32_field", 3, 4));
919     Message m2 = b2.build();
920 
921     assertEquals(m1, m2);
922     assertEquals(m1.hashCode(), m2.hashCode());
923 
924     // Make sure we did compare map fields.
925     b2.setRepeatedField(field, 0, newMapEntry(b1, "int32_to_int32_field", 0, 0));
926     m2 = b2.build();
927     assertFalse(m1.equals(m2));
928     // Don't check m1.hashCode() != m2.hashCode() because it's not guaranteed
929     // to be different.
930   }
931 
testUnknownEnumValues()932   public void testUnknownEnumValues() throws Exception {
933     TestMap.Builder builder =
934         TestMap.newBuilder()
935             .putAllInt32ToEnumFieldValue(
936                 newMap(
937                     0, 0,
938                     1, 1,
939                     2, 1000)); // unknown value.
940     TestMap message = builder.build();
941 
942     assertEquals(TestMap.EnumValue.FOO, message.getInt32ToEnumFieldMap().get(0));
943     assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumFieldMap().get(1));
944     assertEquals(TestMap.EnumValue.UNRECOGNIZED, message.getInt32ToEnumFieldMap().get(2));
945     assertEquals(1000, message.getInt32ToEnumFieldValueMap().get(2).intValue());
946 
947     // Unknown enum values should be preserved after:
948     //   1. Serialization and parsing.
949     //   2. toBuild().
950     //   3. mergeFrom().
951     message = TestMap.parseFrom(message.toByteString());
952     assertEquals(1000, message.getInt32ToEnumFieldValueMap().get(2).intValue());
953     builder = message.toBuilder();
954     assertEquals(1000, builder.getInt32ToEnumFieldValueMap().get(2).intValue());
955     builder = TestMap.newBuilder().mergeFrom(message);
956     assertEquals(1000, builder.getInt32ToEnumFieldValueMap().get(2).intValue());
957 
958     // hashCode()/equals() should take unknown enum values into account.
959     builder.putAllInt32ToEnumFieldValue(newMap(2, 1001));
960     TestMap message2 = builder.build();
961     assertFalse(message.hashCode() == message2.hashCode());
962     assertFalse(message.equals(message2));
963     // Unknown values will be converted to UNRECOGNIZED so the resulted enum map
964     // should be the same.
965     assertEquals(message2.getInt32ToEnumFieldMap(), message.getInt32ToEnumFieldMap());
966   }
967 
testUnknownEnumValuesInReflectionApi()968   public void testUnknownEnumValuesInReflectionApi() throws Exception {
969     Descriptor descriptor = TestMap.getDescriptor();
970     EnumDescriptor enumDescriptor = TestMap.EnumValue.getDescriptor();
971     FieldDescriptor field = descriptor.findFieldByName("int32_to_enum_field");
972 
973     Map<Integer, Integer> data =
974         newMap(
975             0, 0,
976             1, 1,
977             2, 1000); // unknown value
978 
979     TestMap.Builder builder = TestMap.newBuilder().putAllInt32ToEnumFieldValue(data);
980 
981     // Try to read unknown enum values using reflection API.
982     for (int i = 0; i < builder.getRepeatedFieldCount(field); i++) {
983       Message mapEntry = (Message) builder.getRepeatedField(field, i);
984       int key = ((Integer) getFieldValue(mapEntry, "key")).intValue();
985       int value = ((EnumValueDescriptor) getFieldValue(mapEntry, "value")).getNumber();
986       assertEquals(data.get(key).intValue(), value);
987       Message.Builder mapEntryBuilder = mapEntry.toBuilder();
988       // Increase the value by 1.
989       setFieldValue(
990           mapEntryBuilder, "value", enumDescriptor.findValueByNumberCreatingIfUnknown(value + 1));
991       builder.setRepeatedField(field, i, mapEntryBuilder.build());
992     }
993 
994     // Verify that enum values have been successfully updated.
995     TestMap message = builder.build();
996     for (Map.Entry<Integer, Integer> entry : message.getInt32ToEnumFieldValueMap().entrySet()) {
997       assertEquals(data.get(entry.getKey()) + 1, entry.getValue().intValue());
998     }
999   }
1000 
testIterationOrder()1001   public void testIterationOrder() throws Exception {
1002     TestMap.Builder builder = TestMap.newBuilder();
1003     setMapValuesUsingAccessors(builder);
1004     TestMap message = builder.build();
1005 
1006     assertEquals(
1007         Arrays.asList("1", "2", "3"), new ArrayList<>(message.getStringToInt32FieldMap().keySet()));
1008   }
1009 
testGetMap()1010   public void testGetMap() {
1011     TestMap.Builder builder = TestMap.newBuilder();
1012     setMapValuesUsingAccessors(builder);
1013     TestMap message = builder.build();
1014     assertEquals(message.getStringToInt32FieldMap(), message.getStringToInt32FieldMap());
1015     assertEquals(message.getInt32ToBytesFieldMap(), message.getInt32ToBytesFieldMap());
1016     assertEquals(message.getInt32ToEnumFieldMap(), message.getInt32ToEnumFieldMap());
1017     assertEquals(message.getInt32ToEnumFieldValueMap(), message.getInt32ToEnumFieldValueMap());
1018     assertEquals(message.getInt32ToMessageFieldMap(), message.getInt32ToMessageFieldMap());
1019   }
1020 
testContains()1021   public void testContains() {
1022     TestMap.Builder builder = TestMap.newBuilder();
1023     setMapValuesUsingAccessors(builder);
1024     assertMapContainsSetValues(builder);
1025     assertMapContainsSetValues(builder.build());
1026   }
1027 
assertMapContainsSetValues(TestMapOrBuilder testMapOrBuilder)1028   private void assertMapContainsSetValues(TestMapOrBuilder testMapOrBuilder) {
1029     assertTrue(testMapOrBuilder.containsInt32ToInt32Field(1));
1030     assertTrue(testMapOrBuilder.containsInt32ToInt32Field(2));
1031     assertTrue(testMapOrBuilder.containsInt32ToInt32Field(3));
1032     assertFalse(testMapOrBuilder.containsInt32ToInt32Field(-1));
1033 
1034     assertTrue(testMapOrBuilder.containsInt32ToStringField(1));
1035     assertTrue(testMapOrBuilder.containsInt32ToStringField(2));
1036     assertTrue(testMapOrBuilder.containsInt32ToStringField(3));
1037     assertFalse(testMapOrBuilder.containsInt32ToStringField(-1));
1038 
1039     assertTrue(testMapOrBuilder.containsInt32ToBytesField(1));
1040     assertTrue(testMapOrBuilder.containsInt32ToBytesField(2));
1041     assertTrue(testMapOrBuilder.containsInt32ToBytesField(3));
1042     assertFalse(testMapOrBuilder.containsInt32ToBytesField(-1));
1043 
1044     assertTrue(testMapOrBuilder.containsInt32ToEnumField(1));
1045     assertTrue(testMapOrBuilder.containsInt32ToEnumField(2));
1046     assertTrue(testMapOrBuilder.containsInt32ToEnumField(3));
1047     assertFalse(testMapOrBuilder.containsInt32ToEnumField(-1));
1048 
1049     assertTrue(testMapOrBuilder.containsInt32ToMessageField(1));
1050     assertTrue(testMapOrBuilder.containsInt32ToMessageField(2));
1051     assertTrue(testMapOrBuilder.containsInt32ToMessageField(3));
1052     assertFalse(testMapOrBuilder.containsInt32ToMessageField(-1));
1053 
1054     assertTrue(testMapOrBuilder.containsStringToInt32Field("1"));
1055     assertTrue(testMapOrBuilder.containsStringToInt32Field("2"));
1056     assertTrue(testMapOrBuilder.containsStringToInt32Field("3"));
1057     assertFalse(testMapOrBuilder.containsStringToInt32Field("-1"));
1058   }
1059 
testCount()1060   public void testCount() {
1061     TestMap.Builder builder = TestMap.newBuilder();
1062     assertMapCounts(0, builder);
1063 
1064     setMapValuesUsingAccessors(builder);
1065     assertMapCounts(3, builder);
1066 
1067     TestMap message = builder.build();
1068     assertMapCounts(3, message);
1069 
1070     builder = message.toBuilder().putInt32ToInt32Field(4, 44);
1071     assertEquals(4, builder.getInt32ToInt32FieldCount());
1072     assertEquals(4, builder.build().getInt32ToInt32FieldCount());
1073 
1074     // already present - should be unchanged
1075     builder.putInt32ToInt32Field(4, 44);
1076     assertEquals(4, builder.getInt32ToInt32FieldCount());
1077   }
1078 
assertMapCounts(int expectedCount, TestMapOrBuilder testMapOrBuilder)1079   private void assertMapCounts(int expectedCount, TestMapOrBuilder testMapOrBuilder) {
1080     assertEquals(expectedCount, testMapOrBuilder.getInt32ToInt32FieldCount());
1081     assertEquals(expectedCount, testMapOrBuilder.getInt32ToStringFieldCount());
1082     assertEquals(expectedCount, testMapOrBuilder.getInt32ToBytesFieldCount());
1083     assertEquals(expectedCount, testMapOrBuilder.getInt32ToEnumFieldCount());
1084     assertEquals(expectedCount, testMapOrBuilder.getInt32ToMessageFieldCount());
1085     assertEquals(expectedCount, testMapOrBuilder.getStringToInt32FieldCount());
1086   }
1087 
testGetOrDefault()1088   public void testGetOrDefault() {
1089     TestMap.Builder builder = TestMap.newBuilder();
1090     assertMapCounts(0, builder);
1091     setMapValuesUsingAccessors(builder);
1092     doTestGetOrDefault(builder);
1093     doTestGetOrDefault(builder.build());
1094   }
1095 
doTestGetOrDefault(TestMapOrBuilder testMapOrBuilder)1096   public void doTestGetOrDefault(TestMapOrBuilder testMapOrBuilder) {
1097     assertEquals(11, testMapOrBuilder.getInt32ToInt32FieldOrDefault(1, -11));
1098     assertEquals(-11, testMapOrBuilder.getInt32ToInt32FieldOrDefault(-1, -11));
1099 
1100     assertEquals("11", testMapOrBuilder.getInt32ToStringFieldOrDefault(1, "-11"));
1101     assertNull("-11", testMapOrBuilder.getInt32ToStringFieldOrDefault(-1, null));
1102 
1103     assertEquals(TestUtil.toBytes("11"), testMapOrBuilder.getInt32ToBytesFieldOrDefault(1, null));
1104     assertNull(testMapOrBuilder.getInt32ToBytesFieldOrDefault(-1, null));
1105 
1106     assertEquals(TestMap.EnumValue.FOO, testMapOrBuilder.getInt32ToEnumFieldOrDefault(1, null));
1107     assertNull(testMapOrBuilder.getInt32ToEnumFieldOrDefault(-1, null));
1108 
1109     assertEquals(
1110         TestMap.EnumValue.BAR.getNumber(),
1111         testMapOrBuilder.getInt32ToEnumFieldValueOrDefault(2, -1));
1112     assertEquals(-1, testMapOrBuilder.getInt32ToEnumFieldValueOrDefault(-1000, -1));
1113 
1114     assertEquals(
1115         MessageValue.newBuilder().setValue(11).build(),
1116         testMapOrBuilder.getInt32ToMessageFieldOrDefault(1, null));
1117     assertNull(testMapOrBuilder.getInt32ToMessageFieldOrDefault(-1, null));
1118 
1119     assertEquals(11, testMapOrBuilder.getStringToInt32FieldOrDefault("1", -11));
1120     assertEquals(-11, testMapOrBuilder.getStringToInt32FieldOrDefault("-1", -11));
1121 
1122     try {
1123       testMapOrBuilder.getStringToInt32FieldOrDefault(null, -11);
1124       fail();
1125     } catch (NullPointerException e) {
1126       // expected
1127     }
1128   }
1129 
testGetOrThrow()1130   public void testGetOrThrow() {
1131     TestMap.Builder builder = TestMap.newBuilder();
1132     assertMapCounts(0, builder);
1133     setMapValuesUsingAccessors(builder);
1134     doTestGetOrDefault(builder);
1135     doTestGetOrDefault(builder.build());
1136   }
1137 
doTestGetOrThrow(TestMapOrBuilder testMapOrBuilder)1138   public void doTestGetOrThrow(TestMapOrBuilder testMapOrBuilder) {
1139     assertEquals(11, testMapOrBuilder.getInt32ToInt32FieldOrThrow(1));
1140     try {
1141       testMapOrBuilder.getInt32ToInt32FieldOrThrow(-1);
1142       fail();
1143     } catch (IllegalArgumentException e) {
1144       // expected
1145     }
1146 
1147     assertEquals("11", testMapOrBuilder.getInt32ToStringFieldOrThrow(1));
1148 
1149     try {
1150       testMapOrBuilder.getInt32ToStringFieldOrThrow(-1);
1151       fail();
1152     } catch (IllegalArgumentException e) {
1153       // expected
1154     }
1155 
1156     assertEquals(TestUtil.toBytes("11"), testMapOrBuilder.getInt32ToBytesFieldOrThrow(1));
1157 
1158     try {
1159       testMapOrBuilder.getInt32ToBytesFieldOrThrow(-1);
1160       fail();
1161     } catch (IllegalArgumentException e) {
1162       // expected
1163     }
1164 
1165     assertEquals(TestMap.EnumValue.FOO, testMapOrBuilder.getInt32ToEnumFieldOrThrow(1));
1166     try {
1167       testMapOrBuilder.getInt32ToEnumFieldOrThrow(-1);
1168       fail();
1169     } catch (IllegalArgumentException e) {
1170       // expected
1171     }
1172 
1173     assertEquals(
1174         TestMap.EnumValue.BAR.getNumber(), testMapOrBuilder.getInt32ToEnumFieldValueOrThrow(2));
1175     try {
1176       testMapOrBuilder.getInt32ToEnumFieldValueOrThrow(-1);
1177       fail();
1178     } catch (IllegalArgumentException e) {
1179       // expected
1180     }
1181 
1182     assertEquals(
1183         MessageValue.newBuilder().setValue(11).build(),
1184         testMapOrBuilder.getInt32ToMessageFieldOrThrow(1));
1185     try {
1186       testMapOrBuilder.getInt32ToMessageFieldOrThrow(-1);
1187       fail();
1188     } catch (IllegalArgumentException e) {
1189       // expected
1190     }
1191 
1192     assertEquals(11, testMapOrBuilder.getStringToInt32FieldOrThrow("1"));
1193     try {
1194       testMapOrBuilder.getStringToInt32FieldOrThrow("-1");
1195       fail();
1196     } catch (IllegalArgumentException e) {
1197       // expected
1198     }
1199 
1200     try {
1201       testMapOrBuilder.getStringToInt32FieldOrThrow(null);
1202       fail();
1203     } catch (NullPointerException e) {
1204       // expected
1205     }
1206   }
1207 
testPut()1208   public void testPut() {
1209     TestMap.Builder builder = TestMap.newBuilder();
1210     builder.putInt32ToInt32Field(1, 11);
1211     assertEquals(11, builder.getInt32ToInt32FieldOrThrow(1));
1212 
1213     builder.putInt32ToStringField(1, "a");
1214     assertEquals("a", builder.getInt32ToStringFieldOrThrow(1));
1215     try {
1216       builder.putInt32ToStringField(1, null);
1217       fail();
1218     } catch (NullPointerException e) {
1219       // expected
1220     }
1221 
1222     builder.putInt32ToBytesField(1, TestUtil.toBytes("11"));
1223     assertEquals(TestUtil.toBytes("11"), builder.getInt32ToBytesFieldOrThrow(1));
1224     try {
1225       builder.putInt32ToBytesField(1, null);
1226       fail();
1227     } catch (NullPointerException e) {
1228       // expected
1229     }
1230 
1231     builder.putInt32ToEnumField(1, TestMap.EnumValue.FOO);
1232     assertEquals(TestMap.EnumValue.FOO, builder.getInt32ToEnumFieldOrThrow(1));
1233     try {
1234       builder.putInt32ToEnumField(1, null);
1235       fail();
1236     } catch (NullPointerException e) {
1237       // expected
1238     }
1239 
1240     builder.putInt32ToEnumFieldValue(1, TestMap.EnumValue.BAR.getNumber());
1241     assertEquals(TestMap.EnumValue.BAR.getNumber(), builder.getInt32ToEnumFieldValueOrThrow(1));
1242     builder.putInt32ToEnumFieldValue(1, -1);
1243     assertEquals(-1, builder.getInt32ToEnumFieldValueOrThrow(1));
1244     assertEquals(TestMap.EnumValue.UNRECOGNIZED, builder.getInt32ToEnumFieldOrThrow(1));
1245 
1246     builder.putStringToInt32Field("a", 1);
1247     assertEquals(1, builder.getStringToInt32FieldOrThrow("a"));
1248     try {
1249       builder.putStringToInt32Field(null, -1);
1250     } catch (NullPointerException e) {
1251       // expected
1252     }
1253   }
1254 
testRemove()1255   public void testRemove() {
1256     TestMap.Builder builder = TestMap.newBuilder();
1257     setMapValuesUsingAccessors(builder);
1258     assertEquals(11, builder.getInt32ToInt32FieldOrThrow(1));
1259     for (int times = 0; times < 2; times++) {
1260       builder.removeInt32ToInt32Field(1);
1261       assertEquals(-1, builder.getInt32ToInt32FieldOrDefault(1, -1));
1262     }
1263 
1264     assertEquals("11", builder.getInt32ToStringFieldOrThrow(1));
1265     for (int times = 0; times < 2; times++) {
1266       builder.removeInt32ToStringField(1);
1267       assertNull(builder.getInt32ToStringFieldOrDefault(1, null));
1268     }
1269 
1270     assertEquals(TestUtil.toBytes("11"), builder.getInt32ToBytesFieldOrThrow(1));
1271     for (int times = 0; times < 2; times++) {
1272       builder.removeInt32ToBytesField(1);
1273       assertNull(builder.getInt32ToBytesFieldOrDefault(1, null));
1274     }
1275 
1276     assertEquals(TestMap.EnumValue.FOO, builder.getInt32ToEnumFieldOrThrow(1));
1277     for (int times = 0; times < 2; times++) {
1278       builder.removeInt32ToEnumField(1);
1279       assertNull(builder.getInt32ToEnumFieldOrDefault(1, null));
1280     }
1281 
1282     assertEquals(11, builder.getStringToInt32FieldOrThrow("1"));
1283     for (int times = 0; times < 2; times++) {
1284       builder.removeStringToInt32Field("1");
1285       assertEquals(-1, builder.getStringToInt32FieldOrDefault("1", -1));
1286     }
1287 
1288     try {
1289       builder.removeStringToInt32Field(null);
1290       fail();
1291     } catch (NullPointerException e) {
1292       // expected
1293     }
1294   }
1295 
testReservedWordsFieldNames()1296   public void testReservedWordsFieldNames() {
1297     ReservedAsMapField.newBuilder().build();
1298     ReservedAsMapFieldWithEnumValue.newBuilder().build();
1299   }
1300 
testDeterministicSerialziation()1301   public void testDeterministicSerialziation() throws Exception {
1302     TestMap.Builder builder = TestMap.newBuilder();
1303     // int32->int32
1304     builder.putInt32ToInt32Field(5, 1);
1305     builder.putInt32ToInt32Field(1, 1);
1306     builder.putInt32ToInt32Field(4, 1);
1307     builder.putInt32ToInt32Field(-2, 1);
1308     builder.putInt32ToInt32Field(0, 1);
1309 
1310     // uint32->int32
1311     builder.putUint32ToInt32Field(5, 1);
1312     builder.putUint32ToInt32Field(1, 1);
1313     builder.putUint32ToInt32Field(4, 1);
1314     builder.putUint32ToInt32Field(-2, 1);
1315     builder.putUint32ToInt32Field(0, 1);
1316 
1317     // int64->int32
1318     builder.putInt64ToInt32Field(5L, 1);
1319     builder.putInt64ToInt32Field(1L, 1);
1320     builder.putInt64ToInt32Field(4L, 1);
1321     builder.putInt64ToInt32Field(-2L, 1);
1322     builder.putInt64ToInt32Field(0L, 1);
1323 
1324     // string->int32
1325     builder.putStringToInt32Field("baz", 1);
1326     builder.putStringToInt32Field("foo", 1);
1327     builder.putStringToInt32Field("bar", 1);
1328     builder.putStringToInt32Field("", 1);
1329     builder.putStringToInt32Field("hello", 1);
1330     builder.putStringToInt32Field("world", 1);
1331 
1332     TestMap message = builder.build();
1333     byte[] serialized = new byte[message.getSerializedSize()];
1334     CodedOutputStream output = CodedOutputStream.newInstance(serialized);
1335     output.useDeterministicSerialization();
1336     message.writeTo(output);
1337     output.flush();
1338 
1339     CodedInputStream input = CodedInputStream.newInstance(serialized);
1340     List<Integer> int32Keys = new ArrayList<>();
1341     List<Integer> uint32Keys = new ArrayList<>();
1342     List<Long> int64Keys = new ArrayList<>();
1343     List<String> stringKeys = new ArrayList<>();
1344     int tag;
1345     while (true) {
1346       tag = input.readTag();
1347       if (tag == 0) {
1348         break;
1349       }
1350       int length = input.readRawVarint32();
1351       int oldLimit = input.pushLimit(length);
1352       switch (WireFormat.getTagFieldNumber(tag)) {
1353         case TestMap.STRING_TO_INT32_FIELD_FIELD_NUMBER:
1354           stringKeys.add(readMapStringKey(input));
1355           break;
1356         case TestMap.INT32_TO_INT32_FIELD_FIELD_NUMBER:
1357           int32Keys.add(readMapIntegerKey(input));
1358           break;
1359         case TestMap.UINT32_TO_INT32_FIELD_FIELD_NUMBER:
1360           uint32Keys.add(readMapIntegerKey(input));
1361           break;
1362         case TestMap.INT64_TO_INT32_FIELD_FIELD_NUMBER:
1363           int64Keys.add(readMapLongKey(input));
1364           break;
1365         default:
1366           fail("Unexpected fields.");
1367       }
1368       input.popLimit(oldLimit);
1369     }
1370     assertEquals(Arrays.asList(-2, 0, 1, 4, 5), int32Keys);
1371     assertEquals(Arrays.asList(-2, 0, 1, 4, 5), uint32Keys);
1372     assertEquals(Arrays.asList(-2L, 0L, 1L, 4L, 5L), int64Keys);
1373     assertEquals(Arrays.asList("", "bar", "baz", "foo", "hello", "world"), stringKeys);
1374   }
1375 
testInitFromPartialDynamicMessage()1376   public void testInitFromPartialDynamicMessage() {
1377     FieldDescriptor fieldDescriptor =
1378         TestMap.getDescriptor().findFieldByNumber(TestMap.INT32_TO_MESSAGE_FIELD_FIELD_NUMBER);
1379     Descriptor mapEntryType = fieldDescriptor.getMessageType();
1380     FieldDescriptor keyField = mapEntryType.findFieldByNumber(1);
1381     FieldDescriptor valueField = mapEntryType.findFieldByNumber(2);
1382     DynamicMessage dynamicMessage =
1383         DynamicMessage.newBuilder(TestMap.getDescriptor())
1384             .addRepeatedField(
1385                 fieldDescriptor,
1386                 DynamicMessage.newBuilder(mapEntryType)
1387                     .setField(keyField, 10)
1388                     .setField(valueField, TestMap.MessageValue.newBuilder().setValue(10).build())
1389                     .build())
1390             .build();
1391     TestMap message = TestMap.newBuilder().mergeFrom(dynamicMessage).build();
1392     assertEquals(
1393         TestMap.MessageValue.newBuilder().setValue(10).build(),
1394         message.getInt32ToMessageFieldMap().get(10));
1395   }
1396 
testInitFromFullyDynamicMessage()1397   public void testInitFromFullyDynamicMessage() {
1398     FieldDescriptor fieldDescriptor =
1399         TestMap.getDescriptor().findFieldByNumber(TestMap.INT32_TO_MESSAGE_FIELD_FIELD_NUMBER);
1400     Descriptor mapEntryType = fieldDescriptor.getMessageType();
1401     FieldDescriptor keyField = mapEntryType.findFieldByNumber(1);
1402     FieldDescriptor valueField = mapEntryType.findFieldByNumber(2);
1403     DynamicMessage dynamicMessage =
1404         DynamicMessage.newBuilder(TestMap.getDescriptor())
1405             .addRepeatedField(
1406                 fieldDescriptor,
1407                 DynamicMessage.newBuilder(mapEntryType)
1408                     .setField(keyField, 10)
1409                     .setField(
1410                         valueField,
1411                         DynamicMessage.newBuilder(TestMap.MessageValue.getDescriptor())
1412                             .setField(
1413                                 TestMap.MessageValue.getDescriptor().findFieldByName("value"), 10)
1414                             .build())
1415                     .build())
1416             .build();
1417     TestMap message = TestMap.newBuilder().mergeFrom(dynamicMessage).build();
1418     assertEquals(
1419         TestMap.MessageValue.newBuilder().setValue(10).build(),
1420         message.getInt32ToMessageFieldMap().get(10));
1421   }
1422 
readMapIntegerKey(CodedInputStream input)1423   private int readMapIntegerKey(CodedInputStream input) throws IOException {
1424     int tag = input.readTag();
1425     assertEquals(WireFormat.makeTag(1, WireFormat.WIRETYPE_VARINT), tag);
1426     int ret = input.readInt32();
1427     // skip the value field.
1428     input.skipField(input.readTag());
1429     assertTrue(input.isAtEnd());
1430     return ret;
1431   }
1432 
readMapLongKey(CodedInputStream input)1433   private long readMapLongKey(CodedInputStream input) throws IOException {
1434     int tag = input.readTag();
1435     assertEquals(WireFormat.makeTag(1, WireFormat.WIRETYPE_VARINT), tag);
1436     long ret = input.readInt64();
1437     // skip the value field.
1438     input.skipField(input.readTag());
1439     assertTrue(input.isAtEnd());
1440     return ret;
1441   }
1442 
readMapStringKey(CodedInputStream input)1443   private String readMapStringKey(CodedInputStream input) throws IOException {
1444     int tag = input.readTag();
1445     assertEquals(WireFormat.makeTag(1, WireFormat.WIRETYPE_LENGTH_DELIMITED), tag);
1446     String ret = input.readString();
1447     // skip the value field.
1448     input.skipField(input.readTag());
1449     assertTrue(input.isAtEnd());
1450     return ret;
1451   }
1452 
newMap(K key1, V value1)1453   private static <K, V> Map<K, V> newMap(K key1, V value1) {
1454     Map<K, V> map = new HashMap<>();
1455     map.put(key1, value1);
1456     return map;
1457   }
1458 
newMap(K key1, V value1, K key2, V value2)1459   private static <K, V> Map<K, V> newMap(K key1, V value1, K key2, V value2) {
1460     Map<K, V> map = new HashMap<>();
1461     map.put(key1, value1);
1462     map.put(key2, value2);
1463     return map;
1464   }
1465 
newMap(K key1, V value1, K key2, V value2, K key3, V value3)1466   private static <K, V> Map<K, V> newMap(K key1, V value1, K key2, V value2, K key3, V value3) {
1467     Map<K, V> map = new HashMap<>();
1468     map.put(key1, value1);
1469     map.put(key2, value2);
1470     map.put(key3, value3);
1471     return map;
1472   }
1473 
testMap_withNulls()1474   public void testMap_withNulls() {
1475     TestMap.Builder builder = TestMap.newBuilder();
1476 
1477     try {
1478       builder.putStringToInt32Field(null, 3);
1479       fail();
1480     } catch (NullPointerException expected) {
1481     }
1482 
1483     try {
1484       builder.putAllStringToInt32Field(newMap(null, 3, "hi", 4));
1485       fail();
1486     } catch (NullPointerException expected) {
1487     }
1488 
1489     try {
1490       builder.putInt32ToMessageField(3, null);
1491       fail();
1492     } catch (NullPointerException expected) {
1493     }
1494 
1495     try {
1496       builder.putAllInt32ToMessageField(MapTest.<Integer, MessageValue>newMap(4, null, 5, null));
1497       fail();
1498     } catch (NullPointerException expected) {
1499     }
1500 
1501     try {
1502       builder.putAllInt32ToMessageField(null);
1503       fail();
1504     } catch (NullPointerException expected) {
1505     }
1506 
1507     assertArrayEquals(new byte[0], builder.build().toByteArray());
1508   }
1509 }
1510