use r_token::RTokenManager;
use std::sync::Arc;
use std::thread;
use std::time::Instant;
#[cfg(test)]
mod performance {
use super::*;
#[test]
fn login_performance() {
let manager = RTokenManager::new();
let iterations = 1000;
let start = Instant::now();
for i in 0..iterations {
let user_id = format!("user_{}", i);
manager.login(&user_id, 3600).unwrap();
}
let duration = start.elapsed();
println!("Created {} tokens in {:?}", iterations, duration);
println!("Average time per token: {:?}", duration / iterations);
assert!(duration.as_millis() < (iterations as u128));
}
#[test]
fn logout_performance() {
let manager = RTokenManager::new();
let iterations = 1000;
let tokens: Vec<String> = (0..iterations)
.map(|i| manager.login(&format!("user_{}", i), 3600).unwrap())
.collect();
let start = Instant::now();
for token in tokens {
manager.logout(&token).unwrap();
}
let duration = start.elapsed();
println!("Removed {} tokens in {:?}", iterations, duration);
println!("Average time per logout: {:?}", duration / iterations);
}
#[test]
fn concurrent_load() {
let manager = Arc::new(RTokenManager::new());
let num_threads = 10;
let operations_per_thread = 100;
let start = Instant::now();
let handles: Vec<_> = (0..num_threads)
.map(|thread_id| {
let manager_clone = Arc::clone(&manager);
thread::spawn(move || {
for i in 0..operations_per_thread {
let user_id = format!("thread_{}_user_{}", thread_id, i);
let token = manager_clone.login(&user_id, 3600).unwrap();
thread::yield_now();
manager_clone.logout(&token).unwrap();
}
})
})
.collect();
for handle in handles {
handle.join().unwrap();
}
let duration = start.elapsed();
let total_operations = num_threads * operations_per_thread * 2;
println!(
"Completed {} operations across {} threads in {:?}",
total_operations, num_threads, duration
);
println!(
"Average time per operation: {:?}",
duration / (total_operations as u32)
);
}
#[test]
fn memory_usage_with_many_tokens() {
let manager = RTokenManager::new();
let num_tokens = 10_000;
let mut tokens = Vec::with_capacity(num_tokens);
for i in 0..num_tokens {
let token = manager.login(&format!("user_{}", i), 3600).unwrap();
tokens.push(token);
}
println!("Created {} tokens", num_tokens);
for token in tokens {
manager.logout(&token).unwrap();
}
println!("Cleaned up {} tokens", num_tokens);
}
#[test]
fn rapid_login_logout_cycles() {
let manager = RTokenManager::new();
let cycles = 1000;
let start = Instant::now();
for i in 0..cycles {
let user_id = format!("cycling_user_{}", i);
let token = manager.login(&user_id, 3600).unwrap();
manager.logout(&token).unwrap();
}
let duration = start.elapsed();
println!("Completed {} login-logout cycles in {:?}", cycles, duration);
println!("Average cycle time: {:?}", duration / cycles);
}
#[test]
fn clone_overhead() {
let manager1 = RTokenManager::new();
let iterations = 1000;
let start = Instant::now();
for _ in 0..iterations {
let _cloned = manager1.clone();
}
let duration = start.elapsed();
println!("Cloned manager {} times in {:?}", iterations, duration);
println!("Average clone time: {:?}", duration / iterations);
assert!(duration.as_micros() < ((iterations * 10) as u128));
}
#[test]
fn contention_under_load() {
use std::sync::Barrier;
let manager = Arc::new(RTokenManager::new());
let num_threads = 20;
let barrier = Arc::new(Barrier::new(num_threads));
let handles: Vec<_> = (0..num_threads)
.map(|thread_id| {
let manager_clone = Arc::clone(&manager);
let barrier_clone = Arc::clone(&barrier);
thread::spawn(move || {
barrier_clone.wait();
let user_id = format!("concurrent_user_{}", thread_id);
manager_clone.login(&user_id, 3600).unwrap()
})
})
.collect();
let tokens: Vec<String> = handles.into_iter().map(|h| h.join().unwrap()).collect();
for i in 0..tokens.len() {
for j in (i + 1)..tokens.len() {
assert_ne!(tokens[i], tokens[j]);
}
}
}
}