| Index: third_party/pexpect/tests/test_which.py
|
| diff --git a/third_party/pexpect/tests/test_which.py b/third_party/pexpect/tests/test_which.py
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..f909214865c2e7bb57fc37bd5fc4198b47c2414a
|
| --- /dev/null
|
| +++ b/third_party/pexpect/tests/test_which.py
|
| @@ -0,0 +1,274 @@
|
| +# -*- coding: utf-8 -*-
|
| +import subprocess
|
| +import tempfile
|
| +import shutil
|
| +import errno
|
| +import os
|
| +
|
| +import pexpect
|
| +from . import PexpectTestCase
|
| +
|
| +import pytest
|
| +
|
| +
|
| +class TestCaseWhich(PexpectTestCase.PexpectTestCase):
|
| + " Tests for pexpect.which(). "
|
| +
|
| + def test_which_finds_ls(self):
|
| + " which() can find ls(1). "
|
| + exercise = pexpect.which("ls")
|
| + assert exercise is not None
|
| + assert exercise.startswith('/')
|
| +
|
| + def test_os_defpath_which(self):
|
| + " which() finds an executable in $PATH and returns its abspath. "
|
| +
|
| + bin_dir = tempfile.mkdtemp()
|
| + temp_obj = tempfile.NamedTemporaryFile(
|
| + suffix=u'.sh', prefix=u'ǝpoɔıun-',
|
| + dir=bin_dir, delete=False)
|
| + bin_path = temp_obj.name
|
| + fname = os.path.basename(temp_obj.name)
|
| + save_path = os.environ['PATH']
|
| + save_defpath = os.defpath
|
| +
|
| + try:
|
| + # setup
|
| + os.environ['PATH'] = ''
|
| + os.defpath = bin_dir
|
| + with open(bin_path, 'w') as fp:
|
| + pass
|
| +
|
| + # given non-executable,
|
| + os.chmod(bin_path, 0o400)
|
| +
|
| + # exercise absolute and relative,
|
| + assert pexpect.which(bin_path) is None
|
| + assert pexpect.which(fname) is None
|
| +
|
| + # given executable,
|
| + os.chmod(bin_path, 0o700)
|
| +
|
| + # exercise absolute and relative,
|
| + assert pexpect.which(bin_path) == bin_path
|
| + assert pexpect.which(fname) == bin_path
|
| +
|
| + finally:
|
| + # restore,
|
| + os.environ['PATH'] = save_path
|
| + os.defpath = save_defpath
|
| +
|
| + # destroy scratch files and folders,
|
| + if os.path.exists(bin_path):
|
| + os.unlink(bin_path)
|
| + if os.path.exists(bin_dir):
|
| + os.rmdir(bin_dir)
|
| +
|
| + def test_path_search_which(self):
|
| + " which() finds an executable in $PATH and returns its abspath. "
|
| + fname = 'gcc'
|
| + bin_dir = tempfile.mkdtemp()
|
| + bin_path = os.path.join(bin_dir, fname)
|
| + save_path = os.environ['PATH']
|
| + try:
|
| + # setup
|
| + os.environ['PATH'] = bin_dir
|
| + with open(bin_path, 'w') as fp:
|
| + pass
|
| +
|
| + # given non-executable,
|
| + os.chmod(bin_path, 0o400)
|
| +
|
| + # exercise absolute and relative,
|
| + assert pexpect.which(bin_path) is None
|
| + assert pexpect.which(fname) is None
|
| +
|
| + # given executable,
|
| + os.chmod(bin_path, 0o700)
|
| +
|
| + # exercise absolute and relative,
|
| + assert pexpect.which(bin_path) == bin_path
|
| + assert pexpect.which(fname) == bin_path
|
| +
|
| + finally:
|
| + # restore,
|
| + os.environ['PATH'] = save_path
|
| +
|
| + # destroy scratch files and folders,
|
| + if os.path.exists(bin_path):
|
| + os.unlink(bin_path)
|
| + if os.path.exists(bin_dir):
|
| + os.rmdir(bin_dir)
|
| +
|
| + def test_which_follows_symlink(self):
|
| + " which() follows symlinks and returns its path. "
|
| + fname = 'original'
|
| + symname = 'extra-crispy'
|
| + bin_dir = tempfile.mkdtemp()
|
| + bin_path = os.path.join(bin_dir, fname)
|
| + sym_path = os.path.join(bin_dir, symname)
|
| + save_path = os.environ['PATH']
|
| + try:
|
| + # setup
|
| + os.environ['PATH'] = bin_dir
|
| + with open(bin_path, 'w') as fp:
|
| + pass
|
| + os.chmod(bin_path, 0o400)
|
| + os.symlink(bin_path, sym_path)
|
| +
|
| + # should not be found because symlink points to non-executable
|
| + assert pexpect.which(symname) is None
|
| +
|
| + # but now it should -- because it is executable
|
| + os.chmod(bin_path, 0o700)
|
| + assert pexpect.which(symname) == sym_path
|
| +
|
| + finally:
|
| + # restore,
|
| + os.environ['PATH'] = save_path
|
| +
|
| + # destroy scratch files, symlinks, and folders,
|
| + if os.path.exists(sym_path):
|
| + os.unlink(sym_path)
|
| + if os.path.exists(bin_path):
|
| + os.unlink(bin_path)
|
| + if os.path.exists(bin_dir):
|
| + os.rmdir(bin_dir)
|
| +
|
| + def test_which_should_not_match_folders(self):
|
| + " Which does not match folders, even though they are executable. "
|
| + # make up a path and insert a folder that is 'executable', a naive
|
| + # implementation might match (previously pexpect versions 3.2 and
|
| + # sh versions 1.0.8, reported by @lcm337.)
|
| + fname = 'g++'
|
| + bin_dir = tempfile.mkdtemp()
|
| + bin_dir2 = os.path.join(bin_dir, fname)
|
| + save_path = os.environ['PATH']
|
| + try:
|
| + os.environ['PATH'] = bin_dir
|
| + os.mkdir(bin_dir2, 0o755)
|
| + # should not be found because it is not executable *file*,
|
| + # but rather, has the executable bit set, as a good folder
|
| + # should -- it should not be returned because it fails isdir()
|
| + exercise = pexpect.which(fname)
|
| + assert exercise is None
|
| +
|
| + finally:
|
| + # restore,
|
| + os.environ['PATH'] = save_path
|
| + # destroy scratch folders,
|
| + for _dir in (bin_dir2, bin_dir,):
|
| + if os.path.exists(_dir):
|
| + os.rmdir(_dir)
|
| +
|
| + def test_which_should_match_other_group_user(self):
|
| + " which() returns executables by other, group, and user ownership. "
|
| + # create an executable and test that it is found using which() for
|
| + # each of the 'other', 'group', and 'user' permission bits.
|
| + fname = 'g77'
|
| + bin_dir = tempfile.mkdtemp()
|
| + bin_path = os.path.join(bin_dir, fname)
|
| + save_path = os.environ['PATH']
|
| + try:
|
| + # setup
|
| + os.environ['PATH'] = bin_dir
|
| +
|
| + # an interpreted script requires the ability to read,
|
| + # whereas a binary program requires only to be executable.
|
| + #
|
| + # to gain access to a binary program, we make a copy of
|
| + # the existing system program echo(1).
|
| + bin_echo = None
|
| + for pth in ('/bin/echo', '/usr/bin/echo'):
|
| + if os.path.exists(pth):
|
| + bin_echo = pth
|
| + break
|
| + bin_which = None
|
| + for pth in ('/bin/which', '/usr/bin/which'):
|
| + if os.path.exists(pth):
|
| + bin_which = pth
|
| + break
|
| + if not bin_echo or not bin_which:
|
| + pytest.skip('needs `echo` and `which` binaries')
|
| + shutil.copy(bin_echo, bin_path)
|
| + isroot = os.getuid() == 0
|
| + for should_match, mode in (
|
| + # note that although the file may have matching 'group' or
|
| + # 'other' executable permissions, it is *not* executable
|
| + # because the current uid is the owner of the file -- which
|
| + # takes precedence
|
| + (False, 0o000), # ----------, no
|
| + (isroot, 0o001), # ---------x, no
|
| + (isroot, 0o010), # ------x---, no
|
| + (True, 0o100), # ---x------, yes
|
| + (False, 0o002), # --------w-, no
|
| + (False, 0o020), # -----w----, no
|
| + (False, 0o200), # --w-------, no
|
| + (isroot, 0o003), # --------wx, no
|
| + (isroot, 0o030), # -----wx---, no
|
| + (True, 0o300), # --wx------, yes
|
| + (False, 0o004), # -------r--, no
|
| + (False, 0o040), # ----r-----, no
|
| + (False, 0o400), # -r--------, no
|
| + (isroot, 0o005), # -------r-x, no
|
| + (isroot, 0o050), # ----r-x---, no
|
| + (True, 0o500), # -r-x------, yes
|
| + (False, 0o006), # -------rw-, no
|
| + (False, 0o060), # ----rw----, no
|
| + (False, 0o600), # -rw-------, no
|
| + (isroot, 0o007), # -------rwx, no
|
| + (isroot, 0o070), # ----rwx---, no
|
| + (True, 0o700), # -rwx------, yes
|
| + (isroot, 0o4001), # ---S-----x, no
|
| + (isroot, 0o4010), # ---S--x---, no
|
| + (True, 0o4100), # ---s------, yes
|
| + (isroot, 0o4003), # ---S----wx, no
|
| + (isroot, 0o4030), # ---S-wx---, no
|
| + (True, 0o4300), # --ws------, yes
|
| + (isroot, 0o2001), # ------S--x, no
|
| + (isroot, 0o2010), # ------s---, no
|
| + (True, 0o2100), # ---x--S---, yes
|
| +
|
| + ):
|
| + mode_str = '{0:0>4o}'.format(mode)
|
| +
|
| + # given file mode,
|
| + os.chmod(bin_path, mode)
|
| +
|
| + # exercise whether we may execute
|
| + can_execute = True
|
| + try:
|
| + subprocess.Popen(fname).wait() == 0
|
| + except OSError as err:
|
| + if err.errno != errno.EACCES:
|
| + raise
|
| + # permission denied
|
| + can_execute = False
|
| +
|
| + assert should_match == can_execute, (
|
| + should_match, can_execute, mode_str)
|
| +
|
| + # exercise whether which(1) would match
|
| + proc = subprocess.Popen((bin_which, fname),
|
| + env={'PATH': bin_dir},
|
| + stdout=subprocess.PIPE)
|
| + bin_which_match = bool(not proc.wait())
|
| + assert should_match == bin_which_match, (
|
| + should_match, bin_which_match, mode_str)
|
| +
|
| + # finally, exercise pexpect's which(1) matches
|
| + # the same.
|
| + pexpect_match = bool(pexpect.which(fname))
|
| +
|
| + assert should_match == pexpect_match == bin_which_match, (
|
| + should_match, pexpect_match, bin_which_match, mode_str)
|
| +
|
| + finally:
|
| + # restore,
|
| + os.environ['PATH'] = save_path
|
| +
|
| + # destroy scratch files and folders,
|
| + if os.path.exists(bin_path):
|
| + os.unlink(bin_path)
|
| + if os.path.exists(bin_dir):
|
| + os.rmdir(bin_dir)
|
|
|