Skip to main content

piper_driver/
error.rs

1//! 驱动层错误类型定义
2
3use piper_can::CanError;
4use piper_protocol::ProtocolError;
5use thiserror::Error;
6
7/// 驱动层错误类型
8#[derive(Error, Debug)]
9pub enum DriverError {
10    /// CAN 驱动错误
11    #[error("CAN driver error: {0}")]
12    Can(#[from] CanError),
13
14    /// 协议解析错误
15    #[error("Protocol error: {0}")]
16    Protocol(#[from] ProtocolError),
17
18    /// 命令通道已关闭(IO 线程退出)
19    #[error("Command channel closed")]
20    ChannelClosed,
21
22    /// 命令通道已满(缓冲区容量 10)
23    #[error("Command channel full (buffer size: 10)")]
24    ChannelFull,
25
26    /// 未使用双线程模式
27    ///
28    /// 某些方法(如 `send_realtime()`)只能在双线程模式下使用。
29    #[error("Not in dual-thread mode. Use `new_dual_thread()` instead of `new()`")]
30    NotDualThread,
31
32    /// 锁被毒化(线程 panic)
33    #[error("Poisoned lock (thread panic)")]
34    PoisonedLock,
35
36    /// IO 线程错误
37    #[error("IO thread error: {0}")]
38    IoThread(String),
39
40    /// 功能未实现
41    #[error("Not implemented: {0}")]
42    NotImplemented(String),
43
44    /// 操作超时
45    #[error("Operation timeout")]
46    Timeout,
47
48    /// 无效输入(如空帧包)
49    #[error("Invalid input: {0}")]
50    InvalidInput(String),
51}
52
53#[cfg(test)]
54mod tests {
55    use super::DriverError;
56    use piper_can::CanError;
57    use piper_protocol::ProtocolError;
58
59    /// 测试 DriverError 的 Display 实现
60    #[test]
61    fn test_driver_error_display() {
62        // 测试 Can 错误
63        let can_error = CanError::Timeout;
64        let driver_error = DriverError::Can(can_error);
65        let msg = format!("{}", driver_error);
66        assert!(
67            msg.contains("Read timeout") || msg.contains("CAN"),
68            "Can error message: {}",
69            msg
70        );
71
72        // 测试 Protocol 错误
73        let protocol_error = ProtocolError::InvalidLength {
74            expected: 8,
75            actual: 4,
76        };
77        let driver_error = DriverError::Protocol(protocol_error);
78        let msg = format!("{}", driver_error);
79        assert!(
80            msg.contains("Invalid frame length"),
81            "Protocol error message: {}",
82            msg
83        );
84
85        // 测试 ChannelClosed
86        let driver_error = DriverError::ChannelClosed;
87        let msg = format!("{}", driver_error);
88        assert_eq!(msg, "Command channel closed");
89
90        // 测试 ChannelFull
91        let driver_error = DriverError::ChannelFull;
92        let msg = format!("{}", driver_error);
93        assert!(msg.contains("channel full") || msg.contains("ChannelFull"));
94
95        // 测试 PoisonedLock
96        let driver_error = DriverError::PoisonedLock;
97        let msg = format!("{}", driver_error);
98        assert!(msg.contains("Poisoned lock") || msg.contains("PoisonedLock"));
99
100        // 测试 IoThread
101        let driver_error = DriverError::IoThread("test error".to_string());
102        let msg = format!("{}", driver_error);
103        assert!(msg.contains("IO thread") && msg.contains("test error"));
104
105        // 测试 NotImplemented
106        let driver_error = DriverError::NotImplemented("feature".to_string());
107        let msg = format!("{}", driver_error);
108        assert!(msg.contains("Not implemented") && msg.contains("feature"));
109
110        // 测试 Timeout
111        let driver_error = DriverError::Timeout;
112        let msg = format!("{}", driver_error);
113        assert_eq!(msg, "Operation timeout");
114    }
115
116    /// 测试 From<CanError> 转换
117    #[test]
118    fn test_from_can_error() {
119        let can_error = CanError::Timeout;
120        let driver_error: DriverError = can_error.into();
121        match driver_error {
122            DriverError::Can(e) => assert!(matches!(e, CanError::Timeout)),
123            _ => panic!("Expected Can variant"),
124        }
125    }
126
127    /// 测试 From<ProtocolError> 转换
128    #[test]
129    fn test_from_protocol_error() {
130        let protocol_error = ProtocolError::InvalidCanId { id: 0x123 };
131        let driver_error: DriverError = protocol_error.into();
132        match driver_error {
133            DriverError::Protocol(e) => match e {
134                ProtocolError::InvalidCanId { id } => assert_eq!(id, 0x123),
135                _ => panic!("Expected InvalidCanId variant"),
136            },
137            _ => panic!("Expected Protocol variant"),
138        }
139    }
140}