TimerTest.java revision 72e7c5a8d32494c81206971d4c1077e3f2b88f00
1/*
2 *  Licensed to the Apache Software Foundation (ASF) under one or more
3 *  contributor license agreements.  See the NOTICE file distributed with
4 *  this work for additional information regarding copyright ownership.
5 *  The ASF licenses this file to You under the Apache License, Version 2.0
6 *  (the "License"); you may not use this file except in compliance with
7 *  the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 */
17
18package tests.api.java.util;
19
20import dalvik.annotation.TestTargetNew;
21import dalvik.annotation.TestTargets;
22import dalvik.annotation.TestLevel;
23import dalvik.annotation.TestTargetClass;
24
25import java.util.Date;
26import java.util.Timer;
27import java.util.TimerTask;
28import java.util.concurrent.atomic.AtomicReference;
29
30@TestTargetClass(Timer.class)
31public class TimerTest extends junit.framework.TestCase {
32
33    int timerCounter = 0;
34
35    Object sync = new Object();
36
37    /**
38     * Warning: These tests have the possibility to leave a VM hanging if the
39     * Timer is not cancelled.
40     */
41    class TimerTestTask extends TimerTask {
42        int wasRun = 0;
43
44        // Should we sleep for 200 ms each run()?
45        boolean sleepInRun = false;
46
47        // Should we increment the timerCounter?
48        boolean incrementCount = false;
49
50        // Should we terminate the timer at a specific timerCounter?
51        int terminateCount = -1;
52
53        // The timer we belong to
54        Timer timer = null;
55
56        public TimerTestTask() {
57        }
58
59        public TimerTestTask(Timer t) {
60            timer = t;
61        }
62
63        public void run() {
64            synchronized (this) {
65                wasRun++;
66            }
67            if (incrementCount)
68                timerCounter++;
69            if (terminateCount == timerCounter && timer != null)
70                timer.cancel();
71            if (sleepInRun) {
72                try {
73                    Thread.sleep(200);
74                } catch (InterruptedException e) {
75                }
76            }
77            synchronized (sync) {
78                sync.notify();
79            }
80        }
81
82        public synchronized int wasRun() {
83            return wasRun;
84        }
85
86        public void sleepInRun(boolean sleepInRun) {
87            this.sleepInRun = sleepInRun;
88        }
89
90        public void incrementCount(boolean incrementCount) {
91            this.incrementCount = incrementCount;
92        }
93
94        public void terminateCount(int terminateCount) {
95            this.terminateCount = terminateCount;
96        }
97    }
98
99    /**
100     * @tests java.util.Timer#Timer(boolean)
101     */
102    @TestTargetNew(
103        level = TestLevel.COMPLETE,
104        notes = "",
105        method = "Timer",
106        args = {boolean.class}
107    )
108    public void test_ConstructorZ() {
109        Timer t = null;
110        try {
111            // Ensure a task is run
112            t = new Timer(true);
113            TimerTestTask testTask = new TimerTestTask();
114            t.schedule(testTask, 200);
115            synchronized (sync) {
116                try {
117                    sync.wait(1000);
118                } catch (InterruptedException e) {
119                }
120            }
121            assertEquals("TimerTask.run() method not called after 200ms",
122                    1, testTask.wasRun());
123            t.cancel();
124        } finally {
125            if (t != null)
126                t.cancel();
127        }
128
129    }
130
131    /**
132     * @tests java.util.Timer#Timer()
133     */
134    @TestTargetNew(
135        level = TestLevel.COMPLETE,
136        notes = "",
137        method = "Timer",
138        args = {}
139    )
140    public void test_Constructor() {
141        Timer t = null;
142        try {
143            // Ensure a task is run
144            t = new Timer();
145            TimerTestTask testTask = new TimerTestTask();
146            t.schedule(testTask, 200);
147            synchronized (sync) {
148                try {
149                    sync.wait(1000);
150                } catch (InterruptedException e) {
151                }
152            }
153            assertEquals("TimerTask.run() method not called after 200ms",
154                    1, testTask.wasRun());
155            t.cancel();
156        } finally {
157            if (t != null)
158                t.cancel();
159        }
160
161    }
162
163    /**
164     * @tests java.util.Timer#Timer(String, boolean)
165     */
166    @TestTargetNew(
167        level = TestLevel.COMPLETE,
168        notes = "",
169        method = "Timer",
170        args = {java.lang.String.class, boolean.class}
171    )
172    public void test_ConstructorSZ() {
173        Timer t = null;
174        try {
175            // Ensure a task is run
176            t = new Timer("test_ConstructorSZThread", true);
177            TimerTestTask testTask = new TimerTestTask();
178            t.schedule(testTask, 200);
179            synchronized (sync) {
180                try {
181                    sync.wait(1000);
182                } catch (InterruptedException e) {}
183            }
184            assertEquals("TimerTask.run() method not called after 200ms", 1,
185                    testTask.wasRun());
186            t.cancel();
187        } finally {
188            if (t != null)
189                t.cancel();
190        }
191
192        try {
193            new Timer(null, true);
194            fail("NullPointerException expected");
195        } catch (NullPointerException e) {
196            //expected
197        }
198
199        try {
200            new Timer(null, false);
201            fail("NullPointerException expected");
202        } catch (NullPointerException e) {
203            //expected
204        }
205    }
206
207    /**
208     * @tests java.util.Timer#Timer(String)
209     */
210    @TestTargetNew(
211        level = TestLevel.COMPLETE,
212        notes = "",
213        method = "Timer",
214        args = {java.lang.String.class}
215    )
216    public void test_ConstructorS() {
217        Timer t = null;
218        try {
219            // Ensure a task is run
220            t = new Timer("test_ConstructorSThread");
221            TimerTestTask testTask = new TimerTestTask();
222            t.schedule(testTask, 200);
223            synchronized (sync) {
224                try {
225                    sync.wait(1000);
226                } catch (InterruptedException e) {}
227            }
228            assertEquals("TimerTask.run() method not called after 200ms", 1,
229                    testTask.wasRun());
230            t.cancel();
231        } finally {
232            if (t != null)
233                t.cancel();
234        }
235
236        try {
237            new Timer(null);
238            fail("NullPointerException expected");
239        } catch (NullPointerException e) {
240            //expected
241        }
242    }
243
244    /**
245     * @tests java.util.Timer#cancel()
246     */
247    @TestTargetNew(
248        level = TestLevel.COMPLETE,
249        notes = "",
250        method = "cancel",
251        args = {}
252    )
253    public void test_cancel() {
254        Timer t = null;
255        try {
256            // Ensure a task throws an IllegalStateException after cancelled
257            t = new Timer();
258            TimerTestTask testTask = new TimerTestTask();
259            t.cancel();
260            boolean exception = false;
261            try {
262                t.schedule(testTask, 100, 200);
263            } catch (IllegalStateException e) {
264                exception = true;
265            }
266            assertTrue(
267                    "Scheduling a task after Timer.cancel() should throw exception",
268                    exception);
269
270            // Ensure a task is run but not after cancel
271            t = new Timer();
272            testTask = new TimerTestTask();
273            t.schedule(testTask, 100, 500);
274            synchronized (sync) {
275                try {
276                    sync.wait(1000);
277                } catch (InterruptedException e) {
278                }
279            }
280            assertEquals("TimerTask.run() method not called after 200ms",
281                    1, testTask.wasRun());
282            t.cancel();
283            synchronized (sync) {
284                try {
285                    sync.wait(500);
286                } catch (InterruptedException e) {
287                }
288            }
289            assertEquals("TimerTask.run() method should not have been called after cancel",
290                    1, testTask.wasRun());
291
292            // Ensure you can call cancel more than once
293            t = new Timer();
294            testTask = new TimerTestTask();
295            t.schedule(testTask, 100, 500);
296            synchronized (sync) {
297                try {
298                    sync.wait(500);
299                } catch (InterruptedException e) {
300                }
301            }
302            assertEquals("TimerTask.run() method not called after 200ms",
303                    1, testTask.wasRun());
304            t.cancel();
305            t.cancel();
306            t.cancel();
307            synchronized (sync) {
308                try {
309                    sync.wait(500);
310                } catch (InterruptedException e) {
311                }
312            }
313            assertEquals("TimerTask.run() method should not have been called after cancel",
314                    1, testTask.wasRun());
315
316            // Ensure that a call to cancel from within a timer ensures no more
317            // run
318            t = new Timer();
319            testTask = new TimerTestTask(t);
320            testTask.incrementCount(true);
321            testTask.terminateCount(5); // Terminate after 5 runs
322            t.schedule(testTask, 100, 100);
323            synchronized (sync) {
324                try {
325                    sync.wait(200);
326                    sync.wait(200);
327                    sync.wait(200);
328                    sync.wait(200);
329                    sync.wait(200);
330                    sync.wait(200);
331                } catch (InterruptedException e) {
332                }
333            }
334            assertTrue("TimerTask.run() method should be called 5 times not "
335                    + testTask.wasRun(), testTask.wasRun() == 5);
336            t.cancel();
337            try {
338                Thread.sleep(200);
339            } catch (InterruptedException e) {
340            }
341        } finally {
342            if (t != null)
343                t.cancel();
344        }
345
346    }
347
348    /**
349     * @tests java.util.Timer#purge()
350     */
351    @TestTargetNew(
352        level = TestLevel.COMPLETE,
353        notes = "",
354        method = "purge",
355        args = {}
356    )
357    public void test_purge() throws Exception {
358        Timer t = null;
359        try {
360            t = new Timer();
361            assertEquals(0, t.purge());
362
363            TimerTestTask[] tasks = new TimerTestTask[100];
364            int[] delayTime = { 50, 80, 20, 70, 40, 10, 90, 30, 60 };
365
366            int j = 0;
367            for (int i = 0; i < 100; i++) {
368                tasks[i] = new TimerTestTask();
369                t.schedule(tasks[i], delayTime[j++], 200);
370                if (j == 9) {
371                    j = 0;
372                }
373            }
374
375            for (int i = 0; i < 50; i++) {
376                tasks[i].cancel();
377            }
378
379            assertTrue(t.purge() <= 50);
380            assertEquals(0, t.purge());
381        } finally {
382            if (t != null) {
383                t.cancel();
384            }
385        }
386    }
387
388    /**
389     * @tests java.util.Timer#schedule(java.util.TimerTask, java.util.Date)
390     */
391    @TestTargetNew(
392        level = TestLevel.COMPLETE,
393        notes = "",
394        method = "schedule",
395        args = {java.util.TimerTask.class, java.util.Date.class}
396    )
397    public void test_scheduleLjava_util_TimerTaskLjava_util_Date() {
398        Timer t = null;
399        try {
400            // Ensure a Timer throws an IllegalStateException after cancelled
401            t = new Timer();
402            TimerTestTask testTask = new TimerTestTask();
403            Date d = new Date(System.currentTimeMillis() + 100);
404            t.cancel();
405            boolean exception = false;
406            try {
407                t.schedule(testTask, d);
408            } catch (IllegalStateException e) {
409                exception = true;
410            }
411            assertTrue(
412                    "Scheduling a task after Timer.cancel() should throw exception",
413                    exception);
414
415            // Ensure a Timer throws an IllegalStateException if task already
416            // cancelled
417            t = new Timer();
418            testTask = new TimerTestTask();
419            d = new Date(System.currentTimeMillis() + 100);
420            testTask.cancel();
421            exception = false;
422            try {
423                t.schedule(testTask, d);
424            } catch (IllegalStateException e) {
425                exception = true;
426            }
427            assertTrue(
428                    "Scheduling a task after cancelling it should throw exception",
429                    exception);
430            t.cancel();
431
432            // Ensure a Timer throws an IllegalArgumentException if delay is
433            // negative
434            t = new Timer();
435            testTask = new TimerTestTask();
436            d = new Date(-100);
437            exception = false;
438            try {
439                t.schedule(testTask, d);
440            } catch (IllegalArgumentException e) {
441                exception = true;
442            }
443            assertTrue(
444                    "Scheduling a task with negative date should throw IllegalArgumentException",
445                    exception);
446            t.cancel();
447
448            // Ensure a Timer throws a NullPointerException if the task is null
449            t = new Timer();
450            exception = false;
451            d = new Date(System.currentTimeMillis() + 100);
452            try {
453                t.schedule(null, d);
454            } catch (NullPointerException e) {
455                exception = true;
456            }
457            assertTrue(
458                    "Scheduling a null task should throw NullPointerException",
459                    exception);
460            t.cancel();
461
462            // Ensure a Timer throws a NullPointerException if the date is null
463            t = new Timer();
464            testTask = new TimerTestTask();
465            exception = false;
466            try {
467                t.schedule(testTask, null);
468            } catch (NullPointerException e) {
469                exception = true;
470            }
471            assertTrue(
472                    "Scheduling a null date should throw NullPointerException",
473                    exception);
474            t.cancel();
475
476            // Ensure proper sequence of exceptions
477            t = new Timer();
478            d = new Date(-100);
479            exception = false;
480            try {
481                t.schedule(null, d);
482            } catch (NullPointerException e) {
483            } catch (IllegalArgumentException e) {
484                exception = true;
485            }
486            assertTrue(
487                    "Scheduling a null task with negative date should throw IllegalArgumentException first",
488                    exception);
489            t.cancel();
490
491            // Ensure a task is run
492            t = new Timer();
493            testTask = new TimerTestTask();
494            d = new Date(System.currentTimeMillis() + 200);
495            t.schedule(testTask, d);
496            try {
497                Thread.sleep(400);
498            } catch (InterruptedException e) {
499            }
500            assertEquals("TimerTask.run() method not called after 200ms",
501                    1, testTask.wasRun());
502            t.cancel();
503
504            // Ensure multiple tasks are run
505            t = new Timer();
506            testTask = new TimerTestTask();
507            testTask.incrementCount(true);
508            d = new Date(System.currentTimeMillis() + 100);
509            t.schedule(testTask, d);
510            testTask = new TimerTestTask();
511            testTask.incrementCount(true);
512            d = new Date(System.currentTimeMillis() + 150);
513            t.schedule(testTask, d);
514            testTask = new TimerTestTask();
515            testTask.incrementCount(true);
516            d = new Date(System.currentTimeMillis() + 70);
517            t.schedule(testTask, d);
518            testTask = new TimerTestTask();
519            testTask.incrementCount(true);
520            d = new Date(System.currentTimeMillis() + 10);
521            t.schedule(testTask, d);
522            try {
523                Thread.sleep(400);
524            } catch (InterruptedException e) {
525            }
526            assertTrue(
527                    "Multiple tasks should have incremented counter 4 times not "
528                            + timerCounter, timerCounter == 4);
529            t.cancel();
530        } finally {
531            if (t != null)
532                t.cancel();
533        }
534    }
535
536    /**
537     * @tests java.util.Timer#schedule(java.util.TimerTask, long)
538     */
539    @TestTargetNew(
540        level = TestLevel.COMPLETE,
541        notes = "",
542        method = "schedule",
543        args = {java.util.TimerTask.class, long.class}
544    )
545    public void test_scheduleLjava_util_TimerTaskJ() {
546        Timer t = null;
547        try {
548            // Ensure a Timer throws an IllegalStateException after cancelled
549            t = new Timer();
550            TimerTestTask testTask = new TimerTestTask();
551            t.cancel();
552            boolean exception = false;
553            try {
554                t.schedule(testTask, 100);
555            } catch (IllegalStateException e) {
556                exception = true;
557            }
558            assertTrue(
559                    "Scheduling a task after Timer.cancel() should throw exception",
560                    exception);
561
562            // Ensure a Timer throws an IllegalStateException if task already
563            // cancelled
564            t = new Timer();
565            testTask = new TimerTestTask();
566            testTask.cancel();
567            exception = false;
568            try {
569                t.schedule(testTask, 100);
570            } catch (IllegalStateException e) {
571                exception = true;
572            }
573            assertTrue(
574                    "Scheduling a task after cancelling it should throw exception",
575                    exception);
576            t.cancel();
577
578            // Ensure a Timer throws an IllegalArgumentException if delay is
579            // negative
580            t = new Timer();
581            testTask = new TimerTestTask();
582            exception = false;
583            try {
584                t.schedule(testTask, -100);
585            } catch (IllegalArgumentException e) {
586                exception = true;
587            }
588            assertTrue(
589                    "Scheduling a task with negative delay should throw IllegalArgumentException",
590                    exception);
591            t.cancel();
592
593            // Ensure a Timer throws a NullPointerException if the task is null
594            t = new Timer();
595            exception = false;
596            try {
597                t.schedule(null, 10);
598            } catch (NullPointerException e) {
599                exception = true;
600            }
601            assertTrue(
602                    "Scheduling a null task should throw NullPointerException",
603                    exception);
604            t.cancel();
605
606            // Ensure proper sequence of exceptions
607            t = new Timer();
608            exception = false;
609            try {
610                t.schedule(null, -10);
611            } catch (NullPointerException e) {
612            } catch (IllegalArgumentException e) {
613                exception = true;
614            }
615            assertTrue(
616                    "Scheduling a null task with negative delays should throw IllegalArgumentException first",
617                    exception);
618            t.cancel();
619
620            // Ensure a task is run
621            t = new Timer();
622            testTask = new TimerTestTask();
623            t.schedule(testTask, 200);
624            try {
625                Thread.sleep(400);
626            } catch (InterruptedException e) {
627            }
628            assertEquals("TimerTask.run() method not called after 200ms",
629                    1, testTask.wasRun());
630            t.cancel();
631
632            // Ensure multiple tasks are run
633            t = new Timer();
634            testTask = new TimerTestTask();
635            testTask.incrementCount(true);
636            t.schedule(testTask, 100);
637            testTask = new TimerTestTask();
638            testTask.incrementCount(true);
639            t.schedule(testTask, 150);
640            testTask = new TimerTestTask();
641            testTask.incrementCount(true);
642            t.schedule(testTask, 70);
643            testTask = new TimerTestTask();
644            testTask.incrementCount(true);
645            t.schedule(testTask, 10);
646            try {
647                Thread.sleep(400);
648            } catch (InterruptedException e) {
649            }
650            assertTrue(
651                    "Multiple tasks should have incremented counter 4 times not "
652                            + timerCounter, timerCounter == 4);
653            t.cancel();
654        } finally {
655            if (t != null)
656                t.cancel();
657        }
658    }
659
660    /**
661     * @tests java.util.Timer#schedule(java.util.TimerTask, long, long)
662     */
663    @TestTargetNew(
664        level = TestLevel.COMPLETE,
665        notes = "",
666        method = "schedule",
667        args = {java.util.TimerTask.class, long.class, long.class}
668    )
669    public void test_scheduleLjava_util_TimerTaskJJ() {
670        Timer t = null;
671        try {
672            // Ensure a Timer throws an IllegalStateException after cancelled
673            t = new Timer();
674            TimerTestTask testTask = new TimerTestTask();
675            t.cancel();
676            boolean exception = false;
677            try {
678                t.schedule(testTask, 100, 100);
679            } catch (IllegalStateException e) {
680                exception = true;
681            }
682            assertTrue(
683                    "Scheduling a task after Timer.cancel() should throw exception",
684                    exception);
685
686            // Ensure a Timer throws an IllegalStateException if task already
687            // cancelled
688            t = new Timer();
689            testTask = new TimerTestTask();
690            testTask.cancel();
691            exception = false;
692            try {
693                t.schedule(testTask, 100, 100);
694            } catch (IllegalStateException e) {
695                exception = true;
696            }
697            assertTrue(
698                    "Scheduling a task after cancelling it should throw exception",
699                    exception);
700            t.cancel();
701
702            // Ensure a Timer throws an IllegalArgumentException if delay is
703            // negative
704            t = new Timer();
705            testTask = new TimerTestTask();
706            exception = false;
707            try {
708                t.schedule(testTask, -100, 100);
709            } catch (IllegalArgumentException e) {
710                exception = true;
711            }
712            assertTrue(
713                    "Scheduling a task with negative delay should throw IllegalArgumentException",
714                    exception);
715            t.cancel();
716
717            // Ensure a Timer throws an IllegalArgumentException if period is
718            // negative
719            t = new Timer();
720            testTask = new TimerTestTask();
721            exception = false;
722            try {
723                t.schedule(testTask, 100, -100);
724            } catch (IllegalArgumentException e) {
725                exception = true;
726            }
727            assertTrue(
728                    "Scheduling a task with negative period should throw IllegalArgumentException",
729                    exception);
730            t.cancel();
731
732            // Ensure a Timer throws an IllegalArgumentException if period is
733            // zero
734            t = new Timer();
735            testTask = new TimerTestTask();
736            exception = false;
737            try {
738                t.schedule(testTask, 100, 0);
739            } catch (IllegalArgumentException e) {
740                exception = true;
741            }
742            assertTrue(
743                    "Scheduling a task with 0 period should throw IllegalArgumentException",
744                    exception);
745            t.cancel();
746
747            // Ensure a Timer throws a NullPointerException if the task is null
748            t = new Timer();
749            exception = false;
750            try {
751                t.schedule(null, 10, 10);
752            } catch (NullPointerException e) {
753                exception = true;
754            }
755            assertTrue(
756                    "Scheduling a null task should throw NullPointerException",
757                    exception);
758            t.cancel();
759
760            // Ensure proper sequence of exceptions
761            t = new Timer();
762            exception = false;
763            try {
764                t.schedule(null, -10, -10);
765            } catch (NullPointerException e) {
766            } catch (IllegalArgumentException e) {
767                exception = true;
768            }
769            assertTrue(
770                    "Scheduling a null task with negative delays should throw IllegalArgumentException first",
771                    exception);
772            t.cancel();
773
774            // Ensure a task is run at least twice
775            t = new Timer();
776            testTask = new TimerTestTask();
777            t.schedule(testTask, 100, 100);
778            try {
779                Thread.sleep(400);
780            } catch (InterruptedException e) {
781            }
782            assertTrue(
783                    "TimerTask.run() method should have been called at least twice ("
784                            + testTask.wasRun() + ")", testTask.wasRun() >= 2);
785            t.cancel();
786
787            // Ensure multiple tasks are run
788            t = new Timer();
789            testTask = new TimerTestTask();
790            testTask.incrementCount(true);
791            t.schedule(testTask, 100, 100); // at least 9 times
792            testTask = new TimerTestTask();
793            testTask.incrementCount(true);
794            t.schedule(testTask, 200, 100); // at least 7 times
795            testTask = new TimerTestTask();
796            testTask.incrementCount(true);
797            t.schedule(testTask, 300, 200); // at least 4 times
798            testTask = new TimerTestTask();
799            testTask.incrementCount(true);
800            t.schedule(testTask, 100, 200); // at least 4 times
801            try {
802                Thread.sleep(1200); // Allowed more room for error
803            } catch (InterruptedException e) {
804            }
805            assertTrue(
806                    "Multiple tasks should have incremented counter 24 times not "
807                            + timerCounter, timerCounter >= 24);
808            t.cancel();
809        } finally {
810            if (t != null)
811                t.cancel();
812        }
813    }
814
815    /**
816     * @tests java.util.Timer#schedule(java.util.TimerTask, java.util.Date,
817     *        long)
818     */
819    @TestTargetNew(
820        level = TestLevel.COMPLETE,
821        notes = "",
822        method = "schedule",
823        args = {java.util.TimerTask.class, java.util.Date.class, long.class}
824    )
825    public void test_scheduleLjava_util_TimerTaskLjava_util_DateJ() {
826        Timer t = null;
827        try {
828            // Ensure a Timer throws an IllegalStateException after cancelled
829            t = new Timer();
830            TimerTestTask testTask = new TimerTestTask();
831            Date d = new Date(System.currentTimeMillis() + 100);
832            t.cancel();
833            boolean exception = false;
834            try {
835                t.schedule(testTask, d, 100);
836            } catch (IllegalStateException e) {
837                exception = true;
838            }
839            assertTrue(
840                    "Scheduling a task after Timer.cancel() should throw exception",
841                    exception);
842
843            // Ensure a Timer throws an IllegalStateException if task already
844            // cancelled
845            t = new Timer();
846            d = new Date(System.currentTimeMillis() + 100);
847            testTask = new TimerTestTask();
848            testTask.cancel();
849            exception = false;
850            try {
851                t.schedule(testTask, d, 100);
852            } catch (IllegalStateException e) {
853                exception = true;
854            }
855            assertTrue(
856                    "Scheduling a task after cancelling it should throw exception",
857                    exception);
858            t.cancel();
859
860            // Ensure a Timer throws an IllegalArgumentException if delay is
861            // negative
862            t = new Timer();
863            d = new Date(-100);
864            testTask = new TimerTestTask();
865            exception = false;
866            try {
867                t.schedule(testTask, d, 100);
868            } catch (IllegalArgumentException e) {
869                exception = true;
870            }
871            assertTrue(
872                    "Scheduling a task with negative delay should throw IllegalArgumentException",
873                    exception);
874            t.cancel();
875
876            // Ensure a Timer throws an IllegalArgumentException if period is
877            // negative
878            t = new Timer();
879            d = new Date(System.currentTimeMillis() + 100);
880            testTask = new TimerTestTask();
881            exception = false;
882            try {
883                t.schedule(testTask, d, -100);
884            } catch (IllegalArgumentException e) {
885                exception = true;
886            }
887            assertTrue(
888                    "Scheduling a task with negative period should throw IllegalArgumentException",
889                    exception);
890            t.cancel();
891
892            // Ensure a Timer throws a NullPointerException if the task is null
893            t = new Timer();
894            d = new Date(System.currentTimeMillis() + 100);
895            exception = false;
896            try {
897                t.schedule(null, d, 10);
898            } catch (NullPointerException e) {
899                exception = true;
900            }
901            assertTrue(
902                    "Scheduling a null task should throw NullPointerException",
903                    exception);
904            t.cancel();
905
906            // Ensure a Timer throws a NullPointerException if the date is null
907            t = new Timer();
908            testTask = new TimerTestTask();
909            exception = false;
910            try {
911                t.schedule(testTask, null, 10);
912            } catch (NullPointerException e) {
913                exception = true;
914            }
915            assertTrue(
916                    "Scheduling a null task should throw NullPointerException",
917                    exception);
918            t.cancel();
919
920            // Ensure proper sequence of exceptions
921            t = new Timer();
922            d = new Date(-100);
923            exception = false;
924            try {
925                t.schedule(null, d, 10);
926            } catch (NullPointerException e) {
927            } catch (IllegalArgumentException e) {
928                exception = true;
929            }
930            assertTrue(
931                    "Scheduling a null task with negative dates should throw IllegalArgumentException first",
932                    exception);
933            t.cancel();
934
935            // Ensure a task is run at least twice
936            t = new Timer();
937            d = new Date(System.currentTimeMillis() + 100);
938            testTask = new TimerTestTask();
939            t.schedule(testTask, d, 100);
940            try {
941                Thread.sleep(800);
942            } catch (InterruptedException e) {
943            }
944            assertTrue(
945                    "TimerTask.run() method should have been called at least twice ("
946                            + testTask.wasRun() + ")", testTask.wasRun() >= 2);
947            t.cancel();
948
949            // Ensure multiple tasks are run
950            t = new Timer();
951            testTask = new TimerTestTask();
952            testTask.incrementCount(true);
953            d = new Date(System.currentTimeMillis() + 100);
954            t.schedule(testTask, d, 100); // at least 9 times
955            testTask = new TimerTestTask();
956            testTask.incrementCount(true);
957            d = new Date(System.currentTimeMillis() + 200);
958            t.schedule(testTask, d, 100); // at least 7 times
959            testTask = new TimerTestTask();
960            testTask.incrementCount(true);
961            d = new Date(System.currentTimeMillis() + 300);
962            t.schedule(testTask, d, 200); // at least 4 times
963            testTask = new TimerTestTask();
964            testTask.incrementCount(true);
965            d = new Date(System.currentTimeMillis() + 100);
966            t.schedule(testTask, d, 200); // at least 4 times
967            try {
968                Thread.sleep(3000);
969            } catch (InterruptedException e) {
970            }
971            assertTrue(
972                    "Multiple tasks should have incremented counter 24 times not "
973                            + timerCounter, timerCounter >= 24);
974            t.cancel();
975        } finally {
976            if (t != null)
977                t.cancel();
978        }
979    }
980
981    /**
982     * @tests java.util.Timer#scheduleAtFixedRate(java.util.TimerTask, long,
983     *        long)
984     */
985    @TestTargetNew(
986        level = TestLevel.COMPLETE,
987        notes = "",
988        method = "scheduleAtFixedRate",
989        args = {java.util.TimerTask.class, long.class, long.class}
990    )
991    public void test_scheduleAtFixedRateLjava_util_TimerTaskJJ() {
992        Timer t = null;
993        try {
994            // Ensure a Timer throws an IllegalStateException after cancelled
995            t = new Timer();
996            TimerTestTask testTask = new TimerTestTask();
997            t.cancel();
998            boolean exception = false;
999            try {
1000                t.scheduleAtFixedRate(testTask, 100, 100);
1001            } catch (IllegalStateException e) {
1002                exception = true;
1003            }
1004            assertTrue(
1005                    "scheduleAtFixedRate after Timer.cancel() should throw exception",
1006                    exception);
1007
1008            // Ensure a Timer throws an IllegalArgumentException if delay is
1009            // negative
1010            t = new Timer();
1011            testTask = new TimerTestTask();
1012            exception = false;
1013            try {
1014                t.scheduleAtFixedRate(testTask, -100, 100);
1015            } catch (IllegalArgumentException e) {
1016                exception = true;
1017            }
1018            assertTrue(
1019                    "scheduleAtFixedRate with negative delay should throw IllegalArgumentException",
1020                    exception);
1021            t.cancel();
1022
1023            // Ensure a Timer throws an IllegalArgumentException if period is
1024            // negative
1025            t = new Timer();
1026            testTask = new TimerTestTask();
1027            exception = false;
1028            try {
1029                t.scheduleAtFixedRate(testTask, 100, -100);
1030            } catch (IllegalArgumentException e) {
1031                exception = true;
1032            }
1033            assertTrue(
1034                    "scheduleAtFixedRate with negative period should throw IllegalArgumentException",
1035                    exception);
1036            t.cancel();
1037
1038            // Ensure a task is run at least twice
1039            t = new Timer();
1040            testTask = new TimerTestTask();
1041            t.scheduleAtFixedRate(testTask, 100, 100);
1042            try {
1043                Thread.sleep(400);
1044            } catch (InterruptedException e) {
1045            }
1046            assertTrue(
1047                    "TimerTask.run() method should have been called at least twice ("
1048                            + testTask.wasRun() + ")", testTask.wasRun() >= 2);
1049            t.cancel();
1050
1051            class SlowThenFastTask extends TimerTask {
1052                int wasRun = 0;
1053
1054                long startedAt;
1055
1056                long lastDelta;
1057
1058                public void run() {
1059                    if (wasRun == 0)
1060                        startedAt = System.currentTimeMillis();
1061                    lastDelta = System.currentTimeMillis()
1062                            - (startedAt + (100 * wasRun));
1063                    wasRun++;
1064                    if (wasRun == 2) {
1065                        try {
1066                            Thread.sleep(200);
1067                        } catch (InterruptedException e) {
1068                        }
1069                    }
1070                }
1071
1072                public long lastDelta() {
1073                    return lastDelta;
1074                }
1075
1076                public int wasRun() {
1077                    return wasRun;
1078                }
1079            }
1080
1081            // Ensure multiple tasks are run
1082            t = new Timer();
1083            SlowThenFastTask slowThenFastTask = new SlowThenFastTask();
1084
1085            // at least 9 times even when asleep
1086            t.scheduleAtFixedRate(slowThenFastTask, 100, 100);
1087            try {
1088                Thread.sleep(1000);
1089            } catch (InterruptedException e) {
1090            }
1091            long lastDelta = slowThenFastTask.lastDelta();
1092            assertTrue("Fixed Rate Schedule should catch up, but is off by "
1093                    + lastDelta + " ms", slowThenFastTask.lastDelta < 300);
1094            t.cancel();
1095        } finally {
1096            if (t != null)
1097                t.cancel();
1098        }
1099    }
1100
1101    /**
1102     * @tests java.util.Timer#scheduleAtFixedRate(java.util.TimerTask,
1103     *        java.util.Date, long)
1104     */
1105    @TestTargetNew(
1106        level = TestLevel.COMPLETE,
1107        notes = "",
1108        method = "scheduleAtFixedRate",
1109        args = {java.util.TimerTask.class, java.util.Date.class, long.class}
1110    )
1111    public void test_scheduleAtFixedRateLjava_util_TimerTaskLjava_util_DateJ() {
1112        Timer t = null;
1113        try {
1114            // Ensure a Timer throws an IllegalStateException after cancelled
1115            t = new Timer();
1116            TimerTestTask testTask = new TimerTestTask();
1117            t.cancel();
1118            boolean exception = false;
1119            Date d = new Date(System.currentTimeMillis() + 100);
1120            try {
1121                t.scheduleAtFixedRate(testTask, d, 100);
1122            } catch (IllegalStateException e) {
1123                exception = true;
1124            }
1125            assertTrue(
1126                    "scheduleAtFixedRate after Timer.cancel() should throw exception",
1127                    exception);
1128
1129            // Ensure a Timer throws an IllegalArgumentException if delay is
1130            // negative
1131            t = new Timer();
1132            testTask = new TimerTestTask();
1133            exception = false;
1134            d = new Date(-100);
1135            try {
1136                t.scheduleAtFixedRate(testTask, d, 100);
1137            } catch (IllegalArgumentException e) {
1138                exception = true;
1139            }
1140            assertTrue(
1141                    "scheduleAtFixedRate with negative Date should throw IllegalArgumentException",
1142                    exception);
1143            t.cancel();
1144
1145            // Ensure a Timer throws an IllegalArgumentException if period is
1146            // negative
1147            t = new Timer();
1148            testTask = new TimerTestTask();
1149            exception = false;
1150            try {
1151                t.scheduleAtFixedRate(testTask, d, -100);
1152            } catch (IllegalArgumentException e) {
1153                exception = true;
1154            }
1155            assertTrue(
1156                    "scheduleAtFixedRate with negative period should throw IllegalArgumentException",
1157                    exception);
1158            t.cancel();
1159
1160            // Ensure a Timer throws an NullPointerException if date is Null
1161            t = new Timer();
1162            testTask = new TimerTestTask();
1163            exception = false;
1164            try {
1165                t.scheduleAtFixedRate(testTask, null, 100);
1166            } catch (NullPointerException e) {
1167                exception = true;
1168            }
1169            assertTrue(
1170                    "scheduleAtFixedRate with null date should throw NullPointerException",
1171                    exception);
1172            t.cancel();
1173
1174            // Ensure proper sequence of exceptions
1175            t = new Timer();
1176            exception = false;
1177            d = new Date(-100);
1178            try {
1179                t.scheduleAtFixedRate(null, d, 10);
1180            } catch (NullPointerException e) {
1181            } catch (IllegalArgumentException e) {
1182                exception = true;
1183            }
1184            assertTrue(
1185                    "Scheduling a null task with negative date should throw IllegalArgumentException first",
1186                    exception);
1187            t.cancel();
1188
1189            // Ensure proper sequence of exceptions
1190            t = new Timer();
1191            exception = false;
1192            try {
1193                t.scheduleAtFixedRate(null, null, -10);
1194            } catch (NullPointerException e) {
1195            } catch (IllegalArgumentException e) {
1196                exception = true;
1197            }
1198            assertTrue(
1199                    "Scheduling a null task & null date & negative period should throw IllegalArgumentException first",
1200                    exception);
1201            t.cancel();
1202
1203            // Ensure a task is run at least twice
1204            t = new Timer();
1205            testTask = new TimerTestTask();
1206            d = new Date(System.currentTimeMillis() + 100);
1207            t.scheduleAtFixedRate(testTask, d, 100);
1208            try {
1209                Thread.sleep(400);
1210            } catch (InterruptedException e) {
1211            }
1212            assertTrue(
1213                    "TimerTask.run() method should have been called at least twice ("
1214                            + testTask.wasRun() + ")", testTask.wasRun() >= 2);
1215            t.cancel();
1216
1217            class SlowThenFastTask extends TimerTask {
1218                int wasRun = 0;
1219
1220                long startedAt;
1221
1222                long lastDelta;
1223
1224                public void run() {
1225                    if (wasRun == 0)
1226                        startedAt = System.currentTimeMillis();
1227                    lastDelta = System.currentTimeMillis()
1228                            - (startedAt + (100 * wasRun));
1229                    wasRun++;
1230                    if (wasRun == 2) {
1231                        try {
1232                            Thread.sleep(200);
1233                        } catch (InterruptedException e) {
1234                        }
1235                    }
1236                }
1237
1238                public long lastDelta() {
1239                    return lastDelta;
1240                }
1241
1242                public int wasRun() {
1243                    return wasRun;
1244                }
1245            }
1246
1247            // Ensure multiple tasks are run
1248            t = new Timer();
1249            SlowThenFastTask slowThenFastTask = new SlowThenFastTask();
1250            d = new Date(System.currentTimeMillis() + 100);
1251
1252            // at least 9 times even when asleep
1253            t.scheduleAtFixedRate(slowThenFastTask, d, 100);
1254            try {
1255                Thread.sleep(1000);
1256            } catch (InterruptedException e) {
1257            }
1258            long lastDelta = slowThenFastTask.lastDelta();
1259            assertTrue("Fixed Rate Schedule should catch up, but is off by "
1260                    + lastDelta + " ms", lastDelta < 300);
1261            t.cancel();
1262        } finally {
1263            if (t != null)
1264                t.cancel();
1265        }
1266    }
1267
1268    /**
1269     * We used to swallow RuntimeExceptions thrown by tasks. Instead, we need to
1270     * let those exceptions bubble up, where they will both notify the thread's
1271     * uncaught exception handler and terminate the timer's thread.
1272     */
1273    public void testThrowingTaskKillsTimerThread() throws InterruptedException {
1274        final AtomicReference<Thread> threadRef = new AtomicReference<Thread>();
1275        new Timer().schedule(new TimerTask() {
1276            @Override public void run() {
1277                threadRef.set(Thread.currentThread());
1278                throw new RuntimeException("task failure!");
1279            }
1280        }, 1);
1281
1282        Thread.sleep(400);
1283        Thread timerThread = threadRef.get();
1284        assertFalse(timerThread.isAlive());
1285    }
1286
1287    protected void setUp() {
1288        timerCounter = 0;
1289    }
1290
1291    protected void tearDown() {
1292    }
1293}
1294