Faking it, FFF and Variadic Macro Madness

I spend the day updating the Fake Function Framework, Mike Long’s (@meekrosoft) creation. With my client last week, one of the engineers had some problems with Visual Studio (don’t we all) and the Fake Function Framework (a.k.a FFF). I promised to integrate the changes into the FFF. The FFF is created with a ruby script, but you don’t have to care about that unless you have functions to fake that have more than 10 parameters. But anyway, I spent the day updating and reviewing the ruby script that generates the FFF.

FFF lets you make C test stubs using C macros. It can make it easier to do the right thing while you are programming. By the ‘right thing’, I mean make sure you know what your code is doing and that means automating unit tests for your code. Off the soapbox and back to the FFF…

If you had code that used pthread (or some other problem dependency), FFF let’s you create a stub very quickly. First, look at the signature for the function you want to stub, in this case pthread_create:

int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
                          void *(*start_routine) (void *), void *arg);

The way you create an FFF fake is to copy and paste the declaration into you test code; then edit it into this form using the FAKE_VALUE_FUNCTION macro (there is a FAKE_VOID_FUNCTION too):

FAKE_VALUE_FUNCTION(int, pthread_create, pthread_t *, const pthread_attr_t *,
                          void *(*) (void *), void *);

Basically you in insert some commas and remove all the parameter names, though in this case that’s not good enough. The function pointer syntax confounds the FFF. The problem is easily solved with a bridging type just for the FFF’s (and your) benefit.

typedef void *(*threadEntry) (void *);
FAKE_VALUE_FUNCTION(int, pthread_create, pthread_t *, const pthread_attr_t *,
                          threadEntry, void *);

Now you basically have a test stub that remembers each parameter, how many times its been called, and a few other things. It also lets you control the return result in your test scenario.

Any of you that have worked with macros know, they are not known for the clarity of the compiler errors. Make a mistake in the macro and you have no idea until you use it, and then then you know right where the problem is because C preprocessor errors are so clear. Oh wait, that is a different universe, not this one. Actually, the error is almost totally unhelpful.

I came across this handy way to trick the C preprocessor into telling me the macro expansion:

#define FFF_EXPAND_MACRO_HELPER(x) #x
#define FFF_EXPAND_MACRO(x) FFF_EXPAND_MACRO_HELPER(x)
#pragma message "Macro: " FAKE_VALUE_FUNCTION(int, foobar)

Seems like there should be better way to show a macro expansion on demand. Let me know if you have one.

Look at fff.h and you will see some amazing macro madness. Be happy, as I am, that it is generated and did not have to be hand crafted. Thanks Mike for the great tool and figuring out that variadic macro madness. To find out more about the FFF, check it out on my fff gitbub fork of Mike Long’s original version.

3 thoughts on “Faking it, FFF and Variadic Macro Madness

  1. I am trying to fake a function so that I can make it fail, so I can observe what happens when that fails. I have successfully faked functions for this project before, but in this particular instance, the linker shows up with multiple definitions of the same function.

    It is my understanding that API source files that contain only one function create objects with one function. When objects of these types are added to a library, each function can be individually linked into the final program, without dragging other functions in the library along with it. Source files for an API that have multiple functions in the same file can also be compiled and linked and added to the library, but when one function from that source module is linked into the program, ALL of the functions from that source module are linked in as well. With that in mind, I faked all of the functions in the source file; they are now ALL presenting duplicate definitions.

    The linker indicates that the Faked Function is defined first. Why would the linker pull in any functions that have already been defined?

    Let me describe my environment:
    Oracle Linux, running Eclipse Oxygen.2 and MATE Desktop Environment 1.16.2, GNU build tools, with a Makefile in every directory, gcc compiler 4.8.5 20150623.

  2. Sorry to have missed your comment and not replied sooner. Have you figured it out? There must be some reason the original file got pulled in.

    Questions that come to mind

    Are you sure the production code in a library and not linked as an .o file?

    Is there a global in the production code that is needed?

    Is there a typo in one of the fake function names?

Leave a Reply

Your email address will not be published.

Be gone spammers * Time limit is exhausted. Please reload the CAPTCHA.