Ticket #1051: test-nonascii-future-caps.dpatch

File test-nonascii-future-caps.dpatch, 34.9 KB (added by zooko, at 2010-05-19T06:21:58Z)
Line 
1Tue May 18 23:51:46 MDT 2010  zooko@zooko.com
2  * tests: refactor test_web.py to have less duplication of literal caps-from-the-future
3  This is a prelude to a patch which will add tests of caps from the future which have non-ascii chars in them.
4
5Wed May 19 00:06:23 MDT 2010  zooko@zooko.com
6  * add tests of caps from the future that have non-ASCII characters in them
7  Current trunk fails these tests. The changes to test_uri.py, test_client.py, and test_dirnode.py add tests of non-ascii-future-caps (in Python unicode objects) in addition to the current tests of all-ascii-future-caps (in Python str objects). The changes to test_web.py just replace the tests of all-ascii-future-caps with tests of non-ascii-future-caps.
8
9New patches:
10
11[tests: refactor test_web.py to have less duplication of literal caps-from-the-future
12zooko@zooko.com**20100519055146
13 Ignore-this: 49e5412e6cc4566ca67f069ffd850af6
14 This is a prelude to a patch which will add tests of caps from the future which have non-ascii chars in them.
15] {
16hunk ./src/allmydata/test/test_web.py 38
17 
18 timeout = 480 # Most of these take longer than 240 seconds on Francois's arm box.
19 
20+unknown_rwcap = "lafs://from_the_future"
21+unknown_rocap = "ro.lafs://readonly_from_the_future"
22+unknown_immcap = "imm.lafs://immutable_from_the_future"
23+
24 class FakeStatsProvider:
25     def get_stats(self):
26         stats = {'stats': {}, 'counters': {}}
27hunk ./src/allmydata/test/test_web.py 2180
28         filecap2 = make_mutable_file_uri()
29         node3 = self.s.create_node_from_uri(make_mutable_file_uri())
30         filecap3 = node3.get_readonly_uri()
31-        unknown_rwcap = "lafs://from_the_future"
32-        unknown_rocap = "ro.lafs://readonly_from_the_future"
33-        unknown_immcap = "imm.lafs://immutable_from_the_future"
34         node4 = self.s.create_node_from_uri(make_mutable_file_uri())
35         dircap = DirectoryNode(node4, None, None).get_uri()
36         litdircap = "URI:DIR2-LIT:ge3dumj2mewdcotyfqydulbshj5x2lbm"
37hunk ./src/allmydata/test/test_web.py 2215
38         tnode = create_chk_filenode("immutable directory contents\n"*10)
39         dnode = DirectoryNode(tnode, None, None)
40         assert not dnode.is_mutable()
41-        unknown_immcap = "imm.lafs://immutable_from_the_future"
42         immdircap = dnode.get_uri()
43         litdircap = "URI:DIR2-LIT:ge3dumj2mewdcotyfqydulbshj5x2lbm"
44         emptydircap = "URI:DIR2-LIT:"
45hunk ./src/allmydata/test/test_web.py 2456
46         return d
47 
48     def test_POST_link_uri_unknown_bad(self):
49-        newuri = "lafs://from_the_future"
50-        d = self.POST(self.public_url + "/foo", t="uri", name="future.txt", uri=newuri)
51+        d = self.POST(self.public_url + "/foo", t="uri", name="future.txt", uri=unknown_rwcap)
52         d.addBoth(self.shouldFail, error.Error,
53                   "POST_link_uri_unknown_bad",
54                   "400 Bad Request",
55hunk ./src/allmydata/test/test_web.py 2464
56         return d
57 
58     def test_POST_link_uri_unknown_ro_good(self):
59-        newuri = "ro.lafs://readonly_from_the_future"
60-        d = self.POST(self.public_url + "/foo", t="uri", name="future-ro.txt", uri=newuri)
61+        d = self.POST(self.public_url + "/foo", t="uri", name="future-ro.txt", uri=unknown_rocap)
62         d.addCallback(self.failUnlessURIMatchesROChild, self._foo_node, u"future-ro.txt")
63         return d
64 
65hunk ./src/allmydata/test/test_web.py 2469
66     def test_POST_link_uri_unknown_imm_good(self):
67-        newuri = "imm.lafs://immutable_from_the_future"
68-        d = self.POST(self.public_url + "/foo", t="uri", name="future-imm.txt", uri=newuri)
69+        d = self.POST(self.public_url + "/foo", t="uri", name="future-imm.txt", uri=unknown_immcap)
70         d.addCallback(self.failUnlessURIMatchesROChild, self._foo_node, u"future-imm.txt")
71         return d
72 
73hunk ./src/allmydata/test/test_web.py 2760
74         return d
75 
76     def test_PUT_NEWFILEURL_uri_unknown_bad(self):
77-        new_uri = "lafs://from_the_future"
78-        d = self.PUT(self.public_url + "/foo/put-future.txt?t=uri", new_uri)
79+        d = self.PUT(self.public_url + "/foo/put-future.txt?t=uri", unknown_rwcap)
80         d.addBoth(self.shouldFail, error.Error,
81                   "POST_put_uri_unknown_bad",
82                   "400 Bad Request",
83hunk ./src/allmydata/test/test_web.py 2768
84         return d
85 
86     def test_PUT_NEWFILEURL_uri_unknown_ro_good(self):
87-        new_uri = "ro.lafs://readonly_from_the_future"
88-        d = self.PUT(self.public_url + "/foo/put-future-ro.txt?t=uri", new_uri)
89+        d = self.PUT(self.public_url + "/foo/put-future-ro.txt?t=uri", unknown_rocap)
90         d.addCallback(self.failUnlessURIMatchesROChild, self._foo_node,
91                       u"put-future-ro.txt")
92         return d
93hunk ./src/allmydata/test/test_web.py 2774
94 
95     def test_PUT_NEWFILEURL_uri_unknown_imm_good(self):
96-        new_uri = "imm.lafs://immutable_from_the_future"
97-        d = self.PUT(self.public_url + "/foo/put-future-imm.txt?t=uri", new_uri)
98+        d = self.PUT(self.public_url + "/foo/put-future-imm.txt?t=uri", unknown_immcap)
99         d.addCallback(self.failUnlessURIMatchesROChild, self._foo_node,
100                       u"put-future-imm.txt")
101         return d
102hunk ./src/allmydata/test/test_web.py 3367
103         self.uris = {}
104         self.fileurls = {}
105 
106-        future_write_uri = "x-tahoe-crazy://I_am_from_the_future."
107-        future_read_uri = "x-tahoe-crazy-readonly://I_am_from_the_future."
108         # the future cap format may contain slashes, which must be tolerated
109hunk ./src/allmydata/test/test_web.py 3368
110-        expected_info_url = "uri/%s?t=info" % urllib.quote(future_write_uri,
111+        expected_info_url = "uri/%s?t=info" % urllib.quote(unknown_rwcap,
112                                                            safe="")
113 
114         if immutable:
115hunk ./src/allmydata/test/test_web.py 3373
116             name = u"future-imm"
117-            future_node = UnknownNode(None, future_read_uri, deep_immutable=True)
118+            future_node = UnknownNode(None, unknown_immcap, deep_immutable=True)
119             d = c0.create_immutable_dirnode({name: (future_node, {})})
120         else:
121             name = u"future"
122hunk ./src/allmydata/test/test_web.py 3377
123-            future_node = UnknownNode(future_write_uri, future_read_uri)
124+            future_node = UnknownNode(unknown_rwcap, unknown_rocap)
125             d = c0.create_dirnode()
126 
127         def _stash_root_and_create_file(n):
128hunk ./src/allmydata/test/test_web.py 3411
129             f = data[1]["children"][name]
130             self.failUnlessEqual(f[0], "unknown")
131             if expect_rw_uri:
132-                self.failUnlessEqual(f[1]["rw_uri"], future_write_uri)
133+                self.failUnlessEqual(f[1]["rw_uri"], unknown_rwcap)
134             else:
135                 self.failIfIn("rw_uri", f[1])
136             if immutable:
137hunk ./src/allmydata/test/test_web.py 3415
138-                self.failUnlessEqual(f[1]["ro_uri"], "imm." + future_read_uri)
139+                self.failUnlessEqual(f[1]["ro_uri"], unknown_immcap, data)
140             else:
141hunk ./src/allmydata/test/test_web.py 3417
142-                self.failUnlessEqual(f[1]["ro_uri"], "ro." + future_read_uri)
143+                self.failUnlessEqual(f[1]["ro_uri"], unknown_rocap)
144             self.failUnless("metadata" in f[1])
145         d.addCallback(_check_directory_json, expect_rw_uri=not immutable)
146 
147hunk ./src/allmydata/test/test_web.py 3424
148         def _check_info(res, expect_rw_uri, expect_ro_uri):
149             self.failUnlessIn("Object Type: <span>unknown</span>", res)
150             if expect_rw_uri:
151-                self.failUnlessIn(future_write_uri, res)
152+                self.failUnlessIn(unknown_rwcap, res)
153             if expect_ro_uri:
154hunk ./src/allmydata/test/test_web.py 3426
155-                self.failUnlessIn(future_read_uri, res)
156+                if immutable:
157+                    self.failUnlessIn(unknown_immcap, res)
158+                else:
159+                    self.failUnlessIn(unknown_rocap, res)
160             else:
161hunk ./src/allmydata/test/test_web.py 3431
162-                self.failIfIn(future_read_uri, res)
163+                self.failIfIn(unknown_rocap, res)
164             self.failIfIn("Raw data as", res)
165             self.failIfIn("Directory writecap", res)
166             self.failIfIn("Checker Operations", res)
167hunk ./src/allmydata/test/test_web.py 3450
168             data = simplejson.loads(res)
169             self.failUnlessEqual(data[0], "unknown")
170             if expect_rw_uri:
171-                self.failUnlessEqual(data[1]["rw_uri"], future_write_uri)
172+                self.failUnlessEqual(data[1]["rw_uri"], unknown_rwcap)
173             else:
174                 self.failIfIn("rw_uri", data[1])
175 
176hunk ./src/allmydata/test/test_web.py 3455
177             if immutable:
178-                self.failUnlessEqual(data[1]["ro_uri"], "imm." + future_read_uri)
179+                self.failUnlessEqual(data[1]["ro_uri"], unknown_immcap)
180                 self.failUnlessEqual(data[1]["mutable"], False)
181             elif expect_rw_uri:
182hunk ./src/allmydata/test/test_web.py 3458
183-                self.failUnlessEqual(data[1]["ro_uri"], "ro." + future_read_uri)
184+                self.failUnlessEqual(data[1]["ro_uri"], unknown_rocap)
185                 self.failUnlessEqual(data[1]["mutable"], True)
186             else:
187hunk ./src/allmydata/test/test_web.py 3461
188-                self.failUnlessEqual(data[1]["ro_uri"], "ro." + future_read_uri)
189+                self.failUnlessEqual(data[1]["ro_uri"], unknown_rocap)
190                 self.failIf("mutable" in data[1], data[1])
191 
192             # TODO: check metadata contents
193hunk ./src/allmydata/test/test_web.py 3471
194         d.addCallback(_check_json, expect_rw_uri=not immutable)
195 
196         # and make sure that a read-only version of the directory can be
197-        # rendered too. This version will not have future_write_uri, whether
198+        # rendered too. This version will not have unknown_rwcap, whether
199         # or not future_node was immutable.
200         d.addCallback(lambda ign: self.GET(self.rourl))
201         if immutable:
202hunk ./src/allmydata/test/test_web.py 3650
203 
204         # this tests that deep-check and stream-manifest will ignore
205         # UnknownNode instances. Hopefully this will also cover deep-stats.
206-        future_write_uri = "x-tahoe-crazy://I_am_from_the_future."
207-        future_read_uri = "x-tahoe-crazy-readonly://I_am_from_the_future."
208-        future_node = UnknownNode(future_write_uri, future_read_uri)
209+        future_node = UnknownNode(unknown_rwcap, unknown_rocap)
210         d.addCallback(lambda ign: self.rootnode.set_node(u"future", future_node))
211 
212         def _clobber_shares(ignored):
213}
214[add tests of caps from the future that have non-ASCII characters in them
215zooko@zooko.com**20100519060623
216 Ignore-this: 754e6f060da9d96b13feab58e9b60cb9
217 Current trunk fails these tests. The changes to test_uri.py, test_client.py, and test_dirnode.py add tests of non-ascii-future-caps (in Python unicode objects) in addition to the current tests of all-ascii-future-caps (in Python str objects). The changes to test_web.py just replace the tests of all-ascii-future-caps with tests of non-ascii-future-caps.
218] {
219hunk ./src/allmydata/test/test_client.py 1
220+# -*- coding: utf-8 -*-
221 
222 import os
223 from twisted.trial import unittest
224hunk ./src/allmydata/test/test_client.py 304
225         self.failUnlessEqual(n.get_uri(), unknown_rw)
226         self.failUnlessEqual(n.get_write_uri(), unknown_rw)
227         self.failUnlessEqual(n.get_readonly_uri(), "ro." + unknown_ro)
228+
229+        unknown_rw = u"lafs://from_the_future_fw-蜔쳨欝遃䝦舜琇襇邤䍏㵦☚✸킾궑蒴犏띎냔㳆㼿졨浴䒉ΐ屝稜퍙鉧迴"
230+        unknown_ro = u"lafs://readonly_from_the_future_fo-ą쳨欝遃䝦舜琇襇邤䍏㵦☚✸킾궑蒴犏띎냔㳆㼿졨浴䒉ΐ屝稜퍙鉧迴"
231+        n = c.create_node_from_uri(unknown_rw, unknown_ro)
232+        self.failUnless(IFilesystemNode.providedBy(n))
233+        self.failIf(IFileNode.providedBy(n))
234+        self.failIf(IImmutableFileNode.providedBy(n))
235+        self.failIf(IMutableFileNode.providedBy(n))
236+        self.failIf(IDirectoryNode.providedBy(n))
237+        self.failUnless(n.is_unknown())
238+        self.failUnlessEqual(n.get_uri(), unknown_rw)
239+        self.failUnlessEqual(n.get_write_uri(), unknown_rw)
240+        self.failUnlessEqual(n.get_readonly_uri(), "ro." + unknown_ro)
241hunk ./src/allmydata/test/test_dirnode.py 1
242+# -*- coding: utf-8 -*-
243 
244 import time
245 from zope.interface import implements
246hunk ./src/allmydata/test/test_dirnode.py 49
247 mut_read_uri = "URI:SSK-RO:jf6wkflosyvntwxqcdo7a54jvm:euw4iw7bbnkrrwpzuburbhppuxhc3gwxv26f6imekhz7zyw2ojnq"
248 future_write_uri = "x-tahoe-crazy://I_am_from_the_future."
249 future_read_uri = "x-tahoe-crazy-readonly://I_am_from_the_future."
250+future_nonascii_write_uri = u"x-tahoe-even-more-crazy://I_am_from_the_fw-蜔쳨欝遃䝦舜琇襇邤䍏㵦☚✸킾궑蒴犏띎냔㳆㼿졨浴䒉ΐ屝稜퍙鉧迴."
251+future_nonascii_read_uri = u"x-tahoe-even-more-crazy-readonly://I_am_from_the_fo-ą쳨欝遃䝦舜琇襇邤䍏㵦☚✸킾궑蒴犏띎냔㳆㼿졨浴䒉ΐ屝稜퍙鉧迴."
252 
253 class Dirnode(GridTestMixin, unittest.TestCase,
254               testutil.ShouldFailMixin, testutil.StallMixin, ErrorMixin):
255hunk ./src/allmydata/test/test_dirnode.py 85
256                 u"mut": (nm.create_from_cap(mut_write_uri, mut_read_uri), {}),
257                 u"fut": (nm.create_from_cap(future_write_uri, future_read_uri), {}),
258                 u"fro": (nm.create_from_cap(None, future_read_uri), {}),
259+                u"fut-unic": (nm.create_from_cap(future_nonascii_read_uri, future_nonascii_read_uri), {}),
260+                u"fro-unic": (nm.create_from_cap(None, future_nonascii_read_uri), {}),
261                 u"empty_litdir": (nm.create_from_cap(empty_litdir_uri), {}),
262                 u"tiny_litdir": (nm.create_from_cap(tiny_litdir_uri), {}),
263                 }
264hunk ./src/allmydata/test/test_dirnode.py 106
265         
266         def _check_kids(children):
267             self.failUnlessEqual(set(children.keys()),
268-                                 set([u"one", u"two", u"mut", u"fut", u"fro", u"empty_litdir", u"tiny_litdir"]))
269+                                 set([u"one", u"two", u"mut", u"fut", u"fro", u"fut-unic", u"fro-unic", u"empty_litdir", u"tiny_litdir"]))
270             one_node, one_metadata = children[u"one"]
271             two_node, two_metadata = children[u"two"]
272             mut_node, mut_metadata = children[u"mut"]
273hunk ./src/allmydata/test/test_dirnode.py 112
274             fut_node, fut_metadata = children[u"fut"]
275             fro_node, fro_metadata = children[u"fro"]
276+            futna_node, futna_metadata = children[u"fut-unic"]
277+            frona_node, frona_metadata = children[u"fro-unic"]
278             emptylit_node, emptylit_metadata = children[u"empty_litdir"]
279             tinylit_node, tinylit_metadata = children[u"tiny_litdir"]
280             
281hunk ./src/allmydata/test/test_dirnode.py 135
282             self.failUnlessEqual(fut_node.get_uri(), future_write_uri)
283             self.failUnlessEqual(fut_node.get_readonly_uri(), "ro." + future_read_uri)
284             self.failUnless(isinstance(fut_metadata, dict), fut_metadata)
285-           
286+
287+            self.failUnless(futna_node.is_unknown())
288+            self.failUnlessEqual(futna_node.get_uri(), future_nonascii_write_uri)
289+            self.failUnlessEqual(futna_node.get_readonly_uri(), "ro." + future_nonascii_read_uri)
290+            self.failUnless(isinstance(futna_metadata, dict), futna_metadata)
291+
292             self.failUnless(fro_node.is_unknown())
293             self.failUnlessEqual(fro_node.get_uri(), "ro." + future_read_uri)
294             self.failUnlessEqual(fut_node.get_readonly_uri(), "ro." + future_read_uri)
295hunk ./src/allmydata/test/test_dirnode.py 146
296             self.failUnless(isinstance(fro_metadata, dict), fro_metadata)
297 
298+            self.failUnless(frona_node.is_unknown())
299+            self.failUnlessEqual(frona_node.get_uri(), "ro." + future_nonascii_read_uri)
300+            self.failUnlessEqual(futna_node.get_readonly_uri(), "ro." + future_nonascii_read_uri)
301+            self.failUnless(isinstance(frona_metadata, dict), frona_metadata)
302+
303             self.failIf(emptylit_node.is_unknown())
304             self.failUnlessEqual(emptylit_node.get_storage_index(), None)
305             self.failIf(tinylit_node.is_unknown())
306hunk ./src/allmydata/test/test_dirnode.py 200
307                 u"two": (nm.create_from_cap(setup_py_uri),
308                          {"metakey": "metavalue"}),
309                 u"fut": (nm.create_from_cap(None, future_read_uri), {}),
310+                u"futna": (nm.create_from_cap(None, future_nonascii_read_uri), {}),
311                 u"empty_litdir": (nm.create_from_cap(empty_litdir_uri), {}),
312                 u"tiny_litdir": (nm.create_from_cap(tiny_litdir_uri), {}),
313                 }
314hunk ./src/allmydata/test/test_dirnode.py 223
315         
316         def _check_kids(children):
317             self.failUnlessEqual(set(children.keys()),
318-                                 set([u"one", u"two", u"fut", u"empty_litdir", u"tiny_litdir"]))
319+                                 set([u"one", u"two", u"fut", u"futna", u"empty_litdir", u"tiny_litdir"]))
320             one_node, one_metadata = children[u"one"]
321             two_node, two_metadata = children[u"two"]
322             fut_node, fut_metadata = children[u"fut"]
323hunk ./src/allmydata/test/test_dirnode.py 227
324+            futna_node, futna_metadata = children[u"futna"]
325             emptylit_node, emptylit_metadata = children[u"empty_litdir"]
326             tinylit_node, tinylit_metadata = children[u"tiny_litdir"]
327 
328hunk ./src/allmydata/test/test_dirnode.py 246
329             self.failUnlessEqual(fut_node.get_readonly_uri(), "imm." + future_read_uri)
330             self.failUnless(isinstance(fut_metadata, dict), fut_metadata)
331 
332+            self.failUnless(futna_node.is_unknown())
333+            self.failUnlessEqual(futna_node.get_uri(), "imm." + future_nonascii_read_uri)
334+            self.failUnlessEqual(futna_node.get_readonly_uri(), "imm." + future_nonascii_read_uri)
335+            self.failUnless(isinstance(futna_metadata, dict), futna_metadata)
336+
337             self.failIf(emptylit_node.is_unknown())
338             self.failUnlessEqual(emptylit_node.get_storage_index(), None)
339             self.failIf(tinylit_node.is_unknown())
340hunk ./src/allmydata/test/test_dirnode.py 1304
341         # Create a mutable directory that contains unknown URI types, and make sure
342         # we tolerate them properly.
343         d = self.nodemaker.create_new_mutable_directory()
344-        future_write_uri = "x-tahoe-crazy://I_am_from_the_future."
345-        future_read_uri = "x-tahoe-crazy-readonly://I_am_from_the_future."
346-        future_imm_uri = "x-tahoe-crazy-immutable://I_am_from_the_future."
347+        future_write_uri = u"x-tahoe-crazy://I_am_from_the_future_fw-蜔쳨欝遃䝦舜琇襇邤䍏㵦☚✸킾궑蒴犏띎냔㳆㼿졨浴䒉ΐ屝稜퍙鉧迴"
348+        future_read_uri = u"x-tahoe-crazy-readonly://I_am_from_the_future_fo-ą쳨欝遃䝦舜琇襇邤䍏㵦☚✸킾궑蒴犏띎냔㳆㼿졨浴䒉ΐ屝稜퍙鉧迴"
349+        future_imm_uri = u"x-tahoe-crazy-immutable://I_am_from_the_future_fi-Ā쳨欝遃䝦舜琇襇邤䍏㵦☚✸킾궑蒴犏띎냔㳆㼿졨浴䒉ΐ屝稜퍙鉧迴"
350         future_node = UnknownNode(future_write_uri, future_read_uri)
351         def _then(n):
352             self._node = n
353hunk ./src/allmydata/test/test_uri.py 1
354+# -*- coding: utf-8 -*-
355 
356 from twisted.trial import unittest
357 from allmydata import uri
358hunk ./src/allmydata/test/test_uri.py 233
359         self.failUnless(u2.get_readonly() is None)
360         self.failUnless(isinstance(u2.get_error(), CapConstraintError))
361 
362+        # Future caps might have non-ASCII chars in them. (Or maybe not, who can tell about the future?)
363+        future_uri = u"I am a cap from the †‣‡ future. Whatever you "
364+        u = uri.from_string(future_uri)
365+        self.failUnless(isinstance(u, uri.UnknownURI))
366+        self.failUnlessEqual(u.to_string(), future_uri)
367+        self.failUnless(u.get_readonly() is None)
368+        self.failUnless(u.get_error() is None)
369+
370+        u2 = uri.UnknownURI(future_uri, error=CapConstraintError("..."))
371+        self.failUnlessEqual(u.to_string(), future_uri)
372+        self.failUnless(u2.get_readonly() is None)
373+        self.failUnless(isinstance(u2.get_error(), CapConstraintError))
374+
375 class Constraint(unittest.TestCase):
376     def test_constraint(self):
377        good="http://127.0.0.1:3456/uri/URI%3ADIR2%3Agh3l5rbvnv2333mrfvalmjfr4i%3Alz6l7u3z3b7g37s4zkdmfpx5ly4ib4m6thrpbusi6ys62qtc6mma/"
378hunk ./src/allmydata/test/test_web.py 1
379+# -*- coding: utf-8 -*-
380+
381 import os.path, re, urllib
382 import simplejson
383 from StringIO import StringIO
384hunk ./src/allmydata/test/test_web.py 40
385 
386 timeout = 480 # Most of these take longer than 240 seconds on Francois's arm box.
387 
388-unknown_rwcap = "lafs://from_the_future"
389-unknown_rocap = "ro.lafs://readonly_from_the_future"
390-unknown_immcap = "imm.lafs://immutable_from_the_future"
391+unknown_rwcap = u"lafs://from_the_future_fw-蜔쳨欝遃䝦舜琇襇邤䍏㵦☚✸킾궑蒴犏띎냔㳆㼿졨浴䒉ΐ屝稜퍙鉧迴"
392+unknown_rocap = u"ro.lafs://readonly_from_the_future_fo-ą쳨欝遃䝦舜琇襇邤䍏㵦☚✸킾궑蒴犏띎냔㳆㼿졨浴䒉ΐ屝稜퍙鉧迴"
393+unknown_immcap = u"imm.lafs://immutable_from_the_future_fi-‡쳨欝遃䝦舜琇襇邤䍏㵦☚✸킾궑蒴犏띎냔㳆㼿졨浴䒉ΐ屝稜퍙鉧迴"
394 
395 class FakeStatsProvider:
396     def get_stats(self):
397}
398
399Context:
400
401[docs: line-wrap README.txt
402zooko@zooko.com**20100518174240
403 Ignore-this: 670a02d360df7de51ebdcf4fae752577
404] 
405[Hush pyflakes warnings
406Kevan Carstensen <kevan@isnotajoke.com>**20100515184344
407 Ignore-this: fd602c3bba115057770715c36a87b400
408] 
409[setup: new improved misc/show-tool-versions.py
410zooko@zooko.com**20100516050122
411 Ignore-this: ce9b1de1b35b07d733e6cf823b66335a
412] 
413[Improve code coverage of the Tahoe2PeerSelector tests.
414Kevan Carstensen <kevan@isnotajoke.com>**20100515032913
415 Ignore-this: 793151b63ffa65fdae6915db22d9924a
416] 
417[Remove a comment that no longer makes sense.
418Kevan Carstensen <kevan@isnotajoke.com>**20100514203516
419 Ignore-this: 956983c7e7c7e4477215494dfce8f058
420] 
421[docs: update docs/architecture.txt to more fully and correctly explain the upload procedure
422zooko@zooko.com**20100514043458
423 Ignore-this: 538b6ea256a49fed837500342092efa3
424] 
425[Fix up the behavior of #778, per reviewers' comments
426Kevan Carstensen <kevan@isnotajoke.com>**20100514004917
427 Ignore-this: 9c20b60716125278b5456e8feb396bff
428 
429   - Make some important utility functions clearer and more thoroughly
430     documented.
431   - Assert in upload.servers_of_happiness that the buckets attributes
432     of PeerTrackers passed to it are mutually disjoint.
433   - Get rid of some silly non-Pythonisms that I didn't see when I first
434     wrote these patches.
435   - Make sure that should_add_server returns true when queried about a
436     shnum that it doesn't know about yet.
437   - Change Tahoe2PeerSelector.preexisting_shares to map a shareid to a set
438     of peerids, alter dependencies to deal with that.
439   - Remove upload.should_add_servers, because it is no longer necessary
440   - Move upload.shares_of_happiness and upload.shares_by_server to a utility
441     file.
442   - Change some points in Tahoe2PeerSelector.
443   - Compute servers_of_happiness using a bipartite matching algorithm that
444     we know is optimal instead of an ad-hoc greedy algorithm that isn't.
445   - Change servers_of_happiness to just take a sharemap as an argument,
446     change its callers to merge existing_shares and used_peers before
447     calling it.
448   - Change an error message in the encoder to be more appropriate for
449     servers of happiness.
450   - Clarify the wording of an error message in immutable/upload.py
451   - Refactor a happiness failure message to happinessutil.py, and make
452     immutable/upload.py and immutable/encode.py use it.
453   - Move the word "only" as far to the right as possible in failure
454     messages.
455   - Use a better definition of progress during peer selection.
456   - Do read-only peer share detection queries in parallel, not sequentially.
457   - Clean up logging semantics; print the query statistics whenever an
458     upload is unsuccessful, not just in one case.
459 
460] 
461[Alter the error message when an upload fails, per some comments in #778.
462Kevan Carstensen <kevan@isnotajoke.com>**20091230210344
463 Ignore-this: ba97422b2f9737c46abeb828727beb1
464 
465 When I first implemented #778, I just altered the error messages to refer to
466 servers where they referred to shares. The resulting error messages weren't
467 very good. These are a bit better.
468] 
469[Change "UploadHappinessError" to "UploadUnhappinessError"
470Kevan Carstensen <kevan@isnotajoke.com>**20091205043037
471 Ignore-this: 236b64ab19836854af4993bb5c1b221a
472] 
473[Alter the error message returned when peer selection fails
474Kevan Carstensen <kevan@isnotajoke.com>**20091123002405
475 Ignore-this: b2a7dc163edcab8d9613bfd6907e5166
476 
477 The Tahoe2PeerSelector returned either NoSharesError or NotEnoughSharesError
478 for a variety of error conditions that weren't informatively described by them.
479 This patch creates a new error, UploadHappinessError, replaces uses of
480 NoSharesError and NotEnoughSharesError with it, and alters the error message
481 raised with the errors to be more in line with the new servers_of_happiness
482 behavior. See ticket #834 for more information.
483] 
484[Eliminate overcounting iof servers_of_happiness in Tahoe2PeerSelector; also reorganize some things.
485Kevan Carstensen <kevan@isnotajoke.com>**20091118014542
486 Ignore-this: a6cb032cbff74f4f9d4238faebd99868
487] 
488[Change stray "shares_of_happiness" to "servers_of_happiness"
489Kevan Carstensen <kevan@isnotajoke.com>**20091116212459
490 Ignore-this: 1c971ba8c3c4d2e7ba9f020577b28b73
491] 
492[Alter Tahoe2PeerSelector to make sure that it recognizes existing shares on readonly servers, fixing an issue in #778
493Kevan Carstensen <kevan@isnotajoke.com>**20091116192805
494 Ignore-this: 15289f4d709e03851ed0587b286fd955
495] 
496[Alter 'immutable/encode.py' and 'immutable/upload.py' to use servers_of_happiness instead of shares_of_happiness.
497Kevan Carstensen <kevan@isnotajoke.com>**20091104111222
498 Ignore-this: abb3283314820a8bbf9b5d0cbfbb57c8
499] 
500[Alter the signature of set_shareholders in IEncoder to add a 'servermap' parameter, which gives IEncoders enough information to perform a sane check for servers_of_happiness.
501Kevan Carstensen <kevan@isnotajoke.com>**20091104033241
502 Ignore-this: b3a6649a8ac66431beca1026a31fed94
503] 
504[Alter CiphertextDownloader to work with servers_of_happiness
505Kevan Carstensen <kevan@isnotajoke.com>**20090924041932
506 Ignore-this: e81edccf0308c2d3bedbc4cf217da197
507] 
508[Revisions of the #778 tests, per reviewers' comments
509Kevan Carstensen <kevan@isnotajoke.com>**20100514012542
510 Ignore-this: 735bbc7f663dce633caeb3b66a53cf6e
511 
512 - Fix comments and confusing naming.
513 - Add tests for the new error messages suggested by David-Sarah
514   and Zooko.
515 - Alter existing tests for new error messages.
516 - Make sure that the tests continue to work with the trunk.
517 - Add a test for a mutual disjointedness assertion that I added to
518   upload.servers_of_happiness.
519 - Fix the comments to correctly reflect read-onlyness
520 - Add a test for an edge case in should_add_server
521 - Add an assertion to make sure that share redistribution works as it
522   should
523 - Alter tests to work with revised servers_of_happiness semantics
524 - Remove tests for should_add_server, since that function no longer exists.
525 - Alter tests to know about merge_peers, and to use it before calling
526   servers_of_happiness.
527 - Add tests for merge_peers.
528 - Add Zooko's puzzles to the tests.
529 - Edit encoding tests to expect the new kind of failure message.
530 - Edit tests to expect error messages with the word "only" moved as far
531   to the right as possible.
532 - Extended and cleaned up some helper functions.
533 - Changed some tests to call more appropriate helper functions.
534 - Added a test for the failing redistribution algorithm
535 - Added a test for the progress message
536 - Added a test for the upper bound on readonly peer share discovery.
537 
538] 
539[Alter various unit tests to work with the new happy behavior
540Kevan Carstensen <kevan@isnotajoke.com>**20100107181325
541 Ignore-this: 132032bbf865e63a079f869b663be34a
542] 
543[Replace "UploadHappinessError" with "UploadUnhappinessError" in tests.
544Kevan Carstensen <kevan@isnotajoke.com>**20091205043453
545 Ignore-this: 83f4bc50c697d21b5f4e2a4cd91862ca
546] 
547[Add tests for the behavior described in #834.
548Kevan Carstensen <kevan@isnotajoke.com>**20091123012008
549 Ignore-this: d8e0aa0f3f7965ce9b5cea843c6d6f9f
550] 
551[Re-work 'test_upload.py' to be more readable; add more tests for #778
552Kevan Carstensen <kevan@isnotajoke.com>**20091116192334
553 Ignore-this: 7e8565f92fe51dece5ae28daf442d659
554] 
555[Test Tahoe2PeerSelector to make sure that it recognizeses existing shares on readonly servers
556Kevan Carstensen <kevan@isnotajoke.com>**20091109003735
557 Ignore-this: 12f9b4cff5752fca7ed32a6ebcff6446
558] 
559[Add more tests for comment:53 in ticket #778
560Kevan Carstensen <kevan@isnotajoke.com>**20091104112849
561 Ignore-this: 3bb2edd299a944cc9586e14d5d83ec8c
562] 
563[Add a test for upload.shares_by_server
564Kevan Carstensen <kevan@isnotajoke.com>**20091104111324
565 Ignore-this: f9802e82d6982a93e00f92e0b276f018
566] 
567[Minor tweak to an existing test -- make the first server read-write, instead of read-only
568Kevan Carstensen <kevan@isnotajoke.com>**20091104034232
569 Ignore-this: a951a46c93f7f58dd44d93d8623b2aee
570] 
571[Alter tests to use the new form of set_shareholders
572Kevan Carstensen <kevan@isnotajoke.com>**20091104033602
573 Ignore-this: 3deac11fc831618d11441317463ef830
574] 
575[Refactor some behavior into a mixin, and add tests for the behavior described in #778
576"Kevan Carstensen" <kevan@isnotajoke.com>**20091030091908
577 Ignore-this: a6f9797057ca135579b249af3b2b66ac
578] 
579[Alter NoNetworkGrid to allow the creation of readonly servers for testing purposes.
580Kevan Carstensen <kevan@isnotajoke.com>**20091018013013
581 Ignore-this: e12cd7c4ddeb65305c5a7e08df57c754
582] 
583[Update 'docs/architecture.txt' to reflect readonly share discovery
584kevan@isnotajoke.com**20100514003852
585 Ignore-this: 7ead71b34df3b1ecfdcfd3cb2882e4f9
586] 
587[Alter the wording in docs/architecture.txt to more accurately describe the servers_of_happiness behavior.
588Kevan Carstensen <kevan@isnotajoke.com>**20100428002455
589 Ignore-this: 6eff7fa756858a1c6f73728d989544cc
590] 
591[Alter wording in 'interfaces.py' to be correct wrt #778
592"Kevan Carstensen" <kevan@isnotajoke.com>**20091205034005
593 Ignore-this: c9913c700ac14e7a63569458b06980e0
594] 
595[Update 'docs/configuration.txt' to reflect the servers_of_happiness behavior.
596Kevan Carstensen <kevan@isnotajoke.com>**20091205033813
597 Ignore-this: 5e1cb171f8239bfb5b565d73c75ac2b8
598] 
599[Clarify quickstart instructions for installing pywin32
600david-sarah@jacaranda.org**20100511180300
601 Ignore-this: d4668359673600d2acbc7cd8dd44b93c
602] 
603[web: add a simple test that you can load directory.xhtml
604zooko@zooko.com**20100510063729
605 Ignore-this: e49b25fa3c67b3c7a56c8b1ae01bb463
606] 
607[setup: fix typos in misc/show-tool-versions.py
608zooko@zooko.com**20100510063615
609 Ignore-this: 2181b1303a0e288e7a9ebd4c4855628
610] 
611[setup: show code-coverage tool versions in show-tools-versions.py
612zooko@zooko.com**20100510062955
613 Ignore-this: 4b4c68eb3780b762c8dbbd22b39df7cf
614] 
615[Dependency on Windmill test framework is not needed yet.
616david-sarah@jacaranda.org**20100504161043
617 Ignore-this: be088712bec650d4ef24766c0026ebc8
618] 
619[docs: update README, mv it to README.txt, update setup.py
620zooko@zooko.com**20100504094340
621 Ignore-this: 40e28ca36c299ea1fd12d3b91e5b421c
622] 
623[tests: pass z to tar so that BSD tar will know to ungzip
624zooko@zooko.com**20100504090628
625 Ignore-this: 1339e493f255e8fc0b01b70478f23a09
626] 
627[setup: update comments and URLs in setup.cfg
628zooko@zooko.com**20100504061653
629 Ignore-this: f97692807c74bcab56d33100c899f829
630] 
631[CLI: Support for https url in option --node-url
632Francois Deppierraz <francois@ctrlaltdel.ch>**20100430185609
633 Ignore-this: 1717176b4d27c877e6bc67a944d9bf34
634 
635 This patch modifies the regular expression used for verifying of '--node-url'
636 parameter.  Support for accessing a Tahoe gateway over HTTPS was already
637 present, thanks to Python's urllib.
638 
639] 
640[backupdb.did_create_directory: use REPLACE INTO, not INSERT INTO + ignore error
641Brian Warner <warner@lothar.com>**20100428050803
642 Ignore-this: 1fca7b8f364a21ae413be8767161e32f
643 
644 This handles the case where we upload a new tahoe directory for a
645 previously-processed local directory, possibly creating a new dircap (if the
646 metadata had changed). Now we replace the old dirhash->dircap record. The
647 previous behavior left the old record in place (with the old dircap and
648 timestamps), so we'd never stop creating new directories and never converge
649 on a null backup.
650] 
651["tahoe webopen": add --info flag, to get ?t=info
652Brian Warner <warner@lothar.com>**20100424233003
653 Ignore-this: 126b0bb6db340fabacb623d295eb45fa
654 
655 Also fix some trailing whitespace.
656] 
657[setup: reorder and extend the show-tool-versions script, the better to glean information about our new buildslaves
658zooko@zooko.com**20100504045643
659 Ignore-this: 836084b56b8d4ee8f1de1f4efb706d36
660] 
661[docs: install.html http-equiv refresh to quickstart.html
662zooko@zooko.com**20100421165708
663 Ignore-this: 52b4b619f9dde5886ae2cd7f1f3b734b
664] 
665[docs: install.html -> quickstart.html
666zooko@zooko.com**20100421155757
667 Ignore-this: 6084e203909306bed93efb09d0e6181d
668 It is not called "installing" because that implies that it is going to change the configuration of your operating system. It is not called "building" because that implies that you need developer tools like a compiler. Also I added a stern warning against looking at the "InstallDetails" wiki page, which I have renamed to "AdvancedInstall".
669] 
670[Fix another typo in tahoe_storagespace munin plugin
671david-sarah@jacaranda.org**20100416220935
672 Ignore-this: ad1f7aa66b554174f91dfb2b7a3ea5f3
673] 
674[Add dependency on windmill >= 1.3
675david-sarah@jacaranda.org**20100416190404
676 Ignore-this: 4437a7a464e92d6c9012926b18676211
677] 
678[licensing: phrase the OpenSSL-exemption in the vocabulary of copyright instead of computer technology, and replicate the exemption from the GPL to the TGPPL
679zooko@zooko.com**20100414232521
680 Ignore-this: a5494b2f582a295544c6cad3f245e91
681] 
682[munin-tahoe_storagespace
683freestorm77@gmail.com**20100221203626
684 Ignore-this: 14d6d6a587afe1f8883152bf2e46b4aa
685 
686 Plugin configuration rename
687 
688] 
689[setup: add licensing declaration for setuptools (noticed by the FSF compliance folks)
690zooko@zooko.com**20100309184415
691 Ignore-this: 2dfa7d812d65fec7c72ddbf0de609ccb
692] 
693[setup: fix error in licensing declaration from Shawn Willden, as noted by the FSF compliance division
694zooko@zooko.com**20100309163736
695 Ignore-this: c0623d27e469799d86cabf67921a13f8
696] 
697[CREDITS to Jacob Appelbaum
698zooko@zooko.com**20100304015616
699 Ignore-this: 70db493abbc23968fcc8db93f386ea54
700] 
701[desert-island-build-with-proper-versions
702jacob@appelbaum.net**20100304013858] 
703[docs: a few small edits to try to guide newcomers through the docs
704zooko@zooko.com**20100303231902
705 Ignore-this: a6aab44f5bf5ad97ea73e6976bc4042d
706 These edits were suggested by my watching over Jake Appelbaum's shoulder as he completely ignored/skipped/missed install.html and also as he decided that debian.txt wouldn't help him with basic installation. Then I threw in a few docs edits that have been sitting around in my sandbox asking to be committed for months.
707] 
708[TAG allmydata-tahoe-1.6.1
709david-sarah@jacaranda.org**20100228062314
710 Ignore-this: eb5f03ada8ea953ee7780e7fe068539
711] 
712Patch bundle hash:
7138d679b706a82f068012361b83fdf2ba6c860595f