Some checks are pending
Rhai Tests / Run Rhai Tests (push) Waiting to run
- 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.
286 lines
9.4 KiB
Rust
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);
|
|
}
|
|
}
|
|
}
|