2011-01-27 23:29:36 +01:00
|
|
|
/*
|
|
|
|
* 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"
|
|
|
|
|
2011-02-04 10:30:36 +01:00
|
|
|
#include <iterator>
|
2011-01-27 23:29:36 +01:00
|
|
|
#include <vector>
|
|
|
|
#include <string>
|
2011-02-04 10:30:36 +01:00
|
|
|
#include <stdlib.h>
|
2011-01-27 23:29:36 +01:00
|
|
|
|
|
|
|
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
|
|
|
|
{
|
2011-03-09 20:45:05 +01:00
|
|
|
return m_from+static_cast<T>( index );
|
2011-01-27 23:29:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
virtual std::size_t size
|
|
|
|
()
|
|
|
|
const
|
|
|
|
{
|
2012-05-09 09:17:51 +02:00
|
|
|
return static_cast<std::size_t>( 1+m_to-m_from );
|
2011-01-27 23:29:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
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 )
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2011-02-23 10:06:05 +01:00
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
// *** Move semantics, similar to auto_ptr ***
|
|
|
|
CompositeGenerator( CompositeGenerator& other )
|
|
|
|
: m_fileInfo( other.m_fileInfo ),
|
|
|
|
m_totalSize( 0 )
|
|
|
|
{
|
|
|
|
move( other );
|
|
|
|
}
|
|
|
|
|
2011-01-27 23:29:36 +01:00
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
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 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();
|
|
|
|
}
|
2011-02-23 10:06:05 +01:00
|
|
|
CATCH_INTERNAL_ERROR( "Indexed past end of generated range" );
|
2011-03-15 19:49:07 +01:00
|
|
|
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
|
2011-01-27 23:29:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
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
|