2016-11-03 00:27:15 +00:00
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
use MediaWiki\Shell\Command;
|
2017-11-29 02:51:25 +00:00
|
|
|
use Wikimedia\TestingAccessWrapper;
|
2016-11-03 00:27:15 +00:00
|
|
|
|
|
|
|
|
/**
|
2017-12-09 06:08:28 +00:00
|
|
|
* @covers \MediaWiki\Shell\Command
|
2016-11-03 00:27:15 +00:00
|
|
|
* @group Shell
|
|
|
|
|
*/
|
|
|
|
|
class CommandTest extends PHPUnit_Framework_TestCase {
|
|
|
|
|
private function requirePosix() {
|
|
|
|
|
if ( wfIsWindows() ) {
|
|
|
|
|
$this->markTestSkipped( 'This test requires a POSIX environment.' );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @dataProvider provideExecute
|
|
|
|
|
*/
|
|
|
|
|
public function testExecute( $commandInput, $expectedExitCode, $expectedOutput ) {
|
|
|
|
|
$this->requirePosix();
|
|
|
|
|
|
|
|
|
|
$command = new Command();
|
|
|
|
|
$result = $command
|
|
|
|
|
->params( $commandInput )
|
|
|
|
|
->execute();
|
|
|
|
|
|
|
|
|
|
$this->assertSame( $expectedExitCode, $result->getExitCode() );
|
|
|
|
|
$this->assertSame( $expectedOutput, $result->getStdout() );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function provideExecute() {
|
|
|
|
|
return [
|
|
|
|
|
'success status' => [ 'true', 0, '' ],
|
|
|
|
|
'failure status' => [ 'false', 1, '' ],
|
|
|
|
|
'output' => [ [ 'echo', '-n', 'x', '>', 'y' ], 0, 'x > y' ],
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testEnvironment() {
|
|
|
|
|
$this->requirePosix();
|
|
|
|
|
|
|
|
|
|
$command = new Command();
|
|
|
|
|
$result = $command
|
|
|
|
|
->params( [ 'printenv', 'FOO' ] )
|
|
|
|
|
->environment( [ 'FOO' => 'bar' ] )
|
|
|
|
|
->execute();
|
|
|
|
|
$this->assertSame( "bar\n", $result->getStdout() );
|
|
|
|
|
}
|
|
|
|
|
|
2016-12-03 00:12:59 +00:00
|
|
|
public function testStdout() {
|
|
|
|
|
$this->requirePosix();
|
|
|
|
|
|
|
|
|
|
$command = new Command();
|
|
|
|
|
|
|
|
|
|
$result = $command
|
|
|
|
|
->params( 'bash', '-c', 'echo ThisIsStderr 1>&2' )
|
|
|
|
|
->execute();
|
|
|
|
|
|
|
|
|
|
$this->assertNotContains( 'ThisIsStderr', $result->getStdout() );
|
|
|
|
|
$this->assertEquals( "ThisIsStderr\n", $result->getStderr() );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testStdoutRedirection() {
|
|
|
|
|
$this->requirePosix();
|
|
|
|
|
|
|
|
|
|
$command = new Command();
|
|
|
|
|
|
|
|
|
|
$result = $command
|
|
|
|
|
->params( 'bash', '-c', 'echo ThisIsStderr 1>&2' )
|
|
|
|
|
->includeStderr( true )
|
|
|
|
|
->execute();
|
|
|
|
|
|
|
|
|
|
$this->assertEquals( "ThisIsStderr\n", $result->getStdout() );
|
|
|
|
|
$this->assertNull( $result->getStderr() );
|
|
|
|
|
}
|
|
|
|
|
|
2016-11-03 00:27:15 +00:00
|
|
|
public function testOutput() {
|
|
|
|
|
global $IP;
|
|
|
|
|
|
|
|
|
|
$this->requirePosix();
|
2016-12-03 00:12:59 +00:00
|
|
|
chdir( $IP );
|
2016-11-03 00:27:15 +00:00
|
|
|
|
|
|
|
|
$command = new Command();
|
|
|
|
|
$result = $command
|
2016-12-03 00:12:59 +00:00
|
|
|
->params( [ 'ls', 'index.php' ] )
|
2016-11-03 00:27:15 +00:00
|
|
|
->execute();
|
2016-12-03 00:12:59 +00:00
|
|
|
$this->assertRegExp( '/^index.php$/m', $result->getStdout() );
|
|
|
|
|
$this->assertSame( null, $result->getStderr() );
|
2016-11-03 00:27:15 +00:00
|
|
|
|
|
|
|
|
$command = new Command();
|
|
|
|
|
$result = $command
|
|
|
|
|
->params( [ 'ls', 'index.php', 'no-such-file' ] )
|
|
|
|
|
->includeStderr()
|
|
|
|
|
->execute();
|
2016-12-03 00:12:59 +00:00
|
|
|
$this->assertRegExp( '/^index.php$/m', $result->getStdout() );
|
2016-11-03 00:27:15 +00:00
|
|
|
$this->assertRegExp( '/^.+no-such-file.*$/m', $result->getStdout() );
|
2016-12-03 00:12:59 +00:00
|
|
|
$this->assertSame( null, $result->getStderr() );
|
|
|
|
|
|
|
|
|
|
$command = new Command();
|
|
|
|
|
$result = $command
|
|
|
|
|
->params( [ 'ls', 'index.php', 'no-such-file' ] )
|
|
|
|
|
->execute();
|
|
|
|
|
$this->assertRegExp( '/^index.php$/m', $result->getStdout() );
|
|
|
|
|
$this->assertRegExp( '/^.+no-such-file.*$/m', $result->getStderr() );
|
2016-11-03 00:27:15 +00:00
|
|
|
}
|
|
|
|
|
|
2017-11-29 02:51:25 +00:00
|
|
|
/**
|
|
|
|
|
* Test that null values are skipped by params() and unsafeParams()
|
|
|
|
|
*/
|
|
|
|
|
public function testNullsAreSkipped() {
|
|
|
|
|
$command = TestingAccessWrapper::newFromObject( new Command );
|
|
|
|
|
$command->params( 'echo', 'a', null, 'b' );
|
|
|
|
|
$command->unsafeParams( 'c', null, 'd' );
|
|
|
|
|
$this->assertEquals( "'echo' 'a' 'b' c d", $command->command );
|
|
|
|
|
}
|
|
|
|
|
|
2016-11-03 00:27:15 +00:00
|
|
|
public function testT69870() {
|
|
|
|
|
$commandLine = wfIsWindows()
|
|
|
|
|
// 333 = 331 + CRLF
|
|
|
|
|
? ( 'for /l %i in (1, 1, 1001) do @echo ' . str_repeat( '*', 331 ) )
|
|
|
|
|
: 'printf "%-333333s" "*"';
|
|
|
|
|
|
|
|
|
|
// Test several times because it involves a race condition that may randomly succeed or fail
|
|
|
|
|
for ( $i = 0; $i < 10; $i++ ) {
|
|
|
|
|
$command = new Command();
|
|
|
|
|
$output = $command->unsafeParams( $commandLine )
|
|
|
|
|
->execute()
|
|
|
|
|
->getStdout();
|
|
|
|
|
$this->assertEquals( 333333, strlen( $output ) );
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-10-23 08:29:20 +00:00
|
|
|
|
|
|
|
|
public function testLogStderr() {
|
|
|
|
|
$this->requirePosix();
|
|
|
|
|
|
|
|
|
|
$logger = new TestLogger( true, function ( $message, $level, $context ) {
|
|
|
|
|
return $level === Psr\Log\LogLevel::ERROR ? '1' : null;
|
|
|
|
|
}, true );
|
|
|
|
|
$command = new Command();
|
|
|
|
|
$command->setLogger( $logger );
|
|
|
|
|
$command->params( 'bash', '-c', 'echo ThisIsStderr 1>&2' );
|
|
|
|
|
$command->execute();
|
|
|
|
|
$this->assertEmpty( $logger->getBuffer() );
|
|
|
|
|
|
|
|
|
|
$command = new Command();
|
|
|
|
|
$command->setLogger( $logger );
|
|
|
|
|
$command->logStderr();
|
|
|
|
|
$command->params( 'bash', '-c', 'echo ThisIsStderr 1>&2' );
|
|
|
|
|
$command->execute();
|
|
|
|
|
$this->assertSame( 1, count( $logger->getBuffer() ) );
|
|
|
|
|
$this->assertSame( trim( $logger->getBuffer()[0][2]['error'] ), 'ThisIsStderr' );
|
|
|
|
|
}
|
2016-11-03 00:27:15 +00:00
|
|
|
}
|