this repo has no description
1mod common; 2use common::{base_url, client}; 3use reqwest::StatusCode; 4use serde_json::json; 5#[tokio::test] 6#[ignore = "rate limiting is disabled in test environment"] 7async fn test_login_rate_limiting() { 8 let client = client(); 9 let url = format!("{}/xrpc/com.atproto.server.createSession", base_url().await); 10 let payload = json!({ 11 "identifier": "nonexistent_user_for_rate_limit_test", 12 "password": "wrongpassword" 13 }); 14 let mut rate_limited_count = 0; 15 let mut auth_failed_count = 0; 16 for _ in 0..15 { 17 let res = client 18 .post(&url) 19 .json(&payload) 20 .send() 21 .await 22 .expect("Request failed"); 23 match res.status() { 24 StatusCode::TOO_MANY_REQUESTS => { 25 rate_limited_count += 1; 26 } 27 StatusCode::UNAUTHORIZED => { 28 auth_failed_count += 1; 29 } 30 status => { 31 panic!("Unexpected status: {}", status); 32 } 33 } 34 } 35 assert!( 36 rate_limited_count > 0, 37 "Expected at least one rate-limited response after 15 login attempts. Got {} auth failures and {} rate limits.", 38 auth_failed_count, 39 rate_limited_count 40 ); 41} 42#[tokio::test] 43#[ignore = "rate limiting is disabled in test environment"] 44async fn test_password_reset_rate_limiting() { 45 let client = client(); 46 let url = format!( 47 "{}/xrpc/com.atproto.server.requestPasswordReset", 48 base_url().await 49 ); 50 let mut rate_limited_count = 0; 51 let mut success_count = 0; 52 for i in 0..8 { 53 let payload = json!({ 54 "email": format!("ratelimit_test_{}@example.com", i) 55 }); 56 let res = client 57 .post(&url) 58 .json(&payload) 59 .send() 60 .await 61 .expect("Request failed"); 62 match res.status() { 63 StatusCode::TOO_MANY_REQUESTS => { 64 rate_limited_count += 1; 65 } 66 StatusCode::OK => { 67 success_count += 1; 68 } 69 status => { 70 panic!("Unexpected status: {} - {:?}", status, res.text().await); 71 } 72 } 73 } 74 assert!( 75 rate_limited_count > 0, 76 "Expected rate limiting after {} password reset requests. Got {} successes.", 77 success_count + rate_limited_count, 78 success_count 79 ); 80} 81#[tokio::test] 82#[ignore = "rate limiting is disabled in test environment"] 83async fn test_account_creation_rate_limiting() { 84 let client = client(); 85 let url = format!( 86 "{}/xrpc/com.atproto.server.createAccount", 87 base_url().await 88 ); 89 let mut rate_limited_count = 0; 90 let mut other_count = 0; 91 for i in 0..15 { 92 let unique_id = uuid::Uuid::new_v4(); 93 let payload = json!({ 94 "handle": format!("ratelimit_{}_{}", i, unique_id), 95 "email": format!("ratelimit_{}_{}@example.com", i, unique_id), 96 "password": "testpassword123" 97 }); 98 let res = client 99 .post(&url) 100 .json(&payload) 101 .send() 102 .await 103 .expect("Request failed"); 104 match res.status() { 105 StatusCode::TOO_MANY_REQUESTS => { 106 rate_limited_count += 1; 107 } 108 _ => { 109 other_count += 1; 110 } 111 } 112 } 113 assert!( 114 rate_limited_count > 0, 115 "Expected rate limiting after account creation attempts. Got {} other responses and {} rate limits.", 116 other_count, 117 rate_limited_count 118 ); 119} 120#[tokio::test] 121async fn test_valkey_connection() { 122 if std::env::var("VALKEY_URL").is_err() { 123 println!("VALKEY_URL not set, skipping Valkey connection test"); 124 return; 125 } 126 let valkey_url = std::env::var("VALKEY_URL").unwrap(); 127 let client = redis::Client::open(valkey_url.as_str()).expect("Failed to create Redis client"); 128 let mut conn = client 129 .get_multiplexed_async_connection() 130 .await 131 .expect("Failed to connect to Valkey"); 132 let pong: String = redis::cmd("PING") 133 .query_async(&mut conn) 134 .await 135 .expect("PING failed"); 136 assert_eq!(pong, "PONG"); 137 let _: () = redis::cmd("SET") 138 .arg("test_key") 139 .arg("test_value") 140 .arg("EX") 141 .arg(10) 142 .query_async(&mut conn) 143 .await 144 .expect("SET failed"); 145 let value: String = redis::cmd("GET") 146 .arg("test_key") 147 .query_async(&mut conn) 148 .await 149 .expect("GET failed"); 150 assert_eq!(value, "test_value"); 151 let _: () = redis::cmd("DEL") 152 .arg("test_key") 153 .query_async(&mut conn) 154 .await 155 .expect("DEL failed"); 156} 157#[tokio::test] 158async fn test_distributed_rate_limiter_directly() { 159 if std::env::var("VALKEY_URL").is_err() { 160 println!("VALKEY_URL not set, skipping distributed rate limiter test"); 161 return; 162 } 163 use bspds::cache::{DistributedRateLimiter, RedisRateLimiter}; 164 let valkey_url = std::env::var("VALKEY_URL").unwrap(); 165 let client = redis::Client::open(valkey_url.as_str()).expect("Failed to create Redis client"); 166 let conn = client 167 .get_connection_manager() 168 .await 169 .expect("Failed to get connection manager"); 170 let rate_limiter = RedisRateLimiter::new(conn); 171 let test_key = format!("test_rate_limit_{}", uuid::Uuid::new_v4()); 172 let limit = 5; 173 let window_ms = 60_000; 174 for i in 0..limit { 175 let allowed = rate_limiter 176 .check_rate_limit(&test_key, limit, window_ms) 177 .await; 178 assert!( 179 allowed, 180 "Request {} should have been allowed (limit: {})", 181 i + 1, 182 limit 183 ); 184 } 185 let allowed = rate_limiter 186 .check_rate_limit(&test_key, limit, window_ms) 187 .await; 188 assert!( 189 !allowed, 190 "Request {} should have been rate limited (limit: {})", 191 limit + 1, 192 limit 193 ); 194 let allowed = rate_limiter 195 .check_rate_limit(&test_key, limit, window_ms) 196 .await; 197 assert!(!allowed, "Subsequent request should also be rate limited"); 198}