ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/loops/DequeBash.java
Revision: 1.3
Committed: Thu Oct 29 23:09:07 2009 UTC (14 years, 6 months ago) by jsr166
Branch: MAIN
Changes since 1.2: +17 -17 lines
Log Message:
whitespace

File Contents

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