Control: tags 1001262 + pending

Dear maintainer,

I've prepared an NMU for monado (versioned as 21.0.0~dfsg1-2.1) and 
uploaded it to DELAYED/14. Please feel free to tell me if I should 
cancel it.

cu
Adrian
diff -Nru monado-21.0.0~dfsg1/debian/changelog 
monado-21.0.0~dfsg1/debian/changelog
--- monado-21.0.0~dfsg1/debian/changelog        2021-10-27 00:59:16.000000000 
+0300
+++ monado-21.0.0~dfsg1/debian/changelog        2022-09-12 10:16:51.000000000 
+0300
@@ -1,3 +1,10 @@
+monado (21.0.0~dfsg1-2.1) unstable; urgency=medium
+
+  * Non-maintainer upload.
+  * Add upstream fix for FTBFS with glibc 2.34. (Closes: #1001262)
+
+ -- Adrian Bunk <b...@debian.org>  Mon, 12 Sep 2022 10:16:51 +0300
+
 monado (21.0.0~dfsg1-2) unstable; urgency=medium
 
   * d/control
diff -Nru 
monado-21.0.0~dfsg1/debian/patches/0001-src-external-Update-to-Catch2-version-2.13.7.patch
 
monado-21.0.0~dfsg1/debian/patches/0001-src-external-Update-to-Catch2-version-2.13.7.patch
--- 
monado-21.0.0~dfsg1/debian/patches/0001-src-external-Update-to-Catch2-version-2.13.7.patch
  1970-01-01 02:00:00.000000000 +0200
+++ 
monado-21.0.0~dfsg1/debian/patches/0001-src-external-Update-to-Catch2-version-2.13.7.patch
  2022-09-12 09:54:46.000000000 +0300
@@ -0,0 +1,1513 @@
+From 1a556740d5ba79af8f5e72d7145ab62b8867db0b Mon Sep 17 00:00:00 2001
+From: Ryan Pavlik <ryan.pav...@collabora.com>
+Date: Wed, 27 Oct 2021 13:46:55 -0500
+Subject: src/external: Update to Catch2 version 2.13.7
+
+---
+ src/external/Catch2/catch/catch.hpp | 779 ++++++++++++++++++----------
+ 1 file changed, 516 insertions(+), 263 deletions(-)
+
+diff --git a/src/external/Catch2/catch/catch.hpp 
b/src/external/Catch2/catch/catch.hpp
+index f64422ae..7e706f94 100644
+--- a/src/external/Catch2/catch/catch.hpp
++++ b/src/external/Catch2/catch/catch.hpp
+@@ -1,9 +1,9 @@
+ /*
+- *  Catch v2.12.2
+- *  Generated: 2020-05-25 15:09:23.791719
++ *  Catch v2.13.7
++ *  Generated: 2021-07-28 20:29:27.753164
+  *  ----------------------------------------------------------
+  *  This file has been merged from multiple headers. Please don't edit it 
directly
+- *  Copyright (c) 2020 Two Blue Cubes Ltd. All rights reserved.
++ *  Copyright (c) 2021 Two Blue Cubes Ltd. All rights reserved.
+  *
+  *  Distributed under the Boost Software License, Version 1.0. (See 
accompanying
+  *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+@@ -14,8 +14,8 @@
+ 
+ 
+ #define CATCH_VERSION_MAJOR 2
+-#define CATCH_VERSION_MINOR 12
+-#define CATCH_VERSION_PATCH 2
++#define CATCH_VERSION_MINOR 13
++#define CATCH_VERSION_PATCH 7
+ 
+ #ifdef __clang__
+ #    pragma clang system_header
+@@ -66,13 +66,16 @@
+ #if !defined(CATCH_CONFIG_IMPL_ONLY)
+ // start catch_platform.h
+ 
++// See e.g.:
++// 
https://opensource.apple.com/source/CarbonHeaders/CarbonHeaders-18.1/TargetConditionals.h.auto.html
+ #ifdef __APPLE__
+-# include <TargetConditionals.h>
+-# if TARGET_OS_OSX == 1
+-#  define CATCH_PLATFORM_MAC
+-# elif TARGET_OS_IPHONE == 1
+-#  define CATCH_PLATFORM_IPHONE
+-# endif
++#  include <TargetConditionals.h>
++#  if (defined(TARGET_OS_OSX) && TARGET_OS_OSX == 1) || \
++      (defined(TARGET_OS_MAC) && TARGET_OS_MAC == 1)
++#    define CATCH_PLATFORM_MAC
++#  elif (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE == 1)
++#    define CATCH_PLATFORM_IPHONE
++#  endif
+ 
+ #elif defined(linux) || defined(__linux) || defined(__linux__)
+ #  define CATCH_PLATFORM_LINUX
+@@ -132,13 +135,9 @@ namespace Catch {
+ 
+ #endif
+ 
+-#if defined(__cpp_lib_uncaught_exceptions)
+-#  define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
+-#endif
+-
+-// We have to avoid both ICC and Clang, because they try to mask themselves
+-// as gcc, and we want only GCC in this block
+-#if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC)
++// Only GCC compiler should be used in this block, so other compilers trying 
to
++// mask themselves as GCC should be ignored.
++#if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC) && 
!defined(__CUDACC__) && !defined(__LCC__)
+ #    define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "GCC 
diagnostic push" )
+ #    define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION  _Pragma( "GCC 
diagnostic pop" )
+ 
+@@ -162,7 +161,7 @@ namespace Catch {
+ // ```
+ //
+ // Therefore, `CATCH_INTERNAL_IGNORE_BUT_WARN` is not implemented.
+-#  if !defined(__ibmxl__)
++#  if !defined(__ibmxl__) && !defined(__CUDACC__)
+ #    define CATCH_INTERNAL_IGNORE_BUT_WARN(...) 
(void)__builtin_constant_p(__VA_ARGS__) /* 
NOLINT(cppcoreguidelines-pro-type-vararg, hicpp-vararg) */
+ #  endif
+ 
+@@ -244,10 +243,6 @@ namespace Catch {
+ #  define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION __pragma( warning(push) )
+ #  define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION  __pragma( warning(pop) )
+ 
+-#  if _MSC_VER >= 1900 // Visual Studio 2015 or newer
+-#    define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
+-#  endif
+-
+ // Universal Windows platform does not support SEH
+ // Or console colours (or console at all...)
+ #  if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP)
+@@ -330,7 +325,10 @@ namespace Catch {
+ 
+   // Check if byte is available and usable
+   #  if __has_include(<cstddef>) && defined(CATCH_CPP17_OR_GREATER)
+-  #    define CATCH_INTERNAL_CONFIG_CPP17_BYTE
++  #    include <cstddef>
++  #    if defined(__cpp_lib_byte) && (__cpp_lib_byte > 0)
++  #      define CATCH_INTERNAL_CONFIG_CPP17_BYTE
++  #    endif
+   #  endif // __has_include(<cstddef>) && defined(CATCH_CPP17_OR_GREATER)
+ 
+   // Check if variant is available and usable
+@@ -373,10 +371,6 @@ namespace Catch {
+ #  define CATCH_CONFIG_CPP17_OPTIONAL
+ #endif
+ 
+-#if defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) && 
!defined(CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS) && 
!defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS)
+-#  define CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
+-#endif
+-
+ #if defined(CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW) && 
!defined(CATCH_CONFIG_NO_CPP17_STRING_VIEW) && 
!defined(CATCH_CONFIG_CPP17_STRING_VIEW)
+ #  define CATCH_CONFIG_CPP17_STRING_VIEW
+ #endif
+@@ -775,7 +769,7 @@ constexpr auto operator "" _catch_sr( char const* 
rawChars, std::size_t size ) n
+ #define INTERNAL_CATCH_REMOVE_PARENS_4_ARG(_0, _1, _2, _3) 
INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_3_ARG(_1, _2, _3)
+ #define INTERNAL_CATCH_REMOVE_PARENS_5_ARG(_0, _1, _2, _3, _4) 
INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_4_ARG(_1, _2, 
_3, _4)
+ #define INTERNAL_CATCH_REMOVE_PARENS_6_ARG(_0, _1, _2, _3, _4, _5) 
INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_5_ARG(_1, _2, 
_3, _4, _5)
+-#define INTERNAL_CATCH_REMOVE_PARENS_7_ARG(_0, _1, _2, _3, _4, _5, _6) 
INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_6_ARG(_1, _2, 
_4, _5, _6)
++#define INTERNAL_CATCH_REMOVE_PARENS_7_ARG(_0, _1, _2, _3, _4, _5, _6) 
INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_6_ARG(_1, _2, 
_3, _4, _5, _6)
+ #define INTERNAL_CATCH_REMOVE_PARENS_8_ARG(_0, _1, _2, _3, _4, _5, _6, _7) 
INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_7_ARG(_1, _2, 
_3, _4, _5, _6, _7)
+ #define INTERNAL_CATCH_REMOVE_PARENS_9_ARG(_0, _1, _2, _3, _4, _5, _6, _7, 
_8) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_8_ARG(_1, 
_2, _3, _4, _5, _6, _7, _8)
+ #define INTERNAL_CATCH_REMOVE_PARENS_10_ARG(_0, _1, _2, _3, _4, _5, _6, _7, 
_8, _9) INTERNAL_CATCH_REMOVE_PARENS(_0), 
INTERNAL_CATCH_REMOVE_PARENS_9_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9)
+@@ -1105,7 +1099,7 @@ struct AutoReg : NonCopyable {
+                     int index = 0;                                    \
+                     constexpr char const* tmpl_types[] = 
{CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, __VA_ARGS__)};\
+                     using expander = int[];\
+-                    (void)expander{(reg_test(Types{}, Catch::NameAndTags{ 
Name " - " + std::string(tmpl_types[index]), Tags } ), index++, 0)... };/* 
NOLINT */ \
++                    (void)expander{(reg_test(Types{}, Catch::NameAndTags{ 
Name " - " + std::string(tmpl_types[index]), Tags } ), index++)... };/* NOLINT 
*/ \
+                 }\
+             };\
+             static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
+@@ -1151,7 +1145,7 @@ struct AutoReg : NonCopyable {
+                     constexpr char const* tmpl_types[] = 
{CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, 
INTERNAL_CATCH_REMOVE_PARENS(TmplTypes))};\
+                     constexpr char const* types_list[] = 
{CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, 
INTERNAL_CATCH_REMOVE_PARENS(TypesList))};\
+                     constexpr auto num_types = sizeof(types_list) / 
sizeof(types_list[0]);\
+-                    (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( 
&TestFuncName<Types> ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), 
Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index / num_types]) + 
"<" + std::string(types_list[index % num_types]) + ">", Tags } ), index++, 
0)... };/* NOLINT */\
++                    (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( 
&TestFuncName<Types> ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), 
Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index / num_types]) + 
"<" + std::string(types_list[index % num_types]) + ">", Tags } ), index++)... 
};/* NOLINT */\
+                 }                                                     \
+             };                                                        \
+             static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \
+@@ -1195,7 +1189,7 @@ struct AutoReg : NonCopyable {
+             void reg_tests() {                                          \
+                 int index = 0;                                    \
+                 using expander = int[];                           \
+-                (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( 
&TestFunc<Types> ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), 
Catch::NameAndTags{ Name " - " + 
std::string(INTERNAL_CATCH_STRINGIZE(TmplList)) + " - " + 
std::to_string(index), Tags } ), index++, 0)... };/* NOLINT */\
++                (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( 
&TestFunc<Types> ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), 
Catch::NameAndTags{ Name " - " + 
std::string(INTERNAL_CATCH_STRINGIZE(TmplList)) + " - " + 
std::to_string(index), Tags } ), index++)... };/* NOLINT */\
+             }                                                     \
+         };\
+         static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \
+@@ -1229,7 +1223,7 @@ struct AutoReg : NonCopyable {
+                     int index = 0;                                    \
+                     constexpr char const* tmpl_types[] = 
{CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, __VA_ARGS__)};\
+                     using expander = int[];\
+-                    (void)expander{(reg_test(Types{}, #ClassName, 
Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index]), Tags } ), 
index++, 0)... };/* NOLINT */ \
++                    (void)expander{(reg_test(Types{}, #ClassName, 
Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index]), Tags } ), 
index++)... };/* NOLINT */ \
+                 }\
+             };\
+             static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
+@@ -1278,7 +1272,7 @@ struct AutoReg : NonCopyable {
+                     constexpr char const* tmpl_types[] = 
{CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, 
INTERNAL_CATCH_REMOVE_PARENS(TmplTypes))};\
+                     constexpr char const* types_list[] = 
{CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, 
INTERNAL_CATCH_REMOVE_PARENS(TypesList))};\
+                     constexpr auto num_types = sizeof(types_list) / 
sizeof(types_list[0]);\
+-                    (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( 
&TestName<Types>::test ), CATCH_INTERNAL_LINEINFO, #ClassName, 
Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index / num_types]) + 
"<" + std::string(types_list[index % num_types]) + ">", Tags } ), index++, 
0)... };/* NOLINT */ \
++                    (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( 
&TestName<Types>::test ), CATCH_INTERNAL_LINEINFO, #ClassName, 
Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index / num_types]) + 
"<" + std::string(types_list[index % num_types]) + ">", Tags } ), index++)... 
};/* NOLINT */ \
+                 }\
+             };\
+             static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
+@@ -1325,7 +1319,7 @@ struct AutoReg : NonCopyable {
+                 void reg_tests(){\
+                     int index = 0;\
+                     using expander = int[];\
+-                    (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( 
&TestName<Types>::test ), CATCH_INTERNAL_LINEINFO, #ClassName, 
Catch::NameAndTags{ Name " - " + 
std::string(INTERNAL_CATCH_STRINGIZE(TmplList)) + " - " + 
std::to_string(index), Tags } ), index++, 0)... };/* NOLINT */ \
++                    (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( 
&TestName<Types>::test ), CATCH_INTERNAL_LINEINFO, #ClassName, 
Catch::NameAndTags{ Name " - " + 
std::string(INTERNAL_CATCH_STRINGIZE(TmplList)) + " - " + 
std::to_string(index), Tags } ), index++)... };/* NOLINT */ \
+                 }\
+             };\
+             static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
+@@ -1829,8 +1823,8 @@ namespace Catch {
+ #endif
+ 
+     namespace Detail {
+-        template<typename InputIterator>
+-        std::string rangeToString(InputIterator first, InputIterator last) {
++        template<typename InputIterator, typename Sentinel = InputIterator>
++        std::string rangeToString(InputIterator first, Sentinel last) {
+             ReusableStringStream rss;
+             rss << "{ ";
+             if (first != last) {
+@@ -2468,7 +2462,7 @@ namespace Catch {
+         virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0;
+         virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) = 0;
+ 
+-        virtual auto acquireGeneratorTracker( SourceLineInfo const& lineInfo 
) -> IGeneratorTracker& = 0;
++        virtual auto acquireGeneratorTracker( StringRef generatorName, 
SourceLineInfo const& lineInfo ) -> IGeneratorTracker& = 0;
+ 
+ #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
+         virtual void benchmarkPreparing( std::string const& name ) = 0;
+@@ -4080,16 +4074,16 @@ namespace Generators {
+         return makeGenerators( value( T( std::forward<U>( val ) ) ), 
std::forward<Gs>( moreGenerators )... );
+     }
+ 
+-    auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> 
IGeneratorTracker&;
++    auto acquireGeneratorTracker( StringRef generatorName, SourceLineInfo 
const& lineInfo ) -> IGeneratorTracker&;
+ 
+     template<typename L>
+     // Note: The type after -> is weird, because VS2015 cannot parse
+     //       the expression used in the typedef inside, when it is in
+     //       return type. Yeah.
+-    auto generate( SourceLineInfo const& lineInfo, L const& 
generatorExpression ) -> 
decltype(std::declval<decltype(generatorExpression())>().get()) {
++    auto generate( StringRef generatorName, SourceLineInfo const& lineInfo, L 
const& generatorExpression ) -> 
decltype(std::declval<decltype(generatorExpression())>().get()) {
+         using UnderlyingType = typename decltype(generatorExpression())::type;
+ 
+-        IGeneratorTracker& tracker = acquireGeneratorTracker( lineInfo );
++        IGeneratorTracker& tracker = acquireGeneratorTracker( generatorName, 
lineInfo );
+         if (!tracker.hasGenerator()) {
+             
tracker.setGenerator(pf::make_unique<Generators<UnderlyingType>>(generatorExpression()));
+         }
+@@ -4102,11 +4096,17 @@ namespace Generators {
+ } // namespace Catch
+ 
+ #define GENERATE( ... ) \
+-    Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [ ]{ using 
namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) 
//NOLINT(google-build-using-namespace)
++    Catch::Generators::generate( 
INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \
++                                 CATCH_INTERNAL_LINEINFO, \
++                                 [ ]{ using namespace Catch::Generators; 
return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace)
+ #define GENERATE_COPY( ... ) \
+-    Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [=]{ using 
namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) 
//NOLINT(google-build-using-namespace)
++    Catch::Generators::generate( 
INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \
++                                 CATCH_INTERNAL_LINEINFO, \
++                                 [=]{ using namespace Catch::Generators; 
return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace)
+ #define GENERATE_REF( ... ) \
+-    Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [&]{ using 
namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) 
//NOLINT(google-build-using-namespace)
++    Catch::Generators::generate( 
INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \
++                                 CATCH_INTERNAL_LINEINFO, \
++                                 [&]{ using namespace Catch::Generators; 
return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace)
+ 
+ // end catch_generators.hpp
+ // start catch_generators_generic.hpp
+@@ -4516,6 +4516,7 @@ namespace Catch {
+         virtual int abortAfter() const = 0;
+         virtual bool showInvisibles() const = 0;
+         virtual ShowDurations::OrNot showDurations() const = 0;
++        virtual double minDuration() const = 0;
+         virtual TestSpec const& testSpec() const = 0;
+         virtual bool hasTestFilters() const = 0;
+         virtual std::vector<std::string> const& getTestsOrTags() const = 0;
+@@ -5288,6 +5289,7 @@ namespace Catch {
+         Verbosity verbosity = Verbosity::Normal;
+         WarnAbout::What warnings = WarnAbout::Nothing;
+         ShowDurations::OrNot showDurations = 
ShowDurations::DefaultForReporter;
++        double minDuration = -1;
+         RunTests::InWhatOrder runOrder = RunTests::InDeclarationOrder;
+         UseColour::YesOrNo useColour = UseColour::Auto;
+         WaitForKeypress::When waitForKeypress = WaitForKeypress::Never;
+@@ -5338,6 +5340,7 @@ namespace Catch {
+         bool warnAboutMissingAssertions() const override;
+         bool warnAboutNoTests() const override;
+         ShowDurations::OrNot showDurations() const override;
++        double minDuration() const override;
+         RunTests::InWhatOrder runOrder() const override;
+         unsigned int rngSeed() const override;
+         UseColour::YesOrNo useColour() const override;
+@@ -5455,6 +5458,8 @@ namespace Catch {
+ } // namespace Catch
+ 
+ // end catch_outlier_classification.hpp
++
++#include <iterator>
+ #endif // CATCH_CONFIG_ENABLE_BENCHMARKING
+ 
+ #include <string>
+@@ -5715,6 +5720,9 @@ namespace Catch {
+     // Returns double formatted as %.3f (format expected on output)
+     std::string getFormattedDuration( double duration );
+ 
++    //! Should the reporter show
++    bool shouldShowDuration( IConfig const& config, double duration );
++
+     std::string serializeFilters( std::vector<std::string> const& container );
+ 
+     template<typename DerivedT>
+@@ -6108,8 +6116,6 @@ namespace Catch {
+ 
+         static std::string getDescription();
+ 
+-        ReporterPreferences getPreferences() const override;
+-
+         void noMatchingTestCases(std::string const& spec) override;
+ 
+         void assertionStarting(AssertionInfo const&) override;
+@@ -6338,9 +6344,10 @@ namespace Catch {
+ 
+         void writeTestCase(TestCaseNode const& testCaseNode);
+ 
+-        void writeSection(std::string const& className,
+-                          std::string const& rootName,
+-                          SectionNode const& sectionNode);
++        void writeSection( std::string const& className,
++                           std::string const& rootName,
++                           SectionNode const& sectionNode,
++                           bool testOkToFail );
+ 
+         void writeAssertions(SectionNode const& sectionNode);
+         void writeAssertion(AssertionStats const& stats);
+@@ -6875,7 +6882,7 @@ namespace Catch {
+                     }
+                     iters *= 2;
+                 }
+-                throw optimized_away_error{};
++                Catch::throw_exception(optimized_away_error{});
+             }
+         } // namespace Detail
+     } // namespace Benchmark
+@@ -6883,6 +6890,7 @@ namespace Catch {
+ 
+ // end catch_run_for_at_least.hpp
+ #include <algorithm>
++#include <iterator>
+ 
+ namespace Catch {
+     namespace Benchmark {
+@@ -7053,8 +7061,8 @@ namespace Catch {
+                 double b2 = bias - z1;
+                 double a1 = a(b1);
+                 double a2 = a(b2);
+-                auto lo = std::max(cumn(a1), 0);
+-                auto hi = std::min(cumn(a2), n - 1);
++                auto lo = (std::max)(cumn(a1), 0);
++                auto hi = (std::min)(cumn(a2), n - 1);
+ 
+                 return { point, resample[lo], resample[hi], confidence_level 
};
+             }
+@@ -7123,7 +7131,9 @@ namespace Catch {
+             }
+             template <typename Clock>
+             EnvironmentEstimate<FloatDuration<Clock>> 
estimate_clock_cost(FloatDuration<Clock> resolution) {
+-                auto time_limit = std::min(resolution * 
clock_cost_estimation_tick_limit, 
FloatDuration<Clock>(clock_cost_estimation_time_limit));
++                auto time_limit = (std::min)(
++                    resolution * clock_cost_estimation_tick_limit,
++                    FloatDuration<Clock>(clock_cost_estimation_time_limit));
+                 auto time_clock = [](int k) {
+                     return Detail::measure<Clock>([k] {
+                         for (int i = 0; i < k; ++i) {
+@@ -7463,23 +7473,37 @@ namespace TestCaseTracking {
+         SourceLineInfo location;
+ 
+         NameAndLocation( std::string const& _name, SourceLineInfo const& 
_location );
++        friend bool operator==(NameAndLocation const& lhs, NameAndLocation 
const& rhs) {
++            return lhs.name == rhs.name
++                && lhs.location == rhs.location;
++        }
+     };
+ 
+-    struct ITracker;
++    class ITracker;
+ 
+     using ITrackerPtr = std::shared_ptr<ITracker>;
+ 
+-    struct ITracker {
+-        virtual ~ITracker();
++    class  ITracker {
++        NameAndLocation m_nameAndLocation;
++
++    public:
++        ITracker(NameAndLocation const& nameAndLoc) :
++            m_nameAndLocation(nameAndLoc)
++        {}
+ 
+         // static queries
+-        virtual NameAndLocation const& nameAndLocation() const = 0;
++        NameAndLocation const& nameAndLocation() const {
++            return m_nameAndLocation;
++        }
++
++        virtual ~ITracker();
+ 
+         // dynamic queries
+         virtual bool isComplete() const = 0; // Successfully completed or 
failed
+         virtual bool isSuccessfullyCompleted() const = 0;
+         virtual bool isOpen() const = 0; // Started but not complete
+         virtual bool hasChildren() const = 0;
++        virtual bool hasStarted() const = 0;
+ 
+         virtual ITracker& parent() = 0;
+ 
+@@ -7534,7 +7558,6 @@ namespace TestCaseTracking {
+         };
+ 
+         using Children = std::vector<ITrackerPtr>;
+-        NameAndLocation m_nameAndLocation;
+         TrackerContext& m_ctx;
+         ITracker* m_parent;
+         Children m_children;
+@@ -7543,11 +7566,13 @@ namespace TestCaseTracking {
+     public:
+         TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& 
ctx, ITracker* parent );
+ 
+-        NameAndLocation const& nameAndLocation() const override;
+         bool isComplete() const override;
+         bool isSuccessfullyCompleted() const override;
+         bool isOpen() const override;
+         bool hasChildren() const override;
++        bool hasStarted() const override {
++            return m_runState != NotStarted;
++        }
+ 
+         void addChild( ITrackerPtr const& child ) override;
+ 
+@@ -7586,6 +7611,10 @@ namespace TestCaseTracking {
+ 
+         void addInitialFilters( std::vector<std::string> const& filters );
+         void addNextFilters( std::vector<std::string> const& filters );
++        //! Returns filters active in this tracker
++        std::vector<std::string> const& getFilters() const;
++        //! Returns whitespace-trimmed name of the tracked section
++        std::string const& trimmedName() const;
+     };
+ 
+ } // namespace TestCaseTracking
+@@ -7751,7 +7780,7 @@ namespace Catch {
+                 double sb = stddev.point;
+                 double mn = mean.point / n;
+                 double mg_min = mn / 2.;
+-                double sg = std::min(mg_min / 4., sb / std::sqrt(n));
++                double sg = (std::min)(mg_min / 4., sb / std::sqrt(n));
+                 double sg2 = sg * sg;
+                 double sb2 = sb * sb;
+ 
+@@ -7770,7 +7799,7 @@ namespace Catch {
+                     return (nc / n) * (sb2 - nc * sg2);
+                 };
+ 
+-                return std::min(var_out(1), var_out(std::min(c_max(0.), 
c_max(mg_min)))) / sb2;
++                return (std::min)(var_out(1), var_out((std::min)(c_max(0.), 
c_max(mg_min)))) / sb2;
+             }
+ 
+             bootstrap_analysis analyse_samples(double confidence_level, int 
n_resamples, std::vector<double>::iterator first, std::vector<double>::iterator 
last) {
+@@ -7910,7 +7939,11 @@ namespace Catch {
+ 
+ #ifdef CATCH_PLATFORM_MAC
+ 
+-    #define CATCH_TRAP() __asm__("int $3\n" : : ) /* NOLINT */
++    #if defined(__i386__) || defined(__x86_64__)
++        #define CATCH_TRAP() __asm__("int $3\n" : : ) /* NOLINT */
++    #elif defined(__aarch64__)
++        #define CATCH_TRAP()  __asm__(".inst 0xd4200000")
++    #endif
+ 
+ #elif defined(CATCH_PLATFORM_IPHONE)
+ 
+@@ -7956,86 +7989,58 @@ namespace Catch {
+ 
+ // start catch_fatal_condition.h
+ 
+-// start catch_windows_h_proxy.h
+-
+-
+-#if defined(CATCH_PLATFORM_WINDOWS)
+-
+-#if !defined(NOMINMAX) && !defined(CATCH_CONFIG_NO_NOMINMAX)
+-#  define CATCH_DEFINED_NOMINMAX
+-#  define NOMINMAX
+-#endif
+-#if !defined(WIN32_LEAN_AND_MEAN) && 
!defined(CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN)
+-#  define CATCH_DEFINED_WIN32_LEAN_AND_MEAN
+-#  define WIN32_LEAN_AND_MEAN
+-#endif
+-
+-#ifdef __AFXDLL
+-#include <AfxWin.h>
+-#else
+-#include <windows.h>
+-#endif
+-
+-#ifdef CATCH_DEFINED_NOMINMAX
+-#  undef NOMINMAX
+-#endif
+-#ifdef CATCH_DEFINED_WIN32_LEAN_AND_MEAN
+-#  undef WIN32_LEAN_AND_MEAN
+-#endif
+-
+-#endif // defined(CATCH_PLATFORM_WINDOWS)
+-
+-// end catch_windows_h_proxy.h
+-#if defined( CATCH_CONFIG_WINDOWS_SEH )
++#include <cassert>
+ 
+ namespace Catch {
+ 
+-    struct FatalConditionHandler {
+-
+-        static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS 
ExceptionInfo);
++    // Wrapper for platform-specific fatal error (signals/SEH) handlers
++    //
++    // Tries to be cooperative with other handlers, and not step over
++    // other handlers. This means that unknown structured exceptions
++    // are passed on, previous signal handlers are called, and so on.
++    //
++    // Can only be instantiated once, and assumes that once a signal
++    // is caught, the binary will end up terminating. Thus, there
++    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();
+-        static void reset();
+         ~FatalConditionHandler();
+ 
+-    private:
+-        static bool isSet;
+-        static ULONG guaranteeSize;
+-        static PVOID exceptionHandlerHandle;
+-    };
+-
+-} // namespace Catch
+-
+-#elif defined ( CATCH_CONFIG_POSIX_SIGNALS )
+-
+-#include <signal.h>
+-
+-namespace Catch {
+-
+-    struct FatalConditionHandler {
+-
+-        static bool isSet;
+-        static struct sigaction oldSigActions[];
+-        static stack_t oldSigStack;
+-        static char altStackMem[];
+-
+-        static void handleSignal( int sig );
++        void engage() {
++            assert(!m_started && "Handler cannot be installed twice.");
++            m_started = true;
++            engage_platform();
++        }
+ 
+-        FatalConditionHandler();
+-        ~FatalConditionHandler();
+-        static void reset();
++        void disengage() {
++            assert(m_started && "Handler cannot be uninstalled without being 
installed first");
++            m_started = false;
++            disengage_platform();
++        }
+     };
+ 
+-} // namespace Catch
+-
+-#else
+-
+-namespace Catch {
+-    struct FatalConditionHandler {
+-        void reset();
++    //! 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();
++        }
+     };
+-}
+ 
+-#endif
++} // end namespace Catch
+ 
+ // end catch_fatal_condition.h
+ #include <string>
+@@ -8095,7 +8100,7 @@ namespace Catch {
+         void sectionEnded( SectionEndInfo const& endInfo ) override;
+         void sectionEndedEarly( SectionEndInfo const& endInfo ) override;
+ 
+-        auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> 
IGeneratorTracker& override;
++        auto acquireGeneratorTracker( StringRef generatorName, SourceLineInfo 
const& lineInfo ) -> IGeneratorTracker& override;
+ 
+ #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
+         void benchmarkPreparing( std::string const& name ) override;
+@@ -8161,6 +8166,7 @@ namespace Catch {
+         std::vector<SectionEndInfo> m_unfinishedSections;
+         std::vector<ITracker*> m_activeSections;
+         TrackerContext m_trackerContext;
++        FatalConditionHandler m_fatalConditionhandler;
+         bool m_lastAssertionPassed = false;
+         bool m_shouldReportUnexpected = true;
+         bool m_includeSuccessfulResults;
+@@ -9071,7 +9077,7 @@ namespace detail {
+     }
+     inline auto convertInto( std::string const &source, bool &target ) -> 
ParserResult {
+         std::string srcLC = source;
+-        std::transform( srcLC.begin(), srcLC.end(), srcLC.begin(), []( char c 
) { return static_cast<char>( std::tolower(c) ); } );
++        std::transform( srcLC.begin(), srcLC.end(), srcLC.begin(), []( 
unsigned char c ) { return static_cast<char>( std::tolower(c) ); } );
+         if (srcLC == "y" || srcLC == "1" || srcLC == "true" || srcLC == "yes" 
|| srcLC == "on")
+             target = true;
+         else if (srcLC == "n" || srcLC == "0" || srcLC == "false" || srcLC == 
"no" || srcLC == "off")
+@@ -9840,6 +9846,9 @@ namespace Catch {
+             | Opt( [&]( bool flag ) { config.showDurations = flag ? 
ShowDurations::Always : ShowDurations::Never; }, "yes|no" )
+                 ["-d"]["--durations"]
+                 ( "show test durations" )
++            | Opt( config.minDuration, "seconds" )
++                ["-D"]["--min-duration"]
++                ( "show test durations for tests taking at least the given 
number of seconds" )
+             | Opt( loadTestNamesFromFile, "filename" )
+                 ["-f"]["--input-file"]
+                 ( "load test names to run from a file" )
+@@ -9987,6 +9996,7 @@ namespace Catch {
+     bool Config::warnAboutMissingAssertions() const    { return 
!!(m_data.warnings & WarnAbout::NoAssertions); }
+     bool Config::warnAboutNoTests() const              { return 
!!(m_data.warnings & WarnAbout::NoTests); }
+     ShowDurations::OrNot Config::showDurations() const { return 
m_data.showDurations; }
++    double Config::minDuration() const                 { return 
m_data.minDuration; }
+     RunTests::InWhatOrder Config::runOrder() const     { return 
m_data.runOrder; }
+     unsigned int Config::rngSeed() const               { return 
m_data.rngSeed; }
+     UseColour::YesOrNo Config::useColour() const       { return 
m_data.useColour; }
+@@ -10029,6 +10039,36 @@ namespace Catch {
+ }
+ 
+ // end catch_errno_guard.h
++// start catch_windows_h_proxy.h
++
++
++#if defined(CATCH_PLATFORM_WINDOWS)
++
++#if !defined(NOMINMAX) && !defined(CATCH_CONFIG_NO_NOMINMAX)
++#  define CATCH_DEFINED_NOMINMAX
++#  define NOMINMAX
++#endif
++#if !defined(WIN32_LEAN_AND_MEAN) && 
!defined(CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN)
++#  define CATCH_DEFINED_WIN32_LEAN_AND_MEAN
++#  define WIN32_LEAN_AND_MEAN
++#endif
++
++#ifdef __AFXDLL
++#include <AfxWin.h>
++#else
++#include <windows.h>
++#endif
++
++#ifdef CATCH_DEFINED_NOMINMAX
++#  undef NOMINMAX
++#endif
++#ifdef CATCH_DEFINED_WIN32_LEAN_AND_MEAN
++#  undef WIN32_LEAN_AND_MEAN
++#endif
++
++#endif // defined(CATCH_PLATFORM_WINDOWS)
++
++// end catch_windows_h_proxy.h
+ #include <sstream>
+ 
+ namespace Catch {
+@@ -10545,7 +10585,7 @@ namespace Catch {
+             // Extracts the actual name part of an enum instance
+             // In other words, it returns the Blue part of 
Bikeshed::Colour::Blue
+             StringRef extractInstanceName(StringRef enumInstance) {
+-                // Find last occurence of ":"
++                // Find last occurrence of ":"
+                 size_t name_start = enumInstance.size();
+                 while (name_start > 0 && enumInstance[name_start - 1] != ':') 
{
+                     --name_start;
+@@ -10707,25 +10747,47 @@ namespace Catch {
+ // end catch_exception_translator_registry.cpp
+ // start catch_fatal_condition.cpp
+ 
+-#if defined(__GNUC__)
+-#    pragma GCC diagnostic push
+-#    pragma GCC diagnostic ignored "-Wmissing-field-initializers"
+-#endif
++#include <algorithm>
++
++#if !defined( CATCH_CONFIG_WINDOWS_SEH ) && !defined( 
CATCH_CONFIG_POSIX_SIGNALS )
++
++namespace Catch {
++
++    // If neither SEH nor signal handling is required, the handler impls
++    // do not have to do anything, and can be empty.
++    void FatalConditionHandler::engage_platform() {}
++    void FatalConditionHandler::disengage_platform() {}
++    FatalConditionHandler::FatalConditionHandler() = default;
++    FatalConditionHandler::~FatalConditionHandler() = default;
++
++} // end namespace Catch
++
++#endif // !CATCH_CONFIG_WINDOWS_SEH && !CATCH_CONFIG_POSIX_SIGNALS
++
++#if defined( CATCH_CONFIG_WINDOWS_SEH ) && defined( 
CATCH_CONFIG_POSIX_SIGNALS )
++#error "Inconsistent configuration: Windows' SEH handling and POSIX signals 
cannot be enabled at the same time"
++#endif // CATCH_CONFIG_WINDOWS_SEH && CATCH_CONFIG_POSIX_SIGNALS
+ 
+ #if defined( CATCH_CONFIG_WINDOWS_SEH ) || defined( 
CATCH_CONFIG_POSIX_SIGNALS )
+ 
+ namespace {
+-    // Report the error condition
++    //! Signals fatal error message to the run context
+     void reportFatal( char const * const message ) {
+         
Catch::getCurrentContext().getResultCapture()->handleFatalErrorCondition( 
message );
+     }
+-}
+ 
+-#endif // signals/SEH handling
++    //! Minimal size Catch2 needs for its own fatal error handling.
++    //! Picked anecdotally, so it might not be sufficient on all
++    //! platforms, and for all configurations.
++    constexpr std::size_t minStackSizeForErrors = 32 * 1024;
++} // end unnamed namespace
++
++#endif // CATCH_CONFIG_WINDOWS_SEH || CATCH_CONFIG_POSIX_SIGNALS
+ 
+ #if defined( CATCH_CONFIG_WINDOWS_SEH )
+ 
+ namespace Catch {
++
+     struct SignalDefs { DWORD id; const char* name; };
+ 
+     // There is no 1-1 mapping between signals and windows exceptions.
+@@ -10738,7 +10800,7 @@ namespace Catch {
+         { static_cast<DWORD>(EXCEPTION_INT_DIVIDE_BY_ZERO), "Divide by zero 
error" },
+     };
+ 
+-    LONG CALLBACK 
FatalConditionHandler::handleVectoredException(PEXCEPTION_POINTERS 
ExceptionInfo) {
++    static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS 
ExceptionInfo) {
+         for (auto const& def : signalDefs) {
+             if (ExceptionInfo->ExceptionRecord->ExceptionCode == def.id) {
+                 reportFatal(def.name);
+@@ -10749,38 +10811,50 @@ namespace Catch {
+         return EXCEPTION_CONTINUE_SEARCH;
+     }
+ 
++    // 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 = nullptr;
++
++    // For MSVC, we reserve part of the stack memory for handling
++    // memory overflow structured exception.
+     FatalConditionHandler::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 = nullptr;
++        ULONG guaranteeSize = static_cast<ULONG>(minStackSizeForErrors);
++        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.";
++        }
++    }
++
++    // We do not attempt to unset the stack guarantee, because
++    // Windows does not support lowering the stack size guarantee.
++    FatalConditionHandler::~FatalConditionHandler() = default;
++
++    void FatalConditionHandler::engage_platform() {
+         // Register as first handler in current chain
+         exceptionHandlerHandle = AddVectoredExceptionHandler(1, 
handleVectoredException);
+-        // Pass in guarantee size to be filled
+-        SetThreadStackGuarantee(&guaranteeSize);
++        if (!exceptionHandlerHandle) {
++            CATCH_RUNTIME_ERROR("Could not register vectored exception 
handler");
++        }
+     }
+ 
+-    void FatalConditionHandler::reset() {
+-        if (isSet) {
+-            RemoveVectoredExceptionHandler(exceptionHandlerHandle);
+-            SetThreadStackGuarantee(&guaranteeSize);
+-            exceptionHandlerHandle = nullptr;
+-            isSet = false;
++    void FatalConditionHandler::disengage_platform() {
++        if (!RemoveVectoredExceptionHandler(exceptionHandlerHandle)) {
++            CATCH_RUNTIME_ERROR("Could not unregister vectored exception 
handler");
+         }
++        exceptionHandlerHandle = nullptr;
+     }
+ 
+-    FatalConditionHandler::~FatalConditionHandler() {
+-        reset();
+-    }
++} // end namespace Catch
+ 
+-bool FatalConditionHandler::isSet = false;
+-ULONG FatalConditionHandler::guaranteeSize = 0;
+-PVOID FatalConditionHandler::exceptionHandlerHandle = nullptr;
++#endif // CATCH_CONFIG_WINDOWS_SEH
+ 
+-} // namespace Catch
++#if defined( CATCH_CONFIG_POSIX_SIGNALS )
+ 
+-#elif defined( CATCH_CONFIG_POSIX_SIGNALS )
++#include <signal.h>
+ 
+ namespace Catch {
+ 
+@@ -10789,10 +10863,6 @@ namespace Catch {
+         const char* name;
+     };
+ 
+-    // 32kb for the alternate stack seems to be sufficient. However, this 
value
+-    // is experimentally determined, so that's not guaranteed.
+-    static constexpr std::size_t sigStackSize = 32768 >= MINSIGSTKSZ ? 32768 
: MINSIGSTKSZ;
+-
+     static SignalDefs signalDefs[] = {
+         { SIGINT,  "SIGINT - Terminal interrupt signal" },
+         { SIGILL,  "SIGILL - Illegal instruction signal" },
+@@ -10802,7 +10872,32 @@ namespace Catch {
+         { SIGABRT, "SIGABRT - Abort (abnormal termination) signal" }
+     };
+ 
+-    void FatalConditionHandler::handleSignal( int sig ) {
++// 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 char* altStackMem = nullptr;
++    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], nullptr);
++        }
++        // Return the old stack
++        sigaltstack(&oldSigStack, nullptr);
++    }
++
++    static void handleSignal( int sig ) {
+         char const * name = "<unknown signal>";
+         for (auto const& def : signalDefs) {
+             if (sig == def.id) {
+@@ -10810,16 +10905,33 @@ namespace Catch {
+                 break;
+             }
+         }
+-        reset();
+-        reportFatal(name);
++        // 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::FatalConditionHandler() {
+-        isSet = true;
++        assert(!altStackMem && "Cannot initialize POSIX signal handler when 
one already exists");
++        if (altStackSize == 0) {
++            altStackSize = std::max(static_cast<size_t>(SIGSTKSZ), 
minStackSizeForErrors);
++        }
++        altStackMem = new char[altStackSize]();
++    }
++
++    FatalConditionHandler::~FatalConditionHandler() {
++        delete[] altStackMem;
++        // We signal that another instance can be constructed by zeroing
++        // out the pointer.
++        altStackMem = nullptr;
++    }
++
++    void FatalConditionHandler::engage_platform() {
+         stack_t sigStack;
+         sigStack.ss_sp = altStackMem;
+-        sigStack.ss_size = sigStackSize;
++        sigStack.ss_size = altStackSize;
+         sigStack.ss_flags = 0;
+         sigaltstack(&sigStack, &oldSigStack);
+         struct sigaction sa = { };
+@@ -10831,40 +10943,17 @@ namespace Catch {
+         }
+     }
+ 
+-    FatalConditionHandler::~FatalConditionHandler() {
+-        reset();
+-    }
++#if defined(__GNUC__)
++#    pragma GCC diagnostic pop
++#endif
+ 
+-    void FatalConditionHandler::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], nullptr);
+-            }
+-            // Return the old stack
+-            sigaltstack(&oldSigStack, nullptr);
+-            isSet = false;
+-        }
++    void FatalConditionHandler::disengage_platform() {
++        restorePreviousSignalHandlers();
+     }
+ 
+-    bool FatalConditionHandler::isSet = false;
+-    struct sigaction 
FatalConditionHandler::oldSigActions[sizeof(signalDefs)/sizeof(SignalDefs)] = 
{};
+-    stack_t FatalConditionHandler::oldSigStack = {};
+-    char FatalConditionHandler::altStackMem[sigStackSize] = {};
+-
+-} // namespace Catch
+-
+-#else
+-
+-namespace Catch {
+-    void FatalConditionHandler::reset() {}
+-}
+-
+-#endif // signals/SEH handling
++} // end namespace Catch
+ 
+-#if defined(__GNUC__)
+-#    pragma GCC diagnostic pop
+-#endif
++#endif // CATCH_CONFIG_POSIX_SIGNALS
+ // end catch_fatal_condition.cpp
+ // start catch_generators.cpp
+ 
+@@ -10883,8 +10972,8 @@ namespace Generators {
+ 
+     GeneratorUntypedBase::~GeneratorUntypedBase() {}
+ 
+-    auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> 
IGeneratorTracker& {
+-        return getResultCapture().acquireGeneratorTracker( lineInfo );
++    auto acquireGeneratorTracker( StringRef generatorName, SourceLineInfo 
const& lineInfo ) -> IGeneratorTracker& {
++        return getResultCapture().acquireGeneratorTracker( generatorName, 
lineInfo );
+     }
+ 
+ } // namespace Generators
+@@ -11419,7 +11508,8 @@ namespace {
+             return lhs == rhs;
+         }
+ 
+-        auto ulpDiff = std::abs(lc - rc);
++        // static cast as a workaround for IBM XLC
++        auto ulpDiff = std::abs(static_cast<FP>(lc - rc));
+         return static_cast<uint64_t>(ulpDiff) <= maxUlpDiff;
+     }
+ 
+@@ -11593,7 +11683,6 @@ Floating::WithinRelMatcher WithinRel(float target) {
+ 
+ } // namespace Matchers
+ } // namespace Catch
+-
+ // end catch_matchers_floating.cpp
+ // start catch_matchers_generic.cpp
+ 
+@@ -12009,7 +12098,7 @@ namespace Catch {
+         if (tmpnam_s(m_buffer)) {
+             CATCH_RUNTIME_ERROR("Could not get a temp filename");
+         }
+-        if (fopen_s(&m_file, m_buffer, "w")) {
++        if (fopen_s(&m_file, m_buffer, "w+")) {
+             char buffer[100];
+             if (strerror_s(buffer, errno)) {
+                 CATCH_RUNTIME_ERROR("Could not translate errno to a string");
+@@ -12304,11 +12393,13 @@ namespace Catch {
+ namespace Catch {
+ 
+     class StartupExceptionRegistry {
++#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
+     public:
+         void add(std::exception_ptr const& exception) noexcept;
+         std::vector<std::exception_ptr> const& getExceptions() const noexcept;
+     private:
+         std::vector<std::exception_ptr> m_exceptions;
++#endif
+     };
+ 
+ } // end namespace Catch
+@@ -12391,7 +12482,11 @@ namespace Catch {
+                 m_tagAliasRegistry.add( alias, tag, lineInfo );
+             }
+             void registerStartupException() noexcept override {
++#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
+                 m_exceptionRegistry.add(std::current_exception());
++#else
++                CATCH_INTERNAL_ERROR("Attempted to register active exception 
under CATCH_CONFIG_DISABLE_EXCEPTIONS!");
++#endif
+             }
+             IMutableEnumValuesRegistry& getMutableEnumValuesRegistry() 
override {
+                 return m_enumValuesRegistry;
+@@ -12495,17 +12590,32 @@ namespace Catch {
+                 std::shared_ptr<GeneratorTracker> tracker;
+ 
+                 ITracker& currentTracker = ctx.currentTracker();
+-                if( TestCaseTracking::ITrackerPtr childTracker = 
currentTracker.findChild( nameAndLocation ) ) {
++                // Under specific circumstances, the generator we want
++                // to acquire is also the current tracker. If this is
++                // the case, we have to avoid looking through current
++                // tracker's children, and instead return the current
++                // tracker.
++                // A case where this check is important is e.g.
++                //     for (int i = 0; i < 5; ++i) {
++                //         int n = GENERATE(1, 2);
++                //     }
++                //
++                // without it, the code above creates 5 nested generators.
++                if (currentTracker.nameAndLocation() == nameAndLocation) {
++                    auto thisTracker = 
currentTracker.parent().findChild(nameAndLocation);
++                    assert(thisTracker);
++                    assert(thisTracker->isGeneratorTracker());
++                    tracker = 
std::static_pointer_cast<GeneratorTracker>(thisTracker);
++                } else if ( TestCaseTracking::ITrackerPtr childTracker = 
currentTracker.findChild( nameAndLocation ) ) {
+                     assert( childTracker );
+                     assert( childTracker->isGeneratorTracker() );
+                     tracker = std::static_pointer_cast<GeneratorTracker>( 
childTracker );
+-                }
+-                else {
++                } else {
+                     tracker = std::make_shared<GeneratorTracker>( 
nameAndLocation, ctx, &currentTracker );
+                     currentTracker.addChild( tracker );
+                 }
+ 
+-                if( !ctx.completedCycle() && !tracker->isComplete() ) {
++                if( !tracker->isComplete() ) {
+                     tracker->open();
+                 }
+ 
+@@ -12519,8 +12629,68 @@ namespace Catch {
+             }
+             void close() override {
+                 TrackerBase::close();
+-                // Generator interface only finds out if it has another item 
on atual move
+-                if (m_runState == CompletedSuccessfully && 
m_generator->next()) {
++                // If a generator has a child (it is followed by a section)
++                // and none of its children have started, then we must wait
++                // until later to start consuming its values.
++                // This catches cases where `GENERATE` is placed between two
++                // `SECTION`s.
++                // **The check for m_children.empty cannot be removed**.
++                // doing so would break `GENERATE` _not_ followed by 
`SECTION`s.
++                const bool should_wait_for_child = [&]() {
++                    // No children -> nobody to wait for
++                    if ( m_children.empty() ) {
++                        return false;
++                    }
++                    // If at least one child started executing, don't wait
++                    if ( std::find_if(
++                             m_children.begin(),
++                             m_children.end(),
++                             []( TestCaseTracking::ITrackerPtr tracker ) {
++                                 return tracker->hasStarted();
++                             } ) != m_children.end() ) {
++                        return false;
++                    }
++
++                    // No children have started. We need to check if they 
_can_
++                    // start, and thus we should wait for them, or they cannot
++                    // start (due to filters), and we shouldn't wait for them
++                    auto* parent = m_parent;
++                    // This is safe: there is always at least one section
++                    // tracker in a test case tracking tree
++                    while ( !parent->isSectionTracker() ) {
++                        parent = &( parent->parent() );
++                    }
++                    assert( parent &&
++                            "Missing root (test case) level section" );
++
++                    auto const& parentSection =
++                        static_cast<SectionTracker&>( *parent );
++                    auto const& filters = parentSection.getFilters();
++                    // No filters -> no restrictions on running sections
++                    if ( filters.empty() ) {
++                        return true;
++                    }
++
++                    for ( auto const& child : m_children ) {
++                        if ( child->isSectionTracker() &&
++                             std::find( filters.begin(),
++                                        filters.end(),
++                                        static_cast<SectionTracker&>( *child )
++                                            .trimmedName() ) !=
++                                 filters.end() ) {
++                            return true;
++                        }
++                    }
++                    return false;
++                }();
++
++                // This check is a bit tricky, because m_generator->next()
++                // has a side-effect, where it consumes generator's current
++                // value, but we do not want to invoke the side-effect if
++                // this generator is still waiting for any child to start.
++                if ( should_wait_for_child ||
++                     ( m_runState == CompletedSuccessfully &&
++                       m_generator->next() ) ) {
+                     m_children.clear();
+                     m_runState = Executing;
+                 }
+@@ -12656,10 +12826,10 @@ namespace Catch {
+ 
+         return true;
+     }
+-    auto RunContext::acquireGeneratorTracker( SourceLineInfo const& lineInfo 
) -> IGeneratorTracker& {
++    auto RunContext::acquireGeneratorTracker( StringRef generatorName, 
SourceLineInfo const& lineInfo ) -> IGeneratorTracker& {
+         using namespace Generators;
+-        GeneratorTracker& tracker = GeneratorTracker::acquire( 
m_trackerContext, TestCaseTracking::NameAndLocation( "generator", lineInfo ) );
+-        assert( tracker.isOpen() );
++        GeneratorTracker& tracker = 
GeneratorTracker::acquire(m_trackerContext,
++                                                              
TestCaseTracking::NameAndLocation( static_cast<std::string>(generatorName), 
lineInfo ) );
+         m_lastAssertionInfo.lineInfo = lineInfo;
+         return tracker;
+     }
+@@ -12702,17 +12872,17 @@ namespace Catch {
+ 
+ #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
+     void RunContext::benchmarkPreparing(std::string const& name) {
+-              m_reporter->benchmarkPreparing(name);
+-      }
++        m_reporter->benchmarkPreparing(name);
++    }
+     void RunContext::benchmarkStarting( BenchmarkInfo const& info ) {
+         m_reporter->benchmarkStarting( info );
+     }
+     void RunContext::benchmarkEnded( BenchmarkStats<> const& stats ) {
+         m_reporter->benchmarkEnded( stats );
+     }
+-      void RunContext::benchmarkFailed(std::string const & error) {
+-              m_reporter->benchmarkFailed(error);
+-      }
++    void RunContext::benchmarkFailed(std::string const & error) {
++        m_reporter->benchmarkFailed(error);
++    }
+ #endif // CATCH_CONFIG_ENABLE_BENCHMARKING
+ 
+     void RunContext::pushScopedMessage(MessageInfo const & message) {
+@@ -12846,9 +13016,8 @@ namespace Catch {
+     }
+ 
+     void RunContext::invokeActiveTestCase() {
+-        FatalConditionHandler fatalConditionHandler; // Handle signals
++        FatalConditionHandlerGuard _(&m_fatalConditionhandler);
+         m_activeTestCase->invoke();
+-        fatalConditionHandler.reset();
+     }
+ 
+     void RunContext::handleUnfinishedSections() {
+@@ -13433,6 +13602,7 @@ namespace Catch {
+ // end catch_singletons.cpp
+ // start catch_startup_exception_registry.cpp
+ 
++#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
+ namespace Catch {
+ void StartupExceptionRegistry::add( std::exception_ptr const& exception ) 
noexcept {
+         CATCH_TRY {
+@@ -13448,6 +13618,7 @@ void StartupExceptionRegistry::add( std::exception_ptr 
const& exception ) noexce
+     }
+ 
+ } // end namespace Catch
++#endif
+ // end catch_startup_exception_registry.cpp
+ // start catch_stream.cpp
+ 
+@@ -13632,7 +13803,7 @@ namespace Catch {
+ 
+     namespace {
+         char toLowerCh(char c) {
+-            return static_cast<char>( std::tolower( c ) );
++            return static_cast<char>( std::tolower( static_cast<unsigned 
char>(c) ) );
+         }
+     }
+ 
+@@ -14015,24 +14186,28 @@ namespace Catch {
+ 
+     namespace {
+         struct TestHasher {
+-            explicit TestHasher(Catch::SimplePcg32& rng) {
+-                basis = rng();
+-                basis <<= 32;
+-                basis |= rng();
+-            }
++            using hash_t = uint64_t;
+ 
+-            uint64_t basis;
++            explicit TestHasher( hash_t hashSuffix ):
++                m_hashSuffix{ hashSuffix } {}
+ 
+-            uint64_t operator()(TestCase const& t) const {
+-                // Modified FNV-1a hash
+-                static constexpr uint64_t prime = 1099511628211;
+-                uint64_t hash = basis;
+-                for (const char c : t.name) {
++            uint32_t operator()( TestCase const& t ) const {
++                // FNV-1a hash with multiplication fold.
++                const hash_t prime = 1099511628211u;
++                hash_t hash = 14695981039346656037u;
++                for ( const char c : t.name ) {
+                     hash ^= c;
+                     hash *= prime;
+                 }
+-                return hash;
++                hash ^= m_hashSuffix;
++                hash *= prime;
++                const uint32_t low{ static_cast<uint32_t>( hash ) };
++                const uint32_t high{ static_cast<uint32_t>( hash >> 32 ) };
++                return low * high;
+             }
++
++        private:
++            hash_t m_hashSuffix;
+         };
+     } // end unnamed namespace
+ 
+@@ -14050,9 +14225,9 @@ namespace Catch {
+ 
+             case RunTests::InRandomOrder: {
+                 seedRng( config );
+-                TestHasher h( rng() );
++                TestHasher h{ config.rngSeed() };
+ 
+-                using hashedTest = std::pair<uint64_t, TestCase const*>;
++                using hashedTest = std::pair<TestHasher::hash_t, TestCase 
const*>;
+                 std::vector<hashedTest> indexed_tests;
+                 indexed_tests.reserve( unsortedTestCases.size() );
+ 
+@@ -14215,15 +14390,12 @@ namespace TestCaseTracking {
+         m_currentTracker = tracker;
+     }
+ 
+-    TrackerBase::TrackerBase( NameAndLocation const& nameAndLocation, 
TrackerContext& ctx, ITracker* parent )
+-    :   m_nameAndLocation( nameAndLocation ),
++    TrackerBase::TrackerBase( NameAndLocation const& nameAndLocation, 
TrackerContext& ctx, ITracker* parent ):
++        ITracker(nameAndLocation),
+         m_ctx( ctx ),
+         m_parent( parent )
+     {}
+ 
+-    NameAndLocation const& TrackerBase::nameAndLocation() const {
+-        return m_nameAndLocation;
+-    }
+     bool TrackerBase::isComplete() const {
+         return m_runState == CompletedSuccessfully || m_runState == Failed;
+     }
+@@ -14339,7 +14511,8 @@ namespace TestCaseTracking {
+     bool SectionTracker::isComplete() const {
+         bool complete = true;
+ 
+-        if ((m_filters.empty() || m_filters[0] == "")
++        if (m_filters.empty()
++            || m_filters[0] == ""
+             || std::find(m_filters.begin(), m_filters.end(), m_trimmed_name) 
!= m_filters.end()) {
+             complete = TrackerBase::isComplete();
+         }
+@@ -14384,6 +14557,14 @@ namespace TestCaseTracking {
+             m_filters.insert( m_filters.end(), filters.begin()+1, 
filters.end() );
+     }
+ 
++    std::vector<std::string> const& SectionTracker::getFilters() const {
++        return m_filters;
++    }
++
++    std::string const& SectionTracker::trimmedName() const {
++        return m_trimmed_name;
++    }
++
+ } // namespace TestCaseTracking
+ 
+ using TestCaseTracking::ITracker;
+@@ -15118,11 +15299,48 @@ namespace Catch {
+ // end catch_totals.cpp
+ // start catch_uncaught_exceptions.cpp
+ 
++// start catch_config_uncaught_exceptions.hpp
++
++//              Copyright Catch2 Authors
++// Distributed under the Boost Software License, Version 1.0.
++//   (See accompanying file LICENSE_1_0.txt or copy at
++//        https://www.boost.org/LICENSE_1_0.txt)
++
++// SPDX-License-Identifier: BSL-1.0
++
++#ifndef CATCH_CONFIG_UNCAUGHT_EXCEPTIONS_HPP
++#define CATCH_CONFIG_UNCAUGHT_EXCEPTIONS_HPP
++
++#if defined(_MSC_VER)
++#  if _MSC_VER >= 1900 // Visual Studio 2015 or newer
++#    define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
++#  endif
++#endif
++
++#include <exception>
++
++#if defined(__cpp_lib_uncaught_exceptions) \
++    && !defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS)
++
++#  define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
++#endif // __cpp_lib_uncaught_exceptions
++
++#if defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) \
++    && !defined(CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS) \
++    && !defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS)
++
++#  define CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
++#endif
++
++#endif // CATCH_CONFIG_UNCAUGHT_EXCEPTIONS_HPP
++// end catch_config_uncaught_exceptions.hpp
+ #include <exception>
+ 
+ namespace Catch {
+     bool uncaught_exceptions() {
+-#if defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS)
++#if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
++        return false;
++#elif defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS)
+         return std::uncaught_exceptions() > 0;
+ #else
+         return std::uncaught_exception();
+@@ -15162,7 +15380,7 @@ namespace Catch {
+     }
+ 
+     Version const& libraryVersion() {
+-        static Version version( 2, 12, 2, "", 0 );
++        static Version version( 2, 13, 7, "", 0 );
+         return version;
+     }
+ 
+@@ -15564,6 +15782,17 @@ namespace Catch {
+         return std::string(buffer);
+     }
+ 
++    bool shouldShowDuration( IConfig const& config, double duration ) {
++        if ( config.showDurations() == ShowDurations::Always ) {
++            return true;
++        }
++        if ( config.showDurations() == ShowDurations::Never ) {
++            return false;
++        }
++        const double min = config.minDuration();
++        return min >= 0 && duration >= min;
++    }
++
+     std::string serializeFilters( std::vector<std::string> const& container ) 
{
+         ReusableStringStream oss;
+         bool first = true;
+@@ -15830,10 +16059,6 @@ private:
+             return "Reports test results on a single line, suitable for IDEs";
+         }
+ 
+-        ReporterPreferences CompactReporter::getPreferences() const {
+-            return m_reporterPrefs;
+-        }
+-
+         void CompactReporter::noMatchingTestCases( std::string const& spec ) {
+             stream << "No test cases matched '" << spec << '\'' << std::endl;
+         }
+@@ -15860,8 +16085,9 @@ private:
+         }
+ 
+         void CompactReporter::sectionEnded(SectionStats const& _sectionStats) 
{
+-            if (m_config->showDurations() == ShowDurations::Always) {
+-                stream << 
getFormattedDuration(_sectionStats.durationInSeconds) << " s: " << 
_sectionStats.sectionInfo.name << std::endl;
++            double dur = _sectionStats.durationInSeconds;
++            if ( shouldShowDuration( *m_config, dur ) ) {
++                stream << getFormattedDuration( dur ) << " s: " << 
_sectionStats.sectionInfo.name << std::endl;
+             }
+         }
+ 
+@@ -16281,8 +16507,9 @@ void ConsoleReporter::sectionEnded(SectionStats const& 
_sectionStats) {
+             stream << "\nNo assertions in test case";
+         stream << " '" << _sectionStats.sectionInfo.name << "'\n" << 
std::endl;
+     }
+-    if (m_config->showDurations() == ShowDurations::Always) {
+-        stream << getFormattedDuration(_sectionStats.durationInSeconds) << " 
s: " << _sectionStats.sectionInfo.name << std::endl;
++    double dur = _sectionStats.durationInSeconds;
++    if (shouldShowDuration(*m_config, dur)) {
++        stream << getFormattedDuration(dur) << " s: " << 
_sectionStats.sectionInfo.name << std::endl;
+     }
+     if (m_headerPrinted) {
+         m_headerPrinted = false;
+@@ -16566,6 +16793,7 @@ CATCH_REGISTER_REPORTER("console", ConsoleReporter)
+ #include <sstream>
+ #include <ctime>
+ #include <algorithm>
++#include <iomanip>
+ 
+ namespace Catch {
+ 
+@@ -16593,7 +16821,7 @@ namespace Catch {
+ #else
+             std::strftime(timeStamp, timeStampSize, fmt, timeInfo);
+ #endif
+-            return std::string(timeStamp);
++            return std::string(timeStamp, timeStampSize-1);
+         }
+ 
+         std::string fileNameTag(const std::vector<std::string> &tags) {
+@@ -16604,6 +16832,17 @@ namespace Catch {
+                 return it->substr(1);
+             return std::string();
+         }
++
++        // Formats the duration in seconds to 3 decimal places.
++        // This is done because some genius defined Maven Surefire schema
++        // in a way that only accepts 3 decimal places, and tools like
++        // Jenkins use that schema for validation JUnit reporter output.
++        std::string formatDuration( double seconds ) {
++            ReusableStringStream rss;
++            rss << std::fixed << std::setprecision( 3 ) << seconds;
++            return rss.str();
++        }
++
+     } // anonymous namespace
+ 
+     JunitReporter::JunitReporter( ReporterConfig const& _config )
+@@ -16673,7 +16912,7 @@ namespace Catch {
+         if( m_config->showDurations() == ShowDurations::Never )
+             xml.writeAttribute( "time", "" );
+         else
+-            xml.writeAttribute( "time", suiteTime );
++            xml.writeAttribute( "time", formatDuration( suiteTime ) );
+         xml.writeAttribute( "timestamp", getCurrentTimestamp() );
+ 
+         // Write properties if there are any
+@@ -16718,12 +16957,13 @@ namespace Catch {
+         if ( !m_config->name().empty() )
+             className = m_config->name() + "." + className;
+ 
+-        writeSection( className, "", rootSection );
++        writeSection( className, "", rootSection, stats.testInfo.okToFail() );
+     }
+ 
+-    void JunitReporter::writeSection(  std::string const& className,
+-                        std::string const& rootName,
+-                        SectionNode const& sectionNode ) {
++    void JunitReporter::writeSection( std::string const& className,
++                                      std::string const& rootName,
++                                      SectionNode const& sectionNode,
++                                      bool testOkToFail) {
+         std::string name = trim( sectionNode.stats.sectionInfo.name );
+         if( !rootName.empty() )
+             name = rootName + '/' + name;
+@@ -16740,13 +16980,18 @@ namespace Catch {
+                 xml.writeAttribute( "classname", className );
+                 xml.writeAttribute( "name", name );
+             }
+-            xml.writeAttribute( "time", ::Catch::Detail::stringify( 
sectionNode.stats.durationInSeconds ) );
++            xml.writeAttribute( "time", formatDuration( 
sectionNode.stats.durationInSeconds ) );
+             // This is not ideal, but it should be enough to mimic gtest's
+             // junit output.
+             // Ideally the JUnit reporter would also handle `skipTest`
+             // events and write those out appropriately.
+             xml.writeAttribute( "status", "run" );
+ 
++            if (sectionNode.stats.assertions.failedButOk) {
++                xml.scopedElement("skipped")
++                    .writeAttribute("message", "TEST_CASE tagged with 
!mayfail");
++            }
++
+             writeAssertions( sectionNode );
+ 
+             if( !sectionNode.stdOut.empty() )
+@@ -16756,9 +17001,9 @@ namespace Catch {
+         }
+         for( auto const& childNode : sectionNode.childSections )
+             if( className.empty() )
+-                writeSection( name, "", *childNode );
++                writeSection( name, "", *childNode, testOkToFail );
+             else
+-                writeSection( className, name, *childNode );
++                writeSection( className, name, *childNode, testOkToFail );
+     }
+ 
+     void JunitReporter::writeAssertions( SectionNode const& sectionNode ) {
+@@ -17180,6 +17425,10 @@ namespace Catch {
+             .writeAttribute( "successes", 
testGroupStats.totals.assertions.passed )
+             .writeAttribute( "failures", 
testGroupStats.totals.assertions.failed )
+             .writeAttribute( "expectedFailures", 
testGroupStats.totals.assertions.failedButOk );
++        m_xml.scopedElement( "OverallResultsCases")
++            .writeAttribute( "successes", 
testGroupStats.totals.testCases.passed )
++            .writeAttribute( "failures", 
testGroupStats.totals.testCases.failed )
++            .writeAttribute( "expectedFailures", 
testGroupStats.totals.testCases.failedButOk );
+         m_xml.endElement();
+     }
+ 
+@@ -17189,6 +17438,10 @@ namespace Catch {
+             .writeAttribute( "successes", 
testRunStats.totals.assertions.passed )
+             .writeAttribute( "failures", 
testRunStats.totals.assertions.failed )
+             .writeAttribute( "expectedFailures", 
testRunStats.totals.assertions.failedButOk );
++        m_xml.scopedElement( "OverallResultsCases")
++            .writeAttribute( "successes", 
testRunStats.totals.testCases.passed )
++            .writeAttribute( "failures", testRunStats.totals.testCases.failed 
)
++            .writeAttribute( "expectedFailures", 
testRunStats.totals.testCases.failedButOk );
+         m_xml.endElement();
+     }
+ 
+-- 
+2.30.2
+
diff -Nru monado-21.0.0~dfsg1/debian/patches/series 
monado-21.0.0~dfsg1/debian/patches/series
--- monado-21.0.0~dfsg1/debian/patches/series   2021-10-27 00:59:16.000000000 
+0300
+++ monado-21.0.0~dfsg1/debian/patches/series   2022-09-12 10:16:47.000000000 
+0300
@@ -1,2 +1,3 @@
 0001-Allow-overriding-package-version.patch
 0002-comp-Fix-warning-after-Vulkan-1.2.174-VK_NULL_HANDLE.patch
+0001-src-external-Update-to-Catch2-version-2.13.7.patch

Reply via email to