419 lines
16 KiB
C
419 lines
16 KiB
C
#include "fmock/fmock.h"
|
|
|
|
/*
|
|
* global variables
|
|
*/
|
|
|
|
//char *colors_f[]={DEFAULT_K, RED_K, GREEN_K, YELLOW_K, BLUE_K, ""};
|
|
|
|
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;
|
|
|
|
#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);
|
|
|
|
|
|
/*
|
|
* 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);
|
|
|
|
}
|
|
|
|
|
|
|
|
#define SSTRFY(x) STRFY(x)
|
|
|
|
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; i<strlen(ret)-len_pre_id_; ++i){
|
|
if(strncmp(ret+i,pre_id_,len_pre_id_) == 0){
|
|
ret[i]='\0';
|
|
break;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
__attribute__((constructor))
|
|
void
|
|
init_mock_c(){
|
|
|
|
pthread_mutex_init(&mut_g_list_base_fmock, NULL);
|
|
pthread_mutex_init(&mut_f_mock_glist, NULL);
|
|
pthread_mutex_init(&mut_count_f_mock_wished, NULL);
|
|
pthread_mutex_init(&mut_count_f_mock, NULL);
|
|
pthread_mutex_init(&mut_count_expect_mock, NULL);
|
|
}
|
|
|
|
|
|
|
|
void clear_fmock_info_list(struct func_mock_info_struct **f_mock_list){
|
|
if(*f_mock_list){
|
|
struct func_mock_info_struct *tmp_fmock_info = *f_mock_list, *ttmp_fmock_info;
|
|
while(tmp_fmock_info){
|
|
ttmp_fmock_info = tmp_fmock_info;
|
|
tmp_fmock_info = tmp_fmock_info->next;
|
|
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;
|
|
}
|
|
|
|
#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);
|
|
|
|
|
|
|
|
__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;i<w.ws_col-2;++i) reader[i]='='; //memset(reader,'=',w.ws_col);
|
|
reader[w.ws_col-2]='\0';
|
|
char *caller="";
|
|
if(tmp_inf_mock->str_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; i<len_nameff; ++i)
|
|
reader[bg_rd+i]=nameff[i];
|
|
if(len_caller){
|
|
for(size_t i=0;i<len_by_;++i)
|
|
reader[bg_rd+len_nameff+i]=by_[i];
|
|
for(size_t i=0;i<len_caller;++i)
|
|
reader[bg_rd+len_nameff+len_by_+i]=caller[i];
|
|
reader[bg_rd+len_nameff+len_by_+len_caller]=' ';
|
|
}
|
|
else{
|
|
reader[bg_rd+len_nameff]=' ';
|
|
}
|
|
PRINTF("%s%s%s\n\n",colors_f[k_BLUE],reader,DEFAULT_K );
|
|
if(strcmp(caller,"")) free(caller);
|
|
|
|
while(tmp_inf_mock){
|
|
if(0==strncmp(tmp_inf_mock->str_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!");
|
|
|
|
}
|
|
|