From 5cad9d5a8691abdbffb9136706963e19c4a43808 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Thu, 27 Jan 2011 22:29:36 +0000 Subject: [PATCH] Multiple generators working and factored out a bit better --- Test/MiscTests.cpp | 18 ++ Test/Test.xcodeproj/project.pbxproj | 2 + catch.hpp | 7 +- catch_reporter_basic.hpp | 2 +- catch_reporter_junit.hpp | 2 +- catch_reporter_xml.hpp | 2 +- internal/catch_generators.hpp | 298 +++++++++++++++++++++++++ internal/catch_hub_impl.hpp | 30 +-- internal/catch_reporter_registrars.hpp | 2 +- internal/catch_section.hpp | 2 +- 10 files changed, 340 insertions(+), 25 deletions(-) create mode 100644 internal/catch_generators.hpp diff --git a/Test/MiscTests.cpp b/Test/MiscTests.cpp index 59084f85..f1451c07 100644 --- a/Test/MiscTests.cpp +++ b/Test/MiscTests.cpp @@ -80,6 +80,24 @@ TEST_CASE( "./succeeding/Misc/stdout,stderr", "Sends stuff to stdout and stderr" std::cerr << "An error"; } +size_t multiply( int a, int b ) +{ + return a*b; +} + + +TEST_CASE( "./succeeding/generators/1", "Generators over two ranges" ) +{ + using namespace Catch::Generators; + + size_t i = GENERATE( between( 1, 5 ).then( values( 15, 20, 21 ).then( 36 ) ) ); + size_t j = GENERATE( between( 100, 107 ) ); + + REQUIRE( multiply( i, 2 ) == i*2 ); + REQUIRE( multiply( j, 2 ) == j*2 ); +} + + // An unnamed test case. A name, of the form, "unnamed/#" is generated, where // # is an incrementing integer ANON_TEST_CASE() diff --git a/Test/Test.xcodeproj/project.pbxproj b/Test/Test.xcodeproj/project.pbxproj index f338af2b..4be4dff2 100644 --- a/Test/Test.xcodeproj/project.pbxproj +++ b/Test/Test.xcodeproj/project.pbxproj @@ -41,6 +41,7 @@ 4A3BFFB8128DCF06005609E3 /* TestMain.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TestMain.cpp; sourceTree = ""; }; 4A3BFFF0128DD23C005609E3 /* catch_config.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = catch_config.hpp; path = ../internal/catch_config.hpp; sourceTree = SOURCE_ROOT; }; 4A6D514B12C8A547008F0415 /* catch_debugger.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = catch_debugger.hpp; path = ../internal/catch_debugger.hpp; sourceTree = SOURCE_ROOT; }; + 4A8A68FF12F1F75100ACED26 /* catch_generators.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = catch_generators.hpp; path = ../internal/catch_generators.hpp; sourceTree = SOURCE_ROOT; }; 4A992A6512B2156C002B7B66 /* catch_xmlwriter.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = catch_xmlwriter.hpp; path = ../internal/catch_xmlwriter.hpp; sourceTree = SOURCE_ROOT; }; 4A992A6612B21582002B7B66 /* catch_reporter_junit.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = catch_reporter_junit.hpp; path = ../catch_reporter_junit.hpp; sourceTree = SOURCE_ROOT; }; 4AA7EA9112A438C7005A0B97 /* MiscTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MiscTests.cpp; sourceTree = ""; }; @@ -132,6 +133,7 @@ 4AFC341912809A36003A0C29 /* catch_resultinfo.hpp */, 4AFC341A12809A36003A0C29 /* catch_runner_impl.hpp */, 4AD6783212D7ABB3005AAF59 /* catch_interfaces_runner.h */, + 4A8A68FF12F1F75100ACED26 /* catch_generators.hpp */, ); name = "Running & Results"; sourceTree = ""; diff --git a/catch.hpp b/catch.hpp index 354888e0..11897d95 100644 --- a/catch.hpp +++ b/catch.hpp @@ -27,6 +27,7 @@ #include "internal/catch_test_registry.hpp" #include "internal/catch_capture.hpp" #include "internal/catch_section.hpp" +#include "internal/catch_generators.hpp" ////// @@ -49,13 +50,15 @@ #define FAIL( reason ) INTERNAL_CATCH_MSG( reason, Catch::ResultWas::ExplicitFailure, true, "FAIL" ) #define SCOPED_INFO( log ) INTERNAL_CATCH_SCOPED_INFO( log ) -#define SECTION( name, description ) CATCH_SECTION( name, description ) +#define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) #define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description ) #define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "Anonymous test case" ) #define METHOD_AS_TEST_CASE( method, name, description ) CATCH_METHOD_AS_TEST_CASE( method, name, description ) -#define REGISTER_REPORTER( name, reporterType ) CATCH_REGISTER_REPORTER( name, reporterType ) +#define REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) + +#define GENERATE( expr) INTERNAL_CATCH_GENERATE( expr ) /////////////// // Still to be implemented diff --git a/catch_reporter_basic.hpp b/catch_reporter_basic.hpp index f207334a..def3e548 100644 --- a/catch_reporter_basic.hpp +++ b/catch_reporter_basic.hpp @@ -216,7 +216,7 @@ namespace Catch bool m_firstSectionInTestCase; }; - CATCH_REGISTER_REPORTER( "basic", BasicReporter ); + INTERNAL_CATCH_REGISTER_REPORTER( "basic", BasicReporter ); } // end namespace Catch diff --git a/catch_reporter_junit.hpp b/catch_reporter_junit.hpp index da795472..871f844f 100644 --- a/catch_reporter_junit.hpp +++ b/catch_reporter_junit.hpp @@ -256,7 +256,7 @@ namespace Catch std::ostringstream m_stdErr; }; - CATCH_REGISTER_REPORTER( "junit", JunitReporter ); + INTERNAL_CATCH_REGISTER_REPORTER( "junit", JunitReporter ); } // end namespace Catch diff --git a/catch_reporter_xml.hpp b/catch_reporter_xml.hpp index 95f92619..4d6bb349 100644 --- a/catch_reporter_xml.hpp +++ b/catch_reporter_xml.hpp @@ -168,7 +168,7 @@ namespace Catch XmlWriter m_xml; }; - CATCH_REGISTER_REPORTER( "xml", XmlReporter ); + INTERNAL_CATCH_REGISTER_REPORTER( "xml", XmlReporter ); } // end namespace Catch diff --git a/internal/catch_generators.hpp b/internal/catch_generators.hpp new file mode 100644 index 00000000..a6167a4e --- /dev/null +++ b/internal/catch_generators.hpp @@ -0,0 +1,298 @@ +/* + * catch_generators.hpp + * Catch + * + * Created by Phil on 27/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_GENERATORS_HPP_INCLUDED +#define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED + +#include "catch_hub.h" + +#include +#include + +namespace Catch +{ + +template +struct IGenerator +{ + virtual ~IGenerator + () + {} + + virtual T getValue + ( std::size_t index + ) const = 0; + + virtual std::size_t size + () const = 0; +}; + +template +class BetweenGenerator : public IGenerator +{ +public: + /////////////////////////////////////////////////////////////////////////// + BetweenGenerator + ( + T from, + T to + ) + : m_from( from ), + m_to( to ) + { + } + + /////////////////////////////////////////////////////////////////////////// + virtual T getValue + ( + std::size_t index + ) + const + { + return m_from+index; + } + + /////////////////////////////////////////////////////////////////////////// + virtual std::size_t size + () + const + { + return 1+m_to-m_from; + } + +private: + + T m_from; + T m_to; +}; + +template +class ValuesGenerator : public IGenerator +{ +public: + /////////////////////////////////////////////////////////////////////////// + ValuesGenerator + () + { + } + + /////////////////////////////////////////////////////////////////////////// + void add + ( + T value + ) + { + m_values.push_back( value ); + } + + /////////////////////////////////////////////////////////////////////////// + virtual T getValue + ( + std::size_t index + ) + const + { + return m_values[index]; + } + + /////////////////////////////////////////////////////////////////////////// + virtual std::size_t size + () + const + { + return m_values.size(); + } + +private: + + std::vector m_values; +}; + +template +class CompositeGenerator +{ +public: + /////////////////////////////////////////////////////////////////////////// + CompositeGenerator() + : m_totalSize( 0 ) + { + } + + /////////////////////////////////////////////////////////////////////////// + CompositeGenerator& setFileInfo + ( + const char* fileInfo + ) + { + m_fileInfo = fileInfo; + return *this; + } + + /////////////////////////////////////////////////////////////////////////// + ~CompositeGenerator + () + { + deleteAll( m_composed ); + } + + /////////////////////////////////////////////////////////////////////////// + operator T + () + const + { + size_t overallIndex = Hub::getGeneratorIndex( m_fileInfo, m_totalSize ); + + typename std::vector*>::const_iterator it = m_composed.begin(); + typename std::vector*>::const_iterator itEnd = m_composed.end(); + for( size_t index = 0; it != itEnd; ++it ) + { + const IGenerator* generator = *it; + if( overallIndex >= index && overallIndex < index + generator->size() ) + { + return generator->getValue( overallIndex-index ); + } + index += generator->size(); + } + throw "this should never happen!"; + } + + /////////////////////////////////////////////////////////////////////////// + void add + ( + const IGenerator* generator + ) + { + m_totalSize += generator->size(); + m_composed.push_back( generator ); + } + + /////////////////////////////////////////////////////////////////////////// + CompositeGenerator& then + ( + CompositeGenerator& other + ) + { + move( other ); + return *this; + } + + /////////////////////////////////////////////////////////////////////////// + CompositeGenerator& then + ( + T value + ) + { + ValuesGenerator* valuesGen = new ValuesGenerator(); + valuesGen->add( value ); + add( valuesGen ); + return *this; + } + +private: + + /////////////////////////////////////////////////////////////////////////// + void move + ( + CompositeGenerator& other + ) + { + std::copy( other.m_composed.begin(), other.m_composed.end(), std::back_inserter( m_composed ) ); + m_totalSize += other.m_totalSize; + other.m_composed.clear(); + } + + std::vector*> m_composed; + std::string m_fileInfo; + size_t m_totalSize; +}; + +namespace Generators +{ + /////////////////////////////////////////////////////////////////////////// + template + CompositeGenerator between + ( + T from, + T to + ) + { + CompositeGenerator generators; + generators.add( new BetweenGenerator( from, to ) ); + return generators; + } + + /////////////////////////////////////////////////////////////////////////// + template + CompositeGenerator values + ( + T val1, + T val2 + ) + { + CompositeGenerator generators; + ValuesGenerator* valuesGen = new ValuesGenerator(); + valuesGen->add( val1 ); + valuesGen->add( val2 ); + generators.add( valuesGen ); + return generators; + } + + /////////////////////////////////////////////////////////////////////////// + template + CompositeGenerator values + ( + T val1, + T val2, + T val3 + ) + { + CompositeGenerator generators; + ValuesGenerator* valuesGen = new ValuesGenerator(); + valuesGen->add( val1 ); + valuesGen->add( val2 ); + valuesGen->add( val3 ); + generators.add( valuesGen ); + return generators; + } + + /////////////////////////////////////////////////////////////////////////// + template + CompositeGenerator values + ( + T val1, + T val2, + T val3, + T val4 + ) + { + CompositeGenerator generators; + ValuesGenerator* valuesGen = new ValuesGenerator(); + valuesGen->add( val1 ); + valuesGen->add( val2 ); + valuesGen->add( val3 ); + valuesGen->add( val4 ); + generators.add( valuesGen ); + return generators; + } + +} // end namespace Generators + +using namespace Generators; + +} // end namespace Catch + +#define INTERNAL_CATCH_LINESTR2( line ) #line +#define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line ) + +#define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" ) + +#endif // TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED diff --git a/internal/catch_hub_impl.hpp b/internal/catch_hub_impl.hpp index 71608675..fd1ab55d 100644 --- a/internal/catch_hub_impl.hpp +++ b/internal/catch_hub_impl.hpp @@ -96,18 +96,12 @@ namespace Catch { } - void reset - () - { - m_currentIndex = 0; - } - bool moveNext () { if( ++m_currentIndex == m_size ) { - reset(); + m_currentIndex = 0; return false; } return true; @@ -157,20 +151,19 @@ namespace Catch return *it->second; } - void reset - () - { - std::vector::const_iterator it = m_generatorsInOrder.begin(); - std::vector::const_iterator itEnd = m_generatorsInOrder.begin(); - for(; it != itEnd; ++it ) - { - (*it)->reset(); - } - } - bool moveNext () { + std::vector::const_iterator it = m_generatorsInOrder.begin(); + std::vector::const_iterator itEnd = m_generatorsInOrder.end(); + for(; it != itEnd; ++it ) + { + if( (*it)->moveNext() ) + return true; + } + return false; + + /* if( !m_generatorsInOrder[m_currentGenerator]->moveNext() ) { if( ++m_currentGenerator == m_generatorsInOrder.size() ) @@ -180,6 +173,7 @@ namespace Catch } } return true; + */ } private: diff --git a/internal/catch_reporter_registrars.hpp b/internal/catch_reporter_registrars.hpp index 60725ad9..f576732e 100644 --- a/internal/catch_reporter_registrars.hpp +++ b/internal/catch_reporter_registrars.hpp @@ -52,7 +52,7 @@ namespace Catch }; } -#define CATCH_REGISTER_REPORTER( name, reporterType ) \ +#define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \ Catch::ReporterRegistrar catch_internal_RegistrarFor##reporterType( name ); #endif // TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED diff --git a/internal/catch_section.hpp b/internal/catch_section.hpp index 9d9f3cfc..67156d36 100644 --- a/internal/catch_section.hpp +++ b/internal/catch_section.hpp @@ -49,6 +49,6 @@ namespace Catch } // end namespace Catch -#define CATCH_SECTION( name, desc ) if( Catch::Section catch_internal_Section = Catch::Section( name, desc ) ) +#define INTERNAL_CATCH_SECTION( name, desc ) if( Catch::Section catch_internal_Section = Catch::Section( name, desc ) ) #endif // TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED