def test_event_rate_fractions(self): # Test SampleEventRate strategy in the presence of fractional seconds -- # mainly to catch bugs when it was converted to taking seconds instead of # milliseconds, since the previous implementation used an integer number # of milliseconds shortest = 3./8 longest = 6./8 evrate = sampling.SampleEventRate(self.inform, self.sensor, shortest, longest) evrate.set_new_period_callback(mock.Mock()) now = [0] evrate._time = lambda: now[0] evrate.attach() self.assertEqual(len(self.calls), 1) now[0] = 0.999*shortest self.sensor.set_value(1) self.assertEqual(len(self.calls), 1) now[0] = shortest self.sensor.set_value(1) self.assertEqual(len(self.calls), 2) next_time = evrate.periodic(now[0] + 0.99*shortest) self.assertEqual(len(self.calls), 2) self.assertEqual(next_time, now[0] + longest)
def test_event_rate(self): max_period = 10. min_period = 1. event_rate_strat = sampling.SampleEventRate( self.inform, self.sensor, min_period, max_period) self._add_strategy(event_rate_strat) no_max_periods = 3 # Do some 'max period' updates where the sensor has not changed for i in range(no_max_periods): self.timewarp(max_period, event_to_await=self.inform_called) call_times = [t for t, vals in self.calls] self.assertEqual(len(self.calls), no_max_periods + 1) self.assertEqual(call_times, [self.start_time + i*max_period for i in range(no_max_periods + 1)]) del self.calls[:] # Now do a sensor update without moving time along, should not result in # any additional updates update_time = self.time() expected_send_time = update_time + min_period self.sensor.set_value(2, self.sensor.NOMINAL, update_time) # There should, however, be a wake-wait event self.wake_waits.get(timeout=1) self.assertEqual(len(self.calls), 0) # Timewarp less than min update period, should not result in an inform # callback self.timewarp(min_period*0.6) # Move time beyond minimum step self.timewarp(min_period*1.01, event_to_await=self.inform_called) self.assertEqual(len(self.calls), 1) self.assertEqual(self.calls, [(expected_send_time, (self.sensor.name, update_time, 'nominal', '2'))]) # Should not be any outstanding wake-waits self.assertEqual(self.wake_waits.qsize(), 0) del self.calls[:] # Time we expect the next max-period sample expected_send_time += max_period # Timewarp past the next expected max-period sample time self.timewarp(max_period + min_period*0.01, event_to_await=self.inform_called) self.assertEqual(len(self.calls), 1) self.assertEqual(self.calls[0][0], expected_send_time) self.reactor._debug_now = False self.reactor.remove_strategy(event_rate_strat)
def test_event_rate(self): """Test SampleEventRate strategy.""" shortest = 10 longest = 20 patcher = mock.patch('katcp.sampling.time') mtime = patcher.start() self.addCleanup(patcher.stop) time_ = mtime.time time_.return_value = 1 evrate = sampling.SampleEventRate( self.inform, self.sensor, shortest, longest) new_period = mock.Mock() evrate.set_new_period_callback(new_period) time_.return_value = 1 self.assertEqual(self.calls, []) evrate.attach() # Check initial update self.assertEqual(len(self.calls), 1) # Too soon, should not send update self.sensor.set_value(1) self.assertEqual(len(self.calls), 1) # but should have requested a future update at now + shortest-time new_period.assert_called_once_with(evrate, 11) new_period.reset_mock() time_.return_value = 11 next_p = evrate.periodic(11) self.assertEqual(len(self.calls), 2) self.assertEqual(new_period.called, False) evrate.periodic(12) self.assertEqual(len(self.calls), 2) self.assertEqual(new_period.called, False) evrate.periodic(13) self.assertEqual(len(self.calls), 2) self.assertEqual(new_period.called, False) evrate.periodic(31) self.assertEqual(len(self.calls), 3) time_.return_value = 32 self.assertEqual(len(self.calls), 3) time_.return_value = 41 self.sensor.set_value(2) self.assertEqual(len(self.calls), 4)
def test_event_rate(self): """Test SampleEventRate strategy.""" shortest = 1.5 longest = 4.5 t, status, value = self.sensor.read() DUT = sampling.SampleEventRate(self.inform, self.sensor, shortest, longest) self.assertEqual(DUT.get_sampling_formatted(), (b'event-rate', [b'1.5', b'4.5'])) self.assertEqual(len(self.calls), 0) DUT.start() yield self.wake_ioloop() # Check initial update t_last_sent = self.ioloop_time self.assertEqual(self.calls, [(self.sensor, (t, status, value))]) self.calls = [] # Too soon, should not send update yield self.set_ioloop_time(t_last_sent + shortest * 0.99) value = value + 3 t = self.ioloop_time self.sensor.set(t, status, value) self.assertEqual(len(self.calls), 0) # Too soon again, should not send update yield self.set_ioloop_time(t_last_sent + shortest * 0.999) value = value + 1 t = self.ioloop_time self.sensor.set(t, status, value) self.assertEqual(len(self.calls), 0) # Should now get minimum time update yield self.set_ioloop_time(t_last_sent + shortest) t_last_sent = self.ioloop_time self.assertEqual(self.calls, [(self.sensor, (t, status, value))]) self.calls = [] # Warp to just before longest period, should not update yield self.set_ioloop_time(t_last_sent + longest * 0.999) self.assertEqual(len(self.calls), 0) # Warp to longest period, should update yield self.set_ioloop_time(t_last_sent + longest) t_last_sent = self.ioloop_time self.assertEqual(self.calls, [(self.sensor, (t, status, value))]) self.calls = [] # Warp to just before next longest period, should not update yield self.set_ioloop_time(t_last_sent + longest * 0.999) self.assertEqual(len(self.calls), 0) # Warp to longest period, should update yield self.set_ioloop_time(t_last_sent + longest) t_last_sent = self.ioloop_time self.assertEqual(self.calls, [(self.sensor, (t, status, value))]) self.calls = [] # Set identical value, jump past min update time, no update should happen self.sensor.set(self.ioloop_time, status, value) yield self.set_ioloop_time(t_last_sent + shortest) self.assertEqual(len(self.calls), 0) # Set new value, update should happen value = value - 2 self.sensor.set(self.ioloop_time, status, value) t_last_sent = self.ioloop_time self.assertEqual(self.calls, [(self.sensor, (t_last_sent, status, value))]) self.calls = [] # Now warp to after min period, change only status, update should happen yield self.set_ioloop_time(t_last_sent + shortest) status = Sensor.ERROR self.sensor.set(self.ioloop_time, status, value) self.assertEqual(self.calls, [(self.sensor, (self.ioloop_time, status, value))]) t_last_sent = self.ioloop_time self.calls = [] yield self.set_ioloop_time(t_last_sent + shortest) status = Sensor.NOMINAL value = value + 1 yield self._thread_update_check(self.ioloop_time, status, value) yield self._check_cancel(DUT) self.calls = [] # Since strategy is cancelled, no futher updates should be sent yield self.set_ioloop_time(self.ioloop_time + 5 * longest) self.sensor.set(self.ioloop_time, Sensor.WARN, value + 3) self.assertEqual(len(self.calls), 0)