Skip to content

Commit f7fc1e8

Browse files
committed
+ CURL tests
1 parent eabd5ba commit f7fc1e8

12 files changed

+1008
-0
lines changed
Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
<?php
2+
/**
3+
* Simple synchronous HTTP server for async tests
4+
* This server runs in a separate process to avoid interference with async tests
5+
* Usage: Start this server before running tests, or use start_test_server_process()
6+
*/
7+
8+
function start_test_server_process($port = 8088) {
9+
$server_script = __FILE__;
10+
$cmd = PHP_BINARY . " $server_script $port > /dev/null 2>&1 & echo $!";
11+
$pid = exec($cmd);
12+
13+
// Wait a bit for server to start
14+
usleep(100000); // 100ms
15+
16+
return (int)$pid;
17+
}
18+
19+
function stop_test_server_process($pid) {
20+
if (PHP_OS_FAMILY === 'Windows') {
21+
exec("taskkill /PID $pid /F 2>NUL");
22+
} else {
23+
exec("kill $pid 2>/dev/null");
24+
}
25+
}
26+
27+
function run_test_server($port) {
28+
$server = stream_socket_server("tcp://127.0.0.1:$port", $errno, $errstr);
29+
if (!$server) {
30+
die("Failed to create server: $errstr ($errno)\n");
31+
}
32+
33+
echo "Test HTTP server running on 127.0.0.1:$port\n";
34+
35+
while (true) {
36+
$client = stream_socket_accept($server);
37+
if (!$client) continue;
38+
39+
// Read the request
40+
$request = '';
41+
while (!feof($client)) {
42+
$line = fgets($client);
43+
$request .= $line;
44+
if (trim($line) === '') break; // End of headers
45+
}
46+
47+
// Parse request line
48+
$lines = explode("\n", $request);
49+
$request_line = trim($lines[0]);
50+
preg_match('/^(\S+)\s+(\S+)\s+(\S+)$/', $request_line, $matches);
51+
52+
if (count($matches) >= 3) {
53+
$method = $matches[1];
54+
$path = $matches[2];
55+
56+
// Route requests
57+
$response = route_test_request($method, $path, $request);
58+
} else {
59+
$response = http_test_response(400, "Bad Request");
60+
}
61+
62+
fwrite($client, $response);
63+
fclose($client);
64+
}
65+
66+
fclose($server);
67+
}
68+
69+
function route_test_request($method, $path, $full_request) {
70+
switch ($path) {
71+
case '/':
72+
return http_test_response(200, "Hello World");
73+
74+
case '/json':
75+
return http_test_response(200, '{"message":"Hello JSON","status":"ok"}', 'application/json');
76+
77+
case '/slow':
78+
// Simulate slow response (useful for timeout tests)
79+
usleep(500000); // 500ms
80+
return http_test_response(200, "Slow Response");
81+
82+
case '/very-slow':
83+
// Very slow response (for timeout tests)
84+
sleep(2);
85+
return http_test_response(200, "Very Slow Response");
86+
87+
case '/error':
88+
return http_test_response(500, "Internal Server Error");
89+
90+
case '/not-found':
91+
return http_test_response(404, "Not Found");
92+
93+
case '/large':
94+
// Large response for testing data transfer
95+
return http_test_response(200, str_repeat("ABCDEFGHIJ", 1000)); // 10KB
96+
97+
case '/post':
98+
if ($method === 'POST') {
99+
// Extract body if present
100+
$body_start = strpos($full_request, "\r\n\r\n");
101+
$body = $body_start !== false ? substr($full_request, $body_start + 4) : '';
102+
return http_test_response(200, "POST received: " . strlen($body) . " bytes");
103+
} else {
104+
return http_test_response(405, "Method Not Allowed");
105+
}
106+
107+
case '/headers':
108+
// Return request headers as response
109+
$headers = [];
110+
$lines = explode("\n", $full_request);
111+
foreach ($lines as $line) {
112+
$line = trim($line);
113+
if ($line && strpos($line, ':') !== false) {
114+
$headers[] = $line;
115+
}
116+
}
117+
return http_test_response(200, implode("\n", $headers));
118+
119+
case '/echo':
120+
// Echo back the entire request
121+
return http_test_response(200, $full_request, 'text/plain');
122+
123+
case '/redirect':
124+
// Simple redirect
125+
return "HTTP/1.1 302 Found\r\n" .
126+
"Location: /\r\n" .
127+
"Content-Length: 0\r\n" .
128+
"Connection: close\r\n" .
129+
"\r\n";
130+
131+
default:
132+
return http_test_response(404, "Not Found");
133+
}
134+
}
135+
136+
function http_test_response($code, $body, $content_type = 'text/plain') {
137+
$status_text = [
138+
200 => 'OK',
139+
302 => 'Found',
140+
400 => 'Bad Request',
141+
404 => 'Not Found',
142+
405 => 'Method Not Allowed',
143+
500 => 'Internal Server Error'
144+
][$code] ?? 'Unknown';
145+
146+
$length = strlen($body);
147+
148+
return "HTTP/1.1 $code $status_text\r\n" .
149+
"Content-Type: $content_type\r\n" .
150+
"Content-Length: $length\r\n" .
151+
"Connection: close\r\n" .
152+
"Server: AsyncTestServer/1.0\r\n" .
153+
"\r\n" .
154+
$body;
155+
}
156+
157+
// Helper functions for tests
158+
function get_test_server_address($port = 8088) {
159+
return "127.0.0.1:$port";
160+
}
161+
162+
function get_test_server_url($path = '/', $port = 8088) {
163+
return "http://127.0.0.1:$port$path";
164+
}
165+
166+
// If called directly, run the server
167+
if (basename(__FILE__) === basename($_SERVER['SCRIPT_NAME'] ?? '')) {
168+
$port = $argv[1] ?? 8088;
169+
run_test_server($port);
170+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
--TEST--
2+
Basic async curl_exec GET request
3+
--EXTENSIONS--
4+
curl
5+
--FILE--
6+
<?php
7+
include "../common/simple_http_server.php";
8+
9+
use function Async\spawn;
10+
use function Async\await;
11+
12+
// Start test server
13+
$server_pid = start_test_server_process(8088);
14+
15+
function test_basic_get() {
16+
echo "Starting basic GET test\n";
17+
18+
$ch = curl_init();
19+
curl_setopt($ch, CURLOPT_URL, get_test_server_url('/'));
20+
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
21+
curl_setopt($ch, CURLOPT_TIMEOUT, 5);
22+
23+
$response = curl_exec($ch);
24+
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
25+
$error = curl_error($ch);
26+
27+
curl_close($ch);
28+
29+
echo "HTTP Code: $http_code\n";
30+
echo "Error: " . ($error ?: "none") . "\n";
31+
echo "Response: $response\n";
32+
33+
return $response;
34+
}
35+
36+
echo "Test start\n";
37+
38+
$coroutine = spawn(test_basic_get(...));
39+
$result = await($coroutine);
40+
41+
// Stop server
42+
stop_test_server_process($server_pid);
43+
44+
echo "Test end\n";
45+
?>
46+
--EXPECT--
47+
Test start
48+
Starting basic GET test
49+
HTTP Code: 200
50+
Error: none
51+
Response: Hello World
52+
Test end
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
--TEST--
2+
Concurrent async cURL requests
3+
--EXTENSIONS--
4+
curl
5+
--FILE--
6+
<?php
7+
include "../common/simple_http_server.php";
8+
9+
use function Async\spawn;
10+
use function Async\awaitAll;
11+
12+
// Start test server
13+
$server_pid = start_test_server_process(8088);
14+
15+
function make_request($url, $id) {
16+
echo "Request $id: starting\n";
17+
18+
$ch = curl_init();
19+
curl_setopt($ch, CURLOPT_URL, $url);
20+
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
21+
curl_setopt($ch, CURLOPT_TIMEOUT, 5);
22+
23+
$response = curl_exec($ch);
24+
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
25+
26+
curl_close($ch);
27+
28+
echo "Request $id: completed (HTTP $http_code)\n";
29+
return "Request $id result: $response";
30+
}
31+
32+
echo "Test start\n";
33+
34+
// Launch multiple concurrent requests
35+
$coroutines = [
36+
spawn(fn() => make_request(get_test_server_url('/'), 1)),
37+
spawn(fn() => make_request(get_test_server_url('/json'), 2)),
38+
spawn(fn() => make_request(get_test_server_url('/slow'), 3)),
39+
];
40+
41+
$results = awaitAll($coroutines);
42+
43+
foreach ($results as $result) {
44+
echo "Result: $result\n";
45+
}
46+
47+
// Stop server
48+
stop_test_server_process($server_pid);
49+
50+
echo "Test end\n";
51+
?>
52+
--EXPECTF--
53+
Test start
54+
Request 1: starting
55+
Request 2: starting
56+
Request 3: starting
57+
Request 1: completed (HTTP 200)
58+
Request 2: completed (HTTP 200)
59+
Request 3: completed (HTTP 200)
60+
Result: Request 1 result: Hello World
61+
Result: Request 2 result: {"message":"Hello JSON","status":"ok"}
62+
Result: Request 3 result: Slow Response
63+
Test end
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
--TEST--
2+
Async cURL multi-handle operations
3+
--EXTENSIONS--
4+
curl
5+
--FILE--
6+
<?php
7+
include "../common/simple_http_server.php";
8+
9+
use function Async\spawn;
10+
use function Async\await;
11+
12+
// Start test server
13+
$server_pid = start_test_server_process(8088);
14+
15+
function test_multi_handle() {
16+
echo "Starting multi-handle test\n";
17+
18+
$mh = curl_multi_init();
19+
20+
// Create multiple cURL handles
21+
$ch1 = curl_init();
22+
curl_setopt($ch1, CURLOPT_URL, get_test_server_url('/'));
23+
curl_setopt($ch1, CURLOPT_RETURNTRANSFER, true);
24+
curl_multi_add_handle($mh, $ch1);
25+
26+
$ch2 = curl_init();
27+
curl_setopt($ch2, CURLOPT_URL, get_test_server_url('/json'));
28+
curl_setopt($ch2, CURLOPT_RETURNTRANSFER, true);
29+
curl_multi_add_handle($mh, $ch2);
30+
31+
$ch3 = curl_init();
32+
curl_setopt($ch3, CURLOPT_URL, get_test_server_url('/slow'));
33+
curl_setopt($ch3, CURLOPT_RETURNTRANSFER, true);
34+
curl_multi_add_handle($mh, $ch3);
35+
36+
// Execute requests
37+
$active = null;
38+
do {
39+
$status = curl_multi_exec($mh, $active);
40+
if ($status !== CURLM_OK) {
41+
echo "Multi exec error: " . curl_multi_strerror($status) . "\n";
42+
break;
43+
}
44+
45+
if ($active > 0) {
46+
curl_multi_select($mh, 1.0);
47+
}
48+
} while ($active > 0);
49+
50+
// Get results
51+
$response1 = curl_multi_getcontent($ch1);
52+
$response2 = curl_multi_getcontent($ch2);
53+
$response3 = curl_multi_getcontent($ch3);
54+
55+
// Clean up
56+
curl_multi_remove_handle($mh, $ch1);
57+
curl_multi_remove_handle($mh, $ch2);
58+
curl_multi_remove_handle($mh, $ch3);
59+
curl_multi_close($mh);
60+
61+
curl_close($ch1);
62+
curl_close($ch2);
63+
curl_close($ch3);
64+
65+
echo "Response 1: $response1\n";
66+
echo "Response 2: $response2\n";
67+
echo "Response 3: $response3\n";
68+
69+
return [$response1, $response2, $response3];
70+
}
71+
72+
echo "Test start\n";
73+
74+
$coroutine = spawn(test_multi_handle(...));
75+
$results = await($coroutine);
76+
77+
// Stop server
78+
stop_test_server_process($server_pid);
79+
80+
echo "Test end\n";
81+
?>
82+
--EXPECT--
83+
Test start
84+
Starting multi-handle test
85+
Response 1: Hello World
86+
Response 2: {"message":"Hello JSON","status":"ok"}
87+
Response 3: Slow Response
88+
Test end

0 commit comments

Comments
 (0)