1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
|
#ifndef UFTRACE_UNIT_TEST_H
#define UFTRACE_UNIT_TEST_H
#include <stdio.h>
#include <string.h>
enum {
TEST_OK = 0, /* success */
TEST_NG, /* failed */
TEST_SKIP, /* skipped */
TEST_SIG, /* signal caught */
TEST_BAD, /* unknown result */
TEST_MAX,
};
#define stringify(s) __stringify(s)
#define __stringify(s) #s
extern int debug;
#define __TEST_NG(file, line, test, name_a, a, name_b, b) \
({ \
if (debug) { \
printf("test failed at %s:%d: %s\n", file, line, test); \
printf(" %-16s = %ld\n", name_a, (long)a); \
printf(" %-16s = %ld\n", name_b, (long)b); \
fflush(stdout); \
} \
return TEST_NG; \
})
#define __TEST_OP(a, op, b, file, line) \
({ \
const char *name_a; \
const char *name_b; \
__typeof__(a) __a = (a); \
__typeof__(b) __b = (b); \
\
if (__builtin_constant_p(a)) \
name_a = "value_1"; \
else \
name_a = stringify(a); \
\
if (__builtin_constant_p(b)) \
name_b = "value_2"; \
else \
name_b = stringify(b); \
\
if (!(__a op __b)) \
__TEST_NG(file, line, stringify(a op b), name_a, __a, name_b, __b); \
TEST_OK; \
})
#define TEST_EQ(a, b) __TEST_OP(a, ==, b, __FILE__, __LINE__)
#define TEST_NE(a, b) __TEST_OP(a, !=, b, __FILE__, __LINE__)
#define TEST_GT(a, b) __TEST_OP(a, >, b, __FILE__, __LINE__)
#define TEST_GE(a, b) __TEST_OP(a, >=, b, __FILE__, __LINE__)
#define TEST_LT(a, b) __TEST_OP(a, <, b, __FILE__, __LINE__)
#define TEST_LE(a, b) __TEST_OP(a, <=, b, __FILE__, __LINE__)
#define __TEST_STRNG(file, line, test, name_a, a, name_b, b) \
({ \
if (debug) { \
printf("test failed at %s:%d: %s\n", file, line, test); \
printf(" %-16s = %s\n", name_a, a); \
printf(" %-16s = %s\n", name_b, b); \
} \
return TEST_NG; \
})
#define __TEST_STREQ(a, b, file, line) \
({ \
const char *name_a; \
const char *name_b; \
const char *__a = (a); \
const char *__b = (b); \
\
if (__builtin_constant_p(a)) \
name_a = "expected"; \
else \
name_a = stringify(a); \
\
if (__builtin_constant_p(b)) \
name_b = "actual"; \
else \
name_b = stringify(b); \
\
if (strcmp(__a, __b)) \
__TEST_STRNG(file, line, stringify(a == b), name_a, __a, name_b, __b); \
TEST_OK; \
})
#define TEST_STREQ(a, b) __TEST_STREQ(a, b, __FILE__, __LINE__)
#define __TEST_MEMEQ(a, b, sz, file, line) \
({ \
const void *__a = (a); \
const void *__b = (b); \
\
if (memcmp(__a, __b, (sz))) \
__TEST_NG(file, line, stringify(a == b), stringify(a), __a, stringify(b), \
__b); \
TEST_OK; \
})
#define TEST_MEMEQ(a, b, sz) __TEST_MEMEQ((a), (b), (sz), __FILE__, __LINE__)
#define TEST_SECTION "uftrace.unit_test"
struct uftrace_unit_test {
const char *name;
int (*func)(void);
};
#ifdef __clang__
#define TEST_CASE(t) \
extern int func_##t(void); \
\
__attribute__((section(TEST_SECTION), used, no_sanitize("address"))) \
const struct uftrace_unit_test test_##t = { \
.name = stringify(t), \
.func = func_##t, \
}; \
\
int func_##t(void)
#else /* #ifdef __clang__ */
#define TEST_CASE(t) \
extern int func_##t(void); \
\
__attribute__((section(TEST_SECTION), used)) const struct uftrace_unit_test test_##t = { \
.name = stringify(t), \
.func = func_##t, \
}; \
\
int func_##t(void)
#endif /* #ifdef __clang__ */
#define TERM_COLOR_NORMAL ""
#define TERM_COLOR_RESET "\033[0m"
#define TERM_COLOR_BOLD "\033[1m"
#define TERM_COLOR_RED "\033[91m"
#define TERM_COLOR_GREEN "\033[32m"
#define TERM_COLOR_YELLOW "\033[33m"
#endif /* UFTRACE_UNIT_TEST_H */
|