#ifndef PTUNIT_H
#define PTUNIT_H
#include <stdint.h>
#include <string.h>
#ifdef __cplusplus
extern "C" {
#endif
struct ptunit_srcloc {
const char *file;
uint32_t line;
};
enum ptunit_result_type {
ptur_passed,
ptur_skipped,
ptur_failed_signed_int,
ptur_failed_unsigned_int,
ptur_failed_pointer,
ptur_failed_str
};
struct ptunit_failed_signed_int {
const char *expr;
const char *cmp;
int64_t expected;
int64_t actual;
};
struct ptunit_failed_unsigned_int {
const char *expr;
const char *cmp;
uint64_t expected;
uint64_t actual;
};
struct ptunit_failed_pointer {
const char *expr;
const char *cmp;
const void *expected;
const void *actual;
};
struct ptunit_failed_str {
const char *expr;
const char *cmp;
char *expected;
char *actual;
};
struct ptunit_result {
enum ptunit_result_type type;
struct {
struct ptunit_srcloc where;
union {
struct ptunit_failed_signed_int signed_int;
struct ptunit_failed_unsigned_int unsigned_int;
struct ptunit_failed_pointer pointer;
struct ptunit_failed_str str;
} variant;
} failed;
};
typedef struct ptunit_result (*ptunit_tfun_t)(void);
struct ptunit_test {
const char *name;
const char *args;
struct ptunit_result result;
};
struct ptunit_suite {
const char *name;
uint32_t nr_tests;
uint32_t nr_skips;
uint32_t nr_fails;
};
extern struct ptunit_srcloc ptunit_mk_srcloc(const char *file, uint32_t line);
#define ptu_here() ptunit_mk_srcloc(__FILE__, __LINE__)
extern struct ptunit_result ptunit_mk_passed(void);
extern struct ptunit_result ptunit_mk_skipped(void);
extern struct ptunit_result ptunit_mk_failed_signed_int(const char *expr,
const char *cmp,
struct ptunit_srcloc,
int64_t actual,
int64_t expected);
#define ptunit_int_cmp(A, E, C) \
do { \
int64_t a = (A), e = (E); \
\
if (!(a C e)) \
return ptunit_mk_failed_signed_int(#A #C #E, #C, \
ptu_here(), \
a, e); \
} while (0)
extern struct ptunit_result ptunit_mk_failed_unsigned_int(const char *expr,
const char *cmp,
struct ptunit_srcloc,
uint64_t actual,
uint64_t expected);
#define ptunit_uint_cmp(A, E, C) \
do { \
uint64_t a = (A), e = (E); \
\
if (!(a C e)) \
return ptunit_mk_failed_unsigned_int(#A #C #E, #C, \
ptu_here(), \
a, e); \
} while (0)
extern struct ptunit_result ptunit_mk_failed_pointer(const char *expr,
const char *cmp,
struct ptunit_srcloc,
const void *actual,
const void *expected);
#define ptunit_ptr_cmp(A, E, C) \
do { \
const void *a = (A), *e = (E); \
\
if (!(a C e)) \
return ptunit_mk_failed_pointer(#A #C #E, #C, \
ptu_here(), \
a, e); \
} while (0)
extern struct ptunit_result ptunit_mk_failed_str(const char *expr,
const char *cmp,
struct ptunit_srcloc,
const char *actual,
const char *expected);
#define ptunit_str_cmp(A, E, C) \
do { \
const char *a = (A), *e = (E); \
\
if (!a || !e || !(strcmp(a, e) C 0)) \
return ptunit_mk_failed_str(#A "~"#C #E, "~"#C, \
ptu_here(), \
a, e); \
} while (0)
#define ptunit_subtest(T, ...) \
do { \
struct ptunit_result result; \
\
result = (T)(__VA_ARGS__); \
if (result.type != ptur_passed) \
return result; \
} while (0)
#define ptunit_check(T, ...) \
do { \
struct ptunit_result result; \
\
result = (T)(__VA_ARGS__); \
if (result.type != ptur_passed) { \
result.failed.where = ptu_here(); \
return result; \
} \
} while (0)
extern struct ptunit_test ptunit_mk_test(const char *name, const char *args);
extern void ptunit_fini_test(struct ptunit_test *);
extern struct ptunit_suite ptunit_mk_suite(int argc, char **argv);
extern void ptunit_log_test(struct ptunit_suite *, const struct ptunit_test *);
extern int ptunit_report(const struct ptunit_suite *suite);
#define ptunit_run(S, T) \
do { \
struct ptunit_test test; \
\
test = ptunit_mk_test(#T, NULL); \
test.result = (T)(); \
\
ptunit_log_test(S, &test); \
ptunit_fini_test(&test); \
} while (0)
#define ptunit_run_p(S, T, ...) \
do { \
struct ptunit_test test; \
\
test = ptunit_mk_test(#T, #__VA_ARGS__); \
test.result = (T)(__VA_ARGS__); \
\
ptunit_log_test(S, &test); \
ptunit_fini_test(&test); \
} while (0)
#define ptunit_frun(R, T, F, ...) \
do { \
struct ptunit_result *pr = &(R); \
\
pr->type = ptur_passed; \
if ((F)->init) \
*pr = (F)->init(F); \
\
if (pr->type == ptur_passed) { \
*pr = (T)(__VA_ARGS__); \
\
if ((F)->fini) { \
if (pr->type == ptur_passed) \
*pr = (F)->fini(F); \
else \
(void) (F)->fini(F); \
} \
} \
} while (0)
#define ptunit_run_f(S, T, F) \
do { \
struct ptunit_test test; \
\
test = ptunit_mk_test(#T, #F); \
\
ptunit_frun(test.result, T, &(F), &(F)); \
\
ptunit_log_test(S, &test); \
ptunit_fini_test(&test); \
} while (0)
#define ptunit_run_fp(S, T, F, ...) \
do { \
struct ptunit_test test; \
\
test = ptunit_mk_test(#T, #F ", " #__VA_ARGS__); \
\
ptunit_frun(test.result, T, &(F), &(F), __VA_ARGS__); \
\
ptunit_log_test(S, &test); \
ptunit_fini_test(&test); \
} while (0)
#define ptu_int_eq(A, E) ptunit_int_cmp(A, E, ==)
#define ptu_int_ne(A, E) ptunit_int_cmp(A, E, !=)
#define ptu_int_gt(A, E) ptunit_int_cmp(A, E, >)
#define ptu_int_ge(A, E) ptunit_int_cmp(A, E, >=)
#define ptu_int_lt(A, E) ptunit_int_cmp(A, E, <)
#define ptu_int_le(A, E) ptunit_int_cmp(A, E, <=)
#define ptu_uint_eq(A, E) ptunit_uint_cmp(A, E, ==)
#define ptu_uint_ne(A, E) ptunit_uint_cmp(A, E, !=)
#define ptu_uint_gt(A, E) ptunit_uint_cmp(A, E, >)
#define ptu_uint_ge(A, E) ptunit_uint_cmp(A, E, >=)
#define ptu_uint_lt(A, E) ptunit_uint_cmp(A, E, <)
#define ptu_uint_le(A, E) ptunit_uint_cmp(A, E, <=)
#define ptu_ptr_eq(A, E) ptunit_ptr_cmp(A, E, ==)
#define ptu_ptr_ne(A, E) ptunit_ptr_cmp(A, E, !=)
#define ptu_ptr_gt(A, E) ptunit_ptr_cmp(A, E, >)
#define ptu_ptr_ge(A, E) ptunit_ptr_cmp(A, E, >=)
#define ptu_ptr_lt(A, E) ptunit_ptr_cmp(A, E, <)
#define ptu_ptr_le(A, E) ptunit_ptr_cmp(A, E, <=)
#define ptu_null(A) ptunit_ptr_cmp(A, NULL, ==)
#define ptu_ptr(A) ptunit_ptr_cmp(A, NULL, !=)
#define ptu_str_eq(A, E) ptunit_str_cmp(A, E, ==)
#define ptu_str_ne(A, E) ptunit_str_cmp(A, E, !=)
#define ptu_passed() ptunit_mk_passed()
#define ptu_skipped() ptunit_mk_skipped()
#define ptu_test(T, ...) ptunit_subtest(T, __VA_ARGS__)
#define ptu_check(T, ...) ptunit_check(T, __VA_ARGS__)
#define ptu_run(S, T) ptunit_run(&(S), T)
#define ptu_run_p(S, T, ...) ptunit_run_p(&(S), T, __VA_ARGS__)
#define ptu_run_f(S, T, F) ptunit_run_f(&(S), T, F)
#define ptu_run_fp(S, T, F, ...) ptunit_run_fp(&(S), T, F, __VA_ARGS__)
#ifdef __cplusplus
}
#endif
#endif