#!/usr/bin/python

import cPickle
import os, unittest
import common
from autotest_lib.client.bin import local_host
from autotest_lib.client.common_lib import global_config
from autotest_lib.client.common_lib import utils
from autotest_lib.client.common_lib.test_utils import mock
from autotest_lib.frontend import setup_django_lite_environment
from autotest_lib.scheduler import drone_manager, drone_utility, drones
from autotest_lib.scheduler import scheduler_config, drone_manager
from autotest_lib.scheduler import thread_lib
from autotest_lib.scheduler import pidfile_monitor
from autotest_lib.server.hosts import ssh_host


class MockDrone(drones._AbstractDrone):
    def __init__(self, name, active_processes=0, max_processes=10,
                 allowed_users=None, support_ssp=False):
        super(MockDrone, self).__init__()
        self.name = name
        self.hostname = name
        self.active_processes = active_processes
        self.max_processes = max_processes
        self.allowed_users = allowed_users
        self._host = 'mock_drone'
        self._support_ssp = support_ssp
        # maps method names list of tuples containing method arguments
        self._recorded_calls = {'queue_call': [],
                                'send_file_to': []}


    def queue_call(self, method, *args, **kwargs):
        self._recorded_calls['queue_call'].append((method, args, kwargs))


    def call(self, method, *args, **kwargs):
        # don't bother differentiating between call() and queue_call()
        return self.queue_call(method, *args, **kwargs)


    def send_file_to(self, drone, source_path, destination_path,
                     can_fail=False):
        self._recorded_calls['send_file_to'].append(
                (drone, source_path, destination_path))


    # method for use by tests
    def _check_for_recorded_call(self, method_name, arguments):
        recorded_arg_list = self._recorded_calls[method_name]
        was_called = arguments in recorded_arg_list
        if not was_called:
            print 'Recorded args:', recorded_arg_list
            print 'Expected:', arguments
        return was_called


    def was_call_queued(self, method, *args, **kwargs):
        return self._check_for_recorded_call('queue_call',
                                             (method, args, kwargs))


    def was_file_sent(self, drone, source_path, destination_path):
        return self._check_for_recorded_call('send_file_to',
                                             (drone, source_path,
                                              destination_path))


class DroneManager(unittest.TestCase):
    _DRONE_INSTALL_DIR = '/drone/install/dir'
    _DRONE_RESULTS_DIR = os.path.join(_DRONE_INSTALL_DIR, 'results')
    _RESULTS_DIR = '/results/dir'
    _SOURCE_PATH = 'source/path'
    _DESTINATION_PATH = 'destination/path'
    _WORKING_DIRECTORY = 'working/directory'
    _USERNAME = 'my_user'

    def setUp(self):
        self.god = mock.mock_god()
        self.god.stub_with(drones, 'AUTOTEST_INSTALL_DIR',
                           self._DRONE_INSTALL_DIR)
        self.manager = drone_manager.DroneManager()
        self.god.stub_with(self.manager, '_results_dir', self._RESULTS_DIR)

        # we don't want this to ever actually get called
        self.god.stub_function(drones, 'get_drone')
        # we don't want the DroneManager to go messing with global config
        def do_nothing():
            pass
        self.god.stub_with(self.manager, 'refresh_drone_configs', do_nothing)

        # set up some dummy drones
        self.mock_drone = MockDrone('mock_drone')
        self.manager._drones[self.mock_drone.name] = self.mock_drone
        self.results_drone = MockDrone('results_drone', 0, 10)
        self.manager._results_drone = self.results_drone

        self.mock_drone_process = drone_manager.Process(self.mock_drone.name, 0)


    def tearDown(self):
        self.god.unstub_all()


    def _test_choose_drone_for_execution_helper(self, processes_info_list,
                                                requested_processes,
                                                require_ssp=False):
        for index, process_info in enumerate(processes_info_list):
            if len(process_info) == 2:
                active_processes, max_processes = process_info
                support_ssp = False
            else:
                active_processes, max_processes, support_ssp = process_info
            self.manager._enqueue_drone(MockDrone(
                    index, active_processes, max_processes, allowed_users=None,
                    support_ssp=support_ssp))

        return self.manager._choose_drone_for_execution(
                requested_processes, self._USERNAME, None, require_ssp)


    def test_choose_drone_for_execution(self):
        drone = self._test_choose_drone_for_execution_helper([(1, 2), (0, 2)],
                                                             1)
        self.assertEquals(drone.name, 1)


    def test_choose_drone_for_execution_some_full(self):
        drone = self._test_choose_drone_for_execution_helper([(0, 1), (1, 3)],
                                                             2)
        self.assertEquals(drone.name, 1)


    def test_choose_drone_for_execution_all_full(self):
        drone = self._test_choose_drone_for_execution_helper([(2, 1), (3, 2)],
                                                             1)
        self.assertEquals(drone.name, 1)


    def test_choose_drone_for_execution_all_full_same_percentage_capacity(self):
        drone = self._test_choose_drone_for_execution_helper([(5, 3), (10, 6)],
                                                             1)
        self.assertEquals(drone.name, 1)


    def test_choose_drone_for_execution_no_ssp_support(self):
        drone = self._test_choose_drone_for_execution_helper(
                [(0, 1), (1, 3)], 1, True)
        self.assertEquals(drone.name, 0)


    def test_choose_drone_for_execution_with_ssp_support(self):
        self.mock_drone._support_ssp = True
        drone = self._test_choose_drone_for_execution_helper(
                [(0, 1), (1, 3, True)], 1, True)
        self.assertEquals(drone.name, 1)


    def test_user_restrictions(self):
        # this drone is restricted to a different user
        self.manager._enqueue_drone(MockDrone(1, max_processes=10,
                                              allowed_users=['fakeuser']))
        # this drone is allowed but has lower capacity
        self.manager._enqueue_drone(MockDrone(2, max_processes=2,
                                              allowed_users=[self._USERNAME]))

        self.assertEquals(2,
                          self.manager.max_runnable_processes(self._USERNAME,
                                                              None))
        drone = self.manager._choose_drone_for_execution(
                1, username=self._USERNAME, drone_hostnames_allowed=None)
        self.assertEquals(drone.name, 2)


    def test_user_restrictions_with_full_drone(self):
        # this drone is restricted to a different user
        self.manager._enqueue_drone(MockDrone(1, max_processes=10,
                                              allowed_users=['fakeuser']))
        # this drone is allowed but is full
        self.manager._enqueue_drone(MockDrone(2, active_processes=3,
                                              max_processes=2,
                                              allowed_users=[self._USERNAME]))

        self.assertEquals(0,
                          self.manager.max_runnable_processes(self._USERNAME,
                                                              None))
        drone = self.manager._choose_drone_for_execution(
                1, username=self._USERNAME, drone_hostnames_allowed=None)
        self.assertEquals(drone.name, 2)


    def _setup_test_drone_restrictions(self, active_processes=0):
        self.manager._enqueue_drone(MockDrone(
                1, active_processes=active_processes, max_processes=10))
        self.manager._enqueue_drone(MockDrone(
                2, active_processes=active_processes, max_processes=5))
        self.manager._enqueue_drone(MockDrone(
                3, active_processes=active_processes, max_processes=2))


    def test_drone_restrictions_allow_any(self):
        self._setup_test_drone_restrictions()
        self.assertEquals(10,
                          self.manager.max_runnable_processes(self._USERNAME,
                                                              None))
        drone = self.manager._choose_drone_for_execution(
                1, username=self._USERNAME, drone_hostnames_allowed=None)
        self.assertEqual(drone.name, 1)


    def test_drone_restrictions_under_capacity(self):
        self._setup_test_drone_restrictions()
        drone_hostnames_allowed = (2, 3)
        self.assertEquals(
                5, self.manager.max_runnable_processes(self._USERNAME,
                                                       drone_hostnames_allowed))
        drone = self.manager._choose_drone_for_execution(
                1, username=self._USERNAME,
                drone_hostnames_allowed=drone_hostnames_allowed)

        self.assertEqual(drone.name, 2)


    def test_drone_restrictions_over_capacity(self):
        self._setup_test_drone_restrictions(active_processes=6)
        drone_hostnames_allowed = (2, 3)
        self.assertEquals(
                0, self.manager.max_runnable_processes(self._USERNAME,
                                                       drone_hostnames_allowed))
        drone = self.manager._choose_drone_for_execution(
                7, username=self._USERNAME,
                drone_hostnames_allowed=drone_hostnames_allowed)
        self.assertEqual(drone.name, 2)


    def test_drone_restrictions_allow_none(self):
        self._setup_test_drone_restrictions()
        drone_hostnames_allowed = ()
        self.assertEquals(
                0, self.manager.max_runnable_processes(self._USERNAME,
                                                       drone_hostnames_allowed))
        drone = self.manager._choose_drone_for_execution(
                1, username=self._USERNAME,
                drone_hostnames_allowed=drone_hostnames_allowed)
        self.assertEqual(drone, None)


    def test_initialize(self):
        results_hostname = 'results_repo'
        results_install_dir = '/results/install'
        global_config.global_config.override_config_value(
                scheduler_config.CONFIG_SECTION,
                'results_host_installation_directory', results_install_dir)

        (drones.get_drone.expect_call(self.mock_drone.name)
         .and_return(self.mock_drone))

        results_drone = MockDrone('results_drone')
        self.god.stub_function(results_drone, 'set_autotest_install_dir')
        drones.get_drone.expect_call(results_hostname).and_return(results_drone)
        results_drone.set_autotest_install_dir.expect_call(results_install_dir)

        self.manager.initialize(base_results_dir=self._RESULTS_DIR,
                                drone_hostnames=[self.mock_drone.name],
                                results_repository_hostname=results_hostname)

        self.assert_(self.mock_drone.was_call_queued(
                'initialize', self._DRONE_RESULTS_DIR + '/'))
        self.god.check_playback()


    def test_execute_command(self):
        self.manager._enqueue_drone(self.mock_drone)

        pidfile_name = 'my_pidfile'
        log_file = 'log_file'

        pidfile_id = self.manager.execute_command(
                command=['test', drone_manager.WORKING_DIRECTORY],
                working_directory=self._WORKING_DIRECTORY,
                pidfile_name=pidfile_name,
                num_processes=1,
                log_file=log_file)

        full_working_directory = os.path.join(self._DRONE_RESULTS_DIR,
                                              self._WORKING_DIRECTORY)
        self.assertEquals(pidfile_id.path,
                          os.path.join(full_working_directory, pidfile_name))
        self.assert_(self.mock_drone.was_call_queued(
                'execute_command', ['test', full_working_directory],
                full_working_directory,
                os.path.join(self._DRONE_RESULTS_DIR, log_file), pidfile_name))


    def test_attach_file_to_execution(self):
        self.manager._enqueue_drone(self.mock_drone)

        contents = 'my\ncontents'
        attached_path = self.manager.attach_file_to_execution(
                self._WORKING_DIRECTORY, contents)
        self.manager.execute_command(command=['test'],
                                     working_directory=self._WORKING_DIRECTORY,
                                     pidfile_name='mypidfile',
                                     num_processes=1,
                                     drone_hostnames_allowed=None)

        self.assert_(self.mock_drone.was_call_queued(
                'write_to_file',
                os.path.join(self._DRONE_RESULTS_DIR, attached_path),
                contents))


    def test_copy_results_on_drone(self):
        self.manager.copy_results_on_drone(self.mock_drone_process,
                                           self._SOURCE_PATH,
                                           self._DESTINATION_PATH)
        self.assert_(self.mock_drone.was_call_queued(
                'copy_file_or_directory',
                os.path.join(self._DRONE_RESULTS_DIR, self._SOURCE_PATH),
                os.path.join(self._DRONE_RESULTS_DIR, self._DESTINATION_PATH)))


    def test_copy_to_results_repository(self):
        drone_manager.ENABLE_ARCHIVING = True
        self.manager._copy_to_results_repository(self.mock_drone_process,
                                                 self._SOURCE_PATH)
        self.assert_(self.mock_drone.was_file_sent(
                self.results_drone,
                os.path.join(self._DRONE_RESULTS_DIR, self._SOURCE_PATH),
                os.path.join(self._RESULTS_DIR, self._SOURCE_PATH)))


    def test_write_lines_to_file(self):
        file_path = 'file/path'
        lines = ['line1', 'line2']
        written_data = 'line1\nline2\n'

        # write to results repository
        self.manager.write_lines_to_file(file_path, lines)
        self.assert_(self.results_drone.was_call_queued(
                'write_to_file', os.path.join(self._RESULTS_DIR, file_path),
                written_data))

        # write to a drone
        self.manager.write_lines_to_file(
                file_path, lines, paired_with_process=self.mock_drone_process)
        self.assert_(self.mock_drone.was_call_queued(
                'write_to_file',
                os.path.join(self._DRONE_RESULTS_DIR, file_path), written_data))


    def test_pidfile_expiration(self):
        self.god.stub_with(self.manager, '_get_max_pidfile_refreshes',
                           lambda: 0)
        pidfile_id = self.manager.get_pidfile_id_from('tag', 'name')
        self.manager.register_pidfile(pidfile_id)
        self.manager._drop_old_pidfiles()
        self.manager._drop_old_pidfiles()
        self.assertFalse(self.manager._registered_pidfile_info)


class ThreadedDroneTest(unittest.TestCase):
    _DRONE_INSTALL_DIR = '/drone/install/dir'
    _RESULTS_DIR = '/results/dir'
    _DRONE_CLASS = drones._RemoteDrone
    _DRONE_HOST = ssh_host.SSHHost


    def create_drone(self, drone_hostname, mock_hostname,
                     timestamp_remote_calls=False):
        """Create and initialize a Remote Drone.

        @return: A remote drone instance.
        """
        mock_host = self.god.create_mock_class(self._DRONE_HOST, mock_hostname)
        self.god.stub_function(drones.drone_utility, 'create_host')
        drones.drone_utility.create_host.expect_call(drone_hostname).and_return(
                mock_host)
        mock_host.is_up.expect_call().and_return(True)
        return self._DRONE_CLASS(drone_hostname,
                                 timestamp_remote_calls=timestamp_remote_calls)


    def create_fake_pidfile_info(self, tag='tag', name='name'):
        pidfile_id = self.manager.get_pidfile_id_from(tag, name)
        self.manager.register_pidfile(pidfile_id)
        return self.manager._registered_pidfile_info


    def setUp(self):
        self.god = mock.mock_god()
        self.god.stub_with(drones, 'AUTOTEST_INSTALL_DIR',
                           self._DRONE_INSTALL_DIR)
        self.manager = drone_manager.DroneManager()
        self.god.stub_with(self.manager, '_results_dir', self._RESULTS_DIR)

        # we don't want this to ever actually get called
        self.god.stub_function(drones, 'get_drone')
        # we don't want the DroneManager to go messing with global config
        def do_nothing():
            pass
        self.god.stub_with(self.manager, 'refresh_drone_configs', do_nothing)

        self.results_drone = MockDrone('results_drone', 0, 10)
        self.manager._results_drone = self.results_drone
        self.drone_utility_path = 'mock-drone-utility-path'
        self.mock_return = {'results': ['mock results'],
                            'warnings': []}


    def tearDown(self):
        self.god.unstub_all()

    def test_trigger_refresh(self):
        """Test drone manager trigger refresh."""
        self.god.stub_with(self._DRONE_CLASS, '_drone_utility_path',
                           self.drone_utility_path)
        mock_drone = self.create_drone('fakedrone1', 'fakehost1')
        self.manager._drones[mock_drone.hostname] = mock_drone

        # Create some fake pidfiles and confirm that a refresh call is
        # executed on each drone host, with the same pidfile paths. Then
        # check that each drone gets a key in the returned results dictionary.
        for i in range(0, 1):
            pidfile_info = self.create_fake_pidfile_info(
                    'tag%s' % i, 'name%s' %i)
        pidfile_paths = [pidfile.path for pidfile in pidfile_info.keys()]
        refresh_call = drone_utility.call('refresh', pidfile_paths)
        expected_results = {}
        mock_result = utils.CmdResult(
                stdout=cPickle.dumps(self.mock_return))
        for drone in self.manager.get_drones():
            drone._host.run.expect_call(
                    'python %s' % self.drone_utility_path,
                    stdin=cPickle.dumps([refresh_call]), stdout_tee=None,
                    connect_timeout=mock.is_instance_comparator(int)
                ).and_return(mock_result)
            expected_results[drone] = self.mock_return['results']
        self.manager.trigger_refresh()
        self.assertTrue(self.manager._refresh_task_queue.get_results() ==
                        expected_results)
        self.god.check_playback()


    def test_sync_refresh(self):
        """Test drone manager sync refresh."""

        mock_drone = self.create_drone('fakedrone1', 'fakehost1')
        self.manager._drones[mock_drone.hostname] = mock_drone

        # Insert some drone_utility results into the results queue, then
        # check that get_results returns it in the right format, and that
        # the rest of sync_refresh populates the right datastructures for
        # correct handling of agents. Also confirm that this method of
        # syncing is sufficient for the monitor to pick up the exit status
        # of the process in the same way it would in handle_agents.
        pidfile_path = 'results/hosts/host_id/job_id-name/.autoserv_execute'
        pidfiles = {pidfile_path: '123\n12\n0\n'}
        drone_utility_results = {
                'pidfiles': pidfiles,
                'autoserv_processes':{},
                'all_processes':{},
                'parse_processes':{},
                'pidfiles_second_read':pidfiles,
        }
        # Our manager instance isn't the drone manager singletone that the
        # pidfile_monitor will use by default, becuase setUp doesn't call
        # drone_manager.instance().
        self.god.stub_with(drone_manager, '_the_instance', self.manager)
        monitor = pidfile_monitor.PidfileRunMonitor()
        monitor.pidfile_id = drone_manager.PidfileId(pidfile_path)
        self.manager.register_pidfile(monitor.pidfile_id)
        self.assertTrue(monitor._state.exit_status == None)

        self.manager._refresh_task_queue.results_queue.put(
                thread_lib.ThreadedTaskQueue.result(
                    mock_drone, [drone_utility_results]))
        self.manager.sync_refresh()
        pidfiles = self.manager._pidfiles
        pidfile_id = pidfiles.keys()[0]
        pidfile_contents = pidfiles[pidfile_id]

        self.assertTrue(
                pidfile_id.path == pidfile_path and
                pidfile_contents.process.pid == 123 and
                pidfile_contents.process.hostname ==
                        mock_drone.hostname and
                pidfile_contents.exit_status == 12 and
                pidfile_contents.num_tests_failed == 0)
        self.assertTrue(monitor.exit_code() == 12)
        self.god.check_playback()


class ThreadedLocalhostDroneTest(ThreadedDroneTest):
    _DRONE_CLASS = drones._LocalDrone
    _DRONE_HOST = local_host.LocalHost


    def create_drone(self, drone_hostname, mock_hostname,
                     timestamp_remote_calls=False):
        """Create and initialize a Remote Drone.

        @return: A remote drone instance.
        """
        mock_host = self.god.create_mock_class(self._DRONE_HOST, mock_hostname)
        self.god.stub_function(drones.drone_utility, 'create_host')
        local_drone = self._DRONE_CLASS(
                timestamp_remote_calls=timestamp_remote_calls)
        self.god.stub_with(local_drone, '_host', mock_host)
        return local_drone


if __name__ == '__main__':
    unittest.main()
