From bfefcbcfd4ba0e30315ae4dc282fbb19eefb9cf7 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Thu, 15 Dec 2022 15:06:25 +0100 Subject: [PATCH] Rewrote `EventContextProviderTest` to avoid using `call_user_func()` `call_user_func()` is automatically optimized away by PHP-SRC starting from early PHP 7 releases, and therefore cannot be used to generate artificial stack frames that are detected in PHP-SRC itself. With this change, we use `array_map()` instead, which (for now) is not optimized away (yet). --- .../EventLogging/EventContextProviderTest.php | 59 ++++++++++--------- 1 file changed, 32 insertions(+), 27 deletions(-) diff --git a/test/EventLogging/EventContextProviderTest.php b/test/EventLogging/EventContextProviderTest.php index 08be96f..bfb986d 100644 --- a/test/EventLogging/EventContextProviderTest.php +++ b/test/EventLogging/EventContextProviderTest.php @@ -7,38 +7,43 @@ use Laminas\DeveloperTools\EventLogging\EventContextProvider; use PHPUnit\Framework\TestCase; +use function array_map; + +/** @covers \Laminas\DeveloperTools\EventLogging\EventContextProvider */ class EventContextProviderTest extends TestCase { - public function testEventTriggerFileForInvokables() + public function testEventTriggerFileDetectsEmptyFileLocationWhenStackFrameIsInPhpItself(): void { - $eventProviderClass = new class { - public function __invoke() { - return call_user_func([$this, 'get']); - } - - private function get() - { - $eventProviderClass = new class { - public function __invoke($invokableClass, int $maxLevel, int $level = 0) - { - if ($level < $maxLevel) { - return $invokableClass($invokableClass, $maxLevel, ++$level); - } - - return (new EventContextProvider())->getEventTriggerFile(); - } - }; - - return $eventProviderClass($eventProviderClass, 3); - } - }; - - $eventTriggerFile = $eventProviderClass(); - self::assertSame( - '', - $eventTriggerFile, + [ + 'stack frame on this file: EventLogging/EventContextProviderTest.php', + 'stack frame in php core: ', + 'stack frame on this file: EventLogging/EventContextProviderTest.php', + ], + // Important: `array_map()` needed here, as it produces a stack frame without "file" location + array_map( + [$this, 'callEventContextProviderWithStackTraceNestingLevelAndName'], + [ + 'stack frame on this file', + 'stack frame in php core', + 'stack frame on this file', + ], + [ + 3, + 4, + 5, + ] + ), 'trigger file should be empty because user function calls do not refer to a file' ); } + + private function callEventContextProviderWithStackTraceNestingLevelAndName(string $name, int $level): string + { + if ($level > 0) { + return $this->callEventContextProviderWithStackTraceNestingLevelAndName($name, $level - 1); + } + + return $name . ': ' . (new EventContextProvider())->getEventTriggerFile(); + } }