Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 34 additions & 9 deletions googletest/src/internal/test_outcome.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,23 +62,25 @@ impl TestOutcome {
///
/// **For internal use only. API stablility is not guaranteed!**
#[doc(hidden)]
pub fn close_current_test_outcome<E: Display>(result: Result<(), E>) -> Result<(), ()> {
pub fn close_current_test_outcome<E: Display>(
inner_result: Result<(), E>,
) -> Result<(), TestFailure> {
TestOutcome::with_current_test_outcome(|mut outcome| {
let result = match &*outcome {
Some(TestOutcome::Success) => match result {
let outer_result = match &*outcome {
Some(TestOutcome::Success) => match inner_result {
Ok(()) => Ok(()),
Err(f) => {
print!("{}", f);
Err(())
}
Err(_) => Err(TestFailure),
},
Some(TestOutcome::Failure) => Err(()),
Some(TestOutcome::Failure) => Err(TestFailure),
None => {
panic!("No test context found. This indicates a bug in GoogleTest.")
}
};
if let Err(fatal_assertion_failure) = inner_result {
println!("{fatal_assertion_failure}");
}
*outcome = None;
result
outer_result
})
}

Expand Down Expand Up @@ -114,6 +116,29 @@ No test context found.
}
}

/// A market struct indicating that a test has failed.
///
/// This exists to implement the [Error][std::error::Error] trait. It displays
/// to a message indicating that the actual test assertion failure messages are
/// in the text above.
pub struct TestFailure;

impl std::error::Error for TestFailure {}

impl std::fmt::Debug for TestFailure {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
writeln!(f, "See failure output above")?;
Ok(())
}
}

impl std::fmt::Display for TestFailure {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
writeln!(f, "See failure output above")?;
Ok(())
}
}

/// A report that a single test assertion failed.
///
/// **For internal use only. API stablility is not guaranteed!**
Expand Down
2 changes: 1 addition & 1 deletion googletest_macro/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ pub fn test(
};
let function = quote! {
#(#attrs)*
#sig -> std::result::Result<(), ()> {
#sig -> std::result::Result<(), googletest::internal::test_outcome::TestFailure> {
#maybe_closure
use googletest::internal::test_outcome::TestOutcome;
TestOutcome::init_current_test_outcome();
Expand Down
5 changes: 5 additions & 0 deletions integration_tests/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,11 @@ name = "failure_due_to_returned_error"
path = "src/failure_due_to_returned_error.rs"
test = false

[[bin]]
name = "fatal_and_non_fatal_failure"
path = "src/fatal_and_non_fatal_failure.rs"
test = false

[[bin]]
name = "first_failure_aborts"
path = "src/first_failure_aborts.rs"
Expand Down
28 changes: 28 additions & 0 deletions integration_tests/src/fatal_and_non_fatal_failure.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

fn main() {}

#[cfg(test)]
mod tests {
use googletest::prelude::*;

#[googletest::test]
fn fatal_and_non_fatal_failure() -> Result<()> {
let value = 2;
verify_that!(value, eq(3)).and_log_failure();
verify_that!(value, eq(4))?;
Ok(())
}
}
25 changes: 23 additions & 2 deletions integration_tests/src/integration_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,8 @@ mod tests {
}

#[test]
fn should_output_second_failure_message_on_second_assertion_failure_with_expect_that()
-> Result<()> {
fn should_output_second_failure_message_on_second_assertion_failure_with_expect_that(
) -> Result<()> {
let output = run_external_process_in_tests_directory("two_expect_that_failures")?;

verify_that!(
Expand Down Expand Up @@ -220,6 +220,27 @@ mod tests {
)
}

#[test]
fn should_log_fatal_and_non_fatal_errors_to_stdout() -> Result<()> {
let output = run_external_process_in_tests_directory("fatal_and_non_fatal_failure")?;

verify_that!(
output,
all!(
contains_substring(indoc! {"
Expected: is equal to 3
Actual: 2,
which isn't equal to 3
"}),
contains_substring(indoc! {"
Expected: is equal to 4
Actual: 2,
which isn't equal to 4
"})
)
)
}

#[test]
fn should_abort_after_first_failure() -> Result<()> {
let output = run_external_process_in_tests_directory("first_failure_aborts")?;
Expand Down
1 change: 1 addition & 0 deletions run_integration_tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ INTEGRATION_TEST_BINARIES=(
"failure_due_to_fail_macro_with_empty_message"
"failure_due_to_fail_macro_with_format_arguments"
"failure_due_to_returned_error"
"fatal_and_non_fatal_failure"
"first_failure_aborts"
"google_test_with_rstest"
"non_fatal_failure_in_subroutine"
Expand Down