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