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

View File

@@ -257,6 +257,64 @@ TEST_F(FFFTestSuite, custom_fake_sequence_not_exausthed)
ASSERT_EQ('z', a); 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) TEST_F(FFFTestSuite, custom_fake_sequence_exhausted)
{ {
void (*custom_fakes[])(char *) = {voidfunc1outparam_custom_fake1, 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("1 parameter", 1, 10);
voidfunc3var("2 parameters", 2, 10, 20); voidfunc3var("2 parameters", 2, 10, 20);
voidfunc3var("3 parameters", 3, 10, 20, 30); 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) 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("1 parameter", 1, 10);
valuefunc3var("2 parameters", 2, 10, 20); valuefunc3var("2 parameters", 2, 10, 20);
valuefunc3var("3 parameters", 3, 10, 20, 30); 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 */ #endif /* __cplusplus */