mirror of
https://github.com/mat007/turtle.git
synced 2026-06-22 12:13:43 +00:00
Add support for asynchronous expectations.
This commit is contained in:
parent
8c68e7a63e
commit
4eadca553b
5 changed files with 222 additions and 64 deletions
|
|
@ -7,6 +7,7 @@
|
||||||
// http://www.boost.org/LICENSE_1_0.txt)
|
// http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
|
||||||
#include "matcher_base_template.hpp"
|
#include "matcher_base_template.hpp"
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
#define MOCK_EXPECTATION_INITIALIZE(z, n, d) \
|
#define MOCK_EXPECTATION_INITIALIZE(z, n, d) \
|
||||||
BOOST_PP_COMMA_IF(n) c##n##_( c##n )
|
BOOST_PP_COMMA_IF(n) c##n##_( c##n )
|
||||||
|
|
@ -133,7 +134,10 @@ namespace detail
|
||||||
> () )
|
> () )
|
||||||
, file_( "unknown location" )
|
, file_( "unknown location" )
|
||||||
, line_( 0 )
|
, line_( 0 )
|
||||||
{}
|
#if defined(MOCK_THREAD_SAFE)
|
||||||
|
, blocked(ATOMIC_VAR_INIT(false))
|
||||||
|
#endif
|
||||||
|
{ }
|
||||||
expectation( const char* file, int line )
|
expectation( const char* file, int line )
|
||||||
: invocation_( boost::make_shared< unlimited >() )
|
: invocation_( boost::make_shared< unlimited >() )
|
||||||
, matcher_(
|
, matcher_(
|
||||||
|
|
@ -144,7 +148,10 @@ namespace detail
|
||||||
> () )
|
> () )
|
||||||
, file_( file )
|
, file_( file )
|
||||||
, line_( line )
|
, line_( line )
|
||||||
{}
|
#if defined(MOCK_THREAD_SAFE)
|
||||||
|
, blocked(ATOMIC_VAR_INIT(false))
|
||||||
|
#endif
|
||||||
|
{ }
|
||||||
|
|
||||||
~expectation()
|
~expectation()
|
||||||
{
|
{
|
||||||
|
|
@ -185,7 +192,15 @@ namespace detail
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
#if defined(MOCK_THREAD_SAFE)
|
||||||
|
template < typename duration>
|
||||||
|
expectation &async(const duration timeout)
|
||||||
|
{
|
||||||
|
timeout_ = timeout;
|
||||||
|
blocked = false;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
void add( sequence& s )
|
void add( sequence& s )
|
||||||
{
|
{
|
||||||
s.impl_->add( this );
|
s.impl_->add( this );
|
||||||
|
|
@ -196,16 +211,41 @@ namespace detail
|
||||||
{
|
{
|
||||||
return invocation_->verify();
|
return invocation_->verify();
|
||||||
}
|
}
|
||||||
|
#if defined(MOCK_THREAD_SAFE)
|
||||||
|
bool verify(const boost::shared_ptr< condition_variable> &cv, lock &lk) const
|
||||||
|
{
|
||||||
|
if (timeout_)
|
||||||
|
{
|
||||||
|
while (!invocation_->verify())
|
||||||
|
{
|
||||||
|
if (MOCK_THREAD_NAMESPACE::cv_status::timeout == cv->wait_for(lk.get_unique_lock(), *timeout_))
|
||||||
|
{
|
||||||
|
std::atomic_store(&blocked,true);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return invocation_->verify();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
bool is_valid(
|
bool is_valid(
|
||||||
BOOST_PP_ENUM_BINARY_PARAMS(MOCK_NUM_ARGS, T, a) ) const
|
BOOST_PP_ENUM_BINARY_PARAMS(MOCK_NUM_ARGS, T, a) ) const
|
||||||
{
|
{
|
||||||
|
#if defined(MOCK_THREAD_SAFE)
|
||||||
|
return !blocked && !invocation_->exhausted()
|
||||||
|
&& (*matcher_)( BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS, a) );
|
||||||
|
#else
|
||||||
return !invocation_->exhausted()
|
return !invocation_->exhausted()
|
||||||
&& (*matcher_)( BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS, a) );
|
&& (*matcher_)( BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS, a) );
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool invoke() const
|
bool invoke() const
|
||||||
{
|
{
|
||||||
|
#if defined(MOCK_THREAD_SAFE)
|
||||||
|
if (blocked.load(std::memory_order_acquire))
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
for( sequences_cit it = sequences_.begin();
|
for( sequences_cit it = sequences_.begin();
|
||||||
it != sequences_.end(); ++it )
|
it != sequences_.end(); ++it )
|
||||||
if( ! (*it)->is_valid( this ) )
|
if( ! (*it)->is_valid( this ) )
|
||||||
|
|
@ -252,6 +292,10 @@ namespace detail
|
||||||
sequences_type sequences_;
|
sequences_type sequences_;
|
||||||
const char* file_;
|
const char* file_;
|
||||||
int line_;
|
int line_;
|
||||||
|
#if defined(MOCK_THREAD_SAFE)
|
||||||
|
boost::optional<nanoseconds> timeout_;
|
||||||
|
mutable std::atomic_bool blocked;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
} // mock
|
} // mock
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
// http://www.boost.org/LICENSE_1_0.txt)
|
// http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
|
||||||
#include "expectation_template.hpp"
|
#include "expectation_template.hpp"
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
#ifndef MOCK_ERROR_POLICY
|
#ifndef MOCK_ERROR_POLICY
|
||||||
# error no error policy has been set
|
# error no error policy has been set
|
||||||
|
|
@ -44,20 +45,30 @@ namespace detail
|
||||||
: context_( 0 )
|
: context_( 0 )
|
||||||
, valid_( true )
|
, valid_( true )
|
||||||
, mutex_( boost::make_shared< mutex >() )
|
, mutex_( boost::make_shared< mutex >() )
|
||||||
|
#if defined(MOCK_THREAD_SAFE)
|
||||||
|
, cv_( boost::make_shared< condition_variable>() )
|
||||||
|
#endif
|
||||||
{}
|
{}
|
||||||
virtual ~function_impl()
|
virtual ~function_impl()
|
||||||
{
|
{
|
||||||
if( valid_ && ! std::uncaught_exception() )
|
if (valid_ && !std::uncaught_exception()){
|
||||||
for( expectations_cit it = expectations_.begin();
|
lock _(mutex_);
|
||||||
it != expectations_.end(); ++it )
|
for (expectations_cit it = expectations_.begin();
|
||||||
if( ! it->verify() )
|
it != expectations_.end(); ++it)
|
||||||
error_type::fail( "untriggered expectation",
|
#if defined(MOCK_THREAD_SAFE)
|
||||||
boost::unit_test::lazy_ostream::instance()
|
if (!it->verify(cv_, _))
|
||||||
<< lazy_context( this )
|
#else
|
||||||
<< lazy_expectations( this ),
|
if (!it->verify())
|
||||||
it->file(), it->line() );
|
#endif
|
||||||
if( context_ )
|
error_type::fail("untriggered expectation",
|
||||||
context_->remove( *this );
|
boost::unit_test::lazy_ostream::instance()
|
||||||
|
<< lazy_context(this)
|
||||||
|
<< lazy_expectations(this),
|
||||||
|
it->file(), it->line());
|
||||||
|
}
|
||||||
|
context *c = context_.load(std::memory_order_acquire);
|
||||||
|
if (c)
|
||||||
|
c->remove( *this );
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool verify() const
|
virtual bool verify() const
|
||||||
|
|
@ -65,7 +76,11 @@ namespace detail
|
||||||
lock _( mutex_ );
|
lock _( mutex_ );
|
||||||
for( expectations_cit it = expectations_.begin();
|
for( expectations_cit it = expectations_.begin();
|
||||||
it != expectations_.end(); ++it )
|
it != expectations_.end(); ++it )
|
||||||
|
#if defined(MOCK_THREAD_SAFE)
|
||||||
|
if( ! it->verify(cv_,_) )
|
||||||
|
#else
|
||||||
if( ! it->verify() )
|
if( ! it->verify() )
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
valid_ = false;
|
valid_ = false;
|
||||||
error_type::fail( "verification failed",
|
error_type::fail( "verification failed",
|
||||||
|
|
@ -98,35 +113,37 @@ namespace detail
|
||||||
, lock_( m )
|
, lock_( m )
|
||||||
{}
|
{}
|
||||||
|
|
||||||
wrapper once()
|
wrapper(const wrapper &) = delete;
|
||||||
|
|
||||||
|
wrapper &once()
|
||||||
{
|
{
|
||||||
this->e_->invoke( boost::make_shared< detail::once >() );
|
this->e_->invoke( boost::make_shared< detail::once >() );
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
wrapper never()
|
wrapper &never()
|
||||||
{
|
{
|
||||||
this->e_->invoke( boost::make_shared< detail::never >() );
|
this->e_->invoke( boost::make_shared< detail::never >() );
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
wrapper exactly( std::size_t count )
|
wrapper &exactly( std::size_t count )
|
||||||
{
|
{
|
||||||
this->e_->invoke(
|
this->e_->invoke(
|
||||||
boost::make_shared< detail::exactly >( count ) );
|
boost::make_shared< detail::exactly >( count ) );
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
wrapper at_least( std::size_t min )
|
wrapper &at_least( std::size_t min )
|
||||||
{
|
{
|
||||||
this->e_->invoke(
|
this->e_->invoke(
|
||||||
boost::make_shared< detail::at_least >( min ) );
|
boost::make_shared< detail::at_least >( min ) );
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
wrapper at_most( std::size_t max )
|
wrapper &at_most( std::size_t max )
|
||||||
{
|
{
|
||||||
this->e_->invoke(
|
this->e_->invoke(
|
||||||
boost::make_shared< detail::at_most >( max ) );
|
boost::make_shared< detail::at_most >( max ) );
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
wrapper between( std::size_t min, std::size_t max )
|
wrapper &between( std::size_t min, std::size_t max )
|
||||||
{
|
{
|
||||||
this->e_->invoke(
|
this->e_->invoke(
|
||||||
boost::make_shared< detail::between >( min, max ) );
|
boost::make_shared< detail::between >( min, max ) );
|
||||||
|
|
@ -137,7 +154,7 @@ namespace detail
|
||||||
template<
|
template<
|
||||||
BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS, typename Constraint_)
|
BOOST_PP_ENUM_PARAMS(MOCK_NUM_ARGS, typename Constraint_)
|
||||||
>
|
>
|
||||||
wrapper with(
|
wrapper &with(
|
||||||
BOOST_PP_ENUM_BINARY_PARAMS(MOCK_NUM_ARGS, Constraint_, c) )
|
BOOST_PP_ENUM_BINARY_PARAMS(MOCK_NUM_ARGS, Constraint_, c) )
|
||||||
{
|
{
|
||||||
this->e_->with(
|
this->e_->with(
|
||||||
|
|
@ -146,7 +163,7 @@ namespace detail
|
||||||
}
|
}
|
||||||
#if MOCK_NUM_ARGS > 1
|
#if MOCK_NUM_ARGS > 1
|
||||||
template< typename Constraint >
|
template< typename Constraint >
|
||||||
wrapper with( const Constraint& c )
|
wrapper &with( const Constraint& c )
|
||||||
{
|
{
|
||||||
this->e_->with( c );
|
this->e_->with( c );
|
||||||
return *this;
|
return *this;
|
||||||
|
|
@ -158,7 +175,7 @@ namespace detail
|
||||||
this->e_->add( s##n );
|
this->e_->add( s##n );
|
||||||
|
|
||||||
#define MOCK_FUNCTION_IN(z, n, d) \
|
#define MOCK_FUNCTION_IN(z, n, d) \
|
||||||
wrapper in( BOOST_PP_ENUM_PARAMS(n, sequence& s) ) \
|
wrapper &in( BOOST_PP_ENUM_PARAMS(n, sequence& s) ) \
|
||||||
{ \
|
{ \
|
||||||
BOOST_PP_REPEAT(n, MOCK_FUNCTION_IN_ADD, _) \
|
BOOST_PP_REPEAT(n, MOCK_FUNCTION_IN_ADD, _) \
|
||||||
return *this; \
|
return *this; \
|
||||||
|
|
@ -169,7 +186,13 @@ namespace detail
|
||||||
|
|
||||||
#undef MOCK_FUNCTION_IN
|
#undef MOCK_FUNCTION_IN
|
||||||
#undef MOCK_FUNCTION_IN_ADD
|
#undef MOCK_FUNCTION_IN_ADD
|
||||||
|
#if defined(MOCK_THREAD_SAFE)
|
||||||
|
wrapper &async(const nanoseconds &timeout)
|
||||||
|
{
|
||||||
|
this->e_->async(timeout);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
template< typename TT >
|
template< typename TT >
|
||||||
void calls( TT t )
|
void calls( TT t )
|
||||||
{
|
{
|
||||||
|
|
@ -211,6 +234,19 @@ namespace detail
|
||||||
BOOST_PP_ENUM_BINARY_PARAMS(MOCK_NUM_ARGS, T, t) ) const
|
BOOST_PP_ENUM_BINARY_PARAMS(MOCK_NUM_ARGS, T, t) ) const
|
||||||
{
|
{
|
||||||
lock _( mutex_ );
|
lock _( mutex_ );
|
||||||
|
#if defined(MOCK_THREAD_SAFE)
|
||||||
|
struct notify_cv_on_exit
|
||||||
|
{
|
||||||
|
notify_cv_on_exit(condition_variable &cv)
|
||||||
|
: cv(cv){}
|
||||||
|
~notify_cv_on_exit()
|
||||||
|
{
|
||||||
|
cv.notify_one();
|
||||||
|
}
|
||||||
|
condition_variable &cv;
|
||||||
|
};
|
||||||
|
notify_cv_on_exit _cv(*cv_);
|
||||||
|
#endif
|
||||||
valid_ = false;
|
valid_ = false;
|
||||||
for( expectations_cit it = expectations_.begin();
|
for( expectations_cit it = expectations_.begin();
|
||||||
it != expectations_.end(); ++it )
|
it != expectations_.end(); ++it )
|
||||||
|
|
@ -246,11 +282,9 @@ namespace detail
|
||||||
boost::optional< type_name > type,
|
boost::optional< type_name > type,
|
||||||
boost::unit_test::const_string name )
|
boost::unit_test::const_string name )
|
||||||
{
|
{
|
||||||
lock _( mutex_ );
|
if (!context_.exchange(&c,std::memory_order_release))
|
||||||
if( ! context_ )
|
|
||||||
c.add( *this );
|
c.add( *this );
|
||||||
c.add( p, *this, instance, type, name );
|
c.add( p, *this, instance, type, name );
|
||||||
context_ = &c;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
friend std::ostream& operator<<(
|
friend std::ostream& operator<<(
|
||||||
|
|
@ -268,8 +302,10 @@ namespace detail
|
||||||
friend std::ostream& operator<<(
|
friend std::ostream& operator<<(
|
||||||
std::ostream& s, const lazy_context& c )
|
std::ostream& s, const lazy_context& c )
|
||||||
{
|
{
|
||||||
if( c.impl_->context_ )
|
|
||||||
c.impl_->context_->serialize( s, *c.impl_ );
|
context *pContext = c.impl_->context_.load(std::memory_order_acquire);
|
||||||
|
if( pContext )
|
||||||
|
pContext->serialize( s, *c.impl_ );
|
||||||
else
|
else
|
||||||
s << '?';
|
s << '?';
|
||||||
return s;
|
return s;
|
||||||
|
|
@ -297,9 +333,12 @@ namespace detail
|
||||||
typedef typename expectations_type::const_iterator expectations_cit;
|
typedef typename expectations_type::const_iterator expectations_cit;
|
||||||
|
|
||||||
expectations_type expectations_;
|
expectations_type expectations_;
|
||||||
context* context_;
|
std::atomic<context*> context_;
|
||||||
mutable bool valid_;
|
mutable bool valid_;
|
||||||
const boost::shared_ptr< mutex > mutex_;
|
const boost::shared_ptr< mutex > mutex_;
|
||||||
|
#if defined(MOCK_THREAD_SAFE)
|
||||||
|
const boost::shared_ptr<condition_variable> cv_;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
} // mock
|
} // mock
|
||||||
|
|
|
||||||
|
|
@ -17,44 +17,44 @@
|
||||||
|
|
||||||
#ifdef MOCK_HDR_MUTEX
|
#ifdef MOCK_HDR_MUTEX
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
#include <condition_variable>
|
||||||
|
#include <chrono>
|
||||||
#else
|
#else
|
||||||
#include <boost/thread/recursive_mutex.hpp>
|
#include <boost/thread/recursive_mutex.hpp>
|
||||||
#include <boost/thread/lock_guard.hpp>
|
#include <boost/thread/lock_guard.hpp>
|
||||||
|
#include <boost/thread/condition_variable.hpp>
|
||||||
|
#include <boost/chrono.hpp>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MOCK_HDR_MUTEX
|
||||||
|
#define MOCK_THREAD_NAMESPACE std
|
||||||
|
#else
|
||||||
|
#define MOCK_THREAD_NAMESPACE boost
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace mock
|
namespace mock
|
||||||
{
|
{
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
#ifdef MOCK_HDR_MUTEX
|
typedef MOCK_THREAD_NAMESPACE::recursive_mutex mutex;
|
||||||
typedef std::recursive_mutex mutex;
|
typedef MOCK_THREAD_NAMESPACE::lock_guard< mutex > scoped_lock;
|
||||||
typedef std::lock_guard< mutex > scoped_lock;
|
typedef MOCK_THREAD_NAMESPACE::condition_variable_any condition_variable;
|
||||||
#else
|
typedef MOCK_THREAD_NAMESPACE::chrono::nanoseconds nanoseconds;
|
||||||
typedef boost::recursive_mutex mutex;
|
typedef MOCK_THREAD_NAMESPACE::unique_lock<mutex> lock_base;
|
||||||
typedef boost::lock_guard< mutex > scoped_lock;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct lock
|
struct lock : public lock_base
|
||||||
{
|
{
|
||||||
lock( const boost::shared_ptr< mutex >& m )
|
lock(const boost::shared_ptr< detail::mutex > &m)
|
||||||
: m_( m )
|
: lock_base (*m)
|
||||||
{
|
, m_(m)
|
||||||
m_->lock();
|
{}
|
||||||
}
|
|
||||||
lock( const lock& rhs )
|
|
||||||
{
|
|
||||||
m_.swap( rhs.m_ );
|
|
||||||
}
|
|
||||||
~lock()
|
~lock()
|
||||||
{
|
{
|
||||||
if( m_ )
|
unlock();
|
||||||
m_->unlock();
|
|
||||||
}
|
}
|
||||||
|
lock_base &get_unique_lock() { return *this; }
|
||||||
|
|
||||||
private:
|
boost::shared_ptr< detail::mutex > m_;
|
||||||
lock& operator=( const lock& rhs );
|
|
||||||
|
|
||||||
mutable boost::shared_ptr< mutex > m_;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
} // mock
|
} // mock
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ namespace detail
|
||||||
public:
|
public:
|
||||||
object_impl()
|
object_impl()
|
||||||
: mutex_( boost::make_shared< mutex >() )
|
: mutex_( boost::make_shared< mutex >() )
|
||||||
|
, children_mutex_( boost::make_shared< mutex >() )
|
||||||
{}
|
{}
|
||||||
|
|
||||||
virtual void add( const void* /*p*/, verifiable& v,
|
virtual void add( const void* /*p*/, verifiable& v,
|
||||||
|
|
@ -38,7 +39,7 @@ namespace detail
|
||||||
boost::optional< type_name > type,
|
boost::optional< type_name > type,
|
||||||
boost::unit_test::const_string name )
|
boost::unit_test::const_string name )
|
||||||
{
|
{
|
||||||
lock _( mutex_ );
|
lock _( children_mutex_ );
|
||||||
if( children_.empty() )
|
if( children_.empty() )
|
||||||
detail::root.add( *this );
|
detail::root.add( *this );
|
||||||
children_[ &v ].update( parent_, instance, type, name );
|
children_[ &v ].update( parent_, instance, type, name );
|
||||||
|
|
@ -50,16 +51,21 @@ namespace detail
|
||||||
}
|
}
|
||||||
virtual void remove( verifiable& v )
|
virtual void remove( verifiable& v )
|
||||||
{
|
{
|
||||||
lock _( mutex_ );
|
{
|
||||||
group_.remove( v );
|
lock _(mutex_);
|
||||||
children_.erase( &v );
|
group_.remove(v);
|
||||||
if( children_.empty() )
|
}
|
||||||
detail::root.remove( *this );
|
{
|
||||||
|
lock _( children_mutex_ );
|
||||||
|
children_.erase(&v);
|
||||||
|
if (children_.empty())
|
||||||
|
detail::root.remove(*this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void serialize( std::ostream& s, const verifiable& v ) const
|
virtual void serialize( std::ostream& s, const verifiable& v ) const
|
||||||
{
|
{
|
||||||
lock _( mutex_ );
|
lock _( children_mutex_ );
|
||||||
children_cit it = children_.find( &v );
|
children_cit it = children_.find( &v );
|
||||||
if( it != children_.end() )
|
if( it != children_.end() )
|
||||||
s << it->second;
|
s << it->second;
|
||||||
|
|
@ -72,6 +78,7 @@ namespace detail
|
||||||
lock _( mutex_ );
|
lock _( mutex_ );
|
||||||
return group_.verify();
|
return group_.verify();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void reset()
|
virtual void reset()
|
||||||
{
|
{
|
||||||
lock _( mutex_ );
|
lock _( mutex_ );
|
||||||
|
|
@ -87,6 +94,7 @@ namespace detail
|
||||||
parent parent_;
|
parent parent_;
|
||||||
children_t children_;
|
children_t children_;
|
||||||
const boost::shared_ptr< mutex > mutex_;
|
const boost::shared_ptr< mutex > mutex_;
|
||||||
|
const boost::shared_ptr< mutex > children_mutex_;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
} // mock
|
} // mock
|
||||||
|
|
|
||||||
67
test/test_async.cpp
Normal file
67
test/test_async.cpp
Normal file
|
|
@ -0,0 +1,67 @@
|
||||||
|
// http://turtle.sourceforge.net
|
||||||
|
//
|
||||||
|
// 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 "mock_error.hpp"
|
||||||
|
#include <turtle/mock.hpp>
|
||||||
|
#include <boost/test/auto_unit_test.hpp>
|
||||||
|
#include <boost/lexical_cast.hpp>
|
||||||
|
|
||||||
|
#if defined(MOCK_HDR_MUTEX)
|
||||||
|
#include <thread>
|
||||||
|
#else
|
||||||
|
#include <boost/thread.hpp>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
MOCK_CLASS( mock_class )
|
||||||
|
{
|
||||||
|
MOCK_METHOD_EXT( my_method, 1, void( const std::string& ), my_tag )
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_FIXTURE_TEST_CASE( mock_object_asynchonous_call_expectation, mock_error_fixture )
|
||||||
|
{
|
||||||
|
#if defined(MOCK_THREAD_SAFE)
|
||||||
|
const mock_class m;
|
||||||
|
MOCK_EXPECT( m.my_tag ).async(MOCK_THREAD_NAMESPACE::chrono::milliseconds(50)).once().with( "some parameter" );
|
||||||
|
MOCK_THREAD_NAMESPACE::thread context([&](){
|
||||||
|
MOCK_THREAD_NAMESPACE::this_thread::sleep_for(MOCK_THREAD_NAMESPACE::chrono::milliseconds(10));
|
||||||
|
m.my_method("some parameter");
|
||||||
|
});
|
||||||
|
mock::verify();
|
||||||
|
CHECK_CALLS( 1 );
|
||||||
|
context.join();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE( mock_object_asynchonous_call_expectation_fails )
|
||||||
|
{
|
||||||
|
#if defined(MOCK_THREAD_SAFE)
|
||||||
|
const mock_class m;
|
||||||
|
bool unexpected_call_received = false;
|
||||||
|
MOCK_EXPECT( m.my_tag ).async(MOCK_THREAD_NAMESPACE::chrono::milliseconds(50)).once().with( "some parameter" );
|
||||||
|
MOCK_THREAD_NAMESPACE::thread context([&](){
|
||||||
|
MOCK_THREAD_NAMESPACE::this_thread::sleep_for(MOCK_THREAD_NAMESPACE::chrono::milliseconds(100));
|
||||||
|
try{
|
||||||
|
m.my_method("some parameter");
|
||||||
|
}
|
||||||
|
catch (std::exception &)
|
||||||
|
{
|
||||||
|
unexpected_call_received = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
CHECK_ERROR(
|
||||||
|
BOOST_CHECK(!mock::verify()),
|
||||||
|
"verification failed", 0, "m.mock_class::my_tag\n. once().with( \"some parameter\" )");
|
||||||
|
context.join();
|
||||||
|
BOOST_CHECK(unexpected_call_received == true);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue