diff --git a/src/libraries/turtle/boost_test_error.hpp b/src/libraries/turtle/boost_test_error.hpp index c41e43c..8c080ca 100644 --- a/src/libraries/turtle/boost_test_error.hpp +++ b/src/libraries/turtle/boost_test_error.hpp @@ -14,7 +14,6 @@ #include #include #include -#include namespace mock { @@ -33,8 +32,8 @@ namespace mock template< typename Context > static void fail( - const std::string& message, const Context& context, - const std::string& file = "unknown location", int line = 0 ) + const char* message, const Context& context, + const char* file = "unknown location", int line = 0 ) { boost::unit_test::framework::assertion_result( false ); boost::unit_test::unit_test_log @@ -46,7 +45,7 @@ namespace mock template< typename Context > static void expected_call( const Context& context, - const std::string& file, int line ) + const char* file, int line ) { boost::unit_test::framework::assertion_result( true ); boost::unit_test::unit_test_log @@ -58,7 +57,7 @@ namespace mock template< typename Context > static void missing_action( const Context& context, - const std::string& file, int line ) + const char* file, int line ) { fail( "missing action", context, file, line ); } @@ -69,19 +68,19 @@ namespace mock } template< typename Context > static void sequence_failed( const Context& context, - const std::string& /*file*/, int /*line*/ ) + const char* file, int line ) { - fail( "sequence failed", context ); + fail( "sequence failed", context, file, line ); } template< typename Context > static void verification_failed( const Context& context, - const std::string& file, int line ) + const char* file, int line ) { fail( "verification failed", context, file, line ); } template< typename Context > static void untriggered_expectation( const Context& context, - const std::string& file, int line ) + const char* file, int line ) { fail( "untriggered expectation", context, file, line ); } diff --git a/src/libraries/turtle/child.hpp b/src/libraries/turtle/child.hpp index db1cf04..15d67be 100644 --- a/src/libraries/turtle/child.hpp +++ b/src/libraries/turtle/child.hpp @@ -10,8 +10,10 @@ #define MOCK_CHILD_HPP_INCLUDED #include "parent.hpp" +#include "type_name.hpp" +#include +#include #include -#include namespace mock { @@ -23,8 +25,10 @@ namespace detail child() : parent_( 0 ) {} - void update( parent& p, const std::string& instance, - const std::string& type, const std::string& name ) + void update( parent& p, + boost::unit_test::const_string instance, + const boost::optional< type_name >& type, + boost::unit_test::const_string name ) { if( instance != "?" || name_.empty() ) p = parent( instance, type ); @@ -39,7 +43,7 @@ namespace detail } private: const parent* parent_; - std::string name_; + boost::unit_test::const_string name_; }; } } diff --git a/src/libraries/turtle/config.hpp b/src/libraries/turtle/config.hpp index f743df4..8c3c6eb 100644 --- a/src/libraries/turtle/config.hpp +++ b/src/libraries/turtle/config.hpp @@ -38,8 +38,10 @@ # endif #endif -#ifdef BOOST_TEST_DECL -# define MOCK_USE_BOOST_TEST +#ifndef MOCK_USE_BOOST_TEST +# ifdef BOOST_TEST_DECL +# define MOCK_USE_BOOST_TEST +# endif #endif #endif // MOCK_CONFIG_HPP_INCLUDED diff --git a/src/libraries/turtle/context.hpp b/src/libraries/turtle/context.hpp index 775cb19..2ad644a 100644 --- a/src/libraries/turtle/context.hpp +++ b/src/libraries/turtle/context.hpp @@ -9,9 +9,11 @@ #ifndef MOCK_CONTEXT_HPP_INCLUDED #define MOCK_CONTEXT_HPP_INCLUDED +#include "type_name.hpp" #include +#include +#include #include -#include namespace mock { @@ -25,8 +27,10 @@ namespace detail context() {} virtual ~context() {} - virtual void add( const void* p, verifiable& v, const std::string& instance, - const std::string& type, const std::string& name ) = 0; + virtual void add( const void* p, verifiable& v, + boost::unit_test::const_string instance, + const boost::optional< type_name >& type, + boost::unit_test::const_string name ) = 0; virtual void add( verifiable& v ) = 0; virtual void remove( verifiable& v ) = 0; diff --git a/src/libraries/turtle/default_error.hpp b/src/libraries/turtle/default_error.hpp index 6e05f1f..dac0bb0 100644 --- a/src/libraries/turtle/default_error.hpp +++ b/src/libraries/turtle/default_error.hpp @@ -10,7 +10,6 @@ #define MOCK_DEFAULT_ERROR_POLICY_HPP_INCLUDED #include -#include namespace mock { @@ -27,8 +26,8 @@ namespace mock template< typename Context > static void fail( - const std::string& message, const Context& context, - const std::string& file = "unknown location", int line = 0 ) + const char* message, const Context& context, + const char* file = "unknown location", int line = 0 ) { std::cerr << file << '(' << line << "): " << message << ": " << context << std::endl; @@ -36,12 +35,12 @@ namespace mock template< typename Context > static void expected_call( const Context& /*context*/, - const std::string& /*file*/, int /*line*/ ) + const char* /*file*/, int /*line*/ ) {} template< typename Context > static void missing_action( const Context& context, - const std::string& file, int line ) + const char* file, int line ) { fail( "missing action", context, file, line ); } @@ -52,19 +51,19 @@ namespace mock } template< typename Context > static void sequence_failed( const Context& context, - const std::string& /*file*/, int /*line*/ ) + const char* file, int line ) { - fail( "sequence failed", context ); + fail( "sequence failed", context, file, line ); } template< typename Context > static void verification_failed( const Context& context, - const std::string& file, int line ) + const char* file, int line ) { fail( "verification failed", context, file, line ); } template< typename Context > static void untriggered_expectation( const Context& context, - const std::string& file, int line ) + const char* file, int line ) { fail( "untriggered expectation", context, file, line ); } diff --git a/src/libraries/turtle/expectation.hpp b/src/libraries/turtle/expectation.hpp index 06499c6..abfa358 100644 --- a/src/libraries/turtle/expectation.hpp +++ b/src/libraries/turtle/expectation.hpp @@ -36,7 +36,7 @@ namespace detail , file_( "unknown location" ) , line_( 0 ) {} - void set_location( const std::string& file, int line ) + void set_location( const char* file, int line ) { file_ = file; line_ = line; @@ -65,7 +65,7 @@ namespace detail return i_->invoked(); } - const std::string& file() const + const char* file() const { return file_; } @@ -100,7 +100,7 @@ namespace detail typedef sequences_type::const_iterator sequences_cit; sequences_type sequences_; - std::string file_; + const char* file_; int line_; }; diff --git a/src/libraries/turtle/function.hpp b/src/libraries/turtle/function.hpp index 727c4d6..5e052a3 100644 --- a/src/libraries/turtle/function.hpp +++ b/src/libraries/turtle/function.hpp @@ -16,6 +16,7 @@ #include "verifiable.hpp" #include "log.hpp" #include "args.hpp" +#include "type_name.hpp" #include #include #include @@ -23,8 +24,10 @@ #include #include #include +#include #include #include +#include #include #include @@ -63,7 +66,7 @@ namespace mock impl_->reset(); } - expectation_type& expect( const std::string& file, int line ) + expectation_type& expect( const char* file, int line ) { return impl_->expect( file, line ); } @@ -95,18 +98,21 @@ namespace mock return s << *e.impl_; } - function& _configure( detail::context& c, const std::string& instance ) + function& _configure( detail::context& c, + boost::unit_test::const_string instance ) { if( ! impl_->context_ ) c.add( *impl_ ); - c.add( impl_.get(), *impl_, instance, "", "" ); + c.add( impl_.get(), *impl_, instance, + boost::optional< detail::type_name >(), "" ); impl_->context_ = &c; return *this; } void configure( detail::context& c, const void* p, - const std::string& instance, const std::string& type, - const std::string& name ) const + boost::unit_test::const_string instance, + const boost::optional< detail::type_name >& type, + boost::unit_test::const_string name ) const { if( ! impl_->context_ ) c.add( *impl_ ); @@ -170,7 +176,7 @@ namespace mock expectations_.clear(); } - expectation_type& expect( const std::string& file, int line ) + expectation_type& expect( const char* file, int line ) { expectation_type& e = expect(); e.set_location( file, line ); diff --git a/src/libraries/turtle/mock.hpp b/src/libraries/turtle/mock.hpp index db06005..e95a11d 100644 --- a/src/libraries/turtle/mock.hpp +++ b/src/libraries/turtle/mock.hpp @@ -13,8 +13,8 @@ #include "cleanup.hpp" #include "object.hpp" #include "function.hpp" -#include "type_name.hpp" #include "args.hpp" +#include "type_name.hpp" #include #include #include @@ -105,7 +105,7 @@ namespace detail #define MOCK_METHOD_EXPECTATION(S, t) \ mutable mock::function< S > t##expectation; \ mock::function< S >& t##configure( const mock::detail::context&, \ - const std::string& instance ) const \ + boost::unit_test::const_string instance ) const \ { \ mock::detail::configure( *this, t##expectation, instance, \ mock::detail::type_name( typeid( *this ) ), \ diff --git a/src/libraries/turtle/object.hpp b/src/libraries/turtle/object.hpp index e8a2bc5..9a9aa93 100644 --- a/src/libraries/turtle/object.hpp +++ b/src/libraries/turtle/object.hpp @@ -13,10 +13,10 @@ #include "context.hpp" #include "parent.hpp" #include "child.hpp" +#include "type_name.hpp" #include #include #include -#include namespace mock { @@ -41,8 +41,9 @@ namespace mock { public: virtual void add( const void* /*p*/, verifiable& v, - const std::string& instance, const std::string& type, - const std::string& name ) + boost::unit_test::const_string instance, + const boost::optional< detail::type_name >& type, + boost::unit_test::const_string name ) { if( children_.empty() ) mock::detail::root.add( *this ); @@ -95,16 +96,20 @@ namespace mock namespace detail { template< typename E > - E& configure( const object& o, E& e, const std::string& instance, - const std::string& type, const std::string& name ) + E& configure( const object& o, E& e, + boost::unit_test::const_string instance, + const boost::optional< type_name >& type, + boost::unit_test::const_string name ) { e.configure( *o.impl_, o.impl_.get(), instance, type, name ); return e; } template< typename E, typename T > - E& configure( const T& t, E& e, const std::string& instance, - const std::string& type, const std::string& name, + E& configure( const T& t, E& e, + boost::unit_test::const_string instance, + const boost::optional< type_name >& type, + boost::unit_test::const_string name, BOOST_DEDUCED_TYPENAME boost::disable_if< BOOST_DEDUCED_TYPENAME boost::is_base_of< object, T > >::type* = 0 ) diff --git a/src/libraries/turtle/parent.hpp b/src/libraries/turtle/parent.hpp index d7fabf9..93b0224 100644 --- a/src/libraries/turtle/parent.hpp +++ b/src/libraries/turtle/parent.hpp @@ -9,8 +9,10 @@ #ifndef MOCK_PARENT_HPP_INCLUDED #define MOCK_PARENT_HPP_INCLUDED +#include "type_name.hpp" +#include +#include #include -#include namespace mock { @@ -21,20 +23,21 @@ namespace detail public: parent() {} - parent( const std::string& instance, const std::string& type ) + parent( boost::unit_test::const_string instance, + const boost::optional< type_name >& type ) : instance_( instance ) , type_( type ) {} friend std::ostream& operator<<( std::ostream& s, const parent& p ) { s << p.instance_; - if( ! p.type_.empty() ) - s << " " + p.type_ + "::"; + if( p.type_ ) + s << " " << *p.type_ << "::"; return s; } private: - std::string instance_; - std::string type_; + boost::unit_test::const_string instance_; + boost::optional< type_name > type_; }; } } diff --git a/src/libraries/turtle/root.hpp b/src/libraries/turtle/root.hpp index 7975435..562d874 100644 --- a/src/libraries/turtle/root.hpp +++ b/src/libraries/turtle/root.hpp @@ -16,7 +16,6 @@ #include "function.hpp" #include #include -#include #include namespace mock @@ -28,8 +27,9 @@ namespace detail { public: virtual void add( const void* p, verifiable& v, - const std::string& instance, const std::string& type, - const std::string& name ) + boost::unit_test::const_string instance, + const boost::optional< type_name >& type, + boost::unit_test::const_string name ) { children_it it = children_.lower_bound( &v ); if( it == children_.end() || @@ -94,8 +94,9 @@ namespace detail if( --it_->second.second == 0 ) parents_->erase( it_ ); } - void update( const std::string& instance, const std::string& type, - const std::string& name ) + void update( boost::unit_test::const_string instance, + const boost::optional< type_name >& type, + boost::unit_test::const_string name ) { child_.update( it_->second.first, instance, type, name ); } diff --git a/src/libraries/turtle/type_name.hpp b/src/libraries/turtle/type_name.hpp index b36acfd..56f52d7 100644 --- a/src/libraries/turtle/type_name.hpp +++ b/src/libraries/turtle/type_name.hpp @@ -9,8 +9,10 @@ #ifndef MOCK_TYPE_NAME_HPP_INCLUDED #define MOCK_TYPE_NAME_HPP_INCLUDED +#include #include #include +#include #ifdef __GNUC__ #include #include @@ -20,41 +22,62 @@ namespace mock { namespace detail { - inline std::string type_full_name( const std::type_info& info ) + class type_name { - const char* name = info.name(); -#ifdef __GNUC__ - size_t size = 0; - int status = 0; - char* result = abi::__cxa_demangle( name, NULL, &size, &status ); - struct guard + public: + explicit type_name( const std::type_info& info ) + : info_( &info ) + {} + friend std::ostream& operator<<( std::ostream& s, const type_name& t ) { - explicit guard( char* p ) - : p_( p ) - {} - ~guard() + t.serialize( s, *t.info_ ); + return s; + } + private: + void serialize( std::ostream& s, const std::type_info& info ) const + { + const char* name = info.name(); +#ifdef __GNUC__ + size_t size = 0; + int status = 0; + char* result = abi::__cxa_demangle( name, NULL, &size, &status ); + struct guard { - free( p_ ); - } - private: - char* p_; - } g( result ); - if( result ) - return result; + explicit guard( char* p ) + : p_( p ) + {} + ~guard() + { + free( p_ ); + } + private: + char* p_; + } g( result ); + if( result ) + serialize( s, result ); + else #endif - return name; - } - inline std::string type_name( const std::type_info& info ) - { - const std::string name = type_full_name( info ); - std::size_t p = name.rfind( "::" ); - if( p != std::string::npos ) - return name.substr( p + 2 ); - p = name.rfind( " " ); - if( p != std::string::npos ) - return name.substr( p + 1 ); - return name; - } + serialize( s, name ); + } + void serialize( std::ostream& s, boost::unit_test::const_string name ) const + { + std::size_t p = name.rfind( "::" ); + if( p != boost::unit_test::const_string::npos ) + { + s << name.substr( p + 2 ); + return; + } + p = name.rfind( " " ); + if( p != boost::unit_test::const_string::npos ) + { + s << name.substr( p + 1 ); + return; + } + s << name; + } + + const std::type_info* info_; + }; } } diff --git a/src/tests/turtle_test/mock_error.hpp b/src/tests/turtle_test/mock_error.hpp index 5a4d521..c1d163e 100644 --- a/src/tests/turtle_test/mock_error.hpp +++ b/src/tests/turtle_test/mock_error.hpp @@ -12,7 +12,6 @@ #define MOCK_ERROR_POLICY mock_error #include #include -#include namespace { @@ -37,14 +36,14 @@ namespace mock template< typename Context > static void missing_action( const Context& context, - const std::string& /*file*/, int /*line*/ ) + const char* /*file*/, int /*line*/ ) { last_context = boost::lexical_cast< std::string >( context ); ++missing_action_count; } template< typename Context > static void expected_call( const Context& /*context*/, - const std::string& /*file*/, int /*line*/ ) + const char* /*file*/, int /*line*/ ) { last_context.clear(); ++expected_call_count; @@ -57,21 +56,21 @@ namespace mock } template< typename Context > static void sequence_failed( const Context& context, - const std::string& /*file*/, int /*line*/ ) + const char* /*file*/, int /*line*/ ) { last_context = boost::lexical_cast< std::string >( context ); ++sequence_failed_count; } template< typename Context > static void verification_failed( const Context& context, - const std::string& /*file*/, int /*line*/ ) + const char* /*file*/, int /*line*/ ) { last_context = boost::lexical_cast< std::string >( context ); ++verification_failed_count; } template< typename Context > static void untriggered_expectation( const Context& context, - const std::string& /*file*/, int /*line*/ ) + const char* /*file*/, int /*line*/ ) { last_context = boost::lexical_cast< std::string >( context ); ++untriggered_expectation_count; diff --git a/src/tests/turtle_test/object_test.cpp b/src/tests/turtle_test/object_test.cpp index 77bfaaa..baee29b 100644 --- a/src/tests/turtle_test/object_test.cpp +++ b/src/tests/turtle_test/object_test.cpp @@ -28,7 +28,7 @@ namespace { fixture() { - mock::detail::configure( o, e, "instance", "type", "name" ); + mock::detail::configure( o, e, "instance", mock::detail::type_name( typeid( "type" ) ), "name" ); } mock::object o; mock::function< void() > e; @@ -64,7 +64,7 @@ BOOST_AUTO_TEST_CASE( an_object_is_assignable_by_sharing_its_state ) mock::function< void() > e; { mock::object o2; - mock::detail::configure( o2, e, "instance", "type", "name" ); + mock::detail::configure( o2, e, "instance", mock::detail::type_name( typeid( "type" ) ), "name" ); e.expect().once(); o1 = o2; BOOST_CHECK( ! mock::verify( o2 ) ); @@ -78,7 +78,7 @@ BOOST_AUTO_TEST_CASE( an_object_is_copiable_by_sharing_its_state ) std::auto_ptr< mock::object > o2( new mock::object ); const mock::object o1( *o2 ); mock::function< void() > e; - mock::detail::configure( *o2, e, "instance", "type", "name" ); + mock::detail::configure( *o2, e, "instance", mock::detail::type_name( typeid( "type" ) ), "name" ); e.expect().once(); BOOST_CHECK( ! mock::verify( *o2 ) ); BOOST_CHECK( ! mock::verify( o1 ) ); diff --git a/src/tests/turtle_test/type_name_test.cpp b/src/tests/turtle_test/type_name_test.cpp index 2a35fcc..2d9f8c0 100644 --- a/src/tests/turtle_test/type_name_test.cpp +++ b/src/tests/turtle_test/type_name_test.cpp @@ -8,12 +8,22 @@ #include #include +#include struct my_type_from_default_namespace {}; +namespace +{ + template< typename T > + std::string to_string( const T& ) + { + return boost::lexical_cast< std::string >( mock::detail::type_name( typeid( T ) ) ); + } +} + BOOST_AUTO_TEST_CASE( name_of_type_from_default_namespace_is_extracted ) { - BOOST_CHECK_EQUAL( "my_type_from_default_namespace", mock::detail::type_name( typeid( my_type_from_default_namespace ) ) ); + BOOST_CHECK_EQUAL( "my_type_from_default_namespace", to_string( my_type_from_default_namespace() ) ); } namespace @@ -23,7 +33,7 @@ namespace BOOST_AUTO_TEST_CASE( name_of_type_from_anonymous_namespace_is_extracted ) { - BOOST_CHECK_EQUAL( "my_type_from_anonymous_namespace", mock::detail::type_name( typeid( my_type_from_anonymous_namespace ) ) ); + BOOST_CHECK_EQUAL( "my_type_from_anonymous_namespace", to_string( my_type_from_anonymous_namespace() ) ); } namespace nm @@ -33,7 +43,7 @@ namespace nm BOOST_AUTO_TEST_CASE( name_of_type_from_named_namespace_is_extracted ) { - BOOST_CHECK_EQUAL( "my_type_from_named_namespace", mock::detail::type_name( typeid( nm::my_type_from_named_namespace ) ) ); + BOOST_CHECK_EQUAL( "my_type_from_named_namespace", to_string( nm::my_type_from_named_namespace() ) ); } namespace nm @@ -46,7 +56,7 @@ namespace inner BOOST_AUTO_TEST_CASE( name_of_type_from_named_inner_namespace_is_extracted ) { - BOOST_CHECK_EQUAL( "my_type_from_named_inner_namespace", mock::detail::type_name( typeid( nm::inner::my_type_from_named_inner_namespace ) ) ); + BOOST_CHECK_EQUAL( "my_type_from_named_inner_namespace", to_string( nm::inner::my_type_from_named_inner_namespace() ) ); } namespace @@ -59,11 +69,11 @@ namespace inner BOOST_AUTO_TEST_CASE( name_of_type_from_unnamed_inner_namespace_is_extracted ) { - BOOST_CHECK_EQUAL( "my_type_from_unnamed_inner_namespace", mock::detail::type_name( typeid( inner::my_type_from_unnamed_inner_namespace ) ) ); + BOOST_CHECK_EQUAL( "my_type_from_unnamed_inner_namespace", to_string( inner::my_type_from_unnamed_inner_namespace() ) ); } BOOST_AUTO_TEST_CASE( name_of_local_type_is_extracted ) { struct my_local_type {}; - BOOST_CHECK_EQUAL( "my_local_type", mock::detail::type_name( typeid( my_local_type ) ) ); + BOOST_CHECK_EQUAL( "my_local_type", boost::lexical_cast< std::string >( mock::detail::type_name( typeid( my_local_type ) ) ) ); }