Allow output stream to be specified on the command line

This commit is contained in:
Phil Nash 2011-01-18 09:20:06 +00:00
parent 925409d7e9
commit 2885339287
10 changed files with 161 additions and 15 deletions

View File

@ -32,6 +32,7 @@
/* Begin PBXFileReference section */
4A15D2B712E0418F0005EB03 /* catch_self_test.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = catch_self_test.hpp; path = ../internal/catch_self_test.hpp; sourceTree = SOURCE_ROOT; };
4A15D4A812E4DF0D0005EB03 /* catch_stream.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = catch_stream.hpp; path = ../internal/catch_stream.hpp; sourceTree = SOURCE_ROOT; };
4A302DE312D5114900C84B67 /* catch.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = catch.hpp; path = ../catch.hpp; sourceTree = SOURCE_ROOT; };
4A33BCE512CE7F500052A211 /* catch_hub.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = catch_hub.h; path = ../internal/catch_hub.h; sourceTree = SOURCE_ROOT; };
4A33BCF912CE80EC0052A211 /* catch_interfaces_reporter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = catch_interfaces_reporter.h; path = ../internal/catch_interfaces_reporter.h; sourceTree = SOURCE_ROOT; };
@ -163,6 +164,7 @@
4A6D514B12C8A547008F0415 /* catch_debugger.hpp */,
4AFC341612809A36003A0C29 /* catch_common.h */,
4A992A6512B2156C002B7B66 /* catch_xmlwriter.hpp */,
4A15D4A812E4DF0D0005EB03 /* catch_stream.hpp */,
);
name = support;
sourceTree = "<group>";

View File

@ -24,7 +24,6 @@ TEST_CASE( "selftest/main", "Runs all Catch self tests and checks their results"
CHECK( runner.getReporter().getFailed() == 0 );
runner.runMatching( "./failing/*" );
CHECK( runner.getReporter().getSucceeded() == 0 );
CHECK( runner.getReporter().getFailed() == 53 );
}

View File

@ -23,13 +23,17 @@ namespace Catch
{
public:
///////////////////////////////////////////////////////////////////////////
XmlReporter( const IReporterConfig& config )
: m_config( config )
XmlReporter
(
const IReporterConfig& config
)
: m_config( config )
{
}
///////////////////////////////////////////////////////////////////////////
static std::string getDescription()
static std::string getDescription
()
{
return "Reports test results as an XML document";
}
@ -37,14 +41,19 @@ namespace Catch
private: // IReporter
///////////////////////////////////////////////////////////////////////////
virtual void StartTesting()
virtual void StartTesting
()
{
m_xml = XmlWriter( m_config.stream() );
m_xml.startElement( "AllTests" );
}
///////////////////////////////////////////////////////////////////////////
virtual void EndTesting( std::size_t succeeded, std::size_t failed )
virtual void EndTesting
(
std::size_t succeeded,
std::size_t failed
)
{
m_xml.scopedElement( "OverallResults" )
.writeAttribute( "successes", succeeded )
@ -52,14 +61,22 @@ namespace Catch
}
///////////////////////////////////////////////////////////////////////////
virtual void StartGroup( const std::string& groupName )
virtual void StartGroup
(
const std::string& groupName
)
{
m_xml.startElement( "Group" )
.writeAttribute( "name", groupName );
}
///////////////////////////////////////////////////////////////////////////
virtual void EndGroup( const std::string& /*groupName*/, std::size_t succeeded, std::size_t failed )
virtual void EndGroup
(
const std::string& /*groupName*/,
std::size_t succeeded,
std::size_t failed
)
{
m_xml.scopedElement( "OverallResults" )
.writeAttribute( "successes", succeeded )

View File

@ -50,7 +50,7 @@ namespace Catch
<< "\t-l, --list <tests | reporters> [xml]\n"
<< "\t-t, --test <testspec> [<testspec>...]\n"
<< "\t-r, --reporter <reporter name>\n"
<< "\t-o, --out <file name>\n"
<< "\t-o, --out <file name>|<%stream name>\n"
<< "\t-s, --success\n"
<< "\t-b, --break\n\n"
<< "For more detail usage please see: https://github.com/philsquared/Catch/wiki/Command-line" << std::endl;

View File

@ -152,7 +152,10 @@ namespace Catch
case modeOutput:
if( m_args.size() == 0 )
return setErrorMode( m_command + " expected filename" );
m_config.setFilename( m_args[0] );
if( m_args[0][0] == '%' )
m_config.useStream( m_args[0].substr( 1 ) );
else
m_config.setFilename( m_args[0] );
break;
case modeSuccess:
if( m_args.size() != 0 )

View File

@ -23,6 +23,7 @@
namespace Catch
{
class Config : public IReporterConfig
{
private:
@ -59,10 +60,17 @@ namespace Catch
m_listSpec( List::None ),
m_shouldDebugBreak( false ),
m_showHelp( false ),
m_os( std::cout.rdbuf() ),
m_streambuf( std::cout.rdbuf() ),
m_os( m_streambuf ),
m_includeWhat( Include::FailedOnly )
{}
///////////////////////////////////////////////////////////////////////////
~Config()
{
setStreamBuf( NULL );
}
///////////////////////////////////////////////////////////////////////////
void setReporter( const std::string& reporterName )
{
@ -172,7 +180,18 @@ namespace Catch
///////////////////////////////////////////////////////////////////////////
void setStreamBuf( std::streambuf* buf )
{
m_os.rdbuf( buf );
// Delete previous stream buf if we own it
if( m_streambuf && dynamic_cast<StreamBufBase*>( m_streambuf ) )
delete m_streambuf;
m_streambuf = buf;
m_os.rdbuf( buf ? buf : std::cout.rdbuf() );
}
///////////////////////////////////////////////////////////////////////////
void useStream( const std::string& streamName )
{
setStreamBuf( Hub::createStreamBuf( streamName ) );
}
///////////////////////////////////////////////////////////////////////////
@ -189,6 +208,7 @@ namespace Catch
std::vector<std::string> m_testSpecs;
bool m_shouldDebugBreak;
bool m_showHelp;
std::streambuf* m_streambuf;
mutable std::ostream m_os;
Include::What m_includeWhat;
};

View File

@ -15,6 +15,8 @@
#ifndef TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED
#define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED
#include <iostream>
#if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
#include <assert.h>
@ -83,5 +85,14 @@
inline void DebugBreak(){}
#endif
inline void writeToDebugConsole( const std::string& text )
{
#ifdef _WIN32
::OutputDebugStringA( text.get() );
#else
// !TBD: Need a version for Mac/ XCode and other IDEs
std::cout << text;
#endif
}
#endif // TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED

View File

@ -24,6 +24,10 @@ namespace Catch
struct ITestCaseRegistry;
struct IRunner;
class StreamBufBase : public std::streambuf
{
};
class Hub
{
Hub();
@ -49,6 +53,10 @@ namespace Catch
static ITestCaseRegistry& getTestCaseRegistry
();
static std::streambuf* createStreamBuf
( const std::string& streamName
);
static IRunner& getRunner
();

View File

@ -13,6 +13,7 @@
#include "catch_reporter_registry.hpp"
#include "catch_test_case_registry_impl.hpp"
#include "catch_runner_impl.hpp"
#include "catch_stream.hpp"
namespace Catch
{
@ -70,4 +71,18 @@ namespace Catch
{
return *me().m_testCaseRegistry.get();
}
///////////////////////////////////////////////////////////////////////////
std::streambuf* Hub::createStreamBuf
(
const std::string& streamName
)
{
if( streamName == "stdout" ) return std::cout.rdbuf();
if( streamName == "stderr" ) return std::cerr.rdbuf();
if( streamName == "debug" ) return new StreamBufImpl<OutputDebugWriter>;
throw std::domain_error( "Unknown stream: " + streamName );
}
}

71
internal/catch_stream.hpp Normal file
View File

@ -0,0 +1,71 @@
/*
* catch_stream.hpp
* Catch
*
* Created by Phil on 17/01/2011.
* Copyright 2011 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_STREAM_HPP_INCLUDED
#define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED
#include <stdexcept>
namespace Catch
{
template<typename WriterF, size_t bufferSize=256>
class StreamBufImpl : public StreamBufBase
{
char data[bufferSize];
WriterF m_writer;
public:
StreamBufImpl()
{
setp( data, data + sizeof(data) );
}
~StreamBufImpl()
{
sync();
}
private:
int overflow( int c )
{
sync();
if( c != EOF )
{
if( pbase() == epptr() )
m_writer( std::string( 1, (char)c ) );
else
sputc( c );
}
return 0;
}
int sync()
{
if( pbase() != pptr() )
{
m_writer( std::string( pbase(), pptr() - pbase() ) );
setp( pbase(), epptr() );
}
return 0;
}
};
struct OutputDebugWriter
{
void operator()( const std::string &str )
{
writeToDebugConsole( str );
}
};
}
#endif // TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED