]> git.rkrishnan.org Git - tahoe-lafs/tahoe-lafs.git/blob - src/allmydata/test/test_checker.py
big rework of introducer client: change local API, split division of responsibilites...
[tahoe-lafs/tahoe-lafs.git] / src / allmydata / test / test_checker.py
1
2 import simplejson
3 from twisted.trial import unittest
4 from allmydata import check_results, uri
5 from allmydata.web import check_results as web_check_results
6 from allmydata.storage_client import StorageFarmBroker, NativeStorageClientDescriptor
7 from common_web import WebRenderingMixin
8
9 class FakeClient:
10     def get_storage_broker(self):
11         return self.storage_broker
12
13 class WebResultsRendering(unittest.TestCase, WebRenderingMixin):
14
15     def create_fake_client(self):
16         sb = StorageFarmBroker(None, True)
17         for (peerid, nickname) in [("\x00"*20, "peer-0"),
18                                    ("\xff"*20, "peer-f"),
19                                    ("\x11"*20, "peer-11")] :
20             ann_d = { "version": 0,
21                       "service-name": "storage",
22                       "FURL": "fake furl",
23                       "nickname": unicode(nickname),
24                       "app-versions": {}, # need #466 and v2 introducer
25                       "my-version": "ver",
26                       "oldest-supported": "oldest",
27                       }
28             dsc = NativeStorageClientDescriptor(peerid, ann_d)
29             sb.test_add_descriptor(peerid, dsc)
30         c = FakeClient()
31         c.storage_broker = sb
32         return c
33
34     def render_json(self, page):
35         d = self.render1(page, args={"output": ["json"]})
36         return d
37
38     def test_literal(self):
39         c = self.create_fake_client()
40         lcr = web_check_results.LiteralCheckResults(c)
41
42         d = self.render1(lcr)
43         def _check(html):
44             s = self.remove_tags(html)
45             self.failUnlessIn("Literal files are always healthy", s)
46         d.addCallback(_check)
47         d.addCallback(lambda ignored:
48                       self.render1(lcr, args={"return_to": ["FOOURL"]}))
49         def _check_return_to(html):
50             s = self.remove_tags(html)
51             self.failUnlessIn("Literal files are always healthy", s)
52             self.failUnlessIn('<a href="FOOURL">Return to file.</a>',
53                               html)
54         d.addCallback(_check_return_to)
55         d.addCallback(lambda ignored: self.render_json(lcr))
56         def _check_json(json):
57             j = simplejson.loads(json)
58             self.failUnlessEqual(j["storage-index"], "")
59             self.failUnlessEqual(j["results"]["healthy"], True)
60         d.addCallback(_check_json)
61         return d
62
63     def test_check(self):
64         c = self.create_fake_client()
65         serverid_1 = "\x00"*20
66         serverid_f = "\xff"*20
67         u = uri.CHKFileURI("\x00"*16, "\x00"*32, 3, 10, 1234)
68         cr = check_results.CheckResults(u, u.storage_index)
69         cr.set_healthy(True)
70         cr.set_needs_rebalancing(False)
71         cr.set_summary("groovy")
72         data = { "count-shares-needed": 3,
73                  "count-shares-expected": 9,
74                  "count-shares-good": 10,
75                  "count-good-share-hosts": 11,
76                  "list-corrupt-shares": [],
77                  "count-wrong-shares": 0,
78                  "sharemap": {"shareid1": [serverid_1, serverid_f]},
79                  "count-recoverable-versions": 1,
80                  "count-unrecoverable-versions": 0,
81                  "servers-responding": [],
82                  }
83         cr.set_data(data)
84
85         w = web_check_results.CheckResults(c, cr)
86         html = self.render2(w)
87         s = self.remove_tags(html)
88         self.failUnlessIn("File Check Results for SI=2k6avp", s) # abbreviated
89         self.failUnlessIn("Healthy : groovy", s)
90         self.failUnlessIn("Share Counts: need 3-of-9, have 10", s)
91         self.failUnlessIn("Hosts with good shares: 11", s)
92         self.failUnlessIn("Corrupt shares: none", s)
93         self.failUnlessIn("Wrong Shares: 0", s)
94         self.failUnlessIn("Recoverable Versions: 1", s)
95         self.failUnlessIn("Unrecoverable Versions: 0", s)
96
97         cr.set_healthy(False)
98         cr.set_recoverable(True)
99         cr.set_summary("ungroovy")
100         html = self.render2(w)
101         s = self.remove_tags(html)
102         self.failUnlessIn("File Check Results for SI=2k6avp", s) # abbreviated
103         self.failUnlessIn("Not Healthy! : ungroovy", s)
104
105         cr.set_healthy(False)
106         cr.set_recoverable(False)
107         cr.set_summary("rather dead")
108         data["list-corrupt-shares"] = [(serverid_1, u.storage_index, 2)]
109         cr.set_data(data)
110         html = self.render2(w)
111         s = self.remove_tags(html)
112         self.failUnlessIn("File Check Results for SI=2k6avp", s) # abbreviated
113         self.failUnlessIn("Not Recoverable! : rather dead", s)
114         self.failUnlessIn("Corrupt shares: Share ID Nickname Node ID sh#2 peer-0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", s)
115
116         html = self.render2(w)
117         s = self.remove_tags(html)
118         self.failUnlessIn("File Check Results for SI=2k6avp", s) # abbreviated
119         self.failUnlessIn("Not Recoverable! : rather dead", s)
120
121         html = self.render2(w, args={"return_to": ["FOOURL"]})
122         self.failUnlessIn('<a href="FOOURL">Return to file/directory.</a>',
123                           html)
124
125         d = self.render_json(w)
126         def _check_json(jdata):
127             j = simplejson.loads(jdata)
128             self.failUnlessEqual(j["summary"], "rather dead")
129             self.failUnlessEqual(j["storage-index"],
130                                  "2k6avpjga3dho3zsjo6nnkt7n4")
131             expected = {'needs-rebalancing': False,
132                         'count-shares-expected': 9,
133                         'healthy': False,
134                         'count-unrecoverable-versions': 0,
135                         'count-shares-needed': 3,
136                         'sharemap': {"shareid1":
137                                      ["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
138                                       "77777777777777777777777777777777"]},
139                         'count-recoverable-versions': 1,
140                         'list-corrupt-shares':
141                         [["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
142                           "2k6avpjga3dho3zsjo6nnkt7n4", 2]],
143                         'count-good-share-hosts': 11,
144                         'count-wrong-shares': 0,
145                         'count-shares-good': 10,
146                         'count-corrupt-shares': 0,
147                         'servers-responding': [],
148                         'recoverable': False,
149                         }
150             self.failUnlessEqual(j["results"], expected)
151         d.addCallback(_check_json)
152         d.addCallback(lambda ignored: self.render1(w))
153         def _check(html):
154             s = self.remove_tags(html)
155             self.failUnlessIn("File Check Results for SI=2k6avp", s)
156             self.failUnlessIn("Not Recoverable! : rather dead", s)
157         d.addCallback(_check)
158         return d
159
160
161     def test_check_and_repair(self):
162         c = self.create_fake_client()
163         serverid_1 = "\x00"*20
164         serverid_f = "\xff"*20
165         u = uri.CHKFileURI("\x00"*16, "\x00"*32, 3, 10, 1234)
166
167         pre_cr = check_results.CheckResults(u, u.storage_index)
168         pre_cr.set_healthy(False)
169         pre_cr.set_recoverable(True)
170         pre_cr.set_needs_rebalancing(False)
171         pre_cr.set_summary("illing")
172         data = { "count-shares-needed": 3,
173                  "count-shares-expected": 10,
174                  "count-shares-good": 6,
175                  "count-good-share-hosts": 7,
176                  "list-corrupt-shares": [],
177                  "count-wrong-shares": 0,
178                  "sharemap": {"shareid1": [serverid_1, serverid_f]},
179                  "count-recoverable-versions": 1,
180                  "count-unrecoverable-versions": 0,
181                  "servers-responding": [],
182                  }
183         pre_cr.set_data(data)
184
185         post_cr = check_results.CheckResults(u, u.storage_index)
186         post_cr.set_healthy(True)
187         post_cr.set_recoverable(True)
188         post_cr.set_needs_rebalancing(False)
189         post_cr.set_summary("groovy")
190         data = { "count-shares-needed": 3,
191                  "count-shares-expected": 10,
192                  "count-shares-good": 10,
193                  "count-good-share-hosts": 11,
194                  "list-corrupt-shares": [],
195                  "count-wrong-shares": 0,
196                  "sharemap": {"shareid1": [serverid_1, serverid_f]},
197                  "count-recoverable-versions": 1,
198                  "count-unrecoverable-versions": 0,
199                  "servers-responding": [],
200                  }
201         post_cr.set_data(data)
202
203         crr = check_results.CheckAndRepairResults(u.storage_index)
204         crr.pre_repair_results = pre_cr
205         crr.post_repair_results = post_cr
206         crr.repair_attempted = False
207
208         w = web_check_results.CheckAndRepairResults(c, crr)
209         html = self.render2(w)
210         s = self.remove_tags(html)
211
212         self.failUnlessIn("File Check-And-Repair Results for SI=2k6avp", s)
213         self.failUnlessIn("Healthy : groovy", s)
214         self.failUnlessIn("No repair necessary", s)
215         self.failUnlessIn("Post-Repair Checker Results:", s)
216         self.failUnlessIn("Share Counts: need 3-of-10, have 10", s)
217
218         crr.repair_attempted = True
219         crr.repair_successful = True
220         html = self.render2(w)
221         s = self.remove_tags(html)
222
223         self.failUnlessIn("File Check-And-Repair Results for SI=2k6avp", s)
224         self.failUnlessIn("Healthy : groovy", s)
225         self.failUnlessIn("Repair successful", s)
226         self.failUnlessIn("Post-Repair Checker Results:", s)
227
228         crr.repair_attempted = True
229         crr.repair_successful = False
230         post_cr.set_healthy(False)
231         post_cr.set_summary("better")
232         html = self.render2(w)
233         s = self.remove_tags(html)
234
235         self.failUnlessIn("File Check-And-Repair Results for SI=2k6avp", s)
236         self.failUnlessIn("Not Healthy! : better", s)
237         self.failUnlessIn("Repair unsuccessful", s)
238         self.failUnlessIn("Post-Repair Checker Results:", s)
239
240         crr.repair_attempted = True
241         crr.repair_successful = False
242         post_cr.set_healthy(False)
243         post_cr.set_recoverable(False)
244         post_cr.set_summary("worse")
245         html = self.render2(w)
246         s = self.remove_tags(html)
247
248         self.failUnlessIn("File Check-And-Repair Results for SI=2k6avp", s)
249         self.failUnlessIn("Not Recoverable! : worse", s)
250         self.failUnlessIn("Repair unsuccessful", s)
251         self.failUnlessIn("Post-Repair Checker Results:", s)
252
253         d = self.render_json(w)
254         def _got_json(data):
255             j = simplejson.loads(data)
256             self.failUnlessEqual(j["repair-attempted"], True)
257             self.failUnlessEqual(j["storage-index"],
258                                  "2k6avpjga3dho3zsjo6nnkt7n4")
259             self.failUnlessEqual(j["pre-repair-results"]["summary"], "illing")
260             self.failUnlessEqual(j["post-repair-results"]["summary"], "worse")
261         d.addCallback(_got_json)
262
263         w2 = web_check_results.CheckAndRepairResults(c, None)
264         d.addCallback(lambda ignored: self.render_json(w2))
265         def _got_lit_results(data):
266             j = simplejson.loads(data)
267             self.failUnlessEqual(j["repair-attempted"], False)
268             self.failUnlessEqual(j["storage-index"], "")
269         d.addCallback(_got_lit_results)
270         return d
271