]> git.wincent.com - WOTest.git/blob - Tests/NSObjectTests.m
Code clean-up for garbage collection
[WOTest.git] / Tests / NSObjectTests.m
1 //
2 //  NSObjectTests.m
3 //  WOTest
4 //
5 //  Created by Wincent Colaiuta on 10 February 2006.
6 //
7 //  Copyright 2006-2007 Wincent Colaiuta.
8 //  This program is free software: you can redistribute it and/or modify
9 //  it under the terms of the GNU General Public License as published by
10 //  the Free Software Foundation, either version 3 of the License, or
11 //  (at your option) any later version.
12 //
13 //  This program is distributed in the hope that it will be useful,
14 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
15 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 //  GNU General Public License for more details.
17 //
18 //  You should have received a copy of the GNU General Public License
19 //  along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 //
21
22 // class header
23 #import "NSObjectTests.h"
24
25 // framework headers
26 #import "WOLightweightRoot.h"
27
28 @implementation NSObjectTests
29
30 - (void)testDescriptionForObject
31 {
32     // description for nil should be "(nil)"
33     WO_TEST_EQ([NSObject WOTest_descriptionForObject:nil], @"(nil)");
34
35     // NSString objects should be returned as-is
36     WO_TEST_EQ([NSObject WOTest_descriptionForObject:@"foo"], @"foo");
37
38     // NSNumber is a special case:
39     // when an NSValue is initialized with an int NSNumber, the NSValue behaves as though it were initialized with an int
40     NSNumber *number = [NSNumber numberWithInt:1];
41     WO_TEST_EQ([NSObject WOTest_descriptionForObject:number], @"(int)1");
42
43     // other objects should return "description"
44     NSButton *button = [[NSButton alloc] init];
45     WO_TEST_EQ([NSObject WOTest_descriptionForObject:button], [button description]);
46
47     // custom classes that do not respond to "description" return class name
48     WOLightweightRoot *root = [WOLightweightRoot newLightweightRoot];
49     WO_TEST_EQ([NSObject WOTest_descriptionForObject:root], @"WOLightweightRoot");
50
51     // special case: NSValues that contain NSStrings should return the string
52     NSValue *value = [NSValue WOTest_valueWithObject:@"foo"];
53     WO_TEST_EQ([NSObject WOTest_descriptionForObject:value], @"foo");
54
55     // standard case: other NSValues should return "description"
56     NSRange range;
57     range.location  = 0; // can't use NSMakeRange (Intel release warnings)
58     range.length    = 0;
59     value = [NSValue valueWithRange:range];
60     WO_TEST_EQ([NSObject WOTest_descriptionForObject:value], [value WOTest_description]);
61
62     // pointers to void should be formatted as "(void *)<00000000 >", as returned by WOTest_description
63     value = [NSValue valueWithNonretainedObject:@"bar"];
64     WO_TEST_EQ([NSObject WOTest_descriptionForObject:value], [value WOTest_description]);
65 }
66
67 - (void)testIsRegisteredClass
68 {
69     WO_TEST([NSObject WOTest_isRegisteredClass:[self class]]);
70     WO_TEST_FALSE([NSObject WOTest_isRegisteredClass:(Class)self]); // shouldn't raise
71 }
72
73 - (void)testIsMetaClass
74 {
75     WO_TEST([NSObject WOTest_isMetaClass:objc_getMetaClass("NSObjectTests")]);
76     WO_TEST_FALSE([NSObject WOTest_isMetaClass:[self class]]);
77 }
78
79 - (void)testObjectIsKindOfClass
80 {
81     // preliminaries
82     id object       = @"foo";
83     id subobject    = [NSMutableString stringWithString:@"bar"];
84     id otherObject  = [WOLightweightRoot newLightweightRoot];
85
86     // should raise if passed a non-class pointer
87     WO_TEST_THROWS([NSObject WOTest_object:self isKindOfClass:(Class)self]);
88     WO_TEST_DOES_NOT_THROW([NSObject WOTest_object:self isKindOfClass:[self class]]);
89
90     // nil object or NULL class should always return NO
91     WO_TEST_FALSE([NSObject WOTest_object:nil isKindOfClass:NULL]);
92     WO_TEST_FALSE([NSObject WOTest_object:self isKindOfClass:NULL]);
93     WO_TEST_FALSE([NSObject WOTest_object:nil isKindOfClass:[self class]]);
94
95     // basic test cases
96     WO_TEST([NSObject WOTest_object:object isKindOfClass:[NSString class]]);
97     WO_TEST_FALSE([NSObject WOTest_object:object isKindOfClass:[NSNumber class]]);
98
99     // subclass should be considered of same kind as superclass
100     WO_TEST([NSObject WOTest_object:subobject isKindOfClass:[NSString class]]);
101
102     // superclass should not be considered as same kind as subclass
103     WO_TEST_FALSE([NSObject WOTest_object:[[NSObject alloc] init] isKindOfClass:[self class]]);
104
105     // initial attempt at this test failed because the NSString object had a
106     // superclass of "%NSCFString", which happened to match NSMutableString!
107     //WO_TEST_FALSE([NSObject WOTest_object:object
108     //                 isKindOfClass:[NSMutableString class]]);
109     // note that the Cocoa isKindOfClass: method also produces this behaviour:
110     //WO_TEST_FALSE([@"constant string" isKindOfClass:[NSMutableString class]]);
111
112     // should handle custom root classes without problems
113     WO_TEST([NSObject WOTest_object:otherObject isKindOfClass:NSClassFromString(@"WOLightweightRoot")]);
114     WO_TEST_FALSE([NSObject WOTest_object:otherObject isKindOfClass:[NSString class]]);
115     WO_TEST_FALSE([NSObject WOTest_object:self isKindOfClass:NSClassFromString(@"WOLightweightRoot")]);
116 }
117
118 - (void)testInstancesOfClassAreKindOfClass
119 {
120     Class class         = [NSString class];
121     Class subclass      = [NSMutableString class];
122     Class otherClass    = NSClassFromString(@"WOLightweightRoot");
123
124     // should raise if passed non-class pointers
125     WO_TEST_THROWS([NSObject WOTest_instancesOfClass:(Class)self areKindOfClass:(Class)self]);
126     WO_TEST_THROWS([NSObject WOTest_instancesOfClass:(Class)self areKindOfClass:[NSString class]]);
127     WO_TEST_THROWS([NSObject WOTest_instancesOfClass:[NSString class] areKindOfClass:(Class)self]);
128     WO_TEST_DOES_NOT_THROW([NSObject WOTest_instancesOfClass:[self class] areKindOfClass:[NSString class]]);
129
130     // if either class is NULL should always return NO
131     WO_TEST_FALSE([NSObject WOTest_instancesOfClass:NULL areKindOfClass:NULL]);
132     WO_TEST_FALSE([NSObject WOTest_instancesOfClass:[self class] areKindOfClass:NULL]);
133     WO_TEST_FALSE([NSObject WOTest_instancesOfClass:NULL areKindOfClass:[self class]]);
134
135     // basic tests
136     WO_TEST([NSObject WOTest_instancesOfClass:[NSString class] areKindOfClass:[NSString class]]);
137     WO_TEST_FALSE([NSObject WOTest_instancesOfClass:[NSString class] areKindOfClass:[NSNumber class]]);
138
139     // a subclass should be considered of same kind as superclass
140     WO_TEST([NSObject WOTest_instancesOfClass:subclass areKindOfClass:class]);
141
142     // a superclass should not be considered as same kind as subclass
143     WO_TEST_FALSE([NSObject WOTest_instancesOfClass:class areKindOfClass:subclass]);
144
145     // should handle custom root classes without problems
146     WO_TEST([NSObject WOTest_instancesOfClass:otherClass areKindOfClass:otherClass]);
147     WO_TEST_FALSE([NSObject WOTest_instancesOfClass:class areKindOfClass:otherClass]);
148     WO_TEST_FALSE([NSObject WOTest_instancesOfClass:otherClass areKindOfClass:class]);
149 }
150
151 - (void)testObjectRespondsToSelector
152 {
153     // preliminaries
154     id object       = @"foobar";
155     id subobject    = [NSMutableString stringWithString:object];
156     id root         = [WOLightweightRoot newLightweightRoot];
157
158     // test returns NO for nil object or NULL selector
159     WO_TEST_FALSE([NSObject WOTest_object:nil respondsToSelector:NULL]);
160     WO_TEST_FALSE([NSObject WOTest_object:nil respondsToSelector:@selector(length)]);
161     WO_TEST_FALSE([NSObject WOTest_object:self respondsToSelector:NULL]);
162
163     // basic tests
164     WO_TEST([NSObject WOTest_object:self
165           respondsToSelector:@selector(testObjectRespondsToSelector)]);
166     WO_TEST_FALSE([NSObject WOTest_object:self respondsToSelector:@selector(foo)]);
167
168     // should work for subclasses
169     WO_TEST([NSObject WOTest_object:object respondsToSelector:@selector(length)]);
170     WO_TEST([NSObject WOTest_object:subobject respondsToSelector:@selector(length)]);
171     WO_TEST_FALSE([NSObject WOTest_object:object respondsToSelector:@selector(bar)]);
172     WO_TEST_FALSE([NSObject WOTest_object:subobject
173                 respondsToSelector:@selector(bar)]);
174
175     // should handle custom root classes without problems
176     WO_TEST([NSObject WOTest_object:root respondsToSelector:@selector(exampleMethod)]);
177     WO_TEST_FALSE([NSObject WOTest_object:root respondsToSelector:@selector(foobar)]);
178 }
179
180 - (void)testClassRespondsToSelector
181 {
182     // should raise if passed non-class pointer
183     WO_TEST_THROWS([NSObject WOTest_class:(Class)self respondsToSelector:@selector(init)]);
184     WO_TEST_DOES_NOT_THROW([NSObject WOTest_class:[self class] respondsToSelector:@selector(init)]);
185
186     // test that NULL class or NULL selector return NO
187     WO_TEST_FALSE([NSObject WOTest_class:NULL respondsToSelector:NULL]);
188     WO_TEST_FALSE([NSObject WOTest_class:NULL respondsToSelector:@selector(init)]);
189     WO_TEST_FALSE([NSObject WOTest_class:[self class] respondsToSelector:NULL]);
190
191     // basic tests
192     WO_TEST([NSObject WOTest_class:[self class] respondsToSelector:@selector(initialize)]);
193     WO_TEST_FALSE([NSObject WOTest_class:[self class] respondsToSelector:@selector(unimplimentedClassMethod)]);
194 }
195
196 - (void)testInstancesOfClassRespondToSelector
197 {
198     // should raise if passed non-class pointer
199     WO_TEST_THROWS([NSObject WOTest_instancesOfClass:(Class)self respondToSelector:@selector(init)]);
200     WO_TEST_DOES_NOT_THROW([NSObject WOTest_instancesOfClass:[self class] respondToSelector:@selector(init)]);
201
202     // test that NULL class or NULL selector return NO
203     WO_TEST_FALSE([NSObject WOTest_instancesOfClass:NULL respondToSelector:NULL]);
204     WO_TEST_FALSE([NSObject WOTest_instancesOfClass:NULL respondToSelector:@selector(length)]);
205     WO_TEST_FALSE([NSObject WOTest_instancesOfClass:[self class] respondToSelector:NULL]);
206
207     // basic tests
208     WO_TEST([NSObject WOTest_instancesOfClass:[NSString class] respondToSelector:@selector(length)]);
209     WO_TEST_FALSE([NSObject WOTest_instancesOfClass:[NSString class] respondToSelector:@selector(longitude)]);
210
211     // subclasses should work as well
212     WO_TEST([NSObject WOTest_instancesOfClass:[NSMutableString class] respondToSelector:@selector(length)]);
213     WO_TEST_FALSE([NSObject WOTest_instancesOfClass:[NSMutableString class] respondToSelector:@selector(longitude)]);
214
215     // should work with custom root classes
216     WO_TEST([NSObject WOTest_instancesOfClass:NSClassFromString(@"WOLightweightRoot") respondToSelector:@selector(forward::)]);
217     WO_TEST([NSObject WOTest_instancesOfClass:NSClassFromString(@"WOLightweightRoot") respondToSelector:@selector(exampleMethod)]);
218     WO_TEST_FALSE([NSObject WOTest_instancesOfClass:NSClassFromString(@"WOLightweightRoot")
219                                   respondToSelector:@selector(conformsToProtocol:)]);
220 }
221
222 - (void)testInstancesOfClassConformToProtocol
223 {
224     // should throw if passed non-class pointer
225     WO_TEST_THROWS([NSObject WOTest_instancesOfClass:(Class)self conformToProtocol:@protocol(NSLocking)]);
226     WO_TEST_DOES_NOT_THROW([NSObject WOTest_instancesOfClass:[self class] conformToProtocol:@protocol(NSObject)]);
227
228     // test that NULL class or NULL protocol return NO
229     WO_TEST_FALSE([NSObject WOTest_instancesOfClass:NULL conformToProtocol:NULL]);
230     WO_TEST_FALSE([NSObject WOTest_instancesOfClass:[self class] conformToProtocol:NULL]);
231     WO_TEST_FALSE([NSObject WOTest_instancesOfClass:NULL conformToProtocol:@protocol(WOTest)]);
232
233     // basic tests
234     WO_TEST([NSObject WOTest_instancesOfClass:[NSLock class] conformToProtocol:@protocol(NSLocking)]);
235     WO_TEST_FALSE([NSObject WOTest_instancesOfClass:[NSString class] conformToProtocol:@protocol(NSLocking)]);
236     WO_TEST([NSObject WOTest_instancesOfClass:[self class] conformToProtocol:@protocol(WOTest)]);
237     WO_TEST_FALSE([NSObject WOTest_instancesOfClass:[self class] conformToProtocol:@protocol(NSTextAttachmentCell)]);
238
239     // test with subclasses (subclasses should inherit protocol conformance)
240     WO_TEST([NSObject WOTest_instancesOfClass:[NSMutableString class] conformToProtocol:@protocol(NSCopying)]);
241
242     // should handle custom root classes
243     WO_TEST_FALSE
244         ([NSObject WOTest_instancesOfClass:NSClassFromString(@"WOLightweightRoot") conformToProtocol:@protocol(NSLocking)]);
245 }
246
247 - (void)testReturnTypeForClassSelector
248 {
249     // raises if passed NULL class or NULL selector
250     WO_TEST_THROWS([NSObject WOTest_returnTypeForClass:NULL selector:NULL]);
251     WO_TEST_THROWS([NSObject WOTest_returnTypeForClass:NULL selector:@selector(init)]);
252     WO_TEST_THROWS([NSObject WOTest_returnTypeForClass:[self class] selector:NULL]);
253
254     // raises if passed non-class pointer
255     WO_TEST_THROWS([NSObject WOTest_returnTypeForClass:(Class)self selector:@selector(init)]);
256
257     // basic test
258     WO_TEST_EQ([NSObject WOTest_returnTypeForClass:[self class] selector:@selector(initialize)], @"v");
259
260     // returns nil for unrecognized selector
261     WO_TEST_EQ([NSObject WOTest_returnTypeForClass:[self class] selector:@selector(poodle)], nil);
262 }
263
264 - (void)testReturnTypeForObjectSelector
265 {
266     // raises if passed nil object or NULL selector
267     WO_TEST_THROWS([NSObject WOTest_returnTypeForObject:nil selector:NULL]);
268     WO_TEST_THROWS([NSObject WOTest_returnTypeForObject:self selector:NULL]);
269     WO_TEST_THROWS([NSObject WOTest_returnTypeForObject:nil selector:@selector(init)]);
270
271     // basic test
272     WO_TEST_EQ([NSObject WOTest_returnTypeForObject:self selector:@selector(init)], @"@");
273
274     // returns nil for unrecognized selector
275     WO_TEST_EQ([NSObject WOTest_returnTypeForObject:self selector:@selector(beagle:dog:)], nil);
276 }
277
278 - (void)testIsIdReturnType
279 {
280     WO_TEST([NSObject WOTest_isIdReturnType:@"@"]);
281     WO_TEST_FALSE([NSObject WOTest_isIdReturnType:@"v"]);
282
283     // passing nil should return NO, not raise an exception
284     WO_TEST_FALSE([NSObject WOTest_isIdReturnType:nil]);
285 }
286
287 - (void)testIsCharacterStringReturnType
288 {
289     WO_TEST([NSObject WOTest_isCharacterStringReturnType:@"*"]);
290     WO_TEST_FALSE([NSObject WOTest_isCharacterStringReturnType:@"r*"]);
291
292     // passing nil should return NO, not raise an exception
293     WO_TEST_FALSE([NSObject WOTest_isCharacterStringReturnType:nil]);
294 }
295
296 - (void)testIsConstantCharacterStringReturnType
297 {
298     WO_TEST([NSObject WOTest_isConstantCharacterStringReturnType:@"r*"]);
299     WO_TEST_FALSE([NSObject WOTest_isConstantCharacterStringReturnType:@"^v"]);
300
301     // passing nil should return NO, not raise an exception
302     WO_TEST_FALSE([NSObject WOTest_isConstantCharacterStringReturnType:nil]);
303 }
304
305 - (void)testObjectReturnsIdForSelector
306 {
307     // should raise for nil object or NULL selector
308     WO_TEST_THROWS([NSObject WOTest_objectReturnsId:nil forSelector:NULL]);
309     WO_TEST_THROWS([NSObject WOTest_objectReturnsId:self forSelector:NULL]);
310     WO_TEST_THROWS([NSObject WOTest_objectReturnsId:nil forSelector:@selector(init)]);
311
312     // basic tests
313     WO_TEST([NSObject WOTest_objectReturnsId:self forSelector:@selector(init)]);
314     WO_TEST_FALSE([NSObject WOTest_objectReturnsId:self forSelector:@selector(dealloc)]);
315
316     // passing unrecognized selector should return NO, not raise an exception
317     WO_TEST_FALSE([NSObject WOTest_objectReturnsId:self forSelector:@selector(initWithChicken:)]);
318 }
319
320 - (void)testObjectReturnsCharacterStringForSelector
321 {
322     // should raise for nil object or NULL selector
323     WO_TEST_THROWS([NSObject WOTest_objectReturnsCharacterString:nil forSelector:NULL]);
324     WO_TEST_THROWS([NSObject WOTest_objectReturnsCharacterString:self forSelector:NULL]);
325     WO_TEST_THROWS([NSObject WOTest_objectReturnsCharacterString:nil forSelector:@selector(init)]);
326
327     // basic tests
328     char *string = "foo";
329     NSValue *value = [NSValue WOTest_valueWithCharacterString:string];
330     WO_TEST([NSObject WOTest_objectReturnsCharacterString:value forSelector:@selector(WOTest_characterStringValue)]);
331     WO_TEST_FALSE([NSObject WOTest_objectReturnsCharacterString:self forSelector:@selector(init)]);
332
333     // passing unrecognized selector should return NO, not raise an exception
334     WO_TEST_FALSE([NSObject WOTest_objectReturnsCharacterString:self forSelector:@selector(initWithChicken:)]);
335 }
336
337 - (void)testObjectReturnsConstantCharacterString
338 {
339     // should raise for nil object or NULL selector
340     WO_TEST_THROWS([NSObject WOTest_objectReturnsConstantCharacterString:nil forSelector:NULL]);
341     WO_TEST_THROWS([NSObject WOTest_objectReturnsConstantCharacterString:self forSelector:NULL]);
342     WO_TEST_THROWS([NSObject WOTest_objectReturnsConstantCharacterString:nil forSelector:@selector(init)]);
343
344     // basic tests
345     NSValue *value      = [NSValue WOTest_valueWithConstantCharacterString:"foobar"];
346     SEL     selector    = @selector(WOTest_constantCharacterStringValue);
347     WO_TEST([NSObject WOTest_objectReturnsConstantCharacterString:value forSelector:selector]);
348     WO_TEST_FALSE([NSObject WOTest_objectReturnsConstantCharacterString:self forSelector:@selector(init)]);
349
350     // passing unrecognized selector should return NO, not raise an exception
351     WO_TEST_FALSE([NSObject WOTest_objectReturnsConstantCharacterString:self forSelector:@selector(getTurkey)]);
352 }
353
354 @end