]> git.saurik.com Git - apple/objc4.git/blame - test/customrr-nsobject.m
objc4-818.2.tar.gz
[apple/objc4.git] / test / customrr-nsobject.m
CommitLineData
13ba007e
A
1// This file is used in the customrr-nsobject-*.m tests
2
3#include "test.h"
4#include <objc/NSObject.h>
1807f628 5#include <objc/objc-internal.h>
13ba007e
A
6
7#if __has_feature(ptrauth_calls)
8typedef IMP __ptrauth_objc_method_list_imp MethodListIMP;
9#else
10typedef IMP MethodListIMP;
11#endif
12
34d5b5e8
A
13EXTERN_C void _method_setImplementationRawUnsafe(Method m, IMP imp);
14
13ba007e
A
15static int Retains;
16static int Releases;
17static int Autoreleases;
18static int PlusInitializes;
19static int Allocs;
20static int AllocWithZones;
21static int Inits;
1807f628
A
22static int PlusNew;
23static int Self;
24static int PlusSelf;
13ba007e
A
25
26id (*RealRetain)(id self, SEL _cmd);
27void (*RealRelease)(id self, SEL _cmd);
28id (*RealAutorelease)(id self, SEL _cmd);
29id (*RealAlloc)(id self, SEL _cmd);
30id (*RealAllocWithZone)(id self, SEL _cmd, void *zone);
1807f628
A
31id (*RealPlusNew)(id self, SEL _cmd);
32id (*RealSelf)(id self);
33id (*RealPlusSelf)(id self);
13ba007e
A
34
35id HackRetain(id self, SEL _cmd) { Retains++; return RealRetain(self, _cmd); }
36void HackRelease(id self, SEL _cmd) { Releases++; return RealRelease(self, _cmd); }
37id HackAutorelease(id self, SEL _cmd) { Autoreleases++; return RealAutorelease(self, _cmd); }
38
39id HackAlloc(Class self, SEL _cmd) { Allocs++; return RealAlloc(self, _cmd); }
40id HackAllocWithZone(Class self, SEL _cmd, void *zone) { AllocWithZones++; return RealAllocWithZone(self, _cmd, zone); }
41
42void HackPlusInitialize(id self __unused, SEL _cmd __unused) { PlusInitializes++; }
43
44id HackInit(id self, SEL _cmd __unused) { Inits++; return self; }
45
1807f628
A
46id HackPlusNew(id self, SEL _cmd __unused) { PlusNew++; return RealPlusNew(self, _cmd); }
47id HackSelf(id self) { Self++; return RealSelf(self); }
48id HackPlusSelf(id self) { PlusSelf++; return RealPlusSelf(self); }
49
13ba007e
A
50
51int main(int argc __unused, char **argv)
52{
53 Class cls = objc_getClass("NSObject");
54 Method meth;
55
56 meth = class_getClassMethod(cls, @selector(initialize));
57 method_setImplementation(meth, (IMP)HackPlusInitialize);
58
59 // We either swizzle the method normally (testing that it properly
60 // disables optimizations), or we hack the implementation into place
61 // behind objc's back (so we can see whether it got called with the
62 // optimizations still enabled).
63
64 meth = class_getClassMethod(cls, @selector(allocWithZone:));
65 RealAllocWithZone = (typeof(RealAllocWithZone))method_getImplementation(meth);
66#if SWIZZLE_AWZ
67 method_setImplementation(meth, (IMP)HackAllocWithZone);
68#else
34d5b5e8 69 _method_setImplementationRawUnsafe(meth, (IMP)HackAllocWithZone);
13ba007e
A
70#endif
71
1807f628
A
72 meth = class_getClassMethod(cls, @selector(new));
73 RealPlusNew = (typeof(RealPlusNew))method_getImplementation(meth);
74#if SWIZZLE_CORE
75 method_setImplementation(meth, (IMP)HackPlusNew);
76#else
34d5b5e8 77 _method_setImplementationRawUnsafe(meth, (IMP)HackPlusNew);
1807f628
A
78#endif
79
80 meth = class_getClassMethod(cls, @selector(self));
81 RealPlusSelf = (typeof(RealPlusSelf))method_getImplementation(meth);
82#if SWIZZLE_CORE
83 method_setImplementation(meth, (IMP)HackPlusSelf);
84#else
34d5b5e8 85 _method_setImplementationRawUnsafe(meth, (IMP)HackPlusSelf);
1807f628
A
86#endif
87
88 meth = class_getInstanceMethod(cls, @selector(self));
89 RealSelf = (typeof(RealSelf))method_getImplementation(meth);
90#if SWIZZLE_CORE
91 method_setImplementation(meth, (IMP)HackSelf);
92#else
34d5b5e8 93 _method_setImplementationRawUnsafe(meth, (IMP)HackSelf);
1807f628
A
94#endif
95
13ba007e
A
96 meth = class_getInstanceMethod(cls, @selector(release));
97 RealRelease = (typeof(RealRelease))method_getImplementation(meth);
98#if SWIZZLE_RELEASE
99 method_setImplementation(meth, (IMP)HackRelease);
100#else
34d5b5e8 101 _method_setImplementationRawUnsafe(meth, (IMP)HackRelease);
13ba007e
A
102#endif
103
104 // These other methods get hacked for counting purposes only
105
106 meth = class_getInstanceMethod(cls, @selector(retain));
107 RealRetain = (typeof(RealRetain))method_getImplementation(meth);
34d5b5e8 108 _method_setImplementationRawUnsafe(meth, (IMP)HackRetain);
13ba007e
A
109
110 meth = class_getInstanceMethod(cls, @selector(autorelease));
111 RealAutorelease = (typeof(RealAutorelease))method_getImplementation(meth);
34d5b5e8 112 _method_setImplementationRawUnsafe(meth, (IMP)HackAutorelease);
13ba007e
A
113
114 meth = class_getClassMethod(cls, @selector(alloc));
115 RealAlloc = (typeof(RealAlloc))method_getImplementation(meth);
34d5b5e8 116 _method_setImplementationRawUnsafe(meth, (IMP)HackAlloc);
13ba007e
A
117
118 meth = class_getInstanceMethod(cls, @selector(init));
34d5b5e8 119 _method_setImplementationRawUnsafe(meth, (IMP)HackInit);
13ba007e
A
120
121 // Verify that the swizzles occurred before +initialize by provoking it now
122 testassert(PlusInitializes == 0);
123 [NSObject self];
124 testassert(PlusInitializes == 1);
125
126 id obj;
127 id result;
128
129 Allocs = 0;
130 AllocWithZones = 0;
131 Inits = 0;
132 obj = objc_alloc(cls);
133#if SWIZZLE_AWZ
134 testprintf("swizzled AWZ should be called\n");
135 testassert(Allocs == 1);
136 testassert(AllocWithZones == 1);
137 testassert(Inits == 0);
138#else
139 testprintf("unswizzled AWZ should be bypassed\n");
140 testassert(Allocs == 0);
141 testassert(AllocWithZones == 0);
142 testassert(Inits == 0);
143#endif
144 testassert([obj isKindOfClass:[NSObject class]]);
145
146 Allocs = 0;
147 AllocWithZones = 0;
148 Inits = 0;
149 obj = [NSObject alloc];
150#if SWIZZLE_AWZ
151 testprintf("swizzled AWZ should be called\n");
152 testassert(Allocs == 1);
153 testassert(AllocWithZones == 1);
154 testassert(Inits == 0);
155#else
156 testprintf("unswizzled AWZ should be bypassed\n");
157 testassert(Allocs == 1);
158 testassert(AllocWithZones == 0);
159 testassert(Inits == 0);
160#endif
161 testassert([obj isKindOfClass:[NSObject class]]);
162
163 Allocs = 0;
164 AllocWithZones = 0;
165 Inits = 0;
166 obj = objc_alloc_init(cls);
167#if SWIZZLE_AWZ
168 testprintf("swizzled AWZ should be called\n");
169 testassert(Allocs == 1);
170 testassert(AllocWithZones == 1);
171 testassert(Inits == 1);
172#else
173 testprintf("unswizzled AWZ should be bypassed\n");
174 testassert(Allocs == 0);
175 testassert(AllocWithZones == 0);
176 testassert(Inits == 1); // swizzled init is still called
177#endif
178 testassert([obj isKindOfClass:[NSObject class]]);
179
180 Retains = 0;
181 result = objc_retain(obj);
182#if SWIZZLE_RELEASE
183 testprintf("swizzled release should force retain\n");
184 testassert(Retains == 1);
185#else
186 testprintf("unswizzled release should bypass retain\n");
187 testassert(Retains == 0);
188#endif
189 testassert(result == obj);
190
191 Releases = 0;
192 Autoreleases = 0;
193 PUSH_POOL {
194 result = objc_autorelease(obj);
195#if SWIZZLE_RELEASE
196 testprintf("swizzled release should force autorelease\n");
197 testassert(Autoreleases == 1);
198#else
199 testprintf("unswizzled release should bypass autorelease\n");
200 testassert(Autoreleases == 0);
201#endif
202 testassert(result == obj);
203 } POP_POOL
204
205#if SWIZZLE_RELEASE
206 testprintf("swizzled release should be called\n");
207 testassert(Releases == 1);
208#else
209 testprintf("unswizzled release should be bypassed\n");
210 testassert(Releases == 0);
211#endif
212
1807f628
A
213 PlusNew = 0;
214 Self = 0;
215 PlusSelf = 0;
216 Class nso = objc_opt_self([NSObject class]);
217 obj = objc_opt_new(nso);
218 obj = objc_opt_self(obj);
219#if SWIZZLE_CORE
220 testprintf("swizzled Core should be called\n");
221 testassert(PlusNew == 1);
222 testassert(Self == 1);
223 testassert(PlusSelf == 1);
224#else
225 testprintf("unswizzled CORE should be bypassed\n");
226 testassert(PlusNew == 0);
227 testassert(Self == 0);
228 testassert(PlusSelf == 0);
229#endif
230 testassert([obj isKindOfClass:nso]);
231
13ba007e
A
232 succeed(basename(argv[0]));
233}