@@ -1886,6 +1886,10 @@ function run_test(string $php, $file, array $env): string
18861886 $ skipCache = new SkipCache ($ enableSkipCache , $ cfg ['keep ' ]['skip ' ]);
18871887 }
18881888
1889+ $ retriable = true ;
1890+ $ retried = false ;
1891+ retry:
1892+
18891893 $ temp_filenames = null ;
18901894 $ org_file = $ file ;
18911895 $ orig_php = $ php ;
@@ -1930,8 +1934,11 @@ function run_test(string $php, $file, array $env): string
19301934
19311935 $ tested = $ test ->getName ();
19321936
1933- if ($ num_repeats > 1 && $ test ->hasSection ('FILE_EXTERNAL ' )) {
1934- return skip_test ($ tested , $ tested_file , $ shortname , 'Test with FILE_EXTERNAL might not be repeatable ' );
1937+ if ($ test ->hasSection ('FILE_EXTERNAL ' )) {
1938+ $ retriable = false ;
1939+ if ($ num_repeats > 1 ) {
1940+ return skip_test ($ tested , $ tested_file , $ shortname , 'Test with FILE_EXTERNAL might not be repeatable ' );
1941+ }
19351942 }
19361943
19371944 if ($ test ->hasSection ('CAPTURE_STDIO ' )) {
@@ -1957,6 +1964,7 @@ function run_test(string $php, $file, array $env): string
19571964 }
19581965 $ php = $ php_cgi . ' -C ' ;
19591966 $ uses_cgi = true ;
1967+ $ retriable = false ;
19601968 if ($ num_repeats > 1 ) {
19611969 return skip_test ($ tested , $ tested_file , $ shortname , 'CGI does not support --repeat ' );
19621970 }
@@ -1974,20 +1982,18 @@ function run_test(string $php, $file, array $env): string
19741982 } else {
19751983 return skip_test ($ tested , $ tested_file , $ shortname , 'phpdbg not available ' );
19761984 }
1985+ $ retriable = false ;
19771986 if ($ num_repeats > 1 ) {
19781987 return skip_test ($ tested , $ tested_file , $ shortname , 'phpdbg does not support --repeat ' );
19791988 }
19801989 }
19811990
1982- if ($ num_repeats > 1 ) {
1983- if ($ test ->hasSection ('CLEAN ' )) {
1984- return skip_test ($ tested , $ tested_file , $ shortname , 'Test with CLEAN might not be repeatable ' );
1985- }
1986- if ($ test ->hasSection ('STDIN ' )) {
1987- return skip_test ($ tested , $ tested_file , $ shortname , 'Test with STDIN might not be repeatable ' );
1988- }
1989- if ($ test ->hasSection ('CAPTURE_STDIO ' )) {
1990- return skip_test ($ tested , $ tested_file , $ shortname , 'Test with CAPTURE_STDIO might not be repeatable ' );
1991+ foreach (['CLEAN ' , 'STDIN ' , 'CAPTURE_STDIO ' ] as $ section ) {
1992+ if ($ test ->hasSection ($ section )) {
1993+ $ retriable = false ;
1994+ if ($ num_repeats > 1 ) {
1995+ return skip_test ($ tested , $ tested_file , $ shortname , "Test with $ section might not be repeatable " );
1996+ }
19911997 }
19921998 }
19931999
@@ -2166,8 +2172,11 @@ function run_test(string $php, $file, array $env): string
21662172 $ ini = preg_replace ('/{MAIL:(\S+)}/ ' , $ replacement , $ ini );
21672173 settings2array (preg_split ("/[ \n\r]+/ " , $ ini ), $ ini_settings );
21682174
2169- if ($ num_repeats > 1 && isset ($ ini_settings ['opcache.opt_debug_level ' ])) {
2170- return skip_test ($ tested , $ tested_file , $ shortname , 'opt_debug_level tests are not repeatable ' );
2175+ if (isset ($ ini_settings ['opcache.opt_debug_level ' ])) {
2176+ $ retriable = false ;
2177+ if ($ num_repeats > 1 ) {
2178+ return skip_test ($ tested , $ tested_file , $ shortname , 'opt_debug_level tests are not repeatable ' );
2179+ }
21712180 }
21722181 }
21732182
@@ -2693,6 +2702,9 @@ function run_test(string $php, $file, array $env): string
26932702 } elseif ($ test ->hasSection ('XLEAK ' )) {
26942703 $ warn = true ;
26952704 $ info = " (warn: XLEAK section but test passes) " ;
2705+ } elseif ($ retried ) {
2706+ $ warn = true ;
2707+ $ info = " (warn: Test passed on retry attempt) " ;
26962708 } else {
26972709 show_result ("PASS " , $ tested , $ tested_file , '' , $ temp_filenames );
26982710 $ junit ->markTestAs ('PASS ' , $ shortname , $ tested );
@@ -2722,6 +2734,9 @@ function run_test(string $php, $file, array $env): string
27222734 } elseif ($ test ->hasSection ('XLEAK ' )) {
27232735 $ warn = true ;
27242736 $ info = " (warn: XLEAK section but test passes) " ;
2737+ } elseif ($ retried ) {
2738+ $ warn = true ;
2739+ $ info = " (warn: Test passed on retry attempt) " ;
27252740 } else {
27262741 show_result ("PASS " , $ tested , $ tested_file , '' , $ temp_filenames );
27272742 $ junit ->markTestAs ('PASS ' , $ shortname , $ tested );
@@ -2732,6 +2747,10 @@ function run_test(string $php, $file, array $env): string
27322747
27332748 $ wanted_re = null ;
27342749 }
2750+ if (!$ passed && !$ retried && $ retriable && error_may_be_retried ($ output )) {
2751+ $ retried = true ;
2752+ goto retry;
2753+ }
27352754
27362755 // Test failed so we need to report details.
27372756 if ($ failed_headers ) {
@@ -2856,6 +2875,11 @@ function run_test(string $php, $file, array $env): string
28562875 return $ restype [0 ] . 'ED ' ;
28572876}
28582877
2878+ function error_may_be_retried (string $ output ): bool
2879+ {
2880+ return preg_match ('((timed out)|(connection refused))i ' , $ output ) === 1 ;
2881+ }
2882+
28592883/**
28602884 * @return bool|int
28612885 */
0 commit comments