use amethystate::{StoreBuilder, amethystate};
use amethystate_core::test_utils::unique_path;
use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};
#[amethystate]
pub struct ServerConfig {
#[amestate(default = "localhost".to_string())]
pub host: String,
#[amestate(default = 8080)]
pub port: u16,
}
#[amethystate(prefix = "app")]
pub struct AppState {
#[amestate(default = "admin".to_string())]
pub username: String,
#[amestate(nested)]
pub server: ServerConfig,
#[amestate(default = {})]
pub tags: amethystate::ReactiveMap<String, String>,
}
#[test]
fn test_slice_subscribe_all() {
let path = unique_path("slice_sub_all");
let store = StoreBuilder::new(&path).build().unwrap();
let state = AppState::new_with(&store).unwrap();
let change_count = Arc::new(AtomicUsize::new(0));
let cc_clone = change_count.clone();
let mut scope = state.subscribe_all(move || {
cc_clone.fetch_add(1, Ordering::SeqCst);
});
assert_eq!(change_count.load(Ordering::SeqCst), 0);
state.username().set("superuser".to_string()).unwrap();
assert_eq!(change_count.load(Ordering::SeqCst), 1);
state.server().host().set("127.0.0.1".to_string()).unwrap();
assert_eq!(change_count.load(Ordering::SeqCst), 2);
state
.tags()
.set_or_create("env".into(), &"prod".into())
.unwrap();
assert_eq!(change_count.load(Ordering::SeqCst), 3);
scope.clear();
state.username().set("guest".to_string()).unwrap();
assert_eq!(
change_count.load(Ordering::SeqCst),
3,
"Changes must not be tracked after scope clearance"
);
}
#[test]
fn test_slice_subscribe_all_external() {
let path = unique_path("slice_sub_all_ext");
let store = StoreBuilder::new(&path).build().unwrap();
let state = AppState::new_with(&store).unwrap();
let fork = state.fork();
let change_count = Arc::new(AtomicUsize::new(0));
let cc_clone = change_count.clone();
let _scope = state.subscribe_all_external(move || {
cc_clone.fetch_add(1, Ordering::SeqCst);
});
assert_eq!(change_count.load(Ordering::SeqCst), 0);
state.username().set("superuser".to_string()).unwrap();
assert_eq!(
change_count.load(Ordering::SeqCst),
0,
"Own flat field changes must be ignored"
);
fork.username().set("fork_user".to_string()).unwrap();
assert_eq!(
change_count.load(Ordering::SeqCst),
1,
"Updates from fork must be processed"
);
state.server().port().set(9090).unwrap();
assert_eq!(
change_count.load(Ordering::SeqCst),
1,
"Own nested structure changes must be ignored"
);
fork.server().port().set(3000).unwrap();
assert_eq!(
change_count.load(Ordering::SeqCst),
2,
"Updates to nested structure from fork must be processed"
);
state
.tags()
.set_or_create("region".into(), &"eu".into())
.unwrap();
assert_eq!(
change_count.load(Ordering::SeqCst),
3,
"New field creation (Insert) must not be ignored"
);
state.tags().set("region".into(), &"us".into()).unwrap();
assert_eq!(
change_count.load(Ordering::SeqCst),
3,
"Own map updates (Update) must be ignored"
);
fork.tags().set("region".into(), &"asia".into()).unwrap();
assert_eq!(
change_count.load(Ordering::SeqCst),
4,
"Map updates from fork (Update) must be processed"
);
}