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