1+ from hrflow .core .rate_limit import rate_limiter
2+ import pytest
3+ from time import time
4+
5+ @pytest .mark .rate_limit
6+ def test_rate_limit_no_params ():
7+ i = 0
8+
9+ @rate_limiter
10+ def increment ():
11+ nonlocal i
12+ i += 1
13+
14+ start_time = time ()
15+ for round in range (5 ):
16+ increment ()
17+ assert i == round + 1 , ("The sub function wrapper with rate limiting must have" ,
18+ "a side effect, but the result is inconsistent with what it should be" )
19+
20+ end_time = time ()
21+ duration = end_time - start_time
22+
23+ assert duration < 1 , "5 calls should be less than 1 second"
24+
25+ @pytest .mark .rate_limit
26+ def test_rate_limit_no_params_and_with_function_params ():
27+ i = 0
28+ memory = None
29+
30+ @rate_limiter
31+ def increment (round : int ):
32+ nonlocal i
33+ nonlocal memory
34+
35+ i += 1
36+ memory = round
37+
38+
39+ start_time = time ()
40+ for round in range (5 ):
41+ increment (round )
42+ assert i == round + 1 , ("The sub function wrapper with rate limiting must have" ,
43+ "a side effect, but the result is inconsistent with what it should be" )
44+ assert memory == round , ("The sub function wrapper with rate limiting must" ,
45+ "have a side effect, but the result is inconsistent with what it should be" )
46+
47+ end_time = time ()
48+ duration = end_time - start_time
49+
50+ assert duration < 1 , "5 calls should be less than 1 second"
51+
52+ @pytest .mark .rate_limit
53+ def test_rate_limit_sleep_per_req_and_with_function_params ():
54+ min_sleep_per_request = 1 # second(s)
55+ delta_duration = 0.1
56+ i = 0
57+ memory = None
58+
59+ @rate_limiter
60+ def increment (round : int ):
61+ nonlocal i
62+ nonlocal memory
63+
64+ i += 1
65+ memory = round
66+
67+
68+ global_start_time = time ()
69+ round_count = 5
70+ for round in range (round_count ):
71+ round_start_time = time ()
72+ increment (round , min_sleep_per_request = min_sleep_per_request )
73+ assert i == round + 1 , ("The sub function wrapper with rate limiting must have" ,
74+ "a side effect, but the result is inconsistent with what it should be" )
75+ assert memory == round , ("The sub function wrapper with rate limiting must" ,
76+ "have a side effect, but the result is inconsistent with what it should be" )
77+ round_duration = time () - round_start_time
78+ assert round_duration + delta_duration >= min_sleep_per_request , (
79+ "function call must be more than {min_sleep_per_request} second"
80+ )
81+
82+ end_time = time ()
83+ global_duration = end_time - global_start_time
84+
85+ assert global_duration + delta_duration >= min_sleep_per_request * round_count , (
86+ "5 calls should be more than 5 seconds"
87+ )
88+
89+ @pytest .mark .rate_limit
90+ def test_rate_limit_with_rpm ():
91+ SECONDS_IN_MINUTE = 60
92+ max_requests_per_minute = 5 # second(s)
93+ num_requests = 8
94+ delta_duration = 0.1
95+ i = 0
96+
97+ @rate_limiter
98+ def increment ():
99+ # less than 0.1 second function
100+ nonlocal i
101+ i += 1
102+
103+ for round in range (num_requests ):
104+ print (round )
105+ round_start_time = time ()
106+ increment (max_requests_per_minute = max_requests_per_minute )
107+ assert i == round + 1 , ("The sub function wrapper with rate limiting must have" ,
108+ "a side effect, but the result is inconsistent with what it should be" )
109+
110+ round_duration = time () - round_start_time
111+ if round != 0 and round % max_requests_per_minute == 0 :
112+ assert round_duration + delta_duration >= SECONDS_IN_MINUTE , (
113+ f"unexpected more than { max_requests_per_minute } req per minute"
114+ )
115+ else :
116+ assert round_duration <= delta_duration , (
117+ f"function call must be less than { delta_duration } second(s)"
118+ )
119+
120+ @pytest .mark .rate_limit
121+ def test_rate_limit_with_rpm_and_sleep_per_req ():
122+ SECONDS_IN_MINUTE = 60
123+ min_sleep_per_request = 1 # second(s)
124+ max_requests_per_minute = 5 # second(s)
125+ num_requests = 8
126+ delta_duration = 0.1
127+ i = 0
128+
129+ @rate_limiter
130+ def increment ():
131+ # less than 0.1 second function
132+ nonlocal i
133+ i += 1
134+
135+ for round in range (num_requests ):
136+ print (round )
137+ round_start_time = time ()
138+ increment (
139+ max_requests_per_minute = max_requests_per_minute ,
140+ min_sleep_per_request = min_sleep_per_request
141+ )
142+ assert i == round + 1 , ("The sub function wrapper with rate limiting must have" ,
143+ "a side effect, but the result is inconsistent with what it should be" )
144+
145+ round_duration = time () - round_start_time
146+ if round != 0 and round % max_requests_per_minute == 0 :
147+ normilized_duration = round_duration + delta_duration \
148+ + min_sleep_per_request * max_requests_per_minute
149+ assert normilized_duration >= SECONDS_IN_MINUTE , (
150+ f"unexpected more than { max_requests_per_minute } req per minute"
151+ )
152+ else :
153+ assert round_duration + delta_duration >= min_sleep_per_request , (
154+ "function call must be more than {min_sleep_per_request} second"
155+ )
0 commit comments