From 0f3ca699dc5eb8146c8b583759a0f24e67476ced Mon Sep 17 00:00:00 2001 From: fanasina Date: Tue, 24 Mar 2026 11:47:42 +0100 Subject: [PATCH] add : copy fmock --- test.c | 105 ++++++++ y_test_h.h | 736 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 841 insertions(+) diff --git a/test.c b/test.c index 1496acf..2bb6fde 100644 --- a/test.c +++ b/test.c @@ -96,6 +96,111 @@ TEST(lessThan){ EXPECT_LT_TYPE_DOUBLE(db,da); } +IMPLEMENTATION_FMOCK() + +MOCK_FUNC(int, f_mock, (), ()) + + + + + + +EXPECT_MOCK_CALL(int,f_mock, (),false, 2) { + EXPECT_EQ_IN_MOCKF(21,21,f_mock); + EXPECT_EQ(1,3); + EXPECT_EQ(4,4); + EXPECT_EQ_IN_MOCKF(23,24,f_mock); return 12;} +EXPECT_MOCK_CALL(int,f_mock, (),1, 1) { EXPECT_EQ_IN_MOCKF(23,21,f_mock);return 10;} + +EXPECT_MOCK_CALL(int,f_mock, (),1==2||2<1, 1) {return 18;} +EXPECT_MOCK_CALL(int,f_mock, (),1, ININITY_REPS) {return -18;} + + +TEST(mockf1){ + INIT_CALLER_MOCK(f_mock); + + for(int i = 0; i<8; ++i){ + + LOG("call f_mock:%d: ret:%d\n",i,f_mock()); + // int val=f_mock(); + //PRINTF("call f_mock:%d: ret:%d\n",i,val); + } + +} + + +// // + +MOCK_FUNC(int, f2_mock,(int a,int b),(a,b)) + +STR_PRINT_CUR_VAR(f2_mock, (int a,int b),(a,b)){ + char *ret=malloc(150); + //char ret[150]; + sprintf(ret,"(int)a: %d, (int)b: %d",a,b); + return ret; +} + + +EXPECT_MOCK_CALL(int, f2_mock, (int a,int b), (a call f2_mock:%d: %d\n",0,f2_mock(1,4)); + + + for(int i=0; i<8; ++i){ + + if(i<2) { + //int val = f2_mock(i,4); + //LOG("call f2_mock:%d: %d\n",i,val); + LOG("call f2_mock:%d: %d\n",i,f2_mock(i,4)); + + } + else if(i<4) LOG("call:%d: %d\n",i,f2_mock(i,3)); + else LOG("call:%d:%d\n",i,f2_mock(i,i*i)); + } + +} int main(int argc, char **argv){ diff --git a/y_test_h.h b/y_test_h.h index 94d1688..bcf498b 100644 --- a/y_test_h.h +++ b/y_test_h.h @@ -1654,6 +1654,318 @@ do{ #endif /* __TEST_ARRAY_C_H__ */ +#ifndef __MOCK_C_H__ +#define __MOCK_C_H__ + +//#include "ftest/ftest.h" +//#include "tools_t/tools_t.h" + +#define ININITY_REPS -8 +#define INITSTATE -1 +#define DONOTHING 0 + +#define PRE_ID ___line_ +/* + * list of each variable called + * use str_print_current_variables attibute function pointer to record variable + * so if STR_PRINT_CUR_VAR is not defined, this list is empty! + */ +struct list_current_variable{ + char *str_current_variables; + struct list_current_variable *next; +}; + +/* + * list to store info abou mock function + */ +struct func_mock_info_struct{ + long id; + bool used; + char *str_namefunc; + char *str_conditions; + char *str_caller; + //char *str_current_variables; + struct list_current_variable *l_current_var; + int expect_call;/* 1 if EXPECT_MOCK_CALL and 0 if WILL_MOCK_CALL */ + long call;/* increment when call (try to executed) and 0 if not : init value */ + long failed_call;/* increment when condition not fill and 0 if not : init value */ + long init_times_left;/* DONOTHING do nothing (pass to -> next), ININITY_REPS every time; INITSTATE init; > 0 execute and decrement */ + long times_left;/* DONOTHING do nothing (pass to -> next), ININITY_REPS every time; INITSTATE init; > 0 execute and decrement */ + struct func_mock_info_struct *next; +}; + +/* + * to list all mock responses of all mock functions in one list + */ +struct list_base_fmock{ + struct func_mock_info_struct *info_mock; + struct list_base_fmock *next; +}; + + + +int parse_count_args_(char *input); +void append_fmock_to_listmock(struct func_mock_info_struct **f_mock_list, struct func_mock_info_struct *f_mock); +void append_list_base_fmock(struct list_base_fmock **l_fmock, struct func_mock_info_struct *f_mock); +void append_variable_current(struct list_current_variable **lcurrent_var, char *current_var); + +void clear_fmock_info_list(struct func_mock_info_struct **f_mock_list); +void clear_list_base_fmock(struct list_base_fmock **l_fmock); +void clear_variable_current(struct list_current_variable **lcurrent_var); + +// if input == functioname___line_NBLINE return functioname, else it return the input +//char* extract_name_func_mock(char *input); + +extern struct func_mock_info_struct *f_mock_glist; +extern struct list_base_fmock *g_list_base_fmock; + +#if 0 + int expect_call; /* 1 if EXPECT_MOCK_CALL and 0 if WILL_MOCK_CALL */\ + long init_times_left; /* DONOTHING do nothing (pass to -> next), ININITY_REPS every time; INITSTATE init; > 0 execute and decrement */\ + long times_left; /* DONOTHING do nothing (pass to -> next), ININITY_REPS every time; INITSTATE init; > 0 execute and decrement */\ + +#endif + +#define INIT_MOCK_INFO_IF_NO__(tmp__mock, namefunction, pre_id, id) \ + (tmp__mock)->run = NULL;\ + (tmp__mock)->call_mock_condition = NULL;\ + /*(tmp__mock)->str_print_current_variables = list_mo_ ## namefunction .str_print_current_variables;*/\ + ((tmp__mock)->info_mock)->expect_call = -1;\ + ((tmp__mock)->info_mock)->used = true;\ + ((tmp__mock)->info_mock)->call = 0;\ + ((tmp__mock)->info_mock)->failed_call = 0;\ + ((tmp__mock)->info_mock)->str_namefunc = malloc(strlen(#namefunction) + 43 + strlen(#pre_id));\ + sprintf(((tmp__mock)->info_mock)->str_namefunc,"%s%s%d",#namefunction,#pre_id,id);\ + ((tmp__mock)->info_mock)->str_conditions = NULL;\ + ((tmp__mock)->info_mock)->str_caller = NULL;\ + ((tmp__mock)->info_mock)->l_current_var= NULL;\ + ((tmp__mock)->info_mock)->next = NULL;\ + /*(tmp__mock)->next = NULL;*/\ + append_fmock_to_listmock(&f_mock_glist, (tmp__mock)->info_mock);\ + append_list_base_fmock( &g_list_base_fmock ,(tmp__mock)->info_mock); + +#define INIT_MOCK_INFO_IF_NO_(tmp_new_mock, namefunction, pre_id) \ + INIT_MOCK_INFO_IF_NO__(tmp_new_mock, namefunction, pre_id, __LINE__) \ + +#define MOCK_FUNC(returntype, namefunction, args_prototype_with_parenthesis, args_call_with_parenthesis)\ + /*typedef returntype FUNC_type_ ## namefunction args_prototype_with_parenthesis ;*/\ + /*typedef args_prototype_with_parenthesis args_ ## namefunction;*/\ + struct list_mock_return_ ## namefunction{\ + returntype (*run) args_prototype_with_parenthesis;\ + int (*call_mock_condition) args_prototype_with_parenthesis ;/* to store condition */\ + char* (*str_print_current_variables) args_prototype_with_parenthesis ;/* to store current variables CREATE by macro STR_PRINT_CUR_VAR same arguments as MOCK_FUNC without returntype whoch is always char * */\ + struct func_mock_info_struct *info_mock;\ + struct list_mock_return_ ## namefunction *next;\ + } list_mo_ ## namefunction;\ + __attribute__((constructor)) void init_list_m_ ## namefunction(void){\ + list_mo_ ## namefunction.info_mock = malloc(sizeof(struct func_mock_info_struct));\ + (list_mo_ ## namefunction.info_mock)->used = false;\ + (list_mo_ ## namefunction.info_mock)->times_left = INITSTATE;\ + (list_mo_ ## namefunction.info_mock)->init_times_left = INITSTATE;\ + list_mo_ ## namefunction.str_print_current_variables = NULL;\ + list_mo_ ## namefunction.next = NULL;\ + }\ + \ + __attribute__((destructor)) void destruct_list_m_ ## namefunction(void){ \ + /*free(list_mo_ ## namefunction.info_mock);*/ \ + struct list_mock_return_ ## namefunction *tmp_nn = list_mo_ ## namefunction.next, *ttmp_nn;\ + if((list_mo_ ## namefunction.info_mock)->used == false ){\ + free(list_mo_ ## namefunction.info_mock);\ + }\ + while(tmp_nn){\ + ttmp_nn = tmp_nn;\ + tmp_nn = tmp_nn->next;\ + /*free(ttmp_nn->info_mock);*/\ + free(ttmp_nn);\ + }\ + PRINT_DEBUG(" purge list mo_ %s done!\n",#namefunction);\ + \ + }\ + \ + returntype namefunction args_prototype_with_parenthesis {\ + static size_t count_call_f=0;\ + ++count_call_f;\ + PRINT_DEBUG(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>count call of %s: %ld\n",#namefunction,count_call_f);\ + struct list_mock_return_ ## namefunction *tmp_mock = &list_mo_ ## namefunction;\ + if( (tmp_mock->info_mock)->times_left == INITSTATE ){\ + PRINT_HK_C(colors_f[k_YELLOW],tab_hk_f[hk_TR]," WARNING, %s, no EXPECT_MOCK_CALL or WILL_MOCK_CALL, but called %ld times.\n",#namefunction, count_call_f);\ + if(count_call_f==1){\ + PRINT_HK_C(colors_f[k_YELLOW],tab_hk_f[hk_TR]," For instance:\n"\ + "%s EXPECT_MOCK_CALL(%s,%s,%s,true,1){\n"\ + "%s\t %s ret;\n%s \t ...do something with %s;\n"\ + "%s\t return ret;\n"\ + "%s }\n"\ + "%s if call once and accept all args, the same args with WILL_MOCK_CALL \n\n",\ + tab_hk_f[hk_TR], #returntype, #namefunction,#args_prototype_with_parenthesis, tab_hk_f[hk_TR],#returntype, \ + tab_hk_f[hk_TR], #args_call_with_parenthesis, tab_hk_f[hk_TR], tab_hk_f[hk_TR], tab_hk_f[hk_TR] ); \ + /*return (returntype)0;*/ \ + INIT_MOCK_INFO_IF_NO_(tmp_mock,namefunction, PRE_ID);\ + }/* to have log */\ + /*if(list_mo_ ## namefunction.next ) PRINT_ERROR(" %s .next SHOULD BE NULL\n",STRFY(list_mo_ ## namefunction));*/\ + }\ + while(tmp_mock->next && (tmp_mock->info_mock)->times_left == 0) {tmp_mock = tmp_mock->next ;}\ + ++((tmp_mock->info_mock)->call);\ + if(tmp_mock->str_print_current_variables){\ + append_variable_current(&((tmp_mock->info_mock)->l_current_var), tmp_mock->str_print_current_variables args_call_with_parenthesis);\ + }\ + else if(count_call_f == 1){\ + PRINT_HK_C(colors_f[k_YELLOW],tab_hk_f[hk_TR]," no printer variable function defined, to define it:\n"\ + "%s STR_PRINT_CUR_VAR(%s,%s,%s){\n"\ + "%s\t char* ret=malloc(256);/*for instance*/;\n"\ + "%s\t ... sprintf(ret,...., %s);/*for instance*/ \n"\ + "%s\t return ret;\n"\ + "%s }\n"\ + "%s same prototype as MOCK_FUNC whithout returntype which always char* i\n\n",\ + tab_hk_f[hk_TR], #namefunction,#args_prototype_with_parenthesis, #args_call_with_parenthesis, \ + tab_hk_f[hk_TR], tab_hk_f[hk_TR], #args_call_with_parenthesis, tab_hk_f[hk_TR], tab_hk_f[hk_TR], tab_hk_f[hk_TR] ); \ + }\ + /*LOG("condition_func:%d\n", tmp_mock->call_mock_condition args_call_with_parenthesis);*/ /*LOG("%s\n","failure condition");*/\ + /*EXPECT_EQ_TYPE_INT(1, tmp_mock->call_mock_condition args_call_with_parenthesis);*/ /*LOG("%s\n","failure condition");*/\ + /*if ((tmp_mock->info_mock)->times_left == 0)*/ /*no longer response, default return */ \ + /*return (returntype)0;*//* default return */\ + if( (tmp_mock->info_mock)->str_caller == NULL){ \ + if(count_call_f == 1){\ + PRINT_HK_C(colors_f[k_YELLOW],tab_hk_f[hk_TR]," WARNING, no INIT_CALLER_MOCK; you can put it like this: \n"\ + "%s TEST(nametest){\n"\ + "%s\t INIT_CALLER_MOCK(%s); \n"\ + "%s\t %s%s; \n"\ + "%s }\n"\ + "%s i.e before calling %s in this TEST, to have explicit logs\n",\ + tab_hk_f[hk_TR], tab_hk_f[hk_TR], #namefunction, tab_hk_f[hk_TR],#namefunction,#args_call_with_parenthesis, tab_hk_f[hk_TR], tab_hk_f[hk_TR], #namefunction);} \ + /*return (returntype)0;*/ \ + }\ + else if (((tmp_mock->info_mock)->times_left != 0) && ((tmp_mock->info_mock)->times_left != INITSTATE )) {\ + size_t len0 = strlen((tmp_mock->info_mock)->str_conditions);\ + size_t len1 = strlen("when checking condition call: aa");\ + char *msg_call=malloc(len0 + len1 + strlen(__func__)+1);\ + sprintf(msg_call,"when checking %s condition call: %s",__func__,(tmp_mock->info_mock)->str_conditions);\ + HANDLE_OP_EXPECT_NAME(EQ,TYPE_INT,1, tmp_mock->call_mock_condition args_call_with_parenthesis, (tmp_mock->info_mock)->str_caller, msg_call); /*LOG("%s\n","failure condition");*/\ + free(msg_call);\ + }\ + /*if(0 == tmp_mock->call_mock_condition args_call_with_parenthesis){\ + PRINT_LOC("Failure, arguments not expected\ncondition ( %s ) not verified\n\n", (tmp_mock->info_mock)->str_conditions);\ + PRINT_HK_C(RED_K,tab_hk_f[hk_TR]," 1 argument check failed from %s \n",__func__); \ + }*/\ + PRINT_DEBUG(" %*c VALUES: mock function:%s, conditions:%s t_left:%ld, init_left:%ld| args:%s\n",8,'^',(tmp_mock->info_mock)->str_namefunc, (tmp_mock->info_mock)->str_conditions, (tmp_mock->info_mock)->times_left,(tmp_mock->info_mock)->init_times_left, #args_call_with_parenthesis);\ + if (((tmp_mock->info_mock)->times_left <= ININITY_REPS) || ((tmp_mock->info_mock)->times_left > 0)){\ + --((tmp_mock->info_mock)->times_left);\ + PRINT_DEBUG(" %*c VALUES: mock function:%s, conditions:%s t_left:%ld, init_left:%ld| args:%s\n",8,'v',(tmp_mock->info_mock)->str_namefunc, (tmp_mock->info_mock)->str_conditions, (tmp_mock->info_mock)->times_left,(tmp_mock->info_mock)->init_times_left, #args_call_with_parenthesis);\ + if(1 == tmp_mock->call_mock_condition args_call_with_parenthesis){\ + return tmp_mock->run args_call_with_parenthesis;\ + }\ + else ++((tmp_mock->info_mock)->failed_call);\ + }\ + return (returntype)0;/* default return */\ + } + + +char* extract_name_func_mock(char *input); + +/* + * used in mock functions to check the conditions + */ +#define EXPECT_EQ_IN_MOCKF(var1,var2, name_f_mocked)\ + do{ \ + if((list_mo_ ## name_f_mocked.info_mock)->str_caller) {\ + HANDLE_OP_EXPECT_NAME(EQ,TYPE_INT,var1,var2,(list_mo_ ## name_f_mocked.info_mock)->str_caller,"mock test");\ + }\ + else\ + HANDLE_OP_EXPECT_NAME(EQ,TYPE_INT,var1,var2,__func__,"mock test");\ +}while(0) + + +/* + * to inject the name TEST caller in the mock attribute info, usefull in logs and stats + */ +#define INIT_CALLER_MOCK(namefunction)/* */\ + do{\ + struct list_mock_return_ ## namefunction *tmp_mock = &list_mo_ ## namefunction;\ + while(tmp_mock){\ + (tmp_mock->info_mock)->str_caller=malloc(strlen(__func__)+1);\ + strcpy((tmp_mock->info_mock)->str_caller,__func__);\ + tmp_mock = tmp_mock->next;\ + }\ + }while(0); + +/* + * to create/ define str_print_current_variables functions + * prototype: char* str_print_current_variables (prototype of mock function) + * the args of the macro are the same of MOCK_FUNC without the returntype which is always (char*). + * It need to be defined after MOCK_FUNC but need to be before EXPECT_MOCK_CALL or WILL_MOCK_CALL + */ + +#define STR_PRINT_CUR_VAR(namefunction, args_prototype_with_parenthesis, args_call_with_parenthesis)\ + char* str_print_variables ## namefunction args_prototype_with_parenthesis;\ +__attribute__((constructor)) void create_str_print_variables ## namefunction(){\ + list_mo_ ## namefunction .str_print_current_variables = str_print_variables ## namefunction;\ + }\ + char* str_print_variables ## namefunction args_prototype_with_parenthesis + + + + +#define FILL_MOCK_INFO(tmp_new_mock, namefunction, condition_on_args_expression , repeat, f_expect_call, pre_id, id, is_init) \ + (tmp_new_mock)->run = CONCAT(run_ ## namefunction ## pre_id, id);\ + (tmp_new_mock)->call_mock_condition = CONCAT(namefunction ## _cond_, id);\ + if(!is_init)\ + (tmp_new_mock)->str_print_current_variables = list_mo_ ## namefunction .str_print_current_variables;\ + /*(tmp_new_mock)->info_mock = malloc(sizeof(struct func_mock_info_struct));*/\ + ((tmp_new_mock)->info_mock)->expect_call = f_expect_call;\ + ((tmp_new_mock)->info_mock)->used = true;\ + ((tmp_new_mock)->info_mock)->call = 0;\ + ((tmp_new_mock)->info_mock)->failed_call = 0;\ + ((tmp_new_mock)->info_mock)->init_times_left = repeat;\ + ((tmp_new_mock)->info_mock)->times_left = repeat;\ + ((tmp_new_mock)->info_mock)->str_namefunc = malloc(strlen(#namefunction) + 43 + strlen(#pre_id));\ + sprintf(((tmp_new_mock)->info_mock)->str_namefunc,"%s%s%d",#namefunction,#pre_id,id);\ + ((tmp_new_mock)->info_mock)->str_conditions = malloc(strlen(#condition_on_args_expression)+1);\ + strcpy(((tmp_new_mock)->info_mock)->str_conditions, #condition_on_args_expression);\ + ((tmp_new_mock)->info_mock)->str_caller = NULL;\ + ((tmp_new_mock)->info_mock)->l_current_var= NULL;\ + ((tmp_new_mock)->info_mock)->next = NULL;\ + (tmp_new_mock)->next = NULL;\ + append_fmock_to_listmock(&f_mock_glist, (tmp_new_mock)->info_mock); + + +#define ADD_RESPONSE_(returntype, namefunction, args_prototype_with_parenthesis, condition_on_args_expression , repeat, f_expect_call, pre_id, id)\ + /*FUNC_type_ ## namefunction CONCAT(run_ ## namefunction ## pre_id , id);*/\ + returntype CONCAT(run_ ## namefunction ## pre_id , id) args_prototype_with_parenthesis; \ + int CONCAT(namefunction ## _cond_ , id) args_prototype_with_parenthesis {/*LOG("cond:%d\n",condition_on_args_expression);*/ return condition_on_args_expression;}\ + __attribute__((constructor)) void CONCAT(append_list_ ## namefunction , id)(void){\ + PRINT_DEBUG(" in constructor fmock : func :%s\n",#namefunction);\ + struct list_mock_return_ ## namefunction *tmp_mock = &list_mo_ ## namefunction;\ + if((tmp_mock->info_mock)->times_left == INITSTATE){/* init state */\ + FILL_MOCK_INFO(tmp_mock, namefunction, condition_on_args_expression , repeat, f_expect_call, pre_id, id, true);\ + append_list_base_fmock( &g_list_base_fmock ,(tmp_mock->info_mock));\ + }\ + else{\ + while(tmp_mock->next) tmp_mock = tmp_mock->next;\ + tmp_mock->next = malloc(sizeof(list_mo_ ## namefunction));\ + (tmp_mock->next)->info_mock = malloc(sizeof(struct func_mock_info_struct));\ + FILL_MOCK_INFO(tmp_mock->next, namefunction, condition_on_args_expression , repeat, f_expect_call, pre_id, id, false);\ + /*(tmp_mock->info_mock)->next = (tmp_mock->next)->info_mock ;*/\ + }\ + }\ + returntype CONCAT(run_ ## namefunction ## pre_id, id) args_prototype_with_parenthesis + +/* + * have to define this below macro to rewrite the right macro identifier (PRE_ID) + */ + +#define ADD_RESPONSE(returntype, namefunction, args_prototype_with_parenthesis, condition_on_args_expression , repeat, f_expect_call, pre_id, id)\ + ADD_RESPONSE_(returntype, namefunction, args_prototype_with_parenthesis, condition_on_args_expression , repeat, f_expect_call, pre_id, id)\ + + +#define EXPECT_MOCK_CALL(returntype, namefunction, args_prototype_with_parenthesis, condition_on_args_expression ,repeat) \ + ADD_RESPONSE(returntype,namefunction, args_prototype_with_parenthesis, condition_on_args_expression, repeat, 1, PRE_ID, __LINE__) + + +#define WILL_MOCK_CALL(returntype, namefunction, args_prototype_with_parenthesis, condition_on_args_expression ,repeat) \ + ADD_RESPONSE(returntype,namefunction, args_prototype_with_parenthesis, condition_on_args_expression, repeat, 0, PRE_ID, __LINE__) + + + +#endif /* __MOCK_C_H__ */ /* implementations */ @@ -3602,3 +3914,427 @@ purge_tests() \ \ } \ + +/* implementation fmock */ + +//#include "fmock/fmock.h" + +#define LOCK(mutex_var) pthread_mutex_lock(&mutex_var); +#define UNLOCK(mutex_var) pthread_mutex_unlock(&mutex_var); + + +#define INCREMENT_(variable)\ + do{\ + LOCK(mut_##variable); \ + ++variable;\ + UNLOCK(mut_##variable);\ + }while(0); + +#define SSTRFY(x) STRFY(x) + +#define PRINT_VAR_CUR(mockinfo)\ + do{\ + PRINTF("\n%s list of variables when %s was called, with condition %s:\n\t\t",tab_hk_f[hk_EQ],mockinfo->str_namefunc,mockinfo->str_conditions);\ + size_t cal_cur=0;\ + struct list_current_variable *tmp_cur_v = mockinfo->l_current_var;\ + while(tmp_cur_v){\ + PRINTF(" call : %ld : variables : %s \n\t\t",++cal_cur, tmp_cur_v->str_current_variables);\ + tmp_cur_v = tmp_cur_v->next;\ + }\ + PRINTF("\n");\ + }while(0); + + +/* + * global variables + */ + +//char *colors_f[]={DEFAULT_K, RED_K, GREEN_K, YELLOW_K, BLUE_K, ""}; + +#define IMPLEMENTATION_FMOCK() \ + \ +size_t count_f_mock_wished=0; \ +pthread_mutex_t mut_count_f_mock_wished; \ + \ +size_t count_f_mock=0; \ +pthread_mutex_t mut_count_f_mock; \ + \ +size_t count_expect_mock=0; \ +pthread_mutex_t mut_count_expect_mock; \ + \ +struct list_base_fmock *g_list_base_fmock=NULL; \ +pthread_mutex_t mut_g_list_base_fmock; \ + \ +/* \ + * return the numbers of comas (,) +1 in the input string \ + */ \ + \ +int parse_count_args_(char *input){ \ + int val=0; \ + for(int i = 0; i< strlen(input); ++i){ \ + if(input[i]==',') ++val; \ + } \ + return val+1; \ +} \ + \ +/* \ + * the begin only ! \ + */ \ +void append_list_base_fmock(struct list_base_fmock **l_fmock, struct func_mock_info_struct *f_mock){ \ + INCREMENT_(count_f_mock); \ + LOCK(mut_g_list_base_fmock); \ + PRINT_DEBUG(" append_list_base_fmock %s",f_mock->str_namefunc); \ + if(*l_fmock){ \ + struct list_base_fmock *tmp_l_n = *l_fmock; \ + while(tmp_l_n->next) tmp_l_n = tmp_l_n->next; \ + (tmp_l_n->next) = malloc(sizeof(struct list_base_fmock)); \ + (tmp_l_n->next)->info_mock = f_mock; \ + (tmp_l_n->next)->next = NULL; \ + } \ + else{ \ + *l_fmock = malloc(sizeof(struct list_base_fmock)); \ + (*l_fmock)->info_mock = f_mock; \ + (*l_fmock)->next = NULL; \ + } \ + UNLOCK(mut_g_list_base_fmock); \ +} \ + \ +struct func_mock_info_struct *f_mock_glist = NULL; \ +pthread_mutex_t mut_f_mock_glist; \ + \ +void append_variable_current(struct list_current_variable **lcurrent_var, char *current_var){ \ + if(*lcurrent_var){ \ + PRINT_DEBUG("----- l_current_var not NULL, content: %s have to add %s\n",(*lcurrent_var)->str_current_variables, current_var); \ + struct list_current_variable *tmp_lcv = *lcurrent_var; \ + while(tmp_lcv->next) tmp_lcv = tmp_lcv->next; \ + tmp_lcv->next = malloc(sizeof(struct list_current_variable)); \ + /*(tmp_lcv->next)->str_current_variables = malloc(strlen(current_var)); */\ + /*strcpy((tmp_lcv->next)->str_current_variables,current_var); */\ + (tmp_lcv->next)->str_current_variables = current_var; \ + (tmp_lcv->next)->next= NULL; \ + \ + } \ + else{ \ + PRINT_DEBUG("-- lcurrent_var %s\n","NULL"); \ + *lcurrent_var = malloc(sizeof(struct list_current_variable)); \ + /*(*lcurrent_var)->str_current_variables = malloc(strlen(current_var)); */\ + /*strcpy((*lcurrent_var)->str_current_variables,current_var); */\ + (*lcurrent_var)->str_current_variables = current_var; \ + (*lcurrent_var)->next = NULL; \ + } \ +} \ + \ + \ +void append_fmock_to_listmock(struct func_mock_info_struct **f_mock_list, struct func_mock_info_struct *f_mock){ \ + INCREMENT_(count_f_mock_wished); \ + if(f_mock->expect_call) { \ + INCREMENT_(count_expect_mock); \ + } \ + LOCK(mut_f_mock_glist); \ + PRINT_DEBUG(" append_fmock_to_listmock %s",f_mock->str_namefunc); \ + if(*f_mock_list){ \ + struct func_mock_info_struct *tmp_fmock_info = *f_mock_list; \ + while(tmp_fmock_info->next) tmp_fmock_info = tmp_fmock_info->next; \ + tmp_fmock_info->next = f_mock; \ + } \ + else{ \ + *f_mock_list = f_mock; \ + } \ + UNLOCK(mut_f_mock_glist); \ + \ +} \ + \ + \ + \ + \ +char* extract_name_func_mock(char *input){ \ + char * ret=malloc(strlen(input) + 1); \ + strcpy(ret,input); \ + char * pre_id_ = SSTRFY(PRE_ID); \ + size_t len_pre_id_ = strlen(pre_id_); \ + for(size_t i=0; inext; \ + free(ttmp_fmock_info->str_namefunc); \ + free(ttmp_fmock_info->str_conditions); \ + free(ttmp_fmock_info->str_caller); \ + clear_variable_current(&(ttmp_fmock_info->l_current_var)); \ + free(ttmp_fmock_info); \ + } \ + *f_mock_list = NULL; \ + } \ +} \ + \ +void clear_list_base_fmock(struct list_base_fmock **l_fmock){ \ + if(*l_fmock){ \ + struct list_base_fmock *tmp_l_n = *l_fmock, *ttmp_l_n; \ + while(tmp_l_n){ \ + ttmp_l_n = tmp_l_n; \ + tmp_l_n = tmp_l_n->next; \ + /*clear_fmock_info_list(&((ttmp_l_n->next)->info_mock)); */\ + free(ttmp_l_n); \ + } \ + *l_fmock=NULL; \ + } \ + \ +} \ + \ +void clear_variable_current(struct list_current_variable **lcurrent_var){ \ + if(*lcurrent_var){ \ + struct list_current_variable *tmp_lcv = *lcurrent_var, *ttmp_lcv; \ + while(tmp_lcv){ \ + ttmp_lcv = tmp_lcv; \ + tmp_lcv = tmp_lcv->next; \ + \ + free(ttmp_lcv->str_current_variables); \ + free(ttmp_lcv); \ + } \ + *lcurrent_var=NULL; \ + } \ + \ +} \ + \ +/* destructor will be executed in inverse order of call/place in the file */ \ +__attribute__((destructor)) \ + void purge_fmock(){ \ + \ + clear_fmock_info_list(&f_mock_glist); \ + PRINT_DEBUG("purge f_mock_glist %s\n","done"); \ + clear_list_base_fmock(&g_list_base_fmock); \ + /*PRINT_DEBUG("purge g_list_base_fmock %s\n","done"); */\ + } \ + \ + \ +extern bool is_parallel_nb; \ + \ + \ +char * number_call_translate(long nb){ \ + char *ret=malloc(250); \ + if(nb>1) sprintf(ret," be called %ld times",nb); \ + else if(nb == 1) sprintf(ret," be called once"); \ + else if(nb == 0 ) sprintf(ret," not to be executed"); \ + else if(nb==ININITY_REPS) sprintf(ret," be called forever"); \ + else if(nb==INITSTATE) sprintf(ret," not expected"); \ + else sprintf(ret," nothing! it's negative:%ld", nb); \ + \ + return ret; \ +} \ + \ +char * strprint_caller_(char *input){ \ + if(input==NULL) { return "";} \ + char *called_in=",\t called in "; \ + char *ret = malloc(strlen(called_in) + strlen(input) + 1); \ + sprintf(ret,"%s%s",called_in,input); \ + return ret; \ +} \ + \ + \ + \ +__attribute__((destructor)) \ + void \ + check_mock_excpected(){ \ + \ + signal(SIGSEGV, SIG_DFL); /* restore default behaviour , */ \ + \ + /*int k_DEFAULT=0, k_GREEN=1, k_RED=2, k_YELLOW=3, k_BLUE=4, k_NOTHING; */\ + /*if(unicolour) { */\ + /*k_GREEN=k_NOTHING; k_RED=k_NOTHING; k_YELLOW=k_NOTHING; k_BLUE=k_NOTHING; */\ + /*for(int i=0; i< Dk_NOTHING;++i) strcpy(colors_f[i]," "); */\ + /*} */\ + if(only_usage) return; /* do nothing */ \ + if(g_list_base_fmock == NULL) return; /* do nothing because no mock functions */ \ + struct winsize w; \ + ioctl(1, TIOCGWINSZ, &w); \ + \ + char *reader=malloc(w.ws_col+3); \ + strcpy(reader,"STAT OF MOCK FUNCTIONS"); \ + \ + /*fprintf(F_OUT,"%s\n\n%0*d\n %*s \n%0*d %s\n\n", colors_f[k_YELLOW] ,w.ws_col,0, (int)(w.ws_col+strlen(reader))/2, reader,w.ws_col,0, DEFAULT_K ); */\ + PRINTF("%s\n\n%0*d\n %*s \n%0*d %s\n\n", colors_f[k_YELLOW] ,w.ws_col,0, (int)(w.ws_col+strlen(reader))/2, reader,w.ws_col,0, DEFAULT_K ); \ + \ + \ + is_parallel_nb = 0; /* no longer parallel here */ \ + struct func_mock_info_struct *tmock = f_mock_glist; /*, *tfree; */\ + \ + /* global order of fmock , order of expect and will */ \ + while(tmock){ \ + PRINT_DEBUG("check mock function: %s\n",tmock->str_namefunc); \ + /*tfree=tmock; */\ + PRINT_DEBUG("**** STAT mock function:%s, conditions:%s t_left:%ld, init_left:%ld, failed_call:%ld\n",tmock->str_namefunc, tmock->str_conditions, tmock->times_left,tmock->init_times_left, tmock->failed_call); \ + if(((tmock->expect_call) && (tmock->init_times_left == tmock->times_left)) || (tmock->failed_call)){ \ + if(tmock->l_current_var){ \ + char *str_nb_call = number_call_translate(tmock->init_times_left); \ + PRINTF("%s%s %s%s %s: expect %s, it was called %ld times and failed %ld times, with condition %s\n",colors_f[k_RED],tab_hk_f[hk_FL],colors_f[k_YELLOW],tmock->str_namefunc,DEFAULT_K, \ + str_nb_call, \ + tmock->call/*tmock->failed_call + (tmock->init_times_left - tmock->times_left)*/, \ + tmock->failed_call, \ + tmock->str_conditions \ + ); \ + \ + free(str_nb_call); \ + PRINT_VAR_CUR(tmock); \ + } \ + else{ \ + char *str_nb_call = number_call_translate(tmock->init_times_left); \ + PRINTF("%s%s %s%s %s: expect %s, it was called %ld times and failed %ld times, with condition %s \n",colors_f[k_RED],tab_hk_f[hk_FL],colors_f[k_YELLOW],tmock->str_namefunc,DEFAULT_K, \ + str_nb_call, \ + tmock->call/*tmock->failed_call + (tmock->init_times_left - tmock->times_left)*/, \ + tmock->failed_call, \ + tmock->str_conditions \ + ); \ + \ + free(str_nb_call); \ + } \ + } \ + tmock=tmock->next; \ + /*free(tfree); */\ + } \ + \ + PRINTF("\n%s%s STAT MOCK : there are %ld mock functions, %ld wished responses, %ld expected responses, which are:\n\n",colors_f[k_GREEN],tab_hk_f[hk_EQ],count_f_mock, count_f_mock_wished, count_expect_mock); \ + struct list_base_fmock *tmp_list_fm = g_list_base_fmock; \ + struct func_mock_info_struct *tmp_inf_mock; \ + /* list each fmock an each calls */ \ + while(tmp_list_fm){ \ + tmp_inf_mock = tmp_list_fm->info_mock; \ + for(size_t i=0;istr_caller){ \ + caller = extract_func_edited_TEST_from_exec_func_name(tmp_inf_mock->str_caller); \ + } \ + size_t len_caller = strlen(caller); \ + \ + char *nameff=extract_name_func_mock(tmp_inf_mock->str_namefunc); \ + size_t len_nameff=strlen(nameff); \ + char *by_=" called by "; \ + size_t len_by_=strlen(by_); \ + size_t bg_rd=(w.ws_col -1 - len_nameff - len_caller - len_by_)/2; \ + reader[bg_rd++]=' '; \ + for(size_t i=0; istr_namefunc,nameff, len_nameff)){ \ + if(tmp_inf_mock->expect_call==1){ \ + int success = !((tmp_inf_mock->init_times_left == tmp_inf_mock->times_left) || (tmp_inf_mock->failed_call)); \ + \ + if(tmp_inf_mock->l_current_var){ \ + char *str_caller = strprint_caller_(tmp_inf_mock->str_caller); \ + char *str_nb_call = number_call_translate(tmp_inf_mock->init_times_left); \ + PRINTF("%s%s%s %s\t expect to%s,\t called %ld times and failed %ld times %s,\t with condition: %s%s\n" , \ + colors_f[!unicolour*(k_RED - success)],tab_hk_f[hk_FL-success],colors_f[k_NOTHING * success],tmp_inf_mock->str_namefunc, str_nb_call, tmp_inf_mock->call, \ + tmp_inf_mock->failed_call, str_caller, tmp_inf_mock->str_conditions, DEFAULT_K); \ + free(str_nb_call); \ + if(strcmp(str_caller,"")) free(str_caller); \ + PRINT_VAR_CUR(tmp_inf_mock); \ + }else{ \ + char *str_caller = strprint_caller_(tmp_inf_mock->str_caller); \ + char *str_nb_call = number_call_translate(tmp_inf_mock->init_times_left); \ + PRINTF("%s%s%s %s\t expect to%s,\t called %ld times and failed %ld times %s,\t with condition: %s%s\n" , \ + colors_f[!unicolour*(k_RED - success)],tab_hk_f[hk_FL-success],colors_f[k_NOTHING*success],tmp_inf_mock->str_namefunc, str_nb_call, tmp_inf_mock->call, \ + tmp_inf_mock->failed_call, str_caller, tmp_inf_mock->str_conditions , DEFAULT_K); \ + free(str_nb_call); \ + if(strcmp(str_caller,"")) free(str_caller); \ + } \ + }else if(tmp_inf_mock->expect_call==0) {/* will expect */ \ + int success = !(tmp_inf_mock->failed_call); \ + if(tmp_inf_mock->l_current_var){ \ + char *str_caller = strprint_caller_(tmp_inf_mock->str_caller); \ + char *str_nb_call = number_call_translate(tmp_inf_mock->init_times_left); \ + PRINTF("%s%s%s %s\t will%s,\t called %ld times and failed %ld times %s,\t with condition: %s,%s\n" , \ + colors_f[!unicolour*(k_RED + success)],tab_hk_f[hk_FL-success],colors_f[k_NOTHING*success],tmp_inf_mock->str_namefunc, str_nb_call, tmp_inf_mock->call, \ + tmp_inf_mock->failed_call, str_caller, tmp_inf_mock->str_conditions , DEFAULT_K); \ + free(str_nb_call); \ + if(strcmp(str_caller,"")) free(str_caller); \ + PRINT_VAR_CUR(tmp_inf_mock); \ + }else{ \ + char *str_caller = strprint_caller_(tmp_inf_mock->str_caller); \ + char *str_nb_call = number_call_translate(tmp_inf_mock->init_times_left); \ + PRINTF("%s%s%s %s\t will%s,\t called %ld times and failed %ld times %s,\t with condition: %s %s\n" , \ + colors_f[!unicolour*(k_RED + success)],tab_hk_f[hk_FL-success],colors_f[k_NOTHING*success],tmp_inf_mock->str_namefunc, str_nb_call, tmp_inf_mock->call, \ + tmp_inf_mock->failed_call, str_caller, tmp_inf_mock->str_conditions , DEFAULT_K); \ + free(str_nb_call); \ + if(strcmp(str_caller,"")) free(str_caller); \ + } \ + } \ + else if(tmp_inf_mock->expect_call==-1){ \ + if(tmp_inf_mock->l_current_var){ \ + char *str_caller = strprint_caller_(tmp_inf_mock->str_caller); \ + char *str_nb_call = number_call_translate(tmp_inf_mock->init_times_left); \ + PRINTF("%s%s%s %s\t %s,\t called %ld times, %s\n" , \ + colors_f[!unicolour*(k_RED)],tab_hk_f[hk_FL],colors_f[k_DEFAULT],tmp_inf_mock->str_namefunc, \ + str_nb_call, tmp_inf_mock->call, str_caller ); \ + free(str_nb_call); \ + if(strcmp(str_caller,"")) free(str_caller); \ + PRINT_VAR_CUR(tmp_inf_mock); \ + }else{ \ + char *str_nb_call = number_call_translate(tmp_inf_mock->init_times_left); \ + char *str_caller = strprint_caller_(tmp_inf_mock->str_caller); \ + PRINTF("%s%s%s %s\t %s,\t called %ld times, %s\n" , \ + colors_f[!unicolour*(k_RED)],tab_hk_f[hk_FL],colors_f[k_DEFAULT],tmp_inf_mock->str_namefunc, \ + str_nb_call, tmp_inf_mock->call, str_caller); \ + free(str_nb_call); \ + if(strcmp(str_caller,"")) free(str_caller); \ + } \ + \ + } \ + } \ + tmp_inf_mock = tmp_inf_mock->next; \ + } \ + PRINT_DEBUG(" end listing info mock of %s \n", nameff); \ + tmp_list_fm = tmp_list_fm->next; \ + \ + free(nameff); \ + } \ + \ + free(reader); \ + \ + PRINT_DEBUG("%s\n","info mock done!"); \ + \ + pthread_mutex_destroy(&mut_g_list_base_fmock); \ + pthread_mutex_destroy(&mut_f_mock_glist); \ + pthread_mutex_destroy(&mut_count_f_mock_wished); \ + pthread_mutex_destroy(&mut_count_f_mock); \ + pthread_mutex_destroy(&mut_count_expect_mock); \ + PRINT_DEBUG("%s\n","pthread_mutex_destroy done!"); \ + PRINT_DEBUG("%s\n","check mock done!"); \ + \ + } \ +