2017-01-11 12:24:02 -06:00
|
|
|
<?php
|
|
|
|
|
2017-12-02 21:16:52 -06:00
|
|
|
namespace Amp\Process\Test;
|
2017-01-11 12:24:02 -06:00
|
|
|
|
2017-12-04 23:02:41 -06:00
|
|
|
use Amp\ByteStream\ResourceInputStream;
|
|
|
|
use Amp\ByteStream\ResourceOutputStream;
|
2017-03-16 10:04:52 -05:00
|
|
|
use Amp\Loop;
|
2017-01-11 12:24:02 -06:00
|
|
|
use Amp\Process\Process;
|
2017-12-04 23:02:41 -06:00
|
|
|
use Amp\Process\ProcessInputStream;
|
|
|
|
use Amp\Process\ProcessOutputStream;
|
2017-06-15 22:53:33 -05:00
|
|
|
use PHPUnit\Framework\TestCase;
|
2017-01-11 12:24:02 -06:00
|
|
|
|
2017-06-15 22:53:33 -05:00
|
|
|
class ProcessTest extends TestCase {
|
2017-09-17 19:07:13 +02:00
|
|
|
const CMD_PROCESS = \DIRECTORY_SEPARATOR === "\\" ? "cmd /c echo foo" : "echo foo";
|
2017-01-11 12:24:02 -06:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @expectedException \Amp\Process\StatusError
|
|
|
|
*/
|
|
|
|
public function testMultipleExecution() {
|
2017-06-15 12:11:38 -05:00
|
|
|
Loop::run(function () {
|
2017-01-11 12:24:02 -06:00
|
|
|
$process = new Process(self::CMD_PROCESS);
|
2017-03-16 22:19:15 -05:00
|
|
|
$process->start();
|
|
|
|
$process->start();
|
2017-01-11 12:24:02 -06:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2017-01-15 22:49:41 -06:00
|
|
|
public function testIsRunning() {
|
2017-06-15 12:11:38 -05:00
|
|
|
Loop::run(function () {
|
2017-09-17 19:07:13 +02:00
|
|
|
$process = new Process(\DIRECTORY_SEPARATOR === "\\" ? "cmd /c exit 42" : "exit 42");
|
2017-03-16 22:19:15 -05:00
|
|
|
$process->start();
|
|
|
|
$promise = $process->join();
|
2017-01-15 22:49:41 -06:00
|
|
|
|
|
|
|
$this->assertTrue($process->isRunning());
|
|
|
|
|
|
|
|
yield $promise;
|
|
|
|
|
|
|
|
$this->assertFalse($process->isRunning());
|
2017-03-16 10:04:52 -05:00
|
|
|
});
|
2017-01-15 22:49:41 -06:00
|
|
|
}
|
|
|
|
|
2017-01-11 14:27:40 -06:00
|
|
|
public function testExecuteResolvesToExitCode() {
|
2017-06-15 12:11:38 -05:00
|
|
|
Loop::run(function () {
|
2017-09-17 19:07:13 +02:00
|
|
|
$process = new Process(\DIRECTORY_SEPARATOR === "\\" ? "cmd /c exit 42" : "exit 42");
|
2017-03-16 22:19:15 -05:00
|
|
|
$process->start();
|
2017-09-17 19:07:13 +02:00
|
|
|
|
2017-03-16 22:19:15 -05:00
|
|
|
$code = yield $process->join();
|
2017-01-11 12:24:02 -06:00
|
|
|
|
2017-01-11 14:27:40 -06:00
|
|
|
$this->assertSame(42, $code);
|
2017-01-15 22:49:41 -06:00
|
|
|
$this->assertFalse($process->isRunning());
|
2017-03-16 10:04:52 -05:00
|
|
|
});
|
2017-01-11 12:24:02 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
public function testCommandCanRun() {
|
2017-06-15 12:11:38 -05:00
|
|
|
Loop::run(function () {
|
2017-01-11 12:24:02 -06:00
|
|
|
$process = new Process(self::CMD_PROCESS);
|
2017-03-16 22:19:15 -05:00
|
|
|
$process->start();
|
|
|
|
$promise = $process->join();
|
2017-01-11 12:24:02 -06:00
|
|
|
|
2017-09-17 19:07:13 +02:00
|
|
|
$this->assertInternalType('int', yield $process->getPid());
|
2017-01-11 12:24:02 -06:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2017-12-04 23:02:41 -06:00
|
|
|
public function testCommandArray() {
|
|
|
|
Loop::run(function () {
|
|
|
|
$process = new Process(self::CMD_PROCESS);
|
|
|
|
$process->start();
|
|
|
|
$promise = $process->join();
|
|
|
|
|
|
|
|
$this->assertInternalType('object', $process->getPid());
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
public function testProcessCanTerminate() {
|
|
|
|
Loop::run(function () {
|
|
|
|
$process = new Process(self::CMD_PROCESS);
|
|
|
|
$process->start();
|
|
|
|
$promise = $process->join();
|
|
|
|
|
|
|
|
$process->signal(0);
|
|
|
|
$this->assertInternalType('object', $process->getPid());
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
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 () {
|
|
|
|
$process = new Process(self::CMD_PROCESS, null, []);
|
|
|
|
$this->assertSame([], $process->getEnv());
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
public function testGetStdinIsCustomized() {
|
|
|
|
Loop::run(function () {
|
|
|
|
$process = new Process(self::CMD_PROCESS, null, [], [
|
|
|
|
new ResourceInputStream(fopen(__DIR__.'/../stream', 'a+')),
|
|
|
|
]);
|
|
|
|
$process->start();
|
|
|
|
$promise = $process->join();
|
|
|
|
$this->assertInstanceOf(ProcessOutputStream::class, $process->getStdin());
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
public function testGetStdoutIsCustomized() {
|
|
|
|
Loop::run(function () {
|
|
|
|
$process = new Process(self::CMD_PROCESS, null, [], [
|
|
|
|
new ResourceOutputStream(fopen(__DIR__.'/../stream', 'w')),
|
|
|
|
]);
|
|
|
|
$process->start();
|
|
|
|
$promise = $process->join();
|
|
|
|
$this->assertInstanceOf(ProcessInputStream::class, $process->getStdout());
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
public function testGetStderrIsCustomized() {
|
|
|
|
Loop::run(function () {
|
|
|
|
$process = new Process(self::CMD_PROCESS, null, [], [
|
|
|
|
new ResourceOutputStream(fopen(__DIR__.'/../stream', 'w')),
|
|
|
|
]);
|
|
|
|
$process->start();
|
|
|
|
$promise = $process->join();
|
|
|
|
$this->assertInstanceOf(ProcessInputStream::class, $process->getStderr());
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
public function testProcessEnvIsValid() {
|
|
|
|
$process = new Process(self::CMD_PROCESS, null, [
|
|
|
|
'env_value'
|
|
|
|
]);
|
|
|
|
$process->start();
|
|
|
|
$promise = $process->join();
|
|
|
|
$this->assertSame('env_value', $process->getEnv()[0]);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @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();
|
|
|
|
}
|
|
|
|
|
|
|
|
public function testProcessCanReset() {
|
|
|
|
$this->expectException(\Error::class);
|
|
|
|
$process = new Process(self::CMD_PROCESS);
|
|
|
|
$process->start();
|
|
|
|
$promise = $process->join();
|
|
|
|
$processReset = clone $process;
|
|
|
|
$processReset->getPid();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @expectedException \Error
|
|
|
|
* @expectedExceptionMessage Cloning is not allowed!
|
|
|
|
*/
|
|
|
|
public function testProcessResetDeferredIsNull() {
|
|
|
|
$process = new Process(self::CMD_PROCESS);
|
|
|
|
$process->start();
|
|
|
|
$promise = $process->join();
|
|
|
|
$processReset = clone $process;
|
|
|
|
$processReset->join();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @expectedException \Error
|
|
|
|
* @expectedExceptionMessage Cloning is not allowed!
|
|
|
|
*/
|
|
|
|
public function testProcessResetSignalIsNotRunning() {
|
|
|
|
$process = new Process(self::CMD_PROCESS);
|
|
|
|
$process->start();
|
|
|
|
$promise = $process->join();
|
|
|
|
$processReset = clone $process;
|
|
|
|
$processReset->signal(1);
|
|
|
|
}
|
|
|
|
|
2017-01-11 12:24:02 -06:00
|
|
|
/**
|
|
|
|
* @expectedException \Amp\Process\ProcessException
|
|
|
|
* @expectedExceptionMessage The process was killed
|
|
|
|
*/
|
|
|
|
public function testKillSignals() {
|
2017-06-15 12:11:38 -05:00
|
|
|
Loop::run(function () {
|
2017-01-11 12:24:02 -06:00
|
|
|
$process = new Process(self::CMD_PROCESS);
|
2017-03-16 22:19:15 -05:00
|
|
|
$process->start();
|
|
|
|
$promise = $process->join();
|
2017-01-11 12:24:02 -06:00
|
|
|
|
|
|
|
$process->kill();
|
|
|
|
|
2017-09-17 19:07:13 +02:00
|
|
|
yield $promise;
|
2017-03-16 10:04:52 -05:00
|
|
|
});
|
2017-01-11 12:24:02 -06:00
|
|
|
}
|
|
|
|
|
2017-12-04 23:02:41 -06:00
|
|
|
/**
|
|
|
|
* @expectedException \Amp\Process\StatusError
|
|
|
|
* @expectedExceptionMessage Process has not been started.
|
|
|
|
*/
|
|
|
|
public function testProcessHasNotBeenStartedWithJoin() {
|
|
|
|
Loop::run(function () {
|
|
|
|
$process = new Process(self::CMD_PROCESS);
|
|
|
|
$promise = $process->join();
|
|
|
|
|
|
|
|
yield $promise;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @expectedException \Amp\Process\StatusError
|
|
|
|
* @expectedExceptionMessage Process has not been started.
|
|
|
|
*/
|
|
|
|
public function testProcessHasNotBeenStartedWithGetPid() {
|
|
|
|
Loop::run(function () {
|
|
|
|
$process = new Process(self::CMD_PROCESS);
|
|
|
|
$promise = $process->getPid();
|
|
|
|
|
|
|
|
yield $promise;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @expectedException \Amp\Process\StatusError
|
|
|
|
* @expectedExceptionMessage Process is not running.
|
|
|
|
*/
|
|
|
|
public function testProcessIsNotRunningWithKill() {
|
|
|
|
Loop::run(function () {
|
|
|
|
$process = new Process(self::CMD_PROCESS);
|
|
|
|
|
|
|
|
$process->kill();
|
|
|
|
|
|
|
|
yield $promise;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @expectedException \Amp\Process\StatusError
|
|
|
|
* @expectedExceptionMessage Process is not running.
|
|
|
|
*/
|
|
|
|
public function testProcessIsNotRunningWithSignal() {
|
|
|
|
Loop::run(function () {
|
|
|
|
$process = new Process(self::CMD_PROCESS);
|
|
|
|
|
|
|
|
$process->signal(0);
|
|
|
|
|
|
|
|
yield $promise;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @expectedException \Amp\Process\StatusError
|
|
|
|
* @expectedExceptionMessage Process has not been started.
|
|
|
|
*/
|
|
|
|
public function testProcessHasBeenStarted() {
|
|
|
|
Loop::run(function () {
|
|
|
|
$process = new Process(self::CMD_PROCESS);
|
|
|
|
$promise = $process->join();
|
|
|
|
|
|
|
|
yield $promise;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2017-01-11 12:24:02 -06:00
|
|
|
public function testCommand() {
|
2017-12-04 23:02:41 -06:00
|
|
|
$process = new Process([self::CMD_PROCESS]);
|
|
|
|
$this->assertSame(\implode(" ", \array_map("escapeshellarg", [self::CMD_PROCESS])), $process->getCommand());
|
2017-01-11 12:24:02 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
public function testOptions() {
|
|
|
|
$process = new Process(self::CMD_PROCESS);
|
|
|
|
$this->assertSame([], $process->getOptions());
|
|
|
|
}
|
2017-12-04 23:02:41 -06:00
|
|
|
|
|
|
|
public function tearDown() {
|
|
|
|
@unlink(__DIR__.'/../stream');
|
|
|
|
}
|
2017-06-15 12:11:38 -05:00
|
|
|
}
|