diff --git a/src/allmydata/test/test_web.py b/src/allmydata/test/test_web.py index cd8b2e057..a7304c718 100644 --- a/src/allmydata/test/test_web.py +++ b/src/allmydata/test/test_web.py @@ -4,6 +4,7 @@ from StringIO import StringIO from twisted.application import service from twisted.trial import unittest from twisted.internet import defer, reactor +from twisted.internet.task import Clock from twisted.web import client, error, http from twisted.python import failure, log from nevow import rend @@ -119,7 +120,9 @@ class WebMixin(object): self.s = FakeClient() self.s.startService() self.staticdir = self.mktemp() - self.ws = webish.WebishServer(self.s, "0", staticdir=self.staticdir) + self.clock = Clock() + self.ws = webish.WebishServer(self.s, "0", staticdir=self.staticdir, + clock=self.clock) self.ws.setServiceParent(self.s) self.webish_port = port = self.ws.listener._port.getHost().port self.webish_url = "http://localhost:%d" % port @@ -2873,7 +2876,8 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, unittest.TestCase): self.failUnless("finished" in data, res) d.addCallback(_check1) # the retain-for=0 will cause the handle to be expired very soon - d.addCallback(self.stall, 2.0) + d.addCallback(lambda ign: + self.clock.advance(2.0)) d.addCallback(lambda ignored: self.shouldHTTPError("test_ophandle_retainfor", 404, "404 Not Found", diff --git a/src/allmydata/web/operations.py b/src/allmydata/web/operations.py index 7fbf8d270..8ee9f2027 100644 --- a/src/allmydata/web/operations.py +++ b/src/allmydata/web/operations.py @@ -24,10 +24,15 @@ class OphandleTable(rend.Page, service.Service): UNCOLLECTED_HANDLE_LIFETIME = 4*DAY COLLECTED_HANDLE_LIFETIME = 1*DAY - def __init__(self): + def __init__(self, clock=None): # both of these are indexed by ophandle self.handles = {} # tuple of (monitor, renderer, when_added) self.timers = {} + # The tests will provide a deterministic clock + # (twisted.internet.task.Clock) that they can control so that + # they can test ophandle expiration. If this is provided, I'll + # use it schedule the expiration of ophandles. + self.clock = clock def stopService(self): for t in self.timers.values(): @@ -103,7 +108,10 @@ class OphandleTable(rend.Page, service.Service): def _set_timer(self, ophandle, when): if ophandle in self.timers and self.timers[ophandle].active(): self.timers[ophandle].cancel() - t = reactor.callLater(when, self._release_ophandle, ophandle) + if self.clock: + t = self.clock.callLater(when, self._release_ophandle, ophandle) + else: + t = reactor.callLater(when, self._release_ophandle, ophandle) self.timers[ophandle] = t def _release_ophandle(self, ophandle): diff --git a/src/allmydata/web/root.py b/src/allmydata/web/root.py index ee1cd9211..59ebfbdb5 100644 --- a/src/allmydata/web/root.py +++ b/src/allmydata/web/root.py @@ -145,10 +145,12 @@ class Root(rend.Page): addSlash = True docFactory = getxmlfile("welcome.xhtml") - def __init__(self, client): + def __init__(self, client, clock=None): rend.Page.__init__(self, client) self.client = client - self.child_operations = operations.OphandleTable() + # If set, clock is a twisted.internet.task.Clock that the tests + # use to test ophandle expiration. + self.child_operations = operations.OphandleTable(clock) try: s = client.getServiceNamed("storage") except KeyError: diff --git a/src/allmydata/webish.py b/src/allmydata/webish.py index 57b84ca58..8442bb25d 100644 --- a/src/allmydata/webish.py +++ b/src/allmydata/webish.py @@ -121,10 +121,15 @@ class MyRequest(appserver.NevowRequest): class WebishServer(service.MultiService): name = "webish" - def __init__(self, client, webport, nodeurl_path=None, staticdir=None): + def __init__(self, client, webport, nodeurl_path=None, staticdir=None, + clock=None): service.MultiService.__init__(self) # the 'data' argument to all render() methods default to the Client - self.root = root.Root(client) + # the 'clock' argument to root.Root is, if set, a + # twisted.internet.task.Clock that is provided by the unit tests + # so that they can test features that involve the passage of + # time in a deterministic manner. + self.root = root.Root(client, clock) self.buildServer(webport, nodeurl_path, staticdir) if self.root.child_operations: self.site.remember(self.root.child_operations, IOpHandleTable)