mirror of
https://github.com/tahoe-lafs/tahoe-lafs.git
synced 2025-01-29 07:33:52 +00:00
9375056b61
This sets the stage for further changes to the startup process so that "async things" are done before we create the Client instance while still reporting early failures to the shell where "tahoe start" is running Also adds a bunch of test-coverage for the things that got moved around, even though they didn't have coverage before
210 lines
6.9 KiB
Python
210 lines
6.9 KiB
Python
import os
|
|
import shutil
|
|
import subprocess
|
|
from os.path import join
|
|
from mock import patch
|
|
from StringIO import StringIO
|
|
|
|
from twisted.trial import unittest
|
|
from allmydata.scripts import runner
|
|
|
|
|
|
#@patch('twisted.internet.reactor')
|
|
@patch('allmydata.scripts.tahoe_start.subprocess')
|
|
class RunStartTests(unittest.TestCase):
|
|
|
|
def setUp(self):
|
|
d = super(RunStartTests, self).setUp()
|
|
self.node_dir = self.mktemp()
|
|
os.mkdir(self.node_dir)
|
|
return d
|
|
|
|
def _placeholder_nodetype(self, nodetype):
|
|
fname = join(self.node_dir, '{}.tac'.format(nodetype))
|
|
with open(fname, 'w') as f:
|
|
f.write("test placeholder")
|
|
|
|
def _pid_file(self, pid):
|
|
fname = join(self.node_dir, 'twistd.pid')
|
|
with open(fname, 'w') as f:
|
|
f.write(u"{}\n".format(pid))
|
|
|
|
def _logs(self, logs):
|
|
os.mkdir(join(self.node_dir, 'logs'))
|
|
fname = join(self.node_dir, 'logs', 'twistd.log')
|
|
with open(fname, 'w') as f:
|
|
f.write(logs)
|
|
|
|
def test_start_defaults(self, _subprocess):
|
|
self._placeholder_nodetype('client')
|
|
self._pid_file(1234)
|
|
self._logs('one log\ntwo log\nred log\nblue log\n')
|
|
|
|
config = runner.parse_or_exit_with_explanation([
|
|
# have to do this so the tests don't muck around in
|
|
# ~/.tahoe (the default)
|
|
'--node-directory', self.node_dir,
|
|
'start',
|
|
])
|
|
i, o, e = StringIO(), StringIO(), StringIO()
|
|
try:
|
|
with patch('allmydata.scripts.tahoe_start.os'):
|
|
with patch('allmydata.scripts.runner.sys') as s:
|
|
exit_code = [None]
|
|
def _exit(code):
|
|
exit_code[0] = code
|
|
s.exit = _exit
|
|
|
|
def launch(*args, **kw):
|
|
with open(join(self.node_dir, 'logs', 'twistd.log'), 'a') as f:
|
|
f.write('client running\n') # "the magic"
|
|
_subprocess.check_call = launch
|
|
runner.dispatch(config, i, o, e)
|
|
except Exception:
|
|
pass
|
|
|
|
self.assertEqual([0], exit_code)
|
|
self.assertTrue('Node has started' in o.getvalue())
|
|
|
|
def test_start_fails(self, _subprocess):
|
|
self._placeholder_nodetype('client')
|
|
self._logs('existing log line\n')
|
|
|
|
config = runner.parse_or_exit_with_explanation([
|
|
# have to do this so the tests don't muck around in
|
|
# ~/.tahoe (the default)
|
|
'--node-directory', self.node_dir,
|
|
'start',
|
|
])
|
|
|
|
i, o, e = StringIO(), StringIO(), StringIO()
|
|
with patch('allmydata.scripts.tahoe_start.time') as t:
|
|
with patch('allmydata.scripts.runner.sys') as s:
|
|
exit_code = [None]
|
|
def _exit(code):
|
|
exit_code[0] = code
|
|
s.exit = _exit
|
|
|
|
thetime = [0]
|
|
def _time():
|
|
thetime[0] += 0.1
|
|
return thetime[0]
|
|
t.time = _time
|
|
|
|
def launch(*args, **kw):
|
|
with open(join(self.node_dir, 'logs', 'twistd.log'), 'a') as f:
|
|
f.write('a new log line\n')
|
|
_subprocess.check_call = launch
|
|
|
|
runner.dispatch(config, i, o, e)
|
|
|
|
# should print out the collected logs and an error-code
|
|
self.assertTrue("a new log line" in o.getvalue())
|
|
self.assertEqual([1], exit_code)
|
|
|
|
def test_start_subprocess_fails(self, _subprocess):
|
|
self._placeholder_nodetype('client')
|
|
self._logs('existing log line\n')
|
|
|
|
config = runner.parse_or_exit_with_explanation([
|
|
# have to do this so the tests don't muck around in
|
|
# ~/.tahoe (the default)
|
|
'--node-directory', self.node_dir,
|
|
'start',
|
|
])
|
|
|
|
i, o, e = StringIO(), StringIO(), StringIO()
|
|
with patch('allmydata.scripts.tahoe_start.time'):
|
|
with patch('allmydata.scripts.runner.sys') as s:
|
|
# undo patch for the exception-class
|
|
_subprocess.CalledProcessError = subprocess.CalledProcessError
|
|
exit_code = [None]
|
|
def _exit(code):
|
|
exit_code[0] = code
|
|
s.exit = _exit
|
|
|
|
def launch(*args, **kw):
|
|
raise subprocess.CalledProcessError(42, "tahoe")
|
|
_subprocess.check_call = launch
|
|
|
|
runner.dispatch(config, i, o, e)
|
|
|
|
# should get our "odd" error-code
|
|
self.assertEqual([42], exit_code)
|
|
|
|
def test_start_help(self, _subprocess):
|
|
self._placeholder_nodetype('client')
|
|
|
|
std = StringIO()
|
|
with patch('sys.stdout') as stdo:
|
|
stdo.write = std.write
|
|
try:
|
|
runner.parse_or_exit_with_explanation([
|
|
# have to do this so the tests don't muck around in
|
|
# ~/.tahoe (the default)
|
|
'--node-directory', self.node_dir,
|
|
'start',
|
|
'--help',
|
|
], stdout=std)
|
|
self.fail("Should get exit")
|
|
except SystemExit as e:
|
|
print(e)
|
|
|
|
self.assertIn(
|
|
"Usage:",
|
|
std.getvalue()
|
|
)
|
|
|
|
def test_start_unknown_node_type(self, _subprocess):
|
|
self._placeholder_nodetype('bogus')
|
|
|
|
config = runner.parse_or_exit_with_explanation([
|
|
# have to do this so the tests don't muck around in
|
|
# ~/.tahoe (the default)
|
|
'--node-directory', self.node_dir,
|
|
'start',
|
|
])
|
|
|
|
i, o, e = StringIO(), StringIO(), StringIO()
|
|
with patch('allmydata.scripts.runner.sys') as s:
|
|
exit_code = [None]
|
|
def _exit(code):
|
|
exit_code[0] = code
|
|
s.exit = _exit
|
|
|
|
runner.dispatch(config, i, o, e)
|
|
|
|
# should print out the collected logs and an error-code
|
|
self.assertIn(
|
|
"is not a recognizable node directory",
|
|
e.getvalue()
|
|
)
|
|
self.assertEqual([1], exit_code)
|
|
|
|
def test_start_nodedir_not_dir(self, _subprocess):
|
|
shutil.rmtree(self.node_dir)
|
|
assert not os.path.isdir(self.node_dir)
|
|
|
|
config = runner.parse_or_exit_with_explanation([
|
|
# have to do this so the tests don't muck around in
|
|
# ~/.tahoe (the default)
|
|
'--node-directory', self.node_dir,
|
|
'start',
|
|
])
|
|
|
|
i, o, e = StringIO(), StringIO(), StringIO()
|
|
with patch('allmydata.scripts.runner.sys') as s:
|
|
exit_code = [None]
|
|
def _exit(code):
|
|
exit_code[0] = code
|
|
s.exit = _exit
|
|
|
|
runner.dispatch(config, i, o, e)
|
|
|
|
# should print out the collected logs and an error-code
|
|
self.assertIn(
|
|
"does not look like a directory at all",
|
|
e.getvalue()
|
|
)
|
|
self.assertEqual([1], exit_code)
|