forked from 3rd-party/fff
Merge remote-tracking branch 'original/master' into refactorings
This commit is contained in:
39
README.md
39
README.md
@@ -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.
|
||||||
|
|
||||||
|
|||||||
35
fakegen.rb
35
fakegen.rb
@@ -41,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
|
||||||
@@ -102,6 +104,14 @@ def define_declare_all_func_common_helper
|
|||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def define_declare_return_value_history
|
||||||
|
putd ""
|
||||||
|
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
|
def define_save_arg_helper
|
||||||
puts
|
puts
|
||||||
putd_backslash "#define SAVE_ARG(FUNCNAME, n)"
|
putd_backslash "#define SAVE_ARG(FUNCNAME, n)"
|
||||||
@@ -110,6 +120,17 @@ def define_save_arg_helper
|
|||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def define_save_ret_history_helper
|
||||||
|
putd ""
|
||||||
|
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
|
def define_room_for_more_history
|
||||||
puts
|
puts
|
||||||
putd_backslash "#define ROOM_FOR_MORE_HISTORY(FUNCNAME)"
|
putd_backslash "#define ROOM_FOR_MORE_HISTORY(FUNCNAME)"
|
||||||
@@ -170,12 +191,15 @@ def define_return_fake_result_helper
|
|||||||
indent {
|
indent {
|
||||||
putd_backslash "if(FUNCNAME##_fake.return_val_seq_idx < FUNCNAME##_fake.return_val_seq_len) {"
|
putd_backslash "if(FUNCNAME##_fake.return_val_seq_idx < FUNCNAME##_fake.return_val_seq_len) {"
|
||||||
indent {
|
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 "return FUNCNAME##_fake.return_val_seq[FUNCNAME##_fake.return_val_seq_idx++];"
|
||||||
}
|
}
|
||||||
putd_backslash "}"
|
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 "return FUNCNAME##_fake.return_val_seq[FUNCNAME##_fake.return_val_seq_len-1]; /* return last element */"
|
||||||
}
|
}
|
||||||
putd_backslash "}"
|
putd_backslash "}"
|
||||||
|
putd_backslash "SAVE_RET_HISTORY(FUNCNAME, FUNCNAME##_fake.return_val)"
|
||||||
putd_backslash "return FUNCNAME##_fake.return_val;"
|
putd_backslash "return FUNCNAME##_fake.return_val;"
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
@@ -310,12 +334,14 @@ def output_variables(arg_count, has_varargs, is_value_function)
|
|||||||
}
|
}
|
||||||
putd_backslash "DECLARE_ALL_FUNC_COMMON"
|
putd_backslash "DECLARE_ALL_FUNC_COMMON"
|
||||||
putd_backslash "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_backslash "DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE)" unless not is_value_function
|
||||||
putd_backslash "DECLARE_CUSTOM_FAKE_SEQ_VARIABLES"
|
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_backslash "extern FUNCNAME##_Fake FUNCNAME##_fake;"
|
putd_backslash "extern FUNCNAME##_Fake FUNCNAME##_fake;"
|
||||||
putd_backslash "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
|
||||||
@@ -386,6 +412,7 @@ def output_function_body(arg_count, has_varargs, is_value_function)
|
|||||||
putd_backslash "#{custom_fake_call}"
|
putd_backslash "#{custom_fake_call}"
|
||||||
end
|
end
|
||||||
putd_backslash "va_end(ap);"
|
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 "return ret;" if is_value_function
|
||||||
}
|
}
|
||||||
putd_backslash "}"
|
putd_backslash "}"
|
||||||
@@ -395,11 +422,17 @@ def output_function_body(arg_count, has_varargs, is_value_function)
|
|||||||
indent {
|
indent {
|
||||||
putd_backslash "if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){"
|
putd_backslash "if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){"
|
||||||
indent {
|
indent {
|
||||||
putd_backslash "#{return_type}FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](#{arg_list(arg_count)});"
|
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 "}"
|
||||||
putd_backslash "else{"
|
putd_backslash "else{"
|
||||||
indent {
|
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 "#{return_type}FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](#{arg_list(arg_count)});"
|
||||||
}
|
}
|
||||||
putd_backslash "}"
|
putd_backslash "}"
|
||||||
|
|||||||
@@ -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_ */
|
||||||
|
|||||||
@@ -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 */
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user