diff --git a/php-transformer/tests/run.php b/php-transformer/tests/run.php index ad1484b22..b86c9efc6 100644 --- a/php-transformer/tests/run.php +++ b/php-transformer/tests/run.php @@ -4,7 +4,8 @@ * * Each script is its own process and signals failure with a nonzero exit * code. Files ending in `-fixture.php` are builders that tests require, not - * tests, and are skipped. + * tests, and are skipped. Files ending in `-scaling.php` compare their own + * timings, so they run one at a time after the parallel batch. * * Usage: php tests/run.php [--jobs=N] [dir ...] * Defaults: tests/contract tests/unit, one job per CPU. @@ -34,38 +35,53 @@ } } sort($tests); +$scaling = array_values(array_filter($tests, static fn (string $test): bool => str_ends_with($test, '-scaling.php'))); -$queue = $tests; -$running = array(); -$failures = array(); -$durations = array(); -$started = microtime(true); - -while ( array() !== $queue || array() !== $running ) { - while ( count($running) < $jobs && array() !== $queue ) { - $test = array_shift($queue); - $log = tmpfile(); - $process = proc_open(array(PHP_BINARY, $test), array(0 => array('file', '/dev/null', 'r'), 1 => $log, 2 => $log), $pipes, $root); - $running[] = array('test' => $test, 'process' => $process, 'log' => $log, 'start' => microtime(true)); - } - foreach ( $running as $index => $job ) { - $status = proc_get_status($job['process']); - if ( $status['running'] ) { - continue; +/** + * Runs the tests with at most $jobs at once. + * + * @param list $tests + * @return array{0: array, 1: array} Durations and failure output, keyed by test. + */ +function run_tests(array $tests, int $jobs, string $root): array +{ + $running = array(); + $failures = array(); + $durations = array(); + while ( array() !== $tests || array() !== $running ) { + while ( count($running) < $jobs && array() !== $tests ) { + $test = array_shift($tests); + $log = tmpfile(); + $process = proc_open(array(PHP_BINARY, $test), array(0 => array('file', '/dev/null', 'r'), 1 => $log, 2 => $log), $pipes, $root); + $running[] = array('test' => $test, 'process' => $process, 'log' => $log, 'start' => microtime(true)); } - proc_close($job['process']); - $durations[$job['test']] = microtime(true) - $job['start']; - if ( 0 !== $status['exitcode'] ) { - rewind($job['log']); - $failures[$job['test']] = (string) stream_get_contents($job['log']); - fwrite(STDERR, "FAIL {$job['test']}\n"); + foreach ( $running as $index => $job ) { + $status = proc_get_status($job['process']); + if ( $status['running'] ) { + continue; + } + proc_close($job['process']); + $durations[$job['test']] = microtime(true) - $job['start']; + if ( 0 !== $status['exitcode'] ) { + rewind($job['log']); + $failures[$job['test']] = (string) stream_get_contents($job['log']); + fwrite(STDERR, "FAIL {$job['test']}\n"); + } + fclose($job['log']); + unset($running[$index]); } - fclose($job['log']); - unset($running[$index]); + usleep(20000); } - usleep(20000); + + return array($durations, $failures); } +$started = microtime(true); +[$durations, $failures] = run_tests(array_values(array_diff($tests, $scaling)), $jobs, $root); +[$scalingDurations, $scalingFailures] = run_tests($scaling, 1, $root); +$durations += $scalingDurations; +$failures += $scalingFailures; + arsort($durations); echo "Slowest:\n"; foreach ( array_slice($durations, 0, 5, true) as $test => $seconds ) {