@@ -24,6 +24,16 @@ abstract class AsyncTestCase extends PHPUnitTestCase
2424 /** @var int Minimum runtime in milliseconds. */
2525 private $ minimumRuntime = 0 ;
2626
27+ /** @var bool */
28+ private $ setUpInvoked = false ;
29+
30+ protected function setUp ()
31+ {
32+ $ this ->setUpInvoked = true ;
33+ Loop::set ((new Loop \DriverFactory )->create ());
34+ \gc_collect_cycles (); // extensions using an event loop may otherwise leak the file descriptors to the loop
35+ }
36+
2737 /**
2838 * @codeCoverageIgnore Invoked before code coverage data is being collected.
2939 */
@@ -44,29 +54,32 @@ final public function runAsyncTest(...$args)
4454 {
4555 parent ::setName ($ this ->realTestName );
4656
57+ if (!$ this ->setUpInvoked ) {
58+ $ this ->fail (\sprintf (
59+ '%s::setUp() overrides %s::setUp() without calling the parent method ' ,
60+ \str_replace ("\0" , '@ ' , \get_class ($ this )), // replace NUL-byte in anonymous class name
61+ self ::class
62+ ));
63+ }
64+
4765 $ returnValue = null ;
4866
49- try {
50- $ start = \microtime (true );
67+ $ start = \microtime (true );
5168
52- Loop::run (function () use (&$ returnValue , $ args ) {
53- try {
54- $ returnValue = yield call ([$ this , $ this ->realTestName ], ...$ args );
55- } finally {
56- if (isset ($ this ->timeoutId )) {
57- Loop::cancel ($ this ->timeoutId );
58- }
69+ Loop::run (function () use (&$ returnValue , $ args ) {
70+ try {
71+ $ returnValue = yield call ([$ this , $ this ->realTestName ], ...$ args );
72+ } finally {
73+ if (isset ($ this ->timeoutId )) {
74+ Loop::cancel ($ this ->timeoutId );
5975 }
60- });
61-
62- $ actualRuntime = (int ) (\round (\microtime (true ) - $ start , self ::RUNTIME_PRECISION ) * 1000 );
63- if ($ this ->minimumRuntime > $ actualRuntime ) {
64- $ msg = 'Expected test to take at least %dms but instead took %dms ' ;
65- $ this ->fail (\sprintf ($ msg , $ this ->minimumRuntime , $ actualRuntime ));
6676 }
67- } finally {
68- Loop::set ((new Loop \DriverFactory )->create ());
69- \gc_collect_cycles (); // extensions using an event loop may otherwise leak the file descriptors to the loop
77+ });
78+
79+ $ actualRuntime = (int ) (\round (\microtime (true ) - $ start , self ::RUNTIME_PRECISION ) * 1000 );
80+ if ($ this ->minimumRuntime > $ actualRuntime ) {
81+ $ msg = 'Expected test to take at least %dms but instead took %dms ' ;
82+ $ this ->fail (\sprintf ($ msg , $ this ->minimumRuntime , $ actualRuntime ));
7083 }
7184
7285 return $ returnValue ;
0 commit comments