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