#![forbid(unsafe_code)]
use std::sync::Arc;
use rtb_app::app::App;
use rtb_app::metadata::ToolMetadata;
use rtb_app::typed_config::{erase, ErasedConfig, TypedConfigOps};
use rtb_app::version::VersionInfo;
use rtb_assets::Assets;
use rtb_config::Config;
use semver::Version;
mod sealed {
pub trait Sealed {}
}
pub struct TestWitness(());
impl TestWitness {
#[must_use]
pub const fn new() -> Self {
Self(())
}
}
impl Default for TestWitness {
fn default() -> Self {
Self::new()
}
}
impl sealed::Sealed for TestWitness {}
#[must_use]
pub struct TestAppBuilder<W: sealed::Sealed> {
_witness: W,
metadata: Option<ToolMetadata>,
version: Option<VersionInfo>,
typed_config: Option<ErasedConfig>,
typed_config_ops: Option<Arc<TypedConfigOps>>,
}
impl TestAppBuilder<TestWitness> {
pub const fn new(witness: TestWitness) -> Self {
Self {
_witness: witness,
metadata: None,
version: None,
typed_config: None,
typed_config_ops: None,
}
}
pub fn tool(mut self, name: &str, version: &str) -> Self {
self.metadata = Some(ToolMetadata::builder().name(name).summary("test").build());
self.version = Some(VersionInfo::new(Version::parse(version).expect("parse test version")));
self
}
pub fn metadata(mut self, m: ToolMetadata) -> Self {
self.metadata = Some(m);
self
}
pub fn version(mut self, v: VersionInfo) -> Self {
self.version = Some(v);
self
}
pub fn config<C>(mut self, config: Config<C>) -> Self
where
C: serde::Serialize
+ serde::de::DeserializeOwned
+ schemars::JsonSchema
+ Send
+ Sync
+ 'static,
{
let ops = TypedConfigOps::new::<C>();
self.typed_config = Some(erase(config));
self.typed_config_ops = Some(Arc::new(ops));
self
}
pub fn config_value<C>(self, c: C) -> Self
where
C: serde::Serialize
+ serde::de::DeserializeOwned
+ schemars::JsonSchema
+ Send
+ Sync
+ 'static,
{
self.config(Config::<C>::with_value(c))
}
#[must_use]
pub fn build(self) -> App {
let metadata = self.metadata.expect("TestAppBuilder: metadata not set");
let version = self.version.expect("TestAppBuilder: version not set");
let app = App::new(metadata, version, Config::<()>::default(), Assets::default(), None);
match (self.typed_config, self.typed_config_ops) {
(Some(erased), Some(ops)) => app.with_typed_config(erased, ops),
_ => app,
}
}
}