diff --git a/crates/lune/src/tests.rs b/crates/lune/src/tests.rs index e4809e8..cadca69 100644 --- a/crates/lune/src/tests.rs +++ b/crates/lune/src/tests.rs @@ -127,13 +127,19 @@ create_tests! { net_request_methods: "net/request/methods", net_request_query: "net/request/query", net_request_redirect: "net/request/redirect", - net_url_encode: "net/url/encode", - net_url_decode: "net/url/decode", + + net_serve_addresses: "net/serve/addresses", + net_serve_handles: "net/serve/handles", + net_serve_non_blocking: "net/serve/non_blocking", net_serve_requests: "net/serve/requests", net_serve_websockets: "net/serve/websockets", + net_socket_basic: "net/socket/basic", net_socket_wss: "net/socket/wss", net_socket_wss_rw: "net/socket/wss_rw", + + net_url_encode: "net/url/encode", + net_url_decode: "net/url/decode", } #[cfg(feature = "std-process")] diff --git a/tests/net/serve/addresses.luau b/tests/net/serve/addresses.luau new file mode 100644 index 0000000..57f591f --- /dev/null +++ b/tests/net/serve/addresses.luau @@ -0,0 +1,35 @@ +local net = require("@lune/net") + +local PORT = 8081 +local LOCALHOST = "http://localhost" +local BROADCAST = `http://0.0.0.0` +local RESPONSE = "Hello, lune!" + +-- Serve should be able to bind to broadcast IP addresse + +local handle = net.serve(PORT, { + address = BROADCAST, + handleRequest = function(request) + return `Response from {BROADCAST}:{PORT}` + end, +}) + +-- And any requests to localhost should then succeed + +local response = net.request(`{LOCALHOST}:{PORT}`).body +assert(response ~= nil, "Invalid response from server") + +handle.stop() + +-- Attempting to serve with a malformed IP address should throw an error + +local success = pcall(function() + net.serve(8080, { + address = "a.b.c.d", + handleRequest = function() + return RESPONSE + end, + }) +end) + +assert(not success, "Server was created with malformed address") diff --git a/tests/net/serve/handles.luau b/tests/net/serve/handles.luau new file mode 100644 index 0000000..6b2b764 --- /dev/null +++ b/tests/net/serve/handles.luau @@ -0,0 +1,51 @@ +local net = require("@lune/net") +local task = require("@lune/task") + +local PORT = 8083 +local URL = `http://127.0.0.1:{PORT}` +local RESPONSE = "Hello, lune!" + +local handle = net.serve(PORT, function(request) + return RESPONSE +end) + +-- Stopping is not guaranteed to happen instantly since it is async, but +-- it should happen on the next yield, so we wait the minimum amount here + +handle.stop() +task.wait() + +-- Sending a request to the stopped server should now error + +local success, response2 = pcall(net.request, URL) +if not success then + local message = tostring(response2) + assert( + string.find(message, "Connection reset") + or string.find(message, "Connection closed") + or string.find(message, "Connection refused") + or string.find(message, "No connection could be made"), -- Windows Request Error + "Server did not stop responding to requests" + ) +else + assert(not response2.ok, "Server did not stop responding to requests") +end + +--[[ + Trying to *stop* the server again should error, and + also mention that the server has already been stopped + + Note that we cast pcall to any because of a + Luau limitation where it throws a type error for + `err` because handle.stop doesn't return any value +]] + +local success2, err = (pcall :: any)(handle.stop) +assert(not success2, "Calling stop twice on the net serve handle should error") +local message = tostring(err) +assert( + string.find(message, "stop") + or string.find(message, "shutdown") + or string.find(message, "shut down"), + "The error message for calling stop twice on the net serve handle should be descriptive" +) diff --git a/tests/net/serve/non_blocking.luau b/tests/net/serve/non_blocking.luau new file mode 100644 index 0000000..5463527 --- /dev/null +++ b/tests/net/serve/non_blocking.luau @@ -0,0 +1,24 @@ +local net = require("@lune/net") +local process = require("@lune/process") +local stdio = require("@lune/stdio") +local task = require("@lune/task") + +local PORT = 8082 +local RESPONSE = "Hello, lune!" + +-- Serve should not yield the entire main thread forever, only +-- for the initial binding to socket which should be very fast + +local thread = task.delay(1, function() + stdio.ewrite("Serve must not yield the current thread for too long\n") + task.wait(1) + process.exit(1) +end) + +local handle = net.serve(PORT, function(request) + return RESPONSE +end) + +task.cancel(thread) + +handle.stop() diff --git a/tests/net/serve/requests.luau b/tests/net/serve/requests.luau index 36602a0..f2613fc 100644 --- a/tests/net/serve/requests.luau +++ b/tests/net/serve/requests.luau @@ -3,37 +3,20 @@ local process = require("@lune/process") local stdio = require("@lune/stdio") local task = require("@lune/task") -local PORT = 8082 +local PORT = 8083 local URL = `http://127.0.0.1:{PORT}` -local URL_EXTERNAL = `http://0.0.0.0` local RESPONSE = "Hello, lune!" --- A server should never be running before testing -local isRunning = pcall(net.request, URL) -assert(not isRunning, `a server is already running at {URL}`) - --- Serve should not block the thread from continuing - -local thread = task.delay(1, function() - stdio.ewrite("Serve must not block the current thread\n") - task.wait(1) - process.exit(1) -end) +-- Serve should respond to a request we send to it local handle = net.serve(PORT, function(request) - -- print("Request:", request) - -- print("Responding with", RESPONSE) assert(request.path == "/some/path") assert(request.query.key == "param2") assert(request.query.key2 == "param3") return RESPONSE end) -task.cancel(thread) - --- Serve should respond to a request we send to it - -local thread2 = task.delay(1, function() +local thread = task.delay(1, function() stdio.ewrite("Serve should respond to requests in a reasonable amount of time\n") task.wait(1) process.exit(1) @@ -42,78 +25,6 @@ end) local response = net.request(URL .. "/some/path?key=param1&key=param2&key2=param3").body assert(response == RESPONSE, "Invalid response from server") -task.cancel(thread2) +task.cancel(thread) --- Stopping is not guaranteed to happen instantly since it is async, but --- it should happen on the next yield, so we wait the minimum amount here handle.stop() -task.wait() - --- Sending a net request may error if there was --- a connection issue, we should handle that here -local success, response2 = pcall(net.request, URL) -if not success then - local message = tostring(response2) - assert( - string.find(message, "Connection reset") - or string.find(message, "Connection closed") - or string.find(message, "Connection refused") - or string.find(message, "No connection could be made"), -- Windows Request Error - "Server did not stop responding to requests" - ) -else - assert(not response2.ok, "Server did not stop responding to requests") -end - ---[[ - Trying to stop the server again should error and - mention that the server has already been stopped - - Note that we cast pcall to any because of a - Luau limitation where it throws a type error for - `err` because handle.stop doesn't return any value -]] -local success2, err = (pcall :: any)(handle.stop) -assert(not success2, "Calling stop twice on the net serve handle should error") -local message = tostring(err) -assert( - string.find(message, "stop") - or string.find(message, "shutdown") - or string.find(message, "shut down"), - "The error message for calling stop twice on the net serve handle should be descriptive" -) - --- Serve should be able to bind to other IP addresses -local handle2 = net.serve(PORT, { - address = URL_EXTERNAL, - handleRequest = function(request) - return `Response from {URL_EXTERNAL}:{PORT}` - end, -}) - -if process.os == "windows" then - -- In Windows, client cannot directly connect to `0.0.0.0`. - -- `0.0.0.0` is a non-routable meta-address. - URL_EXTERNAL = "http://localhost" -end - --- And any requests to that IP should succeed -local response3 = net.request(`{URL_EXTERNAL}:{PORT}`).body -assert(response3 ~= nil, "Invalid response from server") - -handle2.stop() - --- Attempting to serve with a malformed IP address should throw an error -local success3 = pcall(function() - net.serve(8080, { - address = "a.b.c.d", - handleRequest = function() - return RESPONSE - end, - }) -end) - -assert(not success3, "Server was created with malformed address") - --- We have to manually exit so Windows CI doesn't get stuck forever -process.exit(0)