aboutsummaryrefslogtreecommitdiff
path: root/test_util.h
blob: 2a652dedf2930b6fb9ca2170aaa36d2d623c6d6a (plain)
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
#ifndef TEST_UTIL_H
#define TEST_UTIL_H

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#ifdef _MSC_VER

#define CCALL __cdecl
#pragma section(".CRT$XCU",read)
#define INITIALIZER(f) \
   static void __cdecl f(void); \
   __declspec(allocate(".CRT$XCU")) void (__cdecl*f##_)(void) = f; \
   static void __cdecl f(void)

#elif defined(__GNUC__)

#define CCALL
#define INITIALIZER(f) \
   static void f(void) __attribute__((constructor)); \
   static void f(void)

#endif

// __attribute__((constructor)) static void test_##NAME##_init()

#define TEST(NAME) \
    static void test_##NAME(); \
    void test_util_add_test(const char *name, void (*func)()); \
    INITIALIZER(test_##NAME##_init) \
    { \
        test_util_add_test(__FILE__ "_" #NAME, &test_##NAME); \
    } \
    static void test_##NAME()

#define TEST_MAIN() \
    typedef void (*test_func)(); \
    struct test_def { \
        const char *name; \
        test_func func; \
        struct test_def *next; \
    }; \
    static struct test_def test_defs; \
    void test_util_add_test(const char *name, void (*func)()) \
    { \
        struct test_def *def = calloc(1, sizeof(*def)); \
        struct test_def *last = &test_defs; \
        while (last && last->next) last = last->next; \
        last->next = def; \
        def->name = strdup(name); \
        def->func = func; \
    } \
    int main() \
    { \
        struct test_def *def = test_defs.next; \
        while (def) \
        { \
            printf("running test %s\n", def->name); \
            def->func(); \
            def = def->next; \
        } \
        return 0; \
    }

#define FG_RED "\x1b[31m"
#define FG_RESET "\x1b[39m"

#define ASSERT(X) \
    do { \
        if (!(X)) { \
            fprintf(stderr, FG_RED "assertion %s failed at %s:%d\n" FG_RESET, \
                    #X, __FILE__, __LINE__); \
            return; \
        } \
    } while (0)

#define ASSERT_MSG(X, FMT, ...) \
    do { \
        if (!(X)) { \
            fprintf(stderr, "assertion %s failed at %s:%d (" FMT ")\n", \
                    #X, __FILE__, __LINE__, ##__VA_ARGS__); \
            return; \
        } \
    } while (0)

#define ASSERT_TRUE(X) ASSERT(X)
#define ASSERT_FALSE(X) ASSERT(!(X))

#define ASSERT_EQ(EXPECTED, ACTUAL) ASSERT(((EXPECTED) == (ACTUAL)))
#define ASSERT_NEQ(EXPECTED, ACTUAL) ASSERT(((EXPECTED) != (ACTUAL)))

#define ASSERT_STREQ(EXPECTED, ACTUAL) ASSERT(strcmp((EXPECTED), (ACTUAL)) == 0)
#define ASSERT_STREQ_N(EXPECTED, ACTUAL, N) ASSERT(strncmp((EXPECTED), (ACTUAL), (N)) == 0)

#endif