Esempio n. 1
0
def assert_complete(bash: pexpect.spawn, cmd: str,
                    **kwargs) -> CompletionResult:
    skipif = kwargs.get("skipif")
    if skipif:
        try:
            assert_bash_exec(bash, skipif, want_output=None)
        except AssertionError:
            pass
        else:
            pytest.skip(skipif)
    xfail = kwargs.get("xfail")
    if xfail:
        try:
            assert_bash_exec(bash, xfail, want_output=None)
        except AssertionError:
            pass
        else:
            pytest.xfail(xfail)

    with bash_env_saved(bash, sendintr=True) as bash_env:

        cwd = kwargs.get("cwd")
        if cwd:
            bash_env.chdir(str(cwd))

        for k, v in kwargs.get("env", {}).items():
            bash_env.write_env(k, v, quote=False)

        for k, v in kwargs.get("shopt", {}).items():
            bash_env.shopt(k, v)

        bash.send(cmd + "\t")
        # Sleep a bit if requested, to avoid `.*` matching too early
        time.sleep(kwargs.get("sleep_after_tab", 0))
        bash.expect_exact(kwargs.get("rendered_cmd", cmd))
        bash.send(MAGIC_MARK)
        got = bash.expect([
            # 0: multiple lines, result in .before
            r"\r\n" + re.escape(PS1 + cmd) + ".*" + re.escape(MAGIC_MARK),
            # 1: no completion
            r"^" + re.escape(MAGIC_MARK),
            # 2: on same line, result in .match
            r"^([^\r]+)%s$" % re.escape(MAGIC_MARK),
            pexpect.EOF,
            pexpect.TIMEOUT,
        ])
        if got == 0:
            output = bash.before
            if output.endswith(MAGIC_MARK):
                output = bash.before[:-len(MAGIC_MARK)]
            return CompletionResult(output)
        elif got == 2:
            output = bash.match.group(1)
            return CompletionResult(output)
        else:
            # TODO: warn about EOF/TIMEOUT?
            return CompletionResult()
Esempio n. 2
0
def assert_complete_at_point(
    bash: pexpect.spawn, cmd: str, trail: str
) -> CompletionResult:
    # TODO: merge to assert_complete
    fullcmd = "%s%s%s" % (
        cmd,
        trail,
        "\002" * len(trail),
    )  # \002 = ^B = cursor left
    bash.send(fullcmd + "\t")
    bash.send(MAGIC_MARK)
    bash.expect_exact(fullcmd.replace("\002", "\b"))

    got = bash.expect_exact(
        [
            # 0: multiple lines, result in .before
            PS1 + fullcmd.replace("\002", "\b"),
            # 1: no completion
            MAGIC_MARK,
            pexpect.EOF,
            pexpect.TIMEOUT,
        ]
    )
    if got == 0:
        output = bash.before
        result = CompletionResult(output)

        # At this point, something weird happens. For most test setups, as
        # expected (pun intended!), MAGIC_MARK follows as is. But for some
        # others (e.g. CentOS 6, Ubuntu 14 test containers), we get MAGIC_MARK
        # one character a time, followed each time by trail and the corresponding
        # number of \b's. Don't know why, but accept it until/if someone finds out.
        # Or just be fine with it indefinitely, the visible and practical end
        # result on a terminal is the same anyway.
        repeat = "(%s%s)?" % (re.escape(trail), "\b" * len(trail))
        fullexpected = "".join(
            "%s%s" % (re.escape(x), repeat) for x in MAGIC_MARK
        )
        bash.expect(fullexpected)
    else:
        # TODO: warn about EOF/TIMEOUT?
        result = CompletionResult()

    return result
Esempio n. 3
0
    def _wait_connect(self, p: pexpect.spawn,
                      password_manager: PasswordManager,
                      azure_ad_config: AuthConfig):
        i = p.expect([
            pexpect.EOF,
            re.compile(r"continue connecting \(yes/no(/\[fingerprint])?\)\? "),
            re.compile(r"authenticate\.")
        ])

        if i == 0:
            if self.is_connected():
                return
            else:
                raise GProxyError(f"Error when initializing SSH: {p.before}")
        elif i == 1:
            host_key_fingerprint = self._extract_host_key_fingerprint(p.before)
            if host_key_fingerprint != GPROXY_FINGERPRINT:
                raise GProxyError(
                    f"!!!SEVERE!!! Host fingerprint is not matching expected!!! Report to CCOE!:"
                    f"Actual:{host_key_fingerprint} != Expected:{GPROXY_FINGERPRINT}"
                )
            LOG.info("Confirming host! Fingerprint is matching expected.")
            p.send("yes\r")
            self._wait_connect(p, password_manager, azure_ad_config)
            return

        p.send("\r")
        code = self._extract_code(p.before)
        url = self._extract_url(p.before)
        LOG.info(f"GProxy OTC Code: {code}, Url: {url}")

        if url != GProxyAdLogin.URL:
            raise GProxyError(
                f"Url does not match expected login-url. !={GProxyAdLogin.URL}"
            )

        GProxyAdLogin(code=code,
                      password_manager=password_manager,
                      config=azure_ad_config).login_sync()

        p.expect(pexpect.EOF, timeout=30)
Esempio n. 4
0
def assert_complete(bash: pexpect.spawn, cmd: str,
                    **kwargs) -> CompletionResult:
    skipif = kwargs.get("skipif")
    if skipif:
        try:
            assert_bash_exec(bash, skipif)
        except AssertionError:
            pass
        else:
            pytest.skip(skipif)
    xfail = kwargs.get("xfail")
    if xfail:
        try:
            assert_bash_exec(bash, xfail)
        except AssertionError:
            pass
        else:
            pytest.xfail(xfail)
    cwd = kwargs.get("cwd")
    if cwd:
        assert_bash_exec(bash, "cd '%s'" % cwd)
    env_prefix = "_BASHCOMP_TEST_"
    env = kwargs.get("env", {})
    if env:
        # Back up environment and apply new one
        assert_bash_exec(
            bash,
            " ".join('%s%s="$%s"' % (env_prefix, k, k) for k in env.keys()),
        )
        assert_bash_exec(
            bash,
            "export %s" % " ".join("%s=%s" % (k, v) for k, v in env.items()),
        )
    bash.send(cmd + "\t")
    bash.expect_exact(cmd)
    bash.send(MAGIC_MARK)
    got = bash.expect([
        # 0: multiple lines, result in .before
        r"\r\n" + re.escape(PS1 + cmd) + ".*" + MAGIC_MARK,
        # 1: no completion
        r"^" + MAGIC_MARK,
        # 2: on same line, result in .match
        r"^([^\r]+)%s$" % MAGIC_MARK,
        pexpect.EOF,
        pexpect.TIMEOUT,
    ])
    if got == 0:
        output = bash.before
        if output.endswith(MAGIC_MARK):
            output = bash.before[:-len(MAGIC_MARK)]
        result = CompletionResult(output)
    elif got == 2:
        output = bash.match.group(1)
        result = CompletionResult(output, [shlex.split(cmd + output)[-1]])
    else:
        # TODO: warn about EOF/TIMEOUT?
        result = CompletionResult("", [])
    bash.sendintr()
    bash.expect_exact(PS1)
    if env:
        # Restore environment, and clean up backup
        # TODO: Test with declare -p if a var was set, backup only if yes, and
        #       similarly restore only backed up vars. Should remove some need
        #       for ignore_env.
        assert_bash_exec(
            bash,
            "export %s" % " ".join('%s="$%s%s"' % (k, env_prefix, k)
                                   for k in env.keys()),
        )
        assert_bash_exec(
            bash,
            "unset -v %s" % " ".join("%s%s" % (env_prefix, k)
                                     for k in env.keys()),
        )
    if cwd:
        assert_bash_exec(bash, "cd - >/dev/null")
    return result
Esempio n. 5
0
def slow_sendline(exp: spawn, string: str):
    """Send one character at a time and wait for echo. The expect session deadlocks if we don't do this."""
    for i in range(len(string)):
        exp.send(string[i])
        exp.expect_exact(string[i])
    exp.send('\n')
Esempio n. 6
0
def dump_input_buffer_on_ctrl_g(zsh: pexpect.spawn) -> None:
    zsh.send(
        b"""strager_echo_buffer() { printf '[%s[%s]%s]\\n' '[' "${BUFFER}" ']' }\n"""
    )
    zsh.send(b"zle -N strager_echo_buffer\n")
    zsh.send(b"bindkey '^g' strager_echo_buffer\n")
Esempio n. 7
0
def send_and_expect_byte_by_byte(zsh: pexpect.spawn, input: bytes) -> bytes:
    for byte in input:
        current_input = bytes([byte])
        zsh.send(current_input)
        zsh.expect(string_ignoring_escape_sequences_re(current_input))
Esempio n. 8
0
 def spawnAction(self, sp: spawn):
     print("sending {}".format(self))
     yield sp.send(self)
Esempio n. 9
0
def assert_complete(
        bash: pexpect.spawn, cmd: str, **kwargs) -> CompletionResult:
    skipif = kwargs.get("skipif")
    if skipif:
        try:
            assert_bash_exec(bash, skipif)
        except AssertionError:
            pass
        else:
            pytest.skip(skipif)
            return CompletionResult("", [])
    cwd = kwargs.get("cwd")
    if cwd:
        assert_bash_exec(bash, "cd '%s'" % cwd)
    env_prefix = "_BASHCOMP_TEST_"
    env = kwargs.get("env", {})
    if env:
        # Back up environment and apply new one
        assert_bash_exec(bash, " ".join(
            '%s%s="$%s"' % (env_prefix, k, k) for k in env.keys()
        ))
        assert_bash_exec(bash, "export %s" % " ".join(
            "%s=%s" % (k, v) for k, v in env.items()
        ))
    bash.send(cmd + "\t")
    bash.expect_exact(cmd)
    bash.send(MAGIC_MARK)
    got = bash.expect([
        r"\r\n" + re.escape(PS1 + cmd),  # 0: multiple lines, result in .before
        r"^" + MAGIC_MARK,               # 1: no completion
        r"^[^\r]+",                      # 2: on same line, result in .after
        pexpect.EOF,
        pexpect.TIMEOUT,
    ])
    if got == 0:
        line = bash.before
        if line.endswith(MAGIC_MARK):
            line = bash.before[:-len(MAGIC_MARK)]
        result = CompletionResult(
            line,
            sorted(x for x in re.split(r" {2,}|\r\n", line) if x),
        )
    elif got == 2:
        line = bash.after
        if line.endswith(MAGIC_MARK):
            line = bash.after[:-len(MAGIC_MARK)]
        result = CompletionResult(
            line,
            [shlex.split(cmd + line)[-1]],
        )
    else:
        # TODO: warn about EOF/TIMEOUT?
        result = CompletionResult("", [])
    bash.sendintr()
    bash.expect_exact(PS1)
    if env:
        # Restore environment, and clean up backup
        # TODO: Test with declare -p if a var was set, backup only if yes, and
        #       similarly restore only backed up vars. Should remove some need
        #       for ignore_env.
        assert_bash_exec(bash, "export %s" % " ".join(
            '%s="$%s%s"' % (k, env_prefix, k) for k in env.keys()
        ))
        assert_bash_exec(bash, "unset -v %s" % " ".join(
            "%s%s" % (env_prefix, k) for k in env.keys()
        ))
    if cwd:
        assert_bash_exec(bash, "cd - >/dev/null")
    return result