mirror of
https://github.com/catchorg/Catch2.git
synced 2024-11-22 05:16:10 +01:00
v3.6.0
This commit is contained in:
parent
8ce2426e53
commit
4e8d92bf02
@ -33,7 +33,7 @@ if (CMAKE_BINARY_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
project(Catch2
|
project(Catch2
|
||||||
VERSION 3.5.4 # CML version placeholder, don't delete
|
VERSION 3.6.0 # CML version placeholder, don't delete
|
||||||
LANGUAGES CXX
|
LANGUAGES CXX
|
||||||
# HOMEPAGE_URL is not supported until CMake version 3.12, which
|
# HOMEPAGE_URL is not supported until CMake version 3.12, which
|
||||||
# we do not target yet.
|
# we do not target yet.
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
# Release notes
|
# Release notes
|
||||||
**Contents**<br>
|
**Contents**<br>
|
||||||
|
[3.6.0](#360)<br>
|
||||||
[3.5.4](#354)<br>
|
[3.5.4](#354)<br>
|
||||||
[3.5.3](#353)<br>
|
[3.5.3](#353)<br>
|
||||||
[3.5.2](#352)<br>
|
[3.5.2](#352)<br>
|
||||||
@ -62,6 +63,31 @@
|
|||||||
[Even Older versions](#even-older-versions)<br>
|
[Even Older versions](#even-older-versions)<br>
|
||||||
|
|
||||||
|
|
||||||
|
## 3.6.0
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
* Fixed Windows ARM64 build by fixing the preprocessor condition guarding use `_umul128` intrinsic.
|
||||||
|
* Fixed Windows ARM64EC build by removing intrinsic pragma it does not understand. (#2858)
|
||||||
|
* Why doesn't the x64-emulation build mode understand x64 pragmas? Don't ask me, ask the MSVC guys.
|
||||||
|
* Fixed the JUnit reporter sometimes crashing when reporting a fatal error. (#1210, #2855)
|
||||||
|
* The binary will still exit, but through the original error, rather than secondary error inside the reporter.
|
||||||
|
* The underlying fix applies to all reporters, not just the JUnit one, but only JUnit was currently causing troubles.
|
||||||
|
|
||||||
|
### Improvements
|
||||||
|
* Disable `-Wnon-virtual-dtor` in Decomposer and Matchers (#2854)
|
||||||
|
* `precision` in floating point stringmakers defaults to `max_digits10`.
|
||||||
|
* This means that floating point values will be printed with enough precision to disambiguate any two floats.
|
||||||
|
* Column wrapping ignores ansi colour codes when calculating string width (#2833, #2849)
|
||||||
|
* This makes the output much more readable when the provided messages contain colour codes.
|
||||||
|
|
||||||
|
### Miscellaneous
|
||||||
|
* Conan support improvements
|
||||||
|
* `compatibility_cppstr` is set to False. (#2860)
|
||||||
|
* This means that Conan won't let you mix library and project with different C++ standard settings.
|
||||||
|
* The implementation library CMake target name through Conan is properly set to `Catch2::Catch2` (#2861)
|
||||||
|
* `SelfTest` target can be built through Bazel (#2857)
|
||||||
|
|
||||||
|
|
||||||
## 3.5.4
|
## 3.5.4
|
||||||
|
|
||||||
### Fixes
|
### Fixes
|
||||||
|
@ -6,8 +6,8 @@
|
|||||||
|
|
||||||
// SPDX-License-Identifier: BSL-1.0
|
// SPDX-License-Identifier: BSL-1.0
|
||||||
|
|
||||||
// Catch v3.5.4
|
// Catch v3.6.0
|
||||||
// Generated: 2024-04-10 12:03:46.281848
|
// Generated: 2024-05-05 20:53:27.562886
|
||||||
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
||||||
// This file is an amalgamation of multiple different files.
|
// This file is an amalgamation of multiple different files.
|
||||||
// You probably shouldn't edit it directly.
|
// You probably shouldn't edit it directly.
|
||||||
@ -2156,13 +2156,13 @@ std::string StringMaker<unsigned char>::convert(unsigned char value) {
|
|||||||
return ::Catch::Detail::stringify(static_cast<char>(value));
|
return ::Catch::Detail::stringify(static_cast<char>(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
int StringMaker<float>::precision = 5;
|
int StringMaker<float>::precision = std::numeric_limits<float>::max_digits10;
|
||||||
|
|
||||||
std::string StringMaker<float>::convert(float value) {
|
std::string StringMaker<float>::convert(float value) {
|
||||||
return Detail::fpToString(value, precision) + 'f';
|
return Detail::fpToString(value, precision) + 'f';
|
||||||
}
|
}
|
||||||
|
|
||||||
int StringMaker<double>::precision = 10;
|
int StringMaker<double>::precision = std::numeric_limits<double>::max_digits10;
|
||||||
|
|
||||||
std::string StringMaker<double>::convert(double value) {
|
std::string StringMaker<double>::convert(double value) {
|
||||||
return Detail::fpToString(value, precision);
|
return Detail::fpToString(value, precision);
|
||||||
@ -2273,7 +2273,7 @@ namespace Catch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Version const& libraryVersion() {
|
Version const& libraryVersion() {
|
||||||
static Version version( 3, 5, 4, "", 0 );
|
static Version version( 3, 6, 0, "", 0 );
|
||||||
return version;
|
return version;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5853,6 +5853,13 @@ namespace Catch {
|
|||||||
assertionEnded(CATCH_MOVE(result) );
|
assertionEnded(CATCH_MOVE(result) );
|
||||||
resetAssertionInfo();
|
resetAssertionInfo();
|
||||||
|
|
||||||
|
// Best effort cleanup for sections that have not been destructed yet
|
||||||
|
// Since this is a fatal error, we have not had and won't have the opportunity to destruct them properly
|
||||||
|
while (!m_activeSections.empty()) {
|
||||||
|
auto nl = m_activeSections.back()->nameAndLocation();
|
||||||
|
SectionEndInfo endInfo{ SectionInfo(CATCH_MOVE(nl.location), CATCH_MOVE(nl.name)), {}, 0.0 };
|
||||||
|
sectionEndedEarly(CATCH_MOVE(endInfo));
|
||||||
|
}
|
||||||
handleUnfinishedSections();
|
handleUnfinishedSections();
|
||||||
|
|
||||||
// Recreate section for test case (as we will lose the one that was in scope)
|
// Recreate section for test case (as we will lose the one that was in scope)
|
||||||
@ -7207,117 +7214,228 @@ namespace {
|
|||||||
return std::memchr( chars, c, sizeof( chars ) - 1 ) != nullptr;
|
return std::memchr( chars, c, sizeof( chars ) - 1 ) != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isBoundary( std::string const& line, size_t at ) {
|
|
||||||
assert( at > 0 );
|
|
||||||
assert( at <= line.size() );
|
|
||||||
|
|
||||||
return at == line.size() ||
|
|
||||||
( isWhitespace( line[at] ) && !isWhitespace( line[at - 1] ) ) ||
|
|
||||||
isBreakableBefore( line[at] ) ||
|
|
||||||
isBreakableAfter( line[at - 1] );
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
namespace TextFlow {
|
namespace TextFlow {
|
||||||
|
void AnsiSkippingString::preprocessString() {
|
||||||
|
for ( auto it = m_string.begin(); it != m_string.end(); ) {
|
||||||
|
// try to read through an ansi sequence
|
||||||
|
while ( it != m_string.end() && *it == '\033' &&
|
||||||
|
it + 1 != m_string.end() && *( it + 1 ) == '[' ) {
|
||||||
|
auto cursor = it + 2;
|
||||||
|
while ( cursor != m_string.end() &&
|
||||||
|
( isdigit( *cursor ) || *cursor == ';' ) ) {
|
||||||
|
++cursor;
|
||||||
|
}
|
||||||
|
if ( cursor == m_string.end() || *cursor != 'm' ) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// 'm' -> 0xff
|
||||||
|
*cursor = AnsiSkippingString::sentinel;
|
||||||
|
// if we've read an ansi sequence, set the iterator and
|
||||||
|
// return to the top of the loop
|
||||||
|
it = cursor + 1;
|
||||||
|
}
|
||||||
|
if ( it != m_string.end() ) {
|
||||||
|
++m_size;
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AnsiSkippingString::AnsiSkippingString( std::string const& text ):
|
||||||
|
m_string( text ) {
|
||||||
|
preprocessString();
|
||||||
|
}
|
||||||
|
|
||||||
|
AnsiSkippingString::AnsiSkippingString( std::string&& text ):
|
||||||
|
m_string( CATCH_MOVE( text ) ) {
|
||||||
|
preprocessString();
|
||||||
|
}
|
||||||
|
|
||||||
|
AnsiSkippingString::const_iterator AnsiSkippingString::begin() const {
|
||||||
|
return const_iterator( m_string );
|
||||||
|
}
|
||||||
|
|
||||||
|
AnsiSkippingString::const_iterator AnsiSkippingString::end() const {
|
||||||
|
return const_iterator( m_string, const_iterator::EndTag{} );
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string AnsiSkippingString::substring( const_iterator begin,
|
||||||
|
const_iterator end ) const {
|
||||||
|
// There's one caveat here to an otherwise simple substring: when
|
||||||
|
// making a begin iterator we might have skipped ansi sequences at
|
||||||
|
// the start. If `begin` here is a begin iterator, skipped over
|
||||||
|
// initial ansi sequences, we'll use the true beginning of the
|
||||||
|
// string. Lastly: We need to transform any chars we replaced with
|
||||||
|
// 0xff back to 'm'
|
||||||
|
auto str = std::string( begin == this->begin() ? m_string.begin()
|
||||||
|
: begin.m_it,
|
||||||
|
end.m_it );
|
||||||
|
std::transform( str.begin(), str.end(), str.begin(), []( char c ) {
|
||||||
|
return c == AnsiSkippingString::sentinel ? 'm' : c;
|
||||||
|
} );
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AnsiSkippingString::const_iterator::tryParseAnsiEscapes() {
|
||||||
|
// check if we've landed on an ansi sequence, and if so read through
|
||||||
|
// it
|
||||||
|
while ( m_it != m_string->end() && *m_it == '\033' &&
|
||||||
|
m_it + 1 != m_string->end() && *( m_it + 1 ) == '[' ) {
|
||||||
|
auto cursor = m_it + 2;
|
||||||
|
while ( cursor != m_string->end() &&
|
||||||
|
( isdigit( *cursor ) || *cursor == ';' ) ) {
|
||||||
|
++cursor;
|
||||||
|
}
|
||||||
|
if ( cursor == m_string->end() ||
|
||||||
|
*cursor != AnsiSkippingString::sentinel ) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// if we've read an ansi sequence, set the iterator and
|
||||||
|
// return to the top of the loop
|
||||||
|
m_it = cursor + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AnsiSkippingString::const_iterator::advance() {
|
||||||
|
assert( m_it != m_string->end() );
|
||||||
|
m_it++;
|
||||||
|
tryParseAnsiEscapes();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AnsiSkippingString::const_iterator::unadvance() {
|
||||||
|
assert( m_it != m_string->begin() );
|
||||||
|
m_it--;
|
||||||
|
// if *m_it is 0xff, scan back to the \033 and then m_it-- once more
|
||||||
|
// (and repeat check)
|
||||||
|
while ( *m_it == AnsiSkippingString::sentinel ) {
|
||||||
|
while ( *m_it != '\033' ) {
|
||||||
|
assert( m_it != m_string->begin() );
|
||||||
|
m_it--;
|
||||||
|
}
|
||||||
|
// if this happens, we must have been a begin iterator that had
|
||||||
|
// skipped over ansi sequences at the start of a string
|
||||||
|
assert( m_it != m_string->begin() );
|
||||||
|
assert( *m_it == '\033' );
|
||||||
|
m_it--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool isBoundary( AnsiSkippingString const& line,
|
||||||
|
AnsiSkippingString::const_iterator it ) {
|
||||||
|
return it == line.end() ||
|
||||||
|
( isWhitespace( *it ) &&
|
||||||
|
!isWhitespace( *it.oneBefore() ) ) ||
|
||||||
|
isBreakableBefore( *it ) ||
|
||||||
|
isBreakableAfter( *it.oneBefore() );
|
||||||
|
}
|
||||||
|
|
||||||
void Column::const_iterator::calcLength() {
|
void Column::const_iterator::calcLength() {
|
||||||
m_addHyphen = false;
|
m_addHyphen = false;
|
||||||
m_parsedTo = m_lineStart;
|
m_parsedTo = m_lineStart;
|
||||||
|
AnsiSkippingString const& current_line = m_column.m_string;
|
||||||
|
|
||||||
std::string const& current_line = m_column.m_string;
|
if ( m_parsedTo == current_line.end() ) {
|
||||||
if ( current_line[m_lineStart] == '\n' ) {
|
m_lineEnd = m_parsedTo;
|
||||||
++m_parsedTo;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assert( m_lineStart != current_line.end() );
|
||||||
|
if ( *m_lineStart == '\n' ) { ++m_parsedTo; }
|
||||||
|
|
||||||
const auto maxLineLength = m_column.m_width - indentSize();
|
const auto maxLineLength = m_column.m_width - indentSize();
|
||||||
const auto maxParseTo = std::min(current_line.size(), m_lineStart + maxLineLength);
|
std::size_t lineLength = 0;
|
||||||
while ( m_parsedTo < maxParseTo &&
|
while ( m_parsedTo != current_line.end() &&
|
||||||
current_line[m_parsedTo] != '\n' ) {
|
lineLength < maxLineLength && *m_parsedTo != '\n' ) {
|
||||||
++m_parsedTo;
|
++m_parsedTo;
|
||||||
|
++lineLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we encountered a newline before the column is filled,
|
// If we encountered a newline before the column is filled,
|
||||||
// then we linebreak at the newline and consider this line
|
// then we linebreak at the newline and consider this line
|
||||||
// finished.
|
// finished.
|
||||||
if ( m_parsedTo < m_lineStart + maxLineLength ) {
|
if ( lineLength < maxLineLength ) {
|
||||||
m_lineLength = m_parsedTo - m_lineStart;
|
m_lineEnd = m_parsedTo;
|
||||||
} else {
|
} else {
|
||||||
// Look for a natural linebreak boundary in the column
|
// Look for a natural linebreak boundary in the column
|
||||||
// (We look from the end, so that the first found boundary is
|
// (We look from the end, so that the first found boundary is
|
||||||
// the right one)
|
// the right one)
|
||||||
size_t newLineLength = maxLineLength;
|
m_lineEnd = m_parsedTo;
|
||||||
while ( newLineLength > 0 && !isBoundary( current_line, m_lineStart + newLineLength ) ) {
|
while ( lineLength > 0 &&
|
||||||
--newLineLength;
|
!isBoundary( current_line, m_lineEnd ) ) {
|
||||||
|
--lineLength;
|
||||||
|
--m_lineEnd;
|
||||||
}
|
}
|
||||||
while ( newLineLength > 0 &&
|
while ( lineLength > 0 &&
|
||||||
isWhitespace( current_line[m_lineStart + newLineLength - 1] ) ) {
|
isWhitespace( *m_lineEnd.oneBefore() ) ) {
|
||||||
--newLineLength;
|
--lineLength;
|
||||||
|
--m_lineEnd;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we found one, then that is where we linebreak
|
// If we found one, then that is where we linebreak, otherwise
|
||||||
if ( newLineLength > 0 ) {
|
// we have to split text with a hyphen
|
||||||
m_lineLength = newLineLength;
|
if ( lineLength == 0 ) {
|
||||||
} else {
|
|
||||||
// Otherwise we have to split text with a hyphen
|
|
||||||
m_addHyphen = true;
|
m_addHyphen = true;
|
||||||
m_lineLength = maxLineLength - 1;
|
m_lineEnd = m_parsedTo.oneBefore();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Column::const_iterator::indentSize() const {
|
size_t Column::const_iterator::indentSize() const {
|
||||||
auto initial =
|
auto initial = m_lineStart == m_column.m_string.begin()
|
||||||
m_lineStart == 0 ? m_column.m_initialIndent : std::string::npos;
|
? m_column.m_initialIndent
|
||||||
|
: std::string::npos;
|
||||||
return initial == std::string::npos ? m_column.m_indent : initial;
|
return initial == std::string::npos ? m_column.m_indent : initial;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string
|
std::string Column::const_iterator::addIndentAndSuffix(
|
||||||
Column::const_iterator::addIndentAndSuffix( size_t position,
|
AnsiSkippingString::const_iterator start,
|
||||||
size_t length ) const {
|
AnsiSkippingString::const_iterator end ) const {
|
||||||
std::string ret;
|
std::string ret;
|
||||||
const auto desired_indent = indentSize();
|
const auto desired_indent = indentSize();
|
||||||
ret.reserve( desired_indent + length + m_addHyphen );
|
// ret.reserve( desired_indent + (end - start) + m_addHyphen );
|
||||||
ret.append( desired_indent, ' ' );
|
ret.append( desired_indent, ' ' );
|
||||||
ret.append( m_column.m_string, position, length );
|
// ret.append( start, end );
|
||||||
if ( m_addHyphen ) {
|
ret += m_column.m_string.substring( start, end );
|
||||||
ret.push_back( '-' );
|
if ( m_addHyphen ) { ret.push_back( '-' ); }
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
Column::const_iterator::const_iterator( Column const& column ): m_column( column ) {
|
Column::const_iterator::const_iterator( Column const& column ):
|
||||||
|
m_column( column ),
|
||||||
|
m_lineStart( column.m_string.begin() ),
|
||||||
|
m_lineEnd( column.m_string.begin() ),
|
||||||
|
m_parsedTo( column.m_string.begin() ) {
|
||||||
assert( m_column.m_width > m_column.m_indent );
|
assert( m_column.m_width > m_column.m_indent );
|
||||||
assert( m_column.m_initialIndent == std::string::npos ||
|
assert( m_column.m_initialIndent == std::string::npos ||
|
||||||
m_column.m_width > m_column.m_initialIndent );
|
m_column.m_width > m_column.m_initialIndent );
|
||||||
calcLength();
|
calcLength();
|
||||||
if ( m_lineLength == 0 ) {
|
if ( m_lineStart == m_lineEnd ) {
|
||||||
m_lineStart = m_column.m_string.size();
|
m_lineStart = m_column.m_string.end();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Column::const_iterator::operator*() const {
|
std::string Column::const_iterator::operator*() const {
|
||||||
assert( m_lineStart <= m_parsedTo );
|
assert( m_lineStart <= m_parsedTo );
|
||||||
return addIndentAndSuffix( m_lineStart, m_lineLength );
|
return addIndentAndSuffix( m_lineStart, m_lineEnd );
|
||||||
}
|
}
|
||||||
|
|
||||||
Column::const_iterator& Column::const_iterator::operator++() {
|
Column::const_iterator& Column::const_iterator::operator++() {
|
||||||
m_lineStart += m_lineLength;
|
m_lineStart = m_lineEnd;
|
||||||
std::string const& current_line = m_column.m_string;
|
AnsiSkippingString const& current_line = m_column.m_string;
|
||||||
if ( m_lineStart < current_line.size() && current_line[m_lineStart] == '\n' ) {
|
if ( m_lineStart != current_line.end() && *m_lineStart == '\n' ) {
|
||||||
m_lineStart += 1;
|
m_lineStart++;
|
||||||
} else {
|
} else {
|
||||||
while ( m_lineStart < current_line.size() &&
|
while ( m_lineStart != current_line.end() &&
|
||||||
isWhitespace( current_line[m_lineStart] ) ) {
|
isWhitespace( *m_lineStart ) ) {
|
||||||
++m_lineStart;
|
++m_lineStart;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( m_lineStart != current_line.size() ) {
|
if ( m_lineStart != current_line.end() ) { calcLength(); }
|
||||||
calcLength();
|
|
||||||
}
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -8077,7 +8195,7 @@ namespace Detail {
|
|||||||
|
|
||||||
std::string WithinRelMatcher::describe() const {
|
std::string WithinRelMatcher::describe() const {
|
||||||
Catch::ReusableStringStream sstr;
|
Catch::ReusableStringStream sstr;
|
||||||
sstr << "and " << m_target << " are within " << m_epsilon * 100. << "% of each other";
|
sstr << "and " << ::Catch::Detail::stringify(m_target) << " are within " << m_epsilon * 100. << "% of each other";
|
||||||
return sstr.str();
|
return sstr.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,8 +6,8 @@
|
|||||||
|
|
||||||
// SPDX-License-Identifier: BSL-1.0
|
// SPDX-License-Identifier: BSL-1.0
|
||||||
|
|
||||||
// Catch v3.5.4
|
// Catch v3.6.0
|
||||||
// Generated: 2024-04-10 12:03:45.785902
|
// Generated: 2024-05-05 20:53:27.071502
|
||||||
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
||||||
// This file is an amalgamation of multiple different files.
|
// This file is an amalgamation of multiple different files.
|
||||||
// You probably shouldn't edit it directly.
|
// You probably shouldn't edit it directly.
|
||||||
@ -5242,9 +5242,11 @@ namespace Detail {
|
|||||||
#ifdef __clang__
|
#ifdef __clang__
|
||||||
# pragma clang diagnostic push
|
# pragma clang diagnostic push
|
||||||
# pragma clang diagnostic ignored "-Wsign-compare"
|
# pragma clang diagnostic ignored "-Wsign-compare"
|
||||||
|
# pragma clang diagnostic ignored "-Wnon-virtual-dtor"
|
||||||
#elif defined __GNUC__
|
#elif defined __GNUC__
|
||||||
# pragma GCC diagnostic push
|
# pragma GCC diagnostic push
|
||||||
# pragma GCC diagnostic ignored "-Wsign-compare"
|
# pragma GCC diagnostic ignored "-Wsign-compare"
|
||||||
|
# pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(CATCH_CPP20_OR_GREATER) && __has_include(<compare>)
|
#if defined(CATCH_CPP20_OR_GREATER) && __has_include(<compare>)
|
||||||
@ -7269,8 +7271,8 @@ namespace Catch {
|
|||||||
#define CATCH_VERSION_MACROS_HPP_INCLUDED
|
#define CATCH_VERSION_MACROS_HPP_INCLUDED
|
||||||
|
|
||||||
#define CATCH_VERSION_MAJOR 3
|
#define CATCH_VERSION_MAJOR 3
|
||||||
#define CATCH_VERSION_MINOR 5
|
#define CATCH_VERSION_MINOR 6
|
||||||
#define CATCH_VERSION_PATCH 4
|
#define CATCH_VERSION_PATCH 0
|
||||||
|
|
||||||
#endif // CATCH_VERSION_MACROS_HPP_INCLUDED
|
#endif // CATCH_VERSION_MACROS_HPP_INCLUDED
|
||||||
|
|
||||||
@ -7949,7 +7951,10 @@ namespace Catch {
|
|||||||
// it, and it provides an escape hatch to the users who need it.
|
// it, and it provides an escape hatch to the users who need it.
|
||||||
#if defined( __SIZEOF_INT128__ )
|
#if defined( __SIZEOF_INT128__ )
|
||||||
# define CATCH_CONFIG_INTERNAL_UINT128
|
# define CATCH_CONFIG_INTERNAL_UINT128
|
||||||
#elif defined( _MSC_VER ) && ( defined( _WIN64 ) || defined( _M_ARM64 ) )
|
// Unlike GCC, MSVC does not polyfill umul as mulh + mul pair on ARM machines.
|
||||||
|
// Currently we do not bother doing this ourselves, but we could if it became
|
||||||
|
// important for perf.
|
||||||
|
#elif defined( _MSC_VER ) && defined( _M_X64 )
|
||||||
# define CATCH_CONFIG_INTERNAL_MSVC_UMUL128
|
# define CATCH_CONFIG_INTERNAL_MSVC_UMUL128
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -7964,7 +7969,6 @@ namespace Catch {
|
|||||||
!defined( CATCH_CONFIG_MSVC_UMUL128 )
|
!defined( CATCH_CONFIG_MSVC_UMUL128 )
|
||||||
# define CATCH_CONFIG_MSVC_UMUL128
|
# define CATCH_CONFIG_MSVC_UMUL128
|
||||||
# include <intrin.h>
|
# include <intrin.h>
|
||||||
# pragma intrinsic( _umul128 )
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@ -10944,6 +10948,107 @@ namespace Catch {
|
|||||||
|
|
||||||
class Columns;
|
class Columns;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstraction for a string with ansi escape sequences that
|
||||||
|
* automatically skips over escapes when iterating. Only graphical
|
||||||
|
* escape sequences are considered.
|
||||||
|
*
|
||||||
|
* Internal representation:
|
||||||
|
* An escape sequence looks like \033[39;49m
|
||||||
|
* We need bidirectional iteration and the unbound length of escape
|
||||||
|
* sequences poses a problem for operator-- To make this work we'll
|
||||||
|
* replace the last `m` with a 0xff (this is a codepoint that won't have
|
||||||
|
* any utf-8 meaning).
|
||||||
|
*/
|
||||||
|
class AnsiSkippingString {
|
||||||
|
std::string m_string;
|
||||||
|
std::size_t m_size = 0;
|
||||||
|
|
||||||
|
// perform 0xff replacement and calculate m_size
|
||||||
|
void preprocessString();
|
||||||
|
|
||||||
|
public:
|
||||||
|
class const_iterator;
|
||||||
|
using iterator = const_iterator;
|
||||||
|
// note: must be u-suffixed or this will cause a "truncation of
|
||||||
|
// constant value" warning on MSVC
|
||||||
|
static constexpr char sentinel = static_cast<char>( 0xffu );
|
||||||
|
|
||||||
|
explicit AnsiSkippingString( std::string const& text );
|
||||||
|
explicit AnsiSkippingString( std::string&& text );
|
||||||
|
|
||||||
|
const_iterator begin() const;
|
||||||
|
const_iterator end() const;
|
||||||
|
|
||||||
|
size_t size() const { return m_size; }
|
||||||
|
|
||||||
|
std::string substring( const_iterator begin,
|
||||||
|
const_iterator end ) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
class AnsiSkippingString::const_iterator {
|
||||||
|
friend AnsiSkippingString;
|
||||||
|
struct EndTag {};
|
||||||
|
|
||||||
|
const std::string* m_string;
|
||||||
|
std::string::const_iterator m_it;
|
||||||
|
|
||||||
|
explicit const_iterator( const std::string& string, EndTag ):
|
||||||
|
m_string( &string ), m_it( string.end() ) {}
|
||||||
|
|
||||||
|
void tryParseAnsiEscapes();
|
||||||
|
void advance();
|
||||||
|
void unadvance();
|
||||||
|
|
||||||
|
public:
|
||||||
|
using difference_type = std::ptrdiff_t;
|
||||||
|
using value_type = char;
|
||||||
|
using pointer = value_type*;
|
||||||
|
using reference = value_type&;
|
||||||
|
using iterator_category = std::bidirectional_iterator_tag;
|
||||||
|
|
||||||
|
explicit const_iterator( const std::string& string ):
|
||||||
|
m_string( &string ), m_it( string.begin() ) {
|
||||||
|
tryParseAnsiEscapes();
|
||||||
|
}
|
||||||
|
|
||||||
|
char operator*() const { return *m_it; }
|
||||||
|
|
||||||
|
const_iterator& operator++() {
|
||||||
|
advance();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
const_iterator operator++( int ) {
|
||||||
|
iterator prev( *this );
|
||||||
|
operator++();
|
||||||
|
return prev;
|
||||||
|
}
|
||||||
|
const_iterator& operator--() {
|
||||||
|
unadvance();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
const_iterator operator--( int ) {
|
||||||
|
iterator prev( *this );
|
||||||
|
operator--();
|
||||||
|
return prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==( const_iterator const& other ) const {
|
||||||
|
return m_it == other.m_it;
|
||||||
|
}
|
||||||
|
bool operator!=( const_iterator const& other ) const {
|
||||||
|
return !operator==( other );
|
||||||
|
}
|
||||||
|
bool operator<=( const_iterator const& other ) const {
|
||||||
|
return m_it <= other.m_it;
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator oneBefore() const {
|
||||||
|
auto it = *this;
|
||||||
|
return --it;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a column of text with specific width and indentation
|
* Represents a column of text with specific width and indentation
|
||||||
*
|
*
|
||||||
@ -10953,10 +11058,11 @@ namespace Catch {
|
|||||||
*/
|
*/
|
||||||
class Column {
|
class Column {
|
||||||
// String to be written out
|
// String to be written out
|
||||||
std::string m_string;
|
AnsiSkippingString m_string;
|
||||||
// Width of the column for linebreaking
|
// Width of the column for linebreaking
|
||||||
size_t m_width = CATCH_CONFIG_CONSOLE_WIDTH - 1;
|
size_t m_width = CATCH_CONFIG_CONSOLE_WIDTH - 1;
|
||||||
// Indentation of other lines (including first if initial indent is unset)
|
// Indentation of other lines (including first if initial indent is
|
||||||
|
// unset)
|
||||||
size_t m_indent = 0;
|
size_t m_indent = 0;
|
||||||
// Indentation of the first line
|
// Indentation of the first line
|
||||||
size_t m_initialIndent = std::string::npos;
|
size_t m_initialIndent = std::string::npos;
|
||||||
@ -10971,16 +11077,19 @@ namespace Catch {
|
|||||||
|
|
||||||
Column const& m_column;
|
Column const& m_column;
|
||||||
// Where does the current line start?
|
// Where does the current line start?
|
||||||
size_t m_lineStart = 0;
|
AnsiSkippingString::const_iterator m_lineStart;
|
||||||
// How long should the current line be?
|
// How long should the current line be?
|
||||||
size_t m_lineLength = 0;
|
AnsiSkippingString::const_iterator m_lineEnd;
|
||||||
// How far have we checked the string to iterate?
|
// How far have we checked the string to iterate?
|
||||||
size_t m_parsedTo = 0;
|
AnsiSkippingString::const_iterator m_parsedTo;
|
||||||
// Should a '-' be appended to the line?
|
// Should a '-' be appended to the line?
|
||||||
bool m_addHyphen = false;
|
bool m_addHyphen = false;
|
||||||
|
|
||||||
const_iterator( Column const& column, EndTag ):
|
const_iterator( Column const& column, EndTag ):
|
||||||
m_column( column ), m_lineStart( m_column.m_string.size() ) {}
|
m_column( column ),
|
||||||
|
m_lineStart( m_column.m_string.end() ),
|
||||||
|
m_lineEnd( column.m_string.end() ),
|
||||||
|
m_parsedTo( column.m_string.end() ) {}
|
||||||
|
|
||||||
// Calculates the length of the current line
|
// Calculates the length of the current line
|
||||||
void calcLength();
|
void calcLength();
|
||||||
@ -10990,8 +11099,9 @@ namespace Catch {
|
|||||||
|
|
||||||
// Creates an indented and (optionally) suffixed string from
|
// Creates an indented and (optionally) suffixed string from
|
||||||
// current iterator position, indentation and length.
|
// current iterator position, indentation and length.
|
||||||
std::string addIndentAndSuffix( size_t position,
|
std::string addIndentAndSuffix(
|
||||||
size_t length ) const;
|
AnsiSkippingString::const_iterator start,
|
||||||
|
AnsiSkippingString::const_iterator end ) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using difference_type = std::ptrdiff_t;
|
using difference_type = std::ptrdiff_t;
|
||||||
@ -11008,7 +11118,8 @@ namespace Catch {
|
|||||||
const_iterator operator++( int );
|
const_iterator operator++( int );
|
||||||
|
|
||||||
bool operator==( const_iterator const& other ) const {
|
bool operator==( const_iterator const& other ) const {
|
||||||
return m_lineStart == other.m_lineStart && &m_column == &other.m_column;
|
return m_lineStart == other.m_lineStart &&
|
||||||
|
&m_column == &other.m_column;
|
||||||
}
|
}
|
||||||
bool operator!=( const_iterator const& other ) const {
|
bool operator!=( const_iterator const& other ) const {
|
||||||
return !operator==( other );
|
return !operator==( other );
|
||||||
@ -11049,7 +11160,9 @@ namespace Catch {
|
|||||||
|
|
||||||
size_t width() const { return m_width; }
|
size_t width() const { return m_width; }
|
||||||
const_iterator begin() const { return const_iterator( *this ); }
|
const_iterator begin() const { return const_iterator( *this ); }
|
||||||
const_iterator end() const { return { *this, const_iterator::EndTag{} }; }
|
const_iterator end() const {
|
||||||
|
return { *this, const_iterator::EndTag{} };
|
||||||
|
}
|
||||||
|
|
||||||
friend std::ostream& operator<<( std::ostream& os,
|
friend std::ostream& operator<<( std::ostream& os,
|
||||||
Column const& col );
|
Column const& col );
|
||||||
@ -11320,6 +11433,16 @@ namespace Catch {
|
|||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
# pragma clang diagnostic push
|
||||||
|
# pragma clang diagnostic ignored "-Wsign-compare"
|
||||||
|
# pragma clang diagnostic ignored "-Wnon-virtual-dtor"
|
||||||
|
#elif defined __GNUC__
|
||||||
|
# pragma GCC diagnostic push
|
||||||
|
# pragma GCC diagnostic ignored "-Wsign-compare"
|
||||||
|
# pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
|
||||||
|
#endif
|
||||||
|
|
||||||
template<typename ArgT, typename MatcherT>
|
template<typename ArgT, typename MatcherT>
|
||||||
class MatchExpr : public ITransientExpression {
|
class MatchExpr : public ITransientExpression {
|
||||||
ArgT && m_arg;
|
ArgT && m_arg;
|
||||||
@ -11338,6 +11461,13 @@ namespace Catch {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
# pragma clang diagnostic pop
|
||||||
|
#elif defined __GNUC__
|
||||||
|
# pragma GCC diagnostic pop
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
namespace Matchers {
|
namespace Matchers {
|
||||||
template <typename ArgT>
|
template <typename ArgT>
|
||||||
class MatcherBase;
|
class MatcherBase;
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
project(
|
project(
|
||||||
'catch2',
|
'catch2',
|
||||||
'cpp',
|
'cpp',
|
||||||
version: '3.5.4', # CML version placeholder, don't delete
|
version: '3.6.0', # CML version placeholder, don't delete
|
||||||
license: 'BSL-1.0',
|
license: 'BSL-1.0',
|
||||||
meson_version: '>=0.54.1',
|
meson_version: '>=0.54.1',
|
||||||
)
|
)
|
||||||
|
@ -36,7 +36,7 @@ namespace Catch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Version const& libraryVersion() {
|
Version const& libraryVersion() {
|
||||||
static Version version( 3, 5, 4, "", 0 );
|
static Version version( 3, 6, 0, "", 0 );
|
||||||
return version;
|
return version;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
#define CATCH_VERSION_MACROS_HPP_INCLUDED
|
#define CATCH_VERSION_MACROS_HPP_INCLUDED
|
||||||
|
|
||||||
#define CATCH_VERSION_MAJOR 3
|
#define CATCH_VERSION_MAJOR 3
|
||||||
#define CATCH_VERSION_MINOR 5
|
#define CATCH_VERSION_MINOR 6
|
||||||
#define CATCH_VERSION_PATCH 4
|
#define CATCH_VERSION_PATCH 0
|
||||||
|
|
||||||
#endif // CATCH_VERSION_MACROS_HPP_INCLUDED
|
#endif // CATCH_VERSION_MACROS_HPP_INCLUDED
|
||||||
|
Loading…
Reference in New Issue
Block a user