use std::collections::HashMap;
use std::fs;
use std::time::Duration;
use tokio::time::sleep;
use warp::test::request;
use mockserver::config::Endpoint;
use mockserver::handler::routes;
use mockserver::rate_limit::{new_rate_limit, RateLimit};
#[tokio::test]
async fn test_request_under_limit() {
let mut endpoints = HashMap::new();
endpoints.insert(
"/test".to_string(),
Endpoint {
method: vec!["GET".to_string()],
file: "test_response.json".to_string(),
status_code: Some(200),
authentication: None,
delay: None,
rate_limit: Some(RateLimit {
requests: 2,
window_ms: 1000,
}),
},
);
fs::write("responses/test_response.json", "{\"message\": \"ok\"}").unwrap();
let rate_limiter = new_rate_limit();
let api = routes(endpoints, "responses".to_string(), rate_limiter);
let resp = request()
.method("GET")
.path("/test")
.reply(&api)
.await;
assert_eq!(resp.status(), 200);
let resp = request()
.method("GET")
.path("/test")
.reply(&api)
.await;
assert_eq!(resp.status(), 200);
}
#[tokio::test]
async fn test_exceeding_rate_limit() {
let mut endpoints = HashMap::new();
endpoints.insert(
"/rate_limited".to_string(),
Endpoint {
method: vec!["GET".to_string()],
file: "test_response.json".to_string(),
status_code: Some(200),
authentication: None,
delay: None,
rate_limit: Some(RateLimit {
requests: 2,
window_ms: 1000,
}),
},
);
fs::write("responses/test_response.json", "{\"message\": \"ok\"}").unwrap();
let rate_limiter = new_rate_limit();
let api = routes(endpoints, "responses".to_string(), rate_limiter);
let resp = request()
.method("GET")
.path("/rate_limited")
.reply(&api)
.await;
assert_eq!(resp.status(), 200);
let resp = request()
.method("GET")
.path("/rate_limited")
.reply(&api)
.await;
assert_eq!(resp.status(), 200);
let resp = request()
.method("GET")
.path("/rate_limited")
.reply(&api)
.await;
assert_eq!(resp.status(), 429);
}
#[tokio::test]
async fn test_different_endpoints_have_separate_limits() {
let mut endpoints = HashMap::new();
endpoints.insert(
"/endpoint1".to_string(),
Endpoint {
method: vec!["GET".to_string()],
file: "test_response.json".to_string(),
status_code: Some(200),
authentication: None,
delay: None,
rate_limit: Some(RateLimit {
requests: 1,
window_ms: 1000,
}),
},
);
endpoints.insert(
"/endpoint2".to_string(),
Endpoint {
method: vec!["GET".to_string()],
file: "test_response.json".to_string(),
status_code: Some(200),
authentication: None,
delay: None,
rate_limit: Some(RateLimit {
requests: 1,
window_ms: 1000,
}),
},
);
fs::write("responses/test_response.json", "{\"message\": \"ok\"}").unwrap();
let rate_limiter = new_rate_limit();
let api = routes(endpoints, "responses".to_string(), rate_limiter);
let resp = request()
.method("GET")
.path("/endpoint1")
.reply(&api)
.await;
assert_eq!(resp.status(), 200);
let resp = request()
.method("GET")
.path("/endpoint2")
.reply(&api)
.await;
assert_eq!(resp.status(), 200);
}
#[tokio::test]
async fn test_rate_limit_resets_after_window() {
let mut endpoints = HashMap::new();
endpoints.insert(
"/reset_test".to_string(),
Endpoint {
method: vec!["GET".to_string()],
file: "test_response.json".to_string(),
status_code: Some(200),
authentication: None,
delay: None,
rate_limit: Some(RateLimit {
requests: 1,
window_ms: 500,
}),
},
);
fs::write("responses/test_response.json", "{\"message\": \"ok\"}").unwrap();
let rate_limiter = new_rate_limit();
let api = routes(endpoints, "responses".to_string(), rate_limiter);
let resp = request()
.method("GET")
.path("/reset_test")
.reply(&api)
.await;
assert_eq!(resp.status(), 200);
let resp = request()
.method("GET")
.path("/reset_test")
.reply(&api)
.await;
assert_eq!(resp.status(), 429);
sleep(Duration::from_millis(600)).await;
let resp = request()
.method("GET")
.path("/reset_test")
.reply(&api)
.await;
assert_eq!(resp.status(), 200);
}
#[tokio::test]
async fn test_different_methods_tracked_separately() {
let mut endpoints = HashMap::new();
endpoints.insert(
"/method_test".to_string(),
Endpoint {
method: vec!["GET".to_string(), "POST".to_string()],
file: "test_response.json".to_string(),
status_code: Some(200),
authentication: None,
delay: None,
rate_limit: Some(RateLimit {
requests: 1,
window_ms: 1000,
}),
},
);
fs::write("responses/test_response.json", "{\"message\": \"ok\"}").unwrap();
let rate_limiter = new_rate_limit();
let api = routes(endpoints, "responses".to_string(), rate_limiter);
let resp = request()
.method("GET")
.path("/method_test")
.reply(&api)
.await;
assert_eq!(resp.status(), 200);
let resp = request()
.method("GET")
.path("/method_test")
.reply(&api)
.await;
assert_eq!(resp.status(), 429);
let resp = request()
.method("POST")
.path("/method_test")
.reply(&api)
.await;
assert_eq!(resp.status(), 200);
}