Viewing file: WrapperWorker.php (6.64 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
<?php
declare(strict_types=1);
namespace ParaTest\WrapperRunner;
use ParaTest\Options; use SplFileInfo; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Process\InputStream; use Symfony\Component\Process\Process; use Throwable;
use function array_map; use function assert; use function clearstatcache; use function file_get_contents; use function filesize; use function implode; use function is_string; use function serialize; use function sprintf; use function touch; use function uniqid;
use const DIRECTORY_SEPARATOR;
/** @internal */ final class WrapperWorker { public const COMMAND_EXIT = "EXIT\n";
public readonly SplFileInfo $statusFile; public readonly SplFileInfo $progressFile; public readonly SplFileInfo $unexpectedOutputFile; public readonly SplFileInfo $testresultFile; public readonly SplFileInfo $junitFile; public readonly SplFileInfo $coverageFile; public readonly SplFileInfo $teamcityFile;
public readonly SplFileInfo $testdoxFile; private ?string $currentlyExecuting = null; private Process $process; private int $inExecution = 0; private InputStream $input; private int $exitCode = -1;
/** @param non-empty-string[] $parameters */ public function __construct( private readonly OutputInterface $output, private readonly Options $options, array $parameters, private readonly int $token ) { $commonTmpFilePath = sprintf( '%s%sworker_%02s_stdout_%s_', $options->tmpDir, DIRECTORY_SEPARATOR, $token, uniqid(), ); $this->statusFile = new SplFileInfo($commonTmpFilePath . 'status'); touch($this->statusFile->getPathname()); $this->progressFile = new SplFileInfo($commonTmpFilePath . 'progress'); touch($this->progressFile->getPathname()); $this->unexpectedOutputFile = new SplFileInfo($commonTmpFilePath . 'unexpected_output'); touch($this->unexpectedOutputFile->getPathname()); $this->testresultFile = new SplFileInfo($commonTmpFilePath . 'testresult'); if ($options->configuration->hasLogfileJunit()) { $this->junitFile = new SplFileInfo($commonTmpFilePath . 'junit'); }
if ($options->configuration->hasCoverageReport()) { $this->coverageFile = new SplFileInfo($commonTmpFilePath . 'coverage'); }
if ($options->needsTeamcity) { $this->teamcityFile = new SplFileInfo($commonTmpFilePath . 'teamcity'); }
if ($options->configuration->outputIsTestDox()) { $this->testdoxFile = new SplFileInfo($commonTmpFilePath . 'testdox'); }
$parameters[] = '--status-file'; $parameters[] = $this->statusFile->getPathname(); $parameters[] = '--progress-file'; $parameters[] = $this->progressFile->getPathname(); $parameters[] = '--unexpected-output-file'; $parameters[] = $this->unexpectedOutputFile->getPathname(); $parameters[] = '--testresult-file'; $parameters[] = $this->testresultFile->getPathname(); if (isset($this->teamcityFile)) { $parameters[] = '--teamcity-file'; $parameters[] = $this->teamcityFile->getPathname(); }
if (isset($this->testdoxFile)) { $parameters[] = '--testdox-file'; $parameters[] = $this->testdoxFile->getPathname(); if ($options->configuration->colors()) { $parameters[] = '--testdox-color'; }
$parameters[] = '--testdox-columns'; $parameters[] = (string) $options->configuration->columns(); }
$phpunitArguments = [$options->phpunit]; foreach ($options->phpunitOptions as $key => $value) { if ($options->functional && $key === 'filter') { continue; }
$phpunitArguments[] = "--{$key}"; if ($value === true) { continue; }
$phpunitArguments[] = $value; }
$phpunitArguments[] = '--do-not-cache-result'; $phpunitArguments[] = '--no-logging'; $phpunitArguments[] = '--no-coverage'; $phpunitArguments[] = '--no-output'; if (isset($this->junitFile)) { $phpunitArguments[] = '--log-junit'; $phpunitArguments[] = $this->junitFile->getPathname(); }
if (isset($this->coverageFile)) { $phpunitArguments[] = '--coverage-php'; $phpunitArguments[] = $this->coverageFile->getPathname(); }
$parameters[] = '--phpunit-argv'; $parameters[] = serialize($phpunitArguments);
if ($options->verbose) { $output->write(sprintf( "Starting process {$this->token}: %s\n", implode(' ', array_map('\\escapeshellarg', $parameters)), )); }
$this->input = new InputStream(); $this->process = new Process( $parameters, $options->cwd, $options->fillEnvWithTokens($token), $this->input, null, ); }
public function start(): void { $this->process->start(); }
public function getWorkerCrashedException(?Throwable $previousException = null): WorkerCrashedException { return WorkerCrashedException::fromProcess( $this->process, $this->currentlyExecuting ?? 'N.A.', $previousException, ); }
public function assign(string $test): void { assert($this->currentlyExecuting === null);
if ($this->options->verbose) { $this->output->write("Process {$this->token} executing: {$test}\n"); }
$this->input->write($test . "\n"); $this->currentlyExecuting = $test; ++$this->inExecution; }
public function reset(): void { $this->currentlyExecuting = null; }
public function stop(): void { $this->input->write(self::COMMAND_EXIT); }
public function isFree(): bool { $statusFilepath = $this->statusFile->getPathname(); clearstatcache(true, $statusFilepath);
$isFree = $this->inExecution === filesize($statusFilepath);
if ($isFree && $this->inExecution > 0) { $exitCodes = file_get_contents($statusFilepath); assert(is_string($exitCodes) && $exitCodes !== ''); $this->exitCode = (int) $exitCodes[-1]; }
return $isFree; }
public function getExitCode(): int { return $this->exitCode; }
public function isRunning(): bool { return $this->process->isRunning(); } }
|