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
10 def get_storage_broker(self):
11 return self.storage_broker
13 class WebResultsRendering(unittest.TestCase, WebRenderingMixin):
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",
23 "nickname": unicode(nickname),
24 "app-versions": {}, # need #466 and v2 introducer
26 "oldest-supported": "oldest",
28 dsc = NativeStorageClientDescriptor(peerid, ann_d)
29 sb.test_add_descriptor(peerid, dsc)
34 def render_json(self, page):
35 d = self.render1(page, args={"output": ["json"]})
38 def test_literal(self):
39 c = self.create_fake_client()
40 lcr = web_check_results.LiteralCheckResults(c)
44 s = self.remove_tags(html)
45 self.failUnlessIn("Literal files are always healthy", s)
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>',
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)
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)
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": [],
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)
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)
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)]
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)
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)
121 html = self.render2(w, args={"return_to": ["FOOURL"]})
122 self.failUnlessIn('<a href="FOOURL">Return to file/directory.</a>',
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,
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,
150 self.failUnlessEqual(j["results"], expected)
151 d.addCallback(_check_json)
152 d.addCallback(lambda ignored: self.render1(w))
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)
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)
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": [],
183 pre_cr.set_data(data)
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": [],
201 post_cr.set_data(data)
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
208 w = web_check_results.CheckAndRepairResults(c, crr)
209 html = self.render2(w)
210 s = self.remove_tags(html)
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)
218 crr.repair_attempted = True
219 crr.repair_successful = True
220 html = self.render2(w)
221 s = self.remove_tags(html)
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)
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)
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)
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)
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)
253 d = self.render_json(w)
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)
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)