use crate::sub::Greeter;
use rioc::{injectable, module, provider};
use std::rc::Rc;
#[provider]
struct InitProvider;
#[test]
fn provide_with_simple_module_should_export_its_members_correctly() {
#[injectable]
#[provider]
struct Provider(#[import] sub::SimpleModule);
let provider = InitProvider.provide::<Provider>();
let facade = provider.provide::<sub::SimpleFacade>();
assert_eq!(facade, sub::expected_simple_facade(&provider.0))
}
#[test]
fn provide_with_ref_to_module_should_export_its_members_correctly() {
#[injectable]
#[provider]
struct Provider<'a>(#[import] &'a sub::SimpleModule);
let module = InitProvider.provide::<sub::SimpleModule>();
let provider = Provider(&module);
let facade = provider.provide::<sub::SimpleFacade>();
assert_eq!(facade, sub::expected_simple_facade(&provider.0))
}
#[test]
fn provide_with_generic_module_should_export_its_members_correctly() {
#[provider]
#[provide(&'prov i32, &self.0)]
struct InitProvider(i32);
#[injectable]
#[provider]
struct Provider<'a, T>(#[import] sub::GenericModule<'a, T>);
let init_prov = InitProvider(123);
let provider = init_prov.provide::<Provider<i32>>();
let facade = provider.provide::<sub::GenericFacade<_>>();
assert_eq!(facade, sub::expected_generic_facade(&provider.0))
}
#[test]
fn provide_with_module_with_ref_dep_should_export_its_members_correctly() {
#[injectable]
#[provider]
struct Provider<'a>(#[import] sub::ModuleWithRef<'a>);
let provider = InitProvider.provide::<Provider>();
let facade = provider.provide::<sub::SimpleRefFacade>();
assert_eq!(facade, sub::expected_simple_ref_facade(&provider.0))
}
#[test]
fn provide_with_module_with_dyn_dep_should_export_its_members_correctly() {
#[injectable]
#[provider]
struct Provider(#[import] sub::DynDepModule);
let provider = InitProvider.provide::<Provider>();
let dep = provider.provide::<&dyn sub::Greeter>();
assert_eq!(dep.greet(), sub::GreeterOne.greet())
}
#[test]
fn provide_with_module_with_external_type_export_should_provide_its_members_correctly() {
#[injectable]
#[module(Self)]
#[export(i32, 123)]
struct TestModuleWithLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongName;
#[injectable]
#[provider]
struct Provider(#[import] TestModuleWithLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongName);
let provider = InitProvider.provide::<Provider>();
let dep = provider.provide::<i32>();
assert_eq!(dep, 123)
}
#[injectable]
#[module(crate::TestModule1)]
#[export(std::rc::Rc<i32>, self.0.clone())]
struct TestModule1(#[inject(Rc::new(123))] Rc<i32>);
#[test]
fn provide_with_module_with_external_type_export_with_simple_factory_should_provide_its_members_correctly(
) {
#[injectable]
#[provider]
struct Provider(#[import] crate::TestModule1);
let provider = InitProvider.provide::<Provider>();
let dep = provider.provide::<Rc<i32>>();
assert_eq!(*dep, 123)
}
#[test]
fn provide_with_module_with_external_type_export_with_complex_factory_should_provide_its_members_correctly(
) {
#[injectable]
#[module]
#[export(Box<i32>, |x: i32| Box::new(x))]
struct TestModule2;
#[injectable]
#[provider]
#[provide(i32, 123)]
struct Provider(#[import] TestModule2);
let provider = InitProvider.provide::<Provider>();
let dep = provider.provide::<Box<i32>>();
assert_eq!(*dep, 123)
}
#[test]
fn provide_with_module_with_ref_external_type_export_should_provide_its_members_correctly() {
#[injectable]
#[module]
#[export(&'prov i32, &self.0)]
struct TestModule3(#[inject(123)] i32);
#[injectable]
#[provider]
struct Provider(#[import] TestModule3);
let provider = InitProvider.provide::<Provider>();
let dep = provider.provide::<&i32>();
assert_eq!(dep, &123)
}
#[test]
fn provide_with_module_with_factory_internal_export_should_provide_its_members_correctly() {
#[derive(Debug, PartialEq)]
struct Ref<T: PartialEq>(Rc<T>);
#[injectable]
#[module]
struct Module(
#[inject(Rc::new(123))]
#[export(Ref<i32>, |x| Ref(x.clone()))]
Rc<i32>,
#[inject(Ref(Rc::new(456)))]
#[export(&'prov Ref<i32>, |x| &x)]
Ref<i32>,
);
#[injectable]
#[provider]
struct Provider(#[import] Module);
let provider = InitProvider.provide::<Provider>();
let dep = provider.provide::<Ref<i32>>();
let dep_ref = provider.provide::<&Ref<i32>>();
assert_eq!(dep, Ref(Rc::new(123)));
assert!(Rc::ptr_eq(&dep.0, &provider.0 .0));
assert_eq!(*dep_ref.0, *provider.0 .1 .0);
}
mod sub {
use rioc::{injectable, module};
use rioc::inject;
pub trait Greeter {
fn greet(&self) -> &str;
}
#[injectable]
pub struct GreeterOne;
impl Greeter for GreeterOne {
fn greet(&self) -> &str {
"One"
}
}
static REF_DEP: &SimpleRefDep = &SimpleRefDep(123);
#[derive(PartialEq, Debug)]
#[injectable]
struct SimpleDep(#[inject(123)] i32);
#[derive(PartialEq, Debug)]
#[injectable]
struct SimpleRefDep(#[inject(123)] i32);
#[derive(PartialEq, Debug)]
#[injectable]
pub struct SimpleFacade<'a>(&'a SimpleDep);
#[derive(PartialEq, Debug)]
#[injectable]
pub struct SimpleRefFacade<'a>(&'a SimpleRefDep);
#[injectable]
#[module]
pub struct SimpleModule {
#[export]
hidden: SimpleDep,
}
#[injectable]
#[module]
pub struct DynDepModule {
#[export(dyn Greeter)]
dyn_dep: GreeterOne,
}
#[derive(PartialEq, Debug)]
#[injectable]
struct GenericDep<'a, T>(&'a T);
#[derive(PartialEq, Debug)]
#[injectable]
pub struct GenericFacade<'a, T>(&'a GenericDep<'a, T>);
#[injectable]
#[module]
pub struct GenericModule<'a, T> {
#[export]
hidden: GenericDep<'a, T>,
}
#[injectable]
#[module]
pub struct ModuleWithRef<'a> {
#[export]
#[inject(REF_DEP)]
hidden: &'a SimpleRefDep,
}
pub fn expected_simple_facade<'a>(module: &'a SimpleModule) -> SimpleFacade<'a> {
SimpleFacade(&module.hidden)
}
pub fn expected_simple_ref_facade<'a>(module: &'a ModuleWithRef) -> SimpleRefFacade<'a> {
SimpleRefFacade(&module.hidden)
}
pub fn expected_generic_facade<'a, T>(
module: &'a GenericModule<'a, T>,
) -> GenericFacade<'a, T> {
GenericFacade(&module.hidden)
}
}