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. 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.lang.Exception; 25 import java.lang.Integer; 26 import java.lang.Iterable; 27 import java.lang.Override; 28 import java.util.Arrays; 29 import java.util.LinkedList; 30 import java.util.List; 31 import java.util.Random; 32 import java.util.Set; 33 34 import org.testng.TestException; 35 36 import static org.testng.Assert.assertTrue; 37 38 import java.lang.reflect.Constructor; 39 import java.util.Collection; 40 import java.util.Collections; 41 import java.util.function.Supplier; 42 43 /** 44 * @library 45 * @summary A Supplier of test cases for Collection tests 46 */ 47 public final class CollectionSupplier implements Supplier<Iterable<CollectionSupplier.TestCase>> { 48 49 private final String[] classNames; 50 private final int size; 51 52 /** 53 * A Collection test case. 54 */ 55 public static final class TestCase { 56 57 /** 58 * The name of the test case. 59 */ 60 public final String name; 61 62 /** 63 * Class name of the instantiated Collection. 64 */ 65 public final String className; 66 67 /** 68 * Unmodifiable reference collection, useful for comparisons. 69 */ 70 public final Collection<Integer> original; 71 72 /** 73 * A modifiable test collection. 74 */ 75 public final Collection<Integer> collection; 76 77 /** 78 * Create a Collection test case. 79 * @param name name of the test case 80 * @param className class name of the instantiated collection 81 * @param original reference collection 82 * @param collection the modifiable test collection 83 */ 84 public TestCase(String name, String className, 85 Collection<Integer> original, Collection<Integer> collection) { 86 this.name = name; 87 this.className = className; 88 this.original = 89 List.class.isAssignableFrom(original.getClass()) ? 90 Collections.unmodifiableList((List<Integer>) original) : 91 Set.class.isAssignableFrom(original.getClass()) ? 92 Collections.unmodifiableSet((Set<Integer>) original) : 93 Collections.unmodifiableCollection(original); 94 this.collection = collection; 95 } 96 97 @Override 98 public String toString() { 99 return name + " " + className; 100 } 101 } 102 103 /** 104 * Shuffle a list using a PRNG with known seed for repeatability 105 * @param list the list to be shuffled 106 */ 107 public static <E> void shuffle(final List<E> list) { 108 // PRNG with known seed for repeatable tests 109 final Random prng = new Random(13); 110 final int size = list.size(); 111 for (int i=0; i < size; i++) { 112 // random index in interval [i, size) 113 final int j = i + prng.nextInt(size - i); 114 // swap elements at indices i & j 115 final E e = list.get(i); 116 list.set(i, list.get(j)); 117 list.set(j, e); 118 } 119 } 120 121 /** 122 * Create a {@code Supplier} that creates instances of specified collection 123 * classes of specified length. 124 * 125 * @param classNames class names that implement {@code Collection} 126 * @param size the desired size of each collection 127 */ 128 public CollectionSupplier(String[] classNames, int size) { 129 this.classNames = Arrays.copyOf(classNames, classNames.length); 130 this.size = size; 131 } 132 133 @Override 134 public Iterable<TestCase> get() { 135 try { 136 return getThrows(); 137 } catch (Exception e) { 138 throw new TestException(e); 139 } 140 } 141 142 private Iterable<TestCase> getThrows() throws Exception { 143 final Collection<TestCase> collections = new LinkedList<>(); 144 for (final String className : classNames) { 145 @SuppressWarnings("unchecked") 146 final Class<? extends Collection<Integer>> type = 147 (Class<? extends Collection<Integer>>) Class.forName(className); 148 final Constructor<? extends Collection<Integer>> 149 defaultConstructor = type.getConstructor(); 150 final Constructor<? extends Collection<Integer>> 151 copyConstructor = type.getConstructor(Collection.class); 152 153 final Collection<Integer> empty = defaultConstructor.newInstance(); 154 collections.add(new TestCase("empty", 155 className, 156 copyConstructor.newInstance(empty), 157 empty)); 158 159 final Collection<Integer> single = defaultConstructor.newInstance(); 160 single.add(42); 161 collections.add(new TestCase("single", 162 className, 163 copyConstructor.newInstance(single), 164 single)); 165 166 final Collection<Integer> regular = defaultConstructor.newInstance(); 167 for (int i=0; i < size; i++) { 168 regular.add(i); 169 } 170 collections.add(new TestCase("regular", 171 className, 172 copyConstructor.newInstance(regular), 173 regular)); 174 175 final Collection<Integer> reverse = defaultConstructor.newInstance(); 176 for (int i=size; i >= 0; i--) { 177 reverse.add(i); 178 } 179 collections.add(new TestCase("reverse", 180 className, 181 copyConstructor.newInstance(reverse), 182 reverse)); 183 184 final Collection<Integer> odds = defaultConstructor.newInstance(); 185 for (int i=0; i < size; i++) { 186 odds.add((i * 2) + 1); 187 } 188 collections.add(new TestCase("odds", 189 className, 190 copyConstructor.newInstance(odds), 191 odds)); 192 193 final Collection<Integer> evens = defaultConstructor.newInstance(); 194 for (int i=0; i < size; i++) { 195 evens.add(i * 2); 196 } 197 collections.add(new TestCase("evens", 198 className, 199 copyConstructor.newInstance(evens), 200 evens)); 201 202 final Collection<Integer> fibonacci = defaultConstructor.newInstance(); 203 int prev2 = 0; 204 int prev1 = 1; 205 for (int i=0; i < size; i++) { 206 final int n = prev1 + prev2; 207 if (n < 0) { // stop on overflow 208 break; 209 } 210 fibonacci.add(n); 211 prev2 = prev1; 212 prev1 = n; 213 } 214 collections.add(new TestCase("fibonacci", 215 className, 216 copyConstructor.newInstance(fibonacci), 217 fibonacci)); 218 219 // variants where the size of the backing storage != reported size 220 // created by removing half of the elements 221 222 final Collection<Integer> emptyWithSlack = defaultConstructor.newInstance(); 223 emptyWithSlack.add(42); 224 assertTrue(emptyWithSlack.remove(42)); 225 collections.add(new TestCase("emptyWithSlack", 226 className, 227 copyConstructor.newInstance(emptyWithSlack), 228 emptyWithSlack)); 229 230 final Collection<Integer> singleWithSlack = defaultConstructor.newInstance(); 231 singleWithSlack.add(42); 232 singleWithSlack.add(43); 233 assertTrue(singleWithSlack.remove(43)); 234 collections.add(new TestCase("singleWithSlack", 235 className, 236 copyConstructor.newInstance(singleWithSlack), 237 singleWithSlack)); 238 239 final Collection<Integer> regularWithSlack = defaultConstructor.newInstance(); 240 for (int i=0; i < (2 * size); i++) { 241 regularWithSlack.add(i); 242 } 243 assertTrue(regularWithSlack.removeIf((x) -> {return x >= size;})); 244 collections.add(new TestCase("regularWithSlack", 245 className, 246 copyConstructor.newInstance(regularWithSlack), 247 regularWithSlack)); 248 249 final Collection<Integer> reverseWithSlack = defaultConstructor.newInstance(); 250 for (int i=2 * size; i >= 0; i--) { 251 reverseWithSlack.add(i); 252 } 253 assertTrue(reverseWithSlack.removeIf((x) -> {return x < size;})); 254 collections.add(new TestCase("reverseWithSlack", 255 className, 256 copyConstructor.newInstance(reverseWithSlack), 257 reverseWithSlack)); 258 259 final Collection<Integer> oddsWithSlack = defaultConstructor.newInstance(); 260 for (int i = 0; i < 2 * size; i++) { 261 oddsWithSlack.add((i * 2) + 1); 262 } 263 assertTrue(oddsWithSlack.removeIf((x) -> {return x >= size;})); 264 collections.add(new TestCase("oddsWithSlack", 265 className, 266 copyConstructor.newInstance(oddsWithSlack), 267 oddsWithSlack)); 268 269 final Collection<Integer> evensWithSlack = defaultConstructor.newInstance(); 270 for (int i = 0; i < 2 * size; i++) { 271 evensWithSlack.add(i * 2); 272 } 273 assertTrue(evensWithSlack.removeIf((x) -> {return x >= size;})); 274 collections.add(new TestCase("evensWithSlack", 275 className, 276 copyConstructor.newInstance(evensWithSlack), 277 evensWithSlack)); 278 279 final Collection<Integer> fibonacciWithSlack = defaultConstructor.newInstance(); 280 prev2 = 0; 281 prev1 = 1; 282 for (int i=0; i < size; i++) { 283 final int n = prev1 + prev2; 284 if (n < 0) { // stop on overflow 285 break; 286 } 287 fibonacciWithSlack.add(n); 288 prev2 = prev1; 289 prev1 = n; 290 } 291 assertTrue(fibonacciWithSlack.removeIf((x) -> {return x < 20;})); 292 collections.add(new TestCase("fibonacciWithSlack", 293 className, 294 copyConstructor.newInstance(fibonacciWithSlack), 295 fibonacciWithSlack)); 296 297 } 298 299 return collections; 300 } 301 302 }