Fix 'static_files' and 'serve' tests.

This commit is contained in:
Jeb Rosen 2019-08-14 11:29:55 -07:00 committed by Sergio Benitez
parent b780f9d8e0
commit 8c8598b4fd
5 changed files with 89 additions and 69 deletions

View File

@ -45,7 +45,7 @@ mod static_tests {
"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 mut response = client.get(full_path).dispatch();
if exists {
@ -59,50 +59,60 @@ mod static_tests {
let mut file = File::open(path).expect("open file");
let mut expected_contents = String::new();
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 {
assert_eq!(response.status(), Status::NotFound);
}
}
fn assert_all(client: &Client, prefix: &str, paths: &[&str], exist: bool) {
paths.iter().for_each(|path| assert_file(client, prefix, path, exist))
async fn assert_all(client: &Client, prefix: &str, paths: &[&str], exist: bool) {
for path in paths.iter() {
assert_file(client, prefix, path, exist).await;
}
}
#[test]
fn test_static_no_index() {
rocket::async_test(async {
let client = Client::new(rocket()).expect("valid rocket");
assert_all(&client, "no_index", REGULAR_FILES, true);
assert_all(&client, "no_index", HIDDEN_FILES, false);
assert_all(&client, "no_index", INDEXED_DIRECTORIES, false);
assert_all(&client, "no_index", REGULAR_FILES, true).await;
assert_all(&client, "no_index", HIDDEN_FILES, false).await;
assert_all(&client, "no_index", INDEXED_DIRECTORIES, false).await;
})
}
#[test]
fn test_static_hidden() {
rocket::async_test(async {
let client = Client::new(rocket()).expect("valid rocket");
assert_all(&client, "dots", REGULAR_FILES, true);
assert_all(&client, "dots", HIDDEN_FILES, true);
assert_all(&client, "dots", INDEXED_DIRECTORIES, false);
assert_all(&client, "dots", REGULAR_FILES, true).await;
assert_all(&client, "dots", HIDDEN_FILES, true).await;
assert_all(&client, "dots", INDEXED_DIRECTORIES, false).await;
})
}
#[test]
fn test_static_index() {
rocket::async_test(async {
let client = Client::new(rocket()).expect("valid rocket");
assert_all(&client, "index", REGULAR_FILES, true);
assert_all(&client, "index", HIDDEN_FILES, false);
assert_all(&client, "index", INDEXED_DIRECTORIES, true);
assert_all(&client, "index", REGULAR_FILES, true).await;
assert_all(&client, "index", HIDDEN_FILES, false).await;
assert_all(&client, "index", INDEXED_DIRECTORIES, true).await;
assert_all(&client, "default", REGULAR_FILES, true);
assert_all(&client, "default", HIDDEN_FILES, false);
assert_all(&client, "default", INDEXED_DIRECTORIES, true);
assert_all(&client, "default", REGULAR_FILES, true).await;
assert_all(&client, "default", HIDDEN_FILES, false).await;
assert_all(&client, "default", INDEXED_DIRECTORIES, true).await;
})
}
#[test]
fn test_static_all() {
rocket::async_test(async {
let client = Client::new(rocket()).expect("valid rocket");
assert_all(&client, "both", REGULAR_FILES, true);
assert_all(&client, "both", HIDDEN_FILES, true);
assert_all(&client, "both", INDEXED_DIRECTORIES, true);
assert_all(&client, "both", REGULAR_FILES, true).await;
assert_all(&client, "both", HIDDEN_FILES, true).await;
assert_all(&client, "both", INDEXED_DIRECTORIES, true).await;
})
}
#[test]
@ -121,6 +131,7 @@ mod static_tests {
#[test]
fn test_forwarding() {
rocket::async_test(async {
use rocket::http::RawStr;
use rocket::{get, routes};
@ -135,15 +146,16 @@ mod static_tests {
let mut response = client.get("/default/ireallydontexist").dispatch();
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();
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", HIDDEN_FILES, true);
assert_all(&client, "both", INDEXED_DIRECTORIES, true);
assert_all(&client, "both", REGULAR_FILES, true).await;
assert_all(&client, "both", HIDDEN_FILES, true).await;
assert_all(&client, "both", INDEXED_DIRECTORIES, true).await;
})
}
#[test]

View File

@ -1,5 +1,5 @@
use std::fmt;
use std::rc::Rc;
use std::sync::Arc;
use std::net::SocketAddr;
use std::ops::{Deref, DerefMut};
use std::borrow::Cow;
@ -67,16 +67,16 @@ use crate::local::Client;
/// [`mut_dispatch`]: #method.mut_dispatch
pub struct LocalRequest<'c> {
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
// mutably. This is accomplished via the private `request_mut()` method.
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
// into the request, and thus the request and all of its data needs to be
// 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
// must ensure that 1) neither `LocalRequest` not `LocalResponse` are `Sync`
// 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
// 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
// that any methods of `LocalRequest` that _remove_ values from `Request`
// 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`
// is converted into its owned counterpart before insertion, ensuring stable
// addresses. Together, these properties guarantee the second condition.
request: Rc<Request<'c>>,
request: Arc<Request<'c>>,
data: Vec<u8>,
uri: Cow<'c, str>,
}
@ -118,8 +118,8 @@ impl<'c> LocalRequest<'c> {
}
// See the comments on the structure for what's going on here.
let mut request = Rc::new(request);
let ptr = Rc::get_mut(&mut request).unwrap() as *mut Request<'_>;
let mut request = Arc::new(request);
let ptr = Arc::get_mut(&mut request).unwrap() as *mut Request<'_>;
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> {
// See the comments in the structure for the argument of correctness.
// 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.
unsafe { &mut *self.ptr }
}
@ -393,7 +393,7 @@ impl<'c> LocalRequest<'c> {
fn _dispatch(
client: &'c Client,
request: &'c mut Request<'c>,
owned_request: Rc<Request<'c>>,
owned_request: Arc<Request<'c>>,
uri: &str,
data: Vec<u8>
) -> LocalResponse<'c> {
@ -454,7 +454,7 @@ impl fmt::Debug for LocalRequest<'_> {
/// when invoking methods, a `LocalResponse` can be treated exactly as if it
/// were a `Response`.
pub struct LocalResponse<'c> {
_request: Rc<Request<'c>>,
_request: Arc<Request<'c>>,
response: Response<'c>,
}

View File

@ -1,3 +1,5 @@
#![feature(async_await)]
extern crate rocket;
extern crate rocket_contrib;

View File

@ -6,14 +6,14 @@ use rocket::http::Status;
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>>
{
let client = Client::new(rocket()).unwrap();
let mut response = client.get(path).dispatch();
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() {
let expected_data = read_file_content(filename);
assert!(body_data.map_or(false, |s| s == expected_data));
@ -30,27 +30,35 @@ fn read_file_content(path: &str) -> Vec<u8> {
#[test]
fn test_index_html() {
test_query_file("/", "static/index.html", Status::Ok);
test_query_file("/?v=1", "static/index.html", Status::Ok);
test_query_file("/?this=should&be=ignored", "static/index.html", Status::Ok);
rocket::async_test(async {
test_query_file("/", "static/index.html", Status::Ok).await;
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]
fn test_hidden_file() {
test_query_file("/hidden/hi.txt", "static/hidden/hi.txt", Status::Ok);
test_query_file("/hidden/hi.txt?v=1", "static/hidden/hi.txt", Status::Ok);
test_query_file("/hidden/hi.txt?v=1&a=b", "static/hidden/hi.txt", Status::Ok);
rocket::async_test(async {
test_query_file("/hidden/hi.txt", "static/hidden/hi.txt", Status::Ok).await;
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]
fn test_icon_file() {
test_query_file("/rocket-icon.jpg", "static/rocket-icon.jpg", Status::Ok);
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).await;
test_query_file("/rocket-icon.jpg", "static/rocket-icon.jpg", Status::Ok).await;
})
}
#[test]
fn test_invalid_path() {
test_query_file("/thou_shalt_not_exist", None, Status::NotFound);
test_query_file("/thou/shalt/not/exist", None, Status::NotFound);
test_query_file("/thou/shalt/not/exist?a=b&c=d", None, Status::NotFound);
rocket::async_test(async {
test_query_file("/thou_shalt_not_exist", None, Status::NotFound).await;
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;
})
}

View File

@ -67,8 +67,7 @@ if [ "$1" = "--contrib" ]; then
msgpack
tera_templates
handlebars_templates
# TODO.async: serve needs tests to use tokio runtime, blocked on #1071
# serve
serve
helmet
diesel_postgres_pool
diesel_sqlite_pool
@ -87,9 +86,8 @@ if [ "$1" = "--contrib" ]; then
pushd "${CONTRIB_LIB_ROOT}" > /dev/null 2>&1
# TODO.async: default_features includes `serve`
# echo ":: Building and testing contrib [default]..."
# CARGO_INCREMENTAL=0 cargo test
echo ":: Building and testing contrib [default]..."
CARGO_INCREMENTAL=0 cargo test
for feature in "${FEATURES[@]}"; do
echo ":: Building and testing contrib [${feature}]..."