From 5c61321565d02f8c08b73d31a90676a48ab08694 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Sun, 3 Mar 2019 21:40:03 -0800 Subject: [PATCH] fix state factory support, tests for state and state factory --- src/app.rs | 175 +++++++++++++++++++++++++++++++++++++++++++++-- src/responder.rs | 37 ++++++++++ src/scope.rs | 2 +- 3 files changed, 208 insertions(+), 6 deletions(-) diff --git a/src/app.rs b/src/app.rs index 27658011..3940b9fc 100644 --- a/src/app.rs +++ b/src/app.rs @@ -14,7 +14,7 @@ use futures::future::{ok, Either, FutureResult}; use futures::{Async, Future, IntoFuture, Poll}; use crate::resource::Resource; -use crate::scope::Scope; +use crate::scope::{insert_slash, Scope}; use crate::service::{ServiceRequest, ServiceResponse}; use crate::state::{State, StateFactory, StateFactoryResult}; @@ -103,13 +103,13 @@ where /// Set application state factory. This function is /// similar to `.state()` but it accepts state factory. State get /// constructed asynchronously during application initialization. - pub fn state_factory(mut self, state: F) -> Self + pub fn state_factory(mut self, state: F) -> Self where F: Fn() -> Out + 'static, Out: IntoFuture + 'static, Out::Error: std::fmt::Debug, { - self.state.push(Box::new(State::new(state))); + self.state.push(Box::new(state)); self } @@ -200,7 +200,7 @@ where InitError = (), > + 'static, { - let rdef = ResourceDef::new(path); + let rdef = ResourceDef::new(&insert_slash(path)); let resource = f(Resource::new()); let default = resource.get_default(); @@ -408,7 +408,7 @@ where InitError = (), > + 'static, { - let rdef = ResourceDef::new(path); + let rdef = ResourceDef::new(&insert_slash(path)); let resource = f(Resource::new()); self.defaults.push(resource.get_default()); self.services @@ -891,3 +891,168 @@ where self.chain.call(req) } } + +#[cfg(test)] +mod tests { + use actix_http::http::StatusCode; + + use super::*; + use crate::test::TestRequest; + use crate::{HttpResponse, State}; + + #[test] + fn test_default_resource() { + let mut rt = actix_rt::Runtime::new().unwrap(); + + let app = App::new() + .resource("/test", |r| r.to(|| HttpResponse::Ok())) + .into_new_service(); + let mut srv = rt.block_on(app.new_service(&())).unwrap(); + + let req = TestRequest::with_uri("/test").to_request(); + let resp = rt.block_on(srv.call(req)).unwrap(); + assert_eq!(resp.status(), StatusCode::OK); + + let req = TestRequest::with_uri("/blah").to_request(); + let resp = rt.block_on(srv.call(req)).unwrap(); + assert_eq!(resp.status(), StatusCode::NOT_FOUND); + + let app = App::new() + .resource("/test", |r| r.to(|| HttpResponse::Ok())) + .default_resource(|r| r.to(|| HttpResponse::MethodNotAllowed())) + .into_new_service(); + let mut srv = rt.block_on(app.new_service(&())).unwrap(); + + let req = TestRequest::with_uri("/blah").to_request(); + let resp = rt.block_on(srv.call(req)).unwrap(); + assert_eq!(resp.status(), StatusCode::METHOD_NOT_ALLOWED); + } + + #[test] + fn test_state() { + let mut rt = actix_rt::Runtime::new().unwrap(); + let app = App::new() + .state(10usize) + .resource("/", |r| r.to(|_: State| HttpResponse::Ok())) + .into_new_service(); + let mut srv = rt.block_on(app.new_service(&())).unwrap(); + + let req = TestRequest::default().to_request(); + let resp = rt.block_on(srv.call(req)).unwrap(); + assert_eq!(resp.status(), StatusCode::OK); + + let app = App::new() + .state(10u32) + .resource("/", |r| r.to(|_: State| HttpResponse::Ok())) + .into_new_service(); + let mut srv = rt.block_on(app.new_service(&())).unwrap(); + + let req = TestRequest::default().to_request(); + let resp = rt.block_on(srv.call(req)).unwrap(); + assert_eq!(resp.status(), StatusCode::INTERNAL_SERVER_ERROR); + } + + #[test] + fn test_state_factory() { + let mut rt = actix_rt::Runtime::new().unwrap(); + let app = App::new() + .state_factory(|| Ok::<_, ()>(10usize)) + .resource("/", |r| r.to(|_: State| HttpResponse::Ok())) + .into_new_service(); + let mut srv = rt.block_on(app.new_service(&())).unwrap(); + + let req = TestRequest::default().to_request(); + let resp = rt.block_on(srv.call(req)).unwrap(); + assert_eq!(resp.status(), StatusCode::OK); + + let app = App::new() + .state_factory(|| Ok::<_, ()>(10u32)) + .resource("/", |r| r.to(|_: State| HttpResponse::Ok())) + .into_new_service(); + let mut srv = rt.block_on(app.new_service(&())).unwrap(); + + let req = TestRequest::default().to_request(); + let resp = rt.block_on(srv.call(req)).unwrap(); + assert_eq!(resp.status(), StatusCode::INTERNAL_SERVER_ERROR); + } + + // #[test] + // fn test_handler() { + // let app = App::new() + // .handler("/test", |_: &_| HttpResponse::Ok()) + // .finish(); + + // let req = TestRequest::with_uri("/test").request(); + // let resp = app.run(req); + // assert_eq!(resp.as_msg().status(), StatusCode::OK); + + // let req = TestRequest::with_uri("/test/").request(); + // let resp = app.run(req); + // assert_eq!(resp.as_msg().status(), StatusCode::OK); + + // let req = TestRequest::with_uri("/test/app").request(); + // let resp = app.run(req); + // assert_eq!(resp.as_msg().status(), StatusCode::OK); + + // let req = TestRequest::with_uri("/testapp").request(); + // let resp = app.run(req); + // assert_eq!(resp.as_msg().status(), StatusCode::NOT_FOUND); + + // let req = TestRequest::with_uri("/blah").request(); + // let resp = app.run(req); + // assert_eq!(resp.as_msg().status(), StatusCode::NOT_FOUND); + // } + + // #[test] + // fn test_handler2() { + // let app = App::new() + // .handler("test", |_: &_| HttpResponse::Ok()) + // .finish(); + + // let req = TestRequest::with_uri("/test").request(); + // let resp = app.run(req); + // assert_eq!(resp.as_msg().status(), StatusCode::OK); + + // let req = TestRequest::with_uri("/test/").request(); + // let resp = app.run(req); + // assert_eq!(resp.as_msg().status(), StatusCode::OK); + + // let req = TestRequest::with_uri("/test/app").request(); + // let resp = app.run(req); + // assert_eq!(resp.as_msg().status(), StatusCode::OK); + + // let req = TestRequest::with_uri("/testapp").request(); + // let resp = app.run(req); + // assert_eq!(resp.as_msg().status(), StatusCode::NOT_FOUND); + + // let req = TestRequest::with_uri("/blah").request(); + // let resp = app.run(req); + // assert_eq!(resp.as_msg().status(), StatusCode::NOT_FOUND); + // } + + // #[test] + // fn test_route() { + // let app = App::new() + // .route("/test", Method::GET, |_: HttpRequest| HttpResponse::Ok()) + // .route("/test", Method::POST, |_: HttpRequest| { + // HttpResponse::Created() + // }) + // .finish(); + + // let req = TestRequest::with_uri("/test").method(Method::GET).request(); + // let resp = app.run(req); + // assert_eq!(resp.as_msg().status(), StatusCode::OK); + + // let req = TestRequest::with_uri("/test") + // .method(Method::POST) + // .request(); + // let resp = app.run(req); + // assert_eq!(resp.as_msg().status(), StatusCode::CREATED); + + // let req = TestRequest::with_uri("/test") + // .method(Method::HEAD) + // .request(); + // let resp = app.run(req); + // assert_eq!(resp.as_msg().status(), StatusCode::NOT_FOUND); + // } +} diff --git a/src/responder.rs b/src/responder.rs index 22588a9c..8e7f66b4 100644 --- a/src/responder.rs +++ b/src/responder.rs @@ -272,3 +272,40 @@ where Ok(self.0.poll().map_err(|e| e.into())?) } } + +#[cfg(test)] +mod tests { + // use actix_http::body::Body; + use actix_http::body::{Body, ResponseBody}; + use actix_http::http::StatusCode; + use actix_service::{IntoNewService, NewService, Service}; + use bytes::Bytes; + + use crate::test::TestRequest; + use crate::App; + + #[test] + fn test_option_responder() { + let mut rt = actix_rt::Runtime::new().unwrap(); + let app = App::new() + .resource("/none", |r| r.to(|| -> Option<&'static str> { None })) + .resource("/some", |r| r.to(|| Some("some"))) + .into_new_service(); + let mut srv = rt.block_on(app.new_service(&())).unwrap(); + + let req = TestRequest::with_uri("/none").to_request(); + let resp = rt.block_on(srv.call(req)).unwrap(); + assert_eq!(resp.status(), StatusCode::NOT_FOUND); + + let req = TestRequest::with_uri("/some").to_request(); + let resp = rt.block_on(srv.call(req)).unwrap(); + assert_eq!(resp.status(), StatusCode::OK); + match resp.body() { + ResponseBody::Body(Body::Bytes(ref b)) => { + let bytes: Bytes = b.clone().into(); + assert_eq!(bytes, Bytes::from_static(b"some")); + } + _ => panic!(), + } + } +} diff --git a/src/scope.rs b/src/scope.rs index 5327f953..ec6bc035 100644 --- a/src/scope.rs +++ b/src/scope.rs @@ -272,7 +272,7 @@ where } } -fn insert_slash(path: &str) -> String { +pub(crate) fn insert_slash(path: &str) -> String { let mut path = path.to_owned(); if !path.is_empty() && !path.starts_with('/') { path.insert(0, '/');