@@ -1851,11 +1851,16 @@ function run_test(string $php, $file, array $env): string
1851
1851
$ skipCache = new SkipCache ($ enableSkipCache , $ cfg ['keep ' ]['skip ' ]);
1852
1852
}
1853
1853
1854
+ $ orig_php = $ php ;
1855
+ $ php = escapeshellarg ($ php );
1856
+
1857
+ $ retriable = true ;
1858
+ $ retried = false ;
1859
+ retry:
1860
+
1854
1861
$ temp_filenames = null ;
1855
1862
$ org_file = $ file ;
1856
- $ orig_php = $ php ;
1857
1863
1858
- $ php = escapeshellarg ($ php );
1859
1864
$ php_cgi = $ env ['TEST_PHP_CGI_EXECUTABLE ' ] ?? null ;
1860
1865
$ phpdbg = $ env ['TEST_PHPDBG_EXECUTABLE ' ] ?? null ;
1861
1866
@@ -1891,8 +1896,11 @@ function run_test(string $php, $file, array $env): string
1891
1896
1892
1897
$ tested = $ test ->getName ();
1893
1898
1894
- if ($ num_repeats > 1 && $ test ->hasSection ('FILE_EXTERNAL ' )) {
1895
- return skip_test ($ tested , $ tested_file , $ shortname , 'Test with FILE_EXTERNAL might not be repeatable ' );
1899
+ if ($ test ->hasSection ('FILE_EXTERNAL ' )) {
1900
+ $ retriable = false ;
1901
+ if ($ num_repeats > 1 ) {
1902
+ return skip_test ($ tested , $ tested_file , $ shortname , 'Test with FILE_EXTERNAL might not be repeatable ' );
1903
+ }
1896
1904
}
1897
1905
1898
1906
if ($ test ->hasSection ('CAPTURE_STDIO ' )) {
@@ -1918,6 +1926,7 @@ function run_test(string $php, $file, array $env): string
1918
1926
}
1919
1927
$ php = escapeshellarg ($ php_cgi ) . ' -C ' ;
1920
1928
$ uses_cgi = true ;
1929
+ $ retriable = false ;
1921
1930
if ($ num_repeats > 1 ) {
1922
1931
return skip_test ($ tested , $ tested_file , $ shortname , 'CGI does not support --repeat ' );
1923
1932
}
@@ -1935,20 +1944,18 @@ function run_test(string $php, $file, array $env): string
1935
1944
} else {
1936
1945
return skip_test ($ tested , $ tested_file , $ shortname , 'phpdbg not available ' );
1937
1946
}
1947
+ $ retriable = false ;
1938
1948
if ($ num_repeats > 1 ) {
1939
1949
return skip_test ($ tested , $ tested_file , $ shortname , 'phpdbg does not support --repeat ' );
1940
1950
}
1941
1951
}
1942
1952
1943
- if ($ num_repeats > 1 ) {
1944
- if ($ test ->hasSection ('CLEAN ' )) {
1945
- return skip_test ($ tested , $ tested_file , $ shortname , 'Test with CLEAN might not be repeatable ' );
1946
- }
1947
- if ($ test ->hasSection ('STDIN ' )) {
1948
- return skip_test ($ tested , $ tested_file , $ shortname , 'Test with STDIN might not be repeatable ' );
1949
- }
1950
- if ($ test ->hasSection ('CAPTURE_STDIO ' )) {
1951
- return skip_test ($ tested , $ tested_file , $ shortname , 'Test with CAPTURE_STDIO might not be repeatable ' );
1953
+ foreach (['CLEAN ' , 'STDIN ' , 'CAPTURE_STDIO ' ] as $ section ) {
1954
+ if ($ test ->hasSection ($ section )) {
1955
+ $ retriable = false ;
1956
+ if ($ num_repeats > 1 ) {
1957
+ return skip_test ($ tested , $ tested_file , $ shortname , "Test with $ section might not be repeatable " );
1958
+ }
1952
1959
}
1953
1960
}
1954
1961
@@ -2140,8 +2147,11 @@ function run_test(string $php, $file, array $env): string
2140
2147
}
2141
2148
settings2array (preg_split ("/[ \n\r]+/ " , $ ini ), $ ini_settings );
2142
2149
2143
- if ($ num_repeats > 1 && isset ($ ini_settings ['opcache.opt_debug_level ' ])) {
2144
- return skip_test ($ tested , $ tested_file , $ shortname , 'opt_debug_level tests are not repeatable ' );
2150
+ if (isset ($ ini_settings ['opcache.opt_debug_level ' ])) {
2151
+ $ retriable = false ;
2152
+ if ($ num_repeats > 1 ) {
2153
+ return skip_test ($ tested , $ tested_file , $ shortname , 'opt_debug_level tests are not repeatable ' );
2154
+ }
2145
2155
}
2146
2156
}
2147
2157
@@ -2640,6 +2650,10 @@ function run_test(string $php, $file, array $env): string
2640
2650
2641
2651
$ wanted_re = null ;
2642
2652
}
2653
+ if (!$ passed && !$ retried && $ retriable && error_may_be_retried ($ output )) {
2654
+ $ retried = true ;
2655
+ goto retry;
2656
+ }
2643
2657
2644
2658
if ($ passed ) {
2645
2659
if (!$ cfg ['keep ' ]['php ' ] && !$ leaked ) {
@@ -2671,6 +2685,9 @@ function run_test(string $php, $file, array $env): string
2671
2685
// XLEAK with ASAN completely disables LSAN so the test is expected to pass
2672
2686
$ warn = true ;
2673
2687
$ info = " (warn: XLEAK section but test passes) " ;
2688
+ } elseif ($ retried ) {
2689
+ $ warn = true ;
2690
+ $ info = " (warn: Test passed on retry attempt) " ;
2674
2691
} else {
2675
2692
show_result ("PASS " , $ tested , $ tested_file , '' , $ temp_filenames );
2676
2693
$ junit ->markTestAs ('PASS ' , $ shortname , $ tested );
@@ -2815,6 +2832,11 @@ function run_test(string $php, $file, array $env): string
2815
2832
return $ restype [0 ] . 'ED ' ;
2816
2833
}
2817
2834
2835
+ function error_may_be_retried (string $ output ): bool
2836
+ {
2837
+ return preg_match ('((timed out)|(connection refused))i ' , $ output ) === 1 ;
2838
+ }
2839
+
2818
2840
function expectf_to_regex (?string $ wanted ): string
2819
2841
{
2820
2842
$ wanted_re = $ wanted ?? '' ;
0 commit comments