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 * @library /test/lib 39 */ 40 41 import java.util.ArrayList; 42 import java.util.List; 43 import java.util.concurrent.DelayQueue; 44 import java.util.concurrent.Delayed; 45 import java.util.concurrent.ArrayBlockingQueue; 46 import java.util.concurrent.BlockingQueue; 47 import java.util.concurrent.LinkedBlockingDeque; 48 import java.util.concurrent.LinkedBlockingQueue; 49 import java.util.concurrent.FutureTask; 50 import java.util.concurrent.PriorityBlockingQueue; 51 import java.util.concurrent.RunnableScheduledFuture; 52 import java.util.concurrent.ScheduledThreadPoolExecutor; 53 import java.util.concurrent.TimeUnit; 54 import jdk.test.lib.Utils; 55 56 @SuppressWarnings({"unchecked", "rawtypes"}) 57 public class DrainToFails { 58 static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); 59 final int CAPACITY = 10; 60 final int SMALL = 2; 61 test(String[] args)62 void test(String[] args) throws Throwable { 63 testDelayQueue(new DelayQueue()); 64 testDelayQueue(new ScheduledThreadPoolExecutor(1).getQueue()); 65 66 testUnbounded(new LinkedBlockingQueue()); 67 testUnbounded(new LinkedBlockingDeque()); 68 testUnbounded(new PriorityBlockingQueue()); 69 70 testBounded(new LinkedBlockingQueue(CAPACITY)); 71 testBounded(new LinkedBlockingDeque(CAPACITY)); 72 testBounded(new ArrayBlockingQueue(CAPACITY)); 73 } 74 75 static class PDelay 76 extends FutureTask<Void> 77 implements Delayed, RunnableScheduledFuture<Void> { 78 int pseudodelay; PDelay(int i)79 PDelay(int i) { 80 super(new Runnable() { public void run() {}}, null); 81 pseudodelay = i; 82 } compareTo(PDelay other)83 public int compareTo(PDelay other) { 84 return Integer.compare(this.pseudodelay, other.pseudodelay); 85 } compareTo(Delayed y)86 public int compareTo(Delayed y) { 87 return compareTo((PDelay)y); 88 } equals(Object other)89 public boolean equals(Object other) { 90 return (other instanceof PDelay) && 91 this.pseudodelay == ((PDelay)other).pseudodelay; 92 } getDelay(TimeUnit ignore)93 public long getDelay(TimeUnit ignore) { 94 return Integer.MIN_VALUE + pseudodelay; 95 } toString()96 public String toString() { 97 return String.valueOf(pseudodelay); 98 } isPeriodic()99 public boolean isPeriodic() { return false; } 100 } 101 testDelayQueue(final BlockingQueue q)102 void testDelayQueue(final BlockingQueue q) throws Throwable { 103 System.err.println(q.getClass().getSimpleName()); 104 for (int i = 0; i < CAPACITY; i++) 105 q.add(new PDelay(i)); 106 ArrayBlockingQueue q2 = new ArrayBlockingQueue(SMALL); 107 try { 108 q.drainTo(q2, SMALL + 3); 109 fail("should throw"); 110 } catch (IllegalStateException success) { 111 equal(SMALL, q2.size()); 112 equal(new PDelay(0), q2.poll()); 113 equal(new PDelay(1), q2.poll()); 114 check(q2.isEmpty()); 115 for (int i = SMALL; i < CAPACITY; i++) 116 equal(new PDelay(i), q.poll()); 117 equal(0, q.size()); 118 } 119 } 120 testUnbounded(final BlockingQueue q)121 void testUnbounded(final BlockingQueue q) throws Throwable { 122 System.err.println(q.getClass().getSimpleName()); 123 for (int i = 0; i < CAPACITY; i++) 124 q.add(i); 125 ArrayBlockingQueue q2 = new ArrayBlockingQueue(SMALL); 126 try { 127 q.drainTo(q2, 7); 128 fail("should throw"); 129 } catch (IllegalStateException success) { 130 assertContentsInOrder(q2, 0, 1); 131 q2.clear(); 132 equal(q.size(), CAPACITY - SMALL); 133 equal(SMALL, q.peek()); 134 } 135 136 try { 137 q.drainTo(q2); 138 fail("should throw"); 139 } catch (IllegalStateException success) { 140 assertContentsInOrder(q2, 2, 3); 141 equal(q.size(), CAPACITY - 2 * SMALL); 142 for (int i = 2 * SMALL; i < CAPACITY; i++) 143 equal(i, q.poll()); 144 equal(0, q.size()); 145 } 146 } 147 testBounded(final BlockingQueue q)148 void testBounded(final BlockingQueue q) throws Throwable { 149 System.err.println(q.getClass().getSimpleName()); 150 for (int i = 0; i < CAPACITY; i++) 151 q.add(i); 152 List<Thread> putters = new ArrayList<>(); 153 for (int i = 0; i < 4; i++) { 154 Thread putter = new Thread(putter(q, 42 + i)); 155 putters.add(putter); 156 putter.setDaemon(true); 157 putter.start(); 158 } 159 ArrayBlockingQueue q2 = new ArrayBlockingQueue(SMALL); 160 try { 161 q.drainTo(q2, 7); 162 fail("should throw"); 163 } catch (IllegalStateException success) { 164 while (q.size() < CAPACITY) 165 Thread.yield(); 166 assertContentsInOrder(q2, 0, 1); 167 q2.clear(); 168 } 169 170 try { 171 q.drainTo(q2); 172 fail("should throw"); 173 } catch (IllegalStateException success) { 174 for (Thread putter : putters) { 175 putter.join(LONG_DELAY_MS); 176 check(! putter.isAlive()); 177 } 178 assertContentsInOrder(q2, 2, 3); 179 for (int i = 2 * SMALL; i < CAPACITY; i++) 180 equal(i, q.poll()); 181 equal(4, q.size()); 182 check(q.contains(42)); 183 check(q.contains(43)); 184 check(q.contains(44)); 185 check(q.contains(45)); 186 } 187 } 188 putter(BlockingQueue q, int elt)189 Runnable putter(BlockingQueue q, int elt) { 190 return () -> { 191 try { q.put(elt); } 192 catch (Throwable t) { unexpected(t); }}; 193 } 194 195 void assertContentsInOrder(Iterable it, Object... contents) { 196 int i = 0; 197 for (Object e : it) 198 equal(contents[i++], e); 199 equal(contents.length, i); 200 } 201 202 //--------------------- Infrastructure --------------------------- 203 volatile int passed = 0, failed = 0; 204 void pass() {passed++;} 205 void fail() {failed++; Thread.dumpStack();} 206 void fail(String msg) {System.err.println(msg); fail();} 207 void unexpected(Throwable t) {failed++; t.printStackTrace();} 208 void check(boolean cond) {if (cond) pass(); else fail();} 209 void equal(Object x, Object y) { 210 if (x == null ? y == null : x.equals(y)) pass(); 211 else fail(x + " not equal to " + y);} 212 public static void main(String[] args) throws Throwable { 213 new DrainToFails().instanceMain(args);} 214 public void instanceMain(String[] args) throws Throwable { 215 try {test(args);} catch (Throwable t) {unexpected(t);} 216 System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); 217 if (failed > 0) throw new AssertionError("Some tests failed");} 218 } 219