-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtest.h
316 lines (264 loc) · 8.43 KB
/
test.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
// test.h
// Common definitions for trivial test harness
#ifndef TEST_H
#define TEST_H
#define _GNU_SOURCE
#include <stdio.h>
#include <dlfcn.h> // questionable
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <libgen.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/param.h>
#include <mulle-objc-runtime/mulle-objc-runtime.h>
#include <MulleObjC/mulle-objc.h>
#include <objc/objc-runtime.h>
#ifndef OBJC_ROOT_CLASS
# define OBJC_ROOT_CLASS
#endif
#ifndef OBJC_ROOT_CLASS
# define OBJC_INLINE inline
#endif
#ifndef __unused
# define __unused
#endif
static OBJC_INLINE void *objc_collectableZone(void) { return nil; }
// Configuration macros
// Crazy APPLE changes CPP semantics
#ifndef TARGET_OS_WIN32
# define TARGET_OS_WIN32 0
#endif
#if !__LP64__ || TARGET_OS_WIN32 || __OBJC_GC__ || TARGET_IPHONE_SIMULATOR
# define SUPPORT_NONPOINTER_ISA 0
#elif __x86_64__
# define SUPPORT_NONPOINTER_ISA 1
#elif __arm64__
# define SUPPORT_NONPOINTER_ISA 1
#else
# error unknown architecture
#endif
// Test output
static inline void succeed(const char *name) __attribute__((noreturn));
static inline void succeed(const char *name)
{
if (name) {
char path[MAXPATHLEN+1];
strcpy(path, name);
fprintf(stderr, "OK: %s\n", basename(path));
} else {
fprintf(stderr, "OK\n");
}
exit(0);
}
static inline void fail(const char *msg, ...) __attribute__((noreturn));
static inline void fail(const char *msg, ...)
{
if (msg) {
char *msg2;
mulle_asprintf(&msg2, "BAD: %s\n", msg);
va_list v;
va_start(v, msg);
vfprintf(stderr, msg2, v);
va_end(v);
free(msg2);
} else {
fprintf(stderr, "BAD\n");
}
exit(1);
}
#define testassert(cond) \
((void) (((cond) != 0) ? (void)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 timecheck(name, time, fast, slow) \
if (getenv("VALGRIND") && 0 != strcmp(getenv("VALGRIND"), "NO")) { \
/* valgrind; do nothing */ \
} else if (time > slow) { \
fprintf(stderr, "SLOW: %s %llu, expected %llu..%llu\n", \
name, (uint64_t)(time), (uint64_t)(fast), (uint64_t)(slow)); \
} else if (time < fast) { \
fprintf(stderr, "FAST: %s %llu, expected %llu..%llu\n", \
name, (uint64_t)(time), (uint64_t)(fast), (uint64_t)(slow)); \
} else { \
testprintf("time: %s %llu, expected %llu..%llu\n", \
name, (uint64_t)(time), (uint64_t)(fast), (uint64_t)(slow)); \
}
static inline void testprintf(const char *msg, ...)
{
static int verbose = -1;
if (verbose < 0) verbose = atoi(getenv("VERBOSE") ?: "0");
// VERBOSE=1 prints test harness info only
if (msg && verbose >= 2) {
char *msg2;
mulle_asprintf(&msg2, "VERBOSE: %s", msg);
va_list v;
va_start(v, msg);
vfprintf(stderr, msg2, v);
va_end(v);
free(msg2);
}
}
// complain to output, but don't fail the test
// Use when warning that some test is being temporarily skipped
// because of something like a compiler bug.
static inline void testwarn(const char *msg, ...)
{
if (msg) {
char *msg2;
mulle_asprintf(&msg2, "WARN: %s\n", msg);
va_list v;
va_start(v, msg);
vfprintf(stderr, msg2, v);
va_end(v);
free(msg2);
}
}
static inline void testnoop() { }
#define testexc()
#define testcollect()
// Synchronously run test code on another thread.
// This can help force GC to kill objects promptly, which some tests depend on.
// The block object is unsafe_unretained because we must not allow
// ARC to retain them in non-Foundation tests
static void (*testcodehack)( void);
static inline void *_testthread(void *arg __unused)
{
//objc_registerThreadWithCollector();
testcodehack();
return NULL;
}
static inline void testonthread( void (*code) (void))
{
pthread_t th;
testcodehack = code; // force GC not-thread-local, avoid ARC void* casts
pthread_create(&th, NULL, _testthread, NULL);
pthread_join(th, NULL);
}
static inline BOOL is_guardmalloc(void)
{
const char *env = getenv("GUARDMALLOC");
return (env && 0 == strcmp(env, "YES"));
}
/* Memory management compatibility macros */
static id self_fn(id x) __attribute__((used));
static id self_fn(id x) { return x; }
#if __has_feature(objc_arc)
// ARC
# define RELEASE_VAR(x) x = nil
# define WEAK_STORE(dst, val) (dst = (val))
# define WEAK_LOAD(src) (src)
# define SUPER_DEALLOC()
# define RETAIN(x) (self_fn(x))
# define RELEASE_VALUE(x) ((void)self_fn(x))
# define AUTORELEASE(x) (self_fn(x))
#elif defined(__OBJC_GC__)
// GC
# define RELEASE_VAR(x) x = nil
# define WEAK_STORE(dst, val) (dst = (val))
# define WEAK_LOAD(src) (src)
# define SUPER_DEALLOC() [super dealloc]
# define RETAIN(x) [x self]
# define RELEASE_VALUE(x) (void)[x self]
# define AUTORELEASE(x) [x self]
#else
// MRC
# define RELEASE_VAR(x) do { [x release]; x = nil; } while (0)
# define WEAK_STORE(dst, val) objc_storeWeak((id *)&dst, val)
# define WEAK_LOAD(src) objc_loadWeak((id *)&src)
# define SUPER_DEALLOC() [super dealloc]
# define RETAIN(x) [x retain]
# define RELEASE_VALUE(x) [x release]
# define AUTORELEASE(x) [x autorelease]
#endif
/* gcc compatibility macros */
/* <rdar://problem/9412038> @autoreleasepool should generate objc_autoreleasePoolPush/Pop on 10.7/5.0 */
//#if !defined(__clang__)
# define PUSH_POOL { void *pool = objc_autoreleasePoolPush();
# define POP_POOL objc_autoreleasePoolPop(pool); }
//#else
//# define PUSH_POOL @autoreleasepool
//# define POP_POOL
//#endif
#if __OBJC__
/* General purpose root class */
OBJC_ROOT_CLASS
@interface TestRoot {
// @public
// Class isa; // not in mulle-objc
}
+(void) load;
+(void) initialize;
-(id) self;
-(Class) class;
-(Class) superclass;
+(id) new;
+(id) alloc;
+(id) allocWithZone:(void*)zone;
-(id) copy;
-(id) mutableCopy;
-(id) init;
-(void) dealloc;
-(void) finalize;
@end
@interface TestRoot (RR)
-(id) retain;
-(oneway void) release;
-(id) autorelease;
-(unsigned long) retainCount;
-(id) copyWithZone:(void *)zone;
-(id) mutableCopyWithZone:(void*)zone;
@end
// incremented for each call of TestRoot's methods
extern mulle_atomic_pointer_t TestRootLoad;
extern mulle_atomic_pointer_t TestRootInitialize;
extern mulle_atomic_pointer_t TestRootAlloc;
extern mulle_atomic_pointer_t TestRootAllocWithZone;
extern mulle_atomic_pointer_t TestRootCopy;
extern mulle_atomic_pointer_t TestRootCopyWithZone;
extern mulle_atomic_pointer_t TestRootMutableCopy;
extern mulle_atomic_pointer_t TestRootMutableCopyWithZone;
extern mulle_atomic_pointer_t TestRootInit;
extern mulle_atomic_pointer_t TestRootDealloc;
extern mulle_atomic_pointer_t TestRootFinalize;
extern mulle_atomic_pointer_t TestRootRetain;
extern mulle_atomic_pointer_t TestRootRelease;
extern mulle_atomic_pointer_t TestRootAutorelease;
extern mulle_atomic_pointer_t TestRootRetainCount;
extern mulle_atomic_pointer_t TestRootTryRetain;
extern mulle_atomic_pointer_t TestRootIsDeallocating;
extern mulle_atomic_pointer_t TestRootPlusRetain;
extern mulle_atomic_pointer_t TestRootPlusRelease;
extern mulle_atomic_pointer_t TestRootPlusAutorelease;
extern mulle_atomic_pointer_t TestRootPlusRetainCount;
#endif
// Struct that does not return in registers on any architecture
struct stret {
int a;
int b;
int c;
int d;
int e;
int f;
int g;
int h;
int i;
int j;
};
static inline BOOL stret_equal(struct stret a, struct stret b)
{
return (a.a == b.a &&
a.b == b.b &&
a.c == b.c &&
a.d == b.d &&
a.e == b.e &&
a.f == b.f &&
a.g == b.g &&
a.h == b.h &&
a.i == b.i &&
a.j == b.j);
}
static struct stret STRET_RESULT __attribute__((used)) = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
#endif