def test_chk_filenode(self): u = uri.CHKFileURI(key="\x00" * 16, uri_extension_hash="\x00" * 32, needed_shares=3, total_shares=10, size=1000) fn1 = ImmutableFileNode(u, None, None, None, None) fn2 = ImmutableFileNode(u, None, None, None, None) self.failUnlessEqual(fn1, fn2) self.failIfEqual(fn1, "I am not a filenode") self.failIfEqual(fn1, NotANode()) self.failUnlessEqual(fn1.get_uri(), u.to_string()) self.failUnlessEqual(fn1.get_cap(), u) self.failUnlessEqual(fn1.get_readcap(), u) self.failUnless(fn1.is_readonly()) self.failIf(fn1.is_mutable()) self.failIf(fn1.is_unknown()) self.failUnless(fn1.is_allowed_in_immutable_directory()) self.failUnlessEqual(fn1.get_write_uri(), None) self.failUnlessEqual(fn1.get_readonly_uri(), u.to_string()) self.failUnlessEqual(fn1.get_size(), 1000) self.failUnlessEqual(fn1.get_storage_index(), u.get_storage_index()) fn1.raise_error() fn2.raise_error() d = {} d[fn1] = 1 # exercise __hash__ v = fn1.get_verify_cap() self.failUnless(isinstance(v, uri.CHKFileVerifierURI)) self.failUnlessEqual(fn1.get_repair_cap(), v) self.failUnless(v.is_readonly()) self.failIf(v.is_mutable())
def test_immutable(self): readkey = "\x01" * 16 uri_extension_hash = hashutil.uri_extension_hash("stuff") needed_shares = 3 total_shares = 10 size = 1234 fnuri = uri.CHKFileURI(key=readkey, uri_extension_hash=uri_extension_hash, needed_shares=needed_shares, total_shares=total_shares, size=size) fncap = fnuri.to_string() self.failUnlessReallyEqual(fncap, "URI:CHK:aeaqcaibaeaqcaibaeaqcaibae:nf3nimquen7aeqm36ekgxomalstenpkvsdmf6fplj7swdatbv5oa:3:10:1234") u1 = uri.ImmutableDirectoryURI(fnuri) self.failUnless(u1.is_readonly()) self.failIf(u1.is_mutable()) self.failUnless(IURI.providedBy(u1)) self.failIf(IFileURI.providedBy(u1)) self.failUnless(IDirnodeURI.providedBy(u1)) self.failUnless("DirectoryURI" in str(u1)) u1_filenode = u1.get_filenode_cap() self.failIf(u1_filenode.is_mutable()) self.failUnless(u1_filenode.is_readonly()) self.failUnlessReallyEqual(u1_filenode.to_string(), fncap) self.failUnless(str(u1)) u2 = uri.from_string(u1.to_string()) self.failUnlessReallyEqual(u1.to_string(), u2.to_string()) self.failUnless(u2.is_readonly()) self.failIf(u2.is_mutable()) self.failUnless(IURI.providedBy(u2)) self.failIf(IFileURI.providedBy(u2)) self.failUnless(IDirnodeURI.providedBy(u2)) u2i = uri.from_string(u1.to_string(), deep_immutable=True) self.failUnlessReallyEqual(u1.to_string(), u2i.to_string()) u3 = u2.get_readonly() self.failUnlessReallyEqual(u3.to_string(), u2.to_string()) self.failUnless(str(u3)) u3i = uri.from_string(u2.to_string(), deep_immutable=True) self.failUnlessReallyEqual(u2.to_string(), u3i.to_string()) u2_verifier = u2.get_verify_cap() self.failUnless(isinstance(u2_verifier, uri.ImmutableDirectoryURIVerifier), u2_verifier) self.failUnless(IVerifierURI.providedBy(u2_verifier)) u2vs = u2_verifier.to_string() # URI:DIR2-CHK-Verifier:$key:$ueb:$k:$n:$size self.failUnless(u2vs.startswith("URI:DIR2-CHK-Verifier:"), u2vs) u2_verifier_fileuri = u2_verifier.get_filenode_cap() self.failUnless(IVerifierURI.providedBy(u2_verifier_fileuri)) u2vfs = u2_verifier_fileuri.to_string() # URI:CHK-Verifier:$key:$ueb:$k:$n:$size self.failUnlessReallyEqual(u2vfs, fnuri.get_verify_cap().to_string()) self.failUnlessReallyEqual(u2vs[len("URI:DIR2-"):], u2vfs[len("URI:"):]) self.failUnless(str(u2_verifier))
def random_fsnode(self): coin = random.randrange(0, 3) if coin == 0: cap = uri.CHKFileURI(randutil.insecurerandstr(16), randutil.insecurerandstr(32), random.randrange(1, 5), random.randrange(6, 15), random.randrange(99, 1000000000000)) return ImmutableFileNode(cap, None, None, None, None, None) elif coin == 1: cap = uri.WriteableSSKFileURI(randutil.insecurerandstr(16), randutil.insecurerandstr(32)) n = MutableFileNode(None, None, encoding_parameters, None) return n.init_from_cap(cap) else: assert coin == 2 cap = uri.WriteableSSKFileURI(randutil.insecurerandstr(16), randutil.insecurerandstr(32)) n = MutableFileNode(None, None, encoding_parameters, None) n.init_from_cap(cap) return dirnode.DirectoryNode(n, self.nodemaker, uploader=None)
def make_chk_file_cap(size): return uri.CHKFileURI(key=os.urandom(16), uri_extension_hash=os.urandom(32), needed_shares=3, total_shares=10, size=size)
def test_check_and_repair(self): c = self.create_fake_client() sb = c.storage_broker serverid_1 = "\x00" * 20 serverid_f = "\xff" * 20 u = uri.CHKFileURI("\x00" * 16, "\x00" * 32, 3, 10, 1234) data = { "count_happiness": 5, "count_shares_needed": 3, "count_shares_expected": 10, "count_shares_good": 6, "count_good_share_hosts": 7, "count_recoverable_versions": 1, "count_unrecoverable_versions": 0, "servers_responding": [], "sharemap": { "shareid1": [ sb.get_stub_server(serverid_1), sb.get_stub_server(serverid_f) ] }, "count_wrong_shares": 0, "list_corrupt_shares": [], "count_corrupt_shares": 0, "list_incompatible_shares": [], "count_incompatible_shares": 0, "report": [], "share_problems": [], "servermap": None, } pre_cr = check_results.CheckResults(u, u.get_storage_index(), healthy=False, recoverable=True, summary="illing", **data) data = { "count_happiness": 9, "count_shares_needed": 3, "count_shares_expected": 10, "count_shares_good": 10, "count_good_share_hosts": 11, "count_recoverable_versions": 1, "count_unrecoverable_versions": 0, "servers_responding": [], "sharemap": { "shareid1": [ sb.get_stub_server(serverid_1), sb.get_stub_server(serverid_f) ] }, "count_wrong_shares": 0, "count_corrupt_shares": 0, "list_corrupt_shares": [], "list_incompatible_shares": [], "count_incompatible_shares": 0, "report": [], "share_problems": [], "servermap": None, } post_cr = check_results.CheckResults(u, u.get_storage_index(), healthy=True, recoverable=True, summary="groovy", **data) crr = check_results.CheckAndRepairResults(u.get_storage_index()) crr.pre_repair_results = pre_cr crr.post_repair_results = post_cr crr.repair_attempted = False w = web_check_results.CheckAndRepairResultsRendererElement(c, crr) html = self.render_element(w) s = self.remove_tags(html) self.failUnlessIn("File Check-And-Repair Results for SI=2k6avp", s) self.failUnlessIn("Healthy : groovy", s) self.failUnlessIn("No repair necessary", s) self.failUnlessIn("Post-Repair Checker Results:", s) self.failUnlessIn("Share Counts: need 3-of-10, have 10", s) crr.repair_attempted = True crr.repair_successful = True html = self.render_element(w) s = self.remove_tags(html) self.failUnlessIn("File Check-And-Repair Results for SI=2k6avp", s) self.failUnlessIn("Healthy : groovy", s) self.failUnlessIn("Repair successful", s) self.failUnlessIn("Post-Repair Checker Results:", s) crr.repair_attempted = True crr.repair_successful = False post_cr = check_results.CheckResults(u, u.get_storage_index(), healthy=False, recoverable=True, summary="better", **data) crr.post_repair_results = post_cr html = self.render_element(w) s = self.remove_tags(html) self.failUnlessIn("File Check-And-Repair Results for SI=2k6avp", s) self.failUnlessIn("Not Healthy! : better", s) self.failUnlessIn("Repair unsuccessful", s) self.failUnlessIn("Post-Repair Checker Results:", s) crr.repair_attempted = True crr.repair_successful = False post_cr = check_results.CheckResults(u, u.get_storage_index(), healthy=False, recoverable=False, summary="worse", **data) crr.post_repair_results = post_cr html = self.render_element(w) s = self.remove_tags(html) self.failUnlessIn("File Check-And-Repair Results for SI=2k6avp", s) self.failUnlessIn("Not Recoverable! : worse", s) self.failUnlessIn("Repair unsuccessful", s) self.failUnlessIn("Post-Repair Checker Results:", s) w = web_check_results.CheckAndRepairResultsRenderer(c, crr) j = json.loads(self.render_json(w)) self.failUnlessEqual(j["repair-attempted"], True) self.failUnlessEqual(j["storage-index"], "2k6avpjga3dho3zsjo6nnkt7n4") self.failUnlessEqual(j["pre-repair-results"]["summary"], "illing") self.failUnlessEqual(j["post-repair-results"]["summary"], "worse") w = web_check_results.CheckAndRepairResultsRenderer(c, None) j = json.loads(self.render_json(w)) self.failUnlessEqual(j["repair-attempted"], False) self.failUnlessEqual(j["storage-index"], "")
def test_check(self): c = self.create_fake_client() sb = c.storage_broker serverid_1 = "\x00" * 20 serverid_f = "\xff" * 20 server_1 = sb.get_stub_server(serverid_1) server_f = sb.get_stub_server(serverid_f) u = uri.CHKFileURI("\x00" * 16, "\x00" * 32, 3, 10, 1234) data = { "count_happiness": 8, "count_shares_needed": 3, "count_shares_expected": 9, "count_shares_good": 10, "count_good_share_hosts": 11, "count_recoverable_versions": 1, "count_unrecoverable_versions": 0, "servers_responding": [], "sharemap": { "shareid1": [server_1, server_f] }, "count_wrong_shares": 0, "list_corrupt_shares": [], "count_corrupt_shares": 0, "list_incompatible_shares": [], "count_incompatible_shares": 0, "report": [], "share_problems": [], "servermap": None, } cr = check_results.CheckResults(u, u.get_storage_index(), healthy=True, recoverable=True, summary="groovy", **data) w = web_check_results.CheckResultsRendererElement(c, cr) html = self.render_element(w) s = self.remove_tags(html) self.failUnlessIn("File Check Results for SI=2k6avp", s) # abbreviated self.failUnlessIn("Healthy : groovy", s) self.failUnlessIn("Share Counts: need 3-of-9, have 10", s) self.failUnlessIn("Happiness Level: 8", s) self.failUnlessIn("Hosts with good shares: 11", s) self.failUnlessIn("Corrupt shares: none", s) self.failUnlessIn("Wrong Shares: 0", s) self.failUnlessIn("Recoverable Versions: 1", s) self.failUnlessIn("Unrecoverable Versions: 0", s) self.failUnlessIn( "Good Shares (sorted in share order): Share ID Nickname Node ID shareid1 peer-0 00000000 peer-f ffffffff", s) cr = check_results.CheckResults(u, u.get_storage_index(), healthy=False, recoverable=True, summary="ungroovy", **data) w = web_check_results.CheckResultsRendererElement(c, cr) html = self.render_element(w) s = self.remove_tags(html) self.failUnlessIn("File Check Results for SI=2k6avp", s) # abbreviated self.failUnlessIn("Not Healthy! : ungroovy", s) data["count_corrupt_shares"] = 1 data["list_corrupt_shares"] = [(server_1, u.get_storage_index(), 2)] cr = check_results.CheckResults(u, u.get_storage_index(), healthy=False, recoverable=False, summary="rather dead", **data) w = web_check_results.CheckResultsRendererElement(c, cr) html = self.render_element(w) s = self.remove_tags(html) self.failUnlessIn("File Check Results for SI=2k6avp", s) # abbreviated self.failUnlessIn("Not Recoverable! : rather dead", s) self.failUnlessIn( "Corrupt shares: Share ID Nickname Node ID sh#2 peer-0 00000000", s) html = self.render_element(w) s = self.remove_tags(html) self.failUnlessIn("File Check Results for SI=2k6avp", s) # abbreviated self.failUnlessIn("Not Recoverable! : rather dead", s) html = self.render_element(w, args={"return_to": ["FOOURL"]}) self.failUnlessIn('<a href="FOOURL">Return to file/directory.</a>', html) w = web_check_results.CheckResultsRenderer(c, cr) d = self.render_json(w) def _check_json(jdata): j = json.loads(jdata) self.failUnlessEqual(j["summary"], "rather dead") self.failUnlessEqual(j["storage-index"], "2k6avpjga3dho3zsjo6nnkt7n4") expected = { 'count-happiness': 8, 'count-shares-expected': 9, 'healthy': False, 'count-unrecoverable-versions': 0, 'count-shares-needed': 3, 'sharemap': { "shareid1": ["v0-00000000-long", "v0-ffffffff-long"] }, 'count-recoverable-versions': 1, 'list-corrupt-shares': [["v0-00000000-long", "2k6avpjga3dho3zsjo6nnkt7n4", 2]], 'count-good-share-hosts': 11, 'count-wrong-shares': 0, 'count-shares-good': 10, 'count-corrupt-shares': 1, 'servers-responding': [], 'recoverable': False, } self.failUnlessEqual(j["results"], expected) _check_json(d) w = web_check_results.CheckResultsRendererElement(c, cr) d = self.render_element(w) def _check(html): s = self.remove_tags(html) self.failUnlessIn("File Check Results for SI=2k6avp", s) self.failUnlessIn("Not Recoverable! : rather dead", s) _check(html)
def test_no_reneging_on_no_more_shares_ever(self): # ticket #1191 # Suppose that K=3 and you send two DYHB requests, the first # response offers two shares, and then the last offers one # share. If you tell your share consumer "no more shares, # ever", and then immediately tell them "oh, and here's # another share", then you lose. rcap = uri.CHKFileURI('a' * 32, 'a' * 32, 3, 99, 100) vcap = rcap.get_verify_cap() class MockServer(object): def __init__(self, buckets): self.version = { 'http://allmydata.org/tahoe/protocols/storage/v1': { "tolerates-immutable-read-overrun": True } } self.buckets = buckets self.d = defer.Deferred() self.s = None def callRemote(self, methname, *args, **kwargs): d = defer.Deferred() # Even after the 3rd answer we're still hungry because # we're interested in finding a share on a 3rd server # so we don't have to download more than one share # from the first server. This is actually necessary to # trigger the bug. def _give_buckets_and_hunger_again(): d.callback(self.buckets) self.s.hungry() eventually(_give_buckets_and_hunger_again) return d class MockIServer(object): def __init__(self, serverid, rref): self.serverid = serverid self.rref = rref def get_serverid(self): return self.serverid def get_rref(self): return self.rref def get_name(self): return "name-%s" % self.serverid def get_version(self): return self.rref.version mockserver1 = MockServer({1: mock.Mock(), 2: mock.Mock()}) mockserver2 = MockServer({}) mockserver3 = MockServer({3: mock.Mock()}) mockstoragebroker = mock.Mock() servers = [ MockIServer("ms1", mockserver1), MockIServer("ms2", mockserver2), MockIServer("ms3", mockserver3), ] mockstoragebroker.get_servers_for_psi.return_value = servers mockdownloadstatus = mock.Mock() mocknode = MockNode(check_reneging=True, check_fetch_failed=True) s = finder.ShareFinder(mockstoragebroker, vcap, mocknode, mockdownloadstatus) mockserver1.s = s mockserver2.s = s mockserver3.s = s s.hungry() return mocknode.when_finished()
def test_pack(self): key = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" storage_index = hashutil.storage_index_hash(key) uri_extension_hash = hashutil.uri_extension_hash("stuff") needed_shares = 25 total_shares = 100 size = 1234 u = uri.CHKFileURI(key=key, uri_extension_hash=uri_extension_hash, needed_shares=needed_shares, total_shares=total_shares, size=size) self.failUnlessReallyEqual(u.get_storage_index(), storage_index) self.failUnlessReallyEqual(u.key, key) self.failUnlessReallyEqual(u.uri_extension_hash, uri_extension_hash) self.failUnlessReallyEqual(u.needed_shares, needed_shares) self.failUnlessReallyEqual(u.total_shares, total_shares) self.failUnlessReallyEqual(u.size, size) self.failUnless(u.is_readonly()) self.failIf(u.is_mutable()) self.failUnless(IURI.providedBy(u)) self.failUnless(IFileURI.providedBy(u)) self.failIf(IDirnodeURI.providedBy(u)) self.failUnlessReallyEqual(u.get_size(), 1234) u_ro = u.get_readonly() self.failUnlessIdentical(u, u_ro) u2 = uri.from_string(u.to_string()) self.failUnlessReallyEqual(u2.get_storage_index(), storage_index) self.failUnlessReallyEqual(u2.key, key) self.failUnlessReallyEqual(u2.uri_extension_hash, uri_extension_hash) self.failUnlessReallyEqual(u2.needed_shares, needed_shares) self.failUnlessReallyEqual(u2.total_shares, total_shares) self.failUnlessReallyEqual(u2.size, size) self.failUnless(u2.is_readonly()) self.failIf(u2.is_mutable()) self.failUnless(IURI.providedBy(u2)) self.failUnless(IFileURI.providedBy(u2)) self.failIf(IDirnodeURI.providedBy(u2)) self.failUnlessReallyEqual(u2.get_size(), 1234) u2i = uri.from_string(u.to_string(), deep_immutable=True) self.failUnlessReallyEqual(u.to_string(), u2i.to_string()) u2ro = uri.from_string(uri.ALLEGED_READONLY_PREFIX + u.to_string()) self.failUnlessReallyEqual(u.to_string(), u2ro.to_string()) u2imm = uri.from_string(uri.ALLEGED_IMMUTABLE_PREFIX + u.to_string()) self.failUnlessReallyEqual(u.to_string(), u2imm.to_string()) v = u.get_verify_cap() self.failUnless(isinstance(v.to_string(), str)) self.failUnless(v.is_readonly()) self.failIf(v.is_mutable()) v2 = uri.from_string(v.to_string()) self.failUnlessReallyEqual(v, v2) v3 = uri.CHKFileVerifierURI(storage_index="\x00" * 16, uri_extension_hash="\x00" * 32, needed_shares=3, total_shares=10, size=1234) self.failUnless(isinstance(v3.to_string(), str)) self.failUnless(v3.is_readonly()) self.failIf(v3.is_mutable())
def test_check(self): c = self.create_fake_client() serverid_1 = "\x00"*20 serverid_f = "\xff"*20 u = uri.CHKFileURI("\x00"*16, "\x00"*32, 3, 10, 1234) cr = check_results.CheckResults(u, u.get_storage_index()) cr.set_healthy(True) cr.set_needs_rebalancing(False) cr.set_summary("groovy") data = { "count-shares-needed": 3, "count-shares-expected": 9, "count-shares-good": 10, "count-good-share-hosts": 11, "list-corrupt-shares": [], "count-wrong-shares": 0, "sharemap": {"shareid1": [serverid_1, serverid_f]}, "count-recoverable-versions": 1, "count-unrecoverable-versions": 0, "servers-responding": [], } cr.set_data(data) w = web_check_results.CheckResults(c, cr) html = self.render2(w) s = self.remove_tags(html) self.failUnlessIn("File Check Results for SI=2k6avp", s) # abbreviated self.failUnlessIn("Healthy : groovy", s) self.failUnlessIn("Share Counts: need 3-of-9, have 10", s) self.failUnlessIn("Hosts with good shares: 11", s) self.failUnlessIn("Corrupt shares: none", s) self.failUnlessIn("Wrong Shares: 0", s) self.failUnlessIn("Recoverable Versions: 1", s) self.failUnlessIn("Unrecoverable Versions: 0", s) cr.set_healthy(False) cr.set_recoverable(True) cr.set_summary("ungroovy") html = self.render2(w) s = self.remove_tags(html) self.failUnlessIn("File Check Results for SI=2k6avp", s) # abbreviated self.failUnlessIn("Not Healthy! : ungroovy", s) cr.set_healthy(False) cr.set_recoverable(False) cr.set_summary("rather dead") data["list-corrupt-shares"] = [(serverid_1, u.get_storage_index(), 2)] cr.set_data(data) html = self.render2(w) s = self.remove_tags(html) self.failUnlessIn("File Check Results for SI=2k6avp", s) # abbreviated self.failUnlessIn("Not Recoverable! : rather dead", s) self.failUnlessIn("Corrupt shares: Share ID Nickname Node ID sh#2 peer-0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", s) html = self.render2(w) s = self.remove_tags(html) self.failUnlessIn("File Check Results for SI=2k6avp", s) # abbreviated self.failUnlessIn("Not Recoverable! : rather dead", s) html = self.render2(w, args={"return_to": ["FOOURL"]}) self.failUnlessIn('<a href="FOOURL">Return to file/directory.</a>', html) d = self.render_json(w) def _check_json(jdata): j = simplejson.loads(jdata) self.failUnlessEqual(j["summary"], "rather dead") self.failUnlessEqual(j["storage-index"], "2k6avpjga3dho3zsjo6nnkt7n4") expected = {'needs-rebalancing': False, 'count-shares-expected': 9, 'healthy': False, 'count-unrecoverable-versions': 0, 'count-shares-needed': 3, 'sharemap': {"shareid1": ["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "77777777777777777777777777777777"]}, 'count-recoverable-versions': 1, 'list-corrupt-shares': [["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "2k6avpjga3dho3zsjo6nnkt7n4", 2]], 'count-good-share-hosts': 11, 'count-wrong-shares': 0, 'count-shares-good': 10, 'count-corrupt-shares': 0, 'servers-responding': [], 'recoverable': False, } self.failUnlessEqual(j["results"], expected) d.addCallback(_check_json) d.addCallback(lambda ignored: self.render1(w)) def _check(html): s = self.remove_tags(html) self.failUnlessIn("File Check Results for SI=2k6avp", s) self.failUnlessIn("Not Recoverable! : rather dead", s) d.addCallback(_check) return d
def test_check_and_repair(self): c = self.create_fake_client() serverid_1 = "\x00"*20 serverid_f = "\xff"*20 u = uri.CHKFileURI("\x00"*16, "\x00"*32, 3, 10, 1234) pre_cr = check_results.CheckResults(u, u.get_storage_index()) pre_cr.set_healthy(False) pre_cr.set_recoverable(True) pre_cr.set_needs_rebalancing(False) pre_cr.set_summary("illing") data = { "count-shares-needed": 3, "count-shares-expected": 10, "count-shares-good": 6, "count-good-share-hosts": 7, "list-corrupt-shares": [], "count-wrong-shares": 0, "sharemap": {"shareid1": [serverid_1, serverid_f]}, "count-recoverable-versions": 1, "count-unrecoverable-versions": 0, "servers-responding": [], } pre_cr.set_data(data) post_cr = check_results.CheckResults(u, u.get_storage_index()) post_cr.set_healthy(True) post_cr.set_recoverable(True) post_cr.set_needs_rebalancing(False) post_cr.set_summary("groovy") data = { "count-shares-needed": 3, "count-shares-expected": 10, "count-shares-good": 10, "count-good-share-hosts": 11, "list-corrupt-shares": [], "count-wrong-shares": 0, "sharemap": {"shareid1": [serverid_1, serverid_f]}, "count-recoverable-versions": 1, "count-unrecoverable-versions": 0, "servers-responding": [], } post_cr.set_data(data) crr = check_results.CheckAndRepairResults(u.get_storage_index()) crr.pre_repair_results = pre_cr crr.post_repair_results = post_cr crr.repair_attempted = False w = web_check_results.CheckAndRepairResults(c, crr) html = self.render2(w) s = self.remove_tags(html) self.failUnlessIn("File Check-And-Repair Results for SI=2k6avp", s) self.failUnlessIn("Healthy : groovy", s) self.failUnlessIn("No repair necessary", s) self.failUnlessIn("Post-Repair Checker Results:", s) self.failUnlessIn("Share Counts: need 3-of-10, have 10", s) crr.repair_attempted = True crr.repair_successful = True html = self.render2(w) s = self.remove_tags(html) self.failUnlessIn("File Check-And-Repair Results for SI=2k6avp", s) self.failUnlessIn("Healthy : groovy", s) self.failUnlessIn("Repair successful", s) self.failUnlessIn("Post-Repair Checker Results:", s) crr.repair_attempted = True crr.repair_successful = False post_cr.set_healthy(False) post_cr.set_summary("better") html = self.render2(w) s = self.remove_tags(html) self.failUnlessIn("File Check-And-Repair Results for SI=2k6avp", s) self.failUnlessIn("Not Healthy! : better", s) self.failUnlessIn("Repair unsuccessful", s) self.failUnlessIn("Post-Repair Checker Results:", s) crr.repair_attempted = True crr.repair_successful = False post_cr.set_healthy(False) post_cr.set_recoverable(False) post_cr.set_summary("worse") html = self.render2(w) s = self.remove_tags(html) self.failUnlessIn("File Check-And-Repair Results for SI=2k6avp", s) self.failUnlessIn("Not Recoverable! : worse", s) self.failUnlessIn("Repair unsuccessful", s) self.failUnlessIn("Post-Repair Checker Results:", s) d = self.render_json(w) def _got_json(data): j = simplejson.loads(data) self.failUnlessEqual(j["repair-attempted"], True) self.failUnlessEqual(j["storage-index"], "2k6avpjga3dho3zsjo6nnkt7n4") self.failUnlessEqual(j["pre-repair-results"]["summary"], "illing") self.failUnlessEqual(j["post-repair-results"]["summary"], "worse") d.addCallback(_got_json) w2 = web_check_results.CheckAndRepairResults(c, None) d.addCallback(lambda ignored: self.render_json(w2)) def _got_lit_results(data): j = simplejson.loads(data) self.failUnlessEqual(j["repair-attempted"], False) self.failUnlessEqual(j["storage-index"], "") d.addCallback(_got_lit_results) return d