def test_repeatable(self): event = Event() block = EventSignalTimeout(event) self.configure_block(block, { "intervals": [ { "interval": { "milliseconds": 200 }, "repeatable": True } ] }) block.start() block.process_signals([Signal({'a': 'A'})]) event.wait(.3) self.assert_num_signals_notified(1, block) self.assertDictEqual(block.notified_signals[0].to_dict(), {'timeout': datetime.timedelta(0, 0, 200000), 'group': 'null', 'a': 'A'}) event.wait(.3) self.assert_num_signals_notified(2, block) self.assertDictEqual(block.notified_signals[0].to_dict(), {'timeout': datetime.timedelta(0, 0, 200000), 'group': 'null', 'a': 'A'}) block.stop()
def test_groups(self, back_patch): e = Event() block = EventCounter(e) self.configure_block(block, { "reset_info": { "resetting": True, "scheme": "INTERVAL", "interval": { "seconds": 1 }, }, "group_by": "{{$foo}}" }) block.start() block.process_signals([ Signal({'foo': 'bar'}), Signal({'foo': 'baz'}), Signal({'qux': 'ly'}) ]) self.assertEqual(block._cumulative_count[''], 1) self.assertEqual(block._cumulative_count['bar'], 1) self.assertEqual(block._cumulative_count['baz'], 1) e.wait(2) for k in block._cumulative_count: self.assertEqual(block._cumulative_count[k], 0) block.stop()
def test_groups(self): event = Event() block = EventSignalTimeout(event) self.configure_block(block, { "intervals": [ { "interval": { "milliseconds": 200 }, "repeatable": True } ], "group_by": "{{$group}}" }) block.start() block.process_signals([Signal({'a': 'A', 'group': 'a'})]) block.process_signals([Signal({'b': 'B', 'group': 'b'})]) # Wait for first notification event.wait(.3) self.assert_num_signals_notified(1, block) self.assertDictEqual(block.notified_signals[0].to_dict(), {'timeout': datetime.timedelta(0, 0, 200000), 'group': 'a', 'a': 'A'}) # Wait for second notificiation, it should be right after first event.wait(.3) self.assert_num_signals_notified(2, block) self.assertDictEqual(block.notified_signals[0].to_dict(), {'timeout': datetime.timedelta(0, 0, 200000), 'group': 'b', 'b': 'B'}) block.stop()
def test_all(self, *back_patch): e1 = Event() e2 = Event() e3 = Event() e4 = Event() signals = [ EventFlavorSignal(flavor='apple', event=e1), EventFlavorSignal(flavor='cherry', event=e2), EventFlavorSignal(flavor='cherry', event=e2), EventFlavorSignal(flavor='cherry', event=e4) ] blk = Queue() config = { "interval": { "seconds": 1 }, "capacity": 2, "group_by": '{{$flavor}}', "reload": True, "uniqueness": "{{$flavor}}" } self.configure_block(blk, config) blk.start() blk.process_signals(signals) self.assertEqual(len(blk._queues['cherry']), 1) self.assertEqual(len(blk._queues['apple']), 1) e1.wait(2) self.assertEqual(len(blk._queues['cherry']), 1) self.assertEqual(len(blk._queues['apple']), 1) blk.process_signals([FlavorSignal('cherry')]) self.assertEqual(len(blk._queues['cherry']), 1) blk.stop()
def test_reload(self, *back_patch): e1 = Event() e2 = Event() signals = [ EventFlavorSignal(flavor='apple', event=e1), EventFlavorSignal(flavor='cherry', event=e2) ] blk = Queue() config = { "interval": { "seconds": 1 }, "capacity": 100, "group_by": '{{$flavor}}', "reload": True } self.configure_block(blk, config) blk.start() blk.process_signals(signals) self.assertEqual(len(blk._queues['cherry']), 1) self.assertEqual(len(blk._queues['apple']), 1) e1.wait(2) self.assertEqual(len(blk._queues['cherry']), 1) self.assertEqual(len(blk._queues['apple']), 1) self.assert_num_signals_notified(2, blk) blk.stop()
def test_buffer(self): event = Event() block = EventBuffer(event) block._backup = MagicMock() self.configure_block(block, {"interval": {"milliseconds": 200}}) block.start() block.process_signals([Signal(), Signal(), Signal(), Signal()]) self.assert_num_signals_notified(0, block) event.wait(.3) self.assert_num_signals_notified(4, block) block.stop()
def test_with_no_retry(self): """All signals are notified and no retry is ever called""" e = Event() block = RetryBlock(e, 5) self.configure_block(block, {}) block.start() for _ in range(5): spawn(block.process_signals, [Signal()]) e.wait(2) block.stop() self.assert_num_signals_notified(5) # retry_count was never set because we had no failed calls self.assertEqual(block._retry_count, None)
def test_successful_retry(self): """All signals are notified and a retry is called for each one""" e = Event() block = RetryBlock(e, 5) self.configure_block(block, {}) block.start() for _ in range(5): spawn(block.process_signals, [Signal({'error': 1})]) e.wait(2) block.stop() self.assert_num_signals_notified(5) # retry_count is 0 because before_retry was called on 0th fail self.assertEqual(block._retry_count, 0)
def test_timeout(self): event = Event() block = EventBuffer(event) block._backup = MagicMock() self.configure_block(block, { "interval": { "milliseconds": 200 }, "timeout": True }) block.start() event.wait(.3) self.assert_num_signals_notified(1, block) block.stop()
def test_with_enough_locks(self): """All the signals get through since we have enought locks""" e = Event() block = LockBlock(e, 5, 5) self.configure_block(block, {}) block.start() for _ in range(5): spawn(block.process_signals, [Signal()]) e.wait(2) block.stop() self.assert_num_signals_notified(5) self.assertEqual(block._number_of_locks, 0) # All 5 signals are notified and none get blocked self.assertEqual(block._number_of_lock_queue_full_errors, 0) # Confirm that all signals were processed self.assertEqual(block._num_processes_count, 5)
def test_with_one_lock(self): """Only the first signal is notified and the others are dropped""" e = Event() block = LockBlock(e, 5, 1) self.configure_block(block, {}) block.start() for _ in range(5): spawn(block.process_signals, [Signal()]) e.wait(2) block.stop() self.assert_num_signals_notified(1) self.assertEqual(block._number_of_locks, 0) # One signal is notifed and 4 are blocked self.assertEqual(block._number_of_lock_queue_full_errors, 4) # Confirm that all signals were processed self.assertEqual(block._num_processes_count, 5)
def test_failed_retry(self): """No signals are notified and a retry is called for each one""" e = Event() block = RetryBlock(e, 5) self.configure_block(block, {}) # Let the block retry up to 100 times block.num_retries = 100 block.start() for _ in range(5): spawn(block.process_signals, [Signal({'error': 99})]) e.wait(2) block.stop() # No signals get notified since we retry forever self.assert_num_signals_notified(0) # Assert that at least 10 retries (2 for each signal) self.assertTrue(block._retry_count >= 10)
def test_interval_reset(self, back_patch): e = Event() block = EventCounter(e) self.configure_block(block, { "reset_info": { "resetting": True, "scheme": "INTERVAL", "interval": { "seconds": 1 } } }) block.start() block.process_signals([Signal(), Signal()]) e.wait(2) self.assertEqual(block._cumulative_count['null'], 0) block.stop()
def test_negative_interval(self, *back_patch): e = Event() signals = [EventSignal(e)] blk = Queue() config = { "interval": { "seconds": -1 }, "capacity": 4, "chunk_size": 1, } self.configure_block(blk, config) blk.start() blk.process_signals(signals) e.wait(1) self.assertEqual(len(blk._queues['null']), 1) self.assert_num_signals_notified(0, blk) blk.stop()
def test_reset(self): """ Make sure the block can reset the intervals """ event = Event() block = EventSignalTimeout(event) self.configure_block(block, { "intervals": [ { "interval": { "seconds": 1 } } ] }) block.start() block.process_signals([Signal({'a': 'A'})]) # Wait a bit before sending another signal event.wait(0.6) block.process_signals([Signal({'b': 'B'})]) self.assert_num_signals_notified(0, block) event.wait(0.6) self.assert_num_signals_notified(0, block) event.wait(0.6) self.assert_num_signals_notified(1, block) self.assertDictEqual(block.notified_signals[0].to_dict(), {'timeout': datetime.timedelta(seconds=1), 'group': 'null', 'b': 'B'}) block.stop()
def test_interval_duration(self): event = Event() block = EventBuffer(event) block._backup = MagicMock() self.configure_block( block, { "interval": { "milliseconds": 1000 }, "interval_duration": { "milliseconds": 2000 } }) block.start() # process 4 signals (first group) block.process_signals([Signal(), Signal(), Signal(), Signal()]) self.assert_num_signals_notified(0, block) event.wait(1.3) # first emit notifies first group self.assert_num_signals_notified(4, block) # process 2 more signals (second group) block.process_signals([Signal(), Signal()]) event.wait(1.3) # second emit notifies first group and second group self.assert_num_signals_notified(10, block) # process 2 more signals (thrid group) block.process_signals([Signal(), Signal()]) event.wait(1.3) # third emit notifies second group and third group self.assert_num_signals_notified(14, block) block.stop()
def test_cron_missed_reset(self, back_patch): now = datetime.utcnow() e = Event() block = LieCounter(e) block.reset = MagicMock() # Reset one minute in the past reset_at = now - timedelta(minutes=1) self.configure_block(block, { "log_level": "DEBUG", "reset_info": { "resetting": True, "scheme": "CRON", "at": { "hour": reset_at.hour, "minute": reset_at.minute } }, }) block.start(now - timedelta(minutes=10)) block.process_signals([Signal()]) e.wait(0.5) block.reset.assert_called_once()
def test_cron_sched(self, back_patch): now = datetime.utcnow() e = Event() block = EventCounter(e) block._calculate_next = MagicMock( return_value=now+timedelta(seconds=1)) # Reset one minute in the future reset_at = now + timedelta(minutes=1) self.configure_block(block, { "reset_info": { "resetting": True, "scheme": "CRON", "at": { "hour": reset_at.hour, "minute": reset_at.minute } }, }) block.start() block.process_signals([Signal()]) self.assertEqual(block._cumulative_count['null'], 1) e.wait(1.25) self.assertEqual(block._cumulative_count['null'], 0)
def test_defaults(self): e = Event() blk = self._create_block({}, e) blk.start() e.wait(0.1) blk.stop()