[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