3 from twisted.trial import unittest
4 from twisted.application import service
5 from twisted.python import log
8 from allmydata import client
9 from allmydata.storage_client import StorageFarmBroker
10 from allmydata.util import base32, fileutil
11 from allmydata.interfaces import IFilesystemNode, IFileNode, \
12 IImmutableFileNode, IMutableFileNode, IDirectoryNode
13 from foolscap.api import flushEventualQueue
14 import allmydata.test.common_util as testutil
16 BASECONFIG = ("[client]\n"
17 "introducer.furl = \n"
20 class Basic(testutil.ReallyEqualMixin, unittest.TestCase):
21 def test_loadable(self):
22 basedir = "test_client.Basic.test_loadable"
24 open(os.path.join(basedir, "introducer.furl"), "w").write("")
25 client.Client(basedir)
27 def test_loadable_old_config_bits(self):
28 basedir = "test_client.Basic.test_loadable_old_config_bits"
30 open(os.path.join(basedir, "introducer.furl"), "w").write("")
31 open(os.path.join(basedir, "no_storage"), "w").write("")
32 open(os.path.join(basedir, "readonly_storage"), "w").write("")
33 open(os.path.join(basedir, "debug_discard_storage"), "w").write("")
34 c = client.Client(basedir)
36 c.getServiceNamed("storage")
37 self.fail("that was supposed to fail")
41 def test_loadable_old_storage_config_bits(self):
42 basedir = "test_client.Basic.test_loadable_old_storage_config_bits"
44 open(os.path.join(basedir, "introducer.furl"), "w").write("")
45 open(os.path.join(basedir, "readonly_storage"), "w").write("")
46 open(os.path.join(basedir, "debug_discard_storage"), "w").write("")
47 c = client.Client(basedir)
48 s = c.getServiceNamed("storage")
49 self.failUnless(s.no_storage)
50 self.failUnless(s.readonly_storage)
52 def test_secrets(self):
53 basedir = "test_client.Basic.test_secrets"
55 open(os.path.join(basedir, "introducer.furl"), "w").write("")
56 c = client.Client(basedir)
57 secret_fname = os.path.join(basedir, "private", "secret")
58 self.failUnless(os.path.exists(secret_fname), secret_fname)
59 renew_secret = c.get_renewal_secret()
60 self.failUnless(base32.b2a(renew_secret))
61 cancel_secret = c.get_cancel_secret()
62 self.failUnless(base32.b2a(cancel_secret))
64 def test_reserved_1(self):
65 basedir = "client.Basic.test_reserved_1"
67 f = open(os.path.join(basedir, "tahoe.cfg"), "w")
69 f.write("[storage]\n")
70 f.write("enabled = true\n")
71 f.write("reserved_space = 1000\n")
73 c = client.Client(basedir)
74 self.failUnlessEqual(c.getServiceNamed("storage").reserved_space, 1000)
76 def test_reserved_2(self):
77 basedir = "client.Basic.test_reserved_2"
79 f = open(os.path.join(basedir, "tahoe.cfg"), "w")
81 f.write("[storage]\n")
82 f.write("enabled = true\n")
83 f.write("reserved_space = 10K\n")
85 c = client.Client(basedir)
86 self.failUnlessEqual(c.getServiceNamed("storage").reserved_space, 10*1000)
88 def test_reserved_3(self):
89 basedir = "client.Basic.test_reserved_3"
91 f = open(os.path.join(basedir, "tahoe.cfg"), "w")
93 f.write("[storage]\n")
94 f.write("enabled = true\n")
95 f.write("reserved_space = 5mB\n")
97 c = client.Client(basedir)
98 self.failUnlessEqual(c.getServiceNamed("storage").reserved_space,
101 def test_reserved_4(self):
102 basedir = "client.Basic.test_reserved_4"
104 f = open(os.path.join(basedir, "tahoe.cfg"), "w")
106 f.write("[storage]\n")
107 f.write("enabled = true\n")
108 f.write("reserved_space = 78Gb\n")
110 c = client.Client(basedir)
111 self.failUnlessEqual(c.getServiceNamed("storage").reserved_space,
114 def test_reserved_bad(self):
115 basedir = "client.Basic.test_reserved_bad"
117 f = open(os.path.join(basedir, "tahoe.cfg"), "w")
119 f.write("[storage]\n")
120 f.write("enabled = true\n")
121 f.write("reserved_space = bogus\n")
123 c = client.Client(basedir)
124 self.failUnlessEqual(c.getServiceNamed("storage").reserved_space, 0)
126 def _permute(self, sb, key):
127 return [ s.get_serverid() for s in sb.get_servers_for_psi(key) ]
129 def test_permute(self):
130 sb = StorageFarmBroker(None, True)
131 for k in ["%d" % i for i in range(5)]:
132 sb.test_add_rref(k, "rref")
134 self.failUnlessReallyEqual(self._permute(sb, "one"), ['3','1','0','4','2'])
135 self.failUnlessReallyEqual(self._permute(sb, "two"), ['0','4','2','1','3'])
137 self.failUnlessReallyEqual(self._permute(sb, "one"), [])
139 def test_versions(self):
140 basedir = "test_client.Basic.test_versions"
142 open(os.path.join(basedir, "introducer.furl"), "w").write("")
143 c = client.Client(basedir)
144 ss = c.getServiceNamed("storage")
145 verdict = ss.remote_get_version()
146 self.failUnlessReallyEqual(verdict["application-version"],
147 str(allmydata.__full_version__))
148 self.failIfEqual(str(allmydata.__version__), "unknown")
149 self.failUnless("." in str(allmydata.__full_version__),
150 "non-numeric version in '%s'" % allmydata.__version__)
151 all_versions = allmydata.get_package_versions_string()
152 self.failUnless(allmydata.__appname__ in all_versions)
153 log.msg("tahoe versions: %s" % all_versions)
155 stats = c.get_stats()
156 self.failUnless("node.uptime" in stats)
157 self.failUnless(isinstance(stats["node.uptime"], float))
159 def flush_but_dont_ignore(res):
160 d = flushEventualQueue()
166 class Run(unittest.TestCase, testutil.StallMixin):
169 self.sparent = service.MultiService()
170 self.sparent.startService()
172 d = self.sparent.stopService()
173 d.addBoth(flush_but_dont_ignore)
176 def test_loadable(self):
177 basedir = "test_client.Run.test_loadable"
179 dummy = "pb://wl74cyahejagspqgy4x5ukrvfnevlknt@127.0.0.1:58889/bogus"
180 open(os.path.join(basedir, "introducer.furl"), "w").write(dummy)
181 open(os.path.join(basedir, "suicide_prevention_hotline"), "w")
182 client.Client(basedir)
184 def test_reloadable(self):
185 basedir = "test_client.Run.test_reloadable"
187 dummy = "pb://wl74cyahejagspqgy4x5ukrvfnevlknt@127.0.0.1:58889/bogus"
188 open(os.path.join(basedir, "introducer.furl"), "w").write(dummy)
189 c1 = client.Client(basedir)
190 c1.setServiceParent(self.sparent)
192 # delay to let the service start up completely. I'm not entirely sure
194 d = self.stall(delay=2.0)
195 d.addCallback(lambda res: c1.disownServiceParent())
196 # the cygwin buildslave seems to need more time to let the old
197 # service completely shut down. When delay=0.1, I saw this test fail,
198 # probably due to the logport trying to reclaim the old socket
199 # number. This suggests that either we're dropping a Deferred
200 # somewhere in the shutdown sequence, or that cygwin is just cranky.
201 d.addCallback(self.stall, delay=2.0)
203 # TODO: pause for slightly over one second, to let
204 # Client._check_hotline poll the file once. That will exercise
205 # another few lines. Then add another test in which we don't
206 # update the file at all, and watch to see the node shutdown. (to
207 # do this, use a modified node which overrides Node.shutdown(),
208 # also change _check_hotline to use it instead of a raw
209 # reactor.stop, also instrument the shutdown event in an
210 # attribute that we can check)
211 c2 = client.Client(basedir)
212 c2.setServiceParent(self.sparent)
213 return c2.disownServiceParent()
214 d.addCallback(_restart)
217 class NodeMaker(testutil.ReallyEqualMixin, unittest.TestCase):
218 def test_maker(self):
219 basedir = "client/NodeMaker/maker"
220 fileutil.make_dirs(basedir)
221 f = open(os.path.join(basedir, "tahoe.cfg"), "w")
224 c = client.Client(basedir)
226 n = c.create_node_from_uri("URI:CHK:6nmrpsubgbe57udnexlkiwzmlu:bjt7j6hshrlmadjyr7otq3dc24end5meo5xcr5xe5r663po6itmq:3:10:7277")
227 self.failUnless(IFilesystemNode.providedBy(n))
228 self.failUnless(IFileNode.providedBy(n))
229 self.failUnless(IImmutableFileNode.providedBy(n))
230 self.failIf(IMutableFileNode.providedBy(n))
231 self.failIf(IDirectoryNode.providedBy(n))
232 self.failUnless(n.is_readonly())
233 self.failIf(n.is_mutable())
235 n = c.create_node_from_uri("URI:LIT:n5xgk")
236 self.failUnless(IFilesystemNode.providedBy(n))
237 self.failUnless(IFileNode.providedBy(n))
238 self.failUnless(IImmutableFileNode.providedBy(n))
239 self.failIf(IMutableFileNode.providedBy(n))
240 self.failIf(IDirectoryNode.providedBy(n))
241 self.failUnless(n.is_readonly())
242 self.failIf(n.is_mutable())
244 n = c.create_node_from_uri("URI:SSK:n6x24zd3seu725yluj75q5boaa:mm6yoqjhl6ueh7iereldqxue4nene4wl7rqfjfybqrehdqmqskvq")
245 self.failUnless(IFilesystemNode.providedBy(n))
246 self.failUnless(IFileNode.providedBy(n))
247 self.failIf(IImmutableFileNode.providedBy(n))
248 self.failUnless(IMutableFileNode.providedBy(n))
249 self.failIf(IDirectoryNode.providedBy(n))
250 self.failIf(n.is_readonly())
251 self.failUnless(n.is_mutable())
253 n = c.create_node_from_uri("URI:SSK-RO:b7sr5qsifnicca7cbk3rhrhbvq:mm6yoqjhl6ueh7iereldqxue4nene4wl7rqfjfybqrehdqmqskvq")
254 self.failUnless(IFilesystemNode.providedBy(n))
255 self.failUnless(IFileNode.providedBy(n))
256 self.failIf(IImmutableFileNode.providedBy(n))
257 self.failUnless(IMutableFileNode.providedBy(n))
258 self.failIf(IDirectoryNode.providedBy(n))
259 self.failUnless(n.is_readonly())
260 self.failUnless(n.is_mutable())
262 n = c.create_node_from_uri("URI:DIR2:n6x24zd3seu725yluj75q5boaa:mm6yoqjhl6ueh7iereldqxue4nene4wl7rqfjfybqrehdqmqskvq")
263 self.failUnless(IFilesystemNode.providedBy(n))
264 self.failIf(IFileNode.providedBy(n))
265 self.failIf(IImmutableFileNode.providedBy(n))
266 self.failIf(IMutableFileNode.providedBy(n))
267 self.failUnless(IDirectoryNode.providedBy(n))
268 self.failIf(n.is_readonly())
269 self.failUnless(n.is_mutable())
271 n = c.create_node_from_uri("URI:DIR2-RO:b7sr5qsifnicca7cbk3rhrhbvq:mm6yoqjhl6ueh7iereldqxue4nene4wl7rqfjfybqrehdqmqskvq")
272 self.failUnless(IFilesystemNode.providedBy(n))
273 self.failIf(IFileNode.providedBy(n))
274 self.failIf(IImmutableFileNode.providedBy(n))
275 self.failIf(IMutableFileNode.providedBy(n))
276 self.failUnless(IDirectoryNode.providedBy(n))
277 self.failUnless(n.is_readonly())
278 self.failUnless(n.is_mutable())
280 unknown_rw = "lafs://from_the_future"
281 unknown_ro = "lafs://readonly_from_the_future"
282 n = c.create_node_from_uri(unknown_rw, unknown_ro)
283 self.failUnless(IFilesystemNode.providedBy(n))
284 self.failIf(IFileNode.providedBy(n))
285 self.failIf(IImmutableFileNode.providedBy(n))
286 self.failIf(IMutableFileNode.providedBy(n))
287 self.failIf(IDirectoryNode.providedBy(n))
288 self.failUnless(n.is_unknown())
289 self.failUnlessReallyEqual(n.get_uri(), unknown_rw)
290 self.failUnlessReallyEqual(n.get_write_uri(), unknown_rw)
291 self.failUnlessReallyEqual(n.get_readonly_uri(), "ro." + unknown_ro)
293 # Note: it isn't that we *intend* to deploy non-ASCII caps in
294 # the future, it is that we want to make sure older Tahoe-LAFS
295 # versions wouldn't choke on them if we were to do so. See
296 # #1051 and wiki:NewCapDesign for details.
297 unknown_rw = u"lafs://from_the_future_rw_\u263A".encode('utf-8')
298 unknown_ro = u"lafs://readonly_from_the_future_ro_\u263A".encode('utf-8')
299 n = c.create_node_from_uri(unknown_rw, unknown_ro)
300 self.failUnless(IFilesystemNode.providedBy(n))
301 self.failIf(IFileNode.providedBy(n))
302 self.failIf(IImmutableFileNode.providedBy(n))
303 self.failIf(IMutableFileNode.providedBy(n))
304 self.failIf(IDirectoryNode.providedBy(n))
305 self.failUnless(n.is_unknown())
306 self.failUnlessReallyEqual(n.get_uri(), unknown_rw)
307 self.failUnlessReallyEqual(n.get_write_uri(), unknown_rw)
308 self.failUnlessReallyEqual(n.get_readonly_uri(), "ro." + unknown_ro)