From c14c66d2b00427482f7fd3b3e54af80a257a2641 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Sun, 17 Mar 2019 09:52:41 -0700 Subject: [PATCH] add json extractor tests --- .travis.yml | 2 +- src/error.rs | 4 +-- src/responder.rs | 4 +-- src/test.rs | 24 +++++++++++--- src/types/json.rs | 83 +++++++++++++++++++++++++++++++++++++++++++++-- 5 files changed, 105 insertions(+), 12 deletions(-) diff --git a/.travis.yml b/.travis.yml index 32e6c136c..9caaac1b5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,7 +12,7 @@ matrix: - rust: beta - rust: nightly-2019-03-02 allow_failures: - - rust: nightly + - rust: nightly-2019-03-02 env: global: diff --git a/src/error.rs b/src/error.rs index bf224a223..2231473f2 100644 --- a/src/error.rs +++ b/src/error.rs @@ -87,8 +87,8 @@ impl ResponseError for UrlencodedError { /// A set of errors that can occur during parsing json payloads #[derive(Debug, Display, From)] pub enum JsonPayloadError { - /// Payload size is bigger than allowed. (default: 256kB) - #[display(fmt = "Json payload size is bigger than allowed. (default: 256kB)")] + /// Payload size is bigger than allowed. (default: 32kB) + #[display(fmt = "Json payload size is bigger than allowed.")] Overflow, /// Content type error #[display(fmt = "Content type error")] diff --git a/src/responder.rs b/src/responder.rs index 5f98e6e83..871670bdf 100644 --- a/src/responder.rs +++ b/src/responder.rs @@ -288,7 +288,7 @@ where } #[cfg(test)] -mod tests { +pub(crate) mod tests { use actix_service::Service; use bytes::{Bytes, BytesMut}; @@ -322,7 +322,7 @@ mod tests { } } - trait BodyTest { + pub(crate) trait BodyTest { fn bin_ref(&self) -> &[u8]; fn body(&self) -> &Body; } diff --git a/src/test.rs b/src/test.rs index 13db59771..fe9fb0247 100644 --- a/src/test.rs +++ b/src/test.rs @@ -5,7 +5,7 @@ use std::rc::Rc; use actix_http::http::header::{Header, HeaderName, IntoHeaderValue}; use actix_http::http::{HttpTryFrom, Method, Version}; use actix_http::test::TestRequest as HttpTestRequest; -use actix_http::{PayloadStream, Request}; +use actix_http::{Extensions, PayloadStream, Request}; use actix_router::{Path, ResourceDef, Url}; use actix_rt::Runtime; use actix_server_config::ServerConfig; @@ -15,6 +15,7 @@ use cookie::Cookie; use futures::future::{lazy, Future}; use crate::config::{AppConfig, AppConfigInner}; +use crate::data::RouteData; use crate::rmap::ResourceMap; use crate::service::{ServiceFromRequest, ServiceRequest, ServiceResponse}; use crate::{HttpRequest, HttpResponse}; @@ -157,6 +158,7 @@ pub struct TestRequest { req: HttpTestRequest, rmap: ResourceMap, config: AppConfigInner, + route_data: Extensions, } impl Default for TestRequest { @@ -165,6 +167,7 @@ impl Default for TestRequest { req: HttpTestRequest::default(), rmap: ResourceMap::new(ResourceDef::new("")), config: AppConfigInner::default(), + route_data: Extensions::new(), } } } @@ -177,6 +180,7 @@ impl TestRequest { req: HttpTestRequest::default().uri(path).take(), rmap: ResourceMap::new(ResourceDef::new("")), config: AppConfigInner::default(), + route_data: Extensions::new(), } } @@ -186,6 +190,7 @@ impl TestRequest { req: HttpTestRequest::default().set(hdr).take(), config: AppConfigInner::default(), rmap: ResourceMap::new(ResourceDef::new("")), + route_data: Extensions::new(), } } @@ -199,6 +204,7 @@ impl TestRequest { req: HttpTestRequest::default().header(key, value).take(), config: AppConfigInner::default(), rmap: ResourceMap::new(ResourceDef::new("")), + route_data: Extensions::new(), } } @@ -208,6 +214,7 @@ impl TestRequest { req: HttpTestRequest::default().method(Method::GET).take(), config: AppConfigInner::default(), rmap: ResourceMap::new(ResourceDef::new("")), + route_data: Extensions::new(), } } @@ -217,6 +224,7 @@ impl TestRequest { req: HttpTestRequest::default().method(Method::POST).take(), config: AppConfigInner::default(), rmap: ResourceMap::new(ResourceDef::new("")), + route_data: Extensions::new(), } } @@ -266,12 +274,20 @@ impl TestRequest { self } - /// Set route data - pub fn route_data(self, data: T) -> Self { + /// Set application data. This is equivalent of `App::data()` method + /// for testing purpose. + pub fn app_data(self, data: T) -> Self { self.config.extensions.borrow_mut().insert(data); self } + /// Set route data. This is equivalent of `Route::data()` method + /// for testing purpose. + pub fn route_data(mut self, data: T) -> Self { + self.route_data.insert(RouteData::new(data)); + self + } + #[cfg(test)] /// Set request config pub(crate) fn rmap(mut self, rmap: ResourceMap) -> Self { @@ -324,7 +340,7 @@ impl TestRequest { Rc::new(self.rmap), AppConfig::new(self.config), ); - ServiceFromRequest::new(req, None) + ServiceFromRequest::new(req, Some(Rc::new(self.route_data))) } /// Runs the provided future, blocking the current thread until the future diff --git a/src/types/json.rs b/src/types/json.rs index 4fc2748f0..9e13d994e 100644 --- a/src/types/json.rs +++ b/src/types/json.rs @@ -371,6 +371,11 @@ mod tests { use crate::http::header; use crate::test::{block_on, TestRequest}; + #[derive(Serialize, Deserialize, PartialEq, Debug)] + struct MyObject { + name: String, + } + fn json_eq(err: JsonPayloadError, other: JsonPayloadError) -> bool { match err { JsonPayloadError::Overflow => match other { @@ -385,9 +390,81 @@ mod tests { } } - #[derive(Serialize, Deserialize, PartialEq, Debug)] - struct MyObject { - name: String, + #[test] + fn test_responder() { + let req = TestRequest::default().to_http_request(); + + let j = Json(MyObject { + name: "test".to_string(), + }); + let resp = j.respond_to(&req).unwrap(); + assert_eq!(resp.status(), StatusCode::OK); + assert_eq!( + resp.headers().get(header::CONTENT_TYPE).unwrap(), + header::HeaderValue::from_static("application/json") + ); + + use crate::responder::tests::BodyTest; + assert_eq!(resp.body().bin_ref(), b"{\"name\":\"test\"}"); + } + + #[test] + fn test_extract() { + let mut req = TestRequest::default() + .header( + header::CONTENT_TYPE, + header::HeaderValue::from_static("application/json"), + ) + .header( + header::CONTENT_LENGTH, + header::HeaderValue::from_static("16"), + ) + .set_payload(Bytes::from_static(b"{\"name\": \"test\"}")) + .to_from(); + + let s = block_on(Json::::from_request(&mut req)).unwrap(); + assert_eq!(s.name, "test"); + assert_eq!( + s.into_inner(), + MyObject { + name: "test".to_string() + } + ); + + let mut req = TestRequest::default() + .header( + header::CONTENT_TYPE, + header::HeaderValue::from_static("application/json"), + ) + .header( + header::CONTENT_LENGTH, + header::HeaderValue::from_static("16"), + ) + .set_payload(Bytes::from_static(b"{\"name\": \"test\"}")) + .route_data(JsonConfig::default().limit(10)) + .to_from(); + let s = block_on(Json::::from_request(&mut req)); + assert!(format!("{}", s.err().unwrap()) + .contains("Json payload size is bigger than allowed.")); + + let mut req = TestRequest::default() + .header( + header::CONTENT_TYPE, + header::HeaderValue::from_static("application/json"), + ) + .header( + header::CONTENT_LENGTH, + header::HeaderValue::from_static("16"), + ) + .set_payload(Bytes::from_static(b"{\"name\": \"test\"}")) + .route_data( + JsonConfig::default() + .limit(10) + .error_handler(|_, _| JsonPayloadError::ContentType.into()), + ) + .to_from(); + let s = block_on(Json::::from_request(&mut req)); + assert!(format!("{}", s.err().unwrap()).contains("Content type error")); } #[test]