Вход Регистрация
Файл: vendor/phpunit/phpunit/src/Util/PHP/DefaultPhpProcess.php
Строк: 188
<?php declare(strict_types=1);
/*
 * This file is part of PHPUnit.
 *
 * (c) Sebastian Bergmann <sebastian@phpunit.de>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PHPUnitUtilPHP;

use function 
array_merge;
use function 
fclose;
use function 
file_put_contents;
use function 
fread;
use function 
fwrite;
use function 
is_array;
use function 
is_resource;
use function 
proc_close;
use function 
proc_open;
use function 
proc_terminate;
use function 
rewind;
use function 
sprintf;
use function 
stream_get_contents;
use function 
stream_select;
use function 
sys_get_temp_dir;
use function 
tempnam;
use function 
unlink;
use 
PHPUnitFrameworkException;

/**
 * @internal This class is not covered by the backward compatibility promise for PHPUnit
 */
class DefaultPhpProcess extends AbstractPhpProcess
{
    
/**
     * @var string
     */
    
protected $tempFile;

    
/**
     * Runs a single job (PHP code) using a separate PHP process.
     *
     * @throws Exception
     */
    
public function runJob(string $job, array $settings = []): array
    {
        if (
$this->stdin || $this->useTemporaryFile()) {
            if (!(
$this->tempFile tempnam(sys_get_temp_dir(), 'PHPUnit')) ||
                
file_put_contents($this->tempFile$job) === false) {
                throw new 
Exception(
                    
'Unable to write temporary file'
                
);
            }

            
$job $this->stdin;
        }

        return 
$this->runProcess($job$settings);
    }

    
/**
     * Returns an array of file handles to be used in place of pipes.
     */
    
protected function getHandles(): array
    {
        return [];
    }

    
/**
     * Handles creating the child process and returning the STDOUT and STDERR.
     *
     * @throws Exception
     */
    
protected function runProcess(string $job, array $settings): array
    {
        
$handles $this->getHandles();

        
$env null;

        if (
$this->env) {
            
$env $_SERVER ?? [];
            unset(
$env['argv'], $env['argc']);
            
$env array_merge($env$this->env);

            foreach (
$env as $envKey => $envVar) {
                if (
is_array($envVar)) {
                    unset(
$env[$envKey]);
                }
            }
        }

        
$pipeSpec = [
            
=> $handles[0] ?? ['pipe''r'],
            
=> $handles[1] ?? ['pipe''w'],
            
=> $handles[2] ?? ['pipe''w'],
        ];

        
$process proc_open(
            
$this->getCommand($settings$this->tempFile),
            
$pipeSpec,
            
$pipes,
            
null,
            
$env
        
);

        if (!
is_resource($process)) {
            throw new 
Exception(
                
'Unable to spawn worker process'
            
);
        }

        if (
$job) {
            
$this->process($pipes[0], $job);
        }

        
fclose($pipes[0]);

        
$stderr $stdout '';

        if (
$this->timeout) {
            unset(
$pipes[0]);

            while (
true) {
                
$r $pipes;
                
$w null;
                
$e null;

                
$n = @stream_select($r$w$e$this->timeout);

                if (
$n === false) {
                    break;
                }

                if (
$n === 0) {
                    
proc_terminate($process9);

                    throw new 
Exception(
                        
sprintf(
                            
'Job execution aborted after %d seconds',
                            
$this->timeout
                        
)
                    );
                }

                if (
$n 0) {
                    foreach (
$r as $pipe) {
                        
$pipeOffset 0;

                        foreach (
$pipes as $i => $origPipe) {
                            if (
$pipe === $origPipe) {
                                
$pipeOffset $i;

                                break;
                            }
                        }

                        if (!
$pipeOffset) {
                            break;
                        }

                        
$line fread($pipe8192);

                        if (
$line === '' || $line === false) {
                            
fclose($pipes[$pipeOffset]);

                            unset(
$pipes[$pipeOffset]);
                        } elseif (
$pipeOffset === 1) {
                            
$stdout .= $line;
                        } else {
                            
$stderr .= $line;
                        }
                    }

                    if (empty(
$pipes)) {
                        break;
                    }
                }
            }
        } else {
            if (isset(
$pipes[1])) {
                
$stdout stream_get_contents($pipes[1]);

                
fclose($pipes[1]);
            }

            if (isset(
$pipes[2])) {
                
$stderr stream_get_contents($pipes[2]);

                
fclose($pipes[2]);
            }
        }

        if (isset(
$handles[1])) {
            
rewind($handles[1]);

            
$stdout stream_get_contents($handles[1]);

            
fclose($handles[1]);
        }

        if (isset(
$handles[2])) {
            
rewind($handles[2]);

            
$stderr stream_get_contents($handles[2]);

            
fclose($handles[2]);
        }

        
proc_close($process);

        
$this->cleanup();

        return [
'stdout' => $stdout'stderr' => $stderr];
    }

    
/**
     * @param resource $pipe
     */
    
protected function process($pipestring $job): void
    
{
        
fwrite($pipe$job);
    }

    protected function 
cleanup(): void
    
{
        if (
$this->tempFile) {
            
unlink($this->tempFile);
        }
    }

    protected function 
useTemporaryFile(): bool
    
{
        return 
false;
    }
}
Онлайн: 0
Реклама