1#[cfg(feature = "quic")]
6use runtara_protocol::ClientError;
7use thiserror::Error;
8
9#[derive(Debug, Error)]
11pub enum SdkError {
12 #[error("configuration error: {0}")]
14 Config(String),
15
16 #[cfg(feature = "quic")]
18 #[error("connection error: {0}")]
19 Connection(#[from] ClientError),
20
21 #[error("registration failed: {0}")]
23 Registration(String),
24
25 #[error("checkpoint error: {0}")]
27 Checkpoint(String),
28
29 #[error("sleep error: {0}")]
31 Sleep(String),
32
33 #[error("event error: {0}")]
35 Event(String),
36
37 #[error("signal error: {0}")]
39 Signal(String),
40
41 #[error("status error: {0}")]
43 Status(String),
44
45 #[error("server error: {code} - {message}")]
47 Server {
48 code: String,
50 message: String,
52 },
53
54 #[error("instance cancelled")]
56 Cancelled,
57
58 #[error("instance paused")]
60 Paused,
61
62 #[error("serialization error: {0}")]
64 Serialization(String),
65
66 #[error("unexpected response: {0}")]
68 UnexpectedResponse(String),
69
70 #[error("internal error: {0}")]
72 Internal(String),
73}
74
75impl From<prost::DecodeError> for SdkError {
76 fn from(err: prost::DecodeError) -> Self {
77 SdkError::Serialization(err.to_string())
78 }
79}
80
81pub type Result<T> = std::result::Result<T, SdkError>;
83
84#[cfg(test)]
85mod tests {
86 use super::*;
87
88 #[test]
89 fn test_config_error_display() {
90 let err = SdkError::Config("missing RUNTARA_INSTANCE_ID".to_string());
91 assert_eq!(
92 format!("{}", err),
93 "configuration error: missing RUNTARA_INSTANCE_ID"
94 );
95 }
96
97 #[test]
98 fn test_registration_error_display() {
99 let err = SdkError::Registration("instance already exists".to_string());
100 assert_eq!(
101 format!("{}", err),
102 "registration failed: instance already exists"
103 );
104 }
105
106 #[test]
107 fn test_checkpoint_error_display() {
108 let err = SdkError::Checkpoint("failed to save state".to_string());
109 assert_eq!(format!("{}", err), "checkpoint error: failed to save state");
110 }
111
112 #[test]
113 fn test_sleep_error_display() {
114 let err = SdkError::Sleep("invalid duration".to_string());
115 assert_eq!(format!("{}", err), "sleep error: invalid duration");
116 }
117
118 #[test]
119 fn test_event_error_display() {
120 let err = SdkError::Event("failed to send event".to_string());
121 assert_eq!(format!("{}", err), "event error: failed to send event");
122 }
123
124 #[test]
125 fn test_signal_error_display() {
126 let err = SdkError::Signal("signal rejected".to_string());
127 assert_eq!(format!("{}", err), "signal error: signal rejected");
128 }
129
130 #[test]
131 fn test_status_error_display() {
132 let err = SdkError::Status("not found".to_string());
133 assert_eq!(format!("{}", err), "status error: not found");
134 }
135
136 #[test]
137 fn test_server_error_display() {
138 let err = SdkError::Server {
139 code: "ERR_NOT_FOUND".to_string(),
140 message: "Instance not found".to_string(),
141 };
142 assert_eq!(
143 format!("{}", err),
144 "server error: ERR_NOT_FOUND - Instance not found"
145 );
146 }
147
148 #[test]
149 fn test_cancelled_error_display() {
150 let err = SdkError::Cancelled;
151 assert_eq!(format!("{}", err), "instance cancelled");
152 }
153
154 #[test]
155 fn test_paused_error_display() {
156 let err = SdkError::Paused;
157 assert_eq!(format!("{}", err), "instance paused");
158 }
159
160 #[test]
161 fn test_serialization_error_display() {
162 let err = SdkError::Serialization("invalid JSON".to_string());
163 assert_eq!(format!("{}", err), "serialization error: invalid JSON");
164 }
165
166 #[test]
167 fn test_unexpected_response_error_display() {
168 let err = SdkError::UnexpectedResponse("expected Ack".to_string());
169 assert_eq!(format!("{}", err), "unexpected response: expected Ack");
170 }
171
172 #[test]
173 fn test_internal_error_display() {
174 let err = SdkError::Internal("mutex poisoned".to_string());
175 assert_eq!(format!("{}", err), "internal error: mutex poisoned");
176 }
177
178 #[test]
179 fn test_error_debug() {
180 let err = SdkError::Config("test".to_string());
181 let debug_str = format!("{:?}", err);
182 assert!(debug_str.contains("Config"));
183 assert!(debug_str.contains("test"));
184 }
185
186 #[test]
187 fn test_server_error_debug() {
188 let err = SdkError::Server {
189 code: "ERR_500".to_string(),
190 message: "Internal error".to_string(),
191 };
192 let debug_str = format!("{:?}", err);
193 assert!(debug_str.contains("Server"));
194 assert!(debug_str.contains("ERR_500"));
195 assert!(debug_str.contains("Internal error"));
196 }
197
198 #[test]
199 fn test_from_prost_decode_error() {
200 let invalid_bytes = vec![0xFF, 0xFF, 0xFF];
202 let decode_result: std::result::Result<runtara_protocol::instance_proto::InstanceEvent, _> =
203 prost::Message::decode(invalid_bytes.as_slice());
204
205 if let Err(decode_error) = decode_result {
206 let sdk_error: SdkError = decode_error.into();
207 let msg = format!("{}", sdk_error);
208 assert!(msg.starts_with("serialization error:"));
209 }
210 }
211
212 #[test]
213 fn test_result_type_alias() {
214 fn returns_ok() -> Result<i32> {
215 Ok(42)
216 }
217
218 fn returns_err() -> Result<i32> {
219 Err(SdkError::Internal("test".to_string()))
220 }
221
222 assert!(returns_ok().is_ok());
223 assert!(returns_err().is_err());
224 }
225}