Skip to content

Commit 9bd951d

Browse files
authored
Fix exit code can exceed 255 (#203)
Closes #185
1 parent 7c29eb3 commit 9bd951d

5 files changed

+53
-7
lines changed

infection.json5

+4-2
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,14 @@
3838
"DecrementInteger": {
3939
"ignoreSourceCodeByRegex": [
4040
".*\\$numberOfStreamedItems = .*",
41-
".*\\$numberOfItems \\?\\? 0.*"
41+
".*\\$numberOfItems \\?\\? 0.*",
42+
".*return min\\(\\$exitCode, 255\\);.*"
4243
]
4344
},
4445
"IncrementInteger": {
4546
"ignoreSourceCodeByRegex": [
46-
".*\\$numberOfItems \\?\\? 0.*"
47+
".*\\$numberOfItems \\?\\? 0.*",
48+
".*return min\\(\\$exitCode, 255\\);.*"
4749
]
4850
},
4951
"MBString": false,

src/ParallelExecutor.php

+4-3
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
use Webmozarts\Console\Parallelization\Process\ProcessLauncher;
2626
use Webmozarts\Console\Parallelization\Process\ProcessLauncherFactory;
2727
use function mb_strlen;
28+
use function min;
2829
use function sprintf;
2930

3031
final class ParallelExecutor
@@ -193,7 +194,7 @@ public function execute(
193194
* items of the processed data set and terminates. As long as there is data
194195
* left to process, new child processes are spawned automatically.
195196
*
196-
* @return 0|positive-int
197+
* @return int<0,255>
197198
*/
198199
private function executeMainProcess(
199200
ParallelizationInput $parallelizationInput,
@@ -298,7 +299,7 @@ private function executeChildProcess(
298299
/**
299300
* @param callable():void $advance
300301
*
301-
* @return 0|positive-int
302+
* @return int<0,255>
302303
*/
303304
private function processItems(
304305
ChunkedItemsIterator $itemIterator,
@@ -321,7 +322,7 @@ private function processItems(
321322
($this->runAfterBatch)($input, $output, $items);
322323
}
323324

324-
return $exitCode;
325+
return min($exitCode, 255);
325326
}
326327

327328
/**

src/Process/ProcessLauncher.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ interface ProcessLauncher
2323
* @param list<string>|Iterator<string> $items The items to process. None of the items must
2424
* contain newlines
2525
*
26-
* @return 0|positive-int
26+
* @return int<0,255>
2727
*/
2828
public function run(iterable $items): int;
2929
}

src/Process/SymfonyProcessLauncher.php

+2-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
use Webmozart\Assert\Assert;
1919
use Webmozarts\Console\Parallelization\Logger\Logger;
2020
use function count;
21+
use function min;
2122
use function sprintf;
2223
use const PHP_EOL;
2324

@@ -157,7 +158,7 @@ public function run(iterable $items): int
157158
($this->tick)();
158159
}
159160

160-
return $exitCode;
161+
return min($exitCode, 255);
161162
}
162163

163164
private function startProcess(InputStream $inputStream): void

tests/Process/SymfonyProcessLauncherTest.php

+42
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,11 @@
1414
namespace Webmozarts\Console\Parallelization\Process;
1515

1616
use PHPUnit\Framework\TestCase;
17+
use Prophecy\Argument;
18+
use Prophecy\PhpUnit\ProphecyTrait;
1719
use Symfony\Component\Console\Output\BufferedOutput;
1820
use Symfony\Component\Console\Output\OutputInterface;
21+
use Symfony\Component\Process\Process;
1922
use Webmozarts\Console\Parallelization\FakeCallable;
2023
use Webmozarts\Console\Parallelization\Logger\DummyLogger;
2124
use Webmozarts\Console\Parallelization\Logger\FakeLogger;
@@ -31,6 +34,8 @@
3134
*/
3235
final class SymfonyProcessLauncherTest extends TestCase
3336
{
37+
use ProphecyTrait;
38+
3439
public function test_it_does_nothing_if_there_is_no_items(): void
3540
{
3641
$launcher = new SymfonyProcessLauncher(
@@ -268,6 +273,43 @@ public static function inputProvider(): iterable
268273
];
269274
}
270275

276+
public function test_it_caps_the_exit_code_to_255(): void
277+
{
278+
$output = new BufferedOutput();
279+
280+
$processProphecy = $this->prophesize(Process::class);
281+
$processProphecy->getPid()->willReturn(10);
282+
$processProphecy->getCommandLine()->willReturn('');
283+
$processProphecy->isRunning()->willReturn(false);
284+
$processProphecy->getExitCode()->willReturn(500);
285+
286+
$processFactoryProphecy = $this->prophesize(SymfonyProcessFactory::class);
287+
$processFactoryProphecy
288+
->startProcess(Argument::cetera())
289+
->willReturn($processProphecy->reveal());
290+
291+
$processOutput = self::createProcessOutput($output);
292+
$numberOfTicksRecorded = 0;
293+
294+
$launcher = new SymfonyProcessLauncher(
295+
[],
296+
'',
297+
null,
298+
1,
299+
1,
300+
new DummyLogger(),
301+
$processOutput,
302+
static function () use (&$numberOfTicksRecorded): void {
303+
++$numberOfTicksRecorded;
304+
},
305+
$processFactoryProphecy->reveal(),
306+
);
307+
308+
$exitCode = $launcher->run(['item0']);
309+
310+
self::assertSame(255, $exitCode);
311+
}
312+
271313
/**
272314
* @return ProcessOutput
273315
*/

0 commit comments

Comments
 (0)