OSDN Git Service

2011-01-08 Dominique d'Humieres <dominiq@lps.ens.fr>
[pf3gnuchains/gcc-fork.git] / gcc / testsuite / objc.dg / gnu-api-2-method.m
1 /* Test the Modern GNU Objective-C Runtime API.
2
3   This is test 'method', covering all functions starting with 'method'.  */
4
5 /* { dg-do run } */
6 /* { dg-skip-if "No API#2 pre-Darwin9" { *-*-darwin[5-8]* } { "-fnext-runtime" } { "" } } */
7 /* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
8
9 /* To get the modern GNU Objective-C Runtime API, you include
10    objc/runtime.h.  */
11 #include <objc/runtime.h>
12 #include <stdlib.h>
13 #include <stdio.h>
14 #include <string.h>
15
16 @interface MyRootClass
17 { Class isa; }
18 + alloc;
19 - init;
20 + initialize;
21 @end
22
23 @implementation MyRootClass
24 + alloc { return class_createInstance (self, 0); }
25 - init  { return self; }
26 + initialize { return self; }
27 @end
28
29 @protocol MyProtocol
30 - (id) variable;
31 @end
32
33 @protocol MySecondProtocol
34 - (id) setVariable: (id)value;
35 @end
36
37 @interface MySubClass : MyRootClass <MyProtocol>
38 { id variable_ivar; }
39 - (void) setVariable: (id)value;
40 - (id) variable;
41 - (id) constant;
42 @end
43
44 @implementation MySubClass
45 - (void) setVariable: (id)value { variable_ivar = value; }
46 - (id) variable { return variable_ivar; }
47 - (id) constant { return nil; }
48 @end
49
50
51 int main(int argc, void **args)
52 {
53   /* Functions are tested in alphabetical order.  */
54
55   printf ("Testing method_copyArgumentType () ...\n");
56   {
57     Method method = class_getInstanceMethod (objc_getClass ("MySubClass"),
58                                              @selector (setVariable:));
59     char *type = method_copyArgumentType (method, 2);
60
61     if (type == NULL  ||  type[0] != '@')
62       abort ();
63   }
64
65   printf ("Testing method_copyReturnType () ...\n");
66   {
67     Method method = class_getClassMethod (objc_getClass ("MyRootClass"),
68                                           @selector (alloc));
69     char *type = method_copyReturnType (method);
70
71     /* Check that it returns an object.  */
72     if (type == NULL  ||  type[0] != '@')
73       abort ();
74   }
75
76   printf ("Testing method_exchangeImplementations () ...\n");
77   {
78     Method method_a = class_getInstanceMethod (objc_getClass ("MySubClass"),
79                                                @selector (variable));
80     Method method_b = class_getInstanceMethod (objc_getClass ("MySubClass"),
81                                                @selector (constant));
82     MySubClass *object = [[MySubClass alloc] init];
83
84     /* Check that things work as expected before the swap.  */
85     [object setVariable: object];
86
87     if ([object variable] != object  ||  [object constant] != nil)
88       abort ();
89
90     /* Swap the methods.  */
91     method_exchangeImplementations (method_a, method_b);
92
93     /* Check that behaviour has changed.  */
94     if ([object variable] != nil  ||  [object constant] != object)
95       abort ();
96
97     /* Swap the methods again.  */
98     method_exchangeImplementations (method_a, method_b);
99     
100     /* Check that behaviour is back to normal.  */
101     if ([object variable] != object  ||  [object constant] != nil)
102       abort ();
103   }
104
105   printf ("Testing method_getArgumentType () ...\n");
106   {
107     Method method = class_getInstanceMethod (objc_getClass ("MyRootClass"),
108                                              @selector (init));
109     char type[16];
110     
111     method_getArgumentType (method, 1, type, 16);
112
113     /* Check the second argument (_cmd), which should be a SEL.  */
114     if (type[0] != ':')
115       abort ();
116   }
117
118   printf ("Testing method_getDescription () ...\n");
119   {
120     Method method = class_getInstanceMethod (objc_getClass ("MySubClass"),
121                                              @selector (variable));
122     struct objc_method_description *description = method_getDescription (method);
123
124     if (strcmp (sel_getName (description->name), "variable") != 0)
125       abort ();
126
127     if (method_getDescription (NULL) != NULL)
128       abort ();
129   }
130
131   printf ("Testing method_getImplementation () ...\n");
132   {
133     typedef void (*set_variable_function) (id receiver, SEL _cmd, id variable);
134     Method method = class_getInstanceMethod (objc_getClass ("MySubClass"),
135                                              @selector (setVariable:));
136     set_variable_function imp;
137     MySubClass *object = [[MySubClass alloc] init];
138
139     imp = (set_variable_function)(method_getImplementation (method));
140     
141     (*imp)(object, @selector (setVariable:), object);
142
143     if ([object variable] != object)
144       abort ();
145   }
146
147   printf ("Testing method_getName () ...\n");
148   {
149     Method method = class_getInstanceMethod (objc_getClass ("MySubClass"),
150                                              @selector (setVariable:));
151     if (strcmp (sel_getName (method_getName (method)), "setVariable:") != 0)
152       abort ();
153   }
154
155   printf ("Testing method_getNumberOfArguments () ...\n");
156   {
157     Method method = class_getInstanceMethod (objc_getClass ("MySubClass"),
158                                              @selector (setVariable:));
159     if (method_getNumberOfArguments (method) != 3)
160       abort ();
161
162     method = class_getInstanceMethod (objc_getClass ("MySubClass"),
163                                       @selector (variable));
164     if (method_getNumberOfArguments (method) != 2)
165       abort ();
166   }
167
168   printf ("Testing method_getTypeEncoding () ...\n");
169   {
170     Method method = class_getInstanceMethod (objc_getClass ("MySubClass"),
171                                              @selector (setVariable:));
172     const char *types = method_getTypeEncoding (method);
173
174     /* Check that method type string starts with 'v' (void)  */
175     if (types == NULL || types[0] != 'v')
176       abort ();    
177   }
178
179   printf ("Testing method_getReturnType () ...\n");
180   {
181     Method method = class_getInstanceMethod (objc_getClass ("MySubClass"),
182                                              @selector (setVariable:));
183     char type[16];
184     
185     method_getReturnType (method, type, 16);
186
187     if (type[0] != 'v')
188       abort ();
189
190     method_getReturnType (NULL, type, 16);
191
192     if (type[0] != 0)
193       abort ();
194   }
195
196   printf ("Testing method_setImplementation () ...\n");
197   {
198     Method method_a = class_getInstanceMethod (objc_getClass ("MySubClass"),
199                                                @selector (variable));
200     Method method_b = class_getInstanceMethod (objc_getClass ("MySubClass"),
201                                                @selector (constant));
202     IMP original_imp_a = method_getImplementation (method_a);
203     IMP original_imp_b = method_getImplementation (method_b);
204     MySubClass *object = [[MySubClass alloc] init];
205
206     /* Check that things work as expected before the swap.  */
207     [object setVariable: object];
208     
209     if ([object variable] != object  ||  [object constant] != nil)
210       abort ();
211     
212     /* Have 'variable' use the same implementation as 'constant'.  */
213     if (method_setImplementation (method_a, original_imp_b) != original_imp_a)
214       abort ();
215
216     /* Check that behaviour has changed.  */
217     if ([object variable] != nil  ||  [object constant] != nil)
218       abort ();
219
220     /* Put the original method back.  */
221     if (method_setImplementation (method_a, original_imp_a) != original_imp_b)
222       abort ();
223     
224     /* Check that behaviour is back to normal.  */
225     if ([object variable] != object  ||  [object constant] != nil)
226       abort ();
227   }
228
229   return 0;
230 }