mirror of https://github.com/catchorg/Catch2.git
Factored table writing code out into a TablePrinter class (removes a lot of magic numbers and ad-hoc formatting)
This commit is contained in:
parent
97d6b08087
commit
22e9ebef0d
|
@ -30,24 +30,105 @@ namespace {
|
||||||
else
|
else
|
||||||
return k;
|
return k;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ColumnInfo {
|
||||||
|
enum Justification { Left, Right };
|
||||||
|
std::string name;
|
||||||
|
int width;
|
||||||
|
Justification justification;
|
||||||
|
};
|
||||||
|
struct ColumnBreak {};
|
||||||
|
struct RowBreak {};
|
||||||
|
|
||||||
|
class TablePrinter {
|
||||||
|
std::ostream& m_os;
|
||||||
|
std::vector<ColumnInfo> m_columnInfos;
|
||||||
|
std::ostringstream m_oss;
|
||||||
|
int m_currentColumn = -1;
|
||||||
|
bool m_isOpen = false;
|
||||||
|
|
||||||
|
public:
|
||||||
|
TablePrinter( std::ostream& os, std::vector<ColumnInfo> const& columnInfos )
|
||||||
|
: m_os( os ),
|
||||||
|
m_columnInfos( columnInfos )
|
||||||
|
{}
|
||||||
|
|
||||||
|
auto columnInfos() const -> std::vector<ColumnInfo> const& {
|
||||||
|
return m_columnInfos;
|
||||||
|
}
|
||||||
|
|
||||||
|
void open() {
|
||||||
|
if( !m_isOpen ) {
|
||||||
|
m_isOpen = true;
|
||||||
|
*this << RowBreak();
|
||||||
|
for( auto const& info : m_columnInfos )
|
||||||
|
*this << info.name << ColumnBreak();
|
||||||
|
*this << RowBreak();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void close() {
|
||||||
|
if( m_isOpen ) {
|
||||||
|
*this << RowBreak();
|
||||||
|
m_os << std::endl;
|
||||||
|
m_isOpen = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
friend TablePrinter& operator << ( TablePrinter& tp, T const& value ) {
|
||||||
|
tp.m_oss << value;
|
||||||
|
return tp;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend TablePrinter& operator << ( TablePrinter& tp, ColumnBreak ) {
|
||||||
|
auto colStr = tp.m_oss.str();
|
||||||
|
tp.m_oss.str("");
|
||||||
|
tp.open();
|
||||||
|
if( tp.m_currentColumn == static_cast<int>(tp.m_columnInfos.size()-1) ) {
|
||||||
|
tp.m_currentColumn = -1;
|
||||||
|
tp.m_os << "\n";
|
||||||
|
}
|
||||||
|
if( tp.m_currentColumn == -1 )
|
||||||
|
tp.m_os << "|";
|
||||||
|
tp.m_currentColumn++;
|
||||||
|
|
||||||
|
auto colInfo = tp.m_columnInfos[tp.m_currentColumn];
|
||||||
|
auto padding = ( colStr.size()+2 < static_cast<size_t>( colInfo.width ) )
|
||||||
|
? std::string( colInfo.width-(colStr.size()+2), ' ' )
|
||||||
|
: std::string();
|
||||||
|
if( colInfo.justification == ColumnInfo::Left )
|
||||||
|
tp.m_os << " " << colStr << padding << " |";
|
||||||
|
else
|
||||||
|
tp.m_os << " " << padding << colStr << " |";
|
||||||
|
return tp;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend TablePrinter& operator << ( TablePrinter& tp, RowBreak ) {
|
||||||
|
if( tp.m_currentColumn > 0 ) {
|
||||||
|
tp.m_os << "\n";
|
||||||
|
tp.m_currentColumn = -1;
|
||||||
|
}
|
||||||
|
tp.m_os << Catch::getBoxCharsAcross() << "\n";
|
||||||
|
return tp;
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
auto leftPad( const T& value, int width ) -> std::string {
|
|
||||||
// !TBD: could do with being optimised
|
|
||||||
std::ostringstream oss;
|
|
||||||
oss << value;
|
|
||||||
std::string converted = oss.str();
|
|
||||||
return std::string( width - converted.size(), ' ' ) + converted;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
struct ConsoleReporter : StreamingReporterBase<ConsoleReporter> {
|
struct ConsoleReporter : StreamingReporterBase<ConsoleReporter> {
|
||||||
using StreamingReporterBase::StreamingReporterBase;
|
TablePrinter m_tablePrinter;
|
||||||
bool m_benchmarkTableOpen = false;
|
|
||||||
|
|
||||||
|
ConsoleReporter( ReporterConfig const& config )
|
||||||
|
: StreamingReporterBase( config ),
|
||||||
|
m_tablePrinter( config.stream(),
|
||||||
|
{
|
||||||
|
{ "benchmark name", CATCH_CONFIG_CONSOLE_WIDTH-38, ColumnInfo::Left },
|
||||||
|
{ "iters", 8, ColumnInfo::Right },
|
||||||
|
{ "elapsed ns", 12, ColumnInfo::Right },
|
||||||
|
{ "average", 12, ColumnInfo::Right }
|
||||||
|
} )
|
||||||
|
{}
|
||||||
~ConsoleReporter() override;
|
~ConsoleReporter() override;
|
||||||
static std::string getDescription() {
|
static std::string getDescription() {
|
||||||
return "Reports test results as plain lines of text";
|
return "Reports test results as plain lines of text";
|
||||||
|
@ -58,7 +139,6 @@ namespace Catch {
|
||||||
}
|
}
|
||||||
|
|
||||||
void assertionStarting( AssertionInfo const& ) override {
|
void assertionStarting( AssertionInfo const& ) override {
|
||||||
closeBenchmarkTable();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool assertionEnded( AssertionStats const& _assertionStats ) override {
|
bool assertionEnded( AssertionStats const& _assertionStats ) override {
|
||||||
|
@ -83,7 +163,7 @@ namespace Catch {
|
||||||
StreamingReporterBase::sectionStarting( _sectionInfo );
|
StreamingReporterBase::sectionStarting( _sectionInfo );
|
||||||
}
|
}
|
||||||
void sectionEnded( SectionStats const& _sectionStats ) override {
|
void sectionEnded( SectionStats const& _sectionStats ) override {
|
||||||
closeBenchmarkTable();
|
m_tablePrinter.close();
|
||||||
if( _sectionStats.missingAssertions ) {
|
if( _sectionStats.missingAssertions ) {
|
||||||
lazyPrint();
|
lazyPrint();
|
||||||
Colour colour( Colour::ResultError );
|
Colour colour( Colour::ResultError );
|
||||||
|
@ -102,44 +182,32 @@ namespace Catch {
|
||||||
StreamingReporterBase::sectionEnded( _sectionStats );
|
StreamingReporterBase::sectionEnded( _sectionStats );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void benchmarkStarting( BenchmarkInfo const& info ) override {
|
void benchmarkStarting( BenchmarkInfo const& info ) override {
|
||||||
lazyPrint();
|
lazyPrintWithoutClosingBenchmarkTable();
|
||||||
auto nameColWidth = CATCH_CONFIG_CONSOLE_WIDTH-40;
|
|
||||||
auto nameCol = Column( info.name ).width( nameColWidth );
|
auto nameCol = Column( info.name ).width( m_tablePrinter.columnInfos()[0].width-2 );
|
||||||
if( !m_benchmarkTableOpen ) {
|
|
||||||
stream
|
|
||||||
<< getBoxCharsAcross() << "\n"
|
|
||||||
<< "| benchmark name" << std::string( nameColWidth-14, ' ' ) << " | it'ns | elapsed ns | average |\n"
|
|
||||||
<< getBoxCharsAcross() << "\n";
|
|
||||||
m_benchmarkTableOpen = true;
|
|
||||||
}
|
|
||||||
bool firstLine = true;
|
bool firstLine = true;
|
||||||
for( auto line : nameCol ) {
|
for( auto line : nameCol ) {
|
||||||
if( !firstLine )
|
if( !firstLine )
|
||||||
stream << " | | |" << "\n";
|
m_tablePrinter << ColumnBreak() << ColumnBreak() << ColumnBreak();
|
||||||
else
|
else
|
||||||
firstLine = false;
|
firstLine = false;
|
||||||
|
|
||||||
stream << "| " << line << std::string( nameColWidth-line.size(), ' ' ) << " |";
|
m_tablePrinter << line << ColumnBreak();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void benchmarkEnded( BenchmarkStats const& stats ) override {
|
void benchmarkEnded( BenchmarkStats const& stats ) override {
|
||||||
// !TBD: report average times in natural units?
|
// !TBD: report average times in natural units?
|
||||||
stream
|
m_tablePrinter
|
||||||
<< " " << leftPad( stats.iterations, 6 )
|
<< stats.iterations << ColumnBreak()
|
||||||
<< " | " << leftPad( stats.elapsedTimeInNanoseconds, 10 )
|
<< stats.elapsedTimeInNanoseconds << ColumnBreak()
|
||||||
<< " | " << leftPad( stats.elapsedTimeInNanoseconds/stats.iterations, 7 )
|
<< stats.elapsedTimeInNanoseconds/stats.iterations << " ns" << ColumnBreak();
|
||||||
<< " ns |" << std::endl;
|
|
||||||
}
|
|
||||||
void closeBenchmarkTable() {
|
|
||||||
if( m_benchmarkTableOpen ) {
|
|
||||||
stream << getBoxCharsAcross() << "\n" << std::endl;
|
|
||||||
m_benchmarkTableOpen = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void testCaseEnded( TestCaseStats const& _testCaseStats ) override {
|
void testCaseEnded( TestCaseStats const& _testCaseStats ) override {
|
||||||
closeBenchmarkTable();
|
m_tablePrinter.close();
|
||||||
StreamingReporterBase::testCaseEnded( _testCaseStats );
|
StreamingReporterBase::testCaseEnded( _testCaseStats );
|
||||||
m_headerPrinted = false;
|
m_headerPrinted = false;
|
||||||
}
|
}
|
||||||
|
@ -305,6 +373,12 @@ namespace Catch {
|
||||||
|
|
||||||
void lazyPrint() {
|
void lazyPrint() {
|
||||||
|
|
||||||
|
m_tablePrinter.close();
|
||||||
|
lazyPrintWithoutClosingBenchmarkTable();
|
||||||
|
}
|
||||||
|
|
||||||
|
void lazyPrintWithoutClosingBenchmarkTable() {
|
||||||
|
|
||||||
if( !currentTestRunInfo.used )
|
if( !currentTestRunInfo.used )
|
||||||
lazyPrintRunInfo();
|
lazyPrintRunInfo();
|
||||||
if( !currentGroupInfo.used )
|
if( !currentGroupInfo.used )
|
||||||
|
|
Loading…
Reference in New Issue