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 }