tests: Unregister a destructor on leaving a test function
[libisds.git] / test / test.h
blob48203821be122b3fbe53d1c9075bc103c0b1d496
1 #ifndef __ISDS_TEST_H
2 #define __ISDS_TEST_H
4 #ifndef _XOPEN_SOURCE
5 #define _XOPEN_SOURCE 700 /* strndup */
6 #endif
7 #include <stdlib.h>
8 #include <stdio.h>
9 #include <locale.h>
10 #include <stdint.h>
11 #include <inttypes.h>
12 #include <stdarg.h>
13 #include <string.h>
15 #include "test-tools.h"
17 extern char *unit_name;
18 extern char *reason;
19 extern unsigned int passed, failed, skipped;
20 extern void (*test_destructor_function)(void *);
21 extern void *test_destructor_argument;
23 #define INIT_TEST(name) { \
24 setlocale(LC_ALL, "C"); \
25 unit_name = name; \
26 passed = failed = skipped = 0; \
27 printf("Testing unit: %s\n", unit_name); \
30 #define SUM_TEST() { \
31 printf("Test results: unit = %s, passed = %u, failed = %u, skipped = %u\n\n", \
32 unit_name, passed, failed, skipped); \
33 exit(failed ? EXIT_FAILURE : passed ? EXIT_SUCCESS : \
34 skipped ? 77 : EXIT_SUCCESS); \
37 #define TEST_DESTRUCTOR(function, argument) { \
38 test_destructor_function = function; \
39 test_destructor_argument = argument; \
42 #define PASS_TEST { \
43 if (NULL != test_destructor_function) \
44 test_destructor_function(test_destructor_argument); \
45 TEST_DESTRUCTOR(NULL, NULL); \
46 return 0; \
47 } \
49 #define FAILURE_REASON(...) { \
50 if (!reason) \
51 test_asprintf(&reason, __VA_ARGS__); \
54 #define FAIL_TEST(...) { \
55 FAILURE_REASON(__VA_ARGS__); \
56 if (NULL != test_destructor_function) \
57 test_destructor_function(test_destructor_argument); \
58 TEST_DESTRUCTOR(NULL, NULL); \
59 return 1; \
62 #define SKIP_TEST(...) { \
63 FAILURE_REASON(__VA_ARGS__); \
64 if (NULL != test_destructor_function) \
65 test_destructor_function(test_destructor_argument); \
66 TEST_DESTRUCTOR(NULL, NULL); \
67 return 77; \
70 #define SKIP_TESTS(number, reason) { \
71 if (1 == (number)) { \
72 printf("\t%u test skipped: %s\n", (number), (reason)); \
73 } else {\
74 printf("\t%u tests skipped: %s\n", (number), (reason)); \
75 } \
76 skipped += (number); \
79 #define ABORT_UNIT(message) { \
80 printf("Unit %s procedure aborted: %s\n", unit_name, (message)); \
81 exit(EXIT_FAILURE); \
85 #define TEST(name, function, ...) { \
86 const char *test_message; \
87 free(reason); reason = NULL; \
88 test_destructor_function = NULL; \
89 int status = (function)(__VA_ARGS__); \
90 if (77 == status) { \
91 skipped++; \
92 test_message = "skipped"; \
93 } else if (status) { \
94 failed++; \
95 test_message = "failed"; \
96 } else { \
97 passed++; \
98 test_message = "passed"; \
99 } \
100 printf("\t%s: %s\n", (name), test_message); \
101 if (status) printf("\t\treason: %s\n", reason); \
102 free(reason); reason = NULL; \
105 #define TEST_CALLOC(pointer) { \
106 (pointer) = calloc(1, sizeof(*(pointer))); \
107 if (!(pointer)) \
108 ABORT_UNIT("No enough memory"); \
111 #define TEST_FILL_STRING(pointer) { \
112 (pointer) = strdup("DATA"); \
113 if (!(pointer)) \
114 ABORT_UNIT("No enough memory"); \
117 #define TEST_FILL_INT(pointer) { \
118 (pointer) = malloc(sizeof(*(pointer))); \
119 if (!(pointer)) \
120 ABORT_UNIT("No enough memory"); \
121 *(pointer) = 42; \
125 #define STR(x) #x
127 #define TEST_POINTER_IS_NULL(x) { \
128 if (NULL != (x)) \
129 FAIL_TEST(STR(x) " is not NULL and should be"); \
132 #define TEST_POINTER_DUPLICITY(x, y) { \
133 if (x == NULL && y != NULL) \
134 FAIL_TEST(STR(x) " is NULL, " STR(y) " is not NULL and should be"); \
135 if (x != NULL && y == NULL) \
136 FAIL_TEST(STR(x) " is not NULL, " STR(y) " is NULL and shouldn't be"); \
137 if (x == y && x != NULL) \
138 FAIL_TEST(STR(y) " is the same pointer as " STR(x)); \
141 #define TEST_STRING_DUPLICITY(x, y) { \
142 TEST_POINTER_DUPLICITY(x, y); \
143 if (x != NULL && y != NULL) { \
144 if (strcmp(x, y)) \
145 FAIL_TEST(STR(y) " differs: expected=`%s' is=`%s'", x, y); \
149 #define TEST_INT_DUPLICITY(x, y) { \
150 if ((x) != (y)) \
151 FAIL_TEST(STR(y) " differs: expected=%ld is=%ld", (x), (y)); \
154 #define TEST_INTPTR_DUPLICITY(x, y) { \
155 TEST_POINTER_DUPLICITY(x, y); \
156 if (x != NULL && y != NULL) { \
157 if (*(x) != *(y)) \
158 FAIL_TEST(STR(y) " differs: expected=%ld is=%ld", *(x), *(y)); \
162 #define TEST_BOOLEAN_DUPLICITY(x, y) { \
163 if ((x) != (y)) \
164 FAIL_TEST(STR(y) " differs: expected=%d is=%d", !!(x), !!(y)); \
167 #define TEST_BOOLEANPTR_DUPLICITY(x, y) { \
168 TEST_POINTER_DUPLICITY(x, y); \
169 if (x != NULL && y != NULL) { \
170 if (*(x) != *(y)) \
171 FAIL_TEST(STR(y) " differs: expected=%d is=%d", !!*(x), !!*(y)); \
175 #define TEST_TIMEVALPTR_DUPLICITY(x, y) { \
176 TEST_POINTER_DUPLICITY(x, y); \
177 if ((x) != NULL && (y) != NULL) { \
178 if ((x)->tv_sec != (y)->tv_sec) \
179 FAIL_TEST("struct timeval * differs in tv_sec: " \
180 "expected=%d, got=%d", (x)->tv_sec, (y)->tv_sec); \
181 if ((x)->tv_usec != (y)->tv_usec) \
182 FAIL_TEST("struct timeval * differs in tv_usec: " \
183 "expected=%" PRIdMAX ", got=%" PRIdMAX, (intmax_t)(x)->tv_usec, \
184 (intmax_t)(y)->tv_usec); \
188 #define TEST_TMPTR_DUPLICITY(x, y) { \
189 TEST_POINTER_DUPLICITY(x, y); \
190 if ((x) != NULL && (y) != NULL) { \
191 if ((x)->tm_year != (y)->tm_year) \
192 FAIL_TEST("struct tm * differs in tm_year: " \
193 "expected=%d, got=%d", (x)->tm_year, (y)->tm_year); \
194 if ((x)->tm_mon != (y)->tm_mon) \
195 FAIL_TEST("struct tm * differs in tm_mon: " \
196 "expected=%d, got=%d", (x)->tm_mon, (y)->tm_mon); \
197 if ((x)->tm_mday != (y)->tm_mday) \
198 FAIL_TEST("struct tm * differs in tm_mday: " \
199 "expected=%d, got=%d", (x)->tm_mday, (y)->tm_mday); \
202 #endif