#![doc = include_str!("../crate_docs.md")]
extern crate googletest_macro;
#[cfg(test)]
extern crate quickcheck;
#[macro_use]
pub mod assertions;
pub mod description;
pub mod fixtures;
#[macro_use]
pub mod fmt;
pub mod internal;
pub mod matcher;
pub mod matcher_support;
pub mod matchers;
pub use googletest_macro::__abbreviated_stringify;
pub mod prelude {
pub use super::fixtures::{ConsumableFixture, Fixture, FixtureOf, StaticFixture};
pub use super::gtest;
pub use super::matcher::{Matcher, MatcherBase};
pub use super::matchers::*;
pub use super::scoped_trace;
pub use super::verify_current_test_outcome;
pub use super::GoogleTestSupport;
pub use super::OrFail;
pub use super::Result;
pub use super::{
add_failure, add_failure_at, assert_false, assert_pred, assert_that, assert_true,
expect_eq, expect_false, expect_float_eq, expect_ge, expect_gt, expect_le, expect_lt,
expect_ne, expect_near, expect_pred, expect_that, expect_true, fail, succeed, verify_eq,
verify_false, verify_float_eq, verify_ge, verify_gt, verify_le, verify_lt, verify_ne,
verify_near, verify_pred, verify_that, verify_true,
};
}
#[macro_export]
macro_rules! scoped_trace {
($($arg:tt)*) => {
#[allow(clippy::shadow_same, clippy::shadow_unrelated)]
let _gtest_trace_guard = $crate::internal::scoped_trace::ScopedTraceGuard::new(
format!($($arg)*),
);
};
}
pub use googletest_macro::gtest;
pub use googletest_macro::test;
use internal::test_outcome::{TestAssertionFailure, TestOutcome};
pub type Result<T, E = TestAssertionFailure> = std::result::Result<T, E>;
#[track_caller]
pub fn verify_current_test_outcome() -> Result<()> {
TestOutcome::get_current_test_outcome()
}
pub trait GoogleTestSupport {
fn and_log_failure(self);
fn and_log_failure_with_message(self, provider: impl FnOnce() -> String)
where
Self: Sized,
{
self.with_failure_message(provider).and_log_failure();
}
fn failure_message(self, message: impl Into<String>) -> Self;
fn with_failure_message(self, provider: impl FnOnce() -> String) -> Self;
}
impl<T> GoogleTestSupport for std::result::Result<T, TestAssertionFailure> {
fn and_log_failure(self) {
TestOutcome::ensure_test_context_present();
if let Err(failure) = self {
failure.log();
}
}
fn failure_message(mut self, message: impl Into<String>) -> Self {
if let Err(ref mut failure) = self {
failure.custom_message = Some(message.into());
}
self
}
fn with_failure_message(mut self, provider: impl FnOnce() -> String) -> Self {
if let Err(ref mut failure) = self {
failure.custom_message = Some(provider());
}
self
}
}
pub trait OrFail {
type Output;
fn or_fail(self) -> Result<Self::Output>;
}
impl<T, E: std::fmt::Debug> OrFail for std::result::Result<T, E> {
type Output = T;
#[track_caller]
fn or_fail(self) -> std::result::Result<T, TestAssertionFailure> {
match self {
Ok(t) => Ok(t),
Err(e) => Err(TestAssertionFailure::create(format!("{e:?}"))),
}
}
}
impl<T> OrFail for Option<T> {
type Output = T;
#[track_caller]
fn or_fail(self) -> std::result::Result<T, TestAssertionFailure> {
match self {
Some(t) => Ok(t),
None => Err(TestAssertionFailure::create(format!(
"called `Option::or_fail()` on a `Option::<{}>::None` value",
std::any::type_name::<T>()
))),
}
}
}
#[doc(hidden)]
pub mod __internal_macro_support {
use crate::fixtures::Fixture;
pub struct FixtureTearDownOnDrop<T: Fixture> {
fixture: Option<T>,
}
impl<T: Fixture> FixtureTearDownOnDrop<T> {
pub fn new(fixture: T) -> Self {
Self { fixture: Some(fixture) }
}
pub fn tear_down(mut self) -> crate::Result<()> {
if let Some(fixture) = self.fixture.take() {
fixture.tear_down()
} else {
Ok(())
}
}
}
impl<T: Fixture> AsRef<T> for FixtureTearDownOnDrop<T> {
fn as_ref(&self) -> &T {
self.fixture.as_ref().unwrap()
}
}
impl<T: Fixture> AsMut<T> for FixtureTearDownOnDrop<T> {
fn as_mut(&mut self) -> &mut T {
self.fixture.as_mut().unwrap()
}
}
impl<T: Fixture> Drop for FixtureTearDownOnDrop<T> {
fn drop(&mut self) {
if let Some(fixture) = self.fixture.take() {
fixture.tear_down().unwrap();
}
}
}
}