Skip to content

Commit 59625fd

Browse files
committed
Update console execute stderr capture
1 parent f77104e commit 59625fd

3 files changed

Lines changed: 39 additions & 27 deletions

File tree

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
"psr-4": {"Utopia\\": "src/"}
1515
},
1616
"require": {
17-
"php": ">=7.4"
17+
"php": ">=8.0"
1818
},
1919
"require-dev": {
2020
"phpunit/phpunit": "^9.3",

src/Console.php

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -125,13 +125,14 @@ public static function exit(int $status = 0): void
125125
* This function was inspired by: https://stackoverflow.com/a/13287902/2299554
126126
*
127127
* @param array|string $cmd
128-
* @param string $input
129-
* @param string $output
128+
* @param string $stdin
129+
* @param string $stdout Stdout contents (by reference).
130+
* @param string $stderr Stderr contents (by reference).
130131
* @param int $timeout
131132
* @param callable|null $onProgress
132133
* @return int
133134
*/
134-
public static function execute(array|string $cmd, string $input, string &$output, int $timeout = -1, ?callable $onProgress = null): int
135+
public static function execute(array|string $cmd, string $stdin, string &$stdout, string &$stderr, int $timeout = -1, ?callable $onProgress = null): int
135136
{
136137
// If the $cmd is passed as string, it will be wrapped into a subshell by \proc_open
137138
// Forward stdout and exit codes from the subshell.
@@ -146,7 +147,8 @@ public static function execute(array|string $cmd, string $input, string &$output
146147
$pipes
147148
);
148149
$start = \time();
149-
$output = '';
150+
$stdout = '';
151+
$stderr = '';
150152
$status = '';
151153

152154
if (\is_resource($process)) {
@@ -155,26 +157,23 @@ public static function execute(array|string $cmd, string $input, string &$output
155157
\stream_set_blocking($pipes[2], false);
156158
\stream_set_blocking($pipes[3], false);
157159

158-
\fwrite($pipes[0], $input);
160+
\fwrite($pipes[0], $stdin);
159161
\fclose($pipes[0]);
160162
}
161163

162164
while (\is_resource($process)) {
163165
$stdoutContents = \stream_get_contents($pipes[1]) ?: '';
164166
$stderrContents = \stream_get_contents($pipes[2]) ?: '';
165167

166-
$outputContents = $stdoutContents;
168+
$stderr .= $stderrContents;
167169

168-
if (! empty($stderrContents)) {
169-
$separator = empty($outputContents) ? '' : "\n";
170-
$outputContents .= $separator.$stderrContents;
171-
}
170+
$outputContents = $stdoutContents;
172171

173172
if (isset($onProgress) && (! empty($outputContents))) {
174173
$onProgress($outputContents, $process);
175174
}
176175

177-
$output .= $outputContents;
176+
$stdout .= $outputContents;
178177
$status .= \stream_get_contents($pipes[3]);
179178

180179
if ($timeout > 0 && \time() - $start > $timeout) {
@@ -214,9 +213,9 @@ public static function isInteractive(): bool
214213
*
215214
* Repeatedly execute a callback while limiting CPU consumption.
216215
*
217-
* @param callable $callback
218-
* @param int $sleep Sleep duration in seconds.
219-
* @param int $delay Initial delay in seconds.
216+
* @param callable $callback
217+
* @param int $sleep Sleep duration in seconds.
218+
* @param int $delay Initial delay in seconds.
220219
* @param callable|null $onError
221220
*
222221
* @throws \Exception

tests/Console/ConsoleTest.php

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,9 @@ public function testLogs(): void
2020
public function testExecuteBasic(): void
2121
{
2222
$output = '';
23+
$stderr = '';
2324
$input = '';
24-
$code = Console::execute('php -r "echo \'hello world\';"', $input, $output, 10);
25+
$code = Console::execute('php -r "echo \'hello world\';"', $input, $output, $stderr, 10);
2526

2627
$this->assertEquals('hello world', $output);
2728
$this->assertEquals(0, $code);
@@ -30,9 +31,10 @@ public function testExecuteBasic(): void
3031
public function testExecuteArray(): void
3132
{
3233
$output = '';
34+
$stderr = '';
3335
$input = '';
3436
$cmd = ['php', '-r', "echo 'hello world';"];
35-
$code = Console::execute($cmd, $input, $output, 10);
37+
$code = Console::execute($cmd, $input, $output, $stderr, 10);
3638

3739
$this->assertEquals('hello world', $output);
3840
$this->assertEquals(0, $code);
@@ -44,9 +46,10 @@ public function testExecuteEnvVariables(): void
4446
putenv("FOO={$randomData}");
4547

4648
$output = '';
49+
$stderr = '';
4750
$input = '';
4851
$cmd = ['printenv'];
49-
$code = Console::execute($cmd, $input, $output, 10);
52+
$code = Console::execute($cmd, $input, $output, $stderr, 10);
5053

5154
$this->assertEquals(0, $code);
5255

@@ -68,10 +71,11 @@ public function testExecuteEnvVariables(): void
6871
public function testExecuteStream(): void
6972
{
7073
$output = '';
74+
$stderr = '';
7175
$input = '';
7276

7377
$outputStream = '';
74-
$code = Console::execute('printf 1 && sleep 1 && printf 2 && sleep 1 && printf 3 && sleep 1 && printf 4 && sleep 1 && printf 5', $input, $output, 10, function ($output) use (&$outputStream) {
78+
$code = Console::execute('printf 1 && sleep 1 && printf 2 && sleep 1 && printf 3 && sleep 1 && printf 4 && sleep 1 && printf 5', $input, $output, $stderr, 10, function ($output) use (&$outputStream) {
7579
$outputStream .= $output;
7680
});
7781

@@ -83,35 +87,41 @@ public function testExecuteStream(): void
8387
public function testExecuteStdOut(): void
8488
{
8589
$output = '';
90+
$stderr = '';
8691
$input = '';
87-
$code = Console::execute('>&1 echo "success"', $input, $output, 3);
92+
$code = Console::execute('>&1 echo "success"', $input, $output, $stderr, 3);
8893

8994
$this->assertEquals("success\n", $output);
95+
$this->assertEquals('', $stderr);
9096
$this->assertEquals(0, $code);
9197
}
9298

9399
public function testExecuteStdErr(): void
94100
{
95101
$output = '';
102+
$stderr = '';
96103
$input = '';
97-
$code = Console::execute('>&2 echo "error"', $input, $output, 3);
104+
$code = Console::execute('>&2 echo "error"', $input, $output, $stderr, 3);
98105

99-
$this->assertEquals("error\n", $output);
106+
$this->assertEquals('', $output);
107+
$this->assertEquals("error\n", $stderr);
100108
$this->assertEquals(0, $code);
101109
}
102110

103111
public function testExecuteExitCode(): void
104112
{
105113
$output = '';
114+
$stderr = '';
106115
$input = '';
107-
$code = Console::execute('php -r "echo \'hello world\'; exit(2);"', $input, $output, 10);
116+
$code = Console::execute('php -r "echo \'hello world\'; exit(2);"', $input, $output, $stderr, 10);
108117

109118
$this->assertEquals('hello world', $output);
110119
$this->assertEquals(2, $code);
111120

112121
$output = '';
122+
$stderr = '';
113123
$input = '';
114-
$code = Console::execute('php -r "echo \'hello world\'; exit(100);"', $input, $output, 10);
124+
$code = Console::execute('php -r "echo \'hello world\'; exit(100);"', $input, $output, $stderr, 10);
115125

116126
$this->assertEquals('hello world', $output);
117127
$this->assertEquals(100, $code);
@@ -120,15 +130,17 @@ public function testExecuteExitCode(): void
120130
public function testExecuteTimeout(): void
121131
{
122132
$output = '';
133+
$stderr = '';
123134
$input = '';
124-
$code = Console::execute('php -r "sleep(1); echo \'hello world\'; exit(0);"', $input, $output, 3);
135+
$code = Console::execute('php -r "sleep(1); echo \'hello world\'; exit(0);"', $input, $output, $stderr, 3);
125136

126137
$this->assertEquals('hello world', $output);
127138
$this->assertEquals(0, $code);
128139

129140
$output = '';
141+
$stderr = '';
130142
$input = '';
131-
$code = Console::execute('php -r "sleep(4); echo \'hello world\'; exit(0);"', $input, $output, 3);
143+
$code = Console::execute('php -r "sleep(4); echo \'hello world\'; exit(0);"', $input, $output, $stderr, 3);
132144

133145
$this->assertEquals('', $output);
134146
$this->assertEquals(1, $code);
@@ -139,7 +151,8 @@ public function testLoop(): void
139151
$file = __DIR__.'/../resources/loop.php';
140152
$input = '';
141153
$output = '';
142-
$code = Console::execute('php '.$file, $input, $output, 30);
154+
$stderr = '';
155+
$code = Console::execute('php '.$file, $input, $output, $stderr, 30);
143156

144157
$lines = explode("\n", $output);
145158

0 commit comments

Comments
 (0)