()
| 51 | |
| 52 | #[test] |
| 53 | fn test_circuit_breaker_functionality() { |
| 54 | let config = RateLimitConfig { |
| 55 | max_requests: 1000, // High limit to focus on circuit breaker |
| 56 | window_duration: Duration::from_secs(60), |
| 57 | per_ip_limiting: false, |
| 58 | max_tracked_ips: 100, |
| 59 | cleanup_interval: Duration::from_secs(60), |
| 60 | }; |
| 61 | |
| 62 | let circuit_config = CircuitBreakerConfig { |
| 63 | failure_threshold: 3, |
| 64 | timeout_duration: Duration::from_millis(100), |
| 65 | success_threshold: 2, |
| 66 | enabled: true, |
| 67 | }; |
| 68 | |
| 69 | let limiter = RateLimiter::with_config(config, circuit_config); |
| 70 | |
| 71 | // Initially circuit should be closed |
| 72 | assert_eq!(limiter.get_circuit_state(), CircuitState::Closed); |
| 73 | |
| 74 | // Record failures to open the circuit |
| 75 | for _ in 0..3 { |
| 76 | limiter.record_failure(); |
| 77 | } |
| 78 | |
| 79 | // Circuit should now be open |
| 80 | assert_eq!(limiter.get_circuit_state(), CircuitState::Open); |
| 81 | |
| 82 | // Requests should be rejected |
| 83 | assert!(limiter.check_request(None).is_err()); |
| 84 | |
| 85 | // Wait for timeout |
| 86 | std::thread::sleep(Duration::from_millis(150)); |
| 87 | |
| 88 | // Should transition to half-open on next request |
| 89 | assert!(limiter.check_request(None).is_ok()); |
| 90 | assert_eq!(limiter.get_circuit_state(), CircuitState::HalfOpen); |
| 91 | |
| 92 | // Record success to close circuit |
| 93 | assert!(limiter.check_request(None).is_ok()); |
| 94 | assert_eq!(limiter.get_circuit_state(), CircuitState::Closed); |
| 95 | } |
| 96 | |
| 97 | #[test] |
| 98 | fn test_per_ip_isolation() { |
nothing calls this directly
no test coverage detected