use std::sync::Arc;
use std::time::Duration;
#[path = "../../common/mod.rs"]
mod common;
#[tokio::test]
#[cfg(feature = "sqlite")]
async fn test_pool_builder_basic_initialization() {
let config = dbnexus::DbConfig {
url: "sqlite::memory:".to_string(),
max_connections: 10,
min_connections: 2,
idle_timeout: 300,
acquire_timeout: 5000,
admin_role: "admin".to_string(),
..Default::default()
};
let pool = dbnexus::DbPool::with_config(config)
.await
.expect("Failed to create pool");
assert_eq!(pool.config().max_connections, 10);
assert_eq!(pool.config().min_connections, 2);
assert_eq!(pool.config().idle_timeout, 300);
assert_eq!(pool.config().acquire_timeout, 5000);
assert_eq!(pool.config().admin_role, "admin");
}
#[tokio::test]
#[cfg(feature = "sqlite")]
async fn test_pool_builder_default_values() {
let pool = common::make_sqlite_memory_pool().await;
assert_eq!(pool.config().max_connections, 20);
assert_eq!(pool.config().min_connections, 5);
assert_eq!(pool.config().idle_timeout, 300);
assert_eq!(pool.config().acquire_timeout, 5000);
assert_eq!(pool.config().admin_role, "admin");
}
#[tokio::test]
#[cfg(feature = "sqlite")]
async fn test_pool_builder_chained_configuration() {
let config = dbnexus::DbConfig {
url: "sqlite::memory:".to_string(),
max_connections: 15,
min_connections: 3,
..Default::default()
};
let pool = dbnexus::DbPool::with_config(config)
.await
.expect("Failed to create pool");
assert_eq!(pool.config().max_connections, 15);
assert_eq!(pool.config().min_connections, 3);
}
#[tokio::test]
#[cfg(feature = "sqlite")]
async fn test_pool_config_min_equals_max() {
let config = dbnexus::DbConfig {
url: "sqlite::memory:".to_string(),
max_connections: 5,
min_connections: 5,
..Default::default()
};
let pool = dbnexus::DbPool::with_config(config)
.await
.expect("Failed to create pool");
assert_eq!(pool.config().max_connections, 5);
assert_eq!(pool.config().min_connections, 5);
}
#[test]
fn test_pool_config_validation_min_greater_than_max() {
let config = dbnexus::DbConfig {
url: "sqlite::memory:".to_string(),
max_connections: 5,
min_connections: 10,
..Default::default()
};
assert!(config.max_connections < config.min_connections);
}
#[test]
fn test_pool_config_validation_zero_max_connections() {
let config = dbnexus::DbConfig {
url: "sqlite::memory:".to_string(),
max_connections: 0,
..Default::default()
};
assert_eq!(config.max_connections, 0);
}
#[test]
fn test_pool_config_validation_empty_url() {
let config = dbnexus::DbConfig {
url: "".to_string(),
..Default::default()
};
assert_eq!(config.url, "");
}
#[tokio::test]
#[cfg(feature = "sqlite")]
async fn test_pool_initial_status() {
let pool = common::make_sqlite_memory_pool().await;
let status = pool.status();
assert!(status.total <= pool.config().max_connections);
assert_eq!(status.active, 0);
assert_eq!(status.total, status.active + status.idle);
}
#[tokio::test]
#[cfg(feature = "sqlite")]
async fn test_pool_status_after_session_acquire() {
let pool = common::make_sqlite_memory_pool().await;
let initial_status = pool.status();
{
let _session = pool.get_session("admin").await.expect("Failed to get session");
let status = pool.status();
assert!(status.active >= 1);
assert!(status.total >= initial_status.total);
}
let final_status = pool.status();
assert_eq!(final_status.active, 0);
}
#[tokio::test]
#[cfg(feature = "sqlite")]
async fn test_pool_status_structure() {
let pool = common::make_sqlite_memory_pool().await;
let status = pool.status();
let _total: u32 = status.total;
let _active: u32 = status.active;
let _idle: u32 = status.idle;
let _wait_count: u32 = status.wait_count;
let _borrow_count: u64 = status.borrow_count;
let _max_active: u32 = status.max_active;
assert_eq!(status.total, status.active + status.idle);
}
#[tokio::test]
#[cfg(feature = "sqlite")]
async fn test_pool_max_connections_limit() {
let max_connections = 3;
let config = dbnexus::DbConfig {
url: "sqlite::memory:".to_string(),
max_connections,
min_connections: 1,
acquire_timeout: 1000, ..Default::default()
};
let pool = dbnexus::DbPool::with_config(config)
.await
.expect("Failed to create pool");
let pool = Arc::new(pool);
let mut sessions = Vec::new();
for _ in 0..max_connections {
let session = pool.get_session("admin").await.expect("Failed to get session");
sessions.push(session);
}
let status = pool.status();
assert_eq!(status.active, max_connections);
let pool_clone = pool.clone();
let result = tokio::time::timeout(Duration::from_millis(500), async {
pool_clone.get_session("admin").await
})
.await;
assert!(
result.is_err() || result.unwrap().is_err(),
"Expected timeout or error when exceeding max connections"
);
drop(sessions);
let session = pool.get_session("admin").await;
assert!(session.is_ok(), "Should be able to get session after releasing");
}
#[tokio::test]
#[cfg(feature = "sqlite")]
async fn test_pool_connection_reuse() {
let config = dbnexus::DbConfig {
url: "sqlite::memory:".to_string(),
max_connections: 2,
min_connections: 1,
..Default::default()
};
let pool = dbnexus::DbPool::with_config(config)
.await
.expect("Failed to create pool");
for _ in 0..5 {
let session = pool.get_session("admin").await.expect("Failed to get session");
drop(session);
}
let status = pool.status();
assert!(status.total <= 2);
}
#[tokio::test]
#[cfg(feature = "sqlite")]
async fn test_pool_concurrent_connection_acquire() {
let config = dbnexus::DbConfig {
url: "sqlite::memory:".to_string(),
max_connections: 5,
min_connections: 1,
acquire_timeout: 2000,
..Default::default()
};
let pool = Arc::new(
dbnexus::DbPool::with_config(config)
.await
.expect("Failed to create pool"),
);
let mut handles = Vec::new();
for _ in 0..10 {
let pool_clone = pool.clone();
let handle = tokio::spawn(async move { pool_clone.get_session("admin").await.ok() });
handles.push(handle);
}
let results: Vec<_> = futures::future::join_all(handles).await;
let success_count = results.iter().filter(|r| r.as_ref().unwrap_or(&None).is_some()).count();
assert!(success_count <= 5, "Should not exceed max connections");
drop(results);
tokio::time::sleep(Duration::from_millis(100)).await;
let status = pool.status();
assert_eq!(status.active, 0, "All sessions should be released");
}
#[tokio::test]
#[cfg(feature = "sqlite")]
async fn test_pool_acquire_timeout() {
let config = dbnexus::DbConfig {
url: "sqlite::memory:".to_string(),
max_connections: 1,
min_connections: 1,
acquire_timeout: 500, ..Default::default()
};
let pool = Arc::new(
dbnexus::DbPool::with_config(config)
.await
.expect("Failed to create pool"),
);
let _session = pool.get_session("admin").await.expect("Failed to get session");
let pool_clone = pool.clone();
let start = std::time::Instant::now();
let result = pool_clone.get_session("admin").await;
let elapsed = start.elapsed();
assert!(result.is_err(), "Expected timeout error");
assert!(
elapsed >= Duration::from_millis(400),
"Should wait at least close to timeout"
);
assert!(elapsed < Duration::from_secs(2), "Should not wait too long");
}
#[tokio::test]
#[cfg(feature = "sqlite")]
async fn test_pool_timeout_then_release() {
let config = dbnexus::DbConfig {
url: "sqlite::memory:".to_string(),
max_connections: 1,
min_connections: 1,
acquire_timeout: 500,
..Default::default()
};
let pool = Arc::new(
dbnexus::DbPool::with_config(config)
.await
.expect("Failed to create pool"),
);
let session = pool.get_session("admin").await.expect("Failed to get session");
let pool_clone = pool.clone();
let timeout_task = tokio::spawn(async move { pool_clone.get_session("admin").await });
tokio::time::sleep(Duration::from_millis(100)).await;
drop(session);
let _ = timeout_task.await;
}
#[test]
fn test_pool_timeout_duration_conversion() {
let config = dbnexus::DbConfig {
url: "sqlite::memory:".to_string(),
acquire_timeout: 3000,
..Default::default()
};
assert_eq!(config.acquire_timeout_duration(), Duration::from_millis(3000));
}
#[tokio::test]
#[cfg(feature = "sqlite")]
async fn test_pool_session_auto_release() {
let pool = common::make_sqlite_memory_pool().await;
let initial_status = pool.status();
{
let _session = pool.get_session("admin").await.expect("Failed to get session");
}
tokio::time::sleep(Duration::from_millis(50)).await;
let final_status = pool.status();
assert_eq!(final_status.active, 0, "Session should be auto-released");
assert!(
final_status.idle >= initial_status.idle,
"Connection should be returned to idle pool"
);
}
#[tokio::test]
#[cfg(feature = "sqlite")]
async fn test_pool_borrow_count_tracking() {
let pool = common::make_sqlite_memory_pool().await;
let initial_status = pool.status();
let initial_borrow_count = initial_status.borrow_count;
for _ in 0..3 {
let _session = pool.get_session("admin").await.expect("Failed to get session");
}
tokio::time::sleep(Duration::from_millis(100)).await;
let final_status = pool.status();
assert!(
final_status.borrow_count >= initial_borrow_count + 3,
"borrow_count should track all borrows"
);
}
#[tokio::test]
#[cfg(feature = "sqlite")]
async fn test_pool_max_active_tracking() {
let config = dbnexus::DbConfig {
url: "sqlite::memory:".to_string(),
max_connections: 5,
..Default::default()
};
let pool = dbnexus::DbPool::with_config(config)
.await
.expect("Failed to create pool");
let mut sessions = Vec::new();
for _ in 0..3 {
let session = pool.get_session("admin").await.expect("Failed to get session");
sessions.push(session);
}
let status_with_sessions = pool.status();
assert!(status_with_sessions.max_active >= 3);
drop(sessions);
tokio::time::sleep(Duration::from_millis(50)).await;
let final_status = pool.status();
assert!(final_status.max_active >= 3);
assert_eq!(final_status.active, 0);
}
#[tokio::test]
#[cfg(feature = "sqlite")]
async fn test_pool_status_consistency() {
let pool = common::make_sqlite_memory_pool().await;
for _ in 0..10 {
let status = pool.status();
assert_eq!(
status.total,
status.active + status.idle,
"Status invariant should hold"
);
let session = pool.get_session("admin").await.expect("Failed to get session");
let status = pool.status();
assert_eq!(
status.total,
status.active + status.idle,
"Status invariant should hold after acquire"
);
drop(session);
}
tokio::time::sleep(Duration::from_millis(100)).await;
let final_status = pool.status();
assert_eq!(final_status.total, final_status.active + final_status.idle);
assert_eq!(final_status.active, 0);
}
#[tokio::test]
#[cfg(feature = "sqlite")]
async fn test_connection_lifecycle_via_status() {
let pool = common::make_sqlite_memory_pool().await;
{
let _session = pool.get_session("admin").await.expect("Failed to get session");
let status = pool.status();
assert!(status.borrow_count >= 1, "borrow_count should be at least 1");
}
tokio::time::sleep(std::time::Duration::from_millis(50)).await;
let final_status = pool.status();
assert_eq!(final_status.active, 0, "active should be 0 after release");
}
#[tokio::test]
#[cfg(feature = "sqlite")]
async fn test_connection_lifecycle_borrow_tracking() {
let pool = common::make_sqlite_memory_pool().await;
let initial_borrow_count = pool.status().borrow_count;
for _ in 0..5 {
let _session = pool.get_session("admin").await.expect("Failed to get session");
}
tokio::time::sleep(std::time::Duration::from_millis(100)).await;
let final_status = pool.status();
assert!(
final_status.borrow_count >= initial_borrow_count + 5,
"borrow_count should have increased by at least 5"
);
}
#[tokio::test]
#[cfg(feature = "sqlite")]
async fn test_connection_lifecycle_max_active_tracking() {
let config = dbnexus::DbConfig {
url: "sqlite::memory:".to_string(),
max_connections: 5,
..Default::default()
};
let pool = dbnexus::DbPool::with_config(config)
.await
.expect("Failed to create pool");
let mut sessions = Vec::new();
for _ in 0..3 {
let session = pool.get_session("admin").await.expect("Failed to get session");
sessions.push(session);
}
let status_during = pool.status();
assert!(status_during.max_active >= 3, "max_active should be at least 3");
drop(sessions);
tokio::time::sleep(std::time::Duration::from_millis(50)).await;
let final_status = pool.status();
assert!(final_status.max_active >= 3, "max_active should retain historical peak");
assert_eq!(final_status.active, 0, "active should be 0 after release");
}
#[tokio::test]
#[cfg(feature = "sqlite")]
async fn test_connection_lifecycle_wait_tracking() {
let config = dbnexus::DbConfig {
url: "sqlite::memory:".to_string(),
max_connections: 1,
min_connections: 1,
acquire_timeout: 500,
..Default::default()
};
let pool = std::sync::Arc::new(
dbnexus::DbPool::with_config(config)
.await
.expect("Failed to create pool"),
);
let _session = pool.get_session("admin").await.expect("Failed to get session");
let initial_wait_count = pool.status().wait_count;
let pool_clone = pool.clone();
let _result = pool_clone.get_session("admin").await;
let final_status = pool.status();
assert!(final_status.wait_count >= initial_wait_count);
}
#[test]
fn test_pool_config_default_values_reasonable() {
let config = dbnexus::DbConfig {
url: "sqlite::memory:".to_string(),
..Default::default()
};
assert!(config.max_connections > 0, "max_connections should be > 0");
assert!(config.max_connections <= 1000, "max_connections should be <= 1000");
assert!(config.min_connections > 0, "min_connections should be > 0");
assert!(config.min_connections <= config.max_connections, "min <= max");
assert!(config.idle_timeout >= 30, "idle_timeout should be >= 30");
assert!(config.acquire_timeout >= 1000, "acquire_timeout should be >= 1000");
}
#[tokio::test]
#[cfg(feature = "sqlite")]
async fn test_pool_single_connection() {
let config = dbnexus::DbConfig {
url: "sqlite::memory:".to_string(),
max_connections: 1,
min_connections: 1,
..Default::default()
};
let pool = dbnexus::DbPool::with_config(config)
.await
.expect("Failed to create pool");
{
let _session = pool.get_session("admin").await.expect("Failed to get session");
let status = pool.status();
assert_eq!(status.active, 1);
}
tokio::time::sleep(Duration::from_millis(50)).await;
let status = pool.status();
assert_eq!(status.active, 0);
assert!(status.total <= 1);
}
#[tokio::test]
#[cfg(feature = "sqlite")]
async fn test_pool_large_connection_pool() {
let config = dbnexus::DbConfig {
url: "sqlite::memory:".to_string(),
max_connections: 100,
min_connections: 10,
..Default::default()
};
let pool = dbnexus::DbPool::with_config(config)
.await
.expect("Failed to create pool");
assert_eq!(pool.config().max_connections, 100);
assert_eq!(pool.config().min_connections, 10);
}
#[tokio::test]
#[cfg(feature = "sqlite")]
async fn test_pool_rapid_acquire_release() {
let pool = common::make_sqlite_memory_pool().await;
for _ in 0..100 {
let session = pool.get_session("admin").await.expect("Failed to get session");
drop(session);
}
tokio::time::sleep(Duration::from_millis(100)).await;
let status = pool.status();
assert_eq!(status.active, 0);
assert_eq!(status.total, status.active + status.idle);
}
#[tokio::test]
#[cfg(feature = "sqlite")]
async fn test_session_role() {
let pool = common::make_sqlite_memory_pool().await;
let session = pool.get_session("admin").await.expect("Failed to get session");
assert_eq!(session.role(), "admin");
}
#[tokio::test]
#[cfg(feature = "sqlite")]
async fn test_session_transaction_state() {
let pool = common::make_sqlite_memory_pool().await;
let session = pool.get_session("admin").await.expect("Failed to get session");
assert!(!session.is_in_transaction().await);
session.begin_transaction().await.expect("Failed to begin transaction");
assert!(session.is_in_transaction().await);
session.commit().await.expect("Failed to commit transaction");
assert!(!session.is_in_transaction().await);
}
#[tokio::test]
#[cfg(feature = "sqlite")]
async fn test_session_transaction_rollback() {
let pool = common::make_sqlite_memory_pool().await;
let session = pool.get_session("admin").await.expect("Failed to get session");
session.begin_transaction().await.expect("Failed to begin transaction");
assert!(session.is_in_transaction().await);
session.rollback().await.expect("Failed to rollback transaction");
assert!(!session.is_in_transaction().await);
}
#[tokio::test]
#[cfg(feature = "sqlite")]
async fn test_session_double_begin_transaction() {
let pool = common::make_sqlite_memory_pool().await;
let session = pool.get_session("admin").await.expect("Failed to get session");
session.begin_transaction().await.expect("Failed to begin transaction");
let result = session.begin_transaction().await;
assert!(
result.is_err(),
"Should fail when beginning transaction while already in one"
);
}
#[tokio::test]
#[cfg(feature = "sqlite")]
async fn test_session_commit_without_transaction() {
let pool = common::make_sqlite_memory_pool().await;
let session = pool.get_session("admin").await.expect("Failed to get session");
let result = session.commit().await;
assert!(
result.is_err(),
"Should fail when committing without active transaction"
);
}
#[test]
fn test_url_sanitization_with_password() {
let config = dbnexus::DbConfig {
url: "postgres://user:secret_password@localhost:5432/mydb".to_string(),
..Default::default()
};
assert!(config.url.contains("postgres://"));
assert!(config.url.contains("secret_password"));
}
#[test]
fn test_url_sanitization_sqlite_memory() {
let config = dbnexus::DbConfig {
url: "sqlite::memory:".to_string(),
..Default::default()
};
assert_eq!(config.url, "sqlite::memory:");
}
#[test]
fn test_url_sanitization_no_password() {
let config = dbnexus::DbConfig {
url: "postgres://user@localhost:5432/mydb".to_string(),
..Default::default()
};
assert!(config.url.contains("postgres://"));
}
#[test]
fn test_database_type_parsing() {
use dbnexus::foundation::DatabaseType;
assert_eq!(
DatabaseType::parse_database_type("postgres://localhost/db").unwrap(),
DatabaseType::Postgres
);
assert_eq!(
DatabaseType::parse_database_type("postgresql://localhost/db").unwrap(),
DatabaseType::Postgres
);
assert_eq!(
DatabaseType::parse_database_type("mysql://localhost/db").unwrap(),
DatabaseType::MySql
);
assert_eq!(
DatabaseType::parse_database_type("sqlite::memory:").unwrap(),
DatabaseType::Sqlite
);
assert_eq!(
DatabaseType::parse_database_type("sqlite3://file.db").unwrap(),
DatabaseType::Sqlite
);
}
#[test]
fn test_database_type_display() {
use dbnexus::foundation::DatabaseType;
assert_eq!(DatabaseType::Postgres.to_string(), "postgres");
assert_eq!(DatabaseType::MySql.to_string(), "mysql");
assert_eq!(DatabaseType::Sqlite.to_string(), "sqlite");
}
#[test]
fn test_pool_config_creation() {
use dbnexus::PoolConfig;
let config = PoolConfig {
max_connections: 100,
min_connections: 10,
idle_timeout: 300,
acquire_timeout: 5000,
};
assert_eq!(config.max_connections, 100);
assert_eq!(config.min_connections, 10);
assert_eq!(config.idle_timeout, 300);
assert_eq!(config.acquire_timeout, 5000);
}
#[test]
fn test_pool_config_defaults() {
use dbnexus::PoolConfig;
let config = PoolConfig::default();
assert_eq!(config.max_connections, 20);
assert_eq!(config.min_connections, 5);
assert_eq!(config.idle_timeout, 300);
assert_eq!(config.acquire_timeout, 5000);
}
#[test]
#[cfg(feature = "pool-health-check")]
fn test_health_check_interval_default() {
let interval = dbnexus::DbPool::parse_health_check_interval("");
assert_eq!(interval, 30, "默认健康检查间隔应为 30 秒");
}
#[test]
#[cfg(feature = "pool-health-check")]
fn test_health_check_interval_lower_bound_zero() {
let interval = dbnexus::DbPool::parse_health_check_interval("0");
assert_eq!(interval, 5, "健康检查间隔 0 应被限制为最小值 5 秒");
}
#[test]
#[cfg(feature = "pool-health-check")]
fn test_health_check_interval_lower_bound_five() {
let interval = dbnexus::DbPool::parse_health_check_interval("5");
assert_eq!(interval, 5, "健康检查间隔 5 应保持不变");
}
#[test]
#[cfg(feature = "pool-health-check")]
fn test_health_check_interval_upper_bound_300() {
let interval = dbnexus::DbPool::parse_health_check_interval("300");
assert_eq!(interval, 300, "健康检查间隔 300 应保持不变");
}
#[test]
#[cfg(feature = "pool-health-check")]
fn test_health_check_interval_upper_bound_exceeded() {
let interval = dbnexus::DbPool::parse_health_check_interval("1000");
assert_eq!(interval, 300, "健康检查间隔 1000 应被限制为最大值 300 秒");
}
#[test]
#[cfg(feature = "pool-health-check")]
fn test_health_check_interval_valid_middle_value() {
let interval = dbnexus::DbPool::parse_health_check_interval("60");
assert_eq!(interval, 60, "健康检查间隔 60 应保持不变");
}
#[test]
#[cfg(feature = "pool-health-check")]
fn test_health_check_interval_invalid_string() {
let interval = dbnexus::DbPool::parse_health_check_interval("invalid");
assert_eq!(interval, 30, "无效字符串应使用默认值 30 秒");
}
#[test]
#[cfg(feature = "pool-health-check")]
fn test_health_check_interval_below_minimum() {
let interval = dbnexus::DbPool::parse_health_check_interval("1");
assert_eq!(interval, 5, "健康检查间隔 1 应被限制为最小值 5 秒");
}
#[test]
#[cfg(feature = "pool-health-check")]
fn test_health_check_interval_above_maximum() {
let interval = dbnexus::DbPool::parse_health_check_interval("301");
assert_eq!(interval, 300, "健康检查间隔 301 应被限制为最大值 300 秒");
}
#[tokio::test]
#[cfg(feature = "sqlite")]
async fn test_wait_count_increments_during_contention() {
let config = dbnexus::DbConfig {
url: "sqlite::memory:".to_string(),
max_connections: 2,
min_connections: 1,
acquire_timeout: 5000,
admin_role: "admin".to_string(),
..Default::default()
};
let pool = dbnexus::DbPool::with_config(config)
.await
.expect("Failed to create pool");
let pool = Arc::new(pool);
let initial_status = pool.status();
assert_eq!(initial_status.wait_count, 0, "Initial wait_count should be 0");
assert_eq!(initial_status.max_waiters, 0, "Initial max_waiters should be 0");
let handles: Vec<_> = (0..4)
.map(|_| {
let pool = pool.clone();
tokio::spawn(async move {
let session = pool.get_session("admin").await;
if session.is_ok() {
tokio::time::sleep(Duration::from_millis(30)).await;
}
session
})
})
.collect();
let results: Vec<_> = futures::future::join_all(handles).await;
let success_count = results.iter().filter(|r| r.as_ref().is_ok_and(|r| r.is_ok())).count();
assert!(
success_count >= 2,
"Expected at least 2 successful acquires, got {}",
success_count
);
tokio::time::sleep(Duration::from_millis(50)).await;
let final_status = pool.status();
assert_eq!(
final_status.wait_count, 0,
"Final wait_count should be 0 after all requests complete"
);
assert!(
final_status.max_waiters >= 1,
"max_waiters should be >= 1, got {}",
final_status.max_waiters
);
}
#[tokio::test]
#[cfg(feature = "sqlite")]
async fn test_max_waiters_tracks_historical_peak() {
let config = dbnexus::DbConfig {
url: "sqlite::memory:".to_string(),
max_connections: 1,
min_connections: 1,
acquire_timeout: 5000,
admin_role: "admin".to_string(),
..Default::default()
};
let pool = dbnexus::DbPool::with_config(config)
.await
.expect("Failed to create pool");
let pool = Arc::new(pool);
let handles: Vec<_> = (0..3)
.map(|_| {
let pool = pool.clone();
tokio::spawn(async move { pool.get_session("admin").await })
})
.collect();
futures::future::join_all(handles).await;
tokio::time::sleep(Duration::from_millis(50)).await;
let status_after_round1 = pool.status();
let peak1 = status_after_round1.max_waiters;
assert!(peak1 >= 1, "After 3 requests, max_waiters should be >= 1");
let handles: Vec<_> = (0..5)
.map(|_| {
let pool = pool.clone();
tokio::spawn(async move { pool.get_session("admin").await })
})
.collect();
futures::future::join_all(handles).await;
tokio::time::sleep(Duration::from_millis(50)).await;
let status_after_round2 = pool.status();
assert!(
status_after_round2.max_waiters >= peak1,
"max_waiters should be >= previous peak {}",
peak1
);
}