@@ -160,3 +160,39 @@ def has_budget(idx: int, weight: int) -> bool:
160160
161161 assert isinstance (result , Success )
162162 assert client .key_index == 1
163+
164+
165+ def test_rotate_key_does_not_reset_when_budget_available (monkeypatch : pytest .MonkeyPatch ) -> None :
166+ """Rotation should not reset key state if the key still has budget."""
167+ settings = BitvavoSettings (
168+ api_keys = [{"key" : "k1" , "secret" : "s1" }, {"key" : "k2" , "secret" : "s2" }],
169+ )
170+ manager = RateLimitManager (settings .default_rate_limit , settings .rate_limit_buffer )
171+ client = HTTPClient (settings , manager )
172+
173+ manager .state [1 ]["remaining" ] = 500
174+ manager .state [1 ]["resetAt" ] = 0
175+
176+ with patch .object (manager , "reset_key" ) as mock_reset :
177+ client ._rotate_key () # noqa: SLF001
178+
179+ assert client .key_index == 1
180+ mock_reset .assert_not_called ()
181+
182+
183+ def test_rotate_key_resets_expired_key (monkeypatch : pytest .MonkeyPatch ) -> None :
184+ """Rotation should reset key if its budget is exhausted and reset time passed."""
185+ settings = BitvavoSettings (
186+ api_keys = [{"key" : "k1" , "secret" : "s1" }, {"key" : "k2" , "secret" : "s2" }],
187+ )
188+ manager = RateLimitManager (settings .default_rate_limit , settings .rate_limit_buffer )
189+ client = HTTPClient (settings , manager )
190+
191+ manager .state [1 ]["remaining" ] = 0
192+ manager .state [1 ]["resetAt" ] = 0
193+
194+ with patch .object (manager , "reset_key" ) as mock_reset , patch ("time.time" , return_value = 1 ):
195+ client ._rotate_key () # noqa: SLF001
196+
197+ assert client .key_index == 1
198+ mock_reset .assert_called_once_with (1 )
0 commit comments