assertr/assertions/core/
fn.rs

1use crate::actual::Actual;
2use crate::mode::Mode;
3use crate::prelude::ResultAssertions;
4use crate::tracking::AssertionTracking;
5use crate::{AssertThat, PanicValue};
6use core::fmt::{Debug, Write};
7use indoc::writedoc;
8
9pub trait FnOnceAssertions<'t, R, M: Mode> {
10    #[cfg(feature = "std")]
11    fn panics(self) -> AssertThat<'t, PanicValue, M>;
12
13    #[cfg(feature = "std")]
14    fn does_not_panic(self) -> AssertThat<'t, R, M>
15    where
16        R: Debug;
17}
18
19impl<'t, R, F: FnOnce() -> R, M: Mode> FnOnceAssertions<'t, R, M> for AssertThat<'t, F, M> {
20    #[track_caller]
21    fn panics(self) -> AssertThat<'t, PanicValue, M> {
22        self.track_assertion();
23
24        let this = self.map(|it| match it {
25            Actual::Borrowed(_) => panic!("panics() can only be called on an owned FnOnce!"),
26            Actual::Owned(f) => Actual::Owned(std::panic::catch_unwind(
27                core::panic::AssertUnwindSafe(move || {
28                    f();
29                }),
30            )),
31        });
32
33        if this.actual().is_ok() {
34            this.fail(|w: &mut String| {
35                writedoc! {w, r#"
36                    Expected: Function to panic when called.
37
38                      Actual: No panic occurred!
39                "#}
40            });
41        }
42
43        this.is_err()
44            .with_detail_message("Function did not panic as expected!")
45            .map(|it| {
46                let boxed_any = it.unwrap_owned();
47                PanicValue(boxed_any).into()
48            })
49    }
50
51    #[track_caller]
52    fn does_not_panic(self) -> AssertThat<'t, R, M>
53    where
54        R: Debug,
55    {
56        self.track_assertion();
57
58        let this = self.map(|it| match it {
59            Actual::Borrowed(_) => panic!("panics() can only be called on an owned FnOnce!"),
60            Actual::Owned(f) => {
61                Actual::Owned(std::panic::catch_unwind(core::panic::AssertUnwindSafe(f)))
62            }
63        });
64
65        if this.actual().is_err() {
66            this.fail(|w: &mut String| {
67                writedoc! {w, r#"
68                    Expected: Function to not panic when called.
69
70                      Actual: Function panicked unexpectedly!
71                "#}
72            });
73        }
74
75        this.is_ok()
76            .with_detail_message("Function panicked unexpectedly!")
77            .map(|it| it.unwrap_owned().into())
78    }
79}
80
81#[cfg(test)]
82mod tests {
83
84    mod panics {
85        use crate::prelude::*;
86        use indoc::formatdoc;
87
88        #[test]
89        fn succeeds_when_panic_occurs() {
90            assert_that(|| unimplemented!())
91                .panics()
92                .has_type::<&str>()
93                .is_equal_to("not implemented");
94        }
95
96        #[test]
97        fn panics_when_no_panic_occurs() {
98            assert_that_panic_by(|| assert_that(|| 42).with_location(false).panics())
99                .has_type::<String>()
100                .is_equal_to(formatdoc! {r#"
101                    -------- assertr --------
102                    Expected: Function to panic when called.
103
104                      Actual: No panic occurred!
105                    -------- assertr --------
106                "#});
107        }
108    }
109
110    mod does_not_panic {
111        use crate::prelude::*;
112        use indoc::formatdoc;
113
114        #[test]
115        fn succeeds_when_no_panic_occurs() {
116            assert_that(|| 42).does_not_panic();
117        }
118
119        #[test]
120        fn fails_when_panic_occurs() {
121            assert_that_panic_by(|| {
122                assert_that(|| unimplemented!())
123                    .with_location(false)
124                    .does_not_panic()
125            })
126            .has_type::<String>()
127            .is_equal_to(formatdoc! {r#"
128                -------- assertr --------
129                Expected: Function to not panic when called.
130
131                  Actual: Function panicked unexpectedly!
132                -------- assertr --------
133            "#});
134        }
135    }
136}