mirror of
https://github.com/darlinghq/ctest.git
synced 2024-12-04 18:46:27 +00:00
Add basic C++ support
This commit adds C++ support with the following modifications: - Remove the use of C-only features including designated initializers and non-strict prototypes. - Add spaces between literals and string macros to silence the C++-only -Wliteral-suffix warning. - Conditionally use template specialization instead of tentative definitions to implement optional setup/teardown functions. Note that no C++-specific features have been added. The goal of this commit is to simply enable compiling in C++ mode.
This commit is contained in:
parent
f12e0d811b
commit
f8a83d694b
@ -1,6 +1,6 @@
|
||||
# CTEST
|
||||
|
||||
ctest is a unit test framework for software written in C.
|
||||
ctest is a unit test framework for software written in C/C++.
|
||||
|
||||
Features:
|
||||
* adding tests with minimal hassle (no manual adding to suites or testlists!)
|
||||
|
75
ctest.h
75
ctest.h
@ -16,6 +16,10 @@
|
||||
#ifndef CTEST_H
|
||||
#define CTEST_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define CTEST_IMPL_FORMAT_PRINTF(a, b) __attribute__ ((format(printf, a, b)))
|
||||
#else
|
||||
@ -25,9 +29,16 @@
|
||||
#include <inttypes.h> /* intmax_t, uintmax_t, PRI* */
|
||||
#include <stddef.h> /* size_t */
|
||||
|
||||
typedef void (*ctest_nullary_run_func)(void);
|
||||
typedef void (*ctest_unary_run_func)(void*);
|
||||
typedef void (*ctest_setup_func)(void*);
|
||||
typedef void (*ctest_teardown_func)(void*);
|
||||
|
||||
union ctest_run_func_union {
|
||||
ctest_nullary_run_func nullary;
|
||||
ctest_unary_run_func unary;
|
||||
};
|
||||
|
||||
#define CTEST_IMPL_PRAGMA(x) _Pragma (#x)
|
||||
|
||||
#if defined(__GNUC__)
|
||||
@ -50,12 +61,10 @@ typedef void (*ctest_teardown_func)(void*);
|
||||
#define CTEST_IMPL_DIAG_POP()
|
||||
#endif
|
||||
|
||||
CTEST_IMPL_DIAG_PUSH_IGNORED(strict-prototypes)
|
||||
|
||||
struct ctest {
|
||||
const char* ssname; // suite name
|
||||
const char* ttname; // test name
|
||||
void (*run)();
|
||||
union ctest_run_func_union run;
|
||||
|
||||
void* data;
|
||||
ctest_setup_func* setup;
|
||||
@ -66,8 +75,6 @@ struct ctest {
|
||||
unsigned int magic;
|
||||
};
|
||||
|
||||
CTEST_IMPL_DIAG_POP()
|
||||
|
||||
#define CTEST_IMPL_NAME(name) ctest_##name
|
||||
#define CTEST_IMPL_FNAME(sname, tname) CTEST_IMPL_NAME(sname##_##tname##_run)
|
||||
#define CTEST_IMPL_TNAME(sname, tname) CTEST_IMPL_NAME(sname##_##tname)
|
||||
@ -75,8 +82,10 @@ CTEST_IMPL_DIAG_POP()
|
||||
#define CTEST_IMPL_DATA_TNAME(sname, tname) CTEST_IMPL_NAME(sname##_##tname##_data)
|
||||
#define CTEST_IMPL_SETUP_FNAME(sname) CTEST_IMPL_NAME(sname##_setup)
|
||||
#define CTEST_IMPL_SETUP_FPNAME(sname) CTEST_IMPL_NAME(sname##_setup_ptr)
|
||||
#define CTEST_IMPL_SETUP_TPNAME(sname, tname) CTEST_IMPL_NAME(sname##_##tname##_setup_ptr)
|
||||
#define CTEST_IMPL_TEARDOWN_FNAME(sname) CTEST_IMPL_NAME(sname##_teardown)
|
||||
#define CTEST_IMPL_TEARDOWN_FPNAME(sname) CTEST_IMPL_NAME(sname##_teardown_ptr)
|
||||
#define CTEST_IMPL_TEARDOWN_TPNAME(sname, tname) CTEST_IMPL_NAME(sname##_##tname##_teardown_ptr)
|
||||
|
||||
#define CTEST_IMPL_MAGIC (0xdeadbeef)
|
||||
#ifdef __APPLE__
|
||||
@ -87,14 +96,43 @@ CTEST_IMPL_DIAG_POP()
|
||||
|
||||
#define CTEST_IMPL_STRUCT(sname, tname, tskip, tdata, tsetup, tteardown) \
|
||||
static struct ctest CTEST_IMPL_TNAME(sname, tname) CTEST_IMPL_SECTION = { \
|
||||
.ssname=#sname, \
|
||||
.ttname=#tname, \
|
||||
.run = CTEST_IMPL_FNAME(sname, tname), \
|
||||
.data = tdata, \
|
||||
.setup = (ctest_setup_func*) tsetup, \
|
||||
.teardown = (ctest_teardown_func*) tteardown, \
|
||||
.skip = tskip, \
|
||||
.magic = CTEST_IMPL_MAGIC }
|
||||
#sname, \
|
||||
#tname, \
|
||||
{ (ctest_nullary_run_func) CTEST_IMPL_FNAME(sname, tname) }, \
|
||||
tdata, \
|
||||
(ctest_setup_func*) tsetup, \
|
||||
(ctest_teardown_func*) tteardown, \
|
||||
tskip, \
|
||||
CTEST_IMPL_MAGIC, \
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#define CTEST_SETUP(sname) \
|
||||
template <> void CTEST_IMPL_SETUP_FNAME(sname)(struct CTEST_IMPL_DATA_SNAME(sname)* data)
|
||||
|
||||
#define CTEST_TEARDOWN(sname) \
|
||||
template <> void CTEST_IMPL_TEARDOWN_FNAME(sname)(struct CTEST_IMPL_DATA_SNAME(sname)* data)
|
||||
|
||||
#define CTEST_DATA(sname) \
|
||||
template <typename T> void CTEST_IMPL_SETUP_FNAME(sname)(T* data) { } \
|
||||
template <typename T> void CTEST_IMPL_TEARDOWN_FNAME(sname)(T* data) { } \
|
||||
struct CTEST_IMPL_DATA_SNAME(sname)
|
||||
|
||||
#define CTEST_IMPL_CTEST(sname, tname, tskip) \
|
||||
static void CTEST_IMPL_FNAME(sname, tname)(void); \
|
||||
CTEST_IMPL_STRUCT(sname, tname, tskip, NULL, NULL, NULL); \
|
||||
static void CTEST_IMPL_FNAME(sname, tname)(void)
|
||||
|
||||
#define CTEST_IMPL_CTEST2(sname, tname, tskip) \
|
||||
static struct CTEST_IMPL_DATA_SNAME(sname) CTEST_IMPL_DATA_TNAME(sname, tname); \
|
||||
static void CTEST_IMPL_FNAME(sname, tname)(struct CTEST_IMPL_DATA_SNAME(sname)* data); \
|
||||
static void (*CTEST_IMPL_SETUP_TPNAME(sname, tname))(struct CTEST_IMPL_DATA_SNAME(sname)*) = &CTEST_IMPL_SETUP_FNAME(sname)<struct CTEST_IMPL_DATA_SNAME(sname)>; \
|
||||
static void (*CTEST_IMPL_TEARDOWN_TPNAME(sname, tname))(struct CTEST_IMPL_DATA_SNAME(sname)*) = &CTEST_IMPL_TEARDOWN_FNAME(sname)<struct CTEST_IMPL_DATA_SNAME(sname)>; \
|
||||
CTEST_IMPL_STRUCT(sname, tname, tskip, &CTEST_IMPL_DATA_TNAME(sname, tname), &CTEST_IMPL_SETUP_TPNAME(sname, tname), &CTEST_IMPL_TEARDOWN_TPNAME(sname, tname)); \
|
||||
static void CTEST_IMPL_FNAME(sname, tname)(struct CTEST_IMPL_DATA_SNAME(sname)* data)
|
||||
|
||||
#else
|
||||
|
||||
#define CTEST_SETUP(sname) \
|
||||
static void CTEST_IMPL_SETUP_FNAME(sname)(struct CTEST_IMPL_DATA_SNAME(sname)* data); \
|
||||
@ -123,6 +161,7 @@ CTEST_IMPL_DIAG_POP()
|
||||
CTEST_IMPL_STRUCT(sname, tname, tskip, &CTEST_IMPL_DATA_TNAME(sname, tname), &CTEST_IMPL_SETUP_FPNAME(sname), &CTEST_IMPL_TEARDOWN_FPNAME(sname)); \
|
||||
static void CTEST_IMPL_FNAME(sname, tname)(struct CTEST_IMPL_DATA_SNAME(sname)* data)
|
||||
|
||||
#endif
|
||||
|
||||
void CTEST_LOG(const char* fmt, ...) CTEST_IMPL_FORMAT_PRINTF(1, 2);
|
||||
void CTEST_ERR(const char* fmt, ...) CTEST_IMPL_FORMAT_PRINTF(1, 2); // doesn't return
|
||||
@ -427,7 +466,7 @@ static uint64_t getCurrentTime(void) {
|
||||
|
||||
static void color_print(const char* color, const char* text) {
|
||||
if (color_output)
|
||||
printf("%s%s"ANSI_NORMAL"\n", color, text);
|
||||
printf("%s%s" ANSI_NORMAL "\n", color, text);
|
||||
else
|
||||
printf("%s\n", text);
|
||||
}
|
||||
@ -512,9 +551,9 @@ __attribute__((no_sanitize_address)) int ctest_main(int argc, const char *argv[]
|
||||
if (result == 0) {
|
||||
if (test->setup && *test->setup) (*test->setup)(test->data);
|
||||
if (test->data)
|
||||
test->run(test->data);
|
||||
test->run.unary(test->data);
|
||||
else
|
||||
test->run();
|
||||
test->run.nullary();
|
||||
if (test->teardown && *test->teardown) (*test->teardown)(test->data);
|
||||
// if we got here it's ok
|
||||
#ifdef CTEST_COLOR_OK
|
||||
@ -543,5 +582,9 @@ __attribute__((no_sanitize_address)) int ctest_main(int argc, const char *argv[]
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user