PageRenderTime 106ms CodeModel.GetById 24ms app.highlight 77ms RepoModel.GetById 1ms app.codeStats 1ms

/core/externals/update-engine/externals/google-toolbox-for-mac/Foundation/GTMObjC2RuntimeTest.m

http://macfuse.googlecode.com/
Objective C | 445 lines | 292 code | 74 blank | 79 comment | 9 complexity | 30091c25119cec3818d3a293efba1a4a MD5 | raw file
  1//
  2//  GTMObjC2RuntimeTest.m
  3//
  4//  Copyright 2007-2008 Google Inc.
  5//
  6//  Licensed under the Apache License, Version 2.0 (the "License"); you may not
  7//  use this file except in compliance with the License.  You may obtain a copy
  8//  of the License at
  9//
 10//  http://www.apache.org/licenses/LICENSE-2.0
 11//
 12//  Unless required by applicable law or agreed to in writing, software
 13//  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 14//  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
 15//  License for the specific language governing permissions and limitations under
 16//  the License.
 17//
 18
 19#import "GTMObjC2Runtime.h"
 20#import "GTMSenTestCase.h"
 21#import "GTMSystemVersion.h"
 22#import "GTMTypeCasting.h"
 23
 24#import <string.h>
 25
 26@protocol GTMObjC2Runtime_TestProtocol
 27@end
 28
 29@protocol GTMObjC2Runtime_Test2Protocol
 30AT_OPTIONAL
 31- (NSString*)optional;
 32AT_REQUIRED
 33- (NSString*)required;
 34AT_OPTIONAL
 35+ (NSString*)class_optional;
 36AT_REQUIRED
 37+ (NSString*)class_required;
 38@end
 39
 40@interface GTMObjC2RuntimeTest : GTMTestCase {
 41  Class cls_;
 42}
 43@end
 44
 45@interface GTMObjC2Runtime_TestClass : NSObject <GTMObjC2Runtime_TestProtocol>
 46- (NSString*)kwyjibo;
 47
 48@end
 49
 50@interface GTMObjC2Runtime_TestClass (GMObjC2Runtime_TestClassCategory)
 51- (NSString*)eatMyShorts;
 52@end
 53
 54@implementation GTMObjC2Runtime_TestClass
 55
 56+ (NSString*)dontHaveACow {
 57  return @"dontHaveACow";
 58}
 59
 60- (NSString*)kwyjibo {
 61  return @"kwyjibo";
 62}
 63@end
 64
 65@implementation GTMObjC2Runtime_TestClass (GMObjC2Runtime_TestClassCategory)
 66- (NSString*)eatMyShorts {
 67  return @"eatMyShorts";
 68}
 69
 70+ (NSString*)brokeHisBrain {
 71  return @"brokeHisBrain";
 72}
 73
 74@end
 75
 76@interface GTMObjC2NotificationWatcher : NSObject
 77- (void)startedTest:(NSNotification *)notification;
 78@end
 79
 80@implementation GTMObjC2NotificationWatcher
 81- (id)init {
 82  if ((self = [super init])) {
 83    NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
 84    // We release ourselves when we are notified.
 85    [self retain];
 86    [nc addObserver:self
 87           selector:@selector(startedTest:)
 88               name:SenTestSuiteDidStartNotification
 89             object:nil];
 90
 91  }
 92  return self;
 93}
 94
 95- (void)startedTest:(NSNotification *)notification {
 96  // Logs if we are testing on Tiger or Leopard runtime.
 97  SenTestSuiteRun *suiteRun = GTM_STATIC_CAST(SenTestSuiteRun,
 98                                              [notification object]);
 99  NSString *testName = [[suiteRun test] name];
100  NSString *className = NSStringFromClass([GTMObjC2RuntimeTest class]);
101  if ([testName isEqualToString:className]) {
102    NSString *runtimeString;
103#ifndef OBJC2_UNAVAILABLE
104    runtimeString = @"ObjC1";
105#else
106    runtimeString = @"ObjC2";
107#endif
108    NSLog(@"Running GTMObjC2RuntimeTests using %@ runtime.", runtimeString);
109    NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
110    [nc removeObserver:self];
111    [self autorelease];
112  }
113}
114@end
115
116@implementation GTMObjC2RuntimeTest
117
118+ (void)initialize {
119  // This allows us to track which runtime we are actually testing.
120  [[[GTMObjC2NotificationWatcher alloc] init] autorelease];
121}
122
123- (void)setUp {
124  cls_ = [[GTMObjC2Runtime_TestClass class] retain];
125}
126
127- (void)tearDown {
128  [cls_ release];
129}
130
131- (void)test_object_getClass {
132  // Nil Checks
133  STAssertNil(object_getClass(nil), nil);
134
135  // Standard use check
136  GTMObjC2Runtime_TestClass *test = [[[cls_ alloc] init] autorelease];
137  Class cls = object_getClass(test);
138  STAssertEqualObjects(cls, cls_, nil);
139}
140
141- (void)test_class_getName {
142  // Nil Checks
143  const char *name = class_getName(nil);
144  STAssertEqualCStrings(name, "nil", nil);
145
146  // Standard use check
147  STAssertEqualCStrings(class_getName(cls_), "GTMObjC2Runtime_TestClass", nil);
148}
149
150- (void)test_class_conformsToProtocol {
151  // Nil Checks
152  STAssertFalse(class_conformsToProtocol(cls_, @protocol(NSObject)), nil);
153  STAssertFalse(class_conformsToProtocol(cls_, nil), nil);
154  // The following two tests intentionally commented out as they fail on
155  // Leopard with a crash, so we fail on Tiger intentionally as well.
156  // STAssertFalse(class_conformsToProtocol(nil, @protocol(NSObject)), nil);
157  // STAssertFalse(class_conformsToProtocol(nil, nil), nil);
158
159  // Standard use check
160  STAssertTrue(class_conformsToProtocol(cls_,
161                                        @protocol(GTMObjC2Runtime_TestProtocol)),
162               nil);
163}
164
165- (void)test_class_respondsToSelector {
166  // Nil Checks
167  STAssertFalse(class_respondsToSelector(cls_, @selector(setUp)), nil);
168  STAssertFalse(class_respondsToSelector(cls_, nil), nil);
169
170  // Standard use check
171  STAssertTrue(class_respondsToSelector(cls_, @selector(kwyjibo)), nil);
172}
173
174- (void)test_class_getSuperclass {
175  // Nil Checks
176  STAssertNil(class_getSuperclass(nil), nil);
177
178  // Standard use check
179  STAssertEqualObjects(class_getSuperclass(cls_), [NSObject class], nil);
180}
181
182- (void)test_class_copyMethodList {
183  // Nil Checks
184  Method *list = class_copyMethodList(nil, nil);
185  STAssertNULL(list, nil);
186
187  // Standard use check
188  list = class_copyMethodList(cls_, nil);
189  STAssertNotNULL(list, nil);
190  free(list);
191  unsigned int count = 0;
192  list = class_copyMethodList(cls_, &count);
193  STAssertNotNULL(list, nil);
194  STAssertEquals(count, 2U, nil);
195  STAssertNULL(list[count], nil);
196  free(list);
197
198  // Now test meta class
199  count = 0;
200  list = class_copyMethodList((Class)objc_getMetaClass(class_getName(cls_)),
201                              &count);
202  STAssertNotNULL(list, nil);
203  STAssertEquals(count, 2U, nil);
204  STAssertNULL(list[count], nil);
205  free(list);
206}
207
208- (void)test_method_getName {
209  // Nil Checks
210  STAssertNULL(method_getName(nil), nil);
211
212  // Standard use check
213  Method *list = class_copyMethodList(cls_, nil);
214  STAssertNotNULL(list, nil);
215  const char* selName1 = sel_getName(method_getName(list[0]));
216  const char* selName2 = sel_getName(@selector(kwyjibo));
217  const char* selName3 = sel_getName(@selector(eatMyShorts));
218  BOOL isGood = ((strcmp(selName1, selName2)) == 0 || (strcmp(selName1, selName3) == 0));
219  STAssertTrue(isGood, nil);
220  free(list);
221}
222
223- (void)test_method_exchangeImplementations {
224  // nil checks
225  method_exchangeImplementations(nil, nil);
226
227  // Standard use check
228  GTMObjC2Runtime_TestClass *test = [[GTMObjC2Runtime_TestClass alloc] init];
229  STAssertNotNil(test, nil);
230
231  // Get initial values
232  NSString *val1 = [test kwyjibo];
233  STAssertNotNil(val1, nil);
234  NSString *val2 = [test eatMyShorts];
235  STAssertNotNil(val2, nil);
236  NSString *val3 = [GTMObjC2Runtime_TestClass dontHaveACow];
237  STAssertNotNil(val3, nil);
238  NSString *val4 = [GTMObjC2Runtime_TestClass brokeHisBrain];
239  STAssertNotNil(val4, nil);
240
241  // exchange the imps
242  Method *list = class_copyMethodList(cls_, nil);
243  STAssertNotNULL(list, nil);
244  method_exchangeImplementations(list[0], list[1]);
245
246  // test against initial values
247  NSString *val5 = [test kwyjibo];
248  STAssertNotNil(val5, nil);
249  NSString *val6 = [test eatMyShorts];
250  STAssertNotNil(val6, nil);
251  STAssertEqualStrings(val1, val6, nil);
252  STAssertEqualStrings(val2, val5, nil);
253
254  // Check that other methods not affected
255  STAssertEqualStrings([GTMObjC2Runtime_TestClass dontHaveACow], val3, nil);
256  STAssertEqualStrings([GTMObjC2Runtime_TestClass brokeHisBrain], val4, nil);
257
258  // exchange the imps back
259  method_exchangeImplementations(list[0], list[1]);
260
261  // and test against initial values again
262  NSString *val7 = [test kwyjibo];
263  STAssertNotNil(val7, nil);
264  NSString *val8 = [test eatMyShorts];
265  STAssertNotNil(val8, nil);
266  STAssertEqualStrings(val1, val7, nil);
267  STAssertEqualStrings(val2, val8, nil);
268
269  method_exchangeImplementations(list[0], nil);
270  method_exchangeImplementations(nil, list[0]);
271
272  val7 = [test kwyjibo];
273  STAssertNotNil(val7, nil);
274  val8 = [test eatMyShorts];
275  STAssertNotNil(val8, nil);
276  STAssertEqualStrings(val1, val7, nil);
277  STAssertEqualStrings(val2, val8, nil);
278
279  free(list);
280  [test release];
281}
282
283- (void)test_method_getImplementation {
284  // Nil Checks
285  STAssertNULL(method_getImplementation(nil), nil);
286
287  // Standard use check
288  Method *list = class_copyMethodList(cls_, nil);
289  STAssertNotNULL(list, nil);
290  STAssertNotNULL(method_getImplementation(list[0]), nil);
291  free(list);
292}
293
294- (void)test_method_setImplementation {
295  // Standard use check
296  GTMObjC2Runtime_TestClass *test = [[GTMObjC2Runtime_TestClass alloc] init];
297  Method *list = class_copyMethodList(cls_, nil);
298
299  // Get initial value
300  NSString *str1 = objc_msgSend(test, method_getName(list[0]));
301  STAssertNotNil(str1, nil);
302
303  // set the imp to something else
304  IMP oldImp = method_setImplementation(list[0], method_getImplementation(list[1]));
305  STAssertNotNULL(oldImp, nil);
306
307  // make sure they are different
308  NSString *str2 = objc_msgSend(test,method_getName(list[0]));
309  STAssertNotNil(str2, nil);
310  STAssertNotEqualStrings(str1, str2, nil);
311
312  // reset the imp
313  IMP newImp = method_setImplementation(list[0], oldImp);
314  STAssertNotEquals(oldImp, newImp, nil);
315
316  // test nils
317  // Apparently it was a bug that we could call setImplementation with a nil
318  // so we now test to make sure that setting to nil works as expected on
319  // all systems.
320#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
321  // Built for less then leopard gives us the behaviors we defined...
322  // (doesn't take nil)
323  IMP nullImp = method_setImplementation(list[0], nil);
324  STAssertNULL(nullImp, nil);
325  IMP testImp = method_setImplementation(list[0], newImp);
326  STAssertEquals(testImp, oldImp, nil);
327#else
328  // Built for leopard or later means we get the os runtime behavior...
329  if ([GTMSystemVersion isLeopard]) {
330    // (takes nil)
331    oldImp = method_setImplementation(list[0], nil);
332    STAssertNotNULL(oldImp, nil);
333    newImp = method_setImplementation(list[0], oldImp);
334    STAssertNULL(newImp, nil);
335  } else {
336    // (doesn't take nil)
337    IMP nullImp = method_setImplementation(list[0], nil);
338    STAssertNULL(nullImp, nil);
339    IMP testImp = method_setImplementation(list[0], newImp);
340    STAssertEquals(testImp, oldImp, nil);
341  }
342#endif
343
344  // This case intentionally not tested. Passing nil to method_setImplementation
345  // on Leopard crashes. It does on Tiger as well. Half works on SnowLeopard.
346  // We made our Tiger implementation the same as the SnowLeopard
347  // implementation.
348  // Logged as radar 5572981.
349  if (![GTMSystemVersion isLeopardOrGreater]) {
350    STAssertNULL(method_setImplementation(nil, nil), nil);
351  }
352#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5
353  if ([GTMSystemVersion isSnowLeopardOrGreater]) {
354    STAssertNULL(method_setImplementation(nil, newImp), nil);
355  }
356#endif
357
358  [test release];
359  free(list);
360}
361
362- (void)test_protocol_getMethodDescription {
363  // Check nil cases
364  struct objc_method_description desc = protocol_getMethodDescription(nil, nil,
365                                                                      YES, YES);
366  STAssertNULL(desc.name, nil);
367  desc = protocol_getMethodDescription(nil, @selector(optional), YES, YES);
368  STAssertNULL(desc.name, nil);
369  desc = protocol_getMethodDescription(@protocol(GTMObjC2Runtime_Test2Protocol),
370                                       nil, YES, YES);
371  STAssertNULL(desc.name, nil);
372
373  // Instance Methods
374  // Check Required case. Only OBJC2 supports required.
375  desc = protocol_getMethodDescription(@protocol(GTMObjC2Runtime_Test2Protocol),
376                                       @selector(optional), YES, YES);
377#if OBJC_API_VERSION >= 2
378  STAssertNULL(desc.name, nil);
379#else
380  STAssertNotNULL(desc.name, nil);
381#endif
382
383  // Check Required case. Only OBJC2 supports required.
384  desc = protocol_getMethodDescription(@protocol(GTMObjC2Runtime_Test2Protocol),
385                                       @selector(required), YES, YES);
386
387  STAssertNotNULL(desc.name, nil);
388
389  // Check Optional case. Only OBJC2 supports optional.
390  desc = protocol_getMethodDescription(@protocol(GTMObjC2Runtime_Test2Protocol),
391                                       @selector(optional), NO, YES);
392
393  STAssertNotNULL(desc.name, nil);
394
395  // Check Optional case. Only OBJC2 supports optional.
396  desc = protocol_getMethodDescription(@protocol(GTMObjC2Runtime_Test2Protocol),
397                                       @selector(required), NO, YES);
398#if OBJC_API_VERSION >= 2
399  STAssertNULL(desc.name, nil);
400#else
401  STAssertNotNULL(desc.name, nil);
402#endif
403
404  // Class Methods
405  // Check Required case. Only OBJC2 supports required.
406  desc = protocol_getMethodDescription(@protocol(GTMObjC2Runtime_Test2Protocol),
407                                       @selector(class_optional), YES, NO);
408#if OBJC_API_VERSION >= 2
409  STAssertNULL(desc.name, nil);
410#else
411  STAssertNotNULL(desc.name, nil);
412#endif
413
414  // Check Required case. Only OBJC2 supports required.
415  desc = protocol_getMethodDescription(@protocol(GTMObjC2Runtime_Test2Protocol),
416                                       @selector(class_required), YES, NO);
417
418  STAssertNotNULL(desc.name, nil);
419
420  // Check Optional case. Only OBJC2 supports optional.
421  desc = protocol_getMethodDescription(@protocol(GTMObjC2Runtime_Test2Protocol),
422                                       @selector(class_optional), NO, NO);
423
424  STAssertNotNULL(desc.name, nil);
425
426  // Check Optional case. Only OBJC2 supports optional.
427  desc = protocol_getMethodDescription(@protocol(GTMObjC2Runtime_Test2Protocol),
428                                       @selector(class_required), NO, NO);
429#if OBJC_API_VERSION >= 2
430  STAssertNULL(desc.name, nil);
431#else
432  STAssertNotNULL(desc.name, nil);
433#endif
434
435}
436
437- (void)test_sel_isEqual {
438  STAssertTrue(sel_isEqual(@selector(kwyjibo), @selector(kwyjibo)), nil);
439  STAssertFalse(sel_isEqual(@selector(kwyjibo), @selector(dontHaveACow)), nil);
440  STAssertTrue(sel_isEqual(_cmd, @selector(test_sel_isEqual)), nil);
441  STAssertTrue(sel_isEqual(_cmd, _cmd), nil);
442  STAssertFalse(sel_isEqual(_cmd, @selector(kwyjibo)), nil);
443}
444
445@end