- (void)callAppKitMethod
{
NSView *aView = [[NSView alloc] initWithFrame:NSZeroRect];
- [aView release];
}
By including the AppKit header file you ensure that the compiler doesn't give you any warnings, but if you try to build such code the linker will give you an error that "NSView" is an undefined symbol. Of course, even if you could produce an executable and run it, it wouldn't work because the executable isn't linked to the AppKit.framework. One way to force the framework to load is to set environment variables and then run the product from the command-line. For example, in the bash shell:
[NSBundle bundleWithPath:@"/System/Library/Frameworks/AppKit.framework"];
Class viewClass = [theBundle classNamed:@"NSView"];
NSView *aView = [[viewClass alloc] initWithFrame:NSZeroRect];
- [aView release];
}
No compiler warnings, no linker errors, everything just works. WOTest uses this technique to allow you to load code "on the fly" without having to link to it. All it has to do is look for bundles, load them, and then run the test methods on them.
#ifdef WO_USE_OWN_METHOD_SIGNATURE_IMPLEMENTATION
- return [[[self alloc] initWithObjCTypes:types] autorelease];
+ return [[self alloc] initWithObjCTypes:types];
#else /* use private Apple API */
- NSAssert([self respondsToSelector:@selector(signatureWithObjCTypes:)],
- @"signatureWithObjCTypes: selector not recognized");
+ NSAssert([self respondsToSelector:@selector(signatureWithObjCTypes:)], @"signatureWithObjCTypes: selector not recognized");
return [self signatureWithObjCTypes:types];
#endif
- (NSString *)WOTest_stringByConvertingToAbsolutePath;
-/*! Returns an immutable, autoreleased string created by "collapsing" all of the whitespace in the receiver into single spaces. All newlines are converted into spaces and consecutive spaces are "collapsed" into a single space. */
+/*! Returns an immutable string created by "collapsing" all of the whitespace in the receiver into single spaces. All newlines are converted into spaces and consecutive spaces are "collapsed" into a single space. */
- (NSString *)WOTest_stringByCollapsingWhitespace;
-/*! Returns an immutable, autoreleased string created by appending a single character of type unichar to the receiver. */
+/*! Returns an immutable string created by appending a single character of type unichar to the receiver. */
- (NSString *)WOTest_stringByAppendingCharacter:(unichar)character;
@end
{
fprintf(stdout, "%s\n", [string UTF8String]);
fflush(NULL); // flush all open streams (not just stdout)
- [string release];
}
va_end(args);
}
{
fprintf(stdout, "%s\n", [string UTF8String]);
fflush(NULL); // flush all open streams (not just stdout)
- [string release];
}
}
+ (NSString *)WOTest_stringWithFormat:(NSString *)format arguments:(va_list)argList
{
- return [[[NSString alloc] initWithFormat:format
- arguments:argList] autorelease];
+ return [[NSString alloc] initWithFormat:format arguments:argList];
}
+ (NSString *)WOTest_stringWithCharacter:(unichar)character
- (NSString *)WOTest_stringByCollapsingWhitespace
{
- NSCharacterSet *whitespace = [NSCharacterSet whitespaceAndNewlineCharacterSet];
- NSMutableString *temp = [NSMutableString stringWithString:self];
- unsigned int length = [temp length];
+ NSCharacterSet *whitespace = [NSCharacterSet whitespaceAndNewlineCharacterSet];
+ NSMutableString *temp = [NSMutableString stringWithString:self];
+ unsigned int length = [temp length];
for (unsigned int i = 0; i < length; i++)
{
if ([whitespace characterIsMember:[temp characterAtIndex:i]])
}
}
}
- return [NSString stringWithString:temp]; // return immutable, autoreleased
+ return [temp copy]; // return immutable
}
- (NSString *)WOTest_stringByAppendingCharacter:(unichar)character
{
// for NSString objects: just return content
if ([NSObject WOTest_object:valueContents isKindOfClass:[NSString class]])
- return [[valueContents retain] autorelease];
+ return valueContents;
else if ([NSObject WOTest_object:valueContents respondsToSelector:@selector(description)] &&
[NSObject WOTest_isIdReturnType:[NSObject WOTest_returnTypeForObject:valueContents
selector:@selector(description)]])
// custom classes that do not respond to "description" return class name
WOLightweightRoot *root = [WOLightweightRoot newLightweightRoot];
WO_TEST_EQ([NSObject WOTest_descriptionForObject:root], @"WOLightweightRoot");
- [root dealloc];
// special case: NSValues that contain NSStrings should return the string
NSValue *value = [NSValue WOTest_valueWithObject:@"foo"];
WO_TEST([NSObject WOTest_object:subobject isKindOfClass:[NSString class]]);
// superclass should not be considered as same kind as subclass
- WO_TEST_FALSE([NSObject WOTest_object:[[[NSObject alloc] init] autorelease]
- isKindOfClass:[self class]]);
+ WO_TEST_FALSE([NSObject WOTest_object:[[NSObject alloc] init] isKindOfClass:[self class]]);
// initial attempt at this test failed because the NSString object had a
// superclass of "%NSCFString", which happened to match NSMutableString!
//WO_TEST_FALSE([@"constant string" isKindOfClass:[NSMutableString class]]);
// should handle custom root classes without problems
- WO_TEST([NSObject WOTest_object:otherObject
- isKindOfClass:NSClassFromString(@"WOLightweightRoot")]);
+ WO_TEST([NSObject WOTest_object:otherObject isKindOfClass:NSClassFromString(@"WOLightweightRoot")]);
WO_TEST_FALSE([NSObject WOTest_object:otherObject isKindOfClass:[NSString class]]);
- WO_TEST_FALSE([NSObject WOTest_object:self
- isKindOfClass:NSClassFromString(@"WOLightweightRoot")]);
-
- // cleanup
- [otherObject dealloc];
+ WO_TEST_FALSE([NSObject WOTest_object:self isKindOfClass:NSClassFromString(@"WOLightweightRoot")]);
}
- (void)testInstancesOfClassAreKindOfClass
respondsToSelector:@selector(bar)]);
// should handle custom root classes without problems
- WO_TEST([NSObject WOTest_object:root respondsToSelector:@selector(dealloc)]);
+ WO_TEST([NSObject WOTest_object:root respondsToSelector:@selector(exampleMethod)]);
WO_TEST_FALSE([NSObject WOTest_object:root respondsToSelector:@selector(foobar)]);
-
- // cleanup
- [root dealloc];
}
- (void)testClassRespondsToSelector
// should work with custom root classes
WO_TEST([NSObject WOTest_instancesOfClass:NSClassFromString(@"WOLightweightRoot") respondToSelector:@selector(forward::)]);
- WO_TEST([NSObject WOTest_instancesOfClass:NSClassFromString(@"WOLightweightRoot") respondToSelector:@selector(dealloc)]);
+ WO_TEST([NSObject WOTest_instancesOfClass:NSClassFromString(@"WOLightweightRoot") respondToSelector:@selector(exampleMethod)]);
WO_TEST_FALSE([NSObject WOTest_instancesOfClass:NSClassFromString(@"WOLightweightRoot")
respondToSelector:@selector(conformsToProtocol:)]);
}
// should throw if passed NULL
mock = [WOClassMock alloc];
WO_TEST_THROWS([mock initWithClass:NULL]);
- [mock release];
// should throw if passed non-class pointer
mock = [WOClassMock alloc];
WO_TEST_THROWS([mock initWithClass:(Class)self]);
- [mock release];
// otherwise should work
- WO_TEST_DOES_NOT_THROW
- ([[[WOClassMock alloc] initWithClass:[self class]] autorelease]);
+ WO_TEST_DOES_NOT_THROW([[WOClassMock alloc] initWithClass:[self class]]);
// should throw if passed a meta class
Class class = [NSString class];
Class metaclass = object_getClass(class);
mock = [WOClassMock alloc];
WO_TEST_THROWS([mock initWithClass:metaclass]);
- [mock release];
}
- (void)testAccept
- (void)testInitWithObjectClass
{
- WOObjectMock *mock =
- [[[WOMock alloc] initWithObjectClass:[self class]] autorelease];
+ WOObjectMock *mock = [[WOMock alloc] initWithObjectClass:[self class]];
// make sure WOObjectMock class is returned
WO_TEST_EQ([mock class], [WOObjectMock class]);
// should throw exception instead of entering infinite loop
mock = [WOObjectMock alloc];
WO_TEST_THROWS([mock initWithObjectClass:[self class]]);
- [mock release];
}
- (void)testInitWithClass
{
- WOClassMock *mock =
- [[[WOMock alloc] initWithClass:[self class]] autorelease];
+ WOClassMock *mock = [[WOMock alloc] initWithClass:[self class]];
// make sure WOClassMock class is returned
WO_TEST_EQ([mock class], [WOClassMock class]);
// cannot test this because subclass implements that method directly
//mock = [WOClassMock alloc];
//WO_TEST_THROWS([mock initWithClass:[self class]]);
- //[mock release];
}
- (void)testInitWithProtocol
{
- WOProtocolMock *mock =
- [[[WOMock alloc] initWithProtocol:@protocol(WOTest)] autorelease];
+ WOProtocolMock *mock = [[WOMock alloc] initWithProtocol:@protocol(WOTest)];
// make sure WOProtocolMock class is returned
WO_TEST_EQ([mock class], [WOProtocolMock class]);
// cannot test this because subclass implements that method directly
//mock = [WOProtocolMock alloc];
//WO_TEST_THROWS([mock initWithProtocol:@protocol(WOTest)]);
- //[mock release];
}
- (void)testRecordingMethods
{
// all recording methods should throw an exception (use subclasses instead)
- WOMock *mock = [[[WOMock alloc] init] autorelease];
+ WOMock *mock = [[WOMock alloc] init];
WO_TEST_THROWS([mock reject]);
WO_TEST_THROWS([mock expectInOrder]);
WO_TEST_THROWS([mock expectOnce]);
id *object = NULL; // cause a crash, but WOTest should keep running
*object = @"foo"; // SIGBUS here
WO_TEST_FAIL; // this line never reached
- [pool release]; // nor this one, but pools are in a stack no problem
+ [pool drain]; // nor this one, but pools are in a stack no problem
}
#pragma mark -
- (void)testInitWithClass
{
- // preliminaries
- WOObjectMock *mock = nil;
-
// should throw if passed NULL
- mock = [WOObjectMock alloc];
- WO_TEST_THROWS([mock initWithClass:NULL]);
- [mock release];
+ WO_TEST_THROWS([[WOObjectMock alloc] initWithClass:NULL]);
// should throw if passed non-class pointer
- mock = [WOObjectMock alloc];
- WO_TEST_THROWS([mock initWithClass:(Class)self]);
- [mock release];
+ WO_TEST_THROWS([[WOObjectMock alloc] initWithClass:(Class)self]);
// otherwise should work
- WO_TEST_DOES_NOT_THROW
- ([[[WOObjectMock alloc] initWithClass:[self class]] autorelease]);
+ WO_TEST_DOES_NOT_THROW([[WOObjectMock alloc] initWithClass:[self class]]);
// should throw if passed a meta class
- Class class = [NSString class];
- Class metaclass = object_getClass(class);
- mock = [WOObjectMock alloc];
- WO_TEST_THROWS([mock initWithClass:metaclass]);
- [mock release];
+ WO_TEST_THROWS([[WOObjectMock alloc] initWithClass:object_getClass([NSString class])]);
}
- (void)testMockExpectInOrder
[[mock expect] lowercaseString]; // a valid NSString selector
WO_TEST_DOES_NOT_THROW([mock lowercaseString]);
WO_TEST_DOES_NOT_THROW([mock verify]);
- WO_TEST_DOES_NOT_THROW([mock retain]); // ok (inherited from NSProxy)
- WO_TEST_DOES_NOT_THROW([mock release]); // ok (inherited from NSProxy)
WO_TEST_THROWS([mock uppercaseString]); // fail (not explicitly expected)
// should throw for class methods
// should raise if passed nil class
WO_TEST_THROWS([WOObjectMock mockForClass:nil]);
- WO_TEST_THROWS([[[WOObjectMock alloc] initWithClass:nil] release]);
+ WO_TEST_THROWS([[WOObjectMock alloc] initWithClass:nil]);
WO_TEST_DOES_NOT_THROW([WOObjectMock mockForClass:aClass]);
- WO_TEST_DOES_NOT_THROW([[[WOObjectMock alloc] initWithClass:aClass] release]);
+ WO_TEST_DOES_NOT_THROW([[WOObjectMock alloc] initWithClass:aClass]);
// test if passed a non-class object (ie. an instance)
// raise if initialized with nil class pointer
WO_TEST_DOES_NOT_THROW([WOObjectStub stubForClass:aClass withDelegate:nil]);
WO_TEST_THROWS([WOObjectStub stubForClass:nil withDelegate:nil]);
- WO_TEST_DOES_NOT_THROW([[[WOObjectStub alloc] initWithClass:aClass delegate:nil] release]);
- WO_TEST_THROWS([[[WOObjectStub alloc] initWithClass:nil delegate:nil] release]);
+ WO_TEST_DOES_NOT_THROW([[WOObjectStub alloc] initWithClass:aClass delegate:nil]);
+ WO_TEST_THROWS([[WOObjectStub alloc] initWithClass:nil delegate:nil]);
// test if passed a non-class object (ie. an instance)
WO_TEST_DOES_NOT_THROW(stub = [WOObjectStub stubForClass:aClass withDelegate:nil]);
WO_TEST_THROWS([stub recordedInvocation]);
- // test automatic verify on dealloc
+ // test automatic verify on finalize
}
- (void)testStubEquality
// should throw for NULL protocol
WOProtocolMock *mock = [WOProtocolMock alloc];
WO_TEST_THROWS([mock initWithProtocol:NULL]);
- [mock release];
}
- (void)testMethodSignatureForSelector
// throws if passed NULL
WOProtocolStub *stub = [WOProtocolStub alloc];
WO_TEST_THROWS([stub initWithProtocol:NULL delegate:nil]);
- [stub dealloc];
// otherwise works
stub = [WOProtocolStub alloc];
WO_TEST_DOES_NOT_THROW([stub initWithProtocol:@protocol(WOTest) delegate:nil]);
- [stub dealloc];
}
- (void)testMethodSignatureForSelector
- (void)testMatchesInvocation
{
- WOStub *stub = [[[WOStub alloc] init] autorelease];
+ WOStub *stub = [[WOStub alloc] init];
// raises if sent nil
WO_TEST_THROWS([stub matchesInvocation:nil]);
+ (void)initialize
{
- WOEmptyClassMethodInvocations =
- [[NSMutableArray alloc] initWithCapacity:3];
- WOEmptyInstanceMethodInvocations =
- [[NSMutableArray alloc] initWithCapacity:3];
+ WOEmptyClassMethodInvocations = [NSMutableArray arrayWithCapacity:3];
+ WOEmptyInstanceMethodInvocations = [NSMutableArray arrayWithCapacity:3];
}
+ (void)verify
{
- // cleanup
- [WOEmptyClassMethodInvocations autorelease];
- [WOEmptyInstanceMethodInvocations autorelease];
-
// were class methods called in order?
- NSArray *expectedClassMethods = [NSArray arrayWithObjects:
- @"preflight", @"testClassMethod", @"postflight", nil];
- NSAssert
- ([expectedClassMethods isEqualToArray:WOEmptyClassMethodInvocations],
- @"Class method verification failed");
+ NSArray *expectedClassMethods = [NSArray arrayWithObjects:@"preflight", @"testClassMethod", @"postflight", nil];
+ NSAssert([expectedClassMethods isEqualToArray:WOEmptyClassMethodInvocations], @"Class method verification failed");
// were instance methods called in order?
- NSArray *expectedInstanceMethods = [NSArray arrayWithObjects:
- @"preflight", @"testInstanceMethod", @"postflight", nil];
- NSAssert([expectedInstanceMethods isEqualToArray:
- WOEmptyInstanceMethodInvocations],
- @"Instance method verification failed");
+ NSArray *expectedInstanceMethods = [NSArray arrayWithObjects:@"preflight", @"testInstanceMethod", @"postflight", nil];
+ NSAssert([expectedInstanceMethods isEqualToArray:WOEmptyInstanceMethodInvocations], @"Instance method verification failed");
}
+ (void)preflight
return class_createInstance(class, 0);
}
-- (void)dealloc
-{
- free(self);
-}
-
// http://www.geocities.com/chrootstrap/custom_objective_c_root_classes.html
// http://darwinsource.opendarwin.org/10.3/objc4-235/runtime/Messengers.subproj/objc-msg-ppc.s
// Apple's runtime makes the assumption that this method is implemented
WO_TEST_DOES_NOT_THROW([objectValue WOTest_testIsEqualToValue:nilValue]);
WO_TEST_DOES_NOT_THROW([nilValue WOTest_testIsEqualToValue:objectValue]);
- NSValue *realObjectValue = [NSValue valueWithNonretainedObject:[[[NSObject alloc] init] autorelease]];
+ NSValue *realObjectValue = [NSValue valueWithNonretainedObject:[[NSObject alloc] init]];
WO_TEST_FALSE([realObjectValue WOTest_isObject]);
WO_TEST_TRUE([realObjectValue WOTest_isPointerToVoid]);
WO_TEST_DOES_NOT_THROW([realObjectValue WOTest_testIsEqualToValue:nilValue]);
WO_TEST_EQUAL([NSException WOTest_descriptionForException:exception1], @"foo: bar");
// NSImage responds to name but not reason
- NSImage *exception2 = [[[NSImage alloc] initWithSize:NSZeroSize] autorelease];
+ NSImage *exception2 = [[NSImage alloc] initWithSize:NSZeroSize];
[exception2 setName:@"Roger Smith"];
WO_TEST_EQUAL([NSException WOTest_descriptionForException:exception2],
([NSString stringWithFormat:@"%@ (%x)", [exception2 name], exception2]));
// NSObject responds to description but not to name or reason
- NSObject *exception3 = [[[NSObject alloc] init] autorelease];
+ NSObject *exception3 = [[NSObject alloc] init];
WO_TEST_EQUAL([NSException WOTest_descriptionForException:exception3], [exception3 description]);
WO_TEST_EQUAL([NSException WOTest_nameForException:nil], @"no exception");
- (void)throwWORootClassObject
{
- WORootClass *object = [WORootClass new]; // this is officially a leak
- @throw object;
- [object dealloc]; // leaks because this line is never reached
+ @throw [WORootClass new];
}
- (void)throwObject
{
- Object *object = [[Object alloc] init]; // another leak
- @throw object;
- [object free]; // leaks because this line is never reached
+ @throw [[Object alloc] init];
}
- (void)doNotThrowException
- (void)makeCocoaThrowException
{
// should throw NSInvalidArgumentException
- (void)[[[NSString alloc] initWithFormat:nil] autorelease];
+ (void)[[NSString alloc] initWithFormat:nil];
}
- (void)makeCocoaThrowNSRangeException
+ (id)newLightweightRoot;
-- (void)dealloc;
-
/*! This method required by the runtime (called by _objc_forward for unrecognized selectors). The default implementation simply raises an NSInternalInconsistencyException. */
- forward:(SEL)sel :(marg_list)args;
return class_createInstance(class, 0);
}
-- (void)dealloc
+- (void)exampleMethod
{
- free(self);
+ // do nothing
}
- forward:(SEL)sel :(marg_list)args
Rejected selectors cause an exception to be raised.
- By default, if a selector does not appear in any of the internal lists an exception is raised. This latter behaviour requires you to be explicit about <em>all</em> selectors which a mock object may receive. For example, you may have a mock object that stands in for an NSString instance and expect that it be sent a "lowercaseString" selector. If during your test you also send an "uppercaseString" selector then an exception will be raised (because the selector does not appear in the internal lists, even though it is a valid NSString selector). A small number of methods will be accepted even without being explicitly added the the lists; these include methods like retain and release and other NSObject protocol methods. These are accepted because they are inherited from the parent class of WOMock (NSProxy).
+ By default, if a selector does not appear in any of the internal lists an exception is raised. This latter behaviour requires you to be explicit about <em>all</em> selectors which a mock object may receive. For example, you may have a mock object that stands in for an NSString instance and expect that it be sent a "lowercaseString" selector. If during your test you also send an "uppercaseString" selector then an exception will be raised (because the selector does not appear in the internal lists, even though it is a valid NSString selector). A small number of methods will be accepted even without being explicitly added the the lists; these include methods such as NSObject protocol methods. These are accepted because they are inherited from the parent class of WOMock (NSProxy).
If you wish to override this behaviour you may send the setAcceptsByDefault message passing a flag of YES, but be aware that selectors which fall through to the "accepts by default" cannot return any defined value. For control over return values the selector in question must be explicitly set up with the expectInOrder, expectOnce, expect, acceptOnce or accept methods.
*/
- (id)reject;
-/*! Instructs the receiver to expect a selector; the receiver not only accepts the selector but it actually requires that it be sent. If the expected selector has not been received when the verify method is called (or at dealloc time) then an exception will be raised. The following example shows how to instruct the WOMock instance mock to expect the disconnect selector:
+/*! Instructs the receiver to expect a selector; the receiver not only accepts the selector but it actually requires that it be sent. If the expected selector has not been received when the verify method is called (or at finalize time) then an exception will be raised. The following example shows how to instruct the WOMock instance mock to expect the disconnect selector:
\code
[[mock expect] disconnect];
/*! \endgroup */
-/*! Verifies that all selectors registered with the expect method have been performed. If any have not then an exception is raised. The verify method is automatically called at dealloc time, although you may still wish to invoke it manually. */
+/*! Verifies that all selectors registered with the expect method have been performed. If any have not then an exception is raised. The verify method is automatically called at finalize time, although you may still wish to invoke it manually. */
- (void)verify;
#pragma mark -
if ([self class] != [WOMock class])
[NSException raise:NSInternalInconsistencyException format:@"initWithObjectClass: called from WOMock subclass"];
- id subclass = [[WOObjectMock allocWithZone:[self zone]] initWithClass:aClass];
-
- [self dealloc];
- return subclass;
+ return [[WOObjectMock allocWithZone:[self zone]] initWithClass:aClass];
}
// a true Apple-style cluster would do this by allocating a placeholder object
if ([self class] != [WOMock class])
[NSException raise:NSInternalInconsistencyException format:@"initWithClass: called from WOMock subclass"];
- id subclass = [[WOClassMock allocWithZone:[self zone]] initWithClass:aClass];
- [self dealloc];
- return subclass;
+ return [[WOClassMock allocWithZone:[self zone]] initWithClass:aClass];
}
// a true Apple-style cluster would do this by allocating a placeholder object
if ([self class] != [WOMock class])
[NSException raise:NSInternalInconsistencyException format:@"initWithProtocol: called from WOMock subclass"];
- id subclass = [[WOProtocolMock allocWithZone:[self zone]] initWithProtocol:aProtocol];
- [self dealloc];
- return subclass;
+ return [[WOProtocolMock allocWithZone:[self zone]] initWithProtocol:aProtocol];
}
- (id)init
{
// super (NSProxy) has no init method
- expectedInOrder = [[NSMutableArray alloc] init]; // there are no accessors (to avoid namespace pollution)
- accepted = [[NSMutableSet alloc] init];
- acceptedOnce = [[NSMutableSet alloc] init];
- expected = [[NSMutableSet alloc] init];
- expectedOnce = [[NSMutableSet alloc] init];
- rejected = [[NSMutableSet alloc] init];
- methodSignatures = [[NSMutableDictionary alloc] init];
+ expectedInOrder = [NSMutableArray array]; // there are no accessors (to avoid namespace pollution)
+ accepted = [NSMutableSet set];
+ acceptedOnce = [NSMutableSet set];
+ expected = [NSMutableSet set];
+ expectedOnce = [NSMutableSet set];
+ rejected = [NSMutableSet set];
+ methodSignatures = [NSMutableDictionary dictionary];
return self;
}
-- (void)dealloc
+// TODO: given that the time at which finalize is called is indeterminate consider coming up with some other mechanism for
+// triggering verification
+- (void)finalize
{
- [self verify];
- [accepted release];
- [acceptedOnce release];
- [expected release];
- [expectedOnce release];
- [expectedInOrder release];
- [rejected release];
- [methodSignatures release];
- [super dealloc];
+ [self verify];
}
- (id)accept
{
NSParameterAssert(aClass != NULL);
NSParameterAssert([NSObject WOTest_isRegisteredClass:aClass]); // only registered classes pass (do not pass meta classes)
- return [[[self alloc] initWithClass:aClass] autorelease];
+ return [[self alloc] initWithClass:aClass];
}
- (id)initWithClass:(Class)aClass
+ (id)stubForClass:(Class)aClass withDelegate:(id)aDelegate
{
NSParameterAssert(aClass != NULL);
- return [[[self alloc] initWithClass:aClass delegate:aDelegate] autorelease];
+ return [[self alloc] initWithClass:aClass delegate:aDelegate];
}
- (id)initWithClass:(Class)aClass delegate:(id)aDelegate
+ (id)mockForProtocol:(Protocol *)aProtocol
{
NSParameterAssert(aProtocol != NULL);
- return [[[self alloc] initWithProtocol:aProtocol] autorelease];
+ return [[self alloc] initWithProtocol:aProtocol];
}
- (id)initWithProtocol:(Protocol *)aProtocol
+ (id)stubForProtocol:(Protocol *)aProtocol withDelegate:(id)aDelegate
{
NSParameterAssert(aProtocol != NULL);
- return [[[self alloc] initWithProtocol:aProtocol delegate:aDelegate] autorelease];
+ return [[self alloc] initWithProtocol:aProtocol delegate:aDelegate];
}
/*! Designated initializer. */
/*! Used to specify the return value that should be sent in response to messages. */
- (id)returning:(NSValue *)aValue;
-/*! Used to specify the exception that should be raised in response to messages. \p anException should respond to the retain, release, autorelease, isEqual and hash selectors. */
+/*! Used to specify the exception that should be raised in response to messages. \p anException should respond to the isEqual and hash selectors. */
- (id)raising:(id)anException;
#pragma mark -
#pragma mark -
#pragma mark Accessors
-- (BOOL)acceptsAnyArguments;
-- (void)setAcceptsAnyArguments:(BOOL)flag;
-
/*! Returns the recorded invocation object stored by this instance. Raises an exception if no invocation has yet been recorded. */
- (NSInvocation *)recordedInvocation;
-/*! Direct access to the invocation instance variable. Should not be used. Use recordedInvocation instead. */
-- (NSInvocation *)invocation;
-- (void)setInvocation:(NSInvocation *)anInvocation;
-
-- (NSValue *)returnValue;
-- (void)setReturnValue:(NSValue *)aReturnValue;
+#pragma mark -
+#pragma mark Properties
-- (id)exception;
-- (void)setException:(id)anException;
+@property(assign) NSInvocation *invocation;
+@property(assign) NSValue *returnValue;
+@property BOOL acceptsAnyArguments;
+@property(assign) id exception;
@end
return self; // super (NSProxy) has no init method
}
-- (void)dealloc
-{
- [self setInvocation:nil];
- [self setReturnValue:nil];
- [self setException:nil];
- [super dealloc];
-}
-
- (id)anyArguments
{
[self setAcceptsAnyArguments:YES];
return recordedInvocation;
}
-- (NSInvocation *)invocation
-{
- return [[invocation retain] autorelease];
-}
-
-- (void)setInvocation:(NSInvocation *)anInvocation
-{
- if (invocation != anInvocation)
- {
- [anInvocation retain];
- [invocation release];
- invocation = anInvocation;
- }
-}
-
-- (NSValue *)returnValue
-{
- return [[returnValue retain] autorelease];
-}
-
-- (void)setReturnValue:(NSValue *)aReturnValue
-{
- if (returnValue != aReturnValue)
- {
- [aReturnValue retain];
- [returnValue release];
- returnValue = aReturnValue;
- }
-}
-
-- (BOOL)acceptsAnyArguments
-{
- return acceptsAnyArguments;
-}
-
-- (void)setAcceptsAnyArguments:(BOOL)flag
-{
- acceptsAnyArguments = flag;
-}
-
-- (id)exception
-{
- return [[exception retain] autorelease];
-}
-
-- (void)setException:(id)anException
-{
- if (exception != anException)
- {
- [anException retain];
- [exception release];
- exception = anException;
- }
-}
+@synthesize invocation;
+@synthesize returnValue;
+@synthesize acceptsAnyArguments;
+@synthesize exception;
@end
#pragma mark Marker protocol
-/*! You can indicate that a class contains unit tests by marking it with the WOTest marker protocol. Although there are no selectors explicitly defined in the protocol you should at the very least ensure that your class responds to the alloc, init and release selectors (this is because before running each test method the framework instantiates a new copy of your test class by sending the alloc and init messages and afterwards sends a release message. In practice this means that any subclass of NSObject is suitable for writing test classes. You can also use classes which do not derive from the NSObject root class but you should be aware that if they do not implement alloc, init and release then WOTest will issue warnings at runtime. */
+/*! You can indicate that a class contains unit tests by marking it with the WOTest marker protocol. Although there are no selectors explicitly defined in the protocol you should at the very least ensure that your class responds to the alloc and init selectors (this is because before running each test method the framework instantiates a new copy of your test class by sending the alloc and init messages. In practice this means that any subclass of NSObject is suitable for writing test classes. You can also use classes which do not derive from the NSObject root class but you should be aware that if they do not implement alloc and init then WOTest will issue warnings at runtime. */
@protocol WOTest
@end
if (OSAtomicIncrement32Barrier(&initialized) != 1) return; // do this once only
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- (void)[[self alloc] initWithPath:__FILE__ keepComponents:3]; // will release self after running tests
- [pool release];
+ (void)[[self alloc] initWithPath:__FILE__ keepComponents:3];
+ [pool drain];
}
@end
[tester runAllTests];
[[NSNotificationCenter defaultCenter] removeObserver:self];
- [self release]; // balance alloc/init in load method
}
- (void)applicationFailedToFinishLaunching:(id)ignored
NSLog(@"WOTestBundleInjector: failed to load bundle \"%@\"", bundlePath);
}
}
- [pool release];
+ [pool drain];
}
@end
return instance;
}
-- (oneway void)release
-{
- return;
-}
-
-- (void)dealloc
-{
- [self doesNotRecognizeSelector:_cmd]; // being a singleton, officially does not support dealloc
- [super dealloc]; // this line necessary to suppress compiler warning
-}
-
-- (unsigned)retainCount
-{
- return UINT_MAX;
-}
-
-- (id)autorelease
-{
- return self;
-}
-
-- (id)retain
-{
- return self;
-}
-
// overriding this also overrides copy
- (id)copyWithZone:(NSZone *)zone
{
for (NSString *class in [self testableClasses])
[self runTestsForClassName:class] ? : failures++;
[self printTestResultsSummary];
- [pool release];
+ [pool drain];
return (failures > 0) ? NO : YES;
}
}
else if ([self isInstanceMethod:method])
{
- // class must implement alloc, init and release
+ // class must implement alloc and init
if ([NSObject WOTest_object:aClass respondsToSelector:@selector(alloc)] &&
- [NSObject WOTest_instancesOfClass:aClass respondToSelector:@selector(init)] &&
- [NSObject WOTest_instancesOfClass:aClass respondToSelector:@selector(release)])
+ [NSObject WOTest_instancesOfClass:aClass respondToSelector:@selector(init)])
{
id instance = [[aClass alloc] init];
if ([NSObject WOTest_instancesOfClass:aClass respondToSelector:preflight])
objc_msgSend(instance, [self selectorFromMethod:method]);
if ([NSObject WOTest_instancesOfClass:aClass respondToSelector:postflight])
objc_msgSend(instance, postflight);
- [instance release];
}
else
{
- [self writeError:@"Class %@ must respond to the alloc, init and release selectors",
+ [self writeError:@"Class %@ must respond to the alloc and init selectors",
NSStringFromClass(aClass)];
[self writeLastKnownLocation];
}
if (lowLevelExceptionHandlerInstalled)
[self removeLowLevelExceptionHandler];
_WOLog(@"Finished test method %@ (%.4f seconds)", method, -[startMethod timeIntervalSinceNow]);
- [pool release];
+ [pool drain];
}
}
}
}
}
- // return autoreleased, immutable NSArray
- return [NSArray arrayWithArray:classNames];
+ return [classNames copy]; // return immutable
}
- (NSArray *)testableMethodsFrom:(Class)aClass
[environment removeObjectForKey:@"DYLD_INSERT_LIBRARIES"];
[environment removeObjectForKey:@"WOTestBundleInjector"];
- NSTask *task = [[[NSTask alloc] init] autorelease];
+ NSTask *task = [[NSTask alloc] init];
[task setLaunchPath:@"/usr/bin/env"]; // use env so as to pick up PATH, if set
[task setEnvironment:environment];
NSMutableArray *arguments = [NSMutableArray arrayWithObjects:@"growlnotify",
NSDictionary *userInfo = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:kind], WOTestLowLevelExceptionKind, nil];
- return [[[self alloc] initWithName:WOTestLowLevelExceptionName reason:reason userInfo:userInfo] autorelease];
+ return [[self alloc] initWithName:WOTestLowLevelExceptionName reason:reason userInfo:userInfo];
}
+ (NSString *)nameForType:(ExceptionKind)kind
exitCode = EXIT_FAILURE;
cleanup:
- [pool release];
+ [pool drain];
return exitCode;
}