1/*
2TEST_RUN_OUTPUT
3objc\[\d+\]: class `SwiftV1Class\' not linked into application
4objc\[\d+\]: class `DoesNotExist\' not linked into application
5OK: runtime.m
6OR
7confused by Foundation
8OK: runtime.m
9END
10*/
11
12
13#include "test.h"
14#include "testroot.i"
15#include <string.h>
16#include <dlfcn.h>
17#include <mach-o/ldsyms.h>
18#include <objc/objc-runtime.h>
19
20#if __has_feature(objc_arc)
21
22int main()
23{
24    testwarn("rdar://11368528 confused by Foundation");
25    fprintf(stderr, "confused by Foundation\n");
26    succeed(__FILE__);
27}
28
29#else
30
31@interface Sub : TestRoot @end
32@implementation Sub @end
33
34#if __OBJC2__
35#   define TEST_SWIFT 1
36#else
37#   define TEST_SWIFT 0
38#endif
39
40#define SwiftV1MangledName "_TtC6Module12SwiftV1Class"
41
42#if TEST_SWIFT
43__attribute__((objc_runtime_name(SwiftV1MangledName)))
44@interface SwiftV1Class : TestRoot @end
45@implementation SwiftV1Class @end
46#endif
47
48
49int main()
50{
51    Class list[100];
52    Class *list2;
53    unsigned int count, count0, count2;
54    unsigned int i;
55    int foundTestRoot;
56    int foundSub;
57    int foundSwiftV1;
58    const char **names;
59    Dl_info info;
60
61    [TestRoot class];
62
63    // This shouldn't touch any classes.
64    dladdr(&_mh_execute_header, &info);
65    names = objc_copyClassNamesForImage(info.dli_fname, &count);
66    testassert(names);
67#if TEST_SWIFT
68    testassert(count == 3);
69#else
70    testassert(count == 2);
71#endif
72    testassert(names[count] == NULL);
73    foundTestRoot = 0;
74    foundSub = 0;
75    foundSwiftV1 = 0;
76    for (i = 0; i < count; i++) {
77        if (0 == strcmp(names[i], "TestRoot")) foundTestRoot++;
78        if (0 == strcmp(names[i], "Sub")) foundSub++;
79        if (0 == strcmp(names[i], "Module.SwiftV1Class")) foundSwiftV1++;
80    }
81    testassert(foundTestRoot == 1);
82    testassert(foundSub == 1);
83#if TEST_SWIFT
84    testassert(foundSwiftV1 == 1);
85#endif
86
87
88    // class Sub hasn't been touched - make sure it's in the class list too
89    count0 = objc_getClassList(NULL, 0);
90    testassert(count0 >= 2  &&  count0 < 100);
91
92    list[count0-1] = NULL;
93    count = objc_getClassList(list, count0-1);
94    testassert(list[count0-1] == NULL);
95    testassert(count == count0);
96
97    count = objc_getClassList(list, count0);
98    testassert(count == count0);
99
100    for (i = 0; i < count; i++) {
101        testprintf("%s\n", class_getName(list[i]));
102    }
103
104    foundTestRoot = 0;
105    foundSub = 0;
106    foundSwiftV1 = 0;
107    for (i = 0; i < count; i++) {
108        if (0 == strcmp(class_getName(list[i]), "TestRoot")) foundTestRoot++;
109        if (0 == strcmp(class_getName(list[i]), "Sub")) foundSub++;
110        if (0 == strcmp(class_getName(list[i]), "Module.SwiftV1Class")) foundSwiftV1++;
111        // list should be non-meta classes only
112        testassert(!class_isMetaClass(list[i]));
113    }
114    testassert(foundTestRoot == 1);
115    testassert(foundSub == 1);
116#if TEST_SWIFT
117    testassert(foundSwiftV1 == 1);
118#endif
119
120    // fixme check class handler
121    testassert(objc_getClass("TestRoot") == [TestRoot class]);
122#if TEST_SWIFT
123    testassert(objc_getClass("Module.SwiftV1Class") == [SwiftV1Class class]);
124    testassert(objc_getClass(SwiftV1MangledName) == [SwiftV1Class class]);
125#endif
126    testassert(objc_getClass("SwiftV1Class") == nil);
127    testassert(objc_getClass("DoesNotExist") == nil);
128    testassert(objc_getClass(NULL) == nil);
129
130    testassert(objc_getMetaClass("TestRoot") == object_getClass([TestRoot class]));
131#if TEST_SWIFT
132    testassert(objc_getMetaClass("Module.SwiftV1Class") == object_getClass([SwiftV1Class class]));
133    testassert(objc_getMetaClass(SwiftV1MangledName) == object_getClass([SwiftV1Class class]));
134#endif
135    testassert(objc_getMetaClass("SwiftV1Class") == nil);
136    testassert(objc_getMetaClass("DoesNotExist") == nil);
137    testassert(objc_getMetaClass(NULL) == nil);
138
139    // fixme check class no handler
140    testassert(objc_lookUpClass("TestRoot") == [TestRoot class]);
141#if TEST_SWIFT
142    testassert(objc_lookUpClass("Module.SwiftV1Class") == [SwiftV1Class class]);
143    testassert(objc_lookUpClass(SwiftV1MangledName) == [SwiftV1Class class]);
144#endif
145    testassert(objc_lookUpClass("SwiftV1Class") == nil);
146    testassert(objc_lookUpClass("DoesNotExist") == nil);
147    testassert(objc_lookUpClass(NULL) == nil);
148
149    testassert(! object_isClass(nil));
150    testassert(! object_isClass([TestRoot new]));
151    testassert(object_isClass([TestRoot class]));
152    testassert(object_isClass(object_getClass([TestRoot class])));
153    testassert(object_isClass([Sub class]));
154    testassert(object_isClass(object_getClass([Sub class])));
155#if TEST_SWIFT
156    testassert(object_isClass([SwiftV1Class class]));
157    testassert(object_isClass(object_getClass([SwiftV1Class class])));
158#endif
159
160    list2 = objc_copyClassList(&count2);
161    testassert(count2 == count);
162    testassert(list2);
163    testassert(malloc_size(list2) >= (1+count2) * sizeof(Class));
164    for (i = 0; i < count; i++) {
165        testassert(list[i] == list2[i]);
166    }
167    testassert(list2[count] == NULL);
168    free(list2);
169    free(objc_copyClassList(NULL));
170
171    succeed(__FILE__);
172}
173
174#endif
175