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