diff --git a/tests/stream/038-feof_live_socket.phpt b/tests/stream/038-feof_live_socket.phpt new file mode 100644 index 00000000..97eba83e --- /dev/null +++ b/tests/stream/038-feof_live_socket.phpt @@ -0,0 +1,89 @@ +--TEST-- +feof() returns false on a live connected socket +--FILE-- + client +$c2s = new Channel(1); // client -> server + +$server = spawn(function() use ($s2c, $c2s) { + $socket = stream_socket_server("tcp://127.0.0.1:0", $errno, $errstr); + if (!$socket) { + echo "Server: failed - $errstr\n"; + return; + } + + // Signal the address to the client + $s2c->send(stream_socket_get_name($socket, false)); + + $client = stream_socket_accept($socket, 5); + echo "Server: accepted\n"; + + // Signal that connection is established + $s2c->send("connected"); + + // Wait for client to finish feof check + $c2s->recv(); + + // Close client connection + fclose($client); + echo "Server: closed client\n"; + + // Signal that server closed the connection + $s2c->send("closed"); + + fclose($socket); +}); + +$client = spawn(function() use ($s2c, $c2s) { + $address = $s2c->recv(); + + $sock = stream_socket_client("tcp://$address", $errno, $errstr, 5); + if (!$sock) { + echo "Client: failed - $errstr\n"; + return; + } + echo "Client: connected\n"; + + // Wait for server to confirm accept + $s2c->recv(); + + // Socket is alive — feof() MUST return false + $eof = feof($sock); + echo "feof on live socket: " . ($eof ? "true (BUG!)" : "false") . "\n"; + + // Tell server it can close now + $c2s->send("done"); + + // Wait for server to confirm close + $s2c->recv(); + + // Give TCP stack time to deliver FIN + \Async\delay(1); + + // Server closed — feof() should return true + $eof = feof($sock); + echo "feof after remote close: " . ($eof ? "true" : "false (BUG!)") . "\n"; + + fclose($sock); +}); + +await_all([$server, $client]); + +echo "End\n"; + +?> +--EXPECTF-- +Start +%AServer: accepted +%AClient: connected +%Afeof on live socket: false +Server: closed client +feof after remote close: true +End diff --git a/tests/stream/039-feof_after_connect.phpt b/tests/stream/039-feof_after_connect.phpt new file mode 100644 index 00000000..9b650045 --- /dev/null +++ b/tests/stream/039-feof_after_connect.phpt @@ -0,0 +1,38 @@ +--TEST-- +feof() returns false immediately after connect +--FILE-- +send(stream_socket_get_name($socket, false)); + $client = stream_socket_accept($socket, 5); + $s2c->send("accepted"); + $c2s->recv(); + fclose($client); + fclose($socket); +}); + +$client = spawn(function() use ($s2c, $c2s) { + $address = $s2c->recv(); + $sock = stream_socket_client("tcp://$address", $errno, $errstr, 5); + $s2c->recv(); + + echo "feof after connect: " . (feof($sock) ? "true (BUG!)" : "false") . "\n"; + + $c2s->send("done"); + fclose($sock); +}); + +await_all([$server, $client]); + +?> +--EXPECT-- +feof after connect: false diff --git a/tests/stream/040-feof_after_send.phpt b/tests/stream/040-feof_after_send.phpt new file mode 100644 index 00000000..6143bb79 --- /dev/null +++ b/tests/stream/040-feof_after_send.phpt @@ -0,0 +1,40 @@ +--TEST-- +feof() returns false after sending data +--FILE-- +send(stream_socket_get_name($socket, false)); + $client = stream_socket_accept($socket, 5); + $s2c->send("accepted"); + $c2s->recv(); + fclose($client); + fclose($socket); +}); + +$client = spawn(function() use ($s2c, $c2s) { + $address = $s2c->recv(); + $sock = stream_socket_client("tcp://$address", $errno, $errstr, 5); + $s2c->recv(); + + fwrite($sock, "hello"); + + echo "feof after send: " . (feof($sock) ? "true (BUG!)" : "false") . "\n"; + + $c2s->send("done"); + fclose($sock); +}); + +await_all([$server, $client]); + +?> +--EXPECT-- +feof after send: false diff --git a/tests/stream/041-feof_after_recv.phpt b/tests/stream/041-feof_after_recv.phpt new file mode 100644 index 00000000..49be1551 --- /dev/null +++ b/tests/stream/041-feof_after_recv.phpt @@ -0,0 +1,42 @@ +--TEST-- +feof() returns false after receiving data +--FILE-- +send(stream_socket_get_name($socket, false)); + $client = stream_socket_accept($socket, 5); + fwrite($client, "hello from server"); + $s2c->send("sent"); + $c2s->recv(); + fclose($client); + fclose($socket); +}); + +$client = spawn(function() use ($s2c, $c2s) { + $address = $s2c->recv(); + $sock = stream_socket_client("tcp://$address", $errno, $errstr, 5); + $s2c->recv(); + + $data = fread($sock, 1024); + echo "received: $data\n"; + echo "feof after recv: " . (feof($sock) ? "true (BUG!)" : "false") . "\n"; + + $c2s->send("done"); + fclose($sock); +}); + +await_all([$server, $client]); + +?> +--EXPECT-- +received: hello from server +feof after recv: false diff --git a/tests/stream/042-feof_after_remote_close.phpt b/tests/stream/042-feof_after_remote_close.phpt new file mode 100644 index 00000000..6b98165b --- /dev/null +++ b/tests/stream/042-feof_after_remote_close.phpt @@ -0,0 +1,43 @@ +--TEST-- +feof() returns true after remote close +--FILE-- +send(stream_socket_get_name($socket, false)); + $client = stream_socket_accept($socket, 5); + $s2c->send("accepted"); + $c2s->recv(); + fclose($client); + $s2c->send("closed"); + fclose($socket); +}); + +$client = spawn(function() use ($s2c, $c2s) { + $address = $s2c->recv(); + $sock = stream_socket_client("tcp://$address", $errno, $errstr, 5); + $s2c->recv(); + + $c2s->send("close now"); + $s2c->recv(); + + \Async\delay(1); + + echo "feof after remote close: " . (feof($sock) ? "true" : "false (BUG!)") . "\n"; + + fclose($sock); +}); + +await_all([$server, $client]); + +?> +--EXPECT-- +feof after remote close: true diff --git a/tests/stream/043-feof_after_send_then_remote_close.phpt b/tests/stream/043-feof_after_send_then_remote_close.phpt new file mode 100644 index 00000000..c37f312b --- /dev/null +++ b/tests/stream/043-feof_after_send_then_remote_close.phpt @@ -0,0 +1,47 @@ +--TEST-- +feof() after send then remote close +--FILE-- +send(stream_socket_get_name($socket, false)); + $client = stream_socket_accept($socket, 5); + $s2c->send("accepted"); + $c2s->recv(); + fclose($client); + $s2c->send("closed"); + fclose($socket); +}); + +$client = spawn(function() use ($s2c, $c2s) { + $address = $s2c->recv(); + $sock = stream_socket_client("tcp://$address", $errno, $errstr, 5); + $s2c->recv(); + + fwrite($sock, "payload"); + echo "feof after send: " . (feof($sock) ? "true (BUG!)" : "false") . "\n"; + + $c2s->send("close now"); + $s2c->recv(); + + \Async\delay(1); + + echo "feof after remote close: " . (feof($sock) ? "true" : "false (BUG!)") . "\n"; + + fclose($sock); +}); + +await_all([$server, $client]); + +?> +--EXPECT-- +feof after send: false +feof after remote close: true diff --git a/tests/stream/044-feof_with_pending_data.phpt b/tests/stream/044-feof_with_pending_data.phpt new file mode 100644 index 00000000..a940d7b0 --- /dev/null +++ b/tests/stream/044-feof_with_pending_data.phpt @@ -0,0 +1,47 @@ +--TEST-- +feof() returns false when unread data is pending +--FILE-- +send(stream_socket_get_name($socket, false)); + $client = stream_socket_accept($socket, 5); + fwrite($client, "data in buffer"); + $s2c->send("sent"); + $c2s->recv(); + fclose($client); + fclose($socket); +}); + +$client = spawn(function() use ($s2c, $c2s) { + $address = $s2c->recv(); + $sock = stream_socket_client("tcp://$address", $errno, $errstr, 5); + $s2c->recv(); + + \Async\delay(1); + + echo "feof with pending data: " . (feof($sock) ? "true (BUG!)" : "false") . "\n"; + + $data = fread($sock, 1024); + echo "read: $data\n"; + echo "feof after reading all: " . (feof($sock) ? "true (BUG!)" : "false") . "\n"; + + $c2s->send("done"); + fclose($sock); +}); + +await_all([$server, $client]); + +?> +--EXPECT-- +feof with pending data: false +read: data in buffer +feof after reading all: false