From 748eb37e9982dd9131b3fbce0435f8bc9a5a8d9d Mon Sep 17 00:00:00 2001 From: tianfenghan Date: Thu, 9 Jul 2026 11:56:17 +0800 Subject: [PATCH] test(aot): add Symfony framework compatibility tests - Add test for AssetMapper style match statement with nullsafe side effect and throw arm - Add test for Finder style lazy iterator using yield from callable property invocation - Add test for HttpFoundation style static reflection cache with coalesce assignment operator - Include proper skip conditions for unsupported features - Verify correct behavior of Symfony-style PHP constructs in AOT compilation --- ...etmapper-match-statement-side-effects.phpt | 62 +++++++++++++++++++ ...der-lazy-iterator-yield-from-callable.phpt | 36 +++++++++++ ...tion-reflection-cache-coalesce-assign.phpt | 36 +++++++++++ 3 files changed, 134 insertions(+) create mode 100644 tests/aot/symfony/assetmapper-match-statement-side-effects.phpt create mode 100644 tests/aot/symfony/finder-lazy-iterator-yield-from-callable.phpt create mode 100644 tests/aot/symfony/httpfoundation-reflection-cache-coalesce-assign.phpt diff --git a/tests/aot/symfony/assetmapper-match-statement-side-effects.phpt b/tests/aot/symfony/assetmapper-match-statement-side-effects.phpt new file mode 100644 index 00000000..fac5d26c --- /dev/null +++ b/tests/aot/symfony/assetmapper-match-statement-side-effects.phpt @@ -0,0 +1,62 @@ +--TEST-- +Symfony AssetMapper style match statement with nullsafe side effect and throw arm +--FILE-- +messages[] = $message; + } +} + +class SymfonyMissingImportHandler +{ + public const IGNORE = 'ignore'; + public const WARN = 'warn'; + public const STRICT = 'strict'; + + public function __construct( + private string $mode, + private ?SymfonyMissingImportLogger $logger = null, + ) { + } + + public function handle(string $message): void + { + match ($this->mode) { + self::IGNORE => null, + self::WARN => $this->logger?->warning($message), + self::STRICT => throw new RuntimeException($message), + }; + } +} + +function main(): void +{ + $logger = new SymfonyMissingImportMemoryLogger(); + (new SymfonyMissingImportHandler(SymfonyMissingImportHandler::IGNORE))->handle('ignored'); + (new SymfonyMissingImportHandler(SymfonyMissingImportHandler::WARN, $logger))->handle('missing.js'); + + var_dump($logger->messages); + + try { + (new SymfonyMissingImportHandler(SymfonyMissingImportHandler::STRICT))->handle('strict.js'); + } catch (RuntimeException $e) { + echo $e->getMessage(), "\n"; + } +} +?> +--EXPECT-- +array(1) { + [0]=> + string(10) "missing.js" +} +strict.js diff --git a/tests/aot/symfony/finder-lazy-iterator-yield-from-callable.phpt b/tests/aot/symfony/finder-lazy-iterator-yield-from-callable.phpt new file mode 100644 index 00000000..28a1461e --- /dev/null +++ b/tests/aot/symfony/finder-lazy-iterator-yield-from-callable.phpt @@ -0,0 +1,36 @@ +--TEST-- +Symfony Finder style lazy iterator: yield from callable property invocation +--SKIPIF-- + +--FILE-- +iteratorFactory = $iteratorFactory(...); + } + + public function getIterator(): Traversable + { + yield from ($this->iteratorFactory)(); + } +} + +function main(): void +{ + $iterator = new SymfonyLazyIteratorCase(static function (): Traversable { + yield 'first' => 'alpha'; + yield 'second' => 'beta'; + }); + + foreach ($iterator as $key => $value) { + echo $key, '=', $value, "\n"; + } +} +?> +--EXPECT-- +first=alpha +second=beta diff --git a/tests/aot/symfony/httpfoundation-reflection-cache-coalesce-assign.phpt b/tests/aot/symfony/httpfoundation-reflection-cache-coalesce-assign.phpt new file mode 100644 index 00000000..ec76ddb8 --- /dev/null +++ b/tests/aot/symfony/httpfoundation-reflection-cache-coalesce-assign.phpt @@ -0,0 +1,36 @@ +--TEST-- +Symfony HttpFoundation style static reflection cache with coalesce assignment +--FILE-- +statusText; + } + + public static function setProperty(self $response, string $name, mixed $value): void + { + static $cache; + + $property = $cache[$name] ??= new ReflectionProperty(self::class, $name); + $property->setValue($response, $value); + } +} + +function main(): void +{ + $response = new SymfonyReflectionCacheResponse(); + + SymfonyReflectionCacheResponse::setProperty($response, 'statusText', 'created'); + var_dump($response->getStatusText()); + + SymfonyReflectionCacheResponse::setProperty($response, 'statusText', 'accepted'); + var_dump($response->getStatusText()); +} +?> +--EXPECT-- +string(7) "created" +string(8) "accepted"