Skip to content

Commit 6ab4e33

Browse files
committed
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.
1 parent 3859e74 commit 6ab4e33

15 files changed

+89
-97
lines changed

ext/soap/tests/bug73037.phpt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
--TEST--
22
Bug #73037 SoapServer reports Bad Request when gzipped, var 0
3-
--CONFLICTS--
4-
server
53
--SKIPIF--
64
<?php
75
require_once('skipif.inc');

ext/soap/tests/custom_content_type.phpt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@ SOAP customized Content-Type, eg. SwA use case
88
echo "skip sapi/cli/tests/php_cli_server.inc required but not found";
99
}
1010
?>
11-
--CONFLICTS--
12-
server
1311
--FILE--
1412
<?php
1513

ext/standard/tests/streams/bug64433.phpt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@ if(!$res) {
99
die("skip could not open cli server script");
1010
}
1111
?>
12-
--CONFLICTS--
13-
server
1412
--FILE--
1513
<?php
1614
include __DIR__."/../../../../sapi/cli/tests/php_cli_server.inc";

ext/standard/tests/url/get_headers_error_003.phpt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
--TEST--
22
Test get_headers() function : test with context
3-
--CONFLICTS--
4-
server
53
--FILE--
64
<?php
75

sapi/cli/tests/CONFLICTS

Lines changed: 0 additions & 1 deletion
This file was deleted.

sapi/cli/tests/bug61977.phpt

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,40 +7,37 @@ include "skipif.inc";
77
--FILE--
88
<?php
99
include "php_cli_server.inc";
10-
php_cli_server_start('<?php ?>', null);
10+
$doc_root = php_cli_server_start('<?php ?>', null)->docRoot;
1111

1212
/*
1313
* If a Mime Type is added in php_cli_server.c, add it to this array and update
1414
* the EXPECTF section accordingly
1515
*/
1616
$mimetypes = ['html', 'htm', 'svg', 'css', 'js', 'png', 'webm', 'ogv', 'ogg'];
1717

18-
function test_mimetypes($mimetypes) {
19-
foreach ($mimetypes as $mimetype) {
20-
$host = PHP_CLI_SERVER_HOSTNAME;
21-
$fp = php_cli_server_connect();
22-
if (!$fp) die('Connect failed');
23-
file_put_contents(__DIR__ . "/foo.{$mimetype}", '');
24-
$header = <<<HEADER
18+
foreach ($mimetypes as $mimetype) {
19+
$host = PHP_CLI_SERVER_HOSTNAME;
20+
$fp = php_cli_server_connect();
21+
if (!$fp) die('Connect failed');
22+
file_put_contents($doc_root . "/foo.{$mimetype}", '');
23+
$header = <<<HEADER
2524
GET /foo.{$mimetype} HTTP/1.1
2625
Host: {$host}
2726
2827
2928
HEADER;
30-
if (fwrite($fp, $header)) {
31-
while (!feof($fp)) {
32-
$text = fgets($fp);
33-
if (strncasecmp("Content-type:", $text, 13) == 0) {
34-
echo "foo.{$mimetype} => ", $text;
35-
}
29+
if (fwrite($fp, $header)) {
30+
while (!feof($fp)) {
31+
$text = fgets($fp);
32+
if (strncasecmp("Content-type:", $text, 13) == 0) {
33+
echo "foo.{$mimetype} => ", $text;
3634
}
37-
@unlink(__DIR__ . "/foo.{$mimetype}");
38-
fclose($fp);
3935
}
36+
@unlink($doc_root . "/foo.{$mimetype}");
37+
fclose($fp);
4038
}
4139
}
4240

43-
test_mimetypes($mimetypes);
4441
?>
4542
--EXPECT--
4643
foo.html => Content-Type: text/html; charset=UTF-8

sapi/cli/tests/bug67429_1.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ include "skipif.inc";
88
<?php
99
include "php_cli_server.inc";
1010

11-
$proc_handle = php_cli_server_start(<<<PHP
11+
php_cli_server_start(<<<PHP
1212
http_response_code(308);
1313
PHP
1414
);

sapi/cli/tests/bug67429_2.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ include "skipif.inc";
88
<?php
99
include "php_cli_server.inc";
1010

11-
$proc_handle = php_cli_server_start(<<<PHP
11+
php_cli_server_start(<<<PHP
1212
http_response_code(426);
1313
PHP
1414
);

sapi/cli/tests/bug68291.phpt

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,10 @@ include "skipif.inc";
99
--FILE--
1010
<?php
1111
include "php_cli_server.inc";
12-
file_put_contents(__DIR__ . '/bug68291+test.html', 'Found');
13-
php_cli_server_start(NULL, NULL);
12+
$docRoot = php_cli_server_start(NULL, NULL)->docRoot;
13+
file_put_contents($docRoot . '/bug68291+test.html', 'Found');
1414
echo file_get_contents('http://' . PHP_CLI_SERVER_ADDRESS . '/bug68291+test.html');
15-
?>
16-
--CLEAN--
17-
<?php
18-
@unlink(__DIR__ . '/bug68291+test.html');
15+
@unlink($docRoot . '/bug68291+test.html');
1916
?>
2017
--EXPECT--
2118
Found

sapi/cli/tests/bug69655.phpt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,11 @@ foreach (['MKCO', 'MKCOLL', 'M'] as $method) {
1717
}
1818
?>
1919
--EXPECTF--
20-
Warning: file_get_contents(http://localhost:8964): Failed to open stream: HTTP request failed! HTTP/1.1 501 Not Implemented
20+
Warning: file_get_contents(http://localhost:%d): Failed to open stream: HTTP request failed! HTTP/1.1 501 Not Implemented
2121
in %s on line %d
2222

23-
Warning: file_get_contents(http://localhost:8964): Failed to open stream: HTTP request failed! HTTP/1.1 501 Not Implemented
23+
Warning: file_get_contents(http://localhost:%d): Failed to open stream: HTTP request failed! HTTP/1.1 501 Not Implemented
2424
in %s on line %d
2525

26-
Warning: file_get_contents(http://localhost:8964): Failed to open stream: HTTP request failed! HTTP/1.1 501 Not Implemented
26+
Warning: file_get_contents(http://localhost:%d): Failed to open stream: HTTP request failed! HTTP/1.1 501 Not Implemented
2727
in %s on line %d

sapi/cli/tests/php_cli_server.inc

Lines changed: 60 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,100 +1,110 @@
11
<?php
2-
define("PHP_CLI_SERVER_HOSTNAME", "localhost");
3-
define("PHP_CLI_SERVER_PORT", 8964);
4-
define("PHP_CLI_SERVER_ADDRESS", PHP_CLI_SERVER_HOSTNAME.":".PHP_CLI_SERVER_PORT);
2+
3+
// TODO: Move address/port info in here?
4+
class CliServerInfo {
5+
public function __construct(
6+
public string $docRoot,
7+
) {}
8+
}
59

610
function php_cli_server_start(
711
?string $code = 'echo "Hello world";',
812
?string $router = 'index.php',
913
array $cmd_args = []
10-
) {
14+
): CliServerInfo {
1115
$php_executable = getenv('TEST_PHP_EXECUTABLE');
12-
$doc_root = __DIR__;
1316
$error = null;
1417

18+
// Create dedicated doc root to avoid index.php clashes between tests.
19+
$doc_root = __DIR__ . '/' . basename($_SERVER['PHP_SELF'], '.php');
20+
@mkdir($doc_root);
21+
1522
if ($code) {
1623
file_put_contents($doc_root . '/' . ($router ?: 'index.php'), '<?php ' . $code . ' ?>');
1724
}
1825

19-
$cmd = [$php_executable, '-t', $doc_root, '-n', ...$cmd_args, '-S', PHP_CLI_SERVER_ADDRESS];
26+
$cmd = [$php_executable, '-t', $doc_root, '-n', ...$cmd_args, '-S', 'localhost:0'];
2027
if (!is_null($router)) {
2128
$cmd[] = $router;
2229
}
2330

2431
$descriptorspec = array(
2532
0 => STDIN,
2633
1 => STDOUT,
27-
2 => array("null"),
34+
2 => ['pipe', 'w'],
2835
);
2936
$handle = proc_open($cmd, $descriptorspec, $pipes, $doc_root, null, array("suppress_errors" => true));
3037

31-
// note: here we check the process is running
32-
for ($i=0; $i < 120; $i++) {
38+
// First, wait for the dev server to declare itself ready.
39+
$bound = null;
40+
stream_set_blocking($pipes[2], false);
41+
for ($i = 0; $i < 60; $i++) {
42+
usleep(50000); // 50ms per try
3343
$status = proc_get_status($handle);
44+
if (empty($status['running'])) {
45+
echo "Server is not running\n";
46+
proc_terminate($handle);
47+
exit(1);
48+
}
3449

35-
if (!$status || !$status['running']) {
36-
if ($status &&
37-
($status['running'] == false && $status['exitcode'] != 0)) {
38-
$error =
39-
"Server could not be started\n";
40-
break;
50+
while (($line = fgets($pipes[2])) !== false) {
51+
if (preg_match('@PHP \S* Development Server \(https?://(.*?:\d+)\) started@', $line, $matches)) {
52+
$bound = $matches[1];
53+
// Now that we've identified the listen address, close STDERR.
54+
// Otherwise the pipe may clog up with unread log messages.
55+
fclose($pipes[2]);
56+
break 2;
4157
}
42-
43-
usleep(50000); // 50ms per try
44-
continue;
4558
}
59+
}
60+
if ($bound === null) {
61+
echo "Server did not output startup message";
62+
proc_terminate($handle);
63+
exit(1);
64+
}
4665

47-
if ($status['signaled']) {
48-
$error =
49-
"Server was terminated with {$status['termsig']}\n";
66+
// Now wait for a connection to succeed.
67+
// note: even when server prints 'Listening on localhost:8964...Press Ctrl-C to quit.'
68+
// it might not be listening yet...need to wait until fsockopen() call returns
69+
$error = "Unable to connect to server\n";
70+
for ($i=0; $i < 60; $i++) {
71+
usleep(50000); // 50ms per try
72+
$status = proc_get_status($handle);
73+
$fp = @fsockopen("tcp://$bound");
74+
// Failure, the server is no longer running
75+
if (!($status && $status['running'])) {
76+
$error = "Server is not running\n";
5077
break;
5178
}
52-
53-
if ($status['stopped']) {
54-
$error =
55-
"Server was stopped with {$status['stopsig']}\n";
79+
// Success, Connected to servers
80+
if ($fp) {
81+
$error = '';
5682
break;
5783
}
58-
59-
// note: here we check the server is listening, even when the server prints
60-
// listening on %s:%d
61-
// it may not be ready to accept connections
62-
$start = time();
63-
64-
for ($try = 0; $try < 120; $try++) {
65-
$error = @fsockopen(
66-
PHP_CLI_SERVER_HOSTNAME, PHP_CLI_SERVER_PORT) ?
67-
null :
68-
sprintf(
69-
"Server is not accepting connections after %d seconds\n",
70-
time() - $start);
71-
72-
if (!$error) {
73-
break 2;
74-
}
75-
76-
usleep(50000);
77-
}
78-
79-
break;
8084
}
8185

82-
php_cli_server_start_error:
8386
if ($error) {
8487
echo $error;
8588
proc_terminate($handle);
8689
exit(1);
8790
}
8891

8992
register_shutdown_function(
90-
function($handle) use($router) {
93+
function($handle) use($router, $doc_root) {
9194
proc_terminate($handle);
9295
@unlink(__DIR__ . "/{$router}");
96+
@rmdir($doc_root);
9397
},
9498
$handle
9599
);
96100

97-
return $handle;
101+
// Define the same "constants" we previously did.
102+
$port = (int) substr($bound, strrpos($bound, ':') + 1);
103+
define("PHP_CLI_SERVER_HOSTNAME", "localhost");
104+
define("PHP_CLI_SERVER_PORT", $port);
105+
define("PHP_CLI_SERVER_ADDRESS", PHP_CLI_SERVER_HOSTNAME.":".PHP_CLI_SERVER_PORT);
106+
107+
return new CliServerInfo($doc_root);
98108
}
99109

100110
function php_cli_server_connect() {

sapi/cli/tests/php_cli_server_002.phpt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ php_cli_server_start('var_dump($_SERVER["DOCUMENT_ROOT"], $_SERVER["SERVER_SOFTW
1313
var_dump(file_get_contents("http://" . PHP_CLI_SERVER_ADDRESS));
1414
?>
1515
--EXPECTF--
16-
string(%d) "string(%d) "%stests"
16+
string(%d) "string(%d) "%sphp_cli_server_002"
1717
string(%d) "PHP %s Development Server"
1818
string(%d) "localhost"
19-
string(%d) "8964"
19+
string(%d) "%s"
2020
"

sapi/cli/tests/php_cli_server_012.phpt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ include "skipif.inc";
77
--FILE--
88
<?php
99
include "php_cli_server.inc";
10-
php_cli_server_start('print_r($_REQUEST); $_REQUEST["foo"] = "bar"; return FALSE;');
11-
$doc_root = __DIR__;
10+
$info = php_cli_server_start('print_r($_REQUEST); $_REQUEST["foo"] = "bar"; return FALSE;');
11+
$doc_root = $info->docRoot;
1212
file_put_contents($doc_root . '/request.php', '<?php print_r($_REQUEST); ?>');
1313

1414
$host = PHP_CLI_SERVER_HOSTNAME;

sapi/cli/tests/php_cli_server_015.phpt

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,9 @@ display_errors=1
99
--FILE--
1010
<?php
1111
include "php_cli_server.inc";
12-
php_cli_server_start('require("syntax_error.php");');
13-
$dir = realpath(__DIR__);
12+
$doc_root = php_cli_server_start('require("syntax_error.php");')->docRoot;
1413

15-
file_put_contents($dir . "/syntax_error.php", "<?php non_exists_function(); ?>");
14+
file_put_contents($doc_root . "/syntax_error.php", "<?php non_exists_function(); ?>");
1615

1716
$output = '';
1817
$host = PHP_CLI_SERVER_HOSTNAME;
@@ -30,7 +29,7 @@ HEADER
3029
}
3130
}
3231
echo $output;
33-
@unlink($dir . "/syntax_error.php");
32+
@unlink($doc_root . "/syntax_error.php");
3433
fclose($fp);
3534
?>
3635
--EXPECTF--

tests/basic/bug67198.phpt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
php://input is empty when enable_post_data_reading=Off
33
--INI--
44
allow_url_fopen=1
5-
--CONFLICTS--
6-
server
75
--SKIPIF--
86
<?php
97
include __DIR__."/../../sapi/cli/tests/skipif.inc";

0 commit comments

Comments
 (0)