1 /* 2 * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 import java.io.ByteArrayInputStream; 25 import java.io.ByteArrayOutputStream; 26 import java.io.IOException; 27 import java.io.ObjectInputStream; 28 import java.io.ObjectOutputStream; 29 import java.util.AbstractMap; 30 import java.util.ArrayList; 31 import java.util.Arrays; 32 import java.util.Collections; 33 import java.util.Iterator; 34 import java.util.HashMap; 35 import java.util.List; 36 import java.util.Map; 37 import java.util.stream.Collectors; 38 import java.util.stream.IntStream; 39 40 import org.testng.annotations.DataProvider; 41 import org.testng.annotations.Test; 42 43 import static org.testng.Assert.assertEquals; 44 import static org.testng.Assert.assertFalse; 45 import static org.testng.Assert.assertNotEquals; 46 import static org.testng.Assert.assertNotSame; 47 import static org.testng.Assert.assertSame; 48 import static org.testng.Assert.assertTrue; 49 import static org.testng.Assert.fail; 50 51 /* 52 * @test 53 * @bug 8048330 54 * @summary Test convenience static factory methods on Map. 55 * @run testng MapFactories 56 */ 57 58 public class MapFactories { 59 60 static final int MAX_ENTRIES = 20; // should be larger than the largest fixed-arg overload 61 static String valueFor(int i) { 62 // the String literal below should be of length MAX_ENTRIES 63 return "abcdefghijklmnopqrst".substring(i, i+1); 64 } 65 66 // for "expected" values 67 Map<Integer,String> genMap(int n) { 68 Map<Integer,String> result = new HashMap<>(); 69 for (int i = 0; i < n; i++) { 70 result.put(i, valueFor(i)); 71 } 72 return result; 73 } 74 75 // for varargs Map.Entry methods 76 77 @SuppressWarnings("unchecked") 78 Map.Entry<Integer,String>[] genEmptyEntryArray1() { 79 return (Map.Entry<Integer,String>[])new Map.Entry<?,?>[1]; 80 } 81 82 @SuppressWarnings("unchecked") 83 Map.Entry<Integer,String>[] genEntries(int n) { 84 return IntStream.range(0, n) 85 .mapToObj(i -> Map.entry(i, valueFor(i))) 86 .toArray(Map.Entry[]::new); 87 } 88 89 // returns array of [actual, expected] 90 static Object[] a(Map<Integer,String> act, Map<Integer,String> exp) { 91 return new Object[] { act, exp }; 92 } 93 94 @DataProvider(name="empty") 95 public Iterator<Object[]> empty() { 96 return Collections.singletonList( 97 a(Map.of(), genMap(0)) 98 ).iterator(); 99 } 100 101 @DataProvider(name="nonempty") 102 @SuppressWarnings("unchecked") 103 public Iterator<Object[]> nonempty() { 104 return Arrays.asList( 105 a(Map.of(0, "a"), genMap(1)), 106 a(Map.of(0, "a", 1, "b"), genMap(2)), 107 a(Map.of(0, "a", 1, "b", 2, "c"), genMap(3)), 108 a(Map.of(0, "a", 1, "b", 2, "c", 3, "d"), genMap(4)), 109 a(Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e"), genMap(5)), 110 a(Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e", 5, "f"), genMap(6)), 111 a(Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e", 5, "f", 6, "g"), genMap(7)), 112 a(Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e", 5, "f", 6, "g", 7, "h"), genMap(8)), 113 a(Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e", 5, "f", 6, "g", 7, "h", 8, "i"), genMap(9)), 114 a(Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e", 5, "f", 6, "g", 7, "h", 8, "i", 9, "j"), genMap(10)), 115 a(Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e", 5, "f", 6, "g", 7, "h", 8, "i", 9, "j"), 116 Map.of(4, "e", 5, "f", 6, "g", 7, "h", 8, "i", 9, "j", 0, "a", 1, "b", 2, "c", 3, "d")), 117 a(Map.ofEntries(genEntries(MAX_ENTRIES)), genMap(MAX_ENTRIES)) 118 ).iterator(); 119 } 120 121 @DataProvider(name="all") 122 public Iterator<Object[]> all() { 123 List<Object[]> all = new ArrayList<>(); 124 empty().forEachRemaining(all::add); 125 nonempty().forEachRemaining(all::add); 126 return all.iterator(); 127 } 128 129 @Test(dataProvider="all", expectedExceptions=UnsupportedOperationException.class) 130 public void cannotPutNew(Map<Integer,String> act, Map<Integer,String> exp) { 131 act.put(-1, "xyzzy"); 132 } 133 134 @Test(dataProvider="nonempty", expectedExceptions=UnsupportedOperationException.class) 135 public void cannotPutOld(Map<Integer,String> act, Map<Integer,String> exp) { 136 act.put(0, "a"); 137 } 138 139 @Test(dataProvider="nonempty", expectedExceptions=UnsupportedOperationException.class) 140 public void cannotRemove(Map<Integer,String> act, Map<Integer,String> exp) { 141 act.remove(act.keySet().iterator().next()); 142 } 143 144 @Test(dataProvider="all") 145 public void contentsMatch(Map<Integer,String> act, Map<Integer,String> exp) { 146 assertEquals(act, exp); 147 } 148 149 @Test(dataProvider="all") 150 public void containsAllKeys(Map<Integer,String> act, Map<Integer,String> exp) { 151 assertTrue(act.keySet().containsAll(exp.keySet())); 152 assertTrue(exp.keySet().containsAll(act.keySet())); 153 } 154 155 @Test(dataProvider="all") 156 public void containsAllValues(Map<Integer,String> act, Map<Integer,String> exp) { 157 assertTrue(act.values().containsAll(exp.values())); 158 assertTrue(exp.values().containsAll(act.values())); 159 } 160 161 @Test(expectedExceptions=IllegalArgumentException.class) 162 public void dupKeysDisallowed2() { 163 Map<Integer, String> map = Map.of(0, "a", 0, "b"); 164 } 165 166 @Test(expectedExceptions=IllegalArgumentException.class) 167 public void dupKeysDisallowed3() { 168 Map<Integer, String> map = Map.of(0, "a", 1, "b", 0, "c"); 169 } 170 171 @Test(expectedExceptions=IllegalArgumentException.class) 172 public void dupKeysDisallowed4() { 173 Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 0, "d"); 174 } 175 176 @Test(expectedExceptions=IllegalArgumentException.class) 177 public void dupKeysDisallowed5() { 178 Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 0, "e"); 179 } 180 181 @Test(expectedExceptions=IllegalArgumentException.class) 182 public void dupKeysDisallowed6() { 183 Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e", 184 0, "f"); 185 } 186 187 @Test(expectedExceptions=IllegalArgumentException.class) 188 public void dupKeysDisallowed7() { 189 Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e", 190 5, "f", 0, "g"); 191 } 192 193 @Test(expectedExceptions=IllegalArgumentException.class) 194 public void dupKeysDisallowed8() { 195 Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e", 196 5, "f", 6, "g", 0, "h"); 197 } 198 199 @Test(expectedExceptions=IllegalArgumentException.class) 200 public void dupKeysDisallowed9() { 201 Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e", 202 5, "f", 6, "g", 7, "h", 0, "i"); 203 } 204 205 @Test(expectedExceptions=IllegalArgumentException.class) 206 public void dupKeysDisallowed10() { 207 Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e", 208 5, "f", 6, "g", 7, "h", 8, "i", 0, "j"); 209 } 210 211 @Test(expectedExceptions=IllegalArgumentException.class) 212 public void dupKeysDisallowedN() { 213 Map.Entry<Integer,String>[] entries = genEntries(MAX_ENTRIES); 214 entries[MAX_ENTRIES-1] = Map.entry(0, "xxx"); 215 Map<Integer, String> map = Map.ofEntries(entries); 216 } 217 218 @Test(dataProvider="all") 219 public void hashCodeEquals(Map<Integer,String> act, Map<Integer,String> exp) { 220 assertEquals(act.hashCode(), exp.hashCode()); 221 } 222 223 @Test(expectedExceptions=NullPointerException.class) 224 public void nullKeyDisallowed1() { 225 Map<Integer, String> map = Map.of(null, "a"); 226 } 227 228 @Test(expectedExceptions=NullPointerException.class) 229 public void nullValueDisallowed1() { 230 Map<Integer, String> map = Map.of(0, null); 231 } 232 233 @Test(expectedExceptions=NullPointerException.class) 234 public void nullKeyDisallowed2() { 235 Map<Integer, String> map = Map.of(0, "a", null, "b"); 236 } 237 238 @Test(expectedExceptions=NullPointerException.class) 239 public void nullValueDisallowed2() { 240 Map<Integer, String> map = Map.of(0, "a", 1, null); 241 } 242 243 @Test(expectedExceptions=NullPointerException.class) 244 public void nullKeyDisallowed3() { 245 Map<Integer, String> map = Map.of(0, "a", 1, "b", null, "c"); 246 } 247 248 @Test(expectedExceptions=NullPointerException.class) 249 public void nullValueDisallowed3() { 250 Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, null); 251 } 252 253 @Test(expectedExceptions=NullPointerException.class) 254 public void nullKeyDisallowed4() { 255 Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", null, "d"); 256 } 257 258 @Test(expectedExceptions=NullPointerException.class) 259 public void nullValueDisallowed4() { 260 Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, null); 261 } 262 263 @Test(expectedExceptions=NullPointerException.class) 264 public void nullKeyDisallowed5() { 265 Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", null, "e"); 266 } 267 268 @Test(expectedExceptions=NullPointerException.class) 269 public void nullValueDisallowed5() { 270 Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, null); 271 } 272 273 @Test(expectedExceptions=NullPointerException.class) 274 public void nullKeyDisallowed6() { 275 Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e", 276 null, "f"); 277 } 278 279 @Test(expectedExceptions=NullPointerException.class) 280 public void nullValueDisallowed6() { 281 Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e", 282 5, null); 283 } 284 285 @Test(expectedExceptions=NullPointerException.class) 286 public void nullKeyDisallowed7() { 287 Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e", 288 5, "f", null, "g"); 289 } 290 291 @Test(expectedExceptions=NullPointerException.class) 292 public void nullValueDisallowed7() { 293 Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e", 294 5, "f", 6, null); 295 } 296 297 @Test(expectedExceptions=NullPointerException.class) 298 public void nullKeyDisallowed8() { 299 Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e", 300 5, "f", 6, "g", null, "h"); 301 } 302 303 @Test(expectedExceptions=NullPointerException.class) 304 public void nullValueDisallowed8() { 305 Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e", 306 5, "f", 6, "g", 7, null); 307 } 308 309 @Test(expectedExceptions=NullPointerException.class) 310 public void nullKeyDisallowed9() { 311 Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e", 312 5, "f", 6, "g", 7, "h", null, "i"); 313 } 314 315 @Test(expectedExceptions=NullPointerException.class) 316 public void nullValueDisallowed9() { 317 Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e", 318 5, "f", 6, "g", 7, "h", 8, null); 319 } 320 321 @Test(expectedExceptions=NullPointerException.class) 322 public void nullKeyDisallowed10() { 323 Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e", 324 5, "f", 6, "g", 7, "h", 8, "i", null, "j"); 325 } 326 327 @Test(expectedExceptions=NullPointerException.class) 328 public void nullValueDisallowed10() { 329 Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e", 330 5, "f", 6, "g", 7, "h", 8, "i", 9, null); 331 } 332 333 @Test(expectedExceptions=NullPointerException.class) 334 public void nullKeyDisallowedVar1() { 335 Map.Entry<Integer,String>[] entries = genEmptyEntryArray1(); 336 entries[0] = new AbstractMap.SimpleImmutableEntry<>(null, "a"); 337 Map<Integer, String> map = Map.ofEntries(entries); 338 } 339 340 @Test(expectedExceptions=NullPointerException.class) 341 public void nullValueDisallowedVar1() { 342 Map.Entry<Integer,String>[] entries = genEmptyEntryArray1(); 343 entries[0] = new AbstractMap.SimpleImmutableEntry<>(0, null); 344 Map<Integer, String> map = Map.ofEntries(entries); 345 } 346 347 @Test(expectedExceptions=NullPointerException.class) 348 public void nullEntryDisallowedVar1() { 349 Map.Entry<Integer,String>[] entries = genEmptyEntryArray1(); 350 Map<Integer, String> map = Map.ofEntries(entries); 351 } 352 353 @Test(expectedExceptions=NullPointerException.class) 354 public void nullKeyDisallowedVarN() { 355 Map.Entry<Integer,String>[] entries = genEntries(MAX_ENTRIES); 356 entries[0] = new AbstractMap.SimpleImmutableEntry<>(null, "a"); 357 Map<Integer, String> map = Map.ofEntries(entries); 358 } 359 360 @Test(expectedExceptions=NullPointerException.class) 361 public void nullValueDisallowedVarN() { 362 Map.Entry<Integer,String>[] entries = genEntries(MAX_ENTRIES); 363 entries[0] = new AbstractMap.SimpleImmutableEntry<>(0, null); 364 Map<Integer, String> map = Map.ofEntries(entries); 365 } 366 367 @Test(expectedExceptions=NullPointerException.class) 368 public void nullEntryDisallowedVarN() { 369 Map.Entry<Integer,String>[] entries = genEntries(MAX_ENTRIES); 370 entries[5] = null; 371 Map<Integer, String> map = Map.ofEntries(entries); 372 } 373 374 @Test(expectedExceptions=NullPointerException.class) 375 public void nullArrayDisallowed() { 376 Map.ofEntries((Map.Entry<?,?>[])null); 377 } 378 379 @Test(dataProvider="all", expectedExceptions=NullPointerException.class) 380 public void containsValueNullShouldThrowNPE(Map<Integer,String> act, Map<Integer,String> exp) { 381 act.containsValue(null); 382 } 383 384 @Test(dataProvider="all", expectedExceptions=NullPointerException.class) 385 public void containsKeyNullShouldThrowNPE(Map<Integer,String> act, Map<Integer,String> exp) { 386 act.containsKey(null); 387 } 388 389 @Test(dataProvider="all") 390 public void serialEquality(Map<Integer, String> act, Map<Integer, String> exp) { 391 // assume that act.equals(exp) tested elsewhere 392 Map<Integer, String> copy = serialClone(act); 393 assertEquals(act, copy); 394 assertEquals(copy, exp); 395 } 396 397 @SuppressWarnings("unchecked") 398 static <T> T serialClone(T obj) { 399 try { 400 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 401 try (ObjectOutputStream oos = new ObjectOutputStream(baos)) { 402 oos.writeObject(obj); 403 } 404 ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); 405 ObjectInputStream ois = new ObjectInputStream(bais); 406 return (T) ois.readObject(); 407 } catch (IOException | ClassNotFoundException e) { 408 throw new AssertionError(e); 409 } 410 } 411 412 Map<Integer, String> genMap() { 413 Map<Integer, String> map = new HashMap<>(); 414 map.put(1, "a"); 415 map.put(2, "b"); 416 map.put(3, "c"); 417 return map; 418 } 419 420 @Test 421 public void copyOfResultsEqual() { 422 Map<Integer, String> orig = genMap(); 423 Map<Integer, String> copy = Map.copyOf(orig); 424 425 assertEquals(orig, copy); 426 assertEquals(copy, orig); 427 } 428 429 @Test 430 public void copyOfModifiedUnequal() { 431 Map<Integer, String> orig = genMap(); 432 Map<Integer, String> copy = Map.copyOf(orig); 433 orig.put(4, "d"); 434 435 assertNotEquals(orig, copy); 436 assertNotEquals(copy, orig); 437 } 438 439 @Test 440 public void copyOfIdentity() { 441 Map<Integer, String> orig = genMap(); 442 Map<Integer, String> copy1 = Map.copyOf(orig); 443 Map<Integer, String> copy2 = Map.copyOf(copy1); 444 445 assertNotSame(orig, copy1); 446 assertSame(copy1, copy2); 447 } 448 449 @Test(expectedExceptions=NullPointerException.class) 450 public void copyOfRejectsNullMap() { 451 Map<Integer, String> map = Map.copyOf(null); 452 } 453 454 @Test(expectedExceptions=NullPointerException.class) 455 public void copyOfRejectsNullKey() { 456 Map<Integer, String> map = genMap(); 457 map.put(null, "x"); 458 Map<Integer, String> copy = Map.copyOf(map); 459 } 460 461 @Test(expectedExceptions=NullPointerException.class) 462 public void copyOfRejectsNullValue() { 463 Map<Integer, String> map = genMap(); 464 map.put(-1, null); 465 Map<Integer, String> copy = Map.copyOf(map); 466 } 467 468 // Map.entry() tests 469 470 @Test(expectedExceptions=NullPointerException.class) 471 public void entryWithNullKeyDisallowed() { 472 Map.Entry<Integer,String> e = Map.entry(null, "x"); 473 } 474 475 @Test(expectedExceptions=NullPointerException.class) 476 public void entryWithNullValueDisallowed() { 477 Map.Entry<Integer,String> e = Map.entry(0, null); 478 } 479 480 @Test 481 public void entryBasicTests() { 482 Map.Entry<String,String> kvh1 = Map.entry("xyzzy", "plugh"); 483 Map.Entry<String,String> kvh2 = Map.entry("foobar", "blurfl"); 484 Map.Entry<String,String> sie = new AbstractMap.SimpleImmutableEntry<>("xyzzy", "plugh"); 485 486 assertTrue(kvh1.equals(sie)); 487 assertTrue(sie.equals(kvh1)); 488 assertFalse(kvh2.equals(sie)); 489 assertFalse(sie.equals(kvh2)); 490 assertEquals(sie.hashCode(), kvh1.hashCode()); 491 assertEquals(sie.toString(), kvh1.toString()); 492 } 493 494 // compile-time test of wildcards 495 @Test 496 public void entryWildcardTests() { 497 Map.Entry<Integer,Double> e1 = Map.entry(1, 2.0); 498 Map.Entry<Float,Long> e2 = Map.entry(3.0f, 4L); 499 Map<Number,Number> map = Map.ofEntries(e1, e2); 500 assertEquals(map.size(), 2); 501 } 502 }