Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
fefd585efa053238d4c4f4cc7bd4b8abde579916
[simgrid.git] / tools / tesh2 / src / unit.c
1 #include <unit.h>
2 #include <suite.h>
3 #include <command.h>
4 #include <context.h>
5 #include <fstream.h>
6 #include <variable.h>
7 #include <str_replace.h>
8
9 XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(tesh);
10
11 static void
12 replace_variables(unit_t unit, char** line)
13 {
14         variable_t variable;
15         char name[MAX_PATH + 1] = {0};
16         
17         /* check if some commands have setted some environment variables */
18         /* TODO */
19         
20         /*printf("repalce all the variables of the line %s\n", *line);*/
21         
22         
23         xbt_os_mutex_acquire(unit->mutex);
24         
25         vector_rewind(unit->runner->variables);
26         
27         while((variable = vector_get(unit->runner->variables)))
28         {
29                 sprintf(name, "$%s", variable->name);
30                 /*printf("try to replace all the variable %s\n",name);*/
31                 str_replace_all(line, name, variable->val);
32                 
33                 vector_move_next(unit->runner->variables);
34                 memset(name, 0, MAX_PATH + 1);
35         }
36         
37         xbt_os_mutex_release(unit->mutex);
38         
39         /*printf("line after the variables replacement %s\n",*line);*/
40         
41 }
42
43 /* the unit thread start routine */
44 static void*
45 unit_start(void* p);
46
47 unit_t
48 unit_new(runner_t runner, unit_t root, unit_t owner, fstream_t fstream)
49 {
50         unit_t unit = xbt_new0(s_unit_t, 1);
51
52         /* set the owner of the unit */
53         unit->runner = runner;
54         
55         unit->fstream = fstream;
56
57         unit->sem = NULL;
58
59         unit->commands = vector_new(DEFAULT_COMMANDS_CAPACITY, (fn_finalize_t)command_free);
60         unit->includes = vector_new(DEFAULT_INCLUDES, (fn_finalize_t)unit_free);
61         
62         unit->thread = NULL;
63
64         unit->number_of_started_commands = 0;
65         unit->number_of_interrupted_commands = 0;
66         unit->number_of_failed_commands = 0;
67         unit->number_of_successeded_commands = 0;
68         unit->number_of_terminated_commands = 0;
69         unit->number_of_waiting_commands = 0;
70         unit->interrupted = 0;
71         unit->failed = 0;
72         unit->successeded = 0;
73         unit->parsed = 0;
74         unit->released = 0;
75         unit->parsing_include_file = 0;
76         
77         
78         unit->owner = owner;
79         
80         unit->root = root ?  root : unit;
81         
82         
83         unit->number = 0;
84         unit->suites = vector_new(DEFAULT_SUITES_CAPACITY, (fn_finalize_t)unit_free);
85         unit->owner = owner;
86         
87         unit->running_suite = 0;
88         unit->is_suite = 0;
89         unit->description = NULL;
90
91         return unit;
92
93 }
94
95 /*void
96 unit_add_suite(unit_t unit, suite_t suite)
97 {
98         vector_push_back(unit->suites, suite);
99 }*/
100
101 int
102 unit_free(void** unitptr)
103 {
104         unit_t* __unitptr = (unit_t*)unitptr;
105         
106         vector_free(&((*__unitptr)->commands));
107         
108         vector_free(&((*__unitptr)->includes));
109         
110         vector_free(&((*__unitptr)->suites));
111         
112         /* if the unit is interrupted during its run, the semaphore is NULL */
113         if((*__unitptr)->sem)
114                 xbt_os_sem_destroy((*__unitptr)->sem);
115                 
116         if((*__unitptr)->description)
117                 free((*__unitptr)->description);
118         
119         free((*__unitptr)->suites);
120
121         free(*__unitptr);
122         
123         *__unitptr = NULL;
124         
125         return 0;
126 }
127
128 static void*
129 unit_start(void* p) 
130 {
131         
132         xbt_os_thread_t thread;
133         xbt_os_mutex_t mutex;
134         /*context_t context;*/
135         int i, j;
136
137         unit_t unit = (unit_t)p;
138         unit_t include;
139         
140         xbt_os_mutex_acquire(unit->mutex);
141         unit->runner->number_of_runned_units++;
142         xbt_os_mutex_release(unit->mutex);
143
144         /* try to acquire the jobs semaphore to start */
145         xbt_os_sem_acquire(jobs_sem);
146         
147         mutex = xbt_os_mutex_init();
148         /*context = context_new();*/
149         
150         if(want_dry_run)
151                 INFO1("checking unit %s...",unit->fstream->name); 
152         
153         /* parse the file */
154         /*unit_parse(unit, context, mutex, unit->fstream->name, unit->fstream->stream);*/
155         
156         fstream_parse(unit->fstream, unit, mutex);
157         
158         
159         /* if the unit is not interrupted and not failed the unit, all the file is parsed
160          * so all the command are launched
161          */
162          
163         
164         if(!unit->interrupted)
165         {
166                 unit->parsed = 1;
167                 
168                 /* all the commands have terminate before the end of the parsing of the tesh file
169                  * so the unit release the semaphore itself
170                  */
171                 if(!unit->released && (unit->number_of_started_commands == (unit->number_of_failed_commands + unit->number_of_interrupted_commands + unit->number_of_successeded_commands)))
172                 {
173                         /*INFO1("the unit %s is released", unit->fstream->name);*/
174                         xbt_os_sem_release(unit->sem);  
175                 }
176                 else
177                 {
178                         
179                         INFO1("the unit %s is not released", unit->fstream->name);
180                         INFO1("number of started commands %d", unit->number_of_started_commands);
181                         INFO1("number of failed commands %d", unit->number_of_failed_commands);
182                         INFO1("number of interrupted commands %d", unit->number_of_interrupted_commands);
183                         INFO1("number of successeded commands %d", unit->number_of_successeded_commands);
184                         INFO1("number of waiting commands %d", unit->number_of_waiting_commands);
185                         
186                         
187                         if(unit->number_of_waiting_commands)
188                         {
189                                 command_t command;
190                                 int i, j;
191         
192                                 for(i = 0; i < vector_get_size(unit->includes) ; i++)
193                                 {
194                                         include = vector_get_at(unit->includes, i);
195                                 
196                                         for(j = 0; j < vector_get_size(include->commands); j++)
197                                         {
198                                                 command = vector_get_at(include->commands, j);
199                                                 
200                                                 if(command->status == cs_in_progress)
201                                                 {
202                                                         INFO2("the command %s PID %d is in process", command->context->command_line, command->pid);
203                                                         
204                                                         if(command->writer->done)
205                                                                 INFO2("the writer of the command %s PID %d done", command->context->command_line, command->pid);        
206                                                         else
207                                                                 INFO2("the writer of the command %s PID %d  doesn't done", command->context->command_line, command->pid);
208                                                 }
209                                         }
210                                         
211                                 }
212                         }
213                 }
214                 
215         }
216         
217         /* wait the end of all the commands or a command failure or an interruption */
218         xbt_os_sem_acquire(unit->sem);
219         
220         
221         if(unit->interrupted)
222         {
223                 command_t command;
224                 
225                 /* interrupt all the running commands of the unit */ 
226                 for(i = 0; i < vector_get_size(unit->commands); i++)
227                 {
228                         command = vector_get_at(unit->commands, i);
229
230                         if(command->status == cs_in_progress)
231                                 command_interrupt(command);
232                 }
233                 
234                 for(i = 0; i < vector_get_size(unit->includes); i++)
235                 {
236                         include = vector_get_at(unit->includes, i);
237                         
238                         for(j = 0; j < vector_get_size(include->commands); j++)
239                         {
240                                 command = vector_get_at(include->commands, j);
241
242                                 if(command->status == cs_in_progress)
243                                         command_interrupt(command);
244                         }
245                 }
246                 
247         }
248         
249         /* wait the end of the threads */
250         for(i = 0; i < vector_get_size(unit->commands); i++)
251         {
252                 command_t command = vector_get_at(unit->commands, i);
253                 thread = command->thread;
254                 
255                 if(thread)
256                         xbt_os_thread_join(thread,NULL);
257         }
258         
259         for(i = 0; i < vector_get_size(unit->includes); i++)
260         {
261                 include = vector_get_at(unit->includes, i);
262                 
263                 for(j = 0; j < vector_get_size(include->commands); j++)
264                 {
265                         command_t command = vector_get_at(include->commands, j);
266                         thread = command->thread;
267                 
268                         if(thread)
269                                 xbt_os_thread_join(thread,NULL);
270                 }
271         }
272         
273         /*context_free(&context);*/
274         
275         xbt_os_mutex_destroy(mutex);
276         
277         
278         xbt_os_mutex_acquire(unit->mutex);
279
280         /* increment the number of ended units */
281         unit->runner->number_of_ended_units++;
282         
283         /* it's the last unit, release the runner */
284         if(/*!unit->interrupted &&*/ (unit->runner->number_of_runned_units == unit->runner->number_of_ended_units))
285         {
286                 if(unit->number_of_successeded_commands == unit->number_of_commands)
287                         unit->successeded = 1;
288
289                 /* first release the mutex */
290                 xbt_os_mutex_release(unit->mutex);
291                 
292                 xbt_os_sem_release(units_sem);
293         }
294         else
295                 xbt_os_mutex_release(unit->mutex);
296         
297         /* release the jobs semaphore, then the next unit can start */
298         xbt_os_sem_release(jobs_sem);
299         
300         return NULL;
301
302 }
303
304 void
305 unit_parse(unit_t unit, context_t context, xbt_os_mutex_t mutex, const char* file_name, FILE* stream)
306 {
307         size_t len;
308         char * line = NULL;
309         int line_num=0;
310         char file_pos[256];
311         xbt_strbuff_t buff;
312         int buffbegin = 0; 
313         
314         /* Count the line length while checking wheather it's blank */
315         int blankline;
316         int linelen;    
317         /* Deal with \ at the end of the line, and call handle_line on result */
318         int to_be_continued;
319         
320         buff=xbt_strbuff_new();
321         
322         while(!unit->interrupted  && getline(&line, &len, stream) != -1)
323         {
324                 blankline=1;
325                 linelen = 0;    
326                 to_be_continued = 0;
327
328                 line_num++;
329                 
330                 while(line[linelen] != '\0') 
331                 {
332                         if (line[linelen] != ' ' && line[linelen] != '\t' && line[linelen]!='\n' && line[linelen]!='\r')
333                                 blankline = 0;
334                         
335                         linelen++;
336                 }
337         
338                 if(blankline) 
339                 {
340                         if(!context->command_line && (context->input->used || context->output->used))
341                         {
342                                 ERROR1("[%d] Error: no command found in this chunk of lines.",buffbegin);
343                                 
344                                 if(unit->parsing_include_file)
345                                         ERROR1("Unit `%s': NOK (syntax error)", unit->fstream->name);
346                                 else
347                                         ERROR2("Unit `%s' inclued in `%s' : NOK (syntax error)", file_name, unit->fstream->name);       
348                                 
349                                 exit_code = ESYNTAX;
350                                 unit_handle_failure(unit);
351                                 break;
352                         }
353                         else if(unit->running_suite)
354                         {
355                                 /* TODO */
356                         }
357                                         
358                         
359                         if(context->command_line)
360                         {
361                                 if(!want_dry_run)
362                                 {
363                                         command_t command = command_new(unit, context, mutex);
364                                         command_run(command);
365                                 }
366                                 
367                                 context_reset(context);
368                         }
369                 
370                 
371                         continue;
372                         
373                 }
374                 
375                 if(linelen>1 && line[linelen-2]=='\\') 
376                 {
377                         if (linelen>2 && line[linelen-3] == '\\') 
378                         {
379                                 /* Damn. Escaped \ */
380                                 line[linelen-2] = '\n';
381                                 line[linelen-1] = '\0';
382                         } 
383                         else 
384                         {
385                                 to_be_continued = 1;
386                                 line[linelen-2] = '\0';
387                                 linelen -= 2;  
388                                 
389                                 if (!buff->used)
390                                         buffbegin = line_num;
391                         }
392                 }
393         
394                 if(buff->used || to_be_continued) 
395                 { 
396                         xbt_strbuff_append(buff,line);
397         
398                         if (!to_be_continued) 
399                         {
400                                 snprintf(file_pos,256,"%s:%d",file_name,buffbegin);
401                                 unit_handle_line(unit, context, mutex, file_pos, buff->data);    
402                                 xbt_strbuff_empty(buff);
403                         }
404                 } 
405                 else 
406                 {
407                         snprintf(file_pos,256,"%s:%d",file_name,line_num);
408                         unit_handle_line(unit, context, mutex, file_pos, line);      
409                 }
410         }
411         
412         /* Check that last command of the file ran well */
413         if(context->command_line)
414         {
415                 if(!want_dry_run)
416                 {
417                         command_t command = command_new(unit, context, mutex);
418                         command_run(command);
419                 }
420                 
421                 context_reset(context);
422         }
423
424         /* Clear buffers */
425         if (line)
426                 free(line);
427                 
428         xbt_strbuff_free(buff); 
429 }
430
431
432
433 void 
434 unit_handle_line(unit_t unit, context_t context, xbt_os_mutex_t mutex, const char * filepos, char *line) 
435 {
436         char* line2;
437         /* Search end */
438         xbt_str_rtrim(line+2,"\n");
439         
440         line2 = strdup(line);
441         
442         replace_variables(unit, &line2);
443         
444         switch (line2[0]) 
445         {
446                 case '#': 
447                 break;
448                 
449                 case '$':
450                 case '&':
451                         
452                 context->async = (line2[0] == '&');
453                 
454                 /* further trim useless chars which are significant for in/output */
455                 xbt_str_rtrim(line2+2," \t");
456                 
457                 /* Deal with CD commands here, not in rctx */
458                 if(!strncmp("cd ",line2 + 2, 3)) 
459                 {
460                         /*char *dir=line2+4; */
461                         char* dir = strdup(line2 + 4);
462                         
463                         if(context->command_line)
464                         {
465                                 if(!want_dry_run)
466                                 {
467                                         command_t command = command_new(unit, context, mutex);
468                                         command_run(command);
469                                 }
470                                 
471                                 context_reset(context);
472                         }
473                 
474                         /* search begining */
475                         while (*(dir++) == ' ');
476                         
477                         dir--;
478                         
479                         VERB1("Saw cd '%s'",dir);
480                         
481                         
482                         if(!want_dry_run)
483                         {
484                         
485                                 if(chdir(dir))
486                                 {
487                                         ERROR2("Chdir to %s failed: %s",dir,strerror(errno));
488                                         ERROR1("Test suite `%s': NOK (system error)", unit->fstream->name);
489                                         exit_code = ECHDIR;
490                                         unit_handle_failure(unit);
491                                 }
492                                 
493                                 
494                         }
495                         
496                         break;
497                 } /* else, pushline */
498                 else
499                 {
500                         unit_pushline(unit, context, mutex, filepos, line2[0], line2+2 /* pass '$ ' stuff*/);
501                         break;
502                 }
503                 
504                 case '<':
505                 case '>':
506                 case '!':
507                 unit_pushline(unit, context, mutex, filepos, line2[0], line2+2 /* pass '$ ' stuff*/);    
508                 break;
509                 
510                 case 'p':
511                 if(!want_dry_run)
512                         INFO2("[%s] %s",filepos,line2+2);
513                 break;
514                 
515                 case 'P':
516                 if(!want_dry_run)
517                         CRITICAL2("[%s] %s",filepos,line2+2);
518                 break;
519                 
520                 case 'D':
521                         if(unit->description)
522                                 WARN2("description already specified %s %s", filepos, line2); 
523                         else
524                                 unit->description = strdup(line2 + 2);
525                 break;
526                 
527                 default:
528                 ERROR2("[%s] Syntax error: %s",filepos, line2);
529                 ERROR1("Test suite `%s': NOK (syntax error)",unit->fstream->name);
530                 exit_code = ESYNTAX;
531                 unit_handle_failure(unit);
532                 break;
533         }
534         
535         free(line2);
536 }
537
538 void 
539 unit_pushline(unit_t unit, context_t context, xbt_os_mutex_t mutex, const char* filepos, char kind, char *line) 
540 {
541         switch (kind) 
542         {
543                 case '$':
544                 case '&':
545                 
546                 if(context->command_line) 
547                 {
548                         command_t command;
549                         
550                         if(context->output->used || context->input->used) 
551                         {
552                                 ERROR2("[%s] More than one command in this chunk of lines (previous: %s).\nDunno which input/output belongs to which command.",filepos,context->command_line);
553                                 ERROR1("Test suite `%s': NOK (syntax error)",unit->fstream->name);
554                                 exit_code = ESYNTAX;
555                                 unit_handle_failure(unit);
556                                 return;
557                         }
558                         
559                         if(!want_dry_run)
560                         {
561                                 command = command_new(unit, context, mutex);
562                                 command_run(command);
563                         }
564                         
565                         context_reset(context);
566                         
567                         VERB1("[%s] More than one command in this chunk of lines",filepos);
568                 }
569                 
570                 context->command_line = strdup(line);
571                 
572                 
573                 context->line = strdup(filepos);
574                 /*INFO2("[%s] %s",filepos,context->command_line);*/
575                 
576                 break;
577                 
578                 case '<':
579                 xbt_strbuff_append(context->input,line);
580                 xbt_strbuff_append(context->input,"\n");
581                 break;
582                 
583                 case '>':
584                 xbt_strbuff_append(context->output,line);
585                 xbt_strbuff_append(context->output,"\n");
586                 break;
587                 
588                 case '!':
589                 
590                 if(context->command_line)
591                 {
592                         if(!want_dry_run)
593                         {
594                                 command_t command = command_new(unit, context, mutex);
595                                 command_run(command);
596                         }
597                         
598                         context_reset(context);
599                 }
600                 
601                 if(!strncmp(line,"timeout no",strlen("timeout no"))) 
602                 {
603                         VERB1("[%s] (disable timeout)", filepos);
604                         context->timeout = INDEFINITE;
605                 } 
606                 else if(!strncmp(line,"timeout ",strlen("timeout "))) 
607                 {
608                         int i = 0;
609                         char* p = line + strlen("timeout ");
610         
611                         while(p[i] != '\0')
612                         {
613                                 if(!isdigit(p[i]))
614                                 {
615                                         exit_code = ESYNTAX;
616                                         ERROR2("Invalid timeout value `%s' at %s ", line + strlen("timeout "), filepos);
617                                         unit_handle_failure(unit);
618                                 }
619
620                                 i++;
621                         }
622                         
623                         context->timeout = atoi(line + strlen("timeout"));
624                         VERB2("[%s] (new timeout value: %d)",filepos,context->timeout);
625                 
626                 } 
627                 else if (!strncmp(line,"expect signal ",strlen("expect signal "))) 
628                 {
629                         context->signal = strdup(line + strlen("expect signal "));
630                         
631                         #ifdef WIN32
632                         if(!strstr(context->signal,"SIGSEGVSIGTRAPSIGBUSSIGFPESIGILL"))
633                         {
634                                 exit_code = ESYNTAX;
635                                 /*ERROR2("Signal `%s' not supported at %s", line + strlen("expect signal "), filepos);*/
636                                 unit_handle_failure(unit);
637                         }
638                         #endif
639
640                         xbt_str_trim(context->signal," \n");
641                         VERB2("[%s] (next command must raise signal %s)", filepos, context->signal);
642                 
643                 } 
644                 else if (!strncmp(line,"expect return ",strlen("expect return "))) 
645                 {
646
647                         int i = 0;
648                         char* p = line + strlen("expect return ");
649                         
650                         
651                         while(p[i] != '\0')
652                         {
653                                 if(!isdigit(p[i]))
654                                 {
655                                         exit_code = ESYNTAX;
656                                         ERROR2("Invalid exit code value `%s' at %s ", line + strlen("expect return "), filepos);
657                                         unit_handle_failure(unit);
658                                 }
659
660                                 i++;
661                         }
662
663                         context->exit_code = atoi(line+strlen("expect return "));
664                         VERB2("[%s] (next command must return code %d)",filepos, context->exit_code);
665                 
666                 } 
667                 else if (!strncmp(line,"output ignore",strlen("output ignore"))) 
668                 {
669                         context->output_handling = oh_ignore;
670                         VERB1("[%s] (ignore output of next command)", filepos);
671                 
672                 } 
673                 else if (!strncmp(line,"output display",strlen("output display"))) 
674                 {
675                         context->output_handling = oh_display;
676                         VERB1("[%s] (ignore output of next command)", filepos);
677                 
678                 } 
679                 else if(!strncmp(line,"include ", strlen("include ")))
680                 {
681                         char* p1;
682                         char* p2;
683                         
684                         p1 = line + strlen("include");
685                         
686                         while(*p1 == ' ' || *p1 == '\t')
687                                 p1++;
688                                 
689                         
690                         if(p1[0] == '\0')
691                         {
692                                 
693                                 exit_code = ESYNTAX;
694                                 ERROR1("include file not specified %s ", filepos);
695                                 unit_handle_failure(unit);
696                         }
697                         else
698                         {
699                                 char file_name[MAX_PATH + 1] = {0};
700                                 
701                                 /*INFO1("p1 is %s",p1);*/
702                                 
703                                 p2 = p1;
704                                 
705                                 while(*p2 != '\0' && *p2 != ' ' && *p2 != '\t')
706                                 {
707                                         /*INFO1("p2 is %s",p2);*/
708                                         p2++;
709                                         
710                                 }
711                                 /*INFO1("p2 is %s",p2);*/
712                                         
713                                 strncpy(file_name, p1, p2 - p1);
714                                 
715                                 /*INFO1("filename is %s", file_name);*/
716                                 
717                                 if(p2[0] != '\0')
718                                         while(*p2 == ' ' || *p2 == '\t')
719                                                 p2++;
720                                         
721                                 unit_handle_include(unit, context, mutex, file_name, p2[0] != '\0' ? p2 : NULL);
722                                 
723                         }
724                 }
725                 else if(!strncmp(line,"suite ", strlen("suite ")))
726                 {
727                         unit_handle_suite(unit, context, mutex, line + strlen("suite "));
728                 }
729                 else if(!strncmp(line,"unsetenv ", strlen("unsetenv ")))
730                 {
731                         int i;
732                         int number_of_variables;
733                         int exists = 0;
734                         int env;
735                         variable_t variable;
736                         char* name = line + strlen("unsetenv ");
737                         
738                         xbt_os_mutex_acquire(unit->mutex);
739                         
740                         number_of_variables = vector_get_size(unit->runner->variables);
741                         
742                         for(i = 0; i < number_of_variables; i++)
743                         {
744                                 variable = vector_get_at(unit->runner->variables, i);
745                                 
746                                 if(!strcmp(variable->name, name))
747                                 {
748                                         env = variable->env;
749                                         exists = 1;
750                                         break;
751                                 }
752                         }
753                                 
754                         if(env)
755                         {
756                                 if(exists)
757                                         vector_erase_at(unit->runner->variables, i);
758                                 else
759                                         WARN3("environment variable %s not found %s %s", name, line, filepos);  
760                         }
761                         else
762                         {
763                                 if(exists)
764                                         WARN3("%s is an not environment variable use unset metacommand to delete it %s %s", name, line, filepos);
765                                 else
766                                         WARN3("%s environment variable not found %s %s", name, line, filepos);
767                         }
768                         
769                         xbt_os_mutex_release(unit->mutex);      
770                         
771                                 
772                 }
773                 else if(!strncmp(line,"setenv ", strlen("setenv ")))
774                 {
775                         char* val;
776                         char name[MAX_PATH + 1] = {0};
777                         char* p;
778                         
779                         p = line + strlen("setenv ");
780                         
781                         val = strchr(p, '=');
782                         
783                         if(val)
784                         {
785                                 variable_t variable;
786                                 int exists = 0;
787                                 int env = 0;
788                                 val++;
789                                 
790                                 /* syntax error */
791                                 if(val[0] == '\0')
792                                 {
793                                         
794                                         exit_code = ESYNTAX;
795                                         ERROR2("indefinite variable value %s %s", line, filepos);
796                                         unit_handle_failure(unit);      
797                                 }
798                                 
799                                 
800                                 
801                                 strncpy(name, p, (val - p -1));
802                                 
803                                 /* test if the variable is already registred */
804                                 
805                                 xbt_os_mutex_acquire(unit->mutex);
806                                 
807                                 vector_rewind(unit->runner->variables);
808                                 
809                                 while((variable = vector_get(unit->runner->variables)))
810                                 {
811                                         
812                                         if(!strcmp(variable->name, name))
813                                         {
814                                                 variable->env = 1;
815                                                 exists = 1;
816                                                 break;
817                                         }
818                                         
819                                         vector_move_next(unit->runner->variables);
820                                 }
821                                 
822                                 /* if the variable is already registred, update its value;
823                                  * otherwise register it.
824                                  */
825                                 if(exists)
826                                 {
827                                         if(env)
828                                         {
829                                                 free(variable->val);
830                                                 variable->val = strdup(val);
831                                                 setenv(variable->name, variable->val, 1);
832                                         }
833                                         else
834                                                 WARN3("%s variable already exists %s %s", name, line, filepos); 
835                                 }
836                                 else
837                                 {
838                                         variable = variable_new(name, val);
839                                         variable->env = 1;
840                                         
841                                         vector_push_back(unit->runner->variables, variable);
842                                         
843                                         setenv(variable->name, variable->val, 0);
844                                 }
845                                 
846                                 xbt_os_mutex_release(unit->mutex);
847                                 
848                         }
849                 }
850                 else if(!strncmp(line,"unset ", strlen("unset ")))
851                 {
852                         int i;
853                         int number_of_variables;
854                         int exists = 0;
855                         int env;
856                         int err;
857                         variable_t variable;
858                         char* name = line + strlen("unset ");
859                         
860                         xbt_os_mutex_acquire(unit->mutex);
861                         
862                         number_of_variables = vector_get_size(unit->runner->variables);
863                         
864                         for(i = 0; i < number_of_variables; i++)
865                         {
866                                 variable = vector_get_at(unit->runner->variables, i);
867                                 
868                                 if(!strcmp(variable->name, name))
869                                 {
870                                         env = variable->env;
871                                         err = variable->err;
872                                         exists = 1;
873                                         break;
874                                 }
875                         }
876                                 
877                         if(!env)
878                         {
879                                 if(exists)
880                                         vector_erase_at(unit->runner->variables, i);
881                                 else
882                                         WARN3("variable %s not found %s %s", name, line, filepos);      
883                         }
884                         else if(env)
885                         {
886                                 WARN3("%s is an environment variable use unsetenv metacommand to delete it %s %s", name, line, filepos);        
887                         }
888                         else
889                         {
890                                 WARN3("%s is an error variable : you are not allowed to delete it %s %s", name, line, filepos);
891                         }
892                         xbt_os_mutex_release(unit->mutex);
893                                 
894                 }
895                 else
896                 {
897                         /* may be a variable */
898                         char* val;
899                         char name[MAX_PATH + 1] = {0};
900                         
901                         val = strchr(line, '=');
902                         
903                         if(val)
904                         {
905                                 variable_t variable;
906                                 int exists = 0;
907                                 val++;
908                                 
909                                 /* syntax error */
910                                 if(val[0] == '\0')
911                                 {
912                                         
913                                         exit_code = ESYNTAX;
914                                         ERROR2("indefinite variable value %s %s", line, filepos);
915                                         unit_handle_failure(unit);      
916                                 }
917                                 
918                                 
919                                 /* assume it's a varibale */
920                                 strncpy(name, line, (val - line -1));
921                                 
922                                 xbt_os_mutex_acquire(unit->mutex);
923                                 
924                                 /* test if the variable is already registred */
925                                 
926                                 vector_rewind(unit->runner->variables);
927                                 
928                                 while((variable = vector_get(unit->runner->variables)))
929                                 {
930                                         
931                                         if(!strcmp(variable->name, name))
932                                         {
933                                                 exists = 1;
934                                                 break;
935                                         }
936                                         
937                                         vector_move_next(unit->runner->variables);
938                                 }
939                                 
940                                 /* if the variable is already registred, update its value;
941                                  * otherwise register it.
942                                  */
943                                 if(exists)
944                                 {
945                                         free(variable->val);
946                                         variable->val = strdup(val);
947                                 }
948                                 else
949                                         vector_push_back(unit->runner->variables,variable_new(name, val));
950                                         
951                                 xbt_os_mutex_release(unit->mutex);
952                                 
953                         }
954                         else 
955                         {
956                                 ERROR2("%s: Malformed metacommand: %s",filepos,line);
957                                 ERROR1("Test suite `%s': NOK (syntax error)",unit->fstream->name);
958                                 
959                                 exit_code = ESYNTAX;
960                                 unit_handle_failure(unit);
961                                 return;
962                         }
963                 }
964                 
965                 
966                 break;
967         }
968 }
969
970
971 void
972 unit_handle_failure(unit_t unit)
973 {
974         
975         if(!want_keep_going_unit)
976         {
977                 unit_t root = unit->root ? unit->root : unit;
978                         
979                 if(!root->interrupted)
980                 {
981                         /* the unit interrupted (exit for the loop) */
982                         root->interrupted = 1;
983
984                         /* release the unit */
985                         xbt_os_sem_release(root->sem);
986                 }
987
988                 /* if the --keep-going option is not specified */
989                 if(!want_keep_going)
990                 {
991                         if(!interrupted)
992                         {
993                                 /* request an global interruption by the runner */
994                                 interrupted = 1;
995
996                                 /* release the runner */
997                                 xbt_os_sem_release(units_sem);
998                         }
999                 }
1000         }
1001 }
1002
1003 void
1004 unit_run(unit_t unit, xbt_os_mutex_t mutex)
1005 {
1006         if(!interrupted)
1007         {
1008                 unit->mutex = mutex;
1009                 
1010                 unit->sem = xbt_os_sem_init(0);
1011
1012                 /* start the unit */
1013                 unit->thread = xbt_os_thread_create("", unit_start, unit);
1014         }
1015         else
1016                 /* the unit is interrupted by the runner before its starting 
1017                  * in this case the unit semaphore is NULL take care of that
1018                  * in the function unit_free()
1019                  */
1020                 unit->interrupted = 1;
1021
1022         
1023 }
1024
1025 void
1026 unit_interrupt(unit_t unit)
1027 {
1028         /* interrupt the loop */
1029         unit->interrupted = 1;
1030         xbt_os_sem_release(unit->sem);
1031 }
1032
1033 void 
1034 display_title(const char* description)
1035 {
1036         int i;
1037         char title[80];
1038         int len = strlen(description);
1039                 
1040         title[0]=' ';
1041                 
1042         for (i = 1; i < 79; i++)
1043                 title[i]='=';
1044                 
1045         title[i++]='\n';
1046         title[79]='\0';
1047         
1048         sprintf(title + 40 - (len + 4)/2, "[ %s ]",description);
1049         title[40 + (len + 5 ) / 2] = '=';
1050                 
1051         printf("\n%s\n",title); 
1052 }
1053
1054 void
1055 unit_verbose(unit_t unit)
1056 {
1057         int i, j, k;
1058         command_t command;
1059         unit_t include;
1060         unit_t suite;
1061         char* p;
1062         char title[MAX_PATH + 1] = {0};
1063         
1064         int number_of_tests = 0;                                                /* number of tests of a unit contained by this unit                                     */
1065         int number_of_failed_tests = 0;                                 /* number of failed test of a unit contained by this unit                       */
1066         int number_of_successeded_tests = 0;                    /* number of successeded tests of a unit contained by this unit         */
1067         int number_of_interrupted_tests = 0;                    /* number of interrupted tests of a unit contained by this unit         */
1068         
1069         int number_of_tests_of_suite = 0;                               /* number of tests of a suite contained by this unit                            */
1070         int number_of_interrupted_tests_of_suite = 0;   /* number of interrupted tests of a suite contained by this unit        */      
1071         int number_of_failed_tests_of_suite = 0;                /* number of failed tests of a suite contained by this unit                                     */
1072         int number_of_successeded_tests_of_suite = 0;   /* number of successeded tests of a suite contained by this                     */
1073         
1074         int number_of_units = 0;                                                /* number of units contained by a suite                                                         */
1075         int number_of_failed_units = 0;                                 /* number of failed units contained by a suite                                          */
1076         int number_of_successeded_units = 0;                    /* number of successeded units contained by a suite                                     */
1077         int number_of_interrupted_units = 0;                    /* number of interrupted units contained by a suite                                     */
1078         
1079         int total_of_tests = 0;                                                 /* total of the tests contained by this unit                                            */
1080         int total_of_failed_tests = 0;                                  /* total of failed tests contained by this unit                                         */
1081         int total_of_successeded_tests = 0;                     /* total of successeded tests contained by this unit                            */
1082         int total_of_interrupted_tests = 0;                             /* total of interrupted tests contained by this unit                            */
1083         
1084         int total_of_units = 0;                                                 /* total of units contained by this unit                                                        */
1085         int total_of_failed_units = 0;                                  /* total of failed units contained by this unit                                         */
1086         int total_of_successeded_units = 0;                             /* total of successeded units contained by this unit                            */
1087         int total_of_interrupted_units = 0;                             /* total of interrutped units contained by this unit                            */
1088         
1089         int total_of_suites = 0;                                                /* total of suites contained by this unit                                                       */
1090         int total_of_failed_suites = 0;                                 /* total of failed suites contained by this unit                                        */
1091         int total_of_successeded_suites = 0;                    /* total of successeded suites contained by this unit                           */ 
1092         int total_of_interrupted_suites = 0;                    /* total of interrupted suites contained by this unit                           */
1093         
1094         
1095         if(unit->description)
1096                 strcpy(title, unit->description);
1097         else
1098                 sprintf(title, "file : %s",unit->fstream->name);
1099                 
1100         if(unit->interrupted)
1101                 strcat(title, " (interrupted)");
1102                 
1103         display_title(title);
1104         
1105         number_of_tests = vector_get_size(unit->commands);
1106         
1107         
1108         /* tests */
1109         for(i = 0; i < number_of_tests; i++)
1110         {
1111                 command = vector_get_at(unit->commands, i);
1112                 
1113                 if(command->status == cs_interrupted)
1114                         number_of_interrupted_tests++;
1115                 else if(command->status == cs_failed)
1116                         number_of_failed_tests++;
1117                 else if(command->status == cs_successeded)
1118                         number_of_successeded_tests++;
1119                         
1120         }
1121         
1122         if(number_of_tests)
1123         {
1124                 asprintf(&p," Test(s): .........................................................................");
1125                         
1126                 p[70] = '\0';
1127                 printf("%s", p);
1128                 free(p);        
1129         
1130                 if(number_of_failed_tests > 0) 
1131                         printf(".. failed\n");
1132                 else if(number_of_interrupted_tests > 0) 
1133                         printf("interrupt\n");
1134                 else 
1135                         printf(".... ..ok\n"); 
1136         
1137         
1138                 for(i = 0; i < number_of_tests; i++)
1139                 {
1140                         command = vector_get_at(unit->commands, i);
1141                                 
1142                         printf("        %s: %s [%s]\n", 
1143                                 command->status == cs_interrupted ? "INTR  " 
1144                                 : command->status == cs_failed ? "FAILED" 
1145                                 : command->status == cs_successeded ? "PASS  " 
1146                                 : "UNKNWN",
1147                                 command->context->command_line, 
1148                                 command->context->line);
1149                                 
1150                         if(want_detail_summary)
1151                                 command_display_status(command);
1152                                 
1153                 }
1154         
1155                 printf(" =====================================================================%s\n",
1156                 number_of_failed_tests ? "== FAILED": number_of_interrupted_tests ? "==== INTR" : "====== OK");
1157                 
1158                 printf("    Summary: Test(s): %.0f%% ok (%d test(s): %d ok",
1159                 ((1-((double)number_of_failed_tests + (double)number_of_interrupted_tests)/(double)number_of_tests)*100.0),
1160                  number_of_tests, number_of_successeded_tests);
1161                 
1162                 if(number_of_failed_tests > 0)
1163                         printf(", %d failed", number_of_failed_tests);
1164                 
1165                 if(number_of_interrupted_tests > 0)
1166                         printf(", %d interrupted)", number_of_interrupted_tests);
1167                         
1168                  printf(")\n\n");
1169                                 
1170                 total_of_tests = number_of_tests;
1171                 total_of_failed_tests = number_of_failed_tests;
1172                 total_of_interrupted_tests = number_of_interrupted_tests;
1173                 total_of_successeded_tests = number_of_successeded_tests;
1174         }
1175         
1176         
1177         
1178         /* includes */
1179         
1180         total_of_failed_units = total_of_interrupted_units = total_of_successeded_units = 0;
1181         
1182         number_of_failed_units = number_of_successeded_units = number_of_interrupted_units = 0;
1183         
1184         number_of_units = vector_get_size(unit->includes);
1185         
1186         for(i = 0; i < number_of_units ; i++)
1187         {
1188                 include = vector_get_at(unit->includes, i);
1189                 
1190                 number_of_interrupted_tests = number_of_failed_tests = number_of_successeded_tests = 0;
1191                 
1192                 number_of_tests = vector_get_size(include->commands);
1193                 
1194                 for(j = 0; j < number_of_tests; j++)
1195                 {
1196                         command = vector_get_at(include->commands, j);
1197                         
1198                         if(command->status == cs_interrupted)
1199                                 number_of_interrupted_tests++;
1200                         else if(command->status == cs_failed)
1201                                 number_of_failed_tests++;
1202                         else if(command->status == cs_successeded)
1203                                 number_of_successeded_tests++;  
1204                 }
1205                 
1206                 asprintf(&p," Unit: %s ............................................................................", include->description ? include->description : include->fstream->name);
1207                         
1208                 p[70] = '\0';
1209                 printf("%s", p);
1210                 free(p);        
1211                 
1212                 
1213                 if(number_of_failed_tests > 0) 
1214                 {
1215                         total_of_failed_units++;
1216                         printf(".. failed\n");
1217                 }
1218                 else if(number_of_interrupted_tests > 0) 
1219                 {
1220                         total_of_interrupted_units++;
1221                         printf("interrupt\n");
1222                 }
1223                 else 
1224                 {
1225                         total_of_successeded_units++;
1226                         printf(".... ..ok\n"); 
1227                 }
1228                 
1229                 if(want_detail_summary)
1230                 {               
1231         
1232                         for(j = 0; j < vector_get_size(include->commands); j++)
1233                         {
1234                                 command = vector_get_at(include->commands, j);
1235                                 
1236                                 printf("        %s: %s [%s]\n", 
1237                                 command->status == cs_interrupted ? "INTR  " 
1238                                 : command->status == cs_failed ? "FAILED" 
1239                                 : command->status == cs_successeded ? "PASS  " 
1240                                 : "UNKNWN",
1241                                 command->context->command_line, 
1242                                 command->context->line);
1243                                 
1244                                 command_display_status(command);
1245                         }
1246                         
1247                                         
1248                 }
1249                 
1250                 printf(" =====================================================================%s\n",
1251                 number_of_failed_tests ? "== FAILED": number_of_interrupted_tests ? "==== INTR" : "====== OK");
1252         
1253                 
1254                 printf("    Summary: Test(s): %.0f%% ok (%d test(s): %d ok",
1255                 (number_of_tests ? (1-((double)number_of_failed_tests + (double)number_of_interrupted_tests)/(double)number_of_tests)*100.0 : 100.0),
1256                  number_of_tests, number_of_successeded_tests);
1257                 
1258                 if(number_of_failed_tests > 0)
1259                         printf(", %d failed", number_of_failed_tests);
1260                 
1261                 if(number_of_interrupted_tests > 0)
1262                         printf(", %d interrupted)", number_of_interrupted_tests);
1263                         
1264                  printf(")\n\n");       
1265                  
1266                 
1267                 total_of_tests += number_of_tests;
1268                 total_of_failed_tests += number_of_failed_tests;
1269                 total_of_interrupted_tests += number_of_interrupted_tests;
1270                 total_of_successeded_tests += number_of_successeded_tests;
1271         }
1272         
1273         /* suites */
1274         
1275         total_of_units = number_of_units;
1276         
1277         total_of_failed_suites = total_of_successeded_suites = total_of_interrupted_suites = 0;
1278         
1279         total_of_suites = vector_get_size(unit->suites);
1280         
1281         for(k = 0; k < total_of_suites; k++)
1282         {
1283                 suite = vector_get_at(unit->suites, k);
1284                 
1285                 display_title(suite->description);
1286                 
1287                 number_of_tests_of_suite = number_of_interrupted_tests_of_suite = number_of_failed_tests_of_suite = number_of_successeded_tests_of_suite = 0;
1288                 
1289                 number_of_interrupted_units = number_of_failed_units = number_of_successeded_units = 0;
1290                 
1291                 number_of_units = vector_get_size(suite->includes);
1292                 
1293                 for(i = 0; i < number_of_units; i++)
1294                 {
1295                         number_of_interrupted_tests = number_of_failed_tests = number_of_successeded_tests = 0;
1296                         
1297                         number_of_tests = vector_get_size(include->commands);
1298                         
1299                         for(j = 0; j < vector_get_size(include->commands); j++)
1300                         {
1301                                 command = vector_get_at(include->commands, j);
1302                                 
1303                                 if(command->status == cs_interrupted)
1304                                         number_of_interrupted_tests++;
1305                                 else if(command->status == cs_failed)
1306                                         number_of_failed_tests++;
1307                                 else if(command->status == cs_successeded)
1308                                         number_of_successeded_tests++;
1309                                         
1310                         }
1311                         
1312                         
1313                         include = vector_get_at(suite->includes, i);
1314                         asprintf(&p," Unit: %s ............................................................................", include->description ? include->description : include->fstream->name);
1315                         
1316                         p[70] = '\0';
1317                         printf("%s", p);
1318                         free(p);        
1319                 
1320                         if(number_of_failed_tests > 0) 
1321                         {
1322                                 number_of_failed_units++;
1323                                 printf(".. failed\n");
1324                         }
1325                         else if(number_of_interrupted_tests > 0) 
1326                         {
1327                                 number_of_interrupted_units++;
1328                                 printf("interrupt\n");
1329                         }
1330                         else 
1331                         {
1332                                 number_of_successeded_units++;
1333                                 printf(".... ..ok\n"); 
1334                         } 
1335                         
1336                         number_of_interrupted_tests_of_suite += number_of_interrupted_tests;
1337                         number_of_failed_tests_of_suite += number_of_failed_tests;
1338                         number_of_successeded_tests_of_suite += number_of_successeded_tests;
1339                         
1340                         number_of_tests_of_suite += number_of_tests;
1341                         
1342                         total_of_tests += number_of_tests;
1343                         total_of_failed_tests += number_of_failed_tests;
1344                         total_of_interrupted_tests += number_of_interrupted_tests;
1345                         total_of_successeded_tests += number_of_successeded_tests;
1346                         
1347                         if(want_detail_summary)
1348                         {
1349                                 for(j = 0; j < vector_get_size(include->commands); j++)
1350                                 {
1351                                         command = vector_get_at(include->commands, j);
1352                                         
1353                                         printf("        %s: %s [%s]\n", 
1354                                         command->status == cs_interrupted ? "INTR  " 
1355                                         : command->status == cs_failed ? "FAILED" 
1356                                         : command->status == cs_successeded ? "PASS  " 
1357                                         : "UNKNWN",
1358                                         command->context->command_line, 
1359                                         command->context->line);
1360                                         
1361                                         command_display_status(command);
1362                                                 
1363                                 }
1364                                 
1365                                 
1366                         }
1367                                 
1368                 }
1369                 
1370                 
1371                 
1372                 printf(" =====================================================================%s\n",
1373                 number_of_failed_tests_of_suite ? "== FAILED": number_of_interrupted_tests_of_suite ? "==== INTR" : "====== OK");
1374                 
1375                 if(number_of_failed_tests_of_suite > 0)
1376                         total_of_failed_suites++;
1377                 else if(number_of_interrupted_tests_of_suite)
1378                         total_of_interrupted_suites++;
1379                 else
1380                         total_of_successeded_suites++;
1381                         
1382                 total_of_failed_units += number_of_failed_units;
1383                 total_of_interrupted_units += number_of_interrupted_units;
1384                 total_of_successeded_units += number_of_successeded_units;
1385                         
1386                 total_of_units += number_of_units;
1387                 
1388                 printf("    Summary: Unit(s): %.0f%% ok (%d unit(s): %d ok",
1389                 (number_of_units ? (1-((double)number_of_failed_units + (double)number_of_interrupted_units)/(double)number_of_units)*100.0 : 100.0),
1390                  number_of_units, number_of_successeded_units);
1391                  
1392                 if(number_of_failed_units > 0)
1393                         printf(", %d failed", number_of_failed_units);
1394                 
1395                 if(number_of_interrupted_units > 0)
1396                         printf(", %d interrupted)", number_of_interrupted_units);
1397                         
1398                 printf(")\n");  
1399                 
1400                 printf("             Test(s): %.0f%% ok (%d test(s): %d ok",
1401                 (number_of_tests_of_suite ? (1-((double)number_of_failed_tests_of_suite + (double)number_of_interrupted_tests_of_suite)/(double)number_of_tests_of_suite)*100.0 : 100.0),
1402                 number_of_tests_of_suite, number_of_successeded_tests_of_suite);
1403                  
1404                 if(number_of_failed_tests_of_suite > 0)
1405                         printf(", %d failed", number_of_failed_tests_of_suite);
1406                 
1407                 if(number_of_interrupted_tests_of_suite > 0)
1408                         printf(", %d interrupted)", number_of_interrupted_tests_of_suite);
1409                         
1410                  printf(")\n\n");       
1411         }
1412         
1413         printf(" TOTAL : Suite(s): %.0f%% ok (%d suite(s): %d ok",
1414                 (total_of_suites ? (1-((double)total_of_failed_suites + (double)total_of_interrupted_suites)/(double)total_of_suites)*100.0 : 100.0),
1415                  total_of_suites, total_of_successeded_suites);
1416         
1417         if(total_of_failed_suites > 0)
1418                         printf(", %d failed", total_of_failed_suites);
1419                 
1420         if(total_of_interrupted_suites > 0)
1421                 printf(", %d interrupted)", total_of_interrupted_suites);
1422                 
1423         printf(")\n");  
1424         
1425         printf("         Unit(s):  %.0f%% ok (%d unit(s): %d ok",
1426                 (total_of_units ? (1-((double)total_of_failed_units + (double)total_of_interrupted_units)/(double)total_of_units)*100.0 : 100.0),
1427                  total_of_units, total_of_successeded_units);
1428         
1429         if(total_of_failed_units > 0)
1430                         printf(", %d failed", total_of_failed_units);
1431                 
1432         if(total_of_interrupted_units > 0)
1433                 printf(", %d interrupted)", total_of_interrupted_units);
1434                 
1435         printf(")\n");
1436         
1437         printf("         Test(s):  %.0f%% ok (%d test(s): %d ok",
1438                 (total_of_tests ? (1-((double)total_of_failed_tests + (double)total_of_interrupted_tests)/(double)total_of_tests)*100.0 : 100.0),
1439                  total_of_tests, total_of_successeded_tests); 
1440                  
1441         if(total_of_failed_tests > 0)
1442                         printf(", %d failed", total_of_failed_tests);
1443                 
1444         if(total_of_interrupted_tests > 0)
1445                 printf(", %d interrupted)", total_of_interrupted_tests);
1446                 
1447         printf(")\n\n");
1448         
1449         
1450         if(unit->interrupted)
1451                 unit->runner->total_of_interrupted_units++;
1452         else if(total_of_failed_tests > 0)
1453                 unit->runner->total_of_failed_units++;
1454         else
1455                 unit->runner->total_of_successeded_units++;
1456         
1457         
1458         unit->runner->total_of_tests += total_of_tests;
1459         unit->runner->total_of_failed_tests += total_of_failed_tests;
1460         unit->runner->total_of_successeded_tests += total_of_successeded_tests;
1461         unit->runner->total_of_interrupted_tests += total_of_interrupted_tests;
1462         
1463         
1464         unit->runner->total_of_units += total_of_units + 1;
1465         unit->runner->total_of_successeded_units += total_of_successeded_units;
1466         unit->runner->total_of_failed_units += total_of_failed_units;
1467         unit->runner->total_of_interrupted_units += total_of_interrupted_units;
1468         
1469         
1470         unit->runner->total_of_suites += total_of_suites;
1471         unit->runner->total_of_successeded_suites += total_of_successeded_suites;
1472         unit->runner->total_of_failed_suites += total_of_failed_suites;
1473         unit->runner->total_of_interrupted_suites += total_of_interrupted_suites;
1474         
1475         
1476         
1477 }
1478
1479
1480
1481
1482 void
1483 unit_handle_include(unit_t unit, context_t context, xbt_os_mutex_t mutex, const char* file_name, const char* description)
1484 {
1485         directory_t dir;
1486         char* prev_directory = NULL;
1487         fstream_t fstream = NULL;
1488         struct stat buffer = {0};
1489         
1490         if(!stat(file_name, &buffer) && S_ISREG(buffer.st_mode))
1491         {
1492                 /* the file is in the current directory */
1493                 
1494                 fstream = fstream_new(getcwd(NULL, 0), file_name);
1495                 fstream_open(fstream);
1496         }
1497         /* the file to include is not in the current directory, check if it is in a include directory */
1498         else
1499         {
1500                 prev_directory = getcwd(NULL, 0);
1501                 
1502                 vector_rewind(include_dirs);
1503                 
1504                 while((dir = vector_get(include_dirs)))
1505                 {
1506                         chdir(dir->name);
1507                         
1508                         if(!stat(file_name, &buffer) && S_ISREG(buffer.st_mode))
1509                         {
1510                                 fstream = fstream_new(dir->name, file_name);
1511                                 fstream_open(fstream);
1512                                 break;
1513                         }
1514                         
1515                         
1516                         vector_move_next(include_dirs);
1517                 }
1518                 
1519                 chdir(prev_directory);
1520                 free(prev_directory);
1521         }
1522         
1523         
1524         
1525         /* the file to include is not found handle the failure */
1526         if(!fstream)
1527         {
1528                 exit_code = EINCLUDENOTFOUND;
1529                 ERROR1("Include file %s not found",file_name);
1530                 unit_handle_failure(unit);
1531         }
1532         else
1533         {
1534                 
1535                 if(!unit->running_suite)
1536                 {/* it's the unit of a suite */
1537                         unit_t include = unit_new(unit->runner,unit->root, unit, fstream);
1538                         
1539                         include->mutex = unit->root->mutex;
1540                 
1541                         if(description)
1542                                 include->description = strdup(description);
1543                 
1544                         vector_push_back(unit->includes, include);
1545                 
1546                         fstream_parse(fstream, include, mutex);
1547                 }
1548                 else
1549                 {/* it's a include */
1550                         unit_t owner = vector_get_back(unit->suites);
1551                         unit_t include = unit_new(unit->runner,unit->root, owner, fstream);
1552                         
1553                         include->mutex = unit->root->mutex;
1554                         
1555                         if(description)
1556                                 include->description = strdup(description);
1557                 
1558                         vector_push_back(owner->includes, include);
1559                 
1560                         fstream_parse(fstream, include, mutex); 
1561                 }
1562         }
1563 }
1564
1565 void
1566 unit_handle_suite(unit_t unit, context_t context, xbt_os_mutex_t mutex, const char* description)
1567 {
1568         if(unit->running_suite)
1569         {
1570                 exit_code = ESYNTAX;
1571                 unit_handle_failure(unit);
1572         }
1573         else
1574         {
1575                 unit_t suite = unit_new(unit->runner, unit->root, unit, NULL);
1576                 suite->is_suite = 1;
1577                 suite->description = strdup(description);
1578                 vector_push_back(unit->suites, suite);
1579                 unit->running_suite = 1;
1580         }
1581 }
1582
1583 int
1584 unit_reset(unit_t unit)
1585 {
1586         fseek(unit->fstream->stream,0L, SEEK_SET);
1587         unit->parsed = 0;
1588         unit->number_of_commands = 0;
1589         
1590         return 0;
1591 }