5 #include <malloc/malloc.h>
6 #include <objc/objc-runtime.h>
9 @interface SuperProps { id isa; int prop1; int prop2; }
13 @implementation SuperProps
18 @interface SubProps : SuperProps { int prop3; int prop4; }
22 @implementation SubProps
28 @interface FourProps { int prop1; int prop2; int prop3; int prop4; }
34 @implementation FourProps
42 @interface NoProps @end
43 @implementation NoProps @end
47 @property(readonly,class) int prop1;
48 @property(readonly,class) int prop2;
49 @property(readonly) int prop2;
50 @property(readonly) int prop3;
52 @implementation ClassProps
53 +(int)prop1 { return 0; }
54 +(int)prop2 { return 0; }
55 -(int)prop2 { return 0; }
56 -(int)prop3 { return 0; }
59 static int isNamed(objc_property_t p, const char *name)
61 return (0 == strcmp(name, property_getName(p)));
66 objc_property_t *props;
70 cls = objc_getClass("SubProps");
74 props = class_copyPropertyList(cls, &count);
76 testassert(count == 2);
77 testassert((isNamed(props[0], "prop3") && isNamed(props[1], "prop4")) ||
78 (isNamed(props[1], "prop3") && isNamed(props[0], "prop4")));
79 // props[] should be null-terminated
80 testassert(props[2] == NULL);
83 cls = objc_getClass("SuperProps");
87 props = class_copyPropertyList(cls, &count);
89 testassert(count == 2);
90 testassert((isNamed(props[0], "prop1") && isNamed(props[1], "prop2")) ||
91 (isNamed(props[1], "prop1") && isNamed(props[0], "prop2")));
92 // props[] should be null-terminated
93 testassert(props[2] == NULL);
96 // Check null-termination - this property list block would be 16 bytes
97 // if it weren't for the terminator
98 cls = objc_getClass("FourProps");
102 props = class_copyPropertyList(cls, &count);
104 testassert(count == 4);
105 testassert(malloc_size(props) >= 5 * sizeof(objc_property_t));
106 testassert(props[3] != NULL);
107 testassert(props[4] == NULL);
110 // Check NULL count parameter
111 props = class_copyPropertyList(cls, NULL);
113 testassert(props[4] == NULL);
114 testassert(props[3] != NULL);
117 // Check NULL class parameter
119 props = class_copyPropertyList(NULL, &count);
121 testassert(count == 0);
123 // Check NULL class and count
124 props = class_copyPropertyList(NULL, NULL);
127 // Check class with no properties
128 cls = objc_getClass("NoProps");
132 props = class_copyPropertyList(cls, &count);
134 testassert(count == 0);
136 // Check class properties
138 cls = objc_getClass("ClassProps");
142 props = class_copyPropertyList(cls, &count);
144 testassert(count == 2);
145 testassert((isNamed(props[0], "prop2") && isNamed(props[1], "prop3")) ||
146 (isNamed(props[1], "prop2") && isNamed(props[0], "prop3")));
147 // props[] should be null-terminated
148 testassert(props[2] == NULL);
151 cls = object_getClass(objc_getClass("ClassProps"));
155 props = class_copyPropertyList(cls, &count);
157 testassert(count == 2);
158 testassert((isNamed(props[0], "prop1") && isNamed(props[1], "prop2")) ||
159 (isNamed(props[1], "prop1") && isNamed(props[0], "prop2")));
160 // props[] should be null-terminated
161 testassert(props[2] == NULL);