def test_local_path_doesnt_match_PATH(): echo_path = Path('echo') assert not echo_path.exists(), 'This path is supposed to be nonexistent.' with raises(PROGRAM_NOT_FOUND_ERROR): cmd(echo_path).run() with raises(duct.StatusError): sh(echo_path).run()
def test_sign_detached(): detached = sh("python -m saltpack sign --binary --detached").read( input=message, decode=False) print(detached) _, temp = tempfile.mkstemp() with open(temp, 'wb') as f: f.write(detached) command = ["python", "-m", "saltpack", "verify", "--signature", temp, "--binary", "--debug"] cmd(*command).read(input=message)
def test_sign_detached(): detached = sh("python -m saltpack sign --binary --detached").read( input=message, decode=False) print(detached) _, temp = tempfile.mkstemp() with open(temp, 'wb') as f: f.write(detached) command = [ "python", "-m", "saltpack", "verify", "--signature", temp, "--binary", "--debug" ] cmd(*command).read(input=message)
def main(): os.chdir(str(here)) status = sh("git status --porcelain").read() if status: print("repo isn't clean") return 1 cmd("git", "push", "origin", "master").run() cmd( "ssh", "*****@*****.**", "cd /srv/jacko.io && git pull --ff-only && peru sync --no-cache", ).run()
def test_sign_detached(): detached = sh("python -m saltpack sign --binary --detached") \ .input(message) \ .stdout_capture() \ .run() \ .stdout print(detached) _, temp = tempfile.mkstemp() with open(temp, 'wb') as f: f.write(detached) command = [ "python", "-m", "saltpack", "verify", "--signature", temp, "--binary", "--debug" ] cmd(*command).input(message).read()
def test_run_local_path(): '''Trying to execute 'test.sh' without the leading dot fails in bash and subprocess.py. But it needs to succeed with Path('test.sh'), because there's no difference between that and Path('./test.sh').''' if os.name == 'nt': extension = '.bat' code = textwrap.dedent(u'''\ @echo off echo foo ''') else: extension = '.sh' code = textwrap.dedent(u'''\ #! /bin/sh echo foo ''') # Use a random name just in case. random_letters = binascii.hexlify(os.urandom(4)).decode() local_script = 'test_' + random_letters + extension script_path = Path(local_script) try: with script_path.open('w') as f: f.write(code) script_path.chmod(0o755) assert 'foo' == cmd(script_path).read() assert 'foo' == sh(script_path).read() finally: script_path.unlink()
def test_run_local_path(): '''Trying to execute 'test.sh' without the leading dot fails in bash and subprocess.py. But it needs to succeed with Path('test.sh'), because there's no difference between that and Path('./test.sh').''' if os.name == 'nt': extension = '.bat' code = textwrap.dedent(u'''\ @echo off echo foo ''') else: extension = '.sh' code = textwrap.dedent(u'''\ #! /bin/sh echo foo ''') # Use a random name just in case. random_letters = binascii.hexlify(os.urandom(4)).decode() local_script = 'test_' + random_letters + extension script_path = Path(local_script) try: with script_path.open('w') as f: f.write(code) script_path.chmod(0o755) assert 'foo' == cmd(script_path).read() finally: script_path.unlink()
def replace(a, b): code = textwrap.dedent('''\ import sys input_str = sys.stdin.read() sys.stdout.write(input_str.replace({0}, {1})) '''.format(repr(a), repr(b))) return cmd('python', '-c', code)
def test_invalid_io_args(): with raises(TypeError): cmd('foo').stdin_bytes(1.0).run() with raises(TypeError): cmd('foo').stdin_path(1.0).run() with raises(TypeError): cmd('foo').stdout_path(1.0).run() with raises(TypeError): cmd('foo').stderr_path(1.0).run()
def test_invalid_io_args(): with raises(TypeError): cmd('foo').input(1.0).run() with raises(TypeError): cmd('foo').stdin(1.0).run() with raises(TypeError): cmd('foo').stdout(1.0).run() with raises(TypeError): cmd('foo').stderr(1.0).run()
def test_right_side_fails_to_start(): # Python 3 raises the FileNotFoundError, but Python 2 is less consistent. with raises(Exception) as e1: open("file_that_doesnt_exist") not_found_errno = e1.value.errno with raises(Exception) as e2: sleep_cmd(1000000).pipe(cmd("nonexistent_command_abc123")).run() assert e2.value.errno == not_found_errno
def test_dir_with_relative_paths(): # We need to make sure relative exe paths are valid even when we're using # `dir`. Subprocess spawning on Unix doesn't behave that way by default, so # duct absolutifies relative paths in that case, and that's what we're # testing here. child_working_dir = tempfile.mkdtemp() interpreter_path = sys.executable interpreter_dir = os.path.dirname(interpreter_path) interpreter_relative_path = os.path.join( ".", os.path.basename(interpreter_path)) current_dir = os.getcwd() try: os.chdir(interpreter_dir) # Run an empty Python program. This will succeed if the path to the # interpreter is valid, but it will fail if the path is interpreted # relative to the child's working dir. cmd(interpreter_relative_path, "-c", "").dir(child_working_dir).run() finally: os.chdir(current_dir)
def head_bytes(c): code = textwrap.dedent('''\ import os # PyPy3 on Travis has a wonky bug where stdin and stdout can't read # unicode. This is a workaround. The bug doesn't repro on Arch, though, # so presumably it'll be fixed when they upgrade eventually. stdin = os.fdopen(0, 'r') stdout = os.fdopen(1, 'w') input_str = stdin.read({0}) stdout.write(input_str) '''.format(c)) return cmd('python', '-c', code)
def test_commands_can_be_paths(): tempdir = tempfile.mkdtemp() path = Path(tempdir, "script.bat") # Note that Path.open() rejects Python 2 non-unicode strings. with open(str(path), 'w') as f: if os.name == 'nt': f.write('@echo off\n') else: f.write('#! /bin/sh\n') f.write('echo some stuff\n') path.chmod(0o755) assert 'some stuff' == cmd(path).read()
def test_commands_can_be_paths(): tempdir = tempfile.mkdtemp() path = Path(tempdir, "script.bat") # Note that Path.open() rejects Python 2 non-unicode strings. with open(str(path), 'w') as f: if os.name == 'nt': f.write('@echo off\n') else: f.write('#! /bin/sh\n') f.write('echo some stuff\n') path.chmod(0o755) assert 'some stuff' == cmd(path).read() assert 'some stuff' == sh(path).read()
def test_pipe_SIGPIPE(): '''On the left side of the pipe, run a command that outputs text forever. That program should receive SIGPIPE when the right side terminates.''' zeroes_code = textwrap.dedent('''\ import sys try: while True: sys.stdout.write('0') except Exception: pass ''') zeroes = cmd('python', '-c', zeroes_code) out = zeroes.unchecked().pipe(head_bytes(5)).read() assert "00000" == out
def test_pipe_SIGPIPE(): '''On the left side of the pipe, run a command that outputs text forever. That program should receive SIGPIPE when the right side terminates.''' zeroes_code = textwrap.dedent('''\ import sys try: while True: sys.stdout.write('0') except Exception: pass ''') zeroes = cmd('python', '-c', zeroes_code) out = zeroes.pipe(head_bytes(5)).read() assert "00000" == out
def test_kill_with_grandchild(): # We're going to start a child process, and that child is going to start a # grandchild. The grandchild is going to sleep forever. We'll read some # output from the child to make sure it's done starting the grandchild, and # then we'll kill the child. Now, the grandchild will not be killed, and it # will still hold a write handle to the stdout pipe. So this tests that the # wait done by kill only waits on the child to exit, and does not wait on # IO to finish. # # This test leaks the grandchild process. I'm sorry. grandchild_code = r""" import time time.sleep(24 * 60 * 60) # sleep for 1 day """ child_code = r""" import subprocess import sys p = subprocess.Popen(["python", "-c", '''{}''']) print("started") sys.stdout.flush() p.wait() """.format(grandchild_code) # Capturing stderr means an IO thread is spawned, even though we're using a # ReaderHandle to read stdout. What we're testing here is that kill() # doesn't wait on that IO thread. reader = cmd("python", "-c", child_code).stderr_capture().reader() # Read "started" from the child to make sure we don't kill it before it # starts the grandchild. assert reader.read(7) == b"started" # Ok, this had better not block! reader.kill()
def pwd(): return cmd('python', '-c', 'import os; print(os.getcwd())')
def test_then(): print_a = cmd('python', '-c', 'print("A")') assert 'A' == true().then(print_a).read() assert '' == false().then(print_a).unchecked().read()
def echo_var(var_name): code = textwrap.dedent('''\ import os print(os.environ.get("{0}", "")) '''.format(var_name)) return cmd('python', '-c', code)
def exit_cmd(n): return cmd('python', '-c', 'import sys; sys.exit({0})'.format(n))
def sleep_cmd(seconds): return cmd('python', '-c', 'import time; time.sleep({})'.format(seconds))
def echo_err_cmd(s): return cmd('python', '-c', 'import sys; sys.stderr.write(" ".join(sys.argv[1:]) + "\\n")', s)
def test_decrypt_keybase_message(): decrypted = cmd("python", "-m", "saltpack", "decrypt", keybase_test_secret_key) \ .read(input=keybase_test_ciphertext) assert decrypted == keybase_test_plaintext
def echo_cmd(s): return cmd('python', '-c', 'import sys; print(" ".join(sys.argv[1:]))', s)
def echo_x(): code = textwrap.dedent('''\ import os print(os.environ.get("x", "")) ''') return cmd('python', '-c', code)
def cat_cmd(): return cmd( 'python', '-c', 'import sys, shutil; shutil.copyfileobj(sys.stdin, sys.stdout)')