diff --git a/contrib/lib/tests/compress_responder.rs.disabled b/contrib/lib/tests/compress_responder.rs.disabled index 345400e3..978cfaa9 100644 --- a/contrib/lib/tests/compress_responder.rs.disabled +++ b/contrib/lib/tests/compress_responder.rs.disabled @@ -66,7 +66,7 @@ mod compress_responder_tests { #[test] fn test_prioritizes_brotli() { - let client = Client::tracked(rocket()).expect("valid rocket instance"); + let client = Client::debug(rocket()).expect("valid rocket instance"); let mut response = client .get("/") .header(Header::new("Accept-Encoding", "deflate, gzip, br")) @@ -90,7 +90,7 @@ mod compress_responder_tests { #[test] fn test_br_font() { - let client = Client::tracked(rocket()).expect("valid rocket instance"); + let client = Client::debug(rocket()).expect("valid rocket instance"); let mut response = client .get("/font") .header(Header::new("Accept-Encoding", "deflate, gzip, br")) @@ -114,7 +114,7 @@ mod compress_responder_tests { #[test] fn test_fallback_gzip() { - let client = Client::tracked(rocket()).expect("valid rocket instance"); + let client = Client::debug(rocket()).expect("valid rocket instance"); let mut response = client .get("/") .header(Header::new("Accept-Encoding", "deflate, gzip")) @@ -137,7 +137,7 @@ mod compress_responder_tests { #[test] fn test_does_not_recompress() { - let client = Client::tracked(rocket()).expect("valid rocket instance"); + let client = Client::debug(rocket()).expect("valid rocket instance"); let mut response = client .get("/already_encoded") .header(Header::new("Accept-Encoding", "deflate, gzip, br")) @@ -160,7 +160,7 @@ mod compress_responder_tests { #[test] fn test_does_not_compress_explicit_identity() { - let client = Client::tracked(rocket()).expect("valid rocket instance"); + let client = Client::debug(rocket()).expect("valid rocket instance"); let mut response = client .get("/identity") .header(Header::new("Accept-Encoding", "deflate, gzip, br")) @@ -178,7 +178,7 @@ mod compress_responder_tests { #[test] fn test_ignore_exceptions() { - let client = Client::tracked(rocket()).expect("valid rocket instance"); + let client = Client::debug(rocket()).expect("valid rocket instance"); let mut response = client .get("/image") .header(Header::new("Accept-Encoding", "deflate, gzip, br")) @@ -202,7 +202,7 @@ mod compress_responder_tests { #[test] fn test_ignores_unimplemented_encodings() { - let client = Client::tracked(rocket()).expect("valid rocket instance"); + let client = Client::debug(rocket()).expect("valid rocket instance"); let mut response = client .get("/") .header(Header::new("Accept-Encoding", "deflate")) @@ -220,7 +220,7 @@ mod compress_responder_tests { #[test] fn test_respects_identity_only() { - let client = Client::tracked(rocket()).expect("valid rocket instance"); + let client = Client::debug(rocket()).expect("valid rocket instance"); let mut response = client .get("/") .header(Header::new("Accept-Encoding", "identity")) diff --git a/contrib/lib/tests/compression_fairing.rs.disabled b/contrib/lib/tests/compression_fairing.rs.disabled index 00224d64..6a99265d 100644 --- a/contrib/lib/tests/compression_fairing.rs.disabled +++ b/contrib/lib/tests/compression_fairing.rs.disabled @@ -85,7 +85,7 @@ mod compression_fairing_tests { #[test] fn test_prioritizes_brotli() { - let client = Client::tracked(rocket()).expect("valid rocket instance"); + let client = Client::debug(rocket()).expect("valid rocket instance"); let mut response = client .get("/") .header(Header::new("Accept-Encoding", "deflate, gzip, br")) @@ -109,7 +109,7 @@ mod compression_fairing_tests { #[test] fn test_br_font() { - let client = Client::tracked(rocket()).expect("valid rocket instance"); + let client = Client::debug(rocket()).expect("valid rocket instance"); let mut response = client .get("/font") .header(Header::new("Accept-Encoding", "deflate, gzip, br")) @@ -133,7 +133,7 @@ mod compression_fairing_tests { #[test] fn test_fallback_gzip() { - let client = Client::tracked(rocket()).expect("valid rocket instance"); + let client = Client::debug(rocket()).expect("valid rocket instance"); let mut response = client .get("/") .header(Header::new("Accept-Encoding", "deflate, gzip")) @@ -156,7 +156,7 @@ mod compression_fairing_tests { #[test] fn test_does_not_recompress() { - let client = Client::tracked(rocket()).expect("valid rocket instance"); + let client = Client::debug(rocket()).expect("valid rocket instance"); let mut response = client .get("/already_encoded") .header(Header::new("Accept-Encoding", "deflate, gzip, br")) @@ -179,7 +179,7 @@ mod compression_fairing_tests { #[test] fn test_does_not_compress_explicit_identity() { - let client = Client::tracked(rocket()).expect("valid rocket instance"); + let client = Client::debug(rocket()).expect("valid rocket instance"); let mut response = client .get("/identity") .header(Header::new("Accept-Encoding", "deflate, gzip, br")) @@ -197,7 +197,7 @@ mod compression_fairing_tests { #[test] fn test_does_not_compress_image() { - let client = Client::tracked(rocket()).expect("valid rocket instance"); + let client = Client::debug(rocket()).expect("valid rocket instance"); let mut response = client .get("/image") .header(Header::new("Accept-Encoding", "deflate, gzip, br")) @@ -215,7 +215,7 @@ mod compression_fairing_tests { #[test] fn test_ignores_unimplemented_encodings() { - let client = Client::tracked(rocket()).expect("valid rocket instance"); + let client = Client::debug(rocket()).expect("valid rocket instance"); let mut response = client .get("/") .header(Header::new("Accept-Encoding", "deflate")) @@ -233,7 +233,7 @@ mod compression_fairing_tests { #[test] fn test_respects_identity_only() { - let client = Client::tracked(rocket()).expect("valid rocket instance"); + let client = Client::debug(rocket()).expect("valid rocket instance"); let mut response = client .get("/") .header(Header::new("Accept-Encoding", "identity")) @@ -251,7 +251,7 @@ mod compression_fairing_tests { #[test] fn test_does_not_compress_custom_exception() { - let client = Client::tracked(rocket_tar_exception()).expect("valid rocket instance"); + let client = Client::debug(rocket_tar_exception()).expect("valid rocket instance"); let mut response = client .get("/tar") .header(Header::new("Accept-Encoding", "deflate, gzip, br")) @@ -269,7 +269,7 @@ mod compression_fairing_tests { #[test] fn test_compress_custom_removed_exception() { - let client = Client::tracked(rocket_tar_exception()).expect("valid rocket instance"); + let client = Client::debug(rocket_tar_exception()).expect("valid rocket instance"); let mut response = client .get("/image") .header(Header::new("Accept-Encoding", "deflate, gzip, br")) diff --git a/contrib/lib/tests/helmet.rs b/contrib/lib/tests/helmet.rs index 12b7ee8b..5e603c1b 100644 --- a/contrib/lib/tests/helmet.rs +++ b/contrib/lib/tests/helmet.rs @@ -32,7 +32,7 @@ mod helmet_tests { macro_rules! dispatch { ($helmet:expr, $closure:expr) => {{ let rocket = rocket::ignite().mount("/", routes![hello]).attach($helmet); - let client = Client::tracked(rocket).unwrap(); + let client = Client::debug(rocket).unwrap(); let response = client.get("/").dispatch(); assert_eq!(response.status(), Status::Ok); $closure(response) diff --git a/contrib/lib/tests/static_files.rs b/contrib/lib/tests/static_files.rs index ff003582..a9c4af52 100644 --- a/contrib/lib/tests/static_files.rs +++ b/contrib/lib/tests/static_files.rs @@ -69,7 +69,7 @@ mod static_tests { #[test] fn test_static_no_index() { - let client = Client::tracked(rocket()).expect("valid rocket"); + let client = Client::debug(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); @@ -77,7 +77,7 @@ mod static_tests { #[test] fn test_static_hidden() { - let client = Client::tracked(rocket()).expect("valid rocket"); + let client = Client::debug(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); @@ -85,7 +85,7 @@ mod static_tests { #[test] fn test_static_index() { - let client = Client::tracked(rocket()).expect("valid rocket"); + let client = Client::debug(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); @@ -97,7 +97,7 @@ mod static_tests { #[test] fn test_static_all() { - let client = Client::tracked(rocket()).expect("valid rocket"); + let client = Client::debug(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); @@ -128,7 +128,7 @@ mod static_tests { fn catch_two(a: &str, b: &str) -> String { format!("{}/{}", a, b) } let rocket = rocket().mount("/default", routes![catch_one, catch_two]); - let client = Client::tracked(rocket).expect("valid rocket"); + let client = Client::debug(rocket).expect("valid rocket"); let response = client.get("/default/ireallydontexist").dispatch(); assert_eq!(response.status(), Status::Ok); @@ -145,7 +145,7 @@ mod static_tests { #[test] fn test_redirection() { - let client = Client::tracked(rocket()).expect("valid rocket"); + let client = Client::debug(rocket()).expect("valid rocket"); // Redirection only happens if enabled, and doesn't affect index behaviour. let response = client.get("/no_index/inner").dispatch(); diff --git a/contrib/lib/tests/templates.rs b/contrib/lib/tests/templates.rs index f42bc22d..710ca9e1 100644 --- a/contrib/lib/tests/templates.rs +++ b/contrib/lib/tests/templates.rs @@ -40,12 +40,10 @@ mod templates_tests { Err("error reloading templates!".into()) })); - match Client::untracked(rocket) { - Err(e) => match e.kind() { - FailedFairings(failures) => assert_eq!(failures[0], "Templates"), - _ => panic!("Wrong kind of launch error"), - } - _ => panic!("Wrong kind of error"), + let error = Client::debug(rocket).expect_err("client failure"); + match error.kind() { + FailedFairings(failures) => assert_eq!(failures[0].name, "Templates"), + _ => panic!("Wrong kind of launch error"), } } @@ -79,7 +77,7 @@ mod templates_tests { #[test] fn test_template_metadata_with_tera() { - let client = Client::tracked(rocket()).unwrap(); + let client = Client::debug(rocket()).unwrap(); let response = client.get("/tera/txt_test").dispatch(); assert_eq!(response.status(), Status::Ok); @@ -119,7 +117,7 @@ mod templates_tests { #[test] fn test_template_metadata_with_handlebars() { - let client = Client::tracked(rocket()).unwrap(); + let client = Client::debug(rocket()).unwrap(); let response = client.get("/hbs/test").dispatch(); assert_eq!(response.status(), Status::Ok); @@ -156,7 +154,7 @@ mod templates_tests { write_file(&reload_path, INITIAL_TEXT); // set up the client. if we can't reload templates, then just quit - let client = Client::tracked(rocket()).unwrap(); + let client = Client::debug(rocket()).unwrap(); let res = client.get("/is_reloading").dispatch(); if res.status() != Status::Ok { return; diff --git a/core/codegen/tests/expansion.rs b/core/codegen/tests/expansion.rs index 5aa16ec7..5ef77aca 100644 --- a/core/codegen/tests/expansion.rs +++ b/core/codegen/tests/expansion.rs @@ -34,7 +34,7 @@ foo!("/hello/", name); #[test] fn test_reexpansion() { let rocket = rocket::ignite().mount("/", routes![easy, hard, hi]); - let client = Client::tracked(rocket).unwrap(); + let client = Client::debug(rocket).unwrap(); let response = client.get("/easy/327").dispatch(); assert_eq!(response.into_string().unwrap(), "easy id: 327"); @@ -60,7 +60,7 @@ index!(i32); #[test] fn test_index() { let rocket = rocket::ignite().mount("/", routes![index]).manage(100i32); - let client = Client::tracked(rocket).unwrap(); + let client = Client::debug(rocket).unwrap(); let response = client.get("/").dispatch(); assert_eq!(response.into_string().unwrap(), "Thing: 100"); diff --git a/core/codegen/tests/from_form.rs b/core/codegen/tests/from_form.rs index fbc2d3d2..b224d739 100644 --- a/core/codegen/tests/from_form.rs +++ b/core/codegen/tests/from_form.rs @@ -587,7 +587,7 @@ fn test_nested_multi() { // Ok("hi") // } // -// let client = Client::untracked(crate::ignite().mount("/", routes![form])).unwrap(); +// let client = Client::debug_with(routes![form]).unwrap(); // let ct = "multipart/form-data; boundary=X-BOUNDARY" // .parse::() // .unwrap(); diff --git a/core/codegen/tests/responder.rs b/core/codegen/tests/responder.rs index af00a15e..069b8141 100644 --- a/core/codegen/tests/responder.rs +++ b/core/codegen/tests/responder.rs @@ -21,7 +21,7 @@ pub enum Foo<'r> { #[rocket::async_test] async fn responder_foo() { - let client = Client::tracked(rocket::ignite()).await.expect("valid rocket"); + let client = Client::debug_with(vec![]).await.expect("valid rocket"); let local_req = client.get("/"); let req = local_req.inner(); @@ -70,7 +70,7 @@ pub struct Bar<'r> { #[rocket::async_test] async fn responder_bar() { - let client = Client::tracked(rocket::ignite()).await.expect("valid rocket"); + let client = Client::debug_with(vec![]).await.expect("valid rocket"); let local_req = client.get("/"); let req = local_req.inner(); @@ -95,7 +95,7 @@ pub struct Baz { #[rocket::async_test] async fn responder_baz() { - let client = Client::tracked(rocket::ignite()).await.expect("valid rocket"); + let client = Client::debug_with(vec![]).await.expect("valid rocket"); let local_req = client.get("/"); let req = local_req.inner(); diff --git a/core/codegen/tests/route-data.rs b/core/codegen/tests/route-data.rs index 0deee7a1..c086267b 100644 --- a/core/codegen/tests/route-data.rs +++ b/core/codegen/tests/route-data.rs @@ -1,4 +1,4 @@ -#[macro_use]extern crate rocket; +#[macro_use] extern crate rocket; use rocket::{Request, Data}; use rocket::local::blocking::Client; @@ -33,7 +33,7 @@ fn simple<'r>(simple: Simple<'r>) -> &'r str { simple.0 } #[test] fn test_data() { let rocket = rocket::ignite().mount("/", routes![form, simple]); - let client = Client::tracked(rocket).unwrap(); + let client = Client::debug(rocket).unwrap(); let response = client.post("/f") .header(ContentType::Form) diff --git a/core/codegen/tests/route-format.rs b/core/codegen/tests/route-format.rs index c98e1e62..714614c9 100644 --- a/core/codegen/tests/route-format.rs +++ b/core/codegen/tests/route-format.rs @@ -37,7 +37,7 @@ fn test_formats() { .mount("/", routes![json, xml, json_long, msgpack_long, msgpack, plain, binary, other]); - let client = Client::tracked(rocket).unwrap(); + let client = Client::debug(rocket).unwrap(); let response = client.post("/").header(ContentType::JSON).dispatch(); assert_eq!(response.into_string().unwrap(), "json"); @@ -87,7 +87,7 @@ fn test_custom_formats() { let rocket = rocket::ignite() .mount("/", routes![get_foo, post_foo, get_bar_baz, put_bar_baz]); - let client = Client::tracked(rocket).unwrap(); + let client = Client::debug(rocket).unwrap(); let foo_a = Accept::new(&[MediaType::new("application", "foo").into()]); let foo_ct = ContentType::new("application", "foo"); diff --git a/core/codegen/tests/route-ranking.rs b/core/codegen/tests/route-ranking.rs index 9efefbe1..20b8ca43 100644 --- a/core/codegen/tests/route-ranking.rs +++ b/core/codegen/tests/route-ranking.rs @@ -19,7 +19,7 @@ fn get3(_number: u64) -> &'static str { "3" } #[test] fn test_ranking() { let rocket = rocket::ignite().mount("/", routes![get0, get1, get2, get3]); - let client = Client::tracked(rocket).unwrap(); + let client = Client::debug(rocket).unwrap(); let response = client.get("/0").dispatch(); assert_eq!(response.into_string().unwrap(), "0"); @@ -44,7 +44,7 @@ fn test_rank_collision() { use rocket::error::ErrorKind; let rocket = rocket::ignite().mount("/", routes![get0, get0b]); - let client_result = Client::tracked(rocket); + let client_result = Client::debug(rocket); match client_result.as_ref().map_err(|e| e.kind()) { Err(ErrorKind::Collision(..)) => { /* o.k. */ }, Ok(_) => panic!("client succeeded unexpectedly"), diff --git a/core/codegen/tests/route-raw.rs b/core/codegen/tests/route-raw.rs index 6f429833..d191973d 100644 --- a/core/codegen/tests/route-raw.rs +++ b/core/codegen/tests/route-raw.rs @@ -25,7 +25,7 @@ fn test_raw_ident() { .mount("/", routes![get, swap]) .register(catchers![catch]); - let client = Client::untracked(rocket).unwrap(); + let client = Client::debug(rocket).unwrap(); let response = client.get("/example?type=1").dispatch(); assert_eq!(response.into_string().unwrap(), "example is 1"); diff --git a/core/codegen/tests/route.rs b/core/codegen/tests/route.rs index 995a1e71..3386236c 100644 --- a/core/codegen/tests/route.rs +++ b/core/codegen/tests/route.rs @@ -87,7 +87,7 @@ fn test_full_route() { .mount("/1", routes![post1]) .mount("/2", routes![post2]); - let client = Client::tracked(rocket).unwrap(); + let client = Client::debug(rocket).unwrap(); let a = RawStr::new("A%20A"); let name = RawStr::new("Bob%20McDonald"); @@ -171,7 +171,7 @@ fn filtered_raw_query(bird: usize, color: &str, rest: Contextual<'_, Filtered<'_ #[test] fn test_filtered_raw_query() { let rocket = rocket::ignite().mount("/", routes![filtered_raw_query]); - let client = Client::untracked(rocket).unwrap(); + let client = Client::debug(rocket).unwrap(); #[track_caller] fn run(client: &Client, birds: &[&str], colors: &[&str], cats: &[&str]) -> (Status, String) { @@ -259,7 +259,7 @@ fn test_query_collection() { } fn run_tests(rocket: rocket::Rocket) { - let client = Client::untracked(rocket).unwrap(); + let client = Client::debug(rocket).unwrap(); let colors = &["blue", "green"]; let dog = &["name=Fido", "age=10"]; @@ -327,7 +327,7 @@ fn test_inclusive_segments() { .mount("/", routes![segments]) .mount("/", routes![segments_empty]); - let client = Client::untracked(rocket).unwrap(); + let client = Client::debug(rocket).unwrap(); let get = |uri| client.get(uri).dispatch().into_string().unwrap(); assert_eq!(get("/"), "empty+"); diff --git a/core/codegen/tests/segment-ignore.rs b/core/codegen/tests/segment-ignore.rs index ee2fb108..c9996014 100644 --- a/core/codegen/tests/segment-ignore.rs +++ b/core/codegen/tests/segment-ignore.rs @@ -27,11 +27,7 @@ fn test_ignored_segments() { ig_1, just_static, ig_2, ig_3, ig_1_static, ig_1_static_static, wrapped ]); - let client = match Client::untracked(rocket) { - Ok(client) => client, - Err(e) => { drop(e); panic!("whoops") }, - }; - + let client = Client::debug(rocket).unwrap(); assert_eq!(get_string(&client, "/foo"), "1"); assert_eq!(get_string(&client, "/bar"), "1"); assert_eq!(get_string(&client, "/static"), "static"); diff --git a/core/lib/Cargo.toml b/core/lib/Cargo.toml index a77f6e68..7eb055f7 100644 --- a/core/lib/Cargo.toml +++ b/core/lib/Cargo.toml @@ -47,7 +47,7 @@ async-trait = "0.1.43" [dependencies.state] git = "https://github.com/SergioBenitez/state.git" -rev = "7576652" +rev = "0a7457d2" [dependencies.rocket_codegen] version = "0.5.0-dev" @@ -74,6 +74,7 @@ version_check = "0.9.1" [dev-dependencies] bencher = "0.1" figment = { version = "0.10", features = ["test"] } +pretty_assertions = "0.7" [[bench]] name = "format-routing" diff --git a/core/lib/benches/format-routing.rs b/core/lib/benches/format-routing.rs index 75fcf630..877be120 100644 --- a/core/lib/benches/format-routing.rs +++ b/core/lib/benches/format-routing.rs @@ -10,8 +10,12 @@ fn get() -> &'static str { "get" } fn post() -> &'static str { "post" } fn rocket() -> rocket::Rocket { - rocket::custom(rocket::Config::figment().merge(("log_level", "off"))) - .mount("/", routes![get, post]) + let config = rocket::Config { + log_level: rocket::config::LogLevel::Off, + ..rocket::Config::debug_default() + }; + + rocket::custom(config).mount("/", routes![get, post]) } use bencher::Bencher; diff --git a/core/lib/benches/ranked-routing.rs b/core/lib/benches/ranked-routing.rs index 07bd7ea9..c11d327c 100644 --- a/core/lib/benches/ranked-routing.rs +++ b/core/lib/benches/ranked-routing.rs @@ -20,7 +20,12 @@ fn post2() -> &'static str { "html" } fn post3() -> &'static str { "plain" } fn rocket() -> rocket::Rocket { - rocket::custom(rocket::Config::figment().merge(("log_level", "off"))) + let config = rocket::Config { + log_level: rocket::config::LogLevel::Off, + ..rocket::Config::debug_default() + }; + + rocket::custom(config) .mount("/", routes![get, get2, get3]) .mount("/", routes![post, post2, post3]) } diff --git a/core/lib/benches/simple-routing.rs b/core/lib/benches/simple-routing.rs index 58d054a1..1194949f 100644 --- a/core/lib/benches/simple-routing.rs +++ b/core/lib/benches/simple-routing.rs @@ -23,7 +23,11 @@ fn index_c() -> &'static str { "index" } fn index_dyn_a(_a: &str) -> &'static str { "index" } fn hello_world_rocket() -> rocket::Rocket { - let config = rocket::Config::figment().merge(("log_level", "off")); + let config = rocket::Config { + log_level: rocket::config::LogLevel::Off, + ..rocket::Config::debug_default() + }; + rocket::custom(config).mount("/", routes![hello_world]) } diff --git a/core/lib/src/config/config.rs b/core/lib/src/config/config.rs index 09f952f8..94d40f9b 100644 --- a/core/lib/src/config/config.rs +++ b/core/lib/src/config/config.rs @@ -38,7 +38,7 @@ use crate::config::SecretKey; /// /// * **Profile** /// -/// This provider does not set a profile. +/// The profile is set to the value of the `profile` field. /// /// * **Metadata** /// @@ -54,6 +54,12 @@ use crate::config::SecretKey; /// Note that these behaviors differ from those of [`Config::figment()`]. #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] pub struct Config { + /// The selected profile. **(default: _debug_ `debug` / _release_ `release`)** + /// + /// **Note:** This field is never serialized nor deserialized. It is set to + /// the value of the selected `Profile` during extraction. + #[serde(skip)] + pub profile: Profile, /// IP address to serve on. **(default: `127.0.0.1`)** pub address: IpAddr, /// Port to serve on. **(default: `8000`)** @@ -106,10 +112,10 @@ impl Default for Config { } impl Config { - /// The default "debug" profile. + /// The default debug profile: `debug`. pub const DEBUG_PROFILE: Profile = Profile::const_new("debug"); - /// The default "release" profile. + /// The default release profile: `release`. pub const RELEASE_PROFILE: Profile = Profile::const_new("release"); /// The default profile: "debug" on `debug`, "release" on `release`. @@ -145,6 +151,7 @@ impl Config { /// ``` pub fn debug_default() -> Config { Config { + profile: Self::DEBUG_PROFILE, address: Ipv4Addr::new(127, 0, 0, 1).into(), port: 8000, workers: num_cpus::get(), @@ -177,6 +184,7 @@ impl Config { /// ``` pub fn release_default() -> Config { Config { + profile: Self::RELEASE_PROFILE, log_level: LogLevel::Critical, ..Config::debug_default() } @@ -217,52 +225,55 @@ impl Config { .merge(Env::prefixed("ROCKET_").ignore(&["PROFILE"]).global()) } - /// Attempts to extract a `Config` from `provider`. - /// - /// # Panics - /// - /// If extraction fails, prints an error message indicating the failure and - /// panics. + /// Attempts to extract a `Config` from `provider`, returning the result. /// /// # Example /// /// ```rust - /// use figment::{Figment, providers::{Toml, Format, Env}}; + /// use rocket::Config; + /// use rocket::figment::providers::{Toml, Format, Env}; /// /// // Use Rocket's default `Figment`, but allow values from `MyApp.toml` /// // and `MY_APP_` prefixed environment variables to supersede its values. - /// let figment = rocket::Config::figment() + /// let figment = Config::figment() + /// .merge(("some-thing", 123)) + /// .merge(Env::prefixed("CONFIG_")); + /// + /// let config = Config::try_from(figment); + /// ``` + pub fn try_from(provider: T) -> Result { + let figment = Figment::from(provider); + let mut config = figment.extract::()?; + config.profile = figment.profile().clone(); + Ok(config) + } + + /// Extract a `Config` from `provider`, panicking if extraction fails. + /// + /// # Panics + /// + /// If extraction fails, prints an error message indicating the failure and + /// panics. For a version that doesn't panic, use [`Config::try_from()`]. + /// + /// # Example + /// + /// ```rust + /// use rocket::Config; + /// use rocket::figment::providers::{Toml, Format, Env}; + /// + /// // Use Rocket's default `Figment`, but allow values from `MyApp.toml` + /// // and `MY_APP_` prefixed environment variables to supersede its values. + /// let figment = Config::figment() /// .merge(Toml::file("MyApp.toml").nested()) /// .merge(Env::prefixed("MY_APP_")); /// - /// let config = rocket::Config::from(figment); + /// let config = Config::from(figment); /// ``` - #[track_caller] pub fn from(provider: T) -> Self { - let figment = Figment::from(&provider); - - #[allow(unused_mut)] - let mut config = figment.extract::().unwrap_or_else(|e| { + Self::try_from(provider).unwrap_or_else(|e| { pretty_print_error(e); panic!("aborting due to configuration error(s)") - }); - - #[cfg(all(feature = "secrets", not(test), not(rocket_unsafe_secret_key)))] - if !config.secret_key.is_provided() { - if figment.profile() == Self::DEBUG_PROFILE { - // in debug, try to generate a key for a bit more security - let key = SecretKey::generate().unwrap_or(SecretKey::zero()); - config.secret_key = key; - } else { - crate::logger::try_init(LogLevel::Debug, true, false); - error!("secrets enabled in non-debug without `secret_key`"); - info_!("selected profile: {}", Paint::white(figment.profile())); - info_!("disable `secrets` feature or configure a `secret_key`"); - panic!("aborting due to configuration error(s)") - } - } - - config + }) } /// Returns `true` if TLS is enabled. @@ -306,17 +317,8 @@ impl Config { false => launch_info_!("tls: {}", Paint::default("disabled").bold()), } - #[cfg(all(feature = "secrets", not(test), not(rocket_unsafe_secret_key)))] { - launch_info_!("secret key: {:?}", - Paint::default(&self.secret_key).bold()); - - if !self.secret_key.is_provided() { - warn!("secrets enabled without a configured `secret_key`"); - info_!("disable `secrets` feature or configure a `secret_key`"); - info_!("this becomes a {} in non-debug profiles", - Paint::red("hard error").bold()); - } - } + #[cfg(feature = "secrets")] + launch_info_!("secret key: {:?}", Paint::default(&self.secret_key).bold()); launch_info_!("temp dir: {}", Paint::default(&self.temp_dir.display()).bold()); launch_info_!("log level: {}", Paint::default(self.log_level).bold()); @@ -372,6 +374,9 @@ impl Provider for Config { Ok(map) } + fn profile(&self) -> Option { + Some(self.profile.clone()) + } } #[crate::async_trait] @@ -387,7 +392,9 @@ impl<'a, 'r> FromRequest<'a, 'r> for &'r Config { pub fn pretty_print_error(error: figment::Error) { use figment::error::{Kind, OneOf}; - crate::logger::try_init(LogLevel::Debug, true, false); + let mut config = Config::debug_default(); + config.log_level = LogLevel::Debug; + crate::logger::init(&config); error!("Rocket configuration extraction from provider failed."); for e in error { diff --git a/core/lib/src/config/mod.rs b/core/lib/src/config/mod.rs index b81c3e5b..14231f31 100644 --- a/core/lib/src/config/mod.rs +++ b/core/lib/src/config/mod.rs @@ -130,7 +130,8 @@ pub use secret_key::SecretKey; #[cfg(test)] mod tests { use std::net::Ipv4Addr; - use figment::Figment; + use figment::{Figment, Profile}; + use pretty_assertions::assert_eq; use crate::config::{Config, TlsConfig}; use crate::logger::LogLevel; @@ -140,19 +141,10 @@ mod tests { fn test_default_round_trip() { figment::Jail::expect_with(|_| { let original = Config::figment(); - let profile = original.profile().clone(); - let roundtrip = Figment::from(Config::from(&original)).select(profile); + let roundtrip = Figment::from(Config::from(&original)); for figment in &[original, roundtrip] { - assert_eq!(figment.profile(), Config::DEFAULT_PROFILE); - - #[cfg(debug_assertions)] assert_eq!(figment.profile(), Config::DEBUG_PROFILE); - #[cfg(not(debug_assertions))] assert_eq!(figment.profile(), Config::RELEASE_PROFILE); - - let config: Config = figment.extract().unwrap(); + let config = Config::from(figment); assert_eq!(config, Config::default()); - - #[cfg(debug_assertions)] assert_eq!(config, Config::debug_default()); - #[cfg(not(debug_assertions))] assert_eq!(config, Config::release_default()); } Ok(()) @@ -305,6 +297,7 @@ mod tests { jail.set_env("ROCKET_PROFILE", "unknown"); let config = Config::from(Config::figment()); assert_eq!(config, Config { + profile: Profile::const_new("unknown"), limits: Limits::default() .limit("stream", 50.kilobytes()) .limit("forms", 2.kilobytes()), @@ -314,6 +307,7 @@ mod tests { jail.set_env("ROCKET_PROFILE", "debug"); let config = Config::from(Config::figment()); assert_eq!(config, Config { + profile: Profile::const_new("debug"), limits: Limits::default() .limit("stream", 50.kilobytes()) .limit("forms", 2.kilobytes()) @@ -404,4 +398,60 @@ mod tests { Ok(()) }); } + + #[test] + #[cfg(feature = "secrets")] + #[should_panic] + fn test_err_on_non_debug_and_no_secret_key() { + figment::Jail::expect_with(|jail| { + jail.set_env("ROCKET_PROFILE", "release"); + let rocket = crate::custom(Config::figment()); + let _result = crate::local::blocking::Client::untracked(rocket); + Ok(()) + }); + } + + #[test] + #[cfg(feature = "secrets")] + #[should_panic] + fn test_err_on_non_debug2_and_no_secret_key() { + figment::Jail::expect_with(|jail| { + jail.set_env("ROCKET_PROFILE", "boop"); + let rocket = crate::custom(Config::figment()); + let _result = crate::local::blocking::Client::tracked(rocket); + Ok(()) + }); + } + + #[test] + fn test_no_err_on_debug_and_no_secret_key() { + figment::Jail::expect_with(|jail| { + jail.set_env("ROCKET_PROFILE", "debug"); + let figment = Config::figment(); + assert!(crate::local::blocking::Client::untracked(crate::custom(&figment)).is_ok()); + crate::async_main(async { + let rocket = crate::custom(&figment); + assert!(crate::local::asynchronous::Client::tracked(rocket).await.is_ok()); + }); + + Ok(()) + }); + } + + #[test] + fn test_no_err_on_release_and_custom_secret_key() { + figment::Jail::expect_with(|jail| { + jail.set_env("ROCKET_PROFILE", "release"); + let key = "hPRYyVRiMyxpw5sBB1XeCMN1kFsDCqKvBi2QJxBVHQk="; + let figment = Config::figment().merge(("secret_key", key)); + + assert!(crate::local::blocking::Client::tracked(crate::custom(&figment)).is_ok()); + crate::async_main(async { + let rocket = crate::custom(&figment); + assert!(crate::local::asynchronous::Client::untracked(rocket).await.is_ok()); + }); + + Ok(()) + }); + } } diff --git a/core/lib/src/config/secret_key.rs b/core/lib/src/config/secret_key.rs index b4d300c4..a5d54c51 100644 --- a/core/lib/src/config/secret_key.rs +++ b/core/lib/src/config/secret_key.rs @@ -30,34 +30,40 @@ enum Kind { /// ``` /// /// When configured in the debug profile with the `secrets` feature enabled, a -/// key set a `0` is automatically regenerated from the OS's random source if -/// available. +/// key set as `0` is automatically regenerated at launch time from the OS's +/// random source if available. /// -/// ```rust,ignore -/// # // FIXME: Don't special case `SecretKey`. +/// ```rust /// use rocket::config::Config; +/// use rocket::local::blocking::Client; /// /// let figment = Config::figment() /// .merge(("secret_key", vec![0u8; 64])) /// .select("debug"); /// -/// let config = Config::from(figment); -/// assert!(!config.secret_key.is_zero()); +/// let rocket = rocket::custom(figment); +/// let client = Client::tracked(rocket).expect("okay in debug"); +/// assert!(!client.rocket().config().secret_key.is_zero()); /// ``` /// /// When running in any other profile with the `secrets` feature enabled, /// providing a key of `0` or not provided a key at all results in a failure at /// launch-time: /// -/// ```rust,should_panic,ignore -/// # // FIXME: Don't special case `SecretKey` checking on test/unsafe_key. +/// ```rust /// use rocket::config::Config; +/// use rocket::figment::Profile; +/// use rocket::local::blocking::Client; +/// use rocket::error::ErrorKind; /// +/// let profile = Profile::const_new("staging"); /// let figment = Config::figment() /// .merge(("secret_key", vec![0u8; 64])) -/// .select("staging"); +/// .select(profile.clone()); /// -/// let config = Config::from(figment); +/// let rocket = rocket::custom(figment); +/// let error = Client::tracked(rocket).expect_err("failure in non-debug"); +/// assert!(matches!(error.kind(), ErrorKind::InsecureSecretKey(profile))); /// ``` /// /// [private cookies]: https://rocket.rs/master/guide/requests/#private-cookies diff --git a/core/lib/src/cookies.rs b/core/lib/src/cookies.rs index bf72c222..b9dbf8da 100644 --- a/core/lib/src/cookies.rs +++ b/core/lib/src/cookies.rs @@ -47,8 +47,7 @@ pub use self::cookie::{Cookie, SameSite, Iter}; /// } /// # fn main() { /// # use rocket::local::blocking::Client; -/// # let rocket = rocket::ignite().mount("/", routes![message]); -/// # let client = Client::tracked(rocket).unwrap(); +/// # let client = Client::debug_with(routes![message]).unwrap(); /// # let response = client.get("/message") /// # .cookie(Cookie::new("message", "hi")) /// # .dispatch(); diff --git a/core/lib/src/error.rs b/core/lib/src/error.rs index 76dc1a97..f08fa9cc 100644 --- a/core/lib/src/error.rs +++ b/core/lib/src/error.rs @@ -4,6 +4,7 @@ use std::{io, fmt}; use std::sync::atomic::{Ordering, AtomicBool}; use yansi::Paint; +use figment::Profile; use crate::router::Route; @@ -80,8 +81,10 @@ pub enum ErrorKind { Runtime(Box), /// Route collisions were detected. Collision(Vec<(Route, Route)>), - /// A launch fairing reported an error. - FailedFairings(Vec<&'static str>), + /// Launch fairing(s) failed. + FailedFairings(Vec), + /// The configuration profile is not debug but not secret key is configured. + InsecureSecretKey(Profile), } impl From for Error { @@ -137,9 +140,10 @@ impl fmt::Display for ErrorKind { match self { ErrorKind::Bind(e) => write!(f, "binding failed: {}", e), ErrorKind::Io(e) => write!(f, "I/O error: {}", e), - ErrorKind::Collision(_) => write!(f, "route collisions detected"), - ErrorKind::FailedFairings(_) => write!(f, "a launch fairing failed"), - ErrorKind::Runtime(e) => write!(f, "runtime error: {}", e) + ErrorKind::Collision(_) => "route collisions detected".fmt(f), + ErrorKind::FailedFairings(_) => "a launch fairing failed".fmt(f), + ErrorKind::Runtime(e) => write!(f, "runtime error: {}", e), + ErrorKind::InsecureSecretKey(_) => "insecure secret key config".fmt(f), } } } @@ -166,7 +170,7 @@ impl Drop for Error { return } - match *self.kind() { + match self.kind() { ErrorKind::Bind(ref e) => { error!("Rocket failed to bind network socket to given address/port."); info_!("{}", e); @@ -189,7 +193,7 @@ impl Drop for Error { ErrorKind::FailedFairings(ref failures) => { error!("Rocket failed to launch due to failing fairings:"); for fairing in failures { - info_!("{}", fairing); + info_!("{}", fairing.name); } panic!("aborting due to launch fairing failure"); @@ -199,6 +203,12 @@ impl Drop for Error { info_!("{}", err); panic!("aborting due to runtime failure"); } + ErrorKind::InsecureSecretKey(profile) => { + error!("secrets enabled in non-debug without `secret_key`"); + info_!("selected profile: {}", Paint::white(profile)); + info_!("disable `secrets` feature or configure a `secret_key`"); + panic!("aborting due to insecure configuration") + } } } } diff --git a/core/lib/src/fairing/fairings.rs b/core/lib/src/fairing/fairings.rs index 84f7f129..aa38f3dc 100644 --- a/core/lib/src/fairing/fairings.rs +++ b/core/lib/src/fairing/fairings.rs @@ -1,5 +1,5 @@ use crate::{Rocket, Request, Response, Data}; -use crate::fairing::{Fairing, Kind}; +use crate::fairing::{Fairing, Info, Kind}; use crate::logger::PaintExt; use yansi::Paint; @@ -7,8 +7,9 @@ use yansi::Paint; #[derive(Default)] pub struct Fairings { all_fairings: Vec>, - attach_failures: Vec<&'static str>, + attach_failures: Vec, // The vectors below hold indices into `all_fairings`. + attach: Vec, launch: Vec, request: Vec, response: Vec, @@ -23,26 +24,39 @@ impl Fairings { pub async fn attach(&mut self, fairing: Box, mut rocket: Rocket) -> Rocket { // Run the `on_attach` callback if this is an 'attach' fairing. let kind = fairing.info().kind; - let name = fairing.info().name; + let fairing = self.add(fairing); if kind.is(Kind::Attach) { + let info = fairing.info(); rocket = fairing.on_attach(rocket).await - .unwrap_or_else(|r| { self.attach_failures.push(name); r }) + .unwrap_or_else(|r| { self.attach_failures.push(info); r }) } - self.add(fairing); rocket } - fn add(&mut self, fairing: Box) { + fn add(&mut self, fairing: Box) -> &dyn Fairing { let kind = fairing.info().kind; - if !kind.is_exactly(Kind::Attach) { - let index = self.all_fairings.len(); - self.all_fairings.push(fairing); + let index = self.all_fairings.len(); + self.all_fairings.push(fairing); - if kind.is(Kind::Launch) { self.launch.push(index); } - if kind.is(Kind::Request) { self.request.push(index); } - if kind.is(Kind::Response) { self.response.push(index); } - } + if kind.is(Kind::Attach) { self.attach.push(index); } + if kind.is(Kind::Launch) { self.launch.push(index); } + if kind.is(Kind::Request) { self.request.push(index); } + if kind.is(Kind::Response) { self.response.push(index); } + + &*self.all_fairings[index] + } + + #[inline(always)] + fn fairings(&self, kind: Kind) -> impl Iterator { + let indices = match kind { + k if k.is(Kind::Attach) => &self.attach, + k if k.is(Kind::Launch) => &self.launch, + k if k.is(Kind::Request) => &self.request, + _ => &self.response, + }; + + indices.iter().map(move |i| &*self.all_fairings[*i]) } pub fn append(&mut self, others: Fairings) { @@ -53,26 +67,26 @@ impl Fairings { #[inline(always)] pub fn handle_launch(&self, rocket: &Rocket) { - for &i in &self.launch { - self.all_fairings[i].on_launch(rocket); + for fairing in self.fairings(Kind::Launch) { + fairing.on_launch(rocket); } } #[inline(always)] pub async fn handle_request(&self, req: &mut Request<'_>, data: &mut Data) { - for &i in &self.request { - self.all_fairings[i].on_request(req, data).await; + for fairing in self.fairings(Kind::Request) { + fairing.on_request(req, data).await } } #[inline(always)] pub async fn handle_response<'r>(&self, request: &'r Request<'_>, response: &mut Response<'r>) { - for &i in &self.response { - self.all_fairings[i].on_response(request, response).await; + for fairing in self.fairings(Kind::Response) { + fairing.on_response(request, response).await; } } - pub fn failures(&self) -> Option<&[&'static str]> { + pub fn failures(&self) -> Option<&[Info]> { if self.attach_failures.is_empty() { None } else { @@ -80,24 +94,35 @@ impl Fairings { } } - fn info_for(&self, kind: &str, fairings: &[usize]) { - if !fairings.is_empty() { - let num = fairings.len(); - let names = fairings.iter().cloned() - .map(|i| self.all_fairings[i].info().name) - .collect::>() - .join(", "); - - info_!("{} {}: {}", Paint::default(num).bold(), kind, Paint::default(names).bold()); - } - } - pub fn pretty_print_counts(&self) { + fn pretty_print(f: &Fairings, prefix: &str, kind: Kind) { + let names: Vec<_> = f.fairings(kind).map(|f| f.info().name).collect(); + let num = names.len(); + let joined = names.join(", "); + info_!("{} {}: {}", Paint::default(num).bold(), prefix, Paint::default(joined).bold()); + } + if !self.all_fairings.is_empty() { info!("{}{}:", Paint::emoji("📡 "), Paint::magenta("Fairings")); - self.info_for("launch", &self.launch); - self.info_for("request", &self.request); - self.info_for("response", &self.response); + pretty_print(self, "attach", Kind::Attach); + pretty_print(self, "launch", Kind::Launch); + pretty_print(self, "request", Kind::Request); + pretty_print(self, "response", Kind::Response); } } } + +impl std::fmt::Debug for Fairings { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + fn debug_info(fs: &Fairings, kind: Kind) -> Vec { + fs.fairings(kind).map(|f| f.info()).collect() + } + + f.debug_struct("Fairings") + .field("attach", &debug_info(self, Kind::Attach)) + .field("launch", &debug_info(self, Kind::Launch)) + .field("request", &debug_info(self, Kind::Request)) + .field("response", &debug_info(self, Kind::Response)) + .finish() + } +} diff --git a/core/lib/src/fairing/info_kind.rs b/core/lib/src/fairing/info_kind.rs index 00dffb4b..10ec699c 100644 --- a/core/lib/src/fairing/info_kind.rs +++ b/core/lib/src/fairing/info_kind.rs @@ -22,7 +22,7 @@ use std::ops::BitOr; /// } /// # ; /// ``` -#[derive(Debug)] +#[derive(Debug, Copy, Clone)] pub struct Info { /// The name of the fairing. pub name: &'static str, diff --git a/core/lib/src/local/asynchronous/client.rs b/core/lib/src/local/asynchronous/client.rs index ad079533..d31fcfb4 100644 --- a/core/lib/src/local/asynchronous/client.rs +++ b/core/lib/src/local/asynchronous/client.rs @@ -35,7 +35,7 @@ use crate::error::Error; /// The following snippet creates a `Client` from a `Rocket` instance and /// dispatches a local `POST /` request with a body of `Hello, world!`. /// -/// ```rust +/// ```rust,no_run /// use rocket::local::asynchronous::Client; /// /// # rocket::async_test(async { @@ -69,8 +69,7 @@ impl Client { where F: FnOnce(&Self, LocalRequest<'_>, LocalResponse<'_>) -> T + Send { crate::async_test(async { - let rocket = crate::ignite(); - let client = Client::untracked(rocket).await.expect("valid rocket"); + let client = Client::debug(crate::ignite()).await.unwrap(); let request = client.get("/"); let response = request.clone().dispatch().await; f(&client, request, response) @@ -107,6 +106,12 @@ impl Client { pub_client_impl!("use rocket::local::asynchronous::Client;" @async await); } +impl std::fmt::Debug for Client { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self._rocket().fmt(f) + } +} + #[cfg(test)] mod test { #[test] diff --git a/core/lib/src/local/asynchronous/request.rs b/core/lib/src/local/asynchronous/request.rs index 628ab404..4d6c12d4 100644 --- a/core/lib/src/local/asynchronous/request.rs +++ b/core/lib/src/local/asynchronous/request.rs @@ -14,7 +14,7 @@ use super::{Client, LocalResponse}; /// The following snippet uses the available builder methods to construct and /// dispatch a `POST` request to `/` with a JSON body: /// -/// ```rust +/// ```rust,no_run /// use rocket::local::asynchronous::{Client, LocalRequest}; /// use rocket::http::{ContentType, Cookie}; /// diff --git a/core/lib/src/local/asynchronous/response.rs b/core/lib/src/local/asynchronous/response.rs index 194a5cea..5566841a 100644 --- a/core/lib/src/local/asynchronous/response.rs +++ b/core/lib/src/local/asynchronous/response.rs @@ -27,11 +27,10 @@ use crate::{Request, Response}; /// "Hello, world!" /// } /// -/// # /* /// #[launch] -/// # */ /// fn rocket() -> rocket::Rocket { /// rocket::ignite().mount("/", routes![hello_world]) +/// # .reconfigure(rocket::Config::debug_default()) /// } /// /// # async fn read_body_manually() -> io::Result<()> { diff --git a/core/lib/src/local/blocking/client.rs b/core/lib/src/local/blocking/client.rs index e99a6ab2..3a3f33ad 100644 --- a/core/lib/src/local/blocking/client.rs +++ b/core/lib/src/local/blocking/client.rs @@ -16,7 +16,7 @@ use crate::http::Method; /// The following snippet creates a `Client` from a `Rocket` instance and /// dispatches a local `POST /` request with a body of `Hello, world!`. /// -/// ```rust +/// ```rust,no_run /// use rocket::local::blocking::Client; /// /// let rocket = rocket::ignite(); @@ -47,8 +47,7 @@ impl Client { pub fn _test(f: F) -> T where F: FnOnce(&Self, LocalRequest<'_>, LocalResponse<'_>) -> T + Send { - let rocket = crate::ignite(); - let client = Client::untracked(rocket).expect("valid rocket"); + let client = Client::debug(crate::ignite()).unwrap(); let request = client.get("/"); let response = request.clone().dispatch(); f(&client, request, response) @@ -93,6 +92,12 @@ impl Client { pub_client_impl!("use rocket::local::blocking::Client;"); } +impl std::fmt::Debug for Client { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self._rocket().fmt(f) + } +} + impl Drop for Client { fn drop(&mut self) { let client = self.inner.take(); diff --git a/core/lib/src/local/blocking/request.rs b/core/lib/src/local/blocking/request.rs index 476fff39..c9d9815e 100644 --- a/core/lib/src/local/blocking/request.rs +++ b/core/lib/src/local/blocking/request.rs @@ -13,7 +13,7 @@ use super::{Client, LocalResponse}; /// The following snippet uses the available builder methods to construct and /// dispatch a `POST` request to `/` with a JSON body: /// -/// ```rust +/// ```rust,no_run /// use rocket::local::blocking::{Client, LocalRequest}; /// use rocket::http::{ContentType, Cookie}; /// diff --git a/core/lib/src/local/blocking/response.rs b/core/lib/src/local/blocking/response.rs index 400f35d5..da4ad766 100644 --- a/core/lib/src/local/blocking/response.rs +++ b/core/lib/src/local/blocking/response.rs @@ -24,11 +24,10 @@ use super::Client; /// "Hello, world!" /// } /// -/// # /* /// #[launch] -/// # */ /// fn rocket() -> rocket::Rocket { /// rocket::ignite().mount("/", routes![hello_world]) +/// # .reconfigure(rocket::Config::debug_default()) /// } /// /// # fn read_body_manually() -> io::Result<()> { diff --git a/core/lib/src/local/client.rs b/core/lib/src/local/client.rs index d5cc2adc..4523cd22 100644 --- a/core/lib/src/local/client.rs +++ b/core/lib/src/local/client.rs @@ -96,11 +96,17 @@ macro_rules! pub_client_impl { } #[doc(hidden)] - pub $($prefix)? fn debug(base: &str, routes: Vec) -> Result { - let mut config = crate::Config::debug_default(); + pub $($prefix)? fn debug_with(routes: Vec) -> Result { + let rocket = crate::custom(crate::Config::debug_default()); + Self::debug(rocket.mount("/", routes)) $(.$suffix)? + } + + #[doc(hidden)] + pub $($prefix)? fn debug(rocket: Rocket) -> Result { + let mut config = rocket.config().clone(); config.log_level = crate::config::LogLevel::Debug; - let rocket = crate::custom(config).mount(base, routes); - Self::tracked(rocket) $(.$suffix)? + config.profile = crate::Config::DEBUG_PROFILE; + Self::tracked(rocket.reconfigure(config)) $(.$suffix)? } /// Deprecated alias to [`Client::tracked()`]. @@ -117,7 +123,7 @@ macro_rules! pub_client_impl { /// /// # Example /// - /// ```rust,no_run + /// ```rust #[doc = $import] /// /// # Client::_test(|client, _, _| { @@ -196,5 +202,8 @@ macro_rules! pub_client_impl { fn _ensure_impls_exist() { fn is_send() {} is_send::(); + + fn is_debug() {} + is_debug::(); } }} diff --git a/core/lib/src/logger.rs b/core/lib/src/logger.rs index 70f1cffb..3c28d5d6 100644 --- a/core/lib/src/logger.rs +++ b/core/lib/src/logger.rs @@ -163,27 +163,25 @@ impl log::Log for RocketLogger { } } -pub(crate) fn try_init(level: LogLevel, colors: bool, verbose: bool) -> bool { - if level == LogLevel::Off { +pub(crate) fn init(config: &crate::Config) -> bool { + if config.log_level == LogLevel::Off { return false; } if !atty::is(atty::Stream::Stdout) || (cfg!(windows) && !Paint::enable_windows_ascii()) - || !colors + || !config.cli_colors { Paint::disable(); } - if let Err(e) = log::set_boxed_logger(Box::new(RocketLogger(level))) { - if verbose { + if let Err(e) = log::set_boxed_logger(Box::new(RocketLogger(config.log_level))) { + if config.log_level == LogLevel::Debug { eprintln!("Logger failed to initialize: {}", e); } - - return false; } - log::set_max_level(level.to_level_filter()); + log::set_max_level(config.log_level.to_level_filter()); true } @@ -199,11 +197,6 @@ impl PaintExt for Paint<&str> { } } -#[doc(hidden)] -pub fn init(level: LogLevel) -> bool { - try_init(level, true, true) -} - // Expose logging macros as (hidden) funcions for use by core/contrib codegen. macro_rules! external_log_function { ($fn_name:ident: $macro_name:ident) => ( diff --git a/core/lib/src/request/request.rs b/core/lib/src/request/request.rs index 6011792b..9526c919 100644 --- a/core/lib/src/request/request.rs +++ b/core/lib/src/request/request.rs @@ -104,7 +104,7 @@ impl<'r> Request<'r> { /// ```rust /// use rocket::http::Method; /// - /// # let c = rocket::local::blocking::Client::debug("/", vec![]).unwrap(); + /// # let c = rocket::local::blocking::Client::debug_with(vec![]).unwrap(); /// # let get = |uri| c.get(uri); /// # let post = |uri| c.post(uri); /// assert_eq!(get("/").method(), Method::Get); @@ -139,7 +139,7 @@ impl<'r> Request<'r> { /// # Example /// /// ```rust - /// # let c = rocket::local::blocking::Client::debug("/", vec![]).unwrap(); + /// # let c = rocket::local::blocking::Client::debug_with(vec![]).unwrap(); /// # let get = |uri| c.get(uri); /// assert_eq!(get("/hello/rocketeer").uri().path(), "/hello/rocketeer"); /// assert_eq!(get("/hello").uri().query(), None); @@ -231,7 +231,7 @@ impl<'r> Request<'r> { /// use std::net::Ipv4Addr; /// use rocket::http::Header; /// - /// # let c = rocket::local::blocking::Client::debug("/", vec![]).unwrap(); + /// # let c = rocket::local::blocking::Client::debug_with(vec![]).unwrap(); /// # let req = c.get("/"); /// assert_eq!(req.real_ip(), None); /// @@ -292,7 +292,7 @@ impl<'r> Request<'r> { /// ```rust /// use rocket::http::Cookie; /// - /// # let c = rocket::local::blocking::Client::debug("/", vec![]).unwrap(); + /// # let c = rocket::local::blocking::Client::debug_with(vec![]).unwrap(); /// # let request = c.get("/"); /// # let req = request.inner(); /// req.cookies().add(Cookie::new("key", "val")); @@ -312,7 +312,7 @@ impl<'r> Request<'r> { /// ```rust /// use rocket::http::{Accept, ContentType}; /// - /// # let c = rocket::local::blocking::Client::debug("/", vec![]).unwrap(); + /// # let c = rocket::local::blocking::Client::debug_with(vec![]).unwrap(); /// # let get = |uri| c.get(uri); /// assert!(get("/").headers().is_empty()); /// @@ -384,7 +384,7 @@ impl<'r> Request<'r> { /// ```rust /// use rocket::http::ContentType; /// - /// # let c = rocket::local::blocking::Client::debug("/", vec![]).unwrap(); + /// # let c = rocket::local::blocking::Client::debug_with(vec![]).unwrap(); /// # let get = |uri| c.get(uri); /// assert_eq!(get("/").content_type(), None); /// @@ -406,7 +406,7 @@ impl<'r> Request<'r> { /// ```rust /// use rocket::http::Accept; /// - /// # let c = rocket::local::blocking::Client::debug("/", vec![]).unwrap(); + /// # let c = rocket::local::blocking::Client::debug_with(vec![]).unwrap(); /// # let get = |uri| c.get(uri); /// assert_eq!(get("/").accept(), None); /// assert_eq!(get("/").header(Accept::JSON).accept(), Some(&Accept::JSON)); @@ -432,7 +432,7 @@ impl<'r> Request<'r> { /// /// ```rust /// use rocket::http::{Accept, ContentType, MediaType}; - /// # let c = rocket::local::blocking::Client::debug("/", vec![]).unwrap(); + /// # let c = rocket::local::blocking::Client::debug_with(vec![]).unwrap(); /// # let get = |uri| c.get(uri); /// # let post = |uri| c.post(uri); /// @@ -472,7 +472,7 @@ impl<'r> Request<'r> { /// # Example /// /// ```rust - /// # let c = rocket::local::blocking::Client::debug("/", vec![]).unwrap(); + /// # let c = rocket::local::blocking::Client::debug_with(vec![]).unwrap(); /// # let request = c.get("/"); /// let config = request.config(); /// ``` @@ -486,7 +486,7 @@ impl<'r> Request<'r> { /// /// ```rust /// use rocket::data::ToByteUnit; - /// # let c = rocket::local::blocking::Client::debug("/", vec![]).unwrap(); + /// # let c = rocket::local::blocking::Client::debug_with(vec![]).unwrap(); /// # let request = c.get("/"); /// /// // This is the default `form` limit. @@ -508,7 +508,7 @@ impl<'r> Request<'r> { /// # Example /// /// ```rust - /// # let c = rocket::local::blocking::Client::debug("/", vec![]).unwrap(); + /// # let c = rocket::local::blocking::Client::debug_with(vec![]).unwrap(); /// # let request = c.get("/"); /// let route = request.route(); /// ``` @@ -525,7 +525,7 @@ impl<'r> Request<'r> { /// ```rust /// # type User = rocket::http::Method; /// # rocket::async_test(async move { - /// # let c = rocket::local::asynchronous::Client::debug("/", vec![]).await.unwrap(); + /// # let c = rocket::local::asynchronous::Client::debug_with(vec![]).await.unwrap(); /// # let request = c.get("/"); /// let outcome = request.guard::().await; /// # }) @@ -541,7 +541,7 @@ impl<'r> Request<'r> { /// # Example /// /// ```rust - /// # let c = rocket::local::blocking::Client::debug("/", vec![]).unwrap(); + /// # let c = rocket::local::blocking::Client::debug_with(vec![]).unwrap(); /// # let request = c.get("/"); /// # type Pool = usize; /// let pool = request.managed_state::(); @@ -567,7 +567,7 @@ impl<'r> Request<'r> { /// # Example /// /// ```rust - /// # let c = rocket::local::blocking::Client::debug("/", vec![]).unwrap(); + /// # let c = rocket::local::blocking::Client::debug_with(vec![]).unwrap(); /// # let request = c.get("/"); /// // The first store into local cache for a given type wins. /// let value = request.local_cache(|| "hello"); @@ -602,7 +602,7 @@ impl<'r> Request<'r> { /// } /// /// # rocket::async_test(async move { - /// # let c = rocket::local::asynchronous::Client::debug("/", vec![]).await.unwrap(); + /// # let c = rocket::local::asynchronous::Client::debug_with(vec![]).await.unwrap(); /// # let request = c.get("/"); /// let current_user = request.local_cache_async(async { /// current_user(&request).await @@ -636,7 +636,7 @@ impl<'r> Request<'r> { /// # Example /// /// ```rust - /// # let c = rocket::local::blocking::Client::debug("/", vec![]).unwrap(); + /// # let c = rocket::local::blocking::Client::debug_with(vec![]).unwrap(); /// # let get = |uri| c.get(uri); /// assert_eq!(get("/a/b/c").param(0), Some(Ok("a"))); /// assert_eq!(get("/a/b/c").param(1), Some(Ok("b"))); @@ -674,7 +674,7 @@ impl<'r> Request<'r> { /// ```rust /// use std::path::PathBuf; /// - /// # let c = rocket::local::blocking::Client::debug("/", vec![]).unwrap(); + /// # let c = rocket::local::blocking::Client::debug_with(vec![]).unwrap(); /// # let get = |uri| c.get(uri); /// assert_eq!(get("/").segments(0..), Ok(PathBuf::new())); /// assert_eq!(get("/").segments(2..), Ok(PathBuf::new())); @@ -723,7 +723,7 @@ impl<'r> Request<'r> { /// age: usize /// } /// - /// # let c = rocket::local::blocking::Client::debug("/", vec![]).unwrap(); + /// # let c = rocket::local::blocking::Client::debug_with(vec![]).unwrap(); /// # let get = |uri| c.get(uri); /// let req = get("/?a=apple&z=zebra&a=aardvark"); /// assert_eq!(req.query_value::<&str>("a").unwrap(), Ok("apple")); diff --git a/core/lib/src/response/status.rs b/core/lib/src/response/status.rs index fa20d64d..b521a150 100644 --- a/core/lib/src/response/status.rs +++ b/core/lib/src/response/status.rs @@ -69,8 +69,7 @@ impl<'r, R> Created { /// status::Created::new("http://myservice.com/resource.json") /// } /// - /// # let rocket = rocket::ignite().mount("/", routes![create]); - /// # let client = Client::tracked(rocket).unwrap(); + /// # let client = Client::debug_with(routes![create]).unwrap(); /// let response = client.get("/").dispatch(); /// /// let loc = response.headers().get_one("Location"); @@ -98,8 +97,7 @@ impl<'r, R> Created { /// .body("{ 'resource': 'Hello, world!' }") /// } /// - /// # let rocket = rocket::ignite().mount("/", routes![create]); - /// # let client = Client::tracked(rocket).unwrap(); + /// # let client = Client::debug_with(routes![create]).unwrap(); /// let response = client.get("/").dispatch(); /// /// let loc = response.headers().get_one("Location"); @@ -131,8 +129,7 @@ impl<'r, R> Created { /// .tagged_body("{ 'resource': 'Hello, world!' }") /// } /// - /// # let rocket = rocket::ignite().mount("/", routes![create]); - /// # let client = Client::tracked(rocket).unwrap(); + /// # let client = Client::debug_with(routes![create]).unwrap(); /// let response = client.get("/").dispatch(); /// /// let loc = response.headers().get_one("Location"); diff --git a/core/lib/src/rocket.rs b/core/lib/src/rocket.rs index 9a7fd0a8..001fb7cd 100644 --- a/core/lib/src/rocket.rs +++ b/core/lib/src/rocket.rs @@ -18,6 +18,7 @@ use crate::error::{Error, ErrorKind}; /// The main `Rocket` type: used to mount routes and catchers and launch the /// application. +#[derive(Debug)] pub struct Rocket { pub(crate) config: Config, pub(crate) figment: Figment, @@ -53,6 +54,7 @@ impl Rocket { /// # }; /// ``` #[track_caller] + #[inline(always)] pub fn ignite() -> Rocket { Rocket::custom(Config::figment()) } @@ -63,10 +65,10 @@ impl Rocket { /// /// # Panics /// - /// If there is an error reading configuration sources, this function prints - /// a nice error message and then exits the process. + /// If there is an error reading a [`Config`] from `provider`, function + /// prints a nice error message and then exits the process. /// - /// # Examples + /// # Example /// /// ```rust /// use figment::{Figment, providers::{Toml, Env, Format}}; @@ -80,18 +82,17 @@ impl Rocket { /// rocket::custom(figment) /// } /// ``` - #[inline] #[track_caller] pub fn custom(provider: T) -> Rocket { - let (config, figment) = (Config::from(&provider), Figment::from(provider)); - logger::try_init(config.log_level, config.cli_colors, false); + let config = Config::from(&provider); + let figment = Figment::from(provider); + logger::init(&config); config.pretty_print(&figment); let managed_state = ::new(); let (shutdown_sender, shutdown_receiver) = mpsc::channel(1); Rocket { - config, figment, - managed_state, + config, figment, managed_state, shutdown_handle: Shutdown(shutdown_sender), router: Router::new(), default_catcher: None, @@ -101,6 +102,56 @@ impl Rocket { } } + /// Resets the configuration in `self` to that provided by `provider`. + /// + /// # Panics + /// + /// Like [`Rocket::custom()`], panics if `provider` does not provide a valid + /// [`Config`]. The error message is printed. + /// + /// # Examples + /// + /// To modify only some values, use the existing `config`: + /// + /// ```rust + /// use std::net::Ipv4Addr; + /// + /// let config = rocket::Config { + /// port: 7777, + /// address: Ipv4Addr::new(18, 127, 0, 1).into(), + /// ..rocket::Config::default() + /// }; + /// + /// let rocket = rocket::custom(&config); + /// assert_eq!(rocket.config().port, 7777); + /// assert_eq!(rocket.config().address, Ipv4Addr::new(18, 127, 0, 1)); + /// + /// // Modifying the existing config: + /// let mut new_config = rocket.config().clone(); + /// new_config.port = 8888; + /// + /// let rocket = rocket.reconfigure(new_config); + /// assert_eq!(rocket.config().port, 8888); + /// assert_eq!(rocket.config().address, Ipv4Addr::new(18, 127, 0, 1)); + /// + /// // Modifying the existing figment: + /// let mut new_figment = rocket.figment().clone() + /// .merge(("address", "171.64.200.10")); + /// + /// let rocket = rocket.reconfigure(new_figment); + /// assert_eq!(rocket.config().port, 8888); + /// assert_eq!(rocket.config().address, Ipv4Addr::new(171, 64, 200, 10)); + /// ``` + #[inline] + #[track_caller] + pub fn reconfigure(mut self, provider: T) -> Rocket { + self.config = Config::from(&provider); + self.figment = Figment::from(provider); + logger::init(&self.config); + self.config.pretty_print(&self.figment); + self + } + /// Mounts all of the routes in the supplied vector at the given `base` /// path. Mounting a route with path `path` at path `base` makes the route /// available at `base/path`. @@ -152,7 +203,6 @@ impl Rocket { /// # .launch().await; /// # }; /// ``` - #[inline] pub fn mount>>(mut self, base: &str, routes: R) -> Self { let base_uri = Origin::parse_owned(base.to_string()) .unwrap_or_else(|e| { @@ -210,7 +260,6 @@ impl Rocket { /// rocket::ignite().register(catchers![internal_error, not_found]) /// } /// ``` - #[inline] pub fn register(mut self, catchers: Vec) -> Self { info!("{}{}", Paint::emoji("👾 "), Paint::magenta("Catchers:")); @@ -294,7 +343,6 @@ impl Rocket { /// })) /// } /// ``` - #[inline] pub fn attach(mut self, fairing: F) -> Self { let future = async move { let fairing = Box::new(fairing); @@ -472,8 +520,10 @@ impl Rocket { self.shutdown_handle.clone() } - /// Perform "pre-launch" checks: verify that there are no routing colisions - /// and that there were no fairing failures. + /// Perform "pre-launch" checks: verify: + /// * there are no routing colisionns + /// * there were no fairing failures + /// * a secret key, if needed, is securely configured pub(crate) async fn prelaunch_check(&mut self) -> Result<(), Error> { if let Err(e) = self.router.collisions() { return Err(Error::new(ErrorKind::Collision(e))); @@ -483,6 +533,25 @@ impl Rocket { return Err(Error::new(ErrorKind::FailedFairings(failures.to_vec()))) } + #[cfg(feature = "secrets")] + if !self.config.secret_key.is_provided() { + let profile = self.figment.profile(); + if profile != Config::DEBUG_PROFILE { + return Err(Error::new(ErrorKind::InsecureSecretKey(profile.clone()))); + } else { + self.config.secret_key = crate::config::SecretKey::generate() + .unwrap_or(crate::config::SecretKey::zero()); + + warn!("secrets enabled without a configured `secret_key`"); + info_!("disable `secrets` feature or configure a `secret_key`"); + info_!("this becomes an {} in non-debug profiles", Paint::red("error")); + + if !self.config.secret_key.is_zero() { + warn_!("a random key has been generated for this launch"); + } + } + }; + Ok(()) } diff --git a/core/lib/src/router/mod.rs b/core/lib/src/router/mod.rs index b71e9eed..a67a1108 100644 --- a/core/lib/src/router/mod.rs +++ b/core/lib/src/router/mod.rs @@ -14,7 +14,7 @@ pub use self::segment::Segment; // type Selector = (Method, usize); type Selector = Method; -#[derive(Default)] +#[derive(Debug, Default)] pub struct Router { routes: HashMap>, } diff --git a/core/lib/tests/absolute-uris-okay-issue-443.rs b/core/lib/tests/absolute-uris-okay-issue-443.rs index 79432793..56b348b8 100644 --- a/core/lib/tests/absolute-uris-okay-issue-443.rs +++ b/core/lib/tests/absolute-uris-okay-issue-443.rs @@ -18,7 +18,7 @@ mod test_absolute_uris_okay { #[test] fn redirect_works() { - let client = Client::debug("/", routes![google, redirect]).unwrap(); + let client = Client::debug_with(routes![google, redirect]).unwrap(); let response = client.get("/google").dispatch(); let location = response.headers().get_one("Location"); diff --git a/core/lib/tests/catcher-cookies-1213.rs b/core/lib/tests/catcher-cookies-1213.rs index 877e30fa..3f491873 100644 --- a/core/lib/tests/catcher-cookies-1213.rs +++ b/core/lib/tests/catcher-cookies-1213.rs @@ -29,7 +29,7 @@ mod tests { req.cookies().add(Cookie::new("fairing", "woo")); }))); - let client = Client::tracked(rocket).unwrap(); + let client = Client::debug(rocket).unwrap(); // Check that the index returns the `index` and `fairing` cookie. let response = client.get("/").dispatch(); diff --git a/core/lib/tests/conditionally-set-server-header-996.rs b/core/lib/tests/conditionally-set-server-header-996.rs index 711d4ba8..25fe565d 100644 --- a/core/lib/tests/conditionally-set-server-header-996.rs +++ b/core/lib/tests/conditionally-set-server-header-996.rs @@ -19,8 +19,7 @@ mod conditionally_set_server_header { #[test] fn do_not_overwrite_server_header() { - let rocket = rocket::ignite().mount("/", routes![do_not_overwrite, use_default]); - let client = Client::tracked(rocket).unwrap(); + let client = Client::debug_with(routes![do_not_overwrite, use_default]).unwrap(); let response = client.get("/do_not_overwrite").dispatch(); let server = response.headers().get_one("Server"); diff --git a/core/lib/tests/derive-reexports.rs b/core/lib/tests/derive-reexports.rs index f3f46336..2f719f8f 100644 --- a/core/lib/tests/derive-reexports.rs +++ b/core/lib/tests/derive-reexports.rs @@ -45,8 +45,7 @@ fn number(params: ThingForm) -> DerivedResponder { fn test_derive_reexports() { use rocket::local::blocking::Client; - let rocket = rocket::ignite().mount("/", routes![index, number]); - let client = Client::tracked(rocket).unwrap(); + let client = Client::debug_with(routes![index, number]).unwrap(); let response = client.get("/").dispatch(); assert_eq!(response.into_string().unwrap(), "hello"); diff --git a/core/lib/tests/encoded-uris.rs b/core/lib/tests/encoded-uris.rs index 2be27b40..7adb6692 100644 --- a/core/lib/tests/encoded-uris.rs +++ b/core/lib/tests/encoded-uris.rs @@ -10,8 +10,7 @@ mod encoded_uris { #[test] fn can_route_to_encoded_uri() { - let rocket = rocket::ignite().mount("/", routes![super::index]); - let client = Client::untracked(rocket).unwrap(); + let client = Client::debug_with(routes![super::index]).unwrap(); let response = client.get("/hello%20s%C3%BCper%20%24?a&%3F&value=a+b") .dispatch() .into_string(); diff --git a/core/lib/tests/fairing_before_head_strip-issue-546.rs b/core/lib/tests/fairing_before_head_strip-issue-546.rs index 85380b28..5f2cce0d 100644 --- a/core/lib/tests/fairing_before_head_strip-issue-546.rs +++ b/core/lib/tests/fairing_before_head_strip-issue-546.rs @@ -40,7 +40,7 @@ mod fairing_before_head_strip { }) })); - let client = Client::tracked(rocket).unwrap(); + let client = Client::debug(rocket).unwrap(); let response = client.head("/").dispatch(); assert_eq!(response.status(), Status::Ok); assert!(response.body().is_none()); @@ -71,7 +71,7 @@ mod fairing_before_head_strip { }) })); - let client = Client::tracked(rocket).unwrap(); + let client = Client::debug(rocket).unwrap(); let response = client.head("/").dispatch(); assert_eq!(response.status(), Status::Ok); assert!(response.body().is_none()); diff --git a/core/lib/tests/flash-lazy-removes-issue-466.rs b/core/lib/tests/flash-lazy-removes-issue-466.rs index 44f3e9f5..7cf374a0 100644 --- a/core/lib/tests/flash-lazy-removes-issue-466.rs +++ b/core/lib/tests/flash-lazy-removes-issue-466.rs @@ -27,10 +27,9 @@ mod flash_lazy_remove_tests { #[test] fn test() { use super::*; - let r = rocket::ignite().mount("/", routes![set, unused, used]); - let client = Client::tracked(r).unwrap(); // Ensure the cookie's not there at first. + let client = Client::debug_with(routes![set, unused, used]).unwrap(); let response = client.get("/unused").dispatch(); assert_eq!(response.status(), Status::NotFound); diff --git a/core/lib/tests/form_method-issue-45.rs b/core/lib/tests/form_method-issue-45.rs index 8c876e23..ac704619 100644 --- a/core/lib/tests/form_method-issue-45.rs +++ b/core/lib/tests/form_method-issue-45.rs @@ -20,7 +20,7 @@ mod tests { #[test] fn method_eval() { - let client = Client::tracked(rocket::ignite().mount("/", routes![bug])).unwrap(); + let client = Client::debug_with(routes![bug]).unwrap(); let response = client.post("/") .header(ContentType::Form) .body("_method=patch&form_data=Form+data") @@ -31,7 +31,7 @@ mod tests { #[test] fn get_passes_through() { - let client = Client::tracked(rocket::ignite().mount("/", routes![bug])).unwrap(); + let client = Client::debug_with(routes![bug]).unwrap(); let response = client.get("/") .header(ContentType::Form) .body("_method=patch&form_data=Form+data") diff --git a/core/lib/tests/form_value_decoding-issue-82.rs b/core/lib/tests/form_value_decoding-issue-82.rs index 7adb16e0..e7848c16 100644 --- a/core/lib/tests/form_value_decoding-issue-82.rs +++ b/core/lib/tests/form_value_decoding-issue-82.rs @@ -14,7 +14,7 @@ mod tests { use rocket::http::Status; fn check_decoding(raw: &str, decoded: &str) { - let client = Client::tracked(rocket::ignite().mount("/", routes![bug])).unwrap(); + let client = Client::debug_with(routes![bug]).unwrap(); let response = client.post("/") .header(ContentType::Form) .body(format!("form_data={}", raw)) diff --git a/core/lib/tests/head_handling.rs b/core/lib/tests/head_handling.rs index 8daa3569..d381dd1e 100644 --- a/core/lib/tests/head_handling.rs +++ b/core/lib/tests/head_handling.rs @@ -30,7 +30,7 @@ mod head_handling_tests { #[test] fn auto_head() { - let client = Client::tracked(rocket::ignite().mount("/", routes())).unwrap(); + let client = Client::debug_with(routes()).unwrap(); let response = client.head("/").dispatch(); let content_type: Vec<_> = response.headers().get("Content-Type").collect(); @@ -46,7 +46,7 @@ mod head_handling_tests { #[test] fn user_head() { - let client = Client::tracked(rocket::ignite().mount("/", routes())).unwrap(); + let client = Client::debug_with(routes()).unwrap(); let response = client.head("/other").dispatch(); let content_type: Vec<_> = response.headers().get("Content-Type").collect(); diff --git a/core/lib/tests/limits.rs b/core/lib/tests/limits.rs index 53a9bb8f..a5499ad7 100644 --- a/core/lib/tests/limits.rs +++ b/core/lib/tests/limits.rs @@ -14,17 +14,14 @@ mod limits_tests { use rocket::data::Limits; fn rocket_with_forms_limit(limit: u64) -> rocket::Rocket { - let config = rocket::Config { - limits: Limits::default().limit("form", limit.into()), - ..rocket::Config::debug_default() - }; - + let mut config = rocket::Config::debug_default(); + config.limits = Limits::default().limit("form", limit.into()); rocket::custom(config).mount("/", routes![super::index]) } #[test] fn large_enough() { - let client = Client::tracked(rocket_with_forms_limit(128)).unwrap(); + let client = Client::debug(rocket_with_forms_limit(128)).unwrap(); let response = client.post("/") .body("value=Hello+world") .header(ContentType::Form) @@ -35,7 +32,7 @@ mod limits_tests { #[test] fn just_large_enough() { - let client = Client::tracked(rocket_with_forms_limit(17)).unwrap(); + let client = Client::debug(rocket_with_forms_limit(17)).unwrap(); let response = client.post("/") .body("value=Hello+world") .header(ContentType::Form) @@ -46,7 +43,7 @@ mod limits_tests { #[test] fn much_too_small() { - let client = Client::tracked(rocket_with_forms_limit(4)).unwrap(); + let client = Client::debug(rocket_with_forms_limit(4)).unwrap(); let response = client.post("/") .body("value=Hello+world") .header(ContentType::Form) @@ -57,7 +54,7 @@ mod limits_tests { #[test] fn contracted() { - let client = Client::tracked(rocket_with_forms_limit(10)).unwrap(); + let client = Client::debug(rocket_with_forms_limit(10)).unwrap(); let response = client.post("/") .body("value=Hello+world") .header(ContentType::Form) diff --git a/core/lib/tests/local-client-access-runtime-in-drop.rs b/core/lib/tests/local-client-access-runtime-in-drop.rs index d1be0276..6b67ab42 100644 --- a/core/lib/tests/local-client-access-runtime-in-drop.rs +++ b/core/lib/tests/local-client-access-runtime-in-drop.rs @@ -10,5 +10,5 @@ impl Drop for SpawnBlockingOnDrop { #[test] fn test_access_runtime_in_state_drop() { - Client::tracked(rocket::ignite().manage(SpawnBlockingOnDrop)).unwrap(); + Client::debug(rocket::ignite().manage(SpawnBlockingOnDrop)).unwrap(); } diff --git a/core/lib/tests/local-request-content-type-issue-505.rs b/core/lib/tests/local-request-content-type-issue-505.rs index eaebe0a6..8310e431 100644 --- a/core/lib/tests/local-request-content-type-issue-505.rs +++ b/core/lib/tests/local-request-content-type-issue-505.rs @@ -54,7 +54,7 @@ mod local_request_content_type_tests { #[test] fn has_no_ct() { - let client = Client::tracked(rocket()).unwrap(); + let client = Client::debug(rocket()).unwrap(); let req = client.post("/"); assert_eq!(req.clone().dispatch().into_string(), Some("Absent".to_string())); @@ -69,7 +69,7 @@ mod local_request_content_type_tests { #[test] fn has_ct() { - let client = Client::tracked(rocket()).unwrap(); + let client = Client::debug(rocket()).unwrap(); let req = client.post("/").header(ContentType::JSON); assert_eq!(req.clone().dispatch().into_string(), Some("Present".to_string())); diff --git a/core/lib/tests/local_request_private_cookie-issue-368.rs b/core/lib/tests/local_request_private_cookie-issue-368.rs index 14a7d91c..cf4b25e2 100644 --- a/core/lib/tests/local_request_private_cookie-issue-368.rs +++ b/core/lib/tests/local_request_private_cookie-issue-368.rs @@ -20,7 +20,7 @@ mod tests { fn private_cookie_is_returned() { let rocket = rocket::ignite().mount("/", routes![return_private_cookie]); - let client = Client::tracked(rocket).unwrap(); + let client = Client::debug(rocket).unwrap(); let req = client.get("/").private_cookie(Cookie::new("cookie_name", "cookie_value")); let response = req.dispatch(); @@ -32,7 +32,7 @@ mod tests { fn regular_cookie_is_not_returned() { let rocket = rocket::ignite().mount("/", routes![return_private_cookie]); - let client = Client::tracked(rocket).unwrap(); + let client = Client::debug(rocket).unwrap(); let req = client.get("/").cookie(Cookie::new("cookie_name", "cookie_value")); let response = req.dispatch(); diff --git a/core/lib/tests/many-cookie-jars-at-once.rs b/core/lib/tests/many-cookie-jars-at-once.rs index 68febbd8..9dd1fa82 100644 --- a/core/lib/tests/many-cookie-jars-at-once.rs +++ b/core/lib/tests/many-cookie-jars-at-once.rs @@ -28,7 +28,7 @@ mod many_cookie_jars_tests { #[test] fn test_mutli_add() { - let client = Client::tracked(rocket()).unwrap(); + let client = Client::debug(rocket()).unwrap(); let response = client.post("/").dispatch(); let cookies = response.cookies(); assert_eq!(cookies.iter().count(), 2); @@ -38,7 +38,7 @@ mod many_cookie_jars_tests { #[test] fn test_mutli_get() { - let client = Client::tracked(rocket()).unwrap(); + let client = Client::debug(rocket()).unwrap(); let response = client.get("/") .cookie(Cookie::new("a", "a_val")) .cookie(Cookie::new("b", "hi!")) diff --git a/core/lib/tests/mapped-base-issue-1262.rs b/core/lib/tests/mapped-base-issue-1262.rs index 2cfa23dc..9d9fcd23 100644 --- a/core/lib/tests/mapped-base-issue-1262.rs +++ b/core/lib/tests/mapped-base-issue-1262.rs @@ -30,7 +30,7 @@ mod mapped_base_tests { #[test] fn only_prefix() { - let client = Client::tracked(super::rocket()).unwrap(); + let client = Client::debug(super::rocket()).unwrap(); let response = client.get("/a/b/3").dispatch(); assert_eq!(response.into_string().unwrap(), "3"); @@ -44,7 +44,7 @@ mod mapped_base_tests { #[test] fn prefix_and_base() { - let client = Client::tracked(super::rocket()).unwrap(); + let client = Client::debug(super::rocket()).unwrap(); let response = client.get("/foo/a/b/23").dispatch(); assert_eq!(response.into_string().unwrap(), "23"); diff --git a/core/lib/tests/nested-fairing-attaches.rs b/core/lib/tests/nested-fairing-attaches.rs index b959453d..053c0027 100644 --- a/core/lib/tests/nested-fairing-attaches.rs +++ b/core/lib/tests/nested-fairing-attaches.rs @@ -46,7 +46,7 @@ mod nested_fairing_attaches_tests { #[test] fn test_counts() { - let client = Client::tracked(rocket()).unwrap(); + let client = Client::debug(rocket()).unwrap(); let response = client.get("/").dispatch(); assert_eq!(response.into_string(), Some("1, 1".into())); diff --git a/core/lib/tests/on_launch_fairing_can_inspect_port.rs b/core/lib/tests/on_launch_fairing_can_inspect_port.rs index 7ec0c61a..823f9b57 100644 --- a/core/lib/tests/on_launch_fairing_can_inspect_port.rs +++ b/core/lib/tests/on_launch_fairing_can_inspect_port.rs @@ -5,7 +5,7 @@ use rocket::futures::channel::oneshot; #[rocket::async_test] async fn on_launch_fairing_can_inspect_port() { let (tx, rx) = oneshot::channel(); - let rocket = rocket::custom(Config { port: 0, ..Default::default() }) + let rocket = rocket::custom(Config { port: 0, ..Config::debug_default() }) .attach(AdHoc::on_launch("Send Port -> Channel", move |rocket| { tx.send(rocket.config().port).unwrap(); })); diff --git a/core/lib/tests/panic-handling.rs b/core/lib/tests/panic-handling.rs index 1c41915d..68f086b7 100644 --- a/core/lib/tests/panic-handling.rs +++ b/core/lib/tests/panic-handling.rs @@ -32,7 +32,7 @@ fn rocket() -> Rocket { #[test] fn catches_route_panic() { - let client = Client::untracked(rocket()).unwrap(); + let client = Client::debug(rocket()).unwrap(); let response = client.get("/panic").dispatch(); assert_eq!(response.status(), Status::InternalServerError); assert_eq!(response.into_string().unwrap(), "Hey, sorry! :("); @@ -40,7 +40,7 @@ fn catches_route_panic() { } #[test] fn catches_catcher_panic() { - let client = Client::untracked(rocket()).unwrap(); + let client = Client::debug(rocket()).unwrap(); let response = client.get("/noroute").dispatch(); assert_eq!(response.status(), Status::InternalServerError); assert_eq!(response.into_string().unwrap(), "Hey, sorry! :("); @@ -49,7 +49,7 @@ fn catches_catcher_panic() { #[test] fn catches_double_panic() { let rocket = rocket().register(catchers![double_panic]); - let client = Client::untracked(rocket).unwrap(); + let client = Client::debug(rocket).unwrap(); let response = client.get("/noroute").dispatch(); assert_eq!(response.status(), Status::InternalServerError); assert!(!response.into_string().unwrap().contains(":(")); diff --git a/core/lib/tests/precise-content-type-matching.rs b/core/lib/tests/precise-content-type-matching.rs index 599b359a..b6e9c92c 100644 --- a/core/lib/tests/precise-content-type-matching.rs +++ b/core/lib/tests/precise-content-type-matching.rs @@ -35,7 +35,7 @@ mod tests { macro_rules! check_dispatch { ($mount:expr, $ct:expr, $body:expr) => ( - let client = Client::tracked(rocket()).unwrap(); + let client = Client::debug(rocket()).unwrap(); let mut req = client.post($mount); let ct: Option = $ct; if let Some(ct) = ct { diff --git a/core/lib/tests/redirect_from_catcher-issue-113.rs b/core/lib/tests/redirect_from_catcher-issue-113.rs index 9867e548..c34c2a6f 100644 --- a/core/lib/tests/redirect_from_catcher-issue-113.rs +++ b/core/lib/tests/redirect_from_catcher-issue-113.rs @@ -14,7 +14,7 @@ mod tests { #[test] fn error_catcher_redirect() { - let client = Client::tracked(rocket::ignite().register(catchers![not_found])).unwrap(); + let client = Client::debug(rocket::ignite().register(catchers![not_found])).unwrap(); let response = client.get("/unknown").dispatch(); let location: Vec<_> = response.headers().get("location").collect(); diff --git a/core/lib/tests/replace-content-type-518.rs b/core/lib/tests/replace-content-type-518.rs index 3ed4b9a7..a985e2b2 100644 --- a/core/lib/tests/replace-content-type-518.rs +++ b/core/lib/tests/replace-content-type-518.rs @@ -22,7 +22,7 @@ fn rocket() -> rocket::Rocket { #[test] fn check_fairing_changes_content_type() { - let client = Client::untracked(rocket()).unwrap(); + let client = Client::debug(rocket()).unwrap(); let response = client.post("/").header(ContentType::PNG).dispatch(); assert_eq!(response.into_string().unwrap(), "other"); diff --git a/core/lib/tests/route_guard.rs b/core/lib/tests/route_guard.rs index 17d45169..14e6120f 100644 --- a/core/lib/tests/route_guard.rs +++ b/core/lib/tests/route_guard.rs @@ -24,7 +24,7 @@ mod route_guard_tests { .mount("/first", routes![files]) .mount("/second", routes![files]); - let client = Client::tracked(rocket).unwrap(); + let client = Client::debug(rocket).unwrap(); assert_path(&client, "/first/some/path"); assert_path(&client, "/second/some/path"); assert_path(&client, "/first/second/b/c"); diff --git a/core/lib/tests/segments-issues-41-86.rs b/core/lib/tests/segments-issues-41-86.rs index 680c8019..702f874d 100644 --- a/core/lib/tests/segments-issues-41-86.rs +++ b/core/lib/tests/segments-issues-41-86.rs @@ -36,7 +36,7 @@ mod tests { let rocket = rocket::ignite() .mount("/", routes![test, two, one_two, none, dual]) .mount("/point", routes![test, two, one_two, dual]); - let client = Client::tracked(rocket).unwrap(); + let client = Client::debug(rocket).unwrap(); // We construct a path that matches each of the routes above. We ensure the // prefix is stripped, confirming that dynamic segments are working. diff --git a/core/lib/tests/session-cookies-issue-1506.rs b/core/lib/tests/session-cookies-issue-1506.rs index c47917cb..d26a55e3 100644 --- a/core/lib/tests/session-cookies-issue-1506.rs +++ b/core/lib/tests/session-cookies-issue-1506.rs @@ -15,7 +15,7 @@ mod test_session_cookies { #[test] fn session_cookie_is_session() { let rocket = rocket::ignite().mount("/", rocket::routes![index]); - let client = Client::tracked(rocket).unwrap(); + let client = Client::debug(rocket).unwrap(); let response = client.get("/").dispatch(); let cookie = response.cookies().get_private("key").unwrap(); diff --git a/core/lib/tests/strict_and_lenient_forms.rs b/core/lib/tests/strict_and_lenient_forms.rs index 37f8bbcf..69d16af9 100644 --- a/core/lib/tests/strict_and_lenient_forms.rs +++ b/core/lib/tests/strict_and_lenient_forms.rs @@ -25,7 +25,7 @@ mod strict_and_lenient_forms_tests { const FIELD_VALUE: &str = "just_some_value"; fn client() -> Client { - Client::tracked(rocket::ignite().mount("/", routes![strict, lenient])).unwrap() + Client::debug_with(routes![strict, lenient]).unwrap() } #[test] diff --git a/core/lib/tests/unsound-local-request-1312.rs b/core/lib/tests/unsound-local-request-1312.rs index dd91db83..4ad3b15e 100644 --- a/core/lib/tests/unsound-local-request-1312.rs +++ b/core/lib/tests/unsound-local-request-1312.rs @@ -3,7 +3,7 @@ use rocket::local::blocking::Client; #[test] fn test_local_request_clone_soundness() { - let client = Client::tracked(rocket::ignite()).unwrap(); + let client = Client::debug_with(vec![]).unwrap(); // creates two LocalRequest instances that shouldn't share the same req let r1 = client.get("/").header(Header::new("key", "val1")); diff --git a/core/lib/tests/untracked-vs-tracked.rs b/core/lib/tests/untracked-vs-tracked.rs index 05b9ae5e..05d94b4b 100644 --- a/core/lib/tests/untracked-vs-tracked.rs +++ b/core/lib/tests/untracked-vs-tracked.rs @@ -19,7 +19,8 @@ mod many_cookie_jars_tests { use rocket::http::Status; fn rocket() -> rocket::Rocket { - rocket::ignite().mount("/", routes![add, get]) + rocket::custom(rocket::Config::debug_default()) + .mount("/", routes![add, get]) } #[test] diff --git a/core/lib/tests/uri-percent-encoding-issue-808.rs b/core/lib/tests/uri-percent-encoding-issue-808.rs index 1ec976e1..ec2cdb84 100644 --- a/core/lib/tests/uri-percent-encoding-issue-808.rs +++ b/core/lib/tests/uri-percent-encoding-issue-808.rs @@ -33,7 +33,7 @@ mod tests { #[test] fn uri_percent_encoding_redirect() { let expected_location = vec!["/hello/John%5B%5D%7C%5C%25@%5E"]; - let client = Client::tracked(rocket()).unwrap(); + let client = Client::debug(rocket()).unwrap(); let response = client.get("/raw").dispatch(); let location: Vec<_> = response.headers().get("location").collect(); @@ -48,7 +48,7 @@ mod tests { #[test] fn uri_percent_encoding_get() { - let client = Client::tracked(rocket()).unwrap(); + let client = Client::debug(rocket()).unwrap(); let name = Uri::percent_encode(NAME); let response = client.get(format!("/hello/{}", name)).dispatch(); assert_eq!(response.status(), Status::Ok); diff --git a/scripts/config.sh b/scripts/config.sh index 26b9b7a8..e5206c80 100755 --- a/scripts/config.sh +++ b/scripts/config.sh @@ -47,6 +47,7 @@ CORE_CODEGEN_ROOT=$(relative "core/codegen") || exit $? CORE_HTTP_ROOT=$(relative "core/http") || exit $? CONTRIB_LIB_ROOT=$(relative "contrib/lib") || exit $? CONTRIB_CODEGEN_ROOT=$(relative "contrib/codegen") || exit $? +GUIDE_TESTS_ROOT=$(relative "site/tests") || exit $? # Root of infrastructure directories. EXAMPLES_DIR=$(relative "examples") || exit $? @@ -97,6 +98,7 @@ function print_environment() { echo " CORE_HTTP_ROOT: ${CORE_HTTP_ROOT}" echo " CONTRIB_LIB_ROOT: ${CONTRIB_LIB_ROOT}" echo " CONTRIB_CODEGEN_ROOT: ${CONTRIB_CODEGEN_ROOT}" + echo " GUIDE_TESTS_ROOT: ${GUIDE_TESTS_ROOT}" echo " EXAMPLES_DIR: ${EXAMPLES_DIR}" echo " DOC_DIR: ${DOC_DIR}" echo " ALL_PROJECT_DIRS: ${ALL_PROJECT_DIRS[*]}" diff --git a/scripts/publish.sh b/scripts/publish.sh index 1f10421d..a063e02d 100755 --- a/scripts/publish.sh +++ b/scripts/publish.sh @@ -23,11 +23,10 @@ if ! [ -z "$(git status --porcelain)" ]; then fi # Ensure everything passes before trying to publish. -echo ":::: Running test suite..." +echo ":::: Running complete test suite..." cargo clean -bash "${SCRIPT_DIR}/test.sh" -bash "${SCRIPT_DIR}/test.sh" --contrib -bash "${SCRIPT_DIR}/test.sh" --release +bash "${SCRIPT_DIR}/test.sh" --all +bash "${SCRIPT_DIR}/test.sh" --all --release # Temporarily remove dev-dependencies so crates.io verifies. echo ":::: Stripping [dev-dependencies]..." diff --git a/scripts/test.sh b/scripts/test.sh index 98117da0..6f99be28 100755 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -10,9 +10,6 @@ export PATH=${HOME}/.cargo/bin:${PATH} export CARGO_INCREMENTAL=0 CARGO="cargo" -# We set a `cfg` so that a missing `secret_key` doesn't abort tests. -export RUSTFLAGS="--cfg rocket_unsafe_secret_key" - # Checks that the versions for Cargo projects $@ all match function check_versions_match() { local last_version="" @@ -54,40 +51,7 @@ function ensure_trailing_whitespace_free() { fi } -if [[ $1 == +* ]]; then - CARGO="$CARGO $1" - shift -fi - -# The kind of test we'll be running. -TEST_KIND="all" - -if [[ "$1" == "--contrib" ]] || [[ "$1" == "--core" ]]; then - TEST_KIND=${1#"--"} - shift -fi - -echo ":: Preparing. Environment is..." -print_environment -echo " CARGO: $CARGO" -echo " RUSTFLAGS: $RUSTFLAGS" -echo " EXTRA FLAGS: $@" - -echo ":: Ensuring all crate versions match..." -check_versions_match "${ALL_PROJECT_DIRS[@]}" - -echo ":: Checking for tabs..." -ensure_tab_free - -echo ":: Checking for trailing whitespace..." -ensure_trailing_whitespace_free - -echo ":: Updating dependencies..." -if ! $CARGO update ; then - echo " WARNING: Update failed! Proceeding with possibly outdated deps..." -fi - -if [ $TEST_KIND = "contrib" ]; then +function test_contrib() { FEATURES=( json msgpack @@ -106,18 +70,21 @@ if [ $TEST_KIND = "contrib" ]; then gzip_compression ) + echo ":: Building and testing contrib [default]..." + pushd "${CONTRIB_LIB_ROOT}" > /dev/null 2>&1 - echo ":: Building and testing contrib [default]..." - $CARGO test $@ + $CARGO test $@ - for feature in "${FEATURES[@]}"; do - echo ":: Building and testing contrib [${feature}]..." - $CARGO test --no-default-features --features "${feature}" $@ - done + for feature in "${FEATURES[@]}"; do + echo ":: Building and testing contrib [${feature}]..." + $CARGO test --no-default-features --features "${feature}" $@ + done popd > /dev/null 2>&1 -elif [ $TEST_KIND = "core" ]; then +} + +function test_core() { FEATURES=( secrets tls @@ -125,16 +92,97 @@ elif [ $TEST_KIND = "core" ]; then pushd "${CORE_LIB_ROOT}" > /dev/null 2>&1 - echo ":: Building and testing core [no features]..." - $CARGO test --no-default-features $@ + echo ":: Building and testing core [no features]..." + $CARGO test --no-default-features $@ - for feature in "${FEATURES[@]}"; do - echo ":: Building and testing core [${feature}]..." - $CARGO test --no-default-features --features "${feature}" $@ - done + for feature in "${FEATURES[@]}"; do + echo ":: Building and testing core [${feature}]..." + $CARGO test --no-default-features --features "${feature}" $@ + done popd > /dev/null 2>&1 -else - echo ":: Building and testing libraries..." - $CARGO test --all-features --all $@ +} + +function test_examples() { + for dir in $(find "${EXAMPLES_DIR}" -maxdepth 1 -mindepth 1 -type d); do + echo ":: Building and testing example [${dir#"${EXAMPLES_DIR}/"}]..." + + pushd "${dir}" > /dev/null 2>&1 + $CARGO test $@ + popd > /dev/null 2>&1 + done +} + +function test_guide() { + echo ":: Building and testing guide..." + + pushd "${GUIDE_TESTS_ROOT}" > /dev/null 2>&1 + $CARGO test $@ + popd > /dev/null 2>&1 +} + +function test_default() { + for project in "${ALL_PROJECT_DIRS[@]}"; do + echo ":: Building and testing ${project#"${PROJECT_ROOT}/"}..." + + pushd "${project}" > /dev/null 2>&1 + $CARGO test --all-features $@ + popd > /dev/null 2>&1 + done +} + +if [[ $1 == +* ]]; then + CARGO="$CARGO $1" + shift fi + +# The kind of test we'll be running. +TEST_KIND="default" +KINDS=("contrib" "core" "examples" "guide" "all") + +if [[ " ${KINDS[@]} " =~ " ${1#"--"} " ]]; then + TEST_KIND=${1#"--"} + shift +fi + +echo ":: Preparing. Environment is..." +print_environment +echo " CARGO: $CARGO" +echo " EXTRA FLAGS: $@" + +echo ":: Ensuring all crate versions match..." +check_versions_match "${ALL_PROJECT_DIRS[@]}" + +echo ":: Checking for tabs..." +ensure_tab_free + +echo ":: Checking for trailing whitespace..." +ensure_trailing_whitespace_free + +echo ":: Updating dependencies..." +if ! $CARGO update ; then + echo " WARNING: Update failed! Proceeding with possibly outdated deps..." +fi + +case $TEST_KIND in + contrib) test_contrib $@ ;; + core) test_core $@ ;; + examples) test_examples $@ ;; + guide) test_guide $@ ;; + default) + test_examples $@ & examples=$! + test_default $@ & default=$! + test_guide $@ & guide=$! + + wait $examples && wait $default && wait $guide + ;; + all) + test_core $@ & core=$! + test_contrib $@ & contrib=$! + test_examples $@ & examples=$! + test_default $@ & default=$! + test_guide $@ & guide=$! + + wait $core && wait $contrib && wait $examples && wait $default && wait $guide + ;; +esac diff --git a/site/guide/8-testing.md b/site/guide/8-testing.md index 5bfc2de1..e5da4bc3 100644 --- a/site/guide/8-testing.md +++ b/site/guide/8-testing.md @@ -14,14 +14,14 @@ instance. Usage is straightforward: 1. Construct a `Rocket` instance that represents the application. - ```rust + ```rust,no_run let rocket = rocket::ignite(); # let _ = rocket; ``` 2. Construct a `Client` using the `Rocket` instance. - ```rust + ```rust,no_run # use rocket::local::blocking::Client; # let rocket = rocket::ignite(); let client = Client::tracked(rocket).unwrap(); @@ -30,7 +30,7 @@ instance. Usage is straightforward: 3. Construct requests using the `Client` instance. - ```rust + ```rust,no_run # use rocket::local::blocking::Client; # let rocket = rocket::ignite(); # let client = Client::tracked(rocket).unwrap(); @@ -40,7 +40,7 @@ instance. Usage is straightforward: 4. Dispatch the request to retrieve the response. - ```rust + ```rust,no_run # use rocket::local::blocking::Client; # let rocket = rocket::ignite(); # let client = Client::tracked(rocket).unwrap(); @@ -97,11 +97,11 @@ These methods are typically used in combination with the `assert_eq!` or # .finalize() # } -use rocket::local::blocking::Client; +# use rocket::local::blocking::Client; use rocket::http::{ContentType, Status}; -let rocket = rocket::ignite().mount("/", routes![hello]); -let client = Client::tracked(rocket).expect("valid rocket instance"); +# let rocket = rocket::ignite().mount("/", routes![hello]); +# let client = Client::debug(rocket).expect("valid rocket instance"); let mut response = client.get("/").dispatch(); assert_eq!(response.status(), Status::Ok); @@ -165,7 +165,9 @@ To test our "Hello, world!" application, we create a `Client` for our testing: we _want_ our tests to panic when something goes wrong. ```rust -# fn rocket() -> rocket::Rocket { rocket::ignite() } +# fn rocket() -> rocket::Rocket { +# rocket::ignite().reconfigure(rocket::Config::debug_default()) +# } # use rocket::local::blocking::Client; let client = Client::tracked(rocket()).expect("valid rocket instance"); @@ -175,7 +177,9 @@ Then, we create a new `GET /` request and dispatch it, getting back our application's response: ```rust -# fn rocket() -> rocket::Rocket { rocket::ignite() } +# fn rocket() -> rocket::Rocket { +# rocket::ignite().reconfigure(rocket::Config::debug_default()) +# } # use rocket::local::blocking::Client; # let client = Client::tracked(rocket()).expect("valid rocket instance"); let mut response = client.get("/").dispatch(); @@ -199,7 +203,7 @@ We do this by checking the `Response` object directly: use rocket::http::{ContentType, Status}; # # let rocket = rocket::ignite().mount("/", routes![hello]); -# let client = Client::tracked(rocket).expect("valid rocket instance"); +# let client = Client::debug(rocket).expect("valid rocket instance"); # let mut response = client.get("/").dispatch(); assert_eq!(response.status(), Status::Ok); @@ -232,7 +236,10 @@ mod test { #[test] # */ pub fn hello_world() { + # /* let client = Client::tracked(rocket()).expect("valid rocket instance"); + # */ + # let client = Client::debug(rocket()).expect("valid rocket instance"); let mut response = client.get("/").dispatch(); assert_eq!(response.status(), Status::Ok); assert_eq!(response.into_string(), Some("Hello, world!".into())); diff --git a/site/tests/Cargo.toml b/site/tests/Cargo.toml index bf59fd61..83db72f2 100644 --- a/site/tests/Cargo.toml +++ b/site/tests/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rocket_guide_tests" -version = "0.0.0" +version = "0.5.0-dev" workspace = "../../" edition = "2018" publish = false diff --git a/site/tests/src/lib.rs b/site/tests/src/lib.rs index ebbc54ef..f237442a 100644 --- a/site/tests/src/lib.rs +++ b/site/tests/src/lib.rs @@ -50,5 +50,5 @@ macro_rules! assert_form_parses_ok { } pub fn client(routes: Vec) -> rocket::local::blocking::Client { - rocket::local::blocking::Client::debug("/", routes).unwrap() + rocket::local::blocking::Client::debug_with(routes).unwrap() }