#![cfg(test)]
use crate::ssh::{AuthMethod, HostKeyStore, SshClient, SshConfig};
use std::sync::Arc;
use tokio::sync::RwLock;
const TEST_HOST: &str = "localhost"; const TEST_USERNAME: &str = "testuser"; const TEST_PASSWORD: &str = "testpass"; const TEST_PORT: u16 = 22;
fn test_host_keys() -> Arc<HostKeyStore> {
let tmp = std::env::temp_dir().join(format!("r-shell-test-known_hosts-{}", std::process::id()));
Arc::new(HostKeyStore::new(tmp))
}
fn create_test_config() -> SshConfig {
SshConfig {
host: TEST_HOST.to_string(),
port: TEST_PORT,
username: TEST_USERNAME.to_string(),
auth_method: AuthMethod::Password {
password: TEST_PASSWORD.to_string(),
},
}
}
#[test]
fn test_ssh_config_creation() {
let config = create_test_config();
assert_eq!(config.host, "localhost");
assert_eq!(config.port, 22);
assert_eq!(config.username, "testuser");
}
#[tokio::test]
#[ignore]
async fn test_ssh_connection() {
let client = Arc::new(RwLock::new(SshClient::new(test_host_keys())));
let mut client_write = client.write().await;
let config = create_test_config();
let result = client_write.connect(&config).await;
assert!(
result.is_ok(),
"SSH connection should succeed: {:?}",
result.err()
);
let disconnect_result = client_write.disconnect().await;
assert!(disconnect_result.is_ok(), "Disconnect should succeed");
}
#[tokio::test]
#[ignore]
async fn test_execute_command() {
let client = Arc::new(RwLock::new(SshClient::new(test_host_keys())));
let mut client_write = client.write().await;
let config = create_test_config();
client_write
.connect(&config)
.await
.expect("Failed to connect");
let output = client_write
.execute_command("echo 'test'")
.await
.expect("Failed to execute command");
assert!(
output.contains("test"),
"Command output should contain 'test'"
);
client_write.disconnect().await.ok();
}
#[tokio::test]
#[ignore]
async fn test_invalid_credentials() {
let client = Arc::new(RwLock::new(SshClient::new(test_host_keys())));
let mut client_write = client.write().await;
let config = SshConfig {
host: TEST_HOST.to_string(),
port: TEST_PORT,
username: TEST_USERNAME.to_string(),
auth_method: AuthMethod::Password {
password: "wrongpassword".to_string(),
},
};
let result = client_write.connect(&config).await;
assert!(
result.is_err(),
"Connection with invalid password should fail"
);
}
#[tokio::test]
#[ignore]
async fn test_get_system_stats() {
let client = Arc::new(RwLock::new(SshClient::new(test_host_keys())));
let mut client_write = client.write().await;
let config = create_test_config();
client_write
.connect(&config)
.await
.expect("Failed to connect");
let cpu_output = client_write
.execute_command("top -bn1 | grep 'Cpu(s)' | awk '{print $2}' | cut -d'%' -f1")
.await;
assert!(cpu_output.is_ok(), "Should get CPU stats");
let mem_output = client_write
.execute_command("free | grep Mem | awk '{print ($3/$2) * 100.0}'")
.await;
assert!(mem_output.is_ok(), "Should get memory stats");
client_write.disconnect().await.ok();
}
#[tokio::test]
#[ignore]
async fn test_process_list() {
let client = Arc::new(RwLock::new(SshClient::new(test_host_keys())));
let mut client_write = client.write().await;
let config = create_test_config();
client_write
.connect(&config)
.await
.expect("Failed to connect");
let output = client_write
.execute_command("ps aux | sort -k3nr | head -10")
.await
.expect("Failed to get process list");
assert!(!output.is_empty(), "Process list should not be empty");
assert!(
output.contains("PID") || output.contains("USER"),
"Output should contain process info"
);
client_write.disconnect().await.ok();
}