From 9468799542aa19179118ded1fe3bc9f025ec9aa4 Mon Sep 17 00:00:00 2001 From: Maks Rafalko Date: Sat, 1 Jun 2024 11:26:12 +0200 Subject: [PATCH] Fix usage of custom mutator with bootstrap file (#1973) On Infection Playground, we don't use composer to load files in PSR-4 format, we use custom very simple PSR-4 compliant autoloader, which is configured to be used in `infection.json5` in `bootstrap` setting. In `master` branch, Infection tries to `resolveMutators()` **before** loading bootstrap files, thus failing finding custom mutator. In order to prepare configuration, where custom mutators are resolved, we need to load (`require_once`) custom bootstrap file before mutators are resolved. This fixes the bug and allows Playground to use custom mutators. --- src/Command/RunCommand.php | 20 ---- src/Configuration/ConfigurationFactory.php | 19 +++ .../ConfigurationFactoryTest.php | 111 +++++++++++++++++- .../Fixtures/Files/bootstrap/bootstrap.php | 3 + .../Fixtures/Mutator/CustomMutator.php | 35 ++++++ 5 files changed, 166 insertions(+), 22 deletions(-) create mode 100644 tests/phpunit/Fixtures/Files/bootstrap/bootstrap.php create mode 100644 tests/phpunit/Fixtures/Mutator/CustomMutator.php diff --git a/src/Command/RunCommand.php b/src/Command/RunCommand.php index cb1200acab..afb5ac0e7f 100644 --- a/src/Command/RunCommand.php +++ b/src/Command/RunCommand.php @@ -36,7 +36,6 @@ namespace Infection\Command; use function extension_loaded; -use function file_exists; use function getenv; use function implode; use function in_array; @@ -577,8 +576,6 @@ private function startUp( $config = $container->getConfiguration(); - $this->includeUserBootstrap($config); - $container->getFileSystem()->mkdir($config->getTmpDir()); LogVerbosity::convertVerbosityLevel($io->getInput(), $consoleOutput); @@ -605,23 +602,6 @@ private function runConfigurationCommand(Locator $locator, IO $io): void } } - private function includeUserBootstrap(Configuration $config): void - { - $bootstrap = $config->getBootstrap(); - - if ($bootstrap === null) { - return; - } - - if (!file_exists($bootstrap)) { - throw FileOrDirectoryNotFound::fromFileName($bootstrap, [__DIR__]); - } - - (static function (string $infectionBootstrapFile): void { - require_once $infectionBootstrapFile; - })($bootstrap); - } - private function logRunningWithDebugger(ConsoleOutput $consoleOutput): void { if (PHP_SAPI === 'phpdbg') { diff --git a/src/Configuration/ConfigurationFactory.php b/src/Configuration/ConfigurationFactory.php index 9cc3dc008c..733a79a2be 100644 --- a/src/Configuration/ConfigurationFactory.php +++ b/src/Configuration/ConfigurationFactory.php @@ -40,10 +40,12 @@ use function array_unique; use function array_values; use function dirname; +use function file_exists; use function in_array; use Infection\Configuration\Entry\Logs; use Infection\Configuration\Entry\PhpUnit; use Infection\Configuration\Schema\SchemaConfiguration; +use Infection\FileSystem\Locator\FileOrDirectoryNotFound; use Infection\FileSystem\SourceFileCollector; use Infection\FileSystem\TmpDirProvider; use Infection\Logger\FileLogger; @@ -128,6 +130,8 @@ public function create( $namespacedTmpDir, ); + $this->includeUserBootstrap($schema->getBootstrap()); + $resolvedMutatorsArray = $this->resolveMutators($schema->getMutators(), $mutatorsInput); $mutators = $this->mutatorFactory->create($resolvedMutatorsArray, $useNoopMutators); @@ -172,6 +176,21 @@ public function create( ); } + private function includeUserBootstrap(?string $bootstrap): void + { + if ($bootstrap === null) { + return; + } + + if (!file_exists($bootstrap)) { + throw FileOrDirectoryNotFound::fromFileName($bootstrap, [__DIR__]); + } + + (static function (string $infectionBootstrapFile): void { + require_once $infectionBootstrapFile; + })($bootstrap); + } + /** * @param array $schemaMutators * diff --git a/tests/phpunit/Configuration/ConfigurationFactoryTest.php b/tests/phpunit/Configuration/ConfigurationFactoryTest.php index 929a70e741..98bdfeabd4 100644 --- a/tests/phpunit/Configuration/ConfigurationFactoryTest.php +++ b/tests/phpunit/Configuration/ConfigurationFactoryTest.php @@ -57,6 +57,7 @@ use Infection\TestFramework\MapSourceClassToTestStrategy; use Infection\Testing\SingletonContainer; use Infection\Tests\Fixtures\DummyCiDetector; +use Infection\Tests\Fixtures\Mutator\CustomMutator; use function Infection\Tests\normalizePath; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\DataProvider; @@ -877,7 +878,7 @@ public static function valueProvider(): iterable null, ['@default' => true], 'phpunit', - 'config/bootstrap.php', + __DIR__ . '/../Fixtures/Files/bootstrap/bootstrap.php', '-d zend_extension=wrong_xdebug.so', '--debug', ), @@ -936,7 +937,113 @@ public static function valueProvider(): iterable 'TrueValue' => new TrueValue(new TrueValueConfig([])), ])(), 'phpspec', - 'config/bootstrap.php', + __DIR__ . '/../Fixtures/Files/bootstrap/bootstrap.php', + '-d zend_extension=xdebug.so', + false, + '--stop-on-failure', + '/path/to/dist/coverage', + true, + true, + true, + true, + true, + 72.3, + true, + 81.5, + [], + false, + MapSourceClassToTestStrategy::SIMPLE, + ]; + + yield 'custom mutator with bootstrap file' => [ + false, + false, + new SchemaConfiguration( + '/path/to/infection.json', + 10, + new Source(['src/'], ['vendor/']), + new Logs( + '/text.log', + '/report.html', + '/summary.log', + '/json.log', + '/gitlab.log', + '/debug.log', + '/mutator.log', + true, + StrykerConfig::forFullReport('master'), + '/summary.json', + ), + 'config/tmp', + new PhpUnit( + 'config/phpunit-dir', + 'config/phpunit', + ), + null, + null, + null, + ['@default' => false, 'CustomMutator' => true], + 'phpunit', + __DIR__ . '/../Fixtures/Files/bootstrap/bootstrap.php', + '-d zend_extension=wrong_xdebug.so', + '--debug', + ), + 'dist/coverage', + '-d zend_extension=xdebug.so', + false, + 'none', + true, + true, + true, + true, + 72.3, + true, + 81.5, + '', + 'phpspec', + '--stop-on-failure', + 'src/Foo.php, src/Bar.php', + 4, + true, + null, + false, + 'master', + false, + null, + null, + false, + 2, + 10, + ['src/'], + [ + new SplFileInfo('src/Foo.php', 'src/Foo.php', 'src/Foo.php'), + new SplFileInfo('src/Bar.php', 'src/Bar.php', 'src/Bar.php'), + ], + 'src/Foo.php, src/Bar.php', + ['vendor/'], + new Logs( + '/text.log', + '/report.html', + '/summary.log', + '/json.log', + '/gitlab.log', + '/debug.log', + '/mutator.log', + true, + StrykerConfig::forFullReport('master'), + '/summary.json', + ), + 'none', + '/path/to/config/tmp/infection', + new PhpUnit( + '/path/to/config/phpunit-dir', + 'config/phpunit', + ), + (static fn (): array => [ + 'CustomMutator' => new CustomMutator(), + ])(), + 'phpspec', + __DIR__ . '/../Fixtures/Files/bootstrap/bootstrap.php', '-d zend_extension=xdebug.so', false, '--stop-on-failure', diff --git a/tests/phpunit/Fixtures/Files/bootstrap/bootstrap.php b/tests/phpunit/Fixtures/Files/bootstrap/bootstrap.php new file mode 100644 index 0000000000..d590b6fa7c --- /dev/null +++ b/tests/phpunit/Fixtures/Files/bootstrap/bootstrap.php @@ -0,0 +1,3 @@ +