diff options
| author | Thijs Schreijer <thijs@thijsschreijer.nl> | 2026-08-29 19:59:33 +0200 |
|---|---|---|
| committer | Thijs Schreijer <thijs@thijsschreijer.nl> | 2026-08-30 08:46:47 +0200 |
| commit | e21720da69f2a505bcd1405cc7e8b52d5649df55 (patch) | |
| tree | b37bd8a78ba484dd9987b306a50d391315f639ab /test | |
| parent | 827ae20771d34912a8f79b50dc68e6430945b9eb (diff) | |
| download | luasocket-e21720da69f2a505bcd1405cc7e8b52d5649df55.tar.gz luasocket-e21720da69f2a505bcd1405cc7e8b52d5649df55.tar.bz2 luasocket-e21720da69f2a505bcd1405cc7e8b52d5649df55.zip | |
fix(receive): a receive 0 should immediately return, not block
The fix is slightly more complex because reading from a closed
socket should still return a closed-error.
fixes: #427
fixes: https://github.com/ledgetech/lua-resty-http/pull/313
Diffstat (limited to 'test')
| -rw-r--r-- | test/test_receive_zero.lua | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/test/test_receive_zero.lua b/test/test_receive_zero.lua new file mode 100644 index 0000000..2259910 --- /dev/null +++ b/test/test_receive_zero.lua | |||
| @@ -0,0 +1,36 @@ | |||
| 1 | -- a TCP receive(0) must never block: requesting zero bytes is trivially | ||
| 2 | -- satisfied without touching the transport layer, POSIX recv(fd, buf, 0, 0) | ||
| 3 | -- returns immediately regardless of whether data is available. | ||
| 4 | local socket = require "socket" | ||
| 5 | |||
| 6 | local host, port = "127.0.0.1", "5464" | ||
| 7 | |||
| 8 | local server = assert(socket.bind(host, port)) | ||
| 9 | local client = assert(socket.connect(host, port)) | ||
| 10 | local peer = assert(server:accept()) | ||
| 11 | |||
| 12 | client:settimeout(2) | ||
| 13 | |||
| 14 | -- no data has been sent by the peer: the read buffer is empty, so if | ||
| 15 | -- receive(0) touches the network it will block until the timeout expires | ||
| 16 | local t0 = socket.gettime() | ||
| 17 | local data, err = client:receive(0) | ||
| 18 | local elapsed = socket.gettime() - t0 | ||
| 19 | |||
| 20 | assert(data == "", "receive(0) on empty buffer returned " .. tostring(data)) | ||
| 21 | assert(err == nil, "receive(0) on empty buffer returned error " .. tostring(err)) | ||
| 22 | assert(elapsed < 1, "receive(0) on empty buffer blocked for " .. elapsed .. "s") | ||
| 23 | |||
| 24 | -- receive(0) must also not consume any bytes when data *is* available | ||
| 25 | assert(peer:send("hello")) | ||
| 26 | data, err = client:receive(0) | ||
| 27 | assert(data == "", "receive(0) with data pending returned " .. tostring(data)) | ||
| 28 | assert(err == nil, "receive(0) with data pending returned error " .. tostring(err)) | ||
| 29 | data = assert(client:receive(5)) | ||
| 30 | assert(data == "hello", "receive(0) consumed bytes meant for receive(5)") | ||
| 31 | |||
| 32 | client:close() | ||
| 33 | peer:close() | ||
| 34 | server:close() | ||
| 35 | |||
| 36 | print("done!") | ||
