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