aboutsummaryrefslogtreecommitdiff
path: root/Foundation
diff options
context:
space:
mode:
authorGravatar gtm.daemon <gtm.daemon@7dc7ac4e-7543-0410-b95c-c1676fc8e2a3>2009-03-13 03:45:21 +0000
committerGravatar gtm.daemon <gtm.daemon@7dc7ac4e-7543-0410-b95c-c1676fc8e2a3>2009-03-13 03:45:21 +0000
commitef636da89c2c29f263df52954f7258d1f678d931 (patch)
treee302aa8de6a955fef0cfdc7d4e6da10e962eeaf0 /Foundation
parent398b1c8b28e2d542d632c6502aa0a498540edafc (diff)
[Author: dmaclach]
Fixes up the transient root proxy support so that it's faster and doesn't leak. It also adds the missing timeouts, and now works with generic NSPorts instead of just socket ports. I will update the release notes, and change the file names over from RootSocket to RootPort once these gets approved. DELTA=336 (95 added, 110 deleted, 131 changed) R=krisr,thomasvl
Diffstat (limited to 'Foundation')
-rw-r--r--Foundation/GTMTransientRootProxy.m11
-rw-r--r--Foundation/GTMTransientRootProxyTest.m141
-rw-r--r--Foundation/GTMTransientRootSocketProxy.h38
-rw-r--r--Foundation/GTMTransientRootSocketProxy.m51
-rw-r--r--Foundation/GTMTransientRootSocketProxyTest.m213
5 files changed, 220 insertions, 234 deletions
diff --git a/Foundation/GTMTransientRootProxy.m b/Foundation/GTMTransientRootProxy.m
index 33be603..04591d3 100644
--- a/Foundation/GTMTransientRootProxy.m
+++ b/Foundation/GTMTransientRootProxy.m
@@ -89,6 +89,8 @@
- (void)dealloc {
[self releaseRealProxy];
+ [registeredName_ release];
+ [host_ release];
[super dealloc];
}
@@ -135,13 +137,13 @@
|| [exName isEqualToString:NSFailedAuthenticationException]
|| [exName isEqualToString:NSPortSendException]
|| [exName isEqualToString:NSPortReceiveException]) {
- [self releaseRealProxy];
+ [self releaseRealProxy]; // COV_NF_LINE
} else {
// If the exception was any other type (commonly
// NSInvalidArgumentException) then we'll just re-throw it to the caller.
@throw;
}
- }
+ } // COV_NF_LINE
}
@end
@@ -160,7 +162,8 @@
if (realProxy_) return realProxy_;
NSConnection *conn = [self makeConnection];
-
+ [conn setRequestTimeout:requestTimeout_];
+ [conn setReplyTimeout:replyTimeout_];
@try {
// Try to get the root proxy for this connection's vended object.
realProxy_ = [conn rootProxy];
@@ -169,9 +172,11 @@
// specified by the timeout above. This may happen, for example, if the
// server process is stopped (via SIGSTOP). We'll just ignore this, and
// try again at the next message.
+ [conn invalidate];
return nil;
}
if (!realProxy_) {
+ [conn invalidate];
// Again, no change in connection status
return nil;
}
diff --git a/Foundation/GTMTransientRootProxyTest.m b/Foundation/GTMTransientRootProxyTest.m
index 063f33f..70b69a1 100644
--- a/Foundation/GTMTransientRootProxyTest.m
+++ b/Foundation/GTMTransientRootProxyTest.m
@@ -21,10 +21,18 @@
#import "GTMUnitTestDevLog.h"
#define kDefaultTimeout 5.0
-#define kServerShuttingDownNotification @"serverShuttingDown"
// === Start off declaring some auxillary data structures ===
static NSString *const kTestServerName = @"gtm_test_server";
+static NSString *const kGTMTransientRootNameKey = @"GTMTransientRootNameKey";
+static NSString *const kGTMTransientRootLockKey = @"GTMTransientRootLockKey";
+
+enum {
+ kGTMTransientThreadConditionStarting = 777,
+ kGTMTransientThreadConditionStarted,
+ kGTMTransientThreadConditionQuitting,
+ kGTMTransientThreadConditionQuitted
+};
// The @protocol that we'll use for testing with.
@protocol DOTestProtocol
@@ -34,50 +42,44 @@ static NSString *const kTestServerName = @"gtm_test_server";
@end
// The "server" we'll use to test the DO connection. This server will implement
-// our test protocol, and it will run in a separate thread from the main
+// our test protocol, and it will run in a separate thread from the main
// unit testing thread, so the DO requests can be serviced.
@interface DOTestServer : NSObject <DOTestProtocol> {
- @private
- BOOL quit_;
}
-- (void)runThread:(NSString *)serverName;
-- (void)shutdownServer;
+- (void)runThread:(NSDictionary *)args;
@end
@implementation DOTestServer
-- (BOOL)shouldServerQuit {
- BOOL returnValue = NO;
- @synchronized(self) {
- returnValue = quit_;
- }
- return returnValue;
-}
-
-- (void)runThread:(NSString *)serverName {
+- (void)runThread:(NSDictionary *)args {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-
- NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
- quit_ = NO;
+ NSConditionLock *lock = [args objectForKey:kGTMTransientRootLockKey];
+ NSString *serverName = [args objectForKey:kGTMTransientRootNameKey];
+ NSDate *future = [NSDate dateWithTimeIntervalSinceNow:kDefaultTimeout];
+ if(![lock lockWhenCondition:kGTMTransientThreadConditionStarting
+ beforeDate:future]) {
+ _GTMDevLog(@"Unable to acquire lock in runThread! This is BAD!");
+ [pool drain];
+ [NSThread exit];
+ }
NSConnection *conn = [NSConnection defaultConnection];
[conn setRootObject:self];
if (![conn registerName:serverName]) {
_GTMDevLog(@"Failed to register DO root object with name '%@'",
serverName);
- // We hit an error, we are shutting down.
- quit_ = YES;
+ [pool drain];
+ [NSThread exit];
}
-
- while (![self shouldServerQuit]) {
- NSDate* runUntil = [NSDate dateWithTimeIntervalSinceNow:0.5];
+ [lock unlockWithCondition:kGTMTransientThreadConditionStarted];
+ while (![lock tryLockWhenCondition:kGTMTransientThreadConditionQuitting]) {
+ NSDate* runUntil = [NSDate dateWithTimeIntervalSinceNow:0.1];
[[NSRunLoop currentRunLoop] runUntilDate:runUntil];
}
-
- [conn invalidate];
- [conn release];
- [nc postNotificationName:kServerShuttingDownNotification object:nil];
+ [conn setRootObject:nil];
+ [conn registerName:nil];
[pool drain];
+ [lock unlockWithCondition:kGTMTransientThreadConditionQuitted];
}
- (oneway void)doOneWayVoid {
@@ -87,12 +89,6 @@ static NSString *const kTestServerName = @"gtm_test_server";
return @"TestString";
}
-- (void)shutdownServer {
- @synchronized(self) {
- quit_ = YES;
- }
-}
-
- (void)throwException {
[NSException raise:@"testingException" format:@"for the unittest"];
}
@@ -104,46 +100,33 @@ static NSString *const kTestServerName = @"gtm_test_server";
@interface GTMTransientRootProxyTest : GTMTestCase {
@private
DOTestServer *server_;
- BOOL serverOffline_;
+ NSConditionLock *syncLock_;
}
@end
@implementation GTMTransientRootProxyTest
-- (void)serverIsShuttingDown:(NSNotification *)note {
- @synchronized(self) {
- serverOffline_ = YES;
- }
-}
-
-- (BOOL)serverStatus {
- BOOL returnValue = NO;
- @synchronized(self) {
- returnValue = serverOffline_;
- }
- return returnValue;
-}
-
- (void)testTransientRootProxy {
- // Register for server notifications
- NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
- [nc addObserver:self
- selector:@selector(serverIsShuttingDown:)
- name:kServerShuttingDownNotification
- object:nil];
- serverOffline_ = NO;
-
// Setup our server and create a unqiue server name every time we run
NSTimeInterval timeStamp = [[NSDate date] timeIntervalSinceReferenceDate];
NSString *serverName =
[NSString stringWithFormat:@"%@_%f", kTestServerName, timeStamp];
-
server_ = [[[DOTestServer alloc] init] autorelease];
+ syncLock_ = [[[NSConditionLock alloc]
+ initWithCondition:kGTMTransientThreadConditionStarting]
+ autorelease];
+ NSDictionary *args = [NSDictionary dictionaryWithObjectsAndKeys:
+ syncLock_, kGTMTransientRootLockKey,
+ serverName, kGTMTransientRootNameKey,
+ nil];
[NSThread detachNewThreadSelector:@selector(runThread:)
toTarget:server_
- withObject:serverName];
- // Sleep for 1 second to give the new thread time to set stuff up
- [NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:1]];
+ withObject:args];
+ NSDate *future = [NSDate dateWithTimeIntervalSinceNow:kDefaultTimeout];
+ STAssertTrue([syncLock_ lockWhenCondition:kGTMTransientThreadConditionStarted
+ beforeDate:future],
+ @"Unable to start thread");
+ [syncLock_ unlockWithCondition:kGTMTransientThreadConditionStarted];
GTMTransientRootProxy<DOTestProtocol> *failProxy =
[GTMTransientRootProxy rootProxyWithRegisteredName:nil
@@ -161,7 +144,7 @@ static NSString *const kTestServerName = @"gtm_test_server";
STAssertNil(failProxy, @"should have failed w/o a protocol");
failProxy = [[[GTMTransientRootProxy alloc] init] autorelease];
STAssertNil(failProxy, @"should have failed just calling init");
-
+
GTMTransientRootProxy<DOTestProtocol> *proxy =
[GTMTransientRootProxy rootProxyWithRegisteredName:serverName
host:nil
@@ -169,9 +152,8 @@ static NSString *const kTestServerName = @"gtm_test_server";
requestTimeout:kDefaultTimeout
replyTimeout:kDefaultTimeout];
- STAssertEqualObjects([proxy doReturnStringBycopy],
- @"TestString", @"proxy should have returned "
- @"'TestString'");
+ STAssertEqualObjects([proxy doReturnStringBycopy], @"TestString",
+ @"proxy should have returned 'TestString'");
// Redo the *exact* same test to make sure we can have multiple instances
// in the same app.
@@ -205,7 +187,8 @@ static NSString *const kTestServerName = @"gtm_test_server";
} @catch (id ex) {
e = ex;
}
- STAssertNil(e, @"The GTMRootProxyCatchAll did not catch the exception: %@.", e);
+ STAssertNil(e, @"The GTMRootProxyCatchAll did not catch the exception: %@.",
+ e);
proxy =
[GTMTransientRootProxy rootProxyWithRegisteredName:@"FAKE_SERVER"
@@ -218,20 +201,28 @@ static NSString *const kTestServerName = @"gtm_test_server";
STAssertFalse([proxy isConnected], @"the proxy shouldn't be connected due to "
@"the fake server");
- [server_ shutdownServer];
+ // Now set up a proxy, and then kill our server. We put a super short time
+ // out on it, because we are expecting it to fail.
+ proxy =
+ [GTMTransientRootProxy rootProxyWithRegisteredName:serverName
+ host:nil
+ protocol:@protocol(DOTestProtocol)
+ requestTimeout:0.01
+ replyTimeout:0.01];
+ [syncLock_ tryLockWhenCondition:kGTMTransientThreadConditionStarted];
+ [syncLock_ unlockWithCondition:kGTMTransientThreadConditionQuitting];
// Wait for the server to shutdown so we clean up nicely.
// The max amount of time we will wait until we abort this test.
- id timeout = [NSDate dateWithTimeIntervalSinceNow:30.0];
- while (![self serverStatus] &&
- ([[NSDate date] compare:timeout] != NSOrderedDescending)) {
- NSDate *runUntil = [NSDate dateWithTimeIntervalSinceNow:2.0];
- [[NSRunLoop currentRunLoop] runUntilDate:runUntil];
- }
-
+ NSDate *timeout = [NSDate dateWithTimeIntervalSinceNow:kDefaultTimeout];
// The server did not shutdown and we want to capture this as an error
- STAssertTrue([self serverStatus], @"The server did not shutdown gracefully "
- @"before the timeout.");
+ STAssertTrue([syncLock_ lockWhenCondition:kGTMTransientThreadConditionQuitted
+ beforeDate:timeout],
+ @"The server did not shutdown gracefully before the timeout.");
+ [syncLock_ unlockWithCondition:kGTMTransientThreadConditionQuitted];
+
+ // This should fail gracefully because the server is dead.
+ STAssertNil([proxy doReturnStringBycopy], @"proxy should have returned nil");
}
@end
diff --git a/Foundation/GTMTransientRootSocketProxy.h b/Foundation/GTMTransientRootSocketProxy.h
index ddf08fe..9213ac5 100644
--- a/Foundation/GTMTransientRootSocketProxy.h
+++ b/Foundation/GTMTransientRootSocketProxy.h
@@ -19,24 +19,32 @@
#import <Foundation/Foundation.h>
#import "GTMTransientRootProxy.h"
-@interface GTMTransientRootSocketProxy : GTMTransientRootProxy {
+@interface GTMTransientRootPortProxy : GTMTransientRootProxy {
@private
- NSSocketPort *port_;
+ NSPort *receivePort_;
+ NSPort *sendPort_;
}
-// Returns an autoreleased instance
-+ (id)rootProxyWithSocketPort:(NSSocketPort *)port
- protocol:(Protocol *)protocol
- requestTimeout:(NSTimeInterval)requestTimeout
- replyTimeout:(NSTimeInterval)replyTimeout;
+// Returns an autoreleased instance. See below for details on args.
++ (id)rootProxyWithReceivePort:(NSPort *)receivePort
+ sendPort:(NSPort *)sendPort
+ protocol:(Protocol *)protocol
+ requestTimeout:(NSTimeInterval)requestTimeout
+ replyTimeout:(NSTimeInterval)replyTimeout;
-// This function will return a GTMTransientRootProxy that is using NSSocketPorts
-// for the connection. The |port| argument must be allocated and configured by
-// the caller.
-//
-- (id)initWithSocketPort:(NSSocketPort *)port
- protocol:(Protocol *)protocol
- requestTimeout:(NSTimeInterval)requestTimeout
- replyTimeout:(NSTimeInterval)replyTimeout;
+// This function will return a GTMTransientRootProxy that is using NSPorts
+// for the connection. The |receivePort| and |sendPort| conventions
+// follow the same conventions as -[NSConnection initWithReceivePort:sendPort:].
+// Note that due to Radar 6676818 "NSConnection leaks when initialized with nil
+// sendPort" that you will leak a connection if you pass in "nil" for your
+// sendPort if you are using NSPorts (mach or socket) to communicate between
+// threads. The leak occurs on 10.5.6, and SL 10A286. This simple answer
+// is just to always use two ports to communicate. Check out the test to see
+// how we do cross thread communication.
+- (id)initWithReceivePort:(NSPort *)receivePort
+ sendPort:(NSPort *)sendPort
+ protocol:(Protocol *)protocol
+ requestTimeout:(NSTimeInterval)requestTimeout
+ replyTimeout:(NSTimeInterval)replyTimeout;
@end
diff --git a/Foundation/GTMTransientRootSocketProxy.m b/Foundation/GTMTransientRootSocketProxy.m
index a41938e..5c7e11e 100644
--- a/Foundation/GTMTransientRootSocketProxy.m
+++ b/Foundation/GTMTransientRootSocketProxy.m
@@ -19,33 +19,35 @@
#import "GTMTransientRootSocketProxy.h"
#import "GTMObjC2Runtime.h"
-@interface GTMTransientRootSocketProxy (ProtectedMethods)
-// Returns an NSConnection for NSSocketPorts. This method overrides the one in
+@interface GTMTransientRootPortProxy (ProtectedMethods)
+// Returns an NSConnection for NSPorts. This method overrides the one in
// the GTMTransientRootProxy which allows us to create a connection with a
-// NSSocketPort.
+// NSPort.
//
- (NSConnection *)makeConnection;
@end
+@implementation GTMTransientRootPortProxy
-@implementation GTMTransientRootSocketProxy
-
-+ (id)rootProxyWithSocketPort:(NSSocketPort *)port
- protocol:(Protocol *)protocol
- requestTimeout:(NSTimeInterval)requestTimeout
- replyTimeout:(NSTimeInterval)replyTimeout {
- return [[[self alloc] initWithSocketPort:port
- protocol:protocol
- requestTimeout:requestTimeout
- replyTimeout:replyTimeout] autorelease];
++ (id)rootProxyWithReceivePort:(NSPort *)receivePort
+ sendPort:(NSPort *)sendPort
+ protocol:(Protocol *)protocol
+ requestTimeout:(NSTimeInterval)requestTimeout
+ replyTimeout:(NSTimeInterval)replyTimeout {
+ return [[[self alloc] initWithReceivePort:receivePort
+ sendPort:sendPort
+ protocol:protocol
+ requestTimeout:requestTimeout
+ replyTimeout:replyTimeout] autorelease];
}
-- (id)initWithSocketPort:(NSSocketPort *)port
- protocol:(Protocol *)protocol
- requestTimeout:(NSTimeInterval)requestTimeout
- replyTimeout:(NSTimeInterval)replyTimeout {
- if (!port || !protocol) {
+- (id)initWithReceivePort:(NSPort *)receivePort
+ sendPort:(NSPort *)sendPort
+ protocol:(Protocol *)protocol
+ requestTimeout:(NSTimeInterval)requestTimeout
+ replyTimeout:(NSTimeInterval)replyTimeout {
+ if ((!sendPort && !receivePort) || !protocol) {
[self release];
return nil;
}
@@ -53,23 +55,26 @@
requestTimeout_ = requestTimeout;
replyTimeout_ = replyTimeout;
- port_ = [port retain];
-
+ receivePort_ = [receivePort retain];
+ sendPort_ = [sendPort retain];
+
protocol_ = protocol; // Protocols can't be retained
return self;
}
- (void)dealloc {
- [port_ release];
+ [receivePort_ release];
+ [sendPort_ release];
[super dealloc];
}
@end
-@implementation GTMTransientRootSocketProxy (ProtectedMethods)
+@implementation GTMTransientRootPortProxy (ProtectedMethods)
- (NSConnection *)makeConnection {
- return [NSConnection connectionWithReceivePort:nil sendPort:port_];
+ return [NSConnection connectionWithReceivePort:receivePort_
+ sendPort:sendPort_];
}
@end
diff --git a/Foundation/GTMTransientRootSocketProxyTest.m b/Foundation/GTMTransientRootSocketProxyTest.m
index dcb5cff..fbc8511 100644
--- a/Foundation/GTMTransientRootSocketProxyTest.m
+++ b/Foundation/GTMTransientRootSocketProxyTest.m
@@ -1,5 +1,5 @@
//
-// GTMTransientRootSocketProxyTest.m
+// GTMTransientRootPortProxyTest.m
//
// Copyright 2006-2009 Google Inc.
//
@@ -19,17 +19,19 @@
#import "GTMSenTestCase.h"
#import "GTMTransientRootSocketProxy.h"
-// Needed to get the socket port.
-#import <netinet/in.h>
-#import <arpa/inet.h>
-
#define kDefaultTimeout 5.0
-#define kServerShuttingDownNotification @"serverShuttingDown"
+
+enum {
+ kGTMTransientThreadConditionStarting = 777,
+ kGTMTransientThreadConditionStarted,
+ kGTMTransientThreadConditionQuitting,
+ kGTMTransientThreadConditionQuitted
+};
// === Start off declaring some auxillary data structures ===
// The @protocol that we'll use for testing with.
-@protocol DOSocketTestProtocol
+@protocol DOPortTestProtocol
- (oneway void)doOneWayVoid;
- (bycopy NSString *)doReturnStringBycopy;
@end
@@ -37,59 +39,54 @@
// The "server" we'll use to test the DO connection. This server will implement
// our test protocol, and it will run in a separate thread from the main
// unit testing thread, so the DO requests can be serviced.
-@interface DOSocketTestServer : NSObject <DOSocketTestProtocol> {
-@private
- BOOL quit_;
- unsigned short listeningPort_;
+@interface DOPortTestServer : NSObject <DOPortTestProtocol> {
+ @private
+ NSPort *clientSendPort_;
+ NSPort *clientReceivePort_;
}
-- (void)runThread:(id)ignore;
-- (unsigned short)listeningPort;
-- (void)shutdownServer;
+- (void)runThread:(NSConditionLock *)lock;
+- (NSPort *)clientSendPort;
+- (NSPort *)clientReceivePort;
@end
-@implementation DOSocketTestServer
+@implementation DOPortTestServer
-- (BOOL)shouldServerQuit {
- BOOL returnValue = NO;
- @synchronized(self) {
- returnValue = quit_;
- }
- return returnValue;
-}
-
-- (void)runThread:(id)ignore {
+- (void)runThread:(NSConditionLock *)lock {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ NSDate *future = [NSDate dateWithTimeIntervalSinceNow:kDefaultTimeout];
+ if(![lock lockWhenCondition:kGTMTransientThreadConditionStarting
+ beforeDate:future]) {
+ _GTMDevLog(@"Unable to acquire lock in runThread! This is BAD!");
+ [pool drain];
+ [NSThread exit];
+ }
- NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
- quit_ = NO;
-
- NSSocketPort *serverPort = [[NSSocketPort alloc] init];
-
- // We will need the port so we can hand if off to the client
- // The structure will get us this information.
- struct sockaddr_in addrIn =
- *(struct sockaddr_in *)[[serverPort address] bytes];
- listeningPort_ = htons(addrIn.sin_port);
+ clientSendPort_ = [NSPort port];
+ clientReceivePort_ = [NSPort port];
- NSConnection *conn = [NSConnection connectionWithReceivePort:serverPort
- sendPort:nil];
- // Port is retained by the NSConnection
- [serverPort release];
+ NSConnection *conn
+ = [[NSConnection alloc] initWithReceivePort:clientSendPort_
+ sendPort:clientReceivePort_];
[conn setRootObject:self];
-
- while (![self shouldServerQuit]) {
- NSDate* runUntil = [NSDate dateWithTimeIntervalSinceNow:0.5];
+ [lock unlockWithCondition:kGTMTransientThreadConditionStarted];
+ while (![lock tryLockWhenCondition:kGTMTransientThreadConditionQuitting]) {
+ NSDate *runUntil = [NSDate dateWithTimeIntervalSinceNow:0.1];
[[NSRunLoop currentRunLoop] runUntilDate:runUntil];
}
-
- [conn invalidate];
+ [conn setRootObject:nil];
+ [clientSendPort_ invalidate];
+ [clientReceivePort_ invalidate];
[conn release];
- [nc postNotificationName:kServerShuttingDownNotification object:nil];
[pool drain];
+ [lock unlockWithCondition:kGTMTransientThreadConditionQuitted];
}
-- (unsigned short)listeningPort {
- return listeningPort_;
+- (NSPort *)clientSendPort {
+ return clientSendPort_;
+}
+
+- (NSPort *)clientReceivePort {
+ return clientReceivePort_;
}
- (oneway void)doOneWayVoid {
@@ -99,79 +96,59 @@
return @"TestString";
}
-- (void)shutdownServer {
- @synchronized(self) {
- quit_ = YES;
- }
-}
-
@end
// === Done with auxillary data structures, now for the main test class ===
-@interface GTMTransientRootSocketProxyTest : GTMTestCase {
- DOSocketTestServer *server_;
- BOOL serverOffline_;
+@interface GTMTransientRootPortProxyTest : GTMTestCase {
+ DOPortTestServer *server_;
+ NSConditionLock *syncLock_;
}
@end
-@implementation GTMTransientRootSocketProxyTest
+@implementation GTMTransientRootPortProxyTest
-- (void)serverIsShuttingDown:(NSNotification *)note {
- @synchronized(self) {
- serverOffline_ = YES;
- }
-}
-
-- (BOOL)serverStatus {
- BOOL returnValue = NO;
- @synchronized(self) {
- returnValue = serverOffline_;
- }
- return returnValue;
-}
-
-- (void)testTransientRootSocketProxy {
- // Register for server notifications
- NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
- [nc addObserver:self
- selector:@selector(serverIsShuttingDown:)
- name:kServerShuttingDownNotification
- object:nil];
- serverOffline_ = NO;
+- (void)testTransientRootPortProxy {
+ syncLock_ = [[[NSConditionLock alloc]
+ initWithCondition:kGTMTransientThreadConditionStarting]
+ autorelease];
// Setup our server.
- server_ = [[[DOSocketTestServer alloc] init] autorelease];
+ server_ = [[[DOPortTestServer alloc] init] autorelease];
[NSThread detachNewThreadSelector:@selector(runThread:)
toTarget:server_
- withObject:nil];
- // Sleep for 1 second to give the new thread time to set stuff up
- [NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:1]];
-
- // Create our NSSocketPort
- NSSocketPort *receivePort =
- [[NSSocketPort alloc] initRemoteWithTCPPort:[server_ listeningPort]
- host:@"localhost"];
-
- GTMTransientRootSocketProxy<DOSocketTestProtocol> *failProxy =
- [GTMTransientRootSocketProxy rootProxyWithSocketPort:nil
- protocol:@protocol(DOSocketTestProtocol)
- requestTimeout:kDefaultTimeout
- replyTimeout:kDefaultTimeout];
+ withObject:syncLock_];
+ NSDate *future = [NSDate dateWithTimeIntervalSinceNow:kDefaultTimeout];
+ STAssertTrue([syncLock_ lockWhenCondition:kGTMTransientThreadConditionStarted
+ beforeDate:future],
+ @"Unable to start thread");
+ [syncLock_ unlockWithCondition:kGTMTransientThreadConditionStarted];
+
+ NSPort *receivePort = [server_ clientReceivePort];
+ NSPort *sendPort = [server_ clientSendPort];
+
+ GTMTransientRootPortProxy<DOPortTestProtocol> *failProxy =
+ [GTMTransientRootPortProxy rootProxyWithReceivePort:nil
+ sendPort:nil
+ protocol:@protocol(DOPortTestProtocol)
+ requestTimeout:kDefaultTimeout
+ replyTimeout:kDefaultTimeout];
STAssertNil(failProxy, @"should have failed w/o a port");
failProxy =
- [GTMTransientRootSocketProxy rootProxyWithSocketPort:receivePort
- protocol:nil
- requestTimeout:kDefaultTimeout
- replyTimeout:kDefaultTimeout];
+ [GTMTransientRootPortProxy rootProxyWithReceivePort:receivePort
+ sendPort:sendPort
+ protocol:nil
+ requestTimeout:kDefaultTimeout
+ replyTimeout:kDefaultTimeout];
STAssertNil(failProxy, @"should have failed w/o a protocol");
- GTMTransientRootSocketProxy<DOSocketTestProtocol> *proxy =
- [GTMTransientRootSocketProxy rootProxyWithSocketPort:receivePort
- protocol:@protocol(DOSocketTestProtocol)
- requestTimeout:kDefaultTimeout
- replyTimeout:kDefaultTimeout];
+ GTMTransientRootPortProxy<DOPortTestProtocol> *proxy =
+ [GTMTransientRootPortProxy rootProxyWithReceivePort:receivePort
+ sendPort:sendPort
+ protocol:@protocol(DOPortTestProtocol)
+ requestTimeout:kDefaultTimeout
+ replyTimeout:kDefaultTimeout];
STAssertEqualObjects([proxy doReturnStringBycopy],
@"TestString", @"proxy should have returned "
@@ -180,26 +157,26 @@
// Redo the *exact* same test to make sure we can have multiple instances
// in the same app.
proxy =
- [GTMTransientRootSocketProxy rootProxyWithSocketPort:receivePort
- protocol:@protocol(DOSocketTestProtocol)
- requestTimeout:kDefaultTimeout
- replyTimeout:kDefaultTimeout];
+ [GTMTransientRootPortProxy rootProxyWithReceivePort:receivePort
+ sendPort:sendPort
+ protocol:@protocol(DOPortTestProtocol)
+ requestTimeout:kDefaultTimeout
+ replyTimeout:kDefaultTimeout];
STAssertEqualObjects([proxy doReturnStringBycopy],
@"TestString", @"proxy should have returned "
@"'TestString'");
-
- [server_ shutdownServer];
-
- // Wait for the server to shutdown so we clean up nicely. The max amount of
- // time we will wait until we abort this test.
- id timeout = [NSDate dateWithTimeIntervalSinceNow:30.0];
- while (![self serverStatus] &&
- ([[NSDate date] compare:timeout] != NSOrderedDescending)) {
- NSDate *runUntil = [NSDate dateWithTimeIntervalSinceNow:2.0];
- [[NSRunLoop currentRunLoop] runUntilDate:runUntil];
- }
-
+ [syncLock_ tryLockWhenCondition:kGTMTransientThreadConditionStarted];
+ [syncLock_ unlockWithCondition:kGTMTransientThreadConditionQuitting];
+
+ // Wait for the server to shutdown so we clean up nicely.
+ // The max amount of time we will wait until we abort this test.
+ NSDate *timeout = [NSDate dateWithTimeIntervalSinceNow:kDefaultTimeout];
+ // The server did not shutdown and we want to capture this as an error
+ STAssertTrue([syncLock_ lockWhenCondition:kGTMTransientThreadConditionQuitted
+ beforeDate:timeout],
+ @"The server did not shutdown gracefully before the timeout.");
+ [syncLock_ unlockWithCondition:kGTMTransientThreadConditionQuitted];
}
@end