1
0
mirror of https://github.com/danog/process.git synced 2024-12-04 10:38:04 +01:00
process/test/ProcessTest.php

337 lines
10 KiB
PHP
Raw Normal View History

<?php
2017-12-03 04:16:52 +01:00
namespace Amp\Process\Test;
2017-12-10 22:17:04 +01:00
use Amp\ByteStream\Message;
use Amp\Delayed;
use Amp\Loop;
use Amp\Process\Process;
2017-12-05 06:02:41 +01:00
use Amp\Process\ProcessInputStream;
use Amp\Process\ProcessOutputStream;
2017-12-05 22:53:41 +01:00
use Amp\Promise;
2017-06-16 05:53:33 +02:00
use PHPUnit\Framework\TestCase;
2017-06-16 05:53:33 +02:00
class ProcessTest extends TestCase {
const CMD_PROCESS = \DIRECTORY_SEPARATOR === "\\" ? "cmd /c echo foo" : "echo foo";
2017-12-05 22:53:41 +01:00
const CMD_PROCESS_SLOW = \DIRECTORY_SEPARATOR === "\\" ? "cmd /c ping -n 3 127.0.0.1 > nul" : "sleep 2";
/**
* @expectedException \Amp\Process\StatusError
*/
public function testMultipleExecution() {
2017-06-15 19:11:38 +02:00
Loop::run(function () {
$process = new Process(self::CMD_PROCESS);
$process->start();
$process->start();
});
}
2017-01-16 05:49:41 +01:00
public function testIsRunning() {
2017-06-15 19:11:38 +02:00
Loop::run(function () {
$process = new Process(\DIRECTORY_SEPARATOR === "\\" ? "cmd /c exit 42" : "exit 42");
$process->start();
$promise = $process->join();
2017-01-16 05:49:41 +01:00
$this->assertTrue($process->isRunning());
yield $promise;
$this->assertFalse($process->isRunning());
});
2017-01-16 05:49:41 +01:00
}
public function testExecuteResolvesToExitCode() {
2017-06-15 19:11:38 +02:00
Loop::run(function () {
$process = new Process(\DIRECTORY_SEPARATOR === "\\" ? "cmd /c exit 42" : "exit 42");
$process->start();
$code = yield $process->join();
$this->assertSame(42, $code);
2017-01-16 05:49:41 +01:00
$this->assertFalse($process->isRunning());
});
}
public function testCommandCanRun() {
2017-06-15 19:11:38 +02:00
Loop::run(function () {
$process = new Process(self::CMD_PROCESS);
$process->start();
$this->assertInternalType('int', yield $process->getPid());
$this->assertSame(0, yield $process->join());
});
}
2017-12-05 06:02:41 +01:00
public function testProcessCanTerminate() {
if (\DIRECTORY_SEPARATOR === "\\") {
$this->markTestSkipped("Signals are not supported on Windows");
}
2017-12-05 06:02:41 +01:00
Loop::run(function () {
2017-12-05 22:53:41 +01:00
$process = new Process(self::CMD_PROCESS_SLOW);
2017-12-05 06:02:41 +01:00
$process->start();
$process->signal(0);
2017-12-05 22:53:41 +01:00
$this->assertInstanceOf(Promise::class, $process->getPid());
$this->assertSame(0, yield $process->join());
2017-12-05 06:02:41 +01:00
});
}
public function testGetWorkingDirectoryIsDefault() {
Loop::run(function () {
$process = new Process(self::CMD_PROCESS);
$this->assertSame(getcwd(), $process->getWorkingDirectory());
});
}
public function testGetWorkingDirectoryIsCustomized() {
Loop::run(function () {
$process = new Process(self::CMD_PROCESS, __DIR__);
$this->assertSame(__DIR__, $process->getWorkingDirectory());
});
}
public function testGetEnv() {
Loop::run(function () {
2017-12-05 15:22:23 +01:00
$process = new Process(self::CMD_PROCESS);
2017-12-05 06:02:41 +01:00
$this->assertSame([], $process->getEnv());
});
}
2017-12-05 15:22:23 +01:00
public function testGetStdin() {
2017-12-05 06:02:41 +01:00
Loop::run(function () {
2017-12-05 15:22:23 +01:00
$process = new Process(self::CMD_PROCESS);
2017-12-05 06:02:41 +01:00
$process->start();
$this->assertInstanceOf(ProcessOutputStream::class, $process->getStdin());
2017-12-05 15:22:23 +01:00
yield $process->join();
2017-12-05 06:02:41 +01:00
});
}
2017-12-05 15:22:23 +01:00
public function testGetStdout() {
2017-12-05 06:02:41 +01:00
Loop::run(function () {
2017-12-05 15:22:23 +01:00
$process = new Process(self::CMD_PROCESS);
2017-12-05 06:02:41 +01:00
$process->start();
$this->assertInstanceOf(ProcessInputStream::class, $process->getStdout());
2017-12-05 15:22:23 +01:00
yield $process->join();
2017-12-05 06:02:41 +01:00
});
}
2017-12-05 15:22:23 +01:00
public function testGetStderr() {
2017-12-05 06:02:41 +01:00
Loop::run(function () {
2017-12-05 15:22:23 +01:00
$process = new Process(self::CMD_PROCESS);
2017-12-05 06:02:41 +01:00
$process->start();
$this->assertInstanceOf(ProcessInputStream::class, $process->getStderr());
2017-12-05 15:22:23 +01:00
yield $process->join();
2017-12-05 06:02:41 +01:00
});
}
public function testProcessEnvIsValid() {
2017-12-05 15:22:23 +01:00
Loop::run(function () {
$process = new Process(self::CMD_PROCESS, null, [
2017-12-05 22:41:30 +01:00
'test' => 'foobar',
'PATH' => \getenv('PATH'),
'SystemRoot' => \getenv('SystemRoot') ?: '', // required on Windows for process wrapper
2017-12-05 15:22:23 +01:00
]);
$process->start();
2017-12-05 22:41:30 +01:00
$this->assertSame('foobar', $process->getEnv()['test']);
2017-12-05 15:22:23 +01:00
yield $process->join();
});
2017-12-05 06:02:41 +01:00
}
/**
* @expectedException \Error
*/
public function testProcessEnvIsInvalid() {
$process = new Process(self::CMD_PROCESS, null, [
['error_value']
]);
}
/**
* @expectedException \Amp\Process\StatusError
* @expectedExceptionMessage Process has not been started.
*/
public function testGetStdinIsStatusError() {
$process = new Process(self::CMD_PROCESS, null, []);
$process->getStdin();
}
/**
* @expectedException \Amp\Process\StatusError
* @expectedExceptionMessage Process has not been started.
*/
public function testGetStdoutIsStatusError() {
$process = new Process(self::CMD_PROCESS, null, []);
$process->getStdout();
}
/**
* @expectedException \Amp\Process\StatusError
* @expectedExceptionMessage Process has not been started.
*/
public function testGetStderrIsStatusError() {
$process = new Process(self::CMD_PROCESS, null, []);
$process->getStderr();
}
/**
* @expectedException \Error
* @expectedExceptionMessage Cloning is not allowed!
*/
2017-12-05 22:53:41 +01:00
public function testProcessCantBeCloned() {
2017-12-05 06:02:41 +01:00
$process = new Process(self::CMD_PROCESS);
2017-12-05 22:53:41 +01:00
clone $process;
2017-12-05 06:02:41 +01:00
}
/**
* @expectedException \Amp\Process\ProcessException
* @expectedExceptionMessage The process was killed
*/
public function testKillImmediately() {
2017-06-15 19:11:38 +02:00
Loop::run(function () {
2017-12-05 22:53:41 +01:00
$process = new Process(self::CMD_PROCESS_SLOW);
$process->start();
$process->kill();
yield $process->join();
});
}
/**
* @expectedException \Amp\Process\ProcessException
* @expectedExceptionMessage The process was killed
*/
public function testKillThenReadStdout() {
Loop::run(function () {
$process = new Process(self::CMD_PROCESS_SLOW);
$process->start();
yield new Delayed(100); // Give process a chance to start, otherwise a different error is thrown.
$process->kill();
$this->assertNull(yield $process->getStdout()->read());
2017-12-05 22:53:41 +01:00
yield $process->join();
});
}
2017-12-05 06:02:41 +01:00
/**
* @expectedException \Amp\Process\StatusError
* @expectedExceptionMessage Process has not been started.
*/
public function testProcessHasNotBeenStartedWithJoin() {
Loop::run(function () {
$process = new Process(self::CMD_PROCESS);
2017-12-05 22:53:41 +01:00
yield $process->join();
2017-12-05 06:02:41 +01:00
});
}
/**
* @expectedException \Amp\Process\StatusError
* @expectedExceptionMessage Process has not been started.
*/
public function testProcessHasNotBeenStartedWithGetPid() {
Loop::run(function () {
$process = new Process(self::CMD_PROCESS);
2017-12-05 22:53:41 +01:00
yield $process->getPid();
2017-12-05 06:02:41 +01:00
});
}
/**
* @expectedException \Amp\Process\StatusError
* @expectedExceptionMessage Process is not running.
*/
public function testProcessIsNotRunningWithKill() {
Loop::run(function () {
$process = new Process(self::CMD_PROCESS);
$process->kill();
});
}
/**
* @expectedException \Amp\Process\StatusError
* @expectedExceptionMessage Process is not running.
*/
public function testProcessIsNotRunningWithSignal() {
Loop::run(function () {
$process = new Process(self::CMD_PROCESS);
$process->signal(0);
});
}
/**
* @expectedException \Amp\Process\StatusError
* @expectedExceptionMessage Process has not been started.
*/
public function testProcessHasBeenStarted() {
Loop::run(function () {
$process = new Process(self::CMD_PROCESS);
2017-12-05 22:53:41 +01:00
yield $process->join();
2017-12-05 06:02:41 +01:00
});
}
public function testCommand() {
2017-12-05 06:02:41 +01:00
$process = new Process([self::CMD_PROCESS]);
$this->assertSame(\implode(" ", \array_map("escapeshellarg", [self::CMD_PROCESS])), $process->getCommand());
}
public function testOptions() {
$process = new Process(self::CMD_PROCESS);
$this->assertSame([], $process->getOptions());
}
2017-12-06 20:00:08 +01:00
public function getProcessCounts(): array {
return \array_map(function (int $count): array {
return [$count];
}, \range(2, 32, 2));
2017-12-06 20:00:08 +01:00
}
/**
* @dataProvider getProcessCounts
*
* @param int $count
*/
public function testSpawnMultipleProcesses(int $count) {
Loop::run(function () use ($count) {
$processes = [];
for ($i = 0; $i < $count; ++$i) {
$command = \DIRECTORY_SEPARATOR === "\\" ? "cmd /c exit $i" : "exit $i";
$processes[] = new Process(self::CMD_PROCESS_SLOW . " && " . $command);
}
$promises = [];
foreach ($processes as $process) {
$process->start();
$promises[] = $process->join();
}
$this->assertSame(\range(0, $count - 1), yield $promises);
});
}
public function testReadOutputAfterExit() {
Loop::run(function () {
$process = new Process(["php", __DIR__ . "/bin/worker.php"]);
$process->start();
2017-12-10 22:17:04 +01:00
$process->getStdin()->write("exit 2");
$this->assertSame("..", yield $process->getStdout()->read());
$this->assertSame(0, yield $process->join());
});
}
public function testReadOutputAfterExitWithLongOutput() {
Loop::run(function () {
$process = new Process(["php", __DIR__ . "/bin/worker.php"]);
$process->start();
$count = 128 * 1024 + 1;
$process->getStdin()->write("exit " . $count);
$this->assertSame(str_repeat(".", $count), yield new Message($process->getStdout()));
$this->assertSame(0, yield $process->join());
});
}
2017-06-15 19:11:38 +02:00
}