SimGrid (3.0.2) unstable; urgency=low
XBT:
- * New module: testsuite [MQ]
+ * New module: cunit [MQ]
+ * New functions: xbt_dynar_getfirst_as() and xbt_dynar_getlast_as() [MQ]
--
#include <xbt/heap.h>
#include <xbt/config.h>
-#include <xbt/testsuite.h>
+#include <xbt/cunit.h>
#endif /* xbt_H */
--- /dev/null
+/* $Id$ */
+
+/* cunit - A little C Unit facility */
+
+/* Copyright (c) 2005 Martin Quinson. All rights reserved. */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
+/* This is partially inspirated from the OSSP ts (Test Suite Library) */
+
+#ifndef _XBT_CUNIT_H_
+#define _XBT_CUNIT_H_
+
+#include "xbt/sysdep.h" /* XBT_GNU_PRINTF */
+
+/* test suite object type */
+typedef struct s_xbt_test_suite *xbt_test_suite_t;
+
+/* test object type */
+typedef struct s_xbt_test_unit *xbt_test_unit_t;
+
+/* test callback function type */
+typedef void (*ts_test_cb_t)(xbt_test_unit_t);
+
+/* test suite operations */
+xbt_test_suite_t xbt_test_suite_new (const char *fmt, ...);
+void xbt_test_suite_dump (xbt_test_suite_t suite);
+void xbt_test_suite_push (xbt_test_suite_t suite,
+ ts_test_cb_t func, const char *fmt, ...);
+
+int xbt_test_run (void);
+
+
+/* test operations */
+void _xbt_test(xbt_test_unit_t u, const char*file,int line, const char *fmt, ...)_XBT_GNUC_PRINTF(4,5);
+#define xbt_test0(fmt) _xbt_test(_unit,__FILE__,__LINE__,fmt)
+#define xbt_test1(fmt,a) _xbt_test(_unit,__FILE__,__LINE__,fmt,a)
+#define xbt_test2(fmt,a,b) _xbt_test(_unit,__FILE__,__LINE__,fmt,a,b)
+#define xbt_test3(fmt,a,b,c) _xbt_test(_unit,__FILE__,__LINE__,fmt,a,b,c)
+#define xbt_test4(fmt,a,b,c,d) _xbt_test(_unit,__FILE__,__LINE__,fmt,a,b,c,d)
+#define xbt_test5(fmt,a,b,c,d,e) _xbt_test(_unit,__FILE__,__LINE__,fmt,a,b,c,d,e)
+
+void _xbt_test_fail(xbt_test_unit_t u, const char*file,int line, const char *fmt, ...) _XBT_GNUC_PRINTF(4,5);
+#define xbt_test_fail0(fmt) _xbt_test_fail(_unit, __FILE__, __LINE__, fmt)
+#define xbt_test_fail1(fmt,a) _xbt_test_fail(_unit, __FILE__, __LINE__, fmt,a)
+#define xbt_test_fail2(fmt,a,b) _xbt_test_fail(_unit, __FILE__, __LINE__, fmt,a,b)
+#define xbt_test_fail3(fmt,a,b,c) _xbt_test_fail(_unit, __FILE__, __LINE__, fmt,a,b,c)
+#define xbt_test_fail4(fmt,a,b,c,d) _xbt_test_fail(_unit, __FILE__, __LINE__, fmt,a,b,c,d)
+#define xbt_test_fail5(fmt,a,b,c,d,e) _xbt_test_fail(_unit, __FILE__, __LINE__, fmt,a,b,c,d,e)
+
+void _xbt_test_log (xbt_test_unit_t u, const char*file,int line, const char *fmt, ...)_XBT_GNUC_PRINTF(4,5);
+#define xbt_test_log0(fmt) _xbt_test_log(_unit, __FILE__, __LINE__, fmt)
+#define xbt_test_log1(fmt,a) _xbt_test_log(_unit, __FILE__, __LINE__, fmt,a)
+#define xbt_test_log2(fmt,a,b) _xbt_test_log(_unit, __FILE__, __LINE__, fmt,a,b)
+#define xbt_test_log3(fmt,a,b,c) _xbt_test_log(_unit, __FILE__, __LINE__, fmt,a,b,c)
+#define xbt_test_log4(fmt,a,b,c,d) _xbt_test_log(_unit, __FILE__, __LINE__, fmt,a,b,c,d)
+#define xbt_test_log5(fmt,a,b,c,d,e) _xbt_test_log(_unit, __FILE__, __LINE__, fmt,a,b,c,d,e)
+
+void _xbt_test_expect_failure(xbt_test_unit_t unit);
+#define xbt_test_expect_failure() _xbt_test_expect_failure(_unit)
+
+void _xbt_test_skip(xbt_test_unit_t unit);
+#define xbt_test_skip() _xbt_test_skip(_unit)
+
+/* test suite short-cut macros */
+#define XBT_TEST_UNIT(name) \
+ static void name(xbt_test_unit_t _unit)
+
+#endif /* _TS_H_ */
+
+++ /dev/null
-/*
-** OSSP ts - Test Suite Library
-** Copyright (c) 2001-2004 Ralf S. Engelschall <rse@engelschall.com>
-** Copyright (c) 2001-2004 The OSSP Project <http://www.ossp.org/>
-** Copyright (c) 2001-2004 Cable & Wireless <http://www.cw.com/>
-**
-** 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.h: test suite library API
-*/
-
-#ifndef _TS_H_
-#define _TS_H_
-
-/* test suite object type */
-struct ts_suite_st;
-typedef struct ts_suite_st ts_suite_t;
-
-/* test object type */
-struct ts_test_st;
-typedef struct ts_test_st ts_test_t;
-
-/* test callback function type */
-typedef void (*ts_test_cb_t)(ts_test_t *);
-
-/* test suite operations */
-ts_suite_t *ts_suite_new (const char *fmt, ...);
-void ts_suite_test (ts_suite_t *s, ts_test_cb_t func, const char *fmt, ...);
-int ts_suite_run (ts_suite_t *s);
-void ts_suite_free (ts_suite_t *s);
-
-/* test operations */
-ts_test_t *ts_test_ctx (ts_test_t *t, const char *file, int line);
-void ts_test_check (ts_test_t *t, const char *fmt, ...);
-void ts_test_fail (ts_test_t *t, const char *fmt, ...);
-void ts_test_log (ts_test_t *t, const char *fmt, ...);
-
-/* test suite short-cut macros */
-#define TS_TEST(name) \
- static void name(ts_test_t *_t)
-#define TS_CTX \
- ts_test_ctx(_t, __FILE__, __LINE__)
-
-#endif /* _TS_H_ */
-
xbt/set.c \
xbt/module.c \
xbt/config.c \
- xbt/testsuite.c \
+ xbt/cunit.c \
\
gras/gras.c \
\
--- /dev/null
+/* $Id$ */
+
+/* cunit - A little C Unit facility */
+
+/* Copyright (c) 2005 Martin Quinson. All rights reserved. */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
+/* This is partially inspirated from the OSSP ts (Test Suite Library) */
+
+#include "gras_config.h"
+
+#include "xbt/sysdep.h" /* vasprintf */
+#include "xbt/cunit.h"
+#include "xbt/dynar.h"
+
+XBT_LOG_NEW_DEFAULT_SUBCATEGORY(testsuite,xbt,"Test infrastructure");
+
+/* collection of all suites */
+static xbt_dynar_t _xbt_test_suites = NULL;
+/* global statistics */
+static int _xbt_test_nb_tests = 0;
+static int _xbt_test_test_failed = 0;
+static int _xbt_test_test_ignore = 0;
+static int _xbt_test_test_expect = 0;
+
+static int _xbt_test_nb_units = 0;
+static int _xbt_test_unit_failed = 0;
+static int _xbt_test_unit_ignore = 0;
+
+static int _xbt_test_nb_suites = 0;
+static int _xbt_test_suite_failed = 0;
+static int _xbt_test_suite_ignore = 0;
+
+
+/* test suite test log */
+typedef struct s_xbt_test_log {
+ char *text;
+ const char *file;
+ int line;
+} *xbt_test_log_t;
+
+static void xbt_test_log_dump(xbt_test_log_t log) {
+ if (log)
+ fprintf(stderr," log %p(%s:%d)=%s\n",log,log->file,log->line,log->text);
+ else
+ fprintf(stderr," log=NULL\n");
+}
+static void xbt_test_log_free(xbt_test_log_t log) {
+ if (!log)
+ return;
+ if (log->text)
+ free(log->text);
+ free(log);
+}
+
+/* test suite test check */
+typedef struct s_xbt_test_test {
+ char *title;
+ int failed;
+ int expected_failure;
+ int ignored;
+ const char *file;
+ int line;
+ xbt_dynar_t logs;
+} *xbt_test_test_t;
+
+static void xbt_test_test_dump(xbt_test_test_t test){
+ if (test) {
+ xbt_test_log_t log;
+ int it_log;
+ fprintf(stderr," test %p(%s:%d)=%s (%s)\n",
+ test,test->file,test->line,test->title,
+ test->failed?"failed":"not failed");
+ xbt_dynar_foreach(test->logs,it_log,log)
+ xbt_test_log_dump(log);
+ }
+ else
+ fprintf(stderr," test=NULL\n");
+}
+
+/* test suite test unit */
+struct s_xbt_test_unit {
+ char *title;
+ ts_test_cb_t func;
+ const char *file;
+ int line;
+ xbt_dynar_t tests; /* of xbt_test_test_t*/
+
+ int nb_tests;
+ int test_failed,test_ignore,test_expect;
+};
+
+static void xbt_test_unit_dump(xbt_test_unit_t unit) {
+ if (unit) {
+ xbt_test_test_t test;
+ int it_test;
+ fprintf(stderr," unit %p(%s:%d)=%s (func=%p)\n",
+ unit,unit->file,unit->line,unit->title,unit->file);
+ xbt_dynar_foreach(unit->tests,it_test,test)
+ xbt_test_test_dump(test);
+ } else {
+ fprintf(stderr," unit=NULL\n");
+ }
+}
+
+/* test suite */
+struct s_xbt_test_suite {
+ char *title;
+ xbt_dynar_t units; /* of xbt_test_unit_t */
+
+ int nb_tests,nb_units;
+ int test_failed,test_ignore,test_expect;
+ int unit_failed,unit_ignore;
+};
+
+/* destroy test suite */
+static void xbt_test_suite_free(void *s) {
+ xbt_test_suite_t suite = *(xbt_test_suite_t*) s;
+
+ if (suite == NULL)
+ return;
+ xbt_dynar_free(&suite->units);
+ free(suite->title);
+ free(suite);
+}
+
+/** @brief create test suite */
+xbt_test_suite_t xbt_test_suite_new(const char *fmt, ...) {
+ xbt_test_suite_t suite = xbt_new0(struct s_xbt_test_suite,1);
+ va_list ap;
+
+ if (!_xbt_test_suites)
+ _xbt_test_suites = xbt_dynar_new(sizeof(xbt_test_suite_t),&xbt_test_suite_free);
+
+ va_start(ap, fmt);
+ vasprintf(&suite->title,fmt, ap);
+ suite->units = xbt_dynar_new(sizeof(xbt_test_unit_t), NULL);
+ va_end(ap);
+
+ xbt_dynar_push(_xbt_test_suites,&suite);
+
+ return suite;
+}
+
+void xbt_test_suite_dump(xbt_test_suite_t suite) {
+ if (suite) {
+ xbt_test_unit_t unit;
+ int it_unit;
+ fprintf(stderr,"DUMP suite %s\n",suite->title);
+ xbt_dynar_foreach(suite->units,it_unit,unit)
+ xbt_test_unit_dump(unit);
+ } else {
+ fprintf(stderr,"suite=NULL\n");
+ }
+}
+
+/* add test case to test suite */
+void xbt_test_suite_push(xbt_test_suite_t suite, ts_test_cb_t func, const char *fmt, ...) {
+ xbt_test_unit_t unit;
+ va_list ap;
+
+ xbt_assert(suite);
+ xbt_assert(func);
+ xbt_assert(fmt);
+
+ unit = xbt_new(struct s_xbt_test_unit,1);
+ va_start(ap, fmt);
+ vasprintf(&unit->title, fmt, ap);
+ va_end(ap);
+ unit->func = func;
+ unit->file = NULL;
+ unit->line = 0;
+ unit->tests = xbt_dynar_new(sizeof(xbt_test_test_t), NULL);
+
+ xbt_dynar_push(suite->units, &unit);
+ return;
+}
+
+/* run test one suite */
+static int xbt_test_suite_run(xbt_test_suite_t suite) {
+ xbt_test_unit_t unit;
+ xbt_test_test_t test;
+ xbt_test_log_t log;
+
+ const char *file;
+ int line;
+ char *cp;
+ int it_unit,it_test,it_log;
+
+ if (suite == NULL)
+ return 0;
+
+ /* iterate through all tests to see how much failed */
+ xbt_dynar_foreach(suite->units, it_unit, unit) {
+ /* init unit case counters */
+ unit->nb_tests = 0;
+ unit->test_ignore = 0;
+ unit->test_failed = 0;
+ unit->test_expect = 0;
+
+ /* run the test case function */
+ unit->func(unit);
+
+ /* iterate through all performed tests to determine status */
+ xbt_dynar_foreach(unit->tests,it_test, test) {
+ if (test->ignored) {
+ unit->test_ignore++;
+ } else {
+ unit->nb_tests++;
+
+ if ( test->failed && !test->expected_failure) unit->test_failed++;
+ if (!test->failed && test->expected_failure) unit->test_failed++;
+ if (test->expected_failure)
+ unit->test_expect++;
+ }
+ }
+
+ /* Accumulate test counts into the suite */
+ suite->nb_tests += unit->nb_tests;
+ suite->test_failed += unit->test_failed;
+ suite->test_ignore += unit->test_ignore;
+ suite->test_expect += unit->test_expect;
+
+ _xbt_test_nb_tests += unit->nb_tests;
+ _xbt_test_test_failed += unit->test_failed;
+ _xbt_test_test_ignore += unit->test_ignore;
+ _xbt_test_test_expect += unit->test_expect;
+
+ /* What's the conclusion of this test anyway? */
+ if (unit->nb_tests) {
+ suite->nb_units++;
+ if (unit->test_failed)
+ suite->unit_failed++;
+ } else {
+ suite->unit_ignore++;
+ }
+ }
+ _xbt_test_nb_units += suite->nb_units;
+ _xbt_test_unit_failed += suite->unit_failed;
+ _xbt_test_unit_ignore += suite->unit_ignore;
+
+ if (suite->nb_units) {
+ _xbt_test_nb_suites++;
+ if (suite->test_failed)
+ _xbt_test_suite_failed++;
+ } else {
+ _xbt_test_suite_ignore++;
+ }
+
+ /* suite title pretty-printing */
+ {
+ char suite_title[80];
+ int suite_len=strlen(suite->title);
+ int i;
+
+ xbt_assert2(suite_len<70,"suite title \"%s\" too long (%d should be less than 70",
+ suite->title,suite_len);
+
+ suite_title[0]=' ';
+ for (i=1;i<79;i++)
+ suite_title[i]='=';
+ suite_title[i]='\0';
+
+ sprintf(suite_title + 40 - (suite_len+4)/2, "[ %s ]", suite->title);
+ suite_title[40 + (suite_len+4)/2] = '=';
+
+ fprintf(stderr, "\n%s %s\n",suite_title,
+ (suite->nb_units?(suite->unit_failed?"FAILED":"OK"):"SKIP"));
+
+ }
+
+ /* iterate through all test cases to display details */
+ xbt_dynar_foreach(suite->units, it_unit, unit) {
+ asprintf(&cp," Unit: %s ........................................"
+ "........................................", unit->title);
+ cp[72] = '\0';
+ fprintf(stderr, "%s", cp);
+ free(cp);
+
+ if (unit->test_failed > 0 || unit->test_expect) {
+ /* some tests failed (or were supposed to), so do detailed reporting of test case */
+ if (unit->test_failed > 0) {
+ fprintf(stderr, " failed\n");
+ } else if (unit->nb_tests) {
+ fprintf(stderr, ".... ok\n"); /* successful, but show about expected */
+ } else {
+ fprintf(stderr, ".. skip\n"); /* shouldn't happen, but I'm a bit lost with this logic */
+ }
+ xbt_dynar_foreach(unit->tests,it_test, test) {
+ file = (test->file != NULL ? test->file : unit->file);
+ line = (test->line != 0 ? test->line : unit->line);
+ fprintf(stderr, " %s: %s [%s:%d]\n",
+ (test->ignored?" SKIP":(test->expected_failure?(test->failed?"EFAIL":"EPASS"):
+ (test->failed?" FAIL":" PASS"))),
+ test->title, file, line);
+
+ xbt_dynar_foreach(test->logs,it_log,log) {
+ file = (log->file != NULL ? log->file : file);
+ line = (log->line != 0 ? log->line : line);
+ fprintf(stderr, " %s:%d: %s\n",
+ file, line,log->text);
+
+ }
+ }
+ fprintf(stderr, " Summary: %d of %d tests failed",unit->test_failed, unit->nb_tests);
+ if (unit->test_ignore) {
+ fprintf(stderr," (%d tests ignored)\n",unit->test_ignore);
+ } else {
+ fprintf(stderr,"\n");
+ }
+ } else if (unit->nb_tests) {
+ fprintf(stderr, ".... ok\n"); /* successful */
+ } else {
+ fprintf(stderr, ".. skip\n"); /* no test were run */
+ }
+ }
+
+ /* print test suite summary */
+ fprintf(stderr, " ==============================================================================\n");
+ fprintf(stderr, " Summary: Units: %.0f%% ok (%d units: ",
+ suite->nb_units?((1-(double)suite->unit_failed/(double)suite->nb_units)*100.0):100.0,
+ suite->nb_units);
+ int first=1;
+ if (suite->nb_units != suite->unit_failed) {
+ fprintf(stderr, "%s%d ok",(first?"":", "),suite->nb_units - suite->unit_failed);
+ first = 0;
+ }
+ if (suite->unit_failed) {
+ fprintf(stderr, "%s%d failed",(first?"":", "),suite->unit_failed);
+ first = 0;
+ }
+ if (suite->unit_ignore) {
+ fprintf(stderr, "%s%d ignored",(first?"":", "),suite->unit_ignore);
+ first = 0;
+ }
+ fprintf(stderr,")\n Tests: %.0f%% ok (%d tests: ",
+ suite->nb_tests?((1-(double)suite->test_failed/(double)suite->nb_tests)*100.0):100.0,
+ suite->nb_tests);
+
+ first=1;
+ if (suite->nb_tests != suite->test_failed) {
+ fprintf(stderr, "%s%d ok",(first?"":", "),suite->nb_tests - suite->test_failed);
+ first = 0;
+ }
+ if (suite->test_failed) {
+ fprintf(stderr, "%s%d failed",(first?"":", "),suite->test_failed);
+ first = 0;
+ }
+ if (suite->test_ignore) {
+ fprintf(stderr, "%s%d ignored",(first?"":"; "),suite->test_ignore);
+ first = 0;
+ }
+ if (suite->test_expect) {
+ fprintf(stderr, "%s%d expected to fail",(first?"":"; "),suite->test_expect);
+ first = 0;
+ }
+ fprintf(stderr,")\n");
+
+ return suite->unit_failed;
+}
+
+int xbt_test_run(void) {
+
+ if (_xbt_test_suites) {
+ int it_suite;
+ xbt_test_suite_t suite;
+ int first=1;
+
+ /* Run all the suites */
+ xbt_dynar_foreach(_xbt_test_suites,it_suite,suite)
+ xbt_test_suite_run(suite);
+
+ /* Display some more statistics */
+ fprintf(stderr,"\n\n TOTAL: Suites: %.0f%% ok (%d suites: ",
+ _xbt_test_nb_suites
+ ? ((1-(double)_xbt_test_suite_failed/(double)_xbt_test_nb_suites)*100.0)
+ : 100.0,
+ _xbt_test_nb_suites);
+ if (_xbt_test_nb_suites != _xbt_test_suite_failed) {
+ fprintf(stderr, "%d ok",_xbt_test_nb_suites - _xbt_test_suite_failed);
+ first = 0;
+ }
+ if (_xbt_test_suite_failed) {
+ fprintf(stderr, "%s%d failed",(first?"":", "),_xbt_test_suite_failed);
+ first = 0;
+ }
+
+ if (_xbt_test_suite_ignore) {
+ fprintf(stderr, "%s%d ignored",(first?"":", "),_xbt_test_suite_ignore);
+ first = 0;
+ }
+ fprintf(stderr,")\n Units: %.0f%% ok (%d units: ",
+ _xbt_test_nb_units?((1-(double)_xbt_test_unit_failed/(double)_xbt_test_nb_units)*100.0):100.0,
+ _xbt_test_nb_units);
+ first=1;
+ if (_xbt_test_nb_units != _xbt_test_unit_failed) {
+ fprintf(stderr, "%s%d ok",(first?"":", "),_xbt_test_nb_units - _xbt_test_unit_failed);
+ first = 0;
+ }
+ if (_xbt_test_unit_failed) {
+ fprintf(stderr, "%s%d failed",(first?"":", "),_xbt_test_unit_failed);
+ first = 0;
+ }
+ if (_xbt_test_unit_ignore) {
+ fprintf(stderr, "%s%d ignored",(first?"":", "),_xbt_test_unit_ignore);
+ first = 0;
+ }
+ fprintf(stderr,")\n Tests: %.0f%% ok (%d tests: ",
+ _xbt_test_nb_tests?((1-(double)_xbt_test_test_failed/(double)_xbt_test_nb_tests)*100.0):100.0,
+ _xbt_test_nb_tests);
+ first=1;
+ if (_xbt_test_nb_tests != _xbt_test_test_failed) {
+ fprintf(stderr, "%s%d ok",(first?"":", "),_xbt_test_nb_tests - _xbt_test_test_failed);
+ first = 0;
+ }
+ if (_xbt_test_test_failed) {
+ fprintf(stderr, "%s%d failed",(first?"":", "),_xbt_test_test_failed);
+ first = 0;
+ }
+ if (_xbt_test_test_ignore) {
+ fprintf(stderr, "%s%d ignored",(first?"":", "),_xbt_test_test_ignore);
+ first = 0;
+ }
+ if (_xbt_test_test_expect) {
+ fprintf(stderr, "%s%d expected to fail",(first?"":", "),_xbt_test_test_expect);
+ }
+
+ fprintf(stderr,")\n");
+ } else {
+ fprintf(stderr,"No unit to run!\n");
+ _xbt_test_unit_failed++;
+ }
+ return _xbt_test_unit_failed;
+}
+
+
+/* annotate test case with test */
+void _xbt_test(xbt_test_unit_t unit, const char*file,int line, const char *fmt, ...) {
+ xbt_test_test_t test;
+ va_list ap;
+
+ xbt_assert(unit);
+ xbt_assert(fmt);
+
+ test = xbt_new(struct s_xbt_test_test,1);
+ va_start(ap, fmt);
+ vasprintf(&test->title, fmt, ap);
+ va_end(ap);
+ test->failed = 0;
+ test->expected_failure = 0;
+ test->ignored = 0;
+ test->file = file;
+ test->line = line;
+ test->logs = xbt_dynar_new(sizeof(xbt_test_log_t),NULL);
+ xbt_dynar_push(unit->tests,&test);
+ return;
+}
+
+/* annotate test case with log message and failure */
+void _xbt_test_fail(xbt_test_unit_t unit, const char*file,int line,const char *fmt, ...) {
+ xbt_test_test_t test;
+ xbt_test_log_t log;
+ va_list ap;
+
+ xbt_assert(unit);
+ xbt_assert(fmt);
+
+ log = xbt_new(struct s_xbt_test_log,1);
+ va_start(ap, fmt);
+ vasprintf(&log->text,fmt, ap);
+ va_end(ap);
+ log->file = file;
+ log->line = line;
+
+ test = xbt_dynar_getlast_as(unit->tests, xbt_test_test_t);
+ xbt_dynar_push(test->logs, &log);
+
+ test->failed = 1;
+}
+
+void _xbt_test_expect_failure(xbt_test_unit_t unit) {
+ xbt_test_test_t test = xbt_dynar_getlast_as(unit->tests,xbt_test_test_t);
+ test->expected_failure = 1;
+}
+void _xbt_test_skip(xbt_test_unit_t unit) {
+ xbt_test_test_t test = xbt_dynar_getlast_as(unit->tests,xbt_test_test_t);
+ test->ignored = 1;
+}
+
+/* annotate test case with log message only */
+void _xbt_test_log(xbt_test_unit_t unit, const char*file,int line,const char *fmt, ...) {
+ xbt_test_test_t test;
+ xbt_test_log_t log;
+ va_list ap;
+
+ xbt_assert(unit);
+ xbt_assert(fmt);
+
+ log = xbt_new(struct s_xbt_test_log,1);
+ va_start(ap, fmt);
+ vasprintf(&log->text, fmt, ap);
+ va_end(ap);
+ log->file = file;
+ log->line = line;
+
+ test = xbt_dynar_getlast_as(unit->tests,xbt_test_test_t);
+ xbt_dynar_push(test->logs, &log);
+}
+
+++ /dev/null
-/*
-** OSSP ts - Test Suite Library
-** Copyright (c) 2001-2004 Ralf S. Engelschall <rse@engelschall.com>
-** Copyright (c) 2001-2004 The OSSP Project <http://www.ossp.org/>
-** Copyright (c) 2001-2004 Cable & Wireless <http://www.cw.com/>
-**
-** 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 <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdarg.h>
-#include "gras_config.h"
-
-#include "xbt/testsuite.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: <available-bits> 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 = (char*)"(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;
-}
-
#include <time.h>
#include <string.h>
-#include "xbt/testsuite.h"
+#include "xbt/cunit.h"
#include "xbt/ex.h"
#include "xbt/log.h"
XBT_LOG_NEW_CATEGORY(test,"This test");
-TS_TEST(test_controlflow)
-{
+XBT_TEST_UNIT(test_expected_failure) {
+ xbt_test0("Skipped test");
+ xbt_test_skip();
+
+ xbt_test0("EXPECTED FAILURE");
+ xbt_test_expect_failure();
+ xbt_test_log2("%s %s","Test","log");
+ xbt_test_fail0("EXPECTED FAILURE");
+}
+
+XBT_TEST_UNIT(test_controlflow) {
xbt_ex_t ex;
- volatile int n;
+ volatile int n=1;
+
+ xbt_test0("basic nested control flow");
- ts_test_check(TS_CTX, "basic nested control flow");
- n = 1;
TRY {
if (n != 1)
- ts_test_fail(TS_CTX, "M1: n=%d (!= 1)", n);
+ xbt_test_fail1("M1: n=%d (!= 1)", n);
n++;
TRY {
if (n != 2)
- ts_test_fail(TS_CTX, "M2: n=%d (!= 2)", n);
+ xbt_test_fail1("M2: n=%d (!= 2)", n);
n++;
THROW0(unknown_error,0,"something");
} CATCH (ex) {
if (n != 3)
- ts_test_fail(TS_CTX, "M3: n=%d (!= 1)", n);
+ xbt_test_fail1("M3: n=%d (!= 1)", n);
n++;
RETHROW;
}
- ts_test_fail(TS_CTX, "MX: n=%d (expected: not reached)", n);
+ xbt_test_fail1("MX: n=%d (shouldn't reach this point)", n);
}
CATCH(ex) {
if (n != 4)
- ts_test_fail(TS_CTX, "M4: n=%d (!= 4)", n);
+ xbt_test_fail1("M4: n=%d (!= 4)", n);
n++;
xbt_ex_free(ex);
}
if (n != 5)
- ts_test_fail(TS_CTX, "M5: n=%d (!= 5)", n);
+ xbt_test_fail1("M5: n=%d (!= 5)", n);
}
-TS_TEST(test_value)
-{
+XBT_TEST_UNIT(test_value) {
xbt_ex_t ex;
TRY {
THROW0(unknown_error, 2, "toto");
} CATCH(ex) {
- ts_test_check(TS_CTX, "exception value passing");
+ xbt_test0("exception value passing");
if (ex.category != unknown_error)
- ts_test_fail(TS_CTX, "category=%d (!= 1)", ex.category);
+ xbt_test_fail1("category=%d (!= 1)", ex.category);
if (ex.value != 2)
- ts_test_fail(TS_CTX, "value=%d (!= 2)", ex.value);
+ xbt_test_fail1("value=%d (!= 2)", ex.value);
if (strcmp(ex.msg,"toto"))
- ts_test_fail(TS_CTX, "message=%s (!= toto)", ex.msg);
+ xbt_test_fail1("message=%s (!= toto)", ex.msg);
xbt_ex_free(ex);
}
}
-TS_TEST(test_variables)
-{
+XBT_TEST_UNIT(test_variables) {
xbt_ex_t ex;
int r1, r2;
volatile int v1, v2;
v2 = 5678;
THROW0(unknown_error, 0, "toto");
} CATCH(ex) {
- ts_test_check(TS_CTX, "variable preservation");
+ xbt_test0("variable preservation");
if (r1 != 1234)
- ts_test_fail(TS_CTX, "r1=%d (!= 1234)", r1);
+ xbt_test_fail1("r1=%d (!= 1234)", r1);
if (v1 != 1234)
- ts_test_fail(TS_CTX, "v1=%d (!= 1234)", v1);
+ xbt_test_fail1("v1=%d (!= 1234)", v1);
/* r2 is allowed to be destroyed because not volatile */
if (v2 != 5678)
- ts_test_fail(TS_CTX, "v2=%d (!= 5678)", v2);
+ xbt_test_fail1("v2=%d (!= 5678)", v2);
xbt_ex_free(ex);
}
}
-TS_TEST(test_cleanup)
-{
+XBT_TEST_UNIT(test_cleanup) {
xbt_ex_t ex;
volatile int v1;
int c;
- ts_test_check(TS_CTX, "cleanup handling");
+ xbt_test0("cleanup handling");
v1 = 1234;
c = 0;
THROW0(1, 2, "blah");
} CLEANUP {
if (v1 != 5678)
- ts_test_fail(TS_CTX, "v1 = %d (!= 5678)", v1);
+ xbt_test_fail1("v1 = %d (!= 5678)", v1);
c = 1;
} CATCH(ex) {
if (v1 != 5678)
- ts_test_fail(TS_CTX, "v1 = %d (!= 5678)", v1);
+ xbt_test_fail1("v1 = %d (!= 5678)", v1);
if (!(ex.category == 1 && ex.value == 2 && !strcmp(ex.msg,"blah")))
- ts_test_fail(TS_CTX, "unexpected exception contents");
+ xbt_test_fail0("unexpected exception contents");
xbt_ex_free(ex);
}
if (!c)
- ts_test_fail(TS_CTX, "ex_cleanup not executed");
+ xbt_test_fail0("xbt_ex_free not executed");
}
-int main(int argc, char *argv[])
-{
- ts_suite_t *ts;
- int n;
-
- ts = ts_suite_new("OSSP ex (Exception Handling)");
- ts_suite_test(ts, test_controlflow, "basic nested control flow");
- ts_suite_test(ts, test_value, "exception value passing");
- ts_suite_test(ts, test_variables, "variable value preservation");
- ts_suite_test(ts, test_cleanup, "cleanup handling");
- n = ts_suite_run(ts);
- ts_suite_free(ts);
- return n;
+int main(int argc, char *argv[]) {
+ xbt_test_suite_t suite;
+
+ suite = xbt_test_suite_new("Testsuite Autotest");
+ xbt_test_suite_push(suite, test_expected_failure, "expected failures");
+
+ suite = xbt_test_suite_new("Exception Handling");
+ xbt_test_suite_push(suite, test_controlflow, "basic nested control flow");
+ xbt_test_suite_push(suite, test_value, "exception value passing");
+ xbt_test_suite_push(suite, test_variables, "variable value preservation");
+ xbt_test_suite_push(suite, test_cleanup, "cleanup handling");
+
+ return xbt_test_run();
}