简体   繁体   English

如何测试限速算法?

[英]How to test a rate limiting algorithm?

This is the sliding window rate limiting algorithm I got from this page :这是我从这个页面得到的滑动 window 速率限制算法:

from time import time, sleep

class SlidingWindow:

    def __init__(self, capacity, time_unit, forward_callback, drop_callback):
        self.capacity = capacity
        self.time_unit = time_unit
        self.forward_callback = forward_callback
        self.drop_callback = drop_callback

        self.cur_time = time()
        self.pre_count = capacity
        self.cur_count = 0

    def handle(self, packet):

        if (time() - self.cur_time) > self.time_unit:
            self.cur_time = time()
            self.pre_count = self.cur_count
            self.cur_count = 0

        ec = (self.pre_count * (self.time_unit - (time() - self.cur_time)) / self.time_unit) + self.cur_count

        if (ec > self.capacity):
            return self.drop_callback(packet)

        self.cur_count += 1
        return self.forward_callback(packet)


def forward(packet):
    print("Packet Forwarded: " + str(packet))


def drop(packet):
    print("Packet Dropped: " + str(packet))


throttle = SlidingWindow(5, 1, forward, drop)

packet = 0

while True:
    sleep(0.1)
    throttle.handle(packet)
    packet += 1

How can I test this time sensitive algorithm in pytest?如何在 pytest 中测试这种时间敏感算法? I want to test forward_callback is getting called when the request (by calling handle() ) passes, and drop_callback is getting called when the request fails.我想测试forward_callback在请求(通过调用handle() )通过时被调用,而drop_callback在请求失败时被调用。 How could I simulate a loop in pytest?如何模拟 pytest 中的循环?

You should test the SlidingWindow class directly, without testing the loop in the end.您应该直接测试SlidingWindow class,而不是最后测试循环。 The reason is that the SlidingWindow is independent and it should work regardless of how it's used.原因是SlidingWindow是独立的,无论如何使用它都应该工作。

Since the class is heavily dependent on the current time, you can use pytest-freezegun to simulate the time of the requests.由于 class 严重依赖当前时间,因此可以使用pytest-freezegun来模拟请求的时间。

A test example would be something similar to:测试示例类似于:

from datetime import datetime, timedelta
from mock import MagicMock, call

from sliding_window import SlidingWindow


def test_moving_date(freezer, mg):
    start = datetime(year=2012, month=1, day=14, hour=12, minute=0, second=1)
    freezer.move_to(start)
    forward, drop = MagicMock(), MagicMock()
    throttle = SlidingWindow(5, 1, forward, drop)  # allow rate ~5 per second

    # first two should be accepted, while the 3rd should be dropped
    throttle.handle(0)
    freezer.move_to(start + timedelta(milliseconds=200))
    throttle.handle(1)
    freezer.move_to(start + timedelta(milliseconds=250))
    throttle.handle(2)

    forward.assert_has_calls(calls=[call(0), call(1)])
    drop.assert_called_once_with(2)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM