quanttide_devops/contract/
error.rs1use std::fmt;
2use std::io;
3
4#[derive(Debug)]
6pub enum ContractError {
7 Io(io::Error),
9 Parse(String),
11 NotFound,
13}
14
15impl fmt::Display for ContractError {
16 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
17 match self {
18 Self::Io(e) => write!(f, "读取契约文件失败: {}", e),
19 Self::Parse(msg) => write!(f, "契约 YAML 解析失败: {}", msg),
20 Self::NotFound => write!(f, "契约文件不存在"),
21 }
22 }
23}
24
25impl std::error::Error for ContractError {
26 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
27 match self {
28 Self::Io(e) => Some(e),
29 _ => None,
30 }
31 }
32}
33
34impl From<io::Error> for ContractError {
35 fn from(e: io::Error) -> Self {
36 Self::Io(e)
37 }
38}
39
40#[cfg(test)]
41mod tests {
42 use std::error::Error;
43 use super::*;
44
45 #[test]
46 fn test_display_io() {
47 let err = ContractError::Io(std::io::Error::new(std::io::ErrorKind::NotFound, "file not found"));
48 let msg = err.to_string();
49 assert!(msg.contains("读取契约文件失败"));
50 }
51
52 #[test]
53 fn test_display_parse() {
54 let err = ContractError::Parse("syntax error".into());
55 assert!(err.to_string().contains("YAML 解析失败"));
56 }
57
58 #[test]
59 fn test_display_not_found() {
60 let err = ContractError::NotFound;
61 assert!(err.to_string().contains("契约文件不存在"));
62 }
63
64 #[test]
65 fn test_source_io() {
66 let inner = std::io::Error::new(std::io::ErrorKind::NotFound, "test");
67 let err = ContractError::Io(inner);
68 assert!(err.source().is_some());
69 }
70
71 #[test]
72 fn test_source_other() {
73 assert!(ContractError::NotFound.source().is_none());
74 assert!(ContractError::Parse("x".into()).source().is_none());
75 }
76
77 #[test]
78 fn test_from_io() {
79 let inner = std::io::Error::new(std::io::ErrorKind::PermissionDenied, "denied");
80 let err: ContractError = inner.into();
81 assert!(matches!(err, ContractError::Io(_)));
82 }
83}