0

I am trying to mock functions from an external library with FFF (Fake Function Framework). The functions are kinda weird declared and I have no idea how to do it.

lib.h

...
// XWF_GetItemInformation
typedef INT64 (__stdcall *fptr_XWF_GetItemInformation) (LONG nItemID, 
   LONG nInfoType, LPBOOL lpSuccess); 
...
extern fptr_XWF_GetItemInformation XWF_GetItemInformation;
...

lib.cpp

...
fptr_XWF_GetItemInformation XWF_GetItemInformation;
...
LONG __stdcall XT_RetrieveFunctionPointers()
{
    ...
    XWF_GetItemInformation = (fptr_XWF_GetItemInformation) GetProcAddress(Hdl, "XWF_GetItemInformation");
    ...
}

I am mocking it with:

#include <fff/fff.h>
#include <lib.h>

FAKE_VALUE_FUNC(INT64, XWF_GetItemInformation, LONG, LONG, LPBOOL);

But this gives the error (shortened):

In file included from external/xwf/item.test.cpp:5:
external/fff/fff.h:1793:100: error: 'INT64 XWF_GetItemInformation(LONG, LONG, LPBOOL)' redeclared as different kind of entity
 1793 |     RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2); \
      |                                                                                                    ^
...
external/xwf/x-tension.fff.h:9:1: note: in expansion of macro 'FAKE_VALUE_FUNC'
    9 | FAKE_VALUE_FUNC(INT64, XWF_GetItemInformation, LONG, LONG, LPBOOL)
      | ^~~~~~~~~~~~~~~
In file included from external/xwf/x-tension.h:14,
                 from external/xwf/x-tension.fff.h:5,
                 from external/xwf/item.test.cpp:7:
external/xwf/x-tension/X-Tension.h:322:36: note: previous declaration 'INT64 (* XWF_GetItemInformation)(LONG, LONG, LPBOOL)'
  322 | extern fptr_XWF_GetItemInformation XWF_GetItemInformation;
      |                                    ^~~~~~~~~~~~~~~~~~~~~~
In file included from external/xwf/item.test.cpp:5:
external/fff/fff.h:1797:100: error: 'INT64 XWF_GetItemInformation(LONG, LONG, LPBOOL)' redeclared as different kind of entity
 1797 |     RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2){ \
      |
...
In file included from external/xwf/x-tension.h:14,
                 from external/xwf/x-tension.fff.h:5,
                 from external/xwf/item.test.cpp:7:
external/xwf/x-tension/X-Tension.h:322:36: note: previous declaration 'INT64 (* XWF_GetItemInformation)(LONG, LONG, LPBOOL)'
  322 | extern fptr_XWF_GetItemInformation XWF_GetItemInformation;
      |                                    ^~~~~~~~~~~~~~~~~~~~~~
make: *** [Makefile:201: build/xwf/item.test.o] Error 1

Can someone help me how I can mock this function?

Teharez
  • 501
  • 8
  • 25
  • You have linked issues. Basically you are linked to dependency and at same time you try to mock dependency. Your tests should not link dependency library. From first pick I do not like this `fff` it doesn't do anything better what `gmock` doesn't do better. – Marek R Dec 02 '20 at 16:07
  • @MarekR Thank you. That fixed the compiler error. But now I'm getting a SIGSEGV when the XWF_GetItemInformation is called in the test, which is the same behaviour I get when not mocking the function at all. – Teharez Dec 03 '20 at 08:03
  • new/different problem - file a new question. – Marek R Dec 03 '20 at 11:20
  • Thanks will do. When you post your comment as answer I can accept it. – Teharez Dec 03 '20 at 12:46
  • Regarding `fff` vs `gmock`. From what I read `gmock` is better for OOO and you have to rewrite your code using interfaces to mock free functions while in `fff` that's a lot easier. – Teharez Dec 03 '20 at 12:56
  • This was my personal opinion based on quick review of `fff` manual. Maybe if I would use it, it could turn out handy (but based on examples I really doubt that). – Marek R Dec 03 '20 at 13:16

1 Answers1

0

The issue is mentioned in your compiler output:

error: 'INT64 XWF_GetItemInformation(LONG, LONG, LPBOOL)' redeclared as different kind of entity

Basically, you need to avoid the definition of the function in lib.cpp. You can do that by several ways:

  1. Don't include the file lib.cpp in your unit test project. Only include the lib.h file which is the interface you are mocking. This solution is good in case you have no intention of calling the original implementations of the functions in lib.cpp from your unit test project and there are no other dependencies that call these functions.
  2. Build the entire production source code or the relevant module into a library file and include it in your unit test project instead of your CPP and C source code files. If you create a mock function for a function in that library, the mock will then receive preference and you won't have a redefinition error.
  3. Add the weak attribute before the function in lib.cpp. This will give preference to the other definition of the function (the mock function in your unit test project).
  4. You can use Function Pointer Substitution or Link Time Substitution. You can read more about these two options here: https://stackoverflow.com/a/65814339/4441211 (Function Pointer Substitution with FFF is specifically addressed in that link)
Eyal Gerber
  • 1,026
  • 10
  • 27