From 75ff0b2df823c263d5098b388883b8ff92b30d56 Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Mon, 23 Jan 2023 16:05:36 +0100 Subject: [PATCH] Fix edge cases --- lib/Loop.php | 18 +++++---- test/GenericTest.php | 93 ++++++++++++++++++++++++++++++++++++++----- test/PeriodicTest.php | 2 +- 3 files changed, 93 insertions(+), 20 deletions(-) diff --git a/lib/Loop.php b/lib/Loop.php index d7d4c72..97d901c 100644 --- a/lib/Loop.php +++ b/lib/Loop.php @@ -66,8 +66,9 @@ abstract class Loop implements Stringable return false; } $this->running = true; + $this->paused = true; + \assert($this->resume()); $this->startedLoop(); - $this->resume(); return true; } /** @@ -89,7 +90,7 @@ abstract class Loop implements Stringable if ($this->resumeImmediate) { $storedWatcherId = $this->resumeImmediate; EventLoop::cancel($storedWatcherId); - $this->resumeTimer = null; + $this->resumeImmediate = null; } if ($this->paused) { $this->exitedLoop(); @@ -102,17 +103,18 @@ abstract class Loop implements Stringable private function loopInternal(): void { $this->paused = false; - if (!$this->running) { - $this->exitedLoopInternal(); - return; - } + \assert($this->running); try { $timeout = $this->loop(); } catch (\Throwable $e) { $this->exitedLoopInternal(); throw $e; } - if (!$this->running || $timeout === self::STOP) { + if (!$this->running) { + $this->exitedLoopInternal(); + return; + } + if ($timeout === self::STOP) { $this->exitedLoopInternal(); return; } @@ -139,7 +141,7 @@ abstract class Loop implements Stringable if ($this->resumeImmediate) { $storedWatcherId = $this->resumeImmediate; EventLoop::cancel($storedWatcherId); - $this->resumeTimer = null; + $this->resumeImmediate = null; } $this->exitedLoop(); } diff --git a/test/GenericTest.php b/test/GenericTest.php index 5b8591f..d024923 100644 --- a/test/GenericTest.php +++ b/test/GenericTest.php @@ -104,11 +104,11 @@ class GenericTest extends AsyncTestCase /** * Fixture assertions for started loop. */ - private function fixtureStarted(Loop&LoggingPauseInterface $loop): void + private function fixtureStarted(Loop&LoggingPauseInterface $loop, int $offset = 1): void { $this->assertTrue($loop->isRunning()); - $this->assertEquals(1, $loop->startCounter()); - $this->assertEquals(0, $loop->endCounter()); + $this->assertEquals($offset, $loop->startCounter()); + $this->assertEquals($offset-1, $loop->endCounter()); } /** * Run fixture assertions. @@ -123,20 +123,23 @@ class GenericTest extends AsyncTestCase $loop = new class($closure, Fixtures::LOOP_NAME) extends GenericLoop implements LoggingPauseInterface { use LoggingPause; }; + $expectedRunCount = 0; + $this->assertEquals(Fixtures::LOOP_NAME, "$loop"); $this->assertFalse($loop->isRunning()); $this->assertEquals(0, $loop->startCounter()); $this->assertEquals(0, $loop->endCounter()); - $this->assertEquals(0, $runCount); + $this->assertEquals($expectedRunCount, $runCount); $this->assertEquals(0, $loop->getPauseCount()); - $loop->start(); + $this->assertTrue($loop->start()); delay(0.003); $this->fixtureStarted($loop); + $expectedRunCount++; - $this->assertEquals(1, $runCount); + $this->assertEquals($expectedRunCount, $runCount); $this->assertEquals(1, $loop->getPauseCount()); $this->assertEquals(0, $loop->getLastPause()); @@ -144,29 +147,32 @@ class GenericTest extends AsyncTestCase $this->assertTrue($loop->resume()); delay(0.002); $this->fixtureStarted($loop); + $expectedRunCount++; - $this->assertEquals(2, $runCount); + $this->assertEquals($expectedRunCount, $runCount); $this->assertEquals(2, $loop->getPauseCount()); $this->assertEquals(0.1, $loop->getLastPause()); delay(0.048); $this->fixtureStarted($loop); - $this->assertEquals(2, $runCount); + $this->assertEquals($expectedRunCount, $runCount); $this->assertEquals(2, $loop->getPauseCount()); $this->assertEquals(0.1, $loop->getLastPause()); delay(0.060); $this->fixtureStarted($loop); + $expectedRunCount++; - $this->assertEquals(3, $runCount); + $this->assertEquals($expectedRunCount, $runCount); $this->assertEquals(3, $loop->getPauseCount()); $this->assertEquals(0.1, $loop->getLastPause()); $this->assertTrue($loop->resume()); delay(0.003); + $expectedRunCount++; - $this->assertEquals(4, $runCount); + $this->assertEquals($expectedRunCount, $runCount); $this->assertEquals(4, $loop->getPauseCount()); $this->assertEquals(0.1, $loop->getLastPause()); @@ -175,9 +181,10 @@ class GenericTest extends AsyncTestCase } else { $pauseTime = GenericLoop::STOP; $this->assertTrue($loop->resume()); + $expectedRunCount++; } delay(0.002); - $this->assertEquals($stopSig ? 4 : 5, $runCount); + $this->assertEquals($expectedRunCount, $runCount); $this->assertEquals(4, $loop->getPauseCount()); $this->assertEquals(0.1, $loop->getLastPause()); @@ -187,6 +194,70 @@ class GenericTest extends AsyncTestCase $this->assertFalse($loop->isRunning()); $this->assertFalse($loop->stop()); $this->assertFalse($loop->resume()); + + // Restart loop + $pauseTime = GenericLoop::PAUSE; + $this->assertTrue($loop->start()); + delay(0.003); + $this->fixtureStarted($loop, 2); + $expectedRunCount++; + + $this->assertEquals($expectedRunCount, $runCount); + $this->assertEquals(5, $loop->getPauseCount()); + $this->assertEquals(0.0, $loop->getLastPause()); + + if ($stopSig) { + $this->assertTrue($loop->stop()); + } else { + $pauseTime = GenericLoop::STOP; + $this->assertTrue($loop->resume()); + $expectedRunCount++; + } + delay(0.002); + $this->assertEquals($expectedRunCount, $runCount); + $this->assertEquals(5, $loop->getPauseCount()); + $this->assertEquals(0.0, $loop->getLastPause()); + + $this->assertEquals(2, $loop->startCounter()); + $this->assertEquals(2, $loop->endCounter()); + + $this->assertFalse($loop->isRunning()); + $this->assertFalse($loop->stop()); + $this->assertFalse($loop->resume()); + + // Restart loop and stop it immediately + $pauseTime = GenericLoop::PAUSE; + $this->assertTrue($loop->start()); + $this->assertTrue($loop->stop()); + delay(0.003); + + $this->assertEquals($expectedRunCount, $runCount); + $this->assertEquals(5, $loop->getPauseCount()); + $this->assertEquals(0.0, $loop->getLastPause()); + + $this->assertEquals(3, $loop->startCounter()); + $this->assertEquals(3, $loop->endCounter()); + + $this->assertFalse($loop->isRunning()); + $this->assertFalse($loop->stop()); + $this->assertFalse($loop->resume()); + + // Restart loop with delay and stop it immediately + $pauseTime = 1.0; + $this->assertTrue($loop->start()); + $this->assertTrue($loop->stop()); + delay(0.003); + + $this->assertEquals($expectedRunCount, $runCount); + $this->assertEquals(5, $loop->getPauseCount()); + $this->assertEquals(0.0, $loop->getLastPause()); + + $this->assertEquals(4, $loop->startCounter()); + $this->assertEquals(4, $loop->endCounter()); + + $this->assertFalse($loop->isRunning()); + $this->assertFalse($loop->stop()); + $this->assertFalse($loop->resume()); } /** diff --git a/test/PeriodicTest.php b/test/PeriodicTest.php index 00ca5a7..daf749a 100644 --- a/test/PeriodicTest.php +++ b/test/PeriodicTest.php @@ -131,7 +131,7 @@ class PeriodicTest extends AsyncTestCase $this->assertEquals(0, $runCount); - $loop->start(); + $this->assertTrue($loop->start()); delay(0.002); $this->fixtureStarted($loop);