]> git.saurik.com Git - apple/objc4.git/blob - test/test.h
objc4-437.tar.gz
[apple/objc4.git] / test / test.h
1 // test.h
2 // Common definitions for trivial test harness
3
4
5 #ifndef TEST_H
6 #define TEST_H
7
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <stdarg.h>
11 #include <string.h>
12 #include <libgen.h>
13 #include <unistd.h>
14 #include <malloc/malloc.h>
15 #include <mach/mach_time.h>
16 #include <objc/objc-auto.h>
17
18 static inline void succeed(const char *msg, ...) __attribute__((noreturn));
19 static inline void succeed(const char *msg, ...)
20 {
21 va_list v;
22 if (msg) {
23 fprintf(stderr, "OK: ");
24 va_start(v, msg);
25 vfprintf(stderr, msg, v);
26 va_end(v);
27 fprintf(stderr, "\n");
28 } else {
29 fprintf(stderr, "OK\n");
30 }
31 exit(0);
32 }
33
34 static inline int fail(const char *msg, ...) __attribute__((noreturn));
35 static inline int fail(const char *msg, ...)
36 {
37 va_list v;
38 if (msg) {
39 fprintf(stderr, "BAD: ");
40 va_start(v, msg);
41 vfprintf(stderr, msg, v);
42 va_end(v);
43 fprintf(stderr, "\n");
44 } else {
45 fprintf(stderr, "BAD\n");
46 }
47 exit(1);
48 }
49
50 #define testassert(cond) \
51 ((void) ((cond) ? 0 : __testassert(#cond, __FILE__, __LINE__)))
52 #define __testassert(cond, file, line) \
53 fail("failed assertion '%s' at %s:%u", cond, __FILE__, __LINE__)
54
55 /* time-sensitive assertion, disabled under valgrind */
56 #define timeassert(cond) \
57 testassert((getenv("VALGRIND") && 0 != strcmp(getenv("VALGRIND"), "NO")) || (cond))
58
59 static inline void testprintf(const char *msg, ...)
60 {
61 va_list v;
62 va_start(v, msg);
63 if (getenv("VERBOSE")) vfprintf(stderr, msg, v);
64 va_end(v);
65 }
66
67
68 /* Leak checking
69 Fails if total malloc memory in use at leak_check(n)
70 is more than n bytes above that at leak_mark().
71 */
72
73 static size_t _leak_start;
74 static inline void leak_mark(void)
75 {
76 malloc_statistics_t stats;
77 if (objc_collecting_enabled()) {
78 objc_startCollectorThread();
79 objc_collect(OBJC_EXHAUSTIVE_COLLECTION|OBJC_WAIT_UNTIL_DONE);
80 }
81 malloc_zone_statistics(NULL, &stats);
82 _leak_start = stats.size_in_use;
83 }
84
85 #define leak_check(n) \
86 do { \
87 const char *_check = getenv("LEAK_CHECK"); \
88 if (_check && 0 == strcmp(_check, "NO")) break; \
89 if (objc_collecting_enabled()) { \
90 objc_collect(OBJC_EXHAUSTIVE_COLLECTION|OBJC_WAIT_UNTIL_DONE); \
91 } \
92 malloc_statistics_t stats; \
93 malloc_zone_statistics(NULL, &stats); \
94 if (stats.size_in_use > _leak_start + n) { \
95 if (getenv("HANG_ON_LEAK")) { \
96 printf("leaks %d\n", getpid()); \
97 while (1) sleep(1); \
98 } \
99 fail("%zu bytes leaked at %s:%u", \
100 stats.size_in_use - _leak_start, __FILE__, __LINE__); \
101 } \
102 } while (0)
103
104 #endif