diff --git a/stdlib/tests/stdlib_tests.rs b/stdlib/tests/stdlib_tests.rs index f7df969f..17e7e355 100644 --- a/stdlib/tests/stdlib_tests.rs +++ b/stdlib/tests/stdlib_tests.rs @@ -407,6 +407,82 @@ fn test_regex_operations() { assert_eq!(res.as_string(), Some("hello TechScript")); } +#[test] +fn test_web_module() { + use std::net::TcpListener; + use std::panic; + + let registry = StdlibRegistry::new(); + let web = registry.get_module("std.web").unwrap(); + + let mut caps = HashSet::new(); + caps.insert(Capability::Network); + let mut ctx = RuntimeContext::new(RuntimeConfig { + strict_mode: false, + max_recursion_depth: 1000, + enable_assertions: true, + capabilities: caps, + }); + + let start = web.exports.get("start").unwrap(); + let serve = web.exports.get("serve").unwrap(); + let stop = web.exports.get("stop").unwrap(); + + // Bind a listener to a random port to ensure the port is taken + // Keep it alive to conflict + let listener = TcpListener::bind("0.0.0.0:0").unwrap(); + let port = listener.local_addr().unwrap().port(); + + // Test panic on `start` when port is in use + let start_result = panic::catch_unwind(panic::AssertUnwindSafe(|| { + let mut caps = HashSet::new(); + caps.insert(Capability::Network); + let mut ctx2 = RuntimeContext::new(RuntimeConfig { + strict_mode: false, + max_recursion_depth: 1000, + enable_assertions: true, + capabilities: caps, + }); + let _ = start.call( + &mut ctx2, + vec![ + RuntimeValue::Int(port as i64), + RuntimeValue::Str("

Test

".to_string()), + ], + ); + })); + + assert!( + start_result.is_err(), + "Expected `start` to panic due to port already in use" + ); + + // Make sure we stop the server and cleanup the global bool in case of weirdness, + // although the panic meant it wasn't started fully, but `SERVER_RUNNING` is true. + let _ = stop.call(&mut ctx, vec![]).unwrap(); + + // Test panic on `serve` when port is in use + let serve_result = panic::catch_unwind(panic::AssertUnwindSafe(|| { + let mut caps = HashSet::new(); + caps.insert(Capability::Network); + let mut ctx3 = RuntimeContext::new(RuntimeConfig { + strict_mode: false, + max_recursion_depth: 1000, + enable_assertions: true, + capabilities: caps, + }); + let _ = serve.call(&mut ctx3, vec![RuntimeValue::Int(port as i64)]); + })); + + assert!( + serve_result.is_err(), + "Expected `serve` to panic due to port already in use" + ); + + // Reset `SERVER_RUNNING` so other tests aren't affected + let _ = stop.call(&mut ctx, vec![]).unwrap(); +} + #[test] fn test_http_module() { use std::io::{Read, Write};