Sat Feb 20 17:04:55 PST 2010 Kevan Carstensen * Add tests for the ophandle expiration behavior in #577 New patches: [Add tests for the ophandle expiration behavior in #577 Kevan Carstensen **20100221010455 Ignore-this: 87a435108999c24920354b58fd78353f ] { hunk ./src/allmydata/test/test_web.py 370 self.fail("%s was supposed to Error(404), not get '%s'" % (which, res)) + def should302(self, res, which): + if isinstance(res, failure.Failure): + res.trap(error.Error) + self.failUnlessEqual(res.value.status, "302") + else: + self.fail("%s was supposed to Error(302), not get '%s'" % + (which, res)) + class Web(WebMixin, WebErrorMixin, testutil.StallMixin, unittest.TestCase): def test_create(self): hunk ./src/allmydata/test/test_web.py 2900 "/operations/130?t=status&output=JSON")) return d + def test_uncollected_ophandle_expiration(self): + # uncollected ophandles should expire after 4 days + def _make_uncollected_ophandle(ophandle): + d = self.POST(self.public_url + + "/foo/?t=start-manifest&ophandle=%d" % ophandle, + followRedirect=False) + # When we start the operation, the webapi server will want + # to redirect us to the page for the ophandle, so we get + # confirmation that the operation has started. If the + # manifest operation has finished by the time we get there, + # following that redirect (by setting followRedirect=True + # above) has the side effect of collecting the ophandle that + # we've just created, which means that we can't use the + # ophandle to test the uncollected timeout anymore. So, + # instead, catch the 302 here and don't follow it. + d.addBoth(self.should302, "uncollected_ophandle_creation") + return d + # Create an ophandle, don't collect it, then advance the clock by + # 4 days - 1 second and make sure that the ophandle is still there. + d = _make_uncollected_ophandle(131) + d.addCallback(lambda ign: + self.clock.advance((96*60*60) - 1)) # 96 hours = 4 days + d.addCallback(lambda ign: + self.GET("/operations/131?t=status&output=JSON")) + def _check1(res): + data = simplejson.loads(res) + self.failUnless("finished" in data, res) + d.addCallback(_check1) + # Create an ophandle, don't collect it, then try to collect it + # after 4 days. It should be gone. + d.addCallback(lambda ign: + _make_uncollected_ophandle(132)) + d.addCallback(lambda ign: + self.clock.advance(96*60*60)) + d.addCallback(lambda ign: + self.shouldHTTPError("test_uncollected_ophandle_expired_after_100_hours", + 404, "404 Not Found", + "unknown/expired handle '132'", + self.GET, + "/operations/132?t=status&output=JSON")) + return d + + def test_collected_ophandle_expiration(self): + # collected ophandles should expire after 1 day + def _make_collected_ophandle(ophandle): + d = self.POST(self.public_url + + "/foo/?t=start-manifest&ophandle=%d" % ophandle, + followRedirect=True) + # By following the initial redirect, we collect the ophandle + # we've just created. + return d + # Create a collected ophandle, then collect it after 23 hours + # and 59 seconds to make sure that it is still there. + d = _make_collected_ophandle(133) + d.addCallback(lambda ign: + self.clock.advance((24*60*60) - 1)) + d.addCallback(lambda ign: + self.GET("/operations/133?t=status&output=JSON")) + def _check1(res): + data = simplejson.loads(res) + self.failUnless("finished" in data, res) + d.addCallback(_check1) + # Create another uncollected ophandle, then try to collect it + # after 24 hours to make sure that it is gone. + d.addCallback(lambda ign: + _make_collected_ophandle(134)) + d.addCallback(lambda ign: + self.clock.advance(24*60*60)) + d.addCallback(lambda ign: + self.shouldHTTPError("test_collected_ophandle_expired_after_1000_minutes", + 404, "404 Not Found", + "unknown/expired handle '134'", + self.GET, + "/operations/134?t=status&output=JSON")) + return d + def test_incident(self): d = self.POST("/report_incident", details="eek") def _done(res): } Context: [setup: comment-out the dependency on pycrypto, see #953 zooko@zooko.com**20100215050844 Ignore-this: 2751120921ff35b8189d8fcd896da149 ] [web/storage.py: display total-seen on the last-complete-cycle line. For #940. Brian Warner **20100208002010 Ignore-this: c0ed860f3e9628d3171d2b055d96c5aa ] [Add tests for #939 Kevan Carstensen **20100212062137 Ignore-this: 5459e8c64ba76cca70aa720e68549637 ] [Alter CLI utilities to handle nonexistent aliases better Kevan Carstensen **20100211024318 Ignore-this: e698ea4a57f5fe27c24336581ca0cf65 ] [adding pycrypto to the auto dependencies secorp@allmydata.com**20100206054314 Ignore-this: b873fc00a6a5b001d30d479e6053cf2f ] [docs running.html - "tahoe run ." does not work with the current installation, replaced with "tahoe start ." secorp@allmydata.com**20100206165320 Ignore-this: fdb2dcb0e417d303cd43b1951a4f8c03 ] [code coverage: replace figleaf with coverage.py, should work on py2.6 now. Brian Warner **20100203165421 Ignore-this: 46ab590360be6a385cb4fc4e68b6b42c It still lacks the right HTML report (the builtin report is very pretty, but lacks the "lines uncovered" numbers that I want), and the half-finished delta-from-last-run measurements. ] [More comprehensive changes and ticket references for NEWS david-sarah@jacaranda.org**20100202061256 Ignore-this: 696cf0106e8a7fd388afc5b55fba8a1b ] [docs: install.html: link into Python 2.5.5 download page zooko@zooko.com**20100202065852 Ignore-this: 1a9471b8175b7de5741d8445a7ede29d ] [TAG allmydata-tahoe-1.6.0 zooko@zooko.com**20100202061125 Ignore-this: dee6ade7ac1452cf5d1d9c69a8146d84 ] Patch bundle hash: 2052e1f5d647eee0e79d7123b2e8cbfc6b0efb6b