X-Git-Url: https://git.saurik.com/apple/objc4.git/blobdiff_plain/7c0e6487d7b67b6bf6c632300ee4b74e8950b051..7af964d1562d70f51a8e9aca24215ac3d83d0624:/test/test.h diff --git a/test/test.h b/test/test.h new file mode 100644 index 0000000..a9fa266 --- /dev/null +++ b/test/test.h @@ -0,0 +1,104 @@ +// test.h +// Common definitions for trivial test harness + + +#ifndef TEST_H +#define TEST_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static inline void succeed(const char *msg, ...) __attribute__((noreturn)); +static inline void succeed(const char *msg, ...) +{ + va_list v; + if (msg) { + fprintf(stderr, "OK: "); + va_start(v, msg); + vfprintf(stderr, msg, v); + va_end(v); + fprintf(stderr, "\n"); + } else { + fprintf(stderr, "OK\n"); + } + exit(0); +} + +static inline int fail(const char *msg, ...) __attribute__((noreturn)); +static inline int fail(const char *msg, ...) +{ + va_list v; + if (msg) { + fprintf(stderr, "BAD: "); + va_start(v, msg); + vfprintf(stderr, msg, v); + va_end(v); + fprintf(stderr, "\n"); + } else { + fprintf(stderr, "BAD\n"); + } + exit(1); +} + +#define testassert(cond) \ + ((void) ((cond) ? 0 : __testassert(#cond, __FILE__, __LINE__))) +#define __testassert(cond, file, line) \ + fail("failed assertion '%s' at %s:%u", cond, __FILE__, __LINE__) + +/* time-sensitive assertion, disabled under valgrind */ +#define timeassert(cond) \ + testassert((getenv("VALGRIND") && 0 != strcmp(getenv("VALGRIND"), "NO")) || (cond)) + +static inline void testprintf(const char *msg, ...) +{ + va_list v; + va_start(v, msg); + if (getenv("VERBOSE")) vfprintf(stderr, msg, v); + va_end(v); +} + + +/* Leak checking + Fails if total malloc memory in use at leak_check(n) + is more than n bytes above that at leak_mark(). +*/ + +static size_t _leak_start; +static inline void leak_mark(void) +{ + malloc_statistics_t stats; + if (objc_collecting_enabled()) { + objc_startCollectorThread(); + objc_collect(OBJC_EXHAUSTIVE_COLLECTION|OBJC_WAIT_UNTIL_DONE); + } + malloc_zone_statistics(NULL, &stats); + _leak_start = stats.size_in_use; +} + +#define leak_check(n) \ + do { \ + const char *_check = getenv("LEAK_CHECK"); \ + if (_check && 0 == strcmp(_check, "NO")) break; \ + if (objc_collecting_enabled()) { \ + objc_collect(OBJC_EXHAUSTIVE_COLLECTION|OBJC_WAIT_UNTIL_DONE); \ + } \ + malloc_statistics_t stats; \ + malloc_zone_statistics(NULL, &stats); \ + if (stats.size_in_use > _leak_start + n) { \ + if (getenv("HANG_ON_LEAK")) { \ + printf("leaks %d\n", getpid()); \ + while (1) sleep(1); \ + } \ + fail("%zu bytes leaked at %s:%u", \ + stats.size_in_use - _leak_start, __FILE__, __LINE__); \ + } \ + } while (0) + +#endif