Skip to content

Commit 0ef08ce

Browse files
committed
flesh out
1 parent c57acb2 commit 0ef08ce

9 files changed

+137
-43
lines changed

src/Input/ChildCommandFactory.php

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
* @param list<string> $phpExecutable
3131
*/
3232
public function __construct(
33-
private array $phpExecutable,
33+
public array $phpExecutable,
3434
private string $scriptPath,
3535
private string $commandName,
3636
private InputDefinition $commandDefinition,
@@ -53,7 +53,7 @@ private function createBaseCommand(
5353
InputInterface $input
5454
): array {
5555
return array_filter([
56-
...$this->phpExecutable,
56+
//...$this->phpExecutable,
5757
$this->scriptPath,
5858
$this->commandName,
5959
...array_map(strval(...), self::getArguments($input)),
@@ -76,14 +76,6 @@ private function getForwardedOptions(InputInterface $input): array
7676
);
7777
}
7878

79-
/**
80-
* @return list<string>
81-
*/
82-
private function getEscapedPhpExecutable(): array
83-
{
84-
return explode(' ', $this->phpExecutable);
85-
}
86-
8779
/**
8880
* @return list<string|bool|int|float|null|array<string|bool|int|float|null>>
8981
*/

src/ParallelExecutorFactory.php

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,24 @@ public function withProgressSymbol(string $progressSymbol): self
232232
* The path of the PHP executable. It is the executable that will be used
233233
* to spawn the child process(es).
234234
*
235-
* @param string|list<string> $phpExecutable e.g. ['/path/to/php', '-dmemory_limit=512M']
235+
* It can be a string (the path of the PHP executable), or an array
236+
* to set some PHP settings or others, for example:
237+
*
238+
* ```
239+
* ['/path/to/php', '-dmemory_limit=512M']
240+
* ```
241+
*
242+
* However, beware that those settings will take precedence over the
243+
* inherited settings from the main process. As a result, if you execute:
244+
*
245+
* ```
246+
* $ php -dmemory_limit=1024M bin/console my:command
247+
* ```
248+
*
249+
* Then the memory limit of the main process will be 1024M, but the memory
250+
* limit of the child processes will remain 512M.
251+
*
252+
* @param string|list<string> $phpExecutable
236253
*/
237254
public function withPhpExecutable(string|array $phpExecutable): self
238255
{

src/Process/ProcessLauncherFactory.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ interface ProcessLauncherFactory
3131
* @param callable(): void $tick
3232
*/
3333
public function create(
34-
string $phpExecutable,
34+
array $phpExecutable,
3535
array $command,
3636
string $workingDirectory,
3737
?array $extraEnvironmentVariables,

src/Process/StandardSymfonyProcessFactory.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ final class StandardSymfonyProcessFactory implements SymfonyProcessFactory
2222
public function startProcess(
2323
int $index,
2424
InputStream $inputStream,
25+
array $phpExecutable,
2526
array $command,
2627
string $workingDirectory,
2728
?array $environmentVariables,
@@ -31,6 +32,7 @@ public function startProcess(
3132
$command,
3233
$workingDirectory,
3334
$environmentVariables,
35+
php: $phpExecutable,
3436
);
3537

3638
$process->setInput($inputStream);

src/Process/SymfonyProcessFactory.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ interface SymfonyProcessFactory
3535
public function startProcess(
3636
int $index,
3737
InputStream $inputStream,
38-
string $phpExecutable,
38+
array $phpExecutable,
3939
array $command,
4040
string $workingDirectory,
4141
?array $environmentVariables,

src/Process/SymfonyProcessLauncher.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ final class SymfonyProcessLauncher implements ProcessLauncher
6060
* @param callable(): void $tick
6161
*/
6262
public function __construct(
63-
private readonly string $phpExecutable,
63+
private readonly array $phpExecutable,
6464
private readonly array $command,
6565
private readonly string $workingDirectory,
6666
private readonly ?array $environmentVariables,

src/Process/SymfonyProcessLauncherFactory.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ public function __construct(private SymfonyProcessFactory $processFactory)
3232
* @param callable(): void $tick
3333
*/
3434
public function create(
35-
string $phpExecutable,
35+
array $phpExecutable,
3636
array $command,
3737
string $workingDirectory,
3838
?array $extraEnvironmentVariables,

tests/Fixtures/Command/PhpSettingsCommand.php

Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -26,31 +26,29 @@
2626
use Webmozarts\Console\Parallelization\Logger\Logger;
2727
use Webmozarts\Console\Parallelization\Logger\NullLogger;
2828
use Webmozarts\Console\Parallelization\Logger\StandardLogger;
29+
use Webmozarts\Console\Parallelization\ParallelCommand;
2930
use Webmozarts\Console\Parallelization\ParallelExecutorFactory;
3031
use Webmozarts\Console\Parallelization\Parallelization;
32+
use Webmozarts\Console\Parallelization\Process\PhpExecutableFinder;
3133
use function file_get_contents;
3234
use function ini_get;
3335
use function json_decode;
3436
use function realpath;
37+
use function sprintf;
38+
use function xdebug_break;
3539
use const JSON_THROW_ON_ERROR;
3640

37-
final class PhpSettingsCommand extends Command
41+
final class PhpSettingsCommand extends ParallelCommand
3842
{
39-
use Parallelization;
40-
41-
public const OUTPUT_DIR = __DIR__.'/../../../dist/php-settings';
43+
public const string MAIN_PROCESS_OUTPUT_DIR = __DIR__.'/../../../dist/php-settings_main-process';
44+
public const string CHILD_PROCESS_OUTPUT_DIR = __DIR__.'/../../../dist/php-settings_child-process';
4245

4346
public function __construct(
4447
private Filesystem $filesystem,
4548
) {
4649
parent::__construct('test:php-settings');
4750
}
4851

49-
protected function configure(): void
50-
{
51-
ParallelizationInput::configureCommand($this);
52-
}
53-
5452
/**
5553
* @return list<string>
5654
*/
@@ -76,32 +74,48 @@ protected function getParallelExecutableFactory(
7674
$errorHandler,
7775
)
7876
->withRunBeforeFirstCommand(self::runBeforeFirstCommand(...))
77+
->withPhpExecutable([
78+
...PhpExecutableFinder::find(),
79+
'-dmax_input_time=30',
80+
])
7981
->withScriptPath(realpath(__DIR__.'/../../../bin/console'));
8082
}
8183

8284
private function runBeforeFirstCommand(): void
8385
{
84-
$this->filesystem->dumpFile(
85-
self::OUTPUT_DIR.'_main_process',
86-
ini_get('memory_limit'),
87-
);
86+
$this->dumpMemoryLimit(self::MAIN_PROCESS_OUTPUT_DIR);
8887
}
8988

9089
protected function runSingleCommand(string $item, InputInterface $input, OutputInterface $output): void
90+
{
91+
$this->dumpMemoryLimit(self::CHILD_PROCESS_OUTPUT_DIR);
92+
}
93+
94+
private function dumpMemoryLimit(string $filePath): void
9195
{
9296
$this->filesystem->dumpFile(
93-
self::OUTPUT_DIR,
94-
ini_get('memory_limit'),
97+
$filePath,
98+
sprintf(
99+
'memory_limit=%s%smax_input_time=%s',
100+
ini_get('memory_limit'),
101+
"\n",
102+
ini_get('max_input_time'),
103+
),
95104
);
96105
}
97106

98-
protected function getItemName(?int $count): string
107+
public static function createSettingsOutput(string $memoryLimit, string $maxInputTime): string
99108
{
100-
return 1 === $count ? 'item' : 'items';
109+
return sprintf(
110+
'memory_limit=%s%smax_input_time=%s',
111+
$memoryLimit,
112+
"\n",
113+
$maxInputTime,
114+
);
101115
}
102116

103-
protected function createLogger(InputInterface $input, OutputInterface $output): Logger
117+
protected function getItemName(?int $count): string
104118
{
105-
return new NullLogger();
119+
return 1 === $count ? 'item' : 'items';
106120
}
107121
}

tests/Integration/PhpProcessSettingsTest.php

Lines changed: 78 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
use Symfony\Bundle\FrameworkBundle\Console\Application;
1919
use Symfony\Component\Console\Output\OutputInterface;
2020
use Symfony\Component\Console\Tester\CommandTester;
21+
use Symfony\Component\Filesystem\Filesystem;
2122
use Symfony\Component\Process\Process;
2223
use Webmozarts\Console\Parallelization\Fixtures\Command\ImportMoviesCommand;
2324
use Webmozarts\Console\Parallelization\Fixtures\Command\ImportUnknownMoviesCountCommand;
@@ -30,6 +31,7 @@
3031
use function array_column;
3132
use function array_map;
3233
use function file_get_contents;
34+
use function ini_get;
3335
use function preg_replace;
3436
use function spl_object_id;
3537
use function str_replace;
@@ -40,29 +42,96 @@
4042
#[CoversNothing]
4143
class PhpProcessSettingsTest extends TestCase
4244
{
43-
public function test_it_can_run_the_command_without_sub_processes(): void
45+
protected function setUp(): void
46+
{
47+
self::cleanupOutputFiles();
48+
}
49+
50+
protected function tearDown(): void
51+
{
52+
self::cleanupOutputFiles();
53+
}
54+
55+
public function test_it_can_run_the_command_setting_the_memory_limit(): void
4456
{
4557
$commandProcess = Process::fromShellCommandline(
4658
'php -dmemory_limit="256M" bin/console test:php-settings',
4759
__DIR__.'/../..',
60+
['XDEBUG_SESSION' => '1', 'XDEBUG_MODE' => 'debug'],
4861
);
4962
$commandProcess->run();
5063

51-
$expectedMainProcessMemoryLimit = '256M';
52-
$actualMainProcessMemoryLimit = file_get_contents(PhpSettingsCommand::OUTPUT_DIR.'_main_process');
64+
self::assertTrue(
65+
$commandProcess->isSuccessful(),
66+
$commandProcess->getOutput() . $commandProcess->getErrorOutput(),
67+
);
5368

54-
$expectedChildProcessMemoryLimit = '256M';
55-
$actualChildProcessMemoryLimit = file_get_contents(PhpSettingsCommand::OUTPUT_DIR);
69+
$expectedMainProcessPhpSettings = PhpSettingsCommand::createSettingsOutput(
70+
'256M', // comes from setting it when launching the command
71+
ini_get('max_input_time'),
72+
);
73+
$actualMainProcessPhpSettings = file_get_contents(PhpSettingsCommand::MAIN_PROCESS_OUTPUT_DIR);
74+
75+
$expectedChildProcessPhpSettings = PhpSettingsCommand::createSettingsOutput(
76+
'256M',
77+
'30', // comes from PhpSettingsCommand specifying it in the config
78+
);
79+
$actualChildProcessPhpSettings = file_get_contents(PhpSettingsCommand::CHILD_PROCESS_OUTPUT_DIR);
5680

5781
self::assertSame(
5882
[
59-
$expectedMainProcessMemoryLimit,
60-
$expectedChildProcessMemoryLimit,
83+
'main' => $expectedMainProcessPhpSettings,
84+
'child' => $expectedChildProcessPhpSettings,
6185
],
6286
[
63-
$actualMainProcessMemoryLimit,
64-
$actualChildProcessMemoryLimit,
87+
'main' => $actualMainProcessPhpSettings,
88+
'child' => $actualChildProcessPhpSettings,
6589
],
6690
);
6791
}
92+
93+
public function test_it_can_run_the_command_setting_the_a_php_setting_configured_in_the_command(): void
94+
{
95+
$commandProcess = Process::fromShellCommandline(
96+
'php -dmemory_limit="256M" -dmax_input_time=45 bin/console test:php-settings',
97+
__DIR__.'/../..',
98+
['XDEBUG_SESSION' => '1', 'XDEBUG_MODE' => 'debug'],
99+
);
100+
$commandProcess->run();
101+
102+
self::assertTrue(
103+
$commandProcess->isSuccessful(),
104+
$commandProcess->getOutput() . $commandProcess->getErrorOutput(),
105+
);
106+
107+
$expectedMainProcessPhpSettings = PhpSettingsCommand::createSettingsOutput(
108+
'256M', // comes from setting it when launching the command
109+
'45', // comes from setting it when launching the command
110+
);
111+
$actualMainProcessPhpSettings = file_get_contents(PhpSettingsCommand::MAIN_PROCESS_OUTPUT_DIR);
112+
113+
$expectedChildProcessPhpSettings = PhpSettingsCommand::createSettingsOutput(
114+
'256M',
115+
'30', // comes from PhpSettingsCommand specifying it in the config
116+
);
117+
$actualChildProcessPhpSettings = file_get_contents(PhpSettingsCommand::CHILD_PROCESS_OUTPUT_DIR);
118+
119+
self::assertSame(
120+
[
121+
'main' => $expectedMainProcessPhpSettings,
122+
'child' => $expectedChildProcessPhpSettings,
123+
],
124+
[
125+
'main' => $actualMainProcessPhpSettings,
126+
'child' => $actualChildProcessPhpSettings,
127+
],
128+
);
129+
}
130+
131+
private static function cleanupOutputFiles(): void
132+
{
133+
$fileSystem = new Filesystem();
134+
$fileSystem->remove(PhpSettingsCommand::MAIN_PROCESS_OUTPUT_DIR);
135+
$fileSystem->remove(PhpSettingsCommand::CHILD_PROCESS_OUTPUT_DIR);
136+
}
68137
}

0 commit comments

Comments
 (0)