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