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