Files
xxx/tests/php/Support/PhpProcess.php
T
tim ed959888b4 Add PHP unit tests and page tests.
Run "composer install", then "composer test".
2026-09-26 03:48:09 +02:00

47 lines
2.2 KiB
PHP

<?php
namespace Xxx\Tests\Support;
/*
* Run PHP code in a new process, after tests/php/bootstrap.php. This is
* for code that ends the script (die, exit) or that needs php.ini
* settings which cannot change at run time, such as sendmail_path.
*/
class PhpProcess {
/*
* Returns array('status' => exit code, 'stdout' => ..., 'stderr' => ...,
* 'log' => what the code wrote to the PHP error log).
*/
public static function run(string $code, array $env = array(), array $ini = array()): array {
// One line, so that line numbers in $code stay the same; the code runs
// in publish/, as the unit tests do
return self::runPlain("require " . var_export(XXX_ROOT . '/tests/php/bootstrap.php', TRUE) . "; chdir(XXX_ROOT . '/publish');\n" . $code, $env, $ini);
}
// The same with only the test environment, for code that includes a site library itself
public static function runBare(string $code, array $env = array(), array $ini = array()): array {
return self::runPlain("require " . var_export(XXX_ROOT . '/tests/php/environment.php', TRUE) . ";\n" . $code, $env, $ini);
}
// The same without the bootstrap: the code loads what it needs itself
public static function runPlain(string $code, array $env = array(), array $ini = array()): array {
$script = tempnam(sys_get_temp_dir(), 'xxx-php-');
$log = $script . '.log';
file_put_contents($script, "<?php\n" . $code);
$command = array(PHP_BINARY, '-d', 'display_errors=stderr', '-d', 'error_reporting=-1', '-d', "error_log=$log");
foreach ($ini as $name => $value)
array_push($command, '-d', "$name=$value");
$command[] = $script;
$env = array_merge(getenv(), array('XXX_TEST_LOG' => $log), $env);
$process = proc_open($command, array(1 => array('pipe', 'w'), 2 => array('pipe', 'w')), $pipes, XXX_ROOT, $env);
$stdout = stream_get_contents($pipes[1]);
$stderr = stream_get_contents($pipes[2]);
fclose($pipes[1]);
fclose($pipes[2]);
$status = proc_close($process);
$logged = is_file($log) ? file_get_contents($log) : '';
@unlink($script);
@unlink($log);
return array('status' => $status, 'stdout' => $stdout, 'stderr' => $stderr, 'log' => $logged);
}
}