use fbc_starter::state::AppState;
use std::sync::Arc;
#[derive(Debug, Clone, PartialEq)]
struct MyConfig {
api_key: String,
max_retries: u32,
}
#[derive(Debug, Clone, PartialEq)]
struct SessionStore {
name: String,
}
#[test]
fn test_set_get_extension() {
let state = AppState::new();
let config = MyConfig {
api_key: "secret-123".to_string(),
max_retries: 3,
};
state.set_extension(config.clone());
let retrieved = state.get_extension::<MyConfig>();
assert!(retrieved.is_some());
assert_eq!(*retrieved.unwrap(), config);
}
#[test]
fn test_get_nonexistent_extension() {
let state = AppState::new();
let result = state.get_extension::<MyConfig>();
assert!(result.is_none());
}
#[test]
fn test_has_extension() {
let state = AppState::new();
assert!(!state.has_extension::<MyConfig>());
state.set_extension(MyConfig {
api_key: "key".to_string(),
max_retries: 1,
});
assert!(state.has_extension::<MyConfig>());
assert!(!state.has_extension::<SessionStore>());
}
#[test]
fn test_multiple_extensions() {
let state = AppState::new();
state.set_extension(MyConfig {
api_key: "key-1".to_string(),
max_retries: 5,
});
state.set_extension(SessionStore {
name: "redis-session".to_string(),
});
let config = state.get_extension::<MyConfig>().unwrap();
let session = state.get_extension::<SessionStore>().unwrap();
assert_eq!(config.api_key, "key-1");
assert_eq!(session.name, "redis-session");
}
#[test]
fn test_override_extension() {
let state = AppState::new();
state.set_extension(MyConfig {
api_key: "old-key".to_string(),
max_retries: 1,
});
state.set_extension(MyConfig {
api_key: "new-key".to_string(),
max_retries: 10,
});
let config = state.get_extension::<MyConfig>().unwrap();
assert_eq!(config.api_key, "new-key");
assert_eq!(config.max_retries, 10);
}
#[test]
fn test_with_extension_builder() {
let state = AppState::new()
.with_extension(MyConfig {
api_key: "builder-key".to_string(),
max_retries: 3,
})
.with_extension(SessionStore {
name: "mem-session".to_string(),
});
assert!(state.has_extension::<MyConfig>());
assert!(state.has_extension::<SessionStore>());
}
#[test]
fn test_clone_shares_extensions() {
let state = AppState::new();
state.set_extension(MyConfig {
api_key: "shared".to_string(),
max_retries: 1,
});
let cloned = state.clone();
let config = cloned.get_extension::<MyConfig>().unwrap();
assert_eq!(config.api_key, "shared");
cloned.set_extension(SessionStore {
name: "from-clone".to_string(),
});
assert!(state.has_extension::<SessionStore>());
}
#[test]
fn test_extension_thread_safety() {
let state = Arc::new(AppState::new());
let handles: Vec<_> = (0..10)
.map(|i| {
let s = state.clone();
std::thread::spawn(move || {
s.set_extension(MyConfig {
api_key: format!("thread-{}", i),
max_retries: i as u32,
});
let _ = s.get_extension::<MyConfig>();
})
})
.collect();
for h in handles {
h.join().unwrap();
}
assert!(state.has_extension::<MyConfig>());
}