sal/net/tests/rhai_integration_tests.rs
Mahmoud-Emad 74217364fa
Some checks are pending
Rhai Tests / Run Rhai Tests (push) Waiting to run
feat: Add sal-net package to workspace
- Add new sal-net package to the workspace.
- Update MONOREPO_CONVERSION_PLAN.md to reflect the
  addition of the sal-net package and mark it as
  production-ready.
- Add Cargo.toml and README.md for the sal-net package.
2025-06-22 09:52:20 +03:00

279 lines
8.5 KiB
Rust

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<rhai::Array, Box<EvalAltResult>> = 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<rhai::Array, Box<EvalAltResult>> = 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<rhai::Array, Box<EvalAltResult>> = 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<bool, Box<EvalAltResult>> = 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<rhai::Array, Box<EvalAltResult>> = 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<rhai::Array, Box<EvalAltResult>> = 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<rhai::Array, Box<EvalAltResult>> = 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::<rhai::Array>();
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<rhai::Array, Box<EvalAltResult>> = 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
}