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 "\n original: " + original + 101 "\n target: " + collection; 102 } 103 } 104 105 /** 106 * Shuffle a list using a PRNG with known seed for repeatability 107 * @param list the list to be shuffled 108 */ 109 public static <E> void shuffle(final List<E> list) { 110 // PRNG with known seed for repeatable tests 111 final Random prng = new Random(13); 112 final int size = list.size(); 113 for (int i=0; i < size; i++) { 114 // random index in interval [i, size) 115 final int j = i + prng.nextInt(size - i); 116 // swap elements at indices i & j 117 final E e = list.get(i); 118 list.set(i, list.get(j)); 119 list.set(j, e); 120 } 121 } 122 123 /** 124 * Create a {@code Supplier} that creates instances of specified collection 125 * classes of specified length. 126 * 127 * @param classNames class names that implement {@code Collection} 128 * @param size the desired size of each collection 129 */ 130 public CollectionSupplier(String[] classNames, int size) { 131 this.classNames = Arrays.copyOf(classNames, classNames.length); 132 this.size = size; 133 } 134 135 @Override 136 public Iterable<TestCase> get() { 137 try { 138 return getThrows(); 139 } catch (Exception e) { 140 throw new TestException(e); 141 } 142 } 143 144 private Iterable<TestCase> getThrows() throws Exception { 145 final Collection<TestCase> collections = new LinkedList<>(); 146 for (final String className : classNames) { 147 @SuppressWarnings("unchecked") 148 final Class<? extends Collection<Integer>> type = 149 (Class<? extends Collection<Integer>>) Class.forName(className); 150 final Constructor<? extends Collection<Integer>> 151 defaultConstructor = type.getConstructor(); 152 final Constructor<? extends Collection<Integer>> 153 copyConstructor = type.getConstructor(Collection.class); 154 155 final Collection<Integer> empty = defaultConstructor.newInstance(); 156 collections.add(new TestCase("empty", 157 className, 158 copyConstructor.newInstance(empty), 159 empty)); 160 161 final Collection<Integer> single = defaultConstructor.newInstance(); 162 single.add(42); 163 collections.add(new TestCase("single", 164 className, 165 copyConstructor.newInstance(single), 166 single)); 167 168 final Collection<Integer> regular = defaultConstructor.newInstance(); 169 for (int i=0; i < size; i++) { 170 regular.add(i); 171 } 172 collections.add(new TestCase("regular", 173 className, 174 copyConstructor.newInstance(regular), 175 regular)); 176 177 final Collection<Integer> reverse = defaultConstructor.newInstance(); 178 for (int i=size; i >= 0; i--) { 179 reverse.add(i); 180 } 181 collections.add(new TestCase("reverse", 182 className, 183 copyConstructor.newInstance(reverse), 184 reverse)); 185 186 final Collection<Integer> odds = defaultConstructor.newInstance(); 187 for (int i=0; i < size; i++) { 188 odds.add((i * 2) + 1); 189 } 190 collections.add(new TestCase("odds", 191 className, 192 copyConstructor.newInstance(odds), 193 odds)); 194 195 final Collection<Integer> evens = defaultConstructor.newInstance(); 196 for (int i=0; i < size; i++) { 197 evens.add(i * 2); 198 } 199 collections.add(new TestCase("evens", 200 className, 201 copyConstructor.newInstance(evens), 202 evens)); 203 204 final Collection<Integer> fibonacci = defaultConstructor.newInstance(); 205 int prev2 = 0; 206 int prev1 = 1; 207 for (int i=0; i < size; i++) { 208 final int n = prev1 + prev2; 209 if (n < 0) { // stop on overflow 210 break; 211 } 212 fibonacci.add(n); 213 prev2 = prev1; 214 prev1 = n; 215 } 216 collections.add(new TestCase("fibonacci", 217 className, 218 copyConstructor.newInstance(fibonacci), 219 fibonacci)); 220 221 // variants where the size of the backing storage != reported size 222 // created by removing half of the elements 223 224 final Collection<Integer> emptyWithSlack = defaultConstructor.newInstance(); 225 emptyWithSlack.add(42); 226 assertTrue(emptyWithSlack.remove(42)); 227 collections.add(new TestCase("emptyWithSlack", 228 className, 229 copyConstructor.newInstance(emptyWithSlack), 230 emptyWithSlack)); 231 232 final Collection<Integer> singleWithSlack = defaultConstructor.newInstance(); 233 singleWithSlack.add(42); 234 singleWithSlack.add(43); 235 assertTrue(singleWithSlack.remove(43)); 236 collections.add(new TestCase("singleWithSlack", 237 className, 238 copyConstructor.newInstance(singleWithSlack), 239 singleWithSlack)); 240 241 final Collection<Integer> regularWithSlack = defaultConstructor.newInstance(); 242 for (int i=0; i < (2 * size); i++) { 243 regularWithSlack.add(i); 244 } 245 assertTrue(regularWithSlack.removeIf((x) -> {return x >= size;})); 246 collections.add(new TestCase("regularWithSlack", 247 className, 248 copyConstructor.newInstance(regularWithSlack), 249 regularWithSlack)); 250 251 final Collection<Integer> reverseWithSlack = defaultConstructor.newInstance(); 252 for (int i=2 * size; i >= 0; i--) { 253 reverseWithSlack.add(i); 254 } 255 assertTrue(reverseWithSlack.removeIf((x) -> {return x < size;})); 256 collections.add(new TestCase("reverseWithSlack", 257 className, 258 copyConstructor.newInstance(reverseWithSlack), 259 reverseWithSlack)); 260 261 final Collection<Integer> oddsWithSlack = defaultConstructor.newInstance(); 262 for (int i = 0; i < 2 * size; i++) { 263 oddsWithSlack.add((i * 2) + 1); 264 } 265 assertTrue(oddsWithSlack.removeIf((x) -> {return x >= size;})); 266 collections.add(new TestCase("oddsWithSlack", 267 className, 268 copyConstructor.newInstance(oddsWithSlack), 269 oddsWithSlack)); 270 271 final Collection<Integer> evensWithSlack = defaultConstructor.newInstance(); 272 for (int i = 0; i < 2 * size; i++) { 273 evensWithSlack.add(i * 2); 274 } 275 assertTrue(evensWithSlack.removeIf((x) -> {return x >= size;})); 276 collections.add(new TestCase("evensWithSlack", 277 className, 278 copyConstructor.newInstance(evensWithSlack), 279 evensWithSlack)); 280 281 final Collection<Integer> fibonacciWithSlack = defaultConstructor.newInstance(); 282 prev2 = 0; 283 prev1 = 1; 284 for (int i=0; i < size; i++) { 285 final int n = prev1 + prev2; 286 if (n < 0) { // stop on overflow 287 break; 288 } 289 fibonacciWithSlack.add(n); 290 prev2 = prev1; 291 prev1 = n; 292 } 293 assertTrue(fibonacciWithSlack.removeIf((x) -> {return x < 20;})); 294 collections.add(new TestCase("fibonacciWithSlack", 295 className, 296 copyConstructor.newInstance(fibonacciWithSlack), 297 fibonacciWithSlack)); 298 299 } 300 301 return collections; 302 } 303 304 }