use std::collections::HashMap;
#[derive(Debug, Clone)]
pub struct Database {
connection_string: String,
pool_size: usize,
timeout: u64,
cache: HashMap<String, String>,
}
impl Database {
pub fn new(connection_string: String, pool_size: usize, timeout: u64) -> Self {
Database {
connection_string,
pool_size,
timeout,
cache: HashMap::new(),
}
}
pub fn connection_string(&self) -> &str {
&self.connection_string
}
pub fn pool_size(&self) -> usize {
self.pool_size
}
pub fn timeout(&self) -> u64 {
self.timeout
}
pub fn cache(&self) -> &HashMap<String, String> {
&self.cache
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_new_creates_database_with_correct_connection_string() {
let db = Database::new("postgres://localhost/test".to_string(), 10, 30);
assert_eq!(db.connection_string, "postgres://localhost/test");
}
#[test]
fn test_new_creates_database_with_correct_pool_size() {
let db = Database::new("postgres://localhost/test".to_string(), 10, 30);
assert_eq!(db.pool_size, 10);
}
#[test]
fn test_new_creates_database_with_correct_timeout() {
let db = Database::new("postgres://localhost/test".to_string(), 10, 30);
assert_eq!(db.timeout, 30);
}
#[test]
fn test_new_initializes_empty_cache() {
let db = Database::new("postgres://localhost/test".to_string(), 10, 30);
assert!(db.cache.is_empty());
}
#[test]
fn test_new_with_empty_connection_string() {
let db = Database::new(String::new(), 10, 30);
assert_eq!(db.connection_string, "");
assert_eq!(db.pool_size, 10);
assert_eq!(db.timeout, 30);
}
#[test]
fn test_new_with_zero_pool_size() {
let db = Database::new("postgres://localhost/test".to_string(), 0, 30);
assert_eq!(db.pool_size, 0);
}
#[test]
fn test_new_with_zero_timeout() {
let db = Database::new("postgres://localhost/test".to_string(), 10, 0);
assert_eq!(db.timeout, 0);
}
#[test]
fn test_new_with_large_values() {
let db = Database::new(
"postgres://localhost/test".to_string(),
usize::MAX,
u64::MAX,
);
assert_eq!(db.pool_size, usize::MAX);
assert_eq!(db.timeout, u64::MAX);
}
#[test]
fn test_new_database_fields_are_accessible() {
let db = Database::new("postgres://localhost/test".to_string(), 10, 30);
let _ = &db.connection_string;
let _ = &db.pool_size;
let _ = &db.timeout;
let _ = &db.cache;
}
#[test]
fn test_new_creates_independent_instances() {
let db1 = Database::new("postgres://localhost/db1".to_string(), 10, 30);
let db2 = Database::new("postgres://localhost/db2".to_string(), 20, 60);
assert_ne!(db1.connection_string, db2.connection_string);
assert_ne!(db1.pool_size, db2.pool_size);
assert_ne!(db1.timeout, db2.timeout);
}
#[test]
fn test_new_with_special_characters_in_connection_string() {
let special_conn =
"postgres://user:p@$$w0rd!@localhost:5432/db?sslmode=require".to_string();
let db = Database::new(special_conn.clone(), 10, 30);
assert_eq!(db.connection_string(), special_conn);
assert!(db.cache().is_empty());
}
#[test]
fn test_new_with_unicode_in_connection_string() {
let unicode_conn = "postgres://用户:密码@localhost/数据库".to_string();
let db = Database::new(unicode_conn.clone(), 10, 30);
assert_eq!(db.connection_string(), unicode_conn);
}
#[test]
fn test_new_with_very_long_connection_string() {
let long_string = "postgres://".to_string() + &"x".repeat(1000) + "/database";
let db = Database::new(long_string.clone(), 10, 30);
assert_eq!(db.connection_string, long_string);
}
#[test]
fn test_connection_string_accessor() {
let db = Database::new("postgres://user:pass@host/db".to_string(), 10, 30);
assert_eq!(db.connection_string(), "postgres://user:pass@host/db");
}
#[test]
fn test_connection_string_accessor_returns_correct_value() {
let db = Database::new("postgres://user:pass@host:5432/db".to_string(), 10, 30);
assert_eq!(db.connection_string(), "postgres://user:pass@host:5432/db");
}
#[test]
fn test_connection_string_accessor_with_empty_string() {
let db = Database::new(String::new(), 10, 30);
assert_eq!(db.connection_string(), "");
}
#[test]
fn test_connection_string_accessor_with_special_characters() {
let special_conn = "postgres://user%40:p%40ss@host/db?param=value&other=123";
let db = Database::new(special_conn.to_string(), 10, 30);
assert_eq!(db.connection_string(), special_conn);
}
#[test]
fn test_pool_size_accessor() {
let db = Database::new("postgres://localhost/test".to_string(), 25, 30);
assert_eq!(db.pool_size(), 25);
}
#[test]
fn test_pool_size_accessor_returns_correct_value() {
let db = Database::new("postgres://localhost/test".to_string(), 25, 30);
assert_eq!(db.pool_size(), 25);
}
#[test]
fn test_pool_size_accessor_with_zero() {
let db = Database::new("postgres://localhost/test".to_string(), 0, 30);
assert_eq!(db.pool_size(), 0);
}
#[test]
fn test_pool_size_accessor_with_max_value() {
let db = Database::new("postgres://localhost/test".to_string(), usize::MAX, 30);
assert_eq!(db.pool_size(), usize::MAX);
}
#[test]
fn test_timeout_accessor() {
let db = Database::new("postgres://localhost/test".to_string(), 10, 45);
assert_eq!(db.timeout(), 45);
}
#[test]
fn test_timeout_accessor_returns_correct_value() {
let db = Database::new("postgres://localhost/test".to_string(), 10, 45);
assert_eq!(db.timeout(), 45);
}
#[test]
fn test_timeout_accessor_with_zero() {
let db = Database::new("postgres://localhost/test".to_string(), 10, 0);
assert_eq!(db.timeout(), 0);
}
#[test]
fn test_timeout_accessor_with_max_value() {
let db = Database::new("postgres://localhost/test".to_string(), 10, u64::MAX);
assert_eq!(db.timeout(), u64::MAX);
}
#[test]
fn test_cache_accessor() {
let db = Database::new("postgres://localhost/test".to_string(), 10, 30);
let cache = db.cache();
assert!(cache.is_empty());
assert_eq!(cache.len(), 0);
}
#[test]
fn test_cache_accessor_returns_empty_hashmap() {
let db = Database::new("postgres://localhost/test".to_string(), 10, 30);
assert!(db.cache().is_empty());
assert_eq!(db.cache().len(), 0);
}
#[test]
fn test_cache_accessor_returns_reference() {
let db = Database::new("postgres://localhost/test".to_string(), 10, 30);
let cache_ref = db.cache();
assert!(cache_ref.is_empty());
assert_eq!(cache_ref.len(), 0);
}
#[test]
fn test_new_with_typical_production_values() {
let db = Database::new("postgres://prod.example.com/myapp".to_string(), 50, 300);
assert_eq!(db.connection_string(), "postgres://prod.example.com/myapp");
assert_eq!(db.pool_size(), 50);
assert_eq!(db.timeout(), 300);
assert!(db.cache().is_empty());
}
#[test]
fn test_getter_methods_return_correct_values() {
let conn = "postgresql://localhost:5432/testdb".to_string();
let pool = 25;
let timeout = 120;
let db = Database::new(conn.clone(), pool, timeout);
assert_eq!(db.connection_string(), conn);
assert_eq!(db.pool_size(), pool);
assert_eq!(db.timeout(), timeout);
assert_eq!(db.cache().len(), 0);
}
#[test]
fn test_all_accessors_together() {
let db = Database::new("postgres://prod/maindb".to_string(), 50, 120);
assert_eq!(db.connection_string(), "postgres://prod/maindb");
assert_eq!(db.pool_size(), 50);
assert_eq!(db.timeout(), 120);
assert!(db.cache().is_empty());
}
#[test]
fn test_all_accessors_work_together() {
let conn_str = "postgres://localhost/integration";
let pool = 50;
let timeout = 120;
let db = Database::new(conn_str.to_string(), pool, timeout);
assert_eq!(db.connection_string(), conn_str);
assert_eq!(db.pool_size(), pool);
assert_eq!(db.timeout(), timeout);
assert!(db.cache().is_empty());
}
#[test]
fn test_database_implements_debug_trait() {
let db = Database::new("postgres://localhost/test".to_string(), 10, 30);
let debug_str = format!("{:?}", db);
assert!(debug_str.contains("Database"));
assert!(debug_str.contains("connection_string"));
assert!(debug_str.contains("pool_size"));
assert!(debug_str.contains("timeout"));
}
#[test]
fn test_database_implements_clone_trait() {
let original = Database::new("postgres://localhost/test".to_string(), 10, 30);
let cloned = original.clone();
assert_eq!(original.connection_string, cloned.connection_string);
assert_eq!(original.pool_size, cloned.pool_size);
assert_eq!(original.timeout, cloned.timeout);
}
#[test]
fn test_new_with_minimum_and_maximum_boundary_values() {
let min_db = Database::new("x".to_string(), 1, 1);
assert_eq!(min_db.pool_size, 1);
assert_eq!(min_db.timeout, 1);
let max_db = Database::new("x".to_string(), 10000, 86400);
assert_eq!(max_db.pool_size, 10000);
assert_eq!(max_db.timeout, 86400);
}
#[test]
fn test_database_is_cloneable() {
let db1 = Database::new("test".to_string(), 10, 30);
let db2 = db1.clone();
assert_eq!(db1.connection_string(), db2.connection_string());
assert_eq!(db1.pool_size(), db2.pool_size());
assert_eq!(db1.timeout(), db2.timeout());
}
#[test]
fn test_database_debug_format_with_values() {
let db = Database::new("postgres://localhost/test".to_string(), 10, 30);
let debug_str = format!("{:?}", db);
assert!(debug_str.contains("Database"));
assert!(debug_str.contains("postgres://localhost/test"));
assert!(debug_str.contains("10"));
assert!(debug_str.contains("30"));
}
#[test]
fn test_database_debug_trait() {
let db = Database::new("test".to_string(), 10, 30);
let debug_str = format!("{:?}", db);
assert!(debug_str.contains("Database"));
assert!(debug_str.contains("connection_string"));
assert!(debug_str.contains("pool_size"));
assert!(debug_str.contains("timeout"));
assert!(debug_str.contains("cache"));
}
#[test]
fn test_accessors_multiple_calls_return_same_values() {
let db = Database::new("postgres://localhost/test".to_string(), 10, 30);
assert_eq!(db.connection_string(), db.connection_string());
assert_eq!(db.pool_size(), db.pool_size());
assert_eq!(db.timeout(), db.timeout());
assert_eq!(db.cache().len(), db.cache().len());
}
#[test]
fn test_new_with_various_pool_sizes() {
let test_cases = vec![
(1, "single connection pool"),
(10, "small pool"),
(100, "medium pool"),
(1000, "large pool"),
];
for (size, description) in test_cases {
let db = Database::new(format!("test_{}", description), size, 30);
assert_eq!(db.pool_size(), size, "Failed for {}", description);
}
}
#[test]
fn test_new_with_various_timeouts() {
let test_cases = vec![
(1, "minimal timeout"),
(30, "standard timeout"),
(300, "long timeout"),
(3600, "very long timeout"),
];
for (timeout, description) in test_cases {
let db = Database::new("test".to_string(), 10, timeout);
assert_eq!(db.timeout(), timeout, "Failed for {}", description);
}
}
}