00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044 #if !defined(FCT_INCLUDED__IMB)
00045 #define FCT_INCLUDED__IMB
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056 #if !defined(FCT_DEFAULT_LOGGER)
00057 # define FCT_DEFAULT_LOGGER "standard"
00058 #endif
00059
00060 #define FCT_VERSION_MAJOR 1
00061 #define FCT_VERSION_MINOR 6
00062 #define FCT_VERSION_MICRO 1
00063
00064 #define _FCT_QUOTEME(x) #x
00065 #define FCT_QUOTEME(x) _FCT_QUOTEME(x)
00066
00067 #define FCT_VERSION_STR (FCT_QUOTEME(FCT_VERSION_MAJOR) "."\
00068 FCT_QUOTEME(FCT_VERSION_MINOR) "."\
00069 FCT_QUOTEME(FCT_VERSION_MICRO))
00070
00071 #include <string.h>
00072 #include <assert.h>
00073 #include <stdarg.h>
00074 #include <stdlib.h>
00075 #include <stdio.h>
00076 #include <time.h>
00077 #include <float.h>
00078 #include <math.h>
00079 #include <ctype.h>
00080
00081 #define FCT_MAX_NAME 256
00082 #define FCT_MAX_LOG_LINE 256
00083
00084 #define nbool_t int
00085 #define FCT_TRUE 1
00086 #define FCT_FALSE 0
00087
00088 #define FCTMIN(x, y) ( x < y) ? (x) : (y)
00089
00090 #ifndef __INTEL_COMPILER
00091
00092 #define FCT_ASSERT(expr) assert(expr)
00093 #else
00094
00095 #define FCT_ASSERT(expr) do { \
00096 _Pragma("warning(push,disable:279)"); \
00097 assert(expr); \
00098 _Pragma("warning(pop)"); \
00099 } while (0)
00100 #endif
00101
00102 #if defined(__cplusplus)
00103 #define FCT_EXTERN_C extern "C"
00104 #else
00105 #define FCT_EXTERN_C
00106 #endif
00107
00108
00109
00110
00111 typedef struct _fct_logger_evt_t fct_logger_evt_t;
00112 typedef struct _fct_logger_i fct_logger_i;
00113 typedef struct _fct_logger_types_t fct_logger_types_t;
00114 typedef struct _fct_standard_logger_t fct_standard_logger_t;
00115 typedef struct _fct_junit_logger_t fct_junit_logger_t;
00116 typedef struct _fct_minimal_logger_t fct_minimal_logger_t;
00117 typedef struct _fctchk_t fctchk_t;
00118 typedef struct _fct_test_t fct_test_t;
00119 typedef struct _fct_ts_t fct_ts_t;
00120 typedef struct _fctkern_t fctkern_t;
00121
00122
00123 static fct_logger_i*
00124 fct_standard_logger_new(void);
00125
00126 static fct_logger_i*
00127 fct_minimal_logger_new(void);
00128
00129 static fct_junit_logger_t *
00130 fct_junit_logger_new(void);
00131
00132 static void
00133 fct_logger__del(fct_logger_i *logger);
00134
00135 static void
00136 fct_logger__on_chk(fct_logger_i *self, fctchk_t const *chk);
00137
00138 static void
00139 fct_logger__on_test_start(fct_logger_i *logger, fct_test_t const *test);
00140
00141 static void
00142 fct_logger__on_test_end(fct_logger_i *logger, fct_test_t *test);
00143
00144 static void
00145 fct_logger__on_test_suite_start(fct_logger_i *logger, fct_ts_t const *ts);
00146
00147 static void
00148 fct_logger__on_test_suite_end(fct_logger_i *logger, fct_ts_t const *ts);
00149
00150 static void
00151 fct_logger__on_test_suite_skip(
00152 fct_logger_i *logger,
00153 char const *condition,
00154 char const *name
00155 );
00156
00157 static void
00158 fct_logger__on_test_skip(
00159 fct_logger_i *logger,
00160 char const *condition,
00161 char const *name
00162 );
00163
00164
00165 static void
00166 fct_logger__on_warn(fct_logger_i *logger, char const *warn);
00167
00168
00169
00170
00171 #define fct_pass()
00172
00173 #define fct_unused(x) (void)(x)
00174
00175
00176
00177
00178 #if defined(FCT_CONF_UNWIND)
00179 # define _fct_cmt(string) {char*_=string;}
00180 #else
00181 # define _fct_cmt(string)
00182 #endif
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192 #define FCT_PIPE_RESERVE_BYTES_DEFAULT 512
00193 static int fct_stdout_pipe[2];
00194 static int fct_stderr_pipe[2];
00195 static int fct_saved_stdout;
00196 static int fct_saved_stderr;
00197
00198
00199
00200 #if defined(WIN32)
00201 # include <io.h>
00202 # include <fcntl.h>
00203 # define _fct_pipe(_PFDS_) \
00204 _pipe((_PFDS_), FCT_PIPE_RESERVE_BYTES_DEFAULT, _O_TEXT)
00205 # define _fct_dup _dup
00206 # define _fct_dup2 _dup2
00207 # define _fct_close _close
00208 # define _fct_read _read
00209
00210 # define STDOUT_FILENO 1
00211 # define STDERR_FILENO 2
00212 #else
00213 # include <unistd.h>
00214 # define _fct_pipe pipe
00215 # define _fct_dup dup
00216 # define _fct_dup2 dup2
00217 # define _fct_close close
00218 # define _fct_read read
00219 #endif
00220
00221
00222
00223
00224 static void
00225 fct_switch_std_to_buffer(int std_pipe[2], FILE *out, int fileno_, int *save_handle)
00226 {
00227 fflush(out);
00228 *save_handle = _fct_dup(fileno_);
00229 if ( _fct_pipe(std_pipe) != 0 )
00230 {
00231 exit(1);
00232 }
00233 _fct_dup2(std_pipe[1], fileno_);
00234 _fct_close(std_pipe[1]);
00235 }
00236
00237
00238 static void
00239 fct_switch_std_to_std(FILE *out, int fileno_, int save_handle)
00240 {
00241 fflush(out);
00242 _fct_dup2(save_handle, fileno_);
00243 }
00244
00245
00246 #define FCT_SWITCH_STDOUT_TO_BUFFER() \
00247 fct_switch_std_to_buffer(fct_stdout_pipe, stdout, STDOUT_FILENO, &fct_saved_stdout)
00248 #define FCT_SWITCH_STDOUT_TO_STDOUT() \
00249 fct_switch_std_to_std(stdout, STDOUT_FILENO, fct_saved_stdout)
00250 #define FCT_SWITCH_STDERR_TO_BUFFER() \
00251 fct_switch_std_to_buffer(fct_stderr_pipe, stderr, STDERR_FILENO, &fct_saved_stderr)
00252 #define FCT_SWITCH_STDERR_TO_STDERR() \
00253 fct_switch_std_to_std(stderr, STDERR_FILENO, fct_saved_stderr)
00254
00255
00256
00257
00258 static void
00259 fctstr_safe_cpy(char *dst, char const *src, size_t num)
00260 {
00261 FCT_ASSERT( dst != NULL );
00262 FCT_ASSERT( src != NULL );
00263 FCT_ASSERT( num > 0 );
00264 #if defined(WIN32) && _MSC_VER >= 1400
00265 strncpy_s(dst, num, src, _TRUNCATE);
00266 #else
00267 strncpy(dst, src, num);
00268 #endif
00269 dst[num-1] = '\0';
00270 }
00271
00272
00273 static int
00274 fct_vsnprintf(char *buffer,
00275 size_t buffer_len,
00276 char const *format,
00277 va_list args)
00278 {
00279 int count =0;
00280
00281
00282
00283 #if defined(_MSC_VER) && (_MSC_VER < 1400)
00284 count = _vsnprintf(buffer, buffer_len, format, args);
00285 #elif defined(_MSC_VER) && (_MSC_VER >= 1400)
00286 count = vsnprintf_s(buffer, buffer_len, _TRUNCATE, format, args);
00287 #else
00288 count = vsnprintf(buffer, buffer_len, format, args);
00289 #endif
00290 return count;
00291 }
00292
00293
00294
00295 static int
00296 fct_snprintf(char *buffer, size_t buffer_len, char const *format, ...)
00297 {
00298 int count =0;
00299 va_list args;
00300 va_start(args, format);
00301 count =fct_vsnprintf(buffer, buffer_len, format, args);
00302 va_end(args);
00303 return count;
00304 }
00305
00306
00307
00308
00309 static char*
00310 fctstr_clone(char const *s)
00311 {
00312 char *k =NULL;
00313 size_t klen =0;
00314 FCT_ASSERT( s != NULL && "invalid arg");
00315 klen = strlen(s)+1;
00316 k = (char*)malloc(sizeof(char)*klen+1);
00317 fctstr_safe_cpy(k, s, klen);
00318 return k;
00319 }
00320
00321
00322
00323 static char*
00324 fctstr_clone_lower(char const *s)
00325 {
00326 char *k =NULL;
00327 size_t klen =0;
00328 size_t i;
00329 if ( s == NULL )
00330 {
00331 return NULL;
00332 }
00333 klen = strlen(s)+1;
00334 k = (char*)malloc(sizeof(char)*klen+1);
00335 for ( i=0; i != klen; ++i )
00336 {
00337 k[i] = (char)tolower(s[i]);
00338 }
00339 return k;
00340 }
00341
00342
00343
00344
00345
00346
00347 static nbool_t
00348 fct_filter_pass(char const *prefix, char const *test_str)
00349 {
00350 nbool_t is_match = FCT_FALSE;
00351 char const *prefix_p;
00352 char const *test_str_p;
00353
00354
00355 FCT_ASSERT( test_str != NULL );
00356
00357
00358 if ( prefix == NULL || prefix[0] == '\0' )
00359 {
00360 return FCT_TRUE;
00361 }
00362
00363
00364
00365 for ( prefix_p = prefix, test_str_p = test_str;
00366 *prefix_p != '\0' && *test_str_p != '\0';
00367 ++prefix_p, ++test_str_p )
00368 {
00369 is_match = *prefix_p == *test_str_p;
00370 if ( !is_match )
00371 {
00372 break;
00373 }
00374 }
00375
00376
00377
00378
00379
00380 if ( *test_str_p == '\0' && *prefix_p != '\0' )
00381 {
00382 return FCT_FALSE;
00383 }
00384
00385
00386
00387
00388 return is_match;
00389 }
00390
00391
00392
00393
00394
00395 static int
00396 fctstr_eq(char const *s1, char const *s2)
00397 {
00398 if ( s1 == s2 )
00399 {
00400 return 1;
00401 }
00402 if ( (s1 == NULL && s2 != NULL)
00403 || (s1 != NULL && s2 == NULL) )
00404 {
00405 return 0;
00406 }
00407 while (*s1 == *s2)
00408 {
00409 if (*s1 == '\0')
00410 return 1;
00411 s1++;
00412 s2++;
00413 }
00414
00415 return 0;
00416 }
00417
00418
00419 static int
00420 fctstr_ieq(char const *s1, char const *s2)
00421 {
00422 if ( s1 == s2 )
00423 {
00424 return 1;
00425 }
00426 if ( (s1 == NULL && s2 != NULL)
00427 || (s1 != NULL && s2 == NULL) )
00428 {
00429 return 0;
00430 }
00431 while (tolower(*s1) == tolower(*s2))
00432 {
00433 if (*s1 == '\0')
00434 return 1;
00435 s1++;
00436 s2++;
00437 }
00438
00439 return 0;
00440 }
00441
00442
00443
00444
00445
00446
00447 static int
00448 fctstr_incl(char const *str, char const *check_incl)
00449 {
00450 static char const *blank_s = "";
00451 char const *found = NULL;
00452 if ( str == NULL )
00453 {
00454 str = blank_s;
00455 }
00456 if ( check_incl == NULL )
00457 {
00458 check_incl = blank_s;
00459 }
00460 if ( str == check_incl )
00461 {
00462 return 1;
00463 }
00464 found = strstr(str, check_incl);
00465 return found != NULL;
00466 }
00467
00468
00469
00470 static int
00471 fctstr_iincl(char const *str, char const *check_incl)
00472 {
00473
00474
00475
00476 char *lstr = fctstr_clone_lower(str);
00477 char *lcheck_incl = fctstr_clone_lower(check_incl);
00478 int found = fctstr_incl(lstr, lcheck_incl);
00479 free(lstr);
00480 free(lcheck_incl);
00481 return found;
00482 }
00483
00484
00485
00486
00487 static int
00488 fctstr_startswith(char const *str, char const *check)
00489 {
00490 char const *sp;
00491 if ( str == NULL && check == NULL )
00492 {
00493 return 1;
00494 }
00495 else if ( ((str == NULL) && (check != NULL))
00496 || ((str != NULL) && (check == NULL)) )
00497 {
00498 return 0;
00499 }
00500 sp = strstr(str, check);
00501 return sp == str;
00502 }
00503
00504
00505
00506 static int
00507 fctstr_istartswith(char const *str, char const *check)
00508 {
00509
00510 char *istr = fctstr_clone_lower(str);
00511 char *icheck = fctstr_clone_lower(check);
00512
00513 int startswith = fctstr_startswith(istr, icheck);
00514 free(istr);
00515 free(icheck);
00516 return startswith;
00517 }
00518
00519
00520
00521
00522
00523 static int
00524 fctstr_endswith(char const *str, char const *check)
00525 {
00526 size_t check_i;
00527 size_t str_i;
00528 if ( str == NULL && check == NULL )
00529 {
00530 return 1;
00531 }
00532 else if ( ((str == NULL) && (check != NULL))
00533 || ((str != NULL) && (check == NULL)) )
00534 {
00535 return 0;
00536 }
00537 check_i = strlen(check);
00538 str_i = strlen(str);
00539 if ( str_i < check_i )
00540 {
00541 return 0;
00542 }
00543 for ( ; check_i != 0; --check_i, --str_i)
00544 {
00545 if ( str[str_i] != check[check_i] )
00546 {
00547 return 0;
00548 }
00549 }
00550
00551 return 1;
00552 }
00553
00554
00555 static int
00556 fctstr_iendswith(char const *str, char const *check)
00557 {
00558 size_t check_i;
00559 size_t str_i;
00560 if ( str == NULL && check == NULL )
00561 {
00562 return 1;
00563 }
00564 else if ( ((str == NULL) && (check != NULL))
00565 || ((str != NULL) && (check == NULL)) )
00566 {
00567 return 0;
00568 }
00569 check_i = strlen(check);
00570 str_i = strlen(str);
00571 if ( str_i < check_i )
00572 {
00573 return 0;
00574 }
00575 for ( ; check_i != 0; --check_i, --str_i)
00576 {
00577 if ( tolower(str[str_i]) != tolower(check[check_i]) )
00578 {
00579 return 0;
00580 }
00581 }
00582
00583 return 1;
00584 }
00585
00586
00587
00588
00589
00590
00591
00592
00593 #define FCT_DOTTED_MAX_LEN 256
00594 static void
00595 fct_dotted_line_start(size_t maxwidth, char const *startwith)
00596 {
00597 char line[FCT_DOTTED_MAX_LEN];
00598 size_t len =0;
00599 size_t line_len =0;
00600
00601 memset(line, '.', sizeof(char)*maxwidth);
00602 len = strlen(startwith);
00603 line_len = FCTMIN(maxwidth-1, len);
00604 memcpy(line, startwith, sizeof(char)*line_len);
00605 if ( len < maxwidth-1)
00606 {
00607 line[len] = ' ';
00608 }
00609 line[maxwidth-1] = '\0';
00610 fputs(line, stdout);
00611 }
00612
00613
00614 static void
00615 fct_dotted_line_end(char const *endswith)
00616 {
00617 printf(" %s\n", endswith);
00618 }
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631 typedef struct _fct_timer_t fct_timer_t;
00632 struct _fct_timer_t
00633 {
00634 clock_t start;
00635 clock_t stop;
00636 double duration;
00637 };
00638
00639
00640 static void
00641 fct_timer__init(fct_timer_t *timer)
00642 {
00643 FCT_ASSERT(timer != NULL);
00644 memset(timer, 0, sizeof(fct_timer_t));
00645 }
00646
00647
00648 static void
00649 fct_timer__start(fct_timer_t *timer)
00650 {
00651 FCT_ASSERT(timer != NULL);
00652 timer->start = clock();
00653 }
00654
00655
00656 static void
00657 fct_timer__stop(fct_timer_t *timer)
00658 {
00659 FCT_ASSERT(timer != NULL);
00660 timer->stop = clock();
00661 timer->duration = (double) (timer->stop - timer->start) / CLOCKS_PER_SEC;
00662 }
00663
00664
00665
00666 static double
00667 fct_timer__duration(fct_timer_t const *timer)
00668 {
00669 FCT_ASSERT( timer != NULL );
00670 return timer->duration;
00671 }
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681 #define FCT_LIST_GROWTH_FACTOR 2
00682
00683
00684
00685 #define FCT_LIST_DEFAULT_START_SZ 8
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697 #define FCT_NLIST_FOREACH_BGN(Type, Var, List)\
00698 {\
00699 if ( List != NULL ) {\
00700 size_t item_i##Var;\
00701 size_t num_items##Var = fct_nlist__size(List);\
00702 for( item_i##Var =0; item_i##Var != num_items##Var; ++item_i##Var )\
00703 {\
00704 Type Var = (Type) fct_nlist__at((List), item_i##Var);
00705
00706 #define FCT_NLIST_FOREACH_END() }}}
00707
00708
00709
00710
00711 typedef struct _fct_nlist_t fct_nlist_t;
00712 struct _fct_nlist_t
00713 {
00714
00715 void **itm_list;
00716
00717
00718 size_t avail_itm_num;
00719
00720
00721 size_t used_itm_num;
00722 };
00723 typedef void (*fct_nlist_on_del_t)(void*);
00724
00725
00726
00727
00728
00729 static void
00730 fct_nlist__clear(fct_nlist_t *list, fct_nlist_on_del_t on_del)
00731 {
00732 size_t itm_i__ =0;
00733 FCT_ASSERT( list != NULL );
00734 if ( on_del != NULL )
00735 {
00736 for ( itm_i__=0; itm_i__ != list->used_itm_num; ++itm_i__ )
00737 {
00738 on_del(list->itm_list[itm_i__]);
00739 }
00740 }
00741 list->used_itm_num =0;
00742 }
00743
00744
00745
00746
00747 static void
00748 fct_nlist__final(fct_nlist_t *list, fct_nlist_on_del_t on_del)
00749 {
00750 FCT_ASSERT( list != NULL );
00751 fct_nlist__clear(list, on_del);
00752 free(list->itm_list);
00753 }
00754
00755
00756 static int
00757 fct_nlist__init2(fct_nlist_t *list, size_t start_sz)
00758 {
00759 FCT_ASSERT( list != NULL );
00760 if ( start_sz == 0 )
00761 {
00762 list->itm_list = NULL;
00763 }
00764 else
00765 {
00766 list->itm_list = (void**)malloc(sizeof(void*)*start_sz);
00767 if ( list->itm_list == NULL )
00768 {
00769 return 0;
00770 }
00771 }
00772
00773
00774
00775
00776 list->avail_itm_num = start_sz;
00777 list->used_itm_num =0;
00778 return 1;
00779 }
00780
00781
00782
00783
00784 #define fct_nlist__init(_LIST_PTR_) \
00785 (fct_nlist__init2((_LIST_PTR_), FCT_LIST_DEFAULT_START_SZ))
00786
00787
00788
00789 static size_t
00790 fct_nlist__size(fct_nlist_t const *list)
00791 {
00792 FCT_ASSERT( list != NULL );
00793 return list->used_itm_num;
00794 }
00795
00796
00797
00798 static void*
00799 fct_nlist__at(fct_nlist_t const *list, size_t idx)
00800 {
00801 FCT_ASSERT( list != NULL );
00802 FCT_ASSERT( idx < list->used_itm_num );
00803 return list->itm_list[idx];
00804 }
00805
00806
00807 static void
00808 fct_nlist__append(fct_nlist_t *list, void *itm)
00809 {
00810 FCT_ASSERT( list != NULL );
00811
00812
00813
00814
00815 if ( list->used_itm_num == list->avail_itm_num )
00816 {
00817
00818 list->avail_itm_num = list->avail_itm_num*FCT_LIST_GROWTH_FACTOR+\
00819 FCT_LIST_GROWTH_FACTOR;
00820 list->itm_list = (void**)realloc(
00821 list->itm_list, sizeof(void*)*list->avail_itm_num
00822 );
00823 FCT_ASSERT( list->itm_list != NULL && "memory check");
00824 }
00825
00826 list->itm_list[list->used_itm_num] = itm;
00827 ++(list->used_itm_num);
00828 }
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841 struct _fctchk_t
00842 {
00843
00844 char cndtn[FCT_MAX_LOG_LINE];
00845
00846
00847 char file[FCT_MAX_LOG_LINE];
00848
00849 int lineno;
00850
00851 nbool_t is_pass;
00852
00853
00854
00855
00856 char msg[FCT_MAX_LOG_LINE];
00857 };
00858
00859 #define fctchk__is_pass(_CHK_) ((_CHK_)->is_pass)
00860 #define fctchk__file(_CHK_) ((_CHK_)->file)
00861 #define fctchk__lineno(_CHK_) ((_CHK_)->lineno)
00862 #define fctchk__cndtn(_CHK_) ((_CHK_)->cndtn)
00863 #define fctchk__msg(_CHK_) ((_CHK_)->msg)
00864
00865 static fctchk_t*
00866 fctchk_new(int is_pass,
00867 char const *cndtn,
00868 char const *file,
00869 int lineno,
00870 char const *format,
00871 va_list args)
00872 {
00873 fctchk_t *chk = NULL;
00874
00875 FCT_ASSERT( cndtn != NULL );
00876 FCT_ASSERT( file != NULL );
00877 FCT_ASSERT( lineno > 0 );
00878
00879 chk = (fctchk_t*)calloc(1, sizeof(fctchk_t));
00880 if ( chk == NULL )
00881 {
00882 return NULL;
00883 }
00884
00885 fctstr_safe_cpy(chk->cndtn, cndtn, FCT_MAX_LOG_LINE);
00886 fctstr_safe_cpy(chk->file, file, FCT_MAX_LOG_LINE);
00887 chk->lineno = lineno;
00888
00889 chk->is_pass =is_pass;
00890
00891 if ( format != NULL )
00892 {
00893 fct_vsnprintf(chk->msg, FCT_MAX_LOG_LINE, format, args);
00894 }
00895 else
00896 {
00897
00898
00899 fctstr_safe_cpy(chk->msg, cndtn, FCT_MAX_LOG_LINE);
00900 }
00901
00902 return chk;
00903 }
00904
00905
00906
00907
00908 static void
00909 fctchk__del(fctchk_t *chk)
00910 {
00911 if ( chk == NULL )
00912 {
00913 return;
00914 }
00915 free( chk );
00916 }
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927 struct _fct_test_t
00928 {
00929
00930
00931
00932 fct_nlist_t failed_chks;
00933 fct_nlist_t passed_chks;
00934
00935
00936 fct_timer_t timer;
00937
00938
00939 char name[FCT_MAX_NAME];
00940 };
00941
00942 #define fct_test__name(_TEST_) ((_TEST_)->name)
00943
00944
00945 #define fct_test__clear_failed(test) \
00946 fct_nlist__clear(test->failed_chks, (fct_nlist_on_del_t)fctchk__del);\
00947
00948
00949 static void
00950 fct_test__del(fct_test_t *test)
00951 {
00952 if (test == NULL )
00953 {
00954 return;
00955 }
00956 fct_nlist__final(&(test->passed_chks), (fct_nlist_on_del_t)fctchk__del);
00957 fct_nlist__final(&(test->failed_chks), (fct_nlist_on_del_t)fctchk__del);
00958 free(test);
00959 }
00960
00961
00962 static fct_test_t*
00963 fct_test_new(char const *name)
00964 {
00965 nbool_t ok =FCT_FALSE;
00966 fct_test_t *test =NULL;
00967
00968 test = (fct_test_t*)malloc(sizeof(fct_test_t));
00969 if ( test == NULL )
00970 {
00971 return NULL;
00972 }
00973
00974 fctstr_safe_cpy(test->name, name, FCT_MAX_NAME);
00975
00976
00977
00978 fct_nlist__init2(&(test->failed_chks), 0);
00979 if (!fct_nlist__init(&(test->passed_chks)))
00980 {
00981 ok =FCT_FALSE;
00982 goto finally;
00983 }
00984
00985 fct_timer__init(&(test->timer));
00986
00987 ok =FCT_TRUE;
00988 finally:
00989 if ( !ok )
00990 {
00991 fct_test__del(test);
00992 test =NULL;
00993 }
00994 return test;
00995 }
00996
00997
00998 static void
00999 fct_test__start_timer(fct_test_t *test)
01000 {
01001 FCT_ASSERT( test != NULL );
01002 fct_timer__start(&(test->timer));
01003 }
01004
01005
01006 static void
01007 fct_test__stop_timer(fct_test_t *test)
01008 {
01009 FCT_ASSERT( test != NULL );
01010 fct_timer__stop(&(test->timer));
01011 }
01012
01013
01014 static double
01015 fct_test__duration(fct_test_t const *test)
01016 {
01017 FCT_ASSERT( test != NULL );
01018 return fct_timer__duration(&(test->timer));
01019 }
01020
01021
01022 static nbool_t
01023 fct_test__is_pass(fct_test_t const *test)
01024 {
01025 FCT_ASSERT( test != NULL );
01026 return fct_nlist__size(&(test->failed_chks)) == 0;
01027 }
01028
01029
01030 static void
01031 fct_test__add(fct_test_t *test, fctchk_t *chk)
01032 {
01033
01034 FCT_ASSERT( test != NULL );
01035 FCT_ASSERT( chk != NULL );
01036
01037 if ( fctchk__is_pass(chk) )
01038 {
01039 fct_nlist__append(&(test->passed_chks), (void*)chk);
01040 }
01041 else
01042 {
01043 fct_nlist__append(&(test->failed_chks), (void*)chk);
01044 }
01045 }
01046
01047
01048 static size_t
01049 fct_test__chk_cnt(fct_test_t const *test)
01050 {
01051 FCT_ASSERT( test != NULL );
01052 return fct_nlist__size(&(test->failed_chks)) \
01053 + fct_nlist__size(&(test->passed_chks));
01054 }
01055
01056
01057
01058
01059
01060
01061
01062
01063
01064
01065
01066
01067
01068
01069
01070
01071
01072
01073
01074
01075
01076
01077
01078
01079
01080
01081
01082
01083 enum ts_mode
01084 {
01085 ts_mode_cnt,
01086 ts_mode_setup,
01087 ts_mode_teardown,
01088 ts_mode_test,
01089 ts_mode_ending,
01090 ts_mode_end,
01091 ts_mode_abort
01092 };
01093
01094
01095 typedef enum
01096 {
01097 fct_test_status_SUCCESS,
01098 fct_test_status_FAILURE
01099 } fct_test_status;
01100
01101
01102 struct _fct_ts_t
01103 {
01104
01105
01106 int curr_test_num;
01107 int total_test_num;
01108
01109
01110
01111 enum ts_mode mode;
01112
01113
01114 char name[FCT_MAX_NAME];
01115
01116
01117 fct_nlist_t test_list;
01118 };
01119
01120
01121 #define fct_ts__is_setup_mode(ts) ((ts)->mode == ts_mode_setup)
01122 #define fct_ts__is_teardown_mode(ts) ((ts)->mode == ts_mode_teardown)
01123 #define fct_ts__is_test_mode(ts) ((ts)->mode == ts_mode_test)
01124 #define fct_ts__is_ending_mode(ts) ((ts)->mode == ts_mode_ending)
01125 #define fct_ts__is_end(ts) ((ts)->mode == ts_mode_end)
01126 #define fct_ts__is_cnt_mode(ts) ((ts)->mode == ts_mode_cnt)
01127 #define fct_ts__is_abort_mode(ts) ((ts)->mode == ts_mode_abort)
01128
01129
01130
01131 #define fct_ts__ending(ts) ((ts)->mode = ts_mode_ending)
01132
01133
01134 #define fct_ts__end(ts) ((ts)->mode = ts_mode_end)
01135
01136 #define fct_ts__name(ts) ((ts)->name)
01137
01138
01139 static void
01140 fct_ts__del(fct_ts_t *ts)
01141 {
01142 if ( ts == NULL )
01143 {
01144 return;
01145 }
01146 fct_nlist__final(&(ts->test_list), (fct_nlist_on_del_t)fct_test__del);
01147 free(ts);
01148 }
01149
01150 static fct_ts_t *
01151 fct_ts_new(char const *name)
01152 {
01153 fct_ts_t *ts =NULL;
01154 ts = (fct_ts_t*)calloc(1, sizeof(fct_ts_t));
01155 FCT_ASSERT( ts != NULL );
01156
01157 fctstr_safe_cpy(ts->name, name, FCT_MAX_NAME);
01158 ts->mode = ts_mode_cnt;
01159 fct_nlist__init(&(ts->test_list));
01160 return ts;
01161 }
01162
01163
01164
01165 static nbool_t
01166 fct_ts__is_more_tests(fct_ts_t const *ts)
01167 {
01168 FCT_ASSERT( ts != NULL );
01169 FCT_ASSERT( !fct_ts__is_end(ts) );
01170 return ts->curr_test_num < ts->total_test_num;
01171 }
01172
01173
01174
01175 static void
01176 fct_ts__test_begin(fct_ts_t *ts)
01177 {
01178 FCT_ASSERT( !fct_ts__is_end(ts) );
01179 ++(ts->curr_test_num);
01180 }
01181
01182
01183
01184
01185 static void
01186 fct_ts__add_test(fct_ts_t *ts, fct_test_t *test)
01187 {
01188 FCT_ASSERT( ts != NULL && "invalid arg");
01189 FCT_ASSERT( test != NULL && "invalid arg");
01190 FCT_ASSERT( !fct_ts__is_end(ts) );
01191 fct_nlist__append(&(ts->test_list), test);
01192 }
01193
01194
01195 static void
01196 fct_ts__test_end(fct_ts_t *ts)
01197 {
01198 FCT_ASSERT( ts != NULL );
01199
01200 ts->mode = ts_mode_teardown;
01201 }
01202
01203
01204
01205 static void
01206 fct_ts__inc_total_test_num(fct_ts_t *ts)
01207 {
01208 FCT_ASSERT( ts != NULL );
01209 FCT_ASSERT( fct_ts__is_cnt_mode(ts) );
01210 FCT_ASSERT( !fct_ts__is_end(ts) );
01211 ++(ts->total_test_num);
01212 }
01213
01214
01215
01216
01217 static void
01218 fct_ts__setup_end(fct_ts_t *ts)
01219 {
01220 if ( ts->mode != ts_mode_abort )
01221 {
01222 ts->mode = ts_mode_test;
01223 }
01224 }
01225
01226
01227 static fct_test_t *
01228 fct_ts__make_abort_test(fct_ts_t *ts)
01229 {
01230 char setup_testname[FCT_MAX_LOG_LINE+1] = {'\0'};
01231 char const *suitename = fct_ts__name(ts);
01232 fct_snprintf(setup_testname, FCT_MAX_LOG_LINE, "setup_%s", suitename);
01233 return fct_test_new(setup_testname);
01234 }
01235
01236
01237 static void
01238 fct_ts__setup_abort(fct_ts_t *ts)
01239 {
01240 FCT_ASSERT( ts != NULL );
01241 ts->mode = ts_mode_abort;
01242 }
01243
01244
01245
01246 static void
01247 fct_ts__teardown_end(fct_ts_t *ts)
01248 {
01249 if ( ts->mode == ts_mode_abort )
01250 {
01251 return;
01252 }
01253
01254
01255
01256 if ( fct_ts__is_more_tests(ts) )
01257 {
01258 ts->mode = ts_mode_setup;
01259 }
01260 else
01261 {
01262 ts->mode = ts_mode_ending;
01263 }
01264 }
01265
01266
01267
01268
01269
01270
01271 static void
01272 fct_ts__cnt_end(fct_ts_t *ts)
01273 {
01274 FCT_ASSERT( ts != NULL );
01275 FCT_ASSERT( fct_ts__is_cnt_mode(ts) );
01276 FCT_ASSERT( !fct_ts__is_end(ts) );
01277 if (ts->total_test_num == 0 )
01278 {
01279 ts->mode = ts_mode_ending;
01280 }
01281 else
01282 {
01283 ts->mode = ts_mode_setup;
01284 }
01285 }
01286
01287
01288 static nbool_t
01289 fct_ts__is_test_cnt(fct_ts_t const *ts, int test_num)
01290 {
01291 FCT_ASSERT( ts != NULL );
01292 FCT_ASSERT( 0 <= test_num );
01293 FCT_ASSERT( test_num < ts->total_test_num );
01294 FCT_ASSERT( !fct_ts__is_end(ts) );
01295
01296
01297
01298 return test_num == ts->curr_test_num;
01299 }
01300
01301
01302
01303
01304 static size_t
01305 fct_ts__tst_cnt(fct_ts_t const *ts)
01306 {
01307 FCT_ASSERT( ts != NULL );
01308 FCT_ASSERT(
01309 fct_ts__is_end(ts)
01310 && "can't count number of tests executed until the test suite ends"
01311 );
01312 return fct_nlist__size(&(ts->test_list));
01313 }
01314
01315
01316
01317 static size_t
01318 fct_ts__tst_cnt_passed(fct_ts_t const *ts)
01319 {
01320 size_t tally =0;
01321
01322 FCT_ASSERT( ts != NULL );
01323 FCT_ASSERT( fct_ts__is_end(ts) );
01324
01325 FCT_NLIST_FOREACH_BGN(fct_test_t*, test, &(ts->test_list))
01326 {
01327 if ( fct_test__is_pass(test) )
01328 {
01329 tally += 1;
01330 }
01331 }
01332 FCT_NLIST_FOREACH_END();
01333 return tally;
01334 }
01335
01336
01337
01338 static size_t
01339 fct_ts__chk_cnt(fct_ts_t const *ts)
01340 {
01341 size_t tally =0;
01342
01343 FCT_ASSERT( ts != NULL );
01344
01345 FCT_NLIST_FOREACH_BGN(fct_test_t *, test, &(ts->test_list))
01346 {
01347 tally += fct_test__chk_cnt(test);
01348 }
01349 FCT_NLIST_FOREACH_END();
01350 return tally;
01351 }
01352
01353
01354 static double
01355 fct_ts__duration(fct_ts_t const *ts)
01356 {
01357 double tally =0.0;
01358 FCT_ASSERT( ts != NULL );
01359 FCT_NLIST_FOREACH_BGN(fct_test_t *, test, &(ts->test_list))
01360 {
01361 tally += fct_test__duration(test);
01362 }
01363 FCT_NLIST_FOREACH_END();
01364 return tally;
01365 }
01366
01367
01368
01369
01370
01371
01372
01373
01374
01375
01376
01377
01378 typedef enum
01379 {
01380 FCTCL_STORE_UNDEFINED,
01381 FCTCL_STORE_TRUE,
01382 FCTCL_STORE_VALUE
01383 } fctcl_store_t;
01384
01385
01386 typedef struct _fctcl_init_t
01387 {
01388
01389 char const *long_opt;
01390 char const *short_opt;
01391
01392
01393 fctcl_store_t action;
01394
01395
01396 char const *help;
01397 } fctcl_init_t;
01398
01399
01400
01401 #define FCTCL_INIT_NULL \
01402 {NULL, NULL, FCTCL_STORE_UNDEFINED, NULL}
01403
01404
01405
01406
01407
01408
01409
01410
01411
01412
01413
01414
01415
01416
01417
01418 #define FCTCL_TRUE_STR "1"
01419
01420
01421 typedef struct _fctcl_t
01422 {
01423
01424 char *long_opt;
01425 char *short_opt;
01426
01427
01428 fctcl_store_t action;
01429
01430
01431 char *help;
01432
01433
01434 char *value;
01435 } fctcl_t;
01436
01437
01438 #define fctcl_new() ((fctcl_t*)calloc(1, sizeof(fctcl_t)))
01439
01440
01441 static void
01442 fctcl__del(fctcl_t *clo)
01443 {
01444 if ( clo == NULL )
01445 {
01446 return;
01447 }
01448 if ( clo->long_opt )
01449 {
01450 free(clo->long_opt);
01451 }
01452 if ( clo->short_opt)
01453 {
01454 free(clo->short_opt);
01455 }
01456 if ( clo->value )
01457 {
01458 free(clo->value);
01459 }
01460 if ( clo->help )
01461 {
01462 free(clo->help);
01463 }
01464 free(clo);
01465 }
01466
01467
01468 static fctcl_t*
01469 fctcl_new2(fctcl_init_t const *clo_init)
01470 {
01471 fctcl_t *clone = NULL;
01472 int ok =0;
01473 clone = fctcl_new();
01474 if ( clone == NULL )
01475 {
01476 return NULL;
01477 }
01478 clone->action = clo_init->action;
01479 if ( clo_init->help == NULL )
01480 {
01481 clone->help = NULL;
01482 }
01483 else
01484 {
01485 clone->help = fctstr_clone(clo_init->help);
01486 if ( clone->help == NULL )
01487 {
01488 ok =0;
01489 goto finally;
01490 }
01491 }
01492 if ( clo_init->long_opt == NULL )
01493 {
01494 clone->long_opt = NULL;
01495 }
01496 else
01497 {
01498 clone->long_opt = fctstr_clone(clo_init->long_opt);
01499 if ( clone->long_opt == NULL )
01500 {
01501 ok = 0;
01502 goto finally;
01503 }
01504 }
01505 if ( clo_init->short_opt == NULL )
01506 {
01507 clone->short_opt = NULL;
01508 }
01509 else
01510 {
01511 clone->short_opt = fctstr_clone(clo_init->short_opt);
01512 if ( clone->short_opt == NULL )
01513 {
01514 ok =0;
01515 goto finally;
01516 }
01517 }
01518 ok = 1;
01519 finally:
01520 if ( !ok )
01521 {
01522 fctcl__del(clone);
01523 clone = NULL;
01524 }
01525 return clone;
01526 }
01527
01528
01529 static int
01530 fctcl__is_option(fctcl_t const *clo, char const *option)
01531 {
01532 FCT_ASSERT( clo != NULL );
01533 if ( option == NULL )
01534 {
01535 return 0;
01536 }
01537 return ((clo->long_opt != NULL
01538 && fctstr_eq(clo->long_opt, option))
01539 ||
01540 (clo->short_opt != NULL
01541 && fctstr_eq(clo->short_opt, option))
01542 );
01543 }
01544
01545
01546 #define fctcl__set_value(_CLO_, _VAL_) \
01547 (_CLO_)->value = fctstr_clone((_VAL_));
01548
01549
01550
01551
01552
01553
01554
01555 #define FCT_CLP_MAX_ERR_MSG_LEN 256
01556
01557 typedef struct _fct_clp_t
01558 {
01559
01560 fct_nlist_t clo_list;
01561
01562
01563 fct_nlist_t param_list;
01564
01565 char error_msg[FCT_CLP_MAX_ERR_MSG_LEN];
01566 int is_error;
01567 } fct_clp_t;
01568
01569
01570 static void
01571 fct_clp__final(fct_clp_t *clp)
01572 {
01573 fct_nlist__final(&(clp->clo_list), (fct_nlist_on_del_t)fctcl__del);
01574 fct_nlist__final(&(clp->param_list), (fct_nlist_on_del_t)free);
01575 }
01576
01577
01578
01579 static int
01580 fct_clp__add_options(fct_clp_t *clp, fctcl_init_t const *options)
01581 {
01582 fctcl_init_t const *pclo =NULL;
01583 int ok;
01584 for ( pclo = options; pclo->action != FCTCL_STORE_UNDEFINED; ++pclo )
01585 {
01586 fctcl_t *cpy = fctcl_new2(pclo);
01587 if ( cpy == NULL )
01588 {
01589 ok = 0;
01590 goto finally;
01591 }
01592 fct_nlist__append(&(clp->clo_list), (void*)cpy);
01593 }
01594 ok =1;
01595 finally:
01596 return ok;
01597 }
01598
01599
01600 static int
01601 fct_clp__init(fct_clp_t *clp, fctcl_init_t const *options)
01602 {
01603 int ok =0;
01604 FCT_ASSERT( clp != NULL );
01605
01606
01607 ok = fct_nlist__init(&(clp->clo_list));
01608 if ( !ok )
01609 {
01610 goto finally;
01611 }
01612 if ( options != NULL )
01613 {
01614 ok = fct_clp__add_options(clp, options);
01615 if ( !ok )
01616 {
01617 goto finally;
01618 }
01619 }
01620 ok = fct_nlist__init(&(clp->param_list));
01621 if ( !ok )
01622 {
01623 goto finally;
01624 }
01625 ok =1;
01626 finally:
01627 if ( !ok )
01628 {
01629 fct_clp__final(clp);
01630 }
01631 return ok;
01632 }
01633
01634
01635
01636
01637 static void
01638 fct_clp__parse(fct_clp_t *clp, int argc, char const *argv[])
01639 {
01640 int argi =1;
01641 int is_option =0;
01642 char *arg =NULL;
01643 char *token =NULL;
01644 char *next_token =NULL;
01645
01646 clp->error_msg[0] = '\0';
01647 clp->is_error =0;
01648
01649 while ( argi < argc )
01650 {
01651 is_option =0;
01652 token =NULL;
01653 next_token = NULL;
01654 arg = fctstr_clone(argv[argi]);
01655
01656 #if defined(_MSC_VER) && _MSC_VER > 1300
01657 token = strtok_s(arg, "=", &next_token);
01658 #else
01659 token = strtok(arg, "=");
01660 next_token = strtok(NULL, "=");
01661 #endif
01662
01663 FCT_NLIST_FOREACH_BGN(fctcl_t*, pclo, &(clp->clo_list))
01664 {
01665
01666 if ( fctcl__is_option(pclo, token) )
01667 {
01668 is_option =1;
01669 if ( pclo->action == FCTCL_STORE_VALUE )
01670 {
01671
01672
01673 if ( next_token != NULL && strlen(next_token) > 0 )
01674 {
01675 fctcl__set_value(pclo, next_token);
01676 }
01677 else
01678 {
01679 ++argi;
01680 if ( argi >= argc )
01681 {
01682
01683 fct_snprintf(
01684 clp->error_msg,
01685 FCT_CLP_MAX_ERR_MSG_LEN,
01686 "missing argument for %s",
01687 token
01688 );
01689 clp->is_error =1;
01690 break;
01691 }
01692 fctcl__set_value(pclo, argv[argi]);
01693 }
01694 }
01695 else if (pclo->action == FCTCL_STORE_TRUE)
01696 {
01697 fctcl__set_value(pclo, FCTCL_TRUE_STR);
01698 }
01699 else
01700 {
01701 FCT_ASSERT("undefined action requested");
01702 }
01703 break;
01704 }
01705 }
01706 FCT_NLIST_FOREACH_END();
01707
01708 if ( clp->is_error )
01709 {
01710 break;
01711 }
01712
01713
01714
01715 if ( !is_option )
01716 {
01717 fct_nlist__append(&(clp->param_list), arg);
01718 arg =NULL;
01719 }
01720 ++argi;
01721 if ( arg != NULL )
01722 {
01723 free(arg);
01724 arg =NULL;
01725 }
01726 }
01727 }
01728
01729
01730 static fctcl_t const*
01731 fct_clp__get_clo(fct_clp_t const *clp, char const *option)
01732 {
01733 fctcl_t const *found =NULL;
01734
01735 FCT_NLIST_FOREACH_BGN(fctcl_t const*, pclo, &(clp->clo_list))
01736 {
01737 if ( fctcl__is_option(pclo, option) )
01738 {
01739 found = pclo;
01740 break;
01741 }
01742 }
01743 FCT_NLIST_FOREACH_END();
01744 return found;
01745 }
01746
01747
01748 #define fct_clp__optval(_CLP_, _OPTION_) \
01749 fct_clp__optval2((_CLP_), (_OPTION_), NULL)
01750
01751
01752
01753
01754 static char const*
01755 fct_clp__optval2(fct_clp_t *clp, char const *option, char const *default_val)
01756 {
01757 fctcl_t const *clo =NULL;
01758 FCT_ASSERT( clp != NULL );
01759 FCT_ASSERT( option != NULL );
01760 clo = fct_clp__get_clo(clp, option);
01761 if ( clo == NULL || clo->value == NULL)
01762 {
01763 return default_val;
01764 }
01765 return clo->value;
01766 }
01767
01768
01769
01770
01771 static int
01772 fct_clp__is_param(fct_clp_t *clp, char const *param)
01773 {
01774 if ( clp == NULL || param == NULL )
01775 {
01776 return 0;
01777 }
01778 FCT_NLIST_FOREACH_BGN(char *, aparam, &(clp->param_list))
01779 {
01780 if ( fctstr_eq(aparam, param) )
01781 {
01782 return 1;
01783 }
01784 }
01785 FCT_NLIST_FOREACH_END();
01786 return 0;
01787 }
01788
01789
01790 #define fct_clp__is_error(_CLP_) ((_CLP_)->is_error)
01791 #define fct_clp__get_error(_CLP_) ((_CLP_)->error_msg);
01792
01793 #define fct_clp__num_clo(_CLP_) \
01794 (fct_nlist__size(&((_CLP_)->clo_list)))
01795
01796 #define fct_clp__param_cnt(_CLP_) \
01797 (fct_nlist__size(&((_CLP_)->param_list)))
01798
01799
01800
01801 #define fct_clp__param_at(_CLP_, _IDX_) \
01802 ((char const*)fct_nlist__at(&((_CLP_)->param_list), (_IDX_)))
01803
01804
01805
01806
01807 #define fct_clp__is(_CLP_, _OPTION_) \
01808 (fct_clp__optval((_CLP_), (_OPTION_)) != NULL)
01809
01810
01811
01812
01813
01814
01815
01816
01817
01818
01819
01820
01821 typedef struct _fct_namespace_t
01822 {
01823
01824 fct_ts_t *ts_curr;
01825 int ts_is_skip_suite;
01826 char const *ts_skip_cndtn;
01827
01828
01829 char const* curr_test_name;
01830 fct_test_t *curr_test;
01831 const char *test_skip_cndtn;
01832 int test_is_skip;
01833
01834
01835 int test_num;
01836
01837
01838 size_t num_total_failed;
01839 } fct_namespace_t;
01840
01841
01842 static void
01843 fct_namespace_init(fct_namespace_t *ns)
01844 {
01845 FCT_ASSERT( ns != NULL && "invalid argument!");
01846 memset(ns, 0, sizeof(fct_namespace_t));
01847 }
01848
01849
01850
01851
01852
01853
01854
01855
01856
01857
01858
01859 struct _fctkern_t
01860 {
01861
01862
01863 fct_namespace_t ns;
01864
01865
01866 fct_clp_t cl_parser;
01867
01868
01869 int cl_argc;
01870 char const **cl_argv;
01871
01872 fctcl_init_t const *cl_user_opts;
01873
01874
01875 int cl_is_parsed;
01876
01877
01878 fct_nlist_t logger_list;
01879
01880
01881
01882 fct_logger_types_t *lt_usr;
01883 fct_logger_types_t *lt_sys;
01884
01885
01886
01887 fct_nlist_t prefix_list;
01888
01889
01890
01891 fct_nlist_t ts_list;
01892
01893
01894 size_t num_expected_failures;
01895 };
01896
01897
01898 #define FCT_OPT_VERSION "--version"
01899 #define FCT_OPT_VERSION_SHORT "-v"
01900 #define FCT_OPT_HELP "--help"
01901 #define FCT_OPT_HELP_SHORT "-h"
01902 #define FCT_OPT_LOGGER "--logger"
01903 #define FCT_OPT_LOGGER_SHORT "-l"
01904 static fctcl_init_t FCT_CLP_OPTIONS[] =
01905 {
01906
01907
01908
01909 {
01910 FCT_OPT_VERSION,
01911 FCT_OPT_VERSION_SHORT,
01912 FCTCL_STORE_TRUE,
01913 "Displays the FCTX version number and exits."
01914 },
01915 {
01916 FCT_OPT_HELP,
01917 FCT_OPT_HELP_SHORT,
01918 FCTCL_STORE_TRUE,
01919 "Shows this help."
01920 },
01921 {
01922 FCT_OPT_LOGGER,
01923 FCT_OPT_LOGGER_SHORT,
01924 FCTCL_STORE_VALUE,
01925 NULL
01926 },
01927 FCTCL_INIT_NULL
01928 };
01929
01930 typedef fct_logger_i* (*fct_logger_new_fn)(void);
01931 struct _fct_logger_types_t
01932 {
01933 char const *name;
01934 fct_logger_new_fn logger_new_fn;
01935 char const *desc;
01936 };
01937
01938 static fct_logger_types_t FCT_LOGGER_TYPES[] =
01939 {
01940 {
01941 "standard",
01942 (fct_logger_new_fn)fct_standard_logger_new,
01943 "the basic fctx logger"
01944 },
01945 {
01946 "minimal",
01947 (fct_logger_new_fn)fct_minimal_logger_new,
01948 "the least amount of logging information."
01949 },
01950 {
01951 "junit",
01952 (fct_logger_new_fn)fct_junit_logger_new,
01953 "junit compatable xml"
01954 },
01955 {NULL, (fct_logger_new_fn)NULL, NULL}
01956 };
01957
01958
01959
01960 #define fctkern__filter_cnt(_NK_) (fct_nlist__size(&((_NK_)->prefix_list)))
01961
01962
01963 static void
01964 fctkern__add_logger(fctkern_t *nk, fct_logger_i *logger_owns)
01965 {
01966 FCT_ASSERT(nk != NULL && "invalid arg");
01967 FCT_ASSERT(logger_owns != NULL && "invalid arg");
01968 fct_nlist__append(&(nk->logger_list), logger_owns);
01969 }
01970
01971
01972 static void
01973 fctkern__write_help(fctkern_t *nk, FILE *out)
01974 {
01975 fct_clp_t *clp = &(nk->cl_parser);
01976 fprintf(out, "test.exe [options] prefix_filter ...\n\n");
01977 FCT_NLIST_FOREACH_BGN(fctcl_t*, clo, &(clp->clo_list))
01978 {
01979 if ( clo->short_opt != NULL )
01980 {
01981 fprintf(out, "%s, %s\n", clo->short_opt, clo->long_opt);
01982 }
01983 else
01984 {
01985 fprintf(out, "%s\n", clo->long_opt);
01986 }
01987 if ( !fctstr_ieq(clo->long_opt, FCT_OPT_LOGGER) )
01988 {
01989
01990 fprintf(out, " %s\n", clo->help);
01991 }
01992 else
01993 {
01994 fct_logger_types_t *types[2];
01995 int type_i;
01996 fct_logger_types_t *itr;
01997 types[0] = nk->lt_sys;
01998 types[1] = nk->lt_usr;
01999 fputs(" Sets the logger. The types of loggers currently "
02000 "available are,\n", out);
02001 for (type_i =0; type_i != 2; ++type_i )
02002 {
02003 for ( itr=types[type_i]; itr && itr->name != NULL; ++itr )
02004 {
02005 fprintf(out, " =%s : %s\n", itr->name, itr->desc);
02006 }
02007 }
02008 fprintf(out, " default is '%s'.\n", FCT_DEFAULT_LOGGER);
02009 }
02010 }
02011 FCT_NLIST_FOREACH_END();
02012 fputs("\n", out);
02013 }
02014
02015
02016
02017
02018
02019
02020 static void
02021 fctkern__add_prefix_filter(fctkern_t *nk, char const *prefix_filter)
02022 {
02023 char *filter =NULL;
02024 size_t filter_len =0;
02025 FCT_ASSERT( nk != NULL && "invalid arg" );
02026 FCT_ASSERT( prefix_filter != NULL && "invalid arg" );
02027 FCT_ASSERT( strlen(prefix_filter) > 0 && "invalid arg" );
02028
02029
02030 filter_len = strlen(prefix_filter);
02031 filter = (char*)malloc(sizeof(char)*(filter_len+1));
02032 fctstr_safe_cpy(filter, prefix_filter, filter_len+1);
02033 fct_nlist__append(&(nk->prefix_list), (void*)filter);
02034 }
02035
02036
02037
02038 static void
02039 fctkern__final(fctkern_t *nk)
02040 {
02041 if ( nk == NULL )
02042 {
02043 return;
02044 }
02045 fct_clp__final(&(nk->cl_parser));
02046 fct_nlist__final(&(nk->logger_list), (fct_nlist_on_del_t)fct_logger__del);
02047
02048 fct_nlist__final(&(nk->prefix_list), (fct_nlist_on_del_t)free);
02049 fct_nlist__final(&(nk->ts_list), (fct_nlist_on_del_t)fct_ts__del);
02050 }
02051
02052
02053 #define fctkern__cl_is_parsed(_NK_) ((_NK_)->cl_is_parsed)
02054
02055
02056 static int
02057 fctkern__cl_is(fctkern_t *nk, char const *opt_str)
02058 {
02059 FCT_ASSERT( opt_str != NULL );
02060 return opt_str[0] != '\0'
02061 && fct_clp__is(&(nk->cl_parser), opt_str);
02062 }
02063
02064
02065
02066
02067
02068
02069 static char const *
02070 fctkern__cl_val2(fctkern_t *nk, char const *opt_str, char const *def_str)
02071 {
02072 FCT_ASSERT( opt_str != NULL );
02073 if ( nk == NULL )
02074 {
02075 return NULL;
02076 }
02077 return fct_clp__optval2(&(nk->cl_parser), opt_str, def_str);
02078 }
02079
02080
02081
02082
02083 static fct_logger_i*
02084 fckern_sel_log(fct_logger_types_t *search, char const *sel_logger)
02085 {
02086 fct_logger_types_t *iter;
02087 FCT_ASSERT(search != NULL);
02088 FCT_ASSERT(sel_logger != NULL);
02089 FCT_ASSERT(strlen(sel_logger) > 0);
02090 for ( iter = search; iter->name != NULL; ++iter)
02091 {
02092 if ( fctstr_ieq(iter->name, sel_logger) )
02093 {
02094 return iter->logger_new_fn();
02095 }
02096 }
02097 return NULL;
02098 }
02099
02100 static int
02101 fctkern__cl_parse_config_logger(fctkern_t *nk)
02102 {
02103 fct_logger_i *logger =NULL;
02104 char const *sel_logger =NULL;
02105 char const *def_logger =FCT_DEFAULT_LOGGER;
02106 sel_logger = fctkern__cl_val2(nk, FCT_OPT_LOGGER, def_logger);
02107 FCT_ASSERT(sel_logger != NULL && "should never be NULL");
02108
02109
02110 if ( nk->lt_usr != NULL )
02111 {
02112 logger = fckern_sel_log(nk->lt_usr, sel_logger);
02113 }
02114 if ( nk->lt_sys != NULL && logger == NULL )
02115 {
02116 logger = fckern_sel_log(nk->lt_sys, sel_logger);
02117 }
02118 if ( logger == NULL )
02119 {
02120
02121 fprintf(stderr, "error: unknown logger selected - '%s'", sel_logger);
02122 return 0;
02123 }
02124 fctkern__add_logger(nk, logger);
02125 logger = NULL;
02126 return 1;
02127 }
02128
02129
02130
02131
02132
02133
02134 static int
02135 fctkern__cl_parse(fctkern_t *nk)
02136 {
02137 int status =0;
02138 size_t num_params =0;
02139 size_t param_i =0;
02140 if ( nk == NULL )
02141 {
02142 return 0;
02143 }
02144 if ( nk->cl_user_opts != NULL )
02145 {
02146 if ( !fct_clp__add_options(&(nk->cl_parser), nk->cl_user_opts) )
02147 {
02148 status =0;
02149 goto finally;
02150 }
02151 }
02152
02153
02154
02155 if ( !fct_clp__add_options(&(nk->cl_parser), FCT_CLP_OPTIONS) )
02156 {
02157 status =0;
02158 goto finally;
02159 }
02160 fct_clp__parse(&(nk->cl_parser), nk->cl_argc, nk->cl_argv);
02161 if ( fct_clp__is_error(&(nk->cl_parser)) )
02162 {
02163 char *err = fct_clp__get_error(&(nk->cl_parser));
02164 fprintf(stderr, "error: %s", err);
02165 status =0;
02166 goto finally;
02167 }
02168 num_params = fct_clp__param_cnt(&(nk->cl_parser));
02169 for ( param_i =0; param_i != num_params; ++param_i )
02170 {
02171 char const *param = fct_clp__param_at(&(nk->cl_parser), param_i);
02172 fctkern__add_prefix_filter(nk, param);
02173 }
02174 if ( fctkern__cl_is(nk, FCT_OPT_VERSION) )
02175 {
02176 (void)printf("Built using FCTX version %s.\n", FCT_VERSION_STR);
02177 status = -1;
02178 goto finally;
02179 }
02180 if ( fctkern__cl_is(nk, FCT_OPT_HELP) )
02181 {
02182 fctkern__write_help(nk, stdout);
02183 status = -1;
02184 goto finally;
02185 }
02186 if ( !fctkern__cl_parse_config_logger(nk) )
02187 {
02188 status = -1;
02189 goto finally;
02190 }
02191 status =1;
02192 nk->cl_is_parsed =1;
02193 finally:
02194 return status;
02195 }
02196
02197
02198
02199
02200
02201 static int
02202 fctkern__init(fctkern_t *nk, int argc, const char *argv[])
02203 {
02204 if ( argc == 0 && argv == NULL )
02205 {
02206 return 0;
02207 }
02208 memset(nk, 0, sizeof(fctkern_t));
02209 fct_clp__init(&(nk->cl_parser), NULL);
02210 fct_nlist__init(&(nk->logger_list));
02211 nk->lt_usr = NULL;
02212 nk->lt_sys = FCT_LOGGER_TYPES;
02213 fct_nlist__init2(&(nk->prefix_list), 0);
02214 fct_nlist__init2(&(nk->ts_list), 0);
02215 nk->cl_is_parsed =0;
02216
02217
02218
02219 nk->cl_argc = argc;
02220 nk->cl_argv = argv;
02221 fct_namespace_init(&(nk->ns));
02222 return 1;
02223 }
02224
02225
02226
02227
02228
02229 static void
02230 fctkern__add_ts(fctkern_t *nk, fct_ts_t *ts)
02231 {
02232 FCT_ASSERT( nk != NULL );
02233 FCT_ASSERT( ts != NULL );
02234 fct_nlist__append(&(nk->ts_list), ts);
02235 }
02236
02237
02238
02239
02240 static nbool_t
02241 fctkern__pass_filter(fctkern_t *nk, char const *test_name)
02242 {
02243 size_t prefix_i =0;
02244 size_t prefix_list_size =0;
02245 FCT_ASSERT( nk != NULL && "invalid arg");
02246 FCT_ASSERT( test_name != NULL );
02247 FCT_ASSERT( strlen(test_name) > 0 );
02248 prefix_list_size = fctkern__filter_cnt(nk);
02249
02250 if ( prefix_list_size == 0 )
02251 {
02252 return FCT_TRUE;
02253 }
02254
02255
02256
02257 for ( prefix_i = 0; prefix_i != prefix_list_size; ++prefix_i )
02258 {
02259 char const *prefix = (char const*)fct_nlist__at(
02260 &(nk->prefix_list), prefix_i
02261 );
02262 nbool_t pass = fct_filter_pass(prefix, test_name);
02263 if ( pass )
02264 {
02265 return FCT_TRUE;
02266 }
02267 }
02268
02269
02270
02271 return FCT_FALSE;
02272 }
02273
02274
02275
02276 static size_t
02277 fctkern__tst_cnt(fctkern_t const *nk)
02278 {
02279 size_t tally =0;
02280 FCT_ASSERT( nk != NULL );
02281 FCT_NLIST_FOREACH_BGN(fct_ts_t *, ts, &(nk->ts_list))
02282 {
02283 tally += fct_ts__tst_cnt(ts);
02284 }
02285 FCT_NLIST_FOREACH_END();
02286 return tally;
02287 }
02288
02289
02290
02291 static size_t
02292 fctkern__tst_cnt_passed(fctkern_t const *nk)
02293 {
02294 size_t tally =0;
02295 FCT_ASSERT( nk != NULL );
02296
02297 FCT_NLIST_FOREACH_BGN(fct_ts_t*, ts, &(nk->ts_list))
02298 {
02299 tally += fct_ts__tst_cnt_passed(ts);
02300 }
02301 FCT_NLIST_FOREACH_END();
02302
02303 return tally;
02304 }
02305
02306
02307
02308 #define fctkern__tst_cnt_failed(nk) \
02309 (fctkern__tst_cnt(nk) - fctkern__tst_cnt_passed(nk))
02310
02311
02312
02313 #if defined(FCT_USE_TEST_COUNT)
02314 static size_t
02315 fctkern__chk_cnt(fctkern_t const *nk)
02316 {
02317 size_t tally =0;
02318 FCT_ASSERT( nk != NULL );
02319
02320 FCT_NLIST_FOREACH_BGN(fct_ts_t *, ts, &(nk->ts_list))
02321 {
02322 tally += fct_ts__chk_cnt(ts);
02323 }
02324 FCT_NLIST_FOREACH_END();
02325 return tally;
02326 }
02327 #endif
02328
02329
02330
02331 #define fctkern__end(nk)
02332
02333
02334 static void
02335 fctkern__log_suite_start(fctkern_t *nk, fct_ts_t const *ts)
02336 {
02337 FCT_ASSERT( nk != NULL );
02338 FCT_ASSERT( ts != NULL );
02339 FCT_NLIST_FOREACH_BGN(fct_logger_i*, logger, &(nk->logger_list))
02340 {
02341 fct_logger__on_test_suite_start(logger, ts);
02342 }
02343 FCT_NLIST_FOREACH_END();
02344 }
02345
02346
02347 static void
02348 fctkern__log_suite_end(fctkern_t *nk, fct_ts_t const *ts)
02349 {
02350 FCT_ASSERT( nk != NULL );
02351 FCT_ASSERT( ts != NULL );
02352 FCT_NLIST_FOREACH_BGN(fct_logger_i*, logger, &(nk->logger_list))
02353 {
02354 fct_logger__on_test_suite_end(logger, ts);
02355 }
02356 FCT_NLIST_FOREACH_END();
02357 }
02358
02359
02360 static void
02361 fctkern__log_suite_skip(fctkern_t *nk, char const *condition, char const *name)
02362 {
02363 if ( nk == NULL )
02364 {
02365 return;
02366 }
02367 FCT_NLIST_FOREACH_BGN(fct_logger_i*, logger, &(nk->logger_list))
02368 {
02369 fct_logger__on_test_suite_skip(logger, condition, name);
02370 }
02371 FCT_NLIST_FOREACH_END();
02372 }
02373
02374
02375 static void
02376 fctkern__log_test_skip(fctkern_t *nk, char const *condition, char const *name)
02377 {
02378 FCT_NLIST_FOREACH_BGN(fct_logger_i*, logger, &(nk->logger_list))
02379 {
02380 fct_logger__on_test_skip(logger, condition, name);
02381 }
02382 FCT_NLIST_FOREACH_END();
02383 }
02384
02385
02386
02387
02388 static void
02389 fctkern__log_chk(fctkern_t *nk, fctchk_t const *chk)
02390 {
02391 FCT_ASSERT( nk != NULL );
02392 FCT_ASSERT( chk != NULL );
02393 FCT_NLIST_FOREACH_BGN(fct_logger_i*, logger, &(nk->logger_list))
02394 {
02395 fct_logger__on_chk(logger, chk);
02396 }
02397 FCT_NLIST_FOREACH_END();
02398 }
02399
02400
02401
02402 static void
02403 fctkern__log_warn(fctkern_t *nk, char const *warn)
02404 {
02405 FCT_ASSERT( nk != NULL );
02406 FCT_ASSERT( warn != NULL );
02407 FCT_NLIST_FOREACH_BGN(fct_logger_i*, logger, &(nk->logger_list))
02408 {
02409 fct_logger__on_warn(logger, warn);
02410 }
02411 FCT_NLIST_FOREACH_END();
02412 }
02413
02414
02415
02416 static void
02417 fctkern__log_test_start(fctkern_t *nk, fct_test_t const *test)
02418 {
02419 FCT_ASSERT( nk != NULL );
02420 FCT_ASSERT( test != NULL );
02421 FCT_NLIST_FOREACH_BGN(fct_logger_i*, logger, &(nk->logger_list))
02422 {
02423 fct_logger__on_test_start(logger, test);
02424 }
02425 FCT_NLIST_FOREACH_END();
02426 }
02427
02428
02429 static void
02430 fctkern__log_test_end(fctkern_t *nk, fct_test_t *test)
02431 {
02432 FCT_ASSERT( nk != NULL );
02433 FCT_ASSERT( test != NULL );
02434 FCT_NLIST_FOREACH_BGN(fct_logger_i*, logger, &(nk->logger_list))
02435 {
02436 fct_logger__on_test_end(logger, test);
02437 }
02438 FCT_NLIST_FOREACH_END();
02439 }
02440
02441
02442 #define fctkern__log_start(_NK_) \
02443 {\
02444 FCT_NLIST_FOREACH_BGN(fct_logger_i*, logger, &((_NK_)->logger_list))\
02445 {\
02446 fct_logger__on_fctx_start(logger, (_NK_));\
02447 }\
02448 FCT_NLIST_FOREACH_END();\
02449 }
02450
02451
02452 #define fctkern__log_end(_NK_) \
02453 {\
02454 FCT_NLIST_FOREACH_BGN(fct_logger_i*, logger, &((_NK_)->logger_list))\
02455 {\
02456 fct_logger__on_fctx_end(logger, (_NK_));\
02457 }\
02458 FCT_NLIST_FOREACH_END();\
02459 }
02460
02461
02462
02463
02464
02465
02466
02467
02468
02469
02470
02471
02472
02473
02474
02475
02476
02477
02478
02479 struct _fct_logger_evt_t
02480 {
02481 fctkern_t const *kern;
02482 fctchk_t const *chk;
02483 fct_test_t const *test;
02484 fct_ts_t const *ts;
02485 char const *msg;
02486 char const *cndtn;
02487 char const *name;
02488 };
02489
02490
02491 typedef struct _fct_logger_i_vtable_t
02492 {
02493
02494
02495
02496
02497 void (*on_chk)(fct_logger_i *logger, fct_logger_evt_t const *e);
02498
02499
02500
02501
02502 void (*on_test_start)(
02503 fct_logger_i *logger,
02504 fct_logger_evt_t const *e
02505 );
02506
02507 void (*on_test_end)(
02508 fct_logger_i *logger,
02509 fct_logger_evt_t const *e
02510 );
02511
02512 void (*on_test_suite_start)(
02513 fct_logger_i *logger,
02514 fct_logger_evt_t const *e
02515 );
02516
02517 void (*on_test_suite_end)(
02518 fct_logger_i *logger,
02519 fct_logger_evt_t const *e
02520 );
02521
02522 void (*on_fctx_start)(
02523 fct_logger_i *logger,
02524 fct_logger_evt_t const *e
02525 );
02526
02527 void (*on_fctx_end)(
02528 fct_logger_i *logger,
02529 fct_logger_evt_t const *e
02530 );
02531
02532
02533 void (*on_delete)(
02534 fct_logger_i *logger,
02535 fct_logger_evt_t const *e
02536 );
02537
02538 void (*on_warn)(
02539 fct_logger_i *logger,
02540 fct_logger_evt_t const *e
02541 );
02542
02543
02544 void (*on_test_suite_skip)(
02545 fct_logger_i *logger,
02546 fct_logger_evt_t const *e
02547 );
02548
02549 void (*on_test_skip)(
02550 fct_logger_i *logger,
02551 fct_logger_evt_t const *e
02552 );
02553 } fct_logger_i_vtable_t;
02554
02555 #define _fct_logger_head \
02556 fct_logger_i_vtable_t vtable; \
02557 fct_logger_evt_t evt
02558
02559 struct _fct_logger_i
02560 {
02561 _fct_logger_head;
02562 };
02563
02564
02565 static void
02566 fct_logger__stub(fct_logger_i *l, fct_logger_evt_t const *e)
02567 {
02568 fct_unused(l);
02569 fct_unused(e);
02570 }
02571
02572
02573 static fct_logger_i_vtable_t fct_logger_default_vtable =
02574 {
02575 fct_logger__stub,
02576 fct_logger__stub,
02577 fct_logger__stub,
02578 fct_logger__stub,
02579 fct_logger__stub,
02580 fct_logger__stub,
02581 fct_logger__stub,
02582 fct_logger__stub,
02583 fct_logger__stub,
02584 fct_logger__stub,
02585 fct_logger__stub,
02586 };
02587
02588
02589
02590
02591 static void
02592 fct_logger__init(fct_logger_i *logger)
02593 {
02594 FCT_ASSERT( logger != NULL );
02595 memcpy(
02596 &(logger->vtable),
02597 &fct_logger_default_vtable,
02598 sizeof(fct_logger_i_vtable_t)
02599 );
02600 memset(&(logger->evt),0, sizeof(fct_logger_evt_t));
02601 }
02602
02603 static void
02604 fct_logger__del(fct_logger_i *logger)
02605 {
02606 if ( logger )
02607 {
02608 logger->vtable.on_delete(logger, &(logger->evt));
02609 }
02610 }
02611
02612
02613 static void
02614 fct_logger__on_test_start(fct_logger_i *logger, fct_test_t const *test)
02615 {
02616 logger->evt.test = test;
02617 logger->vtable.on_test_start(logger, &(logger->evt));
02618 }
02619
02620
02621 static void
02622 fct_logger__on_test_end(fct_logger_i *logger, fct_test_t *test)
02623 {
02624 logger->evt.test = test;
02625 logger->vtable.on_test_end(logger, &(logger->evt));
02626 }
02627
02628
02629 static void
02630 fct_logger__on_test_suite_start(fct_logger_i *logger, fct_ts_t const *ts)
02631 {
02632 logger->evt.ts = ts;
02633 logger->vtable.on_test_suite_start(logger, &(logger->evt));
02634 }
02635
02636
02637 static void
02638 fct_logger__on_test_suite_end(fct_logger_i *logger, fct_ts_t const *ts)
02639 {
02640 logger->evt.ts = ts;
02641 logger->vtable.on_test_suite_end(logger, &(logger->evt));
02642 }
02643
02644
02645 static void
02646 fct_logger__on_test_suite_skip(
02647 fct_logger_i *logger,
02648 char const *condition,
02649 char const *name
02650 )
02651 {
02652 logger->evt.cndtn = condition;
02653 logger->evt.name = name;
02654 logger->vtable.on_test_suite_skip(logger, &(logger->evt));
02655 }
02656
02657
02658 static void
02659 fct_logger__on_test_skip(
02660 fct_logger_i *logger,
02661 char const *condition,
02662 char const *name
02663 )
02664 {
02665 logger->evt.cndtn = condition;
02666 logger->evt.name = name;
02667 logger->vtable.on_test_skip(logger, &(logger->evt));
02668 }
02669
02670
02671 static void
02672 fct_logger__on_chk(fct_logger_i *logger, fctchk_t const *chk)
02673 {
02674 logger->evt.chk = chk;
02675 logger->vtable.on_chk(logger, &(logger->evt));
02676 }
02677
02678
02679 #define fct_logger__on_fctx_start(LOGGER, KERN) \
02680 (LOGGER)->evt.kern = (KERN);\
02681 (LOGGER)->vtable.on_fctx_start((LOGGER), &((LOGGER)->evt));
02682
02683
02684
02685 #define fct_logger__on_fctx_end(LOGGER, KERN) \
02686 (LOGGER)->evt.kern = (KERN);\
02687 (LOGGER)->vtable.on_fctx_end((LOGGER), &((LOGGER)->evt));
02688
02689
02690 static void
02691 fct_logger__on_warn(fct_logger_i *logger, char const *msg)
02692 {
02693 logger->evt.msg = msg;
02694 logger->vtable.on_warn(logger, &(logger->evt));
02695 }
02696
02697
02698
02699
02700
02701 static void
02702 fct_logger_record_failure(fctchk_t const* chk, fct_nlist_t* fail_list)
02703 {
02704
02705
02706 char *str = (char*)malloc(sizeof(char)*FCT_MAX_LOG_LINE);
02707 FCT_ASSERT( str != NULL );
02708 fct_snprintf(
02709 str,
02710 FCT_MAX_LOG_LINE,
02711 "%s(%d):\n %s",
02712 fctchk__file(chk),
02713 fctchk__lineno(chk),
02714 fctchk__msg(chk)
02715 );
02716
02717 fct_nlist__append(fail_list, (void*)str);
02718 }
02719
02720
02721
02722 static void
02723 fct_logger_print_failures(fct_nlist_t const *fail_list)
02724 {
02725 puts(
02726 "\n----------------------------------------------------------------------------\n"
02727 );
02728 puts("FAILED TESTS\n\n");
02729 FCT_NLIST_FOREACH_BGN(char *, cndtn_str, fail_list)
02730 {
02731 printf("%s\n", cndtn_str);
02732 }
02733 FCT_NLIST_FOREACH_END();
02734
02735 puts("\n");
02736 }
02737
02738
02739
02740
02741
02742
02743
02744
02745
02746
02747
02748
02749
02750
02751
02752
02753
02754
02755 struct _fct_minimal_logger_t
02756 {
02757 _fct_logger_head;
02758
02759 fct_nlist_t failed_cndtns_list;
02760 };
02761
02762
02763 static void
02764 fct_minimal_logger__on_chk(
02765 fct_logger_i *self_,
02766 fct_logger_evt_t const *e
02767 )
02768 {
02769 fct_minimal_logger_t *self = (fct_minimal_logger_t*)self_;
02770 if ( fctchk__is_pass(e->chk) )
02771 {
02772 fputs(".", stdout);
02773 }
02774 else
02775 {
02776 fputs("x", stdout);
02777 fct_logger_record_failure(e->chk, &(self->failed_cndtns_list));
02778
02779 }
02780 }
02781
02782 static void
02783 fct_minimal_logger__on_fctx_end(
02784 fct_logger_i *self_,
02785 fct_logger_evt_t const *e
02786 )
02787 {
02788 fct_minimal_logger_t *self = (fct_minimal_logger_t*)self_;
02789 fct_unused(e);
02790 if ( fct_nlist__size(&(self->failed_cndtns_list)) >0 )
02791 {
02792 fct_logger_print_failures(&(self->failed_cndtns_list));
02793 }
02794 }
02795
02796
02797 static void
02798 fct_minimal_logger__on_delete(
02799 fct_logger_i *self_,
02800 fct_logger_evt_t const *e
02801 )
02802 {
02803 fct_minimal_logger_t *self = (fct_minimal_logger_t*)self_;
02804 fct_unused(e);
02805 fct_nlist__final(&(self->failed_cndtns_list), free);
02806 free(self);
02807
02808 }
02809
02810
02811 fct_logger_i*
02812 fct_minimal_logger_new(void)
02813 {
02814 fct_minimal_logger_t *self = (fct_minimal_logger_t*)\
02815 calloc(1,sizeof(fct_minimal_logger_t));
02816 if ( self == NULL )
02817 {
02818 return NULL;
02819 }
02820 fct_logger__init((fct_logger_i*)self);
02821 self->vtable.on_chk = fct_minimal_logger__on_chk;
02822 self->vtable.on_fctx_end = fct_minimal_logger__on_fctx_end;
02823 self->vtable.on_delete = fct_minimal_logger__on_delete;
02824 fct_nlist__init2(&(self->failed_cndtns_list), 0);
02825 return (fct_logger_i*)self;
02826 }
02827
02828
02829
02830
02831
02832
02833
02834
02835 struct _fct_standard_logger_t
02836 {
02837 _fct_logger_head;
02838
02839
02840 fct_timer_t timer;
02841
02842
02843 fct_nlist_t failed_cndtns_list;
02844 };
02845
02846
02847 #define FCT_STANDARD_LOGGER_MAX_LINE 68
02848
02849
02850
02851
02852 static void
02853 fct_standard_logger__on_chk(
02854 fct_logger_i *logger_,
02855 fct_logger_evt_t const *e
02856 )
02857 {
02858 fct_standard_logger_t *logger = (fct_standard_logger_t*)logger_;
02859
02860 if ( !fctchk__is_pass(e->chk) )
02861 {
02862 fct_logger_record_failure(e->chk, &(logger->failed_cndtns_list));
02863 }
02864 }
02865
02866
02867 static void
02868 fct_standard_logger__on_test_skip(
02869 fct_logger_i* logger_,
02870 fct_logger_evt_t const *e
02871 )
02872 {
02873 char const *condition = e->cndtn;
02874 char const *name = e->name;
02875 char msg[256] = {'\0'};
02876 fct_unused(logger_);
02877 fct_unused(condition);
02878 fct_snprintf(msg, sizeof(msg), "%s (%s)", name, condition);
02879 msg[sizeof(msg)-1] = '\0';
02880 fct_dotted_line_start(FCT_STANDARD_LOGGER_MAX_LINE, msg);
02881 fct_dotted_line_end("- SKIP -");
02882 }
02883
02884
02885 static void
02886 fct_standard_logger__on_test_start(
02887 fct_logger_i *logger_,
02888 fct_logger_evt_t const *e
02889 )
02890 {
02891 fct_unused(logger_);
02892 fct_dotted_line_start(
02893 FCT_STANDARD_LOGGER_MAX_LINE,
02894 fct_test__name(e->test)
02895 );
02896 }
02897
02898
02899 static void
02900 fct_standard_logger__on_test_end(
02901 fct_logger_i *logger_,
02902 fct_logger_evt_t const *e
02903 )
02904 {
02905 nbool_t is_pass;
02906 fct_unused(logger_);
02907 is_pass = fct_test__is_pass(e->test);
02908 fct_dotted_line_end((is_pass) ? "PASS" : "FAIL ***" );
02909 }
02910
02911
02912 static void
02913 fct_standard_logger__on_fctx_start(
02914 fct_logger_i *logger_,
02915 fct_logger_evt_t const *e
02916 )
02917 {
02918 fct_standard_logger_t *logger = (fct_standard_logger_t*)logger_;
02919 fct_unused(e);
02920 fct_timer__start(&(logger->timer));
02921 }
02922
02923
02924 static void
02925 fct_standard_logger__on_fctx_end(
02926 fct_logger_i *logger_,
02927 fct_logger_evt_t const *e
02928 )
02929 {
02930 fct_standard_logger_t *logger = (fct_standard_logger_t*)logger_;
02931 nbool_t is_success =1;
02932 double elasped_time =0;
02933 size_t num_tests =0;
02934 size_t num_passed =0;
02935
02936 fct_timer__stop(&(logger->timer));
02937
02938 is_success = fct_nlist__size(&(logger->failed_cndtns_list)) ==0;
02939
02940 if ( !is_success )
02941 {
02942 fct_logger_print_failures(&(logger->failed_cndtns_list));
02943 }
02944 puts(
02945 "\n----------------------------------------------------------------------------\n"
02946 );
02947 num_tests = fctkern__tst_cnt(e->kern);
02948 num_passed = fctkern__tst_cnt_passed(e->kern);
02949 printf(
02950 "%s (%lu/%lu tests",
02951 (is_success) ? "PASSED" : "FAILED",
02952 (unsigned long) num_passed,
02953 (unsigned long) num_tests
02954 );
02955 elasped_time = fct_timer__duration(&(logger->timer));
02956 if ( elasped_time > 0.0000001 )
02957 {
02958 printf(" in %.6fs)\n", elasped_time);
02959 }
02960 else
02961 {
02962
02963 puts(")\n");
02964 }
02965 }
02966
02967
02968 static void
02969 fct_standard_logger__on_delete(
02970 fct_logger_i *logger_,
02971 fct_logger_evt_t const *e
02972 )
02973 {
02974 fct_standard_logger_t *logger = (fct_standard_logger_t*)logger_;
02975 fct_unused(e);
02976 fct_nlist__final(&(logger->failed_cndtns_list), free);
02977 free(logger);
02978 logger_ =NULL;
02979 }
02980
02981
02982 static void
02983 fct_standard_logger__on_warn(
02984 fct_logger_i* logger_,
02985 fct_logger_evt_t const *e
02986 )
02987 {
02988 fct_unused(logger_);
02989 (void)printf("WARNING: %s", e->msg);
02990 }
02991
02992
02993 fct_logger_i*
02994 fct_standard_logger_new(void)
02995 {
02996 fct_standard_logger_t *logger = (fct_standard_logger_t *)calloc(
02997 1, sizeof(fct_standard_logger_t)
02998 );
02999 if ( logger == NULL )
03000 {
03001 return NULL;
03002 }
03003 fct_logger__init((fct_logger_i*)logger);
03004 logger->vtable.on_chk = fct_standard_logger__on_chk;
03005 logger->vtable.on_test_start = fct_standard_logger__on_test_start;
03006 logger->vtable.on_test_end = fct_standard_logger__on_test_end;
03007 logger->vtable.on_fctx_start = fct_standard_logger__on_fctx_start;
03008 logger->vtable.on_fctx_end = fct_standard_logger__on_fctx_end;
03009 logger->vtable.on_delete = fct_standard_logger__on_delete;
03010 logger->vtable.on_warn = fct_standard_logger__on_warn;
03011 logger->vtable.on_test_skip = fct_standard_logger__on_test_skip;
03012 fct_nlist__init2(&(logger->failed_cndtns_list), 0);
03013 fct_timer__init(&(logger->timer));
03014 return (fct_logger_i*)logger;
03015 }
03016
03017
03018
03019
03020
03021
03022
03023
03024
03025
03026 struct _fct_junit_logger_t
03027 {
03028 _fct_logger_head;
03029 };
03030
03031
03032 static void
03033 fct_junit_logger__on_test_suite_start(
03034 fct_logger_i *l,
03035 fct_logger_evt_t const *e
03036 )
03037 {
03038 fct_unused(l);
03039 fct_unused(e);
03040 FCT_SWITCH_STDOUT_TO_BUFFER();
03041 FCT_SWITCH_STDERR_TO_BUFFER();
03042 }
03043
03044
03045 static void
03046 fct_junit_logger__on_test_suite_end(
03047 fct_logger_i *logger_,
03048 fct_logger_evt_t const *e
03049 )
03050 {
03051 fct_ts_t const *ts = e->ts;
03052 nbool_t is_pass;
03053 double elasped_time = 0;
03054 char std_buffer[1024];
03055 int read_length;
03056 int first_out_line;
03057
03058 fct_unused(logger_);
03059
03060 elasped_time = fct_ts__duration(ts);
03061
03062 FCT_SWITCH_STDOUT_TO_STDOUT();
03063 FCT_SWITCH_STDERR_TO_STDERR();
03064
03065
03066 printf("\t<testsuite errors=\"%lu\" failures=\"0\" tests=\"%lu\" "
03067 "name=\"%s\" time=\"%.4f\">\n",
03068 (unsigned long) fct_ts__tst_cnt(ts)
03069 - fct_ts__tst_cnt_passed(ts),
03070 (unsigned long) fct_ts__tst_cnt(ts),
03071 fct_ts__name(ts),
03072 elasped_time);
03073
03074 FCT_NLIST_FOREACH_BGN(fct_test_t*, test, &(ts->test_list))
03075 {
03076 is_pass = fct_test__is_pass(test);
03077
03078
03079 if (is_pass)
03080 {
03081 printf("\t\t<testcase name=\"%s\" time=\"%.3f\"",
03082 fct_test__name(test),
03083 fct_test__duration(test)
03084 );
03085 }
03086 else
03087 {
03088 printf("\t\t<testcase name=\"%s\" time=\"%.3f\">\n",
03089 fct_test__name(test),
03090 fct_test__duration(test)
03091 );
03092 }
03093
03094 FCT_NLIST_FOREACH_BGN(fctchk_t*, chk, &(test->failed_chks))
03095 {
03096
03097 printf("\t\t\t<error message=\"%s\" "
03098 "type=\"fctx\">", chk->msg);
03099 printf("file:%s, line:%d", chk->file, chk->lineno);
03100 printf("</error>\n");
03101 }
03102 FCT_NLIST_FOREACH_END();
03103
03104
03105 if (is_pass)
03106 {
03107 printf(" />\n");
03108 }
03109 else
03110 {
03111 printf("\t\t</testcase>\n");
03112 }
03113 }
03114 FCT_NLIST_FOREACH_END();
03115
03116
03117 first_out_line = 1;
03118 printf("\t\t<system-out>\n\t\t\t<![CDATA[");
03119 while ( (read_length = _fct_read(fct_stdout_pipe[0], std_buffer, 1024)) > 0)
03120 {
03121 if (first_out_line)
03122 {
03123 printf("\n");
03124 first_out_line = 0;
03125 }
03126 printf("%.*s", read_length, std_buffer);
03127 }
03128 printf("]]>\n\t\t</system-out>\n");
03129
03130 first_out_line = 1;
03131 printf("\t\t<system-err>\n\t\t\t<![CDATA[");
03132 while ((read_length = _fct_read(fct_stderr_pipe[0], std_buffer, 1024)) > 0)
03133 {
03134 if (first_out_line)
03135 {
03136 printf("\n");
03137 first_out_line = 0;
03138 }
03139 printf("%.*s", read_length, std_buffer);
03140 }
03141 printf("]]>\n\t\t</system-err>\n");
03142
03143
03144 printf("\t</testsuite>\n");
03145 }
03146
03147 static void
03148 fct_junit_logger__on_fct_start(
03149 fct_logger_i *logger_,
03150 fct_logger_evt_t const *e
03151 )
03152 {
03153 fct_unused(logger_);
03154 fct_unused(e);
03155 printf("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n");
03156 printf("<testsuites>\n");
03157 }
03158
03159 static void
03160 fct_junit_logger__on_fctx_end(
03161 fct_logger_i *logger_,
03162 fct_logger_evt_t const *e
03163 )
03164 {
03165 fct_unused(logger_);
03166 fct_unused(e);
03167 printf("</testsuites>\n");
03168 }
03169
03170 static void
03171 fct_junit_logger__on_delete(
03172 fct_logger_i *logger_,
03173 fct_logger_evt_t const *e
03174 )
03175 {
03176 fct_junit_logger_t *logger = (fct_junit_logger_t*)logger_;
03177 fct_unused(e);
03178 free(logger);
03179 logger_ =NULL;
03180 }
03181
03182
03183 fct_junit_logger_t *
03184 fct_junit_logger_new(void)
03185 {
03186 fct_junit_logger_t *logger =
03187 (fct_junit_logger_t *)calloc(1, sizeof(fct_junit_logger_t));
03188 if ( logger == NULL )
03189 {
03190 return NULL;
03191 }
03192 fct_logger__init((fct_logger_i*)logger);
03193 logger->vtable.on_test_suite_start = fct_junit_logger__on_test_suite_start;
03194 logger->vtable.on_test_suite_end = fct_junit_logger__on_test_suite_end;
03195 logger->vtable.on_fctx_start = fct_junit_logger__on_fct_start;
03196 logger->vtable.on_fctx_end = fct_junit_logger__on_fctx_end;
03197 logger->vtable.on_delete = fct_junit_logger__on_delete;
03198 return logger;
03199 }
03200
03201
03202
03203
03204
03205
03206
03207
03208
03209
03210
03211
03212
03213 #define FCT_REFERENCE_FUNCS() \
03214 {\
03215 int check = 0 && fctstr_ieq(NULL, NULL);\
03216 if ( check ) {\
03217 _fct_cmt("not to be executed");\
03218 (void)_fct_chk_empty_str(NULL);\
03219 (void)_fct_chk_full_str(NULL);\
03220 (void)fct_test__start_timer(NULL);\
03221 (void)fct_test__stop_timer(NULL);\
03222 (void)fct_ts_new(NULL);\
03223 (void)fct_ts__test_begin(NULL);\
03224 (void)fct_ts__add_test(NULL, NULL);\
03225 (void)fct_ts__test_end(NULL);\
03226 (void)fct_ts__inc_total_test_num(NULL);\
03227 (void)fct_ts__make_abort_test(NULL);\
03228 (void)fct_ts__setup_abort(NULL);\
03229 (void)fct_ts__setup_end(NULL);\
03230 (void)fct_ts__teardown_end(NULL);\
03231 (void)fct_ts__cnt_end(NULL);\
03232 (void)fct_ts__is_test_cnt(NULL, 0);\
03233 (void)fct_xchk_fn(0, "");\
03234 (void)fct_xchk2_fn(NULL, 0, "");\
03235 (void)fctkern__cl_parse(NULL);\
03236 (void)fctkern__add_ts(NULL, NULL);\
03237 (void)fctkern__pass_filter(NULL, NULL);\
03238 (void)fctkern__log_suite_start(NULL, NULL);\
03239 (void)fctkern__log_suite_end(NULL, NULL);\
03240 (void)fctkern__log_test_skip(NULL, NULL, NULL);\
03241 (void)fctkern__log_test_start(NULL, NULL);\
03242 (void)fctkern__log_test_end(NULL, NULL);\
03243 (void)fctstr_endswith(NULL,NULL);\
03244 (void)fctstr_iendswith(NULL,NULL);\
03245 (void)fctstr_ieq(NULL,NULL);\
03246 (void)fctstr_incl(NULL, NULL);\
03247 (void)fctstr_iincl(NULL, NULL);\
03248 (void)fctstr_iendswith(NULL,NULL);\
03249 (void)fctstr_istartswith(NULL,NULL);\
03250 (void)fctstr_clone_lower(NULL);\
03251 (void)fctstr_startswith(NULL,NULL);\
03252 (void)fctkern__init(NULL, 0, NULL);\
03253 (void)fctkern__cl_is(NULL, "");\
03254 (void)fctkern__cl_val2(NULL, NULL, NULL);\
03255 fctkern__log_suite_skip(NULL, NULL, NULL);\
03256 (void)fct_clp__is_param(NULL,NULL);\
03257 _fct_cmt("should never construct an object");\
03258 (void)fct_test_new(NULL);\
03259 (void)fct_ts__chk_cnt(NULL);\
03260 }\
03261 }
03262
03263
03264 #define FCT_INIT(_ARGC_, _ARGV_) \
03265 fctkern_t fctkern__; \
03266 fctkern_t* fctkern_ptr__ = &fctkern__; \
03267 FCT_REFERENCE_FUNCS(); \
03268 if ( !fctkern__init(fctkern_ptr__, argc, (const char **)argv) ) {\
03269 (void)fprintf( \
03270 stderr, "FATAL ERROR: Unable to initialize FCTX Kernel."\
03271 ); \
03272 exit(EXIT_FAILURE); \
03273 } \
03274
03275
03276 #define FCT_FINAL() \
03277 fctkern_ptr__->ns.num_total_failed = fctkern__tst_cnt_failed( \
03278 (fctkern_ptr__) \
03279 ); \
03280 fctkern__log_end(fctkern_ptr__); \
03281 fctkern__end(fctkern_ptr__); \
03282 fctkern__final(fctkern_ptr__); \
03283 FCT_ASSERT( !((int)fctkern_ptr__->ns.num_total_failed < 0) \
03284 && "or we got truncated!"); \
03285 if ( fctkern_ptr__->ns.num_total_failed == \
03286 fctkern_ptr__->num_expected_failures) { \
03287 fctkern_ptr__->ns.num_total_failed = 0; \
03288 } \
03289
03290
03291
03292 #define FCT_NUM_FAILED() \
03293 fctkern_ptr__->ns.num_total_failed \
03294
03295
03296
03297
03298
03299
03300 #define FCT_EXPECTED_FAILURES(_NUM_FAILS_) \
03301 ((fctkern_ptr__->num_expected_failures = (_NUM_FAILS_)))
03302
03303
03304 #define FCT_BGN_FN(_FNNAME_) \
03305 int _FNNAME_(int argc, char* argv[])\
03306 { \
03307 FCT_INIT(argc, argv)
03308
03309 #define FCT_END_FN() FCT_END()
03310
03311
03312
03313
03314 #define FCT_BGN() FCT_BGN_FN(main)
03315
03316
03317
03318 #ifndef __INTEL_COMPILER
03319 # define FCT_END_WARNINGFIX_BGN
03320 # define FCT_END_WARNINGFIX_END
03321 #else
03322 # define FCT_END_WARNINGFIX_BGN _Pragma("warning(push,disable:981)");
03323 # define FCT_END_WARNINGFIX_END _Pragma("warning(pop)");
03324 #endif
03325
03326
03327
03328
03329 #define FCT_END() \
03330 { \
03331 FCT_END_WARNINGFIX_BGN \
03332 FCT_FINAL(); \
03333 return FCT_NUM_FAILED();\
03334 FCT_END_WARNINGFIX_END \
03335 }\
03336 }
03337
03338 #define fctlog_install(_CUST_LOGGER_LIST_) \
03339 fctkern_ptr__->lt_usr = (_CUST_LOGGER_LIST_)
03340
03341
03342
03343 #define fctcl_install(_CLO_INIT_) \
03344 {\
03345 fctkern_ptr__->cl_user_opts = (_CLO_INIT_);\
03346 _fct_cmt("Delay parse in order to allow for user customization.");\
03347 if ( !fctkern__cl_is_parsed((fctkern_ptr__)) ) {\
03348 int status = fctkern__cl_parse((fctkern_ptr__));\
03349 _fct_cmt("Need to parse command line before we start logger.");\
03350 fctkern__log_start((fctkern_ptr__));\
03351 switch( status ) {\
03352 case -1:\
03353 case 0:\
03354 fctkern__final(fctkern_ptr__);\
03355 exit( (status == 0) ? (EXIT_FAILURE) : (EXIT_SUCCESS) );\
03356 break;\
03357 default:\
03358 fct_pass();\
03359 }\
03360 }\
03361 }
03362
03363
03364 #define fctcl_is(_OPT_STR_) (fctkern__cl_is(fctkern_ptr__, (_OPT_STR_)))
03365
03366 #define fctcl_val(_OPT_STR_) (fctcl_val2((_OPT_STR_), NULL))
03367
03368 #define fctcl_val2(_OPT_STR_, _DEF_STR_) \
03369 (fctkern__cl_val2(fctkern_ptr__, (_OPT_STR_), (_DEF_STR_)))
03370
03371
03372
03373
03374
03375 #define FCT_FIXTURE_SUITE_BGN(_NAME_) \
03376 {\
03377 fctkern_ptr__->ns.ts_curr = fct_ts_new( #_NAME_ );\
03378 _fct_cmt("Delay parse in order to allow for user customization.");\
03379 if ( !fctkern__cl_is_parsed((fctkern_ptr__)) ) {\
03380 int status = fctkern__cl_parse((fctkern_ptr__));\
03381 _fct_cmt("Need to parse command line before we start logger.");\
03382 fctkern__log_start((fctkern_ptr__));\
03383 switch( status ) {\
03384 case -1:\
03385 case 0:\
03386 fct_ts__del((fctkern_ptr__->ns.ts_curr));\
03387 fctkern__final(fctkern_ptr__);\
03388 exit( (status == 0) ? (EXIT_FAILURE) : (EXIT_SUCCESS) );\
03389 break;\
03390 default:\
03391 fct_pass();\
03392 }\
03393 }\
03394 if ( fctkern_ptr__->ns.ts_curr == NULL ) {\
03395 fctkern__log_warn((fctkern_ptr__), "out of memory");\
03396 }\
03397 else\
03398 {\
03399 fctkern__log_suite_start((fctkern_ptr__), fctkern_ptr__->ns.ts_curr);\
03400 for (;;)\
03401 {\
03402 fctkern_ptr__->ns.test_num = -1;\
03403 if ( fct_ts__is_ending_mode(fctkern_ptr__->ns.ts_curr) \
03404 || fct_ts__is_abort_mode(fctkern_ptr__->ns.ts_curr) )\
03405 {\
03406 _fct_cmt("flag the test suite as complete.");\
03407 fct_ts__end(fctkern_ptr__->ns.ts_curr);\
03408 break;\
03409 }
03410
03411
03412
03413
03414 #define FCT_FIXTURE_SUITE_END() \
03415 if ( fct_ts__is_cnt_mode(fctkern_ptr__->ns.ts_curr) )\
03416 {\
03417 fct_ts__cnt_end(fctkern_ptr__->ns.ts_curr);\
03418 }\
03419 }\
03420 fctkern__add_ts((fctkern_ptr__), fctkern_ptr__->ns.ts_curr);\
03421 fctkern__log_suite_end((fctkern_ptr__), fctkern_ptr__->ns.ts_curr);\
03422 fct_ts__end(fctkern_ptr__->ns.ts_curr);\
03423 fctkern_ptr__->ns.ts_curr = NULL;\
03424 }\
03425 }
03426
03427 #define FCT_FIXTURE_SUITE_BGN_IF(_CONDITION_, _NAME_) \
03428 fctkern_ptr__->ns.ts_is_skip_suite = !(_CONDITION_);\
03429 fctkern_ptr__->ns.ts_skip_cndtn = #_CONDITION_;\
03430 if ( fctkern_ptr__->ns.ts_is_skip_suite ) {\
03431 fctkern__log_suite_skip((fctkern_ptr__), #_CONDITION_, #_NAME_);\
03432 }\
03433 FCT_FIXTURE_SUITE_BGN(_NAME_);
03434
03435 #define FCT_FIXTURE_SUITE_END_IF() \
03436 FCT_FIXTURE_SUITE_END();\
03437 fctkern_ptr__->ns.ts_is_skip_suite =0;\
03438 fctkern_ptr__->ns.ts_skip_cndtn =NULL;\
03439
03440 #define FCT_SETUP_BGN()\
03441 if ( fct_ts__is_setup_mode(fctkern_ptr__->ns.ts_curr) ) {
03442
03443 #define FCT_SETUP_END() \
03444 fct_ts__setup_end(fctkern_ptr__->ns.ts_curr); }
03445
03446 #define FCT_TEARDOWN_BGN() \
03447 if ( fct_ts__is_teardown_mode(fctkern_ptr__->ns.ts_curr) ) {\
03448
03449 #define FCT_TEARDOWN_END() \
03450 fct_ts__teardown_end(fctkern_ptr__->ns.ts_curr); \
03451 continue; \
03452 }
03453
03454
03455
03456 #define FCT_SUITE_BGN(Name) \
03457 FCT_FIXTURE_SUITE_BGN(Name) {\
03458 FCT_SETUP_BGN() {_fct_cmt("stubbed"); } FCT_SETUP_END()\
03459 FCT_TEARDOWN_BGN() {_fct_cmt("stubbed");} FCT_TEARDOWN_END()\
03460
03461 #define FCT_SUITE_END() } FCT_FIXTURE_SUITE_END()
03462
03463 #define FCT_SUITE_BGN_IF(_CONDITION_, _NAME_) \
03464 FCT_FIXTURE_SUITE_BGN_IF(_CONDITION_, (_NAME_)) {\
03465 FCT_SETUP_BGN() {_fct_cmt("stubbed"); } FCT_SETUP_END()\
03466 FCT_TEARDOWN_BGN() {_fct_cmt("stubbed");} FCT_TEARDOWN_END()\
03467
03468 #define FCT_SUITE_END_IF() } FCT_FIXTURE_SUITE_END_IF()
03469
03470 typedef enum
03471 {
03472 FCT_TEST_END_FLAG_Default = 0x0000,
03473 FCT_TEST_END_FLAG_ClearFail = 0x0001
03474 } FCT_TEST_END_FLAG;
03475
03476
03477 #define FCT_TEST_BGN_IF(_CONDITION_, _NAME_) { \
03478 fctkern_ptr__->ns.test_is_skip = !(_CONDITION_);\
03479 fctkern_ptr__->ns.test_skip_cndtn = #_CONDITION_;\
03480 FCT_TEST_BGN(_NAME_) {\
03481
03482 #define FCT_TEST_END_IF() \
03483 } FCT_TEST_END();\
03484 fctkern_ptr__->ns.test_is_skip = 0;\
03485 fctkern_ptr__->ns.test_skip_cndtn = NULL;\
03486 }
03487
03488
03489
03490
03491
03492
03493
03494
03495 #define FCT_TEST_BGN(_NAME_) \
03496 {\
03497 fctkern_ptr__->ns.curr_test_name = #_NAME_;\
03498 ++(fctkern_ptr__->ns.test_num);\
03499 if ( fct_ts__is_cnt_mode(fctkern_ptr__->ns.ts_curr) )\
03500 {\
03501 fct_ts__inc_total_test_num(fctkern_ptr__->ns.ts_curr);\
03502 }\
03503 else if ( fct_ts__is_test_mode(fctkern_ptr__->ns.ts_curr) \
03504 && fct_ts__is_test_cnt(fctkern_ptr__->ns.ts_curr, fctkern_ptr__->ns.test_num) )\
03505 {\
03506 fct_ts__test_begin(fctkern_ptr__->ns.ts_curr);\
03507 if ( fctkern__pass_filter(fctkern_ptr__, fctkern_ptr__->ns.curr_test_name ) )\
03508 {\
03509 fctkern_ptr__->ns.curr_test = fct_test_new( fctkern_ptr__->ns.curr_test_name );\
03510 if ( fctkern_ptr__->ns.curr_test == NULL ) {\
03511 fctkern__log_warn(fctkern_ptr__, "out of memory");\
03512 } else if ( fctkern_ptr__->ns.ts_is_skip_suite \
03513 || fctkern_ptr__->ns.test_is_skip ) {\
03514 fct_ts__test_begin(fctkern_ptr__->ns.ts_curr);\
03515 fctkern__log_test_skip(\
03516 fctkern_ptr__,\
03517 fctkern_ptr__->ns.curr_test_name,\
03518 (fctkern_ptr__->ns.test_is_skip) ?\
03519 (fctkern_ptr__->ns.test_skip_cndtn) :\
03520 (fctkern_ptr__->ns.ts_skip_cndtn)\
03521 );\
03522 fct_ts__test_end(fctkern_ptr__->ns.ts_curr);\
03523 continue;\
03524 } else {\
03525 fctkern__log_test_start(fctkern_ptr__, fctkern_ptr__->ns.curr_test);\
03526 fct_test__start_timer(fctkern_ptr__->ns.curr_test);\
03527 for (;;) \
03528 {
03529
03530
03531
03532
03533 #define FCT_TEST_END() \
03534 break;\
03535 }\
03536 fct_test__stop_timer(fctkern_ptr__->ns.curr_test);\
03537 }\
03538 fct_ts__add_test(fctkern_ptr__->ns.ts_curr, fctkern_ptr__->ns.curr_test);\
03539 fctkern__log_test_end(fctkern_ptr__, fctkern_ptr__->ns.curr_test);\
03540 }\
03541 fct_ts__test_end(fctkern_ptr__->ns.ts_curr);\
03542 continue;\
03543 }\
03544 }\
03545
03546
03547
03548
03549
03550
03551
03552
03553
03554
03555
03556
03557
03558
03559
03560
03561
03562
03563
03564
03565
03566 static int fct_xchk_lineno =0;
03567 static char const *fct_xchk_file = NULL;
03568 static fct_test_t *fct_xchk_test = NULL;
03569 static fctkern_t *fct_xchk_kern =NULL;
03570
03571
03572 static int
03573 _fct_xchk_fn_varg(
03574 char const *condition,
03575 int is_pass,
03576 char const *format,
03577 va_list args
03578 )
03579 {
03580 fctchk_t *chk =NULL;
03581 chk = fctchk_new(
03582 is_pass,
03583 condition,
03584 fct_xchk_file,
03585 fct_xchk_lineno,
03586 format,
03587 args
03588 );
03589 if ( chk == NULL )
03590 {
03591 fctkern__log_warn(fct_xchk_kern, "out of memory (aborting test)");
03592 goto finally;
03593 }
03594
03595 fct_test__add(fct_xchk_test, chk);
03596 fctkern__log_chk(fct_xchk_kern, chk);
03597 finally:
03598 fct_xchk_lineno =0;
03599 fct_xchk_file =NULL;
03600 fct_xchk_test =NULL;
03601 fct_xchk_kern =NULL;
03602 return is_pass;
03603 }
03604
03605
03606 static int
03607 fct_xchk2_fn(const char *condition, int is_pass, char const *format, ...)
03608 {
03609 int r =0;
03610 va_list args;
03611 va_start(args, format);
03612 r = _fct_xchk_fn_varg(condition, is_pass, format, args);
03613 va_end(args);
03614 return r;
03615 }
03616
03617
03618 static int
03619 fct_xchk_fn(int is_pass, char const *format, ...)
03620 {
03621 int r=0;
03622 va_list args;
03623 va_start(args, format);
03624 r = _fct_xchk_fn_varg("<none-from-xchk>", is_pass, format, args);
03625 va_end(args);
03626 return r;
03627 }
03628
03629
03630
03631
03632
03633
03634
03635
03636
03637 #define fct_xchk fct_xchk_kern = fctkern_ptr__,\
03638 fct_xchk_test = fctkern_ptr__->ns.curr_test,\
03639 fct_xchk_lineno =__LINE__,\
03640 fct_xchk_file=__FILE__,\
03641 fct_xchk_fn
03642
03643 #define fct_xchk2 fct_xchk_kern = fctkern_ptr__,\
03644 fct_xchk_test = fctkern_ptr__->ns.curr_test,\
03645 fct_xchk_lineno =__LINE__,\
03646 fct_xchk_file=__FILE__,\
03647 fct_xchk2_fn
03648
03649
03650
03651
03652 #define fct_chk(_CNDTN_) (fct_xchk((_CNDTN_) ? 1 : 0, #_CNDTN_))
03653
03654 #define _fct_req(_CNDTN_) \
03655 if ( !(fct_xchk((_CNDTN_) ? 1 : 0, #_CNDTN_)) ) { break; }
03656
03657
03658
03659
03660 #define fct_req(_CNDTN_) \
03661 if ( fct_ts__is_test_mode(fctkern_ptr__->ns.ts_curr) ) { \
03662 _fct_req((_CNDTN_)); \
03663 } \
03664 else if ( fct_ts__is_setup_mode(fctkern_ptr__->ns.ts_curr) \
03665 || fct_ts__is_teardown_mode(fctkern_ptr__->ns.ts_curr) ) { \
03666 fctkern_ptr__->ns.curr_test = fct_ts__make_abort_test( \
03667 fctkern_ptr__->ns.ts_curr \
03668 ); \
03669 if ( !(fct_xchk((_CNDTN_) ? 1 : 0, #_CNDTN_)) ) { \
03670 fct_ts__setup_abort(fctkern_ptr__->ns.ts_curr); \
03671 fct_ts__add_test( \
03672 fctkern_ptr__->ns.ts_curr, fctkern_ptr__->ns.curr_test \
03673 ); \
03674 } \
03675 } else { \
03676 assert("invalid condition for fct_req!"); \
03677 _fct_req((_CNDTN_)); \
03678 }
03679
03680
03681 #define fct_chk_eq_dbl(V1, V2) \
03682 fct_xchk(\
03683 ((int)(fabs((V1)-(V2)) < DBL_EPSILON)),\
03684 "chk_eq_dbl: %f != %f",\
03685 (V1),\
03686 (V2)\
03687 )
03688
03689
03690 #define fct_chk_neq_dbl(V1, V2) \
03691 fct_xchk(\
03692 ((int)(fabs((V1)-(V2)) >= DBL_EPSILON)),\
03693 "chk_neq_dbl: %f == %f",\
03694 (V1),\
03695 (V2)\
03696 )
03697
03698
03699 #define fct_chk_eq_str(V1, V2) \
03700 fct_xchk(fctstr_eq((V1), (V2)),\
03701 "chk_eq_str: '%s' != '%s'",\
03702 (V1),\
03703 (V2)\
03704 )
03705
03706
03707 #define fct_chk_neq_str(V1, V2) \
03708 fct_xchk(!fctstr_eq((V1), (V2)),\
03709 "chk_neq_str: '%s' == '%s'",\
03710 (V1),\
03711 (V2)\
03712 )
03713
03714
03715
03716
03717 static int
03718 _fct_chk_empty_str(char const *s)
03719 {
03720 if ( s == NULL )
03721 {
03722 return 1;
03723 }
03724 return strlen(s) ==0;
03725 }
03726 static int
03727 _fct_chk_full_str(char const *s)
03728 {
03729 if ( s == NULL )
03730 {
03731 return 0;
03732 }
03733 return strlen(s) >0;
03734 }
03735
03736
03737 #define fct_chk_empty_str(V) \
03738 fct_xchk(_fct_chk_empty_str((V)),\
03739 "string not empty: '%s'",\
03740 (V)\
03741 )
03742
03743 #define fct_chk_full_str(V) \
03744 fct_xchk(_fct_chk_full_str((V)),\
03745 "string is full: '%s'",\
03746 (V)\
03747 )
03748
03749
03750 #define fct_chk_eq_istr(V1, V2) \
03751 fct_xchk(fctstr_ieq((V1), (V2)),\
03752 "chk_eq_str: '%s' != '%s'",\
03753 (V1),\
03754 (V2)\
03755 )
03756
03757
03758 #define fct_chk_neq_istr(V1, V2) \
03759 fct_xchk(!fctstr_ieq((V1), (V2)),\
03760 "chk_neq_str: '%s' == '%s'",\
03761 (V1),\
03762 (V2)\
03763 )
03764
03765
03766 #define fct_chk_endswith_str(STR, CHECK)\
03767 fct_xchk(fctstr_endswith((STR),(CHECK)),\
03768 "fct_chk_endswith_str: '%s' doesn't end with '%s'",\
03769 (STR),\
03770 (CHECK)\
03771 )
03772
03773
03774 #define fct_chk_iendswith_str(STR, CHECK)\
03775 fct_xchk(fctstr_iendswith((STR), (CHECK)),\
03776 "fch_chk_iendswith_str: '%s' doesn't end with '%s'.",\
03777 (STR),\
03778 (CHECK)\
03779 )
03780
03781 #define fct_chk_excl_str(STR, CHECK_EXCLUDE) \
03782 fct_xchk(!fctstr_incl((STR), (CHECK_EXCLUDE)),\
03783 "fct_chk_excl_str: '%s' is included in '%s'",\
03784 (STR),\
03785 (CHECK_EXCLUDE)\
03786 )
03787
03788 #define fct_chk_excl_istr(ISTR, ICHECK_EXCLUDE) \
03789 fct_xchk(!fctstr_iincl((ISTR), (ICHECK_EXCLUDE)),\
03790 "fct_chk_excl_istr (case insensitive): '%s' is "\
03791 "included in'%s'",\
03792 (ISTR),\
03793 (ICHECK_EXCLUDE)\
03794 )
03795
03796 #define fct_chk_incl_str(STR, CHECK_INCLUDE) \
03797 fct_xchk(fctstr_incl((STR), (CHECK_INCLUDE)),\
03798 "fct_chk_incl_str: '%s' does not include '%s'",\
03799 (STR),\
03800 (CHECK_INCLUDE)\
03801 )
03802
03803
03804 #define fct_chk_incl_istr(ISTR, ICHECK_INCLUDE) \
03805 fct_xchk(fctstr_iincl((ISTR), (ICHECK_INCLUDE)),\
03806 "fct_chk_incl_istr (case insensitive): '%s' does "\
03807 "not include '%s'",\
03808 (ISTR),\
03809 (ICHECK_INCLUDE)\
03810 )
03811
03812
03813 #define fct_chk_startswith_str(STR, CHECK)\
03814 fct_xchk(fctstr_startswith((STR), (CHECK)),\
03815 "'%s' does not start with '%s'",\
03816 (STR),\
03817 (CHECK)\
03818 )
03819
03820
03821 #define fct_chk_startswith_istr(STR, CHECK)\
03822 fct_xchk(fctstr_istartswith((STR), (CHECK)),\
03823 "case insensitive check: '%s' does not start with '%s'",\
03824 (STR),\
03825 (CHECK)\
03826 )
03827
03828 #define fct_chk_eq_int(V1, V2) \
03829 fct_xchk(\
03830 ((V1) == (V2)),\
03831 "chq_eq_int: %d != %d",\
03832 (V1),\
03833 (V2)\
03834 )
03835
03836
03837 #define fct_chk_neq_int(V1, V2) \
03838 fct_xchk(\
03839 ((V1) != (V2)),\
03840 "chq_neq_int: %d == %d",\
03841 (V1),\
03842 (V2)\
03843 )
03844
03845 #define fct_chk_ex(EXCEPTION, CODE) \
03846 { \
03847 bool pass_chk_ex = false; \
03848 try { \
03849 CODE; \
03850 pass_chk_ex = false; \
03851 } catch ( EXCEPTION ) { \
03852 pass_chk_ex = true; \
03853 } catch ( ... ) { \
03854 pass_chk_ex = false; \
03855 } \
03856 fct_xchk( \
03857 pass_chk_ex, \
03858 "%s exception not generated", \
03859 #EXCEPTION \
03860 ); \
03861 } \
03862
03863
03864
03865
03866
03867
03868
03869
03870
03871
03872
03873
03874 #define _FCT_GUTCHK(_CNDTN_) \
03875 if ( !(_CNDTN_) ) {\
03876 fprintf(stderr, "gutchk fail: '" #_CNDTN_ "' was not true.\n");\
03877 exit(1);\
03878 }\
03879 else {\
03880 fprintf(stdout, "gutchk pass: '" #_CNDTN_ "'\n");\
03881 }
03882
03883
03884
03885
03886
03887
03888
03889
03890
03891
03892
03893
03894
03895
03896
03897
03898
03899
03900
03901
03902
03903 #define FCTMF_FIXTURE_SUITE_BGN(NAME) \
03904 void NAME (fctkern_t *fctkern_ptr__) {\
03905 FCT_REFERENCE_FUNCS();\
03906 FCT_FIXTURE_SUITE_BGN( NAME ) {
03907
03908 #define FCTMF_FIXTURE_SUITE_END() \
03909 } FCT_FIXTURE_SUITE_END();\
03910 }
03911
03912 #define FCTMF_SUITE_BGN(NAME) \
03913 void NAME (fctkern_t *fctkern_ptr__) {\
03914 FCT_REFERENCE_FUNCS();\
03915 FCT_SUITE_BGN( NAME ) {
03916 #define FCTMF_SUITE_END() \
03917 } FCT_SUITE_END(); \
03918 }
03919
03920
03921
03922 #define FCTMF_SUITE_DEF(NAME)
03923
03924
03925
03926 #define FCTMF_SUITE_CALL(NAME) {\
03927 void NAME (fctkern_t *);\
03928 NAME (fctkern_ptr__);\
03929 }
03930
03931
03932
03933
03934
03935
03936
03937
03938
03939
03940
03941
03942 #define FCT_QTEST_BGN(NAME) \
03943 FCT_SUITE_BGN(NAME) {\
03944 FCT_TEST_BGN(NAME) {\
03945
03946 #define FCT_QTEST_END() \
03947 } FCT_TEST_END();\
03948 } FCT_SUITE_END();
03949
03950
03951 #define FCT_QTEST_BGN_IF(_CONDITION_, _NAME_) \
03952 FCT_SUITE_BGN(_NAME_) {\
03953 FCT_TEST_BGN_IF(_CONDITION_, _NAME_) {\
03954
03955 #define FCT_QTEST_END_IF() \
03956 } FCT_TEST_END_IF();\
03957 } FCT_SUITE_END();
03958
03959 #endif