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

# User Rev Content
1 dl 1.1 /*
2     * Written by Josh Bloch of Google Inc. and released to the public domain,
3 jsr166 1.7 * as explained at http://creativecommons.org/publicdomain/zero/1.0/.
4 dl 1.1 */
5    
6 jsr166 1.10 import java.io.*;
7 dl 1.1 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 dl 1.13 static int random() {
26     int r = seed;
27     r ^= r << 13; // xorshift
28     r ^= r >>> 17;
29     return seed = r ^ (r << 5);
30 dl 1.1 }
31    
32 dl 1.13 static int random(int bound) {
33     return (random() & 0x7fffffff) % bound;
34 dl 1.1 }
35 dl 1.13
36 jsr166 1.9 public static void main(String[] args) throws Exception {
37 jsr166 1.6 Class<?> cls = Class.forName(args[0]);
38 dl 1.13 long startTime = System.nanoTime();
39     for (int j = 0; j < 200; ++j) {
40 jsr166 1.6 @SuppressWarnings("unchecked")
41 dl 1.1 Deque<Integer> deque = (Deque<Integer>) cls.newInstance();
42     nextTail = 0;
43     nextHead = -1;
44 dl 1.13 mainTest(deque, (random() & ((1 << 20) - 1)));
45 dl 1.1 if (deque.isEmpty()) System.out.print(" ");
46 dl 1.13 if ((j % 10) == 9) System.out.print(".");
47 dl 1.1 }
48 dl 1.13 long now = System.nanoTime();
49     long elapsedTimeMillis = (now - startTime) / (1000L * 1000L);
50     System.out.printf("\ntotal time %d ms\n", elapsedTimeMillis);
51    
52 dl 1.1 }
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 dl 1.2 if ((i & 1023) == 0) {
65 dl 1.1 testIter(deque);
66 dl 1.2 testDescendingIter(deque);
67     }
68 dl 1.1
69     // Test serialization and copying
70     if ((i & 4095) == 0) {
71 jsr166 1.6 testEqual(deque, serialClone(deque));
72     testEqual(deque, copyConstructorClone(deque));
73 dl 1.1 }
74 jsr166 1.3
75 dl 1.1 // Test fancy removal stuff once in a blue moon
76     if ((i & 8191) == 0)
77     testRemove(deque);
78 jsr166 1.8 }
79 dl 1.1
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 jsr166 1.3 static void testIter(Deque<Integer> deque) throws Exception {
90 dl 1.1 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 jsr166 1.3 static void testDescendingIter(Deque<Integer> deque) throws Exception {
102 dl 1.2 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 dl 1.1 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 jsr166 1.3 if (size() == 0)
123 dl 1.1 testEmpty(deque);
124 jsr166 1.3 else
125 dl 1.1 nonEmptyTest(deque);
126    
127     }
128    
129 jsr166 1.3 static void nonEmptyTest(Deque<Integer> deque) throws Exception {
130 dl 1.1 if (deque.getFirst() != nextHead + 1)
131 jsr166 1.3 throw new Exception("getFirst got: " +
132 dl 1.1 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 jsr166 1.3
143 dl 1.1 if (deque.peekLast() != nextTail - 1)
144     throw new Exception("peekLast got: " + deque.peekLast() +
145     " expecting " + (nextTail - 1));
146     if (deque.getLast() != nextTail - 1)
147 jsr166 1.3 throw new Exception("getLast got: " +
148 dl 1.1 deque.getLast() + " expecting " + (nextTail - 1));
149 jsr166 1.3 }
150    
151 dl 1.1 static void randomOp(Deque<Integer> deque) throws Exception {
152 jsr166 1.3
153 dl 1.1 // Perform a random operation
154 jsr166 1.5 switch (random() & 3) {
155 dl 1.1 case 0:
156 jsr166 1.5 switch (random() & 3) {
157 dl 1.1 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 jsr166 1.5 switch (random(3)) {
170 dl 1.1 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 jsr166 1.4 } catch (NoSuchElementException e) {
176 dl 1.1 threw = true;
177     }
178     if (!threw)
179     throw new Exception("Remove-no exception: " + result);
180     } else { // deque nonempty
181     int result = -1;
182 jsr166 1.5 switch (random(5)) {
183 dl 1.1 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 jsr166 1.5 switch (random(3)) {
197 dl 1.1 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 jsr166 1.4 } catch (NoSuchElementException e) {
210 dl 1.1 threw = true;
211     }
212     if (!threw)
213     throw new Exception("Remove-no exception: " + result);
214     } else { // deque nonempty
215 jsr166 1.4 int result = ((random() & 1) == 0 ?
216 dl 1.1 deque.removeLast() : deque.pollLast());
217     if (result != --nextTail)
218     throw new Exception(
219 jsr166 1.4 "Removed "+ result + " expecting "+(nextTail + 1));
220 dl 1.1 }
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 jsr166 1.4 for (int i : d1) {
234 dl 1.1 int j = it.next();
235     if (j != i)
236     throw new Exception("Element " + j + " != " + i);
237     }
238    
239 jsr166 1.4 for (int i : d1)
240 dl 1.1 if (!d2.contains(i))
241     throw new Exception("d2 doesn't contain " + i);
242 jsr166 1.4 for (int i : d2)
243 dl 1.1 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 jsr166 1.6 @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 dl 1.1 return (T) ois.readObject();
282     }
283    
284     private static void testRemove(Deque<Integer> deque) throws Exception {
285 jsr166 1.6 Deque<Integer> copy = ((random() & 1) == 0) ?
286     copyConstructorClone(deque) :
287     serialClone(deque);
288 dl 1.1
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 jsr166 1.5 switch (random(3)) {
311 dl 1.1 case 0: removed = copy.remove(e); break;
312     case 1: removed = copy.removeFirstOccurrence(e); break;
313     case 2: removed = copy.removeLastOccurrence(e); break;
314 jsr166 1.3 default: throw new Exception("How'd we get here");
315 dl 1.1 }
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 jsr166 1.6 copy = copyConstructorClone(deque);
326 dl 1.1 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 jsr166 1.4 result = ((random() & 1) == 0 ?
358 dl 1.1 deque.getFirst() : deque.element());
359 jsr166 1.4 } catch (NoSuchElementException e) {
360 dl 1.1 threw = true;
361     }
362     if (!threw)
363     throw new Exception("getFirst-no exception: "+result);
364     threw = false;
365     try {
366     result = deque.getLast();
367 jsr166 1.4 } catch (NoSuchElementException e) {
368 dl 1.1 threw = true;
369     }
370     if (!threw)
371     throw new Exception("getLast-no exception: "+result);
372     }
373    
374     }
375     }