3 use MediaWiki\Shell\Command
;
4 use Wikimedia\TestingAccessWrapper
;
7 * @covers \MediaWiki\Shell\Command
10 class CommandTest
extends PHPUnit\Framework\TestCase
{
12 use MediaWikiCoversValidator
;
14 private function requirePosix() {
15 if ( wfIsWindows() ) {
16 $this->markTestSkipped( 'This test requires a POSIX environment.' );
21 * @dataProvider provideExecute
23 public function testExecute( $commandInput, $expectedExitCode, $expectedOutput ) {
24 $this->requirePosix();
26 $command = new Command();
28 ->params( $commandInput )
31 $this->assertSame( $expectedExitCode, $result->getExitCode() );
32 $this->assertSame( $expectedOutput, $result->getStdout() );
35 public function provideExecute() {
37 'success status' => [ 'true', 0, '' ],
38 'failure status' => [ 'false', 1, '' ],
39 'output' => [ [ 'echo', '-n', 'x', '>', 'y' ], 0, 'x > y' ],
43 public function testEnvironment() {
44 $this->requirePosix();
46 $command = new Command();
48 ->params( [ 'printenv', 'FOO' ] )
49 ->environment( [ 'FOO' => 'bar' ] )
51 $this->assertSame( "bar\n", $result->getStdout() );
54 public function testStdout() {
55 $this->requirePosix();
57 $command = new Command();
60 ->params( 'bash', '-c', 'echo ThisIsStderr 1>&2' )
63 $this->assertNotContains( 'ThisIsStderr', $result->getStdout() );
64 $this->assertEquals( "ThisIsStderr\n", $result->getStderr() );
67 public function testStdoutRedirection() {
68 $this->requirePosix();
70 $command = new Command();
73 ->params( 'bash', '-c', 'echo ThisIsStderr 1>&2' )
74 ->includeStderr( true )
77 $this->assertEquals( "ThisIsStderr\n", $result->getStdout() );
78 $this->assertNull( $result->getStderr() );
81 public function testOutput() {
84 $this->requirePosix();
87 $command = new Command();
89 ->params( [ 'ls', 'index.php' ] )
91 $this->assertRegExp( '/^index.php$/m', $result->getStdout() );
92 $this->assertSame( null, $result->getStderr() );
94 $command = new Command();
96 ->params( [ 'ls', 'index.php', 'no-such-file' ] )
99 $this->assertRegExp( '/^index.php$/m', $result->getStdout() );
100 $this->assertRegExp( '/^.+no-such-file.*$/m', $result->getStdout() );
101 $this->assertSame( null, $result->getStderr() );
103 $command = new Command();
105 ->params( [ 'ls', 'index.php', 'no-such-file' ] )
107 $this->assertRegExp( '/^index.php$/m', $result->getStdout() );
108 $this->assertRegExp( '/^.+no-such-file.*$/m', $result->getStderr() );
112 * Test that null values are skipped by params() and unsafeParams()
114 public function testNullsAreSkipped() {
115 $command = TestingAccessWrapper
::newFromObject( new Command
);
116 $command->params( 'echo', 'a', null, 'b' );
117 $command->unsafeParams( 'c', null, 'd' );
118 $this->assertEquals( "'echo' 'a' 'b' c d", $command->command
);
121 public function testT69870() {
122 $commandLine = wfIsWindows()
124 ?
( 'for /l %i in (1, 1, 1001) do @echo ' . str_repeat( '*', 331 ) )
125 : 'printf "%-333333s" "*"';
127 // Test several times because it involves a race condition that may randomly succeed or fail
128 for ( $i = 0; $i < 10; $i++
) {
129 $command = new Command();
130 $output = $command->unsafeParams( $commandLine )
133 $this->assertEquals( 333333, strlen( $output ) );
137 public function testLogStderr() {
138 $this->requirePosix();
140 $logger = new TestLogger( true, function ( $message, $level, $context ) {
141 return $level === Psr\Log\LogLevel
::ERROR ?
'1' : null;
143 $command = new Command();
144 $command->setLogger( $logger );
145 $command->params( 'bash', '-c', 'echo ThisIsStderr 1>&2' );
147 $this->assertEmpty( $logger->getBuffer() );
149 $command = new Command();
150 $command->setLogger( $logger );
151 $command->logStderr();
152 $command->params( 'bash', '-c', 'echo ThisIsStderr 1>&2' );
154 $this->assertSame( 1, count( $logger->getBuffer() ) );
155 $this->assertSame( trim( $logger->getBuffer()[0][2]['error'] ), 'ThisIsStderr' );
158 public function testInput() {
159 $this->requirePosix();
161 $command = new Command();
162 $command->params( 'cat' );
163 $command->input( 'abc' );
164 $result = $command->execute();
165 $this->assertSame( 'abc', $result->getStdout() );
167 // now try it with something that does not fit into a single block
168 $command = new Command();
169 $command->params( 'cat' );
170 $command->input( str_repeat( '!', 1000000 ) );
171 $result = $command->execute();
172 $this->assertSame( 1000000, strlen( $result->getStdout() ) );
174 // And try it with empty input
175 $command = new Command();
176 $command->params( 'cat' );
177 $command->input( '' );
178 $result = $command->execute();
179 $this->assertSame( '', $result->getStdout() );