Example #1
0
class Simulator(object):
    def __init__(self, jobs, num_processors, scheduler):
        self.event_queue = EventQueue()
        self.machine = ValidatingMachine(num_processors=num_processors, event_queue=self.event_queue)
        self.scheduler = scheduler

        self.event_queue.add_handler(JobSubmissionEvent, self.handle_submission_event)
        self.event_queue.add_handler(JobTerminationEvent, self.handle_termination_event)

        for job in jobs:
            self.event_queue.add_event(
                    JobSubmissionEvent(timestamp = job.submit_time, job = job)
                )

    def run(self):
        while not self.event_queue.is_empty:
            self.event_queue.advance()

    def handle_submission_event(self, event):
        assert isinstance(event, JobSubmissionEvent)
        newEvents = self.scheduler.handleSubmissionOfJobEvent(event.job, event.timestamp)
        for event in newEvents:
            self.event_queue.add_event(event)

    def handle_termination_event(self, event):
        assert isinstance(event, JobTerminationEvent)
        newEvents = self.scheduler.handleTerminationOfJobEvent(event.job, event.timestamp)
        for event in newEvents:
            self.event_queue.add_event(event)
            
    def handle_prediction_is_over_event(self, event):
        assert isinstance(event, JobPredictionIsOverEvent)
        newEvents = self.scheduler.handlePredictionIsOverEvent(event.job, event.timestamp)
        for event in newEvents:
            self.event_queue.add_event(event)
class Simulator(object):
    def __init__(self, jobs, num_processors, scheduler):
        self.event_queue = EventQueue()
        self.machine = ValidatingMachine(num_processors=num_processors,
                                         event_queue=self.event_queue)
        self.scheduler = scheduler

        self.event_queue.add_handler(JobSubmissionEvent,
                                     self.handle_submission_event)
        self.event_queue.add_handler(JobTerminationEvent,
                                     self.handle_termination_event)

        for job in jobs:
            self.event_queue.add_event(
                JobSubmissionEvent(timestamp=job.submit_time, job=job))

    def run(self):
        while not self.event_queue.is_empty:
            self.event_queue.advance()

    def handle_submission_event(self, event):
        assert isinstance(event, JobSubmissionEvent)
        newEvents = self.scheduler.handleSubmissionOfJobEvent(
            event.job, event.timestamp)
        for event in newEvents:
            self.event_queue.add_event(event)

    def handle_termination_event(self, event):
        assert isinstance(event, JobTerminationEvent)
        newEvents = self.scheduler.handleTerminationOfJobEvent(
            event.job, event.timestamp)
        for event in newEvents:
            self.event_queue.add_event(event)

    def handle_prediction_is_over_event(self, event):
        assert isinstance(event, JobPredictionIsOverEvent)
        newEvents = self.scheduler.handlePredictionIsOverEvent(
            event.job, event.timestamp)
        for event in newEvents:
            self.event_queue.add_event(event)
class test_EventQueue(TestCase):
    def setUp(self):
        self.queue = EventQueue()
        self.event = prototype.JobEvent(timestamp=0, job=None)
        self.events = [
                prototype.JobEvent(timestamp=i, job=None)
                for i in xrange(10)
            ]

        self.handler = _create_handler()

    def tearDown(self):
        del self.queue, self.event, self.events, self.handler

    def test_len_empty(self):
        self.assertEqual( 0, len(self.queue) )

    def test_len_nonempty(self):
        for event in self.events:
            self.queue.add_event(event)
        self.assertEqual( len(self.events), len(self.queue) )

    def test_add_event_sanity(self):
        self.queue.add_event( self.event )

    def test_add_event_single_event(self):
        self.queue.add_event(self.event)
        self.assertEqual( [self.event], self.queue.sorted_events )

    def test_add_same_event_fails(self):
        self.queue.add_event(self.event)
        self.assertRaises(Exception, self.queue.add_event, self.event)

    def test_add_event_simple(self):
        for event in self.events:
            self.queue.add_event(event)
        self.assertEqual( self.events, list(self.queue.sorted_events) )

    def test_add_event_sorting(self):
        random_events = _gen_random_timestamp_events()
        for event in random_events:
            self.queue.add_event(event)
        self.assertEqual( sorted(random_events), self.queue.sorted_events )

    def test_remove_event_fails_on_empty(self):
        self.assertRaises(Exception, self.queue.remove_event, self.event)

    def test_remove_event_fails_on_missing_event(self):
        event1 = prototype.JobEvent(0, 0)
        event2 = prototype.JobEvent(0, 1)
        assert event1 != event2 # different events
        self.queue.add_event(event1)
        self.assertRaises(Exception, self.queue.remove_event, event2)

    def test_remove_event_succeeds(self):
        self.queue.add_event(self.event)
        self.queue.remove_event(self.event)
        self.failUnless( self.queue.is_empty )

    def test_pop_one_job(self):
        self.queue.add_event( self.event )
        assert self.queue.pop() is self.event

    def test_pop_many_jobs(self):
        for event in self.events:
            self.queue.add_event(event)
        for event in self.events:
            assert self.queue.pop() is event

    def test_pop_empty(self):
        self.assertRaises(AssertionError, self.queue.pop)

    def test_empty_true(self):
        self.failUnless( self.queue.is_empty )

    def test_empty_false(self):
        self.queue.add_event( self.event )
        self.failIf( self.queue.is_empty )

    def test_add_handler_sanity(self):
        self.queue.add_handler(prototype.JobEvent, self.handler)
        self.queue.add_event(self.event)
        self.failIf( self.handler.called )

    def test_get_event_handlers_empty(self):
        self.assertEqual(
            0, len(self.queue._get_event_handlers( prototype.JobEvent ))
        )

    def test_get_event_handlers_nonempty(self):
        self.queue.add_handler(prototype.JobEvent, self.handler)
        self.assertEqual(
            1, len(self.queue._get_event_handlers( prototype.JobEvent ))
        )

    def test_advance_empty_queue(self):
        self.assertRaises(AssertionError, self.queue.advance)

    def test_advance_eats_event(self):
        self._add_event_and_advance(self.event)
        self.failUnless(self.queue.is_empty)

    def test_add_event_earlier_event_after_later_advance(self):
        # after handling an event with a later timestamp, adding an event with
        # an older timestamp should fail
        self._add_event_and_advance(prototype.JobEvent(timestamp=2, job="x"))
        self.assertRaises(Exception, self.queue.add_event, prototype.JobEvent(timestamp=1, job="x"))

    def test_add_event_same_timestamp_after_advance(self):
        # same timestamp should succeed even after an event has been handled
        self._add_event_and_advance(prototype.JobEvent(timestamp=2, job="x"))
        self.queue.add_event(prototype.JobEvent(timestamp=2, job="y"))

    def test_advance_one_handler_handles(self):
        self.queue.add_handler(prototype.JobEvent, self.handler)
        self._add_event_and_advance(self.event)

        self.failUnless( self.handler.called )

    def test_advance_one_handler_doesnt_handle(self):
        self.queue.add_handler(prototype.JobStartEvent, self.handler)
        self._add_event_and_advance(self.event) # JobEvent, different type

        self.failIf( self.handler.called )

    def test_advance_many_handlers(self):
        matching_handlers = [ _create_handler() for i in xrange(5) ]
        nonmatching_handlers = [ _create_handler() for i in xrange(5) ]

        # register handlers that should run
        for handler in matching_handlers:
            self.queue.add_handler(prototype.JobEvent, handler)

        # register handlers that shouldn't run with a different event type
        for handler in nonmatching_handlers:
            self.queue.add_handler(prototype.JobStartEvent, handler)

        self._add_event_and_advance(self.event)

        for handler in matching_handlers:
            self.failUnless( handler.called )

        for handler in nonmatching_handlers:
            self.failIf( handler.called )

    def test_sometimes_relevant_handler(self):
        self.queue.add_handler(prototype.JobEvent, self.handler)
        self._add_event_and_advance(prototype.JobEvent(timestamp=0, job="x"))
        self.failUnless(self.handler.called)
        self.handler.called = False
        self._add_event_and_advance(prototype.JobStartEvent(timestamp=1, job="x"))
        self.failIf(self.handler.called)
        self._add_event_and_advance(prototype.JobEvent(timestamp=2, job="x"))
        self.failUnless(self.handler.called)

    def _add_event_and_advance(self, event):
        self.queue.add_event(event)
        self.queue.advance()
class test_EventQueue(TestCase):
    def setUp(self):
        self.queue = EventQueue()
        self.event = prototype.JobEvent(timestamp=0, job=None)
        self.events = [
            prototype.JobEvent(timestamp=i, job=None) for i in xrange(10)
        ]

        self.handler = _create_handler()

    def tearDown(self):
        del self.queue, self.event, self.events, self.handler

    def test_len_empty(self):
        self.assertEqual(0, len(self.queue))

    def test_len_nonempty(self):
        for event in self.events:
            self.queue.add_event(event)
        self.assertEqual(len(self.events), len(self.queue))

    def test_add_event_sanity(self):
        self.queue.add_event(self.event)

    def test_add_event_single_event(self):
        self.queue.add_event(self.event)
        self.assertEqual([self.event], self.queue.sorted_events)

    def test_add_same_event_fails(self):
        self.queue.add_event(self.event)
        self.assertRaises(Exception, self.queue.add_event, self.event)

    def test_add_event_simple(self):
        for event in self.events:
            self.queue.add_event(event)
        self.assertEqual(self.events, list(self.queue.sorted_events))

    def test_add_event_sorting(self):
        random_events = _gen_random_timestamp_events()
        for event in random_events:
            self.queue.add_event(event)
        self.assertEqual(sorted(random_events), self.queue.sorted_events)

    def test_remove_event_fails_on_empty(self):
        self.assertRaises(Exception, self.queue.remove_event, self.event)

    def test_remove_event_fails_on_missing_event(self):
        event1 = prototype.JobEvent(0, 0)
        event2 = prototype.JobEvent(0, 1)
        assert event1 != event2  # different events
        self.queue.add_event(event1)
        self.assertRaises(Exception, self.queue.remove_event, event2)

    def test_remove_event_succeeds(self):
        self.queue.add_event(self.event)
        self.queue.remove_event(self.event)
        self.failUnless(self.queue.is_empty)

    def test_pop_one_job(self):
        self.queue.add_event(self.event)
        assert self.queue.pop() is self.event

    def test_pop_many_jobs(self):
        for event in self.events:
            self.queue.add_event(event)
        for event in self.events:
            assert self.queue.pop() is event

    def test_pop_empty(self):
        self.assertRaises(AssertionError, self.queue.pop)

    def test_empty_true(self):
        self.failUnless(self.queue.is_empty)

    def test_empty_false(self):
        self.queue.add_event(self.event)
        self.failIf(self.queue.is_empty)

    def test_add_handler_sanity(self):
        self.queue.add_handler(prototype.JobEvent, self.handler)
        self.queue.add_event(self.event)
        self.failIf(self.handler.called)

    def test_get_event_handlers_empty(self):
        self.assertEqual(
            0, len(self.queue._get_event_handlers(prototype.JobEvent)))

    def test_get_event_handlers_nonempty(self):
        self.queue.add_handler(prototype.JobEvent, self.handler)
        self.assertEqual(
            1, len(self.queue._get_event_handlers(prototype.JobEvent)))

    def test_advance_empty_queue(self):
        self.assertRaises(AssertionError, self.queue.advance)

    def test_advance_eats_event(self):
        self._add_event_and_advance(self.event)
        self.failUnless(self.queue.is_empty)

    def test_add_event_earlier_event_after_later_advance(self):
        # after handling an event with a later timestamp, adding an event with
        # an older timestamp should fail
        self._add_event_and_advance(prototype.JobEvent(timestamp=2, job="x"))
        self.assertRaises(Exception, self.queue.add_event,
                          prototype.JobEvent(timestamp=1, job="x"))

    def test_add_event_same_timestamp_after_advance(self):
        # same timestamp should succeed even after an event has been handled
        self._add_event_and_advance(prototype.JobEvent(timestamp=2, job="x"))
        self.queue.add_event(prototype.JobEvent(timestamp=2, job="y"))

    def test_advance_one_handler_handles(self):
        self.queue.add_handler(prototype.JobEvent, self.handler)
        self._add_event_and_advance(self.event)

        self.failUnless(self.handler.called)

    def test_advance_one_handler_doesnt_handle(self):
        self.queue.add_handler(prototype.JobStartEvent, self.handler)
        self._add_event_and_advance(self.event)  # JobEvent, different type

        self.failIf(self.handler.called)

    def test_advance_many_handlers(self):
        matching_handlers = [_create_handler() for i in xrange(5)]
        nonmatching_handlers = [_create_handler() for i in xrange(5)]

        # register handlers that should run
        for handler in matching_handlers:
            self.queue.add_handler(prototype.JobEvent, handler)

        # register handlers that shouldn't run with a different event type
        for handler in nonmatching_handlers:
            self.queue.add_handler(prototype.JobStartEvent, handler)

        self._add_event_and_advance(self.event)

        for handler in matching_handlers:
            self.failUnless(handler.called)

        for handler in nonmatching_handlers:
            self.failIf(handler.called)

    def test_sometimes_relevant_handler(self):
        self.queue.add_handler(prototype.JobEvent, self.handler)
        self._add_event_and_advance(prototype.JobEvent(timestamp=0, job="x"))
        self.failUnless(self.handler.called)
        self.handler.called = False
        self._add_event_and_advance(
            prototype.JobStartEvent(timestamp=1, job="x"))
        self.failIf(self.handler.called)
        self._add_event_and_advance(prototype.JobEvent(timestamp=2, job="x"))
        self.failUnless(self.handler.called)

    def _add_event_and_advance(self, event):
        self.queue.add_event(event)
        self.queue.advance()