]> git.rkrishnan.org Git - tahoe-lafs/tahoe-lafs.git/blob - src/allmydata/test/test_client.py
big rework of introducer client: change local API, split division of responsibilites...
[tahoe-lafs/tahoe-lafs.git] / src / allmydata / test / test_client.py
1
2 import os
3 from twisted.trial import unittest
4 from twisted.application import service
5 from twisted.python import log
6
7 import allmydata
8 from allmydata import client
9 from allmydata.storage_client import StorageFarmBroker
10 from allmydata.introducer.client import IntroducerClient
11 from allmydata.util import base32
12 from foolscap.api import flushEventualQueue
13 import common_util as testutil
14
15 class FakeIntroducerClient(IntroducerClient):
16     def __init__(self):
17         self._connections = set()
18     def add_peer(self, nodeid):
19         entry = (nodeid, "storage", "rref")
20         self._connections.add(entry)
21     def remove_all_peers(self):
22         self._connections.clear()
23
24 class Basic(unittest.TestCase):
25     def test_loadable(self):
26         basedir = "test_client.Basic.test_loadable"
27         os.mkdir(basedir)
28         open(os.path.join(basedir, "introducer.furl"), "w").write("")
29         open(os.path.join(basedir, "vdrive.furl"), "w").write("")
30         c = client.Client(basedir)
31
32     def test_loadable_without_vdrive(self):
33         basedir = "test_client.Basic.test_loadable_without_vdrive"
34         os.mkdir(basedir)
35         open(os.path.join(basedir, "introducer.furl"), "w").write("")
36         c = client.Client(basedir)
37
38     def test_loadable_old_config_bits(self):
39         basedir = "test_client.Basic.test_loadable_old_config_bits"
40         os.mkdir(basedir)
41         open(os.path.join(basedir, "introducer.furl"), "w").write("")
42         open(os.path.join(basedir, "vdrive.furl"), "w").write("")
43         open(os.path.join(basedir, "no_storage"), "w").write("")
44         open(os.path.join(basedir, "readonly_storage"), "w").write("")
45         open(os.path.join(basedir, "debug_discard_storage"), "w").write("")
46         c = client.Client(basedir)
47         try:
48             c.getServiceNamed("storage")
49             self.fail("that was supposed to fail")
50         except KeyError:
51             pass
52
53     def test_loadable_old_storage_config_bits(self):
54         basedir = "test_client.Basic.test_loadable_old_storage_config_bits"
55         os.mkdir(basedir)
56         open(os.path.join(basedir, "introducer.furl"), "w").write("")
57         open(os.path.join(basedir, "vdrive.furl"), "w").write("")
58         open(os.path.join(basedir, "readonly_storage"), "w").write("")
59         open(os.path.join(basedir, "debug_discard_storage"), "w").write("")
60         c = client.Client(basedir)
61         s = c.getServiceNamed("storage")
62         self.failUnless(s.no_storage)
63         self.failUnless(s.readonly_storage)
64
65     def test_secrets(self):
66         basedir = "test_client.Basic.test_secrets"
67         os.mkdir(basedir)
68         open(os.path.join(basedir, "introducer.furl"), "w").write("")
69         open(os.path.join(basedir, "vdrive.furl"), "w").write("")
70         c = client.Client(basedir)
71         secret_fname = os.path.join(basedir, "private", "secret")
72         self.failUnless(os.path.exists(secret_fname), secret_fname)
73         renew_secret = c.get_renewal_secret()
74         self.failUnless(base32.b2a(renew_secret))
75         cancel_secret = c.get_cancel_secret()
76         self.failUnless(base32.b2a(cancel_secret))
77
78     BASECONFIG = ("[client]\n"
79                   "introducer.furl = \n"
80                   )
81
82     def test_reserved_1(self):
83         basedir = "client.Basic.test_reserved_1"
84         os.mkdir(basedir)
85         f = open(os.path.join(basedir, "tahoe.cfg"), "w")
86         f.write(self.BASECONFIG)
87         f.write("[storage]\n")
88         f.write("enabled = true\n")
89         f.write("reserved_space = 1000\n")
90         f.close()
91         c = client.Client(basedir)
92         self.failUnlessEqual(c.getServiceNamed("storage").reserved_space, 1000)
93
94     def test_reserved_2(self):
95         basedir = "client.Basic.test_reserved_2"
96         os.mkdir(basedir)
97         f = open(os.path.join(basedir, "tahoe.cfg"), "w")
98         f.write(self.BASECONFIG)
99         f.write("[storage]\n")
100         f.write("enabled = true\n")
101         f.write("reserved_space = 10K\n")
102         f.close()
103         c = client.Client(basedir)
104         self.failUnlessEqual(c.getServiceNamed("storage").reserved_space, 10*1000)
105
106     def test_reserved_3(self):
107         basedir = "client.Basic.test_reserved_3"
108         os.mkdir(basedir)
109         f = open(os.path.join(basedir, "tahoe.cfg"), "w")
110         f.write(self.BASECONFIG)
111         f.write("[storage]\n")
112         f.write("enabled = true\n")
113         f.write("reserved_space = 5mB\n")
114         f.close()
115         c = client.Client(basedir)
116         self.failUnlessEqual(c.getServiceNamed("storage").reserved_space,
117                              5*1000*1000)
118
119     def test_reserved_4(self):
120         basedir = "client.Basic.test_reserved_4"
121         os.mkdir(basedir)
122         f = open(os.path.join(basedir, "tahoe.cfg"), "w")
123         f.write(self.BASECONFIG)
124         f.write("[storage]\n")
125         f.write("enabled = true\n")
126         f.write("reserved_space = 78Gb\n")
127         f.close()
128         c = client.Client(basedir)
129         self.failUnlessEqual(c.getServiceNamed("storage").reserved_space,
130                              78*1000*1000*1000)
131
132     def test_reserved_bad(self):
133         basedir = "client.Basic.test_reserved_bad"
134         os.mkdir(basedir)
135         f = open(os.path.join(basedir, "tahoe.cfg"), "w")
136         f.write(self.BASECONFIG)
137         f.write("[storage]\n")
138         f.write("enabled = true\n")
139         f.write("reserved_space = bogus\n")
140         f.close()
141         c = client.Client(basedir)
142         self.failUnlessEqual(c.getServiceNamed("storage").reserved_space, 0)
143
144     def _permute(self, sb, key):
145         return [ peerid
146                  for (peerid,rref) in sb.get_servers_for_index(key) ]
147
148     def test_permute(self):
149         sb = StorageFarmBroker(None, True)
150         for k in ["%d" % i for i in range(5)]:
151             sb.test_add_server(k, None)
152
153         self.failUnlessEqual(self._permute(sb, "one"), ['3','1','0','4','2'])
154         self.failUnlessEqual(self._permute(sb, "two"), ['0','4','2','1','3'])
155         sb.test_servers.clear()
156         self.failUnlessEqual(self._permute(sb, "one"), [])
157
158     def test_versions(self):
159         basedir = "test_client.Basic.test_versions"
160         os.mkdir(basedir)
161         open(os.path.join(basedir, "introducer.furl"), "w").write("")
162         open(os.path.join(basedir, "vdrive.furl"), "w").write("")
163         c = client.Client(basedir)
164         ss = c.getServiceNamed("storage")
165         verdict = ss.remote_get_version()
166         self.failUnlessEqual(verdict["application-version"],
167                              str(allmydata.__full_version__))
168         self.failIfEqual(str(allmydata.__version__), "unknown")
169         self.failUnless("." in str(allmydata.__full_version__),
170                         "non-numeric version in '%s'" % allmydata.__version__)
171         all_versions = allmydata.get_package_versions_string()
172         self.failUnless("allmydata-tahoe" in all_versions)
173         log.msg("tahoe versions: %s" % all_versions)
174         # also test stats
175         stats = c.get_stats()
176         self.failUnless("node.uptime" in stats)
177         self.failUnless(isinstance(stats["node.uptime"], float))
178
179 def flush_but_dont_ignore(res):
180     d = flushEventualQueue()
181     def _done(ignored):
182         return res
183     d.addCallback(_done)
184     return d
185
186 class Run(unittest.TestCase, testutil.StallMixin):
187
188     def setUp(self):
189         self.sparent = service.MultiService()
190         self.sparent.startService()
191     def tearDown(self):
192         d = self.sparent.stopService()
193         d.addBoth(flush_but_dont_ignore)
194         return d
195
196     def test_loadable(self):
197         basedir = "test_client.Run.test_loadable"
198         os.mkdir(basedir)
199         dummy = "pb://wl74cyahejagspqgy4x5ukrvfnevlknt@127.0.0.1:58889/bogus"
200         open(os.path.join(basedir, "introducer.furl"), "w").write(dummy)
201         open(os.path.join(basedir, "suicide_prevention_hotline"), "w")
202         c = client.Client(basedir)
203
204     def test_reloadable(self):
205         basedir = "test_client.Run.test_reloadable"
206         os.mkdir(basedir)
207         dummy = "pb://wl74cyahejagspqgy4x5ukrvfnevlknt@127.0.0.1:58889/bogus"
208         open(os.path.join(basedir, "introducer.furl"), "w").write(dummy)
209         c1 = client.Client(basedir)
210         c1.setServiceParent(self.sparent)
211
212         # delay to let the service start up completely. I'm not entirely sure
213         # this is necessary.
214         d = self.stall(delay=2.0)
215         d.addCallback(lambda res: c1.disownServiceParent())
216         # the cygwin buildslave seems to need more time to let the old
217         # service completely shut down. When delay=0.1, I saw this test fail,
218         # probably due to the logport trying to reclaim the old socket
219         # number. This suggests that either we're dropping a Deferred
220         # somewhere in the shutdown sequence, or that cygwin is just cranky.
221         d.addCallback(self.stall, delay=2.0)
222         def _restart(res):
223             # TODO: pause for slightly over one second, to let
224             # Client._check_hotline poll the file once. That will exercise
225             # another few lines. Then add another test in which we don't
226             # update the file at all, and watch to see the node shutdown. (to
227             # do this, use a modified node which overrides Node.shutdown(),
228             # also change _check_hotline to use it instead of a raw
229             # reactor.stop, also instrument the shutdown event in an
230             # attribute that we can check)
231             c2 = client.Client(basedir)
232             c2.setServiceParent(self.sparent)
233             return c2.disownServiceParent()
234         d.addCallback(_restart)
235         return d
236