1use thiserror::Error;
6
7#[derive(Error, Debug)]
11pub enum DDPError {
12 #[error("socket error")]
14 Disconnect(#[from] std::io::Error),
15
16 #[error("No valid socket addr found")]
18 NoValidSocketAddr,
19
20 #[error("parse error")]
22 ParseError(#[from] serde_json::Error),
23
24 #[error("invalid sender, did you forget to connect() ( data from {from:?} - {data:?})")]
26 UnknownClient {
27 from: std::net::SocketAddr,
29 data: Vec<u8>,
31 },
32
33 #[error("Invalid packet")]
35 InvalidPacket,
36
37 #[error("There are no packets waiting to be read. This error should be handled explicitly")]
39 NothingToReceive,
40
41 #[error("Error receiving packet: {0}")]
43 CrossBeamError(#[from] crossbeam::channel::TryRecvError),
44}
45
46#[cfg(test)]
47mod tests {
48 use super::*;
49 use std::net::{IpAddr, Ipv4Addr, SocketAddr};
50
51 #[test]
52 fn test_error_display_disconnect() {
53 let io_error = std::io::Error::new(std::io::ErrorKind::ConnectionReset, "connection reset");
54 let error = DDPError::Disconnect(io_error);
55 assert_eq!(error.to_string(), "socket error");
56 }
57
58 #[test]
59 fn test_error_display_no_valid_socket_addr() {
60 let error = DDPError::NoValidSocketAddr;
61 assert_eq!(error.to_string(), "No valid socket addr found");
62 }
63
64 #[test]
65 fn test_error_display_parse_error() {
66 let json_error = serde_json::from_str::<serde_json::Value>("{invalid json")
67 .expect_err("should fail to parse");
68 let error = DDPError::ParseError(json_error);
69 assert_eq!(error.to_string(), "parse error");
70 }
71
72 #[test]
73 fn test_error_display_unknown_client() {
74 let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(192, 168, 1, 1)), 8080);
75 let data = vec![0x01, 0x02, 0x03];
76 let error = DDPError::UnknownClient {
77 from: addr,
78 data: data.clone(),
79 };
80
81 let error_str = error.to_string();
82 assert!(error_str.contains("invalid sender"));
83 assert!(error_str.contains("192.168.1.1:8080"));
84 assert!(error_str.contains("[1, 2, 3]"));
85 }
86
87 #[test]
88 fn test_error_display_invalid_packet() {
89 let error = DDPError::InvalidPacket;
90 assert_eq!(error.to_string(), "Invalid packet");
91 }
92
93 #[test]
94 fn test_error_display_nothing_to_receive() {
95 let error = DDPError::NothingToReceive;
96 assert_eq!(
97 error.to_string(),
98 "There are no packets waiting to be read. This error should be handled explicitly"
99 );
100 }
101
102 #[test]
103 fn test_error_display_crossbeam_error() {
104 use crossbeam::channel::TryRecvError;
105
106 let error = DDPError::CrossBeamError(TryRecvError::Empty);
107 assert!(error.to_string().contains("Error receiving packet"));
108 }
109
110 #[test]
111 fn test_error_from_io_error() {
112 let io_error = std::io::Error::new(std::io::ErrorKind::BrokenPipe, "broken pipe");
113 let error: DDPError = io_error.into();
114
115 match error {
116 DDPError::Disconnect(_) => {},
117 _ => panic!("Expected Disconnect variant"),
118 }
119 }
120
121 #[test]
122 fn test_error_from_json_error() {
123 let json_error = serde_json::from_str::<serde_json::Value>("{bad}")
124 .expect_err("should fail");
125 let error: DDPError = json_error.into();
126
127 match error {
128 DDPError::ParseError(_) => {},
129 _ => panic!("Expected ParseError variant"),
130 }
131 }
132
133 #[test]
134 fn test_error_from_crossbeam_error() {
135 use crossbeam::channel::TryRecvError;
136
137 let crossbeam_error = TryRecvError::Disconnected;
138 let error: DDPError = crossbeam_error.into();
139
140 match error {
141 DDPError::CrossBeamError(_) => {},
142 _ => panic!("Expected CrossBeamError variant"),
143 }
144 }
145
146 #[test]
147 fn test_error_debug_format() {
148 let error = DDPError::InvalidPacket;
149 let debug_str = format!("{:?}", error);
150 assert_eq!(debug_str, "InvalidPacket");
151 }
152
153 #[test]
154 fn test_unknown_client_error_fields() {
155 let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(10, 0, 0, 1)), 4048);
156 let data = vec![0xDE, 0xAD, 0xBE, 0xEF];
157
158 let error = DDPError::UnknownClient {
159 from: addr.clone(),
160 data: data.clone(),
161 };
162
163 match error {
164 DDPError::UnknownClient { from, data: d } => {
165 assert_eq!(from, addr);
166 assert_eq!(d, data);
167 }
168 _ => panic!("Expected UnknownClient variant"),
169 }
170 }
171
172 #[test]
173 fn test_error_is_send_sync() {
174 fn assert_send_sync<T: Send + Sync>() {}
175 assert_send_sync::<DDPError>();
176 }
177}