2 from twisted.trial import unittest
4 from cStringIO import StringIO
5 from twisted.python import usage, runtime
6 from twisted.internet import defer
8 from allmydata.scripts import runner, debug
9 from allmydata.util import fileutil, testutil
11 class CreateNode(unittest.TestCase):
12 def workdir(self, name):
13 basedir = os.path.join("test_runner", "CreateNode", name)
14 fileutil.make_dirs(basedir)
17 def test_client(self):
18 basedir = self.workdir("test_client")
19 c1 = os.path.join(basedir, "c1")
20 argv = ["--quiet", "create-client", "--basedir", c1]
21 out,err = StringIO(), StringIO()
22 rc = runner.runner(argv, stdout=out, stderr=err)
23 self.failUnlessEqual(err.getvalue(), "")
24 self.failUnlessEqual(out.getvalue(), "")
25 self.failUnlessEqual(rc, 0)
26 self.failUnless(os.path.exists(c1))
27 self.failUnless(os.path.exists(os.path.join(c1, "tahoe-client.tac")))
29 # creating the client a second time should throw an exception
30 out,err = StringIO(), StringIO()
31 rc = runner.runner(argv, stdout=out, stderr=err)
32 self.failIfEqual(rc, 0)
33 self.failUnlessEqual(out.getvalue(), "")
34 self.failUnless("The base directory already exists" in err.getvalue())
36 c2 = os.path.join(basedir, "c2")
37 argv = ["--quiet", "create-client", c2]
39 self.failUnless(os.path.exists(c2))
40 self.failUnless(os.path.exists(os.path.join(c2, "tahoe-client.tac")))
42 self.failUnlessRaises(usage.UsageError,
44 ["create-client", "basedir", "extraarg"],
47 def test_introducer(self):
48 basedir = self.workdir("test_introducer")
49 c1 = os.path.join(basedir, "c1")
50 argv = ["--quiet", "create-introducer", "--basedir", c1]
51 out,err = StringIO(), StringIO()
52 rc = runner.runner(argv, stdout=out, stderr=err)
53 self.failUnlessEqual(err.getvalue(), "")
54 self.failUnlessEqual(out.getvalue(), "")
55 self.failUnlessEqual(rc, 0)
56 self.failUnless(os.path.exists(c1))
57 self.failUnless(os.path.exists(os.path.join(c1,
58 "tahoe-introducer.tac")))
60 # creating the introducer a second time should throw an exception
61 out,err = StringIO(), StringIO()
62 rc = runner.runner(argv, stdout=out, stderr=err)
63 self.failIfEqual(rc, 0)
64 self.failUnlessEqual(out.getvalue(), "")
65 self.failUnless("The base directory already exists" in err.getvalue())
67 c2 = os.path.join(basedir, "c2")
68 argv = ["--quiet", "create-introducer", c2]
70 self.failUnless(os.path.exists(c2))
71 self.failUnless(os.path.exists(os.path.join(c2,
72 "tahoe-introducer.tac")))
74 self.failUnlessRaises(usage.UsageError,
76 ["create-introducer", "basedir", "extraarg"],
79 self.failUnlessRaises(usage.UsageError,
81 ["create-introducer"],
84 def test_subcommands(self):
85 self.failUnlessRaises(usage.UsageError,
90 class Diagnostics(unittest.TestCase):
91 def test_dump_root_dirnode_failure(self):
93 config = {'basedirs': ["missing_basedir"]}
94 rc = debug.dump_root_dirnode(config, s)
96 self.failUnless("unable to read root dirnode file from" in output)
97 self.failIfEqual(rc, 0)
99 class RunNode(unittest.TestCase, testutil.PollMixin):
100 def workdir(self, name):
101 basedir = os.path.join("test_runner", "RunNode", name)
102 fileutil.make_dirs(basedir)
105 def test_client(self):
106 if runtime.platformType == "win32":
107 # twistd on windows doesn't daemonize. cygwin works normally.
108 raise unittest.SkipTest("twistd does not fork under windows")
109 basedir = self.workdir("test_client")
110 c1 = os.path.join(basedir, "c1")
111 argv = ["--quiet", "create-client", "--basedir", c1]
112 out,err = StringIO(), StringIO()
113 rc = runner.runner(argv, stdout=out, stderr=err)
114 self.failUnlessEqual(rc, 0)
115 # by writing this file, we get ten seconds before the client will
116 # exit. This insures that even if the test fails (and the 'stop'
117 # command doesn't work), the client should still terminate.
118 HOTLINE_FILE = os.path.join(c1, "suicide_prevention_hotline")
119 open(HOTLINE_FILE, "w").write("")
120 open(os.path.join(c1, "introducer.furl"), "w").write("pb://xrndsskn2zuuian5ltnxrte7lnuqdrkz@127.0.0.1:55617/introducer\n")
121 # now it's safe to start the node
123 TWISTD_PID_FILE = os.path.join(c1, "twistd.pid")
125 d = defer.succeed(None)
127 argv = ["--quiet", "start", c1]
128 out,err = StringIO(), StringIO()
129 rc = runner.runner(argv, stdout=out, stderr=err)
130 open(HOTLINE_FILE, "w").write("")
131 outs = out.getvalue() ; errs = err.getvalue()
132 errstr = "rc=%d, OUT: '%s', ERR: '%s'" % (rc, outs, errs)
133 self.failUnlessEqual(rc, 0, errstr)
134 self.failUnlessEqual(outs, "", errstr)
135 self.failUnlessEqual(errs, "", errstr)
137 # the parent (twistd) has exited. However, twistd writes the pid
138 # from the child, not the parent, so we can't expect twistd.pid
139 # to exist quite yet.
141 # the node is running, but it might not have made it past the
142 # first reactor turn yet, and if we kill it too early, it won't
143 # remove the twistd.pid file. So wait until it does something
144 # that we know it won't do until after the first turn.
146 d.addCallback(_start)
148 PORTNUMFILE = os.path.join(c1, "client.port")
149 def _node_has_started():
150 return os.path.exists(PORTNUMFILE)
151 d.addCallback(lambda res: self.poll(_node_has_started))
154 open(HOTLINE_FILE, "w").write("")
155 self.failUnless(os.path.exists(TWISTD_PID_FILE))
156 # rm this so we can detect when the second incarnation is ready
157 os.unlink(PORTNUMFILE)
158 argv = ["--quiet", "restart", c1]
159 out,err = StringIO(), StringIO()
160 rc = runner.runner(argv, stdout=out, stderr=err)
161 open(HOTLINE_FILE, "w").write("")
162 outs = out.getvalue() ; errs = err.getvalue()
163 errstr = "rc=%d, OUT: '%s', ERR: '%s'" % (rc, outs, errs)
164 self.failUnlessEqual(rc, 0, errstr)
165 self.failUnlessEqual(outs, "", errstr)
166 self.failUnlessEqual(errs, "", errstr)
167 d.addCallback(_started)
169 # again, the second incarnation of the node might not be ready yet,
170 # so poll until it is
171 d.addCallback(lambda res: self.poll(_node_has_started))
173 # now we can kill it. TODO: On a slow machine, the node might kill
174 # itself before we get a chance too, especially if spawning the
175 # 'tahoe stop' command takes a while.
177 open(HOTLINE_FILE, "w").write("")
178 self.failUnless(os.path.exists(TWISTD_PID_FILE))
179 argv = ["--quiet", "stop", c1]
180 out,err = StringIO(), StringIO()
181 rc = runner.runner(argv, stdout=out, stderr=err)
182 open(HOTLINE_FILE, "w").write("")
183 # the parent has exited by now
184 outs = out.getvalue() ; errs = err.getvalue()
185 errstr = "rc=%d, OUT: '%s', ERR: '%s'" % (rc, outs, errs)
186 self.failUnlessEqual(rc, 0, errstr)
187 self.failUnlessEqual(outs, "", errstr)
188 self.failUnlessEqual(errs, "", errstr)
189 # the parent was supposed to poll and wait until it sees
190 # twistd.pid go away before it exits, so twistd.pid should be
192 self.failIf(os.path.exists(TWISTD_PID_FILE))
194 def _remove_hotline(res):
195 os.unlink(HOTLINE_FILE)
197 d.addBoth(_remove_hotline)
200 def test_baddir(self):
201 basedir = self.workdir("test_baddir")
202 fileutil.make_dirs(basedir)
203 argv = ["--quiet", "start", "--basedir", basedir]
204 out,err = StringIO(), StringIO()
205 rc = runner.runner(argv, stdout=out, stderr=err)
206 self.failUnlessEqual(rc, 1)
207 self.failUnless("does not look like a node directory" in err.getvalue())
209 argv = ["--quiet", "stop", "--basedir", basedir]
210 out,err = StringIO(), StringIO()
211 rc = runner.runner(argv, stdout=out, stderr=err)
212 self.failUnlessEqual(rc, 2)
213 self.failUnless("does not look like a running node directory"
216 not_a_dir = os.path.join(basedir, "bogus")
217 argv = ["--quiet", "start", "--basedir", not_a_dir]
218 out,err = StringIO(), StringIO()
219 rc = runner.runner(argv, stdout=out, stderr=err)
220 self.failUnlessEqual(rc, 1)
221 self.failUnless("does not look like a node directory" in err.getvalue())
222 self.failUnless("doesn't look like a directory at all"