void-packages/srcpkgs/leatherman/patches/catch.patch

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")