// http://turtle.sourceforge.net // // 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) #include "mock_error.hpp" #include "undefined.hpp" #include #include #include #include #include #include #include namespace { struct my_custom_mock { MOCK_METHOD_EXT( my_method, 0, void(), my_tag ) }; } BOOST_FIXTURE_TEST_CASE( custom_mock_object_without_macros_and_without_inheriting_from_object, mock_error_fixture ) { my_custom_mock m; MOCK_EXPECT( m.my_tag ).once(); m.my_method(); CHECK_CALLS( 1 ); } namespace { struct my_custom_mock_object { MOCK_METHOD_EXT( my_method, 0, void(), my_tag ) }; } BOOST_FIXTURE_TEST_CASE( custom_mock_object_without_macros, mock_error_fixture ) { my_custom_mock_object m; MOCK_EXPECT( m.my_tag ).once(); m.my_method(); CHECK_CALLS( 1 ); } namespace { MOCK_CLASS( my_mock ) { MOCK_METHOD_EXT( my_method, 1, int( int ), my_tag ) }; } BOOST_FIXTURE_TEST_CASE( basic_mock_object_usage, mock_error_fixture ) { my_mock m; { MOCK_EXPECT( m.my_tag ).once().returns( 0 ); BOOST_CHECK_EQUAL( 0, m.my_method( 13 ) ); CHECK_CALLS( 1 ); } mock::verify(); mock::reset(); { MOCK_EXPECT( m.my_tag ).once().with( 42 ).returns( 7 ); BOOST_CHECK_EQUAL( 7, m.my_method( 42 ) ); CHECK_CALLS( 1 ); } mock::verify(); mock::reset(); { MOCK_EXPECT( m.my_tag ).once().returns( 51 ); BOOST_CHECK_EQUAL( 51, m.my_method( 27 ) ); CHECK_CALLS( 1 ); } } namespace { class my_ambiguited_interface : boost::noncopyable { public: virtual ~my_ambiguited_interface() {} virtual void my_method() = 0; virtual void my_method( int ) = 0; }; MOCK_BASE_CLASS( my_ambiguited_mock, my_ambiguited_interface ) { MOCK_METHOD_EXT( my_method, 0, void(), my_tag1 ) MOCK_METHOD_EXT( my_method, 1, void( int ), my_tag_2 ) }; } BOOST_FIXTURE_TEST_CASE( mock_object_method_disambiguation, mock_error_fixture ) { my_ambiguited_mock m; MOCK_EXPECT( m.my_tag1 ); m.my_method(); CHECK_ERROR( m.my_method( 12 ), "unexpected call", 1, "?.my_ambiguited_mock::my_tag_2( 12 )" ); } namespace { class my_const_ambiguited_interface : boost::noncopyable { public: virtual ~my_const_ambiguited_interface() {} virtual void my_method() = 0; virtual void my_method() const = 0; }; MOCK_BASE_CLASS( my_const_ambiguited_mock, my_const_ambiguited_interface ) { MOCK_NON_CONST_METHOD_EXT( my_method, 0, void(), tag1 ) MOCK_CONST_METHOD_EXT( my_method, 0, void(), tag_2 ) }; } BOOST_FIXTURE_TEST_CASE( mock_object_method_const_disambiguation, mock_error_fixture ) { my_const_ambiguited_mock mock; MOCK_EXPECT( mock.tag1 ); BOOST_CHECK_NO_THROW( mock.my_method() ); const my_const_ambiguited_mock const_mock; CHECK_ERROR( const_mock.my_method(), "unexpected call", 1, "?.my_const_ambiguited_mock::tag_2()" ); } namespace { MOCK_CLASS( my_undefined_mock ) { MOCK_METHOD_EXT( m, 1, void( undefined& ), t ) }; } BOOST_FIXTURE_TEST_CASE( mock_object_method_with_declared_but_not_defined_parameter_is_valid, mock_error_fixture ) { my_undefined_mock mock; MOCK_EXPECT( mock.t ); } namespace { MOCK_FUNCTOR( gf, int( float, const std::string& ) ); } BOOST_FIXTURE_TEST_CASE( mock_functor_in_namespace_is_supported, mock_error_fixture ) { std::function< int( float, const std::string& ) > func; MOCK_EXPECT( gf ).once().with( 3, "op" ).returns( 42 ); func = gf; BOOST_CHECK_EQUAL( 42, func( 3, "op" ) ); CHECK_CALLS( 1 ); } BOOST_FIXTURE_TEST_CASE( mock_functor_in_function_is_supported, mock_error_fixture ) { std::function< int( float, const std::string& ) > func; { MOCK_FUNCTOR( f, int( float, const std::string& ) ); MOCK_EXPECT( f ).once().with( 3, "op" ).returns( 42 ); func = f; } BOOST_CHECK_EQUAL( 42, func( 3, "op" ) ); CHECK_CALLS( 1 ); } namespace { struct functor_fixture : mock_error_fixture { MOCK_FUNCTOR( f, int( float, const std::string& ) ); }; } BOOST_FIXTURE_TEST_CASE( mock_functor_in_fixture_is_supported, functor_fixture ) { MOCK_EXPECT( f ).once().with( 3, "op" ).returns( 42 ); BOOST_CHECK_EQUAL( 42, f( 3.f, "op" ) ); CHECK_CALLS( 1 ); } namespace { template< typename T > struct my_template_mock { MOCK_METHOD_EXT( my_method, 0, void(), my_tag ) MOCK_METHOD_EXT_TPL( my_method, 2, void( T, std::string ), my_tpl_tag ) MOCK_METHOD_EXT_TPL( my_other_method, 0, void(), my_other_tag ) }; } BOOST_FIXTURE_TEST_CASE( mocking_a_template_class_method_is_supported, mock_error_fixture ) { my_template_mock< int > m; MOCK_EXPECT( m.my_tpl_tag ).with( 3, "" ); m.my_method( 3, "" ); BOOST_CHECK( MOCK_VERIFY( m.my_tpl_tag ) ); CHECK_CALLS( 1 ); } namespace { template< typename T > struct my_template_base_class { virtual ~my_template_base_class() {} virtual void my_method( T ) = 0; virtual void my_other_method() = 0; }; template< typename T > MOCK_BASE_CLASS( my_template_base_class_mock, my_template_base_class< T > ) { MOCK_METHOD_EXT_TPL( my_method, 1, void( T ), my_method ) MOCK_METHOD_EXT_TPL( my_other_method, 0, void(), my_other_method ) }; } BOOST_FIXTURE_TEST_CASE( mocking_a_template_base_class_method_is_supported, mock_error_fixture ) { my_template_base_class_mock< int > m; MOCK_EXPECT( m.my_method ).once().with( 3 ); m.my_method( 3 ); BOOST_CHECK( MOCK_VERIFY( m.my_method ) ); CHECK_CALLS( 1 ); } namespace { class my_observer : boost::noncopyable { public: virtual ~my_observer() {} virtual void notify( int value ) = 0; }; class my_manager : boost::noncopyable { public: virtual ~my_manager() {} virtual my_observer& get_observer() const = 0; }; class my_subject : boost::noncopyable { public: explicit my_subject( my_manager& f ) : o_( f.get_observer() ) , value_( 0 ) {} void increment() { o_.notify( ++value_ ); } private: my_observer& o_; int value_; }; MOCK_BASE_CLASS( my_mock_observer, my_observer ) { MOCK_METHOD( notify, 1 ) }; MOCK_BASE_CLASS( my_mock_manager, my_manager ) { MOCK_METHOD( get_observer, 0 ) }; struct fixture : mock_error_fixture { my_mock_manager manager; my_mock_observer observer; }; } BOOST_FIXTURE_TEST_CASE( basic_mock_object_collaboration_usage, fixture ) { MOCK_EXPECT( manager.get_observer ).returns( boost::ref( observer ) ); my_subject subject( manager ); MOCK_EXPECT( observer.notify ).once().with( 1 ); subject.increment(); MOCK_EXPECT( observer.notify ).once().with( 2 ); subject.increment(); MOCK_EXPECT( observer.notify ).once().with( 3 ); subject.increment(); CHECK_CALLS( 4 ); } namespace { MOCK_CLASS( my_constructed_class ) { MOCK_CONSTRUCTOR( my_constructed_class, 2, ( int, const std::string& ), constructor ) }; } BOOST_FIXTURE_TEST_CASE( mocking_a_constructor, mock_error_fixture ) { MOCK_EXPECT( my_constructed_class::constructor ).with( 42, "some text" ).once(); my_constructed_class( 42, "some text" ); BOOST_CHECK( MOCK_VERIFY( my_constructed_class::constructor ) ); CHECK_CALLS( 1 ); } namespace { template< typename T > MOCK_CLASS( my_constructed_template_class ) { MOCK_CONSTRUCTOR_TPL( my_constructed_template_class, 2, ( T, const std::string& ), constructor ) }; } BOOST_FIXTURE_TEST_CASE( mocking_a_template_class_constructor, mock_error_fixture ) { MOCK_EXPECT( my_constructed_template_class< int >::constructor ).with( 42, "some text" ).once(); my_constructed_template_class< int >( 42, "some text" ); BOOST_CHECK( MOCK_VERIFY( my_constructed_template_class< int >::constructor ) ); CHECK_CALLS( 1 ); } namespace { MOCK_CLASS( my_destroyed_class ) { MOCK_DESTRUCTOR( ~my_destroyed_class, destructor ) }; } BOOST_FIXTURE_TEST_CASE( mocking_a_destructor, mock_error_fixture ) { { my_destroyed_class c; MOCK_EXPECT( c.destructor ).once(); } CHECK_CALLS( 1 ); } BOOST_FIXTURE_TEST_CASE( failed_expectation_in_mocked_destructor_does_not_throw, mock_error_fixture ) { CHECK_ERROR( try { my_destroyed_class c; throw std::runtime_error( "should not crash" ); } catch( std::runtime_error& ) { }, "unexpected call", 0, "?.my_destroyed_class::destructor()" ); } BOOST_FIXTURE_TEST_CASE( failed_sequence_in_mocked_destructor_does_not_throw, mock_error_fixture ) { mock::sequence s; my_custom_mock m; CHECK_ERROR( { my_destroyed_class c; MOCK_EXPECT( c.destructor ).once().in( s ); MOCK_EXPECT( m.my_tag ).once().in( s ); m.my_method(); }, "sequence failed", 1, "c.my_destroyed_class::destructor()\n. once()" ); } namespace { MOCK_CLASS( boost_optional ) { MOCK_METHOD_EXT( method, 0, boost::optional< my_observer& >(), tag ) }; } BOOST_FIXTURE_TEST_CASE( boost_optional_on_base_class_reference_as_return_type_is_supported, mock_error_fixture ) { boost_optional b; my_mock_observer o; MOCK_EXPECT( b.tag ).once().returns( boost::ref( o ) ); b.method(); CHECK_CALLS( 1 ); } namespace { bool serialized = false; struct custom_argument { friend std::ostream& operator<<( std::ostream& s, custom_argument ) { serialized = true; return s; } }; struct custom_constraint { template< typename Actual > friend bool operator==( Actual, custom_constraint ) { return true; } friend std::ostream& operator<<( std::ostream& s, custom_constraint ) { serialized = true; return s; } }; } BOOST_FIXTURE_TEST_CASE( constraints_and_arguments_are_serialized_lazily, mock_error_fixture ) { MOCK_FUNCTOR( f, void( const custom_argument& ) ); MOCK_EXPECT( f ).with( custom_constraint() ); f( custom_argument() ); BOOST_CHECK( ! serialized ); CHECK_CALLS( 1 ); } namespace { struct custom_constraint_with_non_const_operator { template< typename Actual > bool operator()( Actual actual ) { return actual == 42; } }; } BOOST_FIXTURE_TEST_CASE( custom_constraint_function_operator_does_not_need_to_be_const, mock_error_fixture ) { MOCK_FUNCTOR( f, void( float ) ); MOCK_EXPECT( f ).with( mock::constraint< custom_constraint_with_non_const_operator >( custom_constraint_with_non_const_operator() ) ); f( 42 ); CHECK_CALLS( 1 ); } BOOST_FIXTURE_TEST_CASE( boost_reference_wrapper_is_supported_in_value_constraint, mock_error_fixture ) { MOCK_FUNCTOR( f, void( const std::string& ) ); std::string s; MOCK_EXPECT( f ).once().with( boost::cref( s ) ); s = "string"; f( "string" ); CHECK_CALLS( 1 ); } namespace { template< typename T > void nothing( T ) {} struct member_pointer_mock_class { MOCK_CONST_METHOD_EXT( my_method, 0, void(), my_method ) }; } BOOST_FIXTURE_TEST_CASE( member_pointer_on_mock_method_is_valid, mock_error_fixture ) { nothing( &member_pointer_mock_class::my_method ); } namespace { MOCK_FUNCTION( free_function, 1, void( int ), free_function ) } BOOST_FIXTURE_TEST_CASE( a_free_function_can_be_mocked, mock_error_fixture ) { MOCK_EXPECT( free_function ).once(); CHECK_ERROR( BOOST_CHECK( ! MOCK_VERIFY( free_function ) ), "verification failed", 0, "free_function\n. once().with( any )" ); free_function( 42 ); CHECK_CALLS( 1 ); BOOST_CHECK( MOCK_VERIFY( free_function ) ); MOCK_RESET( free_function ); } namespace { struct some_class : mock::object { MOCK_STATIC_METHOD( some_static_method, 1, void( int ), some_static_method ) }; } BOOST_FIXTURE_TEST_CASE( a_static_method_can_be_mocked, mock_error_fixture ) { MOCK_EXPECT( some_class::some_static_method ).once(); CHECK_ERROR( BOOST_CHECK( ! MOCK_VERIFY( some_class::some_static_method ) ), "verification failed", 0, "some_class::some_static_method\n. once().with( any )" ); some_class::some_static_method( 42 ); CHECK_CALLS( 1 ); BOOST_CHECK( MOCK_VERIFY( some_class::some_static_method ) ); MOCK_RESET( some_class::some_static_method ); } BOOST_FIXTURE_TEST_CASE( a_static_method_is_not_reset_when_resetting_an_instance_of_the_class, mock_error_fixture ) { MOCK_EXPECT( some_class::some_static_method ).once(); some_class c; mock::reset( c ); CHECK_ERROR( BOOST_CHECK( ! MOCK_VERIFY( some_class::some_static_method ) ), "verification failed", 0, "some_class::some_static_method\n. once().with( any )" ); MOCK_RESET( some_class::some_static_method ); } namespace { template< typename T > struct some_template_class { MOCK_STATIC_METHOD_TPL( some_static_method, 1, void( T ), some_static_method ) }; } BOOST_FIXTURE_TEST_CASE( a_static_method_in_a_template_class_can_be_mocked, mock_error_fixture ) { MOCK_EXPECT( some_template_class< int >::some_static_method ).once(); CHECK_ERROR( BOOST_CHECK( ! MOCK_VERIFY( some_template_class< int >::some_static_method ) ), "verification failed", 0, "some_template_class< int >::some_static_method\n. once().with( any )" ); some_template_class< int >::some_static_method( 42 ); BOOST_CHECK( mock::verify() ); BOOST_CHECK( MOCK_VERIFY( some_template_class< int >::some_static_method ) ); MOCK_RESET( some_template_class< int >::some_static_method ); CHECK_CALLS( 1 ); } namespace { MOCK_CLASS( mock_class ) { MOCK_METHOD_EXT( m, 0, void(), t ); }; } BOOST_FIXTURE_TEST_CASE( resetting_referenced_mock_class_does_not_crash, mock_error_fixture ) { MOCK_FUNCTOR( f, mock_class() ); { mock_class c; MOCK_EXPECT( f ).returns( c ); MOCK_EXPECT( c.t ); } mock::reset(); } namespace { MOCK_CLASS( mock_class2 ) { MOCK_METHOD_EXT( m, 0, mock_class2(), t ); }; } BOOST_FIXTURE_TEST_CASE( resetting_self_referenced_mock_class_does_not_crash, mock_error_fixture ) { { mock_class2 c; MOCK_EXPECT( c.t ).returns( c ); } mock::reset(); } namespace { template< typename T1, typename T2 > struct my_base {}; MOCK_BASE_CLASS( my_comma_mock, my_base< int BOOST_PP_COMMA() int > ) {}; } #ifdef MOCK_THREAD_SAFE #include namespace { void create_class() { my_mock m; MOCK_EXPECT( m.my_tag ).once().with( 3 ).returns( 42 ); try { m.my_method( 3 ); } catch( ... ) {} } } BOOST_FIXTURE_TEST_CASE( mock_class_creation_is_thread_safe, mock_error_fixture ) { boost::thread_group group; for( int i = 0; i < 100; ++i ) group.create_thread( &create_class ); group.join_all(); CHECK_CALLS( 100 ); } namespace { void create_functor( int i ) { mock::detail::functor< void( int ) > f; boost::this_thread::sleep( boost::posix_time::milliseconds( 100 ) ); mock::detail::functor< void( int ) > f_mock; MOCK_EXPECT( f ).once().with( i ); try { f( i ); } catch( ... ) {} } } BOOST_FIXTURE_TEST_CASE( mock_functor_creation_is_thread_safe, mock_error_fixture ) { boost::thread_group group; for( int i = 0; i < 100; ++i ) group.create_thread( boost::bind( &create_functor, i ) ); group.join_all(); CHECK_CALLS( 100 ); } namespace { void iterate( my_mock& m ) { MOCK_EXPECT( m.my_tag ).once().with( 3 ).returns( 42 ); BOOST_CHECK_EQUAL( 42, m.my_method( 3 ) ); } } BOOST_FIXTURE_TEST_CASE( mock_class_is_thread_safe, mock_error_fixture ) { my_mock m; boost::thread_group group; for( int i = 0; i < 100; ++i ) group.create_thread( boost::bind( &iterate, boost::ref( m ) ) ); group.join_all(); CHECK_CALLS( 100 ); } #endif // MOCK_THREAD_SAFE namespace { MOCK_CLASS( my_multi_mock ) { MOCK_METHOD_EXT( m1, 1, void( int ), m1 ); MOCK_METHOD_EXT( m2, 2, void( int, int ), m2 ); }; } BOOST_FIXTURE_TEST_CASE( mock_method_accepts_multi_constraint, mock_error_fixture ) { my_multi_mock m; MOCK_FUNCTOR( f, bool( int, int ) ); MOCK_EXPECT( m.m2 ).once().with( f ); MOCK_EXPECT( f ).once().with( 1, 2 ).returns( true ); m.m2( 1, 2 ); CHECK_CALLS( 2 ); } namespace { struct my_polymorphic_constraint { template< typename T1, typename T2 > bool operator()( T1, T2 ) const { return true; } }; } BOOST_FIXTURE_TEST_CASE( mock_method_accepts_polymorphic_multi_constraint, mock_error_fixture ) { my_multi_mock m; MOCK_EXPECT( m.m2 ).once().with( my_polymorphic_constraint() ); m.m2( 1, 2 ); CHECK_CALLS( 1 ); } BOOST_FIXTURE_TEST_CASE( std_unique_ptr_argument_is_supported_in_action, mock_error_fixture ) { MOCK_FUNCTOR( f, void( std::unique_ptr< int > ) ); std::unique_ptr< int > p; MOCK_EXPECT( f ).once().calls( []( std::unique_ptr< int > ) { } ); f( std::unique_ptr< int >( new int( 7 ) ) ); CHECK_CALLS( 1 ); } BOOST_FIXTURE_TEST_CASE( std_unique_ptr_argument_is_supported_in_equal_constraint, mock_error_fixture ) { { MOCK_FUNCTOR( f, void( std::unique_ptr< int > ) ); MOCK_EXPECT( f ).once().with( mock::equal( 7 ) ); f( std::unique_ptr< int >( new int( 7 ) ) ); CHECK_CALLS( 1 ); } { MOCK_FUNCTOR( f, void( std::unique_ptr< int > ) ); MOCK_EXPECT( f ).once().with( 7 ); f( std::unique_ptr< int >( new int( 7 ) ) ); CHECK_CALLS( 1 ); } } BOOST_FIXTURE_TEST_CASE( std_unique_ptr_argument_is_supported_in_retrieve_constraint, mock_error_fixture ) { { MOCK_FUNCTOR( f, void( std::unique_ptr< int > ) ); MOCK_EXPECT( f ).once().with( nullptr ); f( 0 ); CHECK_CALLS( 1 ); } { std::unique_ptr< int > i; MOCK_FUNCTOR( f, void( std::unique_ptr< int > ) ); MOCK_EXPECT( f ).once().with( mock::retrieve( i ) ); std::unique_ptr< int > j( new int( 7 ) ); f( std::move( j ) ); BOOST_CHECK( !j ); BOOST_REQUIRE( i ); BOOST_CHECK_EQUAL( 7, *i ); CHECK_CALLS( 1 ); } { std::unique_ptr< int > i; MOCK_FUNCTOR( f, void( std::unique_ptr< int > ) ); MOCK_EXPECT( f ).once().with( nullptr ); MOCK_EXPECT( f ).once().with( mock::retrieve( i ) ); f( 0 ); std::unique_ptr< int > j( new int( 7 ) ); f( std::move( j ) ); BOOST_CHECK( !j ); BOOST_REQUIRE( i ); BOOST_CHECK_EQUAL( 7, *i ); CHECK_CALLS( 2 ); } } struct my_unique_ptr_class { MOCK_CONSTRUCTOR( my_unique_ptr_class, 1, ( std::unique_ptr< int > ), constructor ) MOCK_METHOD_EXT( m, 1, void( std::unique_ptr< int > ), m ) MOCK_STATIC_METHOD( ms, 1, void( std::unique_ptr< int > ), ms ) };