lmrc_ssh/
error.rs

1//! Error types for SSH operations.
2
3use std::io;
4use thiserror::Error;
5
6/// Result type alias for SSH operations.
7pub type Result<T> = std::result::Result<T, Error>;
8
9/// Error types that can occur during SSH operations.
10#[derive(Debug, Error)]
11pub enum Error {
12    /// Failed to establish TCP connection to the remote host.
13    #[error("Failed to connect to {host}:{port}: {source}")]
14    ConnectionFailed {
15        host: String,
16        port: u16,
17        #[source]
18        source: io::Error,
19    },
20
21    /// SSH handshake failed.
22    #[error("SSH handshake failed: {0}")]
23    HandshakeFailed(#[from] ssh2::Error),
24
25    /// Authentication failed.
26    #[error("Authentication failed for user '{username}': {reason}")]
27    AuthenticationFailed { username: String, reason: String },
28
29    /// Failed to open an SSH channel.
30    #[error("Failed to open SSH channel: {0}")]
31    ChannelFailed(String),
32
33    /// Command execution failed.
34    #[error("Command execution failed: {0}")]
35    ExecutionFailed(String),
36
37    /// I/O error occurred.
38    #[error("I/O error: {0}")]
39    Io(#[from] io::Error),
40
41    /// Invalid configuration.
42    #[error("Invalid configuration: {0}")]
43    InvalidConfig(String),
44
45    /// The client is not connected.
46    #[error("Client is not connected. Call connect() first.")]
47    NotConnected,
48
49    /// The private key file was not found or could not be read.
50    #[error("Private key file not found or unreadable: {path}")]
51    PrivateKeyNotFound { path: String },
52}
53
54#[cfg(test)]
55mod tests {
56    use super::*;
57
58    #[test]
59    fn test_error_display() {
60        let err = Error::NotConnected;
61        assert_eq!(
62            err.to_string(),
63            "Client is not connected. Call connect() first."
64        );
65    }
66
67    #[test]
68    fn test_authentication_error() {
69        let err = Error::AuthenticationFailed {
70            username: "testuser".to_string(),
71            reason: "Invalid password".to_string(),
72        };
73        assert!(err.to_string().contains("testuser"));
74        assert!(err.to_string().contains("Invalid password"));
75    }
76
77    #[test]
78    fn test_connection_error() {
79        let io_err = io::Error::new(io::ErrorKind::ConnectionRefused, "refused");
80        let err = Error::ConnectionFailed {
81            host: "example.com".to_string(),
82            port: 22,
83            source: io_err,
84        };
85        assert!(err.to_string().contains("example.com"));
86        assert!(err.to_string().contains("22"));
87    }
88}