Open belchercw opened 6 years ago
@belchercw I tried running your example using gcc 8.2.0 . I keep getting this error:
In file included from /src/tests/test_monitor.cpp:2:
/src/thirdparty/fakeit_freefn.hpp:22:34: error: 'arg1' has not been declared
#define MAKE_PARAMS_1(type) type arg1
^~~~
/src/thirdparty/fakeit_freefn.hpp:27:31: note: in expansion of macro 'MAKE_PARAMS_1'
#define MAKE_PARAMS_N(N, ...) MAKE_PARAMS_##N(__VA_ARGS__)
^~~~~~~~~~~~
/src/thirdparty/fakeit_freefn.hpp:28:37: note: in expansion of macro 'MAKE_PARAMS_N'
#define MAKE_PARAMS_FORCE_N(N, ...) MAKE_PARAMS_N(N, __VA_ARGS__)
^~~~~~~~~~~~~
/src/thirdparty/fakeit_freefn.hpp:29:26: note: in expansion of macro 'MAKE_PARAMS_FORCE_N'
#define MAKE_PARAMS(...) MAKE_PARAMS_FORCE_N(GET_ARG_COUNT(__VA_ARGS__), __VA_ARGS__)
^~~~~~~~~~~~~~~~~~~
/src/thirdparty/fakeit_freefn.hpp:50:32: note: in expansion of macro 'MAKE_PARAMS'
virtual ReturnType Function(MAKE_PARAMS(__VA_ARGS__)) = 0; \
^~~~~~~~~~~
/src/tests/test_monitor.cpp:15:1: note: in expansion of macro 'MockFree'
MockFree(void, Function1)
^~~~~~~~
/src/thirdparty/fakeit_freefn.hpp:53:45: error: variable or field 'Function1' declared void
ReturnType Function(MAKE_PARAMS(__VA_ARGS__)) \
^
/src/tests/test_monitor.cpp:15:1: note: in expansion of macro 'MockFree'
MockFree(void, Function1)
^~~~~~~~
/src/thirdparty/fakeit_freefn.hpp:22:34: error: 'arg1' was not declared in this scope
#define MAKE_PARAMS_1(type) type arg1
^~~~
/src/thirdparty/fakeit_freefn.hpp:27:31: note: in expansion of macro 'MAKE_PARAMS_1'
#define MAKE_PARAMS_N(N, ...) MAKE_PARAMS_##N(__VA_ARGS__)
^~~~~~~~~~~~
/src/thirdparty/fakeit_freefn.hpp:28:37: note: in expansion of macro 'MAKE_PARAMS_N'
#define MAKE_PARAMS_FORCE_N(N, ...) MAKE_PARAMS_N(N, __VA_ARGS__)
^~~~~~~~~~~~~
/src/thirdparty/fakeit_freefn.hpp:29:26: note: in expansion of macro 'MAKE_PARAMS_FORCE_N'
#define MAKE_PARAMS(...) MAKE_PARAMS_FORCE_N(GET_ARG_COUNT(__VA_ARGS__), __VA_ARGS__)
^~~~~~~~~~~~~~~~~~~
/src/thirdparty/fakeit_freefn.hpp:53:21: note: in expansion of macro 'MAKE_PARAMS'
ReturnType Function(MAKE_PARAMS(__VA_ARGS__)) \
^~~~~~~~~~~
/src/tests/test_monitor.cpp:15:1: note: in expansion of macro 'MockFree'
MockFree(void, Function1)
^~~~~~~~
/src/tests/test_monitor.cpp: In function 'void ____C_A_T_C_H____T_E_S_T____0()':
/src/tests/test_monitor.cpp:22:101: error: no matching function for call to 'fakeit::WhenFunctor::MethodProgress<void, int>::Do(____C_A_T_C_H____T_E_S_T____0()::<lambda()>)'
fakeit::When(FreeFunction(Function1)).Do([]() {std::cout << "Called Function1()" << std::endl; });
^
In file included from /src/tests/test_monitor.cpp:1:
/src/thirdparty/fakeit.hpp:7259:59: note: candidate: 'fakeit::MethodStubbingProgress<void, arglist ...>& fakeit::MethodStubbingProgress<void, arglist ...>::Do(std::function<void(const typename fakeit::test_arg<arglist>::type ...)>) [with arglist = {int}]'
virtual MethodStubbingProgress<void, arglist...> &Do(
^~
/src/thirdparty/fakeit.hpp:7259:59: note: no known conversion for argument 1 from '____C_A_T_C_H____T_E_S_T____0()::<lambda()>' to 'std::function<void(int&)>'
/src/thirdparty/fakeit.hpp:7302:9: note: candidate: 'template<class F> fakeit::MethodStubbingProgress<void, arglist ...>& fakeit::MethodStubbingProgress<void, arglist ...>::Do(const fakeit::Quantifier<R>&) [with F = F; arglist = {int}]'
Do(const Quantifier<F> &q) {
^~
/src/thirdparty/fakeit.hpp:7302:9: note: template argument deduction/substitution failed:
/src/tests/test_monitor.cpp:22:101: note: '____C_A_T_C_H____T_E_S_T____0()::<lambda()>' is not derived from 'const fakeit::Quantifier<R>'
fakeit::When(FreeFunction(Function1)).Do([]() {std::cout << "Called Function1()" << std::endl; });
^
In file included from /src/tests/test_monitor.cpp:1:
/src/thirdparty/fakeit.hpp:7308:9: note: candidate: 'template<class first, class second, class ... tail> fakeit::MethodStubbingProgress<void, arglist ...>& fakeit::MethodStubbingProgress<void, arglist ...>::Do(const first&, const second&, const tail& ...) [with first = first; second = second; tail = {tail ...}; arglist = {int}]'
Do(const first &f, const second &s, const tail &... t) {
^~
/src/thirdparty/fakeit.hpp:7308:9: note: template argument deduction/substitution failed:
/src/tests/test_monitor.cpp:22:101: note: candidate expects at least 2 arguments, 1 provided
fakeit::When(FreeFunction(Function1)).Do([]() {std::cout << "Called Function1()" << std::endl; });
^
Problem was that the GET_ARG_COUNT
macro would return 0 even when there were no arguments. I fixed it by using this implementation instead.
#define GET_ARG_COUNT(...) Y_TUPLE_SIZE_II((Y_TUPLE_SIZE_PREFIX_ ## __VA_ARGS__ ## _Y_TUPLE_SIZE_POSTFIX,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0))
#define Y_TUPLE_SIZE_II(__args) Y_TUPLE_SIZE_I __args
#define Y_TUPLE_SIZE_PREFIX__Y_TUPLE_SIZE_POSTFIX ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,0
#define Y_TUPLE_SIZE_I(__p0,__p1,__p2,__p3,__p4,__p5,__p6,__p7,__p8,__p9,__p10,__p11,__p12,__p13,__p14,__p15,__p16,__p17,__p18,__p19,__p20,__p21,__p22,__p23,__p24,__p25,__p26,__p27,__p28,__p29,__p30,__p31,__n,...) __n
I am not sure how well that would work in Visual Studio though. I have only tested it on GCC 8.2.0 .
Just mocking your float Function2(int);
I am getting Function2 is not a type
. I am using g++ 8.2.1.
I would love to see this feature included into this library. Unfortunately without it, a user is most likely forced to group functions into a class (And they cannot be static functions), in order to get the mocking behavior. I also like the nomenclature in this example.
:( this would be great for embedded systems, where you have freeRTOS C functions and C++ app code
I would love to have free function mocks, This would simplify testing higher level functions calling lower level free functions.
However, I don't see how this strategy could be useful. The calling code will still call the real function. The mock will never be invoked. Unless the calling code gets the free function injected somehow.
I have never tried it but if someone's looking for a library that already does that there's powerfake : https://github.com/hedayat/powerfake
From what I understand it can interface with FakeIt, so you can use both. But as I said I never tried so I'm not sure exactly how it works.
@FranckRJ Thanks for mentioning my tool. :)
Currently, it uses a feature of GNU ld to provide a replacement function at link time. Therefore, it has some limitations, for example it cannot catch inlined function calls. It also provides a limited way of capturing calls in the same translation unit which might not work in some optimized contexts and also you lose access to the real function completely.
Finally, it doesn't work with anything other than GNU ld or compatible linkers.
Mocking free functions is useful when calling into C APIs or simply non-member C++ functions. I've hacked together an example that might be useful for others, or for inclusion in the library. Probably needs some T's crossed and I's dotted to work for all use-cases. Here's an example of the result:
Someone with better macro foo than I could probably do a better job, but I've copied the implementation I hacked together below. The macros for creating the argument lists are the bulk of it (which I shamelessly stole off stack overflow). Maybe there's a better way? Scroll to the namespace fakeit at the bottom for the interesting part.
BTW - Great job on FakeIt! Amazing library - would love a tutorial on the crazy VTable hackery going on.