summaryrefslogtreecommitdiff
path: root/source/kit_test/test.h
blob: da6c59b2a99773da87e0c39f71d6a34ed1eef1ea (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 KIT_TEST_TEST_H
#define KIT_TEST_TEST_H

#ifdef __cplusplus
extern "C" {
#endif

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

#ifndef KIT_TEST_FILE
#  define 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,
                                bool);
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];
  bool              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
#  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

#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 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 REQUIRE(ok) \
  kit_test_report_(kit_test_index_, __FILE__, __LINE__, (ok))

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

#ifdef __cplusplus
}
#endif

#endif