summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Zend/tests/@CAN_BE_PARALLELISED0
-rw-r--r--Zend/tests/traits/@CAN_BE_PARALLELISED0
-rw-r--r--ext/curl/tests/CONFLICTS1
-rw-r--r--ext/date/tests/@CAN_BE_PARALLELISED0
-rw-r--r--ext/dom/tests/@CAN_BE_PARALLELISED0
-rw-r--r--ext/ftp/tests/CONFLICTS1
-rw-r--r--ext/mysqli/tests/CONFLICTS1
-rw-r--r--ext/opcache/tests/bug66338.phpt2
-rw-r--r--ext/opcache/tests/issue0115.phpt2
-rw-r--r--ext/opcache/tests/issue0149.phpt2
-rw-r--r--ext/opcache/tests/revalidate_path_01.phpt2
-rw-r--r--ext/openssl/tests/CONFLICTS1
-rw-r--r--ext/pcre/tests/@CAN_BE_PARALLELISED0
-rw-r--r--ext/pdo_mysql/tests/CONFLICTS1
-rw-r--r--ext/pdo_pgsql/tests/CONFLICTS1
-rw-r--r--ext/pgsql/tests/CONFLICTS1
-rw-r--r--ext/reflection/tests/@CAN_BE_PARALLELISED0
-rw-r--r--ext/session/tests/CONFLICTS1
-rw-r--r--ext/soap/tests/bug73037.phpt2
-rw-r--r--ext/standard/tests/file/windows_mb_path/CONFLICTS1
-rw-r--r--ext/standard/tests/http/CONFLICTS1
-rw-r--r--ext/standard/tests/math/@CAN_BE_PARALLELISED0
-rw-r--r--ext/standard/tests/serialize/@CAN_BE_PARALLELISED0
-rw-r--r--ext/standard/tests/streams/bug64433.phpt2
-rw-r--r--ext/standard/tests/streams/bug70198.phpt2
-rw-r--r--ext/standard/tests/strings/@CAN_BE_PARALLELISED0
-rw-r--r--ext/standard/tests/url/get_headers_error_003.phpt2
-rwxr-xr-xrun-tests.php138
-rw-r--r--sapi/cli/tests/CONFLICTS1
-rw-r--r--tests/basic/bug67198.phpt2
-rw-r--r--tests/classes/@CAN_BE_PARALLELISED0
-rw-r--r--tests/lang/@CAN_BE_PARALLELISED0
-rw-r--r--tests/security/CONFLICTS1
33 files changed, 98 insertions, 70 deletions
diff --git a/Zend/tests/@CAN_BE_PARALLELISED b/Zend/tests/@CAN_BE_PARALLELISED
deleted file mode 100644
index e69de29bb2..0000000000
--- a/Zend/tests/@CAN_BE_PARALLELISED
+++ /dev/null
diff --git a/Zend/tests/traits/@CAN_BE_PARALLELISED b/Zend/tests/traits/@CAN_BE_PARALLELISED
deleted file mode 100644
index e69de29bb2..0000000000
--- a/Zend/tests/traits/@CAN_BE_PARALLELISED
+++ /dev/null
diff --git a/ext/curl/tests/CONFLICTS b/ext/curl/tests/CONFLICTS
new file mode 100644
index 0000000000..254defddb5
--- /dev/null
+++ b/ext/curl/tests/CONFLICTS
@@ -0,0 +1 @@
+server
diff --git a/ext/date/tests/@CAN_BE_PARALLELISED b/ext/date/tests/@CAN_BE_PARALLELISED
deleted file mode 100644
index e69de29bb2..0000000000
--- a/ext/date/tests/@CAN_BE_PARALLELISED
+++ /dev/null
diff --git a/ext/dom/tests/@CAN_BE_PARALLELISED b/ext/dom/tests/@CAN_BE_PARALLELISED
deleted file mode 100644
index e69de29bb2..0000000000
--- a/ext/dom/tests/@CAN_BE_PARALLELISED
+++ /dev/null
diff --git a/ext/ftp/tests/CONFLICTS b/ext/ftp/tests/CONFLICTS
new file mode 100644
index 0000000000..254defddb5
--- /dev/null
+++ b/ext/ftp/tests/CONFLICTS
@@ -0,0 +1 @@
+server
diff --git a/ext/mysqli/tests/CONFLICTS b/ext/mysqli/tests/CONFLICTS
new file mode 100644
index 0000000000..0eaebf1275
--- /dev/null
+++ b/ext/mysqli/tests/CONFLICTS
@@ -0,0 +1 @@
+mysql
diff --git a/ext/opcache/tests/bug66338.phpt b/ext/opcache/tests/bug66338.phpt
index 8b30391c4f..5cd9693793 100644
--- a/ext/opcache/tests/bug66338.phpt
+++ b/ext/opcache/tests/bug66338.phpt
@@ -4,6 +4,8 @@ Bug #66338 (Optimization binding of class constants is not safely opcacheable)
opcache.enable=0
--SKIPIF--
<?php if (!extension_loaded('Zend OPcache') || php_sapi_name() != "cli") die("skip CLI only"); ?>
+--CONFLICTS--
+server
--FILE--
<?php
$root = str_replace('.php', "", __FILE__);
diff --git a/ext/opcache/tests/issue0115.phpt b/ext/opcache/tests/issue0115.phpt
index 26d99080eb..bc86d0f4fc 100644
--- a/ext/opcache/tests/issue0115.phpt
+++ b/ext/opcache/tests/issue0115.phpt
@@ -8,6 +8,8 @@ phar.readonly=0
<?php require_once('skipif.inc'); ?>
<?php if (!extension_loaded("phar")) die("skip"); ?>
<?php if (php_sapi_name() != "cli") die("skip CLI only"); ?>
+--CONFLICTS--
+server
--FILE--
<?php
$stub = '<?php
diff --git a/ext/opcache/tests/issue0149.phpt b/ext/opcache/tests/issue0149.phpt
index ba57623fce..da3b778ef5 100644
--- a/ext/opcache/tests/issue0149.phpt
+++ b/ext/opcache/tests/issue0149.phpt
@@ -8,6 +8,8 @@ phar.readonly=0
<?php require_once('skipif.inc'); ?>
<?php if (!extension_loaded("phar")) die("skip"); ?>
<?php if (php_sapi_name() != "cli") die("skip CLI only"); ?>
+--CONFLICTS--
+server
--FILE--
<?php
$stub = "<?php header('Content-Type: text/plain;');
diff --git a/ext/opcache/tests/revalidate_path_01.phpt b/ext/opcache/tests/revalidate_path_01.phpt
index 8261633334..b924ba746b 100644
--- a/ext/opcache/tests/revalidate_path_01.phpt
+++ b/ext/opcache/tests/revalidate_path_01.phpt
@@ -7,6 +7,8 @@ opcache.revalidate_path=1
--SKIPIF--
<?php require_once('skipif.inc'); ?>
<?php if (php_sapi_name() != "cli") die("skip CLI only"); ?>
+--CONFLICTS--
+server
--FILE--
<?php
$dir = dirname(__FILE__);
diff --git a/ext/openssl/tests/CONFLICTS b/ext/openssl/tests/CONFLICTS
new file mode 100644
index 0000000000..254defddb5
--- /dev/null
+++ b/ext/openssl/tests/CONFLICTS
@@ -0,0 +1 @@
+server
diff --git a/ext/pcre/tests/@CAN_BE_PARALLELISED b/ext/pcre/tests/@CAN_BE_PARALLELISED
deleted file mode 100644
index e69de29bb2..0000000000
--- a/ext/pcre/tests/@CAN_BE_PARALLELISED
+++ /dev/null
diff --git a/ext/pdo_mysql/tests/CONFLICTS b/ext/pdo_mysql/tests/CONFLICTS
new file mode 100644
index 0000000000..0eaebf1275
--- /dev/null
+++ b/ext/pdo_mysql/tests/CONFLICTS
@@ -0,0 +1 @@
+mysql
diff --git a/ext/pdo_pgsql/tests/CONFLICTS b/ext/pdo_pgsql/tests/CONFLICTS
new file mode 100644
index 0000000000..7ecf66a952
--- /dev/null
+++ b/ext/pdo_pgsql/tests/CONFLICTS
@@ -0,0 +1 @@
+pgsql
diff --git a/ext/pgsql/tests/CONFLICTS b/ext/pgsql/tests/CONFLICTS
new file mode 100644
index 0000000000..7ecf66a952
--- /dev/null
+++ b/ext/pgsql/tests/CONFLICTS
@@ -0,0 +1 @@
+pgsql
diff --git a/ext/reflection/tests/@CAN_BE_PARALLELISED b/ext/reflection/tests/@CAN_BE_PARALLELISED
deleted file mode 100644
index e69de29bb2..0000000000
--- a/ext/reflection/tests/@CAN_BE_PARALLELISED
+++ /dev/null
diff --git a/ext/session/tests/CONFLICTS b/ext/session/tests/CONFLICTS
new file mode 100644
index 0000000000..30888ae480
--- /dev/null
+++ b/ext/session/tests/CONFLICTS
@@ -0,0 +1 @@
+session
diff --git a/ext/soap/tests/bug73037.phpt b/ext/soap/tests/bug73037.phpt
index 4ceb694aea..0a4271f356 100644
--- a/ext/soap/tests/bug73037.phpt
+++ b/ext/soap/tests/bug73037.phpt
@@ -1,5 +1,7 @@
--TEST--
Bug #73037 SoapServer reports Bad Request when gzipped, var 0
+--CONFLICTS--
+server
--SKIPIF--
<?php
require_once('skipif.inc');
diff --git a/ext/standard/tests/file/windows_mb_path/CONFLICTS b/ext/standard/tests/file/windows_mb_path/CONFLICTS
new file mode 100644
index 0000000000..1d0dfe69be
--- /dev/null
+++ b/ext/standard/tests/file/windows_mb_path/CONFLICTS
@@ -0,0 +1 @@
+windows_mb_path
diff --git a/ext/standard/tests/http/CONFLICTS b/ext/standard/tests/http/CONFLICTS
new file mode 100644
index 0000000000..254defddb5
--- /dev/null
+++ b/ext/standard/tests/http/CONFLICTS
@@ -0,0 +1 @@
+server
diff --git a/ext/standard/tests/math/@CAN_BE_PARALLELISED b/ext/standard/tests/math/@CAN_BE_PARALLELISED
deleted file mode 100644
index e69de29bb2..0000000000
--- a/ext/standard/tests/math/@CAN_BE_PARALLELISED
+++ /dev/null
diff --git a/ext/standard/tests/serialize/@CAN_BE_PARALLELISED b/ext/standard/tests/serialize/@CAN_BE_PARALLELISED
deleted file mode 100644
index e69de29bb2..0000000000
--- a/ext/standard/tests/serialize/@CAN_BE_PARALLELISED
+++ /dev/null
diff --git a/ext/standard/tests/streams/bug64433.phpt b/ext/standard/tests/streams/bug64433.phpt
index 1fbc049960..897947f453 100644
--- a/ext/standard/tests/streams/bug64433.phpt
+++ b/ext/standard/tests/streams/bug64433.phpt
@@ -9,6 +9,8 @@ if(!$res) {
die("skip could not open cli server script");
}
?>
+--CONFLICTS--
+server
--FILE--
<?php
include dirname(__FILE__)."/../../../../sapi/cli/tests/php_cli_server.inc";
diff --git a/ext/standard/tests/streams/bug70198.phpt b/ext/standard/tests/streams/bug70198.phpt
index f79a3d03c4..7b4b8cc16d 100644
--- a/ext/standard/tests/streams/bug70198.phpt
+++ b/ext/standard/tests/streams/bug70198.phpt
@@ -4,6 +4,8 @@ Bug #70198 Checking liveness does not work as expected
<?php
if (getenv("SKIP_SLOW_TESTS")) die("skip slow test");
?>
+--CONFLICTS--
+server
--FILE--
<?php
diff --git a/ext/standard/tests/strings/@CAN_BE_PARALLELISED b/ext/standard/tests/strings/@CAN_BE_PARALLELISED
deleted file mode 100644
index e69de29bb2..0000000000
--- a/ext/standard/tests/strings/@CAN_BE_PARALLELISED
+++ /dev/null
diff --git a/ext/standard/tests/url/get_headers_error_003.phpt b/ext/standard/tests/url/get_headers_error_003.phpt
index c65305af2c..8a50e3bc8a 100644
--- a/ext/standard/tests/url/get_headers_error_003.phpt
+++ b/ext/standard/tests/url/get_headers_error_003.phpt
@@ -1,5 +1,7 @@
--TEST--
Test get_headers() function : test with context
+--CONFLICTS--
+server
--FILE--
<?php
diff --git a/run-tests.php b/run-tests.php
index b9e14f373c..3221766c1a 100755
--- a/run-tests.php
+++ b/run-tests.php
@@ -1348,73 +1348,37 @@ function run_all_tests_parallel($test_files, $env, $redir_tested) {
echo "====⚡️==== WELCOME TO THE FUTURE: run-tests PARALLEL EDITION ====⚡️====\n";
echo "====⚡️===========================================================⚡️====\n";
- // Because some of the PHP test suite has not been written with
- // parallel execution in mind, it is not safe to just run any two tests
- // concurrently.
- // Therefore, we divide the test set into directories and test multiple
- // directories at once, but not multiple tests within them.
-
- $testDirsToGo = [];
-
+ // Each test may specify a list of conflict keys. While a test that conflicts with
+ // key K is running, no other test that conflicts with K may run. Conflict keys are
+ // specified either in the --CONFLICTS-- section, or CONFLICTS file inside a directory.
+ $dirConflictsWith = [];
+ $fileConflictsWith = [];
foreach ($test_files as $file) {
- $dirSeparator = strrpos($file, DIRECTORY_SEPARATOR);
- if ($dirSeparator !== FALSE) {
- $testDirsToGo[substr($file, 0, $dirSeparator)][] = $file;
+ $contents = file_get_contents($file);
+ if (preg_match('/^--CONFLICTS--(.+?)^--/ms', $contents, $matches)) {
+ $conflicts = array_map('trim', explode("\n", trim($matches[1])));
} else {
- $testDirsToGo[""][] = $file;
- }
- }
-
- // We assume most test directories should be executed in serial, but for
- // big directories, this would waste time if they can actually be parallel.
- // Therefore, if a directory has a special '@CAN_BE_PARALLELISED' file, we
- // will divide it up into smaller “directories” automatically.
- foreach ($testDirsToGo as $dir => $tests) {
- if (count($tests) < 64 || !is_string($dir)) {
- continue;
- }
- if (file_exists($dir . DIRECTORY_SEPARATOR . '@CAN_BE_PARALLELISED')) {
- foreach (array_chunk($tests, 64) as $testsChunk) {
- $testDirsToGo[] = $testsChunk;
+ // Cache per-directory conflicts in a separate map, so we compute these only once.
+ $dir = dirname($file);
+ if (!isset($dirConflictsWith[$dir])) {
+ $dirConflicts = [];
+ if (file_exists($dir . '/CONFLICTS')) {
+ $contents = file_get_contents($dir . '/CONFLICTS');
+ $dirConflicts = array_map('trim', explode("\n", trim($contents)));
+ }
+ $dirConflictsWith[$dir] = $dirConflicts;
}
- unset($testDirsToGo[$dir]);
+ $conflicts = $dirConflictsWith[$dir];
}
- }
-
- // Sort test dirs so the biggest ones are handled first, so we spend less
- // time waiting on workers tasked with very large dirs.
- // This is an ascending sort because items are popped off the end.
- // Thank you Rasmus for this idea :)
- uasort($testDirsToGo, function ($a, $b) {
- return count($a) <=> count($b);
- });
-
- $testDirsInProgress = 0;
-
- echo "Isolated ", count($testDirsToGo), " directories to be tested in parallel.\n";
-
- $shamedDirs = array_reverse(array_filter($testDirsToGo, function ($files) {
- return count($files) > 100;
- }), true);
- if ($shamedDirs) {
- $shameList = "";
- foreach ($shamedDirs as $dir => $shame) {
- $shameList .= "\n$dir: " . count($shame) . " files";
- }
-
- echo <<<NAME_AND_SHAME
-----⚠️-----------------------------------------------------------⚠️----
-To effectively utilise parallelism, test directories should not contain
-large numbers of tests that can't be run simultaneously. The following
-directories contain more than 100 test files and do not contain a
-'@CAN_BE_PARALLELISED' file:
-$shameList
-----⚠️-----------------------------------------------------------⚠️----
-
-NAME_AND_SHAME;
+ $fileConflictsWith[$file] = $conflicts;
}
+ // Some tests assume that they are executed in a certain order. We will be popping from
+ // $test_files, so reverse its order here. This makes sure that order is preserved at least
+ // for tests with a common conflict key.
+ $test_files = array_reverse($test_files);
+
echo "Spawning workers… ";
// We use sockets rather than STDIN/STDOUT for comms because on Windows,
@@ -1500,9 +1464,15 @@ NAME_AND_SHAME;
echo "\n";
$rawMessageBuffers = [];
+ $testsInProgress = 0;
+
+ // Map from conflict key to worker ID.
+ $activeConflicts = [];
+ // Tests waiting due to conflicts. Map from conflict key to array.
+ $waitingTests = [];
escape:
- while ($testDirsToGo || ($testDirsInProgress > 0)) {
+ while ($test_files || $testsInProgress > 0) {
$toRead = array_values($workerSocks);
$toWrite = NULL;
$toExcept = NULL;
@@ -1532,15 +1502,43 @@ escape:
}
switch ($message["type"]) {
- case "dir_finished":
- $testDirsInProgress--;
+ case "tests_finished":
+ $testsInProgress--;
+ foreach ($activeConflicts as $key => $workerId) {
+ if ($workerId === $i) {
+ unset($activeConflicts[$key]);
+ if (isset($waitingTests[$key])) {
+ while ($test = array_pop($waitingTests[$key])) {
+ $test_files[] = $test;
+ }
+ unset($waitingTests[$key]);
+ }
+ }
+ }
// intentional fall-through
case "ready":
- if ($testDir = array_pop($testDirsToGo)) {
- $testDirsInProgress++;
+ // Batch multiple tests to reduce communication overhead.
+ $files = [];
+ $batchSize = 32;
+ while (count($files) <= $batchSize && $file = array_pop($test_files)) {
+ foreach ($fileConflictsWith[$file] as $conflictKey) {
+ if (isset($activeConflicts[$conflictKey])) {
+ $waitingTests[$conflictKey][] = $file;
+ continue 2;
+ }
+ }
+ $files[] = $file;
+ }
+ if ($files) {
+ foreach ($files as $file) {
+ foreach ($fileConflictsWith[$file] as $conflictKey) {
+ $activeConflicts[$conflictKey] = $i;
+ }
+ }
+ $testsInProgress++;
send_message($workerSocks[$i], [
"type" => "run_tests",
- "test_files" => $testDir,
+ "test_files" => $files,
"env" => $env,
"redir_tested" => $redir_tested
]);
@@ -1609,8 +1607,8 @@ escape:
kill_children($workerProcs);
- if ($testDirsInProgress < 0) {
- error("$testDirsInProgress test directories “in progress”, which is less than zero. THIS SHOULD NOT HAPPEN.");
+ if ($testsInProgress < 0) {
+ error("$testsInProgress test batches “in progress”, which is less than zero. THIS SHOULD NOT HAPPEN.");
}
}
@@ -1677,7 +1675,7 @@ function run_worker() {
case "run_tests":
run_all_tests($command["test_files"], $command["env"], $command["redir_tested"]);
send_message($workerSock, [
- "type" => "dir_finished"
+ "type" => "tests_finished"
]);
break;
default:
@@ -1793,7 +1791,7 @@ TEST $file
'CAPTURE_STDIO', 'STDIN', 'CGI', 'PHPDBG',
'INI', 'ENV', 'EXTENSIONS',
'SKIPIF', 'XFAIL', 'CLEAN',
- 'CREDITS', 'DESCRIPTION',
+ 'CREDITS', 'DESCRIPTION', 'CONFLICTS',
))) {
$bork_info = 'Unknown section "' . $section . '"';
}
diff --git a/sapi/cli/tests/CONFLICTS b/sapi/cli/tests/CONFLICTS
new file mode 100644
index 0000000000..254defddb5
--- /dev/null
+++ b/sapi/cli/tests/CONFLICTS
@@ -0,0 +1 @@
+server
diff --git a/tests/basic/bug67198.phpt b/tests/basic/bug67198.phpt
index 4c2322b6de..184916197b 100644
--- a/tests/basic/bug67198.phpt
+++ b/tests/basic/bug67198.phpt
@@ -2,6 +2,8 @@
php://input is empty when enable_post_data_reading=Off
--INI--
allow_url_fopen=1
+--CONFLICTS--
+server
--SKIPIF--
<?php
include __DIR__."/../../sapi/cli/tests/skipif.inc";
diff --git a/tests/classes/@CAN_BE_PARALLELISED b/tests/classes/@CAN_BE_PARALLELISED
deleted file mode 100644
index e69de29bb2..0000000000
--- a/tests/classes/@CAN_BE_PARALLELISED
+++ /dev/null
diff --git a/tests/lang/@CAN_BE_PARALLELISED b/tests/lang/@CAN_BE_PARALLELISED
deleted file mode 100644
index e69de29bb2..0000000000
--- a/tests/lang/@CAN_BE_PARALLELISED
+++ /dev/null
diff --git a/tests/security/CONFLICTS b/tests/security/CONFLICTS
new file mode 100644
index 0000000000..84eb3cfb06
--- /dev/null
+++ b/tests/security/CONFLICTS
@@ -0,0 +1 @@
+open_basedir