2011-05-09 21:40:18 +01:00
< ? php
/*
* This file is part of the Symfony package .
*
* ( c ) Fabien Potencier < fabien @ symfony . com >
*
* For the full copyright and license information , please view the LICENSE
* file that was distributed with this source code .
*/
2012-03-28 14:43:52 +01:00
namespace Symfony\Component\Process\Tests ;
2011-05-09 21:40:18 +01:00
2013-08-02 20:20:26 +01:00
use Symfony\Component\Process\Exception\ProcessTimedOutException ;
2012-10-27 14:48:18 +01:00
use Symfony\Component\Process\Process ;
2013-04-06 19:51:55 +01:00
use Symfony\Component\Process\Exception\RuntimeException ;
2012-10-27 14:48:18 +01:00
2011-05-09 21:40:18 +01:00
/**
* @ author Robert Schönthal < seroscho @ googlemail . com >
*/
2012-09-09 15:38:21 +01:00
abstract class AbstractProcessTest extends \PHPUnit_Framework_TestCase
2011-05-09 21:40:18 +01:00
{
2013-10-24 03:56:37 +01:00
public function testThatProcessDoesNotThrowWarningDuringRun ()
{
@ trigger_error ( 'Test Error' , E_USER_NOTICE );
$process = $this -> getProcess ( " php -r 'sleep(3)' " );
$process -> run ();
$actualError = error_get_last ();
$this -> assertEquals ( 'Test Error' , $actualError [ 'message' ]);
$this -> assertEquals ( E_USER_NOTICE , $actualError [ 'type' ]);
}
2012-07-10 14:21:23 +01:00
/**
2013-01-05 17:52:40 +00:00
* @ expectedException \Symfony\Component\Process\Exception\InvalidArgumentException
2012-07-10 14:21:23 +01:00
*/
public function testNegativeTimeoutFromConstructor ()
{
2012-09-09 15:38:21 +01:00
$this -> getProcess ( '' , null , null , null , - 1 );
2012-07-10 14:21:23 +01:00
}
/**
2013-01-05 17:52:40 +00:00
* @ expectedException \Symfony\Component\Process\Exception\InvalidArgumentException
2012-07-10 14:21:23 +01:00
*/
public function testNegativeTimeoutFromSetter ()
{
2012-09-09 15:38:21 +01:00
$p = $this -> getProcess ( '' );
2012-07-10 14:21:23 +01:00
$p -> setTimeout ( - 1 );
}
2013-11-08 00:33:52 +00:00
public function testFloatAndNullTimeout ()
2012-07-11 13:21:05 +01:00
{
2012-09-09 15:38:21 +01:00
$p = $this -> getProcess ( '' );
2013-11-08 00:33:52 +00:00
2012-07-11 13:21:05 +01:00
$p -> setTimeout ( 10 );
2013-11-08 00:33:52 +00:00
$this -> assertSame ( 10.0 , $p -> getTimeout ());
2012-07-11 13:21:05 +01:00
$p -> setTimeout ( null );
2013-11-08 00:33:52 +00:00
$this -> assertNull ( $p -> getTimeout ());
2012-07-11 13:21:05 +01:00
2013-11-08 00:33:52 +00:00
$p -> setTimeout ( 0.0 );
2012-07-11 13:21:05 +01:00
$this -> assertNull ( $p -> getTimeout ());
}
2013-04-06 18:59:02 +01:00
public function testStopWithTimeoutIsActuallyWorking ()
{
2013-06-13 20:00:58 +01:00
$this -> verifyPosixIsEnabled ();
2013-04-06 18:59:02 +01:00
// exec is mandatory here since we send a signal to the process
// see https://github.com/symfony/symfony/issues/5030 about prepending
// command with exec
$p = $this -> getProcess ( 'exec php ' . __DIR__ . '/NonStopableProcess.php 3' );
$p -> start ();
usleep ( 100000 );
$start = microtime ( true );
2012-09-09 15:56:43 +01:00
$p -> stop ( 1.1 , SIGKILL );
2013-04-06 18:59:02 +01:00
while ( $p -> isRunning ()) {
usleep ( 1000 );
}
$duration = microtime ( true ) - $start ;
2013-08-02 22:51:01 +01:00
$this -> assertLessThan ( 1.8 , $duration );
2013-04-06 18:59:02 +01:00
}
2012-07-11 13:21:05 +01:00
2013-08-13 16:56:09 +01:00
public function testCallbacksAreExecutedWithStart ()
{
$data = '' ;
2013-09-02 09:23:35 +01:00
$process = $this -> getProcess ( 'echo foo && php -r "sleep(1);" && echo foo' );
2013-08-13 16:56:09 +01:00
$process -> start ( function ( $type , $buffer ) use ( & $data ) {
$data .= $buffer ;
});
while ( $process -> isRunning ()) {
usleep ( 10000 );
}
2013-09-02 09:23:35 +01:00
$this -> assertEquals ( 2 , preg_match_all ( '/foo/' , $data , $matches ));
2013-08-13 16:56:09 +01:00
}
2011-05-09 21:40:18 +01:00
/**
* tests results from sub processes
2011-06-08 18:56:59 +01:00
*
2011-06-22 20:47:44 +01:00
* @ dataProvider responsesCodeProvider
2011-05-09 21:40:18 +01:00
*/
2011-05-09 22:21:57 +01:00
public function testProcessResponses ( $expected , $getter , $code )
2011-05-09 21:40:18 +01:00
{
2012-09-09 15:38:21 +01:00
$p = $this -> getProcess ( sprintf ( 'php -r %s' , escapeshellarg ( $code )));
2011-05-09 21:40:18 +01:00
$p -> run ();
2011-06-08 18:56:59 +01:00
2011-05-09 21:40:18 +01:00
$this -> assertSame ( $expected , $p -> $getter ());
}
2011-06-08 18:56:59 +01:00
2011-06-22 20:47:44 +01:00
/**
* tests results from sub processes
*
* @ dataProvider pipesCodeProvider
*/
2013-05-06 10:50:13 +01:00
public function testProcessPipes ( $code , $size )
2011-06-22 20:47:44 +01:00
{
2013-05-06 10:50:13 +01:00
$expected = str_repeat ( str_repeat ( '*' , 1024 ), $size ) . '!' ;
$expectedLength = ( 1024 * $size ) + 1 ;
2012-09-09 15:38:21 +01:00
$p = $this -> getProcess ( sprintf ( 'php -r %s' , escapeshellarg ( $code )));
2011-06-22 20:47:44 +01:00
$p -> setStdin ( $expected );
$p -> run ();
2013-05-06 10:50:13 +01:00
$this -> assertEquals ( $expectedLength , strlen ( $p -> getOutput ()));
$this -> assertEquals ( $expectedLength , strlen ( $p -> getErrorOutput ()));
2011-06-22 20:47:44 +01:00
}
2012-09-25 09:21:47 +01:00
public function chainedCommandsOutputProvider ()
{
2013-09-02 09:23:35 +01:00
if ( defined ( 'PHP_WINDOWS_VERSION_BUILD' )) {
return array (
array ( " 2 \r \n 2 \r \n " , '&&' , '2' )
);
}
2012-09-25 09:21:47 +01:00
return array (
2012-11-19 17:07:58 +00:00
array ( " 1 \n 1 \n " , ';' , '1' ),
array ( " 2 \n 2 \n " , '&&' , '2' ),
2012-09-25 09:21:47 +01:00
);
}
/**
*
* @ dataProvider chainedCommandsOutputProvider
*/
public function testChainedCommandsOutput ( $expected , $operator , $input )
2012-09-22 02:03:15 +01:00
{
2012-11-19 17:07:58 +00:00
$process = $this -> getProcess ( sprintf ( 'echo %s %s echo %s' , $input , $operator , $input ));
2012-09-22 02:03:15 +01:00
$process -> run ();
2012-09-25 09:21:47 +01:00
$this -> assertEquals ( $expected , $process -> getOutput ());
2012-09-22 02:03:15 +01:00
}
2012-05-24 18:52:29 +01:00
public function testCallbackIsExecutedForOutput ()
{
2012-09-09 15:38:21 +01:00
$p = $this -> getProcess ( sprintf ( 'php -r %s' , escapeshellarg ( 'echo \'foo\';' )));
2012-05-24 18:52:29 +01:00
$called = false ;
$p -> run ( function ( $type , $buffer ) use ( & $called ) {
$called = $buffer === 'foo' ;
});
$this -> assertTrue ( $called , 'The callback should be executed with the output' );
}
2012-09-19 01:35:24 +01:00
public function testGetErrorOutput ()
{
2013-04-25 14:23:11 +01:00
$p = new Process ( sprintf ( 'php -r %s' , escapeshellarg ( '$n = 0; while ($n < 3) { file_put_contents(\'php://stderr\', \'ERROR\'); $n++; }' )));
2012-09-19 01:35:24 +01:00
$p -> run ();
2013-04-25 14:23:11 +01:00
$this -> assertEquals ( 3 , preg_match_all ( '/ERROR/' , $p -> getErrorOutput (), $matches ));
2012-09-19 01:35:24 +01:00
}
public function testGetIncrementalErrorOutput ()
{
2013-04-25 14:23:11 +01:00
$p = new Process ( sprintf ( 'php -r %s' , escapeshellarg ( '$n = 0; while ($n < 3) { usleep(50000); file_put_contents(\'php://stderr\', \'ERROR\'); $n++; }' )));
2012-09-19 01:35:24 +01:00
$p -> start ();
2012-10-27 17:54:34 +01:00
while ( $p -> isRunning ()) {
2013-04-25 14:23:11 +01:00
$this -> assertLessThanOrEqual ( 1 , preg_match_all ( '/ERROR/' , $p -> getIncrementalErrorOutput (), $matches ));
2012-09-19 01:35:24 +01:00
usleep ( 20000 );
}
}
2013-06-16 10:12:20 +01:00
public function testFlushErrorOutput ()
{
$p = new Process ( sprintf ( 'php -r %s' , escapeshellarg ( '$n = 0; while ($n < 3) { file_put_contents(\'php://stderr\', \'ERROR\'); $n++; }' )));
$p -> run ();
2013-10-30 12:27:00 +00:00
$p -> clearErrorOutput ();
2013-06-16 10:12:20 +01:00
$this -> assertEmpty ( $p -> getErrorOutput ());
}
2012-09-19 01:35:24 +01:00
public function testGetOutput ()
{
2013-09-02 09:23:35 +01:00
$p = new Process ( sprintf ( 'php -r %s' , escapeshellarg ( '$n=0;while ($n<3) {echo \' foo \';$n++; usleep(500); }' )));
2012-09-19 01:35:24 +01:00
$p -> run ();
$this -> assertEquals ( 3 , preg_match_all ( '/foo/' , $p -> getOutput (), $matches ));
}
public function testGetIncrementalOutput ()
{
2012-12-11 10:49:22 +00:00
$p = new Process ( sprintf ( 'php -r %s' , escapeshellarg ( '$n=0;while ($n<3) { echo \' foo \'; usleep(50000); $n++; }' )));
2012-09-19 01:35:24 +01:00
$p -> start ();
2012-10-27 17:54:34 +01:00
while ( $p -> isRunning ()) {
2012-09-19 01:35:24 +01:00
$this -> assertLessThanOrEqual ( 1 , preg_match_all ( '/foo/' , $p -> getIncrementalOutput (), $matches ));
usleep ( 20000 );
}
}
2013-06-16 10:12:20 +01:00
public function testFlushOutput ()
{
$p = new Process ( sprintf ( 'php -r %s' , escapeshellarg ( '$n=0;while ($n<3) {echo \' foo \';$n++;}' )));
$p -> run ();
2013-10-30 12:27:00 +00:00
$p -> clearOutput ();
2013-06-16 10:12:20 +01:00
$this -> assertEmpty ( $p -> getOutput ());
}
2012-08-30 11:55:38 +01:00
public function testExitCodeCommandFailed ()
{
2012-09-09 15:38:21 +01:00
if ( defined ( 'PHP_WINDOWS_VERSION_BUILD' )) {
2012-08-30 11:55:38 +01:00
$this -> markTestSkipped ( 'Windows does not support POSIX exit code' );
}
// such command run in bash return an exitcode 127
2012-09-09 15:38:21 +01:00
$process = $this -> getProcess ( 'nonexistingcommandIhopeneversomeonewouldnameacommandlikethis' );
2012-08-30 11:55:38 +01:00
$process -> run ();
$this -> assertGreaterThan ( 0 , $process -> getExitCode ());
}
2013-04-05 11:35:05 +01:00
public function testTTYCommand ()
{
if ( defined ( 'PHP_WINDOWS_VERSION_BUILD' )) {
$this -> markTestSkipped ( 'Windows does have /dev/tty support' );
}
$process = $this -> getProcess ( 'echo "foo" >> /dev/null' );
$process -> setTTY ( true );
$process -> run ();
$this -> assertSame ( Process :: STATUS_TERMINATED , $process -> getStatus ());
}
2013-08-03 08:10:03 +01:00
public function testPTYCommand ()
{
2014-02-03 08:11:05 +00:00
if ( ! Process :: isPtySupported ()) {
2013-08-03 08:57:35 +01:00
$this -> markTestSkipped ( 'PTY is not supported on this operating system.' );
2013-08-03 08:10:03 +01:00
}
$process = $this -> getProcess ( 'echo "foo"' );
$process -> setPty ( true );
$process -> run ();
$this -> assertSame ( Process :: STATUS_TERMINATED , $process -> getStatus ());
$this -> assertEquals ( " foo \r \n " , $process -> getOutput ());
}
2013-08-03 08:24:32 +01:00
public function testMustRun ()
{
$process = $this -> getProcess ( 'echo "foo"' );
$this -> assertSame ( $process , $process -> mustRun ());
$this -> assertEquals ( " foo \n " , $process -> getOutput ());
$this -> assertEquals ( 0 , $process -> getExitCode ());
}
/**
* @ expectedException Symfony\Component\Process\Exception\ProcessFailedException
*/
public function testMustRunThrowsException ()
{
$process = $this -> getProcess ( 'exit 1' );
$process -> mustRun ();
}
2012-02-13 06:31:37 +00:00
public function testExitCodeText ()
{
2012-09-09 15:38:21 +01:00
$process = $this -> getProcess ( '' );
2012-02-13 06:31:37 +00:00
$r = new \ReflectionObject ( $process );
$p = $r -> getProperty ( 'exitcode' );
$p -> setAccessible ( true );
$p -> setValue ( $process , 2 );
$this -> assertEquals ( 'Misuse of shell builtins' , $process -> getExitCodeText ());
}
2012-03-21 16:58:02 +00:00
public function testStartIsNonBlocking ()
{
2012-09-09 15:38:21 +01:00
$process = $this -> getProcess ( 'php -r "sleep(4);"' );
2012-03-21 16:58:02 +00:00
$start = microtime ( true );
$process -> start ();
$end = microtime ( true );
$this -> assertLessThan ( 1 , $end - $start );
}
2012-03-23 11:59:10 +00:00
public function testUpdateStatus ()
{
2012-09-09 15:38:21 +01:00
$process = $this -> getProcess ( 'php -h' );
$process -> run ();
2012-03-23 11:59:10 +00:00
$this -> assertTrue ( strlen ( $process -> getOutput ()) > 0 );
2012-03-21 16:58:02 +00:00
}
2013-08-20 19:22:08 +01:00
public function testGetExitCodeIsNullOnStart ()
{
$process = $this -> getProcess ( 'php -r "usleep(200000);"' );
$this -> assertNull ( $process -> getExitCode ());
$process -> start ();
$this -> assertNull ( $process -> getExitCode ());
$process -> wait ();
$this -> assertEquals ( 0 , $process -> getExitCode ());
}
public function testGetExitCodeIsNullOnWhenStartingAgain ()
{
$process = $this -> getProcess ( 'php -r "usleep(200000);"' );
$process -> run ();
$this -> assertEquals ( 0 , $process -> getExitCode ());
$process -> start ();
$this -> assertNull ( $process -> getExitCode ());
$process -> wait ();
$this -> assertEquals ( 0 , $process -> getExitCode ());
}
2012-09-09 15:38:21 +01:00
public function testGetExitCode ()
{
$process = $this -> getProcess ( 'php -m' );
$process -> run ();
$this -> assertEquals ( 0 , $process -> getExitCode ());
}
2012-10-27 17:54:34 +01:00
public function testStatus ()
2012-03-23 11:59:10 +00:00
{
2012-09-09 15:56:43 +01:00
$process = $this -> getProcess ( 'php -r "usleep(500000);"' );
2012-03-21 16:58:02 +00:00
$this -> assertFalse ( $process -> isRunning ());
2012-10-27 17:54:34 +01:00
$this -> assertFalse ( $process -> isStarted ());
$this -> assertFalse ( $process -> isTerminated ());
$this -> assertSame ( Process :: STATUS_READY , $process -> getStatus ());
2012-03-21 16:58:02 +00:00
$process -> start ();
$this -> assertTrue ( $process -> isRunning ());
2012-10-27 17:54:34 +01:00
$this -> assertTrue ( $process -> isStarted ());
$this -> assertFalse ( $process -> isTerminated ());
$this -> assertSame ( Process :: STATUS_STARTED , $process -> getStatus ());
2012-03-23 12:02:23 +00:00
$process -> wait ();
2012-03-21 16:58:02 +00:00
$this -> assertFalse ( $process -> isRunning ());
2012-10-27 17:54:34 +01:00
$this -> assertTrue ( $process -> isStarted ());
$this -> assertTrue ( $process -> isTerminated ());
$this -> assertSame ( Process :: STATUS_TERMINATED , $process -> getStatus ());
2012-03-21 16:58:02 +00:00
}
2012-03-23 11:59:10 +00:00
public function testStop ()
{
2013-08-13 17:01:05 +01:00
$process = $this -> getProcess ( 'php -r "sleep(4);"' );
2012-03-21 16:58:02 +00:00
$process -> start ();
$this -> assertTrue ( $process -> isRunning ());
$process -> stop ();
$this -> assertFalse ( $process -> isRunning ());
2012-09-09 15:38:21 +01:00
}
2012-04-08 19:29:02 +01:00
2012-09-09 15:38:21 +01:00
public function testIsSuccessful ()
{
$process = $this -> getProcess ( 'php -m' );
$process -> run ();
$this -> assertTrue ( $process -> isSuccessful ());
}
2013-08-21 15:50:47 +01:00
public function testIsSuccessfulOnlyAfterTerminated ()
{
2013-09-02 09:23:35 +01:00
$process = $this -> getProcess ( 'php -r "sleep(1);"' );
2013-08-21 15:50:47 +01:00
$process -> start ();
while ( $process -> isRunning ()) {
$this -> assertFalse ( $process -> isSuccessful ());
usleep ( 300000 );
}
$this -> assertTrue ( $process -> isSuccessful ());
}
2012-09-09 15:38:21 +01:00
public function testIsNotSuccessful ()
{
2013-08-13 17:01:05 +01:00
$process = $this -> getProcess ( 'php -r "sleep(4);"' );
2012-09-09 15:38:21 +01:00
$process -> start ();
$this -> assertTrue ( $process -> isRunning ());
$process -> stop ();
$this -> assertFalse ( $process -> isSuccessful ());
}
public function testProcessIsNotSignaled ()
{
if ( defined ( 'PHP_WINDOWS_VERSION_BUILD' )) {
$this -> markTestSkipped ( 'Windows does not support POSIX signals' );
2012-04-08 19:29:02 +01:00
}
2012-09-09 15:38:21 +01:00
$process = $this -> getProcess ( 'php -m' );
$process -> run ();
$this -> assertFalse ( $process -> hasBeenSignaled ());
}
2012-09-09 15:56:43 +01:00
public function testProcessWithoutTermSignalIsNotSignaled ()
{
if ( defined ( 'PHP_WINDOWS_VERSION_BUILD' )) {
$this -> markTestSkipped ( 'Windows does not support POSIX signals' );
}
$process = $this -> getProcess ( 'php -m' );
$process -> run ();
$this -> assertFalse ( $process -> hasBeenSignaled ());
}
2012-09-09 15:38:21 +01:00
public function testProcessWithoutTermSignal ()
{
if ( defined ( 'PHP_WINDOWS_VERSION_BUILD' )) {
$this -> markTestSkipped ( 'Windows does not support POSIX signals' );
}
$process = $this -> getProcess ( 'php -m' );
$process -> run ();
$this -> assertEquals ( 0 , $process -> getTermSignal ());
}
public function testProcessIsSignaledIfStopped ()
{
if ( defined ( 'PHP_WINDOWS_VERSION_BUILD' )) {
$this -> markTestSkipped ( 'Windows does not support POSIX signals' );
}
2013-08-13 17:01:05 +01:00
$process = $this -> getProcess ( 'php -r "sleep(4);"' );
2012-09-09 15:38:21 +01:00
$process -> start ();
$process -> stop ();
$this -> assertTrue ( $process -> hasBeenSignaled ());
}
public function testProcessWithTermSignal ()
{
if ( defined ( 'PHP_WINDOWS_VERSION_BUILD' )) {
$this -> markTestSkipped ( 'Windows does not support POSIX signals' );
}
2012-12-30 12:18:39 +00:00
// SIGTERM is only defined if pcntl extension is present
$termSignal = defined ( 'SIGTERM' ) ? SIGTERM : 15 ;
2013-08-13 17:01:05 +01:00
$process = $this -> getProcess ( 'php -r "sleep(4);"' );
2012-09-09 15:38:21 +01:00
$process -> start ();
$process -> stop ();
2012-12-30 12:18:39 +00:00
$this -> assertEquals ( $termSignal , $process -> getTermSignal ());
2012-03-21 16:58:02 +00:00
}
2013-04-29 11:07:05 +01:00
public function testProcessThrowsExceptionWhenExternallySignaled ()
{
if ( defined ( 'PHP_WINDOWS_VERSION_BUILD' )) {
$this -> markTestSkipped ( 'Windows does not support POSIX signals' );
}
if ( ! function_exists ( 'posix_kill' )) {
$this -> markTestSkipped ( 'posix_kill is required for this test' );
}
$termSignal = defined ( 'SIGKILL' ) ? SIGKILL : 9 ;
$process = $this -> getProcess ( 'exec php -r "while (true) {}"' );
$process -> start ();
posix_kill ( $process -> getPid (), $termSignal );
2013-04-30 08:21:49 +01:00
$this -> setExpectedException ( 'Symfony\Component\Process\Exception\RuntimeException' , 'The process has been signaled with signal "9".' );
2013-04-29 11:07:05 +01:00
$process -> wait ();
}
2012-09-07 08:03:48 +01:00
public function testRestart ()
{
2012-10-04 15:37:34 +01:00
$process1 = $this -> getProcess ( 'php -r "echo getmypid();"' );
$process1 -> run ();
$process2 = $process1 -> restart ();
2012-09-07 08:03:48 +01:00
2012-10-04 15:37:34 +01:00
usleep ( 300000 ); // wait for output
2012-09-07 08:03:48 +01:00
2012-10-04 15:37:34 +01:00
// Ensure that both processed finished and the output is numeric
$this -> assertFalse ( $process1 -> isRunning ());
$this -> assertFalse ( $process2 -> isRunning ());
$this -> assertTrue ( is_numeric ( $process1 -> getOutput ()));
$this -> assertTrue ( is_numeric ( $process2 -> getOutput ()));
2012-09-07 08:03:48 +01:00
2012-10-04 15:37:34 +01:00
// Ensure that restart returned a new process by check that the output is different
$this -> assertNotEquals ( $process1 -> getOutput (), $process2 -> getOutput ());
2012-09-07 08:03:48 +01:00
}
2012-04-11 22:08:57 +01:00
public function testPhpDeadlock ()
{
2013-12-27 15:08:19 +00:00
$this -> markTestSkipped ( 'Can course PHP to hang' );
2012-04-11 22:08:57 +01:00
2012-07-28 23:02:29 +01:00
// Sleep doesn't work as it will allow the process to handle signals and close
2012-04-11 22:08:57 +01:00
// file handles from the other end.
2012-09-09 15:38:21 +01:00
$process = $this -> getProcess ( 'php -r "while (true) {}"' );
2012-04-11 22:08:57 +01:00
$process -> start ();
// PHP will deadlock when it tries to cleanup $process
}
2013-04-06 19:51:55 +01:00
public function testRunProcessWithTimeout ()
{
$timeout = 0.5 ;
2013-09-02 09:23:35 +01:00
$process = $this -> getProcess ( 'php -r "sleep(3);"' );
2013-04-06 19:51:55 +01:00
$process -> setTimeout ( $timeout );
$start = microtime ( true );
try {
$process -> run ();
$this -> fail ( 'A RuntimeException should have been raised' );
} catch ( RuntimeException $e ) {
}
$duration = microtime ( true ) - $start ;
$this -> assertLessThan ( $timeout + Process :: TIMEOUT_PRECISION , $duration );
}
public function testCheckTimeoutOnStartedProcess ()
{
$timeout = 0.5 ;
$precision = 100000 ;
2013-09-02 09:23:35 +01:00
$process = $this -> getProcess ( 'php -r "sleep(3);"' );
2013-04-06 19:51:55 +01:00
$process -> setTimeout ( $timeout );
$start = microtime ( true );
$process -> start ();
try {
while ( $process -> isRunning ()) {
$process -> checkTimeout ();
usleep ( $precision );
}
$this -> fail ( 'A RuntimeException should have been raised' );
} catch ( RuntimeException $e ) {
}
$duration = microtime ( true ) - $start ;
$this -> assertLessThan ( $timeout + $precision , $duration );
2013-08-14 16:41:18 +01:00
$this -> assertFalse ( $process -> isSuccessful ());
2013-04-06 19:51:55 +01:00
}
2013-08-02 20:20:26 +01:00
/**
* @ group idle - timeout
*/
public function testIdleTimeout ()
{
$process = $this -> getProcess ( 'sleep 3' );
$process -> setTimeout ( 10 );
$process -> setIdleTimeout ( 1 );
try {
$process -> run ();
$this -> fail ( 'A timeout exception was expected.' );
} catch ( ProcessTimedOutException $ex ) {
$this -> assertTrue ( $ex -> isIdleTimeout ());
$this -> assertFalse ( $ex -> isGeneralTimeout ());
$this -> assertEquals ( 1.0 , $ex -> getExceededTimeout ());
}
}
/**
* @ group idle - timeout
*/
public function testIdleTimeoutNotExceededWhenOutputIsSent ()
{
2013-09-07 15:39:40 +01:00
$process = $this -> getProcess ( 'echo "foo" && sleep 1 && echo "foo" && sleep 1 && echo "foo" && sleep 1 && echo "foo" && sleep 5' );
2013-08-02 20:20:26 +01:00
$process -> setTimeout ( 5 );
$process -> setIdleTimeout ( 3 );
try {
$process -> run ();
$this -> fail ( 'A timeout exception was expected.' );
} catch ( ProcessTimedOutException $ex ) {
$this -> assertTrue ( $ex -> isGeneralTimeout ());
$this -> assertFalse ( $ex -> isIdleTimeout ());
$this -> assertEquals ( 5.0 , $ex -> getExceededTimeout ());
}
}
2013-09-16 12:32:46 +01:00
public function testStartAfterATimeout ()
{
2013-10-30 08:30:20 +00:00
$process = $this -> getProcess ( 'php -r "while (true) {echo \'\'; usleep(1000); }"' );
2013-09-16 12:32:46 +01:00
$process -> setTimeout ( 0.1 );
try {
$process -> run ();
$this -> fail ( 'An exception should have been raised.' );
} catch ( \Exception $e ) {
}
$process -> start ();
usleep ( 10000 );
$process -> stop ();
}
2012-09-09 15:56:43 +01:00
public function testGetPid ()
{
$process = $this -> getProcess ( 'php -r "sleep(1);"' );
$process -> start ();
$this -> assertGreaterThan ( 0 , $process -> getPid ());
$process -> stop ();
}
public function testGetPidIsNullBeforeStart ()
{
$process = $this -> getProcess ( 'php -r "sleep(1);"' );
$this -> assertNull ( $process -> getPid ());
}
public function testGetPidIsNullAfterRun ()
{
$process = $this -> getProcess ( 'php -m' );
$process -> run ();
$this -> assertNull ( $process -> getPid ());
}
public function testSignal ()
{
2013-06-13 20:00:58 +01:00
$this -> verifyPosixIsEnabled ();
2013-04-25 14:23:11 +01:00
2012-09-09 15:56:43 +01:00
$process = $this -> getProcess ( 'exec php -f ' . __DIR__ . '/SignalListener.php' );
$process -> start ();
usleep ( 500000 );
$process -> signal ( SIGUSR1 );
while ( $process -> isRunning () && false === strpos ( $process -> getoutput (), 'Caught SIGUSR1' )) {
usleep ( 10000 );
}
$this -> assertEquals ( 'Caught SIGUSR1' , $process -> getOutput ());
}
2013-08-13 19:21:22 +01:00
public function testExitCodeIsAvailableAfterSignal ()
{
$this -> verifyPosixIsEnabled ();
$process = $this -> getProcess ( 'sleep 4' );
$process -> start ();
$process -> signal ( SIGKILL );
while ( $process -> isRunning ()) {
usleep ( 10000 );
}
$this -> assertFalse ( $process -> isRunning ());
$this -> assertTrue ( $process -> hasBeenSignaled ());
$this -> assertFalse ( $process -> isSuccessful ());
$this -> assertEquals ( 137 , $process -> getExitCode ());
}
2012-09-09 15:56:43 +01:00
/**
2013-11-25 14:52:16 +00:00
* @ expectedException \Symfony\Component\Process\Exception\LogicException
2012-09-09 15:56:43 +01:00
*/
public function testSignalProcessNotRunning ()
2013-06-13 20:00:58 +01:00
{
$this -> verifyPosixIsEnabled ();
$process = $this -> getProcess ( 'php -m' );
$process -> signal ( SIGHUP );
}
private function verifyPosixIsEnabled ()
2012-09-09 15:56:43 +01:00
{
2013-04-25 14:23:11 +01:00
if ( defined ( 'PHP_WINDOWS_VERSION_BUILD' )) {
2013-12-27 15:08:19 +00:00
$this -> markTestSkipped ( 'POSIX signals do not work on Windows' );
2013-04-25 14:23:11 +01:00
}
2013-06-13 20:00:58 +01:00
if ( ! defined ( 'SIGUSR1' )) {
$this -> markTestSkipped ( 'The pcntl extension is not enabled' );
}
2012-09-09 15:56:43 +01:00
}
/**
2013-11-25 14:52:16 +00:00
* @ expectedException \Symfony\Component\Process\Exception\RuntimeException
2012-09-09 15:56:43 +01:00
*/
public function testSignalWithWrongIntSignal ()
{
2013-04-25 14:23:11 +01:00
if ( defined ( 'PHP_WINDOWS_VERSION_BUILD' )) {
2013-12-27 15:08:19 +00:00
$this -> markTestSkipped ( 'POSIX signals do not work on Windows' );
2013-04-25 14:23:11 +01:00
}
2012-09-09 15:56:43 +01:00
$process = $this -> getProcess ( 'php -r "sleep(3);"' );
$process -> start ();
$process -> signal ( - 4 );
}
/**
2013-11-25 14:52:16 +00:00
* @ expectedException \Symfony\Component\Process\Exception\RuntimeException
2012-09-09 15:56:43 +01:00
*/
public function testSignalWithWrongNonIntSignal ()
{
2013-04-25 14:23:11 +01:00
if ( defined ( 'PHP_WINDOWS_VERSION_BUILD' )) {
2013-12-27 15:08:19 +00:00
$this -> markTestSkipped ( 'POSIX signals do not work on Windows' );
2013-04-25 14:23:11 +01:00
}
2012-09-09 15:56:43 +01:00
$process = $this -> getProcess ( 'php -r "sleep(3);"' );
$process -> start ();
$process -> signal ( 'Céphalopodes' );
}
2013-12-11 18:23:45 +00:00
public function testDisableOutputDisablesTheOutput ()
{
$p = $this -> getProcess ( 'php -r "usleep(500000);"' );
$this -> assertFalse ( $p -> isOutputDisabled ());
$p -> disableOutput ();
$this -> assertTrue ( $p -> isOutputDisabled ());
$p -> enableOutput ();
$this -> assertFalse ( $p -> isOutputDisabled ());
}
public function testDisableOutputWhileRunningThrowsException ()
{
$p = $this -> getProcess ( 'php -r "usleep(500000);"' );
$p -> start ();
$this -> setExpectedException ( 'Symfony\Component\Process\Exception\RuntimeException' , 'Disabling output while the process is running is not possible.' );
$p -> disableOutput ();
}
public function testEnableOutputWhileRunningThrowsException ()
{
$p = $this -> getProcess ( 'php -r "usleep(500000);"' );
$p -> disableOutput ();
$p -> start ();
$this -> setExpectedException ( 'Symfony\Component\Process\Exception\RuntimeException' , 'Enabling output while the process is running is not possible.' );
$p -> enableOutput ();
}
public function testEnableOrDisableOutputAfterRunDoesNotThrowException ()
{
$p = $this -> getProcess ( 'php -r "usleep(500000);"' );
$p -> disableOutput ();
$p -> start ();
$p -> wait ();
$p -> enableOutput ();
$p -> disableOutput ();
}
/**
* @ dataProvider provideStartMethods
*/
public function testStartWithACallbackAndDisabledOutput ( $startMethod )
{
$p = $this -> getProcess ( 'php -r "usleep(500000);"' );
$p -> disableOutput ();
$this -> setExpectedException ( 'Symfony\Component\Process\Exception\LogicException' , 'Output has been disabled, enable it to allow the use of a callback.' );
call_user_func ( array ( $p , $startMethod ), function () {});
}
public function provideStartMethods ()
{
return array (
array ( 'start' ),
array ( 'run' ),
array ( 'mustRun' ),
);
}
/**
* @ dataProvider provideOutputFetchingMethods
*/
public function testGetOutputWhileDisabled ( $fetchMethod )
{
$p = $this -> getProcess ( 'php -r "usleep(500000);"' );
$p -> disableOutput ();
$this -> setExpectedException ( 'Symfony\Component\Process\Exception\LogicException' , 'Output has been disabled.' );
call_user_func ( array ( $p , $fetchMethod ));
}
public function provideOutputFetchingMethods ()
{
return array (
array ( 'getOutput' ),
array ( 'getIncrementalOutput' ),
array ( 'getErrorOutput' ),
array ( 'getIncrementalErrorOutput' ),
);
}
2011-06-22 20:47:44 +01:00
public function responsesCodeProvider ()
2011-05-09 21:40:18 +01:00
{
return array (
//expected output / getter / code to execute
//array(1,'getExitCode','exit(1);'),
//array(true,'isSuccessful','exit();'),
2011-07-23 17:04:56 +01:00
array ( 'output' , 'getOutput' , 'echo \'output\';' ),
2011-06-22 20:47:44 +01:00
);
}
2011-06-23 12:39:36 +01:00
2011-06-22 20:47:44 +01:00
public function pipesCodeProvider ()
{
$variations = array (
2011-07-23 17:04:56 +01:00
'fwrite(STDOUT, $in = file_get_contents(\'php://stdin\')); fwrite(STDERR, $in);' ,
2013-09-10 17:39:36 +01:00
'include \'' . __DIR__ . '/PipeStdinInStdoutStdErrStreamSelect.php\';' ,
2011-05-09 21:40:18 +01:00
);
2011-06-22 20:47:44 +01:00
2013-09-10 17:39:36 +01:00
if ( defined ( 'PHP_WINDOWS_VERSION_BUILD' )) {
// Avoid XL buffers on Windows because of https://bugs.php.net/bug.php?id=65650
$sizes = array ( 1 , 2 , 4 , 8 );
} else {
$sizes = array ( 1 , 16 , 64 , 1024 , 4096 );
}
2011-06-22 20:47:44 +01:00
$codes = array ();
2013-09-10 17:39:36 +01:00
foreach ( $sizes as $size ) {
2011-06-22 20:47:44 +01:00
foreach ( $variations as $code ) {
2013-05-06 10:50:13 +01:00
$codes [] = array ( $code , $size );
2011-06-22 20:47:44 +01:00
}
}
2011-06-23 12:39:36 +01:00
2011-06-22 20:47:44 +01:00
return $codes ;
2011-05-09 21:40:18 +01:00
}
2011-06-08 18:56:59 +01:00
2011-05-09 21:40:18 +01:00
/**
* provides default method names for simple getter / setter
*/
public function methodProvider ()
{
$defaults = array (
array ( 'CommandLine' ),
array ( 'Timeout' ),
array ( 'WorkingDirectory' ),
array ( 'Env' ),
array ( 'Stdin' ),
array ( 'Options' )
);
2011-06-08 18:56:59 +01:00
2011-05-09 21:40:18 +01:00
return $defaults ;
}
2013-01-08 19:11:30 +00:00
/**
* @ param string $commandline
* @ param null $cwd
* @ param array $env
* @ param null $stdin
* @ param integer $timeout
* @ param array $options
*
2013-01-16 09:27:54 +00:00
* @ return Process
2013-01-08 19:11:30 +00:00
*/
abstract protected function getProcess ( $commandline , $cwd = null , array $env = null , $stdin = null , $timeout = 60 , array $options = array ());
2011-05-09 21:40:18 +01:00
}