test.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469
  1. // test.h
  2. // Common definitions for trivial test harness
  3. #ifndef TEST_H
  4. #define TEST_H
  5. #include <stdio.h>
  6. #include <dlfcn.h>
  7. #include <stdlib.h>
  8. #include <stdarg.h>
  9. #include <string.h>
  10. #include <libgen.h>
  11. #include <unistd.h>
  12. #include <pthread.h>
  13. #if __cplusplus
  14. #include <atomic>
  15. using namespace std;
  16. #else
  17. #include <stdatomic.h>
  18. #endif
  19. #include <sys/errno.h>
  20. #include <sys/param.h>
  21. #include <malloc/malloc.h>
  22. #include <mach/mach.h>
  23. #include <mach/vm_param.h>
  24. #include <mach/mach_time.h>
  25. #include <objc/objc.h>
  26. #include <objc/runtime.h>
  27. #include <objc/message.h>
  28. #include <objc/objc-abi.h>
  29. #include <objc/objc-auto.h>
  30. #include <objc/objc-internal.h>
  31. #include <TargetConditionals.h>
  32. #if __has_include(<ptrauth.h>)
  33. # include <ptrauth.h>
  34. #endif
  35. #include "../runtime/isa.h"
  36. #if __cplusplus
  37. # define EXTERN_C extern "C"
  38. #else
  39. # define EXTERN_C /*empty*/
  40. #endif
  41. // Test output
  42. static inline void succeed(const char *name) __attribute__((noreturn));
  43. static inline void succeed(const char *name)
  44. {
  45. if (name) {
  46. char path[MAXPATHLEN+1];
  47. strcpy(path, name);
  48. fprintf(stderr, "OK: %s\n", basename(path));
  49. } else {
  50. fprintf(stderr, "OK\n");
  51. }
  52. exit(0);
  53. }
  54. static inline void fail(const char *msg, ...) __attribute__((noreturn));
  55. static inline void fail(const char *msg, ...)
  56. {
  57. if (msg) {
  58. char *msg2;
  59. asprintf(&msg2, "BAD: %s\n", msg);
  60. va_list v;
  61. va_start(v, msg);
  62. vfprintf(stderr, msg2, v);
  63. va_end(v);
  64. free(msg2);
  65. } else {
  66. fprintf(stderr, "BAD\n");
  67. }
  68. exit(1);
  69. }
  70. #define testassert(cond) \
  71. ((void) (((cond) != 0) ? (void)0 : __testassert(#cond, __FILE__, __LINE__)))
  72. #define __testassert(cond, file, line) \
  73. (fail("failed assertion '%s' at %s:%u", cond, __FILE__, __LINE__))
  74. /* time-sensitive assertion, disabled under valgrind */
  75. #define timecheck(name, time, fast, slow) \
  76. if (getenv("VALGRIND") && 0 != strcmp(getenv("VALGRIND"), "NO")) { \
  77. /* valgrind; do nothing */ \
  78. } else if (time > slow) { \
  79. fprintf(stderr, "SLOW: %s %llu, expected %llu..%llu\n", \
  80. name, (uint64_t)(time), (uint64_t)(fast), (uint64_t)(slow)); \
  81. } else if (time < fast) { \
  82. fprintf(stderr, "FAST: %s %llu, expected %llu..%llu\n", \
  83. name, (uint64_t)(time), (uint64_t)(fast), (uint64_t)(slow)); \
  84. } else { \
  85. testprintf("time: %s %llu, expected %llu..%llu\n", \
  86. name, (uint64_t)(time), (uint64_t)(fast), (uint64_t)(slow)); \
  87. }
  88. // Return true if testprintf() output is enabled.
  89. static inline bool testverbose(void)
  90. {
  91. static int verbose = -1;
  92. if (verbose < 0) verbose = atoi(getenv("VERBOSE") ?: "0");
  93. // VERBOSE=1 prints test harness info only
  94. // VERBOSE=2 prints test info
  95. return verbose >= 2;
  96. }
  97. // Print debugging info when VERBOSE=2 is set,
  98. // without disturbing the test's expected output.
  99. static inline void testprintf(const char *msg, ...)
  100. {
  101. if (msg && testverbose()) {
  102. char *msg2;
  103. asprintf(&msg2, "VERBOSE: %s", msg);
  104. va_list v;
  105. va_start(v, msg);
  106. vfprintf(stderr, msg2, v);
  107. va_end(v);
  108. free(msg2);
  109. }
  110. }
  111. // complain to output, but don't fail the test
  112. // Use when warning that some test is being temporarily skipped
  113. // because of something like a compiler bug.
  114. static inline void testwarn(const char *msg, ...)
  115. {
  116. if (msg) {
  117. char *msg2;
  118. asprintf(&msg2, "WARN: %s\n", msg);
  119. va_list v;
  120. va_start(v, msg);
  121. vfprintf(stderr, msg2, v);
  122. va_end(v);
  123. free(msg2);
  124. }
  125. }
  126. static inline void testnoop() { }
  127. // Prevent deprecation warnings from some runtime functions.
  128. static inline void test_objc_flush_caches(Class cls)
  129. {
  130. #pragma clang diagnostic push
  131. #pragma clang diagnostic ignored "-Wdeprecated-declarations"
  132. _objc_flush_caches(cls);
  133. #pragma clang diagnostic pop
  134. }
  135. #define _objc_flush_caches(c) test_objc_flush_caches(c)
  136. static inline Class test_class_setSuperclass(Class cls, Class supercls)
  137. {
  138. #pragma clang diagnostic push
  139. #pragma clang diagnostic ignored "-Wdeprecated-declarations"
  140. return class_setSuperclass(cls, supercls);
  141. #pragma clang diagnostic pop
  142. }
  143. #define class_setSuperclass(c, s) test_class_setSuperclass(c, s)
  144. static inline void testcollect()
  145. {
  146. _objc_flush_caches(nil);
  147. }
  148. // Synchronously run test code on another thread.
  149. // The block object is unsafe_unretained because we must not allow
  150. // ARC to retain them in non-Foundation tests
  151. typedef void(^testblock_t)(void);
  152. static __unsafe_unretained testblock_t testcodehack;
  153. static inline void *_testthread(void *arg __unused)
  154. {
  155. testcodehack();
  156. return NULL;
  157. }
  158. static inline void testonthread(__unsafe_unretained testblock_t code)
  159. {
  160. pthread_t th;
  161. testcodehack = code; // force GC not-thread-local, avoid ARC void* casts
  162. pthread_create(&th, NULL, _testthread, NULL);
  163. pthread_join(th, NULL);
  164. }
  165. /* Make sure libobjc does not call global operator new.
  166. Any test that DOES need to call global operator new must
  167. `#define TEST_CALLS_OPERATOR_NEW` before including test.h.
  168. */
  169. #if __cplusplus && !defined(TEST_CALLS_OPERATOR_NEW)
  170. #pragma clang diagnostic push
  171. #pragma clang diagnostic ignored "-Winline-new-delete"
  172. #import <new>
  173. inline void* operator new(std::size_t) throw (std::bad_alloc) { fail("called global operator new"); }
  174. inline void* operator new[](std::size_t) throw (std::bad_alloc) { fail("called global operator new[]"); }
  175. inline void* operator new(std::size_t, const std::nothrow_t&) throw() { fail("called global operator new(nothrow)"); }
  176. inline void* operator new[](std::size_t, const std::nothrow_t&) throw() { fail("called global operator new[](nothrow)"); }
  177. inline void operator delete(void*) throw() { fail("called global operator delete"); }
  178. inline void operator delete[](void*) throw() { fail("called global operator delete[]"); }
  179. inline void operator delete(void*, const std::nothrow_t&) throw() { fail("called global operator delete(nothrow)"); }
  180. inline void operator delete[](void*, const std::nothrow_t&) throw() { fail("called global operator delete[](nothrow)"); }
  181. #pragma clang diagnostic pop
  182. #endif
  183. /* Leak checking
  184. Fails if total malloc memory in use at leak_check(n)
  185. is more than n bytes above that at leak_mark().
  186. */
  187. static inline void leak_recorder(task_t task __unused, void *ctx, unsigned type __unused, vm_range_t *ranges, unsigned count)
  188. {
  189. size_t *inuse = (size_t *)ctx;
  190. while (count--) {
  191. *inuse += ranges[count].size;
  192. }
  193. }
  194. static inline size_t leak_inuse(void)
  195. {
  196. size_t total = 0;
  197. vm_address_t *zones;
  198. unsigned count;
  199. malloc_get_all_zones(mach_task_self(), NULL, &zones, &count);
  200. for (unsigned i = 0; i < count; i++) {
  201. size_t inuse = 0;
  202. malloc_zone_t *zone = (malloc_zone_t *)zones[i];
  203. if (!zone->introspect || !zone->introspect->enumerator) continue;
  204. // skip DispatchContinuations because it sometimes claims to be
  205. // using lots of memory that then goes away later
  206. if (0 == strcmp(zone->zone_name, "DispatchContinuations")) continue;
  207. zone->introspect->enumerator(mach_task_self(), &inuse, MALLOC_PTR_IN_USE_RANGE_TYPE, (vm_address_t)zone, NULL, leak_recorder);
  208. // fprintf(stderr, "%zu in use for zone %s\n", inuse, zone->zone_name);
  209. total += inuse;
  210. }
  211. return total;
  212. }
  213. static inline void leak_dump_heap(const char *msg)
  214. {
  215. fprintf(stderr, "%s\n", msg);
  216. // Make `heap` write to stderr
  217. int outfd = dup(STDOUT_FILENO);
  218. dup2(STDERR_FILENO, STDOUT_FILENO);
  219. pid_t pid = getpid();
  220. char cmd[256];
  221. // environment variables reset for iOS simulator use
  222. sprintf(cmd, "DYLD_LIBRARY_PATH= DYLD_ROOT_PATH= /usr/bin/heap -addresses all %d", (int)pid);
  223. #pragma clang diagnostic push
  224. #pragma clang diagnostic ignored "-Wdeprecated-declarations"
  225. system(cmd);
  226. #pragma clang diagnostic pop
  227. dup2(outfd, STDOUT_FILENO);
  228. close(outfd);
  229. }
  230. static size_t _leak_start;
  231. static inline void leak_mark(void)
  232. {
  233. testcollect();
  234. if (getenv("LEAK_HEAP")) {
  235. leak_dump_heap("HEAP AT leak_mark");
  236. }
  237. _leak_start = leak_inuse();
  238. }
  239. #define leak_check(n) \
  240. do { \
  241. const char *_check = getenv("LEAK_CHECK"); \
  242. size_t inuse; \
  243. if (_check && 0 == strcmp(_check, "NO")) break; \
  244. testcollect(); \
  245. if (getenv("LEAK_HEAP")) { \
  246. leak_dump_heap("HEAP AT leak_check"); \
  247. } \
  248. inuse = leak_inuse(); \
  249. if (inuse > _leak_start + n) { \
  250. fprintf(stderr, "BAD: %zu bytes leaked at %s:%u " \
  251. "(try LEAK_HEAP and HANG_ON_LEAK to debug)\n", \
  252. inuse - _leak_start, __FILE__, __LINE__); \
  253. if (getenv("HANG_ON_LEAK")) { \
  254. fprintf(stderr, "Hanging after leaks detected. " \
  255. "Leaks command:\n"); \
  256. fprintf(stderr, "leaks %d\n", getpid()); \
  257. while (1) sleep(1); \
  258. } \
  259. } \
  260. } while (0)
  261. // true when running under Guard Malloc
  262. static inline bool is_guardmalloc(void)
  263. {
  264. const char *env = getenv("GUARDMALLOC");
  265. return (env && 0 == strcmp(env, "1"));
  266. }
  267. // true when running a debug build of libobjc
  268. static inline bool is_debug(void)
  269. {
  270. static int debugness = -1;
  271. if (debugness == -1) {
  272. debugness = dlsym(RTLD_DEFAULT, "_objc_isDebugBuild") ? 1 : 0;
  273. }
  274. return (bool)debugness;
  275. }
  276. /* Memory management compatibility macros */
  277. static id self_fn(id x) __attribute__((used));
  278. static id self_fn(id x) { return x; }
  279. #if __has_feature(objc_arc_weak)
  280. // __weak
  281. # define WEAK_STORE(dst, val) (dst = (val))
  282. # define WEAK_LOAD(src) (src)
  283. #else
  284. // no __weak
  285. # define WEAK_STORE(dst, val) objc_storeWeak((id *)&dst, val)
  286. # define WEAK_LOAD(src) objc_loadWeak((id *)&src)
  287. #endif
  288. #if __has_feature(objc_arc)
  289. // ARC
  290. # define RELEASE_VAR(x) x = nil
  291. # define SUPER_DEALLOC()
  292. # define RETAIN(x) (self_fn(x))
  293. # define RELEASE_VALUE(x) ((void)self_fn(x))
  294. # define AUTORELEASE(x) (self_fn(x))
  295. #else
  296. // MRC
  297. # define RELEASE_VAR(x) do { [x release]; x = nil; } while (0)
  298. # define SUPER_DEALLOC() [super dealloc]
  299. # define RETAIN(x) [x retain]
  300. # define RELEASE_VALUE(x) [x release]
  301. # define AUTORELEASE(x) [x autorelease]
  302. #endif
  303. /* gcc compatibility macros */
  304. /* <rdar://problem/9412038> @autoreleasepool should generate objc_autoreleasePoolPush/Pop on 10.7/5.0 */
  305. //#if !defined(__clang__)
  306. # define PUSH_POOL { void *pool = objc_autoreleasePoolPush();
  307. # define POP_POOL objc_autoreleasePoolPop(pool); }
  308. //#else
  309. //# define PUSH_POOL @autoreleasepool
  310. //# define POP_POOL
  311. //#endif
  312. #if __OBJC__
  313. /* General purpose root class */
  314. OBJC_ROOT_CLASS
  315. @interface TestRoot {
  316. @public
  317. Class isa;
  318. }
  319. +(void) load;
  320. +(void) initialize;
  321. -(id) self;
  322. -(Class) class;
  323. -(Class) superclass;
  324. +(id) new;
  325. +(id) alloc;
  326. +(id) allocWithZone:(void*)zone;
  327. -(id) copy;
  328. -(id) mutableCopy;
  329. -(id) init;
  330. -(void) dealloc;
  331. @end
  332. @interface TestRoot (RR)
  333. -(id) retain;
  334. -(oneway void) release;
  335. -(id) autorelease;
  336. -(unsigned long) retainCount;
  337. -(id) copyWithZone:(void *)zone;
  338. -(id) mutableCopyWithZone:(void*)zone;
  339. @end
  340. // incremented for each call of TestRoot's methods
  341. extern atomic_int TestRootLoad;
  342. extern atomic_int TestRootInitialize;
  343. extern atomic_int TestRootAlloc;
  344. extern atomic_int TestRootAllocWithZone;
  345. extern atomic_int TestRootCopy;
  346. extern atomic_int TestRootCopyWithZone;
  347. extern atomic_int TestRootMutableCopy;
  348. extern atomic_int TestRootMutableCopyWithZone;
  349. extern atomic_int TestRootInit;
  350. extern atomic_int TestRootDealloc;
  351. extern atomic_int TestRootRetain;
  352. extern atomic_int TestRootRelease;
  353. extern atomic_int TestRootAutorelease;
  354. extern atomic_int TestRootRetainCount;
  355. extern atomic_int TestRootTryRetain;
  356. extern atomic_int TestRootIsDeallocating;
  357. extern atomic_int TestRootPlusRetain;
  358. extern atomic_int TestRootPlusRelease;
  359. extern atomic_int TestRootPlusAutorelease;
  360. extern atomic_int TestRootPlusRetainCount;
  361. #endif
  362. // Struct that does not return in registers on any architecture
  363. struct stret {
  364. int a;
  365. int b;
  366. int c;
  367. int d;
  368. int e;
  369. int f;
  370. int g;
  371. int h;
  372. int i;
  373. int j;
  374. };
  375. static inline BOOL stret_equal(struct stret a, struct stret b)
  376. {
  377. return (a.a == b.a &&
  378. a.b == b.b &&
  379. a.c == b.c &&
  380. a.d == b.d &&
  381. a.e == b.e &&
  382. a.f == b.f &&
  383. a.g == b.g &&
  384. a.h == b.h &&
  385. a.i == b.i &&
  386. a.j == b.j);
  387. }
  388. static struct stret STRET_RESULT __attribute__((used)) = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
  389. #if TARGET_OS_SIMULATOR
  390. // Force cwd to executable's directory during launch.
  391. // sim used to do this but simctl does not.
  392. #include <crt_externs.h>
  393. __attribute__((constructor))
  394. static void hack_cwd(void)
  395. {
  396. if (!getenv("HACKED_CWD")) {
  397. chdir(dirname((*_NSGetArgv())[0]));
  398. setenv("HACKED_CWD", "1", 1);
  399. }
  400. }
  401. #endif
  402. #endif