Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
ac0ca354a892728808f996609792511459526cb3
[simgrid.git] / src / xbt / cunit.c
1 /* $Id$ */
2
3 /* cunit - A little C Unit facility                                         */
4
5 /* Copyright (c) 2005 Martin Quinson. All rights reserved.                  */
6
7 /* This program is free software; you can redistribute it and/or modify it
8  * under the terms of the license (GNU LGPL) which comes with this package. */
9
10 /* This is partially inspirated from the OSSP ts (Test Suite Library)       */
11
12 #include "portable.h"
13
14 #include "xbt/sysdep.h"    /* vasprintf */
15 #include "xbt/cunit.h"
16 #include "xbt/dynar.h"
17
18 /* collection of all suites */
19 static xbt_dynar_t _xbt_test_suites = NULL; 
20 /* global statistics */
21 static int _xbt_test_nb_tests = 0;
22 static int _xbt_test_test_failed = 0;
23 static int _xbt_test_test_ignore = 0;
24 static int _xbt_test_test_expect = 0;
25
26 static int _xbt_test_nb_units    = 0;
27 static int _xbt_test_unit_failed = 0;
28 static int _xbt_test_unit_ignore = 0;
29 static int _xbt_test_unit_disabled = 0;
30
31 static int _xbt_test_nb_suites    = 0;
32 static int _xbt_test_suite_failed = 0;
33 static int _xbt_test_suite_ignore = 0;
34 static int _xbt_test_suite_disabled = 0;
35
36 /* Context */
37 xbt_test_unit_t _xbt_test_current_unit = NULL;
38
39
40 /* test suite test log */
41 typedef struct s_xbt_test_log {
42   char              *text;
43   const char        *file;
44   int                line;
45 } *xbt_test_log_t;
46
47 static void xbt_test_log_dump(xbt_test_log_t log) {
48   if (log)
49     fprintf(stderr,"      log %p(%s:%d)=%s\n",log,log->file,log->line,log->text);
50   else
51     fprintf(stderr,"      log=NULL\n");    
52 }
53
54 /* test suite test check */
55 typedef struct s_xbt_test_test {
56   char        *title;
57   int          failed;
58   int          expected_failure;
59   int          ignored;
60   const char  *file;
61   int          line;
62   xbt_dynar_t  logs;
63 } *xbt_test_test_t;
64
65 static void xbt_test_test_dump(xbt_test_test_t test){
66   if (test) {
67     xbt_test_log_t log;
68     unsigned int it_log;
69     fprintf(stderr,"    test %p(%s:%d)=%s (%s)\n",
70             test,test->file,test->line,test->title,
71             test->failed?"failed":"not failed");
72     xbt_dynar_foreach(test->logs,it_log,log)
73       xbt_test_log_dump(log);
74   }
75   else
76     fprintf(stderr,"    test=NULL\n");     
77 }
78
79 /* test suite test unit */
80 struct s_xbt_test_unit {
81   int          enabled;
82   char        *name;
83   char        *title;
84   ts_test_cb_t func;
85   const char  *file;
86   int          line;
87   xbt_dynar_t  tests; /* of xbt_test_test_t*/
88
89   int nb_tests;
90   int test_failed,test_ignore,test_expect;
91 };
92
93 static void xbt_test_unit_dump(xbt_test_unit_t unit) {
94   if (unit) {
95     xbt_test_test_t test;
96     unsigned int it_test;
97     fprintf(stderr,"  UNIT %s: %s (%s)\n",
98             unit->name,unit->title,
99             (unit->enabled?"enabled":"disabled"));
100     if (unit->enabled)
101       xbt_dynar_foreach(unit->tests,it_test,test)
102         xbt_test_test_dump(test);
103   } else {
104     fprintf(stderr,"  unit=NULL\n");
105   }
106 }
107
108 /* test suite */
109 struct s_xbt_test_suite {
110   int         enabled;
111   const char *name;
112   char       *title;
113   xbt_dynar_t units; /* of xbt_test_unit_t */
114
115   int nb_tests,nb_units;
116   int test_failed,test_ignore,test_expect;
117   int unit_failed,unit_ignore,unit_disabled;
118 };
119
120 /* destroy test suite */
121 static void xbt_test_suite_free(void *s) {
122   xbt_test_suite_t suite = *(xbt_test_suite_t*) s;
123
124   if (suite == NULL)
125     return;
126   xbt_dynar_free(&suite->units);
127   free(suite->title);
128   free(suite);
129 }
130
131 static void xbt_test_unit_free(void *unit) {
132    xbt_test_unit_t u = *(xbt_test_unit_t*)unit;
133    /* name is static */
134    free(u->title);
135    xbt_dynar_free(&u->tests);
136    free(u);
137 }
138 static void xbt_test_test_free(void *test) {
139    xbt_test_test_t t = *(xbt_test_test_t*)test;
140    free(t->title);
141    xbt_dynar_free(&(t->logs));
142    free(t);
143 }
144 static void xbt_test_log_free(void *log) {
145   xbt_test_log_t l= *(xbt_test_log_t*) log;
146   free(l->text);
147   free(l);
148 }
149
150 /** @brief create test suite */
151 xbt_test_suite_t xbt_test_suite_new(const char *name, const char *fmt, ...) {
152   xbt_test_suite_t suite = xbt_new0(struct s_xbt_test_suite,1);
153   va_list ap;
154
155   if (!_xbt_test_suites) 
156     _xbt_test_suites = xbt_dynar_new(sizeof(xbt_test_suite_t),xbt_test_suite_free);
157
158   va_start(ap, fmt);
159   vasprintf(&suite->title,fmt, ap);
160   suite->units = xbt_dynar_new(sizeof(xbt_test_unit_t), &xbt_test_unit_free);
161   va_end(ap);
162   suite->name = name;
163   suite->enabled = 1;
164
165   xbt_dynar_push(_xbt_test_suites,&suite);
166
167   return suite;
168 }
169
170 /** @brief retrieve a testsuite from name, or create a new one */
171 xbt_test_suite_t xbt_test_suite_by_name(const char *name,const char *fmt, ...) {
172   xbt_test_suite_t suite;
173   unsigned int it_suite;
174
175   char *bufname;
176   va_list ap;
177
178   if (_xbt_test_suites)
179     xbt_dynar_foreach(_xbt_test_suites, it_suite, suite)
180       if (!strcmp(suite->name,name))
181         return suite;
182   
183   va_start(ap, fmt);
184   vasprintf(&bufname,fmt, ap);
185   va_end(ap);
186   suite = xbt_test_suite_new(name,bufname,NULL);
187   free(bufname);
188   
189   return suite;
190 }
191
192 void xbt_test_suite_dump(xbt_test_suite_t suite) {
193   if (suite) {
194     xbt_test_unit_t unit;
195     unsigned int it_unit;
196     fprintf(stderr,"TESTSUITE %s: %s (%s)\n",
197             suite->name, suite->title,
198             suite->enabled?"enabled":"disabled");
199     if (suite->enabled)
200       xbt_dynar_foreach(suite->units,it_unit,unit)
201         xbt_test_unit_dump(unit);
202   } else {
203     fprintf(stderr,"TESTSUITE IS NULL!\n");
204   }
205 }
206
207 /* add test case to test suite */
208 void xbt_test_suite_push(xbt_test_suite_t suite, const char *name, ts_test_cb_t func, const char *fmt, ...) {
209   xbt_test_unit_t unit;
210   va_list ap;
211   
212   xbt_assert(suite);
213   xbt_assert(func);
214   xbt_assert(fmt);
215
216   unit = xbt_new0(struct s_xbt_test_unit,1);
217   va_start(ap, fmt);
218   vasprintf(&unit->title, fmt, ap);
219   va_end(ap);
220   unit->name = (char*)name;
221   unit->func = func;
222   unit->file = NULL;
223   unit->line = 0;
224   unit->enabled = 1;
225   unit->tests = xbt_dynar_new(sizeof(xbt_test_test_t), xbt_test_test_free);
226   
227   xbt_dynar_push(suite->units, &unit);
228   return;
229 }
230
231 /* run test one suite */
232 static int xbt_test_suite_run(xbt_test_suite_t suite) {
233   xbt_test_unit_t unit;
234   xbt_test_test_t test;
235   xbt_test_log_t log;
236
237   const char *file;
238   int line;
239   char *cp;
240   unsigned int it_unit,it_test,it_log;
241
242   int first=1; /* for result pretty printing */
243
244   if (suite == NULL)
245     return 0;
246
247   /* suite title pretty-printing */
248   {
249     char suite_title[80];
250     int suite_len=strlen(suite->title);
251     int i;
252
253     xbt_assert2(suite_len<68,"suite title \"%s\" too long (%d should be less than 68",
254                 suite->title,suite_len);
255     
256     suite_title[0]=' ';
257     for (i=1;i<79;i++)
258       suite_title[i]='=';
259     suite_title[i++]='\n';
260     suite_title[79]='\0';
261
262     sprintf(suite_title + 40 - (suite_len+4)/2, "[ %s ]", suite->title);
263     suite_title[40 + (suite_len+5)/2] = '=';
264     if (!suite->enabled) 
265       sprintf(suite_title+ 70," DISABLED ");
266     fprintf(stderr, "\n%s\n",suite_title);
267   }
268
269   if (suite->enabled) { 
270     /* iterate through all tests */
271     xbt_dynar_foreach(suite->units, it_unit, unit) {
272       /* init unit case counters */
273       unit->nb_tests = 0;
274       unit->test_ignore = 0;
275       unit->test_failed = 0;
276       unit->test_expect = 0;
277       
278       /* display unit title */
279       asprintf(&cp," Unit: %s ......................................"
280                "......................................", unit->title);
281       cp[70] = '\0';
282       fprintf(stderr, "%s", cp);
283       free(cp);
284       
285       /* run the test case function */
286       _xbt_test_current_unit = unit;
287       if (unit->enabled)
288         unit->func();
289       
290       /* iterate through all performed tests to determine status */
291       xbt_dynar_foreach(unit->tests,it_test, test) {
292         if (test->ignored) {
293           unit->test_ignore++;
294         } else {
295           unit->nb_tests++;
296           
297           if ( test->failed && !test->expected_failure) unit->test_failed++;
298           if (!test->failed &&  test->expected_failure) unit->test_failed++;
299           if (test->expected_failure)
300             unit->test_expect++;
301         }
302       }
303     
304     
305       /* Display whether this unit went well */
306       if (unit->test_failed > 0 || unit->test_expect) {
307         /* some tests failed (or were supposed to), so do detailed reporting of test case */
308         if (unit->test_failed > 0) {
309           fprintf(stderr, ".. failed\n");
310         } else if (unit->nb_tests) {
311           fprintf(stderr, "...... ok\n"); /* successful, but show about expected */
312         } else {
313           fprintf(stderr, ".... skip\n"); /* shouldn't happen, but I'm a bit lost with this logic */
314         }
315         xbt_dynar_foreach(unit->tests,it_test, test) {
316           file = (test->file != NULL ? test->file : unit->file);
317           line = (test->line != 0    ? test->line : unit->line);
318           fprintf(stderr, "      %s: %s [%s:%d]\n", 
319                   (test->ignored?" SKIP":(test->expected_failure?(test->failed?"EFAIL":"EPASS"):
320                                           (test->failed?" FAIL":" PASS"))),
321                   test->title, file, line);
322           
323           if  ( (test->expected_failure && !test->failed) || (!test->expected_failure && test->failed) ) {
324              xbt_dynar_foreach(test->logs,it_log,log) {
325                 file = (log->file != NULL ? log->file : file);
326                 line = (log->line != 0    ? log->line : line);
327                 fprintf(stderr, "             %s:%d: %s\n", 
328                         file, line,log->text);
329                 
330              }
331           }
332         }
333         fprintf(stderr, "    Summary: %d of %d tests failed",unit->test_failed, unit->nb_tests);
334         if (unit->test_ignore) {
335           fprintf(stderr," (%d tests ignored)\n",unit->test_ignore);
336         } else {
337           fprintf(stderr,"\n");
338         }
339         
340       } else if (!unit->enabled) {
341         fprintf(stderr, " disabled\n"); /* no test were run */
342       } else if (unit->nb_tests) {
343         fprintf(stderr, "...... ok\n"); /* successful */
344       } else  {
345         fprintf(stderr, ".... skip\n"); /* no test were run */
346       }
347       
348       /* Accumulate test counts into the suite */
349       suite->nb_tests      += unit->nb_tests;
350       suite->test_failed   += unit->test_failed;
351       suite->test_ignore   += unit->test_ignore;
352       suite->test_expect   += unit->test_expect;
353       
354       _xbt_test_nb_tests      += unit->nb_tests;
355       _xbt_test_test_failed   += unit->test_failed;
356       _xbt_test_test_ignore   += unit->test_ignore;
357       _xbt_test_test_expect   += unit->test_expect;  
358       
359       /* What's the conclusion of this test anyway? */
360       if (unit->nb_tests) {
361         suite->nb_units++;
362         if (unit->test_failed)
363           suite->unit_failed++;
364       } else if (!unit->enabled) {
365         suite->unit_disabled++;
366       } else {
367         suite->unit_ignore++;
368       }
369     }
370   }
371   _xbt_test_nb_units      += suite->nb_units;
372   _xbt_test_unit_failed   += suite->unit_failed;
373   _xbt_test_unit_ignore   += suite->unit_ignore;
374   _xbt_test_unit_disabled += suite->unit_disabled;
375
376   if (suite->nb_units) {
377     _xbt_test_nb_suites++;
378     if (suite->test_failed)
379       _xbt_test_suite_failed++;
380   } else if (!suite->enabled) {
381     _xbt_test_suite_disabled++;
382   } else {
383     _xbt_test_suite_ignore++;
384   }
385
386   
387   /* print test suite summary */
388   if (suite->enabled) {
389
390     fprintf(stderr,
391             " =====================================================================%s\n",
392             (suite->nb_units ? (suite->unit_failed   ? "== FAILED":"====== OK")
393                              : (suite->unit_disabled ? " DISABLED":"==== SKIP")));
394     fprintf(stderr, " Summary: Units: %.0f%% ok (%d units: ", 
395             suite->nb_units?((1-(double)suite->unit_failed/(double)suite->nb_units)*100.0):100.0,
396             suite->nb_units);
397     
398     if (suite->nb_units != suite->unit_failed) {
399       fprintf(stderr, "%s%d ok",(first?"":", "),suite->nb_units - suite->unit_failed);
400       first = 0;
401     }
402     if (suite->unit_failed) {
403       fprintf(stderr, "%s%d failed",(first?"":", "),suite->unit_failed);
404       first = 0;
405     }
406     if (suite->unit_ignore) {
407       fprintf(stderr, "%s%d ignored",(first?"":", "),suite->unit_ignore);
408       first = 0;
409     }
410     if (suite->unit_disabled) {
411       fprintf(stderr, "%s%d disabled",(first?"":", "),suite->unit_disabled);
412       first = 0;
413     }
414     fprintf(stderr,")\n          Tests: %.0f%% ok (%d tests: ",
415             suite->nb_tests?((1-(double)suite->test_failed/(double)suite->nb_tests)*100.0):100.0,
416             suite->nb_tests);
417
418     first=1;
419     if (suite->nb_tests != suite->test_failed) {
420       fprintf(stderr, "%s%d ok",(first?"":", "),suite->nb_tests - suite->test_failed);
421       first = 0;
422     }
423     if (suite->test_failed) {
424       fprintf(stderr, "%s%d failed",(first?"":", "),suite->test_failed);
425       first = 0;
426     }
427     if (suite->test_ignore) {
428       fprintf(stderr, "%s%d ignored",(first?"":"; "),suite->test_ignore);
429       first = 0;
430     }
431     if (suite->test_expect) {
432       fprintf(stderr, "%s%d expected to fail",(first?"":"; "),suite->test_expect);
433       first = 0;
434     }
435     fprintf(stderr,")\n");
436   }
437   return suite->unit_failed;
438 }
439
440 static void apply_selection(char *selection) {
441   /* for the parsing */
442   char *sel=selection;
443   char *p;
444   int done = 0;
445   char dir[1024]; /* the directive */
446   /* iterators */
447   unsigned int it_suite;
448   xbt_test_suite_t suite;
449   xbt_test_unit_t unit;
450   unsigned int it_unit;
451
452   char suitename[512];
453   char unitname[512];
454
455   if (!selection || selection[0] == '\0')
456     return;
457
458   /*printf("Test selection: %s\n", selection);*/
459
460   /* First apply the selection */
461   while (!done) {
462     int enabling = 1;
463
464     p=strchr(sel,',');
465     if (p) {
466       strncpy(dir,sel,p-sel);
467       dir[p-sel]='\0';
468       sel=p+1;
469     } else {
470       strcpy(dir, sel);
471       done=1;
472     }
473     
474     if (dir[0] == '-') {
475       enabling = 0;
476       memmove(dir,dir+1,strlen(dir));
477     }
478     if (dir[0] == '+') {
479       enabling = 1;
480       memmove(dir,dir+1,strlen(dir));
481     }
482
483     p =strchr(dir,':');
484     if (p) {
485       strcpy(unitname,p+1); 
486       strncpy(suitename,dir,p-dir);
487       suitename[p-dir]='\0';
488     } else {
489       strcpy(suitename,dir);
490       unitname[0] = '\0';
491     }
492     /*fprintf(stderr,"Seen %s (%s; suite=%s; unit=%s)\n",
493       dir,enabling?"enabling":"disabling", suitename, unitname);*/
494
495     /* Deal with the specific case of 'all' pseudo serie */
496     if (!strcmp("all",suitename)) {
497       if (unitname[0]!='\0') {
498         fprintf(stderr,"The 'all' pseudo-suite does not accept any unit specification\n");
499         exit(1);
500       }
501
502       xbt_dynar_foreach(_xbt_test_suites,it_suite,suite) {
503         xbt_dynar_foreach(suite->units,it_unit,unit) {
504           unit->enabled = enabling;
505         }
506         suite->enabled = enabling;
507       }
508     } else {
509       unsigned int it;
510       for (it=0; it< xbt_dynar_length(_xbt_test_suites); it++) {
511         xbt_test_suite_t thissuite=xbt_dynar_get_as(_xbt_test_suites,it,xbt_test_suite_t);
512         if (!strcmp(suitename,thissuite->name)) {
513           /* Do not disable the whole suite when we just want to disable a child */
514           if (enabling || (unitname[0]=='\0'))
515             thissuite->enabled = enabling;
516
517           if (unitname[0]=='\0') {
518             xbt_dynar_foreach(thissuite->units,it_unit,unit){
519               unit->enabled = enabling;
520             }
521           } else { /* act on one child only */
522             unsigned int it2_unit;
523             /* search it, first (we won't reuse it for external loop which gets broken) */
524             for (it2_unit=0; it2_unit< xbt_dynar_length(thissuite->units); it2_unit++) {
525               xbt_test_unit_t thisunit=xbt_dynar_get_as(thissuite->units,it2_unit,xbt_test_unit_t);
526               if (!strcmp(thisunit->name,unitname)) {
527                 thisunit->enabled = enabling;
528                 break;
529               }
530             } /* search relevant unit */
531             if (it2_unit==xbt_dynar_length(thissuite->units)) {
532               fprintf(stderr,"Suite '%s' has no unit of name '%s'. Cannot apply the selection\n",
533                       suitename,unitname);
534               exit(1);
535             }
536           } /* act on childs (either all or one) */
537
538           break;/* found the relevant serie. We are happy */
539         }
540       } /* search relevant series */
541       if (it==xbt_dynar_length(_xbt_test_suites)) {
542         fprintf(stderr,"No suite of name '%s' found. Cannot apply the selection\n",suitename);
543         exit(1);
544       }
545     }
546
547   }
548 }
549
550 void xbt_test_dump(char *selection) {
551   apply_selection(selection);
552
553   if (_xbt_test_suites) {
554     unsigned int it_suite;
555     xbt_test_suite_t suite;
556
557     xbt_dynar_foreach(_xbt_test_suites,it_suite,suite) 
558       xbt_test_suite_dump(suite);
559   } else {
560     printf(" No suite defined.");
561   }
562 }
563
564 int xbt_test_run(char *selection) {
565   apply_selection(selection);
566
567   if (_xbt_test_suites) {
568     unsigned int it_suite;
569     xbt_test_suite_t suite;
570     int first=1;
571     
572     /* Run all the suites */
573     xbt_dynar_foreach(_xbt_test_suites,it_suite,suite) 
574       xbt_test_suite_run(suite);
575
576     /* Display some more statistics */
577     fprintf(stderr,"\n\n TOTAL: Suites: %.0f%% ok (%d suites: ",
578             _xbt_test_nb_suites
579               ? ((1-(double)_xbt_test_suite_failed/(double)_xbt_test_nb_suites)*100.0)
580               : 100.0,
581             _xbt_test_nb_suites);
582     if (_xbt_test_nb_suites != _xbt_test_suite_failed) {
583       fprintf(stderr, "%d ok",_xbt_test_nb_suites - _xbt_test_suite_failed);
584       first = 0;
585     }
586     if (_xbt_test_suite_failed) {
587       fprintf(stderr, "%s%d failed",(first?"":", "),_xbt_test_suite_failed);
588       first = 0;
589     }
590     
591     if (_xbt_test_suite_ignore) {
592       fprintf(stderr, "%s%d ignored",(first?"":", "),_xbt_test_suite_ignore);
593       first = 0;
594     }
595     fprintf(stderr,")\n        Units:  %.0f%% ok (%d units: ",
596             _xbt_test_nb_units?((1-(double)_xbt_test_unit_failed/(double)_xbt_test_nb_units)*100.0):100.0,
597             _xbt_test_nb_units);
598     first=1;
599     if (_xbt_test_nb_units != _xbt_test_unit_failed) {
600       fprintf(stderr, "%s%d ok",(first?"":", "),_xbt_test_nb_units - _xbt_test_unit_failed);
601       first = 0;
602     }
603     if (_xbt_test_unit_failed) {
604       fprintf(stderr, "%s%d failed",(first?"":", "),_xbt_test_unit_failed);
605       first = 0;
606     }
607     if (_xbt_test_unit_ignore) {
608       fprintf(stderr, "%s%d ignored",(first?"":", "),_xbt_test_unit_ignore);
609       first = 0;
610     }
611     fprintf(stderr,")\n        Tests:  %.0f%% ok (%d tests: ",
612             _xbt_test_nb_tests?((1-(double)_xbt_test_test_failed/(double)_xbt_test_nb_tests)*100.0):100.0,
613             _xbt_test_nb_tests);
614     first=1;
615     if (_xbt_test_nb_tests != _xbt_test_test_failed) {
616       fprintf(stderr, "%s%d ok",(first?"":", "),_xbt_test_nb_tests - _xbt_test_test_failed);
617       first = 0;
618     }
619     if (_xbt_test_test_failed) {
620       fprintf(stderr, "%s%d failed",(first?"":", "),_xbt_test_test_failed);
621       first = 0;
622     }
623     if (_xbt_test_test_ignore) {
624       fprintf(stderr, "%s%d ignored",(first?"":", "),_xbt_test_test_ignore);
625       first = 0;
626     }
627     if (_xbt_test_test_expect) {
628       fprintf(stderr, "%s%d expected to fail",(first?"":", "),_xbt_test_test_expect);
629     }
630     
631     fprintf(stderr,")\n");
632   } else {
633     fprintf(stderr,"No unit to run!\n");
634     _xbt_test_unit_failed++;
635   }
636   return _xbt_test_unit_failed;
637 }
638 void xbt_test_exit(void) {
639    xbt_dynar_free(&_xbt_test_suites);
640 }
641
642 /* annotate test case with test */
643 void _xbt_test_add(const char*file,int line, const char *fmt, ...) {
644   xbt_test_unit_t unit=_xbt_test_current_unit;
645   xbt_test_test_t test;
646   va_list ap;
647   
648   xbt_assert(unit);
649   xbt_assert(fmt);
650
651   test = xbt_new0(struct s_xbt_test_test,1);
652   va_start(ap, fmt);
653   vasprintf(&test->title, fmt, ap);
654   va_end(ap);
655   test->failed = 0;
656   test->expected_failure = 0;
657   test->ignored = 0;
658   test->file = file;
659   test->line = line;
660   test->logs = xbt_dynar_new(sizeof(xbt_test_log_t),xbt_test_log_free);
661   xbt_dynar_push(unit->tests,&test);
662   return;
663 }
664
665 /* annotate test case with log message and failure */
666 void _xbt_test_fail(const char*file,int line,const char *fmt, ...) {
667   xbt_test_unit_t unit = _xbt_test_current_unit;
668   xbt_test_test_t test;
669   xbt_test_log_t log;
670   va_list ap;
671   
672   xbt_assert(unit);
673   xbt_assert(fmt);
674
675   xbt_assert1(xbt_dynar_length(_xbt_test_current_unit->tests),
676               "Test failed even before being declared (broken unit: %s)",
677               unit->title);
678
679   log = xbt_new(struct s_xbt_test_log,1);
680   va_start(ap, fmt);
681   vasprintf(&log->text,fmt, ap);
682   va_end(ap);
683   log->file = file;
684   log->line = line;
685
686   test = xbt_dynar_getlast_as(unit->tests, xbt_test_test_t);
687   xbt_dynar_push(test->logs, &log);
688
689   test->failed = 1;
690 }
691
692 void xbt_test_exception(xbt_ex_t e) {
693   _xbt_test_fail(e.file,e.line,"Exception %s raised: %s",xbt_ex_catname(e.category),e.msg);
694 }
695
696 void xbt_test_expect_failure(void) {
697   xbt_test_test_t test;
698   xbt_assert1(xbt_dynar_length(_xbt_test_current_unit->tests),
699               "Cannot expect the failure of a test before declaring it (broken unit: %s)",
700               _xbt_test_current_unit->title);
701   test = xbt_dynar_getlast_as(_xbt_test_current_unit->tests,xbt_test_test_t);
702   test->expected_failure = 1;
703 }
704 void xbt_test_skip(void) {
705   xbt_test_test_t test;
706
707   xbt_assert1(xbt_dynar_length(_xbt_test_current_unit->tests),
708               "Test skiped even before being declared (broken unit: %s)",
709               _xbt_test_current_unit->title);
710
711   test = xbt_dynar_getlast_as(_xbt_test_current_unit->tests,
712                               xbt_test_test_t);
713   test->ignored = 1;
714 }
715
716 /* annotate test case with log message only */
717 void _xbt_test_log(const char*file,int line,const char *fmt, ...) {
718   xbt_test_unit_t unit=_xbt_test_current_unit;
719   xbt_test_test_t test;
720   xbt_test_log_t log;
721   va_list ap;
722
723   xbt_assert(unit);
724   xbt_assert(fmt);
725
726   xbt_assert1(xbt_dynar_length(_xbt_test_current_unit->tests),
727               "Test logged into even before being declared (broken test unit: %s)",unit->title);
728
729   log = xbt_new(struct s_xbt_test_log,1);
730   va_start(ap, fmt);
731   vasprintf(&log->text, fmt, ap);
732   va_end(ap);
733   log->file = file;
734   log->line = line;
735
736   test = xbt_dynar_getlast_as(unit->tests,xbt_test_test_t);
737   xbt_dynar_push(test->logs, &log);
738 }
739
740
741
742
743 #ifdef SIMGRID_TEST
744
745 XBT_TEST_SUITE("cunit","Testsuite mechanism autotest");
746
747 XBT_TEST_UNIT("expect",test_expected_failure,"expected failures") {
748     xbt_test_add0("Skipped test");
749     xbt_test_skip(); 
750
751     xbt_test_add2("%s %s","EXPECTED","FAILURE");
752     xbt_test_expect_failure();
753     xbt_test_log2("%s %s","Test","log");
754     xbt_test_fail0("EXPECTED FAILURE");
755 }
756
757 #endif /* SIMGRID_TEST */