X-Git-Url: https://git.rkrishnan.org/?a=blobdiff_plain;f=src%2Fallmydata%2Ftest%2Ftest_web.py;h=2a968f9aed4f5087b6dd74849e9a0e69568364e2;hb=c6449b687a6b2fc95ec9f6afd938a20f60a731ab;hp=00d05097459a814518ea9d494ec5e262f96ed5a9;hpb=35f37cc5b86465407a0eb85a7760f8442f5a969f;p=tahoe-lafs%2Ftahoe-lafs.git diff --git a/src/allmydata/test/test_web.py b/src/allmydata/test/test_web.py index 00d05097..2a968f9a 100644 --- a/src/allmydata/test/test_web.py +++ b/src/allmydata/test/test_web.py @@ -50,7 +50,7 @@ unknown_rocap = u"ro.lafs://readonly_from_the_future_ro_\u263A".encode('utf-8') unknown_immcap = u"imm.lafs://immutable_from_the_future_imm_\u263A".encode('utf-8') FAVICON_MARKUP = '' - +DIR_HTML_TAG = '' class FakeStatsProvider: def get_stats(self): @@ -172,25 +172,34 @@ class FakeHistory: return [] class FakeDisplayableServer(StubServer): - def __init__(self, serverid, nickname): + def __init__(self, serverid, nickname, connected, + last_connect_time, last_loss_time, last_rx_time): StubServer.__init__(self, serverid) self.announcement = {"my-version": "allmydata-tahoe-fake", "service-name": "storage", "nickname": nickname} + self.connected = connected + self.last_loss_time = last_loss_time + self.last_rx_time = last_rx_time + self.last_connect_time = last_connect_time def is_connected(self): - return True + return self.connected def get_permutation_seed(self): return "" def get_remote_host(self): return "" def get_last_loss_time(self): - return None - def get_announcement_time(self): - return None + return self.last_loss_time + def get_last_received_data_time(self): + return self.last_rx_time + def get_last_connect_time(self): + return self.last_connect_time def get_announcement(self): return self.announcement def get_nickname(self): return self.announcement["nickname"] + def get_available_space(self): + return 123456 class FakeBucketCounter(object): def get_state(self): @@ -240,7 +249,13 @@ class FakeClient(Client): self.storage_broker = StorageFarmBroker(None, permute_peers=True) # fake knowledge of another server self.storage_broker.test_add_server("other_nodeid", - FakeDisplayableServer("other_nodeid", u"other_nickname \u263B")) + FakeDisplayableServer( + serverid="other_nodeid", nickname=u"other_nickname \u263B", connected = True, + last_connect_time = 10, last_loss_time = 20, last_rx_time = 30)) + self.storage_broker.test_add_server("disconnected_nodeid", + FakeDisplayableServer( + serverid="other_nodeid", nickname=u"disconnected_nickname \u263B", connected = False, + last_connect_time = 15, last_loss_time = 25, last_rx_time = 35)) self.introducer_client = None self.history = FakeHistory() self.uploader = FakeUploader() @@ -254,6 +269,11 @@ class FakeClient(Client): self.mutable_file_default = SDMF_VERSION self.addService(FakeStorageServer(self.nodeid, self.nickname)) + def get_long_nodeid(self): + return "v0-nodeid" + def get_long_tubid(self): + return "tubid" + def startService(self): return service.MultiService.startService(self) def stopService(self): @@ -261,14 +281,16 @@ class FakeClient(Client): MUTABLE_SIZELIMIT = FakeMutableFileNode.MUTABLE_SIZELIMIT -class WebMixin(object): +class WebMixin(testutil.TimezoneMixin): def setUp(self): + self.setTimezone('UTC-13:00') self.s = FakeClient() self.s.startService() self.staticdir = self.mktemp() self.clock = Clock() + self.fakeTime = 86460 # 1d 0h 1m 0s self.ws = webish.WebishServer(self.s, "0", staticdir=self.staticdir, - clock=self.clock) + clock=self.clock, now_fn=lambda:self.fakeTime) self.ws.setServiceParent(self.s) self.webish_port = self.ws.getPortnum() self.webish_url = self.ws.getURL() @@ -594,7 +616,6 @@ class WebMixin(object): self.fail("%s was supposed to Error(302), not get '%s'" % (which, res)) - class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixin, unittest.TestCase): def test_create(self): pass @@ -606,11 +627,35 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi self.failUnlessIn(FAVICON_MARKUP, res) self.failUnlessIn('Recent and Active Operations', res) self.failUnlessIn('Operational Statistics', res) - self.failUnlessIn('', res) + self.failUnless(re.search('',res), res) + self.failUnlessIn('Page rendered at', res) + self.failUnlessIn('Tahoe-LAFS code imported from:', res) res_u = res.decode('utf-8') self.failUnlessIn(u'fake_nickname \u263A', res_u) self.failUnlessIn(u'
other_nickname \u263B
', res_u) + self.failUnlessIn(u'Connected to 1\n of 2 known storage servers', res_u) + def timestamp(t): + return (u'"%s"' % (t,)) if self.have_working_tzset() else u'"[^"]*"' + self.failUnless(re.search( + u'
' + u'
\n 1d\u00A00h\u00A00m\u00A050s' + % timestamp(u'1970-01-01 13:00:10'), res_u), repr(res_u)) + self.failUnless(re.search( + u'
' + u'
\n 1d\u00A00h\u00A00m\u00A035s' + % timestamp(u'1970-01-01 13:00:25'), res_u), repr(res_u)) + self.failUnless(re.search( + u'' + u'1d\u00A00h\u00A00m\u00A030s' + % timestamp(u'1970-01-01 13:00:30'), res_u), repr(res_u)) + self.failUnless(re.search( + u'' + u'1d\u00A00h\u00A00m\u00A025s' + % timestamp(u'1970-01-01 13:00:35'), res_u), repr(res_u)) + self.failUnlessIn(u'\u00A9 Tahoe-LAFS Software Foundation', res_u) + self.failUnlessIn('

Available

', res) + self.failUnlessIn('123.5kB', res) self.s.basedir = 'web/test_welcome' fileutil.make_dirs("web/test_welcome") @@ -638,7 +683,7 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi html = res.replace('\n', ' ') self.failUnlessIn('
pb://someIntroducer/[censored]
', html) self.failIfIn('pb://someIntroducer/secret', html) - self.failUnless(re.search('
[ ]*
Introducer not connected
', html), res) + self.failUnless(re.search('', html), res) d.addCallback(_check_introducer_not_connected_unguessable) # introducer connected, unguessable furl @@ -651,7 +696,7 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi html = res.replace('\n', ' ') self.failUnlessIn('
pb://someIntroducer/[censored]
', html) self.failIfIn('pb://someIntroducer/secret', html) - self.failUnless(re.search('
[ ]*
Introducer
', html), res) + self.failUnless(re.search('', html), res) d.addCallback(_check_introducer_connected_unguessable) # introducer connected, guessable furl @@ -663,7 +708,7 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi def _check_introducer_connected_guessable(res): html = res.replace('\n', ' ') self.failUnlessIn('
pb://someIntroducer/introducer
', html) - self.failUnless(re.search('
[ ]*
Introducer
', html), res) + self.failUnless(re.search('', html), res) d.addCallback(_check_introducer_connected_guessable) return d @@ -677,7 +722,7 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi d.addCallback(_set_no_helper) def _check_no_helper(res): html = res.replace('\n', ' ') - self.failUnless(re.search('
[ ]*
Helper
', html), res) + self.failUnless(re.search('', html), res) d.addCallback(_check_no_helper) # enable helper, not connected @@ -690,7 +735,7 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi html = res.replace('\n', ' ') self.failUnlessIn('
pb://someHelper/[censored]
', html) self.failIfIn('pb://someHelper/secret', html) - self.failUnless(re.search('
[ ]*
Helper not connected
', html), res) + self.failUnless(re.search('', html), res) d.addCallback(_check_helper_not_connected) # enable helper, connected @@ -703,7 +748,7 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi html = res.replace('\n', ' ') self.failUnlessIn('
pb://someHelper/[censored]
', html) self.failIfIn('pb://someHelper/secret', html) - self.failUnless(re.search('
[ ]*
Helper
', html), res) + self.failUnless(re.search('', html), res) d.addCallback(_check_helper_connected) return d @@ -1498,7 +1543,7 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi def _check_upload_and_mkdir_forms(self, html): # We should have a form to create a file, with radio buttons that allow # the user to toggle whether it is a CHK/LIT (default), SDMF, or MDMF file. - self.failUnlessIn('name="t" value="upload"', html) + self.failUnless(re.search('', html), html) self.failUnless(re.search('', html), html) self.failUnless(re.search('
Return to Welcome page', html) + self.failUnlessIn('
  • Return to Welcome page
  • ', html) self._check_upload_and_mkdir_forms(html) self.failUnlessIn("quux", html) d.addCallback(_check) @@ -1609,7 +1654,7 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi d.addCallback(lambda res: self.GET(self.public_url + "/foo/empty/")) def _check4(res): self.failUnlessIn("directory is empty", res) - MKDIR_BUTTON_RE=re.compile('.*Create a new directory in this directory.*', re.I) + MKDIR_BUTTON_RE=re.compile('.*Create a new directory in this directory.*', re.I) self.failUnless(MKDIR_BUTTON_RE.search(res), res) d.addCallback(_check4) @@ -3247,10 +3292,10 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi d = self.GET("/") def _after_get_welcome_page(res): MKDIR_BUTTON_RE = re.compile( - '
    [ ]*' - '[ ]*' - '') + '.*' + '[ ]*' + '[ ]*' + '') html = res.replace('\n', ' ') mo = MKDIR_BUTTON_RE.search(html) self.failUnless(mo, html) @@ -3863,8 +3908,8 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi d = self.GET(self.public_url + "/foo?t=rename-form&name=bar.txt", followRedirect=True) def _check(res): - self.failUnlessIn('name="when_done" value="."', res) - self.failUnless(re.search(r'name="from_name" value="bar\.txt"', res)) + self.failUnless(re.search('', res), res) + self.failUnless(re.search(r'', res), res) self.failUnlessIn(FAVICON_MARKUP, res) d.addCallback(_check) return d @@ -4372,7 +4417,7 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi d = self.POST("/report_incident", details="eek") def _done(res): self.failIfIn("", res) - self.failUnlessIn("Thank you for your report!", res) + self.failUnlessIn("An incident report has been saved", res) d.addCallback(_done) return d @@ -4404,7 +4449,11 @@ class IntroducerWeb(unittest.TestCase): def test_welcome(self): basedir = "web.IntroducerWeb.test_welcome" os.mkdir(basedir) - fileutil.write(os.path.join(basedir, "tahoe.cfg"), "[node]\nweb.port = tcp:0\n") + cfg = "\n".join(["[node]", + "tub.location = 127.0.0.1:1", + "web.port = tcp:0", + ]) + "\n" + fileutil.write(os.path.join(basedir, "tahoe.cfg"), cfg) self.node = IntroducerNode(basedir) self.ws = self.node.getServiceNamed("webish") @@ -4416,6 +4465,8 @@ class IntroducerWeb(unittest.TestCase): def _check(res): self.failUnlessIn('Welcome to the Tahoe-LAFS Introducer', res) self.failUnlessIn(FAVICON_MARKUP, res) + self.failUnlessIn('Page rendered at', res) + self.failUnlessIn('Tahoe-LAFS code imported from:', res) d.addCallback(_check) return d @@ -4571,7 +4622,7 @@ class Grid(GridTestMixin, WebErrorMixin, ShouldFailMixin, testutil.ReallyEqualMi r = simplejson.loads(res) self.failUnlessEqual(r["summary"], "Healthy") self.failUnless(r["results"]["healthy"]) - self.failIf(r["results"]["needs-rebalancing"]) + self.failIfIn("needs-rebalancing", r["results"]) self.failUnless(r["results"]["recoverable"]) d.addCallback(_got_json_good) @@ -4615,8 +4666,8 @@ class Grid(GridTestMixin, WebErrorMixin, ShouldFailMixin, testutil.ReallyEqualMi self.failUnlessEqual(r["summary"], "Not Healthy: 9 shares (enc 3-of-10)") self.failIf(r["results"]["healthy"]) - self.failIf(r["results"]["needs-rebalancing"]) self.failUnless(r["results"]["recoverable"]) + self.failIfIn("needs-rebalancing", r["results"]) d.addCallback(_got_json_sick) d.addCallback(self.CHECK, "dead", "t=check") @@ -4629,8 +4680,8 @@ class Grid(GridTestMixin, WebErrorMixin, ShouldFailMixin, testutil.ReallyEqualMi self.failUnlessEqual(r["summary"], "Not Healthy: 1 shares (enc 3-of-10)") self.failIf(r["results"]["healthy"]) - self.failIf(r["results"]["needs-rebalancing"]) self.failIf(r["results"]["recoverable"]) + self.failIfIn("needs-rebalancing", r["results"]) d.addCallback(_got_json_dead) d.addCallback(self.CHECK, "corrupt", "t=check&verify=true") @@ -4643,6 +4694,8 @@ class Grid(GridTestMixin, WebErrorMixin, ShouldFailMixin, testutil.ReallyEqualMi self.failUnlessIn("Unhealthy: 9 shares (enc 3-of-10)", r["summary"]) self.failIf(r["results"]["healthy"]) self.failUnless(r["results"]["recoverable"]) + self.failIfIn("needs-rebalancing", r["results"]) + self.failUnlessReallyEqual(r["results"]["count-happiness"], 9) self.failUnlessReallyEqual(r["results"]["count-shares-good"], 9) self.failUnlessReallyEqual(r["results"]["count-corrupt-shares"], 1) d.addCallback(_got_json_corrupt) @@ -5091,12 +5144,14 @@ class Grid(GridTestMixin, WebErrorMixin, ShouldFailMixin, testutil.ReallyEqualMi self.failUnlessEqual(u0["type"], "directory") self.failUnlessReallyEqual(to_str(u0["cap"]), self.rootnode.get_uri()) u0cr = u0["check-results"] + self.failUnlessReallyEqual(u0cr["results"]["count-happiness"], 10) self.failUnlessReallyEqual(u0cr["results"]["count-shares-good"], 10) ugood = [u for u in units if u["type"] == "file" and u["path"] == [u"good"]][0] self.failUnlessReallyEqual(to_str(ugood["cap"]), self.uris["good"]) ugoodcr = ugood["check-results"] + self.failUnlessReallyEqual(ugoodcr["results"]["count-happiness"], 10) self.failUnlessReallyEqual(ugoodcr["results"]["count-shares-good"], 10) stats = units[-1] @@ -5195,6 +5250,7 @@ class Grid(GridTestMixin, WebErrorMixin, ShouldFailMixin, testutil.ReallyEqualMi self.failUnlessEqual(last_unit["path"], ["subdir"]) r = last_unit["check-results"]["results"] self.failUnlessReallyEqual(r["count-recoverable-versions"], 0) + self.failUnlessReallyEqual(r["count-happiness"], 1) self.failUnlessReallyEqual(r["count-shares-good"], 1) self.failUnlessReallyEqual(r["recoverable"], False) d.addCallback(_check_broken_deepcheck) @@ -5272,6 +5328,7 @@ class Grid(GridTestMixin, WebErrorMixin, ShouldFailMixin, testutil.ReallyEqualMi self.failUnlessReallyEqual(to_str(u0["cap"]), self.rootnode.get_uri()) u0crr = u0["check-and-repair-results"] self.failUnlessReallyEqual(u0crr["repair-attempted"], False) + self.failUnlessReallyEqual(u0crr["pre-repair-results"]["results"]["count-happiness"], 10) self.failUnlessReallyEqual(u0crr["pre-repair-results"]["results"]["count-shares-good"], 10) ugood = [u for u in units @@ -5279,6 +5336,7 @@ class Grid(GridTestMixin, WebErrorMixin, ShouldFailMixin, testutil.ReallyEqualMi self.failUnlessEqual(to_str(ugood["cap"]), self.uris["good"]) ugoodcrr = ugood["check-and-repair-results"] self.failUnlessReallyEqual(ugoodcrr["repair-attempted"], False) + self.failUnlessReallyEqual(ugoodcrr["pre-repair-results"]["results"]["count-happiness"], 10) self.failUnlessReallyEqual(ugoodcrr["pre-repair-results"]["results"]["count-shares-good"], 10) usick = [u for u in units @@ -5287,7 +5345,9 @@ class Grid(GridTestMixin, WebErrorMixin, ShouldFailMixin, testutil.ReallyEqualMi usickcrr = usick["check-and-repair-results"] self.failUnlessReallyEqual(usickcrr["repair-attempted"], True) self.failUnlessReallyEqual(usickcrr["repair-successful"], True) + self.failUnlessReallyEqual(usickcrr["pre-repair-results"]["results"]["count-happiness"], 9) self.failUnlessReallyEqual(usickcrr["pre-repair-results"]["results"]["count-shares-good"], 9) + self.failUnlessReallyEqual(usickcrr["post-repair-results"]["results"]["count-happiness"], 10) self.failUnlessReallyEqual(usickcrr["post-repair-results"]["results"]["count-shares-good"], 10) stats = units[-1] @@ -5483,7 +5543,7 @@ class Grid(GridTestMixin, WebErrorMixin, ShouldFailMixin, testutil.ReallyEqualMi self.basedir = "web/Grid/exceptions" self.set_up_grid(num_clients=1, num_servers=2) c0 = self.g.clients[0] - c0.DEFAULT_ENCODING_PARAMETERS['happy'] = 2 + c0.encoding_params['happy'] = 2 self.fileurls = {} DATA = "data" * 100 d = c0.create_dirnode() @@ -5572,7 +5632,7 @@ class Grid(GridTestMixin, WebErrorMixin, ShouldFailMixin, testutil.ReallyEqualMi d.addCallback(lambda ignored: self.GET(self.fileurls["dir-0share"])) def _check_0shares_dir_html(body): - self.failUnlessIn("", body) + self.failUnlessIn(DIR_HTML_TAG, body) # we should see the regular page, but without the child table or # the dirops forms body = " ".join(body.strip().split()) @@ -5595,7 +5655,7 @@ class Grid(GridTestMixin, WebErrorMixin, ShouldFailMixin, testutil.ReallyEqualMi # and some-shares like we did for immutable files (since there # are different sorts of advice to offer in each case). For now, # they present the same way. - self.failUnlessIn("", body) + self.failUnlessIn(DIR_HTML_TAG, body) body = " ".join(body.strip().split()) self.failUnlessIn('href="?t=info">More info on this directory', body) @@ -5722,7 +5782,7 @@ class Grid(GridTestMixin, WebErrorMixin, ShouldFailMixin, testutil.ReallyEqualMi d.addCallback(_stash_dir) d.addCallback(lambda ign: self.GET(self.dir_url, followRedirect=True)) def _check_dir_html(body): - self.failUnlessIn("", body) + self.failUnlessIn(DIR_HTML_TAG, body) self.failUnlessIn("blacklisted.txt", body) d.addCallback(_check_dir_html) d.addCallback(lambda ign: self.GET(self.url)) @@ -5746,7 +5806,7 @@ class Grid(GridTestMixin, WebErrorMixin, ShouldFailMixin, testutil.ReallyEqualMi # We should still be able to list the parent directory, in HTML... d.addCallback(lambda ign: self.GET(self.dir_url, followRedirect=True)) def _check_dir_html2(body): - self.failUnlessIn("", body) + self.failUnlessIn(DIR_HTML_TAG, body) self.failUnlessIn("blacklisted.txt", body) d.addCallback(_check_dir_html2) @@ -5797,7 +5857,7 @@ class Grid(GridTestMixin, WebErrorMixin, ShouldFailMixin, testutil.ReallyEqualMi self.child_url = "uri/"+dn.get_readonly_uri()+"/child" d.addCallback(_get_dircap) d.addCallback(lambda ign: self.GET(self.dir_url_base, followRedirect=True)) - d.addCallback(lambda body: self.failUnlessIn("", body)) + d.addCallback(lambda body: self.failUnlessIn(DIR_HTML_TAG, body)) d.addCallback(lambda ign: self.GET(self.dir_url_json1)) d.addCallback(lambda res: simplejson.loads(res)) # just check it decodes d.addCallback(lambda ign: self.GET(self.dir_url_json2))