Merge branch 'master' of kttd/3rd-party-lib-fff into kmaster

This commit was merged in pull request #1.
This commit is contained in:
stubbfel
2018-02-28 22:56:16 +01:00
committed by Gitea
5 changed files with 1686 additions and 1238 deletions

View File

@@ -221,7 +221,6 @@ TEST_F(FFFTestSuite, calls_in_correct_order)
They are reset by calling `FFF_RESET_HISTORY();`
## Default Argument History
The framework will by default store the arguments for the last ten calls made
@@ -371,6 +370,44 @@ The fake will call your custom functions in the order specified by the SET_CUSTO
macro. When the last custom fake is reached the fake will keep calling the last custom
fake in the sequence. This macro works much like the SET_RETURN_SEQ macro.
## Return value history
Say you have two functions f1 and f2. f2 must be called to release some resource
allocated by f1, but only in the cases where f1 returns zero. f1 could be
pthread_mutex_trylock and f2 could be pthread_mutex_unlock. <tt>fff</tt> will
save the history of returned values so this can be easily checked, even when
you use a sequence of custom fakes. Here's a simple example:
TEST_F(FFFTestSuite, return_value_sequence_saved_in_history)
{
long myReturnVals[3] = { 3, 7, 9 };
SET_RETURN_SEQ(longfunc0, myReturnVals, 3);
longfunc0();
longfunc0();
longfunc0();
ASSERT_EQ(myReturnVals[0], longfunc0_fake.return_val_history[0]);
ASSERT_EQ(myReturnVals[1], longfunc0_fake.return_val_history[1]);
ASSERT_EQ(myReturnVals[2], longfunc0_fake.return_val_history[2]);
}
You access the returned values in the <tt>return_val_history</tt> field.
## Variadic Functions
You can fake variadic functions using the macros <tt>FAKE_VALUE_FUNC_VARARG</tt>
and <tt>FAKE_VOID_FUNC_VARARG</tt>. For instance:
FAKE_VALUE_FUNC_VARARG(int, fprintf, FILE *, const char*, ...);
In order to access the variadic parameters from a custom fake function, declare a
<tt>va_list</tt> parameter. For instance, a custom fake for <tt>fprintf()</tt>
could call the real <tt>fprintf()</tt> like this:
int fprintf_custom(FILE *stream, const char *format, va_list ap) {
if (fprintf0_fake.return_val < 0) // should we fail?
return fprintf0_fake.return_val;
return vfprintf(stream, format, ap);
}
## How do I fake a function that returns a value by reference?
The basic mechanism that FFF provides you in this case is the custom_fake field described in the *Custom Return Value Delegate* example above.

View File

@@ -11,16 +11,20 @@ $MAX_CALL_HISTORY = 50
def include_dependencies
putd "#include <stdarg.h>"
putd "#include <string.h> /* For memset and memcpy */"
putd ""
puts
end
def output_constants
putd "#define FFF_MAX_ARGS (#{$MAX_ARGS}u)"
putd "#ifndef FFF_ARG_HISTORY_LEN"
putd " #define FFF_ARG_HISTORY_LEN (#{$DEFAULT_ARG_HISTORY}u)"
indent {
putd "#define FFF_ARG_HISTORY_LEN (#{$DEFAULT_ARG_HISTORY}u)"
}
putd "#endif"
putd "#ifndef FFF_CALL_HISTORY_LEN"
putd " #define FFF_CALL_HISTORY_LEN (#{$MAX_CALL_HISTORY}u)"
indent {
putd "#define FFF_CALL_HISTORY_LEN (#{$MAX_CALL_HISTORY}u)"
}
putd "#endif"
end
@@ -37,8 +41,10 @@ def output_internal_helper_macros
define_reset_fake_macro
define_declare_arg_helper
define_declare_all_func_common_helper
define_declare_return_value_history
define_save_arg_helper
define_room_for_more_history
define_save_ret_history_helper
define_save_arg_history_helper
define_history_dropped_helper
define_value_function_variables_helper
@@ -49,121 +55,181 @@ def output_internal_helper_macros
define_reset_fake_helper
putd "/* -- END INTERNAL HELPER MACROS -- */"
putd ""
puts
end
def define_return_sequence_helper
putd "#define SET_RETURN_SEQ(FUNCNAME, ARRAY_POINTER, ARRAY_LEN) \\"
putd " FUNCNAME##_fake.return_val_seq = ARRAY_POINTER; \\"
putd " FUNCNAME##_fake.return_val_seq_len = ARRAY_LEN;"
putd_backslash "#define SET_RETURN_SEQ(FUNCNAME, ARRAY_POINTER, ARRAY_LEN)"
indent {
putd_backslash "FUNCNAME##_fake.return_val_seq = ARRAY_POINTER;"
putd "FUNCNAME##_fake.return_val_seq_len = ARRAY_LEN;"
}
end
def define_custom_fake_sequence_helper
putd "#define SET_CUSTOM_FAKE_SEQ(FUNCNAME, ARRAY_POINTER, ARRAY_LEN) \\"
putd " FUNCNAME##_fake.custom_fake_seq = ARRAY_POINTER; \\"
putd " FUNCNAME##_fake.custom_fake_seq_len = ARRAY_LEN;"
putd_backslash "#define SET_CUSTOM_FAKE_SEQ(FUNCNAME, ARRAY_POINTER, ARRAY_LEN)"
indent {
putd_backslash "FUNCNAME##_fake.custom_fake_seq = ARRAY_POINTER;"
putd "FUNCNAME##_fake.custom_fake_seq_len = ARRAY_LEN;"
}
end
def define_reset_fake_macro
putd ""
puts
putd "/* Defining a function to reset a fake function */"
putd "#define RESET_FAKE(FUNCNAME) { \\"
putd " FUNCNAME##_reset(); \\"
putd "} \\"
putd ""
putd_backslash "#define RESET_FAKE(FUNCNAME) {"
indent {
putd_backslash "FUNCNAME##_reset();"
}
putd_backslash "}"
puts
end
def define_declare_arg_helper
putd ""
putd "#define DECLARE_ARG(type, n, FUNCNAME) \\"
putd " type arg##n##_val; \\"
putd " type arg##n##_history[FFF_ARG_HISTORY_LEN];"
puts
putd_backslash "#define DECLARE_ARG(type, n, FUNCNAME)"
indent {
putd_backslash "type arg##n##_val;"
putd "type arg##n##_history[FFF_ARG_HISTORY_LEN];"
}
end
def define_declare_all_func_common_helper
puts
putd_backslash "#define DECLARE_ALL_FUNC_COMMON"
indent {
putd_backslash "unsigned int call_count;"
putd_backslash "unsigned int arg_history_len;"
putd_backslash "unsigned int arg_histories_dropped;"
}
end
def define_declare_return_value_history
putd ""
putd "#define DECLARE_ALL_FUNC_COMMON \\"
putd " unsigned int call_count; \\"
putd " unsigned int arg_history_len;\\"
putd " unsigned int arg_histories_dropped; \\"
putd_backslash "#define DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE)"
indent {
putd "RETURN_TYPE return_val_history[FFF_ARG_HISTORY_LEN];"
}
end
def define_save_arg_helper
puts
putd_backslash "#define SAVE_ARG(FUNCNAME, n)"
indent {
putd "memcpy((void*)&FUNCNAME##_fake.arg##n##_val, (void*)&arg##n, sizeof(arg##n));"
}
end
def define_save_ret_history_helper
putd ""
putd "#define SAVE_ARG(FUNCNAME, n) \\"
putd " memcpy((void*)&FUNCNAME##_fake.arg##n##_val, (void*)&arg##n, sizeof(arg##n));"
putd_backslash "#define SAVE_RET_HISTORY(FUNCNAME, RETVAL)"
indent {
putd_backslash "if ((FUNCNAME##_fake.call_count - 1) < FFF_ARG_HISTORY_LEN)"
indent {
putd_backslash "memcpy((void *)&FUNCNAME##_fake.return_val_history[FUNCNAME##_fake.call_count - 1], (const void *) &RETVAL, sizeof(RETVAL));"
}
}
end
def define_room_for_more_history
putd ""
putd "#define ROOM_FOR_MORE_HISTORY(FUNCNAME) \\"
putd " FUNCNAME##_fake.call_count < FFF_ARG_HISTORY_LEN"
puts
putd_backslash "#define ROOM_FOR_MORE_HISTORY(FUNCNAME)"
indent {
putd "FUNCNAME##_fake.call_count < FFF_ARG_HISTORY_LEN"
}
end
def define_save_arg_history_helper
putd ""
putd "#define SAVE_ARG_HISTORY(FUNCNAME, ARGN) \\"
putd " memcpy((void*)&FUNCNAME##_fake.arg##ARGN##_history[FUNCNAME##_fake.call_count], (void*)&arg##ARGN, sizeof(arg##ARGN));"
puts
putd_backslash "#define SAVE_ARG_HISTORY(FUNCNAME, ARGN)"
indent {
putd "memcpy((void*)&FUNCNAME##_fake.arg##ARGN##_history[FUNCNAME##_fake.call_count], (void*)&arg##ARGN, sizeof(arg##ARGN));"
}
end
def define_history_dropped_helper
putd ""
putd "#define HISTORY_DROPPED(FUNCNAME) \\"
putd " FUNCNAME##_fake.arg_histories_dropped++"
puts
putd_backslash "#define HISTORY_DROPPED(FUNCNAME)"
indent {
putd "FUNCNAME##_fake.arg_histories_dropped++"
}
end
def define_value_function_variables_helper
putd ""
putd "#define DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \\"
putd " RETURN_TYPE return_val; \\"
putd " int return_val_seq_len; \\"
putd " int return_val_seq_idx; \\"
putd " RETURN_TYPE * return_val_seq; \\"
puts
putd_backslash "#define DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE)"
indent {
putd_backslash "RETURN_TYPE return_val;"
putd_backslash "int return_val_seq_len;"
putd_backslash "int return_val_seq_idx;"
putd_backslash "RETURN_TYPE * return_val_seq;"
}
end
def define_custom_fake_seq_variables_helper
putd ""
putd "#define DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \\"
putd " int custom_fake_seq_len; \\"
putd " int custom_fake_seq_idx; \\"
puts
putd_backslash "#define DECLARE_CUSTOM_FAKE_SEQ_VARIABLES"
indent {
putd_backslash "int custom_fake_seq_len;"
putd_backslash "int custom_fake_seq_idx;"
}
end
def define_increment_call_count_helper
putd ""
putd "#define INCREMENT_CALL_COUNT(FUNCNAME) \\"
putd " FUNCNAME##_fake.call_count++"
puts
putd_backslash "#define INCREMENT_CALL_COUNT(FUNCNAME)"
indent {
putd "FUNCNAME##_fake.call_count++"
}
end
def define_return_fake_result_helper
putd ""
putd "#define RETURN_FAKE_RESULT(FUNCNAME) \\"
putd " if (FUNCNAME##_fake.return_val_seq_len){ /* then its a sequence */ \\"
putd " if(FUNCNAME##_fake.return_val_seq_idx < FUNCNAME##_fake.return_val_seq_len) { \\"
putd " return FUNCNAME##_fake.return_val_seq[FUNCNAME##_fake.return_val_seq_idx++]; \\"
putd " } \\"
putd " return FUNCNAME##_fake.return_val_seq[FUNCNAME##_fake.return_val_seq_len-1]; /* return last element */ \\"
putd " } \\"
putd " return FUNCNAME##_fake.return_val; \\"
puts
putd_backslash "#define RETURN_FAKE_RESULT(FUNCNAME)"
indent {
putd_backslash "if (FUNCNAME##_fake.return_val_seq_len){ /* then its a sequence */"
indent {
putd_backslash "if(FUNCNAME##_fake.return_val_seq_idx < FUNCNAME##_fake.return_val_seq_len) {"
indent {
putd_backslash "SAVE_RET_HISTORY(FUNCNAME, FUNCNAME##_fake.return_val_seq[FUNCNAME##_fake.return_val_seq_idx])"
putd_backslash "return FUNCNAME##_fake.return_val_seq[FUNCNAME##_fake.return_val_seq_idx++];"
}
putd_backslash "}"
putd_backslash "SAVE_RET_HISTORY(FUNCNAME, FUNCNAME##_fake.return_val_seq[FUNCNAME##_fake.return_val_seq_len-1])"
putd_backslash "return FUNCNAME##_fake.return_val_seq[FUNCNAME##_fake.return_val_seq_len-1]; /* return last element */"
}
putd_backslash "}"
putd_backslash "SAVE_RET_HISTORY(FUNCNAME, FUNCNAME##_fake.return_val)"
putd_backslash "return FUNCNAME##_fake.return_val;"
}
end
def define_extern_c_helper
putd ""
puts
putd "#ifdef __cplusplus"
putd " #define FFF_EXTERN_C extern \"C\"{"
putd " #define FFF_END_EXTERN_C } "
indent {
putd "#define FFF_EXTERN_C extern \"C\"{"
putd "#define FFF_END_EXTERN_C } "
}
putd "#else /* ansi c */"
putd " #define FFF_EXTERN_C "
putd " #define FFF_END_EXTERN_C "
indent {
putd "#define FFF_EXTERN_C "
putd "#define FFF_END_EXTERN_C "
}
putd "#endif /* cpp/ansi c */"
end
def define_reset_fake_helper
putd ""
putd "#define DEFINE_RESET_FUNCTION(FUNCNAME) \\"
putd " void FUNCNAME##_reset(void){ \\"
putd " memset(&FUNCNAME##_fake, 0, sizeof(FUNCNAME##_fake)); \\"
putd " FUNCNAME##_fake.arg_history_len = FFF_ARG_HISTORY_LEN;\\"
putd " }"
puts
putd_backslash "#define DEFINE_RESET_FUNCTION(FUNCNAME)"
indent {
putd_backslash "void FUNCNAME##_reset(void){"
indent {
putd_backslash "memset(&FUNCNAME##_fake, 0, sizeof(FUNCNAME##_fake));"
putd_backslash "FUNCNAME##_fake.arg_history_len = FFF_ARG_HISTORY_LEN;"
}
putd "}"
}
end
# ------ End Helper macros ------ #
@@ -174,6 +240,11 @@ def putd(str)
puts str
end
#multiline putd which adds a \ at the end of the generated macro
def putd_backslash str
putd(str + " \\")
end
def pushd
$current_depth = $current_depth + 4
end
@@ -182,6 +253,12 @@ def popd
$current_depth = $current_depth - 4
end
def indent
pushd
yield
popd
end
def output_macro(arg_count, has_varargs, is_value_function)
vararg_name = has_varargs ? "_VARARG" : ""
@@ -191,36 +268,36 @@ def output_macro(arg_count, has_varargs, is_value_function)
saved_arg_count = arg_count - (has_varargs ? 1 : 0)
return_type = is_value_function ? "RETURN_TYPE" : ""
putd ""
puts
output_macro_header(declare_macro_name, saved_arg_count, has_varargs, return_type)
pushd
indent {
extern_c { # define argument capture variables
output_variables(saved_arg_count, has_varargs, is_value_function)
}
popd
putd ""
}
puts
output_macro_header(define_macro_name, saved_arg_count, has_varargs, return_type)
pushd
indent {
extern_c {
putd "FUNCNAME##_Fake FUNCNAME##_fake;\\"
putd function_signature(saved_arg_count, has_varargs, is_value_function) + "{ \\"
pushd
putd_backslash "FUNCNAME##_Fake FUNCNAME##_fake;"
putd_backslash function_signature(saved_arg_count, has_varargs, is_value_function) + "{"
indent {
output_function_body(saved_arg_count, has_varargs, is_value_function)
popd
putd "} \\"
putd "DEFINE_RESET_FUNCTION(FUNCNAME) \\"
}
putd_backslash "}"
putd_backslash "DEFINE_RESET_FUNCTION(FUNCNAME)"
}
popd
putd ""
}
puts
output_macro_header(fake_macro_name, saved_arg_count, has_varargs, return_type)
pushd
indent {
putd macro_signature_for(declare_macro_name, saved_arg_count, has_varargs, return_type)
putd macro_signature_for(define_macro_name, saved_arg_count, has_varargs, return_type)
putd ""
popd
puts
}
end
def output_macro_header(macro_name, arg_count, has_varargs, return_type)
@@ -232,7 +309,7 @@ def output_macro_name(macro_name, arg_count, has_varargs, return_type)
putd "#define " + macro_signature_for(macro_name, arg_count, has_varargs, return_type)
end
# #macro_name(RETURN_TYPE, FUNCNAME, ARG0,...)
# #macro_name(RETURN_TYPE, FUNCNAME, ARG0,...) \
def macro_signature_for(macro_name, arg_count, has_varargs, return_type)
parameter_list = "#{macro_name}("
if return_type != ""
@@ -250,23 +327,21 @@ def macro_signature_for(macro_name, arg_count, has_varargs, return_type)
parameter_list
end
def output_argument_capture_variables(argN)
putd " DECLARE_ARG(ARG#{argN}_TYPE, #{argN}, FUNCNAME) \\"
end
def output_variables(arg_count, has_varargs, is_value_function)
in_struct{
arg_count.times { |argN|
putd "DECLARE_ARG(ARG#{argN}_TYPE, #{argN}, FUNCNAME) \\"
arg_count.times { |argN|
putd_backslash "DECLARE_ARG(ARG#{argN}_TYPE, #{argN}, FUNCNAME)"
}
putd "DECLARE_ALL_FUNC_COMMON \\"
putd "DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \\" unless not is_value_function
putd "DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \\"
putd_backslash "DECLARE_ALL_FUNC_COMMON"
putd_backslash "DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE)" unless not is_value_function
putd_backslash "DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE)" unless not is_value_function
putd_backslash "DECLARE_CUSTOM_FAKE_SEQ_VARIABLES"
output_custom_function_signature(arg_count, has_varargs, is_value_function)
output_custom_function_array(arg_count, has_varargs, is_value_function)
}
putd "extern FUNCNAME##_Fake FUNCNAME##_fake;\\"
putd "void FUNCNAME##_reset(void); \\"
putd_backslash "extern FUNCNAME##_Fake FUNCNAME##_fake;"
putd_backslash "void FUNCNAME##_reset(void);"
putd_backslash function_signature(arg_count, has_varargs, is_value_function) + ";"
end
#example: ARG0_TYPE arg0, ARG1_TYPE arg1
@@ -289,15 +364,15 @@ end
def output_custom_function_signature(arg_count, has_varargs, is_value_function)
return_type = is_value_function ? "RETURN_TYPE" : "void"
ap_list = has_varargs ? ", va_list ap" : ""
signature = "(*custom_fake)(#{arg_val_list(arg_count)}#{ap_list}); \\"
putd return_type + signature
signature = "(*custom_fake)(#{arg_val_list(arg_count)}#{ap_list});"
putd_backslash return_type + signature
end
def output_custom_function_array(arg_count, has_varargs, is_value_function)
return_type = is_value_function ? "RETURN_TYPE" : "void"
ap_list = has_varargs ? ", va_list ap" : ""
custom_array = "(**custom_fake_seq)(#{arg_val_list(arg_count)}#{ap_list}); \\"
putd return_type + custom_array
custom_array = "(**custom_fake_seq)(#{arg_val_list(arg_count)}#{ap_list});"
putd_backslash return_type + custom_array
end
# example: RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1)
@@ -308,100 +383,124 @@ def function_signature(arg_count, has_varargs, is_value_function)
end
def output_function_body(arg_count, has_varargs, is_value_function)
arg_count.times { |i| putd "SAVE_ARG(FUNCNAME, #{i}); \\" }
putd "if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){\\"
arg_count.times { |i| putd " SAVE_ARG_HISTORY(FUNCNAME, #{i}); \\" }
putd "}\\"
putd "else{\\"
putd " HISTORY_DROPPED(FUNCNAME);\\"
putd "}\\"
putd "INCREMENT_CALL_COUNT(FUNCNAME); \\"
putd "REGISTER_CALL(FUNCNAME); \\"
arg_count.times { |i| putd_backslash "SAVE_ARG(FUNCNAME, #{i});" }
putd_backslash "if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){"
indent {
arg_count.times { |i| putd_backslash "SAVE_ARG_HISTORY(FUNCNAME, #{i});" }
}
putd_backslash "}"
putd_backslash "else{"
indent {
putd_backslash "HISTORY_DROPPED(FUNCNAME);"
}
putd_backslash "}"
putd_backslash "INCREMENT_CALL_COUNT(FUNCNAME);"
putd_backslash "REGISTER_CALL(FUNCNAME);"
if has_varargs
putd "if(FUNCNAME##_fake.custom_fake){\\"
putd " RETURN_TYPE ret;\\" if is_value_function
putd " va_list ap;\\"
putd " va_start(ap, arg#{arg_count-1});\\"
putd_backslash "if(FUNCNAME##_fake.custom_fake){"
indent {
putd_backslash "RETURN_TYPE ret;" if is_value_function
putd_backslash "va_list ap;"
putd_backslash "va_start(ap, arg#{arg_count-1});"
}
custom_fake_call = "FUNCNAME##_fake.custom_fake(#{arg_list(arg_count)}, ap);"
if is_value_function
putd " ret = #{custom_fake_call}\\"
else
putd " #{custom_fake_call}\\"
end
putd " va_end(ap);\\"
putd " return ret;\\" if is_value_function
putd "}\\"
indent {
if is_value_function
putd_backslash "ret = #{custom_fake_call}"
else
putd_backslash "#{custom_fake_call}"
end
putd_backslash "va_end(ap);"
putd_backslash "SAVE_RET_HISTORY(FUNCNAME, ret);" unless not is_value_function
putd_backslash "return ret;" if is_value_function
}
putd_backslash "}"
else
return_type = is_value_function ? "return " : ""
putd "if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \\"
putd " if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \\"
putd " #{return_type}FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](#{arg_list(arg_count)}); \\"
putd " } \\"
putd " else{ \\"
putd " #{return_type}FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](#{arg_list(arg_count)}); \\"
putd " } \\"
putd "} \\"
putd "if (FUNCNAME##_fake.custom_fake) #{return_type}FUNCNAME##_fake.custom_fake(#{arg_list(arg_count)}); \\"
putd_backslash "if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */"
indent {
putd_backslash "if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){"
indent {
putd_backslash "RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](#{arg_list(arg_count)});" unless not is_value_function
putd_backslash "SAVE_RET_HISTORY(FUNCNAME, ret);" unless not is_value_function
putd_backslash "return ret;" unless not is_value_function
putd_backslash "#{return_type}FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](#{arg_list(arg_count)});" unless is_value_function
}
putd_backslash "}"
putd_backslash "else{"
indent {
putd_backslash "RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](#{arg_list(arg_count)});" unless not is_value_function
putd_backslash "SAVE_RET_HISTORY(FUNCNAME, ret);" unless not is_value_function
putd_backslash "return ret;" unless not is_value_function
putd_backslash "#{return_type}FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](#{arg_list(arg_count)});"
}
putd_backslash "}"
}
putd_backslash "}"
putd_backslash "if (FUNCNAME##_fake.custom_fake) #{return_type}FUNCNAME##_fake.custom_fake(#{arg_list(arg_count)});"
end
putd "RETURN_FAKE_RESULT(FUNCNAME) \\" if is_value_function
end
def output_reset_function(arg_count, is_value_function)
putd "void FUNCNAME##_reset(void){ \\"
putd " memset(&FUNCNAME##_fake, 0, sizeof(FUNCNAME##_fake)); \\"
putd " FUNCNAME##_fake.arg_history_len = FFF_ARG_HISTORY_LEN;\\"
putd "} \\"
putd_backslash "RETURN_FAKE_RESULT(FUNCNAME)" if is_value_function
end
def define_fff_globals
putd "typedef void (*fff_function_t)(void);"
putd "typedef struct { "
putd " fff_function_t call_history[FFF_CALL_HISTORY_LEN];"
putd " unsigned int call_history_idx;"
indent {
putd "fff_function_t call_history[FFF_CALL_HISTORY_LEN];"
putd "unsigned int call_history_idx;"
}
putd "} fff_globals_t;"
putd ""
putd "FFF_EXTERN_C \\"
puts
putd_backslash "FFF_EXTERN_C"
putd "extern fff_globals_t fff;"
putd "FFF_END_EXTERN_C \\"
putd ""
putd "#define DEFINE_FFF_GLOBALS \\"
putd " FFF_EXTERN_C \\"
putd " fff_globals_t fff; \\"
putd " FFF_END_EXTERN_C"
putd ""
putd_backslash "FFF_END_EXTERN_C"
puts
putd_backslash "#define DEFINE_FFF_GLOBALS"
indent {
putd_backslash "FFF_EXTERN_C"
indent {
putd_backslash "fff_globals_t fff;"
}
putd "FFF_END_EXTERN_C"
}
puts
putd "#define FFF_RESET_HISTORY() fff.call_history_idx = 0;"
putd ""
putd "#define REGISTER_CALL(function) \\"
putd " if(fff.call_history_idx < FFF_CALL_HISTORY_LEN) \\"
putd " fff.call_history[fff.call_history_idx++] = (fff_function_t)function;"
puts
putd_backslash "#define REGISTER_CALL(function)"
indent {
putd_backslash "if(fff.call_history_idx < FFF_CALL_HISTORY_LEN)"
indent {
putd "fff.call_history[fff.call_history_idx++] = (fff_function_t)function;"
}
}
end
def extern_c
putd "FFF_EXTERN_C \\"
pushd
putd_backslash "FFF_EXTERN_C"
indent {
yield
popd
putd "FFF_END_EXTERN_C \\"
}
putd_backslash "FFF_END_EXTERN_C"
end
def in_struct
putd "typedef struct FUNCNAME##_Fake { \\"
pushd
yield
popd
putd "} FUNCNAME##_Fake;\\"
putd_backslash "typedef struct FUNCNAME##_Fake {"
indent {
yield
}
putd_backslash "} FUNCNAME##_Fake;"
end
def include_guard
putd "#ifndef FAKE_FUNCTIONS"
putd "#define FAKE_FUNCTIONS"
putd ""
puts
yield
putd ""
puts
putd "#endif /* FAKE_FUNCTIONS */"
end

2376
fff.h

File diff suppressed because it is too large Load Diff

View File

@@ -7,15 +7,6 @@
//// Imaginary production code header file ///
void voidfunc1(int);
void voidfunc2(char, char);
void voidfunc1outparam(char *);
long longfunc0();
void voidfunc3var(const char *fmt, int argc, ...);
int valuefunc3var(const char *fmt, int argc, ...);
void voidfunc20(int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int);
int valuefunc20(int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int);
enum MYBOOL { FALSE = 899, TRUE };
struct MyStruct {
int x;
@@ -37,7 +28,6 @@ DECLARE_FAKE_VOID_FUNC(voidfunc20, int, int, int, int, int, int, int, int, int,
DECLARE_FAKE_VALUE_FUNC(int, valuefunc20, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int);
#ifndef __cplusplus
int strlcpy3(char* const, const char* const, const size_t);
DECLARE_FAKE_VALUE_FUNC(int, strlcpy3, char* const, const char* const, const size_t);
#endif /* __cplusplus */
#endif /* GLOBAL_FAKES_H_ */

View File

@@ -257,6 +257,64 @@ TEST_F(FFFTestSuite, custom_fake_sequence_not_exausthed)
ASSERT_EQ('z', a);
}
TEST_F(FFFTestSuite, return_value_sequence_saved_in_history)
{
long myReturnVals[3] = { 3, 7, 9 };
SET_RETURN_SEQ(longfunc0, myReturnVals, 3);
longfunc0();
longfunc0();
longfunc0();
ASSERT_EQ(myReturnVals[0], longfunc0_fake.return_val_history[0]);
ASSERT_EQ(myReturnVals[1], longfunc0_fake.return_val_history[1]);
ASSERT_EQ(myReturnVals[2], longfunc0_fake.return_val_history[2]);
}
TEST_F(FFFTestSuite, return_value_saved_in_history)
{
long i;
for (i = 0; i < FFF_ARG_HISTORY_LEN; i++)
{
longfunc0_fake.return_val = i + 1;
longfunc0();
}
for (i = 0; i < FFF_ARG_HISTORY_LEN; i++)
{
ASSERT_EQ(longfunc0_fake.return_val_history[i], i + 1);
}
}
long custom_longfunc1()
{
return 42;
}
long custom_longfunc2()
{
return 15;
}
long custom_longfunc3()
{
return 7;
}
TEST_F(FFFTestSuite, custom_fake_seq_return_values_saved_in_history)
{
long (*custom_fakes[])(void) = {custom_longfunc1,
custom_longfunc2,
custom_longfunc3};
SET_CUSTOM_FAKE_SEQ(longfunc0, custom_fakes, 3);
longfunc0();
longfunc0();
longfunc0();
ASSERT_EQ(42, longfunc0_fake.return_val_history[0]);
ASSERT_EQ(15, longfunc0_fake.return_val_history[1]);
ASSERT_EQ(7, longfunc0_fake.return_val_history[2]);
}
TEST_F(FFFTestSuite, custom_fake_sequence_exhausted)
{
void (*custom_fakes[])(char *) = {voidfunc1outparam_custom_fake1,
@@ -299,6 +357,11 @@ TEST_F(FFFTestSuite, use_void_vararg_fake_with_different_number_of_arguments)
voidfunc3var("1 parameter", 1, 10);
voidfunc3var("2 parameters", 2, 10, 20);
voidfunc3var("3 parameters", 3, 10, 20, 30);
ASSERT_EQ(voidfunc3var_fake.call_count, 4);
char msg[] = "3 parameters";
ASSERT_EQ(strcmp(voidfunc3var_fake.arg0_val, msg), 0);
ASSERT_EQ(3, voidfunc3var_fake.arg1_val);
}
TEST_F(FFFTestSuite, use_value_vararg_fake_with_different_number_of_arguments)
@@ -307,6 +370,11 @@ TEST_F(FFFTestSuite, use_value_vararg_fake_with_different_number_of_arguments)
valuefunc3var("1 parameter", 1, 10);
valuefunc3var("2 parameters", 2, 10, 20);
valuefunc3var("3 parameters", 3, 10, 20, 30);
ASSERT_EQ(valuefunc3var_fake.call_count, 4);
char msg[] = "3 parameters";
ASSERT_EQ(strcmp(valuefunc3var_fake.arg0_val, msg), 0);
ASSERT_EQ(3, valuefunc3var_fake.arg1_val);
}
#endif /* __cplusplus */