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