1 /* 2 * Copyright (c) 2015, 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(len -> (Map.Entry<Integer,String>[])(new Map.Entry<?,?>[len])); 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.ofEntries(genEntries(MAX_ENTRIES)), genMap(MAX_ENTRIES)) 107 ).iterator(); 108 } 109 110 @DataProvider(name="all") 111 public Iterator<Object[]> all() { 112 List<Object[]> all = new ArrayList<>(); 113 empty().forEachRemaining(all::add); 114 nonempty().forEachRemaining(all::add); 115 return all.iterator(); 116 } 117 118 @Test(dataProvider="all", expectedExceptions=UnsupportedOperationException.class) 119 public void cannotPutNew(Map<Integer,String> act, Map<Integer,String> exp) { 120 act.put(-1, "xyzzy"); 121 } 122 123 @Test(dataProvider="nonempty", expectedExceptions=UnsupportedOperationException.class) 124 public void cannotPutOld(Map<Integer,String> act, Map<Integer,String> exp) { 125 act.put(0, "a"); 126 } 127 128 @Test(dataProvider="nonempty", expectedExceptions=UnsupportedOperationException.class) 129 public void cannotRemove(Map<Integer,String> act, Map<Integer,String> exp) { 130 act.remove(act.keySet().iterator().next()); 131 } 132 133 @Test(dataProvider="all") 134 public void contentsMatch(Map<Integer,String> act, Map<Integer,String> exp) { 135 assertEquals(act, exp); 136 } 137 138 @Test(expectedExceptions=IllegalArgumentException.class) 139 public void dupKeysDisallowed2() { 140 Map<Integer, String> map = Map.of(0, "a", 0, "b"); 141 } 142 143 @Test(expectedExceptions=IllegalArgumentException.class) 144 public void dupKeysDisallowed3() { 145 Map<Integer, String> map = Map.of(0, "a", 1, "b", 0, "c"); 146 } 147 148 @Test(expectedExceptions=IllegalArgumentException.class) 149 public void dupKeysDisallowed4() { 150 Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 0, "d"); 151 } 152 153 @Test(expectedExceptions=IllegalArgumentException.class) 154 public void dupKeysDisallowed5() { 155 Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 0, "e"); 156 } 157 158 @Test(expectedExceptions=IllegalArgumentException.class) 159 public void dupKeysDisallowed6() { 160 Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e", 161 0, "f"); 162 } 163 164 @Test(expectedExceptions=IllegalArgumentException.class) 165 public void dupKeysDisallowed7() { 166 Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e", 167 5, "f", 0, "g"); 168 } 169 170 @Test(expectedExceptions=IllegalArgumentException.class) 171 public void dupKeysDisallowed8() { 172 Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e", 173 5, "f", 6, "g", 0, "h"); 174 } 175 176 @Test(expectedExceptions=IllegalArgumentException.class) 177 public void dupKeysDisallowed9() { 178 Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e", 179 5, "f", 6, "g", 7, "h", 0, "i"); 180 } 181 182 @Test(expectedExceptions=IllegalArgumentException.class) 183 public void dupKeysDisallowed10() { 184 Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e", 185 5, "f", 6, "g", 7, "h", 8, "i", 0, "j"); 186 } 187 188 @Test(expectedExceptions=IllegalArgumentException.class) 189 public void dupKeysDisallowedN() { 190 Map.Entry<Integer,String>[] entries = genEntries(MAX_ENTRIES); 191 entries[MAX_ENTRIES-1] = Map.entry(0, "xxx"); 192 Map<Integer, String> map = Map.ofEntries(entries); 193 } 194 195 @Test(expectedExceptions=NullPointerException.class) 196 public void nullKeyDisallowed1() { 197 Map<Integer, String> map = Map.of(null, "a"); 198 } 199 200 @Test(expectedExceptions=NullPointerException.class) 201 public void nullValueDisallowed1() { 202 Map<Integer, String> map = Map.of(0, null); 203 } 204 205 @Test(expectedExceptions=NullPointerException.class) 206 public void nullKeyDisallowed2() { 207 Map<Integer, String> map = Map.of(0, "a", null, "b"); 208 } 209 210 @Test(expectedExceptions=NullPointerException.class) 211 public void nullValueDisallowed2() { 212 Map<Integer, String> map = Map.of(0, "a", 1, null); 213 } 214 215 @Test(expectedExceptions=NullPointerException.class) 216 public void nullKeyDisallowed3() { 217 Map<Integer, String> map = Map.of(0, "a", 1, "b", null, "c"); 218 } 219 220 @Test(expectedExceptions=NullPointerException.class) 221 public void nullValueDisallowed3() { 222 Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, null); 223 } 224 225 @Test(expectedExceptions=NullPointerException.class) 226 public void nullKeyDisallowed4() { 227 Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", null, "d"); 228 } 229 230 @Test(expectedExceptions=NullPointerException.class) 231 public void nullValueDisallowed4() { 232 Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, null); 233 } 234 235 @Test(expectedExceptions=NullPointerException.class) 236 public void nullKeyDisallowed5() { 237 Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", null, "e"); 238 } 239 240 @Test(expectedExceptions=NullPointerException.class) 241 public void nullValueDisallowed5() { 242 Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, null); 243 } 244 245 @Test(expectedExceptions=NullPointerException.class) 246 public void nullKeyDisallowed6() { 247 Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e", 248 null, "f"); 249 } 250 251 @Test(expectedExceptions=NullPointerException.class) 252 public void nullValueDisallowed6() { 253 Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e", 254 5, null); 255 } 256 257 @Test(expectedExceptions=NullPointerException.class) 258 public void nullKeyDisallowed7() { 259 Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e", 260 5, "f", null, "g"); 261 } 262 263 @Test(expectedExceptions=NullPointerException.class) 264 public void nullValueDisallowed7() { 265 Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e", 266 5, "f", 6, null); 267 } 268 269 @Test(expectedExceptions=NullPointerException.class) 270 public void nullKeyDisallowed8() { 271 Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e", 272 5, "f", 6, "g", null, "h"); 273 } 274 275 @Test(expectedExceptions=NullPointerException.class) 276 public void nullValueDisallowed8() { 277 Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e", 278 5, "f", 6, "g", 7, null); 279 } 280 281 @Test(expectedExceptions=NullPointerException.class) 282 public void nullKeyDisallowed9() { 283 Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e", 284 5, "f", 6, "g", 7, "h", null, "i"); 285 } 286 287 @Test(expectedExceptions=NullPointerException.class) 288 public void nullValueDisallowed9() { 289 Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e", 290 5, "f", 6, "g", 7, "h", 8, null); 291 } 292 293 @Test(expectedExceptions=NullPointerException.class) 294 public void nullKeyDisallowed10() { 295 Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e", 296 5, "f", 6, "g", 7, "h", 8, "i", null, "j"); 297 } 298 299 @Test(expectedExceptions=NullPointerException.class) 300 public void nullValueDisallowed10() { 301 Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e", 302 5, "f", 6, "g", 7, "h", 8, "i", 9, null); 303 } 304 305 @Test(expectedExceptions=NullPointerException.class) 306 public void nullKeyDisallowedN() { 307 Map.Entry<Integer,String>[] entries = genEntries(MAX_ENTRIES); 308 entries[0] = new AbstractMap.SimpleImmutableEntry(null, "a"); 309 Map<Integer, String> map = Map.ofEntries(entries); 310 } 311 312 @Test(expectedExceptions=NullPointerException.class) 313 public void nullValueDisallowedN() { 314 Map.Entry<Integer,String>[] entries = genEntries(MAX_ENTRIES); 315 entries[0] = new AbstractMap.SimpleImmutableEntry(0, null); 316 Map<Integer, String> map = Map.ofEntries(entries); 317 } 318 319 @Test(expectedExceptions=NullPointerException.class) 320 public void nullEntryDisallowedN() { 321 Map.Entry<Integer,String>[] entries = genEntries(MAX_ENTRIES); 322 entries[5] = null; 323 Map<Integer, String> map = Map.ofEntries(entries); 324 } 325 326 @Test(expectedExceptions=NullPointerException.class) 327 public void nullArrayDisallowed() { 328 Map.ofEntries(null); 329 } 330 331 @Test(dataProvider="all") 332 public void serialEquality(Map<Integer, String> act, Map<Integer, String> exp) { 333 // assume that act.equals(exp) tested elsewhere 334 Map<Integer, String> copy = serialClone(act); 335 assertEquals(act, copy); 336 assertEquals(copy, exp); 337 } 338 339 @SuppressWarnings("unchecked") 340 static <T> T serialClone(T obj) { 341 try { 342 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 343 ObjectOutputStream oos = new ObjectOutputStream(baos); 344 oos.writeObject(obj); 345 oos.close(); 346 ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); 347 ObjectInputStream ois = new ObjectInputStream(bais); 348 return (T) ois.readObject(); 349 } catch (IOException | ClassNotFoundException e) { 350 throw new AssertionError(e); 351 } 352 } 353 354 // Map.entry() tests 355 356 @Test(expectedExceptions=NullPointerException.class) 357 public void entryWithNullKeyDisallowed() { 358 Map.Entry<Integer,String> e = Map.entry(null, "x"); 359 } 360 361 @Test(expectedExceptions=NullPointerException.class) 362 public void entryWithNullValueDisallowed() { 363 Map.Entry<Integer,String> e = Map.entry(0, null); 364 } 365 366 @Test 367 public void entryBasicTests() { 368 Map.Entry<String,String> kvh1 = Map.entry("xyzzy", "plugh"); 369 Map.Entry<String,String> kvh2 = Map.entry("foobar", "blurfl"); 370 Map.Entry<String,String> sie = new AbstractMap.SimpleImmutableEntry("xyzzy", "plugh"); 371 372 assertTrue(kvh1.equals(sie)); 373 assertTrue(sie.equals(kvh1)); 374 assertFalse(kvh2.equals(sie)); 375 assertFalse(sie.equals(kvh2)); 376 assertEquals(sie.hashCode(), kvh1.hashCode()); 377 assertEquals(sie.toString(), kvh1.toString()); 378 } 379 380 }