From c152e4461f6e38e6cc9d0d798ed8206df4f69317 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20FIDRY?= Date: Sun, 23 Mar 2025 14:28:00 +0100 Subject: [PATCH 1/3] fix: Inherit PHP settings from the main process --- tests/Fixtures/Command/PhpSettingsCommand.php | 92 +++++++++++++++++++ tests/Integration/PhpProcessSettingsTest.php | 56 +++++++++++ 2 files changed, 148 insertions(+) create mode 100644 tests/Fixtures/Command/PhpSettingsCommand.php create mode 100644 tests/Integration/PhpProcessSettingsTest.php diff --git a/tests/Fixtures/Command/PhpSettingsCommand.php b/tests/Fixtures/Command/PhpSettingsCommand.php new file mode 100644 index 0000000..6a183ea --- /dev/null +++ b/tests/Fixtures/Command/PhpSettingsCommand.php @@ -0,0 +1,92 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Webmozarts\Console\Parallelization\Fixtures\Command; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputDefinition; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Terminal; +use Symfony\Component\Filesystem\Filesystem; +use Webmozarts\Console\Parallelization\ErrorHandler\ErrorHandler; +use Webmozarts\Console\Parallelization\Input\ParallelizationInput; +use Webmozarts\Console\Parallelization\Integration\TestDebugProgressBarFactory; +use Webmozarts\Console\Parallelization\Integration\TestLogger; +use Webmozarts\Console\Parallelization\Logger\Logger; +use Webmozarts\Console\Parallelization\Logger\StandardLogger; +use Webmozarts\Console\Parallelization\ParallelExecutorFactory; +use Webmozarts\Console\Parallelization\Parallelization; +use function file_get_contents; +use function ini_get; +use function json_decode; +use function realpath; +use const JSON_THROW_ON_ERROR; + +final class PhpSettingsCommand extends Command +{ + use Parallelization; + + public const OUTPUT_DIR = __DIR__.'/../../../dist/php-settings'; + + public function __construct( + private Filesystem $filesystem, + ) { + parent::__construct('test:php-settings'); + } + + protected function configure(): void + { + ParallelizationInput::configureCommand($this); + } + + /** + * @return list + */ + protected function fetchItems(InputInterface $input, OutputInterface $output): array + { + return ['item0']; + } + + protected function getParallelExecutableFactory( + callable $fetchItems, + callable $runSingleCommand, + callable $getItemName, + string $commandName, + InputDefinition $commandDefinition, + ErrorHandler $errorHandler + ): ParallelExecutorFactory { + return ParallelExecutorFactory::create( + $fetchItems, + $runSingleCommand, + $getItemName, + $commandName, + $commandDefinition, + $errorHandler, + ) + ->withScriptPath(realpath(__DIR__.'/../../../bin/console')); + } + + protected function runSingleCommand(string $item, InputInterface $input, OutputInterface $output): void + { + $this->filesystem->dumpFile( + self::OUTPUT_DIR, + ini_get('memory_limit'), + ); + } + + protected function getItemName(?int $count): string + { + return 1 === $count ? 'item' : 'items'; + } +} diff --git a/tests/Integration/PhpProcessSettingsTest.php b/tests/Integration/PhpProcessSettingsTest.php new file mode 100644 index 0000000..c6ef120 --- /dev/null +++ b/tests/Integration/PhpProcessSettingsTest.php @@ -0,0 +1,56 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Webmozarts\Console\Parallelization\Integration; + +use PHPUnit\Framework\Attributes\CoversNothing; +use PHPUnit\Framework\TestCase; +use Symfony\Bundle\FrameworkBundle\Console\Application; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Tester\CommandTester; +use Symfony\Component\Process\Process; +use Webmozarts\Console\Parallelization\Fixtures\Command\ImportMoviesCommand; +use Webmozarts\Console\Parallelization\Fixtures\Command\ImportUnknownMoviesCountCommand; +use Webmozarts\Console\Parallelization\Fixtures\Command\LegacyCommand; +use Webmozarts\Console\Parallelization\Fixtures\Command\NoSubProcessCommand; +use Webmozarts\Console\Parallelization\Fixtures\Command\PhpSettingsCommand; +use Webmozarts\Console\Parallelization\Integration\BareKernel; +use Webmozarts\Console\Parallelization\Integration\OutputNormalizer; +use Webmozarts\Console\Parallelization\Integration\TestLogger; +use function array_column; +use function array_map; +use function file_get_contents; +use function preg_replace; +use function spl_object_id; +use function str_replace; + +/** + * @internal + */ +#[CoversNothing] +class PhpProcessSettingsTest extends TestCase +{ + public function test_it_can_run_the_command_without_sub_processes(): void + { + $commandProcess = Process::fromShellCommandline( + 'php -dmemory_limit=768 bin/console test:php-settings', + __DIR__.'/../..', + ); + $commandProcess->run(); + + $expected = '768'; + $actual = file_get_contents(PhpSettingsCommand::OUTPUT_DIR); + + self::assertSame($expected, $actual); + } +} From 86ef5751d8424c38a7f0ac104568fa08f96b2ed5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20FIDRY?= Date: Sun, 23 Mar 2025 15:34:33 +0100 Subject: [PATCH 2/3] wip --- src/Input/ChildCommandFactory.php | 11 +--------- src/ParallelExecutor.php | 1 + src/Process/ProcessLauncherFactory.php | 1 + src/Process/StandardSymfonyProcessFactory.php | 5 ++--- src/Process/SymfonyProcessFactory.php | 1 + src/Process/SymfonyProcessLauncher.php | 2 ++ src/Process/SymfonyProcessLauncherFactory.php | 2 ++ tests/Fixtures/Command/PhpSettingsCommand.php | 15 ++++++++++++++ tests/Integration/PhpProcessSettingsTest.php | 20 +++++++++++++++---- 9 files changed, 41 insertions(+), 17 deletions(-) diff --git a/src/Input/ChildCommandFactory.php b/src/Input/ChildCommandFactory.php index b4ff6ff..5ece0b6 100644 --- a/src/Input/ChildCommandFactory.php +++ b/src/Input/ChildCommandFactory.php @@ -28,7 +28,7 @@ final class ChildCommandFactory { public function __construct( - private readonly string $phpExecutable, + public readonly string $phpExecutable, private readonly string $scriptPath, private readonly string $commandName, private readonly InputDefinition $commandDefinition, @@ -51,7 +51,6 @@ private function createBaseCommand( InputInterface $input ): array { return array_filter([ - ...$this->getEscapedPhpExecutable(), $this->scriptPath, $this->commandName, ...array_map(strval(...), self::getArguments($input)), @@ -74,14 +73,6 @@ private function getForwardedOptions(InputInterface $input): array ); } - /** - * @return list - */ - private function getEscapedPhpExecutable(): array - { - return explode(' ', $this->phpExecutable); - } - /** * @return list> */ diff --git a/src/ParallelExecutor.php b/src/ParallelExecutor.php index 074882c..ad451b5 100644 --- a/src/ParallelExecutor.php +++ b/src/ParallelExecutor.php @@ -266,6 +266,7 @@ private function createProcessLauncher( Logger $logger ): ProcessLauncher { return $this->processLauncherFactory->create( + $this->childCommandFactory->phpExecutable, $this->childCommandFactory->createChildCommand($input), $this->workingDirectory, $this->extraEnvironmentVariables, diff --git a/src/Process/ProcessLauncherFactory.php b/src/Process/ProcessLauncherFactory.php index 95f9ec1..3333881 100644 --- a/src/Process/ProcessLauncherFactory.php +++ b/src/Process/ProcessLauncherFactory.php @@ -31,6 +31,7 @@ interface ProcessLauncherFactory * @param callable(): void $tick */ public function create( + string $phpExecutable, array $command, string $workingDirectory, ?array $extraEnvironmentVariables, diff --git a/src/Process/StandardSymfonyProcessFactory.php b/src/Process/StandardSymfonyProcessFactory.php index b244404..72cb552 100644 --- a/src/Process/StandardSymfonyProcessFactory.php +++ b/src/Process/StandardSymfonyProcessFactory.php @@ -14,6 +14,7 @@ namespace Webmozarts\Console\Parallelization\Process; use Symfony\Component\Process\InputStream; +use Symfony\Component\Process\PhpSubprocess; use Symfony\Component\Process\Process; final class StandardSymfonyProcessFactory implements SymfonyProcessFactory @@ -26,12 +27,10 @@ public function startProcess( ?array $environmentVariables, callable $processOutput ): Process { - $process = new Process( + $process = new PhpSubprocess( $command, $workingDirectory, $environmentVariables, - null, - null, ); $process->setInput($inputStream); diff --git a/src/Process/SymfonyProcessFactory.php b/src/Process/SymfonyProcessFactory.php index c06db8a..1964785 100644 --- a/src/Process/SymfonyProcessFactory.php +++ b/src/Process/SymfonyProcessFactory.php @@ -35,6 +35,7 @@ interface SymfonyProcessFactory public function startProcess( int $index, InputStream $inputStream, + string $phpExecutable, array $command, string $workingDirectory, ?array $environmentVariables, diff --git a/src/Process/SymfonyProcessLauncher.php b/src/Process/SymfonyProcessLauncher.php index 3fdaa0a..2954b39 100644 --- a/src/Process/SymfonyProcessLauncher.php +++ b/src/Process/SymfonyProcessLauncher.php @@ -60,6 +60,7 @@ final class SymfonyProcessLauncher implements ProcessLauncher * @param callable(): void $tick */ public function __construct( + private readonly string $phpExecutable, private readonly array $command, private readonly string $workingDirectory, private readonly ?array $environmentVariables, @@ -135,6 +136,7 @@ private function startProcess(InputStream $inputStream): void $process = $this->processFactory->startProcess( $index, $inputStream, + $this->phpExecutable, $this->command, $this->workingDirectory, $this->environmentVariables, diff --git a/src/Process/SymfonyProcessLauncherFactory.php b/src/Process/SymfonyProcessLauncherFactory.php index 2434171..69ee3ca 100644 --- a/src/Process/SymfonyProcessLauncherFactory.php +++ b/src/Process/SymfonyProcessLauncherFactory.php @@ -32,6 +32,7 @@ public function __construct(private readonly SymfonyProcessFactory $processFacto * @param callable(): void $tick */ public function create( + string $phpExecutable, array $command, string $workingDirectory, ?array $extraEnvironmentVariables, @@ -42,6 +43,7 @@ public function create( callable $tick ): ProcessLauncher { return new SymfonyProcessLauncher( + $phpExecutable, $command, $workingDirectory, $extraEnvironmentVariables, diff --git a/tests/Fixtures/Command/PhpSettingsCommand.php b/tests/Fixtures/Command/PhpSettingsCommand.php index 6a183ea..3a1b589 100644 --- a/tests/Fixtures/Command/PhpSettingsCommand.php +++ b/tests/Fixtures/Command/PhpSettingsCommand.php @@ -24,6 +24,7 @@ use Webmozarts\Console\Parallelization\Integration\TestDebugProgressBarFactory; use Webmozarts\Console\Parallelization\Integration\TestLogger; use Webmozarts\Console\Parallelization\Logger\Logger; +use Webmozarts\Console\Parallelization\Logger\NullLogger; use Webmozarts\Console\Parallelization\Logger\StandardLogger; use Webmozarts\Console\Parallelization\ParallelExecutorFactory; use Webmozarts\Console\Parallelization\Parallelization; @@ -74,9 +75,18 @@ protected function getParallelExecutableFactory( $commandDefinition, $errorHandler, ) + ->withRunBeforeFirstCommand(self::runBeforeFirstCommand(...)) ->withScriptPath(realpath(__DIR__.'/../../../bin/console')); } + private function runBeforeFirstCommand(): void + { + $this->filesystem->dumpFile( + self::OUTPUT_DIR.'_main_process', + ini_get('memory_limit'), + ); + } + protected function runSingleCommand(string $item, InputInterface $input, OutputInterface $output): void { $this->filesystem->dumpFile( @@ -89,4 +99,9 @@ protected function getItemName(?int $count): string { return 1 === $count ? 'item' : 'items'; } + + protected function createLogger(InputInterface $input, OutputInterface $output): Logger + { + return new NullLogger(); + } } diff --git a/tests/Integration/PhpProcessSettingsTest.php b/tests/Integration/PhpProcessSettingsTest.php index c6ef120..5a472b1 100644 --- a/tests/Integration/PhpProcessSettingsTest.php +++ b/tests/Integration/PhpProcessSettingsTest.php @@ -43,14 +43,26 @@ class PhpProcessSettingsTest extends TestCase public function test_it_can_run_the_command_without_sub_processes(): void { $commandProcess = Process::fromShellCommandline( - 'php -dmemory_limit=768 bin/console test:php-settings', + 'php -dmemory_limit="256M" bin/console test:php-settings', __DIR__.'/../..', ); $commandProcess->run(); - $expected = '768'; - $actual = file_get_contents(PhpSettingsCommand::OUTPUT_DIR); + $expectedMainProcessMemoryLimit = '256M'; + $actualMainProcessMemoryLimit = file_get_contents(PhpSettingsCommand::OUTPUT_DIR.'_main_process'); - self::assertSame($expected, $actual); + $expectedChildProcessMemoryLimit = '256M'; + $actualChildProcessMemoryLimit = file_get_contents(PhpSettingsCommand::OUTPUT_DIR); + + self::assertSame( + [ + $expectedMainProcessMemoryLimit, + $expectedChildProcessMemoryLimit, + ], + [ + $actualMainProcessMemoryLimit, + $actualChildProcessMemoryLimit, + ], + ); } } From 0ef08ce4fd9b410b10d69d18cc647a8cec6c8608 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20FIDRY?= Date: Sun, 20 Apr 2025 10:34:40 +0200 Subject: [PATCH 3/3] flesh out --- src/Input/ChildCommandFactory.php | 12 +-- src/ParallelExecutorFactory.php | 19 +++- src/Process/ProcessLauncherFactory.php | 2 +- src/Process/StandardSymfonyProcessFactory.php | 2 + src/Process/SymfonyProcessFactory.php | 2 +- src/Process/SymfonyProcessLauncher.php | 2 +- src/Process/SymfonyProcessLauncherFactory.php | 2 +- tests/Fixtures/Command/PhpSettingsCommand.php | 52 +++++++---- tests/Integration/PhpProcessSettingsTest.php | 87 +++++++++++++++++-- 9 files changed, 137 insertions(+), 43 deletions(-) diff --git a/src/Input/ChildCommandFactory.php b/src/Input/ChildCommandFactory.php index 5db40f6..8736ee3 100644 --- a/src/Input/ChildCommandFactory.php +++ b/src/Input/ChildCommandFactory.php @@ -30,7 +30,7 @@ * @param list $phpExecutable */ public function __construct( - private array $phpExecutable, + public array $phpExecutable, private string $scriptPath, private string $commandName, private InputDefinition $commandDefinition, @@ -53,7 +53,7 @@ private function createBaseCommand( InputInterface $input ): array { return array_filter([ - ...$this->phpExecutable, + //...$this->phpExecutable, $this->scriptPath, $this->commandName, ...array_map(strval(...), self::getArguments($input)), @@ -76,14 +76,6 @@ private function getForwardedOptions(InputInterface $input): array ); } - /** - * @return list - */ - private function getEscapedPhpExecutable(): array - { - return explode(' ', $this->phpExecutable); - } - /** * @return list> */ diff --git a/src/ParallelExecutorFactory.php b/src/ParallelExecutorFactory.php index 7de66d4..b85d8c1 100644 --- a/src/ParallelExecutorFactory.php +++ b/src/ParallelExecutorFactory.php @@ -232,7 +232,24 @@ public function withProgressSymbol(string $progressSymbol): self * The path of the PHP executable. It is the executable that will be used * to spawn the child process(es). * - * @param string|list $phpExecutable e.g. ['/path/to/php', '-dmemory_limit=512M'] + * It can be a string (the path of the PHP executable), or an array + * to set some PHP settings or others, for example: + * + * ``` + * ['/path/to/php', '-dmemory_limit=512M'] + * ``` + * + * However, beware that those settings will take precedence over the + * inherited settings from the main process. As a result, if you execute: + * + * ``` + * $ php -dmemory_limit=1024M bin/console my:command + * ``` + * + * Then the memory limit of the main process will be 1024M, but the memory + * limit of the child processes will remain 512M. + * + * @param string|list $phpExecutable */ public function withPhpExecutable(string|array $phpExecutable): self { diff --git a/src/Process/ProcessLauncherFactory.php b/src/Process/ProcessLauncherFactory.php index 3333881..89fdc0a 100644 --- a/src/Process/ProcessLauncherFactory.php +++ b/src/Process/ProcessLauncherFactory.php @@ -31,7 +31,7 @@ interface ProcessLauncherFactory * @param callable(): void $tick */ public function create( - string $phpExecutable, + array $phpExecutable, array $command, string $workingDirectory, ?array $extraEnvironmentVariables, diff --git a/src/Process/StandardSymfonyProcessFactory.php b/src/Process/StandardSymfonyProcessFactory.php index 72cb552..fd638a3 100644 --- a/src/Process/StandardSymfonyProcessFactory.php +++ b/src/Process/StandardSymfonyProcessFactory.php @@ -22,6 +22,7 @@ final class StandardSymfonyProcessFactory implements SymfonyProcessFactory public function startProcess( int $index, InputStream $inputStream, + array $phpExecutable, array $command, string $workingDirectory, ?array $environmentVariables, @@ -31,6 +32,7 @@ public function startProcess( $command, $workingDirectory, $environmentVariables, + php: $phpExecutable, ); $process->setInput($inputStream); diff --git a/src/Process/SymfonyProcessFactory.php b/src/Process/SymfonyProcessFactory.php index 1964785..a121130 100644 --- a/src/Process/SymfonyProcessFactory.php +++ b/src/Process/SymfonyProcessFactory.php @@ -35,7 +35,7 @@ interface SymfonyProcessFactory public function startProcess( int $index, InputStream $inputStream, - string $phpExecutable, + array $phpExecutable, array $command, string $workingDirectory, ?array $environmentVariables, diff --git a/src/Process/SymfonyProcessLauncher.php b/src/Process/SymfonyProcessLauncher.php index 2954b39..044f4e8 100644 --- a/src/Process/SymfonyProcessLauncher.php +++ b/src/Process/SymfonyProcessLauncher.php @@ -60,7 +60,7 @@ final class SymfonyProcessLauncher implements ProcessLauncher * @param callable(): void $tick */ public function __construct( - private readonly string $phpExecutable, + private readonly array $phpExecutable, private readonly array $command, private readonly string $workingDirectory, private readonly ?array $environmentVariables, diff --git a/src/Process/SymfonyProcessLauncherFactory.php b/src/Process/SymfonyProcessLauncherFactory.php index 4f07c17..8e4edcb 100644 --- a/src/Process/SymfonyProcessLauncherFactory.php +++ b/src/Process/SymfonyProcessLauncherFactory.php @@ -32,7 +32,7 @@ public function __construct(private SymfonyProcessFactory $processFactory) * @param callable(): void $tick */ public function create( - string $phpExecutable, + array $phpExecutable, array $command, string $workingDirectory, ?array $extraEnvironmentVariables, diff --git a/tests/Fixtures/Command/PhpSettingsCommand.php b/tests/Fixtures/Command/PhpSettingsCommand.php index 3a1b589..df6c832 100644 --- a/tests/Fixtures/Command/PhpSettingsCommand.php +++ b/tests/Fixtures/Command/PhpSettingsCommand.php @@ -26,19 +26,22 @@ use Webmozarts\Console\Parallelization\Logger\Logger; use Webmozarts\Console\Parallelization\Logger\NullLogger; use Webmozarts\Console\Parallelization\Logger\StandardLogger; +use Webmozarts\Console\Parallelization\ParallelCommand; use Webmozarts\Console\Parallelization\ParallelExecutorFactory; use Webmozarts\Console\Parallelization\Parallelization; +use Webmozarts\Console\Parallelization\Process\PhpExecutableFinder; use function file_get_contents; use function ini_get; use function json_decode; use function realpath; +use function sprintf; +use function xdebug_break; use const JSON_THROW_ON_ERROR; -final class PhpSettingsCommand extends Command +final class PhpSettingsCommand extends ParallelCommand { - use Parallelization; - - public const OUTPUT_DIR = __DIR__.'/../../../dist/php-settings'; + public const string MAIN_PROCESS_OUTPUT_DIR = __DIR__.'/../../../dist/php-settings_main-process'; + public const string CHILD_PROCESS_OUTPUT_DIR = __DIR__.'/../../../dist/php-settings_child-process'; public function __construct( private Filesystem $filesystem, @@ -46,11 +49,6 @@ public function __construct( parent::__construct('test:php-settings'); } - protected function configure(): void - { - ParallelizationInput::configureCommand($this); - } - /** * @return list */ @@ -76,32 +74,48 @@ protected function getParallelExecutableFactory( $errorHandler, ) ->withRunBeforeFirstCommand(self::runBeforeFirstCommand(...)) + ->withPhpExecutable([ + ...PhpExecutableFinder::find(), + '-dmax_input_time=30', + ]) ->withScriptPath(realpath(__DIR__.'/../../../bin/console')); } private function runBeforeFirstCommand(): void { - $this->filesystem->dumpFile( - self::OUTPUT_DIR.'_main_process', - ini_get('memory_limit'), - ); + $this->dumpMemoryLimit(self::MAIN_PROCESS_OUTPUT_DIR); } protected function runSingleCommand(string $item, InputInterface $input, OutputInterface $output): void + { + $this->dumpMemoryLimit(self::CHILD_PROCESS_OUTPUT_DIR); + } + + private function dumpMemoryLimit(string $filePath): void { $this->filesystem->dumpFile( - self::OUTPUT_DIR, - ini_get('memory_limit'), + $filePath, + sprintf( + 'memory_limit=%s%smax_input_time=%s', + ini_get('memory_limit'), + "\n", + ini_get('max_input_time'), + ), ); } - protected function getItemName(?int $count): string + public static function createSettingsOutput(string $memoryLimit, string $maxInputTime): string { - return 1 === $count ? 'item' : 'items'; + return sprintf( + 'memory_limit=%s%smax_input_time=%s', + $memoryLimit, + "\n", + $maxInputTime, + ); } - protected function createLogger(InputInterface $input, OutputInterface $output): Logger + protected function getItemName(?int $count): string { - return new NullLogger(); + return 1 === $count ? 'item' : 'items'; } } diff --git a/tests/Integration/PhpProcessSettingsTest.php b/tests/Integration/PhpProcessSettingsTest.php index 5a472b1..af281a4 100644 --- a/tests/Integration/PhpProcessSettingsTest.php +++ b/tests/Integration/PhpProcessSettingsTest.php @@ -18,6 +18,7 @@ use Symfony\Bundle\FrameworkBundle\Console\Application; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Tester\CommandTester; +use Symfony\Component\Filesystem\Filesystem; use Symfony\Component\Process\Process; use Webmozarts\Console\Parallelization\Fixtures\Command\ImportMoviesCommand; use Webmozarts\Console\Parallelization\Fixtures\Command\ImportUnknownMoviesCountCommand; @@ -30,6 +31,7 @@ use function array_column; use function array_map; use function file_get_contents; +use function ini_get; use function preg_replace; use function spl_object_id; use function str_replace; @@ -40,29 +42,96 @@ #[CoversNothing] class PhpProcessSettingsTest extends TestCase { - public function test_it_can_run_the_command_without_sub_processes(): void + protected function setUp(): void + { + self::cleanupOutputFiles(); + } + + protected function tearDown(): void + { + self::cleanupOutputFiles(); + } + + public function test_it_can_run_the_command_setting_the_memory_limit(): void { $commandProcess = Process::fromShellCommandline( 'php -dmemory_limit="256M" bin/console test:php-settings', __DIR__.'/../..', + ['XDEBUG_SESSION' => '1', 'XDEBUG_MODE' => 'debug'], ); $commandProcess->run(); - $expectedMainProcessMemoryLimit = '256M'; - $actualMainProcessMemoryLimit = file_get_contents(PhpSettingsCommand::OUTPUT_DIR.'_main_process'); + self::assertTrue( + $commandProcess->isSuccessful(), + $commandProcess->getOutput() . $commandProcess->getErrorOutput(), + ); - $expectedChildProcessMemoryLimit = '256M'; - $actualChildProcessMemoryLimit = file_get_contents(PhpSettingsCommand::OUTPUT_DIR); + $expectedMainProcessPhpSettings = PhpSettingsCommand::createSettingsOutput( + '256M', // comes from setting it when launching the command + ini_get('max_input_time'), + ); + $actualMainProcessPhpSettings = file_get_contents(PhpSettingsCommand::MAIN_PROCESS_OUTPUT_DIR); + + $expectedChildProcessPhpSettings = PhpSettingsCommand::createSettingsOutput( + '256M', + '30', // comes from PhpSettingsCommand specifying it in the config + ); + $actualChildProcessPhpSettings = file_get_contents(PhpSettingsCommand::CHILD_PROCESS_OUTPUT_DIR); self::assertSame( [ - $expectedMainProcessMemoryLimit, - $expectedChildProcessMemoryLimit, + 'main' => $expectedMainProcessPhpSettings, + 'child' => $expectedChildProcessPhpSettings, ], [ - $actualMainProcessMemoryLimit, - $actualChildProcessMemoryLimit, + 'main' => $actualMainProcessPhpSettings, + 'child' => $actualChildProcessPhpSettings, ], ); } + + public function test_it_can_run_the_command_setting_the_a_php_setting_configured_in_the_command(): void + { + $commandProcess = Process::fromShellCommandline( + 'php -dmemory_limit="256M" -dmax_input_time=45 bin/console test:php-settings', + __DIR__.'/../..', + ['XDEBUG_SESSION' => '1', 'XDEBUG_MODE' => 'debug'], + ); + $commandProcess->run(); + + self::assertTrue( + $commandProcess->isSuccessful(), + $commandProcess->getOutput() . $commandProcess->getErrorOutput(), + ); + + $expectedMainProcessPhpSettings = PhpSettingsCommand::createSettingsOutput( + '256M', // comes from setting it when launching the command + '45', // comes from setting it when launching the command + ); + $actualMainProcessPhpSettings = file_get_contents(PhpSettingsCommand::MAIN_PROCESS_OUTPUT_DIR); + + $expectedChildProcessPhpSettings = PhpSettingsCommand::createSettingsOutput( + '256M', + '30', // comes from PhpSettingsCommand specifying it in the config + ); + $actualChildProcessPhpSettings = file_get_contents(PhpSettingsCommand::CHILD_PROCESS_OUTPUT_DIR); + + self::assertSame( + [ + 'main' => $expectedMainProcessPhpSettings, + 'child' => $expectedChildProcessPhpSettings, + ], + [ + 'main' => $actualMainProcessPhpSettings, + 'child' => $actualChildProcessPhpSettings, + ], + ); + } + + private static function cleanupOutputFiles(): void + { + $fileSystem = new Filesystem(); + $fileSystem->remove(PhpSettingsCommand::MAIN_PROCESS_OUTPUT_DIR); + $fileSystem->remove(PhpSettingsCommand::CHILD_PROCESS_OUTPUT_DIR); + } }