77_tr_enable_vt(HANDLE h)
80 if (!GetConsoleMode(h, &mode)) {
83 return SetConsoleMode(h, mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING) != 0;
86static int _tr_colors_enabled = -1;
91 if (_tr_colors_enabled < 0) {
92 _tr_colors_enabled = _tr_enable_vt(GetStdHandle(STD_OUTPUT_HANDLE));
94 return _tr_colors_enabled;
104#define TR_RESET (_tr_use_colors() ? "\x1b[0m" : "")
105#define TR_BOLD (_tr_use_colors() ? "\x1b[1m" : "")
106#define TR_DIM (_tr_use_colors() ? "\x1b[2m" : "")
107#define TR_GREEN (_tr_use_colors() ? "\x1b[32m" : "")
108#define TR_RED (_tr_use_colors() ? "\x1b[31m" : "")
109#define TR_YELLOW (_tr_use_colors() ? "\x1b[33m" : "")
110#define TR_WHITE (_tr_use_colors() ? "\x1b[97m" : "")
120#define TR_MAX_FAILURES_PER_TEST 16
121#define TR_FAILURE_MSG_LEN 256
124 char msg[TR_FAILURE_MSG_LEN];
128static int _tr_fail_count = 0;
131_tr_record_failure(
const char *file,
int line,
const char *expr)
133 if (TR_MAX_FAILURES_PER_TEST <= _tr_fail_count) {
138 const char *p = file;
139 const char *slash = strrchr(file,
'/');
140 const char *bslash = strrchr(file,
'\\');
141 if (slash && slash > p) {
144 if (bslash && bslash > p) {
148 snprintf(_tr_fail_buf[_tr_fail_count].msg, TR_FAILURE_MSG_LEN,
"%s:%d %s", p, line, expr);
152static int _tr_total = 0;
153static int _tr_passed = 0;
154static int _tr_failed = 0;
155static int _tr_suite_total = 0;
156static int _tr_suite_failed = 0;
161#define EXPECT(cond) \
164 _tr_record_failure(__FILE__, __LINE__, #cond); \
175#define EXPECT_FATAL(cond) \
178 _tr_record_failure(__FILE__, __LINE__, #cond); \
180 printf(" %s[FATAL]%s %s:%d: %s\n", \
193#define EXPECT_STR8_EQ(a, b) EXPECT(str8_match((a), (b)))
205#define TEST_CASE(name) static void test_##name(void)
207typedef void (*_TrTestFn)(void);
227 int fails_before = _tr_failed;
229 clock_t t0 = clock();
231 clock_t t1 = clock();
232 long ms = (long)(((
double)(t1 - t0) / CLOCKS_PER_SEC) * 1000.0);
237 if (_tr_failed == fails_before) {
239 printf(
" %sPASS%s %-34s %s(%ldms)%s\n",
248 printf(
" %sFAIL%s %-34s %s(%ldms)%s\n",
255 for (
int i = 0; i < _tr_fail_count; i++) {
256 printf(
" %s%s%s\n", TR_YELLOW, _tr_fail_buf[i].msg, TR_RESET);
273 _tr_suite_failed = 0;
274 printf(
"\n %s%s%s\n", TR_BOLD, name, TR_RESET);
296 printf(
"\n%s %s%s\n", TR_BOLD, title, TR_RESET);
306 printf(
"\n%s Results%s\n", TR_BOLD, TR_RESET);
307 printf(
" %s----------------------------------------%s\n", TR_DIM, TR_RESET);
308 printf(
" %s%d tests%s %s%d passed%s %s%d failed%s\n\n",
315 _tr_failed > 0 ? TR_RED : TR_DIM,
318 return (_tr_failed > 0) ? 1 : 0;
330#define BEGIN_SUITE(name) \
332 _tr_suite_begin(name);
346#define RUN_TEST(name) _tr_run_test(test_##name, #name)
static void _tr_suite_begin(const char *name)
Prints the suite header and resets per-suite counters.
static int tr_end(void)
Print the results summary. Return value is the process exit code.
static void _tr_run_test(_TrTestFn fn, const char *name)
Executes a single test function, times it, and prints the result.
static void tr_begin(const char *title)
Print the top-level banner. Call once at the start of main().
static void _tr_suite_end(void)
Called after all tests in a suite have run.