1
0
mirror of https://github.com/php/php-src.git synced 2026-03-24 00:02:20 +01:00

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.
This commit is contained in:
Nikita Popov
2020-10-23 11:29:44 +02:00
parent 3859e74347
commit 6ab4e330ac
15 changed files with 92 additions and 100 deletions

View File

@@ -1,7 +1,5 @@
--TEST--
Bug #73037 SoapServer reports Bad Request when gzipped, var 0
--CONFLICTS--
server
--SKIPIF--
<?php
require_once('skipif.inc');

View File

@@ -8,8 +8,6 @@ SOAP customized Content-Type, eg. SwA use case
echo "skip sapi/cli/tests/php_cli_server.inc required but not found";
}
?>
--CONFLICTS--
server
--FILE--
<?php

View File

@@ -9,8 +9,6 @@ if(!$res) {
die("skip could not open cli server script");
}
?>
--CONFLICTS--
server
--FILE--
<?php
include __DIR__."/../../../../sapi/cli/tests/php_cli_server.inc";

View File

@@ -1,7 +1,5 @@
--TEST--
Test get_headers() function : test with context
--CONFLICTS--
server
--FILE--
<?php

View File

@@ -1 +0,0 @@
server

View File

@@ -7,7 +7,7 @@ include "skipif.inc";
--FILE--
<?php
include "php_cli_server.inc";
php_cli_server_start('<?php ?>', null);
$doc_root = php_cli_server_start('<?php ?>', 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('<?php ?>', 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 = <<<HEADER
foreach ($mimetypes as $mimetype) {
$host = PHP_CLI_SERVER_HOSTNAME;
$fp = php_cli_server_connect();
if (!$fp) die('Connect failed');
file_put_contents($doc_root . "/foo.{$mimetype}", '');
$header = <<<HEADER
GET /foo.{$mimetype} HTTP/1.1
Host: {$host}
HEADER;
if (fwrite($fp, $header)) {
while (!feof($fp)) {
$text = fgets($fp);
if (strncasecmp("Content-type:", $text, 13) == 0) {
echo "foo.{$mimetype} => ", $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

View File

@@ -8,7 +8,7 @@ include "skipif.inc";
<?php
include "php_cli_server.inc";
$proc_handle = php_cli_server_start(<<<PHP
php_cli_server_start(<<<PHP
http_response_code(308);
PHP
);

View File

@@ -8,7 +8,7 @@ include "skipif.inc";
<?php
include "php_cli_server.inc";
$proc_handle = php_cli_server_start(<<<PHP
php_cli_server_start(<<<PHP
http_response_code(426);
PHP
);

View File

@@ -9,13 +9,10 @@ include "skipif.inc";
--FILE--
<?php
include "php_cli_server.inc";
file_put_contents(__DIR__ . '/bug68291+test.html', 'Found');
php_cli_server_start(NULL, NULL);
$docRoot = php_cli_server_start(NULL, NULL)->docRoot;
file_put_contents($docRoot . '/bug68291+test.html', 'Found');
echo file_get_contents('http://' . PHP_CLI_SERVER_ADDRESS . '/bug68291+test.html');
?>
--CLEAN--
<?php
@unlink(__DIR__ . '/bug68291+test.html');
@unlink($docRoot . '/bug68291+test.html');
?>
--EXPECT--
Found

View File

@@ -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

View File

@@ -1,22 +1,29 @@
<?php
define("PHP_CLI_SERVER_HOSTNAME", "localhost");
define("PHP_CLI_SERVER_PORT", 8964);
define("PHP_CLI_SERVER_ADDRESS", PHP_CLI_SERVER_HOSTNAME.":".PHP_CLI_SERVER_PORT);
// TODO: Move address/port info in here?
class CliServerInfo {
public function __construct(
public string $docRoot,
) {}
}
function php_cli_server_start(
?string $code = 'echo "Hello world";',
?string $router = 'index.php',
array $cmd_args = []
) {
): CliServerInfo {
$php_executable = getenv('TEST_PHP_EXECUTABLE');
$doc_root = __DIR__;
$error = null;
// Create dedicated doc root to avoid index.php clashes between tests.
$doc_root = __DIR__ . '/' . basename($_SERVER['PHP_SELF'], '.php');
@mkdir($doc_root);
if ($code) {
file_put_contents($doc_root . '/' . ($router ?: 'index.php'), '<?php ' . $code . ' ?>');
}
$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 (!$status || !$status['running']) {
if ($status &&
($status['running'] == false && $status['exitcode'] != 0)) {
$error =
"Server could not be started\n";
break;
}
usleep(50000); // 50ms per try
continue;
if (empty($status['running'])) {
echo "Server is not running\n";
proc_terminate($handle);
exit(1);
}
if ($status['signaled']) {
$error =
"Server was terminated with {$status['termsig']}\n";
break;
}
if ($status['stopped']) {
$error =
"Server was stopped with {$status['stopsig']}\n";
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) {
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);
}
break;
}
if ($bound === null) {
echo "Server did not output startup message";
proc_terminate($handle);
exit(1);
}
// 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;
}
// Success, Connected to servers
if ($fp) {
$error = '';
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() {

View File

@@ -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"
"

View File

@@ -7,8 +7,8 @@ include "skipif.inc";
--FILE--
<?php
include "php_cli_server.inc";
php_cli_server_start('print_r($_REQUEST); $_REQUEST["foo"] = "bar"; return FALSE;');
$doc_root = __DIR__;
$info = php_cli_server_start('print_r($_REQUEST); $_REQUEST["foo"] = "bar"; return FALSE;');
$doc_root = $info->docRoot;
file_put_contents($doc_root . '/request.php', '<?php print_r($_REQUEST); ?>');
$host = PHP_CLI_SERVER_HOSTNAME;

View File

@@ -9,10 +9,9 @@ display_errors=1
--FILE--
<?php
include "php_cli_server.inc";
php_cli_server_start('require("syntax_error.php");');
$dir = realpath(__DIR__);
$doc_root = php_cli_server_start('require("syntax_error.php");')->docRoot;
file_put_contents($dir . "/syntax_error.php", "<?php non_exists_function(); ?>");
file_put_contents($doc_root . "/syntax_error.php", "<?php non_exists_function(); ?>");
$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--

View File

@@ -2,8 +2,6 @@
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";