4#include "Stroika/Foundation/StroikaPreComp.h"
12#include "Stroika/Foundation/Containers/Common.h"
14#include "Stroika/Foundation/Debug/Debugger.h"
15#include "Stroika/Foundation/Debug/Fatal.h"
16#include "Stroika/Foundation/Execution/Exceptions.h"
17#include "Stroika/Foundation/Execution/SignalHandlers.h"
19#include "TestHarness.h"
22using namespace Stroika::Frameworks;
26using namespace Stroika::Frameworks::Test;
29 void ASSERT_HANDLER_ (
const wchar_t* assertCategory,
const wchar_t* assertionText,
const wchar_t* fileName,
int lineNum,
const wchar_t* functionName)
noexcept
31 if (assertCategory ==
nullptr) {
32 assertCategory = L
"Unknown assertion";
34 if (assertionText ==
nullptr) {
37 if (fileName ==
nullptr) {
40 if (functionName ==
nullptr) {
43 wcerr <<
"FAILED: " << assertCategory <<
"; " << assertionText <<
";" << functionName <<
";" << fileName <<
": " << lineNum << endl;
44 DbgTrace (
"FAILED: {}; {}; {}; {}; {}"_f, assertCategory, assertionText, functionName, fileName, lineNum);
46 Debug::DropIntoDebuggerIfPresent ();
50 void WEAK_ASSERT_HANDLER_ (
const wchar_t* assertCategory,
const wchar_t* assertionText,
const wchar_t* fileName,
int lineNum,
51 const wchar_t* functionName)
noexcept
53 if (assertCategory ==
nullptr) {
54 assertCategory = L
"Unknown assertion";
56 if (assertionText ==
nullptr) {
59 if (fileName ==
nullptr) {
62 if (functionName ==
nullptr) {
65 wcerr <<
"WARNING: weak assertion " << assertCategory <<
"; " << assertionText <<
";" << functionName <<
";" << fileName <<
": "
67 DbgTrace (
"WARNING: weak assertion {}; {}; {}; {}; {}"_f, assertCategory, assertionText, functionName, fileName, lineNum);
71#if qStroika_Foundation_Characters_SDKUseswchar_t
74 cerr <<
"FAILED: " << msg << endl;
76 Debug::DropIntoDebuggerIfPresent ();
79 void FatalSignalHandler_ (Execution::SignalID signal)
noexcept
81 cerr <<
"FAILED: SIGNAL= " << Execution::SignalToName (signal) << endl;
82 DbgTrace (
"FAILED: SIGNAL= {}"_f, Execution::SignalToName (signal));
83 Debug::DropIntoDebuggerIfPresent ();
88vector<string> Test::Setup ([[maybe_unused]]
int argc, [[maybe_unused]]
const char* argv[])
90#if qStroika_Foundation_Debug_AssertionsChecked
94 Debug::RegisterDefaultFatalErrorHandlers (FatalErrorHandler_);
95 using namespace Execution;
96 SignalHandlerRegistry::sThe.SetStandardCrashHandlerSignals (SignalHandler{FatalSignalHandler_, SignalHandler::Type::eDirect});
97#if qStroika_HasComponent_googletest
99 testing::InitGoogleTest (&argc,
const_cast<char**
> (argv));
102 for (
int i = 0; i < argc; ++i) {
103 v.push_back (argv[i]);
108int Test::PrintPassOrFail (
void (*regressionTest) ())
111 (*regressionTest) ();
112 cout <<
"Succeeded" << endl;
116 auto exc = current_exception ();
117 cerr <<
"FAILED: REGRESSION TEST DUE TO EXCEPTION: '" << Characters::ToString (exc) <<
"'" << endl;
118 cout <<
"Failed" << endl;
119 DbgTrace (
"FAILED: REGRESSION TEST (Exception): '{}"_f, Characters::ToString (exc));
120 Debug::DropIntoDebuggerIfPresent ();
126void Test::Private_::Test_ (
bool failIfFalse,
bool isFailureElseWarning,
const wchar_t* regressionTestText,
const wchar_t* fileName,
int lineNum)
128 if (not failIfFalse) {
129 if (isFailureElseWarning) {
130 ASSERT_HANDLER_ (L
"RegressionTestFailure", regressionTestText, fileName, lineNum,
nullptr);
133 wcerr <<
"WARNING: REGRESSION TEST ISSUE: " << regressionTestText <<
";" << fileName <<
": " << lineNum << endl;
134 DbgTrace (
"WARNING: REGRESSION TEST ISSUE: ; {}; {}; {}"_f, regressionTestText, fileName, lineNum);
140void Test::Private_::VerifyTestResultWarning_ (
bool failIfFalse,
bool isFailureElseWarning,
const wchar_t* regressionTestText,
141 const wchar_t* fileName,
int lineNum)
143 if (not failIfFalse) {
144 if (isFailureElseWarning) {
145 ASSERT_HANDLER_ (L
"RegressionTestFailure", regressionTestText, fileName, lineNum,
nullptr);
148 wcerr <<
"WARNING: REGRESSION TEST ISSUE: " << regressionTestText <<
";" << fileName <<
": " << lineNum << endl;
149 DbgTrace (
"WARNING: REGRESSION TEST ISSUE: ; {}; {}; {}"_f, regressionTestText, fileName, lineNum);
155void Test::WarnTestIssue (
const char* issue)
157 using namespace Characters;
158 WarnTestIssue (NarrowSDK2Wide (issue).c_str ());
161void Test::WarnTestIssue (
const wchar_t* issue)
163 wcerr <<
"WARNING: REGRESSION TEST ISSUE: '" << issue <<
"'" << endl;
164 DbgTrace (
"WARNING: REGRESSION TEST ISSUE: '{}"_f, issue);
169 WarnTestIssue (issue.
As<wstring> ().c_str ());
178 : fSampler_{[this, sampleEvery] () {
180 while (not fDone_.load ()) {
181 this_thread::sleep_for (sampleEvery);
183 double gap = (now - prev).count ();
186 if (gap > fMaxGapSeconds_.load ()) {
187 fMaxGapSeconds_.store (gap);
194Test::ClockContinuitySampler::~ClockContinuitySampler ()
void SetWeakAssertionHandler(AssertionHandlerType assertionHandler)
void SetAssertionHandler(AssertionHandlerType assertionHandler)
time_point< RealtimeClock, DurationSeconds > TimePointSeconds
TimePointSeconds is a simpler approach to chrono::time_point, which doesn't require using templates e...
chrono::duration< double > DurationSeconds
chrono::duration<double> - a time span (length of time) measured in seconds, but high precision.
String is like std::u32string, except it is much easier to use, often much more space efficient,...
static String FromSDKString(const SDKChar *from)
nonvirtual Foundation::Time::DurationSeconds GetMaxObservedGap() const
Create a format-string (see std::wformat_string or Stroika FormatString, or python 'f' strings) - a F...
conditional_t< qStroika_Foundation_Characters_SDKUseswchar_t, wchar_t, char > SDKChar