385dd500a6baa319d642a5243381e2c02dde8509
[lhc/web/wiklou.git] / tests / phpunit / includes / shell / CommandTest.php
1 <?php
2
3 use MediaWiki\Shell\Command;
4 use Wikimedia\TestingAccessWrapper;
5
6 /**
7 * @covers \MediaWiki\Shell\Command
8 * @group Shell
9 */
10 class CommandTest extends PHPUnit_Framework_TestCase {
11 private function requirePosix() {
12 if ( wfIsWindows() ) {
13 $this->markTestSkipped( 'This test requires a POSIX environment.' );
14 }
15 }
16
17 /**
18 * @dataProvider provideExecute
19 */
20 public function testExecute( $commandInput, $expectedExitCode, $expectedOutput ) {
21 $this->requirePosix();
22
23 $command = new Command();
24 $result = $command
25 ->params( $commandInput )
26 ->execute();
27
28 $this->assertSame( $expectedExitCode, $result->getExitCode() );
29 $this->assertSame( $expectedOutput, $result->getStdout() );
30 }
31
32 public function provideExecute() {
33 return [
34 'success status' => [ 'true', 0, '' ],
35 'failure status' => [ 'false', 1, '' ],
36 'output' => [ [ 'echo', '-n', 'x', '>', 'y' ], 0, 'x > y' ],
37 ];
38 }
39
40 public function testEnvironment() {
41 $this->requirePosix();
42
43 $command = new Command();
44 $result = $command
45 ->params( [ 'printenv', 'FOO' ] )
46 ->environment( [ 'FOO' => 'bar' ] )
47 ->execute();
48 $this->assertSame( "bar\n", $result->getStdout() );
49 }
50
51 public function testStdout() {
52 $this->requirePosix();
53
54 $command = new Command();
55
56 $result = $command
57 ->params( 'bash', '-c', 'echo ThisIsStderr 1>&2' )
58 ->execute();
59
60 $this->assertNotContains( 'ThisIsStderr', $result->getStdout() );
61 $this->assertEquals( "ThisIsStderr\n", $result->getStderr() );
62 }
63
64 public function testStdoutRedirection() {
65 $this->requirePosix();
66
67 $command = new Command();
68
69 $result = $command
70 ->params( 'bash', '-c', 'echo ThisIsStderr 1>&2' )
71 ->includeStderr( true )
72 ->execute();
73
74 $this->assertEquals( "ThisIsStderr\n", $result->getStdout() );
75 $this->assertNull( $result->getStderr() );
76 }
77
78 public function testOutput() {
79 global $IP;
80
81 $this->requirePosix();
82 chdir( $IP );
83
84 $command = new Command();
85 $result = $command
86 ->params( [ 'ls', 'index.php' ] )
87 ->execute();
88 $this->assertRegExp( '/^index.php$/m', $result->getStdout() );
89 $this->assertSame( null, $result->getStderr() );
90
91 $command = new Command();
92 $result = $command
93 ->params( [ 'ls', 'index.php', 'no-such-file' ] )
94 ->includeStderr()
95 ->execute();
96 $this->assertRegExp( '/^index.php$/m', $result->getStdout() );
97 $this->assertRegExp( '/^.+no-such-file.*$/m', $result->getStdout() );
98 $this->assertSame( null, $result->getStderr() );
99
100 $command = new Command();
101 $result = $command
102 ->params( [ 'ls', 'index.php', 'no-such-file' ] )
103 ->execute();
104 $this->assertRegExp( '/^index.php$/m', $result->getStdout() );
105 $this->assertRegExp( '/^.+no-such-file.*$/m', $result->getStderr() );
106 }
107
108 /**
109 * Test that null values are skipped by params() and unsafeParams()
110 */
111 public function testNullsAreSkipped() {
112 $command = TestingAccessWrapper::newFromObject( new Command );
113 $command->params( 'echo', 'a', null, 'b' );
114 $command->unsafeParams( 'c', null, 'd' );
115 $this->assertEquals( "'echo' 'a' 'b' c d", $command->command );
116 }
117
118 public function testT69870() {
119 $commandLine = wfIsWindows()
120 // 333 = 331 + CRLF
121 ? ( 'for /l %i in (1, 1, 1001) do @echo ' . str_repeat( '*', 331 ) )
122 : 'printf "%-333333s" "*"';
123
124 // Test several times because it involves a race condition that may randomly succeed or fail
125 for ( $i = 0; $i < 10; $i++ ) {
126 $command = new Command();
127 $output = $command->unsafeParams( $commandLine )
128 ->execute()
129 ->getStdout();
130 $this->assertEquals( 333333, strlen( $output ) );
131 }
132 }
133
134 public function testLogStderr() {
135 $this->requirePosix();
136
137 $logger = new TestLogger( true, function ( $message, $level, $context ) {
138 return $level === Psr\Log\LogLevel::ERROR ? '1' : null;
139 }, true );
140 $command = new Command();
141 $command->setLogger( $logger );
142 $command->params( 'bash', '-c', 'echo ThisIsStderr 1>&2' );
143 $command->execute();
144 $this->assertEmpty( $logger->getBuffer() );
145
146 $command = new Command();
147 $command->setLogger( $logger );
148 $command->logStderr();
149 $command->params( 'bash', '-c', 'echo ThisIsStderr 1>&2' );
150 $command->execute();
151 $this->assertSame( 1, count( $logger->getBuffer() ) );
152 $this->assertSame( trim( $logger->getBuffer()[0][2]['error'] ), 'ThisIsStderr' );
153 }
154 }