1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190
|
/*
* 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_context.h"
#include <iterator>
#include <vector>
#include <string>
#include <stdlib.h>
namespace Catch {
template<typename T>
struct IGenerator {
virtual ~IGenerator() {}
virtual T getValue( std::size_t index ) const = 0;
virtual std::size_t size () const = 0;
};
template<typename T>
class BetweenGenerator : public IGenerator<T> {
public:
BetweenGenerator( T from, T to ) : m_from( from ), m_to( to ){}
virtual T getValue( std::size_t index ) const {
return m_from+static_cast<int>( index );
}
virtual std::size_t size() const {
return static_cast<std::size_t>( 1+m_to-m_from );
}
private:
T m_from;
T m_to;
};
template<typename T>
class ValuesGenerator : public IGenerator<T> {
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<T> m_values;
};
template<typename T>
class CompositeGenerator {
public:
CompositeGenerator() : m_totalSize( 0 ) {}
// *** Move semantics, similar to auto_ptr ***
CompositeGenerator( CompositeGenerator& other )
: m_fileInfo( other.m_fileInfo ),
m_totalSize( 0 )
{
move( other );
}
CompositeGenerator& setFileInfo( const char* fileInfo ) {
m_fileInfo = fileInfo;
return *this;
}
~CompositeGenerator() {
deleteAll( m_composed );
}
operator T () const {
size_t overallIndex = getCurrentContext().getGeneratorIndex( m_fileInfo, m_totalSize );
typename std::vector<const IGenerator<T>*>::const_iterator it = m_composed.begin();
typename std::vector<const IGenerator<T>*>::const_iterator itEnd = m_composed.end();
for( size_t index = 0; it != itEnd; ++it )
{
const IGenerator<T>* generator = *it;
if( overallIndex >= index && overallIndex < index + generator->size() )
{
return generator->getValue( overallIndex-index );
}
index += generator->size();
}
CATCH_INTERNAL_ERROR( "Indexed past end of generated range" );
return T(); // Suppress spurious "not all control paths return a value" warning in Visual Studio - if you know how to fix this please do so
}
void add( const IGenerator<T>* generator ) {
m_totalSize += generator->size();
m_composed.push_back( generator );
}
CompositeGenerator& then( CompositeGenerator& other ) {
move( other );
return *this;
}
CompositeGenerator& then( T value ) {
ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
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<const IGenerator<T>*> m_composed;
std::string m_fileInfo;
size_t m_totalSize;
};
namespace Generators
{
template<typename T>
CompositeGenerator<T> between( T from, T to ) {
CompositeGenerator<T> generators;
generators.add( new BetweenGenerator<T>( from, to ) );
return generators;
}
template<typename T>
CompositeGenerator<T> values( T val1, T val2 ) {
CompositeGenerator<T> generators;
ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
valuesGen->add( val1 );
valuesGen->add( val2 );
generators.add( valuesGen );
return generators;
}
template<typename T>
CompositeGenerator<T> values( T val1, T val2, T val3 ){
CompositeGenerator<T> generators;
ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
valuesGen->add( val1 );
valuesGen->add( val2 );
valuesGen->add( val3 );
generators.add( valuesGen );
return generators;
}
template<typename T>
CompositeGenerator<T> values( T val1, T val2, T val3, T val4 ) {
CompositeGenerator<T> generators;
ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
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
|