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.assertTrue; 46 import static org.testng.Assert.fail; 47 48 /* 49 * @test 50 * @bug 8048330 51 * @summary Test convenience static factory methods on Map. 52 * @run testng MapFactories 53 */ 54 55 public class MapFactories { 56 57 static final int MAX_ENTRIES = 20; // should be larger than the largest fixed-arg overload 58 static String valueFor(int i) { 59 // the String literal below should be of length MAX_ENTRIES 60 return "abcdefghijklmnopqrst".substring(i, i+1); 61 } 62 63 // for "expected" values 64 Map<Integer,String> genMap(int n) { 65 Map<Integer,String> result = new HashMap<>(); 66 for (int i = 0; i < n; i++) { 67 result.put(i, valueFor(i)); 68 } 69 return result; 70 } 71 72 // for varargs Map.Entry methods 73 @SuppressWarnings("unchecked") 74 Map.Entry<Integer,String>[] genEntries(int n) { 75 return IntStream.range(0, n) 76 .mapToObj(i -> Map.entry(i, valueFor(i))) 77 .toArray(Map.Entry[]::new); 78 } 79 80 // returns array of [actual, expected] 81 static Object[] a(Map<Integer,String> act, Map<Integer,String> exp) { 82 return new Object[] { act, exp }; 83 } 84 85 @DataProvider(name="empty") 86 public Iterator<Object[]> empty() { 87 return Collections.singletonList( 88 a(Map.of(), genMap(0)) 89 ).iterator(); 90 } 91 92 @DataProvider(name="nonempty") 93 @SuppressWarnings("unchecked") 94 public Iterator<Object[]> nonempty() { 95 return Arrays.asList( 96 a(Map.of(0, "a"), genMap(1)), 97 a(Map.of(0, "a", 1, "b"), genMap(2)), 98 a(Map.of(0, "a", 1, "b", 2, "c"), genMap(3)), 99 a(Map.of(0, "a", 1, "b", 2, "c", 3, "d"), genMap(4)), 100 a(Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e"), genMap(5)), 101 a(Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e", 5, "f"), genMap(6)), 102 a(Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e", 5, "f", 6, "g"), genMap(7)), 103 a(Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e", 5, "f", 6, "g", 7, "h"), genMap(8)), 104 a(Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e", 5, "f", 6, "g", 7, "h", 8, "i"), genMap(9)), 105 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)), 106 a(Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e", 5, "f", 6, "g", 7, "h", 8, "i", 9, "j"), 107 Map.of(4, "e", 5, "f", 6, "g", 7, "h", 8, "i", 9, "j", 0, "a", 1, "b", 2, "c", 3, "d")), 108 a(Map.ofEntries(genEntries(MAX_ENTRIES)), genMap(MAX_ENTRIES)) 109 ).iterator(); 110 } 111 112 @DataProvider(name="all") 113 public Iterator<Object[]> all() { 114 List<Object[]> all = new ArrayList<>(); 115 empty().forEachRemaining(all::add); 116 nonempty().forEachRemaining(all::add); 117 return all.iterator(); 118 } 119 120 @Test(dataProvider="all", expectedExceptions=UnsupportedOperationException.class) 121 public void cannotPutNew(Map<Integer,String> act, Map<Integer,String> exp) { 122 act.put(-1, "xyzzy"); 123 } 124 125 @Test(dataProvider="nonempty", expectedExceptions=UnsupportedOperationException.class) 126 public void cannotPutOld(Map<Integer,String> act, Map<Integer,String> exp) { 127 act.put(0, "a"); 128 } 129 130 @Test(dataProvider="nonempty", expectedExceptions=UnsupportedOperationException.class) 131 public void cannotRemove(Map<Integer,String> act, Map<Integer,String> exp) { 132 act.remove(act.keySet().iterator().next()); 133 } 134 135 @Test(dataProvider="all") 136 public void contentsMatch(Map<Integer,String> act, Map<Integer,String> exp) { 137 assertEquals(act, exp); 138 } 139 140 @Test(dataProvider="all") 141 public void containsAllKeys(Map<Integer,String> act, Map<Integer,String> exp) { 142 assertTrue(act.keySet().containsAll(exp.keySet())); 143 assertTrue(exp.keySet().containsAll(act.keySet())); 144 } 145 146 @Test(dataProvider="all") 147 public void containsAllValues(Map<Integer,String> act, Map<Integer,String> exp) { 148 assertTrue(act.values().containsAll(exp.values())); 149 assertTrue(exp.values().containsAll(act.values())); 150 } 151 152 @Test(expectedExceptions=IllegalArgumentException.class) 153 public void dupKeysDisallowed2() { 154 Map<Integer, String> map = Map.of(0, "a", 0, "b"); 155 } 156 157 @Test(expectedExceptions=IllegalArgumentException.class) 158 public void dupKeysDisallowed3() { 159 Map<Integer, String> map = Map.of(0, "a", 1, "b", 0, "c"); 160 } 161 162 @Test(expectedExceptions=IllegalArgumentException.class) 163 public void dupKeysDisallowed4() { 164 Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 0, "d"); 165 } 166 167 @Test(expectedExceptions=IllegalArgumentException.class) 168 public void dupKeysDisallowed5() { 169 Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 0, "e"); 170 } 171 172 @Test(expectedExceptions=IllegalArgumentException.class) 173 public void dupKeysDisallowed6() { 174 Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e", 175 0, "f"); 176 } 177 178 @Test(expectedExceptions=IllegalArgumentException.class) 179 public void dupKeysDisallowed7() { 180 Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e", 181 5, "f", 0, "g"); 182 } 183 184 @Test(expectedExceptions=IllegalArgumentException.class) 185 public void dupKeysDisallowed8() { 186 Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e", 187 5, "f", 6, "g", 0, "h"); 188 } 189 190 @Test(expectedExceptions=IllegalArgumentException.class) 191 public void dupKeysDisallowed9() { 192 Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e", 193 5, "f", 6, "g", 7, "h", 0, "i"); 194 } 195 196 @Test(expectedExceptions=IllegalArgumentException.class) 197 public void dupKeysDisallowed10() { 198 Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e", 199 5, "f", 6, "g", 7, "h", 8, "i", 0, "j"); 200 } 201 202 @Test(expectedExceptions=IllegalArgumentException.class) 203 public void dupKeysDisallowedN() { 204 Map.Entry<Integer,String>[] entries = genEntries(MAX_ENTRIES); 205 entries[MAX_ENTRIES-1] = Map.entry(0, "xxx"); 206 Map<Integer, String> map = Map.ofEntries(entries); 207 } 208 209 @Test(dataProvider="all") 210 public void hashCodeEquals(Map<Integer,String> act, Map<Integer,String> exp) { 211 assertEquals(act.hashCode(), exp.hashCode()); 212 } 213 214 @Test(expectedExceptions=NullPointerException.class) 215 public void nullKeyDisallowed1() { 216 Map<Integer, String> map = Map.of(null, "a"); 217 } 218 219 @Test(expectedExceptions=NullPointerException.class) 220 public void nullValueDisallowed1() { 221 Map<Integer, String> map = Map.of(0, null); 222 } 223 224 @Test(expectedExceptions=NullPointerException.class) 225 public void nullKeyDisallowed2() { 226 Map<Integer, String> map = Map.of(0, "a", null, "b"); 227 } 228 229 @Test(expectedExceptions=NullPointerException.class) 230 public void nullValueDisallowed2() { 231 Map<Integer, String> map = Map.of(0, "a", 1, null); 232 } 233 234 @Test(expectedExceptions=NullPointerException.class) 235 public void nullKeyDisallowed3() { 236 Map<Integer, String> map = Map.of(0, "a", 1, "b", null, "c"); 237 } 238 239 @Test(expectedExceptions=NullPointerException.class) 240 public void nullValueDisallowed3() { 241 Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, null); 242 } 243 244 @Test(expectedExceptions=NullPointerException.class) 245 public void nullKeyDisallowed4() { 246 Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", null, "d"); 247 } 248 249 @Test(expectedExceptions=NullPointerException.class) 250 public void nullValueDisallowed4() { 251 Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, null); 252 } 253 254 @Test(expectedExceptions=NullPointerException.class) 255 public void nullKeyDisallowed5() { 256 Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", null, "e"); 257 } 258 259 @Test(expectedExceptions=NullPointerException.class) 260 public void nullValueDisallowed5() { 261 Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, null); 262 } 263 264 @Test(expectedExceptions=NullPointerException.class) 265 public void nullKeyDisallowed6() { 266 Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e", 267 null, "f"); 268 } 269 270 @Test(expectedExceptions=NullPointerException.class) 271 public void nullValueDisallowed6() { 272 Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e", 273 5, null); 274 } 275 276 @Test(expectedExceptions=NullPointerException.class) 277 public void nullKeyDisallowed7() { 278 Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e", 279 5, "f", null, "g"); 280 } 281 282 @Test(expectedExceptions=NullPointerException.class) 283 public void nullValueDisallowed7() { 284 Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e", 285 5, "f", 6, null); 286 } 287 288 @Test(expectedExceptions=NullPointerException.class) 289 public void nullKeyDisallowed8() { 290 Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e", 291 5, "f", 6, "g", null, "h"); 292 } 293 294 @Test(expectedExceptions=NullPointerException.class) 295 public void nullValueDisallowed8() { 296 Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e", 297 5, "f", 6, "g", 7, null); 298 } 299 300 @Test(expectedExceptions=NullPointerException.class) 301 public void nullKeyDisallowed9() { 302 Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e", 303 5, "f", 6, "g", 7, "h", null, "i"); 304 } 305 306 @Test(expectedExceptions=NullPointerException.class) 307 public void nullValueDisallowed9() { 308 Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e", 309 5, "f", 6, "g", 7, "h", 8, null); 310 } 311 312 @Test(expectedExceptions=NullPointerException.class) 313 public void nullKeyDisallowed10() { 314 Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e", 315 5, "f", 6, "g", 7, "h", 8, "i", null, "j"); 316 } 317 318 @Test(expectedExceptions=NullPointerException.class) 319 public void nullValueDisallowed10() { 320 Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e", 321 5, "f", 6, "g", 7, "h", 8, "i", 9, null); 322 } 323 324 @Test(expectedExceptions=NullPointerException.class) 325 public void nullKeyDisallowedN() { 326 Map.Entry<Integer,String>[] entries = genEntries(MAX_ENTRIES); 327 entries[0] = new AbstractMap.SimpleImmutableEntry(null, "a"); 328 Map<Integer, String> map = Map.ofEntries(entries); 329 } 330 331 @Test(expectedExceptions=NullPointerException.class) 332 public void nullValueDisallowedN() { 333 Map.Entry<Integer,String>[] entries = genEntries(MAX_ENTRIES); 334 entries[0] = new AbstractMap.SimpleImmutableEntry(0, null); 335 Map<Integer, String> map = Map.ofEntries(entries); 336 } 337 338 @Test(expectedExceptions=NullPointerException.class) 339 public void nullEntryDisallowedN() { 340 Map.Entry<Integer,String>[] entries = genEntries(MAX_ENTRIES); 341 entries[5] = null; 342 Map<Integer, String> map = Map.ofEntries(entries); 343 } 344 345 @Test(expectedExceptions=NullPointerException.class) 346 public void nullArrayDisallowed() { 347 Map.ofEntries(null); 348 } 349 350 @Test(dataProvider="all") 351 public void serialEquality(Map<Integer, String> act, Map<Integer, String> exp) { 352 // assume that act.equals(exp) tested elsewhere 353 Map<Integer, String> copy = serialClone(act); 354 assertEquals(act, copy); 355 assertEquals(copy, exp); 356 } 357 358 @SuppressWarnings("unchecked") 359 static <T> T serialClone(T obj) { 360 try { 361 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 362 ObjectOutputStream oos = new ObjectOutputStream(baos); 363 oos.writeObject(obj); 364 oos.close(); 365 ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); 366 ObjectInputStream ois = new ObjectInputStream(bais); 367 return (T) ois.readObject(); 368 } catch (IOException | ClassNotFoundException e) { 369 throw new AssertionError(e); 370 } 371 } 372 373 // Map.entry() tests 374 375 @Test(expectedExceptions=NullPointerException.class) 376 public void entryWithNullKeyDisallowed() { 377 Map.Entry<Integer,String> e = Map.entry(null, "x"); 378 } 379 380 @Test(expectedExceptions=NullPointerException.class) 381 public void entryWithNullValueDisallowed() { 382 Map.Entry<Integer,String> e = Map.entry(0, null); 383 } 384 385 @Test 386 public void entryBasicTests() { 387 Map.Entry<String,String> kvh1 = Map.entry("xyzzy", "plugh"); 388 Map.Entry<String,String> kvh2 = Map.entry("foobar", "blurfl"); 389 Map.Entry<String,String> sie = new AbstractMap.SimpleImmutableEntry("xyzzy", "plugh"); 390 391 assertTrue(kvh1.equals(sie)); 392 assertTrue(sie.equals(kvh1)); 393 assertFalse(kvh2.equals(sie)); 394 assertFalse(sie.equals(kvh2)); 395 assertEquals(sie.hashCode(), kvh1.hashCode()); 396 assertEquals(sie.toString(), kvh1.toString()); 397 } 398 399 // compile-time test of wildcards 400 @Test 401 public void entryWildcardTests() { 402 Map.Entry<Integer,Double> e1 = Map.entry(1, 2.0); 403 Map.Entry<Float,Long> e2 = Map.entry(3.0f, 4L); 404 Map<Number,Number> map = Map.ofEntries(e1, e2); 405 assertEquals(map.size(), 2); 406 } 407 408 }