6 #import <objc/objc-internal.h>
13 size_t seenClassesCount;
15 static void clear(void) {
21 static void willInitializeClass(void *context, Class cls) {
22 testprintf("Will initialize %s\n", class_getName(cls));
24 seenClasses = (Class *)realloc(seenClasses, seenClassesCount * sizeof(*seenClasses));
25 seenClasses[seenClassesCount - 1] = cls;
26 testassert(context == &dummy);
30 @interface C: TestRoot @end
33 testprintf("C initialize\n");
39 @interface D: TestRoot @end
42 testprintf("D initialize\n");
48 @interface E: TestRoot @end
51 testprintf("E initialize\n");
58 _objc_addWillInitializeClassFunc(willInitializeClass, &dummy);
60 // Merely getting a class should not trigger the callback.
62 size_t oldCount = seenClassesCount;
63 Class c = objc_getClass("C");
64 testassert(seenClassesCount == oldCount);
65 testassert(initializedC == 0);
67 // Sending a message to C should trigger the callback and the superclass's callback.
69 testassert(seenClassesCount == oldCount + 2);
70 testassert(seenClasses[seenClassesCount - 2] == [TestRoot class]);
71 testassert(seenClasses[seenClassesCount - 1] == [C class]);
73 // Sending a message to D should trigger the callback only for D, since the
74 // superclass is already initialized.
75 oldCount = seenClassesCount;
77 testassert(seenClassesCount == oldCount + 1);
78 testassert(seenClasses[seenClassesCount - 1] == [D class]);
80 // Registering a second callback should inform us of all three exactly once.
82 _objc_addWillInitializeClassFunc(willInitializeClass, &dummy);
83 testassert(seenClassesCount == 3);
88 for (size_t i = 0; i < seenClassesCount; i++) {
89 if (seenClasses[i] == [TestRoot class])
91 if (seenClasses[i] == [C class])
93 if (seenClasses[i] == [D class])
96 testassert(foundRoot == 1);
97 testassert(foundC == 1);
98 testassert(foundD == 1);
100 // Both callbacks should fire when sending a message to E.
103 testassert(initializedE);
104 testassert(seenClassesCount == 2);
105 testassert(seenClasses[0] == [E class]);
106 testassert(seenClasses[1] == [E class]);