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}