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(); } }