Skip to content

Commit 324903f

Browse files
yondifoncrynobonetaylorotwell
authored
Add missing waitUntil method to FakeInvokedProcess (#57030)
* Add missing waitUntil method to FakeInvokedProcess * formatting * support both 'out' and 'err' output streams * formatting * test calling wait/waitUntil multiple times --------- Co-authored-by: Mior Muhammad Zaki <[email protected]> Co-authored-by: Taylor Otwell <[email protected]>
1 parent 57d3174 commit 324903f

File tree

3 files changed

+294
-0
lines changed

3 files changed

+294
-0
lines changed

src/Illuminate/Contracts/Process/InvokedProcess.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,4 +61,12 @@ public function latestErrorOutput();
6161
* @return \Illuminate\Process\ProcessResult
6262
*/
6363
public function wait(?callable $output = null);
64+
65+
/**
66+
* Wait until the given callback returns true.
67+
*
68+
* @param callable|null $output
69+
* @return \Illuminate\Process\ProcessResult
70+
*/
71+
public function waitUntil(?callable $output = null);
6472
}

src/Illuminate/Process/FakeInvokedProcess.php

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,37 @@ public function wait(?callable $output = null)
286286
return $this->process->toProcessResult($this->command);
287287
}
288288

289+
/**
290+
* Wait until the given callback returns true.
291+
*
292+
* @param callable|null $output
293+
* @return \Illuminate\Contracts\Process\ProcessResult
294+
*/
295+
public function waitUntil(?callable $output = null)
296+
{
297+
$shouldStop = false;
298+
299+
$this->outputHandler = $output
300+
? function ($type, $buffer) use ($output, &$shouldStop) {
301+
$shouldStop = call_user_func($output, $type, $buffer);
302+
}
303+
: $this->outputHandler;
304+
305+
if (! $this->outputHandler) {
306+
$this->remainingRunIterations = 0;
307+
308+
return $this->predictProcessResult();
309+
}
310+
311+
while ($this->running() && ! $shouldStop) {
312+
//
313+
}
314+
315+
$this->remainingRunIterations = 0;
316+
317+
return $this->process->toProcessResult($this->command);
318+
}
319+
289320
/**
290321
* Get the ultimate process result that will be returned by this "process".
291322
*

tests/Process/ProcessTest.php

Lines changed: 255 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -765,6 +765,261 @@ public function testFakeInvokedProcessOutputWithLatestOutput()
765765
$this->assertEquals("ONE\nTWO\nTHREE\n", $output[2]);
766766
}
767767

768+
public function testFakeInvokedProcessWaitUntil()
769+
{
770+
$factory = new Factory;
771+
772+
$factory->fake(function () use ($factory) {
773+
return $factory->describe()
774+
->output('WAITING')
775+
->output('READY')
776+
->output('DONE')
777+
->runsFor(iterations: 3);
778+
});
779+
780+
$process = $factory->start('echo "WAITING"; sleep 1; echo "READY"; sleep 1; echo "DONE";');
781+
782+
$callbackInvoked = [];
783+
784+
$result = $process->waitUntil(function ($type, $buffer) use (&$callbackInvoked) {
785+
$callbackInvoked[] = $buffer;
786+
787+
return str_contains($buffer, 'READY');
788+
});
789+
790+
$this->assertInstanceOf(ProcessResult::class, $result);
791+
$this->assertTrue($result->successful());
792+
$this->assertContains("WAITING\n", $callbackInvoked);
793+
$this->assertContains("READY\n", $callbackInvoked);
794+
}
795+
796+
public function testFakeInvokedProcessWaitUntilWithNoCallback()
797+
{
798+
$factory = new Factory;
799+
800+
$factory->fake(function () use ($factory) {
801+
return $factory->describe()
802+
->output('OUTPUT');
803+
});
804+
805+
$process = $factory->start('echo "OUTPUT"');
806+
807+
$result = $process->waitUntil();
808+
809+
$this->assertInstanceOf(ProcessResult::class, $result);
810+
$this->assertTrue($result->successful());
811+
$this->assertEquals("OUTPUT\n", $result->output());
812+
}
813+
814+
public function testFakeInvokedProcessWaitUntilWithErrorOutput()
815+
{
816+
$factory = new Factory;
817+
818+
$factory->fake(function () use ($factory) {
819+
return $factory->describe()
820+
->output('STDOUT')
821+
->errorOutput('ERROR1')
822+
->errorOutput('TARGET_ERROR')
823+
->output('MORE_STDOUT')
824+
->runsFor(iterations: 4);
825+
});
826+
827+
$process = $factory->start('echo "STDOUT"; echo "ERROR1" >&2; echo "TARGET_ERROR" >&2; echo "MORE_STDOUT";');
828+
829+
$callbackInvoked = [];
830+
831+
$result = $process->waitUntil(function ($type, $buffer) use (&$callbackInvoked) {
832+
$callbackInvoked[] = [$type, $buffer];
833+
834+
return str_contains($buffer, 'TARGET_ERROR');
835+
});
836+
837+
$this->assertInstanceOf(ProcessResult::class, $result);
838+
$this->assertTrue($result->successful());
839+
$this->assertContains(['out', "STDOUT\n"], $callbackInvoked);
840+
$this->assertContains(['err', "ERROR1\n"], $callbackInvoked);
841+
$this->assertContains(['err', "TARGET_ERROR\n"], $callbackInvoked);
842+
}
843+
844+
public function testFakeInvokedProcessWaitUntilCalledTwice()
845+
{
846+
$factory = new Factory;
847+
848+
$factory->fake(function () use ($factory) {
849+
return $factory->describe()
850+
->output('FIRST')
851+
->output('SECOND')
852+
->output('THIRD')
853+
->output('FOURTH')
854+
->runsFor(iterations: 4);
855+
});
856+
857+
$process = $factory->start('echo "FIRST"; echo "SECOND"; echo "THIRD"; echo "FOURTH";');
858+
859+
$firstCallbackInvoked = [];
860+
$secondCallbackInvoked = [];
861+
862+
$firstResult = $process->waitUntil(function ($type, $buffer) use (&$firstCallbackInvoked) {
863+
$firstCallbackInvoked[] = $buffer;
864+
865+
return str_contains($buffer, 'SECOND');
866+
});
867+
868+
$this->assertInstanceOf(ProcessResult::class, $firstResult);
869+
$this->assertTrue($firstResult->successful());
870+
$this->assertContains("FIRST\n", $firstCallbackInvoked);
871+
$this->assertContains("SECOND\n", $firstCallbackInvoked);
872+
$this->assertCount(2, $firstCallbackInvoked);
873+
874+
$secondResult = $process->waitUntil(function ($type, $buffer) use (&$secondCallbackInvoked) {
875+
$secondCallbackInvoked[] = $buffer;
876+
877+
return str_contains($buffer, 'FOURTH');
878+
});
879+
880+
$this->assertInstanceOf(ProcessResult::class, $secondResult);
881+
$this->assertTrue($secondResult->successful());
882+
$this->assertContains("THIRD\n", $secondCallbackInvoked);
883+
$this->assertContains("FOURTH\n", $secondCallbackInvoked);
884+
$this->assertCount(2, $secondCallbackInvoked);
885+
}
886+
887+
public function testFakeInvokedProcessWaitUntilThatNeverMatches()
888+
{
889+
$factory = new Factory;
890+
891+
$factory->fake(function () use ($factory) {
892+
return $factory->describe()
893+
->output('LINE1')
894+
->output('LINE2')
895+
->output('LINE3')
896+
->runsFor(iterations: 3);
897+
});
898+
899+
$process = $factory->start('echo "LINE1"; echo "LINE2"; echo "LINE3";');
900+
901+
$callbackInvoked = [];
902+
903+
$result = $process->waitUntil(function ($type, $buffer) use (&$callbackInvoked) {
904+
$callbackInvoked[] = $buffer;
905+
906+
return str_contains($buffer, 'NEVER_MATCHES');
907+
});
908+
909+
$this->assertInstanceOf(ProcessResult::class, $result);
910+
$this->assertTrue($result->successful());
911+
$this->assertCount(3, $callbackInvoked);
912+
$this->assertContains("LINE1\n", $callbackInvoked);
913+
$this->assertContains("LINE2\n", $callbackInvoked);
914+
$this->assertContains("LINE3\n", $callbackInvoked);
915+
}
916+
917+
public function testFakeInvokedProcessWaitUntilFollowedByWait()
918+
{
919+
$factory = new Factory;
920+
921+
$factory->fake(function () use ($factory) {
922+
return $factory->describe()
923+
->output('FIRST')
924+
->output('SECOND')
925+
->output('THIRD')
926+
->runsFor(iterations: 3);
927+
});
928+
929+
$process = $factory->start('echo "FIRST"; echo "SECOND"; echo "THIRD";');
930+
931+
$waitUntilCallbacks = [];
932+
$waitCallbacks = [];
933+
934+
$process->waitUntil(function ($type, $buffer) use (&$waitUntilCallbacks) {
935+
$waitUntilCallbacks[] = $buffer;
936+
937+
return str_contains($buffer, 'FIRST');
938+
});
939+
940+
$result = $process->wait(function ($type, $buffer) use (&$waitCallbacks) {
941+
$waitCallbacks[] = $buffer;
942+
});
943+
944+
$this->assertInstanceOf(ProcessResult::class, $result);
945+
$this->assertTrue($result->successful());
946+
$this->assertCount(1, $waitUntilCallbacks);
947+
$this->assertEquals("FIRST\n", $waitUntilCallbacks[0]);
948+
$this->assertCount(2, $waitCallbacks);
949+
$this->assertContains("SECOND\n", $waitCallbacks);
950+
$this->assertContains("THIRD\n", $waitCallbacks);
951+
}
952+
953+
public function testFakeInvokedProcessWaitCalledTwice()
954+
{
955+
$factory = new Factory;
956+
957+
$factory->fake(function () use ($factory) {
958+
return $factory->describe()
959+
->output('FIRST')
960+
->output('SECOND')
961+
->output('THIRD')
962+
->runsFor(iterations: 3);
963+
});
964+
965+
$process = $factory->start('echo "FIRST"; echo "SECOND"; echo "THIRD";');
966+
967+
$firstCallbackInvoked = [];
968+
$secondCallbackInvoked = [];
969+
970+
$firstResult = $process->wait(function ($type, $buffer) use (&$firstCallbackInvoked) {
971+
$firstCallbackInvoked[] = $buffer;
972+
});
973+
974+
$this->assertInstanceOf(ProcessResult::class, $firstResult);
975+
$this->assertTrue($firstResult->successful());
976+
$this->assertCount(3, $firstCallbackInvoked);
977+
$this->assertContains("FIRST\n", $firstCallbackInvoked);
978+
$this->assertContains("SECOND\n", $firstCallbackInvoked);
979+
$this->assertContains("THIRD\n", $firstCallbackInvoked);
980+
981+
$secondResult = $process->wait(function ($type, $buffer) use (&$secondCallbackInvoked) {
982+
$secondCallbackInvoked[] = $buffer;
983+
});
984+
985+
$this->assertInstanceOf(ProcessResult::class, $secondResult);
986+
$this->assertTrue($secondResult->successful());
987+
$this->assertEmpty($secondCallbackInvoked);
988+
}
989+
990+
public function testFakeInvokedProcessWaitFollowedByWaitUntil()
991+
{
992+
$factory = new Factory;
993+
994+
$factory->fake(function () use ($factory) {
995+
return $factory->describe()
996+
->output('FIRST')
997+
->output('SECOND')
998+
->output('THIRD')
999+
->runsFor(iterations: 3);
1000+
});
1001+
1002+
$process = $factory->start('echo "FIRST"; echo "SECOND"; echo "THIRD";');
1003+
1004+
$waitCallbacks = [];
1005+
$waitUntilCallbacks = [];
1006+
1007+
$process->wait(function ($type, $buffer) use (&$waitCallbacks) {
1008+
$waitCallbacks[] = $buffer;
1009+
});
1010+
1011+
$result = $process->waitUntil(function ($type, $buffer) use (&$waitUntilCallbacks) {
1012+
$waitUntilCallbacks[] = $buffer;
1013+
1014+
return str_contains($buffer, 'THIRD');
1015+
});
1016+
1017+
$this->assertInstanceOf(ProcessResult::class, $result);
1018+
$this->assertTrue($result->successful());
1019+
$this->assertCount(3, $waitCallbacks);
1020+
$this->assertEmpty($waitUntilCallbacks);
1021+
}
1022+
7681023
public function testBasicFakeAssertions()
7691024
{
7701025
$factory = new Factory;

0 commit comments

Comments
 (0)