35 self::$phpBin = getenv(
'SYMFONY_PROCESS_PHP_TEST_BINARY') ?: (
'phpdbg' === PHP_SAPI ?
'php' :
$phpBin->find());
36 if (
'\\' !== DIRECTORY_SEPARATOR) {
40 self::$phpBin =
'exec '.self::$phpBin;
44 phpinfo(INFO_GENERAL);
45 self::$sigchild =
false !== strpos(ob_get_clean(),
'--enable-sigchild');
51 self::$process->stop(0);
52 self::$process = null;
58 if (
'\\' === DIRECTORY_SEPARATOR) {
59 $this->markTestSkipped(
'This test is transient on Windows');
61 @trigger_error(
'Test Error', E_USER_NOTICE);
64 $actualError = error_get_last();
65 $this->assertEquals(
'Test Error', $actualError[
'message']);
66 $this->assertEquals(E_USER_NOTICE, $actualError[
'type']);
91 $this->assertSame(10.0, $p->getTimeout());
94 $this->assertNull($p->getTimeout());
97 $this->assertNull($p->getTimeout());
105 $p = $this->
getProcess(self::$phpBin.
' '.__DIR__.
'/NonStopableProcess.php 30');
108 while (
false === strpos($p->getOutput(),
'received')) {
116 $this->assertLessThan(15, microtime(
true) -
$start);
130 $code = sprintf(
'echo str_repeat(\'*\', %d);', $expectedOutputSize);
131 $p = $this->
getProcess(sprintf(
'%s -r %s', self::$phpBin, escapeshellarg(
$code)));
136 $h = new \ReflectionProperty($p,
'process');
137 $h->setAccessible(
true);
138 $h =
$h->getValue($p);
139 $s = @proc_get_status(
$h);
141 while (!empty($s[
'running'])) {
143 $s = proc_get_status(
$h);
146 $o = $p->getOutput();
148 $this->assertEquals($expectedOutputSize, strlen($o));
170 $p = $this->
getProcess(sprintf(
'%s -r %s', self::$phpBin, escapeshellarg(
$code)));
173 $this->assertSame($expected, $p->$getter());
183 $expected = str_repeat(str_repeat(
'*', 1024),
$size).
'!';
184 $expectedLength = (1024 *
$size) + 1;
186 $p = $this->
getProcess(sprintf(
'%s -r %s', self::$phpBin, escapeshellarg(
$code)));
187 $p->setInput($expected);
190 $this->assertEquals($expectedLength, strlen($p->getOutput()));
191 $this->assertEquals($expectedLength, strlen($p->getErrorOutput()));
199 $expected = str_repeat(str_repeat(
'*', 1024),
$size).
'!';
200 $expectedLength = (1024 *
$size) + 1;
202 $stream = fopen(
'php://temporary',
'w+');
203 fwrite($stream, $expected);
206 $p = $this->
getProcess(sprintf(
'%s -r %s', self::$phpBin, escapeshellarg(
$code)));
207 $p->setInput($stream);
212 $this->assertEquals($expectedLength, strlen($p->getOutput()));
213 $this->assertEquals($expectedLength, strlen($p->getErrorOutput()));
218 $stream = fopen(
'php://memory',
'r+');
219 fwrite($stream,
'hello');
222 $p = $this->
getProcess(sprintf(
'%s -r %s', self::$phpBin, escapeshellarg(
'stream_copy_to_stream(STDIN, STDOUT);')));
223 $p->setInput($stream);
224 $p->start(
function ($type,
$data) use ($stream) {
225 if (
'hello' ===
$data) {
231 $this->assertSame(
'hello', $p->getOutput());
245 $this->fail(
'A LogicException should have been raised.');
279 $this->assertSame($expected,
$process->getInput());
287 array(
'input data',
'input data'),
293 if (
'\\' === DIRECTORY_SEPARATOR) {
295 array(
"2 \r\n2\r\n",
'&&',
'2'),
300 array(
"1\n1\n",
';',
'1'),
301 array(
"2\n2\n",
'&&',
'2'),
310 $process = $this->
getProcess(sprintf(
'echo %s %s echo %s', $input, $operator, $input));
312 $this->assertEquals($expected,
$process->getOutput());
317 $p = $this->
getProcess(sprintf(
'%s -r %s', self::$phpBin, escapeshellarg(
'echo \'foo\';')));
320 $p->run(
function ($type, $buffer) use (&$called) {
321 $called = $buffer ===
'foo';
324 $this->assertTrue($called,
'The callback should be executed with the output');
329 $p = $this->
getProcess(sprintf(
'%s -r %s', self::$phpBin, escapeshellarg(
'echo \'foo\';')));
333 $p->run(
function ($type, $buffer) use (&$called) {
334 $called = $buffer ===
'foo';
337 $this->assertTrue($called,
'The callback should be executed with the output');
342 $p = $this->
getProcess(sprintf(
'%s -r %s', self::$phpBin, escapeshellarg(
'$n = 0; while ($n < 3) { file_put_contents(\'php://stderr\', \'ERROR\'); $n++; }')));
345 $this->assertEquals(3, preg_match_all(
'/ERROR/', $p->getErrorOutput(), $matches));
350 $p = $this->
getProcess(sprintf(
'%s -r %s', self::$phpBin, escapeshellarg(
'$n = 0; while ($n < 3) { file_put_contents(\'php://stderr\', \'ERROR\'); $n++; }')));
353 $p->clearErrorOutput();
354 $this->assertEmpty($p->getErrorOutput());
362 $lock = tempnam(sys_get_temp_dir(), __FUNCTION__);
364 $p = $this->
getProcess(sprintf(
'%s -r %s', self::$phpBin, escapeshellarg(
'file_put_contents($s = \''.$uri.
'\', \
'foo\'); flock(fopen('.var_export($lock,
true).
', \'r\'), LOCK_EX); file_put_contents($s, \'bar\');')));
366 $h = fopen($lock,
'w');
371 foreach (
array(
'foo',
'bar') as $s) {
372 while (
false === strpos($p->$getOutput(), $s)) {
376 $this->assertSame($s, $p->$getIncrementalOutput());
377 $this->assertSame(
'', $p->$getIncrementalOutput());
388 array(
'getOutput',
'getIncrementalOutput',
'php://stdout'),
389 array(
'getErrorOutput',
'getIncrementalErrorOutput',
'php://stderr'),
395 $p = $this->
getProcess(sprintf(
'%s -r %s', self::$phpBin, escapeshellarg(
'$n = 0; while ($n < 3) { echo \' foo \'; $n++; }')));
398 $this->assertEquals(3, preg_match_all(
'/foo/', $p->getOutput(), $matches));
403 $p = $this->
getProcess(sprintf(
'%s -r %s', self::$phpBin, escapeshellarg(
'$n=0;while ($n<3) {echo \' foo \';$n++;}')));
407 $this->assertEmpty($p->getOutput());
412 if (
'\\' === DIRECTORY_SEPARATOR) {
414 $p = $this->
getProcess(
'echo | set /p dummyName=0');
420 $this->assertSame(
'0', $p->getOutput());
425 if (
'\\' === DIRECTORY_SEPARATOR) {
426 $this->markTestSkipped(
'Windows does not support POSIX exit code');
431 $process = $this->
getProcess(
'nonexistingcommandIhopeneversomeonewouldnameacommandlikethis');
434 $this->assertGreaterThan(0,
$process->getExitCode());
439 if (
'\\' === DIRECTORY_SEPARATOR) {
440 $this->markTestSkipped(
'Windows does not have /dev/tty support');
443 $process = $this->
getProcess(
'echo "foo" >> /dev/null && '.self::$phpBin.
' -r "usleep(100000);"');
446 $this->assertTrue(
$process->isRunning());
454 if (
'\\' === DIRECTORY_SEPARATOR) {
455 $this->markTestSkipped(
'Windows does have /dev/tty support');
463 $this->assertTrue(
$process->isSuccessful());
472 if (
'\\' !== DIRECTORY_SEPARATOR) {
473 $this->markTestSkipped(
'This test is for Windows platform only');
486 $this->assertNull(
$process->getExitCodeText());
492 $this->markTestSkipped(
'PTY is not supported on this operating system.');
500 $this->assertEquals(
"foo\r\n",
$process->getOutput());
518 $this->assertEquals(0,
$process->getExitCode());
538 $p =
$r->getProperty(
'exitcode');
539 $p->setAccessible(
true);
542 $this->assertEquals(
'Misuse of shell builtins',
$process->getExitCodeText());
550 $end = microtime(
true);
551 $this->assertLessThan(0.4, $end -
$start);
559 $this->assertTrue(strlen(
$process->getOutput()) > 0);
567 $this->assertNull(
$process->getExitCode());
569 $this->assertNull(
$process->getExitCode());
571 $this->assertEquals(0,
$process->getExitCode());
580 $this->assertEquals(0,
$process->getExitCode());
582 $this->assertNull(
$process->getExitCode());
584 $this->assertEquals(0,
$process->getExitCode());
593 $this->assertSame(0,
$process->getExitCode());
599 $this->assertFalse(
$process->isRunning());
600 $this->assertFalse(
$process->isStarted());
601 $this->assertFalse(
$process->isTerminated());
604 $this->assertTrue(
$process->isRunning());
605 $this->assertTrue(
$process->isStarted());
606 $this->assertFalse(
$process->isTerminated());
609 $this->assertFalse(
$process->isRunning());
610 $this->assertTrue(
$process->isStarted());
611 $this->assertTrue(
$process->isTerminated());
619 $this->assertTrue(
$process->isRunning());
621 $this->assertFalse(
$process->isRunning());
630 $this->assertTrue(
$process->isSuccessful());
640 $this->assertFalse(
$process->isSuccessful());
644 $this->assertTrue(
$process->isSuccessful());
653 $this->assertFalse(
$process->isSuccessful());
658 if (
'\\' === DIRECTORY_SEPARATOR) {
659 $this->markTestSkipped(
'Windows does not support POSIX signals');
665 $this->assertFalse(
$process->hasBeenSignaled());
670 if (
'\\' === DIRECTORY_SEPARATOR) {
671 $this->markTestSkipped(
'Windows does not support POSIX signals');
677 $this->assertEquals(0,
$process->getTermSignal());
682 if (
'\\' === DIRECTORY_SEPARATOR) {
683 $this->markTestSkipped(
'Windows does not support POSIX signals');
690 $this->assertTrue(
$process->hasBeenSignaled());
691 $this->assertEquals(15,
$process->getTermSignal());
700 if (!function_exists(
'posix_kill')) {
701 $this->markTestSkipped(
'Function posix_kill is required.');
714 $process1 = $this->
getProcess(self::$phpBin.
' -r "echo getmypid();"');
716 $process2 = $process1->restart();
721 $this->assertFalse($process1->isRunning());
722 $this->assertFalse($process2->isRunning());
723 $this->assertTrue(is_numeric($process1->getOutput()));
724 $this->assertTrue(is_numeric($process2->getOutput()));
727 $this->assertNotEquals($process1->getOutput(), $process2->getOutput());
741 $this->fail(
'A RuntimeException should have been raised');
745 $this->assertLessThan(15, microtime(
true) -
$start);
753 $this->assertNull(
$process->checkTimeout());
760 $this->assertNull(
$process->checkTimeout());
780 $this->fail(
'A ProcessTimedOutException should have been raised');
784 $this->assertLessThan(15, microtime(
true) -
$start);
798 $this->fail(
'A timeout exception was expected.');
808 $process = $this->
getProcess(sprintf(
'%s -r %s', self::$phpBin, escapeshellarg(
'while (true) {echo \'foo \'; usleep(1000);}')));
812 while (
false === strpos(
$process->getOutput(),
'foo')) {
820 $this->fail(
'A timeout exception was expected.');
822 $this->assertTrue($e->
isGeneralTimeout(),
'A general timeout is expected.');
823 $this->assertFalse($e->
isIdleTimeout(),
'No idle timeout is expected.');
839 $this->fail(
'A ProcessTimedOutException should have been raised.');
842 $this->assertFalse(
$process->isRunning());
844 $this->assertTrue(
$process->isRunning());
854 $this->assertGreaterThan(0,
$process->getPid());
861 $this->assertNull(
$process->getPid());
868 $this->assertNull(
$process->getPid());
879 while (
false === strpos(
$process->getOutput(),
'Caught')) {
885 $this->assertEquals(
'Caught SIGUSR1',
$process->getOutput());
903 $this->assertFalse(
$process->isRunning());
904 $this->assertTrue(
$process->hasBeenSignaled());
905 $this->assertFalse(
$process->isSuccessful());
906 $this->assertEquals(137,
$process->getExitCode());
925 $this->setExpectedException(
'Symfony\Component\Process\Exception\LogicException', sprintf(
'Process must be started before calling %s.', $method));
933 array(
'getIncrementalOutput'),
934 array(
'getErrorOutput'),
935 array(
'getIncrementalErrorOutput'),
952 $this->fail(
'A LogicException must have been thrown');
963 array(
'hasBeenSignaled'),
964 array(
'getTermSignal'),
965 array(
'hasBeenStopped'),
966 array(
'getStopSignal'),
976 if (
'\\' === DIRECTORY_SEPARATOR) {
977 $this->markTestSkipped(
'POSIX signals do not work on Windows');
984 $this->fail(
'A RuntimeException must have been thrown');
996 array(
'Céphalopodes'),
1003 $this->assertFalse($p->isOutputDisabled());
1004 $p->disableOutput();
1005 $this->assertTrue($p->isOutputDisabled());
1007 $this->assertFalse($p->isOutputDisabled());
1016 $p = $this->
getProcess(self::$phpBin.
' -r "sleep(39);"');
1018 $p->disableOutput();
1027 $p = $this->
getProcess(self::$phpBin.
' -r "sleep(40);"');
1028 $p->disableOutput();
1036 $p->disableOutput();
1039 $p->disableOutput();
1040 $this->assertTrue($p->isOutputDisabled());
1079 $p = $this->
getProcess(self::$phpBin.
' -r "sleep(41);"');
1080 $p->disableOutput();
1082 $p->{$fetchMethod}();
1089 array(
'getIncrementalOutput'),
1090 array(
'getErrorOutput'),
1091 array(
'getIncrementalErrorOutput'),
1101 $this->assertTrue(
true,
'A call to stop() is not expected to cause wait() to throw a RuntimeException');
1110 $this->assertTrue(
true,
'A call to signal() is not expected to cause wait() to throw a RuntimeException');
1119 $this->assertTrue(
true,
'A call to signal() is not expected to cause wait() to throw a RuntimeException');
1128 array(
'output',
'getOutput',
'echo \'output\';'),
1134 $variations =
array(
1135 'fwrite(STDOUT, $in = file_get_contents(\'php://stdin\')); fwrite(STDERR, $in);',
1136 'include \''.__DIR__.
'/PipeStdinInStdoutStdErrStreamSelect.php\';',
1139 if (
'\\' === DIRECTORY_SEPARATOR) {
1141 $sizes =
array(1, 2, 4, 8);
1143 $sizes =
array(1, 16, 64, 1024, 4096);
1147 foreach ($sizes as
$size) {
1148 foreach ($variations as
$code) {
1149 $codes[] =
array($code, $size);
1161 $process = $this->
getProcess(self::$phpBin.
' -r '.escapeshellarg(
'$n = 0; while ($n < 3) { file_put_contents(\''.$stream.
'\',
$n, 1);
$n++; usleep(1000); }
'), null, null, null, null); 1164 $limit = microtime(true) + 3; 1167 while ($result !== $expected && microtime(true) < $limit) { 1168 $result .= $process->$method(); 1171 $this->assertSame($expected, $result); 1175 public function provideVariousIncrementals() 1179 array(
'php://stderr',
'getIncrementalErrorOutput'),
1185 $input =
function () {
1190 $process = $this->
getProcess(self::$phpBin.
' -r '.escapeshellarg(
'stream_copy_to_stream(STDIN, STDOUT);'), null, null, $input());
1192 $this->assertSame(
'pingpong',
$process->getOutput());
1199 $process = $this->
getProcess(self::$phpBin.
' -r '.escapeshellarg(
'echo \'ping\'; stream_copy_to_stream(STDIN, STDOUT);'));
1203 if (
'ping' ===
$data) {
1204 $input->write(
'pang');
1205 } elseif (!$input->isClosed()) {
1206 $input->write(
'pong');
1212 $this->assertSame(
'pingpangpong',
$process->getOutput());
1218 $stream = fopen(
'php://memory',
'w+');
1219 $stream =
function () use ($stream, &$i) {
1222 fwrite($stream, ++$i);
1230 $input->onEmpty($stream);
1231 $input->write($stream());
1233 $process = $this->
getProcess(self::$phpBin.
' -r '.escapeshellarg(
'echo fread(STDIN, 3);'));
1240 $this->assertSame(
'123',
$process->getOutput());
1246 $input->onEmpty(
function ($input) {
1251 $process = $this->
getProcess(self::$phpBin.
' -r '.escapeshellarg(
'stream_copy_to_stream(STDIN, STDOUT);'));
1254 $input->write(
'ping');
1256 $this->assertSame(
'pingpong',
$process->getOutput());
1263 $input->onEmpty(
function () use (&$i) {++$i;});
1265 $process = $this->
getProcess(self::$phpBin.
' -r '.escapeshellarg(
'echo 123; echo fread(STDIN, 1); echo 456;'));
1268 if (
'123' ===
$data) {
1274 $this->assertSame(0, $i,
'InputStream->onEmpty callback should be called only when the input *becomes* empty');
1275 $this->assertSame(
'123456',
$process->getOutput());
1282 $process = $this->
getProcess(self::$phpBin.
' -r '.escapeshellarg(
'fwrite(STDOUT, 123); fwrite(STDERR, 234); flush(); usleep(10000); fwrite(STDOUT, fread(STDIN, 3)); fwrite(STDERR, 456);'));
1291 $expectedOutput =
array(
1292 array($process::OUT,
'123'),
1294 $this->assertSame($expectedOutput,
$output);
1302 $this->assertSame(
'',
$process->getOutput());
1303 $this->assertFalse(
$process->isRunning());
1305 $expectedOutput =
array(
1306 array($process::OUT,
'123'),
1307 array($process::ERR,
'234'),
1308 array($process::OUT,
'345'),
1309 array($process::ERR,
'456'),
1311 $this->assertSame($expectedOutput,
$output);
1318 $process = $this->
getProcess(self::$phpBin.
' -r '.escapeshellarg(
'fwrite(STDOUT, fread(STDIN, 3));'));
1323 foreach (
$process->getIterator($process::ITER_NON_BLOCKING | $process::ITER_KEEP_OUTPUT) as $type =>
$data) {
1327 $expectedOutput =
array(
1328 array($process::OUT,
''),
1330 $this->assertSame($expectedOutput,
$output);
1334 foreach (
$process->getIterator($process::ITER_NON_BLOCKING | $process::ITER_KEEP_OUTPUT) as $type =>
$data) {
1340 $this->assertSame(
'123',
$process->getOutput());
1341 $this->assertFalse(
$process->isRunning());
1343 $expectedOutput =
array(
1344 array($process::OUT,
''),
1345 array($process::OUT,
'123'),
1347 $this->assertSame($expectedOutput,
$output);
1352 $p1 =
new Process(self::$phpBin.
' -r '.escapeshellarg(
'fwrite(STDERR, 123); fwrite(STDOUT, 456);'));
1353 $p2 = $this->
getProcess(sprintf(
'%s -r %s', self::$phpBin, escapeshellarg(
'stream_copy_to_stream(STDIN, STDOUT);')));
1359 $this->assertSame(
'123', $p1->getErrorOutput());
1360 $this->assertSame(
'', $p1->getOutput());
1361 $this->assertSame(
'', $p2->getErrorOutput());
1362 $this->assertSame(
'456', $p2->getOutput());
1379 if (
false !== $enhance = getenv(
'ENHANCE_SIGCHLD')) {
1381 $process->setEnhanceSigchildCompatibility(
false);
1383 $this->fail(
'ENHANCE_SIGCHLD must be used together with a sigchild-enabled PHP.');
1385 $this->assertSame(
'This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method.', $e->getMessage());
1387 $process->setEnhanceSigchildCompatibility(
true);
1389 self::$notEnhancedSigchild =
true;
1394 if (self::$process) {
1395 self::$process->stop(0);
1403 if (self::$sigchild) {
1404 if (!$expectException) {
1405 $this->markTestSkipped(
'PHP is compiled with --enable-sigchild.');
1406 } elseif (self::$notEnhancedSigchild) {
1407 $this->setExpectedException(
'Symfony\Component\Process\Exception\RuntimeException',
'This PHP has been compiled with --enable-sigchild.');
testCallbackIsExecutedForOutputWheneverOutputIsDisabled()
testExitCodeTextIsNullWhenExitCodeIsNull()
testSignalProcessNotRunning()
Can not send signal on a non running process.
testIdleTimeoutNotExceededWhenOutputIsSent()
testProcessIsNotSignaled()
testInputStreamWithCallable()
testStopTerminatesProcessCleanly()
testNegativeTimeoutFromSetter()
testCallbackIsExecutedForOutput()
testNonBlockingNorClearingIteratorOutput()
testAllOutputIsActuallyReadOnTermination()
Exception that is thrown when a process times out.
testDisableOutputWhileIdleTimeoutIsSet()
Output can not be disabled while an idle timeout is set.
testTermSignalTerminatesProcessCleanly()
testGetPidIsNullBeforeStart()
skipIfNotEnhancedSigchild($expectException=true)
testSetInputWhileRunningThrowsAnException()
Input can not be set while the process is running.
testChainedCommandsOutput($expected, $operator, $input)
chainedCommandsOutputProvider
testExitCodeIsAvailableAfterSignal()
extension pcntl
testGetPidIsNullAfterRun()
testDisableOutputDisablesTheOutput()
testIncrementalOutputDoesNotRequireAnotherCall($stream, $method)
provideVariousIncrementals
An executable finder specifically designed for the PHP executable.
provideMethodsThatNeedARunningProcess()
provideMethodsThatNeedATerminatedProcess()
testEnableOutputWhileRunningThrowsException()
Enabling output while the process is running is not possible.
testThatProcessDoesNotThrowWarningDuringRun()
testFloatAndNullTimeout()
if(!is_dir( $entity_dir)) exit("Fatal Error ([A-Za-z0-9]+)\+" &#(? foreach( $entity_files as $file) $output
testKillSignalTerminatesProcessCleanly()
testGetExitCodeIsNullOnWhenStartingAgain()
testProcessThrowsExceptionWhenExternallySignaled()
The process has been signaled
if(!is_array($argv)) $options
testGetExitCodeIsNullOnStart()
testIsSuccessfulOnlyAfterTerminated()
testSuccessfulMustRunHasCorrectExitCode()
testMethodsThatNeedARunningProcess($method)
provideMethodsThatNeedARunningProcess
if($is_dev) echo "Review changes write something in WHATSNEW and and then commit with log PHP_EOL
provideOutputFetchingMethods()
testSignal()
extension pcntl
testStopWithTimeoutIsActuallyWorking()
extension pcntl
testMethodsThatNeedATerminatedProcess($method)
provideMethodsThatNeedATerminatedProcess Symfony Process must be terminated before calling ...
testRunProcessWithTimeout()
exceeded the timeout of 0.1 seconds.
chainedCommandsOutputProvider()
getProcess($commandline, $cwd=null, array $env=null, $input=null, $timeout=60, array $options=array())
testTTYInWindowsEnvironment()
TTY mode is not supported on Windows platform.
testProcessPipes($code, $size)
tests results from sub processes.
testWrongSignal($signal)
provideWrongSignal
testDisableOutputWhileRunningThrowsException()
Disabling output while the process is running is not possible.
testExitCodeCommandFailed()
Create styles array
The data for the language used.
LogicException for the Process Component.
testGetOutputWhileDisabled($fetchMethod)
provideOutputFetchingMethods Output has been disabled.
static setUpBeforeClass()
testInvalidInput($value)
provideInvalidInputValues Symfony::setInput only accepts strings, Traversable objects or stream re...
testProcessResponses($expected, $getter, $code)
tests results from sub processes.
static $notEnhancedSigchild
static isPtySupported()
Returns whether PTY is supported on the current operating system.
testCheckTimeoutOnNonStartedProcess()
testSetIdleTimeoutWhileOutputIsDisabled()
timeout can not be set while the output is disabled.
testValidInput($expected, $value)
provideInputValues
testCheckTimeoutOnStartedProcess()
exceeded the timeout of 0.1 seconds.
testProcessWithoutTermSignal()
Process is a thin wrapper around proc_* functions to easily start independent PHP processes...
testCheckTimeoutOnTerminatedProcess()
testProcessIsSignaledIfStopped()
testSetStreamAsInput($code, $size)
pipesCodeProvider
testIncrementalOutput($getOutput, $getIncrementalOutput, $uri)
provideIncrementalOutput
provideIncrementalOutput()
testSetNullIdleTimeoutWhileOutputIsDisabled()
testEnableOrDisableOutputAfterRunDoesNotThrowException()
testCallbacksAreExecutedWithStart()
testMustRunThrowsException()
testInputStreamWithGenerator()
testStartAfterATimeout()
exceeded the timeout of 0.1 seconds.
testNegativeTimeoutFromConstructor()
provideInvalidInputValues()