Skip to content

Commit

Permalink
The child processes used for process isolation now use temporary file…
Browse files Browse the repository at this point in the history
…s to communicate their result to the parent process

As of PHP 8.3, specifically as of php/php-src#11169,
it is no longer possible to capture direct writes to standard output.

Such direct writes to standard output interfere with the previous approach
where the child process would print its result to standard output from where
the parent process would read it.

Co-authored-by: Sebastian Bergmann <sb@sebastian-bergmann.de>
Co-authored-by: Arne Blankerts <Arne@Blankerts.de>
  • Loading branch information
sebastianbergmann and theseer committed Sep 16, 2023
1 parent 33bbe51 commit 3291172
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 18 deletions.
7 changes: 7 additions & 0 deletions ChangeLog-8.5.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

All notable changes of the PHPUnit 8.5 release series are documented in this file using the [Keep a CHANGELOG](https://keepachangelog.com/) principles.

## [8.5.34] - 2023-MM-DD

### Changed

* The child processes used for process isolation now use temporary files to communicate their result to the parent process

## [8.5.33] - 2023-02-27

### Fixed
Expand Down Expand Up @@ -268,6 +274,7 @@ All notable changes of the PHPUnit 8.5 release series are documented in this fil
* [#3967](https://github.com/sebastianbergmann/phpunit/issues/3967): Cannot double interface that extends interface that extends `\Throwable`
* [#3968](https://github.com/sebastianbergmann/phpunit/pull/3968): Test class run in a separate PHP process are passing when `exit` called inside

[8.5.34]: https://github.com/sebastianbergmann/phpunit/compare/8.5.33...8.5
[8.5.33]: https://github.com/sebastianbergmann/phpunit/compare/8.5.32...8.5.33
[8.5.32]: https://github.com/sebastianbergmann/phpunit/compare/8.5.31...8.5.32
[8.5.31]: https://github.com/sebastianbergmann/phpunit/compare/8.5.30...8.5.31
Expand Down
6 changes: 5 additions & 1 deletion src/Framework/TestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@
use function strlen;
use function strpos;
use function substr;
use function sys_get_temp_dir;
use function tempnam;
use function trim;
use function var_export;
use DeepCopy\DeepCopy;
Expand Down Expand Up @@ -801,6 +803,7 @@ public function run(TestResult $result = null): TestResult
$codeCoverageFilter = "'." . $codeCoverageFilter . ".'";

$configurationFilePath = $GLOBALS['__PHPUNIT_CONFIGURATION_FILE'] ?? '';
$processResultFile = tempnam(sys_get_temp_dir(), 'phpunit_');

$var = [
'composerAutoload' => $composerAutoload,
Expand All @@ -824,6 +827,7 @@ public function run(TestResult $result = null): TestResult
'codeCoverageFilter' => $codeCoverageFilter,
'configurationFilePath' => $configurationFilePath,
'name' => $this->getName(false),
'processResultFile' => $processResultFile,
];

if (!$runEntireClass) {
Expand All @@ -833,7 +837,7 @@ public function run(TestResult $result = null): TestResult
$template->setVar($var);

$php = AbstractPhpProcess::factory();
$php->runTestJob($template->render(), $this, $result);
$php->runTestJob($template->render(), $this, $result, $processResultFile);
} else {
$result->run($this);
}
Expand Down
16 changes: 13 additions & 3 deletions src/Util/PHP/AbstractPhpProcess.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
use function array_merge;
use function assert;
use function escapeshellarg;
use function file_exists;
use function file_get_contents;
use function ini_get_all;
use function restore_error_handler;
use function set_error_handler;
Expand All @@ -24,6 +26,7 @@
use function strrpos;
use function substr;
use function trim;
use function unlink;
use function unserialize;
use __PHP_Incomplete_Class;
use ErrorException;
Expand Down Expand Up @@ -174,16 +177,23 @@ public function getTimeout(): int
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
*/
public function runTestJob(string $job, Test $test, TestResult $result): void
public function runTestJob(string $job, Test $test, TestResult $result, string $processResultFile): void
{
$result->startTest($test);

$_result = $this->runJob($job);
$processResult = '';
$_result = $this->runJob($job);

if (file_exists($processResultFile)) {
$processResult = file_get_contents($processResultFile);

@unlink($processResultFile);
}

$this->processChildResult(
$test,
$result,
$_result['stdout'],
$processResult,
$_result['stderr']
);
}
Expand Down
17 changes: 10 additions & 7 deletions src/Util/PHP/Template/TestCaseClass.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -70,13 +70,16 @@ function __phpunit_run_isolated_test()
}
}

print serialize(
[
'testResult' => $test->getResult(),
'numAssertions' => $test->getNumAssertions(),
'result' => $result,
'output' => $output
]
file_put_contents(
'{processResultFile}',
serialize(
[
'testResult' => $test->getResult(),
'numAssertions' => $test->getNumAssertions(),
'result' => $result,
'output' => $output
]
)
);
}

Expand Down
17 changes: 10 additions & 7 deletions src/Util/PHP/Template/TestCaseMethod.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -73,13 +73,16 @@ function __phpunit_run_isolated_test()
}
}

print serialize(
[
'testResult' => $test->getResult(),
'numAssertions' => $test->getNumAssertions(),
'result' => $result,
'output' => $output
]
file_put_contents(
'{processResultFile}',
serialize(
[
'testResult' => $test->getResult(),
'numAssertions' => $test->getNumAssertions(),
'result' => $result,
'output' => $output
]
)
);
}

Expand Down

0 comments on commit 3291172

Please sign in to comment.