summaryrefslogtreecommitdiff
path: root/source/kit_test/test.h
blob: 52a7b9957e76a79a1d27b6b7adc85e2a0d8b1ab4 (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
97
98
99
100
101
102
103
104
105
106
107
108
#ifndef KIT_TEST_TEST_H
#define KIT_TEST_TEST_H

#ifdef __cplusplus
extern "C" {
#endif

#include <stddef.h>
#include <string.h>

#ifndef KIT_TEST_FILE
#  define KIT_TEST_FILE kit_test
#endif

#ifndef KIT_TESTS_SIZE_LIMIT
#  define KIT_TESTS_SIZE_LIMIT 0x1000
#endif

#ifndef KIT_TEST_ASSERTIONS_LIMIT
#  define KIT_TEST_ASSERTIONS_LIMIT 0x50
#endif

#ifndef KIT_TEST_STRING_SIZE
#  define KIT_TEST_STRING_SIZE 0x100
#endif

typedef void (*kit_test_report)(int, char const *file, int line, int);
typedef void (*kit_test_function)(int, kit_test_report);

struct kit_test_case {
  char              test_name[KIT_TEST_STRING_SIZE];
  kit_test_function test_fn;
  int               assertions;
  char const       *file[KIT_TEST_ASSERTIONS_LIMIT];
  int               line[KIT_TEST_ASSERTIONS_LIMIT];
  int               status[KIT_TEST_ASSERTIONS_LIMIT];
};

struct kit_tests_list {
  int                  size;
  struct kit_test_case tests[KIT_TESTS_SIZE_LIMIT];
};

extern struct kit_tests_list kit_tests_list;

#ifdef _MSC_VER
#  ifdef __cplusplus
#    define KIT_EXTERN_C_ extern "C"
#  else
#    define KIT_EXTERN_C_
#  endif

#  pragma section(".CRT$XCU", read)
#  define KIT_TEST_ON_START_2_(f, p)                         \
    KIT_EXTERN_C_ static void f(void);                       \
    __declspec(allocate(".CRT$XCU")) void (*f##_)(void) = f; \
    __pragma(comment(linker, "/include:" p #f "_"))          \
        KIT_EXTERN_C_ static void                            \
        f(void)
#  ifdef _WIN64
#    define KIT_TEST_ON_START_(f) KIT_TEST_ON_START_2_(f, "")
#  else
#    define KIT_TEST_ON_START_(f) KIT_TEST_ON_START_2_(f, "_")
#  endif
#else
#  define KIT_TEST_ON_START_(f)                       \
    static void f(void) __attribute__((constructor)); \
    static void f(void)
#endif

#define KIT_TEST_CONCAT4_(a, b, c, d) a##b##c##d
#define KIT_TEST_CONCAT3_(a, b, c) KIT_TEST_CONCAT4_(a, b, _, c)

#define KIT_TEST(name)                                               \
  static void KIT_TEST_CONCAT3_(                                     \
      kit_test_run_, __LINE__, KIT_TEST_FILE)(int, kit_test_report); \
  KIT_TEST_ON_START_(                                                \
      KIT_TEST_CONCAT3_(kit_test_case_, __LINE__, KIT_TEST_FILE)) {  \
    int n = kit_tests_list.size;                                     \
    if (n < KIT_TESTS_SIZE_LIMIT) {                                  \
      kit_tests_list.size++;                                         \
      kit_tests_list.tests[n].test_fn = KIT_TEST_CONCAT3_(           \
          kit_test_run_, __LINE__, KIT_TEST_FILE);                   \
      strcpy(kit_tests_list.tests[n].test_name, name);               \
      kit_tests_list.tests[n].assertions = 0;                        \
    }                                                                \
  }                                                                  \
  static void KIT_TEST_CONCAT3_(kit_test_run_, __LINE__,             \
                                KIT_TEST_FILE)(                      \
      int kit_test_index_, kit_test_report kit_test_report_)

#define KIT_REQUIRE(...) \
  kit_test_report_(kit_test_index_, __FILE__, __LINE__, (__VA_ARGS__))

int kit_run_tests(int argc, char **argv);

#ifndef KIT_DISABLE_SHORT_NAMES
#  define TEST KIT_TEST
#  define REQUIRE KIT_REQUIRE

#  define run_tests kit_run_tests
#endif

#ifdef __cplusplus
}
#endif

#endif