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:
40
fakegen.rb
40
fakegen.rb
@@ -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)}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user