summaryrefslogtreecommitdiff
path: root/source/kit_test/test.h
blob: 6584cbef1ae6ceb5ca0d5c03b0f6a3f3f2a7e8a8 (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
109
110
111
112
113
114
115
116
117
118
#ifndef KIT_TEST_TEST_H
#define KIT_TEST_TEST_H

#ifdef __cplusplus
extern "C" {
#endif

#ifndef _GNU_SOURCE
#  define _GNU_SOURCE
#endif

#include <stddef.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

typedef void (*kit_test_report_fn)(int test_index, int line,
                                   long long value,
                                   long long expected);
typedef void (*kit_test_run_fn)(
    int kit_test_index_, kit_test_report_fn kit_test_report_fn_);

typedef struct {
  char const     *test_name;
  char const     *test_file;
  kit_test_run_fn test_fn;
  int             assertions;
  int             line[KIT_TEST_ASSERTIONS_LIMIT];
  int             status[KIT_TEST_ASSERTIONS_LIMIT];
  long long       value[KIT_TEST_ASSERTIONS_LIMIT];
  long long       expected[KIT_TEST_ASSERTIONS_LIMIT];
  int             signal;
} kit_test_case_t;

typedef struct {
  int             size;
  kit_test_case_t v[KIT_TESTS_SIZE_LIMIT];
} kit_tests_list_t;

extern kit_tests_list_t kit_tests_list;

#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)

#ifdef __cplusplus
#  define KIT_TEST_ON_START_(f)                              \
    static void f(void);                                     \
    static int  KIT_TEST_CONCAT3_(_kit_test_init_, __LINE__, \
                                  f) = (f(), 0);             \
    static void f(void)
#else
#  ifdef _MSC_VER
#    pragma section(".CRT$XCU", read)
#    define KIT_TEST_ON_START_2_(f, p)                               \
      static void f(void);                                           \
      __declspec(allocate(".CRT$XCU")) void (*f##_)(void) = f;       \
      __pragma(comment(linker, "/include:" p #f "_")) 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
#endif

void kit_test_register(char const *name, char const *file,
                       kit_test_run_fn fn);

#define KIT_TEST(name)                                              \
  static void KIT_TEST_CONCAT3_(kit_test_run_, __LINE__,            \
                                KIT_TEST_FILE)(int,                 \
                                               kit_test_report_fn); \
  KIT_TEST_ON_START_(                                               \
      KIT_TEST_CONCAT3_(kit_test_case_, __LINE__, KIT_TEST_FILE)) { \
    kit_test_register(                                              \
        name, __FILE__,                                             \
        KIT_TEST_CONCAT3_(kit_test_run_, __LINE__, KIT_TEST_FILE)); \
  }                                                                 \
  static void KIT_TEST_CONCAT3_(kit_test_run_, __LINE__,            \
                                KIT_TEST_FILE)(                     \
      int kit_test_index_, kit_test_report_fn kit_test_report_fn_)

#define KIT_REQUIRE(...) \
  kit_test_report_fn_(kit_test_index_, __LINE__, (__VA_ARGS__), 1)

#define KIT_REQUIRE_EQ(...) \
  kit_test_report_fn_(kit_test_index_, __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 REQUIRE_EQ KIT_REQUIRE_EQ

#  define test_register kit_test_register
#  define run_tests kit_run_tests
#endif

#ifdef __cplusplus
}
#endif

#endif