def test_get_display_pattern(self):
        """
        This method tests that the mode is, under all circumstances, returning the correct pattern to be displayed.
        The circumstances are as follows:
            - A pause on the frame the display was showing when it entered screensaver mode.
            - The correct number of clearing frames when running in clearing state.
            - Once clearing state has finished, the correct frames for a screensaver pattern.
        """
        input = "-*-\n-*-\n-*-"
        previous = "---\n---\n---"
        sm = ScreensaverMode(input, previous)

        for _ in range(0, 3):
            # For each frame of the pause.

            # Assert the mode is returning the correct pattern at this point.
            assert sm.get_display_pattern() == previous

        for i, _ in enumerate(previous.split("\n")):
            # For each cell of the previous pattern

            # Assert that the mode is still calculating a pattern at this point.
            assert sm.get_display_pattern()

        # Assert that the mode is returning the input pattern at this point.
        assert sm.get_display_pattern() == input
    def test_is_active_fails(self):
        """
        This method tests that 'screensaver mode' activity does change. The expected result of the test is that the
        is_active method returns inactivity.
        """
        input = "---\n---\n---"
        previous = "---\n---\n---"
        sm = ScreensaverMode(input, previous)

        for _ in range(0, 3):
            # For each frame of the pause

            # Assert the mode is still active.
            assert sm.is_active()
            sm.get_display_pattern()

        for i, _ in enumerate(previous.split("\n")):
            # For each cell in the previous pattern.

            # Assert the mode is still active.
            assert sm.is_active()
            # Calculate the next pattern to be displayed.
            sm.get_display_pattern()

        # Assert that the mode is no longer active.
        assert not sm.is_active()
    def start(self):
        """
        Starts the application: begins checking the current time and working out what information needs to be sent
        to the display at that time.
        """
        mode = ScreensaverMode(self._db_helper.get_random_screensaver())
        last_pattern = None
        last_check_time = datetime.datetime.now() - datetime.timedelta(minutes=10)

        while True:
            # Check the current time and make it accurate to the second
            current_time = datetime.datetime.now()
            min_current_time = minutify(current_time)

            if (current_time.minute % 5) == 0 and (min_current_time > last_check_time):
                # If the current time is on one of the five min. intervals, attempt to pull a pattern from the
                # internal database.
                last_check_time = min_current_time
                t_format = "%Y-%m-%d %H:%M:00.000000"
                pattern = self._db_helper.get_run_for_time(current_time.strftime(t_format))
                if pattern:
                    # If a pattern is successfully pulled, run the display's 'run mode' on it.
                    mode = RunMode(pattern)
                else:
                    # Otherwise pull a random screensaver from the internal database and run that in 'screensaver
                    # mode'
                    mode = ScreensaverMode(self._db_helper.get_random_screensaver(), last_pattern)

            if not mode.is_active():
                # If the current pattern finishes before the five minute timer has stopped, switch to
                # screensaver mode
                mode = ScreensaverMode(self._db_helper.get_random_screensaver(), last_pattern)

            # Retrieve the latest pattern to be sent to the display
            last_pattern = mode.get_display_pattern()

            # Send the pattern to the display controller for printing.
            self._display_controller.output_pattern(last_pattern)

            # While not working, sleep
            sleep_until_time = current_time + datetime.timedelta(seconds=sleep_time)
            time.sleep((sleep_until_time - datetime.datetime.now()).microseconds / 1000000)

            self.logger.warn("Outputted pattern at: %s" % current_time)
    def test_is_active(self):
        """
        This method tests that 'screensaver mode' is still active, especially in its clearing state. The expected
        result of this tests is for the check to show the mode is still active.
        """
        input = "-*-\n-*-\n-*-"
        previous = "---\n---\n---"
        sm = ScreensaverMode(input, previous)

        for _ in range(0, 3):
            # For each frame of the pause

            # Assert the mode is still active.
            assert sm.is_active()
            sm.get_display_pattern()

        for i, _ in enumerate(previous.split("\n")):
            # For each cell in the previous pattern

            # Assert the mode is still active.
            assert sm.is_active()
            # Calculate the next pattern to be displayed.
            sm.get_display_pattern()
            # Assert the mode is still active.
            assert sm.is_active()

        # Calculate the next pattern to be displayed.
        sm.get_display_pattern()
        # Assert the mode is still active.
        assert sm.is_active()