diff options
author | gtm.daemon <gtm.daemon@7dc7ac4e-7543-0410-b95c-c1676fc8e2a3> | 2010-04-15 17:31:09 +0000 |
---|---|---|
committer | gtm.daemon <gtm.daemon@7dc7ac4e-7543-0410-b95c-c1676fc8e2a3> | 2010-04-15 17:31:09 +0000 |
commit | 2ddb245fac99802e63742c21f7da0d499e9cecf6 (patch) | |
tree | 3eebbf1aeed8269c8b14de81e8b680e784b8709b /Foundation | |
parent | 30ac0ff87b594d7bca3a5cc2789ca415840ea0b1 (diff) |
[Author: dmaclach]
refactor GTMUnitTestingUtilities into GTMAppKitUnitTestingUtilties and GTMFoundationUnitTestingUtilities.
convert GTMSignalHandler over to using new runloop routines
fix bug in GTMSignalHandler API with GC where releasing it wasn't sufficient to stop it listening.
R=thomasvl
DELTA=1227 (638 added, 566 deleted, 23 changed)
Diffstat (limited to 'Foundation')
-rw-r--r-- | Foundation/GTMSignalHandler.h | 3 | ||||
-rw-r--r-- | Foundation/GTMSignalHandler.m | 18 | ||||
-rw-r--r-- | Foundation/GTMSignalHandlerTest.m | 52 |
3 files changed, 45 insertions, 28 deletions
diff --git a/Foundation/GTMSignalHandler.h b/Foundation/GTMSignalHandler.h index b1c7c2f..6297197 100644 --- a/Foundation/GTMSignalHandler.h +++ b/Foundation/GTMSignalHandler.h @@ -70,4 +70,7 @@ target:(id)target action:(SEL)action; +// Invalidates the handler so that it isn't listening anymore. +- (void)invalidate; + @end diff --git a/Foundation/GTMSignalHandler.m b/Foundation/GTMSignalHandler.m index dd67269..677c10a 100644 --- a/Foundation/GTMSignalHandler.m +++ b/Foundation/GTMSignalHandler.m @@ -44,7 +44,6 @@ static CFSocketRef gRunLoopSocket = NULL; - (void)notify; - (void)addFileDescriptorMonitor:(int)fd; - (void)registerWithKQueue; -- (void)unregisterWithKQueue; @end @@ -88,19 +87,17 @@ static CFSocketRef gRunLoopSocket = NULL; } #if GTM_SUPPORT_GC + - (void)finalize { - [self unregisterWithKQueue]; - + [self invalidate]; [super finalize]; - } + #endif - (void)dealloc { - [self unregisterWithKQueue]; - + [self invalidate]; [super dealloc]; - } // Cribbed from Advanced Mac OS X Programming. @@ -181,7 +178,7 @@ static void SocketCallBack(CFSocketRef socketref, CFSocketCallBackType type, } -- (void)unregisterWithKQueue { +- (void)invalidate { // Short-circuit cases where we didn't actually register a kqueue event. if (signo_ == 0) return; if (action_ == nil) return; @@ -193,7 +190,10 @@ static void SocketCallBack(CFSocketRef socketref, CFSocketCallBackType type, if (kevent(gSignalKQueueFileDescriptor, &filter, 1, NULL, 0, &noWait) != 0) { _GTMDevLog(@"could not remove event for signal %d. Errno %d", signo_, errno); // COV_NF_LINE } - + + // Set action_ to nil so that if invalidate is called on us twice, + // nothing happens. + action_ = nil; } - (void)notify { diff --git a/Foundation/GTMSignalHandlerTest.m b/Foundation/GTMSignalHandlerTest.m index a0019f3..191d67f 100644 --- a/Foundation/GTMSignalHandlerTest.m +++ b/Foundation/GTMSignalHandlerTest.m @@ -19,19 +19,22 @@ #import "GTMSenTestCase.h" #import "GTMSignalHandler.h" #import "GTMUnitTestDevLog.h" +#import "GTMFoundationUnitTestingUtilities.h" @interface GTMSignalHandlerTest : GTMTestCase @end -@interface SignalCounter : NSObject { +@interface SignalCounter : NSObject<GTMUnitTestingRunLoopContext> { @public int signalCount_; int lastSeenSignal_; + BOOL shouldStop_; } - (int)count; - (int)lastSeen; - (void)countSignal:(int)signo; + (id)signalCounter; +- (void)resetShouldStop; @end // SignalCounter @implementation SignalCounter @@ -48,17 +51,21 @@ - (void)countSignal:(int)signo { signalCount_++; lastSeenSignal_ = signo; + shouldStop_ = YES; } -@end -@implementation GTMSignalHandlerTest +- (BOOL)shouldStop { + return shouldStop_; +} -// Spin the run loop so that the kqueue event notifications will get delivered. -- (void)giveSomeLove { - NSDate *endTime = [NSDate dateWithTimeIntervalSinceNow:0.5]; - [[NSRunLoop currentRunLoop] runUntilDate:endTime]; +- (void)resetShouldStop { + shouldStop_ = NO; } +@end + +@implementation GTMSignalHandlerTest + - (void)testNillage { GTMSignalHandler *handler; @@ -81,23 +88,28 @@ SignalCounter *counter = [SignalCounter signalCounter]; STAssertNotNil(counter, nil); - GTMSignalHandler *handler = [[GTMSignalHandler alloc] - initWithSignal:SIGWINCH - target:counter - action:@selector(countSignal:)]; + GTMSignalHandler *handler = [[[GTMSignalHandler alloc] + initWithSignal:SIGWINCH + target:counter + action:@selector(countSignal:)] + autorelease]; STAssertNotNil(handler, nil); raise(SIGWINCH); - [self giveSomeLove]; + + NSRunLoop *rl = [NSRunLoop currentRunLoop]; + [rl gtm_runUpToSixtySecondsWithContext:counter]; STAssertEquals([counter count], 1, nil); STAssertEquals([counter lastSeen], SIGWINCH, nil); - + [counter resetShouldStop]; + raise(SIGWINCH); - [self giveSomeLove]; + [rl gtm_runUpToSixtySecondsWithContext:counter]; STAssertEquals([counter count], 2, nil); STAssertEquals([counter lastSeen], SIGWINCH, nil); - + [counter resetShouldStop]; + // create a second one to make sure we're seding data where we want SignalCounter *counter2 = [SignalCounter signalCounter]; STAssertNotNil(counter2, nil); @@ -106,19 +118,20 @@ action:@selector(countSignal:)] autorelease]; raise(SIGUSR1); - [self giveSomeLove]; + [rl gtm_runUpToSixtySecondsWithContext:counter2]; STAssertEquals([counter count], 2, nil); STAssertEquals([counter lastSeen], SIGWINCH, nil); STAssertEquals([counter2 count], 1, nil); STAssertEquals([counter2 lastSeen], SIGUSR1, nil); - [handler release]; + [handler invalidate]; // The signal is still ignored (so we shouldn't die), but the // the handler method should not get called. raise(SIGWINCH); - + [rl runUntilDate:[NSDate dateWithTimeIntervalSinceNow:.2]]; + STAssertEquals([counter count], 2, nil); STAssertEquals([counter lastSeen], SIGWINCH, nil); STAssertEquals([counter2 count], 1, nil); @@ -135,7 +148,8 @@ action:NULL] autorelease]; raise(SIGUSR1); - [self giveSomeLove]; + NSRunLoop *rl = [NSRunLoop currentRunLoop]; + [rl runUntilDate:[NSDate dateWithTimeIntervalSinceNow:.2]]; STAssertEquals([counter count], 0, nil); } |