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