[/
 / Copyright (c) 2014 Mathieu Champlon
 /
 / 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)
 /]

[section Limitations]
[import example/limitations_literal_zero.cpp]
[import example/limitations_throw_specifier.cpp]
[import example/limitations_non_virtual_method.cpp]
[import example/limitations_template_base_class_method.cpp]
[import example/limitations_template_method.cpp]
[import example/limitations_protected_private_method.cpp]
[import example/limitations_comma_in_macro.cpp]
[import example/limitations_const_parameter_warning.cpp]

This section lists the library known limitations.

[section No support for unicode logging]

There is no support for unicode logging mainly because Boost.Test does not support it either.

[endsect]

[section Literal 0 cannot be used as null pointer in constraints]

Given :

[limitations_literal_zero_problem]

The following code does not compile :

 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 literal 0 is considered as an int when instantiating a template function.

A workaround is :

[limitations_literal_zero_solution_1]

However a somewhat better solution would be :

[limitations_literal_zero_solution_2]

or with C++11 nullptr support :

[limitations_literal_zero_solution_3]

[endsect]

[section Non-virtual methods cannot be mocked]

Given :

[limitations_non_virtual_method_problem]

the following code compiles but will not work as expected :

[limitations_non_virtual_method_problem_2]

The mock object will never be exercised because the library relies on polymorphism to hook the calls.

There is no other solution than to refactor the production code, the most simple being to change the method to virtual.

[endsect]

[section Template methods cannot be mocked]

Given :

[limitations_template_method_problem]

writing a mock object modeling 'concept' requires to list all the possible versions of 'method' :

[limitations_template_method_solution]

However if one or more template parameters must be explicitly specified as in :

[limitations_template_method_problem_2]

delegate methods must be manually added :

[limitations_template_method_solution_2]

While still somewhat possible, mocking a template method can indeed prove a bit cumbersome.

[endsect]

[section Template base class methods cannot be mocked without specifying the signature]

Given :

[limitations_template_base_class_method_problem]

the following code does not compile :

 template< typename T >
 MOCK_BASE_CLASS( mock_base, base< T > )
 {
     MOCK_METHOD( method, 0 ) // this fails
 };

A workaround would be to add the signature to MOCK_METHOD :

[limitations_template_base_class_method_solution]

[endsect]

[section Protected and private virtual methods cannot be mocked without specifying the signature]

Given :

[limitations_protected_private_method_problem]

the following code does not compile :

 MOCK_BASE_CLASS( mock_base, base )
 {
     MOCK_METHOD( method_1, 0 ) // this fails because a function pointer on 'base::method_1' is not allowed
     MOCK_METHOD( method_2, 0 ) // this fails because 'method_2' is not visible
 };

A workaround would be to add the signature to MOCK_METHOD :

[limitations_protected_private_method_solution]

[endsect]

[section Methods with a throw specifier cannot be mocked]

Given :

[limitations_throw_specifier_problem]

the following code does not compile :

 MOCK_BASE_CLASS( mock_class, base_class )
 {
     MOCK_METHOD( method, 0 ) // this fails because of the throw specifier
 };

A workaround would be to write a proxy member function :

[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 given :

[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 :

[limitations_comma_in_macro_solution_1]

Of course this is not always possible, as in :

 template< typename T1, typename T2 >
 MOCK_BASE_CLASS( my_mock, my_base_type< T1, T2 > )
 {};

Another workaround would make use of [@http://www.boost.org/libs/preprocessor Boost.Preprocessor] :

[limitations_comma_in_macro_solution_2]

Actually BOOST_PP_COMMA implementation is quite trivial, being only :

 #define BOOST_PP_COMMA() ,

Finally another workaround would be to not use the macro at all :

[limitations_comma_in_macro_solution_3]

Note that [@http://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).

[endsect]

[section Warning C4505: '...' : unreferenced local function has been removed]

Example :

[teletype]

 warning C4505: 'base::[thunk]: __thiscall base::`vcall'{0,{flat}}' }'' : unreferenced local function has been removed

[c++]

This seems to be [@https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=324427 a random bug] with some versions of the Microsoft Visual Studio compiler.

The only known workaround is to disable the warning with a pragma :

 #pragma warning( disable: 4505 )

[endsect]

[section Warning C4301: '...': overriding virtual function only differs from '...' by const/volatile qualifier]

Example :

[teletype]

 warning C4301: '`anonymous-namespace'::base::method': overriding virtual function only differs from '`anonymous-namespace'::base::method' by const/volatile qualifier

[c++]

Given :

[limitations_const_parameter_warning_problem]

the following code produces this warning with some versions of the Microsoft Visual Studio compiler :

 MOCK_BASE_CLASS( mock_base, base )
 {
     MOCK_METHOD( method, 1 )                    // this produces the warning
     MOCK_METHOD( method, 1, void( const int ) ) // forcing the signature will not help, this produces the warning too !
 };

The problem is that the 'const' is actually not part of the function signature and therefore cannot be introspected.

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 the following compiles, links and is valid C++ :

[limitations_const_parameter_warning_explanation]

Otherwise another workaround would be to provide a proxy method :

[limitations_const_parameter_warning_solution]

[endsect]

[section Warning C4267: 'argument' : conversion from 'size_t' to 'unsigned int', possible loss of data]

Compiling under Microsoft Visual Studio with the /Wp64 flag produces this warning at various locations in the library code.

This is actually a bug in the compiler, for more information see [@http://connect.microsoft.com/VisualStudio/feedback/details/253172/incorrect-warning-c4267 incorrect-warning-c4267].

[endsect]

[section Using C++11 lambda as constraints requires decltype compiler support]

The technique used in order to detect whether a constraint is a C++11 lambda or not is based on decltype, which means the library can fail to detect a lambda in case the compiler does not support it.

[endsect]

[endsect]
