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_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_any_enabled_day(self): """ Test any_day_enabled() returns False if all repeats are false. """ test_alarm = AlarmItem( 9, 30, (True, False, False, True, False, False, True), True) self.assertTrue(test_alarm.any_day_enabled()) test_alarm.repeat = (False, False, False, False, False, False, False) self.assertFalse(test_alarm.any_day_enabled())
def add_alarm(self, hour, minute, days=(False, False, False, False, False, False, False), enabled=True, label='', timestamp=None): """ Adds an alarm to the database with the input values. If saved successfully it is sent to __set_alarm_thread to see if it should be launched as an enabled alarm thread. :param hour: Integer to indicate the alarm hour. :param minute: Integer to indicate the alarm minute. :param days: 7-item list of booleans to indicate repeat weekdays. :param enabled: Boolean to indicate the alarm enabled state. :param label: Strong to contain the alarm label. :param timestamp: Time, in seconds since 1970, that this alarm was last modified. This value can be added in order to be able to synchronise alarms between different systems. :return: Integer indicating the newly created alarm ID, or None if fail. """ alarm = AlarmItem(hour, minute, days=days, enabled=enabled, label=label, timestamp=timestamp) if alarm is not None: alarm.id_ = AlarmDb().add_alarm(alarm) if alarm.id_ is not None: self.__set_alarm_thread(alarm) return alarm.id_ return None
def add_alarm(self, hour, minute, days=(False, False, False, False, False, False, False), enabled=True, label='', timestamp=None): """ Adds an alarm to the database with the input values. If saved successfully it is sent to __set_alarm_thread to see if it should be launched as an enabled alarm thread. :param hour: Integer to indicate the alarm hour. :param minute: Integer to indicate the alarm minute. :param days: 7-item list of booleans to indicate repeat weekdays. :param enabled: Boolean to indicate the alarm enabled state. :param label: Strong to contain the alarm label. :param timestamp: Time, in seconds since 1970, that this alarm was last modified. This value can be added in order to be able to synchronise alarms between different systems. :return: Integer indicating the newly created alarm ID, or None if fail. """ alarm = AlarmItem( hour, minute, days=days, enabled=enabled, label=label, timestamp=timestamp) if alarm is not None: alarm.id_ = AlarmDb().add_alarm(alarm) if alarm.id_ is not None: self.__set_alarm_thread(alarm) return alarm.id_ return None
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)
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_edit_alarm(self): """ Creates an alarm and edits it. """ adh = AlarmDb(self.db_name) adh.delete_all_alarms() alarm_test = AlarmItem( 13, 35, days=(False, False, False, False, False, False, False), enabled=True, label='') # Check the timestamp changes on add_alarm original_timestamp = alarm_test.timestamp alarm_test.id_ = adh.add_alarm(alarm_test) self.assertNotEqual(alarm_test.timestamp, original_timestamp) # Edit alarm, check new data and different timestamp original_timestamp = alarm_test.timestamp time.sleep(1) edit_success = adh.edit_alarm( alarm_test.id_, 11, 22, enabled=False, label='New label', days=(True, True, True, True, True, True, True)) self.assertEqual(edit_success, True) edited_alarm = adh.get_alarm(alarm_test.id_) self.assertGreater(edited_alarm.timestamp, original_timestamp) self.assertEqual(edited_alarm.hour, 11) self.assertEqual(edited_alarm.minute, 22) self.assertTrue(edited_alarm.monday) self.assertTrue(edited_alarm.tuesday) self.assertTrue(edited_alarm.wednesday) self.assertTrue(edited_alarm.thursday) self.assertTrue(edited_alarm.friday) self.assertTrue(edited_alarm.saturday) self.assertTrue(edited_alarm.sunday) self.assertFalse(edited_alarm.enabled) self.assertEqual(edited_alarm.label, 'New label')
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_string_alarm(self): """ Checks the __str__ output is correct. """ test_alarm = AlarmItem( 9, 30, (True, False, False, True, False, False, True), True) test_alarm.id_ = 10 out = 'Alarm ID: 10 | Time: 09:30 | Enabled: Yes | Repeat: ' +\ 'Mon --- --- Thu --- --- Sun ' self.assertEqual(str(test_alarm), out)
def test_entry(self, mock_time): """ Adds an entry to the database and deletes it. """ hour = 13 minute = 35 mock_timestamp = 12341234 mock_time.return_value = mock_timestamp adh = AlarmDb(self.db_name) # Test an entry with the minimum amount of arguments and check for # default values test_alarm = AlarmItem(hour, minute) test_alarm.id_ = adh.add_alarm(test_alarm) # Test that the alarm object inserted has its member variable edited # with the new timestamp self.assertEqual(mock_timestamp, test_alarm.timestamp) # Check variables with a new alarm with data retrieved directly from db retrieved_alarm = adh.get_alarm(test_alarm.id_) self.assertEqual(hour, retrieved_alarm.hour) self.assertEqual(minute, retrieved_alarm.minute) self.assertEqual(test_alarm.monday, retrieved_alarm.monday) self.assertEqual(test_alarm.tuesday, retrieved_alarm.tuesday) self.assertEqual(test_alarm.wednesday, retrieved_alarm.wednesday) self.assertEqual(test_alarm.thursday, retrieved_alarm.thursday) self.assertEqual(test_alarm.friday, retrieved_alarm.friday) self.assertEqual(test_alarm.saturday, retrieved_alarm.saturday) self.assertEqual(test_alarm.sunday, retrieved_alarm.sunday) self.assertEqual(test_alarm.enabled, retrieved_alarm.enabled) self.assertEqual(test_alarm.label, retrieved_alarm.label) self.assertEqual(mock_timestamp, retrieved_alarm.timestamp) # Test with all possible arguments days = (False, False, True, False, False, True, False) enabled = False label = 'Test alarm label' timestamp = 98765432 test_alarm = AlarmItem( hour, minute, days=days, enabled=enabled, label=label, timestamp=timestamp) test_alarm.id_ = adh.add_alarm(test_alarm) # Check that the timestamp value from the alarm instance was not # modified with the present (in this case the mocked) timestamp self.assertEqual(timestamp, test_alarm.timestamp) # Check variables with a new alarm with data retrieved directly from db retrieved_alarm = adh.get_alarm(test_alarm.id_) self.assertEqual(hour, retrieved_alarm.hour) self.assertEqual(minute, retrieved_alarm.minute) self.assertEqual(days[0], retrieved_alarm.monday) self.assertEqual(days[1], retrieved_alarm.tuesday) self.assertEqual(days[2], retrieved_alarm.wednesday) self.assertEqual(days[3], retrieved_alarm.thursday) self.assertEqual(days[4], retrieved_alarm.friday) self.assertEqual(days[5], retrieved_alarm.saturday) self.assertEqual(days[6], retrieved_alarm.sunday) self.assertEqual(enabled, retrieved_alarm.enabled) self.assertEqual(label, retrieved_alarm.label) self.assertEqual(timestamp, retrieved_alarm.timestamp)
def test_run(self): """ Creates and alarm to trigger within a minute to instate AlarmThread, with an offset alert trigger of -1 minute. This test uses the member method AlarmManagerTestCase.c as the callback method. As the expected number of arguments is not 0, a TypeError is raised when executed, proving that the run method triggers on the alarm time and executes the callback. This test can take a little over 10 seconds in its worse case scenario. """ def good_callback(): pass def bad_callback(one, two, three): """ Does nothing, but because it's it expects several argument it will throw an exception if they are not provided. """ pass # Set alarm for current minute, but only if there is at least 10seconds # 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_thread = AlarmThread(AlarmItem(time_now.tm_hour, time_now.tm_min, enabled=True, alarm_id=96, days=(True, True, True, True, True, True, True)), alarm_callback=bad_callback, offset_alarm_time=-1, offset_callback=good_callback) self.assertRaises(TypeError, alarm_thread.run) alarm_thread.stop() # This time test the pre/post alert time_now = time.localtime(time.time()) while time_now.tm_sec > 50: time.sleep(1) time_now = time.localtime(time.time()) alarm_time = datetime.now() + timedelta(minutes=1) alarm_thread = AlarmThread(AlarmItem(alarm_time.hour, alarm_time.minute, enabled=True, alarm_id=97, days=(True, True, True, True, True, True, True)), alarm_callback=good_callback, offset_alarm_time=-1, offset_callback=bad_callback) self.assertRaises(TypeError, alarm_thread.run)
def test_edit_alarm_single(self): """ Adds an alarm, edits a single value and checks all the others remain the same. """ adh = AlarmDb(self.db_name) alarm_test = AlarmItem( 13, 35, enabled=True, label='yes', days=(True, False, True, False, True, False, True)) # Check the timestamp changes on add_alarm original_timestamp = alarm_test.timestamp alarm_test.id_ = adh.add_alarm(alarm_test) self.assertNotEqual(alarm_test.timestamp, original_timestamp) # Edit alarm, check new data and different timestamp original_timestamp = alarm_test.timestamp time.sleep(1) edit_success = adh.edit_alarm(alarm_test.id_, minute=0) self.assertTrue(edit_success) edited_alarm = adh.get_alarm(alarm_test.id_) self.assertGreater(edited_alarm.timestamp, original_timestamp) self.assertEqual(edited_alarm.hour, 13) self.assertEqual(edited_alarm.minute, 0) self.assertTrue(edited_alarm.monday) self.assertFalse(edited_alarm.tuesday) self.assertTrue(edited_alarm.wednesday) self.assertFalse(edited_alarm.thursday) self.assertTrue(edited_alarm.friday) self.assertFalse(edited_alarm.saturday) self.assertTrue(edited_alarm.sunday) self.assertTrue(edited_alarm.enabled) self.assertEqual(edited_alarm.label, 'yes') # Test with opposite initial values alarm_test = AlarmItem( 10, 20, enabled=False, label='no', days=(False, True, False, True, False, True, False)) alarm_test.id_ = adh.add_alarm(alarm_test) edit_success = adh.edit_alarm(alarm_test.id_, hour=0) self.assertTrue(edit_success) edited_alarm = adh.get_alarm(alarm_test.id_) self.assertEqual(edited_alarm.hour, 0) self.assertEqual(edited_alarm.minute, 20) self.assertFalse(edited_alarm.monday) self.assertTrue(edited_alarm.tuesday) self.assertFalse(edited_alarm.wednesday) self.assertTrue(edited_alarm.thursday) self.assertFalse(edited_alarm.friday) self.assertTrue(edited_alarm.saturday) self.assertFalse(edited_alarm.sunday) self.assertFalse(edited_alarm.enabled) self.assertEqual(edited_alarm.label, 'no')
def test_hour_min_loop_range(self): """ Test setting the hours and minutes accessors to not change values with invalid inputs. """ alarm_test = AlarmItem(0, 1) # The accessor functions print to stderr if bad data is encountered, so # we need to capture stderr to test it. with mock.patch('sys.stderr', new=io.StringIO()) as test_srderr: self.assertEqual(test_srderr.getvalue(), '') alarm_test.hour = 12 alarm_test.minute = 34 self.assertEqual(alarm_test.hour, 12) self.assertEqual(alarm_test.minute, 34) self.assert_stderr(test_srderr, equal=True) # Invalid ints alarm_test.minute = 60 self.assert_stderr(test_srderr) alarm_test.minute = -1 self.assert_stderr(test_srderr) self.assertEqual(alarm_test.minute, 34) alarm_test.hour = 24 self.assert_stderr(test_srderr) alarm_test.hour = -2 self.assert_stderr(test_srderr) self.assertEqual(alarm_test.hour, 12) self.assertEqual(alarm_test.hour, 12) self.assertEqual(alarm_test.minute, 34)
def test_hour_min_integers(self): """ Test setting the hours and minutes values valid integers and non-integer values. """ alarm_test = AlarmItem(0, 0) # The accessor functions print to stderr if bad data is encountered, so # we need to capture stderr to test it. with mock.patch('sys.stderr', new=io.StringIO()) as test_srderr: # First ensure that successful set does not write to stderr self.assertEqual(test_srderr.getvalue(), '') alarm_test.hour = 12 alarm_test.minute = 34 self.assert_stderr(test_srderr, equal=True) # Float instead of integer alarm_test.hour = 12.34 self.assert_stderr(test_srderr) alarm_test.minute = 34.56 self.assert_stderr(test_srderr) # String instead of integer alarm_test.hour = 'minutes' self.assert_stderr(test_srderr) alarm_test.minute = 'hours' self.assert_stderr(test_srderr) self.assertEqual(alarm_test.hour, 12) self.assertEqual(alarm_test.minute, 34)
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_edit_alarm(self): """ Tests the edit_alarm() method. """ # Carefully select the minutes to be different and > |offset_time| offset_minutes = -15 old_minute = 35 new_minute = 20 alarm_test = AlarmItem(9, old_minute, enabled=False, alarm_id=36, days=(True, True, True, True, True, True, True)) new_alarm = AlarmItem(9, new_minute, enabled=False, alarm_id=96, days=(True, True, True, True, True, True, True)) alarm_thread = AlarmThread( alarm_test, alarm_callback=AlarmThreadTestCase.empty_callback, offset_alarm_time=offset_minutes) self.assertIs(alarm_thread._AlarmThread__alarm, alarm_test) # The edit_alarm method prints to stderr if wrong alarm if input, so # we need to capture stderr to test it. with mock.patch('sys.stderr', new=io.StringIO()) as test_srderr: # Test with wrong ID self.assertEqual(test_srderr.getvalue(), '') alarm_thread.edit_alarm(new_alarm) self.assertNotEqual(test_srderr.getvalue(), '') self.assertIsNot(alarm_thread._AlarmThread__alarm, new_alarm) # Check the offset alert has not been updated self.assertEqual(alarm_thread._AlarmThread__offset_alarm.minute, old_minute + offset_minutes) # Test with correct ID new_alarm.id_ = 36 test_srderr.truncate(0) test_srderr.write('') self.assertEqual(test_srderr.getvalue(), '') alarm_thread.edit_alarm(new_alarm) self.assertEqual(test_srderr.getvalue(), '') self.assertIs(alarm_thread._AlarmThread__alarm, new_alarm) # Check the offset alert has also been updated self.assertEqual(alarm_thread._AlarmThread__offset_alarm.minute, new_minute + offset_minutes)
def test_update_alarm(self): """ Creates an alarm and update it. """ adh = AlarmDb(self.db_name) adh.delete_all_alarms() alarm_test = AlarmItem(13, 35, days=(False, False, False, False, False, False, False), enabled=True, label='') original_timestamp = alarm_test.timestamp # Add the alarm to the database and check the timestamp has been set alarm_test.id_ = adh.add_alarm(alarm_test) self.assertNotEqual(alarm_test.timestamp, original_timestamp) original_timestamp = alarm_test.timestamp # Create a new AlarmItem with the same id and timestamp to update the db alarm_updated = AlarmItem(21, 12, days=(True, True, True, True, True, True, True), enabled=False, label='new label', alarm_id=alarm_test.id_, timestamp=original_timestamp) time.sleep(1) update_success = adh.update_alarm(alarm_updated) self.assertEqual(update_success, True) self.assertNotEqual(alarm_updated.timestamp, original_timestamp) # Check the new data has replaced the old, retrieved_alarm = adh.get_alarm(alarm_test.id_) self.assertEqual(retrieved_alarm.hour, 21) self.assertEqual(retrieved_alarm.minute, 12) self.assertTrue(retrieved_alarm.monday) self.assertTrue(retrieved_alarm.tuesday) self.assertTrue(retrieved_alarm.wednesday) self.assertTrue(retrieved_alarm.thursday) self.assertTrue(retrieved_alarm.friday) self.assertTrue(retrieved_alarm.saturday) self.assertTrue(retrieved_alarm.sunday) self.assertFalse(retrieved_alarm.enabled) self.assertEqual(retrieved_alarm.label, 'new label') self.assertEqual(retrieved_alarm.timestamp, alarm_updated.timestamp) self.assertGreater(retrieved_alarm.timestamp, original_timestamp)
def test_timestamp(self): """ Tests the timetstamp member variable accessors filters non-integers. """ alarm_test = AlarmItem(0, 0) alarm_test.timestamp = 1427486989 self.assertEqual(alarm_test.timestamp, 1427486989) # The accessor setter prints to stderr if bad data is encountered, so # we need to capture stderr to test it. with mock.patch('sys.stderr', new=io.StringIO()) as test_srderr: # First ensure that successful set does not write to stderr self.assertEqual(test_srderr.getvalue(), '') alarm_test.timestamp = 10 self.assertEqual(test_srderr.getvalue(), '') self.assertEqual(alarm_test.timestamp, 10) # Negative integer instead of positive integer alarm_test.timestamp = -2 self.assertEqual(alarm_test.timestamp, 10) self.assert_stderr(test_srderr) # String instead of integer alarm_test.timestamp = 'String' self.assertEqual(alarm_test.timestamp, 10) self.assert_stderr(test_srderr) # Float instead of integer alarm_test.timestamp = 10.4 self.assertEqual(alarm_test.timestamp, 10) self.assert_stderr(test_srderr)
def test_repeat_accessors_get(self): """ Sets the repeat list at the constructor and variable level, and test that all the individual accessors for each day of the week works correctly. """ days = [False, True, True, False, True, False, True] # Test constructor input alarm_test = AlarmItem(0, 0, days, False) self.assertEqual(alarm_test.repeat, tuple(days)) self.assert_repeat(alarm_test, days) # Test repeat accesor with opposite repeat list for i in xrange(len(days)): days[i] = not days[i] alarm_test.repeat = days self.assertEqual(alarm_test.repeat, tuple(days)) self.assert_repeat(alarm_test, days)
def test_get_id(self): """ Tests the get_id() method. """ alarm_test = AlarmItem(9, 34, enabled=False, alarm_id=36, days=(True, True, True, True, True, True, True)) alarm_thread = AlarmThread( alarm_test, alarm_callback=AlarmThreadTestCase.empty_callback) self.assertEqual(alarm_thread.get_id(), alarm_test.id_)
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)
def test_get_all_enable_alarms(self): """ Adds 5 alarms into the database, 3 enabled and 2 disabled. Checks the enabled and disabled getters are working. """ adh = AlarmDb(self.db_name) adh.delete_all_alarms() adh.add_alarm(AlarmItem(13, 35, days=self.random_days, enabled=True)) # id 1 adh.add_alarm(AlarmItem(14, 36, days=self.random_days, enabled=False)) # id 2 adh.add_alarm(AlarmItem(15, 37, days=self.random_days, enabled=True)) # id 3 adh.add_alarm(AlarmItem(16, 38, days=self.random_days, enabled=False)) # id 4 adh.add_alarm(AlarmItem(17, 39, days=self.random_days, enabled=True)) # id 5 enabled_alarms = adh.get_all_enabled_alarms() disabled_alarms = adh.get_all_disabled_alarms() self.assertEqual(len(enabled_alarms), 3) self.assertEqual(len(disabled_alarms), 2)
def test_label(self): """ Tests the label variable accessors and its string coversion. """ alarm_test = AlarmItem(0, 0) label = 'Alarm test label' # The accessor setter prints to stderr if bad data is encountered, so # we need to capture stderr to test it. with mock.patch('sys.stderr', new=io.StringIO()) as test_srderr: # First ensure that successful set does not write to stderr self.assertEqual(test_srderr.getvalue(), '') alarm_test.label = label self.assertEqual(label, alarm_test.label) self.assertEqual(test_srderr.getvalue(), '') # Try other types alarm_test.label = 5 self.assertEqual('5', alarm_test.label) self.assertEqual(test_srderr.getvalue(), '') alarm_test.label = True self.assertEqual('True', alarm_test.label) self.assertEqual(test_srderr.getvalue(), '') alarm_test.label = {'test': 5} self.assertEqual("{u'test': 5}", alarm_test.label) self.assertEqual(test_srderr.getvalue(), '')
def test_constructor_hour_min_range(self): """ Test constructor values for hours and minutes to produce a None object if they are larger than 23 and 59 respectively. """ # The accessor functions print to stderr if bad data is encountered, so # we need to capture stderr to test it. with mock.patch('sys.stderr', new=io.StringIO()) as test_srderr: # Invalid minute self.assertEqual(test_srderr.getvalue(), '') alarm_test = AlarmItem(23, 60) self.assertIsNone(alarm_test) self.assert_stderr(test_srderr) alarm_test = AlarmItem(23, -50) self.assertIsNone(alarm_test) self.assert_stderr(test_srderr) # Invalid hour alarm_test = AlarmItem(24, 59) self.assertIsNone(alarm_test) self.assert_stderr(test_srderr) alarm_test = AlarmItem(-12, 59) self.assertIsNone(alarm_test) self.assert_stderr(test_srderr) # Invalid hour and minute alarm_test = AlarmItem(24, 60) self.assertIsNone(alarm_test) self.assert_stderr(test_srderr) alarm_test = AlarmItem(-16, -45) self.assertIsNone(alarm_test) self.assert_stderr(test_srderr)
def test_edit_alarm(self): """ Creates an alarm and edits it. """ adh = AlarmDb(self.db_name) adh.delete_all_alarms() alarm_test = AlarmItem(13, 35, days=(False, False, False, False, False, False, False), enabled=True, label='') # Check the timestamp changes on add_alarm original_timestamp = alarm_test.timestamp alarm_test.id_ = adh.add_alarm(alarm_test) self.assertNotEqual(alarm_test.timestamp, original_timestamp) # Edit alarm, check new data and different timestamp original_timestamp = alarm_test.timestamp time.sleep(1) edit_success = adh.edit_alarm(alarm_test.id_, 11, 22, enabled=False, label='New label', days=(True, True, True, True, True, True, True)) self.assertEqual(edit_success, True) edited_alarm = adh.get_alarm(alarm_test.id_) self.assertGreater(edited_alarm.timestamp, original_timestamp) self.assertEqual(edited_alarm.hour, 11) self.assertEqual(edited_alarm.minute, 22) self.assertTrue(edited_alarm.monday) self.assertTrue(edited_alarm.tuesday) self.assertTrue(edited_alarm.wednesday) self.assertTrue(edited_alarm.thursday) self.assertTrue(edited_alarm.friday) self.assertTrue(edited_alarm.saturday) self.assertTrue(edited_alarm.sunday) self.assertFalse(edited_alarm.enabled) self.assertEqual(edited_alarm.label, 'New label')
def test_constructor(self): """ Tests the class constructor. """ alarm_test = AlarmItem(9, 34, enabled=False, alarm_id=96, days=(True, True, True, True, True, True, True)) # With minimum parameters alarm_thread = AlarmThread(alarm_test) self.assertIs(alarm_thread._AlarmThread__alarm, alarm_test) self.assertFalse(alarm_thread._AlarmThread__offset_flag) # With minimum parameters + callback alarm_thread = AlarmThread( alarm_test, alarm_callback=AlarmThreadTestCase.empty_callback) self.assertIs(alarm_thread._AlarmThread__alarm, alarm_test) self.assertIs(alarm_thread._AlarmThread__alarm_callback, AlarmThreadTestCase.empty_callback) self.assertFalse(alarm_thread._AlarmThread__offset_flag) # With minimum parameters + callback + offset alarm_thread = AlarmThread( alarm_test, alarm_callback=AlarmThreadTestCase.empty_callback, offset_alarm_time=15) self.assertIs(alarm_thread._AlarmThread__alarm, alarm_test) self.assertIs(alarm_thread._AlarmThread__alarm_callback, AlarmThreadTestCase.empty_callback) self.assertEqual(alarm_thread._AlarmThread__offset_time, 15) self.assertTrue(alarm_thread._AlarmThread__offset_flag) self.assertIsNotNone(alarm_thread._AlarmThread__offset_alarm) # With minimum parameters + callback + offset + offset callback alarm_thread = AlarmThread( alarm_test, alarm_callback=AlarmThreadTestCase.empty_callback, offset_callback=AlarmThreadTestCase.empty_callback, offset_alarm_time=15) self.assertIs(alarm_thread._AlarmThread__alarm, alarm_test) self.assertIs(alarm_thread._AlarmThread__alarm_callback, AlarmThreadTestCase.empty_callback) self.assertEqual(alarm_thread._AlarmThread__offset_time, 15) self.assertTrue(alarm_thread._AlarmThread__offset_flag) self.assertIsNotNone(alarm_thread._AlarmThread__offset_alarm) self.assertIs(alarm_thread._AlarmThread__offset_callback, AlarmThreadTestCase.empty_callback) # Incorrect offset_alarm_time alarm_thread = AlarmThread(alarm_test, offset_alarm_time="5") self.assertIs(alarm_thread._AlarmThread__alarm, alarm_test) self.assertFalse(alarm_thread._AlarmThread__offset_flag) self.assertIsNone(alarm_thread._AlarmThread__offset_alarm)
def test_entry(self, mock_time): """ Adds an entry to the database and deletes it. """ hour = 13 minute = 35 mock_timestamp = 12341234 mock_time.return_value = mock_timestamp adh = AlarmDb(self.db_name) # Test an entry with the minimum amount of arguments and check for # default values test_alarm = AlarmItem(hour, minute) test_alarm.id_ = adh.add_alarm(test_alarm) # Test that the alarm object inserted has its member variable edited # with the new timestamp self.assertEqual(mock_timestamp, test_alarm.timestamp) # Check variables with a new alarm with data retrieved directly from db retrieved_alarm = adh.get_alarm(test_alarm.id_) self.assertEqual(hour, retrieved_alarm.hour) self.assertEqual(minute, retrieved_alarm.minute) self.assertEqual(test_alarm.monday, retrieved_alarm.monday) self.assertEqual(test_alarm.tuesday, retrieved_alarm.tuesday) self.assertEqual(test_alarm.wednesday, retrieved_alarm.wednesday) self.assertEqual(test_alarm.thursday, retrieved_alarm.thursday) self.assertEqual(test_alarm.friday, retrieved_alarm.friday) self.assertEqual(test_alarm.saturday, retrieved_alarm.saturday) self.assertEqual(test_alarm.sunday, retrieved_alarm.sunday) self.assertEqual(test_alarm.enabled, retrieved_alarm.enabled) self.assertEqual(test_alarm.label, retrieved_alarm.label) self.assertEqual(mock_timestamp, retrieved_alarm.timestamp) # Test with all possible arguments days = (False, False, True, False, False, True, False) enabled = False label = 'Test alarm label' timestamp = 98765432 test_alarm = AlarmItem(hour, minute, days=days, enabled=enabled, label=label, timestamp=timestamp) test_alarm.id_ = adh.add_alarm(test_alarm) # Check that the timestamp value from the alarm instance was not # modified with the present (in this case the mocked) timestamp self.assertEqual(timestamp, test_alarm.timestamp) # Check variables with a new alarm with data retrieved directly from db retrieved_alarm = adh.get_alarm(test_alarm.id_) self.assertEqual(hour, retrieved_alarm.hour) self.assertEqual(minute, retrieved_alarm.minute) self.assertEqual(days[0], retrieved_alarm.monday) self.assertEqual(days[1], retrieved_alarm.tuesday) self.assertEqual(days[2], retrieved_alarm.wednesday) self.assertEqual(days[3], retrieved_alarm.thursday) self.assertEqual(days[4], retrieved_alarm.friday) self.assertEqual(days[5], retrieved_alarm.saturday) self.assertEqual(days[6], retrieved_alarm.sunday) self.assertEqual(enabled, retrieved_alarm.enabled) self.assertEqual(label, retrieved_alarm.label) self.assertEqual(timestamp, retrieved_alarm.timestamp)
def only_five_entries(self, alarm_db): """ Removes all rows and adds 5 entries into the input alarm database. :param alarm_db: AlarmDb instance to add entries No return as the mutable argument changes remain after exit """ alarm_db.delete_all_alarms() alarm_db.add_alarm( AlarmItem(13, 35, days=self.random_days, enabled=False, label='')) # id 1 alarm_db.add_alarm( AlarmItem(14, 36, days=self.random_days, enabled=False, label='')) # id 2 alarm_db.add_alarm( AlarmItem(15, 37, days=self.random_days, enabled=False, label='')) # id 3 alarm_db.add_alarm( AlarmItem(16, 38, days=self.random_days, enabled=False, label='')) # id 4 alarm_db.add_alarm( AlarmItem(17, 39, days=self.random_days, enabled=False, label='')) # id 5
def test_edit_alarm_single(self): """ Adds an alarm, edits a single value and checks all the others remain the same. """ adh = AlarmDb(self.db_name) alarm_test = AlarmItem(13, 35, enabled=True, label='yes', days=(True, False, True, False, True, False, True)) # Check the timestamp changes on add_alarm original_timestamp = alarm_test.timestamp alarm_test.id_ = adh.add_alarm(alarm_test) self.assertNotEqual(alarm_test.timestamp, original_timestamp) # Edit alarm, check new data and different timestamp original_timestamp = alarm_test.timestamp time.sleep(1) edit_success = adh.edit_alarm(alarm_test.id_, minute=0) self.assertTrue(edit_success) edited_alarm = adh.get_alarm(alarm_test.id_) self.assertGreater(edited_alarm.timestamp, original_timestamp) self.assertEqual(edited_alarm.hour, 13) self.assertEqual(edited_alarm.minute, 0) self.assertTrue(edited_alarm.monday) self.assertFalse(edited_alarm.tuesday) self.assertTrue(edited_alarm.wednesday) self.assertFalse(edited_alarm.thursday) self.assertTrue(edited_alarm.friday) self.assertFalse(edited_alarm.saturday) self.assertTrue(edited_alarm.sunday) self.assertTrue(edited_alarm.enabled) self.assertEqual(edited_alarm.label, 'yes') # Test with opposite initial values alarm_test = AlarmItem(10, 20, enabled=False, label='no', days=(False, True, False, True, False, True, False)) alarm_test.id_ = adh.add_alarm(alarm_test) edit_success = adh.edit_alarm(alarm_test.id_, hour=0) self.assertTrue(edit_success) edited_alarm = adh.get_alarm(alarm_test.id_) self.assertEqual(edited_alarm.hour, 0) self.assertEqual(edited_alarm.minute, 20) self.assertFalse(edited_alarm.monday) self.assertTrue(edited_alarm.tuesday) self.assertFalse(edited_alarm.wednesday) self.assertTrue(edited_alarm.thursday) self.assertFalse(edited_alarm.friday) self.assertTrue(edited_alarm.saturday) self.assertFalse(edited_alarm.sunday) self.assertFalse(edited_alarm.enabled) self.assertEqual(edited_alarm.label, 'no')
def test_update_alarm(self): """ Creates an alarm and update it. """ adh = AlarmDb(self.db_name) adh.delete_all_alarms() alarm_test = AlarmItem( 13, 35, days=(False, False, False, False, False, False, False), enabled=True, label='') original_timestamp = alarm_test.timestamp # Add the alarm to the database and check the timestamp has been set alarm_test.id_ = adh.add_alarm(alarm_test) self.assertNotEqual(alarm_test.timestamp, original_timestamp) original_timestamp = alarm_test.timestamp # Create a new AlarmItem with the same id and timestamp to update the db alarm_updated = AlarmItem( 21, 12, days=(True, True, True, True, True, True, True), enabled=False, label='new label', alarm_id=alarm_test.id_, timestamp=original_timestamp) time.sleep(1) update_success = adh.update_alarm(alarm_updated) self.assertEqual(update_success, True) self.assertNotEqual(alarm_updated.timestamp, original_timestamp) # Check the new data has replaced the old, retrieved_alarm = adh.get_alarm(alarm_test.id_) self.assertEqual(retrieved_alarm.hour, 21) self.assertEqual(retrieved_alarm.minute, 12) self.assertTrue(retrieved_alarm.monday) self.assertTrue(retrieved_alarm.tuesday) self.assertTrue(retrieved_alarm.wednesday) self.assertTrue(retrieved_alarm.thursday) self.assertTrue(retrieved_alarm.friday) self.assertTrue(retrieved_alarm.saturday) self.assertTrue(retrieved_alarm.sunday) self.assertFalse(retrieved_alarm.enabled) self.assertEqual(retrieved_alarm.label, 'new label') self.assertEqual(retrieved_alarm.timestamp, alarm_updated.timestamp) self.assertGreater(retrieved_alarm.timestamp, original_timestamp)
def get_all_alarms(self): """ Returns all the alarms in a list of AlarmItems. :return: List of AlarmItems containing all alarms. Returns an empty list if there aren't any. """ alarms_table = self.__connect_alarms() alarm_list = [] for alarm in alarms_table: alarm_list.append( AlarmItem(alarm['hour'], alarm['minute'], days=(alarm['monday'], alarm['tuesday'], alarm['wednesday'], alarm['thursday'], alarm['friday'], alarm['saturday'], alarm['sunday']), enabled=alarm['enabled'], label=alarm['label'], timestamp=alarm['timestamp'], alarm_id=alarm['id'])) return alarm_list
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 get_alarm(self, alarm_id): """ Get the alarm with the given ID from the database. :param alarm_id: Integer to indicate the primary key of the row to get. :return: AlarmItem with the alarm data, or None if id could not be found. """ alarms_table = self.__connect_alarms() alarm_dict = alarms_table.find_one(id=alarm_id) if alarm_dict is None: return None else: return AlarmItem( alarm_dict['hour'], alarm_dict['minute'], days=(alarm_dict['monday'], alarm_dict['tuesday'], alarm_dict['wednesday'], alarm_dict['thursday'], alarm_dict['friday'], alarm_dict['saturday'], alarm_dict['sunday']), enabled=alarm_dict['enabled'], label=alarm_dict['label'], timestamp=alarm_dict['timestamp'], alarm_id=alarm_dict['id'])
def test_repeat_list_strictness(self): """ Test that the repeat list of booleans is filtered and catches invalid inputs. Including lists of not booleans, and boolean lists with and incorrect number of items. """ alarm_test = AlarmItem(0, 0) valid_days = (False, True, True, False, False, False, False) # Setting a valid value self.assertNotEqual(valid_days, alarm_test.repeat) alarm_test.repeat = valid_days self.assertEqual(valid_days, alarm_test.repeat) # The accessor functions print to stderr if bad data is encountered, so # we need to capture stderr to test it. with mock.patch('sys.stderr', new=io.StringIO()) as test_srderr: # First ensure that successful set does not write to stderr self.assertEqual(test_srderr.getvalue(), '') alarm_test.repeat = valid_days self.assertEqual(alarm_test.repeat, valid_days) self.assertEqual(test_srderr.getvalue(), '') # Too many arguments alarm_test.repeat = ( False, False, False, False, False, False, False, False) self.assert_stderr(test_srderr) self.assertEqual(alarm_test.repeat, valid_days) # Too few arguments alarm_test.repeat = (True, True, True, True, True, True) self.assert_stderr(test_srderr) self.assertEqual(alarm_test.repeat, valid_days) # Wrong arguments alarm_test.repeat = (True, True, True, 0, True, True, True) self.assert_stderr(test_srderr) self.assertEqual(alarm_test.repeat, valid_days)
def test_constructor(self): """ Tests valid inputs to the constructor. """ id_ = 265 hour = 23 minute = 59 days = (False, True, True, False, False, False, False) label = 'Alarm label' timestamp = 12345678 # Check constructor with minimum arguments alarm_test = AlarmItem(hour, minute) self.assertEqual(hour, alarm_test.hour) self.assertEqual(minute, alarm_test.minute) for day in alarm_test.repeat: self.assertEqual(alarm_test.repeat[day], False) self.assertEqual(alarm_test.label, '') self.assertIsNone(alarm_test.timestamp) # Check constructor with minimum arguments + repeat days alarm_test = AlarmItem(hour, minute, days=days) self.assertEqual(days, alarm_test.repeat) # Check constructor with minimum arguments + repeat days + enabled alarm_test = AlarmItem(hour, minute, days=days, enabled=False) self.assertEqual(False, alarm_test.enabled) # Check constructor with minimum arguments + repeat days + enabled + # label alarm_test = AlarmItem( hour, minute, days=days, enabled=False, label=label) self.assertEqual(label, alarm_test.label) # Check constructor with minimum arguments + repeat days + enabled + # label + timestamp alarm_test = AlarmItem(hour, minute, days=days, enabled=False, label=label, timestamp=timestamp) self.assertEqual(timestamp, alarm_test.timestamp) # Check constructor with minimum arguments + repeat days + enabled + # label + id alarm_test = AlarmItem(hour, minute, days=days, enabled=False, label=label, timestamp=timestamp, alarm_id=id_) self.assertEqual(id_, alarm_test.id_)
def test_diff_alarm(self): """ Tests the diff_alarm method returned Alarms. """ # Helper function to assert the alarm properties, takes the outer scope # variables directly as we will be reusing them for all tests def assert_diff_alarm(diff_alarm): self.assertEqual(diff_alarm.minute, expected_minute) self.assertEqual(diff_alarm.hour, expected_hour) self.assert_repeat(diff_alarm, expected_days) self.assertEqual(diff_alarm.enabled, test_enabled) self.assertEqual(diff_alarm.label, expected_label) self.assertNotEqual(diff_alarm.timestamp, test_timestamp) self.assertNotEqual(diff_alarm.id_, test_id) # First test - 15 minutes to 9 30, so only change in minutes time_diff = -15 test_minute = 30 test_hour = 9 expected_minute = 15 expected_hour = 9 test_days = (True, False, False, True, False, False, True) expected_days = test_days test_enabled = True test_id = 98 test_label = "test label" expected_label = test_label + \ (" (Alarm %s %+dmin)" % (test_id, time_diff)) test_timestamp = 1234 test_alarm = AlarmItem( test_hour, test_minute, days=test_days, enabled=test_enabled, timestamp=test_timestamp, label=test_label, alarm_id=test_id) assert_diff_alarm(test_alarm.diff_alarm(time_diff)) # Now test + 15 minutes to 9 30, so only change in minutes time_diff = 15 test_minute = 30 test_hour = 9 expected_minute = 45 expected_hour = 9 expected_label = test_label + \ (" (Alarm %s %+dmin)" % (test_id, time_diff)) test_alarm = AlarmItem( test_hour, test_minute, days=test_days, enabled=test_enabled, timestamp=test_timestamp, label=test_label, alarm_id=test_id) assert_diff_alarm(test_alarm.diff_alarm(time_diff)) # Now test + 15 minutes to 9 30, so only change in minutes time_diff = 15 test_minute = 30 test_hour = 9 expected_minute = 45 expected_hour = 9 expected_label = test_label + \ (" (Alarm %s %+dmin)" % (test_id, time_diff)) test_alarm = AlarmItem( test_hour, test_minute, days=test_days, enabled=test_enabled, timestamp=test_timestamp, label=test_label, alarm_id=test_id) assert_diff_alarm(test_alarm.diff_alarm(time_diff)) # Now test + minutes with hour rollover time_diff = 59 test_minute = 10 test_hour = 14 expected_minute = 9 expected_hour = 15 expected_label = test_label + \ (" (Alarm %s %+dmin)" % (test_id, time_diff)) test_alarm = AlarmItem( test_hour, test_minute, days=test_days, enabled=test_enabled, timestamp=test_timestamp, label=test_label, alarm_id=test_id) assert_diff_alarm(test_alarm.diff_alarm(time_diff)) # Now test - minutes with hour rollover time_diff = -59 test_minute = 10 test_hour = 14 expected_minute = 11 expected_hour = 13 expected_label = test_label + \ (" (Alarm %s %+dmin)" % (test_id, time_diff)) test_alarm = AlarmItem( test_hour, test_minute, days=test_days, enabled=test_enabled, timestamp=test_timestamp, label=test_label, alarm_id=test_id) assert_diff_alarm(test_alarm.diff_alarm(time_diff)) # Now test + minutes with day rollover time_diff = 30 test_minute = 50 test_hour = 23 expected_minute = 20 expected_hour = 0 test_days = (True, False, False, True, True, False, True) expected_days = (True, True, False, False, True, True, False) expected_label = test_label + \ (" (Alarm %s %+dmin)" % (test_id, time_diff)) test_alarm = AlarmItem( test_hour, test_minute, days=test_days, enabled=test_enabled, timestamp=test_timestamp, label=test_label, alarm_id=test_id) assert_diff_alarm(test_alarm.diff_alarm(time_diff)) # Now test - minutes with day rollover time_diff = -30 test_minute = 10 test_hour = 0 expected_minute = 40 expected_hour = 23 test_days = (True, False, False, True, True, False, True) expected_days = (False, False, True, True, False, True, True) expected_label = test_label + \ (" (Alarm %s %+dmin)" % (test_id, time_diff)) test_alarm = AlarmItem( test_hour, test_minute, days=test_days, enabled=test_enabled, timestamp=test_timestamp, label=test_label, alarm_id=test_id) assert_diff_alarm(test_alarm.diff_alarm(time_diff)) # Test input sanitation capturing stderr to check with mock.patch('sys.stderr', new=io.StringIO()) as test_srderr: # First ensure that successful set does not write to stderr self.assertEqual(test_srderr.getvalue(), '') time_diff = 0 test_alarm.diff_alarm(time_diff) self.assertEqual(test_srderr.getvalue(), '') # Lower boundary time_diff = -60 test_alarm.diff_alarm(time_diff) self.assert_stderr(test_srderr) # Upper boundary time_diff = 60 test_alarm.diff_alarm(time_diff) self.assert_stderr(test_srderr) # other types instead of integer time_diff = 0.1 test_alarm.diff_alarm(time_diff) self.assert_stderr(test_srderr) time_diff = "0" test_alarm.diff_alarm(time_diff) self.assert_stderr(test_srderr)
def test_time_to_alarm(self): """ Full tests coverage for the get_time_diff function. Good resource: http://www.timeanddate.com/date/timeduration.html """ one_day = 1440 test_alarm = AlarmItem( 9, 30, (True, False, False, True, False, False, False), True) time_diff = test_alarm.minutes_to_alert(9, 30, 0) self.assertEqual(time_diff, 0) time_diff = test_alarm.minutes_to_alert(9, 29, 0) self.assertEqual(time_diff, 1) time_diff = test_alarm.minutes_to_alert(19, 55, 2) self.assertEqual(time_diff, 815) time_diff = test_alarm.minutes_to_alert(9, 30, 2) self.assertEqual(time_diff, one_day) time_diff = test_alarm.minutes_to_alert(9, 30, 1) self.assertEqual(time_diff, (one_day * 2)) time_diff = test_alarm.minutes_to_alert(9, 31, 1) self.assertEqual(time_diff, ((one_day * 2) - 1)) time_diff = test_alarm.minutes_to_alert(9, 29, 4) self.assertEqual(time_diff, ((one_day * 3) + 1)) time_diff = test_alarm.minutes_to_alert(3, 15, 1) self.assertEqual(time_diff, ((one_day * 2) + (60 * 6) + 15)) test_alarm.repeat = (True, False, False, False, False, False, False) time_diff = test_alarm.minutes_to_alert(9, 31, 0) self.assertEqual(time_diff, ((one_day * 7) - 1)) time_diff = test_alarm.minutes_to_alert(13, 34, 1) self.assertEqual(time_diff, ((one_day * 5) + (60 * 19) + 56)) time_diff = test_alarm.minutes_to_alert(4, 15, 2) self.assertEqual(time_diff, ((one_day * 5) + (60 * 5) + 15))
def test_repeat_accessors_set(self): """ Sets the repeat list and test that the individual set accessors work as expected, including throwing errors if values are not booleans. """ alarm_test = AlarmItem(0, 0) days = [False, True, True, False, True, False, True] # Test with correct values alarm_test.monday = days[0] alarm_test.tuesday = days[1] alarm_test.wednesday = days[2] alarm_test.thursday = days[3] alarm_test.friday = days[4] alarm_test.saturday = days[5] alarm_test.sunday = days[6] self.assert_repeat(alarm_test, days) # To test the incorrect value, the accessor setter prints to stderr # if bad data is encountered, so we need to capture stderr to test it. with mock.patch('sys.stderr', new=io.StringIO()) as test_srderr: # First ensure that successful set does not write to stderr self.assertEqual(test_srderr.getvalue(), '') alarm_test.monday = days[0] self.assertEqual(test_srderr.getvalue(), '') # Monday alarm_test.monday = 'monday' self.assert_stderr(test_srderr) alarm_test.monday = 1 self.assert_stderr(test_srderr) alarm_test.monday = 2.3 self.assert_stderr(test_srderr) self.assertEqual(alarm_test.monday, days[0]) # Tuesday alarm_test.tuesday = 'tuesday' self.assert_stderr(test_srderr) alarm_test.tuesday = 1 self.assert_stderr(test_srderr) alarm_test.tuesday = 2.3 self.assert_stderr(test_srderr) self.assertEqual(alarm_test.tuesday, days[1]) # Wednesday alarm_test.wednesday = 'wednesday' self.assert_stderr(test_srderr) alarm_test.wednesday = 1 self.assert_stderr(test_srderr) alarm_test.wednesday = 2.3 self.assert_stderr(test_srderr) self.assertEqual(alarm_test.wednesday, days[2]) # Thursday alarm_test.thursday = 'thursday' self.assert_stderr(test_srderr) alarm_test.thursday = 1 self.assert_stderr(test_srderr) alarm_test.thursday = 2.3 self.assert_stderr(test_srderr) self.assertEqual(alarm_test.thursday, days[3]) # Friday alarm_test.friday = 'friday' self.assert_stderr(test_srderr) alarm_test.friday = 1 self.assert_stderr(test_srderr) alarm_test.friday = 2.3 self.assert_stderr(test_srderr) self.assertEqual(alarm_test.friday, days[4]) # Saturday alarm_test.saturday = 'saturday' self.assert_stderr(test_srderr) alarm_test.saturday = 1 self.assert_stderr(test_srderr) alarm_test.saturday = 2.3 self.assert_stderr(test_srderr) self.assertEqual(alarm_test.saturday, days[5]) # Sunday alarm_test.sunday = 'sunday' self.assert_stderr(test_srderr) alarm_test.sunday = 1 self.assert_stderr(test_srderr) alarm_test.sunday = 2.3 self.assertEqual(alarm_test.sunday, days[6])