googletest/lib.rs
1// Copyright 2022 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#![doc = include_str!("../crate_docs.md")]
16
17extern crate googletest_macro;
18
19#[cfg(test)]
20extern crate quickcheck;
21
22#[macro_use]
23pub mod assertions;
24pub mod description;
25pub mod fixtures;
26#[macro_use]
27pub mod fmt;
28pub mod internal;
29pub mod matcher;
30pub mod matcher_support;
31pub mod matchers;
32
33pub use googletest_macro::__abbreviated_stringify;
34
35/// Re-exports of the symbols in this crate which are most likely to be used.
36///
37/// This includes:
38/// * All assertion macros,
39/// * Traits and type definitions normally used by tests, and
40/// * All built-in matchers.
41///
42/// Typically, one imports everything in the prelude in one's test module:
43///
44/// ```
45/// mod tests {
46/// use googletest::prelude::*;
47/// }
48/// ```
49pub mod prelude {
50 pub use super::fixtures::{ConsumableFixture, Fixture, FixtureOf, StaticFixture};
51 pub use super::gtest;
52 pub use super::matcher::{Matcher, MatcherBase};
53 pub use super::matchers::*;
54 pub use super::scoped_trace;
55 pub use super::verify_current_test_outcome;
56 pub use super::GoogleTestSupport;
57 pub use super::OrFail;
58 pub use super::Result;
59 // Assert macros
60 pub use super::{
61 add_failure, add_failure_at, assert_false, assert_pred, assert_that, assert_true,
62 expect_eq, expect_false, expect_float_eq, expect_ge, expect_gt, expect_le, expect_lt,
63 expect_ne, expect_near, expect_pred, expect_that, expect_true, fail, succeed, verify_eq,
64 verify_false, verify_float_eq, verify_ge, verify_gt, verify_le, verify_lt, verify_ne,
65 verify_near, verify_pred, verify_that, verify_true,
66 };
67}
68
69/// Causes a trace to be included in every test failure message generated
70/// by code in the current scope.
71#[macro_export]
72macro_rules! scoped_trace {
73 ($($arg:tt)*) => {
74 #[allow(clippy::shadow_same, clippy::shadow_unrelated)]
75 let _gtest_trace_guard = $crate::internal::scoped_trace::ScopedTraceGuard::new(
76 format!($($arg)*),
77 );
78 };
79}
80
81pub use googletest_macro::gtest;
82pub use googletest_macro::test;
83
84use internal::test_outcome::{TestAssertionFailure, TestOutcome};
85
86/// A `Result` whose `Err` variant indicates a test failure.
87///
88/// The assertions [`verify_that!`][crate::verify_that],
89/// [`verify_pred!`][crate::verify_pred], and [`fail!`][crate::fail] evaluate
90/// to `Result<()>`. A test function may return `Result<()>` in combination with
91/// those macros to abort immediately on assertion failure.
92///
93/// This can be used with subroutines which may cause the test to fatally fail
94/// and which return some value needed by the caller. For example:
95///
96/// ```ignore
97/// fn load_file_content_as_string() -> Result<String> {
98/// let file_stream = load_file().err_to_test_failure()?;
99/// Ok(file_stream.to_string())
100/// }
101/// ```
102///
103/// The `Err` variant contains a [`TestAssertionFailure`] which carries the data
104/// of the (fatal) assertion failure which generated this result. Non-fatal
105/// assertion failures, which log the failure and report the test as having
106/// failed but allow it to continue running, are not encoded in this type.
107pub type Result<T, E = TestAssertionFailure> = std::result::Result<T, E>;
108
109/// Returns a [`Result`] corresponding to the outcome of the currently running
110/// test.
111///
112/// This returns `Result::Err` precisely if the current test has recorded at
113/// least one test assertion failure via [`expect_that!`][crate::expect_that],
114/// [`expect_pred!`][crate::expect_pred], or
115/// [`GoogleTestSupport::and_log_failure`]. It can be used in concert with the
116/// `?` operator to continue execution of the test conditionally on there not
117/// having been any failure yet.
118///
119/// This requires the use of the [`#[gtest]`][crate::gtest] attribute macro.
120///
121/// ```
122/// # use googletest::prelude::*;
123/// # /* Make sure this also compiles as a doctest.
124/// #[gtest]
125/// # */
126/// # fn foo() -> u32 { 1 }
127/// # fn bar() -> u32 { 2 }
128/// fn should_fail_and_not_execute_last_assertion() -> Result<()> {
129/// # googletest::internal::test_outcome::TestOutcome::init_current_test_outcome();
130/// expect_that!(foo(), eq(2)); // May fail, but will not abort the test.
131/// expect_that!(bar(), gt(1)); // May fail, but will not abort the test.
132/// verify_current_test_outcome()?; // Aborts the test if one of the previous assertions failed.
133/// verify_that!(foo(), gt(0)) // Does not execute if the line above aborts.
134/// }
135/// # verify_that!(should_fail_and_not_execute_last_assertion(), err(displays_as(contains_substring("Test failed")))).unwrap();
136/// ```
137#[track_caller]
138pub fn verify_current_test_outcome() -> Result<()> {
139 TestOutcome::get_current_test_outcome()
140}
141
142/// Adds to `Result` support for GoogleTest Rust functionality.
143pub trait GoogleTestSupport {
144 /// If `self` is a `Result::Err`, writes to `stdout` a failure report
145 /// and marks the test failed. Otherwise, does nothing.
146 ///
147 /// This can be used for non-fatal test assertions, for example:
148 ///
149 /// ```
150 /// # use googletest::prelude::*;
151 /// # use googletest::internal::test_outcome::TestOutcome;
152 /// # TestOutcome::init_current_test_outcome();
153 /// let actual = 42;
154 /// verify_that!(actual, eq(42)).and_log_failure();
155 /// // Test still passing; nothing happens
156 /// verify_that!(actual, eq(10)).and_log_failure();
157 /// // Test now fails and failure output to stdout
158 /// verify_that!(actual, eq(100)).and_log_failure();
159 /// // Test still fails and new failure also output to stdout
160 /// # TestOutcome::close_current_test_outcome::<&str>(Ok(())).unwrap_err();
161 /// ```
162 fn and_log_failure(self);
163
164 /// If `self` is a `Result::Err`, writes to `stdout` with a failure report
165 /// and the message returned by `provider`.
166 ///
167 /// This is equivalent to combining [`GoogleTestSupport::and_log_failure`]
168 /// with a call to [`GoogleTestSupport::with_failure_message`].
169 ///
170 /// Example:
171 ///
172 /// ```
173 /// # use googletest::GoogleTestSupport;
174 /// # use googletest::assertions::verify_eq;
175 /// # use googletest::internal::test_outcome::TestOutcome;
176 /// # TestOutcome::init_current_test_outcome();
177 /// let actual = 0;
178 /// verify_eq!(actual, 42)
179 /// .and_log_failure_with_message(|| format!("Actual {} was wrong!", actual));
180 /// # TestOutcome::close_current_test_outcome::<&str>(Ok(())).unwrap_err();
181 /// ```
182 fn and_log_failure_with_message(self, provider: impl FnOnce() -> String)
183 where
184 Self: Sized,
185 {
186 self.with_failure_message(provider).and_log_failure();
187 }
188
189 /// Adds `message` to the logged failure message if `self` is a
190 /// `Result::Err`. Otherwise, does nothing.
191 ///
192 /// If this method is called more than once, only `message` from the last
193 /// invocation is output.
194 ///
195 /// For example:
196 ///
197 /// ```
198 /// # use googletest::prelude::*;
199 /// # fn should_fail() -> Result<()> {
200 /// let actual = 0;
201 /// verify_that!(actual, eq(42)).failure_message("Actual was wrong!")?;
202 /// # Ok(())
203 /// # }
204 /// # verify_that!(should_fail(), err(displays_as(contains_substring("Actual was wrong"))))
205 /// # .unwrap();
206 /// ```
207 ///
208 /// results in the following failure message:
209 ///
210 /// ```text
211 /// Expected: actual equal to 42
212 /// but was: 0
213 /// Actual was wrong!
214 /// ```
215 ///
216 /// One can pass a `String` too:
217 ///
218 /// ```
219 /// # use googletest::prelude::*;
220 /// # fn should_fail() -> Result<()> {
221 /// let actual = 0;
222 /// verify_that!(actual, eq(42))
223 /// .failure_message(format!("Actual {} was wrong!", actual))?;
224 /// # Ok(())
225 /// # }
226 /// # verify_that!(should_fail(), err(displays_as(contains_substring("Actual 0 was wrong"))))
227 /// # .unwrap();
228 /// ```
229 ///
230 /// However, consider using [`GoogleTestSupport::with_failure_message`]
231 /// instead in that case to avoid unnecessary memory allocation when the
232 /// message is not needed.
233 fn failure_message(self, message: impl Into<String>) -> Self;
234
235 /// Adds the output of the closure `provider` to the logged failure message
236 /// if `self` is a `Result::Err`. Otherwise, does nothing.
237 ///
238 /// This is analogous to [`GoogleTestSupport::failure_message`] but
239 /// only executes the closure `provider` if it actually produces the
240 /// message, thus saving possible memory allocation.
241 ///
242 /// ```
243 /// # use googletest::prelude::*;
244 /// # fn should_fail() -> Result<()> {
245 /// let actual = 0;
246 /// verify_that!(actual, eq(42))
247 /// .with_failure_message(|| format!("Actual {} was wrong!", actual))?;
248 /// # Ok(())
249 /// # }
250 /// # verify_that!(should_fail(), err(displays_as(contains_substring("Actual 0 was wrong"))))
251 /// # .unwrap();
252 /// ```
253 fn with_failure_message(self, provider: impl FnOnce() -> String) -> Self;
254}
255
256impl<T> GoogleTestSupport for std::result::Result<T, TestAssertionFailure> {
257 fn and_log_failure(self) {
258 TestOutcome::ensure_test_context_present();
259 if let Err(failure) = self {
260 failure.log();
261 }
262 }
263
264 fn failure_message(mut self, message: impl Into<String>) -> Self {
265 if let Err(ref mut failure) = self {
266 failure.custom_message = Some(message.into());
267 }
268 self
269 }
270
271 fn with_failure_message(mut self, provider: impl FnOnce() -> String) -> Self {
272 if let Err(ref mut failure) = self {
273 failure.custom_message = Some(provider());
274 }
275 self
276 }
277}
278
279/// Provides an extension method for converting an arbitrary type into
280/// `googletest`'s [`Result`] type.
281///
282/// A type can implement this trait to provide an easy way to return immediately
283/// from a test in conjunction with the `?` operator. This is useful for
284/// [`Option`] and [`Result`][std::result::Result] types whose `Result::Err`
285/// variant does not implement [`std::error::Error`].
286///
287/// If `Result::Err` implements [`std::error::Error`] you can just use the `?`
288/// operator directly.
289///
290/// ```ignore
291/// #[test]
292/// fn should_work() -> googletest::Result<()> {
293/// let value = something_which_can_fail().or_fail()?;
294/// let value = something_which_can_fail_with_option().or_fail()?;
295/// ...
296/// }
297///
298/// fn something_which_can_fail() -> std::result::Result<T, String> { ... }
299/// fn something_which_can_fail_with_option() -> Option<T> { ... }
300/// ```
301pub trait OrFail {
302 /// The success type of the test result.
303 type Output;
304
305 /// Converts a value into a [`Result`] containing
306 /// either the [`Self::Output`] type or a [`TestAssertionFailure`].
307 ///
308 /// The most frequently used implementations convert
309 /// `Result<T, E>` into `Result<T, TestAssertionFailure>` and
310 /// `Option<T>` into `Result<T, TestAssertionFailure>`.
311 fn or_fail(self) -> Result<Self::Output>;
312}
313
314impl<T, E: std::fmt::Debug> OrFail for std::result::Result<T, E> {
315 type Output = T;
316
317 #[track_caller]
318 fn or_fail(self) -> std::result::Result<T, TestAssertionFailure> {
319 match self {
320 Ok(t) => Ok(t),
321 Err(e) => Err(TestAssertionFailure::create(format!("{e:?}"))),
322 }
323 }
324}
325
326impl<T> OrFail for Option<T> {
327 type Output = T;
328
329 #[track_caller]
330 fn or_fail(self) -> std::result::Result<T, TestAssertionFailure> {
331 match self {
332 Some(t) => Ok(t),
333 None => Err(TestAssertionFailure::create(format!(
334 "called `Option::or_fail()` on a `Option::<{}>::None` value",
335 std::any::type_name::<T>()
336 ))),
337 }
338 }
339}
340
341#[doc(hidden)]
342pub mod __internal_macro_support {
343 use crate::fixtures::Fixture;
344
345 pub struct FixtureTearDownOnDrop<T: Fixture> {
346 fixture: Option<T>,
347 }
348
349 impl<T: Fixture> FixtureTearDownOnDrop<T> {
350 pub fn new(fixture: T) -> Self {
351 Self { fixture: Some(fixture) }
352 }
353 pub fn tear_down(mut self) -> crate::Result<()> {
354 if let Some(fixture) = self.fixture.take() {
355 fixture.tear_down()
356 } else {
357 Ok(())
358 }
359 }
360 }
361
362 impl<T: Fixture> AsRef<T> for FixtureTearDownOnDrop<T> {
363 fn as_ref(&self) -> &T {
364 self.fixture.as_ref().unwrap()
365 }
366 }
367
368 impl<T: Fixture> AsMut<T> for FixtureTearDownOnDrop<T> {
369 fn as_mut(&mut self) -> &mut T {
370 self.fixture.as_mut().unwrap()
371 }
372 }
373
374 impl<T: Fixture> Drop for FixtureTearDownOnDrop<T> {
375 fn drop(&mut self) {
376 if let Some(fixture) = self.fixture.take() {
377 fixture.tear_down().unwrap();
378 }
379 }
380 }
381}