def setup_job(self): mock_graph = mock.Mock(autospec=True) mock_graph.get_action_map.return_value = {} mock_graph.action_map = {} self.job = mock.Mock(autospec=True) self.job.allow_overlap = False self.job.max_runtime = datetime.timedelta(days=1) self.job_scheduler = JobScheduler(job=self.job)
class TestJobSchedulerGetRunsToSchedule(TestCase): @setup def setup_job(self): self.scheduler = mock.Mock() run_collection = mock.Mock(has_pending=False) node_pool = mock.Mock() self.job = job.Job( "jobname", self.scheduler, run_collection=run_collection, node_pool=node_pool, ) self.job_scheduler = JobScheduler(self.job) self.job.runs.get_pending.return_value = False self.scheduler.queue_overlapping = True def test_get_runs_to_schedule_no_queue_with_pending(self): self.scheduler.queue_overlapping = False self.job.runs.has_pending = True job_runs = self.job_scheduler.get_runs_to_schedule(False) assert_length(job_runs, 0) def test_get_runs_to_schedule_queue_with_pending(self): job_runs = list(self.job_scheduler.get_runs_to_schedule(False)) self.job.runs.get_newest.assert_called_with(include_manual=False) self.job.scheduler.next_run_time.assert_called_once_with( self.job.runs.get_newest.return_value.run_time, ) assert_length(job_runs, 1) # This should return a JobRun which has the job attached as an observer job_runs[0].attach.assert_any_call(True, self.job) def test_get_runs_to_schedule_no_pending(self): job_runs = list(self.job_scheduler.get_runs_to_schedule(False)) self.job.runs.get_newest.assert_called_with(include_manual=False) self.job.scheduler.next_run_time.assert_called_once_with( self.job.runs.get_newest.return_value.run_time, ) assert_length(job_runs, 1) # This should return a JobRun which has the job attached as an observer job_runs[0].attach.assert_any_call(True, self.job) def test_get_runs_to_schedule_no_last_run(self): self.job.runs.get_newest.return_value = None job_runs = list(self.job_scheduler.get_runs_to_schedule(False)) self.job.scheduler.next_run_time.assert_called_once_with(None) assert_length(job_runs, 1) # This should return a JobRun which has the job attached as an observer job_runs[0].attach.assert_any_call(True, self.job) def test_get_runs_to_schedule_ignore_last(self): job_runs = list(self.job_scheduler.get_runs_to_schedule(True)) self.job.scheduler.next_run_time.assert_called_once_with(None) assert_length(job_runs, 1) self.scheduler.next_run_time.assert_called_once_with(None)
def setup_job(self): self.scheduler = mock.Mock() run_collection = mock.Mock(has_pending=False) node_pool = mock.Mock() self.job = job.Job( "jobname", self.scheduler, run_collection=run_collection, node_pool=node_pool, ) self.job_scheduler = JobScheduler(self.job) self.job.runs.get_pending.return_value = False self.scheduler.queue_overlapping = True
def setup_job(self): self.scheduler = mock.Mock() run_collection = mock.Mock() node_pool = mock.Mock() self.job = job.Job( "jobname", self.scheduler, run_collection=run_collection, node_pool=node_pool, ) self.job_scheduler = JobScheduler(self.job) self.manual_run = mock.Mock() self.job.build_new_runs = mock.Mock(return_value=[self.manual_run])
class JobSchedulerManualStartTestCase(testingutils.MockTimeTestCase): now = datetime.datetime.now() @setup def setup_job(self): self.scheduler = mock.Mock() run_collection = mock.Mock() node_pool = mock.Mock() self.job = job.Job( "jobname", self.scheduler, run_collection=run_collection, node_pool=node_pool, ) self.job_scheduler = JobScheduler(self.job) self.manual_run = mock.Mock() self.job.build_new_runs = mock.Mock(return_value=[self.manual_run]) def test_manual_start(self): manual_runs = self.job_scheduler.manual_start() self.job.build_new_runs.assert_called_with(self.now, manual=True) assert_length(manual_runs, 1) self.manual_run.start.assert_called_once_with() def test_manual_start_default_with_timezone(self): self.job.time_zone = mock.Mock() with mock.patch( 'tron.core.job_scheduler.timeutils.current_time', autospec=True, ) as mock_current: manual_runs = self.job_scheduler.manual_start() mock_current.assert_called_with(tz=self.job.time_zone) self.job.build_new_runs.assert_called_with( mock_current.return_value, manual=True, ) assert_length(manual_runs, 1) self.manual_run.start.assert_called_once_with() def test_manual_start_with_run_time(self): run_time = datetime.datetime(2012, 3, 14, 15, 9, 26) manual_runs = self.job_scheduler.manual_start(run_time) self.job.build_new_runs.assert_called_with(run_time, manual=True) assert_length(manual_runs, 1) self.manual_run.start.assert_called_once_with()
def setup_job(self): self.scheduler = scheduler.ConstantScheduler() mock_graph = mock.Mock(autospec=True) mock_graph.get_action_map.return_value = {} mock_graph.action_map = {} self.job = mock.Mock(autospec=True) self.job.allow_overlap = False self.job.max_runtime = datetime.timedelta(days=1) self.job_scheduler = JobScheduler(job=self.job)
def _make_job_scheduler(self, job_name, enabled=True): scheduler = mock.Mock() run_collection = mock.Mock() node_pool = mock.Mock() new_job = job.Job( job_name, scheduler, run_collection=run_collection, node_pool=node_pool, enabled=enabled, ) return new_job, JobScheduler(new_job)
class TestJobSchedulerGetRunsToSchedule(TestCase): @setup def setup_job(self): self.scheduler = mock.Mock() run_collection = mock.Mock(has_pending=False) node_pool = mock.Mock() self.job = job.Job( "jobname", self.scheduler, run_collection=run_collection, node_pool=node_pool, ) self.job_scheduler = JobScheduler(self.job) self.job.runs.get_pending.return_value = False self.scheduler.queue_overlapping = True def test_get_runs_to_schedule_with_pending(self): self.scheduler.queue_overlapping = False self.job.runs.has_pending = True job_runs = self.job_scheduler.get_runs_to_schedule(None) assert_length(job_runs, 0) def test_get_runs_to_schedule_guess(self): job_runs = list(self.job_scheduler.get_runs_to_schedule(None)) assert self.job.scheduler.next_run_time.call_args_list == [mock.call(None)] assert_length(job_runs, 1) # This should return a JobRun which has the job attached as an observer job_runs[0].attach.assert_any_call(True, self.job) def test_get_runs_to_schedule_given(self): now = datetime.datetime.now() job_runs = list(self.job_scheduler.get_runs_to_schedule(now)) assert self.job.scheduler.next_run_time.call_count == 0 assert_length(job_runs, 1) # This should return a JobRun which has the job attached as an observer job_runs[0].attach.assert_any_call(True, self.job)
def setup_job(self): self.scheduler = mock.Mock(autospec=True) self.scheduler.next_run_time.return_value = 0 mock_run = mock.Mock() mock_run.seconds_until_run_time.return_value = 0 run_collection = mock.Mock( has_pending=False, autospec=True, return_value=[mock_run], ) mock_build_new_run = mock.Mock() run_collection.build_new_run.return_value = mock_build_new_run mock_build_new_run.seconds_until_run_time.return_value = 0 node_pool = mock.Mock() self.job = job.Job( name="jobname", scheduler=self.scheduler, run_collection=run_collection, node_pool=node_pool, ) self.job_scheduler = JobScheduler(self.job) self.original_build_new_runs = self.job.build_new_runs self.job.build_new_runs = mock.Mock(return_value=[mock_run])
class TestJobScheduler(TestCase): @setup def setup_job(self): mock_graph = mock.Mock(autospec=True) mock_graph.get_action_map.return_value = {} mock_graph.action_map = {} self.job = mock.Mock(autospec=True) self.job.allow_overlap = False self.job.max_runtime = datetime.timedelta(days=1) self.job_scheduler = JobScheduler(job=self.job) def test_restore_state_sets_job_runs(self): self.job.enabled = False mock_runs = [mock.Mock(), mock.Mock()] mock_action_runner = mock.Mock() job_state_data = {'runs': mock_runs, 'enabled': True} self.job_scheduler._set_callback = lambda x: x self.job.runs.runs = collections.deque() self.job.runs.get_scheduled.return_value = [mock.Mock()] self.job.get_job_runs_from_state.return_value = mock_runs with mock.patch( 'tron.core.job_scheduler.recovery.launch_recovery_actionruns_for_job_runs', autospec=True, ) as mock_launch_recovery: mock_launch_recovery.return_value = mock.Mock(autospec=True) self.job_scheduler.restore_state(job_state_data, mock_action_runner) assert self.job.runs.runs == collections.deque(mock_runs) mock_launch_recovery.assert_called_once_with( job_runs=mock_runs, master_action_runner=mock_action_runner) calls = [mock.call(mock_runs[i]) for i in range(0, len(mock_runs))] self.job.watch.assert_has_calls(calls) def test_create_and_schedule_runs_specific_time(self): self.job_scheduler.get_runs_to_schedule = mock.Mock( return_value=[mock.Mock()]) self.job_scheduler._set_callback = mock.Mock() self.job_scheduler.create_and_schedule_runs(next_run_time='a_datetime') assert self.job_scheduler.get_runs_to_schedule.call_args_list == [ mock.call('a_datetime') ] def test_create_and_schedule_runs_guess(self): self.job_scheduler.get_runs_to_schedule = mock.Mock( return_value=[mock.Mock()]) self.job_scheduler._set_callback = mock.Mock() self.job_scheduler.create_and_schedule_runs(next_run_time=None) assert self.job_scheduler.get_runs_to_schedule.call_args_list == [ mock.call(None) ] def test_disable(self): self.job_scheduler.disable() assert self.job_scheduler.job.enabled is False self.job_scheduler.job.runs.cancel_pending.assert_called_once() def test_schedule_reconfigured(self): pending_run = mock.Mock() pending_run.run_time = 'a_run_time' self.job.runs.get_pending.return_value = [pending_run] self.job_scheduler.create_and_schedule_runs = mock.Mock() self.job_scheduler.schedule_reconfigured() assert self.job.runs.remove_pending.call_count == 1 assert self.job_scheduler.create_and_schedule_runs.call_args_list == [ mock.call(next_run_time='a_run_time', ) ] def test_schedule(self): self.job.enabled = True last_run = mock.Mock() last_run.run_time = 'a_run_time' self.job.runs.get_newest = mock.Mock(return_value=last_run) self.job_scheduler.create_and_schedule_runs = mock.Mock() self.job_scheduler.schedule() self.job.scheduler.next_run_time.assert_called_once_with('a_run_time') assert self.job_scheduler.create_and_schedule_runs.call_args_list == [ mock.call( next_run_time=self.job.scheduler.next_run_time.return_value), ] def test_run_job(self): self.job_scheduler.schedule = mock.Mock(autospec=True) self.job.scheduler.schedule_on_complete = False self.job.runs.get_active = lambda n: [] job_run = mock.Mock(autospec=True) job_run.is_cancelled = False self.job_scheduler.run_job(job_run) job_run.start.assert_called_once() self.job_scheduler.schedule.assert_called_once() def test_run_job_job_disabled(self): self.job_scheduler.schedule = MagicMock() job_run = MagicMock() self.job.enabled = False self.job_scheduler.run_job(job_run) assert_length(self.job_scheduler.schedule.mock_calls, 0) assert_length(job_run.start.mock_calls, 0) assert_length(job_run.cancel.mock_calls, 1) def test_run_job_cancelled(self): self.job_scheduler.schedule = MagicMock() job_run = MagicMock(is_scheduled=False) self.job_scheduler.run_job(job_run) assert_length(job_run.start.mock_calls, 0) assert_length(self.job_scheduler.schedule.mock_calls, 1) def test_run_job_already_running_queuing(self): self.job_scheduler.schedule = mock.Mock(autospec=True) self.job.runs.get_active = lambda s: [mock.Mock(autospec=True)] job_run = mock.Mock(autospec=True) job_run.is_cancelled = False self.job_scheduler.run_job(job_run) assert not job_run.start.called job_run.queue.assert_called_once() assert not self.job_scheduler.schedule.called def test_run_job_already_running_cancel(self): self.job_scheduler.schedule = mock.Mock(autospec=True) self.job.runs.get_active = lambda s: [mock.Mock(autospec=True)] self.job.queueing = False job_run = mock.Mock(autospec=True) job_run.is_cancelled = False self.job_scheduler.run_job(job_run) assert not job_run.start.called job_run.cancel.assert_called_once() self.job_scheduler.schedule.assert_called_once() def test_run_job_already_running_allow_overlap(self): self.job_scheduler.schedule = mock.Mock() self.job.runs.get_active = lambda s: [mock.Mock()] self.job.allow_overlap = True job_run = MagicMock(is_cancelled=False) self.job_scheduler.run_job(job_run) job_run.start.assert_called_with() def test_run_job_has_starting_queueing(self): self.job_scheduler.schedule = mock.Mock(autospec=True) self.job.runs.get_active = lambda s: [mock.Mock(autospec=True)] job_run = mock.Mock(autospec=True) job_run.is_cancelled = False self.job_scheduler.run_job(job_run) assert not job_run.start.called job_run.queue.assert_called_once() assert not self.job_scheduler.schedule.called def test_run_job_schedule_on_complete(self): self.job_scheduler.schedule = MagicMock() self.job.scheduler.schedule_on_complete = True self.job.runs.get_active = lambda s: [] job_run = MagicMock(is_cancelled=False) self.job_scheduler.run_job(job_run) assert_length(job_run.start.mock_calls, 1) assert_length(self.job_scheduler.schedule.mock_calls, 0)
class TestJobScheduler(TestCase): @setup def setup_job(self): self.scheduler = scheduler.ConstantScheduler() mock_graph = mock.Mock(autospec=True) mock_graph.get_action_map.return_value = {} mock_graph.action_map = {} self.job = mock.Mock(autospec=True) self.job.allow_overlap = False self.job.max_runtime = datetime.timedelta(days=1) self.job_scheduler = JobScheduler(job=self.job) def test_restore_state_sets_job_runs(self): self.job.enabled = False mock_runs = [mock.Mock(), mock.Mock()] mock_action_runner = mock.Mock() job_state_data = {'runs': mock_runs, 'enabled': True} self.job_scheduler._set_callback = lambda x: x self.job.runs.runs = collections.deque() self.job.runs.get_scheduled.return_value = [mock.Mock()] self.job.get_job_runs_from_state.return_value = mock_runs with mock.patch( 'tron.core.job_scheduler.recovery.launch_recovery_actionruns_for_job_runs', autospec=True, ) as mock_launch_recovery: mock_launch_recovery.return_value = mock.Mock(autospec=True) self.job_scheduler.restore_state( job_state_data, mock_action_runner ) assert self.job.runs.runs == collections.deque(mock_runs) mock_launch_recovery.assert_called_once_with( job_runs=mock_runs, master_action_runner=mock_action_runner ) calls = [mock.call(mock_runs[i]) for i in range(0, len(mock_runs))] self.job.watch.assert_has_calls(calls) def test_disable(self): self.job_scheduler.disable() assert self.job_scheduler.job.enabled is False self.job_scheduler.job.runs.cancel_pending.assert_called_once() def test_schedule_reconfigured(self): self.job_scheduler.schedule_reconfigured() self.job.runs.remove_pending.assert_called_once() def test_run_job(self): self.job_scheduler.schedule = mock.Mock(autospec=True) self.scheduler.schedule_on_complete = False self.job.runs.get_active = lambda n: [] job_run = mock.Mock(autospec=True) job_run.is_cancelled = False self.job_scheduler.run_job(job_run) assert job_run.start.called_once() assert self.job_scheduler.schedule.called_once() def test_run_job_job_disabled(self): self.job_scheduler.schedule = MagicMock() job_run = MagicMock() self.job.enabled = False self.job_scheduler.run_job(job_run) assert_length(self.job_scheduler.schedule.mock_calls, 0) assert_length(job_run.start.mock_calls, 0) assert_length(job_run.cancel.mock_calls, 1) def test_run_job_cancelled(self): self.job_scheduler.schedule = MagicMock() job_run = MagicMock(is_scheduled=False) self.job_scheduler.run_job(job_run) assert_length(job_run.start.mock_calls, 0) assert_length(self.job_scheduler.schedule.mock_calls, 1) def test_run_job_already_running_queuing(self): self.job_scheduler.schedule = mock.Mock(autospec=True) self.job.runs.get_active = lambda s: [mock.Mock(autospec=True)] job_run = mock.Mock(autospec=True) job_run.is_cancelled = False self.job_scheduler.run_job(job_run) assert not job_run.start.called job_run.queue.assert_called_once() assert not self.job_scheduler.schedule.called def test_run_job_already_running_cancel(self): self.job_scheduler.schedule = mock.Mock(autospec=True) self.job.runs.get_active = lambda s: [mock.Mock(autospec=True)] self.job.queueing = False job_run = mock.Mock(autospec=True) job_run.is_cancelled = False self.job_scheduler.run_job(job_run) assert not job_run.start.called job_run.cancel.assert_called_once() self.job_scheduler.schedule.assert_called_once() def test_run_job_already_running_allow_overlap(self): self.job_scheduler.schedule = mock.Mock() self.job.runs.get_active = lambda s: [mock.Mock()] self.job.allow_overlap = True job_run = MagicMock(is_cancelled=False) self.job_scheduler.run_job(job_run) job_run.start.assert_called_with() def test_run_job_has_starting_queueing(self): self.job_scheduler.schedule = mock.Mock(autospec=True) self.job.runs.get_active = lambda s: [mock.Mock(autospec=True)] job_run = mock.Mock(autospec=True) job_run.is_cancelled = False self.job_scheduler.run_job(job_run) assert not job_run.start.called job_run.queue.assert_called_once() assert not self.job_scheduler.schedule.called def test_run_job_schedule_on_complete(self): self.job_scheduler.schedule = MagicMock() self.scheduler.schedule_on_complete = True self.job.runs.get_active = lambda s: [] job_run = MagicMock(is_cancelled=False) self.job_scheduler.run_job(job_run) assert_length(job_run.start.mock_calls, 1) assert_length(self.job_scheduler.schedule.mock_calls, 0)
class TestJobSchedulerSchedule(TestCase): @setup def setup_job(self): self.scheduler = mock.Mock(autospec=True) self.scheduler.next_run_time.return_value = 0 mock_run = mock.Mock() mock_run.seconds_until_run_time.return_value = 0 run_collection = mock.Mock( has_pending=False, autospec=True, return_value=[mock_run], ) mock_build_new_run = mock.Mock() run_collection.build_new_run.return_value = mock_build_new_run mock_build_new_run.seconds_until_run_time.return_value = 0 node_pool = mock.Mock() self.job = job.Job( name="jobname", scheduler=self.scheduler, run_collection=run_collection, node_pool=node_pool, ) self.job_scheduler = JobScheduler(self.job) self.original_build_new_runs = self.job.build_new_runs self.job.build_new_runs = mock.Mock(return_value=[mock_run]) @mock.patch('tron.core.job_scheduler.reactor', autospec=True) def test_enable(self, reactor): self.job.enabled = False self.job_scheduler.enable() assert self.job.enabled assert_length(reactor.callLater.mock_calls, 1) @mock.patch('tron.core.job_scheduler.reactor', autospec=True) def test_enable_noop(self, reactor): self.job.enabled = True self.job_scheduler.enable() assert self.job.enabled assert_length(reactor.callLater.mock_calls, 0) @mock.patch('tron.core.job_scheduler.reactor', autospec=True) def test_schedule(self, reactor): self.job.build_new_runs = self.original_build_new_runs self.job_scheduler.schedule() assert reactor.callLater.call_count == 1 # Args passed to callLater call_args = reactor.callLater.mock_calls[0][1] assert_equal(call_args[1], self.job_scheduler.run_job) secs = call_args[0] run = call_args[2] run.seconds_until_run_time.assert_called_with() # Assert that we use the seconds we get from the run to schedule assert_equal(run.seconds_until_run_time.return_value, secs) @mock.patch('tron.core.job_scheduler.reactor', autospec=True) def test_schedule_disabled_job(self, reactor): self.job.enabled = False self.job_scheduler.schedule() assert reactor.callLater.call_count == 0 @mock.patch('tron.core.job_scheduler.reactor', autospec=True) def test_handle_job_events_no_schedule_on_complete(self, reactor): self.job_scheduler.run_job = mock.Mock() self.job.scheduler.schedule_on_complete = False queued_job_run = mock.Mock() self.job.runs.get_first_queued = lambda: queued_job_run self.job_scheduler.handle_job_events(self.job, job.Job.NOTIFY_RUN_DONE) reactor.callLater.assert_any_call( 0, self.job_scheduler.run_job, queued_job_run, run_queued=True, ) def test_handle_job_events_schedule_on_complete(self): self.job_scheduler.schedule = mock.Mock() self.job.scheduler.schedule_on_complete = True self.job_scheduler.handle_job_events(self.job, job.Job.NOTIFY_RUN_DONE) self.job_scheduler.schedule.assert_called_with() def test_handler_unknown_event(self): self.job.runs.get_runs_by_state = mock.Mock() self.job_scheduler.handler(self.job, 'some_other_event') self.job.runs.get_runs_by_state.assert_not_called() def test_handler_no_queued(self): self.job_scheduler.run_job = mock.Mock() def get_queued(state): if state == ActionRun.QUEUED: return [] self.job.runs.get_runs_by_state = get_queued self.job_scheduler.handler(self.job, job.Job.NOTIFY_RUN_DONE) self.job_scheduler.run_job.assert_not_called() @mock.patch('tron.core.job_scheduler.reactor', autospec=True) def test_run_queue_schedule(self, reactor): with mock.patch.object( self.job_scheduler, 'schedule', ) as mock_schedule: self.job_scheduler.run_job = mock.Mock() self.job.scheduler.schedule_on_complete = False queued_job_run = mock.Mock() self.job.runs.get_first_queued = lambda: queued_job_run self.job_scheduler.run_queue_schedule() reactor.callLater.assert_called_once_with( 0, self.job_scheduler.run_job, queued_job_run, run_queued=True, ) mock_schedule.assert_called_once_with()