mirror of https://github.com/rwf2/Rocket.git
Adds tests for JSON example. Emit warning from JSON FromData.
This also includes a tiny change to the `mk-docs` script to build a blank index at the root of the docs.
This commit is contained in:
parent
b9742c1202
commit
2dc1ba29f0
|
@ -4,7 +4,7 @@ extern crate serde_json;
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
|
||||||
use rocket::outcome::{Outcome, IntoOutcome};
|
use rocket::outcome::Outcome;
|
||||||
use rocket::request::Request;
|
use rocket::request::Request;
|
||||||
use rocket::data::{self, Data, FromData};
|
use rocket::data::{self, Data, FromData};
|
||||||
use rocket::response::{self, Responder, content};
|
use rocket::response::{self, Responder, content};
|
||||||
|
@ -78,7 +78,13 @@ impl<T: Deserialize> FromData for JSON<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let reader = data.open().take(MAX_SIZE);
|
let reader = data.open().take(MAX_SIZE);
|
||||||
serde_json::from_reader(reader).map(|val| JSON(val)).into_outcome()
|
match serde_json::from_reader(reader).map(|val| JSON(val)) {
|
||||||
|
Ok(value) => Outcome::Success(value),
|
||||||
|
Err(e) => {
|
||||||
|
error_!("Couldn't parse JSON body: {:?}", e);
|
||||||
|
Outcome::Failure((Status::BadRequest, e))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ extern crate rocket;
|
||||||
#[cfg(test)] mod tests;
|
#[cfg(test)] mod tests;
|
||||||
|
|
||||||
#[get("/hello/<name>/<age>")]
|
#[get("/hello/<name>/<age>")]
|
||||||
fn hello(name: &str, age: i8) -> String {
|
fn hello(name: &str, age: u8) -> String {
|
||||||
format!("Hello, {} year old named {}!", age, name)
|
format!("Hello, {} year old named {}!", age, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,8 +29,8 @@ fn test_hello() {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_failing_hello() {
|
fn test_failing_hello() {
|
||||||
test_404("/hello/Mike/1000");
|
test_404("/hello/Mike/1000");
|
||||||
test_404("/hello/Mike/128");
|
|
||||||
test_404("/hello/Mike/-129");
|
test_404("/hello/Mike/-129");
|
||||||
|
test_404("/hello/Mike/-1");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -16,3 +16,6 @@ lazy_static = "*"
|
||||||
path = "../../contrib"
|
path = "../../contrib"
|
||||||
default-features = false
|
default-features = false
|
||||||
features = ["json"]
|
features = ["json"]
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
rocket = { path = "../../lib", features = ["testing"] }
|
||||||
|
|
|
@ -7,6 +7,8 @@ extern crate serde_json;
|
||||||
#[macro_use] extern crate rocket_contrib;
|
#[macro_use] extern crate rocket_contrib;
|
||||||
#[macro_use] extern crate serde_derive;
|
#[macro_use] extern crate serde_derive;
|
||||||
|
|
||||||
|
#[cfg(test)] mod tests;
|
||||||
|
|
||||||
use rocket_contrib::JSON;
|
use rocket_contrib::JSON;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
|
@ -27,22 +29,9 @@ struct Message {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: This example can be improved by using `route` with muliple HTTP verbs.
|
// TODO: This example can be improved by using `route` with muliple HTTP verbs.
|
||||||
// To be precise, put/post could/should look like:
|
|
||||||
// #[route(PUT, POST, path = "/<id>", format = "application/json")]
|
|
||||||
// fn f(method: Method, id: ID, message: JSON<Message>) -> Option<JSON<SimpleMap>> {
|
|
||||||
// let mut hashmap = MAP.lock().unwrap();
|
|
||||||
// let exists = hashmap.contains_key(&id);
|
|
||||||
// if method == Method::Put && exists || method == Method::Post && !exists {
|
|
||||||
// hashmap.insert(id, message.0.contents);
|
|
||||||
// return Ok(JSON(map!{ "status" => "ok" }))
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// None
|
|
||||||
// }
|
|
||||||
|
|
||||||
#[post("/<id>", format = "application/json", data = "<message>")]
|
#[post("/<id>", format = "application/json", data = "<message>")]
|
||||||
fn new(id: ID, message: JSON<Message>) -> JSON<SimpleMap> {
|
fn new(id: ID, message: JSON<Message>) -> JSON<SimpleMap> {
|
||||||
let mut hashmap = MAP.lock().unwrap();
|
let mut hashmap = MAP.lock().expect("map lock.");
|
||||||
if hashmap.contains_key(&id) {
|
if hashmap.contains_key(&id) {
|
||||||
JSON(map!{
|
JSON(map!{
|
||||||
"status" => "error",
|
"status" => "error",
|
||||||
|
|
|
@ -0,0 +1,95 @@
|
||||||
|
use rocket;
|
||||||
|
use rocket::testing::MockRequest;
|
||||||
|
use rocket::http::Method::*;
|
||||||
|
use rocket::http::{Status, ContentType};
|
||||||
|
use rocket::Response;
|
||||||
|
|
||||||
|
macro_rules! run_test {
|
||||||
|
($req:expr, $test_fn:expr) => ({
|
||||||
|
let rocket = rocket::ignite()
|
||||||
|
.mount("/message", routes![super::new, super::update, super::get])
|
||||||
|
.catch(errors![super::not_found]);
|
||||||
|
|
||||||
|
$test_fn($req.dispatch_with(&rocket));
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn bad_get_put() {
|
||||||
|
// Try to get a message with an ID that doesn't exist.
|
||||||
|
let mut req = MockRequest::new(Get, "/message/99").header(ContentType::JSON);
|
||||||
|
run_test!(req, |mut response: Response| {
|
||||||
|
assert_eq!(response.status(), Status::NotFound);
|
||||||
|
|
||||||
|
let body = response.body().unwrap().into_string().unwrap();
|
||||||
|
assert!(body.contains("error"));
|
||||||
|
assert!(body.contains("Resource was not found."));
|
||||||
|
});
|
||||||
|
|
||||||
|
// Try to get a message with an invalid ID.
|
||||||
|
let mut req = MockRequest::new(Get, "/message/hi").header(ContentType::JSON);
|
||||||
|
run_test!(req, |mut response: Response| {
|
||||||
|
assert_eq!(response.status(), Status::NotFound);
|
||||||
|
let body = response.body().unwrap().into_string().unwrap();
|
||||||
|
assert!(body.contains("error"));
|
||||||
|
});
|
||||||
|
|
||||||
|
// Try to put a message without a proper body.
|
||||||
|
let mut req = MockRequest::new(Put, "/message/80").header(ContentType::JSON);
|
||||||
|
run_test!(req, |response: Response| {
|
||||||
|
assert_eq!(response.status(), Status::BadRequest);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Try to put a message for an ID that doesn't exist.
|
||||||
|
let mut req = MockRequest::new(Put, "/message/80")
|
||||||
|
.header(ContentType::JSON)
|
||||||
|
.body(r#"{ "contents": "Bye bye, world!" }"#);
|
||||||
|
|
||||||
|
run_test!(req, |response: Response| {
|
||||||
|
assert_eq!(response.status(), Status::NotFound);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn post_get_put_get() {
|
||||||
|
// Check that a message with ID 1 doesn't exist.
|
||||||
|
let mut req = MockRequest::new(Get, "/message/1").header(ContentType::JSON);
|
||||||
|
run_test!(req, |response: Response| {
|
||||||
|
assert_eq!(response.status(), Status::NotFound);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add a new message with ID 1.
|
||||||
|
let mut req = MockRequest::new(Post, "/message/1")
|
||||||
|
.header(ContentType::JSON)
|
||||||
|
.body(r#"{ "contents": "Hello, world!" }"#);
|
||||||
|
|
||||||
|
run_test!(req, |response: Response| {
|
||||||
|
assert_eq!(response.status(), Status::Ok);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Check that the message exists with the correct contents.
|
||||||
|
let mut req = MockRequest::new(Get, "/message/1") .header(ContentType::JSON);
|
||||||
|
run_test!(req, |mut response: Response| {
|
||||||
|
assert_eq!(response.status(), Status::Ok);
|
||||||
|
let body = response.body().unwrap().into_string().unwrap();
|
||||||
|
assert!(body.contains("Hello, world!"));
|
||||||
|
});
|
||||||
|
|
||||||
|
// Change the message contents.
|
||||||
|
let mut req = MockRequest::new(Put, "/message/1")
|
||||||
|
.header(ContentType::JSON)
|
||||||
|
.body(r#"{ "contents": "Bye bye, world!" }"#);
|
||||||
|
|
||||||
|
run_test!(req, |response: Response| {
|
||||||
|
assert_eq!(response.status(), Status::Ok);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Check that the message exists with the updated contents.
|
||||||
|
let mut req = MockRequest::new(Get, "/message/1") .header(ContentType::JSON);
|
||||||
|
run_test!(req, |mut response: Response| {
|
||||||
|
assert_eq!(response.status(), Status::Ok);
|
||||||
|
let body = response.body().unwrap().into_string().unwrap();
|
||||||
|
assert!(!body.contains("Hello, world!"));
|
||||||
|
assert!(body.contains("Bye bye, world!"));
|
||||||
|
});
|
||||||
|
}
|
|
@ -224,13 +224,13 @@ impl<'r, R: Responder<'r>> Responder<'r> for Option<R> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If `self` is `Ok`, responds with the wrapped `Responder`. Otherwise prints a
|
/// If `self` is `Ok`, responds with the wrapped `Responder`. Otherwise prints
|
||||||
/// warning message with the `Err` value returns an `Err` of
|
/// an error message with the `Err` value returns an `Err` of
|
||||||
/// `Status::InternalServerError`.
|
/// `Status::InternalServerError`.
|
||||||
impl<'r, R: Responder<'r>, E: fmt::Debug> Responder<'r> for Result<R, E> {
|
impl<'r, R: Responder<'r>, E: fmt::Debug> Responder<'r> for Result<R, E> {
|
||||||
default fn respond(self) -> Result<Response<'r>, Status> {
|
default fn respond(self) -> Result<Response<'r>, Status> {
|
||||||
self.map(|r| r.respond()).unwrap_or_else(|e| {
|
self.map(|r| r.respond()).unwrap_or_else(|e| {
|
||||||
warn_!("Response was `Err`: {:?}.", e);
|
error_!("Response was `Err`: {:?}.", e);
|
||||||
Err(Status::InternalServerError)
|
Err(Status::InternalServerError)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,3 +25,6 @@ cargo clean
|
||||||
mk_doc $LIB_DIR
|
mk_doc $LIB_DIR
|
||||||
mk_doc $CODEGEN_DIR
|
mk_doc $CODEGEN_DIR
|
||||||
mk_doc $CONTRIB_DIR --all-features
|
mk_doc $CONTRIB_DIR --all-features
|
||||||
|
|
||||||
|
# Blank index, for redirection.
|
||||||
|
touch ${DOC_DIR}/index.html
|
||||||
|
|
Loading…
Reference in New Issue