mirror of https://github.com/rwf2/Rocket.git
Fix 'static_files' and 'serve' tests.
This commit is contained in:
parent
b780f9d8e0
commit
8c8598b4fd
|
@ -45,7 +45,7 @@ mod static_tests {
|
||||||
"inner/",
|
"inner/",
|
||||||
];
|
];
|
||||||
|
|
||||||
fn assert_file(client: &Client, prefix: &str, path: &str, exists: bool) {
|
async fn assert_file(client: &Client, prefix: &str, path: &str, exists: bool) {
|
||||||
let full_path = format!("/{}/{}", prefix, path);
|
let full_path = format!("/{}/{}", prefix, path);
|
||||||
let mut response = client.get(full_path).dispatch();
|
let mut response = client.get(full_path).dispatch();
|
||||||
if exists {
|
if exists {
|
||||||
|
@ -59,50 +59,60 @@ mod static_tests {
|
||||||
let mut file = File::open(path).expect("open file");
|
let mut file = File::open(path).expect("open file");
|
||||||
let mut expected_contents = String::new();
|
let mut expected_contents = String::new();
|
||||||
file.read_to_string(&mut expected_contents).expect("read file");
|
file.read_to_string(&mut expected_contents).expect("read file");
|
||||||
assert_eq!(response.body_string_wait(), Some(expected_contents));
|
assert_eq!(response.body_string().await, Some(expected_contents));
|
||||||
} else {
|
} else {
|
||||||
assert_eq!(response.status(), Status::NotFound);
|
assert_eq!(response.status(), Status::NotFound);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn assert_all(client: &Client, prefix: &str, paths: &[&str], exist: bool) {
|
async fn assert_all(client: &Client, prefix: &str, paths: &[&str], exist: bool) {
|
||||||
paths.iter().for_each(|path| assert_file(client, prefix, path, exist))
|
for path in paths.iter() {
|
||||||
|
assert_file(client, prefix, path, exist).await;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_static_no_index() {
|
fn test_static_no_index() {
|
||||||
|
rocket::async_test(async {
|
||||||
let client = Client::new(rocket()).expect("valid rocket");
|
let client = Client::new(rocket()).expect("valid rocket");
|
||||||
assert_all(&client, "no_index", REGULAR_FILES, true);
|
assert_all(&client, "no_index", REGULAR_FILES, true).await;
|
||||||
assert_all(&client, "no_index", HIDDEN_FILES, false);
|
assert_all(&client, "no_index", HIDDEN_FILES, false).await;
|
||||||
assert_all(&client, "no_index", INDEXED_DIRECTORIES, false);
|
assert_all(&client, "no_index", INDEXED_DIRECTORIES, false).await;
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_static_hidden() {
|
fn test_static_hidden() {
|
||||||
|
rocket::async_test(async {
|
||||||
let client = Client::new(rocket()).expect("valid rocket");
|
let client = Client::new(rocket()).expect("valid rocket");
|
||||||
assert_all(&client, "dots", REGULAR_FILES, true);
|
assert_all(&client, "dots", REGULAR_FILES, true).await;
|
||||||
assert_all(&client, "dots", HIDDEN_FILES, true);
|
assert_all(&client, "dots", HIDDEN_FILES, true).await;
|
||||||
assert_all(&client, "dots", INDEXED_DIRECTORIES, false);
|
assert_all(&client, "dots", INDEXED_DIRECTORIES, false).await;
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_static_index() {
|
fn test_static_index() {
|
||||||
|
rocket::async_test(async {
|
||||||
let client = Client::new(rocket()).expect("valid rocket");
|
let client = Client::new(rocket()).expect("valid rocket");
|
||||||
assert_all(&client, "index", REGULAR_FILES, true);
|
assert_all(&client, "index", REGULAR_FILES, true).await;
|
||||||
assert_all(&client, "index", HIDDEN_FILES, false);
|
assert_all(&client, "index", HIDDEN_FILES, false).await;
|
||||||
assert_all(&client, "index", INDEXED_DIRECTORIES, true);
|
assert_all(&client, "index", INDEXED_DIRECTORIES, true).await;
|
||||||
|
|
||||||
assert_all(&client, "default", REGULAR_FILES, true);
|
assert_all(&client, "default", REGULAR_FILES, true).await;
|
||||||
assert_all(&client, "default", HIDDEN_FILES, false);
|
assert_all(&client, "default", HIDDEN_FILES, false).await;
|
||||||
assert_all(&client, "default", INDEXED_DIRECTORIES, true);
|
assert_all(&client, "default", INDEXED_DIRECTORIES, true).await;
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_static_all() {
|
fn test_static_all() {
|
||||||
|
rocket::async_test(async {
|
||||||
let client = Client::new(rocket()).expect("valid rocket");
|
let client = Client::new(rocket()).expect("valid rocket");
|
||||||
assert_all(&client, "both", REGULAR_FILES, true);
|
assert_all(&client, "both", REGULAR_FILES, true).await;
|
||||||
assert_all(&client, "both", HIDDEN_FILES, true);
|
assert_all(&client, "both", HIDDEN_FILES, true).await;
|
||||||
assert_all(&client, "both", INDEXED_DIRECTORIES, true);
|
assert_all(&client, "both", INDEXED_DIRECTORIES, true).await;
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -121,6 +131,7 @@ mod static_tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_forwarding() {
|
fn test_forwarding() {
|
||||||
|
rocket::async_test(async {
|
||||||
use rocket::http::RawStr;
|
use rocket::http::RawStr;
|
||||||
use rocket::{get, routes};
|
use rocket::{get, routes};
|
||||||
|
|
||||||
|
@ -135,15 +146,16 @@ mod static_tests {
|
||||||
|
|
||||||
let mut response = client.get("/default/ireallydontexist").dispatch();
|
let mut response = client.get("/default/ireallydontexist").dispatch();
|
||||||
assert_eq!(response.status(), Status::Ok);
|
assert_eq!(response.status(), Status::Ok);
|
||||||
assert_eq!(response.body_string_wait().unwrap(), "ireallydontexist");
|
assert_eq!(response.body_string().await.unwrap(), "ireallydontexist");
|
||||||
|
|
||||||
let mut response = client.get("/default/idont/exist").dispatch();
|
let mut response = client.get("/default/idont/exist").dispatch();
|
||||||
assert_eq!(response.status(), Status::Ok);
|
assert_eq!(response.status(), Status::Ok);
|
||||||
assert_eq!(response.body_string_wait().unwrap(), "idont/exist");
|
assert_eq!(response.body_string().await.unwrap(), "idont/exist");
|
||||||
|
|
||||||
assert_all(&client, "both", REGULAR_FILES, true);
|
assert_all(&client, "both", REGULAR_FILES, true).await;
|
||||||
assert_all(&client, "both", HIDDEN_FILES, true);
|
assert_all(&client, "both", HIDDEN_FILES, true).await;
|
||||||
assert_all(&client, "both", INDEXED_DIRECTORIES, true);
|
assert_all(&client, "both", INDEXED_DIRECTORIES, true).await;
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::rc::Rc;
|
use std::sync::Arc;
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
@ -67,16 +67,16 @@ use crate::local::Client;
|
||||||
/// [`mut_dispatch`]: #method.mut_dispatch
|
/// [`mut_dispatch`]: #method.mut_dispatch
|
||||||
pub struct LocalRequest<'c> {
|
pub struct LocalRequest<'c> {
|
||||||
client: &'c Client,
|
client: &'c Client,
|
||||||
// This pointer exists to access the `Rc<Request>` mutably inside of
|
// This pointer exists to access the `Arc<Request>` mutably inside of
|
||||||
// `LocalRequest`. This is the only place that a `Request` can be accessed
|
// `LocalRequest`. This is the only place that a `Request` can be accessed
|
||||||
// mutably. This is accomplished via the private `request_mut()` method.
|
// mutably. This is accomplished via the private `request_mut()` method.
|
||||||
ptr: *mut Request<'c>,
|
ptr: *mut Request<'c>,
|
||||||
// This `Rc` exists so that we can transfer ownership to the `LocalResponse`
|
// This `Arc` exists so that we can transfer ownership to the `LocalResponse`
|
||||||
// selectively on dispatch. This is necessary because responses may point
|
// selectively on dispatch. This is necessary because responses may point
|
||||||
// into the request, and thus the request and all of its data needs to be
|
// into the request, and thus the request and all of its data needs to be
|
||||||
// alive while the response is accessible.
|
// alive while the response is accessible.
|
||||||
//
|
//
|
||||||
// Because both a `LocalRequest` and a `LocalResponse` can hold an `Rc` to
|
// Because both a `LocalRequest` and a `LocalResponse` can hold an `Arc` to
|
||||||
// the same `Request`, _and_ the `LocalRequest` can mutate the request, we
|
// the same `Request`, _and_ the `LocalRequest` can mutate the request, we
|
||||||
// must ensure that 1) neither `LocalRequest` not `LocalResponse` are `Sync`
|
// must ensure that 1) neither `LocalRequest` not `LocalResponse` are `Sync`
|
||||||
// or `Send` and 2) mutations carried out in `LocalRequest` are _stable_:
|
// or `Send` and 2) mutations carried out in `LocalRequest` are _stable_:
|
||||||
|
@ -85,7 +85,7 @@ pub struct LocalRequest<'c> {
|
||||||
// even if the `Request` is mutated by a `LocalRequest`, those mutations are
|
// even if the `Request` is mutated by a `LocalRequest`, those mutations are
|
||||||
// not observable by `LocalResponse`.
|
// not observable by `LocalResponse`.
|
||||||
//
|
//
|
||||||
// The first is ensured by the embedding of the `Rc` type which is neither
|
// The first is ensured by the embedding of the `Arc` type which is neither
|
||||||
// `Send` nor `Sync`. The second is more difficult to argue. First, observe
|
// `Send` nor `Sync`. The second is more difficult to argue. First, observe
|
||||||
// that any methods of `LocalRequest` that _remove_ values from `Request`
|
// that any methods of `LocalRequest` that _remove_ values from `Request`
|
||||||
// only remove _Copy_ values, in particular, `SocketAddr`. Second, the
|
// only remove _Copy_ values, in particular, `SocketAddr`. Second, the
|
||||||
|
@ -94,7 +94,7 @@ pub struct LocalRequest<'c> {
|
||||||
// `Response`. And finally, observe how all of the data stored in `Request`
|
// `Response`. And finally, observe how all of the data stored in `Request`
|
||||||
// is converted into its owned counterpart before insertion, ensuring stable
|
// is converted into its owned counterpart before insertion, ensuring stable
|
||||||
// addresses. Together, these properties guarantee the second condition.
|
// addresses. Together, these properties guarantee the second condition.
|
||||||
request: Rc<Request<'c>>,
|
request: Arc<Request<'c>>,
|
||||||
data: Vec<u8>,
|
data: Vec<u8>,
|
||||||
uri: Cow<'c, str>,
|
uri: Cow<'c, str>,
|
||||||
}
|
}
|
||||||
|
@ -118,8 +118,8 @@ impl<'c> LocalRequest<'c> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// See the comments on the structure for what's going on here.
|
// See the comments on the structure for what's going on here.
|
||||||
let mut request = Rc::new(request);
|
let mut request = Arc::new(request);
|
||||||
let ptr = Rc::get_mut(&mut request).unwrap() as *mut Request<'_>;
|
let ptr = Arc::get_mut(&mut request).unwrap() as *mut Request<'_>;
|
||||||
LocalRequest { client, ptr, request, uri, data: vec![] }
|
LocalRequest { client, ptr, request, uri, data: vec![] }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,7 +150,7 @@ impl<'c> LocalRequest<'c> {
|
||||||
fn long_lived_request<'a>(&mut self) -> &'a mut Request<'c> {
|
fn long_lived_request<'a>(&mut self) -> &'a mut Request<'c> {
|
||||||
// See the comments in the structure for the argument of correctness.
|
// See the comments in the structure for the argument of correctness.
|
||||||
// Additionally, the caller must ensure that the owned instance of
|
// Additionally, the caller must ensure that the owned instance of
|
||||||
// `Rc<Request>` remains valid as long as the returned reference can be
|
// `Arc<Request>` remains valid as long as the returned reference can be
|
||||||
// accessed.
|
// accessed.
|
||||||
unsafe { &mut *self.ptr }
|
unsafe { &mut *self.ptr }
|
||||||
}
|
}
|
||||||
|
@ -393,7 +393,7 @@ impl<'c> LocalRequest<'c> {
|
||||||
fn _dispatch(
|
fn _dispatch(
|
||||||
client: &'c Client,
|
client: &'c Client,
|
||||||
request: &'c mut Request<'c>,
|
request: &'c mut Request<'c>,
|
||||||
owned_request: Rc<Request<'c>>,
|
owned_request: Arc<Request<'c>>,
|
||||||
uri: &str,
|
uri: &str,
|
||||||
data: Vec<u8>
|
data: Vec<u8>
|
||||||
) -> LocalResponse<'c> {
|
) -> LocalResponse<'c> {
|
||||||
|
@ -454,7 +454,7 @@ impl fmt::Debug for LocalRequest<'_> {
|
||||||
/// when invoking methods, a `LocalResponse` can be treated exactly as if it
|
/// when invoking methods, a `LocalResponse` can be treated exactly as if it
|
||||||
/// were a `Response`.
|
/// were a `Response`.
|
||||||
pub struct LocalResponse<'c> {
|
pub struct LocalResponse<'c> {
|
||||||
_request: Rc<Request<'c>>,
|
_request: Arc<Request<'c>>,
|
||||||
response: Response<'c>,
|
response: Response<'c>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
#![feature(async_await)]
|
||||||
|
|
||||||
extern crate rocket;
|
extern crate rocket;
|
||||||
extern crate rocket_contrib;
|
extern crate rocket_contrib;
|
||||||
|
|
||||||
|
|
|
@ -6,14 +6,14 @@ use rocket::http::Status;
|
||||||
|
|
||||||
use super::rocket;
|
use super::rocket;
|
||||||
|
|
||||||
fn test_query_file<T> (path: &str, file: T, status: Status)
|
async fn test_query_file<T> (path: &str, file: T, status: Status)
|
||||||
where T: Into<Option<&'static str>>
|
where T: Into<Option<&'static str>>
|
||||||
{
|
{
|
||||||
let client = Client::new(rocket()).unwrap();
|
let client = Client::new(rocket()).unwrap();
|
||||||
let mut response = client.get(path).dispatch();
|
let mut response = client.get(path).dispatch();
|
||||||
assert_eq!(response.status(), status);
|
assert_eq!(response.status(), status);
|
||||||
|
|
||||||
let body_data = response.body_bytes_wait();
|
let body_data = response.body_bytes().await;
|
||||||
if let Some(filename) = file.into() {
|
if let Some(filename) = file.into() {
|
||||||
let expected_data = read_file_content(filename);
|
let expected_data = read_file_content(filename);
|
||||||
assert!(body_data.map_or(false, |s| s == expected_data));
|
assert!(body_data.map_or(false, |s| s == expected_data));
|
||||||
|
@ -30,27 +30,35 @@ fn read_file_content(path: &str) -> Vec<u8> {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_index_html() {
|
fn test_index_html() {
|
||||||
test_query_file("/", "static/index.html", Status::Ok);
|
rocket::async_test(async {
|
||||||
test_query_file("/?v=1", "static/index.html", Status::Ok);
|
test_query_file("/", "static/index.html", Status::Ok).await;
|
||||||
test_query_file("/?this=should&be=ignored", "static/index.html", Status::Ok);
|
test_query_file("/?v=1", "static/index.html", Status::Ok).await;
|
||||||
|
test_query_file("/?this=should&be=ignored", "static/index.html", Status::Ok).await;
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_hidden_file() {
|
fn test_hidden_file() {
|
||||||
test_query_file("/hidden/hi.txt", "static/hidden/hi.txt", Status::Ok);
|
rocket::async_test(async {
|
||||||
test_query_file("/hidden/hi.txt?v=1", "static/hidden/hi.txt", Status::Ok);
|
test_query_file("/hidden/hi.txt", "static/hidden/hi.txt", Status::Ok).await;
|
||||||
test_query_file("/hidden/hi.txt?v=1&a=b", "static/hidden/hi.txt", Status::Ok);
|
test_query_file("/hidden/hi.txt?v=1", "static/hidden/hi.txt", Status::Ok).await;
|
||||||
|
test_query_file("/hidden/hi.txt?v=1&a=b", "static/hidden/hi.txt", Status::Ok).await;
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_icon_file() {
|
fn test_icon_file() {
|
||||||
test_query_file("/rocket-icon.jpg", "static/rocket-icon.jpg", Status::Ok);
|
rocket::async_test(async {
|
||||||
test_query_file("/rocket-icon.jpg", "static/rocket-icon.jpg", Status::Ok);
|
test_query_file("/rocket-icon.jpg", "static/rocket-icon.jpg", Status::Ok).await;
|
||||||
|
test_query_file("/rocket-icon.jpg", "static/rocket-icon.jpg", Status::Ok).await;
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_invalid_path() {
|
fn test_invalid_path() {
|
||||||
test_query_file("/thou_shalt_not_exist", None, Status::NotFound);
|
rocket::async_test(async {
|
||||||
test_query_file("/thou/shalt/not/exist", None, Status::NotFound);
|
test_query_file("/thou_shalt_not_exist", None, Status::NotFound).await;
|
||||||
test_query_file("/thou/shalt/not/exist?a=b&c=d", None, Status::NotFound);
|
test_query_file("/thou/shalt/not/exist", None, Status::NotFound).await;
|
||||||
|
test_query_file("/thou/shalt/not/exist?a=b&c=d", None, Status::NotFound).await;
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,8 +67,7 @@ if [ "$1" = "--contrib" ]; then
|
||||||
msgpack
|
msgpack
|
||||||
tera_templates
|
tera_templates
|
||||||
handlebars_templates
|
handlebars_templates
|
||||||
# TODO.async: serve needs tests to use tokio runtime, blocked on #1071
|
serve
|
||||||
# serve
|
|
||||||
helmet
|
helmet
|
||||||
diesel_postgres_pool
|
diesel_postgres_pool
|
||||||
diesel_sqlite_pool
|
diesel_sqlite_pool
|
||||||
|
@ -87,9 +86,8 @@ if [ "$1" = "--contrib" ]; then
|
||||||
|
|
||||||
pushd "${CONTRIB_LIB_ROOT}" > /dev/null 2>&1
|
pushd "${CONTRIB_LIB_ROOT}" > /dev/null 2>&1
|
||||||
|
|
||||||
# TODO.async: default_features includes `serve`
|
echo ":: Building and testing contrib [default]..."
|
||||||
# echo ":: Building and testing contrib [default]..."
|
CARGO_INCREMENTAL=0 cargo test
|
||||||
# CARGO_INCREMENTAL=0 cargo test
|
|
||||||
|
|
||||||
for feature in "${FEATURES[@]}"; do
|
for feature in "${FEATURES[@]}"; do
|
||||||
echo ":: Building and testing contrib [${feature}]..."
|
echo ":: Building and testing contrib [${feature}]..."
|
||||||
|
|
Loading…
Reference in New Issue