xref: /drstd/src/std/io/error/tests.rs (revision 86982c5e9b2eaa583327251616ee822c36288824)
1 use super::{const_io_error, Custom, Error, ErrorData, ErrorKind, Repr, SimpleMessage};
2 use crate::std::assert_matches::assert_matches;
3 use crate::std::error;
4 use crate::std::fmt;
5 use crate::std::mem::size_of;
6 use crate::std::sys::decode_error_kind;
7 use crate::std::sys::os::error_string;
8 
9 #[test]
10 fn test_size() {
11     assert!(size_of::<Error>() <= size_of::<[usize; 2]>());
12 }
13 
14 #[test]
15 fn test_debug_error() {
16     let code = 6;
17     let msg = error_string(code);
18     let kind = decode_error_kind(code);
19     let err = Error {
20         repr: Repr::new_custom(Box::new(Custom {
21             kind: ErrorKind::InvalidInput,
22             error: Box::new(Error {
23                 repr: super::Repr::new_os(code),
24             }),
25         })),
26     };
27     let expected = format!(
28         "Custom {{ \
29          kind: InvalidInput, \
30          error: Os {{ \
31          code: {:?}, \
32          kind: {:?}, \
33          message: {:?} \
34          }} \
35          }}",
36         code, kind, msg
37     );
38     assert_eq!(format!("{err:?}"), expected);
39 }
40 
41 #[test]
42 fn test_downcasting() {
43     #[derive(Debug)]
44     struct TestError;
45 
46     impl fmt::Display for TestError {
47         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
48             f.write_str("asdf")
49         }
50     }
51 
52     impl error::Error for TestError {}
53 
54     // we have to call all of these UFCS style right now since method
55     // resolution won't implicitly drop the Send+Sync bounds
56     let mut err = Error::new(ErrorKind::Other, TestError);
57     assert!(err.get_ref().unwrap().is::<TestError>());
58     assert_eq!("asdf", err.get_ref().unwrap().to_string());
59     assert!(err.get_mut().unwrap().is::<TestError>());
60     let extracted = err.into_inner().unwrap();
61     extracted.downcast::<TestError>().unwrap();
62 }
63 
64 #[test]
65 fn test_const() {
66     const E: Error = const_io_error!(ErrorKind::NotFound, "hello");
67 
68     assert_eq!(E.kind(), ErrorKind::NotFound);
69     assert_eq!(E.to_string(), "hello");
70     assert!(format!("{E:?}").contains("\"hello\""));
71     assert!(format!("{E:?}").contains("NotFound"));
72 }
73 
74 #[test]
75 fn test_os_packing() {
76     for code in -20..20 {
77         let e = Error::from_raw_os_error(code);
78         assert_eq!(e.raw_os_error(), Some(code));
79         assert_matches!(
80             e.repr.data(),
81             ErrorData::Os(c) if c == code,
82         );
83     }
84 }
85 
86 #[test]
87 fn test_errorkind_packing() {
88     assert_eq!(Error::from(ErrorKind::NotFound).kind(), ErrorKind::NotFound);
89     assert_eq!(
90         Error::from(ErrorKind::PermissionDenied).kind(),
91         ErrorKind::PermissionDenied
92     );
93     assert_eq!(
94         Error::from(ErrorKind::Uncategorized).kind(),
95         ErrorKind::Uncategorized
96     );
97     // Check that the innards look like what we want.
98     assert_matches!(
99         Error::from(ErrorKind::OutOfMemory).repr.data(),
100         ErrorData::Simple(ErrorKind::OutOfMemory),
101     );
102 }
103 
104 #[test]
105 fn test_simple_message_packing() {
106     use super::{ErrorKind::*, SimpleMessage};
107     macro_rules! check_simple_msg {
108         ($err:expr, $kind:ident, $msg:literal) => {{
109             let e = &$err;
110             // Check that the public api is right.
111             assert_eq!(e.kind(), $kind);
112             assert!(format!("{e:?}").contains($msg));
113             // and we got what we expected
114             assert_matches!(
115                 e.repr.data(),
116                 ErrorData::SimpleMessage(SimpleMessage {
117                     kind: $kind,
118                     message: $msg
119                 })
120             );
121         }};
122     }
123 
124     let not_static = const_io_error!(Uncategorized, "not a constant!");
125     check_simple_msg!(not_static, Uncategorized, "not a constant!");
126 
127     const CONST: Error = const_io_error!(NotFound, "definitely a constant!");
128     check_simple_msg!(CONST, NotFound, "definitely a constant!");
129 
130     static STATIC: Error = const_io_error!(BrokenPipe, "a constant, sort of!");
131     check_simple_msg!(STATIC, BrokenPipe, "a constant, sort of!");
132 }
133 
134 #[derive(Debug, PartialEq)]
135 struct Bojji(bool);
136 impl error::Error for Bojji {}
137 impl fmt::Display for Bojji {
138     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
139         write!(f, "ah! {:?}", self)
140     }
141 }
142 
143 #[test]
144 fn test_custom_error_packing() {
145     use super::Custom;
146     let test = Error::new(ErrorKind::Uncategorized, Bojji(true));
147     assert_matches!(
148         test.repr.data(),
149         ErrorData::Custom(Custom {
150             kind: ErrorKind::Uncategorized,
151             error,
152         }) if error.downcast_ref::<Bojji>().as_deref() == Some(&Bojji(true)),
153     );
154 }
155 
156 #[derive(Debug)]
157 struct E;
158 
159 impl fmt::Display for E {
160     fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
161         Ok(())
162     }
163 }
164 
165 impl error::Error for E {}
166 
167 #[test]
168 fn test_std_io_error_downcast() {
169     // Case 1: custom error, downcast succeeds
170     let io_error = Error::new(ErrorKind::Other, Bojji(true));
171     let e: Box<Bojji> = io_error.downcast().unwrap();
172     assert!(e.0);
173 
174     // Case 2: custom error, downcast fails
175     let io_error = Error::new(ErrorKind::Other, Bojji(true));
176     let io_error = io_error.downcast::<E>().unwrap_err();
177 
178     //   ensures that the custom error is intact
179     assert_eq!(ErrorKind::Other, io_error.kind());
180     let e: Box<Bojji> = io_error.downcast().unwrap();
181     assert!(e.0);
182 
183     // Case 3: os error
184     let errno = 20;
185     let io_error = Error::from_raw_os_error(errno);
186     let io_error = io_error.downcast::<E>().unwrap_err();
187 
188     assert_eq!(errno, io_error.raw_os_error().unwrap());
189 
190     // Case 4: simple
191     let kind = ErrorKind::OutOfMemory;
192     let io_error: Error = kind.into();
193     let io_error = io_error.downcast::<E>().unwrap_err();
194 
195     assert_eq!(kind, io_error.kind());
196 
197     // Case 5: simple message
198     const SIMPLE_MESSAGE: SimpleMessage = SimpleMessage {
199         kind: ErrorKind::Other,
200         message: "simple message error test",
201     };
202     let io_error = Error::from_static_message(&SIMPLE_MESSAGE);
203     let io_error = io_error.downcast::<E>().unwrap_err();
204 
205     assert_eq!(SIMPLE_MESSAGE.kind, io_error.kind());
206     assert_eq!(SIMPLE_MESSAGE.message, format!("{io_error}"));
207 }
208