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 {
main(String[] args)51     public static void main(String[] args) {
52         main(suite(), args);
53     }
54 
suite()55     public static Test suite() {
56         return new TestSuite(TimeUnitTest.class);
57     }
58 
testConversion(TimeUnit x, TimeUnit y, long n, long expected)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 
testConversion(TimeUnit x, TimeUnit y)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      */
testConversions()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      */
testConvertSaturate()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      */
testToNanosSaturate()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      */
testToMicrosSaturate()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      */
testToMillisSaturate()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      */
testToSecondsSaturate()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      */
testToMinutesSaturate()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      */
testToHoursSaturate()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      */
testToString()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      */
testName()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      */
testTimedWait_IllegalMonitorException()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      */
testTimedWait_Interruptible()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      */
testTimedJoin_Interruptible()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      */
testTimedSleep_Interruptible()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      */
testTimedSleep_nonPositive()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      */
testSerialization()455     public void testSerialization() throws Exception {
456         for (TimeUnit x : TimeUnit.values())
457             assertSame(x, serialClone(x));
458     }
459 
460 }
461