First cut of Timer class.

- started integrating with reporters (now (optionally) supported in console reporter).
- introduced Node<> template to help with cumulative reporting and used it instead of ThreadedSectionInfo.
This commit is contained in:
Phil Nash
2013-08-07 18:56:35 +01:00
parent 649f8c24b1
commit 6339254cb2
16 changed files with 379 additions and 174 deletions

View File

@@ -24,15 +24,21 @@ namespace Catch {
inline void addWarning( ConfigData& config, std::string const& _warning ) {
if( _warning == "NoAssertions" )
config.warnings = (ConfigData::WarnAbout::What)( config.warnings | ConfigData::WarnAbout::NoAssertions );
config.warnings = (WarnAbout::What)( config.warnings | WarnAbout::NoAssertions );
else
throw std::runtime_error( "Unrecognised warning: '" + _warning + "'" );
}
inline void setVerbosity( ConfigData& config, int level ) {
// !TBD: accept strings?
config.verbosity = (ConfigData::Verbosity::Level)level;
config.verbosity = (Verbosity::Level)level;
}
inline void setShowDurations( ConfigData& config, bool _showDurations ) {
config.showDurations = _showDurations
? ShowDurations::Always
: ShowDurations::Never;
}
inline Clara::CommandLine<ConfigData> makeCommandLineParser() {
@@ -121,6 +127,12 @@ namespace Catch {
.describe( "which test or tests to use" )
.argName( "test name, pattern or tags" );
cli.bind( &setShowDurations )
.describe( "show test durations" )
.shortOpt( "d")
.longOpt( "durations" )
.argName( "durations" );
return cli;
}

View File

@@ -26,17 +26,6 @@ namespace Catch {
struct ConfigData {
struct Verbosity { enum Level {
NoOutput = 0,
Quiet,
Normal
}; };
struct WarnAbout { enum What {
Nothing = 0x00,
NoAssertions = 0x01
}; };
ConfigData()
: listTests( false ),
listTags( false ),
@@ -47,7 +36,8 @@ namespace Catch {
showHelp( false ),
abortAfter( -1 ),
verbosity( Verbosity::Normal ),
warnings( WarnAbout::Nothing )
warnings( WarnAbout::Nothing ),
showDurations( ShowDurations::DefaultForReporter )
{}
bool listTests;
@@ -63,6 +53,7 @@ namespace Catch {
Verbosity::Level verbosity;
WarnAbout::What warnings;
ShowDurations::OrNot showDurations;
std::string reporterName;
std::string outputFilename;
@@ -166,7 +157,9 @@ namespace Catch {
virtual std::ostream& stream() const { return m_os; }
virtual std::string name() const { return m_data.name.empty() ? m_data.processName : m_data.name; }
virtual bool includeSuccessfulResults() const { return m_data.showSuccessfulTests; }
virtual bool warnAboutMissingAssertions() const { return m_data.warnings & ConfigData::WarnAbout::NoAssertions; }
virtual bool warnAboutMissingAssertions() const { return m_data.warnings & WarnAbout::NoAssertions; }
virtual ShowDurations::OrNot showDurations() const { return m_data.showDurations; }
private:
ConfigData m_data;

View File

@@ -30,6 +30,7 @@
#include "catch_text.hpp"
#include "catch_message.hpp"
#include "catch_legacy_reporter_adapter.hpp"
#include "catch_timer.hpp"
#include "../reporters/catch_reporter_basic.hpp"
#include "../reporters/catch_reporter_xml.hpp"
@@ -57,7 +58,6 @@ namespace Catch {
TestCaseStats::~TestCaseStats() {}
TestGroupStats::~TestGroupStats() {}
TestRunStats::~TestRunStats() {}
ThreadedSectionInfo::~ThreadedSectionInfo() {}
TestGroupNode::~TestGroupNode() {}
TestRunNode::~TestRunNode() {}

View File

@@ -30,7 +30,7 @@ namespace Catch {
virtual void assertionEnded( AssertionResult const& result ) = 0;
virtual bool sectionStarted( SectionInfo const& sectionInfo,
Counts& assertions ) = 0;
virtual void sectionEnded( SectionInfo const& name, Counts const& assertions ) = 0;
virtual void sectionEnded( SectionInfo const& name, Counts const& assertions, double _durationInSeconds ) = 0;
virtual void pushScopedMessage( MessageInfo const& message ) = 0;
virtual void popScopedMessage( MessageInfo const& message ) = 0;

View File

@@ -15,6 +15,23 @@
namespace Catch {
struct Verbosity { enum Level {
NoOutput = 0,
Quiet,
Normal
}; };
struct WarnAbout { enum What {
Nothing = 0x00,
NoAssertions = 0x01
}; };
struct ShowDurations { enum OrNot {
DefaultForReporter,
Always,
Never
}; };
struct IConfig : IShared {
virtual ~IConfig();
@@ -26,6 +43,7 @@ namespace Catch {
virtual bool shouldDebugBreak() const = 0;
virtual bool warnAboutMissingAssertions() const = 0;
virtual int abortAfter() const = 0;
virtual ShowDurations::OrNot showDurations() const = 0;
};
}

View File

@@ -46,6 +46,20 @@ namespace Catch
bool shouldRedirectStdOut;
};
template<typename T>
struct Node : SharedImpl<> {
Node( T const& _value, Node* _parent = NULL )
: value( _value ),
parent( _parent )
{}
virtual ~Node() {}
T value;
std::vector<Ptr<Node> > children;
Node* parent;
};
struct TestRunInfo {
TestRunInfo( std::string const& _name ) : name( _name ) {}
std::string name;
@@ -78,17 +92,6 @@ namespace Catch
SourceLineInfo lineInfo;
};
struct ThreadedSectionInfo : SectionInfo, SharedImpl<> {
ThreadedSectionInfo( SectionInfo const& _sectionInfo, ThreadedSectionInfo* _parent = NULL )
: SectionInfo( _sectionInfo ),
parent( _parent )
{}
virtual ~ThreadedSectionInfo();
std::vector<Ptr<ThreadedSectionInfo> > children;
ThreadedSectionInfo* parent;
};
struct AssertionStats {
AssertionStats( AssertionResult const& _assertionResult,
std::vector<MessageInfo> const& _infoMessages,
@@ -117,15 +120,18 @@ namespace Catch
struct SectionStats {
SectionStats( SectionInfo const& _sectionInfo,
Counts const& _assertions,
double _durationInSeconds,
bool _missingAssertions )
: sectionInfo( _sectionInfo ),
assertions( _assertions ),
durationInSeconds( _durationInSeconds ),
missingAssertions( _missingAssertions )
{}
virtual ~SectionStats();
SectionInfo sectionInfo;
Counts assertions;
double durationInSeconds;
bool missingAssertions;
};
@@ -189,6 +195,7 @@ namespace Catch
bool aborting;
};
struct IStreamingReporter : IShared {
virtual ~IStreamingReporter();
@@ -236,7 +243,7 @@ namespace Catch
unusedTestCaseInfo = _testInfo;
}
virtual void sectionStarting( SectionInfo const& _sectionInfo ) {
Ptr<ThreadedSectionInfo> sectionInfo = new ThreadedSectionInfo( _sectionInfo );
Ptr<Node<SectionInfo> > sectionInfo = new Node<SectionInfo>( _sectionInfo );
if( !currentSectionInfo ) {
currentSectionInfo = sectionInfo;
m_rootSections.push_back( currentSectionInfo );
@@ -268,11 +275,11 @@ namespace Catch
Option<TestRunInfo> testRunInfo;
Option<GroupInfo> unusedGroupInfo;
Option<TestCaseInfo> unusedTestCaseInfo;
Ptr<ThreadedSectionInfo> currentSectionInfo;
Ptr<Node<SectionInfo> > currentSectionInfo;
std::ostream& stream;
// !TBD: This should really go in the TestCaseStats class
std::vector<Ptr<ThreadedSectionInfo> > m_rootSections;
std::vector<Ptr<Node<SectionInfo> > > m_rootSections;
};
struct TestGroupNode : TestGroupStats {

View File

@@ -18,6 +18,7 @@
#include "catch_totals.hpp"
#include "catch_test_spec.h"
#include "catch_test_case_tracker.hpp"
#include "catch_timer.h"
#include <set>
#include <string>
@@ -194,9 +195,9 @@ namespace Catch {
return true;
}
virtual void sectionEnded( SectionInfo const& info, Counts const& prevAssertions ) {
virtual void sectionEnded( SectionInfo const& info, Counts const& prevAssertions, double _durationInSeconds ) {
if( std::uncaught_exception() ) {
m_unfinishedSections.push_back( UnfinishedSections( info, prevAssertions ) );
m_unfinishedSections.push_back( UnfinishedSections( info, prevAssertions, _durationInSeconds ) );
return;
}
@@ -205,7 +206,7 @@ namespace Catch {
m_testCaseTracker->leaveSection();
m_reporter->sectionEnded( SectionStats( info, assertions, missingAssertions ) );
m_reporter->sectionEnded( SectionStats( info, assertions, _durationInSeconds, missingAssertions ) );
m_messages.clear();
}
@@ -260,10 +261,13 @@ namespace Catch {
SectionInfo testCaseSection( testCaseInfo.name, testCaseInfo.description, testCaseInfo.lineInfo );
m_reporter->sectionStarting( testCaseSection );
Counts prevAssertions = m_totals.assertions;
double duration = 0;
try {
m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, "", ResultDisposition::Normal );
TestCaseTracker::Guard guard( *m_testCaseTracker );
Timer timer;
timer.start();
if( m_reporter->getPreferences().shouldRedirectStdOut ) {
StreamRedirect coutRedir( std::cout, redirectedCout );
StreamRedirect cerrRedir( std::cerr, redirectedCerr );
@@ -272,6 +276,7 @@ namespace Catch {
else {
m_activeTestCase->invoke();
}
duration = timer.getElapsedSeconds();
}
catch( TestFailureException& ) {
// This just means the test was aborted due to failure
@@ -287,25 +292,26 @@ namespace Catch {
itEnd = m_unfinishedSections.end();
it != itEnd;
++it )
sectionEnded( it->info, it->prevAssertions );
sectionEnded( it->info, it->prevAssertions, it->durationInSeconds );
m_unfinishedSections.clear();
m_messages.clear();
Counts assertions = m_totals.assertions - prevAssertions;
bool missingAssertions = testForMissingAssertions( assertions );
SectionStats testCaseSectionStats( testCaseSection, assertions, missingAssertions );
SectionStats testCaseSectionStats( testCaseSection, assertions, duration, missingAssertions );
m_reporter->sectionEnded( testCaseSectionStats );
}
private:
struct UnfinishedSections {
UnfinishedSections( SectionInfo const& _info, Counts const& _prevAssertions )
: info( _info ), prevAssertions( _prevAssertions )
UnfinishedSections( SectionInfo const& _info, Counts const& _prevAssertions, double _durationInSeconds )
: info( _info ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds )
{}
SectionInfo info;
Counts prevAssertions;
double durationInSeconds;
};
TestRunInfo m_runInfo;

View File

@@ -11,6 +11,7 @@
#include "catch_capture.hpp"
#include "catch_totals.hpp"
#include "catch_compiler_capabilities.h"
#include "catch_timer.h"
#include <string>
@@ -23,11 +24,13 @@ namespace Catch {
std::string const& description = "" )
: m_info( name, description, lineInfo ),
m_sectionIncluded( getCurrentContext().getResultCapture().sectionStarted( m_info, m_assertions ) )
{}
{
m_timer.start();
}
~Section() {
if( m_sectionIncluded )
getCurrentContext().getResultCapture().sectionEnded( m_info, m_assertions );
getCurrentContext().getResultCapture().sectionEnded( m_info, m_assertions, m_timer.getElapsedSeconds() );
}
// This indicates whether the section should be executed or not
@@ -41,6 +44,7 @@ namespace Catch {
std::string m_name;
Counts m_assertions;
bool m_sectionIncluded;
Timer m_timer;
};
} // end namespace Catch

View File

@@ -0,0 +1,33 @@
/*
* Created by Phil on 05/08/2013.
* Copyright 2013 Two Blue Cubes Ltd. All rights reserved.
*
* Distributed under the Boost Software License, Version 1.0. (See accompanying
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef TWOBLUECUBES_CATCH_TIMER_H_INCLUDED
#define TWOBLUECUBES_CATCH_TIMER_H_INCLUDED
#ifdef WIN32
typedef unsigned long long uint64_t;
#else
#include <stdint.h>
#endif
namespace Catch {
class Timer {
public:
Timer() : m_ticks( 0 ) {}
void start();
unsigned int getElapsedNanoseconds() const;
unsigned int getElapsedMilliseconds() const;
double getElapsedSeconds() const;
private:
uint64_t m_ticks;
};
} // namespace Catch
#endif // TWOBLUECUBES_CATCH_TIMER_H_INCLUDED

View File

@@ -0,0 +1,62 @@
/*
* Created by Phil on 05/08/2013.
* Copyright 2013 Two Blue Cubes Ltd. All rights reserved.
*
* Distributed under the Boost Software License, Version 1.0. (See accompanying
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/
#include "catch_timer.h"
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wc++11-long-long"
#endif
#ifdef WIN32
#include <windows.h>
#else
#include <sys/time.h>
#endif
namespace Catch {
namespace {
#ifdef WIN32
uint64_t getCurrentTicks() {
static uint64_t hz=0, hzo=0;
if (!hz) {
QueryPerformanceFrequency((LARGE_INTEGER*)&hz);
QueryPerformanceCounter((LARGE_INTEGER*)&hzo);
}
uint64_t t;
QueryPerformanceCounter((LARGE_INTEGER*)&t);
return ((t-hzo)*1000000)/hz;
}
#else
uint64_t getCurrentTicks() {
timeval t;
gettimeofday(&t,NULL);
return (uint64_t)t.tv_sec * 1000000ull + (uint64_t)t.tv_usec;
}
#endif
}
void Timer::start() {
m_ticks = getCurrentTicks();
}
unsigned int Timer::getElapsedNanoseconds() const {
return (unsigned int)(getCurrentTicks() - m_ticks);
}
unsigned int Timer::getElapsedMilliseconds() const {
return (unsigned int)((getCurrentTicks() - m_ticks)/1000);
}
double Timer::getElapsedSeconds() const {
return (getCurrentTicks() - m_ticks)/1000000.0;
}
} // namespace Catch
#ifdef __clang__
#pragma clang diagnostic pop
#endif