From 2eab9a2ebf1bcd8c17dad3c42e91658eea19e796 Mon Sep 17 00:00:00 2001 From: Wincent Colaiuta Date: Sat, 11 Aug 2007 15:26:18 +0200 Subject: [PATCH] Code clean-up for garbage collection I've made a pass through the codebase eliminating message sends that have effectively been turned into no-ops by the move to garbage collection (retain, release, autorelease), as well as replacing "release" messages sent to autorelease pools with "drain", replacing the alloc/init pattern with the straightforward autoreleased alternative where possible (for brevity), removing methods that will now never be meaningfully called (dealloc, release, retainCount etc), and switching some accessors over to synthesized properties where this enabled me to get rid of no-op retain, release and autorelease message sends. I also performed some minor reformatting (better wrapping and column alignment) where the already-mentioned changes touch code which would benefit from such reformatting (improved readability); there are still plenty of places in the codebase where the wrapping could be tweaked to make better use of the full 132 columns. Signed-off-by: Wincent Colaiuta --- NOTES.txt | 2 - NSMethodSignature+WOTest.m | 5 +-- NSString+WOTest.h | 4 +- NSString+WOTest.m | 13 +++--- NSValue+WOTest.m | 2 +- Tests/NSObjectTests.m | 20 +++------ Tests/WOClassMockTests.m | 6 +-- Tests/WOMockTests.m | 14 ++----- Tests/WOMultithreadedCrashTests.m | 2 +- Tests/WOObjectMockTests.m | 32 ++++----------- Tests/WOProtocolMockTests.m | 1 - Tests/WOProtocolStubTests.m | 2 - Tests/WOStubTests.m | 2 +- Tests/WOTestSelfTests.m | 45 ++++++-------------- WOLightweightRoot.h | 2 - WOLightweightRoot.m | 4 +- WOMock.h | 6 +-- WOMock.m | 41 +++++++------------ WOObjectMock.m | 2 +- WOObjectStub.m | 2 +- WOProtocolMock.m | 2 +- WOProtocolStub.m | 2 +- WOStub.h | 19 ++++----- WOStub.m | 66 ++---------------------------- WOTest.h | 2 +- WOTestApplicationTestsController.m | 5 +-- WOTestBundleInjector.m | 2 +- WOTestClass.m | 43 ++++--------------- WOTestLowLevelException.m | 2 +- WOTestRunner/WOTestRunner.m | 2 +- 30 files changed, 90 insertions(+), 262 deletions(-) diff --git a/NOTES.txt b/NOTES.txt index 10ddcf7..643d5c6 100644 --- a/NOTES.txt +++ b/NOTES.txt @@ -178,7 +178,6 @@ To illustrate how this works, consider the following example. Imagine a tool tha - (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: @@ -199,7 +198,6 @@ A far more elegant way to solve this problem is to take advantage of the dynamic [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. diff --git a/NSMethodSignature+WOTest.m b/NSMethodSignature+WOTest.m index 1fa828a..c136779 100644 --- a/NSMethodSignature+WOTest.m +++ b/NSMethodSignature+WOTest.m @@ -107,12 +107,11 @@ See also http://www.stuffonfire.com/2005/12/signaturewithobjctypes_is_stil.html #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 diff --git a/NSString+WOTest.h b/NSString+WOTest.h index 2a0901f..606a3be 100644 --- a/NSString+WOTest.h +++ b/NSString+WOTest.h @@ -36,11 +36,11 @@ void _WOLogv(NSString *format, va_list args); - (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 diff --git a/NSString+WOTest.m b/NSString+WOTest.m index aa63f02..06e0b09 100644 --- a/NSString+WOTest.m +++ b/NSString+WOTest.m @@ -31,7 +31,6 @@ void _WOLog(NSString *format, ...) { fprintf(stdout, "%s\n", [string UTF8String]); fflush(NULL); // flush all open streams (not just stdout) - [string release]; } va_end(args); } @@ -44,7 +43,6 @@ void _WOLogv(NSString *format, va_list args) { fprintf(stdout, "%s\n", [string UTF8String]); fflush(NULL); // flush all open streams (not just stdout) - [string release]; } } @@ -52,8 +50,7 @@ void _WOLogv(NSString *format, va_list args) + (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 @@ -73,9 +70,9 @@ void _WOLogv(NSString *format, va_list args) - (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]]) @@ -93,7 +90,7 @@ void _WOLogv(NSString *format, va_list args) } } } - return [NSString stringWithString:temp]; // return immutable, autoreleased + return [temp copy]; // return immutable } - (NSString *)WOTest_stringByAppendingCharacter:(unichar)character diff --git a/NSValue+WOTest.m b/NSValue+WOTest.m index 9bb24c0..d023210 100644 --- a/NSValue+WOTest.m +++ b/NSValue+WOTest.m @@ -843,7 +843,7 @@ { // 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)]]) diff --git a/Tests/NSObjectTests.m b/Tests/NSObjectTests.m index 62c3603..a1383a3 100644 --- a/Tests/NSObjectTests.m +++ b/Tests/NSObjectTests.m @@ -47,7 +47,6 @@ // 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"]; @@ -101,8 +100,7 @@ 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! @@ -112,14 +110,9 @@ //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 @@ -180,11 +173,8 @@ 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 @@ -224,7 +214,7 @@ // 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:)]); } diff --git a/Tests/WOClassMockTests.m b/Tests/WOClassMockTests.m index d53d1f6..90a2653 100644 --- a/Tests/WOClassMockTests.m +++ b/Tests/WOClassMockTests.m @@ -31,23 +31,19 @@ // 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 diff --git a/Tests/WOMockTests.m b/Tests/WOMockTests.m index 6228462..ab472ed 100644 --- a/Tests/WOMockTests.m +++ b/Tests/WOMockTests.m @@ -111,8 +111,7 @@ - (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]); @@ -123,13 +122,11 @@ // 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]); @@ -143,13 +140,11 @@ // 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]); @@ -161,13 +156,12 @@ // 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]); diff --git a/Tests/WOMultithreadedCrashTests.m b/Tests/WOMultithreadedCrashTests.m index c3483b7..e61e3d5 100644 --- a/Tests/WOMultithreadedCrashTests.m +++ b/Tests/WOMultithreadedCrashTests.m @@ -52,7 +52,7 @@ 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 - diff --git a/Tests/WOObjectMockTests.m b/Tests/WOObjectMockTests.m index f458aeb..c196db7 100644 --- a/Tests/WOObjectMockTests.m +++ b/Tests/WOObjectMockTests.m @@ -45,29 +45,17 @@ - (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 @@ -301,8 +289,6 @@ [[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 @@ -402,9 +388,9 @@ // 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) @@ -420,8 +406,8 @@ // 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) @@ -455,7 +441,7 @@ 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 diff --git a/Tests/WOProtocolMockTests.m b/Tests/WOProtocolMockTests.m index 30bf091..d159eb9 100644 --- a/Tests/WOProtocolMockTests.m +++ b/Tests/WOProtocolMockTests.m @@ -35,7 +35,6 @@ // should throw for NULL protocol WOProtocolMock *mock = [WOProtocolMock alloc]; WO_TEST_THROWS([mock initWithProtocol:NULL]); - [mock release]; } - (void)testMethodSignatureForSelector diff --git a/Tests/WOProtocolStubTests.m b/Tests/WOProtocolStubTests.m index d2400ba..a5544b1 100644 --- a/Tests/WOProtocolStubTests.m +++ b/Tests/WOProtocolStubTests.m @@ -35,12 +35,10 @@ // 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 diff --git a/Tests/WOStubTests.m b/Tests/WOStubTests.m index 076ab51..ec70ed2 100644 --- a/Tests/WOStubTests.m +++ b/Tests/WOStubTests.m @@ -25,7 +25,7 @@ - (void)testMatchesInvocation { - WOStub *stub = [[[WOStub alloc] init] autorelease]; + WOStub *stub = [[WOStub alloc] init]; // raises if sent nil WO_TEST_THROWS([stub matchesInvocation:nil]); diff --git a/Tests/WOTestSelfTests.m b/Tests/WOTestSelfTests.m index d31cb3c..09aed92 100644 --- a/Tests/WOTestSelfTests.m +++ b/Tests/WOTestSelfTests.m @@ -39,31 +39,19 @@ NSMutableArray *WOEmptyInstanceMethodInvocations; + (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 @@ -115,11 +103,6 @@ NSMutableArray *WOEmptyInstanceMethodInvocations; 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 @@ -1048,7 +1031,7 @@ NSMutableArray *WOEmptyInstanceMethodInvocations; 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]); @@ -1134,13 +1117,13 @@ NSMutableArray *WOEmptyInstanceMethodInvocations; 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"); @@ -1891,16 +1874,12 @@ NSMutableArray *WOEmptyInstanceMethodInvocations; - (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 @@ -1911,7 +1890,7 @@ NSMutableArray *WOEmptyInstanceMethodInvocations; - (void)makeCocoaThrowException { // should throw NSInvalidArgumentException - (void)[[[NSString alloc] initWithFormat:nil] autorelease]; + (void)[[NSString alloc] initWithFormat:nil]; } - (void)makeCocoaThrowNSRangeException diff --git a/WOLightweightRoot.h b/WOLightweightRoot.h index 64b4d12..aa75af9 100644 --- a/WOLightweightRoot.h +++ b/WOLightweightRoot.h @@ -31,8 +31,6 @@ + (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; diff --git a/WOLightweightRoot.m b/WOLightweightRoot.m index 6f8a0ea..a29c799 100644 --- a/WOLightweightRoot.m +++ b/WOLightweightRoot.m @@ -38,9 +38,9 @@ return class_createInstance(class, 0); } -- (void)dealloc +- (void)exampleMethod { - free(self); + // do nothing } - forward:(SEL)sel :(marg_list)args diff --git a/WOMock.h b/WOMock.h index de270c8..15f8e5d 100644 --- a/WOMock.h +++ b/WOMock.h @@ -102,7 +102,7 @@ The mocked class must at least implement the NSObject method, instanceMethodSign 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 all 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 all 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. @@ -144,7 +144,7 @@ See the WOMockTests class in WOTestSelfTests for usage examples. */ - (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]; @@ -176,7 +176,7 @@ If the selector takes arguments then the arguments passed to the mock must match /*! \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 - diff --git a/WOMock.m b/WOMock.m index 20704c0..e4ddae7 100644 --- a/WOMock.m +++ b/WOMock.m @@ -74,10 +74,7 @@ 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 @@ -87,9 +84,7 @@ 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 @@ -99,35 +94,27 @@ 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 diff --git a/WOObjectMock.m b/WOObjectMock.m index 5dc4c27..f78ae43 100644 --- a/WOObjectMock.m +++ b/WOObjectMock.m @@ -36,7 +36,7 @@ { 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 diff --git a/WOObjectStub.m b/WOObjectStub.m index 2dfb11a..f0cf06f 100644 --- a/WOObjectStub.m +++ b/WOObjectStub.m @@ -35,7 +35,7 @@ + (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 diff --git a/WOProtocolMock.m b/WOProtocolMock.m index 55a5ef2..c742925 100644 --- a/WOProtocolMock.m +++ b/WOProtocolMock.m @@ -48,7 +48,7 @@ NSString *WOStringFromProtocol(Protocol *aProtocol) + (id)mockForProtocol:(Protocol *)aProtocol { NSParameterAssert(aProtocol != NULL); - return [[[self alloc] initWithProtocol:aProtocol] autorelease]; + return [[self alloc] initWithProtocol:aProtocol]; } - (id)initWithProtocol:(Protocol *)aProtocol diff --git a/WOProtocolStub.m b/WOProtocolStub.m index f01cf20..59a388d 100644 --- a/WOProtocolStub.m +++ b/WOProtocolStub.m @@ -42,7 +42,7 @@ + (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. */ diff --git a/WOStub.h b/WOStub.h index 188fe49..bb5c643 100644 --- a/WOStub.h +++ b/WOStub.h @@ -48,7 +48,7 @@ /*! 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 - @@ -60,20 +60,15 @@ #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 diff --git a/WOStub.m b/WOStub.m index 5c6cba1..197342d 100644 --- a/WOStub.m +++ b/WOStub.m @@ -40,14 +40,6 @@ 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]; @@ -207,59 +199,9 @@ 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 diff --git a/WOTest.h b/WOTest.h index 8ff81f2..2353aad 100644 --- a/WOTest.h +++ b/WOTest.h @@ -25,7 +25,7 @@ #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 diff --git a/WOTestApplicationTestsController.m b/WOTestApplicationTestsController.m index e4b6366..74a7950 100644 --- a/WOTestApplicationTestsController.m +++ b/WOTestApplicationTestsController.m @@ -37,8 +37,8 @@ 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 @@ -83,7 +83,6 @@ extern NSString *NSApplicationDidFinishLaunchingNotification; [tester runAllTests]; [[NSNotificationCenter defaultCenter] removeObserver:self]; - [self release]; // balance alloc/init in load method } - (void)applicationFailedToFinishLaunching:(id)ignored diff --git a/WOTestBundleInjector.m b/WOTestBundleInjector.m index 9f45db5..6d12ea7 100644 --- a/WOTestBundleInjector.m +++ b/WOTestBundleInjector.m @@ -62,7 +62,7 @@ NSLog(@"WOTestBundleInjector: failed to load bundle \"%@\"", bundlePath); } } - [pool release]; + [pool drain]; } @end diff --git a/WOTestClass.m b/WOTestClass.m index 8f21e2e..9146ff0 100644 --- a/WOTestClass.m +++ b/WOTestClass.m @@ -242,32 +242,6 @@ OSStatus WOLowLevelExceptionHandler(ExceptionInformation *theException) 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 { @@ -359,7 +333,7 @@ OSStatus WOLowLevelExceptionHandler(ExceptionInformation *theException) for (NSString *class in [self testableClasses]) [self runTestsForClassName:class] ? : failures++; [self printTestResultsSummary]; - [pool release]; + [pool drain]; return (failures > 0) ? NO : YES; } @@ -440,10 +414,9 @@ jump_point: } 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]) @@ -451,11 +424,10 @@ jump_point: 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]; } @@ -491,7 +463,7 @@ jump_point: if (lowLevelExceptionHandlerInstalled) [self removeLowLevelExceptionHandler]; _WOLog(@"Finished test method %@ (%.4f seconds)", method, -[startMethod timeIntervalSinceNow]); - [pool release]; + [pool drain]; } } } @@ -630,8 +602,7 @@ jump_point: } } - // return autoreleased, immutable NSArray - return [NSArray arrayWithArray:classNames]; + return [classNames copy]; // return immutable } - (NSArray *)testableMethodsFrom:(Class)aClass @@ -763,7 +734,7 @@ jump_point: [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", diff --git a/WOTestLowLevelException.m b/WOTestLowLevelException.m index 6e01b61..694b1d8 100644 --- a/WOTestLowLevelException.m +++ b/WOTestLowLevelException.m @@ -33,7 +33,7 @@ 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 diff --git a/WOTestRunner/WOTestRunner.m b/WOTestRunner/WOTestRunner.m index 16ad17f..6c1d730 100644 --- a/WOTestRunner/WOTestRunner.m +++ b/WOTestRunner/WOTestRunner.m @@ -171,7 +171,7 @@ int main(int argc, const char *argv[]) exitCode = EXIT_FAILURE; cleanup: - [pool release]; + [pool drain]; return exitCode; } -- 2.37.1