Compare commits

...

13 Commits

Author SHA1 Message Date
Wmbat 0dd4fd1576
Merge f28ab91b60 into 8ce2426e53 2024-05-05 17:14:10 +01:00
Jeremy Rifkin 8ce2426e53
Handle ANSI escape sequences when performing column wrapping (#2849)
This PR adds functionality to skip around ANSI escape sequences in catch_textflow so they do not contribute to line length and line wrapping code does not split escape sequences in the middle. I've implemented this by creating a AnsiSkippingString abstraction that has a bidirectional iterator that can skip around escape sequences while iterating. Additionally I refactored Column::const_iterator to be iterator-based rather than index-based so this abstraction is a simple drop-in for std::string.

Currently only color sequences are handled, other escape sequences are left unaffected.

Motivation: Text with ANSI color sequences gets messed up when being output by Catch2 #2833.
2024-05-04 23:43:52 +02:00
wmbat f28ab91b60 Moved -Wsign-conversion flag to the correct alphabetical position 2023-12-06 18:50:54 -05:00
wmbat 803062eb29 Fixing sign conversion warnings in MatchersRanges.tests 2023-12-06 18:50:54 -05:00
wmbat 52904f981f Fixed Generators.Tests warnings 2023-12-06 18:50:54 -05:00
wmbat 437b652dca Fixed sign conversion warnings in Benchmark.tests 2023-12-06 18:50:49 -05:00
wmbat 6a1635585d Fixed sign conversion warnings in Sharding.tests 2023-12-06 18:48:29 -05:00
wmbat 382ba723b6 Fixed sign conversion warnings in Generators.tests 2023-12-06 18:48:29 -05:00
wmbat e3b8457b17 Fixed sign conversion warnings in Evt-EventListeners 2023-12-06 18:48:29 -05:00
wmbat 07bd421c31 Fixed sign conversion warnings in catch_test_case_info_hasher 2023-12-06 18:48:29 -05:00
wmbat 043dfb2e8e Fixed sign conversion warnings in catch_timer 2023-12-06 18:48:29 -05:00
wmbat 782df1ee92 Fixed sign conversion warnings in catch_reporter_multi 2023-12-06 18:48:23 -05:00
wmbat ef2202b41b Fixed sign conversion warnings in catch_reporter_console 2023-12-05 20:03:37 -05:00
21 changed files with 613 additions and 192 deletions

View File

@ -78,6 +78,7 @@ function(add_warnings_to_targets targets)
"-Wreorder"
"-Wreturn-std-move"
"-Wshadow"
"-Wsign-conversion"
"-Wstrict-aliasing"
"-Wsubobject-linkage"
"-Wsuggest-destructor-override"

View File

@ -25,7 +25,7 @@
namespace {
std::string ws(int const level) {
std::string ws(std::size_t const level) {
return std::string( 2 * level, ' ' );
}
@ -45,7 +45,7 @@ std::ostream& operator<<( std::ostream& os, std::vector<T> const& v ) {
// std::size_t line;
// };
void print( std::ostream& os, int const level, std::string const& title, Catch::SourceLineInfo const& info ) {
void print( std::ostream& os, std::size_t const level, std::string const& title, Catch::SourceLineInfo const& info ) {
os << ws(level ) << title << ":\n"
<< ws(level+1) << "- file: " << info.file << "\n"
<< ws(level+1) << "- line: " << info.line << "\n";
@ -59,14 +59,14 @@ void print( std::ostream& os, int const level, std::string const& title, Catch::
// unsigned int sequence;
//};
void print( std::ostream& os, int const level, Catch::MessageInfo const& info ) {
void print( std::ostream& os, std::size_t const level, Catch::MessageInfo const& info ) {
os << ws(level+1) << "- macroName: '" << info.macroName << "'\n"
<< ws(level+1) << "- message '" << info.message << "'\n";
print( os,level+1 , "- lineInfo", info.lineInfo );
os << ws(level+1) << "- sequence " << info.sequence << "\n";
}
void print( std::ostream& os, int const level, std::string const& title, std::vector<Catch::MessageInfo> const& v ) {
void print( std::ostream& os, std::size_t const level, std::string const& title, std::vector<Catch::MessageInfo> const& v ) {
os << ws(level ) << title << ":\n";
for ( const auto& x : v )
{
@ -81,7 +81,7 @@ void print( std::ostream& os, int const level, std::string const& title, std::ve
// std::string name;
// };
void print( std::ostream& os, int const level, std::string const& title, Catch::TestRunInfo const& info ) {
void print( std::ostream& os, std::size_t const level, std::string const& title, Catch::TestRunInfo const& info ) {
os << ws(level ) << title << ":\n"
<< ws(level+1) << "- name: " << info.name << "\n";
}
@ -96,7 +96,7 @@ void print( std::ostream& os, int const level, std::string const& title, Catch::
// std::size_t failedButOk = 0;
// };
void print( std::ostream& os, int const level, std::string const& title, Catch::Counts const& info ) {
void print( std::ostream& os, std::size_t const level, std::string const& title, Catch::Counts const& info ) {
os << ws(level ) << title << ":\n"
<< ws(level+1) << "- total(): " << info.total() << "\n"
<< ws(level+1) << "- allPassed(): " << info.allPassed() << "\n"
@ -111,7 +111,7 @@ void print( std::ostream& os, int const level, std::string const& title, Catch::
// Counts testCases;
// };
void print( std::ostream& os, int const level, std::string const& title, Catch::Totals const& info ) {
void print( std::ostream& os, std::size_t const level, std::string const& title, Catch::Totals const& info ) {
os << ws(level) << title << ":\n";
print( os, level+1, "- assertions", info.assertions );
print( os, level+1, "- testCases" , info.testCases );
@ -123,7 +123,7 @@ void print( std::ostream& os, int const level, std::string const& title, Catch::
// bool aborting;
// };
void print( std::ostream& os, int const level, std::string const& title, Catch::TestRunStats const& info ) {
void print( std::ostream& os, std::size_t const level, std::string const& title, Catch::TestRunStats const& info ) {
os << ws(level) << title << ":\n";
print( os, level+1 , "- runInfo", info.runInfo );
print( os, level+1 , "- totals" , info.totals );
@ -161,7 +161,7 @@ void print( std::ostream& os, int const level, std::string const& title, Catch::
// TestCaseProperties properties = TestCaseProperties::None;
// };
void print( std::ostream& os, int const level, std::string const& title, Catch::TestCaseInfo const& info ) {
void print( std::ostream& os, std::size_t const level, std::string const& title, Catch::TestCaseInfo const& info ) {
os << ws(level ) << title << ":\n"
<< ws(level+1) << "- isHidden(): " << info.isHidden() << "\n"
<< ws(level+1) << "- throws(): " << info.throws() << "\n"
@ -183,7 +183,7 @@ void print( std::ostream& os, int const level, std::string const& title, Catch::
// bool aborting;
// };
void print( std::ostream& os, int const level, std::string const& title, Catch::TestCaseStats const& info ) {
void print( std::ostream& os, std::size_t const level, std::string const& title, Catch::TestCaseStats const& info ) {
os << ws(level ) << title << ":\n";
print( os, level+1 , "- testInfo", *info.testInfo );
print( os, level+1 , "- totals" , info.totals );
@ -198,7 +198,7 @@ void print( std::ostream& os, int const level, std::string const& title, Catch::
// SourceLineInfo lineInfo;
// };
void print( std::ostream& os, int const level, std::string const& title, Catch::SectionInfo const& info ) {
void print( std::ostream& os, std::size_t const level, std::string const& title, Catch::SectionInfo const& info ) {
os << ws(level ) << title << ":\n"
<< ws(level+1) << "- name: " << info.name << "\n";
print( os, level+1 , "- lineInfo", info.lineInfo );
@ -211,7 +211,7 @@ void print( std::ostream& os, int const level, std::string const& title, Catch::
// bool missingAssertions;
// };
void print( std::ostream& os, int const level, std::string const& title, Catch::SectionStats const& info ) {
void print( std::ostream& os, std::size_t const level, std::string const& title, Catch::SectionStats const& info ) {
os << ws(level ) << title << ":\n";
print( os, level+1 , "- sectionInfo", info.sectionInfo );
print( os, level+1 , "- assertions" , info.assertions );
@ -227,7 +227,7 @@ void print( std::ostream& os, int const level, std::string const& title, Catch::
// ResultDisposition::Flags resultDisposition;
// };
void print( std::ostream& os, int const level, std::string const& title, Catch::AssertionInfo const& info ) {
void print( std::ostream& os, std::size_t const level, std::string const& title, Catch::AssertionInfo const& info ) {
os << ws(level ) << title << ":\n"
<< ws(level+1) << "- macroName: '" << info.macroName << "'\n";
print( os, level+1 , "- lineInfo" , info.lineInfo );
@ -245,7 +245,7 @@ void print( std::ostream& os, int const level, std::string const& title, Catch::
// ResultWas::OfType resultType;
//};
void print( std::ostream& os, int const level, std::string const& title, Catch::AssertionResultData const& info ) {
void print( std::ostream& os, std::size_t const level, std::string const& title, Catch::AssertionResultData const& info ) {
os << ws(level ) << title << ":\n"
<< ws(level+1) << "- reconstructExpression(): '" << info.reconstructExpression() << "'\n"
<< ws(level+1) << "- message: '" << info.message << "'\n"
@ -271,7 +271,7 @@ void print( std::ostream& os, int const level, std::string const& title, Catch::
// AssertionResultData m_resultData;
//};
void print( std::ostream& os, int const level, std::string const& title, Catch::AssertionResult const& info ) {
void print( std::ostream& os, std::size_t const level, std::string const& title, Catch::AssertionResult const& info ) {
os << ws(level ) << title << ":\n"
<< ws(level+1) << "- isOk(): " << info.isOk() << "\n"
<< ws(level+1) << "- succeeded(): " << info.succeeded() << "\n"
@ -296,7 +296,7 @@ void print( std::ostream& os, int const level, std::string const& title, Catch::
// Totals totals;
// };
void print( std::ostream& os, int const level, std::string const& title, Catch::AssertionStats const& info ) {
void print( std::ostream& os, std::size_t const level, std::string const& title, Catch::AssertionStats const& info ) {
os << ws(level ) << title << ":\n";
print( os, level+1 , "- assertionResult", info.assertionResult );
print( os, level+1 , "- infoMessages", info.infoMessages );

View File

@ -13,7 +13,8 @@ namespace Catch {
namespace {
static auto getCurrentNanosecondsSinceEpoch() -> uint64_t {
return std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now().time_since_epoch()).count();
return static_cast<uint64_t>(std::chrono::duration_cast<std::chrono::nanoseconds>(
std::chrono::high_resolution_clock::now().time_since_epoch()).count());
}
} // end unnamed namespace

View File

@ -17,16 +17,16 @@ namespace Catch {
const hash_t prime = 1099511628211u;
hash_t hash = 14695981039346656037u;
for ( const char c : t.name ) {
hash ^= c;
hash ^= static_cast<hash_t>(c);
hash *= prime;
}
for ( const char c : t.className ) {
hash ^= c;
hash ^= static_cast<hash_t>(c);
hash *= prime;
}
for ( const Tag& tag : t.tags ) {
for ( const char c : tag.original ) {
hash ^= c;
hash ^= static_cast<hash_t>(c);
hash *= prime;
}
}

View File

@ -26,117 +26,228 @@ namespace {
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 Catch {
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() {
m_addHyphen = false;
m_parsedTo = m_lineStart;
AnsiSkippingString const& current_line = m_column.m_string;
std::string const& current_line = m_column.m_string;
if ( current_line[m_lineStart] == '\n' ) {
++m_parsedTo;
if ( m_parsedTo == current_line.end() ) {
m_lineEnd = 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 maxParseTo = std::min(current_line.size(), m_lineStart + maxLineLength);
while ( m_parsedTo < maxParseTo &&
current_line[m_parsedTo] != '\n' ) {
std::size_t lineLength = 0;
while ( m_parsedTo != current_line.end() &&
lineLength < maxLineLength && *m_parsedTo != '\n' ) {
++m_parsedTo;
++lineLength;
}
// If we encountered a newline before the column is filled,
// then we linebreak at the newline and consider this line
// finished.
if ( m_parsedTo < m_lineStart + maxLineLength ) {
m_lineLength = m_parsedTo - m_lineStart;
if ( lineLength < maxLineLength ) {
m_lineEnd = m_parsedTo;
} else {
// Look for a natural linebreak boundary in the column
// (We look from the end, so that the first found boundary is
// the right one)
size_t newLineLength = maxLineLength;
while ( newLineLength > 0 && !isBoundary( current_line, m_lineStart + newLineLength ) ) {
--newLineLength;
m_lineEnd = m_parsedTo;
while ( lineLength > 0 &&
!isBoundary( current_line, m_lineEnd ) ) {
--lineLength;
--m_lineEnd;
}
while ( newLineLength > 0 &&
isWhitespace( current_line[m_lineStart + newLineLength - 1] ) ) {
--newLineLength;
while ( lineLength > 0 &&
isWhitespace( *m_lineEnd.oneBefore() ) ) {
--lineLength;
--m_lineEnd;
}
// If we found one, then that is where we linebreak
if ( newLineLength > 0 ) {
m_lineLength = newLineLength;
} else {
// Otherwise we have to split text with a hyphen
// If we found one, then that is where we linebreak, otherwise
// we have to split text with a hyphen
if ( lineLength == 0 ) {
m_addHyphen = true;
m_lineLength = maxLineLength - 1;
m_lineEnd = m_parsedTo.oneBefore();
}
}
}
size_t Column::const_iterator::indentSize() const {
auto initial =
m_lineStart == 0 ? m_column.m_initialIndent : std::string::npos;
auto initial = m_lineStart == m_column.m_string.begin()
? m_column.m_initialIndent
: std::string::npos;
return initial == std::string::npos ? m_column.m_indent : initial;
}
std::string
Column::const_iterator::addIndentAndSuffix( size_t position,
size_t length ) const {
std::string Column::const_iterator::addIndentAndSuffix(
AnsiSkippingString::const_iterator start,
AnsiSkippingString::const_iterator end ) const {
std::string ret;
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( m_column.m_string, position, length );
if ( m_addHyphen ) {
ret.push_back( '-' );
}
// ret.append( start, end );
ret += m_column.m_string.substring( start, end );
if ( m_addHyphen ) { ret.push_back( '-' ); }
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_initialIndent == std::string::npos ||
m_column.m_width > m_column.m_initialIndent );
calcLength();
if ( m_lineLength == 0 ) {
m_lineStart = m_column.m_string.size();
if ( m_lineStart == m_lineEnd ) {
m_lineStart = m_column.m_string.end();
}
}
std::string Column::const_iterator::operator*() const {
assert( m_lineStart <= m_parsedTo );
return addIndentAndSuffix( m_lineStart, m_lineLength );
return addIndentAndSuffix( m_lineStart, m_lineEnd );
}
Column::const_iterator& Column::const_iterator::operator++() {
m_lineStart += m_lineLength;
std::string const& current_line = m_column.m_string;
if ( m_lineStart < current_line.size() && current_line[m_lineStart] == '\n' ) {
m_lineStart += 1;
m_lineStart = m_lineEnd;
AnsiSkippingString const& current_line = m_column.m_string;
if ( m_lineStart != current_line.end() && *m_lineStart == '\n' ) {
m_lineStart++;
} else {
while ( m_lineStart < current_line.size() &&
isWhitespace( current_line[m_lineStart] ) ) {
while ( m_lineStart != current_line.end() &&
isWhitespace( *m_lineStart ) ) {
++m_lineStart;
}
}
if ( m_lineStart != current_line.size() ) {
calcLength();
}
if ( m_lineStart != current_line.end() ) { calcLength(); }
return *this;
}
@ -233,25 +344,25 @@ namespace Catch {
return os;
}
Columns operator+(Column const& lhs, Column const& rhs) {
Columns operator+( Column const& lhs, Column const& rhs ) {
Columns cols;
cols += lhs;
cols += rhs;
return cols;
}
Columns operator+(Column&& lhs, Column&& rhs) {
Columns operator+( Column&& lhs, Column&& rhs ) {
Columns cols;
cols += CATCH_MOVE( lhs );
cols += CATCH_MOVE( rhs );
return cols;
}
Columns& operator+=(Columns& lhs, Column const& rhs) {
Columns& operator+=( Columns& lhs, Column const& rhs ) {
lhs.m_columns.push_back( rhs );
return lhs;
}
Columns& operator+=(Columns& lhs, Column&& rhs) {
lhs.m_columns.push_back( CATCH_MOVE(rhs) );
Columns& operator+=( Columns& lhs, Column&& rhs ) {
lhs.m_columns.push_back( CATCH_MOVE( rhs ) );
return lhs;
}
Columns operator+( Columns const& lhs, Column const& rhs ) {

View File

@ -20,6 +20,107 @@ namespace Catch {
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
*
@ -29,10 +130,11 @@ namespace Catch {
*/
class Column {
// String to be written out
std::string m_string;
AnsiSkippingString m_string;
// Width of the column for linebreaking
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;
// Indentation of the first line
size_t m_initialIndent = std::string::npos;
@ -47,16 +149,19 @@ namespace Catch {
Column const& m_column;
// Where does the current line start?
size_t m_lineStart = 0;
AnsiSkippingString::const_iterator m_lineStart;
// 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?
size_t m_parsedTo = 0;
AnsiSkippingString::const_iterator m_parsedTo;
// Should a '-' be appended to the line?
bool m_addHyphen = false;
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
void calcLength();
@ -66,8 +171,9 @@ namespace Catch {
// Creates an indented and (optionally) suffixed string from
// current iterator position, indentation and length.
std::string addIndentAndSuffix( size_t position,
size_t length ) const;
std::string addIndentAndSuffix(
AnsiSkippingString::const_iterator start,
AnsiSkippingString::const_iterator end ) const;
public:
using difference_type = std::ptrdiff_t;
@ -84,7 +190,8 @@ namespace Catch {
const_iterator operator++( int );
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 {
return !operator==( other );
@ -94,7 +201,7 @@ namespace Catch {
explicit Column( std::string const& text ): m_string( text ) {}
explicit Column( std::string&& text ):
m_string( CATCH_MOVE(text)) {}
m_string( CATCH_MOVE( text ) ) {}
Column& width( size_t newWidth ) & {
assert( newWidth > 0 );
@ -125,7 +232,9 @@ namespace Catch {
size_t width() const { return m_width; }
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,
Column const& col );

View File

@ -298,7 +298,7 @@ class TablePrinter {
std::ostream& m_os;
std::vector<ColumnInfo> m_columnInfos;
ReusableStringStream m_oss;
int m_currentColumn = -1;
std::size_t m_currentColumn = 0;
bool m_isOpen = false;
public:
@ -345,11 +345,10 @@ public:
const auto strSize = colStr.size();
tp.m_oss.str("");
tp.open();
if (tp.m_currentColumn == static_cast<int>(tp.m_columnInfos.size() - 1)) {
tp.m_currentColumn = -1;
if (tp.m_currentColumn == tp.m_columnInfos.size()) {
tp.m_currentColumn = 0;
tp.m_os << '\n';
}
tp.m_currentColumn++;
auto colInfo = tp.m_columnInfos[tp.m_currentColumn];
auto padding = (strSize + 1 < colInfo.width)
@ -365,7 +364,7 @@ public:
friend TablePrinter& operator<< (TablePrinter& tp, RowBreak) {
if (tp.m_currentColumn > 0) {
tp.m_os << '\n';
tp.m_currentColumn = -1;
tp.m_currentColumn = 0;
}
return tp;
}

View File

@ -24,7 +24,7 @@ namespace Catch {
// Keep track of how many listeners we have already inserted,
// so that we can insert them into the main vector at the right place
size_t m_insertedListeners = 0;
std::vector<IEventListenerPtr>::difference_type m_insertedListeners = 0;
void updatePreferences(IEventListener const& reporterish);

View File

@ -340,7 +340,7 @@ MatchersRanges.tests.cpp:<line number>: passed: c, !Contains(1) for: { 4, 5, 6 }
MatchersRanges.tests.cpp:<line number>: passed: a, Contains(0, close_enough) for: { 1, 2, 3 } contains element 0
MatchersRanges.tests.cpp:<line number>: passed: b, Contains(0, close_enough) for: { 0, 1, 2 } contains element 0
MatchersRanges.tests.cpp:<line number>: passed: c, !Contains(0, close_enough) for: { 4, 5, 6 } not contains element 0
MatchersRanges.tests.cpp:<line number>: passed: a, Contains(4, [](auto&& lhs, size_t sz) { return lhs.size() == sz; }) for: { "abc", "abcd", "abcde" } contains element 4
MatchersRanges.tests.cpp:<line number>: passed: a, Contains(4u, [](auto&& lhs, size_t sz) { return lhs.size() == sz; }) for: { "abc", "abcd", "abcde" } contains element 4
MatchersRanges.tests.cpp:<line number>: passed: in, Contains(1) for: { 1, 2, 3, 4, 5 } contains element 1
MatchersRanges.tests.cpp:<line number>: passed: in, !Contains(8) for: { 1, 2, 3, 4, 5 } not contains element 8
MatchersRanges.tests.cpp:<line number>: passed: in, Contains(MoveOnlyTestElement{ 2 }) for: { 1, 2, 3 } contains element 2
@ -740,21 +740,21 @@ Generators.tests.cpp:<line number>: passed: chunk(2, value(1)), Catch::Generator
Generators.tests.cpp:<line number>: passed: j < i for: -3 < 1
Generators.tests.cpp:<line number>: passed: j < i for: -2 < 1
Generators.tests.cpp:<line number>: passed: j < i for: -1 < 1
Generators.tests.cpp:<line number>: passed: 4u * i > str.size() for: 4 > 1
Generators.tests.cpp:<line number>: passed: 4u * i > str.size() for: 4 > 2
Generators.tests.cpp:<line number>: passed: 4u * i > str.size() for: 4 > 3
Generators.tests.cpp:<line number>: passed: 4u * static_cast<std::size_t>(i) > str.size() for: 4 > 1
Generators.tests.cpp:<line number>: passed: 4u * static_cast<std::size_t>(i) > str.size() for: 4 > 2
Generators.tests.cpp:<line number>: passed: 4u * static_cast<std::size_t>(i) > str.size() for: 4 > 3
Generators.tests.cpp:<line number>: passed: j < i for: -3 < 2
Generators.tests.cpp:<line number>: passed: j < i for: -2 < 2
Generators.tests.cpp:<line number>: passed: j < i for: -1 < 2
Generators.tests.cpp:<line number>: passed: 4u * i > str.size() for: 8 > 1
Generators.tests.cpp:<line number>: passed: 4u * i > str.size() for: 8 > 2
Generators.tests.cpp:<line number>: passed: 4u * i > str.size() for: 8 > 3
Generators.tests.cpp:<line number>: passed: 4u * static_cast<std::size_t>(i) > str.size() for: 8 > 1
Generators.tests.cpp:<line number>: passed: 4u * static_cast<std::size_t>(i) > str.size() for: 8 > 2
Generators.tests.cpp:<line number>: passed: 4u * static_cast<std::size_t>(i) > str.size() for: 8 > 3
Generators.tests.cpp:<line number>: passed: j < i for: -3 < 3
Generators.tests.cpp:<line number>: passed: j < i for: -2 < 3
Generators.tests.cpp:<line number>: passed: j < i for: -1 < 3
Generators.tests.cpp:<line number>: passed: 4u * i > str.size() for: 12 > 1
Generators.tests.cpp:<line number>: passed: 4u * i > str.size() for: 12 > 2
Generators.tests.cpp:<line number>: passed: 4u * i > str.size() for: 12 > 3
Generators.tests.cpp:<line number>: passed: 4u * static_cast<std::size_t>(i) > str.size() for: 12 > 1
Generators.tests.cpp:<line number>: passed: 4u * static_cast<std::size_t>(i) > str.size() for: 12 > 2
Generators.tests.cpp:<line number>: passed: 4u * static_cast<std::size_t>(i) > str.size() for: 12 > 3
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 123 for: 123 == 123
GeneratorsImpl.tests.cpp:<line number>: passed: !(gen.next()) for: !false
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 1 for: 1 == 1

View File

@ -338,7 +338,7 @@ MatchersRanges.tests.cpp:<line number>: passed: c, !Contains(1) for: { 4, 5, 6 }
MatchersRanges.tests.cpp:<line number>: passed: a, Contains(0, close_enough) for: { 1, 2, 3 } contains element 0
MatchersRanges.tests.cpp:<line number>: passed: b, Contains(0, close_enough) for: { 0, 1, 2 } contains element 0
MatchersRanges.tests.cpp:<line number>: passed: c, !Contains(0, close_enough) for: { 4, 5, 6 } not contains element 0
MatchersRanges.tests.cpp:<line number>: passed: a, Contains(4, [](auto&& lhs, size_t sz) { return lhs.size() == sz; }) for: { "abc", "abcd", "abcde" } contains element 4
MatchersRanges.tests.cpp:<line number>: passed: a, Contains(4u, [](auto&& lhs, size_t sz) { return lhs.size() == sz; }) for: { "abc", "abcd", "abcde" } contains element 4
MatchersRanges.tests.cpp:<line number>: passed: in, Contains(1) for: { 1, 2, 3, 4, 5 } contains element 1
MatchersRanges.tests.cpp:<line number>: passed: in, !Contains(8) for: { 1, 2, 3, 4, 5 } not contains element 8
MatchersRanges.tests.cpp:<line number>: passed: in, Contains(MoveOnlyTestElement{ 2 }) for: { 1, 2, 3 } contains element 2
@ -738,21 +738,21 @@ Generators.tests.cpp:<line number>: passed: chunk(2, value(1)), Catch::Generator
Generators.tests.cpp:<line number>: passed: j < i for: -3 < 1
Generators.tests.cpp:<line number>: passed: j < i for: -2 < 1
Generators.tests.cpp:<line number>: passed: j < i for: -1 < 1
Generators.tests.cpp:<line number>: passed: 4u * i > str.size() for: 4 > 1
Generators.tests.cpp:<line number>: passed: 4u * i > str.size() for: 4 > 2
Generators.tests.cpp:<line number>: passed: 4u * i > str.size() for: 4 > 3
Generators.tests.cpp:<line number>: passed: 4u * static_cast<std::size_t>(i) > str.size() for: 4 > 1
Generators.tests.cpp:<line number>: passed: 4u * static_cast<std::size_t>(i) > str.size() for: 4 > 2
Generators.tests.cpp:<line number>: passed: 4u * static_cast<std::size_t>(i) > str.size() for: 4 > 3
Generators.tests.cpp:<line number>: passed: j < i for: -3 < 2
Generators.tests.cpp:<line number>: passed: j < i for: -2 < 2
Generators.tests.cpp:<line number>: passed: j < i for: -1 < 2
Generators.tests.cpp:<line number>: passed: 4u * i > str.size() for: 8 > 1
Generators.tests.cpp:<line number>: passed: 4u * i > str.size() for: 8 > 2
Generators.tests.cpp:<line number>: passed: 4u * i > str.size() for: 8 > 3
Generators.tests.cpp:<line number>: passed: 4u * static_cast<std::size_t>(i) > str.size() for: 8 > 1
Generators.tests.cpp:<line number>: passed: 4u * static_cast<std::size_t>(i) > str.size() for: 8 > 2
Generators.tests.cpp:<line number>: passed: 4u * static_cast<std::size_t>(i) > str.size() for: 8 > 3
Generators.tests.cpp:<line number>: passed: j < i for: -3 < 3
Generators.tests.cpp:<line number>: passed: j < i for: -2 < 3
Generators.tests.cpp:<line number>: passed: j < i for: -1 < 3
Generators.tests.cpp:<line number>: passed: 4u * i > str.size() for: 12 > 1
Generators.tests.cpp:<line number>: passed: 4u * i > str.size() for: 12 > 2
Generators.tests.cpp:<line number>: passed: 4u * i > str.size() for: 12 > 3
Generators.tests.cpp:<line number>: passed: 4u * static_cast<std::size_t>(i) > str.size() for: 12 > 1
Generators.tests.cpp:<line number>: passed: 4u * static_cast<std::size_t>(i) > str.size() for: 12 > 2
Generators.tests.cpp:<line number>: passed: 4u * static_cast<std::size_t>(i) > str.size() for: 12 > 3
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 123 for: 123 == 123
GeneratorsImpl.tests.cpp:<line number>: passed: !(gen.next()) for: !false
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 1 for: 1 == 1

View File

@ -2629,7 +2629,7 @@ MatchersRanges.tests.cpp:<line number>
...............................................................................
MatchersRanges.tests.cpp:<line number>: PASSED:
REQUIRE_THAT( a, Contains(4, [](auto&& lhs, size_t sz) { return lhs.size() == sz; }) )
REQUIRE_THAT( a, Contains(4u, [](auto&& lhs, size_t sz) { return lhs.size() == sz; }) )
with expansion:
{ "abc", "abcd", "abcde" } contains element 4
@ -5420,7 +5420,7 @@ Generators.tests.cpp:<line number>
...............................................................................
Generators.tests.cpp:<line number>: PASSED:
REQUIRE( 4u * i > str.size() )
REQUIRE( 4u * static_cast<std::size_t>(i) > str.size() )
with expansion:
4 > 1
@ -5432,7 +5432,7 @@ Generators.tests.cpp:<line number>
...............................................................................
Generators.tests.cpp:<line number>: PASSED:
REQUIRE( 4u * i > str.size() )
REQUIRE( 4u * static_cast<std::size_t>(i) > str.size() )
with expansion:
4 > 2
@ -5444,7 +5444,7 @@ Generators.tests.cpp:<line number>
...............................................................................
Generators.tests.cpp:<line number>: PASSED:
REQUIRE( 4u * i > str.size() )
REQUIRE( 4u * static_cast<std::size_t>(i) > str.size() )
with expansion:
4 > 3
@ -5492,7 +5492,7 @@ Generators.tests.cpp:<line number>
...............................................................................
Generators.tests.cpp:<line number>: PASSED:
REQUIRE( 4u * i > str.size() )
REQUIRE( 4u * static_cast<std::size_t>(i) > str.size() )
with expansion:
8 > 1
@ -5504,7 +5504,7 @@ Generators.tests.cpp:<line number>
...............................................................................
Generators.tests.cpp:<line number>: PASSED:
REQUIRE( 4u * i > str.size() )
REQUIRE( 4u * static_cast<std::size_t>(i) > str.size() )
with expansion:
8 > 2
@ -5516,7 +5516,7 @@ Generators.tests.cpp:<line number>
...............................................................................
Generators.tests.cpp:<line number>: PASSED:
REQUIRE( 4u * i > str.size() )
REQUIRE( 4u * static_cast<std::size_t>(i) > str.size() )
with expansion:
8 > 3
@ -5564,7 +5564,7 @@ Generators.tests.cpp:<line number>
...............................................................................
Generators.tests.cpp:<line number>: PASSED:
REQUIRE( 4u * i > str.size() )
REQUIRE( 4u * static_cast<std::size_t>(i) > str.size() )
with expansion:
12 > 1
@ -5576,7 +5576,7 @@ Generators.tests.cpp:<line number>
...............................................................................
Generators.tests.cpp:<line number>: PASSED:
REQUIRE( 4u * i > str.size() )
REQUIRE( 4u * static_cast<std::size_t>(i) > str.size() )
with expansion:
12 > 2
@ -5588,7 +5588,7 @@ Generators.tests.cpp:<line number>
...............................................................................
Generators.tests.cpp:<line number>: PASSED:
REQUIRE( 4u * i > str.size() )
REQUIRE( 4u * static_cast<std::size_t>(i) > str.size() )
with expansion:
12 > 3

View File

@ -2627,7 +2627,7 @@ MatchersRanges.tests.cpp:<line number>
...............................................................................
MatchersRanges.tests.cpp:<line number>: PASSED:
REQUIRE_THAT( a, Contains(4, [](auto&& lhs, size_t sz) { return lhs.size() == sz; }) )
REQUIRE_THAT( a, Contains(4u, [](auto&& lhs, size_t sz) { return lhs.size() == sz; }) )
with expansion:
{ "abc", "abcd", "abcde" } contains element 4
@ -5418,7 +5418,7 @@ Generators.tests.cpp:<line number>
...............................................................................
Generators.tests.cpp:<line number>: PASSED:
REQUIRE( 4u * i > str.size() )
REQUIRE( 4u * static_cast<std::size_t>(i) > str.size() )
with expansion:
4 > 1
@ -5430,7 +5430,7 @@ Generators.tests.cpp:<line number>
...............................................................................
Generators.tests.cpp:<line number>: PASSED:
REQUIRE( 4u * i > str.size() )
REQUIRE( 4u * static_cast<std::size_t>(i) > str.size() )
with expansion:
4 > 2
@ -5442,7 +5442,7 @@ Generators.tests.cpp:<line number>
...............................................................................
Generators.tests.cpp:<line number>: PASSED:
REQUIRE( 4u * i > str.size() )
REQUIRE( 4u * static_cast<std::size_t>(i) > str.size() )
with expansion:
4 > 3
@ -5490,7 +5490,7 @@ Generators.tests.cpp:<line number>
...............................................................................
Generators.tests.cpp:<line number>: PASSED:
REQUIRE( 4u * i > str.size() )
REQUIRE( 4u * static_cast<std::size_t>(i) > str.size() )
with expansion:
8 > 1
@ -5502,7 +5502,7 @@ Generators.tests.cpp:<line number>
...............................................................................
Generators.tests.cpp:<line number>: PASSED:
REQUIRE( 4u * i > str.size() )
REQUIRE( 4u * static_cast<std::size_t>(i) > str.size() )
with expansion:
8 > 2
@ -5514,7 +5514,7 @@ Generators.tests.cpp:<line number>
...............................................................................
Generators.tests.cpp:<line number>: PASSED:
REQUIRE( 4u * i > str.size() )
REQUIRE( 4u * static_cast<std::size_t>(i) > str.size() )
with expansion:
8 > 3
@ -5562,7 +5562,7 @@ Generators.tests.cpp:<line number>
...............................................................................
Generators.tests.cpp:<line number>: PASSED:
REQUIRE( 4u * i > str.size() )
REQUIRE( 4u * static_cast<std::size_t>(i) > str.size() )
with expansion:
12 > 1
@ -5574,7 +5574,7 @@ Generators.tests.cpp:<line number>
...............................................................................
Generators.tests.cpp:<line number>: PASSED:
REQUIRE( 4u * i > str.size() )
REQUIRE( 4u * static_cast<std::size_t>(i) > str.size() )
with expansion:
12 > 2
@ -5586,7 +5586,7 @@ Generators.tests.cpp:<line number>
...............................................................................
Generators.tests.cpp:<line number>: PASSED:
REQUIRE( 4u * i > str.size() )
REQUIRE( 4u * static_cast<std::size_t>(i) > str.size() )
with expansion:
12 > 3

View File

@ -629,7 +629,7 @@ ok {test-number} - b, Contains(0, close_enough) for: { 0, 1, 2 } contains elemen
# Basic use of the Contains range matcher
ok {test-number} - c, !Contains(0, close_enough) for: { 4, 5, 6 } not contains element 0
# Basic use of the Contains range matcher
ok {test-number} - a, Contains(4, [](auto&& lhs, size_t sz) { return lhs.size() == sz; }) for: { "abc", "abcd", "abcde" } contains element 4
ok {test-number} - a, Contains(4u, [](auto&& lhs, size_t sz) { return lhs.size() == sz; }) for: { "abc", "abcd", "abcde" } contains element 4
# Basic use of the Contains range matcher
ok {test-number} - in, Contains(1) for: { 1, 2, 3, 4, 5 } contains element 1
# Basic use of the Contains range matcher
@ -1341,11 +1341,11 @@ ok {test-number} - j < i for: -2 < 1
# Generators -- simple
ok {test-number} - j < i for: -1 < 1
# Generators -- simple
ok {test-number} - 4u * i > str.size() for: 4 > 1
ok {test-number} - 4u * static_cast<std::size_t>(i) > str.size() for: 4 > 1
# Generators -- simple
ok {test-number} - 4u * i > str.size() for: 4 > 2
ok {test-number} - 4u * static_cast<std::size_t>(i) > str.size() for: 4 > 2
# Generators -- simple
ok {test-number} - 4u * i > str.size() for: 4 > 3
ok {test-number} - 4u * static_cast<std::size_t>(i) > str.size() for: 4 > 3
# Generators -- simple
ok {test-number} - j < i for: -3 < 2
# Generators -- simple
@ -1353,11 +1353,11 @@ ok {test-number} - j < i for: -2 < 2
# Generators -- simple
ok {test-number} - j < i for: -1 < 2
# Generators -- simple
ok {test-number} - 4u * i > str.size() for: 8 > 1
ok {test-number} - 4u * static_cast<std::size_t>(i) > str.size() for: 8 > 1
# Generators -- simple
ok {test-number} - 4u * i > str.size() for: 8 > 2
ok {test-number} - 4u * static_cast<std::size_t>(i) > str.size() for: 8 > 2
# Generators -- simple
ok {test-number} - 4u * i > str.size() for: 8 > 3
ok {test-number} - 4u * static_cast<std::size_t>(i) > str.size() for: 8 > 3
# Generators -- simple
ok {test-number} - j < i for: -3 < 3
# Generators -- simple
@ -1365,11 +1365,11 @@ ok {test-number} - j < i for: -2 < 3
# Generators -- simple
ok {test-number} - j < i for: -1 < 3
# Generators -- simple
ok {test-number} - 4u * i > str.size() for: 12 > 1
ok {test-number} - 4u * static_cast<std::size_t>(i) > str.size() for: 12 > 1
# Generators -- simple
ok {test-number} - 4u * i > str.size() for: 12 > 2
ok {test-number} - 4u * static_cast<std::size_t>(i) > str.size() for: 12 > 2
# Generators -- simple
ok {test-number} - 4u * i > str.size() for: 12 > 3
ok {test-number} - 4u * static_cast<std::size_t>(i) > str.size() for: 12 > 3
# Generators internals
ok {test-number} - gen.get() == 123 for: 123 == 123
# Generators internals

View File

@ -627,7 +627,7 @@ ok {test-number} - b, Contains(0, close_enough) for: { 0, 1, 2 } contains elemen
# Basic use of the Contains range matcher
ok {test-number} - c, !Contains(0, close_enough) for: { 4, 5, 6 } not contains element 0
# Basic use of the Contains range matcher
ok {test-number} - a, Contains(4, [](auto&& lhs, size_t sz) { return lhs.size() == sz; }) for: { "abc", "abcd", "abcde" } contains element 4
ok {test-number} - a, Contains(4u, [](auto&& lhs, size_t sz) { return lhs.size() == sz; }) for: { "abc", "abcd", "abcde" } contains element 4
# Basic use of the Contains range matcher
ok {test-number} - in, Contains(1) for: { 1, 2, 3, 4, 5 } contains element 1
# Basic use of the Contains range matcher
@ -1339,11 +1339,11 @@ ok {test-number} - j < i for: -2 < 1
# Generators -- simple
ok {test-number} - j < i for: -1 < 1
# Generators -- simple
ok {test-number} - 4u * i > str.size() for: 4 > 1
ok {test-number} - 4u * static_cast<std::size_t>(i) > str.size() for: 4 > 1
# Generators -- simple
ok {test-number} - 4u * i > str.size() for: 4 > 2
ok {test-number} - 4u * static_cast<std::size_t>(i) > str.size() for: 4 > 2
# Generators -- simple
ok {test-number} - 4u * i > str.size() for: 4 > 3
ok {test-number} - 4u * static_cast<std::size_t>(i) > str.size() for: 4 > 3
# Generators -- simple
ok {test-number} - j < i for: -3 < 2
# Generators -- simple
@ -1351,11 +1351,11 @@ ok {test-number} - j < i for: -2 < 2
# Generators -- simple
ok {test-number} - j < i for: -1 < 2
# Generators -- simple
ok {test-number} - 4u * i > str.size() for: 8 > 1
ok {test-number} - 4u * static_cast<std::size_t>(i) > str.size() for: 8 > 1
# Generators -- simple
ok {test-number} - 4u * i > str.size() for: 8 > 2
ok {test-number} - 4u * static_cast<std::size_t>(i) > str.size() for: 8 > 2
# Generators -- simple
ok {test-number} - 4u * i > str.size() for: 8 > 3
ok {test-number} - 4u * static_cast<std::size_t>(i) > str.size() for: 8 > 3
# Generators -- simple
ok {test-number} - j < i for: -3 < 3
# Generators -- simple
@ -1363,11 +1363,11 @@ ok {test-number} - j < i for: -2 < 3
# Generators -- simple
ok {test-number} - j < i for: -1 < 3
# Generators -- simple
ok {test-number} - 4u * i > str.size() for: 12 > 1
ok {test-number} - 4u * static_cast<std::size_t>(i) > str.size() for: 12 > 1
# Generators -- simple
ok {test-number} - 4u * i > str.size() for: 12 > 2
ok {test-number} - 4u * static_cast<std::size_t>(i) > str.size() for: 12 > 2
# Generators -- simple
ok {test-number} - 4u * i > str.size() for: 12 > 3
ok {test-number} - 4u * static_cast<std::size_t>(i) > str.size() for: 12 > 3
# Generators internals
ok {test-number} - gen.get() == 123 for: 123 == 123
# Generators internals

View File

@ -2774,7 +2774,7 @@ Approx( 1.23399996757507324 )
<Section name="Different element type, custom comparisons" filename="tests/<exe-name>/UsageTests/MatchersRanges.tests.cpp" >
<Expression success="true" type="REQUIRE_THAT" filename="tests/<exe-name>/UsageTests/MatchersRanges.tests.cpp" >
<Original>
a, Contains(4, [](auto&amp;&amp; lhs, size_t sz) { return lhs.size() == sz; })
a, Contains(4u, [](auto&amp;&amp; lhs, size_t sz) { return lhs.size() == sz; })
</Original>
<Expanded>
{ "abc", "abcd", "abcde" } contains element 4
@ -6125,7 +6125,7 @@ Approx( 1.30000000000000004 )
<Section name="two" filename="tests/<exe-name>/UsageTests/Generators.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/UsageTests/Generators.tests.cpp" >
<Original>
4u * i > str.size()
4u * static_cast&lt;std::size_t>(i) > str.size()
</Original>
<Expanded>
4 > 1
@ -6136,7 +6136,7 @@ Approx( 1.30000000000000004 )
<Section name="two" filename="tests/<exe-name>/UsageTests/Generators.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/UsageTests/Generators.tests.cpp" >
<Original>
4u * i > str.size()
4u * static_cast&lt;std::size_t>(i) > str.size()
</Original>
<Expanded>
4 > 2
@ -6147,7 +6147,7 @@ Approx( 1.30000000000000004 )
<Section name="two" filename="tests/<exe-name>/UsageTests/Generators.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/UsageTests/Generators.tests.cpp" >
<Original>
4u * i > str.size()
4u * static_cast&lt;std::size_t>(i) > str.size()
</Original>
<Expanded>
4 > 3
@ -6191,7 +6191,7 @@ Approx( 1.30000000000000004 )
<Section name="two" filename="tests/<exe-name>/UsageTests/Generators.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/UsageTests/Generators.tests.cpp" >
<Original>
4u * i > str.size()
4u * static_cast&lt;std::size_t>(i) > str.size()
</Original>
<Expanded>
8 > 1
@ -6202,7 +6202,7 @@ Approx( 1.30000000000000004 )
<Section name="two" filename="tests/<exe-name>/UsageTests/Generators.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/UsageTests/Generators.tests.cpp" >
<Original>
4u * i > str.size()
4u * static_cast&lt;std::size_t>(i) > str.size()
</Original>
<Expanded>
8 > 2
@ -6213,7 +6213,7 @@ Approx( 1.30000000000000004 )
<Section name="two" filename="tests/<exe-name>/UsageTests/Generators.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/UsageTests/Generators.tests.cpp" >
<Original>
4u * i > str.size()
4u * static_cast&lt;std::size_t>(i) > str.size()
</Original>
<Expanded>
8 > 3
@ -6257,7 +6257,7 @@ Approx( 1.30000000000000004 )
<Section name="two" filename="tests/<exe-name>/UsageTests/Generators.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/UsageTests/Generators.tests.cpp" >
<Original>
4u * i > str.size()
4u * static_cast&lt;std::size_t>(i) > str.size()
</Original>
<Expanded>
12 > 1
@ -6268,7 +6268,7 @@ Approx( 1.30000000000000004 )
<Section name="two" filename="tests/<exe-name>/UsageTests/Generators.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/UsageTests/Generators.tests.cpp" >
<Original>
4u * i > str.size()
4u * static_cast&lt;std::size_t>(i) > str.size()
</Original>
<Expanded>
12 > 2
@ -6279,7 +6279,7 @@ Approx( 1.30000000000000004 )
<Section name="two" filename="tests/<exe-name>/UsageTests/Generators.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/UsageTests/Generators.tests.cpp" >
<Original>
4u * i > str.size()
4u * static_cast&lt;std::size_t>(i) > str.size()
</Original>
<Expanded>
12 > 3

View File

@ -2774,7 +2774,7 @@ Approx( 1.23399996757507324 )
<Section name="Different element type, custom comparisons" filename="tests/<exe-name>/UsageTests/MatchersRanges.tests.cpp" >
<Expression success="true" type="REQUIRE_THAT" filename="tests/<exe-name>/UsageTests/MatchersRanges.tests.cpp" >
<Original>
a, Contains(4, [](auto&amp;&amp; lhs, size_t sz) { return lhs.size() == sz; })
a, Contains(4u, [](auto&amp;&amp; lhs, size_t sz) { return lhs.size() == sz; })
</Original>
<Expanded>
{ "abc", "abcd", "abcde" } contains element 4
@ -6125,7 +6125,7 @@ Approx( 1.30000000000000004 )
<Section name="two" filename="tests/<exe-name>/UsageTests/Generators.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/UsageTests/Generators.tests.cpp" >
<Original>
4u * i > str.size()
4u * static_cast&lt;std::size_t>(i) > str.size()
</Original>
<Expanded>
4 > 1
@ -6136,7 +6136,7 @@ Approx( 1.30000000000000004 )
<Section name="two" filename="tests/<exe-name>/UsageTests/Generators.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/UsageTests/Generators.tests.cpp" >
<Original>
4u * i > str.size()
4u * static_cast&lt;std::size_t>(i) > str.size()
</Original>
<Expanded>
4 > 2
@ -6147,7 +6147,7 @@ Approx( 1.30000000000000004 )
<Section name="two" filename="tests/<exe-name>/UsageTests/Generators.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/UsageTests/Generators.tests.cpp" >
<Original>
4u * i > str.size()
4u * static_cast&lt;std::size_t>(i) > str.size()
</Original>
<Expanded>
4 > 3
@ -6191,7 +6191,7 @@ Approx( 1.30000000000000004 )
<Section name="two" filename="tests/<exe-name>/UsageTests/Generators.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/UsageTests/Generators.tests.cpp" >
<Original>
4u * i > str.size()
4u * static_cast&lt;std::size_t>(i) > str.size()
</Original>
<Expanded>
8 > 1
@ -6202,7 +6202,7 @@ Approx( 1.30000000000000004 )
<Section name="two" filename="tests/<exe-name>/UsageTests/Generators.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/UsageTests/Generators.tests.cpp" >
<Original>
4u * i > str.size()
4u * static_cast&lt;std::size_t>(i) > str.size()
</Original>
<Expanded>
8 > 2
@ -6213,7 +6213,7 @@ Approx( 1.30000000000000004 )
<Section name="two" filename="tests/<exe-name>/UsageTests/Generators.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/UsageTests/Generators.tests.cpp" >
<Original>
4u * i > str.size()
4u * static_cast&lt;std::size_t>(i) > str.size()
</Original>
<Expanded>
8 > 3
@ -6257,7 +6257,7 @@ Approx( 1.30000000000000004 )
<Section name="two" filename="tests/<exe-name>/UsageTests/Generators.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/UsageTests/Generators.tests.cpp" >
<Original>
4u * i > str.size()
4u * static_cast&lt;std::size_t>(i) > str.size()
</Original>
<Expanded>
12 > 1
@ -6268,7 +6268,7 @@ Approx( 1.30000000000000004 )
<Section name="two" filename="tests/<exe-name>/UsageTests/Generators.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/UsageTests/Generators.tests.cpp" >
<Original>
4u * i > str.size()
4u * static_cast&lt;std::size_t>(i) > str.size()
</Original>
<Expanded>
12 > 2
@ -6279,7 +6279,7 @@ Approx( 1.30000000000000004 )
<Section name="two" filename="tests/<exe-name>/UsageTests/Generators.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/UsageTests/Generators.tests.cpp" >
<Original>
4u * i > str.size()
4u * static_cast&lt;std::size_t>(i) > str.size()
</Original>
<Expanded>
12 > 3

View File

@ -26,8 +26,8 @@ TEST_CASE("Sharding Function", "[approvals]") {
{7, {1, 1, 1, 1, 1, 1, 1}},
};
auto shardCount = GENERATE(range(1, 7));
auto shardIndex = GENERATE_COPY(filter([=](int i) { return i < shardCount; }, range(0, 6)));
auto shardCount = GENERATE(range(1ul, 7ul));
auto shardIndex = GENERATE_COPY(filter([=](std::size_t i) { return i < shardCount; }, range(0ul, 6ul)));
std::vector<int> result = Catch::createShard(testContainer, shardCount, shardIndex);
@ -35,7 +35,7 @@ TEST_CASE("Sharding Function", "[approvals]") {
REQUIRE(result.size() == sizes[shardIndex]);
std::size_t startIndex = 0;
for(int i = 0; i < shardIndex; i++) {
for(std::size_t i = 0; i < shardIndex; i++) {
startIndex += sizes[i];
}

View File

@ -12,6 +12,7 @@
#include <sstream>
using Catch::TextFlow::Column;
using Catch::TextFlow::AnsiSkippingString;
namespace {
static std::string as_written(Column const& c) {
@ -198,3 +199,202 @@ TEST_CASE( "#1400 - TextFlow::Column wrapping would sometimes duplicate words",
" in \n"
" convallis posuere, libero nisi ultricies orci, nec lobortis.");
}
TEST_CASE( "TextFlow::AnsiSkippingString skips ansi sequences",
"[TextFlow][ansiskippingstring][approvals]" ) {
SECTION("basic string") {
std::string text = "a\033[38;2;98;174;239mb\033[38mc\033[0md\033[me";
AnsiSkippingString str(text);
SECTION( "iterates forward" ) {
auto it = str.begin();
CHECK(*it == 'a');
++it;
CHECK(*it == 'b');
++it;
CHECK(*it == 'c');
++it;
CHECK(*it == 'd');
++it;
CHECK(*it == 'e');
++it;
CHECK(it == str.end());
}
SECTION( "iterates backwards" ) {
auto it = str.end();
--it;
CHECK(*it == 'e');
--it;
CHECK(*it == 'd');
--it;
CHECK(*it == 'c');
--it;
CHECK(*it == 'b');
--it;
CHECK(*it == 'a');
CHECK(it == str.begin());
}
}
SECTION( "ansi escape sequences at the start" ) {
std::string text = "\033[38;2;98;174;239ma\033[38;2;98;174;239mb\033[38mc\033[0md\033[me";
AnsiSkippingString str(text);
auto it = str.begin();
CHECK(*it == 'a');
++it;
CHECK(*it == 'b');
++it;
CHECK(*it == 'c');
++it;
CHECK(*it == 'd');
++it;
CHECK(*it == 'e');
++it;
CHECK(it == str.end());
--it;
CHECK(*it == 'e');
--it;
CHECK(*it == 'd');
--it;
CHECK(*it == 'c');
--it;
CHECK(*it == 'b');
--it;
CHECK(*it == 'a');
CHECK(it == str.begin());
}
SECTION( "ansi escape sequences at the end" ) {
std::string text = "a\033[38;2;98;174;239mb\033[38mc\033[0md\033[me\033[38;2;98;174;239m";
AnsiSkippingString str(text);
auto it = str.begin();
CHECK(*it == 'a');
++it;
CHECK(*it == 'b');
++it;
CHECK(*it == 'c');
++it;
CHECK(*it == 'd');
++it;
CHECK(*it == 'e');
++it;
CHECK(it == str.end());
--it;
CHECK(*it == 'e');
--it;
CHECK(*it == 'd');
--it;
CHECK(*it == 'c');
--it;
CHECK(*it == 'b');
--it;
CHECK(*it == 'a');
CHECK(it == str.begin());
}
SECTION( "skips consecutive escapes" ) {
std::string text = "\033[38;2;98;174;239m\033[38;2;98;174;239ma\033[38;2;98;174;239mb\033[38m\033[38m\033[38mc\033[0md\033[me";
AnsiSkippingString str(text);
auto it = str.begin();
CHECK(*it == 'a');
++it;
CHECK(*it == 'b');
++it;
CHECK(*it == 'c');
++it;
CHECK(*it == 'd');
++it;
CHECK(*it == 'e');
++it;
CHECK(it == str.end());
--it;
CHECK(*it == 'e');
--it;
CHECK(*it == 'd');
--it;
CHECK(*it == 'c');
--it;
CHECK(*it == 'b');
--it;
CHECK(*it == 'a');
CHECK(it == str.begin());
}
SECTION( "handles incomplete ansi sequences" ) {
std::string text = "a\033[b\033[30c\033[30;d\033[30;2e";
AnsiSkippingString str(text);
CHECK(std::string(str.begin(), str.end()) == text);
}
}
TEST_CASE( "TextFlow::AnsiSkippingString computes the size properly",
"[TextFlow][ansiskippingstring][approvals]" ) {
std::string text = "\033[38;2;98;174;239m\033[38;2;98;174;239ma\033[38;2;98;174;239mb\033[38m\033[38m\033[38mc\033[0md\033[me";
AnsiSkippingString str(text);
CHECK(str.size() == 5);
}
TEST_CASE( "TextFlow::AnsiSkippingString substrings properly",
"[TextFlow][ansiskippingstring][approvals]" ) {
SECTION("basic test") {
std::string text = "a\033[38;2;98;174;239mb\033[38mc\033[0md\033[me";
AnsiSkippingString str(text);
auto a = str.begin();
auto b = str.begin();
++b;
++b;
CHECK(str.substring(a, b) == "a\033[38;2;98;174;239mb\033[38m");
++a;
++b;
CHECK(str.substring(a, b) == "b\033[38mc\033[0m");
CHECK(str.substring(a, str.end()) == "b\033[38mc\033[0md\033[me");
CHECK(str.substring(str.begin(), str.end()) == text);
}
SECTION("escapes at the start") {
std::string text = "\033[38;2;98;174;239m\033[38;2;98;174;239ma\033[38;2;98;174;239mb\033[38m\033[38m\033[38mc\033[0md\033[me";
AnsiSkippingString str(text);
auto a = str.begin();
auto b = str.begin();
++b;
++b;
CHECK(str.substring(a, b) == "\033[38;2;98;174;239m\033[38;2;98;174;239ma\033[38;2;98;174;239mb\033[38m\033[38m\033[38m");
++a;
++b;
CHECK(str.substring(a, b) == "b\033[38m\033[38m\033[38mc\033[0m");
CHECK(str.substring(a, str.end()) == "b\033[38m\033[38m\033[38mc\033[0md\033[me");
CHECK(str.substring(str.begin(), str.end()) == text);
}
SECTION("escapes at the end") {
std::string text = "a\033[38;2;98;174;239mb\033[38mc\033[0md\033[me\033[38m";
AnsiSkippingString str(text);
auto a = str.begin();
auto b = str.begin();
++b;
++b;
CHECK(str.substring(a, b) == "a\033[38;2;98;174;239mb\033[38m");
++a;
++b;
CHECK(str.substring(a, b) == "b\033[38mc\033[0m");
CHECK(str.substring(a, str.end()) == "b\033[38mc\033[0md\033[me\033[38m");
CHECK(str.substring(str.begin(), str.end()) == text);
}
}
TEST_CASE( "TextFlow::Column skips ansi escape sequences",
"[TextFlow][column][approvals]" ) {
std::string text = "\033[38;2;98;174;239m\033[38;2;198;120;221mThe quick brown \033[38;2;198;120;221mfox jumped over the lazy dog\033[0m";
Column col(text);
SECTION( "width=20" ) {
col.width( 20 );
REQUIRE( as_written( col ) == "\033[38;2;98;174;239m\033[38;2;198;120;221mThe quick brown \033[38;2;198;120;221mfox\n"
"jumped over the lazy\n"
"dog\033[0m" );
}
SECTION( "width=80" ) {
col.width( 80 );
REQUIRE( as_written( col ) == text );
}
}

View File

@ -62,8 +62,8 @@ TEST_CASE("Benchmark containers", "[!benchmark]") {
// test optimizer control
BENCHMARK("Add up a vector's content") {
uint64_t add = 0;
for (int i = 0; i < size; ++i)
add += v[i];
for (std::size_t i = 0; i < size; ++i)
add += static_cast<std::size_t>(v[i]);
return add;
};
@ -86,7 +86,7 @@ TEST_CASE("Benchmark containers", "[!benchmark]") {
v = std::vector<int>();
v.resize(size);
for (int i = 0; i < size; ++i)
v[i] = i;
v[static_cast<std::size_t>(i)] = i;
};
REQUIRE(v.size() == size);
@ -116,7 +116,7 @@ TEST_CASE("Benchmark containers", "[!benchmark]") {
BENCHMARK("Fill vector indexed", benchmarkIndex) {
v = std::vector<int>();
v.resize(size);
for (int i = 0; i < size; ++i)
for (std::size_t i = 0; i < size; ++i)
v[i] = benchmarkIndex;
runs = benchmarkIndex;
};
@ -132,7 +132,7 @@ TEST_CASE("Benchmark containers", "[!benchmark]") {
BENCHMARK("Fill vector generated") {
v = std::vector<int>();
v.resize(size);
for (int i = 0; i < size; ++i)
for (std::size_t i = 0; i < size; ++i)
v[i] = generated;
};
for (int val : v) {
@ -142,15 +142,15 @@ TEST_CASE("Benchmark containers", "[!benchmark]") {
SECTION("construct and destroy example") {
BENCHMARK_ADVANCED("construct")(Catch::Benchmark::Chronometer meter) {
std::vector<Catch::Benchmark::storage_for<std::string>> storage(meter.runs());
meter.measure([&](int i) { storage[i].construct("thing"); });
std::vector<Catch::Benchmark::storage_for<std::string>> storage(static_cast<std::size_t>(meter.runs()));
meter.measure([&](int i) { storage[static_cast<std::size_t>(i)].construct("thing"); });
};
BENCHMARK_ADVANCED("destroy")(Catch::Benchmark::Chronometer meter) {
std::vector<Catch::Benchmark::destructable_object<std::string>> storage(meter.runs());
std::vector<Catch::Benchmark::destructable_object<std::string>> storage(static_cast<std::size_t>(meter.runs()));
for(auto&& o : storage)
o.construct("thing");
meter.measure([&](int i) { storage[i].destruct(); });
meter.measure([&](int i) { storage[static_cast<std::size_t>(i)].destruct(); });
};
}
}
@ -166,8 +166,8 @@ TEST_CASE("Skip benchmark macros", "[!benchmark]") {
std::size_t counter{0};
BENCHMARK_ADVANCED("construct vector")(Catch::Benchmark::Chronometer meter) {
std::vector<Catch::Benchmark::storage_for<std::string>> storage(meter.runs());
meter.measure([&](int i) { storage[i].construct("thing"); counter++; });
std::vector<Catch::Benchmark::storage_for<std::string>> storage(static_cast<std::size_t>(meter.runs()));
meter.measure([&](int i) { storage[static_cast<std::size_t>(i)].construct("thing"); counter++; });
};
REQUIRE(counter == 0);
}

View File

@ -26,7 +26,7 @@ TEST_CASE("Generators -- simple", "[generators]") {
SECTION("two") {
// You can also explicitly set type for generators via Catch::Generators::as
auto str = GENERATE(as<std::string>{}, "a", "bb", "ccc");
REQUIRE(4u * i > str.size());
REQUIRE(4u * static_cast<std::size_t>(i) > str.size());
}
}

View File

@ -75,7 +75,7 @@ TEST_CASE("Basic use of the Contains range matcher", "[matchers][templated][cont
SECTION("Different element type, custom comparisons") {
std::array<std::string, 3> a{ { "abc", "abcd" , "abcde" } };
REQUIRE_THAT(a, Contains(4, [](auto&& lhs, size_t sz) {
REQUIRE_THAT(a, Contains(4u, [](auto&& lhs, size_t sz) {
return lhs.size() == sz;
}));
}
@ -914,4 +914,4 @@ TEST_CASE( "Type conversions of RangeEquals and similar",
UnorderedRangeEquals( array_a_plus_1, close_enough ) );
}
}
}
}