mirror of
https://github.com/catchorg/Catch2.git
synced 2024-11-22 13:26:10 +01:00
Introduced ReusableStringStream and removed all uses of std::ostringstream from the main path
ReusableStringStream holds a std::ostringstream internally, but only exposes the ostream interface. It caches a pool of ostringstreams in a vector which is currently global, but will be made thread-local. Altogether this should enable both runtime and compile-time benefits. although more work is needed to realise the compile time opportunities.
This commit is contained in:
parent
868e125d49
commit
56e1075613
@ -36,9 +36,9 @@ namespace Detail {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string Approx::toString() const {
|
std::string Approx::toString() const {
|
||||||
std::ostringstream oss;
|
ReusableStringStream rss;
|
||||||
oss << "Approx( " << ::Catch::Detail::stringify( m_value ) << " )";
|
rss << "Approx( " << ::Catch::Detail::stringify( m_value ) << " )";
|
||||||
return oss.str();
|
return rss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Approx::equalityComparisonImpl(const double other) const {
|
bool Approx::equalityComparisonImpl(const double other) const {
|
||||||
|
@ -8,10 +8,10 @@
|
|||||||
#ifndef TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED
|
#ifndef TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED
|
||||||
#define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED
|
#define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED
|
||||||
|
|
||||||
#include "catch_enforce.h"
|
|
||||||
#include "catch_tostring.h"
|
#include "catch_tostring.h"
|
||||||
|
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
namespace Detail {
|
namespace Detail {
|
||||||
@ -83,9 +83,12 @@ namespace Detail {
|
|||||||
template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
|
template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
|
||||||
Approx& epsilon( T const& newEpsilon ) {
|
Approx& epsilon( T const& newEpsilon ) {
|
||||||
double epsilonAsDouble = static_cast<double>(newEpsilon);
|
double epsilonAsDouble = static_cast<double>(newEpsilon);
|
||||||
CATCH_ENFORCE(epsilonAsDouble >= 0 && epsilonAsDouble <= 1.0,
|
if( epsilonAsDouble < 0 || epsilonAsDouble > 1.0 ) {
|
||||||
"Invalid Approx::epsilon: " << epsilonAsDouble
|
throw std::domain_error
|
||||||
<< ", Approx::epsilon has to be between 0 and 1");
|
( "Invalid Approx::epsilon: " +
|
||||||
|
Catch::Detail::stringify( epsilonAsDouble ) +
|
||||||
|
", Approx::epsilon has to be between 0 and 1" );
|
||||||
|
}
|
||||||
m_epsilon = epsilonAsDouble;
|
m_epsilon = epsilonAsDouble;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@ -93,9 +96,13 @@ namespace Detail {
|
|||||||
template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
|
template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
|
||||||
Approx& margin( T const& newMargin ) {
|
Approx& margin( T const& newMargin ) {
|
||||||
double marginAsDouble = static_cast<double>(newMargin);
|
double marginAsDouble = static_cast<double>(newMargin);
|
||||||
CATCH_ENFORCE(marginAsDouble >= 0,
|
if( marginAsDouble < 0 ) {
|
||||||
"Invalid Approx::margin: " << marginAsDouble
|
throw std::domain_error
|
||||||
<< ", Approx::Margin has to be non-negative.");
|
( "Invalid Approx::margin: " +
|
||||||
|
Catch::Detail::stringify( marginAsDouble ) +
|
||||||
|
", Approx::Margin has to be non-negative." );
|
||||||
|
|
||||||
|
}
|
||||||
m_margin = marginAsDouble;
|
m_margin = marginAsDouble;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
@ -17,10 +17,9 @@ namespace Catch {
|
|||||||
|
|
||||||
if( reconstructedExpression.empty() ) {
|
if( reconstructedExpression.empty() ) {
|
||||||
if( lazyExpression ) {
|
if( lazyExpression ) {
|
||||||
// !TBD Use stringstream for now, but rework above to pass stream in
|
ReusableStringStream rss;
|
||||||
std::ostringstream oss;
|
rss << lazyExpression;
|
||||||
oss << lazyExpression;
|
reconstructedExpression = rss.str();
|
||||||
reconstructedExpression = oss.str();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return reconstructedExpression;
|
return reconstructedExpression;
|
||||||
|
@ -23,6 +23,8 @@
|
|||||||
#include "catch_debugger.h"
|
#include "catch_debugger.h"
|
||||||
#include "catch_windows_h_proxy.h"
|
#include "catch_windows_h_proxy.h"
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
@ -8,12 +8,13 @@
|
|||||||
#define TWOBLUECUBES_CATCH_ENFORCE_H_INCLUDED
|
#define TWOBLUECUBES_CATCH_ENFORCE_H_INCLUDED
|
||||||
|
|
||||||
#include "catch_common.h"
|
#include "catch_common.h"
|
||||||
|
#include "catch_stream.h"
|
||||||
|
|
||||||
#include <sstream>
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
#include <iosfwd>
|
||||||
|
|
||||||
#define CATCH_PREPARE_EXCEPTION( type, msg ) \
|
#define CATCH_PREPARE_EXCEPTION( type, msg ) \
|
||||||
type( static_cast<std::ostringstream&&>( std::ostringstream() << msg ).str() )
|
type( static_cast<std::ostringstream&&>( Catch::ReusableStringStream().get() << msg ).str() )
|
||||||
#define CATCH_INTERNAL_ERROR( msg ) \
|
#define CATCH_INTERNAL_ERROR( msg ) \
|
||||||
throw CATCH_PREPARE_EXCEPTION( std::logic_error, CATCH_INTERNAL_LINEINFO << ": Internal Catch error: " << msg);
|
throw CATCH_PREPARE_EXCEPTION( std::logic_error, CATCH_INTERNAL_LINEINFO << ": Internal Catch error: " << msg);
|
||||||
#define CATCH_ERROR( msg ) \
|
#define CATCH_ERROR( msg ) \
|
||||||
|
@ -115,13 +115,14 @@ namespace Catch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for( auto const& tagCount : tagCounts ) {
|
for( auto const& tagCount : tagCounts ) {
|
||||||
std::ostringstream oss;
|
ReusableStringStream rss;
|
||||||
oss << " " << std::setw(2) << tagCount.second.count << " ";
|
rss << " " << std::setw(2) << tagCount.second.count << " ";
|
||||||
|
auto str = rss.str();
|
||||||
auto wrapper = Column( tagCount.second.all() )
|
auto wrapper = Column( tagCount.second.all() )
|
||||||
.initialIndent( 0 )
|
.initialIndent( 0 )
|
||||||
.indent( oss.str().size() )
|
.indent( str.size() )
|
||||||
.width( CATCH_CONFIG_CONSOLE_WIDTH-10 );
|
.width( CATCH_CONFIG_CONSOLE_WIDTH-10 );
|
||||||
Catch::cout() << oss.str() << wrapper << '\n';
|
Catch::cout() << str << wrapper << '\n';
|
||||||
}
|
}
|
||||||
Catch::cout() << pluralise( tagCounts.size(), "tag" ) << '\n' << std::endl;
|
Catch::cout() << pluralise( tagCounts.size(), "tag" ) << '\n' << std::endl;
|
||||||
return tagCounts.size();
|
return tagCounts.size();
|
||||||
|
@ -9,9 +9,9 @@
|
|||||||
#define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED
|
#define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <sstream>
|
|
||||||
#include "catch_result_type.h"
|
#include "catch_result_type.h"
|
||||||
#include "catch_common.h"
|
#include "catch_common.h"
|
||||||
|
#include "catch_stream.h"
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
@ -40,8 +40,7 @@ namespace Catch {
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
// !TBD reuse a global/ thread-local stream
|
ReusableStringStream m_stream;
|
||||||
std::ostringstream m_stream;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MessageBuilder : MessageStream {
|
struct MessageBuilder : MessageStream {
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
@ -13,7 +14,7 @@ namespace Catch {
|
|||||||
: m_stream(stream),
|
: m_stream(stream),
|
||||||
m_prevBuf(stream.rdbuf()),
|
m_prevBuf(stream.rdbuf()),
|
||||||
m_targetString(targetString) {
|
m_targetString(targetString) {
|
||||||
stream.rdbuf(m_oss.rdbuf());
|
stream.rdbuf(m_oss.get().rdbuf());
|
||||||
}
|
}
|
||||||
|
|
||||||
StreamRedirect::~StreamRedirect() {
|
StreamRedirect::~StreamRedirect() {
|
||||||
@ -24,8 +25,8 @@ namespace Catch {
|
|||||||
StdErrRedirect::StdErrRedirect(std::string & targetString)
|
StdErrRedirect::StdErrRedirect(std::string & targetString)
|
||||||
:m_cerrBuf(cerr().rdbuf()), m_clogBuf(clog().rdbuf()),
|
:m_cerrBuf(cerr().rdbuf()), m_clogBuf(clog().rdbuf()),
|
||||||
m_targetString(targetString) {
|
m_targetString(targetString) {
|
||||||
cerr().rdbuf(m_oss.rdbuf());
|
cerr().rdbuf(m_oss.get().rdbuf());
|
||||||
clog().rdbuf(m_oss.rdbuf());
|
clog().rdbuf(m_oss.get().rdbuf());
|
||||||
}
|
}
|
||||||
|
|
||||||
StdErrRedirect::~StdErrRedirect() {
|
StdErrRedirect::~StdErrRedirect() {
|
||||||
|
@ -32,13 +32,12 @@ namespace Catch {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
StreamRedirect(std::ostream& stream, std::string& targetString);
|
StreamRedirect(std::ostream& stream, std::string& targetString);
|
||||||
|
|
||||||
~StreamRedirect();
|
~StreamRedirect();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::ostream& m_stream;
|
std::ostream& m_stream;
|
||||||
std::streambuf* m_prevBuf;
|
std::streambuf* m_prevBuf;
|
||||||
std::ostringstream m_oss;
|
ReusableStringStream m_oss;
|
||||||
std::string& m_targetString;
|
std::string& m_targetString;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -52,7 +51,7 @@ namespace Catch {
|
|||||||
private:
|
private:
|
||||||
std::streambuf* m_cerrBuf;
|
std::streambuf* m_cerrBuf;
|
||||||
std::streambuf* m_clogBuf;
|
std::streambuf* m_clogBuf;
|
||||||
std::ostringstream m_oss;
|
ReusableStringStream m_oss;
|
||||||
std::string& m_targetString;
|
std::string& m_targetString;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -13,10 +13,16 @@
|
|||||||
#include "catch_debug_console.h"
|
#include "catch_debug_console.h"
|
||||||
#include "catch_stringref.h"
|
#include "catch_stringref.h"
|
||||||
|
|
||||||
#include <stdexcept>
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#if defined(__clang__)
|
||||||
|
# pragma clang diagnostic push
|
||||||
|
# pragma clang diagnostic ignored "-Wexit-time-destructors"
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
@ -132,18 +138,64 @@ namespace Catch {
|
|||||||
return new detail::FileStream( filename );
|
return new detail::FileStream( filename );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// This class encapsulates the idea of a pool of ostringstreams that can be reused.
|
||||||
|
struct StringStreams {
|
||||||
|
std::vector<std::unique_ptr<std::ostringstream>> m_streams;
|
||||||
|
std::vector<std::size_t> m_unused;
|
||||||
|
std::ostringstream m_referenceStream; // Used for copy state/ flags from
|
||||||
|
|
||||||
|
auto add() -> std::size_t {
|
||||||
|
if( m_unused.empty() ) {
|
||||||
|
m_streams.push_back( std::unique_ptr<std::ostringstream>( new std::ostringstream ) );
|
||||||
|
return m_streams.size()-1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
auto index = m_unused.back();
|
||||||
|
m_unused.pop_back();
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void release( std::size_t index ) {
|
||||||
|
m_streams[index]->copyfmt( m_referenceStream ); // Restore initial flags and other state
|
||||||
|
m_unused.push_back(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
// !TBD: put in TLS
|
||||||
|
static auto instance() -> StringStreams& {
|
||||||
|
static StringStreams s_stringStreams;
|
||||||
|
return s_stringStreams;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
ReusableStringStream::ReusableStringStream()
|
||||||
|
: m_index( StringStreams::instance().add() ),
|
||||||
|
m_oss( StringStreams::instance().m_streams[m_index].get() )
|
||||||
|
{}
|
||||||
|
|
||||||
|
ReusableStringStream::~ReusableStringStream() {
|
||||||
|
static_cast<std::ostringstream*>( m_oss )->str("");
|
||||||
|
m_oss->clear();
|
||||||
|
StringStreams::instance().release( m_index );
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ReusableStringStream::str() const -> std::string {
|
||||||
|
return static_cast<std::ostringstream*>( m_oss )->str();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
#ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement these functions
|
#ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement these functions
|
||||||
std::ostream& cout() {
|
std::ostream& cout() { return std::cout; }
|
||||||
return std::cout;
|
std::ostream& cerr() { return std::cerr; }
|
||||||
}
|
std::ostream& clog() { return std::clog; }
|
||||||
std::ostream& cerr() {
|
|
||||||
return std::cerr;
|
|
||||||
}
|
|
||||||
std::ostream& clog() {
|
|
||||||
return std::clog;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(__clang__)
|
||||||
|
# pragma clang diagnostic pop
|
||||||
|
#endif
|
||||||
|
@ -10,6 +10,8 @@
|
|||||||
#define TWOBLUECUBES_CATCH_STREAM_H_INCLUDED
|
#define TWOBLUECUBES_CATCH_STREAM_H_INCLUDED
|
||||||
|
|
||||||
#include <iosfwd>
|
#include <iosfwd>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <ostream>
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
@ -25,6 +27,23 @@ namespace Catch {
|
|||||||
};
|
};
|
||||||
|
|
||||||
auto makeStream( StringRef const &filename ) -> IStream const*;
|
auto makeStream( StringRef const &filename ) -> IStream const*;
|
||||||
|
|
||||||
|
class ReusableStringStream {
|
||||||
|
std::size_t m_index;
|
||||||
|
std::ostream* m_oss;
|
||||||
|
public:
|
||||||
|
ReusableStringStream();
|
||||||
|
~ReusableStringStream();
|
||||||
|
|
||||||
|
auto str() const -> std::string;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
auto operator << ( T const& value ) -> ReusableStringStream& {
|
||||||
|
*m_oss << value;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
auto get() -> std::ostream& { return *m_oss; }
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // TWOBLUECUBES_CATCH_STREAM_H_INCLUDED
|
#endif // TWOBLUECUBES_CATCH_STREAM_H_INCLUDED
|
||||||
|
@ -10,9 +10,10 @@
|
|||||||
#include "catch_console_colour.h"
|
#include "catch_console_colour.h"
|
||||||
#include "catch_enforce.h"
|
#include "catch_enforce.h"
|
||||||
#include "catch_interfaces_registry_hub.h"
|
#include "catch_interfaces_registry_hub.h"
|
||||||
#include "catch_stream.h"
|
|
||||||
#include "catch_string_manip.h"
|
#include "catch_string_manip.h"
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
TagAliasRegistry::~TagAliasRegistry() {}
|
TagAliasRegistry::~TagAliasRegistry() {}
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#include <cctype>
|
#include <cctype>
|
||||||
#include <exception>
|
#include <exception>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
|
@ -66,9 +66,9 @@ namespace Catch {
|
|||||||
void TestRegistry::registerTest( TestCase const& testCase ) {
|
void TestRegistry::registerTest( TestCase const& testCase ) {
|
||||||
std::string name = testCase.getTestCaseInfo().name;
|
std::string name = testCase.getTestCaseInfo().name;
|
||||||
if( name.empty() ) {
|
if( name.empty() ) {
|
||||||
std::ostringstream oss;
|
ReusableStringStream rss;
|
||||||
oss << "Anonymous test case " << ++m_unnamedCount;
|
rss << "Anonymous test case " << ++m_unnamedCount;
|
||||||
return registerTest( testCase.withName( oss.str() ) );
|
return registerTest( testCase.withName( rss.str() ) );
|
||||||
}
|
}
|
||||||
m_functions.push_back( testCase );
|
m_functions.push_back( testCase );
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
#if defined(__clang__)
|
#if defined(__clang__)
|
||||||
# pragma clang diagnostic push
|
# pragma clang diagnostic push
|
||||||
|
@ -52,22 +52,22 @@ namespace Detail {
|
|||||||
}
|
}
|
||||||
|
|
||||||
unsigned char const *bytes = static_cast<unsigned char const *>(object);
|
unsigned char const *bytes = static_cast<unsigned char const *>(object);
|
||||||
std::ostringstream os;
|
ReusableStringStream rss;
|
||||||
os << "0x" << std::setfill('0') << std::hex;
|
rss << "0x" << std::setfill('0') << std::hex;
|
||||||
for( ; i != end; i += inc )
|
for( ; i != end; i += inc )
|
||||||
os << std::setw(2) << static_cast<unsigned>(bytes[i]);
|
rss << std::setw(2) << static_cast<unsigned>(bytes[i]);
|
||||||
return os.str();
|
return rss.str();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
std::string fpToString( T value, int precision ) {
|
std::string fpToString( T value, int precision ) {
|
||||||
std::ostringstream oss;
|
ReusableStringStream rss;
|
||||||
oss << std::setprecision( precision )
|
rss << std::setprecision( precision )
|
||||||
<< std::fixed
|
<< std::fixed
|
||||||
<< value;
|
<< value;
|
||||||
std::string d = oss.str();
|
std::string d = rss.str();
|
||||||
std::size_t i = d.find_last_not_of( '0' );
|
std::size_t i = d.find_last_not_of( '0' );
|
||||||
if( i != std::string::npos && i != d.size()-1 ) {
|
if( i != std::string::npos && i != d.size()-1 ) {
|
||||||
if( d[i] == '.' )
|
if( d[i] == '.' )
|
||||||
@ -153,12 +153,12 @@ std::string StringMaker<long>::convert(long value) {
|
|||||||
return ::Catch::Detail::stringify(static_cast<long long>(value));
|
return ::Catch::Detail::stringify(static_cast<long long>(value));
|
||||||
}
|
}
|
||||||
std::string StringMaker<long long>::convert(long long value) {
|
std::string StringMaker<long long>::convert(long long value) {
|
||||||
std::ostringstream oss;
|
ReusableStringStream rss;
|
||||||
oss << value;
|
rss << value;
|
||||||
if (value > Detail::hexThreshold) {
|
if (value > Detail::hexThreshold) {
|
||||||
oss << " (0x" << std::hex << value << ')';
|
rss << " (0x" << std::hex << value << ')';
|
||||||
}
|
}
|
||||||
return oss.str();
|
return rss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string StringMaker<unsigned int>::convert(unsigned int value) {
|
std::string StringMaker<unsigned int>::convert(unsigned int value) {
|
||||||
@ -168,12 +168,12 @@ std::string StringMaker<unsigned long>::convert(unsigned long value) {
|
|||||||
return ::Catch::Detail::stringify(static_cast<unsigned long long>(value));
|
return ::Catch::Detail::stringify(static_cast<unsigned long long>(value));
|
||||||
}
|
}
|
||||||
std::string StringMaker<unsigned long long>::convert(unsigned long long value) {
|
std::string StringMaker<unsigned long long>::convert(unsigned long long value) {
|
||||||
std::ostringstream oss;
|
ReusableStringStream rss;
|
||||||
oss << value;
|
rss << value;
|
||||||
if (value > Detail::hexThreshold) {
|
if (value > Detail::hexThreshold) {
|
||||||
oss << " (0x" << std::hex << value << ')';
|
rss << " (0x" << std::hex << value << ')';
|
||||||
}
|
}
|
||||||
return oss.str();
|
return rss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -9,11 +9,11 @@
|
|||||||
#define TWOBLUECUBES_CATCH_TOSTRING_H_INCLUDED
|
#define TWOBLUECUBES_CATCH_TOSTRING_H_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
#include <sstream>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include "catch_stream.h"
|
||||||
|
|
||||||
#ifdef __OBJC__
|
#ifdef __OBJC__
|
||||||
#include "catch_objc_arc.hpp"
|
#include "catch_objc_arc.hpp"
|
||||||
@ -66,9 +66,9 @@ namespace Catch {
|
|||||||
static
|
static
|
||||||
typename std::enable_if<::Catch::Detail::IsStreamInsertable<Fake>::value, std::string>::type
|
typename std::enable_if<::Catch::Detail::IsStreamInsertable<Fake>::value, std::string>::type
|
||||||
convert(const Fake& t) {
|
convert(const Fake& t) {
|
||||||
std::ostringstream sstr;
|
ReusableStringStream rss;
|
||||||
sstr << t;
|
rss << t;
|
||||||
return sstr.str();
|
return rss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Fake = T>
|
template <typename Fake = T>
|
||||||
@ -221,15 +221,15 @@ namespace Catch {
|
|||||||
namespace Detail {
|
namespace Detail {
|
||||||
template<typename InputIterator>
|
template<typename InputIterator>
|
||||||
std::string rangeToString(InputIterator first, InputIterator last) {
|
std::string rangeToString(InputIterator first, InputIterator last) {
|
||||||
std::ostringstream oss;
|
ReusableStringStream rss;
|
||||||
oss << "{ ";
|
rss << "{ ";
|
||||||
if (first != last) {
|
if (first != last) {
|
||||||
oss << ::Catch::Detail::stringify(*first);
|
rss << ::Catch::Detail::stringify(*first);
|
||||||
for (++first; first != last; ++first)
|
for (++first; first != last; ++first)
|
||||||
oss << ", " << ::Catch::Detail::stringify(*first);
|
rss << ", " << ::Catch::Detail::stringify(*first);
|
||||||
}
|
}
|
||||||
oss << " }";
|
rss << " }";
|
||||||
return oss.str();
|
return rss.str();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -290,13 +290,13 @@ namespace Catch {
|
|||||||
template<typename T1, typename T2>
|
template<typename T1, typename T2>
|
||||||
struct StringMaker<std::pair<T1, T2> > {
|
struct StringMaker<std::pair<T1, T2> > {
|
||||||
static std::string convert(const std::pair<T1, T2>& pair) {
|
static std::string convert(const std::pair<T1, T2>& pair) {
|
||||||
std::ostringstream oss;
|
ReusableStringStream rss;
|
||||||
oss << "{ "
|
rss << "{ "
|
||||||
<< ::Catch::Detail::stringify(pair.first)
|
<< ::Catch::Detail::stringify(pair.first)
|
||||||
<< ", "
|
<< ", "
|
||||||
<< ::Catch::Detail::stringify(pair.second)
|
<< ::Catch::Detail::stringify(pair.second)
|
||||||
<< " }";
|
<< " }";
|
||||||
return oss.str();
|
return rss.str();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -334,11 +334,11 @@ namespace Catch {
|
|||||||
template<typename ...Types>
|
template<typename ...Types>
|
||||||
struct StringMaker<std::tuple<Types...>> {
|
struct StringMaker<std::tuple<Types...>> {
|
||||||
static std::string convert(const std::tuple<Types...>& tuple) {
|
static std::string convert(const std::tuple<Types...>& tuple) {
|
||||||
std::ostringstream os;
|
ReusableStringStream rss;
|
||||||
os << '{';
|
rss << '{';
|
||||||
Detail::TupleElementPrinter<std::tuple<Types...>>::print(tuple, os);
|
Detail::TupleElementPrinter<std::tuple<Types...>>::print(tuple, rss.get());
|
||||||
os << " }";
|
rss << " }";
|
||||||
return os.str();
|
return rss.str();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -358,10 +358,10 @@ struct ratio_string {
|
|||||||
|
|
||||||
template <class Ratio>
|
template <class Ratio>
|
||||||
std::string ratio_string<Ratio>::symbol() {
|
std::string ratio_string<Ratio>::symbol() {
|
||||||
std::ostringstream oss;
|
Catch::ReusableStringStream rss;
|
||||||
oss << '[' << Ratio::num << '/'
|
rss << '[' << Ratio::num << '/'
|
||||||
<< Ratio::den << ']';
|
<< Ratio::den << ']';
|
||||||
return oss.str();
|
return rss.str();
|
||||||
}
|
}
|
||||||
template <>
|
template <>
|
||||||
struct ratio_string<std::atto> {
|
struct ratio_string<std::atto> {
|
||||||
@ -394,33 +394,33 @@ namespace Catch {
|
|||||||
template<typename Value, typename Ratio>
|
template<typename Value, typename Ratio>
|
||||||
struct StringMaker<std::chrono::duration<Value, Ratio>> {
|
struct StringMaker<std::chrono::duration<Value, Ratio>> {
|
||||||
static std::string convert(std::chrono::duration<Value, Ratio> const& duration) {
|
static std::string convert(std::chrono::duration<Value, Ratio> const& duration) {
|
||||||
std::ostringstream oss;
|
ReusableStringStream rss;
|
||||||
oss << duration.count() << ' ' << ratio_string<Ratio>::symbol() << 's';
|
rss << duration.count() << ' ' << ratio_string<Ratio>::symbol() << 's';
|
||||||
return oss.str();
|
return rss.str();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
template<typename Value>
|
template<typename Value>
|
||||||
struct StringMaker<std::chrono::duration<Value, std::ratio<1>>> {
|
struct StringMaker<std::chrono::duration<Value, std::ratio<1>>> {
|
||||||
static std::string convert(std::chrono::duration<Value, std::ratio<1>> const& duration) {
|
static std::string convert(std::chrono::duration<Value, std::ratio<1>> const& duration) {
|
||||||
std::ostringstream oss;
|
ReusableStringStream rss;
|
||||||
oss << duration.count() << " s";
|
rss << duration.count() << " s";
|
||||||
return oss.str();
|
return rss.str();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
template<typename Value>
|
template<typename Value>
|
||||||
struct StringMaker<std::chrono::duration<Value, std::ratio<60>>> {
|
struct StringMaker<std::chrono::duration<Value, std::ratio<60>>> {
|
||||||
static std::string convert(std::chrono::duration<Value, std::ratio<60>> const& duration) {
|
static std::string convert(std::chrono::duration<Value, std::ratio<60>> const& duration) {
|
||||||
std::ostringstream oss;
|
ReusableStringStream rss;
|
||||||
oss << duration.count() << " m";
|
rss << duration.count() << " m";
|
||||||
return oss.str();
|
return rss.str();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
template<typename Value>
|
template<typename Value>
|
||||||
struct StringMaker<std::chrono::duration<Value, std::ratio<3600>>> {
|
struct StringMaker<std::chrono::duration<Value, std::ratio<3600>>> {
|
||||||
static std::string convert(std::chrono::duration<Value, std::ratio<3600>> const& duration) {
|
static std::string convert(std::chrono::duration<Value, std::ratio<3600>> const& duration) {
|
||||||
std::ostringstream oss;
|
ReusableStringStream rss;
|
||||||
oss << duration.count() << " h";
|
rss << duration.count() << " h";
|
||||||
return oss.str();
|
return rss.str();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include "catch_enforce.h"
|
#include "catch_enforce.h"
|
||||||
#include "catch_string_manip.h"
|
#include "catch_string_manip.h"
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
|
@ -11,7 +11,6 @@
|
|||||||
#include "catch_stream.h"
|
#include "catch_stream.h"
|
||||||
#include "catch_compiler_capabilities.h"
|
#include "catch_compiler_capabilities.h"
|
||||||
|
|
||||||
#include <sstream>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
@ -73,10 +72,9 @@ namespace Catch {
|
|||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
XmlWriter& writeAttribute( std::string const& name, T const& attribute ) {
|
XmlWriter& writeAttribute( std::string const& name, T const& attribute ) {
|
||||||
m_oss.clear();
|
ReusableStringStream rss;
|
||||||
m_oss.str(std::string());
|
rss << attribute;
|
||||||
m_oss << attribute;
|
return writeAttribute( name, rss.str() );
|
||||||
return writeAttribute( name, m_oss.str() );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
XmlWriter& writeText( std::string const& text, bool indent = true );
|
XmlWriter& writeText( std::string const& text, bool indent = true );
|
||||||
@ -100,7 +98,6 @@ namespace Catch {
|
|||||||
std::vector<std::string> m_tags;
|
std::vector<std::string> m_tags;
|
||||||
std::string m_indent;
|
std::string m_indent;
|
||||||
std::ostream& m_os;
|
std::ostream& m_os;
|
||||||
std::ostringstream m_oss;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -8,16 +8,15 @@
|
|||||||
#ifndef TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED
|
#ifndef TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED
|
||||||
#define TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED
|
#define TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED
|
||||||
|
|
||||||
#include "../internal/catch_enforce.h"
|
|
||||||
#include "../internal/catch_interfaces_reporter.h"
|
#include "../internal/catch_interfaces_reporter.h"
|
||||||
|
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <cfloat>
|
#include <cfloat>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <ostream>
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
void prepareExpandedExpression(AssertionResult& result);
|
void prepareExpandedExpression(AssertionResult& result);
|
||||||
@ -33,7 +32,8 @@ namespace Catch {
|
|||||||
stream( _config.stream() )
|
stream( _config.stream() )
|
||||||
{
|
{
|
||||||
m_reporterPrefs.shouldRedirectStdOut = false;
|
m_reporterPrefs.shouldRedirectStdOut = false;
|
||||||
CATCH_ENFORCE( DerivedT::getSupportedVerbosities().count( m_config->verbosity() ), "Verbosity level not supported by this reporter" );
|
if( !DerivedT::getSupportedVerbosities().count( m_config->verbosity() ) )
|
||||||
|
throw std::domain_error( "Verbosity level not supported by this reporter" );
|
||||||
}
|
}
|
||||||
|
|
||||||
ReporterPreferences getPreferences() const override {
|
ReporterPreferences getPreferences() const override {
|
||||||
@ -147,7 +147,8 @@ namespace Catch {
|
|||||||
stream( _config.stream() )
|
stream( _config.stream() )
|
||||||
{
|
{
|
||||||
m_reporterPrefs.shouldRedirectStdOut = false;
|
m_reporterPrefs.shouldRedirectStdOut = false;
|
||||||
CATCH_ENFORCE( DerivedT::getSupportedVerbosities().count( m_config->verbosity() ), "Verbosity level not supported by this reporter" );
|
if( !DerivedT::getSupportedVerbosities().count( m_config->verbosity() ) )
|
||||||
|
throw std::domain_error( "Verbosity level not supported by this reporter" );
|
||||||
}
|
}
|
||||||
~CumulativeReporterBase() override = default;
|
~CumulativeReporterBase() override = default;
|
||||||
|
|
||||||
|
@ -543,9 +543,9 @@ namespace Catch {
|
|||||||
colour( _colour )
|
colour( _colour )
|
||||||
{}
|
{}
|
||||||
SummaryColumn addRow( std::size_t count ) {
|
SummaryColumn addRow( std::size_t count ) {
|
||||||
std::ostringstream oss;
|
ReusableStringStream rss;
|
||||||
oss << count;
|
rss << count;
|
||||||
std::string row = oss.str();
|
std::string row = rss.str();
|
||||||
for( auto& oldRow : rows ) {
|
for( auto& oldRow : rows ) {
|
||||||
while( oldRow.size() < row.size() )
|
while( oldRow.size() < row.size() )
|
||||||
oldRow = ' ' + oldRow;
|
oldRow = ' ' + oldRow;
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
#include "../internal/catch_timer.h"
|
#include "../internal/catch_timer.h"
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <sstream>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
@ -230,15 +230,15 @@ namespace Catch {
|
|||||||
xml.writeAttribute( "message", result.getExpandedExpression() );
|
xml.writeAttribute( "message", result.getExpandedExpression() );
|
||||||
xml.writeAttribute( "type", result.getTestMacroName() );
|
xml.writeAttribute( "type", result.getTestMacroName() );
|
||||||
|
|
||||||
std::ostringstream oss;
|
ReusableStringStream rss;
|
||||||
if( !result.getMessage().empty() )
|
if( !result.getMessage().empty() )
|
||||||
oss << result.getMessage() << '\n';
|
rss << result.getMessage() << '\n';
|
||||||
for( auto const& msg : stats.infoMessages )
|
for( auto const& msg : stats.infoMessages )
|
||||||
if( msg.type == ResultWas::Info )
|
if( msg.type == ResultWas::Info )
|
||||||
oss << msg.message << '\n';
|
rss << msg.message << '\n';
|
||||||
|
|
||||||
oss << "at " << result.getSourceInfo();
|
rss << "at " << result.getSourceInfo();
|
||||||
xml.writeText( oss.str(), false );
|
xml.writeText( rss.str(), false );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,6 +14,8 @@
|
|||||||
// file can be distributed as a single header that works with the main
|
// file can be distributed as a single header that works with the main
|
||||||
// Catch single header.
|
// Catch single header.
|
||||||
|
|
||||||
|
#include "../internal/catch_enforce.h"
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
#ifdef __clang__
|
#ifdef __clang__
|
||||||
@ -69,9 +71,9 @@ namespace Catch {
|
|||||||
AssertionResult const& result = assertionStats.assertionResult;
|
AssertionResult const& result = assertionStats.assertionResult;
|
||||||
if( !result.isOk() ) {
|
if( !result.isOk() ) {
|
||||||
|
|
||||||
std::ostringstream msg;
|
ReusableStringStream msg;
|
||||||
if( !m_headerPrintedForThisSection )
|
if( !m_headerPrintedForThisSection )
|
||||||
printSectionHeader( msg );
|
printSectionHeader( msg.get() );
|
||||||
m_headerPrintedForThisSection = true;
|
m_headerPrintedForThisSection = true;
|
||||||
|
|
||||||
msg << result.getSourceInfo() << "\n";
|
msg << result.getSourceInfo() << "\n";
|
||||||
|
@ -8,6 +8,8 @@
|
|||||||
|
|
||||||
#include "catch.hpp"
|
#include "catch.hpp"
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
#ifdef __clang__
|
#ifdef __clang__
|
||||||
#pragma clang diagnostic push
|
#pragma clang diagnostic push
|
||||||
#pragma clang diagnostic ignored "-Wweak-vtables"
|
#pragma clang diagnostic ignored "-Wweak-vtables"
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <cerrno>
|
#include <cerrno>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
TEST_CASE( "random SECTION tests", "[.][sections][failing]" ) {
|
TEST_CASE( "random SECTION tests", "[.][sections][failing]" ) {
|
||||||
int a = 1;
|
int a = 1;
|
||||||
|
@ -15,10 +15,11 @@
|
|||||||
// that is triggered when compiling as Win32|Release
|
// that is triggered when compiling as Win32|Release
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include "catch.hpp"
|
#include "catch.hpp"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
std::string toString( const std::pair<int, int>& value ) {
|
std::string toString( const std::pair<int, int>& value ) {
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
|
Loading…
Reference in New Issue
Block a user