2 // Common definitions for trivial test harness
14 #include <malloc/malloc.h>
15 #include <mach/mach_time.h>
16 #include <objc/objc-auto.h>
18 static inline void succeed(const char *msg
, ...) __attribute__((noreturn
));
19 static inline void succeed(const char *msg
, ...)
23 fprintf(stderr
, "OK: ");
25 vfprintf(stderr
, msg
, v
);
27 fprintf(stderr
, "\n");
29 fprintf(stderr
, "OK\n");
34 static inline int fail(const char *msg
, ...) __attribute__((noreturn
));
35 static inline int fail(const char *msg
, ...)
39 fprintf(stderr
, "BAD: ");
41 vfprintf(stderr
, msg
, v
);
43 fprintf(stderr
, "\n");
45 fprintf(stderr
, "BAD\n");
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__)
55 /* time-sensitive assertion, disabled under valgrind */
56 #define timeassert(cond) \
57 testassert((getenv("VALGRIND") && 0 != strcmp(getenv("VALGRIND"), "NO")) || (cond))
59 static inline void testprintf(const char *msg
, ...)
63 if (getenv("VERBOSE")) vfprintf(stderr
, msg
, v
);
69 Fails if total malloc memory in use at leak_check(n)
70 is more than n bytes above that at leak_mark().
73 static size_t _leak_start
;
74 static inline void leak_mark(void)
76 malloc_statistics_t stats
;
77 if (objc_collecting_enabled()) {
78 objc_startCollectorThread();
79 objc_collect(OBJC_EXHAUSTIVE_COLLECTION
|OBJC_WAIT_UNTIL_DONE
);
81 malloc_zone_statistics(NULL
, &stats
);
82 _leak_start
= stats
.size_in_use
;
85 #define leak_check(n) \
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); \
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()); \
99 fail("%zu bytes leaked at %s:%u", \
100 stats.size_in_use - _leak_start, __FILE__, __LINE__); \