Ticket #577: 577testmodifications.darcspatch.txt

File 577testmodifications.darcspatch.txt, 8.4 KB (added by kevan, at 2010-02-20T22:18:08Z)
Line 
1Sat Feb 20 13:07:13 PST 2010  Kevan Carstensen <kevan@isnotajoke.com>
2  * Change OphandleTable to use a deterministic clock, so we can test it
3 
4  To test the changes for #577, we need a deterministic way to simulate
5  the passage of long periods of time. twisted.internet.task.Clock seems,
6  from my Googling, to be the way to go for this functionality. I changed
7  a few things so that OphandleTable would use twisted.internet.task.Clock
8  when testing:
9 
10    * WebishServer.__init___ now takes an optional 'clock' parameter,
11    * which it passes to the root.Root instance it creates.
12    * root.Root.__init__ now takes an optional 'clock' parameter, which it
13      passes to the OphandleTable.__init__ method.
14    * OphandleTable.__init__ now takes an optional 'clock' parameter. If
15      it is provided, and it isn't None, its callLater method will be used
16      to schedule ophandle expirations (as opposed to using
17      reactor.callLater, which is what OphandleTable does normally).
18    * The WebMixin object in test_web.py now sets a self.clock parameter,
19      which is a twisted.internet.task.Clock that it feeds to the
20      WebishServer it creates.
21 
22  Tests using the WebMixin can control the passage of time in
23  OphandleTable by accessing self.clock.
24
25New patches:
26
27[Change OphandleTable to use a deterministic clock, so we can test it
28Kevan Carstensen <kevan@isnotajoke.com>**20100220210713
29 Ignore-this: a7437f4eda359bdfa243bd534f23bf52
30 
31 To test the changes for #577, we need a deterministic way to simulate
32 the passage of long periods of time. twisted.internet.task.Clock seems,
33 from my Googling, to be the way to go for this functionality. I changed
34 a few things so that OphandleTable would use twisted.internet.task.Clock
35 when testing:
36 
37   * WebishServer.__init___ now takes an optional 'clock' parameter,
38   * which it passes to the root.Root instance it creates.
39   * root.Root.__init__ now takes an optional 'clock' parameter, which it
40     passes to the OphandleTable.__init__ method.
41   * OphandleTable.__init__ now takes an optional 'clock' parameter. If
42     it is provided, and it isn't None, its callLater method will be used
43     to schedule ophandle expirations (as opposed to using
44     reactor.callLater, which is what OphandleTable does normally).
45   * The WebMixin object in test_web.py now sets a self.clock parameter,
46     which is a twisted.internet.task.Clock that it feeds to the
47     WebishServer it creates.
48 
49 Tests using the WebMixin can control the passage of time in
50 OphandleTable by accessing self.clock.
51] {
52hunk ./src/allmydata/test/test_web.py 7
53 from twisted.application import service
54 from twisted.trial import unittest
55 from twisted.internet import defer, reactor
56+from twisted.internet.task import Clock
57 from twisted.web import client, error, http
58 from twisted.python import failure, log
59 from nevow import rend
60hunk ./src/allmydata/test/test_web.py 123
61         self.s = FakeClient()
62         self.s.startService()
63         self.staticdir = self.mktemp()
64-        self.ws = webish.WebishServer(self.s, "0", staticdir=self.staticdir)
65+        self.clock = Clock()
66+        self.ws = webish.WebishServer(self.s, "0", staticdir=self.staticdir,
67+                                      clock=self.clock)
68         self.ws.setServiceParent(self.s)
69         self.webish_port = port = self.ws.listener._port.getHost().port
70         self.webish_url = "http://localhost:%d" % port
71hunk ./src/allmydata/test/test_web.py 2871
72             self.failUnless("finished" in data, res)
73         d.addCallback(_check1)
74         # the retain-for=0 will cause the handle to be expired very soon
75-        d.addCallback(self.stall, 2.0)
76+        d.addCallback(lambda ign:
77+            self.clock.advance(2.0))
78         d.addCallback(lambda ignored:
79                       self.shouldHTTPError("test_ophandle_retainfor",
80                                            404, "404 Not Found",
81hunk ./src/allmydata/web/operations.py 26
82     UNCOLLECTED_HANDLE_LIFETIME = 1*HOUR
83     COLLECTED_HANDLE_LIFETIME = 10*MINUTE
84 
85-    def __init__(self):
86+    def __init__(self, clock=None):
87         # both of these are indexed by ophandle
88         self.handles = {} # tuple of (monitor, renderer, when_added)
89         self.timers = {}
90hunk ./src/allmydata/web/operations.py 30
91+        # The tests will provide a deterministic clock
92+        # (twisted.internet.task.Clock) that they can control so that
93+        # they can test ophandle expiration. If this is provided, I'll
94+        # use it schedule the expiration of ophandles.
95+        self.clock = clock
96 
97     def stopService(self):
98         for t in self.timers.values():
99hunk ./src/allmydata/web/operations.py 110
100     def _set_timer(self, ophandle, when):
101         if ophandle in self.timers and self.timers[ophandle].active():
102             self.timers[ophandle].cancel()
103-        t = reactor.callLater(when, self._release_ophandle, ophandle)
104+        if self.clock:
105+            t = self.clock.callLater(when, self._release_ophandle, ophandle)
106+        else:
107+            t = reactor.callLater(when, self._release_ophandle, ophandle)
108         self.timers[ophandle] = t
109 
110     def _release_ophandle(self, ophandle):
111hunk ./src/allmydata/web/root.py 148
112     addSlash = True
113     docFactory = getxmlfile("welcome.xhtml")
114 
115-    def __init__(self, client):
116+    def __init__(self, client, clock=None):
117         rend.Page.__init__(self, client)
118         self.client = client
119hunk ./src/allmydata/web/root.py 151
120-        self.child_operations = operations.OphandleTable()
121+        # If set, clock is a twisted.internet.task.Clock that the tests
122+        # use to test ophandle expiration.
123+        self.child_operations = operations.OphandleTable(clock)
124         try:
125             s = client.getServiceNamed("storage")
126         except KeyError:
127hunk ./src/allmydata/webish.py 124
128 class WebishServer(service.MultiService):
129     name = "webish"
130 
131-    def __init__(self, client, webport, nodeurl_path=None, staticdir=None):
132+    def __init__(self, client, webport, nodeurl_path=None, staticdir=None,
133+                                        clock=None):
134         service.MultiService.__init__(self)
135         # the 'data' argument to all render() methods default to the Client
136hunk ./src/allmydata/webish.py 128
137-        self.root = root.Root(client)
138+        # the 'clock' argument to root.Root is, if set, a
139+        # twisted.internet.task.Clock that is provided by the unit tests
140+        # so that they can test features that involve the passage of
141+        # time in a deterministic manner.
142+        self.root = root.Root(client, clock)
143         self.buildServer(webport, nodeurl_path, staticdir)
144         if self.root.child_operations:
145             self.site.remember(self.root.child_operations, IOpHandleTable)
146}
147
148Context:
149
150[setup: comment-out the dependency on pycrypto, see #953
151zooko@zooko.com**20100215050844
152 Ignore-this: 2751120921ff35b8189d8fcd896da149
153]
154[web/storage.py: display total-seen on the last-complete-cycle line. For #940.
155Brian Warner <warner@lothar.com>**20100208002010
156 Ignore-this: c0ed860f3e9628d3171d2b055d96c5aa
157]
158[Add tests for #939
159Kevan Carstensen <kevan@isnotajoke.com>**20100212062137
160 Ignore-this: 5459e8c64ba76cca70aa720e68549637
161]
162[Alter CLI utilities to handle nonexistent aliases better
163Kevan Carstensen <kevan@isnotajoke.com>**20100211024318
164 Ignore-this: e698ea4a57f5fe27c24336581ca0cf65
165]
166[adding pycrypto to the auto dependencies
167secorp@allmydata.com**20100206054314
168 Ignore-this: b873fc00a6a5b001d30d479e6053cf2f
169]
170[docs running.html - "tahoe run ." does not work with the current installation, replaced with "tahoe start ."
171secorp@allmydata.com**20100206165320
172 Ignore-this: fdb2dcb0e417d303cd43b1951a4f8c03
173]
174[code coverage: replace figleaf with coverage.py, should work on py2.6 now.
175Brian Warner <warner@lothar.com>**20100203165421
176 Ignore-this: 46ab590360be6a385cb4fc4e68b6b42c
177 
178 It still lacks the right HTML report (the builtin report is very pretty, but
179 lacks the "lines uncovered" numbers that I want), and the half-finished
180 delta-from-last-run measurements.
181]
182[More comprehensive changes and ticket references for NEWS
183david-sarah@jacaranda.org**20100202061256
184 Ignore-this: 696cf0106e8a7fd388afc5b55fba8a1b
185]
186[docs: install.html: link into Python 2.5.5 download page
187zooko@zooko.com**20100202065852
188 Ignore-this: 1a9471b8175b7de5741d8445a7ede29d
189]
190[TAG allmydata-tahoe-1.6.0
191zooko@zooko.com**20100202061125
192 Ignore-this: dee6ade7ac1452cf5d1d9c69a8146d84
193]
194Patch bundle hash:
1954c2db026660c5f16ae93d624f6757e7bcbc5c9ee