2014-08-17 14:36:57 +00:00
|
|
|
import os.path, re, sys, subprocess
|
|
|
|
|
2007-04-20 01:56:45 +00:00
|
|
|
from twisted.trial import unittest
|
|
|
|
|
2009-02-09 09:26:17 +00:00
|
|
|
from twisted.python import usage, runtime
|
2011-01-20 04:32:38 +00:00
|
|
|
from twisted.internet import threads
|
2016-03-16 01:15:29 +00:00
|
|
|
from twisted.internet.defer import inlineCallbacks, returnValue
|
2011-01-20 04:32:38 +00:00
|
|
|
|
2008-10-29 04:15:48 +00:00
|
|
|
from allmydata.util import fileutil, pollmixin
|
2015-10-28 13:49:43 +00:00
|
|
|
from allmydata.util.encodingutil import unicode_to_argv, unicode_to_output, \
|
2015-10-29 21:12:14 +00:00
|
|
|
get_filesystem_encoding
|
2014-08-17 14:36:57 +00:00
|
|
|
from allmydata.client import Client
|
2009-01-22 22:38:18 +00:00
|
|
|
from allmydata.test import common_util
|
2009-01-22 22:52:40 +00:00
|
|
|
import allmydata
|
2016-08-08 01:46:59 +00:00
|
|
|
from allmydata import __appname__
|
2016-09-09 17:06:00 +00:00
|
|
|
from .common_util import parse_cli, run_cli
|
2009-01-22 22:52:40 +00:00
|
|
|
|
2014-08-17 14:36:57 +00:00
|
|
|
|
2010-08-06 04:26:01 +00:00
|
|
|
timeout = 240
|
|
|
|
|
2011-01-19 08:21:45 +00:00
|
|
|
def get_root_from_file(src):
|
|
|
|
srcdir = os.path.dirname(os.path.dirname(os.path.normcase(os.path.realpath(src))))
|
|
|
|
|
|
|
|
root = os.path.dirname(srcdir)
|
|
|
|
if os.path.basename(srcdir) == 'site-packages':
|
|
|
|
if re.search(r'python.+\..+', os.path.basename(root)):
|
|
|
|
root = os.path.dirname(root)
|
|
|
|
root = os.path.dirname(root)
|
|
|
|
elif os.path.basename(root) == 'src':
|
|
|
|
root = os.path.dirname(root)
|
|
|
|
|
|
|
|
return root
|
2010-08-08 04:28:17 +00:00
|
|
|
|
2011-01-19 08:21:45 +00:00
|
|
|
srcfile = allmydata.__file__
|
|
|
|
rootdir = get_root_from_file(srcfile)
|
2010-08-02 04:55:35 +00:00
|
|
|
|
2016-03-16 01:15:29 +00:00
|
|
|
|
2011-01-20 04:32:38 +00:00
|
|
|
class RunBinTahoeMixin:
|
2010-01-16 20:45:56 +00:00
|
|
|
def skip_if_cannot_daemonize(self):
|
|
|
|
if runtime.platformType == "win32":
|
|
|
|
# twistd on windows doesn't daemonize. cygwin should work normally.
|
|
|
|
raise unittest.SkipTest("twistd does not fork under windows")
|
2009-02-09 09:34:00 +00:00
|
|
|
|
2016-03-16 01:15:29 +00:00
|
|
|
@inlineCallbacks
|
|
|
|
def find_import_location(self):
|
|
|
|
res = yield self.run_bintahoe(["--version-and-path"])
|
|
|
|
out, err, rc_or_sig = res
|
|
|
|
self.assertEqual(rc_or_sig, 0, res)
|
|
|
|
lines = out.splitlines()
|
|
|
|
tahoe_pieces = lines[0].split()
|
2016-03-25 19:16:01 +00:00
|
|
|
self.assertEqual(tahoe_pieces[0], "%s:" % (__appname__,), (tahoe_pieces, res))
|
2016-04-19 16:47:00 +00:00
|
|
|
returnValue(tahoe_pieces[-1].strip("()"))
|
2016-03-16 01:15:29 +00:00
|
|
|
|
2011-01-20 04:32:38 +00:00
|
|
|
def run_bintahoe(self, args, stdin=None, python_options=[], env=None):
|
2016-04-19 16:47:00 +00:00
|
|
|
command = [sys.executable] + python_options + ["-m", "allmydata.scripts.runner"] + args
|
2011-01-21 08:04:29 +00:00
|
|
|
|
2011-01-20 04:32:38 +00:00
|
|
|
if stdin is None:
|
|
|
|
stdin_stream = None
|
|
|
|
else:
|
|
|
|
stdin_stream = subprocess.PIPE
|
|
|
|
|
|
|
|
def _run():
|
|
|
|
p = subprocess.Popen(command, stdin=stdin_stream, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env)
|
|
|
|
(out, err) = p.communicate(stdin)
|
|
|
|
return (out, err, p.returncode)
|
|
|
|
return threads.deferToThread(_run)
|
|
|
|
|
2010-01-16 20:45:56 +00:00
|
|
|
|
2011-01-20 04:32:38 +00:00
|
|
|
class BinTahoe(common_util.SignalMixin, unittest.TestCase, RunBinTahoeMixin):
|
2016-03-16 01:15:29 +00:00
|
|
|
@inlineCallbacks
|
|
|
|
def test_the_right_code(self):
|
|
|
|
# running "tahoe" in a subprocess should find the same code that
|
|
|
|
# holds this test file, else something is weird
|
|
|
|
test_path = os.path.dirname(os.path.dirname(os.path.normcase(os.path.realpath(srcfile))))
|
|
|
|
bintahoe_import_path = yield self.find_import_location()
|
2010-08-02 04:55:35 +00:00
|
|
|
|
2016-03-16 01:15:29 +00:00
|
|
|
same = (bintahoe_import_path == test_path)
|
2010-08-02 04:55:35 +00:00
|
|
|
if not same:
|
2016-03-16 01:15:29 +00:00
|
|
|
msg = ("My tests and my 'tahoe' executable are using different paths.\n"
|
|
|
|
"tahoe: %r\n"
|
|
|
|
"tests: %r\n"
|
|
|
|
"( according to the test source filename %r)\n" %
|
|
|
|
(bintahoe_import_path, test_path, srcfile))
|
|
|
|
|
|
|
|
if (not isinstance(rootdir, unicode) and
|
|
|
|
rootdir.decode(get_filesystem_encoding(), 'replace') != rootdir):
|
|
|
|
msg += ("However, this may be a false alarm because the import path\n"
|
|
|
|
"is not representable in the filesystem encoding.")
|
2010-08-02 04:55:35 +00:00
|
|
|
raise unittest.SkipTest(msg)
|
|
|
|
else:
|
2016-03-16 01:15:29 +00:00
|
|
|
msg += "Please run the tests in a virtualenv that includes both the Tahoe-LAFS library and the 'tahoe' executable."
|
2010-08-02 04:55:35 +00:00
|
|
|
self.fail(msg)
|
|
|
|
|
2009-01-22 22:52:40 +00:00
|
|
|
def test_path(self):
|
2011-01-20 04:32:38 +00:00
|
|
|
d = self.run_bintahoe(["--version-and-path"])
|
2009-01-22 22:52:40 +00:00
|
|
|
def _cb(res):
|
2011-01-22 01:42:56 +00:00
|
|
|
from allmydata import normalized_version
|
|
|
|
|
2009-01-22 22:52:40 +00:00
|
|
|
out, err, rc_or_sig = res
|
2010-08-02 01:35:26 +00:00
|
|
|
self.failUnlessEqual(rc_or_sig, 0, str(res))
|
2009-01-22 22:52:40 +00:00
|
|
|
|
2014-12-05 23:29:07 +00:00
|
|
|
# Fail unless the __appname__ package is *this* version *and*
|
2010-09-10 15:41:35 +00:00
|
|
|
# was loaded from *this* source directory.
|
|
|
|
|
2011-01-22 01:42:56 +00:00
|
|
|
required_verstr = str(allmydata.__version__)
|
2010-09-10 15:41:35 +00:00
|
|
|
|
2011-01-22 01:42:56 +00:00
|
|
|
self.failIfEqual(required_verstr, "unknown",
|
2010-09-11 22:19:13 +00:00
|
|
|
"We don't know our version, because this distribution didn't come "
|
2013-03-19 22:26:21 +00:00
|
|
|
"with a _version.py and 'setup.py update_version' hasn't been run.")
|
2010-09-11 22:19:13 +00:00
|
|
|
|
2011-01-19 08:21:45 +00:00
|
|
|
srcdir = os.path.dirname(os.path.dirname(os.path.normcase(os.path.realpath(srcfile))))
|
2011-09-27 22:53:36 +00:00
|
|
|
info = repr((res, allmydata.__appname__, required_verstr, srcdir))
|
2011-01-22 01:42:56 +00:00
|
|
|
|
|
|
|
appverpath = out.split(')')[0]
|
2013-04-25 01:14:50 +00:00
|
|
|
(appverfull, path) = appverpath.split('] (')
|
|
|
|
(appver, comment) = appverfull.split(' [')
|
|
|
|
(branch, full_version) = comment.split(': ')
|
2011-01-22 01:42:56 +00:00
|
|
|
(app, ver) = appver.split(': ')
|
2010-09-10 15:41:35 +00:00
|
|
|
|
2011-01-22 01:42:56 +00:00
|
|
|
self.failUnlessEqual(app, allmydata.__appname__, info)
|
2011-09-27 22:53:36 +00:00
|
|
|
norm_ver = normalized_version(ver)
|
|
|
|
norm_required = normalized_version(required_verstr)
|
|
|
|
self.failUnlessEqual(norm_ver, norm_required, info)
|
2011-01-22 01:42:56 +00:00
|
|
|
self.failUnlessEqual(path, srcdir, info)
|
2013-04-25 01:14:50 +00:00
|
|
|
self.failUnlessEqual(branch, allmydata.branch)
|
|
|
|
self.failUnlessEqual(full_version, allmydata.full_version)
|
2009-01-22 22:52:40 +00:00
|
|
|
d.addCallback(_cb)
|
|
|
|
return d
|
2009-01-22 22:38:18 +00:00
|
|
|
|
2010-07-25 08:32:16 +00:00
|
|
|
def test_unicode_arguments_and_output(self):
|
|
|
|
tricky = u"\u2621"
|
|
|
|
try:
|
|
|
|
tricky_arg = unicode_to_argv(tricky, mangle=True)
|
|
|
|
tricky_out = unicode_to_output(tricky)
|
|
|
|
except UnicodeEncodeError:
|
|
|
|
raise unittest.SkipTest("A non-ASCII argument/output could not be encoded on this platform.")
|
|
|
|
|
2011-01-20 04:32:38 +00:00
|
|
|
d = self.run_bintahoe([tricky_arg])
|
2010-07-25 08:32:16 +00:00
|
|
|
def _cb(res):
|
|
|
|
out, err, rc_or_sig = res
|
2010-08-02 04:55:35 +00:00
|
|
|
self.failUnlessEqual(rc_or_sig, 1, str(res))
|
2010-07-25 08:32:16 +00:00
|
|
|
self.failUnlessIn("Unknown command: "+tricky_out, out)
|
|
|
|
d.addCallback(_cb)
|
|
|
|
return d
|
|
|
|
|
2010-08-02 06:25:58 +00:00
|
|
|
def test_run_with_python_options(self):
|
|
|
|
# -t is a harmless option that warns about tabs.
|
2011-01-20 04:32:38 +00:00
|
|
|
d = self.run_bintahoe(["--version"], python_options=["-t"])
|
2010-08-02 06:25:58 +00:00
|
|
|
def _cb(res):
|
|
|
|
out, err, rc_or_sig = res
|
|
|
|
self.failUnlessEqual(rc_or_sig, 0, str(res))
|
|
|
|
self.failUnless(out.startswith(allmydata.__appname__+':'), str(res))
|
|
|
|
d.addCallback(_cb)
|
|
|
|
return d
|
|
|
|
|
2010-07-20 01:13:45 +00:00
|
|
|
def test_version_no_noise(self):
|
2011-01-20 04:32:38 +00:00
|
|
|
d = self.run_bintahoe(["--version"])
|
2010-07-20 01:13:45 +00:00
|
|
|
def _cb(res):
|
|
|
|
out, err, rc_or_sig = res
|
2010-08-02 01:35:26 +00:00
|
|
|
self.failUnlessEqual(rc_or_sig, 0, str(res))
|
|
|
|
self.failUnless(out.startswith(allmydata.__appname__+':'), str(res))
|
|
|
|
self.failIfIn("DeprecationWarning", out, str(res))
|
2010-10-29 19:18:04 +00:00
|
|
|
errlines = err.split("\n")
|
2010-10-29 20:42:46 +00:00
|
|
|
self.failIf([True for line in errlines if (line != "" and "UserWarning: Unbuilt egg for setuptools" not in line
|
2010-10-29 22:11:23 +00:00
|
|
|
and "from pkg_resources import load_entry_point" not in line)], str(res))
|
2010-10-29 19:18:04 +00:00
|
|
|
if err != "":
|
|
|
|
raise unittest.SkipTest("This test is known not to pass on Ubuntu Lucid; see #1235.")
|
2010-07-20 01:13:45 +00:00
|
|
|
d.addCallback(_cb)
|
|
|
|
return d
|
|
|
|
|
2010-01-16 20:45:56 +00:00
|
|
|
|
2009-02-09 09:26:17 +00:00
|
|
|
class CreateNode(unittest.TestCase):
|
2010-01-16 05:20:55 +00:00
|
|
|
# exercise "tahoe create-node", create-introducer,
|
2009-02-09 09:26:17 +00:00
|
|
|
# create-key-generator, and create-stats-gatherer, by calling the
|
|
|
|
# corresponding code as a subroutine.
|
|
|
|
|
2007-04-20 01:56:45 +00:00
|
|
|
def workdir(self, name):
|
2007-09-17 09:25:31 +00:00
|
|
|
basedir = os.path.join("test_runner", "CreateNode", name)
|
2007-04-20 01:56:45 +00:00
|
|
|
fileutil.make_dirs(basedir)
|
|
|
|
return basedir
|
|
|
|
|
2016-09-09 17:41:20 +00:00
|
|
|
@inlineCallbacks
|
2016-05-04 22:04:12 +00:00
|
|
|
def do_create(self, kind, *args):
|
2010-08-03 08:54:16 +00:00
|
|
|
basedir = self.workdir("test_" + kind)
|
|
|
|
command = "create-" + kind
|
|
|
|
is_client = kind in ("node", "client")
|
|
|
|
tac = is_client and "tahoe-client.tac" or ("tahoe-" + kind + ".tac")
|
|
|
|
|
|
|
|
n1 = os.path.join(basedir, command + "-n1")
|
2016-05-04 22:04:12 +00:00
|
|
|
argv = ["--quiet", command, "--basedir", n1] + list(args)
|
2016-09-09 17:41:20 +00:00
|
|
|
rc, out, err = yield run_cli(*argv)
|
2009-02-09 09:26:17 +00:00
|
|
|
self.failUnlessEqual(err, "")
|
|
|
|
self.failUnlessEqual(out, "")
|
|
|
|
self.failUnlessEqual(rc, 0)
|
2010-08-03 08:54:16 +00:00
|
|
|
self.failUnless(os.path.exists(n1))
|
|
|
|
self.failUnless(os.path.exists(os.path.join(n1, tac)))
|
|
|
|
|
|
|
|
if is_client:
|
|
|
|
# tahoe.cfg should exist, and should have storage enabled for
|
|
|
|
# 'create-node', and disabled for 'create-client'.
|
|
|
|
tahoe_cfg = os.path.join(n1, "tahoe.cfg")
|
|
|
|
self.failUnless(os.path.exists(tahoe_cfg))
|
2011-08-04 00:30:32 +00:00
|
|
|
content = fileutil.read(tahoe_cfg).replace('\r\n', '\n')
|
2010-08-03 08:54:16 +00:00
|
|
|
if kind == "client":
|
2011-01-17 06:05:40 +00:00
|
|
|
self.failUnless(re.search(r"\n\[storage\]\n#.*\nenabled = false\n", content), content)
|
2010-08-03 08:54:16 +00:00
|
|
|
else:
|
2011-01-17 06:05:40 +00:00
|
|
|
self.failUnless(re.search(r"\n\[storage\]\n#.*\nenabled = true\n", content), content)
|
2011-01-16 20:58:22 +00:00
|
|
|
self.failUnless("\nreserved_space = 1G\n" in content)
|
2010-08-03 08:54:16 +00:00
|
|
|
|
|
|
|
# creating the node a second time should be rejected
|
2016-09-09 17:41:20 +00:00
|
|
|
rc, out, err = yield run_cli(*argv)
|
2009-02-09 09:26:17 +00:00
|
|
|
self.failIfEqual(rc, 0, str((out, err, rc)))
|
|
|
|
self.failUnlessEqual(out, "")
|
|
|
|
self.failUnless("is not empty." in err)
|
|
|
|
|
|
|
|
# Fail if there is a non-empty line that doesn't end with a
|
|
|
|
# punctuation mark.
|
|
|
|
for line in err.splitlines():
|
|
|
|
self.failIf(re.search("[\S][^\.!?]$", line), (line,))
|
|
|
|
|
|
|
|
# test that the non --basedir form works too
|
2010-08-03 08:54:16 +00:00
|
|
|
n2 = os.path.join(basedir, command + "-n2")
|
2016-05-04 22:04:12 +00:00
|
|
|
argv = ["--quiet", command] + list(args) + [n2]
|
2016-09-09 17:41:20 +00:00
|
|
|
rc, out, err = yield run_cli(*argv)
|
2010-08-03 08:54:16 +00:00
|
|
|
self.failUnlessEqual(err, "")
|
2009-02-09 09:26:17 +00:00
|
|
|
self.failUnlessEqual(out, "")
|
|
|
|
self.failUnlessEqual(rc, 0)
|
2010-08-03 08:54:16 +00:00
|
|
|
self.failUnless(os.path.exists(n2))
|
|
|
|
self.failUnless(os.path.exists(os.path.join(n2, tac)))
|
2009-02-09 09:26:17 +00:00
|
|
|
|
2010-08-03 08:54:16 +00:00
|
|
|
# test the --node-directory form
|
|
|
|
n3 = os.path.join(basedir, command + "-n3")
|
2016-05-04 22:04:12 +00:00
|
|
|
argv = ["--quiet", "--node-directory", n3, command] + list(args)
|
2016-09-09 17:41:20 +00:00
|
|
|
rc, out, err = yield run_cli(*argv)
|
2010-08-03 08:54:16 +00:00
|
|
|
self.failUnlessEqual(err, "")
|
2009-02-09 09:26:17 +00:00
|
|
|
self.failUnlessEqual(out, "")
|
|
|
|
self.failUnlessEqual(rc, 0)
|
2010-08-03 08:54:16 +00:00
|
|
|
self.failUnless(os.path.exists(n3))
|
|
|
|
self.failUnless(os.path.exists(os.path.join(n3, tac)))
|
2009-02-09 09:26:17 +00:00
|
|
|
|
2015-12-01 17:58:16 +00:00
|
|
|
if kind in ("client", "node", "introducer"):
|
|
|
|
# test that the output (without --quiet) includes the base directory
|
|
|
|
n4 = os.path.join(basedir, command + "-n4")
|
2016-05-04 22:04:12 +00:00
|
|
|
argv = [command] + list(args) + [n4]
|
2016-09-09 17:41:20 +00:00
|
|
|
rc, out, err = yield run_cli(*argv)
|
2015-12-01 17:58:16 +00:00
|
|
|
self.failUnlessEqual(err, "")
|
|
|
|
self.failUnlessIn(" created in ", out)
|
|
|
|
self.failUnlessIn(n4, out)
|
|
|
|
self.failIfIn("\\\\?\\", out)
|
|
|
|
self.failUnlessEqual(rc, 0)
|
|
|
|
self.failUnless(os.path.exists(n4))
|
|
|
|
self.failUnless(os.path.exists(os.path.join(n4, tac)))
|
|
|
|
|
2010-11-27 08:38:09 +00:00
|
|
|
# make sure it rejects too many arguments
|
2016-09-09 17:06:00 +00:00
|
|
|
self.failUnlessRaises(usage.UsageError, parse_cli,
|
|
|
|
command, "basedir", "extraarg")
|
2009-02-09 09:26:17 +00:00
|
|
|
|
2010-08-03 08:54:16 +00:00
|
|
|
# when creating a non-client, there is no default for the basedir
|
|
|
|
if not is_client:
|
|
|
|
argv = [command]
|
2016-09-09 17:06:00 +00:00
|
|
|
self.failUnlessRaises(usage.UsageError, parse_cli,
|
|
|
|
command)
|
2009-02-09 09:26:17 +00:00
|
|
|
|
2010-08-03 08:54:16 +00:00
|
|
|
def test_node(self):
|
|
|
|
self.do_create("node")
|
2009-02-09 09:26:17 +00:00
|
|
|
|
2010-08-03 08:54:16 +00:00
|
|
|
def test_client(self):
|
|
|
|
# create-client should behave like create-node --no-storage.
|
|
|
|
self.do_create("client")
|
2009-02-09 09:26:17 +00:00
|
|
|
|
2010-08-03 08:54:16 +00:00
|
|
|
def test_introducer(self):
|
|
|
|
self.do_create("introducer")
|
2009-02-09 09:26:17 +00:00
|
|
|
|
2010-08-03 08:54:16 +00:00
|
|
|
def test_stats_gatherer(self):
|
2016-05-04 22:04:12 +00:00
|
|
|
self.do_create("stats-gatherer", "--hostname=127.0.0.1")
|
2009-02-09 09:26:17 +00:00
|
|
|
|
|
|
|
def test_subcommands(self):
|
|
|
|
# no arguments should trigger a command listing, via UsageError
|
2016-09-09 17:06:00 +00:00
|
|
|
self.failUnlessRaises(usage.UsageError, parse_cli,
|
|
|
|
)
|
2009-01-22 22:38:18 +00:00
|
|
|
|
2016-09-09 17:06:00 +00:00
|
|
|
@inlineCallbacks
|
2016-05-04 22:04:12 +00:00
|
|
|
def test_stats_gatherer_good_args(self):
|
2016-09-09 17:06:00 +00:00
|
|
|
rc,out,err = yield run_cli("create-stats-gatherer", "--hostname=foo",
|
|
|
|
self.mktemp())
|
2016-05-04 22:04:12 +00:00
|
|
|
self.assertEqual(rc, 0)
|
2016-09-09 17:06:00 +00:00
|
|
|
rc,out,err = yield run_cli("create-stats-gatherer",
|
|
|
|
"--location=tcp:foo:1234",
|
|
|
|
"--port=tcp:1234", self.mktemp())
|
2016-05-04 22:04:12 +00:00
|
|
|
self.assertEqual(rc, 0)
|
|
|
|
|
2016-09-09 17:06:00 +00:00
|
|
|
|
2016-05-04 22:04:12 +00:00
|
|
|
def test_stats_gatherer_bad_args(self):
|
2016-09-09 17:06:00 +00:00
|
|
|
def _test(args):
|
|
|
|
argv = args.split()
|
|
|
|
self.assertRaises(usage.UsageError, parse_cli, *argv)
|
|
|
|
|
2016-05-04 22:04:12 +00:00
|
|
|
# missing hostname/location/port
|
2016-09-09 17:06:00 +00:00
|
|
|
_test("create-stats-gatherer D")
|
2016-05-04 22:04:12 +00:00
|
|
|
|
|
|
|
# missing port
|
2016-09-09 17:06:00 +00:00
|
|
|
_test("create-stats-gatherer --location=foo D")
|
2016-05-04 22:04:12 +00:00
|
|
|
|
|
|
|
# missing location
|
2016-09-09 17:06:00 +00:00
|
|
|
_test("create-stats-gatherer --port=foo D")
|
2016-05-04 22:04:12 +00:00
|
|
|
|
|
|
|
# can't provide both
|
2016-09-09 17:06:00 +00:00
|
|
|
_test("create-stats-gatherer --hostname=foo --port=foo D")
|
2016-05-04 22:04:12 +00:00
|
|
|
|
|
|
|
# can't provide both
|
2016-09-09 17:06:00 +00:00
|
|
|
_test("create-stats-gatherer --hostname=foo --location=foo D")
|
2016-05-04 22:04:12 +00:00
|
|
|
|
|
|
|
# can't provide all three
|
2016-09-09 17:06:00 +00:00
|
|
|
_test("create-stats-gatherer --hostname=foo --location=foo --port=foo D")
|
2009-01-22 22:38:18 +00:00
|
|
|
|
2009-02-23 21:43:12 +00:00
|
|
|
class RunNode(common_util.SignalMixin, unittest.TestCase, pollmixin.PollMixin,
|
2011-01-20 04:32:38 +00:00
|
|
|
RunBinTahoeMixin):
|
2009-02-09 09:34:00 +00:00
|
|
|
# exercise "tahoe start", for both introducer, client node, and
|
|
|
|
# key-generator, by spawning "tahoe start" as a subprocess. This doesn't
|
|
|
|
# get us figleaf-based line-level coverage, but it does a better job of
|
|
|
|
# confirming that the user can actually run "./bin/tahoe start" and
|
|
|
|
# expect it to work. This verifies that bin/tahoe sets up PYTHONPATH and
|
|
|
|
# the like correctly.
|
|
|
|
|
|
|
|
# This doesn't work on cygwin (it hangs forever), so we skip this test
|
|
|
|
# when we're on cygwin. It is likely that "tahoe start" itself doesn't
|
|
|
|
# work on cygwin: twisted seems unable to provide a version of
|
|
|
|
# spawnProcess which really works there.
|
|
|
|
|
2007-09-17 09:25:31 +00:00
|
|
|
def workdir(self, name):
|
|
|
|
basedir = os.path.join("test_runner", "RunNode", name)
|
|
|
|
fileutil.make_dirs(basedir)
|
|
|
|
return basedir
|
|
|
|
|
2008-02-18 07:28:56 +00:00
|
|
|
def test_introducer(self):
|
2010-01-16 20:45:56 +00:00
|
|
|
self.skip_if_cannot_daemonize()
|
2014-08-17 14:32:17 +00:00
|
|
|
|
2008-02-18 07:28:56 +00:00
|
|
|
basedir = self.workdir("test_introducer")
|
|
|
|
c1 = os.path.join(basedir, "c1")
|
2014-08-17 14:36:57 +00:00
|
|
|
exit_trigger_file = os.path.join(c1, Client.EXIT_TRIGGER_FILE)
|
2014-08-17 14:32:17 +00:00
|
|
|
twistd_pid_file = os.path.join(c1, "twistd.pid")
|
|
|
|
introducer_furl_file = os.path.join(c1, "private", "introducer.furl")
|
|
|
|
portnum_file = os.path.join(c1, "introducer.port")
|
|
|
|
node_url_file = os.path.join(c1, "node.url")
|
|
|
|
config_file = os.path.join(c1, "tahoe.cfg")
|
2009-01-22 22:38:18 +00:00
|
|
|
|
2016-09-06 15:03:31 +00:00
|
|
|
d = self.run_bintahoe(["--quiet", "create-introducer", "--basedir", c1, "--hostname", "localhost"])
|
2009-01-22 22:38:18 +00:00
|
|
|
def _cb(res):
|
|
|
|
out, err, rc_or_sig = res
|
|
|
|
self.failUnlessEqual(rc_or_sig, 0)
|
2011-08-03 18:09:17 +00:00
|
|
|
|
|
|
|
# This makes sure that node.url is written, which allows us to
|
|
|
|
# detect when the introducer restarts in _node_has_restarted below.
|
2014-08-17 14:32:17 +00:00
|
|
|
config = fileutil.read(config_file)
|
2011-08-03 18:09:17 +00:00
|
|
|
self.failUnlessIn('\nweb.port = \n', config)
|
2014-08-17 14:32:17 +00:00
|
|
|
fileutil.write(config_file, config.replace('\nweb.port = \n', '\nweb.port = 0\n'))
|
2011-08-03 18:09:17 +00:00
|
|
|
|
2009-01-22 22:38:18 +00:00
|
|
|
# by writing this file, we get ten seconds before the node will
|
|
|
|
# exit. This insures that even if the test fails (and the 'stop'
|
|
|
|
# command doesn't work), the client should still terminate.
|
2014-08-17 14:36:57 +00:00
|
|
|
fileutil.write(exit_trigger_file, "")
|
2009-01-22 22:38:18 +00:00
|
|
|
# now it's safe to start the node
|
|
|
|
d.addCallback(_cb)
|
|
|
|
|
|
|
|
def _then_start_the_node(res):
|
2011-01-20 04:32:38 +00:00
|
|
|
return self.run_bintahoe(["--quiet", "start", c1])
|
2009-01-22 22:38:18 +00:00
|
|
|
d.addCallback(_then_start_the_node)
|
|
|
|
|
|
|
|
def _cb2(res):
|
|
|
|
out, err, rc_or_sig = res
|
2008-02-18 07:28:56 +00:00
|
|
|
|
2014-08-17 14:36:57 +00:00
|
|
|
fileutil.write(exit_trigger_file, "")
|
2009-01-22 22:38:18 +00:00
|
|
|
errstr = "rc=%d, OUT: '%s', ERR: '%s'" % (rc_or_sig, out, err)
|
|
|
|
self.failUnlessEqual(rc_or_sig, 0, errstr)
|
|
|
|
self.failUnlessEqual(out, "", errstr)
|
2009-01-27 00:30:46 +00:00
|
|
|
# self.failUnlessEqual(err, "", errstr) # See test_client_no_noise -- for now we ignore noise.
|
2008-02-18 07:28:56 +00:00
|
|
|
|
|
|
|
# the parent (twistd) has exited. However, twistd writes the pid
|
|
|
|
# from the child, not the parent, so we can't expect twistd.pid
|
|
|
|
# to exist quite yet.
|
|
|
|
|
|
|
|
# the node is running, but it might not have made it past the
|
|
|
|
# first reactor turn yet, and if we kill it too early, it won't
|
|
|
|
# remove the twistd.pid file. So wait until it does something
|
|
|
|
# that we know it won't do until after the first turn.
|
2009-01-22 22:38:18 +00:00
|
|
|
d.addCallback(_cb2)
|
2008-02-18 07:28:56 +00:00
|
|
|
|
|
|
|
def _node_has_started():
|
2014-08-17 14:32:17 +00:00
|
|
|
return os.path.exists(introducer_furl_file)
|
2008-02-18 07:28:56 +00:00
|
|
|
d.addCallback(lambda res: self.poll(_node_has_started))
|
|
|
|
|
|
|
|
def _started(res):
|
2013-03-20 22:10:47 +00:00
|
|
|
# read the introducer.furl and introducer.port files so we can
|
|
|
|
# check that their contents don't change on restart
|
2014-08-17 14:32:17 +00:00
|
|
|
self.furl = fileutil.read(introducer_furl_file)
|
|
|
|
self.failUnless(os.path.exists(portnum_file))
|
|
|
|
self.portnum = fileutil.read(portnum_file)
|
2011-08-06 22:06:35 +00:00
|
|
|
|
2014-08-17 14:36:57 +00:00
|
|
|
fileutil.write(exit_trigger_file, "")
|
2014-08-17 14:32:17 +00:00
|
|
|
self.failUnless(os.path.exists(twistd_pid_file))
|
|
|
|
self.failUnless(os.path.exists(node_url_file))
|
2011-08-06 22:06:35 +00:00
|
|
|
|
2011-08-03 18:09:17 +00:00
|
|
|
# rm this so we can detect when the second incarnation is ready
|
2014-08-17 14:32:17 +00:00
|
|
|
os.unlink(node_url_file)
|
2011-01-20 04:32:38 +00:00
|
|
|
return self.run_bintahoe(["--quiet", "restart", c1])
|
2008-02-18 07:28:56 +00:00
|
|
|
d.addCallback(_started)
|
|
|
|
|
2009-01-22 22:38:18 +00:00
|
|
|
def _then(res):
|
|
|
|
out, err, rc_or_sig = res
|
2014-08-17 14:36:57 +00:00
|
|
|
fileutil.write(exit_trigger_file, "")
|
2009-01-22 22:38:18 +00:00
|
|
|
errstr = "rc=%d, OUT: '%s', ERR: '%s'" % (rc_or_sig, out, err)
|
|
|
|
self.failUnlessEqual(rc_or_sig, 0, errstr)
|
|
|
|
self.failUnlessEqual(out, "", errstr)
|
2009-01-27 00:30:46 +00:00
|
|
|
# self.failUnlessEqual(err, "", errstr) # See test_client_no_noise -- for now we ignore noise.
|
2009-01-22 22:38:18 +00:00
|
|
|
d.addCallback(_then)
|
|
|
|
|
2014-08-17 14:32:17 +00:00
|
|
|
# Again, the second incarnation of the node might not be ready yet,
|
|
|
|
# so poll until it is. This time introducer_furl_file already
|
|
|
|
# exists, so we check for the existence of node_url_file instead.
|
2011-08-03 01:27:04 +00:00
|
|
|
def _node_has_restarted():
|
2014-08-17 14:32:17 +00:00
|
|
|
return os.path.exists(node_url_file) and os.path.exists(portnum_file)
|
2011-08-03 01:27:04 +00:00
|
|
|
d.addCallback(lambda res: self.poll(_node_has_restarted))
|
2008-02-18 07:28:56 +00:00
|
|
|
|
2011-08-06 22:06:35 +00:00
|
|
|
def _check_same_furl_and_port(res):
|
2014-08-17 14:32:17 +00:00
|
|
|
self.failUnless(os.path.exists(introducer_furl_file))
|
|
|
|
self.failUnlessEqual(self.furl, fileutil.read(introducer_furl_file))
|
|
|
|
self.failUnlessEqual(self.portnum, fileutil.read(portnum_file))
|
2011-08-06 22:06:35 +00:00
|
|
|
d.addCallback(_check_same_furl_and_port)
|
|
|
|
|
2014-08-17 14:32:17 +00:00
|
|
|
# Now we can kill it. TODO: On a slow machine, the node might kill
|
2011-08-06 22:06:35 +00:00
|
|
|
# itself before we get a chance to, especially if spawning the
|
2008-02-18 07:28:56 +00:00
|
|
|
# 'tahoe stop' command takes a while.
|
|
|
|
def _stop(res):
|
2014-08-17 14:36:57 +00:00
|
|
|
fileutil.write(exit_trigger_file, "")
|
2014-08-17 14:32:17 +00:00
|
|
|
self.failUnless(os.path.exists(twistd_pid_file))
|
2009-01-22 22:38:18 +00:00
|
|
|
|
2011-01-20 04:32:38 +00:00
|
|
|
return self.run_bintahoe(["--quiet", "stop", c1])
|
2009-01-22 22:38:18 +00:00
|
|
|
d.addCallback(_stop)
|
|
|
|
|
|
|
|
def _after_stopping(res):
|
|
|
|
out, err, rc_or_sig = res
|
2014-08-17 14:36:57 +00:00
|
|
|
fileutil.write(exit_trigger_file, "")
|
2008-02-18 07:28:56 +00:00
|
|
|
# the parent has exited by now
|
2009-01-22 22:38:18 +00:00
|
|
|
errstr = "rc=%d, OUT: '%s', ERR: '%s'" % (rc_or_sig, out, err)
|
|
|
|
self.failUnlessEqual(rc_or_sig, 0, errstr)
|
|
|
|
self.failUnlessEqual(out, "", errstr)
|
2009-01-27 00:30:46 +00:00
|
|
|
# self.failUnlessEqual(err, "", errstr) # See test_client_no_noise -- for now we ignore noise.
|
2008-02-18 07:28:56 +00:00
|
|
|
# the parent was supposed to poll and wait until it sees
|
|
|
|
# twistd.pid go away before it exits, so twistd.pid should be
|
|
|
|
# gone by now.
|
2014-08-17 14:32:17 +00:00
|
|
|
self.failIf(os.path.exists(twistd_pid_file))
|
2009-01-22 22:38:18 +00:00
|
|
|
d.addCallback(_after_stopping)
|
2014-08-17 14:36:57 +00:00
|
|
|
d.addBoth(self._remove, exit_trigger_file)
|
2008-02-18 07:28:56 +00:00
|
|
|
return d
|
2012-03-13 20:26:54 +00:00
|
|
|
# This test has hit a 240-second timeout on our feisty2.5 buildslave, and a 480-second timeout
|
|
|
|
# on Francois's Lenny-armv5tel buildslave.
|
2011-03-17 16:59:09 +00:00
|
|
|
test_introducer.timeout = 960
|
|
|
|
|
2010-02-01 00:44:29 +00:00
|
|
|
def test_client_no_noise(self):
|
|
|
|
self.skip_if_cannot_daemonize()
|
2011-01-22 01:42:56 +00:00
|
|
|
|
2010-02-01 00:44:29 +00:00
|
|
|
basedir = self.workdir("test_client_no_noise")
|
|
|
|
c1 = os.path.join(basedir, "c1")
|
2014-08-17 14:36:57 +00:00
|
|
|
exit_trigger_file = os.path.join(c1, Client.EXIT_TRIGGER_FILE)
|
2014-08-17 14:32:17 +00:00
|
|
|
twistd_pid_file = os.path.join(c1, "twistd.pid")
|
|
|
|
portnum_file = os.path.join(c1, "client.port")
|
2010-02-01 00:44:29 +00:00
|
|
|
|
2011-01-20 04:32:38 +00:00
|
|
|
d = self.run_bintahoe(["--quiet", "create-client", "--basedir", c1, "--webport", "0"])
|
2010-02-01 00:44:29 +00:00
|
|
|
def _cb(res):
|
|
|
|
out, err, rc_or_sig = res
|
|
|
|
errstr = "cc=%d, OUT: '%s', ERR: '%s'" % (rc_or_sig, out, err)
|
|
|
|
assert rc_or_sig == 0, errstr
|
|
|
|
self.failUnlessEqual(rc_or_sig, 0)
|
2011-08-06 22:06:35 +00:00
|
|
|
|
|
|
|
# By writing this file, we get two minutes before the client will exit. This ensures
|
2010-02-01 00:44:29 +00:00
|
|
|
# that even if the 'stop' command doesn't work (and the test fails), the client should
|
|
|
|
# still terminate.
|
2014-08-17 14:36:57 +00:00
|
|
|
fileutil.write(exit_trigger_file, "")
|
2010-02-01 00:44:29 +00:00
|
|
|
# now it's safe to start the node
|
|
|
|
d.addCallback(_cb)
|
|
|
|
|
|
|
|
def _start(res):
|
2011-01-20 04:32:38 +00:00
|
|
|
return self.run_bintahoe(["--quiet", "start", c1])
|
2010-02-01 00:44:29 +00:00
|
|
|
d.addCallback(_start)
|
|
|
|
|
|
|
|
def _cb2(res):
|
|
|
|
out, err, rc_or_sig = res
|
|
|
|
errstr = "cc=%d, OUT: '%s', ERR: '%s'" % (rc_or_sig, out, err)
|
2014-08-17 14:36:57 +00:00
|
|
|
fileutil.write(exit_trigger_file, "")
|
2010-02-01 00:44:29 +00:00
|
|
|
self.failUnlessEqual(rc_or_sig, 0, errstr)
|
|
|
|
self.failUnlessEqual(out, "", errstr) # If you emit noise, you fail this test.
|
2010-10-29 19:18:04 +00:00
|
|
|
errlines = err.split("\n")
|
2010-10-29 20:42:46 +00:00
|
|
|
self.failIf([True for line in errlines if (line != "" and "UserWarning: Unbuilt egg for setuptools" not in line
|
|
|
|
and "from pkg_resources import load_entry_point" not in line)], errstr)
|
2010-10-29 19:18:04 +00:00
|
|
|
if err != "":
|
|
|
|
raise unittest.SkipTest("This test is known not to pass on Ubuntu Lucid; see #1235.")
|
2010-02-01 00:44:29 +00:00
|
|
|
|
|
|
|
# the parent (twistd) has exited. However, twistd writes the pid
|
|
|
|
# from the child, not the parent, so we can't expect twistd.pid
|
|
|
|
# to exist quite yet.
|
|
|
|
|
|
|
|
# the node is running, but it might not have made it past the
|
|
|
|
# first reactor turn yet, and if we kill it too early, it won't
|
|
|
|
# remove the twistd.pid file. So wait until it does something
|
|
|
|
# that we know it won't do until after the first turn.
|
|
|
|
d.addCallback(_cb2)
|
|
|
|
|
|
|
|
def _node_has_started():
|
2014-08-17 14:32:17 +00:00
|
|
|
return os.path.exists(portnum_file)
|
2010-02-01 00:44:29 +00:00
|
|
|
d.addCallback(lambda res: self.poll(_node_has_started))
|
|
|
|
|
|
|
|
# now we can kill it. TODO: On a slow machine, the node might kill
|
2010-11-28 17:45:07 +00:00
|
|
|
# itself before we get a chance to, especially if spawning the
|
2010-02-01 00:44:29 +00:00
|
|
|
# 'tahoe stop' command takes a while.
|
|
|
|
def _stop(res):
|
2014-08-17 14:32:17 +00:00
|
|
|
self.failUnless(os.path.exists(twistd_pid_file),
|
|
|
|
(twistd_pid_file, os.listdir(os.path.dirname(twistd_pid_file))))
|
2011-01-20 04:32:38 +00:00
|
|
|
return self.run_bintahoe(["--quiet", "stop", c1])
|
2010-02-01 00:44:29 +00:00
|
|
|
d.addCallback(_stop)
|
2014-08-17 14:36:57 +00:00
|
|
|
d.addBoth(self._remove, exit_trigger_file)
|
2010-02-01 00:44:29 +00:00
|
|
|
return d
|
|
|
|
|
2007-09-17 09:25:31 +00:00
|
|
|
def test_client(self):
|
2010-01-16 20:45:56 +00:00
|
|
|
self.skip_if_cannot_daemonize()
|
2014-08-17 14:32:17 +00:00
|
|
|
|
2007-09-17 09:25:31 +00:00
|
|
|
basedir = self.workdir("test_client")
|
|
|
|
c1 = os.path.join(basedir, "c1")
|
2014-08-17 14:36:57 +00:00
|
|
|
exit_trigger_file = os.path.join(c1, Client.EXIT_TRIGGER_FILE)
|
2014-08-17 14:32:17 +00:00
|
|
|
twistd_pid_file = os.path.join(c1, "twistd.pid")
|
|
|
|
portnum_file = os.path.join(c1, "client.port")
|
|
|
|
node_url_file = os.path.join(c1, "node.url")
|
|
|
|
config_file = os.path.join(c1, "tahoe.cfg")
|
2009-01-22 22:38:18 +00:00
|
|
|
|
2016-09-06 15:03:31 +00:00
|
|
|
d = self.run_bintahoe(["--quiet", "create-node", "--basedir", c1, "--webport", "0", "--hostname", "localhost"])
|
2009-01-22 22:38:18 +00:00
|
|
|
def _cb(res):
|
|
|
|
out, err, rc_or_sig = res
|
|
|
|
self.failUnlessEqual(rc_or_sig, 0)
|
2011-08-06 22:06:35 +00:00
|
|
|
|
|
|
|
# Check that the --webport option worked.
|
2014-08-17 14:32:17 +00:00
|
|
|
config = fileutil.read(config_file)
|
2011-08-06 22:06:35 +00:00
|
|
|
self.failUnlessIn('\nweb.port = 0\n', config)
|
|
|
|
|
|
|
|
# By writing this file, we get two minutes before the client will exit. This ensures
|
2009-01-22 22:38:18 +00:00
|
|
|
# that even if the 'stop' command doesn't work (and the test fails), the client should
|
|
|
|
# still terminate.
|
2014-08-17 14:36:57 +00:00
|
|
|
fileutil.write(exit_trigger_file, "")
|
2009-01-22 22:38:18 +00:00
|
|
|
# now it's safe to start the node
|
|
|
|
d.addCallback(_cb)
|
2007-09-18 22:17:26 +00:00
|
|
|
|
2007-09-19 20:56:00 +00:00
|
|
|
def _start(res):
|
2011-01-20 04:32:38 +00:00
|
|
|
return self.run_bintahoe(["--quiet", "start", c1])
|
2009-01-22 22:38:18 +00:00
|
|
|
d.addCallback(_start)
|
|
|
|
|
|
|
|
def _cb2(res):
|
|
|
|
out, err, rc_or_sig = res
|
2014-08-17 14:36:57 +00:00
|
|
|
fileutil.write(exit_trigger_file, "")
|
2009-05-20 03:36:20 +00:00
|
|
|
errstr = "rc=%d, OUT: '%s', ERR: '%s'" % (rc_or_sig, out, err)
|
2009-01-22 22:38:18 +00:00
|
|
|
self.failUnlessEqual(rc_or_sig, 0, errstr)
|
|
|
|
self.failUnlessEqual(out, "", errstr)
|
2009-01-27 00:30:46 +00:00
|
|
|
# self.failUnlessEqual(err, "", errstr) # See test_client_no_noise -- for now we ignore noise.
|
2007-09-17 09:25:31 +00:00
|
|
|
|
2007-09-19 20:56:00 +00:00
|
|
|
# the parent (twistd) has exited. However, twistd writes the pid
|
|
|
|
# from the child, not the parent, so we can't expect twistd.pid
|
|
|
|
# to exist quite yet.
|
2007-09-18 22:17:26 +00:00
|
|
|
|
2007-09-19 20:56:00 +00:00
|
|
|
# the node is running, but it might not have made it past the
|
|
|
|
# first reactor turn yet, and if we kill it too early, it won't
|
|
|
|
# remove the twistd.pid file. So wait until it does something
|
|
|
|
# that we know it won't do until after the first turn.
|
2009-01-22 22:38:18 +00:00
|
|
|
d.addCallback(_cb2)
|
2007-09-19 20:56:00 +00:00
|
|
|
|
2007-09-18 22:17:26 +00:00
|
|
|
def _node_has_started():
|
write node.url and portnum files atomically, to fix race in test_runner
Previously, test_runner sometimes fails because the _node_has_started()
poller fires after the portnum file has been opened, but before it has
actually been filled, allowing the test process to observe an empty file,
which flunks the test.
This adds a new fileutil.write_atomically() function (using the usual
write-to-.tmp-then-rename approach), and uses it for both node.url and
client.port . These files are written a bit before the node is really up and
running, but they're late enough for test_runner's purposes, which is to know
when it's safe to read client.port and use 'tahoe restart' (and therefore
SIGINT) to restart the node.
The current node/client code doesn't offer any better "are you really done
with startup" indicator.. the ideal approach would be to either watch the
logfile, or connect to its flogport, but both are a hassle. Changing the node
to write out a new "all done" file would be intrusive for regular
operations.
2012-05-14 20:32:03 +00:00
|
|
|
# this depends upon both files being created atomically
|
2014-08-17 14:32:17 +00:00
|
|
|
return os.path.exists(node_url_file) and os.path.exists(portnum_file)
|
2007-09-19 20:56:00 +00:00
|
|
|
d.addCallback(lambda res: self.poll(_node_has_started))
|
2007-09-18 22:17:26 +00:00
|
|
|
|
|
|
|
def _started(res):
|
2011-08-06 22:06:35 +00:00
|
|
|
# read the client.port file so we can check that its contents
|
|
|
|
# don't change on restart
|
2014-08-17 14:32:17 +00:00
|
|
|
self.portnum = fileutil.read(portnum_file)
|
2011-08-06 22:06:35 +00:00
|
|
|
|
2014-08-17 14:36:57 +00:00
|
|
|
fileutil.write(exit_trigger_file, "")
|
2014-08-17 14:32:17 +00:00
|
|
|
self.failUnless(os.path.exists(twistd_pid_file))
|
2009-01-22 22:38:18 +00:00
|
|
|
|
2011-08-06 22:06:35 +00:00
|
|
|
# rm this so we can detect when the second incarnation is ready
|
2014-08-17 14:32:17 +00:00
|
|
|
os.unlink(node_url_file)
|
2011-01-20 04:32:38 +00:00
|
|
|
return self.run_bintahoe(["--quiet", "restart", c1])
|
2007-09-18 22:17:26 +00:00
|
|
|
d.addCallback(_started)
|
|
|
|
|
2009-01-22 22:38:18 +00:00
|
|
|
def _cb3(res):
|
|
|
|
out, err, rc_or_sig = res
|
|
|
|
|
2014-08-17 14:36:57 +00:00
|
|
|
fileutil.write(exit_trigger_file, "")
|
2009-01-22 22:38:18 +00:00
|
|
|
errstr = "rc=%d, OUT: '%s', ERR: '%s'" % (rc_or_sig, out, err)
|
|
|
|
self.failUnlessEqual(rc_or_sig, 0, errstr)
|
|
|
|
self.failUnlessEqual(out, "", errstr)
|
2009-01-27 00:30:46 +00:00
|
|
|
# self.failUnlessEqual(err, "", errstr) # See test_client_no_noise -- for now we ignore noise.
|
2009-01-22 22:38:18 +00:00
|
|
|
d.addCallback(_cb3)
|
|
|
|
|
2007-09-18 22:17:26 +00:00
|
|
|
# again, the second incarnation of the node might not be ready yet,
|
|
|
|
# so poll until it is
|
|
|
|
d.addCallback(lambda res: self.poll(_node_has_started))
|
|
|
|
|
2011-08-06 22:06:35 +00:00
|
|
|
def _check_same_port(res):
|
2014-08-17 14:32:17 +00:00
|
|
|
self.failUnlessEqual(self.portnum, fileutil.read(portnum_file))
|
2011-08-06 22:06:35 +00:00
|
|
|
d.addCallback(_check_same_port)
|
|
|
|
|
2007-09-19 20:56:00 +00:00
|
|
|
# now we can kill it. TODO: On a slow machine, the node might kill
|
2011-08-06 22:06:35 +00:00
|
|
|
# itself before we get a chance to, especially if spawning the
|
2007-10-11 10:38:24 +00:00
|
|
|
# 'tahoe stop' command takes a while.
|
2007-09-18 22:17:26 +00:00
|
|
|
def _stop(res):
|
2014-08-17 14:36:57 +00:00
|
|
|
fileutil.write(exit_trigger_file, "")
|
2014-08-17 14:32:17 +00:00
|
|
|
self.failUnless(os.path.exists(twistd_pid_file),
|
|
|
|
(twistd_pid_file, os.listdir(os.path.dirname(twistd_pid_file))))
|
2011-01-20 04:32:38 +00:00
|
|
|
return self.run_bintahoe(["--quiet", "stop", c1])
|
2009-01-22 22:38:18 +00:00
|
|
|
d.addCallback(_stop)
|
|
|
|
|
|
|
|
def _cb4(res):
|
|
|
|
out, err, rc_or_sig = res
|
|
|
|
|
2014-08-17 14:36:57 +00:00
|
|
|
fileutil.write(exit_trigger_file, "")
|
2007-09-18 22:17:26 +00:00
|
|
|
# the parent has exited by now
|
2009-01-22 22:38:18 +00:00
|
|
|
errstr = "rc=%d, OUT: '%s', ERR: '%s'" % (rc_or_sig, out, err)
|
|
|
|
self.failUnlessEqual(rc_or_sig, 0, errstr)
|
|
|
|
self.failUnlessEqual(out, "", errstr)
|
2009-01-27 00:30:46 +00:00
|
|
|
# self.failUnlessEqual(err, "", errstr) # See test_client_no_noise -- for now we ignore noise.
|
2007-09-18 22:17:26 +00:00
|
|
|
# the parent was supposed to poll and wait until it sees
|
|
|
|
# twistd.pid go away before it exits, so twistd.pid should be
|
|
|
|
# gone by now.
|
2014-08-17 14:32:17 +00:00
|
|
|
self.failIf(os.path.exists(twistd_pid_file))
|
2009-01-22 22:38:18 +00:00
|
|
|
d.addCallback(_cb4)
|
2014-08-17 14:36:57 +00:00
|
|
|
d.addBoth(self._remove, exit_trigger_file)
|
2007-09-18 22:17:26 +00:00
|
|
|
return d
|
2007-09-17 09:25:31 +00:00
|
|
|
|
2011-08-06 23:16:52 +00:00
|
|
|
def _remove(self, res, file):
|
|
|
|
fileutil.remove(file)
|
|
|
|
return res
|
|
|
|
|
2007-09-19 08:50:27 +00:00
|
|
|
def test_baddir(self):
|
2010-01-16 20:45:56 +00:00
|
|
|
self.skip_if_cannot_daemonize()
|
2007-09-19 08:50:27 +00:00
|
|
|
basedir = self.workdir("test_baddir")
|
|
|
|
fileutil.make_dirs(basedir)
|
2009-01-22 22:38:18 +00:00
|
|
|
|
2011-01-20 04:32:38 +00:00
|
|
|
d = self.run_bintahoe(["--quiet", "start", "--basedir", basedir])
|
2009-01-22 22:38:18 +00:00
|
|
|
def _cb(res):
|
|
|
|
out, err, rc_or_sig = res
|
|
|
|
self.failUnlessEqual(rc_or_sig, 1)
|
'tahoe start': stop using the contents of .tac files
Instead of constructing a sys.argv for 'twistd' that reads the node's
.tac file, we construct arguments that tell twistd to use a special
in-memory-only plugin that creates the desired node instance directly.
We still use the name of the .tac file to decide which kind of instance
to make (Client, IntroducerNode, KeyGenerator, StatsGatherer), but never
actually read the contents of the .tac file. Later improvements could
change this to look inside the tahoe.cfg for a nodetype= directive, etc.
This also makes it easy to have "tahoe start BASEDIR" pass the rest of
its arguments on to twistd, so e.g. "tahoe start BASEDIR --nodaemon
--profile=prof.out" does what you'd expect "twistd --nodaemon
--profile=prof.out" to do. "tahoe run BASEDIR" is thus simply aliased to
"tahoe start BASEDIR --nodaemon". This removes the need to special-case
--profile and --syslog.
I also removed some of the default logging behavior:
before:
'tahoe start' = 'twistd --logfile BASEDIR logs/twistd.log'
'tahoe start --profile' adds '--profile=profiling_results.prof --savestats'
'tahoe run' = 'twistd --nodaemon --logfile BASEDIR/logs/tahoesvc.log'
after:
'tahoe start' = 'twistd --logfile BASEDIR logs/twistd.log'
unless --logfile, --nodaemon, or --syslog are passed
'tahoe start --profile' invalid, use 'tahoe start --profile=OUTPUT'
'tahoe run' = 'twistd --nodaemon'
so log messages go to stdout
This finally enables 'tahoe run' to work with all node types, including
the key-generator and stats-gatherer.
It gets 'tahoe start' one step closer to accepting --reactor= . To
actually accomplish this will require this file, the enclosing
__init_.py files, and everything they import to avoid importing the
reactor. (if anything imports twisted.internet.reactor before
startstop_node.start() gets to run, then --reactor= comes too late).
That will take a lot of work, and requires lazy-loading of many core
libraries (foolscap.logging in particular), and removing a lot of code
from src/allmydata/__init__.py .
2012-05-23 07:19:27 +00:00
|
|
|
self.failUnless("is not a recognizable node directory" in err, err)
|
2009-01-22 22:38:18 +00:00
|
|
|
d.addCallback(_cb)
|
|
|
|
|
2009-01-27 21:32:45 +00:00
|
|
|
def _then_stop_it(res):
|
2011-01-20 04:32:38 +00:00
|
|
|
return self.run_bintahoe(["--quiet", "stop", "--basedir", basedir])
|
2009-01-27 21:32:45 +00:00
|
|
|
d.addCallback(_then_stop_it)
|
|
|
|
|
|
|
|
def _cb2(res):
|
|
|
|
out, err, rc_or_sig = res
|
|
|
|
self.failUnlessEqual(rc_or_sig, 2)
|
|
|
|
self.failUnless("does not look like a running node directory" in err)
|
|
|
|
d.addCallback(_cb2)
|
|
|
|
|
|
|
|
def _then_start_in_bogus_basedir(res):
|
|
|
|
not_a_dir = os.path.join(basedir, "bogus")
|
2011-01-20 04:32:38 +00:00
|
|
|
return self.run_bintahoe(["--quiet", "start", "--basedir", not_a_dir])
|
2009-01-27 21:32:45 +00:00
|
|
|
d.addCallback(_then_start_in_bogus_basedir)
|
|
|
|
|
|
|
|
def _cb3(res):
|
|
|
|
out, err, rc_or_sig = res
|
|
|
|
self.failUnlessEqual(rc_or_sig, 1)
|
'tahoe start': stop using the contents of .tac files
Instead of constructing a sys.argv for 'twistd' that reads the node's
.tac file, we construct arguments that tell twistd to use a special
in-memory-only plugin that creates the desired node instance directly.
We still use the name of the .tac file to decide which kind of instance
to make (Client, IntroducerNode, KeyGenerator, StatsGatherer), but never
actually read the contents of the .tac file. Later improvements could
change this to look inside the tahoe.cfg for a nodetype= directive, etc.
This also makes it easy to have "tahoe start BASEDIR" pass the rest of
its arguments on to twistd, so e.g. "tahoe start BASEDIR --nodaemon
--profile=prof.out" does what you'd expect "twistd --nodaemon
--profile=prof.out" to do. "tahoe run BASEDIR" is thus simply aliased to
"tahoe start BASEDIR --nodaemon". This removes the need to special-case
--profile and --syslog.
I also removed some of the default logging behavior:
before:
'tahoe start' = 'twistd --logfile BASEDIR logs/twistd.log'
'tahoe start --profile' adds '--profile=profiling_results.prof --savestats'
'tahoe run' = 'twistd --nodaemon --logfile BASEDIR/logs/tahoesvc.log'
after:
'tahoe start' = 'twistd --logfile BASEDIR logs/twistd.log'
unless --logfile, --nodaemon, or --syslog are passed
'tahoe start --profile' invalid, use 'tahoe start --profile=OUTPUT'
'tahoe run' = 'twistd --nodaemon'
so log messages go to stdout
This finally enables 'tahoe run' to work with all node types, including
the key-generator and stats-gatherer.
It gets 'tahoe start' one step closer to accepting --reactor= . To
actually accomplish this will require this file, the enclosing
__init_.py files, and everything they import to avoid importing the
reactor. (if anything imports twisted.internet.reactor before
startstop_node.start() gets to run, then --reactor= comes too late).
That will take a lot of work, and requires lazy-loading of many core
libraries (foolscap.logging in particular), and removing a lot of code
from src/allmydata/__init__.py .
2012-05-23 07:19:27 +00:00
|
|
|
self.failUnlessIn("does not look like a directory at all", err)
|
2009-01-27 21:32:45 +00:00
|
|
|
d.addCallback(_cb3)
|
|
|
|
return d
|