use rhai::{Engine, EvalAltResult}; use sal_net::rhai::{create_module, register_net_module, tcp_check, tcp_ping}; use std::time::Duration; use tokio::net::TcpListener; #[test] fn test_create_module() { let module = create_module(); // Verify the module is created successfully // The module is currently empty but serves as a placeholder for future functionality // Functions are registered through register_net_module instead assert!(module.is_empty()); // Module should be empty but valid } #[test] fn test_register_net_module_comprehensive() { let mut engine = Engine::new(); let result = register_net_module(&mut engine); assert!(result.is_ok()); // Test that all functions are properly registered by executing scripts let tcp_script = r#" let result1 = tcp_check("127.0.0.1", 65534); let result2 = tcp_ping("localhost"); [result1, result2] "#; let tcp_result: Result> = engine.eval(tcp_script); assert!(tcp_result.is_ok()); let http_script = r#" let result1 = http_check("https://httpbin.org/status/200"); let result2 = http_status("https://httpbin.org/status/404"); [result1, result2] "#; let http_result: Result> = engine.eval(http_script); assert!(http_result.is_ok()); let ssh_script = r#" let result1 = ssh_execute("invalid-host", "user", "echo test"); let result2 = ssh_execute_output("invalid-host", "user", "echo test"); let result3 = ssh_ping("invalid-host", "user"); [result1, result2, result3] "#; let ssh_result: Result> = engine.eval(ssh_script); assert!(ssh_result.is_ok()); } #[test] fn test_register_net_module() { let mut engine = Engine::new(); let result = register_net_module(&mut engine); assert!(result.is_ok()); // Verify functions are registered let script = r#" let result = tcp_check("127.0.0.1", 65534); result "#; let result: Result> = engine.eval(script); assert!(result.is_ok()); assert!(!result.unwrap()); // Port should be closed } #[tokio::test] async fn test_tcp_check_function_open_port() { // Start a test server let listener = TcpListener::bind("127.0.0.1:0").await.unwrap(); let addr = listener.local_addr().unwrap(); // Keep the listener alive in a background task let _handle = tokio::spawn(async move { loop { if let Ok((stream, _)) = listener.accept().await { drop(stream); // Immediately close the connection } } }); // Give the server a moment to start tokio::time::sleep(Duration::from_millis(10)).await; let result = tcp_check("127.0.0.1", addr.port() as i64); assert!(result); // Port should be open } #[test] fn test_tcp_check_function_closed_port() { let result = tcp_check("127.0.0.1", 65534); assert!(!result); // Port should be closed } #[test] fn test_tcp_check_function_invalid_host() { let result = tcp_check("this-host-definitely-does-not-exist-12345", 80); assert!(!result); // Should return false for invalid host } #[test] fn test_tcp_ping_function_localhost() { let result = tcp_ping("localhost"); // Note: This might fail in some environments (containers, etc.) // We just verify the function doesn't panic and returns a boolean assert!(result == true || result == false); } #[test] fn test_tcp_ping_function_invalid_host() { let result = tcp_ping("this-host-definitely-does-not-exist-12345"); assert!(!result); // Should return false for invalid host } #[test] fn test_rhai_script_tcp_check() { let mut engine = Engine::new(); register_net_module(&mut engine).unwrap(); let script = r#" // Test checking a port that should be closed let result1 = tcp_check("127.0.0.1", 65534); // Test checking an invalid host let result2 = tcp_check("invalid-host-12345", 80); [result1, result2] "#; let result: Result> = engine.eval(script); assert!(result.is_ok()); let results = result.unwrap(); assert_eq!(results.len(), 2); // Both should be false (closed port and invalid host) assert!(!results[0].as_bool().unwrap()); assert!(!results[1].as_bool().unwrap()); } #[test] fn test_rhai_script_tcp_ping() { let mut engine = Engine::new(); register_net_module(&mut engine).unwrap(); let script = r#" // Test pinging localhost (might work or fail depending on environment) let result1 = tcp_ping("localhost"); // Test pinging an invalid host let result2 = tcp_ping("invalid-host-12345"); [result1, result2] "#; let result: Result> = engine.eval(script); assert!(result.is_ok()); let results = result.unwrap(); assert_eq!(results.len(), 2); // Second result should definitely be false (invalid host) assert!(!results[1].as_bool().unwrap()); // First result could be true or false depending on environment let localhost_ping = results[0].as_bool().unwrap(); assert!(localhost_ping == true || localhost_ping == false); } #[test] fn test_rhai_script_complex_network_check() { let mut engine = Engine::new(); register_net_module(&mut engine).unwrap(); let script = r#" // Function to check multiple ports fn check_ports(host, ports) { let results = []; for port in ports { let is_open = tcp_check(host, port); results.push([port, is_open]); } results } // Check some common ports that should be closed let ports = [65534, 65533, 65532]; let results = check_ports("127.0.0.1", ports); results "#; let result: Result> = engine.eval(script); assert!(result.is_ok()); let results = result.unwrap(); assert_eq!(results.len(), 3); // All ports should be closed for port_result in results { let port_array = port_result.cast::(); let is_open = port_array[1].as_bool().unwrap(); assert!(!is_open); // All these high ports should be closed } } #[test] fn test_rhai_script_error_handling() { let mut engine = Engine::new(); register_net_module(&mut engine).unwrap(); let script = r#" // Test with various edge cases let results = []; // Valid cases results.push(tcp_check("127.0.0.1", 65534)); results.push(tcp_ping("localhost")); // Edge cases that should not crash results.push(tcp_check("", 80)); // Empty host results.push(tcp_ping("")); // Empty host results "#; let result: Result> = engine.eval(script); assert!(result.is_ok()); let results = result.unwrap(); assert_eq!(results.len(), 4); // All results should be boolean values (no crashes) for result in results { assert!(result.is_bool()); } } #[test] fn test_http_functions_directly() { use sal_net::rhai::{http_check, http_status}; // Test HTTP check with invalid URL let result = http_check("not-a-valid-url"); assert!(!result); // Should return false for invalid URL // Test HTTP status with invalid URL let status = http_status("not-a-valid-url"); assert_eq!(status, -1); // Should return -1 for invalid URL // Test with unreachable host let result = http_check("https://this-domain-definitely-does-not-exist-12345.com"); assert!(!result); // Should return false for unreachable host } #[test] fn test_ssh_functions_directly() { use sal_net::rhai::{ssh_execute, ssh_execute_output, ssh_ping_host}; // Test SSH execute with invalid host let exit_code = ssh_execute("invalid-host-12345", "user", "echo test"); assert!(exit_code != 0); // Should fail with non-zero exit code // Test SSH execute output with invalid host let output = ssh_execute_output("invalid-host-12345", "user", "echo test"); // Output might be empty or contain error message, both are valid // The important thing is that the function doesn't panic and returns a string let _output_len = output.len(); // Just verify we get a string back // Test SSH ping with invalid host let result = ssh_ping_host("invalid-host-12345", "user"); assert!(!result); // Should return false for invalid host }