meekrosoft / fff

A testing micro framework for creating function test doubles
Other
749 stars 163 forks source link

Allow support for std::function as the `custom_fake` type #110

Closed yperess closed 1 year ago

yperess commented 2 years ago

Is your feature request related to a problem? Please describe. I'd like to be able to use capture groups when assigning a custom fake, but this isn't possible when the custom fake type is a function pointer. Having the ability to override that using a config option would allow me to replace things like:

#define DECLARE_FAKE_VOID_FUNC0(FUNCNAME) \
    typedef struct FUNCNAME##_Fake { \
        DECLARE_ALL_FUNC_COMMON \
        DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
        void(*custom_fake)(void); \
        void(**custom_fake_seq)(void); \

with

#define DECLARE_FAKE_VOID_FUNC0(FUNCNAME) \
    typedef struct FUNCNAME##_Fake { \
        DECLARE_ALL_FUNC_COMMON \
        DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \
        std::function<void(void)> custom_fake; \
        std::function<void(void)> *custom_fake_seq; \

Describe the solution you'd like Allow applications to define a CONFIG_ value to swap away from function pointers and use std::function instead (when possible). This has the known limitation that variadic functions aren't supported by std::function, so VARARG fakes will have to remain as is

#define CONFIG_FFF_USE_STD_FUNCTION
#include "fff.h"

FAKE_VOID_FUN(my_func);

TEST_F(TestSuite, test_x) {
  my_func_fake.custom_fake = [this]() {
    // Can access `this`
  };
  ...
}

Describe alternatives you've considered Turn the generator into a boolean config to only support function pointers or std::function (similar to -wcc). It's less flexible (since clients will need to generate their own fff.h depending on their requirements), but easier to use. I'm happy with either approach.

yperess commented 1 year ago

Update:

After thinking about this some more I've settled on a much simpler solution. I've added:

#ifndef CUSTOM_FFF_FUNCTION_TEMPLATE
#define CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN, FUNCNAME, ...) \
    RETURN(*FUNCNAME)(__VA_ARGS__)
#endif /* CUSTOM_FFF_FUNCTION_TEMPLATE */

To the top of fff.h (the generated takes into account has_calling_conventions). Then both output_custom_function_signature and output_custom_function_array were updated to use CUSTOM_FFF_FUNCTION_TEMPLATE. Now developers can simply define CUSTOM_FFF_FUNCTION_TEMPLATE to use their own function wrapper which can be std::function, but also others like pigweed's implementation (https://pigweed.dev/pw_function/)