Mocking non-virtual functions in C++ with gMock & PowerFake

I’ve not written anything here in about 4 years, and many things have changed in the meantime. After becoming a father and start rising my twins, I was less active in the community. But I hope this will change in future.

Recently, I’ve put some effort to enhance PowerFake further to fix some known issues and enhance its feature set, and also provide some brief docs! Among other things, I figured that Google Test/Google Mock are pretty popular; while I personally prefer Boost Test / FakeIt. Therefore, I also decided to look into integrating with Google Mock (gMock); and I was able to put something together for it. So, it is now possible to mock non-virtual member functions, static member functions and free functions using gMock too. All someone needs to do is to use macros provided by PowerFake instead of gMock macros to define mocked functions, and to inherit from GPowerFake<Class> instead of Class to mock member functions:

class MockFreeFunctions
{
    public:
        GPFK_MOCK_FUNCTION(void, normal_func, (int b, const char **const *c,
                const std::string &d, const char *(*e)(const char *)));
        GPFK_MOCK_FUNCTION(std::string, overloaded2, (int b));
};

class MockSample: public GPowerFake<SampleClass>
{
    public:
        GPFK_MOCK_METHOD(void, CallThis, (), (const));
        GPFK_MOCK_METHOD(int, OverloadedCall, ());

        // free functions can be mocked here too
        GPFK_MOCK_FUNCTION(void, noexcept_func, ());
};

void GMockSamples()
{
    MockSample mock;
    MockFreeFunctions freemock;
    EXPECT_CALL(mock, CallThis()).Times(AtLeast(1));
    EXPECT_CALL(mock, OverloadedCall()).Times(AtLeast(1));
    EXPECT_CALL(freemock, normal_func(1, nullptr, "", nullptr))
        .Times(AtLeast(1));
    EXPECT_CALL(freemock, overloaded2(_)).Times(AtLeast(1));
    EXPECT_CALL(mock, noexcept_func()).Times(AtLeast(1));

    normal_func(1, nullptr, "", nullptr);
    noexcept_func();
    SampleClass s;
    s.CallThis();
    s.OverloadedCall();
    overloaded2(60);
}

In addition to gMock integration support, there are also a number of improvements:

  • Cleaner API: A unified WRAP_FUNCTION() macro instead of having separate macros for private and static member functions
  • HIDE_FUNCTION() macro: supports capturing function calls in the same translation unit (if the call is not optimized out completely), although you’ll lose access the the real function completely. Also, it only works with GNU LD linker currently.
  • Add support for Clang & LLD linker in addition to GCC/MinGW & LD linker
  • Much faster link times
  • Easier CMake integration, specially for compiling with MinGW
  • Add a brief usage doc to README
  • Unified TAG_PRIVATE() macro

That’s it for now!

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.

 

 

 

 

 

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! 🙂

Fedora 25 (Beta)

Fedora 25 will be coming soon! So I decided to try F25 beta to see if I can hunt some bugs; and even if I can start using it as my primary OS. Specially since it is going to use Wayland by default rather than Xorg for its graphical subsystem, more testing is needed to make sure that final release will have less surprising bugs! I’ve tried Wayland in Fedora 24 and some applications (notably Eclipse) work terrible under Wayland; and I’m installed F25 mainly to see how Eclipse works under Wayland there.

Fortunately, Eclipse works fine under Wayland in Fedora 25. Even better, Wayland experience under Fedora 25 seems more smooth than that of Fedora 24 using nouveau driver.

Generally, Wayland under Fedora 25 is usable. However, there are bugs & annoyances here and there. So, it is likely that Fedora will be perceived by a number of users as ‘buggy’. If you are installing Fedora 25 for such users, it is better to switch to using Xorg for now.

For example, I’ve experienced system temporary freeze (e.g. 1 minute or more) a few times. Hamster time tracker and its gnome shell extension have problems under Wayland. The tray icon of Telegram desktop application doesn’t appear.

Fedora 25 comes with a new Gnome. It comes with a new calendar application, which looks good. However, it has crashed for me a lot when adding/removing events. It also lacks some features: e.g. I didn’t find the ability to define recurring events.
Keyboard settings dialog is also updated.
screenshot-from-2016-10-17-18-29-14
Seeing everything in a long list is actually frightening. But being able to search for the desired action is great; which is IMHO the main way to interact with this new settings design.

As every Fedora release, I enjoy installing & using Fedora extra backgrounds. They are really beautiful, and I’d hope they were available by default (Although it seems that there are a few new default background images too).

Installation
—————-
What about installation? Fedora 25 installation has almost nothing new: it looks very similar to that of previous releases. However, I had two issues with it which was new: 1. I was unable to install F25 using the ISO stored on the same disk as the target partition. So, I was forced to install Fedora 25 using a separate USB disk which was something I didn’t do for a long time. 2. Layout switching didn’t work in the installer. Beside these problems, the installation goes like before.

And, if you care about your internet usage, make sure that you disable both dnf makecache timer, and stop PackageKit from downloading updates automatically. I don’t allow a new Fedora installation to access internet before doing these, as it might just eat a considerable amount of data.

Eclipse problems on Fedora 22

Update: Since Eclipse Mars update in Fedora 22, and with latest updates installed, the memory/CPU usage problem is fixed. Also, the problem with mylyn icons is fixed. While there are still some rendering bugs, along with some bad colors here and there; the GTK3 version is now usable for me. 🙂

Since upgrade to Fedora 22, I had several problems with Eclipse. The most annoying one, in my pretty old laptop, was nearly locking up the system after using it for awhile as reported here. I found that my 4GB RAM is almost full and kswapd is taking almost 100% CPU.

First, I suspected that it is a kernel bug since kswapd was using 100% CPU. And, it seems that it really is, but it is an old kernel problem happens when the available RAM is low. Therefore, it should not be the main reason of my problems.

Investigating more, I found the the amount of ‘shared’ memory in ‘free -m’ output keeps increasing when I use Eclipse until I’m forced to close Eclipse due to lock up. Then it is returned back to normal. I guess this is a graphics driver bug, as the Eclipse memory usage reported by ‘top’ is not changed much since its start. (and the kernel out of memory messages always happen in the driver code).

Anyway, besides, Eclipse was very ‘heavy’ on my laptop: it constantly used very high CPU usage even if I just scrolled the editor window. It was also very slow (with lag). Also Eclipse uses a new coloring for various part of the UI in F22, which are sometimes very annoying (e.g. unreadable text, unnoticeable selected region, etc). I was forced to change some colors to have a usable editor.

I was living by all these problems until yesterday, in which I found that mylyn task list is also buggy. It didn’t show unread/new issue marks beside issue icons, so I was missing new/updated issues assigned to me. I was seriously considering switching back to Fedora 21, when I suddenly found out that Eclipse is using GTK3 backend in Fedora 22 and I should be able to make it use GTK2 instead.

The first way to do this I found in Internet was setting SWT_GTK3 environment variable to 0. But it didn’t work in Fedora 22. It turns out that Eclipse has a command line argument for it, which is used by Fedora (in /etc/eclipse.ini) to force usage of GTK3 backend. So, to run Eclipse with GTK2 backend, you are forced to either modify eclipse.ini, or run eclipse with the following command line option:

eclipse --launcher.GTK_version 2

And yes, finally, it fixed all my problems with Eclipse in Fedora 22!

Happy New Year (1394)! :)

Yes, it is a long time sine last time I updated my blog. I really liked to blog about a few things like Fedora 21 release, but I didn’t managed to. Hopefully, there will be more posts this year! 🙂

And this is my card for the new Solar/Jalali(? if I’m not wrong :P) year, Happy Nowruz (the first day of year in our calendar is called Nowruz)!

Happy Nowruz

The Shiny New DNF, and Why I Prefer Yum!

You certainly already know about DNF, the new package manager in Fedora which is available in Fedora repositories since Fedora 18 while Yum is still the default (command line) package manager. However, DNF is expected to replace Yum as the default command line package manager in Fedora 22. And so, every Fedora user should consider it seriously.

DNF has some interesting properties that I really liked about it. Probably the most visible one, and certainly the most exciting one for me, is speed. It is really much faster than Yum. Yum spend much time specially when starting up. For example, I ran a similar “list” command using both DNF and Yum for a few times. Yum took around 25 to 29 seconds to do it, while DNF did it in about 5 seconds (no downloads for both). I don’t know what does do during this period, but my HDD is busy most of the time.

Surprisingly, Yum downloads compressed SQLite metadata, but DNF downloads compressed XML metadata. The former is considerably larger than the latter, but Yum selected it for speed purposes! AFAIK, DNF (actually libsolv) doesn’t use XML metadata internally but converts them to its own format; and IMHO this is actually the right thing to do. Yum could also use a similar approach (I’d prefer), but maybe they preferred to waste bandwidth rather than client’s processing power (and yum wouldn’t be faster than today anyway).

It was great news for me; not only DNF is way faster than Yum, but also it downloads much smaller metadata (about half the size of compressed sqlite dbs used by Yum)… However, I was wrong; The amount of metadata downloaded by DNF is actually more than that of Yum! I saw that Yum downloads about 20M of metadata for fedora-updates repository while DNF get around 30M! Why? Because DNF is too lazy and downloads all metadata, including list of all files in all packages which is around 15M; while Yum only downloads list of files when they are actually needed. And in my system, Yum has never downloaded the list of files while DNF downloads them every time the repository is updated. I always hated Yum for downloading such a large metadata over and over again, and DNF is just horrible. Unfortunately, DNF author has no will to change the situation.

Actually, I use two plugins with Yum which I’d like to have in DNF too: yum-plugin-local and my own Yum Fast Downloader. The former is not that important, and I can live without it; and I hope to be able to create an equivalent of the latter, while it will need a completely new approach.

Currently, I use DNF for some operations like search and list commands, but use Yum for most other tasks. And I almost always run DNF from cache, except when I have free Internet access! I’ve also disabled automatic cache download by DNF, which can make DNF much more hostile!

DNF can eat your Internet credit silently!

Let’s assume that you pay for your Internet connection per GiB. And you install Fedora with DNF, and use it for one month. You never use DNF during this month. Now, you might get shocked that DNF has used about 1GiB of your internet credit, while you have not used it at all! Even if you decide to use DNF after one month, what you get is the latest metadata. So, 30MiB of that 1GiB is what you actually used. Yes, this is currently the default settings, which I consider insane. If Fedora 22 is released with DNF configured like this, it means that: Fedora 22 consumes about 1 GiB of your internet connection by default just for downloading repository metadata! Surprisingly, even if you update your Fedora regularly, the amount of actual data you download to update your Fedora might be less than that (thanks to delta RPMs).
Its true that the repository metadata format is currently very inefficient for updates and you should get all metadata again even if one package is added, and it is not DNF’s fault, but the decision to download metadata automatically, and downloading unnecessary metadata, is what DNF has made. That makes sense for people who have access to cheap internet, or don’t pay for it per GiB; but IMHO this should not be the default settings for a distribution like Fedora.
And, 1 GiB per month is just an estimate. I assumed that updates are pushed to Fedora updates repository once per day, and the metadata is around 30MiB. However, if, for example, updates are pushed two times a day, the estimate would be around 2GiB. Notice that with the default settings, DNF refreshes metadata every 3 hours. So, if there are regular updates in Fedora updates repository, DNF would re-get metadata up to 8 times a day, which will be around 8*30=240MiB per day, which will be 8GiB per month…

Anyway, if you happen to install DNF, make sure that you check metadata_timer_sync option in “man dnf.conf” and put an appropriate option in your dnf.conf. I use “metadata_timer_sync=0” as I don’t want it to waste my money for no good!

 

Parsidora 20 is out!

Took some time, but finally, I’m pleased to announce that Parsidora 20 is ready. It is based on Fedora 20 and its latest updates including: Linux kernel 3.15.4, Gnome 3.10.4, LibreOffice 4.2.5.2, and KDE 4.12.5. Additionally, latest packages from RPMFusion is included such as driver akmod packages, audio/video codecs and players and more. Also, there are some packages in Parsidora repositories like Flash player and Jockey (Old Ubuntu’s “Additional Hardware Drivers” application) to enhance out of the box functionality. Finally, it includes my Yum Fast Downloader plugin! 😉

Unlike most other Fedora remixes, it is mainly provided as an installation media rather than Live disk; and contains lots of packages so that it can provide most of users’ needs without downloading anything from the internet.

While users are more likely to have access to fast AND cheep internet connection these days, there are still many who don’t; and also, there are many situations I personally face which I want to have a new fully working Fedora installation as fast as possible, and downloading packages from Internet is not an option.

Parsidora is Fedora compatible, so it can be even used as an offline repository for existing Fedora installations. Yes, many of you might wonder if an offline repository is useful, but believe me, there are people who might access Internet using dial-up or GPRS, or have good but expensive internet connection.

Anyway, while we are late, I’m happy that it is finally available! 🙂

Nowruz Gift: Yum Fast Downloader 0.6.0 Released!

Happy Nowruz!

Gladly, I was able to devote some time to update yum fast downloader plugin to work much better with recent yum versions in Fedora 19/20. The plugin effectively disabled delta rpm support since the integration of presto into yum. To fix the issue, I reworked the plugin using the new download framework of yum/urlgrabber. The result is yum-fast-downloader plugin for Fedora 20, which not only fixes the problem but also brings better integration. As a result, the plugin is now responsible for almost all downloads including downloading drpm packages.
Besides, it is now possible to specify arbitrary command line arguments (e.g. -q) for aria2c in the plugin’s configuration file. Unlike previous versions, in this version download of multiple files in parallel are handled by multiple instances of aria2c; but I’d like to change it back to a single aria2c instance in future. I’ve added the new version for Fedora 20 in the repo, but not for Fedora 19. It should work on Fedora 19 too, but I have not tested it. If you tried YFD 0.6.0 in Fedora 19 successfully, please let me know so that I’ll add the new version to F19 repo too. Thanks!

What about DNF?
DNF looks promising. It is much faster than yum, and even uses xml metadata rather than sqlite ones which are smaller. However, it’s internal structure is completely different from yum, so it needs a completely new plugin. I’m still not sure if it is possible, but I’ll try in future. 🙂