sal/net/tests/tcp_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

180 lines
5.6 KiB
Rust

use sal_net::TcpConnector;
use std::net::{IpAddr, Ipv4Addr};
use std::time::Duration;
use tokio::net::TcpListener;
#[tokio::test]
async fn test_tcp_connector_new() {
let connector = TcpConnector::new();
// Test that the connector can actually perform operations
// Use a port that should be closed to verify the connector works
let result = connector
.check_port(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 65534)
.await;
assert!(result.is_ok());
assert!(!result.unwrap()); // Port should be closed
}
#[tokio::test]
async fn test_tcp_connector_with_timeout() {
let timeout = Duration::from_millis(100); // Short timeout for testing
let connector = TcpConnector::with_timeout(timeout);
// Test that the custom timeout is actually used by trying to connect to a non-routable IP
// This should timeout quickly with our short timeout
let start = std::time::Instant::now();
let result = connector
.check_port(IpAddr::V4(Ipv4Addr::new(10, 255, 255, 1)), 80)
.await;
let elapsed = start.elapsed();
assert!(result.is_ok());
assert!(!result.unwrap()); // Should timeout and return false
assert!(elapsed < Duration::from_secs(2)); // Should timeout much faster than default
}
#[tokio::test]
async fn test_tcp_connector_default() {
let connector = TcpConnector::default();
// Test that default constructor creates a working connector
// Verify it behaves the same as TcpConnector::new()
let result = connector
.check_port(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 65534)
.await;
assert!(result.is_ok());
assert!(!result.unwrap()); // Port should be closed
// Test that it can also ping (basic functionality test)
let ping_result = connector.ping("127.0.0.1").await;
assert!(ping_result.is_ok()); // Should not error, regardless of ping success
}
#[tokio::test]
async fn test_check_port_open() {
// 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 connector = TcpConnector::new();
let result = connector.check_port(addr.ip(), addr.port()).await;
assert!(result.is_ok());
assert!(result.unwrap()); // Port should be open
}
#[tokio::test]
async fn test_check_port_closed() {
let connector = TcpConnector::new();
// Use a port that's very unlikely to be open
let result = connector
.check_port(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 65534)
.await;
assert!(result.is_ok());
assert!(!result.unwrap()); // Port should be closed
}
#[tokio::test]
async fn test_check_port_timeout() {
let connector = TcpConnector::with_timeout(Duration::from_millis(1));
// Use a non-routable IP to trigger timeout
let result = connector
.check_port(IpAddr::V4(Ipv4Addr::new(10, 255, 255, 1)), 80)
.await;
assert!(result.is_ok());
assert!(!result.unwrap()); // Should timeout and return false
}
#[tokio::test]
async fn test_check_multiple_ports() {
// Start test servers on multiple ports
let listener1 = TcpListener::bind("127.0.0.1:0").await.unwrap();
let addr1 = listener1.local_addr().unwrap();
let listener2 = TcpListener::bind("127.0.0.1:0").await.unwrap();
let addr2 = listener2.local_addr().unwrap();
// Keep listeners alive
let _handle1 = tokio::spawn(async move {
loop {
if let Ok((stream, _)) = listener1.accept().await {
drop(stream);
}
}
});
let _handle2 = tokio::spawn(async move {
loop {
if let Ok((stream, _)) = listener2.accept().await {
drop(stream);
}
}
});
tokio::time::sleep(Duration::from_millis(10)).await;
let connector = TcpConnector::new();
let ports = vec![addr1.port(), addr2.port(), 65533]; // Two open, one closed
let results = connector.check_ports(addr1.ip(), &ports).await;
assert!(results.is_ok());
let results = results.unwrap();
assert_eq!(results.len(), 3);
// First two should be open, last should be closed
assert!(results[0].1); // addr1.port() should be open
assert!(results[1].1); // addr2.port() should be open
assert!(!results[2].1); // 65533 should be closed
}
#[tokio::test]
async fn test_ping_localhost() {
let connector = TcpConnector::new();
// Ping localhost - should work on most systems
let result = connector.ping("localhost").await;
// Note: This might fail in some environments (containers, etc.)
// so we just verify the function doesn't panic and returns a boolean result
assert!(result.is_ok());
}
#[tokio::test]
async fn test_ping_invalid_host() {
let connector = TcpConnector::new();
// Ping an invalid hostname
let result = connector
.ping("this-host-definitely-does-not-exist-12345")
.await;
assert!(result.is_ok());
assert!(!result.unwrap()); // Should fail to ping invalid host
}
#[tokio::test]
async fn test_ping_timeout() {
let connector = TcpConnector::with_timeout(Duration::from_millis(1));
// Use a non-routable IP to trigger timeout
let result = connector.ping("10.255.255.1").await;
assert!(result.is_ok());
// Result could be true or false depending on system, but shouldn't panic
}