391 lines
14 KiB
Diff
391 lines
14 KiB
Diff
Backport
|
|
https://github.com/catchorg/Catch2/commit/6c6cfe126aa5f4a0cfbe8e805db550e47e26aab1
|
|
And run:
|
|
python2 scripts/generateSingleHeader.py
|
|
Index: leatherman-1.12.4/catch/inc/catch.hpp
|
|
===================================================================
|
|
--- leatherman-1.12.4.orig/catch/inc/catch.hpp
|
|
+++ leatherman-1.12.4/catch/inc/catch.hpp
|
|
@@ -1,6 +1,6 @@
|
|
/*
|
|
* Catch v1.10.0
|
|
- * Generated: 2017-08-26 15:16:46.676990
|
|
+ * Generated: 2022-10-12 22:42:54.972394
|
|
* ----------------------------------------------------------
|
|
* This file has been merged from multiple headers. Please don't edit it directly
|
|
* Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved.
|
|
@@ -6320,9 +6320,12 @@ CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS
|
|
// #included from: catch_fatal_condition.hpp
|
|
#define TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED
|
|
|
|
+#include <cassert>
|
|
+#include <stdexcept>
|
|
+
|
|
namespace Catch {
|
|
|
|
- // Report the error condition
|
|
+ //! Signals fatal error message to the run context
|
|
inline void reportFatal( std::string const& message ) {
|
|
IContext& context = Catch::getCurrentContext();
|
|
IResultCapture* resultCapture = context.getResultCapture();
|
|
@@ -6360,8 +6363,31 @@ namespace Catch {
|
|
# if !defined ( CATCH_CONFIG_WINDOWS_SEH )
|
|
|
|
namespace Catch {
|
|
- struct FatalConditionHandler {
|
|
- void reset() {}
|
|
+ class FatalConditionHandler {
|
|
+ bool m_started = false;
|
|
+
|
|
+ // Install/disengage implementation for specific platform.
|
|
+ // Should be if-defed to work on current platform, can assume
|
|
+ // engage-disengage 1:1 pairing.
|
|
+ void engage_platform() {}
|
|
+ void disengage_platform() {}
|
|
+
|
|
+ public:
|
|
+ // Should also have platform-specific implementations as needed
|
|
+ FatalConditionHandler() {}
|
|
+ ~FatalConditionHandler() {}
|
|
+
|
|
+ void engage() {
|
|
+ assert(!m_started && "Handler cannot be installed twice.");
|
|
+ m_started = true;
|
|
+ engage_platform();
|
|
+ }
|
|
+
|
|
+ void disengage() {
|
|
+ assert(m_started && "Handler cannot be uninstalled without being installed first");
|
|
+ m_started = false;
|
|
+ disengage_platform();
|
|
+ }
|
|
};
|
|
}
|
|
|
|
@@ -6381,53 +6407,72 @@ namespace Catch {
|
|
{ EXCEPTION_INT_DIVIDE_BY_ZERO, "Divide by zero error" },
|
|
};
|
|
|
|
- struct FatalConditionHandler {
|
|
-
|
|
- static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) {
|
|
- for (int i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) {
|
|
- if (ExceptionInfo->ExceptionRecord->ExceptionCode == signalDefs[i].id) {
|
|
- reportFatal(signalDefs[i].name);
|
|
- }
|
|
+ static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) {
|
|
+ for (int i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) {
|
|
+ if (ExceptionInfo->ExceptionRecord->ExceptionCode == signalDefs[i].id) {
|
|
+ reportFatal(signalDefs[i].name);
|
|
}
|
|
- // If its not an exception we care about, pass it along.
|
|
- // This stops us from eating debugger breaks etc.
|
|
- return EXCEPTION_CONTINUE_SEARCH;
|
|
}
|
|
+ // If its not an exception we care about, pass it along.
|
|
+ // This stops us from eating debugger breaks etc.
|
|
+ return EXCEPTION_CONTINUE_SEARCH;
|
|
+ }
|
|
|
|
- FatalConditionHandler() {
|
|
- isSet = true;
|
|
- // 32k seems enough for Catch to handle stack overflow,
|
|
- // but the value was found experimentally, so there is no strong guarantee
|
|
- guaranteeSize = 32 * 1024;
|
|
- exceptionHandlerHandle = CATCH_NULL;
|
|
+ // Since we do not support multiple instantiations, we put these
|
|
+ // into global variables and rely on cleaning them up in outlined
|
|
+ // constructors/destructors
|
|
+ static PVOID exceptionHandlerHandle = CATCH_NULL;
|
|
+
|
|
+ class FatalConditionHandler {
|
|
+ bool m_started = false;
|
|
+
|
|
+ // Install/disengage implementation for specific platform.
|
|
+ // Should be if-defed to work on current platform, can assume
|
|
+ // engage-disengage 1:1 pairing.
|
|
+
|
|
+ void engage_platform() {
|
|
// Register as first handler in current chain
|
|
exceptionHandlerHandle = AddVectoredExceptionHandler(1, handleVectoredException);
|
|
- // Pass in guarantee size to be filled
|
|
- SetThreadStackGuarantee(&guaranteeSize);
|
|
+ if (!exceptionHandlerHandle) {
|
|
+ throw std::runtime_error("Could not register vectored exception handler");
|
|
+ }
|
|
}
|
|
|
|
- static void reset() {
|
|
- if (isSet) {
|
|
- // Unregister handler and restore the old guarantee
|
|
- RemoveVectoredExceptionHandler(exceptionHandlerHandle);
|
|
- SetThreadStackGuarantee(&guaranteeSize);
|
|
- exceptionHandlerHandle = CATCH_NULL;
|
|
- isSet = false;
|
|
+ void disengage_platform() {
|
|
+ if (!RemoveVectoredExceptionHandler(exceptionHandlerHandle)) {
|
|
+ throw std::runtime_error("Could not unregister vectored exception handler");
|
|
}
|
|
+ exceptionHandlerHandle = CATCH_NULL;
|
|
}
|
|
|
|
- ~FatalConditionHandler() {
|
|
- reset();
|
|
+ public:
|
|
+ FatalConditionHandler() {
|
|
+ ULONG guaranteeSize = static_cast<ULONG>(32 * 1024);
|
|
+ if (!SetThreadStackGuarantee(&guaranteeSize)) {
|
|
+ // We do not want to fully error out, because needing
|
|
+ // the stack reserve should be rare enough anyway.
|
|
+ Catch::cerr()
|
|
+ << "Failed to reserve piece of stack."
|
|
+ << " Stack overflows will not be reported successfully.";
|
|
+ }
|
|
}
|
|
- private:
|
|
- static bool isSet;
|
|
- static ULONG guaranteeSize;
|
|
- static PVOID exceptionHandlerHandle;
|
|
- };
|
|
|
|
- bool FatalConditionHandler::isSet = false;
|
|
- ULONG FatalConditionHandler::guaranteeSize = 0;
|
|
- PVOID FatalConditionHandler::exceptionHandlerHandle = CATCH_NULL;
|
|
+ // We do not attempt to unset the stack guarantee, because
|
|
+ // Windows does not support lowering the stack size guarantee.
|
|
+ ~FatalConditionHandler() {}
|
|
+
|
|
+ void engage() {
|
|
+ assert(!m_started && "Handler cannot be installed twice.");
|
|
+ m_started = true;
|
|
+ engage_platform();
|
|
+ }
|
|
+
|
|
+ void disengage() {
|
|
+ assert(m_started && "Handler cannot be uninstalled without being installed first");
|
|
+ m_started = false;
|
|
+ disengage_platform();
|
|
+ }
|
|
+ };
|
|
|
|
} // namespace Catch
|
|
|
|
@@ -6438,8 +6483,31 @@ namespace Catch {
|
|
# if !defined(CATCH_CONFIG_POSIX_SIGNALS)
|
|
|
|
namespace Catch {
|
|
- struct FatalConditionHandler {
|
|
- void reset() {}
|
|
+ class FatalConditionHandler {
|
|
+ bool m_started = false;
|
|
+
|
|
+ // Install/disengage implementation for specific platform.
|
|
+ // Should be if-defed to work on current platform, can assume
|
|
+ // engage-disengage 1:1 pairing.
|
|
+ void engage_platform() {}
|
|
+ void disengage_platform() {}
|
|
+
|
|
+ public:
|
|
+ // Should also have platform-specific implementations as needed
|
|
+ FatalConditionHandler() {}
|
|
+ ~FatalConditionHandler() {}
|
|
+
|
|
+ void engage() {
|
|
+ assert(!m_started && "Handler cannot be installed twice.");
|
|
+ m_started = true;
|
|
+ engage_platform();
|
|
+ }
|
|
+
|
|
+ void disengage() {
|
|
+ assert(m_started && "Handler cannot be uninstalled without being installed first");
|
|
+ m_started = false;
|
|
+ disengage_platform();
|
|
+ }
|
|
};
|
|
}
|
|
|
|
@@ -6463,29 +6531,56 @@ namespace Catch {
|
|
{ SIGABRT, "SIGABRT - Abort (abnormal termination) signal" }
|
|
};
|
|
|
|
- struct FatalConditionHandler {
|
|
+// Older GCCs trigger -Wmissing-field-initializers for T foo = {}
|
|
+// which is zero initialization, but not explicit. We want to avoid
|
|
+// that.
|
|
+#if defined(__GNUC__)
|
|
+# pragma GCC diagnostic push
|
|
+# pragma GCC diagnostic ignored "-Wmissing-field-initializers"
|
|
+#endif
|
|
|
|
- static bool isSet;
|
|
- static struct sigaction oldSigActions [sizeof(signalDefs)/sizeof(SignalDefs)];
|
|
- static stack_t oldSigStack;
|
|
- static char altStackMem[SIGSTKSZ];
|
|
-
|
|
- static void handleSignal( int sig ) {
|
|
- std::string name = "<unknown signal>";
|
|
- for (std::size_t i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) {
|
|
- SignalDefs &def = signalDefs[i];
|
|
- if (sig == def.id) {
|
|
- name = def.name;
|
|
- break;
|
|
- }
|
|
+ static char* altStackMem = CATCH_NULL;
|
|
+ static std::size_t altStackSize = 0;
|
|
+ static stack_t oldSigStack;
|
|
+ static struct sigaction oldSigActions[sizeof(signalDefs) / sizeof(SignalDefs)];
|
|
+
|
|
+ static void restorePreviousSignalHandlers() {
|
|
+ // We set signal handlers back to the previous ones. Hopefully
|
|
+ // nobody overwrote them in the meantime, and doesn't expect
|
|
+ // their signal handlers to live past ours given that they
|
|
+ // installed them after ours..
|
|
+ for (std::size_t i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) {
|
|
+ sigaction(signalDefs[i].id, &oldSigActions[i], CATCH_NULL);
|
|
+ }
|
|
+ // Return the old stack
|
|
+ sigaltstack(&oldSigStack, CATCH_NULL);
|
|
+ }
|
|
+
|
|
+ static void handleSignal( int sig ) {
|
|
+ char const * name = "<unknown signal>";
|
|
+ for (std::size_t i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) {
|
|
+ SignalDefs &def = signalDefs[i];
|
|
+ if (sig == def.id) {
|
|
+ name = def.name;
|
|
+ break;
|
|
}
|
|
- reset();
|
|
- reportFatal(name);
|
|
- raise( sig );
|
|
}
|
|
+ // We need to restore previous signal handlers and let them do
|
|
+ // their thing, so that the users can have the debugger break
|
|
+ // when a signal is raised, and so on.
|
|
+ restorePreviousSignalHandlers();
|
|
+ reportFatal( name );
|
|
+ raise( sig );
|
|
+ }
|
|
|
|
- FatalConditionHandler() {
|
|
- isSet = true;
|
|
+ class FatalConditionHandler {
|
|
+ bool m_started = false;
|
|
+
|
|
+ // Install/disengage implementation for specific platform.
|
|
+ // Should be if-defed to work on current platform, can assume
|
|
+ // engage-disengage 1:1 pairing.
|
|
+
|
|
+ void engage_platform() {
|
|
stack_t sigStack;
|
|
sigStack.ss_sp = altStackMem;
|
|
sigStack.ss_size = SIGSTKSZ;
|
|
@@ -6500,26 +6595,42 @@ namespace Catch {
|
|
}
|
|
}
|
|
|
|
- ~FatalConditionHandler() {
|
|
- reset();
|
|
+ void disengage_platform() {
|
|
+ restorePreviousSignalHandlers();
|
|
}
|
|
- static void reset() {
|
|
- if( isSet ) {
|
|
- // Set signals back to previous values -- hopefully nobody overwrote them in the meantime
|
|
- for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) {
|
|
- sigaction(signalDefs[i].id, &oldSigActions[i], CATCH_NULL);
|
|
- }
|
|
- // Return the old stack
|
|
- sigaltstack(&oldSigStack, CATCH_NULL);
|
|
- isSet = false;
|
|
+
|
|
+ public:
|
|
+ FatalConditionHandler() {
|
|
+ assert(!altStackMem && "Cannot initialize POSIX signal handler when one already exists");
|
|
+ if (altStackSize == 0) {
|
|
+ altStackSize = SIGSTKSZ;
|
|
}
|
|
+ altStackMem = new char[altStackSize]();
|
|
+ }
|
|
+
|
|
+ ~FatalConditionHandler() {
|
|
+ delete[] altStackMem;
|
|
+ // We signal that another instance can be constructed by zeroing
|
|
+ // out the pointer.
|
|
+ altStackMem = CATCH_NULL;
|
|
+ }
|
|
+
|
|
+ void engage() {
|
|
+ assert(!m_started && "Handler cannot be installed twice.");
|
|
+ m_started = true;
|
|
+ engage_platform();
|
|
+ }
|
|
+
|
|
+ void disengage() {
|
|
+ assert(m_started && "Handler cannot be uninstalled without being installed first");
|
|
+ m_started = false;
|
|
+ disengage_platform();
|
|
}
|
|
};
|
|
|
|
- bool FatalConditionHandler::isSet = false;
|
|
- struct sigaction FatalConditionHandler::oldSigActions[sizeof(signalDefs)/sizeof(SignalDefs)] = {};
|
|
- stack_t FatalConditionHandler::oldSigStack = {};
|
|
- char FatalConditionHandler::altStackMem[SIGSTKSZ] = {};
|
|
+#if defined(__GNUC__)
|
|
+# pragma GCC diagnostic pop
|
|
+#endif
|
|
|
|
} // namespace Catch
|
|
|
|
@@ -6527,6 +6638,23 @@ namespace Catch {
|
|
|
|
#endif // not Windows
|
|
|
|
+namespace Catch {
|
|
+
|
|
+ //! Simple RAII guard for (dis)engaging the FatalConditionHandler
|
|
+ class FatalConditionHandlerGuard {
|
|
+ FatalConditionHandler* m_handler;
|
|
+ public:
|
|
+ FatalConditionHandlerGuard(FatalConditionHandler* handler):
|
|
+ m_handler(handler) {
|
|
+ m_handler->engage();
|
|
+ }
|
|
+ ~FatalConditionHandlerGuard() {
|
|
+ m_handler->disengage();
|
|
+ }
|
|
+ };
|
|
+
|
|
+} // end namespace Catch
|
|
+
|
|
#include <set>
|
|
#include <string>
|
|
|
|
@@ -6865,9 +6993,8 @@ namespace Catch {
|
|
}
|
|
|
|
void invokeActiveTestCase() {
|
|
- FatalConditionHandler fatalConditionHandler; // Handle signals
|
|
+ FatalConditionHandlerGuard _(&m_fatalConditionhandler);
|
|
m_activeTestCase->invoke();
|
|
- fatalConditionHandler.reset();
|
|
}
|
|
|
|
private:
|
|
@@ -6905,6 +7032,7 @@ namespace Catch {
|
|
std::vector<SectionEndInfo> m_unfinishedSections;
|
|
std::vector<ITracker*> m_activeSections;
|
|
TrackerContext m_trackerContext;
|
|
+ FatalConditionHandler m_fatalConditionhandler;
|
|
size_t m_prevPassed;
|
|
bool m_shouldReportUnexpected;
|
|
};
|
|
Index: leatherman-1.12.4/catch/CMakeLists.txt
|
|
===================================================================
|
|
--- leatherman-1.12.4.orig/catch/CMakeLists.txt
|
|
+++ leatherman-1.12.4/catch/CMakeLists.txt
|
|
@@ -1 +1 @@
|
|
-add_leatherman_vendored("Catch-1.10.0.zip" "Catch-1.10.0" "single_include")
|
|
+add_leatherman_includes("catch/include")
|