]> git.saurik.com Git - apple/objc4.git/blob - test/methodListSmall.mm
objc4-818.2.tar.gz
[apple/objc4.git] / test / methodListSmall.mm
1 // TEST_CFLAGS -std=c++11
2
3 #include "methodListSmall.h"
4
5 void testClass(Class c) {
6 id foo = [c new];
7 [foo myMethod1];
8 testassert(ranMyMethod1);
9 [foo myMethod2];
10 testassert(ranMyMethod2);
11 [foo myMethod3];
12 testassert(ranMyMethod3);
13
14 Method m1 = class_getInstanceMethod(c, @selector(myMethod1));
15 testassert(m1);
16 testassert(method_getName(m1) == @selector(myMethod1));
17 testassert(strcmp(method_getTypeEncoding(m1), "v16@0:8") == 0);
18 testassert(method_getImplementation(m1) == (IMP)myMethod1);
19
20 method_setImplementation(m1, (IMP)myReplacedMethod1);
21 testassert(method_getImplementation(m1) == (IMP)myReplacedMethod1);
22 [foo myMethod1];
23 testassert(ranMyReplacedMethod1);
24
25 Method m2 = class_getInstanceMethod(c, @selector(myMethod2));
26 auto method_invoke_cast = (void (*)(id, Method))method_invoke;
27
28 ranMyMethod2 = 0;
29 method_invoke_cast(foo, m2);
30 testassert(ranMyMethod2);
31
32 method_setImplementation(m2, (IMP)myReplacedMethod2);
33 method_invoke_cast(foo, m2);
34 testassert(ranMyReplacedMethod2);
35
36 Method mstret = class_getInstanceMethod(c, @selector(myMethodStret));
37 #if __arm64__
38 // No _stret variant on ARM64. We'll test struct return through
39 // method_invoke anyway just to be thorough.
40 auto method_invoke_stret_cast = (BigStruct (*)(id, Method))method_invoke;
41 #else
42 auto method_invoke_stret_cast = (BigStruct (*)(id, Method))method_invoke_stret;
43 #endif
44
45 [foo myMethodStret];
46 testassert(ranMyMethodStret);
47
48 ranMyMethodStret = 0;
49 method_invoke_stret_cast(foo, mstret);
50 testassert(ranMyMethodStret);
51
52 method_setImplementation(mstret, (IMP)myReplacedMethodStret);
53 [foo myMethodStret];
54 testassert(ranMyReplacedMethodStret);
55
56 ranMyReplacedMethodStret = 0;
57 method_invoke_stret_cast(foo, mstret);
58 testassert(ranMyReplacedMethodStret);
59
60 auto *desc1 = method_getDescription(m1);
61 testassert(desc1->name == @selector(myMethod1));
62 testassert(desc1->types == method_getTypeEncoding(m1));
63
64 auto *desc2 = method_getDescription(m2);
65 testassert(desc2->name == @selector(myMethod2));
66 testassert(desc2->types == method_getTypeEncoding(m2));
67
68 auto *descstret = method_getDescription(mstret);
69 testassert(descstret->name == @selector(myMethodStret));
70 testassert(descstret->types == method_getTypeEncoding(mstret));
71
72 Method nullTypeMethod = class_getInstanceMethod(c, @selector(myMethodNullTypes));
73 testassert(nullTypeMethod);
74 testassert(method_getName(nullTypeMethod) == @selector(myMethodNullTypes));
75 testassertequal(method_getTypeEncoding(nullTypeMethod), NULL);
76 testassertequal(method_getImplementation(nullTypeMethod), (IMP)myMethod1);
77 }
78
79 int main() {
80 Class fooClass = (__bridge Class)&FooClass;
81
82 // Make sure this class can be duplicated and works as expected.
83 // Duplicate it before testClass mucks around with the methods.
84 // Need to realize fooClass before duplicating it, hence the
85 // class message.
86 Class dupedClass = objc_duplicateClass([fooClass class], "FooDup", 0);
87
88 testprintf("Testing class.\n");
89 testClass(fooClass);
90
91 testprintf("Testing duplicate class.\n");
92 testClass(dupedClass);
93
94 succeed(__FILE__);
95 }