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 * Other contributors include Andrew Wright, Jeffrey Hayes, 33 * Pat Fisher, Mike Judd. 34 */ 35 36 import static java.util.concurrent.TimeUnit.DAYS; 37 import static java.util.concurrent.TimeUnit.HOURS; 38 import static java.util.concurrent.TimeUnit.MICROSECONDS; 39 import static java.util.concurrent.TimeUnit.MILLISECONDS; 40 import static java.util.concurrent.TimeUnit.MINUTES; 41 import static java.util.concurrent.TimeUnit.NANOSECONDS; 42 import static java.util.concurrent.TimeUnit.SECONDS; 43 44 import java.util.concurrent.CountDownLatch; 45 import java.util.concurrent.TimeUnit; 46 47 import junit.framework.Test; 48 import junit.framework.TestSuite; 49 50 public class TimeUnitTest extends JSR166TestCase { 51 public static void main(String[] args) { 52 main(suite(), args); 53 } 54 55 public static Test suite() { 56 return new TestSuite(TimeUnitTest.class); 57 } 58 59 void testConversion(TimeUnit x, TimeUnit y, long n, long expected) { 60 assertEquals(expected, x.convert(n, y)); 61 switch (x) { 62 case NANOSECONDS: assertEquals(expected, y.toNanos(n)); break; 63 case MICROSECONDS: assertEquals(expected, y.toMicros(n)); break; 64 case MILLISECONDS: assertEquals(expected, y.toMillis(n)); break; 65 case SECONDS: assertEquals(expected, y.toSeconds(n)); break; 66 case MINUTES: assertEquals(expected, y.toMinutes(n)); break; 67 case HOURS: assertEquals(expected, y.toHours(n)); break; 68 case DAYS: assertEquals(expected, y.toDays(n)); break; 69 default: throw new AssertionError(); 70 } 71 72 if (n > 0) testConversion(x, y, -n, -expected); 73 } 74 75 void testConversion(TimeUnit x, TimeUnit y) { 76 long ratio = x.toNanos(1)/y.toNanos(1); 77 assertTrue(ratio > 0); 78 long[] ns = { 0, 1, 2, Long.MAX_VALUE/ratio, Long.MIN_VALUE/ratio }; 79 for (long n : ns) { 80 testConversion(y, x, n, n * ratio); 81 long[] ks = { n * ratio, n * ratio + 1, n * ratio - 1 }; 82 for (long k : ks) { 83 testConversion(x, y, k, k / ratio); 84 } 85 } 86 } 87 88 /** 89 * Conversion methods correctly convert sample values 90 */ 91 public void testConversions() { 92 // Sanity check 93 assertEquals(1, NANOSECONDS.toNanos(1)); 94 assertEquals(1000L * NANOSECONDS.toNanos(1), MICROSECONDS.toNanos(1)); 95 assertEquals(1000L * MICROSECONDS.toNanos(1), MILLISECONDS.toNanos(1)); 96 assertEquals(1000L * MILLISECONDS.toNanos(1), SECONDS.toNanos(1)); 97 assertEquals(60L * SECONDS.toNanos(1), MINUTES.toNanos(1)); 98 assertEquals(60L * MINUTES.toNanos(1), HOURS.toNanos(1)); 99 assertEquals(24L * HOURS.toNanos(1), DAYS.toNanos(1)); 100 101 for (TimeUnit x : TimeUnit.values()) { 102 assertEquals(x.toNanos(1), NANOSECONDS.convert(1, x)); 103 } 104 105 for (TimeUnit x : TimeUnit.values()) 106 for (TimeUnit y : TimeUnit.values()) 107 if (x.toNanos(1) >= y.toNanos(1)) 108 testConversion(x, y); 109 } 110 111 /** 112 * convert saturates positive too-large values to Long.MAX_VALUE 113 * and negative to LONG.MIN_VALUE 114 */ 115 public void testConvertSaturate() { 116 assertEquals(Long.MAX_VALUE, 117 NANOSECONDS.convert(Long.MAX_VALUE / 2, SECONDS)); 118 assertEquals(Long.MIN_VALUE, 119 NANOSECONDS.convert(-Long.MAX_VALUE / 4, SECONDS)); 120 assertEquals(Long.MAX_VALUE, 121 NANOSECONDS.convert(Long.MAX_VALUE / 2, MINUTES)); 122 assertEquals(Long.MIN_VALUE, 123 NANOSECONDS.convert(-Long.MAX_VALUE / 4, MINUTES)); 124 assertEquals(Long.MAX_VALUE, 125 NANOSECONDS.convert(Long.MAX_VALUE / 2, HOURS)); 126 assertEquals(Long.MIN_VALUE, 127 NANOSECONDS.convert(-Long.MAX_VALUE / 4, HOURS)); 128 assertEquals(Long.MAX_VALUE, 129 NANOSECONDS.convert(Long.MAX_VALUE / 2, DAYS)); 130 assertEquals(Long.MIN_VALUE, 131 NANOSECONDS.convert(-Long.MAX_VALUE / 4, DAYS)); 132 133 for (TimeUnit x : TimeUnit.values()) 134 for (TimeUnit y : TimeUnit.values()) { 135 long ratio = x.toNanos(1) / y.toNanos(1); 136 if (ratio >= 1) { 137 assertEquals(ratio, y.convert(1, x)); 138 assertEquals(1, x.convert(ratio, y)); 139 long max = Long.MAX_VALUE/ratio; 140 assertEquals(max * ratio, y.convert(max, x)); 141 assertEquals(-max * ratio, y.convert(-max, x)); 142 assertEquals(max, x.convert(max * ratio, y)); 143 assertEquals(-max, x.convert(-max * ratio, y)); 144 if (max < Long.MAX_VALUE) { 145 assertEquals(Long.MAX_VALUE, y.convert(max + 1, x)); 146 assertEquals(Long.MIN_VALUE, y.convert(-max - 1, x)); 147 assertEquals(Long.MIN_VALUE, y.convert(Long.MIN_VALUE + 1, x)); 148 } 149 assertEquals(Long.MAX_VALUE, y.convert(Long.MAX_VALUE, x)); 150 assertEquals(Long.MIN_VALUE, y.convert(Long.MIN_VALUE, x)); 151 } 152 } 153 } 154 155 /** 156 * toNanos saturates positive too-large values to Long.MAX_VALUE 157 * and negative to LONG.MIN_VALUE 158 */ 159 public void testToNanosSaturate() { 160 assertEquals(Long.MAX_VALUE, 161 MILLISECONDS.toNanos(Long.MAX_VALUE / 2)); 162 assertEquals(Long.MIN_VALUE, 163 MILLISECONDS.toNanos(-Long.MAX_VALUE / 3)); 164 165 for (TimeUnit x : TimeUnit.values()) { 166 long ratio = x.toNanos(1) / NANOSECONDS.toNanos(1); 167 if (ratio >= 1) { 168 long max = Long.MAX_VALUE/ratio; 169 for (long z : new long[] {0, 1, -1, max, -max}) 170 assertEquals(z * ratio, x.toNanos(z)); 171 if (max < Long.MAX_VALUE) { 172 assertEquals(Long.MAX_VALUE, x.toNanos(max + 1)); 173 assertEquals(Long.MIN_VALUE, x.toNanos(-max - 1)); 174 assertEquals(Long.MIN_VALUE, x.toNanos(Long.MIN_VALUE + 1)); 175 } 176 assertEquals(Long.MAX_VALUE, x.toNanos(Long.MAX_VALUE)); 177 assertEquals(Long.MIN_VALUE, x.toNanos(Long.MIN_VALUE)); 178 if (max < Integer.MAX_VALUE) { 179 assertEquals(Long.MAX_VALUE, x.toNanos(Integer.MAX_VALUE)); 180 assertEquals(Long.MIN_VALUE, x.toNanos(Integer.MIN_VALUE)); 181 } 182 } 183 } 184 } 185 186 /** 187 * toMicros saturates positive too-large values to Long.MAX_VALUE 188 * and negative to LONG.MIN_VALUE 189 */ 190 public void testToMicrosSaturate() { 191 for (TimeUnit x : TimeUnit.values()) { 192 long ratio = x.toNanos(1) / MICROSECONDS.toNanos(1); 193 if (ratio >= 1) { 194 long max = Long.MAX_VALUE/ratio; 195 for (long z : new long[] {0, 1, -1, max, -max}) 196 assertEquals(z * ratio, x.toMicros(z)); 197 if (max < Long.MAX_VALUE) { 198 assertEquals(Long.MAX_VALUE, x.toMicros(max + 1)); 199 assertEquals(Long.MIN_VALUE, x.toMicros(-max - 1)); 200 assertEquals(Long.MIN_VALUE, x.toMicros(Long.MIN_VALUE + 1)); 201 } 202 assertEquals(Long.MAX_VALUE, x.toMicros(Long.MAX_VALUE)); 203 assertEquals(Long.MIN_VALUE, x.toMicros(Long.MIN_VALUE)); 204 if (max < Integer.MAX_VALUE) { 205 assertEquals(Long.MAX_VALUE, x.toMicros(Integer.MAX_VALUE)); 206 assertEquals(Long.MIN_VALUE, x.toMicros(Integer.MIN_VALUE)); 207 } 208 } 209 } 210 } 211 212 /** 213 * toMillis saturates positive too-large values to Long.MAX_VALUE 214 * and negative to LONG.MIN_VALUE 215 */ 216 public void testToMillisSaturate() { 217 for (TimeUnit x : TimeUnit.values()) { 218 long ratio = x.toNanos(1) / MILLISECONDS.toNanos(1); 219 if (ratio >= 1) { 220 long max = Long.MAX_VALUE/ratio; 221 for (long z : new long[] {0, 1, -1, max, -max}) 222 assertEquals(z * ratio, x.toMillis(z)); 223 if (max < Long.MAX_VALUE) { 224 assertEquals(Long.MAX_VALUE, x.toMillis(max + 1)); 225 assertEquals(Long.MIN_VALUE, x.toMillis(-max - 1)); 226 assertEquals(Long.MIN_VALUE, x.toMillis(Long.MIN_VALUE + 1)); 227 } 228 assertEquals(Long.MAX_VALUE, x.toMillis(Long.MAX_VALUE)); 229 assertEquals(Long.MIN_VALUE, x.toMillis(Long.MIN_VALUE)); 230 if (max < Integer.MAX_VALUE) { 231 assertEquals(Long.MAX_VALUE, x.toMillis(Integer.MAX_VALUE)); 232 assertEquals(Long.MIN_VALUE, x.toMillis(Integer.MIN_VALUE)); 233 } 234 } 235 } 236 } 237 238 /** 239 * toSeconds saturates positive too-large values to Long.MAX_VALUE 240 * and negative to LONG.MIN_VALUE 241 */ 242 public void testToSecondsSaturate() { 243 for (TimeUnit x : TimeUnit.values()) { 244 long ratio = x.toNanos(1) / SECONDS.toNanos(1); 245 if (ratio >= 1) { 246 long max = Long.MAX_VALUE/ratio; 247 for (long z : new long[] {0, 1, -1, max, -max}) 248 assertEquals(z * ratio, x.toSeconds(z)); 249 if (max < Long.MAX_VALUE) { 250 assertEquals(Long.MAX_VALUE, x.toSeconds(max + 1)); 251 assertEquals(Long.MIN_VALUE, x.toSeconds(-max - 1)); 252 assertEquals(Long.MIN_VALUE, x.toSeconds(Long.MIN_VALUE + 1)); 253 } 254 assertEquals(Long.MAX_VALUE, x.toSeconds(Long.MAX_VALUE)); 255 assertEquals(Long.MIN_VALUE, x.toSeconds(Long.MIN_VALUE)); 256 if (max < Integer.MAX_VALUE) { 257 assertEquals(Long.MAX_VALUE, x.toSeconds(Integer.MAX_VALUE)); 258 assertEquals(Long.MIN_VALUE, x.toSeconds(Integer.MIN_VALUE)); 259 } 260 } 261 } 262 } 263 264 /** 265 * toMinutes saturates positive too-large values to Long.MAX_VALUE 266 * and negative to LONG.MIN_VALUE 267 */ 268 public void testToMinutesSaturate() { 269 for (TimeUnit x : TimeUnit.values()) { 270 long ratio = x.toNanos(1) / MINUTES.toNanos(1); 271 if (ratio > 1) { 272 long max = Long.MAX_VALUE/ratio; 273 for (long z : new long[] {0, 1, -1, max, -max}) 274 assertEquals(z * ratio, x.toMinutes(z)); 275 assertEquals(Long.MAX_VALUE, x.toMinutes(max + 1)); 276 assertEquals(Long.MIN_VALUE, x.toMinutes(-max - 1)); 277 assertEquals(Long.MAX_VALUE, x.toMinutes(Long.MAX_VALUE)); 278 assertEquals(Long.MIN_VALUE, x.toMinutes(Long.MIN_VALUE)); 279 assertEquals(Long.MIN_VALUE, x.toMinutes(Long.MIN_VALUE + 1)); 280 } 281 } 282 } 283 284 /** 285 * toHours saturates positive too-large values to Long.MAX_VALUE 286 * and negative to LONG.MIN_VALUE 287 */ 288 public void testToHoursSaturate() { 289 for (TimeUnit x : TimeUnit.values()) { 290 long ratio = x.toNanos(1) / HOURS.toNanos(1); 291 if (ratio >= 1) { 292 long max = Long.MAX_VALUE/ratio; 293 for (long z : new long[] {0, 1, -1, max, -max}) 294 assertEquals(z * ratio, x.toHours(z)); 295 if (max < Long.MAX_VALUE) { 296 assertEquals(Long.MAX_VALUE, x.toHours(max + 1)); 297 assertEquals(Long.MIN_VALUE, x.toHours(-max - 1)); 298 assertEquals(Long.MIN_VALUE, x.toHours(Long.MIN_VALUE + 1)); 299 } 300 assertEquals(Long.MAX_VALUE, x.toHours(Long.MAX_VALUE)); 301 assertEquals(Long.MIN_VALUE, x.toHours(Long.MIN_VALUE)); 302 } 303 } 304 } 305 306 /** 307 * toString returns name of unit 308 */ 309 public void testToString() { 310 assertEquals("NANOSECONDS", NANOSECONDS.toString()); 311 assertEquals("MICROSECONDS", MICROSECONDS.toString()); 312 assertEquals("MILLISECONDS", MILLISECONDS.toString()); 313 assertEquals("SECONDS", SECONDS.toString()); 314 assertEquals("MINUTES", MINUTES.toString()); 315 assertEquals("HOURS", HOURS.toString()); 316 assertEquals("DAYS", DAYS.toString()); 317 } 318 319 /** 320 * name returns name of unit 321 */ 322 public void testName() { 323 for (TimeUnit x : TimeUnit.values()) 324 assertEquals(x.toString(), x.name()); 325 } 326 327 /** 328 * Timed wait without holding lock throws 329 * IllegalMonitorStateException 330 */ 331 public void testTimedWait_IllegalMonitorException() { 332 Thread t = newStartedThread(new CheckedRunnable() { 333 public void realRun() throws InterruptedException { 334 Object o = new Object(); 335 try { 336 MILLISECONDS.timedWait(o, LONGER_DELAY_MS); 337 threadShouldThrow(); 338 } catch (IllegalMonitorStateException success) {} 339 }}); 340 341 awaitTermination(t); 342 } 343 344 /** 345 * timedWait throws InterruptedException when interrupted 346 */ 347 public void testTimedWait_Interruptible() { 348 final CountDownLatch pleaseInterrupt = new CountDownLatch(1); 349 Thread t = newStartedThread(new CheckedRunnable() { 350 public void realRun() throws InterruptedException { 351 Object o = new Object(); 352 353 Thread.currentThread().interrupt(); 354 try { 355 synchronized (o) { 356 MILLISECONDS.timedWait(o, LONGER_DELAY_MS); 357 } 358 shouldThrow(); 359 } catch (InterruptedException success) {} 360 assertFalse(Thread.interrupted()); 361 362 pleaseInterrupt.countDown(); 363 try { 364 synchronized (o) { 365 MILLISECONDS.timedWait(o, LONGER_DELAY_MS); 366 } 367 shouldThrow(); 368 } catch (InterruptedException success) {} 369 assertFalse(Thread.interrupted()); 370 }}); 371 372 await(pleaseInterrupt); 373 if (randomBoolean()) assertThreadBlocks(t, Thread.State.TIMED_WAITING); 374 t.interrupt(); 375 awaitTermination(t); 376 } 377 378 /** 379 * timedJoin throws InterruptedException when interrupted 380 */ 381 public void testTimedJoin_Interruptible() { 382 final CountDownLatch pleaseInterrupt = new CountDownLatch(1); 383 final Thread s = newStartedThread(new CheckedInterruptedRunnable() { 384 public void realRun() throws InterruptedException { 385 Thread.sleep(LONGER_DELAY_MS); 386 }}); 387 final Thread t = newStartedThread(new CheckedRunnable() { 388 public void realRun() throws InterruptedException { 389 Thread.currentThread().interrupt(); 390 try { 391 MILLISECONDS.timedJoin(s, LONGER_DELAY_MS); 392 shouldThrow(); 393 } catch (InterruptedException success) {} 394 assertFalse(Thread.interrupted()); 395 396 pleaseInterrupt.countDown(); 397 try { 398 MILLISECONDS.timedJoin(s, LONGER_DELAY_MS); 399 shouldThrow(); 400 } catch (InterruptedException success) {} 401 assertFalse(Thread.interrupted()); 402 }}); 403 404 await(pleaseInterrupt); 405 if (randomBoolean()) assertThreadBlocks(t, Thread.State.TIMED_WAITING); 406 t.interrupt(); 407 awaitTermination(t); 408 s.interrupt(); 409 awaitTermination(s); 410 } 411 412 /** 413 * timeUnit.sleep throws InterruptedException when interrupted 414 */ 415 public void testTimedSleep_Interruptible() { 416 final CountDownLatch pleaseInterrupt = new CountDownLatch(1); 417 Thread t = newStartedThread(new CheckedRunnable() { 418 public void realRun() throws InterruptedException { 419 Thread.currentThread().interrupt(); 420 try { 421 MILLISECONDS.sleep(LONGER_DELAY_MS); 422 shouldThrow(); 423 } catch (InterruptedException success) {} 424 assertFalse(Thread.interrupted()); 425 426 pleaseInterrupt.countDown(); 427 try { 428 MILLISECONDS.sleep(LONGER_DELAY_MS); 429 shouldThrow(); 430 } catch (InterruptedException success) {} 431 assertFalse(Thread.interrupted()); 432 }}); 433 434 await(pleaseInterrupt); 435 if (randomBoolean()) assertThreadBlocks(t, Thread.State.TIMED_WAITING); 436 t.interrupt(); 437 awaitTermination(t); 438 } 439 440 /** 441 * timeUnit.sleep(x) for x <= 0 does not sleep at all. 442 */ 443 public void testTimedSleep_nonPositive() throws InterruptedException { 444 boolean interrupt = randomBoolean(); 445 if (interrupt) Thread.currentThread().interrupt(); 446 randomTimeUnit().sleep(0L); 447 randomTimeUnit().sleep(-1L); 448 randomTimeUnit().sleep(Long.MIN_VALUE); 449 if (interrupt) assertTrue(Thread.interrupted()); 450 } 451 452 /** 453 * a deserialized/reserialized unit is the same instance 454 */ 455 public void testSerialization() throws Exception { 456 for (TimeUnit x : TimeUnit.values()) 457 assertSame(x, serialClone(x)); 458 } 459 460 }