From 28711f59f3aef932567a8f304fae3589ebd95bc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C3=BA=C5=A1=20Koterba?= Date: Sun, 1 Mar 2026 17:55:26 +0100 Subject: [PATCH 1/4] feat: Add timebox --- src/support/src/Timebox.php | 71 +++++++++++++++++++++++++++ tests/Support/TimeboxTest.php | 92 +++++++++++++++++++++++++++++++++++ 2 files changed, 163 insertions(+) create mode 100644 src/support/src/Timebox.php create mode 100644 tests/Support/TimeboxTest.php diff --git a/src/support/src/Timebox.php b/src/support/src/Timebox.php new file mode 100644 index 000000000..98a59cee2 --- /dev/null +++ b/src/support/src/Timebox.php @@ -0,0 +1,71 @@ +earlyReturn && $remainder > 0) { + $this->usleep($remainder); + } + + if ($exception) { + throw $exception; + } + + return $result; + } + + /** + * @return static + */ + public function returnEarly() + { + $this->earlyReturn = true; + + return $this; + } + + /** + * @return static + */ + public function dontReturnEarly() + { + $this->earlyReturn = false; + + return $this; + } + + protected function usleep(int $microseconds) + { + Sleep::usleep($microseconds); + } +} diff --git a/tests/Support/TimeboxTest.php b/tests/Support/TimeboxTest.php new file mode 100644 index 000000000..00ecb9649 --- /dev/null +++ b/tests/Support/TimeboxTest.php @@ -0,0 +1,92 @@ +assertTrue(true); + }; + + (new Timebox())->call($callback, 0); + } + + public function testMakeWaitsForMicroseconds() + { + $mock = Mockery::spy(Timebox::class)->shouldAllowMockingProtectedMethods()->makePartial(); + $mock->shouldReceive('usleep')->once(); + + $mock->call(function () { + }, 10000); + + $mock->shouldHaveReceived('usleep')->once(); + } + + public function testMakeShouldNotSleepWhenEarlyReturnHasBeenFlagged() + { + $mock = Mockery::spy(Timebox::class)->shouldAllowMockingProtectedMethods()->makePartial(); + $mock->call(function ($timebox) { + $timebox->returnEarly(); + }, 10000); + + $mock->shouldNotHaveReceived('usleep'); + } + + public function testMakeShouldSleepWhenDontEarlyReturnHasBeenFlagged() + { + $mock = Mockery::spy(Timebox::class)->shouldAllowMockingProtectedMethods()->makePartial(); + $mock->shouldReceive('usleep')->once(); + + $mock->call(function ($timebox) { + $timebox->returnEarly(); + $timebox->dontReturnEarly(); + }, 10000); + + $mock->shouldHaveReceived('usleep')->once(); + } + + public function testMakeWaitsForMicrosecondsWhenExceptionIsThrown() + { + $mock = Mockery::spy(Timebox::class)->shouldAllowMockingProtectedMethods()->makePartial(); + $mock->shouldReceive('usleep')->once(); + + try { + $this->expectExceptionMessage('Exception within Timebox callback.'); + + $mock->call(function () { + throw new Exception('Exception within Timebox callback.'); + }, 10000); + } finally { + $mock->shouldHaveReceived('usleep')->once(); + } + } + + public function testMakeShouldNotSleepWhenEarlyReturnHasBeenFlaggedAndExceptionIsThrown() + { + $mock = Mockery::spy(Timebox::class)->shouldAllowMockingProtectedMethods()->makePartial(); + + try { + $this->expectExceptionMessage('Exception within Timebox callback.'); + + $mock->call(function ($timebox) { + $timebox->returnEarly(); + throw new Exception('Exception within Timebox callback.'); + }, 10000); + } finally { + $mock->shouldNotHaveReceived('usleep'); + } + } +} From 4cbecf75f3d5846d0878d378541b4f3615f09ff4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C3=BA=C5=A1=20Koterba?= Date: Sun, 1 Mar 2026 18:00:23 +0100 Subject: [PATCH 2/4] Add return types --- src/support/src/Timebox.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/support/src/Timebox.php b/src/support/src/Timebox.php index 98a59cee2..b5e468078 100644 --- a/src/support/src/Timebox.php +++ b/src/support/src/Timebox.php @@ -47,7 +47,7 @@ public function call(callable $callback, int $microseconds): mixed /** * @return static */ - public function returnEarly() + public function returnEarly(): static { $this->earlyReturn = true; @@ -57,7 +57,7 @@ public function returnEarly() /** * @return static */ - public function dontReturnEarly() + public function dontReturnEarly(): static { $this->earlyReturn = false; From f82eb34346886b2b8342c0b01d0edc22c45280b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C3=BA=C5=A1=20Koterba?= Date: Sun, 1 Mar 2026 18:01:09 +0100 Subject: [PATCH 3/4] More return types --- tests/Support/TimeboxTest.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/Support/TimeboxTest.php b/tests/Support/TimeboxTest.php index 00ecb9649..991d6c448 100644 --- a/tests/Support/TimeboxTest.php +++ b/tests/Support/TimeboxTest.php @@ -15,7 +15,7 @@ */ class TimeboxTest extends TestCase { - public function testMakeExecutesCallback() + public function testMakeExecutesCallback(): void { $callback = function () { $this->assertTrue(true); @@ -24,7 +24,7 @@ public function testMakeExecutesCallback() (new Timebox())->call($callback, 0); } - public function testMakeWaitsForMicroseconds() + public function testMakeWaitsForMicroseconds(): void { $mock = Mockery::spy(Timebox::class)->shouldAllowMockingProtectedMethods()->makePartial(); $mock->shouldReceive('usleep')->once(); @@ -35,7 +35,7 @@ public function testMakeWaitsForMicroseconds() $mock->shouldHaveReceived('usleep')->once(); } - public function testMakeShouldNotSleepWhenEarlyReturnHasBeenFlagged() + public function testMakeShouldNotSleepWhenEarlyReturnHasBeenFlagged(): void { $mock = Mockery::spy(Timebox::class)->shouldAllowMockingProtectedMethods()->makePartial(); $mock->call(function ($timebox) { @@ -45,7 +45,7 @@ public function testMakeShouldNotSleepWhenEarlyReturnHasBeenFlagged() $mock->shouldNotHaveReceived('usleep'); } - public function testMakeShouldSleepWhenDontEarlyReturnHasBeenFlagged() + public function testMakeShouldSleepWhenDontEarlyReturnHasBeenFlagged(): void { $mock = Mockery::spy(Timebox::class)->shouldAllowMockingProtectedMethods()->makePartial(); $mock->shouldReceive('usleep')->once(); @@ -58,7 +58,7 @@ public function testMakeShouldSleepWhenDontEarlyReturnHasBeenFlagged() $mock->shouldHaveReceived('usleep')->once(); } - public function testMakeWaitsForMicrosecondsWhenExceptionIsThrown() + public function testMakeWaitsForMicrosecondsWhenExceptionIsThrown(): void { $mock = Mockery::spy(Timebox::class)->shouldAllowMockingProtectedMethods()->makePartial(); $mock->shouldReceive('usleep')->once(); @@ -74,7 +74,7 @@ public function testMakeWaitsForMicrosecondsWhenExceptionIsThrown() } } - public function testMakeShouldNotSleepWhenEarlyReturnHasBeenFlaggedAndExceptionIsThrown() + public function testMakeShouldNotSleepWhenEarlyReturnHasBeenFlaggedAndExceptionIsThrown(): void { $mock = Mockery::spy(Timebox::class)->shouldAllowMockingProtectedMethods()->makePartial(); From c6472e1c7f44645a856c0dda7ac7c8a0ba0b8cfd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C3=BA=C5=A1=20Koterba?= Date: Sun, 1 Mar 2026 18:02:57 +0100 Subject: [PATCH 4/4] CS --- src/support/src/Timebox.php | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/support/src/Timebox.php b/src/support/src/Timebox.php index b5e468078..16d89ea37 100644 --- a/src/support/src/Timebox.php +++ b/src/support/src/Timebox.php @@ -44,9 +44,6 @@ public function call(callable $callback, int $microseconds): mixed return $result; } - /** - * @return static - */ public function returnEarly(): static { $this->earlyReturn = true; @@ -54,9 +51,6 @@ public function returnEarly(): static return $this; } - /** - * @return static - */ public function dontReturnEarly(): static { $this->earlyReturn = false;