diff options
author | galaxycrab <UgnineSirdis@ydb.tech> | 2023-08-04 13:13:41 +0300 |
---|---|---|
committer | galaxycrab <UgnineSirdis@ydb.tech> | 2023-08-04 14:42:46 +0300 |
commit | 0378da6ac1a3be2823cd3031fbf0ae403d962995 (patch) | |
tree | bb4a84db2196119cf270670b446c875e7a4d0e50 /library/cpp | |
parent | cf273f7a9b5bb6d23c1f3c8ab236a4af1f511724 (diff) | |
download | ydb-0378da6ac1a3be2823cd3031fbf0ae403d962995.tar.gz |
KIKIMR-18702 JUnit tests. Save captured test output even when abort happened
Diffstat (limited to 'library/cpp')
-rw-r--r-- | library/cpp/testing/unittest/junit.cpp | 69 | ||||
-rw-r--r-- | library/cpp/testing/unittest/junit.h | 29 |
2 files changed, 97 insertions, 1 deletions
diff --git a/library/cpp/testing/unittest/junit.cpp b/library/cpp/testing/unittest/junit.cpp index 6d80a204ff..44771ecd14 100644 --- a/library/cpp/testing/unittest/junit.cpp +++ b/library/cpp/testing/unittest/junit.cpp @@ -8,6 +8,7 @@ #include <util/generic/size_literals.h> #include <util/stream/file.h> #include <util/stream/input.h> +#include <util/system/backtrace.h> #include <util/system/env.h> #include <util/system/file.h> #include <util/system/fs.h> @@ -16,6 +17,7 @@ #include <util/system/tempfile.h> #include <stdio.h> +#include <signal.h> #if defined(_win_) #include <io.h> @@ -186,7 +188,8 @@ TJUnitProcessor::~TJUnitProcessor() { } void TJUnitProcessor::OnBeforeTest(const TTest* test) { - Y_UNUSED(test); + CurrentTest.emplace(test); + CaptureSignal(this); if (!GetForkTests() || GetIsForked()) { StdErrCapturer = MakeHolder<TOutputCapturer>(TOutputCapturer::STDERR_FD); StdOutCapturer = MakeHolder<TOutputCapturer>(TOutputCapturer::STDOUT_FD); @@ -228,6 +231,7 @@ void TJUnitProcessor::OnFinish(const TFinish* descr) { } else { MergeSubprocessReport(); } + UncaptureSignal(); } TString TJUnitProcessor::BuildFileName(size_t index, const TStringBuf extension) const { @@ -296,6 +300,69 @@ void TJUnitProcessor::MakeTmpFileNameForForkedTests() { } } +static TJUnitProcessor* CurrentJUnitProcessor = nullptr; + +void TJUnitProcessor::CaptureSignal(TJUnitProcessor* processor) { + CurrentJUnitProcessor = processor; + processor->PrevAbortHandler = signal(SIGABRT, &TJUnitProcessor::SignalHandler); + if (processor->PrevAbortHandler == SIG_ERR) { + processor->PrevAbortHandler = nullptr; + } + processor->PrevSegvHandler = signal(SIGSEGV, &TJUnitProcessor::SignalHandler); + if (processor->PrevSegvHandler == SIG_ERR) { + processor->PrevSegvHandler = nullptr; + } +} + +void TJUnitProcessor::UncaptureSignal() { + if (CurrentJUnitProcessor) { + if (CurrentJUnitProcessor->PrevAbortHandler != nullptr) { + signal(SIGABRT, CurrentJUnitProcessor->PrevAbortHandler); + } else { + signal(SIGABRT, SIG_DFL); + } + + if (CurrentJUnitProcessor->PrevSegvHandler != nullptr) { + signal(SIGSEGV, CurrentJUnitProcessor->PrevSegvHandler); + } else { + signal(SIGSEGV, SIG_DFL); + } + } +} + +void TJUnitProcessor::SignalHandler(int signal) { + if (CurrentJUnitProcessor) { + if (CurrentJUnitProcessor->CurrentTest) { + TError errDesc; + errDesc.test = *CurrentJUnitProcessor->CurrentTest; + if (signal == SIGABRT) { + errDesc.msg = "Test aborted"; + } else { + errDesc.msg = "Segmentation fault"; + PrintBackTrace(); + } + CurrentJUnitProcessor->OnError(&errDesc); + + TFinish finishDesc; + finishDesc.Success = false; + finishDesc.test = *CurrentJUnitProcessor->CurrentTest; + CurrentJUnitProcessor->OnFinish(&finishDesc); + } + + CurrentJUnitProcessor->Save(); + + if (signal == SIGABRT) { + if (CurrentJUnitProcessor->PrevAbortHandler) { + CurrentJUnitProcessor->PrevAbortHandler(signal); + } + } else { + if (CurrentJUnitProcessor->PrevSegvHandler) { + CurrentJUnitProcessor->PrevSegvHandler(signal); + } + } + } +} + #define CHECK_CALL(expr) if (int resultCode = (expr); resultCode < 0) { \ Cerr << "Faield to write to xml. Result code: " << resultCode << Endl; \ return; \ diff --git a/library/cpp/testing/unittest/junit.h b/library/cpp/testing/unittest/junit.h index 1797055877..27b73013ca 100644 --- a/library/cpp/testing/unittest/junit.h +++ b/library/cpp/testing/unittest/junit.h @@ -4,6 +4,8 @@ #include <util/generic/maybe.h> #include <util/system/tempfile.h> +#include <optional> + namespace NUnitTest { extern const TString Y_UNITTEST_OUTPUT_CMDLINE_OPTION; @@ -52,6 +54,26 @@ class TJUnitProcessor : public ITestSuiteProcessor { } }; + // Holds a copy of TTest structure for current test + class TCurrentTest { + public: + TCurrentTest(const TTest* test) + : TestName(test->name) + , Unit(*test->unit) + , Test{&Unit, TestName.c_str()} + { + } + + operator const TTest*() const { + return &Test; + } + + private: + TString TestName; + TUnit Unit; + TTest Test; + }; + struct TOutputCapturer; public: @@ -96,6 +118,10 @@ private: void MakeTmpFileNameForForkedTests(); static void TransferFromCapturer(THolder<TJUnitProcessor::TOutputCapturer>& capturer, TString& out, IOutputStream& outStream); + static void CaptureSignal(TJUnitProcessor* processor); + static void UncaptureSignal(); + static void SignalHandler(int signal); + private: const TString FileName; // cmd line param const TString ExecName; // cmd line param @@ -105,6 +131,9 @@ private: THolder<TOutputCapturer> StdErrCapturer; THolder<TOutputCapturer> StdOutCapturer; TInstant StartCurrentTestTime; + void (*PrevAbortHandler)(int) = nullptr; + void (*PrevSegvHandler)(int) = nullptr; + std::optional<TCurrentTest> CurrentTest; }; } // namespace NUnitTest |