1// TEST_CONFIG 2 3#include "test.h" 4#include <string.h> 5#include <malloc/malloc.h> 6#include <objc/objc-runtime.h> 7 8OBJC_ROOT_CLASS 9@interface SuperProps { id isa; int prop1; int prop2; } 10@property int prop1; 11@property int prop2; 12@end 13@implementation SuperProps 14@synthesize prop1; 15@synthesize prop2; 16@end 17 18@interface SubProps : SuperProps { int prop3; int prop4; } 19@property int prop3; 20@property int prop4; 21@end 22@implementation SubProps 23@synthesize prop3; 24@synthesize prop4; 25@end 26 27OBJC_ROOT_CLASS 28@interface FourProps { int prop1; int prop2; int prop3; int prop4; } 29@property int prop1; 30@property int prop2; 31@property int prop3; 32@property int prop4; 33@end 34@implementation FourProps 35@synthesize prop1; 36@synthesize prop2; 37@synthesize prop3; 38@synthesize prop4; 39@end 40 41OBJC_ROOT_CLASS 42@interface NoProps @end 43@implementation NoProps @end 44 45static int isNamed(objc_property_t p, const char *name) 46{ 47 return (0 == strcmp(name, property_getName(p))); 48} 49 50int main() 51{ 52 objc_property_t *props; 53 unsigned int count; 54 Class cls; 55 56 cls = objc_getClass("SubProps"); 57 testassert(cls); 58 59 count = 100; 60 props = class_copyPropertyList(cls, &count); 61 testassert(props); 62 testassert(count == 2); 63 testassert((isNamed(props[0], "prop3") && isNamed(props[1], "prop4")) || 64 (isNamed(props[1], "prop3") && isNamed(props[0], "prop4"))); 65 // props[] should be null-terminated 66 testassert(props[2] == NULL); 67 free(props); 68 69 cls = objc_getClass("SuperProps"); 70 testassert(cls); 71 72 count = 100; 73 props = class_copyPropertyList(cls, &count); 74 testassert(props); 75 testassert(count == 2); 76 testassert((isNamed(props[0], "prop1") && isNamed(props[1], "prop2")) || 77 (isNamed(props[1], "prop1") && isNamed(props[0], "prop2"))); 78 // props[] should be null-terminated 79 testassert(props[2] == NULL); 80 free(props); 81 82 // Check null-termination - this property list block would be 16 bytes 83 // if it weren't for the terminator 84 cls = objc_getClass("FourProps"); 85 testassert(cls); 86 87 count = 100; 88 props = class_copyPropertyList(cls, &count); 89 testassert(props); 90 testassert(count == 4); 91 testassert(malloc_size(props) >= 5 * sizeof(objc_property_t)); 92 testassert(props[3] != NULL); 93 testassert(props[4] == NULL); 94 free(props); 95 96 // Check NULL count parameter 97 props = class_copyPropertyList(cls, NULL); 98 testassert(props); 99 testassert(props[4] == NULL); 100 testassert(props[3] != NULL); 101 free(props); 102 103 // Check NULL class parameter 104 count = 100; 105 props = class_copyPropertyList(NULL, &count); 106 testassert(!props); 107 testassert(count == 0); 108 109 // Check NULL class and count 110 props = class_copyPropertyList(NULL, NULL); 111 testassert(!props); 112 113 // Check class with no properties 114 cls = objc_getClass("NoProps"); 115 testassert(cls); 116 117 count = 100; 118 props = class_copyPropertyList(cls, &count); 119 testassert(!props); 120 testassert(count == 0); 121 122 succeed(__FILE__); 123 return 0; 124} 125