[CalendarServer-changes] [11568] CalendarServer/trunk/twext/internet

source_changes at macosforge.org source_changes at macosforge.org
Tue Jul 30 16:28:52 PDT 2013


Revision: 11568
          http://trac.calendarserver.org//changeset/11568
Author:   sagen at apple.com
Date:     2013-07-30 16:28:52 -0700 (Tue, 30 Jul 2013)
Log Message:
-----------
Tests for fswatch

Modified Paths:
--------------
    CalendarServer/trunk/twext/internet/fswatch.py
    CalendarServer/trunk/twext/internet/test/test_fswatch.py

Modified: CalendarServer/trunk/twext/internet/fswatch.py
===================================================================
--- CalendarServer/trunk/twext/internet/fswatch.py	2013-07-30 18:46:38 UTC (rev 11567)
+++ CalendarServer/trunk/twext/internet/fswatch.py	2013-07-30 23:28:52 UTC (rev 11568)
@@ -62,16 +62,19 @@
 if kqueueSupported and hasattr(reactor, "_doWriteOrRead"):
 
 
-    # Wrap _doWriteOrRead to support KQ_FILTER_VNODE
-    origDoWriteOrRead = reactor._doWriteOrRead
-    def _doWriteOrReadOrVNodeEvent(selectable, fd, event):
-        origDoWriteOrRead(selectable, fd, event)
-        if event.filter == KQ_FILTER_VNODE:
-            selectable.vnodeEventHappened(event)
-    reactor._doWriteOrRead = _doWriteOrReadOrVNodeEvent
+    def patchReactor(reactor):
+        # Wrap _doWriteOrRead to support KQ_FILTER_VNODE
+        origDoWriteOrRead = reactor._doWriteOrRead
+        def _doWriteOrReadOrVNodeEvent(selectable, fd, event):
+            origDoWriteOrRead(selectable, fd, event)
+            if event.filter == KQ_FILTER_VNODE:
+                selectable.vnodeEventHappened(event)
+        reactor._doWriteOrRead = _doWriteOrReadOrVNodeEvent
 
+    patchReactor(reactor)
 
 
+
     class DirectoryChangeListener(Logger, object):
         """
         Listens for the removal, renaming, or general unavailability of a

Modified: CalendarServer/trunk/twext/internet/test/test_fswatch.py
===================================================================
--- CalendarServer/trunk/twext/internet/test/test_fswatch.py	2013-07-30 18:46:38 UTC (rev 11567)
+++ CalendarServer/trunk/twext/internet/test/test_fswatch.py	2013-07-30 23:28:52 UTC (rev 11568)
@@ -18,10 +18,151 @@
 Tests for L{twext.internet.fswatch}.
 """
 
-# from twext.internet.fswatch import DirectoryChangeListener
-# from twisted.trial.unittest import TestCase
+from twext.internet.fswatch import (DirectoryChangeListener, patchReactor,
+    IDirectoryChangeListenee)
+from twisted.trial.unittest import TestCase
+from twisted.internet.kqreactor import KQueueReactor
+from twisted.python.filepath import FilePath
+from zope.interface import implements
 
-# TODO: tests
 
+class KQueueReactorTestFixture(object):
 
+    def __init__(self, testCase, action=None, timeout=10):
+        """
+        Creates a kqueue reactor for use in unit tests.  The reactor is patched
+        with the vnode event handler.  Once the reactor is running, it will
+        call a supplied method.  It's expected that the method will ultimately
+        trigger the stop() of the reactor.  The reactor will time out after 10
+        seconds.
 
+        @param testCase: a test method which is needed for adding cleanup to
+        @param action: a method which will get called after the reactor is
+            running
+        @param timeout: how many seconds to keep the reactor running before
+            giving up and stopping it
+        """
+        self.testCase = testCase
+        self.reactor = KQueueReactor()
+        patchReactor(self.reactor)
+        self.action = action
+        self.timeout = timeout
+
+        def maybeStop():
+            if self.reactor.running:
+                return self.reactor.stop()
+
+        self.testCase.addCleanup(maybeStop)
+
+
+    def runReactor(self):
+        """
+        Run the test reactor, adding cleanup code to stop if after a timeout,
+        and calling the action method
+        """
+        def getReadyToStop():
+            self.reactor.callLater(self.timeout, self.reactor.stop)
+        self.reactor.callWhenRunning(getReadyToStop)
+        if self.action is not None:
+            self.reactor.callWhenRunning(self.action)
+        self.reactor.run(installSignalHandlers=False)
+
+
+
+class DataStoreMonitor(object):
+    """
+    Stub IDirectoryChangeListenee
+    """
+    implements(IDirectoryChangeListenee)
+
+
+    def __init__(self, reactor, storageService):
+        """
+        @param storageService: the service making use of the DataStore
+            directory; we send it a hardStop() to shut it down
+        """
+        self._reactor = reactor
+        self._storageService = storageService
+        self.methodCalled = ""
+
+
+    def disconnected(self):
+        self.methodCalled = "disconnected"
+        self._storageService.hardStop()
+        self._reactor.stop()
+
+
+    def deleted(self):
+        self.methodCalled = "deleted"
+        self._storageService.hardStop()
+        self._reactor.stop()
+
+
+    def renamed(self):
+        self.methodCalled = "renamed"
+        self._storageService.hardStop()
+        self._reactor.stop()
+
+
+    def connectionLost(self, reason):
+        pass
+
+
+
+class StubStorageService(object):
+    """
+    Implements hardStop for testing
+    """
+
+    def __init__(self, ignored):
+        self.stopCalled = False
+
+
+    def hardStop(self):
+        self.stopCalled = True
+
+
+
+class DirectoryChangeListenerTestCase(TestCase):
+
+    def test_delete(self):
+        """
+        Verify directory deletions can be monitored
+        """
+
+        self.tmpdir = FilePath(self.mktemp())
+        self.tmpdir.makedirs()
+
+        def deleteAction():
+            self.tmpdir.remove()
+
+        resource = KQueueReactorTestFixture(self, deleteAction)
+        storageService = StubStorageService(resource.reactor)
+        delegate = DataStoreMonitor(resource.reactor, storageService)
+        dcl = DirectoryChangeListener(resource.reactor, self.tmpdir.path, delegate)
+        dcl.startListening()
+        resource.runReactor()
+        self.assertTrue(storageService.stopCalled)
+        self.assertEquals(delegate.methodCalled, "deleted")
+
+
+    def test_rename(self):
+        """
+        Verify directory renames can be monitored
+        """
+
+        self.tmpdir = FilePath(self.mktemp())
+        self.tmpdir.makedirs()
+
+        def renameAction():
+            self.tmpdir.moveTo(FilePath(self.mktemp()))
+
+        resource = KQueueReactorTestFixture(self, renameAction)
+        storageService = StubStorageService(resource.reactor)
+        delegate = DataStoreMonitor(resource.reactor, storageService)
+        dcl = DirectoryChangeListener(resource.reactor, self.tmpdir.path, delegate)
+        dcl.startListening()
+        resource.runReactor()
+        self.assertTrue(storageService.stopCalled)
+        self.assertEquals(delegate.methodCalled, "renamed")
+
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20130730/707835ec/attachment.html>


More information about the calendarserver-changes mailing list