class NetworkConnectTaskRunnerTest(TestCase):
    """Tests against the ConnectTaskRunner class and functions."""
    def setUp(self):
        """Create test case setup."""
        self.cred = Credential(name='cred1',
                               username='******',
                               password='******',
                               ssh_keyfile='keyfile',
                               become_method='sudo',
                               become_user='******',
                               become_password='******')
        self.cred.save()

        # Source with excluded hosts
        self.source = Source(name='source1',
                             hosts='["1.2.3.4", "1.2.3.5"]',
                             exclude_hosts='["1.2.3.5", "1.2.3.6"]',
                             source_type='network',
                             port=22)
        self.source.save()
        self.source.credentials.add(self.cred)
        self.source.save()

        self.scan_job, self.scan_task = create_scan_job(
            self.source, ScanTask.SCAN_TYPE_CONNECT)

        self.scan_task.update_stats('TEST NETWORK CONNECT.', sys_failed=0)

        # Source without excluded hosts
        self.source2 = Source(name='source2',
                              hosts='["1.2.3.4"]',
                              source_type='network',
                              port=22)
        self.source2.save()
        self.source2.credentials.add(self.cred)
        self.source2.save()

        self.scan_job2, self.scan_task2 = create_scan_job(
            self.source, 'source2', ScanTask.SCAN_TYPE_CONNECT)

        self.scan_task2.update_stats('TEST NETWORK CONNECT.', sys_failed=0)

    def test_construct_vars(self):
        """Test constructing ansible vars dictionary."""
        hc_serializer = CredentialSerializer(self.cred)
        cred = hc_serializer.data
        vars_dict = _construct_vars(22, cred)
        expected = {
            'ansible_become_pass': '******',
            'ansible_port': 22,
            'ansible_ssh_pass': '******',
            'ansible_ssh_private_key_file': 'keyfile',
            'ansible_user': '******',
            'ansible_become_method': 'sudo',
            'ansible_become_user': '******'
        }
        self.assertEqual(vars_dict, expected)

    def test_get_exclude_host(self):
        """Test get_exclude_hosts() method."""
        assert self.source.get_exclude_hosts() != []
        assert self.source2.get_exclude_hosts() == []

    # Tests for source1 (has hosts and excluded host)
    def test_result_store(self):
        """Test ConnectResultStore."""
        result_store = ConnectResultStore(self.scan_task)

        self.assertEqual(result_store.remaining_hosts(), ['1.2.3.4'])
        self.assertEqual(result_store.scan_task.systems_count, 1)
        self.assertEqual(result_store.scan_task.systems_scanned, 0)
        self.assertEqual(result_store.scan_task.systems_failed, 0)

        result_store.record_result('1.2.3.4', self.source, self.cred,
                                   SystemConnectionResult.SUCCESS)

        self.assertEqual(result_store.remaining_hosts(), [])
        self.assertEqual(result_store.scan_task.systems_count, 1)
        self.assertEqual(result_store.scan_task.systems_scanned, 1)
        self.assertEqual(result_store.scan_task.systems_failed, 0)

    def test_connect_inventory(self):
        """Test construct ansible inventory dictionary."""
        serializer = SourceSerializer(self.source)
        source = serializer.data
        hosts = source['hosts']
        exclude_hosts = source['exclude_hosts']
        connection_port = source['port']
        hc_serializer = CredentialSerializer(self.cred)
        cred = hc_serializer.data
        inventory_dict = construct_connect_inventory(hosts, cred,
                                                     connection_port,
                                                     exclude_hosts)
        expected = {
            'all': {
                'hosts': {
                    '1.2.3.4': None
                },
                'vars': {
                    'ansible_become_pass': '******',
                    'ansible_port': 22,
                    'ansible_ssh_pass': '******',
                    'ansible_ssh_private_key_file': 'keyfile',
                    'ansible_user': '******',
                    'ansible_become_method': 'sudo',
                    'ansible_become_user': '******'
                }
            }
        }
        self.assertEqual(inventory_dict, expected)

    @patch('scanner.network.utils.TaskQueueManager.run',
           side_effect=mock_run_failed)
    @patch('scanner.network.connect._handle_ssh_passphrase',
           side_effect=mock_handle_ssh)
    def test_connect_failure(self, mock_run, mock_ssh_pass):
        """Test connect flow with mocked manager and failure."""
        serializer = SourceSerializer(self.source)
        source = serializer.data
        hosts = source['hosts']
        exclude_hosts = source['exclude_hosts']
        connection_port = source['port']
        hc_serializer = CredentialSerializer(self.cred)
        cred = hc_serializer.data
        with self.assertRaises(AnsibleError):
            connect(hosts, Mock(), cred, connection_port, exclude_hosts)
            mock_run.assert_called()
            mock_ssh_pass.assert_called()

    @patch('scanner.network.utils.TaskQueueManager.run',
           side_effect=mock_run_success)
    def test_connect(self, mock_run):
        """Test connect flow with mocked manager."""
        serializer = SourceSerializer(self.source)
        source = serializer.data
        hosts = source['hosts']
        exclude_hosts = source['exclude_hosts']
        connection_port = source['port']
        hc_serializer = CredentialSerializer(self.cred)
        cred = hc_serializer.data
        connect(hosts, Mock(), cred, connection_port, exclude_hosts)
        mock_run.assert_called_with(ANY)

    @patch('scanner.network.connect.connect')
    def test_connect_runner(self, mock_connect):
        """Test running a connect scan with mocked connection."""
        scanner = ConnectTaskRunner(self.scan_job, self.scan_task)
        result_store = MockResultStore(['1.2.3.4'])
        conn_dict = scanner.run_with_result_store(result_store)
        mock_connect.assert_called_with(ANY, ANY, ANY, 22, False, forks=50)
        self.assertEqual(conn_dict[1], ScanTask.COMPLETED)

    # Similar tests as above modified for source2 (Does not have exclude hosts)
    def test_result_store_src2(self):
        """Test ConnectResultStore."""
        result_store = ConnectResultStore(self.scan_task2)

        self.assertEqual(result_store.remaining_hosts(), ['1.2.3.4'])
        self.assertEqual(result_store.scan_task.systems_count, 1)
        self.assertEqual(result_store.scan_task.systems_scanned, 0)
        self.assertEqual(result_store.scan_task.systems_failed, 0)

        result_store.record_result('1.2.3.4', self.source2, self.cred,
                                   SystemConnectionResult.SUCCESS)

        self.assertEqual(result_store.remaining_hosts(), [])
        self.assertEqual(result_store.scan_task.systems_count, 1)
        self.assertEqual(result_store.scan_task.systems_scanned, 1)
        self.assertEqual(result_store.scan_task.systems_failed, 0)

    def test_connect_inventory_src2(self):
        """Test construct ansible inventory dictionary."""
        serializer = SourceSerializer(self.source2)
        source = serializer.data
        hosts = source['hosts']
        connection_port = source['port']
        hc_serializer = CredentialSerializer(self.cred)
        cred = hc_serializer.data
        inventory_dict = construct_connect_inventory(hosts, cred,
                                                     connection_port)
        expected = {
            'all': {
                'hosts': {
                    '1.2.3.4': None
                },
                'vars': {
                    'ansible_become_pass': '******',
                    'ansible_port': 22,
                    'ansible_ssh_pass': '******',
                    'ansible_ssh_private_key_file': 'keyfile',
                    'ansible_user': '******',
                    'ansible_become_method': 'sudo',
                    'ansible_become_user': '******'
                }
            }
        }
        self.assertEqual(inventory_dict, expected)

    @patch('scanner.network.utils.TaskQueueManager.run',
           side_effect=mock_run_failed)
    @patch('scanner.network.connect._handle_ssh_passphrase',
           side_effect=mock_handle_ssh)
    def test_connect_failure_src2(self, mock_run, mock_ssh_pass):
        """Test connect flow with mocked manager and failure."""
        serializer = SourceSerializer(self.source2)
        source = serializer.data
        hosts = source['hosts']
        connection_port = source['port']
        hc_serializer = CredentialSerializer(self.cred)
        cred = hc_serializer.data
        with self.assertRaises(AnsibleError):
            connect(hosts, Mock(), cred, connection_port)
            mock_run.assert_called()
            mock_ssh_pass.assert_called()

    @patch('scanner.network.utils.TaskQueueManager.run',
           side_effect=mock_run_success)
    def test_connect_src2(self, mock_run):
        """Test connect flow with mocked manager."""
        serializer = SourceSerializer(self.source2)
        source = serializer.data
        hosts = source['hosts']
        connection_port = source['port']
        hc_serializer = CredentialSerializer(self.cred)
        cred = hc_serializer.data
        connect(hosts, Mock(), cred, connection_port)
        mock_run.assert_called_with(ANY)

    @patch('scanner.network.connect.connect')
    def test_connect_runner_src2(self, mock_connect):
        """Test running a connect scan with mocked connection."""
        scanner = ConnectTaskRunner(self.scan_job2, self.scan_task2)
        result_store = MockResultStore(['1.2.3.4'])
        conn_dict = scanner.run_with_result_store(result_store)
        mock_connect.assert_called_with(ANY, ANY, ANY, 22, False, forks=50)
        self.assertEqual(conn_dict[1], ScanTask.COMPLETED)
class NetworkConnectTaskRunnerTest(TestCase):
    """Tests against the ConnectTaskRunner class and functions."""
    def setUp(self):
        """Create test case setup."""
        self.cred = Credential(name='cred1',
                               username='******',
                               password='******',
                               ssh_keyfile='keyfile',
                               become_method='sudo',
                               become_user='******',
                               become_password='******')
        self.cred.save()

        # Source with excluded hosts
        self.source = Source(name='source1',
                             hosts='["1.2.3.4", "1.2.3.5"]',
                             exclude_hosts='["1.2.3.5", "1.2.3.6"]',
                             source_type='network',
                             port=22)
        self.source.save()
        self.source.credentials.add(self.cred)
        self.source.save()

        self.scan_job, self.scan_task = create_scan_job(
            self.source, ScanTask.SCAN_TYPE_CONNECT)

        self.scan_task.update_stats('TEST NETWORK CONNECT.', sys_failed=0)

        # Source without excluded hosts
        self.source2 = Source(name='source2',
                              hosts='["1.2.3.4"]',
                              source_type='network',
                              port=22)
        self.source2.save()
        self.source2.credentials.add(self.cred)
        self.source2.save()

        self.scan_job2, self.scan_task2 = create_scan_job(
            self.source, ScanTask.SCAN_TYPE_CONNECT, 'source2')

        self.scan_task2.update_stats('TEST NETWORK CONNECT.', sys_failed=0)

    def test_construct_vars(self):
        """Test constructing ansible vars dictionary."""
        hc_serializer = CredentialSerializer(self.cred)
        cred = hc_serializer.data
        vars_dict = _construct_vars(22, cred)
        expected = {
            'ansible_become_pass': '******',
            'ansible_port': 22,
            'ansible_ssh_pass': '******',
            'ansible_ssh_private_key_file': 'keyfile',
            'ansible_user': '******',
            'ansible_become_method': 'sudo',
            'ansible_become_user': '******'
        }
        self.assertEqual(vars_dict, expected)

    def test_get_exclude_host(self):
        """Test get_exclude_hosts() method."""
        assert self.source.get_exclude_hosts() != []
        assert self.source2.get_exclude_hosts() == []

    # Tests for source1 (has hosts and excluded host)
    def test_result_store(self):
        """Test ConnectResultStore."""
        result_store = ConnectResultStore(self.scan_task)

        self.assertEqual(result_store.remaining_hosts(), ['1.2.3.4'])
        self.assertEqual(result_store.scan_task.systems_count, 1)
        self.assertEqual(result_store.scan_task.systems_scanned, 0)
        self.assertEqual(result_store.scan_task.systems_failed, 0)

        result_store.record_result('1.2.3.4', self.source, self.cred,
                                   SystemConnectionResult.SUCCESS)

        self.assertEqual(result_store.remaining_hosts(), [])
        self.assertEqual(result_store.scan_task.systems_count, 1)
        self.assertEqual(result_store.scan_task.systems_scanned, 1)
        self.assertEqual(result_store.scan_task.systems_failed, 0)

    def test_connect_inventory(self):
        """Test construct ansible inventory dictionary."""
        serializer = SourceSerializer(self.source)
        source = serializer.data
        hosts = source['hosts']
        exclude_hosts = source['exclude_hosts']
        connection_port = source['port']
        hc_serializer = CredentialSerializer(self.cred)
        cred = hc_serializer.data
        path = '/path/to/executable.py'
        ssh_timeout = '0.1s'
        ssh_args = ['--executable=' + path, '--timeout=' + ssh_timeout, 'ssh']
        _, inventory_dict = _construct_connect_inventory(hosts,
                                                         cred,
                                                         connection_port,
                                                         1,
                                                         exclude_hosts,
                                                         ssh_executable=path,
                                                         ssh_args=ssh_args)
        # pylint: disable=line-too-long
        expected = {
            'all': {
                'children': {
                    'group_0': {
                        'hosts': {
                            '1.2.3.4': {
                                'ansible_host':
                                '1.2.3.4',
                                'ansible_ssh_executable':
                                '/path/to/executable.py',
                                'ansible_ssh_common_args':
                                '--executable=/path/to/executable.py --timeout=0.1s ssh'
                            }
                        }
                    }
                },  # noqa
                'vars': {
                    'ansible_port': 22,
                    'ansible_user': '******',
                    'ansible_ssh_pass': '******',
                    'ansible_ssh_private_key_file': 'keyfile',
                    'ansible_become_pass': '******',
                    'ansible_become_method': 'sudo',
                    'ansible_become_user': '******'
                }
            }
        }
        self.assertEqual(inventory_dict, expected)

    @patch('scanner.network.utils.TaskQueueManager.run',
           side_effect=mock_run_failed)
    @patch('scanner.network.connect._handle_ssh_passphrase',
           side_effect=mock_handle_ssh)
    def test_connect_failure(self, mock_run, mock_ssh_pass):
        """Test connect flow with mocked manager and failure."""
        serializer = SourceSerializer(self.source)
        source = serializer.data
        hosts = source['hosts']
        exclude_hosts = source['exclude_hosts']
        connection_port = source['port']
        with self.assertRaises(AnsibleError):
            _connect(Value('i', ScanJob.JOB_RUN), self.scan_task, hosts,
                     Mock(), self.cred, connection_port, exclude_hosts)
            mock_run.assert_called()
            mock_ssh_pass.assert_called()

    @patch('scanner.network.utils.TaskQueueManager.run',
           side_effect=mock_run_success)
    def test_connect(self, mock_run):
        """Test connect flow with mocked manager."""
        serializer = SourceSerializer(self.source)
        source = serializer.data
        hosts = source['hosts']
        exclude_hosts = source['exclude_hosts']
        connection_port = source['port']
        _connect(Value('i', ScanJob.JOB_RUN), self.scan_task, hosts, Mock(),
                 self.cred, connection_port, exclude_hosts)
        mock_run.assert_called_with(ANY)

    @patch('scanner.network.utils.TaskQueueManager.run',
           side_effect=mock_run_success)
    def test_connect_ssh_crash(self, mock_run):
        """Simulate an ssh crash."""
        serializer = SourceSerializer(self.source)
        source = serializer.data
        hosts = source['hosts']
        exclude_hosts = source['exclude_hosts']
        connection_port = source['port']
        path = os.path.abspath(
            os.path.join(os.path.dirname(__file__),
                         '../../../test_util/crash.py'))
        _connect(Value('i', ScanJob.JOB_RUN),
                 self.scan_task,
                 hosts,
                 Mock(),
                 self.cred,
                 connection_port,
                 exclude_hosts,
                 base_ssh_executable=path)
        mock_run.assert_called_with(ANY)

    @patch('scanner.network.utils.TaskQueueManager.run',
           side_effect=mock_run_success)
    def test_connect_ssh_hang(self, mock_run):
        """Simulate an ssh hang."""
        serializer = SourceSerializer(self.source)
        source = serializer.data
        hosts = source['hosts']
        exclude_hosts = source['exclude_hosts']
        connection_port = source['port']
        path = os.path.abspath(
            os.path.join(os.path.dirname(__file__),
                         '../../../test_util/hang.py'))
        _connect(Value('i', ScanJob.JOB_RUN),
                 self.scan_task,
                 hosts,
                 Mock(),
                 self.cred,
                 connection_port,
                 exclude_hosts,
                 base_ssh_executable=path,
                 ssh_timeout='0.1s')
        mock_run.assert_called_with(ANY)

    @patch('scanner.network.connect._connect')
    def test_connect_runner(self, mock_connect):
        """Test running a connect scan with mocked connection."""
        scanner = ConnectTaskRunner(self.scan_job, self.scan_task)
        result_store = MockResultStore(['1.2.3.4'])
        conn_dict = scanner.run_with_result_store(Value('i', ScanJob.JOB_RUN),
                                                  result_store)
        mock_connect.assert_called_with(ANY,
                                        self.scan_task,
                                        ANY,
                                        ANY,
                                        ANY,
                                        22,
                                        False,
                                        forks=50)
        self.assertEqual(conn_dict[1], ScanTask.COMPLETED)

    # Similar tests as above modified for source2 (Does not have exclude hosts)
    def test_result_store_src2(self):
        """Test ConnectResultStore."""
        result_store = ConnectResultStore(self.scan_task2)

        self.assertEqual(result_store.remaining_hosts(), ['1.2.3.4'])
        self.assertEqual(result_store.scan_task.systems_count, 1)
        self.assertEqual(result_store.scan_task.systems_scanned, 0)
        self.assertEqual(result_store.scan_task.systems_failed, 0)

        result_store.record_result('1.2.3.4', self.source2, self.cred,
                                   SystemConnectionResult.SUCCESS)

        self.assertEqual(result_store.remaining_hosts(), [])
        self.assertEqual(result_store.scan_task.systems_count, 1)
        self.assertEqual(result_store.scan_task.systems_scanned, 1)
        self.assertEqual(result_store.scan_task.systems_failed, 0)

    def test_connect_inventory_src2(self):
        """Test construct ansible inventory dictionary."""
        serializer = SourceSerializer(self.source2)
        source = serializer.data
        hosts = source['hosts']
        connection_port = source['port']
        hc_serializer = CredentialSerializer(self.cred)
        cred = hc_serializer.data
        _, inventory_dict = _construct_connect_inventory(
            hosts, cred, connection_port, 1)
        expected = {
            'all': {
                'children': {
                    'group_0': {
                        'hosts': {
                            '1.2.3.4': {
                                'ansible_host': '1.2.3.4'
                            }
                        }
                    }
                },
                'vars': {
                    'ansible_port': 22,
                    'ansible_user': '******',
                    'ansible_ssh_pass': '******',
                    'ansible_ssh_private_key_file': 'keyfile',
                    'ansible_become_pass': '******',
                    'ansible_become_method': 'sudo',
                    'ansible_become_user': '******'
                }
            }
        }
        self.assertEqual(inventory_dict, expected)

    @patch('scanner.network.utils.TaskQueueManager.run',
           side_effect=mock_run_failed)
    @patch('scanner.network.connect._handle_ssh_passphrase',
           side_effect=mock_handle_ssh)
    def test_connect_failure_src2(self, mock_run, mock_ssh_pass):
        """Test connect flow with mocked manager and failure."""
        serializer = SourceSerializer(self.source2)
        source = serializer.data
        hosts = source['hosts']
        connection_port = source['port']
        with self.assertRaises(AnsibleError):
            _connect(Value('i', ScanJob.JOB_RUN), self.scan_task, hosts,
                     Mock(), self.cred, connection_port)
            mock_run.assert_called()
            mock_ssh_pass.assert_called()

    @patch('scanner.network.utils.TaskQueueManager.run',
           side_effect=mock_run_success)
    def test_connect_src2(self, mock_run):
        """Test connect flow with mocked manager."""
        serializer = SourceSerializer(self.source2)
        source = serializer.data
        hosts = source['hosts']
        connection_port = source['port']
        _connect(Value('i', ScanJob.JOB_RUN), self.scan_task, hosts, Mock(),
                 self.cred, connection_port)
        mock_run.assert_called_with(ANY)

    @patch('scanner.network.connect._connect')
    def test_connect_runner_src2(self, mock_connect):
        """Test running a connect scan with mocked connection."""
        scanner = ConnectTaskRunner(self.scan_job2, self.scan_task2)
        result_store = MockResultStore(['1.2.3.4'])
        conn_dict = scanner.run_with_result_store(Value('i', ScanJob.JOB_RUN),
                                                  result_store)
        mock_connect.assert_called_with(ANY,
                                        self.scan_task2,
                                        ANY,
                                        ANY,
                                        ANY,
                                        22,
                                        False,
                                        forks=50)
        self.assertEqual(conn_dict[1], ScanTask.COMPLETED)
class NetworkConnectTaskRunnerTest(TestCase):
    """Tests against the ConnectTaskRunner class and functions."""

    def setUp(self):
        """Create test case setup."""
        self.cred = Credential(
            name='cred1',
            username='******',
            password='******',
            ssh_keyfile='keyfile',
            become_method='sudo',
            become_user='******',
            become_password='******')
        self.cred.save()

        # Source with excluded hosts
        self.source = Source(
            name='source1',
            hosts='["1.2.3.4", "1.2.3.5"]',
            exclude_hosts='["1.2.3.5", "1.2.3.6"]',
            source_type='network',
            port=22)
        self.source.save()
        self.source.credentials.add(self.cred)
        self.source.save()

        self.scan_job, self.scan_task = create_scan_job(
            self.source, ScanTask.SCAN_TYPE_CONNECT)

        self.scan_task.update_stats('TEST NETWORK CONNECT.', sys_failed=0)

        # Source without excluded hosts
        self.source2 = Source(
            name='source2',
            hosts='["1.2.3.4"]',
            source_type='network',
            port=22)
        self.source2.save()
        self.source2.credentials.add(self.cred)
        self.source2.save()

        self.scan_job2, self.scan_task2 = create_scan_job(
            self.source2, ScanTask.SCAN_TYPE_CONNECT, 'source2',)

        self.scan_task2.update_stats('TEST NETWORK CONNECT.', sys_failed=0)

        # Scans with options & no excluded hosts
        source_options = SourceOptions(use_paramiko=True)
        source_options.save()
        self.source3 = Source(
            name='source3',
            hosts='["1.2.3.4","1.2.3.5","1.2.3.6"]',
            source_type='network',
            port=22,
            options=source_options)
        self.source3.save()
        self.source3.credentials.add(self.cred)
        self.source3.save()

        scan_options = ScanOptions(max_concurrency=2)
        scan_options.save()

        self.scan_job3, self.scan_task3 = create_scan_job(
            self.source3, ScanTask.SCAN_TYPE_CONNECT, 'source3', scan_options)
        self.scan_task3.update_stats('TEST NETWORK CONNECT.', sys_failed=0)
        self.concurrency = ScanOptions.get_default_forks()

    def test_construct_vars(self):
        """Test constructing ansible vars dictionary."""
        hc_serializer = CredentialSerializer(self.cred)
        cred = hc_serializer.data
        vars_dict = _construct_vars(22, cred)
        expected = {'ansible_become_pass': '******',
                    'ansible_port': 22,
                    'ansible_ssh_pass': '******',
                    'ansible_ssh_private_key_file': 'keyfile',
                    'ansible_user': '******',
                    'ansible_become_method': 'sudo',
                    'ansible_become_user': '******'}
        self.assertEqual(vars_dict, expected)

    def test_get_exclude_host(self):
        """Test get_exclude_hosts() method."""
        assert self.source.get_exclude_hosts() != []
        assert self.source3.get_exclude_hosts() == []

    # Tests for source1 (has hosts and excluded host)
    def test_result_store(self):
        """Test ConnectResultStore."""
        result_store = ConnectResultStore(self.scan_task)

        self.assertEqual(result_store.remaining_hosts(), ['1.2.3.4'])
        self.assertEqual(result_store.scan_task.systems_count, 1)
        self.assertEqual(result_store.scan_task.systems_scanned, 0)
        self.assertEqual(result_store.scan_task.systems_failed, 0)

        result_store.record_result('1.2.3.4', self.source, self.cred,
                                   SystemConnectionResult.UNREACHABLE)

        self.assertEqual(result_store.remaining_hosts(), [])
        self.assertEqual(result_store.scan_task.systems_count, 1)
        self.assertEqual(result_store.scan_task.systems_scanned, 0)
        self.assertEqual(result_store.scan_task.systems_unreachable, 1)

    def test_connect_inventory(self):
        """Test construct ansible inventory dictionary."""
        serializer = SourceSerializer(self.source)
        source = serializer.data
        hosts = source['hosts']
        exclude_hosts = source['exclude_hosts']
        connection_port = source['port']
        hc_serializer = CredentialSerializer(self.cred)
        cred = hc_serializer.data
        path = '/path/to/executable.py'
        ssh_timeout = '0.1s'
        ssh_args = ['--executable=' + path,
                    '--timeout=' + ssh_timeout,
                    'ssh']
        _, inventory_dict = _construct_connect_inventory(hosts, cred,
                                                         connection_port,
                                                         1,
                                                         exclude_hosts,
                                                         ssh_executable=path,
                                                         ssh_args=ssh_args)
        # pylint: disable=line-too-long
        expected = {'all':
                    {'children':
                     {'group_0':
                      {'hosts':
                       {'1.2.3.4':
                        {'ansible_host': '1.2.3.4',
                         'ansible_ssh_executable':
                         '/path/to/executable.py',
                         'ansible_ssh_common_args': '--executable=/path/to/executable.py --timeout=0.1s ssh'}}}},  # noqa
                     'vars':
                     {'ansible_port': 22,
                      'ansible_user': '******',
                      'ansible_ssh_pass': '******',
                      'ansible_ssh_private_key_file': 'keyfile',
                      'ansible_become_pass': '******',
                      'ansible_become_method': 'sudo',
                      'ansible_become_user': '******'}}}
        self.assertEqual(inventory_dict, expected)

    @patch('ansible_runner.run')
    @patch('scanner.network.connect._handle_ssh_passphrase',
           side_effect=mock_handle_ssh)
    def test_connect_failure(self, mock_run, mock_ssh_pass):
        """Test connect flow with mocked manager and failure."""
        mock_run.side_effect = AnsibleRunnerException('Fail')
        serializer = SourceSerializer(self.source)
        source = serializer.data
        hosts = source['hosts']
        exclude_hosts = source['exclude_hosts']
        connection_port = source['port']
        with self.assertRaises(AnsibleRunnerException):
            _connect(Value('i', ScanJob.JOB_RUN),
                     self.scan_task, hosts, Mock(), self.cred,
                     connection_port, self.concurrency,
                     exclude_hosts)
            mock_run.assert_called()
            mock_ssh_pass.assert_called()

    @patch('ansible_runner.run')
    def test_connect(self, mock_run):
        """Test connect flow with mocked manager."""
        mock_run.return_value.status = 'successful'
        serializer = SourceSerializer(self.source)
        source = serializer.data
        hosts = source['hosts']
        exclude_hosts = source['exclude_hosts']
        connection_port = source['port']
        _connect(Value('i', ScanJob.JOB_RUN),
                 self.scan_task, hosts, Mock(), self.cred,
                 connection_port, self.concurrency,
                 exclude_hosts)
        mock_run.assert_called()

    @patch('ansible_runner.run')
    def test_connect_ssh_crash(self, mock_run):
        """Simulate an ssh crash."""
        mock_run.return_value.status = 'successful'
        serializer = SourceSerializer(self.source)
        source = serializer.data
        hosts = source['hosts']
        exclude_hosts = source['exclude_hosts']
        connection_port = source['port']
        path = os.path.abspath(
            os.path.join(os.path.dirname(__file__),
                         'test_util/crash.py'))
        _connect(Value('i', ScanJob.JOB_RUN), self.scan_task,
                 hosts, Mock(), self.cred, connection_port,
                 self.concurrency, exclude_hosts,
                 base_ssh_executable=path)
        mock_run.assert_called()

    @patch('ansible_runner.run')
    def test_connect_ssh_hang(self, mock_run):
        """Simulate an ssh hang."""
        mock_run.return_value.status = 'successful'
        serializer = SourceSerializer(self.source)
        source = serializer.data
        hosts = source['hosts']
        exclude_hosts = source['exclude_hosts']
        connection_port = source['port']
        path = os.path.abspath(
            os.path.join(os.path.dirname(__file__),
                         'test_util/hang.py'))
        _connect(
            Value('i', ScanJob.JOB_RUN),
            self.scan_task,
            hosts,
            Mock(), self.cred, connection_port,
            self.concurrency,
            exclude_hosts,
            base_ssh_executable=path,
            ssh_timeout='0.1s')
        mock_run.assert_called()

    @patch('ansible_runner.run')
    def test_connect_runner(self, mock_run):
        """Test running a connect scan with mocked connection."""
        mock_run.return_value.status = 'successful'
        scanner = ConnectTaskRunner(self.scan_job, self.scan_task)
        result_store = MockResultStore(['1.2.3.4'])
        _, result = scanner.run_with_result_store(
            Value('i', ScanJob.JOB_RUN), result_store)
        self.assertEqual(result, ScanTask.COMPLETED)

    # Similar tests as above modified for source2 (Does not have exclude hosts)
    def test_result_store_src2(self):
        """Test ConnectResultStore."""
        result_store = ConnectResultStore(self.scan_task3)
        hosts = ['1.2.3.4', '1.2.3.5', '1.2.3.6']
        self.assertCountEqual(result_store.remaining_hosts(), hosts)
        self.assertEqual(result_store.scan_task.systems_count, 3)
        self.assertEqual(result_store.scan_task.systems_scanned, 0)
        self.assertEqual(result_store.scan_task.systems_failed, 0)

        host = hosts.pop()
        result_store.record_result(host, self.source2, self.cred,
                                   SystemConnectionResult.SUCCESS)

        self.assertCountEqual(result_store.remaining_hosts(), hosts)
        self.assertEqual(result_store.scan_task.systems_count, 3)
        self.assertEqual(result_store.scan_task.systems_scanned, 1)
        self.assertEqual(result_store.scan_task.systems_failed, 0)

        host = hosts.pop()
        # Check failure without cred
        result_store.record_result(host, self.source2, None,
                                   SystemConnectionResult.FAILED)
        self.assertCountEqual(result_store.remaining_hosts(), hosts)
        self.assertEqual(result_store.scan_task.systems_count, 3)
        self.assertEqual(result_store.scan_task.systems_scanned, 1)
        self.assertEqual(result_store.scan_task.systems_failed, 1)

        host = hosts.pop()
        # Check failure with cred
        result_store.record_result(host, self.source2, self.cred,
                                   SystemConnectionResult.FAILED)
        self.assertCountEqual(result_store.remaining_hosts(), hosts)
        self.assertEqual(result_store.scan_task.systems_count, 3)
        self.assertEqual(result_store.scan_task.systems_scanned, 1)
        self.assertEqual(result_store.scan_task.systems_failed, 2)

    def test_connect_inventory_src2(self):
        """Test construct ansible inventory dictionary."""
        serializer = SourceSerializer(self.source2)
        source = serializer.data
        hosts = source['hosts']
        connection_port = source['port']
        hc_serializer = CredentialSerializer(self.cred)
        cred = hc_serializer.data
        _, inventory_dict = _construct_connect_inventory(hosts, cred,
                                                         connection_port, 1)
        expected = {'all':
                    {'children':
                     {'group_0':
                      {'hosts':
                       {'1.2.3.4':
                        {'ansible_host': '1.2.3.4'}}}},
                     'vars':
                     {'ansible_port': 22,
                      'ansible_user': '******',
                      'ansible_ssh_pass': '******',
                      'ansible_ssh_private_key_file': 'keyfile',
                      'ansible_become_pass': '******',
                      'ansible_become_method': 'sudo',
                      'ansible_become_user': '******'}}}
        self.assertEqual(inventory_dict, expected)

    @patch('ansible_runner.run')
    @patch('scanner.network.connect._handle_ssh_passphrase',
           side_effect=mock_handle_ssh)
    def test_connect_failure_src2(self, mock_run, mock_ssh_pass):
        """Test connect flow with mocked manager and failure."""
        mock_run.side_effect = AnsibleRunnerException('Fail')
        serializer = SourceSerializer(self.source2)
        source = serializer.data
        hosts = source['hosts']
        connection_port = source['port']
        with self.assertRaises(AnsibleRunnerException):
            _connect(Value('i', ScanJob.JOB_RUN), self.scan_task,
                     hosts, Mock(), self.cred, connection_port,
                     self.concurrency)
            mock_run.assert_called()
            mock_ssh_pass.assert_called()

    @patch('ansible_runner.run')
    def test_connect_src2(self, mock_run):
        """Test connect flow with mocked manager."""
        mock_run.return_value.status = 'successful'
        serializer = SourceSerializer(self.source2)
        source = serializer.data
        hosts = source['hosts']
        connection_port = source['port']
        _connect(Value('i', ScanJob.JOB_RUN), self.scan_task,
                 hosts, Mock(), self.cred, connection_port,
                 self.concurrency)
        mock_run.assert_called()

    @patch('ansible_runner.run')
    def test_connect_runner_error(self, mock_run):
        """Test connect flow with mocked manager."""
        mock_run.side_effect = AnsibleRunnerException('Fail')
        serializer = SourceSerializer(self.source2)
        source = serializer.data
        hosts = source['hosts']
        connection_port = source['port']
        with self.assertRaises(AnsibleRunnerException):
            _connect(Value('i', ScanJob.JOB_RUN), self.scan_task,
                     hosts, Mock(), self.cred, connection_port,
                     self.concurrency)
            mock_run.assert_called()

    @patch('ansible_runner.run')
    def test_connect_runner_src2(self, mock_run):
        """Test running a connect scan with mocked connection."""
        mock_run.return_value.status = 'successful'
        scanner = ConnectTaskRunner(self.scan_job3, self.scan_task3)
        result_store = MockResultStore(['1.2.3.4'])
        _, result = scanner.run_with_result_store(
            Value('i', ScanJob.JOB_RUN), result_store)
        self.assertEqual(result, ScanTask.COMPLETED)

    @patch('ansible_runner.run')
    def test_connect_paramiko(self, mock_run):
        """Test connect with paramiko."""
        mock_run.return_value.status = 'successful'
        serializer = SourceSerializer(self.source3)
        source = serializer.data
        hosts = source['hosts']
        connection_port = source['port']
        _connect(Value('i', ScanJob.JOB_RUN),
                 self.scan_task, hosts, Mock(), self.cred,
                 connection_port, self.concurrency)
        mock_run.assert_called()

    @patch('ansible_runner.run')
    @patch('scanner.network.connect.settings.ANSIBLE_LOG_LEVEL', '1')
    def test_modifying_log_level(self, mock_run):
        """Test modifying the log level."""
        mock_run.return_value.status = 'successful'
        serializer = SourceSerializer(self.source2)
        source = serializer.data
        hosts = source['hosts']
        connection_port = source['port']
        _connect(Value('i', ScanJob.JOB_RUN),
                 self.scan_task, hosts, Mock(), self.cred,
                 connection_port, self.concurrency)
        mock_run.assert_called()
        calls = mock_run.mock_calls
        # Check to see if the parameter was passed into the runner.run()
        self.assertIn('verbosity=1', str(calls[0]))

    @patch('ansible_runner.run')
    @patch('scanner.network.connect.settings.DJANGO_SECRET_PATH', 'None')
    def test_secret_file_fail(self, mock_run):
        """Test modifying the log level."""
        mock_run.side_effect = AnsibleRunnerException()
        serializer = SourceSerializer(self.source2)
        source = serializer.data
        hosts = source['hosts']
        connection_port = source['port']
        with self.assertRaises(AnsibleRunnerException):
            _connect(Value('i', ScanJob.JOB_RUN),
                     self.scan_task, hosts, Mock(), self.cred,
                     connection_port, self.concurrency)
            mock_run.assert_called()

    @patch('ansible_runner.run')
    def test_unexpected_runner_response(self, mock_run):
        """Test unexpected runner response."""
        mock_run.return_value.status = 'unknown'
        scanner = ConnectTaskRunner(self.scan_job, self.scan_task)
        result_store = MockResultStore(['1.2.3.4'])
        conn_dict = scanner.run_with_result_store(
            Value('i', ScanJob.JOB_RUN), result_store)
        self.assertEqual(conn_dict[1], ScanTask.FAILED)

    @patch('scanner.network.connect.ConnectTaskRunner.run_with_result_store')
    def test_cancel_connect(self, mock_run):
        """Test cancel of connect."""
        # Test cancel at _connect level
        serializer = SourceSerializer(self.source3)
        source = serializer.data
        hosts = source['hosts']
        connection_port = source['port']
        with self.assertRaises(NetworkCancelException):
            _connect(Value('i', ScanJob.JOB_TERMINATE_CANCEL),
                     self.scan_task, hosts, Mock(), self.cred,
                     connection_port, self.concurrency)
        # Test cancel at run() level
        mock_run.side_effect = NetworkCancelException()
        scanner = ConnectTaskRunner(self.scan_job3, self.scan_task3)
        _, scan_result = scanner.run(Value('i', ScanJob.JOB_RUN))
        self.assertEqual(scan_result, ScanTask.CANCELED)

    @patch('scanner.network.connect.ConnectTaskRunner.run_with_result_store')
    def test_pause_connect(self, mock_run):
        """Test pause of connect."""
        # Test cancel at _connect level
        serializer = SourceSerializer(self.source3)
        source = serializer.data
        hosts = source['hosts']
        connection_port = source['port']
        with self.assertRaises(NetworkPauseException):
            _connect(Value('i', ScanJob.JOB_TERMINATE_PAUSE),
                     self.scan_task, hosts, Mock(), self.cred,
                     connection_port, self.concurrency)
        # Test cancel at run() level
        mock_run.side_effect = NetworkPauseException()
        scanner = ConnectTaskRunner(self.scan_job3, self.scan_task3)
        _, scan_result = scanner.run(Value('i', ScanJob.JOB_RUN))
        self.assertEqual(scan_result, ScanTask.PAUSED)

    def test_run_manager_interupt(self):
        """Test manager interupt for run method."""
        scanner = ConnectTaskRunner(self.scan_job, self.scan_task)
        conn_dict = scanner.run(Value('i', ScanJob.JOB_TERMINATE_CANCEL))
        self.assertEqual(conn_dict[1], ScanTask.CANCELED)

    @patch('scanner.network.connect.ConnectTaskRunner.run_with_result_store')
    def test_run_success_return_connect(self, mock_run):
        """Test pause of connect."""
        # Test cancel at run() level
        mock_run.side_effect = [[None, ScanTask.COMPLETED]]
        scanner = ConnectTaskRunner(self.scan_job3, self.scan_task3)
        _, scan_result = scanner.run(Value('i', ScanJob.JOB_RUN))
        self.assertEqual(scan_result, ScanTask.COMPLETED)

    @patch('scanner.network.connect._connect')
    def test_connect_exception(self, mock_run):
        """Test pause of connect."""
        # Test cancel at run() level
        mock_run.side_effect = AnsibleRunnerException('fail')
        scanner = ConnectTaskRunner(self.scan_job3, self.scan_task3)
        _, scan_result = scanner.run(Value('i', ScanJob.JOB_RUN))
        self.assertEqual(scan_result, ScanTask.FAILED)

    @patch('ansible_runner.run')
    def test_empty_hosts(self, mock_run):
        """Test running a connect scan with mocked connection."""
        mock_run.return_value.status = 'successful'
        scanner = ConnectTaskRunner(self.scan_job, self.scan_task)
        result_store = MockResultStore([])
        _, result = scanner.run_with_result_store(
            Value('i', ScanJob.JOB_RUN), result_store)
        self.assertEqual(result, ScanTask.COMPLETED)