1/*
2TEST_RUN_OUTPUT
3objc\[\d+\]: class `DoesNotExist\' not linked into application
4OK: runtime.m
5OR
6confused by Foundation
7OK: runtime.m
8END
9*/
10
11
12#include "test.h"
13#include "testroot.i"
14#include <string.h>
15#include <dlfcn.h>
16#include <mach-o/ldsyms.h>
17#include <objc/objc-runtime.h>
18
19#if __has_feature(objc_arc)
20
21int main()
22{
23    testwarn("rdar://11368528 confused by Foundation");
24    fprintf(stderr, "confused by Foundation\n");
25    succeed(__FILE__);
26}
27
28#else
29
30@interface Sub : TestRoot @end
31@implementation Sub @end
32
33int main()
34{
35    Class list[100];
36    Class *list2;
37    unsigned int count, count0, count2;
38    unsigned int i;
39    int foundTestRoot;
40    int foundSub;
41    const char **names;
42    Dl_info info;
43
44    [TestRoot class];
45
46    // This shouldn't touch any classes.
47    dladdr(&_mh_execute_header, &info);
48    names = objc_copyClassNamesForImage(info.dli_fname, &count);
49    testassert(names);
50    testassert(count == 2);
51    testassert(names[count] == NULL);
52    foundTestRoot = 0;
53    foundSub = 0;
54    for (i = 0; i < count; i++) {
55        if (0 == strcmp(names[i], "TestRoot")) foundTestRoot++;
56        if (0 == strcmp(names[i], "Sub")) foundSub++;
57    }
58    testassert(foundTestRoot == 1);
59    testassert(foundSub == 1);
60
61
62    // class Sub hasn't been touched - make sure it's in the class list too
63    count0 = objc_getClassList(NULL, 0);
64    testassert(count0 >= 2  &&  count0 < 100);
65
66    list[count0-1] = NULL;
67    count = objc_getClassList(list, count0-1);
68    testassert(list[count0-1] == NULL);
69    testassert(count == count0);
70
71    count = objc_getClassList(list, count0);
72    testassert(count == count0);
73    foundTestRoot = 0;
74    foundSub = 0;
75    for (i = 0; i < count; i++) {
76        if (0 == strcmp(class_getName(list[i]), "TestRoot")) foundTestRoot++;
77        if (0 == strcmp(class_getName(list[i]), "Sub")) foundSub++;
78        // list should be non-meta classes only
79        testassert(!class_isMetaClass(list[i]));
80    }
81    testassert(foundTestRoot == 1);
82    testassert(foundSub == 1);
83
84    // fixme check class handler
85    testassert(objc_getClass("TestRoot") == [TestRoot class]);
86    testassert(objc_getClass("DoesNotExist") == nil);
87    testassert(objc_getClass(NULL) == nil);
88
89    testassert(objc_getMetaClass("TestRoot") == object_getClass([TestRoot class]));
90    testassert(objc_getMetaClass("DoesNotExist") == nil);
91    testassert(objc_getMetaClass(NULL) == nil);
92
93    // fixme check class no handler
94    testassert(objc_lookUpClass("TestRoot") == [TestRoot class]);
95    testassert(objc_lookUpClass("DoesNotExist") == nil);
96    testassert(objc_lookUpClass(NULL) == nil);
97
98    list2 = objc_copyClassList(&count2);
99    testassert(count2 == count);
100    testassert(list2);
101    testassert(malloc_size(list2) >= (1+count2) * sizeof(Class));
102    for (i = 0; i < count; i++) {
103        testassert(list[i] == list2[i]);
104    }
105    testassert(list2[count] == NULL);
106    free(list2);
107    free(objc_copyClassList(NULL));
108
109    succeed(__FILE__);
110}
111
112#endif
113