mirror of
https://github.com/mat007/turtle.git
synced 2026-06-22 12:13:43 +00:00
Added move support in actions
git-svn-id: https://svn.code.sf.net/p/turtle/code/trunk@681 860be788-9bd5-4423-9f1e-828f051e677b
This commit is contained in:
parent
fc74b61817
commit
392240a87c
7 changed files with 126 additions and 18 deletions
|
|
@ -7,6 +7,7 @@ Not yet released
|
||||||
* Added MOCK_NO_VARIADIC_MACROS to deactivate variadic macros support
|
* Added MOCK_NO_VARIADIC_MACROS to deactivate variadic macros support
|
||||||
* Added support for movable only types as parameters
|
* Added support for movable only types as parameters
|
||||||
* Added logging support for std::unique_ptr, std::shared_ptr and std::weak_ptr
|
* Added logging support for std::unique_ptr, std::shared_ptr and std::weak_ptr
|
||||||
|
* Added move support in actions
|
||||||
|
|
||||||
[endsect]
|
[endsect]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -624,6 +624,7 @@ BOOST_AUTO_TEST_CASE( demonstrates_configuring_actions )
|
||||||
{
|
{
|
||||||
mock_class c;
|
mock_class c;
|
||||||
MOCK_EXPECT( c.method ).returns( 42 );
|
MOCK_EXPECT( c.method ).returns( 42 );
|
||||||
|
MOCK_EXPECT( c.method ).moves( 42 ); // returns by moving the value
|
||||||
MOCK_EXPECT( c.method ).throws( std::runtime_error( "error !" ) );
|
MOCK_EXPECT( c.method ).throws( std::runtime_error( "error !" ) );
|
||||||
MOCK_EXPECT( c.method ).calls( &function ); // forwards 'method' parameter to 'function'
|
MOCK_EXPECT( c.method ).calls( &function ); // forwards 'method' parameter to 'function'
|
||||||
MOCK_EXPECT( c.method ).calls( boost::bind( &function, 42 ) ); // drops 'method' parameter and binds 42 as parameter to 'function'
|
MOCK_EXPECT( c.method ).calls( boost::bind( &function, 42 ) ); // drops 'method' parameter and binds 42 as parameter to 'function'
|
||||||
|
|
|
||||||
|
|
@ -419,6 +419,7 @@ An action performs additional treatments after an expectation has been deemed va
|
||||||
Synopsis :
|
Synopsis :
|
||||||
|
|
||||||
MOCK_EXPECT( identifier ).returns( value );
|
MOCK_EXPECT( identifier ).returns( value );
|
||||||
|
MOCK_EXPECT( identifier ).moves( value );
|
||||||
MOCK_EXPECT( identifier ).throws( exception );
|
MOCK_EXPECT( identifier ).throws( exception );
|
||||||
MOCK_EXPECT( identifier ).calls( functor ); // gets assigned to a boost::function and throws std::invalid_argument if empty
|
MOCK_EXPECT( identifier ).calls( functor ); // gets assigned to a boost::function and throws std::invalid_argument if empty
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -555,6 +555,57 @@ BOOST_FIXTURE_TEST_CASE( triggering_an_expectation_returns_the_set_auto_ptr_valu
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MOCK_RVALUE_REFERENCES
|
||||||
|
|
||||||
|
BOOST_FIXTURE_TEST_CASE( triggering_an_expectation_moves_the_set_lvalue, error_fixture )
|
||||||
|
{
|
||||||
|
mock::detail::function< int() > f;
|
||||||
|
int i = 3;
|
||||||
|
f.expect().moves( i );
|
||||||
|
BOOST_CHECK_NO_THROW( f() );
|
||||||
|
CHECK_CALLS( 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_FIXTURE_TEST_CASE( triggering_an_expectation_moves_the_set_const_lvalue, error_fixture )
|
||||||
|
{
|
||||||
|
mock::detail::function< int() > f;
|
||||||
|
const int i = 3;
|
||||||
|
f.expect().moves( i );
|
||||||
|
BOOST_CHECK_NO_THROW( f() );
|
||||||
|
CHECK_CALLS( 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_FIXTURE_TEST_CASE( triggering_an_expectation_moves_the_set_rvalue, error_fixture )
|
||||||
|
{
|
||||||
|
mock::detail::function< int() > f;
|
||||||
|
f.expect().moves( 3 );
|
||||||
|
BOOST_CHECK_NO_THROW( f() );
|
||||||
|
CHECK_CALLS( 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MOCK_SMART_PTR
|
||||||
|
|
||||||
|
BOOST_FIXTURE_TEST_CASE( triggering_an_expectation_moves_the_set_unique_ptr_lvalue, error_fixture )
|
||||||
|
{
|
||||||
|
mock::detail::function< std::unique_ptr< int >() > f;
|
||||||
|
std::unique_ptr< int > p( new int );
|
||||||
|
f.expect().moves( std::move( p ) );
|
||||||
|
BOOST_CHECK_NO_THROW( f() );
|
||||||
|
CHECK_CALLS( 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_FIXTURE_TEST_CASE( triggering_an_expectation_moves_the_set_unique_ptr_rvalue, error_fixture )
|
||||||
|
{
|
||||||
|
mock::detail::function< std::unique_ptr< int >() > f;
|
||||||
|
f.expect().moves( std::unique_ptr< int >( new int ) );
|
||||||
|
BOOST_CHECK_NO_THROW( f() );
|
||||||
|
CHECK_CALLS( 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // MOCK_SMART_PTR
|
||||||
|
|
||||||
BOOST_FIXTURE_TEST_CASE( triggering_an_expectation_returns_the_set_shared_ptr_value, error_fixture )
|
BOOST_FIXTURE_TEST_CASE( triggering_an_expectation_returns_the_set_shared_ptr_value, error_fixture )
|
||||||
{
|
{
|
||||||
mock::detail::function< boost::shared_ptr< A >() > f;
|
mock::detail::function< boost::shared_ptr< A >() > f;
|
||||||
|
|
|
||||||
|
|
@ -77,4 +77,10 @@
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||||
|
# ifndef MOCK_NO_RVALUE_REFERENCES
|
||||||
|
# define MOCK_RVALUE_REFERENCES
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // MOCK_CONFIG_HPP_INCLUDED
|
#endif // MOCK_CONFIG_HPP_INCLUDED
|
||||||
|
|
|
||||||
|
|
@ -13,14 +13,50 @@
|
||||||
#include "lambda.hpp"
|
#include "lambda.hpp"
|
||||||
#include <boost/type_traits/remove_reference.hpp>
|
#include <boost/type_traits/remove_reference.hpp>
|
||||||
#include <boost/type_traits/remove_const.hpp>
|
#include <boost/type_traits/remove_const.hpp>
|
||||||
|
#include <boost/noncopyable.hpp>
|
||||||
|
#include <boost/shared_ptr.hpp>
|
||||||
|
#include <boost/move/move.hpp>
|
||||||
#include <boost/function.hpp>
|
#include <boost/function.hpp>
|
||||||
#include <boost/ref.hpp>
|
#include <boost/ref.hpp>
|
||||||
#include <boost/any.hpp>
|
|
||||||
|
|
||||||
namespace mock
|
namespace mock
|
||||||
{
|
{
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
|
struct holder : boost::noncopyable
|
||||||
|
{
|
||||||
|
virtual ~holder()
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
template< typename T >
|
||||||
|
struct holder_imp : holder
|
||||||
|
{
|
||||||
|
holder_imp( BOOST_RV_REF( T ) t )
|
||||||
|
: t_( boost::move( t ) )
|
||||||
|
{}
|
||||||
|
holder_imp( const T& t )
|
||||||
|
: t_( t )
|
||||||
|
{}
|
||||||
|
T t_;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct value
|
||||||
|
{
|
||||||
|
template< typename T >
|
||||||
|
T& store( BOOST_RV_REF( T ) t )
|
||||||
|
{
|
||||||
|
h_.reset( new holder_imp< T >( boost::move( t ) ) );
|
||||||
|
return static_cast< holder_imp< T >* >( h_.get() )->t_;
|
||||||
|
}
|
||||||
|
template< typename T >
|
||||||
|
T& store( const T& t )
|
||||||
|
{
|
||||||
|
h_.reset( new holder_imp< T >( t ) );
|
||||||
|
return static_cast< holder_imp< T >* >( h_.get() )->t_;
|
||||||
|
}
|
||||||
|
boost::shared_ptr< holder > h_;
|
||||||
|
};
|
||||||
|
|
||||||
template< typename Result, typename Signature >
|
template< typename Result, typename Signature >
|
||||||
class action
|
class action
|
||||||
{
|
{
|
||||||
|
|
@ -35,18 +71,15 @@ namespace detail
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template< typename Value >
|
template< typename Value >
|
||||||
void returns( Value v )
|
void returns( const Value& v )
|
||||||
{
|
{
|
||||||
r_ = v;
|
f_ = lambda_type::make_val( boost::ref( v_.store( v ) ) );
|
||||||
f_ = lambda_type::make_val(
|
|
||||||
boost::ref( boost::any_cast< Value& >( r_ ) ) );
|
|
||||||
}
|
}
|
||||||
template< typename Value >
|
template< typename Value >
|
||||||
void returns( Value* v )
|
void returns( Value* v )
|
||||||
{
|
{
|
||||||
r_ = result_type( v );
|
|
||||||
f_ = lambda_type::make_val(
|
f_ = lambda_type::make_val(
|
||||||
boost::ref( boost::any_cast< result_type& >( r_ ) ) );
|
boost::ref( v_.store( result_type( v ) ) ) );
|
||||||
}
|
}
|
||||||
template< typename Y >
|
template< typename Y >
|
||||||
void returns( const boost::reference_wrapper< Y >& r )
|
void returns( const boost::reference_wrapper< Y >& r )
|
||||||
|
|
@ -54,6 +87,12 @@ namespace detail
|
||||||
f_ = lambda_type::make_val( r );
|
f_ = lambda_type::make_val( r );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template< typename Value >
|
||||||
|
void moves( BOOST_RV_REF( Value ) v )
|
||||||
|
{
|
||||||
|
f_ = lambda_type::make_move( v_.store( boost::move( v ) ) );
|
||||||
|
}
|
||||||
|
|
||||||
void calls( const functor_type& f )
|
void calls( const functor_type& f )
|
||||||
{
|
{
|
||||||
if( ! f )
|
if( ! f )
|
||||||
|
|
@ -73,7 +112,7 @@ namespace detail
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
boost::any r_;
|
value v_;
|
||||||
functor_type f_;
|
functor_type f_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -165,9 +204,9 @@ namespace detail
|
||||||
action()
|
action()
|
||||||
{}
|
{}
|
||||||
action( const action& rhs )
|
action( const action& rhs )
|
||||||
: r_( const_cast< action& >( rhs ).r_.release() )
|
: v_( const_cast< action& >( rhs ).v_.release() )
|
||||||
, f_( r_.get()
|
, f_( v_.get()
|
||||||
? lambda_type::make_val( boost::ref( r_ ) )
|
? lambda_type::make_val( boost::ref( v_ ) )
|
||||||
: rhs.f_ )
|
: rhs.f_ )
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
|
@ -188,7 +227,6 @@ namespace detail
|
||||||
void throws( Exception e )
|
void throws( Exception e )
|
||||||
{
|
{
|
||||||
f_ = lambda_type::make_throw( e );
|
f_ = lambda_type::make_throw( e );
|
||||||
r_.reset();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const functor_type& functor() const
|
const functor_type& functor() const
|
||||||
|
|
@ -200,23 +238,22 @@ namespace detail
|
||||||
template< typename Y >
|
template< typename Y >
|
||||||
void set( std::auto_ptr< Y > r )
|
void set( std::auto_ptr< Y > r )
|
||||||
{
|
{
|
||||||
r_ = r;
|
v_ = r;
|
||||||
f_ = lambda_type::make_val( boost::ref( r_ ) );
|
f_ = lambda_type::make_val( boost::ref( v_ ) );
|
||||||
}
|
}
|
||||||
template< typename Y >
|
template< typename Y >
|
||||||
void set( const boost::reference_wrapper< Y >& r )
|
void set( const boost::reference_wrapper< Y >& r )
|
||||||
{
|
{
|
||||||
f_ = lambda_type::make_val( r );
|
f_ = lambda_type::make_val( r );
|
||||||
r_.reset();
|
|
||||||
}
|
}
|
||||||
template< typename Y >
|
template< typename Y >
|
||||||
void set( Y* r )
|
void set( Y* r )
|
||||||
{
|
{
|
||||||
r_.reset( r );
|
v_.reset( r );
|
||||||
f_ = lambda_type::make_val( boost::ref( r_ ) );
|
f_ = lambda_type::make_val( boost::ref( v_ ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
std::auto_ptr< Result > r_;
|
std::auto_ptr< Result > v_;
|
||||||
functor_type f_;
|
functor_type f_;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@
|
||||||
#else
|
#else
|
||||||
#include <boost/bind.hpp>
|
#include <boost/bind.hpp>
|
||||||
#endif
|
#endif
|
||||||
|
#include <boost/move/move.hpp>
|
||||||
#include <boost/function.hpp>
|
#include <boost/function.hpp>
|
||||||
|
|
||||||
namespace mock
|
namespace mock
|
||||||
|
|
@ -45,6 +46,11 @@ namespace detail
|
||||||
&do_ref_identity< T >, t.get_pointer() );
|
&do_ref_identity< T >, t.get_pointer() );
|
||||||
}
|
}
|
||||||
template< typename T >
|
template< typename T >
|
||||||
|
static functor_type make_move( T& t )
|
||||||
|
{
|
||||||
|
return detail::bind( &do_move< T >, boost::ref( t ) );
|
||||||
|
}
|
||||||
|
template< typename T >
|
||||||
static functor_type make_throw( T t )
|
static functor_type make_throw( T t )
|
||||||
{
|
{
|
||||||
return detail::bind( &do_throw< T >, t );
|
return detail::bind( &do_throw< T >, t );
|
||||||
|
|
@ -60,6 +66,11 @@ namespace detail
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
template< typename T >
|
template< typename T >
|
||||||
|
static T do_move( T& t )
|
||||||
|
{
|
||||||
|
return boost::move( t );
|
||||||
|
}
|
||||||
|
template< typename T >
|
||||||
static T& do_ref_identity( T* t )
|
static T& do_ref_identity( T* t )
|
||||||
{
|
{
|
||||||
return *t;
|
return *t;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue