AIstudioProxyAPI / tests /test_quota_rotation_fix.py
peijun1's picture
Deploy AI Studio Proxy API to Hugging Face Spaces
a5784e9
Raw
History Blame Contribute Delete
5.69 kB
#!/usr/bin/env python3
"""
Test to verify the fix for quota rotation stream termination issue.
This test simulates the exact scenario from the bug report:
1. Quota exceeded triggers rotation
2. Rotation completes successfully
3. Stream receives empty DONE signal (Body=0, Reason=0)
4. System should NOT complete the stream, but ignore the stale DONE
The fix ensures that post-rotation empty DONE signals are properly
identified as stale zombie packets and ignored.
"""
import time
import pytest
from config.global_state import GlobalState
class TestQuotaRotationFix:
"""Test the quota rotation fix for stream termination issue"""
def setup_method(self):
"""Reset GlobalState before each test"""
GlobalState.IS_QUOTA_EXCEEDED = False
GlobalState.IS_RECOVERING = False
GlobalState.LAST_ROTATION_TIMESTAMP = 0.0
GlobalState.queued_request_count = 0
def test_post_rotation_zombie_detection_various_timestamps(self):
"""Test zombie detection works correctly for various rotation timestamps"""
# Simulate the exact scenario from the bug report:
# Rotation completes at t=0, DONE received at t=0.9 (< 1 second)
current_time = time.time()
GlobalState.LAST_ROTATION_TIMESTAMP = current_time - 0.9 # 0.9 seconds ago
# Verify the rotation timestamp logic
just_rotated = (time.time() - GlobalState.LAST_ROTATION_TIMESTAMP < 15.0)
recently_recovered = (time.time() - GlobalState.LAST_ROTATION_TIMESTAMP < 30.0)
assert just_rotated is True, "Should detect recent rotation"
assert recently_recovered is True, "Should detect recent recovery"
# Test enhanced rotation detection (45 second window)
time_since_rotation = time.time() - GlobalState.LAST_ROTATION_TIMESTAMP
is_recent_rotation = time_since_rotation < 45.0
assert is_recent_rotation is True, "Should detect rotation within 45s window"
def test_post_rotation_zombie_detection_edge_cases(self):
"""Test edge cases for post-rotation zombie detection"""
# Test case 1: Very recent rotation (within 15s)
current_time = time.time()
GlobalState.LAST_ROTATION_TIMESTAMP = current_time - 10.0 # 10 seconds ago
just_rotated = (time.time() - GlobalState.LAST_ROTATION_TIMESTAMP < 15.0)
recently_recovered = (time.time() - GlobalState.LAST_ROTATION_TIMESTAMP < 30.0)
assert just_rotated is True
assert recently_recovered is True
# Test case 2: Moderate recent rotation (within 30s)
GlobalState.LAST_ROTATION_TIMESTAMP = current_time - 20.0 # 20 seconds ago
just_rotated = (time.time() - GlobalState.LAST_ROTATION_TIMESTAMP < 15.0)
recently_recovered = (time.time() - GlobalState.LAST_ROTATION_TIMESTAMP < 30.0)
assert just_rotated is False
assert recently_recovered is True
# Test case 3: Old rotation (outside 30s)
GlobalState.LAST_ROTATION_TIMESTAMP = current_time - 60.0 # 60 seconds ago
just_rotated = (time.time() - GlobalState.LAST_ROTATION_TIMESTAMP < 15.0)
recently_recovered = (time.time() - GlobalState.LAST_ROTATION_TIMESTAMP < 30.0)
assert just_rotated is False
assert recently_recovered is False
def test_enhanced_zombie_detection_45s_window(self):
"""Test the enhanced 45-second window for zombie detection"""
current_time = time.time()
# Test various timestamps within the 45s window
test_cases = [
(5.0, True), # 5 seconds ago - should detect
(15.0, True), # 15 seconds ago - should detect
(30.0, True), # 30 seconds ago - should detect
(40.0, True), # 40 seconds ago - should detect
(50.0, False), # 50 seconds ago - should NOT detect
(100.0, False) # 100 seconds ago - should NOT detect
]
for seconds_ago, should_detect in test_cases:
GlobalState.LAST_ROTATION_TIMESTAMP = current_time - seconds_ago
time_since_rotation = time.time() - GlobalState.LAST_ROTATION_TIMESTAMP
is_recent_rotation = time_since_rotation < 45.0
assert is_recent_rotation == should_detect, \
f"Rotation {seconds_ago}s ago should {'detect' if should_detect else 'NOT detect'} as recent"
def test_global_state_reset_quota_status(self):
"""Test that quota status reset works correctly"""
# Set quota exceeded state
GlobalState.set_quota_exceeded("Test quota exceeded")
assert GlobalState.IS_QUOTA_EXCEEDED is True
# Reset quota status (simulating what happens after rotation)
GlobalState.reset_quota_status()
assert GlobalState.IS_QUOTA_EXCEEDED is False
# Note: reset_quota_status doesn't update LAST_ROTATION_TIMESTAMP
# After reset, timestamp should be updated during finish_recovery
original_timestamp = GlobalState.LAST_ROTATION_TIMESTAMP
time.sleep(0.1) # Small delay
GlobalState.finish_recovery()
assert GlobalState.LAST_ROTATION_TIMESTAMP > original_timestamp
def test_recovery_state_management(self):
"""Test recovery state transitions work correctly"""
# Start recovery (simulating quota detection)
GlobalState.start_recovery()
assert GlobalState.IS_RECOVERING is True
# Finish recovery (simulating successful rotation)
GlobalState.finish_recovery()
assert GlobalState.IS_RECOVERING is False
assert GlobalState.LAST_ROTATION_TIMESTAMP > 0
if __name__ == "__main__":
# Run the tests
pytest.main([__file__, "-v"])