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