mirror of
https://github.com/ceph/ceph
synced 2024-12-23 11:54:11 +00:00
0566de4979
This lets you do things such as "test -e /foo && bar" or "cd /tmp && blah". Remember that shell pipelines do not detect errors in anything but the last command.
323 lines
10 KiB
Python
323 lines
10 KiB
Python
from nose.tools import eq_ as eq
|
|
from cStringIO import StringIO
|
|
|
|
import fudge
|
|
import gevent.event
|
|
import nose
|
|
import logging
|
|
|
|
from .. import run
|
|
|
|
from .util import assert_raises
|
|
|
|
|
|
@nose.with_setup(fudge.clear_expectations)
|
|
@fudge.with_fakes
|
|
def test_run_log_simple():
|
|
ssh = fudge.Fake('SSHConnection')
|
|
cmd = ssh.expects('exec_command')
|
|
cmd.with_args("foo 'bar baz'")
|
|
in_ = fudge.Fake('ChannelFile(stdin)')
|
|
out = fudge.Fake('ChannelFile(stdout)')
|
|
err = fudge.Fake('ChannelFile(stderr)')
|
|
cmd.returns((in_, out, err))
|
|
in_.expects('close').with_args()
|
|
in_chan = fudge.Fake('channel')
|
|
in_chan.expects('shutdown_write').with_args()
|
|
in_.has_attr(channel=in_chan)
|
|
out.expects('xreadlines').with_args().returns(['foo', 'bar'])
|
|
err.expects('xreadlines').with_args().returns(['bad'])
|
|
logger = fudge.Fake('logger')
|
|
log_err = fudge.Fake('log_err')
|
|
logger.expects('getChild').with_args('err').returns(log_err)
|
|
log_err.expects('log').with_args(logging.INFO, 'bad')
|
|
log_out = fudge.Fake('log_out')
|
|
logger.expects('getChild').with_args('out').returns(log_out)
|
|
log_out.expects('log').with_args(logging.INFO, 'foo')
|
|
log_out.expects('log').with_args(logging.INFO, 'bar')
|
|
channel = fudge.Fake('channel')
|
|
out.has_attr(channel=channel)
|
|
channel.expects('recv_exit_status').with_args().returns(0)
|
|
r = run.run(
|
|
client=ssh,
|
|
logger=logger,
|
|
args=['foo', 'bar baz'],
|
|
)
|
|
eq(r.exitstatus, 0)
|
|
|
|
|
|
@nose.with_setup(fudge.clear_expectations)
|
|
@fudge.with_fakes
|
|
def test_run_capture_stdout():
|
|
ssh = fudge.Fake('SSHConnection')
|
|
cmd = ssh.expects('exec_command')
|
|
cmd.with_args("foo 'bar baz'")
|
|
in_ = fudge.Fake('ChannelFile(stdin)')
|
|
out = fudge.Fake('ChannelFile(stdout)')
|
|
err = fudge.Fake('ChannelFile(stderr)')
|
|
cmd.returns((in_, out, err))
|
|
in_.expects('close').with_args()
|
|
in_chan = fudge.Fake('channel')
|
|
in_chan.expects('shutdown_write').with_args()
|
|
in_.has_attr(channel=in_chan)
|
|
out.remember_order()
|
|
out.expects('read').with_args().returns('foo\nb')
|
|
out.expects('read').with_args().returns('ar\n')
|
|
out.expects('read').with_args().returns('')
|
|
err.expects('xreadlines').with_args().returns(['bad'])
|
|
logger = fudge.Fake('logger')
|
|
log_err = fudge.Fake('log_err')
|
|
logger.expects('getChild').with_args('err').returns(log_err)
|
|
log_err.expects('log').with_args(logging.INFO, 'bad')
|
|
channel = fudge.Fake('channel')
|
|
out.has_attr(channel=channel)
|
|
channel.expects('recv_exit_status').with_args().returns(0)
|
|
out_f = StringIO()
|
|
r = run.run(
|
|
client=ssh,
|
|
logger=logger,
|
|
args=['foo', 'bar baz'],
|
|
stdout=out_f,
|
|
)
|
|
eq(r.exitstatus, 0)
|
|
assert r.stdout is out_f
|
|
eq(r.stdout.getvalue(), 'foo\nbar\n')
|
|
|
|
|
|
@nose.with_setup(fudge.clear_expectations)
|
|
@fudge.with_fakes
|
|
def test_run_status_bad():
|
|
ssh = fudge.Fake('SSHConnection')
|
|
cmd = ssh.expects('exec_command')
|
|
cmd.with_args("foo")
|
|
in_ = fudge.Fake('ChannelFile').is_a_stub()
|
|
out = fudge.Fake('ChannelFile').is_a_stub()
|
|
err = fudge.Fake('ChannelFile').is_a_stub()
|
|
cmd.returns((in_, out, err))
|
|
out.expects('xreadlines').with_args().returns([])
|
|
err.expects('xreadlines').with_args().returns([])
|
|
logger = fudge.Fake('logger').is_a_stub()
|
|
channel = fudge.Fake('channel')
|
|
out.has_attr(channel=channel)
|
|
channel.expects('recv_exit_status').with_args().returns(42)
|
|
e = assert_raises(
|
|
run.CommandFailedError,
|
|
run.run,
|
|
client=ssh,
|
|
logger=logger,
|
|
args=['foo'],
|
|
)
|
|
eq(e.command, 'foo')
|
|
eq(e.exitstatus, 42)
|
|
eq(str(e), "Command failed with status 42: 'foo'")
|
|
|
|
|
|
@nose.with_setup(fudge.clear_expectations)
|
|
@fudge.with_fakes
|
|
def test_run_status_bad_nocheck():
|
|
ssh = fudge.Fake('SSHConnection')
|
|
cmd = ssh.expects('exec_command')
|
|
cmd.with_args("foo")
|
|
in_ = fudge.Fake('ChannelFile').is_a_stub()
|
|
out = fudge.Fake('ChannelFile').is_a_stub()
|
|
err = fudge.Fake('ChannelFile').is_a_stub()
|
|
cmd.returns((in_, out, err))
|
|
out.expects('xreadlines').with_args().returns([])
|
|
err.expects('xreadlines').with_args().returns([])
|
|
logger = fudge.Fake('logger').is_a_stub()
|
|
channel = fudge.Fake('channel')
|
|
out.has_attr(channel=channel)
|
|
channel.expects('recv_exit_status').with_args().returns(42)
|
|
r = run.run(
|
|
client=ssh,
|
|
logger=logger,
|
|
args=['foo'],
|
|
check_status=False,
|
|
)
|
|
eq(r.exitstatus, 42)
|
|
|
|
|
|
@nose.with_setup(fudge.clear_expectations)
|
|
@fudge.with_fakes
|
|
def test_run_status_crash():
|
|
ssh = fudge.Fake('SSHConnection')
|
|
cmd = ssh.expects('exec_command')
|
|
cmd.with_args("foo")
|
|
in_ = fudge.Fake('ChannelFile').is_a_stub()
|
|
out = fudge.Fake('ChannelFile').is_a_stub()
|
|
err = fudge.Fake('ChannelFile').is_a_stub()
|
|
cmd.returns((in_, out, err))
|
|
out.expects('xreadlines').with_args().returns([])
|
|
err.expects('xreadlines').with_args().returns([])
|
|
logger = fudge.Fake('logger').is_a_stub()
|
|
channel = fudge.Fake('channel')
|
|
out.has_attr(channel=channel)
|
|
channel.expects('recv_exit_status').with_args().returns(-1)
|
|
transport = ssh.expects('get_transport').with_args().returns_fake()
|
|
transport.expects('is_active').with_args().returns(True)
|
|
e = assert_raises(
|
|
run.CommandCrashedError,
|
|
run.run,
|
|
client=ssh,
|
|
logger=logger,
|
|
args=['foo'],
|
|
)
|
|
eq(e.command, 'foo')
|
|
eq(str(e), "Command crashed: 'foo'")
|
|
|
|
|
|
@nose.with_setup(fudge.clear_expectations)
|
|
@fudge.with_fakes
|
|
def test_run_status_crash_nocheck():
|
|
ssh = fudge.Fake('SSHConnection')
|
|
cmd = ssh.expects('exec_command')
|
|
cmd.with_args("foo")
|
|
in_ = fudge.Fake('ChannelFile').is_a_stub()
|
|
out = fudge.Fake('ChannelFile').is_a_stub()
|
|
err = fudge.Fake('ChannelFile').is_a_stub()
|
|
cmd.returns((in_, out, err))
|
|
out.expects('xreadlines').with_args().returns([])
|
|
err.expects('xreadlines').with_args().returns([])
|
|
logger = fudge.Fake('logger').is_a_stub()
|
|
channel = fudge.Fake('channel')
|
|
out.has_attr(channel=channel)
|
|
channel.expects('recv_exit_status').with_args().returns(-1)
|
|
r = run.run(
|
|
client=ssh,
|
|
logger=logger,
|
|
args=['foo'],
|
|
check_status=False,
|
|
)
|
|
assert r.exitstatus is None
|
|
|
|
|
|
@nose.with_setup(fudge.clear_expectations)
|
|
@fudge.with_fakes
|
|
def test_run_status_lost():
|
|
ssh = fudge.Fake('SSHConnection')
|
|
cmd = ssh.expects('exec_command')
|
|
cmd.with_args("foo")
|
|
in_ = fudge.Fake('ChannelFile').is_a_stub()
|
|
out = fudge.Fake('ChannelFile').is_a_stub()
|
|
err = fudge.Fake('ChannelFile').is_a_stub()
|
|
cmd.returns((in_, out, err))
|
|
out.expects('xreadlines').with_args().returns([])
|
|
err.expects('xreadlines').with_args().returns([])
|
|
logger = fudge.Fake('logger').is_a_stub()
|
|
channel = fudge.Fake('channel')
|
|
out.has_attr(channel=channel)
|
|
channel.expects('recv_exit_status').with_args().returns(-1)
|
|
transport = ssh.expects('get_transport').with_args().returns_fake()
|
|
transport.expects('is_active').with_args().returns(False)
|
|
e = assert_raises(
|
|
run.ConnectionLostError,
|
|
run.run,
|
|
client=ssh,
|
|
logger=logger,
|
|
args=['foo'],
|
|
)
|
|
|
|
eq(e.command, 'foo')
|
|
eq(str(e), "SSH connection was lost: 'foo'")
|
|
|
|
|
|
@nose.with_setup(fudge.clear_expectations)
|
|
@fudge.with_fakes
|
|
def test_run_status_lost_nocheck():
|
|
ssh = fudge.Fake('SSHConnection')
|
|
cmd = ssh.expects('exec_command')
|
|
cmd.with_args("foo")
|
|
in_ = fudge.Fake('ChannelFile').is_a_stub()
|
|
out = fudge.Fake('ChannelFile').is_a_stub()
|
|
err = fudge.Fake('ChannelFile').is_a_stub()
|
|
cmd.returns((in_, out, err))
|
|
out.expects('xreadlines').with_args().returns([])
|
|
err.expects('xreadlines').with_args().returns([])
|
|
logger = fudge.Fake('logger').is_a_stub()
|
|
channel = fudge.Fake('channel')
|
|
out.has_attr(channel=channel)
|
|
channel.expects('recv_exit_status').with_args().returns(-1)
|
|
r = run.run(
|
|
client=ssh,
|
|
logger=logger,
|
|
args=['foo'],
|
|
check_status=False,
|
|
)
|
|
assert r.exitstatus is None
|
|
|
|
|
|
@nose.with_setup(fudge.clear_expectations)
|
|
@fudge.with_fakes
|
|
def test_run_nowait():
|
|
ssh = fudge.Fake('SSHConnection')
|
|
cmd = ssh.expects('exec_command')
|
|
cmd.with_args("foo")
|
|
in_ = fudge.Fake('ChannelFile').is_a_stub()
|
|
out = fudge.Fake('ChannelFile').is_a_stub()
|
|
err = fudge.Fake('ChannelFile').is_a_stub()
|
|
cmd.returns((in_, out, err))
|
|
out.expects('xreadlines').with_args().returns([])
|
|
err.expects('xreadlines').with_args().returns([])
|
|
logger = fudge.Fake('logger').is_a_stub()
|
|
channel = fudge.Fake('channel')
|
|
out.has_attr(channel=channel)
|
|
channel.expects('recv_exit_status').with_args().returns(42)
|
|
r = run.run(
|
|
client=ssh,
|
|
logger=logger,
|
|
args=['foo'],
|
|
wait=False,
|
|
)
|
|
eq(r.command, 'foo')
|
|
assert isinstance(r.exitstatus, gevent.event.AsyncResult)
|
|
e = assert_raises(
|
|
run.CommandFailedError,
|
|
r.exitstatus.get,
|
|
)
|
|
eq(e.exitstatus, 42)
|
|
eq(str(e), "Command failed with status 42: 'foo'")
|
|
|
|
|
|
@nose.with_setup(fudge.clear_expectations)
|
|
@fudge.with_fakes
|
|
def test_run_stdin_pipe():
|
|
ssh = fudge.Fake('SSHConnection')
|
|
cmd = ssh.expects('exec_command')
|
|
cmd.with_args("foo")
|
|
in_ = fudge.Fake('ChannelFile').is_a_stub()
|
|
out = fudge.Fake('ChannelFile').is_a_stub()
|
|
err = fudge.Fake('ChannelFile').is_a_stub()
|
|
cmd.returns((in_, out, err))
|
|
out.expects('xreadlines').with_args().returns([])
|
|
err.expects('xreadlines').with_args().returns([])
|
|
logger = fudge.Fake('logger').is_a_stub()
|
|
channel = fudge.Fake('channel')
|
|
out.has_attr(channel=channel)
|
|
channel.expects('recv_exit_status').with_args().returns(0)
|
|
r = run.run(
|
|
client=ssh,
|
|
logger=logger,
|
|
args=['foo'],
|
|
stdin=run.PIPE,
|
|
wait=False,
|
|
)
|
|
r.stdin.write('bar')
|
|
eq(r.command, 'foo')
|
|
assert isinstance(r.exitstatus, gevent.event.AsyncResult)
|
|
eq(r.exitstatus.ready(), False)
|
|
got = r.exitstatus.get()
|
|
eq(got, 0)
|
|
|
|
|
|
def test_quote_simple():
|
|
got = run.quote(['a b', ' c', 'd e '])
|
|
eq(got, "'a b' ' c' 'd e '")
|
|
|
|
def test_quote_and_quote():
|
|
got = run.quote(['echo', 'this && is embedded', '&&', 'that was standalone'])
|
|
eq(got, "echo 'this && is embedded' '&&' 'that was standalone'")
|
|
|
|
def test_quote_and_raw():
|
|
got = run.quote(['true', run.Raw('&&'), 'echo', 'yay'])
|
|
eq(got, "true && echo yay")
|