]> git.saurik.com Git - apple/objc4.git/blob - test/category.m
objc4-756.2.tar.gz
[apple/objc4.git] / test / category.m
1 // TEST_CFLAGS -Wl,-no_objc_category_merging
2
3 #include "test.h"
4 #include "testroot.i"
5 #include <string.h>
6 #include <objc/runtime.h>
7
8 static int state = 0;
9
10 @interface Super : TestRoot @end
11 @implementation Super
12 -(void)instancemethod { fail("-instancemethod not overridden by category"); }
13 +(void)method { fail("+method not overridden by category"); }
14 @end
15
16 @interface Super (Category) @end
17 @implementation Super (Category)
18 +(void)method {
19 testprintf("in [Super(Category) method]\n");
20 testassert(self == [Super class]);
21 testassert(state == 0);
22 state = 1;
23 }
24 -(void)instancemethod {
25 testprintf("in [Super(Category) instancemethod]\n");
26 testassert(object_getClass(self) == [Super class]);
27 testassert(state == 1);
28 state = 2;
29 }
30 @end
31
32 @interface Super (PropertyCategory)
33 @property int i;
34 @property(class) int i;
35 @end
36 @implementation Super (PropertyCategory)
37 - (int)i { return 0; }
38 - (void)setI:(int)value { (void)value; }
39 + (int)i { return 0; }
40 + (void)setI:(int)value { (void)value; }
41 @end
42
43 // rdar://5086110 memory smasher in category with class method and property
44 @interface Super (r5086110)
45 @property int property5086110;
46 @end
47 @implementation Super (r5086110)
48 +(void)method5086110 {
49 fail("method method5086110 called!");
50 }
51 - (int)property5086110 { fail("property5086110 called!"); return 0; }
52 - (void)setProperty5086110:(int)value { fail("setProperty5086110 called!"); (void)value; }
53 @end
54
55 // rdar://25605427 incorrect handling of class properties in 10.11 and earlier
56 @interface Super25605427 : TestRoot
57 @property(class, readonly) int i;
58 @end
59 @implementation Super25605427
60 +(int)i { return 0; }
61 @end
62
63 @interface Super25605427 (r25605427a)
64 @property(readonly) int r25605427a1;
65 @end
66 @implementation Super25605427 (r25605427a)
67 -(int)r25605427a1 { return 0; }
68 +(int)r25605427a2 { return 0; }
69 @end
70
71 @interface Super25605427 (r25605427b)
72 @property(readonly) int r25605427b1;
73 @end
74 @implementation Super25605427 (r25605427b)
75 -(int)r25605427b1 { return 0; }
76 +(int)r25605427b2 { return 0; }
77 @end
78
79 @interface Super25605427 (r25605427c)
80 @property(readonly) int r25605427c1;
81 @end
82 @implementation Super25605427 (r25605427c)
83 -(int)r25605427c1 { return 0; }
84 +(int)r25605427c2 { return 0; }
85 @end
86
87 @interface Super25605427 (r25605427d)
88 @property(readonly) int r25605427d1;
89 @end
90 @implementation Super25605427 (r25605427d)
91 -(int)r25605427d1 { return 0; }
92 +(int)r25605427d2 { return 0; }
93 @end
94
95
96 @interface PropertyClass : Super {
97 int q;
98 }
99 @property(readonly) int q;
100 @end
101 @implementation PropertyClass
102 @synthesize q;
103 @end
104
105 @interface PropertyClass (PropertyCategory)
106 @property int q;
107 @end
108 @implementation PropertyClass (PropertyCategory)
109 @dynamic q;
110 @end
111
112
113 int main()
114 {
115 {
116 // rdar://25605427 bugs in 10.11 and earlier when metaclass
117 // has a property and category has metaclass additions.
118 // Memory smasher in buildPropertyList (caught by guard malloc)
119 Class cls = [Super25605427 class];
120 // Incorrect attachment of instance properties from category to metacls
121 testassert(class_getProperty(cls, "r25605427d1"));
122 testassert(! class_getProperty(object_getClass(cls), "r25605427d1"));
123 }
124
125 // methods introduced by category
126 state = 0;
127 [Super method];
128 [[Super new] instancemethod];
129 testassert(state == 2);
130
131 // property introduced by category
132 objc_property_t p = class_getProperty([Super class], "i");
133 testassert(p);
134 testassert(0 == strcmp(property_getName(p), "i"));
135 testassert(property_getAttributes(p));
136
137 objc_property_t p2 = class_getProperty(object_getClass([Super class]), "i");
138 testassert(p2);
139 testassert(p != p2);
140 testassert(0 == strcmp(property_getName(p2), "i"));
141 testassert(property_getAttributes(p2));
142
143 // methods introduced by category's property
144 Method m;
145 m = class_getInstanceMethod([Super class], @selector(i));
146 testassert(m);
147 m = class_getInstanceMethod([Super class], @selector(setI:));
148 testassert(m);
149
150 m = class_getClassMethod([Super class], @selector(i));
151 testassert(m);
152 m = class_getClassMethod([Super class], @selector(setI:));
153 testassert(m);
154
155 // class's property shadowed by category's property
156 objc_property_t *plist = class_copyPropertyList([PropertyClass class], NULL);
157 testassert(plist);
158 testassert(plist[0]);
159 testassert(0 == strcmp(property_getName(plist[0]), "q"));
160 testassert(0 == strcmp(property_getAttributes(plist[0]), "Ti,D"));
161 testassert(plist[1]);
162 testassert(0 == strcmp(property_getName(plist[1]), "q"));
163 testassert(0 == strcmp(property_getAttributes(plist[1]), "Ti,R,Vq"));
164 testassert(!plist[2]);
165 free(plist);
166
167 succeed(__FILE__);
168 }
169