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/testing/unittest/junit.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/testing/unittest/junit.cpp')
-rw-r--r-- | library/cpp/testing/unittest/junit.cpp | 69 |
1 files changed, 68 insertions, 1 deletions
diff --git a/library/cpp/testing/unittest/junit.cpp b/library/cpp/testing/unittest/junit.cpp index 6d80a204fff..44771ecd14c 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; \ |