OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [gcc/] [testsuite/] [objc.dg/] [gnu-api-2-resolve-method.m] - Blame information for rev 704

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 704 jeremybenn
/* Test the Modern GNU Objective-C Runtime API.
2
 
3
   This is test 'resolve-method', covering +resolveClassMethod: and
4
   +resolveInstanceMethod:.  */
5
 
6
/* { dg-do run } */
7
/* { dg-skip-if "" { *-*-* } { "-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
 
13
/* For __objc_msg_forward2.  */
14
#include <objc/message.h>
15
 
16
#include <stdlib.h>
17
#include <stdio.h>
18
#include <string.h>
19
 
20
@interface MyRootClass
21
{ Class isa; }
22
+ alloc;
23
- init;
24
@end
25
 
26
@implementation MyRootClass
27
+ alloc { return class_createInstance (self, 0); }
28
- init  { return self; }
29
@end
30
 
31
 
32
/* A number of tests will try invoking methods that don't exist.  We
33
   want to record the fact, but not abort the program, so we supply
34
   our own fowarding implementation which will invoke the following
35
   function for any method that is not found.  */
36
 
37
/* Keep track of how many times a non-existing method was executed.  */
38
static int nonExistingMethodCount = 0;
39
 
40
/* Inspired by nil_method in libobjc.  */
41
id nonExisting_method (id receiver __attribute__ ((__unused__)),
42
                       SEL sel __attribute__ ((__unused__)))
43
{
44
  nonExistingMethodCount++;
45
  return nil;
46
}
47
 
48
/* Keep track of how many times the forwarding lookup was invoked.  */
49
static int forwardingCount = 0;
50
 
51
/* We install this forwarding hook to cause all failed method lookups
52
   to call our 'nonExisting_method' function.  */
53
IMP forward_everything_to_non_existing_method (id receiver __attribute__ ((__unused__)),
54
                                               SEL sel __attribute__ ((__unused__)))
55
{
56
  forwardingCount++;
57
  return (IMP)nonExisting_method;
58
}
59
 
60
 
61
/* 'CountClass' is used to test that +resolveClassMethod: and
62
   +resolveInstanceMethod: are called when expected.  They do nothing
63
   other than recording that they are called.  */
64
@interface CountClass : MyRootClass
65
+ (BOOL) resolveClassMethod: (SEL)selector;
66
+ (BOOL) resolveInstanceMethod: (SEL)selector;
67
+ (void) existingClassMethod;
68
- (void) existingInstanceMethod;
69
@end
70
 
71
/* Count how many times the methods are called for class
72
   'CountClass'.  */
73
static int resolveClassMethodCount = 0;
74
static int resolveInstanceMethodCount = 0;
75
 
76
@implementation CountClass : MyRootClass
77
+ (BOOL) resolveClassMethod: (SEL)selector
78
{
79
  resolveClassMethodCount++;
80
  return NO;
81
}
82
+ (BOOL) resolveInstanceMethod: (SEL)selector
83
{
84
  resolveInstanceMethodCount++;
85
  return NO;
86
}
87
+ (void) existingClassMethod
88
{
89
  return;
90
}
91
- (void) existingInstanceMethod
92
{
93
  return;
94
}
95
@end
96
 
97
@protocol NonExistingStuff
98
+ (void) nonExistingClassMethod;
99
- (void) nonExistingInstanceMethod;
100
@end
101
 
102
/* Declare a category with some non existing methods, but don't
103
   actually implement them.  */
104
@interface CountClass (NonExistingStuff) <NonExistingStuff>
105
@end
106
 
107
 
108
/* 'SelfExtendingClass' is used to test that +resolveClassMethod: and
109
   +resolveInstanceMethod: can extend the class.  Any time they are
110
   called, they install the requested method, mapping it to the same
111
   implementation as 'countHits'.  */
112
@interface SelfExtendingClass : MyRootClass
113
+ (int) countHits;
114
+ (BOOL) resolveClassMethod: (SEL)selector;
115
+ (BOOL) resolveInstanceMethod: (SEL)selector;
116
@end
117
 
118
/* How many times the countHits method (or a clone) was called.  */
119
static int hitCount = 0;
120
 
121
@implementation SelfExtendingClass : MyRootClass
122
+ (int) countHits
123
{
124
  hitCount++;
125
  return hitCount;
126
}
127
+ (BOOL) resolveClassMethod: (SEL)selector
128
{
129
  /* Duplicate the 'countHits' method into the new method.  */
130
  Method method = class_getClassMethod (self, @selector (countHits));
131
  class_addMethod (object_getClass (self), selector,
132
                   method_getImplementation (method),
133
                   method_getTypeEncoding (method));
134
  resolveClassMethodCount++;
135
  return YES;
136
}
137
+ (BOOL) resolveInstanceMethod: (SEL)selector
138
{
139
  /* Duplicate the 'countHits' method into the new method.  */
140
  Method method = class_getClassMethod (self, @selector (countHits));
141
  class_addMethod (self, selector,
142
                   method_getImplementation (method),
143
                   method_getTypeEncoding (method));
144
  resolveInstanceMethodCount++;
145
  return YES;
146
 
147
}
148
@end
149
 
150
@protocol NonExistingStuff2
151
+ (int) nonExistingCountHitsMethod;
152
- (int) nonExistingCountHitsMethod;
153
 
154
+ (int) nonExistingCountHitsMethod2;
155
- (int) nonExistingCountHitsMethod2;
156
 
157
+ (int) nonExistingCountHitsMethod3;
158
- (int) nonExistingCountHitsMethod3;
159
@end
160
 
161
/* Declare a category with some non existing methods, but don't
162
   actually implement them.  */
163
@interface SelfExtendingClass (NonExistingStuff) <NonExistingStuff2>
164
@end
165
 
166
 
167
int main (int argc, void **args)
168
{
169
  /* Functions are tested in alphabetical order.  */
170
 
171
  /* Install our test forwarding hook.  */
172
  __objc_msg_forward2 = forward_everything_to_non_existing_method;
173
 
174
  printf ("Testing [+resolveClassMethod:]...\n");
175
  {
176
    Method m;
177
    IMP i;
178
 
179
    /** CountClass tests.  **/
180
 
181
    /* Call an existing method.  No +resolveClassMethod and no
182
       forwarding should be triggered.  */
183
    [CountClass existingClassMethod];
184
 
185
    if (resolveClassMethodCount != 0)
186
      abort ();
187
 
188
    if (forwardingCount != 0)
189
      abort ();
190
 
191
    if (nonExistingMethodCount != 0)
192
      abort ();
193
 
194
    /* Call a non-existing method.  Both +resolveClassMethod and the
195
       forwarding should be triggered.  */
196
    [CountClass nonExistingClassMethod];
197
 
198
    if (resolveClassMethodCount != 1)
199
      abort ();
200
 
201
    if (forwardingCount != 1)
202
      abort ();
203
 
204
    if (nonExistingMethodCount != 1)
205
      abort ();
206
 
207
    /* Now try the same tests with class_getClassMethod(), which
208
       should trigger the resolve methods too, but not the
209
       forwarding.  */
210
    m = class_getClassMethod (objc_getClass ("CountClass"),
211
                              @selector (existingClassMethod));
212
    if (resolveClassMethodCount != 1)
213
      abort ();
214
 
215
    if (forwardingCount != 1)
216
      abort ();
217
 
218
    if (nonExistingMethodCount != 1)
219
      abort ();
220
 
221
    m = class_getClassMethod (objc_getClass ("CountClass"),
222
                              @selector (nonExistingClassMethod));
223
    if (resolveClassMethodCount != 2)
224
      abort ();
225
 
226
    if (forwardingCount != 1)
227
      abort ();
228
 
229
    if (nonExistingMethodCount != 1)
230
      abort ();
231
 
232
    /* Now try the same tests with class_getMethodImplementation(),
233
       which should trigger the resolve methods and the forwarding
234
       (but not execute the forwarding, obviously).  */
235
    i = class_getMethodImplementation (object_getClass (objc_getClass ("CountClass")),
236
                                       @selector (existingClassMethod));
237
    if (resolveClassMethodCount != 2)
238
      abort ();
239
 
240
    if (forwardingCount != 1)
241
      abort ();
242
 
243
    if (nonExistingMethodCount != 1)
244
      abort ();
245
 
246
    i = class_getMethodImplementation (object_getClass (objc_getClass ("CountClass")),
247
                                       @selector (nonExistingClassMethod));
248
    if (resolveClassMethodCount != 3)
249
      abort ();
250
 
251
    if (forwardingCount != 2)
252
      abort ();
253
 
254
    if (nonExistingMethodCount != 1)
255
      abort ();
256
 
257
 
258
    /* Reset the counters for the next test.  */
259
    resolveClassMethodCount = 0;
260
    forwardingCount = 0;
261
    nonExistingMethodCount = 0;
262
 
263
 
264
    /** SelfExtendingClass tests.  **/
265
 
266
    /* Try the direct countHits method first.  No resolving or
267
       forwarding should be triggered.  */
268
    if ([SelfExtendingClass countHits] != 1)
269
      abort ();
270
 
271
    if (resolveClassMethodCount != 0)
272
      abort ();
273
 
274
    if (forwardingCount != 0)
275
      abort ();
276
 
277
    if (nonExistingMethodCount != 0)
278
      abort ();
279
 
280
    /* Now, try calling a non-existing count method; it should be
281
       installed and invoked.  */
282
    if ([SelfExtendingClass nonExistingCountHitsMethod] != 2)
283
      abort ();
284
 
285
    if (resolveClassMethodCount != 1)
286
      abort ();
287
 
288
    if (forwardingCount != 0)
289
      abort ();
290
 
291
    if (nonExistingMethodCount != 0)
292
      abort ();
293
 
294
    /* Try it again.  The method has now been installed, so it should
295
       be used and work, but with no additional resolving
296
       involved.  */
297
    if ([SelfExtendingClass nonExistingCountHitsMethod] != 3)
298
      abort ();
299
 
300
    if (resolveClassMethodCount != 1)
301
      abort ();
302
 
303
    if (forwardingCount != 0)
304
      abort ();
305
 
306
    if (nonExistingMethodCount != 0)
307
      abort ();
308
 
309
 
310
    /* Now try the same tests with class_getClassMethod().  */
311
    m = class_getClassMethod (objc_getClass ("SelfExtendingClass"),
312
                              @selector (nonExistingCountHitsMethod2));
313
    if (resolveClassMethodCount != 2)
314
      abort ();
315
 
316
    if (forwardingCount != 0)
317
      abort ();
318
 
319
    if (nonExistingMethodCount != 0)
320
      abort ();
321
 
322
    /* Try it again.  The method has now been installed, so it should
323
       be used and work, but with no additional resolving
324
       involved.  */
325
    if ([SelfExtendingClass nonExistingCountHitsMethod2] != 4)
326
      abort ();
327
 
328
    if (resolveClassMethodCount != 2)
329
      abort ();
330
 
331
    if (forwardingCount != 0)
332
      abort ();
333
 
334
    if (nonExistingMethodCount != 0)
335
      abort ();
336
 
337
 
338
    /* Now try the same tests with class_getMethodImplementation().  */
339
    i = class_getMethodImplementation (object_getClass (objc_getClass ("SelfExtendingClass")),
340
                                       @selector (nonExistingCountHitsMethod3));
341
    if (resolveClassMethodCount != 3)
342
      abort ();
343
 
344
    if (forwardingCount != 0)
345
      abort ();
346
 
347
    if (nonExistingMethodCount != 0)
348
      abort ();
349
 
350
    /* Try it again.  The method has now been installed, so it should
351
       be used and work, but with no additional resolving
352
       involved.  */
353
    if ([SelfExtendingClass nonExistingCountHitsMethod3] != 5)
354
      abort ();
355
 
356
    if (resolveClassMethodCount != 3)
357
      abort ();
358
 
359
    if (forwardingCount != 0)
360
      abort ();
361
 
362
    if (nonExistingMethodCount != 0)
363
      abort ();
364
  }
365
 
366
  /* Reset the counters for the next test.  */
367
  nonExistingMethodCount = 0;
368
  forwardingCount = 0;
369
  hitCount = 0;
370
 
371
  printf ("Testing [+resolveInstanceMethod:]...\n");
372
  {
373
    Method m;
374
    IMP i;
375
    CountClass *object = [[CountClass alloc] init];
376
    SelfExtendingClass *object2 = [[SelfExtendingClass alloc] init];
377
 
378
    /** CountClass tests.  **/
379
 
380
    /* Call an existing method.  No +resolveInstanceMethod and no
381
       forwarding should be triggered.  */
382
    [object existingInstanceMethod];
383
 
384
    if (resolveInstanceMethodCount != 0)
385
      abort ();
386
 
387
    if (forwardingCount != 0)
388
      abort ();
389
 
390
    if (nonExistingMethodCount != 0)
391
      abort ();
392
 
393
    /* Call a non-existing method.  Both +resolveInstanceMethod and the
394
       forwarding should be triggered.  */
395
    [object nonExistingInstanceMethod];
396
 
397
    if (resolveInstanceMethodCount != 1)
398
      abort ();
399
 
400
    if (forwardingCount != 1)
401
      abort ();
402
 
403
    if (nonExistingMethodCount != 1)
404
      abort ();
405
 
406
    /* Now try the same tests with class_getInstanceMethod(), which
407
       should trigger the resolve methods too, but not the
408
       forwarding.  */
409
    m = class_getInstanceMethod (objc_getClass ("CountClass"),
410
                                 @selector (existingInstanceMethod));
411
 
412
    if (resolveInstanceMethodCount != 1)
413
      abort ();
414
 
415
    if (forwardingCount != 1)
416
      abort ();
417
 
418
    if (nonExistingMethodCount != 1)
419
      abort ();
420
 
421
    m = class_getInstanceMethod (objc_getClass ("CountClass"),
422
                                 @selector (nonExistingInstanceMethod));
423
 
424
    if (resolveInstanceMethodCount != 2)
425
      abort ();
426
 
427
    if (forwardingCount != 1)
428
      abort ();
429
 
430
    if (nonExistingMethodCount != 1)
431
      abort ();
432
 
433
    /* Now try the same tests with class_getMethodImplementation(),
434
       which should trigger the resolve methods and the
435
       forwarding.  */
436
    i = class_getMethodImplementation (objc_getClass ("CountClass"),
437
                                       @selector (existingInstanceMethod));
438
    if (resolveInstanceMethodCount != 2)
439
      abort ();
440
 
441
    if (forwardingCount != 1)
442
      abort ();
443
 
444
    if (nonExistingMethodCount != 1)
445
      abort ();
446
 
447
    i = class_getMethodImplementation (objc_getClass ("CountClass"),
448
                                       @selector (nonExistingInstanceMethod));
449
    if (resolveInstanceMethodCount != 3)
450
      abort ();
451
 
452
    if (forwardingCount != 2)
453
      abort ();
454
 
455
    if (nonExistingMethodCount != 1)
456
      abort ();
457
 
458
    /* Reset the counters for the next test.  */
459
    resolveInstanceMethodCount = 0;
460
    forwardingCount = 0;
461
    nonExistingMethodCount = 0;
462
 
463
 
464
    /** SelfExtendingClass tests.  **/
465
 
466
    /* Try the direct countHits method first.  No resolving or
467
       forwarding should be triggered.  */
468
    if ([SelfExtendingClass countHits] != 1)
469
      abort ();
470
 
471
    if (resolveInstanceMethodCount != 0)
472
      abort ();
473
 
474
    if (forwardingCount != 0)
475
      abort ();
476
 
477
    if (nonExistingMethodCount != 0)
478
      abort ();
479
 
480
    /* Now, try calling a non-existing count method; it should be
481
       installed and invoked.  */
482
    if ([object2 nonExistingCountHitsMethod] != 2)
483
      abort ();
484
 
485
    if (resolveInstanceMethodCount != 1)
486
      abort ();
487
 
488
    if (forwardingCount != 0)
489
      abort ();
490
 
491
    if (nonExistingMethodCount != 0)
492
      abort ();
493
 
494
    /* Try it again.  The method has now been installed, so it should
495
       be used and work, but with no additional resolving
496
       involved.  */
497
    if ([object2 nonExistingCountHitsMethod] != 3)
498
      abort ();
499
 
500
    if (resolveInstanceMethodCount != 1)
501
      abort ();
502
 
503
    if (forwardingCount != 0)
504
      abort ();
505
 
506
    if (nonExistingMethodCount != 0)
507
      abort ();
508
 
509
    /* Now try the same tests with class_getInstanceMethod().  */
510
    m = class_getInstanceMethod (objc_getClass ("SelfExtendingClass"),
511
                                 @selector (nonExistingCountHitsMethod2));
512
    if (resolveInstanceMethodCount != 2)
513
      abort ();
514
 
515
    if (forwardingCount != 0)
516
      abort ();
517
 
518
    if (nonExistingMethodCount != 0)
519
      abort ();
520
 
521
    /* Try it again.  The method has now been installed, so it should
522
       be used and work, but with no additional resolving
523
       involved.  */
524
    if ([object2 nonExistingCountHitsMethod2] != 4)
525
      abort ();
526
 
527
    if (resolveInstanceMethodCount != 2)
528
      abort ();
529
 
530
    if (forwardingCount != 0)
531
      abort ();
532
 
533
    if (nonExistingMethodCount != 0)
534
      abort ();
535
 
536
 
537
    /* Now try the same tests with class_getMethodImplementation().  */
538
    i = class_getMethodImplementation (objc_getClass ("SelfExtendingClass"),
539
                                       @selector (nonExistingCountHitsMethod3));
540
    if (resolveInstanceMethodCount != 3)
541
      abort ();
542
 
543
    if (forwardingCount != 0)
544
      abort ();
545
 
546
    if (nonExistingMethodCount != 0)
547
      abort ();
548
 
549
    /* Try it again.  The method has now been installed, so it should
550
       be used and work, but with no additional resolving
551
       involved.  */
552
    if ([object2 nonExistingCountHitsMethod3] != 5)
553
      abort ();
554
 
555
    if (resolveInstanceMethodCount != 3)
556
      abort ();
557
 
558
    if (forwardingCount != 0)
559
      abort ();
560
 
561
    if (nonExistingMethodCount != 0)
562
      abort ();
563
  }
564
 
565
 
566
  return 0;
567
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.