1 | diff -rN -u old-tahoe/src/allmydata/test/common.py new-tahoe/src/allmydata/test/common.py |
---|
2 | --- old-tahoe/src/allmydata/test/common.py 2010-01-23 12:59:04.843000000 +0000 |
---|
3 | +++ new-tahoe/src/allmydata/test/common.py 2010-01-23 12:59:05.306000000 +0000 |
---|
4 | @@ -51,6 +51,8 @@ |
---|
5 | |
---|
6 | def get_uri(self): |
---|
7 | return self.my_uri.to_string() |
---|
8 | + def get_write_uri(self): |
---|
9 | + return None |
---|
10 | def get_readonly_uri(self): |
---|
11 | return self.my_uri.to_string() |
---|
12 | def get_cap(self): |
---|
13 | @@ -103,6 +105,12 @@ |
---|
14 | return False |
---|
15 | def is_readonly(self): |
---|
16 | return True |
---|
17 | + def is_unknown(self): |
---|
18 | + return False |
---|
19 | + def is_allowed_in_immutable_directory(self): |
---|
20 | + return True |
---|
21 | + def raise_error(self): |
---|
22 | + pass |
---|
23 | |
---|
24 | def get_size(self): |
---|
25 | try: |
---|
26 | @@ -190,6 +198,10 @@ |
---|
27 | return self.my_uri.get_readonly() |
---|
28 | def get_uri(self): |
---|
29 | return self.my_uri.to_string() |
---|
30 | + def get_write_uri(self): |
---|
31 | + if self.is_readonly(): |
---|
32 | + return None |
---|
33 | + return self.my_uri.to_string() |
---|
34 | def get_readonly(self): |
---|
35 | return self.my_uri.get_readonly() |
---|
36 | def get_readonly_uri(self): |
---|
37 | @@ -200,6 +212,12 @@ |
---|
38 | return self.my_uri.is_readonly() |
---|
39 | def is_mutable(self): |
---|
40 | return self.my_uri.is_mutable() |
---|
41 | + def is_unknown(self): |
---|
42 | + return False |
---|
43 | + def is_allowed_in_immutable_directory(self): |
---|
44 | + return not self.my_uri.is_mutable() |
---|
45 | + def raise_error(self): |
---|
46 | + pass |
---|
47 | def get_writekey(self): |
---|
48 | return "\x00"*16 |
---|
49 | def get_size(self): |
---|
50 | diff -rN -u old-tahoe/src/allmydata/test/test_client.py new-tahoe/src/allmydata/test/test_client.py |
---|
51 | --- old-tahoe/src/allmydata/test/test_client.py 2010-01-23 12:59:04.959000000 +0000 |
---|
52 | +++ new-tahoe/src/allmydata/test/test_client.py 2010-01-23 12:59:05.413000000 +0000 |
---|
53 | @@ -288,11 +288,14 @@ |
---|
54 | self.failUnless(n.is_readonly()) |
---|
55 | self.failUnless(n.is_mutable()) |
---|
56 | |
---|
57 | - future = "x-tahoe-crazy://future_cap_format." |
---|
58 | - n = c.create_node_from_uri(future) |
---|
59 | + unknown_rw = "lafs://from_the_future" |
---|
60 | + unknown_ro = "lafs://readonly_from_the_future" |
---|
61 | + n = c.create_node_from_uri(unknown_rw, unknown_ro) |
---|
62 | self.failUnless(IFilesystemNode.providedBy(n)) |
---|
63 | self.failIf(IFileNode.providedBy(n)) |
---|
64 | self.failIf(IImmutableFileNode.providedBy(n)) |
---|
65 | self.failIf(IMutableFileNode.providedBy(n)) |
---|
66 | self.failIf(IDirectoryNode.providedBy(n)) |
---|
67 | - self.failUnlessEqual(n.get_uri(), future) |
---|
68 | + self.failUnless(n.is_unknown()) |
---|
69 | + self.failUnlessEqual(n.get_uri(), unknown_rw) |
---|
70 | + self.failUnlessEqual(n.get_readonly_uri(), "ro." + unknown_ro) |
---|
71 | diff -rN -u old-tahoe/src/allmydata/test/test_dirnode.py new-tahoe/src/allmydata/test/test_dirnode.py |
---|
72 | --- old-tahoe/src/allmydata/test/test_dirnode.py 2010-01-23 12:59:04.984000000 +0000 |
---|
73 | +++ new-tahoe/src/allmydata/test/test_dirnode.py 2010-01-23 12:59:05.438000000 +0000 |
---|
74 | @@ -7,8 +7,8 @@ |
---|
75 | from allmydata.client import Client |
---|
76 | from allmydata.immutable import upload |
---|
77 | from allmydata.interfaces import IImmutableFileNode, IMutableFileNode, \ |
---|
78 | - ExistingChildError, NoSuchChildError, NotDeepImmutableError, \ |
---|
79 | - IDeepCheckResults, IDeepCheckAndRepairResults, CannotPackUnknownNodeError |
---|
80 | + ExistingChildError, NoSuchChildError, MustBeDeepImmutableError, \ |
---|
81 | + IDeepCheckResults, IDeepCheckAndRepairResults, MustNotBeUnknownRWError |
---|
82 | from allmydata.mutable.filenode import MutableFileNode |
---|
83 | from allmydata.mutable.common import UncoordinatedWriteError |
---|
84 | from allmydata.util import hashutil, base32 |
---|
85 | @@ -32,6 +32,11 @@ |
---|
86 | d = c.create_dirnode() |
---|
87 | def _done(res): |
---|
88 | self.failUnless(isinstance(res, dirnode.DirectoryNode)) |
---|
89 | + self.failUnless(res.is_mutable()) |
---|
90 | + self.failIf(res.is_readonly()) |
---|
91 | + self.failIf(res.is_unknown()) |
---|
92 | + self.failIf(res.is_allowed_in_immutable_directory()) |
---|
93 | + res.raise_error() |
---|
94 | rep = str(res) |
---|
95 | self.failUnless("RW-MUT" in rep) |
---|
96 | d.addCallback(_done) |
---|
97 | @@ -44,36 +49,74 @@ |
---|
98 | nm = c.nodemaker |
---|
99 | setup_py_uri = "URI:CHK:n7r3m6wmomelk4sep3kw5cvduq:os7ijw5c3maek7pg65e5254k2fzjflavtpejjyhshpsxuqzhcwwq:3:20:14861" |
---|
100 | one_uri = "URI:LIT:n5xgk" # LIT for "one" |
---|
101 | + mut_write_uri = "URI:SSK:vfvcbdfbszyrsaxchgevhmmlii:euw4iw7bbnkrrwpzuburbhppuxhc3gwxv26f6imekhz7zyw2ojnq" |
---|
102 | + mut_read_uri = "URI:SSK-RO:jf6wkflosyvntwxqcdo7a54jvm:euw4iw7bbnkrrwpzuburbhppuxhc3gwxv26f6imekhz7zyw2ojnq" |
---|
103 | + future_write_uri = "x-tahoe-crazy://I_am_from_the_future." |
---|
104 | + future_read_uri = "x-tahoe-crazy-readonly://I_am_from_the_future." |
---|
105 | kids = {u"one": (nm.create_from_cap(one_uri), {}), |
---|
106 | u"two": (nm.create_from_cap(setup_py_uri), |
---|
107 | {"metakey": "metavalue"}), |
---|
108 | + u"mut": (nm.create_from_cap(mut_write_uri, mut_read_uri), {}), |
---|
109 | + u"fut": (nm.create_from_cap(future_write_uri, future_read_uri), {}), |
---|
110 | + u"fro": (nm.create_from_cap(None, future_read_uri), {}), |
---|
111 | } |
---|
112 | d = c.create_dirnode(kids) |
---|
113 | + |
---|
114 | def _created(dn): |
---|
115 | self.failUnless(isinstance(dn, dirnode.DirectoryNode)) |
---|
116 | + self.failUnless(dn.is_mutable()) |
---|
117 | + self.failIf(dn.is_readonly()) |
---|
118 | + self.failIf(dn.is_unknown()) |
---|
119 | + self.failIf(dn.is_allowed_in_immutable_directory()) |
---|
120 | + dn.raise_error() |
---|
121 | rep = str(dn) |
---|
122 | self.failUnless("RW-MUT" in rep) |
---|
123 | return dn.list() |
---|
124 | d.addCallback(_created) |
---|
125 | + |
---|
126 | def _check_kids(children): |
---|
127 | - self.failUnlessEqual(sorted(children.keys()), [u"one", u"two"]) |
---|
128 | + self.failUnlessEqual(sorted(children.keys()), |
---|
129 | + [u"fro", u"fut", u"mut", u"one", u"two"]) |
---|
130 | one_node, one_metadata = children[u"one"] |
---|
131 | two_node, two_metadata = children[u"two"] |
---|
132 | + mut_node, mut_metadata = children[u"mut"] |
---|
133 | + fut_node, fut_metadata = children[u"fut"] |
---|
134 | + fro_node, fro_metadata = children[u"fro"] |
---|
135 | + |
---|
136 | self.failUnlessEqual(one_node.get_size(), 3) |
---|
137 | - self.failUnlessEqual(two_node.get_size(), 14861) |
---|
138 | + self.failUnlessEqual(one_node.get_uri(), one_uri) |
---|
139 | + self.failUnlessEqual(one_node.get_readonly_uri(), one_uri) |
---|
140 | self.failUnless(isinstance(one_metadata, dict), one_metadata) |
---|
141 | + |
---|
142 | + self.failUnlessEqual(two_node.get_size(), 14861) |
---|
143 | + self.failUnlessEqual(two_node.get_uri(), setup_py_uri) |
---|
144 | + self.failUnlessEqual(two_node.get_readonly_uri(), setup_py_uri) |
---|
145 | self.failUnlessEqual(two_metadata["metakey"], "metavalue") |
---|
146 | + |
---|
147 | + self.failUnlessEqual(mut_node.get_uri(), mut_write_uri) |
---|
148 | + self.failUnlessEqual(mut_node.get_readonly_uri(), mut_read_uri) |
---|
149 | + self.failUnless(isinstance(mut_metadata, dict), mut_metadata) |
---|
150 | + |
---|
151 | + self.failUnless(fut_node.is_unknown()) |
---|
152 | + self.failUnlessEqual(fut_node.get_uri(), future_write_uri) |
---|
153 | + self.failUnlessEqual(fut_node.get_readonly_uri(), "ro." + future_read_uri) |
---|
154 | + self.failUnless(isinstance(fut_metadata, dict), fut_metadata) |
---|
155 | + |
---|
156 | + self.failUnless(fro_node.is_unknown()) |
---|
157 | + self.failUnlessEqual(fro_node.get_uri(), "ro." + future_read_uri) |
---|
158 | + self.failUnlessEqual(fut_node.get_readonly_uri(), "ro." + future_read_uri) |
---|
159 | + self.failUnless(isinstance(fro_metadata, dict), fro_metadata) |
---|
160 | d.addCallback(_check_kids) |
---|
161 | + |
---|
162 | d.addCallback(lambda ign: nm.create_new_mutable_directory(kids)) |
---|
163 | d.addCallback(lambda dn: dn.list()) |
---|
164 | d.addCallback(_check_kids) |
---|
165 | - future_writecap = "x-tahoe-crazy://I_am_from_the_future." |
---|
166 | - future_readcap = "x-tahoe-crazy-readonly://I_am_from_the_future." |
---|
167 | - future_node = UnknownNode(future_writecap, future_readcap) |
---|
168 | - bad_kids1 = {u"one": (future_node, {})} |
---|
169 | + |
---|
170 | + bad_future_node = UnknownNode(future_write_uri, None) |
---|
171 | + bad_kids1 = {u"one": (bad_future_node, {})} |
---|
172 | d.addCallback(lambda ign: |
---|
173 | - self.shouldFail(AssertionError, "bad_kids1", |
---|
174 | - "does not accept UnknownNode", |
---|
175 | + self.shouldFail(MustNotBeUnknownRWError, "bad_kids1", |
---|
176 | + "cannot attach unknown", |
---|
177 | nm.create_new_mutable_directory, |
---|
178 | bad_kids1)) |
---|
179 | bad_kids2 = {u"one": (nm.create_from_cap(one_uri), None)} |
---|
180 | @@ -91,17 +134,24 @@ |
---|
181 | nm = c.nodemaker |
---|
182 | setup_py_uri = "URI:CHK:n7r3m6wmomelk4sep3kw5cvduq:os7ijw5c3maek7pg65e5254k2fzjflavtpejjyhshpsxuqzhcwwq:3:20:14861" |
---|
183 | one_uri = "URI:LIT:n5xgk" # LIT for "one" |
---|
184 | - mut_readcap = "URI:SSK-RO:e3mdrzfwhoq42hy5ubcz6rp3o4:ybyibhnp3vvwuq2vaw2ckjmesgkklfs6ghxleztqidihjyofgw7q" |
---|
185 | - mut_writecap = "URI:SSK:vfvcbdfbszyrsaxchgevhmmlii:euw4iw7bbnkrrwpzuburbhppuxhc3gwxv26f6imekhz7zyw2ojnq" |
---|
186 | + mut_write_uri = "URI:SSK:vfvcbdfbszyrsaxchgevhmmlii:euw4iw7bbnkrrwpzuburbhppuxhc3gwxv26f6imekhz7zyw2ojnq" |
---|
187 | + mut_read_uri = "URI:SSK-RO:e3mdrzfwhoq42hy5ubcz6rp3o4:ybyibhnp3vvwuq2vaw2ckjmesgkklfs6ghxleztqidihjyofgw7q" |
---|
188 | + future_write_uri = "x-tahoe-crazy://I_am_from_the_future." |
---|
189 | + future_read_uri = "x-tahoe-crazy-readonly://I_am_from_the_future." |
---|
190 | kids = {u"one": (nm.create_from_cap(one_uri), {}), |
---|
191 | u"two": (nm.create_from_cap(setup_py_uri), |
---|
192 | {"metakey": "metavalue"}), |
---|
193 | + u"fut": (nm.create_from_cap(None, future_read_uri), {}), |
---|
194 | } |
---|
195 | d = c.create_immutable_dirnode(kids) |
---|
196 | + |
---|
197 | def _created(dn): |
---|
198 | self.failUnless(isinstance(dn, dirnode.DirectoryNode)) |
---|
199 | self.failIf(dn.is_mutable()) |
---|
200 | self.failUnless(dn.is_readonly()) |
---|
201 | + self.failIf(dn.is_unknown()) |
---|
202 | + self.failUnless(dn.is_allowed_in_immutable_directory()) |
---|
203 | + dn.raise_error() |
---|
204 | rep = str(dn) |
---|
205 | self.failUnless("RO-IMM" in rep) |
---|
206 | cap = dn.get_cap() |
---|
207 | @@ -109,50 +159,73 @@ |
---|
208 | self.cap = cap |
---|
209 | return dn.list() |
---|
210 | d.addCallback(_created) |
---|
211 | + |
---|
212 | def _check_kids(children): |
---|
213 | - self.failUnlessEqual(sorted(children.keys()), [u"one", u"two"]) |
---|
214 | + self.failUnlessEqual(sorted(children.keys()), [u"fut", u"one", u"two"]) |
---|
215 | one_node, one_metadata = children[u"one"] |
---|
216 | two_node, two_metadata = children[u"two"] |
---|
217 | + fut_node, fut_metadata = children[u"fut"] |
---|
218 | + |
---|
219 | self.failUnlessEqual(one_node.get_size(), 3) |
---|
220 | - self.failUnlessEqual(two_node.get_size(), 14861) |
---|
221 | + self.failUnlessEqual(one_node.get_uri(), one_uri) |
---|
222 | + self.failUnlessEqual(one_node.get_readonly_uri(), one_uri) |
---|
223 | self.failUnless(isinstance(one_metadata, dict), one_metadata) |
---|
224 | + |
---|
225 | + self.failUnlessEqual(two_node.get_size(), 14861) |
---|
226 | + self.failUnlessEqual(two_node.get_uri(), setup_py_uri) |
---|
227 | + self.failUnlessEqual(two_node.get_readonly_uri(), setup_py_uri) |
---|
228 | self.failUnlessEqual(two_metadata["metakey"], "metavalue") |
---|
229 | + |
---|
230 | + self.failUnless(fut_node.is_unknown()) |
---|
231 | + self.failUnlessEqual(fut_node.get_uri(), "imm." + future_read_uri) |
---|
232 | + self.failUnlessEqual(fut_node.get_readonly_uri(), "imm." + future_read_uri) |
---|
233 | + self.failUnless(isinstance(fut_metadata, dict), fut_metadata) |
---|
234 | d.addCallback(_check_kids) |
---|
235 | + |
---|
236 | d.addCallback(lambda ign: nm.create_from_cap(self.cap.to_string())) |
---|
237 | d.addCallback(lambda dn: dn.list()) |
---|
238 | d.addCallback(_check_kids) |
---|
239 | - future_writecap = "x-tahoe-crazy://I_am_from_the_future." |
---|
240 | - future_readcap = "x-tahoe-crazy-readonly://I_am_from_the_future." |
---|
241 | - future_node = UnknownNode(future_writecap, future_readcap) |
---|
242 | - bad_kids1 = {u"one": (future_node, {})} |
---|
243 | + |
---|
244 | + bad_future_node1 = UnknownNode(future_write_uri, None) |
---|
245 | + bad_kids1 = {u"one": (bad_future_node1, {})} |
---|
246 | d.addCallback(lambda ign: |
---|
247 | - self.shouldFail(AssertionError, "bad_kids1", |
---|
248 | - "does not accept UnknownNode", |
---|
249 | + self.shouldFail(MustNotBeUnknownRWError, "bad_kids1", |
---|
250 | + "cannot attach unknown", |
---|
251 | c.create_immutable_dirnode, |
---|
252 | bad_kids1)) |
---|
253 | - bad_kids2 = {u"one": (nm.create_from_cap(one_uri), None)} |
---|
254 | + bad_future_node2 = UnknownNode(future_write_uri, future_read_uri) |
---|
255 | + bad_kids2 = {u"one": (bad_future_node2, {})} |
---|
256 | d.addCallback(lambda ign: |
---|
257 | - self.shouldFail(AssertionError, "bad_kids2", |
---|
258 | - "requires metadata to be a dict", |
---|
259 | + self.shouldFail(MustBeDeepImmutableError, "bad_kids2", |
---|
260 | + "is not immutable", |
---|
261 | c.create_immutable_dirnode, |
---|
262 | bad_kids2)) |
---|
263 | - bad_kids3 = {u"one": (nm.create_from_cap(mut_writecap), {})} |
---|
264 | + bad_kids3 = {u"one": (nm.create_from_cap(one_uri), None)} |
---|
265 | d.addCallback(lambda ign: |
---|
266 | - self.shouldFail(NotDeepImmutableError, "bad_kids3", |
---|
267 | - "is not immutable", |
---|
268 | + self.shouldFail(AssertionError, "bad_kids3", |
---|
269 | + "requires metadata to be a dict", |
---|
270 | c.create_immutable_dirnode, |
---|
271 | bad_kids3)) |
---|
272 | - bad_kids4 = {u"one": (nm.create_from_cap(mut_readcap), {})} |
---|
273 | + bad_kids4 = {u"one": (nm.create_from_cap(mut_write_uri), {})} |
---|
274 | d.addCallback(lambda ign: |
---|
275 | - self.shouldFail(NotDeepImmutableError, "bad_kids4", |
---|
276 | + self.shouldFail(MustBeDeepImmutableError, "bad_kids4", |
---|
277 | "is not immutable", |
---|
278 | c.create_immutable_dirnode, |
---|
279 | bad_kids4)) |
---|
280 | + bad_kids5 = {u"one": (nm.create_from_cap(mut_read_uri), {})} |
---|
281 | + d.addCallback(lambda ign: |
---|
282 | + self.shouldFail(MustBeDeepImmutableError, "bad_kids5", |
---|
283 | + "is not immutable", |
---|
284 | + c.create_immutable_dirnode, |
---|
285 | + bad_kids5)) |
---|
286 | d.addCallback(lambda ign: c.create_immutable_dirnode({})) |
---|
287 | def _created_empty(dn): |
---|
288 | self.failUnless(isinstance(dn, dirnode.DirectoryNode)) |
---|
289 | self.failIf(dn.is_mutable()) |
---|
290 | self.failUnless(dn.is_readonly()) |
---|
291 | + self.failIf(dn.is_unknown()) |
---|
292 | + self.failUnless(dn.is_allowed_in_immutable_directory()) |
---|
293 | + dn.raise_error() |
---|
294 | rep = str(dn) |
---|
295 | self.failUnless("RO-IMM" in rep) |
---|
296 | cap = dn.get_cap() |
---|
297 | @@ -168,6 +241,9 @@ |
---|
298 | self.failUnless(isinstance(dn, dirnode.DirectoryNode)) |
---|
299 | self.failIf(dn.is_mutable()) |
---|
300 | self.failUnless(dn.is_readonly()) |
---|
301 | + self.failIf(dn.is_unknown()) |
---|
302 | + self.failUnless(dn.is_allowed_in_immutable_directory()) |
---|
303 | + dn.raise_error() |
---|
304 | rep = str(dn) |
---|
305 | self.failUnless("RO-IMM" in rep) |
---|
306 | cap = dn.get_cap() |
---|
307 | @@ -193,9 +269,9 @@ |
---|
308 | d.addCallback(_check_kids) |
---|
309 | d.addCallback(lambda ign: n.get(u"subdir")) |
---|
310 | d.addCallback(lambda sd: self.failIf(sd.is_mutable())) |
---|
311 | - bad_kids = {u"one": (nm.create_from_cap(mut_writecap), {})} |
---|
312 | + bad_kids = {u"one": (nm.create_from_cap(mut_write_uri), {})} |
---|
313 | d.addCallback(lambda ign: |
---|
314 | - self.shouldFail(NotDeepImmutableError, "YZ", |
---|
315 | + self.shouldFail(MustBeDeepImmutableError, "YZ", |
---|
316 | "is not immutable", |
---|
317 | n.create_subdirectory, |
---|
318 | u"sub2", bad_kids, mutable=False)) |
---|
319 | @@ -203,7 +279,6 @@ |
---|
320 | d.addCallback(_made_parent) |
---|
321 | return d |
---|
322 | |
---|
323 | - |
---|
324 | def test_check(self): |
---|
325 | self.basedir = "dirnode/Dirnode/test_check" |
---|
326 | self.set_up_grid() |
---|
327 | @@ -337,24 +412,27 @@ |
---|
328 | ro_dn = c.create_node_from_uri(ro_uri) |
---|
329 | self.failUnless(ro_dn.is_readonly()) |
---|
330 | self.failUnless(ro_dn.is_mutable()) |
---|
331 | + self.failIf(ro_dn.is_unknown()) |
---|
332 | + self.failIf(ro_dn.is_allowed_in_immutable_directory()) |
---|
333 | + ro_dn.raise_error() |
---|
334 | |
---|
335 | - self.shouldFail(dirnode.NotMutableError, "set_uri ro", None, |
---|
336 | + self.shouldFail(dirnode.NotWriteableError, "set_uri ro", None, |
---|
337 | ro_dn.set_uri, u"newchild", filecap, filecap) |
---|
338 | - self.shouldFail(dirnode.NotMutableError, "set_uri ro", None, |
---|
339 | + self.shouldFail(dirnode.NotWriteableError, "set_uri ro", None, |
---|
340 | ro_dn.set_node, u"newchild", filenode) |
---|
341 | - self.shouldFail(dirnode.NotMutableError, "set_nodes ro", None, |
---|
342 | + self.shouldFail(dirnode.NotWriteableError, "set_nodes ro", None, |
---|
343 | ro_dn.set_nodes, { u"newchild": (filenode, None) }) |
---|
344 | - self.shouldFail(dirnode.NotMutableError, "set_uri ro", None, |
---|
345 | + self.shouldFail(dirnode.NotWriteableError, "set_uri ro", None, |
---|
346 | ro_dn.add_file, u"newchild", uploadable) |
---|
347 | - self.shouldFail(dirnode.NotMutableError, "set_uri ro", None, |
---|
348 | + self.shouldFail(dirnode.NotWriteableError, "set_uri ro", None, |
---|
349 | ro_dn.delete, u"child") |
---|
350 | - self.shouldFail(dirnode.NotMutableError, "set_uri ro", None, |
---|
351 | + self.shouldFail(dirnode.NotWriteableError, "set_uri ro", None, |
---|
352 | ro_dn.create_subdirectory, u"newchild") |
---|
353 | - self.shouldFail(dirnode.NotMutableError, "set_metadata_for ro", None, |
---|
354 | + self.shouldFail(dirnode.NotWriteableError, "set_metadata_for ro", None, |
---|
355 | ro_dn.set_metadata_for, u"child", {}) |
---|
356 | - self.shouldFail(dirnode.NotMutableError, "set_uri ro", None, |
---|
357 | + self.shouldFail(dirnode.NotWriteableError, "set_uri ro", None, |
---|
358 | ro_dn.move_child_to, u"child", rw_dn) |
---|
359 | - self.shouldFail(dirnode.NotMutableError, "set_uri ro", None, |
---|
360 | + self.shouldFail(dirnode.NotWriteableError, "set_uri ro", None, |
---|
361 | rw_dn.move_child_to, u"child", ro_dn) |
---|
362 | return ro_dn.list() |
---|
363 | d.addCallback(_ready) |
---|
364 | @@ -901,8 +979,8 @@ |
---|
365 | nodemaker = NodeMaker(None, None, None, |
---|
366 | None, None, None, |
---|
367 | {"k": 3, "n": 10}, None) |
---|
368 | - writecap = "URI:SSK-RO:e3mdrzfwhoq42hy5ubcz6rp3o4:ybyibhnp3vvwuq2vaw2ckjmesgkklfs6ghxleztqidihjyofgw7q" |
---|
369 | - filenode = nodemaker.create_from_cap(writecap) |
---|
370 | + write_uri = "URI:SSK-RO:e3mdrzfwhoq42hy5ubcz6rp3o4:ybyibhnp3vvwuq2vaw2ckjmesgkklfs6ghxleztqidihjyofgw7q" |
---|
371 | + filenode = nodemaker.create_from_cap(write_uri) |
---|
372 | node = dirnode.DirectoryNode(filenode, nodemaker, None) |
---|
373 | children = node._unpack_contents(known_tree) |
---|
374 | self._check_children(children) |
---|
375 | @@ -975,23 +1053,23 @@ |
---|
376 | self.failUnlessIn("lit", packed) |
---|
377 | |
---|
378 | kids = self._make_kids(nm, ["imm", "lit", "write"]) |
---|
379 | - self.failUnlessRaises(dirnode.MustBeDeepImmutable, |
---|
380 | + self.failUnlessRaises(dirnode.MustBeDeepImmutableError, |
---|
381 | dirnode.pack_children, |
---|
382 | fn, kids, deep_immutable=True) |
---|
383 | |
---|
384 | # read-only is not enough: all children must be immutable |
---|
385 | kids = self._make_kids(nm, ["imm", "lit", "read"]) |
---|
386 | - self.failUnlessRaises(dirnode.MustBeDeepImmutable, |
---|
387 | + self.failUnlessRaises(dirnode.MustBeDeepImmutableError, |
---|
388 | dirnode.pack_children, |
---|
389 | fn, kids, deep_immutable=True) |
---|
390 | |
---|
391 | kids = self._make_kids(nm, ["imm", "lit", "dirwrite"]) |
---|
392 | - self.failUnlessRaises(dirnode.MustBeDeepImmutable, |
---|
393 | + self.failUnlessRaises(dirnode.MustBeDeepImmutableError, |
---|
394 | dirnode.pack_children, |
---|
395 | fn, kids, deep_immutable=True) |
---|
396 | |
---|
397 | kids = self._make_kids(nm, ["imm", "lit", "dirread"]) |
---|
398 | - self.failUnlessRaises(dirnode.MustBeDeepImmutable, |
---|
399 | + self.failUnlessRaises(dirnode.MustBeDeepImmutableError, |
---|
400 | dirnode.pack_children, |
---|
401 | fn, kids, deep_immutable=True) |
---|
402 | |
---|
403 | @@ -1017,16 +1095,31 @@ |
---|
404 | |
---|
405 | def get_cap(self): |
---|
406 | return self.uri |
---|
407 | + |
---|
408 | def get_uri(self): |
---|
409 | return self.uri.to_string() |
---|
410 | + |
---|
411 | + def get_write_uri(self): |
---|
412 | + return self.uri.to_string() |
---|
413 | + |
---|
414 | def download_best_version(self): |
---|
415 | return defer.succeed(self.data) |
---|
416 | + |
---|
417 | def get_writekey(self): |
---|
418 | return "writekey" |
---|
419 | + |
---|
420 | def is_readonly(self): |
---|
421 | return False |
---|
422 | + |
---|
423 | def is_mutable(self): |
---|
424 | return True |
---|
425 | + |
---|
426 | + def is_unknown(self): |
---|
427 | + return False |
---|
428 | + |
---|
429 | + def is_allowed_in_immutable_directory(self): |
---|
430 | + return False |
---|
431 | + |
---|
432 | def modify(self, modifier): |
---|
433 | self.data = modifier(self.data, None, True) |
---|
434 | return defer.succeed(None) |
---|
435 | @@ -1050,47 +1143,59 @@ |
---|
436 | |
---|
437 | def test_from_future(self): |
---|
438 | # create a dirnode that contains unknown URI types, and make sure we |
---|
439 | - # tolerate them properly. Since dirnodes aren't allowed to add |
---|
440 | - # unknown node types, we have to be tricky. |
---|
441 | + # tolerate them properly. |
---|
442 | d = self.nodemaker.create_new_mutable_directory() |
---|
443 | - future_writecap = "x-tahoe-crazy://I_am_from_the_future." |
---|
444 | - future_readcap = "x-tahoe-crazy-readonly://I_am_from_the_future." |
---|
445 | - future_node = UnknownNode(future_writecap, future_readcap) |
---|
446 | + future_write_uri = "x-tahoe-crazy://I_am_from_the_future." |
---|
447 | + future_read_uri = "x-tahoe-crazy-readonly://I_am_from_the_future." |
---|
448 | + future_node = UnknownNode(future_write_uri, future_read_uri) |
---|
449 | def _then(n): |
---|
450 | self._node = n |
---|
451 | return n.set_node(u"future", future_node) |
---|
452 | d.addCallback(_then) |
---|
453 | |
---|
454 | - # we should be prohibited from adding an unknown URI to a directory, |
---|
455 | - # since we don't know how to diminish the cap to a readcap (for the |
---|
456 | - # dirnode's rocap slot), and we don't want to accidentally grant |
---|
457 | - # write access to a holder of the dirnode's readcap. |
---|
458 | + # We should be prohibited from adding an unknown URI to a directory |
---|
459 | + # just in the rw_uri slot, since we don't know how to diminish the cap |
---|
460 | + # to a readcap (for the ro_uri slot). |
---|
461 | d.addCallback(lambda ign: |
---|
462 | - self.shouldFail(CannotPackUnknownNodeError, |
---|
463 | + self.shouldFail(MustNotBeUnknownRWError, |
---|
464 | "copy unknown", |
---|
465 | - "cannot pack unknown node as child add", |
---|
466 | + "cannot attach unknown rw cap as child", |
---|
467 | self._node.set_uri, u"add", |
---|
468 | - future_writecap, future_readcap)) |
---|
469 | + future_write_uri, None)) |
---|
470 | + |
---|
471 | + # However, we should be able to add both rw_uri and ro_uri as a pair of |
---|
472 | + # unknown URIs. |
---|
473 | + d.addCallback(lambda ign: self._node.set_uri(u"add-pair", |
---|
474 | + future_write_uri, future_read_uri)) |
---|
475 | + |
---|
476 | d.addCallback(lambda ign: self._node.list()) |
---|
477 | def _check(children): |
---|
478 | - self.failUnlessEqual(len(children), 1) |
---|
479 | + self.failUnlessEqual(len(children), 2) |
---|
480 | (fn, metadata) = children[u"future"] |
---|
481 | self.failUnless(isinstance(fn, UnknownNode), fn) |
---|
482 | - self.failUnlessEqual(fn.get_uri(), future_writecap) |
---|
483 | - self.failUnlessEqual(fn.get_readonly_uri(), future_readcap) |
---|
484 | - # but we *should* be allowed to copy this node, because the |
---|
485 | + self.failUnlessEqual(fn.get_uri(), future_write_uri) |
---|
486 | + self.failUnlessEqual(fn.get_readonly_uri(), "ro." + future_read_uri) |
---|
487 | + |
---|
488 | + (fn2, metadata2) = children[u"add-pair"] |
---|
489 | + self.failUnless(isinstance(fn2, UnknownNode), fn2) |
---|
490 | + self.failUnlessEqual(fn2.get_uri(), future_write_uri) |
---|
491 | + self.failUnlessEqual(fn2.get_readonly_uri(), "ro." + future_read_uri) |
---|
492 | + |
---|
493 | + # we should also be allowed to copy this node, because the |
---|
494 | # UnknownNode contains all the information that was in the |
---|
495 | # original directory (readcap and writecap), so we're preserving |
---|
496 | # everything. |
---|
497 | return self._node.set_node(u"copy", fn) |
---|
498 | d.addCallback(_check) |
---|
499 | + |
---|
500 | d.addCallback(lambda ign: self._node.list()) |
---|
501 | def _check2(children): |
---|
502 | - self.failUnlessEqual(len(children), 2) |
---|
503 | + self.failUnlessEqual(len(children), 3) |
---|
504 | (fn, metadata) = children[u"copy"] |
---|
505 | self.failUnless(isinstance(fn, UnknownNode), fn) |
---|
506 | - self.failUnlessEqual(fn.get_uri(), future_writecap) |
---|
507 | - self.failUnlessEqual(fn.get_readonly_uri(), future_readcap) |
---|
508 | + self.failUnlessEqual(fn.get_uri(), future_write_uri) |
---|
509 | + self.failUnlessEqual(fn.get_readonly_uri(), "ro." + future_read_uri) |
---|
510 | + d.addCallback(_check2) |
---|
511 | return d |
---|
512 | |
---|
513 | class DeepStats(unittest.TestCase): |
---|
514 | diff -rN -u old-tahoe/src/allmydata/test/test_filenode.py new-tahoe/src/allmydata/test/test_filenode.py |
---|
515 | --- old-tahoe/src/allmydata/test/test_filenode.py 2010-01-23 12:59:04.999000000 +0000 |
---|
516 | +++ new-tahoe/src/allmydata/test/test_filenode.py 2010-01-23 12:59:05.452000000 +0000 |
---|
517 | @@ -41,14 +41,21 @@ |
---|
518 | self.failUnlessEqual(fn1.get_readcap(), u) |
---|
519 | self.failUnlessEqual(fn1.is_readonly(), True) |
---|
520 | self.failUnlessEqual(fn1.is_mutable(), False) |
---|
521 | + self.failUnlessEqual(fn1.is_unknown(), False) |
---|
522 | + self.failUnlessEqual(fn1.is_allowed_in_immutable_directory(), True) |
---|
523 | + self.failUnlessEqual(fn1.get_write_uri(), None) |
---|
524 | self.failUnlessEqual(fn1.get_readonly_uri(), u.to_string()) |
---|
525 | self.failUnlessEqual(fn1.get_size(), 1000) |
---|
526 | self.failUnlessEqual(fn1.get_storage_index(), u.storage_index) |
---|
527 | + fn1.raise_error() |
---|
528 | + fn2.raise_error() |
---|
529 | d = {} |
---|
530 | d[fn1] = 1 # exercise __hash__ |
---|
531 | v = fn1.get_verify_cap() |
---|
532 | self.failUnless(isinstance(v, uri.CHKFileVerifierURI)) |
---|
533 | self.failUnlessEqual(fn1.get_repair_cap(), v) |
---|
534 | + self.failUnlessEqual(v.is_readonly(), True) |
---|
535 | + self.failUnlessEqual(v.is_mutable(), False) |
---|
536 | |
---|
537 | |
---|
538 | def test_literal_filenode(self): |
---|
539 | @@ -64,9 +71,14 @@ |
---|
540 | self.failUnlessEqual(fn1.get_readcap(), u) |
---|
541 | self.failUnlessEqual(fn1.is_readonly(), True) |
---|
542 | self.failUnlessEqual(fn1.is_mutable(), False) |
---|
543 | + self.failUnlessEqual(fn1.is_unknown(), False) |
---|
544 | + self.failUnlessEqual(fn1.is_allowed_in_immutable_directory(), True) |
---|
545 | + self.failUnlessEqual(fn1.get_write_uri(), None) |
---|
546 | self.failUnlessEqual(fn1.get_readonly_uri(), u.to_string()) |
---|
547 | self.failUnlessEqual(fn1.get_size(), len(DATA)) |
---|
548 | self.failUnlessEqual(fn1.get_storage_index(), None) |
---|
549 | + fn1.raise_error() |
---|
550 | + fn2.raise_error() |
---|
551 | d = {} |
---|
552 | d[fn1] = 1 # exercise __hash__ |
---|
553 | |
---|
554 | @@ -99,24 +111,29 @@ |
---|
555 | self.failUnlessEqual(n.get_writekey(), wk) |
---|
556 | self.failUnlessEqual(n.get_readkey(), rk) |
---|
557 | self.failUnlessEqual(n.get_storage_index(), si) |
---|
558 | - # these itmes are populated on first read (or create), so until that |
---|
559 | + # these items are populated on first read (or create), so until that |
---|
560 | # happens they'll be None |
---|
561 | self.failUnlessEqual(n.get_privkey(), None) |
---|
562 | self.failUnlessEqual(n.get_encprivkey(), None) |
---|
563 | self.failUnlessEqual(n.get_pubkey(), None) |
---|
564 | |
---|
565 | self.failUnlessEqual(n.get_uri(), u.to_string()) |
---|
566 | + self.failUnlessEqual(n.get_write_uri(), u.to_string()) |
---|
567 | self.failUnlessEqual(n.get_readonly_uri(), u.get_readonly().to_string()) |
---|
568 | self.failUnlessEqual(n.get_cap(), u) |
---|
569 | self.failUnlessEqual(n.get_readcap(), u.get_readonly()) |
---|
570 | self.failUnlessEqual(n.is_mutable(), True) |
---|
571 | self.failUnlessEqual(n.is_readonly(), False) |
---|
572 | + self.failUnlessEqual(n.is_unknown(), False) |
---|
573 | + self.failUnlessEqual(n.is_allowed_in_immutable_directory(), False) |
---|
574 | + n.raise_error() |
---|
575 | |
---|
576 | n2 = MutableFileNode(None, None, client.get_encoding_parameters(), |
---|
577 | None).init_from_cap(u) |
---|
578 | self.failUnlessEqual(n, n2) |
---|
579 | self.failIfEqual(n, "not even the right type") |
---|
580 | self.failIfEqual(n, u) # not the right class |
---|
581 | + n.raise_error() |
---|
582 | d = {n: "can these be used as dictionary keys?"} |
---|
583 | d[n2] = "replace the old one" |
---|
584 | self.failUnlessEqual(len(d), 1) |
---|
585 | @@ -127,12 +144,16 @@ |
---|
586 | self.failUnlessEqual(nro.get_readonly(), nro) |
---|
587 | self.failUnlessEqual(nro.get_cap(), u.get_readonly()) |
---|
588 | self.failUnlessEqual(nro.get_readcap(), u.get_readonly()) |
---|
589 | + self.failUnlessEqual(nro.is_mutable(), True) |
---|
590 | + self.failUnlessEqual(nro.is_readonly(), True) |
---|
591 | + self.failUnlessEqual(nro.is_unknown(), False) |
---|
592 | + self.failUnlessEqual(nro.is_allowed_in_immutable_directory(), False) |
---|
593 | nro_u = nro.get_uri() |
---|
594 | self.failUnlessEqual(nro_u, nro.get_readonly_uri()) |
---|
595 | self.failUnlessEqual(nro_u, u.get_readonly().to_string()) |
---|
596 | - self.failUnlessEqual(nro.is_mutable(), True) |
---|
597 | - self.failUnlessEqual(nro.is_readonly(), True) |
---|
598 | + self.failUnlessEqual(nro.get_write_uri(), None) |
---|
599 | self.failUnlessEqual(nro.get_repair_cap(), None) # RSAmut needs writecap |
---|
600 | + nro.raise_error() |
---|
601 | |
---|
602 | v = n.get_verify_cap() |
---|
603 | self.failUnless(isinstance(v, uri.SSKVerifierURI)) |
---|
604 | diff -rN -u old-tahoe/src/allmydata/test/test_system.py new-tahoe/src/allmydata/test/test_system.py |
---|
605 | --- old-tahoe/src/allmydata/test/test_system.py 2010-01-23 12:59:05.147000000 +0000 |
---|
606 | +++ new-tahoe/src/allmydata/test/test_system.py 2010-01-23 12:59:05.618000000 +0000 |
---|
607 | @@ -17,7 +17,7 @@ |
---|
608 | from allmydata.interfaces import IDirectoryNode, IFileNode, \ |
---|
609 | NoSuchChildError, NoSharesError |
---|
610 | from allmydata.monitor import Monitor |
---|
611 | -from allmydata.mutable.common import NotMutableError |
---|
612 | +from allmydata.mutable.common import NotWriteableError |
---|
613 | from allmydata.mutable import layout as mutable_layout |
---|
614 | from foolscap.api import DeadReferenceError |
---|
615 | from twisted.python.failure import Failure |
---|
616 | @@ -890,11 +890,11 @@ |
---|
617 | d1.addCallback(lambda res: dirnode.list()) |
---|
618 | d1.addCallback(self.log, "dirnode.list") |
---|
619 | |
---|
620 | - d1.addCallback(lambda res: self.shouldFail2(NotMutableError, "mkdir(nope)", None, dirnode.create_subdirectory, u"nope")) |
---|
621 | + d1.addCallback(lambda res: self.shouldFail2(NotWriteableError, "mkdir(nope)", None, dirnode.create_subdirectory, u"nope")) |
---|
622 | |
---|
623 | d1.addCallback(self.log, "doing add_file(ro)") |
---|
624 | ut = upload.Data("I will disappear, unrecorded and unobserved. The tragedy of my demise is made more poignant by its silence, but this beauty is not for you to ever know.", convergence="99i-p1x4-xd4-18yc-ywt-87uu-msu-zo -- completely and totally unguessable string (unless you read this)") |
---|
625 | - d1.addCallback(lambda res: self.shouldFail2(NotMutableError, "add_file(nope)", None, dirnode.add_file, u"hope", ut)) |
---|
626 | + d1.addCallback(lambda res: self.shouldFail2(NotWriteableError, "add_file(nope)", None, dirnode.add_file, u"hope", ut)) |
---|
627 | |
---|
628 | d1.addCallback(self.log, "doing get(ro)") |
---|
629 | d1.addCallback(lambda res: dirnode.get(u"mydata992")) |
---|
630 | @@ -902,17 +902,17 @@ |
---|
631 | self.failUnless(IFileNode.providedBy(filenode))) |
---|
632 | |
---|
633 | d1.addCallback(self.log, "doing delete(ro)") |
---|
634 | - d1.addCallback(lambda res: self.shouldFail2(NotMutableError, "delete(nope)", None, dirnode.delete, u"mydata992")) |
---|
635 | + d1.addCallback(lambda res: self.shouldFail2(NotWriteableError, "delete(nope)", None, dirnode.delete, u"mydata992")) |
---|
636 | |
---|
637 | - d1.addCallback(lambda res: self.shouldFail2(NotMutableError, "set_uri(nope)", None, dirnode.set_uri, u"hopeless", self.uri, self.uri)) |
---|
638 | + d1.addCallback(lambda res: self.shouldFail2(NotWriteableError, "set_uri(nope)", None, dirnode.set_uri, u"hopeless", self.uri, self.uri)) |
---|
639 | |
---|
640 | d1.addCallback(lambda res: self.shouldFail2(NoSuchChildError, "get(missing)", "missing", dirnode.get, u"missing")) |
---|
641 | |
---|
642 | personal = self._personal_node |
---|
643 | - d1.addCallback(lambda res: self.shouldFail2(NotMutableError, "mv from readonly", None, dirnode.move_child_to, u"mydata992", personal, u"nope")) |
---|
644 | + d1.addCallback(lambda res: self.shouldFail2(NotWriteableError, "mv from readonly", None, dirnode.move_child_to, u"mydata992", personal, u"nope")) |
---|
645 | |
---|
646 | d1.addCallback(self.log, "doing move_child_to(ro)2") |
---|
647 | - d1.addCallback(lambda res: self.shouldFail2(NotMutableError, "mv to readonly", None, personal.move_child_to, u"sekrit data", dirnode, u"nope")) |
---|
648 | + d1.addCallback(lambda res: self.shouldFail2(NotWriteableError, "mv to readonly", None, personal.move_child_to, u"sekrit data", dirnode, u"nope")) |
---|
649 | |
---|
650 | d1.addCallback(self.log, "finished with _got_s2ro") |
---|
651 | return d1 |
---|
652 | diff -rN -u old-tahoe/src/allmydata/test/test_uri.py new-tahoe/src/allmydata/test/test_uri.py |
---|
653 | --- old-tahoe/src/allmydata/test/test_uri.py 2010-01-23 12:59:05.156000000 +0000 |
---|
654 | +++ new-tahoe/src/allmydata/test/test_uri.py 2010-01-23 12:59:05.626000000 +0000 |
---|
655 | @@ -3,7 +3,7 @@ |
---|
656 | from allmydata import uri |
---|
657 | from allmydata.util import hashutil, base32 |
---|
658 | from allmydata.interfaces import IURI, IFileURI, IDirnodeURI, IMutableFileURI, \ |
---|
659 | - IVerifierURI |
---|
660 | + IVerifierURI, CapConstraintError |
---|
661 | |
---|
662 | class Literal(unittest.TestCase): |
---|
663 | def _help_test(self, data): |
---|
664 | @@ -22,8 +22,16 @@ |
---|
665 | self.failIf(IDirnodeURI.providedBy(u2)) |
---|
666 | self.failUnlessEqual(u2.data, data) |
---|
667 | self.failUnlessEqual(u2.get_size(), len(data)) |
---|
668 | - self.failUnless(u.is_readonly()) |
---|
669 | - self.failIf(u.is_mutable()) |
---|
670 | + self.failUnless(u2.is_readonly()) |
---|
671 | + self.failIf(u2.is_mutable()) |
---|
672 | + |
---|
673 | + u2i = uri.from_string(u.to_string(), deep_immutable=True) |
---|
674 | + self.failUnless(IFileURI.providedBy(u2i)) |
---|
675 | + self.failIf(IDirnodeURI.providedBy(u2i)) |
---|
676 | + self.failUnlessEqual(u2i.data, data) |
---|
677 | + self.failUnlessEqual(u2i.get_size(), len(data)) |
---|
678 | + self.failUnless(u2i.is_readonly()) |
---|
679 | + self.failIf(u2i.is_mutable()) |
---|
680 | |
---|
681 | u3 = u.get_readonly() |
---|
682 | self.failUnlessIdentical(u, u3) |
---|
683 | @@ -51,18 +59,36 @@ |
---|
684 | fileURI = 'URI:CHK:f5ahxa25t4qkktywz6teyfvcx4:opuioq7tj2y6idzfp6cazehtmgs5fdcebcz3cygrxyydvcozrmeq:3:10:345834' |
---|
685 | chk1 = uri.CHKFileURI.init_from_string(fileURI) |
---|
686 | chk2 = uri.CHKFileURI.init_from_string(fileURI) |
---|
687 | + unk = uri.UnknownURI("lafs://from_the_future") |
---|
688 | self.failIfEqual(lit1, chk1) |
---|
689 | self.failUnlessEqual(chk1, chk2) |
---|
690 | self.failIfEqual(chk1, "not actually a URI") |
---|
691 | # these should be hashable too |
---|
692 | - s = set([lit1, chk1, chk2]) |
---|
693 | - self.failUnlessEqual(len(s), 2) # since chk1==chk2 |
---|
694 | + s = set([lit1, chk1, chk2, unk]) |
---|
695 | + self.failUnlessEqual(len(s), 3) # since chk1==chk2 |
---|
696 | |
---|
697 | def test_is_uri(self): |
---|
698 | lit1 = uri.LiteralFileURI("some data").to_string() |
---|
699 | self.failUnless(uri.is_uri(lit1)) |
---|
700 | self.failIf(uri.is_uri(None)) |
---|
701 | |
---|
702 | + def test_is_literal_file_uri(self): |
---|
703 | + lit1 = uri.LiteralFileURI("some data").to_string() |
---|
704 | + self.failUnless(uri.is_literal_file_uri(lit1)) |
---|
705 | + self.failIf(uri.is_literal_file_uri(None)) |
---|
706 | + self.failIf(uri.is_literal_file_uri("foo")) |
---|
707 | + self.failIf(uri.is_literal_file_uri("ro.foo")) |
---|
708 | + self.failIf(uri.is_literal_file_uri("URI:LITfoo")) |
---|
709 | + self.failUnless(uri.is_literal_file_uri("ro.URI:LIT:foo")) |
---|
710 | + self.failUnless(uri.is_literal_file_uri("imm.URI:LIT:foo")) |
---|
711 | + |
---|
712 | + def test_has_uri_prefix(self): |
---|
713 | + self.failUnless(uri.has_uri_prefix("URI:foo")) |
---|
714 | + self.failUnless(uri.has_uri_prefix("ro.URI:foo")) |
---|
715 | + self.failUnless(uri.has_uri_prefix("imm.URI:foo")) |
---|
716 | + self.failIf(uri.has_uri_prefix(None)) |
---|
717 | + self.failIf(uri.has_uri_prefix("foo")) |
---|
718 | + |
---|
719 | class CHKFile(unittest.TestCase): |
---|
720 | def test_pack(self): |
---|
721 | key = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" |
---|
722 | @@ -88,8 +114,7 @@ |
---|
723 | self.failUnless(IFileURI.providedBy(u)) |
---|
724 | self.failIf(IDirnodeURI.providedBy(u)) |
---|
725 | self.failUnlessEqual(u.get_size(), 1234) |
---|
726 | - self.failUnless(u.is_readonly()) |
---|
727 | - self.failIf(u.is_mutable()) |
---|
728 | + |
---|
729 | u_ro = u.get_readonly() |
---|
730 | self.failUnlessIdentical(u, u_ro) |
---|
731 | he = u.to_human_encoding() |
---|
732 | @@ -109,11 +134,19 @@ |
---|
733 | self.failUnless(IFileURI.providedBy(u2)) |
---|
734 | self.failIf(IDirnodeURI.providedBy(u2)) |
---|
735 | self.failUnlessEqual(u2.get_size(), 1234) |
---|
736 | - self.failUnless(u2.is_readonly()) |
---|
737 | - self.failIf(u2.is_mutable()) |
---|
738 | + |
---|
739 | + u2i = uri.from_string(u.to_string(), deep_immutable=True) |
---|
740 | + self.failUnlessEqual(u.to_string(), u2i.to_string()) |
---|
741 | + u2ro = uri.from_string(uri.ALLEGED_READONLY_PREFIX + u.to_string()) |
---|
742 | + self.failUnlessEqual(u.to_string(), u2ro.to_string()) |
---|
743 | + u2imm = uri.from_string(uri.ALLEGED_IMMUTABLE_PREFIX + u.to_string()) |
---|
744 | + self.failUnlessEqual(u.to_string(), u2imm.to_string()) |
---|
745 | |
---|
746 | v = u.get_verify_cap() |
---|
747 | self.failUnless(isinstance(v.to_string(), str)) |
---|
748 | + self.failUnless(v.is_readonly()) |
---|
749 | + self.failIf(v.is_mutable()) |
---|
750 | + |
---|
751 | v2 = uri.from_string(v.to_string()) |
---|
752 | self.failUnlessEqual(v, v2) |
---|
753 | he = v.to_human_encoding() |
---|
754 | @@ -126,6 +159,8 @@ |
---|
755 | total_shares=10, |
---|
756 | size=1234) |
---|
757 | self.failUnless(isinstance(v3.to_string(), str)) |
---|
758 | + self.failUnless(v3.is_readonly()) |
---|
759 | + self.failIf(v3.is_mutable()) |
---|
760 | |
---|
761 | def test_pack_badly(self): |
---|
762 | key = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" |
---|
763 | @@ -179,13 +214,20 @@ |
---|
764 | self.failUnlessEqual(readable["UEB_hash"], |
---|
765 | base32.b2a(hashutil.uri_extension_hash(ext))) |
---|
766 | |
---|
767 | -class Invalid(unittest.TestCase): |
---|
768 | +class Unknown(unittest.TestCase): |
---|
769 | def test_from_future(self): |
---|
770 | # any URI type that we don't recognize should be treated as unknown |
---|
771 | future_uri = "I am a URI from the future. Whatever you do, don't " |
---|
772 | u = uri.from_string(future_uri) |
---|
773 | self.failUnless(isinstance(u, uri.UnknownURI)) |
---|
774 | self.failUnlessEqual(u.to_string(), future_uri) |
---|
775 | + self.failUnless(u.get_readonly() is None) |
---|
776 | + self.failUnless(u.get_error() is None) |
---|
777 | + |
---|
778 | + u2 = uri.UnknownURI(future_uri, error=CapConstraintError("...")) |
---|
779 | + self.failUnlessEqual(u.to_string(), future_uri) |
---|
780 | + self.failUnless(u2.get_readonly() is None) |
---|
781 | + self.failUnless(isinstance(u2.get_error(), CapConstraintError)) |
---|
782 | |
---|
783 | class Constraint(unittest.TestCase): |
---|
784 | def test_constraint(self): |
---|
785 | @@ -226,6 +268,13 @@ |
---|
786 | self.failUnless(IMutableFileURI.providedBy(u2)) |
---|
787 | self.failIf(IDirnodeURI.providedBy(u2)) |
---|
788 | |
---|
789 | + u2i = uri.from_string(u.to_string(), deep_immutable=True) |
---|
790 | + self.failUnless(isinstance(u2i, uri.UnknownURI), u2i) |
---|
791 | + u2ro = uri.from_string(uri.ALLEGED_READONLY_PREFIX + u.to_string()) |
---|
792 | + self.failUnless(isinstance(u2ro, uri.UnknownURI), u2ro) |
---|
793 | + u2imm = uri.from_string(uri.ALLEGED_IMMUTABLE_PREFIX + u.to_string()) |
---|
794 | + self.failUnless(isinstance(u2imm, uri.UnknownURI), u2imm) |
---|
795 | + |
---|
796 | u3 = u2.get_readonly() |
---|
797 | readkey = hashutil.ssk_readkey_hash(writekey) |
---|
798 | self.failUnlessEqual(u3.fingerprint, fingerprint) |
---|
799 | @@ -236,6 +285,13 @@ |
---|
800 | self.failUnless(IMutableFileURI.providedBy(u3)) |
---|
801 | self.failIf(IDirnodeURI.providedBy(u3)) |
---|
802 | |
---|
803 | + u3i = uri.from_string(u3.to_string(), deep_immutable=True) |
---|
804 | + self.failUnless(isinstance(u3i, uri.UnknownURI), u3i) |
---|
805 | + u3ro = uri.from_string(uri.ALLEGED_READONLY_PREFIX + u3.to_string()) |
---|
806 | + self.failUnlessEqual(u3.to_string(), u3ro.to_string()) |
---|
807 | + u3imm = uri.from_string(uri.ALLEGED_IMMUTABLE_PREFIX + u3.to_string()) |
---|
808 | + self.failUnless(isinstance(u3imm, uri.UnknownURI), u3imm) |
---|
809 | + |
---|
810 | he = u3.to_human_encoding() |
---|
811 | u3_h = uri.ReadonlySSKFileURI.init_from_human_encoding(he) |
---|
812 | self.failUnlessEqual(u3, u3_h) |
---|
813 | @@ -249,6 +305,13 @@ |
---|
814 | self.failUnless(IMutableFileURI.providedBy(u4)) |
---|
815 | self.failIf(IDirnodeURI.providedBy(u4)) |
---|
816 | |
---|
817 | + u4i = uri.from_string(u4.to_string(), deep_immutable=True) |
---|
818 | + self.failUnless(isinstance(u4i, uri.UnknownURI), u4i) |
---|
819 | + u4ro = uri.from_string(uri.ALLEGED_READONLY_PREFIX + u4.to_string()) |
---|
820 | + self.failUnlessEqual(u4.to_string(), u4ro.to_string()) |
---|
821 | + u4imm = uri.from_string(uri.ALLEGED_IMMUTABLE_PREFIX + u4.to_string()) |
---|
822 | + self.failUnless(isinstance(u4imm, uri.UnknownURI), u4imm) |
---|
823 | + |
---|
824 | u4a = uri.from_string(u4.to_string()) |
---|
825 | self.failUnlessEqual(u4a, u4) |
---|
826 | self.failUnless("ReadonlySSKFileURI" in str(u4a)) |
---|
827 | @@ -291,12 +354,19 @@ |
---|
828 | self.failIf(IFileURI.providedBy(u2)) |
---|
829 | self.failUnless(IDirnodeURI.providedBy(u2)) |
---|
830 | |
---|
831 | + u2i = uri.from_string(u1.to_string(), deep_immutable=True) |
---|
832 | + self.failUnless(isinstance(u2i, uri.UnknownURI)) |
---|
833 | + |
---|
834 | u3 = u2.get_readonly() |
---|
835 | self.failUnless(u3.is_readonly()) |
---|
836 | self.failUnless(u3.is_mutable()) |
---|
837 | self.failUnless(IURI.providedBy(u3)) |
---|
838 | self.failIf(IFileURI.providedBy(u3)) |
---|
839 | self.failUnless(IDirnodeURI.providedBy(u3)) |
---|
840 | + |
---|
841 | + u3i = uri.from_string(u2.to_string(), deep_immutable=True) |
---|
842 | + self.failUnless(isinstance(u3i, uri.UnknownURI)) |
---|
843 | + |
---|
844 | u3n = u3._filenode_uri |
---|
845 | self.failUnless(u3n.is_readonly()) |
---|
846 | self.failUnless(u3n.is_mutable()) |
---|
847 | @@ -363,10 +433,16 @@ |
---|
848 | self.failIf(IFileURI.providedBy(u2)) |
---|
849 | self.failUnless(IDirnodeURI.providedBy(u2)) |
---|
850 | |
---|
851 | + u2i = uri.from_string(u1.to_string(), deep_immutable=True) |
---|
852 | + self.failUnlessEqual(u1.to_string(), u2i.to_string()) |
---|
853 | + |
---|
854 | u3 = u2.get_readonly() |
---|
855 | self.failUnlessEqual(u3.to_string(), u2.to_string()) |
---|
856 | self.failUnless(str(u3)) |
---|
857 | |
---|
858 | + u3i = uri.from_string(u2.to_string(), deep_immutable=True) |
---|
859 | + self.failUnlessEqual(u2.to_string(), u3i.to_string()) |
---|
860 | + |
---|
861 | u2_verifier = u2.get_verify_cap() |
---|
862 | self.failUnless(isinstance(u2_verifier, |
---|
863 | uri.ImmutableDirectoryURIVerifier), |
---|
864 | diff -rN -u old-tahoe/src/allmydata/test/test_web.py new-tahoe/src/allmydata/test/test_web.py |
---|
865 | --- old-tahoe/src/allmydata/test/test_web.py 2010-01-23 12:59:05.171000000 +0000 |
---|
866 | +++ new-tahoe/src/allmydata/test/test_web.py 2010-01-23 12:59:05.639000000 +0000 |
---|
867 | @@ -7,7 +7,7 @@ |
---|
868 | from twisted.web import client, error, http |
---|
869 | from twisted.python import failure, log |
---|
870 | from nevow import rend |
---|
871 | -from allmydata import interfaces, uri, webish |
---|
872 | +from allmydata import interfaces, uri, webish, dirnode |
---|
873 | from allmydata.storage.shares import get_share_file |
---|
874 | from allmydata.storage_client import StorageFarmBroker |
---|
875 | from allmydata.immutable import upload, download |
---|
876 | @@ -18,6 +18,7 @@ |
---|
877 | from allmydata.scripts.debug import CorruptShareOptions, corrupt_share |
---|
878 | from allmydata.util import fileutil, base32 |
---|
879 | from allmydata.util.consumer import download_to_data |
---|
880 | +from allmydata.util.netstring import split_netstring |
---|
881 | from allmydata.test.common import FakeCHKFileNode, FakeMutableFileNode, \ |
---|
882 | create_chk_filenode, WebErrorMixin, ShouldFailMixin, make_mutable_file_uri |
---|
883 | from allmydata.interfaces import IMutableFileNode |
---|
884 | @@ -366,25 +367,101 @@ |
---|
885 | self.fail("%s was supposed to Error(404), not get '%s'" % |
---|
886 | (which, res)) |
---|
887 | |
---|
888 | + def _dump_res(self, res): |
---|
889 | + import traceback |
---|
890 | + s = "%r\n" % (res,) |
---|
891 | + if hasattr(res, 'tb_frame'): |
---|
892 | + s += "Traceback:\n%s\n" % (traceback.format_tb(res),) |
---|
893 | + if hasattr(res, 'value'): |
---|
894 | + s += "%r\n" % (res.value,) |
---|
895 | + if hasattr(res.value, 'tb_frame'): |
---|
896 | + s += "Traceback:\n%s\n" % (res, res.value, traceback.format_tb(res)) |
---|
897 | + if hasattr(res.value, 'response'): |
---|
898 | + s += "Response body:\n%s\n" % (res.value.response,) |
---|
899 | + return s |
---|
900 | + |
---|
901 | + def shouldSucceedGET(self, urlpath, followRedirect=False, |
---|
902 | + expected_statuscode=http.OK, return_response=False, **kwargs): |
---|
903 | + d = self.GET(urlpath, followRedirect=followRedirect, return_response=True, **kwargs) |
---|
904 | + def done((res, statuscode, headers)): |
---|
905 | + if isinstance(res, failure.Failure): |
---|
906 | + self.fail(("'GET %s' with kwargs %r was supposed to succeed with statuscode %s, " |
---|
907 | + "but it failed with statuscode %s instead.\n" |
---|
908 | + "%s\nThe response headers were:\n%s") % ( |
---|
909 | + urlpath, kwargs, expected_statuscode, statuscode, |
---|
910 | + self._dump_res(res), headers)) |
---|
911 | + if str(statuscode) != str(expected_statuscode): |
---|
912 | + self.fail(("'GET %s' with kwargs %r was supposed to succeed with statuscode %s, " |
---|
913 | + "but it succeeded with statuscode %s instead.\n" |
---|
914 | + "The response headers were:\n%s\n\n" |
---|
915 | + "The response body was:\n%s") % ( |
---|
916 | + urlpath, kwargs, expected_statuscode, statuscode, headers, res)) |
---|
917 | + if return_response: |
---|
918 | + return (res, statuscode, headers) |
---|
919 | + else: |
---|
920 | + return res |
---|
921 | + d.addBoth(done) |
---|
922 | + return d |
---|
923 | + |
---|
924 | + def shouldSucceedHEAD(self, urlpath, expected_statuscode=http.OK, |
---|
925 | + return_response=False, **kwargs): |
---|
926 | + d = self.HEAD(urlpath, return_response=True, **kwargs) |
---|
927 | + def done((res, statuscode, headers)): |
---|
928 | + if isinstance(res, failure.Failure): |
---|
929 | + self.fail(("'HEAD %s' with kwargs %r was supposed to succeed with statuscode %s, " |
---|
930 | + "but it failed with statuscode %s instead.\n" |
---|
931 | + "%s\nThe response headers were:\n%s") % ( |
---|
932 | + urlpath, kwargs, expected_statuscode, statuscode, |
---|
933 | + self._dump_res(res), headers)) |
---|
934 | + if str(statuscode) != str(expected_statuscode): |
---|
935 | + self.fail(("'HEAD %s' with kwargs %r was supposed to succeed with statuscode %s, " |
---|
936 | + "but it succeeded with statuscode %s instead.\n" |
---|
937 | + "The response headers were:\n%s\n\n" |
---|
938 | + "The response body was:\n%s") % ( |
---|
939 | + urlpath, kwargs, expected_statuscode, statuscode, headers, res)) |
---|
940 | + if return_response: |
---|
941 | + return (res, statuscode, headers) |
---|
942 | + else: |
---|
943 | + return res |
---|
944 | + d.addBoth(done) |
---|
945 | + return d |
---|
946 | + |
---|
947 | + def shouldSucceed(self, which, expected_statuscode, callable, *args, **kwargs): |
---|
948 | + d = defer.maybeDeferred(callable, *args, **kwargs) |
---|
949 | + def done(res): |
---|
950 | + if isinstance(res, failure.Failure): |
---|
951 | + self.fail(("%s:\nAn HTTP op with args %r and kwargs %r was supposed to " |
---|
952 | + "succeed with statuscode %s, but it failed:\n%s") % ( |
---|
953 | + which, args, kwargs, expected_statuscode, |
---|
954 | + self._dump_res(res))) |
---|
955 | + #if str(statuscode) != str(expected_statuscode): |
---|
956 | + # self.fail(("%s:\nAn HTTP op with args %r and kwargs %r was supposed to " |
---|
957 | + # "succeed with statuscode %s, but it succeeded with statuscode %s instead.\n" |
---|
958 | + # "The response body was:\n%s") % ( |
---|
959 | + # which, args, kwargs, expected_statuscode, statuscode, res)) |
---|
960 | + return res |
---|
961 | + d.addBoth(done) |
---|
962 | + return d |
---|
963 | + |
---|
964 | |
---|
965 | class Web(WebMixin, WebErrorMixin, testutil.StallMixin, unittest.TestCase): |
---|
966 | def test_create(self): |
---|
967 | pass |
---|
968 | |
---|
969 | def test_welcome(self): |
---|
970 | - d = self.GET("/") |
---|
971 | + d = self.shouldSucceedGET("/") |
---|
972 | def _check(res): |
---|
973 | self.failUnless('Welcome To Tahoe-LAFS' in res, res) |
---|
974 | |
---|
975 | self.s.basedir = 'web/test_welcome' |
---|
976 | fileutil.make_dirs("web/test_welcome") |
---|
977 | fileutil.make_dirs("web/test_welcome/private") |
---|
978 | - return self.GET("/") |
---|
979 | + return self.shouldSucceedGET("/") |
---|
980 | d.addCallback(_check) |
---|
981 | return d |
---|
982 | |
---|
983 | def test_provisioning(self): |
---|
984 | - d = self.GET("/provisioning/") |
---|
985 | + d = self.shouldSucceedGET("/provisioning/") |
---|
986 | def _check(res): |
---|
987 | self.failUnless('Tahoe Provisioning Tool' in res) |
---|
988 | fields = {'filled': True, |
---|
989 | @@ -400,9 +477,10 @@ |
---|
990 | "delete_rate": 10, |
---|
991 | "lease_timer": 7, |
---|
992 | } |
---|
993 | - return self.POST("/provisioning/", **fields) |
---|
994 | - |
---|
995 | + return self.shouldSucceed("POST_provisioning-1", http.OK, self.POST, |
---|
996 | + "/provisioning/", **fields) |
---|
997 | d.addCallback(_check) |
---|
998 | + |
---|
999 | def _check2(res): |
---|
1000 | self.failUnless('Tahoe Provisioning Tool' in res) |
---|
1001 | self.failUnless("Share space consumed: 167.01TB" in res) |
---|
1002 | @@ -422,13 +500,17 @@ |
---|
1003 | "delete_rate": 100, |
---|
1004 | "lease_timer": 7, |
---|
1005 | } |
---|
1006 | - return self.POST("/provisioning/", **fields) |
---|
1007 | + return self.shouldSucceed("POST_provisioning-2", http.OK, self.POST, |
---|
1008 | + "/provisioning/", **fields) |
---|
1009 | d.addCallback(_check2) |
---|
1010 | + |
---|
1011 | def _check3(res): |
---|
1012 | self.failUnless("Share space consumed: huge!" in res) |
---|
1013 | fields = {'filled': True} |
---|
1014 | - return self.POST("/provisioning/", **fields) |
---|
1015 | + return self.shouldSucceed("POST_provisioning-3", http.OK, self.POST, |
---|
1016 | + "/provisioning/", **fields) |
---|
1017 | d.addCallback(_check3) |
---|
1018 | + |
---|
1019 | def _check4(res): |
---|
1020 | self.failUnless("Share space consumed:" in res) |
---|
1021 | d.addCallback(_check4) |
---|
1022 | @@ -442,7 +524,7 @@ |
---|
1023 | except: |
---|
1024 | raise unittest.SkipTest("reliability tool requires NumPy") |
---|
1025 | |
---|
1026 | - d = self.GET("/reliability/") |
---|
1027 | + d = self.shouldSucceedGET("/reliability/") |
---|
1028 | def _check(res): |
---|
1029 | self.failUnless('Tahoe Reliability Tool' in res) |
---|
1030 | fields = {'drive_lifetime': "8Y", |
---|
1031 | @@ -471,7 +553,7 @@ |
---|
1032 | mu_num = h.list_all_mapupdate_statuses()[0].get_counter() |
---|
1033 | pub_num = h.list_all_publish_statuses()[0].get_counter() |
---|
1034 | ret_num = h.list_all_retrieve_statuses()[0].get_counter() |
---|
1035 | - d = self.GET("/status", followRedirect=True) |
---|
1036 | + d = self.shouldSucceedGET("/status", followRedirect=True) |
---|
1037 | def _check(res): |
---|
1038 | self.failUnless('Upload and Download Status' in res, res) |
---|
1039 | self.failUnless('"down-%d"' % dl_num in res, res) |
---|
1040 | @@ -480,7 +562,7 @@ |
---|
1041 | self.failUnless('"publish-%d"' % pub_num in res, res) |
---|
1042 | self.failUnless('"retrieve-%d"' % ret_num in res, res) |
---|
1043 | d.addCallback(_check) |
---|
1044 | - d.addCallback(lambda res: self.GET("/status/?t=json")) |
---|
1045 | + d.addCallback(lambda res: self.shouldSucceedGET("/status/?t=json")) |
---|
1046 | def _check_json(res): |
---|
1047 | data = simplejson.loads(res) |
---|
1048 | self.failUnless(isinstance(data, dict)) |
---|
1049 | @@ -489,23 +571,23 @@ |
---|
1050 | # here. |
---|
1051 | d.addCallback(_check_json) |
---|
1052 | |
---|
1053 | - d.addCallback(lambda res: self.GET("/status/down-%d" % dl_num)) |
---|
1054 | + d.addCallback(lambda res: self.shouldSucceedGET("/status/down-%d" % dl_num)) |
---|
1055 | def _check_dl(res): |
---|
1056 | self.failUnless("File Download Status" in res, res) |
---|
1057 | d.addCallback(_check_dl) |
---|
1058 | - d.addCallback(lambda res: self.GET("/status/up-%d" % ul_num)) |
---|
1059 | + d.addCallback(lambda res: self.shouldSucceedGET("/status/up-%d" % ul_num)) |
---|
1060 | def _check_ul(res): |
---|
1061 | self.failUnless("File Upload Status" in res, res) |
---|
1062 | d.addCallback(_check_ul) |
---|
1063 | - d.addCallback(lambda res: self.GET("/status/mapupdate-%d" % mu_num)) |
---|
1064 | + d.addCallback(lambda res: self.shouldSucceedGET("/status/mapupdate-%d" % mu_num)) |
---|
1065 | def _check_mapupdate(res): |
---|
1066 | self.failUnless("Mutable File Servermap Update Status" in res, res) |
---|
1067 | d.addCallback(_check_mapupdate) |
---|
1068 | - d.addCallback(lambda res: self.GET("/status/publish-%d" % pub_num)) |
---|
1069 | + d.addCallback(lambda res: self.shouldSucceedGET("/status/publish-%d" % pub_num)) |
---|
1070 | def _check_publish(res): |
---|
1071 | self.failUnless("Mutable File Publish Status" in res, res) |
---|
1072 | d.addCallback(_check_publish) |
---|
1073 | - d.addCallback(lambda res: self.GET("/status/retrieve-%d" % ret_num)) |
---|
1074 | + d.addCallback(lambda res: self.shouldSucceedGET("/status/retrieve-%d" % ret_num)) |
---|
1075 | def _check_retrieve(res): |
---|
1076 | self.failUnless("Mutable File Retrieve Status" in res, res) |
---|
1077 | d.addCallback(_check_retrieve) |
---|
1078 | @@ -536,16 +618,15 @@ |
---|
1079 | self.failUnlessEqual(urrm.render_rate(None, 123), "123Bps") |
---|
1080 | |
---|
1081 | def test_GET_FILEURL(self): |
---|
1082 | - d = self.GET(self.public_url + "/foo/bar.txt") |
---|
1083 | + d = self.shouldSucceedGET(self.public_url + "/foo/bar.txt") |
---|
1084 | d.addCallback(self.failUnlessIsBarDotTxt) |
---|
1085 | return d |
---|
1086 | |
---|
1087 | def test_GET_FILEURL_range(self): |
---|
1088 | headers = {"range": "bytes=1-10"} |
---|
1089 | - d = self.GET(self.public_url + "/foo/bar.txt", headers=headers, |
---|
1090 | - return_response=True) |
---|
1091 | - def _got((res, status, headers)): |
---|
1092 | - self.failUnlessEqual(int(status), 206) |
---|
1093 | + d = self.shouldSucceedGET(self.public_url + "/foo/bar.txt", headers=headers, |
---|
1094 | + expected_statuscode=http.PARTIAL_CONTENT, return_response=True) |
---|
1095 | + def _got((res, statuscode, headers)): |
---|
1096 | self.failUnless(headers.has_key("content-range")) |
---|
1097 | self.failUnlessEqual(headers["content-range"][0], |
---|
1098 | "bytes 1-10/%d" % len(self.BAR_CONTENTS)) |
---|
1099 | @@ -556,10 +637,9 @@ |
---|
1100 | def test_GET_FILEURL_partial_range(self): |
---|
1101 | headers = {"range": "bytes=5-"} |
---|
1102 | length = len(self.BAR_CONTENTS) |
---|
1103 | - d = self.GET(self.public_url + "/foo/bar.txt", headers=headers, |
---|
1104 | - return_response=True) |
---|
1105 | - def _got((res, status, headers)): |
---|
1106 | - self.failUnlessEqual(int(status), 206) |
---|
1107 | + d = self.shouldSucceedGET(self.public_url + "/foo/bar.txt", headers=headers, |
---|
1108 | + expected_statuscode=http.PARTIAL_CONTENT, return_response=True) |
---|
1109 | + def _got((res, statuscode, headers)): |
---|
1110 | self.failUnless(headers.has_key("content-range")) |
---|
1111 | self.failUnlessEqual(headers["content-range"][0], |
---|
1112 | "bytes 5-%d/%d" % (length-1, length)) |
---|
1113 | @@ -569,11 +649,10 @@ |
---|
1114 | |
---|
1115 | def test_HEAD_FILEURL_range(self): |
---|
1116 | headers = {"range": "bytes=1-10"} |
---|
1117 | - d = self.HEAD(self.public_url + "/foo/bar.txt", headers=headers, |
---|
1118 | - return_response=True) |
---|
1119 | - def _got((res, status, headers)): |
---|
1120 | + d = self.shouldSucceedHEAD(self.public_url + "/foo/bar.txt", headers=headers, |
---|
1121 | + expected_statuscode=http.PARTIAL_CONTENT, return_response=True) |
---|
1122 | + def _got((res, statuscode, headers)): |
---|
1123 | self.failUnlessEqual(res, "") |
---|
1124 | - self.failUnlessEqual(int(status), 206) |
---|
1125 | self.failUnless(headers.has_key("content-range")) |
---|
1126 | self.failUnlessEqual(headers["content-range"][0], |
---|
1127 | "bytes 1-10/%d" % len(self.BAR_CONTENTS)) |
---|
1128 | @@ -583,10 +662,9 @@ |
---|
1129 | def test_HEAD_FILEURL_partial_range(self): |
---|
1130 | headers = {"range": "bytes=5-"} |
---|
1131 | length = len(self.BAR_CONTENTS) |
---|
1132 | - d = self.HEAD(self.public_url + "/foo/bar.txt", headers=headers, |
---|
1133 | - return_response=True) |
---|
1134 | - def _got((res, status, headers)): |
---|
1135 | - self.failUnlessEqual(int(status), 206) |
---|
1136 | + d = self.shouldSucceedHEAD(self.public_url + "/foo/bar.txt", headers=headers, |
---|
1137 | + expected_statuscode=http.PARTIAL_CONTENT, return_response=True) |
---|
1138 | + def _got((res, statuscode, headers)): |
---|
1139 | self.failUnless(headers.has_key("content-range")) |
---|
1140 | self.failUnlessEqual(headers["content-range"][0], |
---|
1141 | "bytes 5-%d/%d" % (length-1, length)) |
---|
1142 | @@ -595,7 +673,7 @@ |
---|
1143 | |
---|
1144 | def test_GET_FILEURL_range_bad(self): |
---|
1145 | headers = {"range": "BOGUS=fizbop-quarnak"} |
---|
1146 | - d = self.shouldFail2(error.Error, "test_GET_FILEURL_range_bad", |
---|
1147 | + d = self.shouldFail2(error.Error, "GET_FILEURL_range_bad", |
---|
1148 | "400 Bad Request", |
---|
1149 | "Syntactically invalid http range header", |
---|
1150 | self.GET, self.public_url + "/foo/bar.txt", |
---|
1151 | @@ -603,8 +681,9 @@ |
---|
1152 | return d |
---|
1153 | |
---|
1154 | def test_HEAD_FILEURL(self): |
---|
1155 | - d = self.HEAD(self.public_url + "/foo/bar.txt", return_response=True) |
---|
1156 | - def _got((res, status, headers)): |
---|
1157 | + d = self.shouldSucceedHEAD(self.public_url + "/foo/bar.txt", |
---|
1158 | + expected_statuscode=http.OK, return_response=True) |
---|
1159 | + def _got((res, statuscode, headers)): |
---|
1160 | self.failUnlessEqual(res, "") |
---|
1161 | self.failUnlessEqual(headers["content-length"][0], |
---|
1162 | str(len(self.BAR_CONTENTS))) |
---|
1163 | @@ -615,27 +694,27 @@ |
---|
1164 | def test_GET_FILEURL_named(self): |
---|
1165 | base = "/file/%s" % urllib.quote(self._bar_txt_uri) |
---|
1166 | base2 = "/named/%s" % urllib.quote(self._bar_txt_uri) |
---|
1167 | - d = self.GET(base + "/@@name=/blah.txt") |
---|
1168 | + d = self.shouldSucceedGET(base + "/@@name=/blah.txt") |
---|
1169 | d.addCallback(self.failUnlessIsBarDotTxt) |
---|
1170 | - d.addCallback(lambda res: self.GET(base + "/blah.txt")) |
---|
1171 | + d.addCallback(lambda res: self.shouldSucceedGET(base + "/blah.txt")) |
---|
1172 | d.addCallback(self.failUnlessIsBarDotTxt) |
---|
1173 | - d.addCallback(lambda res: self.GET(base + "/ignore/lots/blah.txt")) |
---|
1174 | + d.addCallback(lambda res: self.shouldSucceedGET(base + "/ignore/lots/blah.txt")) |
---|
1175 | d.addCallback(self.failUnlessIsBarDotTxt) |
---|
1176 | - d.addCallback(lambda res: self.GET(base2 + "/@@name=/blah.txt")) |
---|
1177 | + d.addCallback(lambda res: self.shouldSucceedGET(base2 + "/@@name=/blah.txt")) |
---|
1178 | d.addCallback(self.failUnlessIsBarDotTxt) |
---|
1179 | save_url = base + "?save=true&filename=blah.txt" |
---|
1180 | - d.addCallback(lambda res: self.GET(save_url)) |
---|
1181 | + d.addCallback(lambda res: self.shouldSucceedGET(save_url)) |
---|
1182 | d.addCallback(self.failUnlessIsBarDotTxt) # TODO: check headers |
---|
1183 | u_filename = u"n\u00e9wer.txt" # n e-acute w e r . t x t |
---|
1184 | u_fn_e = urllib.quote(u_filename.encode("utf-8")) |
---|
1185 | u_url = base + "?save=true&filename=" + u_fn_e |
---|
1186 | - d.addCallback(lambda res: self.GET(u_url)) |
---|
1187 | + d.addCallback(lambda res: self.shouldSucceedGET(u_url)) |
---|
1188 | d.addCallback(self.failUnlessIsBarDotTxt) # TODO: check headers |
---|
1189 | return d |
---|
1190 | |
---|
1191 | def test_PUT_FILEURL_named_bad(self): |
---|
1192 | base = "/file/%s" % urllib.quote(self._bar_txt_uri) |
---|
1193 | - d = self.shouldFail2(error.Error, "test_PUT_FILEURL_named_bad", |
---|
1194 | + d = self.shouldFail2(error.Error, "PUT_FILEURL_named_bad", |
---|
1195 | "400 Bad Request", |
---|
1196 | "/file can only be used with GET or HEAD", |
---|
1197 | self.PUT, base + "/@@name=/blah.txt", "") |
---|
1198 | @@ -643,14 +722,14 @@ |
---|
1199 | |
---|
1200 | def test_GET_DIRURL_named_bad(self): |
---|
1201 | base = "/file/%s" % urllib.quote(self._foo_uri) |
---|
1202 | - d = self.shouldFail2(error.Error, "test_PUT_DIRURL_named_bad", |
---|
1203 | + d = self.shouldFail2(error.Error, "PUT_DIRURL_named_bad", |
---|
1204 | "400 Bad Request", |
---|
1205 | "is not a file-cap", |
---|
1206 | self.GET, base + "/@@name=/blah.txt") |
---|
1207 | return d |
---|
1208 | |
---|
1209 | def test_GET_slash_file_bad(self): |
---|
1210 | - d = self.shouldFail2(error.Error, "test_GET_slash_file_bad", |
---|
1211 | + d = self.shouldFail2(error.Error, "GET_slash_file_bad", |
---|
1212 | "404 Not Found", |
---|
1213 | "/file must be followed by a file-cap and a name", |
---|
1214 | self.GET, "/file") |
---|
1215 | @@ -671,7 +750,7 @@ |
---|
1216 | verifier_cap = n.get_verify_cap().to_string() |
---|
1217 | base = "/uri/%s" % urllib.quote(verifier_cap) |
---|
1218 | # client.create_node_from_uri() can't handle verify-caps |
---|
1219 | - d = self.shouldFail2(error.Error, "test_GET_unhandled_URI", |
---|
1220 | + d = self.shouldFail2(error.Error, "GET_unhandled_URI", |
---|
1221 | "400 Bad Request", |
---|
1222 | "GET unknown URI type: can only do t=info", |
---|
1223 | self.GET, base) |
---|
1224 | @@ -679,14 +758,14 @@ |
---|
1225 | |
---|
1226 | def test_GET_FILE_URI(self): |
---|
1227 | base = "/uri/%s" % urllib.quote(self._bar_txt_uri) |
---|
1228 | - d = self.GET(base) |
---|
1229 | + d = self.shouldSucceedGET(base) |
---|
1230 | d.addCallback(self.failUnlessIsBarDotTxt) |
---|
1231 | return d |
---|
1232 | |
---|
1233 | def test_GET_FILE_URI_badchild(self): |
---|
1234 | base = "/uri/%s/boguschild" % urllib.quote(self._bar_txt_uri) |
---|
1235 | errmsg = "Files have no children, certainly not named 'boguschild'" |
---|
1236 | - d = self.shouldFail2(error.Error, "test_GET_FILE_URI_badchild", |
---|
1237 | + d = self.shouldFail2(error.Error, "GET_FILE_URI_badchild", |
---|
1238 | "400 Bad Request", errmsg, |
---|
1239 | self.GET, base) |
---|
1240 | return d |
---|
1241 | @@ -694,35 +773,42 @@ |
---|
1242 | def test_PUT_FILE_URI_badchild(self): |
---|
1243 | base = "/uri/%s/boguschild" % urllib.quote(self._bar_txt_uri) |
---|
1244 | errmsg = "Cannot create directory 'boguschild', because its parent is a file, not a directory" |
---|
1245 | - d = self.shouldFail2(error.Error, "test_GET_FILE_URI_badchild", |
---|
1246 | + d = self.shouldFail2(error.Error, "GET_FILE_URI_badchild", |
---|
1247 | "400 Bad Request", errmsg, |
---|
1248 | self.PUT, base, "") |
---|
1249 | return d |
---|
1250 | |
---|
1251 | + # TODO: version of this with a Unicode filename |
---|
1252 | def test_GET_FILEURL_save(self): |
---|
1253 | - d = self.GET(self.public_url + "/foo/bar.txt?filename=bar.txt&save=true") |
---|
1254 | - # TODO: look at the headers, expect a Content-Disposition: attachment |
---|
1255 | - # header. |
---|
1256 | - d.addCallback(self.failUnlessIsBarDotTxt) |
---|
1257 | + d = self.shouldSucceedGET(self.public_url + "/foo/bar.txt?filename=bar.txt&save=true", |
---|
1258 | + return_response=True) |
---|
1259 | + def _got((res, statuscode, headers)): |
---|
1260 | + content_disposition = headers["content-disposition"][0] |
---|
1261 | + self.failUnless(content_disposition == 'attachment; filename="bar.txt"', content_disposition) |
---|
1262 | + self.failUnlessIsBarDotTxt(res) |
---|
1263 | + d.addCallback(_got) |
---|
1264 | return d |
---|
1265 | |
---|
1266 | def test_GET_FILEURL_missing(self): |
---|
1267 | d = self.GET(self.public_url + "/foo/missing") |
---|
1268 | - d.addBoth(self.should404, "test_GET_FILEURL_missing") |
---|
1269 | + d.addBoth(self.should404, "GET_FILEURL_missing") |
---|
1270 | return d |
---|
1271 | |
---|
1272 | def test_PUT_overwrite_only_files(self): |
---|
1273 | # create a directory, put a file in that directory. |
---|
1274 | contents, n, filecap = self.makefile(8) |
---|
1275 | - d = self.PUT(self.public_url + "/foo/dir?t=mkdir", "") |
---|
1276 | + d = self.shouldSucceed("PUT_overwrite_only_files_1", http.OK, self.PUT, |
---|
1277 | + self.public_url + "/foo/dir?t=mkdir", "") |
---|
1278 | d.addCallback(lambda res: |
---|
1279 | - self.PUT(self.public_url + "/foo/dir/file1.txt", |
---|
1280 | - self.NEWFILE_CONTENTS)) |
---|
1281 | + self.shouldSucceed("PUT_overwrite_only_files_2", http.OK, self.PUT, |
---|
1282 | + self.public_url + "/foo/dir/file1.txt", |
---|
1283 | + self.NEWFILE_CONTENTS)) |
---|
1284 | # try to overwrite the file with replace=only-files |
---|
1285 | # (this should work) |
---|
1286 | d.addCallback(lambda res: |
---|
1287 | - self.PUT(self.public_url + "/foo/dir/file1.txt?t=uri&replace=only-files", |
---|
1288 | - filecap)) |
---|
1289 | + self.shouldSucceed("PUT_overwrite_only_files_3", http.OK, self.PUT, |
---|
1290 | + self.public_url + "/foo/dir/file1.txt?t=uri&replace=only-files", |
---|
1291 | + filecap)) |
---|
1292 | d.addCallback(lambda res: |
---|
1293 | self.shouldFail2(error.Error, "PUT_bad_t", "409 Conflict", |
---|
1294 | "There was already a child by that name, and you asked me " |
---|
1295 | @@ -732,21 +818,19 @@ |
---|
1296 | return d |
---|
1297 | |
---|
1298 | def test_PUT_NEWFILEURL(self): |
---|
1299 | - d = self.PUT(self.public_url + "/foo/new.txt", self.NEWFILE_CONTENTS) |
---|
1300 | - # TODO: we lose the response code, so we can't check this |
---|
1301 | - #self.failUnlessEqual(responsecode, 201) |
---|
1302 | - d.addCallback(self.failUnlessURIMatchesChild, self._foo_node, u"new.txt") |
---|
1303 | + d = self.shouldSucceed("PUT_NEWFILEURL", http.CREATED, self.PUT, |
---|
1304 | + self.public_url + "/foo/new.txt", self.NEWFILE_CONTENTS) |
---|
1305 | + d.addCallback(self.failUnlessURIMatchesROChild, self._foo_node, u"new.txt") |
---|
1306 | d.addCallback(lambda res: |
---|
1307 | self.failUnlessChildContentsAre(self._foo_node, u"new.txt", |
---|
1308 | self.NEWFILE_CONTENTS)) |
---|
1309 | return d |
---|
1310 | |
---|
1311 | def test_PUT_NEWFILEURL_not_mutable(self): |
---|
1312 | - d = self.PUT(self.public_url + "/foo/new.txt?mutable=false", |
---|
1313 | - self.NEWFILE_CONTENTS) |
---|
1314 | - # TODO: we lose the response code, so we can't check this |
---|
1315 | - #self.failUnlessEqual(responsecode, 201) |
---|
1316 | - d.addCallback(self.failUnlessURIMatchesChild, self._foo_node, u"new.txt") |
---|
1317 | + d = self.shouldSucceed("PUT_NEWFILEURL_not_mutable", http.CREATED, self.PUT, |
---|
1318 | + self.public_url + "/foo/new.txt?mutable=false", |
---|
1319 | + self.NEWFILE_CONTENTS) |
---|
1320 | + d.addCallback(self.failUnlessURIMatchesROChild, self._foo_node, u"new.txt") |
---|
1321 | d.addCallback(lambda res: |
---|
1322 | self.failUnlessChildContentsAre(self._foo_node, u"new.txt", |
---|
1323 | self.NEWFILE_CONTENTS)) |
---|
1324 | @@ -755,7 +839,7 @@ |
---|
1325 | def test_PUT_NEWFILEURL_range_bad(self): |
---|
1326 | headers = {"content-range": "bytes 1-10/%d" % len(self.NEWFILE_CONTENTS)} |
---|
1327 | target = self.public_url + "/foo/new.txt" |
---|
1328 | - d = self.shouldFail2(error.Error, "test_PUT_NEWFILEURL_range_bad", |
---|
1329 | + d = self.shouldFail2(error.Error, "PUT_NEWFILEURL_range_bad", |
---|
1330 | "501 Not Implemented", |
---|
1331 | "Content-Range in PUT not yet supported", |
---|
1332 | # (and certainly not for immutable files) |
---|
1333 | @@ -766,17 +850,16 @@ |
---|
1334 | return d |
---|
1335 | |
---|
1336 | def test_PUT_NEWFILEURL_mutable(self): |
---|
1337 | - d = self.PUT(self.public_url + "/foo/new.txt?mutable=true", |
---|
1338 | - self.NEWFILE_CONTENTS) |
---|
1339 | - # TODO: we lose the response code, so we can't check this |
---|
1340 | - #self.failUnlessEqual(responsecode, 201) |
---|
1341 | + d = self.shouldSucceed("PUT_NEWFILEURL_mutable", http.CREATED, self.PUT, |
---|
1342 | + self.public_url + "/foo/new.txt?mutable=true", |
---|
1343 | + self.NEWFILE_CONTENTS) |
---|
1344 | def _check_uri(res): |
---|
1345 | u = uri.from_string_mutable_filenode(res) |
---|
1346 | self.failUnless(u.is_mutable()) |
---|
1347 | self.failIf(u.is_readonly()) |
---|
1348 | return res |
---|
1349 | d.addCallback(_check_uri) |
---|
1350 | - d.addCallback(self.failUnlessURIMatchesChild, self._foo_node, u"new.txt") |
---|
1351 | + d.addCallback(self.failUnlessURIMatchesRWChild, self._foo_node, u"new.txt") |
---|
1352 | d.addCallback(lambda res: |
---|
1353 | self.failUnlessMutableChildContentsAre(self._foo_node, |
---|
1354 | u"new.txt", |
---|
1355 | @@ -784,7 +867,7 @@ |
---|
1356 | return d |
---|
1357 | |
---|
1358 | def test_PUT_NEWFILEURL_mutable_toobig(self): |
---|
1359 | - d = self.shouldFail2(error.Error, "test_PUT_NEWFILEURL_mutable_toobig", |
---|
1360 | + d = self.shouldFail2(error.Error, "PUT_NEWFILEURL_mutable_toobig", |
---|
1361 | "413 Request Entity Too Large", |
---|
1362 | "SDMF is limited to one segment, and 10001 > 10000", |
---|
1363 | self.PUT, |
---|
1364 | @@ -793,10 +876,9 @@ |
---|
1365 | return d |
---|
1366 | |
---|
1367 | def test_PUT_NEWFILEURL_replace(self): |
---|
1368 | - d = self.PUT(self.public_url + "/foo/bar.txt", self.NEWFILE_CONTENTS) |
---|
1369 | - # TODO: we lose the response code, so we can't check this |
---|
1370 | - #self.failUnlessEqual(responsecode, 200) |
---|
1371 | - d.addCallback(self.failUnlessURIMatchesChild, self._foo_node, u"bar.txt") |
---|
1372 | + d = self.shouldSucceed("PUT_NEWFILEURL_replace", http.OK, self.PUT, |
---|
1373 | + self.public_url + "/foo/bar.txt", self.NEWFILE_CONTENTS) |
---|
1374 | + d.addCallback(self.failUnlessURIMatchesROChild, self._foo_node, u"bar.txt") |
---|
1375 | d.addCallback(lambda res: |
---|
1376 | self.failUnlessChildContentsAre(self._foo_node, u"bar.txt", |
---|
1377 | self.NEWFILE_CONTENTS)) |
---|
1378 | @@ -819,9 +901,11 @@ |
---|
1379 | return d |
---|
1380 | |
---|
1381 | def test_PUT_NEWFILEURL_mkdirs(self): |
---|
1382 | - d = self.PUT(self.public_url + "/foo/newdir/new.txt", self.NEWFILE_CONTENTS) |
---|
1383 | + d = self.shouldSucceed("PUT_NEWFILEURL_mkdirs", http.OK, self.PUT, |
---|
1384 | + self.public_url + "/foo/newdir/new.txt", |
---|
1385 | + self.NEWFILE_CONTENTS) |
---|
1386 | fn = self._foo_node |
---|
1387 | - d.addCallback(self.failUnlessURIMatchesChild, fn, u"newdir/new.txt") |
---|
1388 | + d.addCallback(self.failUnlessURIMatchesROChild, fn, u"newdir/new.txt") |
---|
1389 | d.addCallback(lambda res: self.failIfNodeHasChild(fn, u"new.txt")) |
---|
1390 | d.addCallback(lambda res: self.failUnlessNodeHasChild(fn, u"newdir")) |
---|
1391 | d.addCallback(lambda res: |
---|
1392 | @@ -839,26 +923,27 @@ |
---|
1393 | |
---|
1394 | def test_PUT_NEWFILEURL_emptyname(self): |
---|
1395 | # an empty pathname component (i.e. a double-slash) is disallowed |
---|
1396 | - d = self.shouldFail2(error.Error, "test_PUT_NEWFILEURL_emptyname", |
---|
1397 | + d = self.shouldFail2(error.Error, "PUT_NEWFILEURL_emptyname", |
---|
1398 | "400 Bad Request", |
---|
1399 | "The webapi does not allow empty pathname components", |
---|
1400 | self.PUT, self.public_url + "/foo//new.txt", "") |
---|
1401 | return d |
---|
1402 | |
---|
1403 | def test_DELETE_FILEURL(self): |
---|
1404 | - d = self.DELETE(self.public_url + "/foo/bar.txt") |
---|
1405 | + d = self.shouldSucceed("DELETE_FILEURL", http.OK, self.DELETE, |
---|
1406 | + self.public_url + "/foo/bar.txt") |
---|
1407 | d.addCallback(lambda res: |
---|
1408 | self.failIfNodeHasChild(self._foo_node, u"bar.txt")) |
---|
1409 | return d |
---|
1410 | |
---|
1411 | def test_DELETE_FILEURL_missing(self): |
---|
1412 | d = self.DELETE(self.public_url + "/foo/missing") |
---|
1413 | - d.addBoth(self.should404, "test_DELETE_FILEURL_missing") |
---|
1414 | + d.addBoth(self.should404, "DELETE_FILEURL_missing") |
---|
1415 | return d |
---|
1416 | |
---|
1417 | def test_DELETE_FILEURL_missing2(self): |
---|
1418 | d = self.DELETE(self.public_url + "/missing/missing") |
---|
1419 | - d.addBoth(self.should404, "test_DELETE_FILEURL_missing2") |
---|
1420 | + d.addBoth(self.should404, "DELETE_FILEURL_missing2") |
---|
1421 | return d |
---|
1422 | |
---|
1423 | def failUnlessHasBarDotTxtMetadata(self, res): |
---|
1424 | @@ -875,7 +960,7 @@ |
---|
1425 | # I can't do "GET /path?json", I have to do "GET /path/t=json" |
---|
1426 | # instead. This may make it tricky to emulate the S3 interface |
---|
1427 | # completely. |
---|
1428 | - d = self.GET(self.public_url + "/foo/bar.txt?t=json") |
---|
1429 | + d = self.shouldSucceedGET(self.public_url + "/foo/bar.txt?t=json") |
---|
1430 | def _check1(data): |
---|
1431 | self.failUnlessIsBarJSON(data) |
---|
1432 | self.failUnlessHasBarDotTxtMetadata(data) |
---|
1433 | @@ -885,16 +970,16 @@ |
---|
1434 | |
---|
1435 | def test_GET_FILEURL_json_missing(self): |
---|
1436 | d = self.GET(self.public_url + "/foo/missing?json") |
---|
1437 | - d.addBoth(self.should404, "test_GET_FILEURL_json_missing") |
---|
1438 | + d.addBoth(self.should404, "GET_FILEURL_json_missing") |
---|
1439 | return d |
---|
1440 | |
---|
1441 | def test_GET_FILEURL_uri(self): |
---|
1442 | - d = self.GET(self.public_url + "/foo/bar.txt?t=uri") |
---|
1443 | + d = self.shouldSucceedGET(self.public_url + "/foo/bar.txt?t=uri") |
---|
1444 | def _check(res): |
---|
1445 | self.failUnlessEqual(res, self._bar_txt_uri) |
---|
1446 | d.addCallback(_check) |
---|
1447 | d.addCallback(lambda res: |
---|
1448 | - self.GET(self.public_url + "/foo/bar.txt?t=readonly-uri")) |
---|
1449 | + self.shouldSucceedGET(self.public_url + "/foo/bar.txt?t=readonly-uri")) |
---|
1450 | def _check2(res): |
---|
1451 | # for now, for files, uris and readonly-uris are the same |
---|
1452 | self.failUnlessEqual(res, self._bar_txt_uri) |
---|
1453 | @@ -910,14 +995,14 @@ |
---|
1454 | |
---|
1455 | def test_GET_FILEURL_uri_missing(self): |
---|
1456 | d = self.GET(self.public_url + "/foo/missing?t=uri") |
---|
1457 | - d.addBoth(self.should404, "test_GET_FILEURL_uri_missing") |
---|
1458 | + d.addBoth(self.should404, "GET_FILEURL_uri_missing") |
---|
1459 | return d |
---|
1460 | |
---|
1461 | def test_GET_DIRURL(self): |
---|
1462 | # the addSlash means we get a redirect here |
---|
1463 | # from /uri/$URI/foo/ , we need ../../../ to get back to the root |
---|
1464 | ROOT = "../../.." |
---|
1465 | - d = self.GET(self.public_url + "/foo", followRedirect=True) |
---|
1466 | + d = self.shouldSucceedGET(self.public_url + "/foo", followRedirect=True) |
---|
1467 | def _check(res): |
---|
1468 | self.failUnless(('<a href="%s">Return to Welcome page' % ROOT) |
---|
1469 | in res, res) |
---|
1470 | @@ -954,9 +1039,9 @@ |
---|
1471 | self.failUnless(re.search(get_sub, res), res) |
---|
1472 | d.addCallback(_check) |
---|
1473 | |
---|
1474 | - # look at a directory which is readonly |
---|
1475 | + # look at a readonly directory |
---|
1476 | d.addCallback(lambda res: |
---|
1477 | - self.GET(self.public_url + "/reedownlee", followRedirect=True)) |
---|
1478 | + self.shouldSucceedGET(self.public_url + "/reedownlee", followRedirect=True)) |
---|
1479 | def _check2(res): |
---|
1480 | self.failUnless("(read-only)" in res, res) |
---|
1481 | self.failIf("Upload a file" in res, res) |
---|
1482 | @@ -964,14 +1049,14 @@ |
---|
1483 | |
---|
1484 | # and at a directory that contains a readonly directory |
---|
1485 | d.addCallback(lambda res: |
---|
1486 | - self.GET(self.public_url, followRedirect=True)) |
---|
1487 | + self.shouldSucceedGET(self.public_url, followRedirect=True)) |
---|
1488 | def _check3(res): |
---|
1489 | self.failUnless(re.search('<td>DIR-RO</td>' |
---|
1490 | r'\s+<td><a href="[\.\/]+/uri/URI%3ADIR2-RO%3A[^"]+">reedownlee</a></td>', res), res) |
---|
1491 | d.addCallback(_check3) |
---|
1492 | |
---|
1493 | # and an empty directory |
---|
1494 | - d.addCallback(lambda res: self.GET(self.public_url + "/foo/empty/")) |
---|
1495 | + d.addCallback(lambda res: self.shouldSucceedGET(self.public_url + "/foo/empty/")) |
---|
1496 | def _check4(res): |
---|
1497 | self.failUnless("directory is empty" in res, res) |
---|
1498 | MKDIR_BUTTON_RE=re.compile('<input type="hidden" name="t" value="mkdir" />.*<legend class="freeform-form-label">Create a new directory in this directory</legend>.*<input type="submit" value="Create" />', re.I) |
---|
1499 | @@ -981,7 +1066,7 @@ |
---|
1500 | return d |
---|
1501 | |
---|
1502 | def test_GET_DIRURL_badtype(self): |
---|
1503 | - d = self.shouldHTTPError("test_GET_DIRURL_badtype", |
---|
1504 | + d = self.shouldHTTPError("GET_DIRURL_badtype", |
---|
1505 | 400, "Bad Request", |
---|
1506 | "bad t=bogus", |
---|
1507 | self.GET, |
---|
1508 | @@ -989,14 +1074,14 @@ |
---|
1509 | return d |
---|
1510 | |
---|
1511 | def test_GET_DIRURL_json(self): |
---|
1512 | - d = self.GET(self.public_url + "/foo?t=json") |
---|
1513 | + d = self.shouldSucceedGET(self.public_url + "/foo?t=json") |
---|
1514 | d.addCallback(self.failUnlessIsFooJSON) |
---|
1515 | return d |
---|
1516 | |
---|
1517 | |
---|
1518 | def test_POST_DIRURL_manifest_no_ophandle(self): |
---|
1519 | d = self.shouldFail2(error.Error, |
---|
1520 | - "test_POST_DIRURL_manifest_no_ophandle", |
---|
1521 | + "POST_DIRURL_manifest_no_ophandle", |
---|
1522 | "400 Bad Request", |
---|
1523 | "slow operation requires ophandle=", |
---|
1524 | self.POST, self.public_url, t="start-manifest") |
---|
1525 | @@ -1005,8 +1090,9 @@ |
---|
1526 | def test_POST_DIRURL_manifest(self): |
---|
1527 | d = defer.succeed(None) |
---|
1528 | def getman(ignored, output): |
---|
1529 | - d = self.POST(self.public_url + "/foo/?t=start-manifest&ophandle=125", |
---|
1530 | - followRedirect=True) |
---|
1531 | + d = self.shouldSucceed("POST_DIRURL_manifest", http.OK, self.POST, |
---|
1532 | + self.public_url + "/foo/?t=start-manifest&ophandle=125", |
---|
1533 | + followRedirect=True) |
---|
1534 | d.addCallback(self.wait_for_operation, "125") |
---|
1535 | d.addCallback(self.get_operation_results, "125", output) |
---|
1536 | return d |
---|
1537 | @@ -1019,7 +1105,7 @@ |
---|
1538 | d.addCallback(_got_html) |
---|
1539 | |
---|
1540 | # both t=status and unadorned GET should be identical |
---|
1541 | - d.addCallback(lambda res: self.GET("/operations/125")) |
---|
1542 | + d.addCallback(lambda res: self.shouldSucceedGET("/operations/125")) |
---|
1543 | d.addCallback(_got_html) |
---|
1544 | |
---|
1545 | d.addCallback(getman, "html") |
---|
1546 | @@ -1047,15 +1133,16 @@ |
---|
1547 | |
---|
1548 | def test_POST_DIRURL_deepsize_no_ophandle(self): |
---|
1549 | d = self.shouldFail2(error.Error, |
---|
1550 | - "test_POST_DIRURL_deepsize_no_ophandle", |
---|
1551 | + "POST_DIRURL_deepsize_no_ophandle", |
---|
1552 | "400 Bad Request", |
---|
1553 | "slow operation requires ophandle=", |
---|
1554 | self.POST, self.public_url, t="start-deep-size") |
---|
1555 | return d |
---|
1556 | |
---|
1557 | def test_POST_DIRURL_deepsize(self): |
---|
1558 | - d = self.POST(self.public_url + "/foo/?t=start-deep-size&ophandle=126", |
---|
1559 | - followRedirect=True) |
---|
1560 | + d = self.shouldSucceed("POST_DIRURL_deepsize", http.OK, self.POST, |
---|
1561 | + self.public_url + "/foo/?t=start-deep-size&ophandle=126", |
---|
1562 | + followRedirect=True) |
---|
1563 | d.addCallback(self.wait_for_operation, "126") |
---|
1564 | d.addCallback(self.get_operation_results, "126", "json") |
---|
1565 | def _got_json(data): |
---|
1566 | @@ -1075,15 +1162,16 @@ |
---|
1567 | |
---|
1568 | def test_POST_DIRURL_deepstats_no_ophandle(self): |
---|
1569 | d = self.shouldFail2(error.Error, |
---|
1570 | - "test_POST_DIRURL_deepstats_no_ophandle", |
---|
1571 | + "POST_DIRURL_deepstats_no_ophandle", |
---|
1572 | "400 Bad Request", |
---|
1573 | "slow operation requires ophandle=", |
---|
1574 | self.POST, self.public_url, t="start-deep-stats") |
---|
1575 | return d |
---|
1576 | |
---|
1577 | def test_POST_DIRURL_deepstats(self): |
---|
1578 | - d = self.POST(self.public_url + "/foo/?t=start-deep-stats&ophandle=127", |
---|
1579 | - followRedirect=True) |
---|
1580 | + d = self.shouldSucceed("POST_DIRURL_deepstats", http.OK, self.POST, |
---|
1581 | + self.public_url + "/foo/?t=start-deep-stats&ophandle=127", |
---|
1582 | + followRedirect=True) |
---|
1583 | d.addCallback(self.wait_for_operation, "127") |
---|
1584 | d.addCallback(self.get_operation_results, "127", "json") |
---|
1585 | def _got_json(stats): |
---|
1586 | @@ -1109,7 +1197,8 @@ |
---|
1587 | return d |
---|
1588 | |
---|
1589 | def test_POST_DIRURL_stream_manifest(self): |
---|
1590 | - d = self.POST(self.public_url + "/foo/?t=stream-manifest") |
---|
1591 | + d = self.shouldSucceed("POST_DIRURL_stream_manifest", http.OK, self.POST, |
---|
1592 | + self.public_url + "/foo/?t=stream-manifest") |
---|
1593 | def _check(res): |
---|
1594 | self.failUnless(res.endswith("\n")) |
---|
1595 | units = [simplejson.loads(t) for t in res[:-1].split("\n")] |
---|
1596 | @@ -1129,21 +1218,22 @@ |
---|
1597 | return d |
---|
1598 | |
---|
1599 | def test_GET_DIRURL_uri(self): |
---|
1600 | - d = self.GET(self.public_url + "/foo?t=uri") |
---|
1601 | + d = self.shouldSucceedGET(self.public_url + "/foo?t=uri") |
---|
1602 | def _check(res): |
---|
1603 | self.failUnlessEqual(res, self._foo_uri) |
---|
1604 | d.addCallback(_check) |
---|
1605 | return d |
---|
1606 | |
---|
1607 | def test_GET_DIRURL_readonly_uri(self): |
---|
1608 | - d = self.GET(self.public_url + "/foo?t=readonly-uri") |
---|
1609 | + d = self.shouldSucceedGET(self.public_url + "/foo?t=readonly-uri") |
---|
1610 | def _check(res): |
---|
1611 | self.failUnlessEqual(res, self._foo_readonly_uri) |
---|
1612 | d.addCallback(_check) |
---|
1613 | return d |
---|
1614 | |
---|
1615 | def test_PUT_NEWDIRURL(self): |
---|
1616 | - d = self.PUT(self.public_url + "/foo/newdir?t=mkdir", "") |
---|
1617 | + d = self.shouldSucceed("PUT_NEWDIRURL", http.OK, self.PUT, |
---|
1618 | + self.public_url + "/foo/newdir?t=mkdir", "") |
---|
1619 | d.addCallback(lambda res: |
---|
1620 | self.failUnlessNodeHasChild(self._foo_node, u"newdir")) |
---|
1621 | d.addCallback(lambda res: self._foo_node.get(u"newdir")) |
---|
1622 | @@ -1151,7 +1241,8 @@ |
---|
1623 | return d |
---|
1624 | |
---|
1625 | def test_POST_NEWDIRURL(self): |
---|
1626 | - d = self.POST2(self.public_url + "/foo/newdir?t=mkdir", "") |
---|
1627 | + d = self.shouldSucceed("POST_NEWDIRURL", http.OK, self.POST2, |
---|
1628 | + self.public_url + "/foo/newdir?t=mkdir", "") |
---|
1629 | d.addCallback(lambda res: |
---|
1630 | self.failUnlessNodeHasChild(self._foo_node, u"newdir")) |
---|
1631 | d.addCallback(lambda res: self._foo_node.get(u"newdir")) |
---|
1632 | @@ -1160,30 +1251,41 @@ |
---|
1633 | |
---|
1634 | def test_POST_NEWDIRURL_emptyname(self): |
---|
1635 | # an empty pathname component (i.e. a double-slash) is disallowed |
---|
1636 | - d = self.shouldFail2(error.Error, "test_POST_NEWDIRURL_emptyname", |
---|
1637 | + d = self.shouldFail2(error.Error, "POST_NEWDIRURL_emptyname", |
---|
1638 | "400 Bad Request", |
---|
1639 | "The webapi does not allow empty pathname components, i.e. a double slash", |
---|
1640 | self.POST, self.public_url + "//?t=mkdir") |
---|
1641 | return d |
---|
1642 | |
---|
1643 | def test_POST_NEWDIRURL_initial_children(self): |
---|
1644 | - (newkids, filecap1, filecap2, filecap3, |
---|
1645 | - dircap) = self._create_initial_children() |
---|
1646 | - d = self.POST2(self.public_url + "/foo/newdir?t=mkdir-with-children", |
---|
1647 | - simplejson.dumps(newkids)) |
---|
1648 | + (newkids, caps) = self._create_initial_children() |
---|
1649 | + d = self.shouldSucceed("POST_NEWDIRURL_initial_children", http.OK, self.POST2, |
---|
1650 | + self.public_url + "/foo/newdir?t=mkdir-with-children", |
---|
1651 | + simplejson.dumps(newkids)) |
---|
1652 | def _check(uri): |
---|
1653 | n = self.s.create_node_from_uri(uri.strip()) |
---|
1654 | d2 = self.failUnlessNodeKeysAre(n, newkids.keys()) |
---|
1655 | d2.addCallback(lambda ign: |
---|
1656 | - self.failUnlessChildURIIs(n, u"child-imm", filecap1)) |
---|
1657 | + self.failUnlessROChildURIIs(n, u"child-imm", |
---|
1658 | + caps['filecap1'])) |
---|
1659 | + d2.addCallback(lambda ign: |
---|
1660 | + self.failUnlessRWChildURIIs(n, u"child-mutable", |
---|
1661 | + caps['filecap2'])) |
---|
1662 | + d2.addCallback(lambda ign: |
---|
1663 | + self.failUnlessROChildURIIs(n, u"child-mutable-ro", |
---|
1664 | + caps['filecap3'])) |
---|
1665 | d2.addCallback(lambda ign: |
---|
1666 | - self.failUnlessChildURIIs(n, u"child-mutable", |
---|
1667 | - filecap2)) |
---|
1668 | + self.failUnlessROChildURIIs(n, u"unknownchild-ro", |
---|
1669 | + caps['unknown_rocap'])) |
---|
1670 | d2.addCallback(lambda ign: |
---|
1671 | - self.failUnlessChildURIIs(n, u"child-mutable-ro", |
---|
1672 | - filecap3)) |
---|
1673 | + self.failUnlessRWChildURIIs(n, u"unknownchild-rw", |
---|
1674 | + caps['unknown_rwcap'])) |
---|
1675 | d2.addCallback(lambda ign: |
---|
1676 | - self.failUnlessChildURIIs(n, u"dirchild", dircap)) |
---|
1677 | + self.failUnlessROChildURIIs(n, u"unknownchild-imm", |
---|
1678 | + caps['unknown_immcap'])) |
---|
1679 | + d2.addCallback(lambda ign: |
---|
1680 | + self.failUnlessRWChildURIIs(n, u"dirchild", |
---|
1681 | + caps['dircap'])) |
---|
1682 | return d2 |
---|
1683 | d.addCallback(_check) |
---|
1684 | d.addCallback(lambda res: |
---|
1685 | @@ -1191,21 +1293,26 @@ |
---|
1686 | d.addCallback(lambda res: self._foo_node.get(u"newdir")) |
---|
1687 | d.addCallback(self.failUnlessNodeKeysAre, newkids.keys()) |
---|
1688 | d.addCallback(lambda res: self._foo_node.get(u"newdir")) |
---|
1689 | - d.addCallback(self.failUnlessChildURIIs, u"child-imm", filecap1) |
---|
1690 | + d.addCallback(self.failUnlessROChildURIIs, u"child-imm", caps['filecap1']) |
---|
1691 | return d |
---|
1692 | |
---|
1693 | def test_POST_NEWDIRURL_immutable(self): |
---|
1694 | - (newkids, filecap1, immdircap) = self._create_immutable_children() |
---|
1695 | - d = self.POST2(self.public_url + "/foo/newdir?t=mkdir-immutable", |
---|
1696 | - simplejson.dumps(newkids)) |
---|
1697 | + (newkids, caps) = self._create_immutable_children() |
---|
1698 | + d = self.shouldSucceed("POST_NEWDIRURL_immutable", http.OK, self.POST2, |
---|
1699 | + self.public_url + "/foo/newdir?t=mkdir-immutable", |
---|
1700 | + simplejson.dumps(newkids)) |
---|
1701 | def _check(uri): |
---|
1702 | n = self.s.create_node_from_uri(uri.strip()) |
---|
1703 | d2 = self.failUnlessNodeKeysAre(n, newkids.keys()) |
---|
1704 | d2.addCallback(lambda ign: |
---|
1705 | - self.failUnlessChildURIIs(n, u"child-imm", filecap1)) |
---|
1706 | + self.failUnlessROChildURIIs(n, u"child-imm", |
---|
1707 | + caps['filecap1'])) |
---|
1708 | + d2.addCallback(lambda ign: |
---|
1709 | + self.failUnlessROChildURIIs(n, u"unknownchild-imm", |
---|
1710 | + caps['unknown_immcap'])) |
---|
1711 | d2.addCallback(lambda ign: |
---|
1712 | - self.failUnlessChildURIIs(n, u"dirchild-imm", |
---|
1713 | - immdircap)) |
---|
1714 | + self.failUnlessROChildURIIs(n, u"dirchild-imm", |
---|
1715 | + caps['immdircap'])) |
---|
1716 | return d2 |
---|
1717 | d.addCallback(_check) |
---|
1718 | d.addCallback(lambda res: |
---|
1719 | @@ -1213,25 +1320,27 @@ |
---|
1720 | d.addCallback(lambda res: self._foo_node.get(u"newdir")) |
---|
1721 | d.addCallback(self.failUnlessNodeKeysAre, newkids.keys()) |
---|
1722 | d.addCallback(lambda res: self._foo_node.get(u"newdir")) |
---|
1723 | - d.addCallback(self.failUnlessChildURIIs, u"child-imm", filecap1) |
---|
1724 | + d.addCallback(self.failUnlessROChildURIIs, u"child-imm", caps['filecap1']) |
---|
1725 | + d.addCallback(lambda res: self._foo_node.get(u"newdir")) |
---|
1726 | + d.addCallback(self.failUnlessROChildURIIs, u"unknownchild-imm", caps['unknown_immcap']) |
---|
1727 | d.addCallback(lambda res: self._foo_node.get(u"newdir")) |
---|
1728 | - d.addCallback(self.failUnlessChildURIIs, u"dirchild-imm", immdircap) |
---|
1729 | + d.addCallback(self.failUnlessROChildURIIs, u"dirchild-imm", caps['immdircap']) |
---|
1730 | d.addErrback(self.explain_web_error) |
---|
1731 | return d |
---|
1732 | |
---|
1733 | def test_POST_NEWDIRURL_immutable_bad(self): |
---|
1734 | - (newkids, filecap1, filecap2, filecap3, |
---|
1735 | - dircap) = self._create_initial_children() |
---|
1736 | - d = self.shouldFail2(error.Error, "test_POST_NEWDIRURL_immutable_bad", |
---|
1737 | + (newkids, caps) = self._create_initial_children() |
---|
1738 | + d = self.shouldFail2(error.Error, "POST_NEWDIRURL_immutable_bad", |
---|
1739 | "400 Bad Request", |
---|
1740 | - "a mkdir-immutable operation was given a child that was not itself immutable", |
---|
1741 | + "needed to be immutable but was not", |
---|
1742 | self.POST2, |
---|
1743 | self.public_url + "/foo/newdir?t=mkdir-immutable", |
---|
1744 | simplejson.dumps(newkids)) |
---|
1745 | return d |
---|
1746 | |
---|
1747 | def test_PUT_NEWDIRURL_exists(self): |
---|
1748 | - d = self.PUT(self.public_url + "/foo/sub?t=mkdir", "") |
---|
1749 | + d = self.shouldSucceed("PUT_NEWDIRURL_exists", http.OK, self.PUT, |
---|
1750 | + self.public_url + "/foo/sub?t=mkdir", "") |
---|
1751 | d.addCallback(lambda res: |
---|
1752 | self.failUnlessNodeHasChild(self._foo_node, u"sub")) |
---|
1753 | d.addCallback(lambda res: self._foo_node.get(u"sub")) |
---|
1754 | @@ -1249,18 +1358,21 @@ |
---|
1755 | d.addCallback(self.failUnlessNodeKeysAre, [u"baz.txt"]) |
---|
1756 | return d |
---|
1757 | |
---|
1758 | - def test_PUT_NEWDIRURL_mkdir_p(self): |
---|
1759 | + def test_POST_NEWDIRURL_mkdir_p(self): |
---|
1760 | d = defer.succeed(None) |
---|
1761 | - d.addCallback(lambda res: self.POST(self.public_url + "/foo", t='mkdir', name='mkp')) |
---|
1762 | + d.addCallback(lambda res: self.shouldSucceed("POST_NEWDIRURL_mkdir_p-1", http.OK, self.POST, |
---|
1763 | + self.public_url + "/foo", t='mkdir', name='mkp')) |
---|
1764 | d.addCallback(lambda res: self.failUnlessNodeHasChild(self._foo_node, u"mkp")) |
---|
1765 | d.addCallback(lambda res: self._foo_node.get(u"mkp")) |
---|
1766 | def mkdir_p(mkpnode): |
---|
1767 | url = '/uri/%s?t=mkdir-p&path=/sub1/sub2' % urllib.quote(mkpnode.get_uri()) |
---|
1768 | - d = self.POST(url) |
---|
1769 | + d = self.shouldSucceed("POST_NEWDIRURL_mkdir_p-2", http.OK, self.POST, |
---|
1770 | + url) |
---|
1771 | def made_subsub(ssuri): |
---|
1772 | d = self._foo_node.get_child_at_path(u"mkp/sub1/sub2") |
---|
1773 | d.addCallback(lambda ssnode: self.failUnlessEqual(ssnode.get_uri(), ssuri)) |
---|
1774 | - d = self.POST(url) |
---|
1775 | + d = self.shouldSucceed("POST_NEWDIRURL_mkdir_p-3", http.OK, self.POST, |
---|
1776 | + url) |
---|
1777 | d.addCallback(lambda uri2: self.failUnlessEqual(uri2, ssuri)) |
---|
1778 | return d |
---|
1779 | d.addCallback(made_subsub) |
---|
1780 | @@ -1269,7 +1381,8 @@ |
---|
1781 | return d |
---|
1782 | |
---|
1783 | def test_PUT_NEWDIRURL_mkdirs(self): |
---|
1784 | - d = self.PUT(self.public_url + "/foo/subdir/newdir?t=mkdir", "") |
---|
1785 | + d = self.shouldSucceed("PUT_NEWDIRURL_mkdirs", http.OK, self.PUT, |
---|
1786 | + self.public_url + "/foo/subdir/newdir?t=mkdir", "") |
---|
1787 | d.addCallback(lambda res: |
---|
1788 | self.failIfNodeHasChild(self._foo_node, u"newdir")) |
---|
1789 | d.addCallback(lambda res: |
---|
1790 | @@ -1280,21 +1393,22 @@ |
---|
1791 | return d |
---|
1792 | |
---|
1793 | def test_DELETE_DIRURL(self): |
---|
1794 | - d = self.DELETE(self.public_url + "/foo") |
---|
1795 | + d = self.shouldSucceed("DELETE_DIRURL", http.OK, self.DELETE, |
---|
1796 | + self.public_url + "/foo") |
---|
1797 | d.addCallback(lambda res: |
---|
1798 | self.failIfNodeHasChild(self.public_root, u"foo")) |
---|
1799 | return d |
---|
1800 | |
---|
1801 | def test_DELETE_DIRURL_missing(self): |
---|
1802 | d = self.DELETE(self.public_url + "/foo/missing") |
---|
1803 | - d.addBoth(self.should404, "test_DELETE_DIRURL_missing") |
---|
1804 | + d.addBoth(self.should404, "DELETE_DIRURL_missing") |
---|
1805 | d.addCallback(lambda res: |
---|
1806 | self.failUnlessNodeHasChild(self.public_root, u"foo")) |
---|
1807 | return d |
---|
1808 | |
---|
1809 | def test_DELETE_DIRURL_missing2(self): |
---|
1810 | d = self.DELETE(self.public_url + "/missing") |
---|
1811 | - d.addBoth(self.should404, "test_DELETE_DIRURL_missing2") |
---|
1812 | + d.addBoth(self.should404, "DELETE_DIRURL_missing2") |
---|
1813 | return d |
---|
1814 | |
---|
1815 | def dump_root(self): |
---|
1816 | @@ -1346,18 +1460,44 @@ |
---|
1817 | d.addCallback(_check) |
---|
1818 | return d |
---|
1819 | |
---|
1820 | - def failUnlessChildURIIs(self, node, name, expected_uri): |
---|
1821 | + def failUnlessRWChildURIIs(self, node, name, expected_uri): |
---|
1822 | + assert isinstance(name, unicode) |
---|
1823 | + d = node.get_child_at_path(name) |
---|
1824 | + def _check(child): |
---|
1825 | + self.failUnless(child.is_unknown() or not child.is_readonly()) |
---|
1826 | + self.failUnlessEqual(child.get_uri(), expected_uri.strip()) |
---|
1827 | + expected_ro_uri = self._make_readonly(expected_uri) |
---|
1828 | + if expected_ro_uri: |
---|
1829 | + self.failUnlessEqual(child.get_readonly_uri(), expected_ro_uri.strip()) |
---|
1830 | + d.addCallback(_check) |
---|
1831 | + return d |
---|
1832 | + |
---|
1833 | + def failUnlessROChildURIIs(self, node, name, expected_uri): |
---|
1834 | assert isinstance(name, unicode) |
---|
1835 | d = node.get_child_at_path(name) |
---|
1836 | def _check(child): |
---|
1837 | + self.failUnless(child.is_unknown() or child.is_readonly()) |
---|
1838 | self.failUnlessEqual(child.get_uri(), expected_uri.strip()) |
---|
1839 | d.addCallback(_check) |
---|
1840 | return d |
---|
1841 | |
---|
1842 | - def failUnlessURIMatchesChild(self, got_uri, node, name): |
---|
1843 | + def failUnlessURIMatchesRWChild(self, got_uri, node, name): |
---|
1844 | + assert isinstance(name, unicode) |
---|
1845 | + d = node.get_child_at_path(name) |
---|
1846 | + def _check(child): |
---|
1847 | + self.failUnless(child.is_unknown() or not child.is_readonly()) |
---|
1848 | + self.failUnlessEqual(child.get_uri(), got_uri.strip()) |
---|
1849 | + expected_ro_uri = self._make_readonly(got_uri) |
---|
1850 | + if expected_ro_uri: |
---|
1851 | + self.failUnlessEqual(child.get_readonly_uri(), expected_ro_uri.strip()) |
---|
1852 | + d.addCallback(_check) |
---|
1853 | + return d |
---|
1854 | + |
---|
1855 | + def failUnlessURIMatchesROChild(self, got_uri, node, name): |
---|
1856 | assert isinstance(name, unicode) |
---|
1857 | d = node.get_child_at_path(name) |
---|
1858 | def _check(child): |
---|
1859 | + self.failUnless(child.is_unknown() or child.is_readonly()) |
---|
1860 | self.failUnlessEqual(got_uri.strip(), child.get_uri()) |
---|
1861 | d.addCallback(_check) |
---|
1862 | return d |
---|
1863 | @@ -1366,10 +1506,11 @@ |
---|
1864 | self.failUnless(FakeCHKFileNode.all_contents[got_uri] == contents) |
---|
1865 | |
---|
1866 | def test_POST_upload(self): |
---|
1867 | - d = self.POST(self.public_url + "/foo", t="upload", |
---|
1868 | - file=("new.txt", self.NEWFILE_CONTENTS)) |
---|
1869 | + d = self.shouldSucceed("POST_upload", http.OK, self.POST, |
---|
1870 | + self.public_url + "/foo", t="upload", |
---|
1871 | + file=("new.txt", self.NEWFILE_CONTENTS)) |
---|
1872 | fn = self._foo_node |
---|
1873 | - d.addCallback(self.failUnlessURIMatchesChild, fn, u"new.txt") |
---|
1874 | + d.addCallback(self.failUnlessURIMatchesROChild, fn, u"new.txt") |
---|
1875 | d.addCallback(lambda res: |
---|
1876 | self.failUnlessChildContentsAre(fn, u"new.txt", |
---|
1877 | self.NEWFILE_CONTENTS)) |
---|
1878 | @@ -1377,15 +1518,16 @@ |
---|
1879 | |
---|
1880 | def test_POST_upload_unicode(self): |
---|
1881 | filename = u"n\u00e9wer.txt" # n e-acute w e r . t x t |
---|
1882 | - d = self.POST(self.public_url + "/foo", t="upload", |
---|
1883 | - file=(filename, self.NEWFILE_CONTENTS)) |
---|
1884 | + d = self.shouldSucceed("POST_upload_unicode", http.OK, self.POST, |
---|
1885 | + self.public_url + "/foo", t="upload", |
---|
1886 | + file=(filename, self.NEWFILE_CONTENTS)) |
---|
1887 | fn = self._foo_node |
---|
1888 | - d.addCallback(self.failUnlessURIMatchesChild, fn, filename) |
---|
1889 | + d.addCallback(self.failUnlessURIMatchesROChild, fn, filename) |
---|
1890 | d.addCallback(lambda res: |
---|
1891 | self.failUnlessChildContentsAre(fn, filename, |
---|
1892 | self.NEWFILE_CONTENTS)) |
---|
1893 | target_url = self.public_url + "/foo/" + filename.encode("utf-8") |
---|
1894 | - d.addCallback(lambda res: self.GET(target_url)) |
---|
1895 | + d.addCallback(lambda res: self.shouldSucceedGET(target_url)) |
---|
1896 | d.addCallback(lambda contents: self.failUnlessEqual(contents, |
---|
1897 | self.NEWFILE_CONTENTS, |
---|
1898 | contents)) |
---|
1899 | @@ -1393,24 +1535,26 @@ |
---|
1900 | |
---|
1901 | def test_POST_upload_unicode_named(self): |
---|
1902 | filename = u"n\u00e9wer.txt" # n e-acute w e r . t x t |
---|
1903 | - d = self.POST(self.public_url + "/foo", t="upload", |
---|
1904 | - name=filename, |
---|
1905 | - file=("overridden", self.NEWFILE_CONTENTS)) |
---|
1906 | + d = self.shouldSucceed("POST_upload_unicode_named", http.OK, self.POST, |
---|
1907 | + self.public_url + "/foo", t="upload", |
---|
1908 | + name=filename, |
---|
1909 | + file=("overridden", self.NEWFILE_CONTENTS)) |
---|
1910 | fn = self._foo_node |
---|
1911 | - d.addCallback(self.failUnlessURIMatchesChild, fn, filename) |
---|
1912 | + d.addCallback(self.failUnlessURIMatchesROChild, fn, filename) |
---|
1913 | d.addCallback(lambda res: |
---|
1914 | self.failUnlessChildContentsAre(fn, filename, |
---|
1915 | self.NEWFILE_CONTENTS)) |
---|
1916 | target_url = self.public_url + "/foo/" + filename.encode("utf-8") |
---|
1917 | - d.addCallback(lambda res: self.GET(target_url)) |
---|
1918 | + d.addCallback(lambda res: self.shouldSucceedGET(target_url)) |
---|
1919 | d.addCallback(lambda contents: self.failUnlessEqual(contents, |
---|
1920 | self.NEWFILE_CONTENTS, |
---|
1921 | contents)) |
---|
1922 | return d |
---|
1923 | |
---|
1924 | def test_POST_upload_no_link(self): |
---|
1925 | - d = self.POST("/uri", t="upload", |
---|
1926 | - file=("new.txt", self.NEWFILE_CONTENTS)) |
---|
1927 | + d = self.shouldSucceed("POST_upload_no_link", http.OK, self.POST, |
---|
1928 | + "/uri", t="upload", |
---|
1929 | + file=("new.txt", self.NEWFILE_CONTENTS)) |
---|
1930 | def _check_upload_results(page): |
---|
1931 | # this should be a page which describes the results of the upload |
---|
1932 | # that just finished. |
---|
1933 | @@ -1449,7 +1593,7 @@ |
---|
1934 | self.failUnlessEqual(statuscode, str(http.FOUND)) |
---|
1935 | self.failUnless(target.startswith(self.webish_url), target) |
---|
1936 | return client.getPage(target, method="GET") |
---|
1937 | - d = self.shouldRedirect2("test_POST_upload_no_link_whendone_results", |
---|
1938 | + d = self.shouldRedirect2("POST_upload_no_link_whendone_results", |
---|
1939 | check, |
---|
1940 | self.POST, "/uri", t="upload", |
---|
1941 | when_done="/uri/%(uri)s", |
---|
1942 | @@ -1459,8 +1603,9 @@ |
---|
1943 | return d |
---|
1944 | |
---|
1945 | def test_POST_upload_no_link_mutable(self): |
---|
1946 | - d = self.POST("/uri", t="upload", mutable="true", |
---|
1947 | - file=("new.txt", self.NEWFILE_CONTENTS)) |
---|
1948 | + d = self.shouldSucceed("POST_upload_no_link_mutable", http.OK, self.POST, |
---|
1949 | + "/uri", t="upload", mutable="true", |
---|
1950 | + file=("new.txt", self.NEWFILE_CONTENTS)) |
---|
1951 | def _check(filecap): |
---|
1952 | filecap = filecap.strip() |
---|
1953 | self.failUnless(filecap.startswith("URI:SSK:"), filecap) |
---|
1954 | @@ -1472,11 +1617,11 @@ |
---|
1955 | d.addCallback(_check) |
---|
1956 | def _check2(data): |
---|
1957 | self.failUnlessEqual(data, self.NEWFILE_CONTENTS) |
---|
1958 | - return self.GET("/uri/%s" % urllib.quote(self.filecap)) |
---|
1959 | + return self.shouldSucceedGET("/uri/%s" % urllib.quote(self.filecap)) |
---|
1960 | d.addCallback(_check2) |
---|
1961 | def _check3(data): |
---|
1962 | self.failUnlessEqual(data, self.NEWFILE_CONTENTS) |
---|
1963 | - return self.GET("/file/%s" % urllib.quote(self.filecap)) |
---|
1964 | + return self.shouldSucceedGET("/file/%s" % urllib.quote(self.filecap)) |
---|
1965 | d.addCallback(_check3) |
---|
1966 | def _check4(data): |
---|
1967 | self.failUnlessEqual(data, self.NEWFILE_CONTENTS) |
---|
1968 | @@ -1485,7 +1630,7 @@ |
---|
1969 | |
---|
1970 | def test_POST_upload_no_link_mutable_toobig(self): |
---|
1971 | d = self.shouldFail2(error.Error, |
---|
1972 | - "test_POST_upload_no_link_mutable_toobig", |
---|
1973 | + "POST_upload_no_link_mutable_toobig", |
---|
1974 | "413 Request Entity Too Large", |
---|
1975 | "SDMF is limited to one segment, and 10001 > 10000", |
---|
1976 | self.POST, |
---|
1977 | @@ -1496,10 +1641,11 @@ |
---|
1978 | |
---|
1979 | def test_POST_upload_mutable(self): |
---|
1980 | # this creates a mutable file |
---|
1981 | - d = self.POST(self.public_url + "/foo", t="upload", mutable="true", |
---|
1982 | - file=("new.txt", self.NEWFILE_CONTENTS)) |
---|
1983 | + d = self.shouldSucceed("POST_upload_mutable", http.OK, self.POST, |
---|
1984 | + self.public_url + "/foo", t="upload", mutable="true", |
---|
1985 | + file=("new.txt", self.NEWFILE_CONTENTS)) |
---|
1986 | fn = self._foo_node |
---|
1987 | - d.addCallback(self.failUnlessURIMatchesChild, fn, u"new.txt") |
---|
1988 | + d.addCallback(self.failUnlessURIMatchesRWChild, fn, u"new.txt") |
---|
1989 | d.addCallback(lambda res: |
---|
1990 | self.failUnlessMutableChildContentsAre(fn, u"new.txt", |
---|
1991 | self.NEWFILE_CONTENTS)) |
---|
1992 | @@ -1515,10 +1661,11 @@ |
---|
1993 | # now upload it again and make sure that the URI doesn't change |
---|
1994 | NEWER_CONTENTS = self.NEWFILE_CONTENTS + "newer\n" |
---|
1995 | d.addCallback(lambda res: |
---|
1996 | - self.POST(self.public_url + "/foo", t="upload", |
---|
1997 | - mutable="true", |
---|
1998 | - file=("new.txt", NEWER_CONTENTS))) |
---|
1999 | - d.addCallback(self.failUnlessURIMatchesChild, fn, u"new.txt") |
---|
2000 | + self.shouldSucceed("POST_upload_mutable-again", http.OK, self.POST, |
---|
2001 | + self.public_url + "/foo", t="upload", |
---|
2002 | + mutable="true", |
---|
2003 | + file=("new.txt", NEWER_CONTENTS))) |
---|
2004 | + d.addCallback(self.failUnlessURIMatchesRWChild, fn, u"new.txt") |
---|
2005 | d.addCallback(lambda res: |
---|
2006 | self.failUnlessMutableChildContentsAre(fn, u"new.txt", |
---|
2007 | NEWER_CONTENTS)) |
---|
2008 | @@ -1533,8 +1680,9 @@ |
---|
2009 | # upload a second time, using PUT instead of POST |
---|
2010 | NEW2_CONTENTS = NEWER_CONTENTS + "overwrite with PUT\n" |
---|
2011 | d.addCallback(lambda res: |
---|
2012 | - self.PUT(self.public_url + "/foo/new.txt", NEW2_CONTENTS)) |
---|
2013 | - d.addCallback(self.failUnlessURIMatchesChild, fn, u"new.txt") |
---|
2014 | + self.shouldSucceed("POST_upload_mutable-again-with-PUT", http.OK, self.PUT, |
---|
2015 | + self.public_url + "/foo/new.txt", NEW2_CONTENTS)) |
---|
2016 | + d.addCallback(self.failUnlessURIMatchesRWChild, fn, u"new.txt") |
---|
2017 | d.addCallback(lambda res: |
---|
2018 | self.failUnlessMutableChildContentsAre(fn, u"new.txt", |
---|
2019 | NEW2_CONTENTS)) |
---|
2020 | @@ -1543,8 +1691,8 @@ |
---|
2021 | # slightly differently |
---|
2022 | |
---|
2023 | d.addCallback(lambda res: |
---|
2024 | - self.GET(self.public_url + "/foo/", |
---|
2025 | - followRedirect=True)) |
---|
2026 | + self.shouldSucceedGET(self.public_url + "/foo/", |
---|
2027 | + followRedirect=True)) |
---|
2028 | def _check_page(res): |
---|
2029 | # TODO: assert more about the contents |
---|
2030 | self.failUnless("SSK" in res) |
---|
2031 | @@ -1561,8 +1709,8 @@ |
---|
2032 | |
---|
2033 | # look at the JSON form of the enclosing directory |
---|
2034 | d.addCallback(lambda res: |
---|
2035 | - self.GET(self.public_url + "/foo/?t=json", |
---|
2036 | - followRedirect=True)) |
---|
2037 | + self.shouldSucceedGET(self.public_url + "/foo/?t=json", |
---|
2038 | + followRedirect=True)) |
---|
2039 | def _check_page_json(res): |
---|
2040 | parsed = simplejson.loads(res) |
---|
2041 | self.failUnlessEqual(parsed[0], "dirnode") |
---|
2042 | @@ -1580,7 +1728,7 @@ |
---|
2043 | |
---|
2044 | # and the JSON form of the file |
---|
2045 | d.addCallback(lambda res: |
---|
2046 | - self.GET(self.public_url + "/foo/new.txt?t=json")) |
---|
2047 | + self.shouldSucceedGET(self.public_url + "/foo/new.txt?t=json")) |
---|
2048 | def _check_file_json(res): |
---|
2049 | parsed = simplejson.loads(res) |
---|
2050 | self.failUnlessEqual(parsed[0], "filenode") |
---|
2051 | @@ -1592,10 +1740,10 @@ |
---|
2052 | |
---|
2053 | # and look at t=uri and t=readonly-uri |
---|
2054 | d.addCallback(lambda res: |
---|
2055 | - self.GET(self.public_url + "/foo/new.txt?t=uri")) |
---|
2056 | + self.shouldSucceedGET(self.public_url + "/foo/new.txt?t=uri")) |
---|
2057 | d.addCallback(lambda res: self.failUnlessEqual(res, self._mutable_uri)) |
---|
2058 | d.addCallback(lambda res: |
---|
2059 | - self.GET(self.public_url + "/foo/new.txt?t=readonly-uri")) |
---|
2060 | + self.shouldSucceedGET(self.public_url + "/foo/new.txt?t=readonly-uri")) |
---|
2061 | def _check_ro_uri(res): |
---|
2062 | ro_uri = unicode(self._mutable_node.get_readonly().to_string()) |
---|
2063 | self.failUnlessEqual(res, ro_uri) |
---|
2064 | @@ -1603,15 +1751,15 @@ |
---|
2065 | |
---|
2066 | # make sure we can get to it from /uri/URI |
---|
2067 | d.addCallback(lambda res: |
---|
2068 | - self.GET("/uri/%s" % urllib.quote(self._mutable_uri))) |
---|
2069 | + self.shouldSucceedGET("/uri/%s" % urllib.quote(self._mutable_uri))) |
---|
2070 | d.addCallback(lambda res: |
---|
2071 | self.failUnlessEqual(res, NEW2_CONTENTS)) |
---|
2072 | |
---|
2073 | # and that HEAD computes the size correctly |
---|
2074 | d.addCallback(lambda res: |
---|
2075 | - self.HEAD(self.public_url + "/foo/new.txt", |
---|
2076 | - return_response=True)) |
---|
2077 | - def _got_headers((res, status, headers)): |
---|
2078 | + self.shouldSucceedHEAD(self.public_url + "/foo/new.txt", |
---|
2079 | + return_response=True)) |
---|
2080 | + def _got_headers((res, statuscode, headers)): |
---|
2081 | self.failUnlessEqual(res, "") |
---|
2082 | self.failUnlessEqual(headers["content-length"][0], |
---|
2083 | str(len(NEW2_CONTENTS))) |
---|
2084 | @@ -1621,7 +1769,7 @@ |
---|
2085 | # make sure that size errors are displayed correctly for overwrite |
---|
2086 | d.addCallback(lambda res: |
---|
2087 | self.shouldFail2(error.Error, |
---|
2088 | - "test_POST_upload_mutable-toobig", |
---|
2089 | + "POST_upload_mutable-toobig", |
---|
2090 | "413 Request Entity Too Large", |
---|
2091 | "SDMF is limited to one segment, and 10001 > 10000", |
---|
2092 | self.POST, |
---|
2093 | @@ -1636,7 +1784,7 @@ |
---|
2094 | |
---|
2095 | def test_POST_upload_mutable_toobig(self): |
---|
2096 | d = self.shouldFail2(error.Error, |
---|
2097 | - "test_POST_upload_mutable_toobig", |
---|
2098 | + "POST_upload_mutable_toobig", |
---|
2099 | "413 Request Entity Too Large", |
---|
2100 | "SDMF is limited to one segment, and 10001 > 10000", |
---|
2101 | self.POST, |
---|
2102 | @@ -1660,19 +1808,21 @@ |
---|
2103 | return f |
---|
2104 | |
---|
2105 | def test_POST_upload_replace(self): |
---|
2106 | - d = self.POST(self.public_url + "/foo", t="upload", |
---|
2107 | - file=("bar.txt", self.NEWFILE_CONTENTS)) |
---|
2108 | + d = self.shouldSucceed("POST_upload_replace", http.OK, self.POST, |
---|
2109 | + self.public_url + "/foo", t="upload", |
---|
2110 | + file=("bar.txt", self.NEWFILE_CONTENTS)) |
---|
2111 | fn = self._foo_node |
---|
2112 | - d.addCallback(self.failUnlessURIMatchesChild, fn, u"bar.txt") |
---|
2113 | + d.addCallback(self.failUnlessURIMatchesROChild, fn, u"bar.txt") |
---|
2114 | d.addCallback(lambda res: |
---|
2115 | self.failUnlessChildContentsAre(fn, u"bar.txt", |
---|
2116 | self.NEWFILE_CONTENTS)) |
---|
2117 | return d |
---|
2118 | |
---|
2119 | def test_POST_upload_no_replace_ok(self): |
---|
2120 | - d = self.POST(self.public_url + "/foo?replace=false", t="upload", |
---|
2121 | - file=("new.txt", self.NEWFILE_CONTENTS)) |
---|
2122 | - d.addCallback(lambda res: self.GET(self.public_url + "/foo/new.txt")) |
---|
2123 | + d = self.shouldSucceed("POST_upload_no_replace_ok", http.OK, self.POST, |
---|
2124 | + self.public_url + "/foo?replace=false", t="upload", |
---|
2125 | + file=("new.txt", self.NEWFILE_CONTENTS)) |
---|
2126 | + d.addCallback(lambda res: self.shouldSucceedGET(self.public_url + "/foo/new.txt")) |
---|
2127 | d.addCallback(lambda res: self.failUnlessEqual(res, |
---|
2128 | self.NEWFILE_CONTENTS)) |
---|
2129 | return d |
---|
2130 | @@ -1685,7 +1835,7 @@ |
---|
2131 | "409 Conflict", |
---|
2132 | "There was already a child by that name, and you asked me " |
---|
2133 | "to not replace it") |
---|
2134 | - d.addCallback(lambda res: self.GET(self.public_url + "/foo/bar.txt")) |
---|
2135 | + d.addCallback(lambda res: self.shouldSucceedGET(self.public_url + "/foo/bar.txt")) |
---|
2136 | d.addCallback(self.failUnlessIsBarDotTxt) |
---|
2137 | return d |
---|
2138 | |
---|
2139 | @@ -1696,7 +1846,7 @@ |
---|
2140 | "409 Conflict", |
---|
2141 | "There was already a child by that name, and you asked me " |
---|
2142 | "to not replace it") |
---|
2143 | - d.addCallback(lambda res: self.GET(self.public_url + "/foo/bar.txt")) |
---|
2144 | + d.addCallback(lambda res: self.shouldSucceedGET(self.public_url + "/foo/bar.txt")) |
---|
2145 | d.addCallback(self.failUnlessIsBarDotTxt) |
---|
2146 | return d |
---|
2147 | |
---|
2148 | @@ -1712,9 +1862,10 @@ |
---|
2149 | |
---|
2150 | def test_POST_upload_named(self): |
---|
2151 | fn = self._foo_node |
---|
2152 | - d = self.POST(self.public_url + "/foo", t="upload", |
---|
2153 | - name="new.txt", file=self.NEWFILE_CONTENTS) |
---|
2154 | - d.addCallback(self.failUnlessURIMatchesChild, fn, u"new.txt") |
---|
2155 | + d = self.shouldSucceed("POST_upload_named", http.OK, self.POST, |
---|
2156 | + self.public_url + "/foo", t="upload", |
---|
2157 | + name="new.txt", file=self.NEWFILE_CONTENTS) |
---|
2158 | + d.addCallback(self.failUnlessURIMatchesROChild, fn, u"new.txt") |
---|
2159 | d.addCallback(lambda res: |
---|
2160 | self.failUnlessChildContentsAre(fn, u"new.txt", |
---|
2161 | self.NEWFILE_CONTENTS)) |
---|
2162 | @@ -1724,7 +1875,7 @@ |
---|
2163 | d = self.POST(self.public_url + "/foo", t="upload", |
---|
2164 | name="slashes/are/bad.txt", file=self.NEWFILE_CONTENTS) |
---|
2165 | d.addBoth(self.shouldFail, error.Error, |
---|
2166 | - "test_POST_upload_named_badfilename", |
---|
2167 | + "POST_upload_named_badfilename", |
---|
2168 | "400 Bad Request", |
---|
2169 | "name= may not contain a slash", |
---|
2170 | ) |
---|
2171 | @@ -1738,7 +1889,8 @@ |
---|
2172 | |
---|
2173 | def test_POST_FILEURL_check(self): |
---|
2174 | bar_url = self.public_url + "/foo/bar.txt" |
---|
2175 | - d = self.POST(bar_url, t="check") |
---|
2176 | + d = self.shouldSucceed("POST_FILEURL_check-1", http.OK, self.POST, |
---|
2177 | + bar_url, t="check") |
---|
2178 | def _check(res): |
---|
2179 | self.failUnless("Healthy :" in res) |
---|
2180 | d.addCallback(_check) |
---|
2181 | @@ -1747,13 +1899,14 @@ |
---|
2182 | self.failUnlessEqual(statuscode, str(http.FOUND)) |
---|
2183 | self.failUnlessEqual(target, redir_url) |
---|
2184 | d.addCallback(lambda res: |
---|
2185 | - self.shouldRedirect2("test_POST_FILEURL_check", |
---|
2186 | + self.shouldRedirect2("POST_FILEURL_check-2", |
---|
2187 | _check2, |
---|
2188 | self.POST, bar_url, |
---|
2189 | t="check", |
---|
2190 | when_done=redir_url)) |
---|
2191 | d.addCallback(lambda res: |
---|
2192 | - self.POST(bar_url, t="check", return_to=redir_url)) |
---|
2193 | + self.shouldSucceed("POST_FILEURL_check-3", http.OK, self.POST, |
---|
2194 | + bar_url, t="check", return_to=redir_url)) |
---|
2195 | def _check3(res): |
---|
2196 | self.failUnless("Healthy :" in res) |
---|
2197 | self.failUnless("Return to file" in res) |
---|
2198 | @@ -1761,7 +1914,8 @@ |
---|
2199 | d.addCallback(_check3) |
---|
2200 | |
---|
2201 | d.addCallback(lambda res: |
---|
2202 | - self.POST(bar_url, t="check", output="JSON")) |
---|
2203 | + self.shouldSucceed("POST_FILEURL_check-4", http.OK, self.POST, |
---|
2204 | + bar_url, t="check", output="JSON")) |
---|
2205 | def _check_json(res): |
---|
2206 | data = simplejson.loads(res) |
---|
2207 | self.failUnless("storage-index" in data) |
---|
2208 | @@ -1772,7 +1926,8 @@ |
---|
2209 | |
---|
2210 | def test_POST_FILEURL_check_and_repair(self): |
---|
2211 | bar_url = self.public_url + "/foo/bar.txt" |
---|
2212 | - d = self.POST(bar_url, t="check", repair="true") |
---|
2213 | + d = self.shouldSucceed("POST_FILEURL_check_and_repair-1", http.OK, self.POST, |
---|
2214 | + bar_url, t="check", repair="true") |
---|
2215 | def _check(res): |
---|
2216 | self.failUnless("Healthy :" in res) |
---|
2217 | d.addCallback(_check) |
---|
2218 | @@ -1781,13 +1936,14 @@ |
---|
2219 | self.failUnlessEqual(statuscode, str(http.FOUND)) |
---|
2220 | self.failUnlessEqual(target, redir_url) |
---|
2221 | d.addCallback(lambda res: |
---|
2222 | - self.shouldRedirect2("test_POST_FILEURL_check_and_repair", |
---|
2223 | + self.shouldRedirect2("POST_FILEURL_check_and_repair-2", |
---|
2224 | _check2, |
---|
2225 | self.POST, bar_url, |
---|
2226 | t="check", repair="true", |
---|
2227 | when_done=redir_url)) |
---|
2228 | d.addCallback(lambda res: |
---|
2229 | - self.POST(bar_url, t="check", return_to=redir_url)) |
---|
2230 | + self.shouldSucceed("POST_FILEURL_check_and_repair-3", http.OK, self.POST, |
---|
2231 | + bar_url, t="check", return_to=redir_url)) |
---|
2232 | def _check3(res): |
---|
2233 | self.failUnless("Healthy :" in res) |
---|
2234 | self.failUnless("Return to file" in res) |
---|
2235 | @@ -1797,7 +1953,8 @@ |
---|
2236 | |
---|
2237 | def test_POST_DIRURL_check(self): |
---|
2238 | foo_url = self.public_url + "/foo/" |
---|
2239 | - d = self.POST(foo_url, t="check") |
---|
2240 | + d = self.shouldSucceed("POST_DIRURL_check-1", http.OK, self.POST, |
---|
2241 | + foo_url, t="check") |
---|
2242 | def _check(res): |
---|
2243 | self.failUnless("Healthy :" in res, res) |
---|
2244 | d.addCallback(_check) |
---|
2245 | @@ -1806,13 +1963,14 @@ |
---|
2246 | self.failUnlessEqual(statuscode, str(http.FOUND)) |
---|
2247 | self.failUnlessEqual(target, redir_url) |
---|
2248 | d.addCallback(lambda res: |
---|
2249 | - self.shouldRedirect2("test_POST_DIRURL_check", |
---|
2250 | + self.shouldRedirect2("POST_DIRURL_check-2", |
---|
2251 | _check2, |
---|
2252 | self.POST, foo_url, |
---|
2253 | t="check", |
---|
2254 | when_done=redir_url)) |
---|
2255 | d.addCallback(lambda res: |
---|
2256 | - self.POST(foo_url, t="check", return_to=redir_url)) |
---|
2257 | + self.shouldSucceed("POST_DIRURL_check-3", http.OK, self.POST, |
---|
2258 | + foo_url, t="check", return_to=redir_url)) |
---|
2259 | def _check3(res): |
---|
2260 | self.failUnless("Healthy :" in res, res) |
---|
2261 | self.failUnless("Return to file/directory" in res) |
---|
2262 | @@ -1820,7 +1978,8 @@ |
---|
2263 | d.addCallback(_check3) |
---|
2264 | |
---|
2265 | d.addCallback(lambda res: |
---|
2266 | - self.POST(foo_url, t="check", output="JSON")) |
---|
2267 | + self.shouldSucceed("POST_DIRURL_check-4", http.OK, self.POST, |
---|
2268 | + foo_url, t="check", output="JSON")) |
---|
2269 | def _check_json(res): |
---|
2270 | data = simplejson.loads(res) |
---|
2271 | self.failUnless("storage-index" in data) |
---|
2272 | @@ -1831,7 +1990,8 @@ |
---|
2273 | |
---|
2274 | def test_POST_DIRURL_check_and_repair(self): |
---|
2275 | foo_url = self.public_url + "/foo/" |
---|
2276 | - d = self.POST(foo_url, t="check", repair="true") |
---|
2277 | + d = self.shouldSucceed("POST_DIRURL_check_and_repair-1", http.OK, self.POST, |
---|
2278 | + foo_url, t="check", repair="true") |
---|
2279 | def _check(res): |
---|
2280 | self.failUnless("Healthy :" in res, res) |
---|
2281 | d.addCallback(_check) |
---|
2282 | @@ -1840,13 +2000,14 @@ |
---|
2283 | self.failUnlessEqual(statuscode, str(http.FOUND)) |
---|
2284 | self.failUnlessEqual(target, redir_url) |
---|
2285 | d.addCallback(lambda res: |
---|
2286 | - self.shouldRedirect2("test_POST_DIRURL_check_and_repair", |
---|
2287 | + self.shouldRedirect2("POST_DIRURL_check_and_repair-2", |
---|
2288 | _check2, |
---|
2289 | self.POST, foo_url, |
---|
2290 | t="check", repair="true", |
---|
2291 | when_done=redir_url)) |
---|
2292 | d.addCallback(lambda res: |
---|
2293 | - self.POST(foo_url, t="check", return_to=redir_url)) |
---|
2294 | + self.shouldSucceed("POST_DIRURL_check_and_repair-3", http.OK, self.POST, |
---|
2295 | + foo_url, t="check", return_to=redir_url)) |
---|
2296 | def _check3(res): |
---|
2297 | self.failUnless("Healthy :" in res) |
---|
2298 | self.failUnless("Return to file/directory" in res) |
---|
2299 | @@ -1857,7 +2018,7 @@ |
---|
2300 | def wait_for_operation(self, ignored, ophandle): |
---|
2301 | url = "/operations/" + ophandle |
---|
2302 | url += "?t=status&output=JSON" |
---|
2303 | - d = self.GET(url) |
---|
2304 | + d = self.shouldSucceedGET(url) |
---|
2305 | def _got(res): |
---|
2306 | data = simplejson.loads(res) |
---|
2307 | if not data["finished"]: |
---|
2308 | @@ -1873,7 +2034,7 @@ |
---|
2309 | url += "?t=status" |
---|
2310 | if output: |
---|
2311 | url += "&output=" + output |
---|
2312 | - d = self.GET(url) |
---|
2313 | + d = self.shouldSucceedGET(url) |
---|
2314 | def _got(res): |
---|
2315 | if output and output.lower() == "json": |
---|
2316 | return simplejson.loads(res) |
---|
2317 | @@ -1883,7 +2044,7 @@ |
---|
2318 | |
---|
2319 | def test_POST_DIRURL_deepcheck_no_ophandle(self): |
---|
2320 | d = self.shouldFail2(error.Error, |
---|
2321 | - "test_POST_DIRURL_deepcheck_no_ophandle", |
---|
2322 | + "POST_DIRURL_deepcheck_no_ophandle", |
---|
2323 | "400 Bad Request", |
---|
2324 | "slow operation requires ophandle=", |
---|
2325 | self.POST, self.public_url, t="start-deep-check") |
---|
2326 | @@ -1893,7 +2054,7 @@ |
---|
2327 | def _check_redirect(statuscode, target): |
---|
2328 | self.failUnlessEqual(statuscode, str(http.FOUND)) |
---|
2329 | self.failUnless(target.endswith("/operations/123")) |
---|
2330 | - d = self.shouldRedirect2("test_POST_DIRURL_deepcheck", _check_redirect, |
---|
2331 | + d = self.shouldRedirect2("POST_DIRURL_deepcheck", _check_redirect, |
---|
2332 | self.POST, self.public_url, |
---|
2333 | t="start-deep-check", ophandle="123") |
---|
2334 | d.addCallback(self.wait_for_operation, "123") |
---|
2335 | @@ -1909,7 +2070,7 @@ |
---|
2336 | d.addCallback(_check_html) |
---|
2337 | |
---|
2338 | d.addCallback(lambda res: |
---|
2339 | - self.GET("/operations/123/")) |
---|
2340 | + self.shouldSucceedGET("/operations/123/")) |
---|
2341 | d.addCallback(_check_html) # should be the same as without the slash |
---|
2342 | |
---|
2343 | d.addCallback(lambda res: |
---|
2344 | @@ -1920,7 +2081,7 @@ |
---|
2345 | foo_si = self._foo_node.get_storage_index() |
---|
2346 | foo_si_s = base32.b2a(foo_si) |
---|
2347 | d.addCallback(lambda res: |
---|
2348 | - self.GET("/operations/123/%s?output=JSON" % foo_si_s)) |
---|
2349 | + self.shouldSucceedGET("/operations/123/%s?output=JSON" % foo_si_s)) |
---|
2350 | def _check_foo_json(res): |
---|
2351 | data = simplejson.loads(res) |
---|
2352 | self.failUnlessEqual(data["storage-index"], foo_si_s) |
---|
2353 | @@ -1929,8 +2090,9 @@ |
---|
2354 | return d |
---|
2355 | |
---|
2356 | def test_POST_DIRURL_deepcheck_and_repair(self): |
---|
2357 | - d = self.POST(self.public_url, t="start-deep-check", repair="true", |
---|
2358 | - ophandle="124", output="json", followRedirect=True) |
---|
2359 | + d = self.shouldSucceed("POST_DIRURL_deepcheck_and_repair", http.OK, self.POST, |
---|
2360 | + self.public_url, t="start-deep-check", repair="true", |
---|
2361 | + ophandle="124", output="json", followRedirect=True) |
---|
2362 | d.addCallback(self.wait_for_operation, "124") |
---|
2363 | def _check_json(data): |
---|
2364 | self.failUnlessEqual(data["finished"], True) |
---|
2365 | @@ -1971,45 +2133,47 @@ |
---|
2366 | return d |
---|
2367 | |
---|
2368 | def test_POST_mkdir(self): # return value? |
---|
2369 | - d = self.POST(self.public_url + "/foo", t="mkdir", name="newdir") |
---|
2370 | + d = self.shouldSucceed("POST_mkdir", http.OK, self.POST, |
---|
2371 | + self.public_url + "/foo", t="mkdir", name="newdir") |
---|
2372 | d.addCallback(lambda res: self._foo_node.get(u"newdir")) |
---|
2373 | d.addCallback(self.failUnlessNodeKeysAre, []) |
---|
2374 | return d |
---|
2375 | |
---|
2376 | def test_POST_mkdir_initial_children(self): |
---|
2377 | - newkids, filecap1, ign, ign, ign = self._create_initial_children() |
---|
2378 | - d = self.POST2(self.public_url + |
---|
2379 | - "/foo?t=mkdir-with-children&name=newdir", |
---|
2380 | - simplejson.dumps(newkids)) |
---|
2381 | + (newkids, caps) = self._create_initial_children() |
---|
2382 | + d = self.shouldSucceed("POST_mkdir_initial_children", http.OK, self.POST2, |
---|
2383 | + self.public_url + "/foo?t=mkdir-with-children&name=newdir", |
---|
2384 | + simplejson.dumps(newkids)) |
---|
2385 | d.addCallback(lambda res: |
---|
2386 | self.failUnlessNodeHasChild(self._foo_node, u"newdir")) |
---|
2387 | d.addCallback(lambda res: self._foo_node.get(u"newdir")) |
---|
2388 | d.addCallback(self.failUnlessNodeKeysAre, newkids.keys()) |
---|
2389 | d.addCallback(lambda res: self._foo_node.get(u"newdir")) |
---|
2390 | - d.addCallback(self.failUnlessChildURIIs, u"child-imm", filecap1) |
---|
2391 | + d.addCallback(self.failUnlessROChildURIIs, u"child-imm", caps['filecap1']) |
---|
2392 | return d |
---|
2393 | |
---|
2394 | def test_POST_mkdir_immutable(self): |
---|
2395 | - (newkids, filecap1, immdircap) = self._create_immutable_children() |
---|
2396 | - d = self.POST2(self.public_url + |
---|
2397 | - "/foo?t=mkdir-immutable&name=newdir", |
---|
2398 | - simplejson.dumps(newkids)) |
---|
2399 | + (newkids, caps) = self._create_immutable_children() |
---|
2400 | + d = self.shouldSucceed("POST_mkdir_immutable", http.OK, self.POST2, |
---|
2401 | + self.public_url + "/foo?t=mkdir-immutable&name=newdir", |
---|
2402 | + simplejson.dumps(newkids)) |
---|
2403 | d.addCallback(lambda res: |
---|
2404 | self.failUnlessNodeHasChild(self._foo_node, u"newdir")) |
---|
2405 | d.addCallback(lambda res: self._foo_node.get(u"newdir")) |
---|
2406 | d.addCallback(self.failUnlessNodeKeysAre, newkids.keys()) |
---|
2407 | d.addCallback(lambda res: self._foo_node.get(u"newdir")) |
---|
2408 | - d.addCallback(self.failUnlessChildURIIs, u"child-imm", filecap1) |
---|
2409 | + d.addCallback(self.failUnlessROChildURIIs, u"child-imm", caps['filecap1']) |
---|
2410 | + d.addCallback(lambda res: self._foo_node.get(u"newdir")) |
---|
2411 | + d.addCallback(self.failUnlessROChildURIIs, u"unknownchild-imm", caps['unknown_immcap']) |
---|
2412 | d.addCallback(lambda res: self._foo_node.get(u"newdir")) |
---|
2413 | - d.addCallback(self.failUnlessChildURIIs, u"dirchild-imm", immdircap) |
---|
2414 | + d.addCallback(self.failUnlessROChildURIIs, u"dirchild-imm", caps['immdircap']) |
---|
2415 | return d |
---|
2416 | |
---|
2417 | def test_POST_mkdir_immutable_bad(self): |
---|
2418 | - (newkids, filecap1, filecap2, filecap3, |
---|
2419 | - dircap) = self._create_initial_children() |
---|
2420 | - d = self.shouldFail2(error.Error, "test_POST_mkdir_immutable_bad", |
---|
2421 | + (newkids, caps) = self._create_initial_children() |
---|
2422 | + d = self.shouldFail2(error.Error, "POST_mkdir_immutable_bad", |
---|
2423 | "400 Bad Request", |
---|
2424 | - "a mkdir-immutable operation was given a child that was not itself immutable", |
---|
2425 | + "needed to be immutable but was not", |
---|
2426 | self.POST2, |
---|
2427 | self.public_url + |
---|
2428 | "/foo?t=mkdir-immutable&name=newdir", |
---|
2429 | @@ -2017,7 +2181,8 @@ |
---|
2430 | return d |
---|
2431 | |
---|
2432 | def test_POST_mkdir_2(self): |
---|
2433 | - d = self.POST(self.public_url + "/foo/newdir?t=mkdir", "") |
---|
2434 | + d = self.shouldSucceed("POST_mkdir_2", http.OK, self.POST, |
---|
2435 | + self.public_url + "/foo/newdir?t=mkdir", "") |
---|
2436 | d.addCallback(lambda res: |
---|
2437 | self.failUnlessNodeHasChild(self._foo_node, u"newdir")) |
---|
2438 | d.addCallback(lambda res: self._foo_node.get(u"newdir")) |
---|
2439 | @@ -2025,7 +2190,8 @@ |
---|
2440 | return d |
---|
2441 | |
---|
2442 | def test_POST_mkdirs_2(self): |
---|
2443 | - d = self.POST(self.public_url + "/foo/bardir/newdir?t=mkdir", "") |
---|
2444 | + d = self.shouldSucceed("POST_mkdirs_2", http.OK, self.POST, |
---|
2445 | + self.public_url + "/foo/bardir/newdir?t=mkdir", "") |
---|
2446 | d.addCallback(lambda res: |
---|
2447 | self.failUnlessNodeHasChild(self._foo_node, u"bardir")) |
---|
2448 | d.addCallback(lambda res: self._foo_node.get(u"bardir")) |
---|
2449 | @@ -2034,7 +2200,8 @@ |
---|
2450 | return d |
---|
2451 | |
---|
2452 | def test_POST_mkdir_no_parentdir_noredirect(self): |
---|
2453 | - d = self.POST("/uri?t=mkdir") |
---|
2454 | + d = self.shouldSucceed("POST_mkdir_no_parentdir_noredirect", http.OK, self.POST, |
---|
2455 | + "/uri?t=mkdir") |
---|
2456 | def _after_mkdir(res): |
---|
2457 | uri.DirectoryURI.init_from_string(res) |
---|
2458 | d.addCallback(_after_mkdir) |
---|
2459 | @@ -2049,21 +2216,43 @@ |
---|
2460 | d.addCallback(_check_target) |
---|
2461 | return d |
---|
2462 | |
---|
2463 | + def _make_readonly(self, u): |
---|
2464 | + ro_uri = uri.from_string(u).get_readonly() |
---|
2465 | + if ro_uri is None: |
---|
2466 | + return None |
---|
2467 | + return ro_uri.to_string() |
---|
2468 | + |
---|
2469 | def _create_initial_children(self): |
---|
2470 | contents, n, filecap1 = self.makefile(12) |
---|
2471 | md1 = {"metakey1": "metavalue1"} |
---|
2472 | filecap2 = make_mutable_file_uri() |
---|
2473 | node3 = self.s.create_node_from_uri(make_mutable_file_uri()) |
---|
2474 | filecap3 = node3.get_readonly_uri() |
---|
2475 | + unknown_rwcap = "lafs://from_the_future" |
---|
2476 | + unknown_rocap = "ro.lafs://readonly_from_the_future" |
---|
2477 | + unknown_immcap = "imm.lafs://immutable_from_the_future" |
---|
2478 | node4 = self.s.create_node_from_uri(make_mutable_file_uri()) |
---|
2479 | dircap = DirectoryNode(node4, None, None).get_uri() |
---|
2480 | - newkids = {u"child-imm": ["filenode", {"ro_uri": filecap1, |
---|
2481 | - "metadata": md1, }], |
---|
2482 | - u"child-mutable": ["filenode", {"rw_uri": filecap2}], |
---|
2483 | + newkids = {u"child-imm": ["filenode", {"rw_uri": filecap1, |
---|
2484 | + "ro_uri": self._make_readonly(filecap1), |
---|
2485 | + "metadata": md1, }], |
---|
2486 | + u"child-mutable": ["filenode", {"rw_uri": filecap2, |
---|
2487 | + "ro_uri": self._make_readonly(filecap2)}], |
---|
2488 | u"child-mutable-ro": ["filenode", {"ro_uri": filecap3}], |
---|
2489 | - u"dirchild": ["dirnode", {"rw_uri": dircap}], |
---|
2490 | + u"unknownchild-rw": ["unknown", {"rw_uri": unknown_rwcap, |
---|
2491 | + "ro_uri": unknown_rocap}], |
---|
2492 | + u"unknownchild-ro": ["unknown", {"ro_uri": unknown_rocap}], |
---|
2493 | + u"unknownchild-imm": ["unknown", {"ro_uri": unknown_immcap}], |
---|
2494 | + u"dirchild": ["dirnode", {"rw_uri": dircap, |
---|
2495 | + "ro_uri": self._make_readonly(dircap)}], |
---|
2496 | } |
---|
2497 | - return newkids, filecap1, filecap2, filecap3, dircap |
---|
2498 | + return newkids, {'filecap1': filecap1, |
---|
2499 | + 'filecap2': filecap2, |
---|
2500 | + 'filecap3': filecap3, |
---|
2501 | + 'unknown_rwcap': unknown_rwcap, |
---|
2502 | + 'unknown_rocap': unknown_rocap, |
---|
2503 | + 'unknown_immcap': unknown_immcap, |
---|
2504 | + 'dircap': dircap} |
---|
2505 | |
---|
2506 | def _create_immutable_children(self): |
---|
2507 | contents, n, filecap1 = self.makefile(12) |
---|
2508 | @@ -2071,31 +2260,46 @@ |
---|
2509 | tnode = create_chk_filenode("immutable directory contents\n"*10) |
---|
2510 | dnode = DirectoryNode(tnode, None, None) |
---|
2511 | assert not dnode.is_mutable() |
---|
2512 | + unknown_immcap = "imm.lafs://immutable_from_the_future" |
---|
2513 | immdircap = dnode.get_uri() |
---|
2514 | - newkids = {u"child-imm": ["filenode", {"ro_uri": filecap1, |
---|
2515 | - "metadata": md1, }], |
---|
2516 | - u"dirchild-imm": ["dirnode", {"ro_uri": immdircap}], |
---|
2517 | + newkids = {u"child-imm": ["filenode", {"ro_uri": filecap1, |
---|
2518 | + "metadata": md1, }], |
---|
2519 | + u"unknownchild-imm": ["unknown", {"ro_uri": unknown_immcap}], |
---|
2520 | + u"dirchild-imm": ["dirnode", {"ro_uri": immdircap}], |
---|
2521 | } |
---|
2522 | - return newkids, filecap1, immdircap |
---|
2523 | + return newkids, {'filecap1': filecap1, |
---|
2524 | + 'unknown_immcap': unknown_immcap, |
---|
2525 | + 'immdircap': immdircap} |
---|
2526 | |
---|
2527 | def test_POST_mkdir_no_parentdir_initial_children(self): |
---|
2528 | - (newkids, filecap1, filecap2, filecap3, |
---|
2529 | - dircap) = self._create_initial_children() |
---|
2530 | - d = self.POST2("/uri?t=mkdir-with-children", simplejson.dumps(newkids)) |
---|
2531 | + (newkids, caps) = self._create_initial_children() |
---|
2532 | + d = self.shouldSucceed("POST_mkdir_no_parentdir_initial_children", http.OK, self.POST2, |
---|
2533 | + "/uri?t=mkdir-with-children", simplejson.dumps(newkids)) |
---|
2534 | def _after_mkdir(res): |
---|
2535 | self.failUnless(res.startswith("URI:DIR"), res) |
---|
2536 | n = self.s.create_node_from_uri(res) |
---|
2537 | d2 = self.failUnlessNodeKeysAre(n, newkids.keys()) |
---|
2538 | d2.addCallback(lambda ign: |
---|
2539 | - self.failUnlessChildURIIs(n, u"child-imm", filecap1)) |
---|
2540 | + self.failUnlessROChildURIIs(n, u"child-imm", |
---|
2541 | + caps['filecap1'])) |
---|
2542 | + d2.addCallback(lambda ign: |
---|
2543 | + self.failUnlessRWChildURIIs(n, u"child-mutable", |
---|
2544 | + caps['filecap2'])) |
---|
2545 | + d2.addCallback(lambda ign: |
---|
2546 | + self.failUnlessROChildURIIs(n, u"child-mutable-ro", |
---|
2547 | + caps['filecap3'])) |
---|
2548 | d2.addCallback(lambda ign: |
---|
2549 | - self.failUnlessChildURIIs(n, u"child-mutable", |
---|
2550 | - filecap2)) |
---|
2551 | + self.failUnlessRWChildURIIs(n, u"unknownchild-rw", |
---|
2552 | + caps['unknown_rwcap'])) |
---|
2553 | d2.addCallback(lambda ign: |
---|
2554 | - self.failUnlessChildURIIs(n, u"child-mutable-ro", |
---|
2555 | - filecap3)) |
---|
2556 | + self.failUnlessROChildURIIs(n, u"unknownchild-ro", |
---|
2557 | + caps['unknown_rocap'])) |
---|
2558 | d2.addCallback(lambda ign: |
---|
2559 | - self.failUnlessChildURIIs(n, u"dirchild", dircap)) |
---|
2560 | + self.failUnlessROChildURIIs(n, u"unknownchild-imm", |
---|
2561 | + caps['unknown_immcap'])) |
---|
2562 | + d2.addCallback(lambda ign: |
---|
2563 | + self.failUnlessRWChildURIIs(n, u"dirchild", |
---|
2564 | + caps['dircap'])) |
---|
2565 | return d2 |
---|
2566 | d.addCallback(_after_mkdir) |
---|
2567 | return d |
---|
2568 | @@ -2103,8 +2307,7 @@ |
---|
2569 | def test_POST_mkdir_no_parentdir_unexpected_children(self): |
---|
2570 | # the regular /uri?t=mkdir operation is specified to ignore its body. |
---|
2571 | # Only t=mkdir-with-children pays attention to it. |
---|
2572 | - (newkids, filecap1, filecap2, filecap3, |
---|
2573 | - dircap) = self._create_initial_children() |
---|
2574 | + (newkids, caps) = self._create_initial_children() |
---|
2575 | d = self.shouldHTTPError("POST t=mkdir unexpected children", |
---|
2576 | 400, "Bad Request", |
---|
2577 | "t=mkdir does not accept children=, " |
---|
2578 | @@ -2121,28 +2324,32 @@ |
---|
2579 | return d |
---|
2580 | |
---|
2581 | def test_POST_mkdir_no_parentdir_immutable(self): |
---|
2582 | - (newkids, filecap1, immdircap) = self._create_immutable_children() |
---|
2583 | - d = self.POST2("/uri?t=mkdir-immutable", simplejson.dumps(newkids)) |
---|
2584 | + (newkids, caps) = self._create_immutable_children() |
---|
2585 | + d = self.shouldSucceed("POST_mkdir_no_parentdir_immutable", http.OK, self.POST2, |
---|
2586 | + "/uri?t=mkdir-immutable", simplejson.dumps(newkids)) |
---|
2587 | def _after_mkdir(res): |
---|
2588 | self.failUnless(res.startswith("URI:DIR"), res) |
---|
2589 | n = self.s.create_node_from_uri(res) |
---|
2590 | d2 = self.failUnlessNodeKeysAre(n, newkids.keys()) |
---|
2591 | d2.addCallback(lambda ign: |
---|
2592 | - self.failUnlessChildURIIs(n, u"child-imm", filecap1)) |
---|
2593 | + self.failUnlessROChildURIIs(n, u"child-imm", |
---|
2594 | + caps['filecap1'])) |
---|
2595 | + d2.addCallback(lambda ign: |
---|
2596 | + self.failUnlessROChildURIIs(n, u"unknownchild-imm", |
---|
2597 | + caps['unknown_immcap'])) |
---|
2598 | d2.addCallback(lambda ign: |
---|
2599 | - self.failUnlessChildURIIs(n, u"dirchild-imm", |
---|
2600 | - immdircap)) |
---|
2601 | + self.failUnlessROChildURIIs(n, u"dirchild-imm", |
---|
2602 | + caps['immdircap'])) |
---|
2603 | return d2 |
---|
2604 | d.addCallback(_after_mkdir) |
---|
2605 | return d |
---|
2606 | |
---|
2607 | def test_POST_mkdir_no_parentdir_immutable_bad(self): |
---|
2608 | - (newkids, filecap1, filecap2, filecap3, |
---|
2609 | - dircap) = self._create_initial_children() |
---|
2610 | + (newkids, caps) = self._create_initial_children() |
---|
2611 | d = self.shouldFail2(error.Error, |
---|
2612 | - "test_POST_mkdir_no_parentdir_immutable_bad", |
---|
2613 | + "POST_mkdir_no_parentdir_immutable_bad", |
---|
2614 | "400 Bad Request", |
---|
2615 | - "a mkdir-immutable operation was given a child that was not itself immutable", |
---|
2616 | + "needed to be immutable but was not", |
---|
2617 | self.POST2, |
---|
2618 | "/uri?t=mkdir-immutable", |
---|
2619 | simplejson.dumps(newkids)) |
---|
2620 | @@ -2150,9 +2357,14 @@ |
---|
2621 | |
---|
2622 | def test_welcome_page_mkdir_button(self): |
---|
2623 | # Fetch the welcome page. |
---|
2624 | - d = self.GET("/") |
---|
2625 | + d = self.shouldSucceedGET("/") |
---|
2626 | def _after_get_welcome_page(res): |
---|
2627 | - MKDIR_BUTTON_RE=re.compile('<form action="([^"]*)" method="post".*?<input type="hidden" name="t" value="([^"]*)" /><input type="hidden" name="([^"]*)" value="([^"]*)" /><input type="submit" value="Create a directory" />', re.I) |
---|
2628 | + MKDIR_BUTTON_RE = re.compile( |
---|
2629 | + '<form action="([^"]*)" method="post".*?' |
---|
2630 | + '<input type="hidden" name="t" value="([^"]*)" />' |
---|
2631 | + '<input type="hidden" name="([^"]*)" value="([^"]*)" />' |
---|
2632 | + '<input type="submit" value="Create a directory" />', |
---|
2633 | + re.I) |
---|
2634 | mo = MKDIR_BUTTON_RE.search(res) |
---|
2635 | formaction = mo.group(1) |
---|
2636 | formt = mo.group(2) |
---|
2637 | @@ -2168,7 +2380,8 @@ |
---|
2638 | return d |
---|
2639 | |
---|
2640 | def test_POST_mkdir_replace(self): # return value? |
---|
2641 | - d = self.POST(self.public_url + "/foo", t="mkdir", name="sub") |
---|
2642 | + d = self.shouldSucceed("POST_mkdir_replace", http.OK, self.POST, |
---|
2643 | + self.public_url + "/foo", t="mkdir", name="sub") |
---|
2644 | d.addCallback(lambda res: self._foo_node.get(u"sub")) |
---|
2645 | d.addCallback(self.failUnlessNodeKeysAre, []) |
---|
2646 | return d |
---|
2647 | @@ -2250,9 +2463,9 @@ |
---|
2648 | |
---|
2649 | d = client.getPage(url, method="POST", postdata=reqbody) |
---|
2650 | def _then(res): |
---|
2651 | - self.failUnlessURIMatchesChild(newuri9, self._foo_node, u"atomic_added_1") |
---|
2652 | - self.failUnlessURIMatchesChild(newuri10, self._foo_node, u"atomic_added_2") |
---|
2653 | - self.failUnlessURIMatchesChild(newuri11, self._foo_node, u"atomic_added_3") |
---|
2654 | + self.failUnlessURIMatchesROChild(newuri9, self._foo_node, u"atomic_added_1") |
---|
2655 | + self.failUnlessURIMatchesROChild(newuri10, self._foo_node, u"atomic_added_2") |
---|
2656 | + self.failUnlessURIMatchesROChild(newuri11, self._foo_node, u"atomic_added_3") |
---|
2657 | |
---|
2658 | d.addCallback(_then) |
---|
2659 | d.addErrback(self.dump_error) |
---|
2660 | @@ -2260,8 +2473,9 @@ |
---|
2661 | |
---|
2662 | def test_POST_put_uri(self): |
---|
2663 | contents, n, newuri = self.makefile(8) |
---|
2664 | - d = self.POST(self.public_url + "/foo", t="uri", name="new.txt", uri=newuri) |
---|
2665 | - d.addCallback(self.failUnlessURIMatchesChild, self._foo_node, u"new.txt") |
---|
2666 | + d = self.shouldSucceed("POST_put_uri", http.OK, self.POST, |
---|
2667 | + self.public_url + "/foo", t="uri", name="new.txt", uri=newuri) |
---|
2668 | + d.addCallback(self.failUnlessURIMatchesROChild, self._foo_node, u"new.txt") |
---|
2669 | d.addCallback(lambda res: |
---|
2670 | self.failUnlessChildContentsAre(self._foo_node, u"new.txt", |
---|
2671 | contents)) |
---|
2672 | @@ -2269,8 +2483,9 @@ |
---|
2673 | |
---|
2674 | def test_POST_put_uri_replace(self): |
---|
2675 | contents, n, newuri = self.makefile(8) |
---|
2676 | - d = self.POST(self.public_url + "/foo", t="uri", name="bar.txt", uri=newuri) |
---|
2677 | - d.addCallback(self.failUnlessURIMatchesChild, self._foo_node, u"bar.txt") |
---|
2678 | + d = self.shouldSucceed("POST_put_uri_replace", http.OK, self.POST, |
---|
2679 | + self.public_url + "/foo", t="uri", name="bar.txt", uri=newuri) |
---|
2680 | + d.addCallback(self.failUnlessURIMatchesROChild, self._foo_node, u"bar.txt") |
---|
2681 | d.addCallback(lambda res: |
---|
2682 | self.failUnlessChildContentsAre(self._foo_node, u"bar.txt", |
---|
2683 | contents)) |
---|
2684 | @@ -2285,7 +2500,7 @@ |
---|
2685 | "409 Conflict", |
---|
2686 | "There was already a child by that name, and you asked me " |
---|
2687 | "to not replace it") |
---|
2688 | - d.addCallback(lambda res: self.GET(self.public_url + "/foo/bar.txt")) |
---|
2689 | + d.addCallback(lambda res: self.shouldSucceedGET(self.public_url + "/foo/bar.txt")) |
---|
2690 | d.addCallback(self.failUnlessIsBarDotTxt) |
---|
2691 | return d |
---|
2692 | |
---|
2693 | @@ -2298,12 +2513,13 @@ |
---|
2694 | "409 Conflict", |
---|
2695 | "There was already a child by that name, and you asked me " |
---|
2696 | "to not replace it") |
---|
2697 | - d.addCallback(lambda res: self.GET(self.public_url + "/foo/bar.txt")) |
---|
2698 | + d.addCallback(lambda res: self.shouldSucceedGET(self.public_url + "/foo/bar.txt")) |
---|
2699 | d.addCallback(self.failUnlessIsBarDotTxt) |
---|
2700 | return d |
---|
2701 | |
---|
2702 | def test_POST_delete(self): |
---|
2703 | - d = self.POST(self.public_url + "/foo", t="delete", name="bar.txt") |
---|
2704 | + d = self.shouldSucceed("POST_delete", http.OK, self.POST, |
---|
2705 | + self.public_url + "/foo", t="delete", name="bar.txt") |
---|
2706 | d.addCallback(lambda res: self._foo_node.list()) |
---|
2707 | def _check(children): |
---|
2708 | self.failIf(u"bar.txt" in children) |
---|
2709 | @@ -2311,40 +2527,43 @@ |
---|
2710 | return d |
---|
2711 | |
---|
2712 | def test_POST_rename_file(self): |
---|
2713 | - d = self.POST(self.public_url + "/foo", t="rename", |
---|
2714 | - from_name="bar.txt", to_name='wibble.txt') |
---|
2715 | + d = self.shouldSucceed("POST_rename_file", http.OK, self.POST, |
---|
2716 | + self.public_url + "/foo", t="rename", |
---|
2717 | + from_name="bar.txt", to_name='wibble.txt') |
---|
2718 | d.addCallback(lambda res: |
---|
2719 | self.failIfNodeHasChild(self._foo_node, u"bar.txt")) |
---|
2720 | d.addCallback(lambda res: |
---|
2721 | self.failUnlessNodeHasChild(self._foo_node, u"wibble.txt")) |
---|
2722 | - d.addCallback(lambda res: self.GET(self.public_url + "/foo/wibble.txt")) |
---|
2723 | + d.addCallback(lambda res: self.shouldSucceedGET(self.public_url + "/foo/wibble.txt")) |
---|
2724 | d.addCallback(self.failUnlessIsBarDotTxt) |
---|
2725 | - d.addCallback(lambda res: self.GET(self.public_url + "/foo/wibble.txt?t=json")) |
---|
2726 | + d.addCallback(lambda res: self.shouldSucceedGET(self.public_url + "/foo/wibble.txt?t=json")) |
---|
2727 | d.addCallback(self.failUnlessIsBarJSON) |
---|
2728 | return d |
---|
2729 | |
---|
2730 | def test_POST_rename_file_redundant(self): |
---|
2731 | - d = self.POST(self.public_url + "/foo", t="rename", |
---|
2732 | - from_name="bar.txt", to_name='bar.txt') |
---|
2733 | + d = self.shouldSucceed("POST_rename_file_redundant", http.OK, self.POST, |
---|
2734 | + self.public_url + "/foo", t="rename", |
---|
2735 | + from_name="bar.txt", to_name='bar.txt') |
---|
2736 | d.addCallback(lambda res: |
---|
2737 | self.failUnlessNodeHasChild(self._foo_node, u"bar.txt")) |
---|
2738 | - d.addCallback(lambda res: self.GET(self.public_url + "/foo/bar.txt")) |
---|
2739 | + d.addCallback(lambda res: self.shouldSucceedGET(self.public_url + "/foo/bar.txt")) |
---|
2740 | d.addCallback(self.failUnlessIsBarDotTxt) |
---|
2741 | - d.addCallback(lambda res: self.GET(self.public_url + "/foo/bar.txt?t=json")) |
---|
2742 | + d.addCallback(lambda res: self.shouldSucceedGET(self.public_url + "/foo/bar.txt?t=json")) |
---|
2743 | d.addCallback(self.failUnlessIsBarJSON) |
---|
2744 | return d |
---|
2745 | |
---|
2746 | def test_POST_rename_file_replace(self): |
---|
2747 | # rename a file and replace a directory with it |
---|
2748 | - d = self.POST(self.public_url + "/foo", t="rename", |
---|
2749 | - from_name="bar.txt", to_name='empty') |
---|
2750 | + d = self.shouldSucceed("POST_rename_file_replace", http.OK, self.POST, |
---|
2751 | + self.public_url + "/foo", t="rename", |
---|
2752 | + from_name="bar.txt", to_name='empty') |
---|
2753 | d.addCallback(lambda res: |
---|
2754 | self.failIfNodeHasChild(self._foo_node, u"bar.txt")) |
---|
2755 | d.addCallback(lambda res: |
---|
2756 | self.failUnlessNodeHasChild(self._foo_node, u"empty")) |
---|
2757 | - d.addCallback(lambda res: self.GET(self.public_url + "/foo/empty")) |
---|
2758 | + d.addCallback(lambda res: self.shouldSucceedGET(self.public_url + "/foo/empty")) |
---|
2759 | d.addCallback(self.failUnlessIsBarDotTxt) |
---|
2760 | - d.addCallback(lambda res: self.GET(self.public_url + "/foo/empty?t=json")) |
---|
2761 | + d.addCallback(lambda res: self.shouldSucceedGET(self.public_url + "/foo/empty?t=json")) |
---|
2762 | d.addCallback(self.failUnlessIsBarJSON) |
---|
2763 | return d |
---|
2764 | |
---|
2765 | @@ -2357,7 +2576,7 @@ |
---|
2766 | "409 Conflict", |
---|
2767 | "There was already a child by that name, and you asked me " |
---|
2768 | "to not replace it") |
---|
2769 | - d.addCallback(lambda res: self.GET(self.public_url + "/foo/empty?t=json")) |
---|
2770 | + d.addCallback(lambda res: self.shouldSucceedGET(self.public_url + "/foo/empty?t=json")) |
---|
2771 | d.addCallback(self.failUnlessIsEmptyJSON) |
---|
2772 | return d |
---|
2773 | |
---|
2774 | @@ -2370,7 +2589,7 @@ |
---|
2775 | "409 Conflict", |
---|
2776 | "There was already a child by that name, and you asked me " |
---|
2777 | "to not replace it") |
---|
2778 | - d.addCallback(lambda res: self.GET(self.public_url + "/foo/empty?t=json")) |
---|
2779 | + d.addCallback(lambda res: self.shouldSucceedGET(self.public_url + "/foo/empty?t=json")) |
---|
2780 | d.addCallback(self.failUnlessIsEmptyJSON) |
---|
2781 | return d |
---|
2782 | |
---|
2783 | @@ -2383,7 +2602,7 @@ |
---|
2784 | d = self.POST(self.public_url + "/foo", t="rename", |
---|
2785 | from_name="bar.txt", to_name='kirk/spock.txt') |
---|
2786 | d.addBoth(self.shouldFail, error.Error, |
---|
2787 | - "test_POST_rename_file_slash_fail", |
---|
2788 | + "POST_rename_file_slash_fail", |
---|
2789 | "400 Bad Request", |
---|
2790 | "to_name= may not contain a slash", |
---|
2791 | ) |
---|
2792 | @@ -2392,13 +2611,14 @@ |
---|
2793 | return d |
---|
2794 | |
---|
2795 | def test_POST_rename_dir(self): |
---|
2796 | - d = self.POST(self.public_url, t="rename", |
---|
2797 | - from_name="foo", to_name='plunk') |
---|
2798 | + d = self.shouldSucceed("POST_rename_dir", http.OK, self.POST, |
---|
2799 | + self.public_url, t="rename", |
---|
2800 | + from_name="foo", to_name='plunk') |
---|
2801 | d.addCallback(lambda res: |
---|
2802 | self.failIfNodeHasChild(self.public_root, u"foo")) |
---|
2803 | d.addCallback(lambda res: |
---|
2804 | self.failUnlessNodeHasChild(self.public_root, u"plunk")) |
---|
2805 | - d.addCallback(lambda res: self.GET(self.public_url + "/plunk?t=json")) |
---|
2806 | + d.addCallback(lambda res: self.shouldSucceedGET(self.public_url + "/plunk?t=json")) |
---|
2807 | d.addCallback(self.failUnlessIsFooJSON) |
---|
2808 | return d |
---|
2809 | |
---|
2810 | @@ -2433,24 +2653,24 @@ |
---|
2811 | d.addCallback(lambda res: self.GET(base+"&t=json")) |
---|
2812 | d.addBoth(self.shouldRedirect, targetbase+"?t=json") |
---|
2813 | d.addCallback(self.log, "about to get file by uri") |
---|
2814 | - d.addCallback(lambda res: self.GET(base, followRedirect=True)) |
---|
2815 | + d.addCallback(lambda res: self.shouldSucceedGET(base, followRedirect=True)) |
---|
2816 | d.addCallback(self.failUnlessIsBarDotTxt) |
---|
2817 | d.addCallback(self.log, "got file by uri, about to get dir by uri") |
---|
2818 | - d.addCallback(lambda res: self.GET("/uri?uri=%s&t=json" % self._foo_uri, |
---|
2819 | - followRedirect=True)) |
---|
2820 | + d.addCallback(lambda res: self.shouldSucceedGET("/uri?uri=%s&t=json" % self._foo_uri, |
---|
2821 | + followRedirect=True)) |
---|
2822 | d.addCallback(self.failUnlessIsFooJSON) |
---|
2823 | d.addCallback(self.log, "got dir by uri") |
---|
2824 | |
---|
2825 | return d |
---|
2826 | |
---|
2827 | def test_GET_URI_form_bad(self): |
---|
2828 | - d = self.shouldFail2(error.Error, "test_GET_URI_form_bad", |
---|
2829 | + d = self.shouldFail2(error.Error, "GET_URI_form_bad", |
---|
2830 | "400 Bad Request", "GET /uri requires uri=", |
---|
2831 | self.GET, "/uri") |
---|
2832 | return d |
---|
2833 | |
---|
2834 | def test_GET_rename_form(self): |
---|
2835 | - d = self.GET(self.public_url + "/foo?t=rename-form&name=bar.txt", |
---|
2836 | + d = self.shouldSucceedGET(self.public_url + "/foo?t=rename-form&name=bar.txt", |
---|
2837 | followRedirect=True) |
---|
2838 | def _check(res): |
---|
2839 | self.failUnless('name="when_done" value="."' in res, res) |
---|
2840 | @@ -2465,23 +2685,23 @@ |
---|
2841 | |
---|
2842 | def test_GET_URI_URL(self): |
---|
2843 | base = "/uri/%s" % self._bar_txt_uri |
---|
2844 | - d = self.GET(base) |
---|
2845 | + d = self.shouldSucceedGET(base) |
---|
2846 | d.addCallback(self.failUnlessIsBarDotTxt) |
---|
2847 | - d.addCallback(lambda res: self.GET(base+"?filename=bar.txt")) |
---|
2848 | + d.addCallback(lambda res: self.shouldSucceedGET(base+"?filename=bar.txt")) |
---|
2849 | d.addCallback(self.failUnlessIsBarDotTxt) |
---|
2850 | - d.addCallback(lambda res: self.GET(base+"?filename=bar.txt&save=true")) |
---|
2851 | + d.addCallback(lambda res: self.shouldSucceedGET(base+"?filename=bar.txt&save=true")) |
---|
2852 | d.addCallback(self.failUnlessIsBarDotTxt) |
---|
2853 | return d |
---|
2854 | |
---|
2855 | def test_GET_URI_URL_dir(self): |
---|
2856 | base = "/uri/%s?t=json" % self._foo_uri |
---|
2857 | - d = self.GET(base) |
---|
2858 | + d = self.shouldSucceedGET(base) |
---|
2859 | d.addCallback(self.failUnlessIsFooJSON) |
---|
2860 | return d |
---|
2861 | |
---|
2862 | def test_GET_URI_URL_missing(self): |
---|
2863 | base = "/uri/%s" % self._bad_file_uri |
---|
2864 | - d = self.shouldHTTPError("test_GET_URI_URL_missing", |
---|
2865 | + d = self.shouldHTTPError("GET_URI_URL_missing", |
---|
2866 | http.GONE, None, "NotEnoughSharesError", |
---|
2867 | self.GET, base) |
---|
2868 | # TODO: how can we exercise both sides of WebDownloadTarget.fail |
---|
2869 | @@ -2499,9 +2719,9 @@ |
---|
2870 | d.addCallback(lambda res: |
---|
2871 | self.failUnlessEqual(res.strip(), new_uri)) |
---|
2872 | d.addCallback(lambda res: |
---|
2873 | - self.failUnlessChildURIIs(self.public_root, |
---|
2874 | - u"foo", |
---|
2875 | - new_uri)) |
---|
2876 | + self.failUnlessRWChildURIIs(self.public_root, |
---|
2877 | + u"foo", |
---|
2878 | + new_uri)) |
---|
2879 | return d |
---|
2880 | d.addCallback(_made_dir) |
---|
2881 | return d |
---|
2882 | @@ -2512,32 +2732,33 @@ |
---|
2883 | new_uri = dn.get_uri() |
---|
2884 | # replace /foo with a new (empty) directory, but ask that |
---|
2885 | # replace=false, so it should fail |
---|
2886 | - d = self.shouldFail2(error.Error, "test_PUT_DIRURL_uri_noreplace", |
---|
2887 | + d = self.shouldFail2(error.Error, "PUT_DIRURL_uri_noreplace", |
---|
2888 | "409 Conflict", "There was already a child by that name, and you asked me to not replace it", |
---|
2889 | self.PUT, |
---|
2890 | self.public_url + "/foo?t=uri&replace=false", |
---|
2891 | new_uri) |
---|
2892 | d.addCallback(lambda res: |
---|
2893 | - self.failUnlessChildURIIs(self.public_root, |
---|
2894 | - u"foo", |
---|
2895 | - self._foo_uri)) |
---|
2896 | + self.failUnlessRWChildURIIs(self.public_root, |
---|
2897 | + u"foo", |
---|
2898 | + self._foo_uri)) |
---|
2899 | return d |
---|
2900 | d.addCallback(_made_dir) |
---|
2901 | return d |
---|
2902 | |
---|
2903 | def test_PUT_DIRURL_bad_t(self): |
---|
2904 | - d = self.shouldFail2(error.Error, "test_PUT_DIRURL_bad_t", |
---|
2905 | + d = self.shouldFail2(error.Error, "PUT_DIRURL_bad_t", |
---|
2906 | "400 Bad Request", "PUT to a directory", |
---|
2907 | self.PUT, self.public_url + "/foo?t=BOGUS", "") |
---|
2908 | d.addCallback(lambda res: |
---|
2909 | - self.failUnlessChildURIIs(self.public_root, |
---|
2910 | - u"foo", |
---|
2911 | - self._foo_uri)) |
---|
2912 | + self.failUnlessRWChildURIIs(self.public_root, |
---|
2913 | + u"foo", |
---|
2914 | + self._foo_uri)) |
---|
2915 | return d |
---|
2916 | |
---|
2917 | def test_PUT_NEWFILEURL_uri(self): |
---|
2918 | contents, n, new_uri = self.makefile(8) |
---|
2919 | - d = self.PUT(self.public_url + "/foo/new.txt?t=uri", new_uri) |
---|
2920 | + d = self.shouldSucceed("PUT_NEWFILEURL_uri", http.OK, self.PUT, |
---|
2921 | + self.public_url + "/foo/new.txt?t=uri", new_uri) |
---|
2922 | d.addCallback(lambda res: self.failUnlessEqual(res.strip(), new_uri)) |
---|
2923 | d.addCallback(lambda res: |
---|
2924 | self.failUnlessChildContentsAre(self._foo_node, u"new.txt", |
---|
2925 | @@ -2564,13 +2785,14 @@ |
---|
2926 | |
---|
2927 | def test_PUT_NEWFILE_URI(self): |
---|
2928 | file_contents = "New file contents here\n" |
---|
2929 | - d = self.PUT("/uri", file_contents) |
---|
2930 | + d = self.shouldSucceed("PUT_NEWFILE_URI", http.OK, self.PUT, |
---|
2931 | + "/uri", file_contents) |
---|
2932 | def _check(uri): |
---|
2933 | assert isinstance(uri, str), uri |
---|
2934 | self.failUnless(uri in FakeCHKFileNode.all_contents) |
---|
2935 | self.failUnlessEqual(FakeCHKFileNode.all_contents[uri], |
---|
2936 | file_contents) |
---|
2937 | - return self.GET("/uri/%s" % uri) |
---|
2938 | + return self.shouldSucceedGET("/uri/%s" % uri) |
---|
2939 | d.addCallback(_check) |
---|
2940 | def _check2(res): |
---|
2941 | self.failUnlessEqual(res, file_contents) |
---|
2942 | @@ -2579,13 +2801,14 @@ |
---|
2943 | |
---|
2944 | def test_PUT_NEWFILE_URI_not_mutable(self): |
---|
2945 | file_contents = "New file contents here\n" |
---|
2946 | - d = self.PUT("/uri?mutable=false", file_contents) |
---|
2947 | + d = self.shouldSucceed("PUT_NEWFILE_URI_not_mutable", http.OK, self.PUT, |
---|
2948 | + "/uri?mutable=false", file_contents) |
---|
2949 | def _check(uri): |
---|
2950 | assert isinstance(uri, str), uri |
---|
2951 | self.failUnless(uri in FakeCHKFileNode.all_contents) |
---|
2952 | self.failUnlessEqual(FakeCHKFileNode.all_contents[uri], |
---|
2953 | file_contents) |
---|
2954 | - return self.GET("/uri/%s" % uri) |
---|
2955 | + return self.shouldSucceedGET("/uri/%s" % uri) |
---|
2956 | d.addCallback(_check) |
---|
2957 | def _check2(res): |
---|
2958 | self.failUnlessEqual(res, file_contents) |
---|
2959 | @@ -2602,7 +2825,8 @@ |
---|
2960 | |
---|
2961 | def test_PUT_NEWFILE_URI_mutable(self): |
---|
2962 | file_contents = "New file contents here\n" |
---|
2963 | - d = self.PUT("/uri?mutable=true", file_contents) |
---|
2964 | + d = self.shouldSucceed("PUT_NEWFILE_URI_mutable", http.OK, self.PUT, |
---|
2965 | + "/uri?mutable=true", file_contents) |
---|
2966 | def _check1(filecap): |
---|
2967 | filecap = filecap.strip() |
---|
2968 | self.failUnless(filecap.startswith("URI:SSK:"), filecap) |
---|
2969 | @@ -2614,7 +2838,7 @@ |
---|
2970 | d.addCallback(_check1) |
---|
2971 | def _check2(data): |
---|
2972 | self.failUnlessEqual(data, file_contents) |
---|
2973 | - return self.GET("/uri/%s" % urllib.quote(self.filecap)) |
---|
2974 | + return self.shouldSucceedGET("/uri/%s" % urllib.quote(self.filecap)) |
---|
2975 | d.addCallback(_check2) |
---|
2976 | def _check3(res): |
---|
2977 | self.failUnlessEqual(res, file_contents) |
---|
2978 | @@ -2622,19 +2846,21 @@ |
---|
2979 | return d |
---|
2980 | |
---|
2981 | def test_PUT_mkdir(self): |
---|
2982 | - d = self.PUT("/uri?t=mkdir", "") |
---|
2983 | + d = self.shouldSucceed("PUT_mkdir", http.OK, self.PUT, |
---|
2984 | + "/uri?t=mkdir", "") |
---|
2985 | def _check(uri): |
---|
2986 | n = self.s.create_node_from_uri(uri.strip()) |
---|
2987 | d2 = self.failUnlessNodeKeysAre(n, []) |
---|
2988 | d2.addCallback(lambda res: |
---|
2989 | - self.GET("/uri/%s?t=json" % uri)) |
---|
2990 | + self.shouldSucceedGET("/uri/%s?t=json" % uri)) |
---|
2991 | return d2 |
---|
2992 | d.addCallback(_check) |
---|
2993 | d.addCallback(self.failUnlessIsEmptyJSON) |
---|
2994 | return d |
---|
2995 | |
---|
2996 | def test_POST_check(self): |
---|
2997 | - d = self.POST(self.public_url + "/foo", t="check", name="bar.txt") |
---|
2998 | + d = self.shouldSucceed("POST_check", http.OK, self.POST, |
---|
2999 | + self.public_url + "/foo", t="check", name="bar.txt") |
---|
3000 | def _done(res): |
---|
3001 | # this returns a string form of the results, which are probably |
---|
3002 | # None since we're using fake filenodes. |
---|
3003 | @@ -2647,7 +2873,7 @@ |
---|
3004 | |
---|
3005 | def test_bad_method(self): |
---|
3006 | url = self.webish_url + self.public_url + "/foo/bar.txt" |
---|
3007 | - d = self.shouldHTTPError("test_bad_method", |
---|
3008 | + d = self.shouldHTTPError("bad_method", |
---|
3009 | 501, "Not Implemented", |
---|
3010 | "I don't know how to treat a BOGUS request.", |
---|
3011 | client.getPage, url, method="BOGUS") |
---|
3012 | @@ -2655,28 +2881,30 @@ |
---|
3013 | |
---|
3014 | def test_short_url(self): |
---|
3015 | url = self.webish_url + "/uri" |
---|
3016 | - d = self.shouldHTTPError("test_short_url", 501, "Not Implemented", |
---|
3017 | + d = self.shouldHTTPError("short_url", 501, "Not Implemented", |
---|
3018 | "I don't know how to treat a DELETE request.", |
---|
3019 | client.getPage, url, method="DELETE") |
---|
3020 | return d |
---|
3021 | |
---|
3022 | def test_ophandle_bad(self): |
---|
3023 | url = self.webish_url + "/operations/bogus?t=status" |
---|
3024 | - d = self.shouldHTTPError("test_ophandle_bad", 404, "404 Not Found", |
---|
3025 | + d = self.shouldHTTPError("ophandle_bad", 404, "404 Not Found", |
---|
3026 | "unknown/expired handle 'bogus'", |
---|
3027 | client.getPage, url) |
---|
3028 | return d |
---|
3029 | |
---|
3030 | def test_ophandle_cancel(self): |
---|
3031 | - d = self.POST(self.public_url + "/foo/?t=start-manifest&ophandle=128", |
---|
3032 | - followRedirect=True) |
---|
3033 | + d = self.shouldSucceed("ophandle_cancel-1", http.OK, self.POST, |
---|
3034 | + self.public_url + "/foo/?t=start-manifest&ophandle=128", |
---|
3035 | + followRedirect=True) |
---|
3036 | d.addCallback(lambda ignored: |
---|
3037 | - self.GET("/operations/128?t=status&output=JSON")) |
---|
3038 | + self.shouldSucceedGET("/operations/128?t=status&output=JSON")) |
---|
3039 | def _check1(res): |
---|
3040 | data = simplejson.loads(res) |
---|
3041 | self.failUnless("finished" in data, res) |
---|
3042 | monitor = self.ws.root.child_operations.handles["128"][0] |
---|
3043 | - d = self.POST("/operations/128?t=cancel&output=JSON") |
---|
3044 | + d = self.shouldSucceed("ophandle_cancel-2", http.OK, self.POST, |
---|
3045 | + "/operations/128?t=cancel&output=JSON") |
---|
3046 | def _check2(res): |
---|
3047 | data = simplejson.loads(res) |
---|
3048 | self.failUnless("finished" in data, res) |
---|
3049 | @@ -2686,7 +2914,7 @@ |
---|
3050 | return d |
---|
3051 | d.addCallback(_check1) |
---|
3052 | d.addCallback(lambda ignored: |
---|
3053 | - self.shouldHTTPError("test_ophandle_cancel", |
---|
3054 | + self.shouldHTTPError("ophandle_cancel", |
---|
3055 | 404, "404 Not Found", |
---|
3056 | "unknown/expired handle '128'", |
---|
3057 | self.GET, |
---|
3058 | @@ -2697,7 +2925,7 @@ |
---|
3059 | d = self.POST(self.public_url + "/foo/?t=start-manifest&ophandle=129&retain-for=60", |
---|
3060 | followRedirect=True) |
---|
3061 | d.addCallback(lambda ignored: |
---|
3062 | - self.GET("/operations/129?t=status&output=JSON&retain-for=0")) |
---|
3063 | + self.shouldSucceedGET("/operations/129?t=status&output=JSON&retain-for=0")) |
---|
3064 | def _check1(res): |
---|
3065 | data = simplejson.loads(res) |
---|
3066 | self.failUnless("finished" in data, res) |
---|
3067 | @@ -2705,7 +2933,7 @@ |
---|
3068 | # the retain-for=0 will cause the handle to be expired very soon |
---|
3069 | d.addCallback(self.stall, 2.0) |
---|
3070 | d.addCallback(lambda ignored: |
---|
3071 | - self.shouldHTTPError("test_ophandle_retainfor", |
---|
3072 | + self.shouldHTTPError("ophandle_retainfor", |
---|
3073 | 404, "404 Not Found", |
---|
3074 | "unknown/expired handle '129'", |
---|
3075 | self.GET, |
---|
3076 | @@ -2713,14 +2941,15 @@ |
---|
3077 | return d |
---|
3078 | |
---|
3079 | def test_ophandle_release_after_complete(self): |
---|
3080 | - d = self.POST(self.public_url + "/foo/?t=start-manifest&ophandle=130", |
---|
3081 | - followRedirect=True) |
---|
3082 | + d = self.shouldSucceed("ophandle_release_after_complete", http.OK, self.POST, |
---|
3083 | + self.public_url + "/foo/?t=start-manifest&ophandle=130", |
---|
3084 | + followRedirect=True) |
---|
3085 | d.addCallback(self.wait_for_operation, "130") |
---|
3086 | d.addCallback(lambda ignored: |
---|
3087 | - self.GET("/operations/130?t=status&output=JSON&release-after-complete=true")) |
---|
3088 | + self.shouldSucceedGET("/operations/130?t=status&output=JSON&release-after-complete=true")) |
---|
3089 | # the release-after-complete=true will cause the handle to be expired |
---|
3090 | d.addCallback(lambda ignored: |
---|
3091 | - self.shouldHTTPError("test_ophandle_release_after_complete", |
---|
3092 | + self.shouldHTTPError("ophandle_release_after_complete", |
---|
3093 | 404, "404 Not Found", |
---|
3094 | "unknown/expired handle '130'", |
---|
3095 | self.GET, |
---|
3096 | @@ -2728,7 +2957,8 @@ |
---|
3097 | return d |
---|
3098 | |
---|
3099 | def test_incident(self): |
---|
3100 | - d = self.POST("/report_incident", details="eek") |
---|
3101 | + d = self.shouldSucceed("incident", http.OK, self.POST, |
---|
3102 | + "/report_incident", details="eek") |
---|
3103 | def _done(res): |
---|
3104 | self.failUnless("Thank you for your report!" in res, res) |
---|
3105 | d.addCallback(_done) |
---|
3106 | @@ -2741,7 +2971,7 @@ |
---|
3107 | f.write("hello") |
---|
3108 | f.close() |
---|
3109 | |
---|
3110 | - d = self.GET("/static/subdir/hello.txt") |
---|
3111 | + d = self.shouldSucceedGET("/static/subdir/hello.txt") |
---|
3112 | def _check(res): |
---|
3113 | self.failUnlessEqual(res, "hello") |
---|
3114 | d.addCallback(_check) |
---|
3115 | @@ -2754,7 +2984,7 @@ |
---|
3116 | self.failUnlessEqual(common.parse_replace_arg("false"), False) |
---|
3117 | self.failUnlessEqual(common.parse_replace_arg("only-files"), |
---|
3118 | "only-files") |
---|
3119 | - self.shouldFail(AssertionError, "test_parse_replace_arg", "", |
---|
3120 | + self.shouldFail(AssertionError, "parse_replace_arg", "", |
---|
3121 | common.parse_replace_arg, "only_fles") |
---|
3122 | |
---|
3123 | def test_abbreviate_time(self): |
---|
3124 | @@ -3059,71 +3289,225 @@ |
---|
3125 | d.addErrback(self.explain_web_error) |
---|
3126 | return d |
---|
3127 | |
---|
3128 | - def test_unknown(self): |
---|
3129 | + def test_unknown(self, immutable=False): |
---|
3130 | self.basedir = "web/Grid/unknown" |
---|
3131 | + if immutable: |
---|
3132 | + self.basedir = "web/Grid/unknown-immutable" |
---|
3133 | + |
---|
3134 | self.set_up_grid() |
---|
3135 | c0 = self.g.clients[0] |
---|
3136 | self.uris = {} |
---|
3137 | self.fileurls = {} |
---|
3138 | |
---|
3139 | - future_writecap = "x-tahoe-crazy://I_am_from_the_future." |
---|
3140 | - future_readcap = "x-tahoe-crazy-readonly://I_am_from_the_future." |
---|
3141 | + future_write_uri = "x-tahoe-crazy://I_am_from_the_future." |
---|
3142 | + future_read_uri = "x-tahoe-crazy-readonly://I_am_from_the_future." |
---|
3143 | # the future cap format may contain slashes, which must be tolerated |
---|
3144 | - expected_info_url = "uri/%s?t=info" % urllib.quote(future_writecap, |
---|
3145 | + expected_info_url = "uri/%s?t=info" % urllib.quote(future_write_uri, |
---|
3146 | safe="") |
---|
3147 | - future_node = UnknownNode(future_writecap, future_readcap) |
---|
3148 | |
---|
3149 | - d = c0.create_dirnode() |
---|
3150 | + if immutable: |
---|
3151 | + name = u"future-imm" |
---|
3152 | + future_node = UnknownNode(None, future_read_uri, deep_immutable=True) |
---|
3153 | + d = c0.create_immutable_dirnode({name: (future_node, {})}) |
---|
3154 | + else: |
---|
3155 | + name = u"future" |
---|
3156 | + future_node = UnknownNode(future_write_uri, future_read_uri) |
---|
3157 | + d = c0.create_dirnode() |
---|
3158 | + |
---|
3159 | def _stash_root_and_create_file(n): |
---|
3160 | self.rootnode = n |
---|
3161 | self.rooturl = "uri/" + urllib.quote(n.get_uri()) + "/" |
---|
3162 | self.rourl = "uri/" + urllib.quote(n.get_readonly_uri()) + "/" |
---|
3163 | - return self.rootnode.set_node(u"future", future_node) |
---|
3164 | + if not immutable: |
---|
3165 | + return self.rootnode.set_node(name, future_node) |
---|
3166 | d.addCallback(_stash_root_and_create_file) |
---|
3167 | + |
---|
3168 | # make sure directory listing tolerates unknown nodes |
---|
3169 | d.addCallback(lambda ign: self.GET(self.rooturl)) |
---|
3170 | def _check_html(res): |
---|
3171 | - self.failUnlessIn("<td>future</td>", res) |
---|
3172 | - # find the More Info link for "future", should be relative |
---|
3173 | + self.failUnlessIn("<td>%s</td>" % (str(name),), res) |
---|
3174 | + # find the More Info link for name, should be relative |
---|
3175 | mo = re.search(r'<a href="([^"]+)">More Info</a>', res) |
---|
3176 | info_url = mo.group(1) |
---|
3177 | - self.failUnlessEqual(info_url, "future?t=info") |
---|
3178 | + self.failUnlessEqual(info_url, "%s?t=info" % (str(name),)) |
---|
3179 | |
---|
3180 | d.addCallback(_check_html) |
---|
3181 | d.addCallback(lambda ign: self.GET(self.rooturl+"?t=json")) |
---|
3182 | - def _check_json(res, expect_writecap): |
---|
3183 | + def _check_json(res, expect_rw_uri): |
---|
3184 | data = simplejson.loads(res) |
---|
3185 | self.failUnlessEqual(data[0], "dirnode") |
---|
3186 | - f = data[1]["children"]["future"] |
---|
3187 | + f = data[1]["children"][name] |
---|
3188 | self.failUnlessEqual(f[0], "unknown") |
---|
3189 | - if expect_writecap: |
---|
3190 | - self.failUnlessEqual(f[1]["rw_uri"], future_writecap) |
---|
3191 | + if expect_rw_uri: |
---|
3192 | + self.failUnlessEqual(f[1]["rw_uri"], future_write_uri) |
---|
3193 | else: |
---|
3194 | self.failIfIn("rw_uri", f[1]) |
---|
3195 | - self.failUnlessEqual(f[1]["ro_uri"], future_readcap) |
---|
3196 | + self.failUnlessEqual(f[1]["ro_uri"], |
---|
3197 | + ("imm." if immutable else "ro.") + future_read_uri) |
---|
3198 | self.failUnless("metadata" in f[1]) |
---|
3199 | - d.addCallback(_check_json, expect_writecap=True) |
---|
3200 | - d.addCallback(lambda ign: self.GET(expected_info_url)) |
---|
3201 | - def _check_info(res, expect_readcap): |
---|
3202 | + d.addCallback(_check_json, expect_rw_uri=not immutable) |
---|
3203 | + |
---|
3204 | + def _check_info(res, expect_rw_uri, expect_ro_uri): |
---|
3205 | self.failUnlessIn("Object Type: <span>unknown</span>", res) |
---|
3206 | - self.failUnlessIn(future_writecap, res) |
---|
3207 | - if expect_readcap: |
---|
3208 | - self.failUnlessIn(future_readcap, res) |
---|
3209 | + if expect_rw_uri: |
---|
3210 | + self.failUnlessIn(future_write_uri, res) |
---|
3211 | + if expect_ro_uri: |
---|
3212 | + self.failUnlessIn(future_read_uri, res) |
---|
3213 | + else: |
---|
3214 | + self.failIfIn(future_read_uri, res) |
---|
3215 | self.failIfIn("Raw data as", res) |
---|
3216 | self.failIfIn("Directory writecap", res) |
---|
3217 | self.failIfIn("Checker Operations", res) |
---|
3218 | self.failIfIn("Mutable File Operations", res) |
---|
3219 | self.failIfIn("Directory Operations", res) |
---|
3220 | - d.addCallback(_check_info, expect_readcap=False) |
---|
3221 | - d.addCallback(lambda ign: self.GET(self.rooturl+"future?t=info")) |
---|
3222 | - d.addCallback(_check_info, expect_readcap=True) |
---|
3223 | + |
---|
3224 | + # Known bug: these should have expect_rw_uri=not immutable, but the |
---|
3225 | + # info pages are currently broken. Related to ticket #922. |
---|
3226 | + |
---|
3227 | + d.addCallback(lambda ign: self.GET(expected_info_url)) |
---|
3228 | + d.addCallback(_check_info, expect_rw_uri=False, expect_ro_uri=False) |
---|
3229 | + d.addCallback(lambda ign: self.GET("%s%s?t=info" % (self.rooturl, str(name)))) |
---|
3230 | + d.addCallback(_check_info, expect_rw_uri=False, expect_ro_uri=True) |
---|
3231 | |
---|
3232 | # and make sure that a read-only version of the directory can be |
---|
3233 | - # rendered too. This version will not have future_writecap |
---|
3234 | + # rendered too. This version will not have future_write_uri, whether |
---|
3235 | + # or not future_node was immutable. |
---|
3236 | d.addCallback(lambda ign: self.GET(self.rourl)) |
---|
3237 | d.addCallback(_check_html) |
---|
3238 | d.addCallback(lambda ign: self.GET(self.rourl+"?t=json")) |
---|
3239 | - d.addCallback(_check_json, expect_writecap=False) |
---|
3240 | + d.addCallback(_check_json, expect_rw_uri=False) |
---|
3241 | + return d |
---|
3242 | + |
---|
3243 | + def test_immutable_unknown(self): |
---|
3244 | + return self.test_unknown(immutable=True) |
---|
3245 | + |
---|
3246 | + def test_mutant_dirnodes_are_omitted(self): |
---|
3247 | + self.basedir = "web/Grid/mutant_dirnodes_are_omitted" |
---|
3248 | + |
---|
3249 | + self.set_up_grid() |
---|
3250 | + c = self.g.clients[0] |
---|
3251 | + nm = c.nodemaker |
---|
3252 | + self.uris = {} |
---|
3253 | + self.fileurls = {} |
---|
3254 | + |
---|
3255 | + lonely_uri = "URI:LIT:n5xgk" # LIT for "one" |
---|
3256 | + mut_write_uri = "URI:SSK:vfvcbdfbszyrsaxchgevhmmlii:euw4iw7bbnkrrwpzuburbhppuxhc3gwxv26f6imekhz7zyw2ojnq" |
---|
3257 | + mut_read_uri = "URI:SSK-RO:e3mdrzfwhoq42hy5ubcz6rp3o4:ybyibhnp3vvwuq2vaw2ckjmesgkklfs6ghxleztqidihjyofgw7q" |
---|
3258 | + |
---|
3259 | + # This method tests mainly dirnode, but we'd have to duplicate code in order to |
---|
3260 | + # test the dirnode and web layers separately. |
---|
3261 | + |
---|
3262 | + # 'lonely' is a valid LIT child, 'ro' is a mutant child with an SSK-RO readcap, |
---|
3263 | + # and 'write-in-ro' is a mutant child with an SSK writecap in the ro_uri field. |
---|
3264 | + # When the directory is read, the mutants should be silently disposed of, leaving |
---|
3265 | + # their lonely sibling. |
---|
3266 | + # We don't test the case of a retrieving a cap from the encrypted rw_uri field, |
---|
3267 | + # because immutable directories don't have a writecap and therefore that field |
---|
3268 | + # isn't (and can't be) decrypted. |
---|
3269 | + # TODO: The field still exists in the netstring. Technically we should check what |
---|
3270 | + # happens if something is put there (it should be ignored), but that can wait. |
---|
3271 | + |
---|
3272 | + lonely_child = nm.create_from_cap(lonely_uri) |
---|
3273 | + mutant_ro_child = nm.create_from_cap(mut_read_uri) |
---|
3274 | + mutant_write_in_ro_child = nm.create_from_cap(mut_write_uri) |
---|
3275 | + |
---|
3276 | + def _by_hook_or_by_crook(): |
---|
3277 | + return True |
---|
3278 | + for n in [mutant_ro_child, mutant_write_in_ro_child]: |
---|
3279 | + n.is_allowed_in_immutable_directory = _by_hook_or_by_crook |
---|
3280 | + |
---|
3281 | + mutant_write_in_ro_child.get_write_uri = lambda: None |
---|
3282 | + mutant_write_in_ro_child.get_readonly_uri = lambda: mut_write_uri |
---|
3283 | + |
---|
3284 | + kids = {u"lonely": (lonely_child, {}), |
---|
3285 | + u"ro": (mutant_ro_child, {}), |
---|
3286 | + u"write-in-ro": (mutant_write_in_ro_child, {}), |
---|
3287 | + } |
---|
3288 | + d = c.create_immutable_dirnode(kids) |
---|
3289 | + |
---|
3290 | + def _created(dn): |
---|
3291 | + self.failUnless(isinstance(dn, dirnode.DirectoryNode)) |
---|
3292 | + self.failIf(dn.is_mutable()) |
---|
3293 | + self.failUnless(dn.is_readonly()) |
---|
3294 | + # This checks that if we somehow ended up calling dn._decrypt_rwcapdata, it would fail. |
---|
3295 | + self.failIf(hasattr(dn._node, 'get_writekey')) |
---|
3296 | + rep = str(dn) |
---|
3297 | + self.failUnless("RO-IMM" in rep) |
---|
3298 | + cap = dn.get_cap() |
---|
3299 | + self.failUnlessIn("CHK", cap.to_string()) |
---|
3300 | + self.cap = cap |
---|
3301 | + self.rootnode = dn |
---|
3302 | + self.rooturl = "uri/" + urllib.quote(dn.get_uri()) + "/" |
---|
3303 | + return download_to_data(dn._node) |
---|
3304 | + d.addCallback(_created) |
---|
3305 | + |
---|
3306 | + def _check_data(data): |
---|
3307 | + # Decode the netstring representation of the directory to check that all children |
---|
3308 | + # are present. This is a bit of an abstraction violation, but there's not really |
---|
3309 | + # any other way to do it given that the real DirectoryNode._unpack_contents would |
---|
3310 | + # strip the mutant children out (which is what we're trying to test, later). |
---|
3311 | + position = 0 |
---|
3312 | + numkids = 0 |
---|
3313 | + while position < len(data): |
---|
3314 | + entries, position = split_netstring(data, 1, position) |
---|
3315 | + entry = entries[0] |
---|
3316 | + (name, ro_uri, rwcapdata, metadata_s), subpos = split_netstring(entry, 4) |
---|
3317 | + name = name.decode("utf-8") |
---|
3318 | + self.failUnless(rwcapdata == "") |
---|
3319 | + ro_uri = ro_uri.strip() |
---|
3320 | + if name in kids: |
---|
3321 | + self.failIfEqual(ro_uri, "") |
---|
3322 | + (expected_child, ign) = kids[name] |
---|
3323 | + self.failUnlessEqual(ro_uri, expected_child.get_readonly_uri()) |
---|
3324 | + numkids += 1 |
---|
3325 | + |
---|
3326 | + self.failUnlessEqual(numkids, 3) |
---|
3327 | + return self.rootnode.list() |
---|
3328 | + d.addCallback(_check_data) |
---|
3329 | + |
---|
3330 | + # Now when we use the real directory listing code, the mutants should be absent. |
---|
3331 | + def _check_kids(children): |
---|
3332 | + self.failUnlessEqual(sorted(children.keys()), [u"lonely"]) |
---|
3333 | + lonely_node, lonely_metadata = children[u"lonely"] |
---|
3334 | + |
---|
3335 | + self.failUnlessEqual(lonely_node.get_write_uri(), None) |
---|
3336 | + self.failUnlessEqual(lonely_node.get_readonly_uri(), lonely_uri) |
---|
3337 | + d.addCallback(_check_kids) |
---|
3338 | + |
---|
3339 | + d.addCallback(lambda ign: nm.create_from_cap(self.cap.to_string())) |
---|
3340 | + d.addCallback(lambda n: n.list()) |
---|
3341 | + d.addCallback(_check_kids) # again with dirnode recreated from cap |
---|
3342 | + |
---|
3343 | + # Make sure the lonely child can be listed in HTML... |
---|
3344 | + d.addCallback(lambda ign: self.GET(self.rooturl)) |
---|
3345 | + def _check_html(res): |
---|
3346 | + self.failIfIn("URI:SSK", res) |
---|
3347 | + get_lonely = "".join([r'<td>FILE</td>', |
---|
3348 | + r'\s+<td>', |
---|
3349 | + r'<a href="[^"]+%s[^"]+">lonely</a>' % (urllib.quote(lonely_uri),), |
---|
3350 | + r'</td>', |
---|
3351 | + r'\s+<td>%d</td>' % len("one"), |
---|
3352 | + ]) |
---|
3353 | + self.failUnless(re.search(get_lonely, res), res) |
---|
3354 | + |
---|
3355 | + # find the More Info link for name, should be relative |
---|
3356 | + mo = re.search(r'<a href="([^"]+)">More Info</a>', res) |
---|
3357 | + info_url = mo.group(1) |
---|
3358 | + self.failUnless(info_url.endswith(urllib.quote(lonely_uri) + "?t=info"), info_url) |
---|
3359 | + d.addCallback(_check_html) |
---|
3360 | + |
---|
3361 | + # ... and in JSON. |
---|
3362 | + d.addCallback(lambda ign: self.GET(self.rooturl+"?t=json")) |
---|
3363 | + def _check_json(res): |
---|
3364 | + data = simplejson.loads(res) |
---|
3365 | + self.failUnlessEqual(data[0], "dirnode") |
---|
3366 | + listed_children = data[1]["children"] |
---|
3367 | + self.failUnlessEqual(sorted(listed_children.keys()), [u"lonely"]) |
---|
3368 | + ll_type, ll_data = listed_children[u"lonely"] |
---|
3369 | + self.failUnlessEqual(ll_type, "filenode") |
---|
3370 | + self.failIf("rw_uri" in ll_data) |
---|
3371 | + self.failUnlessEqual(ll_data["ro_uri"], lonely_uri) |
---|
3372 | + d.addCallback(_check_json) |
---|
3373 | return d |
---|
3374 | |
---|
3375 | def test_deep_check(self): |
---|
3376 | @@ -3156,10 +3540,10 @@ |
---|
3377 | |
---|
3378 | # this tests that deep-check and stream-manifest will ignore |
---|
3379 | # UnknownNode instances. Hopefully this will also cover deep-stats. |
---|
3380 | - future_writecap = "x-tahoe-crazy://I_am_from_the_future." |
---|
3381 | - future_readcap = "x-tahoe-crazy-readonly://I_am_from_the_future." |
---|
3382 | - future_node = UnknownNode(future_writecap, future_readcap) |
---|
3383 | - d.addCallback(lambda ign: self.rootnode.set_node(u"future",future_node)) |
---|
3384 | + future_write_uri = "x-tahoe-crazy://I_am_from_the_future." |
---|
3385 | + future_read_uri = "x-tahoe-crazy-readonly://I_am_from_the_future." |
---|
3386 | + future_node = UnknownNode(future_write_uri, future_read_uri) |
---|
3387 | + d.addCallback(lambda ign: self.rootnode.set_node(u"future", future_node)) |
---|
3388 | |
---|
3389 | def _clobber_shares(ignored): |
---|
3390 | self.delete_shares_numbered(self.uris["sick"], [0,1]) |
---|