Commits

Jean-Tiare Le Bigot committed 427d0d8

add a clean way to bypass timers. closes #8

Comments (0)

Files changed (5)

 
 ### slowness simulation ###
 
+# boolean: enable timers ?
+ENABLE_DELAYS = True
 # seconds: simulate table creation delay. It will still be available immediately
 DELAY_CREATING = 1000
 # seconds: simulate table update delay. It will still be available immediately

ddbmock/database/table.py

 from .item import Item, ItemSize
 from .storage import Store
 from collections import defaultdict, namedtuple
-from threading import Timer, Lock
+from threading import Lock
 from ddbmock import config
 from ddbmock.errors import ValidationException, LimitExceededException, ResourceInUseException
+from ddbmock.utils import schedule_action
 import time, copy, datetime
 
 # All validations are performed on *incomming* data => already done :)
         self.last_decrease_time = 0
         self.count = 0
 
-        Timer(config.DELAY_CREATING, self.activate).start()
+        schedule_action(config.DELAY_CREATING, self.activate)
 
     def delete(self, callback):
         """
 
         self.status = "DELETING"
 
-        Timer(config.DELAY_DELETING, callback, [self]).start()
+        schedule_action(config.DELAY_DELETING, callback, [self])
 
     def activate(self):
         self.status = "ACTIVE"
         self.rt = rt
         self.wt = wt
 
-        Timer(config.DELAY_UPDATING, self.activate).start()
+        schedule_action(config.DELAY_UPDATING, self.activate)
 
     def delete_item(self, key, expected):
         key = Item(key)

ddbmock/utils/__init__.py

 
 from .stat import Stat
 from ddbmock import config
+from threading import Timer
 import logging
 
 tp_stat = {
                                                 config.STAT_TP_AGGREG,
                                                 tp_logger)
     tp_stat['write'][table_name].push(value)
+
+def schedule_action(delay, callback, args=[], kwargs={}):
+    """Unless delays are explicitely disabled, start ``callback`` once ``delay``
+    has expired. Otherwise, call it immediately.
+    """
+    if config.ENABLE_DELAYS:
+        Timer(delay, callback, args, kwargs).start()
+    else:
+        callback(*args, **kwargs)

tests/unit/test_utils.py

+# -*- coding: utf-8 -*-
+
+import unittest, mock
+
+LOGGER = 'unit-stat-test'
+DELAY = 12
+
+class TestUtils(unittest.TestCase):
+    @mock.patch('ddbmock.utils.Timer')
+    def test_schedule_action_enable(self, m_timer):
+        from ddbmock.utils import schedule_action
+        from ddbmock import config
+
+        old_delay_param = config.ENABLE_DELAYS
+        config.ENABLE_DELAYS = True
+
+        m_cb = mock.Mock()
+
+        schedule_action(DELAY, m_cb, ["args"], {'kwargs':'kwargs'})
+        m_timer.assert_called_with(DELAY, m_cb, ["args"], {'kwargs':'kwargs'})
+        m_timer.return_value.start.assert_called_with()
+
+        config.ENABLE_DELAYS = old_delay_param
+
+    @mock.patch('ddbmock.utils.Timer')
+    def test_schedule_action_disable(self, m_timer):
+        from ddbmock.utils import schedule_action
+        from ddbmock import config
+
+        old_delay_param = config.ENABLE_DELAYS
+        config.ENABLE_DELAYS = False
+
+        m_cb = mock.Mock()
+
+        schedule_action(DELAY, m_cb, ["args"], {'kwargs':'kwargs'})
+        m_cb.assert_called_with("args", kwargs='kwargs')
+
+        config.ENABLE_DELAYS = old_delay_param
+
+    def test_average(self):
+        from ddbmock.utils.stat import average
+
+        self.assertEqual(2, average([1,2,3]))
+        self.assertEqual(2, average([1,2,3,4]))
+
+    @mock.patch('ddbmock.utils.stat.time')
+    @mock.patch('ddbmock.utils.stat.atexit')
+    def test_aggregate(self, _, m_time):
+        from ddbmock.utils.stat import Stat
+
+        s = Stat(LOGGER)
+        s.current_point_value = 42
+
+        m_time.return_value = 123.5
+
+        s._aggregate()
+
+        self.assertEqual([42], s.current_point_list)
+        self.assertEqual(0, s.current_point_value)
+        self.assertEqual(123, s.current_point_time)
+
+    @mock.patch('ddbmock.utils.stat.atexit')
+    def test_macro_aggregate(self, _):
+        from ddbmock.utils.stat import Stat
+
+        s = Stat(LOGGER)
+
+        s.current_point_list = [-4,12,5000]
+        s.last_aggregation_time = 32
+
+        s._macro_aggregate()
+
+        self.assertEqual([], s.current_point_list)
+
+    @mock.patch('ddbmock.utils.stat.time')
+    @mock.patch('ddbmock.utils.stat.Stat._aggregate')
+    @mock.patch('ddbmock.utils.stat.Stat._macro_aggregate')
+    @mock.patch('ddbmock.utils.stat.atexit')
+    def test_push(self, _, _m_m_agg, _m_agg, m_time):
+        from ddbmock.utils.stat import Stat
+
+        m_time.return_value = 1
+        s = Stat(LOGGER)
+
+        # nominal
+        s.push(1)
+        s.push(2)
+        s.push(3)
+        self.assertEqual(6, s.current_point_value)
+        self.assertFalse(_m_agg.called)
+        self.assertFalse(_m_m_agg.called)
+
+        # manual clean (mocks...)
+        s.current_point_value = 0
+
+        # change data point
+        m_time.return_value = 2.1
+        s.push(4)
+        self.assertEqual(4, s.current_point_value)
+        self.assertTrue(_m_agg.called)
+        self.assertFalse(_m_m_agg.called)
+
+        # manual clean (mocks...)
+        s.current_point_value = 0
+
+        # change data point
+        m_time.return_value = 5*60+1
+        s.push(6)
+        self.assertEqual(6, s.current_point_value)
+        self.assertTrue(_m_agg.called)
+        self.assertTrue(_m_m_agg.called)
+
+    @mock.patch('ddbmock.utils.stat.Stat._aggregate')
+    @mock.patch('ddbmock.utils.stat.Stat._macro_aggregate')
+    @mock.patch('ddbmock.utils.stat.atexit')
+    def test_flush(self, _, _m_m_agg, _m_agg):
+        from ddbmock.utils.stat import Stat
+
+        s = Stat(LOGGER)
+        m_list = mock.MagicMock()
+        s.flush()
+
+        self.assertTrue(_m_agg.called)
+        self.assertTrue(_m_m_agg.called)

tests/unit/test_utils_stat.py

-# -*- coding: utf-8 -*-
-
-import unittest, mock
-
-LOGGER = 'unit-stat-test'
-
-class TestStat(unittest.TestCase):
-    def test_average(self):
-        from ddbmock.utils.stat import average
-
-        self.assertEqual(2, average([1,2,3]))
-        self.assertEqual(2, average([1,2,3,4]))
-
-    @mock.patch('ddbmock.utils.stat.time')
-    @mock.patch('ddbmock.utils.stat.atexit')
-    def test_aggregate(self, _, m_time):
-        from ddbmock.utils.stat import Stat
-
-        s = Stat(LOGGER)
-        s.current_point_value = 42
-
-        m_time.return_value = 123.5
-
-        s._aggregate()
-
-        self.assertEqual([42], s.current_point_list)
-        self.assertEqual(0, s.current_point_value)
-        self.assertEqual(123, s.current_point_time)
-
-    @mock.patch('ddbmock.utils.stat.atexit')
-    def test_macro_aggregate(self, _):
-        from ddbmock.utils.stat import Stat
-
-        s = Stat(LOGGER)
-
-        s.current_point_list = [-4,12,5000]
-        s.last_aggregation_time = 32
-
-        s._macro_aggregate()
-
-        self.assertEqual([], s.current_point_list)
-
-    @mock.patch('ddbmock.utils.stat.time')
-    @mock.patch('ddbmock.utils.stat.Stat._aggregate')
-    @mock.patch('ddbmock.utils.stat.Stat._macro_aggregate')
-    @mock.patch('ddbmock.utils.stat.atexit')
-    def test_push(self, _, _m_m_agg, _m_agg, m_time):
-        from ddbmock.utils.stat import Stat
-
-        m_time.return_value = 1
-        s = Stat(LOGGER)
-
-        # nominal
-        s.push(1)
-        s.push(2)
-        s.push(3)
-        self.assertEqual(6, s.current_point_value)
-        self.assertFalse(_m_agg.called)
-        self.assertFalse(_m_m_agg.called)
-
-        # manual clean (mocks...)
-        s.current_point_value = 0
-
-        # change data point
-        m_time.return_value = 2.1
-        s.push(4)
-        self.assertEqual(4, s.current_point_value)
-        self.assertTrue(_m_agg.called)
-        self.assertFalse(_m_m_agg.called)
-
-        # manual clean (mocks...)
-        s.current_point_value = 0
-
-        # change data point
-        m_time.return_value = 5*60+1
-        s.push(6)
-        self.assertEqual(6, s.current_point_value)
-        self.assertTrue(_m_agg.called)
-        self.assertTrue(_m_m_agg.called)
-
-    @mock.patch('ddbmock.utils.stat.Stat._aggregate')
-    @mock.patch('ddbmock.utils.stat.Stat._macro_aggregate')
-    @mock.patch('ddbmock.utils.stat.atexit')
-    def test_flush(self, _, _m_m_agg, _m_agg):
-        from ddbmock.utils.stat import Stat
-
-        s = Stat(LOGGER)
-        m_list = mock.MagicMock()
-        s.flush()
-
-        self.assertTrue(_m_agg.called)
-        self.assertTrue(_m_m_agg.called)