head 1.13; access; symbols LMTP2NNTP_1_4_1:1.12 LMTP2NNTP_1_4_0:1.12 SIO_0_9_3:1.12 SA_1_2_6:1.12 SA_1_2_5:1.12 SA_1_2_4:1.12 SA_1_2_3:1.12 LMTP2NNTP_1_3_0:1.11 LMTP2NNTP_1_3b2:1.11 SA_1_2_2:1.11 LMTP2NNTP_1_3b1:1.10 SA_1_2_1:1.10 LMTP2NNTP_1_3a3:1.10 LMTP2NNTP_1_3a2:1.10 LMTP2NNTP_1_3a1:1.10 SA_1_2_0:1.10 SA_1_1_0:1.9 SIO_0_9_2:1.9 SIO_0_9_1:1.9 LMTP2NNTP_1_2_0:1.9 LMTP2NNTP_1_2b4:1.9 LMTP2NNTP_1_2b3:1.9 LMTP2NNTP_1_2b2:1.9 LMTP2NNTP_1_2b1:1.7 LMTP2NNTP_1_2a8:1.7 SIO_0_9_0:1.7 LMTP2NNTP_1_2a7:1.7 SA_1_0_5:1.7 SA_1_0_4:1.6 SA_1_0_3:1.6 SA_1_0_2:1.6 SA_1_0_1:1.6 SA_1_0_0:1.5 SA_0_9_3:1.5 SA_0_9_2:1.5 LMTP2NNTP_1_2a6:1.5 LMTP2NNTP_1_2a5:1.5 SA_0_9_1:1.5 LMTP2NNTP_1_2a4:1.5 LMTP2NNTP_1_2a3:1.4 SA_0_9_0:1.4 LMTP2NNTP_1_2a1:1.3 LMTP2NNTP_1_1_1:1.3 LMTP2NNTP_1_1_0:1.3 LMTP2NNTP_1_1b4:1.3 LMTP2NNTP_1_1b3:1.3 LMTP2NNTP_1_1b2:1.2 LMTP2NNTP_1_1b1:1.2; locks; strict; comment @ * @; 1.13 date 2006.06.10.10.00.17; author rse; state Exp; branches; next 1.12; commitid JpcJR7gM5uNpwrAr; 1.12 date 2005.01.24.15.10.09; author rse; state Exp; branches; next 1.11; 1.11 date 2004.06.26.11.38.20; author rse; state Exp; branches; next 1.10; 1.10 date 2004.04.02.18.21.07; author rse; state Exp; branches; next 1.9; 1.9 date 2003.02.11.12.31.14; author rse; state Exp; branches; next 1.8; 1.8 date 2003.02.10.10.13.29; author thl; state Exp; branches; next 1.7; 1.7 date 2003.01.31.18.58.18; author rse; state Exp; branches; next 1.6; 1.6 date 2002.11.07.12.44.12; author rse; state Exp; branches; next 1.5; 1.5 date 2002.03.08.23.08.39; author rse; state Exp; branches; next 1.4; 1.4 date 2002.01.02.12.43.50; author rse; state Exp; branches; next 1.3; 1.3 date 2001.10.31.19.28.49; author rse; state Exp; branches; next 1.2; 1.2 date 2001.10.10.15.11.42; author rse; state Exp; branches; next 1.1; 1.1 date 2001.10.10.15.01.56; author rse; state Exp; branches; next ; desc @@ 1.13 log @Adjusted all copyright messages for year 2006 @ text @/* ** OSSP ts - Test Suite Library ** Copyright (c) 2001-2006 Ralf S. Engelschall ** Copyright (c) 2001-2006 The OSSP Project ** Copyright (c) 2001-2005 Cable & Wireless ** ** This file is part of OSSP ts, a small test suite library which ** can be found at http://www.ossp.org/pkg/lib/ts/. ** ** Permission to use, copy, modify, and distribute this software for ** any purpose with or without fee is hereby granted, provided that ** the above copyright notice and this permission notice appear in all ** copies. ** ** THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED ** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF ** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ** IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR ** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF ** USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, ** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ** OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ** SUCH DAMAGE. ** ** ts.c: test suite library */ #include #include #include #include #include "config.h" #if defined(HAVE_DMALLOC_H) && defined(WITH_DMALLOC) #include "dmalloc.h" #endif #include "ts.h" /* embedded ring data structure library */ #define RING_ENTRY(elem) \ struct { elem *next; elem *prev; } #define RING_HEAD(elem) \ struct { elem *next; elem *prev; } #define RING_SENTINEL(hp, elem, link) \ (elem *)((char *)(hp) - ((size_t)(&((elem *)0)->link))) #define RING_FIRST(hp) \ (hp)->next #define RING_LAST(hp) \ (hp)->prev #define RING_NEXT(ep, link) \ (ep)->link.next #define RING_PREV(ep, link) \ (ep)->link.prev #define RING_INIT(hp, elem, link) \ do { RING_FIRST((hp)) = RING_SENTINEL((hp), elem, link); \ RING_LAST((hp)) = RING_SENTINEL((hp), elem, link); } while (0) #define RING_EMPTY(hp, elem, link) \ (RING_FIRST((hp)) == RING_SENTINEL((hp), elem, link)) #define RING_ELEM_INIT(ep, link) \ do { RING_NEXT((ep), link) = (ep); \ RING_PREV((ep), link) = (ep); } while (0) #define RING_SPLICE_BEFORE(lep, ep1, epN, link) \ do { RING_NEXT((epN), link) = (lep); \ RING_PREV((ep1), link) = RING_PREV((lep), link); \ RING_NEXT(RING_PREV((lep), link), link) = (ep1); \ RING_PREV((lep), link) = (epN); } while (0) #define RING_SPLICE_TAIL(hp, ep1, epN, elem, link) \ RING_SPLICE_BEFORE(RING_SENTINEL((hp), elem, link), (ep1), (epN), link) #define RING_INSERT_TAIL(hp, nep, elem, link) \ RING_SPLICE_TAIL((hp), (nep), (nep), elem, link) #define RING_FOREACH(ep, hp, elem, link) \ for ((ep) = RING_FIRST((hp)); \ (ep) != RING_SENTINEL((hp), elem, link); \ (ep) = RING_NEXT((ep), link)) #define RING_FOREACH_LA(ep, epT, hp, elem, link) \ for ((ep) = RING_FIRST((hp)), (epT) = RING_NEXT((ep), link); \ (ep) != RING_SENTINEL((hp), elem, link); \ (ep) = (epT), (epT) = RING_NEXT((epT), link)) /* test suite test log */ struct tstl_st; typedef struct tstl_st tstl_t; struct tstl_st { RING_ENTRY(tstl_t) next; char *text; const char *file; int line; }; /* test suite test check */ struct tstc_st; typedef struct tstc_st tstc_t; struct tstc_st { RING_ENTRY(tstc_t) next; char *title; int failed; const char *file; int line; RING_HEAD(tstl_t) logs; }; /* test suite test */ struct ts_test_st { RING_ENTRY(ts_test_t) next; char *title; ts_test_cb_t func; const char *file; int line; RING_HEAD(tstc_t) checks; }; /* test suite */ struct ts_suite_st { char *title; RING_HEAD(ts_test_t) tests; }; /* minimal output-independent vprintf(3) variant which supports %{c,s,d,%} only */ static int ts_suite_mvxprintf(char *buffer, size_t bufsize, const char *format, va_list ap) { /* sufficient integer buffer: x log_10(2) + safety */ char ibuf[((sizeof(int)*8)/3)+10]; char *cp; char c; int d; int n; int bytes; if (format == NULL) return -1; bytes = 0; while (*format != '\0') { if (*format == '%') { c = *(format+1); if (c == '%') { /* expand "%%" */ cp = &c; n = sizeof(char); } else if (c == 'c') { /* expand "%c" */ c = (char)va_arg(ap, int); cp = &c; n = sizeof(char); } else if (c == 's') { /* expand "%s" */ if ((cp = (char *)va_arg(ap, char *)) == NULL) cp = "(null)"; n = strlen(cp); } else if (c == 'd') { /* expand "%d" */ d = (int)va_arg(ap, int); #ifdef HAVE_SNPRINTF snprintf(ibuf, sizeof(ibuf), "%d", d); /* explicitly secure */ #else sprintf(ibuf, "%d", d); /* implicitly secure */ #endif cp = ibuf; n = strlen(cp); } else { /* any other "%X" */ cp = (char *)format; n = 2; } format += 2; } else { /* plain text */ cp = (char *)format; if ((format = strchr(cp, '%')) == NULL) format = strchr(cp, '\0'); n = format - cp; } /* perform output operation */ if (buffer != NULL) { if (n > bufsize) return -1; memcpy(buffer, cp, n); buffer += n; bufsize -= n; } bytes += n; } /* nul-terminate output */ if (buffer != NULL) { if (bufsize == 0) return -1; *buffer = '\0'; } return bytes; } /* minimal vasprintf(3) variant which supports %{c,s,d} only */ static char *ts_suite_mvasprintf(const char *format, va_list ap) { char *buffer; int n; va_list ap2; if (format == NULL) return NULL; va_copy(ap2, ap); if ((n = ts_suite_mvxprintf(NULL, 0, format, ap)) == -1) return NULL; if ((buffer = (char *)malloc(n+1)) == NULL) return NULL; ts_suite_mvxprintf(buffer, n+1, format, ap2); return buffer; } /* minimal asprintf(3) variant which supports %{c,s,d} only */ static char *ts_suite_masprintf(const char *format, ...) { va_list ap; char *cp; va_start(ap, format); cp = ts_suite_mvasprintf(format, ap); va_end(ap); return cp; } /* create test suite */ ts_suite_t *ts_suite_new(const char *fmt, ...) { ts_suite_t *ts; va_list ap; if ((ts = (ts_suite_t *)malloc(sizeof(ts_suite_t))) == NULL) return NULL; va_start(ap, fmt); ts->title = ts_suite_mvasprintf(fmt, ap); RING_INIT(&ts->tests, ts_test_t, next); va_end(ap); return ts; } /* add test case to test suite */ void ts_suite_test(ts_suite_t *ts, ts_test_cb_t func, const char *fmt, ...) { ts_test_t *tst; va_list ap; if (ts == NULL || func == NULL || fmt == NULL) return; if ((tst = (ts_test_t *)malloc(sizeof(ts_test_t))) == NULL) return; RING_ELEM_INIT(tst, next); va_start(ap, fmt); tst->title = ts_suite_mvasprintf(fmt, ap); va_end(ap); tst->func = func; tst->file = NULL; tst->line = 0; RING_INIT(&tst->checks, tstc_t, next); RING_INSERT_TAIL(&ts->tests, tst, ts_test_t, next); return; } /* run test suite */ int ts_suite_run(ts_suite_t *ts) { ts_test_t *tst; tstc_t *tstc; tstl_t *tstl; int total_tests, total_tests_suite_failed; int total_checks, total_checks_failed; int test_checks, test_checks_failed; const char *file; int line; char *cp; if (ts == NULL) return 0; /* init total counters */ total_tests = 0; total_tests_suite_failed = 0; total_checks = 0; total_checks_failed = 0; fprintf(stdout, "\n"); fprintf(stdout, " Test Suite: %s\n", ts->title); fprintf(stdout, " __________________________________________________________________\n"); fprintf(stdout, "\n"); fflush(stdout); /* iterate through all test cases */ RING_FOREACH(tst, &ts->tests, ts_test_t, next) { cp = ts_suite_masprintf(" Test: %s ........................................" "........................................", tst->title); cp[60] = '\0'; fprintf(stdout, "%s", cp); free(cp); fflush(stdout); /* init test case counters */ test_checks = 0; test_checks_failed = 0; /* run the test case function */ tst->func(tst); /* iterate through all performed checks to determine status */ RING_FOREACH(tstc, &tst->checks, tstc_t, next) { test_checks++; if (tstc->failed) test_checks_failed++; } if (test_checks_failed > 0) { /* some checks failed, so do detailed reporting of test case */ fprintf(stdout, " FAILED\n"); fprintf(stdout, " Ops, %d/%d checks failed! Detailed report follows:\n", test_checks_failed, test_checks); RING_FOREACH(tstc, &tst->checks, tstc_t, next) { file = (tstc->file != NULL ? tstc->file : tst->file); line = (tstc->line != 0 ? tstc->line : tst->line); if (file != NULL) fprintf(stdout, " Check: %s [%s:%d]\n", tstc->title, file, line); else fprintf(stdout, " Check: %s\n", tstc->title); RING_FOREACH(tstl, &tstc->logs, tstl_t, next) { file = (tstl->file != NULL ? tstl->file : file); line = (tstl->line != 0 ? tstl->line : line); if (file != NULL) fprintf(stdout, " Log: %s [%s:%d]\n", tstl->text, file, line); else fprintf(stdout, " Log: %s\n", tstl->text); } } } else { /* test case ran successfully */ fprintf(stdout, ".... OK\n"); } fflush(stdout); /* accumulate counters */ total_checks += test_checks; total_tests++; if (test_checks_failed > 0) { total_checks_failed += test_checks_failed; total_tests_suite_failed++; } } /* print test suite summary */ fprintf(stdout, " __________________________________________________________________\n"); fprintf(stdout, "\n"); fprintf(stdout, " Test Summary: %d tests (%d ok, %d failed), %d checks (%d ok, %d failed)\n", total_tests, (total_tests - total_tests_suite_failed), total_tests_suite_failed, total_checks, (total_checks - total_checks_failed), total_checks_failed); if (total_tests_suite_failed > 0) fprintf(stdout, " Test Suite: FAILED\n"); else fprintf(stdout, " Test Suite: OK\n"); fprintf(stdout, "\n"); fflush(stdout); return total_checks_failed; } /* destroy test suite */ void ts_suite_free(ts_suite_t *ts) { ts_test_t *tst, *tstT; tstc_t *tstc, *tstcT; tstl_t *tstl, *tstlT; if (ts == NULL) return; RING_FOREACH_LA(tst, tstT, &ts->tests, ts_test_t, next) { RING_FOREACH_LA(tstc, tstcT, &tst->checks, tstc_t, next) { RING_FOREACH_LA(tstl, tstlT, &tstc->logs, tstl_t, next) { free(tstl->text); } free(tstc->title); free(tstc); } free(tst->title); free(tst); } free(ts->title); free(ts); return; } /* annotate test case with file name and line number */ ts_test_t *ts_test_ctx(ts_test_t *tst, const char *file, int line) { if (tst != NULL && file != NULL) { tst->file = file; tst->line = line; } return tst; } /* annotate test case with check */ void ts_test_check(ts_test_t *tst, const char *fmt, ...) { tstc_t *tstc; va_list ap; if (tst == NULL || fmt == NULL) return; if ((tstc = (tstc_t *)malloc(sizeof(tstc_t))) == NULL) return; va_start(ap, fmt); RING_ELEM_INIT(tstc, next); tstc->title = ts_suite_mvasprintf(fmt, ap); tstc->failed = 0; tstc->file = tst->file; tstc->line = tst->line; RING_INIT(&tstc->logs, tstl_t, next); RING_INSERT_TAIL(&tst->checks, tstc, tstc_t, next); va_end(ap); return; } /* annotate test case with log message and failure */ void ts_test_fail(ts_test_t *tst, const char *fmt, ...) { tstc_t *tstc; tstl_t *tstl; va_list ap; if (tst == NULL || fmt == NULL) return; if ((tstl = (tstl_t *)malloc(sizeof(tstl_t))) == NULL) return; va_start(ap, fmt); tstl->text = ts_suite_mvasprintf(fmt, ap); tstl->file = tst->file; tstl->line = tst->line; RING_ELEM_INIT(tstl, next); tstc = RING_LAST(&tst->checks); RING_INSERT_TAIL(&tstc->logs, tstl, tstl_t, next); tstc->failed = 1; va_end(ap); return; } /* annotate test case with log message only */ void ts_test_log(ts_test_t *tst, const char *fmt, ...) { tstc_t *tstc; tstl_t *tstl; va_list ap; if (tst == NULL || fmt == NULL) return; if ((tstl = (tstl_t *)malloc(sizeof(tstl_t))) == NULL) return; va_start(ap, fmt); tstl->text = ts_suite_mvasprintf(fmt, ap); tstl->file = tst->file; tstl->line = tst->line; RING_ELEM_INIT(tstl, next); tstc = RING_LAST(&tst->checks); RING_INSERT_TAIL(&tstc->logs, tstl, tstl_t, next); va_end(ap); return; } @ 1.12 log @welcome 2005 in OSSP sa, too @ text @d3 2 a4 2 ** Copyright (c) 2001-2005 Ralf S. Engelschall ** Copyright (c) 2001-2005 The OSSP Project @ 1.11 log @o Provide Autoconf check (AC_CHECK_VA_COPY) for va_copy(d,s) macro and fallback implementations and now that we can be sure that va_copy() exists for us, use it in var_formatv() and ts.c instead of the direct assignments (which are not sufficiently portable). o Remove "#undef socklen_t" from sa.h because the socklen_t fallback is a "typedef" since a longer time. @ text @d3 3 a5 3 ** Copyright (c) 2001-2004 Ralf S. Engelschall ** Copyright (c) 2001-2004 The OSSP Project ** Copyright (c) 2001-2004 Cable & Wireless @ 1.10 log @Adjusted all copyright messages for new year 2004. @ text @d2 1 a2 1 ** TS - OSSP Test Suite Library d7 2 a8 2 ** This file is part of OSSP TS, a small test suite library which ** can be found at http://www.ossp.org/pkg/ts/. d130 1 a130 1 size_t n; d209 1 a209 1 ap2 = ap; @ 1.9 log @fix compile warning under latest GCC 3.3 SNAPSHOT @ text @d3 3 a5 3 ** Copyright (c) 2001-2003 Ralf S. Engelschall ** Copyright (c) 2001-2003 The OSSP Project ** Copyright (c) 2001-2003 Cable & Wireless Deutschland @ 1.8 log @extend copyright messages based on CVS information @ text @d130 1 a130 1 int n; @ 1.7 log @Fixed test suite library (ts.c): the ts_suite_free() function performed an illegal iteration for freeing elements (they were freed but still references for traversing to next element). This is now solved by a look-ahead traversion. Hint by: Brian T. Egleston @ text @d3 3 a5 3 ** Copyright (c) 2001-2002 Ralf S. Engelschall ** Copyright (c) 2001-2002 The OSSP Project ** Copyright (c) 2001-2002 Cable & Wireless Deutschland @ 1.6 log @Make sure that "va_list" variables are not compared against NULL because this is not possible on all platforms. @ text @d79 4 d374 3 a376 3 ts_test_t *tst; tstc_t *tstc; tstl_t *tstl; d380 3 a382 3 RING_FOREACH(tst, &ts->tests, ts_test_t, next) { RING_FOREACH(tstc, &tst->checks, tstc_t, next) { RING_FOREACH(tstl, &tstc->logs, tstl_t, next) { @ 1.5 log @upgrade to fixed ts.c @ text @d129 1 a129 1 if (format == NULL || ap == NULL) d203 1 a203 1 if (format == NULL || ap == NULL) @ 1.4 log @bump copyright year @ text @d36 5 d294 1 a294 1 "........................................", tst->title); d387 1 a387 1 free(tst->title); @ 1.3 log @Rename test suite library name spaces in order to get rid of problems under Sun Solaris 2.x. @ text @d3 3 a5 3 ** Copyright (c) 2001 Ralf S. Engelschall ** Copyright (c) 2001 The OSSP Project ** Copyright (c) 2001 Cable & Wireless Deutschland @ 1.2 log @fix texts @ text @d7 1 a7 1 ** This file is part of OSSP TS, a test suite library which d98 2 a99 2 struct tst_st { RING_ENTRY(tst_t) next; d101 1 a101 1 tst_func_t func; d108 1 a108 1 struct ts_st { d110 1 a110 1 RING_HEAD(tst_t) tests; d114 1 a114 1 static int ts_mvxprintf(char *buffer, size_t bufsize, const char *format, va_list ap) d192 1 a192 1 static char *ts_mvasprintf(const char *format, va_list ap) d201 1 a201 1 if ((n = ts_mvxprintf(NULL, 0, format, ap)) == -1) d205 1 a205 1 ts_mvxprintf(buffer, n+1, format, ap2); d210 1 a210 1 static char *ts_masprintf(const char *format, ...) d216 1 a216 1 cp = ts_mvasprintf(format, ap); d222 1 a222 1 ts_t *ts_new(const char *fmt, ...) d224 1 a224 1 ts_t *ts; d227 1 a227 1 if ((ts = (ts_t *)malloc(sizeof(ts_t))) == NULL) d230 2 a231 2 ts->title = ts_mvasprintf(fmt, ap); RING_INIT(&ts->tests, tst_t, next); d237 1 a237 1 void ts_test(ts_t *ts, tst_func_t func, const char *fmt, ...) d239 1 a239 1 tst_t *tst; d244 1 a244 1 if ((tst = (tst_t *)malloc(sizeof(tst_t))) == NULL) d248 1 a248 1 tst->title = ts_mvasprintf(fmt, ap); d254 1 a254 1 RING_INSERT_TAIL(&ts->tests, tst, tst_t, next); d259 1 a259 1 int ts_run(ts_t *ts) d261 1 a261 1 tst_t *tst; d264 1 a264 1 int total_tests, total_tests_failed; d276 1 a276 1 total_tests_failed = 0; d287 2 a288 2 RING_FOREACH(tst, &ts->tests, tst_t, next) { cp = ts_masprintf(" Test: %s ........................................" d342 1 a342 1 total_tests_failed++; d350 1 a350 1 total_tests, (total_tests - total_tests_failed), total_tests_failed, d352 1 a352 1 if (total_tests_failed > 0) d363 1 a363 1 void ts_free(ts_t *ts) d365 1 a365 1 tst_t *tst; d371 1 a371 1 RING_FOREACH(tst, &ts->tests, tst_t, next) { d388 1 a388 1 tst_t *tst_ctx(tst_t *tst, const char *file, int line) d398 1 a398 1 void tst_check(tst_t *tst, const char *fmt, ...) d409 1 a409 1 tstc->title = ts_mvasprintf(fmt, ap); d420 1 a420 1 void tst_fail(tst_t *tst, const char *fmt, ...) d431 1 a431 1 tstl->text = ts_mvasprintf(fmt, ap); d443 1 a443 1 void tst_log(tst_t *tst, const char *fmt, ...) d454 1 a454 1 tstl->text = ts_mvasprintf(fmt, ap); @ 1.1 log @Implemented a new sub-library OSSP TS (Test Suite) and use this new beast for the first cut of an OSSP SA test suite. The TS library produces nice test suite reports like this one (for a failed test suite): | Test Suite: OSSP SA (Socket Abstraction Library) | __________________________________________________________________ | | Test: socket address abstraction .............................. OK | Test: socket abstraction .................................. FAILED | Ops, 1/1 checks failed! Detailed report follows: | Check: testerliX [sa_test.c:43] | Log: sorry [sa_test.c:44] | __________________________________________________________________ | | Test Summary: 2 tests (1 ok, 1 failed), 5 checks (4 ok, 1 failed) | Test Suite: FAILED (Test Suite Failed) Or this one (for a successfull test suite): | Test Suite: OSSP SA (Socket Abstraction Library) | __________________________________________________________________ | | Test: socket address abstraction .............................. OK | Test: socket abstraction ...................................... OK | __________________________________________________________________ | | Test Summary: 2 tests (2 ok, 0 failed), 5 checks (5 ok, 0 failed) | Test Suite: OK (Test Suite Successfully) @ text @d318 1 a318 1 fprintf(stdout, " Check: %sX [%s:%d]\n", tstc->title, file, line); d353 1 a353 1 fprintf(stdout, " Test Suite: FAILED (Test Suite Failed)\n"); d355 1 a355 1 fprintf(stdout, " Test Suite: OK (Test Suite Passed Successfully)\n"); @