diff --git a/mycroft/skills/event_scheduler.py b/mycroft/skills/event_scheduler.py index 18b23f49b3..019d47448f 100644 --- a/mycroft/skills/event_scheduler.py +++ b/mycroft/skills/event_scheduler.py @@ -51,11 +51,12 @@ class EventScheduler(Thread): Load json data with active events from json file. """ if isfile(self.schedule_file): + json_data = {} with open(self.schedule_file) as f: try: json_data = json.load(f) except Exception as e: - LOG.error(e) + LOG.error(e.message) current_time = time.time() for key in json_data: event_list = json_data[key] @@ -97,31 +98,34 @@ class EventScheduler(Thread): def run(self): while self.isRunning: - # Remove events - self.remove_events() - # Fetch newly scheduled events - self.fetch_new_events() - # Update events - self.update_events() - - # Check all events - for event in self.events: - current_time = time.time() - e = self.events[event] - # Get scheduled times that has passed - passed = [(t, r, d) for (t, r, d) in e if t <= current_time] - # and remaining times that we're still waiting for - remaining = [(t, r, d) for t, r, d in e if t > current_time] - # Trigger registered methods - for sched_time, repeat, data in passed: - self.emitter.emit(Message(event, data)) - # if this is a repeated event add a new trigger time - if repeat: - remaining.append((sched_time + repeat, repeat, data)) - # update list of events - self.events[event] = remaining + self.check_state() time.sleep(0.5) + def check_state(self): + # Remove events + self.remove_events() + # Fetch newly scheduled events + self.fetch_new_events() + # Update events + self.update_events() + + # Check all events + for event in self.events: + current_time = time.time() + e = self.events[event] + # Get scheduled times that has passed + passed = [(t, r, d) for (t, r, d) in e if t <= current_time] + # and remaining times that we're still waiting for + remaining = [(t, r, d) for t, r, d in e if t > current_time] + # Trigger registered methods + for sched_time, repeat, data in passed: + self.emitter.emit(Message(event, data)) + # if this is a repeated event add a new trigger time + if repeat: + remaining.append((sched_time + repeat, repeat, data)) + # update list of events + self.events[event] = remaining + def schedule_event(self, event, sched_time, repeat=None, data=None): """ Send event to thread using thread safe queue. """ data = data or {} diff --git a/test/unittests/skills/test_event_scheduler.py b/test/unittests/skills/test_event_scheduler.py new file mode 100644 index 0000000000..3e4706265c --- /dev/null +++ b/test/unittests/skills/test_event_scheduler.py @@ -0,0 +1,70 @@ +import unittest +import mock +import time + +from mycroft.skills.event_scheduler import EventScheduler + +""" + Test cases regarding the event scheduler. +""" + + +class TestEventScheduler(unittest.TestCase): + @mock.patch('threading.Thread') + @mock.patch('json.dump') + @mock.patch('mycroft.skills.event_scheduler.open') + def test_create(self, mock_open, mock_json_dump, mock_thread): + """ + Test creating and shutting down event_scheduler. + """ + mock_open.return_value = mock.MagicMock(spec=file) + emitter = mock.MagicMock() + es = EventScheduler(emitter) + es.shutdown() + self.assertEquals(mock_json_dump.call_args[0][0], {}) + + @mock.patch('threading.Thread') + @mock.patch('json.dump') + @mock.patch('mycroft.skills.event_scheduler.open') + def test_add_remove(self, mock_open, mock_json_dump, mock_thread): + """ + Test add an event and then remove it. + """ + # Thread start is mocked so will not actually run the thread loop + mock_open.return_value = mock.MagicMock(spec=file) + emitter = mock.MagicMock() + es = EventScheduler(emitter) + + es.schedule_event('test', 90000000000, None) + es.schedule_event('test-2', 90000000000, None) + + es.check_state() # run one cycle + self.assertTrue('test' in es.events) + self.assertTrue('test-2' in es.events) + + es.remove_event('test') + es.check_state() # run one cycle + self.assertTrue('test' not in es.events) + self.assertTrue('test-2' in es.events) + es.shutdown() + + @mock.patch('threading.Thread') + @mock.patch('json.load') + @mock.patch('json.dump') + @mock.patch('mycroft.skills.event_scheduler.open') + def test_save(self, mock_open, mock_dump, mock_load, mock_thread): + """ + Test save functionality. + """ + mock_open.return_value = mock.MagicMock(spec=file) + emitter = mock.MagicMock() + es = EventScheduler(emitter) + + es.schedule_event('test', 900000000000, None) + es.schedule_event('test-repeat', 910000000000, 60) + es.check_state() + + es.shutdown() + + self.assertEquals(mock_dump.call_args[0][0], + {'test': [(900000000000, None, {})]})