1#[cfg(feature = "server")]
8pub mod audit;
9pub mod client;
10pub mod config;
11pub mod manager;
12pub mod provider;
13#[cfg(feature = "server")]
14pub mod rate_limit;
15#[cfg(feature = "server")]
16pub mod server;
17#[cfg(feature = "server")]
18pub mod server_config;
19#[cfg(feature = "server")]
20pub mod storage;
21
22pub use client::TunnelClient;
23pub use config::{TunnelConfig, TunnelProvider};
24pub use manager::TunnelManager;
25pub use provider::{TunnelProvider as ProviderTrait, TunnelStatus};
26
27pub type Result<T> = std::result::Result<T, TunnelError>;
29
30#[derive(Debug, thiserror::Error)]
32pub enum TunnelError {
33 #[error("Tunnel connection failed: {0}")]
34 ConnectionFailed(String),
35
36 #[error("Tunnel provider error: {0}")]
37 ProviderError(String),
38
39 #[error("Configuration error: {0}")]
40 ConfigError(String),
41
42 #[error("Tunnel not found: {0}")]
43 NotFound(String),
44
45 #[error("Tunnel already exists: {0}")]
46 AlreadyExists(String),
47
48 #[error("HTTP error: {0}")]
49 Http(#[from] reqwest::Error),
50
51 #[error("URL parsing error: {0}")]
52 Url(#[from] url::ParseError),
53
54 #[error("Serialization error: {0}")]
55 Serialization(#[from] serde_json::Error),
56
57 #[error("IO error: {0}")]
58 Io(#[from] std::io::Error),
59}
60
61#[cfg(test)]
62mod tests {
63 use super::*;
64
65 #[test]
66 fn test_tunnel_error_connection_failed() {
67 let error = TunnelError::ConnectionFailed("connection refused".to_string());
68 let display = error.to_string();
69 assert!(display.contains("Tunnel connection failed"));
70 assert!(display.contains("connection refused"));
71 }
72
73 #[test]
74 fn test_tunnel_error_provider_error() {
75 let error = TunnelError::ProviderError("provider unavailable".to_string());
76 let display = error.to_string();
77 assert!(display.contains("Tunnel provider error"));
78 assert!(display.contains("provider unavailable"));
79 }
80
81 #[test]
82 fn test_tunnel_error_config_error() {
83 let error = TunnelError::ConfigError("missing server_url".to_string());
84 let display = error.to_string();
85 assert!(display.contains("Configuration error"));
86 assert!(display.contains("missing server_url"));
87 }
88
89 #[test]
90 fn test_tunnel_error_not_found() {
91 let error = TunnelError::NotFound("tunnel-123".to_string());
92 let display = error.to_string();
93 assert!(display.contains("Tunnel not found"));
94 assert!(display.contains("tunnel-123"));
95 }
96
97 #[test]
98 fn test_tunnel_error_already_exists() {
99 let error = TunnelError::AlreadyExists("tunnel-456".to_string());
100 let display = error.to_string();
101 assert!(display.contains("Tunnel already exists"));
102 assert!(display.contains("tunnel-456"));
103 }
104
105 #[test]
106 fn test_tunnel_error_debug() {
107 let error = TunnelError::ConnectionFailed("test".to_string());
108 let debug = format!("{:?}", error);
109 assert!(debug.contains("ConnectionFailed"));
110 assert!(debug.contains("test"));
111 }
112
113 #[test]
114 fn test_tunnel_error_from_url_parse() {
115 let url_error = url::ParseError::EmptyHost;
116 let error: TunnelError = url_error.into();
117 let display = error.to_string();
118 assert!(display.contains("URL parsing error"));
119 }
120
121 #[test]
122 fn test_tunnel_error_from_json() {
123 let json_str = "invalid json";
124 let json_error = serde_json::from_str::<serde_json::Value>(json_str).unwrap_err();
125 let error: TunnelError = json_error.into();
126 let display = error.to_string();
127 assert!(display.contains("Serialization error"));
128 }
129
130 #[test]
131 fn test_tunnel_error_from_io() {
132 let io_error = std::io::Error::new(std::io::ErrorKind::NotFound, "file not found");
133 let error: TunnelError = io_error.into();
134 let display = error.to_string();
135 assert!(display.contains("IO error"));
136 assert!(display.contains("file not found"));
137 }
138
139 #[test]
140 fn test_result_type_ok() {
141 let result: Result<i32> = Ok(42);
142 assert_eq!(result.unwrap(), 42);
143 }
144
145 #[test]
146 fn test_result_type_err() {
147 let result: Result<i32> = Err(TunnelError::NotFound("tunnel".to_string()));
148 assert!(result.is_err());
149 }
150
151 #[test]
152 fn test_tunnel_error_variants_are_send_sync() {
153 fn assert_send_sync<T: Send + Sync>() {}
154 }
158
159 #[test]
160 fn test_tunnel_error_connection_failed_empty_message() {
161 let error = TunnelError::ConnectionFailed(String::new());
162 let display = error.to_string();
163 assert!(display.contains("Tunnel connection failed"));
164 }
165
166 #[test]
167 fn test_tunnel_error_chained_display() {
168 let io_error = std::io::Error::new(std::io::ErrorKind::PermissionDenied, "access denied");
169 let error: TunnelError = io_error.into();
170 let display = error.to_string();
172 assert!(display.contains("access denied"));
173 }
174}