ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/loops/DequeBash.java
Revision: 1.6
Committed: Mon Sep 13 08:01:18 2010 UTC (13 years, 8 months ago) by jsr166
Branch: MAIN
Changes since 1.5: +27 -33 lines
Log Message:
fix javac warnings; currentTimeMillis => nanoTime

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