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