assertables/assert_success/assert_success_false.rs
1//! Assert failure.
2//!
3//! Pseudocode:<br>
4//! a.success() = false
5//!
6//! # Example
7//!
8//! ```rust
9//! use assertables::*;
10//!
11//! #[derive(Debug)]
12//! struct A;
13//! impl A { fn success(&self) -> bool { false }}
14//! let a = A{};
15//! assert_success_false!(a);
16//! ```
17//!
18//! # Module macros
19//!
20//! * [`assert_success_false`](macro@crate::assert_success_false)
21//! * [`assert_success_false_as_result`](macro@crate::assert_success_false_as_result)
22//! * [`debug_assert_success_false`](macro@crate::debug_assert_success_false)
23
24/// Assert a failure method is true.
25///
26/// Pseudocode:<br>
27/// a.success() = false
28///
29/// * If true, return Result `Ok(true)`.
30///
31/// * Otherwise, return Result `Err(message)`.
32///
33/// This macro is useful for runtime checks, such as checking parameters,
34/// or sanitizing inputs, or handling different results in different ways.
35///
36/// # Module macros
37///
38/// * [`assert_success_false`](macro@crate::assert_success_false)
39/// * [`assert_success_false_as_result`](macro@crate::assert_success_false_as_result)
40/// * [`debug_assert_success_false`](macro@crate::debug_assert_success_false)
41///
42#[macro_export]
43macro_rules! assert_success_false_as_result {
44 ($a:expr $(,)?) => {
45 if !$a.success() {
46 Ok(true)
47 } else {
48 Err(format!(
49 concat!(
50 "assertion failed: `assert_success_false!(a)`\n",
51 "https://docs.rs/assertables/9.8.3/assertables/macro.assert_success_false.html\n",
52 " a label: `{}`,\n",
53 " a debug: `{:?}`",
54 ),
55 stringify!($a),
56 $a,
57 ))
58 }
59 };
60}
61
62#[cfg(test)]
63mod test_assert_success_false_as_result {
64 // use std::sync::Once;
65
66 #[test]
67 fn success() {
68 #[derive(Debug)]
69 struct A;
70 impl A {
71 fn success(&self) -> bool {
72 false
73 }
74 }
75 let a = A {};
76 for _ in 0..1 {
77 let actual = assert_success_false_as_result!(a);
78 assert_eq!(actual.unwrap(), true);
79 }
80 }
81
82 #[test]
83 fn failure() {
84 #[derive(Debug)]
85 struct A;
86 impl A {
87 fn success(&self) -> bool {
88 true
89 }
90 }
91 let a = A {};
92 let actual = assert_success_false_as_result!(a);
93 let message = concat!(
94 "assertion failed: `assert_success_false!(a)`\n",
95 "https://docs.rs/assertables/9.8.3/assertables/macro.assert_success_false.html\n",
96 " a label: `a`,\n",
97 " a debug: `A`",
98 );
99 assert_eq!(actual.unwrap_err(), message);
100 }
101}
102
103/// Assert a failure method is true.
104///
105/// Pseudocode:<br>
106/// a.success() = false
107///
108/// * If true, return `true`.
109///
110/// * Otherwise, call [`panic!`] with a message and the values of the
111/// expressions with their debug representations.
112///
113/// # Examples
114///
115/// ```rust
116/// use assertables::*;
117/// # use std::panic;
118///
119/// # fn main() {
120/// #[derive(Debug)]
121/// struct A;
122/// impl A { fn success(&self) -> bool { false }}
123/// let a = A{};
124/// assert_success_false!(a);
125///
126/// # let result = panic::catch_unwind(|| {
127/// // This will panic
128/// #[derive(Debug)]
129/// struct A;
130/// impl A { fn success(&self) -> bool { true }}
131/// let a = A{};
132/// assert_success_false!(a);
133/// # });
134/// // assertion failed: `assert_success_false!(a)`
135/// // https://docs.rs/assertables/…/assertables/macro.assert_success_false.html
136/// // a label: `a`,
137/// // a debug: `A`
138/// # let actual = result.unwrap_err().downcast::<String>().unwrap().to_string();
139/// # let message = concat!(
140/// # "assertion failed: `assert_success_false!(a)`\n",
141/// # "https://docs.rs/assertables/9.8.3/assertables/macro.assert_success_false.html\n",
142/// # " a label: `a`,\n",
143/// # " a debug: `A`",
144/// # );
145/// # assert_eq!(actual, message);
146/// # }
147/// ```
148///
149/// # Module macros
150///
151/// * [`assert_success_false`](macro@crate::assert_success_false)
152/// * [`assert_success_false_as_result`](macro@crate::assert_success_false_as_result)
153/// * [`debug_assert_success_false`](macro@crate::debug_assert_success_false)
154///
155#[macro_export]
156macro_rules! assert_success_false {
157 ($a:expr $(,)?) => {
158 match $crate::assert_success_false_as_result!($a) {
159 Ok(x) => x,
160 Err(err) => panic!("{}", err),
161 }
162 };
163 ($a:expr, $($message:tt)+) => {
164 match $crate::assert_success_false_as_result!($a) {
165 Ok(x) => x,
166 Err(err) => panic!("{}\n{}", format_args!($($message)+), err),
167 }
168 };
169}
170
171#[cfg(test)]
172mod test_assert_success_false {
173 use std::panic;
174
175 #[test]
176 fn success() {
177 #[derive(Debug)]
178 struct A;
179 impl A {
180 fn success(&self) -> bool {
181 false
182 }
183 }
184 let a = A {};
185 for _ in 0..1 {
186 let actual = assert_success_false!(a);
187 assert_eq!(actual, true);
188 }
189 }
190
191 #[test]
192 fn failure() {
193 #[derive(Debug)]
194 struct A;
195 impl A {
196 fn success(&self) -> bool {
197 true
198 }
199 }
200 let a = A {};
201 let result = panic::catch_unwind(|| {
202 let _actual = assert_success_false!(a);
203 });
204 let message = concat!(
205 "assertion failed: `assert_success_false!(a)`\n",
206 "https://docs.rs/assertables/9.8.3/assertables/macro.assert_success_false.html\n",
207 " a label: `a`,\n",
208 " a debug: `A`",
209 );
210 assert_eq!(
211 result
212 .unwrap_err()
213 .downcast::<String>()
214 .unwrap()
215 .to_string(),
216 message
217 );
218 }
219}
220
221/// Assert a failure method is true.
222///
223/// Pseudocode:<br>
224/// a.success() = false
225///
226/// This macro provides the same statements as [`assert_success_false`](macro.assert_success_false.html),
227/// except this macro's statements are only enabled in non-optimized
228/// builds by default. An optimized build will not execute this macro's
229/// statements unless `-C debug-assertions` is passed to the compiler.
230///
231/// This macro is useful for checks that are too expensive to be present
232/// in a release build but may be helpful during development.
233///
234/// The result of expanding this macro is always type checked.
235///
236/// An unchecked assertion allows a "bin/exit-with-arg" in an inconsistent state to
237/// keep running, which might have unexpected consequences but does not
238/// introduce unsafety as long as this only happens in safe code. The
239/// performance cost of assertions, however, is not measurable in general.
240/// Replacing `assert*!` with `debug_assert*!` is thus only encouraged
241/// after thorough profiling, and more importantly, only in safe code!
242///
243/// This macro is intended to work in a similar way to
244/// [`::std::debug_assert`](https://doc.rust-lang.org/std/macro.debug_assert.html).
245///
246/// # Module macros
247///
248/// * [`assert_success_false`](macro@crate::assert_success_false)
249/// * [`assert_success_false`](macro@crate::assert_success_false)
250/// * [`debug_assert_success_false`](macro@crate::debug_assert_success_false)
251///
252#[macro_export]
253macro_rules! debug_assert_success_false {
254 ($($arg:tt)*) => {
255 if $crate::cfg!(debug_assertions) {
256 $crate::assert_success_false!($($arg)*);
257 }
258 };
259}