From 6ab4e330ac032389d370a722e54ee63aafaa9728 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Fri, 23 Oct 2020 11:29:44 +0200 Subject: [PATCH] Use ephemeral port in more server tests Port the main php_cli_server.inc to use ephemeral ports, thus allowing CLI server tests to be parallelized. A complication here is that we also need to give each test a separate doc root, to avoid index.php files writing over each other. Closes GH-6375. --- ext/soap/tests/bug73037.phpt | 2 - ext/soap/tests/custom_content_type.phpt | 2 - ext/standard/tests/streams/bug64433.phpt | 2 - .../tests/url/get_headers_error_003.phpt | 2 - sapi/cli/tests/CONFLICTS | 1 - sapi/cli/tests/bug61977.phpt | 31 +++-- sapi/cli/tests/bug67429_1.phpt | 2 +- sapi/cli/tests/bug67429_2.phpt | 2 +- sapi/cli/tests/bug68291.phpt | 9 +- sapi/cli/tests/bug69655.phpt | 6 +- sapi/cli/tests/php_cli_server.inc | 110 ++++++++++-------- sapi/cli/tests/php_cli_server_002.phpt | 4 +- sapi/cli/tests/php_cli_server_012.phpt | 4 +- sapi/cli/tests/php_cli_server_015.phpt | 7 +- tests/basic/bug67198.phpt | 2 - 15 files changed, 89 insertions(+), 97 deletions(-) delete mode 100644 sapi/cli/tests/CONFLICTS diff --git a/ext/soap/tests/bug73037.phpt b/ext/soap/tests/bug73037.phpt index 4e72932862..8060575bd8 100644 --- a/ext/soap/tests/bug73037.phpt +++ b/ext/soap/tests/bug73037.phpt @@ -1,7 +1,5 @@ --TEST-- Bug #73037 SoapServer reports Bad Request when gzipped, var 0 ---CONFLICTS-- -server --SKIPIF-- ---CONFLICTS-- -server --FILE-- ---CONFLICTS-- -server --FILE-- ', null); +$doc_root = php_cli_server_start('', null)->docRoot; /* * If a Mime Type is added in php_cli_server.c, add it to this array and update @@ -15,32 +15,29 @@ php_cli_server_start('', null); */ $mimetypes = ['html', 'htm', 'svg', 'css', 'js', 'png', 'webm', 'ogv', 'ogg']; -function test_mimetypes($mimetypes) { - foreach ($mimetypes as $mimetype) { - $host = PHP_CLI_SERVER_HOSTNAME; - $fp = php_cli_server_connect(); - if (!$fp) die('Connect failed'); - file_put_contents(__DIR__ . "/foo.{$mimetype}", ''); - $header = <<
", $text; - } + if (fwrite($fp, $header)) { + while (!feof($fp)) { + $text = fgets($fp); + if (strncasecmp("Content-type:", $text, 13) == 0) { + echo "foo.{$mimetype} => ", $text; } - @unlink(__DIR__ . "/foo.{$mimetype}"); - fclose($fp); } + @unlink($doc_root . "/foo.{$mimetype}"); + fclose($fp); } } -test_mimetypes($mimetypes); ?> --EXPECT-- foo.html => Content-Type: text/html; charset=UTF-8 diff --git a/sapi/cli/tests/bug67429_1.phpt b/sapi/cli/tests/bug67429_1.phpt index 5b23818bdb..5519463340 100644 --- a/sapi/cli/tests/bug67429_1.phpt +++ b/sapi/cli/tests/bug67429_1.phpt @@ -8,7 +8,7 @@ include "skipif.inc"; docRoot; +file_put_contents($docRoot . '/bug68291+test.html', 'Found'); echo file_get_contents('http://' . PHP_CLI_SERVER_ADDRESS . '/bug68291+test.html'); -?> ---CLEAN-- - --EXPECT-- Found diff --git a/sapi/cli/tests/bug69655.phpt b/sapi/cli/tests/bug69655.phpt index b5612357f9..4ab53bcbaa 100644 --- a/sapi/cli/tests/bug69655.phpt +++ b/sapi/cli/tests/bug69655.phpt @@ -17,11 +17,11 @@ foreach (['MKCO', 'MKCOLL', 'M'] as $method) { } ?> --EXPECTF-- -Warning: file_get_contents(http://localhost:8964): Failed to open stream: HTTP request failed! HTTP/1.1 501 Not Implemented +Warning: file_get_contents(http://localhost:%d): Failed to open stream: HTTP request failed! HTTP/1.1 501 Not Implemented in %s on line %d -Warning: file_get_contents(http://localhost:8964): Failed to open stream: HTTP request failed! HTTP/1.1 501 Not Implemented +Warning: file_get_contents(http://localhost:%d): Failed to open stream: HTTP request failed! HTTP/1.1 501 Not Implemented in %s on line %d -Warning: file_get_contents(http://localhost:8964): Failed to open stream: HTTP request failed! HTTP/1.1 501 Not Implemented +Warning: file_get_contents(http://localhost:%d): Failed to open stream: HTTP request failed! HTTP/1.1 501 Not Implemented in %s on line %d diff --git a/sapi/cli/tests/php_cli_server.inc b/sapi/cli/tests/php_cli_server.inc index 4cf8705a33..26bdd4c18f 100644 --- a/sapi/cli/tests/php_cli_server.inc +++ b/sapi/cli/tests/php_cli_server.inc @@ -1,22 +1,29 @@ '); } - $cmd = [$php_executable, '-t', $doc_root, '-n', ...$cmd_args, '-S', PHP_CLI_SERVER_ADDRESS]; + $cmd = [$php_executable, '-t', $doc_root, '-n', ...$cmd_args, '-S', 'localhost:0']; if (!is_null($router)) { $cmd[] = $router; } @@ -24,62 +31,58 @@ function php_cli_server_start( $descriptorspec = array( 0 => STDIN, 1 => STDOUT, - 2 => array("null"), + 2 => ['pipe', 'w'], ); $handle = proc_open($cmd, $descriptorspec, $pipes, $doc_root, null, array("suppress_errors" => true)); - // note: here we check the process is running - for ($i=0; $i < 120; $i++) { + // First, wait for the dev server to declare itself ready. + $bound = null; + stream_set_blocking($pipes[2], false); + for ($i = 0; $i < 60; $i++) { + usleep(50000); // 50ms per try $status = proc_get_status($handle); + if (empty($status['running'])) { + echo "Server is not running\n"; + proc_terminate($handle); + exit(1); + } - if (!$status || !$status['running']) { - if ($status && - ($status['running'] == false && $status['exitcode'] != 0)) { - $error = - "Server could not be started\n"; - break; + while (($line = fgets($pipes[2])) !== false) { + if (preg_match('@PHP \S* Development Server \(https?://(.*?:\d+)\) started@', $line, $matches)) { + $bound = $matches[1]; + // Now that we've identified the listen address, close STDERR. + // Otherwise the pipe may clog up with unread log messages. + fclose($pipes[2]); + break 2; } - - usleep(50000); // 50ms per try - continue; } + } + if ($bound === null) { + echo "Server did not output startup message"; + proc_terminate($handle); + exit(1); + } - if ($status['signaled']) { - $error = - "Server was terminated with {$status['termsig']}\n"; + // Now wait for a connection to succeed. + // note: even when server prints 'Listening on localhost:8964...Press Ctrl-C to quit.' + // it might not be listening yet...need to wait until fsockopen() call returns + $error = "Unable to connect to server\n"; + for ($i=0; $i < 60; $i++) { + usleep(50000); // 50ms per try + $status = proc_get_status($handle); + $fp = @fsockopen("tcp://$bound"); + // Failure, the server is no longer running + if (!($status && $status['running'])) { + $error = "Server is not running\n"; break; } - - if ($status['stopped']) { - $error = - "Server was stopped with {$status['stopsig']}\n"; + // Success, Connected to servers + if ($fp) { + $error = ''; break; } - - // note: here we check the server is listening, even when the server prints - // listening on %s:%d - // it may not be ready to accept connections - $start = time(); - - for ($try = 0; $try < 120; $try++) { - $error = @fsockopen( - PHP_CLI_SERVER_HOSTNAME, PHP_CLI_SERVER_PORT) ? - null : - sprintf( - "Server is not accepting connections after %d seconds\n", - time() - $start); - - if (!$error) { - break 2; - } - - usleep(50000); - } - - break; } -php_cli_server_start_error: if ($error) { echo $error; proc_terminate($handle); @@ -87,14 +90,21 @@ php_cli_server_start_error: } register_shutdown_function( - function($handle) use($router) { + function($handle) use($router, $doc_root) { proc_terminate($handle); @unlink(__DIR__ . "/{$router}"); + @rmdir($doc_root); }, $handle ); - return $handle; + // Define the same "constants" we previously did. + $port = (int) substr($bound, strrpos($bound, ':') + 1); + define("PHP_CLI_SERVER_HOSTNAME", "localhost"); + define("PHP_CLI_SERVER_PORT", $port); + define("PHP_CLI_SERVER_ADDRESS", PHP_CLI_SERVER_HOSTNAME.":".PHP_CLI_SERVER_PORT); + + return new CliServerInfo($doc_root); } function php_cli_server_connect() { diff --git a/sapi/cli/tests/php_cli_server_002.phpt b/sapi/cli/tests/php_cli_server_002.phpt index e1fbd90398..2daf6aad73 100644 --- a/sapi/cli/tests/php_cli_server_002.phpt +++ b/sapi/cli/tests/php_cli_server_002.phpt @@ -13,8 +13,8 @@ php_cli_server_start('var_dump($_SERVER["DOCUMENT_ROOT"], $_SERVER["SERVER_SOFTW var_dump(file_get_contents("http://" . PHP_CLI_SERVER_ADDRESS)); ?> --EXPECTF-- -string(%d) "string(%d) "%stests" +string(%d) "string(%d) "%sphp_cli_server_002" string(%d) "PHP %s Development Server" string(%d) "localhost" -string(%d) "8964" +string(%d) "%s" " diff --git a/sapi/cli/tests/php_cli_server_012.phpt b/sapi/cli/tests/php_cli_server_012.phpt index 6262aa2c73..9824c63c40 100644 --- a/sapi/cli/tests/php_cli_server_012.phpt +++ b/sapi/cli/tests/php_cli_server_012.phpt @@ -7,8 +7,8 @@ include "skipif.inc"; --FILE-- docRoot; file_put_contents($doc_root . '/request.php', ''); $host = PHP_CLI_SERVER_HOSTNAME; diff --git a/sapi/cli/tests/php_cli_server_015.phpt b/sapi/cli/tests/php_cli_server_015.phpt index af48758306..5821fdbbc2 100644 --- a/sapi/cli/tests/php_cli_server_015.phpt +++ b/sapi/cli/tests/php_cli_server_015.phpt @@ -9,10 +9,9 @@ display_errors=1 --FILE-- docRoot; -file_put_contents($dir . "/syntax_error.php", ""); +file_put_contents($doc_root . "/syntax_error.php", ""); $output = ''; $host = PHP_CLI_SERVER_HOSTNAME; @@ -30,7 +29,7 @@ HEADER } } echo $output; -@unlink($dir . "/syntax_error.php"); +@unlink($doc_root . "/syntax_error.php"); fclose($fp); ?> --EXPECTF-- diff --git a/tests/basic/bug67198.phpt b/tests/basic/bug67198.phpt index e5ffe3bf6c..c89dfd49da 100644 --- a/tests/basic/bug67198.phpt +++ b/tests/basic/bug67198.phpt @@ -2,8 +2,6 @@ php://input is empty when enable_post_data_reading=Off --INI-- allow_url_fopen=1 ---CONFLICTS-- -server --SKIPIF--