piper_sdk/robot/
error.rs

1//! Robot 模块错误类型定义
2
3use crate::can::CanError;
4use crate::protocol::ProtocolError;
5use thiserror::Error;
6
7/// Robot 模块错误类型
8#[derive(Error, Debug)]
9pub enum RobotError {
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#[cfg(test)]
50mod tests {
51    use super::RobotError;
52    use crate::can::CanError;
53    use crate::protocol::ProtocolError;
54
55    /// 测试 RobotError 的 Display 实现
56    #[test]
57    fn test_robot_error_display() {
58        // 测试 Can 错误
59        let can_error = CanError::Timeout;
60        let robot_error = RobotError::Can(can_error);
61        let msg = format!("{}", robot_error);
62        assert!(
63            msg.contains("Read timeout") || msg.contains("CAN"),
64            "Can error message: {}",
65            msg
66        );
67
68        // 测试 Protocol 错误
69        let protocol_error = ProtocolError::InvalidLength {
70            expected: 8,
71            actual: 4,
72        };
73        let robot_error = RobotError::Protocol(protocol_error);
74        let msg = format!("{}", robot_error);
75        assert!(
76            msg.contains("Invalid frame length"),
77            "Protocol error message: {}",
78            msg
79        );
80
81        // 测试 ChannelClosed
82        let robot_error = RobotError::ChannelClosed;
83        let msg = format!("{}", robot_error);
84        assert_eq!(msg, "Command channel closed");
85
86        // 测试 ChannelFull
87        let robot_error = RobotError::ChannelFull;
88        let msg = format!("{}", robot_error);
89        assert!(msg.contains("channel full") || msg.contains("ChannelFull"));
90
91        // 测试 PoisonedLock
92        let robot_error = RobotError::PoisonedLock;
93        let msg = format!("{}", robot_error);
94        assert!(msg.contains("Poisoned lock") || msg.contains("PoisonedLock"));
95
96        // 测试 IoThread
97        let robot_error = RobotError::IoThread("test error".to_string());
98        let msg = format!("{}", robot_error);
99        assert!(msg.contains("IO thread") && msg.contains("test error"));
100
101        // 测试 NotImplemented
102        let robot_error = RobotError::NotImplemented("feature".to_string());
103        let msg = format!("{}", robot_error);
104        assert!(msg.contains("Not implemented") && msg.contains("feature"));
105
106        // 测试 Timeout
107        let robot_error = RobotError::Timeout;
108        let msg = format!("{}", robot_error);
109        assert_eq!(msg, "Operation timeout");
110    }
111
112    /// 测试 From<CanError> 转换
113    #[test]
114    fn test_from_can_error() {
115        let can_error = CanError::Timeout;
116        let robot_error: RobotError = can_error.into();
117        match robot_error {
118            RobotError::Can(e) => assert!(matches!(e, CanError::Timeout)),
119            _ => panic!("Expected Can variant"),
120        }
121    }
122
123    /// 测试 From<ProtocolError> 转换
124    #[test]
125    fn test_from_protocol_error() {
126        let protocol_error = ProtocolError::InvalidCanId { id: 0x123 };
127        let robot_error: RobotError = protocol_error.into();
128        match robot_error {
129            RobotError::Protocol(e) => match e {
130                ProtocolError::InvalidCanId { id } => assert_eq!(id, 0x123),
131                _ => panic!("Expected InvalidCanId variant"),
132            },
133            _ => panic!("Expected Protocol variant"),
134        }
135    }
136}