1use std::fmt;
2use std::time::Duration;
3
4#[derive(Debug)]
6pub enum ScatterProxyError {
7 Timeout { elapsed: Duration },
9 PoolFull { capacity: usize },
11 Init(String),
13}
14
15impl fmt::Display for ScatterProxyError {
16 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
17 match self {
18 ScatterProxyError::Timeout { elapsed } => {
19 write!(f, "task timeout after {:.1}s", elapsed.as_secs_f64())
20 }
21 ScatterProxyError::PoolFull { capacity } => {
22 write!(f, "task pool is full (capacity: {capacity})")
23 }
24 ScatterProxyError::Init(reason) => {
25 write!(f, "initialization error: {reason}")
26 }
27 }
28 }
29}
30
31impl std::error::Error for ScatterProxyError {}
32
33#[cfg(test)]
34mod tests {
35 use super::*;
36
37 #[test]
38 fn display_timeout() {
39 let err = ScatterProxyError::Timeout {
40 elapsed: Duration::from_millis(8500),
41 };
42 let msg = err.to_string();
43 assert!(msg.contains("8.5s"));
44 }
45
46 #[test]
47 fn display_pool_full() {
48 let err = ScatterProxyError::PoolFull { capacity: 1000 };
49 let msg = err.to_string();
50 assert!(msg.contains("task pool is full"));
51 assert!(msg.contains("1000"));
52 }
53
54 #[test]
55 fn display_init() {
56 let err = ScatterProxyError::Init("failed to fetch proxy list".into());
57 let msg = err.to_string();
58 assert!(msg.contains("initialization error"));
59 assert!(msg.contains("failed to fetch proxy list"));
60 }
61
62 #[test]
63 fn error_trait_is_implemented() {
64 let err: Box<dyn std::error::Error> = Box::new(ScatterProxyError::Init("test".into()));
65 assert!(err.source().is_none());
66 }
67
68 #[test]
69 fn debug_format_includes_variant_name() {
70 let err = ScatterProxyError::Timeout {
71 elapsed: Duration::from_secs(1),
72 };
73 let dbg = format!("{err:?}");
74 assert!(dbg.contains("Timeout"));
75 }
76
77 #[test]
78 fn timeout_sub_second_formatting() {
79 let err = ScatterProxyError::Timeout {
80 elapsed: Duration::from_millis(200),
81 };
82 assert!(err.to_string().contains("0.2s"));
83 }
84
85 #[test]
86 fn timeout_exact_seconds_formatting() {
87 let err = ScatterProxyError::Timeout {
88 elapsed: Duration::from_secs(60),
89 };
90 assert!(err.to_string().contains("60.0s"));
91 }
92}