Пример #1
0
    def run(*popenargs, input=None, timeout=None, check=False, **kwargs):
        """Emulating the run routine found in future subprocess modules
        """
        if input is not None:
            if 'stdin' in kwargs:
                raise ValueError('stdin and input args may not both be used.')
            kwargs['stdin'] = subprocess.PIPE

        with subprocess.Popen(*popenargs, **kwargs) as process:
            try:
                stdout, stderr = process.communicate(input, timeout=timeout)
            except subprocess.TimeoutExpired:
                process.kill()
                stdout, stderr = process.communicate()
                raise subprocess.TimeoutExpired(process.args,
                                                timeout,
                                                output=stdout,
                                                stderr=stderr)
            except:
                process.kill()
                process.wait()
                raise
            retcode = process.poll()
            if check and retcode:
                raise subprocess.CalledProcessError(retcode,
                                                    process.args,
                                                    output=stdout + stderr)
        return CompletedProcess(process.args, retcode, stdout, stderr)
Пример #2
0
    def test_pull(self):
        source = "source-file"
        destination = mock.MagicMock(spec=io.BufferedIOBase)

        self.popen_mock.return_value.stdin = None
        self.popen_mock.return_value.stdout.read.return_value = b"stdout data"
        self.popen_mock.return_value.communicate.side_effect = (
            subprocess.TimeoutExpired("foo", 1),
            (b"communicate data", b"error"),
        )

        self.multipass_command.pull_file(source=source, destination=destination)

        self.assertEqual(
            [
                mock.call(
                    ["multipass", "transfer", source, "-"],
                    stdin=subprocess.DEVNULL,
                    stdout=subprocess.PIPE,
                ),
                mock.call().stdout.read(1024),
                mock.call().communicate(timeout=1),
                mock.call().communicate(timeout=1),
            ],
            self.popen_mock.mock_calls,
        )

        self.assertEqual(
            [mock.call(b"stdout data"), mock.call(b"communicate data")],
            destination.write.mock_calls,
        )
Пример #3
0
    def test_buffered_push(self):
        source = mock.MagicMock(spec=io.BufferedIOBase)
        source.read.side_effect = (b"read data", b"")
        destination = "{}/destination-file".format(self.instance_name)

        self.popen_mock.return_value.stdout = None
        self.popen_mock.return_value.communicate.side_effect = (
            subprocess.TimeoutExpired("foo", 1),
            (b"communicate data", b"error"),
        )

        self.multipass_command.push_file(
            source=source, destination=destination, bufsize=9
        )

        self.assertEqual(
            [
                mock.call(
                    ["multipass", "transfer", "-", destination], stdin=subprocess.PIPE
                ),
                mock.call().stdin.write(b"read data"),
                mock.call().communicate(timeout=1),
                mock.call().communicate(timeout=1),
            ],
            self.popen_mock.mock_calls,
        )

        self.assertEqual(source.read.mock_calls, [mock.call(9), mock.call(9)])
Пример #4
0
    def start(self):
        self.proc = subprocess.Popen([
            '{}/lightningd/lightningd'.format(
                LIGHTNING_SRC), '--lightning-dir={}'.format(
                    self.lightning_dir), '--funding-confirms=3',
            '--dev-force-tmp-channel-id=0000000000000000000000000000000000000000000000000000000000000000',
            '--dev-force-privkey=0000000000000000000000000000000000000000000000000000000000000001',
            '--dev-force-bip32-seed=0000000000000000000000000000000000000000000000000000000000000001',
            '--dev-force-channel-secrets=0000000000000000000000000000000000000000000000000000000000000010/0000000000000000000000000000000000000000000000000000000000000011/0000000000000000000000000000000000000000000000000000000000000012/0000000000000000000000000000000000000000000000000000000000000013/0000000000000000000000000000000000000000000000000000000000000014/FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF',
            '--dev-bitcoind-poll=1', '--dev-fast-gossip',
            '--dev-gossip-time=1565587763', '--bind-addr=127.0.0.1:{}'.format(
                self.lightning_port), '--network=regtest',
            '--bitcoin-rpcuser=rpcuser', '--bitcoin-rpcpassword=rpcpass',
            '--bitcoin-rpcport={}'.format(
                self.bitcoind.port), '--log-level=debug', '--log-file=log'
        ] + self.startup_flags)
        self.rpc = lightning.LightningRpc(
            os.path.join(self.lightning_dir, "regtest", "lightning-rpc"))

        def node_ready(rpc):
            try:
                rpc.getinfo()
                return True
            except Exception:
                return False

        if not wait_for(lambda: node_ready(self.rpc)):
            raise subprocess.TimeoutExpired(self.proc,
                                            "Could not contact lightningd")

        # Make sure that we see any funds that come to our wallet
        for i in range(5):
            self.rpc.newaddr()
Пример #5
0
def call_process(cmd, timeout=10, input='/dev/null', output=False, error=False, checkRC=False):
    assert cmd != ''

    curr = os.getcwd()
    stdout = os.path.join(curr, 'stdout')
    stderr = os.path.join(curr, 'stderr')

    command = '{} {} {} < "{}" 1>"{}" 2>"{}"'.format(config['tests']['timeout_prog'], timeout, cmd, input, stdout,
                                                   stderr)

    #print('call_process', command)

    rc = os.system(command)

    return_code = (rc >> 8) & 0xff

    if return_code == 124:  #gtimeout TIMEOUT status
        raise subprocess.TimeoutExpired(command, timeout)

    def get_data(filename):
        with open(filename, 'r', errors='ignore') as f:
            return f.read()

    if checkRC and return_code != 0:
        raise subprocess.CalledProcessError(return_code, command, output=get_data(stdout),stderr=get_data(stderr))

    if output and error:
        return get_data(stdout) and get_data(stderr)
    if output:
        return get_data(stdout)
    if error:
        return get_data(stderr)
Пример #6
0
async def test_subprocess_exceptions(caplog: LogCaptureFixture,
                                     hass: HomeAssistant) -> None:
    """Test that notify subprocess exceptions are handled correctly."""

    with patch("homeassistant.components.command_line.notify.subprocess.Popen"
               ) as check_output:
        check_output.return_value.__enter__ = check_output
        check_output.return_value.communicate.side_effect = [
            subprocess.TimeoutExpired("cmd", 10),
            None,
            subprocess.SubprocessError(),
        ]

        await setup_test_service(hass, {"command": "exit 0"})
        assert await hass.services.async_call(DOMAIN,
                                              "test", {"message": "error"},
                                              blocking=True)
        assert check_output.call_count == 2
        assert "Timeout for command" in caplog.text

        assert await hass.services.async_call(DOMAIN,
                                              "test", {"message": "error"},
                                              blocking=True)
        assert check_output.call_count == 4
        assert "Error trying to exec command" in caplog.text
Пример #7
0
def runCmd(cmd, cmd_timeout=300):
    ''' run command without showing console window on windows - return stdout and stderr as strings '''
    startupinfo = None
    output = ""
    output_err = ""
    debug_log("runCmd: {}".format(cmd))
    if os.name == 'nt':
        startupinfo = subprocess.STARTUPINFO()
        startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
    try:
        proc = subprocess.Popen(cmd,
                                bufsize=-1,
                                startupinfo=startupinfo,
                                stdout=subprocess.PIPE,
                                stderr=subprocess.PIPE,
                                stdin=None,
                                shell=False,
                                universal_newlines=False)
    except SubprocessError as e:
        proc = None
        debug_log("exception in runCmd: {}".format(e), logging.ERROR)
    if proc is not None:
        try:
            outputb, output_errb = proc.communicate()
            output = outputb.decode('utf-8', 'replace')
            output_err = output_errb.decode('utf-8', 'replace')
        except subprocess.TimeoutExpired(timeout=cmd_timeout):
            proc.kill()
            debug_log("runCmd: Process killed due to timeout", logging.WARNING)
    else:
        debug_log("runCmd: Proc was none", logging.WARNING)
    return output, output_err
Пример #8
0
def run(*popenargs, timeout=None, check=False, ssh=None, **kwargs):
    """Run command for ZFS functions that also works over ssh."""

    if ssh is None:
        with sp.Popen(*popenargs, **kwargs) as process:
            try:
                stdout, stderr = process.communicate(timeout=timeout)
            except sp.TimeoutExpired:
                process.kill()
                stdout, stderr = process.communicate()
                raise sp.TimeoutExpired(process.args,
                                        timeout,
                                        output=stdout,
                                        stderr=stderr)
            except:
                process.kill()
                process.wait()
                raise
            retcode = process.poll()
    else:
        args = ' '.join(popenargs[0]) if not isinstance(popenargs[0],
                                                        str) else popenargs[0]

        try:
            stdin, stdout, stderr = ssh.exec_command(args,
                                                     *popenargs[1:],
                                                     timeout=timeout)
            if kwargs.get('stdin', None):
                shutil.copyfileobj(kwargs['stdin'], stdin, 128 * 1024)
            stdin.close()
            retcode = stdout.channel.recv_exit_status()
            stdout, stderr = ''.join(stdout.readlines()), ''.join(
                stderr.readlines())
        except socket.timeout:
            stdout, stderr = None, None
            raise sp.TimeoutExpired(popenargs[0],
                                    timeout,
                                    output=stdout,
                                    stderr=stderr)

    if check and retcode:
        raise sp.CalledProcessError(retcode,
                                    popenargs[0],
                                    output=stdout,
                                    stderr=stderr)

    return sp.CompletedProcess(popenargs[0], retcode, stdout, stderr)
Пример #9
0
def docker_runs(args, images, docker_args=(), image_args=()):
    docker_argv = check_docker()
    container_id = f"satex{os.getpid()}"
    argv = ["run", "--name", container_id, "--rm"]
    if hasattr(args, "timeout"):
        argv += ["-e", f"TIMEOUT={args.timeout}"]
    quiet = hasattr(args, "quiet") and args.quiet
    for opt in _docker_opts:
        if getattr(args, opt) is not None:
            val = getattr(args, opt)
            if isinstance(val, list):
                for v in val:
                    if opt == "volume":
                        v = easy_volume(v)
                    argv += ["--%s" % opt, v]
            else:
                argv += ["--%s" % opt, val]
    argv += list(docker_args)
    image_argv = ["--mode", args.mode
                  ] if hasattr(args, "mode") and args.mode else []
    image_argv += list(image_args)
    run_args = {}
    if quiet:
        run_args["stdout"] = subprocess.DEVNULL
        run_args["stderr"] = subprocess.DEVNULL
    global stop
    stop = False
    for image in images:
        image = f"{DOCKER_NS}/{image}"
        prepare_image(args, docker_argv, image)
        cmd = docker_argv + argv + [image] + image_argv
        if args.pretend:
            print(" ".join(cmd))
        else:

            def killer(s, f):
                global stop
                stop = True
                warn("Killing solver...")
                argv = docker_argv + ["kill", container_id]
                subprocess.run(argv, stdout=subprocess.DEVNULL)

            signal.signal(signal.SIGINT, killer)
            info(" ".join(cmd)) if not quiet else None
            ret = subprocess.run(cmd, **run_args).returncode
            signal.signal(signal.SIGINT, signal.SIG_DFL)
            if stop:
                sys.exit(1)
            if ret == 124:
                if args.fail_if_timeout:
                    raise subprocess.TimeoutExpired(image, args.timeout)
                elif not quiet:
                    warn(f"{image} timeout")
            else:
                if not (ret == 0 or 10 <= ret <= 20):
                    if not quiet:
                        error(f"Solver failed with return code {ret}")
    if not args.pretend:
        return ret
Пример #10
0
def run_subprocess(*popenargs,
                   input=None,
                   capture_output=False,
                   timeout=None,
                   check=False,
                   communicate_fn=None,
                   **kwargs):
    """
    a clone of :function:`subprocess.run` which allows custom handling of communication
    :param popenargs:
    :param input:
    :param capture_output:
    :param timeout:
    :param check:
    :param communicate_fn:
    :param kwargs:
    :return:
    """
    if input is not None:
        if 'stdin' in kwargs:
            raise ValueError('stdin and input arguments may not both be used.')
        kwargs['stdin'] = subprocess.PIPE

    if capture_output:
        if kwargs.get('stdout') is not None or kwargs.get(
                'stderr') is not None:
            raise ValueError('stdout and stderr arguments may not be used '
                             'with capture_output.')
        kwargs['stdout'] = subprocess.PIPE
        kwargs['stderr'] = subprocess.PIPE

    def communicate(process, input=None, timeout=None):
        return (communicate_fn(process, input=input, timeout=timeout)
                if communicate_fn else process.communicate(input=input,
                                                           timeout=timeout))

    with subprocess.Popen(*popenargs, **kwargs) as process:
        try:
            stdout, stderr = communicate(process, input, timeout=timeout)
        except subprocess.TimeoutExpired as e:
            process.kill()
            if sys.platform == 'win32':
                e.stdout, e.stderr = communicate(process)
            else:
                process.wait()
            raise subprocess.TimeoutExpired(process.args,
                                            timeout,
                                            output=stdout,
                                            stderr=stderr)
        except:  # also handles kb interrupts
            process.kill()
            raise
        retcode = process.poll()
        if check and retcode:
            raise subprocess.CalledProcessError(retcode,
                                                process.args,
                                                output=stdout,
                                                stderr=stderr)
    return subprocess.CompletedProcess(process.args, retcode, stdout, stderr)
Пример #11
0
def run_helper(
    cmd: List[str],
    check_exit_code: bool = True,
    timeout: Optional[float] = None,
    env: Optional[Dict[str, str]] = None,
    working_dir: Optional[Path] = None,
) -> types.CompletedProcess:
    check(
        bool(cmd) and cmd[0] is not None and isinstance(cmd[0], str),
        AssertionError("run takes a list of str, not a str"),
    )

    # When using catchsegv, only SIGSEGV will cause a backtrace to be printed.
    # We can also include SIGABRT by setting the following environment variable.
    if cmd[0].endswith("catchsegv"):
        if env is None:
            env = {}
        env["SEGFAULT_SIGNALS"] = "SEGV ABRT"

    env_child: Optional[Dict[str, str]] = None
    if env:
        log(f"Extra environment variables are: {env}")
        env_child = os.environ.copy()
        env_child.update(env)

    with subprocess.Popen(
            cmd,
            encoding="utf-8",
            errors="ignore",
            start_new_session=True,
            env=env_child,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            cwd=working_dir,
    ) as process:
        try:
            stdout, stderr = process.communicate(input=None, timeout=timeout)
        except subprocess.TimeoutExpired:
            try:
                posix_kill_group(process)
            except AttributeError:
                process.kill()
            stdout, stderr = process.communicate()
            assert timeout  # noqa
            raise subprocess.TimeoutExpired(process.args, timeout, stdout,
                                            stderr)
        except:  # noqa
            try:
                posix_kill_group(process)
            except AttributeError:
                process.kill()
            raise

        exit_code = process.poll()
        if check_exit_code and exit_code != 0:
            raise subprocess.CalledProcessError(exit_code, process.args,
                                                stdout, stderr)
        return subprocess.CompletedProcess(process.args, exit_code, stdout,
                                           stderr)
Пример #12
0
def test_does_not_crash_on_exception():
    GIT_REPO = "[email protected]:rossumai/_non_existing_repo_"

    with patch("chart_updater.git.run") as run:
        run.side_effect = subprocess.TimeoutExpired("cmd", 1)
        updater = Updater(Git(GIT_REPO), HelmRepo(HELM_REPO_URL))
        updater.update_loop(one_shot=True)
        run.assert_called_once()
Пример #13
0
    def test_exec_cmd_timed_out_without_serial(self, mock_run_command):
        mock_run_command.side_effect = subprocess.TimeoutExpired(
            cmd='mock_command', timeout=0.01)

        with self.assertRaisesRegex(
                adb.AdbTimeoutError,
                'Timed out executing command "adb fake-cmd" after 0.01s.'):
            adb.AdbProxy().fake_cmd(timeout=0.01)
Пример #14
0
 async def read_async(self) -> str or None:
     self._set_timeout_handler()
     await self._create_async_subprocess()
     stdout, stderr = await self._process.communicate()
     self._timeout_handler and self._timeout_handler.cancel()
     if self._is_timeout:
         raise subprocess.TimeoutExpired(self._cmd, self._timeout)
     return self._read_std(stdout, stderr)
Пример #15
0
 def popen_mock(args, **kwargs):
     # force the login processes to raise TimeoutExpired
     if args[2] == 'login':
         mock_process = create_mock_process()
         mock_process.communicate.side_effect = subprocess.TimeoutExpired(
             cmd='docker login', timeout=30)
         return mock_process
     return create_mock_process()
Пример #16
0
def subprocess_run(*popenargs,
                   input=None,
                   timeout=None,
                   check=False,
                   **kwargs):
    """Run command with arguments and return a CompletedProcess instance.

    The returned instance will have attributes args, returncode, stdout and
    stderr. By default, stdout and stderr are not captured, and those attributes
    will be None. Pass stdout=PIPE and/or stderr=PIPE in order to capture them.

    If check is True and the exit code was non-zero, it raises a
    CalledProcessError. The CalledProcessError object will have the return code
    in the returncode attribute, and output & stderr attributes if those streams
    were captured.

    If timeout is given, and the process takes too long, a TimeoutExpired
    exception will be raised.

    There is an optional argument "input", allowing you to
    pass a string to the subprocess's stdin.  If you use this argument
    you may not also use the Popen constructor's "stdin" argument, as
    it will be used internally.

    The other arguments are the same as for the Popen constructor.

    If universal_newlines=True is passed, the "input" argument must be a
    string and stdout/stderr in the returned object will be strings rather than
    bytes.
    """
    #pylint: disable=redefined-builtin
    if input is not None:
        if 'stdin' in kwargs:
            raise ValueError('stdin and input arguments may not both be used.')
        kwargs['stdin'] = subprocess.PIPE

    with subprocess.Popen(*popenargs, **kwargs) as process:
        try:
            stdout, stderr = process.communicate(input, timeout=timeout)
        except subprocess.TimeoutExpired:
            process.kill()
            stdout, stderr = process.communicate()
            raise subprocess.TimeoutExpired(process.args,
                                            timeout,
                                            output=stdout,
                                            stderr=stderr)
        except:
            process.kill()
            process.wait()
            raise
        retcode = process.poll()
        if check and retcode:
            raise subprocess.CalledProcessError(retcode,
                                                process.args,
                                                output=stdout,
                                                stderr=stderr)
    return CompletedProcess(process.args, retcode, stdout, stderr)
Пример #17
0
 def test_long_command_no_status_output(self, popen, sleep):
     proc = popen.return_value
     proc.returncode = 1  # FIXME: what's the real exit code for a SIGKILL?
     proc.poll.return_value = False  # command not completed
     proc.wait.side_effect = [
         subprocess.TimeoutExpired('gogo', 2), lambda *_: True]
     log_mock = MagicMock()
     runner('gogo', stop_event=make_event(is_set=True), log=log_mock)
     self.assertEqual(log_mock.call_count, 4)  # calls to add in spacing
Пример #18
0
 def communicate(self, msg, timeout=None):
     """Feeds msg to stdin, waits for peer to exit, and returns (stdout, stderr)."""
     #Stop read loop - it seems we can't 'communicate' while doing readline
     self.write_to_stdin("say_quit\n")
     try:
         self.expect_output("QUITTING", 1)
     except subprocess.TimeoutExpired:
         raise subprocess.TimeoutExpired("Peer unresponsive, cannot 'communicate'", 1)
     return self.process.communicate(bytes(msg, "utf-8"), timeout)
Пример #19
0
    def test_javac_timeout(self):
        JAVA_HOME = 'java_home'

        jdk = JDK(JAVA_HOME)

        subprocess.check_call = MagicMock(
            side_effect=subprocess.TimeoutExpired('', 0))

        self.assertFalse(jdk.run_javac('file.java', 10, None))
Пример #20
0
def run(*popenargs, timeout=None, check=False, ssh=None, **kwargs):
    """Run command with ZFS arguments and return a CompletedProcess instance. Works over ssh.
    Parameters:
    ----------
    *popenargs : {}
        Variable length argument list, same as Popen constructor
    **kwargs : {}
        Arbitrary keyword arguments, same as Popen constructor
    timeout : {float}, optional
        Timeout in seconds, if process takes too long TimeoutExpired will be raised (the default is
        None, meaning no timeout)
    check : {bool}, optional
        Check return code (the default is False, meaning return code will not be checked)
    ssh : {ssh.SSH}, optional
        Open ssh connection for remote execution (the default is None)
    Raises
    ------
    sp.TimeoutExpired
        Raised if process takes longer than given timeout
    sp.CalledProcessError
        Raised if check=True and return code != 0
    Returns
    -------
    subprocess.CompletedProcess
        Return instance of CompletedProcess with given return code, stdout and stderr
    """

    logger = logging.getLogger(__name__)

    if ssh:
        popenargs = (ssh.cmd + popenargs[0], *popenargs[1:])

    logger.log(8, "RUN: {:s}".format(' '.join(*popenargs)))
    with sp.Popen(*popenargs, **kwargs) as process:
        try:
            stdout, stderr = process.communicate(timeout=timeout)
        except sp.TimeoutExpired:
            process.kill()
            stdout, stderr = process.communicate()
            raise sp.TimeoutExpired(process.args,
                                    timeout,
                                    output=stdout,
                                    stderr=stderr)
        except:
            process.kill()
            process.wait()
            raise
        retcode = process.poll()

    if check and retcode:
        raise sp.CalledProcessError(retcode,
                                    popenargs[0],
                                    output=stdout,
                                    stderr=stderr)

    return CompletedProcess(popenargs[0], retcode, stdout, stderr)
Пример #21
0
    def test_wait_kills_after_timeout(self, *_):
        """Tests that if a TimeoutExpired error is thrown during wait, the
        process is killed."""
        process = Process('cmd')
        process._process = mock.Mock()
        process._process.wait.side_effect = subprocess.TimeoutExpired('', '')

        process.wait(0)

        self.assertEqual(process._kill_process.called, True)
Пример #22
0
def test_execute_timeout(popen_mock, process_mock):
    # pylint: disable=redefined-outer-name
    side_effects = (subprocess.TimeoutExpired('command', 30), ('Other STDOUT',
                                                               'Other STDERR'))
    process_mock.communicate = MagicMock(side_effect=side_effects)
    popen_mock.configure_mock(return_value=process_mock)

    with pytest.raises(executor.Timeout):
        executor.execute('command')
    process_mock.kill.assert_called_with()
Пример #23
0
 def test_timeout(self, mocked_popen, mocked_warning, _):
     """Tests run_container_command behaves as expected when the command times
 out."""
     popen_magic_mock = mock.MagicMock()
     mocked_popen.return_value = popen_magic_mock
     popen_magic_mock.communicate.side_effect = subprocess.TimeoutExpired(
         ['cmd'], '1')
     result = docker.run_container_command(self.ARGUMENTS)
     self.assertEqual(mocked_warning.call_count, 1)
     self.assertTrue(result.timed_out)
Пример #24
0
    def test_retry_when_failed_start(self):
        self.mock_subprocess.Popen.return_value.wait.side_effect = [
            lambda **kwargs:
            None,  # Indicates a problem, as wait() immediately returns
            subprocess.TimeoutExpired('cmd', 2)  # Success as wait() times out
        ]

        mitmproxy.start('127.0.0.1', 0, {})

        # Mitmproxy took two attempts to start
        self.assertEqual(2, self.mock_subprocess.Popen.call_count)
Пример #25
0
 def wait(self, timeout=None):
     if timeout and timeout < self.__wait:
         self.__wait -= timeout
         raise subprocess.TimeoutExpired(self.args, timeout)
     if self.__thread is not None:
         self.__thread.join()
         if self.returncode is None and self.__returncode is not None:
             self.returncode = self.__returncode
         if self.__thread.exception:
             raise self.__thread.exception
     return self.returncode
Пример #26
0
    def test_query_buck_relative_paths(self, find_buck_root) -> None:
        with patch.object(subprocess, "check_output") as buck_query:
            buck_query.return_value = json.dumps({
                "targetA": {
                    "buck.base_path": "src/python",
                    "srcs": {
                        "a.py": "a.py",
                        "b/c.py": "otherDirectory/c.py"
                    },
                },
                "targetB": {
                    "buck.base_path": "src/python",
                    "buck.base_module": "com.companyname",
                    "srcs": {
                        "package.py": "package.py"
                    },
                },
            }).encode("utf-8")

            paths = [
                "/PROJECT_BUCK_ROOT/src/python/a.py",  # tracked paths
                "/PROJECT_BUCK_ROOT/src/python/b/c.py",
                "/PROJECT_BUCK_ROOT/src/python/package.py",
                "/PROJECT_BUCK_ROOT/src/java/python/a.py",  # untracked paths
                "/PROJECT_BUCK_ROOT/com/companyname/package.py"
                "/OTHER_PROJECT/src/python/a.py",
            ]
            self.assertDictEqual(
                buck.query_buck_relative_paths(paths,
                                               targets=["targetA", "targetB"]),
                {
                    "/PROJECT_BUCK_ROOT/src/python/a.py":
                    "src/python/a.py",
                    "/PROJECT_BUCK_ROOT/src/python/b/c.py":
                    "src/python/otherDirectory/c.py",
                    "/PROJECT_BUCK_ROOT/src/python/package.py":
                    "com/companyname/package.py",
                },
            )
            self.assertDictEqual(
                buck.query_buck_relative_paths(paths, targets=["targetA"]),
                {
                    "/PROJECT_BUCK_ROOT/src/python/a.py":
                    "src/python/a.py",
                    "/PROJECT_BUCK_ROOT/src/python/b/c.py":
                    "src/python/otherDirectory/c.py",
                },
            )

        with patch.object(subprocess,
                          "check_output",
                          side_effect=subprocess.TimeoutExpired("cmd", 30)):
            self.assertRaises(buck.BuckException,
                              buck.query_buck_relative_paths, [], ["targetA"])
Пример #27
0
 def test_docker_pull_image_timeout(self):
     with patch(
             "subprocess.run",
             side_effect=subprocess.TimeoutExpired(cmd=[],
                                                   timeout=DOCKER_TIMEOUT),
     ):
         with pytest.raises(
                 click.exceptions.ClickException,
                 match='docker pull ggshield-non-existant" timed out',
         ):
             docker_pull_image("ggshield-non-existant", DOCKER_TIMEOUT)
Пример #28
0
def test_stop_subprocess_suppress_kill():
    """It should suppress kill signal errors."""
    mock_process = Mock(spec=subprocess.Popen, strict=True, name="Popen")
    mock_process.communicate.side_effect = [
        subprocess.TimeoutExpired([], timeout=3),
        subprocess.TimeoutExpired([], timeout=3),
        subprocess.CalledProcessError(9, ["test"], stderr="stderr of test")
    ]

    stdout, stderr = stop_process(mock_process, timeout=3)
    assert stdout is None
    assert stderr == "stderr of test"
    assert mock_process.method_calls == [
        call.send_signal(signal.SIGINT),
        call.communicate(timeout=3),
        call.send_signal(signal.SIGTERM),
        call.communicate(timeout=3),
        call.send_signal(signal.SIGKILL),
        call.communicate(timeout=None),
    ]
    def stop(self):
        if not self.running:
            return

        end_time = time() + self.timeout

        self._queue.put(self._end_of_stream)
        self._queue.join()
        self._process.stdin.flush()
        self._process.stdin.close()

        self.running = False

        try:
            if self._process.stdin:
                self._stdin_thread.join(timeout=self._remaining_time(end_time))
                if self._stdin_thread.is_alive():
                    raise subprocess.TimeoutExpired(self._process.args,
                                                    self.timeout)
            if self._process.stdout:
                self._stdout_thread.join(
                    timeout=self._remaining_time(end_time))
                if self._stdout_thread.is_alive():
                    raise subprocess.TimeoutExpired(self._process.args,
                                                    self.timeout)
            if self._process.stderr:
                self._stderr_thread.join(
                    timeout=self._remaining_time(end_time))
                if self._stderr_thread.is_alive():
                    raise subprocess.TimeoutExpired(self._process.args,
                                                    self.timeout)

            self.exit_code = self._process.wait(
                timeout=self._remaining_time(end_time))
        except Exception as e:
            self.error = e
            self._process.kill()
            self._process.wait()
        finally:
            self._process = None
            self._queue = None
Пример #30
0
def run_docker_command(command: Union[str, List[str]], cwd: Optional[str] = None,
                       user: Optional[Union[int, Tuple[int, int]]] = None,
                       directory_mapping: Optional[Dict[str, str]] = None,
                       timeout: Optional[float] = None, **kwargs) -> CommandResult:
    r"""Run a command inside a container based on the ``gcc-custom`` Docker image.

    :param command: The command to run. Should be either a `str` or a list of `str`. Note: they're treated the same way,
        because a shell is always spawn in the entry point.
    :param cwd: The working directory of the command to run. If None, uses the default (probably user home).
    :param user: The user ID to use inside the Docker container. Additionally, group ID can be specified by passing
        a tuple of two `int`\ s for this argument. If not specified, the current user and group IDs are used. As a
        special case, pass in ``0`` to run as root.
    :param directory_mapping: Mapping of host directories to container paths. Mapping is performed via "bind mount".
    :param timeout: Maximum running time for the command. If running time exceeds the specified limit,
        ``subprocess.TimeoutExpired`` is thrown.
    :param kwargs: Additional keyword arguments to pass to :meth:`ghcc.utils.run_command`.
    """
    # Validate `command` argument, and append call to `bash` if `shell` is True.
    if isinstance(command, list):
        command = ' '.join(command)
    command = f"'{command}'"

    # Construct the `docker run` command.
    docker_command = ["docker", "run", "--rm"]
    for host, container in (directory_mapping or {}).items():
        docker_command.extend(["-v", f"{os.path.abspath(host)}:{container}"])
    if cwd is not None:
        docker_command.extend(["-w", cwd])

    # Assign user and group IDs based on `user` argument.
    if user != 0:
        user_id: Union[str, int] = "`id -u $USER`"
        group_id: Union[str, int] = "`id -g $USER`"
        if user is not None:
            if isinstance(user, tuple):
                user_id, group_id = user
            else:
                user_id = user
        docker_command.extend(["-e", f"LOCAL_USER_ID={user_id}"])
        docker_command.extend(["-e", f"LOCAL_GROUP_ID={group_id}"])

    docker_command.append("gcc-custom")
    if timeout is not None:
        # Timeout is implemented by calling `timeout` inside Docker container.
        docker_command.extend(["timeout", f"{timeout}s"])
    docker_command.append(command)
    ret = run_command(' '.join(docker_command), shell=True, **kwargs)

    # Check whether exceeded timeout limit by inspecting return code.
    if ret.return_code == 124:
        assert timeout is not None
        raise error_wrapper(subprocess.TimeoutExpired(ret.command, timeout, output=ret.captured_output))
    return ret