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
74 lines
1.9 KiB
C++
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
|