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