class TestThrottlerPerformance: def setup(self): # Fixture setup self.clock = TestClock() self.logger = Logger(self.clock, bypass_logging=True) self.handler = [] self.throttler = Throttler( name="Throttler-1", limit=10000, interval=timedelta(seconds=1), output=self.handler.append, clock=self.clock, logger=self.logger, ) def send(self): self.throttler.send("MESSAGE") def test_send_unlimited(self): PerformanceHarness.profile_function(self.send, 10000, 1) # ~0.0ms / ~0.3μs / 301ns minimum of 10,000 runs @ 1 iteration each run. def test_send_when_limited(self): PerformanceHarness.profile_function(self.send, 100000, 1)
def setup(self): # Fixture setup self.clock = TestClock() self.logger = TestLogger(self.clock) self.handler = [] self.throttler = Throttler( name="Throttler-1", limit=5, interval=timedelta(seconds=1), output=self.handler.append, clock=self.clock, logger=self.logger, )
def setup(self): # Fixture Setup self.clock = TestClock() self.logger = Logger(self.clock) self.handler = [] self.throttler = Throttler( name="Buffer", limit=5, interval=timedelta(seconds=1), output_send=self.handler.append, output_drop=None, # <-- no dropping handler so will buffer clock=self.clock, logger=self.logger, )
def setup(self): # Fixture Setup self.clock = TestClock() self.logger = Logger(self.clock) self.handler = [] self.dropped = [] self.throttler = Throttler( name="Dropper", limit=5, interval=timedelta(seconds=1), output_send=self.handler.append, output_drop=self.dropped.append, # <-- handler for dropping messages clock=self.clock, logger=self.logger, )
def throttler(clock, logger): handler = [] return Throttler( name="Throttler-1", limit=10000, interval=timedelta(seconds=1), output=handler.append, clock=clock, logger=logger, )
def buffering_throttler(clock, logger): handler = [] return Throttler( name="Throttler-1", limit=10000, interval=timedelta(seconds=1), output_send=handler.append, output_drop=None, clock=clock, logger=logger, )
class TestThrottler: def setup(self): # Fixture setup self.clock = TestClock() self.logger = TestLogger(self.clock) self.handler = [] self.throttler = Throttler( name="Throttler-1", limit=5, interval=timedelta(seconds=1), output=self.handler.append, clock=self.clock, logger=self.logger, ) def test_throttler_instantiation(self): # Arrange # Act # Assert assert self.throttler.name == "Throttler-1" assert self.throttler.qsize == 0 assert not self.throttler.is_active assert not self.throttler.is_throttling def test_send_when_not_active_becomes_active(self): # Arrange item = "MESSAGE" # Act self.throttler.send(item) # Assert assert self.throttler.is_active assert not self.throttler.is_throttling assert self.handler == ["MESSAGE"] def test_send_to_limit_becomes_throttled(self): # Arrange item = "MESSAGE" # Act: Send 6 items self.throttler.send(item) self.throttler.send(item) self.throttler.send(item) self.throttler.send(item) self.throttler.send(item) self.throttler.send(item) # Assert: Only 5 items are sent assert self.clock.timer_names() == ["Throttler-1-REFRESH-TOKEN"] assert self.throttler.is_active assert self.throttler.is_throttling assert self.handler == ["MESSAGE"] * 5 assert self.throttler.qsize == 1 def test_refresh_when_at_limit_sends_remaining_items(self): # Arrange item = "MESSAGE" # Act: Send 6 items self.throttler.send(item) self.throttler.send(item) self.throttler.send(item) self.throttler.send(item) self.throttler.send(item) self.throttler.send(item) # Act: Trigger refresh token time alert events = self.clock.advance_time(UNIX_EPOCH + timedelta(seconds=1)) events[0].handle_py() # Assert: Remaining items sent assert self.clock.timer_names() == ["Throttler-1-REFRESH-TOKEN"] assert self.throttler.is_active assert self.throttler.is_throttling is False assert self.handler == ["MESSAGE"] * 6 assert self.throttler.qsize == 0
class TestBufferingThrottler: def setup(self): # Fixture Setup self.clock = TestClock() self.logger = Logger(self.clock) self.handler = [] self.throttler = Throttler( name="Buffer", limit=5, interval=timedelta(seconds=1), output_send=self.handler.append, output_drop=None, # <-- no dropping handler so will buffer clock=self.clock, logger=self.logger, ) def test_throttler_instantiation(self): # Arrange, Act, Assert assert self.throttler.name == "Buffer" assert not self.throttler.is_limiting assert self.throttler.qsize == 0 assert self.throttler.used() == 0 assert self.throttler.recv_count == 0 assert self.throttler.sent_count == 0 def test_send_sends_message_to_handler(self): # Arrange item = "MESSAGE" # Act self.throttler.send(item) # Assert assert not self.throttler.is_limiting assert self.handler == ["MESSAGE"] assert self.throttler.recv_count == 1 assert self.throttler.sent_count == 1 def test_send_to_limit_becomes_throttled(self): # Arrange item = "MESSAGE" # Act: Send 6 items self.throttler.send(item) self.throttler.send(item) self.throttler.send(item) self.throttler.send(item) self.throttler.send(item) self.throttler.send(item) # Assert: Only 5 items are sent assert self.clock.timer_names() == ["Buffer-DEQUE"] assert self.throttler.is_limiting assert self.handler == ["MESSAGE"] * 5 assert self.throttler.qsize == 1 assert self.throttler.used() == 1 assert self.throttler.recv_count == 6 assert self.throttler.sent_count == 5 def test_used_when_sent_to_limit_returns_one(self): # Arrange item = "MESSAGE" # Act: Send 6 items self.throttler.send(item) self.throttler.send(item) self.throttler.send(item) self.throttler.send(item) self.throttler.send(item) # Act used = self.throttler.used() # Assert: Remaining items sent assert used == 1 assert self.throttler.recv_count == 5 assert self.throttler.sent_count == 5 def test_used_when_half_interval_from_limit_returns_half(self): # Arrange item = "MESSAGE" # Act: Send 6 items self.throttler.send(item) self.throttler.send(item) self.throttler.send(item) self.throttler.send(item) self.throttler.send(item) self.clock.advance_time(500_000_000) # Act used = self.throttler.used() # Assert: Remaining items sent assert used == 0.5 assert self.throttler.recv_count == 5 assert self.throttler.sent_count == 5 def test_used_before_limit_when_halfway_returns_half(self): # Arrange item = "MESSAGE" # Act: Send 6 items self.throttler.send(item) self.throttler.send(item) self.throttler.send(item) # Act used = self.throttler.used() # Assert assert used == 0.6 def test_refresh_when_at_limit_sends_remaining_items(self): # Arrange item = "MESSAGE" # Act: Send 6 items self.throttler.send(item) self.throttler.send(item) self.throttler.send(item) self.throttler.send(item) self.throttler.send(item) self.throttler.send(item) # Act: Trigger refresh token time alert events = self.clock.advance_time(1_000_000_000) events[0].handle_py() # Assert: Remaining items sent assert self.clock.timer_names() == [] # No longer timing to process assert self.throttler.is_limiting is False assert self.handler == ["MESSAGE"] * 6 assert self.throttler.qsize == 0 assert self.throttler.used() == 0 assert self.throttler.recv_count == 6 assert self.throttler.sent_count == 6
class TestDroppingThrottler: def setup(self): # Fixture Setup self.clock = TestClock() self.logger = Logger(self.clock) self.handler = [] self.dropped = [] self.throttler = Throttler( name="Dropper", limit=5, interval=timedelta(seconds=1), output_send=self.handler.append, output_drop=self.dropped. append, # <-- handler for dropping messages clock=self.clock, logger=self.logger, ) def test_throttler_instantiation(self): # Arrange, Act, Assert assert self.throttler.name == "Dropper" assert not self.throttler.is_limiting assert self.throttler.qsize == 0 assert self.throttler.used() == 0 assert self.throttler.recv_count == 0 assert self.throttler.sent_count == 0 def test_send_sends_message_to_handler(self): # Arrange item = "MESSAGE" # Act self.throttler.send(item) # Assert assert not self.throttler.is_limiting assert self.handler == ["MESSAGE"] assert self.throttler.recv_count == 1 assert self.throttler.sent_count == 1 def test_send_to_limit_drops_message(self): # Arrange item = "MESSAGE" # Act: Send 6 items self.throttler.send(item) self.throttler.send(item) self.throttler.send(item) self.throttler.send(item) self.throttler.send(item) self.throttler.send(item) # Assert: Only 5 items are sent assert self.clock.timer_names() == ["Dropper-DEQUE"] assert self.throttler.is_limiting assert self.handler == ["MESSAGE"] * 5 assert self.dropped == ["MESSAGE"] assert self.throttler.qsize == 0 assert self.throttler.used() == 1 assert self.throttler.recv_count == 6 assert self.throttler.sent_count == 5 def test_advance_time_when_at_limit_dropped_message(self): # Arrange item = "MESSAGE" # Act: Send 6 items self.throttler.send(item) self.throttler.send(item) self.throttler.send(item) self.throttler.send(item) self.throttler.send(item) self.throttler.send(item) # Act: Trigger refresh token time alert events = self.clock.advance_time(1_000_000_000) events[0].handle_py() # Assert: Remaining items sent assert self.clock.timer_names() == [] # No longer timing to process assert self.throttler.is_limiting is False assert self.handler == ["MESSAGE"] * 5 assert self.dropped == ["MESSAGE"] assert self.throttler.qsize == 0 assert self.throttler.used() == 0 assert self.throttler.recv_count == 6 assert self.throttler.sent_count == 5