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 with assistance from members of JCP JSR-166 30 * Expert Group and released to the public domain, as explained at 31 * http://creativecommons.org/publicdomain/zero/1.0/ 32 */ 33 34 /* 35 * @test 36 * @bug 6725789 37 * @summary Check for long overflow in task time comparison. 38 * @library /test/lib 39 */ 40 41 import static java.util.concurrent.TimeUnit.DAYS; 42 import static java.util.concurrent.TimeUnit.MILLISECONDS; 43 import static java.util.concurrent.TimeUnit.NANOSECONDS; 44 45 import java.util.concurrent.CountDownLatch; 46 import java.util.concurrent.Executors; 47 import java.util.concurrent.ScheduledThreadPoolExecutor; 48 import jdk.test.lib.Utils; 49 50 public class DelayOverflow { 51 static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); 52 53 static void waitForNanoTimeTick() { 54 for (long t0 = System.nanoTime(); t0 == System.nanoTime(); ) 55 ; 56 } 57 58 void scheduleNow(ScheduledThreadPoolExecutor pool, 59 Runnable r, int how) { 60 switch (how) { 61 case 0: 62 pool.schedule(r, 0, MILLISECONDS); 63 break; 64 case 1: 65 pool.schedule(Executors.callable(r), 0, DAYS); 66 break; 67 case 2: 68 pool.scheduleWithFixedDelay(r, 0, 1000, NANOSECONDS); 69 break; 70 case 3: 71 pool.scheduleAtFixedRate(r, 0, 1000, MILLISECONDS); 72 break; 73 default: 74 fail(String.valueOf(how)); 75 } 76 } 77 78 void scheduleAtTheEndOfTime(ScheduledThreadPoolExecutor pool, 79 Runnable r, int how) { 80 switch (how) { 81 case 0: 82 pool.schedule(r, Long.MAX_VALUE, MILLISECONDS); 83 break; 84 case 1: 85 pool.schedule(Executors.callable(r), Long.MAX_VALUE, DAYS); 86 break; 87 case 2: 88 pool.scheduleWithFixedDelay(r, Long.MAX_VALUE, 1000, NANOSECONDS); 89 break; 90 case 3: 91 pool.scheduleAtFixedRate(r, Long.MAX_VALUE, 1000, MILLISECONDS); 92 break; 93 default: 94 fail(String.valueOf(how)); 95 } 96 } 97 98 /** 99 * Attempts to test exhaustively and deterministically, all 20 100 * possible ways that one task can be scheduled in the maximal 101 * distant future, while at the same time an existing task's time 102 * has already expired. 103 */ 104 void test(String[] args) throws Throwable { 105 for (int nowHow = 0; nowHow < 4; nowHow++) { 106 for (int thenHow = 0; thenHow < 4; thenHow++) { 107 108 final ScheduledThreadPoolExecutor pool 109 = new ScheduledThreadPoolExecutor(1); 110 final CountDownLatch runLatch = new CountDownLatch(1); 111 final CountDownLatch busyLatch = new CountDownLatch(1); 112 final CountDownLatch proceedLatch = new CountDownLatch(1); 113 final Runnable notifier = new Runnable() { 114 public void run() { runLatch.countDown(); }}; 115 final Runnable neverRuns = new Runnable() { 116 public void run() { fail(); }}; 117 final Runnable keepPoolBusy = new Runnable() { 118 public void run() { 119 try { 120 busyLatch.countDown(); 121 proceedLatch.await(); 122 } catch (Throwable t) { unexpected(t); } 123 }}; 124 pool.schedule(keepPoolBusy, 0, DAYS); 125 busyLatch.await(); 126 scheduleNow(pool, notifier, nowHow); 127 waitForNanoTimeTick(); 128 scheduleAtTheEndOfTime(pool, neverRuns, thenHow); 129 proceedLatch.countDown(); 130 131 check(runLatch.await(LONG_DELAY_MS, MILLISECONDS)); 132 equal(runLatch.getCount(), 0L); 133 134 pool.setExecuteExistingDelayedTasksAfterShutdownPolicy(false); 135 pool.shutdown(); 136 } 137 138 final int nowHowCopy = nowHow; 139 final ScheduledThreadPoolExecutor pool 140 = new ScheduledThreadPoolExecutor(1); 141 final CountDownLatch runLatch = new CountDownLatch(1); 142 final Runnable notifier = new Runnable() { 143 public void run() { runLatch.countDown(); }}; 144 final Runnable scheduleNowScheduler = new Runnable() { 145 public void run() { 146 try { 147 scheduleNow(pool, notifier, nowHowCopy); 148 waitForNanoTimeTick(); 149 } catch (Throwable t) { unexpected(t); } 150 }}; 151 pool.scheduleWithFixedDelay(scheduleNowScheduler, 152 0, Long.MAX_VALUE, NANOSECONDS); 153 154 check(runLatch.await(LONG_DELAY_MS, MILLISECONDS)); 155 equal(runLatch.getCount(), 0L); 156 157 pool.setExecuteExistingDelayedTasksAfterShutdownPolicy(false); 158 pool.shutdown(); 159 } 160 } 161 162 //--------------------- Infrastructure --------------------------- 163 volatile int passed = 0, failed = 0; 164 void pass() {passed++;} 165 void fail() {failed++; Thread.dumpStack();} 166 void fail(String msg) {System.err.println(msg); fail();} 167 void unexpected(Throwable t) {failed++; t.printStackTrace();} 168 void check(boolean cond) {if (cond) pass(); else fail();} 169 void equal(Object x, Object y) { 170 if (x == null ? y == null : x.equals(y)) pass(); 171 else fail(x + " not equal to " + y);} 172 public static void main(String[] args) throws Throwable { 173 new DelayOverflow().instanceMain(args);} 174 void instanceMain(String[] args) throws Throwable { 175 try {test(args);} catch (Throwable t) {unexpected(t);} 176 System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); 177 if (failed > 0) throw new AssertionError("Some tests failed");} 178 }