#![cfg(feature = "watch")]
use futures::StreamExt;
use rskit_config::{
ConfigChange, ConfigLoader, ConfigMapSource, ConfigSink, ConfigWatch, InMemoryConfigSink,
};
use serde::Deserialize;
use tokio_util::sync::CancellationToken;
#[derive(Debug, Deserialize)]
struct AppSettings {
port: u16,
}
fn redecode(sink: &InMemoryConfigSink) -> AppSettings {
let port = sink
.get("port")
.map(|v| v.expose().to_string())
.unwrap_or_default();
let source = ConfigMapSource::new().with_value("port", port);
ConfigLoader::custom()
.with_source(source)
.load::<AppSettings>()
.expect("decode current config")
}
#[tokio::test]
async fn change_event_triggers_redecode() {
let sink = InMemoryConfigSink::new();
sink.set("port", rskit_config::SecretString::new("8080"))
.unwrap();
let cancel = CancellationToken::new();
let mut changes = sink.watch(cancel.clone()).unwrap();
sink.set("port", rskit_config::SecretString::new("8081"))
.unwrap();
let event = changes.next().await.expect("a change event");
assert_eq!(
event,
ConfigChange::Set {
key: "port".to_string()
}
);
let settings = redecode(&sink);
assert_eq!(settings.port, 8081);
cancel.cancel();
}
#[tokio::test]
async fn remove_emits_removed_event() {
let sink = InMemoryConfigSink::new();
sink.set("k", rskit_config::SecretString::new("v")).unwrap();
let cancel = CancellationToken::new();
let mut changes = sink.watch(cancel.clone()).unwrap();
sink.remove("k").unwrap();
let event = changes.next().await.expect("a change event");
assert_eq!(
event,
ConfigChange::Removed {
key: "k".to_string()
}
);
cancel.cancel();
}
#[tokio::test]
async fn cancellation_terminates_stream() {
let sink = InMemoryConfigSink::new();
let cancel = CancellationToken::new();
let mut changes = sink.watch(cancel.clone()).unwrap();
cancel.cancel();
assert!(changes.next().await.is_none());
}
#[tokio::test]
async fn multiple_subscribers_each_receive_changes() {
let sink = InMemoryConfigSink::new();
let cancel = CancellationToken::new();
let mut first = sink.watch(cancel.clone()).unwrap();
let mut second = sink.watch(cancel.clone()).unwrap();
sink.set("k", rskit_config::SecretString::new("v")).unwrap();
let expected = ConfigChange::Set {
key: "k".to_string(),
};
assert_eq!(first.next().await.unwrap(), expected);
assert_eq!(second.next().await.unwrap(), expected);
cancel.cancel();
}