From 983ee9b32d1d5efc15388c2a2feac7ec9d274285 Mon Sep 17 00:00:00 2001 From: Sergio Benitez Date: Sat, 3 Nov 2018 01:51:00 -0700 Subject: [PATCH] Make inner 'LenientForm' field public. Add 'State::from()'. --- core/lib/src/request/form/lenient.rs | 2 +- core/lib/src/request/state.rs | 51 ++++++++++++++++++++++++++++ examples/state/src/tests.rs | 12 +++++++ 3 files changed, 64 insertions(+), 1 deletion(-) diff --git a/core/lib/src/request/form/lenient.rs b/core/lib/src/request/form/lenient.rs index bac3b05b..fbb47724 100644 --- a/core/lib/src/request/form/lenient.rs +++ b/core/lib/src/request/form/lenient.rs @@ -59,7 +59,7 @@ use http::uri::FromUriParam; /// forms = 524288 /// ``` #[derive(Debug)] -pub struct LenientForm(crate T); +pub struct LenientForm(pub T); impl LenientForm { /// Consumes `self` and returns the parsed value. diff --git a/core/lib/src/request/state.rs b/core/lib/src/request/state.rs index 7bb9b2ad..be4eb5a5 100644 --- a/core/lib/src/request/state.rs +++ b/core/lib/src/request/state.rs @@ -1,5 +1,6 @@ use std::ops::Deref; +use Rocket; use request::{self, FromRequest, Request}; use outcome::Outcome; use http::Status; @@ -78,6 +79,29 @@ use http::Status; /// } /// } /// ``` +/// +/// # Testing with `State` +/// +/// When unit testing your application, you may find it necessary to manually +/// construct a type of `State` to pass to your functions. To do so, use the +/// [`State::from()`] static method: +/// +/// ```rust +/// # #![feature(proc_macro_hygiene, decl_macro)] +/// # #[macro_use] extern crate rocket; +/// use rocket::State; +/// +/// struct MyManagedState(usize); +/// +/// #[get("/")] +/// fn handler(state: State) -> String { +/// state.0.to_string() +/// } +/// +/// let rocket = rocket::ignite().manage(MyManagedState(127)); +/// let state = State::from(&rocket).expect("managing `MyManagedState`"); +/// assert_eq!(handler(state), "127"); +/// ``` #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct State<'r, T: Send + Sync + 'static>(&'r T); @@ -112,6 +136,33 @@ impl<'r, T: Send + Sync + 'static> State<'r, T> { pub fn inner(&self) -> &'r T { self.0 } + + /// Returns the managed state value in `rocket` for the type `T` if it is + /// being managed by `rocket`. Otherwise, returns `None`. + /// + /// # Example + /// + /// ```rust + /// use rocket::State; + /// + /// #[derive(Debug, PartialEq)] + /// struct Managed(usize); + /// + /// #[derive(Debug, PartialEq)] + /// struct Unmanaged(usize); + /// + /// let rocket = rocket::ignite().manage(Managed(7)); + /// + /// let state: Option> = State::from(&rocket); + /// assert_eq!(state.map(|s| s.inner()), Some(&Managed(7))); + /// + /// let state: Option> = State::from(&rocket); + /// assert_eq!(state, None); + /// ``` + #[inline(always)] + pub fn from(rocket: &'r Rocket) -> Option { + rocket.state.try_get::().map(State) + } } impl<'a, 'r, T: Send + Sync + 'static> FromRequest<'a, 'r> for State<'r, T> { diff --git a/examples/state/src/tests.rs b/examples/state/src/tests.rs index f2b060a1..d27faf6a 100644 --- a/examples/state/src/tests.rs +++ b/examples/state/src/tests.rs @@ -25,6 +25,18 @@ fn test_count() { assert_eq!(get_count(&client), 100); } +#[test] +fn test_raw_state_count() { + use rocket::State; + use super::{count, index}; + + let rocket = super::rocket(); + + assert_eq!(count(State::from(&rocket).unwrap()), "0"); + assert!(index(State::from(&rocket).unwrap()).0.contains("Visits: 1")); + assert_eq!(count(State::from(&rocket).unwrap()), "1"); +} + // Cargo runs each test in parallel on different threads. We use all of these // tests below to show (and assert) that state is managed per-Rocket instance. #[test] fn test_count_parallel() { test_count() }