mirror of
https://github.com/catchorg/Catch2.git
synced 2025-02-16 19:43:28 +01:00
Add stringification for std::chrono::{duration,time_point}
Also hides std::chrono, std::pair and std::chrono::* behind new configuration macros, CATCH_CONFIG_ENABLE_*_STRINGMAKER to avoid dragging in <utility>, <tuple> and <chrono> in common path, unless requested.
This commit is contained in:
parent
f972732737
commit
79b405fd3f
@ -68,6 +68,7 @@ set(TEST_SOURCES
|
|||||||
${SELF_TEST_DIR}/PartTrackerTests.cpp
|
${SELF_TEST_DIR}/PartTrackerTests.cpp
|
||||||
${SELF_TEST_DIR}/TagAliasTests.cpp
|
${SELF_TEST_DIR}/TagAliasTests.cpp
|
||||||
${SELF_TEST_DIR}/TestMain.cpp
|
${SELF_TEST_DIR}/TestMain.cpp
|
||||||
|
${SELF_TEST_DIR}/ToStringChrono.cpp
|
||||||
${SELF_TEST_DIR}/ToStringGeneralTests.cpp
|
${SELF_TEST_DIR}/ToStringGeneralTests.cpp
|
||||||
${SELF_TEST_DIR}/ToStringPair.cpp
|
${SELF_TEST_DIR}/ToStringPair.cpp
|
||||||
${SELF_TEST_DIR}/ToStringTuple.cpp
|
${SELF_TEST_DIR}/ToStringTuple.cpp
|
||||||
|
@ -1,14 +1,15 @@
|
|||||||
<a id="top"></a>
|
<a id="top"></a>
|
||||||
# Compile-time configuration
|
# Compile-time configuration
|
||||||
|
|
||||||
**Contents**
|
**Contents**
|
||||||
[main()/ implementation](#main-implementation)
|
[main()/ implementation](#main-implementation)
|
||||||
[Prefixing Catch macros](#prefixing-catch-macros)
|
[Prefixing Catch macros](#prefixing-catch-macros)
|
||||||
[Terminal colour](#terminal-colour)
|
[Terminal colour](#terminal-colour)
|
||||||
[Console width](#console-width)
|
[Console width](#console-width)
|
||||||
[stdout](#stdout)
|
[stdout](#stdout)
|
||||||
[Other toggles](#other-toggles)
|
[Other toggles](#other-toggles)
|
||||||
[Windows header clutter](#windows-header-clutter)
|
[Windows header clutter](#windows-header-clutter)
|
||||||
|
[Enabling stringification](#enabling-stringification)
|
||||||
|
|
||||||
Catch is designed to "just work" as much as possible. For most people the only configuration needed is telling Catch which source file should host all the implementation code (```CATCH_CONFIG_MAIN```).
|
Catch is designed to "just work" as much as possible. For most people the only configuration needed is telling Catch which source file should host all the implementation code (```CATCH_CONFIG_MAIN```).
|
||||||
|
|
||||||
@ -121,6 +122,17 @@ On Windows Catch includes `windows.h`. To minimize global namespace clutter in t
|
|||||||
CATCH_CONFIG_NO_NOMINMAX // Stops Catch from using NOMINMAX macro
|
CATCH_CONFIG_NO_NOMINMAX // Stops Catch from using NOMINMAX macro
|
||||||
CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN // Stops Catch from using WIN32_LEAN_AND_MEAN macro
|
CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN // Stops Catch from using WIN32_LEAN_AND_MEAN macro
|
||||||
|
|
||||||
|
|
||||||
|
## Enabling stringification
|
||||||
|
|
||||||
|
By default, Catch does not stringify some types from the standard library. This is done to avoid dragging in various standard library headers by default. However, Catch does contain these and can be configured to provide them, using these macros:
|
||||||
|
|
||||||
|
CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER // Provide StringMaker specialization for std::pair
|
||||||
|
CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER // Provide StringMaker specialization for std::tuple
|
||||||
|
CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER // Provide StringMaker specialization for std::chrono::duration, std::chrono::timepoint
|
||||||
|
CATCH_CONFIG_ENABLE_ALL_STRINGMAKERS // Defines all of the above
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
[Home](Readme.md#top)
|
[Home](Readme.md#top)
|
||||||
|
@ -22,7 +22,9 @@
|
|||||||
* Removed support for non-const comparison operators
|
* Removed support for non-const comparison operators
|
||||||
* Non-const comparison operators are an abomination that should not exist
|
* Non-const comparison operators are an abomination that should not exist
|
||||||
* They were breaking support for comparing function to function pointer
|
* They were breaking support for comparing function to function pointer
|
||||||
|
* `std::pair` and `std::tuple` are no longer stringified by default
|
||||||
|
* This is done to avoid dragging in `<tuple>` and `<utility>` headers in common path
|
||||||
|
* Their stringification can be enabled per-file via new configuration macros
|
||||||
|
|
||||||
## Improvements
|
## Improvements
|
||||||
* Reporters and Listeners can be defined in files different from the main file
|
* Reporters and Listeners can be defined in files different from the main file
|
||||||
@ -53,7 +55,8 @@
|
|||||||
* Reporters/Listeners are now notified of fatal errors
|
* Reporters/Listeners are now notified of fatal errors
|
||||||
* This means specific signals or structured exceptions
|
* This means specific signals or structured exceptions
|
||||||
* The Reporter/Listener interface provides default, empty, implementation to preserve backward compatibility
|
* The Reporter/Listener interface provides default, empty, implementation to preserve backward compatibility
|
||||||
|
* Stringification of `std::chrono::duration` and `std::chrono::time_point` is now supported
|
||||||
|
* Needs to be enabled by a per-file compile time configuration option
|
||||||
|
|
||||||
## Fixes
|
## Fixes
|
||||||
* Don't use console colour if running in XCode
|
* Don't use console colour if running in XCode
|
||||||
|
@ -12,7 +12,6 @@
|
|||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <tuple>
|
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
@ -57,7 +56,7 @@ namespace Catch {
|
|||||||
public:
|
public:
|
||||||
static const bool value = decltype(test<std::ostream, const T&>(0))::value;
|
static const bool value = decltype(test<std::ostream, const T&>(0))::value;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Detail
|
} // namespace Detail
|
||||||
|
|
||||||
// If we decide for C++14, change these to enable_if_ts
|
// If we decide for C++14, change these to enable_if_ts
|
||||||
@ -241,7 +240,53 @@ namespace Catch {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// === Pair ===
|
template<typename T>
|
||||||
|
struct EnumStringMaker {
|
||||||
|
static std::string convert(const T& t) {
|
||||||
|
return ::Catch::Detail::stringify(static_cast<typename std::underlying_type<T>::type>(t));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef __OBJC__
|
||||||
|
template<>
|
||||||
|
struct StringMaker<NSString*> {
|
||||||
|
static std::string convert(NSString * nsstring) {
|
||||||
|
if (!nsstring)
|
||||||
|
return "nil";
|
||||||
|
return std::string("@") + [nsstring UTF8String];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
template<>
|
||||||
|
struct StringMaker<NSObject*> {
|
||||||
|
static std::string convert(NSObject* nsObject) {
|
||||||
|
return ::Catch::Detail::stringify([nsObject description]);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
namespace Detail {
|
||||||
|
inline std::string stringify( NSString* nsstring ) {
|
||||||
|
return StringMaker<NSString*>::convert( nsstring );
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Detail
|
||||||
|
#endif // __OBJC__
|
||||||
|
|
||||||
|
} // namespace Catch
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////
|
||||||
|
// Separate std-lib types stringification, so it can be selectively enabled
|
||||||
|
// This means that we do not bring in
|
||||||
|
|
||||||
|
#if defined(CATCH_CONFIG_ENABLE_ALL_STRINGMAKERS)
|
||||||
|
# define CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER
|
||||||
|
# define CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER
|
||||||
|
# define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Separate std::pair specialization
|
||||||
|
#if defined(CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER)
|
||||||
|
#include <utility>
|
||||||
|
namespace Catch {
|
||||||
template<typename T1, typename T2>
|
template<typename T1, typename T2>
|
||||||
struct StringMaker<std::pair<T1, T2> > {
|
struct StringMaker<std::pair<T1, T2> > {
|
||||||
static std::string convert(const std::pair<T1, T2>& pair) {
|
static std::string convert(const std::pair<T1, T2>& pair) {
|
||||||
@ -254,9 +299,13 @@ namespace Catch {
|
|||||||
return oss.str();
|
return oss.str();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
#endif // CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER
|
||||||
|
|
||||||
|
// Separate std::tuple specialization
|
||||||
|
#if defined(CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER)
|
||||||
|
#include <tuple>
|
||||||
|
namespace Catch {
|
||||||
namespace Detail {
|
namespace Detail {
|
||||||
template<
|
template<
|
||||||
typename Tuple,
|
typename Tuple,
|
||||||
@ -292,40 +341,126 @@ namespace Catch {
|
|||||||
return os.str();
|
return os.str();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
#endif // CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER
|
||||||
|
|
||||||
|
|
||||||
template<typename T>
|
// Separate std::chrono::duration specialization
|
||||||
struct EnumStringMaker {
|
#if defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER)
|
||||||
static std::string convert(const T& t) {
|
#include <chrono>
|
||||||
return ::Catch::Detail::stringify(static_cast<typename std::underlying_type<T>::type>(t));
|
|
||||||
|
#include <ratio>
|
||||||
|
|
||||||
|
template <class Ratio>
|
||||||
|
struct ratio_string {
|
||||||
|
static std::string symbol();
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class Ratio>
|
||||||
|
std::string ratio_string<Ratio>::symbol() {
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << '[' << Ratio::num << '/'
|
||||||
|
<< Ratio::den << ']';
|
||||||
|
return oss.str();
|
||||||
|
}
|
||||||
|
template <>
|
||||||
|
struct ratio_string<std::atto> {
|
||||||
|
static std::string symbol() { return "a"; }
|
||||||
|
};
|
||||||
|
template <>
|
||||||
|
struct ratio_string<std::femto> {
|
||||||
|
static std::string symbol() { return "f"; }
|
||||||
|
};
|
||||||
|
template <>
|
||||||
|
struct ratio_string<std::pico> {
|
||||||
|
static std::string symbol() { return "p"; }
|
||||||
|
};
|
||||||
|
template <>
|
||||||
|
struct ratio_string<std::nano> {
|
||||||
|
static std::string symbol() { return "n"; }
|
||||||
|
};
|
||||||
|
template <>
|
||||||
|
struct ratio_string<std::micro> {
|
||||||
|
static std::string symbol() { return "u"; }
|
||||||
|
};
|
||||||
|
template <>
|
||||||
|
struct ratio_string<std::milli> {
|
||||||
|
static std::string symbol() { return "m"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace Catch {
|
||||||
|
////////////
|
||||||
|
// std::chrono::duration specializations
|
||||||
|
template<typename Value, typename Ratio>
|
||||||
|
struct StringMaker<std::chrono::duration<Value, Ratio>> {
|
||||||
|
static std::string convert(std::chrono::duration<Value, Ratio> const& duration) {
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << duration.count() << ' ' << ratio_string<Ratio>::symbol() << 's';
|
||||||
|
return oss.str();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
template<typename Value>
|
||||||
|
struct StringMaker<std::chrono::duration<Value, std::ratio<1>>> {
|
||||||
|
static std::string convert(std::chrono::duration<Value, std::ratio<1>> const& duration) {
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << duration.count() << " s";
|
||||||
|
return oss.str();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
template<typename Value>
|
||||||
|
struct StringMaker<std::chrono::duration<Value, std::ratio<60>>> {
|
||||||
|
static std::string convert(std::chrono::duration<Value, std::ratio<60>> const& duration) {
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << duration.count() << " m";
|
||||||
|
return oss.str();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
template<typename Value>
|
||||||
|
struct StringMaker<std::chrono::duration<Value, std::ratio<3600>>> {
|
||||||
|
static std::string convert(std::chrono::duration<Value, std::ratio<3600>> const& duration) {
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << duration.count() << " h";
|
||||||
|
return oss.str();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef __OBJC__
|
////////////
|
||||||
template<>
|
// std::chrono::time_point specialization
|
||||||
struct StringMaker<NSString*> {
|
// Generic time_point cannot be specialized, only std::chrono::time_point<system_clock>
|
||||||
static std::string convert(NSString * nsstring) {
|
template<typename Clock, typename Duration>
|
||||||
if (!nsstring)
|
struct StringMaker<std::chrono::time_point<Clock, Duration>> {
|
||||||
return "nil";
|
static std::string convert(std::chrono::time_point<Clock, Duration> const& time_point) {
|
||||||
return std::string("@") + [nsstring UTF8String];
|
return ::Catch::Detail::stringify(time_point.time_since_epoch()) + " since epoch";
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
template<>
|
// std::chrono::time_point<system_clock> specialization
|
||||||
struct StringMaker<NSObject*> {
|
template<typename Duration>
|
||||||
static std::string convert(NSObject* nsObject) {
|
struct StringMaker<std::chrono::time_point<std::chrono::system_clock, Duration>> {
|
||||||
return ::Catch::Detail::stringify([nsObject description]);
|
static std::string convert(std::chrono::time_point<std::chrono::system_clock, Duration> const& time_point) {
|
||||||
}
|
auto converted = std::chrono::system_clock::to_time_t(time_point);
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
std::tm timeInfo = {};
|
||||||
|
gmtime_s(&timeInfo, &converted);
|
||||||
|
#else
|
||||||
|
std::tm* timeInfo = std::gmtime(&converted);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
auto const timeStampSize = sizeof("2017-01-16T17:06:45Z");
|
||||||
|
char timeStamp[timeStampSize];
|
||||||
|
const char * const fmt = "%Y-%m-%dT%H:%M:%SZ";
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
std::strftime(timeStamp, timeStampSize, fmt, &timeInfo);
|
||||||
|
#else
|
||||||
|
std::strftime(timeStamp, timeStampSize, fmt, timeInfo);
|
||||||
|
#endif
|
||||||
|
return std::string(timeStamp);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
namespace Detail {
|
}
|
||||||
inline std::string stringify( NSString* nsstring ) {
|
#endif // CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER
|
||||||
return StringMaker<NSString*>::convert( nsstring );
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Detail
|
|
||||||
#endif // __OBJC__
|
|
||||||
|
|
||||||
} // namespace Catch
|
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
|
@ -1003,6 +1003,6 @@ with expansion:
|
|||||||
"{?}" == "1"
|
"{?}" == "1"
|
||||||
|
|
||||||
===============================================================================
|
===============================================================================
|
||||||
test cases: 176 | 125 passed | 47 failed | 4 failed as expected
|
test cases: 180 | 129 passed | 47 failed | 4 failed as expected
|
||||||
assertions: 878 | 761 passed | 96 failed | 21 failed as expected
|
assertions: 886 | 769 passed | 96 failed | 21 failed as expected
|
||||||
|
|
||||||
|
@ -4613,6 +4613,84 @@ PASSED:
|
|||||||
with expansion:
|
with expansion:
|
||||||
11 == 11
|
11 == 11
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Stringifying std::chrono::duration helpers
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
ToStringChrono.cpp:<line number>
|
||||||
|
...............................................................................
|
||||||
|
|
||||||
|
ToStringChrono.cpp:<line number>:
|
||||||
|
PASSED:
|
||||||
|
REQUIRE( minute == seconds )
|
||||||
|
with expansion:
|
||||||
|
1 m == 60 s
|
||||||
|
|
||||||
|
ToStringChrono.cpp:<line number>:
|
||||||
|
PASSED:
|
||||||
|
REQUIRE( hour != seconds )
|
||||||
|
with expansion:
|
||||||
|
1 h != 60 s
|
||||||
|
|
||||||
|
ToStringChrono.cpp:<line number>:
|
||||||
|
PASSED:
|
||||||
|
REQUIRE( micro != milli )
|
||||||
|
with expansion:
|
||||||
|
1 us != 1 ms
|
||||||
|
|
||||||
|
ToStringChrono.cpp:<line number>:
|
||||||
|
PASSED:
|
||||||
|
REQUIRE( nano != micro )
|
||||||
|
with expansion:
|
||||||
|
1 ns != 1 us
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Stringifying std::chrono::duration with weird ratios
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
ToStringChrono.cpp:<line number>
|
||||||
|
...............................................................................
|
||||||
|
|
||||||
|
ToStringChrono.cpp:<line number>:
|
||||||
|
PASSED:
|
||||||
|
REQUIRE( half_minute != femto_second )
|
||||||
|
with expansion:
|
||||||
|
1 [30/1]s != 1 fs
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Stringifying std::chrono::time_point<Clock>
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
ToStringChrono.cpp:<line number>
|
||||||
|
...............................................................................
|
||||||
|
|
||||||
|
ToStringChrono.cpp:<line number>:
|
||||||
|
PASSED:
|
||||||
|
REQUIRE( now != later )
|
||||||
|
with expansion:
|
||||||
|
{iso8601-timestamp}
|
||||||
|
!=
|
||||||
|
{iso8601-timestamp}
|
||||||
|
|
||||||
|
ToStringChrono.cpp:<line number>:
|
||||||
|
PASSED:
|
||||||
|
REQUIRE( now2 != later2 )
|
||||||
|
with expansion:
|
||||||
|
{since-epoch-report}
|
||||||
|
!=
|
||||||
|
{since-epoch-report}
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Stringifying std::chrono::time_point<system_clock>
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
ToStringChrono.cpp:<line number>
|
||||||
|
...............................................................................
|
||||||
|
|
||||||
|
ToStringChrono.cpp:<line number>:
|
||||||
|
PASSED:
|
||||||
|
REQUIRE( now != later )
|
||||||
|
with expansion:
|
||||||
|
{iso8601-timestamp}
|
||||||
|
!=
|
||||||
|
{iso8601-timestamp}
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Tabs and newlines show in output
|
Tabs and newlines show in output
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
@ -7434,6 +7512,6 @@ MiscTests.cpp:<line number>:
|
|||||||
PASSED:
|
PASSED:
|
||||||
|
|
||||||
===============================================================================
|
===============================================================================
|
||||||
test cases: 176 | 123 passed | 49 failed | 4 failed as expected
|
test cases: 180 | 127 passed | 49 failed | 4 failed as expected
|
||||||
assertions: 877 | 757 passed | 99 failed | 21 failed as expected
|
assertions: 885 | 765 passed | 99 failed | 21 failed as expected
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<testsuitesloose text artifact
|
<testsuitesloose text artifact
|
||||||
>
|
>
|
||||||
<testsuite name="<exe-name>" errors="15" failures="85" tests="878" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
|
<testsuite name="<exe-name>" errors="15" failures="85" tests="886" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
|
||||||
<testcase classname="<exe-name>.global" name="# A test name that starts with a #" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="# A test name that starts with a #" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="#1005: Comparing pointer to int and long (NULL can be either on various systems)" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="#1005: Comparing pointer to int and long (NULL can be either on various systems)" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="#748 - captures with unexpected exceptions/outside assertions" time="{duration}">
|
<testcase classname="<exe-name>.global" name="#748 - captures with unexpected exceptions/outside assertions" time="{duration}">
|
||||||
@ -519,6 +519,10 @@ StringRef.tests.cpp:<line number>
|
|||||||
<testcase classname="<exe-name>.global" name="StringRef/to std::string/implicitly constructed" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="StringRef/to std::string/implicitly constructed" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="StringRef/to std::string/explicitly constructed" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="StringRef/to std::string/explicitly constructed" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="StringRef/to std::string/assigned" time="{duration}"/>
|
<testcase classname="<exe-name>.global" name="StringRef/to std::string/assigned" time="{duration}"/>
|
||||||
|
<testcase classname="<exe-name>.global" name="Stringifying std::chrono::duration helpers" time="{duration}"/>
|
||||||
|
<testcase classname="<exe-name>.global" name="Stringifying std::chrono::duration with weird ratios" time="{duration}"/>
|
||||||
|
<testcase classname="<exe-name>.global" name="Stringifying std::chrono::time_point<Clock>" time="{duration}"/>
|
||||||
|
<testcase classname="<exe-name>.global" name="Stringifying std::chrono::time_point<system_clock>" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="Tabs and newlines show in output" time="{duration}">
|
<testcase classname="<exe-name>.global" name="Tabs and newlines show in output" time="{duration}">
|
||||||
<failure message=""if ($b == 10) {
|
<failure message=""if ($b == 10) {
|
||||||
$a = 20;
|
$a = 20;
|
||||||
|
@ -5250,6 +5250,88 @@ Message from section two
|
|||||||
</Section>
|
</Section>
|
||||||
<OverallResult success="false"/>
|
<OverallResult success="false"/>
|
||||||
</TestCase>
|
</TestCase>
|
||||||
|
<TestCase name="Stringifying std::chrono::duration helpers" tags="[chrono][toString]" filename="projects/<exe-name>/ToStringChrono.cpp" >
|
||||||
|
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/ToStringChrono.cpp" >
|
||||||
|
<Original>
|
||||||
|
minute == seconds
|
||||||
|
</Original>
|
||||||
|
<Expanded>
|
||||||
|
1 m == 60 s
|
||||||
|
</Expanded>
|
||||||
|
</Expression>
|
||||||
|
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/ToStringChrono.cpp" >
|
||||||
|
<Original>
|
||||||
|
hour != seconds
|
||||||
|
</Original>
|
||||||
|
<Expanded>
|
||||||
|
1 h != 60 s
|
||||||
|
</Expanded>
|
||||||
|
</Expression>
|
||||||
|
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/ToStringChrono.cpp" >
|
||||||
|
<Original>
|
||||||
|
micro != milli
|
||||||
|
</Original>
|
||||||
|
<Expanded>
|
||||||
|
1 us != 1 ms
|
||||||
|
</Expanded>
|
||||||
|
</Expression>
|
||||||
|
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/ToStringChrono.cpp" >
|
||||||
|
<Original>
|
||||||
|
nano != micro
|
||||||
|
</Original>
|
||||||
|
<Expanded>
|
||||||
|
1 ns != 1 us
|
||||||
|
</Expanded>
|
||||||
|
</Expression>
|
||||||
|
<OverallResult success="true"/>
|
||||||
|
</TestCase>
|
||||||
|
<TestCase name="Stringifying std::chrono::duration with weird ratios" tags="[chrono][toString]" filename="projects/<exe-name>/ToStringChrono.cpp" >
|
||||||
|
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/ToStringChrono.cpp" >
|
||||||
|
<Original>
|
||||||
|
half_minute != femto_second
|
||||||
|
</Original>
|
||||||
|
<Expanded>
|
||||||
|
1 [30/1]s != 1 fs
|
||||||
|
</Expanded>
|
||||||
|
</Expression>
|
||||||
|
<OverallResult success="true"/>
|
||||||
|
</TestCase>
|
||||||
|
<TestCase name="Stringifying std::chrono::time_point<Clock>" tags="[chrono][toString]" filename="projects/<exe-name>/ToStringChrono.cpp" >
|
||||||
|
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/ToStringChrono.cpp" >
|
||||||
|
<Original>
|
||||||
|
now != later
|
||||||
|
</Original>
|
||||||
|
<Expanded>
|
||||||
|
{iso8601-timestamp}
|
||||||
|
!=
|
||||||
|
{iso8601-timestamp}
|
||||||
|
</Expanded>
|
||||||
|
</Expression>
|
||||||
|
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/ToStringChrono.cpp" >
|
||||||
|
<Original>
|
||||||
|
now2 != later2
|
||||||
|
</Original>
|
||||||
|
<Expanded>
|
||||||
|
{since-epoch-report}
|
||||||
|
!=
|
||||||
|
{since-epoch-report}
|
||||||
|
</Expanded>
|
||||||
|
</Expression>
|
||||||
|
<OverallResult success="true"/>
|
||||||
|
</TestCase>
|
||||||
|
<TestCase name="Stringifying std::chrono::time_point<system_clock>" tags="[chrono][toString]" filename="projects/<exe-name>/ToStringChrono.cpp" >
|
||||||
|
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/ToStringChrono.cpp" >
|
||||||
|
<Original>
|
||||||
|
now != later
|
||||||
|
</Original>
|
||||||
|
<Expanded>
|
||||||
|
{iso8601-timestamp}
|
||||||
|
!=
|
||||||
|
{iso8601-timestamp}
|
||||||
|
</Expanded>
|
||||||
|
</Expression>
|
||||||
|
<OverallResult success="true"/>
|
||||||
|
</TestCase>
|
||||||
<TestCase name="Tabs and newlines show in output" tags="[.][failing][whitespace]" filename="projects/<exe-name>/MiscTests.cpp" >
|
<TestCase name="Tabs and newlines show in output" tags="[.][failing][whitespace]" filename="projects/<exe-name>/MiscTests.cpp" >
|
||||||
<Expression success="false" type="CHECK" filename="projects/<exe-name>/MiscTests.cpp" >
|
<Expression success="false" type="CHECK" filename="projects/<exe-name>/MiscTests.cpp" >
|
||||||
<Original>
|
<Original>
|
||||||
@ -8209,7 +8291,7 @@ loose text artifact
|
|||||||
</Section>
|
</Section>
|
||||||
<OverallResult success="true"/>
|
<OverallResult success="true"/>
|
||||||
</TestCase>
|
</TestCase>
|
||||||
<OverallResults successes="757" failures="100" expectedFailures="21"/>
|
<OverallResults successes="765" failures="100" expectedFailures="21"/>
|
||||||
</Group>
|
</Group>
|
||||||
<OverallResults successes="757" failures="99" expectedFailures="21"/>
|
<OverallResults successes="765" failures="99" expectedFailures="21"/>
|
||||||
</Catch>
|
</Catch>
|
||||||
|
41
projects/SelfTest/ToStringChrono.cpp
Normal file
41
projects/SelfTest/ToStringChrono.cpp
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
#define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER
|
||||||
|
#include "catch.hpp"
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
TEST_CASE("Stringifying std::chrono::duration helpers", "[toString][chrono]") {
|
||||||
|
// No literals because we still support c++11
|
||||||
|
auto hour = std::chrono::hours(1);
|
||||||
|
auto minute = std::chrono::minutes(1);
|
||||||
|
auto seconds = std::chrono::seconds(60);
|
||||||
|
auto micro = std::chrono::microseconds(1);
|
||||||
|
auto milli = std::chrono::milliseconds(1);
|
||||||
|
auto nano = std::chrono::nanoseconds(1);
|
||||||
|
REQUIRE(minute == seconds);
|
||||||
|
REQUIRE(hour != seconds);
|
||||||
|
REQUIRE(micro != milli);
|
||||||
|
REQUIRE(nano != micro);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Stringifying std::chrono::duration with weird ratios", "[toString][chrono]") {
|
||||||
|
std::chrono::duration<int64_t, std::ratio<30>> half_minute(1);
|
||||||
|
std::chrono::duration<int64_t, std::ratio<1, 1000000000000000>> femto_second(1);
|
||||||
|
REQUIRE(half_minute != femto_second);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Stringifying std::chrono::time_point<system_clock>", "[toString][chrono]") {
|
||||||
|
auto now = std::chrono::system_clock::now();
|
||||||
|
auto later = now + std::chrono::minutes(2);
|
||||||
|
REQUIRE(now != later);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Stringifying std::chrono::time_point<Clock>", "[toString][chrono]") {
|
||||||
|
auto now = std::chrono::high_resolution_clock::now();
|
||||||
|
auto later = now + std::chrono::minutes(2);
|
||||||
|
REQUIRE(now != later);
|
||||||
|
|
||||||
|
auto now2 = std::chrono::steady_clock::now();
|
||||||
|
auto later2 = now2 + std::chrono::minutes(2);
|
||||||
|
REQUIRE(now2 != later2);
|
||||||
|
}
|
@ -1,3 +1,4 @@
|
|||||||
|
#define CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER
|
||||||
#include "catch.hpp"
|
#include "catch.hpp"
|
||||||
|
|
||||||
TEST_CASE( "std::pair<int,std::string> -> toString", "[toString][pair]" ) {
|
TEST_CASE( "std::pair<int,std::string> -> toString", "[toString][pair]" ) {
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
#define CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER
|
||||||
#include "catch.hpp"
|
#include "catch.hpp"
|
||||||
|
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
|
@ -24,7 +24,7 @@ filelocParser = re.compile(r'''
|
|||||||
lineNumberParser = re.compile(r' line="[0-9]*"')
|
lineNumberParser = re.compile(r' line="[0-9]*"')
|
||||||
hexParser = re.compile(r'\b(0[xX][0-9a-fA-F]+)\b')
|
hexParser = re.compile(r'\b(0[xX][0-9a-fA-F]+)\b')
|
||||||
durationsParser = re.compile(r' time="[0-9]*\.[0-9]*"')
|
durationsParser = re.compile(r' time="[0-9]*\.[0-9]*"')
|
||||||
timestampsParser = re.compile(r' timestamp="\d{4}-\d{2}-\d{2}T\d{2}\:\d{2}\:\d{2}Z"')
|
timestampsParser = re.compile(r'\d{4}-\d{2}-\d{2}T\d{2}\:\d{2}\:\d{2}Z')
|
||||||
versionParser = re.compile(r'Catch v[0-9]+\.[0-9]+\.[0-9]+(-develop\.[0-9]+)?')
|
versionParser = re.compile(r'Catch v[0-9]+\.[0-9]+\.[0-9]+(-develop\.[0-9]+)?')
|
||||||
nullParser = re.compile(r'\b(__null|nullptr)\b')
|
nullParser = re.compile(r'\b(__null|nullptr)\b')
|
||||||
exeNameParser = re.compile(r'''
|
exeNameParser = re.compile(r'''
|
||||||
@ -44,6 +44,7 @@ errnoParser = re.compile(r'''
|
|||||||
|
|
|
|
||||||
\(\*_errno\(\)\)
|
\(\*_errno\(\)\)
|
||||||
''', re.VERBOSE)
|
''', re.VERBOSE)
|
||||||
|
sinceEpochParser = re.compile(r'\d+ .+ since epoch')
|
||||||
|
|
||||||
if len(sys.argv) == 2:
|
if len(sys.argv) == 2:
|
||||||
cmdPath = sys.argv[1]
|
cmdPath = sys.argv[1]
|
||||||
@ -97,9 +98,10 @@ def filterLine(line):
|
|||||||
|
|
||||||
# strip durations and timestamps
|
# strip durations and timestamps
|
||||||
line = durationsParser.sub(' time="{duration}"', line)
|
line = durationsParser.sub(' time="{duration}"', line)
|
||||||
line = timestampsParser.sub(' timestamp="{iso8601-timestamp}"', line)
|
line = timestampsParser.sub('{iso8601-timestamp}', line)
|
||||||
line = specialCaseParser.sub('file:\g<1>', line)
|
line = specialCaseParser.sub('file:\g<1>', line)
|
||||||
line = errnoParser.sub('errno', line)
|
line = errnoParser.sub('errno', line)
|
||||||
|
line = sinceEpochParser.sub('{since-epoch-report}', line)
|
||||||
return line
|
return line
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user