410
|
1 /* |
|
2 * dt.h -- minimalist C testing library |
|
3 * |
|
4 * Copyright (c) 2022 David Demelier <markand@malikania.fr> |
|
5 * |
|
6 * Permission to use, copy, modify, and/or distribute this software for any |
|
7 * purpose with or without fee is hereby granted, provided that the above |
|
8 * copyright notice and this permission notice appear in all copies. |
|
9 * |
|
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
|
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
|
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
|
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
|
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
|
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
|
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
|
17 */ |
|
18 |
|
19 #ifndef DT_H |
|
20 #define DT_H |
|
21 |
|
22 #include <inttypes.h> |
|
23 #include <math.h> |
|
24 #include <stdint.h> |
|
25 #include <stdio.h> |
|
26 #include <string.h> |
|
27 |
|
28 static size_t dt_ntests; |
|
29 static size_t dt_nchecks; |
|
30 static size_t dt_nfailures; |
|
31 |
|
32 #ifndef DT_DOUBLE_TOLERANCE |
|
33 #define DT_DOUBLE_TOLERANCE 0.001 |
|
34 #endif |
|
35 |
|
36 #define DT_ASSERT(x) \ |
|
37 do { \ |
|
38 ++ dt_nchecks; \ |
|
39 \ |
|
40 if (!(x)) { \ |
|
41 ++ dt_nfailures; \ |
|
42 \ |
|
43 printf("%s:%d: assertion '" #x "' failed\n", __FILE__, __LINE__); \ |
|
44 } \ |
|
45 } while (0) |
|
46 |
|
47 #define DT_EQ(x, y, type, f) \ |
|
48 do { \ |
|
49 const type tx = x; \ |
|
50 const type ty = y; \ |
|
51 \ |
|
52 ++ dt_nchecks; \ |
|
53 \ |
|
54 if (tx != ty) { \ |
|
55 ++ dt_nfailures; \ |
|
56 \ |
|
57 printf("%s:%d: assertion " #x " == " #y " failed (" f " != " f ")\n", \ |
|
58 __FILE__, __LINE__, tx, ty); \ |
|
59 } \ |
|
60 } while (0) |
|
61 |
|
62 #define DT_EQ_PTR(x, y) \ |
|
63 do { \ |
|
64 const void *tx = x; \ |
|
65 const void *ty = y; \ |
|
66 \ |
|
67 ++ dt_nchecks; \ |
|
68 \ |
|
69 if (tx != ty) { \ |
|
70 ++ dt_nfailures; \ |
|
71 \ |
|
72 printf("%s:%d: assertion " #x " == " #y " failed (%p != %p)\n", \ |
|
73 __FILE__, __LINE__, tx, ty); \ |
|
74 } \ |
|
75 } while (0) |
|
76 |
|
77 #define DT_EQ_STR(x, y) \ |
|
78 do { \ |
|
79 ++ dt_nchecks; \ |
|
80 \ |
|
81 if (strcmp(x, y) != 0) { \ |
|
82 ++ dt_nfailures; \ |
|
83 \ |
|
84 printf("%s:%d: assertion " #x " == " #y " failed (%s != %s)\n", \ |
|
85 __FILE__, __LINE__, (x), (y)); \ |
|
86 } \ |
|
87 } while (0) |
|
88 |
|
89 #define DT_EQ_DOUBLE(x, y) \ |
|
90 do { \ |
|
91 const double tx = x; \ |
|
92 const double ty = y; \ |
|
93 \ |
|
94 ++ dt_nchecks; \ |
|
95 \ |
|
96 if (fabs(tx - ty) > DT_DOUBLE_TOLERANCE) { \ |
|
97 ++ dt_nfailures; \ |
|
98 \ |
|
99 printf("%s:%d: assertion " #x " == " #y " failed (%f != %f)\n", \ |
|
100 __FILE__, __LINE__, tx, ty); \ |
|
101 } \ |
|
102 } while (0) |
|
103 |
|
104 #define DT_RUN(f, ...) \ |
|
105 do { \ |
|
106 const size_t nchecks = dt_nchecks; \ |
|
107 const size_t nfailures = dt_nfailures; \ |
|
108 \ |
|
109 ++ dt_ntests; \ |
|
110 \ |
|
111 printf("== test " #f " ==\n"); \ |
|
112 f(__VA_ARGS__); \ |
|
113 \ |
|
114 printf("\n%zu checks, %zu failures\n\n", \ |
|
115 dt_nchecks - nchecks, dt_nfailures - nfailures); \ |
|
116 } while (0) |
|
117 |
|
118 #define DT_SUMMARY() \ |
|
119 do { \ |
|
120 printf("summary: %zu tests, %zu checks, %zu failures\n", \ |
|
121 dt_ntests, dt_nchecks, dt_nfailures); \ |
|
122 } while (0) |
|
123 |
|
124 /* Aliases for basic types. */ |
|
125 #define DT_EQ_CHAR(x, y) DT_EQ(x, y, char, "%c") |
|
126 #define DT_EQ_SHORT(x, y) DT_EQ(x, y, short, "%hd") |
|
127 #define DT_EQ_USHORT(x, y) DT_EQ(x, y, unsigned short, "%hu") |
|
128 #define DT_EQ_INT(x, y) DT_EQ(x, y, int, "%d") |
|
129 #define DT_EQ_UINT(x, y) DT_EQ(x, y, unsigned int, "%u") |
|
130 #define DT_EQ_LONG(x, y) DT_EQ(x, y, long, "%ld") |
|
131 #define DT_EQ_ULONG(x, y) DT_EQ(x, y, unsigned long, "%lu") |
|
132 #define DT_EQ_LLONG(x, y) DT_EQ(x, y, long long, "%lld") |
|
133 #define DT_EQ_ULLONG(x, y) DT_EQ(x, y, unsigned long long, "%llu") |
|
134 #define DT_EQ_INTMAX(x, y) DT_EQ(x, y, intmax_t, "%jd") |
|
135 #define DT_EQ_UINTMAX(x, y) DT_EQ(x, y, uintmax_t, "%ju") |
|
136 |
|
137 /* Aliases for fixed size integers. */ |
|
138 #define DT_EQ_INT8(x, y) DT_EQ(x, y, int8_t, PRId8) |
|
139 #define DT_EQ_UINT8(x, y) DT_EQ(x, y, uint8_t int, PRIu8) |
|
140 #define DT_EQ_INT16(x, y) DT_EQ(x, y, int16_t, PRId16) |
|
141 #define DT_EQ_UINT16(x, y) DT_EQ(x, y, uint16_t int, PRIu16) |
|
142 #define DT_EQ_INT32(x, y) DT_EQ(x, y, int32_t, PRId32) |
|
143 #define DT_EQ_UINT32(x, y) DT_EQ(x, y, uint32_t int, PRIu32) |
|
144 #define DT_EQ_INT64(x, y) DT_EQ(x, y, int64_t, PRId64) |
|
145 #define DT_EQ_UINT64(x, y) DT_EQ(x, y, uint64_t int, PRIu64) |
|
146 |
|
147 #endif /* !DT_H */ |