def test_cli_timeout_greater_than_timeout_kw(minion_id, config_dir, config_file, cli_script_name):
    # Both --timeout and _timeout are passed.
    # Since --timeout is greater than _timeout, the value of _timeout is updated to the value of --timeout plus 5
    default_timeout = 10
    explicit_timeout = 20
    cli_timeout = 60
    config = {"conf_file": config_file, "id": "the-id"}
    args = ["--timeout", str(cli_timeout), "test.ping"]
    kwargs = {"minion_tgt": minion_id, "_timeout": explicit_timeout}
    expected = [
        sys.executable,
        cli_script_name,
        "--config-dir={}".format(config_dir.strpath),
        "--out=json",
        "--out-indent=0",
        "--log-level=quiet",
        minion_id,
        "--timeout",
        "60",
        "test.ping",
    ]

    popen_mock = mock.MagicMock()
    popen_mock.pid = os.getpid()
    popen_mock.poll = mock.MagicMock(side_effect=[None, None, None, None, True])
    terminate_mock = mock.MagicMock(return_value=ProcessResult(0, "", "", cmdline=()))
    popen_mock.terminate = terminate_mock

    proc = SaltCliFactory(
        cli_script_name=cli_script_name, config=config, default_timeout=default_timeout
    )
    with mock.patch.object(proc.impl, "init_terminal", popen_mock), mock.patch.object(
        proc, "terminate", terminate_mock
    ):
        proc.impl._terminal = popen_mock
        # We set __cli_timeout_supported__ to True just to test. This would be an attribute set
        # at the class level for Salt CLI's that support the timeout flag, like for example, salt-run
        proc.__cli_timeout_supported__ = True
        ret = proc.run(*args, **kwargs)
        assert proc.impl._terminal_timeout == cli_timeout + 5
        assert popen_mock.call_args[0][0] == expected  # pylint: disable=unsubscriptable-object
def test_default_cli_flags_with_timeout_and_timeout_kwargs(
    minion_id, config_dir, config_file, cli_script_name
):
    """
    This test assures that when _timeout is passed as a keyword argument, that the _terminal_timeout property
    does not get get updated to the value of --timeout
    """
    default_timeout = 10
    explicit_timeout = 60
    config = {"conf_file": config_file, "id": "the-id"}
    args = ["--timeout=6", "test.ping"]
    kwargs = {"minion_tgt": minion_id, "_timeout": explicit_timeout}
    expected = [
        sys.executable,
        cli_script_name,
        "--config-dir={}".format(config_dir.strpath),
        "--out=json",
        "--log-level=quiet",
        minion_id,
        "--timeout=6",
        "test.ping",
    ]

    popen_mock = mock.MagicMock()
    popen_mock.pid = os.getpid()
    popen_mock.poll = mock.MagicMock(side_effect=[None, None, None, None, True])
    terminate_mock = mock.MagicMock(return_value=ProcessResult(0, "", "", cmdline=()))
    popen_mock.terminate = terminate_mock

    proc = SaltCliFactory(
        cli_script_name=cli_script_name, config=config, default_timeout=default_timeout
    )
    with mock.patch.object(proc, "init_terminal", popen_mock), mock.patch.object(
        proc, "terminate", terminate_mock
    ):
        proc._terminal = popen_mock
        # We set __cli_timeout_supported__ to True just to test. This would be an attribute set
        # at the class level for Salt CLI's that support the timeout flag, like for example, salt-run
        proc.__cli_timeout_supported__ = True
        ret = proc.run(*args, **kwargs)
        assert proc._terminal_timeout_set_explicitly is True
        assert proc._terminal_timeout == explicit_timeout
        assert popen_mock.call_args[0][0] == expected  # pylint: disable=unsubscriptable-object

    # To confirm behavior, let's NOT pass --timeout in args
    default_timeout = 10
    explicit_timeout = 60
    config = {"conf_file": config_file, "id": "the-id"}
    args = ["test.ping"]
    kwargs = {"minion_tgt": minion_id, "_timeout": explicit_timeout}
    expected = [
        sys.executable,
        cli_script_name,
        "--config-dir={}".format(config_dir.strpath),
        "--timeout={}".format(explicit_timeout),
        "--out=json",
        "--log-level=quiet",
        minion_id,
        "test.ping",
    ]

    popen_mock = mock.MagicMock()
    popen_mock.pid = os.getpid()
    popen_mock.poll = mock.MagicMock(side_effect=[None, None, None, None, True])
    popen_mock.terminate = mock.MagicMock(return_value=ProcessResult(0, "", "", cmdline=()))
    terminate_mock = mock.MagicMock(return_value=ProcessResult(0, "", ""))

    proc = SaltCliFactory(
        cli_script_name=cli_script_name, config=config, default_timeout=default_timeout
    )
    with mock.patch.object(proc, "init_terminal", popen_mock), mock.patch.object(
        proc, "terminate", terminate_mock
    ):
        proc._terminal = popen_mock
        # We set __cli_timeout_supported__ to True just to test. This would be an attribute set
        # at the class level for Salt CLI's that support the timeout flag, like for example, salt-run
        proc.__cli_timeout_supported__ = True
        ret = proc.run(*args, **kwargs)
        assert proc._terminal_timeout_set_explicitly is True
        assert proc._terminal_timeout == explicit_timeout
        assert popen_mock.call_args[0][0] == expected  # pylint: disable=unsubscriptable-object

    # To confirm behavior, let's NOT pass --timeout in args nor _timeout in kwargs
    default_timeout = 10
    config = {"conf_file": config_file, "id": "the-id"}
    args = ["test.ping"]
    kwargs = {"minion_tgt": minion_id}
    expected = [
        sys.executable,
        cli_script_name,
        "--config-dir={}".format(config_dir.strpath),
        "--timeout={}".format(default_timeout - 5),
        "--out=json",
        "--log-level=quiet",
        minion_id,
        "test.ping",
    ]

    popen_mock = mock.MagicMock()
    popen_mock.pid = os.getpid()
    popen_mock.poll = mock.MagicMock(side_effect=[None, None, None, None, True])
    popen_mock.terminate = mock.MagicMock(return_value=ProcessResult(0, "", "", cmdline=()))
    terminate_mock = mock.MagicMock(return_value=ProcessResult(0, "", ""))

    proc = SaltCliFactory(
        cli_script_name=cli_script_name, config=config, default_timeout=default_timeout
    )
    with mock.patch.object(proc, "init_terminal", popen_mock), mock.patch.object(
        proc, "terminate", terminate_mock
    ):
        proc._terminal = popen_mock
        # We set __cli_timeout_supported__ to True just to test. This would be an attribute set
        # at the class level for Salt CLI's that support the timeout flag, like for example, salt-run
        proc.__cli_timeout_supported__ = True
        ret = proc.run(*args, **kwargs)
        assert proc._terminal_timeout_set_explicitly is False
        assert proc._terminal_timeout == default_timeout
        assert popen_mock.call_args[0][0] == expected  # pylint: disable=unsubscriptable-object