duplicateClass.m 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. // TEST_CFLAGS -Wno-deprecated-declarations -Wl,-no_objc_category_merging
  2. #include "test.h"
  3. #include "testroot.i"
  4. #include <objc/runtime.h>
  5. static int state;
  6. @protocol Proto
  7. +(void)classMethod;
  8. -(void)instanceMethod;
  9. @end
  10. @interface Super : TestRoot <Proto> {
  11. int i;
  12. }
  13. @property int i;
  14. @end
  15. @implementation Super
  16. @synthesize i;
  17. +(void)classMethod {
  18. state = 1;
  19. }
  20. -(void)instanceMethod {
  21. state = 3;
  22. }
  23. @end
  24. #if __clang__
  25. #pragma clang diagnostic push
  26. #pragma clang diagnostic ignored "-Wobjc-protocol-method-implementation"
  27. #endif
  28. @implementation Super (Category)
  29. +(void)classMethod {
  30. state = 2;
  31. }
  32. -(void)instanceMethod {
  33. state = 4;
  34. }
  35. @end
  36. #if __clang__
  37. #pragma clang diagnostic pop
  38. #endif
  39. int main()
  40. {
  41. Class clone;
  42. Class cls;
  43. Method *m1, *m2;
  44. int i;
  45. cls = [Super class];
  46. clone = objc_duplicateClass(cls, "Super_copy", 0);
  47. testassert(clone != cls);
  48. testassert(object_getClass(clone) == object_getClass(cls));
  49. testassert(class_getSuperclass(clone) == class_getSuperclass(cls));
  50. testassert(class_getVersion(clone) == class_getVersion(cls));
  51. testassert(class_isMetaClass(clone) == class_isMetaClass(cls));
  52. testassert(class_getIvarLayout(clone) == class_getIvarLayout(cls));
  53. testassert(class_getWeakIvarLayout(clone) == class_getWeakIvarLayout(cls));
  54. // Check method list
  55. m1 = class_copyMethodList(cls, NULL);
  56. m2 = class_copyMethodList(clone, NULL);
  57. testassert(m1);
  58. testassert(m2);
  59. for (i = 0; m1[i] && m2[i]; i++) {
  60. testassert(m1[i] != m2[i]); // method list must be deep-copied
  61. testassert(method_getName(m1[i]) == method_getName(m2[i]));
  62. testassert(method_getImplementation(m1[i]) == method_getImplementation(m2[i]));
  63. testassert(method_getTypeEncoding(m1[i]) == method_getTypeEncoding(m2[i]));
  64. }
  65. testassert(m1[i] == NULL && m2[i] == NULL);
  66. free(m1);
  67. free(m2);
  68. // Check ivar list
  69. Ivar *i1 = class_copyIvarList(cls, NULL);
  70. Ivar *i2 = class_copyIvarList(clone, NULL);
  71. testassert(i1);
  72. testassert(i2);
  73. for (i = 0; i1[i] && i2[i]; i++) {
  74. testassert(i1[i] == i2[i]); // ivars are not deep-copied
  75. }
  76. testassert(i1[i] == NULL && i2[i] == NULL);
  77. free(i1);
  78. free(i2);
  79. // Check protocol list
  80. Protocol * __unsafe_unretained *p1 = class_copyProtocolList(cls, NULL);
  81. Protocol * __unsafe_unretained *p2 = class_copyProtocolList(clone, NULL);
  82. testassert(p1);
  83. testassert(p2);
  84. for (i = 0; p1[i] && p2[i]; i++) {
  85. testassert(p1[i] == p2[i]); // protocols are not deep-copied
  86. }
  87. testassert(p1[i] == NULL && p2[i] == NULL);
  88. free(p1);
  89. free(p2);
  90. // Check property list
  91. objc_property_t *o1 = class_copyPropertyList(cls, NULL);
  92. objc_property_t *o2 = class_copyPropertyList(clone, NULL);
  93. testassert(o1);
  94. testassert(o2);
  95. for (i = 0; o1[i] && o2[i]; i++) {
  96. testassert(o1[i] == o2[i]); // properties are not deep-copied
  97. }
  98. testassert(o1[i] == NULL && o2[i] == NULL);
  99. free(o1);
  100. free(o2);
  101. // Check method calls
  102. state = 0;
  103. [cls classMethod];
  104. testassert(state == 2);
  105. state = 0;
  106. [clone classMethod];
  107. testassert(state == 2);
  108. // #4511660 Make sure category implementation is still the preferred one
  109. id obj;
  110. obj = [cls new];
  111. state = 0;
  112. [obj instanceMethod];
  113. testassert(state == 4);
  114. RELEASE_VAR(obj);
  115. obj = [clone new];
  116. state = 0;
  117. [obj instanceMethod];
  118. testassert(state == 4);
  119. RELEASE_VAR(obj);
  120. succeed(__FILE__);
  121. }