xtest/include/xtest/xtest.h

164 lines
6.2 KiB
C

#ifndef XTEST_XTEST_H
#define XTEST_XTEST_H
#if defined(XTEST_XASSERT)
#error "do not include xtest.h before assert.h. If your tests make use of standard library assertions, include first xtest.h and then assert.h"
#endif
#if defined(__GNUC__) || defined(__clang__)
#define XTEST_UNUSED __attribute__((unused))
#else
#define XTEST_UNUSED
#endif
#include <string.h>
#include <stdint.h>
typedef void (*xtest_test_fn)(void * fixture, void ** params);
typedef void (*xtest_setup_fn)(void ** fixture);
typedef void (*xtest_teardown_fn)(void * fixture);
typedef struct xtest_param_s xtest_param;
typedef void *xtest_param_values[];
struct xtest_param_s {
const char *name;
xtest_param_values *values;
};
enum xtest_type {
xtest_type_bool,
xtest_type_char,
xtest_type_short,
xtest_type_unsigned_short,
xtest_type_int,
xtest_type_unsigned_int,
xtest_type_long,
xtest_type_unsigned_long,
xtest_type_long_long,
xtest_type_unsigned_long_long,
xtest_type_float,
xtest_type_double,
xtest_type_long_double,
xtest_type_string,
xtest_type_void_pointer,
xtest_type_other,
};
void xtest_init(int argc, char**argv);
void xtest_fail_assert(const char *expression, const char *file, int line, void *expected,
void *actual, _Bool invert, enum xtest_type type);
void
xtest_assert_float(double expected, double actual, int precision, _Bool invert, const char *expression, const char *file,
int line);
void xtest_assert_mem(const char *expected, const char *actual, size_t length, _Bool invert, const char *expression, const char *file,
int line);
void xtest_internal_run(xtest_test_fn fn, const char *name, xtest_param *params, xtest_setup_fn setup,
xtest_teardown_fn teardown);
void xtest_internal_start_group(const char *name);
void xtest_internal_end_group();
void xtest_skip(const char *reason);
void xtest_expect_assertion_failure();
int xtest_complete();
#ifdef XTEST_PRNG
void xtest_rand_fill(char* buf, size_t len);
double xtest_rand_double();
double xtest_rand_double_range(double min, double max);
int xtest_rand_int();
int xtest_rand_int_range(int min, int max);
uint8_t xtest_rand_8();
uint16_t xtest_rand_16();
uint32_t xtest_rand_32();
uint64_t xtest_rand_64();
#endif
#define xtest_run(fn) xtest_internal_run(fn, #fn, (void*)0, (void*)0, (void*)0)
#define xtest_run_parameterized(fn, params) xtest_internal_run(fn, #fn, params, (void*)0, (void*)0)
#define xtest_run_with_fixture(fn, setup, teardown) xtest_internal_run(fn, #fn, (void*)0, setup, teardown)
#define xtest_run_parameterized_with_fixture(fn, params, setup, teardown) xtest_internal_run(fn, #fn, params, setup, teardown)
#define xtest_group(name) xtest_internal_start_group(#name)
#define xtest_end_group() xtest_internal_end_group()
#define xtest_run_group(fn) do { \
xtest_group(fn); \
fn(); \
xtest_end_group(); \
} while (0)
#define xtest_get_param(type, idx, params) *((type*)(params)[idx])
#define xtest_get_param_ptr(type, idx, params) (type)(params)[idx]
#define xtest_get_type(val) _Generic(val, \
_Bool: xtest_type_bool, \
char: xtest_type_char, \
signed char: xtest_type_char, \
unsigned char: xtest_type_char, \
short: xtest_type_short, \
unsigned short: xtest_type_unsigned_short,\
int: xtest_type_int,\
unsigned int: xtest_type_unsigned_int,\
long: xtest_type_long,\
unsigned long: xtest_type_unsigned_long,\
long long: xtest_type_long_long,\
unsigned long long: xtest_type_unsigned_long_long,\
float: xtest_type_float,\
double: xtest_type_double,\
long double: xtest_type_long_double,\
const char *: xtest_type_string,\
void*:xtest_type_void_pointer,\
default: xtest_type_other)
#define force_types_equal(a, b) (void) _Generic(a, \
__typeof__(b): (void*)0 \
)
#define xtest_assert_(expr, s, actual, expected, invert) do { \
force_types_equal(expected, actual); \
int _xtest_res = (expr); \
if (!(_xtest_res)) { \
__typeof__(actual) _xtest_a = actual; \
__typeof__(expected) _xtest_e = expected; \
enum xtest_type _xtest_type = xtest_get_type(actual); \
xtest_fail_assert(s, __FILE__, __LINE__, &_xtest_e, &_xtest_a, invert, _xtest_type); \
} \
} while(0)
#define xtest_assert(e) xtest_assert_(!!(e), #e, (_Bool)(e), (_Bool)1, 0)
#define xtest_assert_is(actual, expected) xtest_assert_((actual) == (expected), #actual " is " #expected, actual, expected, 0)
#define xtest_assert_is_not(actual, expected) xtest_assert_((actual) != (expected), #actual " is not " #expected, actual, expected, 1)
#define xtest_assert_float_is(actual, expected, precision) xtest_assert_float(expected, actual, precision, 0, #actual " is " #expected, __FILE__, __LINE__)
#define xtest_assert_float_is_not(actual, expected, precision) xtest_assert_float(expected, actual, precision, 1, #actual " is not " #expected, __FILE__, __LINE__)
#define xtest_assert_str_is(actual, expected) xtest_assert_(strcmp(actual, expected) == 0, #actual " is " #expected, (const char*)(actual), (const char*)(expected), 0)
#define xtest_assert_str_is_not(actual, expected) xtest_assert_(strcmp(actual, expected) != 0, #actual " is not " #expected, (const char*)(actual), (const char*)(expected), 1)
#define xtest_assert_mem_is(actual, expected, len) xtest_assert_mem(expected, actual, len, 0, #actual " is " #expected " (" #len " bytes)", __FILE__, __LINE__)
#define xtest_assert_mem_is_not(actual, expected, len) xtest_assert_mem(expected, actual, len, 1, #actual " is not " #expected " (" #len " bytes)", __FILE__, __LINE__)
#define XTEST_RUN_MAIN(fn) int main(int argc, char ** argv) { \
xtest_init(argc, argv); \
fn(); \
return xtest_complete(); \
}
#define XTEST_MAIN void __xtest_main(); \
XTEST_RUN_MAIN(__xtest_main) \
void __xtest_main()
#endif //XTEST_XTEST_H