From 89ea0e10d8d0c79e3b8c062ad02927d8f8c063d0 Mon Sep 17 00:00:00 2001 From: Paulo Antonio Alvarez Date: Tue, 15 Aug 2017 23:36:49 -0300 Subject: [PATCH] Return values saved in history On some contexts, we need to call one function to free some resource allocated by another function based on the return value of the second function. For example, every time pthread_mutex_trylock suceeds, you need to unlock it, and only in those cases. While this could be done with the return value sequence, it does not really work for a sequence of custom fakes. Now we save the return values in the member return_val_history, which works pretty much like arg_history, only for the return values. --- fakegen.rb | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/fakegen.rb b/fakegen.rb index 3cfdbee..25a59d4 100644 --- a/fakegen.rb +++ b/fakegen.rb @@ -37,8 +37,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 @@ -88,12 +90,25 @@ def define_declare_all_func_common_helper putd " unsigned int arg_histories_dropped; \\" end +def define_declare_return_value_history + putd "" + putd "#define DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \\" + putd " RETURN_TYPE return_val_history[FFF_ARG_HISTORY_LEN];" +end + def define_save_arg_helper putd "" putd "#define SAVE_ARG(FUNCNAME, n) \\" 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_RET_HISTORY(FUNCNAME, RETVAL) \\" + putd " if ((FUNCNAME##_fake.call_count - 1) < FFF_ARG_HISTORY_LEN) \\" + putd " 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) \\" @@ -139,10 +154,13 @@ def define_return_fake_result_helper 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 " SAVE_RET_HISTORY(FUNCNAME, FUNCNAME##_fake.return_val_seq[FUNCNAME##_fake.return_val_seq_idx]) \\" putd " return FUNCNAME##_fake.return_val_seq[FUNCNAME##_fake.return_val_seq_idx++]; \\" putd " } \\" + putd " SAVE_RET_HISTORY(FUNCNAME, FUNCNAME##_fake.return_val_seq[FUNCNAME##_fake.return_val_seq_len-1]) \\" putd " return FUNCNAME##_fake.return_val_seq[FUNCNAME##_fake.return_val_seq_len-1]; /* return last element */ \\" putd " } \\" + putd " SAVE_RET_HISTORY(FUNCNAME, FUNCNAME##_fake.return_val) \\" putd " return FUNCNAME##_fake.return_val; \\" end @@ -261,6 +279,7 @@ def output_variables(arg_count, has_varargs, is_value_function) } putd "DECLARE_ALL_FUNC_COMMON \\" putd "DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \\" unless not is_value_function + putd "DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \\" unless not is_value_function putd "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) @@ -330,15 +349,22 @@ def output_function_body(arg_count, has_varargs, is_value_function) putd " #{custom_fake_call}\\" end putd " va_end(ap);\\" + putd " SAVE_RET_HISTORY(FUNCNAME, ret); \\" unless not is_value_function putd " return ret;\\" if is_value_function putd "}\\" 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 " RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](#{arg_list(arg_count)}); \\" unless not is_value_function + putd " SAVE_RET_HISTORY(FUNCNAME, ret); \\" unless not is_value_function + putd " return ret; \\" unless not is_value_function + putd " #{return_type}FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](#{arg_list(arg_count)}); \\" unless is_value_function putd " } \\" putd " else{ \\" + putd " 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 " SAVE_RET_HISTORY(FUNCNAME, ret); \\" unless not is_value_function + putd " return ret; \\" 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 " } \\" putd "} \\"