1
0
mirror of https://github.com/meekrosoft/fff synced 2026-01-23 00:15:59 +01:00

Add support for custom_fake function signatures

Update the generator to include a check for CUSTOM_FFF_FUNCTION_TEMPLATE.
If not present it will default to the C style function pointer.
Alternatively, developers may define their own version of the template to
leverage std::function or pw:Function (from the embedded Pigweed library).

Signed-off-by: Yuval Peress <peress@google.com>
This commit is contained in:
Yuval Peress
2022-08-11 11:34:53 -06:00
parent 1f6a3c8331
commit 2cce6b0fc8
3 changed files with 268 additions and 235 deletions

View File

@@ -35,10 +35,21 @@ def output_constants
putd "#define FFF_GCC_FUNCTION_ATTRIBUTES"
}
putd "#endif"
end
def output_default_function_pointer_macro(has_calling_conventions)
name = has_calling_conventions ? "(CALLING_CONVENTION *FUNCNAME)" : "(*FUNCNAME)"
calling_conv = has_calling_conventions ? ", CALLING_CONVENTION" : ""
putd "#ifndef CUSTOM_FFF_FUNCTION_TEMPLATE"
putd_backslash "#define CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN#{calling_conv}, FUNCNAME, ...)"
indent {
putd "RETURN#{name}(__VA_ARGS__)"
}
putd "#endif /* CUSTOM_FFF_FUNCTION_TEMPLATE */"
end
@@ -235,7 +246,9 @@ def define_reset_fake_helper
indent {
putd_backslash "void FUNCNAME##_reset(void){"
indent {
putd_backslash "memset(&FUNCNAME##_fake, 0, sizeof(FUNCNAME##_fake));"
putd_backslash "memset((void*)&FUNCNAME##_fake, 0, sizeof(FUNCNAME##_fake) - sizeof(FUNCNAME##_fake.custom_fake) - sizeof(FUNCNAME##_fake.custom_fake_seq));"
putd_backslash "FUNCNAME##_fake.custom_fake = NULL;"
putd_backslash "FUNCNAME##_fake.custom_fake_seq = NULL;"
putd_backslash "FUNCNAME##_fake.arg_history_len = FFF_ARG_HISTORY_LEN;"
}
putd "}"
@@ -359,6 +372,14 @@ def arg_val_list(args_count)
arguments.join(", ")
end
#example: ARG0_TYPE, ARG1_TYPE
def arg_type_list(args_count)
return "void" if (args_count == 0)
arguments = []
args_count.times { |i| arguments << "ARG#{i}_TYPE" }
arguments.join(", ")
end
#example: arg0, arg1
def arg_list(args_count)
arguments = []
@@ -374,17 +395,15 @@ end
def output_custom_function_signature(arg_count, has_varargs, has_calling_conventions, is_value_function)
return_type = is_value_function ? "RETURN_TYPE" : "void"
ap_list = has_varargs ? ", va_list ap" : ""
signature = has_calling_conventions ? "(CALLING_CONVENTION *custom_fake)" : "(*custom_fake)"
signature += "(#{arg_val_list(arg_count)}#{ap_list});"
putd_backslash return_type + signature
calling_conv = has_calling_conventions ? ", CALLING_CONVENTION" : ""
putd_backslash "CUSTOM_FFF_FUNCTION_TEMPLATE(#{return_type}#{calling_conv}, custom_fake, #{arg_type_list(arg_count)}#{ap_list});"
end
def output_custom_function_array(arg_count, has_varargs, has_calling_conventions, is_value_function)
return_type = is_value_function ? "RETURN_TYPE" : "void"
ap_list = has_varargs ? ", va_list ap" : ""
custom_array = has_calling_conventions ? "(CALLING_CONVENTION **custom_fake_seq)" : "(**custom_fake_seq)"
custom_array += "(#{arg_val_list(arg_count)}#{ap_list});"
putd_backslash return_type + custom_array
calling_conv = has_calling_conventions ? ", CALLING_CONVENTION" : ""
putd_backslash "CUSTOM_FFF_FUNCTION_TEMPLATE(#{return_type}#{calling_conv}, *custom_fake_seq, #{arg_type_list(arg_count)}#{ap_list});"
end
# example: RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1)
@@ -483,7 +502,7 @@ def output_function_body(arg_count, has_varargs, is_value_function)
putd_backslash "}"
}
putd_backslash "}"
putd_backslash "if (FUNCNAME##_fake.custom_fake){ "
putd_backslash "if (FUNCNAME##_fake.custom_fake != NULL){ "
indent {
putd_backslash "RETURN_TYPE ret = FUNCNAME##_fake.custom_fake(#{arg_list(arg_count)});" unless not is_value_function
putd_backslash "SAVE_RET_HISTORY(FUNCNAME, ret);" unless not is_value_function
@@ -644,6 +663,7 @@ def output_c_and_cpp(has_calling_conventions)
include_guard {
include_dependencies
output_constants
output_default_function_pointer_macro(has_calling_conventions)
output_internal_helper_macros
yield
output_macro_counting_shortcuts(has_calling_conventions)
@@ -675,4 +695,4 @@ help {
(2..$MAX_ARGS).each {|arg_count| output_macro(arg_count, true, has_calling_conventions, false)}
(2..$MAX_ARGS).each {|arg_count| output_macro(arg_count, true, has_calling_conventions, true)}
}
}
}

412
fff.h

File diff suppressed because it is too large Load Diff

View File

@@ -244,9 +244,11 @@ void voidfunc1outparam_custom_fake3(char *a)
TEST_F(FFFTestSuite, custom_fake_sequence_not_exausthed)
{
void (*custom_fakes[])(char *) = {voidfunc1outparam_custom_fake1,
voidfunc1outparam_custom_fake2,
voidfunc1outparam_custom_fake3};
CUSTOM_FFF_FUNCTION_TEMPLATE(void, custom_fakes[], char *) = {
voidfunc1outparam_custom_fake1,
voidfunc1outparam_custom_fake2,
voidfunc1outparam_custom_fake3
};
char a = 'a';
SET_CUSTOM_FAKE_SEQ(voidfunc1outparam, custom_fakes, 3);
@@ -304,9 +306,10 @@ long custom_longfunc3(void)
TEST_F(FFFTestSuite, custom_fake_seq_return_values_saved_in_history)
{
long (*custom_fakes[])(void) = {custom_longfunc1,
custom_longfunc2,
custom_longfunc3};
CUSTOM_FFF_FUNCTION_TEMPLATE(long, custom_fakes[], void) = {
custom_longfunc1,
custom_longfunc2,
custom_longfunc3};
SET_CUSTOM_FAKE_SEQ(longfunc0, custom_fakes, 3);
@@ -321,9 +324,10 @@ TEST_F(FFFTestSuite, custom_fake_seq_return_values_saved_in_history)
TEST_F(FFFTestSuite, custom_fake_sequence_exhausted)
{
void (*custom_fakes[])(char *) = {voidfunc1outparam_custom_fake1,
voidfunc1outparam_custom_fake2,
voidfunc1outparam_custom_fake3};
CUSTOM_FFF_FUNCTION_TEMPLATE(void, custom_fakes[], char *) = {
voidfunc1outparam_custom_fake1,
voidfunc1outparam_custom_fake2,
voidfunc1outparam_custom_fake3};
char a = 'a';
SET_CUSTOM_FAKE_SEQ(voidfunc1outparam, custom_fakes, 3);
@@ -399,9 +403,10 @@ int valuefunc3var_custom_fake3(const char *str, int a, va_list vl)
TEST_F(FFFTestSuite, vararg_custom_fake_sequence_not_exhausted)
{
int (*custom_fakes[])(const char *, int, va_list) = {valuefunc3var_custom_fake1,
valuefunc3var_custom_fake2,
valuefunc3var_custom_fake3};
CUSTOM_FFF_FUNCTION_TEMPLATE(int, custom_fakes[], const char *, int,
va_list) = {valuefunc3var_custom_fake1,
valuefunc3var_custom_fake2,
valuefunc3var_custom_fake3};
SET_CUSTOM_FAKE_SEQ(valuefunc3var, custom_fakes, 3);
int a = 1;
ASSERT_EQ(valuefunc3var("a", a, 2, 3, 4, 0), 10);
@@ -411,9 +416,10 @@ TEST_F(FFFTestSuite, vararg_custom_fake_sequence_not_exhausted)
TEST_F(FFFTestSuite, vararg_custom_fake_seq_return_values_saved_in_history)
{
int (*custom_fakes[])(const char *, int, va_list) = {valuefunc3var_custom_fake1,
valuefunc3var_custom_fake2,
valuefunc3var_custom_fake3};
CUSTOM_FFF_FUNCTION_TEMPLATE(int, custom_fakes[], const char *, int,
va_list) = {valuefunc3var_custom_fake1,
valuefunc3var_custom_fake2,
valuefunc3var_custom_fake3};
SET_CUSTOM_FAKE_SEQ(valuefunc3var, custom_fakes, 3);
int a = 1;
valuefunc3var("a", a, 2, 3, 4, 0);
@@ -426,9 +432,10 @@ TEST_F(FFFTestSuite, vararg_custom_fake_seq_return_values_saved_in_history)
TEST_F(FFFTestSuite, vararg_custom_fake_sequence_exhausted)
{
int (*custom_fakes[])(const char *, int, va_list) = {valuefunc3var_custom_fake1,
valuefunc3var_custom_fake2,
valuefunc3var_custom_fake3};
CUSTOM_FFF_FUNCTION_TEMPLATE(int, custom_fakes[], const char *, int,
va_list) = {valuefunc3var_custom_fake1,
valuefunc3var_custom_fake2,
valuefunc3var_custom_fake3};
SET_CUSTOM_FAKE_SEQ(valuefunc3var, custom_fakes, 3);
int a = 1;
ASSERT_EQ(valuefunc3var("a", a, 2, 3, 4, 0), 10);
@@ -440,9 +447,10 @@ TEST_F(FFFTestSuite, vararg_custom_fake_sequence_exhausted)
TEST_F(FFFTestSuite, vararg_custom_fake_sequence_reset)
{
int (*custom_fakes[])(const char *, int, va_list) = {valuefunc3var_custom_fake1,
valuefunc3var_custom_fake2,
valuefunc3var_custom_fake3};
CUSTOM_FFF_FUNCTION_TEMPLATE(int, custom_fakes[], const char *, int,
va_list) = {valuefunc3var_custom_fake1,
valuefunc3var_custom_fake2,
valuefunc3var_custom_fake3};
SET_CUSTOM_FAKE_SEQ(valuefunc3var, custom_fakes, 3);
int a = 1;
ASSERT_EQ(valuefunc3var("a", a, 2, 3, 4, 0), 10);
@@ -534,4 +542,3 @@ TEST_F(FFFTestSuite, value_func_can_capture_upto_20_arguments_correctly)
ASSERT_EQ(18, valuefunc20_fake.arg18_val);
ASSERT_EQ(19, valuefunc20_fake.arg19_val);
}