mod example_app;
use self::example_app::{ExampleApp, ExampleConfig};
use abscissa_core::{Component, FrameworkError, FrameworkErrorKind::ComponentError, component};
const FOOBAR_COMPONENT_ID: component::Id = component::Id::new("component::FoobarComponent");
const BAZ_COMPONENT_ID: component::Id = component::Id::new("component::BazComponent");
const QUUX_COMPONENT_ID: component::Id = component::Id::new("component::QuuxComponent");
#[derive(Component, Debug, Default)]
pub struct FoobarComponent {
pub state: Option<String>,
}
impl FoobarComponent {
pub fn set_state(&mut self, state_str: &str) {
self.state = Some(state_str.to_owned());
}
}
#[derive(Component, Debug, Default)]
pub struct BazComponent {}
#[derive(Component, Debug, Default)]
#[component(inject = "init_foobar(component::FoobarComponent)")]
#[component(inject = "init_baz(component::BazComponent)")]
pub struct QuuxComponent {
pub foobar_state: Option<String>,
pub baz_initialized: bool,
}
impl QuuxComponent {
pub fn init_foobar(&mut self, foobar: &mut FoobarComponent) -> Result<(), FrameworkError> {
self.foobar_state = foobar.state.clone();
foobar.state = Some("hijacked!".to_owned());
Ok(())
}
pub fn init_baz(&mut self, _baz: &BazComponent) -> Result<(), FrameworkError> {
self.baz_initialized = true;
Ok(())
}
}
fn init_components() -> Vec<Box<dyn Component<ExampleApp>>> {
let mut foobar = FoobarComponent::default();
foobar.set_state("original foobar state");
let component1 = Box::new(foobar);
let component2 = Box::<BazComponent>::default();
let component3 = Box::<QuuxComponent>::default();
let components: Vec<Box<dyn Component<ExampleApp>>> = vec![component1, component2, component3];
assert_eq!(components[0].id(), FOOBAR_COMPONENT_ID);
assert_eq!(components[1].id(), BAZ_COMPONENT_ID);
assert_eq!(components[2].id(), QUUX_COMPONENT_ID);
components
}
#[test]
fn component_registration() {
let mut registry = component::Registry::default();
assert!(registry.is_empty());
let components = init_components();
registry.register(components).unwrap();
assert_eq!(registry.len(), 3);
let foobar_comp = registry.get_by_id(FOOBAR_COMPONENT_ID).unwrap();
assert_eq!(foobar_comp.id(), FOOBAR_COMPONENT_ID);
let baz_comp = registry.get_by_id(BAZ_COMPONENT_ID).unwrap();
assert_eq!(baz_comp.id(), BAZ_COMPONENT_ID);
let quux_comp = registry.get_by_id(QUUX_COMPONENT_ID).unwrap();
assert_eq!(quux_comp.id(), QUUX_COMPONENT_ID);
}
#[test]
fn duplicate_component_registration() {
let foobar1 = Box::<FoobarComponent>::default();
let foobar2 = Box::<FoobarComponent>::default();
let components: Vec<Box<dyn Component<ExampleApp>>> = vec![foobar1, foobar2];
let mut registry = component::Registry::default();
assert!(registry.is_empty());
let err = registry.register(components).err().unwrap();
assert_eq!(*err.kind(), ComponentError);
assert_eq!(registry.len(), 1);
let foobar = registry.get_by_id(FOOBAR_COMPONENT_ID).unwrap();
assert_eq!(foobar.id(), FOOBAR_COMPONENT_ID);
}
#[test]
fn get_downcast_ref() {
let mut registry = component::Registry::default();
let component = Box::<FoobarComponent>::default() as Box<dyn Component<ExampleApp>>;
registry.register(vec![component]).unwrap();
{
let foo_mut = registry.get_downcast_mut::<FoobarComponent>().unwrap();
foo_mut.set_state("mutated!");
}
{
let foo_comp = registry.get_downcast_ref::<FoobarComponent>().unwrap();
assert_eq!(foo_comp.state.as_ref().unwrap(), "mutated!");
}
}
#[test]
fn dependency_injection() {
let mut registry = component::Registry::default();
let mut components = init_components();
components.reverse();
registry.register(components).unwrap();
registry.after_config(&ExampleConfig::default()).unwrap();
let foobar_comp = registry.get_downcast_ref::<FoobarComponent>().unwrap();
assert_eq!(foobar_comp.state.as_ref().unwrap(), "hijacked!");
let quux_comp = registry.get_downcast_ref::<QuuxComponent>().unwrap();
assert_eq!(
quux_comp.foobar_state.as_ref().unwrap(),
"original foobar state"
);
}