From 800e164a83388aa5ca7675f8031b0f0d7c6b6051 Mon Sep 17 00:00:00 2001 From: HampusM Date: Wed, 16 Aug 2023 22:35:47 +0200 Subject: test: make the prevent-circular example an integration test --- Cargo.toml | 4 -- examples/prevent-circular/main.rs | 52 ---------------------- tests/prevent_circular.rs | 94 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 94 insertions(+), 56 deletions(-) delete mode 100644 examples/prevent-circular/main.rs create mode 100644 tests/prevent_circular.rs diff --git a/Cargo.toml b/Cargo.toml index 77b73c2..d33742b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -35,10 +35,6 @@ required-features = ["async", "factory"] name = "async-factory" required-features = ["async", "factory"] -[[example]] -name = "prevent-circular" -required-features = ["prevent-circular"] - [dependencies] syrette_macros = { path = "./macros", version = "0.4.2" } linkme = "0.3.0" diff --git a/examples/prevent-circular/main.rs b/examples/prevent-circular/main.rs deleted file mode 100644 index c690a9c..0000000 --- a/examples/prevent-circular/main.rs +++ /dev/null @@ -1,52 +0,0 @@ -//! Example demonstrating the prevention of circular dependencies. -//! -//! Having circular dependencies is generally bad practice and is detected by Syrette when -//! the `prevent-circular` feature is enabled. -#![deny(clippy::all)] -#![deny(clippy::pedantic)] -#![allow(clippy::disallowed_names)] - -use syrette::di_container::blocking::prelude::*; -use syrette::injectable; -use syrette::ptr::TransientPtr; - -struct Foo -{ - _bar: TransientPtr, -} - -#[injectable] -impl Foo -{ - fn new(bar: TransientPtr) -> Self - { - Self { _bar: bar } - } -} - -struct Bar -{ - _foo: TransientPtr, -} - -#[injectable] -impl Bar -{ - fn new(foo: TransientPtr) -> Self - { - Self { _foo: foo } - } -} - -fn main() -> Result<(), anyhow::Error> -{ - let mut di_container = DIContainer::new(); - - di_container.bind::().to::()?; - di_container.bind::().to::()?; - - // The following won't work. Err will be returned. - let _foo = di_container.get::()?.transient()?; - - Ok(()) -} diff --git a/tests/prevent_circular.rs b/tests/prevent_circular.rs new file mode 100644 index 0000000..4b95dea --- /dev/null +++ b/tests/prevent_circular.rs @@ -0,0 +1,94 @@ +#![deny(clippy::all, clippy::pedantic)] +#![allow(clippy::disallowed_names)] + +use syrette::di_container::blocking::prelude::*; +use syrette::errors::di_container::DIContainerError; +use syrette::errors::injectable::InjectableError; +use syrette::injectable; +use syrette::ptr::TransientPtr; + +#[derive(Debug)] +struct Foo +{ + _bar: TransientPtr, +} + +#[injectable] +impl Foo +{ + fn new(bar: TransientPtr) -> Self + { + Self { _bar: bar } + } +} + +#[derive(Debug)] +struct Bar +{ + _foo: TransientPtr, +} + +#[injectable] +impl Bar +{ + fn new(foo: TransientPtr) -> Self + { + Self { _foo: foo } + } +} + +macro_rules! assert_match { + ($target: expr, $pattern: pat => $expr: expr) => {{ + let target = $target; + + // Not all pattern variables will be used here + #[allow(unused_variables)] + { + assert!(matches!(&target, $pattern)); + } + + match target { + $pattern => $expr, + _ => { + unreachable!(); + } + } + }}; +} + +#[test] +fn prevent_circular_works() +{ + let mut di_container = DIContainer::new(); + + di_container.bind::().to::().expect("Expected Ok"); + di_container.bind::().to::().expect("Expected Ok"); + + let err = di_container.get::().expect_err("Expected Err"); + + let container_err_a = assert_match!( + err, + DIContainerError::BindingResolveFailed { + reason: InjectableError::ResolveFailed { reason, affected: _ }, + interface: _ + } => *reason + ); + + let container_err_b = assert_match!( + container_err_a, + DIContainerError::BindingResolveFailed { + reason: InjectableError::ResolveFailed { reason, affected: _ }, + interface: _ + } => *reason + ); + + assert!(matches!( + container_err_b, + DIContainerError::BindingResolveFailed { + reason: InjectableError::DetectedCircular { + dependency_history: _ + }, + interface: _ + } + )); +} -- cgit v1.2.3-18-g5258