]> git.saurik.com Git - apple/objc4.git/blob - test/unload.m
81ce9adccd7816006eacb00a81d2bd1e47ee457e
[apple/objc4.git] / test / unload.m
1 /*
2 TEST_BUILD
3 $C{COMPILE} $DIR/unload4.m -o unload4.dylib -dynamiclib
4 $C{COMPILE_C} $DIR/unload3.c -o unload3.dylib -dynamiclib
5 $C{COMPILE} $DIR/unload2.m -o unload2.bundle -bundle
6 $C{COMPILE} $DIR/unload.m -o unload.out
7 END
8 */
9
10 #include "test.h"
11 #include <objc/runtime.h>
12 #include <dlfcn.h>
13 #include <unistd.h>
14
15 #include "unload.h"
16
17 #if __has_feature(objc_arc)
18
19 int main()
20 {
21 testwarn("rdar://11368528 confused by Foundation");
22 succeed(__FILE__);
23 }
24
25 #else
26
27 static id forward_handler(void)
28 {
29 return 0;
30 }
31
32 static BOOL hasName(const char * const *names, const char *query)
33 {
34 const char *name;
35 while ((name = *names++)) {
36 if (strstr(name, query)) return YES;
37 }
38
39 return NO;
40 }
41
42 void cycle(void)
43 {
44 int i;
45 char buf[100];
46 unsigned int imageCount, imageCount0;
47 const char **names;
48 const char *name;
49
50 names = objc_copyImageNames(&imageCount0);
51 testassert(names);
52 free(names);
53
54 void *bundle = dlopen("unload2.bundle", RTLD_LAZY);
55 testassert(bundle);
56
57 names = objc_copyImageNames(&imageCount);
58 testassert(names);
59 testassert(imageCount == imageCount0 + 1);
60 testassert(hasName(names, "unload2.bundle"));
61 free(names);
62
63 Class small = objc_getClass("SmallClass");
64 Class big = objc_getClass("BigClass");
65 testassert(small);
66 testassert(big);
67
68 name = class_getImageName(small);
69 testassert(name);
70 testassert(strstr(name, "unload2.bundle"));
71 name = class_getImageName(big);
72 testassert(name);
73 testassert(strstr(name, "unload2.bundle"));
74
75 id o1 = [small new];
76 id o2 = [big new];
77 testassert(o1);
78 testassert(o2);
79
80 // give BigClass and BigClass->isa large method caches (4692641)
81 for (i = 0; i < 10000; i++) {
82 sprintf(buf, "method_%d", i);
83 SEL sel = sel_registerName(buf);
84 ((void(*)(id, SEL))objc_msgSend)(o2, sel);
85 ((void(*)(id, SEL))objc_msgSend)(object_getClass(o2), sel);
86 }
87
88 RELEASE_VAR(o1);
89 RELEASE_VAR(o2);
90
91 testcollect();
92
93 int err = dlclose(bundle);
94 testassert(err == 0);
95 err = dlclose(bundle);
96 testassert(err == -1); // already closed
97
98 testassert(objc_getClass("SmallClass") == NULL);
99 testassert(objc_getClass("BigClass") == NULL);
100
101 names = objc_copyImageNames(&imageCount);
102 testassert(names);
103 testassert(imageCount == imageCount0);
104 testassert(! hasName(names, "unload2.bundle"));
105 free(names);
106
107 // these selectors came from the bundle
108 testassert(0 == strcmp("unload2_instance_method", sel_getName(sel_registerName("unload2_instance_method"))));
109 testassert(0 == strcmp("unload2_category_method", sel_getName(sel_registerName("unload2_category_method"))));
110 }
111
112 int main()
113 {
114 // fixme object_dispose() not aggressive enough?
115 if (objc_collectingEnabled()) succeed(__FILE__);
116
117 objc_setForwardHandler((void*)&forward_handler, (void*)&forward_handler);
118
119 #if defined(__arm__)
120 int count = 10;
121 #else
122 int count = is_guardmalloc() ? 10 : 100;
123 #endif
124
125 cycle();
126 #if __LP64__
127 // fixme heap use goes up 512 bytes after the 2nd cycle only - bad or not?
128 cycle();
129 #endif
130
131 leak_mark();
132 while (count--) {
133 cycle();
134 }
135 leak_check(0);
136
137 // 5359412 Make sure dylibs with nothing other than image_info can close
138 void *dylib = dlopen("unload3.dylib", RTLD_LAZY);
139 testassert(dylib);
140 int err = dlclose(dylib);
141 testassert(err == 0);
142 err = dlclose(dylib);
143 testassert(err == -1); // already closed
144
145 // Make sure dylibs with real objc content cannot close
146 dylib = dlopen("unload4.dylib", RTLD_LAZY);
147 testassert(dylib);
148 err = dlclose(dylib);
149 testassert(err == 0);
150 err = dlclose(dylib);
151 testassert(err == 0); // dlopen from libobjc itself
152 err = dlclose(dylib);
153 testassert(err == -1); // already closed
154
155 succeed(__FILE__);
156 }
157
158 #endif