ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/loops/DequeBash.java
Revision: 1.13
Committed: Sat Oct 22 19:30:48 2016 UTC (7 years, 6 months ago) by dl
Branch: MAIN
Changes since 1.12: +16 -19 lines
Log Message:
longer randomized tests

File Contents

# Content
1 /*
2 * Written by Josh Bloch of Google Inc. and released to the public domain,
3 * as explained at http://creativecommons.org/publicdomain/zero/1.0/.
4 */
5
6 import java.io.*;
7 import java.util.*;
8
9 /**
10 * Interface-based Deque tester. This test currently makes three
11 * assumptions about the implementation under test:
12 *
13 * 1) It has no size limitation.
14 * 2) It implements Serializable.
15 * 3) It has a conventional (Collection) constructor.
16 *
17 * All of these assumptions could be relaxed.
18 */
19 public class DequeBash {
20 static int seed = 7;
21 static int nextTail = 0;
22 static int nextHead = -1;
23 static int size() { return nextTail - nextHead - 1; }
24
25 static int random() {
26 int r = seed;
27 r ^= r << 13; // xorshift
28 r ^= r >>> 17;
29 return seed = r ^ (r << 5);
30 }
31
32 static int random(int bound) {
33 return (random() & 0x7fffffff) % bound;
34 }
35
36 public static void main(String[] args) throws Exception {
37 Class<?> cls = Class.forName(args[0]);
38 long startTime = System.nanoTime();
39 for (int j = 0; j < 200; ++j) {
40 @SuppressWarnings("unchecked")
41 Deque<Integer> deque = (Deque<Integer>) cls.newInstance();
42 nextTail = 0;
43 nextHead = -1;
44 mainTest(deque, (random() & ((1 << 20) - 1)));
45 if (deque.isEmpty()) System.out.print(" ");
46 if ((j % 10) == 9) System.out.print(".");
47 }
48 long now = System.nanoTime();
49 long elapsedTimeMillis = (now - startTime) / (1000L * 1000L);
50 System.out.printf("\ntotal time %d ms\n", elapsedTimeMillis);
51
52 }
53
54 static void mainTest(Deque<Integer> deque, int n) throws Exception {
55 /*
56 * Perform a random sequence of operations, keeping contiguous
57 * sequence of integers on the deque.
58 */
59 for (int i = 0; i < n; i++) {
60 sizeTests(deque);
61 randomOp(deque);
62
63 // Test iterator occasionally
64 if ((i & 1023) == 0) {
65 testIter(deque);
66 testDescendingIter(deque);
67 }
68
69 // Test serialization and copying
70 if ((i & 4095) == 0) {
71 testEqual(deque, serialClone(deque));
72 testEqual(deque, copyConstructorClone(deque));
73 }
74
75 // Test fancy removal stuff once in a blue moon
76 if ((i & 8191) == 0)
77 testRemove(deque);
78 }
79
80 // Stupid tests for clear, toString
81 deque.clear();
82 testEmpty(deque);
83 Collection<Integer> c = Arrays.asList(1, 2, 3);
84 deque.addAll(c);
85 if (!deque.toString().equals("[1, 2, 3]"))
86 throw new Exception("Deque.toString(): " + deque.toString());
87 }
88
89 static void testIter(Deque<Integer> deque) throws Exception {
90 int next = nextHead + 1;
91 int count = 0;
92 for (int j : deque) {
93 if (j != next++)
94 throw new Exception("Element "+ j + " != " + (next-1));
95 count++;
96 }
97 if (count != size())
98 throw new Exception("Count " + count + " != " + size());
99 }
100
101 static void testDescendingIter(Deque<Integer> deque) throws Exception {
102 int next = deque.size() + nextHead;
103 int count = 0;
104 for (Iterator<Integer> it = deque.descendingIterator(); it.hasNext();) {
105 int j = it.next();
106 if (j != next--)
107 throw new Exception("Element "+ j + " != " + (next-1));
108 count++;
109 }
110 if (count != size())
111 throw new Exception("Count " + count + " != " + size());
112 }
113
114 static void sizeTests(Deque<Integer> deque) throws Exception {
115 if (deque.size() != size())
116 throw new Exception("Size: " + deque.size() +
117 ", expecting " + size());
118 if (deque.isEmpty() != (size() == 0))
119 throw new Exception(
120 "IsEmpty " + deque.isEmpty() + ", size " + size());
121 // Check head and tail
122 if (size() == 0)
123 testEmpty(deque);
124 else
125 nonEmptyTest(deque);
126
127 }
128
129 static void nonEmptyTest(Deque<Integer> deque) throws Exception {
130 if (deque.getFirst() != nextHead + 1)
131 throw new Exception("getFirst got: " +
132 deque.getFirst() + " expecting " + (nextHead + 1));
133 if (deque.element() != nextHead + 1)
134 throw new Exception("element got: " + deque.element() +
135 " expecting " + (nextHead + 1));
136 if (deque.peekFirst() != nextHead + 1)
137 throw new Exception("peekFirst got: "+deque.peekFirst() +
138 " expecting " + (nextHead + 1));
139 if (deque.peek() != nextHead + 1)
140 throw new Exception("peek got: " + deque.peek() +
141 " expecting " + (nextHead + 1));
142
143 if (deque.peekLast() != nextTail - 1)
144 throw new Exception("peekLast got: " + deque.peekLast() +
145 " expecting " + (nextTail - 1));
146 if (deque.getLast() != nextTail - 1)
147 throw new Exception("getLast got: " +
148 deque.getLast() + " expecting " + (nextTail - 1));
149 }
150
151 static void randomOp(Deque<Integer> deque) throws Exception {
152
153 // Perform a random operation
154 switch (random() & 3) {
155 case 0:
156 switch (random() & 3) {
157 case 0: deque.addLast(nextTail++); break;
158 case 1: deque.offerLast(nextTail++); break;
159 case 2: deque.offer(nextTail++); break;
160 case 3: deque.add(nextTail++); break;
161 default: throw new Exception("How'd we get here");
162 }
163 break;
164 case 1:
165 if (size() == 0) {
166 int result = 666;
167 boolean threw = false;
168 try {
169 switch (random(3)) {
170 case 0: result = deque.removeFirst(); break;
171 case 1: result = deque.remove(); break;
172 case 2: result = deque.pop(); break;
173 default: throw new Exception("How'd we get here");
174 }
175 } catch (NoSuchElementException e) {
176 threw = true;
177 }
178 if (!threw)
179 throw new Exception("Remove-no exception: " + result);
180 } else { // deque nonempty
181 int result = -1;
182 switch (random(5)) {
183 case 0: result = deque.removeFirst(); break;
184 case 1: result = deque.remove(); break;
185 case 2: result = deque.pop(); break;
186 case 3: result = deque.pollFirst(); break;
187 case 4: result = deque.poll(); break;
188 default: throw new Exception("How'd we get here");
189 }
190 if (result != ++nextHead)
191 throw new Exception(
192 "Removed "+ result + " expecting "+(nextHead - 1));
193 }
194 break;
195 case 2:
196 switch (random(3)) {
197 case 0: deque.addFirst(nextHead--); break;
198 case 1: deque.offerFirst(nextHead--); break;
199 case 2: deque.push(nextHead--); break;
200 default: throw new Exception("How'd we get here");
201 }
202 break;
203 case 3:
204 if (size() == 0) {
205 int result = -1;
206 boolean threw = false;
207 try {
208 result = deque.removeLast();
209 } catch (NoSuchElementException e) {
210 threw = true;
211 }
212 if (!threw)
213 throw new Exception("Remove-no exception: " + result);
214 } else { // deque nonempty
215 int result = ((random() & 1) == 0 ?
216 deque.removeLast() : deque.pollLast());
217 if (result != --nextTail)
218 throw new Exception(
219 "Removed "+ result + " expecting "+(nextTail + 1));
220 }
221 break;
222 default:
223 throw new Exception("How'd we get here");
224 }
225 }
226
227 private static void testEqual(Deque<Integer> d1, Deque<Integer> d2)
228 throws Exception
229 {
230 if (d1.size() != d2.size())
231 throw new Exception("Size " + d1.size() + " != " + d2.size());
232 Iterator<Integer> it = d2.iterator();
233 for (int i : d1) {
234 int j = it.next();
235 if (j != i)
236 throw new Exception("Element " + j + " != " + i);
237 }
238
239 for (int i : d1)
240 if (!d2.contains(i))
241 throw new Exception("d2 doesn't contain " + i);
242 for (int i : d2)
243 if (!d1.contains(i))
244 throw new Exception("d2 doesn't contain " + i);
245
246 if (d1.contains(Integer.MIN_VALUE))
247 throw new Exception("d2 contains Integer.MIN_VALUE");
248 if (d2.contains(Integer.MIN_VALUE))
249 throw new Exception("d2 contains Integer.MIN_VALUE");
250 if (d1.contains(null))
251 throw new Exception("d1 contains null");
252 if (d2.contains(null))
253 throw new Exception("d2 contains null");
254
255 if (!d1.containsAll(d2))
256 throw new Exception("d1 doesn't contain all of d2");
257 if (!d2.containsAll(d1))
258 throw new Exception("d2 doesn't contain all of d1");
259 Collection<Integer> c = Collections.singleton(Integer.MIN_VALUE);
260 if (d1.containsAll(c))
261 throw new Exception("d1 contains all of {Integer.MIN_VALUE }");
262 if (d2.containsAll(c))
263 throw new Exception("d2 contains all of {Integer.MIN_VALUE }");
264 }
265
266 @SuppressWarnings("unchecked")
267 private static <T> T copyConstructorClone(T o) throws Exception {
268 return (T) o.getClass().getConstructor(Collection.class).newInstance(o);
269 }
270
271 @SuppressWarnings("unchecked")
272 private static <T> T serialClone(T o) throws Exception {
273 ByteArrayOutputStream bos = new ByteArrayOutputStream();
274 ObjectOutputStream oos = new ObjectOutputStream(bos);
275 oos.writeObject(o);
276 oos.flush();
277 oos.close();
278 ByteArrayInputStream bin =
279 new ByteArrayInputStream(bos.toByteArray());
280 ObjectInputStream ois = new ObjectInputStream(bin);
281 return (T) ois.readObject();
282 }
283
284 private static void testRemove(Deque<Integer> deque) throws Exception {
285 Deque<Integer> copy = ((random() & 1) == 0) ?
286 copyConstructorClone(deque) :
287 serialClone(deque);
288
289 int numRemoved = 0;
290 for (Iterator<Integer> it = copy.iterator(); it.hasNext(); ) {
291 if ((it.next() & 1) == 0) {
292 it.remove();
293 numRemoved++;
294 }
295 }
296
297 if (copy.size() + numRemoved != size())
298 throw new Exception((copy.size() + numRemoved) + " != " + size());
299 for (int i : copy)
300 if ((i & 1) == 0)
301 throw new Exception("Even number still present: " + i);
302
303 List<Integer> elements = Arrays.asList(copy.toArray(new Integer[0]));
304 Collections.shuffle(elements);
305 for (int e : elements) {
306 if (!copy.contains(e))
307 throw new Exception(e + " missing.");
308
309 boolean removed = false;
310 switch (random(3)) {
311 case 0: removed = copy.remove(e); break;
312 case 1: removed = copy.removeFirstOccurrence(e); break;
313 case 2: removed = copy.removeLastOccurrence(e); break;
314 default: throw new Exception("How'd we get here");
315 }
316 if (!removed)
317 throw new Exception(e + " not removed.");
318
319 if (copy.contains(e))
320 throw new Exception(e + " present after removal.");
321 }
322
323 testEmpty(copy);
324
325 copy = copyConstructorClone(deque);
326 copy.retainAll(deque);
327 testEqual(deque, copy);
328 copy.removeAll(deque);
329 testEmpty(copy);
330 }
331
332 static boolean checkedThrows;
333
334 private static void testEmpty(Deque<Integer> deque) throws Exception {
335 if (!deque.isEmpty())
336 throw new Exception("Deque isn't empty");
337 if (deque.size() != 0)
338 throw new Exception("Deque size isn't zero");
339 if (!(deque.pollFirst() == null))
340 throw new Exception("pollFirst lies");
341 if (!(deque.poll() == null))
342 throw new Exception("poll lies");
343 if (!(deque.peekFirst() == null))
344 throw new Exception("peekFirst lies");
345 if (!(deque.peek() == null))
346 throw new Exception("peek lies");
347 if (!(deque.pollLast() == null))
348 throw new Exception("pollLast lies");
349 if (!(deque.peekLast() == null))
350 throw new Exception("peekLast lies");
351
352 if (!checkedThrows) {
353 checkedThrows = true;
354 boolean threw = false;
355 int result = 666;
356 try {
357 result = ((random() & 1) == 0 ?
358 deque.getFirst() : deque.element());
359 } catch (NoSuchElementException e) {
360 threw = true;
361 }
362 if (!threw)
363 throw new Exception("getFirst-no exception: "+result);
364 threw = false;
365 try {
366 result = deque.getLast();
367 } catch (NoSuchElementException e) {
368 threw = true;
369 }
370 if (!threw)
371 throw new Exception("getLast-no exception: "+result);
372 }
373
374 }
375 }