test_that/assertions.rs
1// Copyright 2022 Google LLC
2// Copyright 2026 Bradford Hovinen <bradford@hovinen.me>
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16// There are no visible documentation elements in this module; the declarative
17// macros are documented at the top level.
18#![doc(hidden)]
19
20/// Checks whether the `Matcher` given by the second argument matches the first
21/// argument.
22///
23/// Evaluates to `Result::Ok(())` if the matcher matches and
24/// `Result::Err(TestAssertionFailure)` if it does not. The caller must then
25/// decide how to handle the `Err` variant. It has a few options:
26///
27/// * Abort the current function with the `?` operator. This requires that the
28/// function return a suitable `Result`.
29/// * Log the test failure and continue by calling the method
30/// `and_log_failure`.
31///
32/// Of course, one can also use all other standard methods on `Result`.
33///
34/// **Invoking this macro by itself does not cause a test failure to be recorded
35/// or output.** The resulting `Result` must be handled as described above to
36/// cause the test to be recorded as a failure.
37///
38/// Example:
39/// ```
40/// # use test_that::prelude::*;
41/// # fn should_pass() -> TestResult<()> {
42/// verify_that!(42, eq(42))?; // This will pass.
43/// # Ok(())
44/// # }
45/// # should_pass().unwrap();
46/// # fn should_fail() -> TestResult<()> {
47/// # #[cfg(feature = "std")]
48/// # test_that::internal::test_outcome::TestOutcome::init_current_test_outcome();
49/// verify_that!(42, eq(123)).and_log_failure();
50/// // This will log a test failure and allow execution to continue.
51/// let _ = verify_that!(42, eq(123)); // This will do nothing.
52/// verify_that!(42, eq(123))?; // This will fail, returning immediately.
53/// verify_that!(42, eq(0))?; // This will not run.
54/// # #[cfg(feature = "std")]
55/// # { test_that::internal::test_outcome::TestOutcome::close_current_test_outcome::<&str>(Ok(())).unwrap_err(); }
56/// # Ok(())
57/// # }
58/// # verify_that!(should_fail(), err(displays_as(contains_substring("Expected: is equal to 123"))))
59/// # .unwrap();
60/// ```
61///
62/// This macro has special support for matching against container. Namely:
63/// * `verify_that!(actual, [m1, m2, ...])` is equivalent to
64/// `verify_that!(actual, contains_exactly![m1, m2, ...].in_order())`
65/// * `verify_that!(actual, {m1, m2, ...})` is equivalent to
66/// `verify_that!(actual, contains_exactly![m1, m2, ...])`
67#[macro_export]
68macro_rules! verify_that {
69 ($actual:expr, [$($expecteds:expr),+ $(,)?]) => {
70 $crate::assertions::internal::check_matcher(
71 &$actual,
72 $crate::matchers::containers::contains_exactly![$($expecteds),+].in_order(),
73 stringify!($actual),
74 $crate::internal::source_location::SourceLocation::new(file!(), line!(), column!()),
75 )
76 };
77 ($actual:expr, {$($expecteds:expr),+ $(,)?}) => {
78 $crate::assertions::internal::check_matcher(
79 &$actual,
80 $crate::matchers::containers::contains_exactly![$($expecteds),+],
81 stringify!($actual),
82 $crate::internal::source_location::SourceLocation::new(file!(), line!(), column!()),
83 )
84 };
85 ($actual:expr, $expected:expr $(,)?) => {
86 $crate::assertions::internal::check_matcher(
87 &$actual,
88 $expected,
89 stringify!($actual),
90 $crate::internal::source_location::SourceLocation::new(file!(), line!(), column!()),
91 )
92 };
93}
94
95/// Asserts that the given predicate applied to the given arguments returns
96/// true.
97///
98/// Similarly to [`verify_that`], this evaluates to a `Result` whose `Ok`
99/// variant indicates that the given predicate returned true and whose `Err`
100/// variant indicates that it returned false.
101///
102/// The failure message contains detailed information about the arguments. For
103/// example:
104///
105/// ```
106/// # use test_that::prelude::*;
107/// fn equals_modulo(a: i32, b: i32, n: i32) -> bool { a % n == b % n }
108///
109/// # /* The attribute macro would prevent the function from being compiled in a doctest.
110/// #[test]
111/// # */
112/// fn test() -> TestResult<()> {
113/// let a = 1;
114/// let b = 7;
115/// let n = 5;
116/// verify_pred!(equals_modulo(a, b, n))?;
117/// Ok(())
118/// }
119/// # verify_that!(
120/// # test(),
121/// # err(displays_as(contains_substring("equals_modulo(a, b, n) was false with")))
122/// # ).unwrap();
123/// ```
124///
125/// This results in the following message:
126///
127/// ```text
128/// equals_modulo(a, b, n) was false with
129/// a = 1,
130/// b = 7,
131/// n = 5
132/// ```
133///
134/// The function passed to this macro must return `bool`. Each of the arguments
135/// must evaluate to a type implementing [`std::fmt::Debug`]. The debug output
136/// is used to construct the failure message.
137///
138/// The predicate can also be a method on a struct, e.g.:
139///
140/// ```ignore
141/// struct AStruct {};
142///
143/// impl AStruct {
144/// fn equals_modulo(...) {...}
145/// }
146///
147/// verify_pred!((AStruct {}).equals_modulo(a, b, n))?;
148/// ```
149///
150/// **Warning:** This macro assumes that the arguments passed to the predicate
151/// are either *variables* or *calls to pure functions*. If two subsequent
152/// invocations to any of the expresssions passed as arguments result in
153/// different values, then the output message of a test failure will deviate
154/// from the values actually passed to the predicate. For this reason, *always
155/// assign the outputs of non-pure functions to variables before using them in
156/// this macro. For example:
157///
158/// ```ignore
159/// let output = generate_random_number(); // Assigned outside of verify_pred.
160/// verify_pred!(is_sufficiently_random(output))?;
161/// ```
162#[macro_export]
163macro_rules! verify_pred {
164 ([$($predicate:tt)*]($($arg:tt),* $(,)?)) => {
165 if !$($predicate)*($($arg),*) {
166 $crate::assertions::internal::report_failed_predicate(
167 concat!(stringify!($($predicate)*), stringify!(($($arg),*))),
168 $crate::__alloc::vec![$((($crate::__alloc::format!(concat!(stringify!($arg), " = {:?}"), $arg)))),*],
169 $crate::internal::source_location::SourceLocation::new(
170 file!(),
171 line!(),
172 column!(),
173 ),
174 )
175 } else {
176 Ok(())
177 }
178 };
179
180 ([$($predicate:tt)*] $first:tt $($rest:tt)*) => {
181 $crate::verify_pred!([$($predicate)* $first] $($rest)*)
182 };
183
184 ($first:tt $($rest:tt)*) => {
185 $crate::verify_pred!([$first] $($rest)*)
186 };
187}
188
189/// Evaluates to a `Result` which contains an `Err` variant with the given test
190/// failure message.
191///
192/// This can be used to force the test to fail if its execution reaches a
193/// particular point. For example:
194///
195/// ```ignore
196/// match some_value {
197/// ExpectedVariant => {...}
198/// UnwantedVaraint => {
199/// fail!("This thing which should not happen happened anyway")?;
200/// }
201/// }
202/// ```
203///
204/// One may include formatted arguments in the failure message:
205///
206/// ```ignore
207/// match some_value {
208/// ExpectedVariant => {...}
209/// UnwantedVaraint => {
210/// fail!("This thing which should not happen happened anyway: {}", some_value)?;
211/// }
212/// }
213/// ```
214///
215/// One may also omit the message, in which case the test failure message will
216/// be generic:
217///
218/// ```ignore
219/// match some_value {
220/// ExpectedVariant => {...}
221/// UnwantedVaraint => {
222/// fail!()?;
223/// }
224/// }
225/// ```
226///
227/// Unlike `panic!` but analogously to [`verify_that`] and [`verify_pred`], this
228/// macro has no effect on the flow of control but instead returns a `Result`
229/// which must be handled by the invoking function. This can be done with the
230/// question mark operator (as above) or the method
231/// [`and_log_failure`](crate::TestResultExt::and_log_failure).
232#[macro_export]
233macro_rules! fail {
234 ($($message:expr),+) => {{
235 // We wrap this in a function so that we can annotate it with the must_use attribute.
236 // must_use on expressions is still experimental.
237 #[must_use = "The assertion result must be evaluated to affect the test result."]
238 fn create_fail_result(message: $crate::__alloc::string::String) -> $crate::TestResult<()> {
239 Err($crate::internal::test_outcome::TestAssertionFailure::create($crate::__alloc::format!(
240 "{}\n{}",
241 message,
242 $crate::internal::source_location::SourceLocation::new(
243 file!(),
244 line!(),
245 column!(),
246 ),
247 )))
248 }
249 create_fail_result($crate::__alloc::format!($($message),*))
250 }};
251
252 () => { fail!("Test failed") };
253}
254
255/// Matches the given value against the given matcher, panicking if it does not
256/// match.
257///
258/// ```should_panic
259/// # use test_that::prelude::*;
260/// # fn should_fail() {
261/// let value = 2;
262/// assert_that!(value, eq(3)); // Fails and panics.
263/// # }
264/// # should_fail();
265/// ```
266///
267/// This is analogous to assertions in most Rust test libraries, where a failed
268/// assertion causes a panic.
269///
270/// One may optionally add arguments which will be formatted and appended to a
271/// failure message. For example:
272///
273/// ```should_panic
274/// # use test_that::prelude::*;
275/// # fn should_fail() {
276/// let value = 2;
277/// let extra_information = "Some additional information";
278/// assert_that!(value, eq(3), "Test failed. Extra information: {extra_information}.");
279/// # }
280/// # should_fail();
281/// ```
282///
283/// This is output as follows:
284///
285/// ```text
286/// Value of: value
287/// Expected: is equal to 3
288/// Actual: 2,
289/// which isn't equal to 3
290/// at ...
291/// Test failed. Extra information: Some additional information.
292/// ```
293///
294/// **Note for users of [GoogleTest for C++](http://google.github.io/googletest/):**
295/// This differs from the `ASSERT_THAT` macro in that it panics rather
296/// than triggering an early return from the invoking function. To get behaviour
297/// equivalent to `ASSERT_THAT`, use [`verify_that!`] with the `?` operator.
298#[macro_export]
299macro_rules! assert_that {
300 ($actual:expr, $expected:expr $(,)?) => {
301 match $crate::verify_that!($actual, $expected) {
302 Ok(_) => {}
303 Err(e) => {
304 // The extra newline before the assertion failure message makes the failure a
305 // bit easier to read when there's some generic boilerplate from the panic.
306 panic!("\n{}", e);
307 }
308 }
309 };
310
311 ($actual:expr, $expected:expr, $($format_args:expr),* $(,)?) => {
312 match $crate::verify_that!($actual, $expected)
313 .with_failure_message(|| format!($($format_args),*))
314 {
315 Ok(_) => {}
316 Err(e) => {
317 // The extra newline before the assertion failure message makes the failure a
318 // bit easier to read when there's some generic boilerplate from the panic.
319 panic!("\n{}", e);
320 }
321 }
322 };
323}
324
325/// Asserts that the given predicate applied to the given arguments returns
326/// true, panicking if it does not.
327///
328/// **Note for users of [GoogleTest for C++](http://google.github.io/googletest/):**
329/// This differs from the `ASSERT_PRED*` family of macros in that it panics
330/// rather than triggering an early return from the invoking function. To get
331/// behaviour equivalent to `ASSERT_PRED*`, use [`verify_pred!`] with the `?`
332/// operator.
333#[macro_export]
334macro_rules! assert_pred {
335 ($($content:tt)*) => {
336 match $crate::verify_pred!($($content)*) {
337 Ok(_) => {}
338 Err(e) => {
339 // The extra newline before the assertion failure message makes the failure a
340 // bit easier to read when there's some generic boilerplate from the panic.
341 panic!("\n{}", e);
342 }
343 }
344 };
345}
346
347/// Matches the given value against the given matcher, marking the test as
348/// failed but continuing execution if it does not match.
349///
350/// This is a *non-fatal* assertion: the test continues
351/// execution in the event of assertion failure.
352///
353/// This can only be invoked inside tests with the
354/// [`test_that::test`][crate::test] attribute. The assertion must
355/// occur in the same thread as that running the test itself.
356///
357/// Invoking this macro is equivalent to using
358/// [`and_log_failure`](crate::TestResultExt::and_log_failure) as follows:
359///
360/// ```ignore
361/// verify_that!(actual, expected).and_log_failure()
362/// ```
363///
364/// One may optionally add arguments which will be formatted and appended to a
365/// failure message. For example:
366///
367/// ```
368/// # use test_that::prelude::*;
369/// # fn should_fail() -> std::result::Result<(), test_that::internal::test_outcome::TestFailure> {
370/// # test_that::internal::test_outcome::TestOutcome::init_current_test_outcome();
371/// let value = 2;
372/// let extra_information = "Some additional information";
373/// expect_that!(value, eq(3), "Test failed. Extra information: {extra_information}.");
374/// # test_that::internal::test_outcome::TestOutcome::close_current_test_outcome::<&str>(Ok(()))
375/// # }
376/// # should_fail().unwrap_err();
377/// ```
378///
379/// This is output as follows:
380///
381/// ```text
382/// Value of: value
383/// Expected: is equal to 3
384/// Actual: 2,
385/// which isn't equal to 3
386/// at ...
387/// Test failed. Extra information: Some additional information.
388/// ```
389#[cfg(feature = "non-fatal-assertions")]
390#[macro_export]
391macro_rules! expect_that {
392 ($actual:expr, $expected:expr $(,)?) => {{
393 use $crate::TestResultExt;
394 $crate::verify_that!($actual, $expected).and_log_failure();
395 }};
396
397 ($actual:expr, $expected:expr, $($format_args:expr),* $(,)?) => {
398 $crate::verify_that!($actual, $expected)
399 .with_failure_message(|| format!($($format_args),*))
400 .and_log_failure()
401 };
402}
403
404/// Asserts that the given predicate applied to the given arguments returns
405/// true, failing the test but continuing execution if not.
406///
407/// This is a *non-fatal* predicate assertion: the test
408/// continues execution in the event of assertion failure.
409///
410/// This can only be invoked inside tests with the
411/// [`test_that::test`][crate::test] attribute. The assertion must
412/// occur in the same thread as that running the test itself.
413///
414/// Invoking this macro is equivalent to using
415/// [`and_log_failure`](crate::TestResultExt::and_log_failure) as follows:
416///
417/// ```ignore
418/// verify_pred!(predicate(...)).and_log_failure()
419/// ```
420#[cfg(feature = "non-fatal-assertions")]
421#[macro_export]
422macro_rules! expect_pred {
423 ($($content:tt)*) => {{
424 use $crate::TestResultExt;
425 $crate::verify_pred!($($content)*).and_log_failure();
426 }};
427}
428
429/// Functions for use only by the procedural macros in this module.
430///
431/// **For internal use only. API stablility is not guaranteed!**
432#[doc(hidden)]
433pub mod internal {
434 use crate::{
435 internal::{source_location::SourceLocation, test_outcome::TestAssertionFailure},
436 matcher::{Matcher, MatcherResult, create_assertion_failure},
437 };
438 use core::fmt::Debug;
439
440 /// Checks whether the matcher `expected` matches the value `actual`, adding
441 /// a test failure report if it does not match.
442 ///
443 /// Returns `Ok(())` if the value matches and `Err(())` if it does not
444 /// match.
445 ///
446 /// **For internal use only. API stablility is not guaranteed!**
447 #[must_use = "The assertion result must be evaluated to affect the test result."]
448 pub fn check_matcher<T: Debug + ?Sized>(
449 actual: &T,
450 expected: impl Matcher<T>,
451 actual_expr: &'static str,
452 source_location: SourceLocation,
453 ) -> Result<(), TestAssertionFailure> {
454 match expected.matches(actual) {
455 MatcherResult::Match => Ok(()),
456 MatcherResult::NoMatch => {
457 Err(create_assertion_failure(&expected, actual, actual_expr, source_location))
458 }
459 }
460 }
461
462 /// Constructs a `Result::Err(TestAssertionFailure)` for a predicate failure
463 /// as produced by the macro [`crate::verify_pred`].
464 ///
465 /// This intended only for use by the macro [`crate::verify_pred`].
466 ///
467 /// **For internal use only. API stablility is not guaranteed!**
468 #[must_use = "The assertion result must be evaluated to affect the test result."]
469 pub fn report_failed_predicate(
470 actual_expr: &'static str,
471 formatted_arguments: alloc::vec::Vec<alloc::string::String>,
472 source_location: SourceLocation,
473 ) -> Result<(), TestAssertionFailure> {
474 Err(TestAssertionFailure::create(alloc::format!(
475 "{} was false with\n {}\n{}",
476 actual_expr,
477 formatted_arguments.join(",\n "),
478 source_location,
479 )))
480 }
481}