From 73620678c4e16674fb04b8f78c36e767c195d063 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gina=20H=C3=A4u=C3=9Fge?= Date: Fri, 28 Aug 2015 16:56:14 +0200 Subject: [PATCH] Unit tests for octoprint.util.RepeatedTimer --- tests/util/test_repeated_timer.py | 180 ++++++++++++++++++++++++++++++ 1 file changed, 180 insertions(+) create mode 100644 tests/util/test_repeated_timer.py diff --git a/tests/util/test_repeated_timer.py b/tests/util/test_repeated_timer.py new file mode 100644 index 00000000..6eed773b --- /dev/null +++ b/tests/util/test_repeated_timer.py @@ -0,0 +1,180 @@ +# coding=utf-8 +from __future__ import absolute_import + +__author__ = "Gina Häußge " +__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' +__copyright__ = "Copyright (C) 2015 The OctoPrint Project - Released under terms of the AGPLv3 License" + +import unittest +import mock +import time + +from octoprint.util import RepeatedTimer + + +class Countdown(object): + def __init__(self, start): + self._counter = start + + def step(self): + self._counter -= 1 + + @property + def counter(self): + return self._counter + + +class IncreasingInterval(Countdown): + def __init__(self, start, factor): + Countdown.__init__(self, start) + self._start = start + self._factor = factor + + def interval(self): + result = (self._start - self._counter + 1) * self._factor + return result + + +class RepeatedTimerTest(unittest.TestCase): + + def setUp(self): + pass + + def test_condition(self): + countdown = Countdown(5) + timer_task = mock.MagicMock() + timer_task.side_effect = countdown.step + + timer = RepeatedTimer(0.1, timer_task, condition=lambda: countdown.counter > 0) + timer.start() + + # wait for it + timer.join() + + self.assertEquals(5, timer_task.call_count) + + def test_finished_callback(self): + countdown = Countdown(5) + timer_task = mock.MagicMock() + timer_task.side_effect = countdown.step + + on_finished = mock.MagicMock() + + timer = RepeatedTimer(0.1, timer_task, condition=lambda: countdown.counter > 0, on_finish=on_finished) + timer.start() + + # wait for it + timer.join() + + self.assertEquals(1, on_finished.call_count) + + def test_condition_callback(self): + countdown = Countdown(5) + timer_task = mock.MagicMock() + timer_task.side_effect = countdown.step + + on_cancelled = mock.MagicMock() + on_condition_false = mock.MagicMock() + + timer = RepeatedTimer(0.1, timer_task, + condition=lambda: countdown.counter > 0, + on_condition_false=on_condition_false, + on_cancelled=on_cancelled) + timer.start() + + # wait for it + timer.join() + + self.assertEquals(1, on_condition_false.call_count) + self.assertEquals(0, on_cancelled.call_count) + + def test_cancelled_callback(self): + countdown = Countdown(5) + timer_task = mock.MagicMock() + timer_task.side_effect = countdown.step + + on_cancelled = mock.MagicMock() + on_condition_false = mock.MagicMock() + + timer = RepeatedTimer(10, timer_task, + condition=lambda: countdown.counter > 0, + on_condition_false=on_condition_false, + on_cancelled=on_cancelled) + timer.start() + + # give it some time to run + time.sleep(1) + + # then cancel it and wait for the thread to really finish + timer.cancel() + timer.join() + + self.assertEquals(0, on_condition_false.call_count) + self.assertEquals(1, on_cancelled.call_count) + + def test_run_first(self): + timer_task = mock.MagicMock() + + timer = RepeatedTimer(60, timer_task, run_first=True) + timer.start() + + # give it some time to run + time.sleep(1) + + # then cancel it and wait for the thread to really finish + timer.cancel() + timer.join() + + # should have run once + self.assertEquals(1, timer_task.call_count) + + def test_not_run_first(self): + timer_task = mock.MagicMock() + + timer = RepeatedTimer(60, timer_task) + timer.start() + + # give it some time to run - should hang in the sleep phase though + time.sleep(1) + + # then cancel it and wait for the thread to really finish + timer.cancel() + timer.join() + + self.assertEquals(0, timer_task.call_count) + + def test_adjusted_interval(self): + increasing_interval = IncreasingInterval(3, 1) + + timer_task = mock.MagicMock() + timer_task.side_effect = increasing_interval.step + + timer = RepeatedTimer(increasing_interval.interval, + timer_task, + condition=lambda: increasing_interval.counter > 0) + + # this should take 1 + 2 + 3 = 6s + start_time = time.time() + timer.start() + timer.join() + duration = time.time() - start_time + + self.assertEquals(3, timer_task.call_count) + self.assertGreaterEqual(duration, 6) + self.assertLess(duration, 7) + + def test_condition_change_during_task(self): + def sleep(): + time.sleep(2) + + timer_task = mock.MagicMock() + timer_task.side_effect = sleep + + timer = RepeatedTimer(0.1, timer_task, run_first=True) + timer.start() + + time.sleep(1) + timer.condition = lambda: False + timer.join() + + self.assertEquals(1, timer_task.call_count)