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