updated catch with v2.13.7
This commit is contained in:
parent
197905e841
commit
889fffda69
450
catch/catch.hpp
450
catch/catch.hpp
@ -1,9 +1,9 @@
|
|||||||
/*
|
/*
|
||||||
* Catch v2.13.3
|
* Catch v2.13.7
|
||||||
* Generated: 2020-10-31 18:20:31.045274
|
* Generated: 2021-07-28 20:29:27.753164
|
||||||
* ----------------------------------------------------------
|
* ----------------------------------------------------------
|
||||||
* This file has been merged from multiple headers. Please don't edit it directly
|
* This file has been merged from multiple headers. Please don't edit it directly
|
||||||
* Copyright (c) 2020 Two Blue Cubes Ltd. All rights reserved.
|
* Copyright (c) 2021 Two Blue Cubes Ltd. All rights reserved.
|
||||||
*
|
*
|
||||||
* Distributed under the Boost Software License, Version 1.0. (See accompanying
|
* Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
#define CATCH_VERSION_MAJOR 2
|
#define CATCH_VERSION_MAJOR 2
|
||||||
#define CATCH_VERSION_MINOR 13
|
#define CATCH_VERSION_MINOR 13
|
||||||
#define CATCH_VERSION_PATCH 3
|
#define CATCH_VERSION_PATCH 7
|
||||||
|
|
||||||
#ifdef __clang__
|
#ifdef __clang__
|
||||||
# pragma clang system_header
|
# pragma clang system_header
|
||||||
@ -66,11 +66,14 @@
|
|||||||
#if !defined(CATCH_CONFIG_IMPL_ONLY)
|
#if !defined(CATCH_CONFIG_IMPL_ONLY)
|
||||||
// start catch_platform.h
|
// start catch_platform.h
|
||||||
|
|
||||||
|
// See e.g.:
|
||||||
|
// https://opensource.apple.com/source/CarbonHeaders/CarbonHeaders-18.1/TargetConditionals.h.auto.html
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
# include <TargetConditionals.h>
|
# include <TargetConditionals.h>
|
||||||
# if TARGET_OS_OSX == 1
|
# if (defined(TARGET_OS_OSX) && TARGET_OS_OSX == 1) || \
|
||||||
|
(defined(TARGET_OS_MAC) && TARGET_OS_MAC == 1)
|
||||||
# define CATCH_PLATFORM_MAC
|
# define CATCH_PLATFORM_MAC
|
||||||
# elif TARGET_OS_IPHONE == 1
|
# elif (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE == 1)
|
||||||
# define CATCH_PLATFORM_IPHONE
|
# define CATCH_PLATFORM_IPHONE
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
@ -132,9 +135,9 @@ namespace Catch {
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// We have to avoid both ICC and Clang, because they try to mask themselves
|
// Only GCC compiler should be used in this block, so other compilers trying to
|
||||||
// as gcc, and we want only GCC in this block
|
// mask themselves as GCC should be ignored.
|
||||||
#if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC) && !defined(__CUDACC__)
|
#if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC) && !defined(__CUDACC__) && !defined(__LCC__)
|
||||||
# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic push" )
|
# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic push" )
|
||||||
# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic pop" )
|
# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic pop" )
|
||||||
|
|
||||||
@ -323,7 +326,7 @@ namespace Catch {
|
|||||||
// Check if byte is available and usable
|
// Check if byte is available and usable
|
||||||
# if __has_include(<cstddef>) && defined(CATCH_CPP17_OR_GREATER)
|
# if __has_include(<cstddef>) && defined(CATCH_CPP17_OR_GREATER)
|
||||||
# include <cstddef>
|
# include <cstddef>
|
||||||
# if __cpp_lib_byte > 0
|
# if defined(__cpp_lib_byte) && (__cpp_lib_byte > 0)
|
||||||
# define CATCH_INTERNAL_CONFIG_CPP17_BYTE
|
# define CATCH_INTERNAL_CONFIG_CPP17_BYTE
|
||||||
# endif
|
# endif
|
||||||
# endif // __has_include(<cstddef>) && defined(CATCH_CPP17_OR_GREATER)
|
# endif // __has_include(<cstddef>) && defined(CATCH_CPP17_OR_GREATER)
|
||||||
@ -5455,6 +5458,8 @@ namespace Catch {
|
|||||||
} // namespace Catch
|
} // namespace Catch
|
||||||
|
|
||||||
// end catch_outlier_classification.hpp
|
// end catch_outlier_classification.hpp
|
||||||
|
|
||||||
|
#include <iterator>
|
||||||
#endif // CATCH_CONFIG_ENABLE_BENCHMARKING
|
#endif // CATCH_CONFIG_ENABLE_BENCHMARKING
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
@ -6339,9 +6344,10 @@ namespace Catch {
|
|||||||
|
|
||||||
void writeTestCase(TestCaseNode const& testCaseNode);
|
void writeTestCase(TestCaseNode const& testCaseNode);
|
||||||
|
|
||||||
void writeSection(std::string const& className,
|
void writeSection( std::string const& className,
|
||||||
std::string const& rootName,
|
std::string const& rootName,
|
||||||
SectionNode const& sectionNode);
|
SectionNode const& sectionNode,
|
||||||
|
bool testOkToFail );
|
||||||
|
|
||||||
void writeAssertions(SectionNode const& sectionNode);
|
void writeAssertions(SectionNode const& sectionNode);
|
||||||
void writeAssertion(AssertionStats const& stats);
|
void writeAssertion(AssertionStats const& stats);
|
||||||
@ -6876,7 +6882,7 @@ namespace Catch {
|
|||||||
}
|
}
|
||||||
iters *= 2;
|
iters *= 2;
|
||||||
}
|
}
|
||||||
throw optimized_away_error{};
|
Catch::throw_exception(optimized_away_error{});
|
||||||
}
|
}
|
||||||
} // namespace Detail
|
} // namespace Detail
|
||||||
} // namespace Benchmark
|
} // namespace Benchmark
|
||||||
@ -6884,6 +6890,7 @@ namespace Catch {
|
|||||||
|
|
||||||
// end catch_run_for_at_least.hpp
|
// end catch_run_for_at_least.hpp
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <iterator>
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
namespace Benchmark {
|
namespace Benchmark {
|
||||||
@ -7054,8 +7061,8 @@ namespace Catch {
|
|||||||
double b2 = bias - z1;
|
double b2 = bias - z1;
|
||||||
double a1 = a(b1);
|
double a1 = a(b1);
|
||||||
double a2 = a(b2);
|
double a2 = a(b2);
|
||||||
auto lo = std::max(cumn(a1), 0);
|
auto lo = (std::max)(cumn(a1), 0);
|
||||||
auto hi = std::min(cumn(a2), n - 1);
|
auto hi = (std::min)(cumn(a2), n - 1);
|
||||||
|
|
||||||
return { point, resample[lo], resample[hi], confidence_level };
|
return { point, resample[lo], resample[hi], confidence_level };
|
||||||
}
|
}
|
||||||
@ -7124,7 +7131,9 @@ namespace Catch {
|
|||||||
}
|
}
|
||||||
template <typename Clock>
|
template <typename Clock>
|
||||||
EnvironmentEstimate<FloatDuration<Clock>> estimate_clock_cost(FloatDuration<Clock> resolution) {
|
EnvironmentEstimate<FloatDuration<Clock>> estimate_clock_cost(FloatDuration<Clock> resolution) {
|
||||||
auto time_limit = std::min(resolution * clock_cost_estimation_tick_limit, FloatDuration<Clock>(clock_cost_estimation_time_limit));
|
auto time_limit = (std::min)(
|
||||||
|
resolution * clock_cost_estimation_tick_limit,
|
||||||
|
FloatDuration<Clock>(clock_cost_estimation_time_limit));
|
||||||
auto time_clock = [](int k) {
|
auto time_clock = [](int k) {
|
||||||
return Detail::measure<Clock>([k] {
|
return Detail::measure<Clock>([k] {
|
||||||
for (int i = 0; i < k; ++i) {
|
for (int i = 0; i < k; ++i) {
|
||||||
@ -7771,7 +7780,7 @@ namespace Catch {
|
|||||||
double sb = stddev.point;
|
double sb = stddev.point;
|
||||||
double mn = mean.point / n;
|
double mn = mean.point / n;
|
||||||
double mg_min = mn / 2.;
|
double mg_min = mn / 2.;
|
||||||
double sg = std::min(mg_min / 4., sb / std::sqrt(n));
|
double sg = (std::min)(mg_min / 4., sb / std::sqrt(n));
|
||||||
double sg2 = sg * sg;
|
double sg2 = sg * sg;
|
||||||
double sb2 = sb * sb;
|
double sb2 = sb * sb;
|
||||||
|
|
||||||
@ -7790,7 +7799,7 @@ namespace Catch {
|
|||||||
return (nc / n) * (sb2 - nc * sg2);
|
return (nc / n) * (sb2 - nc * sg2);
|
||||||
};
|
};
|
||||||
|
|
||||||
return std::min(var_out(1), var_out(std::min(c_max(0.), c_max(mg_min)))) / sb2;
|
return (std::min)(var_out(1), var_out((std::min)(c_max(0.), c_max(mg_min)))) / sb2;
|
||||||
}
|
}
|
||||||
|
|
||||||
bootstrap_analysis analyse_samples(double confidence_level, int n_resamples, std::vector<double>::iterator first, std::vector<double>::iterator last) {
|
bootstrap_analysis analyse_samples(double confidence_level, int n_resamples, std::vector<double>::iterator first, std::vector<double>::iterator last) {
|
||||||
@ -7980,86 +7989,58 @@ namespace Catch {
|
|||||||
|
|
||||||
// start catch_fatal_condition.h
|
// start catch_fatal_condition.h
|
||||||
|
|
||||||
// start catch_windows_h_proxy.h
|
#include <cassert>
|
||||||
|
|
||||||
|
|
||||||
#if defined(CATCH_PLATFORM_WINDOWS)
|
|
||||||
|
|
||||||
#if !defined(NOMINMAX) && !defined(CATCH_CONFIG_NO_NOMINMAX)
|
|
||||||
# define CATCH_DEFINED_NOMINMAX
|
|
||||||
# define NOMINMAX
|
|
||||||
#endif
|
|
||||||
#if !defined(WIN32_LEAN_AND_MEAN) && !defined(CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN)
|
|
||||||
# define CATCH_DEFINED_WIN32_LEAN_AND_MEAN
|
|
||||||
# define WIN32_LEAN_AND_MEAN
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __AFXDLL
|
|
||||||
#include <AfxWin.h>
|
|
||||||
#else
|
|
||||||
#include <windows.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef CATCH_DEFINED_NOMINMAX
|
|
||||||
# undef NOMINMAX
|
|
||||||
#endif
|
|
||||||
#ifdef CATCH_DEFINED_WIN32_LEAN_AND_MEAN
|
|
||||||
# undef WIN32_LEAN_AND_MEAN
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // defined(CATCH_PLATFORM_WINDOWS)
|
|
||||||
|
|
||||||
// end catch_windows_h_proxy.h
|
|
||||||
#if defined( CATCH_CONFIG_WINDOWS_SEH )
|
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
struct FatalConditionHandler {
|
// Wrapper for platform-specific fatal error (signals/SEH) handlers
|
||||||
|
//
|
||||||
static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo);
|
// Tries to be cooperative with other handlers, and not step over
|
||||||
FatalConditionHandler();
|
// other handlers. This means that unknown structured exceptions
|
||||||
static void reset();
|
// are passed on, previous signal handlers are called, and so on.
|
||||||
~FatalConditionHandler();
|
//
|
||||||
|
// Can only be instantiated once, and assumes that once a signal
|
||||||
private:
|
// is caught, the binary will end up terminating. Thus, there
|
||||||
static bool isSet;
|
class FatalConditionHandler {
|
||||||
static ULONG guaranteeSize;
|
bool m_started = false;
|
||||||
static PVOID exceptionHandlerHandle;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Catch
|
|
||||||
|
|
||||||
#elif defined ( CATCH_CONFIG_POSIX_SIGNALS )
|
|
||||||
|
|
||||||
#include <signal.h>
|
|
||||||
|
|
||||||
namespace Catch {
|
|
||||||
|
|
||||||
struct FatalConditionHandler {
|
|
||||||
|
|
||||||
static bool isSet;
|
|
||||||
static struct sigaction oldSigActions[];
|
|
||||||
static stack_t oldSigStack;
|
|
||||||
static char altStackMem[];
|
|
||||||
|
|
||||||
static void handleSignal( int sig );
|
|
||||||
|
|
||||||
|
// Install/disengage implementation for specific platform.
|
||||||
|
// Should be if-defed to work on current platform, can assume
|
||||||
|
// engage-disengage 1:1 pairing.
|
||||||
|
void engage_platform();
|
||||||
|
void disengage_platform();
|
||||||
|
public:
|
||||||
|
// Should also have platform-specific implementations as needed
|
||||||
FatalConditionHandler();
|
FatalConditionHandler();
|
||||||
~FatalConditionHandler();
|
~FatalConditionHandler();
|
||||||
static void reset();
|
|
||||||
|
void engage() {
|
||||||
|
assert(!m_started && "Handler cannot be installed twice.");
|
||||||
|
m_started = true;
|
||||||
|
engage_platform();
|
||||||
|
}
|
||||||
|
|
||||||
|
void disengage() {
|
||||||
|
assert(m_started && "Handler cannot be uninstalled without being installed first");
|
||||||
|
m_started = false;
|
||||||
|
disengage_platform();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Catch
|
//! Simple RAII guard for (dis)engaging the FatalConditionHandler
|
||||||
|
class FatalConditionHandlerGuard {
|
||||||
#else
|
FatalConditionHandler* m_handler;
|
||||||
|
public:
|
||||||
namespace Catch {
|
FatalConditionHandlerGuard(FatalConditionHandler* handler):
|
||||||
struct FatalConditionHandler {
|
m_handler(handler) {
|
||||||
void reset();
|
m_handler->engage();
|
||||||
|
}
|
||||||
|
~FatalConditionHandlerGuard() {
|
||||||
|
m_handler->disengage();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
} // end namespace Catch
|
||||||
|
|
||||||
// end catch_fatal_condition.h
|
// end catch_fatal_condition.h
|
||||||
#include <string>
|
#include <string>
|
||||||
@ -8185,6 +8166,7 @@ namespace Catch {
|
|||||||
std::vector<SectionEndInfo> m_unfinishedSections;
|
std::vector<SectionEndInfo> m_unfinishedSections;
|
||||||
std::vector<ITracker*> m_activeSections;
|
std::vector<ITracker*> m_activeSections;
|
||||||
TrackerContext m_trackerContext;
|
TrackerContext m_trackerContext;
|
||||||
|
FatalConditionHandler m_fatalConditionhandler;
|
||||||
bool m_lastAssertionPassed = false;
|
bool m_lastAssertionPassed = false;
|
||||||
bool m_shouldReportUnexpected = true;
|
bool m_shouldReportUnexpected = true;
|
||||||
bool m_includeSuccessfulResults;
|
bool m_includeSuccessfulResults;
|
||||||
@ -10057,6 +10039,36 @@ namespace Catch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// end catch_errno_guard.h
|
// end catch_errno_guard.h
|
||||||
|
// start catch_windows_h_proxy.h
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(CATCH_PLATFORM_WINDOWS)
|
||||||
|
|
||||||
|
#if !defined(NOMINMAX) && !defined(CATCH_CONFIG_NO_NOMINMAX)
|
||||||
|
# define CATCH_DEFINED_NOMINMAX
|
||||||
|
# define NOMINMAX
|
||||||
|
#endif
|
||||||
|
#if !defined(WIN32_LEAN_AND_MEAN) && !defined(CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN)
|
||||||
|
# define CATCH_DEFINED_WIN32_LEAN_AND_MEAN
|
||||||
|
# define WIN32_LEAN_AND_MEAN
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __AFXDLL
|
||||||
|
#include <AfxWin.h>
|
||||||
|
#else
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CATCH_DEFINED_NOMINMAX
|
||||||
|
# undef NOMINMAX
|
||||||
|
#endif
|
||||||
|
#ifdef CATCH_DEFINED_WIN32_LEAN_AND_MEAN
|
||||||
|
# undef WIN32_LEAN_AND_MEAN
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // defined(CATCH_PLATFORM_WINDOWS)
|
||||||
|
|
||||||
|
// end catch_windows_h_proxy.h
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
@ -10573,7 +10585,7 @@ namespace Catch {
|
|||||||
// Extracts the actual name part of an enum instance
|
// Extracts the actual name part of an enum instance
|
||||||
// In other words, it returns the Blue part of Bikeshed::Colour::Blue
|
// In other words, it returns the Blue part of Bikeshed::Colour::Blue
|
||||||
StringRef extractInstanceName(StringRef enumInstance) {
|
StringRef extractInstanceName(StringRef enumInstance) {
|
||||||
// Find last occurence of ":"
|
// Find last occurrence of ":"
|
||||||
size_t name_start = enumInstance.size();
|
size_t name_start = enumInstance.size();
|
||||||
while (name_start > 0 && enumInstance[name_start - 1] != ':') {
|
while (name_start > 0 && enumInstance[name_start - 1] != ':') {
|
||||||
--name_start;
|
--name_start;
|
||||||
@ -10735,25 +10747,47 @@ namespace Catch {
|
|||||||
// end catch_exception_translator_registry.cpp
|
// end catch_exception_translator_registry.cpp
|
||||||
// start catch_fatal_condition.cpp
|
// start catch_fatal_condition.cpp
|
||||||
|
|
||||||
#if defined(__GNUC__)
|
#include <algorithm>
|
||||||
# pragma GCC diagnostic push
|
|
||||||
# pragma GCC diagnostic ignored "-Wmissing-field-initializers"
|
#if !defined( CATCH_CONFIG_WINDOWS_SEH ) && !defined( CATCH_CONFIG_POSIX_SIGNALS )
|
||||||
#endif
|
|
||||||
|
namespace Catch {
|
||||||
|
|
||||||
|
// If neither SEH nor signal handling is required, the handler impls
|
||||||
|
// do not have to do anything, and can be empty.
|
||||||
|
void FatalConditionHandler::engage_platform() {}
|
||||||
|
void FatalConditionHandler::disengage_platform() {}
|
||||||
|
FatalConditionHandler::FatalConditionHandler() = default;
|
||||||
|
FatalConditionHandler::~FatalConditionHandler() = default;
|
||||||
|
|
||||||
|
} // end namespace Catch
|
||||||
|
|
||||||
|
#endif // !CATCH_CONFIG_WINDOWS_SEH && !CATCH_CONFIG_POSIX_SIGNALS
|
||||||
|
|
||||||
|
#if defined( CATCH_CONFIG_WINDOWS_SEH ) && defined( CATCH_CONFIG_POSIX_SIGNALS )
|
||||||
|
#error "Inconsistent configuration: Windows' SEH handling and POSIX signals cannot be enabled at the same time"
|
||||||
|
#endif // CATCH_CONFIG_WINDOWS_SEH && CATCH_CONFIG_POSIX_SIGNALS
|
||||||
|
|
||||||
#if defined( CATCH_CONFIG_WINDOWS_SEH ) || defined( CATCH_CONFIG_POSIX_SIGNALS )
|
#if defined( CATCH_CONFIG_WINDOWS_SEH ) || defined( CATCH_CONFIG_POSIX_SIGNALS )
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
// Report the error condition
|
//! Signals fatal error message to the run context
|
||||||
void reportFatal( char const * const message ) {
|
void reportFatal( char const * const message ) {
|
||||||
Catch::getCurrentContext().getResultCapture()->handleFatalErrorCondition( message );
|
Catch::getCurrentContext().getResultCapture()->handleFatalErrorCondition( message );
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
#endif // signals/SEH handling
|
//! Minimal size Catch2 needs for its own fatal error handling.
|
||||||
|
//! Picked anecdotally, so it might not be sufficient on all
|
||||||
|
//! platforms, and for all configurations.
|
||||||
|
constexpr std::size_t minStackSizeForErrors = 32 * 1024;
|
||||||
|
} // end unnamed namespace
|
||||||
|
|
||||||
|
#endif // CATCH_CONFIG_WINDOWS_SEH || CATCH_CONFIG_POSIX_SIGNALS
|
||||||
|
|
||||||
#if defined( CATCH_CONFIG_WINDOWS_SEH )
|
#if defined( CATCH_CONFIG_WINDOWS_SEH )
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
struct SignalDefs { DWORD id; const char* name; };
|
struct SignalDefs { DWORD id; const char* name; };
|
||||||
|
|
||||||
// There is no 1-1 mapping between signals and windows exceptions.
|
// There is no 1-1 mapping between signals and windows exceptions.
|
||||||
@ -10766,7 +10800,7 @@ namespace Catch {
|
|||||||
{ static_cast<DWORD>(EXCEPTION_INT_DIVIDE_BY_ZERO), "Divide by zero error" },
|
{ static_cast<DWORD>(EXCEPTION_INT_DIVIDE_BY_ZERO), "Divide by zero error" },
|
||||||
};
|
};
|
||||||
|
|
||||||
LONG CALLBACK FatalConditionHandler::handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) {
|
static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) {
|
||||||
for (auto const& def : signalDefs) {
|
for (auto const& def : signalDefs) {
|
||||||
if (ExceptionInfo->ExceptionRecord->ExceptionCode == def.id) {
|
if (ExceptionInfo->ExceptionRecord->ExceptionCode == def.id) {
|
||||||
reportFatal(def.name);
|
reportFatal(def.name);
|
||||||
@ -10777,38 +10811,50 @@ namespace Catch {
|
|||||||
return EXCEPTION_CONTINUE_SEARCH;
|
return EXCEPTION_CONTINUE_SEARCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Since we do not support multiple instantiations, we put these
|
||||||
|
// into global variables and rely on cleaning them up in outlined
|
||||||
|
// constructors/destructors
|
||||||
|
static PVOID exceptionHandlerHandle = nullptr;
|
||||||
|
|
||||||
|
// For MSVC, we reserve part of the stack memory for handling
|
||||||
|
// memory overflow structured exception.
|
||||||
FatalConditionHandler::FatalConditionHandler() {
|
FatalConditionHandler::FatalConditionHandler() {
|
||||||
isSet = true;
|
ULONG guaranteeSize = static_cast<ULONG>(minStackSizeForErrors);
|
||||||
// 32k seems enough for Catch to handle stack overflow,
|
if (!SetThreadStackGuarantee(&guaranteeSize)) {
|
||||||
// but the value was found experimentally, so there is no strong guarantee
|
// We do not want to fully error out, because needing
|
||||||
guaranteeSize = 32 * 1024;
|
// the stack reserve should be rare enough anyway.
|
||||||
exceptionHandlerHandle = nullptr;
|
Catch::cerr()
|
||||||
|
<< "Failed to reserve piece of stack."
|
||||||
|
<< " Stack overflows will not be reported successfully.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We do not attempt to unset the stack guarantee, because
|
||||||
|
// Windows does not support lowering the stack size guarantee.
|
||||||
|
FatalConditionHandler::~FatalConditionHandler() = default;
|
||||||
|
|
||||||
|
void FatalConditionHandler::engage_platform() {
|
||||||
// Register as first handler in current chain
|
// Register as first handler in current chain
|
||||||
exceptionHandlerHandle = AddVectoredExceptionHandler(1, handleVectoredException);
|
exceptionHandlerHandle = AddVectoredExceptionHandler(1, handleVectoredException);
|
||||||
// Pass in guarantee size to be filled
|
if (!exceptionHandlerHandle) {
|
||||||
SetThreadStackGuarantee(&guaranteeSize);
|
CATCH_RUNTIME_ERROR("Could not register vectored exception handler");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FatalConditionHandler::reset() {
|
void FatalConditionHandler::disengage_platform() {
|
||||||
if (isSet) {
|
if (!RemoveVectoredExceptionHandler(exceptionHandlerHandle)) {
|
||||||
RemoveVectoredExceptionHandler(exceptionHandlerHandle);
|
CATCH_RUNTIME_ERROR("Could not unregister vectored exception handler");
|
||||||
SetThreadStackGuarantee(&guaranteeSize);
|
}
|
||||||
exceptionHandlerHandle = nullptr;
|
exceptionHandlerHandle = nullptr;
|
||||||
isSet = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FatalConditionHandler::~FatalConditionHandler() {
|
} // end namespace Catch
|
||||||
reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FatalConditionHandler::isSet = false;
|
#endif // CATCH_CONFIG_WINDOWS_SEH
|
||||||
ULONG FatalConditionHandler::guaranteeSize = 0;
|
|
||||||
PVOID FatalConditionHandler::exceptionHandlerHandle = nullptr;
|
|
||||||
|
|
||||||
} // namespace Catch
|
#if defined( CATCH_CONFIG_POSIX_SIGNALS )
|
||||||
|
|
||||||
#elif defined( CATCH_CONFIG_POSIX_SIGNALS )
|
#include <signal.h>
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
@ -10817,10 +10863,6 @@ namespace Catch {
|
|||||||
const char* name;
|
const char* name;
|
||||||
};
|
};
|
||||||
|
|
||||||
// 32kb for the alternate stack seems to be sufficient. However, this value
|
|
||||||
// is experimentally determined, so that's not guaranteed.
|
|
||||||
static constexpr std::size_t sigStackSize = 32768 >= MINSIGSTKSZ ? 32768 : MINSIGSTKSZ;
|
|
||||||
|
|
||||||
static SignalDefs signalDefs[] = {
|
static SignalDefs signalDefs[] = {
|
||||||
{ SIGINT, "SIGINT - Terminal interrupt signal" },
|
{ SIGINT, "SIGINT - Terminal interrupt signal" },
|
||||||
{ SIGILL, "SIGILL - Illegal instruction signal" },
|
{ SIGILL, "SIGILL - Illegal instruction signal" },
|
||||||
@ -10830,7 +10872,32 @@ namespace Catch {
|
|||||||
{ SIGABRT, "SIGABRT - Abort (abnormal termination) signal" }
|
{ SIGABRT, "SIGABRT - Abort (abnormal termination) signal" }
|
||||||
};
|
};
|
||||||
|
|
||||||
void FatalConditionHandler::handleSignal( int sig ) {
|
// Older GCCs trigger -Wmissing-field-initializers for T foo = {}
|
||||||
|
// which is zero initialization, but not explicit. We want to avoid
|
||||||
|
// that.
|
||||||
|
#if defined(__GNUC__)
|
||||||
|
# pragma GCC diagnostic push
|
||||||
|
# pragma GCC diagnostic ignored "-Wmissing-field-initializers"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static char* altStackMem = nullptr;
|
||||||
|
static std::size_t altStackSize = 0;
|
||||||
|
static stack_t oldSigStack{};
|
||||||
|
static struct sigaction oldSigActions[sizeof(signalDefs) / sizeof(SignalDefs)]{};
|
||||||
|
|
||||||
|
static void restorePreviousSignalHandlers() {
|
||||||
|
// We set signal handlers back to the previous ones. Hopefully
|
||||||
|
// nobody overwrote them in the meantime, and doesn't expect
|
||||||
|
// their signal handlers to live past ours given that they
|
||||||
|
// installed them after ours..
|
||||||
|
for (std::size_t i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) {
|
||||||
|
sigaction(signalDefs[i].id, &oldSigActions[i], nullptr);
|
||||||
|
}
|
||||||
|
// Return the old stack
|
||||||
|
sigaltstack(&oldSigStack, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handleSignal( int sig ) {
|
||||||
char const * name = "<unknown signal>";
|
char const * name = "<unknown signal>";
|
||||||
for (auto const& def : signalDefs) {
|
for (auto const& def : signalDefs) {
|
||||||
if (sig == def.id) {
|
if (sig == def.id) {
|
||||||
@ -10838,16 +10905,33 @@ namespace Catch {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
reset();
|
// We need to restore previous signal handlers and let them do
|
||||||
reportFatal(name);
|
// their thing, so that the users can have the debugger break
|
||||||
|
// when a signal is raised, and so on.
|
||||||
|
restorePreviousSignalHandlers();
|
||||||
|
reportFatal( name );
|
||||||
raise( sig );
|
raise( sig );
|
||||||
}
|
}
|
||||||
|
|
||||||
FatalConditionHandler::FatalConditionHandler() {
|
FatalConditionHandler::FatalConditionHandler() {
|
||||||
isSet = true;
|
assert(!altStackMem && "Cannot initialize POSIX signal handler when one already exists");
|
||||||
|
if (altStackSize == 0) {
|
||||||
|
altStackSize = std::max(static_cast<size_t>(SIGSTKSZ), minStackSizeForErrors);
|
||||||
|
}
|
||||||
|
altStackMem = new char[altStackSize]();
|
||||||
|
}
|
||||||
|
|
||||||
|
FatalConditionHandler::~FatalConditionHandler() {
|
||||||
|
delete[] altStackMem;
|
||||||
|
// We signal that another instance can be constructed by zeroing
|
||||||
|
// out the pointer.
|
||||||
|
altStackMem = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FatalConditionHandler::engage_platform() {
|
||||||
stack_t sigStack;
|
stack_t sigStack;
|
||||||
sigStack.ss_sp = altStackMem;
|
sigStack.ss_sp = altStackMem;
|
||||||
sigStack.ss_size = sigStackSize;
|
sigStack.ss_size = altStackSize;
|
||||||
sigStack.ss_flags = 0;
|
sigStack.ss_flags = 0;
|
||||||
sigaltstack(&sigStack, &oldSigStack);
|
sigaltstack(&sigStack, &oldSigStack);
|
||||||
struct sigaction sa = { };
|
struct sigaction sa = { };
|
||||||
@ -10859,40 +10943,17 @@ namespace Catch {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FatalConditionHandler::~FatalConditionHandler() {
|
|
||||||
reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FatalConditionHandler::reset() {
|
|
||||||
if( isSet ) {
|
|
||||||
// Set signals back to previous values -- hopefully nobody overwrote them in the meantime
|
|
||||||
for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) {
|
|
||||||
sigaction(signalDefs[i].id, &oldSigActions[i], nullptr);
|
|
||||||
}
|
|
||||||
// Return the old stack
|
|
||||||
sigaltstack(&oldSigStack, nullptr);
|
|
||||||
isSet = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FatalConditionHandler::isSet = false;
|
|
||||||
struct sigaction FatalConditionHandler::oldSigActions[sizeof(signalDefs)/sizeof(SignalDefs)] = {};
|
|
||||||
stack_t FatalConditionHandler::oldSigStack = {};
|
|
||||||
char FatalConditionHandler::altStackMem[sigStackSize] = {};
|
|
||||||
|
|
||||||
} // namespace Catch
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
namespace Catch {
|
|
||||||
void FatalConditionHandler::reset() {}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // signals/SEH handling
|
|
||||||
|
|
||||||
#if defined(__GNUC__)
|
#if defined(__GNUC__)
|
||||||
# pragma GCC diagnostic pop
|
# pragma GCC diagnostic pop
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void FatalConditionHandler::disengage_platform() {
|
||||||
|
restorePreviousSignalHandlers();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // end namespace Catch
|
||||||
|
|
||||||
|
#endif // CATCH_CONFIG_POSIX_SIGNALS
|
||||||
// end catch_fatal_condition.cpp
|
// end catch_fatal_condition.cpp
|
||||||
// start catch_generators.cpp
|
// start catch_generators.cpp
|
||||||
|
|
||||||
@ -11447,7 +11508,8 @@ namespace {
|
|||||||
return lhs == rhs;
|
return lhs == rhs;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ulpDiff = std::abs(lc - rc);
|
// static cast as a workaround for IBM XLC
|
||||||
|
auto ulpDiff = std::abs(static_cast<FP>(lc - rc));
|
||||||
return static_cast<uint64_t>(ulpDiff) <= maxUlpDiff;
|
return static_cast<uint64_t>(ulpDiff) <= maxUlpDiff;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -11621,7 +11683,6 @@ Floating::WithinRelMatcher WithinRel(float target) {
|
|||||||
|
|
||||||
} // namespace Matchers
|
} // namespace Matchers
|
||||||
} // namespace Catch
|
} // namespace Catch
|
||||||
|
|
||||||
// end catch_matchers_floating.cpp
|
// end catch_matchers_floating.cpp
|
||||||
// start catch_matchers_generic.cpp
|
// start catch_matchers_generic.cpp
|
||||||
|
|
||||||
@ -12955,9 +13016,8 @@ namespace Catch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void RunContext::invokeActiveTestCase() {
|
void RunContext::invokeActiveTestCase() {
|
||||||
FatalConditionHandler fatalConditionHandler; // Handle signals
|
FatalConditionHandlerGuard _(&m_fatalConditionhandler);
|
||||||
m_activeTestCase->invoke();
|
m_activeTestCase->invoke();
|
||||||
fatalConditionHandler.reset();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RunContext::handleUnfinishedSections() {
|
void RunContext::handleUnfinishedSections() {
|
||||||
@ -14126,24 +14186,28 @@ namespace Catch {
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
struct TestHasher {
|
struct TestHasher {
|
||||||
explicit TestHasher(Catch::SimplePcg32& rng_instance) {
|
using hash_t = uint64_t;
|
||||||
basis = rng_instance();
|
|
||||||
basis <<= 32;
|
|
||||||
basis |= rng_instance();
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t basis;
|
explicit TestHasher( hash_t hashSuffix ):
|
||||||
|
m_hashSuffix{ hashSuffix } {}
|
||||||
|
|
||||||
uint64_t operator()(TestCase const& t) const {
|
uint32_t operator()( TestCase const& t ) const {
|
||||||
// Modified FNV-1a hash
|
// FNV-1a hash with multiplication fold.
|
||||||
static constexpr uint64_t prime = 1099511628211;
|
const hash_t prime = 1099511628211u;
|
||||||
uint64_t hash = basis;
|
hash_t hash = 14695981039346656037u;
|
||||||
for (const char c : t.name) {
|
for ( const char c : t.name ) {
|
||||||
hash ^= c;
|
hash ^= c;
|
||||||
hash *= prime;
|
hash *= prime;
|
||||||
}
|
}
|
||||||
return hash;
|
hash ^= m_hashSuffix;
|
||||||
|
hash *= prime;
|
||||||
|
const uint32_t low{ static_cast<uint32_t>( hash ) };
|
||||||
|
const uint32_t high{ static_cast<uint32_t>( hash >> 32 ) };
|
||||||
|
return low * high;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
hash_t m_hashSuffix;
|
||||||
};
|
};
|
||||||
} // end unnamed namespace
|
} // end unnamed namespace
|
||||||
|
|
||||||
@ -14161,9 +14225,9 @@ namespace Catch {
|
|||||||
|
|
||||||
case RunTests::InRandomOrder: {
|
case RunTests::InRandomOrder: {
|
||||||
seedRng( config );
|
seedRng( config );
|
||||||
TestHasher h( rng() );
|
TestHasher h{ config.rngSeed() };
|
||||||
|
|
||||||
using hashedTest = std::pair<uint64_t, TestCase const*>;
|
using hashedTest = std::pair<TestHasher::hash_t, TestCase const*>;
|
||||||
std::vector<hashedTest> indexed_tests;
|
std::vector<hashedTest> indexed_tests;
|
||||||
indexed_tests.reserve( unsortedTestCases.size() );
|
indexed_tests.reserve( unsortedTestCases.size() );
|
||||||
|
|
||||||
@ -15316,7 +15380,7 @@ namespace Catch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Version const& libraryVersion() {
|
Version const& libraryVersion() {
|
||||||
static Version version( 2, 13, 3, "", 0 );
|
static Version version( 2, 13, 7, "", 0 );
|
||||||
return version;
|
return version;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -16729,6 +16793,7 @@ CATCH_REGISTER_REPORTER("console", ConsoleReporter)
|
|||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <iomanip>
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
@ -16756,7 +16821,7 @@ namespace Catch {
|
|||||||
#else
|
#else
|
||||||
std::strftime(timeStamp, timeStampSize, fmt, timeInfo);
|
std::strftime(timeStamp, timeStampSize, fmt, timeInfo);
|
||||||
#endif
|
#endif
|
||||||
return std::string(timeStamp);
|
return std::string(timeStamp, timeStampSize-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string fileNameTag(const std::vector<std::string> &tags) {
|
std::string fileNameTag(const std::vector<std::string> &tags) {
|
||||||
@ -16767,6 +16832,17 @@ namespace Catch {
|
|||||||
return it->substr(1);
|
return it->substr(1);
|
||||||
return std::string();
|
return std::string();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Formats the duration in seconds to 3 decimal places.
|
||||||
|
// This is done because some genius defined Maven Surefire schema
|
||||||
|
// in a way that only accepts 3 decimal places, and tools like
|
||||||
|
// Jenkins use that schema for validation JUnit reporter output.
|
||||||
|
std::string formatDuration( double seconds ) {
|
||||||
|
ReusableStringStream rss;
|
||||||
|
rss << std::fixed << std::setprecision( 3 ) << seconds;
|
||||||
|
return rss.str();
|
||||||
|
}
|
||||||
|
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
|
||||||
JunitReporter::JunitReporter( ReporterConfig const& _config )
|
JunitReporter::JunitReporter( ReporterConfig const& _config )
|
||||||
@ -16836,7 +16912,7 @@ namespace Catch {
|
|||||||
if( m_config->showDurations() == ShowDurations::Never )
|
if( m_config->showDurations() == ShowDurations::Never )
|
||||||
xml.writeAttribute( "time", "" );
|
xml.writeAttribute( "time", "" );
|
||||||
else
|
else
|
||||||
xml.writeAttribute( "time", suiteTime );
|
xml.writeAttribute( "time", formatDuration( suiteTime ) );
|
||||||
xml.writeAttribute( "timestamp", getCurrentTimestamp() );
|
xml.writeAttribute( "timestamp", getCurrentTimestamp() );
|
||||||
|
|
||||||
// Write properties if there are any
|
// Write properties if there are any
|
||||||
@ -16881,12 +16957,13 @@ namespace Catch {
|
|||||||
if ( !m_config->name().empty() )
|
if ( !m_config->name().empty() )
|
||||||
className = m_config->name() + "." + className;
|
className = m_config->name() + "." + className;
|
||||||
|
|
||||||
writeSection( className, "", rootSection );
|
writeSection( className, "", rootSection, stats.testInfo.okToFail() );
|
||||||
}
|
}
|
||||||
|
|
||||||
void JunitReporter::writeSection( std::string const& className,
|
void JunitReporter::writeSection( std::string const& className,
|
||||||
std::string const& rootName,
|
std::string const& rootName,
|
||||||
SectionNode const& sectionNode ) {
|
SectionNode const& sectionNode,
|
||||||
|
bool testOkToFail) {
|
||||||
std::string name = trim( sectionNode.stats.sectionInfo.name );
|
std::string name = trim( sectionNode.stats.sectionInfo.name );
|
||||||
if( !rootName.empty() )
|
if( !rootName.empty() )
|
||||||
name = rootName + '/' + name;
|
name = rootName + '/' + name;
|
||||||
@ -16903,13 +16980,18 @@ namespace Catch {
|
|||||||
xml.writeAttribute( "classname", className );
|
xml.writeAttribute( "classname", className );
|
||||||
xml.writeAttribute( "name", name );
|
xml.writeAttribute( "name", name );
|
||||||
}
|
}
|
||||||
xml.writeAttribute( "time", ::Catch::Detail::stringify( sectionNode.stats.durationInSeconds ) );
|
xml.writeAttribute( "time", formatDuration( sectionNode.stats.durationInSeconds ) );
|
||||||
// This is not ideal, but it should be enough to mimic gtest's
|
// This is not ideal, but it should be enough to mimic gtest's
|
||||||
// junit output.
|
// junit output.
|
||||||
// Ideally the JUnit reporter would also handle `skipTest`
|
// Ideally the JUnit reporter would also handle `skipTest`
|
||||||
// events and write those out appropriately.
|
// events and write those out appropriately.
|
||||||
xml.writeAttribute( "status", "run" );
|
xml.writeAttribute( "status", "run" );
|
||||||
|
|
||||||
|
if (sectionNode.stats.assertions.failedButOk) {
|
||||||
|
xml.scopedElement("skipped")
|
||||||
|
.writeAttribute("message", "TEST_CASE tagged with !mayfail");
|
||||||
|
}
|
||||||
|
|
||||||
writeAssertions( sectionNode );
|
writeAssertions( sectionNode );
|
||||||
|
|
||||||
if( !sectionNode.stdOut.empty() )
|
if( !sectionNode.stdOut.empty() )
|
||||||
@ -16919,9 +17001,9 @@ namespace Catch {
|
|||||||
}
|
}
|
||||||
for( auto const& childNode : sectionNode.childSections )
|
for( auto const& childNode : sectionNode.childSections )
|
||||||
if( className.empty() )
|
if( className.empty() )
|
||||||
writeSection( name, "", *childNode );
|
writeSection( name, "", *childNode, testOkToFail );
|
||||||
else
|
else
|
||||||
writeSection( className, name, *childNode );
|
writeSection( className, name, *childNode, testOkToFail );
|
||||||
}
|
}
|
||||||
|
|
||||||
void JunitReporter::writeAssertions( SectionNode const& sectionNode ) {
|
void JunitReporter::writeAssertions( SectionNode const& sectionNode ) {
|
||||||
|
|||||||
181
catch/catch_reporter_sonarqube.hpp
Normal file
181
catch/catch_reporter_sonarqube.hpp
Normal file
@ -0,0 +1,181 @@
|
|||||||
|
/*
|
||||||
|
* Created by Daniel Garcia on 2018-12-04.
|
||||||
|
* Copyright Social Point SL. All rights reserved.
|
||||||
|
*
|
||||||
|
* Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*/
|
||||||
|
#ifndef CATCH_REPORTER_SONARQUBE_HPP_INCLUDED
|
||||||
|
#define CATCH_REPORTER_SONARQUBE_HPP_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
// Don't #include any Catch headers here - we can assume they are already
|
||||||
|
// included before this header.
|
||||||
|
// This is not good practice in general but is necessary in this case so this
|
||||||
|
// file can be distributed as a single header that works with the main
|
||||||
|
// Catch single header.
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
namespace Catch {
|
||||||
|
|
||||||
|
struct SonarQubeReporter : CumulativeReporterBase<SonarQubeReporter> {
|
||||||
|
|
||||||
|
SonarQubeReporter(ReporterConfig const& config)
|
||||||
|
: CumulativeReporterBase(config)
|
||||||
|
, xml(config.stream()) {
|
||||||
|
m_reporterPrefs.shouldRedirectStdOut = true;
|
||||||
|
m_reporterPrefs.shouldReportAllAssertions = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
~SonarQubeReporter() override;
|
||||||
|
|
||||||
|
static std::string getDescription() {
|
||||||
|
return "Reports test results in the Generic Test Data SonarQube XML format";
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::set<Verbosity> getSupportedVerbosities() {
|
||||||
|
return { Verbosity::Normal };
|
||||||
|
}
|
||||||
|
|
||||||
|
void noMatchingTestCases(std::string const& /*spec*/) override {}
|
||||||
|
|
||||||
|
void testRunStarting(TestRunInfo const& testRunInfo) override {
|
||||||
|
CumulativeReporterBase::testRunStarting(testRunInfo);
|
||||||
|
xml.startElement("testExecutions");
|
||||||
|
xml.writeAttribute("version", "1");
|
||||||
|
}
|
||||||
|
|
||||||
|
void testGroupEnded(TestGroupStats const& testGroupStats) override {
|
||||||
|
CumulativeReporterBase::testGroupEnded(testGroupStats);
|
||||||
|
writeGroup(*m_testGroups.back());
|
||||||
|
}
|
||||||
|
|
||||||
|
void testRunEndedCumulative() override {
|
||||||
|
xml.endElement();
|
||||||
|
}
|
||||||
|
|
||||||
|
void writeGroup(TestGroupNode const& groupNode) {
|
||||||
|
std::map<std::string, TestGroupNode::ChildNodes> testsPerFile;
|
||||||
|
for(auto const& child : groupNode.children)
|
||||||
|
testsPerFile[child->value.testInfo.lineInfo.file].push_back(child);
|
||||||
|
|
||||||
|
for(auto const& kv : testsPerFile)
|
||||||
|
writeTestFile(kv.first.c_str(), kv.second);
|
||||||
|
}
|
||||||
|
|
||||||
|
void writeTestFile(const char* filename, TestGroupNode::ChildNodes const& testCaseNodes) {
|
||||||
|
XmlWriter::ScopedElement e = xml.scopedElement("file");
|
||||||
|
xml.writeAttribute("path", filename);
|
||||||
|
|
||||||
|
for(auto const& child : testCaseNodes)
|
||||||
|
writeTestCase(*child);
|
||||||
|
}
|
||||||
|
|
||||||
|
void writeTestCase(TestCaseNode const& testCaseNode) {
|
||||||
|
// All test cases have exactly one section - which represents the
|
||||||
|
// test case itself. That section may have 0-n nested sections
|
||||||
|
assert(testCaseNode.children.size() == 1);
|
||||||
|
SectionNode const& rootSection = *testCaseNode.children.front();
|
||||||
|
writeSection("", rootSection, testCaseNode.value.testInfo.okToFail());
|
||||||
|
}
|
||||||
|
|
||||||
|
void writeSection(std::string const& rootName, SectionNode const& sectionNode, bool okToFail) {
|
||||||
|
std::string name = trim(sectionNode.stats.sectionInfo.name);
|
||||||
|
if(!rootName.empty())
|
||||||
|
name = rootName + '/' + name;
|
||||||
|
|
||||||
|
if(!sectionNode.assertions.empty() || !sectionNode.stdOut.empty() || !sectionNode.stdErr.empty()) {
|
||||||
|
XmlWriter::ScopedElement e = xml.scopedElement("testCase");
|
||||||
|
xml.writeAttribute("name", name);
|
||||||
|
xml.writeAttribute("duration", static_cast<long>(sectionNode.stats.durationInSeconds * 1000));
|
||||||
|
|
||||||
|
writeAssertions(sectionNode, okToFail);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(auto const& childNode : sectionNode.childSections)
|
||||||
|
writeSection(name, *childNode, okToFail);
|
||||||
|
}
|
||||||
|
|
||||||
|
void writeAssertions(SectionNode const& sectionNode, bool okToFail) {
|
||||||
|
for(auto const& assertion : sectionNode.assertions)
|
||||||
|
writeAssertion( assertion, okToFail);
|
||||||
|
}
|
||||||
|
|
||||||
|
void writeAssertion(AssertionStats const& stats, bool okToFail) {
|
||||||
|
AssertionResult const& result = stats.assertionResult;
|
||||||
|
if(!result.isOk()) {
|
||||||
|
std::string elementName;
|
||||||
|
if(okToFail) {
|
||||||
|
elementName = "skipped";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
switch(result.getResultType()) {
|
||||||
|
case ResultWas::ThrewException:
|
||||||
|
case ResultWas::FatalErrorCondition:
|
||||||
|
elementName = "error";
|
||||||
|
break;
|
||||||
|
case ResultWas::ExplicitFailure:
|
||||||
|
elementName = "failure";
|
||||||
|
break;
|
||||||
|
case ResultWas::ExpressionFailed:
|
||||||
|
elementName = "failure";
|
||||||
|
break;
|
||||||
|
case ResultWas::DidntThrowException:
|
||||||
|
elementName = "failure";
|
||||||
|
break;
|
||||||
|
|
||||||
|
// We should never see these here:
|
||||||
|
case ResultWas::Info:
|
||||||
|
case ResultWas::Warning:
|
||||||
|
case ResultWas::Ok:
|
||||||
|
case ResultWas::Unknown:
|
||||||
|
case ResultWas::FailureBit:
|
||||||
|
case ResultWas::Exception:
|
||||||
|
elementName = "internalError";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
XmlWriter::ScopedElement e = xml.scopedElement(elementName);
|
||||||
|
|
||||||
|
ReusableStringStream messageRss;
|
||||||
|
messageRss << result.getTestMacroName() << "(" << result.getExpression() << ")";
|
||||||
|
xml.writeAttribute("message", messageRss.str());
|
||||||
|
|
||||||
|
ReusableStringStream textRss;
|
||||||
|
if (stats.totals.assertions.total() > 0) {
|
||||||
|
textRss << "FAILED:\n";
|
||||||
|
if (result.hasExpression()) {
|
||||||
|
textRss << "\t" << result.getExpressionInMacro() << "\n";
|
||||||
|
}
|
||||||
|
if (result.hasExpandedExpression()) {
|
||||||
|
textRss << "with expansion:\n\t" << result.getExpandedExpression() << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!result.getMessage().empty())
|
||||||
|
textRss << result.getMessage() << "\n";
|
||||||
|
|
||||||
|
for(auto const& msg : stats.infoMessages)
|
||||||
|
if(msg.type == ResultWas::Info)
|
||||||
|
textRss << msg.message << "\n";
|
||||||
|
|
||||||
|
textRss << "at " << result.getSourceInfo();
|
||||||
|
xml.writeText(textRss.str(), XmlFormatting::Newline);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
XmlWriter xml;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef CATCH_IMPL
|
||||||
|
SonarQubeReporter::~SonarQubeReporter() {}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
CATCH_REGISTER_REPORTER( "sonarqube", SonarQubeReporter )
|
||||||
|
|
||||||
|
} // end namespace Catch
|
||||||
|
|
||||||
|
#endif // CATCH_REPORTER_SONARQUBE_HPP_INCLUDED
|
||||||
@ -23,18 +23,17 @@ namespace Catch {
|
|||||||
|
|
||||||
using StreamingReporterBase::StreamingReporterBase;
|
using StreamingReporterBase::StreamingReporterBase;
|
||||||
|
|
||||||
|
TAPReporter( ReporterConfig const& config ):
|
||||||
|
StreamingReporterBase( config ) {
|
||||||
|
m_reporterPrefs.shouldReportAllAssertions = true;
|
||||||
|
}
|
||||||
|
|
||||||
~TAPReporter() override;
|
~TAPReporter() override;
|
||||||
|
|
||||||
static std::string getDescription() {
|
static std::string getDescription() {
|
||||||
return "Reports test results in TAP format, suitable for test harnesses";
|
return "Reports test results in TAP format, suitable for test harnesses";
|
||||||
}
|
}
|
||||||
|
|
||||||
ReporterPreferences getPreferences() const override {
|
|
||||||
ReporterPreferences prefs;
|
|
||||||
prefs.shouldRedirectStdOut = false;
|
|
||||||
return prefs;
|
|
||||||
}
|
|
||||||
|
|
||||||
void noMatchingTestCases( std::string const& spec ) override {
|
void noMatchingTestCases( std::string const& spec ) override {
|
||||||
stream << "# No test cases matched '" << spec << "'" << std::endl;
|
stream << "# No test cases matched '" << spec << "'" << std::endl;
|
||||||
}
|
}
|
||||||
@ -44,9 +43,9 @@ namespace Catch {
|
|||||||
bool assertionEnded( AssertionStats const& _assertionStats ) override {
|
bool assertionEnded( AssertionStats const& _assertionStats ) override {
|
||||||
++counter;
|
++counter;
|
||||||
|
|
||||||
|
stream << "# " << currentTestCaseInfo->name << std::endl;
|
||||||
AssertionPrinter printer( stream, _assertionStats, counter );
|
AssertionPrinter printer( stream, _assertionStats, counter );
|
||||||
printer.print();
|
printer.print();
|
||||||
stream << " # " << currentTestCaseInfo->name ;
|
|
||||||
|
|
||||||
stream << std::endl;
|
stream << std::endl;
|
||||||
return true;
|
return true;
|
||||||
@ -205,16 +204,15 @@ namespace Catch {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// using messages.end() directly (or auto) yields compilation error:
|
const auto itEnd = messages.cend();
|
||||||
std::vector<MessageInfo>::const_iterator itEnd = messages.end();
|
const auto N = static_cast<std::size_t>( std::distance( itMessage, itEnd ) );
|
||||||
const std::size_t N = static_cast<std::size_t>( std::distance( itMessage, itEnd ) );
|
|
||||||
|
|
||||||
{
|
{
|
||||||
Colour colourGuard( colour );
|
Colour colourGuard( colour );
|
||||||
stream << " with " << pluralise( N, "message" ) << ":";
|
stream << " with " << pluralise( N, "message" ) << ":";
|
||||||
}
|
}
|
||||||
|
|
||||||
for(; itMessage != itEnd; ) {
|
while( itMessage != itEnd ) {
|
||||||
// If this assertion is a warning ignore any INFO messages
|
// If this assertion is a warning ignore any INFO messages
|
||||||
if( printInfoMessages || itMessage->type != ResultWas::Info ) {
|
if( printInfoMessages || itMessage->type != ResultWas::Info ) {
|
||||||
stream << " '" << itMessage->message << "'";
|
stream << " '" << itMessage->message << "'";
|
||||||
@ -222,7 +220,9 @@ namespace Catch {
|
|||||||
Colour colourGuard( dimColour() );
|
Colour colourGuard( dimColour() );
|
||||||
stream << " and";
|
stream << " and";
|
||||||
}
|
}
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
++itMessage;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -236,10 +236,9 @@ namespace Catch {
|
|||||||
};
|
};
|
||||||
|
|
||||||
void printTotals( const Totals& totals ) const {
|
void printTotals( const Totals& totals ) const {
|
||||||
|
stream << "1.." << totals.assertions.total();
|
||||||
if( totals.testCases.total() == 0 ) {
|
if( totals.testCases.total() == 0 ) {
|
||||||
stream << "1..0 # Skipped: No tests ran.";
|
stream << " # Skipped: No tests ran.";
|
||||||
} else {
|
|
||||||
stream << "1.." << counter;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -97,12 +97,12 @@ namespace Catch {
|
|||||||
case ResultWas::Ok:
|
case ResultWas::Ok:
|
||||||
case ResultWas::Info:
|
case ResultWas::Info:
|
||||||
case ResultWas::Warning:
|
case ResultWas::Warning:
|
||||||
throw std::domain_error( "Internal error in TeamCity reporter" );
|
CATCH_ERROR( "Internal error in TeamCity reporter" );
|
||||||
// These cases are here to prevent compiler warnings
|
// These cases are here to prevent compiler warnings
|
||||||
case ResultWas::Unknown:
|
case ResultWas::Unknown:
|
||||||
case ResultWas::FailureBit:
|
case ResultWas::FailureBit:
|
||||||
case ResultWas::Exception:
|
case ResultWas::Exception:
|
||||||
throw std::domain_error( "Not implemented" );
|
CATCH_ERROR( "Not implemented" );
|
||||||
}
|
}
|
||||||
if( assertionStats.infoMessages.size() == 1 )
|
if( assertionStats.infoMessages.size() == 1 )
|
||||||
msg << " with message:";
|
msg << " with message:";
|
||||||
@ -183,7 +183,6 @@ namespace Catch {
|
|||||||
|
|
||||||
SourceLineInfo lineInfo = m_sectionStack.front().lineInfo;
|
SourceLineInfo lineInfo = m_sectionStack.front().lineInfo;
|
||||||
|
|
||||||
if( !lineInfo.empty() )
|
|
||||||
os << lineInfo << "\n";
|
os << lineInfo << "\n";
|
||||||
os << getLineOfChars<'.'>() << "\n\n";
|
os << getLineOfChars<'.'>() << "\n\n";
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user