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