def test_in_memory_expiry_moving_window(self): with hiro.Timeline().freeze() as timeline: storage = MemoryStorage() limiter = MovingWindowRateLimiter(storage) per_min = PER_MINUTE(10) per_sec = PER_SECOND(1) for i in range(0, 2): for i in range(0, 10): self.assertTrue(limiter.hit(per_min)) timeline.forward(60) self.assertTrue(limiter.hit(per_sec)) time.sleep(1) self.assertEqual([], storage.events[per_min.key_for()])
def test_moving_window_redis(self): storage = RedisStorage("redis://localhost:6379") limiter = MovingWindowRateLimiter(storage) limit = PER_SECOND(10) start = time.time() for i in range(0,10): self.assertTrue(limiter.hit(limit)) time.sleep(0.095) self.assertFalse(limiter.hit(limit)) time.sleep(0.2) self.assertTrue(limiter.hit(limit)) self.assertTrue(limiter.hit(limit)) self.assertFalse(limiter.hit(limit)) self.assertTrue(storage.storage.llen(limit.key_for()) == 10)
def test_moving_window_in_memory(self): storage = MemoryStorage() limiter = MovingWindowRateLimiter(storage) with hiro.Timeline().freeze() as timeline: limit = PER_MINUTE(10) for i in range(0,5): self.assertTrue(limiter.hit(limit)) self.assertTrue(limiter.hit(limit)) timeline.forward(10) self.assertFalse(limiter.hit(limit)) timeline.forward(20) self.assertTrue(limiter.hit(limit)) self.assertTrue(limiter.hit(limit)) self.assertFalse(limiter.hit(limit)) self.assertEqual(len(storage.events[limit.key_for()]), 10)
def test_moving_window_redis(self): storage = RedisStorage("redis://localhost:6379") limiter = MovingWindowRateLimiter(storage) limit = PER_SECOND(10, 2) for i in range(0,10): self.assertTrue(limiter.hit(limit)) self.assertEqual(limiter.get_window_stats(limit)[1], 10 - (i + 1)) time.sleep(2*0.095) self.assertFalse(limiter.hit(limit)) time.sleep(0.4) self.assertTrue(limiter.hit(limit)) self.assertTrue(limiter.hit(limit)) self.assertEqual(limiter.get_window_stats(limit)[1], 0)
def test_moving_window_in_memory(self): storage = MemoryStorage() limiter = MovingWindowRateLimiter(storage) with hiro.Timeline().freeze() as timeline: limit = PER_MINUTE(10) for i in range(0,5): self.assertTrue(limiter.hit(limit)) self.assertTrue(limiter.hit(limit)) self.assertEqual( limiter.get_window_stats(limit)[1], 10 - ((i + 1) * 2) ) timeline.forward(10) self.assertEqual(limiter.get_window_stats(limit)[1], 0) self.assertFalse(limiter.hit(limit)) timeline.forward(20) self.assertEqual(limiter.get_window_stats(limit)[1], 2) self.assertEqual(limiter.get_window_stats(limit)[0], int(time.time() + 30)) timeline.forward(31) self.assertEqual(limiter.get_window_stats(limit)[1], 10)
def test_large_dataset_redis_moving_window_expiry(self): storage = RedisStorage("redis://localhost:6379") limiter = MovingWindowRateLimiter(storage) limit = PER_SECOND(1000) keys_start = storage.storage.keys('%s/*' % limit.namespace) # 100 routes fake_routes = [uuid4().hex for _ in range(0, 100)] # go as fast as possible in 2 seconds. start = time.time() def smack(e): while not e.is_set(): self.assertTrue(limiter.hit(limit, random.choice(fake_routes))) events = [threading.Event() for _ in range(0, 100)] threads = [threading.Thread(target=smack, args=(e, )) for e in events] [k.start() for k in threads] while time.time() - start < 2: time.sleep(0.1) [k.set() for k in events] time.sleep(2) self.assertTrue(storage.storage.keys("%s/*" % limit.namespace) == [])
def test_pluggable_storage_moving_window(self): class MyStorage(Storage): STORAGE_SCHEME = "mystorage" def incr(self, key, expiry, elastic_expiry=False): return def get(self, key): return 0 def get_expiry(self, key): return time.time() def acquire_entry(self, *a, **k): return True def get_moving_window(self, *a, **k): return (time.time(), 1) storage = storage_from_string("mystorage://") self.assertTrue(isinstance(storage, MyStorage)) MovingWindowRateLimiter(storage)