From 095add46f850061a496a140d4ef638c46bf9fa51 Mon Sep 17 00:00:00 2001 From: mat007 Date: Sat, 6 Jul 2013 21:19:29 +0000 Subject: [PATCH] Moved limitation workarounds code to compiled source file git-svn-id: https://svn.code.sf.net/p/turtle/code/trunk@673 860be788-9bd5-4423-9f1e-828f051e677b --- build/boost/doc/Jamfile.jam | 4 + .../example/limitations_comma_in_macro.cpp | 40 ++++ .../limitations_const_parameter_warning.cpp | 42 ++++ .../doc/example/limitations_literal_zero.cpp | 35 ++++ .../example/limitations_private_method.cpp | 21 ++ .../example/limitations_template_method.cpp | 33 ++++ .../example/limitations_throw_specifier.cpp | 27 +++ build/boost/doc/limitations.qbk | 184 ++++++------------ 8 files changed, 257 insertions(+), 129 deletions(-) create mode 100644 build/boost/doc/example/limitations_comma_in_macro.cpp create mode 100644 build/boost/doc/example/limitations_const_parameter_warning.cpp create mode 100644 build/boost/doc/example/limitations_literal_zero.cpp create mode 100644 build/boost/doc/example/limitations_private_method.cpp create mode 100644 build/boost/doc/example/limitations_template_method.cpp create mode 100644 build/boost/doc/example/limitations_throw_specifier.cpp diff --git a/build/boost/doc/Jamfile.jam b/build/boost/doc/Jamfile.jam index 7f6bb17..313da73 100644 --- a/build/boost/doc/Jamfile.jam +++ b/build/boost/doc/Jamfile.jam @@ -52,3 +52,7 @@ compile example/patterns_retrieve_cref.cpp ; compile example/patterns_invoke_functor.cpp ; compile example/patterns_quick_constraint.cpp ; compile example/reference.cpp ; +compile example/limitations_throw_specifier.cpp ; +compile example/limitations_literal_zero.cpp ; +compile example/limitations_template_method.cpp ; +compile example/limitations_private_method.cpp ; diff --git a/build/boost/doc/example/limitations_comma_in_macro.cpp b/build/boost/doc/example/limitations_comma_in_macro.cpp new file mode 100644 index 0000000..a1c85bd --- /dev/null +++ b/build/boost/doc/example/limitations_comma_in_macro.cpp @@ -0,0 +1,40 @@ +#define BOOST_AUTO_TEST_MAIN +#include +#include + +namespace +{ +//[ limitations_comma_in_macro_problem + template< typename T1, typename T2 > + struct my_base_class + {}; +//] +} + +namespace limitations_comma_in_macro_solution_1 +{ +//[ limitations_comma_in_macro_solution_1 + typedef my_base_class< int, int > my_base_type; + + MOCK_BASE_CLASS( my_mock, my_base_type ) + {}; +//] +} + +namespace limitations_comma_in_macro_solution_2 +{ +//[ limitations_comma_in_macro_solution_2 + template< typename T1, typename T2 > + MOCK_BASE_CLASS( my_mock, my_base_type< T1 BOOST_PP_COMMA() T2 > ) + {}; +//] +} + +namespace limitations_comma_in_macro_solution_3 +{ +//[ limitations_comma_in_macro_solution_3 + template< typename T1, typename T2 > + struct my_mock : my_base_type< T1, T2 >, mock::object + {}; +//] +} diff --git a/build/boost/doc/example/limitations_const_parameter_warning.cpp b/build/boost/doc/example/limitations_const_parameter_warning.cpp new file mode 100644 index 0000000..32cbfe5 --- /dev/null +++ b/build/boost/doc/example/limitations_const_parameter_warning.cpp @@ -0,0 +1,42 @@ +#define BOOST_AUTO_TEST_MAIN +#include +#include + +namespace +{ +//[ limitations_const_parameter_warning_problem + class base + { + public: + virtual void method( const int ) = 0; + }; +//] +} + +namespace limitations_const_parameter_warning_explanation +{ +//[ limitations_const_parameter_warning_explanation + class derived : public base + { + public: + virtual void method( const int ); + }; + + void derived::method( int ) + {} +//] +} + +namespace limitations_const_parameter_warning_solution +{ +//[ limitations_const_parameter_warning_solution + MOCK_BASE_CLASS( mock_base, base ) + { + void method( const int i ) + { + method_stub( i ); + } + MOCK_METHOD( method_stub, 1, void( int ), method ) + }; +//] +} diff --git a/build/boost/doc/example/limitations_literal_zero.cpp b/build/boost/doc/example/limitations_literal_zero.cpp new file mode 100644 index 0000000..a55daef --- /dev/null +++ b/build/boost/doc/example/limitations_literal_zero.cpp @@ -0,0 +1,35 @@ +#define BOOST_AUTO_TEST_MAIN +#include +#include + +namespace +{ +//[ limitations_literal_zero_problem + class base + { + public: + virtual void method( int* i ) = 0; + }; + + MOCK_BASE_CLASS( mock_base, base ) + { + MOCK_METHOD( method, 1 ) + }; +//] +} + +BOOST_AUTO_TEST_CASE( literal_zero ) +{ + mock_base m; +//[ limitations_literal_zero_solution_1 + MOCK_EXPECT( m.method ).with( mock::equal< int* >( 0 ) ); // this compiles +//] +//[ limitations_literal_zero_solution_2 + MOCK_EXPECT( m.method ).with( mock::negate ); +//] +#ifdef MOCK_NULLPTR +//[ limitations_literal_zero_solution_3 + MOCK_EXPECT( m.method ).with( nullptr ); +//] +#endif +} diff --git a/build/boost/doc/example/limitations_private_method.cpp b/build/boost/doc/example/limitations_private_method.cpp new file mode 100644 index 0000000..5121c7f --- /dev/null +++ b/build/boost/doc/example/limitations_private_method.cpp @@ -0,0 +1,21 @@ +#define BOOST_AUTO_TEST_MAIN +#include +#include + +namespace +{ +//[ limitations_private_method_problem + class base + { + private: + virtual void method() = 0; + }; +//] + +//[ limitations_private_method_solution + MOCK_BASE_CLASS( mock_base, base ) + { + MOCK_METHOD( method, 0, void() ) + }; +//] +} diff --git a/build/boost/doc/example/limitations_template_method.cpp b/build/boost/doc/example/limitations_template_method.cpp new file mode 100644 index 0000000..70659a6 --- /dev/null +++ b/build/boost/doc/example/limitations_template_method.cpp @@ -0,0 +1,33 @@ +#define BOOST_AUTO_TEST_MAIN +#include +#include + +//[ limitations_template_method_problem +class concept +{ +public: + template< typename T > + void method( T t ) + {} +}; + +template< typename T > +class client +{ +public: + client( T t ) // T is supposed to model the previous concept + { + t.method( 42 ); + t.method( "string" ); + } +}; +//] + +//[ limitations_template_method_solution +MOCK_CLASS( mock_concept ) +{ + MOCK_METHOD( method, 1, void( int ), method_int ) + MOCK_METHOD( method, 1, void( const char* ), method_string ) +}; +//] + diff --git a/build/boost/doc/example/limitations_throw_specifier.cpp b/build/boost/doc/example/limitations_throw_specifier.cpp new file mode 100644 index 0000000..f6c6923 --- /dev/null +++ b/build/boost/doc/example/limitations_throw_specifier.cpp @@ -0,0 +1,27 @@ +#define BOOST_AUTO_TEST_MAIN +#include +#include + +namespace +{ +//[ limitations_throw_specifier_problem + struct base_class + { + virtual ~base_class() + {} + + virtual void method() throw (); + }; +//] + +//[ limitations_throw_specifier_solution + MOCK_BASE_CLASS( mock_class, base_class ) + { + void method() throw () + { + method_proxy(); + } + MOCK_METHOD( method_proxy, 0, void(), method ) + }; +//] +} diff --git a/build/boost/doc/limitations.qbk b/build/boost/doc/limitations.qbk index 2d2ac44..428673f 100644 --- a/build/boost/doc/limitations.qbk +++ b/build/boost/doc/limitations.qbk @@ -1,4 +1,10 @@ [section Limitations] +[import example/limitations_literal_zero.cpp] +[import example/limitations_throw_specifier.cpp] +[import example/limitations_template_method.cpp] +[import example/limitations_private_method.cpp] +[import example/limitations_comma_in_macro.cpp] +[import example/limitations_const_parameter_warning.cpp] This section lists the library known limitations. @@ -8,73 +14,46 @@ There is no support for unicode logging mainly because Boost.Test does not suppo [endsect] -[section Litteral 0 cannot be used as null pointer in constraints] +[section Literal 0 cannot be used as null pointer in constraints] Given : - class base - { - public: - virtual void method( int i* ) = 0; - }; - - MOCK_BASE_CLASS( mock_base, base ) - { - MOCK_METHOD( method, 1 ) - }; +[limitations_literal_zero_problem] The following code does not compile : - mock_base m; - MOCK_EXPECT( m.method ).with( mock::equal( 0 ) ); // this fails - MOCK_EXPECT( m.method ).with( 0 ); // this fails too ! + BOOST_AUTO_TEST_CASE( literal_zero ) + { + mock_base m; + MOCK_EXPECT( m.method ).with( mock::equal( 0 ) ); // this fails + MOCK_EXPECT( m.method ).with( 0 ); // this fails too ! + } -This is due to the fact that the library uses templates pretty heavily, and the litteral 0 is considered as an int when instantiating a template function. +This is due to the fact that the library uses templates pretty heavily, and literal 0 is considered as an int when instantiating a template function. A workaround is : - MOCK_EXPECT( m.method ).with( mock::equal< int* >( 0 ) ); // this compiles +[limitations_literal_zero_solution_1] However a somewhat better solution would be : - MOCK_EXPECT( m.method ).with( mock::negate ); +[limitations_literal_zero_solution_2] or with C++11 nullptr support : - MOCK_EXPECT( m.method ).with( nullptr ); +[limitations_literal_zero_solution_3] [endsect] [section Template methods cannot be mocked] -Given the following client code : +Given : - class concept - { - public: - template< typename T > - void method( T t ) - {} - }; - - template< typename T > - class client - { - public: - client( T t ) // T is supposed to model the previous concept - { - t.method( 42 ); - t.method( "string" ); - } - }; +[limitations_template_method_problem] -Writing a mock object modeling 'concept' requires to list all the possible versions of 'method' : +writing a mock object modeling 'concept' requires to list all the possible versions of 'method' : - MOCK_CLASS( mock_concept ) - { - MOCK_METHOD( method, 1, void( int ), method_int ) - MOCK_METHOD( method, 1, void( const char* ), method_string ) - }; +[limitations_template_method_solution] While still somewhat possible, mocking a template method is indeed a bit cumbersome. @@ -82,89 +61,56 @@ While still somewhat possible, mocking a template method is indeed a bit cumbers [section Private virtual methods cannot be mocked without spelling out the signature] -The following code does not compile : +Given : + +[limitations_private_method_problem] + +the following code does not compile : - class base - { - private: - virtual void method() = 0; - }; - MOCK_BASE_CLASS( mock_base, base ) { - MOCK_METHOD( method, 0 ) // this fails to compile because 'method' is not visible + MOCK_METHOD( method, 0 ) // this fails because 'method' is not visible }; A workaround would be to add the signature to MOCK_METHOD : - MOCK_BASE_CLASS( mock_base, base ) - { - MOCK_METHOD_EXT( method, 0, void() ) - }; +[limitations_private_method_solution] [endsect] [section Methods with a throw specifier cannot be mocked] -The following code does not compile : +Given : - namespace +[limitations_throw_specifier_problem] + +the following code does not compile : + + MOCK_BASE_CLASS( mock_class, base_class ) { - struct base_class - { - virtual ~base_class() - {} - - virtual void method() throw; - }; - - MOCK_BASE_CLASS( mock_class, base_class ) - { - MOCK_METHOD( method, 0 ) // this fails to compile because of the throw specifier - }; - } + MOCK_METHOD( method, 0 ) // this fails because of the throw specifier + }; A workaround would be to write a proxy member function : - namespace - { - struct base_class - { - virtual ~base_class() - {} - - virtual void method() throw; - }; - - MOCK_BASE_CLASS( mock_class, base_class ) - { - void method() throw - { - method_proxy(); - } - MOCK_METHOD( method_proxy, 0, void(), method ) - }; - } +[limitations_throw_specifier_solution] [endsect] [section Compilers without support for variadic macros fail on commas in MOCK_BASE_CLASS] -For compilers without support for variadic macros the following code does not compile : +For compilers without support for variadic macros given : - template< typename T1, typename T2 > - struct my_base_class - {}; - - MOCK_BASE_CLASS( my_mock, my_base_class< int, int > ) // this fails to compile because the pre-processor believes the macro to be called with 3 arguments +[limitations_comma_in_macro_problem] + +the following code does not compile : + + MOCK_BASE_CLASS( my_mock, my_base_class< int, int > ) // this fails because the pre-processor believes the macro to be called with 3 arguments {}; One workaround is : - typedef my_base_class< int, int > my_base_type; - - MOCK_BASE_CLASS( my_mock, my_base_type ) - {}; +[limitations_comma_in_macro_solution_1] Of course this is not always possible, as in : @@ -174,9 +120,7 @@ Of course this is not always possible, as in : Another workaround would make use of [@http://www.boost.org/libs/preprocessor Boost.Preprocessor] : - template< typename T1, typename T2 > - MOCK_BASE_CLASS( my_mock, my_base_type< T1 BOOST_PP_COMMA() T2 > ) - {}; +[limitations_comma_in_macro_solution_2] Actually BOOST_PP_COMMA implementation is quite trivial, being only : @@ -184,9 +128,7 @@ Actually BOOST_PP_COMMA implementation is quite trivial, being only : Finally another workaround would be to not use the macro at all : - template< typename T1, typename T2 > - struct my_mock : my_base_type< T1, T2 >, mock::object - {}; +[limitations_comma_in_macro_solution_3] Note that [@www.boost.org/libs/utility/identity_type/doc/html/index.html Boost.IdentityType] is of little help here because the type is by essence very often abstract, which doesn't work well for some compilers (e.g. gcc). @@ -220,14 +162,12 @@ Example : [c++] -The following code produces this warning with some versions of the Microsoft Visual Studio compiler : +Given : + +[limitations_const_parameter_warning_problem] + +the following code produces this warning with some versions of the Microsoft Visual Studio compiler : - class base - { - public: - virtual void method( const int ) = 0; - }; - MOCK_BASE_CLASS( mock_base, base ) { MOCK_METHOD( method, 1 ) // this produces the warning @@ -238,27 +178,13 @@ The problem is that the 'const' is actually not part of the function signature a The first workaround would be to remove the 'const' all together. -This is more sensible than it first sounds, after all the 'const' is useless in this situation, indeed : +This is more sensible than it first sounds, after all the 'const' is useless in this situation, indeed the following compiles, links and is valid C++ : - class derived : public base - { - public: - virtual void method( const int ); - }; - - void derived::method( int ) // this compiles, links and is valid C++ - {} +[limitations_const_parameter_warning_explanation] Otherwise another workaround would be to provide a proxy method : - MOCK_BASE_CLASS( mock_base, base ) - { - void method( const int i ) - { - method_stub( i ); - } - MOCK_METHOD( method_stub, 1, void( int ), method ) - }; +[limitations_const_parameter_warning_solution] [endsect]