1 /*
2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3  *
4  * This code is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License version 2 only, as
6  * published by the Free Software Foundation.
7  *
8  * This code is distributed in the hope that it will be useful, but WITHOUT
9  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
11  * version 2 for more details (a copy is included in the LICENSE file that
12  * accompanied this code).
13  *
14  * You should have received a copy of the GNU General Public License version
15  * 2 along with this work; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
17  *
18  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
19  * or visit www.oracle.com if you need additional information or have any
20  * questions.
21  */
22 
23 /*
24  * This file is available under and governed by the GNU General Public
25  * License version 2 only, as published by the Free Software Foundation.
26  * However, the following notice accompanied the original version of this
27  * file:
28  *
29  * Written by Doug Lea and Martin Buchholz with assistance from
30  * members of JCP JSR-166 Expert Group and released to the public
31  * domain, as explained at
32  * http://creativecommons.org/publicdomain/zero/1.0/
33  */
34 
35 /*
36  * @test
37  * @summary Test drainTo failing due to c.add throwing
38  */
39 
40 import java.util.ArrayList;
41 import java.util.List;
42 import java.util.concurrent.DelayQueue;
43 import java.util.concurrent.Delayed;
44 import java.util.concurrent.ArrayBlockingQueue;
45 import java.util.concurrent.BlockingQueue;
46 import java.util.concurrent.LinkedBlockingDeque;
47 import java.util.concurrent.LinkedBlockingQueue;
48 import java.util.concurrent.FutureTask;
49 import java.util.concurrent.PriorityBlockingQueue;
50 import java.util.concurrent.RunnableScheduledFuture;
51 import java.util.concurrent.ScheduledThreadPoolExecutor;
52 import java.util.concurrent.TimeUnit;
53 
54 @SuppressWarnings({"unchecked", "rawtypes"})
55 public class DrainToFails {
56     final int CAPACITY = 10;
57     final int SMALL = 2;
58 
test(String[] args)59     void test(String[] args) throws Throwable {
60         testDelayQueue(new DelayQueue());
61         testDelayQueue(new ScheduledThreadPoolExecutor(1).getQueue());
62 
63         testUnbounded(new LinkedBlockingQueue());
64         testUnbounded(new LinkedBlockingDeque());
65         testUnbounded(new PriorityBlockingQueue());
66 
67         testBounded(new LinkedBlockingQueue(CAPACITY));
68         testBounded(new LinkedBlockingDeque(CAPACITY));
69         testBounded(new ArrayBlockingQueue(CAPACITY));
70     }
71 
72     static class PDelay
73         extends FutureTask<Void>
74         implements Delayed, RunnableScheduledFuture<Void> {
75         int pseudodelay;
PDelay(int i)76         PDelay(int i) {
77             super(new Runnable() { public void run() {}}, null);
78             pseudodelay = i;
79         }
compareTo(PDelay other)80         public int compareTo(PDelay other) {
81             return Integer.compare(this.pseudodelay, other.pseudodelay);
82         }
compareTo(Delayed y)83         public int compareTo(Delayed y) {
84             return compareTo((PDelay)y);
85         }
equals(Object other)86         public boolean equals(Object other) {
87             return (other instanceof PDelay) &&
88                 this.pseudodelay == ((PDelay)other).pseudodelay;
89         }
getDelay(TimeUnit ignore)90         public long getDelay(TimeUnit ignore) {
91             return Integer.MIN_VALUE + pseudodelay;
92         }
toString()93         public String toString() {
94             return String.valueOf(pseudodelay);
95         }
isPeriodic()96         public boolean isPeriodic() { return false; }
97     }
98 
testDelayQueue(final BlockingQueue q)99     void testDelayQueue(final BlockingQueue q) throws Throwable {
100         System.err.println(q.getClass().getSimpleName());
101         for (int i = 0; i < CAPACITY; i++)
102             q.add(new PDelay(i));
103         ArrayBlockingQueue q2 = new ArrayBlockingQueue(SMALL);
104         try {
105             q.drainTo(q2, SMALL + 3);
106             fail("should throw");
107         } catch (IllegalStateException success) {
108             equal(SMALL, q2.size());
109             equal(new PDelay(0), q2.poll());
110             equal(new PDelay(1), q2.poll());
111             check(q2.isEmpty());
112             for (int i = SMALL; i < CAPACITY; i++)
113                 equal(new PDelay(i), q.poll());
114             equal(0, q.size());
115         }
116     }
117 
testUnbounded(final BlockingQueue q)118     void testUnbounded(final BlockingQueue q) throws Throwable {
119         System.err.println(q.getClass().getSimpleName());
120         for (int i = 0; i < CAPACITY; i++)
121             q.add(i);
122         ArrayBlockingQueue q2 = new ArrayBlockingQueue(SMALL);
123         try {
124             q.drainTo(q2, 7);
125             fail("should throw");
126         } catch (IllegalStateException success) {
127             assertContentsInOrder(q2, 0, 1);
128             q2.clear();
129             equal(q.size(), CAPACITY - SMALL);
130             equal(SMALL, q.peek());
131         }
132 
133         try {
134             q.drainTo(q2);
135             fail("should throw");
136         } catch (IllegalStateException success) {
137             assertContentsInOrder(q2, 2, 3);
138             equal(q.size(), CAPACITY - 2 * SMALL);
139             for (int i = 2 * SMALL; i < CAPACITY; i++)
140                 equal(i, q.poll());
141             equal(0, q.size());
142         }
143     }
144 
testBounded(final BlockingQueue q)145     void testBounded(final BlockingQueue q) throws Throwable {
146         System.err.println(q.getClass().getSimpleName());
147         for (int i = 0; i < CAPACITY; i++)
148             q.add(i);
149         List<Thread> putters = new ArrayList<>();
150         for (int i = 0; i < 4; i++) {
151             Thread putter = new Thread(putter(q, 42 + i));
152             putters.add(putter);
153             putter.setDaemon(true);
154             putter.start();
155         }
156         ArrayBlockingQueue q2 = new ArrayBlockingQueue(SMALL);
157         try {
158             q.drainTo(q2, 7);
159             fail("should throw");
160         } catch (IllegalStateException success) {
161             while (q.size() < CAPACITY)
162                 Thread.yield();
163             assertContentsInOrder(q2, 0, 1);
164             q2.clear();
165         }
166 
167         try {
168             q.drainTo(q2);
169             fail("should throw");
170         } catch (IllegalStateException success) {
171             for (Thread putter : putters) {
172                 putter.join(2000L);
173                 check(! putter.isAlive());
174             }
175             assertContentsInOrder(q2, 2, 3);
176             for (int i = 2 * SMALL; i < CAPACITY; i++)
177                 equal(i, q.poll());
178             equal(4, q.size());
179             check(q.contains(42));
180             check(q.contains(43));
181             check(q.contains(44));
182             check(q.contains(45));
183         }
184     }
185 
putter(final BlockingQueue q, final int elt)186     Runnable putter(final BlockingQueue q, final int elt) {
187         return new Runnable() {
188             public void run() {
189                 try { q.put(elt); }
190                 catch (Throwable t) { unexpected(t); }}};
191     }
192 
193     void assertContentsInOrder(Iterable it, Object... contents) {
194         int i = 0;
195         for (Object e : it)
196             equal(contents[i++], e);
197         equal(contents.length, i);
198     }
199 
200     //--------------------- Infrastructure ---------------------------
201     volatile int passed = 0, failed = 0;
202     void pass() {passed++;}
203     void fail() {failed++; Thread.dumpStack();}
204     void fail(String msg) {System.err.println(msg); fail();}
205     void unexpected(Throwable t) {failed++; t.printStackTrace();}
206     void check(boolean cond) {if (cond) pass(); else fail();}
207     void equal(Object x, Object y) {
208         if (x == null ? y == null : x.equals(y)) pass();
209         else fail(x + " not equal to " + y);}
210     public static void main(String[] args) throws Throwable {
211         new DrainToFails().instanceMain(args);}
212     public void instanceMain(String[] args) throws Throwable {
213         try {test(args);} catch (Throwable t) {unexpected(t);}
214         System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
215         if (failed > 0) throw new AssertionError("Some tests failed");}
216 }
217