From 6cf4096156594724406fa370f2ebd4fd3d0b80bf Mon Sep 17 00:00:00 2001 From: Brian Warner <warner@allmydata.com> Date: Tue, 24 Feb 2009 20:00:10 -0700 Subject: [PATCH] test_deepcheck: convert MutableChecker to no-network GridTest --- src/allmydata/test/common.py | 17 ++++- src/allmydata/test/test_deepcheck.py | 108 ++++++++++----------------- 2 files changed, 55 insertions(+), 70 deletions(-) diff --git a/src/allmydata/test/common.py b/src/allmydata/test/common.py index fd9cb1bb..be0834d0 100644 --- a/src/allmydata/test/common.py +++ b/src/allmydata/test/common.py @@ -13,7 +13,9 @@ from allmydata.interfaces import IURI, IMutableFileNode, IFileNode, \ from allmydata.check_results import CheckResults, CheckAndRepairResults, \ DeepCheckResults, DeepCheckAndRepairResults from allmydata.mutable.common import CorruptShareError +from allmydata.mutable.layout import unpack_header from allmydata.storage.server import storage_index_to_dir +from allmydata.storage.mutable import MutableShareFile from allmydata.util import hashutil, log, fileutil, pollmixin from allmydata.util.assertutil import precondition from allmydata.stats import StatsGathererService @@ -1255,11 +1257,24 @@ def _corrupt_offset_of_uri_extension_to_force_short_read(data, debug=False): log.msg("testing: corrupting offset %d, size %d, changing %d to %d (len(data) == %d)" % (0x48, 8, struct.unpack(">Q", data[0x48:0x48+8])[0], len(data)-0x0c-3, len(data))) return data[:0x48] + struct.pack(">Q", len(data)-0x0c-3) + data[0x48+8:] +def _corrupt_mutable_share_data(data): + prefix = data[:32] + assert prefix == MutableShareFile.MAGIC, "This function is designed to corrupt mutable shares of v1, and the magic number doesn't look right: %r vs %r" % (prefix, MutableShareFile.MAGIC) + data_offset = MutableShareFile.DATA_OFFSET + sharetype = data[data_offset:data_offset+1] + assert sharetype == "\x00", "non-SDMF mutable shares not supported" + (version, ig_seqnum, ig_roothash, ig_IV, ig_k, ig_N, ig_segsize, + ig_datalen, offsets) = unpack_header(data[data_offset:]) + assert version == 0, "this function only handles v0 SDMF files" + start = data_offset + offsets["share_data"] + length = data_offset + offsets["enc_privkey"] - start + return corrupt_field(data, start, length) + def _corrupt_share_data(data): """ Scramble the file data -- the field containing the share data itself will have one bit flipped or else will be changed to a random value. """ sharevernum = struct.unpack(">L", data[0x0c:0x0c+4])[0] - assert sharevernum in (1, 2), "This test is designed to corrupt immutable shares of v1 or v2 in specific ways." + assert sharevernum in (1, 2), "This test is designed to corrupt immutable shares of v1 or v2 in specific ways, not v%d." % sharevernum if sharevernum == 1: sharedatasize = struct.unpack(">L", data[0x0c+0x08:0x0c+0x08+4])[0] diff --git a/src/allmydata/test/test_deepcheck.py b/src/allmydata/test/test_deepcheck.py index f8d4cfc4..7ec1ed26 100644 --- a/src/allmydata/test/test_deepcheck.py +++ b/src/allmydata/test/test_deepcheck.py @@ -13,9 +13,11 @@ from allmydata.interfaces import ICheckResults, ICheckAndRepairResults, \ from allmydata.monitor import Monitor, OperationCancelledError from twisted.web.client import getPage -from allmydata.test.common import SystemTestMixin, ErrorMixin +from allmydata.test.common import SystemTestMixin, ErrorMixin, \ + _corrupt_mutable_share_data +from allmydata.test.no_network import GridTestMixin -class MutableChecker(SystemTestMixin, unittest.TestCase, ErrorMixin): +class MutableChecker(GridTestMixin, unittest.TestCase, ErrorMixin): def _run_cli(self, argv): stdout, stderr = StringIO(), StringIO() @@ -25,21 +27,18 @@ class MutableChecker(SystemTestMixin, unittest.TestCase, ErrorMixin): return stdout.getvalue() def test_good(self): - self.basedir = self.mktemp() - d = self.set_up_nodes() + self.basedir = "deepcheck/MutableChecker/good" + self.set_up_grid() CONTENTS = "a little bit of data" - d.addCallback(lambda res: self.clients[0].create_mutable_file(CONTENTS)) + d = self.g.clients[0].create_mutable_file(CONTENTS) def _created(node): self.node = node + self.fileurl = "uri/" + urllib.quote(node.get_uri()) si = self.node.get_storage_index() d.addCallback(_created) # now make sure the webapi verifier sees no problems - def _do_check(res): - url = (self.webish_url + - "uri/%s" % urllib.quote(self.node.get_uri()) + - "?t=check&verify=true") - return getPage(url, method="POST") - d.addCallback(_do_check) + d.addCallback(lambda ign: self.GET(self.fileurl+"?t=check&verify=true", + method="POST")) def _got_results(out): self.failUnless("<span>Healthy : Healthy</span>" in out, out) self.failUnless("Recoverable Versions: 10*seq1-" in out, out) @@ -51,31 +50,19 @@ class MutableChecker(SystemTestMixin, unittest.TestCase, ErrorMixin): return d def test_corrupt(self): - self.basedir = self.mktemp() - d = self.set_up_nodes() + self.basedir = "deepcheck/MutableChecker/corrupt" + self.set_up_grid() CONTENTS = "a little bit of data" - d.addCallback(lambda res: self.clients[0].create_mutable_file(CONTENTS)) - def _created(node): + d = self.g.clients[0].create_mutable_file(CONTENTS) + def _stash_and_corrupt(node): self.node = node - si = self.node.get_storage_index() - out = self._run_cli(["debug", "find-shares", base32.b2a(si), - self.clients[1].basedir]) - files = out.split("\n") - # corrupt one of them, using the CLI debug command - f = files[0] - shnum = os.path.basename(f) - nodeid = self.clients[1].nodeid - nodeid_prefix = idlib.shortnodeid_b2a(nodeid) - self.corrupt_shareid = "%s-sh%s" % (nodeid_prefix, shnum) - out = self._run_cli(["debug", "corrupt-share", files[0]]) - d.addCallback(_created) + self.fileurl = "uri/" + urllib.quote(node.get_uri()) + self.corrupt_shares_numbered(node.get_uri(), [0], + _corrupt_mutable_share_data) + d.addCallback(_stash_and_corrupt) # now make sure the webapi verifier notices it - def _do_check(res): - url = (self.webish_url + - "uri/%s" % urllib.quote(self.node.get_uri()) + - "?t=check&verify=true") - return getPage(url, method="POST") - d.addCallback(_do_check) + d.addCallback(lambda ign: self.GET(self.fileurl+"?t=check&verify=true", + method="POST")) def _got_results(out): self.failUnless("Not Healthy!" in out, out) self.failUnless("Unhealthy: best version has only 9 shares (encoding is 3-of-10)" in out, out) @@ -83,16 +70,14 @@ class MutableChecker(SystemTestMixin, unittest.TestCase, ErrorMixin): d.addCallback(_got_results) # now make sure the webapi repairer can fix it - def _do_repair(res): - url = (self.webish_url + - "uri/%s" % urllib.quote(self.node.get_uri()) + - "?t=check&verify=true&repair=true") - return getPage(url, method="POST") - d.addCallback(_do_repair) + d.addCallback(lambda ign: + self.GET(self.fileurl+"?t=check&verify=true&repair=true", + method="POST")) def _got_repair_results(out): self.failUnless("<div>Repair successful</div>" in out, out) d.addCallback(_got_repair_results) - d.addCallback(_do_check) + d.addCallback(lambda ign: self.GET(self.fileurl+"?t=check&verify=true", + method="POST")) def _got_postrepair_results(out): self.failIf("Not Healthy!" in out, out) self.failUnless("Recoverable Versions: 10*seq" in out, out) @@ -102,31 +87,18 @@ class MutableChecker(SystemTestMixin, unittest.TestCase, ErrorMixin): return d def test_delete_share(self): - self.basedir = self.mktemp() - d = self.set_up_nodes() + self.basedir = "deepcheck/MutableChecker/delete_share" + self.set_up_grid() CONTENTS = "a little bit of data" - d.addCallback(lambda res: self.clients[0].create_mutable_file(CONTENTS)) - def _created(node): + d = self.g.clients[0].create_mutable_file(CONTENTS) + def _stash_and_delete(node): self.node = node - si = self.node.get_storage_index() - out = self._run_cli(["debug", "find-shares", base32.b2a(si), - self.clients[1].basedir]) - files = out.split("\n") - # corrupt one of them, using the CLI debug command - f = files[0] - shnum = os.path.basename(f) - nodeid = self.clients[1].nodeid - nodeid_prefix = idlib.shortnodeid_b2a(nodeid) - self.corrupt_shareid = "%s-sh%s" % (nodeid_prefix, shnum) - os.unlink(files[0]) - d.addCallback(_created) + self.fileurl = "uri/" + urllib.quote(node.get_uri()) + self.delete_shares_numbered(node.get_uri(), [0]) + d.addCallback(_stash_and_delete) # now make sure the webapi checker notices it - def _do_check(res): - url = (self.webish_url + - "uri/%s" % urllib.quote(self.node.get_uri()) + - "?t=check&verify=false") - return getPage(url, method="POST") - d.addCallback(_do_check) + d.addCallback(lambda ign: self.GET(self.fileurl+"?t=check&verify=false", + method="POST")) def _got_results(out): self.failUnless("Not Healthy!" in out, out) self.failUnless("Unhealthy: best version has only 9 shares (encoding is 3-of-10)" in out, out) @@ -134,16 +106,14 @@ class MutableChecker(SystemTestMixin, unittest.TestCase, ErrorMixin): d.addCallback(_got_results) # now make sure the webapi repairer can fix it - def _do_repair(res): - url = (self.webish_url + - "uri/%s" % urllib.quote(self.node.get_uri()) + - "?t=check&verify=false&repair=true") - return getPage(url, method="POST") - d.addCallback(_do_repair) + d.addCallback(lambda ign: + self.GET(self.fileurl+"?t=check&verify=false&repair=true", + method="POST")) def _got_repair_results(out): self.failUnless("Repair successful" in out) d.addCallback(_got_repair_results) - d.addCallback(_do_check) + d.addCallback(lambda ign: self.GET(self.fileurl+"?t=check&verify=false", + method="POST")) def _got_postrepair_results(out): self.failIf("Not Healthy!" in out, out) self.failUnless("Recoverable Versions: 10*seq" in out) -- 2.45.2