def test_kill_job_must_sync_with_batsim(self, mocker): mocker.patch("batsim_py.simulator.KillJobBatsimRequest") s = SimulatorHandler() s.start("p", "w") e = BatsimEventAPI.get_job_submitted(res=1) msg = BatsimMessage(150, [JobSubmittedBatsimEvent(150, e['data'])]) mocker.patch.object(protocol.NetworkHandler, 'recv', return_value=msg) mocker.patch.object(batsim_py.jobs.Job, '_terminate') mocker.patch.object(batsim_py.resources.Host, '_release') s.proceed_time() mocker.patch("batsim_py.simulator.BatsimMessage") mocker.patch.object(batsim_py.jobs.Job, 'is_running', return_value=True) mocker.patch.object( protocol.NetworkHandler, 'recv', return_value=BatsimMessage(s.current_time, [])) job_id = s.jobs[0].id s.kill_job(job_id) assert s.jobs batsim_py.jobs.Job._terminate.assert_not_called() batsim_py.resources.Host._release.assert_not_called() simulator.KillJobBatsimRequest.assert_called_once_with( # type: ignore 150, job_id) assert simulator.NetworkHandler.send.call_count == 2
def test_agenda_with_multiple_jobs_in_one_host(self, mocker): s = SimulatorHandler() s.start("p", "w") e1 = BatsimEventAPI.get_job_submitted( job_id="w!0", res=1, walltime=100) e1 = JobSubmittedBatsimEvent(0, e1['data']) e2 = BatsimEventAPI.get_job_submitted( job_id="w!1", res=1, walltime=200) e2 = JobSubmittedBatsimEvent(0, e2['data']) msg = BatsimMessage(0, [e1, e2]) mocker.patch.object(protocol.NetworkHandler, 'recv', return_value=msg) s.proceed_time() s.allocate(e1.job.id, [0]) s.allocate(e2.job.id, [0]) msg = BatsimMessage(10, [RequestedCallBatsimEvent(10)]) mocker.patch.object(protocol.NetworkHandler, 'recv', return_value=msg) s.proceed_time() agenda = list(s.agenda) assert s.current_time == 10 assert agenda[0].host.id == 0 and agenda[0].release_time == e2.job.walltime-10 assert agenda[1].host.id == 1 and agenda[1].release_time == 0
def test_on_batsim_job_completed_must_terminate_job_and_release_resources(self, mocker): s = SimulatorHandler() s.start("p", "w") # Setup Allocate profile = BatsimJobProfileAPI.get_data_staging("a", "b", 10) e = BatsimEventAPI.get_job_submitted(res=1, profile=profile) job_id, job_alloc = e['data']['job_id'], [0] msg = BatsimMessage(150, [JobSubmittedBatsimEvent(150, e['data'])]) mocker.patch.object(protocol.NetworkHandler, 'recv', return_value=msg) storage = list(s.platform.storages)[0] s.proceed_time() s.allocate(job_id, job_alloc, {"a": storage.id, "b": storage.id}) # Setup Completed mocker.patch.object(batsim_py.jobs.Job, '_terminate') mocker.patch.object(batsim_py.resources.Host, '_release') mocker.patch.object(batsim_py.resources.Storage, '_release') e = BatsimEventAPI.get_job_completted(100, job_id, alloc=job_alloc) msg = BatsimMessage(150, [JobCompletedBatsimEvent(150, e['data'])]) mocker.patch.object(protocol.NetworkHandler, 'recv', return_value=msg) s.proceed_time() batsim_py.jobs.Job._terminate.assert_called_once() batsim_py.resources.Host._release.assert_called_once_with(job_id) batsim_py.resources.Storage._release.assert_called_once_with(job_id) assert not s.jobs
def test_on_batsim_job_completed_must_dispatch_event(self, mocker): def foo_j(j: Job): self.__j_called, self.__j_id = True, j.id def foo_h(h: Host): self.__h_called, self.__h_id = True, h.id self.__j_called = self.__h_called = False self.__j_id = self.__h_id = -1 s = SimulatorHandler() s.start("p", "w") s.subscribe(HostEvent.STATE_CHANGED, foo_h) s.subscribe(JobEvent.COMPLETED, foo_j) # Setup Allocate e = BatsimEventAPI.get_job_submitted(res=1) job_id, job_alloc = e['data']['job_id'], [0] msg = BatsimMessage(150, [JobSubmittedBatsimEvent(150, e['data'])]) mocker.patch.object(protocol.NetworkHandler, 'recv', return_value=msg) s.proceed_time() s.allocate(job_id, job_alloc) # Setup Completed mocker.patch.object(batsim_py.jobs.Job, '_terminate') e = BatsimEventAPI.get_job_completted(100, job_id, alloc=job_alloc) msg = BatsimMessage(150, [JobCompletedBatsimEvent(150, e['data'])]) mocker.patch.object(protocol.NetworkHandler, 'recv', return_value=msg) s.proceed_time() assert self.__j_called and self.__j_id == job_id assert self.__h_called and self.__h_id == job_alloc[0]
def test_send_and_recv(self, mocker): msg = BatsimMessage(0) mocker.patch.object(protocol.zmq.Socket, 'recv_json', return_value=msg) p = NetworkHandler("tcp://localhost:28000") p.bind() m = p.send_and_recv(msg) assert m == msg protocol.zmq.Socket.recv_json.assert_called_once() protocol.zmq.Socket.send_json.assert_called_once_with(msg.to_json())
def test_to_json_must_include_requests_only(self): events = [ RequestedCallBatsimEvent(15), KillJobBatsimRequest(10, "w!1", "w!2") ] m = BatsimMessage(15, events) events_json = [ BatsimRequestAPI.get_kill_job(10, ["w!1", "w!2"]), ] m_jsn = BatsimAPI.get_message(15, events_json) assert m.to_json() == m_jsn
def test_proceed_time_with_is_submitter_finished_and_sim_time_must_allow_callback(self, mocker): s = SimulatorHandler() s.start("p", "w", simulation_time=100) e = BatsimEventAPI.get_notify_no_more_static_job_to_submit(10) msg = BatsimMessage(10, [NotifyBatsimEvent(10, e['data'])]) mocker.patch.object(protocol.NetworkHandler, 'recv', return_value=msg) s.proceed_time() assert s.is_submitter_finished msg = BatsimMessage(50, [SimulationEndsBatsimEvent(50)]) mocker.patch.object(protocol.NetworkHandler, 'recv', return_value=msg) mocker.patch.object(SimulatorHandler, 'set_callback') s.proceed_time(50) SimulatorHandler.set_callback.assert_called_once()
def test_invalid_event_timestamp_must_raise(self): events = [ RequestedCallBatsimEvent(15), KillJobBatsimRequest(10, "w!1", "w!2") ] with pytest.raises(ValueError): BatsimMessage(11, events)
def test_allocate_start_must_dispatch_events(self, mocker): def foo_j(j: Job): self.__j_called, self.__j_id = True, j.id def foo_h(h: Host): self.__h_called, self.__h_id = True, h.id self.__j_called = self.__h_called = False self.__j_id = self.__h_id = -1 s = SimulatorHandler() s.start("p", "w") s.subscribe(JobEvent.STARTED, foo_j) s.subscribe(HostEvent.STATE_CHANGED, foo_h) e = BatsimEventAPI.get_job_submitted(res=1) msg = BatsimMessage(150, [JobSubmittedBatsimEvent(150, e['data'])]) mocker.patch.object(protocol.NetworkHandler, 'recv', return_value=msg) s.proceed_time() assert s.queue job = s.jobs[0] s.allocate(job.id, [0]) assert self.__j_called and self.__j_id == job.id assert self.__h_called and self.__h_id == 0
def test_proceed_time_with_is_submitter_finished_and_external_events_to_happen_must_allow_callback(self, mocker): s = SimulatorHandler() s.start("p", "w", external_events=".txt") e = BatsimEventAPI.get_notify_no_more_static_job_to_submit(10) msg = BatsimMessage(10, [NotifyBatsimEvent(10, e['data'])]) mocker.patch.object(protocol.NetworkHandler, 'recv', return_value=msg) s.proceed_time() assert s.is_submitter_finished msg = BatsimMessage(50, [SimulationEndsBatsimEvent(50)]) mocker.patch.object(protocol.NetworkHandler, 'recv', return_value=msg) mocker.patch.object(SimulatorHandler, 'set_callback') s.proceed_time(100) assert not s.is_running assert s.current_time == 50 SimulatorHandler.set_callback.assert_called()
def test_current_time_must_truncate(self, mocker): s = SimulatorHandler() s.start("p", "w") e = BatsimEventAPI.get_notify_no_more_static_job_to_submit(10) msg = BatsimMessage(10.00199, [NotifyBatsimEvent(10.00199, e['data'])]) mocker.patch.object(protocol.NetworkHandler, 'recv', return_value=msg) s.proceed_time() assert s.current_time == 10
def test_on_batsim_simulation_ends_must_ack(self, mocker): s = SimulatorHandler() s.start("p", "w") msg = BatsimMessage(100, [SimulationEndsBatsimEvent(100)]) mocker.patch.object(protocol.NetworkHandler, 'recv', return_value=msg) s.proceed_time() assert not s.is_running assert protocol.NetworkHandler.send.call_count == 2
def test_message(self): events = [ RequestedCallBatsimEvent(15), KillJobBatsimRequest(10, "w!1", "w!2") ] m = BatsimMessage(15, events) events[1], events[0] = events[0], events[1] # sort assert m.now == 15 assert m.events == events
def test_proceed_time_with_time_must_setup_call_request(self, mocker): mocker.patch("batsim_py.simulator.SimulatorHandler.set_callback") s = SimulatorHandler() s.start("p", "w") msg = BatsimMessage(50, [SimulationEndsBatsimEvent(50)]) mocker.patch.object(protocol.NetworkHandler, 'recv', return_value=msg) s.proceed_time(50) simulator.SimulatorHandler.set_callback.assert_called_once_with( 50, mocker.ANY)
def test_proceed_time_without_time_must_go_to_next_event(self, mocker): s = SimulatorHandler() s.start("p", "w") e = BatsimEventAPI.get_job_submitted() msg = BatsimMessage(150, [JobSubmittedBatsimEvent(150, e['data'])]) mocker.patch.object(protocol.NetworkHandler, 'recv', return_value=msg) mocker.patch.object(SimulatorHandler, 'set_callback') s.proceed_time() SimulatorHandler.set_callback.assert_not_called() assert s.current_time == 150
def test_agenda_with_job_not_running(self, mocker): s = SimulatorHandler() s.start("p", "w") s.switch_off([h.id for h in s.platform.hosts]) e = BatsimEventAPI.get_job_submitted(res=1, walltime=100) e = JobSubmittedBatsimEvent(0, e['data']) msg = BatsimMessage(0, [e]) mocker.patch.object(protocol.NetworkHandler, 'recv', return_value=msg) s.proceed_time() s.allocate(e.job.id, [0]) msg = BatsimMessage(10, [RequestedCallBatsimEvent(10)]) mocker.patch.object(protocol.NetworkHandler, 'recv', return_value=msg) s.proceed_time() agenda = list(s.agenda) assert s.current_time == 10 assert agenda[0].host.id == 0 and agenda[0].release_time == e.job.walltime
def test_on_batsim_job_submitted_must_append_in_queue(self, mocker): s = SimulatorHandler() s.start("p", "w") # Setup Allocate e = BatsimEventAPI.get_job_submitted(res=1) job_id, job_alloc = e['data']['job_id'], [0] msg = BatsimMessage(150, [JobSubmittedBatsimEvent(150, e['data'])]) mocker.patch.object(protocol.NetworkHandler, 'recv', return_value=msg) s.proceed_time() assert s.queue and s.queue[0].id == job_id
def test_agenda_with_job_without_walltime(self, mocker): s = SimulatorHandler() s.start("p", "w") e = BatsimEventAPI.get_job_submitted(res=1) e = JobSubmittedBatsimEvent(0, e['data']) msg = BatsimMessage(0, [e]) mocker.patch.object(protocol.NetworkHandler, 'recv', return_value=msg) s.proceed_time() s.allocate(e.job.id, [0]) msg = BatsimMessage(10, [RequestedCallBatsimEvent(10)]) mocker.patch.object(protocol.NetworkHandler, 'recv', return_value=msg) s.proceed_time() agenda = list(s.agenda) assert s.current_time == 10 assert agenda[0].host.id == 0 and agenda[0].release_time == np.inf assert agenda[1].host.id == 1 and agenda[1].release_time == 0
def test_callback_invalid_time_must_raise(self, mocker): def foo(p): pass s = SimulatorHandler() s.start("p", "w") msg = BatsimMessage(50, [RequestedCallBatsimEvent(50)]) mocker.patch.object(protocol.NetworkHandler, 'recv', return_value=msg) s.proceed_time(50) with pytest.raises(ValueError) as excinfo: s.set_callback(50, foo) assert "at" in str(excinfo.value)
def test_allocate_invalid_host_must_raise(self, mocker): s = SimulatorHandler() s.start("p", "w") e = BatsimEventAPI.get_job_submitted(res=1) msg = BatsimMessage(150, [JobSubmittedBatsimEvent(150, e['data'])]) mocker.patch.object(protocol.NetworkHandler, 'recv', return_value=msg) s.proceed_time() with pytest.raises(LookupError) as excinfo: s.allocate(e['data']['job_id'], [3]) assert "resources" in str(excinfo.value)
def test_on_batsim_notify_machine_unavailable(self, mocker): s = SimulatorHandler() s.start("p", "w") # Setup e = BatsimEventAPI.get_notify_machine_unavailable(10, [0, 1, 2]) msg = BatsimMessage(150, [NotifyBatsimEvent(150, e['data'])]) mocker.patch.object(protocol.NetworkHandler, 'recv', return_value=msg) s.proceed_time() assert s.platform.get(0).is_unavailable assert s.platform.get(1).is_unavailable assert s.platform.get(2).is_unavailable
def test_kill_job_not_running_must_raise(self, mocker): mocker.patch("batsim_py.simulator.KillJobBatsimRequest") s = SimulatorHandler() s.start("p", "w") e = BatsimEventAPI.get_job_submitted(res=1) msg = BatsimMessage(150, [JobSubmittedBatsimEvent(150, e['data'])]) mocker.patch.object(protocol.NetworkHandler, 'recv', return_value=msg) s.proceed_time() with pytest.raises(RuntimeError) as excinfo: s.kill_job(s.jobs[0].id) assert "not running" in str(excinfo.value)
def test_proceed_time_with_simulation_time_must_force_close(self, mocker): s = SimulatorHandler() s.start("p2", "w2", simulation_time=10) # setup e = BatsimEventAPI.get_job_submitted(res=1) events = [ JobSubmittedBatsimEvent(5, e['data']), RequestedCallBatsimEvent(10) ] msg = BatsimMessage(10, events) mocker.patch.object(protocol.NetworkHandler, 'recv', return_value=msg) s.proceed_time() assert not s.is_running
def test_on_batsim_job_submitted_must_dispatch_event(self, mocker): def foo(j: Job): self.__called, self.__j_id = True, j.id self.__called, self.__j_id = False, -1 s = SimulatorHandler() s.start("p", "w") s.subscribe(JobEvent.SUBMITTED, foo) # Setup Allocate e = BatsimEventAPI.get_job_submitted(res=1) job_id = e['data']['job_id'] msg = BatsimMessage(150, [JobSubmittedBatsimEvent(150, e['data'])]) mocker.patch.object(protocol.NetworkHandler, 'recv', return_value=msg) s.proceed_time() assert self.__called and self.__j_id == job_id
def test_queue(self, mocker): s = SimulatorHandler() s.start("p", "w") e = [ JobSubmittedBatsimEvent( 0, BatsimEventAPI.get_job_submitted(job_id="w!0")['data']), JobSubmittedBatsimEvent( 0, BatsimEventAPI.get_job_submitted(job_id="w!1")['data']), ] msg = BatsimMessage(150, e) mocker.patch.object(protocol.NetworkHandler, 'recv', return_value=msg) s.proceed_time() assert s.queue and len(s.queue) == 2 s.allocate("w!1", [0]) assert s.queue and len(s.queue) == 1
def test_reject_job(self, mocker): mocker.patch("batsim_py.simulator.RejectJobBatsimRequest") s = SimulatorHandler() s.start("p", "w") e = BatsimEventAPI.get_job_submitted(res=1) msg = BatsimMessage(150, [JobSubmittedBatsimEvent(150, e['data'])]) mocker.patch.object(protocol.NetworkHandler, 'recv', return_value=msg) mocker.patch.object(batsim_py.jobs.Job, '_reject') s.proceed_time() job_id = e['data']['job_id'] s.reject_job(job_id) assert not s.jobs batsim_py.jobs.Job._reject.assert_called_once() simulator.RejectJobBatsimRequest.assert_called_once_with( # type: ignore 150, job_id)
def test_on_batsim_notify_machine_unavailable_must_dispatch_host_event(self, mocker): def foo(h: Host): self.nb_called += 1 assert h.is_unavailable self.nb_called = 0 s = SimulatorHandler() s.start("p", "w") s.subscribe(HostEvent.STATE_CHANGED, foo) # Setup e = BatsimEventAPI.get_notify_machine_unavailable(10, [0, 1, 2]) msg = BatsimMessage(10, [NotifyBatsimEvent(10, e['data'])]) mocker.patch.object(protocol.NetworkHandler, 'recv', return_value=msg) s.proceed_time() assert self.nb_called == 2
def test_allocate_with_switching_off_host_must_not_start_job(self, mocker): mocker.patch("batsim_py.protocol.ExecuteJobBatsimRequest") s = SimulatorHandler() s.start("p", "w") # setup host = s.platform.get_host(0) host._switch_off() e = BatsimEventAPI.get_job_submitted(res=1) msg = BatsimMessage(150, [JobSubmittedBatsimEvent(150, e['data'])]) mocker.patch.object(protocol.NetworkHandler, 'recv', return_value=msg) s.proceed_time() s.allocate(e['data']['job_id'], [0]) assert s.jobs[0].is_runnable assert host.is_switching_off protocol.ExecuteJobBatsimRequest.assert_not_called() # type: ignore
def test_allocate_must_dispatch_job_event(self, mocker): def foo(j: Job): self.__called = True self.__job_id = j.id self.__called, self.__job_id = False, -1 s = SimulatorHandler() s.start("p", "w") e = BatsimEventAPI.get_job_submitted(res=1) msg = BatsimMessage(150, [JobSubmittedBatsimEvent(150, e['data'])]) mocker.patch.object(protocol.NetworkHandler, 'recv', return_value=msg) s.proceed_time() s.subscribe(JobEvent.ALLOCATED, foo) job = s.jobs[0] s.allocate(job.id, [0]) assert self.__called and self.__job_id == job.id
def test_allocate_must_start_job_and_host(self, mocker): mocker.patch("batsim_py.simulator.ExecuteJobBatsimRequest") s = SimulatorHandler() s.start("p", "w") e = BatsimEventAPI.get_job_submitted(res=1) msg = BatsimMessage(150, [JobSubmittedBatsimEvent(150, e['data'])]) mocker.patch.object(protocol.NetworkHandler, 'recv', return_value=msg) s.proceed_time() assert s.queue job = s.jobs[0] s.allocate(job.id, [0]) assert job.is_running assert s.platform.get_host(0).is_computing simulator.ExecuteJobBatsimRequest.assert_called_once_with( # type: ignore 150, job.id, job.allocation, job.storage_mapping)