Example #1
0
    def test_update_alarm(self):
        """
        Places 5 alarms into the database, it then retrieves one, updates it
        and confirms all edits were successful and the timestamp has changed.
        """
        alarm_mgr = AlarmManager()
        # id 3 = 11, 15, (True, False, False, True, False, False, True), True,''
        self.create_alarms(alarm_mgr)

        # Check the alarm has the expected data before editing it
        retrieved_alarm = AlarmManager.get_alarm(3)
        self.assert_alarm(retrieved_alarm, 3, 11, 15,
                          (True, False, False, True, False, False, True), True,
                          '')
        original_timestamp = retrieved_alarm.timestamp

        # Edit it AlarmInstance
        retrieved_alarm.hour = 23
        retrieved_alarm.minute = 34
        retrieved_alarm.enabled = False
        retrieved_alarm.monday = False
        retrieved_alarm.label = 'edited'

        # Update the alarm in the db and check values
        time.sleep(1)
        update_success = alarm_mgr.update_alarm(retrieved_alarm)
        self.assertTrue(update_success)
        self.assertGreater(retrieved_alarm.timestamp, original_timestamp)
        retrieved_alarm = AlarmManager.get_alarm(retrieved_alarm.id_)
        self.assertGreater(retrieved_alarm.timestamp, original_timestamp)
        self.assert_alarm(retrieved_alarm, 3, 23, 34,
                          (False, False, False, True, False, False, True),
                          False, 'edited')
    def test_set_alarm_thread_edit(self):
        """
        Tests the __set_alarm_thread when an existing alarm thread is inputted.
        No need to check for input with wrong ID as that gets dealt with in the
        AlarmThread class and unit test.
        """
        first_alarm = AlarmItem(
            self.hour, 34, label="test", alarm_id=96, days=(True, True, True, True, True, True, True), enabled=True
        )
        new_alarm = AlarmItem(
            self.hour,
            34,
            enabled=False,
            alarm_id=96,
            label="test replace",
            days=(False, False, False, False, False, False, False),
        )
        alarm_mgr = AlarmManager()
        alarm_mgr.delete_all_alarms()
        numb_threads = threading.activeCount()
        launch_success = alarm_mgr._AlarmManager__set_alarm_thread(first_alarm)
        self.assertTrue(launch_success)
        self.assertGreater(threading.activeCount(), numb_threads)

        # Editing to the new alarm data should stop the thread as it is inactive
        launch_success = alarm_mgr._AlarmManager__set_alarm_thread(new_alarm)
        self.assertFalse(launch_success)
        self.assertEqual(threading.activeCount(), numb_threads)
 def test_alarm_trigger_callback(self):
     """
     Creates and alarm to trigger within a minute and check it has done so
     correctly.
     This test uses the static variable AlarmManagerTestCase.thread_alert to
     be be change it in the callback function, and exit an infinite loop.
     This test can take over 10 seconds in its worse case scenario.
     """
     # Set alarm for current minute, but only if there is at least 10 seconds
     # left for this minute. Better than setting it for the next minute.
     time_now = time.localtime(time.time())
     while time_now.tm_sec > 50:
         time.sleep(1)
         time_now = time.localtime(time.time())
     alarm = AlarmItem(
         time_now.tm_hour,
         time_now.tm_min,
         days=(True, True, True, True, True, True, True),
         enabled=True,
         alarm_id=96,
     )
     alarm_mgr = AlarmManager(alert_callback=AlarmManagerTestCase.c)
     alarm_mgr.delete_all_alarms()
     launch_success = alarm_mgr._AlarmManager__set_alarm_thread(alarm)
     self.assertTrue(launch_success)
     while AlarmManagerTestCase.thread_alert is False:
         # This loop will never finish if the thread does not callback
         time.sleep(0.001)
     self.assertTrue(AlarmManagerTestCase.thread_alert)
    def test_update_alarm(self):
        """
        Places 5 alarms into the database, it then retrieves one, updates it
        and confirms all edits were successful and the timestamp has changed.
        """
        alarm_mgr = AlarmManager()
        # id 3 = 11, 15, (True, False, False, True, False, False, True), True,''
        self.create_alarms(alarm_mgr)

        # Check the alarm has the expected data before editing it
        retrieved_alarm = AlarmManager.get_alarm(3)
        self.assert_alarm(retrieved_alarm, 3, 11, 15, (True, False, False, True, False, False, True), True, "")
        original_timestamp = retrieved_alarm.timestamp

        # Edit it AlarmInstance
        retrieved_alarm.hour = 23
        retrieved_alarm.minute = 34
        retrieved_alarm.enabled = False
        retrieved_alarm.monday = False
        retrieved_alarm.label = "edited"

        # Update the alarm in the db and check values
        time.sleep(1)
        update_success = alarm_mgr.update_alarm(retrieved_alarm)
        self.assertTrue(update_success)
        self.assertGreater(retrieved_alarm.timestamp, original_timestamp)
        retrieved_alarm = AlarmManager.get_alarm(retrieved_alarm.id_)
        self.assertGreater(retrieved_alarm.timestamp, original_timestamp)
        self.assert_alarm(retrieved_alarm, 3, 23, 34, (False, False, False, True, False, False, True), False, "edited")
Example #5
0
 def test_alarm_trigger_callback(self):
     """
     Creates and alarm to trigger within a minute and check it has done so
     correctly.
     This test uses the static variable AlarmManagerTestCase.thread_alert to
     be be change it in the callback function, and exit an infinite loop.
     This test can take over 10 seconds in its worse case scenario.
     """
     # Set alarm for current minute, but only if there is at least 10 seconds
     # left for this minute. Better than setting it for the next minute.
     time_now = time.localtime(time.time())
     while time_now.tm_sec > 50:
         time.sleep(1)
         time_now = time.localtime(time.time())
     alarm = AlarmItem(time_now.tm_hour,
                       time_now.tm_min,
                       days=(True, True, True, True, True, True, True),
                       enabled=True,
                       alarm_id=96)
     alarm_mgr = AlarmManager(alert_callback=AlarmManagerTestCase.c)
     alarm_mgr.delete_all_alarms()
     launch_success = alarm_mgr._AlarmManager__set_alarm_thread(alarm)
     self.assertTrue(launch_success)
     while AlarmManagerTestCase.thread_alert is False:
         # This loop will never finish if the thread does not callback
         time.sleep(0.001)
     self.assertTrue(AlarmManagerTestCase.thread_alert)
 def test_add_alarm(self):
     """ Adds an alarm and checks it has been set correctly. """
     alarm_mgr = AlarmManager()
     alarm_mgr.delete_all_alarms()
     add_success = alarm_mgr.add_alarm(8, 30, (False, True, False, True, False, True, False), True, "test")  # id 1
     self.assertIsInstance(add_success, types.IntType)
     all_alarms = AlarmManager.get_all_alarms()
     latest = len(all_alarms) - 1
     self.assert_alarm(all_alarms[latest], 1, 8, 30, (False, True, False, True, False, True, False), True, "test")
Example #7
0
 def test_delete_all_alarms(self):
     """
     Adds 5 alarms to the database, checks there are alarms in the db and
     proceeds to delete them all and check.
     """
     alarm_mgr = AlarmManager()
     self.create_alarms(alarm_mgr)
     numb_alarms = AlarmManager.get_number_of_alarms()
     self.assertGreater(numb_alarms, 0)
     delete_success = alarm_mgr.delete_all_alarms()
     self.assertTrue(delete_success)
     self.assertEqual(AlarmManager.get_number_of_alarms(), 0)
 def test_delete_all_alarms(self):
     """
     Adds 5 alarms to the database, checks there are alarms in the db and
     proceeds to delete them all and check.
     """
     alarm_mgr = AlarmManager()
     self.create_alarms(alarm_mgr)
     numb_alarms = AlarmManager.get_number_of_alarms()
     self.assertGreater(numb_alarms, 0)
     delete_success = alarm_mgr.delete_all_alarms()
     self.assertTrue(delete_success)
     self.assertEqual(AlarmManager.get_number_of_alarms(), 0)
Example #9
0
 def __init__(self, alarm_mgr=None):
     """
     Instance initialiser.
     Attaches an AlarmManager instance, or creates a new one with the CLI
     default alarm alert callback.
     """
     cmd.Cmd.__init__(self)
     self.alert_running = False
     if alarm_mgr is None:
         self.alarm_mgr = AlarmManager(alert_callback=self.alarm_alert)
     else:
         self.alarm_mgr = alarm_mgr
Example #10
0
 def test_is_alarm_running(self):
     """ Adds a couple of alarms and tests the is_alarm_running() method. """
     alarm_active = AlarmItem(self.hour,
                              20,
                              enabled=True,
                              alarm_id=96,
                              days=(True, True, True, True, True, True,
                                    True))
     alarm_inactive = AlarmItem(self.hour,
                                20,
                                enabled=False,
                                alarm_id=86,
                                days=(False, False, False, False, False,
                                      False, False))
     alarm_mgr = AlarmManager()
     alarm_mgr.delete_all_alarms()
     launch_success = alarm_mgr._AlarmManager__set_alarm_thread(
         alarm_active)
     self.assertTrue(launch_success)
     launch_success = alarm_mgr._AlarmManager__set_alarm_thread(
         alarm_inactive)
     self.assertFalse(launch_success)
     # Now everything is set up, test the is_alarm_running method
     self.assertTrue(alarm_mgr.is_alarm_running(alarm_active.id_))
     self.assertFalse(alarm_mgr.is_alarm_running(alarm_inactive.id_))
Example #11
0
    def do_delete(self, alarm_id_string):
        """
        Delete an alarm identified by its id, or all the alarms. E.g.:
        'delete 3'
        'delete all'
        """
        if alarm_id_string == 'all':
            success = self.alarm_mgr.delete_all_alarms()
            if success is True:
                print('All alarms have been deleted !')
        else:
            try:
                alarm_id = int(alarm_id_string)
            except ValueError:
                self.display_alarms()
                print('After "delete" there must be a number indicating ' +
                      'the Alarm ID to be deleted !')
                return
            alarm_string = str(AlarmManager.get_alarm(alarm_id))
            success = self.alarm_mgr.delete_alarm(alarm_id)
            if success is True:
                self.display_alarms()
                print('Alarm ID %s has been deleted:\n' % alarm_id +
                      AlarmCli.dashes_line + '\n%s' % alarm_string)

        if not success:
            self.display_alarms()
            print('Alarm/s "%s" could not be deleted.' % alarm_id_string)
Example #12
0
    def do_delete(self, alarm_id_string):
        """
        Delete an alarm identified by its id, or all the alarms. E.g.:
        'delete 3'
        'delete all'
        """
        if alarm_id_string == 'all':
            success = self.alarm_mgr.delete_all_alarms()
            if success is True:
                print('All alarms have been deleted !')
        else:
            try:
                alarm_id = int(alarm_id_string)
            except ValueError:
                self.display_alarms()
                print('After "delete" there must be a number indicating ' +
                      'the Alarm ID to be deleted !')
                return
            alarm_string = str(AlarmManager.get_alarm(alarm_id))
            success = self.alarm_mgr.delete_alarm(alarm_id)
            if success is True:
                self.display_alarms()
                print('Alarm ID %s has been deleted:\n' % alarm_id +
                      AlarmCli.dashes_line + '\n%s' % alarm_string)

        if not success:
            self.display_alarms()
            print('Alarm/s "%s" could not be deleted.' % alarm_id_string)
Example #13
0
 def test_stop_all_alarm_threads(self):
     """
     Launches 2 alarms threads, checks they are running and them stops them
     all and checks again.
     """
     alarm_one = AlarmItem(self.hour,
                           34,
                           enabled=True,
                           alarm_id=31,
                           days=(False, False, False, False, False, False,
                                 True))
     alarm_two = AlarmItem(self.hour,
                           34,
                           enabled=True,
                           alarm_id=32,
                           days=(False, False, False, False, False, False,
                                 True))
     alarm_mgr = AlarmManager()
     # There is a bit of circular dependency here as delete all will execute
     # __stop_all_alarm_threads
     alarm_mgr.delete_all_alarms()
     launch_success = alarm_mgr._AlarmManager__set_alarm_thread(alarm_one)
     self.assertTrue(launch_success)
     launch_success = alarm_mgr._AlarmManager__set_alarm_thread(alarm_two)
     self.assertTrue(launch_success)
     numb_threads = threading.activeCount()
     self.assertGreaterEqual(numb_threads, 2)
     delete_success = alarm_mgr._AlarmManager__stop_all_alarm_threads()
     self.assertTrue(delete_success)
     self.assertEqual(threading.activeCount(), numb_threads - 2)
Example #14
0
    def test_edit_alarm(self):
        """
        Places 5 alarms into the database, it then retrieves one, edits it and
        confirms all edits were successful.
        """
        alarm_mgr = AlarmManager()
        # id 3 = 11, 15, (True, False, False, True, False, False, True), True,''
        self.create_alarms(alarm_mgr)

        # Check the alarm has the expected data before editing it
        retrieved_alarm = AlarmManager.get_alarm(3)
        self.assert_alarm(retrieved_alarm, 3, 11, 15,
                          (True, False, False, True, False, False, True), True,
                          '')

        # Edit it and check values
        edit_success = alarm_mgr.edit_alarm(
            retrieved_alarm.id_, 23, 34,
            (False, True, False, True, False, True, False), False, 'edited')
        self.assertTrue(edit_success)
        retrieved_alarm = AlarmManager.get_alarm(retrieved_alarm.id_)
        self.assert_alarm(retrieved_alarm, 3, 23, 34,
                          (False, True, False, True, False, True, False),
                          False, 'edited')

        # Ensure nothing changes if no edit arguments are added
        edit_success = alarm_mgr.edit_alarm(retrieved_alarm.id_)
        self.assertTrue(edit_success)
        retrieved_alarm = AlarmManager.get_alarm(retrieved_alarm.id_)
        self.assert_alarm(retrieved_alarm, 3, 23, 34,
                          (False, True, False, True, False, True, False),
                          False, 'edited')
Example #15
0
    def test_set_alarm_thread(self):
        """
        Test that the __set_alarm_thread private method will only launch an
        Alarm Thread if there is an active alarm.
        Ensure the thread has been launched successfully.
        This test accesses private methods.
        """
        alarm = AlarmItem(self.hour,
                          34,
                          days=(True, True, True, True, True, True, True),
                          enabled=False,
                          label='test',
                          alarm_id=96)
        alarm_mgr = AlarmManager()
        alarm_mgr.delete_all_alarms()
        numb_threads = threading.activeCount()

        # Test setting inactive alarm
        launch_success = alarm_mgr._AlarmManager__set_alarm_thread(alarm)
        self.assertFalse(launch_success)
        self.assertEqual(threading.activeCount(), numb_threads)

        # Test enabled alarm with no repeats
        alarm.repeat = (False, False, False, False, False, False, False)
        alarm.enabled = True
        launch_success = alarm_mgr._AlarmManager__set_alarm_thread(alarm)
        self.assertFalse(launch_success)
        self.assertEqual(threading.activeCount(), numb_threads)

        # Test fully active alarm
        alarm.wednesday = True
        launch_success = alarm_mgr._AlarmManager__set_alarm_thread(alarm)
        self.assertTrue(launch_success)
        self.assertGreater(threading.activeCount(), numb_threads)
Example #16
0
 def test_dummy_alarms(self):
     """
     Tests that if the database is empty it will populate it with the dummy
     alarms.
     This also accesses the static methods from a AlarmManager() instacne.
     """
     alarm_mgr = AlarmManager()
     alarm_mgr.delete_all_alarms()
     self.assertEqual(alarm_mgr.get_number_of_alarms(), 0)
     alarm_mgr = AlarmManager()
     self.assertNotEqual(alarm_mgr.get_number_of_alarms(), 0)
 def test_stop_alarm_thread(self):
     """
     Test that the __stop_alarm_thread private method will stop a running
     Alarm Thread, which due to the nature of the thread code can take up to
     10 seconds.
     This test accesses private methods.
     """
     alarm = AlarmItem(
         self.hour, 34, enabled=True, label="t", alarm_id=96, days=(False, True, True, True, True, True, True)
     )
     alarm_mgr = AlarmManager()
     alarm_mgr.delete_all_alarms()
     numb_threads = threading.activeCount()
     launch_success = alarm_mgr._AlarmManager__set_alarm_thread(alarm)
     self.assertTrue(launch_success)
     self.assertGreater(threading.activeCount(), numb_threads)
     stop_success = alarm_mgr._AlarmManager__stop_alarm_thread(alarm.id_)
     self.assertTrue(stop_success)
     self.assertEqual(threading.activeCount(), numb_threads)
Example #18
0
 def test_get_running_alarms(self):
     """
     Tests get_running_alarms returns a list of the running alarms (active
     alarms with a running thread), or an empty list.
     """
     alarm_mgr = AlarmManager()
     # All these alarms are active
     self.create_alarms(alarm_mgr)
     running_alarms = alarm_mgr.get_running_alarms()
     self.assertGreater(len(running_alarms), 0)
     alarm_mgr.edit_alarm(1, enabled=False)
     alarm_mgr.edit_alarm(3, enabled=False)
     self.assertEqual(
         len(running_alarms) - 2, len(alarm_mgr.get_running_alarms()))
     alarm_mgr.delete_all_alarms()
     running_alarms = alarm_mgr.get_running_alarms()
     self.assertEqual(len(running_alarms), 0)
Example #19
0
 def __init__(self, alarm_mgr=None):
     """
     Instance initialiser.
     Attaches an AlarmManager instance, or creates a new one with the CLI
     default alarm alert callback.
     """
     cmd.Cmd.__init__(self)
     self.alert_running = False
     if alarm_mgr is None:
         self.alarm_mgr = AlarmManager(alert_callback=self.alarm_alert)
     else:
         self.alarm_mgr = alarm_mgr
Example #20
0
    def test_set_alarm_thread_edit(self):
        """
        Tests the __set_alarm_thread when an existing alarm thread is inputted.
        No need to check for input with wrong ID as that gets dealt with in the
        AlarmThread class and unit test.
        """
        first_alarm = AlarmItem(self.hour,
                                34,
                                label='test',
                                alarm_id=96,
                                days=(True, True, True, True, True, True,
                                      True),
                                enabled=True)
        new_alarm = AlarmItem(self.hour,
                              34,
                              enabled=False,
                              alarm_id=96,
                              label='test replace',
                              days=(False, False, False, False, False, False,
                                    False))
        alarm_mgr = AlarmManager()
        alarm_mgr.delete_all_alarms()
        numb_threads = threading.activeCount()
        launch_success = alarm_mgr._AlarmManager__set_alarm_thread(first_alarm)
        self.assertTrue(launch_success)
        self.assertGreater(threading.activeCount(), numb_threads)

        # Editing to the new alarm data should stop the thread as it is inactive
        launch_success = alarm_mgr._AlarmManager__set_alarm_thread(new_alarm)
        self.assertFalse(launch_success)
        self.assertEqual(threading.activeCount(), numb_threads)
    def test_edit_alarm(self):
        """
        Places 5 alarms into the database, it then retrieves one, edits it and
        confirms all edits were successful.
        """
        alarm_mgr = AlarmManager()
        # id 3 = 11, 15, (True, False, False, True, False, False, True), True,''
        self.create_alarms(alarm_mgr)

        # Check the alarm has the expected data before editing it
        retrieved_alarm = AlarmManager.get_alarm(3)
        self.assert_alarm(retrieved_alarm, 3, 11, 15, (True, False, False, True, False, False, True), True, "")

        # Edit it and check values
        edit_success = alarm_mgr.edit_alarm(
            retrieved_alarm.id_, 23, 34, (False, True, False, True, False, True, False), False, "edited"
        )
        self.assertTrue(edit_success)
        retrieved_alarm = AlarmManager.get_alarm(retrieved_alarm.id_)
        self.assert_alarm(retrieved_alarm, 3, 23, 34, (False, True, False, True, False, True, False), False, "edited")

        # Ensure nothing changes if no edit arguments are added
        edit_success = alarm_mgr.edit_alarm(retrieved_alarm.id_)
        self.assertTrue(edit_success)
        retrieved_alarm = AlarmManager.get_alarm(retrieved_alarm.id_)
        self.assert_alarm(retrieved_alarm, 3, 23, 34, (False, True, False, True, False, True, False), False, "edited")
    def test_set_alarm_thread(self):
        """
        Test that the __set_alarm_thread private method will only launch an
        Alarm Thread if there is an active alarm.
        Ensure the thread has been launched successfully.
        This test accesses private methods.
        """
        alarm = AlarmItem(
            self.hour, 34, days=(True, True, True, True, True, True, True), enabled=False, label="test", alarm_id=96
        )
        alarm_mgr = AlarmManager()
        alarm_mgr.delete_all_alarms()
        numb_threads = threading.activeCount()

        # Test setting inactive alarm
        launch_success = alarm_mgr._AlarmManager__set_alarm_thread(alarm)
        self.assertFalse(launch_success)
        self.assertEqual(threading.activeCount(), numb_threads)

        # Test enabled alarm with no repeats
        alarm.repeat = (False, False, False, False, False, False, False)
        alarm.enabled = True
        launch_success = alarm_mgr._AlarmManager__set_alarm_thread(alarm)
        self.assertFalse(launch_success)
        self.assertEqual(threading.activeCount(), numb_threads)

        # Test fully active alarm
        alarm.wednesday = True
        launch_success = alarm_mgr._AlarmManager__set_alarm_thread(alarm)
        self.assertTrue(launch_success)
        self.assertGreater(threading.activeCount(), numb_threads)
 def test_get_running_alarms(self):
     """
     Tests get_running_alarms returns a list of the running alarms (active
     alarms with a running thread), or an empty list.
     """
     alarm_mgr = AlarmManager()
     # All these alarms are active
     self.create_alarms(alarm_mgr)
     running_alarms = alarm_mgr.get_running_alarms()
     self.assertGreater(len(running_alarms), 0)
     alarm_mgr.edit_alarm(1, enabled=False)
     alarm_mgr.edit_alarm(3, enabled=False)
     self.assertEqual(len(running_alarms) - 2, len(alarm_mgr.get_running_alarms()))
     alarm_mgr.delete_all_alarms()
     running_alarms = alarm_mgr.get_running_alarms()
     self.assertEqual(len(running_alarms), 0)
Example #24
0
 def test_get_all_active_alarms(self):
     """ Test the get_all_active_alarms method. """
     alarm_mgr = AlarmManager()
     # First test with 5 active alarms
     self.create_alarms(alarm_mgr)
     active_alarms = AlarmManager.get_all_active_alarms()
     self.assertEquals(len(active_alarms), 5)
     # Deactivate a couple of alarms and try again
     edit_success = alarm_mgr.edit_alarm(1, enabled=False)
     self.assertTrue(edit_success)
     edit_success = alarm_mgr.edit_alarm(3,
                                         days=(False, False, False, False,
                                               False, False, False))
     self.assertTrue(edit_success)
     active_alarms = AlarmManager.get_all_active_alarms()
     self.assertEquals(len(active_alarms), 3)
     # Check it returns an empty list if no ative alarms
     alarm_mgr.delete_all_alarms()
     active_alarms = AlarmManager.get_all_active_alarms()
     self.assertEqual(len(active_alarms), 0)
Example #25
0
 def test_delete_alarm(self):
     """
     Adds 5 alarms to the database, checks it is able to retrieve one of
     them and proceeds to delete and check it has been deleted.
     """
     alarm_mgr = AlarmManager()
     self.create_alarms(alarm_mgr)
     numb_alarms = AlarmManager.get_number_of_alarms()
     self.assertGreater(numb_alarms, 0)
     all_alarms = AlarmManager.get_all_alarms()
     alarm_retrieved = AlarmManager.get_alarm(all_alarms[0].id_)
     self.assertIsNotNone(alarm_retrieved)
     delete_success = alarm_mgr.delete_alarm(1)
     self.assertTrue(delete_success)
     self.assertLess(AlarmManager.get_number_of_alarms(), numb_alarms)
     alarm_retrieved = AlarmManager.get_alarm(alarm_retrieved.id_)
     self.assertIsNone(alarm_retrieved)
 def test_get_all_active_alarms(self):
     """ Test the get_all_active_alarms method. """
     alarm_mgr = AlarmManager()
     # First test with 5 active alarms
     self.create_alarms(alarm_mgr)
     active_alarms = AlarmManager.get_all_active_alarms()
     self.assertEquals(len(active_alarms), 5)
     # Deactivate a couple of alarms and try again
     edit_success = alarm_mgr.edit_alarm(1, enabled=False)
     self.assertTrue(edit_success)
     edit_success = alarm_mgr.edit_alarm(3, days=(False, False, False, False, False, False, False))
     self.assertTrue(edit_success)
     active_alarms = AlarmManager.get_all_active_alarms()
     self.assertEquals(len(active_alarms), 3)
     # Check it returns an empty list if no ative alarms
     alarm_mgr.delete_all_alarms()
     active_alarms = AlarmManager.get_all_active_alarms()
     self.assertEqual(len(active_alarms), 0)
 def test_dummy_alarms(self):
     """
     Tests that if the database is empty it will populate it with the dummy
     alarms.
     This also accesses the static methods from a AlarmManager() instacne.
     """
     alarm_mgr = AlarmManager()
     alarm_mgr.delete_all_alarms()
     self.assertEqual(alarm_mgr.get_number_of_alarms(), 0)
     alarm_mgr = AlarmManager()
     self.assertNotEqual(alarm_mgr.get_number_of_alarms(), 0)
Example #28
0
 def test_add_alarm(self):
     """ Adds an alarm and checks it has been set correctly. """
     alarm_mgr = AlarmManager()
     alarm_mgr.delete_all_alarms()
     add_success = alarm_mgr.add_alarm(  # id 1
         8, 30, (False, True, False, True, False, True, False), True,
         'test')
     self.assertIsInstance(add_success, types.IntType)
     all_alarms = AlarmManager.get_all_alarms()
     latest = len(all_alarms) - 1
     self.assert_alarm(all_alarms[latest], 1, 8, 30,
                       (False, True, False, True, False, True, False), True,
                       'test')
 def test_is_alarm_running(self):
     """ Adds a couple of alarms and tests the is_alarm_running() method. """
     alarm_active = AlarmItem(
         self.hour, 20, enabled=True, alarm_id=96, days=(True, True, True, True, True, True, True)
     )
     alarm_inactive = AlarmItem(
         self.hour, 20, enabled=False, alarm_id=86, days=(False, False, False, False, False, False, False)
     )
     alarm_mgr = AlarmManager()
     alarm_mgr.delete_all_alarms()
     launch_success = alarm_mgr._AlarmManager__set_alarm_thread(alarm_active)
     self.assertTrue(launch_success)
     launch_success = alarm_mgr._AlarmManager__set_alarm_thread(alarm_inactive)
     self.assertFalse(launch_success)
     # Now everything is set up, test the is_alarm_running method
     self.assertTrue(alarm_mgr.is_alarm_running(alarm_active.id_))
     self.assertFalse(alarm_mgr.is_alarm_running(alarm_inactive.id_))
 def test_delete_alarm(self):
     """
     Adds 5 alarms to the database, checks it is able to retrieve one of
     them and proceeds to delete and check it has been deleted.
     """
     alarm_mgr = AlarmManager()
     self.create_alarms(alarm_mgr)
     numb_alarms = AlarmManager.get_number_of_alarms()
     self.assertGreater(numb_alarms, 0)
     all_alarms = AlarmManager.get_all_alarms()
     alarm_retrieved = AlarmManager.get_alarm(all_alarms[0].id_)
     self.assertIsNotNone(alarm_retrieved)
     delete_success = alarm_mgr.delete_alarm(1)
     self.assertTrue(delete_success)
     self.assertLess(AlarmManager.get_number_of_alarms(), numb_alarms)
     alarm_retrieved = AlarmManager.get_alarm(alarm_retrieved.id_)
     self.assertIsNone(alarm_retrieved)
Example #31
0
 def test_stop_alarm_thread(self):
     """
     Test that the __stop_alarm_thread private method will stop a running
     Alarm Thread, which due to the nature of the thread code can take up to
     10 seconds.
     This test accesses private methods.
     """
     alarm = AlarmItem(self.hour,
                       34,
                       enabled=True,
                       label='t',
                       alarm_id=96,
                       days=(False, True, True, True, True, True, True))
     alarm_mgr = AlarmManager()
     alarm_mgr.delete_all_alarms()
     numb_threads = threading.activeCount()
     launch_success = alarm_mgr._AlarmManager__set_alarm_thread(alarm)
     self.assertTrue(launch_success)
     self.assertGreater(threading.activeCount(), numb_threads)
     stop_success = alarm_mgr._AlarmManager__stop_alarm_thread(alarm.id_)
     self.assertTrue(stop_success)
     self.assertEqual(threading.activeCount(), numb_threads)
 def test_stop_all_alarm_threads(self):
     """
     Launches 2 alarms threads, checks they are running and them stops them
     all and checks again.
     """
     alarm_one = AlarmItem(
         self.hour, 34, enabled=True, alarm_id=31, days=(False, False, False, False, False, False, True)
     )
     alarm_two = AlarmItem(
         self.hour, 34, enabled=True, alarm_id=32, days=(False, False, False, False, False, False, True)
     )
     alarm_mgr = AlarmManager()
     # There is a bit of circular dependency here as delete all will execute
     # __stop_all_alarm_threads
     alarm_mgr.delete_all_alarms()
     launch_success = alarm_mgr._AlarmManager__set_alarm_thread(alarm_one)
     self.assertTrue(launch_success)
     launch_success = alarm_mgr._AlarmManager__set_alarm_thread(alarm_two)
     self.assertTrue(launch_success)
     numb_threads = threading.activeCount()
     self.assertGreaterEqual(numb_threads, 2)
     delete_success = alarm_mgr._AlarmManager__stop_all_alarm_threads()
     self.assertTrue(delete_success)
     self.assertEqual(threading.activeCount(), numb_threads - 2)
Example #33
0
    def do_add(self, alarm_str):
        """Help add:
        Add an alarm using the format (days follow the 3 letter format):
        'hh mm <enabled/disabled> <days to repeat>'
        e.g. 'add 9 00 enabled Mon Fri'
            'add 10 30 disabled sat sun'
            'add 7 10 enabled all'
            'add 22 55 disabled'
        """
        words = alarm_str.split(' ')
        # First check for enough items
        if len(words) < 2:
            print('Not enough data provided, for information about this ' +
                  'command use the "help add"\ncommand !')
            return

        # First word is the hour, mandatory
        try:
            hour = int(words[0])
        except ValueError:
            print('First item must be a number indicating the time !')
            return

        # Second word is the minute, mandatory
        try:
            minute = int(words[1])
        except ValueError:
            print('First item must be a number indicating the time !')
            return

        # Third word is the enable, optional
        if len(words) > 2:
            if words[2].lower() == 'enable' or words[2].lower() == 'enabled':
                enable = True
            elif words[2].lower() == 'disable' or \
                    words[2].lower() == 'disabled':
                enable = False
            else:
                print('Third item must indicate if the alarm will be ' +
                      '"enable" or "disabled" !')
                return
        else:
            # Defaults to enabled
            enable = True

        # Following words are the repeat days, optional
        if len(words) > 3:
            if words[3].lower() == 'all':
                repeats = (True, True, True, True, True, True, True)
            elif words[3].lower() == 'none':
                repeats = (False, False, False, False, False, False, False)
            else:
                repeats = [False] * 7
                for i in xrange(len(words[3:])):
                    if words[i+3].lower() == 'mon':
                        repeats[0] = True
                    elif words[i+3].lower() == 'tue':
                        repeats[1] = True
                    elif words[i+3].lower() == 'wed':
                        repeats[2] = True
                    elif words[i+3].lower() == 'thu':
                        repeats[3] = True
                    elif words[i+3].lower() == 'fri':
                        repeats[4] = True
                    elif words[i+3].lower() == 'sat':
                        repeats[5] = True
                    elif words[i+3].lower() == 'sun':
                        repeats[6] = True
                    else:
                        print(('Repeat day "%s" not recognised,' % words[i+3]) +
                              ' use the "help add" command for more info !')
                        return
        else:
            # Defaults to all days enabled
            repeats = (True, True, True, True, True, True, True)

        # Create the alarm and inform the user
        alarm_id = self.alarm_mgr.add_alarm(hour, minute, repeats, enable)
        if alarm_id is not None:
            self.display_alarms()
            print('Created Alarm:\n' + AlarmCli.dashes_line +
                  '\n%s' % AlarmManager.get_alarm(alarm_id))
        else:
            print('There was a problem creating the alarm.')
Example #34
0
    def test_check_threads_state(self):
        """ Test almost all pathways of check_threads_state. """
        alarm_mgr = AlarmManager()
        self.create_alarms(alarm_mgr)
        check_result = alarm_mgr.check_threads_state()
        self.assertTrue(check_result)

        # Now that everything is working correctly, sneak around AlarmManager
        # and edit a running thread by editing an AlarmItem using the
        # AlarmThread internal reference to the AlarmItem instance (which does
        # not do the extra checks for tracking like AlarmManager does).
        # Also edit the database entry for that alarm bypassing AlarmManager.
        alarm_bypass = \
            alarm_mgr._AlarmManager__alarm_threads[0]._AlarmThread__alarm
        alarm_bypass.enabled = False
        alarm_id = alarm_bypass.id_
        AlarmDb().edit_alarm(alarm_id, enabled=False)
        check_result = alarm_mgr.check_threads_state()
        self.assertFalse(check_result)
        # Executing check_threads_state should have return false as there was
        # an issue, but if fixed correctly the second time should return true
        check_result = alarm_mgr.check_threads_state()
        self.assertTrue(check_result)

        # Now the thread for alarm 'alarm_bypass' with ID 'alarm_id' has been
        # stopped, we can bypass AlarmManager again to activate it and check
        # if check_threads_state recovers again.
        alarm_bypass.enabled = True
        AlarmDb().edit_alarm(alarm_bypass.id_, enabled=True)
        check_result = alarm_mgr.check_threads_state()
        self.assertFalse(check_result)
        check_result = alarm_mgr.check_threads_state()
        self.assertTrue(check_result)

        # Now that everything is working correctly once more, add extra thread
        alarm_test = AlarmItem(self.hour,
                               20,
                               enabled=True,
                               alarm_id=96,
                               days=(True, True, True, True, True, True, True))
        launch_success = alarm_mgr._AlarmManager__set_alarm_thread(alarm_test)
        self.assertTrue(launch_success)
        check_result = alarm_mgr.check_threads_state()
        self.assertFalse(check_result)
        check_result = alarm_mgr.check_threads_state()
        self.assertTrue(check_result)

        # Now we stop a running thread bypassing AlarmManager public methods
        alarm_mgr._AlarmManager__alarm_threads[0].stop()
        while alarm_mgr._AlarmManager__alarm_threads[0].isAlive():
            time.sleep(0.1)
        check_result = alarm_mgr.check_threads_state()
        self.assertFalse(check_result)
        check_result = alarm_mgr.check_threads_state()
        self.assertTrue(check_result)
Example #35
0
class AlarmCli(cmd.Cmd):
    """
    Command processor class to control LightUpAlarm.
    The Pydoc comments do not include the 'param' and 'return' data because
    the class uses these comments for the command line help menu.
    """
    # Class variable for a full line (80 chars) of dashes
    dashes_line = '----------------------------------------' + \
                  '----------------------------------------'

    #
    # metaclass methods
    #
    def __init__(self, alarm_mgr=None):
        """
        Instance initialiser.
        Attaches an AlarmManager instance, or creates a new one with the CLI
        default alarm alert callback.
        """
        cmd.Cmd.__init__(self)
        self.alert_running = False
        if alarm_mgr is None:
            self.alarm_mgr = AlarmManager(alert_callback=self.alarm_alert)
        else:
            self.alarm_mgr = alarm_mgr

    #
    # parent class methods and class variables
    #
    prompt = '(command): '
    doc_header = 'Available commands (for more info type "help <command>")'

    def preloop(self):
        """ Gets executed before the run loop. """
        self.show_header_only()
        self.display_alarms()

    def onecmd(self, s):
        """
        Parses and executes the command. Overwritten to added method to only
        show the header and current alarms at the top of the terminal and the
        current command output.
        """
        self.show_header_only()
        return cmd.Cmd.onecmd(self, s)

    def postcmd(self, stop, line):
        """
        Runs after the command is executed. Overwritten to add a couple of blank
        lines before the command input is displayed. Used for visual spacing.
        """
        print('\n')
        return cmd.Cmd.postcmd(self, stop, line)

    #
    # Alar command methods
    #
    def do_alarms(self, full_str):
        """Help alarms:
        Displays all the alarms.
        Use the keyword 'full' to display additional info.
        """
        if full_str == '':
            self.display_alarms()
        elif full_str == 'full':
            all_alarms = self.alarm_mgr.get_all_alarms()
            print('All Alarms:\n' + AlarmCli.dashes_line)
            if not all_alarms:
                print('\tThere are not saved alarms.')
            else:
                for alarm in all_alarms:
                    print(
                        '%s\n              | timestamp: %s      | label: %s\n'
                        % (alarm, alarm.timestamp, alarm.label))
        else:
            print('The only command that can follow alarms is "full"')

    def do_active(self, empty_str):
        """Help active:
        Displays the active alarms currently running.
        """
        self.display_alarms()
        running_alarms = self.alarm_mgr.get_running_alarms()
        print('Active Alarms running:\n' + AlarmCli.dashes_line)
        if not running_alarms:
            print('\tThere are not active alarms running.')
        else:
            for alarm in running_alarms:
                print(alarm)

    def do_next(self, empty_str):
        """Help next:
        Displays the next scheduled alarm to alert.
        """
        self.display_alarms()
        next_alarm = self.alarm_mgr.get_next_alarm()
        if next_alarm is not None:
            print('The next scheduled Alarm is:\n' + AlarmCli.dashes_line)
            print(next_alarm)
        else:
            print('\tThere are not active alarms running.')

    def do_add(self, alarm_str):
        """Help add:
        Add an alarm using the format (days follow the 3 letter format):
        'hh mm <enabled/disabled> <days to repeat>'
        e.g. 'add 9 00 enabled Mon Fri'
            'add 10 30 disabled sat sun'
            'add 7 10 enabled all'
            'add 22 55 disabled'
        """
        words = alarm_str.split(' ')
        # First check for enough items
        if len(words) < 2:
            print('Not enough data provided, for information about this ' +
                  'command use the "help add"\ncommand !')
            return

        # First word is the hour, mandatory
        try:
            hour = int(words[0])
        except ValueError:
            print('First item must be a number indicating the time !')
            return

        # Second word is the minute, mandatory
        try:
            minute = int(words[1])
        except ValueError:
            print('First item must be a number indicating the time !')
            return

        # Third word is the enable, optional
        if len(words) > 2:
            if words[2].lower() == 'enable' or words[2].lower() == 'enabled':
                enable = True
            elif words[2].lower() == 'disable' or \
                    words[2].lower() == 'disabled':
                enable = False
            else:
                print('Third item must indicate if the alarm will be ' +
                      '"enable" or "disabled" !')
                return
        else:
            # Defaults to enabled
            enable = True

        # Following words are the repeat days, optional
        if len(words) > 3:
            if words[3].lower() == 'all':
                repeats = (True, True, True, True, True, True, True)
            elif words[3].lower() == 'none':
                repeats = (False, False, False, False, False, False, False)
            else:
                repeats = [False] * 7
                for i in xrange(len(words[3:])):
                    if words[i + 3].lower() == 'mon':
                        repeats[0] = True
                    elif words[i + 3].lower() == 'tue':
                        repeats[1] = True
                    elif words[i + 3].lower() == 'wed':
                        repeats[2] = True
                    elif words[i + 3].lower() == 'thu':
                        repeats[3] = True
                    elif words[i + 3].lower() == 'fri':
                        repeats[4] = True
                    elif words[i + 3].lower() == 'sat':
                        repeats[5] = True
                    elif words[i + 3].lower() == 'sun':
                        repeats[6] = True
                    else:
                        print(('Repeat day "%s" not recognised,' %
                               words[i + 3]) +
                              ' use the "help add" command for more info !')
                        return
        else:
            # Defaults to all days enabled
            repeats = (True, True, True, True, True, True, True)

        # Create the alarm and inform the user
        alarm_id = self.alarm_mgr.add_alarm(hour, minute, repeats, enable)
        if alarm_id is not None:
            self.display_alarms()
            print('Created Alarm:\n' + AlarmCli.dashes_line +
                  '\n%s' % AlarmManager.get_alarm(alarm_id))
        else:
            print('There was a problem creating the alarm.')

    def do_edit(self, edit_str):
        """Help edit command:
        Edit an alarm using the following format:
        'edit <alarm ID> <attribute> <new value>'
        e.g. 'edit 3 hour 9'
            'edit 4 minute 30'
            'edit 7 enabled no'
            'edit 1 repeat mon fri'
        """
        words = edit_str.split(' ')
        # First check for enough items
        if len(words) < 3:
            print('Not enough data provided, for information about this ' +
                  'command use the "help edit"\ncommand !')
            return

        # First word is the Alarm ID
        try:
            alarm_id = int(words[0])
        except ValueError:
            print('First item must be a the ID number of the alarm to edit!')
            return

        # Capture the original alarm, to check if it exits and later comparison
        original_alarm = self.alarm_mgr.get_alarm(alarm_id)
        if original_alarm is None:
            self.display_alarms()
            print('The Alarm with ID %s could not be found !' % alarm_id)
            return

        # Second word is the attribute to change, the third word parsed
        # immediately after each second word option.
        # Hours
        if words[1].lower() == 'hour' or words[2] == 'hours':
            try:
                hour = int(words[2])
            except ValueError:
                self.display_alarms()
                print('To edit the hour it must be followed a valid number !')
                return
            self.alarm_mgr.edit_alarm(alarm_id, hour=hour)
        # Minutes
        elif words[1].lower() == 'minute' or words[2] == 'minutes':
            try:
                minute = int(words[2])
            except ValueError:
                print(
                    'To edit the minute it must be followed a valid number !')
                return
            self.alarm_mgr.edit_alarm(alarm_id, minute=minute)
        # Enable
        elif words[1].lower() == 'enable' or words[1] == 'enabled':
            if words[2].lower() == 'yes':
                self.alarm_mgr.edit_alarm(alarm_id, enabled=True)
            elif words[2].lower() == 'no':
                self.alarm_mgr.edit_alarm(alarm_id, enabled=False)
            else:
                print('To edit the enable it must be followed by "yes" or ' +
                      '"No" !')
                return
        # Disable (should not really be an option, but accepted)
        elif words[1].lower() == 'disable' or words[1] == 'disabled':
            if words[2].lower() == 'yes':
                self.alarm_mgr.edit_alarm(alarm_id, enabled=False)
            elif words[2].lower() == 'no':
                self.alarm_mgr.edit_alarm(alarm_id, enabled=True)
            else:
                print('To edit the enable it must be followed by "yes" or ' +
                      '"No" !')
                return
        # Label
        elif words[1].lower() == 'label':
            label_str = ' '.join(str(x) for x in words[2:])
            self.alarm_mgr.edit_alarm(alarm_id, label=label_str)
        # Days
        elif words[1].lower() == 'repeat':
            if words[2].lower() == 'all':
                repeats = (True, True, True, True, True, True, True)
            elif words[2].lower() == 'none':
                repeats = (False, False, False, False, False, False, False)
            else:
                repeats = [False] * 7
                for i in xrange(len(words[2:])):
                    if words[i + 2].lower() == 'mon':
                        repeats[0] = True
                    elif words[i + 2].lower() == 'tue':
                        repeats[1] = True
                    elif words[i + 2].lower() == 'wed':
                        repeats[2] = True
                    elif words[i + 2].lower() == 'thu':
                        repeats[3] = True
                    elif words[i + 2].lower() == 'fri':
                        repeats[4] = True
                    elif words[i + 2].lower() == 'sat':
                        repeats[5] = True
                    elif words[i + 2].lower() == 'sun':
                        repeats[6] = True
                    else:
                        print(('Repeat day "%s" not recognised,' %
                               words[i + 2]) +
                              ' use the "help edit" command for more info !')
                        return
            self.alarm_mgr.edit_alarm(alarm_id, days=repeats)
        else:
            # Invalid keyword
            print('Incorrect data provided, for information about this ' +
                  'command use the "help edit"\ncommand !')
            return

        # If this point has been reached, a success edit has been carried
        self.display_alarms()
        new_alarm = self.alarm_mgr.get_alarm(alarm_id)
        print(('Edited Alarm %s:\n' % alarm_id) + AlarmCli.dashes_line +
              ('\nOriginal:\n%s\n              | label: %s\n' %
               (original_alarm, original_alarm.label)) +
              ('\nNew:\n%s\n              | label: %s' %
               (new_alarm, new_alarm.label)))

    def do_delete(self, alarm_id_string):
        """
        Delete an alarm identified by its id, or all the alarms. E.g.:
        'delete 3'
        'delete all'
        """
        if alarm_id_string == 'all':
            success = self.alarm_mgr.delete_all_alarms()
            if success is True:
                print('All alarms have been deleted !')
        else:
            try:
                alarm_id = int(alarm_id_string)
            except ValueError:
                self.display_alarms()
                print('After "delete" there must be a number indicating ' +
                      'the Alarm ID to be deleted !')
                return
            alarm_string = str(AlarmManager.get_alarm(alarm_id))
            success = self.alarm_mgr.delete_alarm(alarm_id)
            if success is True:
                self.display_alarms()
                print('Alarm ID %s has been deleted:\n' % alarm_id +
                      AlarmCli.dashes_line + '\n%s' % alarm_string)

        if not success:
            self.display_alarms()
            print('Alarm/s "%s" could not be deleted.' % alarm_id_string)

    #
    # Settings command methods
    #
    def do_snooze(self, new_snooze_str):
        """Help snooze:
        Displays the currently set snooze time, or if accompanied by an integer
        it will change the snooze time and display the new value. E.g.:
        'snooze'
        'snooze 5'
        """
        snooze_text = 'Snooze time is:'
        if new_snooze_str:
            try:
                snooze_time = int(new_snooze_str)
            except ValueError:
                print('To edit the snooze time, the snooze command must be '
                      'followed a valid number !')
                return
            snooze_text = 'New snooze time is:'
            self.alarm_mgr.set_snooze_time(snooze_time)

        self.display_alarms()
        print(snooze_text + ' %s' % self.alarm_mgr.get_snooze_time())

    def do_offsetalert(self, new_offset_alert_str):
        """Help offsetalert:
        Displays the currently set offset alert time, (time before the alarm
        alert is triggered and used to launch any kind of process), or if
        accompanied by an integer it will change the offset alert time and
        display the new value. E.g.:
        'offsetalert'
        'offsetalert 5'
        'offsetalert -15'
        """
        offset_alert_text = 'Offset alert time is: '
        if new_offset_alert_str:
            try:
                new_offset_alert_str = int(new_offset_alert_str)
            except ValueError:
                print('To edit the offset alert time, the offsetalert command '
                      'must be followed a valid number !')
                return
            offset_alert_text = 'New offset alert time is: '
            self.alarm_mgr.set__offset_alert_time(new_offset_alert_str)

        self.display_alarms()
        print(offset_alert_text +
              '%s' % self.alarm_mgr.get_offset_alert_time())

    #
    # General command methods
    #
    def do_exit(self, empty_str):
        """ Exists the LightUp Alarm program. """
        self.display_alarms()
        return True

    def do_EOF(self, empty_str):
        """ Keyboard interrupt signal, exit program. """
        self.do_exit('')

    #
    # Command line interface methods
    #
    def show_header_only(self):
        """
        Clears the screen and displays the application header with next alarm.
        :return: All outputs for this method go straight to the stdout.
        """
        # First cleat the screen
        if os.name == 'nt':
            os.system("cls")
        else:
            os.system('clear')

        # Then print the header
        empty_line = '=                                       ' + \
                     '                                       =\n'
        print('========================================' +
              '========================================\n' + empty_line +
              '=                              LightUpPi' +
              ' Alarm                                 =')
        # If there are active alarms, print the next schedule time to alert
        next_alarm = self.alarm_mgr.get_next_alarm()
        if next_alarm is not None:
            print(empty_line + AlarmCli.dashes_line + '\n' + empty_line +
                  '=                   Next scheduled alert'
                  ' is for Alarm ID %3d                   =' % next_alarm.id_)
        print(empty_line + AlarmCli.dashes_line + '\n' + empty_line +
              '=    Use the "help" command for informat' +
              'ion about how to use this program.     =\n' +
              '=    This program must remain open for t' +
              'he alarms to be active and running.    =\n' + empty_line +
              '========================================' +
              '========================================')

        print('\n')  # Empty line for visual spacing

    def display_alarms(self):
        """
        Displays all the current alarms.
        :return: All outputs for this method go straight to the stdout
        """
        # And finally, display the alarms below the header
        all_alarms = self.alarm_mgr.get_all_alarms()
        print('All Alarms:\n' + AlarmCli.dashes_line)
        if not all_alarms:
            print('\tThere are not saved alarms.')
        else:
            for alarm in all_alarms:
                print(alarm)
        print('\n')  # Empty line for visual spacing

    #
    # callback method
    #
    def alarm_alert(self):
        """
        This is the default command line interface Alarm Alert function. It will
        be executed every time an alarm alert is triggered.
        """
        # Try to prevent re-entry
        while self.alert_running is True:
            time.sleep(float(random.randint(1, 100)) / 1000.0)
        # Should be safe now
        self.alert_running = True
        # '\a' is a request to the terminal to beep
        print('\n\nRING RING RING!!!!\a')
        print('\a')
        time.sleep(0.8)
        print('\a')
        time.sleep(0.8)
        print('\a')
        # print without a new line, using sys to work on python 2 and 3
        sys.stdout.write(self.prompt)
        self.alert_running = False
    def test_get_next_alarm(self, mock_time):
        """
        Creates 5 alarms with different settings. It then mocks the current time
        to get calculate the next alarm at different reference points.
        """
        alarm_mgr = AlarmManager()
        alarm_mgr.delete_all_alarms()
        alarm_mgr.add_alarm(11, 20, (True, False, False, False, False, False, False), True)
        alarm_mgr.add_alarm(11, 15, (True, False, False, False, False, False, False), True)

        #             year, mon, mday, hour, min, sec, wday, yday, isdst
        time_tuple = (2015, 0, 0, 12, 30, 00, 0, 0, 0)
        mock_time.return_value = time.struct_time(time_tuple)
        next_alarm = AlarmManager.get_next_alarm()
        self.assertEqual(next_alarm.id_, 2)

        #             year, mon, mday, hour, min, sec, wday, yday, isdst
        time_tuple = (2015, 0, 0, 11, 17, 00, 0, 0, 0)
        mock_time.return_value = time.struct_time(time_tuple)
        next_alarm = AlarmManager.get_next_alarm()
        self.assertEqual(next_alarm.id_, 1)

        self.create_alarms(alarm_mgr)

        #             year, mon, mday, hour, min, sec, wday, yday, isdst
        time_tuple = (2015, 0, 0, 19, 30, 00, 1, 0, 0)
        mock_time.return_value = time.struct_time(time_tuple)
        next_alarm = AlarmManager.get_next_alarm()
        self.assertEqual(next_alarm.id_, 2)

        #             year, mon, mday, hour, min, sec, wday, yday, isdst
        time_tuple = (2015, 0, 0, 13, 00, 00, 4, 0, 0)
        mock_time.return_value = time.struct_time(time_tuple)
        next_alarm = AlarmManager.get_next_alarm()
        self.assertEqual(next_alarm.id_, 4)

        #             year, mon, mday, hour, min, sec, wday, yday, isdst
        time_tuple = (2015, 0, 0, 21, 45, 00, 5, 0, 0)
        mock_time.return_value = time.struct_time(time_tuple)
        next_alarm = AlarmManager.get_next_alarm()
        self.assertEqual(next_alarm.id_, 3)

        #             year, mon, mday, hour, min, sec, wday, yday, isdst
        time_tuple = (2015, 0, 0, 11, 15, 00, 6, 0, 0)
        mock_time.return_value = time.struct_time(time_tuple)
        next_alarm = AlarmManager.get_next_alarm()
        self.assertEqual(next_alarm.id_, 3)
Example #37
0
    def test_get_next_alarm(self, mock_time):
        """
        Creates 5 alarms with different settings. It then mocks the current time
        to get calculate the next alarm at different reference points.
        """
        alarm_mgr = AlarmManager()
        alarm_mgr.delete_all_alarms()
        alarm_mgr.add_alarm(11, 20,
                            (True, False, False, False, False, False, False),
                            True)
        alarm_mgr.add_alarm(11, 15,
                            (True, False, False, False, False, False, False),
                            True)

        #             year, mon, mday, hour, min, sec, wday, yday, isdst
        time_tuple = (2015, 0, 0, 12, 30, 00, 0, 0, 0)
        mock_time.return_value = time.struct_time(time_tuple)
        next_alarm = AlarmManager.get_next_alarm()
        self.assertEqual(next_alarm.id_, 2)

        #             year, mon, mday, hour, min, sec, wday, yday, isdst
        time_tuple = (2015, 0, 0, 11, 17, 00, 0, 0, 0)
        mock_time.return_value = time.struct_time(time_tuple)
        next_alarm = AlarmManager.get_next_alarm()
        self.assertEqual(next_alarm.id_, 1)

        self.create_alarms(alarm_mgr)

        #             year, mon, mday, hour, min, sec, wday, yday, isdst
        time_tuple = (2015, 0, 0, 19, 30, 00, 1, 0, 0)
        mock_time.return_value = time.struct_time(time_tuple)
        next_alarm = AlarmManager.get_next_alarm()
        self.assertEqual(next_alarm.id_, 2)

        #             year, mon, mday, hour, min, sec, wday, yday, isdst
        time_tuple = (2015, 0, 0, 13, 00, 00, 4, 0, 0)
        mock_time.return_value = time.struct_time(time_tuple)
        next_alarm = AlarmManager.get_next_alarm()
        self.assertEqual(next_alarm.id_, 4)

        #             year, mon, mday, hour, min, sec, wday, yday, isdst
        time_tuple = (2015, 0, 0, 21, 45, 00, 5, 0, 0)
        mock_time.return_value = time.struct_time(time_tuple)
        next_alarm = AlarmManager.get_next_alarm()
        self.assertEqual(next_alarm.id_, 3)

        #             year, mon, mday, hour, min, sec, wday, yday, isdst
        time_tuple = (2015, 0, 0, 11, 15, 00, 6, 0, 0)
        mock_time.return_value = time.struct_time(time_tuple)
        next_alarm = AlarmManager.get_next_alarm()
        self.assertEqual(next_alarm.id_, 3)
    def test_check_threads_state(self):
        """ Test almost all pathways of check_threads_state. """
        alarm_mgr = AlarmManager()
        self.create_alarms(alarm_mgr)
        check_result = alarm_mgr.check_threads_state()
        self.assertTrue(check_result)

        # Now that everything is working correctly, sneak around AlarmManager
        # and edit a running thread by editing an AlarmItem using the
        # AlarmThread internal reference to the AlarmItem instance (which does
        # not do the extra checks for tracking like AlarmManager does).
        # Also edit the database entry for that alarm bypassing AlarmManager.
        alarm_bypass = alarm_mgr._AlarmManager__alarm_threads[0]._AlarmThread__alarm
        alarm_bypass.enabled = False
        alarm_id = alarm_bypass.id_
        AlarmDb().edit_alarm(alarm_id, enabled=False)
        check_result = alarm_mgr.check_threads_state()
        self.assertFalse(check_result)
        # Executing check_threads_state should have return false as there was
        # an issue, but if fixed correctly the second time should return true
        check_result = alarm_mgr.check_threads_state()
        self.assertTrue(check_result)

        # Now the thread for alarm 'alarm_bypass' with ID 'alarm_id' has been
        # stopped, we can bypass AlarmManager again to activate it and check
        # if check_threads_state recovers again.
        alarm_bypass.enabled = True
        AlarmDb().edit_alarm(alarm_bypass.id_, enabled=True)
        check_result = alarm_mgr.check_threads_state()
        self.assertFalse(check_result)
        check_result = alarm_mgr.check_threads_state()
        self.assertTrue(check_result)

        # Now that everything is working correctly once more, add extra thread
        alarm_test = AlarmItem(
            self.hour, 20, enabled=True, alarm_id=96, days=(True, True, True, True, True, True, True)
        )
        launch_success = alarm_mgr._AlarmManager__set_alarm_thread(alarm_test)
        self.assertTrue(launch_success)
        check_result = alarm_mgr.check_threads_state()
        self.assertFalse(check_result)
        check_result = alarm_mgr.check_threads_state()
        self.assertTrue(check_result)

        # Now we stop a running thread bypassing AlarmManager public methods
        alarm_mgr._AlarmManager__alarm_threads[0].stop()
        while alarm_mgr._AlarmManager__alarm_threads[0].isAlive():
            time.sleep(0.1)
        check_result = alarm_mgr.check_threads_state()
        self.assertFalse(check_result)
        check_result = alarm_mgr.check_threads_state()
        self.assertTrue(check_result)
Example #39
0
class AlarmCli(cmd.Cmd):
    """
    Command processor class to control LightUpAlarm.
    The Pydoc comments do not include the 'param' and 'return' data because
    the class uses these comments for the command line help menu.
    """
    # Class variable for a full line (80 chars) of dashes
    dashes_line = '----------------------------------------' + \
                  '----------------------------------------'

    #
    # metaclass methods
    #
    def __init__(self, alarm_mgr=None):
        """
        Instance initialiser.
        Attaches an AlarmManager instance, or creates a new one with the CLI
        default alarm alert callback.
        """
        cmd.Cmd.__init__(self)
        self.alert_running = False
        if alarm_mgr is None:
            self.alarm_mgr = AlarmManager(alert_callback=self.alarm_alert)
        else:
            self.alarm_mgr = alarm_mgr

    #
    # parent class methods and class variables
    #
    prompt = '(command): '
    doc_header = 'Available commands (for more info type "help <command>")'

    def preloop(self):
        """ Gets executed before the run loop. """
        self.show_header_only()
        self.display_alarms()

    def onecmd(self, s):
        """
        Parses and executes the command. Overwritten to added method to only
        show the header and current alarms at the top of the terminal and the
        current command output.
        """
        self.show_header_only()
        return cmd.Cmd.onecmd(self, s)

    def postcmd(self, stop, line):
        """
        Runs after the command is executed. Overwritten to add a couple of blank
        lines before the command input is displayed. Used for visual spacing.
        """
        print('\n')
        return cmd.Cmd.postcmd(self, stop, line)

    #
    # Alar command methods
    #
    def do_alarms(self, full_str):
        """Help alarms:
        Displays all the alarms.
        Use the keyword 'full' to display additional info.
        """
        if full_str == '':
            self.display_alarms()
        elif full_str == 'full':
            all_alarms = self.alarm_mgr.get_all_alarms()
            print('All Alarms:\n' + AlarmCli.dashes_line)
            if not all_alarms:
                print('\tThere are not saved alarms.')
            else:
                for alarm in all_alarms:
                    print('%s\n              | timestamp: %s      | label: %s\n'
                          % (alarm, alarm.timestamp, alarm.label))
        else:
            print('The only command that can follow alarms is "full"')

    def do_active(self, empty_str):
        """Help active:
        Displays the active alarms currently running.
        """
        self.display_alarms()
        running_alarms = self.alarm_mgr.get_running_alarms()
        print('Active Alarms running:\n' + AlarmCli.dashes_line)
        if not running_alarms:
            print('\tThere are not active alarms running.')
        else:
            for alarm in running_alarms:
                print(alarm)

    def do_next(self, empty_str):
        """Help next:
        Displays the next scheduled alarm to alert.
        """
        self.display_alarms()
        next_alarm = self.alarm_mgr.get_next_alarm()
        if next_alarm is not None:
            print('The next scheduled Alarm is:\n' + AlarmCli.dashes_line)
            print(next_alarm)
        else:
            print('\tThere are not active alarms running.')

    def do_add(self, alarm_str):
        """Help add:
        Add an alarm using the format (days follow the 3 letter format):
        'hh mm <enabled/disabled> <days to repeat>'
        e.g. 'add 9 00 enabled Mon Fri'
            'add 10 30 disabled sat sun'
            'add 7 10 enabled all'
            'add 22 55 disabled'
        """
        words = alarm_str.split(' ')
        # First check for enough items
        if len(words) < 2:
            print('Not enough data provided, for information about this ' +
                  'command use the "help add"\ncommand !')
            return

        # First word is the hour, mandatory
        try:
            hour = int(words[0])
        except ValueError:
            print('First item must be a number indicating the time !')
            return

        # Second word is the minute, mandatory
        try:
            minute = int(words[1])
        except ValueError:
            print('First item must be a number indicating the time !')
            return

        # Third word is the enable, optional
        if len(words) > 2:
            if words[2].lower() == 'enable' or words[2].lower() == 'enabled':
                enable = True
            elif words[2].lower() == 'disable' or \
                    words[2].lower() == 'disabled':
                enable = False
            else:
                print('Third item must indicate if the alarm will be ' +
                      '"enable" or "disabled" !')
                return
        else:
            # Defaults to enabled
            enable = True

        # Following words are the repeat days, optional
        if len(words) > 3:
            if words[3].lower() == 'all':
                repeats = (True, True, True, True, True, True, True)
            elif words[3].lower() == 'none':
                repeats = (False, False, False, False, False, False, False)
            else:
                repeats = [False] * 7
                for i in xrange(len(words[3:])):
                    if words[i+3].lower() == 'mon':
                        repeats[0] = True
                    elif words[i+3].lower() == 'tue':
                        repeats[1] = True
                    elif words[i+3].lower() == 'wed':
                        repeats[2] = True
                    elif words[i+3].lower() == 'thu':
                        repeats[3] = True
                    elif words[i+3].lower() == 'fri':
                        repeats[4] = True
                    elif words[i+3].lower() == 'sat':
                        repeats[5] = True
                    elif words[i+3].lower() == 'sun':
                        repeats[6] = True
                    else:
                        print(('Repeat day "%s" not recognised,' % words[i+3]) +
                              ' use the "help add" command for more info !')
                        return
        else:
            # Defaults to all days enabled
            repeats = (True, True, True, True, True, True, True)

        # Create the alarm and inform the user
        alarm_id = self.alarm_mgr.add_alarm(hour, minute, repeats, enable)
        if alarm_id is not None:
            self.display_alarms()
            print('Created Alarm:\n' + AlarmCli.dashes_line +
                  '\n%s' % AlarmManager.get_alarm(alarm_id))
        else:
            print('There was a problem creating the alarm.')

    def do_edit(self, edit_str):
        """Help edit command:
        Edit an alarm using the following format:
        'edit <alarm ID> <attribute> <new value>'
        e.g. 'edit 3 hour 9'
            'edit 4 minute 30'
            'edit 7 enabled no'
            'edit 1 repeat mon fri'
        """
        words = edit_str.split(' ')
        # First check for enough items
        if len(words) < 3:
            print('Not enough data provided, for information about this ' +
                  'command use the "help edit"\ncommand !')
            return

        # First word is the Alarm ID
        try:
            alarm_id = int(words[0])
        except ValueError:
            print('First item must be a the ID number of the alarm to edit!')
            return

        # Capture the original alarm, to check if it exits and later comparison
        original_alarm = self.alarm_mgr.get_alarm(alarm_id)
        if original_alarm is None:
            self.display_alarms()
            print('The Alarm with ID %s could not be found !' % alarm_id)
            return

        # Second word is the attribute to change, the third word parsed
        # immediately after each second word option.
        # Hours
        if words[1].lower() == 'hour' or words[2] == 'hours':
            try:
                hour = int(words[2])
            except ValueError:
                self.display_alarms()
                print('To edit the hour it must be followed a valid number !')
                return
            self.alarm_mgr.edit_alarm(alarm_id, hour=hour)
        # Minutes
        elif words[1].lower() == 'minute' or words[2] == 'minutes':
            try:
                minute = int(words[2])
            except ValueError:
                print('To edit the minute it must be followed a valid number !')
                return
            self.alarm_mgr.edit_alarm(alarm_id, minute=minute)
        # Enable
        elif words[1].lower() == 'enable' or words[1] == 'enabled':
            if words[2].lower() == 'yes':
                self.alarm_mgr.edit_alarm(alarm_id, enabled=True)
            elif words[2].lower() == 'no':
                self.alarm_mgr.edit_alarm(alarm_id, enabled=False)
            else:
                print('To edit the enable it must be followed by "yes" or ' +
                      '"No" !')
                return
        # Disable (should not really be an option, but accepted)
        elif words[1].lower() == 'disable' or words[1] == 'disabled':
            if words[2].lower() == 'yes':
                self.alarm_mgr.edit_alarm(alarm_id, enabled=False)
            elif words[2].lower() == 'no':
                self.alarm_mgr.edit_alarm(alarm_id, enabled=True)
            else:
                print('To edit the enable it must be followed by "yes" or ' +
                      '"No" !')
                return
        # Label
        elif words[1].lower() == 'label':
            label_str = ' '.join(str(x) for x in words[2:])
            self.alarm_mgr.edit_alarm(alarm_id, label=label_str)
        # Days
        elif words[1].lower() == 'repeat':
            if words[2].lower() == 'all':
                repeats = (True, True, True, True, True, True, True)
            elif words[2].lower() == 'none':
                repeats = (False, False, False, False, False, False, False)
            else:
                repeats = [False] * 7
                for i in xrange(len(words[2:])):
                    if words[i+2].lower() == 'mon':
                        repeats[0] = True
                    elif words[i+2].lower() == 'tue':
                        repeats[1] = True
                    elif words[i+2].lower() == 'wed':
                        repeats[2] = True
                    elif words[i+2].lower() == 'thu':
                        repeats[3] = True
                    elif words[i+2].lower() == 'fri':
                        repeats[4] = True
                    elif words[i+2].lower() == 'sat':
                        repeats[5] = True
                    elif words[i+2].lower() == 'sun':
                        repeats[6] = True
                    else:
                        print(('Repeat day "%s" not recognised,' % words[i+2]) +
                              ' use the "help edit" command for more info !')
                        return
            self.alarm_mgr.edit_alarm(alarm_id, days=repeats)
        else:
            # Invalid keyword
            print('Incorrect data provided, for information about this ' +
                  'command use the "help edit"\ncommand !')
            return

        # If this point has been reached, a success edit has been carried
        self.display_alarms()
        new_alarm = self.alarm_mgr.get_alarm(alarm_id)
        print(('Edited Alarm %s:\n' % alarm_id) + AlarmCli.dashes_line +
              ('\nOriginal:\n%s\n              | label: %s\n' %
               (original_alarm, original_alarm.label)) +
              ('\nNew:\n%s\n              | label: %s' %
               (new_alarm, new_alarm.label)))

    def do_delete(self, alarm_id_string):
        """
        Delete an alarm identified by its id, or all the alarms. E.g.:
        'delete 3'
        'delete all'
        """
        if alarm_id_string == 'all':
            success = self.alarm_mgr.delete_all_alarms()
            if success is True:
                print('All alarms have been deleted !')
        else:
            try:
                alarm_id = int(alarm_id_string)
            except ValueError:
                self.display_alarms()
                print('After "delete" there must be a number indicating ' +
                      'the Alarm ID to be deleted !')
                return
            alarm_string = str(AlarmManager.get_alarm(alarm_id))
            success = self.alarm_mgr.delete_alarm(alarm_id)
            if success is True:
                self.display_alarms()
                print('Alarm ID %s has been deleted:\n' % alarm_id +
                      AlarmCli.dashes_line + '\n%s' % alarm_string)

        if not success:
            self.display_alarms()
            print('Alarm/s "%s" could not be deleted.' % alarm_id_string)

    #
    # Settings command methods
    #
    def do_snooze(self, new_snooze_str):
        """Help snooze:
        Displays the currently set snooze time, or if accompanied by an integer
        it will change the snooze time and display the new value. E.g.:
        'snooze'
        'snooze 5'
        """
        snooze_text = 'Snooze time is:'
        if new_snooze_str:
            try:
                snooze_time = int(new_snooze_str)
            except ValueError:
                print('To edit the snooze time, the snooze command must be '
                      'followed a valid number !')
                return
            snooze_text = 'New snooze time is:'
            self.alarm_mgr.set_snooze_time(snooze_time)

        self.display_alarms()
        print(snooze_text + ' %s' % self.alarm_mgr.get_snooze_time())

    def do_offsetalert(self, new_offset_alert_str):
        """Help offsetalert:
        Displays the currently set offset alert time, (time before the alarm
        alert is triggered and used to launch any kind of process), or if
        accompanied by an integer it will change the offset alert time and
        display the new value. E.g.:
        'offsetalert'
        'offsetalert 5'
        'offsetalert -15'
        """
        offset_alert_text = 'Offset alert time is: '
        if new_offset_alert_str:
            try:
                new_offset_alert_str = int(new_offset_alert_str)
            except ValueError:
                print('To edit the offset alert time, the offsetalert command '
                      'must be followed a valid number !')
                return
            offset_alert_text = 'New offset alert time is: '
            self.alarm_mgr.set__offset_alert_time(new_offset_alert_str)

        self.display_alarms()
        print(offset_alert_text + '%s' % self.alarm_mgr.get_offset_alert_time())

    #
    # General command methods
    #
    def do_exit(self, empty_str):
        """ Exists the LightUp Alarm program. """
        self.display_alarms()
        return True

    def do_EOF(self, empty_str):
        """ Keyboard interrupt signal, exit program. """
        self.do_exit('')

    #
    # Command line interface methods
    #
    def show_header_only(self):
        """
        Clears the screen and displays the application header with next alarm.
        :return: All outputs for this method go straight to the stdout.
        """
        # First cleat the screen
        if os.name == 'nt':
            os.system("cls")
        else:
            os.system('clear')

        # Then print the header
        empty_line = '=                                       ' + \
                     '                                       =\n'
        print('========================================' +
              '========================================\n' + empty_line +
              '=                              LightUpPi' +
              ' Alarm                                 =')
        # If there are active alarms, print the next schedule time to alert
        next_alarm = self.alarm_mgr.get_next_alarm()
        if next_alarm is not None:
            print(empty_line + AlarmCli.dashes_line + '\n' + empty_line +
                  '=                   Next scheduled alert'
                  ' is for Alarm ID %3d                   =' % next_alarm.id_)
        print(empty_line + AlarmCli.dashes_line + '\n' + empty_line +
              '=    Use the "help" command for informat' +
              'ion about how to use this program.     =\n' +
              '=    This program must remain open for t' +
              'he alarms to be active and running.    =\n' + empty_line +
              '========================================' +
              '========================================')

        print('\n')  # Empty line for visual spacing

    def display_alarms(self):
        """
        Displays all the current alarms.
        :return: All outputs for this method go straight to the stdout
        """
        # And finally, display the alarms below the header
        all_alarms = self.alarm_mgr.get_all_alarms()
        print('All Alarms:\n' + AlarmCli.dashes_line)
        if not all_alarms:
            print('\tThere are not saved alarms.')
        else:
            for alarm in all_alarms:
                print(alarm)
        print('\n')  # Empty line for visual spacing

    #
    # callback method
    #
    def alarm_alert(self):
        """
        This is the default command line interface Alarm Alert function. It will
        be executed every time an alarm alert is triggered.
        """
        # Try to prevent re-entry
        while self.alert_running is True:
            time.sleep(float(random.randint(1, 100)) / 1000.0)
        # Should be safe now
        self.alert_running = True
        # '\a' is a request to the terminal to beep
        print('\n\nRING RING RING!!!!\a')
        print('\a')
        time.sleep(0.8)
        print('\a')
        time.sleep(0.8)
        print('\a')
        # print without a new line, using sys to work on python 2 and 3
        sys.stdout.write(self.prompt)
        self.alert_running = False
    def test_add_alarm_error(self):
        """
        Adds an alarm incorrectly and check for errors. The label variable
        cannot really be checked for errors as any input is converted into a
        string before it is saved.
        """
        alarm_mgr = AlarmManager()
        # We capture stderr to stop unit test from printing all errors
        # No need to check stderr as returning None is proof enough
        with mock.patch("sys.stderr", new=io.StringIO()) as test_srderr:
            # Test hour
            add_success = alarm_mgr.add_alarm(26, 0, (False, True, False, True, False, True, False), True)
            self.assertIsNone(add_success)
            add_success = alarm_mgr.add_alarm(22.5, 0, (False, True, False, True, False, True, False), True)
            self.assertIsNone(add_success)
            add_success = alarm_mgr.add_alarm("22", 0, (False, True, False, True, False, True, False), True)
            self.assertIsNone(add_success)
            add_success = alarm_mgr.add_alarm(-2, 0, (False, True, False, True, False, True, False), True)
            self.assertIsNone(add_success)

            # Test minute
            add_success = alarm_mgr.add_alarm(22, 60, (False, True, False, True, False, True, False), True)
            self.assertIsNone(add_success)
            add_success = alarm_mgr.add_alarm(22, 35.5, (False, True, False, True, False, True, False), True)
            self.assertIsNone(add_success)
            add_success = alarm_mgr.add_alarm(22, "25", (False, True, False, True, False, True, False), True)
            self.assertIsNone(add_success)
            add_success = alarm_mgr.add_alarm(22, -20, (False, True, False, True, False, True, False), True)
            self.assertIsNone(add_success)

            # Test days
            add_success = alarm_mgr.add_alarm(8, 30, (False, True, False, True, False, True, False, True), True)
            self.assertIsNone(add_success)
            add_success = alarm_mgr.add_alarm(8, 30, (False, True, False, True, False, True), True)
            self.assertIsNone(add_success)
            add_success = alarm_mgr.add_alarm(22, 0, (False, True, False, "True", False, True, False), True)
            self.assertIsNone(add_success)

            # Test enabled
            add_success = alarm_mgr.add_alarm(8, 30, (False, True, False, True, False, True, False), -1)
            self.assertIsNone(add_success)
            add_success = alarm_mgr.add_alarm(8, 30, (False, True, False, True, False, True, False), "3")
            self.assertIsNone(add_success)
            add_success = alarm_mgr.add_alarm(8, 30, (False, True, False, True, False, True, False), 2.3)
            self.assertIsNone(add_success)
Example #41
0
    def test_add_alarm_error(self):
        """
        Adds an alarm incorrectly and check for errors. The label variable
        cannot really be checked for errors as any input is converted into a
        string before it is saved.
        """
        alarm_mgr = AlarmManager()
        # We capture stderr to stop unit test from printing all errors
        # No need to check stderr as returning None is proof enough
        with mock.patch('sys.stderr', new=io.StringIO()) as test_srderr:
            # Test hour
            add_success = alarm_mgr.add_alarm(
                26, 0, (False, True, False, True, False, True, False), True)
            self.assertIsNone(add_success)
            add_success = alarm_mgr.add_alarm(
                22.5, 0, (False, True, False, True, False, True, False), True)
            self.assertIsNone(add_success)
            add_success = alarm_mgr.add_alarm(
                '22', 0, (False, True, False, True, False, True, False), True)
            self.assertIsNone(add_success)
            add_success = alarm_mgr.add_alarm(
                -2, 0, (False, True, False, True, False, True, False), True)
            self.assertIsNone(add_success)

            # Test minute
            add_success = alarm_mgr.add_alarm(
                22, 60, (False, True, False, True, False, True, False), True)
            self.assertIsNone(add_success)
            add_success = alarm_mgr.add_alarm(
                22, 35.5, (False, True, False, True, False, True, False), True)
            self.assertIsNone(add_success)
            add_success = alarm_mgr.add_alarm(
                22, '25', (False, True, False, True, False, True, False), True)
            self.assertIsNone(add_success)
            add_success = alarm_mgr.add_alarm(
                22, -20, (False, True, False, True, False, True, False), True)
            self.assertIsNone(add_success)

            # Test days
            add_success = alarm_mgr.add_alarm(
                8, 30, (False, True, False, True, False, True, False, True),
                True)
            self.assertIsNone(add_success)
            add_success = alarm_mgr.add_alarm(
                8, 30, (False, True, False, True, False, True), True)
            self.assertIsNone(add_success)
            add_success = alarm_mgr.add_alarm(
                22, 0, (False, True, False, 'True', False, True, False), True)
            self.assertIsNone(add_success)

            # Test enabled
            add_success = alarm_mgr.add_alarm(
                8, 30, (False, True, False, True, False, True, False), -1)
            self.assertIsNone(add_success)
            add_success = alarm_mgr.add_alarm(
                8, 30, (False, True, False, True, False, True, False), '3')
            self.assertIsNone(add_success)
            add_success = alarm_mgr.add_alarm(
                8, 30, (False, True, False, True, False, True, False), 2.3)
            self.assertIsNone(add_success)
Example #42
0
    def do_add(self, alarm_str):
        """Help add:
        Add an alarm using the format (days follow the 3 letter format):
        'hh mm <enabled/disabled> <days to repeat>'
        e.g. 'add 9 00 enabled Mon Fri'
            'add 10 30 disabled sat sun'
            'add 7 10 enabled all'
            'add 22 55 disabled'
        """
        words = alarm_str.split(' ')
        # First check for enough items
        if len(words) < 2:
            print('Not enough data provided, for information about this ' +
                  'command use the "help add"\ncommand !')
            return

        # First word is the hour, mandatory
        try:
            hour = int(words[0])
        except ValueError:
            print('First item must be a number indicating the time !')
            return

        # Second word is the minute, mandatory
        try:
            minute = int(words[1])
        except ValueError:
            print('First item must be a number indicating the time !')
            return

        # Third word is the enable, optional
        if len(words) > 2:
            if words[2].lower() == 'enable' or words[2].lower() == 'enabled':
                enable = True
            elif words[2].lower() == 'disable' or \
                    words[2].lower() == 'disabled':
                enable = False
            else:
                print('Third item must indicate if the alarm will be ' +
                      '"enable" or "disabled" !')
                return
        else:
            # Defaults to enabled
            enable = True

        # Following words are the repeat days, optional
        if len(words) > 3:
            if words[3].lower() == 'all':
                repeats = (True, True, True, True, True, True, True)
            elif words[3].lower() == 'none':
                repeats = (False, False, False, False, False, False, False)
            else:
                repeats = [False] * 7
                for i in xrange(len(words[3:])):
                    if words[i + 3].lower() == 'mon':
                        repeats[0] = True
                    elif words[i + 3].lower() == 'tue':
                        repeats[1] = True
                    elif words[i + 3].lower() == 'wed':
                        repeats[2] = True
                    elif words[i + 3].lower() == 'thu':
                        repeats[3] = True
                    elif words[i + 3].lower() == 'fri':
                        repeats[4] = True
                    elif words[i + 3].lower() == 'sat':
                        repeats[5] = True
                    elif words[i + 3].lower() == 'sun':
                        repeats[6] = True
                    else:
                        print(('Repeat day "%s" not recognised,' %
                               words[i + 3]) +
                              ' use the "help add" command for more info !')
                        return
        else:
            # Defaults to all days enabled
            repeats = (True, True, True, True, True, True, True)

        # Create the alarm and inform the user
        alarm_id = self.alarm_mgr.add_alarm(hour, minute, repeats, enable)
        if alarm_id is not None:
            self.display_alarms()
            print('Created Alarm:\n' + AlarmCli.dashes_line +
                  '\n%s' % AlarmManager.get_alarm(alarm_id))
        else:
            print('There was a problem creating the alarm.')