1use thiserror::Error;
4
5use crate::Backend;
6
7pub type Result<T> = std::result::Result<T, TruenoError>;
9
10#[derive(Debug, Clone, Error, PartialEq, Eq)]
12pub enum TruenoError {
13 #[error("Backend not supported on this platform: {0:?}")]
15 UnsupportedBackend(Backend),
16
17 #[error("Size mismatch: expected {expected}, got {actual}")]
19 SizeMismatch {
20 expected: usize,
22 actual: usize,
24 },
25
26 #[error("GPU error: {0}")]
28 GpuError(String),
29
30 #[error("Invalid input: {0}")]
32 InvalidInput(String),
33
34 #[error("Division by zero")]
36 DivisionByZero,
37
38 #[error("Empty vector")]
40 EmptyVector,
41}
42
43#[cfg(test)]
44mod tests {
45 use super::*;
46
47 #[test]
48 fn test_unsupported_backend_error() {
49 let err = TruenoError::UnsupportedBackend(Backend::AVX512);
50 assert_eq!(err.to_string(), "Backend not supported on this platform: AVX512");
51 }
52
53 #[test]
54 fn test_size_mismatch_error() {
55 let err = TruenoError::SizeMismatch { expected: 10, actual: 5 };
56 assert_eq!(err.to_string(), "Size mismatch: expected 10, got 5");
57 }
58
59 #[test]
60 fn test_gpu_error() {
61 let err = TruenoError::GpuError("Device not found".to_string());
62 assert_eq!(err.to_string(), "GPU error: Device not found");
63 }
64
65 #[test]
66 fn test_invalid_input_error() {
67 let err = TruenoError::InvalidInput("Empty vector".to_string());
68 assert_eq!(err.to_string(), "Invalid input: Empty vector");
69 }
70
71 #[test]
72 fn test_error_equality() {
73 let err1 = TruenoError::SizeMismatch { expected: 10, actual: 5 };
74 let err2 = TruenoError::SizeMismatch { expected: 10, actual: 5 };
75 assert_eq!(err1, err2);
76 }
77
78 #[test]
79 fn test_division_by_zero_error() {
80 let err = TruenoError::DivisionByZero;
81 assert_eq!(err.to_string(), "Division by zero");
82 }
83
84 #[test]
85 fn test_empty_vector_error() {
86 let err = TruenoError::EmptyVector;
87 assert_eq!(err.to_string(), "Empty vector");
88 }
89
90 #[test]
95 fn test_error_debug_unsupported_backend() {
96 let err = TruenoError::UnsupportedBackend(Backend::AVX512);
97 let debug = format!("{:?}", err);
98 assert!(debug.contains("UnsupportedBackend"));
99 assert!(debug.contains("AVX512"));
100 }
101
102 #[test]
103 fn test_error_debug_size_mismatch() {
104 let err = TruenoError::SizeMismatch { expected: 100, actual: 50 };
105 let debug = format!("{:?}", err);
106 assert!(debug.contains("SizeMismatch"));
107 assert!(debug.contains("100"));
108 assert!(debug.contains("50"));
109 }
110
111 #[test]
112 fn test_error_debug_gpu_error() {
113 let err = TruenoError::GpuError("out of memory".to_string());
114 let debug = format!("{:?}", err);
115 assert!(debug.contains("GpuError"));
116 assert!(debug.contains("out of memory"));
117 }
118
119 #[test]
120 fn test_error_debug_invalid_input() {
121 let err = TruenoError::InvalidInput("negative dimension".to_string());
122 let debug = format!("{:?}", err);
123 assert!(debug.contains("InvalidInput"));
124 assert!(debug.contains("negative dimension"));
125 }
126
127 #[test]
128 fn test_error_debug_division_by_zero() {
129 let err = TruenoError::DivisionByZero;
130 let debug = format!("{:?}", err);
131 assert!(debug.contains("DivisionByZero"));
132 }
133
134 #[test]
135 fn test_error_debug_empty_vector() {
136 let err = TruenoError::EmptyVector;
137 let debug = format!("{:?}", err);
138 assert!(debug.contains("EmptyVector"));
139 }
140
141 #[test]
146 fn test_error_inequality_different_variants() {
147 let err1 = TruenoError::DivisionByZero;
148 let err2 = TruenoError::EmptyVector;
149 assert_ne!(err1, err2);
150 }
151
152 #[test]
153 fn test_error_inequality_different_values() {
154 let err1 = TruenoError::SizeMismatch { expected: 10, actual: 5 };
155 let err2 = TruenoError::SizeMismatch { expected: 20, actual: 5 };
156 assert_ne!(err1, err2);
157 }
158
159 #[test]
160 fn test_error_equality_gpu_errors() {
161 let err1 = TruenoError::GpuError("same".to_string());
162 let err2 = TruenoError::GpuError("same".to_string());
163 assert_eq!(err1, err2);
164 }
165
166 #[test]
167 fn test_error_inequality_gpu_errors() {
168 let err1 = TruenoError::GpuError("err a".to_string());
169 let err2 = TruenoError::GpuError("err b".to_string());
170 assert_ne!(err1, err2);
171 }
172
173 #[test]
174 fn test_error_equality_invalid_input() {
175 let err1 = TruenoError::InvalidInput("test".to_string());
176 let err2 = TruenoError::InvalidInput("test".to_string());
177 assert_eq!(err1, err2);
178 }
179
180 #[test]
181 fn test_error_inequality_invalid_input() {
182 let err1 = TruenoError::InvalidInput("a".to_string());
183 let err2 = TruenoError::InvalidInput("b".to_string());
184 assert_ne!(err1, err2);
185 }
186
187 #[test]
192 fn test_unsupported_backend_all_backends() {
193 let backends = [
194 (Backend::Scalar, "Scalar"),
195 (Backend::SSE2, "SSE2"),
196 (Backend::AVX, "AVX"),
197 (Backend::AVX2, "AVX2"),
198 (Backend::AVX512, "AVX512"),
199 (Backend::NEON, "NEON"),
200 (Backend::WasmSIMD, "WasmSIMD"),
201 (Backend::GPU, "GPU"),
202 (Backend::Auto, "Auto"),
203 ];
204 for (backend, name) in backends {
205 let err = TruenoError::UnsupportedBackend(backend);
206 let msg = err.to_string();
207 assert!(msg.contains(name), "Expected '{}' in '{}'", name, msg);
208 }
209 }
210
211 #[test]
212 fn test_size_mismatch_various_values() {
213 let err = TruenoError::SizeMismatch { expected: 0, actual: 0 };
214 assert_eq!(err.to_string(), "Size mismatch: expected 0, got 0");
215
216 let err = TruenoError::SizeMismatch { expected: 1000000, actual: 999999 };
217 assert!(err.to_string().contains("1000000"));
218 assert!(err.to_string().contains("999999"));
219 }
220
221 #[test]
222 fn test_gpu_error_empty_message() {
223 let err = TruenoError::GpuError(String::new());
224 assert_eq!(err.to_string(), "GPU error: ");
225 }
226
227 #[test]
228 fn test_invalid_input_empty_message() {
229 let err = TruenoError::InvalidInput(String::new());
230 assert_eq!(err.to_string(), "Invalid input: ");
231 }
232
233 #[test]
238 fn test_error_is_std_error() {
239 let err = TruenoError::DivisionByZero;
240 let _: &dyn std::error::Error = &err;
242 }
243
244 #[test]
245 fn test_error_source_is_none() {
246 use std::error::Error;
247 let err = TruenoError::DivisionByZero;
248 assert!(err.source().is_none());
249
250 let err = TruenoError::EmptyVector;
251 assert!(err.source().is_none());
252
253 let err = TruenoError::GpuError("test".to_string());
254 assert!(err.source().is_none());
255
256 let err = TruenoError::InvalidInput("test".to_string());
257 assert!(err.source().is_none());
258
259 let err = TruenoError::SizeMismatch { expected: 1, actual: 2 };
260 assert!(err.source().is_none());
261
262 let err = TruenoError::UnsupportedBackend(Backend::Scalar);
263 assert!(err.source().is_none());
264 }
265
266 #[test]
271 fn test_result_type_alias_ok() {
272 let result: Result<i32> = Ok(42);
273 assert!(result.is_ok());
274 assert_eq!(result, Ok(42));
275 }
276
277 #[test]
278 fn test_result_type_alias_err() {
279 let result: Result<i32> = Err(TruenoError::EmptyVector);
280 assert!(result.is_err());
281 }
282
283 #[test]
288 fn test_error_clone_all_variants() {
289 let errors: Vec<TruenoError> = vec![
290 TruenoError::UnsupportedBackend(Backend::AVX512),
291 TruenoError::SizeMismatch { expected: 10, actual: 5 },
292 TruenoError::GpuError("test clone".to_string()),
293 TruenoError::InvalidInput("test clone".to_string()),
294 TruenoError::DivisionByZero,
295 TruenoError::EmptyVector,
296 ];
297
298 for err in &errors {
299 let cloned = err.clone();
300 assert_eq!(*err, cloned, "Clone mismatch for {:?}", err);
301 }
302 }
303}