use { std::sync::{Arc, Mutex}, tsukuyomi::{ config::prelude::*, // handler::{AllowedMethods, Handler, ModifyHandler}, App, }, }; #[derive(Clone)] struct MockModifier { marker: Arc>>, name: &'static str, } impl ModifyHandler for MockModifier { type Output = H::Output; type Handler = MockHandler; fn modify(&self, inner: H) -> Self::Handler { MockHandler { inner, marker: self.marker.clone(), name: self.name, } } } struct MockHandler { inner: H, marker: Arc>>, name: &'static str, } impl Handler for MockHandler where H: Handler, { type Output = H::Output; type Error = H::Error; type Handle = H::Handle; fn allowed_methods(&self) -> Option<&AllowedMethods> { self.inner.allowed_methods() } fn handle(&self) -> Self::Handle { self.marker.lock().unwrap().push(self.name); self.inner.handle() } } #[test] fn global_modifier() -> tsukuyomi_server::Result<()> { let marker = Arc::new(Mutex::new(vec![])); let app = App::create( path!("/") // .to(endpoint::reply("")) .modify(MockModifier { marker: marker.clone(), name: "M", }), )?; let mut server = tsukuyomi_server::test::server(app)?; let _ = server.perform("/")?; assert_eq!(*marker.lock().unwrap(), vec!["M"]); marker.lock().unwrap().clear(); let _ = server.perform("/noroute")?; assert!(marker.lock().unwrap().is_empty()); Ok(()) } #[test] fn global_modifiers() -> tsukuyomi_server::Result<()> { let marker = Arc::new(Mutex::new(vec![])); let app = App::create( path!("/") // .to(endpoint::reply("")) .modify(chain![ MockModifier { marker: marker.clone(), name: "M1", }, MockModifier { marker: marker.clone(), name: "M2", } ]), )?; let mut server = tsukuyomi_server::test::server(app)?; let _ = server.perform("/")?; assert_eq!(*marker.lock().unwrap(), vec!["M2", "M1"]); Ok(()) } #[test] fn scoped_modifier() -> tsukuyomi_server::Result<()> { let marker = Arc::new(Mutex::new(vec![])); let app = App::create( chain![ mount("/path1").with({ path!("/") // .to(endpoint::reply("")) .modify(MockModifier { marker: marker.clone(), name: "M2", }) }), // path!("/path2").to(endpoint::reply("")), ] .modify(MockModifier { marker: marker.clone(), name: "M1", }), )?; let mut server = tsukuyomi_server::test::server(app)?; let _ = server.perform("/path1")?; assert_eq!(*marker.lock().unwrap(), vec!["M2", "M1"]); marker.lock().unwrap().clear(); let _ = server.perform("/path2")?; assert_eq!(*marker.lock().unwrap(), vec!["M1"]); Ok(()) } #[test] fn nested_modifiers() -> tsukuyomi_server::Result<()> { let marker = Arc::new(Mutex::new(vec![])); let app = App::create({ mount("/path").with({ mount("/to") .with( chain![ path!("/").to(endpoint::reply("")), mount("/a").with({ path!("/") // .to(endpoint::reply("")) .modify(MockModifier { marker: marker.clone(), name: "M3", }) }) ] .modify(MockModifier { marker: marker.clone(), name: "M2", }), ) .modify(MockModifier { marker: marker.clone(), name: "M1", }) }) })?; let mut server = tsukuyomi_server::test::server(app)?; let _ = server.perform("/path/to")?; assert_eq!(*marker.lock().unwrap(), vec!["M2", "M1"]); marker.lock().unwrap().clear(); let _ = server.perform("/path/to/a")?; assert_eq!(*marker.lock().unwrap(), vec!["M3", "M2", "M1"]); Ok(()) }