1 /* 2 * Copyright (c) 2012 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 import java.util.Collections; 27 import java.util.Comparator; 28 import java.util.List; 29 import java.util.LinkedList; 30 import java.util.ListIterator; 31 import java.util.concurrent.atomic.AtomicInteger; 32 33 import org.testng.annotations.Test; 34 35 import java.lang.reflect.Constructor; 36 import java.util.ConcurrentModificationException; 37 import java.util.function.Predicate; 38 39 import static org.testng.Assert.*; 40 41 /** 42 * @test 43 * @library testlibrary 44 * @build CollectionAsserts CollectionSupplier 45 * @run testng ListExtensionMethodsTest 46 * @summary Unit tests for extension methods on List 47 */ 48 public class ListExtensionMethodsTest { 49 50 private static final String[] LIST_CLASSES = { 51 "java.util.ArrayList", 52 "java.util.LinkedList", 53 "java.util.Vector", 54 "java.util.concurrent.CopyOnWriteArrayList" 55 }; 56 57 private static final String[] LIST_CME_CLASSES = { 58 "java.util.ArrayList", 59 "java.util.Vector" 60 }; 61 62 private static final Predicate<Integer> P_EVEN = x -> 0 == x % 2; 63 private static final Predicate<Integer> P_ODD = x -> 0 != x % 2; 64 65 private static final Comparator<Integer> BIT_COUNT_COMPARATOR = 66 (x, y) -> Integer.bitCount(x) - Integer.bitCount(y); 67 68 private static final Comparator<AtomicInteger> ATOMIC_INTEGER_COMPARATOR = 69 (x, y) -> x.intValue() - y.intValue(); 70 71 @Test 72 public void testUnmodifiable() throws Exception { 73 final CollectionSupplier supplier = new CollectionSupplier(LIST_CLASSES, 10); 74 for (final CollectionSupplier.TestCase test : supplier.get()) { 75 final List<Integer> list = ((List<Integer>) test.collection); 76 final List<Integer> unmodifiable = Collections.unmodifiableList(list); 77 // forEach does not modify, it should not throw UnsupportedOperationException 78 unmodifiable.forEach((x) -> {}); 79 try { 80 unmodifiable.removeAll(P_EVEN); 81 fail("removeAll on unmodifiable list did not throw exception"); 82 } catch (UnsupportedOperationException ignore) {} 83 try { 84 unmodifiable.replaceAll(x -> x); 85 fail("replaceAll on unmodifiable list did not throw exception"); 86 } catch (UnsupportedOperationException ignore) {} 87 try { 88 unmodifiable.sort((x, y) -> x - y); 89 fail("sort on unmodifiable list did not throw exception"); 90 } catch (UnsupportedOperationException ignore) {} 91 } 92 } 93 94 @Test 95 public void testForNullPointerException() throws Exception { 96 final CollectionSupplier supplier = new CollectionSupplier(LIST_CLASSES, 10); 97 for (final CollectionSupplier.TestCase test : supplier.get()) { 98 final List<Integer> list = ((List<Integer>) test.collection); 99 try { 100 list.forEach(null); 101 fail("forEach with null Block did not throw NPE"); 102 } catch (NullPointerException nx) {} 103 try { 104 list.removeAll((Predicate<? super Integer>) null); 105 fail("removeAll with null Predicate did not throw NPE"); 106 } catch (NullPointerException nx) {} 107 try { 108 list.replaceAll(null); 109 fail("replaceAll with null UnaryOperator did not throw NPE"); 110 } catch (NullPointerException nx) {} 111 try { 112 list.sort(null); 113 fail("sort with null Comparator did not throw NPE"); 114 } catch (NullPointerException nx) {} 115 } 116 } 117 118 @Test 119 public void testForEach() throws Exception { 120 final CollectionSupplier supplier = new CollectionSupplier(LIST_CLASSES, 1000); 121 for (final CollectionSupplier.TestCase test : supplier.get()) { 122 final List<Integer> original = ((List<Integer>) test.original); 123 final List<Integer> list = ((List<Integer>) test.collection); 124 final List<Integer> actual = new LinkedList<>(); 125 list.forEach(actual::add); 126 CollectionAsserts.assertContents(actual, list); 127 CollectionAsserts.assertContents(actual, original); 128 } 129 } 130 131 @Test 132 public void testRemoveAll() throws Exception { 133 final CollectionSupplier supplier = new CollectionSupplier(LIST_CLASSES, 1000); 134 for (final CollectionSupplier.TestCase test : supplier.get()) { 135 final List<Integer> original = ((List<Integer>) test.original); 136 final List<Integer> list = ((List<Integer>) test.collection); 137 list.removeAll(P_ODD); 138 for (final int i : list) { 139 assertTrue((i % 2) == 0); 140 } 141 final ListIterator<Integer> li = list.listIterator(); 142 for (final int i : original) { 143 if (i % 2 == 0) { 144 assertEquals(li.next().intValue(), i); 145 } 146 } 147 assertFalse(li.hasNext()); 148 list.removeAll(P_EVEN); 149 assertTrue(list.isEmpty()); 150 } 151 } 152 153 @Test 154 public void testReplaceAll() throws Exception { 155 final int scale = 3; 156 final CollectionSupplier supplier = new CollectionSupplier(LIST_CLASSES, 1000); 157 for (final CollectionSupplier.TestCase test : supplier.get()) { 158 final List<Integer> original = ((List<Integer>) test.original); 159 final List<Integer> list = ((List<Integer>) test.collection); 160 list.replaceAll(x -> scale * x); 161 for (int i=0; i < original.size(); i++) { 162 assertTrue(list.get(i) == (scale * original.get(i)), "mismatch at index " + i); 163 } 164 } 165 } 166 167 @Test 168 public void testSort() throws Exception { 169 final CollectionSupplier supplier = new CollectionSupplier(LIST_CLASSES, 1000); 170 for (final CollectionSupplier.TestCase test : supplier.get()) { 171 final List<Integer> original = ((List<Integer>) test.original); 172 final List<Integer> list = ((List<Integer>) test.collection); 173 CollectionSupplier.shuffle(list); 174 list.sort(Integer::compare); 175 CollectionAsserts.assertSorted(list, Integer::compare); 176 if (test.name.startsWith("reverse")) { 177 Collections.reverse(list); 178 } 179 CollectionAsserts.assertContents(list, original); 180 181 /* disabled until java.util.Comparators is availlable 182 CollectionSupplier.shuffle(list); 183 list.sort(Comparators.<Integer>naturalOrder()); 184 CollectionAsserts.assertSorted(list, Comparators.<Integer>naturalOrder()); 185 if (test.name.startsWith("reverse")) { 186 Collections.reverse(list); 187 } 188 CollectionAsserts.assertContents(list, original); 189 190 CollectionSupplier.shuffle(list); 191 list.sort(Comparators.<Integer>reverseOrder()); 192 CollectionAsserts.assertSorted(list, Comparators.<Integer>reverseOrder()); 193 if (!test.name.startsWith("reverse")) { 194 Collections.reverse(list); 195 } 196 CollectionAsserts.assertContents(list, original); 197 */ 198 199 CollectionSupplier.shuffle(list); 200 list.sort(BIT_COUNT_COMPARATOR); 201 CollectionAsserts.assertSorted(list, BIT_COUNT_COMPARATOR); 202 // check sort by verifying that bitCount increases and never drops 203 int minBitCount = 0; 204 int bitCount; 205 for (final Integer i : list) { 206 bitCount = Integer.bitCount(i); 207 assertTrue(bitCount >= minBitCount); 208 minBitCount = bitCount; 209 } 210 211 @SuppressWarnings("unchecked") 212 final Class<? extends List<AtomicInteger>> type = 213 (Class<? extends List<AtomicInteger>>) Class.forName(test.className); 214 final Constructor<? extends List<AtomicInteger>> defaultConstructor = type.getConstructor(); 215 final List<AtomicInteger> incomparables = defaultConstructor.newInstance(); 216 217 for (int i=0; i < test.original.size(); i++) { 218 incomparables.add(new AtomicInteger(i)); 219 } 220 CollectionSupplier.shuffle(incomparables); 221 incomparables.sort(ATOMIC_INTEGER_COMPARATOR); 222 for (int i=0; i < test.original.size(); i++) { 223 assertEquals(i, incomparables.get(i).intValue()); 224 } 225 } 226 } 227 228 @Test 229 public void testRemoveAllThrowsCME() throws Exception { 230 final CollectionSupplier supplier = new CollectionSupplier(LIST_CME_CLASSES, 100); 231 for (final CollectionSupplier.TestCase test : supplier.get()) { 232 final List<Integer> list = ((List<Integer>) test.collection); 233 if (list.size() <= 1) { 234 continue; 235 } 236 boolean gotException = false; 237 try { 238 // bad predicate that modifies its list, should throw CME 239 list.removeAll(list::add); 240 } catch (ConcurrentModificationException cme) { 241 gotException = true; 242 } 243 if (!gotException) { 244 fail("expected CME was not thrown from " + test); 245 } 246 } 247 } 248 249 @Test 250 public void testReplaceAllThrowsCME() throws Exception { 251 final CollectionSupplier supplier = new CollectionSupplier(LIST_CME_CLASSES, 100); 252 for (final CollectionSupplier.TestCase test : supplier.get()) { 253 final List<Integer> list = ((List<Integer>) test.collection); 254 if (list.size() <= 1) { 255 continue; 256 } 257 boolean gotException = false; 258 try { 259 // bad predicate that modifies its list, should throw CME 260 list.replaceAll(x -> {int n = 3 * x; list.add(n); return n;}); 261 } catch (ConcurrentModificationException cme) { 262 gotException = true; 263 } 264 if (!gotException) { 265 fail("expected CME was not thrown from " + test); 266 } 267 } 268 } 269 270 @Test 271 public void testSortThrowsCME() throws Exception { 272 final CollectionSupplier supplier = new CollectionSupplier(LIST_CME_CLASSES, 100); 273 for (final CollectionSupplier.TestCase test : supplier.get()) { 274 final List<Integer> list = ((List<Integer>) test.collection); 275 if (list.size() <= 1) { 276 continue; 277 } 278 boolean gotException = false; 279 try { 280 // bad predicate that modifies its list, should throw CME 281 list.sort((x, y) -> {list.add(x); return x - y;}); 282 } catch (ConcurrentModificationException cme) { 283 gotException = true; 284 } 285 if (!gotException) { 286 fail("expected CME was not thrown from " + test); 287 } 288 } 289 } 290 291 }