diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/archive.rs | 58 | ||||
-rw-r--r-- | tests/auth.rs | 140 | ||||
-rw-r--r-- | tests/data/cert.pem | 29 | ||||
-rwxr-xr-x | tests/data/generate_tls_certs.sh | 2 | ||||
-rw-r--r-- | tests/data/key.pem | 52 | ||||
-rw-r--r-- | tests/fixtures/mod.rs | 116 | ||||
-rw-r--r-- | tests/header.rs | 24 | ||||
-rw-r--r-- | tests/navigation.rs | 103 | ||||
-rw-r--r-- | tests/qrcode.rs | 59 | ||||
-rw-r--r-- | tests/serve_request.rs | 114 | ||||
-rw-r--r-- | tests/tls.rs | 53 | ||||
-rw-r--r-- | tests/upload_files.rs | 48 |
12 files changed, 355 insertions, 443 deletions
diff --git a/tests/archive.rs b/tests/archive.rs index 6a7f8bf..b8def22 100644 --- a/tests/archive.rs +++ b/tests/archive.rs @@ -1,30 +1,15 @@ mod fixtures; -use assert_cmd::prelude::*; -use assert_fs::fixture::TempDir; -use fixtures::{port, tmpdir, Error}; +use fixtures::{server, Error, TestServer}; use reqwest::StatusCode; use rstest::rstest; use select::document::Document; use select::predicate::Text; -use std::process::{Command, Stdio}; -use std::thread::sleep; -use std::time::Duration; #[rstest] -fn archives_are_disabled(tmpdir: TempDir, port: u16) -> Result<(), Error> { - let mut child = Command::cargo_bin("miniserve")? - .arg(tmpdir.path()) - .arg("-p") - .arg(port.to_string()) - .stdout(Stdio::null()) - .spawn()?; - - sleep(Duration::from_secs(1)); - +fn archives_are_disabled(server: TestServer) -> Result<(), Error> { // Ensure the links to the archives are not present - let body = reqwest::blocking::get(format!("http://localhost:{}", port).as_str())? - .error_for_status()?; + let body = reqwest::blocking::get(server.url())?.error_for_status()?; let parsed = Document::from_read(body)?; assert!(parsed .find(Text) @@ -32,63 +17,42 @@ fn archives_are_disabled(tmpdir: TempDir, port: u16) -> Result<(), Error> { // Try to download anyway, ensure it's forbidden assert_eq!( - reqwest::blocking::get(format!("http://localhost:{}/?download=tar_gz", port).as_str())? - .status(), + reqwest::blocking::get(server.url().join("?download=tar_gz")?)?.status(), StatusCode::FORBIDDEN ); assert_eq!( - reqwest::blocking::get(format!("http://localhost:{}/?download=tar", port).as_str())? - .status(), + reqwest::blocking::get(server.url().join("?download=tar")?)?.status(), StatusCode::FORBIDDEN ); assert_eq!( - reqwest::blocking::get(format!("http://localhost:{}/?download=zip", port).as_str())? - .status(), + reqwest::blocking::get(server.url().join("?download=zip")?)?.status(), StatusCode::FORBIDDEN ); - child.kill()?; - Ok(()) } #[rstest] -fn test_tar_archives(tmpdir: TempDir, port: u16) -> Result<(), Error> { - let mut child = Command::cargo_bin("miniserve")? - .arg(tmpdir.path()) - .arg("-p") - .arg(port.to_string()) - .arg("-g") - .stdout(Stdio::null()) - .spawn()?; - - sleep(Duration::from_secs(1)); - +fn test_tar_archives(#[with(&["-g"])] server: TestServer) -> Result<(), Error> { // Ensure the links to the tar archive exists and tar not exists - let body = reqwest::blocking::get(format!("http://localhost:{}", port).as_str())? - .error_for_status()?; + let body = reqwest::blocking::get(server.url())?.error_for_status()?; let parsed = Document::from_read(body)?; assert!(parsed.find(Text).any(|x| x.text() == "Download .tar.gz")); assert!(parsed.find(Text).all(|x| x.text() != "Download .tar")); // Try to download, only tar_gz should works assert_eq!( - reqwest::blocking::get(format!("http://localhost:{}/?download=tar_gz", port).as_str())? - .status(), + reqwest::blocking::get(server.url().join("?download=tar_gz")?)?.status(), StatusCode::OK ); assert_eq!( - reqwest::blocking::get(format!("http://localhost:{}/?download=tar", port).as_str())? - .status(), + reqwest::blocking::get(server.url().join("?download=tar")?)?.status(), StatusCode::FORBIDDEN ); assert_eq!( - reqwest::blocking::get(format!("http://localhost:{}/?download=zip", port).as_str())? - .status(), + reqwest::blocking::get(server.url().join("?download=zip")?)?.status(), StatusCode::FORBIDDEN ); - child.kill()?; - Ok(()) } diff --git a/tests/auth.rs b/tests/auth.rs index 09ea8d8..920f738 100644 --- a/tests/auth.rs +++ b/tests/auth.rs @@ -1,17 +1,12 @@ mod fixtures; -use assert_cmd::prelude::*; -use assert_fs::fixture::TempDir; -use fixtures::{port, tmpdir, Error, FILES}; +use fixtures::{server, server_no_stderr, Error, FILES}; use pretty_assertions::assert_eq; use reqwest::blocking::Client; use reqwest::StatusCode; use rstest::rstest; use select::document::Document; use select::predicate::Text; -use std::process::{Command, Stdio}; -use std::thread::sleep; -use std::time::Duration; #[rstest( cli_auth_arg, client_username, client_password, @@ -28,26 +23,14 @@ use std::time::Duration; ), )] fn auth_accepts( - tmpdir: TempDir, - port: u16, cli_auth_arg: &str, client_username: &str, client_password: &str, ) -> Result<(), Error> { - let mut child = Command::cargo_bin("miniserve")? - .arg(tmpdir.path()) - .arg("-p") - .arg(port.to_string()) - .arg("-a") - .arg(cli_auth_arg) - .stdout(Stdio::null()) - .spawn()?; - - sleep(Duration::from_secs(1)); - + let server = server(&["-a", cli_auth_arg]); let client = Client::new(); let response = client - .get(format!("http://localhost:{}", port).as_str()) + .get(server.url()) .basic_auth(client_username, Some(client_password)) .send()?; @@ -60,8 +43,6 @@ fn auth_accepts( assert!(parsed.find(Text).any(|x| x.text() == file)); } - child.kill()?; - Ok(()) } @@ -91,56 +72,39 @@ fn auth_accepts( ), )] fn auth_rejects( - tmpdir: TempDir, - port: u16, cli_auth_arg: &str, client_username: &str, client_password: &str, ) -> Result<(), Error> { - let mut child = Command::cargo_bin("miniserve")? - .arg(tmpdir.path()) - .arg("-p") - .arg(port.to_string()) - .arg("-a") - .arg(cli_auth_arg) - .stdout(Stdio::null()) - .stderr(Stdio::null()) - .spawn()?; - - sleep(Duration::from_secs(1)); - + let server = server_no_stderr(&["-a", cli_auth_arg]); let client = Client::new(); let status = client - .get(format!("http://localhost:{}", port).as_str()) + .get(server.url()) .basic_auth(client_username, Some(client_password)) .send()? .status(); assert_eq!(status, StatusCode::UNAUTHORIZED); - child.kill()?; - Ok(()) } -/// Helper function that registers multiple accounts -#[cfg(test)] -fn register_accounts<'a>(command: &'a mut Command) -> &'a mut Command { - command - .arg("--auth") - .arg("usr0:pwd0") - .arg("--auth") - .arg("usr1:pwd1") - .arg("--auth") - .arg("usr2:sha256:149d2937d1bce53fa683ae652291bd54cc8754444216a9e278b45776b76375af") // pwd2 - .arg("--auth") - .arg("usr3:sha256:ffc169417b4146cebe09a3e9ffbca33db82e3e593b4d04c0959a89c05b87e15d") // pwd3 - .arg("--auth") - .arg("usr4:sha512:68050a967d061ac480b414bc8f9a6d368ad0082203edcd23860e94c36178aad1a038e061716707d5479e23081a6d920dc6e9f88e5eb789cdd23e211d718d161a") // pwd4 - .arg("--auth") - .arg("usr5:sha512:be82a7dccd06122f9e232e9730e67e69e30ec61b268fd9b21a5e5d42db770d45586a1ce47816649a0107e9fadf079d9cf0104f0a3aaa0f67bad80289c3ba25a8") +/// Command line arguments that register multiple accounts +static ACCOUNTS: &[&str] = &[ + "--auth", + "usr0:pwd0", + "--auth", + "usr1:pwd1", + "--auth", + "usr2:sha256:149d2937d1bce53fa683ae652291bd54cc8754444216a9e278b45776b76375af", // pwd2 + "--auth", + "usr3:sha256:ffc169417b4146cebe09a3e9ffbca33db82e3e593b4d04c0959a89c05b87e15d", // pwd3 + "--auth", + "usr4:sha512:68050a967d061ac480b414bc8f9a6d368ad0082203edcd23860e94c36178aad1a038e061716707d5479e23081a6d920dc6e9f88e5eb789cdd23e211d718d161a", // pwd4 + "--auth", + "usr5:sha512:be82a7dccd06122f9e232e9730e67e69e30ec61b268fd9b21a5e5d42db770d45586a1ce47816649a0107e9fadf079d9cf0104f0a3aaa0f67bad80289c3ba25a8", // pwd5 -} +]; #[rstest( username, @@ -152,25 +116,12 @@ fn register_accounts<'a>(command: &'a mut Command) -> &'a mut Command { case("usr4", "pwd4"), case("usr5", "pwd5") )] -fn auth_multiple_accounts_pass( - tmpdir: TempDir, - port: u16, - username: &str, - password: &str, -) -> Result<(), Error> { - let mut child = register_accounts(&mut Command::cargo_bin("miniserve")?) - .arg("-p") - .arg(port.to_string()) - .arg(tmpdir.path()) - .stdout(Stdio::null()) - .spawn()?; - - sleep(Duration::from_secs(1)); - +fn auth_multiple_accounts_pass(username: &str, password: &str) -> Result<(), Error> { + let server = server(ACCOUNTS); let client = Client::new(); let response = client - .get(format!("http://localhost:{}", port).as_str()) + .get(server.url()) .basic_auth(username, Some(password)) .send()?; @@ -183,37 +134,22 @@ fn auth_multiple_accounts_pass( assert!(parsed.find(Text).any(|x| x.text() == file)); } - child.kill()?; - Ok(()) } #[rstest] -fn auth_multiple_accounts_wrong_username(tmpdir: TempDir, port: u16) -> Result<(), Error> { - let mut child = register_accounts( - Command::cargo_bin("miniserve")? - .arg(tmpdir.path()) - .arg("-p") - .arg(port.to_string()) - .stdout(Stdio::null()) - .stderr(Stdio::null()), - ) - .spawn()?; - - sleep(Duration::from_secs(1)); - +fn auth_multiple_accounts_wrong_username() -> Result<(), Error> { + let server = server_no_stderr(ACCOUNTS); let client = Client::new(); let status = client - .get(format!("http://localhost:{}", port).as_str()) + .get(server.url()) .basic_auth("unregistered user", Some("pwd0")) .send()? .status(); assert_eq!(status, StatusCode::UNAUTHORIZED); - child.kill()?; - Ok(()) } @@ -227,35 +163,17 @@ fn auth_multiple_accounts_wrong_username(tmpdir: TempDir, port: u16) -> Result<( case("usr4", "pwd1"), case("usr5", "pwd0") )] -fn auth_multiple_accounts_wrong_password( - tmpdir: TempDir, - port: u16, - username: &str, - password: &str, -) -> Result<(), Error> { - let mut child = register_accounts( - Command::cargo_bin("miniserve")? - .arg(tmpdir.path()) - .arg("-p") - .arg(port.to_string()) - .stdout(Stdio::null()) - .stderr(Stdio::null()), - ) - .spawn()?; - - sleep(Duration::from_secs(1)); - +fn auth_multiple_accounts_wrong_password(username: &str, password: &str) -> Result<(), Error> { + let server = server_no_stderr(ACCOUNTS); let client = Client::new(); let status = client - .get(format!("http://localhost:{}", port).as_str()) + .get(server.url()) .basic_auth(username, Some(password)) .send()? .status(); assert_eq!(status, StatusCode::UNAUTHORIZED); - child.kill()?; - Ok(()) } diff --git a/tests/data/cert.pem b/tests/data/cert.pem new file mode 100644 index 0000000..c907ef2 --- /dev/null +++ b/tests/data/cert.pem @@ -0,0 +1,29 @@ +-----BEGIN CERTIFICATE----- +MIIFCTCCAvGgAwIBAgIUJUf2QS/pOdHEW4EHTfdXxeTvtM8wDQYJKoZIhvcNAQEL +BQAwFDESMBAGA1UEAwwJbG9jYWxob3N0MB4XDTIxMDgyNzAwMzEyOFoXDTMxMDgy +NTAwMzEyOFowFDESMBAGA1UEAwwJbG9jYWxob3N0MIICIjANBgkqhkiG9w0BAQEF +AAOCAg8AMIICCgKCAgEAwmYOqToI0R30lPyYtF9bSuhIOCp9cp0jl2nuHaO8mpr1 +gMiJKKN4HjAdgac+3hYkTRFqK2mKKpV9QdVKR24Ib7mC45Ek7BlLw3VbxPRKrK/j +rKW3M3ui+453B24yf6K8dH36x9gZo4glzghFxuodFakIX2zNKo6tEx0XVkbhsu/w +vj2s+0L3oToPAYZaiOB/7xYU6Yu9n7Tn6rE9/orDfK1DlrZDP3hzyxLzuf6tqXCh +66cgaPQTh+xyyWZcvl60kbB4H3bdhqbYGMMQO8bUxXTQXjwvUsvl0yn9qCpMIn99 +Pm9xhfDQSF3zawM3CQ/lmn9uFQzdOEfYlO6oaidTqxLtBhVUcEutIcmoW9nmmv2g +Ei49/3OmvWQcEdMWt8xwxSrMvKDSeUdF3rbalTHBFQHJlJiKRX9wTNtSZ5T8FTU7 +4Ip4EzAtP8wY5NDv253mddANoyKsVRGytS35LDFkCS/TxuVDZrjluc86yqUId/jf +HZAzQ7ifpC890aG0JOq/0mmVDvbn7MzdTsTWwhE8UaOiFljTiNQX3QjX3TaEu32M +XHKo5nebNqDVRGnFMFmfXw2ZP8lgQCWk1HxLr0qhRxIy8XmIK1ZUz7Uc4Cba73XB +pSxcIPytpDuuKotslBjoIYu9DY07n1Hu4zYPvpP9DnaunEW6zmANEtjSyrE/TQ0C +AwEAAaNTMFEwHQYDVR0OBBYEFH0VzGnFqGVB+11uyvqea2qXYxQKMB8GA1UdIwQY +MBaAFH0VzGnFqGVB+11uyvqea2qXYxQKMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZI +hvcNAQELBQADggIBAA4FqzX34FCU1WYzmBRcq7QHSrc7LcuTbxhESB7mYbI8IPFt +cgrtXL1mTP+nz5nN+E6fyA8Y9zIyXm/6svYpJzXgUTtbdgDW22v5iN+YZvOaQ3Jt +/0eEtkx7wdNjLsN0aM6OjPXDw0mAVFDdevE7wgnra6x6/VHOt6pksNJa76ZVPX5X +dlLj+OU4eQPPMVxhL7p3xdSPFDZzXY7mNfVycO3tK5Fzrwko7OQKqEBMtc0oZxLd +m/FvqcJveHYHfXZl5XKMcsCNO8bG0XXDhwg0CLTf1p0hmp1oLieqplekOWs54Alo +FF4EBNdDaIFdQ4FAYaAU+9KLoPstorTl+3Owj/k3xhDB+0sGwGeX/e88nhs/ppEy +bxOt0j4AruwapkcvkwhQeMpQJRYyOrcvlbUEZqFABozZ9gbGRQvnConDNg7tz5zc +nVUupszA7zs0Vn9b1zVLOcOcS2ziQvoCyh687MsVbjw65Y6tkhvLI35G68zrFKsl +MS5mqnK4DZYFc1gGGI/rjsFUf3dD4ww6PTnwv3Ga2yBvXi7EckEeEqB+dRlVdvob +cH/grVUum3s5Y4PTnxyNAUFZlFNZ8jlOcgXtAFuTnJ/jcvboZdE7Oja2OIMJo53d +rbkqAPNGhQ98QDuTwWjHUq/Th1CQK4ALI/wqoc22TJpSh/mme5Dj4HhB7LWl +-----END CERTIFICATE----- diff --git a/tests/data/generate_tls_certs.sh b/tests/data/generate_tls_certs.sh new file mode 100755 index 0000000..969a38c --- /dev/null +++ b/tests/data/generate_tls_certs.sh @@ -0,0 +1,2 @@ +#!/usr/bin/env bash +openssl req -subj '/CN=localhost' -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -nodes -days 3650 diff --git a/tests/data/key.pem b/tests/data/key.pem new file mode 100644 index 0000000..4263815 --- /dev/null +++ b/tests/data/key.pem @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +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 +UbBWUEN95O4LnWFuyhEIOIEmp5JtGks= +-----END PRIVATE KEY----- diff --git a/tests/fixtures/mod.rs b/tests/fixtures/mod.rs index 1cf6c59..ec17f3e 100644 --- a/tests/fixtures/mod.rs +++ b/tests/fixtures/mod.rs @@ -1,7 +1,12 @@ +use assert_cmd::prelude::*; use assert_fs::fixture::TempDir; use assert_fs::prelude::*; use port_check::free_local_port; +use reqwest::Url; use rstest::fixture; +use std::process::{Child, Command, Stdio}; +use std::thread::sleep; +use std::time::{Duration, Instant}; /// Error type used by tests pub type Error = Box<dyn std::error::Error>; @@ -19,6 +24,8 @@ pub static FILES: &[&str] = &[ "#[]{}()@!$&'`+,;= %20.test", #[cfg(unix)] ":?#[]{}<>()@!$&'`|*+,;= %20.test", + #[cfg(not(windows))] + "foo\\bar.test", ]; /// Hidden files for testing purpose @@ -76,3 +83,112 @@ pub fn tmpdir() -> TempDir { pub fn port() -> u16 { free_local_port().expect("Couldn't find a free local port") } + +/// Run miniserve as a server; Start with a temporary directory, a free port and some +/// optional arguments then wait for a while for the server setup to complete. +#[fixture] +#[allow(dead_code)] +pub fn server<I>(#[default(&[] as &[&str])] args: I) -> TestServer +where + I: IntoIterator + Clone, + I::Item: AsRef<std::ffi::OsStr>, +{ + let port = port(); + let tmpdir = tmpdir(); + let child = Command::cargo_bin("miniserve") + .expect("Couldn't find test binary") + .arg(tmpdir.path()) + .arg("-p") + .arg(port.to_string()) + .args(args.clone()) + .stdout(Stdio::null()) + .spawn() + .expect("Couldn't run test binary"); + let is_tls = args + .into_iter() + .any(|x| x.as_ref().to_str().unwrap().contains("tls")); + + wait_for_port(port); + TestServer::new(port, tmpdir, child, is_tls) +} + +/// Same as `server()` but ignore stderr +#[fixture] +#[allow(dead_code)] +pub fn server_no_stderr<I>(#[default(&[] as &[&str])] args: I) -> TestServer +where + I: IntoIterator + Clone, + I::Item: AsRef<std::ffi::OsStr>, +{ + let port = port(); + let tmpdir = tmpdir(); + let child = Command::cargo_bin("miniserve") + .expect("Couldn't find test binary") + .arg(tmpdir.path()) + .arg("-p") + .arg(port.to_string()) + .args(args.clone()) + .stdout(Stdio::null()) + .stderr(Stdio::null()) + .spawn() + .expect("Couldn't run test binary"); + let is_tls = args + .into_iter() + .any(|x| x.as_ref().to_str().unwrap().contains("tls")); + + wait_for_port(port); + TestServer::new(port, tmpdir, child, is_tls) +} + +/// Wait a max of 1s for the port to become available. +fn wait_for_port(port: u16) { + let start_wait = Instant::now(); + + while !port_check::is_port_reachable(format!("localhost:{}", port)) { + sleep(Duration::from_millis(100)); + + if start_wait.elapsed().as_secs() > 1 { + panic!("timeout waiting for port {}", port); + } + } +} + +#[allow(dead_code)] +pub struct TestServer { + port: u16, + tmpdir: TempDir, + child: Child, + is_tls: bool, +} + +#[allow(dead_code)] +impl TestServer { + pub fn new(port: u16, tmpdir: TempDir, child: Child, is_tls: bool) -> Self { + Self { + port, + tmpdir, + child, + is_tls, + } + } + + pub fn url(&self) -> Url { + let protocol = if self.is_tls { "https" } else { "http" }; + Url::parse(&format!("{}://localhost:{}", protocol, self.port)).unwrap() + } + + pub fn path(&self) -> &std::path::Path { + self.tmpdir.path() + } + + pub fn port(&self) -> u16 { + self.port + } +} + +impl Drop for TestServer { + fn drop(&mut self) { + self.child.kill().expect("Couldn't kill test server"); + self.child.wait().unwrap(); + } +} diff --git a/tests/header.rs b/tests/header.rs index e46044c..4ac38b1 100644 --- a/tests/header.rs +++ b/tests/header.rs @@ -1,29 +1,15 @@ mod fixtures; -use assert_cmd::prelude::*; -use assert_fs::fixture::TempDir; -use fixtures::{port, tmpdir, Error}; +use fixtures::{server, Error}; use rstest::rstest; -use std::process::{Command, Stdio}; -use std::thread::sleep; -use std::time::Duration; #[rstest(headers, case(vec!["x-info: 123".to_string()]), case(vec!["x-info1: 123".to_string(), "x-info2: 345".to_string()]) )] -fn custom_header_set(tmpdir: TempDir, port: u16, headers: Vec<String>) -> Result<(), Error> { - let mut child = Command::cargo_bin("miniserve")? - .arg(tmpdir.path()) - .arg("-p") - .arg(port.to_string()) - .args(headers.iter().flat_map(|h| vec!["--header", h])) - .stdout(Stdio::null()) - .spawn()?; - - sleep(Duration::from_secs(1)); - - let resp = reqwest::blocking::get(format!("http://localhost:{}", port).as_str())?; +fn custom_header_set(headers: Vec<String>) -> Result<(), Error> { + let server = server(headers.iter().flat_map(|h| vec!["--header", h])); + let resp = reqwest::blocking::get(server.url())?; for header in headers { let mut header_split = header.splitn(2, ':'); @@ -32,7 +18,5 @@ fn custom_header_set(tmpdir: TempDir, port: u16, headers: Vec<String>) -> Result assert_eq!(resp.headers().get(header_name).unwrap(), header_value); } - child.kill()?; - Ok(()) } diff --git a/tests/navigation.rs b/tests/navigation.rs index c5c18cb..f4a2e1f 100644 --- a/tests/navigation.rs +++ b/tests/navigation.rs @@ -1,16 +1,11 @@ mod fixtures; mod utils; -use assert_cmd::prelude::*; -use assert_fs::fixture::TempDir; -use fixtures::{port, tmpdir, Error, DEEPLY_NESTED_FILE, DIRECTORIES}; +use fixtures::{server, Error, TestServer, DEEPLY_NESTED_FILE, DIRECTORIES}; use pretty_assertions::{assert_eq, assert_ne}; use rstest::rstest; use select::document::Document; use std::process::{Command, Stdio}; -use std::thread::sleep; -use std::time::Duration; -use url::Url; use utils::get_link_from_text; #[rstest( @@ -22,45 +17,19 @@ use utils::get_link_from_text; case("/very/deeply/nested", "/very/deeply/nested/") )] /// Directories get a trailing slash. -fn index_gets_trailing_slash( - tmpdir: TempDir, - port: u16, - input: &str, - expected: &str, -) -> Result<(), Error> { - let mut child = Command::cargo_bin("miniserve")? - .arg("-p") - .arg(port.to_string()) - .arg(tmpdir.path()) - .stdout(Stdio::null()) - .spawn()?; - - sleep(Duration::from_secs(1)); - - let base_url = Url::parse(&format!("http://localhost:{}", port))?; - let resp = reqwest::blocking::get(base_url.join(input)?)?; +fn index_gets_trailing_slash(server: TestServer, input: &str, expected: &str) -> Result<(), Error> { + let resp = reqwest::blocking::get(server.url().join(input)?)?; assert!(resp.url().as_str().ends_with(expected)); - child.kill()?; - Ok(()) } #[rstest] /// Can't navigate up the root. -fn cant_navigate_up_the_root(tmpdir: TempDir, port: u16) -> Result<(), Error> { - let mut child = Command::cargo_bin("miniserve")? - .arg("-p") - .arg(port.to_string()) - .arg(tmpdir.path()) - .stdout(Stdio::null()) - .spawn()?; - - sleep(Duration::from_secs(1)); - +fn cant_navigate_up_the_root(server: TestServer) -> Result<(), Error> { // We're using curl for this as it has the option `--path-as-is` which doesn't normalize // invalid urls. A useful feature in this particular case. - let base_url = Url::parse(&format!("http://localhost:{}", port))?; + let base_url = server.url(); let curl_successful = Command::new("curl") .arg("-s") .arg("--fail") @@ -71,24 +40,13 @@ fn cant_navigate_up_the_root(tmpdir: TempDir, port: u16) -> Result<(), Error> { .success(); assert!(curl_successful); - child.kill()?; - Ok(()) } #[rstest] /// We can navigate into directories and back using shown links. -fn can_navigate_into_dirs_and_back(tmpdir: TempDir, port: u16) -> Result<(), Error> { - let mut child = Command::cargo_bin("miniserve")? - .arg("-p") - .arg(port.to_string()) - .arg(tmpdir.path()) - .stdout(Stdio::null()) - .spawn()?; - - sleep(Duration::from_secs(1)); - - let base_url = Url::parse(&format!("http://localhost:{}/", port))?; +fn can_navigate_into_dirs_and_back(server: TestServer) -> Result<(), Error> { + let base_url = server.url(); let initial_body = reqwest::blocking::get(base_url.as_str())?.error_for_status()?; let initial_parsed = Document::from_read(initial_body)?; for &directory in DIRECTORIES { @@ -105,23 +63,12 @@ fn can_navigate_into_dirs_and_back(tmpdir: TempDir, port: u16) -> Result<(), Err assert_eq!(resp.url().as_str(), base_url.as_str()); } - child.kill()?; - Ok(()) } #[rstest] /// We can navigate deep into the file tree and back using shown links. -fn can_navigate_deep_into_dirs_and_back(tmpdir: TempDir, port: u16) -> Result<(), Error> { - let mut child = Command::cargo_bin("miniserve")? - .arg("-p") - .arg(port.to_string()) - .arg(tmpdir.path()) - .stdout(Stdio::null()) - .spawn()?; - - sleep(Duration::from_secs(1)); - +fn can_navigate_deep_into_dirs_and_back(server: TestServer) -> Result<(), Error> { // Create a vector of directory names. We don't need to fetch the file and so we'll // remove that part. let dir_names = { @@ -132,7 +79,7 @@ fn can_navigate_deep_into_dirs_and_back(tmpdir: TempDir, port: u16) -> Result<() comps.pop(); comps }; - let base_url = Url::parse(&format!("http://localhost:{}/", port))?; + let base_url = server.url(); // First we'll go forwards through the directory tree and then we'll go backwards. // In the end, we'll have to end up where we came from. @@ -157,29 +104,17 @@ fn can_navigate_deep_into_dirs_and_back(tmpdir: TempDir, port: u16) -> Result<() } assert_eq!(base_url, next_url); - child.kill()?; - Ok(()) } -#[rstest(use_custom_title, case(true), case(false))] +#[rstest] +#[case(server(&["--title", "some title"]), "some title")] +#[case(server(None::<&str>), format!("localhost:{}", server.port()))] /// We can use breadcrumbs to navigate. fn can_navigate_using_breadcrumbs( - tmpdir: TempDir, - port: u16, - use_custom_title: bool, + #[case] server: TestServer, + #[case] title_name: String, ) -> Result<(), Error> { - let mut command_base = Command::cargo_bin("miniserve")?; - let mut command = command_base.arg("-p").arg(port.to_string()); - - if use_custom_title { - command = command.arg("--title").arg("some title") - } - - let mut child = command.arg(tmpdir.path()).stdout(Stdio::null()).spawn()?; - - sleep(Duration::from_secs(1)); - // Create a vector of directory names. We don't need to fetch the file and so we'll // remove that part. let dir: String = { @@ -191,19 +126,13 @@ fn can_navigate_using_breadcrumbs( comps.join("") }; - let base_url = Url::parse(&format!("http://localhost:{}/", port))?; + let base_url = server.url(); let nested_url = base_url.join(&dir)?; let resp = reqwest::blocking::get(nested_url.as_str())?; let body = resp.error_for_status()?; let parsed = Document::from_read(body)?; - let title_name = if use_custom_title { - "some title".to_string() - } else { - format!("localhost:{}", port) - }; - // can go back to root dir by clicking title let title_link = get_link_from_text(&parsed, &title_name).expect("Root dir link not found."); assert_eq!("/", title_link); @@ -217,7 +146,5 @@ fn can_navigate_using_breadcrumbs( let current_dir_link = get_link_from_text(&parsed, "nested"); assert_eq!(None, current_dir_link); - child.kill()?; - Ok(()) } diff --git a/tests/qrcode.rs b/tests/qrcode.rs index d9a5529..a9c27fe 100644 --- a/tests/qrcode.rs +++ b/tests/qrcode.rs @@ -1,74 +1,34 @@ mod fixtures; -use assert_cmd::prelude::*; -use assert_fs::fixture::TempDir; -use fixtures::{port, tmpdir, Error}; +use fixtures::{server, server_no_stderr, Error, TestServer}; use reqwest::StatusCode; use rstest::rstest; use select::document::Document; use select::predicate::Attr; use std::iter::repeat_with; -use std::process::{Command, Stdio}; -use std::thread::sleep; -use std::time::Duration; #[rstest] -fn hide_qrcode_element(tmpdir: TempDir, port: u16) -> Result<(), Error> { - let mut child = Command::cargo_bin("miniserve")? - .arg(tmpdir.path()) - .arg("-p") - .arg(port.to_string()) - .stdout(Stdio::null()) - .spawn()?; - - sleep(Duration::from_secs(1)); - - let body = reqwest::blocking::get(format!("http://localhost:{}", port).as_str())? - .error_for_status()?; +fn hide_qrcode_element(server: TestServer) -> Result<(), Error> { + let body = reqwest::blocking::get(server.url())?.error_for_status()?; let parsed = Document::from_read(body)?; assert!(parsed.find(Attr("id", "qrcode")).next().is_none()); - child.kill()?; - Ok(()) } #[rstest] -fn show_qrcode_element(tmpdir: TempDir, port: u16) -> Result<(), Error> { - let mut child = Command::cargo_bin("miniserve")? - .arg(tmpdir.path()) - .arg("-p") - .arg(port.to_string()) - .arg("-q") - .stdout(Stdio::null()) - .spawn()?; - - sleep(Duration::from_secs(1)); - - let body = reqwest::blocking::get(format!("http://localhost:{}", port).as_str())? - .error_for_status()?; +fn show_qrcode_element(#[with(&["-q"])] server: TestServer) -> Result<(), Error> { + let body = reqwest::blocking::get(server.url())?.error_for_status()?; let parsed = Document::from_read(body)?; assert!(parsed.find(Attr("id", "qrcode")).next().is_some()); - child.kill()?; - Ok(()) } #[rstest] -fn get_svg_qrcode(tmpdir: TempDir, port: u16) -> Result<(), Error> { - let mut child = Command::cargo_bin("miniserve")? - .arg(tmpdir.path()) - .arg("-p") - .arg(port.to_string()) - .stdout(Stdio::null()) - .stderr(Stdio::null()) - .spawn()?; - - sleep(Duration::from_secs(1)); - +fn get_svg_qrcode(#[from(server_no_stderr)] server: TestServer) -> Result<(), Error> { // Ok - let resp = reqwest::blocking::get(format!("http://localhost:{}/?qrcode=test", port).as_str())?; + let resp = reqwest::blocking::get(server.url().join("/?qrcode=test")?)?; assert_eq!(resp.status(), StatusCode::OK); assert_eq!(resp.headers()["Content-Type"], "image/svg+xml"); @@ -78,12 +38,9 @@ fn get_svg_qrcode(tmpdir: TempDir, port: u16) -> Result<(), Error> { // Err let content: String = repeat_with(|| '0').take(8 * 1024).collect(); - let resp = - reqwest::blocking::get(format!("http://localhost:{}/?qrcode={}", port, content).as_str())?; + let resp = reqwest::blocking::get(server.url().join(&format!("?qrcode={}", content))?)?; assert_eq!(resp.status(), StatusCode::URI_TOO_LONG); - child.kill()?; - Ok(()) } diff --git a/tests/serve_request.rs b/tests/serve_request.rs index e259b9e..361801b 100644 --- a/tests/serve_request.rs +++ b/tests/serve_request.rs @@ -2,13 +2,14 @@ mod fixtures; use assert_cmd::prelude::*; use assert_fs::fixture::TempDir; -use fixtures::{port, tmpdir, Error, DIRECTORIES, FILES, HIDDEN_DIRECTORIES, HIDDEN_FILES}; +use fixtures::{ + port, server, tmpdir, Error, TestServer, DIRECTORIES, FILES, HIDDEN_DIRECTORIES, HIDDEN_FILES, +}; use http::StatusCode; use regex::Regex; use rstest::rstest; use select::document::Document; use select::node::Node; -use std::path::Path; use std::process::{Command, Stdio}; use std::thread::sleep; use std::time::Duration; @@ -39,28 +40,13 @@ fn serves_requests_with_no_options(tmpdir: TempDir) -> Result<(), Error> { } #[rstest] -fn serves_requests_with_non_default_port(tmpdir: TempDir, port: u16) -> Result<(), Error> { - let mut child = Command::cargo_bin("miniserve")? - .arg(tmpdir.path()) - .arg("-p") - .arg(port.to_string()) - .stdout(Stdio::null()) - .spawn()?; - - sleep(Duration::from_secs(1)); - - let body = reqwest::blocking::get(format!("http://localhost:{}", port).as_str())? - .error_for_status()?; +fn serves_requests_with_non_default_port(server: TestServer) -> Result<(), Error> { + let body = reqwest::blocking::get(server.url())?.error_for_status()?; let parsed = Document::from_read(body)?; for &file in FILES { let f = parsed.find(|x: &Node| x.text() == file).next().unwrap(); - reqwest::blocking::get(format!( - "http://localhost:{}/{}", - port, - f.attr("href").unwrap() - ))? - .error_for_status()?; + reqwest::blocking::get(server.url().join(f.attr("href").unwrap())?)?.error_for_status()?; assert_eq!( format!("/{}", file), percent_encoding::percent_decode_str(f.attr("href").unwrap()).decode_utf8_lossy(), @@ -73,8 +59,7 @@ fn serves_requests_with_non_default_port(tmpdir: TempDir, port: u16) -> Result<( .next() .is_some()); let dir_body = - reqwest::blocking::get(format!("http://localhost:{}/{}", port, directory).as_str())? - .error_for_status()?; + reqwest::blocking::get(server.url().join(&directory)?)?.error_for_status()?; let dir_body_parsed = Document::from_read(dir_body)?; for &file in FILES { assert!(dir_body_parsed @@ -84,25 +69,12 @@ fn serves_requests_with_non_default_port(tmpdir: TempDir, port: u16) -> Result<( } } - child.kill()?; - Ok(()) } #[rstest] -fn serves_requests_hidden_files(tmpdir: TempDir, port: u16) -> Result<(), Error> { - let mut child = Command::cargo_bin("miniserve")? - .arg(tmpdir.path()) - .arg("-p") - .arg(port.to_string()) - .arg("--hidden") - .stdout(Stdio::null()) - .spawn()?; - - sleep(Duration::from_secs(1)); - - let body = reqwest::blocking::get(format!("http://localhost:{}", port).as_str())? - .error_for_status()?; +fn serves_requests_hidden_files(#[with(&["--hidden"])] server: TestServer) -> Result<(), Error> { + let body = reqwest::blocking::get(server.url())?.error_for_status()?; let parsed = Document::from_read(body)?; for &file in FILES.into_iter().chain(HIDDEN_FILES) { @@ -119,8 +91,7 @@ fn serves_requests_hidden_files(tmpdir: TempDir, port: u16) -> Result<(), Error> .next() .is_some()); let dir_body = - reqwest::blocking::get(format!("http://localhost:{}/{}", port, directory).as_str())? - .error_for_status()?; + reqwest::blocking::get(server.url().join(&directory)?)?.error_for_status()?; let dir_body_parsed = Document::from_read(dir_body)?; for &file in FILES.into_iter().chain(HIDDEN_FILES) { assert!(dir_body_parsed @@ -130,24 +101,12 @@ fn serves_requests_hidden_files(tmpdir: TempDir, port: u16) -> Result<(), Error> } } - child.kill()?; - Ok(()) } #[rstest] -fn serves_requests_no_hidden_files_without_flag(tmpdir: TempDir, port: u16) -> Result<(), Error> { - let mut child = Command::cargo_bin("miniserve")? - .arg(tmpdir.path()) - .arg("-p") - .arg(port.to_string()) - .stdout(Stdio::null()) - .spawn()?; - - sleep(Duration::from_secs(1)); - - let body = reqwest::blocking::get(format!("http://localhost:{}", port).as_str())? - .error_for_status()?; +fn serves_requests_no_hidden_files_without_flag(server: TestServer) -> Result<(), Error> { + let body = reqwest::blocking::get(server.url())?.error_for_status()?; let parsed = Document::from_read(body)?; for &hidden_item in HIDDEN_FILES.into_iter().chain(HIDDEN_DIRECTORIES) { @@ -155,54 +114,38 @@ fn serves_requests_no_hidden_files_without_flag(tmpdir: TempDir, port: u16) -> R .find(|x: &Node| x.text() == hidden_item) .next() .is_none()); - let resp = - reqwest::blocking::get(format!("http://localhost:{}/{}", port, hidden_item).as_str())?; + let resp = reqwest::blocking::get(server.url().join(&hidden_item)?)?; assert_eq!(resp.status(), StatusCode::BAD_REQUEST); } - child.kill()?; - Ok(()) } -#[rstest(no_symlinks, case(true), case(false))] -fn serves_requests_symlinks(tmpdir: TempDir, port: u16, no_symlinks: bool) -> Result<(), Error> { - let mut comm = Command::cargo_bin("miniserve")?; - comm.arg(tmpdir.path()) - .arg("-p") - .arg(port.to_string()) - .stdout(Stdio::null()); - if no_symlinks { - comm.arg("--no-symlinks"); - } - - let mut child = comm.spawn()?; - sleep(Duration::from_secs(1)); - +#[rstest] +#[case(true, server(&["--no-symlinks"]))] +#[case(false, server(None::<&str>))] +fn serves_requests_symlinks( + #[case] no_symlinks: bool, + #[case] server: TestServer, +) -> Result<(), Error> { let files = &["symlink-file.html"]; let dirs = &["symlink-dir/"]; let broken = &["symlink broken"]; for &directory in dirs { - let orig = Path::new(DIRECTORIES[0].strip_suffix("/").unwrap()); - let link = tmpdir - .path() - .join(Path::new(directory.strip_suffix("/").unwrap())); + let orig = DIRECTORIES[0].strip_suffix("/").unwrap(); + let link = server.path().join(directory.strip_suffix("/").unwrap()); symlink_dir(orig, link).expect("Couldn't create symlink"); } for &file in files { - let orig = Path::new(FILES[0]); - let link = tmpdir.path().join(Path::new(file)); - symlink_file(orig, link).expect("Couldn't create symlink"); + symlink_file(FILES[0], server.path().join(file)).expect("Couldn't create symlink"); } for &file in broken { - let orig = Path::new("should-not-exist.xxx"); - let link = tmpdir.path().join(Path::new(file)); - symlink_file(orig, link).expect("Couldn't create symlink"); + symlink_file("should-not-exist.xxx", server.path().join(file)) + .expect("Couldn't create symlink"); } - let body = reqwest::blocking::get(format!("http://localhost:{}", port).as_str())? - .error_for_status()?; + let body = reqwest::blocking::get(server.url())?.error_for_status()?; let parsed = Document::from_read(body)?; for &entry in files.into_iter().chain(dirs) { @@ -216,8 +159,7 @@ fn serves_requests_symlinks(tmpdir: TempDir, port: u16, no_symlinks: bool) -> Re let node = node.unwrap(); assert_eq!(node.attr("href").unwrap().strip_prefix("/").unwrap(), entry); - reqwest::blocking::get(format!("http://localhost:{}/{}", port, entry))? - .error_for_status()?; + reqwest::blocking::get(server.url().join(&entry)?)?.error_for_status()?; if entry.ends_with("/") { assert_eq!(node.attr("class").unwrap(), "directory"); } else { @@ -228,8 +170,6 @@ fn serves_requests_symlinks(tmpdir: TempDir, port: u16, no_symlinks: bool) -> Re assert!(parsed.find(|x: &Node| x.text() == entry).next().is_none()); } - child.kill()?; - Ok(()) } diff --git a/tests/tls.rs b/tests/tls.rs new file mode 100644 index 0000000..2464e1f --- /dev/null +++ b/tests/tls.rs @@ -0,0 +1,53 @@ +mod fixtures; + +use assert_cmd::Command; +use fixtures::{server, Error, TestServer, FILES}; +use predicates::str::contains; +use reqwest::blocking::ClientBuilder; +use rstest::rstest; +use select::{document::Document, node::Node}; + +/// Can start the server with TLS and receive encrypted responses. +#[rstest] +fn tls_works( + #[with(&[ + "--tls-cert", "tests/data/cert.pem", + "--tls-key", "tests/data/key.pem" + ])] + server: TestServer, +) -> Result<(), Error> { + let client = ClientBuilder::new() + .danger_accept_invalid_certs(true) + .build()?; + let body = client.get(server.url()).send()?.error_for_status()?; + let parsed = Document::from_read(body)?; + for &file in FILES { + assert!(parsed.find(|x: &Node| x.text() == file).next().is_some()); + } + + Ok(()) +} + +/// Wrong path for cert throws error. +#[rstest] +fn wrong_path_cert() -> Result<(), Error> { + Command::cargo_bin("miniserve")? + .args(&["--tls-cert", "wrong", "--tls-key", "tests/data/key.pem"]) + .assert() + .failure() + .stderr(contains("Error: Couldn't access TLS certificate \"wrong\"")); + + Ok(()) +} + +/// Wrong paths for key throws errors. +#[rstest] +fn wrong_path_key() -> Result<(), Error> { + Command::cargo_bin("miniserve")? + .args(&["--tls-cert", "tests/data/cert.pem", "--tls-key", "wrong"]) + .assert() + .failure() + .stderr(contains("Error: Couldn't access TLS key \"wrong\"")); + + Ok(()) +} diff --git a/tests/upload_files.rs b/tests/upload_files.rs index 58707c5..698eb46 100644 --- a/tests/upload_files.rs +++ b/tests/upload_files.rs @@ -1,33 +1,17 @@ mod fixtures; -use assert_cmd::prelude::*; -use assert_fs::fixture::TempDir; -use fixtures::{port, tmpdir, Error}; +use fixtures::{server, Error, TestServer}; use reqwest::blocking::{multipart, Client}; use rstest::rstest; use select::document::Document; use select::predicate::{Attr, Text}; -use std::process::{Command, Stdio}; -use std::thread::sleep; -use std::time::Duration; #[rstest] -fn uploading_files_works(tmpdir: TempDir, port: u16) -> Result<(), Error> { +fn uploading_files_works(#[with(&["-u"])] server: TestServer) -> Result<(), Error> { let test_file_name = "uploaded test file.txt"; - let mut child = Command::cargo_bin("miniserve")? - .arg(tmpdir.path()) - .arg("-p") - .arg(port.to_string()) - .arg("-u") - .stdout(Stdio::null()) - .spawn()?; - - sleep(Duration::from_secs(1)); - // Before uploading, check whether the uploaded file does not yet exist. - let body = reqwest::blocking::get(format!("http://localhost:{}", port).as_str())? - .error_for_status()?; + let body = reqwest::blocking::get(server.url())?.error_for_status()?; let parsed = Document::from_read(body)?; assert!(parsed.find(Text).all(|x| x.text() != test_file_name)); @@ -46,37 +30,25 @@ fn uploading_files_works(tmpdir: TempDir, port: u16) -> Result<(), Error> { let client = Client::new(); client - .post(format!("http://localhost:{}{}", port, upload_action).as_str()) + .post(server.url().join(upload_action)?) .multipart(form) .send()? .error_for_status()?; // After uploading, check whether the uploaded file is now getting listed. - let body = reqwest::blocking::get(format!("http://localhost:{}", port).as_str())?; + let body = reqwest::blocking::get(server.url())?; let parsed = Document::from_read(body)?; assert!(parsed.find(Text).any(|x| x.text() == test_file_name)); - child.kill()?; - Ok(()) } #[rstest] -fn uploading_files_is_prevented(tmpdir: TempDir, port: u16) -> Result<(), Error> { +fn uploading_files_is_prevented(server: TestServer) -> Result<(), Error> { let test_file_name = "uploaded test file.txt"; - let mut child = Command::cargo_bin("miniserve")? - .arg(tmpdir.path()) - .arg("-p") - .arg(port.to_string()) - .stdout(Stdio::null()) - .spawn()?; - - sleep(Duration::from_secs(1)); - // Before uploading, check whether the uploaded file does not yet exist. - let body = reqwest::blocking::get(format!("http://localhost:{}", port).as_str())? - .error_for_status()?; + let body = reqwest::blocking::get(server.url())?.error_for_status()?; let parsed = Document::from_read(body)?; assert!(parsed.find(Text).all(|x| x.text() != test_file_name)); @@ -93,18 +65,16 @@ fn uploading_files_is_prevented(tmpdir: TempDir, port: u16) -> Result<(), Error> let client = Client::new(); // Ensure uploading fails and returns an error assert!(client - .post(format!("http://localhost:{}{}", port, "/upload?path=/").as_str()) + .post(server.url().join("/upload?path=/")?) .multipart(form) .send()? .error_for_status() .is_err()); // After uploading, check whether the uploaded file is now getting listed. - let body = reqwest::blocking::get(format!("http://localhost:{}", port).as_str())?; + let body = reqwest::blocking::get(server.url())?; let parsed = Document::from_read(body)?; assert!(!parsed.find(Text).any(|x| x.text() == test_file_name)); - child.kill()?; - Ok(()) } |