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}