Refactored constraints

git-svn-id: https://svn.code.sf.net/p/turtle/code/trunk@179 860be788-9bd5-4423-9f1e-828f051e677b
This commit is contained in:
mat007 2011-01-10 22:14:31 +00:00
parent 176611c735
commit 3b6e4f6d37
12 changed files with 204 additions and 454 deletions

View file

@ -168,6 +168,10 @@
RelativePath="..\..\src\libraries\turtle\config.hpp"
>
</File>
<File
RelativePath="..\..\src\libraries\turtle\constraint.hpp"
>
</File>
<File
RelativePath="..\..\src\libraries\turtle\constraints.hpp"
>
@ -188,14 +192,6 @@
RelativePath="..\..\src\libraries\turtle\function.hpp"
>
</File>
<File
RelativePath="..\..\src\libraries\turtle\functional.hpp"
>
</File>
<File
RelativePath="..\..\src\libraries\turtle\has_operator.hpp"
>
</File>
<File
RelativePath="..\..\src\libraries\turtle\invocation.hpp"
>
@ -220,10 +216,6 @@
RelativePath="..\..\src\libraries\turtle\operators.hpp"
>
</File>
<File
RelativePath="..\..\src\libraries\turtle\placeholder.hpp"
>
</File>
<File
RelativePath="..\..\src\libraries\turtle\root.hpp"
>

View file

@ -206,10 +206,6 @@
RelativePath="..\..\src\tests\turtle_test\function_test.cpp"
>
</File>
<File
RelativePath="..\..\src\tests\turtle_test\has_operator_test.cpp"
>
</File>
<File
RelativePath="..\..\src\tests\turtle_test\integration_test.cpp"
>

View file

@ -9,10 +9,9 @@
#ifndef MOCK_CHECK_HPP_INCLUDED
#define MOCK_CHECK_HPP_INCLUDED
#include "placeholder.hpp"
#include "is_functor.hpp"
#include "has_operator.hpp"
#include "constraints.hpp"
#include "operators.hpp"
#include "format.hpp"
#include <boost/function.hpp>
#include <boost/utility/enable_if.hpp>
@ -68,10 +67,7 @@ namespace detail
template< typename Functor >
explicit check( const Functor& f,
BOOST_DEDUCED_TYPENAME boost::enable_if<
BOOST_DEDUCED_TYPENAME boost::mpl::or_<
BOOST_DEDUCED_TYPENAME detail::is_functor< Functor >,
BOOST_DEDUCED_TYPENAME detail::has_operator< Functor, Actual > // $$$$ MAT : add a has_const_operator too ?
>
BOOST_DEDUCED_TYPENAME detail::is_functor< Functor >
>::type* = 0 )
: desc_( mock::format( f ) )
{
@ -83,10 +79,7 @@ namespace detail
template< typename Expected >
explicit check( const Expected& expected,
BOOST_DEDUCED_TYPENAME boost::disable_if<
BOOST_DEDUCED_TYPENAME boost::mpl::or_<
BOOST_DEDUCED_TYPENAME detail::is_functor< Expected >,
BOOST_DEDUCED_TYPENAME detail::has_operator< Expected, Actual >
>
BOOST_DEDUCED_TYPENAME detail::is_functor< Expected >
>::type* = 0 )
: desc_( mock::format( expected ) )
{
@ -96,8 +89,8 @@ namespace detail
std::invalid_argument( "invalid constraint" );
}
template< typename Functor >
explicit check( const placeholder< Functor >& ph )
: desc_( ph.desc_ )
explicit check( const constraint< Functor >& ph )
: desc_( mock::format( ph.f_ ) )
{
BOOST_CONCEPT_ASSERT(( FunctorCompatible< Functor, Actual > ));
f_ = ph.f_;

View file

@ -0,0 +1,26 @@
//
// Copyright Mathieu Champlon 2008
//
// 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 MOCK_PLACEHOLDER_HPP_INCLUDED
#define MOCK_PLACEHOLDER_HPP_INCLUDED
#include "format.hpp"
namespace mock
{
template< typename Constraint >
struct constraint
{
constraint( const Constraint& c )
: f_( c )
{}
Constraint f_;
};
}
#endif // #ifndef MOCK_PLACEHOLDER_HPP_INCLUDED

View file

@ -9,103 +9,173 @@
#ifndef MOCK_CONSTRAINTS_HPP_INCLUDED
#define MOCK_CONSTRAINTS_HPP_INCLUDED
#include "functional.hpp"
#include "operators.hpp"
#include "constraint.hpp"
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/preprocessor/stringize.hpp>
namespace mock
{
#define MOCK_CONSTRAINT(N,Expr) \
namespace detail \
{ \
struct N \
{ \
template< typename Actual > \
bool operator()( const Actual& actual ) const \
{ \
(void)actual; \
return Expr; \
} \
friend std::ostream& operator<<( std::ostream& os, const N& ) \
{ \
return os << BOOST_STRINGIZE( N ); \
} \
}; \
} \
template<> \
struct constraint< detail::N > \
{ \
constraint() \
{} \
detail::N f_; \
}; \
const constraint< detail::N > N;
MOCK_CONSTRAINT( any, true )
MOCK_CONSTRAINT( negate, ! actual )
MOCK_CONSTRAINT( evaluate, actual() )
#undef MOCK_CONSTRAINT
#define MOCK_CONSTRAINT(N,Expr) \
namespace detail \
{ \
template< typename Expected > \
struct N \
{ \
explicit N( const Expected& expected ) \
: expected_( expected ) \
{} \
template< typename Actual > \
bool operator()( const Actual& actual ) const \
{ \
return Expr; \
} \
friend std::ostream& operator<<( std::ostream& os, const N& n ) \
{ \
return os << BOOST_STRINGIZE( N ) << "( " << mock::format( n.expected_ ) << " )"; \
} \
Expected expected_; \
}; \
} \
template< typename T > \
constraint< detail::N< T > > N( T t ) \
{ \
return detail::N< T >( t ); \
}
MOCK_CONSTRAINT( equal, actual == expected_ )
MOCK_CONSTRAINT( less, actual < expected_ )
MOCK_CONSTRAINT( greater, actual > expected_ )
MOCK_CONSTRAINT( less_equal, actual <= expected_ )
MOCK_CONSTRAINT( greater_equal, actual >= expected_ )
MOCK_CONSTRAINT( contain, boost::algorithm::contains( actual, expected_ ) )
namespace detail
{
template<>
struct placeholder< any >
template< typename Expected >
struct same
{
placeholder()
: desc_( "any" )
explicit same( const Expected& expected )
: expected_( &expected )
{}
any f_;
std::string desc_;
template< typename Actual >
bool operator()( const Actual& actual ) const
{
return &actual == expected_;
}
friend std::ostream& operator<<( std::ostream& os, const same& s )
{
return os << "same( " << mock::format( *s.expected_ ) << " )";
}
const Expected* expected_;
};
template<>
struct placeholder< negate >
template< typename Expected >
struct assign
{
placeholder()
: desc_( "negate" )
explicit assign( const Expected& expected )
: expected_( expected )
{}
negate f_;
std::string desc_;
template< typename Actual >
bool operator()( Actual& actual,
BOOST_DEDUCED_TYPENAME boost::disable_if<
boost::is_convertible< Expected*, Actual >, Actual >::type* = 0 ) const
{
actual = expected_;
return true;
}
template< typename Actual >
bool operator()( Actual* actual,
BOOST_DEDUCED_TYPENAME boost::enable_if<
boost::is_convertible< Expected, Actual >, Actual >::type* = 0 ) const
{
*actual = expected_;
return true;
}
friend std::ostream& operator<<( std::ostream& os, const assign& a )
{
return os << "assign( " << mock::format( a.expected_ ) << " )";
}
Expected expected_;
};
template<>
struct placeholder< evaluate >
template< typename Expected >
struct retrieve
{
placeholder()
: desc_( "evaluate" )
explicit retrieve( Expected& expected )
: expected_( &expected )
{}
evaluate f_;
std::string desc_;
template< typename Actual >
bool operator()( const Actual& actual,
BOOST_DEDUCED_TYPENAME boost::disable_if<
boost::is_convertible< const Actual*, Expected >, Actual >::type* = 0 ) const
{
*expected_ = actual;
return true;
}
template< typename Actual >
bool operator()( Actual& actual,
BOOST_DEDUCED_TYPENAME boost::enable_if<
boost::is_convertible< Actual*, Expected >, Actual >::type* = 0 ) const
{
*expected_ = &actual;
return true;
}
friend std::ostream& operator<<( std::ostream& os, const retrieve& r )
{
return os << "retrieve( " << mock::format( *r.expected_ ) << " )";
}
Expected* expected_;
};
}
const detail::placeholder< detail::any > any;
const detail::placeholder< detail::negate > negate;
const detail::placeholder< detail::evaluate > evaluate;
template< typename T >
detail::placeholder< detail::equal< T > > equal( T t )
constraint< detail::same< T > > same( T& t )
{
return constraint( detail::equal< T >( t ), "equal", t );
return detail::same< T >( t );
}
template< typename T >
detail::placeholder< detail::same< T > > same( T& t )
constraint< detail::retrieve< T > > retrieve( T& t )
{
return constraint( detail::same< T >( t ), "same", &t );
return detail::retrieve< T >( t );
}
template< typename T >
detail::placeholder< detail::less< T > > less( T t )
constraint< detail::assign< T > > assign( T t )
{
return constraint( detail::less< T >( t ), "less", t );
}
template< typename T >
detail::placeholder< detail::greater< T > > greater( T t )
{
return constraint( detail::greater< T >( t ), "greater", t );
}
template< typename T >
detail::placeholder<
detail::or_< detail::less< T >, detail::equal< T > > >
less_equal( T t )
{
return constraint( (less( t ) || equal( t )).f_,
"less_equal", t );
}
template< typename T >
detail::placeholder<
detail::or_< detail::greater< T >, detail::equal< T > > >
greater_equal( T t )
{
return constraint( (greater( t ) || equal( t )).f_,
"greater_equal", t );
}
template< typename T >
detail::placeholder< detail::assign< T > > assign( T t )
{
return constraint( detail::assign< T >( t ), "assign", t );
}
template< typename T >
detail::placeholder< detail::retrieve< T > > retrieve( T& t )
{
return constraint( detail::retrieve< T >( t ), "retrieve", t );
}
template< typename T >
detail::placeholder< detail::contains< T > > contain( T t )
{
return constraint( detail::contains< T >( t ), "contain", t );
return detail::assign< T >( t );
}
}

View file

@ -1,187 +0,0 @@
//
// Copyright Mathieu Champlon 2008
//
// 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 MOCK_FUNCTIONAL_HPP_INCLUDED
#define MOCK_FUNCTIONAL_HPP_INCLUDED
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <boost/algorithm/string/predicate.hpp>
namespace mock
{
namespace detail
{
class any
{
public:
template< typename Actual >
bool operator()( const Actual& ) const
{
return true;
}
};
class negate
{
public:
template< typename Actual >
bool operator()( const Actual& actual ) const
{
return ! actual;
}
};
class evaluate
{
public:
template< typename Actual >
bool operator()( const Actual& actual ) const
{
return actual();
}
};
template< typename Expected >
class equal
{
public:
explicit equal( const Expected& expected )
: expected_( expected )
{}
template< typename Actual >
bool operator()( const Actual& actual ) const
{
return actual == expected_;
}
private:
Expected expected_;
};
template< typename Expected >
class same
{
public:
explicit same( const Expected& expected )
: expected_( &expected )
{}
template< typename Actual >
bool operator()( const Actual& actual ) const
{
return &actual == expected_;
}
private:
const Expected* expected_;
};
template< typename Expected >
class less
{
public:
explicit less( const Expected& expected )
: expected_( expected )
{}
template< typename Actual >
bool operator()( const Actual& actual ) const
{
return actual < expected_;
}
private:
Expected expected_;
};
template< typename Expected >
class greater
{
public:
explicit greater( const Expected& expected )
: expected_( expected )
{}
template< typename Actual >
bool operator()( const Actual& actual ) const
{
return actual > expected_;
}
private:
Expected expected_;
};
template< typename Expected >
class assign
{
public:
explicit assign( const Expected& expected )
: expected_( expected )
{}
template< typename Actual >
bool operator()( Actual& actual,
BOOST_DEDUCED_TYPENAME boost::disable_if<
boost::is_convertible< Expected*, Actual >, Actual >::type* = 0 ) const
{
actual = expected_;
return true;
}
template< typename Actual >
bool operator()( Actual* actual,
BOOST_DEDUCED_TYPENAME boost::enable_if<
boost::is_convertible< Expected, Actual >, Actual >::type* = 0 ) const
{
*actual = expected_;
return true;
}
private:
Expected expected_;
};
template< typename Expected >
class retrieve
{
public:
explicit retrieve( Expected& expected )
: expected_( &expected )
{}
template< typename Actual >
bool operator()( const Actual& actual,
BOOST_DEDUCED_TYPENAME boost::disable_if<
boost::is_convertible< const Actual*, Expected >, Actual >::type* = 0 ) const
{
*expected_ = actual;
return true;
}
template< typename Actual >
bool operator()( Actual& actual,
BOOST_DEDUCED_TYPENAME boost::enable_if<
boost::is_convertible< Actual*, Expected >, Actual >::type* = 0 ) const
{
*expected_ = &actual;
return true;
}
private:
Expected* expected_;
};
template< typename Expected >
class contains
{
public:
explicit contains( const Expected& expected )
: expected_( expected )
{}
template< typename Actual >
bool operator()( const Actual& actual ) const
{
return boost::algorithm::contains( actual, expected_ );
}
private:
Expected expected_;
};
}
}
#endif // #ifndef MOCK_FUNCTIONAL_HPP_INCLUDED

View file

@ -1,34 +0,0 @@
//
// Copyright Mathieu Champlon 2011
//
// 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 MOCK_HAS_OPERATOR_HPP_INCLUDED
#define MOCK_HAS_OPERATOR_HPP_INCLUDED
#include <boost/function_types/is_callable_builtin.hpp>
#include <boost/type_traits/integral_constant.hpp>
#include <boost/type_traits/detail/yes_no_type.hpp>
namespace mock
{
namespace detail
{
typedef boost::type_traits::yes_type yes_type;
typedef boost::type_traits::no_type no_type;
template< typename T, typename Actual, bool(T::*)( Actual ) const > struct has_operator_helper_class {};
template< typename T, typename Actual > yes_type& has_operator_helper( has_operator_helper_class< T, Actual, &T::operator() >* );
template< typename T, typename Actual > no_type& has_operator_helper( ... );
template< typename T, typename Actual > struct has_operator
: boost::mpl::bool_< sizeof( has_operator_helper< T, Actual >( 0 ) ) == sizeof( yes_type ) >
{};
}
}
#endif // #ifndef MOCK_HAS_OPERATOR_HPP_INCLUDED

View file

@ -9,7 +9,7 @@
#ifndef MOCK_OPERATORS_HPP_INCLUDED
#define MOCK_OPERATORS_HPP_INCLUDED
#include "placeholder.hpp"
#include "constraint.hpp"
namespace mock
{
@ -28,6 +28,10 @@ namespace detail
{
return f1_( actual ) && f2_( actual );
}
friend std::ostream& operator<<( std::ostream& os, const and_& a )
{
return os << "( " << a.f1_ << " && " << a.f2_ << " )";
}
private:
Functor1 f1_;
Functor2 f2_;
@ -46,6 +50,10 @@ namespace detail
{
return f1_( actual ) || f2_( actual );
}
friend std::ostream& operator<<( std::ostream& os, const or_& o )
{
return os << "( " << o.f1_ << " || " << o.f2_ << " )";
}
private:
Functor1 f1_;
Functor2 f2_;
@ -63,37 +71,36 @@ namespace detail
{
return ! f_( actual );
}
friend std::ostream& operator<<( std::ostream& os, const not_& n )
{
return os << "! " << n.f_;
}
private:
Functor f_;
};
template< typename Functor1, typename Functor2 >
const placeholder< or_< Functor1, Functor2 > >
operator||( const placeholder< Functor1 >& lhs,
const placeholder< Functor2 >& rhs )
{
return constraint(
or_< Functor1, Functor2 >( lhs.f_, rhs.f_ ),
"(" + lhs.desc_ + " || " + rhs.desc_ + ")" );
}
template< typename Functor1, typename Functor2 >
const placeholder< and_< Functor1, Functor2 > >
operator&&( const placeholder< Functor1 >& lhs,
const placeholder< Functor2 >& rhs )
const constraint< detail::or_< Functor1, Functor2 > >
operator||( const constraint< Functor1 >& lhs,
const constraint< Functor2 >& rhs )
{
return constraint(
and_< Functor1, Functor2 >( lhs.f_, rhs.f_ ),
"(" + lhs.desc_ + " && " + rhs.desc_ + ")" );
return detail::or_< Functor1, Functor2 >( lhs.f_, rhs.f_ );
}
template< typename Functor1, typename Functor2 >
const constraint< detail::and_< Functor1, Functor2 > >
operator&&( const constraint< Functor1 >& lhs,
const constraint< Functor2 >& rhs )
{
return detail::and_< Functor1, Functor2 >( lhs.f_, rhs.f_ );
}
template< typename Functor >
const placeholder< not_< Functor > >
operator!( const placeholder< Functor >& ph )
const constraint< detail::not_< Functor > >
operator!( const constraint< Functor >& ph )
{
return constraint(
not_< Functor >( ph.f_ ), "! " + ph.desc_ );
}
return detail::not_< Functor >( ph.f_ );
}
}

View file

@ -1,53 +0,0 @@
//
// Copyright Mathieu Champlon 2008
//
// 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 MOCK_PLACEHOLDER_HPP_INCLUDED
#define MOCK_PLACEHOLDER_HPP_INCLUDED
#include "format.hpp"
namespace mock
{
namespace detail
{
template< typename Functor >
struct placeholder
{
placeholder( const Functor& f, const std::string& desc )
: f_( f )
, desc_( desc )
{}
Functor f_;
std::string desc_;
};
}
template< typename Functor, typename Description >
const detail::placeholder< Functor > constraint( const Functor& f,
const Description& desc )
{
std::stringstream s;
s << std::boolalpha << desc;
return detail::placeholder< Functor >( f, s.str() );
}
template< typename Functor >
const detail::placeholder< Functor > constraint( const Functor& f )
{
return detail::placeholder< Functor >( f, "?" );
}
template< typename Functor, typename T >
const detail::placeholder< Functor > constraint( const Functor& f,
const std::string& name,
const T& t )
{
return detail::placeholder< Functor >( f,
name + "( " + mock::format( t ) + " )" );
}
}
#endif // #ifndef MOCK_PLACEHOLDER_HPP_INCLUDED

View file

@ -337,13 +337,6 @@ BOOST_FIXTURE_TEST_CASE( triggering_an_expectation_with_failing_custom_constrain
}
}
BOOST_FIXTURE_TEST_CASE( triggering_an_expectation_with_wrong_parameter_value_in_custom_constraint_calls_unexpected_call_error, error_fixture )
{
mock::function< void( int ) > f;
f.expect().with( mock::constraint( &custom_constraint, "custom constraint" ) );
CHECK_ERROR( f( 42 ), unexpected_call, 0 );
}
/*
BOOST_FIXTURE_TEST_CASE( literal_zero_can_be_used_in_place_of_null_pointers_in_constraints, error_fixture )
{
@ -715,24 +708,6 @@ BOOST_FIXTURE_TEST_CASE( expectation_can_be_serialized_to_be_human_readable, err
BOOST_CHECK_EQUAL( expected, to_string( f ) );
f.reset();
}
{
mock::function< void( int ) > f;
f.tag( "my function" );
f.expect().once().with( mock::constraint( &custom_constraint, "custom constraint" ) );
const std::string expected = "my function\n"
". once().with( custom constraint )";
BOOST_CHECK_EQUAL( expected, to_string( f ) );
f.reset();
}
{
mock::function< void( int ) > f;
f.tag( "my function" );
f.expect().once().with( mock::constraint( &custom_constraint, true ) );
const std::string expected = "my function\n"
". once().with( true )";
BOOST_CHECK_EQUAL( expected, to_string( f ) );
f.reset();
}
}
BOOST_FIXTURE_TEST_CASE( expectation_with_remaining_untriggered_matches_upon_destruction_calls_untriggered_expectation, error_fixture )

View file

@ -1,35 +0,0 @@
//
// Copyright Mathieu Champlon 2009
//
// 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 <turtle/has_operator.hpp>
#include <boost/test/auto_unit_test.hpp>
#define BOOST_LIB_NAME boost_unit_test_framework
#include <boost/config/auto_link.hpp>
namespace
{
struct functor_with_valid_operator
{
bool operator()( float ) const
{
return true;
}
};
BOOST_STATIC_ASSERT(( mock::detail::has_operator< functor_with_valid_operator, float >::type::value ));
struct functor_with_valid_template_operator
{
template< typename T >
bool operator()( T ) const
{
return true;
}
};
BOOST_STATIC_ASSERT(( mock::detail::has_operator< functor_with_valid_template_operator, float >::type::value ));
}

View file

@ -342,7 +342,7 @@ namespace
Expected threshold_;
};
template< typename Expected >
near_constraint< Expected > near( Expected expected, Expected threshold )
mock::constraint< near_constraint< Expected > > near( Expected expected, Expected threshold )
{
return near_constraint< Expected >( expected, threshold );
}