diff --git a/composer.json b/composer.json index ad50b25..fba70b8 100644 --- a/composer.json +++ b/composer.json @@ -29,11 +29,11 @@ "php": ">=5.3.0", "evenement/evenement": "^3.0 || ^2.0 || ^1.0", "react/event-loop": "^1.2", - "react/stream": "^1.2" + "react/stream": "^1.4" }, "require-dev": { "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36", - "react/socket": "^1.8", + "react/socket": "^1.16", "sebastian/environment": "^5.0 || ^3.0 || ^2.0 || ^1.0" }, "autoload": { diff --git a/src/Process.php b/src/Process.php index d947039..406e417 100644 --- a/src/Process.php +++ b/src/Process.php @@ -103,8 +103,14 @@ class Process extends EventEmitter * @param null|array $fds File descriptors to allocate for this process (or null = default STDIO streams) * @throws \LogicException On windows or when proc_open() is not installed */ - public function __construct($cmd, $cwd = null, array $env = null, array $fds = null) + public function __construct($cmd, $cwd = null, $env = null, $fds = null) { + if ($env !== null && !\is_array($env)) { // manual type check to support legacy PHP < 7.1 + throw new \InvalidArgumentException('Argument #3 ($env) expected null|array'); + } + if ($fds !== null && !\is_array($fds)) { // manual type check to support legacy PHP < 7.1 + throw new \InvalidArgumentException('Argument #4 ($fds) expected null|array'); + } if (!\function_exists('proc_open')) { throw new \LogicException('The Process class relies on proc_open(), which is not available on your PHP installation.'); } @@ -154,8 +160,11 @@ public function __construct($cmd, $cwd = null, array $env = null, array $fds = n * @param float $interval Interval to periodically monitor process state (seconds) * @throws \RuntimeException If the process is already running or fails to start */ - public function start(LoopInterface $loop = null, $interval = 0.1) + public function start($loop = null, $interval = 0.1) { + if ($loop !== null && !$loop instanceof LoopInterface) { // manual type check to support legacy PHP < 7.1 + throw new \InvalidArgumentException('Argument #1 ($loop) expected null|React\EventLoop\LoopInterface'); + } if ($this->isRunning()) { throw new \RuntimeException('Process is already running'); } diff --git a/tests/AbstractProcessTest.php b/tests/AbstractProcessTest.php index 606336f..4a81d0b 100644 --- a/tests/AbstractProcessTest.php +++ b/tests/AbstractProcessTest.php @@ -11,6 +11,18 @@ abstract class AbstractProcessTest extends TestCase { abstract public function createLoop(); + public function testCtorThrowsForInvalidEnv() + { + $this->setExpectedException('InvalidArgumentException', 'Argument #3 ($env) expected null|array'); + new Process('exit 0', null, 'env'); + } + + public function testCtorThrowsForInvalidFds() + { + $this->setExpectedException('InvalidArgumentException', 'Argument #4 ($fds) expected null|array'); + new Process('exit 0', null, null, 'fds'); + } + public function testGetCommand() { $process = new Process('echo foo', null, null, array()); @@ -126,6 +138,14 @@ public function testStartWithCustomPipesWillAssignPipes() $this->assertInstanceOf('React\Stream\WritableStreamInterface', $process->pipes[3]); } + public function testStartWithInvalidLoopWillThrow() + { + $process = new Process('exit 0', null, null, array()); + + $this->setExpectedException('InvalidArgumentException', 'Argument #1 ($loop) expected null|React\EventLoop\LoopInterface'); + $process->start('loop'); + } + public function testStartWithInvalidFileDescriptorPathWillThrowWithoutCallingCustomErrorHandler() { if (defined('HHVM_VERSION')) {