#!/usr/bin/python
#pylint: disable-msg=C0111

import gc, time
import common
from autotest_lib.frontend import setup_django_environment
from autotest_lib.frontend.afe import frontend_test_utils
from autotest_lib.client.common_lib.test_utils import mock
from autotest_lib.client.common_lib.test_utils import unittest
from autotest_lib.database import database_connection
from autotest_lib.frontend.afe import models
from autotest_lib.scheduler import agent_task
from autotest_lib.scheduler import monitor_db, drone_manager, email_manager
from autotest_lib.scheduler import pidfile_monitor
from autotest_lib.scheduler import scheduler_config, gc_stats
from autotest_lib.scheduler import scheduler_lib
from autotest_lib.scheduler import scheduler_models
from autotest_lib.client.common_lib import global_config

_DEBUG = False


class DummyAgentTask(object):
    num_processes = 1
    owner_username = 'my_user'

    def get_drone_hostnames_allowed(self):
        return None


class DummyAgent(object):
    started = False
    _is_done = False
    host_ids = ()
    queue_entry_ids = ()

    def __init__(self):
        self.task = DummyAgentTask()


    def tick(self):
        self.started = True


    def is_done(self):
        return self._is_done


    def set_done(self, done):
        self._is_done = done


class IsRow(mock.argument_comparator):
    def __init__(self, row_id):
        self.row_id = row_id


    def is_satisfied_by(self, parameter):
        return list(parameter)[0] == self.row_id


    def __str__(self):
        return 'row with id %s' % self.row_id


class IsAgentWithTask(mock.argument_comparator):
    def __init__(self, task):
        self._task = task


    def is_satisfied_by(self, parameter):
        if not isinstance(parameter, monitor_db.Agent):
            return False
        tasks = list(parameter.queue.queue)
        if len(tasks) != 1:
            return False
        return tasks[0] == self._task


def _set_host_and_qe_ids(agent_or_task, id_list=None):
    if id_list is None:
        id_list = []
    agent_or_task.host_ids = agent_or_task.queue_entry_ids = id_list


class BaseSchedulerTest(unittest.TestCase,
                        frontend_test_utils.FrontendTestMixin):
    _config_section = 'AUTOTEST_WEB'

    def _do_query(self, sql):
        self._database.execute(sql)


    def _set_monitor_stubs(self):
        # Clear the instance cache as this is a brand new database.
        scheduler_models.DBObject._clear_instance_cache()

        self._database = (
            database_connection.TranslatingDatabase.get_test_database(
                translators=scheduler_lib._DB_TRANSLATORS))
        self._database.connect(db_type='django')
        self._database.debug = _DEBUG

        connection_manager = scheduler_lib.ConnectionManager(autocommit=False)
        self.god.stub_with(connection_manager, 'db_connection', self._database)
        self.god.stub_with(monitor_db, '_db_manager', connection_manager)
        self.god.stub_with(monitor_db, '_db', self._database)

        # These tests only make sense if hosts are acquired inline with the
        # rest of the tick.
        self.god.stub_with(monitor_db, '_inline_host_acquisition', True)
        self.god.stub_with(monitor_db.BaseDispatcher,
                           '_get_pending_queue_entries',
                           self._get_pending_hqes)
        self.god.stub_with(scheduler_models, '_db', self._database)
        self.god.stub_with(drone_manager.instance(), '_results_dir',
                           '/test/path')
        self.god.stub_with(drone_manager.instance(), '_temporary_directory',
                           '/test/path/tmp')
        self.god.stub_with(drone_manager.instance(), 'initialize',
                           lambda *args: None)
        self.god.stub_with(drone_manager.instance(), 'execute_actions',
                           lambda *args: None)

        monitor_db.initialize_globals()
        scheduler_models.initialize_globals()


    def setUp(self):
        self._frontend_common_setup()
        self._set_monitor_stubs()
        self._dispatcher = monitor_db.Dispatcher()


    def tearDown(self):
        self._database.disconnect()
        self._frontend_common_teardown()


    def _update_hqe(self, set, where=''):
        query = 'UPDATE afe_host_queue_entries SET ' + set
        if where:
            query += ' WHERE ' + where
        self._do_query(query)


    def _get_pending_hqes(self):
        query_string=('afe_jobs.priority DESC, '
                      'ifnull(nullif(host_id, NULL), host_id) DESC, '
                      'ifnull(nullif(meta_host, NULL), meta_host) DESC, '
                      'job_id')
        return list(scheduler_models.HostQueueEntry.fetch(
            joins='INNER JOIN afe_jobs ON (job_id=afe_jobs.id)',
            where='NOT complete AND NOT active AND status="Queued"',
            order_by=query_string))


class DispatcherSchedulingTest(BaseSchedulerTest):
    _jobs_scheduled = []


    def tearDown(self):
        super(DispatcherSchedulingTest, self).tearDown()


    def _set_monitor_stubs(self):
        super(DispatcherSchedulingTest, self)._set_monitor_stubs()

        def hqe__do_schedule_pre_job_tasks_stub(queue_entry):
            """Called by HostQueueEntry.run()."""
            self._record_job_scheduled(queue_entry.job.id, queue_entry.host.id)
            queue_entry.set_status('Starting')

        self.god.stub_with(scheduler_models.HostQueueEntry,
                           '_do_schedule_pre_job_tasks',
                           hqe__do_schedule_pre_job_tasks_stub)


    def _record_job_scheduled(self, job_id, host_id):
        record = (job_id, host_id)
        self.assert_(record not in self._jobs_scheduled,
                     'Job %d scheduled on host %d twice' %
                     (job_id, host_id))
        self._jobs_scheduled.append(record)


    def _assert_job_scheduled_on(self, job_id, host_id):
        record = (job_id, host_id)
        self.assert_(record in self._jobs_scheduled,
                     'Job %d not scheduled on host %d as expected\n'
                     'Jobs scheduled: %s' %
                     (job_id, host_id, self._jobs_scheduled))
        self._jobs_scheduled.remove(record)


    def _assert_job_scheduled_on_number_of(self, job_id, host_ids, number):
        """Assert job was scheduled on exactly number hosts out of a set."""
        found = []
        for host_id in host_ids:
            record = (job_id, host_id)
            if record in self._jobs_scheduled:
                found.append(record)
                self._jobs_scheduled.remove(record)
        if len(found) < number:
            self.fail('Job %d scheduled on fewer than %d hosts in %s.\n'
                      'Jobs scheduled: %s' % (job_id, number, host_ids, found))
        elif len(found) > number:
            self.fail('Job %d scheduled on more than %d hosts in %s.\n'
                      'Jobs scheduled: %s' % (job_id, number, host_ids, found))


    def _check_for_extra_schedulings(self):
        if len(self._jobs_scheduled) != 0:
            self.fail('Extra jobs scheduled: ' +
                      str(self._jobs_scheduled))


    def _convert_jobs_to_metahosts(self, *job_ids):
        sql_tuple = '(' + ','.join(str(i) for i in job_ids) + ')'
        self._do_query('UPDATE afe_host_queue_entries SET '
                       'meta_host=host_id, host_id=NULL '
                       'WHERE job_id IN ' + sql_tuple)


    def _lock_host(self, host_id):
        self._do_query('UPDATE afe_hosts SET locked=1 WHERE id=' +
                       str(host_id))


    def setUp(self):
        super(DispatcherSchedulingTest, self).setUp()
        self._jobs_scheduled = []


    def _run_scheduler(self):
        self._dispatcher._host_scheduler.tick()
        for _ in xrange(2): # metahost scheduling can take two cycles
            self._dispatcher._schedule_new_jobs()


    def _test_basic_scheduling_helper(self, use_metahosts):
        'Basic nonmetahost scheduling'
        self._create_job_simple([1], use_metahosts)
        self._create_job_simple([2], use_metahosts)
        self._run_scheduler()
        self._assert_job_scheduled_on(1, 1)
        self._assert_job_scheduled_on(2, 2)
        self._check_for_extra_schedulings()


    def _test_priorities_helper(self, use_metahosts):
        'Test prioritization ordering'
        self._create_job_simple([1], use_metahosts)
        self._create_job_simple([2], use_metahosts)
        self._create_job_simple([1,2], use_metahosts)
        self._create_job_simple([1], use_metahosts, priority=1)
        self._run_scheduler()
        self._assert_job_scheduled_on(4, 1) # higher priority
        self._assert_job_scheduled_on(2, 2) # earlier job over later
        self._check_for_extra_schedulings()


    def _test_hosts_ready_helper(self, use_metahosts):
        """
        Only hosts that are status=Ready, unlocked and not invalid get
        scheduled.
        """
        self._create_job_simple([1], use_metahosts)
        self._do_query('UPDATE afe_hosts SET status="Running" WHERE id=1')
        self._run_scheduler()
        self._check_for_extra_schedulings()

        self._do_query('UPDATE afe_hosts SET status="Ready", locked=1 '
                       'WHERE id=1')
        self._run_scheduler()
        self._check_for_extra_schedulings()

        self._do_query('UPDATE afe_hosts SET locked=0, invalid=1 '
                       'WHERE id=1')
        self._run_scheduler()
        if not use_metahosts:
            self._assert_job_scheduled_on(1, 1)
        self._check_for_extra_schedulings()


    def _test_hosts_idle_helper(self, use_metahosts):
        'Only idle hosts get scheduled'
        self._create_job(hosts=[1], active=True)
        self._create_job_simple([1], use_metahosts)
        self._run_scheduler()
        self._check_for_extra_schedulings()


    def _test_obey_ACLs_helper(self, use_metahosts):
        self._do_query('DELETE FROM afe_acl_groups_hosts WHERE host_id=1')
        self._create_job_simple([1], use_metahosts)
        self._run_scheduler()
        self._check_for_extra_schedulings()


    def test_basic_scheduling(self):
        self._test_basic_scheduling_helper(False)


    def test_priorities(self):
        self._test_priorities_helper(False)


    def test_hosts_ready(self):
        self._test_hosts_ready_helper(False)


    def test_hosts_idle(self):
        self._test_hosts_idle_helper(False)


    def test_obey_ACLs(self):
        self._test_obey_ACLs_helper(False)


    def test_one_time_hosts_ignore_ACLs(self):
        self._do_query('DELETE FROM afe_acl_groups_hosts WHERE host_id=1')
        self._do_query('UPDATE afe_hosts SET invalid=1 WHERE id=1')
        self._create_job_simple([1])
        self._run_scheduler()
        self._assert_job_scheduled_on(1, 1)
        self._check_for_extra_schedulings()


    def test_non_metahost_on_invalid_host(self):
        """
        Non-metahost entries can get scheduled on invalid hosts (this is how
        one-time hosts work).
        """
        self._do_query('UPDATE afe_hosts SET invalid=1')
        self._test_basic_scheduling_helper(False)


    def test_metahost_scheduling(self):
        """
        Basic metahost scheduling
        """
        self._test_basic_scheduling_helper(True)


    def test_metahost_priorities(self):
        self._test_priorities_helper(True)


    def test_metahost_hosts_ready(self):
        self._test_hosts_ready_helper(True)


    def test_metahost_hosts_idle(self):
        self._test_hosts_idle_helper(True)


    def test_metahost_obey_ACLs(self):
        self._test_obey_ACLs_helper(True)


    def test_nonmetahost_over_metahost(self):
        """
        Non-metahost entries should take priority over metahost entries
        for the same host
        """
        self._create_job(metahosts=[1])
        self._create_job(hosts=[1])
        self._run_scheduler()
        self._assert_job_scheduled_on(2, 1)
        self._check_for_extra_schedulings()


#    TODO: Revive this test.
#    def test_HostScheduler_get_host_atomic_group_id(self):
#        job = self._create_job(metahosts=[self.label6.id])
#        queue_entry = scheduler_models.HostQueueEntry.fetch(
#                where='job_id=%d' % job.id)[0]
#        # Indirectly initialize the internal state of the host scheduler.
#        self._dispatcher._refresh_pending_queue_entries()
#
#        # Test the host scheduler
#        host_scheduler = self._dispatcher._host_scheduler
#
#
#        # Two labels each in a different atomic group.  This should log an
#        # error and continue.
#        orig_logging_error = logging.error
#        def mock_logging_error(message, *args):
#            mock_logging_error._num_calls += 1
#            # Test the logging call itself, we just wrapped it to count it.
#            orig_logging_error(message, *args)
#        mock_logging_error._num_calls = 0
#        self.god.stub_with(logging, 'error', mock_logging_error)
#        host_scheduler.refresh([])
#        self.assertNotEquals(None, host_scheduler._get_host_atomic_group_id(
#                [self.label4.id, self.label8.id], queue_entry))
#        self.assertTrue(mock_logging_error._num_calls > 0)
#        self.god.unstub(logging, 'error')
#
#        # Two labels both in the same atomic group, this should not raise an
#        # error, it will merely cause the job to schedule on the intersection.
#        self.assertEquals(1, host_scheduler._get_host_atomic_group_id(
#                [self.label4.id, self.label5.id]))
#
#        self.assertEquals(None, host_scheduler._get_host_atomic_group_id([]))
#        self.assertEquals(None, host_scheduler._get_host_atomic_group_id(
#                [self.label3.id, self.label7.id, self.label6.id]))
#        self.assertEquals(1, host_scheduler._get_host_atomic_group_id(
#                [self.label4.id, self.label7.id, self.label6.id]))
#        self.assertEquals(1, host_scheduler._get_host_atomic_group_id(
#                [self.label7.id, self.label5.id]))


    def test_no_execution_subdir_not_found(self):
        """Reproduce bug crosbug.com/334353 and recover from it."""

        global_config.global_config.override_config_value(
                'SCHEDULER', 'drones', 'localhost')

        job = self._create_job(hostless=True)

        # Ensure execution_subdir is set before status
        original_set_status = scheduler_models.HostQueueEntry.set_status
        def fake_set_status(hqe, *args, **kwargs):
            self.assertEqual(hqe.execution_subdir, 'hostless')
            original_set_status(hqe, *args, **kwargs)

        self.god.stub_with(scheduler_models.HostQueueEntry, 'set_status',
                           fake_set_status)

        self._dispatcher._schedule_new_jobs()

        hqe = job.hostqueueentry_set.all()[0]
        self.assertEqual(models.HostQueueEntry.Status.STARTING, hqe.status)
        self.assertEqual('hostless', hqe.execution_subdir)


    def test_only_schedule_queued_entries(self):
        self._create_job(metahosts=[1])
        self._update_hqe(set='active=1, host_id=2')
        self._run_scheduler()
        self._check_for_extra_schedulings()


    def test_no_ready_hosts(self):
        self._create_job(hosts=[1])
        self._do_query('UPDATE afe_hosts SET status="Repair Failed"')
        self._run_scheduler()
        self._check_for_extra_schedulings()


    def test_garbage_collection(self):
        self.god.stub_with(self._dispatcher, '_seconds_between_garbage_stats',
                           999999)
        self.god.stub_function(gc, 'collect')
        self.god.stub_function(gc_stats, '_log_garbage_collector_stats')
        gc.collect.expect_call().and_return(0)
        gc_stats._log_garbage_collector_stats.expect_call()
        # Force a garbage collection run
        self._dispatcher._last_garbage_stats_time = 0
        self._dispatcher._garbage_collection()
        # The previous call should have reset the time, it won't do anything
        # the second time.  If it does, we'll get an unexpected call.
        self._dispatcher._garbage_collection()


class DispatcherThrottlingTest(BaseSchedulerTest):
    """
    Test that the dispatcher throttles:
     * total number of running processes
     * number of processes started per cycle
    """
    _MAX_RUNNING = 3
    _MAX_STARTED = 2

    def setUp(self):
        super(DispatcherThrottlingTest, self).setUp()
        scheduler_config.config.max_processes_per_drone = self._MAX_RUNNING
        scheduler_config.config.max_processes_started_per_cycle = (
            self._MAX_STARTED)

        def fake_max_runnable_processes(fake_self, username,
                                        drone_hostnames_allowed):
            running = sum(agent.task.num_processes
                          for agent in self._agents
                          if agent.started and not agent.is_done())
            return self._MAX_RUNNING - running
        self.god.stub_with(drone_manager.DroneManager, 'max_runnable_processes',
                           fake_max_runnable_processes)


    def _setup_some_agents(self, num_agents):
        self._agents = [DummyAgent() for i in xrange(num_agents)]
        self._dispatcher._agents = list(self._agents)


    def _run_a_few_cycles(self):
        for i in xrange(4):
            self._dispatcher._handle_agents()


    def _assert_agents_started(self, indexes, is_started=True):
        for i in indexes:
            self.assert_(self._agents[i].started == is_started,
                         'Agent %d %sstarted' %
                         (i, is_started and 'not ' or ''))


    def _assert_agents_not_started(self, indexes):
        self._assert_agents_started(indexes, False)


    def test_throttle_total(self):
        self._setup_some_agents(4)
        self._run_a_few_cycles()
        self._assert_agents_started([0, 1, 2])
        self._assert_agents_not_started([3])


    def test_throttle_per_cycle(self):
        self._setup_some_agents(3)
        self._dispatcher._handle_agents()
        self._assert_agents_started([0, 1])
        self._assert_agents_not_started([2])


    def test_throttle_with_synchronous(self):
        self._setup_some_agents(2)
        self._agents[0].task.num_processes = 3
        self._run_a_few_cycles()
        self._assert_agents_started([0])
        self._assert_agents_not_started([1])


    def test_large_agent_starvation(self):
        """
        Ensure large agents don't get starved by lower-priority agents.
        """
        self._setup_some_agents(3)
        self._agents[1].task.num_processes = 3
        self._run_a_few_cycles()
        self._assert_agents_started([0])
        self._assert_agents_not_started([1, 2])

        self._agents[0].set_done(True)
        self._run_a_few_cycles()
        self._assert_agents_started([1])
        self._assert_agents_not_started([2])


    def test_zero_process_agent(self):
        self._setup_some_agents(5)
        self._agents[4].task.num_processes = 0
        self._run_a_few_cycles()
        self._assert_agents_started([0, 1, 2, 4])
        self._assert_agents_not_started([3])


class PidfileRunMonitorTest(unittest.TestCase):
    execution_tag = 'test_tag'
    pid = 12345
    process = drone_manager.Process('myhost', pid)
    num_tests_failed = 1

    def setUp(self):
        self.god = mock.mock_god()
        self.mock_drone_manager = self.god.create_mock_class(
            drone_manager.DroneManager, 'drone_manager')
        self.god.stub_with(drone_manager, '_the_instance',
                           self.mock_drone_manager)
        self.god.stub_function(email_manager.manager, 'enqueue_notify_email')
        self.god.stub_with(pidfile_monitor, '_get_pidfile_timeout_secs',
                           self._mock_get_pidfile_timeout_secs)

        self.pidfile_id = object()

        (self.mock_drone_manager.get_pidfile_id_from
             .expect_call(self.execution_tag,
                          pidfile_name=drone_manager.AUTOSERV_PID_FILE)
             .and_return(self.pidfile_id))

        self.monitor = pidfile_monitor.PidfileRunMonitor()
        self.monitor.attach_to_existing_process(self.execution_tag)

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


    def _mock_get_pidfile_timeout_secs(self):
        return 300


    def setup_pidfile(self, pid=None, exit_code=None, tests_failed=None,
                      use_second_read=False):
        contents = drone_manager.PidfileContents()
        if pid is not None:
            contents.process = drone_manager.Process('myhost', pid)
        contents.exit_status = exit_code
        contents.num_tests_failed = tests_failed
        self.mock_drone_manager.get_pidfile_contents.expect_call(
            self.pidfile_id, use_second_read=use_second_read).and_return(
            contents)


    def set_not_yet_run(self):
        self.setup_pidfile()


    def set_empty_pidfile(self):
        self.setup_pidfile()


    def set_running(self, use_second_read=False):
        self.setup_pidfile(self.pid, use_second_read=use_second_read)


    def set_complete(self, error_code, use_second_read=False):
        self.setup_pidfile(self.pid, error_code, self.num_tests_failed,
                           use_second_read=use_second_read)


    def _check_monitor(self, expected_pid, expected_exit_status,
                       expected_num_tests_failed):
        if expected_pid is None:
            self.assertEquals(self.monitor._state.process, None)
        else:
            self.assertEquals(self.monitor._state.process.pid, expected_pid)
        self.assertEquals(self.monitor._state.exit_status, expected_exit_status)
        self.assertEquals(self.monitor._state.num_tests_failed,
                          expected_num_tests_failed)


        self.god.check_playback()


    def _test_read_pidfile_helper(self, expected_pid, expected_exit_status,
                                  expected_num_tests_failed):
        self.monitor._read_pidfile()
        self._check_monitor(expected_pid, expected_exit_status,
                            expected_num_tests_failed)


    def _get_expected_tests_failed(self, expected_exit_status):
        if expected_exit_status is None:
            expected_tests_failed = None
        else:
            expected_tests_failed = self.num_tests_failed
        return expected_tests_failed


    def test_read_pidfile(self):
        self.set_not_yet_run()
        self._test_read_pidfile_helper(None, None, None)

        self.set_empty_pidfile()
        self._test_read_pidfile_helper(None, None, None)

        self.set_running()
        self._test_read_pidfile_helper(self.pid, None, None)

        self.set_complete(123)
        self._test_read_pidfile_helper(self.pid, 123, self.num_tests_failed)


    def test_read_pidfile_error(self):
        self.mock_drone_manager.get_pidfile_contents.expect_call(
            self.pidfile_id, use_second_read=False).and_return(
            drone_manager.InvalidPidfile('error'))
        self.assertRaises(pidfile_monitor.PidfileRunMonitor._PidfileException,
                          self.monitor._read_pidfile)
        self.god.check_playback()


    def setup_is_running(self, is_running):
        self.mock_drone_manager.is_process_running.expect_call(
            self.process).and_return(is_running)


    def _test_get_pidfile_info_helper(self, expected_pid, expected_exit_status,
                                      expected_num_tests_failed):
        self.monitor._get_pidfile_info()
        self._check_monitor(expected_pid, expected_exit_status,
                            expected_num_tests_failed)


    def test_get_pidfile_info(self):
        """
        normal cases for get_pidfile_info
        """
        # running
        self.set_running()
        self.setup_is_running(True)
        self._test_get_pidfile_info_helper(self.pid, None, None)

        # exited during check
        self.set_running()
        self.setup_is_running(False)
        self.set_complete(123, use_second_read=True) # pidfile gets read again
        self._test_get_pidfile_info_helper(self.pid, 123, self.num_tests_failed)

        # completed
        self.set_complete(123)
        self._test_get_pidfile_info_helper(self.pid, 123, self.num_tests_failed)


    def test_get_pidfile_info_running_no_proc(self):
        """
        pidfile shows process running, but no proc exists
        """
        # running but no proc
        self.set_running()
        self.setup_is_running(False)
        self.set_running(use_second_read=True)
        email_manager.manager.enqueue_notify_email.expect_call(
            mock.is_string_comparator(), mock.is_string_comparator())
        self._test_get_pidfile_info_helper(self.pid, 1, 0)
        self.assertTrue(self.monitor.lost_process)


    def test_get_pidfile_info_not_yet_run(self):
        """
        pidfile hasn't been written yet
        """
        self.set_not_yet_run()
        self._test_get_pidfile_info_helper(None, None, None)


    def test_process_failed_to_write_pidfile(self):
        self.set_not_yet_run()
        email_manager.manager.enqueue_notify_email.expect_call(
            mock.is_string_comparator(), mock.is_string_comparator())
        self.monitor._start_time = (time.time() -
                                    pidfile_monitor._get_pidfile_timeout_secs() - 1)
        self._test_get_pidfile_info_helper(None, 1, 0)
        self.assertTrue(self.monitor.lost_process)


class AgentTest(unittest.TestCase):
    def setUp(self):
        self.god = mock.mock_god()
        self._dispatcher = self.god.create_mock_class(monitor_db.Dispatcher,
                                                      'dispatcher')


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


    def _create_mock_task(self, name):
        task = self.god.create_mock_class(agent_task.AgentTask, name)
        task.num_processes = 1
        _set_host_and_qe_ids(task)
        return task

    def _create_agent(self, task):
        agent = monitor_db.Agent(task)
        agent.dispatcher = self._dispatcher
        return agent


    def _finish_agent(self, agent):
        while not agent.is_done():
            agent.tick()


    def test_agent_abort(self):
        task = self._create_mock_task('task')
        task.poll.expect_call()
        task.is_done.expect_call().and_return(False)
        task.abort.expect_call()
        task.aborted = True

        agent = self._create_agent(task)
        agent.tick()
        agent.abort()
        self._finish_agent(agent)
        self.god.check_playback()


    def _test_agent_abort_before_started_helper(self, ignore_abort=False):
        task = self._create_mock_task('task')
        task.abort.expect_call()
        if ignore_abort:
            task.aborted = False
            task.poll.expect_call()
            task.is_done.expect_call().and_return(True)
            task.success = True
        else:
            task.aborted = True

        agent = self._create_agent(task)
        agent.abort()
        self._finish_agent(agent)
        self.god.check_playback()


    def test_agent_abort_before_started(self):
        self._test_agent_abort_before_started_helper()
        self._test_agent_abort_before_started_helper(True)


class JobSchedulingTest(BaseSchedulerTest):
    def _test_run_helper(self, expect_agent=True, expect_starting=False,
                         expect_pending=False):
        if expect_starting:
            expected_status = models.HostQueueEntry.Status.STARTING
        elif expect_pending:
            expected_status = models.HostQueueEntry.Status.PENDING
        else:
            expected_status = models.HostQueueEntry.Status.VERIFYING
        job = scheduler_models.Job.fetch('id = 1')[0]
        queue_entry = scheduler_models.HostQueueEntry.fetch('id = 1')[0]
        assert queue_entry.job is job
        job.run_if_ready(queue_entry)

        self.god.check_playback()

        self._dispatcher._schedule_delay_tasks()
        self._dispatcher._schedule_running_host_queue_entries()
        agent = self._dispatcher._agents[0]

        actual_status = models.HostQueueEntry.smart_get(1).status
        self.assertEquals(expected_status, actual_status)

        if not expect_agent:
            self.assertEquals(agent, None)
            return

        self.assert_(isinstance(agent, monitor_db.Agent))
        self.assert_(agent.task)
        return agent.task


    def test_run_if_ready_delays(self):
        # Also tests Job.run_with_ready_delay() on atomic group jobs.
        django_job = self._create_job(hosts=[5, 6], atomic_group=1)
        job = scheduler_models.Job(django_job.id)
        self.assertEqual(1, job.synch_count)
        django_hqes = list(models.HostQueueEntry.objects.filter(job=job.id))
        self.assertEqual(2, len(django_hqes))
        self.assertEqual(2, django_hqes[0].atomic_group.max_number_of_machines)

        def set_hqe_status(django_hqe, status):
            django_hqe.status = status
            django_hqe.save()
            scheduler_models.HostQueueEntry(django_hqe.id).host.set_status(status)

        # An initial state, our synch_count is 1
        set_hqe_status(django_hqes[0], models.HostQueueEntry.Status.VERIFYING)
        set_hqe_status(django_hqes[1], models.HostQueueEntry.Status.PENDING)

        # So that we don't depend on the config file value during the test.
        self.assert_(scheduler_config.config
                     .secs_to_wait_for_atomic_group_hosts is not None)
        self.god.stub_with(scheduler_config.config,
                           'secs_to_wait_for_atomic_group_hosts', 123456)

        # Get the pending one as a scheduler_models.HostQueueEntry object.
        hqe = scheduler_models.HostQueueEntry(django_hqes[1].id)
        self.assert_(not job._delay_ready_task)
        self.assertTrue(job.is_ready())

        # Ready with one pending, one verifying and an atomic group should
        # result in a DelayCallTask to re-check if we're ready a while later.
        job.run_if_ready(hqe)
        self.assertEquals('Waiting', hqe.status)
        self._dispatcher._schedule_delay_tasks()
        self.assertEquals('Pending', hqe.status)
        agent = self._dispatcher._agents[0]
        self.assert_(job._delay_ready_task)
        self.assert_(isinstance(agent, monitor_db.Agent))
        self.assert_(agent.task)
        delay_task = agent.task
        self.assert_(isinstance(delay_task, scheduler_models.DelayedCallTask))
        self.assert_(not delay_task.is_done())

        self.god.stub_function(delay_task, 'abort')

        self.god.stub_function(job, 'run')

        self.god.stub_function(job, '_pending_count')
        self.god.stub_with(job, 'synch_count', 9)
        self.god.stub_function(job, 'request_abort')

        # Test that the DelayedCallTask's callback queued up above does the
        # correct thing and does not call run if there are not enough hosts
        # in pending after the delay.
        job._pending_count.expect_call().and_return(0)
        job.request_abort.expect_call()
        delay_task._callback()
        self.god.check_playback()

        # Test that the DelayedCallTask's callback queued up above does the
        # correct thing and returns the Agent returned by job.run() if
        # there are still enough hosts pending after the delay.
        job.synch_count = 4
        job._pending_count.expect_call().and_return(4)
        job.run.expect_call(hqe)
        delay_task._callback()
        self.god.check_playback()

        job._pending_count.expect_call().and_return(4)

        # Adjust the delay deadline so that enough time has passed.
        job._delay_ready_task.end_time = time.time() - 111111
        job.run.expect_call(hqe)
        # ...the delay_expired condition should cause us to call run()
        self._dispatcher._handle_agents()
        self.god.check_playback()
        delay_task.success = False

        # Adjust the delay deadline back so that enough time has not passed.
        job._delay_ready_task.end_time = time.time() + 111111
        self._dispatcher._handle_agents()
        self.god.check_playback()

        # Now max_number_of_machines HQEs are in pending state.  Remaining
        # delay will now be ignored.
        other_hqe = scheduler_models.HostQueueEntry(django_hqes[0].id)
        self.god.unstub(job, 'run')
        self.god.unstub(job, '_pending_count')
        self.god.unstub(job, 'synch_count')
        self.god.unstub(job, 'request_abort')
        # ...the over_max_threshold test should cause us to call run()
        delay_task.abort.expect_call()
        other_hqe.on_pending()
        self.assertEquals('Starting', other_hqe.status)
        self.assertEquals('Starting', hqe.status)
        self.god.stub_function(job, 'run')
        self.god.unstub(delay_task, 'abort')

        hqe.set_status('Pending')
        other_hqe.set_status('Pending')
        # Now we're not over the max for the atomic group.  But all assigned
        # hosts are in pending state.  over_max_threshold should make us run().
        hqe.atomic_group.max_number_of_machines += 1
        hqe.atomic_group.save()
        job.run.expect_call(hqe)
        hqe.on_pending()
        self.god.check_playback()
        hqe.atomic_group.max_number_of_machines -= 1
        hqe.atomic_group.save()

        other_hqe = scheduler_models.HostQueueEntry(django_hqes[0].id)
        self.assertTrue(hqe.job is other_hqe.job)
        # DBObject classes should reuse instances so these should be the same.
        self.assertEqual(job, other_hqe.job)
        self.assertEqual(other_hqe.job, hqe.job)
        # Be sure our delay was not lost during the other_hqe construction.
        self.assertEqual(job._delay_ready_task, delay_task)
        self.assert_(job._delay_ready_task)
        self.assertFalse(job._delay_ready_task.is_done())
        self.assertFalse(job._delay_ready_task.aborted)

        # We want the real run() to be called below.
        self.god.unstub(job, 'run')

        # We pass in the other HQE this time the same way it would happen
        # for real when one host finishes verifying and enters pending.
        job.run_if_ready(other_hqe)

        # The delayed task must be aborted by the actual run() call above.
        self.assertTrue(job._delay_ready_task.aborted)
        self.assertFalse(job._delay_ready_task.success)
        self.assertTrue(job._delay_ready_task.is_done())

        # Check that job run() and _finish_run() were called by the above:
        self._dispatcher._schedule_running_host_queue_entries()
        agent = self._dispatcher._agents[0]
        self.assert_(agent.task)
        task = agent.task
        self.assert_(isinstance(task, monitor_db.QueueTask))
        # Requery these hqes in order to verify the status from the DB.
        django_hqes = list(models.HostQueueEntry.objects.filter(job=job.id))
        for entry in django_hqes:
            self.assertEqual(models.HostQueueEntry.Status.STARTING,
                             entry.status)

        # We're already running, but more calls to run_with_ready_delay can
        # continue to come in due to straggler hosts enter Pending.  Make
        # sure we don't do anything.
        self.god.stub_function(job, 'run')
        job.run_with_ready_delay(hqe)
        self.god.check_playback()
        self.god.unstub(job, 'run')


    def test_run_synchronous_atomic_group_ready(self):
        self._create_job(hosts=[5, 6], atomic_group=1, synchronous=True)
        self._update_hqe("status='Pending', execution_subdir=''")

        queue_task = self._test_run_helper(expect_starting=True)

        self.assert_(isinstance(queue_task, monitor_db.QueueTask))
        # Atomic group jobs that do not depend on a specific label in the
        # atomic group will use the atomic group name as their group name.
        self.assertEquals(queue_task.queue_entries[0].get_group_name(),
                          'atomic1')


    def test_run_synchronous_atomic_group_with_label_ready(self):
        job = self._create_job(hosts=[5, 6], atomic_group=1, synchronous=True)
        job.dependency_labels.add(self.label4)
        self._update_hqe("status='Pending', execution_subdir=''")

        queue_task = self._test_run_helper(expect_starting=True)

        self.assert_(isinstance(queue_task, monitor_db.QueueTask))
        # Atomic group jobs that also specify a label in the atomic group
        # will use the label name as their group name.
        self.assertEquals(queue_task.queue_entries[0].get_group_name(),
                          'label4')


    def test_run_synchronous_ready(self):
        self._create_job(hosts=[1, 2], synchronous=True)
        self._update_hqe("status='Pending', execution_subdir=''")

        queue_task = self._test_run_helper(expect_starting=True)

        self.assert_(isinstance(queue_task, monitor_db.QueueTask))
        self.assertEquals(queue_task.job.id, 1)
        hqe_ids = [hqe.id for hqe in queue_task.queue_entries]
        self.assertEquals(hqe_ids, [1, 2])


    def test_schedule_running_host_queue_entries_fail(self):
        self._create_job(hosts=[2])
        self._update_hqe("status='%s', execution_subdir=''" %
                         models.HostQueueEntry.Status.PENDING)
        job = scheduler_models.Job.fetch('id = 1')[0]
        queue_entry = scheduler_models.HostQueueEntry.fetch('id = 1')[0]
        assert queue_entry.job is job
        job.run_if_ready(queue_entry)
        self.assertEqual(queue_entry.status,
                         models.HostQueueEntry.Status.STARTING)
        self.assert_(queue_entry.execution_subdir)
        self.god.check_playback()

        class dummy_test_agent(object):
            task = 'dummy_test_agent'
        self._dispatcher._register_agent_for_ids(
                self._dispatcher._host_agents, [queue_entry.host.id],
                dummy_test_agent)

        # Attempted to schedule on a host that already has an agent.
        self.assertRaises(scheduler_lib.SchedulerError,
                          self._dispatcher._schedule_running_host_queue_entries)


    def test_schedule_hostless_job(self):
        job = self._create_job(hostless=True)
        self.assertEqual(1, job.hostqueueentry_set.count())
        hqe_query = scheduler_models.HostQueueEntry.fetch(
                'id = %s' % job.hostqueueentry_set.all()[0].id)
        self.assertEqual(1, len(hqe_query))
        hqe = hqe_query[0]

        self.assertEqual(models.HostQueueEntry.Status.QUEUED, hqe.status)
        self.assertEqual(0, len(self._dispatcher._agents))

        self._dispatcher._schedule_new_jobs()

        self.assertEqual(models.HostQueueEntry.Status.STARTING, hqe.status)
        self.assertEqual(1, len(self._dispatcher._agents))

        self._dispatcher._schedule_new_jobs()

        # No change to previously schedule hostless job, and no additional agent
        self.assertEqual(models.HostQueueEntry.Status.STARTING, hqe.status)
        self.assertEqual(1, len(self._dispatcher._agents))


class TopLevelFunctionsTest(unittest.TestCase):
    def setUp(self):
        self.god = mock.mock_god()


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


    def test_autoserv_command_line(self):
        machines = 'abcd12,efgh34'
        extra_args = ['-Z', 'hello']
        expected_command_line_base = set((monitor_db._autoserv_path, '-p',
                                          '-m', machines, '-r',
                                          drone_manager.WORKING_DIRECTORY))

        expected_command_line = expected_command_line_base.union(
                ['--verbose']).union(extra_args)
        command_line = set(
                monitor_db._autoserv_command_line(machines, extra_args))
        self.assertEqual(expected_command_line, command_line)

        class FakeJob(object):
            owner = 'Bob'
            name = 'fake job name'
            test_retry = 0
            id = 1337

        class FakeHQE(object):
            job = FakeJob

        expected_command_line = expected_command_line_base.union(
                ['-u', FakeJob.owner, '-l', FakeJob.name])
        command_line = set(monitor_db._autoserv_command_line(
                machines, extra_args=[], queue_entry=FakeHQE, verbose=False))
        self.assertEqual(expected_command_line, command_line)


class AgentTaskTest(unittest.TestCase,
                    frontend_test_utils.FrontendTestMixin):
    def setUp(self):
        self._frontend_common_setup()


    def tearDown(self):
        self._frontend_common_teardown()


    def _setup_drones(self):
        self.god.stub_function(models.DroneSet, 'drone_sets_enabled')
        models.DroneSet.drone_sets_enabled.expect_call().and_return(True)

        drones = []
        for x in xrange(4):
            drones.append(models.Drone.objects.create(hostname=str(x)))

        drone_set_1 = models.DroneSet.objects.create(name='1')
        drone_set_1.drones.add(*drones[0:2])
        drone_set_2 = models.DroneSet.objects.create(name='2')
        drone_set_2.drones.add(*drones[2:4])
        drone_set_3 = models.DroneSet.objects.create(name='3')

        job_1 = self._create_job_simple([self.hosts[0].id],
                                        drone_set=drone_set_1)
        job_2 = self._create_job_simple([self.hosts[0].id],
                                        drone_set=drone_set_2)
        job_3 = self._create_job_simple([self.hosts[0].id],
                                        drone_set=drone_set_3)

        job_4 = self._create_job_simple([self.hosts[0].id])
        job_4.drone_set = None
        job_4.save()

        hqe_1 = job_1.hostqueueentry_set.all()[0]
        hqe_2 = job_2.hostqueueentry_set.all()[0]
        hqe_3 = job_3.hostqueueentry_set.all()[0]
        hqe_4 = job_4.hostqueueentry_set.all()[0]

        return (hqe_1, hqe_2, hqe_3, hqe_4), agent_task.AgentTask()


    def test_get_drone_hostnames_allowed_no_drones_in_set(self):
        hqes, task = self._setup_drones()
        task.queue_entry_ids = (hqes[2].id,)
        self.assertEqual(set(), task.get_drone_hostnames_allowed())
        self.god.check_playback()


    def test_get_drone_hostnames_allowed_no_drone_set(self):
        hqes, task = self._setup_drones()
        hqe = hqes[3]
        task.queue_entry_ids = (hqe.id,)

        result = object()

        self.god.stub_function(task, '_user_or_global_default_drone_set')
        task._user_or_global_default_drone_set.expect_call(
                hqe.job, hqe.job.user()).and_return(result)

        self.assertEqual(result, task.get_drone_hostnames_allowed())
        self.god.check_playback()


    def test_get_drone_hostnames_allowed_success(self):
        hqes, task = self._setup_drones()
        task.queue_entry_ids = (hqes[0].id,)
        self.assertEqual(set(('0','1')), task.get_drone_hostnames_allowed())
        self.god.check_playback()


    def test_get_drone_hostnames_allowed_multiple_jobs(self):
        hqes, task = self._setup_drones()
        task.queue_entry_ids = (hqes[0].id, hqes[1].id)
        self.assertRaises(AssertionError,
                          task.get_drone_hostnames_allowed)
        self.god.check_playback()


    def test_get_drone_hostnames_allowed_no_hqe(self):
        class MockSpecialTask(object):
            requested_by = object()

        class MockSpecialAgentTask(agent_task.SpecialAgentTask):
            task = MockSpecialTask()
            queue_entry_ids = []
            def __init__(self, *args, **kwargs):
                pass

        task = MockSpecialAgentTask()
        self.god.stub_function(models.DroneSet, 'drone_sets_enabled')
        self.god.stub_function(task, '_user_or_global_default_drone_set')

        result = object()
        models.DroneSet.drone_sets_enabled.expect_call().and_return(True)
        task._user_or_global_default_drone_set.expect_call(
                task.task, MockSpecialTask.requested_by).and_return(result)

        self.assertEqual(result, task.get_drone_hostnames_allowed())
        self.god.check_playback()


    def _setup_test_user_or_global_default_drone_set(self):
        result = object()
        class MockDroneSet(object):
            def get_drone_hostnames(self):
                return result

        self.god.stub_function(models.DroneSet, 'get_default')
        models.DroneSet.get_default.expect_call().and_return(MockDroneSet())
        return result


    def test_user_or_global_default_drone_set(self):
        expected = object()
        class MockDroneSet(object):
            def get_drone_hostnames(self):
                return expected
        class MockUser(object):
            drone_set = MockDroneSet()

        self._setup_test_user_or_global_default_drone_set()

        actual = agent_task.AgentTask()._user_or_global_default_drone_set(
                None, MockUser())

        self.assertEqual(expected, actual)
        self.god.check_playback()


    def test_user_or_global_default_drone_set_no_user(self):
        expected = self._setup_test_user_or_global_default_drone_set()
        actual = agent_task.AgentTask()._user_or_global_default_drone_set(
                None, None)

        self.assertEqual(expected, actual)
        self.god.check_playback()


    def test_user_or_global_default_drone_set_no_user_drone_set(self):
        class MockUser(object):
            drone_set = None
            login = None

        expected = self._setup_test_user_or_global_default_drone_set()
        actual = agent_task.AgentTask()._user_or_global_default_drone_set(
                None, MockUser())

        self.assertEqual(expected, actual)
        self.god.check_playback()


    def test_abort_HostlessQueueTask(self):
        hqe = self.god.create_mock_class(scheduler_models.HostQueueEntry,
                                         'HostQueueEntry')
        # If hqe is still in STARTING status, aborting the task should finish
        # without changing hqe's status.
        hqe.status = models.HostQueueEntry.Status.STARTING
        hqe.job = None
        hqe.id = 0
        task = monitor_db.HostlessQueueTask(hqe)
        task.abort()

        # If hqe is in RUNNING status, aborting the task should change hqe's
        # status to Parsing, so FinalReparseTask can be scheduled.
        hqe.set_status.expect_call('Parsing')
        hqe.status = models.HostQueueEntry.Status.RUNNING
        hqe.job = None
        hqe.id = 0
        task = monitor_db.HostlessQueueTask(hqe)
        task.abort()


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