def run_main(args, exit_code=0, expect_stderr=False): """Run main() of the datalad, do basic checks and provide outputs Parameters ---------- args : list List of string cmdline arguments to pass exit_code : int Expected exit code. Would raise AssertionError if differs expect_stderr : bool or string Either to expect stderr output. If string -- match Returns ------- stdout, stderr strings Output produced """ with patch('sys.stderr', new_callable=StringIO) as cmerr: with patch('sys.stdout', new_callable=StringIO) as cmout: with assert_raises(SystemExit) as cm: main(args) assert_equal(cm.exception.code, exit_code) # exit code must be 0 stdout = cmout.getvalue() stderr = cmerr.getvalue() if expect_stderr == False: assert_equal(stderr, "") elif expect_stderr == True: # do nothing -- just return pass else: # must be a string assert_equal(stderr, expect_stderr) return stdout, stderr
def test_ssh_option(): # This test is hacky in that it depends on systems commonly configuring # `AcceptEnv LC_*` in their sshd_config. If it ends up causing problems, we # should just scrap it. with patch.dict('os.environ', {"LC_DATALAD_HACK": 'hackbert'}): with swallow_outputs() as cmo: # need to give smth with .fileno ;) main([ "datalad", "sshrun", "-oSendEnv=LC_DATALAD_HACK", "localhost", "echo $LC_DATALAD_HACK" ]) assert_equal(cmo.out.strip(), "hackbert")
def test_exit_code(): # will relay actual exit code on CommandError cmd = ['sshrun', 'localhost', 'exit 42'] with assert_raises(SystemExit) as cme: if isinstance(sys.stdout, StringIO): # running nosetests without -s with swallow_outputs(): # need to give smth with .fileno ;) main(cmd) else: # to test both scenarios main(cmd) assert_equal(cme.exception.code, 42)
def test_exit_code(): # will relay actual exit code on CommandError cmd = ['datalad', 'sshrun', 'localhost', 'exit 42'] with assert_raises(SystemExit) as cme: # running nosetests without -s if isinstance(sys.stdout, StringIO): # pragma: no cover with swallow_outputs(): # need to give smth with .fileno ;) main(cmd) else: # to test both scenarios main(cmd) assert_equal(cme.exception.code, 42)
def test_ssh_option(): # This test is hacky in that detecting the sent value depends on systems # commonly configuring `AcceptEnv LC_*` in their sshd_config. If we get # back an empty value, assume that isn't configured, and skip the test. with patch.dict('os.environ', {"LC_DATALAD_HACK": 'hackbert'}): with swallow_outputs() as cmo: main([ "datalad", "sshrun", "-oSendEnv=LC_DATALAD_HACK", "localhost", "echo $LC_DATALAD_HACK" ]) out = cmo.out.strip() if not out: raise SkipTest( "SSH target probably does not accept LC_* variables. " "Skipping") assert_equal(out, "hackbert")
def test_run_cmdline_disambiguation(path): Dataset(path).create() with chpwd(path): # Without a positional argument starting a command, any option is # treated as an option to 'datalad run'. with swallow_outputs() as cmo: with patch("datalad.core.local.run._execute_command") as exec_cmd: with assert_raises(SystemExit): main(["datalad", "run", "--message"]) exec_cmd.assert_not_called() assert_in("message: expected one", cmo.err) # If we want to pass an option as the first value of a command (e.g., # because we are using a runscript with containers-run), we can do this # with "--". with patch("datalad.core.local.run._execute_command") as exec_cmd: with assert_raises(SystemExit): main(["datalad", "run", "--", "--message"]) exec_cmd.assert_called_once_with( '"--message"' if on_windows else "--message", path, expected_exit=None) # And a twist on above: Our parser mishandles --version (gh-3067), # treating 'datalad run CMD --version' as 'datalad --version'. version_stream = "out" with swallow_outputs() as cmo: with assert_raises(SystemExit) as cm: main(["datalad", "run", "echo", "--version"]) eq_(cm.exception.code, 0) out = getattr(cmo, version_stream) with swallow_outputs() as cmo: with assert_raises(SystemExit): main(["datalad", "--version"]) version_out = getattr(cmo, version_stream) ok_(version_out) eq_(version_out, out) # We can work around that (i.e., make "--version" get passed as # command) with "--". with patch("datalad.core.local.run._execute_command") as exec_cmd: with assert_raises(SystemExit): main(["datalad", "run", "--", "echo", "--version"]) exec_cmd.assert_called_once_with( '"echo" "--version"' if on_windows else "echo --version", path, expected_exit=None)
def test_run_cmdline_disambiguation(path): Dataset(path).create() with chpwd(path): # Without a positional argument starting a command, any option is # treated as an option to 'datalad run'. with swallow_outputs() as cmo: with patch("datalad.core.local.run._execute_command") as exec_cmd: with assert_raises(SystemExit): main(["datalad", "run", "--message"]) exec_cmd.assert_not_called() assert_in("message: expected one", cmo.err) # If we want to pass an option as the first value of a command (e.g., # because we are using a runscript with containers-run), we can do this # with "--". with patch("datalad.core.local.run._execute_command") as exec_cmd: with assert_raises(SystemExit): main(["datalad", "run", "--", "--message"]) exec_cmd.assert_called_once_with( "--message", path, expected_exit=None) # And a twist on above: Our parser mishandles --version (gh-3067), # treating 'datalad run CMD --version' as 'datalad --version'. version_stream = "err" if PY2 else "out" with swallow_outputs() as cmo: with assert_raises(SystemExit) as cm: main(["datalad", "run", "echo", "--version"]) eq_(cm.exception.code, 0) out = getattr(cmo, version_stream) with swallow_outputs() as cmo: with assert_raises(SystemExit): main(["datalad", "--version"]) version_out = getattr(cmo, version_stream) ok_(version_out) eq_(version_out, out) # We can work around that (i.e., make "--version" get passed as # command) with "--". with patch("datalad.core.local.run._execute_command") as exec_cmd: with assert_raises(SystemExit): main(["datalad", "run", "--", "echo", "--version"]) exec_cmd.assert_called_once_with( "echo --version", path, expected_exit=None)
def test_run_cmdline_disambiguation(path): Dataset(path).create() with chpwd(path): # Without a positional argument starting a command, any option is # treated as an option to 'datalad run'. with swallow_outputs() as cmo: with patch("datalad.core.local.run._execute_command") as exec_cmd: with assert_raises(SystemExit): main(["datalad", "run", "--message"]) exec_cmd.assert_not_called() assert_in("message: expected one", cmo.err) # If we want to pass an option as the first value of a command (e.g., # because we are using a runscript with containers-run), we can do this # with "--". with patch("datalad.core.local.run._execute_command") as exec_cmd: with assert_raises(SystemExit): main(["datalad", "run", "--", "--message"]) exec_cmd.assert_called_once_with( '"--message"' if on_windows else "--message", path, expected_exit=None) # Our parser used to mishandle --version (gh-3067), # treating 'datalad run CMD --version' as 'datalad --version'. # but that is no longer the case and echo --version should work with or # without explicit "--" separator for sep in [[], ['--']]: with patch("datalad.core.local.run._execute_command") as exec_cmd: with assert_raises(SystemExit): main(["datalad", "run"] + sep + ["echo", "--version"]) exec_cmd.assert_called_once_with( '"echo" "--version"' if on_windows else "echo --version", path, expected_exit=None)
def test_ssh_ipv4_6_incompatible(): with assert_raises(SystemExit): main(["datalad", "sshrun", "-4", "-6", "localhost", "true"])