Skip to main content

arcbox_virtio/
error.rs

1//! Error types for `VirtIO` devices.
2
3use arcbox_error::CommonError;
4use thiserror::Error;
5
6/// Result type alias for `VirtIO` operations.
7pub type Result<T> = std::result::Result<T, VirtioError>;
8
9/// Errors that can occur during `VirtIO` operations.
10#[derive(Debug, Error)]
11pub enum VirtioError {
12    /// Common error from arcbox-error.
13    #[error(transparent)]
14    Common(#[from] CommonError),
15
16    /// Device not ready.
17    #[error("device not ready: {0}")]
18    NotReady(String),
19
20    /// Invalid queue configuration.
21    #[error("invalid queue configuration: {0}")]
22    InvalidQueue(String),
23
24    /// Invalid descriptor.
25    #[error("invalid descriptor: {0}")]
26    InvalidDescriptor(String),
27
28    /// Buffer too small.
29    #[error("buffer too small: need {needed}, got {got}")]
30    BufferTooSmall { needed: usize, got: usize },
31
32    /// `VirtIO` I/O error (string message).
33    #[error("I/O error: {0}")]
34    Io(String),
35
36    /// Memory error.
37    #[error("memory error: {0}")]
38    MemoryError(String),
39
40    /// Device-specific error.
41    #[error("{device} error: {message}")]
42    DeviceError { device: String, message: String },
43
44    /// Feature not supported.
45    #[error("feature not supported: {0}")]
46    FeatureNotSupported(String),
47
48    /// Operation not supported.
49    #[error("operation not supported: {0}")]
50    NotSupported(String),
51
52    /// Invalid operation.
53    #[error("invalid operation: {0}")]
54    InvalidOperation(String),
55}
56
57// Allow automatic conversion from std::io::Error to VirtioError via CommonError.
58impl From<std::io::Error> for VirtioError {
59    fn from(err: std::io::Error) -> Self {
60        Self::Common(CommonError::from(err))
61    }
62}
63
64#[cfg(test)]
65mod tests {
66    use super::*;
67
68    #[test]
69    fn test_not_ready_error() {
70        let err = VirtioError::NotReady("device not initialized".to_string());
71        assert!(err.to_string().contains("device not ready"));
72        assert!(err.to_string().contains("device not initialized"));
73    }
74
75    #[test]
76    fn test_invalid_queue_error() {
77        let err = VirtioError::InvalidQueue("size must be power of 2".to_string());
78        assert!(err.to_string().contains("invalid queue"));
79    }
80
81    #[test]
82    fn test_invalid_descriptor_error() {
83        let err = VirtioError::InvalidDescriptor("out of bounds".to_string());
84        assert!(err.to_string().contains("invalid descriptor"));
85    }
86
87    #[test]
88    fn test_buffer_too_small_error() {
89        let err = VirtioError::BufferTooSmall {
90            needed: 1024,
91            got: 512,
92        };
93        let msg = err.to_string();
94        assert!(msg.contains("1024"));
95        assert!(msg.contains("512"));
96    }
97
98    #[test]
99    fn test_io_error() {
100        let err = VirtioError::Io("read failed".to_string());
101        assert!(err.to_string().contains("I/O error"));
102    }
103
104    #[test]
105    fn test_io_error_from_std() {
106        let std_err = std::io::Error::new(std::io::ErrorKind::NotFound, "file not found");
107        let err: VirtioError = std_err.into();
108        assert!(err.to_string().contains("file not found"));
109    }
110
111    #[test]
112    fn test_memory_error() {
113        let err = VirtioError::MemoryError("allocation failed".to_string());
114        assert!(err.to_string().contains("memory error"));
115    }
116
117    #[test]
118    fn test_device_error() {
119        let err = VirtioError::DeviceError {
120            device: "block".to_string(),
121            message: "disk full".to_string(),
122        };
123        let msg = err.to_string();
124        assert!(msg.contains("block"));
125        assert!(msg.contains("disk full"));
126    }
127
128    #[test]
129    fn test_feature_not_supported() {
130        let err = VirtioError::FeatureNotSupported("multiqueue".to_string());
131        assert!(err.to_string().contains("feature not supported"));
132    }
133
134    #[test]
135    fn test_not_supported_error() {
136        let err = VirtioError::NotSupported("flush".to_string());
137        assert!(err.to_string().contains("operation not supported"));
138    }
139
140    #[test]
141    fn test_invalid_operation_error() {
142        let err = VirtioError::InvalidOperation("write to read-only".to_string());
143        assert!(err.to_string().contains("invalid operation"));
144    }
145
146    #[test]
147    fn test_error_debug() {
148        let err = VirtioError::NotReady("test".to_string());
149        let debug_str = format!("{:?}", err);
150        assert!(debug_str.contains("NotReady"));
151    }
152
153    #[test]
154    fn test_result_type_alias() {
155        fn returns_ok() -> Result<u32> {
156            Ok(42)
157        }
158
159        fn returns_err() -> Result<u32> {
160            Err(VirtioError::NotReady("test".to_string()))
161        }
162
163        assert!(returns_ok().is_ok());
164        assert!(returns_err().is_err());
165    }
166}