from unittest import TestCase

from mock import mock_open, patch
from paramiko import ProxyCommand

from pyinfra.api.connectors.sshuserclient import SSHClient

SSH_CONFIG_DATA = '''
# Comment
Host 127.0.0.1
    IdentityFile /id_rsa
    IdentityFile /id_rsa2
    User testuser
    Port 33
    ProxyCommand ssh thing

Include other_file
'''

SSH_CONFIG_OTHER_FILE = '''
Host 192.168.1.1
    User "otheruser"
    ProxyCommand None
    ForwardAgent yes
'''

BAD_SSH_CONFIG_DATA = '''
&
'''

LOOPING_SSH_CONFIG_DATA = '''
Include other_file
'''


@patch(
    'pyinfra.api.connectors.sshuserclient.client.path.exists',
    lambda path: True,
)
class TestSSHUserConfig(TestCase):
    @patch(
        'pyinfra.api.connectors.sshuserclient.client.open',
        mock_open(read_data=SSH_CONFIG_DATA),
        create=True,
    )
    @patch(
        'pyinfra.api.connectors.sshuserclient.config.open',
        mock_open(read_data=SSH_CONFIG_OTHER_FILE),
        create=True,
    )
    @patch(
        'pyinfra.api.connectors.sshuserclient.config.glob.iglob',
        lambda path: ['other_file'],
    )
    @patch(
        'pyinfra.api.connectors.sshuserclient.config.os.path.isfile',
        lambda path: True,
    )
    @patch(
        'pyinfra.api.connectors.sshuserclient.config.os.path.isabs',
        lambda path: True,
    )
    def test_load_ssh_config(self):
        client = SSHClient()

        _, config, forward_agent = client.parse_config('127.0.0.1')

        assert config.get('key_filename') == ['/id_rsa', '/id_rsa2']
        assert config.get('username') == 'testuser'
        assert config.get('port') == 33
        assert isinstance(config.get('sock'), ProxyCommand)
        assert forward_agent is False

        _, other_config, forward_agent = client.parse_config('192.168.1.1')

        assert other_config.get('username') == 'otheruser'
        assert forward_agent is True

    @patch(
        'pyinfra.api.connectors.sshuserclient.client.open',
        mock_open(read_data=BAD_SSH_CONFIG_DATA),
        create=True,
    )
    def test_invalid_ssh_config(self):
        client = SSHClient()

        with self.assertRaises(Exception) as context:
            client.parse_config('127.0.0.1')

        assert context.exception.args[0] == 'Unparsable line &'

    @patch(
        'pyinfra.api.connectors.sshuserclient.client.open',
        mock_open(read_data=LOOPING_SSH_CONFIG_DATA),
        create=True,
    )
    @patch(
        'pyinfra.api.connectors.sshuserclient.config.open',
        mock_open(read_data=LOOPING_SSH_CONFIG_DATA),
        create=True,
    )
    @patch(
        'pyinfra.api.connectors.sshuserclient.config.glob.iglob',
        lambda path: ['other_file'],
    )
    @patch(
        'pyinfra.api.connectors.sshuserclient.config.os.path.isfile',
        lambda path: True,
    )
    def test_include_loop_ssh_config(self):
        client = SSHClient()

        with self.assertRaises(Exception) as context:
            client.parse_config('127.0.0.1')

        assert context.exception.args[0] == 'Include loop detected in ssh config file: other_file'

@@ -2798,32 +2798,151 @@
 th: True,%0A    )%0A
+    @patch(%0A        'pyinfra.api.connectors.sshuserclient.config.os.path.expanduser',%0A        lambda path: path,%0A    )%0A
     def test_inc

Fix SSH config include test.