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 org.apache.harmony.tests.java.util;
19
20import java.util.Timer;
21import java.util.TimerTask;
22
23public class TimerTaskTest extends junit.framework.TestCase {
24    /**
25     * Warning: These tests have the possibility to leave a VM hanging if the
26     * Timer is not cancelled.
27     */
28    class TimerTestTask extends TimerTask {
29
30        private final Object sync = new Object();
31        private final Object start = new Object();
32
33        private int wasRun = 0;
34
35        // Set this to true to see normal tests fail (or hang possibly)
36        // The default is false and needs to be set by some tests
37        private boolean sleepInRun = false;
38
39        public void run() {
40            synchronized (this) {
41                wasRun++;
42            }
43            synchronized (start) {
44                start.notify();
45            }
46            if (sleepInRun) {
47
48                try {
49                    Thread.sleep(200);
50                } catch (InterruptedException e) {
51                }
52            }
53            synchronized (sync) {
54                sync.notify();
55            }
56        }
57
58        public synchronized int wasRun() {
59            return wasRun;
60        }
61
62        public void sleepInRun(boolean value) {
63            sleepInRun = value;
64        }
65    }
66
67    /**
68     * java.util.TimerTask#TimerTask()
69     */
70    public void test_Constructor() {
71        // Ensure the constructor does not fail
72        new TimerTestTask();
73    }
74
75    /**
76     * java.util.TimerTask#cancel()
77     */
78    public void test_cancel() {
79        Timer t = null;
80        try {
81            // Ensure cancel returns false if never scheduled
82            TimerTestTask testTask = new TimerTestTask();
83            assertTrue("Unsheduled tasks should return false for cancel()",
84                    !testTask.cancel());
85
86            // Ensure cancelled task never runs
87            t = new Timer();
88            testTask = new TimerTestTask();
89            t.schedule(testTask, 500);
90            assertTrue("TimerTask should not have run yet", testTask.cancel());
91            t.cancel();
92
93            // Ensure cancelling a task which has already run returns true
94            t = new Timer();
95            testTask = new TimerTestTask();
96            t.schedule(testTask, 50);
97            while (testTask.wasRun() == 0) {
98                try {
99                    Thread.sleep(150);
100                } catch (InterruptedException e) {
101                }
102            }
103            assertFalse(
104                    "TimerTask.cancel() should return false if task has run",
105                    testTask.cancel());
106            assertFalse(
107                    "TimerTask.cancel() should return false if called a second time",
108                    testTask.cancel());
109            t.cancel();
110
111            // Ensure cancelling a repeated execution task which has never run
112            // returns true
113            t = new Timer();
114            testTask = new TimerTestTask();
115            t.schedule(testTask, 500, 500); // should never run
116            assertTrue(
117                    "TimerTask.cancel() should return true if sheduled for repeated execution even if not run",
118                    testTask.cancel());
119            t.cancel();
120
121            // Ensure cancelling a repeated execution task which HAS run returns
122            // true
123            t = new Timer();
124            testTask = new TimerTestTask();
125            t.schedule(testTask, 50, 50);
126            while (testTask.wasRun() == 0) {
127                try {
128                    Thread.sleep(100);
129                } catch (InterruptedException e) {
130                }
131            }
132            assertTrue(
133                    "TimerTask.cancel() should return true if sheduled for repeated execution and run",
134                    testTask.cancel());
135            t.cancel();
136
137            // Ensure calling cancel a second returns false
138            t = new Timer();
139            testTask = new TimerTestTask();
140            t.schedule(testTask, 5000); // Should never run
141            assertTrue(
142                    "TimerTask.cancel() should return true if task has never run",
143                    testTask.cancel());
144            assertFalse(
145                    "TimerTask.cancel() should return false if called a second time",
146                    testTask.cancel());
147            t.cancel();
148
149            // Ensure cancelling a task won't cause deadlock
150            t = new Timer();
151            testTask = new TimerTestTask();
152            testTask.sleepInRun(true);
153            synchronized (testTask.start) {
154                t.schedule(testTask, 0);
155                try {
156                    testTask.start.wait();
157                    Thread.sleep(50);
158                } catch (InterruptedException e) {
159                }
160            }
161            assertFalse("TimerTask should have been cancelled", testTask
162                    .cancel());
163            t.cancel();
164        } finally {
165            if (t != null)
166                t.cancel();
167        }
168    }
169
170    /**
171     * java.util.TimerTask#scheduledExecutionTime()
172     */
173    public void test_scheduledExecutionTime() {
174        Timer t = null;
175        try {
176            TimerTestTask testTask = new TimerTestTask();
177            assertEquals(0, testTask.scheduledExecutionTime());
178
179            // Ensure scheduledExecutionTime is roughly right
180            t = new Timer();
181            testTask = new TimerTestTask();
182            t.schedule(testTask, 100);
183            long time = System.currentTimeMillis() + 100;
184            synchronized (testTask.sync) {
185                try {
186                    testTask.sync.wait(500);
187                } catch (InterruptedException e) {
188                }
189            }
190            long scheduledExecutionTime = testTask.scheduledExecutionTime();
191            assertTrue(scheduledExecutionTime <= time);
192            t.cancel();
193
194            // Ensure scheduledExecutionTime is the last scheduled time
195            t = new Timer();
196            testTask = new TimerTestTask();
197            t.schedule(testTask, 100, 500);
198
199            // Should be scheduled ~100ms from "now" (and then again in ~600ms) so account
200            // for some jitter.
201            long estNow = System.currentTimeMillis() + 200;
202
203            // Will wake in 100, and every 500 run again
204            // We want to try to get it after it's run at least once but not
205            // twice
206            synchronized (testTask.sync) {
207                try {
208                    testTask.sync.wait(500);
209                } catch (InterruptedException e) {
210                }
211            }
212            scheduledExecutionTime = testTask.scheduledExecutionTime();
213            assertTrue(scheduledExecutionTime <= estNow);
214            t.cancel();
215        } finally {
216            if (t != null)
217                t.cancel();
218        }
219
220    }
221
222    /**
223     * java.util.TimerTask#run()
224     */
225    public void test_run() {
226        Timer t = null;
227        try {
228            // Ensure a new task is never run
229            TimerTestTask testTask = new TimerTestTask();
230            try {
231                Thread.sleep(200);
232            } catch (InterruptedException e) {
233            }
234            assertEquals("TimerTask.run() method should not have been called",
235                    0, testTask.wasRun());
236
237            // Ensure a task is run
238            t = new Timer();
239            testTask = new TimerTestTask();
240            t.schedule(testTask, 200);
241            while(testTask.wasRun() < 1) {
242                try {
243                    Thread.sleep(400);
244                } catch (InterruptedException e) {
245                }
246            }
247            assertFalse(testTask.cancel());
248            t.cancel();
249        } finally {
250            if (t != null)
251                t.cancel();
252        }
253
254    }
255}
256