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