summaryrefslogtreecommitdiffstats
path: root/library/std/src/io/error/tests.rs
diff options
context:
space:
mode:
Diffstat (limited to 'library/std/src/io/error/tests.rs')
-rw-r--r--library/std/src/io/error/tests.rs194
1 files changed, 194 insertions, 0 deletions
diff --git a/library/std/src/io/error/tests.rs b/library/std/src/io/error/tests.rs
new file mode 100644
index 000000000..c897a5e87
--- /dev/null
+++ b/library/std/src/io/error/tests.rs
@@ -0,0 +1,194 @@
+use super::{const_io_error, Custom, Error, ErrorData, ErrorKind, Repr, SimpleMessage};
+use crate::assert_matches::assert_matches;
+use crate::error;
+use crate::fmt;
+use crate::mem::size_of;
+use crate::sys::decode_error_kind;
+use crate::sys::os::error_string;
+
+#[test]
+fn test_size() {
+ assert!(size_of::<Error>() <= size_of::<[usize; 2]>());
+}
+
+#[test]
+fn test_debug_error() {
+ let code = 6;
+ let msg = error_string(code);
+ let kind = decode_error_kind(code);
+ let err = Error {
+ repr: Repr::new_custom(Box::new(Custom {
+ kind: ErrorKind::InvalidInput,
+ error: Box::new(Error { repr: super::Repr::new_os(code) }),
+ })),
+ };
+ let expected = format!(
+ "Custom {{ \
+ kind: InvalidInput, \
+ error: Os {{ \
+ code: {:?}, \
+ kind: {:?}, \
+ message: {:?} \
+ }} \
+ }}",
+ code, kind, msg
+ );
+ assert_eq!(format!("{err:?}"), expected);
+}
+
+#[test]
+fn test_downcasting() {
+ #[derive(Debug)]
+ struct TestError;
+
+ impl fmt::Display for TestError {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.write_str("asdf")
+ }
+ }
+
+ impl error::Error for TestError {}
+
+ // we have to call all of these UFCS style right now since method
+ // resolution won't implicitly drop the Send+Sync bounds
+ let mut err = Error::new(ErrorKind::Other, TestError);
+ assert!(err.get_ref().unwrap().is::<TestError>());
+ assert_eq!("asdf", err.get_ref().unwrap().to_string());
+ assert!(err.get_mut().unwrap().is::<TestError>());
+ let extracted = err.into_inner().unwrap();
+ extracted.downcast::<TestError>().unwrap();
+}
+
+#[test]
+fn test_const() {
+ const E: Error = const_io_error!(ErrorKind::NotFound, "hello");
+
+ assert_eq!(E.kind(), ErrorKind::NotFound);
+ assert_eq!(E.to_string(), "hello");
+ assert!(format!("{E:?}").contains("\"hello\""));
+ assert!(format!("{E:?}").contains("NotFound"));
+}
+
+#[test]
+fn test_os_packing() {
+ for code in -20i32..20i32 {
+ let e = Error::from_raw_os_error(code);
+ assert_eq!(e.raw_os_error(), Some(code));
+ assert_matches!(
+ e.repr.data(),
+ ErrorData::Os(c) if c == code,
+ );
+ }
+}
+
+#[test]
+fn test_errorkind_packing() {
+ assert_eq!(Error::from(ErrorKind::NotFound).kind(), ErrorKind::NotFound);
+ assert_eq!(Error::from(ErrorKind::PermissionDenied).kind(), ErrorKind::PermissionDenied);
+ assert_eq!(Error::from(ErrorKind::Uncategorized).kind(), ErrorKind::Uncategorized);
+ // Check that the innards look like like what we want.
+ assert_matches!(
+ Error::from(ErrorKind::OutOfMemory).repr.data(),
+ ErrorData::Simple(ErrorKind::OutOfMemory),
+ );
+}
+
+#[test]
+fn test_simple_message_packing() {
+ use super::{ErrorKind::*, SimpleMessage};
+ macro_rules! check_simple_msg {
+ ($err:expr, $kind:ident, $msg:literal) => {{
+ let e = &$err;
+ // Check that the public api is right.
+ assert_eq!(e.kind(), $kind);
+ assert!(format!("{e:?}").contains($msg));
+ // and we got what we expected
+ assert_matches!(
+ e.repr.data(),
+ ErrorData::SimpleMessage(SimpleMessage { kind: $kind, message: $msg })
+ );
+ }};
+ }
+
+ let not_static = const_io_error!(Uncategorized, "not a constant!");
+ check_simple_msg!(not_static, Uncategorized, "not a constant!");
+
+ const CONST: Error = const_io_error!(NotFound, "definitely a constant!");
+ check_simple_msg!(CONST, NotFound, "definitely a constant!");
+
+ static STATIC: Error = const_io_error!(BrokenPipe, "a constant, sort of!");
+ check_simple_msg!(STATIC, BrokenPipe, "a constant, sort of!");
+}
+
+#[derive(Debug, PartialEq)]
+struct Bojji(bool);
+impl error::Error for Bojji {}
+impl fmt::Display for Bojji {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(f, "ah! {:?}", self)
+ }
+}
+
+#[test]
+fn test_custom_error_packing() {
+ use super::Custom;
+ let test = Error::new(ErrorKind::Uncategorized, Bojji(true));
+ assert_matches!(
+ test.repr.data(),
+ ErrorData::Custom(Custom {
+ kind: ErrorKind::Uncategorized,
+ error,
+ }) if error.downcast_ref::<Bojji>().as_deref() == Some(&Bojji(true)),
+ );
+}
+
+#[derive(Debug)]
+struct E;
+
+impl fmt::Display for E {
+ fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ Ok(())
+ }
+}
+
+impl error::Error for E {}
+
+#[test]
+fn test_std_io_error_downcast() {
+ // Case 1: custom error, downcast succeeds
+ let io_error = Error::new(ErrorKind::Other, Bojji(true));
+ let e: Box<Bojji> = io_error.downcast().unwrap();
+ assert!(e.0);
+
+ // Case 2: custom error, downcast fails
+ let io_error = Error::new(ErrorKind::Other, Bojji(true));
+ let io_error = io_error.downcast::<E>().unwrap_err();
+
+ // ensures that the custom error is intact
+ assert_eq!(ErrorKind::Other, io_error.kind());
+ let e: Box<Bojji> = io_error.downcast().unwrap();
+ assert!(e.0);
+
+ // Case 3: os error
+ let errno = 20;
+ let io_error = Error::from_raw_os_error(errno);
+ let io_error = io_error.downcast::<E>().unwrap_err();
+
+ assert_eq!(errno, io_error.raw_os_error().unwrap());
+
+ // Case 4: simple
+ let kind = ErrorKind::OutOfMemory;
+ let io_error: Error = kind.into();
+ let io_error = io_error.downcast::<E>().unwrap_err();
+
+ assert_eq!(kind, io_error.kind());
+
+ // Case 5: simple message
+ const SIMPLE_MESSAGE: SimpleMessage =
+ SimpleMessage { kind: ErrorKind::Other, message: "simple message error test" };
+ let io_error = Error::from_static_message(&SIMPLE_MESSAGE);
+ let io_error = io_error.downcast::<E>().unwrap_err();
+
+ assert_eq!(SIMPLE_MESSAGE.kind, io_error.kind());
+ assert_eq!(SIMPLE_MESSAGE.message, &*format!("{io_error}"));
+}