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

286 lines
9.4 KiB
Rust

use sal_net::SshConnectionBuilder;
use std::path::PathBuf;
use std::time::Duration;
#[tokio::test]
async fn test_ssh_connection_builder_new() {
// Test that builder creates a functional connection with defaults
let connection = SshConnectionBuilder::new().build();
// Test that the connection can actually attempt operations
// Use an invalid host to verify the connection object works but fails as expected
let result = connection.execute("echo test").await;
// Should fail because no host is configured, but the connection object should work
match result {
Ok((exit_code, _)) => assert!(exit_code != 0), // Should fail due to missing host
Err(_) => {} // Error is expected when no host is configured
}
}
#[tokio::test]
async fn test_ssh_connection_builder_host_functionality() {
// Test that setting a host actually affects connection behavior
let connection = SshConnectionBuilder::new()
.host("nonexistent-host-12345.invalid")
.user("testuser")
.timeout(Duration::from_millis(100))
.build();
// This should fail because the host doesn't exist
let result = connection.execute("echo test").await;
match result {
Ok((exit_code, _)) => assert!(exit_code != 0), // Should fail
Err(_) => {} // Error is expected for invalid hosts
}
}
#[tokio::test]
async fn test_ssh_connection_builder_port_functionality() {
// Test that setting a custom port affects connection behavior
let connection = SshConnectionBuilder::new()
.host("127.0.0.1")
.port(12345) // Non-standard SSH port that should be closed
.user("testuser")
.timeout(Duration::from_millis(100))
.build();
// This should fail because port 12345 is not running SSH
let result = connection.ping().await;
match result {
Ok(success) => assert!(!success), // Should fail to connect
Err(_) => {} // Error is expected for closed ports
}
}
#[tokio::test]
async fn test_ssh_connection_builder_user_functionality() {
// Test that setting a user affects connection behavior
let connection = SshConnectionBuilder::new()
.host("127.0.0.1")
.user("nonexistent-user-12345")
.timeout(Duration::from_millis(100))
.build();
// This should fail because the user doesn't exist
let result = connection.execute("whoami").await;
match result {
Ok((exit_code, _)) => assert!(exit_code != 0), // Should fail
Err(_) => {} // Error is expected for invalid users
}
}
#[tokio::test]
async fn test_ssh_connection_builder_identity_file() {
// Test that setting an identity file affects connection behavior
let path = PathBuf::from("/nonexistent/path/to/key");
let connection = SshConnectionBuilder::new()
.host("127.0.0.1")
.user("testuser")
.identity_file(path)
.timeout(Duration::from_millis(100))
.build();
// Test that connection with identity file attempts operations but fails as expected
let result = connection.ping().await;
// Should fail due to invalid key file or authentication, but connection should work
match result {
Ok(success) => assert!(!success), // Should fail due to invalid key or auth
Err(_) => {} // Error is expected for invalid key file
}
}
#[tokio::test]
async fn test_ssh_connection_builder_timeout_functionality() {
// Test that timeout setting actually affects connection behavior
let short_timeout = Duration::from_secs(1); // More reasonable timeout
let connection = SshConnectionBuilder::new()
.host("10.255.255.1") // Non-routable IP to trigger timeout
.timeout(short_timeout)
.build();
let start = std::time::Instant::now();
let result = connection.ping().await;
let elapsed = start.elapsed();
// Should timeout reasonably quickly (within 10 seconds)
assert!(elapsed < Duration::from_secs(10));
match result {
Ok(success) => assert!(!success), // Should timeout/fail
Err(_) => {} // Error is expected for timeouts
}
}
#[tokio::test]
async fn test_ssh_connection_builder_chaining() {
// Test that method chaining works and produces a functional connection
let connection = SshConnectionBuilder::new()
.host("invalid-host-12345.test")
.port(2222)
.user("testuser")
.timeout(Duration::from_millis(100))
.build();
// Test that the chained configuration actually works
let result = connection.ping().await;
match result {
Ok(success) => assert!(!success), // Should fail to connect to invalid host
Err(_) => {} // Error is expected for invalid hosts
}
}
#[tokio::test]
async fn test_ssh_execute_invalid_host() {
let connection = SshConnectionBuilder::new()
.host("this-host-definitely-does-not-exist-12345")
.user("testuser")
.timeout(Duration::from_secs(1))
.build();
let result = connection.execute("echo 'test'").await;
// Should fail because host doesn't exist
// Note: This test depends on SSH client being available
match result {
Ok((exit_code, _output)) => {
// SSH might return various exit codes for connection failures
assert!(exit_code != 0); // Should not succeed
}
Err(_) => {
// Error is also acceptable (SSH client might not be available)
// This is expected behavior for invalid hosts
}
}
}
#[tokio::test]
async fn test_ssh_execute_localhost_no_auth() {
let connection = SshConnectionBuilder::new()
.host("localhost")
.user("nonexistentuser12345")
.timeout(Duration::from_secs(1))
.build();
let result = connection.execute("echo 'test'").await;
// Should fail due to authentication/user issues
match result {
Ok((exit_code, _output)) => {
// SSH should fail with non-zero exit code
assert!(exit_code != 0);
}
Err(_) => {
// Error is also acceptable (SSH client might not be available)
// This is expected behavior for authentication failures
}
}
}
#[tokio::test]
async fn test_ssh_ping_invalid_host() {
let connection = SshConnectionBuilder::new()
.host("this-host-definitely-does-not-exist-12345")
.user("testuser")
.timeout(Duration::from_secs(1))
.build();
let result = connection.ping().await;
match result {
Ok(success) => {
assert!(!success); // Should not succeed
}
Err(_) => {
// Error is also acceptable for invalid hosts
// This is expected behavior
}
}
}
#[tokio::test]
async fn test_ssh_ping_localhost_no_auth() {
let connection = SshConnectionBuilder::new()
.host("localhost")
.user("nonexistentuser12345")
.timeout(Duration::from_secs(1))
.build();
let result = connection.ping().await;
match result {
Ok(success) => {
// Should fail due to authentication issues
assert!(!success);
}
Err(_) => {
// Error is also acceptable for authentication failures
// This is expected behavior
}
}
}
#[tokio::test]
async fn test_ssh_connection_builder_default_values() {
// Test that builder creates connection with reasonable defaults
let connection = SshConnectionBuilder::new().build();
// Test that default connection can attempt operations but fails gracefully
let result = connection.ping().await;
// Should fail because no host is configured, but should handle it gracefully
match result {
Ok(success) => assert!(!success), // Should fail due to missing host
Err(_) => {} // Error is expected when no host is configured
}
}
#[tokio::test]
async fn test_ssh_connection_builder_full_config() {
// Test builder with all options set
let connection = SshConnectionBuilder::new()
.host("nonexistent-host-12345.invalid")
.port(2222)
.user("testuser")
.identity_file(PathBuf::from("/nonexistent/path/to/key"))
.timeout(Duration::from_millis(100))
.build();
// Test that fully configured connection attempts operations but fails as expected
let result = connection.ping().await;
// Should fail because host doesn't exist, but all configuration should be applied
match result {
Ok(success) => assert!(!success), // Should fail due to invalid host
Err(_) => {} // Error is expected for invalid host
}
}
// Integration test that requires actual SSH setup
// This test is disabled by default as it requires SSH server and keys
#[tokio::test]
#[ignore]
async fn test_ssh_execute_real_connection() {
// This test would require:
// 1. SSH server running on localhost
// 2. Valid SSH keys set up
// 3. User account configured
let connection = SshConnectionBuilder::new()
.host("localhost")
.user("testuser") // Replace with actual user
.build();
let result = connection.execute("echo 'Hello from SSH'").await;
match result {
Ok((exit_code, output)) => {
assert_eq!(exit_code, 0);
assert!(output.contains("Hello from SSH"));
}
Err(e) => {
panic!("SSH execution failed: {}", e);
}
}
}