Add internal macro to make tests of nest easier to write (#1694)

This commit is contained in:
David Pedersen 2023-01-14 15:12:01 +01:00 committed by GitHub
parent 607a20dfac
commit 1be25d9496
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
31 changed files with 230 additions and 159 deletions

View file

@ -11,6 +11,10 @@ readme = "README.md"
repository = "https://github.com/tokio-rs/axum" repository = "https://github.com/tokio-rs/axum"
version = "0.3.1" # remember to also bump the version that axum and axum-extra depends on version = "0.3.1" # remember to also bump the version that axum and axum-extra depends on
[features]
default = []
__private = ["syn/visit-mut"]
[lib] [lib]
proc-macro = true proc-macro = true

View file

@ -0,0 +1,45 @@
use proc_macro2::TokenStream;
use quote::{format_ident, quote};
use syn::{parse::Parse, parse_quote, visit_mut::VisitMut, ItemFn};
pub(crate) fn expand(_attr: Attrs, mut item_fn: ItemFn) -> TokenStream {
item_fn.attrs.push(parse_quote!(#[tokio::test]));
let nest_service_fn = replace_nest_with_nest_service(item_fn.clone());
quote! {
#item_fn
#nest_service_fn
}
}
pub(crate) struct Attrs;
impl Parse for Attrs {
fn parse(_input: syn::parse::ParseStream) -> syn::Result<Self> {
Ok(Self)
}
}
fn replace_nest_with_nest_service(mut item_fn: ItemFn) -> Option<ItemFn> {
item_fn.sig.ident = format_ident!("{}_with_nest_service", item_fn.sig.ident);
let mut visitor = NestToNestService::default();
syn::visit_mut::visit_item_fn_mut(&mut visitor, &mut item_fn);
(visitor.count > 0).then(|| item_fn)
}
#[derive(Default)]
struct NestToNestService {
count: usize,
}
impl VisitMut for NestToNestService {
fn visit_expr_method_call_mut(&mut self, i: &mut syn::ExprMethodCall) {
if i.method == "nest" && i.args.len() == 2 {
i.method = parse_quote!(nest_service);
self.count += 1;
}
}
}

View file

@ -48,6 +48,8 @@ use quote::{quote, ToTokens};
use syn::{parse::Parse, Type}; use syn::{parse::Parse, Type};
mod attr_parsing; mod attr_parsing;
#[cfg(feature = "__private")]
mod axum_test;
mod debug_handler; mod debug_handler;
mod from_ref; mod from_ref;
mod from_request; mod from_request;
@ -555,6 +557,22 @@ pub fn debug_handler(_attr: TokenStream, input: TokenStream) -> TokenStream {
return expand_attr_with(_attr, input, debug_handler::expand); return expand_attr_with(_attr, input, debug_handler::expand);
} }
/// Private API: Do no use this!
///
/// Attribute macro to be placed on test functions that'll generate two functions:
///
/// 1. One identical to the function it was placed on.
/// 2. One where calls to `Router::nest` has been replaced with `Router::nest_service`
///
/// This makes it easy to that `nest` and `nest_service` behaves in the same way, without having to
/// manually write identical tests for both methods.
#[cfg(feature = "__private")]
#[proc_macro_attribute]
#[doc(hidden)]
pub fn __private_axum_test(_attr: TokenStream, input: TokenStream) -> TokenStream {
expand_attr_with(_attr, input, axum_test::expand)
}
/// Derive an implementation of [`axum_extra::routing::TypedPath`]. /// Derive an implementation of [`axum_extra::routing::TypedPath`].
/// ///
/// See that trait for more details. /// See that trait for more details.

View file

@ -68,6 +68,7 @@ rustversion = "1.0.9"
[dev-dependencies] [dev-dependencies]
anyhow = "1.0" anyhow = "1.0"
axum-macros = { path = "../axum-macros", version = "0.3.1", features = ["__private"] }
futures = "0.3" futures = "0.3"
quickcheck = "1.0" quickcheck = "1.0"
quickcheck_macros = "1.0" quickcheck_macros = "1.0"

View file

@ -148,7 +148,7 @@ mod tests {
use crate::{routing::get, Router, Server}; use crate::{routing::get, Router, Server};
use std::net::{SocketAddr, TcpListener}; use std::net::{SocketAddr, TcpListener};
#[tokio::test] #[crate::test]
async fn socket_addr() { async fn socket_addr() {
async fn handler(ConnectInfo(addr): ConnectInfo<SocketAddr>) -> String { async fn handler(ConnectInfo(addr): ConnectInfo<SocketAddr>) -> String {
format!("{}", addr) format!("{}", addr)
@ -175,7 +175,7 @@ mod tests {
assert!(body.starts_with("127.0.0.1:")); assert!(body.starts_with("127.0.0.1:"));
} }
#[tokio::test] #[crate::test]
async fn custom() { async fn custom() {
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
struct MyConnectInfo { struct MyConnectInfo {

View file

@ -90,7 +90,7 @@ mod tests {
TestClient::new(Router::new().route("/", get(host_as_body))) TestClient::new(Router::new().route("/", get(host_as_body)))
} }
#[tokio::test] #[crate::test]
async fn host_header() { async fn host_header() {
let original_host = "some-domain:123"; let original_host = "some-domain:123";
let host = test_client() let host = test_client()
@ -103,7 +103,7 @@ mod tests {
assert_eq!(host, original_host); assert_eq!(host, original_host);
} }
#[tokio::test] #[crate::test]
async fn x_forwarded_host_header() { async fn x_forwarded_host_header() {
let original_host = "some-domain:456"; let original_host = "some-domain:456";
let host = test_client() let host = test_client()
@ -116,7 +116,7 @@ mod tests {
assert_eq!(host, original_host); assert_eq!(host, original_host);
} }
#[tokio::test] #[crate::test]
async fn x_forwarded_host_precedence_over_host_header() { async fn x_forwarded_host_precedence_over_host_header() {
let x_forwarded_host_header = "some-domain:456"; let x_forwarded_host_header = "some-domain:456";
let host_header = "some-domain:123"; let host_header = "some-domain:123";
@ -131,7 +131,7 @@ mod tests {
assert_eq!(host, x_forwarded_host_header); assert_eq!(host, x_forwarded_host_header);
} }
#[tokio::test] #[crate::test]
async fn uri_host() { async fn uri_host() {
let host = test_client().get("/").send().await.text().await; let host = test_client().get("/").send().await.text().await;
assert!(host.contains("127.0.0.1")); assert!(host.contains("127.0.0.1"));

View file

@ -177,7 +177,7 @@ mod tests {
}; };
use http::{Request, StatusCode}; use http::{Request, StatusCode};
#[tokio::test] #[crate::test]
async fn extracting_on_handler() { async fn extracting_on_handler() {
let app = Router::new().route( let app = Router::new().route(
"/:a", "/:a",
@ -190,7 +190,7 @@ mod tests {
assert_eq!(res.text().await, "/:a"); assert_eq!(res.text().await, "/:a");
} }
#[tokio::test] #[crate::test]
async fn extracting_on_handler_in_nested_router() { async fn extracting_on_handler_in_nested_router() {
let app = Router::new().nest( let app = Router::new().nest(
"/:a", "/:a",
@ -206,7 +206,7 @@ mod tests {
assert_eq!(res.text().await, "/:a/:b"); assert_eq!(res.text().await, "/:a/:b");
} }
#[tokio::test] #[crate::test]
async fn extracting_on_handler_in_deeply_nested_router() { async fn extracting_on_handler_in_deeply_nested_router() {
let app = Router::new().nest( let app = Router::new().nest(
"/:a", "/:a",
@ -225,7 +225,7 @@ mod tests {
assert_eq!(res.text().await, "/:a/:b/:c"); assert_eq!(res.text().await, "/:a/:b/:c");
} }
#[tokio::test] #[crate::test]
async fn cannot_extract_nested_matched_path_in_middleware() { async fn cannot_extract_nested_matched_path_in_middleware() {
async fn extract_matched_path<B>( async fn extract_matched_path<B>(
matched_path: Option<MatchedPath>, matched_path: Option<MatchedPath>,
@ -245,7 +245,7 @@ mod tests {
assert_eq!(res.status(), StatusCode::OK); assert_eq!(res.status(), StatusCode::OK);
} }
#[tokio::test] #[crate::test]
async fn cannot_extract_nested_matched_path_in_middleware_via_extension() { async fn cannot_extract_nested_matched_path_in_middleware_via_extension() {
async fn assert_no_matched_path<B>(req: Request<B>) -> Request<B> { async fn assert_no_matched_path<B>(req: Request<B>) -> Request<B> {
assert!(req.extensions().get::<MatchedPath>().is_none()); assert!(req.extensions().get::<MatchedPath>().is_none());
@ -262,7 +262,7 @@ mod tests {
assert_eq!(res.status(), StatusCode::OK); assert_eq!(res.status(), StatusCode::OK);
} }
#[tokio::test] #[crate::test]
async fn can_extract_nested_matched_path_in_middleware_on_nested_router() { async fn can_extract_nested_matched_path_in_middleware_on_nested_router() {
async fn extract_matched_path<B>(matched_path: MatchedPath, req: Request<B>) -> Request<B> { async fn extract_matched_path<B>(matched_path: MatchedPath, req: Request<B>) -> Request<B> {
assert_eq!(matched_path.as_str(), "/:a/:b"); assert_eq!(matched_path.as_str(), "/:a/:b");
@ -282,7 +282,7 @@ mod tests {
assert_eq!(res.status(), StatusCode::OK); assert_eq!(res.status(), StatusCode::OK);
} }
#[tokio::test] #[crate::test]
async fn can_extract_nested_matched_path_in_middleware_on_nested_router_via_extension() { async fn can_extract_nested_matched_path_in_middleware_on_nested_router_via_extension() {
async fn extract_matched_path<B>(req: Request<B>) -> Request<B> { async fn extract_matched_path<B>(req: Request<B>) -> Request<B> {
let matched_path = req.extensions().get::<MatchedPath>().unwrap(); let matched_path = req.extensions().get::<MatchedPath>().unwrap();
@ -303,7 +303,7 @@ mod tests {
assert_eq!(res.status(), StatusCode::OK); assert_eq!(res.status(), StatusCode::OK);
} }
#[tokio::test] #[crate::test]
async fn extracting_on_nested_handler() { async fn extracting_on_nested_handler() {
async fn handler(path: Option<MatchedPath>) { async fn handler(path: Option<MatchedPath>) {
assert!(path.is_none()); assert!(path.is_none());

View file

@ -102,7 +102,7 @@ pub(super) fn has_content_type(headers: &HeaderMap, expected_content_type: &mime
mod tests { mod tests {
use crate::{routing::get, test_helpers::*, Router}; use crate::{routing::get, test_helpers::*, Router};
#[tokio::test] #[crate::test]
async fn consume_body() { async fn consume_body() {
let app = Router::new().route("/", get(|body: String| async { body })); let app = Router::new().route("/", get(|body: String| async { body }));

View file

@ -250,7 +250,7 @@ mod tests {
use super::*; use super::*;
use crate::{body::Body, response::IntoResponse, routing::post, test_helpers::*, Router}; use crate::{body::Body, response::IntoResponse, routing::post, test_helpers::*, Router};
#[tokio::test] #[crate::test]
async fn content_type_with_encoding() { async fn content_type_with_encoding() {
const BYTES: &[u8] = "<!doctype html><title>🦀</title>".as_bytes(); const BYTES: &[u8] = "<!doctype html><title>🦀</title>".as_bytes();
const FILE_NAME: &str = "index.html"; const FILE_NAME: &str = "index.html";

View file

@ -440,7 +440,7 @@ mod tests {
use serde::Deserialize; use serde::Deserialize;
use std::collections::HashMap; use std::collections::HashMap;
#[tokio::test] #[crate::test]
async fn extracting_url_params() { async fn extracting_url_params() {
let app = Router::new().route( let app = Router::new().route(
"/users/:id", "/users/:id",
@ -461,7 +461,7 @@ mod tests {
assert_eq!(res.status(), StatusCode::OK); assert_eq!(res.status(), StatusCode::OK);
} }
#[tokio::test] #[crate::test]
async fn extracting_url_params_multiple_times() { async fn extracting_url_params_multiple_times() {
let app = Router::new().route("/users/:id", get(|_: Path<i32>, _: Path<String>| async {})); let app = Router::new().route("/users/:id", get(|_: Path<i32>, _: Path<String>| async {}));
@ -471,7 +471,7 @@ mod tests {
assert_eq!(res.status(), StatusCode::OK); assert_eq!(res.status(), StatusCode::OK);
} }
#[tokio::test] #[crate::test]
async fn percent_decoding() { async fn percent_decoding() {
let app = Router::new().route( let app = Router::new().route(
"/:key", "/:key",
@ -485,7 +485,7 @@ mod tests {
assert_eq!(res.text().await, "one two"); assert_eq!(res.text().await, "one two");
} }
#[tokio::test] #[crate::test]
async fn supports_128_bit_numbers() { async fn supports_128_bit_numbers() {
let app = Router::new() let app = Router::new()
.route( .route(
@ -506,7 +506,7 @@ mod tests {
assert_eq!(res.text().await, "123"); assert_eq!(res.text().await, "123");
} }
#[tokio::test] #[crate::test]
async fn wildcard() { async fn wildcard() {
let app = Router::new() let app = Router::new()
.route( .route(
@ -529,7 +529,7 @@ mod tests {
assert_eq!(res.text().await, "baz/qux"); assert_eq!(res.text().await, "baz/qux");
} }
#[tokio::test] #[crate::test]
async fn captures_dont_match_empty_segments() { async fn captures_dont_match_empty_segments() {
let app = Router::new().route("/:key", get(|| async {})); let app = Router::new().route("/:key", get(|| async {}));
@ -542,7 +542,7 @@ mod tests {
assert_eq!(res.status(), StatusCode::OK); assert_eq!(res.status(), StatusCode::OK);
} }
#[tokio::test] #[crate::test]
async fn str_reference_deserialize() { async fn str_reference_deserialize() {
struct Param(String); struct Param(String);
impl<'de> serde::Deserialize<'de> for Param { impl<'de> serde::Deserialize<'de> for Param {
@ -567,7 +567,7 @@ mod tests {
assert_eq!(res.text().await, "foo bar"); assert_eq!(res.text().await, "foo bar");
} }
#[tokio::test] #[crate::test]
async fn two_path_extractors() { async fn two_path_extractors() {
let app = Router::new().route("/:a/:b", get(|_: Path<String>, _: Path<String>| async {})); let app = Router::new().route("/:a/:b", get(|_: Path<String>, _: Path<String>| async {}));
@ -582,7 +582,7 @@ mod tests {
); );
} }
#[tokio::test] #[crate::test]
async fn deserialize_into_vec_of_tuples() { async fn deserialize_into_vec_of_tuples() {
let app = Router::new().route( let app = Router::new().route(
"/:a/:b", "/:a/:b",
@ -603,7 +603,7 @@ mod tests {
assert_eq!(res.status(), StatusCode::OK); assert_eq!(res.status(), StatusCode::OK);
} }
#[tokio::test] #[crate::test]
async fn type_that_uses_deserialize_any() { async fn type_that_uses_deserialize_any() {
use time::Date; use time::Date;
@ -694,7 +694,7 @@ mod tests {
assert_eq!(res.text().await, "struct: 2023-01-01 2023-01-02 2023-01-03"); assert_eq!(res.text().await, "struct: 2023-01-01 2023-01-02 2023-01-03");
} }
#[tokio::test] #[crate::test]
async fn wrong_number_of_parameters_json() { async fn wrong_number_of_parameters_json() {
use serde_json::Value; use serde_json::Value;

View file

@ -91,7 +91,7 @@ mod tests {
assert_eq!(Query::<T>::from_request(req, &()).await.unwrap().0, value); assert_eq!(Query::<T>::from_request(req, &()).await.unwrap().0, value);
} }
#[tokio::test] #[crate::test]
async fn test_query() { async fn test_query() {
#[derive(Debug, PartialEq, Deserialize)] #[derive(Debug, PartialEq, Deserialize)]
struct Pagination { struct Pagination {
@ -127,7 +127,7 @@ mod tests {
.await; .await;
} }
#[tokio::test] #[crate::test]
async fn correct_rejection_status_code() { async fn correct_rejection_status_code() {
#[derive(Deserialize)] #[derive(Deserialize)]
#[allow(dead_code)] #[allow(dead_code)]

View file

@ -92,21 +92,21 @@ mod tests {
assert_eq!(RawForm::from_request(req, &()).await.unwrap().0, body); assert_eq!(RawForm::from_request(req, &()).await.unwrap().0, body);
} }
#[tokio::test] #[crate::test]
async fn test_from_query() { async fn test_from_query() {
check_query("http://example.com/test", b"").await; check_query("http://example.com/test", b"").await;
check_query("http://example.com/test?page=0&size=10", b"page=0&size=10").await; check_query("http://example.com/test?page=0&size=10", b"page=0&size=10").await;
} }
#[tokio::test] #[crate::test]
async fn test_from_body() { async fn test_from_body() {
check_body(b"").await; check_body(b"").await;
check_body(b"username=user&password=secure%20password").await; check_body(b"username=user&password=secure%20password").await;
} }
#[tokio::test] #[crate::test]
async fn test_incorrect_content_type() { async fn test_incorrect_content_type() {
let req = Request::post("http://example.com/test") let req = Request::post("http://example.com/test")
.body(Full::<Bytes>::from(Bytes::from("page=0&size=10"))) .body(Full::<Bytes>::from(Bytes::from("page=0&size=10")))

View file

@ -226,7 +226,7 @@ mod tests {
use crate::{extract::Extension, routing::get, test_helpers::*, Router}; use crate::{extract::Extension, routing::get, test_helpers::*, Router};
use http::{Method, StatusCode}; use http::{Method, StatusCode};
#[tokio::test] #[crate::test]
async fn extract_request_parts() { async fn extract_request_parts() {
#[derive(Clone)] #[derive(Clone)]
struct Ext; struct Ext;

View file

@ -814,7 +814,7 @@ mod tests {
use http::{Request, Version}; use http::{Request, Version};
use tower::ServiceExt; use tower::ServiceExt;
#[tokio::test] #[crate::test]
async fn rejects_http_1_0_requests() { async fn rejects_http_1_0_requests() {
let svc = get(|ws: Result<WebSocketUpgrade, WebSocketUpgradeRejection>| { let svc = get(|ws: Result<WebSocketUpgrade, WebSocketUpgradeRejection>| {
let rejection = ws.unwrap_err(); let rejection = ws.unwrap_err();

View file

@ -149,7 +149,7 @@ mod tests {
assert_eq!(Form::<T>::from_request(req, &()).await.unwrap().0, value); assert_eq!(Form::<T>::from_request(req, &()).await.unwrap().0, value);
} }
#[tokio::test] #[crate::test]
async fn test_form_query() { async fn test_form_query() {
check_query( check_query(
"http://example.com/test", "http://example.com/test",
@ -179,7 +179,7 @@ mod tests {
.await; .await;
} }
#[tokio::test] #[crate::test]
async fn test_form_body() { async fn test_form_body() {
check_body(Pagination { check_body(Pagination {
size: None, size: None,
@ -200,7 +200,7 @@ mod tests {
.await; .await;
} }
#[tokio::test] #[crate::test]
async fn test_incorrect_content_type() { async fn test_incorrect_content_type() {
let req = Request::builder() let req = Request::builder()
.uri("http://example.com/test") .uri("http://example.com/test")

View file

@ -352,7 +352,7 @@ mod tests {
timeout::TimeoutLayer, timeout::TimeoutLayer,
}; };
#[tokio::test] #[crate::test]
async fn handler_into_service() { async fn handler_into_service() {
async fn handle(body: String) -> impl IntoResponse { async fn handle(body: String) -> impl IntoResponse {
format!("you said: {}", body) format!("you said: {}", body)
@ -365,7 +365,7 @@ mod tests {
assert_eq!(res.text().await, "you said: hi there!"); assert_eq!(res.text().await, "you said: hi there!");
} }
#[tokio::test] #[crate::test]
async fn with_layer_that_changes_request_body_and_state() { async fn with_layer_that_changes_request_body_and_state() {
async fn handle(State(state): State<&'static str>) -> &'static str { async fn handle(State(state): State<&'static str>) -> &'static str {
state state

View file

@ -226,7 +226,7 @@ mod tests {
use serde::Deserialize; use serde::Deserialize;
use serde_json::{json, Value}; use serde_json::{json, Value};
#[tokio::test] #[crate::test]
async fn deserialize_body() { async fn deserialize_body() {
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize)]
struct Input { struct Input {
@ -242,7 +242,7 @@ mod tests {
assert_eq!(body, "bar"); assert_eq!(body, "bar");
} }
#[tokio::test] #[crate::test]
async fn consume_body_to_json_requires_json_content_type() { async fn consume_body_to_json_requires_json_content_type() {
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize)]
struct Input { struct Input {
@ -259,7 +259,7 @@ mod tests {
assert_eq!(status, StatusCode::UNSUPPORTED_MEDIA_TYPE); assert_eq!(status, StatusCode::UNSUPPORTED_MEDIA_TYPE);
} }
#[tokio::test] #[crate::test]
async fn json_content_types() { async fn json_content_types() {
async fn valid_json_content_type(content_type: &str) -> bool { async fn valid_json_content_type(content_type: &str) -> bool {
println!("testing {:?}", content_type); println!("testing {:?}", content_type);
@ -283,7 +283,7 @@ mod tests {
assert!(!valid_json_content_type("text/json").await); assert!(!valid_json_content_type("text/json").await);
} }
#[tokio::test] #[crate::test]
async fn invalid_json_syntax() { async fn invalid_json_syntax() {
let app = Router::new().route("/", post(|_: Json<serde_json::Value>| async {})); let app = Router::new().route("/", post(|_: Json<serde_json::Value>| async {}));
@ -314,7 +314,7 @@ mod tests {
y: i32, y: i32,
} }
#[tokio::test] #[crate::test]
async fn invalid_json_data() { async fn invalid_json_data() {
let app = Router::new().route("/", post(|_: Json<Foo>| async {})); let app = Router::new().route("/", post(|_: Json<Foo>| async {}));

View file

@ -493,3 +493,6 @@ pub use axum_core::{BoxError, Error, RequestExt, RequestPartsExt};
pub use axum_macros::debug_handler; pub use axum_macros::debug_handler;
pub use self::service_ext::ServiceExt; pub use self::service_ext::ServiceExt;
#[cfg(test)]
use axum_macros::__private_axum_test as test;

View file

@ -309,7 +309,7 @@ mod tests {
use http::{header, request::Parts, StatusCode}; use http::{header, request::Parts, StatusCode};
use tower_http::limit::RequestBodyLimitLayer; use tower_http::limit::RequestBodyLimitLayer;
#[tokio::test] #[crate::test]
async fn test_from_extractor() { async fn test_from_extractor() {
#[derive(Clone)] #[derive(Clone)]
struct Secret(&'static str); struct Secret(&'static str);

View file

@ -372,7 +372,7 @@ mod tests {
use http::{HeaderMap, StatusCode}; use http::{HeaderMap, StatusCode};
use tower::ServiceExt; use tower::ServiceExt;
#[tokio::test] #[crate::test]
async fn basic() { async fn basic() {
async fn insert_header<B>(mut req: Request<B>, next: Next<B>) -> impl IntoResponse { async fn insert_header<B>(mut req: Request<B>, next: Next<B>) -> impl IntoResponse {
req.headers_mut() req.headers_mut()

View file

@ -385,7 +385,7 @@ mod tests {
use crate::{routing::get, test_helpers::TestClient, Router}; use crate::{routing::get, test_helpers::TestClient, Router};
use http::{HeaderMap, StatusCode}; use http::{HeaderMap, StatusCode};
#[tokio::test] #[crate::test]
async fn works() { async fn works() {
async fn add_header<B>(mut req: Request<B>) -> Request<B> { async fn add_header<B>(mut req: Request<B>) -> Request<B> {
req.headers_mut().insert("x-foo", "foo".parse().unwrap()); req.headers_mut().insert("x-foo", "foo".parse().unwrap());
@ -410,7 +410,7 @@ mod tests {
assert_eq!(res.text().await, "foo"); assert_eq!(res.text().await, "foo");
} }
#[tokio::test] #[crate::test]
async fn works_for_short_circutting() { async fn works_for_short_circutting() {
async fn add_header<B>(_req: Request<B>) -> Result<Request<B>, (StatusCode, &'static str)> { async fn add_header<B>(_req: Request<B>) -> Result<Request<B>, (StatusCode, &'static str)> {
Err((StatusCode::INTERNAL_SERVER_ERROR, "something went wrong")) Err((StatusCode::INTERNAL_SERVER_ERROR, "something went wrong"))

View file

@ -346,7 +346,7 @@ mod tests {
use super::*; use super::*;
use crate::{test_helpers::TestClient, Router}; use crate::{test_helpers::TestClient, Router};
#[tokio::test] #[crate::test]
async fn works() { async fn works() {
async fn add_header<B>(mut res: Response<B>) -> Response<B> { async fn add_header<B>(mut res: Response<B>) -> Response<B> {
res.headers_mut().insert("x-foo", "foo".parse().unwrap()); res.headers_mut().insert("x-foo", "foo".parse().unwrap());

View file

@ -508,7 +508,7 @@ mod tests {
assert_eq!(&*leading_space.finalize(), b"data: foobar\n\n"); assert_eq!(&*leading_space.finalize(), b"data: foobar\n\n");
} }
#[tokio::test] #[crate::test]
async fn basic() { async fn basic() {
let app = Router::new().route( let app = Router::new().route(
"/", "/",

View file

@ -1280,7 +1280,7 @@ mod tests {
use tower::{timeout::TimeoutLayer, Service, ServiceBuilder, ServiceExt}; use tower::{timeout::TimeoutLayer, Service, ServiceBuilder, ServiceExt};
use tower_http::{auth::RequireAuthorizationLayer, services::fs::ServeDir}; use tower_http::{auth::RequireAuthorizationLayer, services::fs::ServeDir};
#[tokio::test] #[crate::test]
async fn method_not_allowed_by_default() { async fn method_not_allowed_by_default() {
let mut svc = MethodRouter::new(); let mut svc = MethodRouter::new();
let (status, _, body) = call(Method::GET, &mut svc).await; let (status, _, body) = call(Method::GET, &mut svc).await;
@ -1288,7 +1288,7 @@ mod tests {
assert!(body.is_empty()); assert!(body.is_empty());
} }
#[tokio::test] #[crate::test]
async fn get_service_fn() { async fn get_service_fn() {
async fn handle(_req: Request<Body>) -> Result<Response<Body>, Infallible> { async fn handle(_req: Request<Body>) -> Result<Response<Body>, Infallible> {
Ok(Response::new(Body::from("ok"))) Ok(Response::new(Body::from("ok")))
@ -1301,7 +1301,7 @@ mod tests {
assert_eq!(body, "ok"); assert_eq!(body, "ok");
} }
#[tokio::test] #[crate::test]
async fn get_handler() { async fn get_handler() {
let mut svc = MethodRouter::new().get(ok); let mut svc = MethodRouter::new().get(ok);
let (status, _, body) = call(Method::GET, &mut svc).await; let (status, _, body) = call(Method::GET, &mut svc).await;
@ -1309,7 +1309,7 @@ mod tests {
assert_eq!(body, "ok"); assert_eq!(body, "ok");
} }
#[tokio::test] #[crate::test]
async fn get_accepts_head() { async fn get_accepts_head() {
let mut svc = MethodRouter::new().get(ok); let mut svc = MethodRouter::new().get(ok);
let (status, _, body) = call(Method::HEAD, &mut svc).await; let (status, _, body) = call(Method::HEAD, &mut svc).await;
@ -1317,7 +1317,7 @@ mod tests {
assert!(body.is_empty()); assert!(body.is_empty());
} }
#[tokio::test] #[crate::test]
async fn head_takes_precedence_over_get() { async fn head_takes_precedence_over_get() {
let mut svc = MethodRouter::new().head(created).get(ok); let mut svc = MethodRouter::new().head(created).get(ok);
let (status, _, body) = call(Method::HEAD, &mut svc).await; let (status, _, body) = call(Method::HEAD, &mut svc).await;
@ -1325,7 +1325,7 @@ mod tests {
assert!(body.is_empty()); assert!(body.is_empty());
} }
#[tokio::test] #[crate::test]
async fn merge() { async fn merge() {
let mut svc = get(ok).merge(post(ok)); let mut svc = get(ok).merge(post(ok));
@ -1336,7 +1336,7 @@ mod tests {
assert_eq!(status, StatusCode::OK); assert_eq!(status, StatusCode::OK);
} }
#[tokio::test] #[crate::test]
async fn layer() { async fn layer() {
let mut svc = MethodRouter::new() let mut svc = MethodRouter::new()
.get(|| async { std::future::pending::<()>().await }) .get(|| async { std::future::pending::<()>().await })
@ -1351,7 +1351,7 @@ mod tests {
assert_eq!(status, StatusCode::UNAUTHORIZED); assert_eq!(status, StatusCode::UNAUTHORIZED);
} }
#[tokio::test] #[crate::test]
async fn route_layer() { async fn route_layer() {
let mut svc = MethodRouter::new() let mut svc = MethodRouter::new()
.get(|| async { std::future::pending::<()>().await }) .get(|| async { std::future::pending::<()>().await })
@ -1392,7 +1392,7 @@ mod tests {
crate::Server::bind(&"0.0.0.0:0".parse().unwrap()).serve(app.into_make_service()); crate::Server::bind(&"0.0.0.0:0".parse().unwrap()).serve(app.into_make_service());
} }
#[tokio::test] #[crate::test]
async fn sets_allow_header() { async fn sets_allow_header() {
let mut svc = MethodRouter::new().put(ok).patch(ok); let mut svc = MethodRouter::new().put(ok).patch(ok);
let (status, headers, _) = call(Method::GET, &mut svc).await; let (status, headers, _) = call(Method::GET, &mut svc).await;
@ -1400,7 +1400,7 @@ mod tests {
assert_eq!(headers[ALLOW], "PUT,PATCH"); assert_eq!(headers[ALLOW], "PUT,PATCH");
} }
#[tokio::test] #[crate::test]
async fn sets_allow_header_get_head() { async fn sets_allow_header_get_head() {
let mut svc = MethodRouter::new().get(ok).head(ok); let mut svc = MethodRouter::new().get(ok).head(ok);
let (status, headers, _) = call(Method::PUT, &mut svc).await; let (status, headers, _) = call(Method::PUT, &mut svc).await;
@ -1408,7 +1408,7 @@ mod tests {
assert_eq!(headers[ALLOW], "GET,HEAD"); assert_eq!(headers[ALLOW], "GET,HEAD");
} }
#[tokio::test] #[crate::test]
async fn empty_allow_header_by_default() { async fn empty_allow_header_by_default() {
let mut svc = MethodRouter::new(); let mut svc = MethodRouter::new();
let (status, headers, _) = call(Method::PATCH, &mut svc).await; let (status, headers, _) = call(Method::PATCH, &mut svc).await;
@ -1416,7 +1416,7 @@ mod tests {
assert_eq!(headers[ALLOW], ""); assert_eq!(headers[ALLOW], "");
} }
#[tokio::test] #[crate::test]
async fn allow_header_when_merging() { async fn allow_header_when_merging() {
let a = put(ok).patch(ok); let a = put(ok).patch(ok);
let b = get(ok).head(ok); let b = get(ok).head(ok);
@ -1427,7 +1427,7 @@ mod tests {
assert_eq!(headers[ALLOW], "PUT,PATCH,GET,HEAD"); assert_eq!(headers[ALLOW], "PUT,PATCH,GET,HEAD");
} }
#[tokio::test] #[crate::test]
async fn allow_header_any() { async fn allow_header_any() {
let mut svc = any(ok); let mut svc = any(ok);
@ -1436,7 +1436,7 @@ mod tests {
assert!(!headers.contains_key(ALLOW)); assert!(!headers.contains_key(ALLOW));
} }
#[tokio::test] #[crate::test]
async fn allow_header_with_fallback() { async fn allow_header_with_fallback() {
let mut svc = MethodRouter::new() let mut svc = MethodRouter::new()
.get(ok) .get(ok)
@ -1447,7 +1447,7 @@ mod tests {
assert_eq!(headers[ALLOW], "GET,HEAD"); assert_eq!(headers[ALLOW], "GET,HEAD");
} }
#[tokio::test] #[crate::test]
async fn allow_header_with_fallback_that_sets_allow() { async fn allow_header_with_fallback_that_sets_allow() {
async fn fallback(method: Method) -> Response { async fn fallback(method: Method) -> Response {
if method == Method::POST { if method == Method::POST {
@ -1475,7 +1475,7 @@ mod tests {
assert_eq!(headers[ALLOW], "GET,POST"); assert_eq!(headers[ALLOW], "GET,POST");
} }
#[tokio::test] #[crate::test]
#[should_panic( #[should_panic(
expected = "Overlapping method route. Cannot add two method routes that both handle `GET`" expected = "Overlapping method route. Cannot add two method routes that both handle `GET`"
)] )]
@ -1483,7 +1483,7 @@ mod tests {
let _: MethodRouter<()> = get(ok).get(ok); let _: MethodRouter<()> = get(ok).get(ok);
} }
#[tokio::test] #[crate::test]
#[should_panic( #[should_panic(
expected = "Overlapping method route. Cannot add two method routes that both handle `POST`" expected = "Overlapping method route. Cannot add two method routes that both handle `POST`"
)] )]
@ -1491,17 +1491,17 @@ mod tests {
let _: MethodRouter<()> = post_service(ok.into_service()).post_service(ok.into_service()); let _: MethodRouter<()> = post_service(ok.into_service()).post_service(ok.into_service());
} }
#[tokio::test] #[crate::test]
async fn get_head_does_not_overlap() { async fn get_head_does_not_overlap() {
let _: MethodRouter<()> = get(ok).head(ok); let _: MethodRouter<()> = get(ok).head(ok);
} }
#[tokio::test] #[crate::test]
async fn head_get_does_not_overlap() { async fn head_get_does_not_overlap() {
let _: MethodRouter<()> = head(ok).get(ok); let _: MethodRouter<()> = head(ok).get(ok);
} }
#[tokio::test] #[crate::test]
async fn accessing_state() { async fn accessing_state() {
let mut svc = MethodRouter::new() let mut svc = MethodRouter::new()
.get(|State(state): State<&'static str>| async move { state }) .get(|State(state): State<&'static str>| async move { state })
@ -1513,7 +1513,7 @@ mod tests {
assert_eq!(text, "state"); assert_eq!(text, "state");
} }
#[tokio::test] #[crate::test]
async fn fallback_accessing_state() { async fn fallback_accessing_state() {
let mut svc = MethodRouter::new() let mut svc = MethodRouter::new()
.fallback(|State(state): State<&'static str>| async move { state }) .fallback(|State(state): State<&'static str>| async move { state })
@ -1525,7 +1525,7 @@ mod tests {
assert_eq!(text, "state"); assert_eq!(text, "state");
} }
#[tokio::test] #[crate::test]
async fn merge_accessing_state() { async fn merge_accessing_state() {
let one = get(|State(state): State<&'static str>| async move { state }); let one = get(|State(state): State<&'static str>| async move { state });
let two = post(|State(state): State<&'static str>| async move { state }); let two = post(|State(state): State<&'static str>| async move { state });

View file

@ -3,7 +3,7 @@ use tower::ServiceExt;
use super::*; use super::*;
use crate::middleware::{map_request, map_response}; use crate::middleware::{map_request, map_response};
#[tokio::test] #[crate::test]
async fn basic() { async fn basic() {
let app = Router::new() let app = Router::new()
.route("/foo", get(|| async {})) .route("/foo", get(|| async {}))
@ -18,7 +18,7 @@ async fn basic() {
assert_eq!(res.text().await, "fallback"); assert_eq!(res.text().await, "fallback");
} }
#[tokio::test] #[crate::test]
async fn nest() { async fn nest() {
let app = Router::new() let app = Router::new()
.nest("/foo", Router::new().route("/bar", get(|| async {}))) .nest("/foo", Router::new().route("/bar", get(|| async {})))
@ -33,7 +33,7 @@ async fn nest() {
assert_eq!(res.text().await, "fallback"); assert_eq!(res.text().await, "fallback");
} }
#[tokio::test] #[crate::test]
async fn or() { async fn or() {
let one = Router::new().route("/one", get(|| async {})); let one = Router::new().route("/one", get(|| async {}));
let two = Router::new().route("/two", get(|| async {})); let two = Router::new().route("/two", get(|| async {}));
@ -50,7 +50,7 @@ async fn or() {
assert_eq!(res.text().await, "fallback"); assert_eq!(res.text().await, "fallback");
} }
#[tokio::test] #[crate::test]
async fn fallback_accessing_state() { async fn fallback_accessing_state() {
let app = Router::new() let app = Router::new()
.fallback(|State(state): State<&'static str>| async move { state }) .fallback(|State(state): State<&'static str>| async move { state })
@ -71,7 +71,7 @@ async fn outer_fallback() -> impl IntoResponse {
(StatusCode::NOT_FOUND, "outer") (StatusCode::NOT_FOUND, "outer")
} }
#[tokio::test] #[crate::test]
async fn nested_router_inherits_fallback() { async fn nested_router_inherits_fallback() {
let inner = Router::new(); let inner = Router::new();
let app = Router::new().nest("/foo", inner).fallback(outer_fallback); let app = Router::new().nest("/foo", inner).fallback(outer_fallback);
@ -83,7 +83,7 @@ async fn nested_router_inherits_fallback() {
assert_eq!(res.text().await, "outer"); assert_eq!(res.text().await, "outer");
} }
#[tokio::test] #[crate::test]
async fn doesnt_inherit_fallback_if_overriden() { async fn doesnt_inherit_fallback_if_overriden() {
let inner = Router::new().fallback(inner_fallback); let inner = Router::new().fallback(inner_fallback);
let app = Router::new().nest("/foo", inner).fallback(outer_fallback); let app = Router::new().nest("/foo", inner).fallback(outer_fallback);
@ -95,7 +95,7 @@ async fn doesnt_inherit_fallback_if_overriden() {
assert_eq!(res.text().await, "inner"); assert_eq!(res.text().await, "inner");
} }
#[tokio::test] #[crate::test]
async fn deeply_nested_inherit_from_top() { async fn deeply_nested_inherit_from_top() {
let app = Router::new() let app = Router::new()
.nest("/foo", Router::new().nest("/bar", Router::new())) .nest("/foo", Router::new().nest("/bar", Router::new()))
@ -108,7 +108,7 @@ async fn deeply_nested_inherit_from_top() {
assert_eq!(res.text().await, "outer"); assert_eq!(res.text().await, "outer");
} }
#[tokio::test] #[crate::test]
async fn deeply_nested_inherit_from_middle() { async fn deeply_nested_inherit_from_middle() {
let app = Router::new().nest( let app = Router::new().nest(
"/foo", "/foo",
@ -124,7 +124,7 @@ async fn deeply_nested_inherit_from_middle() {
assert_eq!(res.text().await, "outer"); assert_eq!(res.text().await, "outer");
} }
#[tokio::test] #[crate::test]
async fn with_middleware_on_inner_fallback() { async fn with_middleware_on_inner_fallback() {
async fn never_called<B>(_: Request<B>) -> Request<B> { async fn never_called<B>(_: Request<B>) -> Request<B> {
panic!("should never be called") panic!("should never be called")
@ -140,7 +140,7 @@ async fn with_middleware_on_inner_fallback() {
assert_eq!(res.text().await, "outer"); assert_eq!(res.text().await, "outer");
} }
#[tokio::test] #[crate::test]
async fn also_inherits_default_layered_fallback() { async fn also_inherits_default_layered_fallback() {
async fn set_header<B>(mut res: Response<B>) -> Response<B> { async fn set_header<B>(mut res: Response<B>) -> Response<B> {
res.headers_mut() res.headers_mut()
@ -162,7 +162,7 @@ async fn also_inherits_default_layered_fallback() {
assert_eq!(res.text().await, "outer"); assert_eq!(res.text().await, "outer");
} }
#[tokio::test] #[crate::test]
async fn fallback_inherited_into_nested_router_service() { async fn fallback_inherited_into_nested_router_service() {
let inner = Router::new() let inner = Router::new()
.route( .route(
@ -182,7 +182,7 @@ async fn fallback_inherited_into_nested_router_service() {
assert_eq!(res.text().await, "outer"); assert_eq!(res.text().await, "outer");
} }
#[tokio::test] #[crate::test]
async fn fallback_inherited_into_nested_opaque_service() { async fn fallback_inherited_into_nested_opaque_service() {
let inner = Router::new() let inner = Router::new()
.route( .route(

View file

@ -6,7 +6,7 @@ mod for_handlers {
use super::*; use super::*;
use http::HeaderMap; use http::HeaderMap;
#[tokio::test] #[crate::test]
async fn get_handles_head() { async fn get_handles_head() {
let app = Router::new().route( let app = Router::new().route(
"/", "/",
@ -41,7 +41,7 @@ mod for_services {
use super::*; use super::*;
use crate::routing::get_service; use crate::routing::get_service;
#[tokio::test] #[crate::test]
async fn get_handles_head() { async fn get_handles_head() {
let app = Router::new().route( let app = Router::new().route(
"/", "/",

View file

@ -29,7 +29,7 @@ impl<R> Service<R> for Svc {
} }
} }
#[tokio::test] #[crate::test]
async fn handler() { async fn handler() {
let app = Router::new().route( let app = Router::new().route(
"/", "/",
@ -48,7 +48,7 @@ async fn handler() {
assert_eq!(res.status(), StatusCode::REQUEST_TIMEOUT); assert_eq!(res.status(), StatusCode::REQUEST_TIMEOUT);
} }
#[tokio::test] #[crate::test]
async fn handler_multiple_methods_first() { async fn handler_multiple_methods_first() {
let app = Router::new().route( let app = Router::new().route(
"/", "/",
@ -68,7 +68,7 @@ async fn handler_multiple_methods_first() {
assert_eq!(res.status(), StatusCode::REQUEST_TIMEOUT); assert_eq!(res.status(), StatusCode::REQUEST_TIMEOUT);
} }
#[tokio::test] #[crate::test]
async fn handler_multiple_methods_middle() { async fn handler_multiple_methods_middle() {
let app = Router::new().route( let app = Router::new().route(
"/", "/",
@ -91,7 +91,7 @@ async fn handler_multiple_methods_middle() {
assert_eq!(res.status(), StatusCode::REQUEST_TIMEOUT); assert_eq!(res.status(), StatusCode::REQUEST_TIMEOUT);
} }
#[tokio::test] #[crate::test]
async fn handler_multiple_methods_last() { async fn handler_multiple_methods_last() {
let app = Router::new().route( let app = Router::new().route(
"/", "/",

View file

@ -3,7 +3,7 @@ use crate::{error_handling::HandleErrorLayer, extract::OriginalUri, response::In
use serde_json::{json, Value}; use serde_json::{json, Value};
use tower::{limit::ConcurrencyLimitLayer, timeout::TimeoutLayer}; use tower::{limit::ConcurrencyLimitLayer, timeout::TimeoutLayer};
#[tokio::test] #[crate::test]
async fn basic() { async fn basic() {
let one = Router::new() let one = Router::new()
.route("/foo", get(|| async {})) .route("/foo", get(|| async {}))
@ -26,7 +26,7 @@ async fn basic() {
assert_eq!(res.status(), StatusCode::NOT_FOUND); assert_eq!(res.status(), StatusCode::NOT_FOUND);
} }
#[tokio::test] #[crate::test]
async fn multiple_ors_balanced_differently() { async fn multiple_ors_balanced_differently() {
let one = Router::new().route("/one", get(|| async { "one" })); let one = Router::new().route("/one", get(|| async { "one" }));
let two = Router::new().route("/two", get(|| async { "two" })); let two = Router::new().route("/two", get(|| async { "two" }));
@ -71,7 +71,7 @@ async fn multiple_ors_balanced_differently() {
} }
} }
#[tokio::test] #[crate::test]
async fn nested_or() { async fn nested_or() {
let bar = Router::new().route("/bar", get(|| async { "bar" })); let bar = Router::new().route("/bar", get(|| async { "bar" }));
let baz = Router::new().route("/baz", get(|| async { "baz" })); let baz = Router::new().route("/baz", get(|| async { "baz" }));
@ -87,7 +87,7 @@ async fn nested_or() {
assert_eq!(client.get("/foo/baz").send().await.text().await, "baz"); assert_eq!(client.get("/foo/baz").send().await.text().await, "baz");
} }
#[tokio::test] #[crate::test]
async fn or_with_route_following() { async fn or_with_route_following() {
let one = Router::new().route("/one", get(|| async { "one" })); let one = Router::new().route("/one", get(|| async { "one" }));
let two = Router::new().route("/two", get(|| async { "two" })); let two = Router::new().route("/two", get(|| async { "two" }));
@ -105,7 +105,7 @@ async fn or_with_route_following() {
assert_eq!(res.status(), StatusCode::OK); assert_eq!(res.status(), StatusCode::OK);
} }
#[tokio::test] #[crate::test]
async fn layer() { async fn layer() {
let one = Router::new().route("/foo", get(|| async {})); let one = Router::new().route("/foo", get(|| async {}));
let two = Router::new() let two = Router::new()
@ -122,7 +122,7 @@ async fn layer() {
assert_eq!(res.status(), StatusCode::OK); assert_eq!(res.status(), StatusCode::OK);
} }
#[tokio::test] #[crate::test]
async fn layer_and_handle_error() { async fn layer_and_handle_error() {
let one = Router::new().route("/foo", get(|| async {})); let one = Router::new().route("/foo", get(|| async {}));
let two = Router::new() let two = Router::new()
@ -142,7 +142,7 @@ async fn layer_and_handle_error() {
assert_eq!(res.status(), StatusCode::REQUEST_TIMEOUT); assert_eq!(res.status(), StatusCode::REQUEST_TIMEOUT);
} }
#[tokio::test] #[crate::test]
async fn nesting() { async fn nesting() {
let one = Router::new().route("/foo", get(|| async {})); let one = Router::new().route("/foo", get(|| async {}));
let two = Router::new().nest("/bar", Router::new().route("/baz", get(|| async {}))); let two = Router::new().nest("/bar", Router::new().route("/baz", get(|| async {})));
@ -154,7 +154,7 @@ async fn nesting() {
assert_eq!(res.status(), StatusCode::OK); assert_eq!(res.status(), StatusCode::OK);
} }
#[tokio::test] #[crate::test]
async fn boxed() { async fn boxed() {
let one = Router::new().route("/foo", get(|| async {})); let one = Router::new().route("/foo", get(|| async {}));
let two = Router::new().route("/bar", get(|| async {})); let two = Router::new().route("/bar", get(|| async {}));
@ -166,7 +166,7 @@ async fn boxed() {
assert_eq!(res.status(), StatusCode::OK); assert_eq!(res.status(), StatusCode::OK);
} }
#[tokio::test] #[crate::test]
async fn many_ors() { async fn many_ors() {
let app = Router::new() let app = Router::new()
.route("/r1", get(|| async {})) .route("/r1", get(|| async {}))
@ -188,7 +188,7 @@ async fn many_ors() {
assert_eq!(res.status(), StatusCode::NOT_FOUND); assert_eq!(res.status(), StatusCode::NOT_FOUND);
} }
#[tokio::test] #[crate::test]
async fn services() { async fn services() {
use crate::routing::get_service; use crate::routing::get_service;
@ -227,7 +227,7 @@ async fn all_the_uris(
})) }))
} }
#[tokio::test] #[crate::test]
async fn nesting_and_seeing_the_right_uri() { async fn nesting_and_seeing_the_right_uri() {
let one = Router::new().nest("/foo/", Router::new().route("/bar", get(all_the_uris))); let one = Router::new().nest("/foo/", Router::new().route("/bar", get(all_the_uris)));
let two = Router::new().route("/foo", get(all_the_uris)); let two = Router::new().route("/foo", get(all_the_uris));
@ -257,7 +257,7 @@ async fn nesting_and_seeing_the_right_uri() {
); );
} }
#[tokio::test] #[crate::test]
async fn nesting_and_seeing_the_right_uri_at_more_levels_of_nesting() { async fn nesting_and_seeing_the_right_uri_at_more_levels_of_nesting() {
let one = Router::new().nest( let one = Router::new().nest(
"/foo/", "/foo/",
@ -290,7 +290,7 @@ async fn nesting_and_seeing_the_right_uri_at_more_levels_of_nesting() {
); );
} }
#[tokio::test] #[crate::test]
async fn nesting_and_seeing_the_right_uri_ors_with_nesting() { async fn nesting_and_seeing_the_right_uri_ors_with_nesting() {
let one = Router::new().nest( let one = Router::new().nest(
"/one", "/one",
@ -335,7 +335,7 @@ async fn nesting_and_seeing_the_right_uri_ors_with_nesting() {
); );
} }
#[tokio::test] #[crate::test]
async fn nesting_and_seeing_the_right_uri_ors_with_multi_segment_uris() { async fn nesting_and_seeing_the_right_uri_ors_with_multi_segment_uris() {
let one = Router::new().nest( let one = Router::new().nest(
"/one", "/one",
@ -368,7 +368,7 @@ async fn nesting_and_seeing_the_right_uri_ors_with_multi_segment_uris() {
); );
} }
#[tokio::test] #[crate::test]
async fn middleware_that_return_early() { async fn middleware_that_return_early() {
let private = Router::new() let private = Router::new()
.route("/", get(|| async {})) .route("/", get(|| async {}))

View file

@ -29,7 +29,7 @@ mod handle_error;
mod merge; mod merge;
mod nest; mod nest;
#[tokio::test] #[crate::test]
async fn hello_world() { async fn hello_world() {
async fn root(_: Request<Body>) -> &'static str { async fn root(_: Request<Body>) -> &'static str {
"Hello, World!" "Hello, World!"
@ -62,7 +62,7 @@ async fn hello_world() {
assert_eq!(body, "users#create"); assert_eq!(body, "users#create");
} }
#[tokio::test] #[crate::test]
async fn routing() { async fn routing() {
let app = Router::new() let app = Router::new()
.route( .route(
@ -98,7 +98,7 @@ async fn routing() {
assert_eq!(res.text().await, "users#action"); assert_eq!(res.text().await, "users#action");
} }
#[tokio::test] #[crate::test]
async fn router_type_doesnt_change() { async fn router_type_doesnt_change() {
let app: Router = Router::new() let app: Router = Router::new()
.route( .route(
@ -123,7 +123,7 @@ async fn router_type_doesnt_change() {
assert_eq!(res.text().await, "hi from POST"); assert_eq!(res.text().await, "hi from POST");
} }
#[tokio::test] #[crate::test]
async fn routing_between_services() { async fn routing_between_services() {
use std::convert::Infallible; use std::convert::Infallible;
use tower::service_fn; use tower::service_fn;
@ -169,7 +169,7 @@ async fn routing_between_services() {
assert_eq!(res.text().await, "handler"); assert_eq!(res.text().await, "handler");
} }
#[tokio::test] #[crate::test]
async fn middleware_on_single_route() { async fn middleware_on_single_route() {
use tower::ServiceBuilder; use tower::ServiceBuilder;
use tower_http::{compression::CompressionLayer, trace::TraceLayer}; use tower_http::{compression::CompressionLayer, trace::TraceLayer};
@ -196,7 +196,7 @@ async fn middleware_on_single_route() {
assert_eq!(body, "Hello, World!"); assert_eq!(body, "Hello, World!");
} }
#[tokio::test] #[crate::test]
async fn service_in_bottom() { async fn service_in_bottom() {
async fn handler(_req: Request<Body>) -> Result<Response<Body>, Infallible> { async fn handler(_req: Request<Body>) -> Result<Response<Body>, Infallible> {
Ok(Response::new(hyper::Body::empty())) Ok(Response::new(hyper::Body::empty()))
@ -207,7 +207,7 @@ async fn service_in_bottom() {
TestClient::new(app); TestClient::new(app);
} }
#[tokio::test] #[crate::test]
async fn wrong_method_handler() { async fn wrong_method_handler() {
let app = Router::new() let app = Router::new()
.route("/", get(|| async {}).post(|| async {})) .route("/", get(|| async {}).post(|| async {}))
@ -230,7 +230,7 @@ async fn wrong_method_handler() {
assert_eq!(res.status(), StatusCode::NOT_FOUND); assert_eq!(res.status(), StatusCode::NOT_FOUND);
} }
#[tokio::test] #[crate::test]
async fn wrong_method_service() { async fn wrong_method_service() {
#[derive(Clone)] #[derive(Clone)]
struct Svc; struct Svc;
@ -270,7 +270,7 @@ async fn wrong_method_service() {
assert_eq!(res.status(), StatusCode::NOT_FOUND); assert_eq!(res.status(), StatusCode::NOT_FOUND);
} }
#[tokio::test] #[crate::test]
async fn multiple_methods_for_one_handler() { async fn multiple_methods_for_one_handler() {
async fn root(_: Request<Body>) -> &'static str { async fn root(_: Request<Body>) -> &'static str {
"Hello, World!" "Hello, World!"
@ -287,7 +287,7 @@ async fn multiple_methods_for_one_handler() {
assert_eq!(res.status(), StatusCode::OK); assert_eq!(res.status(), StatusCode::OK);
} }
#[tokio::test] #[crate::test]
async fn wildcard_sees_whole_url() { async fn wildcard_sees_whole_url() {
let app = Router::new().route("/api/*rest", get(|uri: Uri| async move { uri.to_string() })); let app = Router::new().route("/api/*rest", get(|uri: Uri| async move { uri.to_string() }));
@ -297,7 +297,7 @@ async fn wildcard_sees_whole_url() {
assert_eq!(res.text().await, "/api/foo/bar"); assert_eq!(res.text().await, "/api/foo/bar");
} }
#[tokio::test] #[crate::test]
async fn middleware_applies_to_routes_above() { async fn middleware_applies_to_routes_above() {
let app = Router::new() let app = Router::new()
.route("/one", get(std::future::pending::<()>)) .route("/one", get(std::future::pending::<()>))
@ -319,7 +319,7 @@ async fn middleware_applies_to_routes_above() {
assert_eq!(res.status(), StatusCode::OK); assert_eq!(res.status(), StatusCode::OK);
} }
#[tokio::test] #[crate::test]
async fn not_found_for_extra_trailing_slash() { async fn not_found_for_extra_trailing_slash() {
let app = Router::new().route("/foo", get(|| async {})); let app = Router::new().route("/foo", get(|| async {}));
@ -332,7 +332,7 @@ async fn not_found_for_extra_trailing_slash() {
assert_eq!(res.status(), StatusCode::OK); assert_eq!(res.status(), StatusCode::OK);
} }
#[tokio::test] #[crate::test]
async fn not_found_for_missing_trailing_slash() { async fn not_found_for_missing_trailing_slash() {
let app = Router::new().route("/foo/", get(|| async {})); let app = Router::new().route("/foo/", get(|| async {}));
@ -342,7 +342,7 @@ async fn not_found_for_missing_trailing_slash() {
assert_eq!(res.status(), StatusCode::NOT_FOUND); assert_eq!(res.status(), StatusCode::NOT_FOUND);
} }
#[tokio::test] #[crate::test]
async fn with_and_without_trailing_slash() { async fn with_and_without_trailing_slash() {
let app = Router::new() let app = Router::new()
.route("/foo", get(|| async { "without tsr" })) .route("/foo", get(|| async { "without tsr" }))
@ -360,7 +360,7 @@ async fn with_and_without_trailing_slash() {
} }
// for https://github.com/tokio-rs/axum/issues/420 // for https://github.com/tokio-rs/axum/issues/420
#[tokio::test] #[crate::test]
async fn wildcard_doesnt_match_just_trailing_slash() { async fn wildcard_doesnt_match_just_trailing_slash() {
let app = Router::new().route( let app = Router::new().route(
"/x/*path", "/x/*path",
@ -380,7 +380,7 @@ async fn wildcard_doesnt_match_just_trailing_slash() {
assert_eq!(res.text().await, "foo/bar"); assert_eq!(res.text().await, "foo/bar");
} }
#[tokio::test] #[crate::test]
async fn static_and_dynamic_paths() { async fn static_and_dynamic_paths() {
let app = Router::new() let app = Router::new()
.route( .route(
@ -398,14 +398,14 @@ async fn static_and_dynamic_paths() {
assert_eq!(res.text().await, "static"); assert_eq!(res.text().await, "static");
} }
#[tokio::test] #[crate::test]
#[should_panic(expected = "Paths must start with a `/`. Use \"/\" for root routes")] #[should_panic(expected = "Paths must start with a `/`. Use \"/\" for root routes")]
async fn empty_route() { async fn empty_route() {
let app = Router::new().route("", get(|| async {})); let app = Router::new().route("", get(|| async {}));
TestClient::new(app); TestClient::new(app);
} }
#[tokio::test] #[crate::test]
async fn middleware_still_run_for_unmatched_requests() { async fn middleware_still_run_for_unmatched_requests() {
#[derive(Clone)] #[derive(Clone)]
struct CountMiddleware<S>(S); struct CountMiddleware<S>(S);
@ -445,7 +445,7 @@ async fn middleware_still_run_for_unmatched_requests() {
assert_eq!(COUNT.load(Ordering::SeqCst), 2); assert_eq!(COUNT.load(Ordering::SeqCst), 2);
} }
#[tokio::test] #[crate::test]
#[should_panic(expected = "\ #[should_panic(expected = "\
Invalid route: `Router::route_service` cannot be used with `Router`s. \ Invalid route: `Router::route_service` cannot be used with `Router`s. \
Use `Router::nest` instead\ Use `Router::nest` instead\
@ -454,7 +454,7 @@ async fn routing_to_router_panics() {
TestClient::new(Router::new().route_service("/", Router::new())); TestClient::new(Router::new().route_service("/", Router::new()));
} }
#[tokio::test] #[crate::test]
async fn route_layer() { async fn route_layer() {
let app = Router::new() let app = Router::new()
.route("/foo", get(|| async {})) .route("/foo", get(|| async {}))
@ -482,7 +482,7 @@ async fn route_layer() {
assert_eq!(res.status(), StatusCode::UNAUTHORIZED); assert_eq!(res.status(), StatusCode::UNAUTHORIZED);
} }
#[tokio::test] #[crate::test]
async fn different_methods_added_in_different_routes() { async fn different_methods_added_in_different_routes() {
let app = Router::new() let app = Router::new()
.route("/", get(|| async { "GET" })) .route("/", get(|| async { "GET" }))
@ -499,7 +499,7 @@ async fn different_methods_added_in_different_routes() {
assert_eq!(body, "POST"); assert_eq!(body, "POST");
} }
#[tokio::test] #[crate::test]
#[should_panic(expected = "Cannot merge two `Router`s that both have a fallback")] #[should_panic(expected = "Cannot merge two `Router`s that both have a fallback")]
async fn merging_routers_with_fallbacks_panics() { async fn merging_routers_with_fallbacks_panics() {
async fn fallback() {} async fn fallback() {}
@ -525,7 +525,7 @@ fn merging_with_overlapping_method_routes() {
app.clone().merge(app); app.clone().merge(app);
} }
#[tokio::test] #[crate::test]
async fn merging_routers_with_same_paths_but_different_methods() { async fn merging_routers_with_same_paths_but_different_methods() {
let one = Router::new().route("/", get(|| async { "GET" })); let one = Router::new().route("/", get(|| async { "GET" }));
let two = Router::new().route("/", post(|| async { "POST" })); let two = Router::new().route("/", post(|| async { "POST" }));
@ -541,7 +541,7 @@ async fn merging_routers_with_same_paths_but_different_methods() {
assert_eq!(body, "POST"); assert_eq!(body, "POST");
} }
#[tokio::test] #[crate::test]
async fn head_content_length_through_hyper_server() { async fn head_content_length_through_hyper_server() {
let app = Router::new() let app = Router::new()
.route("/", get(|| async { "foo" })) .route("/", get(|| async { "foo" }))
@ -558,7 +558,7 @@ async fn head_content_length_through_hyper_server() {
assert!(res.text().await.is_empty()); assert!(res.text().await.is_empty());
} }
#[tokio::test] #[crate::test]
async fn head_content_length_through_hyper_server_that_hits_fallback() { async fn head_content_length_through_hyper_server_that_hits_fallback() {
let app = Router::new().fallback(|| async { "foo" }); let app = Router::new().fallback(|| async { "foo" });
@ -568,7 +568,7 @@ async fn head_content_length_through_hyper_server_that_hits_fallback() {
assert_eq!(res.headers()["content-length"], "3"); assert_eq!(res.headers()["content-length"], "3");
} }
#[tokio::test] #[crate::test]
async fn head_with_middleware_applied() { async fn head_with_middleware_applied() {
use tower_http::compression::{predicate::SizeAbove, CompressionLayer}; use tower_http::compression::{predicate::SizeAbove, CompressionLayer};
@ -601,14 +601,14 @@ async fn head_with_middleware_applied() {
assert!(!res.headers().contains_key("content-length")); assert!(!res.headers().contains_key("content-length"));
} }
#[tokio::test] #[crate::test]
#[should_panic(expected = "Paths must start with a `/`")] #[should_panic(expected = "Paths must start with a `/`")]
async fn routes_must_start_with_slash() { async fn routes_must_start_with_slash() {
let app = Router::new().route(":foo", get(|| async {})); let app = Router::new().route(":foo", get(|| async {}));
TestClient::new(app); TestClient::new(app);
} }
#[tokio::test] #[crate::test]
async fn body_limited_by_default() { async fn body_limited_by_default() {
let app = Router::new() let app = Router::new()
.route("/bytes", post(|_: Bytes| async {})) .route("/bytes", post(|_: Bytes| async {}))
@ -636,7 +636,7 @@ async fn body_limited_by_default() {
} }
} }
#[tokio::test] #[crate::test]
async fn disabling_the_default_limit() { async fn disabling_the_default_limit() {
let app = Router::new() let app = Router::new()
.route("/", post(|_: Bytes| async {})) .route("/", post(|_: Bytes| async {}))
@ -652,7 +652,7 @@ async fn disabling_the_default_limit() {
assert_eq!(res.status(), StatusCode::OK); assert_eq!(res.status(), StatusCode::OK);
} }
#[tokio::test] #[crate::test]
async fn limited_body_with_content_length() { async fn limited_body_with_content_length() {
const LIMIT: usize = 3; const LIMIT: usize = 3;
@ -674,7 +674,7 @@ async fn limited_body_with_content_length() {
assert_eq!(res.status(), StatusCode::PAYLOAD_TOO_LARGE); assert_eq!(res.status(), StatusCode::PAYLOAD_TOO_LARGE);
} }
#[tokio::test] #[crate::test]
async fn changing_the_default_limit() { async fn changing_the_default_limit() {
let new_limit = 2; let new_limit = 2;
@ -699,7 +699,7 @@ async fn changing_the_default_limit() {
assert_eq!(res.status(), StatusCode::PAYLOAD_TOO_LARGE); assert_eq!(res.status(), StatusCode::PAYLOAD_TOO_LARGE);
} }
#[tokio::test] #[crate::test]
async fn limited_body_with_streaming_body() { async fn limited_body_with_streaming_body() {
const LIMIT: usize = 3; const LIMIT: usize = 3;
@ -731,7 +731,7 @@ async fn limited_body_with_streaming_body() {
assert_eq!(res.status(), StatusCode::PAYLOAD_TOO_LARGE); assert_eq!(res.status(), StatusCode::PAYLOAD_TOO_LARGE);
} }
#[tokio::test] #[crate::test]
async fn extract_state() { async fn extract_state() {
#[derive(Clone)] #[derive(Clone)]
struct AppState { struct AppState {
@ -767,7 +767,7 @@ async fn extract_state() {
assert_eq!(res.status(), StatusCode::OK); assert_eq!(res.status(), StatusCode::OK);
} }
#[tokio::test] #[crate::test]
async fn explicitly_set_state() { async fn explicitly_set_state() {
let app = Router::new() let app = Router::new()
.route_service( .route_service(
@ -781,7 +781,7 @@ async fn explicitly_set_state() {
assert_eq!(res.text().await, "foo"); assert_eq!(res.text().await, "foo");
} }
#[tokio::test] #[crate::test]
async fn layer_response_into_response() { async fn layer_response_into_response() {
fn map_response<B>(_res: Response<B>) -> Result<Response<B>, impl IntoResponse> { fn map_response<B>(_res: Response<B>) -> Result<Response<B>, impl IntoResponse> {
let headers = [("x-foo", "bar")]; let headers = [("x-foo", "bar")];

View file

@ -3,7 +3,7 @@ use crate::{body::boxed, extract::Extension};
use std::collections::HashMap; use std::collections::HashMap;
use tower_http::services::ServeDir; use tower_http::services::ServeDir;
#[tokio::test] #[crate::test]
async fn nesting_apps() { async fn nesting_apps() {
let api_routes = Router::new() let api_routes = Router::new()
.route( .route(
@ -58,7 +58,7 @@ async fn nesting_apps() {
assert_eq!(res.text().await, "v0: games#show (123)"); assert_eq!(res.text().await, "v0: games#show (123)");
} }
#[tokio::test] #[crate::test]
async fn wrong_method_nest() { async fn wrong_method_nest() {
let nested_app = Router::new().route("/", get(|| async {})); let nested_app = Router::new().route("/", get(|| async {}));
let app = Router::new().nest("/", nested_app); let app = Router::new().nest("/", nested_app);
@ -76,7 +76,7 @@ async fn wrong_method_nest() {
assert_eq!(res.status(), StatusCode::NOT_FOUND); assert_eq!(res.status(), StatusCode::NOT_FOUND);
} }
#[tokio::test] #[crate::test]
async fn nesting_router_at_root() { async fn nesting_router_at_root() {
let nested = Router::new().route("/foo", get(|uri: Uri| async move { uri.to_string() })); let nested = Router::new().route("/foo", get(|uri: Uri| async move { uri.to_string() }));
let app = Router::new().nest("/", nested); let app = Router::new().nest("/", nested);
@ -94,7 +94,7 @@ async fn nesting_router_at_root() {
assert_eq!(res.status(), StatusCode::NOT_FOUND); assert_eq!(res.status(), StatusCode::NOT_FOUND);
} }
#[tokio::test] #[crate::test]
async fn nesting_router_at_empty_path() { async fn nesting_router_at_empty_path() {
let nested = Router::new().route("/foo", get(|uri: Uri| async move { uri.to_string() })); let nested = Router::new().route("/foo", get(|uri: Uri| async move { uri.to_string() }));
let app = Router::new().nest("", nested); let app = Router::new().nest("", nested);
@ -112,7 +112,7 @@ async fn nesting_router_at_empty_path() {
assert_eq!(res.status(), StatusCode::NOT_FOUND); assert_eq!(res.status(), StatusCode::NOT_FOUND);
} }
#[tokio::test] #[crate::test]
async fn nesting_handler_at_root() { async fn nesting_handler_at_root() {
let app = Router::new().nest_service("/", get(|uri: Uri| async move { uri.to_string() })); let app = Router::new().nest_service("/", get(|uri: Uri| async move { uri.to_string() }));
@ -131,7 +131,7 @@ async fn nesting_handler_at_root() {
assert_eq!(res.text().await, "/foo/bar"); assert_eq!(res.text().await, "/foo/bar");
} }
#[tokio::test] #[crate::test]
async fn nested_url_extractor() { async fn nested_url_extractor() {
let app = Router::new().nest( let app = Router::new().nest(
"/foo", "/foo",
@ -157,7 +157,7 @@ async fn nested_url_extractor() {
assert_eq!(res.text().await, "/qux"); assert_eq!(res.text().await, "/qux");
} }
#[tokio::test] #[crate::test]
async fn nested_url_original_extractor() { async fn nested_url_original_extractor() {
let app = Router::new().nest( let app = Router::new().nest(
"/foo", "/foo",
@ -177,7 +177,7 @@ async fn nested_url_original_extractor() {
assert_eq!(res.text().await, "/foo/bar/baz"); assert_eq!(res.text().await, "/foo/bar/baz");
} }
#[tokio::test] #[crate::test]
async fn nested_service_sees_stripped_uri() { async fn nested_service_sees_stripped_uri() {
let app = Router::new().nest( let app = Router::new().nest(
"/foo", "/foo",
@ -200,7 +200,7 @@ async fn nested_service_sees_stripped_uri() {
assert_eq!(res.text().await, "/baz"); assert_eq!(res.text().await, "/baz");
} }
#[tokio::test] #[crate::test]
async fn nest_static_file_server() { async fn nest_static_file_server() {
let app = Router::new().nest_service( let app = Router::new().nest_service(
"/static", "/static",
@ -218,7 +218,7 @@ async fn nest_static_file_server() {
assert_eq!(res.status(), StatusCode::OK); assert_eq!(res.status(), StatusCode::OK);
} }
#[tokio::test] #[crate::test]
async fn nested_multiple_routes() { async fn nested_multiple_routes() {
let app = Router::new() let app = Router::new()
.nest( .nest(
@ -244,7 +244,7 @@ fn nested_at_root_with_other_routes() {
.route("/", get(|| async {})); .route("/", get(|| async {}));
} }
#[tokio::test] #[crate::test]
async fn multiple_top_level_nests() { async fn multiple_top_level_nests() {
let app = Router::new() let app = Router::new()
.nest( .nest(
@ -262,13 +262,13 @@ async fn multiple_top_level_nests() {
assert_eq!(client.get("/two/route").send().await.text().await, "two"); assert_eq!(client.get("/two/route").send().await.text().await, "two");
} }
#[tokio::test] #[crate::test]
#[should_panic(expected = "Invalid route: nested routes cannot contain wildcards (*)")] #[should_panic(expected = "Invalid route: nested routes cannot contain wildcards (*)")]
async fn nest_cannot_contain_wildcards() { async fn nest_cannot_contain_wildcards() {
Router::<(), Body>::new().nest("/one/*rest", Router::new()); Router::<(), Body>::new().nest("/one/*rest", Router::new());
} }
#[tokio::test] #[crate::test]
async fn outer_middleware_still_see_whole_url() { async fn outer_middleware_still_see_whole_url() {
#[derive(Clone)] #[derive(Clone)]
struct SetUriExtension<S>(S); struct SetUriExtension<S>(S);
@ -319,7 +319,7 @@ async fn outer_middleware_still_see_whole_url() {
assert_eq!(client.get("/one/two").send().await.text().await, "/one/two"); assert_eq!(client.get("/one/two").send().await.text().await, "/one/two");
} }
#[tokio::test] #[crate::test]
async fn nest_at_capture() { async fn nest_at_capture() {
let api_routes = Router::new().route( let api_routes = Router::new().route(
"/:b", "/:b",
@ -335,7 +335,7 @@ async fn nest_at_capture() {
assert_eq!(res.text().await, "a=foo b=bar"); assert_eq!(res.text().await, "a=foo b=bar");
} }
#[tokio::test] #[crate::test]
async fn nest_with_and_without_trailing() { async fn nest_with_and_without_trailing() {
let app = Router::new().nest_service("/foo", get(|| async {})); let app = Router::new().nest_service("/foo", get(|| async {}));
@ -351,7 +351,7 @@ async fn nest_with_and_without_trailing() {
assert_eq!(res.status(), StatusCode::OK); assert_eq!(res.status(), StatusCode::OK);
} }
#[tokio::test] #[crate::test]
async fn nesting_with_root_inner_router() { async fn nesting_with_root_inner_router() {
let app = Router::new().nest( let app = Router::new().nest(
"/foo", "/foo",
@ -371,7 +371,7 @@ async fn nesting_with_root_inner_router() {
assert_eq!(res.status(), StatusCode::OK); assert_eq!(res.status(), StatusCode::OK);
} }
#[tokio::test] #[crate::test]
async fn fallback_on_inner() { async fn fallback_on_inner() {
let app = Router::new() let app = Router::new()
.nest( .nest(
@ -399,7 +399,7 @@ macro_rules! nested_route_test {
// the route we expect to be able to call // the route we expect to be able to call
expected = $expected_path:literal $(,)? expected = $expected_path:literal $(,)?
) => { ) => {
#[tokio::test] #[crate::test]
async fn $name() { async fn $name() {
let inner = Router::new().route($route_path, get(|| async {})); let inner = Router::new().route($route_path, get(|| async {}));
let app = Router::new().nest($nested_path, inner); let app = Router::new().nest($nested_path, inner);

View file

@ -170,7 +170,7 @@ mod tests {
use super::*; use super::*;
use crate::{response::IntoResponse, routing::get, test_helpers::*, Router}; use crate::{response::IntoResponse, routing::get, test_helpers::*, Router};
#[tokio::test] #[crate::test]
async fn typed_header() { async fn typed_header() {
async fn handle( async fn handle(
TypedHeader(user_agent): TypedHeader<headers::UserAgent>, TypedHeader(user_agent): TypedHeader<headers::UserAgent>,