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") 380 public void serialEquality(Map<Integer, String> act, Map<Integer, String> exp) { 381 // assume that act.equals(exp) tested elsewhere 382 Map<Integer, String> copy = serialClone(act); 383 assertEquals(act, copy); 384 assertEquals(copy, exp); 385 } 386 387 @SuppressWarnings("unchecked") 388 static <T> T serialClone(T obj) { 389 try { 390 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 391 try (ObjectOutputStream oos = new ObjectOutputStream(baos)) { 392 oos.writeObject(obj); 393 } 394 ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); 395 ObjectInputStream ois = new ObjectInputStream(bais); 396 return (T) ois.readObject(); 397 } catch (IOException | ClassNotFoundException e) { 398 throw new AssertionError(e); 399 } 400 } 401 402 Map<Integer, String> genMap() { 403 Map<Integer, String> map = new HashMap<>(); 404 map.put(1, "a"); 405 map.put(2, "b"); 406 map.put(3, "c"); 407 return map; 408 } 409 410 @Test 411 public void copyOfResultsEqual() { 412 Map<Integer, String> orig = genMap(); 413 Map<Integer, String> copy = Map.copyOf(orig); 414 415 assertEquals(orig, copy); 416 assertEquals(copy, orig); 417 } 418 419 @Test 420 public void copyOfModifiedUnequal() { 421 Map<Integer, String> orig = genMap(); 422 Map<Integer, String> copy = Map.copyOf(orig); 423 orig.put(4, "d"); 424 425 assertNotEquals(orig, copy); 426 assertNotEquals(copy, orig); 427 } 428 429 @Test 430 public void copyOfIdentity() { 431 Map<Integer, String> orig = genMap(); 432 Map<Integer, String> copy1 = Map.copyOf(orig); 433 Map<Integer, String> copy2 = Map.copyOf(copy1); 434 435 assertNotSame(orig, copy1); 436 assertSame(copy1, copy2); 437 } 438 439 @Test(expectedExceptions=NullPointerException.class) 440 public void copyOfRejectsNullMap() { 441 Map<Integer, String> map = Map.copyOf(null); 442 } 443 444 @Test(expectedExceptions=NullPointerException.class) 445 public void copyOfRejectsNullKey() { 446 Map<Integer, String> map = genMap(); 447 map.put(null, "x"); 448 Map<Integer, String> copy = Map.copyOf(map); 449 } 450 451 @Test(expectedExceptions=NullPointerException.class) 452 public void copyOfRejectsNullValue() { 453 Map<Integer, String> map = genMap(); 454 map.put(-1, null); 455 Map<Integer, String> copy = Map.copyOf(map); 456 } 457 458 // Map.entry() tests 459 460 @Test(expectedExceptions=NullPointerException.class) 461 public void entryWithNullKeyDisallowed() { 462 Map.Entry<Integer,String> e = Map.entry(null, "x"); 463 } 464 465 @Test(expectedExceptions=NullPointerException.class) 466 public void entryWithNullValueDisallowed() { 467 Map.Entry<Integer,String> e = Map.entry(0, null); 468 } 469 470 @Test 471 public void entryBasicTests() { 472 Map.Entry<String,String> kvh1 = Map.entry("xyzzy", "plugh"); 473 Map.Entry<String,String> kvh2 = Map.entry("foobar", "blurfl"); 474 Map.Entry<String,String> sie = new AbstractMap.SimpleImmutableEntry<>("xyzzy", "plugh"); 475 476 assertTrue(kvh1.equals(sie)); 477 assertTrue(sie.equals(kvh1)); 478 assertFalse(kvh2.equals(sie)); 479 assertFalse(sie.equals(kvh2)); 480 assertEquals(sie.hashCode(), kvh1.hashCode()); 481 assertEquals(sie.toString(), kvh1.toString()); 482 } 483 484 // compile-time test of wildcards 485 @Test 486 public void entryWildcardTests() { 487 Map.Entry<Integer,Double> e1 = Map.entry(1, 2.0); 488 Map.Entry<Float,Long> e2 = Map.entry(3.0f, 4L); 489 Map<Number,Number> map = Map.ofEntries(e1, e2); 490 assertEquals(map.size(), 2); 491 } 492 }