home readme diff tree note docs

0commit e50ea9e1356a74af18fdd171337ef9dc931e1f4e
1Author: Mason Wright <mason@lakefox.net>
2Date:   Tue Jun 24 20:44:14 2025 -0600
3
4    Added tests to parser
5
6diff --git a/.gitignore b/.gitignore
7new file mode 100644
8index 0000000..18d2eaf
9--- /dev/null
10+++ b/.gitignore
11@@ -0,0 +1,2 @@
12+build/
13+main
14diff --git a/Makefile b/Makefile
15index 1260c17..714bc8e 100644
16--- a/Makefile
17+++ b/Makefile
18@@ -2,7 +2,7 @@
19 CCFLAGS = -Wall -Wextra -std=c++23
20 CC = clang++
21 
22-.PHONY: all clean run docs
23+.PHONY: all clean run docs tests
24 
25 all: main
26 
27@@ -18,10 +18,17 @@ build/grim.o: src/grim.cc include/grim.h | build
28 build/parser.o: src/parser.cc include/parser.h | build
29 	${CC} ${CCFLAGS} -Iinclude/ -c src/parser.cc -o build/parser.o
30 
31+tests: build/grim.o build/parser.o build/catch.o
32+	clear && ${CC} ${CCFLAGS} -Itests/ -Iinclude/ ./tests/main.cc ./build/grim.o ./build/parser.o ./build/catch.o -o ./tests/main && ./tests/main
33+
34+build/catch.o: ./tests/catch_amalgamated.cpp ./tests/catch_amalgamated.hpp | build
35+	${CC} ${CCFLAGS} -Itests/ -c ./tests/catch_amalgamated.cpp -o build/catch.o
36+
37 clean:
38 	rm -f main build/*.o
39 
40 run:
41 	clear && ./main
42+
43 docs:
44 	cd ../build && ./git.sh && ./tracker.sh
45diff --git a/build/grim.o b/build/grim.o
46deleted file mode 100644
47index a655a9c..0000000
48Binary files a/build/grim.o and /dev/null differ
49diff --git a/build/parser.o b/build/parser.o
50deleted file mode 100644
51index 4be662f..0000000
52Binary files a/build/parser.o and /dev/null differ
53diff --git a/index.html b/index.html
54index 3284123..289b7f3 100644
55--- a/index.html
56+++ b/index.html
57@@ -4,6 +4,7 @@
58 <style>
59 	h1 {
60 		color: red;
61+		content: "<h1>hi</h1>";
62 	}
63 </style>
64 	</head>
65@@ -16,5 +17,9 @@
66 	<p id="test">
67 		this is a test
68 	</p>
69+	<pre>
70+	<script> console.log("</pre>");</script>
71+	</pre>
72+	<textarea><script>console.log(\"</pre>\");</script></textarea>
73 	</body>
74 </html>
75diff --git a/main b/main
76deleted file mode 100755
77index f079efc..0000000
78Binary files a/main and /dev/null differ
79diff --git a/tests/catch_amalgamated.cpp b/tests/catch_amalgamated.cpp
80new file mode 100644
81index 0000000..6aa6788
82--- /dev/null
83+++ b/tests/catch_amalgamated.cpp
84@@ -0,0 +1,11520 @@
85+
86+//              Copyright Catch2 Authors
87+// Distributed under the Boost Software License, Version 1.0.
88+//   (See accompanying file LICENSE.txt or copy at
89+//        https://www.boost.org/LICENSE_1_0.txt)
90+
91+// SPDX-License-Identifier: BSL-1.0
92+
93+//  Catch v3.5.4
94+//  Generated: 2024-04-10 12:03:46.281848
95+//  ----------------------------------------------------------
96+//  This file is an amalgamation of multiple different files.
97+//  You probably shouldn't edit it directly.
98+//  ----------------------------------------------------------
99+
100+#include "catch_amalgamated.hpp"
101+
102+
103+#ifndef CATCH_WINDOWS_H_PROXY_HPP_INCLUDED
104+#define CATCH_WINDOWS_H_PROXY_HPP_INCLUDED
105+
106+
107+#if defined(CATCH_PLATFORM_WINDOWS)
108+
109+// We might end up with the define made globally through the compiler,
110+// and we don't want to trigger warnings for this
111+#if !defined(NOMINMAX)
112+#  define NOMINMAX
113+#endif
114+#if !defined(WIN32_LEAN_AND_MEAN)
115+#  define WIN32_LEAN_AND_MEAN
116+#endif
117+
118+#include <windows.h>
119+
120+#endif // defined(CATCH_PLATFORM_WINDOWS)
121+
122+#endif // CATCH_WINDOWS_H_PROXY_HPP_INCLUDED
123+
124+
125+
126+
127+namespace Catch {
128+    namespace Benchmark {
129+        namespace Detail {
130+            ChronometerConcept::~ChronometerConcept() = default;
131+        } // namespace Detail
132+    } // namespace Benchmark
133+} // namespace Catch
134+
135+
136+// Adapted from donated nonius code.
137+
138+
139+#include <vector>
140+
141+namespace Catch {
142+    namespace Benchmark {
143+        namespace Detail {
144+            SampleAnalysis analyse(const IConfig &cfg, FDuration* first, FDuration* last) {
145+                if (!cfg.benchmarkNoAnalysis()) {
146+                    std::vector<double> samples;
147+                    samples.reserve(static_cast<size_t>(last - first));
148+                    for (auto current = first; current != last; ++current) {
149+                        samples.push_back( current->count() );
150+                    }
151+
152+                    auto analysis = Catch::Benchmark::Detail::analyse_samples(
153+                        cfg.benchmarkConfidenceInterval(),
154+                        cfg.benchmarkResamples(),
155+                        samples.data(),
156+                        samples.data() + samples.size() );
157+                    auto outliers = Catch::Benchmark::Detail::classify_outliers(
158+                        samples.data(), samples.data() + samples.size() );
159+
160+                    auto wrap_estimate = [](Estimate<double> e) {
161+                        return Estimate<FDuration> {
162+                            FDuration(e.point),
163+                                FDuration(e.lower_bound),
164+                                FDuration(e.upper_bound),
165+                                e.confidence_interval,
166+                        };
167+                    };
168+                    std::vector<FDuration> samples2;
169+                    samples2.reserve(samples.size());
170+                    for (auto s : samples) {
171+                        samples2.push_back( FDuration( s ) );
172+                    }
173+
174+                    return {
175+                        CATCH_MOVE(samples2),
176+                        wrap_estimate(analysis.mean),
177+                        wrap_estimate(analysis.standard_deviation),
178+                        outliers,
179+                        analysis.outlier_variance,
180+                    };
181+                } else {
182+                    std::vector<FDuration> samples;
183+                    samples.reserve(static_cast<size_t>(last - first));
184+
185+                    FDuration mean = FDuration(0);
186+                    int i = 0;
187+                    for (auto it = first; it < last; ++it, ++i) {
188+                        samples.push_back(*it);
189+                        mean += *it;
190+                    }
191+                    mean /= i;
192+
193+                    return SampleAnalysis{
194+                        CATCH_MOVE(samples),
195+                        Estimate<FDuration>{ mean, mean, mean, 0.0 },
196+                        Estimate<FDuration>{ FDuration( 0 ),
197+                                             FDuration( 0 ),
198+                                             FDuration( 0 ),
199+                                             0.0 },
200+                        OutlierClassification{},
201+                        0.0
202+                    };
203+                }
204+            }
205+        } // namespace Detail
206+    } // namespace Benchmark
207+} // namespace Catch
208+
209+
210+
211+
212+namespace Catch {
213+    namespace Benchmark {
214+        namespace Detail {
215+            BenchmarkFunction::callable::~callable() = default;
216+        } // namespace Detail
217+    } // namespace Benchmark
218+} // namespace Catch
219+
220+
221+
222+
223+#include <exception>
224+
225+namespace Catch {
226+    namespace Benchmark {
227+        namespace Detail {
228+            struct optimized_away_error : std::exception {
229+                const char* what() const noexcept override;
230+            };
231+
232+            const char* optimized_away_error::what() const noexcept {
233+                return "could not measure benchmark, maybe it was optimized away";
234+            }
235+
236+            void throw_optimized_away_error() {
237+                Catch::throw_exception(optimized_away_error{});
238+            }
239+
240+        } // namespace Detail
241+    } // namespace Benchmark
242+} // namespace Catch
243+
244+
245+// Adapted from donated nonius code.
246+
247+
248+
249+#include <algorithm>
250+#include <cassert>
251+#include <cmath>
252+#include <cstddef>
253+#include <numeric>
254+#include <random>
255+
256+
257+#if defined(CATCH_CONFIG_USE_ASYNC)
258+#include <future>
259+#endif
260+
261+namespace Catch {
262+    namespace Benchmark {
263+        namespace Detail {
264+            namespace {
265+
266+                template <typename URng, typename Estimator>
267+                static sample
268+                resample( URng& rng,
269+                          unsigned int resamples,
270+                          double const* first,
271+                          double const* last,
272+                          Estimator& estimator ) {
273+                    auto n = static_cast<size_t>( last - first );
274+                    Catch::uniform_integer_distribution<size_t> dist( 0, n - 1 );
275+
276+                    sample out;
277+                    out.reserve( resamples );
278+                    std::vector<double> resampled;
279+                    resampled.reserve( n );
280+                    for ( size_t i = 0; i < resamples; ++i ) {
281+                        resampled.clear();
282+                        for ( size_t s = 0; s < n; ++s ) {
283+                            resampled.push_back( first[dist( rng )] );
284+                        }
285+                        const auto estimate =
286+                            estimator( resampled.data(), resampled.data() + resampled.size() );
287+                        out.push_back( estimate );
288+                    }
289+                    std::sort( out.begin(), out.end() );
290+                    return out;
291+                }
292+
293+                static double outlier_variance( Estimate<double> mean,
294+                                                Estimate<double> stddev,
295+                                                int n ) {
296+                    double sb = stddev.point;
297+                    double mn = mean.point / n;
298+                    double mg_min = mn / 2.;
299+                    double sg = (std::min)( mg_min / 4., sb / std::sqrt( n ) );
300+                    double sg2 = sg * sg;
301+                    double sb2 = sb * sb;
302+
303+                    auto c_max = [n, mn, sb2, sg2]( double x ) -> double {
304+                        double k = mn - x;
305+                        double d = k * k;
306+                        double nd = n * d;
307+                        double k0 = -n * nd;
308+                        double k1 = sb2 - n * sg2 + nd;
309+                        double det = k1 * k1 - 4 * sg2 * k0;
310+                        return static_cast<int>( -2. * k0 /
311+                                                 ( k1 + std::sqrt( det ) ) );
312+                    };
313+
314+                    auto var_out = [n, sb2, sg2]( double c ) {
315+                        double nc = n - c;
316+                        return ( nc / n ) * ( sb2 - nc * sg2 );
317+                    };
318+
319+                    return (std::min)( var_out( 1 ),
320+                                       var_out(
321+                                           (std::min)( c_max( 0. ),
322+                                                       c_max( mg_min ) ) ) ) /
323+                           sb2;
324+                }
325+
326+                static double erf_inv( double x ) {
327+                    // Code accompanying the article "Approximating the erfinv
328+                    // function" in GPU Computing Gems, Volume 2
329+                    double w, p;
330+
331+                    w = -log( ( 1.0 - x ) * ( 1.0 + x ) );
332+
333+                    if ( w < 6.250000 ) {
334+                        w = w - 3.125000;
335+                        p = -3.6444120640178196996e-21;
336+                        p = -1.685059138182016589e-19 + p * w;
337+                        p = 1.2858480715256400167e-18 + p * w;
338+                        p = 1.115787767802518096e-17 + p * w;
339+                        p = -1.333171662854620906e-16 + p * w;
340+                        p = 2.0972767875968561637e-17 + p * w;
341+                        p = 6.6376381343583238325e-15 + p * w;
342+                        p = -4.0545662729752068639e-14 + p * w;
343+                        p = -8.1519341976054721522e-14 + p * w;
344+                        p = 2.6335093153082322977e-12 + p * w;
345+                        p = -1.2975133253453532498e-11 + p * w;
346+                        p = -5.4154120542946279317e-11 + p * w;
347+                        p = 1.051212273321532285e-09 + p * w;
348+                        p = -4.1126339803469836976e-09 + p * w;
349+                        p = -2.9070369957882005086e-08 + p * w;
350+                        p = 4.2347877827932403518e-07 + p * w;
351+                        p = -1.3654692000834678645e-06 + p * w;
352+                        p = -1.3882523362786468719e-05 + p * w;
353+                        p = 0.0001867342080340571352 + p * w;
354+                        p = -0.00074070253416626697512 + p * w;
355+                        p = -0.0060336708714301490533 + p * w;
356+                        p = 0.24015818242558961693 + p * w;
357+                        p = 1.6536545626831027356 + p * w;
358+                    } else if ( w < 16.000000 ) {
359+                        w = sqrt( w ) - 3.250000;
360+                        p = 2.2137376921775787049e-09;
361+                        p = 9.0756561938885390979e-08 + p * w;
362+                        p = -2.7517406297064545428e-07 + p * w;
363+                        p = 1.8239629214389227755e-08 + p * w;
364+                        p = 1.5027403968909827627e-06 + p * w;
365+                        p = -4.013867526981545969e-06 + p * w;
366+                        p = 2.9234449089955446044e-06 + p * w;
367+                        p = 1.2475304481671778723e-05 + p * w;
368+                        p = -4.7318229009055733981e-05 + p * w;
369+                        p = 6.8284851459573175448e-05 + p * w;
370+                        p = 2.4031110387097893999e-05 + p * w;
371+                        p = -0.0003550375203628474796 + p * w;
372+                        p = 0.00095328937973738049703 + p * w;
373+                        p = -0.0016882755560235047313 + p * w;
374+                        p = 0.0024914420961078508066 + p * w;
375+                        p = -0.0037512085075692412107 + p * w;
376+                        p = 0.005370914553590063617 + p * w;
377+                        p = 1.0052589676941592334 + p * w;
378+                        p = 3.0838856104922207635 + p * w;
379+                    } else {
380+                        w = sqrt( w ) - 5.000000;
381+                        p = -2.7109920616438573243e-11;
382+                        p = -2.5556418169965252055e-10 + p * w;
383+                        p = 1.5076572693500548083e-09 + p * w;
384+                        p = -3.7894654401267369937e-09 + p * w;
385+                        p = 7.6157012080783393804e-09 + p * w;
386+                        p = -1.4960026627149240478e-08 + p * w;
387+                        p = 2.9147953450901080826e-08 + p * w;
388+                        p = -6.7711997758452339498e-08 + p * w;
389+                        p = 2.2900482228026654717e-07 + p * w;
390+                        p = -9.9298272942317002539e-07 + p * w;
391+                        p = 4.5260625972231537039e-06 + p * w;
392+                        p = -1.9681778105531670567e-05 + p * w;
393+                        p = 7.5995277030017761139e-05 + p * w;
394+                        p = -0.00021503011930044477347 + p * w;
395+                        p = -0.00013871931833623122026 + p * w;
396+                        p = 1.0103004648645343977 + p * w;
397+                        p = 4.8499064014085844221 + p * w;
398+                    }
399+                    return p * x;
400+                }
401+
402+                static double
403+                standard_deviation( double const* first, double const* last ) {
404+                    auto m = Catch::Benchmark::Detail::mean( first, last );
405+                    double variance =
406+                        std::accumulate( first,
407+                                         last,
408+                                         0.,
409+                                         [m]( double a, double b ) {
410+                                             double diff = b - m;
411+                                             return a + diff * diff;
412+                                         } ) /
413+                        ( last - first );
414+                    return std::sqrt( variance );
415+                }
416+
417+                static sample jackknife( double ( *estimator )( double const*,
418+                                                                double const* ),
419+                                         double* first,
420+                                         double* last ) {
421+                    const auto second = first + 1;
422+                    sample results;
423+                    results.reserve( static_cast<size_t>( last - first ) );
424+
425+                    for ( auto it = first; it != last; ++it ) {
426+                        std::iter_swap( it, first );
427+                        results.push_back( estimator( second, last ) );
428+                    }
429+
430+                    return results;
431+                }
432+
433+
434+            } // namespace
435+        }     // namespace Detail
436+    }         // namespace Benchmark
437+} // namespace Catch
438+
439+namespace Catch {
440+    namespace Benchmark {
441+        namespace Detail {
442+
443+            double weighted_average_quantile( int k,
444+                                              int q,
445+                                              double* first,
446+                                              double* last ) {
447+                auto count = last - first;
448+                double idx = (count - 1) * k / static_cast<double>(q);
449+                int j = static_cast<int>(idx);
450+                double g = idx - j;
451+                std::nth_element(first, first + j, last);
452+                auto xj = first[j];
453+                if ( Catch::Detail::directCompare( g, 0 ) ) {
454+                    return xj;
455+                }
456+
457+                auto xj1 = *std::min_element(first + (j + 1), last);
458+                return xj + g * (xj1 - xj);
459+            }
460+
461+            OutlierClassification
462+            classify_outliers( double const* first, double const* last ) {
463+                std::vector<double> copy( first, last );
464+
465+                auto q1 = weighted_average_quantile( 1, 4, copy.data(), copy.data() + copy.size() );
466+                auto q3 = weighted_average_quantile( 3, 4, copy.data(), copy.data() + copy.size() );
467+                auto iqr = q3 - q1;
468+                auto los = q1 - ( iqr * 3. );
469+                auto lom = q1 - ( iqr * 1.5 );
470+                auto him = q3 + ( iqr * 1.5 );
471+                auto his = q3 + ( iqr * 3. );
472+
473+                OutlierClassification o;
474+                for ( ; first != last; ++first ) {
475+                    const double t = *first;
476+                    if ( t < los ) {
477+                        ++o.low_severe;
478+                    } else if ( t < lom ) {
479+                        ++o.low_mild;
480+                    } else if ( t > his ) {
481+                        ++o.high_severe;
482+                    } else if ( t > him ) {
483+                        ++o.high_mild;
484+                    }
485+                    ++o.samples_seen;
486+                }
487+                return o;
488+            }
489+
490+            double mean( double const* first, double const* last ) {
491+                auto count = last - first;
492+                double sum = 0.;
493+                while (first != last) {
494+                    sum += *first;
495+                    ++first;
496+                }
497+                return sum / static_cast<double>(count);
498+            }
499+
500+            double normal_cdf( double x ) {
501+                return std::erfc( -x / std::sqrt( 2.0 ) ) / 2.0;
502+            }
503+
504+            double erfc_inv(double x) {
505+                return erf_inv(1.0 - x);
506+            }
507+
508+            double normal_quantile(double p) {
509+                static const double ROOT_TWO = std::sqrt(2.0);
510+
511+                double result = 0.0;
512+                assert(p >= 0 && p <= 1);
513+                if (p < 0 || p > 1) {
514+                    return result;
515+                }
516+
517+                result = -erfc_inv(2.0 * p);
518+                // result *= normal distribution standard deviation (1.0) * sqrt(2)
519+                result *= /*sd * */ ROOT_TWO;
520+                // result += normal disttribution mean (0)
521+                return result;
522+            }
523+
524+            Estimate<double>
525+            bootstrap( double confidence_level,
526+                       double* first,
527+                       double* last,
528+                       sample const& resample,
529+                       double ( *estimator )( double const*, double const* ) ) {
530+                auto n_samples = last - first;
531+
532+                double point = estimator( first, last );
533+                // Degenerate case with a single sample
534+                if ( n_samples == 1 )
535+                    return { point, point, point, confidence_level };
536+
537+                sample jack = jackknife( estimator, first, last );
538+                double jack_mean =
539+                    mean( jack.data(), jack.data() + jack.size() );
540+                double sum_squares = 0, sum_cubes = 0;
541+                for ( double x : jack ) {
542+                    auto difference = jack_mean - x;
543+                    auto square = difference * difference;
544+                    auto cube = square * difference;
545+                    sum_squares += square;
546+                    sum_cubes += cube;
547+                }
548+
549+                double accel = sum_cubes / ( 6 * std::pow( sum_squares, 1.5 ) );
550+                long n = static_cast<long>( resample.size() );
551+                double prob_n =
552+                    std::count_if( resample.begin(),
553+                                   resample.end(),
554+                                   [point]( double x ) { return x < point; } ) /
555+                    static_cast<double>( n );
556+                // degenerate case with uniform samples
557+                if ( Catch::Detail::directCompare( prob_n, 0. ) ) {
558+                    return { point, point, point, confidence_level };
559+                }
560+
561+                double bias = normal_quantile( prob_n );
562+                double z1 = normal_quantile( ( 1. - confidence_level ) / 2. );
563+
564+                auto cumn = [n]( double x ) -> long {
565+                    return std::lround( normal_cdf( x ) *
566+                                        static_cast<double>( n ) );
567+                };
568+                auto a = [bias, accel]( double b ) {
569+                    return bias + b / ( 1. - accel * b );
570+                };
571+                double b1 = bias + z1;
572+                double b2 = bias - z1;
573+                double a1 = a( b1 );
574+                double a2 = a( b2 );
575+                auto lo = static_cast<size_t>( (std::max)( cumn( a1 ), 0l ) );
576+                auto hi =
577+                    static_cast<size_t>( (std::min)( cumn( a2 ), n - 1 ) );
578+
579+                return { point, resample[lo], resample[hi], confidence_level };
580+            }
581+
582+            bootstrap_analysis analyse_samples(double confidence_level,
583+                                               unsigned int n_resamples,
584+                                               double* first,
585+                                               double* last) {
586+                auto mean = &Detail::mean;
587+                auto stddev = &standard_deviation;
588+
589+#if defined(CATCH_CONFIG_USE_ASYNC)
590+                auto Estimate = [=](double(*f)(double const*, double const*)) {
591+                    std::random_device rd;
592+                    auto seed = rd();
593+                    return std::async(std::launch::async, [=] {
594+                        SimplePcg32 rng( seed );
595+                        auto resampled = resample(rng, n_resamples, first, last, f);
596+                        return bootstrap(confidence_level, first, last, resampled, f);
597+                    });
598+                };
599+
600+                auto mean_future = Estimate(mean);
601+                auto stddev_future = Estimate(stddev);
602+
603+                auto mean_estimate = mean_future.get();
604+                auto stddev_estimate = stddev_future.get();
605+#else
606+                auto Estimate = [=](double(*f)(double const* , double const*)) {
607+                    std::random_device rd;
608+                    auto seed = rd();
609+                    SimplePcg32 rng( seed );
610+                    auto resampled = resample(rng, n_resamples, first, last, f);
611+                    return bootstrap(confidence_level, first, last, resampled, f);
612+                };
613+
614+                auto mean_estimate = Estimate(mean);
615+                auto stddev_estimate = Estimate(stddev);
616+#endif // CATCH_USE_ASYNC
617+
618+                auto n = static_cast<int>(last - first); // seriously, one can't use integral types without hell in C++
619+                double outlier_variance = Detail::outlier_variance(mean_estimate, stddev_estimate, n);
620+
621+                return { mean_estimate, stddev_estimate, outlier_variance };
622+            }
623+        } // namespace Detail
624+    } // namespace Benchmark
625+} // namespace Catch
626+
627+
628+
629+#include <cmath>
630+#include <limits>
631+
632+namespace {
633+
634+// Performs equivalent check of std::fabs(lhs - rhs) <= margin
635+// But without the subtraction to allow for INFINITY in comparison
636+bool marginComparison(double lhs, double rhs, double margin) {
637+    return (lhs + margin >= rhs) && (rhs + margin >= lhs);
638+}
639+
640+}
641+
642+namespace Catch {
643+
644+    Approx::Approx ( double value )
645+    :   m_epsilon( static_cast<double>(std::numeric_limits<float>::epsilon())*100. ),
646+        m_margin( 0.0 ),
647+        m_scale( 0.0 ),
648+        m_value( value )
649+    {}
650+
651+    Approx Approx::custom() {
652+        return Approx( 0 );
653+    }
654+
655+    Approx Approx::operator-() const {
656+        auto temp(*this);
657+        temp.m_value = -temp.m_value;
658+        return temp;
659+    }
660+
661+
662+    std::string Approx::toString() const {
663+        ReusableStringStream rss;
664+        rss << "Approx( " << ::Catch::Detail::stringify( m_value ) << " )";
665+        return rss.str();
666+    }
667+
668+    bool Approx::equalityComparisonImpl(const double other) const {
669+        // First try with fixed margin, then compute margin based on epsilon, scale and Approx's value
670+        // Thanks to Richard Harris for his help refining the scaled margin value
671+        return marginComparison(m_value, other, m_margin)
672+            || marginComparison(m_value, other, m_epsilon * (m_scale + std::fabs(std::isinf(m_value)? 0 : m_value)));
673+    }
674+
675+    void Approx::setMargin(double newMargin) {
676+        CATCH_ENFORCE(newMargin >= 0,
677+            "Invalid Approx::margin: " << newMargin << '.'
678+            << " Approx::Margin has to be non-negative.");
679+        m_margin = newMargin;
680+    }
681+
682+    void Approx::setEpsilon(double newEpsilon) {
683+        CATCH_ENFORCE(newEpsilon >= 0 && newEpsilon <= 1.0,
684+            "Invalid Approx::epsilon: " << newEpsilon << '.'
685+            << " Approx::epsilon has to be in [0, 1]");
686+        m_epsilon = newEpsilon;
687+    }
688+
689+namespace literals {
690+    Approx operator ""_a(long double val) {
691+        return Approx(val);
692+    }
693+    Approx operator ""_a(unsigned long long val) {
694+        return Approx(val);
695+    }
696+} // end namespace literals
697+
698+std::string StringMaker<Catch::Approx>::convert(Catch::Approx const& value) {
699+    return value.toString();
700+}
701+
702+} // end namespace Catch
703+
704+
705+
706+namespace Catch {
707+
708+    AssertionResultData::AssertionResultData(ResultWas::OfType _resultType, LazyExpression const & _lazyExpression):
709+        lazyExpression(_lazyExpression),
710+        resultType(_resultType) {}
711+
712+    std::string AssertionResultData::reconstructExpression() const {
713+
714+        if( reconstructedExpression.empty() ) {
715+            if( lazyExpression ) {
716+                ReusableStringStream rss;
717+                rss << lazyExpression;
718+                reconstructedExpression = rss.str();
719+            }
720+        }
721+        return reconstructedExpression;
722+    }
723+
724+    AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData&& data )
725+    :   m_info( info ),
726+        m_resultData( CATCH_MOVE(data) )
727+    {}
728+
729+    // Result was a success
730+    bool AssertionResult::succeeded() const {
731+        return Catch::isOk( m_resultData.resultType );
732+    }
733+
734+    // Result was a success, or failure is suppressed
735+    bool AssertionResult::isOk() const {
736+        return Catch::isOk( m_resultData.resultType ) || shouldSuppressFailure( m_info.resultDisposition );
737+    }
738+
739+    ResultWas::OfType AssertionResult::getResultType() const {
740+        return m_resultData.resultType;
741+    }
742+
743+    bool AssertionResult::hasExpression() const {
744+        return !m_info.capturedExpression.empty();
745+    }
746+
747+    bool AssertionResult::hasMessage() const {
748+        return !m_resultData.message.empty();
749+    }
750+
751+    std::string AssertionResult::getExpression() const {
752+        // Possibly overallocating by 3 characters should be basically free
753+        std::string expr; expr.reserve(m_info.capturedExpression.size() + 3);
754+        if (isFalseTest(m_info.resultDisposition)) {
755+            expr += "!(";
756+        }
757+        expr += m_info.capturedExpression;
758+        if (isFalseTest(m_info.resultDisposition)) {
759+            expr += ')';
760+        }
761+        return expr;
762+    }
763+
764+    std::string AssertionResult::getExpressionInMacro() const {
765+        if ( m_info.macroName.empty() ) {
766+            return static_cast<std::string>( m_info.capturedExpression );
767+        }
768+        std::string expr;
769+        expr.reserve( m_info.macroName.size() + m_info.capturedExpression.size() + 4 );
770+        expr += m_info.macroName;
771+        expr += "( ";
772+        expr += m_info.capturedExpression;
773+        expr += " )";
774+        return expr;
775+    }
776+
777+    bool AssertionResult::hasExpandedExpression() const {
778+        return hasExpression() && getExpandedExpression() != getExpression();
779+    }
780+
781+    std::string AssertionResult::getExpandedExpression() const {
782+        std::string expr = m_resultData.reconstructExpression();
783+        return expr.empty()
784+                ? getExpression()
785+                : expr;
786+    }
787+
788+    StringRef AssertionResult::getMessage() const {
789+        return m_resultData.message;
790+    }
791+    SourceLineInfo AssertionResult::getSourceInfo() const {
792+        return m_info.lineInfo;
793+    }
794+
795+    StringRef AssertionResult::getTestMacroName() const {
796+        return m_info.macroName;
797+    }
798+
799+} // end namespace Catch
800+
801+
802+
803+#include <fstream>
804+
805+namespace Catch {
806+
807+    namespace {
808+        static bool enableBazelEnvSupport() {
809+#if defined( CATCH_CONFIG_BAZEL_SUPPORT )
810+            return true;
811+#else
812+            return Detail::getEnv( "BAZEL_TEST" ) != nullptr;
813+#endif
814+        }
815+
816+        struct bazelShardingOptions {
817+            unsigned int shardIndex, shardCount;
818+            std::string shardFilePath;
819+        };
820+
821+        static Optional<bazelShardingOptions> readBazelShardingOptions() {
822+            const auto bazelShardIndex = Detail::getEnv( "TEST_SHARD_INDEX" );
823+            const auto bazelShardTotal = Detail::getEnv( "TEST_TOTAL_SHARDS" );
824+            const auto bazelShardInfoFile = Detail::getEnv( "TEST_SHARD_STATUS_FILE" );
825+
826+
827+            const bool has_all =
828+                bazelShardIndex && bazelShardTotal && bazelShardInfoFile;
829+            if ( !has_all ) {
830+                // We provide nice warning message if the input is
831+                // misconfigured.
832+                auto warn = []( const char* env_var ) {
833+                    Catch::cerr()
834+                        << "Warning: Bazel shard configuration is missing '"
835+                        << env_var << "'. Shard configuration is skipped.\n";
836+                };
837+                if ( !bazelShardIndex ) {
838+                    warn( "TEST_SHARD_INDEX" );
839+                }
840+                if ( !bazelShardTotal ) {
841+                    warn( "TEST_TOTAL_SHARDS" );
842+                }
843+                if ( !bazelShardInfoFile ) {
844+                    warn( "TEST_SHARD_STATUS_FILE" );
845+                }
846+                return {};
847+            }
848+
849+            auto shardIndex = parseUInt( bazelShardIndex );
850+            if ( !shardIndex ) {
851+                Catch::cerr()
852+                    << "Warning: could not parse 'TEST_SHARD_INDEX' ('" << bazelShardIndex
853+                    << "') as unsigned int.\n";
854+                return {};
855+            }
856+            auto shardTotal = parseUInt( bazelShardTotal );
857+            if ( !shardTotal ) {
858+                Catch::cerr()
859+                    << "Warning: could not parse 'TEST_TOTAL_SHARD' ('"
860+                    << bazelShardTotal << "') as unsigned int.\n";
861+                return {};
862+            }
863+
864+            return bazelShardingOptions{
865+                *shardIndex, *shardTotal, bazelShardInfoFile };
866+
867+        }
868+    } // end namespace
869+
870+
871+    bool operator==( ProcessedReporterSpec const& lhs,
872+                     ProcessedReporterSpec const& rhs ) {
873+        return lhs.name == rhs.name &&
874+               lhs.outputFilename == rhs.outputFilename &&
875+               lhs.colourMode == rhs.colourMode &&
876+               lhs.customOptions == rhs.customOptions;
877+    }
878+
879+    Config::Config( ConfigData const& data ):
880+        m_data( data ) {
881+        // We need to trim filter specs to avoid trouble with superfluous
882+        // whitespace (esp. important for bdd macros, as those are manually
883+        // aligned with whitespace).
884+
885+        for (auto& elem : m_data.testsOrTags) {
886+            elem = trim(elem);
887+        }
888+        for (auto& elem : m_data.sectionsToRun) {
889+            elem = trim(elem);
890+        }
891+
892+        // Insert the default reporter if user hasn't asked for a specific one
893+        if ( m_data.reporterSpecifications.empty() ) {
894+#if defined( CATCH_CONFIG_DEFAULT_REPORTER )
895+            const auto default_spec = CATCH_CONFIG_DEFAULT_REPORTER;
896+#else
897+            const auto default_spec = "console";
898+#endif
899+            auto parsed = parseReporterSpec(default_spec);
900+            CATCH_ENFORCE( parsed,
901+                           "Cannot parse the provided default reporter spec: '"
902+                               << default_spec << '\'' );
903+            m_data.reporterSpecifications.push_back( std::move( *parsed ) );
904+        }
905+
906+        if ( enableBazelEnvSupport() ) {
907+            readBazelEnvVars();
908+        }
909+
910+        // Bazel support can modify the test specs, so parsing has to happen
911+        // after reading Bazel env vars.
912+        TestSpecParser parser( ITagAliasRegistry::get() );
913+        if ( !m_data.testsOrTags.empty() ) {
914+            m_hasTestFilters = true;
915+            for ( auto const& testOrTags : m_data.testsOrTags ) {
916+                parser.parse( testOrTags );
917+            }
918+        }
919+        m_testSpec = parser.testSpec();
920+
921+
922+        // We now fixup the reporter specs to handle default output spec,
923+        // default colour spec, etc
924+        bool defaultOutputUsed = false;
925+        for ( auto const& reporterSpec : m_data.reporterSpecifications ) {
926+            // We do the default-output check separately, while always
927+            // using the default output below to make the code simpler
928+            // and avoid superfluous copies.
929+            if ( reporterSpec.outputFile().none() ) {
930+                CATCH_ENFORCE( !defaultOutputUsed,
931+                               "Internal error: cannot use default output for "
932+                               "multiple reporters" );
933+                defaultOutputUsed = true;
934+            }
935+
936+            m_processedReporterSpecs.push_back( ProcessedReporterSpec{
937+                reporterSpec.name(),
938+                reporterSpec.outputFile() ? *reporterSpec.outputFile()
939+                                          : data.defaultOutputFilename,
940+                reporterSpec.colourMode().valueOr( data.defaultColourMode ),
941+                reporterSpec.customOptions() } );
942+        }
943+    }
944+
945+    Config::~Config() = default;
946+
947+
948+    bool Config::listTests() const          { return m_data.listTests; }
949+    bool Config::listTags() const           { return m_data.listTags; }
950+    bool Config::listReporters() const      { return m_data.listReporters; }
951+    bool Config::listListeners() const      { return m_data.listListeners; }
952+
953+    std::vector<std::string> const& Config::getTestsOrTags() const { return m_data.testsOrTags; }
954+    std::vector<std::string> const& Config::getSectionsToRun() const { return m_data.sectionsToRun; }
955+
956+    std::vector<ReporterSpec> const& Config::getReporterSpecs() const {
957+        return m_data.reporterSpecifications;
958+    }
959+
960+    std::vector<ProcessedReporterSpec> const&
961+    Config::getProcessedReporterSpecs() const {
962+        return m_processedReporterSpecs;
963+    }
964+
965+    TestSpec const& Config::testSpec() const { return m_testSpec; }
966+    bool Config::hasTestFilters() const { return m_hasTestFilters; }
967+
968+    bool Config::showHelp() const { return m_data.showHelp; }
969+
970+    // IConfig interface
971+    bool Config::allowThrows() const                   { return !m_data.noThrow; }
972+    StringRef Config::name() const { return m_data.name.empty() ? m_data.processName : m_data.name; }
973+    bool Config::includeSuccessfulResults() const      { return m_data.showSuccessfulTests; }
974+    bool Config::warnAboutMissingAssertions() const {
975+        return !!( m_data.warnings & WarnAbout::NoAssertions );
976+    }
977+    bool Config::warnAboutUnmatchedTestSpecs() const {
978+        return !!( m_data.warnings & WarnAbout::UnmatchedTestSpec );
979+    }
980+    bool Config::zeroTestsCountAsSuccess() const       { return m_data.allowZeroTests; }
981+    ShowDurations Config::showDurations() const        { return m_data.showDurations; }
982+    double Config::minDuration() const                 { return m_data.minDuration; }
983+    TestRunOrder Config::runOrder() const              { return m_data.runOrder; }
984+    uint32_t Config::rngSeed() const                   { return m_data.rngSeed; }
985+    unsigned int Config::shardCount() const            { return m_data.shardCount; }
986+    unsigned int Config::shardIndex() const            { return m_data.shardIndex; }
987+    ColourMode Config::defaultColourMode() const       { return m_data.defaultColourMode; }
988+    bool Config::shouldDebugBreak() const              { return m_data.shouldDebugBreak; }
989+    int Config::abortAfter() const                     { return m_data.abortAfter; }
990+    bool Config::showInvisibles() const                { return m_data.showInvisibles; }
991+    Verbosity Config::verbosity() const                { return m_data.verbosity; }
992+
993+    bool Config::skipBenchmarks() const                           { return m_data.skipBenchmarks; }
994+    bool Config::benchmarkNoAnalysis() const                      { return m_data.benchmarkNoAnalysis; }
995+    unsigned int Config::benchmarkSamples() const                 { return m_data.benchmarkSamples; }
996+    double Config::benchmarkConfidenceInterval() const            { return m_data.benchmarkConfidenceInterval; }
997+    unsigned int Config::benchmarkResamples() const               { return m_data.benchmarkResamples; }
998+    std::chrono::milliseconds Config::benchmarkWarmupTime() const { return std::chrono::milliseconds(m_data.benchmarkWarmupTime); }
999+
1000+    void Config::readBazelEnvVars() {
1001+        // Register a JUnit reporter for Bazel. Bazel sets an environment
1002+        // variable with the path to XML output. If this file is written to
1003+        // during test, Bazel will not generate a default XML output.
1004+        // This allows the XML output file to contain higher level of detail
1005+        // than what is possible otherwise.
1006+        const auto bazelOutputFile = Detail::getEnv( "XML_OUTPUT_FILE" );
1007+
1008+        if ( bazelOutputFile ) {
1009+            m_data.reporterSpecifications.push_back(
1010+                { "junit", std::string( bazelOutputFile ), {}, {} } );
1011+        }
1012+
1013+        const auto bazelTestSpec = Detail::getEnv( "TESTBRIDGE_TEST_ONLY" );
1014+        if ( bazelTestSpec ) {
1015+            // Presumably the test spec from environment should overwrite
1016+            // the one we got from CLI (if we got any)
1017+            m_data.testsOrTags.clear();
1018+            m_data.testsOrTags.push_back( bazelTestSpec );
1019+        }
1020+
1021+        const auto bazelShardOptions = readBazelShardingOptions();
1022+        if ( bazelShardOptions ) {
1023+            std::ofstream f( bazelShardOptions->shardFilePath,
1024+                             std::ios_base::out | std::ios_base::trunc );
1025+            if ( f.is_open() ) {
1026+                f << "";
1027+                m_data.shardIndex = bazelShardOptions->shardIndex;
1028+                m_data.shardCount = bazelShardOptions->shardCount;
1029+            }
1030+        }
1031+    }
1032+
1033+} // end namespace Catch
1034+
1035+
1036+
1037+
1038+
1039+namespace Catch {
1040+    std::uint32_t getSeed() {
1041+        return getCurrentContext().getConfig()->rngSeed();
1042+    }
1043+}
1044+
1045+
1046+
1047+#include <cassert>
1048+#include <stack>
1049+
1050+namespace Catch {
1051+
1052+    ////////////////////////////////////////////////////////////////////////////
1053+
1054+
1055+    ScopedMessage::ScopedMessage( MessageBuilder&& builder ):
1056+        m_info( CATCH_MOVE(builder.m_info) ) {
1057+        m_info.message = builder.m_stream.str();
1058+        getResultCapture().pushScopedMessage( m_info );
1059+    }
1060+
1061+    ScopedMessage::ScopedMessage( ScopedMessage&& old ) noexcept:
1062+        m_info( CATCH_MOVE( old.m_info ) ) {
1063+        old.m_moved = true;
1064+    }
1065+
1066+    ScopedMessage::~ScopedMessage() {
1067+        if ( !uncaught_exceptions() && !m_moved ){
1068+            getResultCapture().popScopedMessage(m_info);
1069+        }
1070+    }
1071+
1072+
1073+    Capturer::Capturer( StringRef macroName,
1074+                        SourceLineInfo const& lineInfo,
1075+                        ResultWas::OfType resultType,
1076+                        StringRef names ):
1077+        m_resultCapture( getResultCapture() ) {
1078+        auto trimmed = [&] (size_t start, size_t end) {
1079+            while (names[start] == ',' || isspace(static_cast<unsigned char>(names[start]))) {
1080+                ++start;
1081+            }
1082+            while (names[end] == ',' || isspace(static_cast<unsigned char>(names[end]))) {
1083+                --end;
1084+            }
1085+            return names.substr(start, end - start + 1);
1086+        };
1087+        auto skipq = [&] (size_t start, char quote) {
1088+            for (auto i = start + 1; i < names.size() ; ++i) {
1089+                if (names[i] == quote)
1090+                    return i;
1091+                if (names[i] == '\\')
1092+                    ++i;
1093+            }
1094+            CATCH_INTERNAL_ERROR("CAPTURE parsing encountered unmatched quote");
1095+        };
1096+
1097+        size_t start = 0;
1098+        std::stack<char> openings;
1099+        for (size_t pos = 0; pos < names.size(); ++pos) {
1100+            char c = names[pos];
1101+            switch (c) {
1102+            case '[':
1103+            case '{':
1104+            case '(':
1105+            // It is basically impossible to disambiguate between
1106+            // comparison and start of template args in this context
1107+//            case '<':
1108+                openings.push(c);
1109+                break;
1110+            case ']':
1111+            case '}':
1112+            case ')':
1113+//           case '>':
1114+                openings.pop();
1115+                break;
1116+            case '"':
1117+            case '\'':
1118+                pos = skipq(pos, c);
1119+                break;
1120+            case ',':
1121+                if (start != pos && openings.empty()) {
1122+                    m_messages.emplace_back(macroName, lineInfo, resultType);
1123+                    m_messages.back().message = static_cast<std::string>(trimmed(start, pos));
1124+                    m_messages.back().message += " := ";
1125+                    start = pos;
1126+                }
1127+            default:; // noop
1128+            }
1129+        }
1130+        assert(openings.empty() && "Mismatched openings");
1131+        m_messages.emplace_back(macroName, lineInfo, resultType);
1132+        m_messages.back().message = static_cast<std::string>(trimmed(start, names.size() - 1));
1133+        m_messages.back().message += " := ";
1134+    }
1135+    Capturer::~Capturer() {
1136+        if ( !uncaught_exceptions() ){
1137+            assert( m_captured == m_messages.size() );
1138+            for( size_t i = 0; i < m_captured; ++i  )
1139+                m_resultCapture.popScopedMessage( m_messages[i] );
1140+        }
1141+    }
1142+
1143+    void Capturer::captureValue( size_t index, std::string const& value ) {
1144+        assert( index < m_messages.size() );
1145+        m_messages[index].message += value;
1146+        m_resultCapture.pushScopedMessage( m_messages[index] );
1147+        m_captured++;
1148+    }
1149+
1150+} // end namespace Catch
1151+
1152+
1153+
1154+
1155+#include <exception>
1156+
1157+namespace Catch {
1158+
1159+    namespace {
1160+
1161+        class RegistryHub : public IRegistryHub,
1162+                            public IMutableRegistryHub,
1163+                            private Detail::NonCopyable {
1164+
1165+        public: // IRegistryHub
1166+            RegistryHub() = default;
1167+            ReporterRegistry const& getReporterRegistry() const override {
1168+                return m_reporterRegistry;
1169+            }
1170+            ITestCaseRegistry const& getTestCaseRegistry() const override {
1171+                return m_testCaseRegistry;
1172+            }
1173+            IExceptionTranslatorRegistry const& getExceptionTranslatorRegistry() const override {
1174+                return m_exceptionTranslatorRegistry;
1175+            }
1176+            ITagAliasRegistry const& getTagAliasRegistry() const override {
1177+                return m_tagAliasRegistry;
1178+            }
1179+            StartupExceptionRegistry const& getStartupExceptionRegistry() const override {
1180+                return m_exceptionRegistry;
1181+            }
1182+
1183+        public: // IMutableRegistryHub
1184+            void registerReporter( std::string const& name, IReporterFactoryPtr factory ) override {
1185+                m_reporterRegistry.registerReporter( name, CATCH_MOVE(factory) );
1186+            }
1187+            void registerListener( Detail::unique_ptr<EventListenerFactory> factory ) override {
1188+                m_reporterRegistry.registerListener( CATCH_MOVE(factory) );
1189+            }
1190+            void registerTest( Detail::unique_ptr<TestCaseInfo>&& testInfo, Detail::unique_ptr<ITestInvoker>&& invoker ) override {
1191+                m_testCaseRegistry.registerTest( CATCH_MOVE(testInfo), CATCH_MOVE(invoker) );
1192+            }
1193+            void registerTranslator( Detail::unique_ptr<IExceptionTranslator>&& translator ) override {
1194+                m_exceptionTranslatorRegistry.registerTranslator( CATCH_MOVE(translator) );
1195+            }
1196+            void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) override {
1197+                m_tagAliasRegistry.add( alias, tag, lineInfo );
1198+            }
1199+            void registerStartupException() noexcept override {
1200+#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
1201+                m_exceptionRegistry.add(std::current_exception());
1202+#else
1203+                CATCH_INTERNAL_ERROR("Attempted to register active exception under CATCH_CONFIG_DISABLE_EXCEPTIONS!");
1204+#endif
1205+            }
1206+            IMutableEnumValuesRegistry& getMutableEnumValuesRegistry() override {
1207+                return m_enumValuesRegistry;
1208+            }
1209+
1210+        private:
1211+            TestRegistry m_testCaseRegistry;
1212+            ReporterRegistry m_reporterRegistry;
1213+            ExceptionTranslatorRegistry m_exceptionTranslatorRegistry;
1214+            TagAliasRegistry m_tagAliasRegistry;
1215+            StartupExceptionRegistry m_exceptionRegistry;
1216+            Detail::EnumValuesRegistry m_enumValuesRegistry;
1217+        };
1218+    }
1219+
1220+    using RegistryHubSingleton = Singleton<RegistryHub, IRegistryHub, IMutableRegistryHub>;
1221+
1222+    IRegistryHub const& getRegistryHub() {
1223+        return RegistryHubSingleton::get();
1224+    }
1225+    IMutableRegistryHub& getMutableRegistryHub() {
1226+        return RegistryHubSingleton::getMutable();
1227+    }
1228+    void cleanUp() {
1229+        cleanupSingletons();
1230+        cleanUpContext();
1231+    }
1232+    std::string translateActiveException() {
1233+        return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException();
1234+    }
1235+
1236+
1237+} // end namespace Catch
1238+
1239+
1240+
1241+#include <algorithm>
1242+#include <cassert>
1243+#include <exception>
1244+#include <iomanip>
1245+#include <set>
1246+
1247+namespace Catch {
1248+
1249+    namespace {
1250+        const int MaxExitCode = 255;
1251+
1252+        IEventListenerPtr createReporter(std::string const& reporterName, ReporterConfig&& config) {
1253+            auto reporter = Catch::getRegistryHub().getReporterRegistry().create(reporterName, CATCH_MOVE(config));
1254+            CATCH_ENFORCE(reporter, "No reporter registered with name: '" << reporterName << '\'');
1255+
1256+            return reporter;
1257+        }
1258+
1259+        IEventListenerPtr prepareReporters(Config const* config) {
1260+            if (Catch::getRegistryHub().getReporterRegistry().getListeners().empty()
1261+                    && config->getProcessedReporterSpecs().size() == 1) {
1262+                auto const& spec = config->getProcessedReporterSpecs()[0];
1263+                return createReporter(
1264+                    spec.name,
1265+                    ReporterConfig( config,
1266+                                    makeStream( spec.outputFilename ),
1267+                                    spec.colourMode,
1268+                                    spec.customOptions ) );
1269+            }
1270+
1271+            auto multi = Detail::make_unique<MultiReporter>(config);
1272+
1273+            auto const& listeners = Catch::getRegistryHub().getReporterRegistry().getListeners();
1274+            for (auto const& listener : listeners) {
1275+                multi->addListener(listener->create(config));
1276+            }
1277+
1278+            for ( auto const& reporterSpec : config->getProcessedReporterSpecs() ) {
1279+                multi->addReporter( createReporter(
1280+                    reporterSpec.name,
1281+                    ReporterConfig( config,
1282+                                    makeStream( reporterSpec.outputFilename ),
1283+                                    reporterSpec.colourMode,
1284+                                    reporterSpec.customOptions ) ) );
1285+            }
1286+
1287+            return multi;
1288+        }
1289+
1290+        class TestGroup {
1291+        public:
1292+            explicit TestGroup(IEventListenerPtr&& reporter, Config const* config):
1293+                m_reporter(reporter.get()),
1294+                m_config{config},
1295+                m_context{config, CATCH_MOVE(reporter)} {
1296+
1297+                assert( m_config->testSpec().getInvalidSpecs().empty() &&
1298+                        "Invalid test specs should be handled before running tests" );
1299+
1300+                auto const& allTestCases = getAllTestCasesSorted(*m_config);
1301+                auto const& testSpec = m_config->testSpec();
1302+                if ( !testSpec.hasFilters() ) {
1303+                    for ( auto const& test : allTestCases ) {
1304+                        if ( !test.getTestCaseInfo().isHidden() ) {
1305+                            m_tests.emplace( &test );
1306+                        }
1307+                    }
1308+                } else {
1309+                    m_matches =
1310+                        testSpec.matchesByFilter( allTestCases, *m_config );
1311+                    for ( auto const& match : m_matches ) {
1312+                        m_tests.insert( match.tests.begin(),
1313+                                        match.tests.end() );
1314+                    }
1315+                }
1316+
1317+                m_tests = createShard(m_tests, m_config->shardCount(), m_config->shardIndex());
1318+            }
1319+
1320+            Totals execute() {
1321+                Totals totals;
1322+                for (auto const& testCase : m_tests) {
1323+                    if (!m_context.aborting())
1324+                        totals += m_context.runTest(*testCase);
1325+                    else
1326+                        m_reporter->skipTest(testCase->getTestCaseInfo());
1327+                }
1328+
1329+                for (auto const& match : m_matches) {
1330+                    if (match.tests.empty()) {
1331+                        m_unmatchedTestSpecs = true;
1332+                        m_reporter->noMatchingTestCases( match.name );
1333+                    }
1334+                }
1335+
1336+                return totals;
1337+            }
1338+
1339+            bool hadUnmatchedTestSpecs() const {
1340+                return m_unmatchedTestSpecs;
1341+            }
1342+
1343+
1344+        private:
1345+            IEventListener* m_reporter;
1346+            Config const* m_config;
1347+            RunContext m_context;
1348+            std::set<TestCaseHandle const*> m_tests;
1349+            TestSpec::Matches m_matches;
1350+            bool m_unmatchedTestSpecs = false;
1351+        };
1352+
1353+        void applyFilenamesAsTags() {
1354+            for (auto const& testInfo : getRegistryHub().getTestCaseRegistry().getAllInfos()) {
1355+                testInfo->addFilenameTag();
1356+            }
1357+        }
1358+
1359+    } // anon namespace
1360+
1361+    Session::Session() {
1362+        static bool alreadyInstantiated = false;
1363+        if( alreadyInstantiated ) {
1364+            CATCH_TRY { CATCH_INTERNAL_ERROR( "Only one instance of Catch::Session can ever be used" ); }
1365+            CATCH_CATCH_ALL { getMutableRegistryHub().registerStartupException(); }
1366+        }
1367+
1368+        // There cannot be exceptions at startup in no-exception mode.
1369+#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
1370+        const auto& exceptions = getRegistryHub().getStartupExceptionRegistry().getExceptions();
1371+        if ( !exceptions.empty() ) {
1372+            config();
1373+            getCurrentMutableContext().setConfig(m_config.get());
1374+
1375+            m_startupExceptions = true;
1376+            auto errStream = makeStream( "%stderr" );
1377+            auto colourImpl = makeColourImpl(
1378+                ColourMode::PlatformDefault, errStream.get() );
1379+            auto guard = colourImpl->guardColour( Colour::Red );
1380+            errStream->stream() << "Errors occurred during startup!" << '\n';
1381+            // iterate over all exceptions and notify user
1382+            for ( const auto& ex_ptr : exceptions ) {
1383+                try {
1384+                    std::rethrow_exception(ex_ptr);
1385+                } catch ( std::exception const& ex ) {
1386+                    errStream->stream() << TextFlow::Column( ex.what() ).indent(2) << '\n';
1387+                }
1388+            }
1389+        }
1390+#endif
1391+
1392+        alreadyInstantiated = true;
1393+        m_cli = makeCommandLineParser( m_configData );
1394+    }
1395+    Session::~Session() {
1396+        Catch::cleanUp();
1397+    }
1398+
1399+    void Session::showHelp() const {
1400+        Catch::cout()
1401+                << "\nCatch2 v" << libraryVersion() << '\n'
1402+                << m_cli << '\n'
1403+                << "For more detailed usage please see the project docs\n\n" << std::flush;
1404+    }
1405+    void Session::libIdentify() {
1406+        Catch::cout()
1407+                << std::left << std::setw(16) << "description: " << "A Catch2 test executable\n"
1408+                << std::left << std::setw(16) << "category: " << "testframework\n"
1409+                << std::left << std::setw(16) << "framework: " << "Catch2\n"
1410+                << std::left << std::setw(16) << "version: " << libraryVersion() << '\n' << std::flush;
1411+    }
1412+
1413+    int Session::applyCommandLine( int argc, char const * const * argv ) {
1414+        if( m_startupExceptions )
1415+            return 1;
1416+
1417+        auto result = m_cli.parse( Clara::Args( argc, argv ) );
1418+
1419+        if( !result ) {
1420+            config();
1421+            getCurrentMutableContext().setConfig(m_config.get());
1422+            auto errStream = makeStream( "%stderr" );
1423+            auto colour = makeColourImpl( ColourMode::PlatformDefault, errStream.get() );
1424+
1425+            errStream->stream()
1426+                << colour->guardColour( Colour::Red )
1427+                << "\nError(s) in input:\n"
1428+                << TextFlow::Column( result.errorMessage() ).indent( 2 )
1429+                << "\n\n";
1430+            errStream->stream() << "Run with -? for usage\n\n" << std::flush;
1431+            return MaxExitCode;
1432+        }
1433+
1434+        if( m_configData.showHelp )
1435+            showHelp();
1436+        if( m_configData.libIdentify )
1437+            libIdentify();
1438+
1439+        m_config.reset();
1440+        return 0;
1441+    }
1442+
1443+#if defined(CATCH_CONFIG_WCHAR) && defined(_WIN32) && defined(UNICODE)
1444+    int Session::applyCommandLine( int argc, wchar_t const * const * argv ) {
1445+
1446+        char **utf8Argv = new char *[ argc ];
1447+
1448+        for ( int i = 0; i < argc; ++i ) {
1449+            int bufSize = WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, nullptr, 0, nullptr, nullptr );
1450+
1451+            utf8Argv[ i ] = new char[ bufSize ];
1452+
1453+            WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, utf8Argv[i], bufSize, nullptr, nullptr );
1454+        }
1455+
1456+        int returnCode = applyCommandLine( argc, utf8Argv );
1457+
1458+        for ( int i = 0; i < argc; ++i )
1459+            delete [] utf8Argv[ i ];
1460+
1461+        delete [] utf8Argv;
1462+
1463+        return returnCode;
1464+    }
1465+#endif
1466+
1467+    void Session::useConfigData( ConfigData const& configData ) {
1468+        m_configData = configData;
1469+        m_config.reset();
1470+    }
1471+
1472+    int Session::run() {
1473+        if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeStart ) != 0 ) {
1474+            Catch::cout() << "...waiting for enter/ return before starting\n" << std::flush;
1475+            static_cast<void>(std::getchar());
1476+        }
1477+        int exitCode = runInternal();
1478+        if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeExit ) != 0 ) {
1479+            Catch::cout() << "...waiting for enter/ return before exiting, with code: " << exitCode << '\n' << std::flush;
1480+            static_cast<void>(std::getchar());
1481+        }
1482+        return exitCode;
1483+    }
1484+
1485+    Clara::Parser const& Session::cli() const {
1486+        return m_cli;
1487+    }
1488+    void Session::cli( Clara::Parser const& newParser ) {
1489+        m_cli = newParser;
1490+    }
1491+    ConfigData& Session::configData() {
1492+        return m_configData;
1493+    }
1494+    Config& Session::config() {
1495+        if( !m_config )
1496+            m_config = Detail::make_unique<Config>( m_configData );
1497+        return *m_config;
1498+    }
1499+
1500+    int Session::runInternal() {
1501+        if( m_startupExceptions )
1502+            return 1;
1503+
1504+        if (m_configData.showHelp || m_configData.libIdentify) {
1505+            return 0;
1506+        }
1507+
1508+        if ( m_configData.shardIndex >= m_configData.shardCount ) {
1509+            Catch::cerr() << "The shard count (" << m_configData.shardCount
1510+                          << ") must be greater than the shard index ("
1511+                          << m_configData.shardIndex << ")\n"
1512+                          << std::flush;
1513+            return 1;
1514+        }
1515+
1516+        CATCH_TRY {
1517+            config(); // Force config to be constructed
1518+
1519+            seedRng( *m_config );
1520+
1521+            if (m_configData.filenamesAsTags) {
1522+                applyFilenamesAsTags();
1523+            }
1524+
1525+            // Set up global config instance before we start calling into other functions
1526+            getCurrentMutableContext().setConfig(m_config.get());
1527+
1528+            // Create reporter(s) so we can route listings through them
1529+            auto reporter = prepareReporters(m_config.get());
1530+
1531+            auto const& invalidSpecs = m_config->testSpec().getInvalidSpecs();
1532+            if ( !invalidSpecs.empty() ) {
1533+                for ( auto const& spec : invalidSpecs ) {
1534+                    reporter->reportInvalidTestSpec( spec );
1535+                }
1536+                return 1;
1537+            }
1538+
1539+
1540+            // Handle list request
1541+            if (list(*reporter, *m_config)) {
1542+                return 0;
1543+            }
1544+
1545+            TestGroup tests { CATCH_MOVE(reporter), m_config.get() };
1546+            auto const totals = tests.execute();
1547+
1548+            if ( tests.hadUnmatchedTestSpecs()
1549+                && m_config->warnAboutUnmatchedTestSpecs() ) {
1550+                return 3;
1551+            }
1552+
1553+            if ( totals.testCases.total() == 0
1554+                && !m_config->zeroTestsCountAsSuccess() ) {
1555+                return 2;
1556+            }
1557+
1558+            if ( totals.testCases.total() > 0 &&
1559+                 totals.testCases.total() == totals.testCases.skipped
1560+                && !m_config->zeroTestsCountAsSuccess() ) {
1561+                return 4;
1562+            }
1563+
1564+            // Note that on unices only the lower 8 bits are usually used, clamping
1565+            // the return value to 255 prevents false negative when some multiple
1566+            // of 256 tests has failed
1567+            return (std::min) (MaxExitCode, static_cast<int>(totals.assertions.failed));
1568+        }
1569+#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
1570+        catch( std::exception& ex ) {
1571+            Catch::cerr() << ex.what() << '\n' << std::flush;
1572+            return MaxExitCode;
1573+        }
1574+#endif
1575+    }
1576+
1577+} // end namespace Catch
1578+
1579+
1580+
1581+
1582+namespace Catch {
1583+
1584+    RegistrarForTagAliases::RegistrarForTagAliases(char const* alias, char const* tag, SourceLineInfo const& lineInfo) {
1585+        CATCH_TRY {
1586+            getMutableRegistryHub().registerTagAlias(alias, tag, lineInfo);
1587+        } CATCH_CATCH_ALL {
1588+            // Do not throw when constructing global objects, instead register the exception to be processed later
1589+            getMutableRegistryHub().registerStartupException();
1590+        }
1591+    }
1592+
1593+}
1594+
1595+
1596+
1597+#include <cassert>
1598+#include <cctype>
1599+#include <algorithm>
1600+
1601+namespace Catch {
1602+
1603+    namespace {
1604+        using TCP_underlying_type = uint8_t;
1605+        static_assert(sizeof(TestCaseProperties) == sizeof(TCP_underlying_type),
1606+                      "The size of the TestCaseProperties is different from the assumed size");
1607+
1608+        TestCaseProperties operator|(TestCaseProperties lhs, TestCaseProperties rhs) {
1609+            return static_cast<TestCaseProperties>(
1610+                static_cast<TCP_underlying_type>(lhs) | static_cast<TCP_underlying_type>(rhs)
1611+            );
1612+        }
1613+
1614+        TestCaseProperties& operator|=(TestCaseProperties& lhs, TestCaseProperties rhs) {
1615+            lhs = static_cast<TestCaseProperties>(
1616+                static_cast<TCP_underlying_type>(lhs) | static_cast<TCP_underlying_type>(rhs)
1617+            );
1618+            return lhs;
1619+        }
1620+
1621+        TestCaseProperties operator&(TestCaseProperties lhs, TestCaseProperties rhs) {
1622+            return static_cast<TestCaseProperties>(
1623+                static_cast<TCP_underlying_type>(lhs) & static_cast<TCP_underlying_type>(rhs)
1624+            );
1625+        }
1626+
1627+        bool applies(TestCaseProperties tcp) {
1628+            static_assert(static_cast<TCP_underlying_type>(TestCaseProperties::None) == 0,
1629+                          "TestCaseProperties::None must be equal to 0");
1630+            return tcp != TestCaseProperties::None;
1631+        }
1632+
1633+        TestCaseProperties parseSpecialTag( StringRef tag ) {
1634+            if( !tag.empty() && tag[0] == '.' )
1635+                return TestCaseProperties::IsHidden;
1636+            else if( tag == "!throws"_sr )
1637+                return TestCaseProperties::Throws;
1638+            else if( tag == "!shouldfail"_sr )
1639+                return TestCaseProperties::ShouldFail;
1640+            else if( tag == "!mayfail"_sr )
1641+                return TestCaseProperties::MayFail;
1642+            else if( tag == "!nonportable"_sr )
1643+                return TestCaseProperties::NonPortable;
1644+            else if( tag == "!benchmark"_sr )
1645+                return TestCaseProperties::Benchmark | TestCaseProperties::IsHidden;
1646+            else
1647+                return TestCaseProperties::None;
1648+        }
1649+        bool isReservedTag( StringRef tag ) {
1650+            return parseSpecialTag( tag ) == TestCaseProperties::None
1651+                && tag.size() > 0
1652+                && !std::isalnum( static_cast<unsigned char>(tag[0]) );
1653+        }
1654+        void enforceNotReservedTag( StringRef tag, SourceLineInfo const& _lineInfo ) {
1655+            CATCH_ENFORCE( !isReservedTag(tag),
1656+                          "Tag name: [" << tag << "] is not allowed.\n"
1657+                          << "Tag names starting with non alphanumeric characters are reserved\n"
1658+                          << _lineInfo );
1659+        }
1660+
1661+        std::string makeDefaultName() {
1662+            static size_t counter = 0;
1663+            return "Anonymous test case " + std::to_string(++counter);
1664+        }
1665+
1666+        StringRef extractFilenamePart(StringRef filename) {
1667+            size_t lastDot = filename.size();
1668+            while (lastDot > 0 && filename[lastDot - 1] != '.') {
1669+                --lastDot;
1670+            }
1671+            // In theory we could have filename without any extension in it
1672+            if ( lastDot == 0 ) { return StringRef(); }
1673+
1674+            --lastDot;
1675+            size_t nameStart = lastDot;
1676+            while (nameStart > 0 && filename[nameStart - 1] != '/' && filename[nameStart - 1] != '\\') {
1677+                --nameStart;
1678+            }
1679+
1680+            return filename.substr(nameStart, lastDot - nameStart);
1681+        }
1682+
1683+        // Returns the upper bound on size of extra tags ([#file]+[.])
1684+        size_t sizeOfExtraTags(StringRef filepath) {
1685+            // [.] is 3, [#] is another 3
1686+            const size_t extras = 3 + 3;
1687+            return extractFilenamePart(filepath).size() + extras;
1688+        }
1689+    } // end unnamed namespace
1690+
1691+    bool operator<(  Tag const& lhs, Tag const& rhs ) {
1692+        Detail::CaseInsensitiveLess cmp;
1693+        return cmp( lhs.original, rhs.original );
1694+    }
1695+    bool operator==( Tag const& lhs, Tag const& rhs ) {
1696+        Detail::CaseInsensitiveEqualTo cmp;
1697+        return cmp( lhs.original, rhs.original );
1698+    }
1699+
1700+    Detail::unique_ptr<TestCaseInfo>
1701+        makeTestCaseInfo(StringRef _className,
1702+                         NameAndTags const& nameAndTags,
1703+                         SourceLineInfo const& _lineInfo ) {
1704+        return Detail::make_unique<TestCaseInfo>(_className, nameAndTags, _lineInfo);
1705+    }
1706+
1707+    TestCaseInfo::TestCaseInfo(StringRef _className,
1708+                               NameAndTags const& _nameAndTags,
1709+                               SourceLineInfo const& _lineInfo):
1710+        name( _nameAndTags.name.empty() ? makeDefaultName() : _nameAndTags.name ),
1711+        className( _className ),
1712+        lineInfo( _lineInfo )
1713+    {
1714+        StringRef originalTags = _nameAndTags.tags;
1715+        // We need to reserve enough space to store all of the tags
1716+        // (including optional hidden tag and filename tag)
1717+        auto requiredSize = originalTags.size() + sizeOfExtraTags(_lineInfo.file);
1718+        backingTags.reserve(requiredSize);
1719+
1720+        // We cannot copy the tags directly, as we need to normalize
1721+        // some tags, so that [.foo] is copied as [.][foo].
1722+        size_t tagStart = 0;
1723+        size_t tagEnd = 0;
1724+        bool inTag = false;
1725+        for (size_t idx = 0; idx < originalTags.size(); ++idx) {
1726+            auto c = originalTags[idx];
1727+            if (c == '[') {
1728+                CATCH_ENFORCE(
1729+                    !inTag,
1730+                    "Found '[' inside a tag while registering test case '"
1731+                        << _nameAndTags.name << "' at " << _lineInfo );
1732+
1733+                inTag = true;
1734+                tagStart = idx;
1735+            }
1736+            if (c == ']') {
1737+                CATCH_ENFORCE(
1738+                    inTag,
1739+                    "Found unmatched ']' while registering test case '"
1740+                        << _nameAndTags.name << "' at " << _lineInfo );
1741+
1742+                inTag = false;
1743+                tagEnd = idx;
1744+                assert(tagStart < tagEnd);
1745+
1746+                // We need to check the tag for special meanings, copy
1747+                // it over to backing storage and actually reference the
1748+                // backing storage in the saved tags
1749+                StringRef tagStr = originalTags.substr(tagStart+1, tagEnd - tagStart - 1);
1750+                CATCH_ENFORCE( !tagStr.empty(),
1751+                               "Found an empty tag while registering test case '"
1752+                                   << _nameAndTags.name << "' at "
1753+                                   << _lineInfo );
1754+
1755+                enforceNotReservedTag(tagStr, lineInfo);
1756+                properties |= parseSpecialTag(tagStr);
1757+                // When copying a tag to the backing storage, we need to
1758+                // check if it is a merged hide tag, such as [.foo], and
1759+                // if it is, we need to handle it as if it was [foo].
1760+                if (tagStr.size() > 1 && tagStr[0] == '.') {
1761+                    tagStr = tagStr.substr(1, tagStr.size() - 1);
1762+                }
1763+                // We skip over dealing with the [.] tag, as we will add
1764+                // it later unconditionally and then sort and unique all
1765+                // the tags.
1766+                internalAppendTag(tagStr);
1767+            }
1768+        }
1769+        CATCH_ENFORCE( !inTag,
1770+                       "Found an unclosed tag while registering test case '"
1771+                           << _nameAndTags.name << "' at " << _lineInfo );
1772+
1773+
1774+        // Add [.] if relevant
1775+        if (isHidden()) {
1776+            internalAppendTag("."_sr);
1777+        }
1778+
1779+        // Sort and prepare tags
1780+        std::sort(begin(tags), end(tags));
1781+        tags.erase(std::unique(begin(tags), end(tags)),
1782+                   end(tags));
1783+    }
1784+
1785+    bool TestCaseInfo::isHidden() const {
1786+        return applies( properties & TestCaseProperties::IsHidden );
1787+    }
1788+    bool TestCaseInfo::throws() const {
1789+        return applies( properties & TestCaseProperties::Throws );
1790+    }
1791+    bool TestCaseInfo::okToFail() const {
1792+        return applies( properties & (TestCaseProperties::ShouldFail | TestCaseProperties::MayFail ) );
1793+    }
1794+    bool TestCaseInfo::expectedToFail() const {
1795+        return applies( properties & (TestCaseProperties::ShouldFail) );
1796+    }
1797+
1798+    void TestCaseInfo::addFilenameTag() {
1799+        std::string combined("#");
1800+        combined += extractFilenamePart(lineInfo.file);
1801+        internalAppendTag(combined);
1802+    }
1803+
1804+    std::string TestCaseInfo::tagsAsString() const {
1805+        std::string ret;
1806+        // '[' and ']' per tag
1807+        std::size_t full_size = 2 * tags.size();
1808+        for (const auto& tag : tags) {
1809+            full_size += tag.original.size();
1810+        }
1811+        ret.reserve(full_size);
1812+        for (const auto& tag : tags) {
1813+            ret.push_back('[');
1814+            ret += tag.original;
1815+            ret.push_back(']');
1816+        }
1817+
1818+        return ret;
1819+    }
1820+
1821+    void TestCaseInfo::internalAppendTag(StringRef tagStr) {
1822+        backingTags += '[';
1823+        const auto backingStart = backingTags.size();
1824+        backingTags += tagStr;
1825+        const auto backingEnd = backingTags.size();
1826+        backingTags += ']';
1827+        tags.emplace_back(StringRef(backingTags.c_str() + backingStart, backingEnd - backingStart));
1828+    }
1829+
1830+    bool operator<( TestCaseInfo const& lhs, TestCaseInfo const& rhs ) {
1831+        // We want to avoid redoing the string comparisons multiple times,
1832+        // so we store the result of a three-way comparison before using
1833+        // it in the actual comparison logic.
1834+        const auto cmpName = lhs.name.compare( rhs.name );
1835+        if ( cmpName != 0 ) {
1836+            return cmpName < 0;
1837+        }
1838+        const auto cmpClassName = lhs.className.compare( rhs.className );
1839+        if ( cmpClassName != 0 ) {
1840+            return cmpClassName < 0;
1841+        }
1842+        return lhs.tags < rhs.tags;
1843+    }
1844+
1845+    TestCaseInfo const& TestCaseHandle::getTestCaseInfo() const {
1846+        return *m_info;
1847+    }
1848+
1849+} // end namespace Catch
1850+
1851+
1852+
1853+#include <algorithm>
1854+#include <string>
1855+#include <vector>
1856+#include <ostream>
1857+
1858+namespace Catch {
1859+
1860+    TestSpec::Pattern::Pattern( std::string const& name )
1861+    : m_name( name )
1862+    {}
1863+
1864+    TestSpec::Pattern::~Pattern() = default;
1865+
1866+    std::string const& TestSpec::Pattern::name() const {
1867+        return m_name;
1868+    }
1869+
1870+
1871+    TestSpec::NamePattern::NamePattern( std::string const& name, std::string const& filterString )
1872+    : Pattern( filterString )
1873+    , m_wildcardPattern( toLower( name ), CaseSensitive::No )
1874+    {}
1875+
1876+    bool TestSpec::NamePattern::matches( TestCaseInfo const& testCase ) const {
1877+        return m_wildcardPattern.matches( testCase.name );
1878+    }
1879+
1880+    void TestSpec::NamePattern::serializeTo( std::ostream& out ) const {
1881+        out << '"' << name() << '"';
1882+    }
1883+
1884+
1885+    TestSpec::TagPattern::TagPattern( std::string const& tag, std::string const& filterString )
1886+    : Pattern( filterString )
1887+    , m_tag( tag )
1888+    {}
1889+
1890+    bool TestSpec::TagPattern::matches( TestCaseInfo const& testCase ) const {
1891+        return std::find( begin( testCase.tags ),
1892+                          end( testCase.tags ),
1893+                          Tag( m_tag ) ) != end( testCase.tags );
1894+    }
1895+
1896+    void TestSpec::TagPattern::serializeTo( std::ostream& out ) const {
1897+        out << name();
1898+    }
1899+
1900+    bool TestSpec::Filter::matches( TestCaseInfo const& testCase ) const {
1901+        bool should_use = !testCase.isHidden();
1902+        for (auto const& pattern : m_required) {
1903+            should_use = true;
1904+            if (!pattern->matches(testCase)) {
1905+                return false;
1906+            }
1907+        }
1908+        for (auto const& pattern : m_forbidden) {
1909+            if (pattern->matches(testCase)) {
1910+                return false;
1911+            }
1912+        }
1913+        return should_use;
1914+    }
1915+
1916+    void TestSpec::Filter::serializeTo( std::ostream& out ) const {
1917+        bool first = true;
1918+        for ( auto const& pattern : m_required ) {
1919+            if ( !first ) {
1920+                out << ' ';
1921+            }
1922+            out << *pattern;
1923+            first = false;
1924+        }
1925+        for ( auto const& pattern : m_forbidden ) {
1926+            if ( !first ) {
1927+                out << ' ';
1928+            }
1929+            out << *pattern;
1930+            first = false;
1931+        }
1932+    }
1933+
1934+
1935+    std::string TestSpec::extractFilterName( Filter const& filter ) {
1936+        Catch::ReusableStringStream sstr;
1937+        sstr << filter;
1938+        return sstr.str();
1939+    }
1940+
1941+    bool TestSpec::hasFilters() const {
1942+        return !m_filters.empty();
1943+    }
1944+
1945+    bool TestSpec::matches( TestCaseInfo const& testCase ) const {
1946+        return std::any_of( m_filters.begin(), m_filters.end(), [&]( Filter const& f ){ return f.matches( testCase ); } );
1947+    }
1948+
1949+    TestSpec::Matches TestSpec::matchesByFilter( std::vector<TestCaseHandle> const& testCases, IConfig const& config ) const {
1950+        Matches matches;
1951+        matches.reserve( m_filters.size() );
1952+        for ( auto const& filter : m_filters ) {
1953+            std::vector<TestCaseHandle const*> currentMatches;
1954+            for ( auto const& test : testCases )
1955+                if ( isThrowSafe( test, config ) &&
1956+                     filter.matches( test.getTestCaseInfo() ) )
1957+                    currentMatches.emplace_back( &test );
1958+            matches.push_back(
1959+                FilterMatch{ extractFilterName( filter ), currentMatches } );
1960+        }
1961+        return matches;
1962+    }
1963+
1964+    const TestSpec::vectorStrings& TestSpec::getInvalidSpecs() const {
1965+        return m_invalidSpecs;
1966+    }
1967+
1968+    void TestSpec::serializeTo( std::ostream& out ) const {
1969+        bool first = true;
1970+        for ( auto const& filter : m_filters ) {
1971+            if ( !first ) {
1972+                out << ',';
1973+            }
1974+            out << filter;
1975+            first = false;
1976+        }
1977+    }
1978+
1979+}
1980+
1981+
1982+
1983+#include <chrono>
1984+
1985+namespace Catch {
1986+
1987+    namespace {
1988+        static auto getCurrentNanosecondsSinceEpoch() -> uint64_t {
1989+            return std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now().time_since_epoch()).count();
1990+        }
1991+    } // end unnamed namespace
1992+
1993+    void Timer::start() {
1994+       m_nanoseconds = getCurrentNanosecondsSinceEpoch();
1995+    }
1996+    auto Timer::getElapsedNanoseconds() const -> uint64_t {
1997+        return getCurrentNanosecondsSinceEpoch() - m_nanoseconds;
1998+    }
1999+    auto Timer::getElapsedMicroseconds() const -> uint64_t {
2000+        return getElapsedNanoseconds()/1000;
2001+    }
2002+    auto Timer::getElapsedMilliseconds() const -> unsigned int {
2003+        return static_cast<unsigned int>(getElapsedMicroseconds()/1000);
2004+    }
2005+    auto Timer::getElapsedSeconds() const -> double {
2006+        return getElapsedMicroseconds()/1000000.0;
2007+    }
2008+
2009+
2010+} // namespace Catch
2011+
2012+
2013+
2014+
2015+#include <cmath>
2016+#include <iomanip>
2017+
2018+namespace Catch {
2019+
2020+namespace Detail {
2021+
2022+    namespace {
2023+        const int hexThreshold = 255;
2024+
2025+        struct Endianness {
2026+            enum Arch { Big, Little };
2027+
2028+            static Arch which() {
2029+                int one = 1;
2030+                // If the lowest byte we read is non-zero, we can assume
2031+                // that little endian format is used.
2032+                auto value = *reinterpret_cast<char*>(&one);
2033+                return value ? Little : Big;
2034+            }
2035+        };
2036+
2037+        template<typename T>
2038+        std::string fpToString(T value, int precision) {
2039+            if (Catch::isnan(value)) {
2040+                return "nan";
2041+            }
2042+
2043+            ReusableStringStream rss;
2044+            rss << std::setprecision(precision)
2045+                << std::fixed
2046+                << value;
2047+            std::string d = rss.str();
2048+            std::size_t i = d.find_last_not_of('0');
2049+            if (i != std::string::npos && i != d.size() - 1) {
2050+                if (d[i] == '.')
2051+                    i++;
2052+                d = d.substr(0, i + 1);
2053+            }
2054+            return d;
2055+        }
2056+    } // end unnamed namespace
2057+
2058+    std::string convertIntoString(StringRef string, bool escapeInvisibles) {
2059+        std::string ret;
2060+        // This is enough for the "don't escape invisibles" case, and a good
2061+        // lower bound on the "escape invisibles" case.
2062+        ret.reserve(string.size() + 2);
2063+
2064+        if (!escapeInvisibles) {
2065+            ret += '"';
2066+            ret += string;
2067+            ret += '"';
2068+            return ret;
2069+        }
2070+
2071+        ret += '"';
2072+        for (char c : string) {
2073+            switch (c) {
2074+            case '\r':
2075+                ret.append("\\r");
2076+                break;
2077+            case '\n':
2078+                ret.append("\\n");
2079+                break;
2080+            case '\t':
2081+                ret.append("\\t");
2082+                break;
2083+            case '\f':
2084+                ret.append("\\f");
2085+                break;
2086+            default:
2087+                ret.push_back(c);
2088+                break;
2089+            }
2090+        }
2091+        ret += '"';
2092+
2093+        return ret;
2094+    }
2095+
2096+    std::string convertIntoString(StringRef string) {
2097+        return convertIntoString(string, getCurrentContext().getConfig()->showInvisibles());
2098+    }
2099+
2100+    std::string rawMemoryToString( const void *object, std::size_t size ) {
2101+        // Reverse order for little endian architectures
2102+        int i = 0, end = static_cast<int>( size ), inc = 1;
2103+        if( Endianness::which() == Endianness::Little ) {
2104+            i = end-1;
2105+            end = inc = -1;
2106+        }
2107+
2108+        unsigned char const *bytes = static_cast<unsigned char const *>(object);
2109+        ReusableStringStream rss;
2110+        rss << "0x" << std::setfill('0') << std::hex;
2111+        for( ; i != end; i += inc )
2112+             rss << std::setw(2) << static_cast<unsigned>(bytes[i]);
2113+       return rss.str();
2114+    }
2115+} // end Detail namespace
2116+
2117+
2118+
2119+//// ======================================================= ////
2120+//
2121+//   Out-of-line defs for full specialization of StringMaker
2122+//
2123+//// ======================================================= ////
2124+
2125+std::string StringMaker<std::string>::convert(const std::string& str) {
2126+    return Detail::convertIntoString( str );
2127+}
2128+
2129+#ifdef CATCH_CONFIG_CPP17_STRING_VIEW
2130+std::string StringMaker<std::string_view>::convert(std::string_view str) {
2131+    return Detail::convertIntoString( StringRef( str.data(), str.size() ) );
2132+}
2133+#endif
2134+
2135+std::string StringMaker<char const*>::convert(char const* str) {
2136+    if (str) {
2137+        return Detail::convertIntoString( str );
2138+    } else {
2139+        return{ "{null string}" };
2140+    }
2141+}
2142+std::string StringMaker<char*>::convert(char* str) { // NOLINT(readability-non-const-parameter)
2143+    if (str) {
2144+        return Detail::convertIntoString( str );
2145+    } else {
2146+        return{ "{null string}" };
2147+    }
2148+}
2149+
2150+#ifdef CATCH_CONFIG_WCHAR
2151+std::string StringMaker<std::wstring>::convert(const std::wstring& wstr) {
2152+    std::string s;
2153+    s.reserve(wstr.size());
2154+    for (auto c : wstr) {
2155+        s += (c <= 0xff) ? static_cast<char>(c) : '?';
2156+    }
2157+    return ::Catch::Detail::stringify(s);
2158+}
2159+
2160+# ifdef CATCH_CONFIG_CPP17_STRING_VIEW
2161+std::string StringMaker<std::wstring_view>::convert(std::wstring_view str) {
2162+    return StringMaker<std::wstring>::convert(std::wstring(str));
2163+}
2164+# endif
2165+
2166+std::string StringMaker<wchar_t const*>::convert(wchar_t const * str) {
2167+    if (str) {
2168+        return ::Catch::Detail::stringify(std::wstring{ str });
2169+    } else {
2170+        return{ "{null string}" };
2171+    }
2172+}
2173+std::string StringMaker<wchar_t *>::convert(wchar_t * str) {
2174+    if (str) {
2175+        return ::Catch::Detail::stringify(std::wstring{ str });
2176+    } else {
2177+        return{ "{null string}" };
2178+    }
2179+}
2180+#endif
2181+
2182+#if defined(CATCH_CONFIG_CPP17_BYTE)
2183+#include <cstddef>
2184+std::string StringMaker<std::byte>::convert(std::byte value) {
2185+    return ::Catch::Detail::stringify(std::to_integer<unsigned long long>(value));
2186+}
2187+#endif // defined(CATCH_CONFIG_CPP17_BYTE)
2188+
2189+std::string StringMaker<int>::convert(int value) {
2190+    return ::Catch::Detail::stringify(static_cast<long long>(value));
2191+}
2192+std::string StringMaker<long>::convert(long value) {
2193+    return ::Catch::Detail::stringify(static_cast<long long>(value));
2194+}
2195+std::string StringMaker<long long>::convert(long long value) {
2196+    ReusableStringStream rss;
2197+    rss << value;
2198+    if (value > Detail::hexThreshold) {
2199+        rss << " (0x" << std::hex << value << ')';
2200+    }
2201+    return rss.str();
2202+}
2203+
2204+std::string StringMaker<unsigned int>::convert(unsigned int value) {
2205+    return ::Catch::Detail::stringify(static_cast<unsigned long long>(value));
2206+}
2207+std::string StringMaker<unsigned long>::convert(unsigned long value) {
2208+    return ::Catch::Detail::stringify(static_cast<unsigned long long>(value));
2209+}
2210+std::string StringMaker<unsigned long long>::convert(unsigned long long value) {
2211+    ReusableStringStream rss;
2212+    rss << value;
2213+    if (value > Detail::hexThreshold) {
2214+        rss << " (0x" << std::hex << value << ')';
2215+    }
2216+    return rss.str();
2217+}
2218+
2219+std::string StringMaker<signed char>::convert(signed char value) {
2220+    if (value == '\r') {
2221+        return "'\\r'";
2222+    } else if (value == '\f') {
2223+        return "'\\f'";
2224+    } else if (value == '\n') {
2225+        return "'\\n'";
2226+    } else if (value == '\t') {
2227+        return "'\\t'";
2228+    } else if ('\0' <= value && value < ' ') {
2229+        return ::Catch::Detail::stringify(static_cast<unsigned int>(value));
2230+    } else {
2231+        char chstr[] = "' '";
2232+        chstr[1] = value;
2233+        return chstr;
2234+    }
2235+}
2236+std::string StringMaker<char>::convert(char c) {
2237+    return ::Catch::Detail::stringify(static_cast<signed char>(c));
2238+}
2239+std::string StringMaker<unsigned char>::convert(unsigned char value) {
2240+    return ::Catch::Detail::stringify(static_cast<char>(value));
2241+}
2242+
2243+int StringMaker<float>::precision = 5;
2244+
2245+std::string StringMaker<float>::convert(float value) {
2246+    return Detail::fpToString(value, precision) + 'f';
2247+}
2248+
2249+int StringMaker<double>::precision = 10;
2250+
2251+std::string StringMaker<double>::convert(double value) {
2252+    return Detail::fpToString(value, precision);
2253+}
2254+
2255+} // end namespace Catch
2256+
2257+
2258+
2259+namespace Catch {
2260+
2261+    Counts Counts::operator - ( Counts const& other ) const {
2262+        Counts diff;
2263+        diff.passed = passed - other.passed;
2264+        diff.failed = failed - other.failed;
2265+        diff.failedButOk = failedButOk - other.failedButOk;
2266+        diff.skipped = skipped - other.skipped;
2267+        return diff;
2268+    }
2269+
2270+    Counts& Counts::operator += ( Counts const& other ) {
2271+        passed += other.passed;
2272+        failed += other.failed;
2273+        failedButOk += other.failedButOk;
2274+        skipped += other.skipped;
2275+        return *this;
2276+    }
2277+
2278+    std::uint64_t Counts::total() const {
2279+        return passed + failed + failedButOk + skipped;
2280+    }
2281+    bool Counts::allPassed() const {
2282+        return failed == 0 && failedButOk == 0 && skipped == 0;
2283+    }
2284+    bool Counts::allOk() const {
2285+        return failed == 0;
2286+    }
2287+
2288+    Totals Totals::operator - ( Totals const& other ) const {
2289+        Totals diff;
2290+        diff.assertions = assertions - other.assertions;
2291+        diff.testCases = testCases - other.testCases;
2292+        return diff;
2293+    }
2294+
2295+    Totals& Totals::operator += ( Totals const& other ) {
2296+        assertions += other.assertions;
2297+        testCases += other.testCases;
2298+        return *this;
2299+    }
2300+
2301+    Totals Totals::delta( Totals const& prevTotals ) const {
2302+        Totals diff = *this - prevTotals;
2303+        if( diff.assertions.failed > 0 )
2304+            ++diff.testCases.failed;
2305+        else if( diff.assertions.failedButOk > 0 )
2306+            ++diff.testCases.failedButOk;
2307+        else if ( diff.assertions.skipped > 0 )
2308+            ++ diff.testCases.skipped;
2309+        else
2310+            ++diff.testCases.passed;
2311+        return diff;
2312+    }
2313+
2314+}
2315+
2316+
2317+
2318+
2319+namespace Catch {
2320+    namespace Detail {
2321+        void registerTranslatorImpl(
2322+            Detail::unique_ptr<IExceptionTranslator>&& translator ) {
2323+            getMutableRegistryHub().registerTranslator(
2324+                CATCH_MOVE( translator ) );
2325+        }
2326+    } // namespace Detail
2327+} // namespace Catch
2328+
2329+
2330+#include <ostream>
2331+
2332+namespace Catch {
2333+
2334+    Version::Version
2335+        (   unsigned int _majorVersion,
2336+            unsigned int _minorVersion,
2337+            unsigned int _patchNumber,
2338+            char const * const _branchName,
2339+            unsigned int _buildNumber )
2340+    :   majorVersion( _majorVersion ),
2341+        minorVersion( _minorVersion ),
2342+        patchNumber( _patchNumber ),
2343+        branchName( _branchName ),
2344+        buildNumber( _buildNumber )
2345+    {}
2346+
2347+    std::ostream& operator << ( std::ostream& os, Version const& version ) {
2348+        os  << version.majorVersion << '.'
2349+            << version.minorVersion << '.'
2350+            << version.patchNumber;
2351+        // branchName is never null -> 0th char is \0 if it is empty
2352+        if (version.branchName[0]) {
2353+            os << '-' << version.branchName
2354+               << '.' << version.buildNumber;
2355+        }
2356+        return os;
2357+    }
2358+
2359+    Version const& libraryVersion() {
2360+        static Version version( 3, 5, 4, "", 0 );
2361+        return version;
2362+    }
2363+
2364+}
2365+
2366+
2367+
2368+
2369+namespace Catch {
2370+
2371+    const char* GeneratorException::what() const noexcept {
2372+        return m_msg;
2373+    }
2374+
2375+} // end namespace Catch
2376+
2377+
2378+
2379+
2380+namespace Catch {
2381+
2382+    IGeneratorTracker::~IGeneratorTracker() = default;
2383+
2384+namespace Generators {
2385+
2386+namespace Detail {
2387+
2388+    [[noreturn]]
2389+    void throw_generator_exception(char const* msg) {
2390+        Catch::throw_exception(GeneratorException{ msg });
2391+    }
2392+} // end namespace Detail
2393+
2394+    GeneratorUntypedBase::~GeneratorUntypedBase() = default;
2395+
2396+    IGeneratorTracker* acquireGeneratorTracker(StringRef generatorName, SourceLineInfo const& lineInfo ) {
2397+        return getResultCapture().acquireGeneratorTracker( generatorName, lineInfo );
2398+    }
2399+
2400+    IGeneratorTracker* createGeneratorTracker( StringRef generatorName,
2401+                                 SourceLineInfo lineInfo,
2402+                                 GeneratorBasePtr&& generator ) {
2403+        return getResultCapture().createGeneratorTracker(
2404+            generatorName, lineInfo, CATCH_MOVE( generator ) );
2405+    }
2406+
2407+} // namespace Generators
2408+} // namespace Catch
2409+
2410+
2411+
2412+
2413+#include <random>
2414+
2415+namespace Catch {
2416+    namespace Generators {
2417+        namespace Detail {
2418+            std::uint32_t getSeed() { return sharedRng()(); }
2419+        } // namespace Detail
2420+
2421+        struct RandomFloatingGenerator<long double>::PImpl {
2422+            PImpl( long double a, long double b, uint32_t seed ):
2423+                rng( seed ), dist( a, b ) {}
2424+
2425+            Catch::SimplePcg32 rng;
2426+            std::uniform_real_distribution<long double> dist;
2427+        };
2428+
2429+        RandomFloatingGenerator<long double>::RandomFloatingGenerator(
2430+            long double a, long double b, std::uint32_t seed) :
2431+            m_pimpl(Catch::Detail::make_unique<PImpl>(a, b, seed)) {
2432+            static_cast<void>( next() );
2433+        }
2434+
2435+        RandomFloatingGenerator<long double>::~RandomFloatingGenerator() =
2436+            default;
2437+        bool RandomFloatingGenerator<long double>::next() {
2438+            m_current_number = m_pimpl->dist( m_pimpl->rng );
2439+            return true;
2440+        }
2441+    } // namespace Generators
2442+} // namespace Catch
2443+
2444+
2445+
2446+
2447+namespace Catch {
2448+    IResultCapture::~IResultCapture() = default;
2449+}
2450+
2451+
2452+
2453+
2454+namespace Catch {
2455+    IConfig::~IConfig() = default;
2456+}
2457+
2458+
2459+
2460+
2461+namespace Catch {
2462+    IExceptionTranslator::~IExceptionTranslator() = default;
2463+    IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() = default;
2464+}
2465+
2466+
2467+
2468+#include <string>
2469+
2470+namespace Catch {
2471+    namespace Generators {
2472+
2473+        bool GeneratorUntypedBase::countedNext() {
2474+            auto ret = next();
2475+            if ( ret ) {
2476+                m_stringReprCache.clear();
2477+                ++m_currentElementIndex;
2478+            }
2479+            return ret;
2480+        }
2481+
2482+        StringRef GeneratorUntypedBase::currentElementAsString() const {
2483+            if ( m_stringReprCache.empty() ) {
2484+                m_stringReprCache = stringifyImpl();
2485+            }
2486+            return m_stringReprCache;
2487+        }
2488+
2489+    } // namespace Generators
2490+} // namespace Catch
2491+
2492+
2493+
2494+
2495+namespace Catch {
2496+    IRegistryHub::~IRegistryHub() = default;
2497+    IMutableRegistryHub::~IMutableRegistryHub() = default;
2498+}
2499+
2500+
2501+
2502+#include <cassert>
2503+
2504+namespace Catch {
2505+
2506+    ReporterConfig::ReporterConfig(
2507+        IConfig const* _fullConfig,
2508+        Detail::unique_ptr<IStream> _stream,
2509+        ColourMode colourMode,
2510+        std::map<std::string, std::string> customOptions ):
2511+        m_stream( CATCH_MOVE(_stream) ),
2512+        m_fullConfig( _fullConfig ),
2513+        m_colourMode( colourMode ),
2514+        m_customOptions( CATCH_MOVE( customOptions ) ) {}
2515+
2516+    Detail::unique_ptr<IStream> ReporterConfig::takeStream() && {
2517+        assert( m_stream );
2518+        return CATCH_MOVE( m_stream );
2519+    }
2520+    IConfig const * ReporterConfig::fullConfig() const { return m_fullConfig; }
2521+    ColourMode ReporterConfig::colourMode() const { return m_colourMode; }
2522+
2523+    std::map<std::string, std::string> const&
2524+    ReporterConfig::customOptions() const {
2525+        return m_customOptions;
2526+    }
2527+
2528+    ReporterConfig::~ReporterConfig() = default;
2529+
2530+    AssertionStats::AssertionStats( AssertionResult const& _assertionResult,
2531+                                    std::vector<MessageInfo> const& _infoMessages,
2532+                                    Totals const& _totals )
2533+    :   assertionResult( _assertionResult ),
2534+        infoMessages( _infoMessages ),
2535+        totals( _totals )
2536+    {
2537+        if( assertionResult.hasMessage() ) {
2538+            // Copy message into messages list.
2539+            // !TBD This should have been done earlier, somewhere
2540+            MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() );
2541+            builder.m_info.message = static_cast<std::string>(assertionResult.getMessage());
2542+
2543+            infoMessages.push_back( CATCH_MOVE(builder.m_info) );
2544+        }
2545+    }
2546+
2547+    SectionStats::SectionStats(  SectionInfo&& _sectionInfo,
2548+                                 Counts const& _assertions,
2549+                                 double _durationInSeconds,
2550+                                 bool _missingAssertions )
2551+    :   sectionInfo( CATCH_MOVE(_sectionInfo) ),
2552+        assertions( _assertions ),
2553+        durationInSeconds( _durationInSeconds ),
2554+        missingAssertions( _missingAssertions )
2555+    {}
2556+
2557+
2558+    TestCaseStats::TestCaseStats(  TestCaseInfo const& _testInfo,
2559+                                   Totals const& _totals,
2560+                                   std::string&& _stdOut,
2561+                                   std::string&& _stdErr,
2562+                                   bool _aborting )
2563+    : testInfo( &_testInfo ),
2564+        totals( _totals ),
2565+        stdOut( CATCH_MOVE(_stdOut) ),
2566+        stdErr( CATCH_MOVE(_stdErr) ),
2567+        aborting( _aborting )
2568+    {}
2569+
2570+
2571+    TestRunStats::TestRunStats(   TestRunInfo const& _runInfo,
2572+                    Totals const& _totals,
2573+                    bool _aborting )
2574+    :   runInfo( _runInfo ),
2575+        totals( _totals ),
2576+        aborting( _aborting )
2577+    {}
2578+
2579+    IEventListener::~IEventListener() = default;
2580+
2581+} // end namespace Catch
2582+
2583+
2584+
2585+
2586+namespace Catch {
2587+    IReporterFactory::~IReporterFactory() = default;
2588+    EventListenerFactory::~EventListenerFactory() = default;
2589+}
2590+
2591+
2592+
2593+
2594+namespace Catch {
2595+    ITestCaseRegistry::~ITestCaseRegistry() = default;
2596+}
2597+
2598+
2599+
2600+namespace Catch {
2601+
2602+    AssertionHandler::AssertionHandler
2603+        (   StringRef macroName,
2604+            SourceLineInfo const& lineInfo,
2605+            StringRef capturedExpression,
2606+            ResultDisposition::Flags resultDisposition )
2607+    :   m_assertionInfo{ macroName, lineInfo, capturedExpression, resultDisposition },
2608+        m_resultCapture( getResultCapture() )
2609+    {
2610+        m_resultCapture.notifyAssertionStarted( m_assertionInfo );
2611+    }
2612+
2613+    void AssertionHandler::handleExpr( ITransientExpression const& expr ) {
2614+        m_resultCapture.handleExpr( m_assertionInfo, expr, m_reaction );
2615+    }
2616+    void AssertionHandler::handleMessage(ResultWas::OfType resultType, StringRef message) {
2617+        m_resultCapture.handleMessage( m_assertionInfo, resultType, message, m_reaction );
2618+    }
2619+
2620+    auto AssertionHandler::allowThrows() const -> bool {
2621+        return getCurrentContext().getConfig()->allowThrows();
2622+    }
2623+
2624+    void AssertionHandler::complete() {
2625+        m_completed = true;
2626+        if( m_reaction.shouldDebugBreak ) {
2627+
2628+            // If you find your debugger stopping you here then go one level up on the
2629+            // call-stack for the code that caused it (typically a failed assertion)
2630+
2631+            // (To go back to the test and change execution, jump over the throw, next)
2632+            CATCH_BREAK_INTO_DEBUGGER();
2633+        }
2634+        if (m_reaction.shouldThrow) {
2635+            throw_test_failure_exception();
2636+        }
2637+        if ( m_reaction.shouldSkip ) {
2638+            throw_test_skip_exception();
2639+        }
2640+    }
2641+
2642+    void AssertionHandler::handleUnexpectedInflightException() {
2643+        m_resultCapture.handleUnexpectedInflightException( m_assertionInfo, Catch::translateActiveException(), m_reaction );
2644+    }
2645+
2646+    void AssertionHandler::handleExceptionThrownAsExpected() {
2647+        m_resultCapture.handleNonExpr(m_assertionInfo, ResultWas::Ok, m_reaction);
2648+    }
2649+    void AssertionHandler::handleExceptionNotThrownAsExpected() {
2650+        m_resultCapture.handleNonExpr(m_assertionInfo, ResultWas::Ok, m_reaction);
2651+    }
2652+
2653+    void AssertionHandler::handleUnexpectedExceptionNotThrown() {
2654+        m_resultCapture.handleUnexpectedExceptionNotThrown( m_assertionInfo, m_reaction );
2655+    }
2656+
2657+    void AssertionHandler::handleThrowingCallSkipped() {
2658+        m_resultCapture.handleNonExpr(m_assertionInfo, ResultWas::Ok, m_reaction);
2659+    }
2660+
2661+    // This is the overload that takes a string and infers the Equals matcher from it
2662+    // The more general overload, that takes any string matcher, is in catch_capture_matchers.cpp
2663+    void handleExceptionMatchExpr( AssertionHandler& handler, std::string const& str ) {
2664+        handleExceptionMatchExpr( handler, Matchers::Equals( str ) );
2665+    }
2666+
2667+} // namespace Catch
2668+
2669+
2670+
2671+
2672+#include <algorithm>
2673+
2674+namespace Catch {
2675+    namespace Detail {
2676+
2677+        bool CaseInsensitiveLess::operator()( StringRef lhs,
2678+                                              StringRef rhs ) const {
2679+            return std::lexicographical_compare(
2680+                lhs.begin(), lhs.end(),
2681+                rhs.begin(), rhs.end(),
2682+                []( char l, char r ) { return toLower( l ) < toLower( r ); } );
2683+        }
2684+
2685+        bool
2686+        CaseInsensitiveEqualTo::operator()( StringRef lhs,
2687+                                            StringRef rhs ) const {
2688+            return std::equal(
2689+                lhs.begin(), lhs.end(),
2690+                rhs.begin(), rhs.end(),
2691+                []( char l, char r ) { return toLower( l ) == toLower( r ); } );
2692+        }
2693+
2694+    } // namespace Detail
2695+} // namespace Catch
2696+
2697+
2698+
2699+
2700+#include <algorithm>
2701+#include <ostream>
2702+
2703+namespace {
2704+    bool isOptPrefix( char c ) {
2705+        return c == '-'
2706+#ifdef CATCH_PLATFORM_WINDOWS
2707+               || c == '/'
2708+#endif
2709+            ;
2710+    }
2711+
2712+    Catch::StringRef normaliseOpt( Catch::StringRef optName ) {
2713+        if ( optName[0] == '-'
2714+#if defined(CATCH_PLATFORM_WINDOWS)
2715+             || optName[0] == '/'
2716+#endif
2717+        ) {
2718+            return optName.substr( 1, optName.size() );
2719+        }
2720+
2721+        return optName;
2722+    }
2723+
2724+    static size_t find_first_separator(Catch::StringRef sr) {
2725+        auto is_separator = []( char c ) {
2726+            return c == ' ' || c == ':' || c == '=';
2727+        };
2728+        size_t pos = 0;
2729+        while (pos < sr.size()) {
2730+            if (is_separator(sr[pos])) { return pos; }
2731+            ++pos;
2732+        }
2733+
2734+        return Catch::StringRef::npos;
2735+    }
2736+
2737+} // namespace
2738+
2739+namespace Catch {
2740+    namespace Clara {
2741+        namespace Detail {
2742+
2743+            void TokenStream::loadBuffer() {
2744+                m_tokenBuffer.clear();
2745+
2746+                // Skip any empty strings
2747+                while ( it != itEnd && it->empty() ) {
2748+                    ++it;
2749+                }
2750+
2751+                if ( it != itEnd ) {
2752+                    StringRef next = *it;
2753+                    if ( isOptPrefix( next[0] ) ) {
2754+                        auto delimiterPos = find_first_separator(next);
2755+                        if ( delimiterPos != StringRef::npos ) {
2756+                            m_tokenBuffer.push_back(
2757+                                { TokenType::Option,
2758+                                  next.substr( 0, delimiterPos ) } );
2759+                            m_tokenBuffer.push_back(
2760+                                { TokenType::Argument,
2761+                                  next.substr( delimiterPos + 1, next.size() ) } );
2762+                        } else {
2763+                            if ( next[1] != '-' && next.size() > 2 ) {
2764+                                // Combined short args, e.g. "-ab" for "-a -b"
2765+                                for ( size_t i = 1; i < next.size(); ++i ) {
2766+                                    m_tokenBuffer.push_back(
2767+                                        { TokenType::Option,
2768+                                          next.substr( i, 1 ) } );
2769+                                }
2770+                            } else {
2771+                                m_tokenBuffer.push_back(
2772+                                    { TokenType::Option, next } );
2773+                            }
2774+                        }
2775+                    } else {
2776+                        m_tokenBuffer.push_back(
2777+                            { TokenType::Argument, next } );
2778+                    }
2779+                }
2780+            }
2781+
2782+            TokenStream::TokenStream( Args const& args ):
2783+                TokenStream( args.m_args.begin(), args.m_args.end() ) {}
2784+
2785+            TokenStream::TokenStream( Iterator it_, Iterator itEnd_ ):
2786+                it( it_ ), itEnd( itEnd_ ) {
2787+                loadBuffer();
2788+            }
2789+
2790+            TokenStream& TokenStream::operator++() {
2791+                if ( m_tokenBuffer.size() >= 2 ) {
2792+                    m_tokenBuffer.erase( m_tokenBuffer.begin() );
2793+                } else {
2794+                    if ( it != itEnd )
2795+                        ++it;
2796+                    loadBuffer();
2797+                }
2798+                return *this;
2799+            }
2800+
2801+            ParserResult convertInto( std::string const& source,
2802+                                      std::string& target ) {
2803+                target = source;
2804+                return ParserResult::ok( ParseResultType::Matched );
2805+            }
2806+
2807+            ParserResult convertInto( std::string const& source,
2808+                                      bool& target ) {
2809+                std::string srcLC = toLower( source );
2810+
2811+                if ( srcLC == "y" || srcLC == "1" || srcLC == "true" ||
2812+                     srcLC == "yes" || srcLC == "on" ) {
2813+                    target = true;
2814+                } else if ( srcLC == "n" || srcLC == "0" || srcLC == "false" ||
2815+                            srcLC == "no" || srcLC == "off" ) {
2816+                    target = false;
2817+                } else {
2818+                    return ParserResult::runtimeError(
2819+                        "Expected a boolean value but did not recognise: '" +
2820+                        source + '\'' );
2821+                }
2822+                return ParserResult::ok( ParseResultType::Matched );
2823+            }
2824+
2825+            size_t ParserBase::cardinality() const { return 1; }
2826+
2827+            InternalParseResult ParserBase::parse( Args const& args ) const {
2828+                return parse( static_cast<std::string>(args.exeName()), TokenStream( args ) );
2829+            }
2830+
2831+            ParseState::ParseState( ParseResultType type,
2832+                                    TokenStream remainingTokens ):
2833+                m_type( type ), m_remainingTokens( CATCH_MOVE(remainingTokens) ) {}
2834+
2835+            ParserResult BoundFlagRef::setFlag( bool flag ) {
2836+                m_ref = flag;
2837+                return ParserResult::ok( ParseResultType::Matched );
2838+            }
2839+
2840+            ResultBase::~ResultBase() = default;
2841+
2842+            bool BoundRef::isContainer() const { return false; }
2843+
2844+            bool BoundRef::isFlag() const { return false; }
2845+
2846+            bool BoundFlagRefBase::isFlag() const { return true; }
2847+
2848+} // namespace Detail
2849+
2850+        Detail::InternalParseResult Arg::parse(std::string const&,
2851+                                               Detail::TokenStream tokens) const {
2852+            auto validationResult = validate();
2853+            if (!validationResult)
2854+                return Detail::InternalParseResult(validationResult);
2855+
2856+            auto token = *tokens;
2857+            if (token.type != Detail::TokenType::Argument)
2858+                return Detail::InternalParseResult::ok(Detail::ParseState(
2859+                    ParseResultType::NoMatch, CATCH_MOVE(tokens)));
2860+
2861+            assert(!m_ref->isFlag());
2862+            auto valueRef =
2863+                static_cast<Detail::BoundValueRefBase*>(m_ref.get());
2864+
2865+            auto result = valueRef->setValue(static_cast<std::string>(token.token));
2866+            if ( !result )
2867+                return Detail::InternalParseResult( result );
2868+            else
2869+                return Detail::InternalParseResult::ok(
2870+                    Detail::ParseState( ParseResultType::Matched,
2871+                                        CATCH_MOVE( ++tokens ) ) );
2872+        }
2873+
2874+        Opt::Opt(bool& ref) :
2875+            ParserRefImpl(std::make_shared<Detail::BoundFlagRef>(ref)) {}
2876+
2877+        Detail::HelpColumns Opt::getHelpColumns() const {
2878+            ReusableStringStream oss;
2879+            bool first = true;
2880+            for (auto const& opt : m_optNames) {
2881+                if (first)
2882+                    first = false;
2883+                else
2884+                    oss << ", ";
2885+                oss << opt;
2886+            }
2887+            if (!m_hint.empty())
2888+                oss << " <" << m_hint << '>';
2889+            return { oss.str(), m_description };
2890+        }
2891+
2892+        bool Opt::isMatch(StringRef optToken) const {
2893+            auto normalisedToken = normaliseOpt(optToken);
2894+            for (auto const& name : m_optNames) {
2895+                if (normaliseOpt(name) == normalisedToken)
2896+                    return true;
2897+            }
2898+            return false;
2899+        }
2900+
2901+        Detail::InternalParseResult Opt::parse(std::string const&,
2902+                                       Detail::TokenStream tokens) const {
2903+            auto validationResult = validate();
2904+            if (!validationResult)
2905+                return Detail::InternalParseResult(validationResult);
2906+
2907+            if (tokens &&
2908+                tokens->type == Detail::TokenType::Option) {
2909+                auto const& token = *tokens;
2910+                if (isMatch(token.token)) {
2911+                    if (m_ref->isFlag()) {
2912+                        auto flagRef =
2913+                            static_cast<Detail::BoundFlagRefBase*>(
2914+                                m_ref.get());
2915+                        auto result = flagRef->setFlag(true);
2916+                        if (!result)
2917+                            return Detail::InternalParseResult(result);
2918+                        if (result.value() ==
2919+                            ParseResultType::ShortCircuitAll)
2920+                            return Detail::InternalParseResult::ok(Detail::ParseState(
2921+                                result.value(), CATCH_MOVE(tokens)));
2922+                    } else {
2923+                        auto valueRef =
2924+                            static_cast<Detail::BoundValueRefBase*>(
2925+                                m_ref.get());
2926+                        ++tokens;
2927+                        if (!tokens)
2928+                            return Detail::InternalParseResult::runtimeError(
2929+                                "Expected argument following " +
2930+                                token.token);
2931+                        auto const& argToken = *tokens;
2932+                        if (argToken.type != Detail::TokenType::Argument)
2933+                            return Detail::InternalParseResult::runtimeError(
2934+                                "Expected argument following " +
2935+                                token.token);
2936+                        const auto result = valueRef->setValue(static_cast<std::string>(argToken.token));
2937+                        if (!result)
2938+                            return Detail::InternalParseResult(result);
2939+                        if (result.value() ==
2940+                            ParseResultType::ShortCircuitAll)
2941+                            return Detail::InternalParseResult::ok(Detail::ParseState(
2942+                                result.value(), CATCH_MOVE(tokens)));
2943+                    }
2944+                    return Detail::InternalParseResult::ok(Detail::ParseState(
2945+                        ParseResultType::Matched, CATCH_MOVE(++tokens)));
2946+                }
2947+            }
2948+            return Detail::InternalParseResult::ok(
2949+                Detail::ParseState(ParseResultType::NoMatch, CATCH_MOVE(tokens)));
2950+        }
2951+
2952+        Detail::Result Opt::validate() const {
2953+            if (m_optNames.empty())
2954+                return Detail::Result::logicError("No options supplied to Opt");
2955+            for (auto const& name : m_optNames) {
2956+                if (name.empty())
2957+                    return Detail::Result::logicError(
2958+                        "Option name cannot be empty");
2959+#ifdef CATCH_PLATFORM_WINDOWS
2960+                if (name[0] != '-' && name[0] != '/')
2961+                    return Detail::Result::logicError(
2962+                        "Option name must begin with '-' or '/'");
2963+#else
2964+                if (name[0] != '-')
2965+                    return Detail::Result::logicError(
2966+                        "Option name must begin with '-'");
2967+#endif
2968+            }
2969+            return ParserRefImpl::validate();
2970+        }
2971+
2972+        ExeName::ExeName() :
2973+            m_name(std::make_shared<std::string>("<executable>")) {}
2974+
2975+        ExeName::ExeName(std::string& ref) : ExeName() {
2976+            m_ref = std::make_shared<Detail::BoundValueRef<std::string>>(ref);
2977+        }
2978+
2979+        Detail::InternalParseResult
2980+            ExeName::parse(std::string const&,
2981+                           Detail::TokenStream tokens) const {
2982+            return Detail::InternalParseResult::ok(
2983+                Detail::ParseState(ParseResultType::NoMatch, CATCH_MOVE(tokens)));
2984+        }
2985+
2986+        ParserResult ExeName::set(std::string const& newName) {
2987+            auto lastSlash = newName.find_last_of("\\/");
2988+            auto filename = (lastSlash == std::string::npos)
2989+                ? newName
2990+                : newName.substr(lastSlash + 1);
2991+
2992+            *m_name = filename;
2993+            if (m_ref)
2994+                return m_ref->setValue(filename);
2995+            else
2996+                return ParserResult::ok(ParseResultType::Matched);
2997+        }
2998+
2999+
3000+
3001+
3002+        Parser& Parser::operator|=( Parser const& other ) {
3003+            m_options.insert( m_options.end(),
3004+                              other.m_options.begin(),
3005+                              other.m_options.end() );
3006+            m_args.insert(
3007+                m_args.end(), other.m_args.begin(), other.m_args.end() );
3008+            return *this;
3009+        }
3010+
3011+        std::vector<Detail::HelpColumns> Parser::getHelpColumns() const {
3012+            std::vector<Detail::HelpColumns> cols;
3013+            cols.reserve( m_options.size() );
3014+            for ( auto const& o : m_options ) {
3015+                cols.push_back(o.getHelpColumns());
3016+            }
3017+            return cols;
3018+        }
3019+
3020+        void Parser::writeToStream( std::ostream& os ) const {
3021+            if ( !m_exeName.name().empty() ) {
3022+                os << "usage:\n"
3023+                   << "  " << m_exeName.name() << ' ';
3024+                bool required = true, first = true;
3025+                for ( auto const& arg : m_args ) {
3026+                    if ( first )
3027+                        first = false;
3028+                    else
3029+                        os << ' ';
3030+                    if ( arg.isOptional() && required ) {
3031+                        os << '[';
3032+                        required = false;
3033+                    }
3034+                    os << '<' << arg.hint() << '>';
3035+                    if ( arg.cardinality() == 0 )
3036+                        os << " ... ";
3037+                }
3038+                if ( !required )
3039+                    os << ']';
3040+                if ( !m_options.empty() )
3041+                    os << " options";
3042+                os << "\n\nwhere options are:\n";
3043+            }
3044+
3045+            auto rows = getHelpColumns();
3046+            size_t consoleWidth = CATCH_CONFIG_CONSOLE_WIDTH;
3047+            size_t optWidth = 0;
3048+            for ( auto const& cols : rows )
3049+                optWidth = ( std::max )( optWidth, cols.left.size() + 2 );
3050+
3051+            optWidth = ( std::min )( optWidth, consoleWidth / 2 );
3052+
3053+            for ( auto& cols : rows ) {
3054+                auto row = TextFlow::Column( CATCH_MOVE(cols.left) )
3055+                               .width( optWidth )
3056+                               .indent( 2 ) +
3057+                           TextFlow::Spacer( 4 ) +
3058+                           TextFlow::Column( static_cast<std::string>(cols.descriptions) )
3059+                               .width( consoleWidth - 7 - optWidth );
3060+                os << row << '\n';
3061+            }
3062+        }
3063+
3064+        Detail::Result Parser::validate() const {
3065+            for ( auto const& opt : m_options ) {
3066+                auto result = opt.validate();
3067+                if ( !result )
3068+                    return result;
3069+            }
3070+            for ( auto const& arg : m_args ) {
3071+                auto result = arg.validate();
3072+                if ( !result )
3073+                    return result;
3074+            }
3075+            return Detail::Result::ok();
3076+        }
3077+
3078+        Detail::InternalParseResult
3079+        Parser::parse( std::string const& exeName,
3080+                       Detail::TokenStream tokens ) const {
3081+
3082+            struct ParserInfo {
3083+                ParserBase const* parser = nullptr;
3084+                size_t count = 0;
3085+            };
3086+            std::vector<ParserInfo> parseInfos;
3087+            parseInfos.reserve( m_options.size() + m_args.size() );
3088+            for ( auto const& opt : m_options ) {
3089+                parseInfos.push_back( { &opt, 0 } );
3090+            }
3091+            for ( auto const& arg : m_args ) {
3092+                parseInfos.push_back( { &arg, 0 } );
3093+            }
3094+
3095+            m_exeName.set( exeName );
3096+
3097+            auto result = Detail::InternalParseResult::ok(
3098+                Detail::ParseState( ParseResultType::NoMatch, CATCH_MOVE(tokens) ) );
3099+            while ( result.value().remainingTokens() ) {
3100+                bool tokenParsed = false;
3101+
3102+                for ( auto& parseInfo : parseInfos ) {
3103+                    if ( parseInfo.parser->cardinality() == 0 ||
3104+                         parseInfo.count < parseInfo.parser->cardinality() ) {
3105+                        result = parseInfo.parser->parse(
3106+                            exeName, CATCH_MOVE(result).value().remainingTokens() );
3107+                        if ( !result )
3108+                            return result;
3109+                        if ( result.value().type() !=
3110+                             ParseResultType::NoMatch ) {
3111+                            tokenParsed = true;
3112+                            ++parseInfo.count;
3113+                            break;
3114+                        }
3115+                    }
3116+                }
3117+
3118+                if ( result.value().type() == ParseResultType::ShortCircuitAll )
3119+                    return result;
3120+                if ( !tokenParsed )
3121+                    return Detail::InternalParseResult::runtimeError(
3122+                        "Unrecognised token: " +
3123+                        result.value().remainingTokens()->token );
3124+            }
3125+            // !TBD Check missing required options
3126+            return result;
3127+        }
3128+
3129+        Args::Args(int argc, char const* const* argv) :
3130+            m_exeName(argv[0]), m_args(argv + 1, argv + argc) {}
3131+
3132+        Args::Args(std::initializer_list<StringRef> args) :
3133+            m_exeName(*args.begin()),
3134+            m_args(args.begin() + 1, args.end()) {}
3135+
3136+
3137+        Help::Help( bool& showHelpFlag ):
3138+            Opt( [&]( bool flag ) {
3139+                showHelpFlag = flag;
3140+                return ParserResult::ok( ParseResultType::ShortCircuitAll );
3141+            } ) {
3142+            static_cast<Opt&> ( *this )(
3143+                "display usage information" )["-?"]["-h"]["--help"]
3144+                .optional();
3145+        }
3146+
3147+    } // namespace Clara
3148+} // namespace Catch
3149+
3150+
3151+
3152+
3153+#include <fstream>
3154+#include <string>
3155+
3156+namespace Catch {
3157+
3158+    Clara::Parser makeCommandLineParser( ConfigData& config ) {
3159+
3160+        using namespace Clara;
3161+
3162+        auto const setWarning = [&]( std::string const& warning ) {
3163+            if ( warning == "NoAssertions" ) {
3164+                config.warnings = static_cast<WarnAbout::What>(config.warnings | WarnAbout::NoAssertions);
3165+                return ParserResult::ok( ParseResultType::Matched );
3166+            } else if ( warning == "UnmatchedTestSpec" ) {
3167+                config.warnings = static_cast<WarnAbout::What>(config.warnings | WarnAbout::UnmatchedTestSpec);
3168+                return ParserResult::ok( ParseResultType::Matched );
3169+            }
3170+
3171+            return ParserResult ::runtimeError(
3172+                "Unrecognised warning option: '" + warning + '\'' );
3173+        };
3174+        auto const loadTestNamesFromFile = [&]( std::string const& filename ) {
3175+                std::ifstream f( filename.c_str() );
3176+                if( !f.is_open() )
3177+                    return ParserResult::runtimeError( "Unable to load input file: '" + filename + '\'' );
3178+
3179+                std::string line;
3180+                while( std::getline( f, line ) ) {
3181+                    line = trim(line);
3182+                    if( !line.empty() && !startsWith( line, '#' ) ) {
3183+                        if( !startsWith( line, '"' ) )
3184+                            line = '"' + CATCH_MOVE(line) + '"';
3185+                        config.testsOrTags.push_back( line );
3186+                        config.testsOrTags.emplace_back( "," );
3187+                    }
3188+                }
3189+                //Remove comma in the end
3190+                if(!config.testsOrTags.empty())
3191+                    config.testsOrTags.erase( config.testsOrTags.end()-1 );
3192+
3193+                return ParserResult::ok( ParseResultType::Matched );
3194+            };
3195+        auto const setTestOrder = [&]( std::string const& order ) {
3196+                if( startsWith( "declared", order ) )
3197+                    config.runOrder = TestRunOrder::Declared;
3198+                else if( startsWith( "lexical", order ) )
3199+                    config.runOrder = TestRunOrder::LexicographicallySorted;
3200+                else if( startsWith( "random", order ) )
3201+                    config.runOrder = TestRunOrder::Randomized;
3202+                else
3203+                    return ParserResult::runtimeError( "Unrecognised ordering: '" + order + '\'' );
3204+                return ParserResult::ok( ParseResultType::Matched );
3205+            };
3206+        auto const setRngSeed = [&]( std::string const& seed ) {
3207+                if( seed == "time" ) {
3208+                    config.rngSeed = generateRandomSeed(GenerateFrom::Time);
3209+                    return ParserResult::ok(ParseResultType::Matched);
3210+                } else if (seed == "random-device") {
3211+                    config.rngSeed = generateRandomSeed(GenerateFrom::RandomDevice);
3212+                    return ParserResult::ok(ParseResultType::Matched);
3213+                }
3214+
3215+                // TODO: ideally we should be parsing uint32_t directly
3216+                //       fix this later when we add new parse overload
3217+                auto parsedSeed = parseUInt( seed, 0 );
3218+                if ( !parsedSeed ) {
3219+                    return ParserResult::runtimeError( "Could not parse '" + seed + "' as seed" );
3220+                }
3221+                config.rngSeed = *parsedSeed;
3222+                return ParserResult::ok( ParseResultType::Matched );
3223+            };
3224+        auto const setDefaultColourMode = [&]( std::string const& colourMode ) {
3225+            Optional<ColourMode> maybeMode = Catch::Detail::stringToColourMode(toLower( colourMode ));
3226+            if ( !maybeMode ) {
3227+                return ParserResult::runtimeError(
3228+                    "colour mode must be one of: default, ansi, win32, "
3229+                    "or none. '" +
3230+                    colourMode + "' is not recognised" );
3231+            }
3232+            auto mode = *maybeMode;
3233+            if ( !isColourImplAvailable( mode ) ) {
3234+                return ParserResult::runtimeError(
3235+                    "colour mode '" + colourMode +
3236+                    "' is not supported in this binary" );
3237+            }
3238+            config.defaultColourMode = mode;
3239+            return ParserResult::ok( ParseResultType::Matched );
3240+        };
3241+        auto const setWaitForKeypress = [&]( std::string const& keypress ) {
3242+                auto keypressLc = toLower( keypress );
3243+                if (keypressLc == "never")
3244+                    config.waitForKeypress = WaitForKeypress::Never;
3245+                else if( keypressLc == "start" )
3246+                    config.waitForKeypress = WaitForKeypress::BeforeStart;
3247+                else if( keypressLc == "exit" )
3248+                    config.waitForKeypress = WaitForKeypress::BeforeExit;
3249+                else if( keypressLc == "both" )
3250+                    config.waitForKeypress = WaitForKeypress::BeforeStartAndExit;
3251+                else
3252+                    return ParserResult::runtimeError( "keypress argument must be one of: never, start, exit or both. '" + keypress + "' not recognised" );
3253+            return ParserResult::ok( ParseResultType::Matched );
3254+            };
3255+        auto const setVerbosity = [&]( std::string const& verbosity ) {
3256+            auto lcVerbosity = toLower( verbosity );
3257+            if( lcVerbosity == "quiet" )
3258+                config.verbosity = Verbosity::Quiet;
3259+            else if( lcVerbosity == "normal" )
3260+                config.verbosity = Verbosity::Normal;
3261+            else if( lcVerbosity == "high" )
3262+                config.verbosity = Verbosity::High;
3263+            else
3264+                return ParserResult::runtimeError( "Unrecognised verbosity, '" + verbosity + '\'' );
3265+            return ParserResult::ok( ParseResultType::Matched );
3266+        };
3267+        auto const setReporter = [&]( std::string const& userReporterSpec ) {
3268+            if ( userReporterSpec.empty() ) {
3269+                return ParserResult::runtimeError( "Received empty reporter spec." );
3270+            }
3271+
3272+            Optional<ReporterSpec> parsed =
3273+                parseReporterSpec( userReporterSpec );
3274+            if ( !parsed ) {
3275+                return ParserResult::runtimeError(
3276+                    "Could not parse reporter spec '" + userReporterSpec +
3277+                    "'" );
3278+            }
3279+
3280+            auto const& reporterSpec = *parsed;
3281+
3282+            auto const& factories =
3283+                getRegistryHub().getReporterRegistry().getFactories();
3284+            auto result = factories.find( reporterSpec.name() );
3285+
3286+            if ( result == factories.end() ) {
3287+                return ParserResult::runtimeError(
3288+                    "Unrecognized reporter, '" + reporterSpec.name() +
3289+                    "'. Check available with --list-reporters" );
3290+            }
3291+
3292+
3293+            const bool hadOutputFile = reporterSpec.outputFile().some();
3294+            config.reporterSpecifications.push_back( CATCH_MOVE( *parsed ) );
3295+            // It would be enough to check this only once at the very end, but
3296+            // there is  not a place where we could call this check, so do it
3297+            // every time it could fail. For valid inputs, this is still called
3298+            // at most once.
3299+            if (!hadOutputFile) {
3300+                int n_reporters_without_file = 0;
3301+                for (auto const& spec : config.reporterSpecifications) {
3302+                    if (spec.outputFile().none()) {
3303+                        n_reporters_without_file++;
3304+                    }
3305+                }
3306+                if (n_reporters_without_file > 1) {
3307+                    return ParserResult::runtimeError( "Only one reporter may have unspecified output file." );
3308+                }
3309+            }
3310+
3311+            return ParserResult::ok( ParseResultType::Matched );
3312+        };
3313+        auto const setShardCount = [&]( std::string const& shardCount ) {
3314+            auto parsedCount = parseUInt( shardCount );
3315+            if ( !parsedCount ) {
3316+                return ParserResult::runtimeError(
3317+                    "Could not parse '" + shardCount + "' as shard count" );
3318+            }
3319+            if ( *parsedCount == 0 ) {
3320+                return ParserResult::runtimeError(
3321+                    "Shard count must be positive" );
3322+            }
3323+            config.shardCount = *parsedCount;
3324+            return ParserResult::ok( ParseResultType::Matched );
3325+        };
3326+
3327+        auto const setShardIndex = [&](std::string const& shardIndex) {
3328+            auto parsedIndex = parseUInt( shardIndex );
3329+            if ( !parsedIndex ) {
3330+                return ParserResult::runtimeError(
3331+                    "Could not parse '" + shardIndex + "' as shard index" );
3332+            }
3333+            config.shardIndex = *parsedIndex;
3334+            return ParserResult::ok( ParseResultType::Matched );
3335+        };
3336+
3337+        auto cli
3338+            = ExeName( config.processName )
3339+            | Help( config.showHelp )
3340+            | Opt( config.showSuccessfulTests )
3341+                ["-s"]["--success"]
3342+                ( "include successful tests in output" )
3343+            | Opt( config.shouldDebugBreak )
3344+                ["-b"]["--break"]
3345+                ( "break into debugger on failure" )
3346+            | Opt( config.noThrow )
3347+                ["-e"]["--nothrow"]
3348+                ( "skip exception tests" )
3349+            | Opt( config.showInvisibles )
3350+                ["-i"]["--invisibles"]
3351+                ( "show invisibles (tabs, newlines)" )
3352+            | Opt( config.defaultOutputFilename, "filename" )
3353+                ["-o"]["--out"]
3354+                ( "default output filename" )
3355+            | Opt( accept_many, setReporter, "name[::key=value]*" )
3356+                ["-r"]["--reporter"]
3357+                ( "reporter to use (defaults to console)" )
3358+            | Opt( config.name, "name" )
3359+                ["-n"]["--name"]
3360+                ( "suite name" )
3361+            | Opt( [&]( bool ){ config.abortAfter = 1; } )
3362+                ["-a"]["--abort"]
3363+                ( "abort at first failure" )
3364+            | Opt( [&]( int x ){ config.abortAfter = x; }, "no. failures" )
3365+                ["-x"]["--abortx"]
3366+                ( "abort after x failures" )
3367+            | Opt( accept_many, setWarning, "warning name" )
3368+                ["-w"]["--warn"]
3369+                ( "enable warnings" )
3370+            | Opt( [&]( bool flag ) { config.showDurations = flag ? ShowDurations::Always : ShowDurations::Never; }, "yes|no" )
3371+                ["-d"]["--durations"]
3372+                ( "show test durations" )
3373+            | Opt( config.minDuration, "seconds" )
3374+                ["-D"]["--min-duration"]
3375+                ( "show test durations for tests taking at least the given number of seconds" )
3376+            | Opt( loadTestNamesFromFile, "filename" )
3377+                ["-f"]["--input-file"]
3378+                ( "load test names to run from a file" )
3379+            | Opt( config.filenamesAsTags )
3380+                ["-#"]["--filenames-as-tags"]
3381+                ( "adds a tag for the filename" )
3382+            | Opt( config.sectionsToRun, "section name" )
3383+                ["-c"]["--section"]
3384+                ( "specify section to run" )
3385+            | Opt( setVerbosity, "quiet|normal|high" )
3386+                ["-v"]["--verbosity"]
3387+                ( "set output verbosity" )
3388+            | Opt( config.listTests )
3389+                ["--list-tests"]
3390+                ( "list all/matching test cases" )
3391+            | Opt( config.listTags )
3392+                ["--list-tags"]
3393+                ( "list all/matching tags" )
3394+            | Opt( config.listReporters )
3395+                ["--list-reporters"]
3396+                ( "list all available reporters" )
3397+            | Opt( config.listListeners )
3398+                ["--list-listeners"]
3399+                ( "list all listeners" )
3400+            | Opt( setTestOrder, "decl|lex|rand" )
3401+                ["--order"]
3402+                ( "test case order (defaults to decl)" )
3403+            | Opt( setRngSeed, "'time'|'random-device'|number" )
3404+                ["--rng-seed"]
3405+                ( "set a specific seed for random numbers" )
3406+            | Opt( setDefaultColourMode, "ansi|win32|none|default" )
3407+                ["--colour-mode"]
3408+                ( "what color mode should be used as default" )
3409+            | Opt( config.libIdentify )
3410+                ["--libidentify"]
3411+                ( "report name and version according to libidentify standard" )
3412+            | Opt( setWaitForKeypress, "never|start|exit|both" )
3413+                ["--wait-for-keypress"]
3414+                ( "waits for a keypress before exiting" )
3415+            | Opt( config.skipBenchmarks)
3416+                ["--skip-benchmarks"]
3417+                ( "disable running benchmarks")
3418+            | Opt( config.benchmarkSamples, "samples" )
3419+                ["--benchmark-samples"]
3420+                ( "number of samples to collect (default: 100)" )
3421+            | Opt( config.benchmarkResamples, "resamples" )
3422+                ["--benchmark-resamples"]
3423+                ( "number of resamples for the bootstrap (default: 100000)" )
3424+            | Opt( config.benchmarkConfidenceInterval, "confidence interval" )
3425+                ["--benchmark-confidence-interval"]
3426+                ( "confidence interval for the bootstrap (between 0 and 1, default: 0.95)" )
3427+            | Opt( config.benchmarkNoAnalysis )
3428+                ["--benchmark-no-analysis"]
3429+                ( "perform only measurements; do not perform any analysis" )
3430+            | Opt( config.benchmarkWarmupTime, "benchmarkWarmupTime" )
3431+                ["--benchmark-warmup-time"]
3432+                ( "amount of time in milliseconds spent on warming up each test (default: 100)" )
3433+            | Opt( setShardCount, "shard count" )
3434+                ["--shard-count"]
3435+                ( "split the tests to execute into this many groups" )
3436+            | Opt( setShardIndex, "shard index" )
3437+                ["--shard-index"]
3438+                ( "index of the group of tests to execute (see --shard-count)" )
3439+            | Opt( config.allowZeroTests )
3440+                ["--allow-running-no-tests"]
3441+                ( "Treat 'No tests run' as a success" )
3442+            | Arg( config.testsOrTags, "test name|pattern|tags" )
3443+                ( "which test or tests to use" );
3444+
3445+        return cli;
3446+    }
3447+
3448+} // end namespace Catch
3449+
3450+
3451+#if defined(__clang__)
3452+#    pragma clang diagnostic push
3453+#    pragma clang diagnostic ignored "-Wexit-time-destructors"
3454+#endif
3455+
3456+
3457+
3458+#include <cassert>
3459+#include <ostream>
3460+#include <utility>
3461+
3462+namespace Catch {
3463+
3464+    ColourImpl::~ColourImpl() = default;
3465+
3466+    ColourImpl::ColourGuard ColourImpl::guardColour( Colour::Code colourCode ) {
3467+        return ColourGuard(colourCode, this );
3468+    }
3469+
3470+    void ColourImpl::ColourGuard::engageImpl( std::ostream& stream ) {
3471+        assert( &stream == &m_colourImpl->m_stream->stream() &&
3472+                "Engaging colour guard for different stream than used by the "
3473+                "parent colour implementation" );
3474+        static_cast<void>( stream );
3475+
3476+        m_engaged = true;
3477+        m_colourImpl->use( m_code );
3478+    }
3479+
3480+    ColourImpl::ColourGuard::ColourGuard( Colour::Code code,
3481+                                          ColourImpl const* colour ):
3482+        m_colourImpl( colour ), m_code( code ) {
3483+    }
3484+    ColourImpl::ColourGuard::ColourGuard( ColourGuard&& rhs ) noexcept:
3485+        m_colourImpl( rhs.m_colourImpl ),
3486+        m_code( rhs.m_code ),
3487+        m_engaged( rhs.m_engaged ) {
3488+        rhs.m_engaged = false;
3489+    }
3490+    ColourImpl::ColourGuard&
3491+    ColourImpl::ColourGuard::operator=( ColourGuard&& rhs ) noexcept {
3492+        using std::swap;
3493+        swap( m_colourImpl, rhs.m_colourImpl );
3494+        swap( m_code, rhs.m_code );
3495+        swap( m_engaged, rhs.m_engaged );
3496+
3497+        return *this;
3498+    }
3499+    ColourImpl::ColourGuard::~ColourGuard() {
3500+        if ( m_engaged ) {
3501+            m_colourImpl->use( Colour::None );
3502+        }
3503+    }
3504+
3505+    ColourImpl::ColourGuard&
3506+    ColourImpl::ColourGuard::engage( std::ostream& stream ) & {
3507+        engageImpl( stream );
3508+        return *this;
3509+    }
3510+
3511+    ColourImpl::ColourGuard&&
3512+    ColourImpl::ColourGuard::engage( std::ostream& stream ) && {
3513+        engageImpl( stream );
3514+        return CATCH_MOVE(*this);
3515+    }
3516+
3517+    namespace {
3518+        //! A do-nothing implementation of colour, used as fallback for unknown
3519+        //! platforms, and when the user asks to deactivate all colours.
3520+        class NoColourImpl final : public ColourImpl {
3521+        public:
3522+            NoColourImpl( IStream* stream ): ColourImpl( stream ) {}
3523+
3524+        private:
3525+            void use( Colour::Code ) const override {}
3526+        };
3527+    } // namespace
3528+
3529+
3530+} // namespace Catch
3531+
3532+
3533+#if defined ( CATCH_CONFIG_COLOUR_WIN32 ) /////////////////////////////////////////
3534+
3535+namespace Catch {
3536+namespace {
3537+
3538+    class Win32ColourImpl final : public ColourImpl {
3539+    public:
3540+        Win32ColourImpl(IStream* stream):
3541+            ColourImpl(stream) {
3542+            CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
3543+            GetConsoleScreenBufferInfo( GetStdHandle( STD_OUTPUT_HANDLE ),
3544+                                        &csbiInfo );
3545+            originalForegroundAttributes = csbiInfo.wAttributes & ~( BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY );
3546+            originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY );
3547+        }
3548+
3549+        static bool useImplementationForStream(IStream const& stream) {
3550+            // Win32 text colour APIs can only be used on console streams
3551+            // We cannot check that the output hasn't been redirected,
3552+            // so we just check that the original stream is console stream.
3553+            return stream.isConsole();
3554+        }
3555+
3556+    private:
3557+        void use( Colour::Code _colourCode ) const override {
3558+            switch( _colourCode ) {
3559+                case Colour::None:      return setTextAttribute( originalForegroundAttributes );
3560+                case Colour::White:     return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
3561+                case Colour::Red:       return setTextAttribute( FOREGROUND_RED );
3562+                case Colour::Green:     return setTextAttribute( FOREGROUND_GREEN );
3563+                case Colour::Blue:      return setTextAttribute( FOREGROUND_BLUE );
3564+                case Colour::Cyan:      return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN );
3565+                case Colour::Yellow:    return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN );
3566+                case Colour::Grey:      return setTextAttribute( 0 );
3567+
3568+                case Colour::LightGrey:     return setTextAttribute( FOREGROUND_INTENSITY );
3569+                case Colour::BrightRed:     return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED );
3570+                case Colour::BrightGreen:   return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN );
3571+                case Colour::BrightWhite:   return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
3572+                case Colour::BrightYellow:  return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN );
3573+
3574+                case Colour::Bright: CATCH_INTERNAL_ERROR( "not a colour" );
3575+
3576+                default:
3577+                    CATCH_ERROR( "Unknown colour requested" );
3578+            }
3579+        }
3580+
3581+        void setTextAttribute( WORD _textAttribute ) const {
3582+            SetConsoleTextAttribute( GetStdHandle( STD_OUTPUT_HANDLE ),
3583+                                     _textAttribute |
3584+                                         originalBackgroundAttributes );
3585+        }
3586+        WORD originalForegroundAttributes;
3587+        WORD originalBackgroundAttributes;
3588+    };
3589+
3590+} // end anon namespace
3591+} // end namespace Catch
3592+
3593+#endif // Windows/ ANSI/ None
3594+
3595+
3596+#if defined( CATCH_PLATFORM_LINUX ) || defined( CATCH_PLATFORM_MAC )
3597+#    define CATCH_INTERNAL_HAS_ISATTY
3598+#    include <unistd.h>
3599+#endif
3600+
3601+namespace Catch {
3602+namespace {
3603+
3604+    class ANSIColourImpl final : public ColourImpl {
3605+    public:
3606+        ANSIColourImpl( IStream* stream ): ColourImpl( stream ) {}
3607+
3608+        static bool useImplementationForStream(IStream const& stream) {
3609+            // This is kinda messy due to trying to support a bunch of
3610+            // different platforms at once.
3611+            // The basic idea is that if we are asked to do autodetection (as
3612+            // opposed to being told to use posixy colours outright), then we
3613+            // only want to use the colours if we are writing to console.
3614+            // However, console might be redirected, so we make an attempt at
3615+            // checking for that on platforms where we know how to do that.
3616+            bool useColour = stream.isConsole();
3617+#if defined( CATCH_INTERNAL_HAS_ISATTY ) && \
3618+    !( defined( __DJGPP__ ) && defined( __STRICT_ANSI__ ) )
3619+            ErrnoGuard _; // for isatty
3620+            useColour = useColour && isatty( STDOUT_FILENO );
3621+#    endif
3622+#    if defined( CATCH_PLATFORM_MAC ) || defined( CATCH_PLATFORM_IPHONE )
3623+            useColour = useColour && !isDebuggerActive();
3624+#    endif
3625+
3626+            return useColour;
3627+        }
3628+
3629+    private:
3630+        void use( Colour::Code _colourCode ) const override {
3631+            auto setColour = [&out =
3632+                                  m_stream->stream()]( char const* escapeCode ) {
3633+                // The escape sequence must be flushed to console, otherwise
3634+                // if stdin and stderr are intermixed, we'd get accidentally
3635+                // coloured output.
3636+                out << '\033' << escapeCode << std::flush;
3637+            };
3638+            switch( _colourCode ) {
3639+                case Colour::None:
3640+                case Colour::White:     return setColour( "[0m" );
3641+                case Colour::Red:       return setColour( "[0;31m" );
3642+                case Colour::Green:     return setColour( "[0;32m" );
3643+                case Colour::Blue:      return setColour( "[0;34m" );
3644+                case Colour::Cyan:      return setColour( "[0;36m" );
3645+                case Colour::Yellow:    return setColour( "[0;33m" );
3646+                case Colour::Grey:      return setColour( "[1;30m" );
3647+
3648+                case Colour::LightGrey:     return setColour( "[0;37m" );
3649+                case Colour::BrightRed:     return setColour( "[1;31m" );
3650+                case Colour::BrightGreen:   return setColour( "[1;32m" );
3651+                case Colour::BrightWhite:   return setColour( "[1;37m" );
3652+                case Colour::BrightYellow:  return setColour( "[1;33m" );
3653+
3654+                case Colour::Bright: CATCH_INTERNAL_ERROR( "not a colour" );
3655+                default: CATCH_INTERNAL_ERROR( "Unknown colour requested" );
3656+            }
3657+        }
3658+    };
3659+
3660+} // end anon namespace
3661+} // end namespace Catch
3662+
3663+namespace Catch {
3664+
3665+    Detail::unique_ptr<ColourImpl> makeColourImpl( ColourMode colourSelection,
3666+                                                   IStream* stream ) {
3667+#if defined( CATCH_CONFIG_COLOUR_WIN32 )
3668+        if ( colourSelection == ColourMode::Win32 ) {
3669+            return Detail::make_unique<Win32ColourImpl>( stream );
3670+        }
3671+#endif
3672+        if ( colourSelection == ColourMode::ANSI ) {
3673+            return Detail::make_unique<ANSIColourImpl>( stream );
3674+        }
3675+        if ( colourSelection == ColourMode::None ) {
3676+            return Detail::make_unique<NoColourImpl>( stream );
3677+        }
3678+
3679+        if ( colourSelection == ColourMode::PlatformDefault) {
3680+#if defined( CATCH_CONFIG_COLOUR_WIN32 )
3681+            if ( Win32ColourImpl::useImplementationForStream( *stream ) ) {
3682+                return Detail::make_unique<Win32ColourImpl>( stream );
3683+            }
3684+#endif
3685+            if ( ANSIColourImpl::useImplementationForStream( *stream ) ) {
3686+                return Detail::make_unique<ANSIColourImpl>( stream );
3687+            }
3688+            return Detail::make_unique<NoColourImpl>( stream );
3689+        }
3690+
3691+        CATCH_ERROR( "Could not create colour impl for selection " << static_cast<int>(colourSelection) );
3692+    }
3693+
3694+    bool isColourImplAvailable( ColourMode colourSelection ) {
3695+        switch ( colourSelection ) {
3696+#if defined( CATCH_CONFIG_COLOUR_WIN32 )
3697+        case ColourMode::Win32:
3698+#endif
3699+        case ColourMode::ANSI:
3700+        case ColourMode::None:
3701+        case ColourMode::PlatformDefault:
3702+            return true;
3703+        default:
3704+            return false;
3705+        }
3706+    }
3707+
3708+
3709+} // end namespace Catch
3710+
3711+#if defined(__clang__)
3712+#    pragma clang diagnostic pop
3713+#endif
3714+
3715+
3716+
3717+
3718+namespace Catch {
3719+
3720+    Context* Context::currentContext = nullptr;
3721+
3722+    void cleanUpContext() {
3723+        delete Context::currentContext;
3724+        Context::currentContext = nullptr;
3725+    }
3726+    void Context::createContext() {
3727+        currentContext = new Context();
3728+    }
3729+
3730+    Context& getCurrentMutableContext() {
3731+        if ( !Context::currentContext ) { Context::createContext(); }
3732+        // NOLINTNEXTLINE(clang-analyzer-core.uninitialized.UndefReturn)
3733+        return *Context::currentContext;
3734+    }
3735+
3736+    void Context::setResultCapture( IResultCapture* resultCapture ) {
3737+        m_resultCapture = resultCapture;
3738+    }
3739+
3740+    void Context::setConfig( IConfig const* config ) { m_config = config; }
3741+
3742+    SimplePcg32& sharedRng() {
3743+        static SimplePcg32 s_rng;
3744+        return s_rng;
3745+    }
3746+
3747+}
3748+
3749+
3750+
3751+
3752+
3753+#include <ostream>
3754+
3755+#if defined(CATCH_CONFIG_ANDROID_LOGWRITE)
3756+#include <android/log.h>
3757+
3758+    namespace Catch {
3759+        void writeToDebugConsole( std::string const& text ) {
3760+            __android_log_write( ANDROID_LOG_DEBUG, "Catch", text.c_str() );
3761+        }
3762+    }
3763+
3764+#elif defined(CATCH_PLATFORM_WINDOWS)
3765+
3766+    namespace Catch {
3767+        void writeToDebugConsole( std::string const& text ) {
3768+            ::OutputDebugStringA( text.c_str() );
3769+        }
3770+    }
3771+
3772+#else
3773+
3774+    namespace Catch {
3775+        void writeToDebugConsole( std::string const& text ) {
3776+            // !TBD: Need a version for Mac/ XCode and other IDEs
3777+            Catch::cout() << text;
3778+        }
3779+    }
3780+
3781+#endif // Platform
3782+
3783+
3784+
3785+#if defined(CATCH_PLATFORM_MAC) || defined(CATCH_PLATFORM_IPHONE)
3786+
3787+#  include <cassert>
3788+#  include <sys/types.h>
3789+#  include <unistd.h>
3790+#  include <cstddef>
3791+#  include <ostream>
3792+
3793+#ifdef __apple_build_version__
3794+    // These headers will only compile with AppleClang (XCode)
3795+    // For other compilers (Clang, GCC, ... ) we need to exclude them
3796+#  include <sys/sysctl.h>
3797+#endif
3798+
3799+    namespace Catch {
3800+        #ifdef __apple_build_version__
3801+        // The following function is taken directly from the following technical note:
3802+        // https://developer.apple.com/library/archive/qa/qa1361/_index.html
3803+
3804+        // Returns true if the current process is being debugged (either
3805+        // running under the debugger or has a debugger attached post facto).
3806+        bool isDebuggerActive(){
3807+            int                 mib[4];
3808+            struct kinfo_proc   info;
3809+            std::size_t         size;
3810+
3811+            // Initialize the flags so that, if sysctl fails for some bizarre
3812+            // reason, we get a predictable result.
3813+
3814+            info.kp_proc.p_flag = 0;
3815+
3816+            // Initialize mib, which tells sysctl the info we want, in this case
3817+            // we're looking for information about a specific process ID.
3818+
3819+            mib[0] = CTL_KERN;
3820+            mib[1] = KERN_PROC;
3821+            mib[2] = KERN_PROC_PID;
3822+            mib[3] = getpid();
3823+
3824+            // Call sysctl.
3825+
3826+            size = sizeof(info);
3827+            if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, nullptr, 0) != 0 ) {
3828+                Catch::cerr() << "\n** Call to sysctl failed - unable to determine if debugger is active **\n\n" << std::flush;
3829+                return false;
3830+            }
3831+
3832+            // We're being debugged if the P_TRACED flag is set.
3833+
3834+            return ( (info.kp_proc.p_flag & P_TRACED) != 0 );
3835+        }
3836+        #else
3837+        bool isDebuggerActive() {
3838+            // We need to find another way to determine this for non-appleclang compilers on macOS
3839+            return false;
3840+        }
3841+        #endif
3842+    } // namespace Catch
3843+
3844+#elif defined(CATCH_PLATFORM_LINUX)
3845+    #include <fstream>
3846+    #include <string>
3847+
3848+    namespace Catch{
3849+        // The standard POSIX way of detecting a debugger is to attempt to
3850+        // ptrace() the process, but this needs to be done from a child and not
3851+        // this process itself to still allow attaching to this process later
3852+        // if wanted, so is rather heavy. Under Linux we have the PID of the
3853+        // "debugger" (which doesn't need to be gdb, of course, it could also
3854+        // be strace, for example) in /proc/$PID/status, so just get it from
3855+        // there instead.
3856+        bool isDebuggerActive(){
3857+            // Libstdc++ has a bug, where std::ifstream sets errno to 0
3858+            // This way our users can properly assert over errno values
3859+            ErrnoGuard guard;
3860+            std::ifstream in("/proc/self/status");
3861+            for( std::string line; std::getline(in, line); ) {
3862+                static const int PREFIX_LEN = 11;
3863+                if( line.compare(0, PREFIX_LEN, "TracerPid:\t") == 0 ) {
3864+                    // We're traced if the PID is not 0 and no other PID starts
3865+                    // with 0 digit, so it's enough to check for just a single
3866+                    // character.
3867+                    return line.length() > PREFIX_LEN && line[PREFIX_LEN] != '0';
3868+                }
3869+            }
3870+
3871+            return false;
3872+        }
3873+    } // namespace Catch
3874+#elif defined(_MSC_VER)
3875+    extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
3876+    namespace Catch {
3877+        bool isDebuggerActive() {
3878+            return IsDebuggerPresent() != 0;
3879+        }
3880+    }
3881+#elif defined(__MINGW32__)
3882+    extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
3883+    namespace Catch {
3884+        bool isDebuggerActive() {
3885+            return IsDebuggerPresent() != 0;
3886+        }
3887+    }
3888+#else
3889+    namespace Catch {
3890+       bool isDebuggerActive() { return false; }
3891+    }
3892+#endif // Platform
3893+
3894+
3895+
3896+
3897+namespace Catch {
3898+
3899+    void ITransientExpression::streamReconstructedExpression(
3900+        std::ostream& os ) const {
3901+        // We can't make this function pure virtual to keep ITransientExpression
3902+        // constexpr, so we write error message instead
3903+        os << "Some class derived from ITransientExpression without overriding streamReconstructedExpression";
3904+    }
3905+
3906+    void formatReconstructedExpression( std::ostream &os, std::string const& lhs, StringRef op, std::string const& rhs ) {
3907+        if( lhs.size() + rhs.size() < 40 &&
3908+                lhs.find('\n') == std::string::npos &&
3909+                rhs.find('\n') == std::string::npos )
3910+            os << lhs << ' ' << op << ' ' << rhs;
3911+        else
3912+            os << lhs << '\n' << op << '\n' << rhs;
3913+    }
3914+}
3915+
3916+
3917+
3918+#include <stdexcept>
3919+
3920+
3921+namespace Catch {
3922+#if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) && !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS_CUSTOM_HANDLER)
3923+    [[noreturn]]
3924+    void throw_exception(std::exception const& e) {
3925+        Catch::cerr() << "Catch will terminate because it needed to throw an exception.\n"
3926+                      << "The message was: " << e.what() << '\n';
3927+        std::terminate();
3928+    }
3929+#endif
3930+
3931+    [[noreturn]]
3932+    void throw_logic_error(std::string const& msg) {
3933+        throw_exception(std::logic_error(msg));
3934+    }
3935+
3936+    [[noreturn]]
3937+    void throw_domain_error(std::string const& msg) {
3938+        throw_exception(std::domain_error(msg));
3939+    }
3940+
3941+    [[noreturn]]
3942+    void throw_runtime_error(std::string const& msg) {
3943+        throw_exception(std::runtime_error(msg));
3944+    }
3945+
3946+
3947+
3948+} // namespace Catch;
3949+
3950+
3951+
3952+#include <cassert>
3953+
3954+namespace Catch {
3955+
3956+    IMutableEnumValuesRegistry::~IMutableEnumValuesRegistry() = default;
3957+
3958+    namespace Detail {
3959+
3960+        namespace {
3961+            // Extracts the actual name part of an enum instance
3962+            // In other words, it returns the Blue part of Bikeshed::Colour::Blue
3963+            StringRef extractInstanceName(StringRef enumInstance) {
3964+                // Find last occurrence of ":"
3965+                size_t name_start = enumInstance.size();
3966+                while (name_start > 0 && enumInstance[name_start - 1] != ':') {
3967+                    --name_start;
3968+                }
3969+                return enumInstance.substr(name_start, enumInstance.size() - name_start);
3970+            }
3971+        }
3972+
3973+        std::vector<StringRef> parseEnums( StringRef enums ) {
3974+            auto enumValues = splitStringRef( enums, ',' );
3975+            std::vector<StringRef> parsed;
3976+            parsed.reserve( enumValues.size() );
3977+            for( auto const& enumValue : enumValues ) {
3978+                parsed.push_back(trim(extractInstanceName(enumValue)));
3979+            }
3980+            return parsed;
3981+        }
3982+
3983+        EnumInfo::~EnumInfo() = default;
3984+
3985+        StringRef EnumInfo::lookup( int value ) const {
3986+            for( auto const& valueToName : m_values ) {
3987+                if( valueToName.first == value )
3988+                    return valueToName.second;
3989+            }
3990+            return "{** unexpected enum value **}"_sr;
3991+        }
3992+
3993+        Catch::Detail::unique_ptr<EnumInfo> makeEnumInfo( StringRef enumName, StringRef allValueNames, std::vector<int> const& values ) {
3994+            auto enumInfo = Catch::Detail::make_unique<EnumInfo>();
3995+            enumInfo->m_name = enumName;
3996+            enumInfo->m_values.reserve( values.size() );
3997+
3998+            const auto valueNames = Catch::Detail::parseEnums( allValueNames );
3999+            assert( valueNames.size() == values.size() );
4000+            std::size_t i = 0;
4001+            for( auto value : values )
4002+                enumInfo->m_values.emplace_back(value, valueNames[i++]);
4003+
4004+            return enumInfo;
4005+        }
4006+
4007+        EnumInfo const& EnumValuesRegistry::registerEnum( StringRef enumName, StringRef allValueNames, std::vector<int> const& values ) {
4008+            m_enumInfos.push_back(makeEnumInfo(enumName, allValueNames, values));
4009+            return *m_enumInfos.back();
4010+        }
4011+
4012+    } // Detail
4013+} // Catch
4014+
4015+
4016+
4017+
4018+
4019+#include <cerrno>
4020+
4021+namespace Catch {
4022+        ErrnoGuard::ErrnoGuard():m_oldErrno(errno){}
4023+        ErrnoGuard::~ErrnoGuard() { errno = m_oldErrno; }
4024+}
4025+
4026+
4027+
4028+#include <exception>
4029+
4030+namespace Catch {
4031+
4032+#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
4033+    namespace {
4034+        static std::string tryTranslators(
4035+            std::vector<
4036+                Detail::unique_ptr<IExceptionTranslator const>> const& translators ) {
4037+            if ( translators.empty() ) {
4038+                std::rethrow_exception( std::current_exception() );
4039+            } else {
4040+                return translators[0]->translate( translators.begin() + 1,
4041+                                                  translators.end() );
4042+            }
4043+        }
4044+
4045+    }
4046+#endif //!defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
4047+
4048+    ExceptionTranslatorRegistry::~ExceptionTranslatorRegistry() = default;
4049+
4050+    void ExceptionTranslatorRegistry::registerTranslator( Detail::unique_ptr<IExceptionTranslator>&& translator ) {
4051+        m_translators.push_back( CATCH_MOVE( translator ) );
4052+    }
4053+
4054+#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
4055+    std::string ExceptionTranslatorRegistry::translateActiveException() const {
4056+        // Compiling a mixed mode project with MSVC means that CLR
4057+        // exceptions will be caught in (...) as well. However, these do
4058+        // do not fill-in std::current_exception and thus lead to crash
4059+        // when attempting rethrow.
4060+        // /EHa switch also causes structured exceptions to be caught
4061+        // here, but they fill-in current_exception properly, so
4062+        // at worst the output should be a little weird, instead of
4063+        // causing a crash.
4064+        if ( std::current_exception() == nullptr ) {
4065+            return "Non C++ exception. Possibly a CLR exception.";
4066+        }
4067+
4068+        // First we try user-registered translators. If none of them can
4069+        // handle the exception, it will be rethrown handled by our defaults.
4070+        try {
4071+            return tryTranslators(m_translators);
4072+        }
4073+        // To avoid having to handle TFE explicitly everywhere, we just
4074+        // rethrow it so that it goes back up the caller.
4075+        catch( TestFailureException& ) {
4076+            std::rethrow_exception(std::current_exception());
4077+        }
4078+        catch( TestSkipException& ) {
4079+            std::rethrow_exception(std::current_exception());
4080+        }
4081+        catch( std::exception const& ex ) {
4082+            return ex.what();
4083+        }
4084+        catch( std::string const& msg ) {
4085+            return msg;
4086+        }
4087+        catch( const char* msg ) {
4088+            return msg;
4089+        }
4090+        catch(...) {
4091+            return "Unknown exception";
4092+        }
4093+    }
4094+
4095+#else // ^^ Exceptions are enabled // Exceptions are disabled vv
4096+    std::string ExceptionTranslatorRegistry::translateActiveException() const {
4097+        CATCH_INTERNAL_ERROR("Attempted to translate active exception under CATCH_CONFIG_DISABLE_EXCEPTIONS!");
4098+    }
4099+#endif
4100+
4101+}
4102+
4103+
4104+
4105+/** \file
4106+ * This file provides platform specific implementations of FatalConditionHandler
4107+ *
4108+ * This means that there is a lot of conditional compilation, and platform
4109+ * specific code. Currently, Catch2 supports a dummy handler (if no
4110+ * handler is desired), and 2 platform specific handlers:
4111+ *  * Windows' SEH
4112+ *  * POSIX signals
4113+ *
4114+ * Consequently, various pieces of code below are compiled if either of
4115+ * the platform specific handlers is enabled, or if none of them are
4116+ * enabled. It is assumed that both cannot be enabled at the same time,
4117+ * and doing so should cause a compilation error.
4118+ *
4119+ * If another platform specific handler is added, the compile guards
4120+ * below will need to be updated taking these assumptions into account.
4121+ */
4122+
4123+
4124+
4125+#include <algorithm>
4126+
4127+#if !defined( CATCH_CONFIG_WINDOWS_SEH ) && !defined( CATCH_CONFIG_POSIX_SIGNALS )
4128+
4129+namespace Catch {
4130+
4131+    // If neither SEH nor signal handling is required, the handler impls
4132+    // do not have to do anything, and can be empty.
4133+    void FatalConditionHandler::engage_platform() {}
4134+    void FatalConditionHandler::disengage_platform() noexcept {}
4135+    FatalConditionHandler::FatalConditionHandler() = default;
4136+    FatalConditionHandler::~FatalConditionHandler() = default;
4137+
4138+} // end namespace Catch
4139+
4140+#endif // !CATCH_CONFIG_WINDOWS_SEH && !CATCH_CONFIG_POSIX_SIGNALS
4141+
4142+#if defined( CATCH_CONFIG_WINDOWS_SEH ) && defined( CATCH_CONFIG_POSIX_SIGNALS )
4143+#error "Inconsistent configuration: Windows' SEH handling and POSIX signals cannot be enabled at the same time"
4144+#endif // CATCH_CONFIG_WINDOWS_SEH && CATCH_CONFIG_POSIX_SIGNALS
4145+
4146+#if defined( CATCH_CONFIG_WINDOWS_SEH ) || defined( CATCH_CONFIG_POSIX_SIGNALS )
4147+
4148+namespace {
4149+    //! Signals fatal error message to the run context
4150+    void reportFatal( char const * const message ) {
4151+        Catch::getCurrentContext().getResultCapture()->handleFatalErrorCondition( message );
4152+    }
4153+
4154+    //! Minimal size Catch2 needs for its own fatal error handling.
4155+    //! Picked empirically, so it might not be sufficient on all
4156+    //! platforms, and for all configurations.
4157+    constexpr std::size_t minStackSizeForErrors = 32 * 1024;
4158+} // end unnamed namespace
4159+
4160+#endif // CATCH_CONFIG_WINDOWS_SEH || CATCH_CONFIG_POSIX_SIGNALS
4161+
4162+#if defined( CATCH_CONFIG_WINDOWS_SEH )
4163+
4164+namespace Catch {
4165+
4166+    struct SignalDefs { DWORD id; const char* name; };
4167+
4168+    // There is no 1-1 mapping between signals and windows exceptions.
4169+    // Windows can easily distinguish between SO and SigSegV,
4170+    // but SigInt, SigTerm, etc are handled differently.
4171+    static SignalDefs signalDefs[] = {
4172+        { EXCEPTION_ILLEGAL_INSTRUCTION,  "SIGILL - Illegal instruction signal" },
4173+        { EXCEPTION_STACK_OVERFLOW, "SIGSEGV - Stack overflow" },
4174+        { EXCEPTION_ACCESS_VIOLATION, "SIGSEGV - Segmentation violation signal" },
4175+        { EXCEPTION_INT_DIVIDE_BY_ZERO, "Divide by zero error" },
4176+    };
4177+
4178+    static LONG CALLBACK topLevelExceptionFilter(PEXCEPTION_POINTERS ExceptionInfo) {
4179+        for (auto const& def : signalDefs) {
4180+            if (ExceptionInfo->ExceptionRecord->ExceptionCode == def.id) {
4181+                reportFatal(def.name);
4182+            }
4183+        }
4184+        // If its not an exception we care about, pass it along.
4185+        // This stops us from eating debugger breaks etc.
4186+        return EXCEPTION_CONTINUE_SEARCH;
4187+    }
4188+
4189+    // Since we do not support multiple instantiations, we put these
4190+    // into global variables and rely on cleaning them up in outlined
4191+    // constructors/destructors
4192+    static LPTOP_LEVEL_EXCEPTION_FILTER previousTopLevelExceptionFilter = nullptr;
4193+
4194+
4195+    // For MSVC, we reserve part of the stack memory for handling
4196+    // memory overflow structured exception.
4197+    FatalConditionHandler::FatalConditionHandler() {
4198+        ULONG guaranteeSize = static_cast<ULONG>(minStackSizeForErrors);
4199+        if (!SetThreadStackGuarantee(&guaranteeSize)) {
4200+            // We do not want to fully error out, because needing
4201+            // the stack reserve should be rare enough anyway.
4202+            Catch::cerr()
4203+                << "Failed to reserve piece of stack."
4204+                << " Stack overflows will not be reported successfully.";
4205+        }
4206+    }
4207+
4208+    // We do not attempt to unset the stack guarantee, because
4209+    // Windows does not support lowering the stack size guarantee.
4210+    FatalConditionHandler::~FatalConditionHandler() = default;
4211+
4212+
4213+    void FatalConditionHandler::engage_platform() {
4214+        // Register as a the top level exception filter.
4215+        previousTopLevelExceptionFilter = SetUnhandledExceptionFilter(topLevelExceptionFilter);
4216+    }
4217+
4218+    void FatalConditionHandler::disengage_platform() noexcept {
4219+        if (SetUnhandledExceptionFilter(previousTopLevelExceptionFilter) != topLevelExceptionFilter) {
4220+            Catch::cerr()
4221+                << "Unexpected SEH unhandled exception filter on disengage."
4222+                << " The filter was restored, but might be rolled back unexpectedly.";
4223+        }
4224+        previousTopLevelExceptionFilter = nullptr;
4225+    }
4226+
4227+} // end namespace Catch
4228+
4229+#endif // CATCH_CONFIG_WINDOWS_SEH
4230+
4231+#if defined( CATCH_CONFIG_POSIX_SIGNALS )
4232+
4233+#include <signal.h>
4234+
4235+namespace Catch {
4236+
4237+    struct SignalDefs {
4238+        int id;
4239+        const char* name;
4240+    };
4241+
4242+    static SignalDefs signalDefs[] = {
4243+        { SIGINT,  "SIGINT - Terminal interrupt signal" },
4244+        { SIGILL,  "SIGILL - Illegal instruction signal" },
4245+        { SIGFPE,  "SIGFPE - Floating point error signal" },
4246+        { SIGSEGV, "SIGSEGV - Segmentation violation signal" },
4247+        { SIGTERM, "SIGTERM - Termination request signal" },
4248+        { SIGABRT, "SIGABRT - Abort (abnormal termination) signal" }
4249+    };
4250+
4251+// Older GCCs trigger -Wmissing-field-initializers for T foo = {}
4252+// which is zero initialization, but not explicit. We want to avoid
4253+// that.
4254+#if defined(__GNUC__)
4255+#    pragma GCC diagnostic push
4256+#    pragma GCC diagnostic ignored "-Wmissing-field-initializers"
4257+#endif
4258+
4259+    static char* altStackMem = nullptr;
4260+    static std::size_t altStackSize = 0;
4261+    static stack_t oldSigStack{};
4262+    static struct sigaction oldSigActions[sizeof(signalDefs) / sizeof(SignalDefs)]{};
4263+
4264+    static void restorePreviousSignalHandlers() noexcept {
4265+        // We set signal handlers back to the previous ones. Hopefully
4266+        // nobody overwrote them in the meantime, and doesn't expect
4267+        // their signal handlers to live past ours given that they
4268+        // installed them after ours..
4269+        for (std::size_t i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) {
4270+            sigaction(signalDefs[i].id, &oldSigActions[i], nullptr);
4271+        }
4272+        // Return the old stack
4273+        sigaltstack(&oldSigStack, nullptr);
4274+    }
4275+
4276+    static void handleSignal( int sig ) {
4277+        char const * name = "<unknown signal>";
4278+        for (auto const& def : signalDefs) {
4279+            if (sig == def.id) {
4280+                name = def.name;
4281+                break;
4282+            }
4283+        }
4284+        // We need to restore previous signal handlers and let them do
4285+        // their thing, so that the users can have the debugger break
4286+        // when a signal is raised, and so on.
4287+        restorePreviousSignalHandlers();
4288+        reportFatal( name );
4289+        raise( sig );
4290+    }
4291+
4292+    FatalConditionHandler::FatalConditionHandler() {
4293+        assert(!altStackMem && "Cannot initialize POSIX signal handler when one already exists");
4294+        if (altStackSize == 0) {
4295+            altStackSize = std::max(static_cast<size_t>(SIGSTKSZ), minStackSizeForErrors);
4296+        }
4297+        altStackMem = new char[altStackSize]();
4298+    }
4299+
4300+    FatalConditionHandler::~FatalConditionHandler() {
4301+        delete[] altStackMem;
4302+        // We signal that another instance can be constructed by zeroing
4303+        // out the pointer.
4304+        altStackMem = nullptr;
4305+    }
4306+
4307+    void FatalConditionHandler::engage_platform() {
4308+        stack_t sigStack;
4309+        sigStack.ss_sp = altStackMem;
4310+        sigStack.ss_size = altStackSize;
4311+        sigStack.ss_flags = 0;
4312+        sigaltstack(&sigStack, &oldSigStack);
4313+        struct sigaction sa = { };
4314+
4315+        sa.sa_handler = handleSignal;
4316+        sa.sa_flags = SA_ONSTACK;
4317+        for (std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i) {
4318+            sigaction(signalDefs[i].id, &sa, &oldSigActions[i]);
4319+        }
4320+    }
4321+
4322+#if defined(__GNUC__)
4323+#    pragma GCC diagnostic pop
4324+#endif
4325+
4326+
4327+    void FatalConditionHandler::disengage_platform() noexcept {
4328+        restorePreviousSignalHandlers();
4329+    }
4330+
4331+} // end namespace Catch
4332+
4333+#endif // CATCH_CONFIG_POSIX_SIGNALS
4334+
4335+
4336+
4337+
4338+#include <cstring>
4339+
4340+namespace Catch {
4341+    namespace Detail {
4342+
4343+        uint32_t convertToBits(float f) {
4344+            static_assert(sizeof(float) == sizeof(uint32_t), "Important ULP matcher assumption violated");
4345+            uint32_t i;
4346+            std::memcpy(&i, &f, sizeof(f));
4347+            return i;
4348+        }
4349+
4350+        uint64_t convertToBits(double d) {
4351+            static_assert(sizeof(double) == sizeof(uint64_t), "Important ULP matcher assumption violated");
4352+            uint64_t i;
4353+            std::memcpy(&i, &d, sizeof(d));
4354+            return i;
4355+        }
4356+
4357+#if defined( __GNUC__ ) || defined( __clang__ )
4358+#    pragma GCC diagnostic push
4359+#    pragma GCC diagnostic ignored "-Wfloat-equal"
4360+#endif
4361+        bool directCompare( float lhs, float rhs ) { return lhs == rhs; }
4362+        bool directCompare( double lhs, double rhs ) { return lhs == rhs; }
4363+#if defined( __GNUC__ ) || defined( __clang__ )
4364+#    pragma GCC diagnostic pop
4365+#endif
4366+
4367+
4368+    } // end namespace Detail
4369+} // end namespace Catch
4370+
4371+
4372+
4373+
4374+
4375+
4376+#include <cstdlib>
4377+
4378+namespace Catch {
4379+    namespace Detail {
4380+
4381+#if !defined (CATCH_CONFIG_GETENV)
4382+        char const* getEnv( char const* ) { return nullptr; }
4383+#else
4384+
4385+        char const* getEnv( char const* varName ) {
4386+#    if defined( _MSC_VER )
4387+#        pragma warning( push )
4388+#        pragma warning( disable : 4996 ) // use getenv_s instead of getenv
4389+#    endif
4390+
4391+            return std::getenv( varName );
4392+
4393+#    if defined( _MSC_VER )
4394+#        pragma warning( pop )
4395+#    endif
4396+        }
4397+#endif
4398+} // namespace Detail
4399+} // namespace Catch
4400+
4401+
4402+
4403+
4404+#include <cstdio>
4405+#include <fstream>
4406+#include <sstream>
4407+#include <vector>
4408+
4409+namespace Catch {
4410+
4411+    Catch::IStream::~IStream() = default;
4412+
4413+namespace Detail {
4414+    namespace {
4415+        template<typename WriterF, std::size_t bufferSize=256>
4416+        class StreamBufImpl final : public std::streambuf {
4417+            char data[bufferSize];
4418+            WriterF m_writer;
4419+
4420+        public:
4421+            StreamBufImpl() {
4422+                setp( data, data + sizeof(data) );
4423+            }
4424+
4425+            ~StreamBufImpl() noexcept override {
4426+                StreamBufImpl::sync();
4427+            }
4428+
4429+        private:
4430+            int overflow( int c ) override {
4431+                sync();
4432+
4433+                if( c != EOF ) {
4434+                    if( pbase() == epptr() )
4435+                        m_writer( std::string( 1, static_cast<char>( c ) ) );
4436+                    else
4437+                        sputc( static_cast<char>( c ) );
4438+                }
4439+                return 0;
4440+            }
4441+
4442+            int sync() override {
4443+                if( pbase() != pptr() ) {
4444+                    m_writer( std::string( pbase(), static_cast<std::string::size_type>( pptr() - pbase() ) ) );
4445+                    setp( pbase(), epptr() );
4446+                }
4447+                return 0;
4448+            }
4449+        };
4450+
4451+        ///////////////////////////////////////////////////////////////////////////
4452+
4453+        struct OutputDebugWriter {
4454+
4455+            void operator()( std::string const& str ) {
4456+                if ( !str.empty() ) {
4457+                    writeToDebugConsole( str );
4458+                }
4459+            }
4460+        };
4461+
4462+        ///////////////////////////////////////////////////////////////////////////
4463+
4464+        class FileStream final : public IStream {
4465+            std::ofstream m_ofs;
4466+        public:
4467+            FileStream( std::string const& filename ) {
4468+                m_ofs.open( filename.c_str() );
4469+                CATCH_ENFORCE( !m_ofs.fail(), "Unable to open file: '" << filename << '\'' );
4470+                m_ofs << std::unitbuf;
4471+            }
4472+        public: // IStream
4473+            std::ostream& stream() override {
4474+                return m_ofs;
4475+            }
4476+        };
4477+
4478+        ///////////////////////////////////////////////////////////////////////////
4479+
4480+        class CoutStream final : public IStream {
4481+            std::ostream m_os;
4482+        public:
4483+            // Store the streambuf from cout up-front because
4484+            // cout may get redirected when running tests
4485+            CoutStream() : m_os( Catch::cout().rdbuf() ) {}
4486+
4487+        public: // IStream
4488+            std::ostream& stream() override { return m_os; }
4489+            bool isConsole() const override { return true; }
4490+        };
4491+
4492+        class CerrStream : public IStream {
4493+            std::ostream m_os;
4494+
4495+        public:
4496+            // Store the streambuf from cerr up-front because
4497+            // cout may get redirected when running tests
4498+            CerrStream(): m_os( Catch::cerr().rdbuf() ) {}
4499+
4500+        public: // IStream
4501+            std::ostream& stream() override { return m_os; }
4502+            bool isConsole() const override { return true; }
4503+        };
4504+
4505+        ///////////////////////////////////////////////////////////////////////////
4506+
4507+        class DebugOutStream final : public IStream {
4508+            Detail::unique_ptr<StreamBufImpl<OutputDebugWriter>> m_streamBuf;
4509+            std::ostream m_os;
4510+        public:
4511+            DebugOutStream()
4512+            :   m_streamBuf( Detail::make_unique<StreamBufImpl<OutputDebugWriter>>() ),
4513+                m_os( m_streamBuf.get() )
4514+            {}
4515+
4516+        public: // IStream
4517+            std::ostream& stream() override { return m_os; }
4518+        };
4519+
4520+    } // unnamed namespace
4521+} // namespace Detail
4522+
4523+    ///////////////////////////////////////////////////////////////////////////
4524+
4525+    auto makeStream( std::string const& filename ) -> Detail::unique_ptr<IStream> {
4526+        if ( filename.empty() || filename == "-" ) {
4527+            return Detail::make_unique<Detail::CoutStream>();
4528+        }
4529+        if( filename[0] == '%' ) {
4530+            if ( filename == "%debug" ) {
4531+                return Detail::make_unique<Detail::DebugOutStream>();
4532+            } else if ( filename == "%stderr" ) {
4533+                return Detail::make_unique<Detail::CerrStream>();
4534+            } else if ( filename == "%stdout" ) {
4535+                return Detail::make_unique<Detail::CoutStream>();
4536+            } else {
4537+                CATCH_ERROR( "Unrecognised stream: '" << filename << '\'' );
4538+            }
4539+        }
4540+        return Detail::make_unique<Detail::FileStream>( filename );
4541+    }
4542+
4543+}
4544+
4545+
4546+
4547+namespace Catch {
4548+    void JsonUtils::indent( std::ostream& os, std::uint64_t level ) {
4549+        for ( std::uint64_t i = 0; i < level; ++i ) {
4550+            os << "  ";
4551+        }
4552+    }
4553+    void JsonUtils::appendCommaNewline( std::ostream& os,
4554+                                        bool& should_comma,
4555+                                        std::uint64_t level ) {
4556+        if ( should_comma ) { os << ','; }
4557+        should_comma = true;
4558+        os << '\n';
4559+        indent( os, level );
4560+    }
4561+
4562+    JsonObjectWriter::JsonObjectWriter( std::ostream& os ):
4563+        JsonObjectWriter{ os, 0 } {}
4564+
4565+    JsonObjectWriter::JsonObjectWriter( std::ostream& os,
4566+                                        std::uint64_t indent_level ):
4567+        m_os{ os }, m_indent_level{ indent_level } {
4568+        m_os << '{';
4569+    }
4570+    JsonObjectWriter::JsonObjectWriter( JsonObjectWriter&& source ) noexcept:
4571+        m_os{ source.m_os },
4572+        m_indent_level{ source.m_indent_level },
4573+        m_should_comma{ source.m_should_comma },
4574+        m_active{ source.m_active } {
4575+        source.m_active = false;
4576+    }
4577+
4578+    JsonObjectWriter::~JsonObjectWriter() {
4579+        if ( !m_active ) { return; }
4580+
4581+        m_os << '\n';
4582+        JsonUtils::indent( m_os, m_indent_level );
4583+        m_os << '}';
4584+    }
4585+
4586+    JsonValueWriter JsonObjectWriter::write( StringRef key ) {
4587+        JsonUtils::appendCommaNewline(
4588+            m_os, m_should_comma, m_indent_level + 1 );
4589+
4590+        m_os << '"' << key << "\": ";
4591+        return JsonValueWriter{ m_os, m_indent_level + 1 };
4592+    }
4593+
4594+    JsonArrayWriter::JsonArrayWriter( std::ostream& os ):
4595+        JsonArrayWriter{ os, 0 } {}
4596+    JsonArrayWriter::JsonArrayWriter( std::ostream& os,
4597+                                      std::uint64_t indent_level ):
4598+        m_os{ os }, m_indent_level{ indent_level } {
4599+        m_os << '[';
4600+    }
4601+    JsonArrayWriter::JsonArrayWriter( JsonArrayWriter&& source ) noexcept:
4602+        m_os{ source.m_os },
4603+        m_indent_level{ source.m_indent_level },
4604+        m_should_comma{ source.m_should_comma },
4605+        m_active{ source.m_active } {
4606+        source.m_active = false;
4607+    }
4608+    JsonArrayWriter::~JsonArrayWriter() {
4609+        if ( !m_active ) { return; }
4610+
4611+        m_os << '\n';
4612+        JsonUtils::indent( m_os, m_indent_level );
4613+        m_os << ']';
4614+    }
4615+
4616+    JsonObjectWriter JsonArrayWriter::writeObject() {
4617+        JsonUtils::appendCommaNewline(
4618+            m_os, m_should_comma, m_indent_level + 1 );
4619+        return JsonObjectWriter{ m_os, m_indent_level + 1 };
4620+    }
4621+
4622+    JsonArrayWriter JsonArrayWriter::writeArray() {
4623+        JsonUtils::appendCommaNewline(
4624+            m_os, m_should_comma, m_indent_level + 1 );
4625+        return JsonArrayWriter{ m_os, m_indent_level + 1 };
4626+    }
4627+
4628+    JsonArrayWriter& JsonArrayWriter::write( bool value ) {
4629+        return writeImpl( value );
4630+    }
4631+
4632+    JsonValueWriter::JsonValueWriter( std::ostream& os ):
4633+        JsonValueWriter{ os, 0 } {}
4634+
4635+    JsonValueWriter::JsonValueWriter( std::ostream& os,
4636+                                      std::uint64_t indent_level ):
4637+        m_os{ os }, m_indent_level{ indent_level } {}
4638+
4639+    JsonObjectWriter JsonValueWriter::writeObject() && {
4640+        return JsonObjectWriter{ m_os, m_indent_level };
4641+    }
4642+
4643+    JsonArrayWriter JsonValueWriter::writeArray() && {
4644+        return JsonArrayWriter{ m_os, m_indent_level };
4645+    }
4646+
4647+    void JsonValueWriter::write( Catch::StringRef value ) && {
4648+        writeImpl( value, true );
4649+    }
4650+
4651+    void JsonValueWriter::write( bool value ) && {
4652+        writeImpl( value ? "true"_sr : "false"_sr, false );
4653+    }
4654+
4655+    void JsonValueWriter::writeImpl( Catch::StringRef value, bool quote ) {
4656+        if ( quote ) { m_os << '"'; }
4657+        for (char c : value) {
4658+            // Escape list taken from https://www.json.org/json-en.html,
4659+            // string definition.
4660+            // Note that while forward slash _can_ be escaped, it does
4661+            // not have to be, if JSON is not further embedded somewhere
4662+            // where forward slash is meaningful.
4663+            if ( c == '"' ) {
4664+                m_os << "\\\"";
4665+            } else if ( c == '\\' ) {
4666+                m_os << "\\\\";
4667+            } else if ( c == '\b' ) {
4668+                m_os << "\\b";
4669+            } else if ( c == '\f' ) {
4670+                m_os << "\\f";
4671+            } else if ( c == '\n' ) {
4672+                m_os << "\\n";
4673+            } else if ( c == '\r' ) {
4674+                m_os << "\\r";
4675+            } else if ( c == '\t' ) {
4676+                m_os << "\\t";
4677+            } else {
4678+                m_os << c;
4679+            }
4680+        }
4681+        if ( quote ) { m_os << '"'; }
4682+    }
4683+
4684+} // namespace Catch
4685+
4686+
4687+
4688+
4689+namespace Catch {
4690+
4691+    auto operator << (std::ostream& os, LazyExpression const& lazyExpr) -> std::ostream& {
4692+        if (lazyExpr.m_isNegated)
4693+            os << '!';
4694+
4695+        if (lazyExpr) {
4696+            if (lazyExpr.m_isNegated && lazyExpr.m_transientExpression->isBinaryExpression())
4697+                os << '(' << *lazyExpr.m_transientExpression << ')';
4698+            else
4699+                os << *lazyExpr.m_transientExpression;
4700+        } else {
4701+            os << "{** error - unchecked empty expression requested **}";
4702+        }
4703+        return os;
4704+    }
4705+
4706+} // namespace Catch
4707+
4708+
4709+
4710+
4711+#ifdef CATCH_CONFIG_WINDOWS_CRTDBG
4712+#include <crtdbg.h>
4713+
4714+namespace Catch {
4715+
4716+    LeakDetector::LeakDetector() {
4717+        int flag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
4718+        flag |= _CRTDBG_LEAK_CHECK_DF;
4719+        flag |= _CRTDBG_ALLOC_MEM_DF;
4720+        _CrtSetDbgFlag(flag);
4721+        _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
4722+        _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
4723+        // Change this to leaking allocation's number to break there
4724+        _CrtSetBreakAlloc(-1);
4725+    }
4726+}
4727+
4728+#else // ^^ Windows crt debug heap enabled // Windows crt debug heap disabled vv
4729+
4730+    Catch::LeakDetector::LeakDetector() = default;
4731+
4732+#endif // CATCH_CONFIG_WINDOWS_CRTDBG
4733+
4734+Catch::LeakDetector::~LeakDetector() {
4735+    Catch::cleanUp();
4736+}
4737+
4738+
4739+
4740+
4741+namespace Catch {
4742+    namespace {
4743+
4744+        void listTests(IEventListener& reporter, IConfig const& config) {
4745+            auto const& testSpec = config.testSpec();
4746+            auto matchedTestCases = filterTests(getAllTestCasesSorted(config), testSpec, config);
4747+            reporter.listTests(matchedTestCases);
4748+        }
4749+
4750+        void listTags(IEventListener& reporter, IConfig const& config) {
4751+            auto const& testSpec = config.testSpec();
4752+            std::vector<TestCaseHandle> matchedTestCases = filterTests(getAllTestCasesSorted(config), testSpec, config);
4753+
4754+            std::map<StringRef, TagInfo, Detail::CaseInsensitiveLess> tagCounts;
4755+            for (auto const& testCase : matchedTestCases) {
4756+                for (auto const& tagName : testCase.getTestCaseInfo().tags) {
4757+                    auto it = tagCounts.find(tagName.original);
4758+                    if (it == tagCounts.end())
4759+                        it = tagCounts.insert(std::make_pair(tagName.original, TagInfo())).first;
4760+                    it->second.add(tagName.original);
4761+                }
4762+            }
4763+
4764+            std::vector<TagInfo> infos; infos.reserve(tagCounts.size());
4765+            for (auto& tagc : tagCounts) {
4766+                infos.push_back(CATCH_MOVE(tagc.second));
4767+            }
4768+
4769+            reporter.listTags(infos);
4770+        }
4771+
4772+        void listReporters(IEventListener& reporter) {
4773+            std::vector<ReporterDescription> descriptions;
4774+
4775+            auto const& factories = getRegistryHub().getReporterRegistry().getFactories();
4776+            descriptions.reserve(factories.size());
4777+            for (auto const& fac : factories) {
4778+                descriptions.push_back({ fac.first, fac.second->getDescription() });
4779+            }
4780+
4781+            reporter.listReporters(descriptions);
4782+        }
4783+
4784+        void listListeners(IEventListener& reporter) {
4785+            std::vector<ListenerDescription> descriptions;
4786+
4787+            auto const& factories =
4788+                getRegistryHub().getReporterRegistry().getListeners();
4789+            descriptions.reserve( factories.size() );
4790+            for ( auto const& fac : factories ) {
4791+                descriptions.push_back( { fac->getName(), fac->getDescription() } );
4792+            }
4793+
4794+            reporter.listListeners( descriptions );
4795+        }
4796+
4797+    } // end anonymous namespace
4798+
4799+    void TagInfo::add( StringRef spelling ) {
4800+        ++count;
4801+        spellings.insert( spelling );
4802+    }
4803+
4804+    std::string TagInfo::all() const {
4805+        // 2 per tag for brackets '[' and ']'
4806+        size_t size =  spellings.size() * 2;
4807+        for (auto const& spelling : spellings) {
4808+            size += spelling.size();
4809+        }
4810+
4811+        std::string out; out.reserve(size);
4812+        for (auto const& spelling : spellings) {
4813+            out += '[';
4814+            out += spelling;
4815+            out += ']';
4816+        }
4817+        return out;
4818+    }
4819+
4820+    bool list( IEventListener& reporter, Config const& config ) {
4821+        bool listed = false;
4822+        if (config.listTests()) {
4823+            listed = true;
4824+            listTests(reporter, config);
4825+        }
4826+        if (config.listTags()) {
4827+            listed = true;
4828+            listTags(reporter, config);
4829+        }
4830+        if (config.listReporters()) {
4831+            listed = true;
4832+            listReporters(reporter);
4833+        }
4834+        if ( config.listListeners() ) {
4835+            listed = true;
4836+            listListeners( reporter );
4837+        }
4838+        return listed;
4839+    }
4840+
4841+} // end namespace Catch
4842+
4843+
4844+
4845+namespace Catch {
4846+    CATCH_INTERNAL_START_WARNINGS_SUPPRESSION
4847+    CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS
4848+    static LeakDetector leakDetector;
4849+    CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
4850+}
4851+
4852+// Allow users of amalgamated .cpp file to remove our main and provide their own.
4853+#if !defined(CATCH_AMALGAMATED_CUSTOM_MAIN)
4854+
4855+#if defined(CATCH_CONFIG_WCHAR) && defined(CATCH_PLATFORM_WINDOWS) && defined(_UNICODE) && !defined(DO_NOT_USE_WMAIN)
4856+// Standard C/C++ Win32 Unicode wmain entry point
4857+extern "C" int __cdecl wmain (int argc, wchar_t * argv[], wchar_t * []) {
4858+#else
4859+// Standard C/C++ main entry point
4860+int main (int argc, char * argv[]) {
4861+#endif
4862+
4863+    // We want to force the linker not to discard the global variable
4864+    // and its constructor, as it (optionally) registers leak detector
4865+    (void)&Catch::leakDetector;
4866+
4867+    return Catch::Session().run( argc, argv );
4868+}
4869+
4870+#endif // !defined(CATCH_AMALGAMATED_CUSTOM_MAIN
4871+
4872+
4873+
4874+
4875+namespace Catch {
4876+
4877+    MessageInfo::MessageInfo(   StringRef _macroName,
4878+                                SourceLineInfo const& _lineInfo,
4879+                                ResultWas::OfType _type )
4880+    :   macroName( _macroName ),
4881+        lineInfo( _lineInfo ),
4882+        type( _type ),
4883+        sequence( ++globalCount )
4884+    {}
4885+
4886+    // This may need protecting if threading support is added
4887+    unsigned int MessageInfo::globalCount = 0;
4888+
4889+} // end namespace Catch
4890+
4891+
4892+
4893+#include <cstdio>
4894+#include <cstring>
4895+#include <sstream>
4896+
4897+#if defined(CATCH_CONFIG_NEW_CAPTURE)
4898+    #if defined(_MSC_VER)
4899+    #include <io.h>      //_dup and _dup2
4900+    #define dup _dup
4901+    #define dup2 _dup2
4902+    #define fileno _fileno
4903+    #else
4904+    #include <unistd.h>  // dup and dup2
4905+    #endif
4906+#endif
4907+
4908+
4909+namespace Catch {
4910+
4911+    RedirectedStream::RedirectedStream( std::ostream& originalStream, std::ostream& redirectionStream )
4912+    :   m_originalStream( originalStream ),
4913+        m_redirectionStream( redirectionStream ),
4914+        m_prevBuf( m_originalStream.rdbuf() )
4915+    {
4916+        m_originalStream.rdbuf( m_redirectionStream.rdbuf() );
4917+    }
4918+
4919+    RedirectedStream::~RedirectedStream() {
4920+        m_originalStream.rdbuf( m_prevBuf );
4921+    }
4922+
4923+    RedirectedStdOut::RedirectedStdOut() : m_cout( Catch::cout(), m_rss.get() ) {}
4924+    auto RedirectedStdOut::str() const -> std::string { return m_rss.str(); }
4925+
4926+    RedirectedStdErr::RedirectedStdErr()
4927+    :   m_cerr( Catch::cerr(), m_rss.get() ),
4928+        m_clog( Catch::clog(), m_rss.get() )
4929+    {}
4930+    auto RedirectedStdErr::str() const -> std::string { return m_rss.str(); }
4931+
4932+    RedirectedStreams::RedirectedStreams(std::string& redirectedCout, std::string& redirectedCerr)
4933+    :   m_redirectedCout(redirectedCout),
4934+        m_redirectedCerr(redirectedCerr)
4935+    {}
4936+
4937+    RedirectedStreams::~RedirectedStreams() {
4938+        m_redirectedCout += m_redirectedStdOut.str();
4939+        m_redirectedCerr += m_redirectedStdErr.str();
4940+    }
4941+
4942+#if defined(CATCH_CONFIG_NEW_CAPTURE)
4943+
4944+#if defined(_MSC_VER)
4945+    TempFile::TempFile() {
4946+        if (tmpnam_s(m_buffer)) {
4947+            CATCH_RUNTIME_ERROR("Could not get a temp filename");
4948+        }
4949+        if (fopen_s(&m_file, m_buffer, "w+")) {
4950+            char buffer[100];
4951+            if (strerror_s(buffer, errno)) {
4952+                CATCH_RUNTIME_ERROR("Could not translate errno to a string");
4953+            }
4954+            CATCH_RUNTIME_ERROR("Could not open the temp file: '" << m_buffer << "' because: " << buffer);
4955+        }
4956+    }
4957+#else
4958+    TempFile::TempFile() {
4959+        m_file = std::tmpfile();
4960+        if (!m_file) {
4961+            CATCH_RUNTIME_ERROR("Could not create a temp file.");
4962+        }
4963+    }
4964+
4965+#endif
4966+
4967+    TempFile::~TempFile() {
4968+         // TBD: What to do about errors here?
4969+         std::fclose(m_file);
4970+         // We manually create the file on Windows only, on Linux
4971+         // it will be autodeleted
4972+#if defined(_MSC_VER)
4973+         std::remove(m_buffer);
4974+#endif
4975+    }
4976+
4977+
4978+    FILE* TempFile::getFile() {
4979+        return m_file;
4980+    }
4981+
4982+    std::string TempFile::getContents() {
4983+        std::stringstream sstr;
4984+        char buffer[100] = {};
4985+        std::rewind(m_file);
4986+        while (std::fgets(buffer, sizeof(buffer), m_file)) {
4987+            sstr << buffer;
4988+        }
4989+        return sstr.str();
4990+    }
4991+
4992+    OutputRedirect::OutputRedirect(std::string& stdout_dest, std::string& stderr_dest) :
4993+        m_originalStdout(dup(1)),
4994+        m_originalStderr(dup(2)),
4995+        m_stdoutDest(stdout_dest),
4996+        m_stderrDest(stderr_dest) {
4997+        dup2(fileno(m_stdoutFile.getFile()), 1);
4998+        dup2(fileno(m_stderrFile.getFile()), 2);
4999+    }
5000+
5001+    OutputRedirect::~OutputRedirect() {
5002+        Catch::cout() << std::flush;
5003+        fflush(stdout);
5004+        // Since we support overriding these streams, we flush cerr
5005+        // even though std::cerr is unbuffered
5006+        Catch::cerr() << std::flush;
5007+        Catch::clog() << std::flush;
5008+        fflush(stderr);
5009+
5010+        dup2(m_originalStdout, 1);
5011+        dup2(m_originalStderr, 2);
5012+
5013+        m_stdoutDest += m_stdoutFile.getContents();
5014+        m_stderrDest += m_stderrFile.getContents();
5015+    }
5016+
5017+#endif // CATCH_CONFIG_NEW_CAPTURE
5018+
5019+} // namespace Catch
5020+
5021+#if defined(CATCH_CONFIG_NEW_CAPTURE)
5022+    #if defined(_MSC_VER)
5023+    #undef dup
5024+    #undef dup2
5025+    #undef fileno
5026+    #endif
5027+#endif
5028+
5029+
5030+
5031+
5032+#include <limits>
5033+#include <stdexcept>
5034+
5035+namespace Catch {
5036+
5037+    Optional<unsigned int> parseUInt(std::string const& input, int base) {
5038+        auto trimmed = trim( input );
5039+        // std::stoull is annoying and accepts numbers starting with '-',
5040+        // it just negates them into unsigned int
5041+        if ( trimmed.empty() || trimmed[0] == '-' ) {
5042+            return {};
5043+        }
5044+
5045+        CATCH_TRY {
5046+            size_t pos = 0;
5047+            const auto ret = std::stoull( trimmed, &pos, base );
5048+
5049+            // We did not consume the whole input, so there is an issue
5050+            // This can be bunch of different stuff, like multiple numbers
5051+            // in the input, or invalid digits/characters and so on. Either
5052+            // way, we do not want to return the partially parsed result.
5053+            if ( pos != trimmed.size() ) {
5054+                return {};
5055+            }
5056+            // Too large
5057+            if ( ret > std::numeric_limits<unsigned int>::max() ) {
5058+                return {};
5059+            }
5060+            return static_cast<unsigned int>(ret);
5061+        }
5062+        CATCH_CATCH_ANON( std::invalid_argument const& ) {
5063+            // no conversion could be performed
5064+        }
5065+        CATCH_CATCH_ANON( std::out_of_range const& ) {
5066+            // the input does not fit into an unsigned long long
5067+        }
5068+        return {};
5069+    }
5070+
5071+} // namespace Catch
5072+
5073+
5074+
5075+
5076+#include <cmath>
5077+
5078+namespace Catch {
5079+
5080+#if !defined(CATCH_CONFIG_POLYFILL_ISNAN)
5081+    bool isnan(float f) {
5082+        return std::isnan(f);
5083+    }
5084+    bool isnan(double d) {
5085+        return std::isnan(d);
5086+    }
5087+#else
5088+    // For now we only use this for embarcadero
5089+    bool isnan(float f) {
5090+        return std::_isnan(f);
5091+    }
5092+    bool isnan(double d) {
5093+        return std::_isnan(d);
5094+    }
5095+#endif
5096+
5097+#if !defined( CATCH_CONFIG_GLOBAL_NEXTAFTER )
5098+    float nextafter( float x, float y ) { return std::nextafter( x, y ); }
5099+    double nextafter( double x, double y ) { return std::nextafter( x, y ); }
5100+#else
5101+    float nextafter( float x, float y ) { return ::nextafterf( x, y ); }
5102+    double nextafter( double x, double y ) { return ::nextafter( x, y ); }
5103+#endif
5104+
5105+} // end namespace Catch
5106+
5107+
5108+
5109+namespace Catch {
5110+
5111+namespace {
5112+
5113+#if defined(_MSC_VER)
5114+#pragma warning(push)
5115+#pragma warning(disable:4146) // we negate uint32 during the rotate
5116+#endif
5117+        // Safe rotr implementation thanks to John Regehr
5118+        uint32_t rotate_right(uint32_t val, uint32_t count) {
5119+            const uint32_t mask = 31;
5120+            count &= mask;
5121+            return (val >> count) | (val << (-count & mask));
5122+        }
5123+
5124+#if defined(_MSC_VER)
5125+#pragma warning(pop)
5126+#endif
5127+
5128+}
5129+
5130+
5131+    SimplePcg32::SimplePcg32(result_type seed_) {
5132+        seed(seed_);
5133+    }
5134+
5135+
5136+    void SimplePcg32::seed(result_type seed_) {
5137+        m_state = 0;
5138+        (*this)();
5139+        m_state += seed_;
5140+        (*this)();
5141+    }
5142+
5143+    void SimplePcg32::discard(uint64_t skip) {
5144+        // We could implement this to run in O(log n) steps, but this
5145+        // should suffice for our use case.
5146+        for (uint64_t s = 0; s < skip; ++s) {
5147+            static_cast<void>((*this)());
5148+        }
5149+    }
5150+
5151+    SimplePcg32::result_type SimplePcg32::operator()() {
5152+        // prepare the output value
5153+        const uint32_t xorshifted = static_cast<uint32_t>(((m_state >> 18u) ^ m_state) >> 27u);
5154+        const auto output = rotate_right(xorshifted, m_state >> 59u);
5155+
5156+        // advance state
5157+        m_state = m_state * 6364136223846793005ULL + s_inc;
5158+
5159+        return output;
5160+    }
5161+
5162+    bool operator==(SimplePcg32 const& lhs, SimplePcg32 const& rhs) {
5163+        return lhs.m_state == rhs.m_state;
5164+    }
5165+
5166+    bool operator!=(SimplePcg32 const& lhs, SimplePcg32 const& rhs) {
5167+        return lhs.m_state != rhs.m_state;
5168+    }
5169+}
5170+
5171+
5172+
5173+
5174+
5175+#include <ctime>
5176+#include <random>
5177+
5178+namespace Catch {
5179+
5180+    std::uint32_t generateRandomSeed( GenerateFrom from ) {
5181+        switch ( from ) {
5182+        case GenerateFrom::Time:
5183+            return static_cast<std::uint32_t>( std::time( nullptr ) );
5184+
5185+        case GenerateFrom::Default:
5186+        case GenerateFrom::RandomDevice: {
5187+            std::random_device rd;
5188+            return Detail::fillBitsFrom<std::uint32_t>( rd );
5189+        }
5190+
5191+        default:
5192+            CATCH_ERROR("Unknown generation method");
5193+        }
5194+    }
5195+
5196+} // end namespace Catch
5197+
5198+
5199+
5200+
5201+namespace Catch {
5202+    struct ReporterRegistry::ReporterRegistryImpl {
5203+        std::vector<Detail::unique_ptr<EventListenerFactory>> listeners;
5204+        std::map<std::string, IReporterFactoryPtr, Detail::CaseInsensitiveLess>
5205+            factories;
5206+    };
5207+
5208+    ReporterRegistry::ReporterRegistry():
5209+        m_impl( Detail::make_unique<ReporterRegistryImpl>() ) {
5210+        // Because it is impossible to move out of initializer list,
5211+        // we have to add the elements manually
5212+        m_impl->factories["Automake"] =
5213+            Detail::make_unique<ReporterFactory<AutomakeReporter>>();
5214+        m_impl->factories["compact"] =
5215+            Detail::make_unique<ReporterFactory<CompactReporter>>();
5216+        m_impl->factories["console"] =
5217+            Detail::make_unique<ReporterFactory<ConsoleReporter>>();
5218+        m_impl->factories["JUnit"] =
5219+            Detail::make_unique<ReporterFactory<JunitReporter>>();
5220+        m_impl->factories["SonarQube"] =
5221+            Detail::make_unique<ReporterFactory<SonarQubeReporter>>();
5222+        m_impl->factories["TAP"] =
5223+            Detail::make_unique<ReporterFactory<TAPReporter>>();
5224+        m_impl->factories["TeamCity"] =
5225+            Detail::make_unique<ReporterFactory<TeamCityReporter>>();
5226+        m_impl->factories["XML"] =
5227+            Detail::make_unique<ReporterFactory<XmlReporter>>();
5228+        m_impl->factories["JSON"] =
5229+            Detail::make_unique<ReporterFactory<JsonReporter>>();
5230+    }
5231+
5232+    ReporterRegistry::~ReporterRegistry() = default;
5233+
5234+    IEventListenerPtr
5235+    ReporterRegistry::create( std::string const& name,
5236+                              ReporterConfig&& config ) const {
5237+        auto it = m_impl->factories.find( name );
5238+        if ( it == m_impl->factories.end() ) return nullptr;
5239+        return it->second->create( CATCH_MOVE( config ) );
5240+    }
5241+
5242+    void ReporterRegistry::registerReporter( std::string const& name,
5243+                                             IReporterFactoryPtr factory ) {
5244+        CATCH_ENFORCE( name.find( "::" ) == name.npos,
5245+                       "'::' is not allowed in reporter name: '" + name +
5246+                           '\'' );
5247+        auto ret = m_impl->factories.emplace( name, CATCH_MOVE( factory ) );
5248+        CATCH_ENFORCE( ret.second,
5249+                       "reporter using '" + name +
5250+                           "' as name was already registered" );
5251+    }
5252+    void ReporterRegistry::registerListener(
5253+        Detail::unique_ptr<EventListenerFactory> factory ) {
5254+        m_impl->listeners.push_back( CATCH_MOVE( factory ) );
5255+    }
5256+
5257+    std::map<std::string,
5258+             IReporterFactoryPtr,
5259+             Detail::CaseInsensitiveLess> const&
5260+    ReporterRegistry::getFactories() const {
5261+        return m_impl->factories;
5262+    }
5263+
5264+    std::vector<Detail::unique_ptr<EventListenerFactory>> const&
5265+    ReporterRegistry::getListeners() const {
5266+        return m_impl->listeners;
5267+    }
5268+} // namespace Catch
5269+
5270+
5271+
5272+
5273+
5274+#include <algorithm>
5275+
5276+namespace Catch {
5277+
5278+    namespace {
5279+        struct kvPair {
5280+            StringRef key, value;
5281+        };
5282+
5283+        kvPair splitKVPair(StringRef kvString) {
5284+            auto splitPos = static_cast<size_t>(
5285+                std::find( kvString.begin(), kvString.end(), '=' ) -
5286+                kvString.begin() );
5287+
5288+            return { kvString.substr( 0, splitPos ),
5289+                     kvString.substr( splitPos + 1, kvString.size() ) };
5290+        }
5291+    }
5292+
5293+    namespace Detail {
5294+        std::vector<std::string> splitReporterSpec( StringRef reporterSpec ) {
5295+            static constexpr auto separator = "::";
5296+            static constexpr size_t separatorSize = 2;
5297+
5298+            size_t separatorPos = 0;
5299+            auto findNextSeparator = [&reporterSpec]( size_t startPos ) {
5300+                static_assert(
5301+                    separatorSize == 2,
5302+                    "The code below currently assumes 2 char separator" );
5303+
5304+                auto currentPos = startPos;
5305+                do {
5306+                    while ( currentPos < reporterSpec.size() &&
5307+                            reporterSpec[currentPos] != separator[0] ) {
5308+                        ++currentPos;
5309+                    }
5310+                    if ( currentPos + 1 < reporterSpec.size() &&
5311+                         reporterSpec[currentPos + 1] == separator[1] ) {
5312+                        return currentPos;
5313+                    }
5314+                    ++currentPos;
5315+                } while ( currentPos < reporterSpec.size() );
5316+
5317+                return static_cast<size_t>( -1 );
5318+            };
5319+
5320+            std::vector<std::string> parts;
5321+
5322+            while ( separatorPos < reporterSpec.size() ) {
5323+                const auto nextSeparator = findNextSeparator( separatorPos );
5324+                parts.push_back( static_cast<std::string>( reporterSpec.substr(
5325+                    separatorPos, nextSeparator - separatorPos ) ) );
5326+
5327+                if ( nextSeparator == static_cast<size_t>( -1 ) ) {
5328+                    break;
5329+                }
5330+                separatorPos = nextSeparator + separatorSize;
5331+            }
5332+
5333+            // Handle a separator at the end.
5334+            // This is not a valid spec, but we want to do validation in a
5335+            // centralized place
5336+            if ( separatorPos == reporterSpec.size() ) {
5337+                parts.emplace_back();
5338+            }
5339+
5340+            return parts;
5341+        }
5342+
5343+        Optional<ColourMode> stringToColourMode( StringRef colourMode ) {
5344+            if ( colourMode == "default" ) {
5345+                return ColourMode::PlatformDefault;
5346+            } else if ( colourMode == "ansi" ) {
5347+                return ColourMode::ANSI;
5348+            } else if ( colourMode == "win32" ) {
5349+                return ColourMode::Win32;
5350+            } else if ( colourMode == "none" ) {
5351+                return ColourMode::None;
5352+            } else {
5353+                return {};
5354+            }
5355+        }
5356+    } // namespace Detail
5357+
5358+
5359+    bool operator==( ReporterSpec const& lhs, ReporterSpec const& rhs ) {
5360+        return lhs.m_name == rhs.m_name &&
5361+               lhs.m_outputFileName == rhs.m_outputFileName &&
5362+               lhs.m_colourMode == rhs.m_colourMode &&
5363+               lhs.m_customOptions == rhs.m_customOptions;
5364+    }
5365+
5366+    Optional<ReporterSpec> parseReporterSpec( StringRef reporterSpec ) {
5367+        auto parts = Detail::splitReporterSpec( reporterSpec );
5368+
5369+        assert( parts.size() > 0 && "Split should never return empty vector" );
5370+
5371+        std::map<std::string, std::string> kvPairs;
5372+        Optional<std::string> outputFileName;
5373+        Optional<ColourMode> colourMode;
5374+
5375+        // First part is always reporter name, so we skip it
5376+        for ( size_t i = 1; i < parts.size(); ++i ) {
5377+            auto kv = splitKVPair( parts[i] );
5378+            auto key = kv.key, value = kv.value;
5379+
5380+            if ( key.empty() || value.empty() ) { // NOLINT(bugprone-branch-clone)
5381+                return {};
5382+            } else if ( key[0] == 'X' ) {
5383+                // This is a reporter-specific option, we don't check these
5384+                // apart from basic sanity checks
5385+                if ( key.size() == 1 ) {
5386+                    return {};
5387+                }
5388+
5389+                auto ret = kvPairs.emplace( std::string(kv.key), std::string(kv.value) );
5390+                if ( !ret.second ) {
5391+                    // Duplicated key. We might want to handle this differently,
5392+                    // e.g. by overwriting the existing value?
5393+                    return {};
5394+                }
5395+            } else if ( key == "out" ) {
5396+                // Duplicated key
5397+                if ( outputFileName ) {
5398+                    return {};
5399+                }
5400+                outputFileName = static_cast<std::string>( value );
5401+            } else if ( key == "colour-mode" ) {
5402+                // Duplicated key
5403+                if ( colourMode ) {
5404+                    return {};
5405+                }
5406+                colourMode = Detail::stringToColourMode( value );
5407+                // Parsing failed
5408+                if ( !colourMode ) {
5409+                    return {};
5410+                }
5411+            } else {
5412+                // Unrecognized option
5413+                return {};
5414+            }
5415+        }
5416+
5417+        return ReporterSpec{ CATCH_MOVE( parts[0] ),
5418+                             CATCH_MOVE( outputFileName ),
5419+                             CATCH_MOVE( colourMode ),
5420+                             CATCH_MOVE( kvPairs ) };
5421+    }
5422+
5423+ReporterSpec::ReporterSpec(
5424+        std::string name,
5425+        Optional<std::string> outputFileName,
5426+        Optional<ColourMode> colourMode,
5427+        std::map<std::string, std::string> customOptions ):
5428+        m_name( CATCH_MOVE( name ) ),
5429+        m_outputFileName( CATCH_MOVE( outputFileName ) ),
5430+        m_colourMode( CATCH_MOVE( colourMode ) ),
5431+        m_customOptions( CATCH_MOVE( customOptions ) ) {}
5432+
5433+} // namespace Catch
5434+
5435+
5436+
5437+namespace Catch {
5438+
5439+    bool isOk( ResultWas::OfType resultType ) {
5440+        return ( resultType & ResultWas::FailureBit ) == 0;
5441+    }
5442+    bool isJustInfo( int flags ) {
5443+        return flags == ResultWas::Info;
5444+    }
5445+
5446+    ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) {
5447+        return static_cast<ResultDisposition::Flags>( static_cast<int>( lhs ) | static_cast<int>( rhs ) );
5448+    }
5449+
5450+    bool shouldContinueOnFailure( int flags )    { return ( flags & ResultDisposition::ContinueOnFailure ) != 0; }
5451+    bool shouldSuppressFailure( int flags )      { return ( flags & ResultDisposition::SuppressFail ) != 0; }
5452+
5453+} // end namespace Catch
5454+
5455+
5456+
5457+#include <cstdio>
5458+#include <sstream>
5459+#include <vector>
5460+
5461+namespace Catch {
5462+
5463+    // This class encapsulates the idea of a pool of ostringstreams that can be reused.
5464+    struct StringStreams {
5465+        std::vector<Detail::unique_ptr<std::ostringstream>> m_streams;
5466+        std::vector<std::size_t> m_unused;
5467+        std::ostringstream m_referenceStream; // Used for copy state/ flags from
5468+
5469+        auto add() -> std::size_t {
5470+            if( m_unused.empty() ) {
5471+                m_streams.push_back( Detail::make_unique<std::ostringstream>() );
5472+                return m_streams.size()-1;
5473+            }
5474+            else {
5475+                auto index = m_unused.back();
5476+                m_unused.pop_back();
5477+                return index;
5478+            }
5479+        }
5480+
5481+        void release( std::size_t index ) {
5482+            m_streams[index]->copyfmt( m_referenceStream ); // Restore initial flags and other state
5483+            m_unused.push_back(index);
5484+        }
5485+    };
5486+
5487+    ReusableStringStream::ReusableStringStream()
5488+    :   m_index( Singleton<StringStreams>::getMutable().add() ),
5489+        m_oss( Singleton<StringStreams>::getMutable().m_streams[m_index].get() )
5490+    {}
5491+
5492+    ReusableStringStream::~ReusableStringStream() {
5493+        static_cast<std::ostringstream*>( m_oss )->str("");
5494+        m_oss->clear();
5495+        Singleton<StringStreams>::getMutable().release( m_index );
5496+    }
5497+
5498+    std::string ReusableStringStream::str() const {
5499+        return static_cast<std::ostringstream*>( m_oss )->str();
5500+    }
5501+
5502+    void ReusableStringStream::str( std::string const& str ) {
5503+        static_cast<std::ostringstream*>( m_oss )->str( str );
5504+    }
5505+
5506+
5507+}
5508+
5509+
5510+
5511+
5512+#include <cassert>
5513+#include <algorithm>
5514+
5515+namespace Catch {
5516+
5517+    namespace Generators {
5518+        namespace {
5519+            struct GeneratorTracker final : TestCaseTracking::TrackerBase,
5520+                                      IGeneratorTracker {
5521+                GeneratorBasePtr m_generator;
5522+
5523+                GeneratorTracker(
5524+                    TestCaseTracking::NameAndLocation&& nameAndLocation,
5525+                    TrackerContext& ctx,
5526+                    ITracker* parent ):
5527+                    TrackerBase( CATCH_MOVE( nameAndLocation ), ctx, parent ) {}
5528+
5529+                static GeneratorTracker*
5530+                acquire( TrackerContext& ctx,
5531+                         TestCaseTracking::NameAndLocationRef const&
5532+                             nameAndLocation ) {
5533+                    GeneratorTracker* tracker;
5534+
5535+                    ITracker& currentTracker = ctx.currentTracker();
5536+                    // Under specific circumstances, the generator we want
5537+                    // to acquire is also the current tracker. If this is
5538+                    // the case, we have to avoid looking through current
5539+                    // tracker's children, and instead return the current
5540+                    // tracker.
5541+                    // A case where this check is important is e.g.
5542+                    //     for (int i = 0; i < 5; ++i) {
5543+                    //         int n = GENERATE(1, 2);
5544+                    //     }
5545+                    //
5546+                    // without it, the code above creates 5 nested generators.
5547+                    if ( currentTracker.nameAndLocation() == nameAndLocation ) {
5548+                        auto thisTracker = currentTracker.parent()->findChild(
5549+                            nameAndLocation );
5550+                        assert( thisTracker );
5551+                        assert( thisTracker->isGeneratorTracker() );
5552+                        tracker = static_cast<GeneratorTracker*>( thisTracker );
5553+                    } else if ( ITracker* childTracker =
5554+                                    currentTracker.findChild(
5555+                                        nameAndLocation ) ) {
5556+                        assert( childTracker );
5557+                        assert( childTracker->isGeneratorTracker() );
5558+                        tracker =
5559+                            static_cast<GeneratorTracker*>( childTracker );
5560+                    } else {
5561+                        return nullptr;
5562+                    }
5563+
5564+                    if ( !tracker->isComplete() ) { tracker->open(); }
5565+
5566+                    return tracker;
5567+                }
5568+
5569+                // TrackerBase interface
5570+                bool isGeneratorTracker() const override { return true; }
5571+                auto hasGenerator() const -> bool override {
5572+                    return !!m_generator;
5573+                }
5574+                void close() override {
5575+                    TrackerBase::close();
5576+                    // If a generator has a child (it is followed by a section)
5577+                    // and none of its children have started, then we must wait
5578+                    // until later to start consuming its values.
5579+                    // This catches cases where `GENERATE` is placed between two
5580+                    // `SECTION`s.
5581+                    // **The check for m_children.empty cannot be removed**.
5582+                    // doing so would break `GENERATE` _not_ followed by
5583+                    // `SECTION`s.
5584+                    const bool should_wait_for_child = [&]() {
5585+                        // No children -> nobody to wait for
5586+                        if ( m_children.empty() ) { return false; }
5587+                        // If at least one child started executing, don't wait
5588+                        if ( std::find_if(
5589+                                 m_children.begin(),
5590+                                 m_children.end(),
5591+                                 []( TestCaseTracking::ITrackerPtr const&
5592+                                         tracker ) {
5593+                                     return tracker->hasStarted();
5594+                                 } ) != m_children.end() ) {
5595+                            return false;
5596+                        }
5597+
5598+                        // No children have started. We need to check if they
5599+                        // _can_ start, and thus we should wait for them, or
5600+                        // they cannot start (due to filters), and we shouldn't
5601+                        // wait for them
5602+                        ITracker* parent = m_parent;
5603+                        // This is safe: there is always at least one section
5604+                        // tracker in a test case tracking tree
5605+                        while ( !parent->isSectionTracker() ) {
5606+                            parent = parent->parent();
5607+                        }
5608+                        assert( parent &&
5609+                                "Missing root (test case) level section" );
5610+
5611+                        auto const& parentSection =
5612+                            static_cast<SectionTracker const&>( *parent );
5613+                        auto const& filters = parentSection.getFilters();
5614+                        // No filters -> no restrictions on running sections
5615+                        if ( filters.empty() ) { return true; }
5616+
5617+                        for ( auto const& child : m_children ) {
5618+                            if ( child->isSectionTracker() &&
5619+                                 std::find( filters.begin(),
5620+                                            filters.end(),
5621+                                            static_cast<SectionTracker const&>(
5622+                                                *child )
5623+                                                .trimmedName() ) !=
5624+                                     filters.end() ) {
5625+                                return true;
5626+                            }
5627+                        }
5628+                        return false;
5629+                    }();
5630+
5631+                    // This check is a bit tricky, because m_generator->next()
5632+                    // has a side-effect, where it consumes generator's current
5633+                    // value, but we do not want to invoke the side-effect if
5634+                    // this generator is still waiting for any child to start.
5635+                    assert( m_generator && "Tracker without generator" );
5636+                    if ( should_wait_for_child ||
5637+                         ( m_runState == CompletedSuccessfully &&
5638+                           m_generator->countedNext() ) ) {
5639+                        m_children.clear();
5640+                        m_runState = Executing;
5641+                    }
5642+                }
5643+
5644+                // IGeneratorTracker interface
5645+                auto getGenerator() const -> GeneratorBasePtr const& override {
5646+                    return m_generator;
5647+                }
5648+                void setGenerator( GeneratorBasePtr&& generator ) override {
5649+                    m_generator = CATCH_MOVE( generator );
5650+                }
5651+            };
5652+        } // namespace
5653+    }
5654+
5655+    RunContext::RunContext(IConfig const* _config, IEventListenerPtr&& reporter)
5656+    :   m_runInfo(_config->name()),
5657+        m_config(_config),
5658+        m_reporter(CATCH_MOVE(reporter)),
5659+        m_lastAssertionInfo{ StringRef(), SourceLineInfo("",0), StringRef(), ResultDisposition::Normal },
5660+        m_includeSuccessfulResults( m_config->includeSuccessfulResults() || m_reporter->getPreferences().shouldReportAllAssertions )
5661+    {
5662+        getCurrentMutableContext().setResultCapture( this );
5663+        m_reporter->testRunStarting(m_runInfo);
5664+    }
5665+
5666+    RunContext::~RunContext() {
5667+        m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals, aborting()));
5668+    }
5669+
5670+    Totals RunContext::runTest(TestCaseHandle const& testCase) {
5671+        const Totals prevTotals = m_totals;
5672+
5673+        auto const& testInfo = testCase.getTestCaseInfo();
5674+        m_reporter->testCaseStarting(testInfo);
5675+        m_activeTestCase = &testCase;
5676+
5677+
5678+        ITracker& rootTracker = m_trackerContext.startRun();
5679+        assert(rootTracker.isSectionTracker());
5680+        static_cast<SectionTracker&>(rootTracker).addInitialFilters(m_config->getSectionsToRun());
5681+
5682+        // We intentionally only seed the internal RNG once per test case,
5683+        // before it is first invoked. The reason for that is a complex
5684+        // interplay of generator/section implementation details and the
5685+        // Random*Generator types.
5686+        //
5687+        // The issue boils down to us needing to seed the Random*Generators
5688+        // with different seed each, so that they return different sequences
5689+        // of random numbers. We do this by giving them a number from the
5690+        // shared RNG instance as their seed.
5691+        //
5692+        // However, this runs into an issue if the reseeding happens each
5693+        // time the test case is entered (as opposed to first time only),
5694+        // because multiple generators could get the same seed, e.g. in
5695+        // ```cpp
5696+        // TEST_CASE() {
5697+        //     auto i = GENERATE(take(10, random(0, 100));
5698+        //     SECTION("A") {
5699+        //         auto j = GENERATE(take(10, random(0, 100));
5700+        //     }
5701+        //     SECTION("B") {
5702+        //         auto k = GENERATE(take(10, random(0, 100));
5703+        //     }
5704+        // }
5705+        // ```
5706+        // `i` and `j` would properly return values from different sequences,
5707+        // but `i` and `k` would return the same sequence, because their seed
5708+        // would be the same.
5709+        // (The reason their seeds would be the same is that the generator
5710+        //  for k would be initialized when the test case is entered the second
5711+        //  time, after the shared RNG instance was reset to the same value
5712+        //  it had when the generator for i was initialized.)
5713+        seedRng( *m_config );
5714+
5715+        uint64_t testRuns = 0;
5716+        std::string redirectedCout;
5717+        std::string redirectedCerr;
5718+        do {
5719+            m_trackerContext.startCycle();
5720+            m_testCaseTracker = &SectionTracker::acquire(m_trackerContext, TestCaseTracking::NameAndLocationRef(testInfo.name, testInfo.lineInfo));
5721+
5722+            m_reporter->testCasePartialStarting(testInfo, testRuns);
5723+
5724+            const auto beforeRunTotals = m_totals;
5725+            std::string oneRunCout, oneRunCerr;
5726+            runCurrentTest(oneRunCout, oneRunCerr);
5727+            redirectedCout += oneRunCout;
5728+            redirectedCerr += oneRunCerr;
5729+
5730+            const auto singleRunTotals = m_totals.delta(beforeRunTotals);
5731+            auto statsForOneRun = TestCaseStats(testInfo, singleRunTotals, CATCH_MOVE(oneRunCout), CATCH_MOVE(oneRunCerr), aborting());
5732+
5733+            m_reporter->testCasePartialEnded(statsForOneRun, testRuns);
5734+            ++testRuns;
5735+        } while (!m_testCaseTracker->isSuccessfullyCompleted() && !aborting());
5736+
5737+        Totals deltaTotals = m_totals.delta(prevTotals);
5738+        if (testInfo.expectedToFail() && deltaTotals.testCases.passed > 0) {
5739+            deltaTotals.assertions.failed++;
5740+            deltaTotals.testCases.passed--;
5741+            deltaTotals.testCases.failed++;
5742+        }
5743+        m_totals.testCases += deltaTotals.testCases;
5744+        m_reporter->testCaseEnded(TestCaseStats(testInfo,
5745+                                  deltaTotals,
5746+                                  CATCH_MOVE(redirectedCout),
5747+                                  CATCH_MOVE(redirectedCerr),
5748+                                  aborting()));
5749+
5750+        m_activeTestCase = nullptr;
5751+        m_testCaseTracker = nullptr;
5752+
5753+        return deltaTotals;
5754+    }
5755+
5756+
5757+    void RunContext::assertionEnded(AssertionResult&& result) {
5758+        if (result.getResultType() == ResultWas::Ok) {
5759+            m_totals.assertions.passed++;
5760+            m_lastAssertionPassed = true;
5761+        } else if (result.getResultType() == ResultWas::ExplicitSkip) {
5762+            m_totals.assertions.skipped++;
5763+            m_lastAssertionPassed = true;
5764+        } else if (!result.succeeded()) {
5765+            m_lastAssertionPassed = false;
5766+            if (result.isOk()) {
5767+            }
5768+            else if( m_activeTestCase->getTestCaseInfo().okToFail() )
5769+                m_totals.assertions.failedButOk++;
5770+            else
5771+                m_totals.assertions.failed++;
5772+        }
5773+        else {
5774+            m_lastAssertionPassed = true;
5775+        }
5776+
5777+        m_reporter->assertionEnded(AssertionStats(result, m_messages, m_totals));
5778+
5779+        if ( result.getResultType() != ResultWas::Warning ) {
5780+            m_messageScopes.clear();
5781+        }
5782+
5783+        // Reset working state. assertion info will be reset after
5784+        // populateReaction is run if it is needed
5785+        m_lastResult = CATCH_MOVE( result );
5786+    }
5787+    void RunContext::resetAssertionInfo() {
5788+        m_lastAssertionInfo.macroName = StringRef();
5789+        m_lastAssertionInfo.capturedExpression = "{Unknown expression after the reported line}"_sr;
5790+        m_lastAssertionInfo.resultDisposition = ResultDisposition::Normal;
5791+    }
5792+
5793+    void RunContext::notifyAssertionStarted( AssertionInfo const& info ) {
5794+        m_reporter->assertionStarting( info );
5795+    }
5796+
5797+    bool RunContext::sectionStarted( StringRef sectionName,
5798+                                     SourceLineInfo const& sectionLineInfo,
5799+                                     Counts& assertions ) {
5800+        ITracker& sectionTracker =
5801+            SectionTracker::acquire( m_trackerContext,
5802+                                     TestCaseTracking::NameAndLocationRef(
5803+                                         sectionName, sectionLineInfo ) );
5804+
5805+        if (!sectionTracker.isOpen())
5806+            return false;
5807+        m_activeSections.push_back(&sectionTracker);
5808+
5809+        SectionInfo sectionInfo( sectionLineInfo, static_cast<std::string>(sectionName) );
5810+        m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo;
5811+
5812+        m_reporter->sectionStarting(sectionInfo);
5813+
5814+        assertions = m_totals.assertions;
5815+
5816+        return true;
5817+    }
5818+    IGeneratorTracker*
5819+    RunContext::acquireGeneratorTracker( StringRef generatorName,
5820+                                         SourceLineInfo const& lineInfo ) {
5821+        using namespace Generators;
5822+        GeneratorTracker* tracker = GeneratorTracker::acquire(
5823+            m_trackerContext,
5824+            TestCaseTracking::NameAndLocationRef(
5825+                 generatorName, lineInfo ) );
5826+        m_lastAssertionInfo.lineInfo = lineInfo;
5827+        return tracker;
5828+    }
5829+
5830+    IGeneratorTracker* RunContext::createGeneratorTracker(
5831+        StringRef generatorName,
5832+        SourceLineInfo lineInfo,
5833+        Generators::GeneratorBasePtr&& generator ) {
5834+
5835+        auto nameAndLoc = TestCaseTracking::NameAndLocation( static_cast<std::string>( generatorName ), lineInfo );
5836+        auto& currentTracker = m_trackerContext.currentTracker();
5837+        assert(
5838+            currentTracker.nameAndLocation() != nameAndLoc &&
5839+            "Trying to create tracker for a genreator that already has one" );
5840+
5841+        auto newTracker = Catch::Detail::make_unique<Generators::GeneratorTracker>(
5842+            CATCH_MOVE(nameAndLoc), m_trackerContext, &currentTracker );
5843+        auto ret = newTracker.get();
5844+        currentTracker.addChild( CATCH_MOVE( newTracker ) );
5845+
5846+        ret->setGenerator( CATCH_MOVE( generator ) );
5847+        ret->open();
5848+        return ret;
5849+    }
5850+
5851+    bool RunContext::testForMissingAssertions(Counts& assertions) {
5852+        if (assertions.total() != 0)
5853+            return false;
5854+        if (!m_config->warnAboutMissingAssertions())
5855+            return false;
5856+        if (m_trackerContext.currentTracker().hasChildren())
5857+            return false;
5858+        m_totals.assertions.failed++;
5859+        assertions.failed++;
5860+        return true;
5861+    }
5862+
5863+    void RunContext::sectionEnded(SectionEndInfo&& endInfo) {
5864+        Counts assertions = m_totals.assertions - endInfo.prevAssertions;
5865+        bool missingAssertions = testForMissingAssertions(assertions);
5866+
5867+        if (!m_activeSections.empty()) {
5868+            m_activeSections.back()->close();
5869+            m_activeSections.pop_back();
5870+        }
5871+
5872+        m_reporter->sectionEnded(SectionStats(CATCH_MOVE(endInfo.sectionInfo), assertions, endInfo.durationInSeconds, missingAssertions));
5873+        m_messages.clear();
5874+        m_messageScopes.clear();
5875+    }
5876+
5877+    void RunContext::sectionEndedEarly(SectionEndInfo&& endInfo) {
5878+        if ( m_unfinishedSections.empty() ) {
5879+            m_activeSections.back()->fail();
5880+        } else {
5881+            m_activeSections.back()->close();
5882+        }
5883+        m_activeSections.pop_back();
5884+
5885+        m_unfinishedSections.push_back(CATCH_MOVE(endInfo));
5886+    }
5887+
5888+    void RunContext::benchmarkPreparing( StringRef name ) {
5889+        m_reporter->benchmarkPreparing(name);
5890+    }
5891+    void RunContext::benchmarkStarting( BenchmarkInfo const& info ) {
5892+        m_reporter->benchmarkStarting( info );
5893+    }
5894+    void RunContext::benchmarkEnded( BenchmarkStats<> const& stats ) {
5895+        m_reporter->benchmarkEnded( stats );
5896+    }
5897+    void RunContext::benchmarkFailed( StringRef error ) {
5898+        m_reporter->benchmarkFailed( error );
5899+    }
5900+
5901+    void RunContext::pushScopedMessage(MessageInfo const & message) {
5902+        m_messages.push_back(message);
5903+    }
5904+
5905+    void RunContext::popScopedMessage(MessageInfo const & message) {
5906+        m_messages.erase(std::remove(m_messages.begin(), m_messages.end(), message), m_messages.end());
5907+    }
5908+
5909+    void RunContext::emplaceUnscopedMessage( MessageBuilder&& builder ) {
5910+        m_messageScopes.emplace_back( CATCH_MOVE(builder) );
5911+    }
5912+
5913+    std::string RunContext::getCurrentTestName() const {
5914+        return m_activeTestCase
5915+            ? m_activeTestCase->getTestCaseInfo().name
5916+            : std::string();
5917+    }
5918+
5919+    const AssertionResult * RunContext::getLastResult() const {
5920+        return &(*m_lastResult);
5921+    }
5922+
5923+    void RunContext::exceptionEarlyReported() {
5924+        m_shouldReportUnexpected = false;
5925+    }
5926+
5927+    void RunContext::handleFatalErrorCondition( StringRef message ) {
5928+        // First notify reporter that bad things happened
5929+        m_reporter->fatalErrorEncountered(message);
5930+
5931+        // Don't rebuild the result -- the stringification itself can cause more fatal errors
5932+        // Instead, fake a result data.
5933+        AssertionResultData tempResult( ResultWas::FatalErrorCondition, { false } );
5934+        tempResult.message = static_cast<std::string>(message);
5935+        AssertionResult result(m_lastAssertionInfo, CATCH_MOVE(tempResult));
5936+
5937+        assertionEnded(CATCH_MOVE(result) );
5938+        resetAssertionInfo();
5939+
5940+        handleUnfinishedSections();
5941+
5942+        // Recreate section for test case (as we will lose the one that was in scope)
5943+        auto const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
5944+        SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name);
5945+
5946+        Counts assertions;
5947+        assertions.failed = 1;
5948+        SectionStats testCaseSectionStats(CATCH_MOVE(testCaseSection), assertions, 0, false);
5949+        m_reporter->sectionEnded(testCaseSectionStats);
5950+
5951+        auto const& testInfo = m_activeTestCase->getTestCaseInfo();
5952+
5953+        Totals deltaTotals;
5954+        deltaTotals.testCases.failed = 1;
5955+        deltaTotals.assertions.failed = 1;
5956+        m_reporter->testCaseEnded(TestCaseStats(testInfo,
5957+                                  deltaTotals,
5958+                                  std::string(),
5959+                                  std::string(),
5960+                                  false));
5961+        m_totals.testCases.failed++;
5962+        m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals, false));
5963+    }
5964+
5965+    bool RunContext::lastAssertionPassed() {
5966+         return m_lastAssertionPassed;
5967+    }
5968+
5969+    void RunContext::assertionPassed() {
5970+        m_lastAssertionPassed = true;
5971+        ++m_totals.assertions.passed;
5972+        resetAssertionInfo();
5973+        m_messageScopes.clear();
5974+    }
5975+
5976+    bool RunContext::aborting() const {
5977+        return m_totals.assertions.failed >= static_cast<std::size_t>(m_config->abortAfter());
5978+    }
5979+
5980+    void RunContext::runCurrentTest(std::string & redirectedCout, std::string & redirectedCerr) {
5981+        auto const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
5982+        SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name);
5983+        m_reporter->sectionStarting(testCaseSection);
5984+        Counts prevAssertions = m_totals.assertions;
5985+        double duration = 0;
5986+        m_shouldReportUnexpected = true;
5987+        m_lastAssertionInfo = { "TEST_CASE"_sr, testCaseInfo.lineInfo, StringRef(), ResultDisposition::Normal };
5988+
5989+        Timer timer;
5990+        CATCH_TRY {
5991+            if (m_reporter->getPreferences().shouldRedirectStdOut) {
5992+#if !defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT)
5993+                RedirectedStreams redirectedStreams(redirectedCout, redirectedCerr);
5994+
5995+                timer.start();
5996+                invokeActiveTestCase();
5997+#else
5998+                OutputRedirect r(redirectedCout, redirectedCerr);
5999+                timer.start();
6000+                invokeActiveTestCase();
6001+#endif
6002+            } else {
6003+                timer.start();
6004+                invokeActiveTestCase();
6005+            }
6006+            duration = timer.getElapsedSeconds();
6007+        } CATCH_CATCH_ANON (TestFailureException&) {
6008+            // This just means the test was aborted due to failure
6009+        } CATCH_CATCH_ANON (TestSkipException&) {
6010+            // This just means the test was explicitly skipped
6011+        } CATCH_CATCH_ALL {
6012+            // Under CATCH_CONFIG_FAST_COMPILE, unexpected exceptions under REQUIRE assertions
6013+            // are reported without translation at the point of origin.
6014+            if( m_shouldReportUnexpected ) {
6015+                AssertionReaction dummyReaction;
6016+                handleUnexpectedInflightException( m_lastAssertionInfo, translateActiveException(), dummyReaction );
6017+            }
6018+        }
6019+        Counts assertions = m_totals.assertions - prevAssertions;
6020+        bool missingAssertions = testForMissingAssertions(assertions);
6021+
6022+        m_testCaseTracker->close();
6023+        handleUnfinishedSections();
6024+        m_messages.clear();
6025+        m_messageScopes.clear();
6026+
6027+        SectionStats testCaseSectionStats(CATCH_MOVE(testCaseSection), assertions, duration, missingAssertions);
6028+        m_reporter->sectionEnded(testCaseSectionStats);
6029+    }
6030+
6031+    void RunContext::invokeActiveTestCase() {
6032+        // We need to engage a handler for signals/structured exceptions
6033+        // before running the tests themselves, or the binary can crash
6034+        // without failed test being reported.
6035+        FatalConditionHandlerGuard _(&m_fatalConditionhandler);
6036+        // We keep having issue where some compilers warn about an unused
6037+        // variable, even though the type has non-trivial constructor and
6038+        // destructor. This is annoying and ugly, but it makes them stfu.
6039+        (void)_;
6040+
6041+        m_activeTestCase->invoke();
6042+    }
6043+
6044+    void RunContext::handleUnfinishedSections() {
6045+        // If sections ended prematurely due to an exception we stored their
6046+        // infos here so we can tear them down outside the unwind process.
6047+        for (auto it = m_unfinishedSections.rbegin(),
6048+             itEnd = m_unfinishedSections.rend();
6049+             it != itEnd;
6050+             ++it)
6051+            sectionEnded(CATCH_MOVE(*it));
6052+        m_unfinishedSections.clear();
6053+    }
6054+
6055+    void RunContext::handleExpr(
6056+        AssertionInfo const& info,
6057+        ITransientExpression const& expr,
6058+        AssertionReaction& reaction
6059+    ) {
6060+        bool negated = isFalseTest( info.resultDisposition );
6061+        bool result = expr.getResult() != negated;
6062+
6063+        if( result ) {
6064+            if (!m_includeSuccessfulResults) {
6065+                assertionPassed();
6066+            }
6067+            else {
6068+                reportExpr(info, ResultWas::Ok, &expr, negated);
6069+            }
6070+        }
6071+        else {
6072+            reportExpr(info, ResultWas::ExpressionFailed, &expr, negated );
6073+            populateReaction( reaction );
6074+        }
6075+        resetAssertionInfo();
6076+    }
6077+    void RunContext::reportExpr(
6078+            AssertionInfo const &info,
6079+            ResultWas::OfType resultType,
6080+            ITransientExpression const *expr,
6081+            bool negated ) {
6082+
6083+        m_lastAssertionInfo = info;
6084+        AssertionResultData data( resultType, LazyExpression( negated ) );
6085+
6086+        AssertionResult assertionResult{ info, CATCH_MOVE( data ) };
6087+        assertionResult.m_resultData.lazyExpression.m_transientExpression = expr;
6088+
6089+        assertionEnded( CATCH_MOVE(assertionResult) );
6090+    }
6091+
6092+    void RunContext::handleMessage(
6093+            AssertionInfo const& info,
6094+            ResultWas::OfType resultType,
6095+            StringRef message,
6096+            AssertionReaction& reaction
6097+    ) {
6098+        m_lastAssertionInfo = info;
6099+
6100+        AssertionResultData data( resultType, LazyExpression( false ) );
6101+        data.message = static_cast<std::string>(message);
6102+        AssertionResult assertionResult{ m_lastAssertionInfo,
6103+                                         CATCH_MOVE( data ) };
6104+
6105+        const auto isOk = assertionResult.isOk();
6106+        assertionEnded( CATCH_MOVE(assertionResult) );
6107+        if ( !isOk ) {
6108+            populateReaction( reaction );
6109+        } else if ( resultType == ResultWas::ExplicitSkip ) {
6110+            // TODO: Need to handle this explicitly, as ExplicitSkip is
6111+            // considered "OK"
6112+            reaction.shouldSkip = true;
6113+        }
6114+        resetAssertionInfo();
6115+    }
6116+    void RunContext::handleUnexpectedExceptionNotThrown(
6117+            AssertionInfo const& info,
6118+            AssertionReaction& reaction
6119+    ) {
6120+        handleNonExpr(info, Catch::ResultWas::DidntThrowException, reaction);
6121+    }
6122+
6123+    void RunContext::handleUnexpectedInflightException(
6124+            AssertionInfo const& info,
6125+            std::string&& message,
6126+            AssertionReaction& reaction
6127+    ) {
6128+        m_lastAssertionInfo = info;
6129+
6130+        AssertionResultData data( ResultWas::ThrewException, LazyExpression( false ) );
6131+        data.message = CATCH_MOVE(message);
6132+        AssertionResult assertionResult{ info, CATCH_MOVE(data) };
6133+        assertionEnded( CATCH_MOVE(assertionResult) );
6134+        populateReaction( reaction );
6135+        resetAssertionInfo();
6136+    }
6137+
6138+    void RunContext::populateReaction( AssertionReaction& reaction ) {
6139+        reaction.shouldDebugBreak = m_config->shouldDebugBreak();
6140+        reaction.shouldThrow = aborting() || (m_lastAssertionInfo.resultDisposition & ResultDisposition::Normal);
6141+    }
6142+
6143+    void RunContext::handleIncomplete(
6144+            AssertionInfo const& info
6145+    ) {
6146+        using namespace std::string_literals;
6147+        m_lastAssertionInfo = info;
6148+
6149+        AssertionResultData data( ResultWas::ThrewException, LazyExpression( false ) );
6150+        data.message = "Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE"s;
6151+        AssertionResult assertionResult{ info, CATCH_MOVE( data ) };
6152+        assertionEnded( CATCH_MOVE(assertionResult) );
6153+        resetAssertionInfo();
6154+    }
6155+    void RunContext::handleNonExpr(
6156+            AssertionInfo const &info,
6157+            ResultWas::OfType resultType,
6158+            AssertionReaction &reaction
6159+    ) {
6160+        m_lastAssertionInfo = info;
6161+
6162+        AssertionResultData data( resultType, LazyExpression( false ) );
6163+        AssertionResult assertionResult{ info, CATCH_MOVE( data ) };
6164+
6165+        const auto isOk = assertionResult.isOk();
6166+        assertionEnded( CATCH_MOVE(assertionResult) );
6167+        if ( !isOk ) { populateReaction( reaction ); }
6168+        resetAssertionInfo();
6169+    }
6170+
6171+
6172+    IResultCapture& getResultCapture() {
6173+        if (auto* capture = getCurrentContext().getResultCapture())
6174+            return *capture;
6175+        else
6176+            CATCH_INTERNAL_ERROR("No result capture instance");
6177+    }
6178+
6179+    void seedRng(IConfig const& config) {
6180+        sharedRng().seed(config.rngSeed());
6181+    }
6182+
6183+    unsigned int rngSeed() {
6184+        return getCurrentContext().getConfig()->rngSeed();
6185+    }
6186+
6187+}
6188+
6189+
6190+
6191+namespace Catch {
6192+
6193+    Section::Section( SectionInfo&& info ):
6194+        m_info( CATCH_MOVE( info ) ),
6195+        m_sectionIncluded(
6196+            getResultCapture().sectionStarted( m_info.name, m_info.lineInfo, m_assertions ) ) {
6197+        // Non-"included" sections will not use the timing information
6198+        // anyway, so don't bother with the potential syscall.
6199+        if (m_sectionIncluded) {
6200+            m_timer.start();
6201+        }
6202+    }
6203+
6204+    Section::Section( SourceLineInfo const& _lineInfo,
6205+                      StringRef _name,
6206+                      const char* const ):
6207+        m_info( { "invalid", static_cast<std::size_t>( -1 ) }, std::string{} ),
6208+        m_sectionIncluded(
6209+            getResultCapture().sectionStarted( _name, _lineInfo, m_assertions ) ) {
6210+        // We delay initialization the SectionInfo member until we know
6211+        // this section needs it, so we avoid allocating std::string for name.
6212+        // We also delay timer start to avoid the potential syscall unless we
6213+        // will actually use the result.
6214+        if ( m_sectionIncluded ) {
6215+            m_info.name = static_cast<std::string>( _name );
6216+            m_info.lineInfo = _lineInfo;
6217+            m_timer.start();
6218+        }
6219+    }
6220+
6221+    Section::~Section() {
6222+        if( m_sectionIncluded ) {
6223+            SectionEndInfo endInfo{ CATCH_MOVE(m_info), m_assertions, m_timer.getElapsedSeconds() };
6224+            if ( uncaught_exceptions() ) {
6225+                getResultCapture().sectionEndedEarly( CATCH_MOVE(endInfo) );
6226+            } else {
6227+                getResultCapture().sectionEnded( CATCH_MOVE( endInfo ) );
6228+            }
6229+        }
6230+    }
6231+
6232+    // This indicates whether the section should be executed or not
6233+    Section::operator bool() const {
6234+        return m_sectionIncluded;
6235+    }
6236+
6237+
6238+} // end namespace Catch
6239+
6240+
6241+
6242+#include <vector>
6243+
6244+namespace Catch {
6245+
6246+    namespace {
6247+        static auto getSingletons() -> std::vector<ISingleton*>*& {
6248+            static std::vector<ISingleton*>* g_singletons = nullptr;
6249+            if( !g_singletons )
6250+                g_singletons = new std::vector<ISingleton*>();
6251+            return g_singletons;
6252+        }
6253+    }
6254+
6255+    ISingleton::~ISingleton() = default;
6256+
6257+    void addSingleton(ISingleton* singleton ) {
6258+        getSingletons()->push_back( singleton );
6259+    }
6260+    void cleanupSingletons() {
6261+        auto& singletons = getSingletons();
6262+        for( auto singleton : *singletons )
6263+            delete singleton;
6264+        delete singletons;
6265+        singletons = nullptr;
6266+    }
6267+
6268+} // namespace Catch
6269+
6270+
6271+
6272+#include <cstring>
6273+#include <ostream>
6274+
6275+namespace Catch {
6276+
6277+    bool SourceLineInfo::operator == ( SourceLineInfo const& other ) const noexcept {
6278+        return line == other.line && (file == other.file || std::strcmp(file, other.file) == 0);
6279+    }
6280+    bool SourceLineInfo::operator < ( SourceLineInfo const& other ) const noexcept {
6281+        // We can assume that the same file will usually have the same pointer.
6282+        // Thus, if the pointers are the same, there is no point in calling the strcmp
6283+        return line < other.line || ( line == other.line && file != other.file && (std::strcmp(file, other.file) < 0));
6284+    }
6285+
6286+    std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) {
6287+#ifndef __GNUG__
6288+        os << info.file << '(' << info.line << ')';
6289+#else
6290+        os << info.file << ':' << info.line;
6291+#endif
6292+        return os;
6293+    }
6294+
6295+} // end namespace Catch
6296+
6297+
6298+
6299+
6300+namespace Catch {
6301+#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
6302+    void StartupExceptionRegistry::add( std::exception_ptr const& exception ) noexcept {
6303+        CATCH_TRY {
6304+            m_exceptions.push_back(exception);
6305+        } CATCH_CATCH_ALL {
6306+            // If we run out of memory during start-up there's really not a lot more we can do about it
6307+            std::terminate();
6308+        }
6309+    }
6310+
6311+    std::vector<std::exception_ptr> const& StartupExceptionRegistry::getExceptions() const noexcept {
6312+        return m_exceptions;
6313+    }
6314+#endif
6315+
6316+} // end namespace Catch
6317+
6318+
6319+
6320+
6321+
6322+#include <iostream>
6323+
6324+namespace Catch {
6325+
6326+// If you #define this you must implement these functions
6327+#if !defined( CATCH_CONFIG_NOSTDOUT )
6328+    std::ostream& cout() { return std::cout; }
6329+    std::ostream& cerr() { return std::cerr; }
6330+    std::ostream& clog() { return std::clog; }
6331+#endif
6332+
6333+} // namespace Catch
6334+
6335+
6336+
6337+#include <ostream>
6338+#include <cstring>
6339+#include <cctype>
6340+#include <vector>
6341+
6342+namespace Catch {
6343+
6344+    bool startsWith( std::string const& s, std::string const& prefix ) {
6345+        return s.size() >= prefix.size() && std::equal(prefix.begin(), prefix.end(), s.begin());
6346+    }
6347+    bool startsWith( StringRef s, char prefix ) {
6348+        return !s.empty() && s[0] == prefix;
6349+    }
6350+    bool endsWith( std::string const& s, std::string const& suffix ) {
6351+        return s.size() >= suffix.size() && std::equal(suffix.rbegin(), suffix.rend(), s.rbegin());
6352+    }
6353+    bool endsWith( std::string const& s, char suffix ) {
6354+        return !s.empty() && s[s.size()-1] == suffix;
6355+    }
6356+    bool contains( std::string const& s, std::string const& infix ) {
6357+        return s.find( infix ) != std::string::npos;
6358+    }
6359+    void toLowerInPlace( std::string& s ) {
6360+        for ( char& c : s ) {
6361+            c = toLower( c );
6362+        }
6363+    }
6364+    std::string toLower( std::string const& s ) {
6365+        std::string lc = s;
6366+        toLowerInPlace( lc );
6367+        return lc;
6368+    }
6369+    char toLower(char c) {
6370+        return static_cast<char>(std::tolower(static_cast<unsigned char>(c)));
6371+    }
6372+
6373+    std::string trim( std::string const& str ) {
6374+        static char const* whitespaceChars = "\n\r\t ";
6375+        std::string::size_type start = str.find_first_not_of( whitespaceChars );
6376+        std::string::size_type end = str.find_last_not_of( whitespaceChars );
6377+
6378+        return start != std::string::npos ? str.substr( start, 1+end-start ) : std::string();
6379+    }
6380+
6381+    StringRef trim(StringRef ref) {
6382+        const auto is_ws = [](char c) {
6383+            return c == ' ' || c == '\t' || c == '\n' || c == '\r';
6384+        };
6385+        size_t real_begin = 0;
6386+        while (real_begin < ref.size() && is_ws(ref[real_begin])) { ++real_begin; }
6387+        size_t real_end = ref.size();
6388+        while (real_end > real_begin && is_ws(ref[real_end - 1])) { --real_end; }
6389+
6390+        return ref.substr(real_begin, real_end - real_begin);
6391+    }
6392+
6393+    bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ) {
6394+        std::size_t i = str.find( replaceThis );
6395+        if (i == std::string::npos) {
6396+            return false;
6397+        }
6398+        std::size_t copyBegin = 0;
6399+        std::string origStr = CATCH_MOVE(str);
6400+        str.clear();
6401+        // There is at least one replacement, so reserve with the best guess
6402+        // we can make without actually counting the number of occurences.
6403+        str.reserve(origStr.size() - replaceThis.size() + withThis.size());
6404+        do {
6405+            str.append(origStr, copyBegin, i-copyBegin );
6406+            str += withThis;
6407+            copyBegin = i + replaceThis.size();
6408+            if( copyBegin < origStr.size() )
6409+                i = origStr.find( replaceThis, copyBegin );
6410+            else
6411+                i = std::string::npos;
6412+        } while( i != std::string::npos );
6413+        if ( copyBegin < origStr.size() ) {
6414+            str.append(origStr, copyBegin, origStr.size() );
6415+        }
6416+        return true;
6417+    }
6418+
6419+    std::vector<StringRef> splitStringRef( StringRef str, char delimiter ) {
6420+        std::vector<StringRef> subStrings;
6421+        std::size_t start = 0;
6422+        for(std::size_t pos = 0; pos < str.size(); ++pos ) {
6423+            if( str[pos] == delimiter ) {
6424+                if( pos - start > 1 )
6425+                    subStrings.push_back( str.substr( start, pos-start ) );
6426+                start = pos+1;
6427+            }
6428+        }
6429+        if( start < str.size() )
6430+            subStrings.push_back( str.substr( start, str.size()-start ) );
6431+        return subStrings;
6432+    }
6433+
6434+    std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ) {
6435+        os << pluraliser.m_count << ' ' << pluraliser.m_label;
6436+        if( pluraliser.m_count != 1 )
6437+            os << 's';
6438+        return os;
6439+    }
6440+
6441+}
6442+
6443+
6444+
6445+#include <algorithm>
6446+#include <ostream>
6447+#include <cstring>
6448+#include <cstdint>
6449+
6450+namespace Catch {
6451+    StringRef::StringRef( char const* rawChars ) noexcept
6452+    : StringRef( rawChars, std::strlen(rawChars) )
6453+    {}
6454+
6455+
6456+    bool StringRef::operator<(StringRef rhs) const noexcept {
6457+        if (m_size < rhs.m_size) {
6458+            return strncmp(m_start, rhs.m_start, m_size) <= 0;
6459+        }
6460+        return strncmp(m_start, rhs.m_start, rhs.m_size) < 0;
6461+    }
6462+
6463+    int StringRef::compare( StringRef rhs ) const {
6464+        auto cmpResult =
6465+            strncmp( m_start, rhs.m_start, std::min( m_size, rhs.m_size ) );
6466+
6467+        // This means that strncmp found a difference before the strings
6468+        // ended, and we can return it directly
6469+        if ( cmpResult != 0 ) {
6470+            return cmpResult;
6471+        }
6472+
6473+        // If strings are equal up to length, then their comparison results on
6474+        // their size
6475+        if ( m_size < rhs.m_size ) {
6476+            return -1;
6477+        } else if ( m_size > rhs.m_size ) {
6478+            return 1;
6479+        } else {
6480+            return 0;
6481+        }
6482+    }
6483+
6484+    auto operator << ( std::ostream& os, StringRef str ) -> std::ostream& {
6485+        return os.write(str.data(), static_cast<std::streamsize>(str.size()));
6486+    }
6487+
6488+    std::string operator+(StringRef lhs, StringRef rhs) {
6489+        std::string ret;
6490+        ret.reserve(lhs.size() + rhs.size());
6491+        ret += lhs;
6492+        ret += rhs;
6493+        return ret;
6494+    }
6495+
6496+    auto operator+=( std::string& lhs, StringRef rhs ) -> std::string& {
6497+        lhs.append(rhs.data(), rhs.size());
6498+        return lhs;
6499+    }
6500+
6501+} // namespace Catch
6502+
6503+
6504+
6505+namespace Catch {
6506+
6507+    TagAliasRegistry::~TagAliasRegistry() = default;
6508+
6509+    TagAlias const* TagAliasRegistry::find( std::string const& alias ) const {
6510+        auto it = m_registry.find( alias );
6511+        if( it != m_registry.end() )
6512+            return &(it->second);
6513+        else
6514+            return nullptr;
6515+    }
6516+
6517+    std::string TagAliasRegistry::expandAliases( std::string const& unexpandedTestSpec ) const {
6518+        std::string expandedTestSpec = unexpandedTestSpec;
6519+        for( auto const& registryKvp : m_registry ) {
6520+            std::size_t pos = expandedTestSpec.find( registryKvp.first );
6521+            if( pos != std::string::npos ) {
6522+                expandedTestSpec =  expandedTestSpec.substr( 0, pos ) +
6523+                                    registryKvp.second.tag +
6524+                                    expandedTestSpec.substr( pos + registryKvp.first.size() );
6525+            }
6526+        }
6527+        return expandedTestSpec;
6528+    }
6529+
6530+    void TagAliasRegistry::add( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) {
6531+        CATCH_ENFORCE( startsWith(alias, "[@") && endsWith(alias, ']'),
6532+                      "error: tag alias, '" << alias << "' is not of the form [@alias name].\n" << lineInfo );
6533+
6534+        CATCH_ENFORCE( m_registry.insert(std::make_pair(alias, TagAlias(tag, lineInfo))).second,
6535+                      "error: tag alias, '" << alias << "' already registered.\n"
6536+                      << "\tFirst seen at: " << find(alias)->lineInfo << "\n"
6537+                      << "\tRedefined at: " << lineInfo );
6538+    }
6539+
6540+    ITagAliasRegistry::~ITagAliasRegistry() = default;
6541+
6542+    ITagAliasRegistry const& ITagAliasRegistry::get() {
6543+        return getRegistryHub().getTagAliasRegistry();
6544+    }
6545+
6546+} // end namespace Catch
6547+
6548+
6549+
6550+
6551+namespace Catch {
6552+    TestCaseInfoHasher::TestCaseInfoHasher( hash_t seed ): m_seed( seed ) {}
6553+
6554+    uint32_t TestCaseInfoHasher::operator()( TestCaseInfo const& t ) const {
6555+        // FNV-1a hash algorithm that is designed for uniqueness:
6556+        const hash_t prime = 1099511628211u;
6557+        hash_t hash = 14695981039346656037u;
6558+        for ( const char c : t.name ) {
6559+            hash ^= c;
6560+            hash *= prime;
6561+        }
6562+        for ( const char c : t.className ) {
6563+            hash ^= c;
6564+            hash *= prime;
6565+        }
6566+        for ( const Tag& tag : t.tags ) {
6567+            for ( const char c : tag.original ) {
6568+                hash ^= c;
6569+                hash *= prime;
6570+            }
6571+        }
6572+        hash ^= m_seed;
6573+        hash *= prime;
6574+        const uint32_t low{ static_cast<uint32_t>( hash ) };
6575+        const uint32_t high{ static_cast<uint32_t>( hash >> 32 ) };
6576+        return low * high;
6577+    }
6578+} // namespace Catch
6579+
6580+
6581+
6582+
6583+#include <algorithm>
6584+#include <set>
6585+
6586+namespace Catch {
6587+
6588+    namespace {
6589+        static void enforceNoDuplicateTestCases(
6590+            std::vector<TestCaseHandle> const& tests ) {
6591+            auto testInfoCmp = []( TestCaseInfo const* lhs,
6592+                                   TestCaseInfo const* rhs ) {
6593+                return *lhs < *rhs;
6594+            };
6595+            std::set<TestCaseInfo const*, decltype( testInfoCmp )&> seenTests(
6596+                testInfoCmp );
6597+            for ( auto const& test : tests ) {
6598+                const auto infoPtr = &test.getTestCaseInfo();
6599+                const auto prev = seenTests.insert( infoPtr );
6600+                CATCH_ENFORCE( prev.second,
6601+                               "error: test case \""
6602+                                   << infoPtr->name << "\", with tags \""
6603+                                   << infoPtr->tagsAsString()
6604+                                   << "\" already defined.\n"
6605+                                   << "\tFirst seen at "
6606+                                   << ( *prev.first )->lineInfo << "\n"
6607+                                   << "\tRedefined at " << infoPtr->lineInfo );
6608+            }
6609+        }
6610+
6611+        static bool matchTest( TestCaseHandle const& testCase,
6612+                               TestSpec const& testSpec,
6613+                               IConfig const& config ) {
6614+            return testSpec.matches( testCase.getTestCaseInfo() ) &&
6615+                   isThrowSafe( testCase, config );
6616+        }
6617+
6618+    } // end unnamed namespace
6619+
6620+    std::vector<TestCaseHandle> sortTests( IConfig const& config, std::vector<TestCaseHandle> const& unsortedTestCases ) {
6621+        switch (config.runOrder()) {
6622+        case TestRunOrder::Declared:
6623+            return unsortedTestCases;
6624+
6625+        case TestRunOrder::LexicographicallySorted: {
6626+            std::vector<TestCaseHandle> sorted = unsortedTestCases;
6627+            std::sort(
6628+                sorted.begin(),
6629+                sorted.end(),
6630+                []( TestCaseHandle const& lhs, TestCaseHandle const& rhs ) {
6631+                    return lhs.getTestCaseInfo() < rhs.getTestCaseInfo();
6632+                }
6633+            );
6634+            return sorted;
6635+        }
6636+        case TestRunOrder::Randomized: {
6637+            using TestWithHash = std::pair<TestCaseInfoHasher::hash_t, TestCaseHandle>;
6638+
6639+            TestCaseInfoHasher h{ config.rngSeed() };
6640+            std::vector<TestWithHash> indexed_tests;
6641+            indexed_tests.reserve(unsortedTestCases.size());
6642+
6643+            for (auto const& handle : unsortedTestCases) {
6644+                indexed_tests.emplace_back(h(handle.getTestCaseInfo()), handle);
6645+            }
6646+
6647+            std::sort( indexed_tests.begin(),
6648+                       indexed_tests.end(),
6649+                       []( TestWithHash const& lhs, TestWithHash const& rhs ) {
6650+                           if ( lhs.first == rhs.first ) {
6651+                               return lhs.second.getTestCaseInfo() <
6652+                                      rhs.second.getTestCaseInfo();
6653+                           }
6654+                           return lhs.first < rhs.first;
6655+                       } );
6656+
6657+            std::vector<TestCaseHandle> randomized;
6658+            randomized.reserve(indexed_tests.size());
6659+
6660+            for (auto const& indexed : indexed_tests) {
6661+                randomized.push_back(indexed.second);
6662+            }
6663+
6664+            return randomized;
6665+        }
6666+        }
6667+
6668+        CATCH_INTERNAL_ERROR("Unknown test order value!");
6669+    }
6670+
6671+    bool isThrowSafe( TestCaseHandle const& testCase, IConfig const& config ) {
6672+        return !testCase.getTestCaseInfo().throws() || config.allowThrows();
6673+    }
6674+
6675+    std::vector<TestCaseHandle> filterTests( std::vector<TestCaseHandle> const& testCases, TestSpec const& testSpec, IConfig const& config ) {
6676+        std::vector<TestCaseHandle> filtered;
6677+        filtered.reserve( testCases.size() );
6678+        for (auto const& testCase : testCases) {
6679+            if ((!testSpec.hasFilters() && !testCase.getTestCaseInfo().isHidden()) ||
6680+                (testSpec.hasFilters() && matchTest(testCase, testSpec, config))) {
6681+                filtered.push_back(testCase);
6682+            }
6683+        }
6684+        return createShard(filtered, config.shardCount(), config.shardIndex());
6685+    }
6686+    std::vector<TestCaseHandle> const& getAllTestCasesSorted( IConfig const& config ) {
6687+        return getRegistryHub().getTestCaseRegistry().getAllTestsSorted( config );
6688+    }
6689+
6690+    TestRegistry::~TestRegistry() = default;
6691+
6692+    void TestRegistry::registerTest(Detail::unique_ptr<TestCaseInfo> testInfo, Detail::unique_ptr<ITestInvoker> testInvoker) {
6693+        m_handles.emplace_back(testInfo.get(), testInvoker.get());
6694+        m_viewed_test_infos.push_back(testInfo.get());
6695+        m_owned_test_infos.push_back(CATCH_MOVE(testInfo));
6696+        m_invokers.push_back(CATCH_MOVE(testInvoker));
6697+    }
6698+
6699+    std::vector<TestCaseInfo*> const& TestRegistry::getAllInfos() const {
6700+        return m_viewed_test_infos;
6701+    }
6702+
6703+    std::vector<TestCaseHandle> const& TestRegistry::getAllTests() const {
6704+        return m_handles;
6705+    }
6706+    std::vector<TestCaseHandle> const& TestRegistry::getAllTestsSorted( IConfig const& config ) const {
6707+        if( m_sortedFunctions.empty() )
6708+            enforceNoDuplicateTestCases( m_handles );
6709+
6710+        if(  m_currentSortOrder != config.runOrder() || m_sortedFunctions.empty() ) {
6711+            m_sortedFunctions = sortTests( config, m_handles );
6712+            m_currentSortOrder = config.runOrder();
6713+        }
6714+        return m_sortedFunctions;
6715+    }
6716+
6717+} // end namespace Catch
6718+
6719+
6720+
6721+
6722+#include <algorithm>
6723+#include <cassert>
6724+
6725+#if defined(__clang__)
6726+#    pragma clang diagnostic push
6727+#    pragma clang diagnostic ignored "-Wexit-time-destructors"
6728+#endif
6729+
6730+namespace Catch {
6731+namespace TestCaseTracking {
6732+
6733+    NameAndLocation::NameAndLocation( std::string&& _name, SourceLineInfo const& _location )
6734+    :   name( CATCH_MOVE(_name) ),
6735+        location( _location )
6736+    {}
6737+
6738+
6739+    ITracker::~ITracker() = default;
6740+
6741+    void ITracker::markAsNeedingAnotherRun() {
6742+        m_runState = NeedsAnotherRun;
6743+    }
6744+
6745+    void ITracker::addChild( ITrackerPtr&& child ) {
6746+        m_children.push_back( CATCH_MOVE(child) );
6747+    }
6748+
6749+    ITracker* ITracker::findChild( NameAndLocationRef const& nameAndLocation ) {
6750+        auto it = std::find_if(
6751+            m_children.begin(),
6752+            m_children.end(),
6753+            [&nameAndLocation]( ITrackerPtr const& tracker ) {
6754+                auto const& tnameAndLoc = tracker->nameAndLocation();
6755+                if ( tnameAndLoc.location.line !=
6756+                     nameAndLocation.location.line ) {
6757+                    return false;
6758+                }
6759+                return tnameAndLoc == nameAndLocation;
6760+            } );
6761+        return ( it != m_children.end() ) ? it->get() : nullptr;
6762+    }
6763+
6764+    bool ITracker::isSectionTracker() const { return false; }
6765+    bool ITracker::isGeneratorTracker() const { return false; }
6766+
6767+    bool ITracker::isOpen() const {
6768+        return m_runState != NotStarted && !isComplete();
6769+    }
6770+
6771+    bool ITracker::hasStarted() const { return m_runState != NotStarted; }
6772+
6773+    void ITracker::openChild() {
6774+        if (m_runState != ExecutingChildren) {
6775+            m_runState = ExecutingChildren;
6776+            if (m_parent) {
6777+                m_parent->openChild();
6778+            }
6779+        }
6780+    }
6781+
6782+    ITracker& TrackerContext::startRun() {
6783+        using namespace std::string_literals;
6784+        m_rootTracker = Catch::Detail::make_unique<SectionTracker>(
6785+            NameAndLocation( "{root}"s, CATCH_INTERNAL_LINEINFO ),
6786+            *this,
6787+            nullptr );
6788+        m_currentTracker = nullptr;
6789+        m_runState = Executing;
6790+        return *m_rootTracker;
6791+    }
6792+
6793+    void TrackerContext::completeCycle() {
6794+        m_runState = CompletedCycle;
6795+    }
6796+
6797+    bool TrackerContext::completedCycle() const {
6798+        return m_runState == CompletedCycle;
6799+    }
6800+    void TrackerContext::setCurrentTracker( ITracker* tracker ) {
6801+        m_currentTracker = tracker;
6802+    }
6803+
6804+
6805+    TrackerBase::TrackerBase( NameAndLocation&& nameAndLocation, TrackerContext& ctx, ITracker* parent ):
6806+        ITracker(CATCH_MOVE(nameAndLocation), parent),
6807+        m_ctx( ctx )
6808+    {}
6809+
6810+    bool TrackerBase::isComplete() const {
6811+        return m_runState == CompletedSuccessfully || m_runState == Failed;
6812+    }
6813+
6814+    void TrackerBase::open() {
6815+        m_runState = Executing;
6816+        moveToThis();
6817+        if( m_parent )
6818+            m_parent->openChild();
6819+    }
6820+
6821+    void TrackerBase::close() {
6822+
6823+        // Close any still open children (e.g. generators)
6824+        while( &m_ctx.currentTracker() != this )
6825+            m_ctx.currentTracker().close();
6826+
6827+        switch( m_runState ) {
6828+            case NeedsAnotherRun:
6829+                break;
6830+
6831+            case Executing:
6832+                m_runState = CompletedSuccessfully;
6833+                break;
6834+            case ExecutingChildren:
6835+                if( std::all_of(m_children.begin(), m_children.end(), [](ITrackerPtr const& t){ return t->isComplete(); }) )
6836+                    m_runState = CompletedSuccessfully;
6837+                break;
6838+
6839+            case NotStarted:
6840+            case CompletedSuccessfully:
6841+            case Failed:
6842+                CATCH_INTERNAL_ERROR( "Illogical state: " << m_runState );
6843+
6844+            default:
6845+                CATCH_INTERNAL_ERROR( "Unknown state: " << m_runState );
6846+        }
6847+        moveToParent();
6848+        m_ctx.completeCycle();
6849+    }
6850+    void TrackerBase::fail() {
6851+        m_runState = Failed;
6852+        if( m_parent )
6853+            m_parent->markAsNeedingAnotherRun();
6854+        moveToParent();
6855+        m_ctx.completeCycle();
6856+    }
6857+
6858+    void TrackerBase::moveToParent() {
6859+        assert( m_parent );
6860+        m_ctx.setCurrentTracker( m_parent );
6861+    }
6862+    void TrackerBase::moveToThis() {
6863+        m_ctx.setCurrentTracker( this );
6864+    }
6865+
6866+    SectionTracker::SectionTracker( NameAndLocation&& nameAndLocation, TrackerContext& ctx, ITracker* parent )
6867+    :   TrackerBase( CATCH_MOVE(nameAndLocation), ctx, parent ),
6868+        m_trimmed_name(trim(StringRef(ITracker::nameAndLocation().name)))
6869+    {
6870+        if( parent ) {
6871+            while ( !parent->isSectionTracker() ) {
6872+                parent = parent->parent();
6873+            }
6874+
6875+            SectionTracker& parentSection = static_cast<SectionTracker&>( *parent );
6876+            addNextFilters( parentSection.m_filters );
6877+        }
6878+    }
6879+
6880+    bool SectionTracker::isComplete() const {
6881+        bool complete = true;
6882+
6883+        if (m_filters.empty()
6884+            || m_filters[0].empty()
6885+            || std::find(m_filters.begin(), m_filters.end(), m_trimmed_name) != m_filters.end()) {
6886+            complete = TrackerBase::isComplete();
6887+        }
6888+        return complete;
6889+    }
6890+
6891+    bool SectionTracker::isSectionTracker() const { return true; }
6892+
6893+    SectionTracker& SectionTracker::acquire( TrackerContext& ctx, NameAndLocationRef const& nameAndLocation ) {
6894+        SectionTracker* tracker;
6895+
6896+        ITracker& currentTracker = ctx.currentTracker();
6897+        if ( ITracker* childTracker =
6898+                 currentTracker.findChild( nameAndLocation ) ) {
6899+            assert( childTracker );
6900+            assert( childTracker->isSectionTracker() );
6901+            tracker = static_cast<SectionTracker*>( childTracker );
6902+        } else {
6903+            auto newTracker = Catch::Detail::make_unique<SectionTracker>(
6904+                NameAndLocation{ static_cast<std::string>(nameAndLocation.name),
6905+                                 nameAndLocation.location },
6906+                ctx,
6907+                &currentTracker );
6908+            tracker = newTracker.get();
6909+            currentTracker.addChild( CATCH_MOVE( newTracker ) );
6910+        }
6911+
6912+        if ( !ctx.completedCycle() ) {
6913+            tracker->tryOpen();
6914+        }
6915+
6916+        return *tracker;
6917+    }
6918+
6919+    void SectionTracker::tryOpen() {
6920+        if( !isComplete() )
6921+            open();
6922+    }
6923+
6924+    void SectionTracker::addInitialFilters( std::vector<std::string> const& filters ) {
6925+        if( !filters.empty() ) {
6926+            m_filters.reserve( m_filters.size() + filters.size() + 2 );
6927+            m_filters.emplace_back(StringRef{}); // Root - should never be consulted
6928+            m_filters.emplace_back(StringRef{}); // Test Case - not a section filter
6929+            m_filters.insert( m_filters.end(), filters.begin(), filters.end() );
6930+        }
6931+    }
6932+    void SectionTracker::addNextFilters( std::vector<StringRef> const& filters ) {
6933+        if( filters.size() > 1 )
6934+            m_filters.insert( m_filters.end(), filters.begin()+1, filters.end() );
6935+    }
6936+
6937+    StringRef SectionTracker::trimmedName() const {
6938+        return m_trimmed_name;
6939+    }
6940+
6941+} // namespace TestCaseTracking
6942+
6943+} // namespace Catch
6944+
6945+#if defined(__clang__)
6946+#    pragma clang diagnostic pop
6947+#endif
6948+
6949+
6950+
6951+
6952+namespace Catch {
6953+
6954+    void throw_test_failure_exception() {
6955+#if !defined( CATCH_CONFIG_DISABLE_EXCEPTIONS )
6956+        throw TestFailureException{};
6957+#else
6958+        CATCH_ERROR( "Test failure requires aborting test!" );
6959+#endif
6960+    }
6961+
6962+    void throw_test_skip_exception() {
6963+#if !defined( CATCH_CONFIG_DISABLE_EXCEPTIONS )
6964+        throw Catch::TestSkipException();
6965+#else
6966+        CATCH_ERROR( "Explicitly skipping tests during runtime requires exceptions" );
6967+#endif
6968+    }
6969+
6970+} // namespace Catch
6971+
6972+
6973+
6974+#include <algorithm>
6975+#include <iterator>
6976+
6977+namespace Catch {
6978+    ITestInvoker::~ITestInvoker() = default;
6979+
6980+    namespace {
6981+        static StringRef extractClassName( StringRef classOrMethodName ) {
6982+            if ( !startsWith( classOrMethodName, '&' ) ) {
6983+                return classOrMethodName;
6984+            }
6985+
6986+            // Remove the leading '&' to avoid having to special case it later
6987+            const auto methodName =
6988+                classOrMethodName.substr( 1, classOrMethodName.size() );
6989+
6990+            auto reverseStart = std::make_reverse_iterator( methodName.end() );
6991+            auto reverseEnd = std::make_reverse_iterator( methodName.begin() );
6992+
6993+            // We make a simplifying assumption that ":" is only present
6994+            // in the input as part of "::" from C++ typenames (this is
6995+            // relatively safe assumption because the input is generated
6996+            // as stringification of type through preprocessor).
6997+            auto lastColons = std::find( reverseStart, reverseEnd, ':' ) + 1;
6998+            auto secondLastColons =
6999+                std::find( lastColons + 1, reverseEnd, ':' );
7000+
7001+            auto const startIdx = reverseEnd - secondLastColons;
7002+            auto const classNameSize = secondLastColons - lastColons - 1;
7003+
7004+            return methodName.substr(
7005+                static_cast<std::size_t>( startIdx ),
7006+                static_cast<std::size_t>( classNameSize ) );
7007+        }
7008+
7009+        class TestInvokerAsFunction final : public ITestInvoker {
7010+            using TestType = void ( * )();
7011+            TestType m_testAsFunction;
7012+
7013+        public:
7014+            TestInvokerAsFunction( TestType testAsFunction ) noexcept:
7015+                m_testAsFunction( testAsFunction ) {}
7016+
7017+            void invoke() const override { m_testAsFunction(); }
7018+        };
7019+
7020+    } // namespace
7021+
7022+    Detail::unique_ptr<ITestInvoker> makeTestInvoker( void(*testAsFunction)() ) {
7023+        return Detail::make_unique<TestInvokerAsFunction>( testAsFunction );
7024+    }
7025+
7026+    AutoReg::AutoReg( Detail::unique_ptr<ITestInvoker> invoker, SourceLineInfo const& lineInfo, StringRef classOrMethod, NameAndTags const& nameAndTags ) noexcept {
7027+        CATCH_TRY {
7028+            getMutableRegistryHub()
7029+                    .registerTest(
7030+                        makeTestCaseInfo(
7031+                            extractClassName( classOrMethod ),
7032+                            nameAndTags,
7033+                            lineInfo),
7034+                        CATCH_MOVE(invoker)
7035+                    );
7036+        } CATCH_CATCH_ALL {
7037+            // Do not throw when constructing global objects, instead register the exception to be processed later
7038+            getMutableRegistryHub().registerStartupException();
7039+        }
7040+    }
7041+}
7042+
7043+
7044+
7045+
7046+
7047+namespace Catch {
7048+
7049+    TestSpecParser::TestSpecParser( ITagAliasRegistry const& tagAliases ) : m_tagAliases( &tagAliases ) {}
7050+
7051+    TestSpecParser& TestSpecParser::parse( std::string const& arg ) {
7052+        m_mode = None;
7053+        m_exclusion = false;
7054+        m_arg = m_tagAliases->expandAliases( arg );
7055+        m_escapeChars.clear();
7056+        m_substring.reserve(m_arg.size());
7057+        m_patternName.reserve(m_arg.size());
7058+        m_realPatternPos = 0;
7059+
7060+        for( m_pos = 0; m_pos < m_arg.size(); ++m_pos )
7061+          //if visitChar fails
7062+           if( !visitChar( m_arg[m_pos] ) ){
7063+               m_testSpec.m_invalidSpecs.push_back(arg);
7064+               break;
7065+           }
7066+        endMode();
7067+        return *this;
7068+    }
7069+    TestSpec TestSpecParser::testSpec() {
7070+        addFilter();
7071+        return CATCH_MOVE(m_testSpec);
7072+    }
7073+    bool TestSpecParser::visitChar( char c ) {
7074+        if( (m_mode != EscapedName) && (c == '\\') ) {
7075+            escape();
7076+            addCharToPattern(c);
7077+            return true;
7078+        }else if((m_mode != EscapedName) && (c == ',') )  {
7079+            return separate();
7080+        }
7081+
7082+        switch( m_mode ) {
7083+        case None:
7084+            if( processNoneChar( c ) )
7085+                return true;
7086+            break;
7087+        case Name:
7088+            processNameChar( c );
7089+            break;
7090+        case EscapedName:
7091+            endMode();
7092+            addCharToPattern(c);
7093+            return true;
7094+        default:
7095+        case Tag:
7096+        case QuotedName:
7097+            if( processOtherChar( c ) )
7098+                return true;
7099+            break;
7100+        }
7101+
7102+        m_substring += c;
7103+        if( !isControlChar( c ) ) {
7104+            m_patternName += c;
7105+            m_realPatternPos++;
7106+        }
7107+        return true;
7108+    }
7109+    // Two of the processing methods return true to signal the caller to return
7110+    // without adding the given character to the current pattern strings
7111+    bool TestSpecParser::processNoneChar( char c ) {
7112+        switch( c ) {
7113+        case ' ':
7114+            return true;
7115+        case '~':
7116+            m_exclusion = true;
7117+            return false;
7118+        case '[':
7119+            startNewMode( Tag );
7120+            return false;
7121+        case '"':
7122+            startNewMode( QuotedName );
7123+            return false;
7124+        default:
7125+            startNewMode( Name );
7126+            return false;
7127+        }
7128+    }
7129+    void TestSpecParser::processNameChar( char c ) {
7130+        if( c == '[' ) {
7131+            if( m_substring == "exclude:" )
7132+                m_exclusion = true;
7133+            else
7134+                endMode();
7135+            startNewMode( Tag );
7136+        }
7137+    }
7138+    bool TestSpecParser::processOtherChar( char c ) {
7139+        if( !isControlChar( c ) )
7140+            return false;
7141+        m_substring += c;
7142+        endMode();
7143+        return true;
7144+    }
7145+    void TestSpecParser::startNewMode( Mode mode ) {
7146+        m_mode = mode;
7147+    }
7148+    void TestSpecParser::endMode() {
7149+        switch( m_mode ) {
7150+        case Name:
7151+        case QuotedName:
7152+            return addNamePattern();
7153+        case Tag:
7154+            return addTagPattern();
7155+        case EscapedName:
7156+            revertBackToLastMode();
7157+            return;
7158+        case None:
7159+        default:
7160+            return startNewMode( None );
7161+        }
7162+    }
7163+    void TestSpecParser::escape() {
7164+        saveLastMode();
7165+        m_mode = EscapedName;
7166+        m_escapeChars.push_back(m_realPatternPos);
7167+    }
7168+    bool TestSpecParser::isControlChar( char c ) const {
7169+        switch( m_mode ) {
7170+            default:
7171+                return false;
7172+            case None:
7173+                return c == '~';
7174+            case Name:
7175+                return c == '[';
7176+            case EscapedName:
7177+                return true;
7178+            case QuotedName:
7179+                return c == '"';
7180+            case Tag:
7181+                return c == '[' || c == ']';
7182+        }
7183+    }
7184+
7185+    void TestSpecParser::addFilter() {
7186+        if( !m_currentFilter.m_required.empty() || !m_currentFilter.m_forbidden.empty() ) {
7187+            m_testSpec.m_filters.push_back( CATCH_MOVE(m_currentFilter) );
7188+            m_currentFilter = TestSpec::Filter();
7189+        }
7190+    }
7191+
7192+    void TestSpecParser::saveLastMode() {
7193+      lastMode = m_mode;
7194+    }
7195+
7196+    void TestSpecParser::revertBackToLastMode() {
7197+      m_mode = lastMode;
7198+    }
7199+
7200+    bool TestSpecParser::separate() {
7201+      if( (m_mode==QuotedName) || (m_mode==Tag) ){
7202+         //invalid argument, signal failure to previous scope.
7203+         m_mode = None;
7204+         m_pos = m_arg.size();
7205+         m_substring.clear();
7206+         m_patternName.clear();
7207+         m_realPatternPos = 0;
7208+         return false;
7209+      }
7210+      endMode();
7211+      addFilter();
7212+      return true; //success
7213+    }
7214+
7215+    std::string TestSpecParser::preprocessPattern() {
7216+        std::string token = m_patternName;
7217+        for (std::size_t i = 0; i < m_escapeChars.size(); ++i)
7218+            token = token.substr(0, m_escapeChars[i] - i) + token.substr(m_escapeChars[i] - i + 1);
7219+        m_escapeChars.clear();
7220+        if (startsWith(token, "exclude:")) {
7221+            m_exclusion = true;
7222+            token = token.substr(8);
7223+        }
7224+
7225+        m_patternName.clear();
7226+        m_realPatternPos = 0;
7227+
7228+        return token;
7229+    }
7230+
7231+    void TestSpecParser::addNamePattern() {
7232+        auto token = preprocessPattern();
7233+
7234+        if (!token.empty()) {
7235+            if (m_exclusion) {
7236+                m_currentFilter.m_forbidden.emplace_back(Detail::make_unique<TestSpec::NamePattern>(token, m_substring));
7237+            } else {
7238+                m_currentFilter.m_required.emplace_back(Detail::make_unique<TestSpec::NamePattern>(token, m_substring));
7239+            }
7240+        }
7241+        m_substring.clear();
7242+        m_exclusion = false;
7243+        m_mode = None;
7244+    }
7245+
7246+    void TestSpecParser::addTagPattern() {
7247+        auto token = preprocessPattern();
7248+
7249+        if (!token.empty()) {
7250+            // If the tag pattern is the "hide and tag" shorthand (e.g. [.foo])
7251+            // we have to create a separate hide tag and shorten the real one
7252+            if (token.size() > 1 && token[0] == '.') {
7253+                token.erase(token.begin());
7254+                if (m_exclusion) {
7255+                    m_currentFilter.m_forbidden.emplace_back(Detail::make_unique<TestSpec::TagPattern>(".", m_substring));
7256+                } else {
7257+                    m_currentFilter.m_required.emplace_back(Detail::make_unique<TestSpec::TagPattern>(".", m_substring));
7258+                }
7259+            }
7260+            if (m_exclusion) {
7261+                m_currentFilter.m_forbidden.emplace_back(Detail::make_unique<TestSpec::TagPattern>(token, m_substring));
7262+            } else {
7263+                m_currentFilter.m_required.emplace_back(Detail::make_unique<TestSpec::TagPattern>(token, m_substring));
7264+            }
7265+        }
7266+        m_substring.clear();
7267+        m_exclusion = false;
7268+        m_mode = None;
7269+    }
7270+
7271+} // namespace Catch
7272+
7273+
7274+
7275+#include <algorithm>
7276+#include <cstring>
7277+#include <ostream>
7278+
7279+namespace {
7280+    bool isWhitespace( char c ) {
7281+        return c == ' ' || c == '\t' || c == '\n' || c == '\r';
7282+    }
7283+
7284+    bool isBreakableBefore( char c ) {
7285+        static const char chars[] = "[({<|";
7286+        return std::memchr( chars, c, sizeof( chars ) - 1 ) != nullptr;
7287+    }
7288+
7289+    bool isBreakableAfter( char c ) {
7290+        static const char chars[] = "])}>.,:;*+-=&/\\";
7291+        return std::memchr( chars, c, sizeof( chars ) - 1 ) != nullptr;
7292+    }
7293+
7294+    bool isBoundary( std::string const& line, size_t at ) {
7295+        assert( at > 0 );
7296+        assert( at <= line.size() );
7297+
7298+        return at == line.size() ||
7299+               ( isWhitespace( line[at] ) && !isWhitespace( line[at - 1] ) ) ||
7300+               isBreakableBefore( line[at] ) ||
7301+               isBreakableAfter( line[at - 1] );
7302+    }
7303+
7304+} // namespace
7305+
7306+namespace Catch {
7307+    namespace TextFlow {
7308+
7309+        void Column::const_iterator::calcLength() {
7310+            m_addHyphen = false;
7311+            m_parsedTo = m_lineStart;
7312+
7313+            std::string const& current_line = m_column.m_string;
7314+            if ( current_line[m_lineStart] == '\n' ) {
7315+                ++m_parsedTo;
7316+            }
7317+
7318+            const auto maxLineLength = m_column.m_width - indentSize();
7319+            const auto maxParseTo = std::min(current_line.size(), m_lineStart + maxLineLength);
7320+            while ( m_parsedTo < maxParseTo &&
7321+                    current_line[m_parsedTo] != '\n' ) {
7322+                ++m_parsedTo;
7323+            }
7324+
7325+            // If we encountered a newline before the column is filled,
7326+            // then we linebreak at the newline and consider this line
7327+            // finished.
7328+            if ( m_parsedTo < m_lineStart + maxLineLength ) {
7329+                m_lineLength = m_parsedTo - m_lineStart;
7330+            } else {
7331+                // Look for a natural linebreak boundary in the column
7332+                // (We look from the end, so that the first found boundary is
7333+                // the right one)
7334+                size_t newLineLength = maxLineLength;
7335+                while ( newLineLength > 0 && !isBoundary( current_line, m_lineStart + newLineLength ) ) {
7336+                    --newLineLength;
7337+                }
7338+                while ( newLineLength > 0 &&
7339+                        isWhitespace( current_line[m_lineStart + newLineLength - 1] ) ) {
7340+                    --newLineLength;
7341+                }
7342+
7343+                // If we found one, then that is where we linebreak
7344+                if ( newLineLength > 0 ) {
7345+                    m_lineLength = newLineLength;
7346+                } else {
7347+                    // Otherwise we have to split text with a hyphen
7348+                    m_addHyphen = true;
7349+                    m_lineLength = maxLineLength - 1;
7350+                }
7351+            }
7352+        }
7353+
7354+        size_t Column::const_iterator::indentSize() const {
7355+            auto initial =
7356+                m_lineStart == 0 ? m_column.m_initialIndent : std::string::npos;
7357+            return initial == std::string::npos ? m_column.m_indent : initial;
7358+        }
7359+
7360+        std::string
7361+        Column::const_iterator::addIndentAndSuffix( size_t position,
7362+                                              size_t length ) const {
7363+            std::string ret;
7364+            const auto desired_indent = indentSize();
7365+            ret.reserve( desired_indent + length + m_addHyphen );
7366+            ret.append( desired_indent, ' ' );
7367+            ret.append( m_column.m_string, position, length );
7368+            if ( m_addHyphen ) {
7369+                ret.push_back( '-' );
7370+            }
7371+
7372+            return ret;
7373+        }
7374+
7375+        Column::const_iterator::const_iterator( Column const& column ): m_column( column ) {
7376+            assert( m_column.m_width > m_column.m_indent );
7377+            assert( m_column.m_initialIndent == std::string::npos ||
7378+                    m_column.m_width > m_column.m_initialIndent );
7379+            calcLength();
7380+            if ( m_lineLength == 0 ) {
7381+                m_lineStart = m_column.m_string.size();
7382+            }
7383+        }
7384+
7385+        std::string Column::const_iterator::operator*() const {
7386+            assert( m_lineStart <= m_parsedTo );
7387+            return addIndentAndSuffix( m_lineStart, m_lineLength );
7388+        }
7389+
7390+        Column::const_iterator& Column::const_iterator::operator++() {
7391+            m_lineStart += m_lineLength;
7392+            std::string const& current_line = m_column.m_string;
7393+            if ( m_lineStart < current_line.size() && current_line[m_lineStart] == '\n' ) {
7394+                m_lineStart += 1;
7395+            } else {
7396+                while ( m_lineStart < current_line.size() &&
7397+                        isWhitespace( current_line[m_lineStart] ) ) {
7398+                    ++m_lineStart;
7399+                }
7400+            }
7401+
7402+            if ( m_lineStart != current_line.size() ) {
7403+                calcLength();
7404+            }
7405+            return *this;
7406+        }
7407+
7408+        Column::const_iterator Column::const_iterator::operator++( int ) {
7409+            const_iterator prev( *this );
7410+            operator++();
7411+            return prev;
7412+        }
7413+
7414+        std::ostream& operator<<( std::ostream& os, Column const& col ) {
7415+            bool first = true;
7416+            for ( auto line : col ) {
7417+                if ( first ) {
7418+                    first = false;
7419+                } else {
7420+                    os << '\n';
7421+                }
7422+                os << line;
7423+            }
7424+            return os;
7425+        }
7426+
7427+        Column Spacer( size_t spaceWidth ) {
7428+            Column ret{ "" };
7429+            ret.width( spaceWidth );
7430+            return ret;
7431+        }
7432+
7433+        Columns::iterator::iterator( Columns const& columns, EndTag ):
7434+            m_columns( columns.m_columns ), m_activeIterators( 0 ) {
7435+
7436+            m_iterators.reserve( m_columns.size() );
7437+            for ( auto const& col : m_columns ) {
7438+                m_iterators.push_back( col.end() );
7439+            }
7440+        }
7441+
7442+        Columns::iterator::iterator( Columns const& columns ):
7443+            m_columns( columns.m_columns ),
7444+            m_activeIterators( m_columns.size() ) {
7445+
7446+            m_iterators.reserve( m_columns.size() );
7447+            for ( auto const& col : m_columns ) {
7448+                m_iterators.push_back( col.begin() );
7449+            }
7450+        }
7451+
7452+        std::string Columns::iterator::operator*() const {
7453+            std::string row, padding;
7454+
7455+            for ( size_t i = 0; i < m_columns.size(); ++i ) {
7456+                const auto width = m_columns[i].width();
7457+                if ( m_iterators[i] != m_columns[i].end() ) {
7458+                    std::string col = *m_iterators[i];
7459+                    row += padding;
7460+                    row += col;
7461+
7462+                    padding.clear();
7463+                    if ( col.size() < width ) {
7464+                        padding.append( width - col.size(), ' ' );
7465+                    }
7466+                } else {
7467+                    padding.append( width, ' ' );
7468+                }
7469+            }
7470+            return row;
7471+        }
7472+
7473+        Columns::iterator& Columns::iterator::operator++() {
7474+            for ( size_t i = 0; i < m_columns.size(); ++i ) {
7475+                if ( m_iterators[i] != m_columns[i].end() ) {
7476+                    ++m_iterators[i];
7477+                }
7478+            }
7479+            return *this;
7480+        }
7481+
7482+        Columns::iterator Columns::iterator::operator++( int ) {
7483+            iterator prev( *this );
7484+            operator++();
7485+            return prev;
7486+        }
7487+
7488+        std::ostream& operator<<( std::ostream& os, Columns const& cols ) {
7489+            bool first = true;
7490+            for ( auto line : cols ) {
7491+                if ( first ) {
7492+                    first = false;
7493+                } else {
7494+                    os << '\n';
7495+                }
7496+                os << line;
7497+            }
7498+            return os;
7499+        }
7500+
7501+        Columns operator+(Column const& lhs, Column const& rhs) {
7502+            Columns cols;
7503+            cols += lhs;
7504+            cols += rhs;
7505+            return cols;
7506+        }
7507+        Columns operator+(Column&& lhs, Column&& rhs) {
7508+            Columns cols;
7509+            cols += CATCH_MOVE( lhs );
7510+            cols += CATCH_MOVE( rhs );
7511+            return cols;
7512+        }
7513+
7514+        Columns& operator+=(Columns& lhs, Column const& rhs) {
7515+            lhs.m_columns.push_back( rhs );
7516+            return lhs;
7517+        }
7518+        Columns& operator+=(Columns& lhs, Column&& rhs) {
7519+            lhs.m_columns.push_back( CATCH_MOVE(rhs) );
7520+            return lhs;
7521+        }
7522+        Columns operator+( Columns const& lhs, Column const& rhs ) {
7523+            auto combined( lhs );
7524+            combined += rhs;
7525+            return combined;
7526+        }
7527+        Columns operator+( Columns&& lhs, Column&& rhs ) {
7528+            lhs += CATCH_MOVE( rhs );
7529+            return CATCH_MOVE( lhs );
7530+        }
7531+
7532+    } // namespace TextFlow
7533+} // namespace Catch
7534+
7535+
7536+
7537+
7538+#include <exception>
7539+
7540+namespace Catch {
7541+    bool uncaught_exceptions() {
7542+#if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
7543+        return false;
7544+#elif defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS)
7545+        return std::uncaught_exceptions() > 0;
7546+#else
7547+        return std::uncaught_exception();
7548+#endif
7549+  }
7550+} // end namespace Catch
7551+
7552+
7553+
7554+namespace Catch {
7555+
7556+    WildcardPattern::WildcardPattern( std::string const& pattern,
7557+                                      CaseSensitive caseSensitivity )
7558+    :   m_caseSensitivity( caseSensitivity ),
7559+        m_pattern( normaliseString( pattern ) )
7560+    {
7561+        if( startsWith( m_pattern, '*' ) ) {
7562+            m_pattern = m_pattern.substr( 1 );
7563+            m_wildcard = WildcardAtStart;
7564+        }
7565+        if( endsWith( m_pattern, '*' ) ) {
7566+            m_pattern = m_pattern.substr( 0, m_pattern.size()-1 );
7567+            m_wildcard = static_cast<WildcardPosition>( m_wildcard | WildcardAtEnd );
7568+        }
7569+    }
7570+
7571+    bool WildcardPattern::matches( std::string const& str ) const {
7572+        switch( m_wildcard ) {
7573+            case NoWildcard:
7574+                return m_pattern == normaliseString( str );
7575+            case WildcardAtStart:
7576+                return endsWith( normaliseString( str ), m_pattern );
7577+            case WildcardAtEnd:
7578+                return startsWith( normaliseString( str ), m_pattern );
7579+            case WildcardAtBothEnds:
7580+                return contains( normaliseString( str ), m_pattern );
7581+            default:
7582+                CATCH_INTERNAL_ERROR( "Unknown enum" );
7583+        }
7584+    }
7585+
7586+    std::string WildcardPattern::normaliseString( std::string const& str ) const {
7587+        return trim( m_caseSensitivity == CaseSensitive::No ? toLower( str ) : str );
7588+    }
7589+}
7590+
7591+
7592+// Note: swapping these two includes around causes MSVC to error out
7593+//       while in /permissive- mode. No, I don't know why.
7594+//       Tested on VS 2019, 18.{3, 4}.x
7595+
7596+#include <cstdint>
7597+#include <iomanip>
7598+#include <type_traits>
7599+
7600+namespace Catch {
7601+
7602+namespace {
7603+
7604+    size_t trailingBytes(unsigned char c) {
7605+        if ((c & 0xE0) == 0xC0) {
7606+            return 2;
7607+        }
7608+        if ((c & 0xF0) == 0xE0) {
7609+            return 3;
7610+        }
7611+        if ((c & 0xF8) == 0xF0) {
7612+            return 4;
7613+        }
7614+        CATCH_INTERNAL_ERROR("Invalid multibyte utf-8 start byte encountered");
7615+    }
7616+
7617+    uint32_t headerValue(unsigned char c) {
7618+        if ((c & 0xE0) == 0xC0) {
7619+            return c & 0x1F;
7620+        }
7621+        if ((c & 0xF0) == 0xE0) {
7622+            return c & 0x0F;
7623+        }
7624+        if ((c & 0xF8) == 0xF0) {
7625+            return c & 0x07;
7626+        }
7627+        CATCH_INTERNAL_ERROR("Invalid multibyte utf-8 start byte encountered");
7628+    }
7629+
7630+    void hexEscapeChar(std::ostream& os, unsigned char c) {
7631+        std::ios_base::fmtflags f(os.flags());
7632+        os << "\\x"
7633+            << std::uppercase << std::hex << std::setfill('0') << std::setw(2)
7634+            << static_cast<int>(c);
7635+        os.flags(f);
7636+    }
7637+
7638+    bool shouldNewline(XmlFormatting fmt) {
7639+        return !!(static_cast<std::underlying_type_t<XmlFormatting>>(fmt & XmlFormatting::Newline));
7640+    }
7641+
7642+    bool shouldIndent(XmlFormatting fmt) {
7643+        return !!(static_cast<std::underlying_type_t<XmlFormatting>>(fmt & XmlFormatting::Indent));
7644+    }
7645+
7646+} // anonymous namespace
7647+
7648+    XmlFormatting operator | (XmlFormatting lhs, XmlFormatting rhs) {
7649+        return static_cast<XmlFormatting>(
7650+            static_cast<std::underlying_type_t<XmlFormatting>>(lhs) |
7651+            static_cast<std::underlying_type_t<XmlFormatting>>(rhs)
7652+        );
7653+    }
7654+
7655+    XmlFormatting operator & (XmlFormatting lhs, XmlFormatting rhs) {
7656+        return static_cast<XmlFormatting>(
7657+            static_cast<std::underlying_type_t<XmlFormatting>>(lhs) &
7658+            static_cast<std::underlying_type_t<XmlFormatting>>(rhs)
7659+        );
7660+    }
7661+
7662+
7663+    XmlEncode::XmlEncode( StringRef str, ForWhat forWhat )
7664+    :   m_str( str ),
7665+        m_forWhat( forWhat )
7666+    {}
7667+
7668+    void XmlEncode::encodeTo( std::ostream& os ) const {
7669+        // Apostrophe escaping not necessary if we always use " to write attributes
7670+        // (see: http://www.w3.org/TR/xml/#syntax)
7671+
7672+        for( std::size_t idx = 0; idx < m_str.size(); ++ idx ) {
7673+            unsigned char c = static_cast<unsigned char>(m_str[idx]);
7674+            switch (c) {
7675+            case '<':   os << "&lt;"; break;
7676+            case '&':   os << "&amp;"; break;
7677+
7678+            case '>':
7679+                // See: http://www.w3.org/TR/xml/#syntax
7680+                if (idx > 2 && m_str[idx - 1] == ']' && m_str[idx - 2] == ']')
7681+                    os << "&gt;";
7682+                else
7683+                    os << c;
7684+                break;
7685+
7686+            case '\"':
7687+                if (m_forWhat == ForAttributes)
7688+                    os << "&quot;";
7689+                else
7690+                    os << c;
7691+                break;
7692+
7693+            default:
7694+                // Check for control characters and invalid utf-8
7695+
7696+                // Escape control characters in standard ascii
7697+                // see http://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0
7698+                if (c < 0x09 || (c > 0x0D && c < 0x20) || c == 0x7F) {
7699+                    hexEscapeChar(os, c);
7700+                    break;
7701+                }
7702+
7703+                // Plain ASCII: Write it to stream
7704+                if (c < 0x7F) {
7705+                    os << c;
7706+                    break;
7707+                }
7708+
7709+                // UTF-8 territory
7710+                // Check if the encoding is valid and if it is not, hex escape bytes.
7711+                // Important: We do not check the exact decoded values for validity, only the encoding format
7712+                // First check that this bytes is a valid lead byte:
7713+                // This means that it is not encoded as 1111 1XXX
7714+                // Or as 10XX XXXX
7715+                if (c <  0xC0 ||
7716+                    c >= 0xF8) {
7717+                    hexEscapeChar(os, c);
7718+                    break;
7719+                }
7720+
7721+                auto encBytes = trailingBytes(c);
7722+                // Are there enough bytes left to avoid accessing out-of-bounds memory?
7723+                if (idx + encBytes - 1 >= m_str.size()) {
7724+                    hexEscapeChar(os, c);
7725+                    break;
7726+                }
7727+                // The header is valid, check data
7728+                // The next encBytes bytes must together be a valid utf-8
7729+                // This means: bitpattern 10XX XXXX and the extracted value is sane (ish)
7730+                bool valid = true;
7731+                uint32_t value = headerValue(c);
7732+                for (std::size_t n = 1; n < encBytes; ++n) {
7733+                    unsigned char nc = static_cast<unsigned char>(m_str[idx + n]);
7734+                    valid &= ((nc & 0xC0) == 0x80);
7735+                    value = (value << 6) | (nc & 0x3F);
7736+                }
7737+
7738+                if (
7739+                    // Wrong bit pattern of following bytes
7740+                    (!valid) ||
7741+                    // Overlong encodings
7742+                    (value < 0x80) ||
7743+                    (0x80 <= value && value < 0x800   && encBytes > 2) ||
7744+                    (0x800 < value && value < 0x10000 && encBytes > 3) ||
7745+                    // Encoded value out of range
7746+                    (value >= 0x110000)
7747+                    ) {
7748+                    hexEscapeChar(os, c);
7749+                    break;
7750+                }
7751+
7752+                // If we got here, this is in fact a valid(ish) utf-8 sequence
7753+                for (std::size_t n = 0; n < encBytes; ++n) {
7754+                    os << m_str[idx + n];
7755+                }
7756+                idx += encBytes - 1;
7757+                break;
7758+            }
7759+        }
7760+    }
7761+
7762+    std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ) {
7763+        xmlEncode.encodeTo( os );
7764+        return os;
7765+    }
7766+
7767+    XmlWriter::ScopedElement::ScopedElement( XmlWriter* writer, XmlFormatting fmt )
7768+    :   m_writer( writer ),
7769+        m_fmt(fmt)
7770+    {}
7771+
7772+    XmlWriter::ScopedElement::ScopedElement( ScopedElement&& other ) noexcept
7773+    :   m_writer( other.m_writer ),
7774+        m_fmt(other.m_fmt)
7775+    {
7776+        other.m_writer = nullptr;
7777+        other.m_fmt = XmlFormatting::None;
7778+    }
7779+    XmlWriter::ScopedElement& XmlWriter::ScopedElement::operator=( ScopedElement&& other ) noexcept {
7780+        if ( m_writer ) {
7781+            m_writer->endElement();
7782+        }
7783+        m_writer = other.m_writer;
7784+        other.m_writer = nullptr;
7785+        m_fmt = other.m_fmt;
7786+        other.m_fmt = XmlFormatting::None;
7787+        return *this;
7788+    }
7789+
7790+
7791+    XmlWriter::ScopedElement::~ScopedElement() {
7792+        if (m_writer) {
7793+            m_writer->endElement(m_fmt);
7794+        }
7795+    }
7796+
7797+    XmlWriter::ScopedElement&
7798+    XmlWriter::ScopedElement::writeText( StringRef text, XmlFormatting fmt ) {
7799+        m_writer->writeText( text, fmt );
7800+        return *this;
7801+    }
7802+
7803+    XmlWriter::ScopedElement&
7804+    XmlWriter::ScopedElement::writeAttribute( StringRef name,
7805+                                              StringRef attribute ) {
7806+        m_writer->writeAttribute( name, attribute );
7807+        return *this;
7808+    }
7809+
7810+
7811+    XmlWriter::XmlWriter( std::ostream& os ) : m_os( os )
7812+    {
7813+        writeDeclaration();
7814+    }
7815+
7816+    XmlWriter::~XmlWriter() {
7817+        while (!m_tags.empty()) {
7818+            endElement();
7819+        }
7820+        newlineIfNecessary();
7821+    }
7822+
7823+    XmlWriter& XmlWriter::startElement( std::string const& name, XmlFormatting fmt ) {
7824+        ensureTagClosed();
7825+        newlineIfNecessary();
7826+        if (shouldIndent(fmt)) {
7827+            m_os << m_indent;
7828+            m_indent += "  ";
7829+        }
7830+        m_os << '<' << name;
7831+        m_tags.push_back( name );
7832+        m_tagIsOpen = true;
7833+        applyFormatting(fmt);
7834+        return *this;
7835+    }
7836+
7837+    XmlWriter::ScopedElement XmlWriter::scopedElement( std::string const& name, XmlFormatting fmt ) {
7838+        ScopedElement scoped( this, fmt );
7839+        startElement( name, fmt );
7840+        return scoped;
7841+    }
7842+
7843+    XmlWriter& XmlWriter::endElement(XmlFormatting fmt) {
7844+        m_indent = m_indent.substr(0, m_indent.size() - 2);
7845+
7846+        if( m_tagIsOpen ) {
7847+            m_os << "/>";
7848+            m_tagIsOpen = false;
7849+        } else {
7850+            newlineIfNecessary();
7851+            if (shouldIndent(fmt)) {
7852+                m_os << m_indent;
7853+            }
7854+            m_os << "</" << m_tags.back() << '>';
7855+        }
7856+        m_os << std::flush;
7857+        applyFormatting(fmt);
7858+        m_tags.pop_back();
7859+        return *this;
7860+    }
7861+
7862+    XmlWriter& XmlWriter::writeAttribute( StringRef name,
7863+                                          StringRef attribute ) {
7864+        if( !name.empty() && !attribute.empty() )
7865+            m_os << ' ' << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << '"';
7866+        return *this;
7867+    }
7868+
7869+    XmlWriter& XmlWriter::writeAttribute( StringRef name, bool attribute ) {
7870+        writeAttribute(name, (attribute ? "true"_sr : "false"_sr));
7871+        return *this;
7872+    }
7873+
7874+    XmlWriter& XmlWriter::writeAttribute( StringRef name,
7875+                                          char const* attribute ) {
7876+        writeAttribute( name, StringRef( attribute ) );
7877+        return *this;
7878+    }
7879+
7880+    XmlWriter& XmlWriter::writeText( StringRef text, XmlFormatting fmt ) {
7881+        CATCH_ENFORCE(!m_tags.empty(), "Cannot write text as top level element");
7882+        if( !text.empty() ){
7883+            bool tagWasOpen = m_tagIsOpen;
7884+            ensureTagClosed();
7885+            if (tagWasOpen && shouldIndent(fmt)) {
7886+                m_os << m_indent;
7887+            }
7888+            m_os << XmlEncode( text, XmlEncode::ForTextNodes );
7889+            applyFormatting(fmt);
7890+        }
7891+        return *this;
7892+    }
7893+
7894+    XmlWriter& XmlWriter::writeComment( StringRef text, XmlFormatting fmt ) {
7895+        ensureTagClosed();
7896+        if (shouldIndent(fmt)) {
7897+            m_os << m_indent;
7898+        }
7899+        m_os << "<!-- " << text << " -->";
7900+        applyFormatting(fmt);
7901+        return *this;
7902+    }
7903+
7904+    void XmlWriter::writeStylesheetRef( StringRef url ) {
7905+        m_os << R"(<?xml-stylesheet type="text/xsl" href=")" << url << R"("?>)" << '\n';
7906+    }
7907+
7908+    void XmlWriter::ensureTagClosed() {
7909+        if( m_tagIsOpen ) {
7910+            m_os << '>' << std::flush;
7911+            newlineIfNecessary();
7912+            m_tagIsOpen = false;
7913+        }
7914+    }
7915+
7916+    void XmlWriter::applyFormatting(XmlFormatting fmt) {
7917+        m_needsNewline = shouldNewline(fmt);
7918+    }
7919+
7920+    void XmlWriter::writeDeclaration() {
7921+        m_os << R"(<?xml version="1.0" encoding="UTF-8"?>)" << '\n';
7922+    }
7923+
7924+    void XmlWriter::newlineIfNecessary() {
7925+        if( m_needsNewline ) {
7926+            m_os << '\n' << std::flush;
7927+            m_needsNewline = false;
7928+        }
7929+    }
7930+}
7931+
7932+
7933+
7934+
7935+
7936+namespace Catch {
7937+namespace Matchers {
7938+
7939+    std::string MatcherUntypedBase::toString() const {
7940+        if (m_cachedToString.empty()) {
7941+            m_cachedToString = describe();
7942+        }
7943+        return m_cachedToString;
7944+    }
7945+
7946+    MatcherUntypedBase::~MatcherUntypedBase() = default;
7947+
7948+} // namespace Matchers
7949+} // namespace Catch
7950+
7951+
7952+
7953+
7954+namespace Catch {
7955+namespace Matchers {
7956+
7957+    std::string IsEmptyMatcher::describe() const {
7958+        return "is empty";
7959+    }
7960+
7961+    std::string HasSizeMatcher::describe() const {
7962+        ReusableStringStream sstr;
7963+        sstr << "has size == " << m_target_size;
7964+        return sstr.str();
7965+    }
7966+
7967+    IsEmptyMatcher IsEmpty() {
7968+        return {};
7969+    }
7970+
7971+    HasSizeMatcher SizeIs(std::size_t sz) {
7972+        return HasSizeMatcher{ sz };
7973+    }
7974+
7975+} // end namespace Matchers
7976+} // end namespace Catch
7977+
7978+
7979+
7980+namespace Catch {
7981+namespace Matchers {
7982+
7983+bool ExceptionMessageMatcher::match(std::exception const& ex) const {
7984+    return ex.what() == m_message;
7985+}
7986+
7987+std::string ExceptionMessageMatcher::describe() const {
7988+    return "exception message matches \"" + m_message + '"';
7989+}
7990+
7991+ExceptionMessageMatcher Message(std::string const& message) {
7992+    return ExceptionMessageMatcher(message);
7993+}
7994+
7995+} // namespace Matchers
7996+} // namespace Catch
7997+
7998+
7999+
8000+#include <algorithm>
8001+#include <cmath>
8002+#include <cstdlib>
8003+#include <cstdint>
8004+#include <sstream>
8005+#include <iomanip>
8006+#include <limits>
8007+
8008+
8009+namespace Catch {
8010+namespace {
8011+
8012+    template <typename FP>
8013+    bool almostEqualUlps(FP lhs, FP rhs, uint64_t maxUlpDiff) {
8014+        // Comparison with NaN should always be false.
8015+        // This way we can rule it out before getting into the ugly details
8016+        if (Catch::isnan(lhs) || Catch::isnan(rhs)) {
8017+            return false;
8018+        }
8019+
8020+        // This should also handle positive and negative zeros, infinities
8021+        const auto ulpDist = ulpDistance(lhs, rhs);
8022+
8023+        return ulpDist <= maxUlpDiff;
8024+    }
8025+
8026+
8027+template <typename FP>
8028+FP step(FP start, FP direction, uint64_t steps) {
8029+    for (uint64_t i = 0; i < steps; ++i) {
8030+        start = Catch::nextafter(start, direction);
8031+    }
8032+    return start;
8033+}
8034+
8035+// Performs equivalent check of std::fabs(lhs - rhs) <= margin
8036+// But without the subtraction to allow for INFINITY in comparison
8037+bool marginComparison(double lhs, double rhs, double margin) {
8038+    return (lhs + margin >= rhs) && (rhs + margin >= lhs);
8039+}
8040+
8041+template <typename FloatingPoint>
8042+void write(std::ostream& out, FloatingPoint num) {
8043+    out << std::scientific
8044+        << std::setprecision(std::numeric_limits<FloatingPoint>::max_digits10 - 1)
8045+        << num;
8046+}
8047+
8048+} // end anonymous namespace
8049+
8050+namespace Matchers {
8051+namespace Detail {
8052+
8053+    enum class FloatingPointKind : uint8_t {
8054+        Float,
8055+        Double
8056+    };
8057+
8058+} // end namespace Detail
8059+
8060+
8061+    WithinAbsMatcher::WithinAbsMatcher(double target, double margin)
8062+        :m_target{ target }, m_margin{ margin } {
8063+        CATCH_ENFORCE(margin >= 0, "Invalid margin: " << margin << '.'
8064+            << " Margin has to be non-negative.");
8065+    }
8066+
8067+    // Performs equivalent check of std::fabs(lhs - rhs) <= margin
8068+    // But without the subtraction to allow for INFINITY in comparison
8069+    bool WithinAbsMatcher::match(double const& matchee) const {
8070+        return (matchee + m_margin >= m_target) && (m_target + m_margin >= matchee);
8071+    }
8072+
8073+    std::string WithinAbsMatcher::describe() const {
8074+        return "is within " + ::Catch::Detail::stringify(m_margin) + " of " + ::Catch::Detail::stringify(m_target);
8075+    }
8076+
8077+
8078+    WithinUlpsMatcher::WithinUlpsMatcher(double target, uint64_t ulps, Detail::FloatingPointKind baseType)
8079+        :m_target{ target }, m_ulps{ ulps }, m_type{ baseType } {
8080+        CATCH_ENFORCE(m_type == Detail::FloatingPointKind::Double
8081+                   || m_ulps < (std::numeric_limits<uint32_t>::max)(),
8082+            "Provided ULP is impossibly large for a float comparison.");
8083+        CATCH_ENFORCE( std::numeric_limits<double>::is_iec559,
8084+                       "WithinUlp matcher only supports platforms with "
8085+                       "IEEE-754 compatible floating point representation" );
8086+    }
8087+
8088+#if defined(__clang__)
8089+#pragma clang diagnostic push
8090+// Clang <3.5 reports on the default branch in the switch below
8091+#pragma clang diagnostic ignored "-Wunreachable-code"
8092+#endif
8093+
8094+    bool WithinUlpsMatcher::match(double const& matchee) const {
8095+        switch (m_type) {
8096+        case Detail::FloatingPointKind::Float:
8097+            return almostEqualUlps<float>(static_cast<float>(matchee), static_cast<float>(m_target), m_ulps);
8098+        case Detail::FloatingPointKind::Double:
8099+            return almostEqualUlps<double>(matchee, m_target, m_ulps);
8100+        default:
8101+            CATCH_INTERNAL_ERROR( "Unknown Detail::FloatingPointKind value" );
8102+        }
8103+    }
8104+
8105+#if defined(__clang__)
8106+#pragma clang diagnostic pop
8107+#endif
8108+
8109+    std::string WithinUlpsMatcher::describe() const {
8110+        std::stringstream ret;
8111+
8112+        ret << "is within " << m_ulps << " ULPs of ";
8113+
8114+        if (m_type == Detail::FloatingPointKind::Float) {
8115+            write(ret, static_cast<float>(m_target));
8116+            ret << 'f';
8117+        } else {
8118+            write(ret, m_target);
8119+        }
8120+
8121+        ret << " ([";
8122+        if (m_type == Detail::FloatingPointKind::Double) {
8123+            write( ret,
8124+                   step( m_target,
8125+                         -std::numeric_limits<double>::infinity(),
8126+                         m_ulps ) );
8127+            ret << ", ";
8128+            write( ret,
8129+                   step( m_target,
8130+                         std::numeric_limits<double>::infinity(),
8131+                         m_ulps ) );
8132+        } else {
8133+            // We have to cast INFINITY to float because of MinGW, see #1782
8134+            write( ret,
8135+                   step( static_cast<float>( m_target ),
8136+                         -std::numeric_limits<float>::infinity(),
8137+                         m_ulps ) );
8138+            ret << ", ";
8139+            write( ret,
8140+                   step( static_cast<float>( m_target ),
8141+                         std::numeric_limits<float>::infinity(),
8142+                         m_ulps ) );
8143+        }
8144+        ret << "])";
8145+
8146+        return ret.str();
8147+    }
8148+
8149+    WithinRelMatcher::WithinRelMatcher(double target, double epsilon):
8150+        m_target(target),
8151+        m_epsilon(epsilon){
8152+        CATCH_ENFORCE(m_epsilon >= 0., "Relative comparison with epsilon <  0 does not make sense.");
8153+        CATCH_ENFORCE(m_epsilon  < 1., "Relative comparison with epsilon >= 1 does not make sense.");
8154+    }
8155+
8156+    bool WithinRelMatcher::match(double const& matchee) const {
8157+        const auto relMargin = m_epsilon * (std::max)(std::fabs(matchee), std::fabs(m_target));
8158+        return marginComparison(matchee, m_target,
8159+                                std::isinf(relMargin)? 0 : relMargin);
8160+    }
8161+
8162+    std::string WithinRelMatcher::describe() const {
8163+        Catch::ReusableStringStream sstr;
8164+        sstr << "and " << m_target << " are within " << m_epsilon * 100. << "% of each other";
8165+        return sstr.str();
8166+    }
8167+
8168+
8169+WithinUlpsMatcher WithinULP(double target, uint64_t maxUlpDiff) {
8170+    return WithinUlpsMatcher(target, maxUlpDiff, Detail::FloatingPointKind::Double);
8171+}
8172+
8173+WithinUlpsMatcher WithinULP(float target, uint64_t maxUlpDiff) {
8174+    return WithinUlpsMatcher(target, maxUlpDiff, Detail::FloatingPointKind::Float);
8175+}
8176+
8177+WithinAbsMatcher WithinAbs(double target, double margin) {
8178+    return WithinAbsMatcher(target, margin);
8179+}
8180+
8181+WithinRelMatcher WithinRel(double target, double eps) {
8182+    return WithinRelMatcher(target, eps);
8183+}
8184+
8185+WithinRelMatcher WithinRel(double target) {
8186+    return WithinRelMatcher(target, std::numeric_limits<double>::epsilon() * 100);
8187+}
8188+
8189+WithinRelMatcher WithinRel(float target, float eps) {
8190+    return WithinRelMatcher(target, eps);
8191+}
8192+
8193+WithinRelMatcher WithinRel(float target) {
8194+    return WithinRelMatcher(target, std::numeric_limits<float>::epsilon() * 100);
8195+}
8196+
8197+
8198+
8199+bool IsNaNMatcher::match( double const& matchee ) const {
8200+    return std::isnan( matchee );
8201+}
8202+
8203+std::string IsNaNMatcher::describe() const {
8204+    using namespace std::string_literals;
8205+    return "is NaN"s;
8206+}
8207+
8208+IsNaNMatcher IsNaN() { return IsNaNMatcher(); }
8209+
8210+    } // namespace Matchers
8211+} // namespace Catch
8212+
8213+
8214+
8215+
8216+std::string Catch::Matchers::Detail::finalizeDescription(const std::string& desc) {
8217+    if (desc.empty()) {
8218+        return "matches undescribed predicate";
8219+    } else {
8220+        return "matches predicate: \"" + desc + '"';
8221+    }
8222+}
8223+
8224+
8225+
8226+namespace Catch {
8227+    namespace Matchers {
8228+        std::string AllTrueMatcher::describe() const { return "contains only true"; }
8229+
8230+        AllTrueMatcher AllTrue() { return AllTrueMatcher{}; }
8231+
8232+        std::string NoneTrueMatcher::describe() const { return "contains no true"; }
8233+
8234+        NoneTrueMatcher NoneTrue() { return NoneTrueMatcher{}; }
8235+
8236+        std::string AnyTrueMatcher::describe() const { return "contains at least one true"; }
8237+
8238+        AnyTrueMatcher AnyTrue() { return AnyTrueMatcher{}; }
8239+    } // namespace Matchers
8240+} // namespace Catch
8241+
8242+
8243+
8244+#include <regex>
8245+
8246+namespace Catch {
8247+namespace Matchers {
8248+
8249+    CasedString::CasedString( std::string const& str, CaseSensitive caseSensitivity )
8250+    :   m_caseSensitivity( caseSensitivity ),
8251+        m_str( adjustString( str ) )
8252+    {}
8253+    std::string CasedString::adjustString( std::string const& str ) const {
8254+        return m_caseSensitivity == CaseSensitive::No
8255+               ? toLower( str )
8256+               : str;
8257+    }
8258+    StringRef CasedString::caseSensitivitySuffix() const {
8259+        return m_caseSensitivity == CaseSensitive::Yes
8260+                   ? StringRef()
8261+                   : " (case insensitive)"_sr;
8262+    }
8263+
8264+
8265+    StringMatcherBase::StringMatcherBase( StringRef operation, CasedString const& comparator )
8266+    : m_comparator( comparator ),
8267+      m_operation( operation ) {
8268+    }
8269+
8270+    std::string StringMatcherBase::describe() const {
8271+        std::string description;
8272+        description.reserve(5 + m_operation.size() + m_comparator.m_str.size() +
8273+                                    m_comparator.caseSensitivitySuffix().size());
8274+        description += m_operation;
8275+        description += ": \"";
8276+        description += m_comparator.m_str;
8277+        description += '"';
8278+        description += m_comparator.caseSensitivitySuffix();
8279+        return description;
8280+    }
8281+
8282+    StringEqualsMatcher::StringEqualsMatcher( CasedString const& comparator ) : StringMatcherBase( "equals"_sr, comparator ) {}
8283+
8284+    bool StringEqualsMatcher::match( std::string const& source ) const {
8285+        return m_comparator.adjustString( source ) == m_comparator.m_str;
8286+    }
8287+
8288+
8289+    StringContainsMatcher::StringContainsMatcher( CasedString const& comparator ) : StringMatcherBase( "contains"_sr, comparator ) {}
8290+
8291+    bool StringContainsMatcher::match( std::string const& source ) const {
8292+        return contains( m_comparator.adjustString( source ), m_comparator.m_str );
8293+    }
8294+
8295+
8296+    StartsWithMatcher::StartsWithMatcher( CasedString const& comparator ) : StringMatcherBase( "starts with"_sr, comparator ) {}
8297+
8298+    bool StartsWithMatcher::match( std::string const& source ) const {
8299+        return startsWith( m_comparator.adjustString( source ), m_comparator.m_str );
8300+    }
8301+
8302+
8303+    EndsWithMatcher::EndsWithMatcher( CasedString const& comparator ) : StringMatcherBase( "ends with"_sr, comparator ) {}
8304+
8305+    bool EndsWithMatcher::match( std::string const& source ) const {
8306+        return endsWith( m_comparator.adjustString( source ), m_comparator.m_str );
8307+    }
8308+
8309+
8310+
8311+    RegexMatcher::RegexMatcher(std::string regex, CaseSensitive caseSensitivity): m_regex(CATCH_MOVE(regex)), m_caseSensitivity(caseSensitivity) {}
8312+
8313+    bool RegexMatcher::match(std::string const& matchee) const {
8314+        auto flags = std::regex::ECMAScript; // ECMAScript is the default syntax option anyway
8315+        if (m_caseSensitivity == CaseSensitive::No) {
8316+            flags |= std::regex::icase;
8317+        }
8318+        auto reg = std::regex(m_regex, flags);
8319+        return std::regex_match(matchee, reg);
8320+    }
8321+
8322+    std::string RegexMatcher::describe() const {
8323+        return "matches " + ::Catch::Detail::stringify(m_regex) + ((m_caseSensitivity == CaseSensitive::Yes)? " case sensitively" : " case insensitively");
8324+    }
8325+
8326+
8327+    StringEqualsMatcher Equals( std::string const& str, CaseSensitive caseSensitivity ) {
8328+        return StringEqualsMatcher( CasedString( str, caseSensitivity) );
8329+    }
8330+    StringContainsMatcher ContainsSubstring( std::string const& str, CaseSensitive caseSensitivity ) {
8331+        return StringContainsMatcher( CasedString( str, caseSensitivity) );
8332+    }
8333+    EndsWithMatcher EndsWith( std::string const& str, CaseSensitive caseSensitivity ) {
8334+        return EndsWithMatcher( CasedString( str, caseSensitivity) );
8335+    }
8336+    StartsWithMatcher StartsWith( std::string const& str, CaseSensitive caseSensitivity ) {
8337+        return StartsWithMatcher( CasedString( str, caseSensitivity) );
8338+    }
8339+
8340+    RegexMatcher Matches(std::string const& regex, CaseSensitive caseSensitivity) {
8341+        return RegexMatcher(regex, caseSensitivity);
8342+    }
8343+
8344+} // namespace Matchers
8345+} // namespace Catch
8346+
8347+
8348+
8349+namespace Catch {
8350+namespace Matchers {
8351+    MatcherGenericBase::~MatcherGenericBase() = default;
8352+
8353+    namespace Detail {
8354+
8355+        std::string describe_multi_matcher(StringRef combine, std::string const* descriptions_begin, std::string const* descriptions_end) {
8356+            std::string description;
8357+            std::size_t combined_size = 4;
8358+            for ( auto desc = descriptions_begin; desc != descriptions_end; ++desc ) {
8359+                combined_size += desc->size();
8360+            }
8361+            combined_size += static_cast<size_t>(descriptions_end - descriptions_begin - 1) * combine.size();
8362+
8363+            description.reserve(combined_size);
8364+
8365+            description += "( ";
8366+            bool first = true;
8367+            for( auto desc = descriptions_begin; desc != descriptions_end; ++desc ) {
8368+                if( first )
8369+                    first = false;
8370+                else
8371+                    description += combine;
8372+                description += *desc;
8373+            }
8374+            description += " )";
8375+            return description;
8376+        }
8377+
8378+    } // namespace Detail
8379+} // namespace Matchers
8380+} // namespace Catch
8381+
8382+
8383+
8384+
8385+namespace Catch {
8386+
8387+    // This is the general overload that takes a any string matcher
8388+    // There is another overload, in catch_assertionhandler.h/.cpp, that only takes a string and infers
8389+    // the Equals matcher (so the header does not mention matchers)
8390+    void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher ) {
8391+        std::string exceptionMessage = Catch::translateActiveException();
8392+        MatchExpr<std::string, StringMatcher const&> expr( CATCH_MOVE(exceptionMessage), matcher );
8393+        handler.handleExpr( expr );
8394+    }
8395+
8396+} // namespace Catch
8397+
8398+
8399+
8400+#include <ostream>
8401+
8402+namespace Catch {
8403+
8404+    AutomakeReporter::~AutomakeReporter() = default;
8405+
8406+    void AutomakeReporter::testCaseEnded(TestCaseStats const& _testCaseStats) {
8407+        // Possible values to emit are PASS, XFAIL, SKIP, FAIL, XPASS and ERROR.
8408+        m_stream << ":test-result: ";
8409+        if ( _testCaseStats.totals.testCases.skipped > 0 ) {
8410+            m_stream << "SKIP";
8411+        } else if (_testCaseStats.totals.assertions.allPassed()) {
8412+            m_stream << "PASS";
8413+        } else if (_testCaseStats.totals.assertions.allOk()) {
8414+            m_stream << "XFAIL";
8415+        } else {
8416+            m_stream << "FAIL";
8417+        }
8418+        m_stream << ' ' << _testCaseStats.testInfo->name << '\n';
8419+        StreamingReporterBase::testCaseEnded(_testCaseStats);
8420+    }
8421+
8422+    void AutomakeReporter::skipTest(TestCaseInfo const& testInfo) {
8423+        m_stream << ":test-result: SKIP " << testInfo.name << '\n';
8424+    }
8425+
8426+} // end namespace Catch
8427+
8428+
8429+
8430+
8431+
8432+
8433+namespace Catch {
8434+    ReporterBase::ReporterBase( ReporterConfig&& config ):
8435+        IEventListener( config.fullConfig() ),
8436+        m_wrapped_stream( CATCH_MOVE(config).takeStream() ),
8437+        m_stream( m_wrapped_stream->stream() ),
8438+        m_colour( makeColourImpl( config.colourMode(), m_wrapped_stream.get() ) ),
8439+        m_customOptions( config.customOptions() )
8440+    {}
8441+
8442+    ReporterBase::~ReporterBase() = default;
8443+
8444+    void ReporterBase::listReporters(
8445+        std::vector<ReporterDescription> const& descriptions ) {
8446+        defaultListReporters(m_stream, descriptions, m_config->verbosity());
8447+    }
8448+
8449+    void ReporterBase::listListeners(
8450+        std::vector<ListenerDescription> const& descriptions ) {
8451+        defaultListListeners( m_stream, descriptions );
8452+    }
8453+
8454+    void ReporterBase::listTests(std::vector<TestCaseHandle> const& tests) {
8455+        defaultListTests(m_stream,
8456+                         m_colour.get(),
8457+                         tests,
8458+                         m_config->hasTestFilters(),
8459+                         m_config->verbosity());
8460+    }
8461+
8462+    void ReporterBase::listTags(std::vector<TagInfo> const& tags) {
8463+        defaultListTags( m_stream, tags, m_config->hasTestFilters() );
8464+    }
8465+
8466+} // namespace Catch
8467+
8468+
8469+
8470+
8471+#include <ostream>
8472+
8473+namespace Catch {
8474+namespace {
8475+
8476+    // Colour::LightGrey
8477+    static constexpr Colour::Code compactDimColour = Colour::FileName;
8478+
8479+#ifdef CATCH_PLATFORM_MAC
8480+    static constexpr Catch::StringRef compactFailedString = "FAILED"_sr;
8481+    static constexpr Catch::StringRef compactPassedString = "PASSED"_sr;
8482+#else
8483+    static constexpr Catch::StringRef compactFailedString = "failed"_sr;
8484+    static constexpr Catch::StringRef compactPassedString = "passed"_sr;
8485+#endif
8486+
8487+// Implementation of CompactReporter formatting
8488+class AssertionPrinter {
8489+public:
8490+    AssertionPrinter& operator= (AssertionPrinter const&) = delete;
8491+    AssertionPrinter(AssertionPrinter const&) = delete;
8492+    AssertionPrinter(std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages, ColourImpl* colourImpl_)
8493+        : stream(_stream)
8494+        , result(_stats.assertionResult)
8495+        , messages(_stats.infoMessages)
8496+        , itMessage(_stats.infoMessages.begin())
8497+        , printInfoMessages(_printInfoMessages)
8498+        , colourImpl(colourImpl_)
8499+    {}
8500+
8501+    void print() {
8502+        printSourceInfo();
8503+
8504+        itMessage = messages.begin();
8505+
8506+        switch (result.getResultType()) {
8507+        case ResultWas::Ok:
8508+            printResultType(Colour::ResultSuccess, compactPassedString);
8509+            printOriginalExpression();
8510+            printReconstructedExpression();
8511+            if (!result.hasExpression())
8512+                printRemainingMessages(Colour::None);
8513+            else
8514+                printRemainingMessages();
8515+            break;
8516+        case ResultWas::ExpressionFailed:
8517+            if (result.isOk())
8518+                printResultType(Colour::ResultSuccess, compactFailedString + " - but was ok"_sr);
8519+            else
8520+                printResultType(Colour::Error, compactFailedString);
8521+            printOriginalExpression();
8522+            printReconstructedExpression();
8523+            printRemainingMessages();
8524+            break;
8525+        case ResultWas::ThrewException:
8526+            printResultType(Colour::Error, compactFailedString);
8527+            printIssue("unexpected exception with message:");
8528+            printMessage();
8529+            printExpressionWas();
8530+            printRemainingMessages();
8531+            break;
8532+        case ResultWas::FatalErrorCondition:
8533+            printResultType(Colour::Error, compactFailedString);
8534+            printIssue("fatal error condition with message:");
8535+            printMessage();
8536+            printExpressionWas();
8537+            printRemainingMessages();
8538+            break;
8539+        case ResultWas::DidntThrowException:
8540+            printResultType(Colour::Error, compactFailedString);
8541+            printIssue("expected exception, got none");
8542+            printExpressionWas();
8543+            printRemainingMessages();
8544+            break;
8545+        case ResultWas::Info:
8546+            printResultType(Colour::None, "info"_sr);
8547+            printMessage();
8548+            printRemainingMessages();
8549+            break;
8550+        case ResultWas::Warning:
8551+            printResultType(Colour::None, "warning"_sr);
8552+            printMessage();
8553+            printRemainingMessages();
8554+            break;
8555+        case ResultWas::ExplicitFailure:
8556+            printResultType(Colour::Error, compactFailedString);
8557+            printIssue("explicitly");
8558+            printRemainingMessages(Colour::None);
8559+            break;
8560+        case ResultWas::ExplicitSkip:
8561+            printResultType(Colour::Skip, "skipped"_sr);
8562+            printMessage();
8563+            printRemainingMessages();
8564+            break;
8565+            // These cases are here to prevent compiler warnings
8566+        case ResultWas::Unknown:
8567+        case ResultWas::FailureBit:
8568+        case ResultWas::Exception:
8569+            printResultType(Colour::Error, "** internal error **");
8570+            break;
8571+        }
8572+    }
8573+
8574+private:
8575+    void printSourceInfo() const {
8576+        stream << colourImpl->guardColour( Colour::FileName )
8577+               << result.getSourceInfo() << ':';
8578+    }
8579+
8580+    void printResultType(Colour::Code colour, StringRef passOrFail) const {
8581+        if (!passOrFail.empty()) {
8582+            stream << colourImpl->guardColour(colour) << ' ' << passOrFail;
8583+            stream << ':';
8584+        }
8585+    }
8586+
8587+    void printIssue(char const* issue) const {
8588+        stream << ' ' << issue;
8589+    }
8590+
8591+    void printExpressionWas() {
8592+        if (result.hasExpression()) {
8593+            stream << ';';
8594+            {
8595+                stream << colourImpl->guardColour(compactDimColour) << " expression was:";
8596+            }
8597+            printOriginalExpression();
8598+        }
8599+    }
8600+
8601+    void printOriginalExpression() const {
8602+        if (result.hasExpression()) {
8603+            stream << ' ' << result.getExpression();
8604+        }
8605+    }
8606+
8607+    void printReconstructedExpression() const {
8608+        if (result.hasExpandedExpression()) {
8609+            stream << colourImpl->guardColour(compactDimColour) << " for: ";
8610+            stream << result.getExpandedExpression();
8611+        }
8612+    }
8613+
8614+    void printMessage() {
8615+        if (itMessage != messages.end()) {
8616+            stream << " '" << itMessage->message << '\'';
8617+            ++itMessage;
8618+        }
8619+    }
8620+
8621+    void printRemainingMessages(Colour::Code colour = compactDimColour) {
8622+        if (itMessage == messages.end())
8623+            return;
8624+
8625+        const auto itEnd = messages.cend();
8626+        const auto N = static_cast<std::size_t>(itEnd - itMessage);
8627+
8628+        stream << colourImpl->guardColour( colour ) << " with "
8629+               << pluralise( N, "message"_sr ) << ':';
8630+
8631+        while (itMessage != itEnd) {
8632+            // If this assertion is a warning ignore any INFO messages
8633+            if (printInfoMessages || itMessage->type != ResultWas::Info) {
8634+                printMessage();
8635+                if (itMessage != itEnd) {
8636+                    stream << colourImpl->guardColour(compactDimColour) << " and";
8637+                }
8638+                continue;
8639+            }
8640+            ++itMessage;
8641+        }
8642+    }
8643+
8644+private:
8645+    std::ostream& stream;
8646+    AssertionResult const& result;
8647+    std::vector<MessageInfo> const& messages;
8648+    std::vector<MessageInfo>::const_iterator itMessage;
8649+    bool printInfoMessages;
8650+    ColourImpl* colourImpl;
8651+};
8652+
8653+} // anon namespace
8654+
8655+        std::string CompactReporter::getDescription() {
8656+            return "Reports test results on a single line, suitable for IDEs";
8657+        }
8658+
8659+        void CompactReporter::noMatchingTestCases( StringRef unmatchedSpec ) {
8660+            m_stream << "No test cases matched '" << unmatchedSpec << "'\n";
8661+        }
8662+
8663+        void CompactReporter::testRunStarting( TestRunInfo const& ) {
8664+            if ( m_config->testSpec().hasFilters() ) {
8665+                m_stream << m_colour->guardColour( Colour::BrightYellow )
8666+                         << "Filters: "
8667+                         << m_config->testSpec()
8668+                         << '\n';
8669+            }
8670+            m_stream << "RNG seed: " << getSeed() << '\n';
8671+        }
8672+
8673+        void CompactReporter::assertionEnded( AssertionStats const& _assertionStats ) {
8674+            AssertionResult const& result = _assertionStats.assertionResult;
8675+
8676+            bool printInfoMessages = true;
8677+
8678+            // Drop out if result was successful and we're not printing those
8679+            if( !m_config->includeSuccessfulResults() && result.isOk() ) {
8680+                if( result.getResultType() != ResultWas::Warning && result.getResultType() != ResultWas::ExplicitSkip )
8681+                    return;
8682+                printInfoMessages = false;
8683+            }
8684+
8685+            AssertionPrinter printer( m_stream, _assertionStats, printInfoMessages, m_colour.get() );
8686+            printer.print();
8687+
8688+            m_stream << '\n' << std::flush;
8689+        }
8690+
8691+        void CompactReporter::sectionEnded(SectionStats const& _sectionStats) {
8692+            double dur = _sectionStats.durationInSeconds;
8693+            if ( shouldShowDuration( *m_config, dur ) ) {
8694+                m_stream << getFormattedDuration( dur ) << " s: " << _sectionStats.sectionInfo.name << '\n' << std::flush;
8695+            }
8696+        }
8697+
8698+        void CompactReporter::testRunEnded( TestRunStats const& _testRunStats ) {
8699+            printTestRunTotals( m_stream, *m_colour, _testRunStats.totals );
8700+            m_stream << "\n\n" << std::flush;
8701+            StreamingReporterBase::testRunEnded( _testRunStats );
8702+        }
8703+
8704+        CompactReporter::~CompactReporter() = default;
8705+
8706+} // end namespace Catch
8707+
8708+
8709+
8710+
8711+#include <cstdio>
8712+
8713+#if defined(_MSC_VER)
8714+#pragma warning(push)
8715+#pragma warning(disable:4061) // Not all labels are EXPLICITLY handled in switch
8716+ // Note that 4062 (not all labels are handled and default is missing) is enabled
8717+#endif
8718+
8719+#if defined(__clang__)
8720+#  pragma clang diagnostic push
8721+// For simplicity, benchmarking-only helpers are always enabled
8722+#  pragma clang diagnostic ignored "-Wunused-function"
8723+#endif
8724+
8725+
8726+
8727+namespace Catch {
8728+
8729+namespace {
8730+
8731+// Formatter impl for ConsoleReporter
8732+class ConsoleAssertionPrinter {
8733+public:
8734+    ConsoleAssertionPrinter& operator= (ConsoleAssertionPrinter const&) = delete;
8735+    ConsoleAssertionPrinter(ConsoleAssertionPrinter const&) = delete;
8736+    ConsoleAssertionPrinter(std::ostream& _stream, AssertionStats const& _stats, ColourImpl* colourImpl_, bool _printInfoMessages)
8737+        : stream(_stream),
8738+        stats(_stats),
8739+        result(_stats.assertionResult),
8740+        colour(Colour::None),
8741+        messages(_stats.infoMessages),
8742+        colourImpl(colourImpl_),
8743+        printInfoMessages(_printInfoMessages) {
8744+        switch (result.getResultType()) {
8745+        case ResultWas::Ok:
8746+            colour = Colour::Success;
8747+            passOrFail = "PASSED"_sr;
8748+            //if( result.hasMessage() )
8749+            if (messages.size() == 1)
8750+                messageLabel = "with message"_sr;
8751+            if (messages.size() > 1)
8752+                messageLabel = "with messages"_sr;
8753+            break;
8754+        case ResultWas::ExpressionFailed:
8755+            if (result.isOk()) {
8756+                colour = Colour::Success;
8757+                passOrFail = "FAILED - but was ok"_sr;
8758+            } else {
8759+                colour = Colour::Error;
8760+                passOrFail = "FAILED"_sr;
8761+            }
8762+            if (messages.size() == 1)
8763+                messageLabel = "with message"_sr;
8764+            if (messages.size() > 1)
8765+                messageLabel = "with messages"_sr;
8766+            break;
8767+        case ResultWas::ThrewException:
8768+            colour = Colour::Error;
8769+            passOrFail = "FAILED"_sr;
8770+            // todo switch
8771+            switch (messages.size()) { case 0:
8772+                messageLabel = "due to unexpected exception with "_sr;
8773+                break;
8774+            case 1:
8775+                messageLabel = "due to unexpected exception with message"_sr;
8776+                break;
8777+            default:
8778+                messageLabel = "due to unexpected exception with messages"_sr;
8779+                break;
8780+            }
8781+            break;
8782+        case ResultWas::FatalErrorCondition:
8783+            colour = Colour::Error;
8784+            passOrFail = "FAILED"_sr;
8785+            messageLabel = "due to a fatal error condition"_sr;
8786+            break;
8787+        case ResultWas::DidntThrowException:
8788+            colour = Colour::Error;
8789+            passOrFail = "FAILED"_sr;
8790+            messageLabel = "because no exception was thrown where one was expected"_sr;
8791+            break;
8792+        case ResultWas::Info:
8793+            messageLabel = "info"_sr;
8794+            break;
8795+        case ResultWas::Warning:
8796+            messageLabel = "warning"_sr;
8797+            break;
8798+        case ResultWas::ExplicitFailure:
8799+            passOrFail = "FAILED"_sr;
8800+            colour = Colour::Error;
8801+            if (messages.size() == 1)
8802+                messageLabel = "explicitly with message"_sr;
8803+            if (messages.size() > 1)
8804+                messageLabel = "explicitly with messages"_sr;
8805+            break;
8806+        case ResultWas::ExplicitSkip:
8807+            colour = Colour::Skip;
8808+            passOrFail = "SKIPPED"_sr;
8809+            if (messages.size() == 1)
8810+                messageLabel = "explicitly with message"_sr;
8811+            if (messages.size() > 1)
8812+                messageLabel = "explicitly with messages"_sr;
8813+            break;
8814+            // These cases are here to prevent compiler warnings
8815+        case ResultWas::Unknown:
8816+        case ResultWas::FailureBit:
8817+        case ResultWas::Exception:
8818+            passOrFail = "** internal error **"_sr;
8819+            colour = Colour::Error;
8820+            break;
8821+        }
8822+    }
8823+
8824+    void print() const {
8825+        printSourceInfo();
8826+        if (stats.totals.assertions.total() > 0) {
8827+            printResultType();
8828+            printOriginalExpression();
8829+            printReconstructedExpression();
8830+        } else {
8831+            stream << '\n';
8832+        }
8833+        printMessage();
8834+    }
8835+
8836+private:
8837+    void printResultType() const {
8838+        if (!passOrFail.empty()) {
8839+            stream << colourImpl->guardColour(colour) << passOrFail << ":\n";
8840+        }
8841+    }
8842+    void printOriginalExpression() const {
8843+        if (result.hasExpression()) {
8844+            stream << colourImpl->guardColour( Colour::OriginalExpression )
8845+                   << "  " << result.getExpressionInMacro() << '\n';
8846+        }
8847+    }
8848+    void printReconstructedExpression() const {
8849+        if (result.hasExpandedExpression()) {
8850+            stream << "with expansion:\n";
8851+            stream << colourImpl->guardColour( Colour::ReconstructedExpression )
8852+                   << TextFlow::Column( result.getExpandedExpression() )
8853+                          .indent( 2 )
8854+                   << '\n';
8855+        }
8856+    }
8857+    void printMessage() const {
8858+        if (!messageLabel.empty())
8859+            stream << messageLabel << ':' << '\n';
8860+        for (auto const& msg : messages) {
8861+            // If this assertion is a warning ignore any INFO messages
8862+            if (printInfoMessages || msg.type != ResultWas::Info)
8863+                stream << TextFlow::Column(msg.message).indent(2) << '\n';
8864+        }
8865+    }
8866+    void printSourceInfo() const {
8867+        stream << colourImpl->guardColour( Colour::FileName )
8868+               << result.getSourceInfo() << ": ";
8869+    }
8870+
8871+    std::ostream& stream;
8872+    AssertionStats const& stats;
8873+    AssertionResult const& result;
8874+    Colour::Code colour;
8875+    StringRef passOrFail;
8876+    StringRef messageLabel;
8877+    std::vector<MessageInfo> const& messages;
8878+    ColourImpl* colourImpl;
8879+    bool printInfoMessages;
8880+};
8881+
8882+std::size_t makeRatio( std::uint64_t number, std::uint64_t total ) {
8883+    const auto ratio = total > 0 ? CATCH_CONFIG_CONSOLE_WIDTH * number / total : 0;
8884+    return (ratio == 0 && number > 0) ? 1 : static_cast<std::size_t>(ratio);
8885+}
8886+
8887+std::size_t&
8888+findMax( std::size_t& i, std::size_t& j, std::size_t& k, std::size_t& l ) {
8889+    if (i > j && i > k && i > l)
8890+        return i;
8891+    else if (j > k && j > l)
8892+        return j;
8893+    else if (k > l)
8894+        return k;
8895+    else
8896+        return l;
8897+}
8898+
8899+struct ColumnBreak {};
8900+struct RowBreak {};
8901+struct OutputFlush {};
8902+
8903+class Duration {
8904+    enum class Unit {
8905+        Auto,
8906+        Nanoseconds,
8907+        Microseconds,
8908+        Milliseconds,
8909+        Seconds,
8910+        Minutes
8911+    };
8912+    static const uint64_t s_nanosecondsInAMicrosecond = 1000;
8913+    static const uint64_t s_nanosecondsInAMillisecond = 1000 * s_nanosecondsInAMicrosecond;
8914+    static const uint64_t s_nanosecondsInASecond = 1000 * s_nanosecondsInAMillisecond;
8915+    static const uint64_t s_nanosecondsInAMinute = 60 * s_nanosecondsInASecond;
8916+
8917+    double m_inNanoseconds;
8918+    Unit m_units;
8919+
8920+public:
8921+    explicit Duration(double inNanoseconds, Unit units = Unit::Auto)
8922+        : m_inNanoseconds(inNanoseconds),
8923+        m_units(units) {
8924+        if (m_units == Unit::Auto) {
8925+            if (m_inNanoseconds < s_nanosecondsInAMicrosecond)
8926+                m_units = Unit::Nanoseconds;
8927+            else if (m_inNanoseconds < s_nanosecondsInAMillisecond)
8928+                m_units = Unit::Microseconds;
8929+            else if (m_inNanoseconds < s_nanosecondsInASecond)
8930+                m_units = Unit::Milliseconds;
8931+            else if (m_inNanoseconds < s_nanosecondsInAMinute)
8932+                m_units = Unit::Seconds;
8933+            else
8934+                m_units = Unit::Minutes;
8935+        }
8936+
8937+    }
8938+
8939+    auto value() const -> double {
8940+        switch (m_units) {
8941+        case Unit::Microseconds:
8942+            return m_inNanoseconds / static_cast<double>(s_nanosecondsInAMicrosecond);
8943+        case Unit::Milliseconds:
8944+            return m_inNanoseconds / static_cast<double>(s_nanosecondsInAMillisecond);
8945+        case Unit::Seconds:
8946+            return m_inNanoseconds / static_cast<double>(s_nanosecondsInASecond);
8947+        case Unit::Minutes:
8948+            return m_inNanoseconds / static_cast<double>(s_nanosecondsInAMinute);
8949+        default:
8950+            return m_inNanoseconds;
8951+        }
8952+    }
8953+    StringRef unitsAsString() const {
8954+        switch (m_units) {
8955+        case Unit::Nanoseconds:
8956+            return "ns"_sr;
8957+        case Unit::Microseconds:
8958+            return "us"_sr;
8959+        case Unit::Milliseconds:
8960+            return "ms"_sr;
8961+        case Unit::Seconds:
8962+            return "s"_sr;
8963+        case Unit::Minutes:
8964+            return "m"_sr;
8965+        default:
8966+            return "** internal error **"_sr;
8967+        }
8968+
8969+    }
8970+    friend auto operator << (std::ostream& os, Duration const& duration) -> std::ostream& {
8971+        return os << duration.value() << ' ' << duration.unitsAsString();
8972+    }
8973+};
8974+} // end anon namespace
8975+
8976+enum class Justification { Left, Right };
8977+
8978+struct ColumnInfo {
8979+    std::string name;
8980+    std::size_t width;
8981+    Justification justification;
8982+};
8983+
8984+class TablePrinter {
8985+    std::ostream& m_os;
8986+    std::vector<ColumnInfo> m_columnInfos;
8987+    ReusableStringStream m_oss;
8988+    int m_currentColumn = -1;
8989+    bool m_isOpen = false;
8990+
8991+public:
8992+    TablePrinter( std::ostream& os, std::vector<ColumnInfo> columnInfos )
8993+    :   m_os( os ),
8994+        m_columnInfos( CATCH_MOVE( columnInfos ) ) {}
8995+
8996+    auto columnInfos() const -> std::vector<ColumnInfo> const& {
8997+        return m_columnInfos;
8998+    }
8999+
9000+    void open() {
9001+        if (!m_isOpen) {
9002+            m_isOpen = true;
9003+            *this << RowBreak();
9004+
9005+			TextFlow::Columns headerCols;
9006+			for (auto const& info : m_columnInfos) {
9007+                assert(info.width > 2);
9008+				headerCols += TextFlow::Column(info.name).width(info.width - 2);
9009+                headerCols += TextFlow::Spacer( 2 );
9010+			}
9011+			m_os << headerCols << '\n';
9012+
9013+            m_os << lineOfChars('-') << '\n';
9014+        }
9015+    }
9016+    void close() {
9017+        if (m_isOpen) {
9018+            *this << RowBreak();
9019+            m_os << '\n' << std::flush;
9020+            m_isOpen = false;
9021+        }
9022+    }
9023+
9024+    template<typename T>
9025+    friend TablePrinter& operator<< (TablePrinter& tp, T const& value) {
9026+        tp.m_oss << value;
9027+        return tp;
9028+    }
9029+
9030+    friend TablePrinter& operator<< (TablePrinter& tp, ColumnBreak) {
9031+        auto colStr = tp.m_oss.str();
9032+        const auto strSize = colStr.size();
9033+        tp.m_oss.str("");
9034+        tp.open();
9035+        if (tp.m_currentColumn == static_cast<int>(tp.m_columnInfos.size() - 1)) {
9036+            tp.m_currentColumn = -1;
9037+            tp.m_os << '\n';
9038+        }
9039+        tp.m_currentColumn++;
9040+
9041+        auto colInfo = tp.m_columnInfos[tp.m_currentColumn];
9042+        auto padding = (strSize + 1 < colInfo.width)
9043+            ? std::string(colInfo.width - (strSize + 1), ' ')
9044+            : std::string();
9045+        if (colInfo.justification == Justification::Left)
9046+            tp.m_os << colStr << padding << ' ';
9047+        else
9048+            tp.m_os << padding << colStr << ' ';
9049+        return tp;
9050+    }
9051+
9052+    friend TablePrinter& operator<< (TablePrinter& tp, RowBreak) {
9053+        if (tp.m_currentColumn > 0) {
9054+            tp.m_os << '\n';
9055+            tp.m_currentColumn = -1;
9056+        }
9057+        return tp;
9058+    }
9059+
9060+    friend TablePrinter& operator<<(TablePrinter& tp, OutputFlush) {
9061+        tp.m_os << std::flush;
9062+        return tp;
9063+    }
9064+};
9065+
9066+ConsoleReporter::ConsoleReporter(ReporterConfig&& config):
9067+    StreamingReporterBase( CATCH_MOVE( config ) ),
9068+    m_tablePrinter(Detail::make_unique<TablePrinter>(m_stream,
9069+        [&config]() -> std::vector<ColumnInfo> {
9070+        if (config.fullConfig()->benchmarkNoAnalysis())
9071+        {
9072+            return{
9073+                { "benchmark name", CATCH_CONFIG_CONSOLE_WIDTH - 43, Justification::Left },
9074+                { "     samples", 14, Justification::Right },
9075+                { "  iterations", 14, Justification::Right },
9076+                { "        mean", 14, Justification::Right }
9077+            };
9078+        }
9079+        else
9080+        {
9081+            return{
9082+                { "benchmark name", CATCH_CONFIG_CONSOLE_WIDTH - 43, Justification::Left },
9083+                { "samples      mean       std dev", 14, Justification::Right },
9084+                { "iterations   low mean   low std dev", 14, Justification::Right },
9085+                { "est run time high mean  high std dev", 14, Justification::Right }
9086+            };
9087+        }
9088+    }())) {}
9089+ConsoleReporter::~ConsoleReporter() = default;
9090+
9091+std::string ConsoleReporter::getDescription() {
9092+    return "Reports test results as plain lines of text";
9093+}
9094+
9095+void ConsoleReporter::noMatchingTestCases( StringRef unmatchedSpec ) {
9096+    m_stream << "No test cases matched '" << unmatchedSpec << "'\n";
9097+}
9098+
9099+void ConsoleReporter::reportInvalidTestSpec( StringRef arg ) {
9100+    m_stream << "Invalid Filter: " << arg << '\n';
9101+}
9102+
9103+void ConsoleReporter::assertionStarting(AssertionInfo const&) {}
9104+
9105+void ConsoleReporter::assertionEnded(AssertionStats const& _assertionStats) {
9106+    AssertionResult const& result = _assertionStats.assertionResult;
9107+
9108+    bool includeResults = m_config->includeSuccessfulResults() || !result.isOk();
9109+
9110+    // Drop out if result was successful but we're not printing them.
9111+    // TODO: Make configurable whether skips should be printed
9112+    if (!includeResults && result.getResultType() != ResultWas::Warning && result.getResultType() != ResultWas::ExplicitSkip)
9113+        return;
9114+
9115+    lazyPrint();
9116+
9117+    ConsoleAssertionPrinter printer(m_stream, _assertionStats, m_colour.get(), includeResults);
9118+    printer.print();
9119+    m_stream << '\n' << std::flush;
9120+}
9121+
9122+void ConsoleReporter::sectionStarting(SectionInfo const& _sectionInfo) {
9123+    m_tablePrinter->close();
9124+    m_headerPrinted = false;
9125+    StreamingReporterBase::sectionStarting(_sectionInfo);
9126+}
9127+void ConsoleReporter::sectionEnded(SectionStats const& _sectionStats) {
9128+    m_tablePrinter->close();
9129+    if (_sectionStats.missingAssertions) {
9130+        lazyPrint();
9131+        auto guard =
9132+            m_colour->guardColour( Colour::ResultError ).engage( m_stream );
9133+        if (m_sectionStack.size() > 1)
9134+            m_stream << "\nNo assertions in section";
9135+        else
9136+            m_stream << "\nNo assertions in test case";
9137+        m_stream << " '" << _sectionStats.sectionInfo.name << "'\n\n" << std::flush;
9138+    }
9139+    double dur = _sectionStats.durationInSeconds;
9140+    if (shouldShowDuration(*m_config, dur)) {
9141+        m_stream << getFormattedDuration(dur) << " s: " << _sectionStats.sectionInfo.name << '\n' << std::flush;
9142+    }
9143+    if (m_headerPrinted) {
9144+        m_headerPrinted = false;
9145+    }
9146+    StreamingReporterBase::sectionEnded(_sectionStats);
9147+}
9148+
9149+void ConsoleReporter::benchmarkPreparing( StringRef name ) {
9150+	lazyPrintWithoutClosingBenchmarkTable();
9151+
9152+	auto nameCol = TextFlow::Column( static_cast<std::string>( name ) )
9153+                       .width( m_tablePrinter->columnInfos()[0].width - 2 );
9154+
9155+	bool firstLine = true;
9156+	for (auto line : nameCol) {
9157+		if (!firstLine)
9158+			(*m_tablePrinter) << ColumnBreak() << ColumnBreak() << ColumnBreak();
9159+		else
9160+			firstLine = false;
9161+
9162+		(*m_tablePrinter) << line << ColumnBreak();
9163+	}
9164+}
9165+
9166+void ConsoleReporter::benchmarkStarting(BenchmarkInfo const& info) {
9167+    (*m_tablePrinter) << info.samples << ColumnBreak()
9168+        << info.iterations << ColumnBreak();
9169+    if ( !m_config->benchmarkNoAnalysis() ) {
9170+        ( *m_tablePrinter )
9171+            << Duration( info.estimatedDuration ) << ColumnBreak();
9172+    }
9173+    ( *m_tablePrinter ) << OutputFlush{};
9174+}
9175+void ConsoleReporter::benchmarkEnded(BenchmarkStats<> const& stats) {
9176+    if (m_config->benchmarkNoAnalysis())
9177+    {
9178+        (*m_tablePrinter) << Duration(stats.mean.point.count()) << ColumnBreak();
9179+    }
9180+    else
9181+    {
9182+        (*m_tablePrinter) << ColumnBreak()
9183+            << Duration(stats.mean.point.count()) << ColumnBreak()
9184+            << Duration(stats.mean.lower_bound.count()) << ColumnBreak()
9185+            << Duration(stats.mean.upper_bound.count()) << ColumnBreak() << ColumnBreak()
9186+            << Duration(stats.standardDeviation.point.count()) << ColumnBreak()
9187+            << Duration(stats.standardDeviation.lower_bound.count()) << ColumnBreak()
9188+            << Duration(stats.standardDeviation.upper_bound.count()) << ColumnBreak() << ColumnBreak() << ColumnBreak() << ColumnBreak() << ColumnBreak();
9189+    }
9190+}
9191+
9192+void ConsoleReporter::benchmarkFailed( StringRef error ) {
9193+    auto guard = m_colour->guardColour( Colour::Red ).engage( m_stream );
9194+    (*m_tablePrinter)
9195+        << "Benchmark failed (" << error << ')'
9196+        << ColumnBreak() << RowBreak();
9197+}
9198+
9199+void ConsoleReporter::testCaseEnded(TestCaseStats const& _testCaseStats) {
9200+    m_tablePrinter->close();
9201+    StreamingReporterBase::testCaseEnded(_testCaseStats);
9202+    m_headerPrinted = false;
9203+}
9204+void ConsoleReporter::testRunEnded(TestRunStats const& _testRunStats) {
9205+    printTotalsDivider(_testRunStats.totals);
9206+    printTestRunTotals( m_stream, *m_colour, _testRunStats.totals );
9207+    m_stream << '\n' << std::flush;
9208+    StreamingReporterBase::testRunEnded(_testRunStats);
9209+}
9210+void ConsoleReporter::testRunStarting(TestRunInfo const& _testRunInfo) {
9211+    StreamingReporterBase::testRunStarting(_testRunInfo);
9212+    if ( m_config->testSpec().hasFilters() ) {
9213+        m_stream << m_colour->guardColour( Colour::BrightYellow ) << "Filters: "
9214+                 << m_config->testSpec() << '\n';
9215+    }
9216+    m_stream << "Randomness seeded to: " << getSeed() << '\n';
9217+}
9218+
9219+void ConsoleReporter::lazyPrint() {
9220+
9221+    m_tablePrinter->close();
9222+    lazyPrintWithoutClosingBenchmarkTable();
9223+}
9224+
9225+void ConsoleReporter::lazyPrintWithoutClosingBenchmarkTable() {
9226+
9227+    if ( !m_testRunInfoPrinted ) {
9228+        lazyPrintRunInfo();
9229+    }
9230+    if (!m_headerPrinted) {
9231+        printTestCaseAndSectionHeader();
9232+        m_headerPrinted = true;
9233+    }
9234+}
9235+void ConsoleReporter::lazyPrintRunInfo() {
9236+    m_stream << '\n'
9237+             << lineOfChars( '~' ) << '\n'
9238+             << m_colour->guardColour( Colour::SecondaryText )
9239+             << currentTestRunInfo.name << " is a Catch2 v" << libraryVersion()
9240+             << " host application.\n"
9241+             << "Run with -? for options\n\n";
9242+
9243+    m_testRunInfoPrinted = true;
9244+}
9245+void ConsoleReporter::printTestCaseAndSectionHeader() {
9246+    assert(!m_sectionStack.empty());
9247+    printOpenHeader(currentTestCaseInfo->name);
9248+
9249+    if (m_sectionStack.size() > 1) {
9250+        auto guard = m_colour->guardColour( Colour::Headers ).engage( m_stream );
9251+
9252+        auto
9253+            it = m_sectionStack.begin() + 1, // Skip first section (test case)
9254+            itEnd = m_sectionStack.end();
9255+        for (; it != itEnd; ++it)
9256+            printHeaderString(it->name, 2);
9257+    }
9258+
9259+    SourceLineInfo lineInfo = m_sectionStack.back().lineInfo;
9260+
9261+
9262+    m_stream << lineOfChars( '-' ) << '\n'
9263+             << m_colour->guardColour( Colour::FileName ) << lineInfo << '\n'
9264+             << lineOfChars( '.' ) << "\n\n"
9265+             << std::flush;
9266+}
9267+
9268+void ConsoleReporter::printClosedHeader(std::string const& _name) {
9269+    printOpenHeader(_name);
9270+    m_stream << lineOfChars('.') << '\n';
9271+}
9272+void ConsoleReporter::printOpenHeader(std::string const& _name) {
9273+    m_stream << lineOfChars('-') << '\n';
9274+    {
9275+        auto guard = m_colour->guardColour( Colour::Headers ).engage( m_stream );
9276+        printHeaderString(_name);
9277+    }
9278+}
9279+
9280+void ConsoleReporter::printHeaderString(std::string const& _string, std::size_t indent) {
9281+    // We want to get a bit fancy with line breaking here, so that subsequent
9282+    // lines start after ":" if one is present, e.g.
9283+    // ```
9284+    // blablabla: Fancy
9285+    //            linebreaking
9286+    // ```
9287+    // but we also want to avoid problems with overly long indentation causing
9288+    // the text to take up too many lines, e.g.
9289+    // ```
9290+    // blablabla: F
9291+    //            a
9292+    //            n
9293+    //            c
9294+    //            y
9295+    //            .
9296+    //            .
9297+    //            .
9298+    // ```
9299+    // So we limit the prefix indentation check to first quarter of the possible
9300+    // width
9301+    std::size_t idx = _string.find( ": " );
9302+    if ( idx != std::string::npos && idx < CATCH_CONFIG_CONSOLE_WIDTH / 4 ) {
9303+        idx += 2;
9304+    } else {
9305+        idx = 0;
9306+    }
9307+    m_stream << TextFlow::Column( _string )
9308+                  .indent( indent + idx )
9309+                  .initialIndent( indent )
9310+           << '\n';
9311+}
9312+
9313+void ConsoleReporter::printTotalsDivider(Totals const& totals) {
9314+    if (totals.testCases.total() > 0) {
9315+        std::size_t failedRatio = makeRatio(totals.testCases.failed, totals.testCases.total());
9316+        std::size_t failedButOkRatio = makeRatio(totals.testCases.failedButOk, totals.testCases.total());
9317+        std::size_t passedRatio = makeRatio(totals.testCases.passed, totals.testCases.total());
9318+        std::size_t skippedRatio = makeRatio(totals.testCases.skipped, totals.testCases.total());
9319+        while (failedRatio + failedButOkRatio + passedRatio + skippedRatio < CATCH_CONFIG_CONSOLE_WIDTH - 1)
9320+            findMax(failedRatio, failedButOkRatio, passedRatio, skippedRatio)++;
9321+        while (failedRatio + failedButOkRatio + passedRatio > CATCH_CONFIG_CONSOLE_WIDTH - 1)
9322+            findMax(failedRatio, failedButOkRatio, passedRatio, skippedRatio)--;
9323+
9324+        m_stream << m_colour->guardColour( Colour::Error )
9325+                 << std::string( failedRatio, '=' )
9326+                 << m_colour->guardColour( Colour::ResultExpectedFailure )
9327+                 << std::string( failedButOkRatio, '=' );
9328+        if ( totals.testCases.allPassed() ) {
9329+            m_stream << m_colour->guardColour( Colour::ResultSuccess )
9330+                     << std::string( passedRatio, '=' );
9331+        } else {
9332+            m_stream << m_colour->guardColour( Colour::Success )
9333+                     << std::string( passedRatio, '=' );
9334+        }
9335+        m_stream << m_colour->guardColour( Colour::Skip )
9336+                 << std::string( skippedRatio, '=' );
9337+    } else {
9338+        m_stream << m_colour->guardColour( Colour::Warning )
9339+                 << std::string( CATCH_CONFIG_CONSOLE_WIDTH - 1, '=' );
9340+    }
9341+    m_stream << '\n';
9342+}
9343+
9344+} // end namespace Catch
9345+
9346+#if defined(_MSC_VER)
9347+#pragma warning(pop)
9348+#endif
9349+
9350+#if defined(__clang__)
9351+#  pragma clang diagnostic pop
9352+#endif
9353+
9354+
9355+
9356+
9357+#include <algorithm>
9358+#include <cassert>
9359+
9360+namespace Catch {
9361+    namespace {
9362+        struct BySectionInfo {
9363+            BySectionInfo( SectionInfo const& other ): m_other( other ) {}
9364+            BySectionInfo( BySectionInfo const& other ) = default;
9365+            bool operator()(
9366+                Detail::unique_ptr<CumulativeReporterBase::SectionNode> const&
9367+                    node ) const {
9368+                return (
9369+                    ( node->stats.sectionInfo.name == m_other.name ) &&
9370+                    ( node->stats.sectionInfo.lineInfo == m_other.lineInfo ) );
9371+            }
9372+            void operator=( BySectionInfo const& ) = delete;
9373+
9374+        private:
9375+            SectionInfo const& m_other;
9376+        };
9377+
9378+    } // namespace
9379+
9380+    namespace Detail {
9381+        AssertionOrBenchmarkResult::AssertionOrBenchmarkResult(
9382+            AssertionStats const& assertion ):
9383+            m_assertion( assertion ) {}
9384+
9385+        AssertionOrBenchmarkResult::AssertionOrBenchmarkResult(
9386+            BenchmarkStats<> const& benchmark ):
9387+            m_benchmark( benchmark ) {}
9388+
9389+        bool AssertionOrBenchmarkResult::isAssertion() const {
9390+            return m_assertion.some();
9391+        }
9392+        bool AssertionOrBenchmarkResult::isBenchmark() const {
9393+            return m_benchmark.some();
9394+        }
9395+
9396+        AssertionStats const& AssertionOrBenchmarkResult::asAssertion() const {
9397+            assert(m_assertion.some());
9398+
9399+            return *m_assertion;
9400+        }
9401+        BenchmarkStats<> const& AssertionOrBenchmarkResult::asBenchmark() const {
9402+            assert(m_benchmark.some());
9403+
9404+            return *m_benchmark;
9405+        }
9406+
9407+    }
9408+
9409+    CumulativeReporterBase::~CumulativeReporterBase() = default;
9410+
9411+    void CumulativeReporterBase::benchmarkEnded(BenchmarkStats<> const& benchmarkStats) {
9412+        m_sectionStack.back()->assertionsAndBenchmarks.emplace_back(benchmarkStats);
9413+    }
9414+
9415+    void
9416+    CumulativeReporterBase::sectionStarting( SectionInfo const& sectionInfo ) {
9417+        // We need a copy, because SectionStats expect to take ownership
9418+        SectionStats incompleteStats( SectionInfo(sectionInfo), Counts(), 0, false );
9419+        SectionNode* node;
9420+        if ( m_sectionStack.empty() ) {
9421+            if ( !m_rootSection ) {
9422+                m_rootSection =
9423+                    Detail::make_unique<SectionNode>( incompleteStats );
9424+            }
9425+            node = m_rootSection.get();
9426+        } else {
9427+            SectionNode& parentNode = *m_sectionStack.back();
9428+            auto it = std::find_if( parentNode.childSections.begin(),
9429+                                    parentNode.childSections.end(),
9430+                                    BySectionInfo( sectionInfo ) );
9431+            if ( it == parentNode.childSections.end() ) {
9432+                auto newNode =
9433+                    Detail::make_unique<SectionNode>( incompleteStats );
9434+                node = newNode.get();
9435+                parentNode.childSections.push_back( CATCH_MOVE( newNode ) );
9436+            } else {
9437+                node = it->get();
9438+            }
9439+        }
9440+
9441+        m_deepestSection = node;
9442+        m_sectionStack.push_back( node );
9443+    }
9444+
9445+    void CumulativeReporterBase::assertionEnded(
9446+        AssertionStats const& assertionStats ) {
9447+        assert( !m_sectionStack.empty() );
9448+        // AssertionResult holds a pointer to a temporary DecomposedExpression,
9449+        // which getExpandedExpression() calls to build the expression string.
9450+        // Our section stack copy of the assertionResult will likely outlive the
9451+        // temporary, so it must be expanded or discarded now to avoid calling
9452+        // a destroyed object later.
9453+        if ( m_shouldStoreFailedAssertions &&
9454+             !assertionStats.assertionResult.isOk() ) {
9455+            static_cast<void>(
9456+                assertionStats.assertionResult.getExpandedExpression() );
9457+        }
9458+        if ( m_shouldStoreSuccesfulAssertions &&
9459+             assertionStats.assertionResult.isOk() ) {
9460+            static_cast<void>(
9461+                assertionStats.assertionResult.getExpandedExpression() );
9462+        }
9463+        SectionNode& sectionNode = *m_sectionStack.back();
9464+        sectionNode.assertionsAndBenchmarks.emplace_back( assertionStats );
9465+    }
9466+
9467+    void CumulativeReporterBase::sectionEnded( SectionStats const& sectionStats ) {
9468+        assert( !m_sectionStack.empty() );
9469+        SectionNode& node = *m_sectionStack.back();
9470+        node.stats = sectionStats;
9471+        m_sectionStack.pop_back();
9472+    }
9473+
9474+    void CumulativeReporterBase::testCaseEnded(
9475+        TestCaseStats const& testCaseStats ) {
9476+        auto node = Detail::make_unique<TestCaseNode>( testCaseStats );
9477+        assert( m_sectionStack.size() == 0 );
9478+        node->children.push_back( CATCH_MOVE(m_rootSection) );
9479+        m_testCases.push_back( CATCH_MOVE(node) );
9480+
9481+        assert( m_deepestSection );
9482+        m_deepestSection->stdOut = testCaseStats.stdOut;
9483+        m_deepestSection->stdErr = testCaseStats.stdErr;
9484+    }
9485+
9486+
9487+    void CumulativeReporterBase::testRunEnded( TestRunStats const& testRunStats ) {
9488+        assert(!m_testRun && "CumulativeReporterBase assumes there can only be one test run");
9489+        m_testRun = Detail::make_unique<TestRunNode>( testRunStats );
9490+        m_testRun->children.swap( m_testCases );
9491+        testRunEndedCumulative();
9492+    }
9493+
9494+    bool CumulativeReporterBase::SectionNode::hasAnyAssertions() const {
9495+        return std::any_of(
9496+            assertionsAndBenchmarks.begin(),
9497+            assertionsAndBenchmarks.end(),
9498+            []( Detail::AssertionOrBenchmarkResult const& res ) {
9499+                return res.isAssertion();
9500+            } );
9501+    }
9502+
9503+} // end namespace Catch
9504+
9505+
9506+
9507+
9508+namespace Catch {
9509+
9510+    void EventListenerBase::fatalErrorEncountered( StringRef ) {}
9511+
9512+    void EventListenerBase::benchmarkPreparing( StringRef ) {}
9513+    void EventListenerBase::benchmarkStarting( BenchmarkInfo const& ) {}
9514+    void EventListenerBase::benchmarkEnded( BenchmarkStats<> const& ) {}
9515+    void EventListenerBase::benchmarkFailed( StringRef ) {}
9516+
9517+    void EventListenerBase::assertionStarting( AssertionInfo const& ) {}
9518+
9519+    void EventListenerBase::assertionEnded( AssertionStats const& ) {}
9520+    void EventListenerBase::listReporters(
9521+        std::vector<ReporterDescription> const& ) {}
9522+    void EventListenerBase::listListeners(
9523+        std::vector<ListenerDescription> const& ) {}
9524+    void EventListenerBase::listTests( std::vector<TestCaseHandle> const& ) {}
9525+    void EventListenerBase::listTags( std::vector<TagInfo> const& ) {}
9526+    void EventListenerBase::noMatchingTestCases( StringRef ) {}
9527+    void EventListenerBase::reportInvalidTestSpec( StringRef ) {}
9528+    void EventListenerBase::testRunStarting( TestRunInfo const& ) {}
9529+    void EventListenerBase::testCaseStarting( TestCaseInfo const& ) {}
9530+    void EventListenerBase::testCasePartialStarting(TestCaseInfo const&, uint64_t) {}
9531+    void EventListenerBase::sectionStarting( SectionInfo const& ) {}
9532+    void EventListenerBase::sectionEnded( SectionStats const& ) {}
9533+    void EventListenerBase::testCasePartialEnded(TestCaseStats const&, uint64_t) {}
9534+    void EventListenerBase::testCaseEnded( TestCaseStats const& ) {}
9535+    void EventListenerBase::testRunEnded( TestRunStats const& ) {}
9536+    void EventListenerBase::skipTest( TestCaseInfo const& ) {}
9537+} // namespace Catch
9538+
9539+
9540+
9541+
9542+#include <algorithm>
9543+#include <cfloat>
9544+#include <cstdio>
9545+#include <ostream>
9546+#include <iomanip>
9547+
9548+namespace Catch {
9549+
9550+    namespace {
9551+        void listTestNamesOnly(std::ostream& out,
9552+                               std::vector<TestCaseHandle> const& tests) {
9553+            for (auto const& test : tests) {
9554+                auto const& testCaseInfo = test.getTestCaseInfo();
9555+
9556+                if (startsWith(testCaseInfo.name, '#')) {
9557+                    out << '"' << testCaseInfo.name << '"';
9558+                } else {
9559+                    out << testCaseInfo.name;
9560+                }
9561+
9562+                out << '\n';
9563+            }
9564+            out << std::flush;
9565+        }
9566+    } // end unnamed namespace
9567+
9568+
9569+    // Because formatting using c++ streams is stateful, drop down to C is
9570+    // required Alternatively we could use stringstream, but its performance
9571+    // is... not good.
9572+    std::string getFormattedDuration( double duration ) {
9573+        // Max exponent + 1 is required to represent the whole part
9574+        // + 1 for decimal point
9575+        // + 3 for the 3 decimal places
9576+        // + 1 for null terminator
9577+        const std::size_t maxDoubleSize = DBL_MAX_10_EXP + 1 + 1 + 3 + 1;
9578+        char buffer[maxDoubleSize];
9579+
9580+        // Save previous errno, to prevent sprintf from overwriting it
9581+        ErrnoGuard guard;
9582+#ifdef _MSC_VER
9583+        size_t printedLength = static_cast<size_t>(
9584+            sprintf_s( buffer, "%.3f", duration ) );
9585+#else
9586+        size_t printedLength = static_cast<size_t>(
9587+            std::snprintf( buffer, maxDoubleSize, "%.3f", duration ) );
9588+#endif
9589+        return std::string( buffer, printedLength );
9590+    }
9591+
9592+    bool shouldShowDuration( IConfig const& config, double duration ) {
9593+        if ( config.showDurations() == ShowDurations::Always ) {
9594+            return true;
9595+        }
9596+        if ( config.showDurations() == ShowDurations::Never ) {
9597+            return false;
9598+        }
9599+        const double min = config.minDuration();
9600+        return min >= 0 && duration >= min;
9601+    }
9602+
9603+    std::string serializeFilters( std::vector<std::string> const& filters ) {
9604+        // We add a ' ' separator between each filter
9605+        size_t serialized_size = filters.size() - 1;
9606+        for (auto const& filter : filters) {
9607+            serialized_size += filter.size();
9608+        }
9609+
9610+        std::string serialized;
9611+        serialized.reserve(serialized_size);
9612+        bool first = true;
9613+
9614+        for (auto const& filter : filters) {
9615+            if (!first) {
9616+                serialized.push_back(' ');
9617+            }
9618+            first = false;
9619+            serialized.append(filter);
9620+        }
9621+
9622+        return serialized;
9623+    }
9624+
9625+    std::ostream& operator<<( std::ostream& out, lineOfChars value ) {
9626+        for ( size_t idx = 0; idx < CATCH_CONFIG_CONSOLE_WIDTH - 1; ++idx ) {
9627+            out.put( value.c );
9628+        }
9629+        return out;
9630+    }
9631+
9632+    void
9633+    defaultListReporters( std::ostream& out,
9634+                          std::vector<ReporterDescription> const& descriptions,
9635+                          Verbosity verbosity ) {
9636+        out << "Available reporters:\n";
9637+        const auto maxNameLen =
9638+            std::max_element( descriptions.begin(),
9639+                              descriptions.end(),
9640+                              []( ReporterDescription const& lhs,
9641+                                  ReporterDescription const& rhs ) {
9642+                                  return lhs.name.size() < rhs.name.size();
9643+                              } )
9644+                ->name.size();
9645+
9646+        for ( auto const& desc : descriptions ) {
9647+            if ( verbosity == Verbosity::Quiet ) {
9648+                out << TextFlow::Column( desc.name )
9649+                           .indent( 2 )
9650+                           .width( 5 + maxNameLen )
9651+                    << '\n';
9652+            } else {
9653+                out << TextFlow::Column( desc.name + ':' )
9654+                               .indent( 2 )
9655+                               .width( 5 + maxNameLen ) +
9656+                           TextFlow::Column( desc.description )
9657+                               .initialIndent( 0 )
9658+                               .indent( 2 )
9659+                               .width( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen - 8 )
9660+                    << '\n';
9661+            }
9662+        }
9663+        out << '\n' << std::flush;
9664+    }
9665+
9666+    void defaultListListeners( std::ostream& out,
9667+                               std::vector<ListenerDescription> const& descriptions ) {
9668+        out << "Registered listeners:\n";
9669+
9670+        if(descriptions.empty()) {
9671+            return;
9672+        }
9673+
9674+        const auto maxNameLen =
9675+            std::max_element( descriptions.begin(),
9676+                              descriptions.end(),
9677+                              []( ListenerDescription const& lhs,
9678+                                  ListenerDescription const& rhs ) {
9679+                                  return lhs.name.size() < rhs.name.size();
9680+                              } )
9681+                ->name.size();
9682+
9683+        for ( auto const& desc : descriptions ) {
9684+            out << TextFlow::Column( static_cast<std::string>( desc.name ) +
9685+                                     ':' )
9686+                           .indent( 2 )
9687+                           .width( maxNameLen + 5 ) +
9688+                       TextFlow::Column( desc.description )
9689+                           .initialIndent( 0 )
9690+                           .indent( 2 )
9691+                           .width( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen - 8 )
9692+                << '\n';
9693+        }
9694+
9695+        out << '\n' << std::flush;
9696+    }
9697+
9698+    void defaultListTags( std::ostream& out,
9699+                          std::vector<TagInfo> const& tags,
9700+                          bool isFiltered ) {
9701+        if ( isFiltered ) {
9702+            out << "Tags for matching test cases:\n";
9703+        } else {
9704+            out << "All available tags:\n";
9705+        }
9706+
9707+        for ( auto const& tagCount : tags ) {
9708+            ReusableStringStream rss;
9709+            rss << "  " << std::setw( 2 ) << tagCount.count << "  ";
9710+            auto str = rss.str();
9711+            auto wrapper = TextFlow::Column( tagCount.all() )
9712+                               .initialIndent( 0 )
9713+                               .indent( str.size() )
9714+                               .width( CATCH_CONFIG_CONSOLE_WIDTH - 10 );
9715+            out << str << wrapper << '\n';
9716+        }
9717+        out << pluralise(tags.size(), "tag"_sr) << "\n\n" << std::flush;
9718+    }
9719+
9720+    void defaultListTests(std::ostream& out, ColourImpl* streamColour, std::vector<TestCaseHandle> const& tests, bool isFiltered, Verbosity verbosity) {
9721+        // We special case this to provide the equivalent of old
9722+        // `--list-test-names-only`, which could then be used by the
9723+        // `--input-file` option.
9724+        if (verbosity == Verbosity::Quiet) {
9725+            listTestNamesOnly(out, tests);
9726+            return;
9727+        }
9728+
9729+        if (isFiltered) {
9730+            out << "Matching test cases:\n";
9731+        } else {
9732+            out << "All available test cases:\n";
9733+        }
9734+
9735+        for (auto const& test : tests) {
9736+            auto const& testCaseInfo = test.getTestCaseInfo();
9737+            Colour::Code colour = testCaseInfo.isHidden()
9738+                ? Colour::SecondaryText
9739+                : Colour::None;
9740+            auto colourGuard = streamColour->guardColour( colour ).engage( out );
9741+
9742+            out << TextFlow::Column(testCaseInfo.name).indent(2) << '\n';
9743+            if (verbosity >= Verbosity::High) {
9744+                out << TextFlow::Column(Catch::Detail::stringify(testCaseInfo.lineInfo)).indent(4) << '\n';
9745+            }
9746+            if (!testCaseInfo.tags.empty() &&
9747+                verbosity > Verbosity::Quiet) {
9748+                out << TextFlow::Column(testCaseInfo.tagsAsString()).indent(6) << '\n';
9749+            }
9750+        }
9751+
9752+        if (isFiltered) {
9753+            out << pluralise(tests.size(), "matching test case"_sr);
9754+        } else {
9755+            out << pluralise(tests.size(), "test case"_sr);
9756+        }
9757+        out << "\n\n" << std::flush;
9758+    }
9759+
9760+    namespace {
9761+        class SummaryColumn {
9762+        public:
9763+            SummaryColumn( std::string suffix, Colour::Code colour ):
9764+                m_suffix( CATCH_MOVE( suffix ) ), m_colour( colour ) {}
9765+
9766+            SummaryColumn&& addRow( std::uint64_t count ) && {
9767+                std::string row = std::to_string(count);
9768+                auto const new_width = std::max( m_width, row.size() );
9769+                if ( new_width > m_width ) {
9770+                    for ( auto& oldRow : m_rows ) {
9771+                        oldRow.insert( 0, new_width - m_width, ' ' );
9772+                    }
9773+                } else {
9774+                    row.insert( 0, m_width - row.size(), ' ' );
9775+                }
9776+                m_width = new_width;
9777+                m_rows.push_back( row );
9778+                return std::move( *this );
9779+            }
9780+
9781+            std::string const& getSuffix() const { return m_suffix; }
9782+            Colour::Code getColour() const { return m_colour; }
9783+            std::string const& getRow( std::size_t index ) const {
9784+                return m_rows[index];
9785+            }
9786+
9787+        private:
9788+            std::string m_suffix;
9789+            Colour::Code m_colour;
9790+            std::size_t m_width = 0;
9791+            std::vector<std::string> m_rows;
9792+        };
9793+
9794+        void printSummaryRow( std::ostream& stream,
9795+                              ColourImpl& colour,
9796+                              StringRef label,
9797+                              std::vector<SummaryColumn> const& cols,
9798+                              std::size_t row ) {
9799+            for ( auto const& col : cols ) {
9800+                auto const& value = col.getRow( row );
9801+                auto const& suffix = col.getSuffix();
9802+                if ( suffix.empty() ) {
9803+                    stream << label << ": ";
9804+                    if ( value != "0" ) {
9805+                        stream << value;
9806+                    } else {
9807+                        stream << colour.guardColour( Colour::Warning )
9808+                               << "- none -";
9809+                    }
9810+                } else if ( value != "0" ) {
9811+                    stream << colour.guardColour( Colour::LightGrey ) << " | "
9812+                           << colour.guardColour( col.getColour() ) << value
9813+                           << ' ' << suffix;
9814+                }
9815+            }
9816+            stream << '\n';
9817+        }
9818+    } // namespace
9819+
9820+    void printTestRunTotals( std::ostream& stream,
9821+                             ColourImpl& streamColour,
9822+                             Totals const& totals ) {
9823+        if ( totals.testCases.total() == 0 ) {
9824+            stream << streamColour.guardColour( Colour::Warning )
9825+                   << "No tests ran\n";
9826+            return;
9827+        }
9828+
9829+        if ( totals.assertions.total() > 0 && totals.testCases.allPassed() ) {
9830+            stream << streamColour.guardColour( Colour::ResultSuccess )
9831+                   << "All tests passed";
9832+            stream << " ("
9833+                   << pluralise( totals.assertions.passed, "assertion"_sr )
9834+                   << " in "
9835+                   << pluralise( totals.testCases.passed, "test case"_sr )
9836+                   << ')' << '\n';
9837+            return;
9838+        }
9839+
9840+        std::vector<SummaryColumn> columns;
9841+        // Don't include "skipped assertions" in total count
9842+        const auto totalAssertionCount =
9843+            totals.assertions.total() - totals.assertions.skipped;
9844+        columns.push_back( SummaryColumn( "", Colour::None )
9845+                               .addRow( totals.testCases.total() )
9846+                               .addRow( totalAssertionCount ) );
9847+        columns.push_back( SummaryColumn( "passed", Colour::Success )
9848+                               .addRow( totals.testCases.passed )
9849+                               .addRow( totals.assertions.passed ) );
9850+        columns.push_back( SummaryColumn( "failed", Colour::ResultError )
9851+                               .addRow( totals.testCases.failed )
9852+                               .addRow( totals.assertions.failed ) );
9853+        columns.push_back( SummaryColumn( "skipped", Colour::Skip )
9854+                               .addRow( totals.testCases.skipped )
9855+                               // Don't print "skipped assertions"
9856+                               .addRow( 0 ) );
9857+        columns.push_back(
9858+            SummaryColumn( "failed as expected", Colour::ResultExpectedFailure )
9859+                .addRow( totals.testCases.failedButOk )
9860+                .addRow( totals.assertions.failedButOk ) );
9861+        printSummaryRow( stream, streamColour, "test cases"_sr, columns, 0 );
9862+        printSummaryRow( stream, streamColour, "assertions"_sr, columns, 1 );
9863+    }
9864+
9865+} // namespace Catch
9866+
9867+
9868+//
9869+
9870+namespace Catch {
9871+    namespace {
9872+        void writeSourceInfo( JsonObjectWriter& writer,
9873+                              SourceLineInfo const& sourceInfo ) {
9874+            auto source_location_writer =
9875+                writer.write( "source-location"_sr ).writeObject();
9876+            source_location_writer.write( "filename"_sr )
9877+                .write( sourceInfo.file );
9878+            source_location_writer.write( "line"_sr ).write( sourceInfo.line );
9879+        }
9880+
9881+        void writeTags( JsonArrayWriter writer, std::vector<Tag> const& tags ) {
9882+            for ( auto const& tag : tags ) {
9883+                writer.write( tag.original );
9884+            }
9885+        }
9886+
9887+        void writeProperties( JsonArrayWriter writer,
9888+                              TestCaseInfo const& info ) {
9889+            if ( info.isHidden() ) { writer.write( "is-hidden"_sr ); }
9890+            if ( info.okToFail() ) { writer.write( "ok-to-fail"_sr ); }
9891+            if ( info.expectedToFail() ) {
9892+                writer.write( "expected-to-fail"_sr );
9893+            }
9894+            if ( info.throws() ) { writer.write( "throws"_sr ); }
9895+        }
9896+
9897+    } // namespace
9898+
9899+    JsonReporter::JsonReporter( ReporterConfig&& config ):
9900+        StreamingReporterBase{ CATCH_MOVE( config ) } {
9901+
9902+        m_preferences.shouldRedirectStdOut = true;
9903+        // TBD: Do we want to report all assertions? XML reporter does
9904+        //      not, but for machine-parseable reporters I think the answer
9905+        //      should be yes.
9906+        m_preferences.shouldReportAllAssertions = true;
9907+
9908+        m_objectWriters.emplace( m_stream );
9909+        m_writers.emplace( Writer::Object );
9910+        auto& writer = m_objectWriters.top();
9911+
9912+        writer.write( "version"_sr ).write( 1 );
9913+
9914+        {
9915+            auto metadata_writer = writer.write( "metadata"_sr ).writeObject();
9916+            metadata_writer.write( "name"_sr ).write( m_config->name() );
9917+            metadata_writer.write( "rng-seed"_sr ).write( m_config->rngSeed() );
9918+            metadata_writer.write( "catch2-version"_sr )
9919+                .write( libraryVersion() );
9920+            if ( m_config->testSpec().hasFilters() ) {
9921+                metadata_writer.write( "filters"_sr )
9922+                    .write( m_config->testSpec() );
9923+            }
9924+        }
9925+    }
9926+
9927+    JsonReporter::~JsonReporter() {
9928+        endListing();
9929+        // TODO: Ensure this closes the top level object, add asserts
9930+        assert( m_writers.size() == 1 && "Only the top level object should be open" );
9931+        assert( m_writers.top() == Writer::Object );
9932+        endObject();
9933+        m_stream << '\n' << std::flush;
9934+        assert( m_writers.empty() );
9935+    }
9936+
9937+    JsonArrayWriter& JsonReporter::startArray() {
9938+        m_arrayWriters.emplace( m_arrayWriters.top().writeArray() );
9939+        m_writers.emplace( Writer::Array );
9940+        return m_arrayWriters.top();
9941+    }
9942+    JsonArrayWriter& JsonReporter::startArray( StringRef key ) {
9943+        m_arrayWriters.emplace(
9944+            m_objectWriters.top().write( key ).writeArray() );
9945+        m_writers.emplace( Writer::Array );
9946+        return m_arrayWriters.top();
9947+    }
9948+
9949+    JsonObjectWriter& JsonReporter::startObject() {
9950+        m_objectWriters.emplace( m_arrayWriters.top().writeObject() );
9951+        m_writers.emplace( Writer::Object );
9952+        return m_objectWriters.top();
9953+    }
9954+    JsonObjectWriter& JsonReporter::startObject( StringRef key ) {
9955+        m_objectWriters.emplace(
9956+            m_objectWriters.top().write( key ).writeObject() );
9957+        m_writers.emplace( Writer::Object );
9958+        return m_objectWriters.top();
9959+    }
9960+
9961+    void JsonReporter::endObject() {
9962+        assert( isInside( Writer::Object ) );
9963+        m_objectWriters.pop();
9964+        m_writers.pop();
9965+    }
9966+    void JsonReporter::endArray() {
9967+        assert( isInside( Writer::Array ) );
9968+        m_arrayWriters.pop();
9969+        m_writers.pop();
9970+    }
9971+
9972+    bool JsonReporter::isInside( Writer writer ) {
9973+        return !m_writers.empty() && m_writers.top() == writer;
9974+    }
9975+
9976+    void JsonReporter::startListing() {
9977+        if ( !m_startedListing ) { startObject( "listings"_sr ); }
9978+        m_startedListing = true;
9979+    }
9980+    void JsonReporter::endListing() {
9981+        if ( m_startedListing ) { endObject(); }
9982+        m_startedListing = false;
9983+    }
9984+
9985+    std::string JsonReporter::getDescription() {
9986+        return "Outputs listings as JSON. Test listing is Work-in-Progress!";
9987+    }
9988+
9989+    void JsonReporter::testRunStarting( TestRunInfo const& runInfo ) {
9990+        StreamingReporterBase::testRunStarting( runInfo );
9991+        endListing();
9992+
9993+        assert( isInside( Writer::Object ) );
9994+        startObject( "test-run"_sr );
9995+        startArray( "test-cases"_sr );
9996+    }
9997+
9998+     static void writeCounts( JsonObjectWriter&& writer, Counts const& counts ) {
9999+        writer.write( "passed"_sr ).write( counts.passed );
10000+        writer.write( "failed"_sr ).write( counts.failed );
10001+        writer.write( "fail-but-ok"_sr ).write( counts.failedButOk );
10002+        writer.write( "skipped"_sr ).write( counts.skipped );
10003+    }
10004+
10005+    void JsonReporter::testRunEnded(TestRunStats const& runStats) {
10006+        assert( isInside( Writer::Array ) );
10007+        // End "test-cases"
10008+        endArray();
10009+
10010+        {
10011+            auto totals =
10012+                m_objectWriters.top().write( "totals"_sr ).writeObject();
10013+            writeCounts( totals.write( "assertions"_sr ).writeObject(),
10014+                         runStats.totals.assertions );
10015+            writeCounts( totals.write( "test-cases"_sr ).writeObject(),
10016+                         runStats.totals.testCases );
10017+        }
10018+
10019+        // End the "test-run" object
10020+        endObject();
10021+    }
10022+
10023+    void JsonReporter::testCaseStarting( TestCaseInfo const& tcInfo ) {
10024+        StreamingReporterBase::testCaseStarting( tcInfo );
10025+
10026+        assert( isInside( Writer::Array ) &&
10027+                "We should be in the 'test-cases' array" );
10028+        startObject();
10029+        // "test-info" prelude
10030+        {
10031+            auto testInfo =
10032+                m_objectWriters.top().write( "test-info"_sr ).writeObject();
10033+            // TODO: handle testName vs className!!
10034+            testInfo.write( "name"_sr ).write( tcInfo.name );
10035+            writeSourceInfo(testInfo, tcInfo.lineInfo);
10036+            writeTags( testInfo.write( "tags"_sr ).writeArray(), tcInfo.tags );
10037+            writeProperties( testInfo.write( "properties"_sr ).writeArray(),
10038+                             tcInfo );
10039+        }
10040+
10041+
10042+        // Start the array for individual test runs (testCasePartial pairs)
10043+        startArray( "runs"_sr );
10044+    }
10045+
10046+    void JsonReporter::testCaseEnded( TestCaseStats const& tcStats ) {
10047+        StreamingReporterBase::testCaseEnded( tcStats );
10048+
10049+        // We need to close the 'runs' array before finishing the test case
10050+        assert( isInside( Writer::Array ) );
10051+        endArray();
10052+
10053+        {
10054+            auto totals =
10055+                m_objectWriters.top().write( "totals"_sr ).writeObject();
10056+            writeCounts( totals.write( "assertions"_sr ).writeObject(),
10057+                         tcStats.totals.assertions );
10058+            // We do not write the test case totals, because there will always be just one test case here.
10059+            // TODO: overall "result" -> success, skip, fail here? Or in partial result?
10060+        }
10061+        // We do not write out stderr/stdout, because we instead wrote those out in partial runs
10062+
10063+        // TODO: aborting?
10064+
10065+        // And we also close this test case's object
10066+        assert( isInside( Writer::Object ) );
10067+        endObject();
10068+    }
10069+
10070+    void JsonReporter::testCasePartialStarting( TestCaseInfo const& /*tcInfo*/,
10071+                                                uint64_t index ) {
10072+        startObject();
10073+        m_objectWriters.top().write( "run-idx"_sr ).write( index );
10074+        startArray( "path"_sr );
10075+        // TODO: we want to delay most of the printing to the 'root' section
10076+        // TODO: childSection key name?
10077+    }
10078+
10079+    void JsonReporter::testCasePartialEnded( TestCaseStats const& tcStats,
10080+                                             uint64_t /*index*/ ) {
10081+        // Fixme: the top level section handles this.
10082+        //// path object
10083+        endArray();
10084+        if ( !tcStats.stdOut.empty() ) {
10085+            m_objectWriters.top()
10086+                .write( "captured-stdout"_sr )
10087+                .write( tcStats.stdOut );
10088+        }
10089+        if ( !tcStats.stdErr.empty() ) {
10090+            m_objectWriters.top()
10091+                .write( "captured-stderr"_sr )
10092+                .write( tcStats.stdErr );
10093+        }
10094+        {
10095+            auto totals =
10096+                m_objectWriters.top().write( "totals"_sr ).writeObject();
10097+            writeCounts( totals.write( "assertions"_sr ).writeObject(),
10098+                         tcStats.totals.assertions );
10099+            // We do not write the test case totals, because there will
10100+            // always be just one test case here.
10101+            // TODO: overall "result" -> success, skip, fail here? Or in
10102+            // partial result?
10103+        }
10104+        // TODO: aborting?
10105+        // run object
10106+        endObject();
10107+    }
10108+
10109+    void JsonReporter::sectionStarting( SectionInfo const& sectionInfo ) {
10110+        assert( isInside( Writer::Array ) &&
10111+                "Section should always start inside an object" );
10112+        // We want to nest top level sections, even though it shares name
10113+        // and source loc with the TEST_CASE
10114+        auto& sectionObject = startObject();
10115+        sectionObject.write( "kind"_sr ).write( "section"_sr );
10116+        sectionObject.write( "name"_sr ).write( sectionInfo.name );
10117+        writeSourceInfo( m_objectWriters.top(), sectionInfo.lineInfo );
10118+
10119+
10120+        // TBD: Do we want to create this event lazily? It would become
10121+        //      rather complex, but we could do it, and it would look
10122+        //      better for empty sections. OTOH, empty sections should
10123+        //      be rare.
10124+        startArray( "path"_sr );
10125+    }
10126+    void JsonReporter::sectionEnded( SectionStats const& /*sectionStats */) {
10127+        // End the subpath array
10128+        endArray();
10129+        // TODO: metadata
10130+        // TODO: what info do we have here?
10131+
10132+        // End the section object
10133+        endObject();
10134+    }
10135+
10136+    void JsonReporter::assertionStarting( AssertionInfo const& /*assertionInfo*/ ) {}
10137+    void JsonReporter::assertionEnded( AssertionStats const& assertionStats ) {
10138+        // TODO: There is lot of different things to handle here, but
10139+        //       we can fill it in later, after we show that the basic
10140+        //       outline and streaming reporter impl works well enough.
10141+        //if ( !m_config->includeSuccessfulResults()
10142+        //    && assertionStats.assertionResult.isOk() ) {
10143+        //    return;
10144+        //}
10145+        assert( isInside( Writer::Array ) );
10146+        auto assertionObject = m_arrayWriters.top().writeObject();
10147+
10148+        assertionObject.write( "kind"_sr ).write( "assertion"_sr );
10149+        writeSourceInfo( assertionObject,
10150+                         assertionStats.assertionResult.getSourceInfo() );
10151+        assertionObject.write( "status"_sr )
10152+            .write( assertionStats.assertionResult.isOk() );
10153+        // TODO: handling of result.
10154+        // TODO: messages
10155+        // TODO: totals?
10156+    }
10157+
10158+
10159+    void JsonReporter::benchmarkPreparing( StringRef name ) { (void)name; }
10160+    void JsonReporter::benchmarkStarting( BenchmarkInfo const& ) {}
10161+    void JsonReporter::benchmarkEnded( BenchmarkStats<> const& ) {}
10162+    void JsonReporter::benchmarkFailed( StringRef error ) { (void)error; }
10163+
10164+    void JsonReporter::listReporters(
10165+        std::vector<ReporterDescription> const& descriptions ) {
10166+        startListing();
10167+
10168+        auto writer =
10169+            m_objectWriters.top().write( "reporters"_sr ).writeArray();
10170+        for ( auto const& desc : descriptions ) {
10171+            auto desc_writer = writer.writeObject();
10172+            desc_writer.write( "name"_sr ).write( desc.name );
10173+            desc_writer.write( "description"_sr ).write( desc.description );
10174+        }
10175+    }
10176+    void JsonReporter::listListeners(
10177+        std::vector<ListenerDescription> const& descriptions ) {
10178+        startListing();
10179+
10180+        auto writer =
10181+            m_objectWriters.top().write( "listeners"_sr ).writeArray();
10182+
10183+        for ( auto const& desc : descriptions ) {
10184+            auto desc_writer = writer.writeObject();
10185+            desc_writer.write( "name"_sr ).write( desc.name );
10186+            desc_writer.write( "description"_sr ).write( desc.description );
10187+        }
10188+    }
10189+    void JsonReporter::listTests( std::vector<TestCaseHandle> const& tests ) {
10190+        startListing();
10191+
10192+        auto writer = m_objectWriters.top().write( "tests"_sr ).writeArray();
10193+
10194+        for ( auto const& test : tests ) {
10195+            auto desc_writer = writer.writeObject();
10196+            auto const& info = test.getTestCaseInfo();
10197+
10198+            desc_writer.write( "name"_sr ).write( info.name );
10199+            desc_writer.write( "class-name"_sr ).write( info.className );
10200+            {
10201+                auto tag_writer = desc_writer.write( "tags"_sr ).writeArray();
10202+                for ( auto const& tag : info.tags ) {
10203+                    tag_writer.write( tag.original );
10204+                }
10205+            }
10206+            writeSourceInfo( desc_writer, info.lineInfo );
10207+        }
10208+    }
10209+    void JsonReporter::listTags( std::vector<TagInfo> const& tags ) {
10210+        startListing();
10211+
10212+        auto writer = m_objectWriters.top().write( "tags"_sr ).writeArray();
10213+        for ( auto const& tag : tags ) {
10214+            auto tag_writer = writer.writeObject();
10215+            {
10216+                auto aliases_writer =
10217+                    tag_writer.write( "aliases"_sr ).writeArray();
10218+                for ( auto alias : tag.spellings ) {
10219+                    aliases_writer.write( alias );
10220+                }
10221+            }
10222+            tag_writer.write( "count"_sr ).write( tag.count );
10223+        }
10224+    }
10225+} // namespace Catch
10226+
10227+
10228+
10229+
10230+#include <cassert>
10231+#include <ctime>
10232+#include <algorithm>
10233+#include <iomanip>
10234+
10235+namespace Catch {
10236+
10237+    namespace {
10238+        std::string getCurrentTimestamp() {
10239+            time_t rawtime;
10240+            std::time(&rawtime);
10241+
10242+            std::tm timeInfo = {};
10243+#if defined (_MSC_VER) || defined (__MINGW32__)
10244+            gmtime_s(&timeInfo, &rawtime);
10245+#elif defined (CATCH_PLATFORM_PLAYSTATION)
10246+            gmtime_s(&rawtime, &timeInfo);
10247+#elif defined (__IAR_SYSTEMS_ICC__)
10248+            timeInfo = *std::gmtime(&rawtime);
10249+#else
10250+            gmtime_r(&rawtime, &timeInfo);
10251+#endif
10252+
10253+            auto const timeStampSize = sizeof("2017-01-16T17:06:45Z");
10254+            char timeStamp[timeStampSize];
10255+            const char * const fmt = "%Y-%m-%dT%H:%M:%SZ";
10256+
10257+            std::strftime(timeStamp, timeStampSize, fmt, &timeInfo);
10258+
10259+            return std::string(timeStamp, timeStampSize - 1);
10260+        }
10261+
10262+        std::string fileNameTag(std::vector<Tag> const& tags) {
10263+            auto it = std::find_if(begin(tags),
10264+                                   end(tags),
10265+                                   [] (Tag const& tag) {
10266+                                       return tag.original.size() > 0
10267+                                           && tag.original[0] == '#'; });
10268+            if (it != tags.end()) {
10269+                return static_cast<std::string>(
10270+                    it->original.substr(1, it->original.size() - 1)
10271+                );
10272+            }
10273+            return std::string();
10274+        }
10275+
10276+        // Formats the duration in seconds to 3 decimal places.
10277+        // This is done because some genius defined Maven Surefire schema
10278+        // in a way that only accepts 3 decimal places, and tools like
10279+        // Jenkins use that schema for validation JUnit reporter output.
10280+        std::string formatDuration( double seconds ) {
10281+            ReusableStringStream rss;
10282+            rss << std::fixed << std::setprecision( 3 ) << seconds;
10283+            return rss.str();
10284+        }
10285+
10286+        static void normalizeNamespaceMarkers(std::string& str) {
10287+            std::size_t pos = str.find( "::" );
10288+            while ( pos != std::string::npos ) {
10289+                str.replace( pos, 2, "." );
10290+                pos += 1;
10291+                pos = str.find( "::", pos );
10292+            }
10293+        }
10294+
10295+    } // anonymous namespace
10296+
10297+    JunitReporter::JunitReporter( ReporterConfig&& _config )
10298+        :   CumulativeReporterBase( CATCH_MOVE(_config) ),
10299+            xml( m_stream )
10300+        {
10301+            m_preferences.shouldRedirectStdOut = true;
10302+            m_preferences.shouldReportAllAssertions = true;
10303+            m_shouldStoreSuccesfulAssertions = false;
10304+        }
10305+
10306+    std::string JunitReporter::getDescription() {
10307+        return "Reports test results in an XML format that looks like Ant's junitreport target";
10308+    }
10309+
10310+    void JunitReporter::testRunStarting( TestRunInfo const& runInfo )  {
10311+        CumulativeReporterBase::testRunStarting( runInfo );
10312+        xml.startElement( "testsuites" );
10313+        suiteTimer.start();
10314+        stdOutForSuite.clear();
10315+        stdErrForSuite.clear();
10316+        unexpectedExceptions = 0;
10317+    }
10318+
10319+    void JunitReporter::testCaseStarting( TestCaseInfo const& testCaseInfo ) {
10320+        m_okToFail = testCaseInfo.okToFail();
10321+    }
10322+
10323+    void JunitReporter::assertionEnded( AssertionStats const& assertionStats ) {
10324+        if( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException && !m_okToFail )
10325+            unexpectedExceptions++;
10326+        CumulativeReporterBase::assertionEnded( assertionStats );
10327+    }
10328+
10329+    void JunitReporter::testCaseEnded( TestCaseStats const& testCaseStats ) {
10330+        stdOutForSuite += testCaseStats.stdOut;
10331+        stdErrForSuite += testCaseStats.stdErr;
10332+        CumulativeReporterBase::testCaseEnded( testCaseStats );
10333+    }
10334+
10335+    void JunitReporter::testRunEndedCumulative() {
10336+        const auto suiteTime = suiteTimer.getElapsedSeconds();
10337+        writeRun( *m_testRun, suiteTime );
10338+        xml.endElement();
10339+    }
10340+
10341+    void JunitReporter::writeRun( TestRunNode const& testRunNode, double suiteTime ) {
10342+        XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" );
10343+
10344+        TestRunStats const& stats = testRunNode.value;
10345+        xml.writeAttribute( "name"_sr, stats.runInfo.name );
10346+        xml.writeAttribute( "errors"_sr, unexpectedExceptions );
10347+        xml.writeAttribute( "failures"_sr, stats.totals.assertions.failed-unexpectedExceptions );
10348+        xml.writeAttribute( "skipped"_sr, stats.totals.assertions.skipped );
10349+        xml.writeAttribute( "tests"_sr, stats.totals.assertions.total() );
10350+        xml.writeAttribute( "hostname"_sr, "tbd"_sr ); // !TBD
10351+        if( m_config->showDurations() == ShowDurations::Never )
10352+            xml.writeAttribute( "time"_sr, ""_sr );
10353+        else
10354+            xml.writeAttribute( "time"_sr, formatDuration( suiteTime ) );
10355+        xml.writeAttribute( "timestamp"_sr, getCurrentTimestamp() );
10356+
10357+        // Write properties
10358+        {
10359+            auto properties = xml.scopedElement("properties");
10360+            xml.scopedElement("property")
10361+                .writeAttribute("name"_sr, "random-seed"_sr)
10362+                .writeAttribute("value"_sr, m_config->rngSeed());
10363+            if (m_config->testSpec().hasFilters()) {
10364+                xml.scopedElement("property")
10365+                    .writeAttribute("name"_sr, "filters"_sr)
10366+                    .writeAttribute("value"_sr, m_config->testSpec());
10367+            }
10368+        }
10369+
10370+        // Write test cases
10371+        for( auto const& child : testRunNode.children )
10372+            writeTestCase( *child );
10373+
10374+        xml.scopedElement( "system-out" ).writeText( trim( stdOutForSuite ), XmlFormatting::Newline );
10375+        xml.scopedElement( "system-err" ).writeText( trim( stdErrForSuite ), XmlFormatting::Newline );
10376+    }
10377+
10378+    void JunitReporter::writeTestCase( TestCaseNode const& testCaseNode ) {
10379+        TestCaseStats const& stats = testCaseNode.value;
10380+
10381+        // All test cases have exactly one section - which represents the
10382+        // test case itself. That section may have 0-n nested sections
10383+        assert( testCaseNode.children.size() == 1 );
10384+        SectionNode const& rootSection = *testCaseNode.children.front();
10385+
10386+        std::string className =
10387+            static_cast<std::string>( stats.testInfo->className );
10388+
10389+        if( className.empty() ) {
10390+            className = fileNameTag(stats.testInfo->tags);
10391+            if ( className.empty() ) {
10392+                className = "global";
10393+            }
10394+        }
10395+
10396+        if ( !m_config->name().empty() )
10397+            className = static_cast<std::string>(m_config->name()) + '.' + className;
10398+
10399+        normalizeNamespaceMarkers(className);
10400+
10401+        writeSection( className, "", rootSection, stats.testInfo->okToFail() );
10402+    }
10403+
10404+    void JunitReporter::writeSection( std::string const& className,
10405+                                      std::string const& rootName,
10406+                                      SectionNode const& sectionNode,
10407+                                      bool testOkToFail) {
10408+        std::string name = trim( sectionNode.stats.sectionInfo.name );
10409+        if( !rootName.empty() )
10410+            name = rootName + '/' + name;
10411+
10412+        if( sectionNode.hasAnyAssertions()
10413+           || !sectionNode.stdOut.empty()
10414+           || !sectionNode.stdErr.empty() ) {
10415+            XmlWriter::ScopedElement e = xml.scopedElement( "testcase" );
10416+            if( className.empty() ) {
10417+                xml.writeAttribute( "classname"_sr, name );
10418+                xml.writeAttribute( "name"_sr, "root"_sr );
10419+            }
10420+            else {
10421+                xml.writeAttribute( "classname"_sr, className );
10422+                xml.writeAttribute( "name"_sr, name );
10423+            }
10424+            xml.writeAttribute( "time"_sr, formatDuration( sectionNode.stats.durationInSeconds ) );
10425+            // This is not ideal, but it should be enough to mimic gtest's
10426+            // junit output.
10427+            // Ideally the JUnit reporter would also handle `skipTest`
10428+            // events and write those out appropriately.
10429+            xml.writeAttribute( "status"_sr, "run"_sr );
10430+
10431+            if (sectionNode.stats.assertions.failedButOk) {
10432+                xml.scopedElement("skipped")
10433+                    .writeAttribute("message", "TEST_CASE tagged with !mayfail");
10434+            }
10435+
10436+            writeAssertions( sectionNode );
10437+
10438+
10439+            if( !sectionNode.stdOut.empty() )
10440+                xml.scopedElement( "system-out" ).writeText( trim( sectionNode.stdOut ), XmlFormatting::Newline );
10441+            if( !sectionNode.stdErr.empty() )
10442+                xml.scopedElement( "system-err" ).writeText( trim( sectionNode.stdErr ), XmlFormatting::Newline );
10443+        }
10444+        for( auto const& childNode : sectionNode.childSections )
10445+            if( className.empty() )
10446+                writeSection( name, "", *childNode, testOkToFail );
10447+            else
10448+                writeSection( className, name, *childNode, testOkToFail );
10449+    }
10450+
10451+    void JunitReporter::writeAssertions( SectionNode const& sectionNode ) {
10452+        for (auto const& assertionOrBenchmark : sectionNode.assertionsAndBenchmarks) {
10453+            if (assertionOrBenchmark.isAssertion()) {
10454+                writeAssertion(assertionOrBenchmark.asAssertion());
10455+            }
10456+        }
10457+    }
10458+
10459+    void JunitReporter::writeAssertion( AssertionStats const& stats ) {
10460+        AssertionResult const& result = stats.assertionResult;
10461+        if ( !result.isOk() ||
10462+             result.getResultType() == ResultWas::ExplicitSkip ) {
10463+            std::string elementName;
10464+            switch( result.getResultType() ) {
10465+                case ResultWas::ThrewException:
10466+                case ResultWas::FatalErrorCondition:
10467+                    elementName = "error";
10468+                    break;
10469+                case ResultWas::ExplicitFailure:
10470+                case ResultWas::ExpressionFailed:
10471+                case ResultWas::DidntThrowException:
10472+                    elementName = "failure";
10473+                    break;
10474+                case ResultWas::ExplicitSkip:
10475+                    elementName = "skipped";
10476+                    break;
10477+                // We should never see these here:
10478+                case ResultWas::Info:
10479+                case ResultWas::Warning:
10480+                case ResultWas::Ok:
10481+                case ResultWas::Unknown:
10482+                case ResultWas::FailureBit:
10483+                case ResultWas::Exception:
10484+                    elementName = "internalError";
10485+                    break;
10486+            }
10487+
10488+            XmlWriter::ScopedElement e = xml.scopedElement( elementName );
10489+
10490+            xml.writeAttribute( "message"_sr, result.getExpression() );
10491+            xml.writeAttribute( "type"_sr, result.getTestMacroName() );
10492+
10493+            ReusableStringStream rss;
10494+            if ( result.getResultType() == ResultWas::ExplicitSkip ) {
10495+                rss << "SKIPPED\n";
10496+            } else {
10497+                rss << "FAILED" << ":\n";
10498+                if (result.hasExpression()) {
10499+                    rss << "  ";
10500+                    rss << result.getExpressionInMacro();
10501+                    rss << '\n';
10502+                }
10503+                if (result.hasExpandedExpression()) {
10504+                    rss << "with expansion:\n";
10505+                    rss << TextFlow::Column(result.getExpandedExpression()).indent(2) << '\n';
10506+                }
10507+            }
10508+
10509+            if( result.hasMessage() )
10510+                rss << result.getMessage() << '\n';
10511+            for( auto const& msg : stats.infoMessages )
10512+                if( msg.type == ResultWas::Info )
10513+                    rss << msg.message << '\n';
10514+
10515+            rss << "at " << result.getSourceInfo();
10516+            xml.writeText( rss.str(), XmlFormatting::Newline );
10517+        }
10518+    }
10519+
10520+} // end namespace Catch
10521+
10522+
10523+
10524+
10525+#include <ostream>
10526+
10527+namespace Catch {
10528+    void MultiReporter::updatePreferences(IEventListener const& reporterish) {
10529+        m_preferences.shouldRedirectStdOut |=
10530+            reporterish.getPreferences().shouldRedirectStdOut;
10531+        m_preferences.shouldReportAllAssertions |=
10532+            reporterish.getPreferences().shouldReportAllAssertions;
10533+    }
10534+
10535+    void MultiReporter::addListener( IEventListenerPtr&& listener ) {
10536+        updatePreferences(*listener);
10537+        m_reporterLikes.insert(m_reporterLikes.begin() + m_insertedListeners, CATCH_MOVE(listener) );
10538+        ++m_insertedListeners;
10539+    }
10540+
10541+    void MultiReporter::addReporter( IEventListenerPtr&& reporter ) {
10542+        updatePreferences(*reporter);
10543+
10544+        // We will need to output the captured stdout if there are reporters
10545+        // that do not want it captured.
10546+        // We do not consider listeners, because it is generally assumed that
10547+        // listeners are output-transparent, even though they can ask for stdout
10548+        // capture to do something with it.
10549+        m_haveNoncapturingReporters |= !reporter->getPreferences().shouldRedirectStdOut;
10550+
10551+        // Reporters can always be placed to the back without breaking the
10552+        // reporting order
10553+        m_reporterLikes.push_back( CATCH_MOVE( reporter ) );
10554+    }
10555+
10556+    void MultiReporter::noMatchingTestCases( StringRef unmatchedSpec ) {
10557+        for ( auto& reporterish : m_reporterLikes ) {
10558+            reporterish->noMatchingTestCases( unmatchedSpec );
10559+        }
10560+    }
10561+
10562+    void MultiReporter::fatalErrorEncountered( StringRef error ) {
10563+        for ( auto& reporterish : m_reporterLikes ) {
10564+            reporterish->fatalErrorEncountered( error );
10565+        }
10566+    }
10567+
10568+    void MultiReporter::reportInvalidTestSpec( StringRef arg ) {
10569+        for ( auto& reporterish : m_reporterLikes ) {
10570+            reporterish->reportInvalidTestSpec( arg );
10571+        }
10572+    }
10573+
10574+    void MultiReporter::benchmarkPreparing( StringRef name ) {
10575+        for (auto& reporterish : m_reporterLikes) {
10576+            reporterish->benchmarkPreparing(name);
10577+        }
10578+    }
10579+    void MultiReporter::benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) {
10580+        for ( auto& reporterish : m_reporterLikes ) {
10581+            reporterish->benchmarkStarting( benchmarkInfo );
10582+        }
10583+    }
10584+    void MultiReporter::benchmarkEnded( BenchmarkStats<> const& benchmarkStats ) {
10585+        for ( auto& reporterish : m_reporterLikes ) {
10586+            reporterish->benchmarkEnded( benchmarkStats );
10587+        }
10588+    }
10589+
10590+    void MultiReporter::benchmarkFailed( StringRef error ) {
10591+        for (auto& reporterish : m_reporterLikes) {
10592+            reporterish->benchmarkFailed(error);
10593+        }
10594+    }
10595+
10596+    void MultiReporter::testRunStarting( TestRunInfo const& testRunInfo ) {
10597+        for ( auto& reporterish : m_reporterLikes ) {
10598+            reporterish->testRunStarting( testRunInfo );
10599+        }
10600+    }
10601+
10602+    void MultiReporter::testCaseStarting( TestCaseInfo const& testInfo ) {
10603+        for ( auto& reporterish : m_reporterLikes ) {
10604+            reporterish->testCaseStarting( testInfo );
10605+        }
10606+    }
10607+
10608+    void
10609+    MultiReporter::testCasePartialStarting( TestCaseInfo const& testInfo,
10610+                                                uint64_t partNumber ) {
10611+        for ( auto& reporterish : m_reporterLikes ) {
10612+            reporterish->testCasePartialStarting( testInfo, partNumber );
10613+        }
10614+    }
10615+
10616+    void MultiReporter::sectionStarting( SectionInfo const& sectionInfo ) {
10617+        for ( auto& reporterish : m_reporterLikes ) {
10618+            reporterish->sectionStarting( sectionInfo );
10619+        }
10620+    }
10621+
10622+    void MultiReporter::assertionStarting( AssertionInfo const& assertionInfo ) {
10623+        for ( auto& reporterish : m_reporterLikes ) {
10624+            reporterish->assertionStarting( assertionInfo );
10625+        }
10626+    }
10627+
10628+    void MultiReporter::assertionEnded( AssertionStats const& assertionStats ) {
10629+        const bool reportByDefault =
10630+            assertionStats.assertionResult.getResultType() != ResultWas::Ok ||
10631+            m_config->includeSuccessfulResults();
10632+
10633+        for ( auto & reporterish : m_reporterLikes ) {
10634+            if ( reportByDefault ||
10635+                 reporterish->getPreferences().shouldReportAllAssertions ) {
10636+                    reporterish->assertionEnded( assertionStats );
10637+            }
10638+        }
10639+    }
10640+
10641+    void MultiReporter::sectionEnded( SectionStats const& sectionStats ) {
10642+        for ( auto& reporterish : m_reporterLikes ) {
10643+            reporterish->sectionEnded( sectionStats );
10644+        }
10645+    }
10646+
10647+    void MultiReporter::testCasePartialEnded( TestCaseStats const& testStats,
10648+                                                  uint64_t partNumber ) {
10649+        if ( m_preferences.shouldRedirectStdOut &&
10650+             m_haveNoncapturingReporters ) {
10651+            if ( !testStats.stdOut.empty() ) {
10652+                Catch::cout() << testStats.stdOut << std::flush;
10653+            }
10654+            if ( !testStats.stdErr.empty() ) {
10655+                Catch::cerr() << testStats.stdErr << std::flush;
10656+            }
10657+        }
10658+
10659+        for ( auto& reporterish : m_reporterLikes ) {
10660+            reporterish->testCasePartialEnded( testStats, partNumber );
10661+        }
10662+    }
10663+
10664+    void MultiReporter::testCaseEnded( TestCaseStats const& testCaseStats ) {
10665+        for ( auto& reporterish : m_reporterLikes ) {
10666+            reporterish->testCaseEnded( testCaseStats );
10667+        }
10668+    }
10669+
10670+    void MultiReporter::testRunEnded( TestRunStats const& testRunStats ) {
10671+        for ( auto& reporterish : m_reporterLikes ) {
10672+            reporterish->testRunEnded( testRunStats );
10673+        }
10674+    }
10675+
10676+
10677+    void MultiReporter::skipTest( TestCaseInfo const& testInfo ) {
10678+        for ( auto& reporterish : m_reporterLikes ) {
10679+            reporterish->skipTest( testInfo );
10680+        }
10681+    }
10682+
10683+    void MultiReporter::listReporters(std::vector<ReporterDescription> const& descriptions) {
10684+        for (auto& reporterish : m_reporterLikes) {
10685+            reporterish->listReporters(descriptions);
10686+        }
10687+    }
10688+
10689+    void MultiReporter::listListeners(
10690+        std::vector<ListenerDescription> const& descriptions ) {
10691+        for ( auto& reporterish : m_reporterLikes ) {
10692+            reporterish->listListeners( descriptions );
10693+        }
10694+    }
10695+
10696+    void MultiReporter::listTests(std::vector<TestCaseHandle> const& tests) {
10697+        for (auto& reporterish : m_reporterLikes) {
10698+            reporterish->listTests(tests);
10699+        }
10700+    }
10701+
10702+    void MultiReporter::listTags(std::vector<TagInfo> const& tags) {
10703+        for (auto& reporterish : m_reporterLikes) {
10704+            reporterish->listTags(tags);
10705+        }
10706+    }
10707+
10708+} // end namespace Catch
10709+
10710+
10711+
10712+
10713+
10714+namespace Catch {
10715+    namespace Detail {
10716+
10717+        void registerReporterImpl( std::string const& name,
10718+                                   IReporterFactoryPtr reporterPtr ) {
10719+            CATCH_TRY {
10720+                getMutableRegistryHub().registerReporter(
10721+                    name, CATCH_MOVE( reporterPtr ) );
10722+            }
10723+            CATCH_CATCH_ALL {
10724+                // Do not throw when constructing global objects, instead
10725+                // register the exception to be processed later
10726+                getMutableRegistryHub().registerStartupException();
10727+            }
10728+        }
10729+
10730+        void registerListenerImpl( Detail::unique_ptr<EventListenerFactory> listenerFactory ) {
10731+            getMutableRegistryHub().registerListener( CATCH_MOVE(listenerFactory) );
10732+        }
10733+
10734+
10735+    } // namespace Detail
10736+} // namespace Catch
10737+
10738+
10739+
10740+
10741+#include <map>
10742+
10743+namespace Catch {
10744+
10745+    namespace {
10746+        std::string createMetadataString(IConfig const& config) {
10747+            ReusableStringStream sstr;
10748+            if ( config.testSpec().hasFilters() ) {
10749+                sstr << "filters='"
10750+                         << config.testSpec()
10751+                         << "' ";
10752+            }
10753+            sstr << "rng-seed=" << config.rngSeed();
10754+            return sstr.str();
10755+        }
10756+    }
10757+
10758+    void SonarQubeReporter::testRunStarting(TestRunInfo const& testRunInfo) {
10759+        CumulativeReporterBase::testRunStarting(testRunInfo);
10760+
10761+        xml.writeComment( createMetadataString( *m_config ) );
10762+        xml.startElement("testExecutions");
10763+        xml.writeAttribute("version"_sr, '1');
10764+    }
10765+
10766+    void SonarQubeReporter::writeRun( TestRunNode const& runNode ) {
10767+        std::map<StringRef, std::vector<TestCaseNode const*>> testsPerFile;
10768+
10769+        for ( auto const& child : runNode.children ) {
10770+            testsPerFile[child->value.testInfo->lineInfo.file].push_back(
10771+                child.get() );
10772+        }
10773+
10774+        for ( auto const& kv : testsPerFile ) {
10775+            writeTestFile( kv.first, kv.second );
10776+        }
10777+    }
10778+
10779+    void SonarQubeReporter::writeTestFile(StringRef filename, std::vector<TestCaseNode const*> const& testCaseNodes) {
10780+        XmlWriter::ScopedElement e = xml.scopedElement("file");
10781+        xml.writeAttribute("path"_sr, filename);
10782+
10783+        for (auto const& child : testCaseNodes)
10784+            writeTestCase(*child);
10785+    }
10786+
10787+    void SonarQubeReporter::writeTestCase(TestCaseNode const& testCaseNode) {
10788+        // All test cases have exactly one section - which represents the
10789+        // test case itself. That section may have 0-n nested sections
10790+        assert(testCaseNode.children.size() == 1);
10791+        SectionNode const& rootSection = *testCaseNode.children.front();
10792+        writeSection("", rootSection, testCaseNode.value.testInfo->okToFail());
10793+    }
10794+
10795+    void SonarQubeReporter::writeSection(std::string const& rootName, SectionNode const& sectionNode, bool okToFail) {
10796+        std::string name = trim(sectionNode.stats.sectionInfo.name);
10797+        if (!rootName.empty())
10798+            name = rootName + '/' + name;
10799+
10800+        if ( sectionNode.hasAnyAssertions()
10801+            || !sectionNode.stdOut.empty()
10802+            ||  !sectionNode.stdErr.empty() ) {
10803+            XmlWriter::ScopedElement e = xml.scopedElement("testCase");
10804+            xml.writeAttribute("name"_sr, name);
10805+            xml.writeAttribute("duration"_sr, static_cast<long>(sectionNode.stats.durationInSeconds * 1000));
10806+
10807+            writeAssertions(sectionNode, okToFail);
10808+        }
10809+
10810+        for (auto const& childNode : sectionNode.childSections)
10811+            writeSection(name, *childNode, okToFail);
10812+    }
10813+
10814+    void SonarQubeReporter::writeAssertions(SectionNode const& sectionNode, bool okToFail) {
10815+        for (auto const& assertionOrBenchmark : sectionNode.assertionsAndBenchmarks) {
10816+            if (assertionOrBenchmark.isAssertion()) {
10817+                writeAssertion(assertionOrBenchmark.asAssertion(), okToFail);
10818+            }
10819+        }
10820+    }
10821+
10822+    void SonarQubeReporter::writeAssertion(AssertionStats const& stats, bool okToFail) {
10823+        AssertionResult const& result = stats.assertionResult;
10824+        if ( !result.isOk() ||
10825+             result.getResultType() == ResultWas::ExplicitSkip ) {
10826+            std::string elementName;
10827+            if (okToFail) {
10828+                elementName = "skipped";
10829+            } else {
10830+                switch (result.getResultType()) {
10831+                case ResultWas::ThrewException:
10832+                case ResultWas::FatalErrorCondition:
10833+                    elementName = "error";
10834+                    break;
10835+                case ResultWas::ExplicitFailure:
10836+                case ResultWas::ExpressionFailed:
10837+                case ResultWas::DidntThrowException:
10838+                    elementName = "failure";
10839+                    break;
10840+                case ResultWas::ExplicitSkip:
10841+                    elementName = "skipped";
10842+                    break;
10843+                    // We should never see these here:
10844+                case ResultWas::Info:
10845+                case ResultWas::Warning:
10846+                case ResultWas::Ok:
10847+                case ResultWas::Unknown:
10848+                case ResultWas::FailureBit:
10849+                case ResultWas::Exception:
10850+                    elementName = "internalError";
10851+                    break;
10852+                }
10853+            }
10854+
10855+            XmlWriter::ScopedElement e = xml.scopedElement(elementName);
10856+
10857+            ReusableStringStream messageRss;
10858+            messageRss << result.getTestMacroName() << '(' << result.getExpression() << ')';
10859+            xml.writeAttribute("message"_sr, messageRss.str());
10860+
10861+            ReusableStringStream textRss;
10862+            if ( result.getResultType() == ResultWas::ExplicitSkip ) {
10863+                textRss << "SKIPPED\n";
10864+            } else {
10865+                textRss << "FAILED:\n";
10866+                if (result.hasExpression()) {
10867+                    textRss << '\t' << result.getExpressionInMacro() << '\n';
10868+                }
10869+                if (result.hasExpandedExpression()) {
10870+                    textRss << "with expansion:\n\t" << result.getExpandedExpression() << '\n';
10871+                }
10872+            }
10873+
10874+            if (result.hasMessage())
10875+                textRss << result.getMessage() << '\n';
10876+
10877+            for (auto const& msg : stats.infoMessages)
10878+                if (msg.type == ResultWas::Info)
10879+                    textRss << msg.message << '\n';
10880+
10881+            textRss << "at " << result.getSourceInfo();
10882+            xml.writeText(textRss.str(), XmlFormatting::Newline);
10883+        }
10884+    }
10885+
10886+} // end namespace Catch
10887+
10888+
10889+
10890+namespace Catch {
10891+
10892+    StreamingReporterBase::~StreamingReporterBase() = default;
10893+
10894+    void
10895+    StreamingReporterBase::testRunStarting( TestRunInfo const& _testRunInfo ) {
10896+        currentTestRunInfo = _testRunInfo;
10897+    }
10898+
10899+    void StreamingReporterBase::testRunEnded( TestRunStats const& ) {
10900+        currentTestCaseInfo = nullptr;
10901+    }
10902+
10903+} // end namespace Catch
10904+
10905+
10906+
10907+#include <algorithm>
10908+#include <ostream>
10909+
10910+namespace Catch {
10911+
10912+    namespace {
10913+        // Yes, this has to be outside the class and namespaced by naming.
10914+        // Making older compiler happy is hard.
10915+        static constexpr StringRef tapFailedString = "not ok"_sr;
10916+        static constexpr StringRef tapPassedString = "ok"_sr;
10917+        static constexpr Colour::Code tapDimColour = Colour::FileName;
10918+
10919+        class TapAssertionPrinter {
10920+        public:
10921+            TapAssertionPrinter& operator= (TapAssertionPrinter const&) = delete;
10922+            TapAssertionPrinter(TapAssertionPrinter const&) = delete;
10923+            TapAssertionPrinter(std::ostream& _stream, AssertionStats const& _stats, std::size_t _counter, ColourImpl* colour_)
10924+                : stream(_stream)
10925+                , result(_stats.assertionResult)
10926+                , messages(_stats.infoMessages)
10927+                , itMessage(_stats.infoMessages.begin())
10928+                , printInfoMessages(true)
10929+                , counter(_counter)
10930+                , colourImpl( colour_ ) {}
10931+
10932+            void print() {
10933+                itMessage = messages.begin();
10934+
10935+                switch (result.getResultType()) {
10936+                case ResultWas::Ok:
10937+                    printResultType(tapPassedString);
10938+                    printOriginalExpression();
10939+                    printReconstructedExpression();
10940+                    if (!result.hasExpression())
10941+                        printRemainingMessages(Colour::None);
10942+                    else
10943+                        printRemainingMessages();
10944+                    break;
10945+                case ResultWas::ExpressionFailed:
10946+                    if (result.isOk()) {
10947+                        printResultType(tapPassedString);
10948+                    } else {
10949+                        printResultType(tapFailedString);
10950+                    }
10951+                    printOriginalExpression();
10952+                    printReconstructedExpression();
10953+                    if (result.isOk()) {
10954+                        printIssue(" # TODO");
10955+                    }
10956+                    printRemainingMessages();
10957+                    break;
10958+                case ResultWas::ThrewException:
10959+                    printResultType(tapFailedString);
10960+                    printIssue("unexpected exception with message:"_sr);
10961+                    printMessage();
10962+                    printExpressionWas();
10963+                    printRemainingMessages();
10964+                    break;
10965+                case ResultWas::FatalErrorCondition:
10966+                    printResultType(tapFailedString);
10967+                    printIssue("fatal error condition with message:"_sr);
10968+                    printMessage();
10969+                    printExpressionWas();
10970+                    printRemainingMessages();
10971+                    break;
10972+                case ResultWas::DidntThrowException:
10973+                    printResultType(tapFailedString);
10974+                    printIssue("expected exception, got none"_sr);
10975+                    printExpressionWas();
10976+                    printRemainingMessages();
10977+                    break;
10978+                case ResultWas::Info:
10979+                    printResultType("info"_sr);
10980+                    printMessage();
10981+                    printRemainingMessages();
10982+                    break;
10983+                case ResultWas::Warning:
10984+                    printResultType("warning"_sr);
10985+                    printMessage();
10986+                    printRemainingMessages();
10987+                    break;
10988+                case ResultWas::ExplicitFailure:
10989+                    printResultType(tapFailedString);
10990+                    printIssue("explicitly"_sr);
10991+                    printRemainingMessages(Colour::None);
10992+                    break;
10993+                case ResultWas::ExplicitSkip:
10994+                    printResultType(tapPassedString);
10995+                    printIssue(" # SKIP"_sr);
10996+                    printMessage();
10997+                    printRemainingMessages();
10998+                    break;
10999+                    // These cases are here to prevent compiler warnings
11000+                case ResultWas::Unknown:
11001+                case ResultWas::FailureBit:
11002+                case ResultWas::Exception:
11003+                    printResultType("** internal error **"_sr);
11004+                    break;
11005+                }
11006+            }
11007+
11008+        private:
11009+            void printResultType(StringRef passOrFail) const {
11010+                if (!passOrFail.empty()) {
11011+                    stream << passOrFail << ' ' << counter << " -";
11012+                }
11013+            }
11014+
11015+            void printIssue(StringRef issue) const {
11016+                stream << ' ' << issue;
11017+            }
11018+
11019+            void printExpressionWas() {
11020+                if (result.hasExpression()) {
11021+                    stream << ';';
11022+                    stream << colourImpl->guardColour( tapDimColour )
11023+                           << " expression was:";
11024+                    printOriginalExpression();
11025+                }
11026+            }
11027+
11028+            void printOriginalExpression() const {
11029+                if (result.hasExpression()) {
11030+                    stream << ' ' << result.getExpression();
11031+                }
11032+            }
11033+
11034+            void printReconstructedExpression() const {
11035+                if (result.hasExpandedExpression()) {
11036+                    stream << colourImpl->guardColour( tapDimColour ) << " for: ";
11037+
11038+                    std::string expr = result.getExpandedExpression();
11039+                    std::replace(expr.begin(), expr.end(), '\n', ' ');
11040+                    stream << expr;
11041+                }
11042+            }
11043+
11044+            void printMessage() {
11045+                if (itMessage != messages.end()) {
11046+                    stream << " '" << itMessage->message << '\'';
11047+                    ++itMessage;
11048+                }
11049+            }
11050+
11051+            void printRemainingMessages(Colour::Code colour = tapDimColour) {
11052+                if (itMessage == messages.end()) {
11053+                    return;
11054+                }
11055+
11056+                // using messages.end() directly (or auto) yields compilation error:
11057+                std::vector<MessageInfo>::const_iterator itEnd = messages.end();
11058+                const std::size_t N = static_cast<std::size_t>(itEnd - itMessage);
11059+
11060+                stream << colourImpl->guardColour( colour ) << " with "
11061+                       << pluralise( N, "message"_sr ) << ':';
11062+
11063+                for (; itMessage != itEnd; ) {
11064+                    // If this assertion is a warning ignore any INFO messages
11065+                    if (printInfoMessages || itMessage->type != ResultWas::Info) {
11066+                        stream << " '" << itMessage->message << '\'';
11067+                        if (++itMessage != itEnd) {
11068+                            stream << colourImpl->guardColour(tapDimColour) << " and";
11069+                        }
11070+                    }
11071+                }
11072+            }
11073+
11074+        private:
11075+            std::ostream& stream;
11076+            AssertionResult const& result;
11077+            std::vector<MessageInfo> const& messages;
11078+            std::vector<MessageInfo>::const_iterator itMessage;
11079+            bool printInfoMessages;
11080+            std::size_t counter;
11081+            ColourImpl* colourImpl;
11082+        };
11083+
11084+    } // End anonymous namespace
11085+
11086+    void TAPReporter::testRunStarting( TestRunInfo const& ) {
11087+        if ( m_config->testSpec().hasFilters() ) {
11088+            m_stream << "# filters: " << m_config->testSpec() << '\n';
11089+        }
11090+        m_stream << "# rng-seed: " << m_config->rngSeed() << '\n';
11091+    }
11092+
11093+    void TAPReporter::noMatchingTestCases( StringRef unmatchedSpec ) {
11094+        m_stream << "# No test cases matched '" << unmatchedSpec << "'\n";
11095+    }
11096+
11097+    void TAPReporter::assertionEnded(AssertionStats const& _assertionStats) {
11098+        ++counter;
11099+
11100+        m_stream << "# " << currentTestCaseInfo->name << '\n';
11101+        TapAssertionPrinter printer(m_stream, _assertionStats, counter, m_colour.get());
11102+        printer.print();
11103+
11104+        m_stream << '\n' << std::flush;
11105+    }
11106+
11107+    void TAPReporter::testRunEnded(TestRunStats const& _testRunStats) {
11108+        m_stream << "1.." << _testRunStats.totals.assertions.total();
11109+        if (_testRunStats.totals.testCases.total() == 0) {
11110+            m_stream << " # Skipped: No tests ran.";
11111+        }
11112+        m_stream << "\n\n" << std::flush;
11113+        StreamingReporterBase::testRunEnded(_testRunStats);
11114+    }
11115+
11116+
11117+
11118+
11119+} // end namespace Catch
11120+
11121+
11122+
11123+
11124+#include <cassert>
11125+#include <ostream>
11126+
11127+namespace Catch {
11128+
11129+    namespace {
11130+        // if string has a : in first line will set indent to follow it on
11131+        // subsequent lines
11132+        void printHeaderString(std::ostream& os, std::string const& _string, std::size_t indent = 0) {
11133+            std::size_t i = _string.find(": ");
11134+            if (i != std::string::npos)
11135+                i += 2;
11136+            else
11137+                i = 0;
11138+            os << TextFlow::Column(_string)
11139+                  .indent(indent + i)
11140+                  .initialIndent(indent) << '\n';
11141+        }
11142+
11143+        std::string escape(StringRef str) {
11144+            std::string escaped = static_cast<std::string>(str);
11145+            replaceInPlace(escaped, "|", "||");
11146+            replaceInPlace(escaped, "'", "|'");
11147+            replaceInPlace(escaped, "\n", "|n");
11148+            replaceInPlace(escaped, "\r", "|r");
11149+            replaceInPlace(escaped, "[", "|[");
11150+            replaceInPlace(escaped, "]", "|]");
11151+            return escaped;
11152+        }
11153+    } // end anonymous namespace
11154+
11155+
11156+    TeamCityReporter::~TeamCityReporter() = default;
11157+
11158+    void TeamCityReporter::testRunStarting( TestRunInfo const& runInfo ) {
11159+        m_stream << "##teamcity[testSuiteStarted name='" << escape( runInfo.name )
11160+               << "']\n";
11161+    }
11162+
11163+    void TeamCityReporter::testRunEnded( TestRunStats const& runStats ) {
11164+        m_stream << "##teamcity[testSuiteFinished name='"
11165+               << escape( runStats.runInfo.name ) << "']\n";
11166+    }
11167+
11168+    void TeamCityReporter::assertionEnded(AssertionStats const& assertionStats) {
11169+        AssertionResult const& result = assertionStats.assertionResult;
11170+        if ( !result.isOk() ||
11171+             result.getResultType() == ResultWas::ExplicitSkip ) {
11172+
11173+            ReusableStringStream msg;
11174+            if (!m_headerPrintedForThisSection)
11175+                printSectionHeader(msg.get());
11176+            m_headerPrintedForThisSection = true;
11177+
11178+            msg << result.getSourceInfo() << '\n';
11179+
11180+            switch (result.getResultType()) {
11181+            case ResultWas::ExpressionFailed:
11182+                msg << "expression failed";
11183+                break;
11184+            case ResultWas::ThrewException:
11185+                msg << "unexpected exception";
11186+                break;
11187+            case ResultWas::FatalErrorCondition:
11188+                msg << "fatal error condition";
11189+                break;
11190+            case ResultWas::DidntThrowException:
11191+                msg << "no exception was thrown where one was expected";
11192+                break;
11193+            case ResultWas::ExplicitFailure:
11194+                msg << "explicit failure";
11195+                break;
11196+            case ResultWas::ExplicitSkip:
11197+                msg << "explicit skip";
11198+                break;
11199+
11200+                // We shouldn't get here because of the isOk() test
11201+            case ResultWas::Ok:
11202+            case ResultWas::Info:
11203+            case ResultWas::Warning:
11204+                CATCH_ERROR("Internal error in TeamCity reporter");
11205+                // These cases are here to prevent compiler warnings
11206+            case ResultWas::Unknown:
11207+            case ResultWas::FailureBit:
11208+            case ResultWas::Exception:
11209+                CATCH_ERROR("Not implemented");
11210+            }
11211+            if (assertionStats.infoMessages.size() == 1)
11212+                msg << " with message:";
11213+            if (assertionStats.infoMessages.size() > 1)
11214+                msg << " with messages:";
11215+            for (auto const& messageInfo : assertionStats.infoMessages)
11216+                msg << "\n  \"" << messageInfo.message << '"';
11217+
11218+
11219+            if (result.hasExpression()) {
11220+                msg <<
11221+                    "\n  " << result.getExpressionInMacro() << "\n"
11222+                    "with expansion:\n"
11223+                    "  " << result.getExpandedExpression() << '\n';
11224+            }
11225+
11226+            if ( result.getResultType() == ResultWas::ExplicitSkip ) {
11227+                m_stream << "##teamcity[testIgnored";
11228+            } else if ( currentTestCaseInfo->okToFail() ) {
11229+                msg << "- failure ignore as test marked as 'ok to fail'\n";
11230+                m_stream << "##teamcity[testIgnored";
11231+            } else {
11232+                m_stream << "##teamcity[testFailed";
11233+            }
11234+            m_stream << " name='" << escape( currentTestCaseInfo->name ) << '\''
11235+                     << " message='" << escape( msg.str() ) << '\'' << "]\n";
11236+        }
11237+        m_stream.flush();
11238+    }
11239+
11240+    void TeamCityReporter::testCaseStarting(TestCaseInfo const& testInfo) {
11241+        m_testTimer.start();
11242+        StreamingReporterBase::testCaseStarting(testInfo);
11243+        m_stream << "##teamcity[testStarted name='"
11244+            << escape(testInfo.name) << "']\n";
11245+        m_stream.flush();
11246+    }
11247+
11248+    void TeamCityReporter::testCaseEnded(TestCaseStats const& testCaseStats) {
11249+        StreamingReporterBase::testCaseEnded(testCaseStats);
11250+        auto const& testCaseInfo = *testCaseStats.testInfo;
11251+        if (!testCaseStats.stdOut.empty())
11252+            m_stream << "##teamcity[testStdOut name='"
11253+            << escape(testCaseInfo.name)
11254+            << "' out='" << escape(testCaseStats.stdOut) << "']\n";
11255+        if (!testCaseStats.stdErr.empty())
11256+            m_stream << "##teamcity[testStdErr name='"
11257+            << escape(testCaseInfo.name)
11258+            << "' out='" << escape(testCaseStats.stdErr) << "']\n";
11259+        m_stream << "##teamcity[testFinished name='"
11260+            << escape(testCaseInfo.name) << "' duration='"
11261+            << m_testTimer.getElapsedMilliseconds() << "']\n";
11262+        m_stream.flush();
11263+    }
11264+
11265+    void TeamCityReporter::printSectionHeader(std::ostream& os) {
11266+        assert(!m_sectionStack.empty());
11267+
11268+        if (m_sectionStack.size() > 1) {
11269+            os << lineOfChars('-') << '\n';
11270+
11271+            std::vector<SectionInfo>::const_iterator
11272+                it = m_sectionStack.begin() + 1, // Skip first section (test case)
11273+                itEnd = m_sectionStack.end();
11274+            for (; it != itEnd; ++it)
11275+                printHeaderString(os, it->name);
11276+            os << lineOfChars('-') << '\n';
11277+        }
11278+
11279+        SourceLineInfo lineInfo = m_sectionStack.front().lineInfo;
11280+
11281+        os << lineInfo << '\n';
11282+        os << lineOfChars('.') << "\n\n";
11283+    }
11284+
11285+} // end namespace Catch
11286+
11287+
11288+
11289+
11290+#if defined(_MSC_VER)
11291+#pragma warning(push)
11292+#pragma warning(disable:4061) // Not all labels are EXPLICITLY handled in switch
11293+                              // Note that 4062 (not all labels are handled
11294+                              // and default is missing) is enabled
11295+#endif
11296+
11297+namespace Catch {
11298+    XmlReporter::XmlReporter( ReporterConfig&& _config )
11299+    :   StreamingReporterBase( CATCH_MOVE(_config) ),
11300+        m_xml(m_stream)
11301+    {
11302+        m_preferences.shouldRedirectStdOut = true;
11303+        m_preferences.shouldReportAllAssertions = true;
11304+    }
11305+
11306+    XmlReporter::~XmlReporter() = default;
11307+
11308+    std::string XmlReporter::getDescription() {
11309+        return "Reports test results as an XML document";
11310+    }
11311+
11312+    std::string XmlReporter::getStylesheetRef() const {
11313+        return std::string();
11314+    }
11315+
11316+    void XmlReporter::writeSourceInfo( SourceLineInfo const& sourceInfo ) {
11317+        m_xml
11318+            .writeAttribute( "filename"_sr, sourceInfo.file )
11319+            .writeAttribute( "line"_sr, sourceInfo.line );
11320+    }
11321+
11322+    void XmlReporter::testRunStarting( TestRunInfo const& testInfo ) {
11323+        StreamingReporterBase::testRunStarting( testInfo );
11324+        std::string stylesheetRef = getStylesheetRef();
11325+        if( !stylesheetRef.empty() )
11326+            m_xml.writeStylesheetRef( stylesheetRef );
11327+        m_xml.startElement("Catch2TestRun")
11328+             .writeAttribute("name"_sr, m_config->name())
11329+             .writeAttribute("rng-seed"_sr, m_config->rngSeed())
11330+             .writeAttribute("xml-format-version"_sr, 3)
11331+             .writeAttribute("catch2-version"_sr, libraryVersion());
11332+        if ( m_config->testSpec().hasFilters() ) {
11333+            m_xml.writeAttribute( "filters"_sr, m_config->testSpec() );
11334+        }
11335+    }
11336+
11337+    void XmlReporter::testCaseStarting( TestCaseInfo const& testInfo ) {
11338+        StreamingReporterBase::testCaseStarting(testInfo);
11339+        m_xml.startElement( "TestCase" )
11340+            .writeAttribute( "name"_sr, trim( StringRef(testInfo.name) ) )
11341+            .writeAttribute( "tags"_sr, testInfo.tagsAsString() );
11342+
11343+        writeSourceInfo( testInfo.lineInfo );
11344+
11345+        if ( m_config->showDurations() == ShowDurations::Always )
11346+            m_testCaseTimer.start();
11347+        m_xml.ensureTagClosed();
11348+    }
11349+
11350+    void XmlReporter::sectionStarting( SectionInfo const& sectionInfo ) {
11351+        StreamingReporterBase::sectionStarting( sectionInfo );
11352+        if( m_sectionDepth++ > 0 ) {
11353+            m_xml.startElement( "Section" )
11354+                .writeAttribute( "name"_sr, trim( StringRef(sectionInfo.name) ) );
11355+            writeSourceInfo( sectionInfo.lineInfo );
11356+            m_xml.ensureTagClosed();
11357+        }
11358+    }
11359+
11360+    void XmlReporter::assertionStarting( AssertionInfo const& ) { }
11361+
11362+    void XmlReporter::assertionEnded( AssertionStats const& assertionStats ) {
11363+
11364+        AssertionResult const& result = assertionStats.assertionResult;
11365+
11366+        bool includeResults = m_config->includeSuccessfulResults() || !result.isOk();
11367+
11368+        if( includeResults || result.getResultType() == ResultWas::Warning ) {
11369+            // Print any info messages in <Info> tags.
11370+            for( auto const& msg : assertionStats.infoMessages ) {
11371+                if( msg.type == ResultWas::Info && includeResults ) {
11372+                    auto t = m_xml.scopedElement( "Info" );
11373+                    writeSourceInfo( msg.lineInfo );
11374+                    t.writeText( msg.message );
11375+                } else if ( msg.type == ResultWas::Warning ) {
11376+                    auto t = m_xml.scopedElement( "Warning" );
11377+                    writeSourceInfo( msg.lineInfo );
11378+                    t.writeText( msg.message );
11379+                }
11380+            }
11381+        }
11382+
11383+        // Drop out if result was successful but we're not printing them.
11384+        if ( !includeResults && result.getResultType() != ResultWas::Warning &&
11385+             result.getResultType() != ResultWas::ExplicitSkip ) {
11386+            return;
11387+        }
11388+
11389+        // Print the expression if there is one.
11390+        if( result.hasExpression() ) {
11391+            m_xml.startElement( "Expression" )
11392+                .writeAttribute( "success"_sr, result.succeeded() )
11393+                .writeAttribute( "type"_sr, result.getTestMacroName() );
11394+
11395+            writeSourceInfo( result.getSourceInfo() );
11396+
11397+            m_xml.scopedElement( "Original" )
11398+                .writeText( result.getExpression() );
11399+            m_xml.scopedElement( "Expanded" )
11400+                .writeText( result.getExpandedExpression() );
11401+        }
11402+
11403+        // And... Print a result applicable to each result type.
11404+        switch( result.getResultType() ) {
11405+            case ResultWas::ThrewException:
11406+                m_xml.startElement( "Exception" );
11407+                writeSourceInfo( result.getSourceInfo() );
11408+                m_xml.writeText( result.getMessage() );
11409+                m_xml.endElement();
11410+                break;
11411+            case ResultWas::FatalErrorCondition:
11412+                m_xml.startElement( "FatalErrorCondition" );
11413+                writeSourceInfo( result.getSourceInfo() );
11414+                m_xml.writeText( result.getMessage() );
11415+                m_xml.endElement();
11416+                break;
11417+            case ResultWas::Info:
11418+                m_xml.scopedElement( "Info" )
11419+                     .writeText( result.getMessage() );
11420+                break;
11421+            case ResultWas::Warning:
11422+                // Warning will already have been written
11423+                break;
11424+            case ResultWas::ExplicitFailure:
11425+                m_xml.startElement( "Failure" );
11426+                writeSourceInfo( result.getSourceInfo() );
11427+                m_xml.writeText( result.getMessage() );
11428+                m_xml.endElement();
11429+                break;
11430+            case ResultWas::ExplicitSkip:
11431+                m_xml.startElement( "Skip" );
11432+                writeSourceInfo( result.getSourceInfo() );
11433+                m_xml.writeText( result.getMessage() );
11434+                m_xml.endElement();
11435+                break;
11436+            default:
11437+                break;
11438+        }
11439+
11440+        if( result.hasExpression() )
11441+            m_xml.endElement();
11442+    }
11443+
11444+    void XmlReporter::sectionEnded( SectionStats const& sectionStats ) {
11445+        StreamingReporterBase::sectionEnded( sectionStats );
11446+        if ( --m_sectionDepth > 0 ) {
11447+            {
11448+                XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResults" );
11449+                e.writeAttribute( "successes"_sr, sectionStats.assertions.passed );
11450+                e.writeAttribute( "failures"_sr, sectionStats.assertions.failed );
11451+                e.writeAttribute( "expectedFailures"_sr, sectionStats.assertions.failedButOk );
11452+                e.writeAttribute( "skipped"_sr, sectionStats.assertions.skipped > 0 );
11453+
11454+                if ( m_config->showDurations() == ShowDurations::Always )
11455+                    e.writeAttribute( "durationInSeconds"_sr, sectionStats.durationInSeconds );
11456+            }
11457+            // Ends assertion tag
11458+            m_xml.endElement();
11459+        }
11460+    }
11461+
11462+    void XmlReporter::testCaseEnded( TestCaseStats const& testCaseStats ) {
11463+        StreamingReporterBase::testCaseEnded( testCaseStats );
11464+        XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResult" );
11465+        e.writeAttribute( "success"_sr, testCaseStats.totals.assertions.allOk() );
11466+        e.writeAttribute( "skips"_sr, testCaseStats.totals.assertions.skipped );
11467+
11468+        if ( m_config->showDurations() == ShowDurations::Always )
11469+            e.writeAttribute( "durationInSeconds"_sr, m_testCaseTimer.getElapsedSeconds() );
11470+        if( !testCaseStats.stdOut.empty() )
11471+            m_xml.scopedElement( "StdOut" ).writeText( trim( StringRef(testCaseStats.stdOut) ), XmlFormatting::Newline );
11472+        if( !testCaseStats.stdErr.empty() )
11473+            m_xml.scopedElement( "StdErr" ).writeText( trim( StringRef(testCaseStats.stdErr) ), XmlFormatting::Newline );
11474+
11475+        m_xml.endElement();
11476+    }
11477+
11478+    void XmlReporter::testRunEnded( TestRunStats const& testRunStats ) {
11479+        StreamingReporterBase::testRunEnded( testRunStats );
11480+        m_xml.scopedElement( "OverallResults" )
11481+            .writeAttribute( "successes"_sr, testRunStats.totals.assertions.passed )
11482+            .writeAttribute( "failures"_sr, testRunStats.totals.assertions.failed )
11483+            .writeAttribute( "expectedFailures"_sr, testRunStats.totals.assertions.failedButOk )
11484+            .writeAttribute( "skips"_sr, testRunStats.totals.assertions.skipped );
11485+        m_xml.scopedElement( "OverallResultsCases")
11486+            .writeAttribute( "successes"_sr, testRunStats.totals.testCases.passed )
11487+            .writeAttribute( "failures"_sr, testRunStats.totals.testCases.failed )
11488+            .writeAttribute( "expectedFailures"_sr, testRunStats.totals.testCases.failedButOk )
11489+            .writeAttribute( "skips"_sr, testRunStats.totals.testCases.skipped );
11490+        m_xml.endElement();
11491+    }
11492+
11493+    void XmlReporter::benchmarkPreparing( StringRef name ) {
11494+        m_xml.startElement("BenchmarkResults")
11495+             .writeAttribute("name"_sr, name);
11496+    }
11497+
11498+    void XmlReporter::benchmarkStarting(BenchmarkInfo const &info) {
11499+        m_xml.writeAttribute("samples"_sr, info.samples)
11500+            .writeAttribute("resamples"_sr, info.resamples)
11501+            .writeAttribute("iterations"_sr, info.iterations)
11502+            .writeAttribute("clockResolution"_sr, info.clockResolution)
11503+            .writeAttribute("estimatedDuration"_sr, info.estimatedDuration)
11504+            .writeComment("All values in nano seconds"_sr);
11505+    }
11506+
11507+    void XmlReporter::benchmarkEnded(BenchmarkStats<> const& benchmarkStats) {
11508+        m_xml.scopedElement("mean")
11509+            .writeAttribute("value"_sr, benchmarkStats.mean.point.count())
11510+            .writeAttribute("lowerBound"_sr, benchmarkStats.mean.lower_bound.count())
11511+            .writeAttribute("upperBound"_sr, benchmarkStats.mean.upper_bound.count())
11512+            .writeAttribute("ci"_sr, benchmarkStats.mean.confidence_interval);
11513+        m_xml.scopedElement("standardDeviation")
11514+            .writeAttribute("value"_sr, benchmarkStats.standardDeviation.point.count())
11515+            .writeAttribute("lowerBound"_sr, benchmarkStats.standardDeviation.lower_bound.count())
11516+            .writeAttribute("upperBound"_sr, benchmarkStats.standardDeviation.upper_bound.count())
11517+            .writeAttribute("ci"_sr, benchmarkStats.standardDeviation.confidence_interval);
11518+        m_xml.scopedElement("outliers")
11519+            .writeAttribute("variance"_sr, benchmarkStats.outlierVariance)
11520+            .writeAttribute("lowMild"_sr, benchmarkStats.outliers.low_mild)
11521+            .writeAttribute("lowSevere"_sr, benchmarkStats.outliers.low_severe)
11522+            .writeAttribute("highMild"_sr, benchmarkStats.outliers.high_mild)
11523+            .writeAttribute("highSevere"_sr, benchmarkStats.outliers.high_severe);
11524+        m_xml.endElement();
11525+    }
11526+
11527+    void XmlReporter::benchmarkFailed(StringRef error) {
11528+        m_xml.scopedElement("failed").
11529+            writeAttribute("message"_sr, error);
11530+        m_xml.endElement();
11531+    }
11532+
11533+    void XmlReporter::listReporters(std::vector<ReporterDescription> const& descriptions) {
11534+        auto outerTag = m_xml.scopedElement("AvailableReporters");
11535+        for (auto const& reporter : descriptions) {
11536+            auto inner = m_xml.scopedElement("Reporter");
11537+            m_xml.startElement("Name", XmlFormatting::Indent)
11538+                 .writeText(reporter.name, XmlFormatting::None)
11539+                 .endElement(XmlFormatting::Newline);
11540+            m_xml.startElement("Description", XmlFormatting::Indent)
11541+                 .writeText(reporter.description, XmlFormatting::None)
11542+                 .endElement(XmlFormatting::Newline);
11543+        }
11544+    }
11545+
11546+    void XmlReporter::listListeners(std::vector<ListenerDescription> const& descriptions) {
11547+        auto outerTag = m_xml.scopedElement( "RegisteredListeners" );
11548+        for ( auto const& listener : descriptions ) {
11549+            auto inner = m_xml.scopedElement( "Listener" );
11550+            m_xml.startElement( "Name", XmlFormatting::Indent )
11551+                .writeText( listener.name, XmlFormatting::None )
11552+                .endElement( XmlFormatting::Newline );
11553+            m_xml.startElement( "Description", XmlFormatting::Indent )
11554+                .writeText( listener.description, XmlFormatting::None )
11555+                .endElement( XmlFormatting::Newline );
11556+        }
11557+    }
11558+
11559+    void XmlReporter::listTests(std::vector<TestCaseHandle> const& tests) {
11560+        auto outerTag = m_xml.scopedElement("MatchingTests");
11561+        for (auto const& test : tests) {
11562+            auto innerTag = m_xml.scopedElement("TestCase");
11563+            auto const& testInfo = test.getTestCaseInfo();
11564+            m_xml.startElement("Name", XmlFormatting::Indent)
11565+                 .writeText(testInfo.name, XmlFormatting::None)
11566+                 .endElement(XmlFormatting::Newline);
11567+            m_xml.startElement("ClassName", XmlFormatting::Indent)
11568+                 .writeText(testInfo.className, XmlFormatting::None)
11569+                 .endElement(XmlFormatting::Newline);
11570+            m_xml.startElement("Tags", XmlFormatting::Indent)
11571+                 .writeText(testInfo.tagsAsString(), XmlFormatting::None)
11572+                 .endElement(XmlFormatting::Newline);
11573+
11574+            auto sourceTag = m_xml.scopedElement("SourceInfo");
11575+            m_xml.startElement("File", XmlFormatting::Indent)
11576+                 .writeText(testInfo.lineInfo.file, XmlFormatting::None)
11577+                 .endElement(XmlFormatting::Newline);
11578+            m_xml.startElement("Line", XmlFormatting::Indent)
11579+                 .writeText(std::to_string(testInfo.lineInfo.line), XmlFormatting::None)
11580+                 .endElement(XmlFormatting::Newline);
11581+        }
11582+    }
11583+
11584+    void XmlReporter::listTags(std::vector<TagInfo> const& tags) {
11585+        auto outerTag = m_xml.scopedElement("TagsFromMatchingTests");
11586+        for (auto const& tag : tags) {
11587+            auto innerTag = m_xml.scopedElement("Tag");
11588+            m_xml.startElement("Count", XmlFormatting::Indent)
11589+                 .writeText(std::to_string(tag.count), XmlFormatting::None)
11590+                 .endElement(XmlFormatting::Newline);
11591+            auto aliasTag = m_xml.scopedElement("Aliases");
11592+            for (auto const& alias : tag.spellings) {
11593+                m_xml.startElement("Alias", XmlFormatting::Indent)
11594+                     .writeText(alias, XmlFormatting::None)
11595+                     .endElement(XmlFormatting::Newline);
11596+            }
11597+        }
11598+    }
11599+
11600+} // end namespace Catch
11601+
11602+#if defined(_MSC_VER)
11603+#pragma warning(pop)
11604+#endif
11605diff --git a/tests/catch_amalgamated.hpp b/tests/catch_amalgamated.hpp
11606new file mode 100644
11607index 0000000..7e75a5d
11608--- /dev/null
11609+++ b/tests/catch_amalgamated.hpp
11610@@ -0,0 +1,13927 @@
11611+
11612+//              Copyright Catch2 Authors
11613+// Distributed under the Boost Software License, Version 1.0.
11614+//   (See accompanying file LICENSE.txt or copy at
11615+//        https://www.boost.org/LICENSE_1_0.txt)
11616+
11617+// SPDX-License-Identifier: BSL-1.0
11618+
11619+//  Catch v3.5.4
11620+//  Generated: 2024-04-10 12:03:45.785902
11621+//  ----------------------------------------------------------
11622+//  This file is an amalgamation of multiple different files.
11623+//  You probably shouldn't edit it directly.
11624+//  ----------------------------------------------------------
11625+#ifndef CATCH_AMALGAMATED_HPP_INCLUDED
11626+#define CATCH_AMALGAMATED_HPP_INCLUDED
11627+
11628+
11629+/** \file
11630+ * This is a convenience header for Catch2. It includes **all** of Catch2 headers.
11631+ *
11632+ * Generally the Catch2 users should use specific includes they need,
11633+ * but this header can be used instead for ease-of-experimentation, or
11634+ * just plain convenience, at the cost of (significantly) increased
11635+ * compilation times.
11636+ *
11637+ * When a new header is added to either the top level folder, or to the
11638+ * corresponding internal subfolder, it should be added here. Headers
11639+ * added to the various subparts (e.g. matchers, generators, etc...),
11640+ * should go their respective catch-all headers.
11641+ */
11642+
11643+#ifndef CATCH_ALL_HPP_INCLUDED
11644+#define CATCH_ALL_HPP_INCLUDED
11645+
11646+
11647+
11648+/** \file
11649+ * This is a convenience header for Catch2's benchmarking. It includes
11650+ * **all** of Catch2 headers related to benchmarking.
11651+ *
11652+ * Generally the Catch2 users should use specific includes they need,
11653+ * but this header can be used instead for ease-of-experimentation, or
11654+ * just plain convenience, at the cost of (significantly) increased
11655+ * compilation times.
11656+ *
11657+ * When a new header is added to either the `benchmark` folder, or to
11658+ * the corresponding internal (detail) subfolder, it should be added here.
11659+ */
11660+
11661+#ifndef CATCH_BENCHMARK_ALL_HPP_INCLUDED
11662+#define CATCH_BENCHMARK_ALL_HPP_INCLUDED
11663+
11664+
11665+
11666+// Adapted from donated nonius code.
11667+
11668+#ifndef CATCH_BENCHMARK_HPP_INCLUDED
11669+#define CATCH_BENCHMARK_HPP_INCLUDED
11670+
11671+
11672+
11673+#ifndef CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED
11674+#define CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED
11675+
11676+// Detect a number of compiler features - by compiler
11677+// The following features are defined:
11678+//
11679+// CATCH_CONFIG_WINDOWS_SEH : is Windows SEH supported?
11680+// CATCH_CONFIG_POSIX_SIGNALS : are POSIX signals supported?
11681+// CATCH_CONFIG_DISABLE_EXCEPTIONS : Are exceptions enabled?
11682+// ****************
11683+// Note to maintainers: if new toggles are added please document them
11684+// in configuration.md, too
11685+// ****************
11686+
11687+// In general each macro has a _NO_<feature name> form
11688+// (e.g. CATCH_CONFIG_NO_POSIX_SIGNALS) which disables the feature.
11689+// Many features, at point of detection, define an _INTERNAL_ macro, so they
11690+// can be combined, en-mass, with the _NO_ forms later.
11691+
11692+
11693+
11694+#ifndef CATCH_PLATFORM_HPP_INCLUDED
11695+#define CATCH_PLATFORM_HPP_INCLUDED
11696+
11697+// See e.g.:
11698+// https://opensource.apple.com/source/CarbonHeaders/CarbonHeaders-18.1/TargetConditionals.h.auto.html
11699+#ifdef __APPLE__
11700+#  ifndef __has_extension
11701+#    define __has_extension(x) 0
11702+#  endif
11703+#  include <TargetConditionals.h>
11704+#  if (defined(TARGET_OS_OSX) && TARGET_OS_OSX == 1) || \
11705+      (defined(TARGET_OS_MAC) && TARGET_OS_MAC == 1)
11706+#    define CATCH_PLATFORM_MAC
11707+#  elif (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE == 1)
11708+#    define CATCH_PLATFORM_IPHONE
11709+#  endif
11710+
11711+#elif defined(linux) || defined(__linux) || defined(__linux__)
11712+#  define CATCH_PLATFORM_LINUX
11713+
11714+#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || defined(__MINGW32__)
11715+#  define CATCH_PLATFORM_WINDOWS
11716+
11717+#  if defined( WINAPI_FAMILY ) && ( WINAPI_FAMILY == WINAPI_FAMILY_APP )
11718+#      define CATCH_PLATFORM_WINDOWS_UWP
11719+#  endif
11720+
11721+#elif defined(__ORBIS__) || defined(__PROSPERO__)
11722+#  define CATCH_PLATFORM_PLAYSTATION
11723+
11724+#endif
11725+
11726+#endif // CATCH_PLATFORM_HPP_INCLUDED
11727+
11728+#ifdef __cplusplus
11729+
11730+#  if (__cplusplus >= 201703L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
11731+#    define CATCH_CPP17_OR_GREATER
11732+#  endif
11733+
11734+#  if (__cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L)
11735+#    define CATCH_CPP20_OR_GREATER
11736+#  endif
11737+
11738+#endif
11739+
11740+// Only GCC compiler should be used in this block, so other compilers trying to
11741+// mask themselves as GCC should be ignored.
11742+#if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC) && !defined(__CUDACC__) && !defined(__LCC__) && !defined(__NVCOMPILER)
11743+#    define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic push" )
11744+#    define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION  _Pragma( "GCC diagnostic pop" )
11745+
11746+// This only works on GCC 9+. so we have to also add a global suppression of Wparentheses
11747+// for older versions of GCC.
11748+#    define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
11749+         _Pragma( "GCC diagnostic ignored \"-Wparentheses\"" )
11750+
11751+#    define CATCH_INTERNAL_SUPPRESS_UNUSED_RESULT \
11752+         _Pragma( "GCC diagnostic ignored \"-Wunused-result\"" )
11753+
11754+#    define CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
11755+         _Pragma( "GCC diagnostic ignored \"-Wunused-variable\"" )
11756+
11757+#    define CATCH_INTERNAL_SUPPRESS_USELESS_CAST_WARNINGS \
11758+         _Pragma( "GCC diagnostic ignored \"-Wuseless-cast\"" )
11759+
11760+#    define CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS \
11761+         _Pragma( "GCC diagnostic ignored \"-Wshadow\"" )
11762+
11763+#    define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__)
11764+
11765+#endif
11766+
11767+#if defined(__NVCOMPILER)
11768+#    define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "diag push" )
11769+#    define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION  _Pragma( "diag pop" )
11770+#    define CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS _Pragma( "diag_suppress declared_but_not_referenced" )
11771+#endif
11772+
11773+#if defined(__CUDACC__) && !defined(__clang__)
11774+#  ifdef __NVCC_DIAG_PRAGMA_SUPPORT__
11775+// New pragmas introduced in CUDA 11.5+
11776+#    define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "nv_diagnostic push" )
11777+#    define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION  _Pragma( "nv_diagnostic pop" )
11778+#    define CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS _Pragma( "nv_diag_suppress 177" )
11779+#  else
11780+#    define CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS _Pragma( "diag_suppress 177" )
11781+#  endif
11782+#endif
11783+
11784+// clang-cl defines _MSC_VER as well as __clang__, which could cause the
11785+// start/stop internal suppression macros to be double defined.
11786+#if defined(__clang__) && !defined(_MSC_VER)
11787+
11788+#    define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic push" )
11789+#    define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION  _Pragma( "clang diagnostic pop" )
11790+
11791+#endif // __clang__ && !_MSC_VER
11792+
11793+#if defined(__clang__)
11794+
11795+// As of this writing, IBM XL's implementation of __builtin_constant_p has a bug
11796+// which results in calls to destructors being emitted for each temporary,
11797+// without a matching initialization. In practice, this can result in something
11798+// like `std::string::~string` being called on an uninitialized value.
11799+//
11800+// For example, this code will likely segfault under IBM XL:
11801+// ```
11802+// REQUIRE(std::string("12") + "34" == "1234")
11803+// ```
11804+//
11805+// Similarly, NVHPC's implementation of `__builtin_constant_p` has a bug which
11806+// results in calls to the immediately evaluated lambda expressions to be
11807+// reported as unevaluated lambdas.
11808+// https://developer.nvidia.com/nvidia_bug/3321845.
11809+//
11810+// Therefore, `CATCH_INTERNAL_IGNORE_BUT_WARN` is not implemented.
11811+#  if !defined(__ibmxl__) && !defined(__CUDACC__) && !defined( __NVCOMPILER )
11812+#    define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__) /* NOLINT(cppcoreguidelines-pro-type-vararg, hicpp-vararg) */
11813+#  endif
11814+
11815+
11816+#    define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
11817+         _Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) \
11818+         _Pragma( "clang diagnostic ignored \"-Wglobal-constructors\"")
11819+
11820+#    define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
11821+         _Pragma( "clang diagnostic ignored \"-Wparentheses\"" )
11822+
11823+#    define CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
11824+         _Pragma( "clang diagnostic ignored \"-Wunused-variable\"" )
11825+
11826+#    define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
11827+         _Pragma( "clang diagnostic ignored \"-Wgnu-zero-variadic-macro-arguments\"" )
11828+
11829+#    define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
11830+         _Pragma( "clang diagnostic ignored \"-Wunused-template\"" )
11831+
11832+#    define CATCH_INTERNAL_SUPPRESS_COMMA_WARNINGS \
11833+        _Pragma( "clang diagnostic ignored \"-Wcomma\"" )
11834+
11835+#    define CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS \
11836+        _Pragma( "clang diagnostic ignored \"-Wshadow\"" )
11837+
11838+#endif // __clang__
11839+
11840+
11841+////////////////////////////////////////////////////////////////////////////////
11842+// We know some environments not to support full POSIX signals
11843+#if defined( CATCH_PLATFORM_WINDOWS ) ||                                       \
11844+    defined( CATCH_PLATFORM_PLAYSTATION ) ||                                   \
11845+    defined( __CYGWIN__ ) ||                                                   \
11846+    defined( __QNX__ ) ||                                                      \
11847+    defined( __EMSCRIPTEN__ ) ||                                               \
11848+    defined( __DJGPP__ ) ||                                                    \
11849+    defined( __OS400__ )
11850+#    define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS
11851+#else
11852+#    define CATCH_INTERNAL_CONFIG_POSIX_SIGNALS
11853+#endif
11854+
11855+////////////////////////////////////////////////////////////////////////////////
11856+// Assume that some platforms do not support getenv.
11857+#if defined( CATCH_PLATFORM_WINDOWS_UWP ) ||                                   \
11858+    defined( CATCH_PLATFORM_PLAYSTATION ) ||                                   \
11859+    defined( _GAMING_XBOX )
11860+#    define CATCH_INTERNAL_CONFIG_NO_GETENV
11861+#else
11862+#    define CATCH_INTERNAL_CONFIG_GETENV
11863+#endif
11864+
11865+////////////////////////////////////////////////////////////////////////////////
11866+// Android somehow still does not support std::to_string
11867+#if defined(__ANDROID__)
11868+#    define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING
11869+#endif
11870+
11871+////////////////////////////////////////////////////////////////////////////////
11872+// Not all Windows environments support SEH properly
11873+#if defined(__MINGW32__)
11874+#    define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH
11875+#endif
11876+
11877+////////////////////////////////////////////////////////////////////////////////
11878+// PS4
11879+#if defined(__ORBIS__)
11880+#    define CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE
11881+#endif
11882+
11883+////////////////////////////////////////////////////////////////////////////////
11884+// Cygwin
11885+#ifdef __CYGWIN__
11886+
11887+// Required for some versions of Cygwin to declare gettimeofday
11888+// see: http://stackoverflow.com/questions/36901803/gettimeofday-not-declared-in-this-scope-cygwin
11889+#   define _BSD_SOURCE
11890+// some versions of cygwin (most) do not support std::to_string. Use the libstd check.
11891+// https://gcc.gnu.org/onlinedocs/gcc-4.8.2/libstdc++/api/a01053_source.html line 2812-2813
11892+# if !((__cplusplus >= 201103L) && defined(_GLIBCXX_USE_C99) \
11893+           && !defined(_GLIBCXX_HAVE_BROKEN_VSWPRINTF))
11894+
11895+#    define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING
11896+
11897+# endif
11898+#endif // __CYGWIN__
11899+
11900+////////////////////////////////////////////////////////////////////////////////
11901+// Visual C++
11902+#if defined(_MSC_VER)
11903+
11904+// We want to defer to nvcc-specific warning suppression if we are compiled
11905+// with nvcc masquerading for MSVC.
11906+#    if !defined( __CUDACC__ )
11907+#        define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
11908+            __pragma( warning( push ) )
11909+#        define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
11910+            __pragma( warning( pop ) )
11911+#    endif
11912+
11913+// Universal Windows platform does not support SEH
11914+// Or console colours (or console at all...)
11915+#  if defined(CATCH_PLATFORM_WINDOWS_UWP)
11916+#    define CATCH_INTERNAL_CONFIG_NO_COLOUR_WIN32
11917+#  else
11918+#    define CATCH_INTERNAL_CONFIG_WINDOWS_SEH
11919+#  endif
11920+
11921+// MSVC traditional preprocessor needs some workaround for __VA_ARGS__
11922+// _MSVC_TRADITIONAL == 0 means new conformant preprocessor
11923+// _MSVC_TRADITIONAL == 1 means old traditional non-conformant preprocessor
11924+#  if !defined(__clang__) // Handle Clang masquerading for msvc
11925+#    if !defined(_MSVC_TRADITIONAL) || (defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL)
11926+#      define CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
11927+#    endif // MSVC_TRADITIONAL
11928+#  endif // __clang__
11929+
11930+#endif // _MSC_VER
11931+
11932+#if defined(_REENTRANT) || defined(_MSC_VER)
11933+// Enable async processing, as -pthread is specified or no additional linking is required
11934+# define CATCH_INTERNAL_CONFIG_USE_ASYNC
11935+#endif // _MSC_VER
11936+
11937+////////////////////////////////////////////////////////////////////////////////
11938+// Check if we are compiled with -fno-exceptions or equivalent
11939+#if defined(__EXCEPTIONS) || defined(__cpp_exceptions) || defined(_CPPUNWIND)
11940+#  define CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED
11941+#endif
11942+
11943+
11944+////////////////////////////////////////////////////////////////////////////////
11945+// Embarcadero C++Build
11946+#if defined(__BORLANDC__)
11947+    #define CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN
11948+#endif
11949+
11950+////////////////////////////////////////////////////////////////////////////////
11951+
11952+// RTX is a special version of Windows that is real time.
11953+// This means that it is detected as Windows, but does not provide
11954+// the same set of capabilities as real Windows does.
11955+#if defined(UNDER_RTSS) || defined(RTX64_BUILD)
11956+    #define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH
11957+    #define CATCH_INTERNAL_CONFIG_NO_ASYNC
11958+    #define CATCH_INTERNAL_CONFIG_NO_COLOUR_WIN32
11959+#endif
11960+
11961+#if !defined(_GLIBCXX_USE_C99_MATH_TR1)
11962+#define CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER
11963+#endif
11964+
11965+// Various stdlib support checks that require __has_include
11966+#if defined(__has_include)
11967+  // Check if string_view is available and usable
11968+  #if __has_include(<string_view>) && defined(CATCH_CPP17_OR_GREATER)
11969+  #    define CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW
11970+  #endif
11971+
11972+  // Check if optional is available and usable
11973+  #  if __has_include(<optional>) && defined(CATCH_CPP17_OR_GREATER)
11974+  #    define CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL
11975+  #  endif // __has_include(<optional>) && defined(CATCH_CPP17_OR_GREATER)
11976+
11977+  // Check if byte is available and usable
11978+  #  if __has_include(<cstddef>) && defined(CATCH_CPP17_OR_GREATER)
11979+  #    include <cstddef>
11980+  #    if defined(__cpp_lib_byte) && (__cpp_lib_byte > 0)
11981+  #      define CATCH_INTERNAL_CONFIG_CPP17_BYTE
11982+  #    endif
11983+  #  endif // __has_include(<cstddef>) && defined(CATCH_CPP17_OR_GREATER)
11984+
11985+  // Check if variant is available and usable
11986+  #  if __has_include(<variant>) && defined(CATCH_CPP17_OR_GREATER)
11987+  #    if defined(__clang__) && (__clang_major__ < 8)
11988+         // work around clang bug with libstdc++ https://bugs.llvm.org/show_bug.cgi?id=31852
11989+         // fix should be in clang 8, workaround in libstdc++ 8.2
11990+  #      include <ciso646>
11991+  #      if defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9)
11992+  #        define CATCH_CONFIG_NO_CPP17_VARIANT
11993+  #      else
11994+  #        define CATCH_INTERNAL_CONFIG_CPP17_VARIANT
11995+  #      endif // defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9)
11996+  #    else
11997+  #      define CATCH_INTERNAL_CONFIG_CPP17_VARIANT
11998+  #    endif // defined(__clang__) && (__clang_major__ < 8)
11999+  #  endif // __has_include(<variant>) && defined(CATCH_CPP17_OR_GREATER)
12000+#endif // defined(__has_include)
12001+
12002+
12003+#if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && !defined(CATCH_CONFIG_WINDOWS_SEH) && !defined(CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH)
12004+#   define CATCH_CONFIG_WINDOWS_SEH
12005+#endif
12006+// This is set by default, because we assume that unix compilers are posix-signal-compatible by default.
12007+#if defined(CATCH_INTERNAL_CONFIG_POSIX_SIGNALS) && !defined(CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_POSIX_SIGNALS)
12008+#   define CATCH_CONFIG_POSIX_SIGNALS
12009+#endif
12010+
12011+#if defined(CATCH_INTERNAL_CONFIG_GETENV) && !defined(CATCH_INTERNAL_CONFIG_NO_GETENV) && !defined(CATCH_CONFIG_NO_GETENV) && !defined(CATCH_CONFIG_GETENV)
12012+#   define CATCH_CONFIG_GETENV
12013+#endif
12014+
12015+#if !defined(CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_CPP11_TO_STRING)
12016+#    define CATCH_CONFIG_CPP11_TO_STRING
12017+#endif
12018+
12019+#if defined(CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_NO_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_CPP17_OPTIONAL)
12020+#  define CATCH_CONFIG_CPP17_OPTIONAL
12021+#endif
12022+
12023+#if defined(CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_NO_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_CPP17_STRING_VIEW)
12024+#  define CATCH_CONFIG_CPP17_STRING_VIEW
12025+#endif
12026+
12027+#if defined(CATCH_INTERNAL_CONFIG_CPP17_VARIANT) && !defined(CATCH_CONFIG_NO_CPP17_VARIANT) && !defined(CATCH_CONFIG_CPP17_VARIANT)
12028+#  define CATCH_CONFIG_CPP17_VARIANT
12029+#endif
12030+
12031+#if defined(CATCH_INTERNAL_CONFIG_CPP17_BYTE) && !defined(CATCH_CONFIG_NO_CPP17_BYTE) && !defined(CATCH_CONFIG_CPP17_BYTE)
12032+#  define CATCH_CONFIG_CPP17_BYTE
12033+#endif
12034+
12035+
12036+#if defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT)
12037+#  define CATCH_INTERNAL_CONFIG_NEW_CAPTURE
12038+#endif
12039+
12040+#if defined(CATCH_INTERNAL_CONFIG_NEW_CAPTURE) && !defined(CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE) && !defined(CATCH_CONFIG_NO_NEW_CAPTURE) && !defined(CATCH_CONFIG_NEW_CAPTURE)
12041+#  define CATCH_CONFIG_NEW_CAPTURE
12042+#endif
12043+
12044+#if !defined( CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED ) && \
12045+    !defined( CATCH_CONFIG_DISABLE_EXCEPTIONS ) &&          \
12046+    !defined( CATCH_CONFIG_NO_DISABLE_EXCEPTIONS )
12047+#  define CATCH_CONFIG_DISABLE_EXCEPTIONS
12048+#endif
12049+
12050+#if defined(CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_NO_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_POLYFILL_ISNAN)
12051+#  define CATCH_CONFIG_POLYFILL_ISNAN
12052+#endif
12053+
12054+#if defined(CATCH_INTERNAL_CONFIG_USE_ASYNC)  && !defined(CATCH_INTERNAL_CONFIG_NO_ASYNC) && !defined(CATCH_CONFIG_NO_USE_ASYNC) && !defined(CATCH_CONFIG_USE_ASYNC)
12055+#  define CATCH_CONFIG_USE_ASYNC
12056+#endif
12057+
12058+#if defined(CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER) && !defined(CATCH_CONFIG_NO_GLOBAL_NEXTAFTER) && !defined(CATCH_CONFIG_GLOBAL_NEXTAFTER)
12059+#  define CATCH_CONFIG_GLOBAL_NEXTAFTER
12060+#endif
12061+
12062+
12063+// Even if we do not think the compiler has that warning, we still have
12064+// to provide a macro that can be used by the code.
12065+#if !defined(CATCH_INTERNAL_START_WARNINGS_SUPPRESSION)
12066+#   define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION
12067+#endif
12068+#if !defined(CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION)
12069+#   define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
12070+#endif
12071+#if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS)
12072+#   define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS
12073+#endif
12074+#if !defined(CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS)
12075+#   define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS
12076+#endif
12077+#if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_RESULT)
12078+#   define CATCH_INTERNAL_SUPPRESS_UNUSED_RESULT
12079+#endif
12080+#if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS)
12081+#   define CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS
12082+#endif
12083+#if !defined(CATCH_INTERNAL_SUPPRESS_USELESS_CAST_WARNINGS)
12084+#   define CATCH_INTERNAL_SUPPRESS_USELESS_CAST_WARNINGS
12085+#endif
12086+#if !defined(CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS)
12087+#   define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS
12088+#endif
12089+#if !defined( CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS )
12090+#    define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS
12091+#endif
12092+#if !defined( CATCH_INTERNAL_SUPPRESS_COMMA_WARNINGS )
12093+#    define CATCH_INTERNAL_SUPPRESS_COMMA_WARNINGS
12094+#endif
12095+#if !defined( CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS )
12096+#    define CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS
12097+#endif
12098+
12099+
12100+// The goal of this macro is to avoid evaluation of the arguments, but
12101+// still have the compiler warn on problems inside...
12102+#if !defined(CATCH_INTERNAL_IGNORE_BUT_WARN)
12103+#   define CATCH_INTERNAL_IGNORE_BUT_WARN(...)
12104+#endif
12105+
12106+#if defined(__APPLE__) && defined(__apple_build_version__) && (__clang_major__ < 10)
12107+#   undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS
12108+#elif defined(__clang__) && (__clang_major__ < 5)
12109+#   undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS
12110+#endif
12111+
12112+
12113+#if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
12114+#define CATCH_TRY if ((true))
12115+#define CATCH_CATCH_ALL if ((false))
12116+#define CATCH_CATCH_ANON(type) if ((false))
12117+#else
12118+#define CATCH_TRY try
12119+#define CATCH_CATCH_ALL catch (...)
12120+#define CATCH_CATCH_ANON(type) catch (type)
12121+#endif
12122+
12123+#if defined(CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_NO_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR)
12124+#define CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
12125+#endif
12126+
12127+#if defined( CATCH_PLATFORM_WINDOWS ) &&       \
12128+    !defined( CATCH_CONFIG_COLOUR_WIN32 ) && \
12129+    !defined( CATCH_CONFIG_NO_COLOUR_WIN32 ) && \
12130+    !defined( CATCH_INTERNAL_CONFIG_NO_COLOUR_WIN32 )
12131+#    define CATCH_CONFIG_COLOUR_WIN32
12132+#endif
12133+
12134+#if defined( CATCH_CONFIG_SHARED_LIBRARY ) && defined( _MSC_VER ) && \
12135+    !defined( CATCH_CONFIG_STATIC )
12136+#    ifdef Catch2_EXPORTS
12137+#        define CATCH_EXPORT //__declspec( dllexport ) // not needed
12138+#    else
12139+#        define CATCH_EXPORT __declspec( dllimport )
12140+#    endif
12141+#else
12142+#    define CATCH_EXPORT
12143+#endif
12144+
12145+#endif // CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED
12146+
12147+
12148+#ifndef CATCH_CONTEXT_HPP_INCLUDED
12149+#define CATCH_CONTEXT_HPP_INCLUDED
12150+
12151+
12152+namespace Catch {
12153+
12154+    class IResultCapture;
12155+    class IConfig;
12156+
12157+    class Context {
12158+        IConfig const* m_config = nullptr;
12159+        IResultCapture* m_resultCapture = nullptr;
12160+
12161+        CATCH_EXPORT static Context* currentContext;
12162+        friend Context& getCurrentMutableContext();
12163+        friend Context const& getCurrentContext();
12164+        static void createContext();
12165+        friend void cleanUpContext();
12166+
12167+    public:
12168+        IResultCapture* getResultCapture() const { return m_resultCapture; }
12169+        IConfig const* getConfig() const { return m_config; }
12170+        void setResultCapture( IResultCapture* resultCapture );
12171+        void setConfig( IConfig const* config );
12172+    };
12173+
12174+    Context& getCurrentMutableContext();
12175+
12176+    inline Context const& getCurrentContext() {
12177+        // We duplicate the logic from `getCurrentMutableContext` here,
12178+        // to avoid paying the call overhead in debug mode.
12179+        if ( !Context::currentContext ) { Context::createContext(); }
12180+        // NOLINTNEXTLINE(clang-analyzer-core.uninitialized.UndefReturn)
12181+        return *Context::currentContext;
12182+    }
12183+
12184+    void cleanUpContext();
12185+
12186+    class SimplePcg32;
12187+    SimplePcg32& sharedRng();
12188+}
12189+
12190+#endif // CATCH_CONTEXT_HPP_INCLUDED
12191+
12192+
12193+#ifndef CATCH_MOVE_AND_FORWARD_HPP_INCLUDED
12194+#define CATCH_MOVE_AND_FORWARD_HPP_INCLUDED
12195+
12196+#include <type_traits>
12197+
12198+//! Replacement for std::move with better compile time performance
12199+#define CATCH_MOVE(...) static_cast<std::remove_reference_t<decltype(__VA_ARGS__)>&&>(__VA_ARGS__)
12200+
12201+//! Replacement for std::forward with better compile time performance
12202+#define CATCH_FORWARD(...) static_cast<decltype(__VA_ARGS__)&&>(__VA_ARGS__)
12203+
12204+#endif // CATCH_MOVE_AND_FORWARD_HPP_INCLUDED
12205+
12206+
12207+#ifndef CATCH_TEST_FAILURE_EXCEPTION_HPP_INCLUDED
12208+#define CATCH_TEST_FAILURE_EXCEPTION_HPP_INCLUDED
12209+
12210+namespace Catch {
12211+
12212+    //! Used to signal that an assertion macro failed
12213+    struct TestFailureException{};
12214+    //! Used to signal that the remainder of a test should be skipped
12215+    struct TestSkipException {};
12216+
12217+    /**
12218+     * Outlines throwing of `TestFailureException` into a single TU
12219+     *
12220+     * Also handles `CATCH_CONFIG_DISABLE_EXCEPTIONS` for callers.
12221+     */
12222+    [[noreturn]] void throw_test_failure_exception();
12223+
12224+    /**
12225+     * Outlines throwing of `TestSkipException` into a single TU
12226+     *
12227+     * Also handles `CATCH_CONFIG_DISABLE_EXCEPTIONS` for callers.
12228+     */
12229+    [[noreturn]] void throw_test_skip_exception();
12230+
12231+} // namespace Catch
12232+
12233+#endif // CATCH_TEST_FAILURE_EXCEPTION_HPP_INCLUDED
12234+
12235+
12236+#ifndef CATCH_UNIQUE_NAME_HPP_INCLUDED
12237+#define CATCH_UNIQUE_NAME_HPP_INCLUDED
12238+
12239+
12240+
12241+
12242+/** \file
12243+ * Wrapper for the CONFIG configuration option
12244+ *
12245+ * When generating internal unique names, there are two options. Either
12246+ * we mix in the current line number, or mix in an incrementing number.
12247+ * We prefer the latter, using `__COUNTER__`, but users might want to
12248+ * use the former.
12249+ */
12250+
12251+#ifndef CATCH_CONFIG_COUNTER_HPP_INCLUDED
12252+#define CATCH_CONFIG_COUNTER_HPP_INCLUDED
12253+
12254+
12255+#if ( !defined(__JETBRAINS_IDE__) || __JETBRAINS_IDE__ >= 20170300L )
12256+    #define CATCH_INTERNAL_CONFIG_COUNTER
12257+#endif
12258+
12259+#if defined( CATCH_INTERNAL_CONFIG_COUNTER ) && \
12260+    !defined( CATCH_CONFIG_NO_COUNTER ) && \
12261+    !defined( CATCH_CONFIG_COUNTER )
12262+#    define CATCH_CONFIG_COUNTER
12263+#endif
12264+
12265+
12266+#endif // CATCH_CONFIG_COUNTER_HPP_INCLUDED
12267+#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line
12268+#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line )
12269+#ifdef CATCH_CONFIG_COUNTER
12270+#  define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ )
12271+#else
12272+#  define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ )
12273+#endif
12274+
12275+#endif // CATCH_UNIQUE_NAME_HPP_INCLUDED
12276+
12277+
12278+#ifndef CATCH_INTERFACES_CAPTURE_HPP_INCLUDED
12279+#define CATCH_INTERFACES_CAPTURE_HPP_INCLUDED
12280+
12281+#include <string>
12282+#include <chrono>
12283+
12284+
12285+
12286+#ifndef CATCH_STRINGREF_HPP_INCLUDED
12287+#define CATCH_STRINGREF_HPP_INCLUDED
12288+
12289+#include <cstddef>
12290+#include <string>
12291+#include <iosfwd>
12292+#include <cassert>
12293+
12294+#include <cstring>
12295+
12296+namespace Catch {
12297+
12298+    /// A non-owning string class (similar to the forthcoming std::string_view)
12299+    /// Note that, because a StringRef may be a substring of another string,
12300+    /// it may not be null terminated.
12301+    class StringRef {
12302+    public:
12303+        using size_type = std::size_t;
12304+        using const_iterator = const char*;
12305+
12306+        static constexpr size_type npos{ static_cast<size_type>( -1 ) };
12307+
12308+    private:
12309+        static constexpr char const* const s_empty = "";
12310+
12311+        char const* m_start = s_empty;
12312+        size_type m_size = 0;
12313+
12314+    public: // construction
12315+        constexpr StringRef() noexcept = default;
12316+
12317+        StringRef( char const* rawChars ) noexcept;
12318+
12319+        constexpr StringRef( char const* rawChars, size_type size ) noexcept
12320+        :   m_start( rawChars ),
12321+            m_size( size )
12322+        {}
12323+
12324+        StringRef( std::string const& stdString ) noexcept
12325+        :   m_start( stdString.c_str() ),
12326+            m_size( stdString.size() )
12327+        {}
12328+
12329+        explicit operator std::string() const {
12330+            return std::string(m_start, m_size);
12331+        }
12332+
12333+    public: // operators
12334+        auto operator == ( StringRef other ) const noexcept -> bool {
12335+            return m_size == other.m_size
12336+                && (std::memcmp( m_start, other.m_start, m_size ) == 0);
12337+        }
12338+        auto operator != (StringRef other) const noexcept -> bool {
12339+            return !(*this == other);
12340+        }
12341+
12342+        constexpr auto operator[] ( size_type index ) const noexcept -> char {
12343+            assert(index < m_size);
12344+            return m_start[index];
12345+        }
12346+
12347+        bool operator<(StringRef rhs) const noexcept;
12348+
12349+    public: // named queries
12350+        constexpr auto empty() const noexcept -> bool {
12351+            return m_size == 0;
12352+        }
12353+        constexpr auto size() const noexcept -> size_type {
12354+            return m_size;
12355+        }
12356+
12357+        // Returns a substring of [start, start + length).
12358+        // If start + length > size(), then the substring is [start, size()).
12359+        // If start > size(), then the substring is empty.
12360+        constexpr StringRef substr(size_type start, size_type length) const noexcept {
12361+            if (start < m_size) {
12362+                const auto shortened_size = m_size - start;
12363+                return StringRef(m_start + start, (shortened_size < length) ? shortened_size : length);
12364+            } else {
12365+                return StringRef();
12366+            }
12367+        }
12368+
12369+        // Returns the current start pointer. May not be null-terminated.
12370+        constexpr char const* data() const noexcept {
12371+            return m_start;
12372+        }
12373+
12374+        constexpr const_iterator begin() const { return m_start; }
12375+        constexpr const_iterator end() const { return m_start + m_size; }
12376+
12377+
12378+        friend std::string& operator += (std::string& lhs, StringRef rhs);
12379+        friend std::ostream& operator << (std::ostream& os, StringRef str);
12380+        friend std::string operator+(StringRef lhs, StringRef rhs);
12381+
12382+        /**
12383+         * Provides a three-way comparison with rhs
12384+         *
12385+         * Returns negative number if lhs < rhs, 0 if lhs == rhs, and a positive
12386+         * number if lhs > rhs
12387+         */
12388+        int compare( StringRef rhs ) const;
12389+    };
12390+
12391+
12392+    constexpr auto operator ""_sr( char const* rawChars, std::size_t size ) noexcept -> StringRef {
12393+        return StringRef( rawChars, size );
12394+    }
12395+} // namespace Catch
12396+
12397+constexpr auto operator ""_catch_sr( char const* rawChars, std::size_t size ) noexcept -> Catch::StringRef {
12398+    return Catch::StringRef( rawChars, size );
12399+}
12400+
12401+#endif // CATCH_STRINGREF_HPP_INCLUDED
12402+
12403+
12404+#ifndef CATCH_RESULT_TYPE_HPP_INCLUDED
12405+#define CATCH_RESULT_TYPE_HPP_INCLUDED
12406+
12407+namespace Catch {
12408+
12409+    // ResultWas::OfType enum
12410+    struct ResultWas { enum OfType {
12411+        Unknown = -1,
12412+        Ok = 0,
12413+        Info = 1,
12414+        Warning = 2,
12415+        // TODO: Should explicit skip be considered "not OK" (cf. isOk)? I.e., should it have the failure bit?
12416+        ExplicitSkip = 4,
12417+
12418+        FailureBit = 0x10,
12419+
12420+        ExpressionFailed = FailureBit | 1,
12421+        ExplicitFailure = FailureBit | 2,
12422+
12423+        Exception = 0x100 | FailureBit,
12424+
12425+        ThrewException = Exception | 1,
12426+        DidntThrowException = Exception | 2,
12427+
12428+        FatalErrorCondition = 0x200 | FailureBit
12429+
12430+    }; };
12431+
12432+    bool isOk( ResultWas::OfType resultType );
12433+    bool isJustInfo( int flags );
12434+
12435+
12436+    // ResultDisposition::Flags enum
12437+    struct ResultDisposition { enum Flags {
12438+        Normal = 0x01,
12439+
12440+        ContinueOnFailure = 0x02,   // Failures fail test, but execution continues
12441+        FalseTest = 0x04,           // Prefix expression with !
12442+        SuppressFail = 0x08         // Failures are reported but do not fail the test
12443+    }; };
12444+
12445+    ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs );
12446+
12447+    bool shouldContinueOnFailure( int flags );
12448+    inline bool isFalseTest( int flags ) { return ( flags & ResultDisposition::FalseTest ) != 0; }
12449+    bool shouldSuppressFailure( int flags );
12450+
12451+} // end namespace Catch
12452+
12453+#endif // CATCH_RESULT_TYPE_HPP_INCLUDED
12454+
12455+
12456+#ifndef CATCH_UNIQUE_PTR_HPP_INCLUDED
12457+#define CATCH_UNIQUE_PTR_HPP_INCLUDED
12458+
12459+#include <cassert>
12460+#include <type_traits>
12461+
12462+
12463+namespace Catch {
12464+namespace Detail {
12465+    /**
12466+     * A reimplementation of `std::unique_ptr` for improved compilation performance
12467+     *
12468+     * Does not support arrays nor custom deleters.
12469+     */
12470+    template <typename T>
12471+    class unique_ptr {
12472+        T* m_ptr;
12473+    public:
12474+        constexpr unique_ptr(std::nullptr_t = nullptr):
12475+            m_ptr{}
12476+        {}
12477+        explicit constexpr unique_ptr(T* ptr):
12478+            m_ptr(ptr)
12479+        {}
12480+
12481+        template <typename U, typename = std::enable_if_t<std::is_base_of<T, U>::value>>
12482+        unique_ptr(unique_ptr<U>&& from):
12483+            m_ptr(from.release())
12484+        {}
12485+
12486+        template <typename U, typename = std::enable_if_t<std::is_base_of<T, U>::value>>
12487+        unique_ptr& operator=(unique_ptr<U>&& from) {
12488+            reset(from.release());
12489+
12490+            return *this;
12491+        }
12492+
12493+        unique_ptr(unique_ptr const&) = delete;
12494+        unique_ptr& operator=(unique_ptr const&) = delete;
12495+
12496+        unique_ptr(unique_ptr&& rhs) noexcept:
12497+            m_ptr(rhs.m_ptr) {
12498+            rhs.m_ptr = nullptr;
12499+        }
12500+        unique_ptr& operator=(unique_ptr&& rhs) noexcept {
12501+            reset(rhs.release());
12502+
12503+            return *this;
12504+        }
12505+
12506+        ~unique_ptr() {
12507+            delete m_ptr;
12508+        }
12509+
12510+        T& operator*() {
12511+            assert(m_ptr);
12512+            return *m_ptr;
12513+        }
12514+        T const& operator*() const {
12515+            assert(m_ptr);
12516+            return *m_ptr;
12517+        }
12518+        T* operator->() noexcept {
12519+            assert(m_ptr);
12520+            return m_ptr;
12521+        }
12522+        T const* operator->() const noexcept {
12523+            assert(m_ptr);
12524+            return m_ptr;
12525+        }
12526+
12527+        T* get() { return m_ptr; }
12528+        T const* get() const { return m_ptr; }
12529+
12530+        void reset(T* ptr = nullptr) {
12531+            delete m_ptr;
12532+            m_ptr = ptr;
12533+        }
12534+
12535+        T* release() {
12536+            auto temp = m_ptr;
12537+            m_ptr = nullptr;
12538+            return temp;
12539+        }
12540+
12541+        explicit operator bool() const {
12542+            return m_ptr;
12543+        }
12544+
12545+        friend void swap(unique_ptr& lhs, unique_ptr& rhs) {
12546+            auto temp = lhs.m_ptr;
12547+            lhs.m_ptr = rhs.m_ptr;
12548+            rhs.m_ptr = temp;
12549+        }
12550+    };
12551+
12552+    //! Specialization to cause compile-time error for arrays
12553+    template <typename T>
12554+    class unique_ptr<T[]>;
12555+
12556+    template <typename T, typename... Args>
12557+    unique_ptr<T> make_unique(Args&&... args) {
12558+        return unique_ptr<T>(new T(CATCH_FORWARD(args)...));
12559+    }
12560+
12561+
12562+} // end namespace Detail
12563+} // end namespace Catch
12564+
12565+#endif // CATCH_UNIQUE_PTR_HPP_INCLUDED
12566+
12567+
12568+#ifndef CATCH_BENCHMARK_STATS_FWD_HPP_INCLUDED
12569+#define CATCH_BENCHMARK_STATS_FWD_HPP_INCLUDED
12570+
12571+
12572+
12573+// Adapted from donated nonius code.
12574+
12575+#ifndef CATCH_CLOCK_HPP_INCLUDED
12576+#define CATCH_CLOCK_HPP_INCLUDED
12577+
12578+#include <chrono>
12579+
12580+namespace Catch {
12581+    namespace Benchmark {
12582+        using IDuration = std::chrono::nanoseconds;
12583+        using FDuration = std::chrono::duration<double, std::nano>;
12584+
12585+        template <typename Clock>
12586+        using TimePoint = typename Clock::time_point;
12587+
12588+        using default_clock = std::chrono::steady_clock;
12589+    } // namespace Benchmark
12590+} // namespace Catch
12591+
12592+#endif // CATCH_CLOCK_HPP_INCLUDED
12593+
12594+namespace Catch {
12595+
12596+    // We cannot forward declare the type with default template argument
12597+    // multiple times, so it is split out into a separate header so that
12598+    // we can prevent multiple declarations in dependees
12599+    template <typename Duration = Benchmark::FDuration>
12600+    struct BenchmarkStats;
12601+
12602+} // end namespace Catch
12603+
12604+#endif // CATCH_BENCHMARK_STATS_FWD_HPP_INCLUDED
12605+
12606+namespace Catch {
12607+
12608+    class AssertionResult;
12609+    struct AssertionInfo;
12610+    struct SectionInfo;
12611+    struct SectionEndInfo;
12612+    struct MessageInfo;
12613+    struct MessageBuilder;
12614+    struct Counts;
12615+    struct AssertionReaction;
12616+    struct SourceLineInfo;
12617+
12618+    class ITransientExpression;
12619+    class IGeneratorTracker;
12620+
12621+    struct BenchmarkInfo;
12622+
12623+    namespace Generators {
12624+        class GeneratorUntypedBase;
12625+        using GeneratorBasePtr = Catch::Detail::unique_ptr<GeneratorUntypedBase>;
12626+    }
12627+
12628+
12629+    class IResultCapture {
12630+    public:
12631+        virtual ~IResultCapture();
12632+
12633+        virtual void notifyAssertionStarted( AssertionInfo const& info ) = 0;
12634+        virtual bool sectionStarted( StringRef sectionName,
12635+                                     SourceLineInfo const& sectionLineInfo,
12636+                                     Counts& assertions ) = 0;
12637+        virtual void sectionEnded( SectionEndInfo&& endInfo ) = 0;
12638+        virtual void sectionEndedEarly( SectionEndInfo&& endInfo ) = 0;
12639+
12640+        virtual IGeneratorTracker*
12641+        acquireGeneratorTracker( StringRef generatorName,
12642+                                 SourceLineInfo const& lineInfo ) = 0;
12643+        virtual IGeneratorTracker*
12644+        createGeneratorTracker( StringRef generatorName,
12645+                                SourceLineInfo lineInfo,
12646+                                Generators::GeneratorBasePtr&& generator ) = 0;
12647+
12648+        virtual void benchmarkPreparing( StringRef name ) = 0;
12649+        virtual void benchmarkStarting( BenchmarkInfo const& info ) = 0;
12650+        virtual void benchmarkEnded( BenchmarkStats<> const& stats ) = 0;
12651+        virtual void benchmarkFailed( StringRef error ) = 0;
12652+
12653+        virtual void pushScopedMessage( MessageInfo const& message ) = 0;
12654+        virtual void popScopedMessage( MessageInfo const& message ) = 0;
12655+
12656+        virtual void emplaceUnscopedMessage( MessageBuilder&& builder ) = 0;
12657+
12658+        virtual void handleFatalErrorCondition( StringRef message ) = 0;
12659+
12660+        virtual void handleExpr
12661+                (   AssertionInfo const& info,
12662+                    ITransientExpression const& expr,
12663+                    AssertionReaction& reaction ) = 0;
12664+        virtual void handleMessage
12665+                (   AssertionInfo const& info,
12666+                    ResultWas::OfType resultType,
12667+                    StringRef message,
12668+                    AssertionReaction& reaction ) = 0;
12669+        virtual void handleUnexpectedExceptionNotThrown
12670+                (   AssertionInfo const& info,
12671+                    AssertionReaction& reaction ) = 0;
12672+        virtual void handleUnexpectedInflightException
12673+                (   AssertionInfo const& info,
12674+                    std::string&& message,
12675+                    AssertionReaction& reaction ) = 0;
12676+        virtual void handleIncomplete
12677+                (   AssertionInfo const& info ) = 0;
12678+        virtual void handleNonExpr
12679+                (   AssertionInfo const &info,
12680+                    ResultWas::OfType resultType,
12681+                    AssertionReaction &reaction ) = 0;
12682+
12683+
12684+
12685+        virtual bool lastAssertionPassed() = 0;
12686+        virtual void assertionPassed() = 0;
12687+
12688+        // Deprecated, do not use:
12689+        virtual std::string getCurrentTestName() const = 0;
12690+        virtual const AssertionResult* getLastResult() const = 0;
12691+        virtual void exceptionEarlyReported() = 0;
12692+    };
12693+
12694+    IResultCapture& getResultCapture();
12695+}
12696+
12697+#endif // CATCH_INTERFACES_CAPTURE_HPP_INCLUDED
12698+
12699+
12700+#ifndef CATCH_INTERFACES_CONFIG_HPP_INCLUDED
12701+#define CATCH_INTERFACES_CONFIG_HPP_INCLUDED
12702+
12703+
12704+
12705+#ifndef CATCH_NONCOPYABLE_HPP_INCLUDED
12706+#define CATCH_NONCOPYABLE_HPP_INCLUDED
12707+
12708+namespace Catch {
12709+    namespace Detail {
12710+
12711+        //! Deriving classes become noncopyable and nonmovable
12712+        class NonCopyable {
12713+            NonCopyable( NonCopyable const& ) = delete;
12714+            NonCopyable( NonCopyable&& ) = delete;
12715+            NonCopyable& operator=( NonCopyable const& ) = delete;
12716+            NonCopyable& operator=( NonCopyable&& ) = delete;
12717+
12718+        protected:
12719+            NonCopyable() noexcept = default;
12720+        };
12721+
12722+    } // namespace Detail
12723+} // namespace Catch
12724+
12725+#endif // CATCH_NONCOPYABLE_HPP_INCLUDED
12726+
12727+#include <chrono>
12728+#include <iosfwd>
12729+#include <string>
12730+#include <vector>
12731+
12732+namespace Catch {
12733+
12734+    enum class Verbosity {
12735+        Quiet = 0,
12736+        Normal,
12737+        High
12738+    };
12739+
12740+    struct WarnAbout { enum What {
12741+        Nothing = 0x00,
12742+        //! A test case or leaf section did not run any assertions
12743+        NoAssertions = 0x01,
12744+        //! A command line test spec matched no test cases
12745+        UnmatchedTestSpec = 0x02,
12746+    }; };
12747+
12748+    enum class ShowDurations {
12749+        DefaultForReporter,
12750+        Always,
12751+        Never
12752+    };
12753+    enum class TestRunOrder {
12754+        Declared,
12755+        LexicographicallySorted,
12756+        Randomized
12757+    };
12758+    enum class ColourMode : std::uint8_t {
12759+        //! Let Catch2 pick implementation based on platform detection
12760+        PlatformDefault,
12761+        //! Use ANSI colour code escapes
12762+        ANSI,
12763+        //! Use Win32 console colour API
12764+        Win32,
12765+        //! Don't use any colour
12766+        None
12767+    };
12768+    struct WaitForKeypress { enum When {
12769+        Never,
12770+        BeforeStart = 1,
12771+        BeforeExit = 2,
12772+        BeforeStartAndExit = BeforeStart | BeforeExit
12773+    }; };
12774+
12775+    class TestSpec;
12776+    class IStream;
12777+
12778+    class IConfig : public Detail::NonCopyable {
12779+    public:
12780+        virtual ~IConfig();
12781+
12782+        virtual bool allowThrows() const = 0;
12783+        virtual StringRef name() const = 0;
12784+        virtual bool includeSuccessfulResults() const = 0;
12785+        virtual bool shouldDebugBreak() const = 0;
12786+        virtual bool warnAboutMissingAssertions() const = 0;
12787+        virtual bool warnAboutUnmatchedTestSpecs() const = 0;
12788+        virtual bool zeroTestsCountAsSuccess() const = 0;
12789+        virtual int abortAfter() const = 0;
12790+        virtual bool showInvisibles() const = 0;
12791+        virtual ShowDurations showDurations() const = 0;
12792+        virtual double minDuration() const = 0;
12793+        virtual TestSpec const& testSpec() const = 0;
12794+        virtual bool hasTestFilters() const = 0;
12795+        virtual std::vector<std::string> const& getTestsOrTags() const = 0;
12796+        virtual TestRunOrder runOrder() const = 0;
12797+        virtual uint32_t rngSeed() const = 0;
12798+        virtual unsigned int shardCount() const = 0;
12799+        virtual unsigned int shardIndex() const = 0;
12800+        virtual ColourMode defaultColourMode() const = 0;
12801+        virtual std::vector<std::string> const& getSectionsToRun() const = 0;
12802+        virtual Verbosity verbosity() const = 0;
12803+
12804+        virtual bool skipBenchmarks() const = 0;
12805+        virtual bool benchmarkNoAnalysis() const = 0;
12806+        virtual unsigned int benchmarkSamples() const = 0;
12807+        virtual double benchmarkConfidenceInterval() const = 0;
12808+        virtual unsigned int benchmarkResamples() const = 0;
12809+        virtual std::chrono::milliseconds benchmarkWarmupTime() const = 0;
12810+    };
12811+}
12812+
12813+#endif // CATCH_INTERFACES_CONFIG_HPP_INCLUDED
12814+
12815+
12816+#ifndef CATCH_INTERFACES_REGISTRY_HUB_HPP_INCLUDED
12817+#define CATCH_INTERFACES_REGISTRY_HUB_HPP_INCLUDED
12818+
12819+
12820+#include <string>
12821+
12822+namespace Catch {
12823+
12824+    class TestCaseHandle;
12825+    struct TestCaseInfo;
12826+    class ITestCaseRegistry;
12827+    class IExceptionTranslatorRegistry;
12828+    class IExceptionTranslator;
12829+    class ReporterRegistry;
12830+    class IReporterFactory;
12831+    class ITagAliasRegistry;
12832+    class ITestInvoker;
12833+    class IMutableEnumValuesRegistry;
12834+    struct SourceLineInfo;
12835+
12836+    class StartupExceptionRegistry;
12837+    class EventListenerFactory;
12838+
12839+    using IReporterFactoryPtr = Detail::unique_ptr<IReporterFactory>;
12840+
12841+    class IRegistryHub {
12842+    public:
12843+        virtual ~IRegistryHub(); // = default
12844+
12845+        virtual ReporterRegistry const& getReporterRegistry() const = 0;
12846+        virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0;
12847+        virtual ITagAliasRegistry const& getTagAliasRegistry() const = 0;
12848+        virtual IExceptionTranslatorRegistry const& getExceptionTranslatorRegistry() const = 0;
12849+
12850+
12851+        virtual StartupExceptionRegistry const& getStartupExceptionRegistry() const = 0;
12852+    };
12853+
12854+    class IMutableRegistryHub {
12855+    public:
12856+        virtual ~IMutableRegistryHub(); // = default
12857+        virtual void registerReporter( std::string const& name, IReporterFactoryPtr factory ) = 0;
12858+        virtual void registerListener( Detail::unique_ptr<EventListenerFactory> factory ) = 0;
12859+        virtual void registerTest(Detail::unique_ptr<TestCaseInfo>&& testInfo, Detail::unique_ptr<ITestInvoker>&& invoker) = 0;
12860+        virtual void registerTranslator( Detail::unique_ptr<IExceptionTranslator>&& translator ) = 0;
12861+        virtual void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) = 0;
12862+        virtual void registerStartupException() noexcept = 0;
12863+        virtual IMutableEnumValuesRegistry& getMutableEnumValuesRegistry() = 0;
12864+    };
12865+
12866+    IRegistryHub const& getRegistryHub();
12867+    IMutableRegistryHub& getMutableRegistryHub();
12868+    void cleanUp();
12869+    std::string translateActiveException();
12870+
12871+}
12872+
12873+#endif // CATCH_INTERFACES_REGISTRY_HUB_HPP_INCLUDED
12874+
12875+
12876+#ifndef CATCH_BENCHMARK_STATS_HPP_INCLUDED
12877+#define CATCH_BENCHMARK_STATS_HPP_INCLUDED
12878+
12879+
12880+
12881+// Adapted from donated nonius code.
12882+
12883+#ifndef CATCH_ESTIMATE_HPP_INCLUDED
12884+#define CATCH_ESTIMATE_HPP_INCLUDED
12885+
12886+namespace Catch {
12887+    namespace Benchmark {
12888+        template <typename Type>
12889+        struct Estimate {
12890+            Type point;
12891+            Type lower_bound;
12892+            Type upper_bound;
12893+            double confidence_interval;
12894+        };
12895+    } // namespace Benchmark
12896+} // namespace Catch
12897+
12898+#endif // CATCH_ESTIMATE_HPP_INCLUDED
12899+
12900+
12901+// Adapted from donated nonius code.
12902+
12903+#ifndef CATCH_OUTLIER_CLASSIFICATION_HPP_INCLUDED
12904+#define CATCH_OUTLIER_CLASSIFICATION_HPP_INCLUDED
12905+
12906+namespace Catch {
12907+    namespace Benchmark {
12908+        struct OutlierClassification {
12909+            int samples_seen = 0;
12910+            int low_severe = 0;     // more than 3 times IQR below Q1
12911+            int low_mild = 0;       // 1.5 to 3 times IQR below Q1
12912+            int high_mild = 0;      // 1.5 to 3 times IQR above Q3
12913+            int high_severe = 0;    // more than 3 times IQR above Q3
12914+
12915+            int total() const {
12916+                return low_severe + low_mild + high_mild + high_severe;
12917+            }
12918+        };
12919+    } // namespace Benchmark
12920+} // namespace Catch
12921+
12922+#endif // CATCH_OUTLIERS_CLASSIFICATION_HPP_INCLUDED
12923+// The fwd decl & default specialization needs to be seen by VS2017 before
12924+// BenchmarkStats itself, or VS2017 will report compilation error.
12925+
12926+#include <string>
12927+#include <vector>
12928+
12929+namespace Catch {
12930+
12931+    struct BenchmarkInfo {
12932+        std::string name;
12933+        double estimatedDuration;
12934+        int iterations;
12935+        unsigned int samples;
12936+        unsigned int resamples;
12937+        double clockResolution;
12938+        double clockCost;
12939+    };
12940+
12941+    // We need to keep template parameter for backwards compatibility,
12942+    // but we also do not want to use the template paraneter.
12943+    template <class Dummy>
12944+    struct BenchmarkStats {
12945+        BenchmarkInfo info;
12946+
12947+        std::vector<Benchmark::FDuration> samples;
12948+        Benchmark::Estimate<Benchmark::FDuration> mean;
12949+        Benchmark::Estimate<Benchmark::FDuration> standardDeviation;
12950+        Benchmark::OutlierClassification outliers;
12951+        double outlierVariance;
12952+    };
12953+
12954+
12955+} // end namespace Catch
12956+
12957+#endif // CATCH_BENCHMARK_STATS_HPP_INCLUDED
12958+
12959+
12960+// Adapted from donated nonius code.
12961+
12962+#ifndef CATCH_ENVIRONMENT_HPP_INCLUDED
12963+#define CATCH_ENVIRONMENT_HPP_INCLUDED
12964+
12965+
12966+namespace Catch {
12967+    namespace Benchmark {
12968+        struct EnvironmentEstimate {
12969+            FDuration mean;
12970+            OutlierClassification outliers;
12971+        };
12972+        struct Environment {
12973+            EnvironmentEstimate clock_resolution;
12974+            EnvironmentEstimate clock_cost;
12975+        };
12976+    } // namespace Benchmark
12977+} // namespace Catch
12978+
12979+#endif // CATCH_ENVIRONMENT_HPP_INCLUDED
12980+
12981+
12982+// Adapted from donated nonius code.
12983+
12984+#ifndef CATCH_EXECUTION_PLAN_HPP_INCLUDED
12985+#define CATCH_EXECUTION_PLAN_HPP_INCLUDED
12986+
12987+
12988+
12989+// Adapted from donated nonius code.
12990+
12991+#ifndef CATCH_BENCHMARK_FUNCTION_HPP_INCLUDED
12992+#define CATCH_BENCHMARK_FUNCTION_HPP_INCLUDED
12993+
12994+
12995+
12996+// Adapted from donated nonius code.
12997+
12998+#ifndef CATCH_CHRONOMETER_HPP_INCLUDED
12999+#define CATCH_CHRONOMETER_HPP_INCLUDED
13000+
13001+
13002+
13003+// Adapted from donated nonius code.
13004+
13005+#ifndef CATCH_OPTIMIZER_HPP_INCLUDED
13006+#define CATCH_OPTIMIZER_HPP_INCLUDED
13007+
13008+#if defined(_MSC_VER) || defined(__IAR_SYSTEMS_ICC__)
13009+#   include <atomic> // atomic_thread_fence
13010+#endif
13011+
13012+
13013+#include <type_traits>
13014+
13015+namespace Catch {
13016+    namespace Benchmark {
13017+#if defined(__GNUC__) || defined(__clang__)
13018+        template <typename T>
13019+        inline void keep_memory(T* p) {
13020+            asm volatile("" : : "g"(p) : "memory");
13021+        }
13022+        inline void keep_memory() {
13023+            asm volatile("" : : : "memory");
13024+        }
13025+
13026+        namespace Detail {
13027+            inline void optimizer_barrier() { keep_memory(); }
13028+        } // namespace Detail
13029+#elif defined(_MSC_VER) || defined(__IAR_SYSTEMS_ICC__)
13030+
13031+#if defined(_MSVC_VER)
13032+#pragma optimize("", off)
13033+#elif defined(__IAR_SYSTEMS_ICC__)
13034+// For IAR the pragma only affects the following function
13035+#pragma optimize=disable
13036+#endif
13037+        template <typename T>
13038+        inline void keep_memory(T* p) {
13039+            // thanks @milleniumbug
13040+            *reinterpret_cast<char volatile*>(p) = *reinterpret_cast<char const volatile*>(p);
13041+        }
13042+        // TODO equivalent keep_memory()
13043+#if defined(_MSVC_VER)
13044+#pragma optimize("", on)
13045+#endif
13046+
13047+        namespace Detail {
13048+            inline void optimizer_barrier() {
13049+                std::atomic_thread_fence(std::memory_order_seq_cst);
13050+            }
13051+        } // namespace Detail
13052+
13053+#endif
13054+
13055+        template <typename T>
13056+        inline void deoptimize_value(T&& x) {
13057+            keep_memory(&x);
13058+        }
13059+
13060+        template <typename Fn, typename... Args>
13061+        inline auto invoke_deoptimized(Fn&& fn, Args&&... args) -> std::enable_if_t<!std::is_same<void, decltype(fn(args...))>::value> {
13062+            deoptimize_value(CATCH_FORWARD(fn) (CATCH_FORWARD(args)...));
13063+        }
13064+
13065+        template <typename Fn, typename... Args>
13066+        inline auto invoke_deoptimized(Fn&& fn, Args&&... args) -> std::enable_if_t<std::is_same<void, decltype(fn(args...))>::value> {
13067+            CATCH_FORWARD((fn)) (CATCH_FORWARD(args)...);
13068+        }
13069+    } // namespace Benchmark
13070+} // namespace Catch
13071+
13072+#endif // CATCH_OPTIMIZER_HPP_INCLUDED
13073+
13074+
13075+#ifndef CATCH_META_HPP_INCLUDED
13076+#define CATCH_META_HPP_INCLUDED
13077+
13078+#include <type_traits>
13079+
13080+namespace Catch {
13081+    template <typename>
13082+    struct true_given : std::true_type {};
13083+
13084+    struct is_callable_tester {
13085+        template <typename Fun, typename... Args>
13086+        static true_given<decltype(std::declval<Fun>()(std::declval<Args>()...))> test(int);
13087+        template <typename...>
13088+        static std::false_type test(...);
13089+    };
13090+
13091+    template <typename T>
13092+    struct is_callable;
13093+
13094+    template <typename Fun, typename... Args>
13095+    struct is_callable<Fun(Args...)> : decltype(is_callable_tester::test<Fun, Args...>(0)) {};
13096+
13097+
13098+#if defined(__cpp_lib_is_invocable) && __cpp_lib_is_invocable >= 201703
13099+    // std::result_of is deprecated in C++17 and removed in C++20. Hence, it is
13100+    // replaced with std::invoke_result here.
13101+    template <typename Func, typename... U>
13102+    using FunctionReturnType = std::remove_reference_t<std::remove_cv_t<std::invoke_result_t<Func, U...>>>;
13103+#else
13104+    template <typename Func, typename... U>
13105+    using FunctionReturnType = std::remove_reference_t<std::remove_cv_t<std::result_of_t<Func(U...)>>>;
13106+#endif
13107+
13108+} // namespace Catch
13109+
13110+namespace mpl_{
13111+    struct na;
13112+}
13113+
13114+#endif // CATCH_META_HPP_INCLUDED
13115+
13116+namespace Catch {
13117+    namespace Benchmark {
13118+        namespace Detail {
13119+            struct ChronometerConcept {
13120+                virtual void start() = 0;
13121+                virtual void finish() = 0;
13122+                virtual ~ChronometerConcept(); // = default;
13123+
13124+                ChronometerConcept() = default;
13125+                ChronometerConcept(ChronometerConcept const&) = default;
13126+                ChronometerConcept& operator=(ChronometerConcept const&) = default;
13127+            };
13128+            template <typename Clock>
13129+            struct ChronometerModel final : public ChronometerConcept {
13130+                void start() override { started = Clock::now(); }
13131+                void finish() override { finished = Clock::now(); }
13132+
13133+                IDuration elapsed() const {
13134+                    return std::chrono::duration_cast<std::chrono::nanoseconds>(
13135+                        finished - started );
13136+                }
13137+
13138+                TimePoint<Clock> started;
13139+                TimePoint<Clock> finished;
13140+            };
13141+        } // namespace Detail
13142+
13143+        struct Chronometer {
13144+        public:
13145+            template <typename Fun>
13146+            void measure(Fun&& fun) { measure(CATCH_FORWARD(fun), is_callable<Fun(int)>()); }
13147+
13148+            int runs() const { return repeats; }
13149+
13150+            Chronometer(Detail::ChronometerConcept& meter, int repeats_)
13151+                : impl(&meter)
13152+                , repeats(repeats_) {}
13153+
13154+        private:
13155+            template <typename Fun>
13156+            void measure(Fun&& fun, std::false_type) {
13157+                measure([&fun](int) { return fun(); }, std::true_type());
13158+            }
13159+
13160+            template <typename Fun>
13161+            void measure(Fun&& fun, std::true_type) {
13162+                Detail::optimizer_barrier();
13163+                impl->start();
13164+                for (int i = 0; i < repeats; ++i) invoke_deoptimized(fun, i);
13165+                impl->finish();
13166+                Detail::optimizer_barrier();
13167+            }
13168+
13169+            Detail::ChronometerConcept* impl;
13170+            int repeats;
13171+        };
13172+    } // namespace Benchmark
13173+} // namespace Catch
13174+
13175+#endif // CATCH_CHRONOMETER_HPP_INCLUDED
13176+
13177+#include <type_traits>
13178+
13179+namespace Catch {
13180+    namespace Benchmark {
13181+        namespace Detail {
13182+            template <typename T, typename U>
13183+            struct is_related
13184+                : std::is_same<std::decay_t<T>, std::decay_t<U>> {};
13185+
13186+            /// We need to reinvent std::function because every piece of code that might add overhead
13187+            /// in a measurement context needs to have consistent performance characteristics so that we
13188+            /// can account for it in the measurement.
13189+            /// Implementations of std::function with optimizations that aren't always applicable, like
13190+            /// small buffer optimizations, are not uncommon.
13191+            /// This is effectively an implementation of std::function without any such optimizations;
13192+            /// it may be slow, but it is consistently slow.
13193+            struct BenchmarkFunction {
13194+            private:
13195+                struct callable {
13196+                    virtual void call(Chronometer meter) const = 0;
13197+                    virtual Catch::Detail::unique_ptr<callable> clone() const = 0;
13198+                    virtual ~callable(); // = default;
13199+
13200+                    callable() = default;
13201+                    callable(callable const&) = default;
13202+                    callable& operator=(callable const&) = default;
13203+                };
13204+                template <typename Fun>
13205+                struct model : public callable {
13206+                    model(Fun&& fun_) : fun(CATCH_MOVE(fun_)) {}
13207+                    model(Fun const& fun_) : fun(fun_) {}
13208+
13209+                    Catch::Detail::unique_ptr<callable> clone() const override {
13210+                        return Catch::Detail::make_unique<model<Fun>>( *this );
13211+                    }
13212+
13213+                    void call(Chronometer meter) const override {
13214+                        call(meter, is_callable<Fun(Chronometer)>());
13215+                    }
13216+                    void call(Chronometer meter, std::true_type) const {
13217+                        fun(meter);
13218+                    }
13219+                    void call(Chronometer meter, std::false_type) const {
13220+                        meter.measure(fun);
13221+                    }
13222+
13223+                    Fun fun;
13224+                };
13225+
13226+                struct do_nothing { void operator()() const {} };
13227+
13228+                template <typename T>
13229+                BenchmarkFunction(model<T>* c) : f(c) {}
13230+
13231+            public:
13232+                BenchmarkFunction()
13233+                    : f(new model<do_nothing>{ {} }) {}
13234+
13235+                template <typename Fun,
13236+                    std::enable_if_t<!is_related<Fun, BenchmarkFunction>::value, int> = 0>
13237+                    BenchmarkFunction(Fun&& fun)
13238+                    : f(new model<std::decay_t<Fun>>(CATCH_FORWARD(fun))) {}
13239+
13240+                BenchmarkFunction( BenchmarkFunction&& that ) noexcept:
13241+                    f( CATCH_MOVE( that.f ) ) {}
13242+
13243+                BenchmarkFunction(BenchmarkFunction const& that)
13244+                    : f(that.f->clone()) {}
13245+
13246+                BenchmarkFunction&
13247+                operator=( BenchmarkFunction&& that ) noexcept {
13248+                    f = CATCH_MOVE( that.f );
13249+                    return *this;
13250+                }
13251+
13252+                BenchmarkFunction& operator=(BenchmarkFunction const& that) {
13253+                    f = that.f->clone();
13254+                    return *this;
13255+                }
13256+
13257+                void operator()(Chronometer meter) const { f->call(meter); }
13258+
13259+            private:
13260+                Catch::Detail::unique_ptr<callable> f;
13261+            };
13262+        } // namespace Detail
13263+    } // namespace Benchmark
13264+} // namespace Catch
13265+
13266+#endif // CATCH_BENCHMARK_FUNCTION_HPP_INCLUDED
13267+
13268+
13269+// Adapted from donated nonius code.
13270+
13271+#ifndef CATCH_REPEAT_HPP_INCLUDED
13272+#define CATCH_REPEAT_HPP_INCLUDED
13273+
13274+#include <type_traits>
13275+
13276+namespace Catch {
13277+    namespace Benchmark {
13278+        namespace Detail {
13279+            template <typename Fun>
13280+            struct repeater {
13281+                void operator()(int k) const {
13282+                    for (int i = 0; i < k; ++i) {
13283+                        fun();
13284+                    }
13285+                }
13286+                Fun fun;
13287+            };
13288+            template <typename Fun>
13289+            repeater<std::decay_t<Fun>> repeat(Fun&& fun) {
13290+                return { CATCH_FORWARD(fun) };
13291+            }
13292+        } // namespace Detail
13293+    } // namespace Benchmark
13294+} // namespace Catch
13295+
13296+#endif // CATCH_REPEAT_HPP_INCLUDED
13297+
13298+
13299+// Adapted from donated nonius code.
13300+
13301+#ifndef CATCH_RUN_FOR_AT_LEAST_HPP_INCLUDED
13302+#define CATCH_RUN_FOR_AT_LEAST_HPP_INCLUDED
13303+
13304+
13305+
13306+// Adapted from donated nonius code.
13307+
13308+#ifndef CATCH_MEASURE_HPP_INCLUDED
13309+#define CATCH_MEASURE_HPP_INCLUDED
13310+
13311+
13312+
13313+// Adapted from donated nonius code.
13314+
13315+#ifndef CATCH_COMPLETE_INVOKE_HPP_INCLUDED
13316+#define CATCH_COMPLETE_INVOKE_HPP_INCLUDED
13317+
13318+
13319+namespace Catch {
13320+    namespace Benchmark {
13321+        namespace Detail {
13322+            template <typename T>
13323+            struct CompleteType { using type = T; };
13324+            template <>
13325+            struct CompleteType<void> { struct type {}; };
13326+
13327+            template <typename T>
13328+            using CompleteType_t = typename CompleteType<T>::type;
13329+
13330+            template <typename Result>
13331+            struct CompleteInvoker {
13332+                template <typename Fun, typename... Args>
13333+                static Result invoke(Fun&& fun, Args&&... args) {
13334+                    return CATCH_FORWARD(fun)(CATCH_FORWARD(args)...);
13335+                }
13336+            };
13337+            template <>
13338+            struct CompleteInvoker<void> {
13339+                template <typename Fun, typename... Args>
13340+                static CompleteType_t<void> invoke(Fun&& fun, Args&&... args) {
13341+                    CATCH_FORWARD(fun)(CATCH_FORWARD(args)...);
13342+                    return {};
13343+                }
13344+            };
13345+
13346+            // invoke and not return void :(
13347+            template <typename Fun, typename... Args>
13348+            CompleteType_t<FunctionReturnType<Fun, Args...>> complete_invoke(Fun&& fun, Args&&... args) {
13349+                return CompleteInvoker<FunctionReturnType<Fun, Args...>>::invoke(CATCH_FORWARD(fun), CATCH_FORWARD(args)...);
13350+            }
13351+
13352+        } // namespace Detail
13353+
13354+        template <typename Fun>
13355+        Detail::CompleteType_t<FunctionReturnType<Fun>> user_code(Fun&& fun) {
13356+            return Detail::complete_invoke(CATCH_FORWARD(fun));
13357+        }
13358+    } // namespace Benchmark
13359+} // namespace Catch
13360+
13361+#endif // CATCH_COMPLETE_INVOKE_HPP_INCLUDED
13362+
13363+
13364+// Adapted from donated nonius code.
13365+
13366+#ifndef CATCH_TIMING_HPP_INCLUDED
13367+#define CATCH_TIMING_HPP_INCLUDED
13368+
13369+
13370+#include <type_traits>
13371+
13372+namespace Catch {
13373+    namespace Benchmark {
13374+        template <typename Result>
13375+        struct Timing {
13376+            IDuration elapsed;
13377+            Result result;
13378+            int iterations;
13379+        };
13380+        template <typename Func, typename... Args>
13381+        using TimingOf = Timing<Detail::CompleteType_t<FunctionReturnType<Func, Args...>>>;
13382+    } // namespace Benchmark
13383+} // namespace Catch
13384+
13385+#endif // CATCH_TIMING_HPP_INCLUDED
13386+
13387+namespace Catch {
13388+    namespace Benchmark {
13389+        namespace Detail {
13390+            template <typename Clock, typename Fun, typename... Args>
13391+            TimingOf<Fun, Args...> measure(Fun&& fun, Args&&... args) {
13392+                auto start = Clock::now();
13393+                auto&& r = Detail::complete_invoke(fun, CATCH_FORWARD(args)...);
13394+                auto end = Clock::now();
13395+                auto delta = end - start;
13396+                return { delta, CATCH_FORWARD(r), 1 };
13397+            }
13398+        } // namespace Detail
13399+    } // namespace Benchmark
13400+} // namespace Catch
13401+
13402+#endif // CATCH_MEASURE_HPP_INCLUDED
13403+
13404+#include <type_traits>
13405+
13406+namespace Catch {
13407+    namespace Benchmark {
13408+        namespace Detail {
13409+            template <typename Clock, typename Fun>
13410+            TimingOf<Fun, int> measure_one(Fun&& fun, int iters, std::false_type) {
13411+                return Detail::measure<Clock>(fun, iters);
13412+            }
13413+            template <typename Clock, typename Fun>
13414+            TimingOf<Fun, Chronometer> measure_one(Fun&& fun, int iters, std::true_type) {
13415+                Detail::ChronometerModel<Clock> meter;
13416+                auto&& result = Detail::complete_invoke(fun, Chronometer(meter, iters));
13417+
13418+                return { meter.elapsed(), CATCH_MOVE(result), iters };
13419+            }
13420+
13421+            template <typename Clock, typename Fun>
13422+            using run_for_at_least_argument_t = std::conditional_t<is_callable<Fun(Chronometer)>::value, Chronometer, int>;
13423+
13424+
13425+            [[noreturn]]
13426+            void throw_optimized_away_error();
13427+
13428+            template <typename Clock, typename Fun>
13429+            TimingOf<Fun, run_for_at_least_argument_t<Clock, Fun>>
13430+                run_for_at_least(IDuration how_long,
13431+                                 const int initial_iterations,
13432+                                 Fun&& fun) {
13433+                auto iters = initial_iterations;
13434+                while (iters < (1 << 30)) {
13435+                    auto&& Timing = measure_one<Clock>(fun, iters, is_callable<Fun(Chronometer)>());
13436+
13437+                    if (Timing.elapsed >= how_long) {
13438+                        return { Timing.elapsed, CATCH_MOVE(Timing.result), iters };
13439+                    }
13440+                    iters *= 2;
13441+                }
13442+                throw_optimized_away_error();
13443+            }
13444+        } // namespace Detail
13445+    } // namespace Benchmark
13446+} // namespace Catch
13447+
13448+#endif // CATCH_RUN_FOR_AT_LEAST_HPP_INCLUDED
13449+
13450+#include <vector>
13451+
13452+namespace Catch {
13453+    namespace Benchmark {
13454+        struct ExecutionPlan {
13455+            int iterations_per_sample;
13456+            FDuration estimated_duration;
13457+            Detail::BenchmarkFunction benchmark;
13458+            FDuration warmup_time;
13459+            int warmup_iterations;
13460+
13461+            template <typename Clock>
13462+            std::vector<FDuration> run(const IConfig &cfg, Environment env) const {
13463+                // warmup a bit
13464+                Detail::run_for_at_least<Clock>(
13465+                    std::chrono::duration_cast<IDuration>( warmup_time ),
13466+                    warmup_iterations,
13467+                    Detail::repeat( []() { return Clock::now(); } )
13468+                );
13469+
13470+                std::vector<FDuration> times;
13471+                const auto num_samples = cfg.benchmarkSamples();
13472+                times.reserve( num_samples );
13473+                for ( size_t i = 0; i < num_samples; ++i ) {
13474+                    Detail::ChronometerModel<Clock> model;
13475+                    this->benchmark( Chronometer( model, iterations_per_sample ) );
13476+                    auto sample_time = model.elapsed() - env.clock_cost.mean;
13477+                    if ( sample_time < FDuration::zero() ) {
13478+                        sample_time = FDuration::zero();
13479+                    }
13480+                    times.push_back(sample_time / iterations_per_sample);
13481+                }
13482+                return times;
13483+            }
13484+        };
13485+    } // namespace Benchmark
13486+} // namespace Catch
13487+
13488+#endif // CATCH_EXECUTION_PLAN_HPP_INCLUDED
13489+
13490+
13491+// Adapted from donated nonius code.
13492+
13493+#ifndef CATCH_ESTIMATE_CLOCK_HPP_INCLUDED
13494+#define CATCH_ESTIMATE_CLOCK_HPP_INCLUDED
13495+
13496+
13497+
13498+// Adapted from donated nonius code.
13499+
13500+#ifndef CATCH_STATS_HPP_INCLUDED
13501+#define CATCH_STATS_HPP_INCLUDED
13502+
13503+
13504+#include <vector>
13505+
13506+namespace Catch {
13507+    namespace Benchmark {
13508+        namespace Detail {
13509+            using sample = std::vector<double>;
13510+
13511+            double weighted_average_quantile( int k,
13512+                                              int q,
13513+                                              double* first,
13514+                                              double* last );
13515+
13516+            OutlierClassification
13517+            classify_outliers( double const* first, double const* last );
13518+
13519+            double mean( double const* first, double const* last );
13520+
13521+            double normal_cdf( double x );
13522+
13523+            double erfc_inv(double x);
13524+
13525+            double normal_quantile(double p);
13526+
13527+            Estimate<double>
13528+            bootstrap( double confidence_level,
13529+                       double* first,
13530+                       double* last,
13531+                       sample const& resample,
13532+                       double ( *estimator )( double const*, double const* ) );
13533+
13534+            struct bootstrap_analysis {
13535+                Estimate<double> mean;
13536+                Estimate<double> standard_deviation;
13537+                double outlier_variance;
13538+            };
13539+
13540+            bootstrap_analysis analyse_samples(double confidence_level,
13541+                                               unsigned int n_resamples,
13542+                                               double* first,
13543+                                               double* last);
13544+        } // namespace Detail
13545+    } // namespace Benchmark
13546+} // namespace Catch
13547+
13548+#endif // CATCH_STATS_HPP_INCLUDED
13549+
13550+#include <algorithm>
13551+#include <vector>
13552+#include <cmath>
13553+
13554+namespace Catch {
13555+    namespace Benchmark {
13556+        namespace Detail {
13557+            template <typename Clock>
13558+            std::vector<double> resolution(int k) {
13559+                std::vector<TimePoint<Clock>> times;
13560+                times.reserve(static_cast<size_t>(k + 1));
13561+                for ( int i = 0; i < k + 1; ++i ) {
13562+                    times.push_back( Clock::now() );
13563+                }
13564+
13565+                std::vector<double> deltas;
13566+                deltas.reserve(static_cast<size_t>(k));
13567+                for ( size_t idx = 1; idx < times.size(); ++idx ) {
13568+                    deltas.push_back( static_cast<double>(
13569+                        ( times[idx] - times[idx - 1] ).count() ) );
13570+                }
13571+
13572+                return deltas;
13573+            }
13574+
13575+            constexpr auto warmup_iterations = 10000;
13576+            constexpr auto warmup_time = std::chrono::milliseconds(100);
13577+            constexpr auto minimum_ticks = 1000;
13578+            constexpr auto warmup_seed = 10000;
13579+            constexpr auto clock_resolution_estimation_time = std::chrono::milliseconds(500);
13580+            constexpr auto clock_cost_estimation_time_limit = std::chrono::seconds(1);
13581+            constexpr auto clock_cost_estimation_tick_limit = 100000;
13582+            constexpr auto clock_cost_estimation_time = std::chrono::milliseconds(10);
13583+            constexpr auto clock_cost_estimation_iterations = 10000;
13584+
13585+            template <typename Clock>
13586+            int warmup() {
13587+                return run_for_at_least<Clock>(warmup_time, warmup_seed, &resolution<Clock>)
13588+                    .iterations;
13589+            }
13590+            template <typename Clock>
13591+            EnvironmentEstimate estimate_clock_resolution(int iterations) {
13592+                auto r = run_for_at_least<Clock>(clock_resolution_estimation_time, iterations, &resolution<Clock>)
13593+                    .result;
13594+                return {
13595+                    FDuration(mean(r.data(), r.data() + r.size())),
13596+                    classify_outliers(r.data(), r.data() + r.size()),
13597+                };
13598+            }
13599+            template <typename Clock>
13600+            EnvironmentEstimate estimate_clock_cost(FDuration resolution) {
13601+                auto time_limit = (std::min)(
13602+                    resolution * clock_cost_estimation_tick_limit,
13603+                    FDuration(clock_cost_estimation_time_limit));
13604+                auto time_clock = [](int k) {
13605+                    return Detail::measure<Clock>([k] {
13606+                        for (int i = 0; i < k; ++i) {
13607+                            volatile auto ignored = Clock::now();
13608+                            (void)ignored;
13609+                        }
13610+                    }).elapsed;
13611+                };
13612+                time_clock(1);
13613+                int iters = clock_cost_estimation_iterations;
13614+                auto&& r = run_for_at_least<Clock>(clock_cost_estimation_time, iters, time_clock);
13615+                std::vector<double> times;
13616+                int nsamples = static_cast<int>(std::ceil(time_limit / r.elapsed));
13617+                times.reserve(static_cast<size_t>(nsamples));
13618+                for ( int s = 0; s < nsamples; ++s ) {
13619+                    times.push_back( static_cast<double>(
13620+                        ( time_clock( r.iterations ) / r.iterations )
13621+                            .count() ) );
13622+                }
13623+                return {
13624+                    FDuration(mean(times.data(), times.data() + times.size())),
13625+                    classify_outliers(times.data(), times.data() + times.size()),
13626+                };
13627+            }
13628+
13629+            template <typename Clock>
13630+            Environment measure_environment() {
13631+#if defined(__clang__)
13632+#    pragma clang diagnostic push
13633+#    pragma clang diagnostic ignored "-Wexit-time-destructors"
13634+#endif
13635+                static Catch::Detail::unique_ptr<Environment> env;
13636+#if defined(__clang__)
13637+#    pragma clang diagnostic pop
13638+#endif
13639+                if (env) {
13640+                    return *env;
13641+                }
13642+
13643+                auto iters = Detail::warmup<Clock>();
13644+                auto resolution = Detail::estimate_clock_resolution<Clock>(iters);
13645+                auto cost = Detail::estimate_clock_cost<Clock>(resolution.mean);
13646+
13647+                env = Catch::Detail::make_unique<Environment>( Environment{resolution, cost} );
13648+                return *env;
13649+            }
13650+        } // namespace Detail
13651+    } // namespace Benchmark
13652+} // namespace Catch
13653+
13654+#endif // CATCH_ESTIMATE_CLOCK_HPP_INCLUDED
13655+
13656+
13657+// Adapted from donated nonius code.
13658+
13659+#ifndef CATCH_ANALYSE_HPP_INCLUDED
13660+#define CATCH_ANALYSE_HPP_INCLUDED
13661+
13662+
13663+
13664+// Adapted from donated nonius code.
13665+
13666+#ifndef CATCH_SAMPLE_ANALYSIS_HPP_INCLUDED
13667+#define CATCH_SAMPLE_ANALYSIS_HPP_INCLUDED
13668+
13669+
13670+#include <vector>
13671+
13672+namespace Catch {
13673+    namespace Benchmark {
13674+        struct SampleAnalysis {
13675+            std::vector<FDuration> samples;
13676+            Estimate<FDuration> mean;
13677+            Estimate<FDuration> standard_deviation;
13678+            OutlierClassification outliers;
13679+            double outlier_variance;
13680+        };
13681+    } // namespace Benchmark
13682+} // namespace Catch
13683+
13684+#endif // CATCH_SAMPLE_ANALYSIS_HPP_INCLUDED
13685+
13686+
13687+namespace Catch {
13688+    class IConfig;
13689+
13690+    namespace Benchmark {
13691+        namespace Detail {
13692+            SampleAnalysis analyse(const IConfig &cfg, FDuration* first, FDuration* last);
13693+        } // namespace Detail
13694+    } // namespace Benchmark
13695+} // namespace Catch
13696+
13697+#endif // CATCH_ANALYSE_HPP_INCLUDED
13698+
13699+#include <algorithm>
13700+#include <chrono>
13701+#include <exception>
13702+#include <string>
13703+#include <cmath>
13704+
13705+namespace Catch {
13706+    namespace Benchmark {
13707+        struct Benchmark {
13708+            Benchmark(std::string&& benchmarkName)
13709+                : name(CATCH_MOVE(benchmarkName)) {}
13710+
13711+            template <class FUN>
13712+            Benchmark(std::string&& benchmarkName , FUN &&func)
13713+                : fun(CATCH_MOVE(func)), name(CATCH_MOVE(benchmarkName)) {}
13714+
13715+            template <typename Clock>
13716+            ExecutionPlan prepare(const IConfig &cfg, Environment env) const {
13717+                auto min_time = env.clock_resolution.mean * Detail::minimum_ticks;
13718+                auto run_time = std::max(min_time, std::chrono::duration_cast<decltype(min_time)>(cfg.benchmarkWarmupTime()));
13719+                auto&& test = Detail::run_for_at_least<Clock>(std::chrono::duration_cast<IDuration>(run_time), 1, fun);
13720+                int new_iters = static_cast<int>(std::ceil(min_time * test.iterations / test.elapsed));
13721+                return { new_iters, test.elapsed / test.iterations * new_iters * cfg.benchmarkSamples(), fun, std::chrono::duration_cast<FDuration>(cfg.benchmarkWarmupTime()), Detail::warmup_iterations };
13722+            }
13723+
13724+            template <typename Clock = default_clock>
13725+            void run() {
13726+                static_assert( Clock::is_steady,
13727+                               "Benchmarking clock should be steady" );
13728+                auto const* cfg = getCurrentContext().getConfig();
13729+
13730+                auto env = Detail::measure_environment<Clock>();
13731+
13732+                getResultCapture().benchmarkPreparing(name);
13733+                CATCH_TRY{
13734+                    auto plan = user_code([&] {
13735+                        return prepare<Clock>(*cfg, env);
13736+                    });
13737+
13738+                    BenchmarkInfo info {
13739+                        CATCH_MOVE(name),
13740+                        plan.estimated_duration.count(),
13741+                        plan.iterations_per_sample,
13742+                        cfg->benchmarkSamples(),
13743+                        cfg->benchmarkResamples(),
13744+                        env.clock_resolution.mean.count(),
13745+                        env.clock_cost.mean.count()
13746+                    };
13747+
13748+                    getResultCapture().benchmarkStarting(info);
13749+
13750+                    auto samples = user_code([&] {
13751+                        return plan.template run<Clock>(*cfg, env);
13752+                    });
13753+
13754+                    auto analysis = Detail::analyse(*cfg, samples.data(), samples.data() + samples.size());
13755+                    BenchmarkStats<> stats{ CATCH_MOVE(info), CATCH_MOVE(analysis.samples), analysis.mean, analysis.standard_deviation, analysis.outliers, analysis.outlier_variance };
13756+                    getResultCapture().benchmarkEnded(stats);
13757+                } CATCH_CATCH_ANON (TestFailureException const&) {
13758+                    getResultCapture().benchmarkFailed("Benchmark failed due to failed assertion"_sr);
13759+                } CATCH_CATCH_ALL{
13760+                    getResultCapture().benchmarkFailed(translateActiveException());
13761+                    // We let the exception go further up so that the
13762+                    // test case is marked as failed.
13763+                    std::rethrow_exception(std::current_exception());
13764+                }
13765+            }
13766+
13767+            // sets lambda to be used in fun *and* executes benchmark!
13768+            template <typename Fun, std::enable_if_t<!Detail::is_related<Fun, Benchmark>::value, int> = 0>
13769+                Benchmark & operator=(Fun func) {
13770+                auto const* cfg = getCurrentContext().getConfig();
13771+                if (!cfg->skipBenchmarks()) {
13772+                    fun = Detail::BenchmarkFunction(func);
13773+                    run();
13774+                }
13775+                return *this;
13776+            }
13777+
13778+            explicit operator bool() {
13779+                return true;
13780+            }
13781+
13782+        private:
13783+            Detail::BenchmarkFunction fun;
13784+            std::string name;
13785+        };
13786+    }
13787+} // namespace Catch
13788+
13789+#define INTERNAL_CATCH_GET_1_ARG(arg1, arg2, ...) arg1
13790+#define INTERNAL_CATCH_GET_2_ARG(arg1, arg2, ...) arg2
13791+
13792+#define INTERNAL_CATCH_BENCHMARK(BenchmarkName, name, benchmarkIndex)\
13793+    if( Catch::Benchmark::Benchmark BenchmarkName{name} ) \
13794+        BenchmarkName = [&](int benchmarkIndex)
13795+
13796+#define INTERNAL_CATCH_BENCHMARK_ADVANCED(BenchmarkName, name)\
13797+    if( Catch::Benchmark::Benchmark BenchmarkName{name} ) \
13798+        BenchmarkName = [&]
13799+
13800+#if defined(CATCH_CONFIG_PREFIX_ALL)
13801+
13802+#define CATCH_BENCHMARK(...) \
13803+    INTERNAL_CATCH_BENCHMARK(INTERNAL_CATCH_UNIQUE_NAME(CATCH2_INTERNAL_BENCHMARK_), INTERNAL_CATCH_GET_1_ARG(__VA_ARGS__,,), INTERNAL_CATCH_GET_2_ARG(__VA_ARGS__,,))
13804+#define CATCH_BENCHMARK_ADVANCED(name) \
13805+    INTERNAL_CATCH_BENCHMARK_ADVANCED(INTERNAL_CATCH_UNIQUE_NAME(CATCH2_INTERNAL_BENCHMARK_), name)
13806+
13807+#else
13808+
13809+#define BENCHMARK(...) \
13810+    INTERNAL_CATCH_BENCHMARK(INTERNAL_CATCH_UNIQUE_NAME(CATCH2_INTERNAL_BENCHMARK_), INTERNAL_CATCH_GET_1_ARG(__VA_ARGS__,,), INTERNAL_CATCH_GET_2_ARG(__VA_ARGS__,,))
13811+#define BENCHMARK_ADVANCED(name) \
13812+    INTERNAL_CATCH_BENCHMARK_ADVANCED(INTERNAL_CATCH_UNIQUE_NAME(CATCH2_INTERNAL_BENCHMARK_), name)
13813+
13814+#endif
13815+
13816+#endif // CATCH_BENCHMARK_HPP_INCLUDED
13817+
13818+
13819+// Adapted from donated nonius code.
13820+
13821+#ifndef CATCH_CONSTRUCTOR_HPP_INCLUDED
13822+#define CATCH_CONSTRUCTOR_HPP_INCLUDED
13823+
13824+
13825+#include <type_traits>
13826+
13827+namespace Catch {
13828+    namespace Benchmark {
13829+        namespace Detail {
13830+            template <typename T, bool Destruct>
13831+            struct ObjectStorage
13832+            {
13833+                ObjectStorage() = default;
13834+
13835+                ObjectStorage(const ObjectStorage& other)
13836+                {
13837+                    new(&data) T(other.stored_object());
13838+                }
13839+
13840+                ObjectStorage(ObjectStorage&& other)
13841+                {
13842+                    new(data) T(CATCH_MOVE(other.stored_object()));
13843+                }
13844+
13845+                ~ObjectStorage() { destruct_on_exit<T>(); }
13846+
13847+                template <typename... Args>
13848+                void construct(Args&&... args)
13849+                {
13850+                    new (data) T(CATCH_FORWARD(args)...);
13851+                }
13852+
13853+                template <bool AllowManualDestruction = !Destruct>
13854+                std::enable_if_t<AllowManualDestruction> destruct()
13855+                {
13856+                    stored_object().~T();
13857+                }
13858+
13859+            private:
13860+                // If this is a constructor benchmark, destruct the underlying object
13861+                template <typename U>
13862+                void destruct_on_exit(std::enable_if_t<Destruct, U>* = nullptr) { destruct<true>(); }
13863+                // Otherwise, don't
13864+                template <typename U>
13865+                void destruct_on_exit(std::enable_if_t<!Destruct, U>* = nullptr) { }
13866+
13867+#if defined( __GNUC__ ) && __GNUC__ <= 6
13868+#    pragma GCC diagnostic push
13869+#    pragma GCC diagnostic ignored "-Wstrict-aliasing"
13870+#endif
13871+                T& stored_object() { return *reinterpret_cast<T*>( data ); }
13872+
13873+                T const& stored_object() const {
13874+                    return *reinterpret_cast<T const*>( data );
13875+                }
13876+#if defined( __GNUC__ ) && __GNUC__ <= 6
13877+#    pragma GCC diagnostic pop
13878+#endif
13879+
13880+                alignas( T ) unsigned char data[sizeof( T )]{};
13881+            };
13882+        } // namespace Detail
13883+
13884+        template <typename T>
13885+        using storage_for = Detail::ObjectStorage<T, true>;
13886+
13887+        template <typename T>
13888+        using destructable_object = Detail::ObjectStorage<T, false>;
13889+    } // namespace Benchmark
13890+} // namespace Catch
13891+
13892+#endif // CATCH_CONSTRUCTOR_HPP_INCLUDED
13893+
13894+#endif // CATCH_BENCHMARK_ALL_HPP_INCLUDED
13895+
13896+
13897+#ifndef CATCH_APPROX_HPP_INCLUDED
13898+#define CATCH_APPROX_HPP_INCLUDED
13899+
13900+
13901+
13902+#ifndef CATCH_TOSTRING_HPP_INCLUDED
13903+#define CATCH_TOSTRING_HPP_INCLUDED
13904+
13905+
13906+#include <vector>
13907+#include <cstddef>
13908+#include <type_traits>
13909+#include <string>
13910+
13911+
13912+
13913+
13914+/** \file
13915+ * Wrapper for the WCHAR configuration option
13916+ *
13917+ * We want to support platforms that do not provide `wchar_t`, so we
13918+ * sometimes have to disable providing wchar_t overloads through Catch2,
13919+ * e.g. the StringMaker specialization for `std::wstring`.
13920+ */
13921+
13922+#ifndef CATCH_CONFIG_WCHAR_HPP_INCLUDED
13923+#define CATCH_CONFIG_WCHAR_HPP_INCLUDED
13924+
13925+
13926+// We assume that WCHAR should be enabled by default, and only disabled
13927+// for a shortlist (so far only DJGPP) of compilers.
13928+
13929+#if defined(__DJGPP__)
13930+#  define CATCH_INTERNAL_CONFIG_NO_WCHAR
13931+#endif // __DJGPP__
13932+
13933+#if !defined( CATCH_INTERNAL_CONFIG_NO_WCHAR ) && \
13934+    !defined( CATCH_CONFIG_NO_WCHAR ) && \
13935+    !defined( CATCH_CONFIG_WCHAR )
13936+#    define CATCH_CONFIG_WCHAR
13937+#endif
13938+
13939+#endif // CATCH_CONFIG_WCHAR_HPP_INCLUDED
13940+
13941+
13942+#ifndef CATCH_REUSABLE_STRING_STREAM_HPP_INCLUDED
13943+#define CATCH_REUSABLE_STRING_STREAM_HPP_INCLUDED
13944+
13945+
13946+#include <iosfwd>
13947+#include <cstddef>
13948+#include <ostream>
13949+#include <string>
13950+
13951+namespace Catch {
13952+
13953+    class ReusableStringStream : Detail::NonCopyable {
13954+        std::size_t m_index;
13955+        std::ostream* m_oss;
13956+    public:
13957+        ReusableStringStream();
13958+        ~ReusableStringStream();
13959+
13960+        //! Returns the serialized state
13961+        std::string str() const;
13962+        //! Sets internal state to `str`
13963+        void str(std::string const& str);
13964+
13965+#if defined(__GNUC__) && !defined(__clang__)
13966+#pragma GCC diagnostic push
13967+// Old versions of GCC do not understand -Wnonnull-compare
13968+#pragma GCC diagnostic ignored "-Wpragmas"
13969+// Streaming a function pointer triggers Waddress and Wnonnull-compare
13970+// on GCC, because it implicitly converts it to bool and then decides
13971+// that the check it uses (a? true : false) is tautological and cannot
13972+// be null...
13973+#pragma GCC diagnostic ignored "-Waddress"
13974+#pragma GCC diagnostic ignored "-Wnonnull-compare"
13975+#endif
13976+
13977+        template<typename T>
13978+        auto operator << ( T const& value ) -> ReusableStringStream& {
13979+            *m_oss << value;
13980+            return *this;
13981+        }
13982+
13983+#if defined(__GNUC__) && !defined(__clang__)
13984+#pragma GCC diagnostic pop
13985+#endif
13986+        auto get() -> std::ostream& { return *m_oss; }
13987+    };
13988+}
13989+
13990+#endif // CATCH_REUSABLE_STRING_STREAM_HPP_INCLUDED
13991+
13992+
13993+#ifndef CATCH_VOID_TYPE_HPP_INCLUDED
13994+#define CATCH_VOID_TYPE_HPP_INCLUDED
13995+
13996+
13997+namespace Catch {
13998+    namespace Detail {
13999+
14000+        template <typename...>
14001+        struct make_void { using type = void; };
14002+
14003+        template <typename... Ts>
14004+        using void_t = typename make_void<Ts...>::type;
14005+
14006+    } // namespace Detail
14007+} // namespace Catch
14008+
14009+
14010+#endif // CATCH_VOID_TYPE_HPP_INCLUDED
14011+
14012+
14013+#ifndef CATCH_INTERFACES_ENUM_VALUES_REGISTRY_HPP_INCLUDED
14014+#define CATCH_INTERFACES_ENUM_VALUES_REGISTRY_HPP_INCLUDED
14015+
14016+
14017+#include <vector>
14018+
14019+namespace Catch {
14020+
14021+    namespace Detail {
14022+        struct EnumInfo {
14023+            StringRef m_name;
14024+            std::vector<std::pair<int, StringRef>> m_values;
14025+
14026+            ~EnumInfo();
14027+
14028+            StringRef lookup( int value ) const;
14029+        };
14030+    } // namespace Detail
14031+
14032+    class IMutableEnumValuesRegistry {
14033+    public:
14034+        virtual ~IMutableEnumValuesRegistry(); // = default;
14035+
14036+        virtual Detail::EnumInfo const& registerEnum( StringRef enumName, StringRef allEnums, std::vector<int> const& values ) = 0;
14037+
14038+        template<typename E>
14039+        Detail::EnumInfo const& registerEnum( StringRef enumName, StringRef allEnums, std::initializer_list<E> values ) {
14040+            static_assert(sizeof(int) >= sizeof(E), "Cannot serialize enum to int");
14041+            std::vector<int> intValues;
14042+            intValues.reserve( values.size() );
14043+            for( auto enumValue : values )
14044+                intValues.push_back( static_cast<int>( enumValue ) );
14045+            return registerEnum( enumName, allEnums, intValues );
14046+        }
14047+    };
14048+
14049+} // Catch
14050+
14051+#endif // CATCH_INTERFACES_ENUM_VALUES_REGISTRY_HPP_INCLUDED
14052+
14053+#ifdef CATCH_CONFIG_CPP17_STRING_VIEW
14054+#include <string_view>
14055+#endif
14056+
14057+#ifdef _MSC_VER
14058+#pragma warning(push)
14059+#pragma warning(disable:4180) // We attempt to stream a function (address) by const&, which MSVC complains about but is harmless
14060+#endif
14061+
14062+// We need a dummy global operator<< so we can bring it into Catch namespace later
14063+struct Catch_global_namespace_dummy{};
14064+std::ostream& operator<<(std::ostream&, Catch_global_namespace_dummy);
14065+
14066+namespace Catch {
14067+    // Bring in global namespace operator<< for ADL lookup in
14068+    // `IsStreamInsertable` below.
14069+    using ::operator<<;
14070+
14071+    namespace Detail {
14072+
14073+        inline std::size_t catch_strnlen(const char *str, std::size_t n) {
14074+            auto ret = std::char_traits<char>::find(str, n, '\0');
14075+            if (ret != nullptr) {
14076+                return static_cast<std::size_t>(ret - str);
14077+            }
14078+            return n;
14079+        }
14080+
14081+        constexpr StringRef unprintableString = "{?}"_sr;
14082+
14083+        //! Encases `string in quotes, and optionally escapes invisibles
14084+        std::string convertIntoString( StringRef string, bool escapeInvisibles );
14085+
14086+        //! Encases `string` in quotes, and escapes invisibles if user requested
14087+        //! it via CLI
14088+        std::string convertIntoString( StringRef string );
14089+
14090+        std::string rawMemoryToString( const void *object, std::size_t size );
14091+
14092+        template<typename T>
14093+        std::string rawMemoryToString( const T& object ) {
14094+          return rawMemoryToString( &object, sizeof(object) );
14095+        }
14096+
14097+        template<typename T>
14098+        class IsStreamInsertable {
14099+            template<typename Stream, typename U>
14100+            static auto test(int)
14101+                -> decltype(std::declval<Stream&>() << std::declval<U>(), std::true_type());
14102+
14103+            template<typename, typename>
14104+            static auto test(...)->std::false_type;
14105+
14106+        public:
14107+            static const bool value = decltype(test<std::ostream, const T&>(0))::value;
14108+        };
14109+
14110+        template<typename E>
14111+        std::string convertUnknownEnumToString( E e );
14112+
14113+        template<typename T>
14114+        std::enable_if_t<
14115+            !std::is_enum<T>::value && !std::is_base_of<std::exception, T>::value,
14116+        std::string> convertUnstreamable( T const& ) {
14117+            return std::string(Detail::unprintableString);
14118+        }
14119+        template<typename T>
14120+        std::enable_if_t<
14121+            !std::is_enum<T>::value && std::is_base_of<std::exception, T>::value,
14122+         std::string> convertUnstreamable(T const& ex) {
14123+            return ex.what();
14124+        }
14125+
14126+
14127+        template<typename T>
14128+        std::enable_if_t<
14129+            std::is_enum<T>::value,
14130+        std::string> convertUnstreamable( T const& value ) {
14131+            return convertUnknownEnumToString( value );
14132+        }
14133+
14134+#if defined(_MANAGED)
14135+        //! Convert a CLR string to a utf8 std::string
14136+        template<typename T>
14137+        std::string clrReferenceToString( T^ ref ) {
14138+            if (ref == nullptr)
14139+                return std::string("null");
14140+            auto bytes = System::Text::Encoding::UTF8->GetBytes(ref->ToString());
14141+            cli::pin_ptr<System::Byte> p = &bytes[0];
14142+            return std::string(reinterpret_cast<char const *>(p), bytes->Length);
14143+        }
14144+#endif
14145+
14146+    } // namespace Detail
14147+
14148+
14149+    template <typename T, typename = void>
14150+    struct StringMaker {
14151+        template <typename Fake = T>
14152+        static
14153+        std::enable_if_t<::Catch::Detail::IsStreamInsertable<Fake>::value, std::string>
14154+            convert(const Fake& value) {
14155+                ReusableStringStream rss;
14156+                // NB: call using the function-like syntax to avoid ambiguity with
14157+                // user-defined templated operator<< under clang.
14158+                rss.operator<<(value);
14159+                return rss.str();
14160+        }
14161+
14162+        template <typename Fake = T>
14163+        static
14164+        std::enable_if_t<!::Catch::Detail::IsStreamInsertable<Fake>::value, std::string>
14165+            convert( const Fake& value ) {
14166+#if !defined(CATCH_CONFIG_FALLBACK_STRINGIFIER)
14167+            return Detail::convertUnstreamable(value);
14168+#else
14169+            return CATCH_CONFIG_FALLBACK_STRINGIFIER(value);
14170+#endif
14171+        }
14172+    };
14173+
14174+    namespace Detail {
14175+
14176+        // This function dispatches all stringification requests inside of Catch.
14177+        // Should be preferably called fully qualified, like ::Catch::Detail::stringify
14178+        template <typename T>
14179+        std::string stringify(const T& e) {
14180+            return ::Catch::StringMaker<std::remove_cv_t<std::remove_reference_t<T>>>::convert(e);
14181+        }
14182+
14183+        template<typename E>
14184+        std::string convertUnknownEnumToString( E e ) {
14185+            return ::Catch::Detail::stringify(static_cast<std::underlying_type_t<E>>(e));
14186+        }
14187+
14188+#if defined(_MANAGED)
14189+        template <typename T>
14190+        std::string stringify( T^ e ) {
14191+            return ::Catch::StringMaker<T^>::convert(e);
14192+        }
14193+#endif
14194+
14195+    } // namespace Detail
14196+
14197+    // Some predefined specializations
14198+
14199+    template<>
14200+    struct StringMaker<std::string> {
14201+        static std::string convert(const std::string& str);
14202+    };
14203+
14204+#ifdef CATCH_CONFIG_CPP17_STRING_VIEW
14205+    template<>
14206+    struct StringMaker<std::string_view> {
14207+        static std::string convert(std::string_view str);
14208+    };
14209+#endif
14210+
14211+    template<>
14212+    struct StringMaker<char const *> {
14213+        static std::string convert(char const * str);
14214+    };
14215+    template<>
14216+    struct StringMaker<char *> {
14217+        static std::string convert(char * str);
14218+    };
14219+
14220+#if defined(CATCH_CONFIG_WCHAR)
14221+    template<>
14222+    struct StringMaker<std::wstring> {
14223+        static std::string convert(const std::wstring& wstr);
14224+    };
14225+
14226+# ifdef CATCH_CONFIG_CPP17_STRING_VIEW
14227+    template<>
14228+    struct StringMaker<std::wstring_view> {
14229+        static std::string convert(std::wstring_view str);
14230+    };
14231+# endif
14232+
14233+    template<>
14234+    struct StringMaker<wchar_t const *> {
14235+        static std::string convert(wchar_t const * str);
14236+    };
14237+    template<>
14238+    struct StringMaker<wchar_t *> {
14239+        static std::string convert(wchar_t * str);
14240+    };
14241+#endif // CATCH_CONFIG_WCHAR
14242+
14243+    template<size_t SZ>
14244+    struct StringMaker<char[SZ]> {
14245+        static std::string convert(char const* str) {
14246+            return Detail::convertIntoString(
14247+                StringRef( str, Detail::catch_strnlen( str, SZ ) ) );
14248+        }
14249+    };
14250+    template<size_t SZ>
14251+    struct StringMaker<signed char[SZ]> {
14252+        static std::string convert(signed char const* str) {
14253+            auto reinterpreted = reinterpret_cast<char const*>(str);
14254+            return Detail::convertIntoString(
14255+                StringRef(reinterpreted, Detail::catch_strnlen(reinterpreted, SZ)));
14256+        }
14257+    };
14258+    template<size_t SZ>
14259+    struct StringMaker<unsigned char[SZ]> {
14260+        static std::string convert(unsigned char const* str) {
14261+            auto reinterpreted = reinterpret_cast<char const*>(str);
14262+            return Detail::convertIntoString(
14263+                StringRef(reinterpreted, Detail::catch_strnlen(reinterpreted, SZ)));
14264+        }
14265+    };
14266+
14267+#if defined(CATCH_CONFIG_CPP17_BYTE)
14268+    template<>
14269+    struct StringMaker<std::byte> {
14270+        static std::string convert(std::byte value);
14271+    };
14272+#endif // defined(CATCH_CONFIG_CPP17_BYTE)
14273+    template<>
14274+    struct StringMaker<int> {
14275+        static std::string convert(int value);
14276+    };
14277+    template<>
14278+    struct StringMaker<long> {
14279+        static std::string convert(long value);
14280+    };
14281+    template<>
14282+    struct StringMaker<long long> {
14283+        static std::string convert(long long value);
14284+    };
14285+    template<>
14286+    struct StringMaker<unsigned int> {
14287+        static std::string convert(unsigned int value);
14288+    };
14289+    template<>
14290+    struct StringMaker<unsigned long> {
14291+        static std::string convert(unsigned long value);
14292+    };
14293+    template<>
14294+    struct StringMaker<unsigned long long> {
14295+        static std::string convert(unsigned long long value);
14296+    };
14297+
14298+    template<>
14299+    struct StringMaker<bool> {
14300+        static std::string convert(bool b) {
14301+            using namespace std::string_literals;
14302+            return b ? "true"s : "false"s;
14303+        }
14304+    };
14305+
14306+    template<>
14307+    struct StringMaker<char> {
14308+        static std::string convert(char c);
14309+    };
14310+    template<>
14311+    struct StringMaker<signed char> {
14312+        static std::string convert(signed char value);
14313+    };
14314+    template<>
14315+    struct StringMaker<unsigned char> {
14316+        static std::string convert(unsigned char value);
14317+    };
14318+
14319+    template<>
14320+    struct StringMaker<std::nullptr_t> {
14321+        static std::string convert(std::nullptr_t) {
14322+            using namespace std::string_literals;
14323+            return "nullptr"s;
14324+        }
14325+    };
14326+
14327+    template<>
14328+    struct StringMaker<float> {
14329+        static std::string convert(float value);
14330+        CATCH_EXPORT static int precision;
14331+    };
14332+
14333+    template<>
14334+    struct StringMaker<double> {
14335+        static std::string convert(double value);
14336+        CATCH_EXPORT static int precision;
14337+    };
14338+
14339+    template <typename T>
14340+    struct StringMaker<T*> {
14341+        template <typename U>
14342+        static std::string convert(U* p) {
14343+            if (p) {
14344+                return ::Catch::Detail::rawMemoryToString(p);
14345+            } else {
14346+                return "nullptr";
14347+            }
14348+        }
14349+    };
14350+
14351+    template <typename R, typename C>
14352+    struct StringMaker<R C::*> {
14353+        static std::string convert(R C::* p) {
14354+            if (p) {
14355+                return ::Catch::Detail::rawMemoryToString(p);
14356+            } else {
14357+                return "nullptr";
14358+            }
14359+        }
14360+    };
14361+
14362+#if defined(_MANAGED)
14363+    template <typename T>
14364+    struct StringMaker<T^> {
14365+        static std::string convert( T^ ref ) {
14366+            return ::Catch::Detail::clrReferenceToString(ref);
14367+        }
14368+    };
14369+#endif
14370+
14371+    namespace Detail {
14372+        template<typename InputIterator, typename Sentinel = InputIterator>
14373+        std::string rangeToString(InputIterator first, Sentinel last) {
14374+            ReusableStringStream rss;
14375+            rss << "{ ";
14376+            if (first != last) {
14377+                rss << ::Catch::Detail::stringify(*first);
14378+                for (++first; first != last; ++first)
14379+                    rss << ", " << ::Catch::Detail::stringify(*first);
14380+            }
14381+            rss << " }";
14382+            return rss.str();
14383+        }
14384+    }
14385+
14386+} // namespace Catch
14387+
14388+//////////////////////////////////////////////////////
14389+// Separate std-lib types stringification, so it can be selectively enabled
14390+// This means that we do not bring in their headers
14391+
14392+#if defined(CATCH_CONFIG_ENABLE_ALL_STRINGMAKERS)
14393+#  define CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER
14394+#  define CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER
14395+#  define CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER
14396+#  define CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER
14397+#endif
14398+
14399+// Separate std::pair specialization
14400+#if defined(CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER)
14401+#include <utility>
14402+namespace Catch {
14403+    template<typename T1, typename T2>
14404+    struct StringMaker<std::pair<T1, T2> > {
14405+        static std::string convert(const std::pair<T1, T2>& pair) {
14406+            ReusableStringStream rss;
14407+            rss << "{ "
14408+                << ::Catch::Detail::stringify(pair.first)
14409+                << ", "
14410+                << ::Catch::Detail::stringify(pair.second)
14411+                << " }";
14412+            return rss.str();
14413+        }
14414+    };
14415+}
14416+#endif // CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER
14417+
14418+#if defined(CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER) && defined(CATCH_CONFIG_CPP17_OPTIONAL)
14419+#include <optional>
14420+namespace Catch {
14421+    template<typename T>
14422+    struct StringMaker<std::optional<T> > {
14423+        static std::string convert(const std::optional<T>& optional) {
14424+            if (optional.has_value()) {
14425+                return ::Catch::Detail::stringify(*optional);
14426+            } else {
14427+                return "{ }";
14428+            }
14429+        }
14430+    };
14431+    template <>
14432+    struct StringMaker<std::nullopt_t> {
14433+        static std::string convert(const std::nullopt_t&) {
14434+            return "{ }";
14435+        }
14436+    };
14437+}
14438+#endif // CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER
14439+
14440+// Separate std::tuple specialization
14441+#if defined(CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER)
14442+#include <tuple>
14443+namespace Catch {
14444+    namespace Detail {
14445+        template<
14446+            typename Tuple,
14447+            std::size_t N = 0,
14448+            bool = (N < std::tuple_size<Tuple>::value)
14449+            >
14450+            struct TupleElementPrinter {
14451+            static void print(const Tuple& tuple, std::ostream& os) {
14452+                os << (N ? ", " : " ")
14453+                    << ::Catch::Detail::stringify(std::get<N>(tuple));
14454+                TupleElementPrinter<Tuple, N + 1>::print(tuple, os);
14455+            }
14456+        };
14457+
14458+        template<
14459+            typename Tuple,
14460+            std::size_t N
14461+        >
14462+            struct TupleElementPrinter<Tuple, N, false> {
14463+            static void print(const Tuple&, std::ostream&) {}
14464+        };
14465+
14466+    }
14467+
14468+
14469+    template<typename ...Types>
14470+    struct StringMaker<std::tuple<Types...>> {
14471+        static std::string convert(const std::tuple<Types...>& tuple) {
14472+            ReusableStringStream rss;
14473+            rss << '{';
14474+            Detail::TupleElementPrinter<std::tuple<Types...>>::print(tuple, rss.get());
14475+            rss << " }";
14476+            return rss.str();
14477+        }
14478+    };
14479+}
14480+#endif // CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER
14481+
14482+#if defined(CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER) && defined(CATCH_CONFIG_CPP17_VARIANT)
14483+#include <variant>
14484+namespace Catch {
14485+    template<>
14486+    struct StringMaker<std::monostate> {
14487+        static std::string convert(const std::monostate&) {
14488+            return "{ }";
14489+        }
14490+    };
14491+
14492+    template<typename... Elements>
14493+    struct StringMaker<std::variant<Elements...>> {
14494+        static std::string convert(const std::variant<Elements...>& variant) {
14495+            if (variant.valueless_by_exception()) {
14496+                return "{valueless variant}";
14497+            } else {
14498+                return std::visit(
14499+                    [](const auto& value) {
14500+                        return ::Catch::Detail::stringify(value);
14501+                    },
14502+                    variant
14503+                );
14504+            }
14505+        }
14506+    };
14507+}
14508+#endif // CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER
14509+
14510+namespace Catch {
14511+    // Import begin/ end from std here
14512+    using std::begin;
14513+    using std::end;
14514+
14515+    namespace Detail {
14516+        template <typename T, typename = void>
14517+        struct is_range_impl : std::false_type {};
14518+
14519+        template <typename T>
14520+        struct is_range_impl<T, void_t<decltype(begin(std::declval<T>()))>> : std::true_type {};
14521+    } // namespace Detail
14522+
14523+    template <typename T>
14524+    struct is_range : Detail::is_range_impl<T> {};
14525+
14526+#if defined(_MANAGED) // Managed types are never ranges
14527+    template <typename T>
14528+    struct is_range<T^> {
14529+        static const bool value = false;
14530+    };
14531+#endif
14532+
14533+    template<typename Range>
14534+    std::string rangeToString( Range const& range ) {
14535+        return ::Catch::Detail::rangeToString( begin( range ), end( range ) );
14536+    }
14537+
14538+    // Handle vector<bool> specially
14539+    template<typename Allocator>
14540+    std::string rangeToString( std::vector<bool, Allocator> const& v ) {
14541+        ReusableStringStream rss;
14542+        rss << "{ ";
14543+        bool first = true;
14544+        for( bool b : v ) {
14545+            if( first )
14546+                first = false;
14547+            else
14548+                rss << ", ";
14549+            rss << ::Catch::Detail::stringify( b );
14550+        }
14551+        rss << " }";
14552+        return rss.str();
14553+    }
14554+
14555+    template<typename R>
14556+    struct StringMaker<R, std::enable_if_t<is_range<R>::value && !::Catch::Detail::IsStreamInsertable<R>::value>> {
14557+        static std::string convert( R const& range ) {
14558+            return rangeToString( range );
14559+        }
14560+    };
14561+
14562+    template <typename T, size_t SZ>
14563+    struct StringMaker<T[SZ]> {
14564+        static std::string convert(T const(&arr)[SZ]) {
14565+            return rangeToString(arr);
14566+        }
14567+    };
14568+
14569+
14570+} // namespace Catch
14571+
14572+// Separate std::chrono::duration specialization
14573+#include <ctime>
14574+#include <ratio>
14575+#include <chrono>
14576+
14577+
14578+namespace Catch {
14579+
14580+template <class Ratio>
14581+struct ratio_string {
14582+    static std::string symbol() {
14583+        Catch::ReusableStringStream rss;
14584+        rss << '[' << Ratio::num << '/'
14585+            << Ratio::den << ']';
14586+        return rss.str();
14587+    }
14588+};
14589+
14590+template <>
14591+struct ratio_string<std::atto> {
14592+    static char symbol() { return 'a'; }
14593+};
14594+template <>
14595+struct ratio_string<std::femto> {
14596+    static char symbol() { return 'f'; }
14597+};
14598+template <>
14599+struct ratio_string<std::pico> {
14600+    static char symbol() { return 'p'; }
14601+};
14602+template <>
14603+struct ratio_string<std::nano> {
14604+    static char symbol() { return 'n'; }
14605+};
14606+template <>
14607+struct ratio_string<std::micro> {
14608+    static char symbol() { return 'u'; }
14609+};
14610+template <>
14611+struct ratio_string<std::milli> {
14612+    static char symbol() { return 'm'; }
14613+};
14614+
14615+    ////////////
14616+    // std::chrono::duration specializations
14617+    template<typename Value, typename Ratio>
14618+    struct StringMaker<std::chrono::duration<Value, Ratio>> {
14619+        static std::string convert(std::chrono::duration<Value, Ratio> const& duration) {
14620+            ReusableStringStream rss;
14621+            rss << duration.count() << ' ' << ratio_string<Ratio>::symbol() << 's';
14622+            return rss.str();
14623+        }
14624+    };
14625+    template<typename Value>
14626+    struct StringMaker<std::chrono::duration<Value, std::ratio<1>>> {
14627+        static std::string convert(std::chrono::duration<Value, std::ratio<1>> const& duration) {
14628+            ReusableStringStream rss;
14629+            rss << duration.count() << " s";
14630+            return rss.str();
14631+        }
14632+    };
14633+    template<typename Value>
14634+    struct StringMaker<std::chrono::duration<Value, std::ratio<60>>> {
14635+        static std::string convert(std::chrono::duration<Value, std::ratio<60>> const& duration) {
14636+            ReusableStringStream rss;
14637+            rss << duration.count() << " m";
14638+            return rss.str();
14639+        }
14640+    };
14641+    template<typename Value>
14642+    struct StringMaker<std::chrono::duration<Value, std::ratio<3600>>> {
14643+        static std::string convert(std::chrono::duration<Value, std::ratio<3600>> const& duration) {
14644+            ReusableStringStream rss;
14645+            rss << duration.count() << " h";
14646+            return rss.str();
14647+        }
14648+    };
14649+
14650+    ////////////
14651+    // std::chrono::time_point specialization
14652+    // Generic time_point cannot be specialized, only std::chrono::time_point<system_clock>
14653+    template<typename Clock, typename Duration>
14654+    struct StringMaker<std::chrono::time_point<Clock, Duration>> {
14655+        static std::string convert(std::chrono::time_point<Clock, Duration> const& time_point) {
14656+            return ::Catch::Detail::stringify(time_point.time_since_epoch()) + " since epoch";
14657+        }
14658+    };
14659+    // std::chrono::time_point<system_clock> specialization
14660+    template<typename Duration>
14661+    struct StringMaker<std::chrono::time_point<std::chrono::system_clock, Duration>> {
14662+        static std::string convert(std::chrono::time_point<std::chrono::system_clock, Duration> const& time_point) {
14663+            auto converted = std::chrono::system_clock::to_time_t(time_point);
14664+
14665+#ifdef _MSC_VER
14666+            std::tm timeInfo = {};
14667+            gmtime_s(&timeInfo, &converted);
14668+#else
14669+            std::tm* timeInfo = std::gmtime(&converted);
14670+#endif
14671+
14672+            auto const timeStampSize = sizeof("2017-01-16T17:06:45Z");
14673+            char timeStamp[timeStampSize];
14674+            const char * const fmt = "%Y-%m-%dT%H:%M:%SZ";
14675+
14676+#ifdef _MSC_VER
14677+            std::strftime(timeStamp, timeStampSize, fmt, &timeInfo);
14678+#else
14679+            std::strftime(timeStamp, timeStampSize, fmt, timeInfo);
14680+#endif
14681+            return std::string(timeStamp, timeStampSize - 1);
14682+        }
14683+    };
14684+}
14685+
14686+
14687+#define INTERNAL_CATCH_REGISTER_ENUM( enumName, ... ) \
14688+namespace Catch { \
14689+    template<> struct StringMaker<enumName> { \
14690+        static std::string convert( enumName value ) { \
14691+            static const auto& enumInfo = ::Catch::getMutableRegistryHub().getMutableEnumValuesRegistry().registerEnum( #enumName, #__VA_ARGS__, { __VA_ARGS__ } ); \
14692+            return static_cast<std::string>(enumInfo.lookup( static_cast<int>( value ) )); \
14693+        } \
14694+    }; \
14695+}
14696+
14697+#define CATCH_REGISTER_ENUM( enumName, ... ) INTERNAL_CATCH_REGISTER_ENUM( enumName, __VA_ARGS__ )
14698+
14699+#ifdef _MSC_VER
14700+#pragma warning(pop)
14701+#endif
14702+
14703+#endif // CATCH_TOSTRING_HPP_INCLUDED
14704+
14705+#include <type_traits>
14706+
14707+namespace Catch {
14708+
14709+    class Approx {
14710+    private:
14711+        bool equalityComparisonImpl(double other) const;
14712+        // Sets and validates the new margin (margin >= 0)
14713+        void setMargin(double margin);
14714+        // Sets and validates the new epsilon (0 < epsilon < 1)
14715+        void setEpsilon(double epsilon);
14716+
14717+    public:
14718+        explicit Approx ( double value );
14719+
14720+        static Approx custom();
14721+
14722+        Approx operator-() const;
14723+
14724+        template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
14725+        Approx operator()( T const& value ) const {
14726+            Approx approx( static_cast<double>(value) );
14727+            approx.m_epsilon = m_epsilon;
14728+            approx.m_margin = m_margin;
14729+            approx.m_scale = m_scale;
14730+            return approx;
14731+        }
14732+
14733+        template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
14734+        explicit Approx( T const& value ): Approx(static_cast<double>(value))
14735+        {}
14736+
14737+
14738+        template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
14739+        friend bool operator == ( const T& lhs, Approx const& rhs ) {
14740+            auto lhs_v = static_cast<double>(lhs);
14741+            return rhs.equalityComparisonImpl(lhs_v);
14742+        }
14743+
14744+        template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
14745+        friend bool operator == ( Approx const& lhs, const T& rhs ) {
14746+            return operator==( rhs, lhs );
14747+        }
14748+
14749+        template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
14750+        friend bool operator != ( T const& lhs, Approx const& rhs ) {
14751+            return !operator==( lhs, rhs );
14752+        }
14753+
14754+        template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
14755+        friend bool operator != ( Approx const& lhs, T const& rhs ) {
14756+            return !operator==( rhs, lhs );
14757+        }
14758+
14759+        template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
14760+        friend bool operator <= ( T const& lhs, Approx const& rhs ) {
14761+            return static_cast<double>(lhs) < rhs.m_value || lhs == rhs;
14762+        }
14763+
14764+        template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
14765+        friend bool operator <= ( Approx const& lhs, T const& rhs ) {
14766+            return lhs.m_value < static_cast<double>(rhs) || lhs == rhs;
14767+        }
14768+
14769+        template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
14770+        friend bool operator >= ( T const& lhs, Approx const& rhs ) {
14771+            return static_cast<double>(lhs) > rhs.m_value || lhs == rhs;
14772+        }
14773+
14774+        template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
14775+        friend bool operator >= ( Approx const& lhs, T const& rhs ) {
14776+            return lhs.m_value > static_cast<double>(rhs) || lhs == rhs;
14777+        }
14778+
14779+        template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
14780+        Approx& epsilon( T const& newEpsilon ) {
14781+            const auto epsilonAsDouble = static_cast<double>(newEpsilon);
14782+            setEpsilon(epsilonAsDouble);
14783+            return *this;
14784+        }
14785+
14786+        template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
14787+        Approx& margin( T const& newMargin ) {
14788+            const auto marginAsDouble = static_cast<double>(newMargin);
14789+            setMargin(marginAsDouble);
14790+            return *this;
14791+        }
14792+
14793+        template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
14794+        Approx& scale( T const& newScale ) {
14795+            m_scale = static_cast<double>(newScale);
14796+            return *this;
14797+        }
14798+
14799+        std::string toString() const;
14800+
14801+    private:
14802+        double m_epsilon;
14803+        double m_margin;
14804+        double m_scale;
14805+        double m_value;
14806+    };
14807+
14808+namespace literals {
14809+    Approx operator ""_a(long double val);
14810+    Approx operator ""_a(unsigned long long val);
14811+} // end namespace literals
14812+
14813+template<>
14814+struct StringMaker<Catch::Approx> {
14815+    static std::string convert(Catch::Approx const& value);
14816+};
14817+
14818+} // end namespace Catch
14819+
14820+#endif // CATCH_APPROX_HPP_INCLUDED
14821+
14822+
14823+#ifndef CATCH_ASSERTION_INFO_HPP_INCLUDED
14824+#define CATCH_ASSERTION_INFO_HPP_INCLUDED
14825+
14826+
14827+
14828+#ifndef CATCH_SOURCE_LINE_INFO_HPP_INCLUDED
14829+#define CATCH_SOURCE_LINE_INFO_HPP_INCLUDED
14830+
14831+#include <cstddef>
14832+#include <iosfwd>
14833+
14834+namespace Catch {
14835+
14836+    struct SourceLineInfo {
14837+
14838+        SourceLineInfo() = delete;
14839+        constexpr SourceLineInfo( char const* _file, std::size_t _line ) noexcept:
14840+            file( _file ),
14841+            line( _line )
14842+        {}
14843+
14844+        bool operator == ( SourceLineInfo const& other ) const noexcept;
14845+        bool operator < ( SourceLineInfo const& other ) const noexcept;
14846+
14847+        char const* file;
14848+        std::size_t line;
14849+
14850+        friend std::ostream& operator << (std::ostream& os, SourceLineInfo const& info);
14851+    };
14852+}
14853+
14854+#define CATCH_INTERNAL_LINEINFO \
14855+    ::Catch::SourceLineInfo( __FILE__, static_cast<std::size_t>( __LINE__ ) )
14856+
14857+#endif // CATCH_SOURCE_LINE_INFO_HPP_INCLUDED
14858+
14859+namespace Catch {
14860+
14861+    struct AssertionInfo {
14862+        // AssertionInfo() = delete;
14863+
14864+        StringRef macroName;
14865+        SourceLineInfo lineInfo;
14866+        StringRef capturedExpression;
14867+        ResultDisposition::Flags resultDisposition;
14868+    };
14869+
14870+} // end namespace Catch
14871+
14872+#endif // CATCH_ASSERTION_INFO_HPP_INCLUDED
14873+
14874+
14875+#ifndef CATCH_ASSERTION_RESULT_HPP_INCLUDED
14876+#define CATCH_ASSERTION_RESULT_HPP_INCLUDED
14877+
14878+
14879+
14880+#ifndef CATCH_LAZY_EXPR_HPP_INCLUDED
14881+#define CATCH_LAZY_EXPR_HPP_INCLUDED
14882+
14883+#include <iosfwd>
14884+
14885+namespace Catch {
14886+
14887+    class ITransientExpression;
14888+
14889+    class LazyExpression {
14890+        friend class AssertionHandler;
14891+        friend struct AssertionStats;
14892+        friend class RunContext;
14893+
14894+        ITransientExpression const* m_transientExpression = nullptr;
14895+        bool m_isNegated;
14896+    public:
14897+        LazyExpression( bool isNegated ):
14898+            m_isNegated(isNegated)
14899+        {}
14900+        LazyExpression(LazyExpression const& other) = default;
14901+        LazyExpression& operator = ( LazyExpression const& ) = delete;
14902+
14903+        explicit operator bool() const {
14904+            return m_transientExpression != nullptr;
14905+        }
14906+
14907+        friend auto operator << ( std::ostream& os, LazyExpression const& lazyExpr ) -> std::ostream&;
14908+    };
14909+
14910+} // namespace Catch
14911+
14912+#endif // CATCH_LAZY_EXPR_HPP_INCLUDED
14913+
14914+#include <string>
14915+
14916+namespace Catch {
14917+
14918+    struct AssertionResultData
14919+    {
14920+        AssertionResultData() = delete;
14921+
14922+        AssertionResultData( ResultWas::OfType _resultType, LazyExpression const& _lazyExpression );
14923+
14924+        std::string message;
14925+        mutable std::string reconstructedExpression;
14926+        LazyExpression lazyExpression;
14927+        ResultWas::OfType resultType;
14928+
14929+        std::string reconstructExpression() const;
14930+    };
14931+
14932+    class AssertionResult {
14933+    public:
14934+        AssertionResult() = delete;
14935+        AssertionResult( AssertionInfo const& info, AssertionResultData&& data );
14936+
14937+        bool isOk() const;
14938+        bool succeeded() const;
14939+        ResultWas::OfType getResultType() const;
14940+        bool hasExpression() const;
14941+        bool hasMessage() const;
14942+        std::string getExpression() const;
14943+        std::string getExpressionInMacro() const;
14944+        bool hasExpandedExpression() const;
14945+        std::string getExpandedExpression() const;
14946+        StringRef getMessage() const;
14947+        SourceLineInfo getSourceInfo() const;
14948+        StringRef getTestMacroName() const;
14949+
14950+    //protected:
14951+        AssertionInfo m_info;
14952+        AssertionResultData m_resultData;
14953+    };
14954+
14955+} // end namespace Catch
14956+
14957+#endif // CATCH_ASSERTION_RESULT_HPP_INCLUDED
14958+
14959+
14960+#ifndef CATCH_CONFIG_HPP_INCLUDED
14961+#define CATCH_CONFIG_HPP_INCLUDED
14962+
14963+
14964+
14965+#ifndef CATCH_TEST_SPEC_HPP_INCLUDED
14966+#define CATCH_TEST_SPEC_HPP_INCLUDED
14967+
14968+#ifdef __clang__
14969+#pragma clang diagnostic push
14970+#pragma clang diagnostic ignored "-Wpadded"
14971+#endif
14972+
14973+
14974+
14975+#ifndef CATCH_WILDCARD_PATTERN_HPP_INCLUDED
14976+#define CATCH_WILDCARD_PATTERN_HPP_INCLUDED
14977+
14978+
14979+
14980+#ifndef CATCH_CASE_SENSITIVE_HPP_INCLUDED
14981+#define CATCH_CASE_SENSITIVE_HPP_INCLUDED
14982+
14983+namespace Catch {
14984+
14985+    enum class CaseSensitive { Yes, No };
14986+
14987+} // namespace Catch
14988+
14989+#endif // CATCH_CASE_SENSITIVE_HPP_INCLUDED
14990+
14991+#include <string>
14992+
14993+namespace Catch
14994+{
14995+    class WildcardPattern {
14996+        enum WildcardPosition {
14997+            NoWildcard = 0,
14998+            WildcardAtStart = 1,
14999+            WildcardAtEnd = 2,
15000+            WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd
15001+        };
15002+
15003+    public:
15004+
15005+        WildcardPattern( std::string const& pattern, CaseSensitive caseSensitivity );
15006+        bool matches( std::string const& str ) const;
15007+
15008+    private:
15009+        std::string normaliseString( std::string const& str ) const;
15010+        CaseSensitive m_caseSensitivity;
15011+        WildcardPosition m_wildcard = NoWildcard;
15012+        std::string m_pattern;
15013+    };
15014+}
15015+
15016+#endif // CATCH_WILDCARD_PATTERN_HPP_INCLUDED
15017+
15018+#include <iosfwd>
15019+#include <string>
15020+#include <vector>
15021+
15022+namespace Catch {
15023+
15024+    class IConfig;
15025+    struct TestCaseInfo;
15026+    class TestCaseHandle;
15027+
15028+    class TestSpec {
15029+
15030+        class Pattern {
15031+        public:
15032+            explicit Pattern( std::string const& name );
15033+            virtual ~Pattern();
15034+            virtual bool matches( TestCaseInfo const& testCase ) const = 0;
15035+            std::string const& name() const;
15036+        private:
15037+            virtual void serializeTo( std::ostream& out ) const = 0;
15038+            // Writes string that would be reparsed into the pattern
15039+            friend std::ostream& operator<<(std::ostream& out,
15040+                                            Pattern const& pattern) {
15041+                pattern.serializeTo( out );
15042+                return out;
15043+            }
15044+
15045+            std::string const m_name;
15046+        };
15047+
15048+        class NamePattern : public Pattern {
15049+        public:
15050+            explicit NamePattern( std::string const& name, std::string const& filterString );
15051+            bool matches( TestCaseInfo const& testCase ) const override;
15052+        private:
15053+            void serializeTo( std::ostream& out ) const override;
15054+
15055+            WildcardPattern m_wildcardPattern;
15056+        };
15057+
15058+        class TagPattern : public Pattern {
15059+        public:
15060+            explicit TagPattern( std::string const& tag, std::string const& filterString );
15061+            bool matches( TestCaseInfo const& testCase ) const override;
15062+        private:
15063+            void serializeTo( std::ostream& out ) const override;
15064+
15065+            std::string m_tag;
15066+        };
15067+
15068+        struct Filter {
15069+            std::vector<Detail::unique_ptr<Pattern>> m_required;
15070+            std::vector<Detail::unique_ptr<Pattern>> m_forbidden;
15071+
15072+            //! Serializes this filter into a string that would be parsed into
15073+            //! an equivalent filter
15074+            void serializeTo( std::ostream& out ) const;
15075+            friend std::ostream& operator<<(std::ostream& out, Filter const& f) {
15076+                f.serializeTo( out );
15077+                return out;
15078+            }
15079+
15080+            bool matches( TestCaseInfo const& testCase ) const;
15081+        };
15082+
15083+        static std::string extractFilterName( Filter const& filter );
15084+
15085+    public:
15086+        struct FilterMatch {
15087+            std::string name;
15088+            std::vector<TestCaseHandle const*> tests;
15089+        };
15090+        using Matches = std::vector<FilterMatch>;
15091+        using vectorStrings = std::vector<std::string>;
15092+
15093+        bool hasFilters() const;
15094+        bool matches( TestCaseInfo const& testCase ) const;
15095+        Matches matchesByFilter( std::vector<TestCaseHandle> const& testCases, IConfig const& config ) const;
15096+        const vectorStrings & getInvalidSpecs() const;
15097+
15098+    private:
15099+        std::vector<Filter> m_filters;
15100+        std::vector<std::string> m_invalidSpecs;
15101+
15102+        friend class TestSpecParser;
15103+        //! Serializes this test spec into a string that would be parsed into
15104+        //! equivalent test spec
15105+        void serializeTo( std::ostream& out ) const;
15106+        friend std::ostream& operator<<(std::ostream& out,
15107+                                        TestSpec const& spec) {
15108+            spec.serializeTo( out );
15109+            return out;
15110+        }
15111+    };
15112+}
15113+
15114+#ifdef __clang__
15115+#pragma clang diagnostic pop
15116+#endif
15117+
15118+#endif // CATCH_TEST_SPEC_HPP_INCLUDED
15119+
15120+
15121+#ifndef CATCH_OPTIONAL_HPP_INCLUDED
15122+#define CATCH_OPTIONAL_HPP_INCLUDED
15123+
15124+
15125+#include <cassert>
15126+
15127+namespace Catch {
15128+
15129+    // An optional type
15130+    template<typename T>
15131+    class Optional {
15132+    public:
15133+        Optional(): nullableValue( nullptr ) {}
15134+        ~Optional() { reset(); }
15135+
15136+        Optional( T const& _value ):
15137+            nullableValue( new ( storage ) T( _value ) ) {}
15138+        Optional( T&& _value ):
15139+            nullableValue( new ( storage ) T( CATCH_MOVE( _value ) ) ) {}
15140+
15141+        Optional& operator=( T const& _value ) {
15142+            reset();
15143+            nullableValue = new ( storage ) T( _value );
15144+            return *this;
15145+        }
15146+        Optional& operator=( T&& _value ) {
15147+            reset();
15148+            nullableValue = new ( storage ) T( CATCH_MOVE( _value ) );
15149+            return *this;
15150+        }
15151+
15152+        Optional( Optional const& _other ):
15153+            nullableValue( _other ? new ( storage ) T( *_other ) : nullptr ) {}
15154+        Optional( Optional&& _other ):
15155+            nullableValue( _other ? new ( storage ) T( CATCH_MOVE( *_other ) )
15156+                                  : nullptr ) {}
15157+
15158+        Optional& operator=( Optional const& _other ) {
15159+            if ( &_other != this ) {
15160+                reset();
15161+                if ( _other ) { nullableValue = new ( storage ) T( *_other ); }
15162+            }
15163+            return *this;
15164+        }
15165+        Optional& operator=( Optional&& _other ) {
15166+            if ( &_other != this ) {
15167+                reset();
15168+                if ( _other ) {
15169+                    nullableValue = new ( storage ) T( CATCH_MOVE( *_other ) );
15170+                }
15171+            }
15172+            return *this;
15173+        }
15174+
15175+        void reset() {
15176+            if ( nullableValue ) { nullableValue->~T(); }
15177+            nullableValue = nullptr;
15178+        }
15179+
15180+        T& operator*() {
15181+            assert(nullableValue);
15182+            return *nullableValue;
15183+        }
15184+        T const& operator*() const {
15185+            assert(nullableValue);
15186+            return *nullableValue;
15187+        }
15188+        T* operator->() {
15189+            assert(nullableValue);
15190+            return nullableValue;
15191+        }
15192+        const T* operator->() const {
15193+            assert(nullableValue);
15194+            return nullableValue;
15195+        }
15196+
15197+        T valueOr( T const& defaultValue ) const {
15198+            return nullableValue ? *nullableValue : defaultValue;
15199+        }
15200+
15201+        bool some() const { return nullableValue != nullptr; }
15202+        bool none() const { return nullableValue == nullptr; }
15203+
15204+        bool operator !() const { return nullableValue == nullptr; }
15205+        explicit operator bool() const {
15206+            return some();
15207+        }
15208+
15209+        friend bool operator==(Optional const& a, Optional const& b) {
15210+            if (a.none() && b.none()) {
15211+                return true;
15212+            } else if (a.some() && b.some()) {
15213+                return *a == *b;
15214+            } else {
15215+                return false;
15216+            }
15217+        }
15218+        friend bool operator!=(Optional const& a, Optional const& b) {
15219+            return !( a == b );
15220+        }
15221+
15222+    private:
15223+        T* nullableValue;
15224+        alignas(alignof(T)) char storage[sizeof(T)];
15225+    };
15226+
15227+} // end namespace Catch
15228+
15229+#endif // CATCH_OPTIONAL_HPP_INCLUDED
15230+
15231+
15232+#ifndef CATCH_RANDOM_SEED_GENERATION_HPP_INCLUDED
15233+#define CATCH_RANDOM_SEED_GENERATION_HPP_INCLUDED
15234+
15235+#include <cstdint>
15236+
15237+namespace Catch {
15238+
15239+    enum class GenerateFrom {
15240+        Time,
15241+        RandomDevice,
15242+        //! Currently equivalent to RandomDevice, but can change at any point
15243+        Default
15244+    };
15245+
15246+    std::uint32_t generateRandomSeed(GenerateFrom from);
15247+
15248+} // end namespace Catch
15249+
15250+#endif // CATCH_RANDOM_SEED_GENERATION_HPP_INCLUDED
15251+
15252+
15253+#ifndef CATCH_REPORTER_SPEC_PARSER_HPP_INCLUDED
15254+#define CATCH_REPORTER_SPEC_PARSER_HPP_INCLUDED
15255+
15256+
15257+#include <map>
15258+#include <string>
15259+#include <vector>
15260+
15261+namespace Catch {
15262+
15263+    enum class ColourMode : std::uint8_t;
15264+
15265+    namespace Detail {
15266+        //! Splits the reporter spec into reporter name and kv-pair options
15267+        std::vector<std::string> splitReporterSpec( StringRef reporterSpec );
15268+
15269+        Optional<ColourMode> stringToColourMode( StringRef colourMode );
15270+    }
15271+
15272+    /**
15273+     * Structured reporter spec that a reporter can be created from
15274+     *
15275+     * Parsing has been validated, but semantics have not. This means e.g.
15276+     * that the colour mode is known to Catch2, but it might not be
15277+     * compiled into the binary, and the output filename might not be
15278+     * openable.
15279+     */
15280+    class ReporterSpec {
15281+        std::string m_name;
15282+        Optional<std::string> m_outputFileName;
15283+        Optional<ColourMode> m_colourMode;
15284+        std::map<std::string, std::string> m_customOptions;
15285+
15286+        friend bool operator==( ReporterSpec const& lhs,
15287+                                ReporterSpec const& rhs );
15288+        friend bool operator!=( ReporterSpec const& lhs,
15289+                                ReporterSpec const& rhs ) {
15290+            return !( lhs == rhs );
15291+        }
15292+
15293+    public:
15294+        ReporterSpec(
15295+            std::string name,
15296+            Optional<std::string> outputFileName,
15297+            Optional<ColourMode> colourMode,
15298+            std::map<std::string, std::string> customOptions );
15299+
15300+        std::string const& name() const { return m_name; }
15301+
15302+        Optional<std::string> const& outputFile() const {
15303+            return m_outputFileName;
15304+        }
15305+
15306+        Optional<ColourMode> const& colourMode() const { return m_colourMode; }
15307+
15308+        std::map<std::string, std::string> const& customOptions() const {
15309+            return m_customOptions;
15310+        }
15311+    };
15312+
15313+    /**
15314+     * Parses provided reporter spec string into
15315+     *
15316+     * Returns empty optional on errors, e.g.
15317+     *  * field that is not first and not a key+value pair
15318+     *  * duplicated keys in kv pair
15319+     *  * unknown catch reporter option
15320+     *  * empty key/value in an custom kv pair
15321+     *  * ...
15322+     */
15323+    Optional<ReporterSpec> parseReporterSpec( StringRef reporterSpec );
15324+
15325+}
15326+
15327+#endif // CATCH_REPORTER_SPEC_PARSER_HPP_INCLUDED
15328+
15329+#include <chrono>
15330+#include <map>
15331+#include <string>
15332+#include <vector>
15333+
15334+namespace Catch {
15335+
15336+    class IStream;
15337+
15338+    /**
15339+     * `ReporterSpec` but with the defaults filled in.
15340+     *
15341+     * Like `ReporterSpec`, the semantics are unchecked.
15342+     */
15343+    struct ProcessedReporterSpec {
15344+        std::string name;
15345+        std::string outputFilename;
15346+        ColourMode colourMode;
15347+        std::map<std::string, std::string> customOptions;
15348+        friend bool operator==( ProcessedReporterSpec const& lhs,
15349+                                ProcessedReporterSpec const& rhs );
15350+        friend bool operator!=( ProcessedReporterSpec const& lhs,
15351+                                ProcessedReporterSpec const& rhs ) {
15352+            return !( lhs == rhs );
15353+        }
15354+    };
15355+
15356+    struct ConfigData {
15357+
15358+        bool listTests = false;
15359+        bool listTags = false;
15360+        bool listReporters = false;
15361+        bool listListeners = false;
15362+
15363+        bool showSuccessfulTests = false;
15364+        bool shouldDebugBreak = false;
15365+        bool noThrow = false;
15366+        bool showHelp = false;
15367+        bool showInvisibles = false;
15368+        bool filenamesAsTags = false;
15369+        bool libIdentify = false;
15370+        bool allowZeroTests = false;
15371+
15372+        int abortAfter = -1;
15373+        uint32_t rngSeed = generateRandomSeed(GenerateFrom::Default);
15374+
15375+        unsigned int shardCount = 1;
15376+        unsigned int shardIndex = 0;
15377+
15378+        bool skipBenchmarks = false;
15379+        bool benchmarkNoAnalysis = false;
15380+        unsigned int benchmarkSamples = 100;
15381+        double benchmarkConfidenceInterval = 0.95;
15382+        unsigned int benchmarkResamples = 100'000;
15383+        std::chrono::milliseconds::rep benchmarkWarmupTime = 100;
15384+
15385+        Verbosity verbosity = Verbosity::Normal;
15386+        WarnAbout::What warnings = WarnAbout::Nothing;
15387+        ShowDurations showDurations = ShowDurations::DefaultForReporter;
15388+        double minDuration = -1;
15389+        TestRunOrder runOrder = TestRunOrder::Declared;
15390+        ColourMode defaultColourMode = ColourMode::PlatformDefault;
15391+        WaitForKeypress::When waitForKeypress = WaitForKeypress::Never;
15392+
15393+        std::string defaultOutputFilename;
15394+        std::string name;
15395+        std::string processName;
15396+        std::vector<ReporterSpec> reporterSpecifications;
15397+
15398+        std::vector<std::string> testsOrTags;
15399+        std::vector<std::string> sectionsToRun;
15400+    };
15401+
15402+
15403+    class Config : public IConfig {
15404+    public:
15405+
15406+        Config() = default;
15407+        Config( ConfigData const& data );
15408+        ~Config() override; // = default in the cpp file
15409+
15410+        bool listTests() const;
15411+        bool listTags() const;
15412+        bool listReporters() const;
15413+        bool listListeners() const;
15414+
15415+        std::vector<ReporterSpec> const& getReporterSpecs() const;
15416+        std::vector<ProcessedReporterSpec> const&
15417+        getProcessedReporterSpecs() const;
15418+
15419+        std::vector<std::string> const& getTestsOrTags() const override;
15420+        std::vector<std::string> const& getSectionsToRun() const override;
15421+
15422+        TestSpec const& testSpec() const override;
15423+        bool hasTestFilters() const override;
15424+
15425+        bool showHelp() const;
15426+
15427+        // IConfig interface
15428+        bool allowThrows() const override;
15429+        StringRef name() const override;
15430+        bool includeSuccessfulResults() const override;
15431+        bool warnAboutMissingAssertions() const override;
15432+        bool warnAboutUnmatchedTestSpecs() const override;
15433+        bool zeroTestsCountAsSuccess() const override;
15434+        ShowDurations showDurations() const override;
15435+        double minDuration() const override;
15436+        TestRunOrder runOrder() const override;
15437+        uint32_t rngSeed() const override;
15438+        unsigned int shardCount() const override;
15439+        unsigned int shardIndex() const override;
15440+        ColourMode defaultColourMode() const override;
15441+        bool shouldDebugBreak() const override;
15442+        int abortAfter() const override;
15443+        bool showInvisibles() const override;
15444+        Verbosity verbosity() const override;
15445+        bool skipBenchmarks() const override;
15446+        bool benchmarkNoAnalysis() const override;
15447+        unsigned int benchmarkSamples() const override;
15448+        double benchmarkConfidenceInterval() const override;
15449+        unsigned int benchmarkResamples() const override;
15450+        std::chrono::milliseconds benchmarkWarmupTime() const override;
15451+
15452+    private:
15453+        // Reads Bazel env vars and applies them to the config
15454+        void readBazelEnvVars();
15455+
15456+        ConfigData m_data;
15457+        std::vector<ProcessedReporterSpec> m_processedReporterSpecs;
15458+        TestSpec m_testSpec;
15459+        bool m_hasTestFilters = false;
15460+    };
15461+} // end namespace Catch
15462+
15463+#endif // CATCH_CONFIG_HPP_INCLUDED
15464+
15465+
15466+#ifndef CATCH_GET_RANDOM_SEED_HPP_INCLUDED
15467+#define CATCH_GET_RANDOM_SEED_HPP_INCLUDED
15468+
15469+#include <cstdint>
15470+
15471+namespace Catch {
15472+    //! Returns Catch2's current RNG seed.
15473+    std::uint32_t getSeed();
15474+}
15475+
15476+#endif // CATCH_GET_RANDOM_SEED_HPP_INCLUDED
15477+
15478+
15479+#ifndef CATCH_MESSAGE_HPP_INCLUDED
15480+#define CATCH_MESSAGE_HPP_INCLUDED
15481+
15482+
15483+
15484+
15485+/** \file
15486+ * Wrapper for the CATCH_CONFIG_PREFIX_MESSAGES configuration option
15487+ *
15488+ * CATCH_CONFIG_PREFIX_ALL can be used to avoid clashes with other macros
15489+ * by prepending CATCH_. This may not be desirable if the only clashes are with
15490+ * logger macros such as INFO and WARN. In this cases
15491+ * CATCH_CONFIG_PREFIX_MESSAGES can be used to only prefix a small subset
15492+ * of relevant macros.
15493+ *
15494+ */
15495+
15496+#ifndef CATCH_CONFIG_PREFIX_MESSAGES_HPP_INCLUDED
15497+#define CATCH_CONFIG_PREFIX_MESSAGES_HPP_INCLUDED
15498+
15499+
15500+#if defined(CATCH_CONFIG_PREFIX_ALL) && !defined(CATCH_CONFIG_PREFIX_MESSAGES)
15501+    #define CATCH_CONFIG_PREFIX_MESSAGES
15502+#endif
15503+
15504+#endif // CATCH_CONFIG_PREFIX_MESSAGES_HPP_INCLUDED
15505+
15506+
15507+#ifndef CATCH_STREAM_END_STOP_HPP_INCLUDED
15508+#define CATCH_STREAM_END_STOP_HPP_INCLUDED
15509+
15510+
15511+namespace Catch {
15512+
15513+    // Use this in variadic streaming macros to allow
15514+    //    << +StreamEndStop
15515+    // as well as
15516+    //    << stuff +StreamEndStop
15517+    struct StreamEndStop {
15518+        constexpr StringRef operator+() const { return StringRef(); }
15519+
15520+        template <typename T>
15521+        constexpr friend T const& operator+( T const& value, StreamEndStop ) {
15522+            return value;
15523+        }
15524+    };
15525+
15526+} // namespace Catch
15527+
15528+#endif // CATCH_STREAM_END_STOP_HPP_INCLUDED
15529+
15530+
15531+#ifndef CATCH_MESSAGE_INFO_HPP_INCLUDED
15532+#define CATCH_MESSAGE_INFO_HPP_INCLUDED
15533+
15534+
15535+#include <string>
15536+
15537+namespace Catch {
15538+
15539+    struct MessageInfo {
15540+        MessageInfo(    StringRef _macroName,
15541+                        SourceLineInfo const& _lineInfo,
15542+                        ResultWas::OfType _type );
15543+
15544+        StringRef macroName;
15545+        std::string message;
15546+        SourceLineInfo lineInfo;
15547+        ResultWas::OfType type;
15548+        unsigned int sequence;
15549+
15550+        bool operator == (MessageInfo const& other) const {
15551+            return sequence == other.sequence;
15552+        }
15553+        bool operator < (MessageInfo const& other) const {
15554+            return sequence < other.sequence;
15555+        }
15556+    private:
15557+        static unsigned int globalCount;
15558+    };
15559+
15560+} // end namespace Catch
15561+
15562+#endif // CATCH_MESSAGE_INFO_HPP_INCLUDED
15563+
15564+#include <string>
15565+#include <vector>
15566+
15567+namespace Catch {
15568+
15569+    struct SourceLineInfo;
15570+    class IResultCapture;
15571+
15572+    struct MessageStream {
15573+
15574+        template<typename T>
15575+        MessageStream& operator << ( T const& value ) {
15576+            m_stream << value;
15577+            return *this;
15578+        }
15579+
15580+        ReusableStringStream m_stream;
15581+    };
15582+
15583+    struct MessageBuilder : MessageStream {
15584+        MessageBuilder( StringRef macroName,
15585+                        SourceLineInfo const& lineInfo,
15586+                        ResultWas::OfType type ):
15587+            m_info(macroName, lineInfo, type) {}
15588+
15589+        template<typename T>
15590+        MessageBuilder&& operator << ( T const& value ) && {
15591+            m_stream << value;
15592+            return CATCH_MOVE(*this);
15593+        }
15594+
15595+        MessageInfo m_info;
15596+    };
15597+
15598+    class ScopedMessage {
15599+    public:
15600+        explicit ScopedMessage( MessageBuilder&& builder );
15601+        ScopedMessage( ScopedMessage& duplicate ) = delete;
15602+        ScopedMessage( ScopedMessage&& old ) noexcept;
15603+        ~ScopedMessage();
15604+
15605+        MessageInfo m_info;
15606+        bool m_moved = false;
15607+    };
15608+
15609+    class Capturer {
15610+        std::vector<MessageInfo> m_messages;
15611+        IResultCapture& m_resultCapture;
15612+        size_t m_captured = 0;
15613+    public:
15614+        Capturer( StringRef macroName, SourceLineInfo const& lineInfo, ResultWas::OfType resultType, StringRef names );
15615+
15616+        Capturer(Capturer const&) = delete;
15617+        Capturer& operator=(Capturer const&) = delete;
15618+
15619+        ~Capturer();
15620+
15621+        void captureValue( size_t index, std::string const& value );
15622+
15623+        template<typename T>
15624+        void captureValues( size_t index, T const& value ) {
15625+            captureValue( index, Catch::Detail::stringify( value ) );
15626+        }
15627+
15628+        template<typename T, typename... Ts>
15629+        void captureValues( size_t index, T const& value, Ts const&... values ) {
15630+            captureValue( index, Catch::Detail::stringify(value) );
15631+            captureValues( index+1, values... );
15632+        }
15633+    };
15634+
15635+} // end namespace Catch
15636+
15637+///////////////////////////////////////////////////////////////////////////////
15638+#define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, ... ) \
15639+    do { \
15640+        Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::StringRef(), resultDisposition ); \
15641+        catchAssertionHandler.handleMessage( messageType, ( Catch::MessageStream() << __VA_ARGS__ + ::Catch::StreamEndStop() ).m_stream.str() ); \
15642+        INTERNAL_CATCH_REACT( catchAssertionHandler ) \
15643+    } while( false )
15644+
15645+///////////////////////////////////////////////////////////////////////////////
15646+#define INTERNAL_CATCH_CAPTURE( varName, macroName, ... ) \
15647+    Catch::Capturer varName( macroName##_catch_sr,        \
15648+                             CATCH_INTERNAL_LINEINFO,     \
15649+                             Catch::ResultWas::Info,      \
15650+                             #__VA_ARGS__##_catch_sr );   \
15651+    varName.captureValues( 0, __VA_ARGS__ )
15652+
15653+///////////////////////////////////////////////////////////////////////////////
15654+#define INTERNAL_CATCH_INFO( macroName, log ) \
15655+    const Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage )( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log )
15656+
15657+///////////////////////////////////////////////////////////////////////////////
15658+#define INTERNAL_CATCH_UNSCOPED_INFO( macroName, log ) \
15659+    Catch::getResultCapture().emplaceUnscopedMessage( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log )
15660+
15661+
15662+#if defined(CATCH_CONFIG_PREFIX_MESSAGES) && !defined(CATCH_CONFIG_DISABLE)
15663+
15664+  #define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", msg )
15665+  #define CATCH_UNSCOPED_INFO( msg ) INTERNAL_CATCH_UNSCOPED_INFO( "CATCH_UNSCOPED_INFO", msg )
15666+  #define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( "CATCH_WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg )
15667+  #define CATCH_CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CATCH_CAPTURE", __VA_ARGS__ )
15668+
15669+#elif defined(CATCH_CONFIG_PREFIX_MESSAGES) && defined(CATCH_CONFIG_DISABLE)
15670+
15671+  #define CATCH_INFO( msg )          (void)(0)
15672+  #define CATCH_UNSCOPED_INFO( msg ) (void)(0)
15673+  #define CATCH_WARN( msg )          (void)(0)
15674+  #define CATCH_CAPTURE( ... )       (void)(0)
15675+
15676+#elif !defined(CATCH_CONFIG_PREFIX_MESSAGES) && !defined(CATCH_CONFIG_DISABLE)
15677+
15678+  #define INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg )
15679+  #define UNSCOPED_INFO( msg ) INTERNAL_CATCH_UNSCOPED_INFO( "UNSCOPED_INFO", msg )
15680+  #define WARN( msg ) INTERNAL_CATCH_MSG( "WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg )
15681+  #define CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CAPTURE", __VA_ARGS__ )
15682+
15683+#elif !defined(CATCH_CONFIG_PREFIX_MESSAGES) && defined(CATCH_CONFIG_DISABLE)
15684+
15685+  #define INFO( msg )          (void)(0)
15686+  #define UNSCOPED_INFO( msg ) (void)(0)
15687+  #define WARN( msg )          (void)(0)
15688+  #define CAPTURE( ... )       (void)(0)
15689+
15690+#endif // end of user facing macro declarations
15691+
15692+
15693+
15694+
15695+#endif // CATCH_MESSAGE_HPP_INCLUDED
15696+
15697+
15698+#ifndef CATCH_SECTION_INFO_HPP_INCLUDED
15699+#define CATCH_SECTION_INFO_HPP_INCLUDED
15700+
15701+
15702+
15703+#ifndef CATCH_TOTALS_HPP_INCLUDED
15704+#define CATCH_TOTALS_HPP_INCLUDED
15705+
15706+#include <cstdint>
15707+
15708+namespace Catch {
15709+
15710+    struct Counts {
15711+        Counts operator - ( Counts const& other ) const;
15712+        Counts& operator += ( Counts const& other );
15713+
15714+        std::uint64_t total() const;
15715+        bool allPassed() const;
15716+        bool allOk() const;
15717+
15718+        std::uint64_t passed = 0;
15719+        std::uint64_t failed = 0;
15720+        std::uint64_t failedButOk = 0;
15721+        std::uint64_t skipped = 0;
15722+    };
15723+
15724+    struct Totals {
15725+
15726+        Totals operator - ( Totals const& other ) const;
15727+        Totals& operator += ( Totals const& other );
15728+
15729+        Totals delta( Totals const& prevTotals ) const;
15730+
15731+        Counts assertions;
15732+        Counts testCases;
15733+    };
15734+}
15735+
15736+#endif // CATCH_TOTALS_HPP_INCLUDED
15737+
15738+#include <string>
15739+
15740+namespace Catch {
15741+
15742+    struct SectionInfo {
15743+        // The last argument is ignored, so that people can write
15744+        // SECTION("ShortName", "Proper description that is long") and
15745+        // still use the `-c` flag comfortably.
15746+        SectionInfo( SourceLineInfo const& _lineInfo, std::string _name,
15747+                    const char* const = nullptr ):
15748+            name(CATCH_MOVE(_name)),
15749+            lineInfo(_lineInfo)
15750+            {}
15751+
15752+        std::string name;
15753+        SourceLineInfo lineInfo;
15754+    };
15755+
15756+    struct SectionEndInfo {
15757+        SectionInfo sectionInfo;
15758+        Counts prevAssertions;
15759+        double durationInSeconds;
15760+    };
15761+
15762+} // end namespace Catch
15763+
15764+#endif // CATCH_SECTION_INFO_HPP_INCLUDED
15765+
15766+
15767+#ifndef CATCH_SESSION_HPP_INCLUDED
15768+#define CATCH_SESSION_HPP_INCLUDED
15769+
15770+
15771+
15772+#ifndef CATCH_COMMANDLINE_HPP_INCLUDED
15773+#define CATCH_COMMANDLINE_HPP_INCLUDED
15774+
15775+
15776+
15777+#ifndef CATCH_CLARA_HPP_INCLUDED
15778+#define CATCH_CLARA_HPP_INCLUDED
15779+
15780+#if defined( __clang__ )
15781+#    pragma clang diagnostic push
15782+#    pragma clang diagnostic ignored "-Wweak-vtables"
15783+#    pragma clang diagnostic ignored "-Wshadow"
15784+#    pragma clang diagnostic ignored "-Wdeprecated"
15785+#endif
15786+
15787+#if defined( __GNUC__ )
15788+#    pragma GCC diagnostic push
15789+#    pragma GCC diagnostic ignored "-Wsign-conversion"
15790+#endif
15791+
15792+#ifndef CLARA_CONFIG_OPTIONAL_TYPE
15793+#    ifdef __has_include
15794+#        if __has_include( <optional>) && __cplusplus >= 201703L
15795+#            include <optional>
15796+#            define CLARA_CONFIG_OPTIONAL_TYPE std::optional
15797+#        endif
15798+#    endif
15799+#endif
15800+
15801+
15802+#include <cassert>
15803+#include <memory>
15804+#include <ostream>
15805+#include <sstream>
15806+#include <string>
15807+#include <type_traits>
15808+#include <vector>
15809+
15810+namespace Catch {
15811+    namespace Clara {
15812+
15813+        class Args;
15814+        class Parser;
15815+
15816+        // enum of result types from a parse
15817+        enum class ParseResultType {
15818+            Matched,
15819+            NoMatch,
15820+            ShortCircuitAll,
15821+            ShortCircuitSame
15822+        };
15823+
15824+        struct accept_many_t {};
15825+        constexpr accept_many_t accept_many {};
15826+
15827+        namespace Detail {
15828+            struct fake_arg {
15829+                template <typename T>
15830+                operator T();
15831+            };
15832+
15833+            template <typename F, typename = void>
15834+            struct is_unary_function : std::false_type {};
15835+
15836+            template <typename F>
15837+            struct is_unary_function<
15838+                F,
15839+                Catch::Detail::void_t<decltype(
15840+                    std::declval<F>()( fake_arg() ) )
15841+                >
15842+            > : std::true_type {};
15843+
15844+            // Traits for extracting arg and return type of lambdas (for single
15845+            // argument lambdas)
15846+            template <typename L>
15847+            struct UnaryLambdaTraits
15848+                : UnaryLambdaTraits<decltype( &L::operator() )> {};
15849+
15850+            template <typename ClassT, typename ReturnT, typename... Args>
15851+            struct UnaryLambdaTraits<ReturnT ( ClassT::* )( Args... ) const> {
15852+                static const bool isValid = false;
15853+            };
15854+
15855+            template <typename ClassT, typename ReturnT, typename ArgT>
15856+            struct UnaryLambdaTraits<ReturnT ( ClassT::* )( ArgT ) const> {
15857+                static const bool isValid = true;
15858+                using ArgType = std::remove_const_t<std::remove_reference_t<ArgT>>;
15859+                using ReturnType = ReturnT;
15860+            };
15861+
15862+            class TokenStream;
15863+
15864+            // Wraps a token coming from a token stream. These may not directly
15865+            // correspond to strings as a single string may encode an option +
15866+            // its argument if the : or = form is used
15867+            enum class TokenType { Option, Argument };
15868+            struct Token {
15869+                TokenType type;
15870+                StringRef token;
15871+            };
15872+
15873+            // Abstracts iterators into args as a stream of tokens, with option
15874+            // arguments uniformly handled
15875+            class TokenStream {
15876+                using Iterator = std::vector<StringRef>::const_iterator;
15877+                Iterator it;
15878+                Iterator itEnd;
15879+                std::vector<Token> m_tokenBuffer;
15880+                void loadBuffer();
15881+
15882+            public:
15883+                explicit TokenStream( Args const& args );
15884+                TokenStream( Iterator it, Iterator itEnd );
15885+
15886+                explicit operator bool() const {
15887+                    return !m_tokenBuffer.empty() || it != itEnd;
15888+                }
15889+
15890+                size_t count() const {
15891+                    return m_tokenBuffer.size() + ( itEnd - it );
15892+                }
15893+
15894+                Token operator*() const {
15895+                    assert( !m_tokenBuffer.empty() );
15896+                    return m_tokenBuffer.front();
15897+                }
15898+
15899+                Token const* operator->() const {
15900+                    assert( !m_tokenBuffer.empty() );
15901+                    return &m_tokenBuffer.front();
15902+                }
15903+
15904+                TokenStream& operator++();
15905+            };
15906+
15907+            //! Denotes type of a parsing result
15908+            enum class ResultType {
15909+                Ok,          ///< No errors
15910+                LogicError,  ///< Error in user-specified arguments for
15911+                             ///< construction
15912+                RuntimeError ///< Error in parsing inputs
15913+            };
15914+
15915+            class ResultBase {
15916+            protected:
15917+                ResultBase( ResultType type ): m_type( type ) {}
15918+                virtual ~ResultBase(); // = default;
15919+
15920+
15921+                ResultBase(ResultBase const&) = default;
15922+                ResultBase& operator=(ResultBase const&) = default;
15923+                ResultBase(ResultBase&&) = default;
15924+                ResultBase& operator=(ResultBase&&) = default;
15925+
15926+                virtual void enforceOk() const = 0;
15927+
15928+                ResultType m_type;
15929+            };
15930+
15931+            template <typename T>
15932+            class ResultValueBase : public ResultBase {
15933+            public:
15934+                T const& value() const& {
15935+                    enforceOk();
15936+                    return m_value;
15937+                }
15938+                T&& value() && {
15939+                    enforceOk();
15940+                    return CATCH_MOVE( m_value );
15941+                }
15942+
15943+            protected:
15944+                ResultValueBase( ResultType type ): ResultBase( type ) {}
15945+
15946+                ResultValueBase( ResultValueBase const& other ):
15947+                    ResultBase( other ) {
15948+                    if ( m_type == ResultType::Ok )
15949+                        new ( &m_value ) T( other.m_value );
15950+                }
15951+                ResultValueBase( ResultValueBase&& other ):
15952+                    ResultBase( other ) {
15953+                    if ( m_type == ResultType::Ok )
15954+                        new ( &m_value ) T( CATCH_MOVE(other.m_value) );
15955+                }
15956+
15957+
15958+                ResultValueBase( ResultType, T const& value ):
15959+                    ResultBase( ResultType::Ok ) {
15960+                    new ( &m_value ) T( value );
15961+                }
15962+                ResultValueBase( ResultType, T&& value ):
15963+                    ResultBase( ResultType::Ok ) {
15964+                    new ( &m_value ) T( CATCH_MOVE(value) );
15965+                }
15966+
15967+                ResultValueBase& operator=( ResultValueBase const& other ) {
15968+                    if ( m_type == ResultType::Ok )
15969+                        m_value.~T();
15970+                    ResultBase::operator=( other );
15971+                    if ( m_type == ResultType::Ok )
15972+                        new ( &m_value ) T( other.m_value );
15973+                    return *this;
15974+                }
15975+                ResultValueBase& operator=( ResultValueBase&& other ) {
15976+                    if ( m_type == ResultType::Ok ) m_value.~T();
15977+                    ResultBase::operator=( other );
15978+                    if ( m_type == ResultType::Ok )
15979+                        new ( &m_value ) T( CATCH_MOVE(other.m_value) );
15980+                    return *this;
15981+                }
15982+
15983+
15984+                ~ResultValueBase() override {
15985+                    if ( m_type == ResultType::Ok )
15986+                        m_value.~T();
15987+                }
15988+
15989+                union {
15990+                    T m_value;
15991+                };
15992+            };
15993+
15994+            template <> class ResultValueBase<void> : public ResultBase {
15995+            protected:
15996+                using ResultBase::ResultBase;
15997+            };
15998+
15999+            template <typename T = void>
16000+            class BasicResult : public ResultValueBase<T> {
16001+            public:
16002+                template <typename U>
16003+                explicit BasicResult( BasicResult<U> const& other ):
16004+                    ResultValueBase<T>( other.type() ),
16005+                    m_errorMessage( other.errorMessage() ) {
16006+                    assert( type() != ResultType::Ok );
16007+                }
16008+
16009+                template <typename U>
16010+                static auto ok( U&& value ) -> BasicResult {
16011+                    return { ResultType::Ok, CATCH_FORWARD(value) };
16012+                }
16013+                static auto ok() -> BasicResult { return { ResultType::Ok }; }
16014+                static auto logicError( std::string&& message )
16015+                    -> BasicResult {
16016+                    return { ResultType::LogicError, CATCH_MOVE(message) };
16017+                }
16018+                static auto runtimeError( std::string&& message )
16019+                    -> BasicResult {
16020+                    return { ResultType::RuntimeError, CATCH_MOVE(message) };
16021+                }
16022+
16023+                explicit operator bool() const {
16024+                    return m_type == ResultType::Ok;
16025+                }
16026+                auto type() const -> ResultType { return m_type; }
16027+                auto errorMessage() const -> std::string const& {
16028+                    return m_errorMessage;
16029+                }
16030+
16031+            protected:
16032+                void enforceOk() const override {
16033+
16034+                    // Errors shouldn't reach this point, but if they do
16035+                    // the actual error message will be in m_errorMessage
16036+                    assert( m_type != ResultType::LogicError );
16037+                    assert( m_type != ResultType::RuntimeError );
16038+                    if ( m_type != ResultType::Ok )
16039+                        std::abort();
16040+                }
16041+
16042+                std::string
16043+                    m_errorMessage; // Only populated if resultType is an error
16044+
16045+                BasicResult( ResultType type,
16046+                             std::string&& message ):
16047+                    ResultValueBase<T>( type ), m_errorMessage( CATCH_MOVE(message) ) {
16048+                    assert( m_type != ResultType::Ok );
16049+                }
16050+
16051+                using ResultValueBase<T>::ResultValueBase;
16052+                using ResultBase::m_type;
16053+            };
16054+
16055+            class ParseState {
16056+            public:
16057+                ParseState( ParseResultType type,
16058+                            TokenStream remainingTokens );
16059+
16060+                ParseResultType type() const { return m_type; }
16061+                TokenStream const& remainingTokens() const& {
16062+                    return m_remainingTokens;
16063+                }
16064+                TokenStream&& remainingTokens() && {
16065+                    return CATCH_MOVE( m_remainingTokens );
16066+                }
16067+
16068+            private:
16069+                ParseResultType m_type;
16070+                TokenStream m_remainingTokens;
16071+            };
16072+
16073+            using Result = BasicResult<void>;
16074+            using ParserResult = BasicResult<ParseResultType>;
16075+            using InternalParseResult = BasicResult<ParseState>;
16076+
16077+            struct HelpColumns {
16078+                std::string left;
16079+                StringRef descriptions;
16080+            };
16081+
16082+            template <typename T>
16083+            ParserResult convertInto( std::string const& source, T& target ) {
16084+                std::stringstream ss( source );
16085+                ss >> target;
16086+                if ( ss.fail() ) {
16087+                    return ParserResult::runtimeError(
16088+                        "Unable to convert '" + source +
16089+                        "' to destination type" );
16090+                } else {
16091+                    return ParserResult::ok( ParseResultType::Matched );
16092+                }
16093+            }
16094+            ParserResult convertInto( std::string const& source,
16095+                                      std::string& target );
16096+            ParserResult convertInto( std::string const& source, bool& target );
16097+
16098+#ifdef CLARA_CONFIG_OPTIONAL_TYPE
16099+            template <typename T>
16100+            auto convertInto( std::string const& source,
16101+                              CLARA_CONFIG_OPTIONAL_TYPE<T>& target )
16102+                -> ParserResult {
16103+                T temp;
16104+                auto result = convertInto( source, temp );
16105+                if ( result )
16106+                    target = CATCH_MOVE( temp );
16107+                return result;
16108+            }
16109+#endif // CLARA_CONFIG_OPTIONAL_TYPE
16110+
16111+            struct BoundRef : Catch::Detail::NonCopyable {
16112+                virtual ~BoundRef() = default;
16113+                virtual bool isContainer() const;
16114+                virtual bool isFlag() const;
16115+            };
16116+            struct BoundValueRefBase : BoundRef {
16117+                virtual auto setValue( std::string const& arg )
16118+                    -> ParserResult = 0;
16119+            };
16120+            struct BoundFlagRefBase : BoundRef {
16121+                virtual auto setFlag( bool flag ) -> ParserResult = 0;
16122+                bool isFlag() const override;
16123+            };
16124+
16125+            template <typename T> struct BoundValueRef : BoundValueRefBase {
16126+                T& m_ref;
16127+
16128+                explicit BoundValueRef( T& ref ): m_ref( ref ) {}
16129+
16130+                ParserResult setValue( std::string const& arg ) override {
16131+                    return convertInto( arg, m_ref );
16132+                }
16133+            };
16134+
16135+            template <typename T>
16136+            struct BoundValueRef<std::vector<T>> : BoundValueRefBase {
16137+                std::vector<T>& m_ref;
16138+
16139+                explicit BoundValueRef( std::vector<T>& ref ): m_ref( ref ) {}
16140+
16141+                auto isContainer() const -> bool override { return true; }
16142+
16143+                auto setValue( std::string const& arg )
16144+                    -> ParserResult override {
16145+                    T temp;
16146+                    auto result = convertInto( arg, temp );
16147+                    if ( result )
16148+                        m_ref.push_back( temp );
16149+                    return result;
16150+                }
16151+            };
16152+
16153+            struct BoundFlagRef : BoundFlagRefBase {
16154+                bool& m_ref;
16155+
16156+                explicit BoundFlagRef( bool& ref ): m_ref( ref ) {}
16157+
16158+                ParserResult setFlag( bool flag ) override;
16159+            };
16160+
16161+            template <typename ReturnType> struct LambdaInvoker {
16162+                static_assert(
16163+                    std::is_same<ReturnType, ParserResult>::value,
16164+                    "Lambda must return void or clara::ParserResult" );
16165+
16166+                template <typename L, typename ArgType>
16167+                static auto invoke( L const& lambda, ArgType const& arg )
16168+                    -> ParserResult {
16169+                    return lambda( arg );
16170+                }
16171+            };
16172+
16173+            template <> struct LambdaInvoker<void> {
16174+                template <typename L, typename ArgType>
16175+                static auto invoke( L const& lambda, ArgType const& arg )
16176+                    -> ParserResult {
16177+                    lambda( arg );
16178+                    return ParserResult::ok( ParseResultType::Matched );
16179+                }
16180+            };
16181+
16182+            template <typename ArgType, typename L>
16183+            auto invokeLambda( L const& lambda, std::string const& arg )
16184+                -> ParserResult {
16185+                ArgType temp{};
16186+                auto result = convertInto( arg, temp );
16187+                return !result ? result
16188+                               : LambdaInvoker<typename UnaryLambdaTraits<
16189+                                     L>::ReturnType>::invoke( lambda, temp );
16190+            }
16191+
16192+            template <typename L> struct BoundLambda : BoundValueRefBase {
16193+                L m_lambda;
16194+
16195+                static_assert(
16196+                    UnaryLambdaTraits<L>::isValid,
16197+                    "Supplied lambda must take exactly one argument" );
16198+                explicit BoundLambda( L const& lambda ): m_lambda( lambda ) {}
16199+
16200+                auto setValue( std::string const& arg )
16201+                    -> ParserResult override {
16202+                    return invokeLambda<typename UnaryLambdaTraits<L>::ArgType>(
16203+                        m_lambda, arg );
16204+                }
16205+            };
16206+
16207+            template <typename L> struct BoundManyLambda : BoundLambda<L> {
16208+                explicit BoundManyLambda( L const& lambda ): BoundLambda<L>( lambda ) {}
16209+                bool isContainer() const override { return true; }
16210+            };
16211+
16212+            template <typename L> struct BoundFlagLambda : BoundFlagRefBase {
16213+                L m_lambda;
16214+
16215+                static_assert(
16216+                    UnaryLambdaTraits<L>::isValid,
16217+                    "Supplied lambda must take exactly one argument" );
16218+                static_assert(
16219+                    std::is_same<typename UnaryLambdaTraits<L>::ArgType,
16220+                                 bool>::value,
16221+                    "flags must be boolean" );
16222+
16223+                explicit BoundFlagLambda( L const& lambda ):
16224+                    m_lambda( lambda ) {}
16225+
16226+                auto setFlag( bool flag ) -> ParserResult override {
16227+                    return LambdaInvoker<typename UnaryLambdaTraits<
16228+                        L>::ReturnType>::invoke( m_lambda, flag );
16229+                }
16230+            };
16231+
16232+            enum class Optionality { Optional, Required };
16233+
16234+            class ParserBase {
16235+            public:
16236+                virtual ~ParserBase() = default;
16237+                virtual auto validate() const -> Result { return Result::ok(); }
16238+                virtual auto parse( std::string const& exeName,
16239+                                    TokenStream tokens ) const
16240+                    -> InternalParseResult = 0;
16241+                virtual size_t cardinality() const;
16242+
16243+                InternalParseResult parse( Args const& args ) const;
16244+            };
16245+
16246+            template <typename DerivedT>
16247+            class ComposableParserImpl : public ParserBase {
16248+            public:
16249+                template <typename T>
16250+                auto operator|( T const& other ) const -> Parser;
16251+            };
16252+
16253+            // Common code and state for Args and Opts
16254+            template <typename DerivedT>
16255+            class ParserRefImpl : public ComposableParserImpl<DerivedT> {
16256+            protected:
16257+                Optionality m_optionality = Optionality::Optional;
16258+                std::shared_ptr<BoundRef> m_ref;
16259+                StringRef m_hint;
16260+                StringRef m_description;
16261+
16262+                explicit ParserRefImpl( std::shared_ptr<BoundRef> const& ref ):
16263+                    m_ref( ref ) {}
16264+
16265+            public:
16266+                template <typename LambdaT>
16267+                ParserRefImpl( accept_many_t,
16268+                               LambdaT const& ref,
16269+                               StringRef hint ):
16270+                    m_ref( std::make_shared<BoundManyLambda<LambdaT>>( ref ) ),
16271+                    m_hint( hint ) {}
16272+
16273+                template <typename T,
16274+                          typename = typename std::enable_if_t<
16275+                              !Detail::is_unary_function<T>::value>>
16276+                ParserRefImpl( T& ref, StringRef hint ):
16277+                    m_ref( std::make_shared<BoundValueRef<T>>( ref ) ),
16278+                    m_hint( hint ) {}
16279+
16280+                template <typename LambdaT,
16281+                          typename = typename std::enable_if_t<
16282+                              Detail::is_unary_function<LambdaT>::value>>
16283+                ParserRefImpl( LambdaT const& ref, StringRef hint ):
16284+                    m_ref( std::make_shared<BoundLambda<LambdaT>>( ref ) ),
16285+                    m_hint( hint ) {}
16286+
16287+                DerivedT& operator()( StringRef description ) & {
16288+                    m_description = description;
16289+                    return static_cast<DerivedT&>( *this );
16290+                }
16291+                DerivedT&& operator()( StringRef description ) && {
16292+                    m_description = description;
16293+                    return static_cast<DerivedT&&>( *this );
16294+                }
16295+
16296+                auto optional() -> DerivedT& {
16297+                    m_optionality = Optionality::Optional;
16298+                    return static_cast<DerivedT&>( *this );
16299+                }
16300+
16301+                auto required() -> DerivedT& {
16302+                    m_optionality = Optionality::Required;
16303+                    return static_cast<DerivedT&>( *this );
16304+                }
16305+
16306+                auto isOptional() const -> bool {
16307+                    return m_optionality == Optionality::Optional;
16308+                }
16309+
16310+                auto cardinality() const -> size_t override {
16311+                    if ( m_ref->isContainer() )
16312+                        return 0;
16313+                    else
16314+                        return 1;
16315+                }
16316+
16317+                StringRef hint() const { return m_hint; }
16318+            };
16319+
16320+        } // namespace detail
16321+
16322+
16323+        // A parser for arguments
16324+        class Arg : public Detail::ParserRefImpl<Arg> {
16325+        public:
16326+            using ParserRefImpl::ParserRefImpl;
16327+            using ParserBase::parse;
16328+
16329+            Detail::InternalParseResult
16330+                parse(std::string const&,
16331+                      Detail::TokenStream tokens) const override;
16332+        };
16333+
16334+        // A parser for options
16335+        class Opt : public Detail::ParserRefImpl<Opt> {
16336+        protected:
16337+            std::vector<StringRef> m_optNames;
16338+
16339+        public:
16340+            template <typename LambdaT>
16341+            explicit Opt(LambdaT const& ref) :
16342+                ParserRefImpl(
16343+                    std::make_shared<Detail::BoundFlagLambda<LambdaT>>(ref)) {}
16344+
16345+            explicit Opt(bool& ref);
16346+
16347+            template <typename LambdaT,
16348+                      typename = typename std::enable_if_t<
16349+                          Detail::is_unary_function<LambdaT>::value>>
16350+            Opt( LambdaT const& ref, StringRef hint ):
16351+                ParserRefImpl( ref, hint ) {}
16352+
16353+            template <typename LambdaT>
16354+            Opt( accept_many_t, LambdaT const& ref, StringRef hint ):
16355+                ParserRefImpl( accept_many, ref, hint ) {}
16356+
16357+            template <typename T,
16358+                      typename = typename std::enable_if_t<
16359+                          !Detail::is_unary_function<T>::value>>
16360+            Opt( T& ref, StringRef hint ):
16361+                ParserRefImpl( ref, hint ) {}
16362+
16363+            Opt& operator[]( StringRef optName ) & {
16364+                m_optNames.push_back(optName);
16365+                return *this;
16366+            }
16367+            Opt&& operator[]( StringRef optName ) && {
16368+                m_optNames.push_back( optName );
16369+                return CATCH_MOVE(*this);
16370+            }
16371+
16372+            Detail::HelpColumns getHelpColumns() const;
16373+
16374+            bool isMatch(StringRef optToken) const;
16375+
16376+            using ParserBase::parse;
16377+
16378+            Detail::InternalParseResult
16379+                parse(std::string const&,
16380+                      Detail::TokenStream tokens) const override;
16381+
16382+            Detail::Result validate() const override;
16383+        };
16384+
16385+        // Specifies the name of the executable
16386+        class ExeName : public Detail::ComposableParserImpl<ExeName> {
16387+            std::shared_ptr<std::string> m_name;
16388+            std::shared_ptr<Detail::BoundValueRefBase> m_ref;
16389+
16390+        public:
16391+            ExeName();
16392+            explicit ExeName(std::string& ref);
16393+
16394+            template <typename LambdaT>
16395+            explicit ExeName(LambdaT const& lambda) : ExeName() {
16396+                m_ref = std::make_shared<Detail::BoundLambda<LambdaT>>(lambda);
16397+            }
16398+
16399+            // The exe name is not parsed out of the normal tokens, but is
16400+            // handled specially
16401+            Detail::InternalParseResult
16402+                parse(std::string const&,
16403+                      Detail::TokenStream tokens) const override;
16404+
16405+            std::string const& name() const { return *m_name; }
16406+            Detail::ParserResult set(std::string const& newName);
16407+        };
16408+
16409+
16410+        // A Combined parser
16411+        class Parser : Detail::ParserBase {
16412+            mutable ExeName m_exeName;
16413+            std::vector<Opt> m_options;
16414+            std::vector<Arg> m_args;
16415+
16416+        public:
16417+
16418+            auto operator|=(ExeName const& exeName) -> Parser& {
16419+                m_exeName = exeName;
16420+                return *this;
16421+            }
16422+
16423+            auto operator|=(Arg const& arg) -> Parser& {
16424+                m_args.push_back(arg);
16425+                return *this;
16426+            }
16427+
16428+            friend Parser& operator|=( Parser& p, Opt const& opt ) {
16429+                p.m_options.push_back( opt );
16430+                return p;
16431+            }
16432+            friend Parser& operator|=( Parser& p, Opt&& opt ) {
16433+                p.m_options.push_back( CATCH_MOVE(opt) );
16434+                return p;
16435+            }
16436+
16437+            Parser& operator|=(Parser const& other);
16438+
16439+            template <typename T>
16440+            friend Parser operator|( Parser const& p, T&& rhs ) {
16441+                Parser temp( p );
16442+                temp |= rhs;
16443+                return temp;
16444+            }
16445+
16446+            template <typename T>
16447+            friend Parser operator|( Parser&& p, T&& rhs ) {
16448+                p |= CATCH_FORWARD(rhs);
16449+                return CATCH_MOVE(p);
16450+            }
16451+
16452+            std::vector<Detail::HelpColumns> getHelpColumns() const;
16453+
16454+            void writeToStream(std::ostream& os) const;
16455+
16456+            friend auto operator<<(std::ostream& os, Parser const& parser)
16457+                -> std::ostream& {
16458+                parser.writeToStream(os);
16459+                return os;
16460+            }
16461+
16462+            Detail::Result validate() const override;
16463+
16464+            using ParserBase::parse;
16465+            Detail::InternalParseResult
16466+                parse(std::string const& exeName,
16467+                      Detail::TokenStream tokens) const override;
16468+        };
16469+
16470+        /**
16471+         * Wrapper over argc + argv, assumes that the inputs outlive it
16472+         */
16473+        class Args {
16474+            friend Detail::TokenStream;
16475+            StringRef m_exeName;
16476+            std::vector<StringRef> m_args;
16477+
16478+        public:
16479+            Args(int argc, char const* const* argv);
16480+            // Helper constructor for testing
16481+            Args(std::initializer_list<StringRef> args);
16482+
16483+            StringRef exeName() const { return m_exeName; }
16484+        };
16485+
16486+
16487+        // Convenience wrapper for option parser that specifies the help option
16488+        struct Help : Opt {
16489+            Help(bool& showHelpFlag);
16490+        };
16491+
16492+        // Result type for parser operation
16493+        using Detail::ParserResult;
16494+
16495+        namespace Detail {
16496+            template <typename DerivedT>
16497+            template <typename T>
16498+            Parser
16499+                ComposableParserImpl<DerivedT>::operator|(T const& other) const {
16500+                return Parser() | static_cast<DerivedT const&>(*this) | other;
16501+            }
16502+        }
16503+
16504+    } // namespace Clara
16505+} // namespace Catch
16506+
16507+#if defined( __clang__ )
16508+#    pragma clang diagnostic pop
16509+#endif
16510+
16511+#if defined( __GNUC__ )
16512+#    pragma GCC diagnostic pop
16513+#endif
16514+
16515+#endif // CATCH_CLARA_HPP_INCLUDED
16516+
16517+namespace Catch {
16518+
16519+    struct ConfigData;
16520+
16521+    Clara::Parser makeCommandLineParser( ConfigData& config );
16522+
16523+} // end namespace Catch
16524+
16525+#endif // CATCH_COMMANDLINE_HPP_INCLUDED
16526+
16527+namespace Catch {
16528+
16529+    class Session : Detail::NonCopyable {
16530+    public:
16531+
16532+        Session();
16533+        ~Session();
16534+
16535+        void showHelp() const;
16536+        void libIdentify();
16537+
16538+        int applyCommandLine( int argc, char const * const * argv );
16539+    #if defined(CATCH_CONFIG_WCHAR) && defined(_WIN32) && defined(UNICODE)
16540+        int applyCommandLine( int argc, wchar_t const * const * argv );
16541+    #endif
16542+
16543+        void useConfigData( ConfigData const& configData );
16544+
16545+        template<typename CharT>
16546+        int run(int argc, CharT const * const argv[]) {
16547+            if (m_startupExceptions)
16548+                return 1;
16549+            int returnCode = applyCommandLine(argc, argv);
16550+            if (returnCode == 0)
16551+                returnCode = run();
16552+            return returnCode;
16553+        }
16554+
16555+        int run();
16556+
16557+        Clara::Parser const& cli() const;
16558+        void cli( Clara::Parser const& newParser );
16559+        ConfigData& configData();
16560+        Config& config();
16561+    private:
16562+        int runInternal();
16563+
16564+        Clara::Parser m_cli;
16565+        ConfigData m_configData;
16566+        Detail::unique_ptr<Config> m_config;
16567+        bool m_startupExceptions = false;
16568+    };
16569+
16570+} // end namespace Catch
16571+
16572+#endif // CATCH_SESSION_HPP_INCLUDED
16573+
16574+
16575+#ifndef CATCH_TAG_ALIAS_HPP_INCLUDED
16576+#define CATCH_TAG_ALIAS_HPP_INCLUDED
16577+
16578+
16579+#include <string>
16580+
16581+namespace Catch {
16582+
16583+    struct TagAlias {
16584+        TagAlias(std::string const& _tag, SourceLineInfo _lineInfo):
16585+            tag(_tag),
16586+            lineInfo(_lineInfo)
16587+        {}
16588+
16589+        std::string tag;
16590+        SourceLineInfo lineInfo;
16591+    };
16592+
16593+} // end namespace Catch
16594+
16595+#endif // CATCH_TAG_ALIAS_HPP_INCLUDED
16596+
16597+
16598+#ifndef CATCH_TAG_ALIAS_AUTOREGISTRAR_HPP_INCLUDED
16599+#define CATCH_TAG_ALIAS_AUTOREGISTRAR_HPP_INCLUDED
16600+
16601+
16602+namespace Catch {
16603+
16604+    struct RegistrarForTagAliases {
16605+        RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo );
16606+    };
16607+
16608+} // end namespace Catch
16609+
16610+#define CATCH_REGISTER_TAG_ALIAS( alias, spec ) \
16611+    CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
16612+    CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
16613+    namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } \
16614+    CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
16615+
16616+#endif // CATCH_TAG_ALIAS_AUTOREGISTRAR_HPP_INCLUDED
16617+
16618+
16619+#ifndef CATCH_TEMPLATE_TEST_MACROS_HPP_INCLUDED
16620+#define CATCH_TEMPLATE_TEST_MACROS_HPP_INCLUDED
16621+
16622+// We need this suppression to leak, because it took until GCC 10
16623+// for the front end to handle local suppression via _Pragma properly
16624+// inside templates (so `TEMPLATE_TEST_CASE` and co).
16625+// **THIS IS DIFFERENT FOR STANDARD TESTS, WHERE GCC 9 IS SUFFICIENT**
16626+#if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC) && __GNUC__ < 10
16627+#pragma GCC diagnostic ignored "-Wparentheses"
16628+#endif
16629+
16630+
16631+
16632+
16633+#ifndef CATCH_TEST_MACROS_HPP_INCLUDED
16634+#define CATCH_TEST_MACROS_HPP_INCLUDED
16635+
16636+
16637+
16638+#ifndef CATCH_TEST_MACRO_IMPL_HPP_INCLUDED
16639+#define CATCH_TEST_MACRO_IMPL_HPP_INCLUDED
16640+
16641+
16642+
16643+#ifndef CATCH_ASSERTION_HANDLER_HPP_INCLUDED
16644+#define CATCH_ASSERTION_HANDLER_HPP_INCLUDED
16645+
16646+
16647+
16648+#ifndef CATCH_DECOMPOSER_HPP_INCLUDED
16649+#define CATCH_DECOMPOSER_HPP_INCLUDED
16650+
16651+
16652+
16653+#ifndef CATCH_COMPARE_TRAITS_HPP_INCLUDED
16654+#define CATCH_COMPARE_TRAITS_HPP_INCLUDED
16655+
16656+
16657+#include <type_traits>
16658+
16659+namespace Catch {
16660+    namespace Detail {
16661+
16662+#if defined( __GNUC__ ) && !defined( __clang__ )
16663+#    pragma GCC diagnostic push
16664+    // GCC likes to complain about comparing bool with 0, in the decltype()
16665+    // that defines the comparable traits below.
16666+#    pragma GCC diagnostic ignored "-Wbool-compare"
16667+    // "ordered comparison of pointer with integer zero" same as above,
16668+    // but it does not have a separate warning flag to suppress
16669+#    pragma GCC diagnostic ignored "-Wextra"
16670+    // Did you know that comparing floats with `0` directly
16671+    // is super-duper dangerous in unevaluated context?
16672+#    pragma GCC diagnostic ignored "-Wfloat-equal"
16673+#endif
16674+
16675+#if defined( __clang__ )
16676+#    pragma clang diagnostic push
16677+    // Did you know that comparing floats with `0` directly
16678+    // is super-duper dangerous in unevaluated context?
16679+#    pragma clang diagnostic ignored "-Wfloat-equal"
16680+#endif
16681+
16682+#define CATCH_DEFINE_COMPARABLE_TRAIT( id, op )                               \
16683+    template <typename, typename, typename = void>                            \
16684+    struct is_##id##_comparable : std::false_type {};                         \
16685+    template <typename T, typename U>                                         \
16686+    struct is_##id##_comparable<                                              \
16687+        T,                                                                    \
16688+        U,                                                                    \
16689+        void_t<decltype( std::declval<T>() op std::declval<U>() )>>           \
16690+        : std::true_type {};                                                  \
16691+    template <typename, typename = void>                                      \
16692+    struct is_##id##_0_comparable : std::false_type {};                       \
16693+    template <typename T>                                                     \
16694+    struct is_##id##_0_comparable<T,                                          \
16695+                                  void_t<decltype( std::declval<T>() op 0 )>> \
16696+        : std::true_type {};
16697+
16698+        // We need all 6 pre-spaceship comparison ops: <, <=, >, >=, ==, !=
16699+        CATCH_DEFINE_COMPARABLE_TRAIT( lt, < )
16700+        CATCH_DEFINE_COMPARABLE_TRAIT( le, <= )
16701+        CATCH_DEFINE_COMPARABLE_TRAIT( gt, > )
16702+        CATCH_DEFINE_COMPARABLE_TRAIT( ge, >= )
16703+        CATCH_DEFINE_COMPARABLE_TRAIT( eq, == )
16704+        CATCH_DEFINE_COMPARABLE_TRAIT( ne, != )
16705+
16706+#undef CATCH_DEFINE_COMPARABLE_TRAIT
16707+
16708+#if defined( __GNUC__ ) && !defined( __clang__ )
16709+#    pragma GCC diagnostic pop
16710+#endif
16711+#if defined( __clang__ )
16712+#    pragma clang diagnostic pop
16713+#endif
16714+
16715+
16716+    } // namespace Detail
16717+} // namespace Catch
16718+
16719+#endif // CATCH_COMPARE_TRAITS_HPP_INCLUDED
16720+
16721+
16722+#ifndef CATCH_LOGICAL_TRAITS_HPP_INCLUDED
16723+#define CATCH_LOGICAL_TRAITS_HPP_INCLUDED
16724+
16725+#include <type_traits>
16726+
16727+namespace Catch {
16728+namespace Detail {
16729+
16730+#if defined( __cpp_lib_logical_traits ) && __cpp_lib_logical_traits >= 201510
16731+
16732+    using std::conjunction;
16733+    using std::disjunction;
16734+    using std::negation;
16735+
16736+#else
16737+
16738+    template <class...> struct conjunction : std::true_type {};
16739+    template <class B1> struct conjunction<B1> : B1 {};
16740+    template <class B1, class... Bn>
16741+    struct conjunction<B1, Bn...>
16742+        : std::conditional_t<bool( B1::value ), conjunction<Bn...>, B1> {};
16743+
16744+    template <class...> struct disjunction : std::false_type {};
16745+    template <class B1> struct disjunction<B1> : B1 {};
16746+    template <class B1, class... Bn>
16747+    struct disjunction<B1, Bn...>
16748+        : std::conditional_t<bool( B1::value ), B1, disjunction<Bn...>> {};
16749+
16750+    template <class B>
16751+    struct negation : std::integral_constant<bool, !bool(B::value)> {};
16752+
16753+#endif
16754+
16755+} // namespace Detail
16756+} // namespace Catch
16757+
16758+#endif // CATCH_LOGICAL_TRAITS_HPP_INCLUDED
16759+
16760+#include <type_traits>
16761+#include <iosfwd>
16762+
16763+/** \file
16764+ * Why does decomposing look the way it does:
16765+ *
16766+ * Conceptually, decomposing is simple. We change `REQUIRE( a == b )` into
16767+ * `Decomposer{} <= a == b`, so that `Decomposer{} <= a` is evaluated first,
16768+ * and our custom operator is used for `a == b`, because `a` is transformed
16769+ * into `ExprLhs<T&>` and then into `BinaryExpr<T&, U&>`.
16770+ *
16771+ * In practice, decomposing ends up a mess, because we have to support
16772+ * various fun things.
16773+ *
16774+ * 1) Types that are only comparable with literal 0, and they do this by
16775+ *    comparing against a magic type with pointer constructor and deleted
16776+ *    other constructors. Example: `REQUIRE((a <=> b) == 0)` in libstdc++
16777+ *
16778+ * 2) Types that are only comparable with literal 0, and they do this by
16779+ *    comparing against a magic type with consteval integer constructor.
16780+ *    Example: `REQUIRE((a <=> b) == 0)` in current MSVC STL.
16781+ *
16782+ * 3) Types that have no linkage, and so we cannot form a reference to
16783+ *    them. Example: some implementations of traits.
16784+ *
16785+ * 4) Starting with C++20, when the compiler sees `a == b`, it also uses
16786+ *    `b == a` when constructing the overload set. For us this means that
16787+ *    when the compiler handles `ExprLhs<T> == b`, it also tries to resolve
16788+ *    the overload set for `b == ExprLhs<T>`.
16789+ *
16790+ * To accomodate these use cases, decomposer ended up rather complex.
16791+ *
16792+ * 1) These types are handled by adding SFINAE overloads to our comparison
16793+ *    operators, checking whether `T == U` are comparable with the given
16794+ *    operator, and if not, whether T (or U) are comparable with literal 0.
16795+ *    If yes, the overload compares T (or U) with 0 literal inline in the
16796+ *    definition.
16797+ *
16798+ *    Note that for extra correctness, we check  that the other type is
16799+ *    either an `int` (literal 0 is captured as `int` by templates), or
16800+ *    a `long` (some platforms use 0L for `NULL` and we want to support
16801+ *    that for pointer comparisons).
16802+ *
16803+ * 2) For these types, `is_foo_comparable<T, int>` is true, but letting
16804+ *    them fall into the overload that actually does `T == int` causes
16805+ *    compilation error. Handling them requires that the decomposition
16806+ *    is `constexpr`, so that P2564R3 applies and the `consteval` from
16807+ *    their accompanying magic type is propagated through the `constexpr`
16808+ *    call stack.
16809+ *
16810+ *    However this is not enough to handle these types automatically,
16811+ *    because our default is to capture types by reference, to avoid
16812+ *    runtime copies. While these references cannot become dangling,
16813+ *    they outlive the constexpr context and thus the default capture
16814+ *    path cannot be actually constexpr.
16815+ *
16816+ *    The solution is to capture these types by value, by explicitly
16817+ *    specializing `Catch::capture_by_value` for them. Catch2 provides
16818+ *    specialization for `std::foo_ordering`s, but users can specialize
16819+ *    the trait for their own types as well.
16820+ *
16821+ * 3) If a type has no linkage, we also cannot capture it by reference.
16822+ *    The solution is once again to capture them by value. We handle
16823+ *    the common cases by using `std::is_arithmetic` as the default
16824+ *    for `Catch::capture_by_value`, but that is only a some-effort
16825+ *    heuristic. But as with 2), users can specialize `capture_by_value`
16826+ *    for their own types as needed.
16827+ *
16828+ * 4) To support C++20 and make the SFINAE on our decomposing operators
16829+ *    work, the SFINAE has to happen in return type, rather than in
16830+ *    a template type. This is due to our use of logical type traits
16831+ *    (`conjunction`/`disjunction`/`negation`), that we use to workaround
16832+ *    an issue in older (9-) versions of GCC. I still blame C++20 for
16833+ *    this, because without the comparison order switching, the logical
16834+ *    traits could still be used in template type.
16835+ *
16836+ * There are also other side concerns, e.g. supporting both `REQUIRE(a)`
16837+ * and `REQUIRE(a == b)`, or making `REQUIRE_THAT(a, IsEqual(b))` slot
16838+ * nicely into the same expression handling logic, but these are rather
16839+ * straightforward and add only a bit of complexity (e.g. common base
16840+ * class for decomposed expressions).
16841+ */
16842+
16843+#ifdef _MSC_VER
16844+#pragma warning(push)
16845+#pragma warning(disable:4389) // '==' : signed/unsigned mismatch
16846+#pragma warning(disable:4018) // more "signed/unsigned mismatch"
16847+#pragma warning(disable:4312) // Converting int to T* using reinterpret_cast (issue on x64 platform)
16848+#pragma warning(disable:4180) // qualifier applied to function type has no meaning
16849+#pragma warning(disable:4800) // Forcing result to true or false
16850+#endif
16851+
16852+#ifdef __clang__
16853+#  pragma clang diagnostic push
16854+#  pragma clang diagnostic ignored "-Wsign-compare"
16855+#elif defined __GNUC__
16856+#  pragma GCC diagnostic push
16857+#  pragma GCC diagnostic ignored "-Wsign-compare"
16858+#endif
16859+
16860+#if defined(CATCH_CPP20_OR_GREATER) && __has_include(<compare>)
16861+#  include <compare>
16862+#    if defined( __cpp_lib_three_way_comparison ) && \
16863+            __cpp_lib_three_way_comparison >= 201907L
16864+#      define CATCH_CONFIG_CPP20_COMPARE_OVERLOADS
16865+#    endif
16866+#endif
16867+
16868+namespace Catch {
16869+
16870+    namespace Detail {
16871+        // This was added in C++20, but we require only C++14 for now.
16872+        template <typename T>
16873+        using RemoveCVRef_t = std::remove_cv_t<std::remove_reference_t<T>>;
16874+    }
16875+
16876+    // Note: There is nothing that stops us from extending this,
16877+    //       e.g. to `std::is_scalar`, but the more encompassing
16878+    //       traits are usually also more expensive. For now we
16879+    //       keep this as it used to be and it can be changed later.
16880+    template <typename T>
16881+    struct capture_by_value
16882+        : std::integral_constant<bool, std::is_arithmetic<T>{}> {};
16883+
16884+#if defined( CATCH_CONFIG_CPP20_COMPARE_OVERLOADS )
16885+    template <>
16886+    struct capture_by_value<std::strong_ordering> : std::true_type {};
16887+    template <>
16888+    struct capture_by_value<std::weak_ordering> : std::true_type {};
16889+    template <>
16890+    struct capture_by_value<std::partial_ordering> : std::true_type {};
16891+#endif
16892+
16893+    template <typename T>
16894+    struct always_false : std::false_type {};
16895+
16896+    class ITransientExpression {
16897+        bool m_isBinaryExpression;
16898+        bool m_result;
16899+
16900+    public:
16901+        constexpr auto isBinaryExpression() const -> bool { return m_isBinaryExpression; }
16902+        constexpr auto getResult() const -> bool { return m_result; }
16903+        //! This function **has** to be overriden by the derived class.
16904+        virtual void streamReconstructedExpression( std::ostream& os ) const;
16905+
16906+        constexpr ITransientExpression( bool isBinaryExpression, bool result )
16907+        :   m_isBinaryExpression( isBinaryExpression ),
16908+            m_result( result )
16909+        {}
16910+
16911+        ITransientExpression() = default;
16912+        ITransientExpression(ITransientExpression const&) = default;
16913+        ITransientExpression& operator=(ITransientExpression const&) = default;
16914+
16915+        friend std::ostream& operator<<(std::ostream& out, ITransientExpression const& expr) {
16916+            expr.streamReconstructedExpression(out);
16917+            return out;
16918+        }
16919+
16920+    protected:
16921+        ~ITransientExpression() = default;
16922+    };
16923+
16924+    void formatReconstructedExpression( std::ostream &os, std::string const& lhs, StringRef op, std::string const& rhs );
16925+
16926+    template<typename LhsT, typename RhsT>
16927+    class BinaryExpr  : public ITransientExpression {
16928+        LhsT m_lhs;
16929+        StringRef m_op;
16930+        RhsT m_rhs;
16931+
16932+        void streamReconstructedExpression( std::ostream &os ) const override {
16933+            formatReconstructedExpression
16934+                    ( os, Catch::Detail::stringify( m_lhs ), m_op, Catch::Detail::stringify( m_rhs ) );
16935+        }
16936+
16937+    public:
16938+        constexpr BinaryExpr( bool comparisonResult, LhsT lhs, StringRef op, RhsT rhs )
16939+        :   ITransientExpression{ true, comparisonResult },
16940+            m_lhs( lhs ),
16941+            m_op( op ),
16942+            m_rhs( rhs )
16943+        {}
16944+
16945+        template<typename T>
16946+        auto operator && ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
16947+            static_assert(always_false<T>::value,
16948+            "chained comparisons are not supported inside assertions, "
16949+            "wrap the expression inside parentheses, or decompose it");
16950+        }
16951+
16952+        template<typename T>
16953+        auto operator || ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
16954+            static_assert(always_false<T>::value,
16955+            "chained comparisons are not supported inside assertions, "
16956+            "wrap the expression inside parentheses, or decompose it");
16957+        }
16958+
16959+        template<typename T>
16960+        auto operator == ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
16961+            static_assert(always_false<T>::value,
16962+            "chained comparisons are not supported inside assertions, "
16963+            "wrap the expression inside parentheses, or decompose it");
16964+        }
16965+
16966+        template<typename T>
16967+        auto operator != ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
16968+            static_assert(always_false<T>::value,
16969+            "chained comparisons are not supported inside assertions, "
16970+            "wrap the expression inside parentheses, or decompose it");
16971+        }
16972+
16973+        template<typename T>
16974+        auto operator > ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
16975+            static_assert(always_false<T>::value,
16976+            "chained comparisons are not supported inside assertions, "
16977+            "wrap the expression inside parentheses, or decompose it");
16978+        }
16979+
16980+        template<typename T>
16981+        auto operator < ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
16982+            static_assert(always_false<T>::value,
16983+            "chained comparisons are not supported inside assertions, "
16984+            "wrap the expression inside parentheses, or decompose it");
16985+        }
16986+
16987+        template<typename T>
16988+        auto operator >= ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
16989+            static_assert(always_false<T>::value,
16990+            "chained comparisons are not supported inside assertions, "
16991+            "wrap the expression inside parentheses, or decompose it");
16992+        }
16993+
16994+        template<typename T>
16995+        auto operator <= ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
16996+            static_assert(always_false<T>::value,
16997+            "chained comparisons are not supported inside assertions, "
16998+            "wrap the expression inside parentheses, or decompose it");
16999+        }
17000+    };
17001+
17002+    template<typename LhsT>
17003+    class UnaryExpr : public ITransientExpression {
17004+        LhsT m_lhs;
17005+
17006+        void streamReconstructedExpression( std::ostream &os ) const override {
17007+            os << Catch::Detail::stringify( m_lhs );
17008+        }
17009+
17010+    public:
17011+        explicit constexpr UnaryExpr( LhsT lhs )
17012+        :   ITransientExpression{ false, static_cast<bool>(lhs) },
17013+            m_lhs( lhs )
17014+        {}
17015+    };
17016+
17017+
17018+    template<typename LhsT>
17019+    class ExprLhs {
17020+        LhsT m_lhs;
17021+    public:
17022+        explicit constexpr ExprLhs( LhsT lhs ) : m_lhs( lhs ) {}
17023+
17024+#define CATCH_INTERNAL_DEFINE_EXPRESSION_EQUALITY_OPERATOR( id, op )           \
17025+    template <typename RhsT>                                                   \
17026+    constexpr friend auto operator op( ExprLhs&& lhs, RhsT&& rhs )             \
17027+        -> std::enable_if_t<                                                   \
17028+            Detail::conjunction<Detail::is_##id##_comparable<LhsT, RhsT>,      \
17029+                                Detail::negation<capture_by_value<             \
17030+                                    Detail::RemoveCVRef_t<RhsT>>>>::value,     \
17031+            BinaryExpr<LhsT, RhsT const&>> {                                   \
17032+        return {                                                               \
17033+            static_cast<bool>( lhs.m_lhs op rhs ), lhs.m_lhs, #op##_sr, rhs }; \
17034+    }                                                                          \
17035+    template <typename RhsT>                                                   \
17036+    constexpr friend auto operator op( ExprLhs&& lhs, RhsT rhs )               \
17037+        -> std::enable_if_t<                                                   \
17038+            Detail::conjunction<Detail::is_##id##_comparable<LhsT, RhsT>,      \
17039+                                capture_by_value<RhsT>>::value,                \
17040+            BinaryExpr<LhsT, RhsT>> {                                          \
17041+        return {                                                               \
17042+            static_cast<bool>( lhs.m_lhs op rhs ), lhs.m_lhs, #op##_sr, rhs }; \
17043+    }                                                                          \
17044+    template <typename RhsT>                                                   \
17045+    constexpr friend auto operator op( ExprLhs&& lhs, RhsT rhs )               \
17046+        -> std::enable_if_t<                                                   \
17047+            Detail::conjunction<                                               \
17048+                Detail::negation<Detail::is_##id##_comparable<LhsT, RhsT>>,    \
17049+                Detail::is_eq_0_comparable<LhsT>,                              \
17050+              /* We allow long because we want `ptr op NULL` to be accepted */ \
17051+                Detail::disjunction<std::is_same<RhsT, int>,                   \
17052+                                    std::is_same<RhsT, long>>>::value,         \
17053+            BinaryExpr<LhsT, RhsT>> {                                          \
17054+        if ( rhs != 0 ) { throw_test_failure_exception(); }                    \
17055+        return {                                                               \
17056+            static_cast<bool>( lhs.m_lhs op 0 ), lhs.m_lhs, #op##_sr, rhs };   \
17057+    }                                                                          \
17058+    template <typename RhsT>                                                   \
17059+    constexpr friend auto operator op( ExprLhs&& lhs, RhsT rhs )               \
17060+        -> std::enable_if_t<                                                   \
17061+            Detail::conjunction<                                               \
17062+                Detail::negation<Detail::is_##id##_comparable<LhsT, RhsT>>,    \
17063+                Detail::is_eq_0_comparable<RhsT>,                              \
17064+              /* We allow long because we want `ptr op NULL` to be accepted */ \
17065+                Detail::disjunction<std::is_same<LhsT, int>,                   \
17066+                                    std::is_same<LhsT, long>>>::value,         \
17067+            BinaryExpr<LhsT, RhsT>> {                                          \
17068+        if ( lhs.m_lhs != 0 ) { throw_test_failure_exception(); }              \
17069+        return { static_cast<bool>( 0 op rhs ), lhs.m_lhs, #op##_sr, rhs };    \
17070+    }
17071+
17072+        CATCH_INTERNAL_DEFINE_EXPRESSION_EQUALITY_OPERATOR( eq, == )
17073+        CATCH_INTERNAL_DEFINE_EXPRESSION_EQUALITY_OPERATOR( ne, != )
17074+
17075+    #undef CATCH_INTERNAL_DEFINE_EXPRESSION_EQUALITY_OPERATOR
17076+
17077+
17078+#define CATCH_INTERNAL_DEFINE_EXPRESSION_COMPARISON_OPERATOR( id, op )         \
17079+    template <typename RhsT>                                                   \
17080+    constexpr friend auto operator op( ExprLhs&& lhs, RhsT&& rhs )             \
17081+        -> std::enable_if_t<                                                   \
17082+            Detail::conjunction<Detail::is_##id##_comparable<LhsT, RhsT>,      \
17083+                                Detail::negation<capture_by_value<             \
17084+                                    Detail::RemoveCVRef_t<RhsT>>>>::value,     \
17085+            BinaryExpr<LhsT, RhsT const&>> {                                   \
17086+        return {                                                               \
17087+            static_cast<bool>( lhs.m_lhs op rhs ), lhs.m_lhs, #op##_sr, rhs }; \
17088+    }                                                                          \
17089+    template <typename RhsT>                                                   \
17090+    constexpr friend auto operator op( ExprLhs&& lhs, RhsT rhs )               \
17091+        -> std::enable_if_t<                                                   \
17092+            Detail::conjunction<Detail::is_##id##_comparable<LhsT, RhsT>,      \
17093+                                capture_by_value<RhsT>>::value,                \
17094+            BinaryExpr<LhsT, RhsT>> {                                          \
17095+        return {                                                               \
17096+            static_cast<bool>( lhs.m_lhs op rhs ), lhs.m_lhs, #op##_sr, rhs }; \
17097+    }                                                                          \
17098+    template <typename RhsT>                                                   \
17099+    constexpr friend auto operator op( ExprLhs&& lhs, RhsT rhs )               \
17100+        -> std::enable_if_t<                                                   \
17101+            Detail::conjunction<                                               \
17102+                Detail::negation<Detail::is_##id##_comparable<LhsT, RhsT>>,    \
17103+                Detail::is_##id##_0_comparable<LhsT>,                          \
17104+                std::is_same<RhsT, int>>::value,                               \
17105+            BinaryExpr<LhsT, RhsT>> {                                          \
17106+        if ( rhs != 0 ) { throw_test_failure_exception(); }                    \
17107+        return {                                                               \
17108+            static_cast<bool>( lhs.m_lhs op 0 ), lhs.m_lhs, #op##_sr, rhs };   \
17109+    }                                                                          \
17110+    template <typename RhsT>                                                   \
17111+    constexpr friend auto operator op( ExprLhs&& lhs, RhsT rhs )               \
17112+        -> std::enable_if_t<                                                   \
17113+            Detail::conjunction<                                               \
17114+                Detail::negation<Detail::is_##id##_comparable<LhsT, RhsT>>,    \
17115+                Detail::is_##id##_0_comparable<RhsT>,                          \
17116+                std::is_same<LhsT, int>>::value,                               \
17117+            BinaryExpr<LhsT, RhsT>> {                                          \
17118+        if ( lhs.m_lhs != 0 ) { throw_test_failure_exception(); }              \
17119+        return { static_cast<bool>( 0 op rhs ), lhs.m_lhs, #op##_sr, rhs };    \
17120+    }
17121+
17122+        CATCH_INTERNAL_DEFINE_EXPRESSION_COMPARISON_OPERATOR( lt, < )
17123+        CATCH_INTERNAL_DEFINE_EXPRESSION_COMPARISON_OPERATOR( le, <= )
17124+        CATCH_INTERNAL_DEFINE_EXPRESSION_COMPARISON_OPERATOR( gt, > )
17125+        CATCH_INTERNAL_DEFINE_EXPRESSION_COMPARISON_OPERATOR( ge, >= )
17126+
17127+    #undef CATCH_INTERNAL_DEFINE_EXPRESSION_COMPARISON_OPERATOR
17128+
17129+
17130+#define CATCH_INTERNAL_DEFINE_EXPRESSION_OPERATOR( op )                        \
17131+    template <typename RhsT>                                                   \
17132+    constexpr friend auto operator op( ExprLhs&& lhs, RhsT&& rhs )             \
17133+        -> std::enable_if_t<                                                   \
17134+            !capture_by_value<Detail::RemoveCVRef_t<RhsT>>::value,             \
17135+            BinaryExpr<LhsT, RhsT const&>> {                                   \
17136+        return {                                                               \
17137+            static_cast<bool>( lhs.m_lhs op rhs ), lhs.m_lhs, #op##_sr, rhs }; \
17138+    }                                                                          \
17139+    template <typename RhsT>                                                   \
17140+    constexpr friend auto operator op( ExprLhs&& lhs, RhsT rhs )               \
17141+        -> std::enable_if_t<capture_by_value<RhsT>::value,                     \
17142+                            BinaryExpr<LhsT, RhsT>> {                          \
17143+        return {                                                               \
17144+            static_cast<bool>( lhs.m_lhs op rhs ), lhs.m_lhs, #op##_sr, rhs }; \
17145+    }
17146+
17147+        CATCH_INTERNAL_DEFINE_EXPRESSION_OPERATOR(|)
17148+        CATCH_INTERNAL_DEFINE_EXPRESSION_OPERATOR(&)
17149+        CATCH_INTERNAL_DEFINE_EXPRESSION_OPERATOR(^)
17150+
17151+    #undef CATCH_INTERNAL_DEFINE_EXPRESSION_OPERATOR
17152+
17153+        template<typename RhsT>
17154+        friend auto operator && ( ExprLhs &&, RhsT && ) -> BinaryExpr<LhsT, RhsT const&> {
17155+            static_assert(always_false<RhsT>::value,
17156+            "operator&& is not supported inside assertions, "
17157+            "wrap the expression inside parentheses, or decompose it");
17158+        }
17159+
17160+        template<typename RhsT>
17161+        friend auto operator || ( ExprLhs &&, RhsT && ) -> BinaryExpr<LhsT, RhsT const&> {
17162+            static_assert(always_false<RhsT>::value,
17163+            "operator|| is not supported inside assertions, "
17164+            "wrap the expression inside parentheses, or decompose it");
17165+        }
17166+
17167+        constexpr auto makeUnaryExpr() const -> UnaryExpr<LhsT> {
17168+            return UnaryExpr<LhsT>{ m_lhs };
17169+        }
17170+    };
17171+
17172+    struct Decomposer {
17173+        template <typename T,
17174+                  std::enable_if_t<!capture_by_value<Detail::RemoveCVRef_t<T>>::value,
17175+                      int> = 0>
17176+        constexpr friend auto operator <= ( Decomposer &&, T && lhs ) -> ExprLhs<T const&> {
17177+            return ExprLhs<const T&>{ lhs };
17178+        }
17179+
17180+        template <typename T,
17181+                  std::enable_if_t<capture_by_value<T>::value, int> = 0>
17182+        constexpr friend auto operator <= ( Decomposer &&, T value ) -> ExprLhs<T> {
17183+            return ExprLhs<T>{ value };
17184+        }
17185+    };
17186+
17187+} // end namespace Catch
17188+
17189+#ifdef _MSC_VER
17190+#pragma warning(pop)
17191+#endif
17192+#ifdef __clang__
17193+#  pragma clang diagnostic pop
17194+#elif defined __GNUC__
17195+#  pragma GCC diagnostic pop
17196+#endif
17197+
17198+#endif // CATCH_DECOMPOSER_HPP_INCLUDED
17199+
17200+#include <string>
17201+
17202+namespace Catch {
17203+
17204+    struct AssertionReaction {
17205+        bool shouldDebugBreak = false;
17206+        bool shouldThrow = false;
17207+        bool shouldSkip = false;
17208+    };
17209+
17210+    class AssertionHandler {
17211+        AssertionInfo m_assertionInfo;
17212+        AssertionReaction m_reaction;
17213+        bool m_completed = false;
17214+        IResultCapture& m_resultCapture;
17215+
17216+    public:
17217+        AssertionHandler
17218+            (   StringRef macroName,
17219+                SourceLineInfo const& lineInfo,
17220+                StringRef capturedExpression,
17221+                ResultDisposition::Flags resultDisposition );
17222+        ~AssertionHandler() {
17223+            if ( !m_completed ) {
17224+                m_resultCapture.handleIncomplete( m_assertionInfo );
17225+            }
17226+        }
17227+
17228+
17229+        template<typename T>
17230+        void handleExpr( ExprLhs<T> const& expr ) {
17231+            handleExpr( expr.makeUnaryExpr() );
17232+        }
17233+        void handleExpr( ITransientExpression const& expr );
17234+
17235+        void handleMessage(ResultWas::OfType resultType, StringRef message);
17236+
17237+        void handleExceptionThrownAsExpected();
17238+        void handleUnexpectedExceptionNotThrown();
17239+        void handleExceptionNotThrownAsExpected();
17240+        void handleThrowingCallSkipped();
17241+        void handleUnexpectedInflightException();
17242+
17243+        void complete();
17244+
17245+        // query
17246+        auto allowThrows() const -> bool;
17247+    };
17248+
17249+    void handleExceptionMatchExpr( AssertionHandler& handler, std::string const& str );
17250+
17251+} // namespace Catch
17252+
17253+#endif // CATCH_ASSERTION_HANDLER_HPP_INCLUDED
17254+
17255+
17256+#ifndef CATCH_PREPROCESSOR_INTERNAL_STRINGIFY_HPP_INCLUDED
17257+#define CATCH_PREPROCESSOR_INTERNAL_STRINGIFY_HPP_INCLUDED
17258+
17259+
17260+#if !defined(CATCH_CONFIG_DISABLE_STRINGIFICATION)
17261+  #define CATCH_INTERNAL_STRINGIFY(...) #__VA_ARGS__##_catch_sr
17262+#else
17263+  #define CATCH_INTERNAL_STRINGIFY(...) "Disabled by CATCH_CONFIG_DISABLE_STRINGIFICATION"_catch_sr
17264+#endif
17265+
17266+#endif // CATCH_PREPROCESSOR_INTERNAL_STRINGIFY_HPP_INCLUDED
17267+
17268+// We need this suppression to leak, because it took until GCC 10
17269+// for the front end to handle local suppression via _Pragma properly
17270+#if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC) && __GNUC__ <= 9
17271+  #pragma GCC diagnostic ignored "-Wparentheses"
17272+#endif
17273+
17274+#if !defined(CATCH_CONFIG_DISABLE)
17275+
17276+#if defined(CATCH_CONFIG_FAST_COMPILE) || defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
17277+
17278+///////////////////////////////////////////////////////////////////////////////
17279+// Another way to speed-up compilation is to omit local try-catch for REQUIRE*
17280+// macros.
17281+#define INTERNAL_CATCH_TRY
17282+#define INTERNAL_CATCH_CATCH( capturer )
17283+
17284+#else // CATCH_CONFIG_FAST_COMPILE
17285+
17286+#define INTERNAL_CATCH_TRY try
17287+#define INTERNAL_CATCH_CATCH( handler ) catch(...) { (handler).handleUnexpectedInflightException(); }
17288+
17289+#endif
17290+
17291+#define INTERNAL_CATCH_REACT( handler ) handler.complete();
17292+
17293+///////////////////////////////////////////////////////////////////////////////
17294+#define INTERNAL_CATCH_TEST( macroName, resultDisposition, ... ) \
17295+    do { /* NOLINT(bugprone-infinite-loop) */ \
17296+        /* The expression should not be evaluated, but warnings should hopefully be checked */ \
17297+        CATCH_INTERNAL_IGNORE_BUT_WARN(__VA_ARGS__); \
17298+        Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \
17299+        INTERNAL_CATCH_TRY { \
17300+            CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
17301+            CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
17302+            catchAssertionHandler.handleExpr( Catch::Decomposer() <= __VA_ARGS__ ); /* NOLINT(bugprone-chained-comparison) */ \
17303+            CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
17304+        } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \
17305+        INTERNAL_CATCH_REACT( catchAssertionHandler ) \
17306+    } while( (void)0, (false) && static_cast<const bool&>( !!(__VA_ARGS__) ) ) // the expression here is never evaluated at runtime but it forces the compiler to give it a look
17307+    // The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&.
17308+
17309+///////////////////////////////////////////////////////////////////////////////
17310+#define INTERNAL_CATCH_IF( macroName, resultDisposition, ... ) \
17311+    INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \
17312+    if( Catch::getResultCapture().lastAssertionPassed() )
17313+
17314+///////////////////////////////////////////////////////////////////////////////
17315+#define INTERNAL_CATCH_ELSE( macroName, resultDisposition, ... ) \
17316+    INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \
17317+    if( !Catch::getResultCapture().lastAssertionPassed() )
17318+
17319+///////////////////////////////////////////////////////////////////////////////
17320+#define INTERNAL_CATCH_NO_THROW( macroName, resultDisposition, ... ) \
17321+    do { \
17322+        Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \
17323+        try { \
17324+            CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
17325+            CATCH_INTERNAL_SUPPRESS_USELESS_CAST_WARNINGS \
17326+            static_cast<void>(__VA_ARGS__); \
17327+            CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
17328+            catchAssertionHandler.handleExceptionNotThrownAsExpected(); \
17329+        } \
17330+        catch( ... ) { \
17331+            catchAssertionHandler.handleUnexpectedInflightException(); \
17332+        } \
17333+        INTERNAL_CATCH_REACT( catchAssertionHandler ) \
17334+    } while( false )
17335+
17336+///////////////////////////////////////////////////////////////////////////////
17337+#define INTERNAL_CATCH_THROWS( macroName, resultDisposition, ... ) \
17338+    do { \
17339+        Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition); \
17340+        if( catchAssertionHandler.allowThrows() ) \
17341+            try { \
17342+                CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
17343+                CATCH_INTERNAL_SUPPRESS_UNUSED_RESULT \
17344+                CATCH_INTERNAL_SUPPRESS_USELESS_CAST_WARNINGS \
17345+                static_cast<void>(__VA_ARGS__); \
17346+                CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
17347+                catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
17348+            } \
17349+            catch( ... ) { \
17350+                catchAssertionHandler.handleExceptionThrownAsExpected(); \
17351+            } \
17352+        else \
17353+            catchAssertionHandler.handleThrowingCallSkipped(); \
17354+        INTERNAL_CATCH_REACT( catchAssertionHandler ) \
17355+    } while( false )
17356+
17357+///////////////////////////////////////////////////////////////////////////////
17358+#define INTERNAL_CATCH_THROWS_AS( macroName, exceptionType, resultDisposition, expr ) \
17359+    do { \
17360+        Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(expr) ", " CATCH_INTERNAL_STRINGIFY(exceptionType), resultDisposition ); \
17361+        if( catchAssertionHandler.allowThrows() ) \
17362+            try { \
17363+                CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
17364+                CATCH_INTERNAL_SUPPRESS_UNUSED_RESULT \
17365+                CATCH_INTERNAL_SUPPRESS_USELESS_CAST_WARNINGS \
17366+                static_cast<void>(expr); \
17367+                CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
17368+                catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
17369+            } \
17370+            catch( exceptionType const& ) { \
17371+                catchAssertionHandler.handleExceptionThrownAsExpected(); \
17372+            } \
17373+            catch( ... ) { \
17374+                catchAssertionHandler.handleUnexpectedInflightException(); \
17375+            } \
17376+        else \
17377+            catchAssertionHandler.handleThrowingCallSkipped(); \
17378+        INTERNAL_CATCH_REACT( catchAssertionHandler ) \
17379+    } while( false )
17380+
17381+
17382+
17383+///////////////////////////////////////////////////////////////////////////////
17384+// Although this is matcher-based, it can be used with just a string
17385+#define INTERNAL_CATCH_THROWS_STR_MATCHES( macroName, resultDisposition, matcher, ... ) \
17386+    do { \
17387+        Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \
17388+        if( catchAssertionHandler.allowThrows() ) \
17389+            try { \
17390+                CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
17391+                CATCH_INTERNAL_SUPPRESS_UNUSED_RESULT \
17392+                CATCH_INTERNAL_SUPPRESS_USELESS_CAST_WARNINGS \
17393+                static_cast<void>(__VA_ARGS__); \
17394+                CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
17395+                catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
17396+            } \
17397+            catch( ... ) { \
17398+                Catch::handleExceptionMatchExpr( catchAssertionHandler, matcher ); \
17399+            } \
17400+        else \
17401+            catchAssertionHandler.handleThrowingCallSkipped(); \
17402+        INTERNAL_CATCH_REACT( catchAssertionHandler ) \
17403+    } while( false )
17404+
17405+#endif // CATCH_CONFIG_DISABLE
17406+
17407+#endif // CATCH_TEST_MACRO_IMPL_HPP_INCLUDED
17408+
17409+
17410+#ifndef CATCH_SECTION_HPP_INCLUDED
17411+#define CATCH_SECTION_HPP_INCLUDED
17412+
17413+
17414+
17415+
17416+/** \file
17417+ * Wrapper for the STATIC_ANALYSIS_SUPPORT configuration option
17418+ *
17419+ * Some of Catch2's macros can be defined differently to work better with
17420+ * static analysis tools, like clang-tidy or coverity.
17421+ * Currently the main use case is to show that `SECTION`s are executed
17422+ * exclusively, and not all in one run of a `TEST_CASE`.
17423+ */
17424+
17425+#ifndef CATCH_CONFIG_STATIC_ANALYSIS_SUPPORT_HPP_INCLUDED
17426+#define CATCH_CONFIG_STATIC_ANALYSIS_SUPPORT_HPP_INCLUDED
17427+
17428+
17429+#if defined(__clang_analyzer__) || defined(__COVERITY__)
17430+    #define CATCH_INTERNAL_CONFIG_STATIC_ANALYSIS_SUPPORT
17431+#endif
17432+
17433+#if defined( CATCH_INTERNAL_CONFIG_STATIC_ANALYSIS_SUPPORT ) && \
17434+    !defined( CATCH_CONFIG_NO_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT ) && \
17435+    !defined( CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT )
17436+#    define CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT
17437+#endif
17438+
17439+
17440+#endif // CATCH_CONFIG_STATIC_ANALYSIS_SUPPORT_HPP_INCLUDED
17441+
17442+
17443+#ifndef CATCH_TIMER_HPP_INCLUDED
17444+#define CATCH_TIMER_HPP_INCLUDED
17445+
17446+#include <cstdint>
17447+
17448+namespace Catch {
17449+
17450+    class Timer {
17451+        uint64_t m_nanoseconds = 0;
17452+    public:
17453+        void start();
17454+        auto getElapsedNanoseconds() const -> uint64_t;
17455+        auto getElapsedMicroseconds() const -> uint64_t;
17456+        auto getElapsedMilliseconds() const -> unsigned int;
17457+        auto getElapsedSeconds() const -> double;
17458+    };
17459+
17460+} // namespace Catch
17461+
17462+#endif // CATCH_TIMER_HPP_INCLUDED
17463+
17464+namespace Catch {
17465+
17466+    class Section : Detail::NonCopyable {
17467+    public:
17468+        Section( SectionInfo&& info );
17469+        Section( SourceLineInfo const& _lineInfo,
17470+                 StringRef _name,
17471+                 const char* const = nullptr );
17472+        ~Section();
17473+
17474+        // This indicates whether the section should be executed or not
17475+        explicit operator bool() const;
17476+
17477+    private:
17478+        SectionInfo m_info;
17479+
17480+        Counts m_assertions;
17481+        bool m_sectionIncluded;
17482+        Timer m_timer;
17483+    };
17484+
17485+} // end namespace Catch
17486+
17487+#if !defined(CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT)
17488+#    define INTERNAL_CATCH_SECTION( ... )                                 \
17489+        CATCH_INTERNAL_START_WARNINGS_SUPPRESSION                         \
17490+        CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS                  \
17491+        if ( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME(            \
17492+                 catch_internal_Section ) =                               \
17493+                 Catch::Section( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) \
17494+        CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
17495+
17496+#    define INTERNAL_CATCH_DYNAMIC_SECTION( ... )                     \
17497+        CATCH_INTERNAL_START_WARNINGS_SUPPRESSION                     \
17498+        CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS              \
17499+        if ( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME(        \
17500+                 catch_internal_Section ) =                           \
17501+                 Catch::SectionInfo(                                  \
17502+                     CATCH_INTERNAL_LINEINFO,                         \
17503+                     ( Catch::ReusableStringStream() << __VA_ARGS__ ) \
17504+                         .str() ) )                                   \
17505+        CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
17506+
17507+#else
17508+
17509+// These section definitions imply that at most one section at one level
17510+// will be intered (because only one section's __LINE__ can be equal to
17511+// the dummy `catchInternalSectionHint` variable from `TEST_CASE`).
17512+
17513+namespace Catch {
17514+    namespace Detail {
17515+        // Intentionally without linkage, as it should only be used as a dummy
17516+        // symbol for static analysis.
17517+        // The arguments are used as a dummy for checking warnings in the passed
17518+        // expressions.
17519+        int GetNewSectionHint( StringRef, const char* const = nullptr );
17520+    } // namespace Detail
17521+} // namespace Catch
17522+
17523+
17524+#    define INTERNAL_CATCH_SECTION( ... )                                   \
17525+        CATCH_INTERNAL_START_WARNINGS_SUPPRESSION                           \
17526+        CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS                    \
17527+        CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS                             \
17528+        if ( [[maybe_unused]] const int catchInternalPreviousSectionHint =  \
17529+                 catchInternalSectionHint,                                  \
17530+             catchInternalSectionHint =                                     \
17531+                 Catch::Detail::GetNewSectionHint(__VA_ARGS__);             \
17532+             catchInternalPreviousSectionHint == __LINE__ )                 \
17533+        CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
17534+
17535+#    define INTERNAL_CATCH_DYNAMIC_SECTION( ... )                           \
17536+        CATCH_INTERNAL_START_WARNINGS_SUPPRESSION                           \
17537+        CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS                    \
17538+        CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS                             \
17539+        if ( [[maybe_unused]] const int catchInternalPreviousSectionHint =  \
17540+                 catchInternalSectionHint,                                  \
17541+             catchInternalSectionHint = Catch::Detail::GetNewSectionHint(   \
17542+                ( Catch::ReusableStringStream() << __VA_ARGS__ ).str());    \
17543+             catchInternalPreviousSectionHint == __LINE__ )                 \
17544+        CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
17545+
17546+#endif
17547+
17548+
17549+#endif // CATCH_SECTION_HPP_INCLUDED
17550+
17551+
17552+#ifndef CATCH_TEST_REGISTRY_HPP_INCLUDED
17553+#define CATCH_TEST_REGISTRY_HPP_INCLUDED
17554+
17555+
17556+
17557+#ifndef CATCH_INTERFACES_TEST_INVOKER_HPP_INCLUDED
17558+#define CATCH_INTERFACES_TEST_INVOKER_HPP_INCLUDED
17559+
17560+namespace Catch {
17561+
17562+    class ITestInvoker {
17563+    public:
17564+        virtual void invoke() const = 0;
17565+        virtual ~ITestInvoker(); // = default
17566+    };
17567+
17568+} // namespace Catch
17569+
17570+#endif // CATCH_INTERFACES_TEST_INVOKER_HPP_INCLUDED
17571+
17572+
17573+#ifndef CATCH_PREPROCESSOR_REMOVE_PARENS_HPP_INCLUDED
17574+#define CATCH_PREPROCESSOR_REMOVE_PARENS_HPP_INCLUDED
17575+
17576+#define INTERNAL_CATCH_EXPAND1( param ) INTERNAL_CATCH_EXPAND2( param )
17577+#define INTERNAL_CATCH_EXPAND2( ... ) INTERNAL_CATCH_NO##__VA_ARGS__
17578+#define INTERNAL_CATCH_DEF( ... ) INTERNAL_CATCH_DEF __VA_ARGS__
17579+#define INTERNAL_CATCH_NOINTERNAL_CATCH_DEF
17580+
17581+#define INTERNAL_CATCH_REMOVE_PARENS( ... ) \
17582+    INTERNAL_CATCH_EXPAND1( INTERNAL_CATCH_DEF __VA_ARGS__ )
17583+
17584+#endif // CATCH_PREPROCESSOR_REMOVE_PARENS_HPP_INCLUDED
17585+
17586+// GCC 5 and older do not properly handle disabling unused-variable warning
17587+// with a _Pragma. This means that we have to leak the suppression to the
17588+// user code as well :-(
17589+#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ <= 5
17590+#pragma GCC diagnostic ignored "-Wunused-variable"
17591+#endif
17592+
17593+
17594+
17595+namespace Catch {
17596+
17597+template<typename C>
17598+class TestInvokerAsMethod : public ITestInvoker {
17599+    void (C::*m_testAsMethod)();
17600+public:
17601+    TestInvokerAsMethod( void (C::*testAsMethod)() ) noexcept : m_testAsMethod( testAsMethod ) {}
17602+
17603+    void invoke() const override {
17604+        C obj;
17605+        (obj.*m_testAsMethod)();
17606+    }
17607+};
17608+
17609+Detail::unique_ptr<ITestInvoker> makeTestInvoker( void(*testAsFunction)() );
17610+
17611+template<typename C>
17612+Detail::unique_ptr<ITestInvoker> makeTestInvoker( void (C::*testAsMethod)() ) {
17613+    return Detail::make_unique<TestInvokerAsMethod<C>>( testAsMethod );
17614+}
17615+
17616+struct NameAndTags {
17617+    constexpr NameAndTags( StringRef name_ = StringRef(),
17618+                           StringRef tags_ = StringRef() ) noexcept:
17619+        name( name_ ), tags( tags_ ) {}
17620+    StringRef name;
17621+    StringRef tags;
17622+};
17623+
17624+struct AutoReg : Detail::NonCopyable {
17625+    AutoReg( Detail::unique_ptr<ITestInvoker> invoker, SourceLineInfo const& lineInfo, StringRef classOrMethod, NameAndTags const& nameAndTags ) noexcept;
17626+};
17627+
17628+} // end namespace Catch
17629+
17630+#if defined(CATCH_CONFIG_DISABLE)
17631+    #define INTERNAL_CATCH_TESTCASE_NO_REGISTRATION( TestName, ... ) \
17632+        static inline void TestName()
17633+    #define INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION( TestName, ClassName, ... ) \
17634+        namespace{                        \
17635+            struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName) { \
17636+                void test();              \
17637+            };                            \
17638+        }                                 \
17639+        void TestName::test()
17640+#endif
17641+
17642+
17643+#if !defined(CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT)
17644+
17645+    ///////////////////////////////////////////////////////////////////////////////
17646+    #define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \
17647+        static void TestName(); \
17648+        CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
17649+        CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
17650+        CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
17651+        namespace{ const Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &TestName ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \
17652+        CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
17653+        static void TestName()
17654+    #define INTERNAL_CATCH_TESTCASE( ... ) \
17655+        INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ), __VA_ARGS__ )
17656+
17657+#else  // ^^ !CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT | vv CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT
17658+
17659+
17660+// Dummy registrator for the dumy test case macros
17661+namespace Catch {
17662+    namespace Detail {
17663+        struct DummyUse {
17664+            DummyUse( void ( * )( int ), Catch::NameAndTags const& );
17665+        };
17666+    } // namespace Detail
17667+} // namespace Catch
17668+
17669+// Note that both the presence of the argument and its exact name are
17670+// necessary for the section support.
17671+
17672+// We provide a shadowed variable so that a `SECTION` inside non-`TEST_CASE`
17673+// tests can compile. The redefined `TEST_CASE` shadows this with param.
17674+static int catchInternalSectionHint = 0;
17675+
17676+#    define INTERNAL_CATCH_TESTCASE2( fname, ... )                         \
17677+        static void fname( int );                                          \
17678+        CATCH_INTERNAL_START_WARNINGS_SUPPRESSION                          \
17679+        CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS                           \
17680+        CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS                   \
17681+        static const Catch::Detail::DummyUse INTERNAL_CATCH_UNIQUE_NAME(   \
17682+            dummyUser )( &(fname), Catch::NameAndTags{ __VA_ARGS__ } );    \
17683+        CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS                            \
17684+        static void fname( [[maybe_unused]] int catchInternalSectionHint ) \
17685+            CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
17686+#    define INTERNAL_CATCH_TESTCASE( ... ) \
17687+        INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( dummyFunction ), __VA_ARGS__ )
17688+
17689+
17690+#endif // CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT
17691+
17692+    ///////////////////////////////////////////////////////////////////////////////
17693+    #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\
17694+        CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
17695+        CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
17696+        CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
17697+        namespace{ \
17698+            struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName) { \
17699+                void test(); \
17700+            }; \
17701+            const Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( \
17702+            Catch::makeTestInvoker( &TestName::test ),                    \
17703+            CATCH_INTERNAL_LINEINFO,                                      \
17704+            #ClassName##_catch_sr,                                        \
17705+            Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \
17706+        } \
17707+        CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
17708+        void TestName::test()
17709+    #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \
17710+        INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ), ClassName, __VA_ARGS__ )
17711+
17712+
17713+    ///////////////////////////////////////////////////////////////////////////////
17714+    #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \
17715+        CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
17716+        CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
17717+        CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
17718+        namespace {                                                           \
17719+        const Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( \
17720+            Catch::makeTestInvoker( &QualifiedMethod ),                   \
17721+            CATCH_INTERNAL_LINEINFO,                                      \
17722+            "&" #QualifiedMethod##_catch_sr,                              \
17723+            Catch::NameAndTags{ __VA_ARGS__ } );                          \
17724+    } /* NOLINT */ \
17725+        CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
17726+
17727+
17728+    ///////////////////////////////////////////////////////////////////////////////
17729+    #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \
17730+        do { \
17731+            CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
17732+            CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
17733+            CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
17734+            Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( Function ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \
17735+            CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
17736+        } while(false)
17737+
17738+
17739+#endif // CATCH_TEST_REGISTRY_HPP_INCLUDED
17740+
17741+
17742+// All of our user-facing macros support configuration toggle, that
17743+// forces them to be defined prefixed with CATCH_. We also like to
17744+// support another toggle that can minimize (disable) their implementation.
17745+// Given this, we have 4 different configuration options below
17746+
17747+#if defined(CATCH_CONFIG_PREFIX_ALL) && !defined(CATCH_CONFIG_DISABLE)
17748+
17749+  #define CATCH_REQUIRE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ )
17750+  #define CATCH_REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ )
17751+
17752+  #define CATCH_REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS", Catch::ResultDisposition::Normal, __VA_ARGS__ )
17753+  #define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr )
17754+  #define CATCH_REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ )
17755+
17756+  #define CATCH_CHECK( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
17757+  #define CATCH_CHECK_FALSE( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, __VA_ARGS__ )
17758+  #define CATCH_CHECKED_IF( ... ) INTERNAL_CATCH_IF( "CATCH_CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ )
17759+  #define CATCH_CHECKED_ELSE( ... ) INTERNAL_CATCH_ELSE( "CATCH_CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ )
17760+  #define CATCH_CHECK_NOFAIL( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ )
17761+
17762+  #define CATCH_CHECK_THROWS( ... )  INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
17763+  #define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr )
17764+  #define CATCH_CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
17765+
17766+  #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
17767+  #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
17768+  #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
17769+  #define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
17770+  #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
17771+  #define CATCH_DYNAMIC_SECTION( ... ) INTERNAL_CATCH_DYNAMIC_SECTION( __VA_ARGS__ )
17772+  #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ )
17773+  #define CATCH_FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
17774+  #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( "CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
17775+  #define CATCH_SKIP( ... ) INTERNAL_CATCH_MSG( "SKIP", Catch::ResultWas::ExplicitSkip, Catch::ResultDisposition::Normal, __VA_ARGS__ )
17776+
17777+
17778+  #if !defined(CATCH_CONFIG_RUNTIME_STATIC_REQUIRE)
17779+    #define CATCH_STATIC_REQUIRE( ... )       static_assert(   __VA_ARGS__ ,      #__VA_ARGS__ );     CATCH_SUCCEED( #__VA_ARGS__ )
17780+    #define CATCH_STATIC_REQUIRE_FALSE( ... ) static_assert( !(__VA_ARGS__), "!(" #__VA_ARGS__ ")" ); CATCH_SUCCEED( #__VA_ARGS__ )
17781+    #define CATCH_STATIC_CHECK( ... )       static_assert(   __VA_ARGS__ ,      #__VA_ARGS__ );     CATCH_SUCCEED( #__VA_ARGS__ )
17782+    #define CATCH_STATIC_CHECK_FALSE( ... ) static_assert( !(__VA_ARGS__), "!(" #__VA_ARGS__ ")" ); CATCH_SUCCEED( #__VA_ARGS__ )
17783+  #else
17784+    #define CATCH_STATIC_REQUIRE( ... )       CATCH_REQUIRE( __VA_ARGS__ )
17785+    #define CATCH_STATIC_REQUIRE_FALSE( ... ) CATCH_REQUIRE_FALSE( __VA_ARGS__ )
17786+    #define CATCH_STATIC_CHECK( ... )       CATCH_CHECK( __VA_ARGS__ )
17787+    #define CATCH_STATIC_CHECK_FALSE( ... ) CATCH_CHECK_FALSE( __VA_ARGS__ )
17788+  #endif
17789+
17790+
17791+  // "BDD-style" convenience wrappers
17792+  #define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ )
17793+  #define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
17794+  #define CATCH_GIVEN( desc )     INTERNAL_CATCH_DYNAMIC_SECTION( "    Given: " << desc )
17795+  #define CATCH_AND_GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( "And given: " << desc )
17796+  #define CATCH_WHEN( desc )      INTERNAL_CATCH_DYNAMIC_SECTION( "     When: " << desc )
17797+  #define CATCH_AND_WHEN( desc )  INTERNAL_CATCH_DYNAMIC_SECTION( " And when: " << desc )
17798+  #define CATCH_THEN( desc )      INTERNAL_CATCH_DYNAMIC_SECTION( "     Then: " << desc )
17799+  #define CATCH_AND_THEN( desc )  INTERNAL_CATCH_DYNAMIC_SECTION( "      And: " << desc )
17800+
17801+#elif defined(CATCH_CONFIG_PREFIX_ALL) && defined(CATCH_CONFIG_DISABLE) // ^^ prefixed, implemented | vv prefixed, disabled
17802+
17803+  #define CATCH_REQUIRE( ... )        (void)(0)
17804+  #define CATCH_REQUIRE_FALSE( ... )  (void)(0)
17805+
17806+  #define CATCH_REQUIRE_THROWS( ... ) (void)(0)
17807+  #define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) (void)(0)
17808+  #define CATCH_REQUIRE_NOTHROW( ... ) (void)(0)
17809+
17810+  #define CATCH_CHECK( ... )         (void)(0)
17811+  #define CATCH_CHECK_FALSE( ... )   (void)(0)
17812+  #define CATCH_CHECKED_IF( ... )    if (__VA_ARGS__)
17813+  #define CATCH_CHECKED_ELSE( ... )  if (!(__VA_ARGS__))
17814+  #define CATCH_CHECK_NOFAIL( ... )  (void)(0)
17815+
17816+  #define CATCH_CHECK_THROWS( ... )  (void)(0)
17817+  #define CATCH_CHECK_THROWS_AS( expr, exceptionType ) (void)(0)
17818+  #define CATCH_CHECK_NOTHROW( ... ) (void)(0)
17819+
17820+  #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ))
17821+  #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ))
17822+  #define CATCH_METHOD_AS_TEST_CASE( method, ... )
17823+  #define CATCH_REGISTER_TEST_CASE( Function, ... ) (void)(0)
17824+  #define CATCH_SECTION( ... )
17825+  #define CATCH_DYNAMIC_SECTION( ... )
17826+  #define CATCH_FAIL( ... ) (void)(0)
17827+  #define CATCH_FAIL_CHECK( ... ) (void)(0)
17828+  #define CATCH_SUCCEED( ... ) (void)(0)
17829+  #define CATCH_SKIP( ... ) (void)(0)
17830+
17831+  #define CATCH_STATIC_REQUIRE( ... )       (void)(0)
17832+  #define CATCH_STATIC_REQUIRE_FALSE( ... ) (void)(0)
17833+  #define CATCH_STATIC_CHECK( ... )       (void)(0)
17834+  #define CATCH_STATIC_CHECK_FALSE( ... ) (void)(0)
17835+
17836+  // "BDD-style" convenience wrappers
17837+  #define CATCH_SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ))
17838+  #define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ), className )
17839+  #define CATCH_GIVEN( desc )
17840+  #define CATCH_AND_GIVEN( desc )
17841+  #define CATCH_WHEN( desc )
17842+  #define CATCH_AND_WHEN( desc )
17843+  #define CATCH_THEN( desc )
17844+  #define CATCH_AND_THEN( desc )
17845+
17846+#elif !defined(CATCH_CONFIG_PREFIX_ALL) && !defined(CATCH_CONFIG_DISABLE) // ^^ prefixed, disabled | vv unprefixed, implemented
17847+
17848+  #define REQUIRE( ... ) INTERNAL_CATCH_TEST( "REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__  )
17849+  #define REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST( "REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ )
17850+
17851+  #define REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "REQUIRE_THROWS", Catch::ResultDisposition::Normal, __VA_ARGS__ )
17852+  #define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr )
17853+  #define REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ )
17854+
17855+  #define CHECK( ... ) INTERNAL_CATCH_TEST( "CHECK", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
17856+  #define CHECK_FALSE( ... ) INTERNAL_CATCH_TEST( "CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, __VA_ARGS__ )
17857+  #define CHECKED_IF( ... ) INTERNAL_CATCH_IF( "CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ )
17858+  #define CHECKED_ELSE( ... ) INTERNAL_CATCH_ELSE( "CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ )
17859+  #define CHECK_NOFAIL( ... ) INTERNAL_CATCH_TEST( "CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ )
17860+
17861+  #define CHECK_THROWS( ... )  INTERNAL_CATCH_THROWS( "CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
17862+  #define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr )
17863+  #define CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
17864+
17865+  #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
17866+  #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
17867+  #define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
17868+  #define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
17869+  #define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
17870+  #define DYNAMIC_SECTION( ... ) INTERNAL_CATCH_DYNAMIC_SECTION( __VA_ARGS__ )
17871+  #define FAIL( ... ) INTERNAL_CATCH_MSG( "FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ )
17872+  #define FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
17873+  #define SUCCEED( ... ) INTERNAL_CATCH_MSG( "SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
17874+  #define SKIP( ... ) INTERNAL_CATCH_MSG( "SKIP", Catch::ResultWas::ExplicitSkip, Catch::ResultDisposition::Normal, __VA_ARGS__ )
17875+
17876+
17877+  #if !defined(CATCH_CONFIG_RUNTIME_STATIC_REQUIRE)
17878+    #define STATIC_REQUIRE( ... )       static_assert(   __VA_ARGS__,  #__VA_ARGS__ ); SUCCEED( #__VA_ARGS__ )
17879+    #define STATIC_REQUIRE_FALSE( ... ) static_assert( !(__VA_ARGS__), "!(" #__VA_ARGS__ ")" ); SUCCEED( "!(" #__VA_ARGS__ ")" )
17880+    #define STATIC_CHECK( ... )       static_assert(   __VA_ARGS__,  #__VA_ARGS__ ); SUCCEED( #__VA_ARGS__ )
17881+    #define STATIC_CHECK_FALSE( ... ) static_assert( !(__VA_ARGS__), "!(" #__VA_ARGS__ ")" ); SUCCEED( "!(" #__VA_ARGS__ ")" )
17882+  #else
17883+    #define STATIC_REQUIRE( ... )       REQUIRE( __VA_ARGS__ )
17884+    #define STATIC_REQUIRE_FALSE( ... ) REQUIRE_FALSE( __VA_ARGS__ )
17885+    #define STATIC_CHECK( ... )       CHECK( __VA_ARGS__ )
17886+    #define STATIC_CHECK_FALSE( ... ) CHECK_FALSE( __VA_ARGS__ )
17887+  #endif
17888+
17889+  // "BDD-style" convenience wrappers
17890+  #define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ )
17891+  #define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
17892+  #define GIVEN( desc )     INTERNAL_CATCH_DYNAMIC_SECTION( "    Given: " << desc )
17893+  #define AND_GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( "And given: " << desc )
17894+  #define WHEN( desc )      INTERNAL_CATCH_DYNAMIC_SECTION( "     When: " << desc )
17895+  #define AND_WHEN( desc )  INTERNAL_CATCH_DYNAMIC_SECTION( " And when: " << desc )
17896+  #define THEN( desc )      INTERNAL_CATCH_DYNAMIC_SECTION( "     Then: " << desc )
17897+  #define AND_THEN( desc )  INTERNAL_CATCH_DYNAMIC_SECTION( "      And: " << desc )
17898+
17899+#elif !defined(CATCH_CONFIG_PREFIX_ALL) && defined(CATCH_CONFIG_DISABLE) // ^^ unprefixed, implemented | vv unprefixed, disabled
17900+
17901+  #define REQUIRE( ... )       (void)(0)
17902+  #define REQUIRE_FALSE( ... ) (void)(0)
17903+
17904+  #define REQUIRE_THROWS( ... ) (void)(0)
17905+  #define REQUIRE_THROWS_AS( expr, exceptionType ) (void)(0)
17906+  #define REQUIRE_NOTHROW( ... ) (void)(0)
17907+
17908+  #define CHECK( ... ) (void)(0)
17909+  #define CHECK_FALSE( ... ) (void)(0)
17910+  #define CHECKED_IF( ... ) if (__VA_ARGS__)
17911+  #define CHECKED_ELSE( ... ) if (!(__VA_ARGS__))
17912+  #define CHECK_NOFAIL( ... ) (void)(0)
17913+
17914+  #define CHECK_THROWS( ... )  (void)(0)
17915+  #define CHECK_THROWS_AS( expr, exceptionType ) (void)(0)
17916+  #define CHECK_NOTHROW( ... ) (void)(0)
17917+
17918+  #define TEST_CASE( ... )  INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ), __VA_ARGS__)
17919+  #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ))
17920+  #define METHOD_AS_TEST_CASE( method, ... )
17921+  #define REGISTER_TEST_CASE( Function, ... ) (void)(0)
17922+  #define SECTION( ... )
17923+  #define DYNAMIC_SECTION( ... )
17924+  #define FAIL( ... ) (void)(0)
17925+  #define FAIL_CHECK( ... ) (void)(0)
17926+  #define SUCCEED( ... ) (void)(0)
17927+  #define SKIP( ... ) (void)(0)
17928+
17929+  #define STATIC_REQUIRE( ... )       (void)(0)
17930+  #define STATIC_REQUIRE_FALSE( ... ) (void)(0)
17931+  #define STATIC_CHECK( ... )       (void)(0)
17932+  #define STATIC_CHECK_FALSE( ... ) (void)(0)
17933+
17934+  // "BDD-style" convenience wrappers
17935+  #define SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ) )
17936+  #define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ), className )
17937+
17938+  #define GIVEN( desc )
17939+  #define AND_GIVEN( desc )
17940+  #define WHEN( desc )
17941+  #define AND_WHEN( desc )
17942+  #define THEN( desc )
17943+  #define AND_THEN( desc )
17944+
17945+#endif // ^^ unprefixed, disabled
17946+
17947+// end of user facing macros
17948+
17949+#endif // CATCH_TEST_MACROS_HPP_INCLUDED
17950+
17951+
17952+#ifndef CATCH_TEMPLATE_TEST_REGISTRY_HPP_INCLUDED
17953+#define CATCH_TEMPLATE_TEST_REGISTRY_HPP_INCLUDED
17954+
17955+
17956+
17957+#ifndef CATCH_PREPROCESSOR_HPP_INCLUDED
17958+#define CATCH_PREPROCESSOR_HPP_INCLUDED
17959+
17960+
17961+#if defined(__GNUC__)
17962+// We need to silence "empty __VA_ARGS__ warning", and using just _Pragma does not work
17963+#pragma GCC system_header
17964+#endif
17965+
17966+
17967+#define CATCH_RECURSION_LEVEL0(...) __VA_ARGS__
17968+#define CATCH_RECURSION_LEVEL1(...) CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(__VA_ARGS__)))
17969+#define CATCH_RECURSION_LEVEL2(...) CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(__VA_ARGS__)))
17970+#define CATCH_RECURSION_LEVEL3(...) CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(__VA_ARGS__)))
17971+#define CATCH_RECURSION_LEVEL4(...) CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(__VA_ARGS__)))
17972+#define CATCH_RECURSION_LEVEL5(...) CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(__VA_ARGS__)))
17973+
17974+#ifdef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
17975+#define INTERNAL_CATCH_EXPAND_VARGS(...) __VA_ARGS__
17976+// MSVC needs more evaluations
17977+#define CATCH_RECURSION_LEVEL6(...) CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(__VA_ARGS__)))
17978+#define CATCH_RECURSE(...)  CATCH_RECURSION_LEVEL6(CATCH_RECURSION_LEVEL6(__VA_ARGS__))
17979+#else
17980+#define CATCH_RECURSE(...)  CATCH_RECURSION_LEVEL5(__VA_ARGS__)
17981+#endif
17982+
17983+#define CATCH_REC_END(...)
17984+#define CATCH_REC_OUT
17985+
17986+#define CATCH_EMPTY()
17987+#define CATCH_DEFER(id) id CATCH_EMPTY()
17988+
17989+#define CATCH_REC_GET_END2() 0, CATCH_REC_END
17990+#define CATCH_REC_GET_END1(...) CATCH_REC_GET_END2
17991+#define CATCH_REC_GET_END(...) CATCH_REC_GET_END1
17992+#define CATCH_REC_NEXT0(test, next, ...) next CATCH_REC_OUT
17993+#define CATCH_REC_NEXT1(test, next) CATCH_DEFER ( CATCH_REC_NEXT0 ) ( test, next, 0)
17994+#define CATCH_REC_NEXT(test, next)  CATCH_REC_NEXT1(CATCH_REC_GET_END test, next)
17995+
17996+#define CATCH_REC_LIST0(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ )
17997+#define CATCH_REC_LIST1(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST0) ) ( f, peek, __VA_ARGS__ )
17998+#define CATCH_REC_LIST2(f, x, peek, ...)   f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ )
17999+
18000+#define CATCH_REC_LIST0_UD(f, userdata, x, peek, ...) , f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1_UD) ) ( f, userdata, peek, __VA_ARGS__ )
18001+#define CATCH_REC_LIST1_UD(f, userdata, x, peek, ...) , f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST0_UD) ) ( f, userdata, peek, __VA_ARGS__ )
18002+#define CATCH_REC_LIST2_UD(f, userdata, x, peek, ...)   f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1_UD) ) ( f, userdata, peek, __VA_ARGS__ )
18003+
18004+// Applies the function macro `f` to each of the remaining parameters, inserts commas between the results,
18005+// and passes userdata as the first parameter to each invocation,
18006+// e.g. CATCH_REC_LIST_UD(f, x, a, b, c) evaluates to f(x, a), f(x, b), f(x, c)
18007+#define CATCH_REC_LIST_UD(f, userdata, ...) CATCH_RECURSE(CATCH_REC_LIST2_UD(f, userdata, __VA_ARGS__, ()()(), ()()(), ()()(), 0))
18008+
18009+#define CATCH_REC_LIST(f, ...) CATCH_RECURSE(CATCH_REC_LIST2(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0))
18010+
18011+#define INTERNAL_CATCH_STRINGIZE(...) INTERNAL_CATCH_STRINGIZE2(__VA_ARGS__)
18012+#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
18013+#define INTERNAL_CATCH_STRINGIZE2(...) #__VA_ARGS__
18014+#define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param))
18015+#else
18016+// MSVC is adding extra space and needs another indirection to expand INTERNAL_CATCH_NOINTERNAL_CATCH_DEF
18017+#define INTERNAL_CATCH_STRINGIZE2(...) INTERNAL_CATCH_STRINGIZE3(__VA_ARGS__)
18018+#define INTERNAL_CATCH_STRINGIZE3(...) #__VA_ARGS__
18019+#define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) (INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param)) + 1)
18020+#endif
18021+
18022+#define INTERNAL_CATCH_MAKE_NAMESPACE2(...) ns_##__VA_ARGS__
18023+#define INTERNAL_CATCH_MAKE_NAMESPACE(name) INTERNAL_CATCH_MAKE_NAMESPACE2(name)
18024+
18025+#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
18026+#define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) decltype(get_wrapper<INTERNAL_CATCH_REMOVE_PARENS_GEN(__VA_ARGS__)>())
18027+#define INTERNAL_CATCH_MAKE_TYPE_LIST(...) INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__))
18028+#else
18029+#define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) INTERNAL_CATCH_EXPAND_VARGS(decltype(get_wrapper<INTERNAL_CATCH_REMOVE_PARENS_GEN(__VA_ARGS__)>()))
18030+#define INTERNAL_CATCH_MAKE_TYPE_LIST(...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__)))
18031+#endif
18032+
18033+#define INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(...)\
18034+    CATCH_REC_LIST(INTERNAL_CATCH_MAKE_TYPE_LIST,__VA_ARGS__)
18035+
18036+#define INTERNAL_CATCH_REMOVE_PARENS_1_ARG(_0) INTERNAL_CATCH_REMOVE_PARENS(_0)
18037+#define INTERNAL_CATCH_REMOVE_PARENS_2_ARG(_0, _1) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_1_ARG(_1)
18038+#define INTERNAL_CATCH_REMOVE_PARENS_3_ARG(_0, _1, _2) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_2_ARG(_1, _2)
18039+#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)
18040+#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)
18041+#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)
18042+#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)
18043+#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)
18044+#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)
18045+#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)
18046+#define INTERNAL_CATCH_REMOVE_PARENS_11_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_10_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10)
18047+
18048+#define INTERNAL_CATCH_VA_NARGS_IMPL(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N
18049+
18050+#define INTERNAL_CATCH_TYPE_GEN\
18051+    template<typename...> struct TypeList {};\
18052+    template<typename...Ts>\
18053+    constexpr auto get_wrapper() noexcept -> TypeList<Ts...> { return {}; }\
18054+    template<template<typename...> class...> struct TemplateTypeList{};\
18055+    template<template<typename...> class...Cs>\
18056+    constexpr auto get_wrapper() noexcept -> TemplateTypeList<Cs...> { return {}; }\
18057+    template<typename...>\
18058+    struct append;\
18059+    template<typename...>\
18060+    struct rewrap;\
18061+    template<template<typename...> class, typename...>\
18062+    struct create;\
18063+    template<template<typename...> class, typename>\
18064+    struct convert;\
18065+    \
18066+    template<typename T> \
18067+    struct append<T> { using type = T; };\
18068+    template< template<typename...> class L1, typename...E1, template<typename...> class L2, typename...E2, typename...Rest>\
18069+    struct append<L1<E1...>, L2<E2...>, Rest...> { using type = typename append<L1<E1...,E2...>, Rest...>::type; };\
18070+    template< template<typename...> class L1, typename...E1, typename...Rest>\
18071+    struct append<L1<E1...>, TypeList<mpl_::na>, Rest...> { using type = L1<E1...>; };\
18072+    \
18073+    template< template<typename...> class Container, template<typename...> class List, typename...elems>\
18074+    struct rewrap<TemplateTypeList<Container>, List<elems...>> { using type = TypeList<Container<elems...>>; };\
18075+    template< template<typename...> class Container, template<typename...> class List, class...Elems, typename...Elements>\
18076+    struct rewrap<TemplateTypeList<Container>, List<Elems...>, Elements...> { using type = typename append<TypeList<Container<Elems...>>, typename rewrap<TemplateTypeList<Container>, Elements...>::type>::type; };\
18077+    \
18078+    template<template <typename...> class Final, template< typename...> class...Containers, typename...Types>\
18079+    struct create<Final, TemplateTypeList<Containers...>, TypeList<Types...>> { using type = typename append<Final<>, typename rewrap<TemplateTypeList<Containers>, Types...>::type...>::type; };\
18080+    template<template <typename...> class Final, template <typename...> class List, typename...Ts>\
18081+    struct convert<Final, List<Ts...>> { using type = typename append<Final<>,TypeList<Ts>...>::type; };
18082+
18083+#define INTERNAL_CATCH_NTTP_1(signature, ...)\
18084+    template<INTERNAL_CATCH_REMOVE_PARENS(signature)> struct Nttp{};\
18085+    template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\
18086+    constexpr auto get_wrapper() noexcept -> Nttp<__VA_ARGS__> { return {}; } \
18087+    template<template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class...> struct NttpTemplateTypeList{};\
18088+    template<template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class...Cs>\
18089+    constexpr auto get_wrapper() noexcept -> NttpTemplateTypeList<Cs...> { return {}; } \
18090+    \
18091+    template< template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class Container, template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class List, INTERNAL_CATCH_REMOVE_PARENS(signature)>\
18092+    struct rewrap<NttpTemplateTypeList<Container>, List<__VA_ARGS__>> { using type = TypeList<Container<__VA_ARGS__>>; };\
18093+    template< template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class Container, template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class List, INTERNAL_CATCH_REMOVE_PARENS(signature), typename...Elements>\
18094+    struct rewrap<NttpTemplateTypeList<Container>, List<__VA_ARGS__>, Elements...> { using type = typename append<TypeList<Container<__VA_ARGS__>>, typename rewrap<NttpTemplateTypeList<Container>, Elements...>::type>::type; };\
18095+    template<template <typename...> class Final, template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class...Containers, typename...Types>\
18096+    struct create<Final, NttpTemplateTypeList<Containers...>, TypeList<Types...>> { using type = typename append<Final<>, typename rewrap<NttpTemplateTypeList<Containers>, Types...>::type...>::type; };
18097+
18098+#define INTERNAL_CATCH_DECLARE_SIG_TEST0(TestName)
18099+#define INTERNAL_CATCH_DECLARE_SIG_TEST1(TestName, signature)\
18100+    template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\
18101+    static void TestName()
18102+#define INTERNAL_CATCH_DECLARE_SIG_TEST_X(TestName, signature, ...)\
18103+    template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\
18104+    static void TestName()
18105+
18106+#define INTERNAL_CATCH_DEFINE_SIG_TEST0(TestName)
18107+#define INTERNAL_CATCH_DEFINE_SIG_TEST1(TestName, signature)\
18108+    template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\
18109+    static void TestName()
18110+#define INTERNAL_CATCH_DEFINE_SIG_TEST_X(TestName, signature,...)\
18111+    template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\
18112+    static void TestName()
18113+
18114+#define INTERNAL_CATCH_NTTP_REGISTER0(TestFunc, signature)\
18115+    template<typename Type>\
18116+    void reg_test(TypeList<Type>, Catch::NameAndTags nameAndTags)\
18117+    {\
18118+        Catch::AutoReg( Catch::makeTestInvoker(&TestFunc<Type>), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), nameAndTags);\
18119+    }
18120+
18121+#define INTERNAL_CATCH_NTTP_REGISTER(TestFunc, signature, ...)\
18122+    template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\
18123+    void reg_test(Nttp<__VA_ARGS__>, Catch::NameAndTags nameAndTags)\
18124+    {\
18125+        Catch::AutoReg( Catch::makeTestInvoker(&TestFunc<__VA_ARGS__>), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), nameAndTags);\
18126+    }
18127+
18128+#define INTERNAL_CATCH_NTTP_REGISTER_METHOD0(TestName, signature, ...)\
18129+    template<typename Type>\
18130+    void reg_test(TypeList<Type>, Catch::StringRef className, Catch::NameAndTags nameAndTags)\
18131+    {\
18132+        Catch::AutoReg( Catch::makeTestInvoker(&TestName<Type>::test), CATCH_INTERNAL_LINEINFO, className, nameAndTags);\
18133+    }
18134+
18135+#define INTERNAL_CATCH_NTTP_REGISTER_METHOD(TestName, signature, ...)\
18136+    template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\
18137+    void reg_test(Nttp<__VA_ARGS__>, Catch::StringRef className, Catch::NameAndTags nameAndTags)\
18138+    {\
18139+        Catch::AutoReg( Catch::makeTestInvoker(&TestName<__VA_ARGS__>::test), CATCH_INTERNAL_LINEINFO, className, nameAndTags);\
18140+    }
18141+
18142+#define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD0(TestName, ClassName)
18143+#define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD1(TestName, ClassName, signature)\
18144+    template<typename TestType> \
18145+    struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName)<TestType> { \
18146+        void test();\
18147+    }
18148+
18149+#define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X(TestName, ClassName, signature, ...)\
18150+    template<INTERNAL_CATCH_REMOVE_PARENS(signature)> \
18151+    struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName)<__VA_ARGS__> { \
18152+        void test();\
18153+    }
18154+
18155+#define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD0(TestName)
18156+#define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD1(TestName, signature)\
18157+    template<typename TestType> \
18158+    void INTERNAL_CATCH_MAKE_NAMESPACE(TestName)::TestName<TestType>::test()
18159+#define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X(TestName, signature, ...)\
18160+    template<INTERNAL_CATCH_REMOVE_PARENS(signature)> \
18161+    void INTERNAL_CATCH_MAKE_NAMESPACE(TestName)::TestName<__VA_ARGS__>::test()
18162+
18163+#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
18164+#define INTERNAL_CATCH_NTTP_0
18165+#define INTERNAL_CATCH_NTTP_GEN(...) INTERNAL_CATCH_VA_NARGS_IMPL(__VA_ARGS__, INTERNAL_CATCH_NTTP_1(__VA_ARGS__), INTERNAL_CATCH_NTTP_1(__VA_ARGS__), INTERNAL_CATCH_NTTP_1(__VA_ARGS__), INTERNAL_CATCH_NTTP_1(__VA_ARGS__), INTERNAL_CATCH_NTTP_1(__VA_ARGS__), INTERNAL_CATCH_NTTP_1( __VA_ARGS__), INTERNAL_CATCH_NTTP_1( __VA_ARGS__), INTERNAL_CATCH_NTTP_1( __VA_ARGS__), INTERNAL_CATCH_NTTP_1( __VA_ARGS__),INTERNAL_CATCH_NTTP_1( __VA_ARGS__), INTERNAL_CATCH_NTTP_0)
18166+#define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD(TestName, ...) INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD1, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD0)(TestName, __VA_ARGS__)
18167+#define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD(TestName, ClassName, ...) INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD1, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD0)(TestName, ClassName, __VA_ARGS__)
18168+#define INTERNAL_CATCH_NTTP_REG_METHOD_GEN(TestName, ...) INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD0, INTERNAL_CATCH_NTTP_REGISTER_METHOD0)(TestName, __VA_ARGS__)
18169+#define INTERNAL_CATCH_NTTP_REG_GEN(TestFunc, ...) INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER0, INTERNAL_CATCH_NTTP_REGISTER0)(TestFunc, __VA_ARGS__)
18170+#define INTERNAL_CATCH_DEFINE_SIG_TEST(TestName, ...) INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X,INTERNAL_CATCH_DEFINE_SIG_TEST_X,INTERNAL_CATCH_DEFINE_SIG_TEST1, INTERNAL_CATCH_DEFINE_SIG_TEST0)(TestName, __VA_ARGS__)
18171+#define INTERNAL_CATCH_DECLARE_SIG_TEST(TestName, ...) INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DECLARE_SIG_TEST_X,INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X,INTERNAL_CATCH_DECLARE_SIG_TEST_X,INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST1, INTERNAL_CATCH_DECLARE_SIG_TEST0)(TestName, __VA_ARGS__)
18172+#define INTERNAL_CATCH_REMOVE_PARENS_GEN(...) INTERNAL_CATCH_VA_NARGS_IMPL(__VA_ARGS__, INTERNAL_CATCH_REMOVE_PARENS_11_ARG,INTERNAL_CATCH_REMOVE_PARENS_10_ARG,INTERNAL_CATCH_REMOVE_PARENS_9_ARG,INTERNAL_CATCH_REMOVE_PARENS_8_ARG,INTERNAL_CATCH_REMOVE_PARENS_7_ARG,INTERNAL_CATCH_REMOVE_PARENS_6_ARG,INTERNAL_CATCH_REMOVE_PARENS_5_ARG,INTERNAL_CATCH_REMOVE_PARENS_4_ARG,INTERNAL_CATCH_REMOVE_PARENS_3_ARG,INTERNAL_CATCH_REMOVE_PARENS_2_ARG,INTERNAL_CATCH_REMOVE_PARENS_1_ARG)(__VA_ARGS__)
18173+#else
18174+#define INTERNAL_CATCH_NTTP_0(signature)
18175+#define INTERNAL_CATCH_NTTP_GEN(...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL(__VA_ARGS__, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1,INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_0)( __VA_ARGS__))
18176+#define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD(TestName, ...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD1, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD0)(TestName, __VA_ARGS__))
18177+#define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD(TestName, ClassName, ...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD1, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD0)(TestName, ClassName, __VA_ARGS__))
18178+#define INTERNAL_CATCH_NTTP_REG_METHOD_GEN(TestName, ...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD0, INTERNAL_CATCH_NTTP_REGISTER_METHOD0)(TestName, __VA_ARGS__))
18179+#define INTERNAL_CATCH_NTTP_REG_GEN(TestFunc, ...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER0, INTERNAL_CATCH_NTTP_REGISTER0)(TestFunc, __VA_ARGS__))
18180+#define INTERNAL_CATCH_DEFINE_SIG_TEST(TestName, ...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X,INTERNAL_CATCH_DEFINE_SIG_TEST_X,INTERNAL_CATCH_DEFINE_SIG_TEST1, INTERNAL_CATCH_DEFINE_SIG_TEST0)(TestName, __VA_ARGS__))
18181+#define INTERNAL_CATCH_DECLARE_SIG_TEST(TestName, ...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DECLARE_SIG_TEST_X,INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X,INTERNAL_CATCH_DECLARE_SIG_TEST_X,INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST1, INTERNAL_CATCH_DECLARE_SIG_TEST0)(TestName, __VA_ARGS__))
18182+#define INTERNAL_CATCH_REMOVE_PARENS_GEN(...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL(__VA_ARGS__, INTERNAL_CATCH_REMOVE_PARENS_11_ARG,INTERNAL_CATCH_REMOVE_PARENS_10_ARG,INTERNAL_CATCH_REMOVE_PARENS_9_ARG,INTERNAL_CATCH_REMOVE_PARENS_8_ARG,INTERNAL_CATCH_REMOVE_PARENS_7_ARG,INTERNAL_CATCH_REMOVE_PARENS_6_ARG,INTERNAL_CATCH_REMOVE_PARENS_5_ARG,INTERNAL_CATCH_REMOVE_PARENS_4_ARG,INTERNAL_CATCH_REMOVE_PARENS_3_ARG,INTERNAL_CATCH_REMOVE_PARENS_2_ARG,INTERNAL_CATCH_REMOVE_PARENS_1_ARG)(__VA_ARGS__))
18183+#endif
18184+
18185+#endif // CATCH_PREPROCESSOR_HPP_INCLUDED
18186+
18187+
18188+// GCC 5 and older do not properly handle disabling unused-variable warning
18189+// with a _Pragma. This means that we have to leak the suppression to the
18190+// user code as well :-(
18191+#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ <= 5
18192+#pragma GCC diagnostic ignored "-Wunused-variable"
18193+#endif
18194+
18195+#if defined(CATCH_CONFIG_DISABLE)
18196+    #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( TestName, TestFunc, Name, Tags, Signature, ... )  \
18197+        INTERNAL_CATCH_DEFINE_SIG_TEST(TestFunc, INTERNAL_CATCH_REMOVE_PARENS(Signature))
18198+    #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( TestNameClass, TestName, ClassName, Name, Tags, Signature, ... )    \
18199+        namespace{                                                                                  \
18200+            namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName) {                                      \
18201+            INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD(TestName, ClassName, INTERNAL_CATCH_REMOVE_PARENS(Signature));\
18202+        }                                                                                           \
18203+        }                                                                                           \
18204+        INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD(TestName, INTERNAL_CATCH_REMOVE_PARENS(Signature))
18205+
18206+    #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
18207+        #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(Name, Tags, ...) \
18208+            INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), Name, Tags, typename TestType, __VA_ARGS__ )
18209+    #else
18210+        #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(Name, Tags, ...) \
18211+            INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), Name, Tags, typename TestType, __VA_ARGS__ ) )
18212+    #endif
18213+
18214+    #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
18215+        #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(Name, Tags, Signature, ...) \
18216+            INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), Name, Tags, Signature, __VA_ARGS__ )
18217+    #else
18218+        #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(Name, Tags, Signature, ...) \
18219+            INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), Name, Tags, Signature, __VA_ARGS__ ) )
18220+    #endif
18221+
18222+    #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
18223+        #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION( ClassName, Name, Tags,... ) \
18224+            INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_CLASS_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ )
18225+    #else
18226+        #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION( ClassName, Name, Tags,... ) \
18227+            INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_CLASS_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ ) )
18228+    #endif
18229+
18230+    #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
18231+        #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION( ClassName, Name, Tags, Signature, ... ) \
18232+            INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_CLASS_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ )
18233+    #else
18234+        #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION( ClassName, Name, Tags, Signature, ... ) \
18235+            INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_CLASS_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ ) )
18236+    #endif
18237+#endif
18238+
18239+
18240+    ///////////////////////////////////////////////////////////////////////////////
18241+    #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_2(TestName, TestFunc, Name, Tags, Signature, ... )\
18242+        CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
18243+        CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
18244+        CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
18245+        CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
18246+        CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
18247+        CATCH_INTERNAL_SUPPRESS_COMMA_WARNINGS \
18248+        INTERNAL_CATCH_DECLARE_SIG_TEST(TestFunc, INTERNAL_CATCH_REMOVE_PARENS(Signature));\
18249+        namespace {\
18250+        namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){\
18251+            INTERNAL_CATCH_TYPE_GEN\
18252+            INTERNAL_CATCH_NTTP_GEN(INTERNAL_CATCH_REMOVE_PARENS(Signature))\
18253+            INTERNAL_CATCH_NTTP_REG_GEN(TestFunc,INTERNAL_CATCH_REMOVE_PARENS(Signature))\
18254+            template<typename...Types> \
18255+            struct TestName{\
18256+                TestName(){\
18257+                    size_t index = 0;                                    \
18258+                    constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, __VA_ARGS__)}; /* NOLINT(cppcoreguidelines-avoid-c-arrays,modernize-avoid-c-arrays,hicpp-avoid-c-arrays) */\
18259+                    using expander = size_t[]; /* NOLINT(cppcoreguidelines-avoid-c-arrays,modernize-avoid-c-arrays,hicpp-avoid-c-arrays) */\
18260+                    (void)expander{(reg_test(Types{}, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index]), Tags } ), index++)... };/* NOLINT */ \
18261+                }\
18262+            };\
18263+            static const int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
18264+            TestName<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(__VA_ARGS__)>();\
18265+            return 0;\
18266+        }();\
18267+        }\
18268+        }\
18269+        CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
18270+        INTERNAL_CATCH_DEFINE_SIG_TEST(TestFunc,INTERNAL_CATCH_REMOVE_PARENS(Signature))
18271+
18272+#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
18273+    #define INTERNAL_CATCH_TEMPLATE_TEST_CASE(Name, Tags, ...) \
18274+        INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), Name, Tags, typename TestType, __VA_ARGS__ )
18275+#else
18276+    #define INTERNAL_CATCH_TEMPLATE_TEST_CASE(Name, Tags, ...) \
18277+        INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), Name, Tags, typename TestType, __VA_ARGS__ ) )
18278+#endif
18279+
18280+#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
18281+    #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG(Name, Tags, Signature, ...) \
18282+        INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), Name, Tags, Signature, __VA_ARGS__ )
18283+#else
18284+    #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG(Name, Tags, Signature, ...) \
18285+        INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), Name, Tags, Signature, __VA_ARGS__ ) )
18286+#endif
18287+
18288+    #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(TestName, TestFuncName, Name, Tags, Signature, TmplTypes, TypesList) \
18289+        CATCH_INTERNAL_START_WARNINGS_SUPPRESSION                      \
18290+        CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS                      \
18291+        CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS                \
18292+        CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS       \
18293+        CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
18294+        CATCH_INTERNAL_SUPPRESS_COMMA_WARNINGS \
18295+        template<typename TestType> static void TestFuncName();       \
18296+        namespace {\
18297+        namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName) {                                     \
18298+            INTERNAL_CATCH_TYPE_GEN                                                  \
18299+            INTERNAL_CATCH_NTTP_GEN(INTERNAL_CATCH_REMOVE_PARENS(Signature))         \
18300+            template<typename... Types>                               \
18301+            struct TestName {                                         \
18302+                void reg_tests() {                                          \
18303+                    size_t index = 0;                                    \
18304+                    using expander = size_t[];                           \
18305+                    constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes))};\
18306+                    constexpr char const* types_list[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TypesList))};\
18307+                    constexpr auto num_types = sizeof(types_list) / sizeof(types_list[0]);\
18308+                    (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 */\
18309+                }                                                     \
18310+            };                                                        \
18311+            static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \
18312+                using TestInit = typename create<TestName, decltype(get_wrapper<INTERNAL_CATCH_REMOVE_PARENS(TmplTypes)>()), TypeList<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(INTERNAL_CATCH_REMOVE_PARENS(TypesList))>>::type; \
18313+                TestInit t;                                           \
18314+                t.reg_tests();                                        \
18315+                return 0;                                             \
18316+            }();                                                      \
18317+        }                                                             \
18318+        }                                                             \
18319+        CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION                       \
18320+        template<typename TestType>                                   \
18321+        static void TestFuncName()
18322+
18323+#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
18324+    #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(Name, Tags, ...)\
18325+        INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), Name, Tags, typename T,__VA_ARGS__)
18326+#else
18327+    #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(Name, Tags, ...)\
18328+        INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), Name, Tags, typename T, __VA_ARGS__ ) )
18329+#endif
18330+
18331+#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
18332+    #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG(Name, Tags, Signature, ...)\
18333+        INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), Name, Tags, Signature, __VA_ARGS__)
18334+#else
18335+    #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG(Name, Tags, Signature, ...)\
18336+        INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), Name, Tags, Signature, __VA_ARGS__ ) )
18337+#endif
18338+
18339+    #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_2(TestName, TestFunc, Name, Tags, TmplList)\
18340+        CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
18341+        CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
18342+        CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
18343+        CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
18344+        CATCH_INTERNAL_SUPPRESS_COMMA_WARNINGS \
18345+        template<typename TestType> static void TestFunc();       \
18346+        namespace {\
18347+        namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){\
18348+        INTERNAL_CATCH_TYPE_GEN\
18349+        template<typename... Types>                               \
18350+        struct TestName {                                         \
18351+            void reg_tests() {                                          \
18352+                size_t index = 0;                                    \
18353+                using expander = size_t[];                           \
18354+                (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestFunc<Types> ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ Name " - " INTERNAL_CATCH_STRINGIZE(TmplList) " - " + std::to_string(index), Tags } ), index++)... };/* NOLINT */\
18355+            }                                                     \
18356+        };\
18357+        static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \
18358+                using TestInit = typename convert<TestName, TmplList>::type; \
18359+                TestInit t;                                           \
18360+                t.reg_tests();                                        \
18361+                return 0;                                             \
18362+            }();                                                      \
18363+        }}\
18364+        CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION                       \
18365+        template<typename TestType>                                   \
18366+        static void TestFunc()
18367+
18368+    #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE(Name, Tags, TmplList) \
18369+        INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), Name, Tags, TmplList )
18370+
18371+
18372+    #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( TestNameClass, TestName, ClassName, Name, Tags, Signature, ... ) \
18373+        CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
18374+        CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
18375+        CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
18376+        CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
18377+        CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
18378+        namespace {\
18379+        namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){ \
18380+            INTERNAL_CATCH_TYPE_GEN\
18381+            INTERNAL_CATCH_NTTP_GEN(INTERNAL_CATCH_REMOVE_PARENS(Signature))\
18382+            INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD(TestName, ClassName, INTERNAL_CATCH_REMOVE_PARENS(Signature));\
18383+            INTERNAL_CATCH_NTTP_REG_METHOD_GEN(TestName, INTERNAL_CATCH_REMOVE_PARENS(Signature))\
18384+            template<typename...Types> \
18385+            struct TestNameClass{\
18386+                TestNameClass(){\
18387+                    size_t index = 0;                                    \
18388+                    constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, __VA_ARGS__)};\
18389+                    using expander = size_t[];\
18390+                    (void)expander{(reg_test(Types{}, #ClassName, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index]), Tags } ), index++)... };/* NOLINT */ \
18391+                }\
18392+            };\
18393+            static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
18394+                TestNameClass<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(__VA_ARGS__)>();\
18395+                return 0;\
18396+        }();\
18397+        }\
18398+        }\
18399+        CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
18400+        INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD(TestName, INTERNAL_CATCH_REMOVE_PARENS(Signature))
18401+
18402+#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
18403+    #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( ClassName, Name, Tags,... ) \
18404+        INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_CLASS_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ )
18405+#else
18406+    #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( ClassName, Name, Tags,... ) \
18407+        INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_CLASS_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ ) )
18408+#endif
18409+
18410+#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
18411+    #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... ) \
18412+        INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_CLASS_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ )
18413+#else
18414+    #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... ) \
18415+        INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_CLASS_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ ) )
18416+#endif
18417+
18418+    #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2(TestNameClass, TestName, ClassName, Name, Tags, Signature, TmplTypes, TypesList)\
18419+        CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
18420+        CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
18421+        CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
18422+        CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
18423+        CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
18424+        template<typename TestType> \
18425+            struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName <TestType>) { \
18426+                void test();\
18427+            };\
18428+        namespace {\
18429+        namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestNameClass) {\
18430+            INTERNAL_CATCH_TYPE_GEN                  \
18431+            INTERNAL_CATCH_NTTP_GEN(INTERNAL_CATCH_REMOVE_PARENS(Signature))\
18432+            template<typename...Types>\
18433+            struct TestNameClass{\
18434+                void reg_tests(){\
18435+                    std::size_t index = 0;\
18436+                    using expander = std::size_t[];\
18437+                    constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes))};\
18438+                    constexpr char const* types_list[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TypesList))};\
18439+                    constexpr auto num_types = sizeof(types_list) / sizeof(types_list[0]);\
18440+                    (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 */ \
18441+                }\
18442+            };\
18443+            static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
18444+                using TestInit = typename create<TestNameClass, decltype(get_wrapper<INTERNAL_CATCH_REMOVE_PARENS(TmplTypes)>()), TypeList<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(INTERNAL_CATCH_REMOVE_PARENS(TypesList))>>::type;\
18445+                TestInit t;\
18446+                t.reg_tests();\
18447+                return 0;\
18448+            }(); \
18449+        }\
18450+        }\
18451+        CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
18452+        template<typename TestType> \
18453+        void TestName<TestType>::test()
18454+
18455+#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
18456+    #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( ClassName, Name, Tags, ... )\
18457+        INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), ClassName, Name, Tags, typename T, __VA_ARGS__ )
18458+#else
18459+    #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( ClassName, Name, Tags, ... )\
18460+        INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), ClassName, Name, Tags, typename T,__VA_ARGS__ ) )
18461+#endif
18462+
18463+#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
18464+    #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... )\
18465+        INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), ClassName, Name, Tags, Signature, __VA_ARGS__ )
18466+#else
18467+    #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... )\
18468+        INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), ClassName, Name, Tags, Signature,__VA_ARGS__ ) )
18469+#endif
18470+
18471+    #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD_2( TestNameClass, TestName, ClassName, Name, Tags, TmplList) \
18472+        CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
18473+        CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
18474+        CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
18475+        CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
18476+        CATCH_INTERNAL_SUPPRESS_COMMA_WARNINGS \
18477+        template<typename TestType> \
18478+        struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName <TestType>) { \
18479+            void test();\
18480+        };\
18481+        namespace {\
18482+        namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){ \
18483+            INTERNAL_CATCH_TYPE_GEN\
18484+            template<typename...Types>\
18485+            struct TestNameClass{\
18486+                void reg_tests(){\
18487+                    size_t index = 0;\
18488+                    using expander = size_t[];\
18489+                    (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestName<Types>::test ), CATCH_INTERNAL_LINEINFO, #ClassName##_catch_sr, Catch::NameAndTags{ Name " - " INTERNAL_CATCH_STRINGIZE(TmplList) " - " + std::to_string(index), Tags } ), index++)... };/* NOLINT */ \
18490+                }\
18491+            };\
18492+            static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
18493+                using TestInit = typename convert<TestNameClass, TmplList>::type;\
18494+                TestInit t;\
18495+                t.reg_tests();\
18496+                return 0;\
18497+            }(); \
18498+        }}\
18499+        CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
18500+        template<typename TestType> \
18501+        void TestName<TestType>::test()
18502+
18503+#define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD(ClassName, Name, Tags, TmplList) \
18504+        INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), ClassName, Name, Tags, TmplList )
18505+
18506+
18507+#endif // CATCH_TEMPLATE_TEST_REGISTRY_HPP_INCLUDED
18508+
18509+
18510+#if defined(CATCH_CONFIG_PREFIX_ALL) && !defined(CATCH_CONFIG_DISABLE)
18511+
18512+  #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
18513+    #define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )
18514+    #define CATCH_TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG( __VA_ARGS__ )
18515+    #define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
18516+    #define CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ )
18517+    #define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ )
18518+    #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( __VA_ARGS__ )
18519+    #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ )
18520+    #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ )
18521+    #define CATCH_TEMPLATE_LIST_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE(__VA_ARGS__)
18522+    #define CATCH_TEMPLATE_LIST_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD( className, __VA_ARGS__ )
18523+  #else
18524+    #define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) )
18525+    #define CATCH_TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG( __VA_ARGS__ ) )
18526+    #define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) )
18527+    #define CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) )
18528+    #define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ ) )
18529+    #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( __VA_ARGS__ ) )
18530+    #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ ) )
18531+    #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) )
18532+    #define CATCH_TEMPLATE_LIST_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE( __VA_ARGS__ ) )
18533+    #define CATCH_TEMPLATE_LIST_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD( className, __VA_ARGS__ ) )
18534+  #endif
18535+
18536+#elif defined(CATCH_CONFIG_PREFIX_ALL) && defined(CATCH_CONFIG_DISABLE)
18537+
18538+  #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
18539+    #define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__)
18540+    #define CATCH_TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(__VA_ARGS__)
18541+    #define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(className, __VA_ARGS__)
18542+    #define CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION(className, __VA_ARGS__ )
18543+  #else
18544+    #define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__) )
18545+    #define CATCH_TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(__VA_ARGS__) )
18546+    #define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(className, __VA_ARGS__ ) )
18547+    #define CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION(className, __VA_ARGS__ ) )
18548+  #endif
18549+
18550+  // When disabled, these can be shared between proper preprocessor and MSVC preprocessor
18551+  #define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )
18552+  #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )
18553+  #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
18554+  #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
18555+  #define CATCH_TEMPLATE_LIST_TEST_CASE( ... ) CATCH_TEMPLATE_TEST_CASE(__VA_ARGS__)
18556+  #define CATCH_TEMPLATE_LIST_TEST_CASE_METHOD( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
18557+
18558+#elif !defined(CATCH_CONFIG_PREFIX_ALL) && !defined(CATCH_CONFIG_DISABLE)
18559+
18560+  #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
18561+    #define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )
18562+    #define TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG( __VA_ARGS__ )
18563+    #define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
18564+    #define TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ )
18565+    #define TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ )
18566+    #define TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( __VA_ARGS__ )
18567+    #define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ )
18568+    #define TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ )
18569+    #define TEMPLATE_LIST_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE(__VA_ARGS__)
18570+    #define TEMPLATE_LIST_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD( className, __VA_ARGS__ )
18571+  #else
18572+    #define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) )
18573+    #define TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG( __VA_ARGS__ ) )
18574+    #define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) )
18575+    #define TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) )
18576+    #define TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ ) )
18577+    #define TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( __VA_ARGS__ ) )
18578+    #define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ ) )
18579+    #define TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) )
18580+    #define TEMPLATE_LIST_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE( __VA_ARGS__ ) )
18581+    #define TEMPLATE_LIST_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD( className, __VA_ARGS__ ) )
18582+  #endif
18583+
18584+#elif !defined(CATCH_CONFIG_PREFIX_ALL) && defined(CATCH_CONFIG_DISABLE)
18585+
18586+  #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
18587+    #define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__)
18588+    #define TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(__VA_ARGS__)
18589+    #define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(className, __VA_ARGS__)
18590+    #define TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION(className, __VA_ARGS__ )
18591+  #else
18592+    #define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__) )
18593+    #define TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(__VA_ARGS__) )
18594+    #define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(className, __VA_ARGS__ ) )
18595+    #define TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION(className, __VA_ARGS__ ) )
18596+  #endif
18597+
18598+  // When disabled, these can be shared between proper preprocessor and MSVC preprocessor
18599+  #define TEMPLATE_PRODUCT_TEST_CASE( ... ) TEMPLATE_TEST_CASE( __VA_ARGS__ )
18600+  #define TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) TEMPLATE_TEST_CASE( __VA_ARGS__ )
18601+  #define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
18602+  #define TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
18603+  #define TEMPLATE_LIST_TEST_CASE( ... ) TEMPLATE_TEST_CASE(__VA_ARGS__)
18604+  #define TEMPLATE_LIST_TEST_CASE_METHOD( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
18605+
18606+#endif // end of user facing macro declarations
18607+
18608+
18609+#endif // CATCH_TEMPLATE_TEST_MACROS_HPP_INCLUDED
18610+
18611+
18612+#ifndef CATCH_TEST_CASE_INFO_HPP_INCLUDED
18613+#define CATCH_TEST_CASE_INFO_HPP_INCLUDED
18614+
18615+
18616+
18617+#include <cstdint>
18618+#include <string>
18619+#include <vector>
18620+
18621+#ifdef __clang__
18622+#pragma clang diagnostic push
18623+#pragma clang diagnostic ignored "-Wpadded"
18624+#endif
18625+
18626+namespace Catch {
18627+
18628+    /**
18629+     * A **view** of a tag string that provides case insensitive comparisons
18630+     *
18631+     * Note that in Catch2 internals, the square brackets around tags are
18632+     * not a part of tag's representation, so e.g. "[cool-tag]" is represented
18633+     * as "cool-tag" internally.
18634+     */
18635+    struct Tag {
18636+        constexpr Tag(StringRef original_):
18637+            original(original_)
18638+        {}
18639+        StringRef original;
18640+
18641+        friend bool operator< ( Tag const& lhs, Tag const& rhs );
18642+        friend bool operator==( Tag const& lhs, Tag const& rhs );
18643+    };
18644+
18645+    class ITestInvoker;
18646+    struct NameAndTags;
18647+
18648+    enum class TestCaseProperties : uint8_t {
18649+        None = 0,
18650+        IsHidden = 1 << 1,
18651+        ShouldFail = 1 << 2,
18652+        MayFail = 1 << 3,
18653+        Throws = 1 << 4,
18654+        NonPortable = 1 << 5,
18655+        Benchmark = 1 << 6
18656+    };
18657+
18658+    /**
18659+     * Various metadata about the test case.
18660+     *
18661+     * A test case is uniquely identified by its (class)name and tags
18662+     * combination, with source location being ignored, and other properties
18663+     * being determined from tags.
18664+     *
18665+     * Tags are kept sorted.
18666+     */
18667+    struct TestCaseInfo : Detail::NonCopyable {
18668+
18669+        TestCaseInfo(StringRef _className,
18670+                     NameAndTags const& _nameAndTags,
18671+                     SourceLineInfo const& _lineInfo);
18672+
18673+        bool isHidden() const;
18674+        bool throws() const;
18675+        bool okToFail() const;
18676+        bool expectedToFail() const;
18677+
18678+        // Adds the tag(s) with test's filename (for the -# flag)
18679+        void addFilenameTag();
18680+
18681+        //! Orders by name, classname and tags
18682+        friend bool operator<( TestCaseInfo const& lhs,
18683+                               TestCaseInfo const& rhs );
18684+
18685+
18686+        std::string tagsAsString() const;
18687+
18688+        std::string name;
18689+        StringRef className;
18690+    private:
18691+        std::string backingTags;
18692+        // Internally we copy tags to the backing storage and then add
18693+        // refs to this storage to the tags vector.
18694+        void internalAppendTag(StringRef tagString);
18695+    public:
18696+        std::vector<Tag> tags;
18697+        SourceLineInfo lineInfo;
18698+        TestCaseProperties properties = TestCaseProperties::None;
18699+    };
18700+
18701+    /**
18702+     * Wrapper over the test case information and the test case invoker
18703+     *
18704+     * Does not own either, and is specifically made to be cheap
18705+     * to copy around.
18706+     */
18707+    class TestCaseHandle {
18708+        TestCaseInfo* m_info;
18709+        ITestInvoker* m_invoker;
18710+    public:
18711+        TestCaseHandle(TestCaseInfo* info, ITestInvoker* invoker) :
18712+            m_info(info), m_invoker(invoker) {}
18713+
18714+        void invoke() const {
18715+            m_invoker->invoke();
18716+        }
18717+
18718+        TestCaseInfo const& getTestCaseInfo() const;
18719+    };
18720+
18721+    Detail::unique_ptr<TestCaseInfo>
18722+    makeTestCaseInfo( StringRef className,
18723+                      NameAndTags const& nameAndTags,
18724+                      SourceLineInfo const& lineInfo );
18725+}
18726+
18727+#ifdef __clang__
18728+#pragma clang diagnostic pop
18729+#endif
18730+
18731+#endif // CATCH_TEST_CASE_INFO_HPP_INCLUDED
18732+
18733+
18734+#ifndef CATCH_TRANSLATE_EXCEPTION_HPP_INCLUDED
18735+#define CATCH_TRANSLATE_EXCEPTION_HPP_INCLUDED
18736+
18737+
18738+
18739+#ifndef CATCH_INTERFACES_EXCEPTION_HPP_INCLUDED
18740+#define CATCH_INTERFACES_EXCEPTION_HPP_INCLUDED
18741+
18742+
18743+#include <string>
18744+#include <vector>
18745+
18746+namespace Catch {
18747+    using exceptionTranslateFunction = std::string(*)();
18748+
18749+    class IExceptionTranslator;
18750+    using ExceptionTranslators = std::vector<Detail::unique_ptr<IExceptionTranslator const>>;
18751+
18752+    class IExceptionTranslator {
18753+    public:
18754+        virtual ~IExceptionTranslator(); // = default
18755+        virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const = 0;
18756+    };
18757+
18758+    class IExceptionTranslatorRegistry {
18759+    public:
18760+        virtual ~IExceptionTranslatorRegistry(); // = default
18761+        virtual std::string translateActiveException() const = 0;
18762+    };
18763+
18764+} // namespace Catch
18765+
18766+#endif // CATCH_INTERFACES_EXCEPTION_HPP_INCLUDED
18767+
18768+#include <exception>
18769+
18770+namespace Catch {
18771+    namespace Detail {
18772+        void registerTranslatorImpl(
18773+            Detail::unique_ptr<IExceptionTranslator>&& translator );
18774+    }
18775+
18776+    class ExceptionTranslatorRegistrar {
18777+        template<typename T>
18778+        class ExceptionTranslator : public IExceptionTranslator {
18779+        public:
18780+
18781+            ExceptionTranslator( std::string(*translateFunction)( T const& ) )
18782+            : m_translateFunction( translateFunction )
18783+            {}
18784+
18785+            std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const override {
18786+#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
18787+                try {
18788+                    if( it == itEnd )
18789+                        std::rethrow_exception(std::current_exception());
18790+                    else
18791+                        return (*it)->translate( it+1, itEnd );
18792+                }
18793+                catch( T const& ex ) {
18794+                    return m_translateFunction( ex );
18795+                }
18796+#else
18797+                return "You should never get here!";
18798+#endif
18799+            }
18800+
18801+        protected:
18802+            std::string(*m_translateFunction)( T const& );
18803+        };
18804+
18805+    public:
18806+        template<typename T>
18807+        ExceptionTranslatorRegistrar( std::string(*translateFunction)( T const& ) ) {
18808+            Detail::registerTranslatorImpl(
18809+                Detail::make_unique<ExceptionTranslator<T>>(
18810+                    translateFunction ) );
18811+        }
18812+    };
18813+
18814+} // namespace Catch
18815+
18816+///////////////////////////////////////////////////////////////////////////////
18817+#define INTERNAL_CATCH_TRANSLATE_EXCEPTION2( translatorName, signature ) \
18818+    static std::string translatorName( signature ); \
18819+    CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
18820+    CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
18821+    namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &translatorName ); } \
18822+    CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
18823+    static std::string translatorName( signature )
18824+
18825+#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION2( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature )
18826+
18827+#if defined(CATCH_CONFIG_DISABLE)
18828+    #define INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( translatorName, signature) \
18829+            static std::string translatorName( signature )
18830+#endif
18831+
18832+
18833+// This macro is always prefixed
18834+#if !defined(CATCH_CONFIG_DISABLE)
18835+#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature )
18836+#else
18837+#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature )
18838+#endif
18839+
18840+
18841+#endif // CATCH_TRANSLATE_EXCEPTION_HPP_INCLUDED
18842+
18843+
18844+#ifndef CATCH_VERSION_HPP_INCLUDED
18845+#define CATCH_VERSION_HPP_INCLUDED
18846+
18847+#include <iosfwd>
18848+
18849+namespace Catch {
18850+
18851+    // Versioning information
18852+    struct Version {
18853+        Version( Version const& ) = delete;
18854+        Version& operator=( Version const& ) = delete;
18855+        Version(    unsigned int _majorVersion,
18856+                    unsigned int _minorVersion,
18857+                    unsigned int _patchNumber,
18858+                    char const * const _branchName,
18859+                    unsigned int _buildNumber );
18860+
18861+        unsigned int const majorVersion;
18862+        unsigned int const minorVersion;
18863+        unsigned int const patchNumber;
18864+
18865+        // buildNumber is only used if branchName is not null
18866+        char const * const branchName;
18867+        unsigned int const buildNumber;
18868+
18869+        friend std::ostream& operator << ( std::ostream& os, Version const& version );
18870+    };
18871+
18872+    Version const& libraryVersion();
18873+}
18874+
18875+#endif // CATCH_VERSION_HPP_INCLUDED
18876+
18877+
18878+#ifndef CATCH_VERSION_MACROS_HPP_INCLUDED
18879+#define CATCH_VERSION_MACROS_HPP_INCLUDED
18880+
18881+#define CATCH_VERSION_MAJOR 3
18882+#define CATCH_VERSION_MINOR 5
18883+#define CATCH_VERSION_PATCH 4
18884+
18885+#endif // CATCH_VERSION_MACROS_HPP_INCLUDED
18886+
18887+
18888+/** \file
18889+ * This is a convenience header for Catch2's Generator support. It includes
18890+ * **all** of Catch2 headers related to generators.
18891+ *
18892+ * Generally the Catch2 users should use specific includes they need,
18893+ * but this header can be used instead for ease-of-experimentation, or
18894+ * just plain convenience, at the cost of (significantly) increased
18895+ * compilation times.
18896+ *
18897+ * When a new header is added to either the `generators` folder,
18898+ * or to the corresponding internal subfolder, it should be added here.
18899+ */
18900+
18901+#ifndef CATCH_GENERATORS_ALL_HPP_INCLUDED
18902+#define CATCH_GENERATORS_ALL_HPP_INCLUDED
18903+
18904+
18905+
18906+#ifndef CATCH_GENERATOR_EXCEPTION_HPP_INCLUDED
18907+#define CATCH_GENERATOR_EXCEPTION_HPP_INCLUDED
18908+
18909+#include <exception>
18910+
18911+namespace Catch {
18912+
18913+    // Exception type to be thrown when a Generator runs into an error,
18914+    // e.g. it cannot initialize the first return value based on
18915+    // runtime information
18916+    class GeneratorException : public std::exception {
18917+        const char* const m_msg = "";
18918+
18919+    public:
18920+        GeneratorException(const char* msg):
18921+            m_msg(msg)
18922+        {}
18923+
18924+        const char* what() const noexcept override final;
18925+    };
18926+
18927+} // end namespace Catch
18928+
18929+#endif // CATCH_GENERATOR_EXCEPTION_HPP_INCLUDED
18930+
18931+
18932+#ifndef CATCH_GENERATORS_HPP_INCLUDED
18933+#define CATCH_GENERATORS_HPP_INCLUDED
18934+
18935+
18936+
18937+#ifndef CATCH_INTERFACES_GENERATORTRACKER_HPP_INCLUDED
18938+#define CATCH_INTERFACES_GENERATORTRACKER_HPP_INCLUDED
18939+
18940+
18941+#include <string>
18942+
18943+namespace Catch {
18944+
18945+    namespace Generators {
18946+        class GeneratorUntypedBase {
18947+            // Caches result from `toStringImpl`, assume that when it is an
18948+            // empty string, the cache is invalidated.
18949+            mutable std::string m_stringReprCache;
18950+
18951+            // Counts based on `next` returning true
18952+            std::size_t m_currentElementIndex = 0;
18953+
18954+            /**
18955+             * Attempts to move the generator to the next element
18956+             *
18957+             * Returns true iff the move succeeded (and a valid element
18958+             * can be retrieved).
18959+             */
18960+            virtual bool next() = 0;
18961+
18962+            //! Customization point for `currentElementAsString`
18963+            virtual std::string stringifyImpl() const = 0;
18964+
18965+        public:
18966+            GeneratorUntypedBase() = default;
18967+            // Generation of copy ops is deprecated (and Clang will complain)
18968+            // if there is a user destructor defined
18969+            GeneratorUntypedBase(GeneratorUntypedBase const&) = default;
18970+            GeneratorUntypedBase& operator=(GeneratorUntypedBase const&) = default;
18971+
18972+            virtual ~GeneratorUntypedBase(); // = default;
18973+
18974+            /**
18975+             * Attempts to move the generator to the next element
18976+             *
18977+             * Serves as a non-virtual interface to `next`, so that the
18978+             * top level interface can provide sanity checking and shared
18979+             * features.
18980+             *
18981+             * As with `next`, returns true iff the move succeeded and
18982+             * the generator has new valid element to provide.
18983+             */
18984+            bool countedNext();
18985+
18986+            std::size_t currentElementIndex() const { return m_currentElementIndex; }
18987+
18988+            /**
18989+             * Returns generator's current element as user-friendly string.
18990+             *
18991+             * By default returns string equivalent to calling
18992+             * `Catch::Detail::stringify` on the current element, but generators
18993+             * can customize their implementation as needed.
18994+             *
18995+             * Not thread-safe due to internal caching.
18996+             *
18997+             * The returned ref is valid only until the generator instance
18998+             * is destructed, or it moves onto the next element, whichever
18999+             * comes first.
19000+             */
19001+            StringRef currentElementAsString() const;
19002+        };
19003+        using GeneratorBasePtr = Catch::Detail::unique_ptr<GeneratorUntypedBase>;
19004+
19005+    } // namespace Generators
19006+
19007+    class IGeneratorTracker {
19008+    public:
19009+        virtual ~IGeneratorTracker(); // = default;
19010+        virtual auto hasGenerator() const -> bool = 0;
19011+        virtual auto getGenerator() const -> Generators::GeneratorBasePtr const& = 0;
19012+        virtual void setGenerator( Generators::GeneratorBasePtr&& generator ) = 0;
19013+    };
19014+
19015+} // namespace Catch
19016+
19017+#endif // CATCH_INTERFACES_GENERATORTRACKER_HPP_INCLUDED
19018+
19019+#include <vector>
19020+#include <tuple>
19021+
19022+namespace Catch {
19023+
19024+namespace Generators {
19025+
19026+namespace Detail {
19027+
19028+    //! Throws GeneratorException with the provided message
19029+    [[noreturn]]
19030+    void throw_generator_exception(char const * msg);
19031+
19032+} // end namespace detail
19033+
19034+    template<typename T>
19035+    class IGenerator : public GeneratorUntypedBase {
19036+        std::string stringifyImpl() const override {
19037+            return ::Catch::Detail::stringify( get() );
19038+        }
19039+
19040+    public:
19041+        // Returns the current element of the generator
19042+        //
19043+        // \Precondition The generator is either freshly constructed,
19044+        // or the last call to `next()` returned true
19045+        virtual T const& get() const = 0;
19046+        using type = T;
19047+    };
19048+
19049+    template <typename T>
19050+    using GeneratorPtr = Catch::Detail::unique_ptr<IGenerator<T>>;
19051+
19052+    template <typename T>
19053+    class GeneratorWrapper final {
19054+        GeneratorPtr<T> m_generator;
19055+    public:
19056+        //! Takes ownership of the passed pointer.
19057+        GeneratorWrapper(IGenerator<T>* generator):
19058+            m_generator(generator) {}
19059+        GeneratorWrapper(GeneratorPtr<T> generator):
19060+            m_generator(CATCH_MOVE(generator)) {}
19061+
19062+        T const& get() const {
19063+            return m_generator->get();
19064+        }
19065+        bool next() {
19066+            return m_generator->countedNext();
19067+        }
19068+    };
19069+
19070+
19071+    template<typename T>
19072+    class SingleValueGenerator final : public IGenerator<T> {
19073+        T m_value;
19074+    public:
19075+        SingleValueGenerator(T const& value) :
19076+            m_value(value)
19077+        {}
19078+        SingleValueGenerator(T&& value):
19079+            m_value(CATCH_MOVE(value))
19080+        {}
19081+
19082+        T const& get() const override {
19083+            return m_value;
19084+        }
19085+        bool next() override {
19086+            return false;
19087+        }
19088+    };
19089+
19090+    template<typename T>
19091+    class FixedValuesGenerator final : public IGenerator<T> {
19092+        static_assert(!std::is_same<T, bool>::value,
19093+            "FixedValuesGenerator does not support bools because of std::vector<bool>"
19094+            "specialization, use SingleValue Generator instead.");
19095+        std::vector<T> m_values;
19096+        size_t m_idx = 0;
19097+    public:
19098+        FixedValuesGenerator( std::initializer_list<T> values ) : m_values( values ) {}
19099+
19100+        T const& get() const override {
19101+            return m_values[m_idx];
19102+        }
19103+        bool next() override {
19104+            ++m_idx;
19105+            return m_idx < m_values.size();
19106+        }
19107+    };
19108+
19109+    template <typename T, typename DecayedT = std::decay_t<T>>
19110+    GeneratorWrapper<DecayedT> value( T&& value ) {
19111+        return GeneratorWrapper<DecayedT>(
19112+            Catch::Detail::make_unique<SingleValueGenerator<DecayedT>>(
19113+                CATCH_FORWARD( value ) ) );
19114+    }
19115+    template <typename T>
19116+    GeneratorWrapper<T> values(std::initializer_list<T> values) {
19117+        return GeneratorWrapper<T>(Catch::Detail::make_unique<FixedValuesGenerator<T>>(values));
19118+    }
19119+
19120+    template<typename T>
19121+    class Generators : public IGenerator<T> {
19122+        std::vector<GeneratorWrapper<T>> m_generators;
19123+        size_t m_current = 0;
19124+
19125+        void add_generator( GeneratorWrapper<T>&& generator ) {
19126+            m_generators.emplace_back( CATCH_MOVE( generator ) );
19127+        }
19128+        void add_generator( T const& val ) {
19129+            m_generators.emplace_back( value( val ) );
19130+        }
19131+        void add_generator( T&& val ) {
19132+            m_generators.emplace_back( value( CATCH_MOVE( val ) ) );
19133+        }
19134+        template <typename U>
19135+        std::enable_if_t<!std::is_same<std::decay_t<U>, T>::value>
19136+        add_generator( U&& val ) {
19137+            add_generator( T( CATCH_FORWARD( val ) ) );
19138+        }
19139+
19140+        template <typename U> void add_generators( U&& valueOrGenerator ) {
19141+            add_generator( CATCH_FORWARD( valueOrGenerator ) );
19142+        }
19143+
19144+        template <typename U, typename... Gs>
19145+        void add_generators( U&& valueOrGenerator, Gs&&... moreGenerators ) {
19146+            add_generator( CATCH_FORWARD( valueOrGenerator ) );
19147+            add_generators( CATCH_FORWARD( moreGenerators )... );
19148+        }
19149+
19150+    public:
19151+        template <typename... Gs>
19152+        Generators(Gs &&... moreGenerators) {
19153+            m_generators.reserve(sizeof...(Gs));
19154+            add_generators(CATCH_FORWARD(moreGenerators)...);
19155+        }
19156+
19157+        T const& get() const override {
19158+            return m_generators[m_current].get();
19159+        }
19160+
19161+        bool next() override {
19162+            if (m_current >= m_generators.size()) {
19163+                return false;
19164+            }
19165+            const bool current_status = m_generators[m_current].next();
19166+            if (!current_status) {
19167+                ++m_current;
19168+            }
19169+            return m_current < m_generators.size();
19170+        }
19171+    };
19172+
19173+
19174+    template <typename... Ts>
19175+    GeneratorWrapper<std::tuple<std::decay_t<Ts>...>>
19176+    table( std::initializer_list<std::tuple<std::decay_t<Ts>...>> tuples ) {
19177+        return values<std::tuple<Ts...>>( tuples );
19178+    }
19179+
19180+    // Tag type to signal that a generator sequence should convert arguments to a specific type
19181+    template <typename T>
19182+    struct as {};
19183+
19184+    template<typename T, typename... Gs>
19185+    auto makeGenerators( GeneratorWrapper<T>&& generator, Gs &&... moreGenerators ) -> Generators<T> {
19186+        return Generators<T>(CATCH_MOVE(generator), CATCH_FORWARD(moreGenerators)...);
19187+    }
19188+    template<typename T>
19189+    auto makeGenerators( GeneratorWrapper<T>&& generator ) -> Generators<T> {
19190+        return Generators<T>(CATCH_MOVE(generator));
19191+    }
19192+    template<typename T, typename... Gs>
19193+    auto makeGenerators( T&& val, Gs &&... moreGenerators ) -> Generators<std::decay_t<T>> {
19194+        return makeGenerators( value( CATCH_FORWARD( val ) ), CATCH_FORWARD( moreGenerators )... );
19195+    }
19196+    template<typename T, typename U, typename... Gs>
19197+    auto makeGenerators( as<T>, U&& val, Gs &&... moreGenerators ) -> Generators<T> {
19198+        return makeGenerators( value( T( CATCH_FORWARD( val ) ) ), CATCH_FORWARD( moreGenerators )... );
19199+    }
19200+
19201+    IGeneratorTracker* acquireGeneratorTracker( StringRef generatorName,
19202+                                                SourceLineInfo const& lineInfo );
19203+    IGeneratorTracker* createGeneratorTracker( StringRef generatorName,
19204+                                               SourceLineInfo lineInfo,
19205+                                               GeneratorBasePtr&& generator );
19206+
19207+    template<typename L>
19208+    auto generate( StringRef generatorName, SourceLineInfo const& lineInfo, L const& generatorExpression ) -> typename decltype(generatorExpression())::type {
19209+        using UnderlyingType = typename decltype(generatorExpression())::type;
19210+
19211+        IGeneratorTracker* tracker = acquireGeneratorTracker( generatorName, lineInfo );
19212+        // Creation of tracker is delayed after generator creation, so
19213+        // that constructing generator can fail without breaking everything.
19214+        if (!tracker) {
19215+            tracker = createGeneratorTracker(
19216+                generatorName,
19217+                lineInfo,
19218+                Catch::Detail::make_unique<Generators<UnderlyingType>>(
19219+                    generatorExpression() ) );
19220+        }
19221+
19222+        auto const& generator = static_cast<IGenerator<UnderlyingType> const&>( *tracker->getGenerator() );
19223+        return generator.get();
19224+    }
19225+
19226+} // namespace Generators
19227+} // namespace Catch
19228+
19229+#define CATCH_INTERNAL_GENERATOR_STRINGIZE_IMPL( ... ) #__VA_ARGS__##_catch_sr
19230+#define CATCH_INTERNAL_GENERATOR_STRINGIZE(...) CATCH_INTERNAL_GENERATOR_STRINGIZE_IMPL(__VA_ARGS__)
19231+
19232+#define GENERATE( ... ) \
19233+    Catch::Generators::generate( CATCH_INTERNAL_GENERATOR_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \
19234+                                 CATCH_INTERNAL_LINEINFO, \
19235+                                 [ ]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace)
19236+#define GENERATE_COPY( ... ) \
19237+    Catch::Generators::generate( CATCH_INTERNAL_GENERATOR_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \
19238+                                 CATCH_INTERNAL_LINEINFO, \
19239+                                 [=]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace)
19240+#define GENERATE_REF( ... ) \
19241+    Catch::Generators::generate( CATCH_INTERNAL_GENERATOR_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \
19242+                                 CATCH_INTERNAL_LINEINFO, \
19243+                                 [&]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace)
19244+
19245+#endif // CATCH_GENERATORS_HPP_INCLUDED
19246+
19247+
19248+#ifndef CATCH_GENERATORS_ADAPTERS_HPP_INCLUDED
19249+#define CATCH_GENERATORS_ADAPTERS_HPP_INCLUDED
19250+
19251+
19252+#include <cassert>
19253+
19254+namespace Catch {
19255+namespace Generators {
19256+
19257+    template <typename T>
19258+    class TakeGenerator final : public IGenerator<T> {
19259+        GeneratorWrapper<T> m_generator;
19260+        size_t m_returned = 0;
19261+        size_t m_target;
19262+    public:
19263+        TakeGenerator(size_t target, GeneratorWrapper<T>&& generator):
19264+            m_generator(CATCH_MOVE(generator)),
19265+            m_target(target)
19266+        {
19267+            assert(target != 0 && "Empty generators are not allowed");
19268+        }
19269+        T const& get() const override {
19270+            return m_generator.get();
19271+        }
19272+        bool next() override {
19273+            ++m_returned;
19274+            if (m_returned >= m_target) {
19275+                return false;
19276+            }
19277+
19278+            const auto success = m_generator.next();
19279+            // If the underlying generator does not contain enough values
19280+            // then we cut short as well
19281+            if (!success) {
19282+                m_returned = m_target;
19283+            }
19284+            return success;
19285+        }
19286+    };
19287+
19288+    template <typename T>
19289+    GeneratorWrapper<T> take(size_t target, GeneratorWrapper<T>&& generator) {
19290+        return GeneratorWrapper<T>(Catch::Detail::make_unique<TakeGenerator<T>>(target, CATCH_MOVE(generator)));
19291+    }
19292+
19293+
19294+    template <typename T, typename Predicate>
19295+    class FilterGenerator final : public IGenerator<T> {
19296+        GeneratorWrapper<T> m_generator;
19297+        Predicate m_predicate;
19298+    public:
19299+        template <typename P = Predicate>
19300+        FilterGenerator(P&& pred, GeneratorWrapper<T>&& generator):
19301+            m_generator(CATCH_MOVE(generator)),
19302+            m_predicate(CATCH_FORWARD(pred))
19303+        {
19304+            if (!m_predicate(m_generator.get())) {
19305+                // It might happen that there are no values that pass the
19306+                // filter. In that case we throw an exception.
19307+                auto has_initial_value = next();
19308+                if (!has_initial_value) {
19309+                    Detail::throw_generator_exception("No valid value found in filtered generator");
19310+                }
19311+            }
19312+        }
19313+
19314+        T const& get() const override {
19315+            return m_generator.get();
19316+        }
19317+
19318+        bool next() override {
19319+            bool success = m_generator.next();
19320+            if (!success) {
19321+                return false;
19322+            }
19323+            while (!m_predicate(m_generator.get()) && (success = m_generator.next()) == true);
19324+            return success;
19325+        }
19326+    };
19327+
19328+
19329+    template <typename T, typename Predicate>
19330+    GeneratorWrapper<T> filter(Predicate&& pred, GeneratorWrapper<T>&& generator) {
19331+        return GeneratorWrapper<T>(Catch::Detail::make_unique<FilterGenerator<T, Predicate>>(CATCH_FORWARD(pred), CATCH_MOVE(generator)));
19332+    }
19333+
19334+    template <typename T>
19335+    class RepeatGenerator final : public IGenerator<T> {
19336+        static_assert(!std::is_same<T, bool>::value,
19337+            "RepeatGenerator currently does not support bools"
19338+            "because of std::vector<bool> specialization");
19339+        GeneratorWrapper<T> m_generator;
19340+        mutable std::vector<T> m_returned;
19341+        size_t m_target_repeats;
19342+        size_t m_current_repeat = 0;
19343+        size_t m_repeat_index = 0;
19344+    public:
19345+        RepeatGenerator(size_t repeats, GeneratorWrapper<T>&& generator):
19346+            m_generator(CATCH_MOVE(generator)),
19347+            m_target_repeats(repeats)
19348+        {
19349+            assert(m_target_repeats > 0 && "Repeat generator must repeat at least once");
19350+        }
19351+
19352+        T const& get() const override {
19353+            if (m_current_repeat == 0) {
19354+                m_returned.push_back(m_generator.get());
19355+                return m_returned.back();
19356+            }
19357+            return m_returned[m_repeat_index];
19358+        }
19359+
19360+        bool next() override {
19361+            // There are 2 basic cases:
19362+            // 1) We are still reading the generator
19363+            // 2) We are reading our own cache
19364+
19365+            // In the first case, we need to poke the underlying generator.
19366+            // If it happily moves, we are left in that state, otherwise it is time to start reading from our cache
19367+            if (m_current_repeat == 0) {
19368+                const auto success = m_generator.next();
19369+                if (!success) {
19370+                    ++m_current_repeat;
19371+                }
19372+                return m_current_repeat < m_target_repeats;
19373+            }
19374+
19375+            // In the second case, we need to move indices forward and check that we haven't run up against the end
19376+            ++m_repeat_index;
19377+            if (m_repeat_index == m_returned.size()) {
19378+                m_repeat_index = 0;
19379+                ++m_current_repeat;
19380+            }
19381+            return m_current_repeat < m_target_repeats;
19382+        }
19383+    };
19384+
19385+    template <typename T>
19386+    GeneratorWrapper<T> repeat(size_t repeats, GeneratorWrapper<T>&& generator) {
19387+        return GeneratorWrapper<T>(Catch::Detail::make_unique<RepeatGenerator<T>>(repeats, CATCH_MOVE(generator)));
19388+    }
19389+
19390+    template <typename T, typename U, typename Func>
19391+    class MapGenerator final : public IGenerator<T> {
19392+        // TBD: provide static assert for mapping function, for friendly error message
19393+        GeneratorWrapper<U> m_generator;
19394+        Func m_function;
19395+        // To avoid returning dangling reference, we have to save the values
19396+        T m_cache;
19397+    public:
19398+        template <typename F2 = Func>
19399+        MapGenerator(F2&& function, GeneratorWrapper<U>&& generator) :
19400+            m_generator(CATCH_MOVE(generator)),
19401+            m_function(CATCH_FORWARD(function)),
19402+            m_cache(m_function(m_generator.get()))
19403+        {}
19404+
19405+        T const& get() const override {
19406+            return m_cache;
19407+        }
19408+        bool next() override {
19409+            const auto success = m_generator.next();
19410+            if (success) {
19411+                m_cache = m_function(m_generator.get());
19412+            }
19413+            return success;
19414+        }
19415+    };
19416+
19417+    template <typename Func, typename U, typename T = FunctionReturnType<Func, U>>
19418+    GeneratorWrapper<T> map(Func&& function, GeneratorWrapper<U>&& generator) {
19419+        return GeneratorWrapper<T>(
19420+            Catch::Detail::make_unique<MapGenerator<T, U, Func>>(CATCH_FORWARD(function), CATCH_MOVE(generator))
19421+        );
19422+    }
19423+
19424+    template <typename T, typename U, typename Func>
19425+    GeneratorWrapper<T> map(Func&& function, GeneratorWrapper<U>&& generator) {
19426+        return GeneratorWrapper<T>(
19427+            Catch::Detail::make_unique<MapGenerator<T, U, Func>>(CATCH_FORWARD(function), CATCH_MOVE(generator))
19428+        );
19429+    }
19430+
19431+    template <typename T>
19432+    class ChunkGenerator final : public IGenerator<std::vector<T>> {
19433+        std::vector<T> m_chunk;
19434+        size_t m_chunk_size;
19435+        GeneratorWrapper<T> m_generator;
19436+        bool m_used_up = false;
19437+    public:
19438+        ChunkGenerator(size_t size, GeneratorWrapper<T> generator) :
19439+            m_chunk_size(size), m_generator(CATCH_MOVE(generator))
19440+        {
19441+            m_chunk.reserve(m_chunk_size);
19442+            if (m_chunk_size != 0) {
19443+                m_chunk.push_back(m_generator.get());
19444+                for (size_t i = 1; i < m_chunk_size; ++i) {
19445+                    if (!m_generator.next()) {
19446+                        Detail::throw_generator_exception("Not enough values to initialize the first chunk");
19447+                    }
19448+                    m_chunk.push_back(m_generator.get());
19449+                }
19450+            }
19451+        }
19452+        std::vector<T> const& get() const override {
19453+            return m_chunk;
19454+        }
19455+        bool next() override {
19456+            m_chunk.clear();
19457+            for (size_t idx = 0; idx < m_chunk_size; ++idx) {
19458+                if (!m_generator.next()) {
19459+                    return false;
19460+                }
19461+                m_chunk.push_back(m_generator.get());
19462+            }
19463+            return true;
19464+        }
19465+    };
19466+
19467+    template <typename T>
19468+    GeneratorWrapper<std::vector<T>> chunk(size_t size, GeneratorWrapper<T>&& generator) {
19469+        return GeneratorWrapper<std::vector<T>>(
19470+            Catch::Detail::make_unique<ChunkGenerator<T>>(size, CATCH_MOVE(generator))
19471+        );
19472+    }
19473+
19474+} // namespace Generators
19475+} // namespace Catch
19476+
19477+
19478+#endif // CATCH_GENERATORS_ADAPTERS_HPP_INCLUDED
19479+
19480+
19481+#ifndef CATCH_GENERATORS_RANDOM_HPP_INCLUDED
19482+#define CATCH_GENERATORS_RANDOM_HPP_INCLUDED
19483+
19484+
19485+
19486+#ifndef CATCH_RANDOM_NUMBER_GENERATOR_HPP_INCLUDED
19487+#define CATCH_RANDOM_NUMBER_GENERATOR_HPP_INCLUDED
19488+
19489+#include <cstdint>
19490+
19491+namespace Catch {
19492+
19493+    // This is a simple implementation of C++11 Uniform Random Number
19494+    // Generator. It does not provide all operators, because Catch2
19495+    // does not use it, but it should behave as expected inside stdlib's
19496+    // distributions.
19497+    // The implementation is based on the PCG family (http://pcg-random.org)
19498+    class SimplePcg32 {
19499+        using state_type = std::uint64_t;
19500+    public:
19501+        using result_type = std::uint32_t;
19502+        static constexpr result_type (min)() {
19503+            return 0;
19504+        }
19505+        static constexpr result_type (max)() {
19506+            return static_cast<result_type>(-1);
19507+        }
19508+
19509+        // Provide some default initial state for the default constructor
19510+        SimplePcg32():SimplePcg32(0xed743cc4U) {}
19511+
19512+        explicit SimplePcg32(result_type seed_);
19513+
19514+        void seed(result_type seed_);
19515+        void discard(uint64_t skip);
19516+
19517+        result_type operator()();
19518+
19519+    private:
19520+        friend bool operator==(SimplePcg32 const& lhs, SimplePcg32 const& rhs);
19521+        friend bool operator!=(SimplePcg32 const& lhs, SimplePcg32 const& rhs);
19522+
19523+        // In theory we also need operator<< and operator>>
19524+        // In practice we do not use them, so we will skip them for now
19525+
19526+
19527+        std::uint64_t m_state;
19528+        // This part of the state determines which "stream" of the numbers
19529+        // is chosen -- we take it as a constant for Catch2, so we only
19530+        // need to deal with seeding the main state.
19531+        // Picked by reading 8 bytes from `/dev/random` :-)
19532+        static const std::uint64_t s_inc = (0x13ed0cc53f939476ULL << 1ULL) | 1ULL;
19533+    };
19534+
19535+} // end namespace Catch
19536+
19537+#endif // CATCH_RANDOM_NUMBER_GENERATOR_HPP_INCLUDED
19538+
19539+
19540+
19541+#ifndef CATCH_UNIFORM_INTEGER_DISTRIBUTION_HPP_INCLUDED
19542+#define CATCH_UNIFORM_INTEGER_DISTRIBUTION_HPP_INCLUDED
19543+
19544+
19545+
19546+
19547+#ifndef CATCH_RANDOM_INTEGER_HELPERS_HPP_INCLUDED
19548+#define CATCH_RANDOM_INTEGER_HELPERS_HPP_INCLUDED
19549+
19550+#include <climits>
19551+#include <cstddef>
19552+#include <cstdint>
19553+#include <type_traits>
19554+
19555+// Note: We use the usual enable-disable-autodetect dance here even though
19556+//       we do not support these in CMake configuration options (yet?).
19557+//       It is highly unlikely that we will need to make these actually
19558+//       user-configurable, but this will make it simpler if weend up needing
19559+//       it, and it provides an escape hatch to the users who need it.
19560+#if defined( __SIZEOF_INT128__ )
19561+#    define CATCH_CONFIG_INTERNAL_UINT128
19562+#elif defined( _MSC_VER ) && ( defined( _WIN64 ) || defined( _M_ARM64 ) )
19563+#    define CATCH_CONFIG_INTERNAL_MSVC_UMUL128
19564+#endif
19565+
19566+#if defined( CATCH_CONFIG_INTERNAL_UINT128 ) && \
19567+    !defined( CATCH_CONFIG_NO_UINT128 ) &&      \
19568+    !defined( CATCH_CONFIG_UINT128 )
19569+#define CATCH_CONFIG_UINT128
19570+#endif
19571+
19572+#if defined( CATCH_CONFIG_INTERNAL_MSVC_UMUL128 ) && \
19573+    !defined( CATCH_CONFIG_NO_MSVC_UMUL128 ) &&      \
19574+    !defined( CATCH_CONFIG_MSVC_UMUL128 )
19575+#    define CATCH_CONFIG_MSVC_UMUL128
19576+#    include <intrin.h>
19577+#    pragma intrinsic( _umul128 )
19578+#endif
19579+
19580+
19581+namespace Catch {
19582+    namespace Detail {
19583+
19584+        template <std::size_t>
19585+        struct SizedUnsignedType;
19586+#define SizedUnsignedTypeHelper( TYPE )        \
19587+    template <>                                \
19588+    struct SizedUnsignedType<sizeof( TYPE )> { \
19589+        using type = TYPE;                     \
19590+    }
19591+
19592+        SizedUnsignedTypeHelper( std::uint8_t );
19593+        SizedUnsignedTypeHelper( std::uint16_t );
19594+        SizedUnsignedTypeHelper( std::uint32_t );
19595+        SizedUnsignedTypeHelper( std::uint64_t );
19596+#undef SizedUnsignedTypeHelper
19597+
19598+        template <std::size_t sz>
19599+        using SizedUnsignedType_t = typename SizedUnsignedType<sz>::type;
19600+
19601+        template <typename T>
19602+        using DoubleWidthUnsignedType_t = SizedUnsignedType_t<2 * sizeof( T )>;
19603+
19604+        template <typename T>
19605+        struct ExtendedMultResult {
19606+            T upper;
19607+            T lower;
19608+            bool operator==( ExtendedMultResult const& rhs ) const {
19609+                return upper == rhs.upper && lower == rhs.lower;
19610+            }
19611+        };
19612+
19613+        /**
19614+         * Returns 128 bit result of lhs * rhs using portable C++ code
19615+         *
19616+         * This implementation is almost twice as fast as naive long multiplication,
19617+         * and unlike intrinsic-based approach, it supports constexpr evaluation.
19618+         */
19619+        constexpr ExtendedMultResult<std::uint64_t>
19620+        extendedMultPortable(std::uint64_t lhs, std::uint64_t rhs) {
19621+#define CarryBits( x ) ( x >> 32 )
19622+#define Digits( x ) ( x & 0xFF'FF'FF'FF )
19623+            std::uint64_t lhs_low = Digits( lhs );
19624+            std::uint64_t rhs_low = Digits( rhs );
19625+            std::uint64_t low_low = ( lhs_low * rhs_low );
19626+            std::uint64_t high_high = CarryBits( lhs ) * CarryBits( rhs );
19627+
19628+            // We add in carry bits from low-low already
19629+            std::uint64_t high_low =
19630+                ( CarryBits( lhs ) * rhs_low ) + CarryBits( low_low );
19631+            // Note that we can add only low bits from high_low, to avoid
19632+            // overflow with large inputs
19633+            std::uint64_t low_high =
19634+                ( lhs_low * CarryBits( rhs ) ) + Digits( high_low );
19635+
19636+            return { high_high + CarryBits( high_low ) + CarryBits( low_high ),
19637+                     ( low_high << 32 ) | Digits( low_low ) };
19638+#undef CarryBits
19639+#undef Digits
19640+        }
19641+
19642+        //! Returns 128 bit result of lhs * rhs
19643+        inline ExtendedMultResult<std::uint64_t>
19644+        extendedMult( std::uint64_t lhs, std::uint64_t rhs ) {
19645+#if defined( CATCH_CONFIG_UINT128 )
19646+            auto result = __uint128_t( lhs ) * __uint128_t( rhs );
19647+            return { static_cast<std::uint64_t>( result >> 64 ),
19648+                     static_cast<std::uint64_t>( result ) };
19649+#elif defined( CATCH_CONFIG_MSVC_UMUL128 )
19650+            std::uint64_t high;
19651+            std::uint64_t low = _umul128( lhs, rhs, &high );
19652+            return { high, low };
19653+#else
19654+            return extendedMultPortable( lhs, rhs );
19655+#endif
19656+        }
19657+
19658+
19659+        template <typename UInt>
19660+        constexpr ExtendedMultResult<UInt> extendedMult( UInt lhs, UInt rhs ) {
19661+            static_assert( std::is_unsigned<UInt>::value,
19662+                           "extendedMult can only handle unsigned integers" );
19663+            static_assert( sizeof( UInt ) < sizeof( std::uint64_t ),
19664+                           "Generic extendedMult can only handle types smaller "
19665+                           "than uint64_t" );
19666+            using WideType = DoubleWidthUnsignedType_t<UInt>;
19667+
19668+            auto result = WideType( lhs ) * WideType( rhs );
19669+            return {
19670+                static_cast<UInt>( result >> ( CHAR_BIT * sizeof( UInt ) ) ),
19671+                static_cast<UInt>( result & UInt( -1 ) ) };
19672+        }
19673+
19674+
19675+        template <typename TargetType,
19676+                  typename Generator>
19677+            std::enable_if_t<sizeof(typename Generator::result_type) >= sizeof(TargetType),
19678+            TargetType> fillBitsFrom(Generator& gen) {
19679+            using gresult_type = typename Generator::result_type;
19680+            static_assert( std::is_unsigned<TargetType>::value, "Only unsigned integers are supported" );
19681+            static_assert( Generator::min() == 0 &&
19682+                           Generator::max() == static_cast<gresult_type>( -1 ),
19683+                           "Generator must be able to output all numbers in its result type (effectively it must be a random bit generator)" );
19684+
19685+            // We want to return the top bits from a generator, as they are
19686+            // usually considered higher quality.
19687+            constexpr auto generated_bits = sizeof( gresult_type ) * CHAR_BIT;
19688+            constexpr auto return_bits = sizeof( TargetType ) * CHAR_BIT;
19689+
19690+            return static_cast<TargetType>( gen() >>
19691+                                            ( generated_bits - return_bits) );
19692+        }
19693+
19694+        template <typename TargetType,
19695+                  typename Generator>
19696+            std::enable_if_t<sizeof(typename Generator::result_type) < sizeof(TargetType),
19697+            TargetType> fillBitsFrom(Generator& gen) {
19698+            using gresult_type = typename Generator::result_type;
19699+            static_assert( std::is_unsigned<TargetType>::value,
19700+                           "Only unsigned integers are supported" );
19701+            static_assert( Generator::min() == 0 &&
19702+                           Generator::max() == static_cast<gresult_type>( -1 ),
19703+                           "Generator must be able to output all numbers in its result type (effectively it must be a random bit generator)" );
19704+
19705+            constexpr auto generated_bits = sizeof( gresult_type ) * CHAR_BIT;
19706+            constexpr auto return_bits = sizeof( TargetType ) * CHAR_BIT;
19707+            std::size_t filled_bits = 0;
19708+            TargetType ret = 0;
19709+            do {
19710+                ret <<= generated_bits;
19711+                ret |= gen();
19712+                filled_bits += generated_bits;
19713+            } while ( filled_bits < return_bits );
19714+
19715+            return ret;
19716+        }
19717+
19718+        /*
19719+         * Transposes numbers into unsigned type while keeping their ordering
19720+         *
19721+         * This means that signed types are changed so that the ordering is
19722+         * [INT_MIN, ..., -1, 0, ..., INT_MAX], rather than order we would
19723+         * get by simple casting ([0, ..., INT_MAX, INT_MIN, ..., -1])
19724+         */
19725+        template <typename OriginalType, typename UnsignedType>
19726+        std::enable_if_t<std::is_signed<OriginalType>::value, UnsignedType>
19727+        transposeToNaturalOrder( UnsignedType in ) {
19728+            static_assert(
19729+                sizeof( OriginalType ) == sizeof( UnsignedType ),
19730+                "reordering requires the same sized types on both sides" );
19731+            static_assert( std::is_unsigned<UnsignedType>::value,
19732+                           "Input type must be unsigned" );
19733+            // Assuming 2s complement (standardized in current C++), the
19734+            // positive and negative numbers are already internally ordered,
19735+            // and their difference is in the top bit. Swapping it orders
19736+            // them the desired way.
19737+            constexpr auto highest_bit =
19738+                UnsignedType( 1 ) << ( sizeof( UnsignedType ) * CHAR_BIT - 1 );
19739+            return static_cast<UnsignedType>( in ^ highest_bit );
19740+        }
19741+
19742+
19743+
19744+        template <typename OriginalType,
19745+                  typename UnsignedType>
19746+        std::enable_if_t<std::is_unsigned<OriginalType>::value, UnsignedType>
19747+            transposeToNaturalOrder(UnsignedType in) {
19748+            static_assert(
19749+                sizeof( OriginalType ) == sizeof( UnsignedType ),
19750+                "reordering requires the same sized types on both sides" );
19751+            static_assert( std::is_unsigned<UnsignedType>::value, "Input type must be unsigned" );
19752+            // No reordering is needed for unsigned -> unsigned
19753+            return in;
19754+        }
19755+    } // namespace Detail
19756+} // namespace Catch
19757+
19758+#endif // CATCH_RANDOM_INTEGER_HELPERS_HPP_INCLUDED
19759+
19760+namespace Catch {
19761+
19762+/**
19763+ * Implementation of uniform distribution on integers.
19764+ *
19765+ * Unlike `std::uniform_int_distribution`, this implementation supports
19766+ * various 1 byte integral types, including bool (but you should not
19767+ * actually use it for bools).
19768+ *
19769+ * The underlying algorithm is based on the one described in "Fast Random
19770+ * Integer Generation in an Interval" by Daniel Lemire, but has been
19771+ * optimized under the assumption of reuse of the same distribution object.
19772+ */
19773+template <typename IntegerType>
19774+class uniform_integer_distribution {
19775+    static_assert(std::is_integral<IntegerType>::value, "...");
19776+
19777+    using UnsignedIntegerType = Detail::SizedUnsignedType_t<sizeof(IntegerType)>;
19778+
19779+    // Only the left bound is stored, and we store it converted to its
19780+    // unsigned image. This avoids having to do the conversions inside
19781+    // the operator(), at the cost of having to do the conversion in
19782+    // the a() getter. The right bound is only needed in the b() getter,
19783+    // so we recompute it there from other stored data.
19784+    UnsignedIntegerType m_a;
19785+
19786+    // How many different values are there in [a, b]. a == b => 1, can be 0 for distribution over all values in the type.
19787+    UnsignedIntegerType m_ab_distance;
19788+
19789+    // We hoisted this out of the main generation function. Technically,
19790+    // this means that using this distribution will be slower than Lemire's
19791+    // algorithm if this distribution instance will be used only few times,
19792+    // but it will be faster if it is used many times. Since Catch2 uses
19793+    // distributions only to implement random generators, we assume that each
19794+    // distribution will be reused many times and this is an optimization.
19795+    UnsignedIntegerType m_rejection_threshold = 0;
19796+
19797+    UnsignedIntegerType computeDistance(IntegerType a, IntegerType b) const {
19798+        // This overflows and returns 0 if a == 0 and b == TYPE_MAX.
19799+        // We handle that later when generating the number.
19800+        return transposeTo(b) - transposeTo(a) + 1;
19801+    }
19802+
19803+    static UnsignedIntegerType computeRejectionThreshold(UnsignedIntegerType ab_distance) {
19804+        // distance == 0 means that we will return all possible values from
19805+        // the type's range, and that we shouldn't reject anything.
19806+        if ( ab_distance == 0 ) { return 0; }
19807+        return ( ~ab_distance + 1 ) % ab_distance;
19808+    }
19809+
19810+    static UnsignedIntegerType transposeTo(IntegerType in) {
19811+        return Detail::transposeToNaturalOrder<IntegerType>(
19812+            static_cast<UnsignedIntegerType>( in ) );
19813+    }
19814+    static IntegerType transposeBack(UnsignedIntegerType in) {
19815+        return static_cast<IntegerType>(
19816+            Detail::transposeToNaturalOrder<IntegerType>(in) );
19817+    }
19818+
19819+public:
19820+    using result_type = IntegerType;
19821+
19822+    uniform_integer_distribution( IntegerType a, IntegerType b ):
19823+        m_a( transposeTo(a) ),
19824+        m_ab_distance( computeDistance(a, b) ),
19825+        m_rejection_threshold( computeRejectionThreshold(m_ab_distance) ) {
19826+        assert( a <= b );
19827+    }
19828+
19829+    template <typename Generator>
19830+    result_type operator()( Generator& g ) {
19831+        // All possible values of result_type are valid.
19832+        if ( m_ab_distance == 0 ) {
19833+            return transposeBack( Detail::fillBitsFrom<UnsignedIntegerType>( g ) );
19834+        }
19835+
19836+        auto random_number = Detail::fillBitsFrom<UnsignedIntegerType>( g );
19837+        auto emul = Detail::extendedMult( random_number, m_ab_distance );
19838+        // Unlike Lemire's algorithm we skip the ab_distance check, since
19839+        // we precomputed the rejection threshold, which is always tighter.
19840+        while (emul.lower < m_rejection_threshold) {
19841+            random_number = Detail::fillBitsFrom<UnsignedIntegerType>( g );
19842+            emul = Detail::extendedMult( random_number, m_ab_distance );
19843+        }
19844+
19845+        return transposeBack(m_a + emul.upper);
19846+    }
19847+
19848+    result_type a() const { return transposeBack(m_a); }
19849+    result_type b() const { return transposeBack(m_ab_distance + m_a - 1); }
19850+};
19851+
19852+} // end namespace Catch
19853+
19854+#endif // CATCH_UNIFORM_INTEGER_DISTRIBUTION_HPP_INCLUDED
19855+
19856+
19857+
19858+#ifndef CATCH_UNIFORM_FLOATING_POINT_DISTRIBUTION_HPP_INCLUDED
19859+#define CATCH_UNIFORM_FLOATING_POINT_DISTRIBUTION_HPP_INCLUDED
19860+
19861+
19862+
19863+
19864+#ifndef CATCH_RANDOM_FLOATING_POINT_HELPERS_HPP_INCLUDED
19865+#define CATCH_RANDOM_FLOATING_POINT_HELPERS_HPP_INCLUDED
19866+
19867+
19868+
19869+#ifndef CATCH_POLYFILLS_HPP_INCLUDED
19870+#define CATCH_POLYFILLS_HPP_INCLUDED
19871+
19872+namespace Catch {
19873+
19874+    bool isnan(float f);
19875+    bool isnan(double d);
19876+
19877+    float nextafter(float x, float y);
19878+    double nextafter(double x, double y);
19879+
19880+}
19881+
19882+#endif // CATCH_POLYFILLS_HPP_INCLUDED
19883+
19884+#include <cassert>
19885+#include <cmath>
19886+#include <cstdint>
19887+#include <limits>
19888+#include <type_traits>
19889+
19890+namespace Catch {
19891+
19892+    namespace Detail {
19893+        /**
19894+         * Returns the largest magnitude of 1-ULP distance inside the [a, b] range.
19895+         *
19896+         * Assumes `a < b`.
19897+         */
19898+        template <typename FloatType>
19899+        FloatType gamma(FloatType a, FloatType b) {
19900+            static_assert( std::is_floating_point<FloatType>::value,
19901+                           "gamma returns the largest ULP magnitude within "
19902+                           "floating point range [a, b]. This only makes sense "
19903+                           "for floating point types" );
19904+            assert( a <= b );
19905+
19906+            const auto gamma_up = Catch::nextafter( a, std::numeric_limits<FloatType>::infinity() ) - a;
19907+            const auto gamma_down = b - Catch::nextafter( b, -std::numeric_limits<FloatType>::infinity() );
19908+
19909+            return gamma_up < gamma_down ? gamma_down : gamma_up;
19910+        }
19911+
19912+        template <typename FloatingPoint>
19913+        struct DistanceTypePicker;
19914+        template <>
19915+        struct DistanceTypePicker<float> {
19916+            using type = std::uint32_t;
19917+        };
19918+        template <>
19919+        struct DistanceTypePicker<double> {
19920+            using type = std::uint64_t;
19921+        };
19922+
19923+        template <typename T>
19924+        using DistanceType = typename DistanceTypePicker<T>::type;
19925+
19926+#if defined( __GNUC__ ) || defined( __clang__ )
19927+#    pragma GCC diagnostic push
19928+#    pragma GCC diagnostic ignored "-Wfloat-equal"
19929+#endif
19930+        /**
19931+         * Computes the number of equi-distant floats in [a, b]
19932+         *
19933+         * Since not every range can be split into equidistant floats
19934+         * exactly, we actually compute ceil(b/distance - a/distance),
19935+         * because in those cases we want to overcount.
19936+         *
19937+         * Uses modified Dekker's FastTwoSum algorithm to handle rounding.
19938+         */
19939+        template <typename FloatType>
19940+        DistanceType<FloatType>
19941+        count_equidistant_floats( FloatType a, FloatType b, FloatType distance ) {
19942+            assert( a <= b );
19943+            // We get distance as gamma for our uniform float distribution,
19944+            // so this will round perfectly.
19945+            const auto ag = a / distance;
19946+            const auto bg = b / distance;
19947+
19948+            const auto s = bg - ag;
19949+            const auto err = ( std::fabs( a ) <= std::fabs( b ) )
19950+                                 ? -ag - ( s - bg )
19951+                                 : bg - ( s + ag );
19952+            const auto ceil_s = static_cast<DistanceType<FloatType>>( std::ceil( s ) );
19953+
19954+            return ( ceil_s != s ) ? ceil_s : ceil_s + ( err > 0 );
19955+        }
19956+#if defined( __GNUC__ ) || defined( __clang__ )
19957+#    pragma GCC diagnostic pop
19958+#endif
19959+
19960+    }
19961+
19962+} // end namespace Catch
19963+
19964+#endif // CATCH_RANDOM_FLOATING_POINT_HELPERS_HPP_INCLUDED
19965+
19966+#include <cmath>
19967+#include <type_traits>
19968+
19969+namespace Catch {
19970+
19971+    namespace Detail {
19972+#if defined( __GNUC__ ) || defined( __clang__ )
19973+#    pragma GCC diagnostic push
19974+#    pragma GCC diagnostic ignored "-Wfloat-equal"
19975+#endif
19976+        // The issue with overflow only happens with maximal ULP and HUGE
19977+        // distance, e.g. when generating numbers in [-inf, inf] for given
19978+        // type. So we only check for the largest possible ULP in the
19979+        // type, and return something that does not overflow to inf in 1 mult.
19980+        constexpr std::uint64_t calculate_max_steps_in_one_go(double gamma) {
19981+            if ( gamma == 1.99584030953472e+292 ) { return 9007199254740991; }
19982+            return static_cast<std::uint64_t>( -1 );
19983+        }
19984+        constexpr std::uint32_t calculate_max_steps_in_one_go(float gamma) {
19985+            if ( gamma == 2.028241e+31f ) { return 16777215; }
19986+            return static_cast<std::uint32_t>( -1 );
19987+        }
19988+#if defined( __GNUC__ ) || defined( __clang__ )
19989+#    pragma GCC diagnostic pop
19990+#endif
19991+    }
19992+
19993+/**
19994+ * Implementation of uniform distribution on floating point numbers.
19995+ *
19996+ * Note that we support only `float` and `double` types, because these
19997+ * usually mean the same thing across different platform. `long double`
19998+ * varies wildly by platform and thus we cannot provide reproducible
19999+ * implementation. Also note that we don't implement all parts of
20000+ * distribution per standard: this distribution is not serializable, nor
20001+ * can the range be arbitrarily reset.
20002+ *
20003+ * The implementation also uses different approach than the one taken by
20004+ * `std::uniform_real_distribution`, where instead of generating a number
20005+ * between [0, 1) and then multiplying the range bounds with it, we first
20006+ * split the [a, b] range into a set of equidistributed floating point
20007+ * numbers, and then use uniform int distribution to pick which one to
20008+ * return.
20009+ *
20010+ * This has the advantage of guaranteeing uniformity (the multiplication
20011+ * method loses uniformity due to rounding when multiplying floats), except
20012+ * for small non-uniformity at one side of the interval, where we have
20013+ * to deal with the fact that not every interval is splittable into
20014+ * equidistributed floats.
20015+ *
20016+ * Based on "Drawing random floating-point numbers from an interval" by
20017+ * Frederic Goualard.
20018+ */
20019+template <typename FloatType>
20020+class uniform_floating_point_distribution {
20021+    static_assert(std::is_floating_point<FloatType>::value, "...");
20022+    static_assert(!std::is_same<FloatType, long double>::value,
20023+                  "We do not support long double due to inconsistent behaviour between platforms");
20024+
20025+    using WidthType = Detail::DistanceType<FloatType>;
20026+
20027+    FloatType m_a, m_b;
20028+    FloatType m_ulp_magnitude;
20029+    WidthType m_floats_in_range;
20030+    uniform_integer_distribution<WidthType> m_int_dist;
20031+
20032+    // In specific cases, we can overflow into `inf` when computing the
20033+    // `steps * g` offset. To avoid this, we don't offset by more than this
20034+    // in one multiply + addition.
20035+    WidthType m_max_steps_in_one_go;
20036+    // We don't want to do the magnitude check every call to `operator()`
20037+    bool m_a_has_leq_magnitude;
20038+
20039+public:
20040+    using result_type = FloatType;
20041+
20042+    uniform_floating_point_distribution( FloatType a, FloatType b ):
20043+        m_a( a ),
20044+        m_b( b ),
20045+        m_ulp_magnitude( Detail::gamma( m_a, m_b ) ),
20046+        m_floats_in_range( Detail::count_equidistant_floats( m_a, m_b, m_ulp_magnitude ) ),
20047+        m_int_dist(0, m_floats_in_range),
20048+        m_max_steps_in_one_go( Detail::calculate_max_steps_in_one_go(m_ulp_magnitude)),
20049+        m_a_has_leq_magnitude(std::fabs(m_a) <= std::fabs(m_b))
20050+    {
20051+        assert( a <= b );
20052+    }
20053+
20054+    template <typename Generator>
20055+    result_type operator()( Generator& g ) {
20056+        WidthType steps = m_int_dist( g );
20057+        if ( m_a_has_leq_magnitude ) {
20058+            if ( steps == m_floats_in_range ) { return m_a; }
20059+            auto b = m_b;
20060+            while (steps > m_max_steps_in_one_go) {
20061+                b -= m_max_steps_in_one_go * m_ulp_magnitude;
20062+                steps -= m_max_steps_in_one_go;
20063+            }
20064+            return b - steps * m_ulp_magnitude;
20065+        } else {
20066+            if ( steps == m_floats_in_range ) { return m_b; }
20067+            auto a = m_a;
20068+            while (steps > m_max_steps_in_one_go) {
20069+                a += m_max_steps_in_one_go * m_ulp_magnitude;
20070+                steps -= m_max_steps_in_one_go;
20071+            }
20072+            return a + steps * m_ulp_magnitude;
20073+        }
20074+    }
20075+
20076+    result_type a() const { return m_a; }
20077+    result_type b() const { return m_b; }
20078+};
20079+
20080+} // end namespace Catch
20081+
20082+#endif // CATCH_UNIFORM_FLOATING_POINT_DISTRIBUTION_HPP_INCLUDED
20083+
20084+namespace Catch {
20085+namespace Generators {
20086+namespace Detail {
20087+    // Returns a suitable seed for a random floating generator based off
20088+    // the primary internal rng. It does so by taking current value from
20089+    // the rng and returning it as the seed.
20090+    std::uint32_t getSeed();
20091+}
20092+
20093+template <typename Float>
20094+class RandomFloatingGenerator final : public IGenerator<Float> {
20095+    Catch::SimplePcg32 m_rng;
20096+    Catch::uniform_floating_point_distribution<Float> m_dist;
20097+    Float m_current_number;
20098+public:
20099+    RandomFloatingGenerator( Float a, Float b, std::uint32_t seed ):
20100+        m_rng(seed),
20101+        m_dist(a, b) {
20102+        static_cast<void>(next());
20103+    }
20104+
20105+    Float const& get() const override {
20106+        return m_current_number;
20107+    }
20108+    bool next() override {
20109+        m_current_number = m_dist(m_rng);
20110+        return true;
20111+    }
20112+};
20113+
20114+template <>
20115+class RandomFloatingGenerator<long double> final : public IGenerator<long double> {
20116+    // We still rely on <random> for this specialization, but we don't
20117+    // want to drag it into the header.
20118+    struct PImpl;
20119+    Catch::Detail::unique_ptr<PImpl> m_pimpl;
20120+    long double m_current_number;
20121+
20122+public:
20123+    RandomFloatingGenerator( long double a, long double b, std::uint32_t seed );
20124+
20125+    long double const& get() const override { return m_current_number; }
20126+    bool next() override;
20127+
20128+    ~RandomFloatingGenerator() override; // = default
20129+};
20130+
20131+template <typename Integer>
20132+class RandomIntegerGenerator final : public IGenerator<Integer> {
20133+    Catch::SimplePcg32 m_rng;
20134+    Catch::uniform_integer_distribution<Integer> m_dist;
20135+    Integer m_current_number;
20136+public:
20137+    RandomIntegerGenerator( Integer a, Integer b, std::uint32_t seed ):
20138+        m_rng(seed),
20139+        m_dist(a, b) {
20140+        static_cast<void>(next());
20141+    }
20142+
20143+    Integer const& get() const override {
20144+        return m_current_number;
20145+    }
20146+    bool next() override {
20147+        m_current_number = m_dist(m_rng);
20148+        return true;
20149+    }
20150+};
20151+
20152+template <typename T>
20153+std::enable_if_t<std::is_integral<T>::value, GeneratorWrapper<T>>
20154+random(T a, T b) {
20155+    return GeneratorWrapper<T>(
20156+        Catch::Detail::make_unique<RandomIntegerGenerator<T>>(a, b, Detail::getSeed())
20157+    );
20158+}
20159+
20160+template <typename T>
20161+std::enable_if_t<std::is_floating_point<T>::value,
20162+GeneratorWrapper<T>>
20163+random(T a, T b) {
20164+    return GeneratorWrapper<T>(
20165+        Catch::Detail::make_unique<RandomFloatingGenerator<T>>(a, b, Detail::getSeed())
20166+    );
20167+}
20168+
20169+
20170+} // namespace Generators
20171+} // namespace Catch
20172+
20173+
20174+#endif // CATCH_GENERATORS_RANDOM_HPP_INCLUDED
20175+
20176+
20177+#ifndef CATCH_GENERATORS_RANGE_HPP_INCLUDED
20178+#define CATCH_GENERATORS_RANGE_HPP_INCLUDED
20179+
20180+
20181+#include <iterator>
20182+#include <type_traits>
20183+
20184+namespace Catch {
20185+namespace Generators {
20186+
20187+
20188+template <typename T>
20189+class RangeGenerator final : public IGenerator<T> {
20190+    T m_current;
20191+    T m_end;
20192+    T m_step;
20193+    bool m_positive;
20194+
20195+public:
20196+    RangeGenerator(T const& start, T const& end, T const& step):
20197+        m_current(start),
20198+        m_end(end),
20199+        m_step(step),
20200+        m_positive(m_step > T(0))
20201+    {
20202+        assert(m_current != m_end && "Range start and end cannot be equal");
20203+        assert(m_step != T(0) && "Step size cannot be zero");
20204+        assert(((m_positive && m_current <= m_end) || (!m_positive && m_current >= m_end)) && "Step moves away from end");
20205+    }
20206+
20207+    RangeGenerator(T const& start, T const& end):
20208+        RangeGenerator(start, end, (start < end) ? T(1) : T(-1))
20209+    {}
20210+
20211+    T const& get() const override {
20212+        return m_current;
20213+    }
20214+
20215+    bool next() override {
20216+        m_current += m_step;
20217+        return (m_positive) ? (m_current < m_end) : (m_current > m_end);
20218+    }
20219+};
20220+
20221+template <typename T>
20222+GeneratorWrapper<T> range(T const& start, T const& end, T const& step) {
20223+    static_assert(std::is_arithmetic<T>::value && !std::is_same<T, bool>::value, "Type must be numeric");
20224+    return GeneratorWrapper<T>(Catch::Detail::make_unique<RangeGenerator<T>>(start, end, step));
20225+}
20226+
20227+template <typename T>
20228+GeneratorWrapper<T> range(T const& start, T const& end) {
20229+    static_assert(std::is_integral<T>::value && !std::is_same<T, bool>::value, "Type must be an integer");
20230+    return GeneratorWrapper<T>(Catch::Detail::make_unique<RangeGenerator<T>>(start, end));
20231+}
20232+
20233+
20234+template <typename T>
20235+class IteratorGenerator final : public IGenerator<T> {
20236+    static_assert(!std::is_same<T, bool>::value,
20237+        "IteratorGenerator currently does not support bools"
20238+        "because of std::vector<bool> specialization");
20239+
20240+    std::vector<T> m_elems;
20241+    size_t m_current = 0;
20242+public:
20243+    template <typename InputIterator, typename InputSentinel>
20244+    IteratorGenerator(InputIterator first, InputSentinel last):m_elems(first, last) {
20245+        if (m_elems.empty()) {
20246+            Detail::throw_generator_exception("IteratorGenerator received no valid values");
20247+        }
20248+    }
20249+
20250+    T const& get() const override {
20251+        return m_elems[m_current];
20252+    }
20253+
20254+    bool next() override {
20255+        ++m_current;
20256+        return m_current != m_elems.size();
20257+    }
20258+};
20259+
20260+template <typename InputIterator,
20261+          typename InputSentinel,
20262+          typename ResultType = typename std::iterator_traits<InputIterator>::value_type>
20263+GeneratorWrapper<ResultType> from_range(InputIterator from, InputSentinel to) {
20264+    return GeneratorWrapper<ResultType>(Catch::Detail::make_unique<IteratorGenerator<ResultType>>(from, to));
20265+}
20266+
20267+template <typename Container>
20268+auto from_range(Container const& cnt) {
20269+    using std::begin;
20270+    using std::end;
20271+    return from_range( begin( cnt ), end( cnt ) );
20272+}
20273+
20274+
20275+} // namespace Generators
20276+} // namespace Catch
20277+
20278+
20279+#endif // CATCH_GENERATORS_RANGE_HPP_INCLUDED
20280+
20281+#endif // CATCH_GENERATORS_ALL_HPP_INCLUDED
20282+
20283+
20284+/** \file
20285+ * This is a convenience header for Catch2's interfaces. It includes
20286+ * **all** of Catch2 headers related to interfaces.
20287+ *
20288+ * Generally the Catch2 users should use specific includes they need,
20289+ * but this header can be used instead for ease-of-experimentation, or
20290+ * just plain convenience, at the cost of somewhat increased compilation
20291+ * times.
20292+ *
20293+ * When a new header is added to either the `interfaces` folder, or to
20294+ * the corresponding internal subfolder, it should be added here.
20295+ */
20296+
20297+
20298+#ifndef CATCH_INTERFACES_ALL_HPP_INCLUDED
20299+#define CATCH_INTERFACES_ALL_HPP_INCLUDED
20300+
20301+
20302+
20303+#ifndef CATCH_INTERFACES_REPORTER_HPP_INCLUDED
20304+#define CATCH_INTERFACES_REPORTER_HPP_INCLUDED
20305+
20306+
20307+
20308+#ifndef CATCH_TEST_RUN_INFO_HPP_INCLUDED
20309+#define CATCH_TEST_RUN_INFO_HPP_INCLUDED
20310+
20311+
20312+namespace Catch {
20313+
20314+    struct TestRunInfo {
20315+        constexpr TestRunInfo(StringRef _name) : name(_name) {}
20316+        StringRef name;
20317+    };
20318+
20319+} // end namespace Catch
20320+
20321+#endif // CATCH_TEST_RUN_INFO_HPP_INCLUDED
20322+
20323+#include <map>
20324+#include <string>
20325+#include <vector>
20326+#include <iosfwd>
20327+
20328+namespace Catch {
20329+
20330+    struct ReporterDescription;
20331+    struct ListenerDescription;
20332+    struct TagInfo;
20333+    struct TestCaseInfo;
20334+    class TestCaseHandle;
20335+    class IConfig;
20336+    class IStream;
20337+    enum class ColourMode : std::uint8_t;
20338+
20339+    struct ReporterConfig {
20340+        ReporterConfig( IConfig const* _fullConfig,
20341+                        Detail::unique_ptr<IStream> _stream,
20342+                        ColourMode colourMode,
20343+                        std::map<std::string, std::string> customOptions );
20344+
20345+        ReporterConfig( ReporterConfig&& ) = default;
20346+        ReporterConfig& operator=( ReporterConfig&& ) = default;
20347+        ~ReporterConfig(); // = default
20348+
20349+        Detail::unique_ptr<IStream> takeStream() &&;
20350+        IConfig const* fullConfig() const;
20351+        ColourMode colourMode() const;
20352+        std::map<std::string, std::string> const& customOptions() const;
20353+
20354+    private:
20355+        Detail::unique_ptr<IStream> m_stream;
20356+        IConfig const* m_fullConfig;
20357+        ColourMode m_colourMode;
20358+        std::map<std::string, std::string> m_customOptions;
20359+    };
20360+
20361+    struct AssertionStats {
20362+        AssertionStats( AssertionResult const& _assertionResult,
20363+                        std::vector<MessageInfo> const& _infoMessages,
20364+                        Totals const& _totals );
20365+
20366+        AssertionStats( AssertionStats const& )              = default;
20367+        AssertionStats( AssertionStats && )                  = default;
20368+        AssertionStats& operator = ( AssertionStats const& ) = delete;
20369+        AssertionStats& operator = ( AssertionStats && )     = delete;
20370+
20371+        AssertionResult assertionResult;
20372+        std::vector<MessageInfo> infoMessages;
20373+        Totals totals;
20374+    };
20375+
20376+    struct SectionStats {
20377+        SectionStats(   SectionInfo&& _sectionInfo,
20378+                        Counts const& _assertions,
20379+                        double _durationInSeconds,
20380+                        bool _missingAssertions );
20381+
20382+        SectionInfo sectionInfo;
20383+        Counts assertions;
20384+        double durationInSeconds;
20385+        bool missingAssertions;
20386+    };
20387+
20388+    struct TestCaseStats {
20389+        TestCaseStats(  TestCaseInfo const& _testInfo,
20390+                        Totals const& _totals,
20391+                        std::string&& _stdOut,
20392+                        std::string&& _stdErr,
20393+                        bool _aborting );
20394+
20395+        TestCaseInfo const * testInfo;
20396+        Totals totals;
20397+        std::string stdOut;
20398+        std::string stdErr;
20399+        bool aborting;
20400+    };
20401+
20402+    struct TestRunStats {
20403+        TestRunStats(   TestRunInfo const& _runInfo,
20404+                        Totals const& _totals,
20405+                        bool _aborting );
20406+
20407+        TestRunInfo runInfo;
20408+        Totals totals;
20409+        bool aborting;
20410+    };
20411+
20412+    //! By setting up its preferences, a reporter can modify Catch2's behaviour
20413+    //! in some regards, e.g. it can request Catch2 to capture writes to
20414+    //! stdout/stderr during test execution, and pass them to the reporter.
20415+    struct ReporterPreferences {
20416+        //! Catch2 should redirect writes to stdout and pass them to the
20417+        //! reporter
20418+        bool shouldRedirectStdOut = false;
20419+        //! Catch2 should call `Reporter::assertionEnded` even for passing
20420+        //! assertions
20421+        bool shouldReportAllAssertions = false;
20422+    };
20423+
20424+    /**
20425+     * The common base for all reporters and event listeners
20426+     *
20427+     * Implementing classes must also implement:
20428+     *
20429+     *     //! User-friendly description of the reporter/listener type
20430+     *     static std::string getDescription()
20431+     *
20432+     * Generally shouldn't be derived from by users of Catch2 directly,
20433+     * instead they should derive from one of the utility bases that
20434+     * derive from this class.
20435+     */
20436+    class IEventListener {
20437+    protected:
20438+        //! Derived classes can set up their preferences here
20439+        ReporterPreferences m_preferences;
20440+        //! The test run's config as filled in from CLI and defaults
20441+        IConfig const* m_config;
20442+
20443+    public:
20444+        IEventListener( IConfig const* config ): m_config( config ) {}
20445+
20446+        virtual ~IEventListener(); // = default;
20447+
20448+        // Implementing class must also provide the following static methods:
20449+        // static std::string getDescription();
20450+
20451+        ReporterPreferences const& getPreferences() const {
20452+            return m_preferences;
20453+        }
20454+
20455+        //! Called when no test cases match provided test spec
20456+        virtual void noMatchingTestCases( StringRef unmatchedSpec ) = 0;
20457+        //! Called for all invalid test specs from the cli
20458+        virtual void reportInvalidTestSpec( StringRef invalidArgument ) = 0;
20459+
20460+        /**
20461+         * Called once in a testing run before tests are started
20462+         *
20463+         * Not called if tests won't be run (e.g. only listing will happen)
20464+         */
20465+        virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0;
20466+
20467+        //! Called _once_ for each TEST_CASE, no matter how many times it is entered
20468+        virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0;
20469+        //! Called _every time_ a TEST_CASE is entered, including repeats (due to sections)
20470+        virtual void testCasePartialStarting( TestCaseInfo const& testInfo, uint64_t partNumber ) = 0;
20471+        //! Called when a `SECTION` is being entered. Not called for skipped sections
20472+        virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0;
20473+
20474+        //! Called when user-code is being probed before the actual benchmark runs
20475+        virtual void benchmarkPreparing( StringRef benchmarkName ) = 0;
20476+        //! Called after probe but before the user-code is being benchmarked
20477+        virtual void benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) = 0;
20478+        //! Called with the benchmark results if benchmark successfully finishes
20479+        virtual void benchmarkEnded( BenchmarkStats<> const& benchmarkStats ) = 0;
20480+        //! Called if running the benchmarks fails for any reason
20481+        virtual void benchmarkFailed( StringRef benchmarkName ) = 0;
20482+
20483+        //! Called before assertion success/failure is evaluated
20484+        virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0;
20485+
20486+        //! Called after assertion was fully evaluated
20487+        virtual void assertionEnded( AssertionStats const& assertionStats ) = 0;
20488+
20489+        //! Called after a `SECTION` has finished running
20490+        virtual void sectionEnded( SectionStats const& sectionStats ) = 0;
20491+        //! Called _every time_ a TEST_CASE is entered, including repeats (due to sections)
20492+        virtual void testCasePartialEnded(TestCaseStats const& testCaseStats, uint64_t partNumber ) = 0;
20493+        //! Called _once_ for each TEST_CASE, no matter how many times it is entered
20494+        virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0;
20495+        /**
20496+         * Called once after all tests in a testing run are finished
20497+         *
20498+         * Not called if tests weren't run (e.g. only listings happened)
20499+         */
20500+        virtual void testRunEnded( TestRunStats const& testRunStats ) = 0;
20501+
20502+        /**
20503+         * Called with test cases that are skipped due to the test run aborting.
20504+         * NOT called for test cases that are explicitly skipped using the `SKIP` macro.
20505+         *
20506+         * Deprecated - will be removed in the next major release.
20507+         */
20508+        virtual void skipTest( TestCaseInfo const& testInfo ) = 0;
20509+
20510+        //! Called if a fatal error (signal/structured exception) occurred
20511+        virtual void fatalErrorEncountered( StringRef error ) = 0;
20512+
20513+        //! Writes out information about provided reporters using reporter-specific format
20514+        virtual void listReporters(std::vector<ReporterDescription> const& descriptions) = 0;
20515+        //! Writes out the provided listeners descriptions using reporter-specific format
20516+        virtual void listListeners(std::vector<ListenerDescription> const& descriptions) = 0;
20517+        //! Writes out information about provided tests using reporter-specific format
20518+        virtual void listTests(std::vector<TestCaseHandle> const& tests) = 0;
20519+        //! Writes out information about the provided tags using reporter-specific format
20520+        virtual void listTags(std::vector<TagInfo> const& tags) = 0;
20521+    };
20522+    using IEventListenerPtr = Detail::unique_ptr<IEventListener>;
20523+
20524+} // end namespace Catch
20525+
20526+#endif // CATCH_INTERFACES_REPORTER_HPP_INCLUDED
20527+
20528+
20529+#ifndef CATCH_INTERFACES_REPORTER_FACTORY_HPP_INCLUDED
20530+#define CATCH_INTERFACES_REPORTER_FACTORY_HPP_INCLUDED
20531+
20532+
20533+#include <string>
20534+
20535+namespace Catch {
20536+
20537+    struct ReporterConfig;
20538+    class IConfig;
20539+    class IEventListener;
20540+    using IEventListenerPtr = Detail::unique_ptr<IEventListener>;
20541+
20542+
20543+    class IReporterFactory {
20544+    public:
20545+        virtual ~IReporterFactory(); // = default
20546+
20547+        virtual IEventListenerPtr
20548+        create( ReporterConfig&& config ) const = 0;
20549+        virtual std::string getDescription() const = 0;
20550+    };
20551+    using IReporterFactoryPtr = Detail::unique_ptr<IReporterFactory>;
20552+
20553+    class EventListenerFactory {
20554+    public:
20555+        virtual ~EventListenerFactory(); // = default
20556+        virtual IEventListenerPtr create( IConfig const* config ) const = 0;
20557+        //! Return a meaningful name for the listener, e.g. its type name
20558+        virtual StringRef getName() const = 0;
20559+        //! Return listener's description if available
20560+        virtual std::string getDescription() const = 0;
20561+    };
20562+} // namespace Catch
20563+
20564+#endif // CATCH_INTERFACES_REPORTER_FACTORY_HPP_INCLUDED
20565+
20566+
20567+#ifndef CATCH_INTERFACES_TAG_ALIAS_REGISTRY_HPP_INCLUDED
20568+#define CATCH_INTERFACES_TAG_ALIAS_REGISTRY_HPP_INCLUDED
20569+
20570+#include <string>
20571+
20572+namespace Catch {
20573+
20574+    struct TagAlias;
20575+
20576+    class ITagAliasRegistry {
20577+    public:
20578+        virtual ~ITagAliasRegistry(); // = default
20579+        // Nullptr if not present
20580+        virtual TagAlias const* find( std::string const& alias ) const = 0;
20581+        virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const = 0;
20582+
20583+        static ITagAliasRegistry const& get();
20584+    };
20585+
20586+} // end namespace Catch
20587+
20588+#endif // CATCH_INTERFACES_TAG_ALIAS_REGISTRY_HPP_INCLUDED
20589+
20590+
20591+#ifndef CATCH_INTERFACES_TESTCASE_HPP_INCLUDED
20592+#define CATCH_INTERFACES_TESTCASE_HPP_INCLUDED
20593+
20594+#include <vector>
20595+
20596+namespace Catch {
20597+
20598+    struct TestCaseInfo;
20599+    class TestCaseHandle;
20600+    class IConfig;
20601+
20602+    class ITestCaseRegistry {
20603+    public:
20604+        virtual ~ITestCaseRegistry(); // = default
20605+        // TODO: this exists only for adding filenames to test cases -- let's expose this in a saner way later
20606+        virtual std::vector<TestCaseInfo* > const& getAllInfos() const = 0;
20607+        virtual std::vector<TestCaseHandle> const& getAllTests() const = 0;
20608+        virtual std::vector<TestCaseHandle> const& getAllTestsSorted( IConfig const& config ) const = 0;
20609+    };
20610+
20611+}
20612+
20613+#endif // CATCH_INTERFACES_TESTCASE_HPP_INCLUDED
20614+
20615+#endif // CATCH_INTERFACES_ALL_HPP_INCLUDED
20616+
20617+
20618+#ifndef CATCH_CASE_INSENSITIVE_COMPARISONS_HPP_INCLUDED
20619+#define CATCH_CASE_INSENSITIVE_COMPARISONS_HPP_INCLUDED
20620+
20621+
20622+namespace Catch {
20623+    namespace Detail {
20624+        //! Provides case-insensitive `op<` semantics when called
20625+        struct CaseInsensitiveLess {
20626+            bool operator()( StringRef lhs,
20627+                             StringRef rhs ) const;
20628+        };
20629+
20630+        //! Provides case-insensitive `op==` semantics when called
20631+        struct CaseInsensitiveEqualTo {
20632+            bool operator()( StringRef lhs,
20633+                             StringRef rhs ) const;
20634+        };
20635+
20636+    } // namespace Detail
20637+} // namespace Catch
20638+
20639+#endif // CATCH_CASE_INSENSITIVE_COMPARISONS_HPP_INCLUDED
20640+
20641+
20642+
20643+/** \file
20644+ * Wrapper for ANDROID_LOGWRITE configuration option
20645+ *
20646+ * We want to default to enabling it when compiled for android, but
20647+ * users of the library should also be able to disable it if they want
20648+ * to.
20649+ */
20650+
20651+#ifndef CATCH_CONFIG_ANDROID_LOGWRITE_HPP_INCLUDED
20652+#define CATCH_CONFIG_ANDROID_LOGWRITE_HPP_INCLUDED
20653+
20654+
20655+#if defined(__ANDROID__)
20656+#    define CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE
20657+#endif
20658+
20659+
20660+#if defined( CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE ) && \
20661+    !defined( CATCH_CONFIG_NO_ANDROID_LOGWRITE ) &&      \
20662+    !defined( CATCH_CONFIG_ANDROID_LOGWRITE )
20663+#    define CATCH_CONFIG_ANDROID_LOGWRITE
20664+#endif
20665+
20666+#endif // CATCH_CONFIG_ANDROID_LOGWRITE_HPP_INCLUDED
20667+
20668+
20669+
20670+/** \file
20671+ * Wrapper for UNCAUGHT_EXCEPTIONS configuration option
20672+ *
20673+ * For some functionality, Catch2 requires to know whether there is
20674+ * an active exception. Because `std::uncaught_exception` is deprecated
20675+ * in C++17, we want to use `std::uncaught_exceptions` if possible.
20676+ */
20677+
20678+#ifndef CATCH_CONFIG_UNCAUGHT_EXCEPTIONS_HPP_INCLUDED
20679+#define CATCH_CONFIG_UNCAUGHT_EXCEPTIONS_HPP_INCLUDED
20680+
20681+
20682+#if defined(_MSC_VER)
20683+#  if _MSC_VER >= 1900 // Visual Studio 2015 or newer
20684+#    define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
20685+#  endif
20686+#endif
20687+
20688+
20689+#include <exception>
20690+
20691+#if defined(__cpp_lib_uncaught_exceptions) \
20692+    && !defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS)
20693+
20694+#  define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
20695+#endif // __cpp_lib_uncaught_exceptions
20696+
20697+
20698+#if defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) \
20699+    && !defined(CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS) \
20700+    && !defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS)
20701+
20702+#  define CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
20703+#endif
20704+
20705+
20706+#endif // CATCH_CONFIG_UNCAUGHT_EXCEPTIONS_HPP_INCLUDED
20707+
20708+
20709+#ifndef CATCH_CONSOLE_COLOUR_HPP_INCLUDED
20710+#define CATCH_CONSOLE_COLOUR_HPP_INCLUDED
20711+
20712+
20713+#include <iosfwd>
20714+#include <cstdint>
20715+
20716+namespace Catch {
20717+
20718+    enum class ColourMode : std::uint8_t;
20719+    class IStream;
20720+
20721+    struct Colour {
20722+        enum Code {
20723+            None = 0,
20724+
20725+            White,
20726+            Red,
20727+            Green,
20728+            Blue,
20729+            Cyan,
20730+            Yellow,
20731+            Grey,
20732+
20733+            Bright = 0x10,
20734+
20735+            BrightRed = Bright | Red,
20736+            BrightGreen = Bright | Green,
20737+            LightGrey = Bright | Grey,
20738+            BrightWhite = Bright | White,
20739+            BrightYellow = Bright | Yellow,
20740+
20741+            // By intention
20742+            FileName = LightGrey,
20743+            Warning = BrightYellow,
20744+            ResultError = BrightRed,
20745+            ResultSuccess = BrightGreen,
20746+            ResultExpectedFailure = Warning,
20747+
20748+            Error = BrightRed,
20749+            Success = Green,
20750+            Skip = LightGrey,
20751+
20752+            OriginalExpression = Cyan,
20753+            ReconstructedExpression = BrightYellow,
20754+
20755+            SecondaryText = LightGrey,
20756+            Headers = White
20757+        };
20758+    };
20759+
20760+    class ColourImpl {
20761+    protected:
20762+        //! The associated stream of this ColourImpl instance
20763+        IStream* m_stream;
20764+    public:
20765+        ColourImpl( IStream* stream ): m_stream( stream ) {}
20766+
20767+        //! RAII wrapper around writing specific colour of text using specific
20768+        //! colour impl into a stream.
20769+        class ColourGuard {
20770+            ColourImpl const* m_colourImpl;
20771+            Colour::Code m_code;
20772+            bool m_engaged = false;
20773+
20774+        public:
20775+            //! Does **not** engage the guard/start the colour
20776+            ColourGuard( Colour::Code code,
20777+                         ColourImpl const* colour );
20778+
20779+            ColourGuard( ColourGuard const& rhs ) = delete;
20780+            ColourGuard& operator=( ColourGuard const& rhs ) = delete;
20781+
20782+            ColourGuard( ColourGuard&& rhs ) noexcept;
20783+            ColourGuard& operator=( ColourGuard&& rhs ) noexcept;
20784+
20785+            //! Removes colour _if_ the guard was engaged
20786+            ~ColourGuard();
20787+
20788+            /**
20789+             * Explicitly engages colour for given stream.
20790+             *
20791+             * The API based on operator<< should be preferred.
20792+             */
20793+            ColourGuard& engage( std::ostream& stream ) &;
20794+            /**
20795+             * Explicitly engages colour for given stream.
20796+             *
20797+             * The API based on operator<< should be preferred.
20798+             */
20799+            ColourGuard&& engage( std::ostream& stream ) &&;
20800+
20801+        private:
20802+            //! Engages the guard and starts using colour
20803+            friend std::ostream& operator<<( std::ostream& lhs,
20804+                                             ColourGuard& guard ) {
20805+                guard.engageImpl( lhs );
20806+                return lhs;
20807+            }
20808+            //! Engages the guard and starts using colour
20809+            friend std::ostream& operator<<( std::ostream& lhs,
20810+                                            ColourGuard&& guard) {
20811+                guard.engageImpl( lhs );
20812+                return lhs;
20813+            }
20814+
20815+            void engageImpl( std::ostream& stream );
20816+
20817+        };
20818+
20819+        virtual ~ColourImpl(); // = default
20820+        /**
20821+         * Creates a guard object for given colour and this colour impl
20822+         *
20823+         * **Important:**
20824+         * the guard starts disengaged, and has to be engaged explicitly.
20825+         */
20826+        ColourGuard guardColour( Colour::Code colourCode );
20827+
20828+    private:
20829+        virtual void use( Colour::Code colourCode ) const = 0;
20830+    };
20831+
20832+    //! Provides ColourImpl based on global config and target compilation platform
20833+    Detail::unique_ptr<ColourImpl> makeColourImpl( ColourMode colourSelection,
20834+                                                   IStream* stream );
20835+
20836+    //! Checks if specific colour impl has been compiled into the binary
20837+    bool isColourImplAvailable( ColourMode colourSelection );
20838+
20839+} // end namespace Catch
20840+
20841+#endif // CATCH_CONSOLE_COLOUR_HPP_INCLUDED
20842+
20843+
20844+#ifndef CATCH_CONSOLE_WIDTH_HPP_INCLUDED
20845+#define CATCH_CONSOLE_WIDTH_HPP_INCLUDED
20846+
20847+// This include must be kept so that user's configured value for CONSOLE_WIDTH
20848+// is used before we attempt to provide a default value
20849+
20850+#ifndef CATCH_CONFIG_CONSOLE_WIDTH
20851+#define CATCH_CONFIG_CONSOLE_WIDTH 80
20852+#endif
20853+
20854+#endif // CATCH_CONSOLE_WIDTH_HPP_INCLUDED
20855+
20856+
20857+#ifndef CATCH_CONTAINER_NONMEMBERS_HPP_INCLUDED
20858+#define CATCH_CONTAINER_NONMEMBERS_HPP_INCLUDED
20859+
20860+
20861+#include <cstddef>
20862+#include <initializer_list>
20863+
20864+// We want a simple polyfill over `std::empty`, `std::size` and so on
20865+// for C++14 or C++ libraries with incomplete support.
20866+// We also have to handle that MSVC std lib will happily provide these
20867+// under older standards.
20868+#if defined(CATCH_CPP17_OR_GREATER) || defined(_MSC_VER)
20869+
20870+// We are already using this header either way, so there shouldn't
20871+// be much additional overhead in including it to get the feature
20872+// test macros
20873+#include <string>
20874+
20875+#  if !defined(__cpp_lib_nonmember_container_access)
20876+#      define CATCH_CONFIG_POLYFILL_NONMEMBER_CONTAINER_ACCESS
20877+#  endif
20878+
20879+#else
20880+#define CATCH_CONFIG_POLYFILL_NONMEMBER_CONTAINER_ACCESS
20881+#endif
20882+
20883+
20884+
20885+namespace Catch {
20886+namespace Detail {
20887+
20888+#if defined(CATCH_CONFIG_POLYFILL_NONMEMBER_CONTAINER_ACCESS)
20889+    template <typename Container>
20890+    constexpr auto empty(Container const& cont) -> decltype(cont.empty()) {
20891+        return cont.empty();
20892+    }
20893+    template <typename T, std::size_t N>
20894+    constexpr bool empty(const T (&)[N]) noexcept {
20895+        // GCC < 7 does not support the const T(&)[] parameter syntax
20896+        // so we have to ignore the length explicitly
20897+        (void)N;
20898+        return false;
20899+    }
20900+    template <typename T>
20901+    constexpr bool empty(std::initializer_list<T> list) noexcept {
20902+        return list.size() > 0;
20903+    }
20904+
20905+
20906+    template <typename Container>
20907+    constexpr auto size(Container const& cont) -> decltype(cont.size()) {
20908+        return cont.size();
20909+    }
20910+    template <typename T, std::size_t N>
20911+    constexpr std::size_t size(const T(&)[N]) noexcept {
20912+        return N;
20913+    }
20914+#endif // CATCH_CONFIG_POLYFILL_NONMEMBER_CONTAINER_ACCESS
20915+
20916+} // end namespace Detail
20917+} // end namespace Catch
20918+
20919+
20920+
20921+#endif // CATCH_CONTAINER_NONMEMBERS_HPP_INCLUDED
20922+
20923+
20924+#ifndef CATCH_DEBUG_CONSOLE_HPP_INCLUDED
20925+#define CATCH_DEBUG_CONSOLE_HPP_INCLUDED
20926+
20927+#include <string>
20928+
20929+namespace Catch {
20930+    void writeToDebugConsole( std::string const& text );
20931+}
20932+
20933+#endif // CATCH_DEBUG_CONSOLE_HPP_INCLUDED
20934+
20935+
20936+#ifndef CATCH_DEBUGGER_HPP_INCLUDED
20937+#define CATCH_DEBUGGER_HPP_INCLUDED
20938+
20939+
20940+namespace Catch {
20941+    bool isDebuggerActive();
20942+}
20943+
20944+#ifdef CATCH_PLATFORM_MAC
20945+
20946+    #if defined(__i386__) || defined(__x86_64__)
20947+        #define CATCH_TRAP() __asm__("int $3\n" : : ) /* NOLINT */
20948+    #elif defined(__aarch64__)
20949+        #define CATCH_TRAP() __asm__(".inst 0xd43e0000")
20950+    #elif defined(__POWERPC__)
20951+        #define CATCH_TRAP() __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \
20952+        : : : "memory","r0","r3","r4" ) /* NOLINT */
20953+    #endif
20954+
20955+#elif defined(CATCH_PLATFORM_IPHONE)
20956+
20957+    // use inline assembler
20958+    #if defined(__i386__) || defined(__x86_64__)
20959+        #define CATCH_TRAP()  __asm__("int $3")
20960+    #elif defined(__aarch64__)
20961+        #define CATCH_TRAP()  __asm__(".inst 0xd4200000")
20962+    #elif defined(__arm__) && !defined(__thumb__)
20963+        #define CATCH_TRAP()  __asm__(".inst 0xe7f001f0")
20964+    #elif defined(__arm__) &&  defined(__thumb__)
20965+        #define CATCH_TRAP()  __asm__(".inst 0xde01")
20966+    #endif
20967+
20968+#elif defined(CATCH_PLATFORM_LINUX)
20969+    // If we can use inline assembler, do it because this allows us to break
20970+    // directly at the location of the failing check instead of breaking inside
20971+    // raise() called from it, i.e. one stack frame below.
20972+    #if defined(__GNUC__) && (defined(__i386) || defined(__x86_64))
20973+        #define CATCH_TRAP() asm volatile ("int $3") /* NOLINT */
20974+    #else // Fall back to the generic way.
20975+        #include <signal.h>
20976+
20977+        #define CATCH_TRAP() raise(SIGTRAP)
20978+    #endif
20979+#elif defined(_MSC_VER)
20980+    #define CATCH_TRAP() __debugbreak()
20981+#elif defined(__MINGW32__)
20982+    extern "C" __declspec(dllimport) void __stdcall DebugBreak();
20983+    #define CATCH_TRAP() DebugBreak()
20984+#endif
20985+
20986+#ifndef CATCH_BREAK_INTO_DEBUGGER
20987+    #ifdef CATCH_TRAP
20988+        #define CATCH_BREAK_INTO_DEBUGGER() []{ if( Catch::isDebuggerActive() ) { CATCH_TRAP(); } }()
20989+    #else
20990+        #define CATCH_BREAK_INTO_DEBUGGER() []{}()
20991+    #endif
20992+#endif
20993+
20994+#endif // CATCH_DEBUGGER_HPP_INCLUDED
20995+
20996+
20997+#ifndef CATCH_ENFORCE_HPP_INCLUDED
20998+#define CATCH_ENFORCE_HPP_INCLUDED
20999+
21000+
21001+#include <exception>
21002+
21003+namespace Catch {
21004+#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
21005+    template <typename Ex>
21006+    [[noreturn]]
21007+    void throw_exception(Ex const& e) {
21008+        throw e;
21009+    }
21010+#else // ^^ Exceptions are enabled //  Exceptions are disabled vv
21011+    [[noreturn]]
21012+    void throw_exception(std::exception const& e);
21013+#endif
21014+
21015+    [[noreturn]]
21016+    void throw_logic_error(std::string const& msg);
21017+    [[noreturn]]
21018+    void throw_domain_error(std::string const& msg);
21019+    [[noreturn]]
21020+    void throw_runtime_error(std::string const& msg);
21021+
21022+} // namespace Catch;
21023+
21024+#define CATCH_MAKE_MSG(...) \
21025+    (Catch::ReusableStringStream() << __VA_ARGS__).str()
21026+
21027+#define CATCH_INTERNAL_ERROR(...) \
21028+    Catch::throw_logic_error(CATCH_MAKE_MSG( CATCH_INTERNAL_LINEINFO << ": Internal Catch2 error: " << __VA_ARGS__))
21029+
21030+#define CATCH_ERROR(...) \
21031+    Catch::throw_domain_error(CATCH_MAKE_MSG( __VA_ARGS__ ))
21032+
21033+#define CATCH_RUNTIME_ERROR(...) \
21034+    Catch::throw_runtime_error(CATCH_MAKE_MSG( __VA_ARGS__ ))
21035+
21036+#define CATCH_ENFORCE( condition, ... ) \
21037+    do{ if( !(condition) ) CATCH_ERROR( __VA_ARGS__ ); } while(false)
21038+
21039+
21040+#endif // CATCH_ENFORCE_HPP_INCLUDED
21041+
21042+
21043+#ifndef CATCH_ENUM_VALUES_REGISTRY_HPP_INCLUDED
21044+#define CATCH_ENUM_VALUES_REGISTRY_HPP_INCLUDED
21045+
21046+
21047+#include <vector>
21048+
21049+namespace Catch {
21050+
21051+    namespace Detail {
21052+
21053+        Catch::Detail::unique_ptr<EnumInfo> makeEnumInfo( StringRef enumName, StringRef allValueNames, std::vector<int> const& values );
21054+
21055+        class EnumValuesRegistry : public IMutableEnumValuesRegistry {
21056+
21057+            std::vector<Catch::Detail::unique_ptr<EnumInfo>> m_enumInfos;
21058+
21059+            EnumInfo const& registerEnum( StringRef enumName, StringRef allValueNames, std::vector<int> const& values) override;
21060+        };
21061+
21062+        std::vector<StringRef> parseEnums( StringRef enums );
21063+
21064+    } // Detail
21065+
21066+} // Catch
21067+
21068+#endif // CATCH_ENUM_VALUES_REGISTRY_HPP_INCLUDED
21069+
21070+
21071+#ifndef CATCH_ERRNO_GUARD_HPP_INCLUDED
21072+#define CATCH_ERRNO_GUARD_HPP_INCLUDED
21073+
21074+namespace Catch {
21075+
21076+    //! Simple RAII class that stores the value of `errno`
21077+    //! at construction and restores it at destruction.
21078+    class ErrnoGuard {
21079+    public:
21080+        // Keep these outlined to avoid dragging in macros from <cerrno>
21081+
21082+        ErrnoGuard();
21083+        ~ErrnoGuard();
21084+    private:
21085+        int m_oldErrno;
21086+    };
21087+
21088+}
21089+
21090+#endif // CATCH_ERRNO_GUARD_HPP_INCLUDED
21091+
21092+
21093+#ifndef CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED
21094+#define CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED
21095+
21096+
21097+#include <vector>
21098+#include <string>
21099+
21100+namespace Catch {
21101+
21102+    class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry {
21103+    public:
21104+        ~ExceptionTranslatorRegistry() override;
21105+        void registerTranslator( Detail::unique_ptr<IExceptionTranslator>&& translator );
21106+        std::string translateActiveException() const override;
21107+
21108+    private:
21109+        ExceptionTranslators m_translators;
21110+    };
21111+}
21112+
21113+#endif // CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED
21114+
21115+
21116+#ifndef CATCH_FATAL_CONDITION_HANDLER_HPP_INCLUDED
21117+#define CATCH_FATAL_CONDITION_HANDLER_HPP_INCLUDED
21118+
21119+#include <cassert>
21120+
21121+namespace Catch {
21122+
21123+    /**
21124+     * Wrapper for platform-specific fatal error (signals/SEH) handlers
21125+     *
21126+     * Tries to be cooperative with other handlers, and not step over
21127+     * other handlers. This means that unknown structured exceptions
21128+     * are passed on, previous signal handlers are called, and so on.
21129+     *
21130+     * Can only be instantiated once, and assumes that once a signal
21131+     * is caught, the binary will end up terminating. Thus, there
21132+     */
21133+    class FatalConditionHandler {
21134+        bool m_started = false;
21135+
21136+        // Install/disengage implementation for specific platform.
21137+        // Should be if-defed to work on current platform, can assume
21138+        // engage-disengage 1:1 pairing.
21139+        void engage_platform();
21140+        void disengage_platform() noexcept;
21141+    public:
21142+        // Should also have platform-specific implementations as needed
21143+        FatalConditionHandler();
21144+        ~FatalConditionHandler();
21145+
21146+        void engage() {
21147+            assert(!m_started && "Handler cannot be installed twice.");
21148+            m_started = true;
21149+            engage_platform();
21150+        }
21151+
21152+        void disengage() noexcept {
21153+            assert(m_started && "Handler cannot be uninstalled without being installed first");
21154+            m_started = false;
21155+            disengage_platform();
21156+        }
21157+    };
21158+
21159+    //! Simple RAII guard for (dis)engaging the FatalConditionHandler
21160+    class FatalConditionHandlerGuard {
21161+        FatalConditionHandler* m_handler;
21162+    public:
21163+        FatalConditionHandlerGuard(FatalConditionHandler* handler):
21164+            m_handler(handler) {
21165+            m_handler->engage();
21166+        }
21167+        ~FatalConditionHandlerGuard() {
21168+            m_handler->disengage();
21169+        }
21170+    };
21171+
21172+} // end namespace Catch
21173+
21174+#endif // CATCH_FATAL_CONDITION_HANDLER_HPP_INCLUDED
21175+
21176+
21177+#ifndef CATCH_FLOATING_POINT_HELPERS_HPP_INCLUDED
21178+#define CATCH_FLOATING_POINT_HELPERS_HPP_INCLUDED
21179+
21180+
21181+#include <cassert>
21182+#include <cmath>
21183+#include <cstdint>
21184+#include <utility>
21185+#include <limits>
21186+
21187+namespace Catch {
21188+    namespace Detail {
21189+
21190+        uint32_t convertToBits(float f);
21191+        uint64_t convertToBits(double d);
21192+
21193+        // Used when we know we want == comparison of two doubles
21194+        // to centralize warning suppression
21195+        bool directCompare( float lhs, float rhs );
21196+        bool directCompare( double lhs, double rhs );
21197+
21198+    } // end namespace Detail
21199+
21200+
21201+
21202+#if defined( __GNUC__ ) || defined( __clang__ )
21203+#    pragma GCC diagnostic push
21204+    // We do a bunch of direct compensations of floating point numbers,
21205+    // because we know what we are doing and actually do want the direct
21206+    // comparison behaviour.
21207+#    pragma GCC diagnostic ignored "-Wfloat-equal"
21208+#endif
21209+
21210+    /**
21211+     * Calculates the ULP distance between two floating point numbers
21212+     *
21213+     * The ULP distance of two floating point numbers is the count of
21214+     * valid floating point numbers representable between them.
21215+     *
21216+     * There are some exceptions between how this function counts the
21217+     * distance, and the interpretation of the standard as implemented.
21218+     * by e.g. `nextafter`. For this function it always holds that:
21219+     * * `(x == y) => ulpDistance(x, y) == 0` (so `ulpDistance(-0, 0) == 0`)
21220+     * * `ulpDistance(maxFinite, INF) == 1`
21221+     * * `ulpDistance(x, -x) == 2 * ulpDistance(x, 0)`
21222+     *
21223+     * \pre `!isnan( lhs )`
21224+     * \pre `!isnan( rhs )`
21225+     * \pre floating point numbers are represented in IEEE-754 format
21226+     */
21227+    template <typename FP>
21228+    uint64_t ulpDistance( FP lhs, FP rhs ) {
21229+        assert( std::numeric_limits<FP>::is_iec559 &&
21230+            "ulpDistance assumes IEEE-754 format for floating point types" );
21231+        assert( !Catch::isnan( lhs ) &&
21232+                "Distance between NaN and number is not meaningful" );
21233+        assert( !Catch::isnan( rhs ) &&
21234+                "Distance between NaN and number is not meaningful" );
21235+
21236+        // We want X == Y to imply 0 ULP distance even if X and Y aren't
21237+        // bit-equal (-0 and 0), or X - Y != 0 (same sign infinities).
21238+        if ( lhs == rhs ) { return 0; }
21239+
21240+        // We need a properly typed positive zero for type inference.
21241+        static constexpr FP positive_zero{};
21242+
21243+        // We want to ensure that +/- 0 is always represented as positive zero
21244+        if ( lhs == positive_zero ) { lhs = positive_zero; }
21245+        if ( rhs == positive_zero ) { rhs = positive_zero; }
21246+
21247+        // If arguments have different signs, we can handle them by summing
21248+        // how far are they from 0 each.
21249+        if ( std::signbit( lhs ) != std::signbit( rhs ) ) {
21250+            return ulpDistance( std::abs( lhs ), positive_zero ) +
21251+                   ulpDistance( std::abs( rhs ), positive_zero );
21252+        }
21253+
21254+        // When both lhs and rhs are of the same sign, we can just
21255+        // read the numbers bitwise as integers, and then subtract them
21256+        // (assuming IEEE).
21257+        uint64_t lc = Detail::convertToBits( lhs );
21258+        uint64_t rc = Detail::convertToBits( rhs );
21259+
21260+        // The ulp distance between two numbers is symmetric, so to avoid
21261+        // dealing with overflows we want the bigger converted number on the lhs
21262+        if ( lc < rc ) {
21263+            std::swap( lc, rc );
21264+        }
21265+
21266+        return lc - rc;
21267+    }
21268+
21269+#if defined( __GNUC__ ) || defined( __clang__ )
21270+#    pragma GCC diagnostic pop
21271+#endif
21272+
21273+
21274+} // end namespace Catch
21275+
21276+#endif // CATCH_FLOATING_POINT_HELPERS_HPP_INCLUDED
21277+
21278+
21279+#ifndef CATCH_GETENV_HPP_INCLUDED
21280+#define CATCH_GETENV_HPP_INCLUDED
21281+
21282+namespace Catch {
21283+namespace Detail {
21284+
21285+    //! Wrapper over `std::getenv` that compiles on UWP (and always returns nullptr there)
21286+    char const* getEnv(char const* varName);
21287+
21288+}
21289+}
21290+
21291+#endif // CATCH_GETENV_HPP_INCLUDED
21292+
21293+
21294+#ifndef CATCH_IS_PERMUTATION_HPP_INCLUDED
21295+#define CATCH_IS_PERMUTATION_HPP_INCLUDED
21296+
21297+#include <algorithm>
21298+#include <iterator>
21299+
21300+namespace Catch {
21301+    namespace Detail {
21302+
21303+        template <typename ForwardIter,
21304+                  typename Sentinel,
21305+                  typename T,
21306+                  typename Comparator>
21307+        ForwardIter find_sentinel( ForwardIter start,
21308+                                   Sentinel sentinel,
21309+                                   T const& value,
21310+                                   Comparator cmp ) {
21311+            while ( start != sentinel ) {
21312+                if ( cmp( *start, value ) ) { break; }
21313+                ++start;
21314+            }
21315+            return start;
21316+        }
21317+
21318+        template <typename ForwardIter,
21319+                  typename Sentinel,
21320+                  typename T,
21321+                  typename Comparator>
21322+        std::ptrdiff_t count_sentinel( ForwardIter start,
21323+                                       Sentinel sentinel,
21324+                                       T const& value,
21325+                                       Comparator cmp ) {
21326+            std::ptrdiff_t count = 0;
21327+            while ( start != sentinel ) {
21328+                if ( cmp( *start, value ) ) { ++count; }
21329+                ++start;
21330+            }
21331+            return count;
21332+        }
21333+
21334+        template <typename ForwardIter, typename Sentinel>
21335+        std::enable_if_t<!std::is_same<ForwardIter, Sentinel>::value,
21336+                         std::ptrdiff_t>
21337+        sentinel_distance( ForwardIter iter, const Sentinel sentinel ) {
21338+            std::ptrdiff_t dist = 0;
21339+            while ( iter != sentinel ) {
21340+                ++iter;
21341+                ++dist;
21342+            }
21343+            return dist;
21344+        }
21345+
21346+        template <typename ForwardIter>
21347+        std::ptrdiff_t sentinel_distance( ForwardIter first,
21348+                                          ForwardIter last ) {
21349+            return std::distance( first, last );
21350+        }
21351+
21352+        template <typename ForwardIter1,
21353+                  typename Sentinel1,
21354+                  typename ForwardIter2,
21355+                  typename Sentinel2,
21356+                  typename Comparator>
21357+        bool check_element_counts( ForwardIter1 first_1,
21358+                                   const Sentinel1 end_1,
21359+                                   ForwardIter2 first_2,
21360+                                   const Sentinel2 end_2,
21361+                                   Comparator cmp ) {
21362+            auto cursor = first_1;
21363+            while ( cursor != end_1 ) {
21364+                if ( find_sentinel( first_1, cursor, *cursor, cmp ) ==
21365+                     cursor ) {
21366+                    // we haven't checked this element yet
21367+                    const auto count_in_range_2 =
21368+                        count_sentinel( first_2, end_2, *cursor, cmp );
21369+                    // Not a single instance in 2nd range, so it cannot be a
21370+                    // permutation of 1st range
21371+                    if ( count_in_range_2 == 0 ) { return false; }
21372+
21373+                    const auto count_in_range_1 =
21374+                        count_sentinel( cursor, end_1, *cursor, cmp );
21375+                    if ( count_in_range_1 != count_in_range_2 ) {
21376+                        return false;
21377+                    }
21378+                }
21379+
21380+                ++cursor;
21381+            }
21382+
21383+            return true;
21384+        }
21385+
21386+        template <typename ForwardIter1,
21387+                  typename Sentinel1,
21388+                  typename ForwardIter2,
21389+                  typename Sentinel2,
21390+                  typename Comparator>
21391+        bool is_permutation( ForwardIter1 first_1,
21392+                             const Sentinel1 end_1,
21393+                             ForwardIter2 first_2,
21394+                             const Sentinel2 end_2,
21395+                             Comparator cmp ) {
21396+            // TODO: no optimization for stronger iterators, because we would also have to constrain on sentinel vs not sentinel types
21397+            // TODO: Comparator has to be "both sides", e.g. a == b => b == a
21398+            // This skips shared prefix of the two ranges
21399+            while (first_1 != end_1 && first_2 != end_2 && cmp(*first_1, *first_2)) {
21400+                ++first_1;
21401+                ++first_2;
21402+            }
21403+
21404+            // We need to handle case where at least one of the ranges has no more elements
21405+            if (first_1 == end_1 || first_2 == end_2) {
21406+                return first_1 == end_1 && first_2 == end_2;
21407+            }
21408+
21409+            // pair counting is n**2, so we pay linear walk to compare the sizes first
21410+            auto dist_1 = sentinel_distance( first_1, end_1 );
21411+            auto dist_2 = sentinel_distance( first_2, end_2 );
21412+
21413+            if (dist_1 != dist_2) { return false; }
21414+
21415+            // Since we do not try to handle stronger iterators pair (e.g.
21416+            // bidir) optimally, the only thing left to do is to check counts in
21417+            // the remaining ranges.
21418+            return check_element_counts( first_1, end_1, first_2, end_2, cmp );
21419+        }
21420+
21421+    } // namespace Detail
21422+} // namespace Catch
21423+
21424+#endif // CATCH_IS_PERMUTATION_HPP_INCLUDED
21425+
21426+
21427+#ifndef CATCH_ISTREAM_HPP_INCLUDED
21428+#define CATCH_ISTREAM_HPP_INCLUDED
21429+
21430+
21431+#include <iosfwd>
21432+#include <cstddef>
21433+#include <ostream>
21434+#include <string>
21435+
21436+namespace Catch {
21437+
21438+    class IStream {
21439+    public:
21440+        virtual ~IStream(); // = default
21441+        virtual std::ostream& stream() = 0;
21442+        /**
21443+         * Best guess on whether the instance is writing to a console (e.g. via stdout/stderr)
21444+         *
21445+         * This is useful for e.g. Win32 colour support, because the Win32
21446+         * API manipulates console directly, unlike POSIX escape codes,
21447+         * that can be written anywhere.
21448+         *
21449+         * Due to variety of ways to change where the stdout/stderr is
21450+         * _actually_ being written, users should always assume that
21451+         * the answer might be wrong.
21452+         */
21453+        virtual bool isConsole() const { return false; }
21454+    };
21455+
21456+    /**
21457+     * Creates a stream wrapper that writes to specific file.
21458+     *
21459+     * Also recognizes 4 special filenames
21460+     * * `-` for stdout
21461+     * * `%stdout` for stdout
21462+     * * `%stderr` for stderr
21463+     * * `%debug` for platform specific debugging output
21464+     *
21465+     * \throws if passed an unrecognized %-prefixed stream
21466+     */
21467+    auto makeStream( std::string const& filename ) -> Detail::unique_ptr<IStream>;
21468+
21469+}
21470+
21471+#endif // CATCH_STREAM_HPP_INCLUDED
21472+
21473+
21474+#ifndef CATCH_JSONWRITER_HPP_INCLUDED
21475+#define CATCH_JSONWRITER_HPP_INCLUDED
21476+
21477+
21478+#include <cstdint>
21479+#include <sstream>
21480+
21481+namespace Catch {
21482+    class JsonObjectWriter;
21483+    class JsonArrayWriter;
21484+
21485+    struct JsonUtils {
21486+        static void indent( std::ostream& os, std::uint64_t level );
21487+        static void appendCommaNewline( std::ostream& os,
21488+                                        bool& should_comma,
21489+                                        std::uint64_t level );
21490+    };
21491+
21492+    class JsonValueWriter {
21493+    public:
21494+        JsonValueWriter( std::ostream& os );
21495+        JsonValueWriter( std::ostream& os, std::uint64_t indent_level );
21496+
21497+        JsonObjectWriter writeObject() &&;
21498+        JsonArrayWriter writeArray() &&;
21499+
21500+        template <typename T>
21501+        void write( T const& value ) && {
21502+            writeImpl( value, !std::is_arithmetic<T>::value );
21503+        }
21504+        void write( StringRef value ) &&;
21505+        void write( bool value ) &&;
21506+
21507+    private:
21508+        void writeImpl( StringRef value, bool quote );
21509+
21510+        // Without this SFINAE, this overload is a better match
21511+        // for `std::string`, `char const*`, `char const[N]` args.
21512+        // While it would still work, it would cause code bloat
21513+        // and multiple iteration over the strings
21514+        template <typename T,
21515+                  typename = typename std::enable_if_t<
21516+                      !std::is_convertible<T, StringRef>::value>>
21517+        void writeImpl( T const& value, bool quote_value ) {
21518+            m_sstream << value;
21519+            writeImpl( m_sstream.str(), quote_value );
21520+        }
21521+
21522+        std::ostream& m_os;
21523+        std::stringstream m_sstream;
21524+        std::uint64_t m_indent_level;
21525+    };
21526+
21527+    class JsonObjectWriter {
21528+    public:
21529+        JsonObjectWriter( std::ostream& os );
21530+        JsonObjectWriter( std::ostream& os, std::uint64_t indent_level );
21531+
21532+        JsonObjectWriter( JsonObjectWriter&& source ) noexcept;
21533+        JsonObjectWriter& operator=( JsonObjectWriter&& source ) = delete;
21534+
21535+        ~JsonObjectWriter();
21536+
21537+        JsonValueWriter write( StringRef key );
21538+
21539+    private:
21540+        std::ostream& m_os;
21541+        std::uint64_t m_indent_level;
21542+        bool m_should_comma = false;
21543+        bool m_active = true;
21544+    };
21545+
21546+    class JsonArrayWriter {
21547+    public:
21548+        JsonArrayWriter( std::ostream& os );
21549+        JsonArrayWriter( std::ostream& os, std::uint64_t indent_level );
21550+
21551+        JsonArrayWriter( JsonArrayWriter&& source ) noexcept;
21552+        JsonArrayWriter& operator=( JsonArrayWriter&& source ) = delete;
21553+
21554+        ~JsonArrayWriter();
21555+
21556+        JsonObjectWriter writeObject();
21557+        JsonArrayWriter writeArray();
21558+
21559+        template <typename T>
21560+        JsonArrayWriter& write( T const& value ) {
21561+            return writeImpl( value );
21562+        }
21563+
21564+        JsonArrayWriter& write( bool value );
21565+
21566+    private:
21567+        template <typename T>
21568+        JsonArrayWriter& writeImpl( T const& value ) {
21569+            JsonUtils::appendCommaNewline(
21570+                m_os, m_should_comma, m_indent_level + 1 );
21571+            JsonValueWriter{ m_os }.write( value );
21572+
21573+            return *this;
21574+        }
21575+
21576+        std::ostream& m_os;
21577+        std::uint64_t m_indent_level;
21578+        bool m_should_comma = false;
21579+        bool m_active = true;
21580+    };
21581+
21582+} // namespace Catch
21583+
21584+#endif // CATCH_JSONWRITER_HPP_INCLUDED
21585+
21586+
21587+#ifndef CATCH_LEAK_DETECTOR_HPP_INCLUDED
21588+#define CATCH_LEAK_DETECTOR_HPP_INCLUDED
21589+
21590+namespace Catch {
21591+
21592+    struct LeakDetector {
21593+        LeakDetector();
21594+        ~LeakDetector();
21595+    };
21596+
21597+}
21598+#endif // CATCH_LEAK_DETECTOR_HPP_INCLUDED
21599+
21600+
21601+#ifndef CATCH_LIST_HPP_INCLUDED
21602+#define CATCH_LIST_HPP_INCLUDED
21603+
21604+
21605+#include <set>
21606+#include <string>
21607+
21608+
21609+namespace Catch {
21610+
21611+    class IEventListener;
21612+    class Config;
21613+
21614+
21615+    struct ReporterDescription {
21616+        std::string name, description;
21617+    };
21618+    struct ListenerDescription {
21619+        StringRef name;
21620+        std::string description;
21621+    };
21622+
21623+    struct TagInfo {
21624+        void add(StringRef spelling);
21625+        std::string all() const;
21626+
21627+        std::set<StringRef> spellings;
21628+        std::size_t count = 0;
21629+    };
21630+
21631+    bool list( IEventListener& reporter, Config const& config );
21632+
21633+} // end namespace Catch
21634+
21635+#endif // CATCH_LIST_HPP_INCLUDED
21636+
21637+
21638+#ifndef CATCH_OUTPUT_REDIRECT_HPP_INCLUDED
21639+#define CATCH_OUTPUT_REDIRECT_HPP_INCLUDED
21640+
21641+
21642+#include <cstdio>
21643+#include <iosfwd>
21644+#include <string>
21645+
21646+namespace Catch {
21647+
21648+    class RedirectedStream {
21649+        std::ostream& m_originalStream;
21650+        std::ostream& m_redirectionStream;
21651+        std::streambuf* m_prevBuf;
21652+
21653+    public:
21654+        RedirectedStream( std::ostream& originalStream, std::ostream& redirectionStream );
21655+        ~RedirectedStream();
21656+    };
21657+
21658+    class RedirectedStdOut {
21659+        ReusableStringStream m_rss;
21660+        RedirectedStream m_cout;
21661+    public:
21662+        RedirectedStdOut();
21663+        auto str() const -> std::string;
21664+    };
21665+
21666+    // StdErr has two constituent streams in C++, std::cerr and std::clog
21667+    // This means that we need to redirect 2 streams into 1 to keep proper
21668+    // order of writes
21669+    class RedirectedStdErr {
21670+        ReusableStringStream m_rss;
21671+        RedirectedStream m_cerr;
21672+        RedirectedStream m_clog;
21673+    public:
21674+        RedirectedStdErr();
21675+        auto str() const -> std::string;
21676+    };
21677+
21678+    class RedirectedStreams {
21679+    public:
21680+        RedirectedStreams(RedirectedStreams const&) = delete;
21681+        RedirectedStreams& operator=(RedirectedStreams const&) = delete;
21682+        RedirectedStreams(RedirectedStreams&&) = delete;
21683+        RedirectedStreams& operator=(RedirectedStreams&&) = delete;
21684+
21685+        RedirectedStreams(std::string& redirectedCout, std::string& redirectedCerr);
21686+        ~RedirectedStreams();
21687+    private:
21688+        std::string& m_redirectedCout;
21689+        std::string& m_redirectedCerr;
21690+        RedirectedStdOut m_redirectedStdOut;
21691+        RedirectedStdErr m_redirectedStdErr;
21692+    };
21693+
21694+#if defined(CATCH_CONFIG_NEW_CAPTURE)
21695+
21696+    // Windows's implementation of std::tmpfile is terrible (it tries
21697+    // to create a file inside system folder, thus requiring elevated
21698+    // privileges for the binary), so we have to use tmpnam(_s) and
21699+    // create the file ourselves there.
21700+    class TempFile {
21701+    public:
21702+        TempFile(TempFile const&) = delete;
21703+        TempFile& operator=(TempFile const&) = delete;
21704+        TempFile(TempFile&&) = delete;
21705+        TempFile& operator=(TempFile&&) = delete;
21706+
21707+        TempFile();
21708+        ~TempFile();
21709+
21710+        std::FILE* getFile();
21711+        std::string getContents();
21712+
21713+    private:
21714+        std::FILE* m_file = nullptr;
21715+    #if defined(_MSC_VER)
21716+        char m_buffer[L_tmpnam] = { 0 };
21717+    #endif
21718+    };
21719+
21720+
21721+    class OutputRedirect {
21722+    public:
21723+        OutputRedirect(OutputRedirect const&) = delete;
21724+        OutputRedirect& operator=(OutputRedirect const&) = delete;
21725+        OutputRedirect(OutputRedirect&&) = delete;
21726+        OutputRedirect& operator=(OutputRedirect&&) = delete;
21727+
21728+
21729+        OutputRedirect(std::string& stdout_dest, std::string& stderr_dest);
21730+        ~OutputRedirect();
21731+
21732+    private:
21733+        int m_originalStdout = -1;
21734+        int m_originalStderr = -1;
21735+        TempFile m_stdoutFile;
21736+        TempFile m_stderrFile;
21737+        std::string& m_stdoutDest;
21738+        std::string& m_stderrDest;
21739+    };
21740+
21741+#endif
21742+
21743+} // end namespace Catch
21744+
21745+#endif // CATCH_OUTPUT_REDIRECT_HPP_INCLUDED
21746+
21747+
21748+#ifndef CATCH_PARSE_NUMBERS_HPP_INCLUDED
21749+#define CATCH_PARSE_NUMBERS_HPP_INCLUDED
21750+
21751+
21752+#include <string>
21753+
21754+namespace Catch {
21755+
21756+    /**
21757+     * Parses unsigned int from the input, using provided base
21758+     *
21759+     * Effectively a wrapper around std::stoul but with better error checking
21760+     * e.g. "-1" is rejected, instead of being parsed as UINT_MAX.
21761+     */
21762+    Optional<unsigned int> parseUInt(std::string const& input, int base = 10);
21763+}
21764+
21765+#endif // CATCH_PARSE_NUMBERS_HPP_INCLUDED
21766+
21767+
21768+#ifndef CATCH_REPORTER_REGISTRY_HPP_INCLUDED
21769+#define CATCH_REPORTER_REGISTRY_HPP_INCLUDED
21770+
21771+
21772+#include <map>
21773+#include <string>
21774+#include <vector>
21775+
21776+namespace Catch {
21777+
21778+    class IEventListener;
21779+    using IEventListenerPtr = Detail::unique_ptr<IEventListener>;
21780+    class IReporterFactory;
21781+    using IReporterFactoryPtr = Detail::unique_ptr<IReporterFactory>;
21782+    struct ReporterConfig;
21783+    class EventListenerFactory;
21784+
21785+    class ReporterRegistry {
21786+        struct ReporterRegistryImpl;
21787+        Detail::unique_ptr<ReporterRegistryImpl> m_impl;
21788+
21789+    public:
21790+        ReporterRegistry();
21791+        ~ReporterRegistry(); // = default;
21792+
21793+        IEventListenerPtr create( std::string const& name,
21794+                                  ReporterConfig&& config ) const;
21795+
21796+        void registerReporter( std::string const& name,
21797+                               IReporterFactoryPtr factory );
21798+
21799+        void
21800+        registerListener( Detail::unique_ptr<EventListenerFactory> factory );
21801+
21802+        std::map<std::string,
21803+                 IReporterFactoryPtr,
21804+                 Detail::CaseInsensitiveLess> const&
21805+        getFactories() const;
21806+
21807+        std::vector<Detail::unique_ptr<EventListenerFactory>> const&
21808+        getListeners() const;
21809+    };
21810+
21811+} // end namespace Catch
21812+
21813+#endif // CATCH_REPORTER_REGISTRY_HPP_INCLUDED
21814+
21815+
21816+#ifndef CATCH_RUN_CONTEXT_HPP_INCLUDED
21817+#define CATCH_RUN_CONTEXT_HPP_INCLUDED
21818+
21819+
21820+
21821+#ifndef CATCH_TEST_CASE_TRACKER_HPP_INCLUDED
21822+#define CATCH_TEST_CASE_TRACKER_HPP_INCLUDED
21823+
21824+
21825+#include <string>
21826+#include <vector>
21827+
21828+namespace Catch {
21829+namespace TestCaseTracking {
21830+
21831+    struct NameAndLocation {
21832+        std::string name;
21833+        SourceLineInfo location;
21834+
21835+        NameAndLocation( std::string&& _name, SourceLineInfo const& _location );
21836+        friend bool operator==(NameAndLocation const& lhs, NameAndLocation const& rhs) {
21837+            // This is a very cheap check that should have a very high hit rate.
21838+            // If we get to SourceLineInfo::operator==, we will redo it, but the
21839+            // cost of repeating is trivial at that point (we will be paying
21840+            // multiple strcmp/memcmps at that point).
21841+            if ( lhs.location.line != rhs.location.line ) { return false; }
21842+            return lhs.name == rhs.name && lhs.location == rhs.location;
21843+        }
21844+        friend bool operator!=(NameAndLocation const& lhs,
21845+                               NameAndLocation const& rhs) {
21846+            return !( lhs == rhs );
21847+        }
21848+    };
21849+
21850+    /**
21851+     * This is a variant of `NameAndLocation` that does not own the name string
21852+     *
21853+     * This avoids extra allocations when trying to locate a tracker by its
21854+     * name and location, as long as we make sure that trackers only keep
21855+     * around the owning variant.
21856+     */
21857+    struct NameAndLocationRef {
21858+        StringRef name;
21859+        SourceLineInfo location;
21860+
21861+        constexpr NameAndLocationRef( StringRef name_,
21862+                                      SourceLineInfo location_ ):
21863+            name( name_ ), location( location_ ) {}
21864+
21865+        friend bool operator==( NameAndLocation const& lhs,
21866+                                NameAndLocationRef const& rhs ) {
21867+            // This is a very cheap check that should have a very high hit rate.
21868+            // If we get to SourceLineInfo::operator==, we will redo it, but the
21869+            // cost of repeating is trivial at that point (we will be paying
21870+            // multiple strcmp/memcmps at that point).
21871+            if ( lhs.location.line != rhs.location.line ) { return false; }
21872+            return StringRef( lhs.name ) == rhs.name &&
21873+                   lhs.location == rhs.location;
21874+        }
21875+        friend bool operator==( NameAndLocationRef const& lhs,
21876+                                NameAndLocation const& rhs ) {
21877+            return rhs == lhs;
21878+        }
21879+    };
21880+
21881+    class ITracker;
21882+
21883+    using ITrackerPtr = Catch::Detail::unique_ptr<ITracker>;
21884+
21885+    class ITracker {
21886+        NameAndLocation m_nameAndLocation;
21887+
21888+        using Children = std::vector<ITrackerPtr>;
21889+
21890+    protected:
21891+        enum CycleState {
21892+            NotStarted,
21893+            Executing,
21894+            ExecutingChildren,
21895+            NeedsAnotherRun,
21896+            CompletedSuccessfully,
21897+            Failed
21898+        };
21899+
21900+        ITracker* m_parent = nullptr;
21901+        Children m_children;
21902+        CycleState m_runState = NotStarted;
21903+
21904+    public:
21905+        ITracker( NameAndLocation&& nameAndLoc, ITracker* parent ):
21906+            m_nameAndLocation( CATCH_MOVE(nameAndLoc) ),
21907+            m_parent( parent )
21908+        {}
21909+
21910+
21911+        // static queries
21912+        NameAndLocation const& nameAndLocation() const {
21913+            return m_nameAndLocation;
21914+        }
21915+        ITracker* parent() const {
21916+            return m_parent;
21917+        }
21918+
21919+        virtual ~ITracker(); // = default
21920+
21921+
21922+        // dynamic queries
21923+
21924+        //! Returns true if tracker run to completion (successfully or not)
21925+        virtual bool isComplete() const = 0;
21926+        //! Returns true if tracker run to completion successfully
21927+        bool isSuccessfullyCompleted() const {
21928+            return m_runState == CompletedSuccessfully;
21929+        }
21930+        //! Returns true if tracker has started but hasn't been completed
21931+        bool isOpen() const;
21932+        //! Returns true iff tracker has started
21933+        bool hasStarted() const;
21934+
21935+        // actions
21936+        virtual void close() = 0; // Successfully complete
21937+        virtual void fail() = 0;
21938+        void markAsNeedingAnotherRun();
21939+
21940+        //! Register a nested ITracker
21941+        void addChild( ITrackerPtr&& child );
21942+        /**
21943+         * Returns ptr to specific child if register with this tracker.
21944+         *
21945+         * Returns nullptr if not found.
21946+         */
21947+        ITracker* findChild( NameAndLocationRef const& nameAndLocation );
21948+        //! Have any children been added?
21949+        bool hasChildren() const {
21950+            return !m_children.empty();
21951+        }
21952+
21953+
21954+        //! Marks tracker as executing a child, doing se recursively up the tree
21955+        void openChild();
21956+
21957+        /**
21958+         * Returns true if the instance is a section tracker
21959+         *
21960+         * Subclasses should override to true if they are, replaces RTTI
21961+         * for internal debug checks.
21962+         */
21963+        virtual bool isSectionTracker() const;
21964+        /**
21965+         * Returns true if the instance is a generator tracker
21966+         *
21967+         * Subclasses should override to true if they are, replaces RTTI
21968+         * for internal debug checks.
21969+         */
21970+        virtual bool isGeneratorTracker() const;
21971+    };
21972+
21973+    class TrackerContext {
21974+
21975+        enum RunState {
21976+            NotStarted,
21977+            Executing,
21978+            CompletedCycle
21979+        };
21980+
21981+        ITrackerPtr m_rootTracker;
21982+        ITracker* m_currentTracker = nullptr;
21983+        RunState m_runState = NotStarted;
21984+
21985+    public:
21986+
21987+        ITracker& startRun();
21988+
21989+        void startCycle() {
21990+            m_currentTracker = m_rootTracker.get();
21991+            m_runState = Executing;
21992+        }
21993+        void completeCycle();
21994+
21995+        bool completedCycle() const;
21996+        ITracker& currentTracker() { return *m_currentTracker; }
21997+        void setCurrentTracker( ITracker* tracker );
21998+    };
21999+
22000+    class TrackerBase : public ITracker {
22001+    protected:
22002+
22003+        TrackerContext& m_ctx;
22004+
22005+    public:
22006+        TrackerBase( NameAndLocation&& nameAndLocation, TrackerContext& ctx, ITracker* parent );
22007+
22008+        bool isComplete() const override;
22009+
22010+        void open();
22011+
22012+        void close() override;
22013+        void fail() override;
22014+
22015+    private:
22016+        void moveToParent();
22017+        void moveToThis();
22018+    };
22019+
22020+    class SectionTracker : public TrackerBase {
22021+        std::vector<StringRef> m_filters;
22022+        // Note that lifetime-wise we piggy back off the name stored in the `ITracker` parent`.
22023+        // Currently it allocates owns the name, so this is safe. If it is later refactored
22024+        // to not own the name, the name still has to outlive the `ITracker` parent, so
22025+        // this should still be safe.
22026+        StringRef m_trimmed_name;
22027+    public:
22028+        SectionTracker( NameAndLocation&& nameAndLocation, TrackerContext& ctx, ITracker* parent );
22029+
22030+        bool isSectionTracker() const override;
22031+
22032+        bool isComplete() const override;
22033+
22034+        static SectionTracker& acquire( TrackerContext& ctx, NameAndLocationRef const& nameAndLocation );
22035+
22036+        void tryOpen();
22037+
22038+        void addInitialFilters( std::vector<std::string> const& filters );
22039+        void addNextFilters( std::vector<StringRef> const& filters );
22040+        //! Returns filters active in this tracker
22041+        std::vector<StringRef> const& getFilters() const { return m_filters; }
22042+        //! Returns whitespace-trimmed name of the tracked section
22043+        StringRef trimmedName() const;
22044+    };
22045+
22046+} // namespace TestCaseTracking
22047+
22048+using TestCaseTracking::ITracker;
22049+using TestCaseTracking::TrackerContext;
22050+using TestCaseTracking::SectionTracker;
22051+
22052+} // namespace Catch
22053+
22054+#endif // CATCH_TEST_CASE_TRACKER_HPP_INCLUDED
22055+
22056+#include <string>
22057+
22058+namespace Catch {
22059+
22060+    class IGeneratorTracker;
22061+    class IConfig;
22062+    class IEventListener;
22063+    using IEventListenerPtr = Detail::unique_ptr<IEventListener>;
22064+
22065+    ///////////////////////////////////////////////////////////////////////////
22066+
22067+    class RunContext final : public IResultCapture {
22068+
22069+    public:
22070+        RunContext( RunContext const& ) = delete;
22071+        RunContext& operator =( RunContext const& ) = delete;
22072+
22073+        explicit RunContext( IConfig const* _config, IEventListenerPtr&& reporter );
22074+
22075+        ~RunContext() override;
22076+
22077+        Totals runTest(TestCaseHandle const& testCase);
22078+
22079+    public: // IResultCapture
22080+
22081+        // Assertion handlers
22082+        void handleExpr
22083+                (   AssertionInfo const& info,
22084+                    ITransientExpression const& expr,
22085+                    AssertionReaction& reaction ) override;
22086+        void handleMessage
22087+                (   AssertionInfo const& info,
22088+                    ResultWas::OfType resultType,
22089+                    StringRef message,
22090+                    AssertionReaction& reaction ) override;
22091+        void handleUnexpectedExceptionNotThrown
22092+                (   AssertionInfo const& info,
22093+                    AssertionReaction& reaction ) override;
22094+        void handleUnexpectedInflightException
22095+                (   AssertionInfo const& info,
22096+                    std::string&& message,
22097+                    AssertionReaction& reaction ) override;
22098+        void handleIncomplete
22099+                (   AssertionInfo const& info ) override;
22100+        void handleNonExpr
22101+                (   AssertionInfo const &info,
22102+                    ResultWas::OfType resultType,
22103+                    AssertionReaction &reaction ) override;
22104+
22105+        void notifyAssertionStarted( AssertionInfo const& info ) override;
22106+        bool sectionStarted( StringRef sectionName,
22107+                             SourceLineInfo const& sectionLineInfo,
22108+                             Counts& assertions ) override;
22109+
22110+        void sectionEnded( SectionEndInfo&& endInfo ) override;
22111+        void sectionEndedEarly( SectionEndInfo&& endInfo ) override;
22112+
22113+        IGeneratorTracker*
22114+        acquireGeneratorTracker( StringRef generatorName,
22115+                                 SourceLineInfo const& lineInfo ) override;
22116+        IGeneratorTracker* createGeneratorTracker(
22117+            StringRef generatorName,
22118+            SourceLineInfo lineInfo,
22119+            Generators::GeneratorBasePtr&& generator ) override;
22120+
22121+
22122+        void benchmarkPreparing( StringRef name ) override;
22123+        void benchmarkStarting( BenchmarkInfo const& info ) override;
22124+        void benchmarkEnded( BenchmarkStats<> const& stats ) override;
22125+        void benchmarkFailed( StringRef error ) override;
22126+
22127+        void pushScopedMessage( MessageInfo const& message ) override;
22128+        void popScopedMessage( MessageInfo const& message ) override;
22129+
22130+        void emplaceUnscopedMessage( MessageBuilder&& builder ) override;
22131+
22132+        std::string getCurrentTestName() const override;
22133+
22134+        const AssertionResult* getLastResult() const override;
22135+
22136+        void exceptionEarlyReported() override;
22137+
22138+        void handleFatalErrorCondition( StringRef message ) override;
22139+
22140+        bool lastAssertionPassed() override;
22141+
22142+        void assertionPassed() override;
22143+
22144+    public:
22145+        // !TBD We need to do this another way!
22146+        bool aborting() const;
22147+
22148+    private:
22149+
22150+        void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr );
22151+        void invokeActiveTestCase();
22152+
22153+        void resetAssertionInfo();
22154+        bool testForMissingAssertions( Counts& assertions );
22155+
22156+        void assertionEnded( AssertionResult&& result );
22157+        void reportExpr
22158+                (   AssertionInfo const &info,
22159+                    ResultWas::OfType resultType,
22160+                    ITransientExpression const *expr,
22161+                    bool negated );
22162+
22163+        void populateReaction( AssertionReaction& reaction );
22164+
22165+    private:
22166+
22167+        void handleUnfinishedSections();
22168+
22169+        TestRunInfo m_runInfo;
22170+        TestCaseHandle const* m_activeTestCase = nullptr;
22171+        ITracker* m_testCaseTracker = nullptr;
22172+        Optional<AssertionResult> m_lastResult;
22173+
22174+        IConfig const* m_config;
22175+        Totals m_totals;
22176+        IEventListenerPtr m_reporter;
22177+        std::vector<MessageInfo> m_messages;
22178+        std::vector<ScopedMessage> m_messageScopes; /* Keeps owners of so-called unscoped messages. */
22179+        AssertionInfo m_lastAssertionInfo;
22180+        std::vector<SectionEndInfo> m_unfinishedSections;
22181+        std::vector<ITracker*> m_activeSections;
22182+        TrackerContext m_trackerContext;
22183+        FatalConditionHandler m_fatalConditionhandler;
22184+        bool m_lastAssertionPassed = false;
22185+        bool m_shouldReportUnexpected = true;
22186+        bool m_includeSuccessfulResults;
22187+    };
22188+
22189+    void seedRng(IConfig const& config);
22190+    unsigned int rngSeed();
22191+} // end namespace Catch
22192+
22193+#endif // CATCH_RUN_CONTEXT_HPP_INCLUDED
22194+
22195+
22196+#ifndef CATCH_SHARDING_HPP_INCLUDED
22197+#define CATCH_SHARDING_HPP_INCLUDED
22198+
22199+#include <cassert>
22200+#include <cmath>
22201+#include <algorithm>
22202+
22203+namespace Catch {
22204+
22205+    template<typename Container>
22206+    Container createShard(Container const& container, std::size_t const shardCount, std::size_t const shardIndex) {
22207+        assert(shardCount > shardIndex);
22208+
22209+        if (shardCount == 1) {
22210+            return container;
22211+        }
22212+
22213+        const std::size_t totalTestCount = container.size();
22214+
22215+        const std::size_t shardSize = totalTestCount / shardCount;
22216+        const std::size_t leftoverTests = totalTestCount % shardCount;
22217+
22218+        const std::size_t startIndex = shardIndex * shardSize + (std::min)(shardIndex, leftoverTests);
22219+        const std::size_t endIndex = (shardIndex + 1) * shardSize + (std::min)(shardIndex + 1, leftoverTests);
22220+
22221+        auto startIterator = std::next(container.begin(), static_cast<std::ptrdiff_t>(startIndex));
22222+        auto endIterator = std::next(container.begin(), static_cast<std::ptrdiff_t>(endIndex));
22223+
22224+        return Container(startIterator, endIterator);
22225+    }
22226+
22227+}
22228+
22229+#endif // CATCH_SHARDING_HPP_INCLUDED
22230+
22231+
22232+#ifndef CATCH_SINGLETONS_HPP_INCLUDED
22233+#define CATCH_SINGLETONS_HPP_INCLUDED
22234+
22235+namespace Catch {
22236+
22237+    struct ISingleton {
22238+        virtual ~ISingleton(); // = default
22239+    };
22240+
22241+
22242+    void addSingleton( ISingleton* singleton );
22243+    void cleanupSingletons();
22244+
22245+
22246+    template<typename SingletonImplT, typename InterfaceT = SingletonImplT, typename MutableInterfaceT = InterfaceT>
22247+    class Singleton : SingletonImplT, public ISingleton {
22248+
22249+        static auto getInternal() -> Singleton* {
22250+            static Singleton* s_instance = nullptr;
22251+            if( !s_instance ) {
22252+                s_instance = new Singleton;
22253+                addSingleton( s_instance );
22254+            }
22255+            return s_instance;
22256+        }
22257+
22258+    public:
22259+        static auto get() -> InterfaceT const& {
22260+            return *getInternal();
22261+        }
22262+        static auto getMutable() -> MutableInterfaceT& {
22263+            return *getInternal();
22264+        }
22265+    };
22266+
22267+} // namespace Catch
22268+
22269+#endif // CATCH_SINGLETONS_HPP_INCLUDED
22270+
22271+
22272+#ifndef CATCH_STARTUP_EXCEPTION_REGISTRY_HPP_INCLUDED
22273+#define CATCH_STARTUP_EXCEPTION_REGISTRY_HPP_INCLUDED
22274+
22275+
22276+#include <vector>
22277+#include <exception>
22278+
22279+namespace Catch {
22280+
22281+    class StartupExceptionRegistry {
22282+#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
22283+    public:
22284+        void add(std::exception_ptr const& exception) noexcept;
22285+        std::vector<std::exception_ptr> const& getExceptions() const noexcept;
22286+    private:
22287+        std::vector<std::exception_ptr> m_exceptions;
22288+#endif
22289+    };
22290+
22291+} // end namespace Catch
22292+
22293+#endif // CATCH_STARTUP_EXCEPTION_REGISTRY_HPP_INCLUDED
22294+
22295+
22296+
22297+#ifndef CATCH_STDSTREAMS_HPP_INCLUDED
22298+#define CATCH_STDSTREAMS_HPP_INCLUDED
22299+
22300+#include <iosfwd>
22301+
22302+namespace Catch {
22303+
22304+    std::ostream& cout();
22305+    std::ostream& cerr();
22306+    std::ostream& clog();
22307+
22308+} // namespace Catch
22309+
22310+#endif
22311+
22312+
22313+#ifndef CATCH_STRING_MANIP_HPP_INCLUDED
22314+#define CATCH_STRING_MANIP_HPP_INCLUDED
22315+
22316+
22317+#include <cstdint>
22318+#include <string>
22319+#include <iosfwd>
22320+#include <vector>
22321+
22322+namespace Catch {
22323+
22324+    bool startsWith( std::string const& s, std::string const& prefix );
22325+    bool startsWith( StringRef s, char prefix );
22326+    bool endsWith( std::string const& s, std::string const& suffix );
22327+    bool endsWith( std::string const& s, char suffix );
22328+    bool contains( std::string const& s, std::string const& infix );
22329+    void toLowerInPlace( std::string& s );
22330+    std::string toLower( std::string const& s );
22331+    char toLower( char c );
22332+    //! Returns a new string without whitespace at the start/end
22333+    std::string trim( std::string const& str );
22334+    //! Returns a substring of the original ref without whitespace. Beware lifetimes!
22335+    StringRef trim(StringRef ref);
22336+
22337+    // !!! Be aware, returns refs into original string - make sure original string outlives them
22338+    std::vector<StringRef> splitStringRef( StringRef str, char delimiter );
22339+    bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis );
22340+
22341+    /**
22342+     * Helper for streaming a "count [maybe-plural-of-label]" human-friendly string
22343+     *
22344+     * Usage example:
22345+     * ```cpp
22346+     * std::cout << "Found " << pluralise(count, "error") << '\n';
22347+     * ```
22348+     *
22349+     * **Important:** The provided string must outlive the instance
22350+     */
22351+    class pluralise {
22352+        std::uint64_t m_count;
22353+        StringRef m_label;
22354+
22355+    public:
22356+        constexpr pluralise(std::uint64_t count, StringRef label):
22357+            m_count(count),
22358+            m_label(label)
22359+        {}
22360+
22361+        friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser );
22362+    };
22363+}
22364+
22365+#endif // CATCH_STRING_MANIP_HPP_INCLUDED
22366+
22367+
22368+#ifndef CATCH_TAG_ALIAS_REGISTRY_HPP_INCLUDED
22369+#define CATCH_TAG_ALIAS_REGISTRY_HPP_INCLUDED
22370+
22371+
22372+#include <map>
22373+#include <string>
22374+
22375+namespace Catch {
22376+    struct SourceLineInfo;
22377+
22378+    class TagAliasRegistry : public ITagAliasRegistry {
22379+    public:
22380+        ~TagAliasRegistry() override;
22381+        TagAlias const* find( std::string const& alias ) const override;
22382+        std::string expandAliases( std::string const& unexpandedTestSpec ) const override;
22383+        void add( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo );
22384+
22385+    private:
22386+        std::map<std::string, TagAlias> m_registry;
22387+    };
22388+
22389+} // end namespace Catch
22390+
22391+#endif // CATCH_TAG_ALIAS_REGISTRY_HPP_INCLUDED
22392+
22393+
22394+#ifndef CATCH_TEST_CASE_INFO_HASHER_HPP_INCLUDED
22395+#define CATCH_TEST_CASE_INFO_HASHER_HPP_INCLUDED
22396+
22397+#include <cstdint>
22398+
22399+namespace Catch {
22400+
22401+    struct TestCaseInfo;
22402+
22403+    class TestCaseInfoHasher {
22404+    public:
22405+        using hash_t = std::uint64_t;
22406+        TestCaseInfoHasher( hash_t seed );
22407+        uint32_t operator()( TestCaseInfo const& t ) const;
22408+
22409+    private:
22410+        hash_t m_seed;
22411+    };
22412+
22413+} // namespace Catch
22414+
22415+#endif /* CATCH_TEST_CASE_INFO_HASHER_HPP_INCLUDED */
22416+
22417+
22418+#ifndef CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED
22419+#define CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED
22420+
22421+
22422+#include <vector>
22423+
22424+namespace Catch {
22425+
22426+    class IConfig;
22427+    class ITestInvoker;
22428+    class TestCaseHandle;
22429+    class TestSpec;
22430+
22431+    std::vector<TestCaseHandle> sortTests( IConfig const& config, std::vector<TestCaseHandle> const& unsortedTestCases );
22432+
22433+    bool isThrowSafe( TestCaseHandle const& testCase, IConfig const& config );
22434+
22435+    std::vector<TestCaseHandle> filterTests( std::vector<TestCaseHandle> const& testCases, TestSpec const& testSpec, IConfig const& config );
22436+    std::vector<TestCaseHandle> const& getAllTestCasesSorted( IConfig const& config );
22437+
22438+    class TestRegistry : public ITestCaseRegistry {
22439+    public:
22440+        void registerTest( Detail::unique_ptr<TestCaseInfo> testInfo, Detail::unique_ptr<ITestInvoker> testInvoker );
22441+
22442+        std::vector<TestCaseInfo*> const& getAllInfos() const override;
22443+        std::vector<TestCaseHandle> const& getAllTests() const override;
22444+        std::vector<TestCaseHandle> const& getAllTestsSorted( IConfig const& config ) const override;
22445+
22446+        ~TestRegistry() override; // = default
22447+
22448+    private:
22449+        std::vector<Detail::unique_ptr<TestCaseInfo>> m_owned_test_infos;
22450+        // Keeps a materialized vector for `getAllInfos`.
22451+        // We should get rid of that eventually (see interface note)
22452+        std::vector<TestCaseInfo*> m_viewed_test_infos;
22453+
22454+        std::vector<Detail::unique_ptr<ITestInvoker>> m_invokers;
22455+        std::vector<TestCaseHandle> m_handles;
22456+        mutable TestRunOrder m_currentSortOrder = TestRunOrder::Declared;
22457+        mutable std::vector<TestCaseHandle> m_sortedFunctions;
22458+    };
22459+
22460+    ///////////////////////////////////////////////////////////////////////////
22461+
22462+
22463+} // end namespace Catch
22464+
22465+
22466+#endif // CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED
22467+
22468+
22469+#ifndef CATCH_TEST_SPEC_PARSER_HPP_INCLUDED
22470+#define CATCH_TEST_SPEC_PARSER_HPP_INCLUDED
22471+
22472+#ifdef __clang__
22473+#pragma clang diagnostic push
22474+#pragma clang diagnostic ignored "-Wpadded"
22475+#endif
22476+
22477+
22478+#include <vector>
22479+#include <string>
22480+
22481+namespace Catch {
22482+
22483+    class ITagAliasRegistry;
22484+
22485+    class TestSpecParser {
22486+        enum Mode{ None, Name, QuotedName, Tag, EscapedName };
22487+        Mode m_mode = None;
22488+        Mode lastMode = None;
22489+        bool m_exclusion = false;
22490+        std::size_t m_pos = 0;
22491+        std::size_t m_realPatternPos = 0;
22492+        std::string m_arg;
22493+        std::string m_substring;
22494+        std::string m_patternName;
22495+        std::vector<std::size_t> m_escapeChars;
22496+        TestSpec::Filter m_currentFilter;
22497+        TestSpec m_testSpec;
22498+        ITagAliasRegistry const* m_tagAliases = nullptr;
22499+
22500+    public:
22501+        TestSpecParser( ITagAliasRegistry const& tagAliases );
22502+
22503+        TestSpecParser& parse( std::string const& arg );
22504+        TestSpec testSpec();
22505+
22506+    private:
22507+        bool visitChar( char c );
22508+        void startNewMode( Mode mode );
22509+        bool processNoneChar( char c );
22510+        void processNameChar( char c );
22511+        bool processOtherChar( char c );
22512+        void endMode();
22513+        void escape();
22514+        bool isControlChar( char c ) const;
22515+        void saveLastMode();
22516+        void revertBackToLastMode();
22517+        void addFilter();
22518+        bool separate();
22519+
22520+        // Handles common preprocessing of the pattern for name/tag patterns
22521+        std::string preprocessPattern();
22522+        // Adds the current pattern as a test name
22523+        void addNamePattern();
22524+        // Adds the current pattern as a tag
22525+        void addTagPattern();
22526+
22527+        inline void addCharToPattern(char c) {
22528+            m_substring += c;
22529+            m_patternName += c;
22530+            m_realPatternPos++;
22531+        }
22532+
22533+    };
22534+
22535+} // namespace Catch
22536+
22537+#ifdef __clang__
22538+#pragma clang diagnostic pop
22539+#endif
22540+
22541+#endif // CATCH_TEST_SPEC_PARSER_HPP_INCLUDED
22542+
22543+
22544+#ifndef CATCH_TEXTFLOW_HPP_INCLUDED
22545+#define CATCH_TEXTFLOW_HPP_INCLUDED
22546+
22547+
22548+#include <cassert>
22549+#include <string>
22550+#include <vector>
22551+
22552+namespace Catch {
22553+    namespace TextFlow {
22554+
22555+        class Columns;
22556+
22557+        /**
22558+         * Represents a column of text with specific width and indentation
22559+         *
22560+         * When written out to a stream, it will perform linebreaking
22561+         * of the provided text so that the written lines fit within
22562+         * target width.
22563+         */
22564+        class Column {
22565+            // String to be written out
22566+            std::string m_string;
22567+            // Width of the column for linebreaking
22568+            size_t m_width = CATCH_CONFIG_CONSOLE_WIDTH - 1;
22569+            // Indentation of other lines (including first if initial indent is unset)
22570+            size_t m_indent = 0;
22571+            // Indentation of the first line
22572+            size_t m_initialIndent = std::string::npos;
22573+
22574+        public:
22575+            /**
22576+             * Iterates "lines" in `Column` and returns them
22577+             */
22578+            class const_iterator {
22579+                friend Column;
22580+                struct EndTag {};
22581+
22582+                Column const& m_column;
22583+                // Where does the current line start?
22584+                size_t m_lineStart = 0;
22585+                // How long should the current line be?
22586+                size_t m_lineLength = 0;
22587+                // How far have we checked the string to iterate?
22588+                size_t m_parsedTo = 0;
22589+                // Should a '-' be appended to the line?
22590+                bool m_addHyphen = false;
22591+
22592+                const_iterator( Column const& column, EndTag ):
22593+                    m_column( column ), m_lineStart( m_column.m_string.size() ) {}
22594+
22595+                // Calculates the length of the current line
22596+                void calcLength();
22597+
22598+                // Returns current indentation width
22599+                size_t indentSize() const;
22600+
22601+                // Creates an indented and (optionally) suffixed string from
22602+                // current iterator position, indentation and length.
22603+                std::string addIndentAndSuffix( size_t position,
22604+                                                size_t length ) const;
22605+
22606+            public:
22607+                using difference_type = std::ptrdiff_t;
22608+                using value_type = std::string;
22609+                using pointer = value_type*;
22610+                using reference = value_type&;
22611+                using iterator_category = std::forward_iterator_tag;
22612+
22613+                explicit const_iterator( Column const& column );
22614+
22615+                std::string operator*() const;
22616+
22617+                const_iterator& operator++();
22618+                const_iterator operator++( int );
22619+
22620+                bool operator==( const_iterator const& other ) const {
22621+                    return m_lineStart == other.m_lineStart && &m_column == &other.m_column;
22622+                }
22623+                bool operator!=( const_iterator const& other ) const {
22624+                    return !operator==( other );
22625+                }
22626+            };
22627+            using iterator = const_iterator;
22628+
22629+            explicit Column( std::string const& text ): m_string( text ) {}
22630+            explicit Column( std::string&& text ):
22631+                m_string( CATCH_MOVE(text)) {}
22632+
22633+            Column& width( size_t newWidth ) & {
22634+                assert( newWidth > 0 );
22635+                m_width = newWidth;
22636+                return *this;
22637+            }
22638+            Column&& width( size_t newWidth ) && {
22639+                assert( newWidth > 0 );
22640+                m_width = newWidth;
22641+                return CATCH_MOVE( *this );
22642+            }
22643+            Column& indent( size_t newIndent ) & {
22644+                m_indent = newIndent;
22645+                return *this;
22646+            }
22647+            Column&& indent( size_t newIndent ) && {
22648+                m_indent = newIndent;
22649+                return CATCH_MOVE( *this );
22650+            }
22651+            Column& initialIndent( size_t newIndent ) & {
22652+                m_initialIndent = newIndent;
22653+                return *this;
22654+            }
22655+            Column&& initialIndent( size_t newIndent ) && {
22656+                m_initialIndent = newIndent;
22657+                return CATCH_MOVE( *this );
22658+            }
22659+
22660+            size_t width() const { return m_width; }
22661+            const_iterator begin() const { return const_iterator( *this ); }
22662+            const_iterator end() const { return { *this, const_iterator::EndTag{} }; }
22663+
22664+            friend std::ostream& operator<<( std::ostream& os,
22665+                                             Column const& col );
22666+
22667+            friend Columns operator+( Column const& lhs, Column const& rhs );
22668+            friend Columns operator+( Column&& lhs, Column&& rhs );
22669+        };
22670+
22671+        //! Creates a column that serves as an empty space of specific width
22672+        Column Spacer( size_t spaceWidth );
22673+
22674+        class Columns {
22675+            std::vector<Column> m_columns;
22676+
22677+        public:
22678+            class iterator {
22679+                friend Columns;
22680+                struct EndTag {};
22681+
22682+                std::vector<Column> const& m_columns;
22683+                std::vector<Column::const_iterator> m_iterators;
22684+                size_t m_activeIterators;
22685+
22686+                iterator( Columns const& columns, EndTag );
22687+
22688+            public:
22689+                using difference_type = std::ptrdiff_t;
22690+                using value_type = std::string;
22691+                using pointer = value_type*;
22692+                using reference = value_type&;
22693+                using iterator_category = std::forward_iterator_tag;
22694+
22695+                explicit iterator( Columns const& columns );
22696+
22697+                auto operator==( iterator const& other ) const -> bool {
22698+                    return m_iterators == other.m_iterators;
22699+                }
22700+                auto operator!=( iterator const& other ) const -> bool {
22701+                    return m_iterators != other.m_iterators;
22702+                }
22703+                std::string operator*() const;
22704+                iterator& operator++();
22705+                iterator operator++( int );
22706+            };
22707+            using const_iterator = iterator;
22708+
22709+            iterator begin() const { return iterator( *this ); }
22710+            iterator end() const { return { *this, iterator::EndTag() }; }
22711+
22712+            friend Columns& operator+=( Columns& lhs, Column const& rhs );
22713+            friend Columns& operator+=( Columns& lhs, Column&& rhs );
22714+            friend Columns operator+( Columns const& lhs, Column const& rhs );
22715+            friend Columns operator+( Columns&& lhs, Column&& rhs );
22716+
22717+            friend std::ostream& operator<<( std::ostream& os,
22718+                                             Columns const& cols );
22719+        };
22720+
22721+    } // namespace TextFlow
22722+} // namespace Catch
22723+#endif // CATCH_TEXTFLOW_HPP_INCLUDED
22724+
22725+
22726+#ifndef CATCH_TO_STRING_HPP_INCLUDED
22727+#define CATCH_TO_STRING_HPP_INCLUDED
22728+
22729+#include <string>
22730+
22731+
22732+namespace Catch {
22733+    template <typename T>
22734+    std::string to_string(T const& t) {
22735+#if defined(CATCH_CONFIG_CPP11_TO_STRING)
22736+        return std::to_string(t);
22737+#else
22738+        ReusableStringStream rss;
22739+        rss << t;
22740+        return rss.str();
22741+#endif
22742+    }
22743+} // end namespace Catch
22744+
22745+#endif // CATCH_TO_STRING_HPP_INCLUDED
22746+
22747+
22748+#ifndef CATCH_UNCAUGHT_EXCEPTIONS_HPP_INCLUDED
22749+#define CATCH_UNCAUGHT_EXCEPTIONS_HPP_INCLUDED
22750+
22751+namespace Catch {
22752+    bool uncaught_exceptions();
22753+} // end namespace Catch
22754+
22755+#endif // CATCH_UNCAUGHT_EXCEPTIONS_HPP_INCLUDED
22756+
22757+
22758+#ifndef CATCH_XMLWRITER_HPP_INCLUDED
22759+#define CATCH_XMLWRITER_HPP_INCLUDED
22760+
22761+
22762+#include <iosfwd>
22763+#include <vector>
22764+
22765+namespace Catch {
22766+    enum class XmlFormatting {
22767+        None = 0x00,
22768+        Indent = 0x01,
22769+        Newline = 0x02,
22770+    };
22771+
22772+    XmlFormatting operator | (XmlFormatting lhs, XmlFormatting rhs);
22773+    XmlFormatting operator & (XmlFormatting lhs, XmlFormatting rhs);
22774+
22775+    /**
22776+     * Helper for XML-encoding text (escaping angle brackets, quotes, etc)
22777+     *
22778+     * Note: doesn't take ownership of passed strings, and thus the
22779+     *       encoded string must outlive the encoding instance.
22780+     */
22781+    class XmlEncode {
22782+    public:
22783+        enum ForWhat { ForTextNodes, ForAttributes };
22784+
22785+        XmlEncode( StringRef str, ForWhat forWhat = ForTextNodes );
22786+
22787+        void encodeTo( std::ostream& os ) const;
22788+
22789+        friend std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode );
22790+
22791+    private:
22792+        StringRef m_str;
22793+        ForWhat m_forWhat;
22794+    };
22795+
22796+    class XmlWriter {
22797+    public:
22798+
22799+        class ScopedElement {
22800+        public:
22801+            ScopedElement( XmlWriter* writer, XmlFormatting fmt );
22802+
22803+            ScopedElement( ScopedElement&& other ) noexcept;
22804+            ScopedElement& operator=( ScopedElement&& other ) noexcept;
22805+
22806+            ~ScopedElement();
22807+
22808+            ScopedElement&
22809+            writeText( StringRef text,
22810+                       XmlFormatting fmt = XmlFormatting::Newline |
22811+                                           XmlFormatting::Indent );
22812+
22813+            ScopedElement& writeAttribute( StringRef name,
22814+                                           StringRef attribute );
22815+            template <typename T,
22816+                      // Without this SFINAE, this overload is a better match
22817+                      // for `std::string`, `char const*`, `char const[N]` args.
22818+                      // While it would still work, it would cause code bloat
22819+                      // and multiple iteration over the strings
22820+                      typename = typename std::enable_if_t<
22821+                          !std::is_convertible<T, StringRef>::value>>
22822+            ScopedElement& writeAttribute( StringRef name,
22823+                                           T const& attribute ) {
22824+                m_writer->writeAttribute( name, attribute );
22825+                return *this;
22826+            }
22827+
22828+        private:
22829+            XmlWriter* m_writer = nullptr;
22830+            XmlFormatting m_fmt;
22831+        };
22832+
22833+        XmlWriter( std::ostream& os );
22834+        ~XmlWriter();
22835+
22836+        XmlWriter( XmlWriter const& ) = delete;
22837+        XmlWriter& operator=( XmlWriter const& ) = delete;
22838+
22839+        XmlWriter& startElement( std::string const& name, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent);
22840+
22841+        ScopedElement scopedElement( std::string const& name, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent);
22842+
22843+        XmlWriter& endElement(XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent);
22844+
22845+        //! The attribute content is XML-encoded
22846+        XmlWriter& writeAttribute( StringRef name, StringRef attribute );
22847+
22848+        //! Writes the attribute as "true/false"
22849+        XmlWriter& writeAttribute( StringRef name, bool attribute );
22850+
22851+        //! The attribute content is XML-encoded
22852+        XmlWriter& writeAttribute( StringRef name, char const* attribute );
22853+
22854+        //! The attribute value must provide op<<(ostream&, T). The resulting
22855+        //! serialization is XML-encoded
22856+        template <typename T,
22857+                  // Without this SFINAE, this overload is a better match
22858+                  // for `std::string`, `char const*`, `char const[N]` args.
22859+                  // While it would still work, it would cause code bloat
22860+                  // and multiple iteration over the strings
22861+                  typename = typename std::enable_if_t<
22862+                      !std::is_convertible<T, StringRef>::value>>
22863+        XmlWriter& writeAttribute( StringRef name, T const& attribute ) {
22864+            ReusableStringStream rss;
22865+            rss << attribute;
22866+            return writeAttribute( name, rss.str() );
22867+        }
22868+
22869+        //! Writes escaped `text` in a element
22870+        XmlWriter& writeText( StringRef text,
22871+                              XmlFormatting fmt = XmlFormatting::Newline |
22872+                                                  XmlFormatting::Indent );
22873+
22874+        //! Writes XML comment as "<!-- text -->"
22875+        XmlWriter& writeComment( StringRef text,
22876+                                 XmlFormatting fmt = XmlFormatting::Newline |
22877+                                                     XmlFormatting::Indent );
22878+
22879+        void writeStylesheetRef( StringRef url );
22880+
22881+        void ensureTagClosed();
22882+
22883+    private:
22884+
22885+        void applyFormatting(XmlFormatting fmt);
22886+
22887+        void writeDeclaration();
22888+
22889+        void newlineIfNecessary();
22890+
22891+        bool m_tagIsOpen = false;
22892+        bool m_needsNewline = false;
22893+        std::vector<std::string> m_tags;
22894+        std::string m_indent;
22895+        std::ostream& m_os;
22896+    };
22897+
22898+}
22899+
22900+#endif // CATCH_XMLWRITER_HPP_INCLUDED
22901+
22902+
22903+/** \file
22904+ * This is a convenience header for Catch2's Matcher support. It includes
22905+ * **all** of Catch2 headers related to matchers.
22906+ *
22907+ * Generally the Catch2 users should use specific includes they need,
22908+ * but this header can be used instead for ease-of-experimentation, or
22909+ * just plain convenience, at the cost of increased compilation times.
22910+ *
22911+ * When a new header is added to either the `matchers` folder, or to
22912+ * the corresponding internal subfolder, it should be added here.
22913+ */
22914+
22915+#ifndef CATCH_MATCHERS_ALL_HPP_INCLUDED
22916+#define CATCH_MATCHERS_ALL_HPP_INCLUDED
22917+
22918+
22919+
22920+#ifndef CATCH_MATCHERS_HPP_INCLUDED
22921+#define CATCH_MATCHERS_HPP_INCLUDED
22922+
22923+
22924+
22925+#ifndef CATCH_MATCHERS_IMPL_HPP_INCLUDED
22926+#define CATCH_MATCHERS_IMPL_HPP_INCLUDED
22927+
22928+
22929+#include <string>
22930+
22931+namespace Catch {
22932+
22933+    template<typename ArgT, typename MatcherT>
22934+    class MatchExpr : public ITransientExpression {
22935+        ArgT && m_arg;
22936+        MatcherT const& m_matcher;
22937+    public:
22938+        MatchExpr( ArgT && arg, MatcherT const& matcher )
22939+        :   ITransientExpression{ true, matcher.match( arg ) }, // not forwarding arg here on purpose
22940+            m_arg( CATCH_FORWARD(arg) ),
22941+            m_matcher( matcher )
22942+        {}
22943+
22944+        void streamReconstructedExpression( std::ostream& os ) const override {
22945+            os << Catch::Detail::stringify( m_arg )
22946+               << ' '
22947+               << m_matcher.toString();
22948+        }
22949+    };
22950+
22951+    namespace Matchers {
22952+        template <typename ArgT>
22953+        class MatcherBase;
22954+    }
22955+
22956+    using StringMatcher = Matchers::MatcherBase<std::string>;
22957+
22958+    void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher );
22959+
22960+    template<typename ArgT, typename MatcherT>
22961+    auto makeMatchExpr( ArgT && arg, MatcherT const& matcher ) -> MatchExpr<ArgT, MatcherT> {
22962+        return MatchExpr<ArgT, MatcherT>( CATCH_FORWARD(arg), matcher );
22963+    }
22964+
22965+} // namespace Catch
22966+
22967+
22968+///////////////////////////////////////////////////////////////////////////////
22969+#define INTERNAL_CHECK_THAT( macroName, matcher, resultDisposition, arg ) \
22970+    do { \
22971+        Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(arg) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \
22972+        INTERNAL_CATCH_TRY { \
22973+            catchAssertionHandler.handleExpr( Catch::makeMatchExpr( arg, matcher ) ); \
22974+        } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \
22975+        INTERNAL_CATCH_REACT( catchAssertionHandler ) \
22976+    } while( false )
22977+
22978+
22979+///////////////////////////////////////////////////////////////////////////////
22980+#define INTERNAL_CATCH_THROWS_MATCHES( macroName, exceptionType, resultDisposition, matcher, ... ) \
22981+    do { \
22982+        Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(exceptionType) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \
22983+        if( catchAssertionHandler.allowThrows() ) \
22984+            try { \
22985+                static_cast<void>(__VA_ARGS__ ); \
22986+                catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
22987+            } \
22988+            catch( exceptionType const& ex ) { \
22989+                catchAssertionHandler.handleExpr( Catch::makeMatchExpr( ex, matcher ) ); \
22990+            } \
22991+            catch( ... ) { \
22992+                catchAssertionHandler.handleUnexpectedInflightException(); \
22993+            } \
22994+        else \
22995+            catchAssertionHandler.handleThrowingCallSkipped(); \
22996+        INTERNAL_CATCH_REACT( catchAssertionHandler ) \
22997+    } while( false )
22998+
22999+
23000+#endif // CATCH_MATCHERS_IMPL_HPP_INCLUDED
23001+
23002+#include <string>
23003+#include <vector>
23004+
23005+namespace Catch {
23006+namespace Matchers {
23007+
23008+    class MatcherUntypedBase {
23009+    public:
23010+        MatcherUntypedBase() = default;
23011+
23012+        MatcherUntypedBase(MatcherUntypedBase const&) = default;
23013+        MatcherUntypedBase(MatcherUntypedBase&&) = default;
23014+
23015+        MatcherUntypedBase& operator = (MatcherUntypedBase const&) = delete;
23016+        MatcherUntypedBase& operator = (MatcherUntypedBase&&) = delete;
23017+
23018+        std::string toString() const;
23019+
23020+    protected:
23021+        virtual ~MatcherUntypedBase(); // = default;
23022+        virtual std::string describe() const = 0;
23023+        mutable std::string m_cachedToString;
23024+    };
23025+
23026+
23027+    template<typename T>
23028+    class MatcherBase : public MatcherUntypedBase {
23029+    public:
23030+        virtual bool match( T const& arg ) const = 0;
23031+    };
23032+
23033+    namespace Detail {
23034+
23035+        template<typename ArgT>
23036+        class MatchAllOf final : public MatcherBase<ArgT> {
23037+            std::vector<MatcherBase<ArgT> const*> m_matchers;
23038+
23039+        public:
23040+            MatchAllOf() = default;
23041+            MatchAllOf(MatchAllOf const&) = delete;
23042+            MatchAllOf& operator=(MatchAllOf const&) = delete;
23043+            MatchAllOf(MatchAllOf&&) = default;
23044+            MatchAllOf& operator=(MatchAllOf&&) = default;
23045+
23046+
23047+            bool match( ArgT const& arg ) const override {
23048+                for( auto matcher : m_matchers ) {
23049+                    if (!matcher->match(arg))
23050+                        return false;
23051+                }
23052+                return true;
23053+            }
23054+            std::string describe() const override {
23055+                std::string description;
23056+                description.reserve( 4 + m_matchers.size()*32 );
23057+                description += "( ";
23058+                bool first = true;
23059+                for( auto matcher : m_matchers ) {
23060+                    if( first )
23061+                        first = false;
23062+                    else
23063+                        description += " and ";
23064+                    description += matcher->toString();
23065+                }
23066+                description += " )";
23067+                return description;
23068+            }
23069+
23070+            friend MatchAllOf operator&& (MatchAllOf&& lhs, MatcherBase<ArgT> const& rhs) {
23071+                lhs.m_matchers.push_back(&rhs);
23072+                return CATCH_MOVE(lhs);
23073+            }
23074+            friend MatchAllOf operator&& (MatcherBase<ArgT> const& lhs, MatchAllOf&& rhs) {
23075+                rhs.m_matchers.insert(rhs.m_matchers.begin(), &lhs);
23076+                return CATCH_MOVE(rhs);
23077+            }
23078+        };
23079+
23080+        //! lvalue overload is intentionally deleted, users should
23081+        //! not be trying to compose stored composition matchers
23082+        template<typename ArgT>
23083+        MatchAllOf<ArgT> operator&& (MatchAllOf<ArgT> const& lhs, MatcherBase<ArgT> const& rhs) = delete;
23084+        //! lvalue overload is intentionally deleted, users should
23085+        //! not be trying to compose stored composition matchers
23086+        template<typename ArgT>
23087+        MatchAllOf<ArgT> operator&& (MatcherBase<ArgT> const& lhs, MatchAllOf<ArgT> const& rhs) = delete;
23088+
23089+        template<typename ArgT>
23090+        class MatchAnyOf final : public MatcherBase<ArgT> {
23091+            std::vector<MatcherBase<ArgT> const*> m_matchers;
23092+        public:
23093+            MatchAnyOf() = default;
23094+            MatchAnyOf(MatchAnyOf const&) = delete;
23095+            MatchAnyOf& operator=(MatchAnyOf const&) = delete;
23096+            MatchAnyOf(MatchAnyOf&&) = default;
23097+            MatchAnyOf& operator=(MatchAnyOf&&) = default;
23098+
23099+            bool match( ArgT const& arg ) const override {
23100+                for( auto matcher : m_matchers ) {
23101+                    if (matcher->match(arg))
23102+                        return true;
23103+                }
23104+                return false;
23105+            }
23106+            std::string describe() const override {
23107+                std::string description;
23108+                description.reserve( 4 + m_matchers.size()*32 );
23109+                description += "( ";
23110+                bool first = true;
23111+                for( auto matcher : m_matchers ) {
23112+                    if( first )
23113+                        first = false;
23114+                    else
23115+                        description += " or ";
23116+                    description += matcher->toString();
23117+                }
23118+                description += " )";
23119+                return description;
23120+            }
23121+
23122+            friend MatchAnyOf operator|| (MatchAnyOf&& lhs, MatcherBase<ArgT> const& rhs) {
23123+                lhs.m_matchers.push_back(&rhs);
23124+                return CATCH_MOVE(lhs);
23125+            }
23126+            friend MatchAnyOf operator|| (MatcherBase<ArgT> const& lhs, MatchAnyOf&& rhs) {
23127+                rhs.m_matchers.insert(rhs.m_matchers.begin(), &lhs);
23128+                return CATCH_MOVE(rhs);
23129+            }
23130+        };
23131+
23132+        //! lvalue overload is intentionally deleted, users should
23133+        //! not be trying to compose stored composition matchers
23134+        template<typename ArgT>
23135+        MatchAnyOf<ArgT> operator|| (MatchAnyOf<ArgT> const& lhs, MatcherBase<ArgT> const& rhs) = delete;
23136+        //! lvalue overload is intentionally deleted, users should
23137+        //! not be trying to compose stored composition matchers
23138+        template<typename ArgT>
23139+        MatchAnyOf<ArgT> operator|| (MatcherBase<ArgT> const& lhs, MatchAnyOf<ArgT> const& rhs) = delete;
23140+
23141+        template<typename ArgT>
23142+        class MatchNotOf final : public MatcherBase<ArgT> {
23143+            MatcherBase<ArgT> const& m_underlyingMatcher;
23144+
23145+        public:
23146+            explicit MatchNotOf( MatcherBase<ArgT> const& underlyingMatcher ):
23147+                m_underlyingMatcher( underlyingMatcher )
23148+            {}
23149+
23150+            bool match( ArgT const& arg ) const override {
23151+                return !m_underlyingMatcher.match( arg );
23152+            }
23153+
23154+            std::string describe() const override {
23155+                return "not " + m_underlyingMatcher.toString();
23156+            }
23157+        };
23158+
23159+    } // namespace Detail
23160+
23161+    template <typename T>
23162+    Detail::MatchAllOf<T> operator&& (MatcherBase<T> const& lhs, MatcherBase<T> const& rhs) {
23163+        return Detail::MatchAllOf<T>{} && lhs && rhs;
23164+    }
23165+    template <typename T>
23166+    Detail::MatchAnyOf<T> operator|| (MatcherBase<T> const& lhs, MatcherBase<T> const& rhs) {
23167+        return Detail::MatchAnyOf<T>{} || lhs || rhs;
23168+    }
23169+
23170+    template <typename T>
23171+    Detail::MatchNotOf<T> operator! (MatcherBase<T> const& matcher) {
23172+        return Detail::MatchNotOf<T>{ matcher };
23173+    }
23174+
23175+
23176+} // namespace Matchers
23177+} // namespace Catch
23178+
23179+
23180+#if defined(CATCH_CONFIG_PREFIX_ALL) && !defined(CATCH_CONFIG_DISABLE)
23181+  #define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr )
23182+  #define CATCH_REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr )
23183+
23184+  #define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr )
23185+  #define CATCH_CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr )
23186+
23187+  #define CATCH_CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg )
23188+  #define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg )
23189+
23190+#elif defined(CATCH_CONFIG_PREFIX_ALL) && defined(CATCH_CONFIG_DISABLE)
23191+
23192+  #define CATCH_REQUIRE_THROWS_WITH( expr, matcher )                   (void)(0)
23193+  #define CATCH_REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0)
23194+
23195+  #define CATCH_CHECK_THROWS_WITH( expr, matcher )                     (void)(0)
23196+  #define CATCH_CHECK_THROWS_MATCHES( expr, exceptionType, matcher )   (void)(0)
23197+
23198+  #define CATCH_CHECK_THAT( arg, matcher )                             (void)(0)
23199+  #define CATCH_REQUIRE_THAT( arg, matcher )                           (void)(0)
23200+
23201+#elif !defined(CATCH_CONFIG_PREFIX_ALL) && !defined(CATCH_CONFIG_DISABLE)
23202+
23203+  #define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr )
23204+  #define REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr )
23205+
23206+  #define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr )
23207+  #define CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr )
23208+
23209+  #define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg )
23210+  #define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg )
23211+
23212+#elif !defined(CATCH_CONFIG_PREFIX_ALL) && defined(CATCH_CONFIG_DISABLE)
23213+
23214+  #define REQUIRE_THROWS_WITH( expr, matcher )                   (void)(0)
23215+  #define REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0)
23216+
23217+  #define CHECK_THROWS_WITH( expr, matcher )                     (void)(0)
23218+  #define CHECK_THROWS_MATCHES( expr, exceptionType, matcher )   (void)(0)
23219+
23220+  #define CHECK_THAT( arg, matcher )                             (void)(0)
23221+  #define REQUIRE_THAT( arg, matcher )                           (void)(0)
23222+
23223+#endif // end of user facing macro declarations
23224+
23225+#endif // CATCH_MATCHERS_HPP_INCLUDED
23226+
23227+
23228+#ifndef CATCH_MATCHERS_CONTAINER_PROPERTIES_HPP_INCLUDED
23229+#define CATCH_MATCHERS_CONTAINER_PROPERTIES_HPP_INCLUDED
23230+
23231+
23232+
23233+#ifndef CATCH_MATCHERS_TEMPLATED_HPP_INCLUDED
23234+#define CATCH_MATCHERS_TEMPLATED_HPP_INCLUDED
23235+
23236+
23237+#include <array>
23238+#include <algorithm>
23239+#include <string>
23240+#include <type_traits>
23241+
23242+namespace Catch {
23243+namespace Matchers {
23244+    class MatcherGenericBase : public MatcherUntypedBase {
23245+    public:
23246+        MatcherGenericBase() = default;
23247+        ~MatcherGenericBase() override; // = default;
23248+
23249+        MatcherGenericBase(MatcherGenericBase const&) = default;
23250+        MatcherGenericBase(MatcherGenericBase&&) = default;
23251+
23252+        MatcherGenericBase& operator=(MatcherGenericBase const&) = delete;
23253+        MatcherGenericBase& operator=(MatcherGenericBase&&) = delete;
23254+    };
23255+
23256+
23257+    namespace Detail {
23258+        template<std::size_t N, std::size_t M>
23259+        std::array<void const*, N + M> array_cat(std::array<void const*, N> && lhs, std::array<void const*, M> && rhs) {
23260+            std::array<void const*, N + M> arr{};
23261+            std::copy_n(lhs.begin(), N, arr.begin());
23262+            std::copy_n(rhs.begin(), M, arr.begin() + N);
23263+            return arr;
23264+        }
23265+
23266+        template<std::size_t N>
23267+        std::array<void const*, N+1> array_cat(std::array<void const*, N> && lhs, void const* rhs) {
23268+            std::array<void const*, N+1> arr{};
23269+            std::copy_n(lhs.begin(), N, arr.begin());
23270+            arr[N] = rhs;
23271+            return arr;
23272+        }
23273+
23274+        template<std::size_t N>
23275+        std::array<void const*, N+1> array_cat(void const* lhs, std::array<void const*, N> && rhs) {
23276+            std::array<void const*, N + 1> arr{ {lhs} };
23277+            std::copy_n(rhs.begin(), N, arr.begin() + 1);
23278+            return arr;
23279+        }
23280+
23281+        template<typename T>
23282+        using is_generic_matcher = std::is_base_of<
23283+            Catch::Matchers::MatcherGenericBase,
23284+            std::remove_cv_t<std::remove_reference_t<T>>
23285+        >;
23286+
23287+        template<typename... Ts>
23288+        using are_generic_matchers = Catch::Detail::conjunction<is_generic_matcher<Ts>...>;
23289+
23290+        template<typename T>
23291+        using is_matcher = std::is_base_of<
23292+            Catch::Matchers::MatcherUntypedBase,
23293+            std::remove_cv_t<std::remove_reference_t<T>>
23294+        >;
23295+
23296+
23297+        template<std::size_t N, typename Arg>
23298+        bool match_all_of(Arg&&, std::array<void const*, N> const&, std::index_sequence<>) {
23299+            return true;
23300+        }
23301+
23302+        template<typename T, typename... MatcherTs, std::size_t N, typename Arg, std::size_t Idx, std::size_t... Indices>
23303+        bool match_all_of(Arg&& arg, std::array<void const*, N> const& matchers, std::index_sequence<Idx, Indices...>) {
23304+            return static_cast<T const*>(matchers[Idx])->match(arg) && match_all_of<MatcherTs...>(arg, matchers, std::index_sequence<Indices...>{});
23305+        }
23306+
23307+
23308+        template<std::size_t N, typename Arg>
23309+        bool match_any_of(Arg&&, std::array<void const*, N> const&, std::index_sequence<>) {
23310+            return false;
23311+        }
23312+
23313+        template<typename T, typename... MatcherTs, std::size_t N, typename Arg, std::size_t Idx, std::size_t... Indices>
23314+        bool match_any_of(Arg&& arg, std::array<void const*, N> const& matchers, std::index_sequence<Idx, Indices...>) {
23315+            return static_cast<T const*>(matchers[Idx])->match(arg) || match_any_of<MatcherTs...>(arg, matchers, std::index_sequence<Indices...>{});
23316+        }
23317+
23318+        std::string describe_multi_matcher(StringRef combine, std::string const* descriptions_begin, std::string const* descriptions_end);
23319+
23320+        template<typename... MatcherTs, std::size_t... Idx>
23321+        std::string describe_multi_matcher(StringRef combine, std::array<void const*, sizeof...(MatcherTs)> const& matchers, std::index_sequence<Idx...>) {
23322+            std::array<std::string, sizeof...(MatcherTs)> descriptions {{
23323+                static_cast<MatcherTs const*>(matchers[Idx])->toString()...
23324+            }};
23325+
23326+            return describe_multi_matcher(combine, descriptions.data(), descriptions.data() + descriptions.size());
23327+        }
23328+
23329+
23330+        template<typename... MatcherTs>
23331+        class MatchAllOfGeneric final : public MatcherGenericBase {
23332+        public:
23333+            MatchAllOfGeneric(MatchAllOfGeneric const&) = delete;
23334+            MatchAllOfGeneric& operator=(MatchAllOfGeneric const&) = delete;
23335+            MatchAllOfGeneric(MatchAllOfGeneric&&) = default;
23336+            MatchAllOfGeneric& operator=(MatchAllOfGeneric&&) = default;
23337+
23338+            MatchAllOfGeneric(MatcherTs const&... matchers) : m_matchers{ {std::addressof(matchers)...} } {}
23339+            explicit MatchAllOfGeneric(std::array<void const*, sizeof...(MatcherTs)> matchers) : m_matchers{matchers} {}
23340+
23341+            template<typename Arg>
23342+            bool match(Arg&& arg) const {
23343+                return match_all_of<MatcherTs...>(arg, m_matchers, std::index_sequence_for<MatcherTs...>{});
23344+            }
23345+
23346+            std::string describe() const override {
23347+                return describe_multi_matcher<MatcherTs...>(" and "_sr, m_matchers, std::index_sequence_for<MatcherTs...>{});
23348+            }
23349+
23350+            // Has to be public to enable the concatenating operators
23351+            // below, because they are not friend of the RHS, only LHS,
23352+            // and thus cannot access private fields of RHS
23353+            std::array<void const*, sizeof...( MatcherTs )> m_matchers;
23354+
23355+
23356+            //! Avoids type nesting for `GenericAllOf && GenericAllOf` case
23357+            template<typename... MatchersRHS>
23358+            friend
23359+            MatchAllOfGeneric<MatcherTs..., MatchersRHS...> operator && (
23360+                    MatchAllOfGeneric<MatcherTs...>&& lhs,
23361+                    MatchAllOfGeneric<MatchersRHS...>&& rhs) {
23362+                return MatchAllOfGeneric<MatcherTs..., MatchersRHS...>{array_cat(CATCH_MOVE(lhs.m_matchers), CATCH_MOVE(rhs.m_matchers))};
23363+            }
23364+
23365+            //! Avoids type nesting for `GenericAllOf && some matcher` case
23366+            template<typename MatcherRHS>
23367+            friend std::enable_if_t<is_matcher<MatcherRHS>::value,
23368+            MatchAllOfGeneric<MatcherTs..., MatcherRHS>> operator && (
23369+                    MatchAllOfGeneric<MatcherTs...>&& lhs,
23370+                    MatcherRHS const& rhs) {
23371+                return MatchAllOfGeneric<MatcherTs..., MatcherRHS>{array_cat(CATCH_MOVE(lhs.m_matchers), static_cast<void const*>(&rhs))};
23372+            }
23373+
23374+            //! Avoids type nesting for `some matcher && GenericAllOf` case
23375+            template<typename MatcherLHS>
23376+            friend std::enable_if_t<is_matcher<MatcherLHS>::value,
23377+            MatchAllOfGeneric<MatcherLHS, MatcherTs...>> operator && (
23378+                    MatcherLHS const& lhs,
23379+                    MatchAllOfGeneric<MatcherTs...>&& rhs) {
23380+                return MatchAllOfGeneric<MatcherLHS, MatcherTs...>{array_cat(static_cast<void const*>(std::addressof(lhs)), CATCH_MOVE(rhs.m_matchers))};
23381+            }
23382+        };
23383+
23384+
23385+        template<typename... MatcherTs>
23386+        class MatchAnyOfGeneric final : public MatcherGenericBase {
23387+        public:
23388+            MatchAnyOfGeneric(MatchAnyOfGeneric const&) = delete;
23389+            MatchAnyOfGeneric& operator=(MatchAnyOfGeneric const&) = delete;
23390+            MatchAnyOfGeneric(MatchAnyOfGeneric&&) = default;
23391+            MatchAnyOfGeneric& operator=(MatchAnyOfGeneric&&) = default;
23392+
23393+            MatchAnyOfGeneric(MatcherTs const&... matchers) : m_matchers{ {std::addressof(matchers)...} } {}
23394+            explicit MatchAnyOfGeneric(std::array<void const*, sizeof...(MatcherTs)> matchers) : m_matchers{matchers} {}
23395+
23396+            template<typename Arg>
23397+            bool match(Arg&& arg) const {
23398+                return match_any_of<MatcherTs...>(arg, m_matchers, std::index_sequence_for<MatcherTs...>{});
23399+            }
23400+
23401+            std::string describe() const override {
23402+                return describe_multi_matcher<MatcherTs...>(" or "_sr, m_matchers, std::index_sequence_for<MatcherTs...>{});
23403+            }
23404+
23405+
23406+            // Has to be public to enable the concatenating operators
23407+            // below, because they are not friend of the RHS, only LHS,
23408+            // and thus cannot access private fields of RHS
23409+            std::array<void const*, sizeof...( MatcherTs )> m_matchers;
23410+
23411+            //! Avoids type nesting for `GenericAnyOf || GenericAnyOf` case
23412+            template<typename... MatchersRHS>
23413+            friend MatchAnyOfGeneric<MatcherTs..., MatchersRHS...> operator || (
23414+                    MatchAnyOfGeneric<MatcherTs...>&& lhs,
23415+                    MatchAnyOfGeneric<MatchersRHS...>&& rhs) {
23416+                return MatchAnyOfGeneric<MatcherTs..., MatchersRHS...>{array_cat(CATCH_MOVE(lhs.m_matchers), CATCH_MOVE(rhs.m_matchers))};
23417+            }
23418+
23419+            //! Avoids type nesting for `GenericAnyOf || some matcher` case
23420+            template<typename MatcherRHS>
23421+            friend std::enable_if_t<is_matcher<MatcherRHS>::value,
23422+            MatchAnyOfGeneric<MatcherTs..., MatcherRHS>> operator || (
23423+                    MatchAnyOfGeneric<MatcherTs...>&& lhs,
23424+                    MatcherRHS const& rhs) {
23425+                return MatchAnyOfGeneric<MatcherTs..., MatcherRHS>{array_cat(CATCH_MOVE(lhs.m_matchers), static_cast<void const*>(std::addressof(rhs)))};
23426+            }
23427+
23428+            //! Avoids type nesting for `some matcher || GenericAnyOf` case
23429+            template<typename MatcherLHS>
23430+            friend std::enable_if_t<is_matcher<MatcherLHS>::value,
23431+            MatchAnyOfGeneric<MatcherLHS, MatcherTs...>> operator || (
23432+                MatcherLHS const& lhs,
23433+                MatchAnyOfGeneric<MatcherTs...>&& rhs) {
23434+                return MatchAnyOfGeneric<MatcherLHS, MatcherTs...>{array_cat(static_cast<void const*>(std::addressof(lhs)), CATCH_MOVE(rhs.m_matchers))};
23435+            }
23436+        };
23437+
23438+
23439+        template<typename MatcherT>
23440+        class MatchNotOfGeneric final : public MatcherGenericBase {
23441+            MatcherT const& m_matcher;
23442+
23443+        public:
23444+            MatchNotOfGeneric(MatchNotOfGeneric const&) = delete;
23445+            MatchNotOfGeneric& operator=(MatchNotOfGeneric const&) = delete;
23446+            MatchNotOfGeneric(MatchNotOfGeneric&&) = default;
23447+            MatchNotOfGeneric& operator=(MatchNotOfGeneric&&) = default;
23448+
23449+            explicit MatchNotOfGeneric(MatcherT const& matcher) : m_matcher{matcher} {}
23450+
23451+            template<typename Arg>
23452+            bool match(Arg&& arg) const {
23453+                return !m_matcher.match(arg);
23454+            }
23455+
23456+            std::string describe() const override {
23457+                return "not " + m_matcher.toString();
23458+            }
23459+
23460+            //! Negating negation can just unwrap and return underlying matcher
23461+            friend MatcherT const& operator ! (MatchNotOfGeneric<MatcherT> const& matcher) {
23462+                return matcher.m_matcher;
23463+            }
23464+        };
23465+    } // namespace Detail
23466+
23467+
23468+    // compose only generic matchers
23469+    template<typename MatcherLHS, typename MatcherRHS>
23470+    std::enable_if_t<Detail::are_generic_matchers<MatcherLHS, MatcherRHS>::value, Detail::MatchAllOfGeneric<MatcherLHS, MatcherRHS>>
23471+        operator && (MatcherLHS const& lhs, MatcherRHS const& rhs) {
23472+        return { lhs, rhs };
23473+    }
23474+
23475+    template<typename MatcherLHS, typename MatcherRHS>
23476+    std::enable_if_t<Detail::are_generic_matchers<MatcherLHS, MatcherRHS>::value, Detail::MatchAnyOfGeneric<MatcherLHS, MatcherRHS>>
23477+        operator || (MatcherLHS const& lhs, MatcherRHS const& rhs) {
23478+        return { lhs, rhs };
23479+    }
23480+
23481+    //! Wrap provided generic matcher in generic negator
23482+    template<typename MatcherT>
23483+    std::enable_if_t<Detail::is_generic_matcher<MatcherT>::value, Detail::MatchNotOfGeneric<MatcherT>>
23484+        operator ! (MatcherT const& matcher) {
23485+        return Detail::MatchNotOfGeneric<MatcherT>{matcher};
23486+    }
23487+
23488+
23489+    // compose mixed generic and non-generic matchers
23490+    template<typename MatcherLHS, typename ArgRHS>
23491+    std::enable_if_t<Detail::is_generic_matcher<MatcherLHS>::value, Detail::MatchAllOfGeneric<MatcherLHS, MatcherBase<ArgRHS>>>
23492+        operator && (MatcherLHS const& lhs, MatcherBase<ArgRHS> const& rhs) {
23493+        return { lhs, rhs };
23494+    }
23495+
23496+    template<typename ArgLHS, typename MatcherRHS>
23497+    std::enable_if_t<Detail::is_generic_matcher<MatcherRHS>::value, Detail::MatchAllOfGeneric<MatcherBase<ArgLHS>, MatcherRHS>>
23498+        operator && (MatcherBase<ArgLHS> const& lhs, MatcherRHS const& rhs) {
23499+        return { lhs, rhs };
23500+    }
23501+
23502+    template<typename MatcherLHS, typename ArgRHS>
23503+    std::enable_if_t<Detail::is_generic_matcher<MatcherLHS>::value, Detail::MatchAnyOfGeneric<MatcherLHS, MatcherBase<ArgRHS>>>
23504+        operator || (MatcherLHS const& lhs, MatcherBase<ArgRHS> const& rhs) {
23505+        return { lhs, rhs };
23506+    }
23507+
23508+    template<typename ArgLHS, typename MatcherRHS>
23509+    std::enable_if_t<Detail::is_generic_matcher<MatcherRHS>::value, Detail::MatchAnyOfGeneric<MatcherBase<ArgLHS>, MatcherRHS>>
23510+        operator || (MatcherBase<ArgLHS> const& lhs, MatcherRHS const& rhs) {
23511+        return { lhs, rhs };
23512+    }
23513+
23514+} // namespace Matchers
23515+} // namespace Catch
23516+
23517+#endif // CATCH_MATCHERS_TEMPLATED_HPP_INCLUDED
23518+
23519+namespace Catch {
23520+    namespace Matchers {
23521+
23522+        class IsEmptyMatcher final : public MatcherGenericBase {
23523+        public:
23524+            template <typename RangeLike>
23525+            bool match(RangeLike&& rng) const {
23526+#if defined(CATCH_CONFIG_POLYFILL_NONMEMBER_CONTAINER_ACCESS)
23527+                using Catch::Detail::empty;
23528+#else
23529+                using std::empty;
23530+#endif
23531+                return empty(rng);
23532+            }
23533+
23534+            std::string describe() const override;
23535+        };
23536+
23537+        class HasSizeMatcher final : public MatcherGenericBase {
23538+            std::size_t m_target_size;
23539+        public:
23540+            explicit HasSizeMatcher(std::size_t target_size):
23541+                m_target_size(target_size)
23542+            {}
23543+
23544+            template <typename RangeLike>
23545+            bool match(RangeLike&& rng) const {
23546+#if defined(CATCH_CONFIG_POLYFILL_NONMEMBER_CONTAINER_ACCESS)
23547+                using Catch::Detail::size;
23548+#else
23549+                using std::size;
23550+#endif
23551+                return size(rng) == m_target_size;
23552+            }
23553+
23554+            std::string describe() const override;
23555+        };
23556+
23557+        template <typename Matcher>
23558+        class SizeMatchesMatcher final : public MatcherGenericBase {
23559+            Matcher m_matcher;
23560+        public:
23561+            explicit SizeMatchesMatcher(Matcher m):
23562+                m_matcher(CATCH_MOVE(m))
23563+            {}
23564+
23565+            template <typename RangeLike>
23566+            bool match(RangeLike&& rng) const {
23567+#if defined(CATCH_CONFIG_POLYFILL_NONMEMBER_CONTAINER_ACCESS)
23568+                using Catch::Detail::size;
23569+#else
23570+                using std::size;
23571+#endif
23572+                return m_matcher.match(size(rng));
23573+            }
23574+
23575+            std::string describe() const override {
23576+                return "size matches " + m_matcher.describe();
23577+            }
23578+        };
23579+
23580+
23581+        //! Creates a matcher that accepts empty ranges/containers
23582+        IsEmptyMatcher IsEmpty();
23583+        //! Creates a matcher that accepts ranges/containers with specific size
23584+        HasSizeMatcher SizeIs(std::size_t sz);
23585+        template <typename Matcher>
23586+        std::enable_if_t<Detail::is_matcher<Matcher>::value,
23587+        SizeMatchesMatcher<Matcher>> SizeIs(Matcher&& m) {
23588+            return SizeMatchesMatcher<Matcher>{CATCH_FORWARD(m)};
23589+        }
23590+
23591+    } // end namespace Matchers
23592+} // end namespace Catch
23593+
23594+#endif // CATCH_MATCHERS_CONTAINER_PROPERTIES_HPP_INCLUDED
23595+
23596+
23597+#ifndef CATCH_MATCHERS_CONTAINS_HPP_INCLUDED
23598+#define CATCH_MATCHERS_CONTAINS_HPP_INCLUDED
23599+
23600+
23601+#include <algorithm>
23602+#include <functional>
23603+
23604+namespace Catch {
23605+    namespace Matchers {
23606+        //! Matcher for checking that an element in range is equal to specific element
23607+        template <typename T, typename Equality>
23608+        class ContainsElementMatcher final : public MatcherGenericBase {
23609+            T m_desired;
23610+            Equality m_eq;
23611+        public:
23612+            template <typename T2, typename Equality2>
23613+            ContainsElementMatcher(T2&& target, Equality2&& predicate):
23614+                m_desired(CATCH_FORWARD(target)),
23615+                m_eq(CATCH_FORWARD(predicate))
23616+            {}
23617+
23618+            std::string describe() const override {
23619+                return "contains element " + Catch::Detail::stringify(m_desired);
23620+            }
23621+
23622+            template <typename RangeLike>
23623+            bool match( RangeLike&& rng ) const {
23624+                for ( auto&& elem : rng ) {
23625+                    if ( m_eq( elem, m_desired ) ) { return true; }
23626+                }
23627+                return false;
23628+            }
23629+        };
23630+
23631+        //! Meta-matcher for checking that an element in a range matches a specific matcher
23632+        template <typename Matcher>
23633+        class ContainsMatcherMatcher final : public MatcherGenericBase {
23634+            Matcher m_matcher;
23635+        public:
23636+            // Note that we do a copy+move to avoid having to SFINAE this
23637+            // constructor (and also avoid some perfect forwarding failure
23638+            // cases)
23639+            ContainsMatcherMatcher(Matcher matcher):
23640+                m_matcher(CATCH_MOVE(matcher))
23641+            {}
23642+
23643+            template <typename RangeLike>
23644+            bool match(RangeLike&& rng) const {
23645+                for (auto&& elem : rng) {
23646+                    if (m_matcher.match(elem)) {
23647+                        return true;
23648+                    }
23649+                }
23650+                return false;
23651+            }
23652+
23653+            std::string describe() const override {
23654+                return "contains element matching " + m_matcher.describe();
23655+            }
23656+        };
23657+
23658+        /**
23659+         * Creates a matcher that checks whether a range contains a specific element.
23660+         *
23661+         * Uses `std::equal_to` to do the comparison
23662+         */
23663+        template <typename T>
23664+        std::enable_if_t<!Detail::is_matcher<T>::value,
23665+        ContainsElementMatcher<T, std::equal_to<>>> Contains(T&& elem) {
23666+            return { CATCH_FORWARD(elem), std::equal_to<>{} };
23667+        }
23668+
23669+        //! Creates a matcher that checks whether a range contains element matching a matcher
23670+        template <typename Matcher>
23671+        std::enable_if_t<Detail::is_matcher<Matcher>::value,
23672+        ContainsMatcherMatcher<Matcher>> Contains(Matcher&& matcher) {
23673+            return { CATCH_FORWARD(matcher) };
23674+        }
23675+
23676+        /**
23677+         * Creates a matcher that checks whether a range contains a specific element.
23678+         *
23679+         * Uses `eq` to do the comparisons, the element is provided on the rhs
23680+         */
23681+        template <typename T, typename Equality>
23682+        ContainsElementMatcher<T, Equality> Contains(T&& elem, Equality&& eq) {
23683+            return { CATCH_FORWARD(elem), CATCH_FORWARD(eq) };
23684+        }
23685+
23686+    }
23687+}
23688+
23689+#endif // CATCH_MATCHERS_CONTAINS_HPP_INCLUDED
23690+
23691+
23692+#ifndef CATCH_MATCHERS_EXCEPTION_HPP_INCLUDED
23693+#define CATCH_MATCHERS_EXCEPTION_HPP_INCLUDED
23694+
23695+
23696+namespace Catch {
23697+namespace Matchers {
23698+
23699+class ExceptionMessageMatcher final : public MatcherBase<std::exception> {
23700+    std::string m_message;
23701+public:
23702+
23703+    ExceptionMessageMatcher(std::string const& message):
23704+        m_message(message)
23705+    {}
23706+
23707+    bool match(std::exception const& ex) const override;
23708+
23709+    std::string describe() const override;
23710+};
23711+
23712+//! Creates a matcher that checks whether a std derived exception has the provided message
23713+ExceptionMessageMatcher Message(std::string const& message);
23714+
23715+template <typename StringMatcherType>
23716+class ExceptionMessageMatchesMatcher final
23717+    : public MatcherBase<std::exception> {
23718+    StringMatcherType m_matcher;
23719+
23720+public:
23721+    ExceptionMessageMatchesMatcher( StringMatcherType matcher ):
23722+        m_matcher( CATCH_MOVE( matcher ) ) {}
23723+
23724+    bool match( std::exception const& ex ) const override {
23725+        return m_matcher.match( ex.what() );
23726+    }
23727+
23728+    std::string describe() const override {
23729+        return " matches \"" + m_matcher.describe() + '"';
23730+    }
23731+};
23732+
23733+//! Creates a matcher that checks whether a message from an std derived
23734+//! exception matches a provided matcher
23735+template <typename StringMatcherType>
23736+ExceptionMessageMatchesMatcher<StringMatcherType>
23737+MessageMatches( StringMatcherType&& matcher ) {
23738+    return { CATCH_FORWARD( matcher ) };
23739+}
23740+
23741+} // namespace Matchers
23742+} // namespace Catch
23743+
23744+#endif // CATCH_MATCHERS_EXCEPTION_HPP_INCLUDED
23745+
23746+
23747+#ifndef CATCH_MATCHERS_FLOATING_POINT_HPP_INCLUDED
23748+#define CATCH_MATCHERS_FLOATING_POINT_HPP_INCLUDED
23749+
23750+
23751+namespace Catch {
23752+namespace Matchers {
23753+
23754+    namespace Detail {
23755+        enum class FloatingPointKind : uint8_t;
23756+    }
23757+
23758+    class  WithinAbsMatcher final : public MatcherBase<double> {
23759+    public:
23760+        WithinAbsMatcher(double target, double margin);
23761+        bool match(double const& matchee) const override;
23762+        std::string describe() const override;
23763+    private:
23764+        double m_target;
23765+        double m_margin;
23766+    };
23767+
23768+    //! Creates a matcher that accepts numbers within certain range of target
23769+    WithinAbsMatcher WithinAbs( double target, double margin );
23770+
23771+
23772+
23773+    class WithinUlpsMatcher final : public MatcherBase<double> {
23774+    public:
23775+        WithinUlpsMatcher( double target,
23776+                           uint64_t ulps,
23777+                           Detail::FloatingPointKind baseType );
23778+        bool match(double const& matchee) const override;
23779+        std::string describe() const override;
23780+    private:
23781+        double m_target;
23782+        uint64_t m_ulps;
23783+        Detail::FloatingPointKind m_type;
23784+    };
23785+
23786+    //! Creates a matcher that accepts doubles within certain ULP range of target
23787+    WithinUlpsMatcher WithinULP(double target, uint64_t maxUlpDiff);
23788+    //! Creates a matcher that accepts floats within certain ULP range of target
23789+    WithinUlpsMatcher WithinULP(float target, uint64_t maxUlpDiff);
23790+
23791+
23792+
23793+    // Given IEEE-754 format for floats and doubles, we can assume
23794+    // that float -> double promotion is lossless. Given this, we can
23795+    // assume that if we do the standard relative comparison of
23796+    // |lhs - rhs| <= epsilon * max(fabs(lhs), fabs(rhs)), then we get
23797+    // the same result if we do this for floats, as if we do this for
23798+    // doubles that were promoted from floats.
23799+    class WithinRelMatcher final : public MatcherBase<double> {
23800+    public:
23801+        WithinRelMatcher( double target, double epsilon );
23802+        bool match(double const& matchee) const override;
23803+        std::string describe() const override;
23804+    private:
23805+        double m_target;
23806+        double m_epsilon;
23807+    };
23808+
23809+    //! Creates a matcher that accepts doubles within certain relative range of target
23810+    WithinRelMatcher WithinRel(double target, double eps);
23811+    //! Creates a matcher that accepts doubles within 100*DBL_EPS relative range of target
23812+    WithinRelMatcher WithinRel(double target);
23813+    //! Creates a matcher that accepts doubles within certain relative range of target
23814+    WithinRelMatcher WithinRel(float target, float eps);
23815+    //! Creates a matcher that accepts floats within 100*FLT_EPS relative range of target
23816+    WithinRelMatcher WithinRel(float target);
23817+
23818+
23819+
23820+    class IsNaNMatcher final : public MatcherBase<double> {
23821+    public:
23822+        IsNaNMatcher() = default;
23823+        bool match( double const& matchee ) const override;
23824+        std::string describe() const override;
23825+    };
23826+
23827+    IsNaNMatcher IsNaN();
23828+
23829+} // namespace Matchers
23830+} // namespace Catch
23831+
23832+#endif // CATCH_MATCHERS_FLOATING_POINT_HPP_INCLUDED
23833+
23834+
23835+#ifndef CATCH_MATCHERS_PREDICATE_HPP_INCLUDED
23836+#define CATCH_MATCHERS_PREDICATE_HPP_INCLUDED
23837+
23838+
23839+#include <string>
23840+
23841+namespace Catch {
23842+namespace Matchers {
23843+
23844+namespace Detail {
23845+    std::string finalizeDescription(const std::string& desc);
23846+} // namespace Detail
23847+
23848+template <typename T, typename Predicate>
23849+class PredicateMatcher final : public MatcherBase<T> {
23850+    Predicate m_predicate;
23851+    std::string m_description;
23852+public:
23853+
23854+    PredicateMatcher(Predicate&& elem, std::string const& descr)
23855+        :m_predicate(CATCH_FORWARD(elem)),
23856+        m_description(Detail::finalizeDescription(descr))
23857+    {}
23858+
23859+    bool match( T const& item ) const override {
23860+        return m_predicate(item);
23861+    }
23862+
23863+    std::string describe() const override {
23864+        return m_description;
23865+    }
23866+};
23867+
23868+    /**
23869+     * Creates a matcher that calls delegates `match` to the provided predicate.
23870+     *
23871+     * The user has to explicitly specify the argument type to the matcher
23872+     */
23873+    template<typename T, typename Pred>
23874+    PredicateMatcher<T, Pred> Predicate(Pred&& predicate, std::string const& description = "") {
23875+        static_assert(is_callable<Pred(T)>::value, "Predicate not callable with argument T");
23876+        static_assert(std::is_same<bool, FunctionReturnType<Pred, T>>::value, "Predicate does not return bool");
23877+        return PredicateMatcher<T, Pred>(CATCH_FORWARD(predicate), description);
23878+    }
23879+
23880+} // namespace Matchers
23881+} // namespace Catch
23882+
23883+#endif // CATCH_MATCHERS_PREDICATE_HPP_INCLUDED
23884+
23885+
23886+#ifndef CATCH_MATCHERS_QUANTIFIERS_HPP_INCLUDED
23887+#define CATCH_MATCHERS_QUANTIFIERS_HPP_INCLUDED
23888+
23889+
23890+namespace Catch {
23891+    namespace Matchers {
23892+        // Matcher for checking that all elements in range matches a given matcher.
23893+        template <typename Matcher>
23894+        class AllMatchMatcher final : public MatcherGenericBase {
23895+            Matcher m_matcher;
23896+        public:
23897+            AllMatchMatcher(Matcher matcher):
23898+                m_matcher(CATCH_MOVE(matcher))
23899+            {}
23900+
23901+            std::string describe() const override {
23902+                return "all match " + m_matcher.describe();
23903+            }
23904+
23905+            template <typename RangeLike>
23906+            bool match(RangeLike&& rng) const {
23907+                for (auto&& elem : rng) {
23908+                    if (!m_matcher.match(elem)) {
23909+                        return false;
23910+                    }
23911+                }
23912+                return true;
23913+            }
23914+        };
23915+
23916+        // Matcher for checking that no element in range matches a given matcher.
23917+        template <typename Matcher>
23918+        class NoneMatchMatcher final : public MatcherGenericBase {
23919+            Matcher m_matcher;
23920+        public:
23921+            NoneMatchMatcher(Matcher matcher):
23922+                m_matcher(CATCH_MOVE(matcher))
23923+            {}
23924+
23925+            std::string describe() const override {
23926+                return "none match " + m_matcher.describe();
23927+            }
23928+
23929+            template <typename RangeLike>
23930+            bool match(RangeLike&& rng) const {
23931+                for (auto&& elem : rng) {
23932+                    if (m_matcher.match(elem)) {
23933+                        return false;
23934+                    }
23935+                }
23936+                return true;
23937+            }
23938+        };
23939+
23940+        // Matcher for checking that at least one element in range matches a given matcher.
23941+        template <typename Matcher>
23942+        class AnyMatchMatcher final : public MatcherGenericBase {
23943+            Matcher m_matcher;
23944+        public:
23945+            AnyMatchMatcher(Matcher matcher):
23946+                m_matcher(CATCH_MOVE(matcher))
23947+            {}
23948+
23949+            std::string describe() const override {
23950+                return "any match " + m_matcher.describe();
23951+            }
23952+
23953+            template <typename RangeLike>
23954+            bool match(RangeLike&& rng) const {
23955+                for (auto&& elem : rng) {
23956+                    if (m_matcher.match(elem)) {
23957+                        return true;
23958+                    }
23959+                }
23960+                return false;
23961+            }
23962+        };
23963+
23964+        // Matcher for checking that all elements in range are true.
23965+        class AllTrueMatcher final : public MatcherGenericBase {
23966+        public:
23967+            std::string describe() const override;
23968+
23969+            template <typename RangeLike>
23970+            bool match(RangeLike&& rng) const {
23971+                for (auto&& elem : rng) {
23972+                    if (!elem) {
23973+                        return false;
23974+                    }
23975+                }
23976+                return true;
23977+            }
23978+        };
23979+
23980+        // Matcher for checking that no element in range is true.
23981+        class NoneTrueMatcher final : public MatcherGenericBase {
23982+        public:
23983+            std::string describe() const override;
23984+
23985+            template <typename RangeLike>
23986+            bool match(RangeLike&& rng) const {
23987+                for (auto&& elem : rng) {
23988+                    if (elem) {
23989+                        return false;
23990+                    }
23991+                }
23992+                return true;
23993+            }
23994+        };
23995+
23996+        // Matcher for checking that any element in range is true.
23997+        class AnyTrueMatcher final : public MatcherGenericBase {
23998+        public:
23999+            std::string describe() const override;
24000+
24001+            template <typename RangeLike>
24002+            bool match(RangeLike&& rng) const {
24003+                for (auto&& elem : rng) {
24004+                    if (elem) {
24005+                        return true;
24006+                    }
24007+                }
24008+                return false;
24009+            }
24010+        };
24011+
24012+        // Creates a matcher that checks whether all elements in a range match a matcher
24013+        template <typename Matcher>
24014+        AllMatchMatcher<Matcher> AllMatch(Matcher&& matcher) {
24015+            return { CATCH_FORWARD(matcher) };
24016+        }
24017+
24018+        // Creates a matcher that checks whether no element in a range matches a matcher.
24019+        template <typename Matcher>
24020+        NoneMatchMatcher<Matcher> NoneMatch(Matcher&& matcher) {
24021+            return { CATCH_FORWARD(matcher) };
24022+        }
24023+
24024+        // Creates a matcher that checks whether any element in a range matches a matcher.
24025+        template <typename Matcher>
24026+        AnyMatchMatcher<Matcher> AnyMatch(Matcher&& matcher) {
24027+            return { CATCH_FORWARD(matcher) };
24028+        }
24029+
24030+        // Creates a matcher that checks whether all elements in a range are true
24031+        AllTrueMatcher AllTrue();
24032+
24033+        // Creates a matcher that checks whether no element in a range is true
24034+        NoneTrueMatcher NoneTrue();
24035+
24036+        // Creates a matcher that checks whether any element in a range is true
24037+        AnyTrueMatcher AnyTrue();
24038+    }
24039+}
24040+
24041+#endif // CATCH_MATCHERS_QUANTIFIERS_HPP_INCLUDED
24042+
24043+
24044+#ifndef CATCH_MATCHERS_RANGE_EQUALS_HPP_INCLUDED
24045+#define CATCH_MATCHERS_RANGE_EQUALS_HPP_INCLUDED
24046+
24047+
24048+#include <algorithm>
24049+#include <utility>
24050+
24051+namespace Catch {
24052+    namespace Matchers {
24053+
24054+        /**
24055+         * Matcher for checking that an element contains the same
24056+         * elements in the same order
24057+         */
24058+        template <typename TargetRangeLike, typename Equality>
24059+        class RangeEqualsMatcher final : public MatcherGenericBase {
24060+            TargetRangeLike m_desired;
24061+            Equality m_predicate;
24062+
24063+        public:
24064+            template <typename TargetRangeLike2, typename Equality2>
24065+            RangeEqualsMatcher( TargetRangeLike2&& range,
24066+                                Equality2&& predicate ):
24067+                m_desired( CATCH_FORWARD( range ) ),
24068+                m_predicate( CATCH_FORWARD( predicate ) ) {}
24069+
24070+            template <typename RangeLike>
24071+            bool match( RangeLike&& rng ) const {
24072+                auto rng_start = begin( rng );
24073+                const auto rng_end = end( rng );
24074+                auto target_start = begin( m_desired );
24075+                const auto target_end = end( m_desired );
24076+
24077+                while (rng_start != rng_end && target_start != target_end) {
24078+                    if (!m_predicate(*rng_start, *target_start)) {
24079+                        return false;
24080+                    }
24081+                    ++rng_start;
24082+                    ++target_start;
24083+                }
24084+                return rng_start == rng_end && target_start == target_end;
24085+            }
24086+
24087+            std::string describe() const override {
24088+                return "elements are " + Catch::Detail::stringify( m_desired );
24089+            }
24090+        };
24091+
24092+        /**
24093+         * Matcher for checking that an element contains the same
24094+         * elements (but not necessarily in the same order)
24095+         */
24096+        template <typename TargetRangeLike, typename Equality>
24097+        class UnorderedRangeEqualsMatcher final : public MatcherGenericBase {
24098+            TargetRangeLike m_desired;
24099+            Equality m_predicate;
24100+
24101+        public:
24102+            template <typename TargetRangeLike2, typename Equality2>
24103+            UnorderedRangeEqualsMatcher( TargetRangeLike2&& range,
24104+                                         Equality2&& predicate ):
24105+                m_desired( CATCH_FORWARD( range ) ),
24106+                m_predicate( CATCH_FORWARD( predicate ) ) {}
24107+
24108+            template <typename RangeLike>
24109+            bool match( RangeLike&& rng ) const {
24110+                using std::begin;
24111+                using std::end;
24112+                return Catch::Detail::is_permutation( begin( m_desired ),
24113+                                                      end( m_desired ),
24114+                                                      begin( rng ),
24115+                                                      end( rng ),
24116+                                                      m_predicate );
24117+            }
24118+
24119+            std::string describe() const override {
24120+                return "unordered elements are " +
24121+                       ::Catch::Detail::stringify( m_desired );
24122+            }
24123+        };
24124+
24125+        /**
24126+         * Creates a matcher that checks if all elements in a range are equal
24127+         * to all elements in another range.
24128+         *
24129+         * Uses `std::equal_to` to do the comparison
24130+         */
24131+        template <typename RangeLike>
24132+        std::enable_if_t<!Detail::is_matcher<RangeLike>::value,
24133+                         RangeEqualsMatcher<RangeLike, std::equal_to<>>>
24134+        RangeEquals( RangeLike&& range ) {
24135+            return { CATCH_FORWARD( range ), std::equal_to<>{} };
24136+        }
24137+
24138+        /**
24139+         * Creates a matcher that checks if all elements in a range are equal
24140+         * to all elements in another range.
24141+         *
24142+         * Uses to provided predicate `predicate` to do the comparisons
24143+         */
24144+        template <typename RangeLike, typename Equality>
24145+        RangeEqualsMatcher<RangeLike, Equality>
24146+        RangeEquals( RangeLike&& range, Equality&& predicate ) {
24147+            return { CATCH_FORWARD( range ), CATCH_FORWARD( predicate ) };
24148+        }
24149+
24150+        /**
24151+         * Creates a matcher that checks if all elements in a range are equal
24152+         * to all elements in another range, in some permutation
24153+         *
24154+         * Uses `std::equal_to` to do the comparison
24155+         */
24156+        template <typename RangeLike>
24157+        std::enable_if_t<
24158+            !Detail::is_matcher<RangeLike>::value,
24159+            UnorderedRangeEqualsMatcher<RangeLike, std::equal_to<>>>
24160+        UnorderedRangeEquals( RangeLike&& range ) {
24161+            return { CATCH_FORWARD( range ), std::equal_to<>{} };
24162+        }
24163+
24164+        /**
24165+         * Creates a matcher that checks if all elements in a range are equal
24166+         * to all elements in another range, in some permutation.
24167+         *
24168+         * Uses to provided predicate `predicate` to do the comparisons
24169+         */
24170+        template <typename RangeLike, typename Equality>
24171+        UnorderedRangeEqualsMatcher<RangeLike, Equality>
24172+        UnorderedRangeEquals( RangeLike&& range, Equality&& predicate ) {
24173+            return { CATCH_FORWARD( range ), CATCH_FORWARD( predicate ) };
24174+        }
24175+    } // namespace Matchers
24176+} // namespace Catch
24177+
24178+#endif // CATCH_MATCHERS_RANGE_EQUALS_HPP_INCLUDED
24179+
24180+
24181+#ifndef CATCH_MATCHERS_STRING_HPP_INCLUDED
24182+#define CATCH_MATCHERS_STRING_HPP_INCLUDED
24183+
24184+
24185+#include <string>
24186+
24187+namespace Catch {
24188+namespace Matchers {
24189+
24190+    struct CasedString {
24191+        CasedString( std::string const& str, CaseSensitive caseSensitivity );
24192+        std::string adjustString( std::string const& str ) const;
24193+        StringRef caseSensitivitySuffix() const;
24194+
24195+        CaseSensitive m_caseSensitivity;
24196+        std::string m_str;
24197+    };
24198+
24199+    class StringMatcherBase : public MatcherBase<std::string> {
24200+    protected:
24201+        CasedString m_comparator;
24202+        StringRef m_operation;
24203+
24204+    public:
24205+        StringMatcherBase( StringRef operation,
24206+                           CasedString const& comparator );
24207+        std::string describe() const override;
24208+    };
24209+
24210+    class StringEqualsMatcher final : public StringMatcherBase {
24211+    public:
24212+        StringEqualsMatcher( CasedString const& comparator );
24213+        bool match( std::string const& source ) const override;
24214+    };
24215+    class StringContainsMatcher final : public StringMatcherBase {
24216+    public:
24217+        StringContainsMatcher( CasedString const& comparator );
24218+        bool match( std::string const& source ) const override;
24219+    };
24220+    class StartsWithMatcher final : public StringMatcherBase {
24221+    public:
24222+        StartsWithMatcher( CasedString const& comparator );
24223+        bool match( std::string const& source ) const override;
24224+    };
24225+    class EndsWithMatcher final : public StringMatcherBase {
24226+    public:
24227+        EndsWithMatcher( CasedString const& comparator );
24228+        bool match( std::string const& source ) const override;
24229+    };
24230+
24231+    class RegexMatcher final : public MatcherBase<std::string> {
24232+        std::string m_regex;
24233+        CaseSensitive m_caseSensitivity;
24234+
24235+    public:
24236+        RegexMatcher( std::string regex, CaseSensitive caseSensitivity );
24237+        bool match( std::string const& matchee ) const override;
24238+        std::string describe() const override;
24239+    };
24240+
24241+    //! Creates matcher that accepts strings that are exactly equal to `str`
24242+    StringEqualsMatcher Equals( std::string const& str, CaseSensitive caseSensitivity = CaseSensitive::Yes );
24243+    //! Creates matcher that accepts strings that contain `str`
24244+    StringContainsMatcher ContainsSubstring( std::string const& str, CaseSensitive caseSensitivity = CaseSensitive::Yes );
24245+    //! Creates matcher that accepts strings that _end_ with `str`
24246+    EndsWithMatcher EndsWith( std::string const& str, CaseSensitive caseSensitivity = CaseSensitive::Yes );
24247+    //! Creates matcher that accepts strings that _start_ with `str`
24248+    StartsWithMatcher StartsWith( std::string const& str, CaseSensitive caseSensitivity = CaseSensitive::Yes );
24249+    //! Creates matcher that accepts strings matching `regex`
24250+    RegexMatcher Matches( std::string const& regex, CaseSensitive caseSensitivity = CaseSensitive::Yes );
24251+
24252+} // namespace Matchers
24253+} // namespace Catch
24254+
24255+#endif // CATCH_MATCHERS_STRING_HPP_INCLUDED
24256+
24257+
24258+#ifndef CATCH_MATCHERS_VECTOR_HPP_INCLUDED
24259+#define CATCH_MATCHERS_VECTOR_HPP_INCLUDED
24260+
24261+
24262+#include <algorithm>
24263+
24264+namespace Catch {
24265+namespace Matchers {
24266+
24267+    template<typename T, typename Alloc>
24268+    class VectorContainsElementMatcher final : public MatcherBase<std::vector<T, Alloc>> {
24269+        T const& m_comparator;
24270+
24271+    public:
24272+        VectorContainsElementMatcher(T const& comparator):
24273+            m_comparator(comparator)
24274+        {}
24275+
24276+        bool match(std::vector<T, Alloc> const& v) const override {
24277+            for (auto const& el : v) {
24278+                if (el == m_comparator) {
24279+                    return true;
24280+                }
24281+            }
24282+            return false;
24283+        }
24284+
24285+        std::string describe() const override {
24286+            return "Contains: " + ::Catch::Detail::stringify( m_comparator );
24287+        }
24288+    };
24289+
24290+    template<typename T, typename AllocComp, typename AllocMatch>
24291+    class ContainsMatcher final : public MatcherBase<std::vector<T, AllocMatch>> {
24292+        std::vector<T, AllocComp> const& m_comparator;
24293+
24294+    public:
24295+        ContainsMatcher(std::vector<T, AllocComp> const& comparator):
24296+            m_comparator( comparator )
24297+        {}
24298+
24299+        bool match(std::vector<T, AllocMatch> const& v) const override {
24300+            // !TBD: see note in EqualsMatcher
24301+            if (m_comparator.size() > v.size())
24302+                return false;
24303+            for (auto const& comparator : m_comparator) {
24304+                auto present = false;
24305+                for (const auto& el : v) {
24306+                    if (el == comparator) {
24307+                        present = true;
24308+                        break;
24309+                    }
24310+                }
24311+                if (!present) {
24312+                    return false;
24313+                }
24314+            }
24315+            return true;
24316+        }
24317+        std::string describe() const override {
24318+            return "Contains: " + ::Catch::Detail::stringify( m_comparator );
24319+        }
24320+    };
24321+
24322+    template<typename T, typename AllocComp, typename AllocMatch>
24323+    class EqualsMatcher final : public MatcherBase<std::vector<T, AllocMatch>> {
24324+        std::vector<T, AllocComp> const& m_comparator;
24325+
24326+    public:
24327+        EqualsMatcher(std::vector<T, AllocComp> const& comparator):
24328+            m_comparator( comparator )
24329+        {}
24330+
24331+        bool match(std::vector<T, AllocMatch> const& v) const override {
24332+            // !TBD: This currently works if all elements can be compared using !=
24333+            // - a more general approach would be via a compare template that defaults
24334+            // to using !=. but could be specialised for, e.g. std::vector<T> etc
24335+            // - then just call that directly
24336+            if ( m_comparator.size() != v.size() ) { return false; }
24337+            for ( std::size_t i = 0; i < v.size(); ++i ) {
24338+                if ( !( m_comparator[i] == v[i] ) ) { return false; }
24339+            }
24340+            return true;
24341+        }
24342+        std::string describe() const override {
24343+            return "Equals: " + ::Catch::Detail::stringify( m_comparator );
24344+        }
24345+    };
24346+
24347+    template<typename T, typename AllocComp, typename AllocMatch>
24348+    class ApproxMatcher final : public MatcherBase<std::vector<T, AllocMatch>> {
24349+        std::vector<T, AllocComp> const& m_comparator;
24350+        mutable Catch::Approx approx = Catch::Approx::custom();
24351+
24352+    public:
24353+        ApproxMatcher(std::vector<T, AllocComp> const& comparator):
24354+            m_comparator( comparator )
24355+        {}
24356+
24357+        bool match(std::vector<T, AllocMatch> const& v) const override {
24358+            if (m_comparator.size() != v.size())
24359+                return false;
24360+            for (std::size_t i = 0; i < v.size(); ++i)
24361+                if (m_comparator[i] != approx(v[i]))
24362+                    return false;
24363+            return true;
24364+        }
24365+        std::string describe() const override {
24366+            return "is approx: " + ::Catch::Detail::stringify( m_comparator );
24367+        }
24368+        template <typename = std::enable_if_t<std::is_constructible<double, T>::value>>
24369+        ApproxMatcher& epsilon( T const& newEpsilon ) {
24370+            approx.epsilon(static_cast<double>(newEpsilon));
24371+            return *this;
24372+        }
24373+        template <typename = std::enable_if_t<std::is_constructible<double, T>::value>>
24374+        ApproxMatcher& margin( T const& newMargin ) {
24375+            approx.margin(static_cast<double>(newMargin));
24376+            return *this;
24377+        }
24378+        template <typename = std::enable_if_t<std::is_constructible<double, T>::value>>
24379+        ApproxMatcher& scale( T const& newScale ) {
24380+            approx.scale(static_cast<double>(newScale));
24381+            return *this;
24382+        }
24383+    };
24384+
24385+    template<typename T, typename AllocComp, typename AllocMatch>
24386+    class UnorderedEqualsMatcher final : public MatcherBase<std::vector<T, AllocMatch>> {
24387+        std::vector<T, AllocComp> const& m_target;
24388+
24389+    public:
24390+        UnorderedEqualsMatcher(std::vector<T, AllocComp> const& target):
24391+            m_target(target)
24392+        {}
24393+        bool match(std::vector<T, AllocMatch> const& vec) const override {
24394+            if (m_target.size() != vec.size()) {
24395+                return false;
24396+            }
24397+            return std::is_permutation(m_target.begin(), m_target.end(), vec.begin());
24398+        }
24399+
24400+        std::string describe() const override {
24401+            return "UnorderedEquals: " + ::Catch::Detail::stringify(m_target);
24402+        }
24403+    };
24404+
24405+
24406+    // The following functions create the actual matcher objects.
24407+    // This allows the types to be inferred
24408+
24409+    //! Creates a matcher that matches vectors that contain all elements in `comparator`
24410+    template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp>
24411+    ContainsMatcher<T, AllocComp, AllocMatch> Contains( std::vector<T, AllocComp> const& comparator ) {
24412+        return ContainsMatcher<T, AllocComp, AllocMatch>(comparator);
24413+    }
24414+
24415+    //! Creates a matcher that matches vectors that contain `comparator` as an element
24416+    template<typename T, typename Alloc = std::allocator<T>>
24417+    VectorContainsElementMatcher<T, Alloc> VectorContains( T const& comparator ) {
24418+        return VectorContainsElementMatcher<T, Alloc>(comparator);
24419+    }
24420+
24421+    //! Creates a matcher that matches vectors that are exactly equal to `comparator`
24422+    template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp>
24423+    EqualsMatcher<T, AllocComp, AllocMatch> Equals( std::vector<T, AllocComp> const& comparator ) {
24424+        return EqualsMatcher<T, AllocComp, AllocMatch>(comparator);
24425+    }
24426+
24427+    //! Creates a matcher that matches vectors that `comparator` as an element
24428+    template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp>
24429+    ApproxMatcher<T, AllocComp, AllocMatch> Approx( std::vector<T, AllocComp> const& comparator ) {
24430+        return ApproxMatcher<T, AllocComp, AllocMatch>(comparator);
24431+    }
24432+
24433+    //! Creates a matcher that matches vectors that is equal to `target` modulo permutation
24434+    template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp>
24435+    UnorderedEqualsMatcher<T, AllocComp, AllocMatch> UnorderedEquals(std::vector<T, AllocComp> const& target) {
24436+        return UnorderedEqualsMatcher<T, AllocComp, AllocMatch>(target);
24437+    }
24438+
24439+} // namespace Matchers
24440+} // namespace Catch
24441+
24442+#endif // CATCH_MATCHERS_VECTOR_HPP_INCLUDED
24443+
24444+#endif // CATCH_MATCHERS_ALL_HPP_INCLUDED
24445+
24446+
24447+/** \file
24448+ * This is a convenience header for Catch2's Reporter support. It includes
24449+ * **all** of Catch2 headers related to reporters, including all reporters.
24450+ *
24451+ * Generally the Catch2 users should use specific includes they need,
24452+ * but this header can be used instead for ease-of-experimentation, or
24453+ * just plain convenience, at the cost of (significantly) increased
24454+ * compilation times.
24455+ *
24456+ * When a new header (reporter) is added to either the `reporter` folder,
24457+ * or to the corresponding internal subfolder, it should be added here.
24458+ */
24459+
24460+#ifndef CATCH_REPORTERS_ALL_HPP_INCLUDED
24461+#define CATCH_REPORTERS_ALL_HPP_INCLUDED
24462+
24463+
24464+
24465+#ifndef CATCH_REPORTER_AUTOMAKE_HPP_INCLUDED
24466+#define CATCH_REPORTER_AUTOMAKE_HPP_INCLUDED
24467+
24468+
24469+
24470+#ifndef CATCH_REPORTER_STREAMING_BASE_HPP_INCLUDED
24471+#define CATCH_REPORTER_STREAMING_BASE_HPP_INCLUDED
24472+
24473+
24474+
24475+#ifndef CATCH_REPORTER_COMMON_BASE_HPP_INCLUDED
24476+#define CATCH_REPORTER_COMMON_BASE_HPP_INCLUDED
24477+
24478+
24479+#include <map>
24480+#include <string>
24481+
24482+namespace Catch {
24483+    class ColourImpl;
24484+
24485+    /**
24486+     * This is the base class for all reporters.
24487+     *
24488+     * If are writing a reporter, you must derive from this type, or one
24489+     * of the helper reporter bases that are derived from this type.
24490+     *
24491+     * ReporterBase centralizes handling of various common tasks in reporters,
24492+     * like storing the right stream for the reporters to write to, and
24493+     * providing the default implementation of the different listing events.
24494+     */
24495+    class ReporterBase : public IEventListener {
24496+    protected:
24497+        //! The stream wrapper as passed to us by outside code
24498+        Detail::unique_ptr<IStream> m_wrapped_stream;
24499+        //! Cached output stream from `m_wrapped_stream` to reduce
24500+        //! number of indirect calls needed to write output.
24501+        std::ostream& m_stream;
24502+        //! Colour implementation this reporter was configured for
24503+        Detail::unique_ptr<ColourImpl> m_colour;
24504+        //! The custom reporter options user passed down to the reporter
24505+        std::map<std::string, std::string> m_customOptions;
24506+
24507+    public:
24508+        ReporterBase( ReporterConfig&& config );
24509+        ~ReporterBase() override; // = default;
24510+
24511+        /**
24512+         * Provides a simple default listing of reporters.
24513+         *
24514+         * Should look roughly like the reporter listing in v2 and earlier
24515+         * versions of Catch2.
24516+         */
24517+        void listReporters(
24518+            std::vector<ReporterDescription> const& descriptions ) override;
24519+        /**
24520+         * Provides a simple default listing of listeners
24521+         *
24522+         * Looks similarly to listing of reporters, but with listener type
24523+         * instead of reporter name.
24524+         */
24525+        void listListeners(
24526+            std::vector<ListenerDescription> const& descriptions ) override;
24527+        /**
24528+         * Provides a simple default listing of tests.
24529+         *
24530+         * Should look roughly like the test listing in v2 and earlier versions
24531+         * of Catch2. Especially supports low-verbosity listing that mimics the
24532+         * old `--list-test-names-only` output.
24533+         */
24534+        void listTests( std::vector<TestCaseHandle> const& tests ) override;
24535+        /**
24536+         * Provides a simple default listing of tags.
24537+         *
24538+         * Should look roughly like the tag listing in v2 and earlier versions
24539+         * of Catch2.
24540+         */
24541+        void listTags( std::vector<TagInfo> const& tags ) override;
24542+    };
24543+} // namespace Catch
24544+
24545+#endif // CATCH_REPORTER_COMMON_BASE_HPP_INCLUDED
24546+
24547+#include <vector>
24548+
24549+namespace Catch {
24550+
24551+    class StreamingReporterBase : public ReporterBase {
24552+    public:
24553+        // GCC5 compat: we cannot use inherited constructor, because it
24554+        //              doesn't implement backport of P0136
24555+        StreamingReporterBase(ReporterConfig&& _config):
24556+            ReporterBase(CATCH_MOVE(_config))
24557+        {}
24558+        ~StreamingReporterBase() override;
24559+
24560+        void benchmarkPreparing( StringRef ) override {}
24561+        void benchmarkStarting( BenchmarkInfo const& ) override {}
24562+        void benchmarkEnded( BenchmarkStats<> const& ) override {}
24563+        void benchmarkFailed( StringRef ) override {}
24564+
24565+        void fatalErrorEncountered( StringRef /*error*/ ) override {}
24566+        void noMatchingTestCases( StringRef /*unmatchedSpec*/ ) override {}
24567+        void reportInvalidTestSpec( StringRef /*invalidArgument*/ ) override {}
24568+
24569+        void testRunStarting( TestRunInfo const& _testRunInfo ) override;
24570+
24571+        void testCaseStarting(TestCaseInfo const& _testInfo) override  {
24572+            currentTestCaseInfo = &_testInfo;
24573+        }
24574+        void testCasePartialStarting( TestCaseInfo const&, uint64_t ) override {}
24575+        void sectionStarting(SectionInfo const& _sectionInfo) override {
24576+            m_sectionStack.push_back(_sectionInfo);
24577+        }
24578+
24579+        void assertionStarting( AssertionInfo const& ) override {}
24580+        void assertionEnded( AssertionStats const& ) override {}
24581+
24582+        void sectionEnded(SectionStats const& /* _sectionStats */) override {
24583+            m_sectionStack.pop_back();
24584+        }
24585+        void testCasePartialEnded( TestCaseStats const&, uint64_t ) override {}
24586+        void testCaseEnded(TestCaseStats const& /* _testCaseStats */) override {
24587+            currentTestCaseInfo = nullptr;
24588+        }
24589+        void testRunEnded( TestRunStats const& /* _testRunStats */ ) override;
24590+
24591+        void skipTest(TestCaseInfo const&) override {
24592+            // Don't do anything with this by default.
24593+            // It can optionally be overridden in the derived class.
24594+        }
24595+
24596+    protected:
24597+        TestRunInfo currentTestRunInfo{ "test run has not started yet"_sr };
24598+        TestCaseInfo const* currentTestCaseInfo = nullptr;
24599+
24600+        //! Stack of all _active_ sections in the _current_ test case
24601+        std::vector<SectionInfo> m_sectionStack;
24602+    };
24603+
24604+} // end namespace Catch
24605+
24606+#endif // CATCH_REPORTER_STREAMING_BASE_HPP_INCLUDED
24607+
24608+#include <string>
24609+
24610+namespace Catch {
24611+
24612+    class AutomakeReporter final : public StreamingReporterBase {
24613+    public:
24614+        // GCC5 compat: we cannot use inherited constructor, because it
24615+        //              doesn't implement backport of P0136
24616+        AutomakeReporter(ReporterConfig&& _config):
24617+            StreamingReporterBase(CATCH_MOVE(_config))
24618+        {}
24619+        ~AutomakeReporter() override;
24620+
24621+        static std::string getDescription() {
24622+            using namespace std::string_literals;
24623+            return "Reports test results in the format of Automake .trs files"s;
24624+        }
24625+
24626+        void testCaseEnded(TestCaseStats const& _testCaseStats) override;
24627+        void skipTest(TestCaseInfo const& testInfo) override;
24628+    };
24629+
24630+} // end namespace Catch
24631+
24632+#endif // CATCH_REPORTER_AUTOMAKE_HPP_INCLUDED
24633+
24634+
24635+#ifndef CATCH_REPORTER_COMPACT_HPP_INCLUDED
24636+#define CATCH_REPORTER_COMPACT_HPP_INCLUDED
24637+
24638+
24639+
24640+
24641+namespace Catch {
24642+
24643+    class CompactReporter final : public StreamingReporterBase {
24644+    public:
24645+        using StreamingReporterBase::StreamingReporterBase;
24646+
24647+        ~CompactReporter() override;
24648+
24649+        static std::string getDescription();
24650+
24651+        void noMatchingTestCases( StringRef unmatchedSpec ) override;
24652+
24653+        void testRunStarting( TestRunInfo const& _testInfo ) override;
24654+
24655+        void assertionEnded(AssertionStats const& _assertionStats) override;
24656+
24657+        void sectionEnded(SectionStats const& _sectionStats) override;
24658+
24659+        void testRunEnded(TestRunStats const& _testRunStats) override;
24660+
24661+    };
24662+
24663+} // end namespace Catch
24664+
24665+#endif // CATCH_REPORTER_COMPACT_HPP_INCLUDED
24666+
24667+
24668+#ifndef CATCH_REPORTER_CONSOLE_HPP_INCLUDED
24669+#define CATCH_REPORTER_CONSOLE_HPP_INCLUDED
24670+
24671+
24672+namespace Catch {
24673+    // Fwd decls
24674+    class TablePrinter;
24675+
24676+    class ConsoleReporter final : public StreamingReporterBase {
24677+        Detail::unique_ptr<TablePrinter> m_tablePrinter;
24678+
24679+    public:
24680+        ConsoleReporter(ReporterConfig&& config);
24681+        ~ConsoleReporter() override;
24682+        static std::string getDescription();
24683+
24684+        void noMatchingTestCases( StringRef unmatchedSpec ) override;
24685+        void reportInvalidTestSpec( StringRef arg ) override;
24686+
24687+        void assertionStarting(AssertionInfo const&) override;
24688+
24689+        void assertionEnded(AssertionStats const& _assertionStats) override;
24690+
24691+        void sectionStarting(SectionInfo const& _sectionInfo) override;
24692+        void sectionEnded(SectionStats const& _sectionStats) override;
24693+
24694+        void benchmarkPreparing( StringRef name ) override;
24695+        void benchmarkStarting(BenchmarkInfo const& info) override;
24696+        void benchmarkEnded(BenchmarkStats<> const& stats) override;
24697+        void benchmarkFailed( StringRef error ) override;
24698+
24699+        void testCaseEnded(TestCaseStats const& _testCaseStats) override;
24700+        void testRunEnded(TestRunStats const& _testRunStats) override;
24701+        void testRunStarting(TestRunInfo const& _testRunInfo) override;
24702+
24703+    private:
24704+        void lazyPrint();
24705+
24706+        void lazyPrintWithoutClosingBenchmarkTable();
24707+        void lazyPrintRunInfo();
24708+        void printTestCaseAndSectionHeader();
24709+
24710+        void printClosedHeader(std::string const& _name);
24711+        void printOpenHeader(std::string const& _name);
24712+
24713+        // if string has a : in first line will set indent to follow it on
24714+        // subsequent lines
24715+        void printHeaderString(std::string const& _string, std::size_t indent = 0);
24716+
24717+        void printTotalsDivider(Totals const& totals);
24718+
24719+        bool m_headerPrinted = false;
24720+        bool m_testRunInfoPrinted = false;
24721+    };
24722+
24723+} // end namespace Catch
24724+
24725+#endif // CATCH_REPORTER_CONSOLE_HPP_INCLUDED
24726+
24727+
24728+#ifndef CATCH_REPORTER_CUMULATIVE_BASE_HPP_INCLUDED
24729+#define CATCH_REPORTER_CUMULATIVE_BASE_HPP_INCLUDED
24730+
24731+
24732+#include <string>
24733+#include <vector>
24734+
24735+namespace Catch {
24736+
24737+    namespace Detail {
24738+
24739+        //! Represents either an assertion or a benchmark result to be handled by cumulative reporter later
24740+        class AssertionOrBenchmarkResult {
24741+            // This should really be a variant, but this is much faster
24742+            // to write and the data layout here is already terrible
24743+            // enough that we do not have to care about the object size.
24744+            Optional<AssertionStats> m_assertion;
24745+            Optional<BenchmarkStats<>> m_benchmark;
24746+        public:
24747+            AssertionOrBenchmarkResult(AssertionStats const& assertion);
24748+            AssertionOrBenchmarkResult(BenchmarkStats<> const& benchmark);
24749+
24750+            bool isAssertion() const;
24751+            bool isBenchmark() const;
24752+
24753+            AssertionStats const& asAssertion() const;
24754+            BenchmarkStats<> const& asBenchmark() const;
24755+        };
24756+    }
24757+
24758+    /**
24759+     * Utility base for reporters that need to handle all results at once
24760+     *
24761+     * It stores tree of all test cases, sections and assertions, and after the
24762+     * test run is finished, calls into `testRunEndedCumulative` to pass the
24763+     * control to the deriving class.
24764+     *
24765+     * If you are deriving from this class and override any testing related
24766+     * member functions, you should first call into the base's implementation to
24767+     * avoid breaking the tree construction.
24768+     *
24769+     * Due to the way this base functions, it has to expand assertions up-front,
24770+     * even if they are later unused (e.g. because the deriving reporter does
24771+     * not report successful assertions, or because the deriving reporter does
24772+     * not use assertion expansion at all). Derived classes can use two
24773+     * customization points, `m_shouldStoreSuccesfulAssertions` and
24774+     * `m_shouldStoreFailedAssertions`, to disable the expansion and gain extra
24775+     * performance. **Accessing the assertion expansions if it wasn't stored is
24776+     * UB.**
24777+     */
24778+    class CumulativeReporterBase : public ReporterBase {
24779+    public:
24780+        template<typename T, typename ChildNodeT>
24781+        struct Node {
24782+            explicit Node( T const& _value ) : value( _value ) {}
24783+
24784+            using ChildNodes = std::vector<Detail::unique_ptr<ChildNodeT>>;
24785+            T value;
24786+            ChildNodes children;
24787+        };
24788+        struct SectionNode {
24789+            explicit SectionNode(SectionStats const& _stats) : stats(_stats) {}
24790+
24791+            bool operator == (SectionNode const& other) const {
24792+                return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo;
24793+            }
24794+
24795+            bool hasAnyAssertions() const;
24796+
24797+            SectionStats stats;
24798+            std::vector<Detail::unique_ptr<SectionNode>> childSections;
24799+            std::vector<Detail::AssertionOrBenchmarkResult> assertionsAndBenchmarks;
24800+            std::string stdOut;
24801+            std::string stdErr;
24802+        };
24803+
24804+
24805+        using TestCaseNode = Node<TestCaseStats, SectionNode>;
24806+        using TestRunNode = Node<TestRunStats, TestCaseNode>;
24807+
24808+        // GCC5 compat: we cannot use inherited constructor, because it
24809+        //              doesn't implement backport of P0136
24810+        CumulativeReporterBase(ReporterConfig&& _config):
24811+            ReporterBase(CATCH_MOVE(_config))
24812+        {}
24813+        ~CumulativeReporterBase() override;
24814+
24815+        void benchmarkPreparing( StringRef ) override {}
24816+        void benchmarkStarting( BenchmarkInfo const& ) override {}
24817+        void benchmarkEnded( BenchmarkStats<> const& benchmarkStats ) override;
24818+        void benchmarkFailed( StringRef ) override {}
24819+
24820+        void noMatchingTestCases( StringRef ) override {}
24821+        void reportInvalidTestSpec( StringRef ) override {}
24822+        void fatalErrorEncountered( StringRef /*error*/ ) override {}
24823+
24824+        void testRunStarting( TestRunInfo const& ) override {}
24825+
24826+        void testCaseStarting( TestCaseInfo const& ) override {}
24827+        void testCasePartialStarting( TestCaseInfo const&, uint64_t ) override {}
24828+        void sectionStarting( SectionInfo const& sectionInfo ) override;
24829+
24830+        void assertionStarting( AssertionInfo const& ) override {}
24831+
24832+        void assertionEnded( AssertionStats const& assertionStats ) override;
24833+        void sectionEnded( SectionStats const& sectionStats ) override;
24834+        void testCasePartialEnded( TestCaseStats const&, uint64_t ) override {}
24835+        void testCaseEnded( TestCaseStats const& testCaseStats ) override;
24836+        void testRunEnded( TestRunStats const& testRunStats ) override;
24837+        //! Customization point: called after last test finishes (testRunEnded has been handled)
24838+        virtual void testRunEndedCumulative() = 0;
24839+
24840+        void skipTest(TestCaseInfo const&) override {}
24841+
24842+    protected:
24843+        //! Should the cumulative base store the assertion expansion for successful assertions?
24844+        bool m_shouldStoreSuccesfulAssertions = true;
24845+        //! Should the cumulative base store the assertion expansion for failed assertions?
24846+        bool m_shouldStoreFailedAssertions = true;
24847+
24848+        // We need lazy construction here. We should probably refactor it
24849+        // later, after the events are redone.
24850+        //! The root node of the test run tree.
24851+        Detail::unique_ptr<TestRunNode> m_testRun;
24852+
24853+    private:
24854+        // Note: We rely on pointer identity being stable, which is why
24855+        //       we store pointers to the nodes rather than the values.
24856+        std::vector<Detail::unique_ptr<TestCaseNode>> m_testCases;
24857+        // Root section of the _current_ test case
24858+        Detail::unique_ptr<SectionNode> m_rootSection;
24859+        // Deepest section of the _current_ test case
24860+        SectionNode* m_deepestSection = nullptr;
24861+        // Stack of _active_ sections in the _current_ test case
24862+        std::vector<SectionNode*> m_sectionStack;
24863+    };
24864+
24865+} // end namespace Catch
24866+
24867+#endif // CATCH_REPORTER_CUMULATIVE_BASE_HPP_INCLUDED
24868+
24869+
24870+#ifndef CATCH_REPORTER_EVENT_LISTENER_HPP_INCLUDED
24871+#define CATCH_REPORTER_EVENT_LISTENER_HPP_INCLUDED
24872+
24873+
24874+namespace Catch {
24875+
24876+    /**
24877+     * Base class to simplify implementing listeners.
24878+     *
24879+     * Provides empty default implementation for all IEventListener member
24880+     * functions, so that a listener implementation can pick which
24881+     * member functions it actually cares about.
24882+     */
24883+    class EventListenerBase : public IEventListener {
24884+    public:
24885+        using IEventListener::IEventListener;
24886+
24887+        void reportInvalidTestSpec( StringRef unmatchedSpec ) override;
24888+        void fatalErrorEncountered( StringRef error ) override;
24889+
24890+        void benchmarkPreparing( StringRef name ) override;
24891+        void benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) override;
24892+        void benchmarkEnded( BenchmarkStats<> const& benchmarkStats ) override;
24893+        void benchmarkFailed( StringRef error ) override;
24894+
24895+        void assertionStarting( AssertionInfo const& assertionInfo ) override;
24896+        void assertionEnded( AssertionStats const& assertionStats ) override;
24897+
24898+        void listReporters(
24899+            std::vector<ReporterDescription> const& descriptions ) override;
24900+        void listListeners(
24901+            std::vector<ListenerDescription> const& descriptions ) override;
24902+        void listTests( std::vector<TestCaseHandle> const& tests ) override;
24903+        void listTags( std::vector<TagInfo> const& tagInfos ) override;
24904+
24905+        void noMatchingTestCases( StringRef unmatchedSpec ) override;
24906+        void testRunStarting( TestRunInfo const& testRunInfo ) override;
24907+        void testCaseStarting( TestCaseInfo const& testInfo ) override;
24908+        void testCasePartialStarting( TestCaseInfo const& testInfo,
24909+                                      uint64_t partNumber ) override;
24910+        void sectionStarting( SectionInfo const& sectionInfo ) override;
24911+        void sectionEnded( SectionStats const& sectionStats ) override;
24912+        void testCasePartialEnded( TestCaseStats const& testCaseStats,
24913+                                   uint64_t partNumber ) override;
24914+        void testCaseEnded( TestCaseStats const& testCaseStats ) override;
24915+        void testRunEnded( TestRunStats const& testRunStats ) override;
24916+        void skipTest( TestCaseInfo const& testInfo ) override;
24917+    };
24918+
24919+} // end namespace Catch
24920+
24921+#endif // CATCH_REPORTER_EVENT_LISTENER_HPP_INCLUDED
24922+
24923+
24924+#ifndef CATCH_REPORTER_HELPERS_HPP_INCLUDED
24925+#define CATCH_REPORTER_HELPERS_HPP_INCLUDED
24926+
24927+#include <iosfwd>
24928+#include <string>
24929+#include <vector>
24930+
24931+
24932+namespace Catch {
24933+
24934+    class IConfig;
24935+    class TestCaseHandle;
24936+    class ColourImpl;
24937+
24938+    // Returns double formatted as %.3f (format expected on output)
24939+    std::string getFormattedDuration( double duration );
24940+
24941+    //! Should the reporter show duration of test given current configuration?
24942+    bool shouldShowDuration( IConfig const& config, double duration );
24943+
24944+    std::string serializeFilters( std::vector<std::string> const& filters );
24945+
24946+    struct lineOfChars {
24947+        char c;
24948+        constexpr lineOfChars( char c_ ): c( c_ ) {}
24949+
24950+        friend std::ostream& operator<<( std::ostream& out, lineOfChars value );
24951+    };
24952+
24953+    /**
24954+     * Lists reporter descriptions to the provided stream in user-friendly
24955+     * format
24956+     *
24957+     * Used as the default listing implementation by the first party reporter
24958+     * bases. The output should be backwards compatible with the output of
24959+     * Catch2 v2 binaries.
24960+     */
24961+    void
24962+    defaultListReporters( std::ostream& out,
24963+                          std::vector<ReporterDescription> const& descriptions,
24964+                          Verbosity verbosity );
24965+
24966+    /**
24967+     * Lists listeners descriptions to the provided stream in user-friendly
24968+     * format
24969+     */
24970+    void defaultListListeners( std::ostream& out,
24971+                               std::vector<ListenerDescription> const& descriptions );
24972+
24973+    /**
24974+     * Lists tag information to the provided stream in user-friendly format
24975+     *
24976+     * Used as the default listing implementation by the first party reporter
24977+     * bases. The output should be backwards compatible with the output of
24978+     * Catch2 v2 binaries.
24979+     */
24980+    void defaultListTags( std::ostream& out, std::vector<TagInfo> const& tags, bool isFiltered );
24981+
24982+    /**
24983+     * Lists test case information to the provided stream in user-friendly
24984+     * format
24985+     *
24986+     * Used as the default listing implementation by the first party reporter
24987+     * bases. The output is backwards compatible with the output of Catch2
24988+     * v2 binaries, and also supports the format specific to the old
24989+     * `--list-test-names-only` option, for people who used it in integrations.
24990+     */
24991+    void defaultListTests( std::ostream& out,
24992+                           ColourImpl* streamColour,
24993+                           std::vector<TestCaseHandle> const& tests,
24994+                           bool isFiltered,
24995+                           Verbosity verbosity );
24996+
24997+    /**
24998+     * Prints test run totals to the provided stream in user-friendly format
24999+     *
25000+     * Used by the console and compact reporters.
25001+     */
25002+    void printTestRunTotals( std::ostream& stream,
25003+                      ColourImpl& streamColour,
25004+                      Totals const& totals );
25005+
25006+} // end namespace Catch
25007+
25008+#endif // CATCH_REPORTER_HELPERS_HPP_INCLUDED
25009+
25010+
25011+
25012+#ifndef CATCH_REPORTER_JSON_HPP_INCLUDED
25013+#define CATCH_REPORTER_JSON_HPP_INCLUDED
25014+
25015+
25016+#include <stack>
25017+
25018+namespace Catch {
25019+    class JsonReporter : public StreamingReporterBase {
25020+    public:
25021+        JsonReporter( ReporterConfig&& config );
25022+
25023+        ~JsonReporter() override;
25024+
25025+        static std::string getDescription();
25026+
25027+    public: // StreamingReporterBase
25028+        void testRunStarting( TestRunInfo const& runInfo ) override;
25029+        void testRunEnded( TestRunStats const& runStats ) override;
25030+
25031+        void testCaseStarting( TestCaseInfo const& tcInfo ) override;
25032+        void testCaseEnded( TestCaseStats const& tcStats ) override;
25033+
25034+        void testCasePartialStarting( TestCaseInfo const& tcInfo,
25035+                                      uint64_t index ) override;
25036+        void testCasePartialEnded( TestCaseStats const& tcStats,
25037+                                   uint64_t index ) override;
25038+
25039+        void sectionStarting( SectionInfo const& sectionInfo ) override;
25040+        void sectionEnded( SectionStats const& sectionStats ) override;
25041+
25042+        void assertionStarting( AssertionInfo const& assertionInfo ) override;
25043+        void assertionEnded( AssertionStats const& assertionStats ) override;
25044+
25045+        //void testRunEndedCumulative() override;
25046+
25047+        void benchmarkPreparing( StringRef name ) override;
25048+        void benchmarkStarting( BenchmarkInfo const& ) override;
25049+        void benchmarkEnded( BenchmarkStats<> const& ) override;
25050+        void benchmarkFailed( StringRef error ) override;
25051+
25052+        void listReporters(
25053+            std::vector<ReporterDescription> const& descriptions ) override;
25054+        void listListeners(
25055+            std::vector<ListenerDescription> const& descriptions ) override;
25056+        void listTests( std::vector<TestCaseHandle> const& tests ) override;
25057+        void listTags( std::vector<TagInfo> const& tags ) override;
25058+
25059+    private:
25060+        Timer m_testCaseTimer;
25061+        enum class Writer {
25062+            Object,
25063+            Array
25064+        };
25065+
25066+        JsonArrayWriter& startArray();
25067+        JsonArrayWriter& startArray( StringRef key );
25068+
25069+        JsonObjectWriter& startObject();
25070+        JsonObjectWriter& startObject( StringRef key );
25071+
25072+        void endObject();
25073+        void endArray();
25074+
25075+        bool isInside( Writer writer );
25076+
25077+        void startListing();
25078+        void endListing();
25079+
25080+        // Invariant:
25081+        // When m_writers is not empty and its top element is
25082+        // - Writer::Object, then m_objectWriters is not be empty
25083+        // - Writer::Array,  then m_arrayWriters shall not be empty
25084+        std::stack<JsonObjectWriter> m_objectWriters{};
25085+        std::stack<JsonArrayWriter> m_arrayWriters{};
25086+        std::stack<Writer> m_writers{};
25087+
25088+        bool m_startedListing = false;
25089+
25090+        // std::size_t m_sectionDepth = 0;
25091+        // std::size_t m_sectionStarted = 0;
25092+    };
25093+} // namespace Catch
25094+
25095+#endif // CATCH_REPORTER_JSON_HPP_INCLUDED
25096+
25097+
25098+#ifndef CATCH_REPORTER_JUNIT_HPP_INCLUDED
25099+#define CATCH_REPORTER_JUNIT_HPP_INCLUDED
25100+
25101+
25102+
25103+namespace Catch {
25104+
25105+    class JunitReporter final : public CumulativeReporterBase {
25106+    public:
25107+        JunitReporter(ReporterConfig&& _config);
25108+
25109+        static std::string getDescription();
25110+
25111+        void testRunStarting(TestRunInfo const& runInfo) override;
25112+
25113+        void testCaseStarting(TestCaseInfo const& testCaseInfo) override;
25114+        void assertionEnded(AssertionStats const& assertionStats) override;
25115+
25116+        void testCaseEnded(TestCaseStats const& testCaseStats) override;
25117+
25118+        void testRunEndedCumulative() override;
25119+
25120+    private:
25121+        void writeRun(TestRunNode const& testRunNode, double suiteTime);
25122+
25123+        void writeTestCase(TestCaseNode const& testCaseNode);
25124+
25125+        void writeSection( std::string const& className,
25126+                           std::string const& rootName,
25127+                           SectionNode const& sectionNode,
25128+                           bool testOkToFail );
25129+
25130+        void writeAssertions(SectionNode const& sectionNode);
25131+        void writeAssertion(AssertionStats const& stats);
25132+
25133+        XmlWriter xml;
25134+        Timer suiteTimer;
25135+        std::string stdOutForSuite;
25136+        std::string stdErrForSuite;
25137+        unsigned int unexpectedExceptions = 0;
25138+        bool m_okToFail = false;
25139+    };
25140+
25141+} // end namespace Catch
25142+
25143+#endif // CATCH_REPORTER_JUNIT_HPP_INCLUDED
25144+
25145+
25146+#ifndef CATCH_REPORTER_MULTI_HPP_INCLUDED
25147+#define CATCH_REPORTER_MULTI_HPP_INCLUDED
25148+
25149+
25150+namespace Catch {
25151+
25152+    class MultiReporter final : public IEventListener {
25153+        /*
25154+         * Stores all added reporters and listeners
25155+         *
25156+         * All Listeners are stored before all reporters, and individual
25157+         * listeners/reporters are stored in order of insertion.
25158+         */
25159+        std::vector<IEventListenerPtr> m_reporterLikes;
25160+        bool m_haveNoncapturingReporters = false;
25161+
25162+        // Keep track of how many listeners we have already inserted,
25163+        // so that we can insert them into the main vector at the right place
25164+        size_t m_insertedListeners = 0;
25165+
25166+        void updatePreferences(IEventListener const& reporterish);
25167+
25168+    public:
25169+        using IEventListener::IEventListener;
25170+
25171+        void addListener( IEventListenerPtr&& listener );
25172+        void addReporter( IEventListenerPtr&& reporter );
25173+
25174+    public: // IEventListener
25175+
25176+        void noMatchingTestCases( StringRef unmatchedSpec ) override;
25177+        void fatalErrorEncountered( StringRef error ) override;
25178+        void reportInvalidTestSpec( StringRef arg ) override;
25179+
25180+        void benchmarkPreparing( StringRef name ) override;
25181+        void benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) override;
25182+        void benchmarkEnded( BenchmarkStats<> const& benchmarkStats ) override;
25183+        void benchmarkFailed( StringRef error ) override;
25184+
25185+        void testRunStarting( TestRunInfo const& testRunInfo ) override;
25186+        void testCaseStarting( TestCaseInfo const& testInfo ) override;
25187+        void testCasePartialStarting(TestCaseInfo const& testInfo, uint64_t partNumber) override;
25188+        void sectionStarting( SectionInfo const& sectionInfo ) override;
25189+        void assertionStarting( AssertionInfo const& assertionInfo ) override;
25190+
25191+        void assertionEnded( AssertionStats const& assertionStats ) override;
25192+        void sectionEnded( SectionStats const& sectionStats ) override;
25193+        void testCasePartialEnded(TestCaseStats const& testStats, uint64_t partNumber) override;
25194+        void testCaseEnded( TestCaseStats const& testCaseStats ) override;
25195+        void testRunEnded( TestRunStats const& testRunStats ) override;
25196+
25197+        void skipTest( TestCaseInfo const& testInfo ) override;
25198+
25199+        void listReporters(std::vector<ReporterDescription> const& descriptions) override;
25200+        void listListeners(std::vector<ListenerDescription> const& descriptions) override;
25201+        void listTests(std::vector<TestCaseHandle> const& tests) override;
25202+        void listTags(std::vector<TagInfo> const& tags) override;
25203+
25204+
25205+    };
25206+
25207+} // end namespace Catch
25208+
25209+#endif // CATCH_REPORTER_MULTI_HPP_INCLUDED
25210+
25211+
25212+#ifndef CATCH_REPORTER_REGISTRARS_HPP_INCLUDED
25213+#define CATCH_REPORTER_REGISTRARS_HPP_INCLUDED
25214+
25215+
25216+#include <type_traits>
25217+
25218+namespace Catch {
25219+
25220+    namespace Detail {
25221+
25222+        template <typename T, typename = void>
25223+        struct has_description : std::false_type {};
25224+
25225+        template <typename T>
25226+        struct has_description<
25227+            T,
25228+            void_t<decltype( T::getDescription() )>>
25229+            : std::true_type {};
25230+
25231+        //! Indirection for reporter registration, so that the error handling is
25232+        //! independent on the reporter's concrete type
25233+        void registerReporterImpl( std::string const& name,
25234+                                   IReporterFactoryPtr reporterPtr );
25235+        //! Actually registers the factory, independent on listener's concrete type
25236+        void registerListenerImpl( Detail::unique_ptr<EventListenerFactory> listenerFactory );
25237+    } // namespace Detail
25238+
25239+    class IEventListener;
25240+    using IEventListenerPtr = Detail::unique_ptr<IEventListener>;
25241+
25242+    template <typename T>
25243+    class ReporterFactory : public IReporterFactory {
25244+
25245+        IEventListenerPtr create( ReporterConfig&& config ) const override {
25246+            return Detail::make_unique<T>( CATCH_MOVE(config) );
25247+        }
25248+
25249+        std::string getDescription() const override {
25250+            return T::getDescription();
25251+        }
25252+    };
25253+
25254+
25255+    template<typename T>
25256+    class ReporterRegistrar {
25257+    public:
25258+        explicit ReporterRegistrar( std::string const& name ) {
25259+            registerReporterImpl( name,
25260+                                  Detail::make_unique<ReporterFactory<T>>() );
25261+        }
25262+    };
25263+
25264+    template<typename T>
25265+    class ListenerRegistrar {
25266+
25267+        class TypedListenerFactory : public EventListenerFactory {
25268+            StringRef m_listenerName;
25269+
25270+            std::string getDescriptionImpl( std::true_type ) const {
25271+                return T::getDescription();
25272+            }
25273+
25274+            std::string getDescriptionImpl( std::false_type ) const {
25275+                return "(No description provided)";
25276+            }
25277+
25278+        public:
25279+            TypedListenerFactory( StringRef listenerName ):
25280+                m_listenerName( listenerName ) {}
25281+
25282+            IEventListenerPtr create( IConfig const* config ) const override {
25283+                return Detail::make_unique<T>( config );
25284+            }
25285+
25286+            StringRef getName() const override {
25287+                return m_listenerName;
25288+            }
25289+
25290+            std::string getDescription() const override {
25291+                return getDescriptionImpl( Detail::has_description<T>{} );
25292+            }
25293+        };
25294+
25295+    public:
25296+        ListenerRegistrar(StringRef listenerName) {
25297+            registerListenerImpl( Detail::make_unique<TypedListenerFactory>(listenerName) );
25298+        }
25299+    };
25300+}
25301+
25302+#if !defined(CATCH_CONFIG_DISABLE)
25303+
25304+#    define CATCH_REGISTER_REPORTER( name, reporterType )                      \
25305+        CATCH_INTERNAL_START_WARNINGS_SUPPRESSION                              \
25306+        CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS                               \
25307+        namespace {                                                            \
25308+            Catch::ReporterRegistrar<reporterType> INTERNAL_CATCH_UNIQUE_NAME( \
25309+                catch_internal_RegistrarFor )( name );                         \
25310+        }                                                                      \
25311+        CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
25312+
25313+#    define CATCH_REGISTER_LISTENER( listenerType )                            \
25314+        CATCH_INTERNAL_START_WARNINGS_SUPPRESSION                              \
25315+        CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS                               \
25316+        namespace {                                                            \
25317+            Catch::ListenerRegistrar<listenerType> INTERNAL_CATCH_UNIQUE_NAME( \
25318+                catch_internal_RegistrarFor )( #listenerType##_catch_sr );     \
25319+        }                                                                      \
25320+        CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
25321+
25322+#else // CATCH_CONFIG_DISABLE
25323+
25324+#define CATCH_REGISTER_REPORTER(name, reporterType)
25325+#define CATCH_REGISTER_LISTENER(listenerType)
25326+
25327+#endif // CATCH_CONFIG_DISABLE
25328+
25329+#endif // CATCH_REPORTER_REGISTRARS_HPP_INCLUDED
25330+
25331+
25332+#ifndef CATCH_REPORTER_SONARQUBE_HPP_INCLUDED
25333+#define CATCH_REPORTER_SONARQUBE_HPP_INCLUDED
25334+
25335+
25336+
25337+namespace Catch {
25338+
25339+    class SonarQubeReporter final : public CumulativeReporterBase {
25340+    public:
25341+        SonarQubeReporter(ReporterConfig&& config)
25342+        : CumulativeReporterBase(CATCH_MOVE(config))
25343+        , xml(m_stream) {
25344+            m_preferences.shouldRedirectStdOut = true;
25345+            m_preferences.shouldReportAllAssertions = true;
25346+            m_shouldStoreSuccesfulAssertions = false;
25347+        }
25348+
25349+        static std::string getDescription() {
25350+            using namespace std::string_literals;
25351+            return "Reports test results in the Generic Test Data SonarQube XML format"s;
25352+        }
25353+
25354+        void testRunStarting( TestRunInfo const& testRunInfo ) override;
25355+
25356+        void testRunEndedCumulative() override {
25357+            writeRun( *m_testRun );
25358+            xml.endElement();
25359+        }
25360+
25361+        void writeRun( TestRunNode const& runNode );
25362+
25363+        void writeTestFile(StringRef filename, std::vector<TestCaseNode const*> const& testCaseNodes);
25364+
25365+        void writeTestCase(TestCaseNode const& testCaseNode);
25366+
25367+        void writeSection(std::string const& rootName, SectionNode const& sectionNode, bool okToFail);
25368+
25369+        void writeAssertions(SectionNode const& sectionNode, bool okToFail);
25370+
25371+        void writeAssertion(AssertionStats const& stats, bool okToFail);
25372+
25373+    private:
25374+        XmlWriter xml;
25375+    };
25376+
25377+
25378+} // end namespace Catch
25379+
25380+#endif // CATCH_REPORTER_SONARQUBE_HPP_INCLUDED
25381+
25382+
25383+#ifndef CATCH_REPORTER_TAP_HPP_INCLUDED
25384+#define CATCH_REPORTER_TAP_HPP_INCLUDED
25385+
25386+
25387+namespace Catch {
25388+
25389+    class TAPReporter final : public StreamingReporterBase {
25390+    public:
25391+        TAPReporter( ReporterConfig&& config ):
25392+            StreamingReporterBase( CATCH_MOVE(config) ) {
25393+            m_preferences.shouldReportAllAssertions = true;
25394+        }
25395+
25396+        static std::string getDescription() {
25397+            using namespace std::string_literals;
25398+            return "Reports test results in TAP format, suitable for test harnesses"s;
25399+        }
25400+
25401+        void testRunStarting( TestRunInfo const& testInfo ) override;
25402+
25403+        void noMatchingTestCases( StringRef unmatchedSpec ) override;
25404+
25405+        void assertionEnded(AssertionStats const& _assertionStats) override;
25406+
25407+        void testRunEnded(TestRunStats const& _testRunStats) override;
25408+
25409+    private:
25410+        std::size_t counter = 0;
25411+    };
25412+
25413+} // end namespace Catch
25414+
25415+#endif // CATCH_REPORTER_TAP_HPP_INCLUDED
25416+
25417+
25418+#ifndef CATCH_REPORTER_TEAMCITY_HPP_INCLUDED
25419+#define CATCH_REPORTER_TEAMCITY_HPP_INCLUDED
25420+
25421+
25422+#include <cstring>
25423+
25424+#ifdef __clang__
25425+#   pragma clang diagnostic push
25426+#   pragma clang diagnostic ignored "-Wpadded"
25427+#endif
25428+
25429+namespace Catch {
25430+
25431+    class TeamCityReporter final : public StreamingReporterBase {
25432+    public:
25433+        TeamCityReporter( ReporterConfig&& _config )
25434+        :   StreamingReporterBase( CATCH_MOVE(_config) )
25435+        {
25436+            m_preferences.shouldRedirectStdOut = true;
25437+        }
25438+
25439+        ~TeamCityReporter() override;
25440+
25441+        static std::string getDescription() {
25442+            using namespace std::string_literals;
25443+            return "Reports test results as TeamCity service messages"s;
25444+        }
25445+
25446+        void testRunStarting( TestRunInfo const& runInfo ) override;
25447+        void testRunEnded( TestRunStats const& runStats ) override;
25448+
25449+
25450+        void assertionEnded(AssertionStats const& assertionStats) override;
25451+
25452+        void sectionStarting(SectionInfo const& sectionInfo) override {
25453+            m_headerPrintedForThisSection = false;
25454+            StreamingReporterBase::sectionStarting( sectionInfo );
25455+        }
25456+
25457+        void testCaseStarting(TestCaseInfo const& testInfo) override;
25458+
25459+        void testCaseEnded(TestCaseStats const& testCaseStats) override;
25460+
25461+    private:
25462+        void printSectionHeader(std::ostream& os);
25463+
25464+        bool m_headerPrintedForThisSection = false;
25465+        Timer m_testTimer;
25466+    };
25467+
25468+} // end namespace Catch
25469+
25470+#ifdef __clang__
25471+#   pragma clang diagnostic pop
25472+#endif
25473+
25474+#endif // CATCH_REPORTER_TEAMCITY_HPP_INCLUDED
25475+
25476+
25477+#ifndef CATCH_REPORTER_XML_HPP_INCLUDED
25478+#define CATCH_REPORTER_XML_HPP_INCLUDED
25479+
25480+
25481+
25482+
25483+namespace Catch {
25484+    class XmlReporter : public StreamingReporterBase {
25485+    public:
25486+        XmlReporter(ReporterConfig&& _config);
25487+
25488+        ~XmlReporter() override;
25489+
25490+        static std::string getDescription();
25491+
25492+        virtual std::string getStylesheetRef() const;
25493+
25494+        void writeSourceInfo(SourceLineInfo const& sourceInfo);
25495+
25496+    public: // StreamingReporterBase
25497+
25498+        void testRunStarting(TestRunInfo const& testInfo) override;
25499+
25500+        void testCaseStarting(TestCaseInfo const& testInfo) override;
25501+
25502+        void sectionStarting(SectionInfo const& sectionInfo) override;
25503+
25504+        void assertionStarting(AssertionInfo const&) override;
25505+
25506+        void assertionEnded(AssertionStats const& assertionStats) override;
25507+
25508+        void sectionEnded(SectionStats const& sectionStats) override;
25509+
25510+        void testCaseEnded(TestCaseStats const& testCaseStats) override;
25511+
25512+        void testRunEnded(TestRunStats const& testRunStats) override;
25513+
25514+        void benchmarkPreparing( StringRef name ) override;
25515+        void benchmarkStarting(BenchmarkInfo const&) override;
25516+        void benchmarkEnded(BenchmarkStats<> const&) override;
25517+        void benchmarkFailed( StringRef error ) override;
25518+
25519+        void listReporters(std::vector<ReporterDescription> const& descriptions) override;
25520+        void listListeners(std::vector<ListenerDescription> const& descriptions) override;
25521+        void listTests(std::vector<TestCaseHandle> const& tests) override;
25522+        void listTags(std::vector<TagInfo> const& tags) override;
25523+
25524+    private:
25525+        Timer m_testCaseTimer;
25526+        XmlWriter m_xml;
25527+        int m_sectionDepth = 0;
25528+    };
25529+
25530+} // end namespace Catch
25531+
25532+#endif // CATCH_REPORTER_XML_HPP_INCLUDED
25533+
25534+#endif // CATCH_REPORTERS_ALL_HPP_INCLUDED
25535+
25536+#endif // CATCH_ALL_HPP_INCLUDED
25537+#endif // CATCH_AMALGAMATED_HPP_INCLUDED
25538diff --git a/tests/main.cc b/tests/main.cc
25539new file mode 100644
25540index 0000000..e115601
25541--- /dev/null
25542+++ b/tests/main.cc
25543@@ -0,0 +1,189 @@
25544+#include <catch_amalgamated.hpp>
25545+#include "../include/grim.h"
25546+#include "../include/parser.h" 
25547+#include <string>
25548+#include <fstream>
25549+
25550+void checkNode(Node* node, std::string tagName, unsigned long children, std::string id, std::vector<std::string> classes, std::unordered_map<std::string, std::string> attributes, std::string note = "") {
25551+	INFO("=========================");
25552+	INFO("TAG: "+tagName);
25553+	INFO("NOTE: "+note+"\n");
25554+	INFO("HTML:\n"+node->print());
25555+
25556+	REQUIRE(node->getTagName() == tagName);
25557+	REQUIRE(node->children.size() == children);
25558+	REQUIRE(node->getId() == id);
25559+
25560+	size_t i = 0;
25561+	for (auto c : node->classList.values()) {
25562+		REQUIRE(c == classes[i]);
25563+		i++;
25564+	}
25565+
25566+	for (auto pair : attributes) {
25567+		REQUIRE(node->getAttribute(pair.first) == pair.second);
25568+	}
25569+}
25570+
25571+
25572+TEST_CASE( "parseStream can parse various types of HTML strings", "[html]" ) {
25573+	SECTION("Parses a simple HTML document") {
25574+		std::string html = "<!DOCTYPE html>"
25575+			"<html>"
25576+				"<head>"
25577+					"<title>This is a simple test</title>"
25578+					"<link rel=\"stylesheet\" href=\'/style.css\'/>"
25579+				"</head>"
25580+				"<body>"
25581+					"<p id=\"paragraph\" class=\"class1 class2\">This is some text for a simple test</p>"
25582+				"</body>"
25583+			"</html>";
25584+
25585+
25586+		std::stringstream ss(html);
25587+		std::unique_ptr<Node> document = parseStream(ss);
25588+
25589+		// Ensure the only child of root is html
25590+		Node* current = document->children[0].get();
25591+
25592+		checkNode(current, "html", 2, "", {}, {{}});
25593+
25594+		current = current->children[0].get();
25595+		checkNode(current, "head", 2, "", {}, {{}});
25596+
25597+		current = current->children[0].get();
25598+		checkNode(current, "title", 1, "", {}, {{}});
25599+
25600+		current = current->children[0].get();
25601+		checkNode(current, "text", 0, "", {}, {{"innerText","This is a simple test"}}, "First innerText check");
25602+
25603+		current = current->parent->parent->children[1].get();
25604+		checkNode(current, "link", 0, "", {}, {{"rel","stylesheet"}, {"href","/style.css"}}
25605+				, "Check attribute parsing with different quote types. Also check self closing tags");
25606+
25607+		current = current->parent->parent->children[1].get();
25608+		checkNode(current, "body", 1, "", {}, {{}});
25609+
25610+		current = current->children[0].get();
25611+		checkNode(current, "p", 1, "paragraph", {"class1", "class2"}, {{}}, "Checks for id and class parsing");
25612+
25613+		current = current->children[0].get();
25614+		checkNode(current, "text", 0, "", {}, {{"innerText","This is some text for a simple test"}}, "Second innerText check");
25615+	} 
25616+
25617+	SECTION("Inline comment") {
25618+		std::string html = "<div>"
25619+					"<!-- this is a comment -->"
25620+				   "</div>";
25621+
25622+		std::stringstream ss(html);
25623+		std::unique_ptr<Node> document = parseStream(ss);
25624+
25625+		// Ensure the only child of root is html
25626+		Node* current = document->children[0].get();
25627+
25628+		checkNode(current, "div", 0, "", {}, {{}});
25629+	} 
25630+
25631+	SECTION("Multi line comment") {
25632+		std::string html = "<div>"
25633+					"<!-- this is a comment"
25634+					"That has two lines!"
25635+					" -->"
25636+				   "</div>";
25637+
25638+		std::stringstream ss(html);
25639+		std::unique_ptr<Node> document = parseStream(ss);
25640+
25641+		// Ensure the only child of root is html
25642+		Node* current = document->children[0].get();
25643+
25644+		checkNode(current, "div", 0, "", {}, {{}});
25645+	}
25646+
25647+	SECTION("Multi line comment with html") {
25648+		std::string html = "<div>"
25649+					"<!-- this is a comment"
25650+					"<html>with HTML inside</html>"
25651+					" -->"
25652+				   "</div>";
25653+
25654+		std::stringstream ss(html);
25655+		std::unique_ptr<Node> document = parseStream(ss);
25656+
25657+		// Ensure the only child of root is html
25658+		Node* current = document->children[0].get();
25659+
25660+		checkNode(current, "div", 0, "", {}, {{}});
25661+	}
25662+
25663+	SECTION("Style tag parsing (with HTML in the content prop)") {
25664+		std::string html = "<style>"
25665+					"body > h1 {"
25666+						"margin-left: calc(100% / 50px);"
25667+						"background: url(https://example.com/image.png);"
25668+						"content: \"<h1>hi</h1>\";"
25669+					"}"
25670+				   "</style>"
25671+				   "<h1>test</h1>";
25672+
25673+		std::stringstream ss(html);
25674+		std::unique_ptr<Node> document = parseStream(ss);
25675+
25676+		// Ensure the only child of root is html
25677+		Node* current = document->children[0].get();
25678+
25679+		checkNode(current, "style", 1, "", {}, {{}});
25680+
25681+		current = current->children[0].get();
25682+		checkNode(current, "text", 0, "", {}, {{"innerText", "body > h1 {"
25683+						"margin-left: calc(100% / 50px);"
25684+						"background: url(https://example.com/image.png);"
25685+						"content: \"<h1>hi</h1>\";"
25686+					"}"}});
25687+		current = document->children[1].get();
25688+		checkNode(current, "h1", 1, "", {}, {{}});
25689+
25690+
25691+		current = current->children[0].get();
25692+		checkNode(current, "text", 0, "", {}, {{"innerText", "test"}});
25693+	}
25694+
25695+	SECTION("Script tag prematurly closing a pre tag") {
25696+		std::string html = "<pre>"
25697+					"<script>console.log(\"</pre>\");</script>"
25698+				"</pre>";
25699+
25700+		std::stringstream ss(html);
25701+		std::unique_ptr<Node> document = parseStream(ss);
25702+
25703+		// Ensure the only child of root is html
25704+		Node* current = document->children[0].get();
25705+
25706+		checkNode(current, "pre", 1, "", {}, {{}});
25707+
25708+		current = current->children[0].get();
25709+		checkNode(current, "script", 1, "", {}, {{}});
25710+
25711+		current = current->children[0].get();
25712+		checkNode(current, "text", 0, "", {}, {{"innerText", "console.log(\"</pre>\");"}});
25713+	}
25714+
25715+	SECTION("Textarea with script tag inside") {
25716+		std::string html = "<textarea>"
25717+					"<script>console.log(\"</pre>\");</script>"
25718+				"</textarea>";
25719+
25720+		std::stringstream ss(html);
25721+		std::unique_ptr<Node> document = parseStream(ss);
25722+
25723+		// Ensure the only child of root is html
25724+		Node* current = document->children[0].get();
25725+
25726+		checkNode(current, "textarea", 1, "", {}, {{}});
25727+
25728+		current = current->children[0].get();
25729+		checkNode(current, "text", 0, "", {}, {{"innerText","<script>console.log(\"</pre>\");</script>"}});
25730+	}
25731+}
25732+