protocol_copyPropertyList.m 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. // TEST_CFLAGS -framework Foundation
  2. // need Foundation to get NSObject compatibility additions for class Protocol
  3. // because ARC calls [protocol retain]
  4. /*
  5. TEST_BUILD_OUTPUT
  6. .*protocol_copyPropertyList.m:\d+:\d+: warning: null passed to a callee that requires a non-null argument \[-Wnonnull\]
  7. .*protocol_copyPropertyList.m:\d+:\d+: warning: null passed to a callee that requires a non-null argument \[-Wnonnull\]
  8. .*protocol_copyPropertyList.m:\d+:\d+: warning: null passed to a callee that requires a non-null argument \[-Wnonnull\]
  9. .*protocol_copyPropertyList.m:\d+:\d+: warning: null passed to a callee that requires a non-null argument \[-Wnonnull\]
  10. END
  11. */
  12. #include "test.h"
  13. #include <string.h>
  14. #include <malloc/malloc.h>
  15. #include <objc/runtime.h>
  16. @protocol SuperProps
  17. @property int prop1;
  18. @property int prop2;
  19. @property(class) int prop1;
  20. @property(class) int prop2;
  21. @end
  22. @protocol SubProps <SuperProps>
  23. @property int prop3;
  24. @property int prop4;
  25. @property(class) int prop3;
  26. @property(class) int prop4;
  27. @end
  28. @protocol FourProps
  29. @property int prop1;
  30. @property int prop2;
  31. @property int prop3;
  32. @property int prop4;
  33. @property(class) int prop1;
  34. @property(class) int prop2;
  35. @property(class) int prop3;
  36. @property(class) int prop4;
  37. @end
  38. @protocol NoProps @end
  39. @protocol OneProp
  40. @property int instanceProp;
  41. @property(class) int classProp;
  42. @end
  43. static int isNamed(objc_property_t p, const char *name)
  44. {
  45. return (0 == strcmp(name, property_getName(p)));
  46. }
  47. void testfn(objc_property_t *(*copyPropertyList_fn)(Protocol*, unsigned int *),
  48. const char *onePropName)
  49. {
  50. objc_property_t *props;
  51. unsigned int count;
  52. Protocol *proto;
  53. proto = @protocol(SubProps);
  54. testassert(proto);
  55. count = 100;
  56. props = copyPropertyList_fn(proto, &count);
  57. testassert(props);
  58. testassert(count == 2);
  59. testassert((isNamed(props[0], "prop4") && isNamed(props[1], "prop3")) ||
  60. (isNamed(props[0], "prop3") && isNamed(props[1], "prop4")));
  61. // props[] should be null-terminated
  62. testassert(props[2] == NULL);
  63. free(props);
  64. proto = @protocol(SuperProps);
  65. testassert(proto);
  66. count = 100;
  67. props = copyPropertyList_fn(proto, &count);
  68. testassert(props);
  69. testassert(count == 2);
  70. testassert((isNamed(props[0], "prop1") && isNamed(props[1], "prop2")) ||
  71. (isNamed(props[0], "prop2") && isNamed(props[1], "prop1")));
  72. // props[] should be null-terminated
  73. testassert(props[2] == NULL);
  74. free(props);
  75. // Check null-termination - this property list block would be 16 bytes
  76. // if it weren't for the terminator
  77. proto = @protocol(FourProps);
  78. testassert(proto);
  79. count = 100;
  80. props = copyPropertyList_fn(proto, &count);
  81. testassert(props);
  82. testassert(count == 4);
  83. testassert(malloc_size(props) >= 5 * sizeof(objc_property_t));
  84. testassert(props[3] != NULL);
  85. testassert(props[4] == NULL);
  86. free(props);
  87. // Check NULL count parameter
  88. props = copyPropertyList_fn(proto, NULL);
  89. testassert(props);
  90. testassert(props[4] == NULL);
  91. testassert(props[3] != NULL);
  92. free(props);
  93. // Check NULL protocol parameter
  94. count = 100;
  95. props = copyPropertyList_fn(NULL, &count);
  96. testassert(!props);
  97. testassert(count == 0);
  98. // Check NULL protocol and count
  99. props = copyPropertyList_fn(NULL, NULL);
  100. testassert(!props);
  101. // Check protocol with no properties
  102. proto = @protocol(NoProps);
  103. testassert(proto);
  104. count = 100;
  105. props = copyPropertyList_fn(proto, &count);
  106. testassert(!props);
  107. testassert(count == 0);
  108. // Check instance vs class properties
  109. proto = @protocol(OneProp);
  110. testassert(proto);
  111. count = 100;
  112. props = copyPropertyList_fn(proto, &count);
  113. testassert(props);
  114. testassert(count == 1);
  115. testassert(0 == strcmp(property_getName(props[0]), onePropName));
  116. free(props);
  117. }
  118. objc_property_t *protocol_copyPropertyList2_YES_YES(Protocol *proto, unsigned int *outCount)
  119. {
  120. return protocol_copyPropertyList2(proto, outCount, YES, YES);
  121. }
  122. objc_property_t *protocol_copyPropertyList2_YES_NO(Protocol *proto, unsigned int *outCount)
  123. {
  124. return protocol_copyPropertyList2(proto, outCount, YES, NO);
  125. }
  126. int main()
  127. {
  128. // protocol_copyPropertyList(...) is identical to
  129. // protocol_copyPropertyList2(..., YES, YES)
  130. testfn(protocol_copyPropertyList, "instanceProp");
  131. testfn(protocol_copyPropertyList2_YES_YES, "instanceProp");
  132. // protocol_copyPropertyList2(..., YES, NO) is also identical
  133. // with the protocol definitions above, except for protocol OneProp.
  134. testfn(protocol_copyPropertyList2_YES_NO, "classProp");
  135. // Check non-functionality of optional properties
  136. unsigned int count;
  137. objc_property_t *props;
  138. count = 100;
  139. props = protocol_copyPropertyList2(@protocol(FourProps), &count, NO, YES);
  140. testassert(!props);
  141. testassert(count == 0);
  142. count = 100;
  143. props = protocol_copyPropertyList2(@protocol(FourProps), &count, NO, NO);
  144. testassert(!props);
  145. testassert(count == 0);
  146. // Check nil count parameter
  147. props = protocol_copyPropertyList2(@protocol(FourProps), nil, NO, YES);
  148. testassert(!props);
  149. props = protocol_copyPropertyList2(@protocol(FourProps), nil, NO, NO);
  150. testassert(!props);
  151. // Check nil protocol parameter
  152. count = 100;
  153. props = protocol_copyPropertyList2(nil, &count, NO, YES);
  154. testassert(!props);
  155. testassert(count == 0);
  156. count = 100;
  157. props = protocol_copyPropertyList2(nil, &count, NO, NO);
  158. testassert(!props);
  159. testassert(count == 0);
  160. // Check nil protocol and count
  161. props = protocol_copyPropertyList2(nil, nil, NO, YES);
  162. testassert(!props);
  163. props = protocol_copyPropertyList2(nil, nil, NO, NO);
  164. testassert(!props);
  165. succeed(__FILE__);
  166. return 0;
  167. }