[CalendarServer-changes] [5995] CalendarServer/branches/users/glyph/sql-store
source_changes at macosforge.org
source_changes at macosforge.org
Fri Aug 6 10:37:42 PDT 2010
Revision: 5995
http://trac.macosforge.org/projects/calendarserver/changeset/5995
Author: glyph at apple.com
Date: 2010-08-06 10:37:41 -0700 (Fri, 06 Aug 2010)
Log Message:
-----------
checkpoint: tests for default calendar, create default calendar in postgres, correct interface specification to add newTransaction label arg
Modified Paths:
--------------
CalendarServer/branches/users/glyph/sql-store/txcaldav/calendarstore/postgres.py
CalendarServer/branches/users/glyph/sql-store/txcaldav/calendarstore/scheduling.py
CalendarServer/branches/users/glyph/sql-store/txcaldav/calendarstore/test/common.py
CalendarServer/branches/users/glyph/sql-store/txcaldav/calendarstore/test/test_postgres.py
CalendarServer/branches/users/glyph/sql-store/txdav/idav.py
Modified: CalendarServer/branches/users/glyph/sql-store/txcaldav/calendarstore/postgres.py
===================================================================
--- CalendarServer/branches/users/glyph/sql-store/txcaldav/calendarstore/postgres.py 2010-08-06 13:37:33 UTC (rev 5994)
+++ CalendarServer/branches/users/glyph/sql-store/txcaldav/calendarstore/postgres.py 2010-08-06 17:37:41 UTC (rev 5995)
@@ -832,7 +832,9 @@
"insert into CALENDAR_HOME (OWNER_UID) values (%s)",
[uid]
)
- return self.calendarHomeWithUID(uid)
+ home = self.calendarHomeWithUID(uid)
+ home.createCalendarWithName("calendar")
+ return home
resid = data[0][0]
notifier = self._notifierFactory.newNotifier(id=uid)
return PostgresCalendarHome(self, uid, resid, notifier)
@@ -884,7 +886,7 @@
self.attachmentsPath = attachmentsPath
- def newTransaction(self):
+ def newTransaction(self, label="unlabeled"):
return PostgresCalendarTransaction(
self,
self.connectionFactory(),
Modified: CalendarServer/branches/users/glyph/sql-store/txcaldav/calendarstore/scheduling.py
===================================================================
--- CalendarServer/branches/users/glyph/sql-store/txcaldav/calendarstore/scheduling.py 2010-08-06 13:37:33 UTC (rev 5994)
+++ CalendarServer/branches/users/glyph/sql-store/txcaldav/calendarstore/scheduling.py 2010-08-06 17:37:41 UTC (rev 5995)
@@ -153,9 +153,9 @@
self._calendarStore = calendarStore
- def newTransaction(self):
+ def newTransaction(self, label="unlabeled"):
"""
Wrap an underlying L{ITransaction}.
"""
return ImplicitTransaction(
- self._calendarStore.newTransaction())
+ self._calendarStore.newTransaction(label))
Modified: CalendarServer/branches/users/glyph/sql-store/txcaldav/calendarstore/test/common.py
===================================================================
--- CalendarServer/branches/users/glyph/sql-store/txcaldav/calendarstore/test/common.py 2010-08-06 13:37:33 UTC (rev 5994)
+++ CalendarServer/branches/users/glyph/sql-store/txcaldav/calendarstore/test/common.py 2010-08-06 17:37:41 UTC (rev 5995)
@@ -144,6 +144,22 @@
+def assertProvides(testCase, interface, provider):
+ """
+ Verify that C{provider} properly provides C{interface}
+
+ @type interface: L{zope.interface.Interface}
+ @type provider: C{provider}
+ """
+ try:
+ verifyObject(interface, provider)
+ except BrokenMethodImplementation, e:
+ testCase.fail(e)
+ except DoesNotImplement, e:
+ testCase.fail("%r does not provide %s.%s" %
+ (provider, interface.__module__, interface.getName()))
+
+
class CommonTests(object):
"""
Tests for common functionality of interfaces defined in
@@ -243,22 +259,8 @@
return self.calendarUnderTest().calendarObjectWithName("1.ics")
- def assertProvides(self, interface, provider):
- """
- Verify that C{provider} properly provides C{interface}
+ assertProvides = assertProvides
- @type interface: L{zope.interface.Interface}
- @type provider: C{provider}
- """
- try:
- verifyObject(interface, provider)
- except BrokenMethodImplementation, e:
- self.fail(e)
- except DoesNotImplement, e:
- self.fail("%r does not provide %s.%s" %
- (provider, interface.__module__, interface.getName()))
-
-
def test_calendarStoreProvides(self):
"""
The calendar store provides L{IDataStore} and its required attributes.
@@ -397,14 +399,14 @@
home = self.homeUnderTest()
self.assertNotIdentical(home.calendarWithName(name), None)
- otherTxn = self.storeUnderTest().newTransaction()
- self.addCleanup(otherTxn.commit)
- home = otherTxn.calendarHomeWithUID("home1")
- # Sanity check: are the properties actually persisted?
- # FIXME: no independent testing of this right now
+ # Sanity check: are the properties actually persisted? Check in
+ # subsequent transaction.
checkProperties()
+ # FIXME: no independent testing of the property store's persistence
+ # right now
+
def test_createCalendarWithName_exists(self):
"""
L{ICalendarHome.createCalendarWithName} raises
@@ -777,6 +779,9 @@
self.addCleanup(otherTxn.commit)
return otherTxn.calendarHomeWithUID(noHomeUID)
self.assertProvides(ICalendarHome, calendarHome)
+ # Default calendar should be automatically created.
+ self.assertProvides(ICalendar,
+ calendarHome.calendarWithName("calendar"))
# A concurrent transaction shouldn't be able to read it yet:
self.assertIdentical(readOtherTxn(), None)
self.commit()
Modified: CalendarServer/branches/users/glyph/sql-store/txcaldav/calendarstore/test/test_postgres.py
===================================================================
--- CalendarServer/branches/users/glyph/sql-store/txcaldav/calendarstore/test/test_postgres.py 2010-08-06 13:37:33 UTC (rev 5994)
+++ CalendarServer/branches/users/glyph/sql-store/txcaldav/calendarstore/test/test_postgres.py 2010-08-06 17:37:41 UTC (rev 5995)
@@ -26,7 +26,7 @@
from txdav.datastore.subpostgres import PostgresService, \
DiagnosticConnectionWrapper
from txcaldav.calendarstore.postgres import PostgresStore, v1_schema
-from twisted.internet.defer import Deferred
+from twisted.internet.defer import Deferred, inlineCallbacks, succeed
from twisted.internet import reactor
from twext.python.filepath import CachingFilePath
from twext.python.vcomponent import VComponent
@@ -51,100 +51,114 @@
-sharedService = None
-currentTestID = None
-
-class SQLStorageTests(CommonTests, unittest.TestCase):
+class StoreBuilder(object):
"""
- File storage tests.
+ Test-fixture-builder which can construct a PostgresStore.
"""
+ sharedService = None
+ currentTestID = None
- def setUp(self):
- super(SQLStorageTests, self).setUp()
- global sharedService
- global currentTestID
- currentTestID = self.id()
- dbRoot = CachingFilePath("../_test_postgres_db")
- if sharedService is None:
+ SHARED_DB_PATH = "../_test_postgres_db"
+
+ def buildStore(self, testCase, notifierFactory):
+ """
+ Do the necessary work to build a store for a particular test case.
+
+ @return: a L{Deferred} which fires with an L{IDataStore}.
+ """
+ currentTestID = testCase.id()
+ dbRoot = CachingFilePath(self.SHARED_DB_PATH)
+ if self.sharedService is None:
ready = Deferred()
def getReady(connectionFactory):
- global calendarStore
attachmentRoot = dbRoot.child("attachments")
try:
attachmentRoot.createDirectory()
except OSError:
pass
try:
- calendarStore = PostgresStore(
+ self.calendarStore = PostgresStore(
lambda label=None: connectionFactory(
label or currentTestID
),
- self.notifierFactory,
+ notifierFactory,
attachmentRoot
)
except:
ready.errback()
raise
else:
- self.cleanAndPopulate().chainDeferred(ready)
- return calendarStore
- sharedService = PostgresService(
+ self.cleanDatabase(testCase)
+ ready.callback(self.calendarStore)
+ return self.calendarStore
+ self.sharedService = PostgresService(
dbRoot,
getReady, v1_schema, "caldav"
)
- sharedService.startService()
+ self.sharedService.startService()
def startStopping():
log.msg("Starting stopping.")
- sharedService.unpauseMonitor()
- return sharedService.stopService()
+ self.sharedService.unpauseMonitor()
+ return self.sharedService.stopService()
reactor.addSystemEventTrigger(#@UndefinedVariable
"before", "shutdown", startStopping)
- return ready
+ result = ready
else:
- calendarStore.notifierFactory = self.notifierFactory
- return self.cleanAndPopulate()
+ self.calendarStore.notifierFactory = notifierFactory
+ self.cleanDatabase(testCase)
+ result = succeed(self.calendarStore)
+ def cleanUp():
+ # FIXME: clean up any leaked connections and report them with an
+ # immediate test failure.
+ def stopit():
+ self.sharedService.pauseMonitor()
+ return deferLater(reactor, 0.1, stopit)
+ testCase.addCleanup(cleanUp)
+ return result
- def cleanAndPopulate(self):
- """
- Delete everything from the database, then clean it up.
- """
- cleanupConn = calendarStore.connectionFactory(
- "%s schema-cleanup" % (self.id(),)
+
+ def cleanDatabase(self, testCase):
+ cleanupConn = self.calendarStore.connectionFactory(
+ "%s schema-cleanup" % (testCase.id(),)
)
cursor = cleanupConn.cursor()
cursor.execute("delete from RESOURCE_PROPERTY")
- cleanupConn.commit()
cursor.execute("delete from ATTACHMENT")
- cleanupConn.commit()
cursor.execute("delete from CALENDAR_OBJECT")
- cleanupConn.commit()
cursor.execute("delete from CALENDAR_BIND")
- cleanupConn.commit()
cursor.execute("delete from CALENDAR")
- cleanupConn.commit()
cursor.execute("delete from CALENDAR_HOME")
cleanupConn.commit()
cleanupConn.close()
- self.populate()
- sharedService.unpauseMonitor()
- # I need to allow the log buffer to unspool.
- return deferLater(reactor, 0.1, lambda : None)
- def tearDown(self):
- super(SQLStorageTests, self).tearDown()
- def stopit():
- sharedService.pauseMonitor()
- return deferLater(reactor, 0.1, stopit)
+theStoreBuilder = StoreBuilder()
+buildStore = theStoreBuilder.buildStore
+
+class SQLStorageTests(CommonTests, unittest.TestCase):
+ """
+ File storage tests.
+ """
+
+ @inlineCallbacks
+ def setUp(self):
+ super(SQLStorageTests, self).setUp()
+ self.calendarStore = yield buildStore(self, self.notifierFactory)
+ self.populate()
+
+
def populate(self):
- populateTxn = calendarStore.newTransaction()
+ populateTxn = self.calendarStore.newTransaction()
for homeUID in self.requirements:
calendars = self.requirements[homeUID]
if calendars is not None:
home = populateTxn.calendarHomeWithUID(homeUID, True)
+ # We don't want the default calendar to appear unless it's
+ # explicitly listed.
+ home.removeCalendarWithName("calendar")
for calendarName in calendars:
calendarObjNames = calendars[calendarName]
if calendarObjNames is not None:
@@ -163,5 +177,5 @@
"""
Create and return a L{CalendarStore} for testing.
"""
- return calendarStore
+ return self.calendarStore
Modified: CalendarServer/branches/users/glyph/sql-store/txdav/idav.py
===================================================================
--- CalendarServer/branches/users/glyph/sql-store/txdav/idav.py 2010-08-06 13:37:33 UTC (rev 5994)
+++ CalendarServer/branches/users/glyph/sql-store/txdav/idav.py 2010-08-06 17:37:41 UTC (rev 5995)
@@ -99,9 +99,13 @@
An L{IDataStore} is a storage of some objects.
"""
- def newTransaction():
+ def newTransaction(label=None):
"""
Create a new transaction.
+
+ @param label: A label to assign to this transaction for diagnostic
+ purposes.
+ @type label: C{str}
@return: a new transaction which provides L{ITransaction}, as well as
sub-interfaces to request appropriate data objects.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20100806/7da7f72d/attachment-0001.html>
More information about the calendarserver-changes
mailing list