123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109 |
- // TEST_CONFIG MEM=mrc
- #import "test.h"
- #import "testroot.i"
- #import <objc/objc-internal.h>
- #import <stdio.h>
- char dummy;
- Class *seenClasses;
- size_t seenClassesCount;
- static void clear(void) {
- free(seenClasses);
- seenClasses = NULL;
- seenClassesCount = 0;
- }
- static void willInitializeClass(void *context, Class cls) {
- testprintf("Will initialize %s\n", class_getName(cls));
- seenClassesCount++;
- seenClasses = (Class *)realloc(seenClasses, seenClassesCount * sizeof(*seenClasses));
- seenClasses[seenClassesCount - 1] = cls;
- testassert(context == &dummy);
- }
- int initializedC;
- @interface C: TestRoot @end
- @implementation C
- + (void)initialize {
- testprintf("C initialize\n");
- initializedC = 1;
- }
- @end
- int initializedD;
- @interface D: TestRoot @end
- @implementation D
- + (void)initialize {
- testprintf("D initialize\n");
- initializedD = 1;
- }
- @end
- int initializedE;
- @interface E: TestRoot @end
- @implementation E
- + (void)initialize {
- testprintf("E initialize\n");
- initializedE = 1;
- }
- @end
- int main()
- {
- _objc_addWillInitializeClassFunc(willInitializeClass, &dummy);
- // Merely getting a class should not trigger the callback.
- clear();
- size_t oldCount = seenClassesCount;
- Class c = objc_getClass("C");
- testassert(seenClassesCount == oldCount);
- testassert(initializedC == 0);
- // Sending a message to C should trigger the callback and the superclass's callback.
- [c class];
- testassert(seenClassesCount == oldCount + 2);
- testassert(seenClasses[seenClassesCount - 2] == [TestRoot class]);
- testassert(seenClasses[seenClassesCount - 1] == [C class]);
- // Sending a message to D should trigger the callback only for D, since the
- // superclass is already initialized.
- oldCount = seenClassesCount;
- [D class];
- testassert(seenClassesCount == oldCount + 1);
- testassert(seenClasses[seenClassesCount - 1] == [D class]);
- // Registering a second callback should inform us of all three exactly once.
- clear();
- _objc_addWillInitializeClassFunc(willInitializeClass, &dummy);
- testassert(seenClassesCount == 3);
- int foundRoot = 0;
- int foundC = 0;
- int foundD = 0;
- for (size_t i = 0; i < seenClassesCount; i++) {
- if (seenClasses[i] == [TestRoot class])
- foundRoot++;
- if (seenClasses[i] == [C class])
- foundC++;
- if (seenClasses[i] == [D class])
- foundD++;
- }
- testassert(foundRoot == 1);
- testassert(foundC == 1);
- testassert(foundD == 1);
-
- // Both callbacks should fire when sending a message to E.
- clear();
- [E class];
- testassert(initializedE);
- testassert(seenClassesCount == 2);
- testassert(seenClasses[0] == [E class]);
- testassert(seenClasses[1] == [E class]);
- succeed(__FILE__);
- }
|