Commits

Tuukka Norri committed 3c77c0e

Database object model
- The object model storage used by the context can now be set. This is useful mostly for testing purposes.
- Made BXDatabaseObjectModel safer to use with multiple threads.
- Fixed a problem which caused the tests to fail.

  • Participants
  • Parent commits 2dfaf22

Comments (0)

Files changed (14)

File BaseTen.xcodeproj/project.pbxproj

 
 /* Begin PBXBuildFile section */
 		53015A850FBEF22400E52C1E /* BXArraySize.h in Headers */ = {isa = PBXBuildFile; fileRef = 53015A830FBEF18800E52C1E /* BXArraySize.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		530A69831199A5BA00ED63FD /* NSDictionary+BaseTenAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 530A69811199A5BA00ED63FD /* NSDictionary+BaseTenAdditions.h */; };
+		530A69841199A5BA00ED63FD /* NSDictionary+BaseTenAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 530A69821199A5BA00ED63FD /* NSDictionary+BaseTenAdditions.m */; };
 		531A21500DE431D1006C757A /* BXPGConnectionResetRecoveryAttempter.h in Headers */ = {isa = PBXBuildFile; fileRef = 531A214E0DE431D1006C757A /* BXPGConnectionResetRecoveryAttempter.h */; };
 		531A21510DE431D1006C757A /* BXPGConnectionResetRecoveryAttempter.m in Sources */ = {isa = PBXBuildFile; fileRef = 531A214F0DE431D1006C757A /* BXPGConnectionResetRecoveryAttempter.m */; };
 		531A21560DE4324D006C757A /* BXPGAutocommitConnectionResetRecoveryAttempter.h in Headers */ = {isa = PBXBuildFile; fileRef = 531A21540DE4324D006C757A /* BXPGAutocommitConnectionResetRecoveryAttempter.h */; };
 		530132E209D460230037C485 /* BXPGInterface.m */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; includeInIndex = 1; name = BXPGInterface.m; path = Sources/BXPGInterface.m; sourceTree = "<group>"; };
 		53015A830FBEF18800E52C1E /* BXArraySize.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BXArraySize.h; path = Sources/BXArraySize.h; sourceTree = "<group>"; };
 		5308940D0E4349A50063C5E7 /* InterfaceBuilderPlugin.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = InterfaceBuilderPlugin.xcodeproj; path = InterfaceBuilderPlugin/InterfaceBuilderPlugin.xcodeproj; sourceTree = "<group>"; };
+		530A69811199A5BA00ED63FD /* NSDictionary+BaseTenAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSDictionary+BaseTenAdditions.h"; path = "Sources/NSDictionary+BaseTenAdditions.h"; sourceTree = "<group>"; };
+		530A69821199A5BA00ED63FD /* NSDictionary+BaseTenAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSDictionary+BaseTenAdditions.m"; path = "Sources/NSDictionary+BaseTenAdditions.m"; sourceTree = "<group>"; };
 		530ADD8309ED21EF004A13C3 /* BaseTen.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = BaseTen.h; path = Sources/BaseTen.h; sourceTree = "<group>"; };
 		531266E40B68F9CA00637EDA /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; };
 		531A214E0DE431D1006C757A /* BXPGConnectionResetRecoveryAttempter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BXPGConnectionResetRecoveryAttempter.h; path = Sources/BXPGConnectionResetRecoveryAttempter.h; sourceTree = "<group>"; };
 				535661CB0F025DD800920008 /* NSURL+BaseTenAdditions.m */,
 				535661CD0F025DD800920008 /* NSArray+BaseTenAdditions.h */,
 				535661CE0F025DD800920008 /* NSArray+BaseTenAdditions.m */,
+				530A69811199A5BA00ED63FD /* NSDictionary+BaseTenAdditions.h */,
+				530A69821199A5BA00ED63FD /* NSDictionary+BaseTenAdditions.m */,
 				535661D00F025DD800920008 /* NSPredicate+BaseTenAdditions.h */,
 				535661CF0F025DD800920008 /* NSPredicate+BaseTenAdditions.m */,
 				538334C30F03F4DF0040368E /* NSString+PGTSAdditions.h */,
 				53C8CC65118F1B8800E7AF88 /* BXDatabaseObjectModelStoragePrivate.h in Headers */,
 				53C8CC66118F1B8800E7AF88 /* BXDatabaseObjectModelPrivate.h in Headers */,
 				53C4C3F41192EC10003FB842 /* BXCFHostCompatibility.h in Headers */,
+				530A69831199A5BA00ED63FD /* NSDictionary+BaseTenAdditions.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
 				53617F921035B89D003CE4F5 /* stringutils.c in Sources */,
 				53617F931035B89D003CE4F5 /* variables.c in Sources */,
 				53E8985E1035B97D0062AA4D /* psqlscan.l in Sources */,
+				530A69841199A5BA00ED63FD /* NSDictionary+BaseTenAdditions.m in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};

File Sources/BXDatabaseContext.h

 @class BXEntityDescription;
 @class BXDatabaseObjectID;
 @class BXDatabaseObjectModel;
+@class BXDatabaseObjectModelStorage;
 @class NSEntityDescription;
 
 
 	NSMutableIndexSet*						mUndoGroupingLevels;
 	BXHiddenId <BXConnector>				mConnectionSetupManager;
 	BXDatabaseObjectModel*					mObjectModel;
+	BXDatabaseObjectModelStorage*			mObjectModelStorage;
 	
     SecKeychainItemRef                      mKeychainPasswordItem;
     NSNotificationCenter*                   mNotificationCenter;
 
 - (BOOL) logsQueries;
 - (void) setLogsQueries: (BOOL) shouldLog;
+
+- (BXDatabaseObjectModelStorage *) databaseObjectModelStorage;
+- (void) setDatabaseObjectModelStorage: (BXDatabaseObjectModelStorage *) storage;
 @end
 
 

File Sources/BXDatabaseContext.m

     [mObjects makeObjectsPerformSelector: @selector (BXDatabaseContextWillDealloc) withObject: nil];
     
 	[mObjectModel release];
+	[mObjectModelStorage release];
     [mDatabaseInterface release];
     [mDatabaseURI release];
     [mObjects release];
  * \param   uri     The database URI
  * \throw   NSException named \em kBXUnsupportedDatabaseException in case the given URI cannot be handled.
  */
-- (void) setDatabaseURI: (NSURL *) uri
+- (void) setDatabaseURI: (NSURL *) URI
 {
-	[self setKeychainPasswordItem: NULL];
-	if (! [[uri scheme] isEqual: [mDatabaseURI scheme]])
+	if (mDatabaseURI != URI)
 	{
-		[self setDatabaseInterface: nil];
-		[self databaseInterface];
-	}
+		[self setKeychainPasswordItem: NULL];
+		if (! [[URI scheme] isEqual: [mDatabaseURI scheme]])
+		{
+			[self setDatabaseInterface: nil];
+			[self databaseInterface];
+		}
 
-	if (mDatabaseURI && 0 < [[mDatabaseURI host] length])
-		[self setDatabaseObjectModel: nil];
+		if (mDatabaseURI && 0 < [[mDatabaseURI host] length])
+			[self setDatabaseObjectModel: nil];
 	
-	[self setDatabaseURIInternal: uri];
+		[self setDatabaseURIInternal: URI];
 
-	if (0 < [[mDatabaseURI host] length])
-	{
-		[self databaseObjectModel];
+		if (0 < [[mDatabaseURI host] length])
+		{
+			[self databaseObjectModel];
 
-		[[self internalDelegate] databaseContextGotDatabaseURI: self];
-		NSNotificationCenter* nc = [self notificationCenter];
-		[nc postNotificationName: kBXGotDatabaseURINotification object: self];	
+			[mDelegateProxy databaseContextGotDatabaseURI: self];
+			NSNotificationCenter* nc = [self notificationCenter];
+			[nc postNotificationName: kBXGotDatabaseURINotification object: self];	
+		}
 	}
 }
 
 			port = [mDatabaseInterface defaultPort];
 		
 		NSURL* key = [mDatabaseURI BXURIForHost: nil port: port database: nil username: @"" password: @""];
-		[self setDatabaseObjectModel: [[BXDatabaseObjectModelStorage defaultStorage] objectModelForURI: key]];
+		BXDatabaseObjectModelStorage *storage = mObjectModelStorage;
+		if (! storage)
+			storage = [BXDatabaseObjectModelStorage defaultStorage];
+		[self setDatabaseObjectModel: [storage objectModelForURI: key]];
 	}
 	return mObjectModel;
 }
+
+
+- (BXDatabaseObjectModelStorage *) databaseObjectModelStorage
+{
+	return mObjectModelStorage;
+}
+
+
+- (void) setDatabaseObjectModelStorage: (BXDatabaseObjectModelStorage *) storage
+{
+	if (! ([[mDatabaseURI host] length]))
+	{
+		if (storage != mObjectModelStorage)
+		{
+			[mObjectModelStorage release];
+			mObjectModelStorage = [storage retain];
+		}
+	}
+}
 @end
 
 
 	return [BXError errorWithDomain: kBXErrorDomain code: kBXErrorUnsuccessfulQuery userInfo: userInfo];	
 }
 
+
 - (void) connectionLost: (NSError *) error
 {
 	[mDelegateProxy databaseContext: self lostConnection: error];
 }
 
+
 //FIXME: We do too many things in this method. It should be refactored.
 - (BOOL) connectedToDatabase: (BOOL) connected async: (BOOL) async error: (NSError **) error;
 {
 		NSNotification* notification = nil;
 		if ([[self databaseObjectModel] contextConnectedUsingDatabaseInterface: mDatabaseInterface error: &localError])
 		{
-			[mObjectModel setCanCreateEntityDescriptions: NO];
 			notification = [NSNotification notificationWithName: kBXConnectionSuccessfulNotification object: self userInfo: nil];
 			if (async)
 				[mDelegateProxy databaseContextConnectionSucceeded: self];
 
 - (void) networkStatusChanged: (SCNetworkConnectionFlags) newFlags
 {
-	[[self internalDelegate] databaseContext: self networkStatusChanged: newFlags];
+	[mDelegateProxy databaseContext: self networkStatusChanged: newFlags];
 }
 @end
 
 	BXDeprecationLog ();
 	NSError* localError = nil;
 	NSDictionary* retval = [mObjectModel entitiesBySchemaAndName: mDatabaseInterface reload: reload error: &localError];
-	[mObjectModel setCanCreateEntityDescriptions: NO];
 	BXHandleError (outError, localError);
 	return retval;
 }
 	return retval;
 }
 
+
 - (void) setLastConnectionError: (NSError *) anError
 {
 	if (mLastConnectionError != anError)
 	}
 }
 
+
 - (void) setDatabaseObjectModel: (BXDatabaseObjectModel *) model
 {
 	if (model != mObjectModel)

File Sources/BXDatabaseObjectModel.h

 	BXDatabaseObjectModelStorage* mStorage;
 	NSURL* mStorageKey;
 	NSMutableDictionary* mEntitiesBySchemaAndName;
-	BOOL mCanCreateEntities;
+	volatile NSInteger mConnectionCount;
+	volatile BOOL mReloading;
 }
 + (NSError *) errorForMissingEntity: (NSString *) name inSchema: (NSString *) schemaName;
 

File Sources/BXDatabaseObjectModel.m

 #import "BXLogger.h"
 #import "BXLocalizedString.h"
 #import "BXError.h"
+#import "NSDictionary+BaseTenAdditions.h"
 
 
 /** 
 	return nil;
 }
 
+
 - (void) dealloc
 {	
 	[mEntitiesBySchemaAndName release];
 	BOOL retval = NO;
 	@synchronized (mEntitiesBySchemaAndName)
 	{
-		retval = mCanCreateEntities;
+		retval = ((0 == mConnectionCount) || mReloading ? YES : NO);
 	}
 	return retval;
 }
 {
 	NSMutableDictionary* schemaDict = nil;
 	BXEntityDescription* retval = nil;
-	BOOL canCreateEntityDesc = NO;
 	@synchronized (mEntitiesBySchemaAndName)
 	{
-		//We need the lock for this.
-		canCreateEntityDesc = mCanCreateEntities;
-		
 		schemaDict = [[[mEntitiesBySchemaAndName objectForKey: schemaName] retain] autorelease];
 		if (! schemaDict)
 		{
 			schemaDict = [NSMutableDictionary dictionary];
 			[mEntitiesBySchemaAndName setObject: schemaDict forKey: schemaName];
 		}
-	}
-	
-	@synchronized (schemaDict)
-	{
+		
 		retval = [[[schemaDict objectForKey: name] retain] autorelease];
-		if (! retval && canCreateEntityDesc)
+		if (! retval && [self canCreateEntityDescriptions])
 		{
 			retval = [[[BXEntityDescription alloc] initWithDatabaseURI: mStorageKey table: name inSchema: schemaName] autorelease];
 			[schemaDict setObject: retval forKey: name];
 		}
 	}
-	
 	return retval;
 }
 
 - (NSArray *) entities
 {
 	NSMutableArray* retval = [NSMutableArray array];
-	NSDictionary* schemas = nil;
 	@synchronized (mEntitiesBySchemaAndName)
 	{
-		schemas = [[mEntitiesBySchemaAndName copy] autorelease];
+		BXEnumerate (currentSchema, e, [mEntitiesBySchemaAndName objectEnumerator])
+			[retval addObjectsFromArray: currentSchema];
 	}
-	
-	BXEnumerate (currentSchema, e, [schemas objectEnumerator])
-	{
-		@synchronized (currentSchema)
-		{
-			[retval addObjectsFromArray: currentSchema];
-		}
-	}
-	
-	return retval;
+	return [[retval copy] autorelease];
 }
 
 
 		id <BXInterface> interface = [context databaseInterface];
 		[interface reloadDatabaseMetadata];
 		@synchronized (mEntitiesBySchemaAndName)
-		{			
-			mCanCreateEntities = YES;
+		{
+			mReloading = YES;
+
 			[interface prepareForEntityValidation];
 			NSArray* entities = [self entities];
 			if (entities)
 					[currentEntity removeValidation];
 				
 				if ([interface validateEntities: entities error: &localError])
-					retval = [[mEntitiesBySchemaAndName copy] autorelease];
+					retval = [[mEntitiesBySchemaAndName BXDeepCopy] autorelease];
 				else
 					[context handleError: localError outError: outError];
 			}
+			
+			mReloading = NO;
 		}
 	}
 	else
 	{
 		@synchronized (mEntitiesBySchemaAndName)
 		{
-			retval = [[mEntitiesBySchemaAndName copy] autorelease];
+			retval = [[mEntitiesBySchemaAndName BXDeepCopy] autorelease];
 		}
 	}
 	return retval;
 		mStorage = [storage retain];
 		mStorageKey = [key retain];
 		mEntitiesBySchemaAndName = [[NSMutableDictionary alloc] init];
-		mCanCreateEntities = YES;
 	}
 	return self;
 }
 	[interface prepareForEntityValidation];
 	
 	NSArray* entities = [self entities];
-	if (entities)
-		retval = [interface validateEntities: entities error: outError];
+	if (entities && [interface validateEntities: entities error: outError])
+	{
+		retval = YES;
+		@synchronized (mEntitiesBySchemaAndName)
+		{
+			mConnectionCount++;
+		}
+	}
 	return retval;
 }
-
-
-- (void) setCanCreateEntityDescriptions: (BOOL) aBool
-{
-	@synchronized (mEntitiesBySchemaAndName)
-	{
-		mCanCreateEntities = aBool;
-	}
-}
 @end

File Sources/BXDatabaseObjectModelPrivate.h

 @interface BXDatabaseObjectModel (PrivateMethods)
 - (id) initWithStorage: (BXDatabaseObjectModelStorage *) storage key: (NSURL *) key;
 - (BOOL) contextConnectedUsingDatabaseInterface: (id <BXInterface>) interface error: (NSError **) outError;
-- (void) setCanCreateEntityDescriptions: (BOOL) aBool;
 @end

File Sources/BXPGInterface.m

 {
 	//Warm-up the cache by ensuring that an entity exists for each table.
 	BXDatabaseObjectModel* objectModel = [mContext databaseObjectModel];
-	ExpectV ([objectModel canCreateEntityDescriptions]);
-	BXEnumerate (schema, e, [[[mTransactionHandler databaseDescription] schemasByName] objectEnumerator])
+	if ([objectModel canCreateEntityDescriptions])
 	{
-		BXEnumerate (table, e, [[schema allTables] objectEnumerator])
+		BXEnumerate (schema, e, [[[mTransactionHandler databaseDescription] schemasByName] objectEnumerator])
 		{
-			[objectModel entityForTable: [table name] inSchema: [table schemaName]];
+			BXEnumerate (table, e, [[schema allTables] objectEnumerator])
+			{
+				[objectModel entityForTable: [table name] inSchema: [table schemaName]];
+			}
 		}
 	}
 }
 	
 	BXEnumerate (entity, e, [entities objectEnumerator])
 	{
+		// Return YES if the entity needs to be validated.
 		if ([entity beginValidation])
 		{
 			BXPGTableDescription* table = [self tableForEntity: entity];

File UnitTests/Sources/BXConnectionTests.h

+//
+// BXConnectionTests.h
+// BaseTen
+//
+// Copyright (C) 2006-2010 Marko Karppinen & Co. LLC.
+//
+// Before using this software, please review the available licensing options
+// by visiting http://basetenframework.org/licensing/ or by contacting
+// us at sales@karppinen.fi. Without an additional license, this software
+// may be distributed only in compliance with the GNU General Public License.
+//
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License, version 2.0,
+// as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+// $Id$
+//
+
+#import <SenTestingKit/SenTestingKit.h>
+#import "BXTestCase.h"
+@class BXDatabaseContext;
+
+
+@interface BXConnectionTests : BXTestCase 
+{
+    BXDatabaseContext* mContext;
+	NSInteger mExpectedCount;
+}
+@end

File UnitTests/Sources/BXConnectionTests.m

+//
+// BXConnectTests.m
+// BaseTen
+//
+// Copyright (C) 2006-2010 Marko Karppinen & Co. LLC.
+//
+// Before using this software, please review the available licensing options
+// by visiting http://basetenframework.org/licensing/ or by contacting
+// us at sales@karppinen.fi. Without an additional license, this software
+// may be distributed only in compliance with the GNU General Public License.
+//
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License, version 2.0,
+// as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+// $Id$
+//
+
+#import "BXConnectionTests.h"
+#import "MKCSenTestCaseAdditions.h"
+#import <BaseTen/BaseTen.h>
+
+
+@implementation BXConnectionTests
+- (void) setUp
+{
+	[super setUp];
+
+    mContext = [[BXDatabaseContext alloc] init];
+	[mContext setAutocommits: NO];
+	[mContext setDelegate: self];
+}
+
+
+- (void) tearDown
+{
+	[mContext disconnect];
+    [mContext release];
+	[super tearDown];
+}
+
+
+- (void) waitForConnectionAttempts: (NSInteger) count
+{
+	for (NSInteger i = 0; i < 300; i++)
+	{
+		NSLog (@"Attempt %d, count %d, expected %d", i, mExpectedCount, count);
+		if (count == mExpectedCount)
+			break;
+		
+		[[NSRunLoop currentRunLoop] runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 2.0]];
+	}
+}
+
+
+- (void) test1Connect
+{
+    MKCAssertNoThrow ([mContext setDatabaseURI: [self databaseURI]]);
+    MKCAssertNoThrow ([mContext connectIfNeeded: nil]);
+}
+
+
+- (void) test2Connect
+{
+	NSURL* uri = [self databaseURI];
+	NSString* uriString = [uri absoluteString];
+	uriString = [uriString stringByAppendingString: @"/"];
+	uri = [NSURL URLWithString: uriString];
+	
+    MKCAssertNoThrow ([mContext setDatabaseURI: uri]);
+    MKCAssertNoThrow ([mContext connectIfNeeded: nil]);
+}
+
+
+- (void) test3ConnectFail
+{
+    MKCAssertNoThrow ([mContext setDatabaseURI: [NSURL URLWithString: @"pgsql://localhost/anonexistantdatabase"]]);
+    MKCAssertThrows ([mContext connectIfNeeded: nil]);
+}
+
+
+- (void) test4ConnectFail
+{
+    MKCAssertNoThrow ([mContext setDatabaseURI: 
+        [NSURL URLWithString: @"pgsql://user@localhost/basetentest/a/malformed/database/uri"]]);
+    MKCAssertThrows ([mContext connectIfNeeded: nil]);
+}
+
+
+- (void) test5ConnectFail
+{
+    MKCAssertThrows ([mContext setDatabaseURI: [NSURL URLWithString: @"invalid://user@localhost/invalid"]]);
+}
+
+
+- (void) test7NilURI
+{
+	NSError* error = nil;
+	id fetched = nil;
+	BXEntityDescription* entity = [[mContext databaseObjectModel] entityForTable: @"test"];
+	fetched = [mContext executeFetchForEntity: entity withPredicate: nil error: &error];
+	MKCAssertNotNil (error);
+	fetched = [mContext createObjectForEntity: entity withFieldValues: nil error: &error];
+	MKCAssertNotNil (error);
+}
+
+
+- (void) test6ConnectFail
+{
+	[mContext setDatabaseURI: [NSURL URLWithString: @"pgsql://localhost/anonexistantdatabase"]];
+	[[mContext notificationCenter] addObserver: self selector: @selector (expected:) name: kBXConnectionFailedNotification object: nil];
+	[[mContext notificationCenter] addObserver: self selector: @selector (unexpected:) name: kBXConnectionSuccessfulNotification object: nil];
+	[mContext connectAsync];
+	[self waitForConnectionAttempts: 1];
+	[mContext connectAsync];
+	[self waitForConnectionAttempts: 2];
+	[mContext connectAsync];
+	[self waitForConnectionAttempts: 3];
+	STAssertTrue (3 == mExpectedCount, @"Expected 3 connection attempts while there were %d.", mExpectedCount);
+}
+
+
+- (void) expected: (NSNotification *) n
+{
+	mExpectedCount++;
+}
+
+
+- (void) unexpected: (NSNotification *) n
+{
+	STAssertTrue (NO, @"Expected connection not to have been made.");
+}
+@end

File UnitTests/Sources/BXTestCase.m

 	[super setUp];
 	
 	NSURL* databaseURI = [self databaseURI];
-	mContext = [[BXDatabaseContext alloc] initWithDatabaseURI: databaseURI];
+
+	mContext = [[BXDatabaseContext alloc] init];
+	[mContext setDatabaseURI: databaseURI];
 	[mContext setAutocommits: NO];
 	[mContext setDelegate: self];
 	

File UnitTests/Sources/ConnectTest.h

-//
-// ConnectTest.h
-// BaseTen
-//
-// Copyright (C) 2006-2008 Marko Karppinen & Co. LLC.
-//
-// Before using this software, please review the available licensing options
-// by visiting http://basetenframework.org/licensing/ or by contacting
-// us at sales@karppinen.fi. Without an additional license, this software
-// may be distributed only in compliance with the GNU General Public License.
-//
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License, version 2.0,
-// as published by the Free Software Foundation.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-//
-// $Id$
-//
-
-#import <SenTestingKit/SenTestingKit.h>
-#import "BXTestCase.h"
-@class BXDatabaseContext;
-
-@interface ConnectTest : BXTestCase 
-{
-    BXDatabaseContext* ctx;
-	int expectedCount;
-}
-
-@end

File UnitTests/Sources/ConnectTest.m

-//
-// ConnectTest.m
-// BaseTen
-//
-// Copyright (C) 2006-2008 Marko Karppinen & Co. LLC.
-//
-// Before using this software, please review the available licensing options
-// by visiting http://basetenframework.org/licensing/ or by contacting
-// us at sales@karppinen.fi. Without an additional license, this software
-// may be distributed only in compliance with the GNU General Public License.
-//
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License, version 2.0,
-// as published by the Free Software Foundation.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-//
-// $Id$
-//
-
-#import "ConnectTest.h"
-#import <BaseTen/BaseTen.h>
-#import "MKCSenTestCaseAdditions.h"
-
-
-@implementation ConnectTest
-
-- (void) setUp
-{
-	[super setUp];
-	
-    ctx = [[BXDatabaseContext alloc] init];
-	[ctx setAutocommits: NO];
-	[ctx setDelegate: self];
-	expectedCount = 0;
-}
-
-- (void) tearDown
-{
-	[ctx disconnect];
-    [ctx release];
-	[super tearDown];
-}
-
-- (void) waitForConnectionAttempts: (NSInteger) count
-{
-	for (NSInteger i = 0; i < 300; i++)
-	{
-		NSLog (@"Attempt %d, count %d, expected %d", i, expectedCount, count);
-		if (count == expectedCount)
-			break;
-		
-		[[NSRunLoop currentRunLoop] runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 2.0]];
-	}
-}
-
-- (void) test1Connect
-{
-    MKCAssertNoThrow ([ctx setDatabaseURI: [self databaseURI]]);
-    MKCAssertNoThrow ([ctx connectIfNeeded: nil]);
-}
-
-- (void) test2Connect
-{
-	NSURL* uri = [self databaseURI];
-	NSString* uriString = [uri absoluteString];
-	uriString = [uriString stringByAppendingString: @"/"];
-	uri = [NSURL URLWithString: uriString];
-	
-    MKCAssertNoThrow ([ctx setDatabaseURI: uri]);
-    MKCAssertNoThrow ([ctx connectIfNeeded: nil]);
-}
- 
-- (void) test3ConnectFail
-{
-    MKCAssertNoThrow ([ctx setDatabaseURI: [NSURL URLWithString: @"pgsql://localhost/anonexistantdatabase"]]);
-    MKCAssertThrows ([ctx connectIfNeeded: nil]);
-}
- 
-- (void) test4ConnectFail
-{
-    MKCAssertNoThrow ([ctx setDatabaseURI: 
-        [NSURL URLWithString: @"pgsql://user@localhost/basetentest/a/malformed/database/uri"]]);
-    MKCAssertThrows ([ctx connectIfNeeded: nil]);
-}
-
-- (void) test5ConnectFail
-{
-    MKCAssertThrows ([ctx setDatabaseURI: [NSURL URLWithString: @"invalid://user@localhost/invalid"]]);
-}
-
-- (void) test7NilURI
-{
-	NSError* error = nil;
-	id fetched = nil;
-	BXEntityDescription* entity = [[ctx databaseObjectModel] entityForTable: @"test"];
-	fetched = [ctx executeFetchForEntity: entity withPredicate: nil error: &error];
-	MKCAssertNotNil (error);
-	fetched = [ctx createObjectForEntity: entity withFieldValues: nil error: &error];
-	MKCAssertNotNil (error);
-}
-
-- (void) test6ConnectFail
-{
-	[ctx setDatabaseURI: [NSURL URLWithString: @"pgsql://localhost/anonexistantdatabase"]];
-	[[ctx notificationCenter] addObserver: self selector: @selector (expected:) name: kBXConnectionFailedNotification object: nil];
-	[[ctx notificationCenter] addObserver: self selector: @selector (unexpected:) name: kBXConnectionSuccessfulNotification object: nil];
-	[ctx connectAsync];
-	[self waitForConnectionAttempts: 1];
-	[ctx connectAsync];
-	[self waitForConnectionAttempts: 2];
-	[ctx connectAsync];
-	[self waitForConnectionAttempts: 3];
-	STAssertTrue (3 == expectedCount, @"Expected 3 connection attempts while there were %d.", expectedCount);
-}
-
-- (void) expected: (NSNotification *) n
-{
-	expectedCount++;
-}
-
-- (void) unexpected: (NSNotification *) n
-{
-	STAssertTrue (NO, @"Expected connection not to have been made.");
-}
-
-@end

File UnitTests/Sources/TestLoader.m

 #import "PGTSNotificationTests.h"
 #import "PGTSPgBouncerTests.h"
 
-#import "ConnectTest.h"
+#import "BXConnectionTests.h"
 #import "BXSSLConnectionTests.h"
 #import "BXMetadataTests.h"
 #import "BXDataModelTests.h"
 							[PGTSNotificationTests class],
 							[PGTSPgBouncerTests class],
 							
-							[ConnectTest class],
+							[BXConnectionTests class],
 							[BXSSLConnectionTests class],
 							[BXMetadataTests class],
 							[BXDataModelTests class],
 							[ToOneChangeNotificationTests class],
 							nil];
 	
-	//testClasses = [NSArray arrayWithObject: [BXArbitrarySQLTests class]];
+	//testClasses = [NSArray arrayWithObject: [ConnectTest class]];
 	
 	for (Class testCaseClass in testClasses)
 	{

File UnitTests/UnitTests.xcodeproj/project.pbxproj

 		5317CEB70D1ACB0E00A48792 /* BXModificationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 5373A65D0A6D3F9A0036424B /* BXModificationTests.m */; };
 		5317CEB80D1ACB0E00A48792 /* ForeignKeyTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 53EAD1B50A668733008F3CE5 /* ForeignKeyTests.m */; };
 		5317CEBA0D1ACB1000A48792 /* EntityTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 531E118C0A6A3A6C003A0F23 /* EntityTests.m */; };
-		5317CEBC0D1ACB1100A48792 /* ConnectTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 530A439E0A5C114E00A4722B /* ConnectTest.m */; };
+		5317CEBC0D1ACB1100A48792 /* BXConnectionTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 530A439E0A5C114E00A4722B /* BXConnectionTests.m */; };
 		53193F0A0BC51702009A77EC /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 53193E8D0BC51701009A77EC /* Foundation.framework */; };
 		534C95EC0FAB623F006BBC8A /* relationship-optionality.xcdatamodel in Sources */ = {isa = PBXBuildFile; fileRef = 534C95EB0FAB623F006BBC8A /* relationship-optionality.xcdatamodel */; };
 		535627B90E6E805D002EA3FD /* BXPredicateTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 535627B80E6E805D002EA3FD /* BXPredicateTests.m */; };
 		530A435E0A5C0E0100A4722B /* BaseTen.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = BaseTen.xcodeproj; path = ../BaseTen.xcodeproj; sourceTree = SOURCE_ROOT; };
 		530A438C0A5C0FD000A4722B /* UnitTests.octest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = UnitTests.octest; sourceTree = BUILT_PRODUCTS_DIR; };
 		530A438E0A5C0FD000A4722B /* UnitTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "UnitTests-Info.plist"; sourceTree = "<group>"; };
-		530A439D0A5C114E00A4722B /* ConnectTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ConnectTest.h; path = Sources/ConnectTest.h; sourceTree = "<group>"; };
-		530A439E0A5C114E00A4722B /* ConnectTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ConnectTest.m; path = Sources/ConnectTest.m; sourceTree = "<group>"; };
+		530A439D0A5C114E00A4722B /* BXConnectionTests.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BXConnectionTests.h; path = Sources/BXConnectionTests.h; sourceTree = "<group>"; };
+		530A439E0A5C114E00A4722B /* BXConnectionTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BXConnectionTests.m; path = Sources/BXConnectionTests.m; sourceTree = "<group>"; };
 		53193E8D0BC51701009A77EC /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; };
 		531E118B0A6A3A6C003A0F23 /* EntityTests.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = EntityTests.h; path = Sources/EntityTests.h; sourceTree = "<group>"; };
 		531E118C0A6A3A6C003A0F23 /* EntityTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = EntityTests.m; path = Sources/EntityTests.m; sourceTree = "<group>"; };
 		536C46360F2E1CC0003A8231 /* BaseTen */ = {
 			isa = PBXGroup;
 			children = (
-				530A439D0A5C114E00A4722B /* ConnectTest.h */,
-				530A439E0A5C114E00A4722B /* ConnectTest.m */,
+				530A439D0A5C114E00A4722B /* BXConnectionTests.h */,
+				530A439E0A5C114E00A4722B /* BXConnectionTests.m */,
 				5392E6610FC1B0C70056DF6A /* BXSSLConnectionTests.h */,
 				5392E6620FC1B0C70056DF6A /* BXSSLConnectionTests.m */,
 				53C4C679119443E1003FB842 /* BXMetadataTests.h */,
 				5317CEB70D1ACB0E00A48792 /* BXModificationTests.m in Sources */,
 				5317CEB80D1ACB0E00A48792 /* ForeignKeyTests.m in Sources */,
 				5317CEBA0D1ACB1000A48792 /* EntityTests.m in Sources */,
-				5317CEBC0D1ACB1100A48792 /* ConnectTest.m in Sources */,
+				5317CEBC0D1ACB1100A48792 /* BXConnectionTests.m in Sources */,
 				53A59C560E3509CE0026D7E1 /* FetchTests.m in Sources */,
 				535627B90E6E805D002EA3FD /* BXPredicateTests.m in Sources */,
 				53DAA0590E6EEB46001DC1D9 /* BXKeyPathComponentTest.m in Sources */,