AbstractTimerTest.php 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. <?php
  2. namespace React\Tests\EventLoop\Timer;
  3. use React\EventLoop\LoopInterface;
  4. use React\Tests\EventLoop\TestCase;
  5. abstract class AbstractTimerTest extends TestCase
  6. {
  7. /**
  8. * @return LoopInterface
  9. */
  10. abstract public function createLoop();
  11. public function testAddTimerReturnsNonPeriodicTimerInstance()
  12. {
  13. $loop = $this->createLoop();
  14. $timer = $loop->addTimer(0.001, $this->expectCallableNever());
  15. $this->assertInstanceOf('React\EventLoop\TimerInterface', $timer);
  16. $this->assertFalse($timer->isPeriodic());
  17. }
  18. public function testAddTimerWillBeInvokedOnceAndBlocksLoopWhenRunning()
  19. {
  20. $loop = $this->createLoop();
  21. $loop->addTimer(0.005, $this->expectCallableOnce());
  22. $start = microtime(true);
  23. $loop->run();
  24. $end = microtime(true);
  25. // 1 invocation should take 5ms (± a few milliseconds due to timer inaccuracies)
  26. // make no strict assumptions about time interval, must at least take 1ms
  27. // and should not take longer than 0.1s for slower loops.
  28. $this->assertGreaterThanOrEqual(0.001, $end - $start);
  29. $this->assertLessThan(0.1, $end - $start);
  30. }
  31. public function testAddPeriodicTimerReturnsPeriodicTimerInstance()
  32. {
  33. $loop = $this->createLoop();
  34. $periodic = $loop->addPeriodicTimer(0.1, $this->expectCallableNever());
  35. $this->assertInstanceOf('React\EventLoop\TimerInterface', $periodic);
  36. $this->assertTrue($periodic->isPeriodic());
  37. }
  38. public function testAddPeriodicTimerWillBeInvokedUntilItIsCancelled()
  39. {
  40. $loop = $this->createLoop();
  41. $periodic = $loop->addPeriodicTimer(0.1, $this->expectCallableExactly(3));
  42. // make no strict assumptions about actual time interval.
  43. // leave some room to ensure this ticks exactly 3 times.
  44. $loop->addTimer(0.350, function () use ($loop, $periodic) {
  45. $loop->cancelTimer($periodic);
  46. });
  47. $loop->run();
  48. }
  49. public function testAddPeriodicTimerWillBeInvokedWithMaximumAccuracyUntilItIsCancelled()
  50. {
  51. $loop = $this->createLoop();
  52. $i = 0;
  53. $periodic = $loop->addPeriodicTimer(0.001, function () use (&$i) {
  54. ++$i;
  55. });
  56. $loop->addTimer(0.1, function () use ($loop, $periodic) {
  57. $loop->cancelTimer($periodic);
  58. });
  59. $loop->run();
  60. // make no strict assumptions about number of invocations.
  61. // we know it must be no more than 100 times and should at least be
  62. // invoked 4 times for really slow loops
  63. $this->assertLessThanOrEqual(100, $i);
  64. $this->assertGreaterThanOrEqual(4, $i);
  65. }
  66. public function testAddPeriodicTimerCancelsItself()
  67. {
  68. $loop = $this->createLoop();
  69. $i = 0;
  70. $loop->addPeriodicTimer(0.001, function ($timer) use (&$i, $loop) {
  71. $i++;
  72. if ($i === 5) {
  73. $loop->cancelTimer($timer);
  74. }
  75. });
  76. $start = microtime(true);
  77. $loop->run();
  78. $end = microtime(true);
  79. $this->assertEquals(5, $i);
  80. // 5 invocations should take 5ms (± 1ms due to timer inaccuracies)
  81. // make no strict assumptions about time interval, must at least take 4ms
  82. // and should not take longer than 0.2s for slower loops.
  83. $this->assertGreaterThanOrEqual(0.004, $end - $start);
  84. $this->assertLessThan(0.2, $end - $start);
  85. }
  86. public function testMinimumIntervalOneMicrosecond()
  87. {
  88. $loop = $this->createLoop();
  89. $timer = $loop->addTimer(0, function () {});
  90. $this->assertEquals(0.000001, $timer->getInterval());
  91. }
  92. public function testAddPeriodicTimerWithZeroIntervalWillExecuteCallbackFunctionAtLeastTwice()
  93. {
  94. $loop = $this->createLoop();
  95. $timeout = $loop->addTimer(2, $this->expectCallableNever()); //Timeout the test after two seconds if the periodic timer hasn't fired twice
  96. $i = 0;
  97. $loop->addPeriodicTimer(0, function ($timer) use (&$i, $loop, $timeout) {
  98. ++$i;
  99. if ($i === 2) {
  100. $loop->cancelTimer($timer);
  101. $loop->cancelTimer($timeout);
  102. }
  103. });
  104. $loop->run();
  105. $this->assertEquals(2, $i);
  106. }
  107. public function testTimerIntervalBelowZeroRunsImmediately()
  108. {
  109. $loop = $this->createLoop();
  110. $start = 0;
  111. $loop->addTimer(
  112. -1,
  113. function () use (&$start) {
  114. $start = \microtime(true);
  115. }
  116. );
  117. $loop->run();
  118. $end = \microtime(true);
  119. // 1ms should be enough even on slow machines (± 1ms due to timer inaccuracies)
  120. $this->assertLessThan(0.002, $end - $start);
  121. }
  122. }