Files
tubestation/testing/gtest/mozilla/MozHelpers.cpp
Andreas Pehrson a8ef21bebc Bug 1825259 - Implement ScopedTestResultReporter to help print assertion failures in death test child processes. r=gbrown
Gtest checks (with ASSERT_* or EXPECT_* macros) in gtest death test child
processes are usually ignored with no way of manually enabling them.

This patch implements a helper class, ScopedTestResultReporter, that when it is
the current test reporter will print TestPartResults to stderr. Stderr of a
death test child process will get printed by the parent only if the testcase
failed. A death test child can only signal to the parent to fail the testcase
by means of the exit code (or the absence of exit). To help signal an
unexpected exit code, ScopedTestResultReporter can be made to exit the process
automatically as it goes out of scope, using different exit codes depending on
the death test child's test status where 0=pass, 1=nonfatal failure, and
2=fatal failure.

Note that when used like this, the death test parent process must be set up to
expect an exit code of 0 from the death test child process, typically through
`EXPECT_EXIT(DoTestThatExits(), testing::ExitedWithCode(0), "");`.

When an `EXPECT_EXIT` check fails, gtest makes sure to print stderr from the
child process with the unexpected exit code (which is where the test results
passed through ScopedTestResultReporter were printed).

Differential Revision: https://phabricator.services.mozilla.com/D175139
2023-04-19 08:40:23 +00:00

74 lines
1.9 KiB
C++

#include "MozHelpers.h"
#include <iostream>
#include "gtest/gtest-spi.h"
#include "mozilla/Mutex.h"
#include "nsDebug.h"
namespace mozilla::gtest {
void DisableCrashReporter() {
nsCOMPtr<nsICrashReporter> crashreporter =
do_GetService("@mozilla.org/toolkit/crash-reporter;1");
if (crashreporter) {
crashreporter->SetEnabled(false);
}
}
class ScopedTestResultReporterImpl
: public ScopedTestResultReporter,
public testing::ScopedFakeTestPartResultReporter {
public:
explicit ScopedTestResultReporterImpl(ExitMode aExitMode)
: testing::ScopedFakeTestPartResultReporter(INTERCEPT_ALL_THREADS,
nullptr),
mExitMode(aExitMode) {}
~ScopedTestResultReporterImpl() {
switch (mExitMode) {
case ExitMode::ExitOnDtor:
exit(ExitCode(Status()));
case ExitMode::NoExit:
break;
}
}
void ReportTestPartResult(const testing::TestPartResult& aResult) override {
{
MutexAutoLock lock(mMutex);
if (aResult.nonfatally_failed() &&
mStatus < TestResultStatus::NonFatalFailure) {
mStatus = TestResultStatus::NonFatalFailure;
}
if (aResult.fatally_failed() &&
mStatus < TestResultStatus::FatalFailure) {
mStatus = TestResultStatus::FatalFailure;
}
}
std::ostringstream stream;
stream << aResult;
printf_stderr("%s\n", stream.str().c_str());
}
TestResultStatus Status() const override {
MutexAutoLock lock(mMutex);
return mStatus;
}
private:
const ExitMode mExitMode;
mutable Mutex mMutex{"ScopedTestResultReporterImpl::mMutex"};
TestResultStatus mStatus MOZ_GUARDED_BY(mMutex) = TestResultStatus::Pass;
};
UniquePtr<ScopedTestResultReporter> ScopedTestResultReporter::Create(
ExitMode aExitMode) {
return MakeUnique<ScopedTestResultReporterImpl>(aExitMode);
}
} // namespace mozilla::gtest