Archive for the ‘Programming’ Category

Power.Fake.It: PowerFake + FakeIt

As I said in the introduction, PowerFake lacked the features of a complete mocking framework, and I was hoping to be able to integrate it with one or more mocking frameworks. So, I decided to try integrating it with FakeIt as the first target.

Thanks to its flexible design using virtual functions and abstract classes, I was able to integrate PowerFake with it nicely, and the result is PowerFakeIt template class. Using it, you can use almost all of FakeIt tools with free functions and non-virtual member functions, effectively extending FakeIt for such use cases.

You still have to use WRAP_FUNCTION macors to mark the desired functions. But instead of using MakeFake() directly, you can use PowerFakeIt<> class with utilities of FakeIt:

PowerFakeIt<> pfk;

When(Function(pfk, normal_func)).Do([](int ){ cout << "WOW :) " << endl; });

normal_func(100);

Verify(Function(pfk, normal_func).Using(100)).Exactly(1);

PowerFakeIt<SampleClass> pfk2;
When(Method(pfk2, CallThis)).Do([]() { cout << "WOW2" << endl; });
When(OverloadedMethod(pfk2, OverloadedCall, int())).Return(4);
When(ConstOverloadedMethod(pfk2, OverloadedCall, int(int))).Return(5);

SampleClass s;
s.CallThis();
s.OverloadedCall();

Verify(Method(pfk2, CallThis)).Exactly(1);
Using(pfk2).Verify(Method(pfk2, CallThis)
+ OverloadedMethod(pfk2, OverloadedCall, int()));

VerifyNoOtherInvocations(Method(pfk2, CallThis));

 

Going for Virtual Functions

Initially, I didn’t intend to do anything for virtual functions in PowerFake, as I thought it is already covered enough in mocking frameworks. However, soon I realized that it is not true: you also need to use a mock object and pass it to the functions using the virtual functions… but it is not always possible to inject your mock object in the production code, because the function might have used an internal object for its purpose. In some cases, the virtual function call might even got devirtualized by the compiler, which will result in a direct function call rather than an indirect, virtual call. And, PowerFake already supports faking devirtualized calls.

Reading a bit, I figured that I can also cover virtual function calls of GCC in PowerFake. Now that PowerFake can be used with mocking utilities of FakeIt, my next priority is supporting virtual function calls. And, it’ll fake virtual functions of the target class, so every object of that class will call the fake function and there is no need to use & pass  a mock object to the target function.

Finally, note that PowerFake is still in the early stages of development, so no backward compatibility is guaranteed and there might be many corner cases which need to be fixed.

 

 

 

 

 

Advertisements

Introducing PowerFake for C++

PowerFake is a new mini-framework/tool to make it possible to fake/mock  free functions and static & non-virtual member functions in C++. It requires no change to the code under test, but it might need some structural changes, like moving some parts of the code to a different .cpp file; or making inline functions non-inline when built for testing.

It is useful for writing unit tests and faking/mocking functions which should not/cannot be run during a test case. Some say that such a feature is useful for existing code, but should not be needed for a code which is written testable from the beginning. But, personally I don’t agree that it is always appropriate to inject such dependencies using virtual interfaces or templates.

Currently, it is not supposed to become a mocking framework on its own. I hope that I can integrate PowerFake into at least one existing C++ mocking framework. Therefore, currently it doesn’t provide anything beyond faking existing functions.

Unlike similar solutions like CppFreeMock, Injector++(Currently Windows only), and Hippomocks(Free functions only); it doesn’t do runtime patching of functions. Probably the most similar solution is C Mock, which relies on the mocked functions to be in dynamic libraries and redefines them, but it takes a slightly different approach. Instead PowerFake relies on using GNU ld’s --wrap option to provide a replacement function for the original function while linking. Therefore, currently PowerFake is a GCC & GNU ld only solution, but it should be fairly easy to port to other linkers which provide a similar option. It also depends on the GCC implementation of type_info::name() to retrieve mangled name of a type. Therefore, porting to other compilers would need a way to extract such information too.

CppFreeMock seems to be able to satisfy my needs, but I personally doesn’t feel safe about runtime patching, specially since the code is not actively maintained and I wonder if it is guaranteed to work with any version of GCC. PowerFake solution seems safer to me, but it has its own limitations as it relies on link-time wrapping of target functions.

If the caller and called function are in the same translation unit, it won’t be intercepted by PowerFake. Also, using PowerFake needs some modifications to how test suite is built because some linker flags are generated by PowerFake, and it also needs to adjust some symbol names. It also can’t fake inline functions, and faking template functions needs some work.

Currently, support for using PowerFake in CMake projects is provided so that using it is as easy as possible. But using it with other build tools would need more work.

Example

After setting up the build system to properly integrate PowerFake, using it is fairly easy. There are 2 main steps to fake a function: 1. Marking the functions which should be faked. 2. Faking them as appropriate

For simplicity, I use a file named wrap.cpp to mark functions for faking:

#include 

#include "functions.h"
#include "SampleClass.h"

WRAP_FUNCTION(normal_func);

WRAP_FUNCTION(SampleClass::CallThis);

And now, faking the function is as simple as a MakeFake() call:

...
 normal_func(3); // Calls the real function auto normalfk = MakeFake(normal_func,
 [](int) { cout << "Fake called for normal_func(int)" << endl; }
 );
 normal_func(3); // Calls the fake function created above

 auto ccfk = MakeFake(&SampleClass::CallThis,
 []() { cout << "Fake called for SampleClass::CallThis" << endl; }
 );
 SampleClass c;
 c.CallThis();

// Fakes are in effect as while as fake objects (normalfk & 
// ccfk above) live.
...

 

Hope that somebody finds PowerFake useful too! 🙂