sigoden
3 years ago
committed by
GitHub
21 changed files with 2637 additions and 94 deletions
@ -0,0 +1,61 @@
@@ -0,0 +1,61 @@
|
||||
mod fixtures; |
||||
mod utils; |
||||
|
||||
use fixtures::{server, Error, TestServer}; |
||||
use rstest::rstest; |
||||
|
||||
#[rstest] |
||||
fn default_not_allow_upload(server: TestServer) -> Result<(), Error> { |
||||
let url = format!("{}file1", server.url()); |
||||
let resp = fetch!(b"PUT", &url).body(b"abc".to_vec()).send()?; |
||||
assert_eq!(resp.status(), 403); |
||||
Ok(()) |
||||
} |
||||
|
||||
#[rstest] |
||||
fn default_not_allow_delete(server: TestServer) -> Result<(), Error> { |
||||
let url = format!("{}test.html", server.url()); |
||||
let resp = fetch!(b"DELETE", &url).send()?; |
||||
assert_eq!(resp.status(), 403); |
||||
Ok(()) |
||||
} |
||||
|
||||
#[rstest] |
||||
fn default_not_exist_dir(server: TestServer) -> Result<(), Error> { |
||||
let resp = reqwest::blocking::get(format!("{}404/", server.url()))?; |
||||
assert_eq!(resp.status(), 404); |
||||
Ok(()) |
||||
} |
||||
|
||||
#[rstest] |
||||
fn allow_upload_not_exist_dir( |
||||
#[with(&["--allow-upload"])] server: TestServer, |
||||
) -> Result<(), Error> { |
||||
let resp = reqwest::blocking::get(format!("{}404/", server.url()))?; |
||||
assert_eq!(resp.status(), 200); |
||||
Ok(()) |
||||
} |
||||
|
||||
#[rstest] |
||||
fn allow_upload_no_override(#[with(&["--allow-upload"])] server: TestServer) -> Result<(), Error> { |
||||
let url = format!("{}index.html", server.url()); |
||||
let resp = fetch!(b"PUT", &url).body(b"abc".to_vec()).send()?; |
||||
assert_eq!(resp.status(), 403); |
||||
Ok(()) |
||||
} |
||||
|
||||
#[rstest] |
||||
fn allow_delete_no_override(#[with(&["--allow-delete"])] server: TestServer) -> Result<(), Error> { |
||||
let url = format!("{}index.html", server.url()); |
||||
let resp = fetch!(b"PUT", &url).body(b"abc".to_vec()).send()?; |
||||
assert_eq!(resp.status(), 403); |
||||
Ok(()) |
||||
} |
||||
|
||||
#[rstest] |
||||
fn allow_upload_delete_can_override(#[with(&["-A"])] server: TestServer) -> Result<(), Error> { |
||||
let url = format!("{}index.html", server.url()); |
||||
let resp = fetch!(b"PUT", &url).body(b"abc".to_vec()).send()?; |
||||
assert_eq!(resp.status(), 201); |
||||
Ok(()) |
||||
} |
@ -0,0 +1,38 @@
@@ -0,0 +1,38 @@
|
||||
mod fixtures; |
||||
mod utils; |
||||
|
||||
use diqwest::blocking::WithDigestAuth; |
||||
use fixtures::{server, Error, TestServer}; |
||||
use rstest::rstest; |
||||
|
||||
#[rstest] |
||||
fn no_auth(#[with(&["--auth", "user:pass", "-A"])] server: TestServer) -> Result<(), Error> { |
||||
let resp = reqwest::blocking::get(server.url())?; |
||||
assert_eq!(resp.status(), 401); |
||||
assert!(resp.headers().contains_key("www-authenticate")); |
||||
let url = format!("{}file1", server.url()); |
||||
let resp = fetch!(b"PUT", &url).body(b"abc".to_vec()).send()?; |
||||
assert_eq!(resp.status(), 401); |
||||
Ok(()) |
||||
} |
||||
|
||||
#[rstest] |
||||
fn auth(#[with(&["--auth", "user:pass", "-A"])] server: TestServer) -> Result<(), Error> { |
||||
let url = format!("{}file1", server.url()); |
||||
let resp = fetch!(b"PUT", &url).body(b"abc".to_vec()).send()?; |
||||
assert_eq!(resp.status(), 401); |
||||
let resp = fetch!(b"PUT", &url) |
||||
.body(b"abc".to_vec()) |
||||
.send_with_digest_auth("user", "pass")?; |
||||
assert_eq!(resp.status(), 201); |
||||
Ok(()) |
||||
} |
||||
|
||||
#[rstest] |
||||
fn auth_skip_access( |
||||
#[with(&["--auth", "user:pass", "--no-auth-access"])] server: TestServer, |
||||
) -> Result<(), Error> { |
||||
let resp = reqwest::blocking::get(server.url())?; |
||||
assert_eq!(resp.status(), 200); |
||||
Ok(()) |
||||
} |
@ -0,0 +1,80 @@
@@ -0,0 +1,80 @@
|
||||
mod fixtures; |
||||
|
||||
use fixtures::{port, server, tmpdir, Error, TestServer}; |
||||
|
||||
use assert_cmd::prelude::*; |
||||
use assert_fs::fixture::TempDir; |
||||
use regex::Regex; |
||||
use rstest::rstest; |
||||
use std::io::{BufRead, BufReader}; |
||||
use std::process::{Command, Stdio}; |
||||
|
||||
#[rstest] |
||||
#[case(&["-b", "20.205.243.166"])] |
||||
fn bind_fails(tmpdir: TempDir, port: u16, #[case] args: &[&str]) -> Result<(), Error> { |
||||
Command::cargo_bin("duf")? |
||||
.env("RUST_LOG", "false") |
||||
.arg(tmpdir.path()) |
||||
.arg("-p") |
||||
.arg(port.to_string()) |
||||
.args(args) |
||||
.assert() |
||||
.stderr(predicates::str::contains("creating server listener")) |
||||
.failure(); |
||||
|
||||
Ok(()) |
||||
} |
||||
|
||||
#[rstest] |
||||
fn bind_ipv4(server: TestServer) -> Result<(), Error> { |
||||
assert!(reqwest::blocking::get(format!("http://127.0.0.1:{}", server.port()).as_str()).is_ok()); |
||||
Ok(()) |
||||
} |
||||
|
||||
#[rstest] |
||||
fn bind_ipv6(#[with(&["-b", "::"])] server: TestServer) -> Result<(), Error> { |
||||
assert_eq!( |
||||
reqwest::blocking::get(format!("http://127.0.0.1:{}", server.port()).as_str()).is_ok(), |
||||
!cfg!(windows) |
||||
); |
||||
assert!(reqwest::blocking::get(format!("http://[::1]:{}", server.port()).as_str()).is_ok()); |
||||
Ok(()) |
||||
} |
||||
|
||||
#[rstest] |
||||
#[case(&[] as &[&str])] |
||||
#[case(&["--path-prefix", "/prefix"])] |
||||
fn validate_printed_urls(tmpdir: TempDir, port: u16, #[case] args: &[&str]) -> Result<(), Error> { |
||||
let mut child = Command::cargo_bin("duf")? |
||||
.env("RUST_LOG", "false") |
||||
.arg(tmpdir.path()) |
||||
.arg("-p") |
||||
.arg(port.to_string()) |
||||
.args(args) |
||||
.stdout(Stdio::piped()) |
||||
.spawn()?; |
||||
|
||||
// WARN assumes urls list is terminated by an empty line
|
||||
let url_lines = BufReader::new(child.stdout.take().unwrap()) |
||||
.lines() |
||||
.map(|line| line.expect("Error reading stdout")) |
||||
.take_while(|line| !line.is_empty()) /* non-empty lines */ |
||||
.collect::<Vec<_>>(); |
||||
let url_lines = url_lines.join("\n"); |
||||
|
||||
let urls = Regex::new(r"http://[a-zA-Z0-9\.\[\]:/]+") |
||||
.unwrap() |
||||
.captures_iter(url_lines.as_str()) |
||||
.map(|caps| caps.get(0).unwrap().as_str()) |
||||
.collect::<Vec<_>>(); |
||||
|
||||
assert!(!urls.is_empty()); |
||||
|
||||
for url in urls { |
||||
reqwest::blocking::get(url)?.error_for_status()?; |
||||
} |
||||
|
||||
child.kill()?; |
||||
|
||||
Ok(()) |
||||
} |
@ -0,0 +1,37 @@
@@ -0,0 +1,37 @@
|
||||
mod fixtures; |
||||
mod utils; |
||||
|
||||
use fixtures::{server, Error, TestServer}; |
||||
use rstest::rstest; |
||||
|
||||
#[rstest] |
||||
fn cors(#[with(&["--cors"])] server: TestServer) -> Result<(), Error> { |
||||
let resp = reqwest::blocking::get(server.url())?; |
||||
|
||||
assert_eq!( |
||||
resp.headers().get("access-control-allow-origin").unwrap(), |
||||
"*" |
||||
); |
||||
assert_eq!( |
||||
resp.headers().get("access-control-allow-headers").unwrap(), |
||||
"range, content-type, accept, origin, www-authenticate" |
||||
); |
||||
|
||||
Ok(()) |
||||
} |
||||
|
||||
#[rstest] |
||||
fn cors_options(#[with(&["--cors"])] server: TestServer) -> Result<(), Error> { |
||||
let resp = fetch!(b"OPTIONS", server.url()).send()?; |
||||
|
||||
assert_eq!( |
||||
resp.headers().get("access-control-allow-origin").unwrap(), |
||||
"*" |
||||
); |
||||
assert_eq!( |
||||
resp.headers().get("access-control-allow-headers").unwrap(), |
||||
"range, content-type, accept, origin, www-authenticate" |
||||
); |
||||
|
||||
Ok(()) |
||||
} |
@ -0,0 +1,29 @@
@@ -0,0 +1,29 @@
|
||||
-----BEGIN CERTIFICATE----- |
||||
MIIFCTCCAvGgAwIBAgIUcegjikATvwNSIbN43QybKWIcKSMwDQYJKoZIhvcNAQEL |
||||
BQAwFDESMBAGA1UEAwwJbG9jYWxob3N0MB4XDTIyMDYxMTA4NTQyMloXDTMyMDYw |
||||
ODA4NTQyMlowFDESMBAGA1UEAwwJbG9jYWxob3N0MIICIjANBgkqhkiG9w0BAQEF |
||||
AAOCAg8AMIICCgKCAgEAo2wdMbFPkX7CAF/Y+hVj5bwm4dlxhwW2Z9Ic2RZFC5w2 |
||||
oK2XwyasDBEqDlgv/bN4xObAVlDZ/4/SuTVSDrNB8dtQl7GTWptpbFKJUdNocU88 |
||||
wqd4k/cLZg2aiQqnZKD88w/AxXnYw+F8yU0pFGj9GX0S5at3/V1hrBVxVO8Y99bb |
||||
gnJA8NMm0Pw2xYZS++ULuzoECk0xbNdtbtPrIuweI5mMvsJvtiw67EIdl3N9Lj5p |
||||
L4a7X1C0Xk5H4mOcwM0qq3m31HsCW91PMCjU6suo764rx5Jqv0n9HCNxdiSEadCw |
||||
f+GrmKtFOw3DcGPETg5AJR8H3rG1agKKjI+vRtL/tZ7coFOhZKXdjGvvUFcWcqO+ |
||||
GppHh16pzJDXi2qeD9Cu5b2ayM2uBnfV7Q3FjOeDqD+BCJ0ClaqNmAD9TF2htzdu |
||||
Inl+G3OJb4cqaYjaF5YmiZISfrimK5eR2I3et5cqnbuDHMKvDfUd9Jgj/2IqPOHJ |
||||
EguuXSO7WNKfQmlTv7EN/xrD6jiB/M8ADaSxjCqTbtKNyCbJlu2Wy9WlDXwPkNW8 |
||||
g70T4Br4U4Iy3N/0w2lAAhiizdC2jkehSKmWE2nmixGSXxkSOMgXQXDJ9RBtDQfd |
||||
8ym/ADfyVndUSnHvf9jCH1NPHlFbB7RVSvUHX22Qq63NUvhV32ct+/IyD/qPpl0C |
||||
AwEAAaNTMFEwHQYDVR0OBBYEFKwSSbPXBIkmzja3/cNJyqhWy96WMB8GA1UdIwQY |
||||
MBaAFKwSSbPXBIkmzja3/cNJyqhWy96WMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZI |
||||
hvcNAQELBQADggIBAHcrdu1nGDN5YvcHXzbBx73AC921fmn5xxzeFRO7af157g5h |
||||
4zornLMk4Obp+UGkMbWK4K0NAQXKKm5WjcmoOHNRg7TgTE7b1gcVuS4phdwlIqA6 |
||||
eZGg+NWZyeaIJNjdHgWgGoe+S+5Ne1I7sDKiEXrOzITJrDcQgBKFF08kqT6UNY2W |
||||
q90m+olPtrewAMgWllpxJ90u4qifPcwP+neDZJim9MhVYtHHeFsmyzlS185iasj8 |
||||
sxvp5HDTopmz0tDuiLHvOMKmyf7vapsnbqEGngQi2qV9rBmldyRLnWSe8u/FN31f |
||||
zhSk1ikSm1cQ/iyL898XexSmTafyaF8ELswdIMHkGZkVQurWeKn3/CEDXokXkpMI |
||||
4dlCSgM7SU+XtcjtXbR8/pHpcW2ZnBR0la/qIv81aNKkJeUkTcPC8BUv4jI/oT6z |
||||
LRrvRjMnHJjnADACuutlNRU4/e7h1XuvlXgFHsp63k7GJXouoIwdHjfkErZXsoEX |
||||
WeS+pPatkT7wbhfgYVwglMRIpgCu++htSRCV/lbSuYzCG6mKtxJyy4eslSjpHNPG |
||||
wELDKgzsgLtuTyNfP458O9i8x6wf9J6eVaHe3nqgqkOnnmQxEYnsPaFUMWG1/DYi |
||||
U+mA/VdQrPe3J4Z082sCe4MVmTzWlWCDpNFFQpv51NbWzc/kuIZuJCAwoZD0 |
||||
-----END CERTIFICATE----- |
@ -0,0 +1,3 @@
@@ -0,0 +1,3 @@
|
||||
#!/usr/bin/env bash |
||||
openssl req -subj '/CN=localhost' -x509 -newkey rsa:4096 -keyout key_pkcs8.pem -out cert.pem -nodes -days 3650 |
||||
openssl rsa -in key_pkcs8.pem -out key_pkcs1.pem |
@ -0,0 +1,51 @@
@@ -0,0 +1,51 @@
|
||||
-----BEGIN RSA PRIVATE KEY----- |
||||
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 |
||||
-----END RSA PRIVATE KEY----- |
@ -0,0 +1,52 @@
@@ -0,0 +1,52 @@
|
||||
-----BEGIN PRIVATE KEY----- |
||||
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 |
||||
afHJpnY0yZEqN1PeDaKVOCQAHbD8qQ== |
||||
-----END PRIVATE KEY----- |
@ -0,0 +1,25 @@
@@ -0,0 +1,25 @@
|
||||
mod fixtures; |
||||
mod utils; |
||||
|
||||
use fixtures::{server, Error, TestServer}; |
||||
use rstest::rstest; |
||||
|
||||
#[rstest] |
||||
fn default_favicon(server: TestServer) -> Result<(), Error> { |
||||
let resp = reqwest::blocking::get(format!("{}favicon.ico", server.url()))?; |
||||
assert_eq!(resp.status(), 200); |
||||
assert_eq!(resp.headers().get("content-type").unwrap(), "image/x-icon"); |
||||
Ok(()) |
||||
} |
||||
|
||||
#[rstest] |
||||
fn exist_favicon(#[with(&["-A"])] server: TestServer) -> Result<(), Error> { |
||||
let url = format!("{}favicon.ico", server.url()); |
||||
let data = b"abc"; |
||||
let resp = fetch!(b"PUT", &url).body(data.to_vec()).send()?; |
||||
assert_eq!(resp.status(), 201); |
||||
let resp = reqwest::blocking::get(url)?; |
||||
assert_eq!(resp.status(), 200); |
||||
assert_eq!(resp.bytes()?, data.to_vec()); |
||||
Ok(()) |
||||
} |
@ -0,0 +1,191 @@
@@ -0,0 +1,191 @@
|
||||
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}; |
||||
|
||||
#[allow(dead_code)] |
||||
pub type Error = Box<dyn std::error::Error>; |
||||
|
||||
/// File names for testing purpose
|
||||
#[allow(dead_code)] |
||||
pub static FILES: &[&str] = &[ |
||||
"test.txt", |
||||
"test.html", |
||||
"index.html", |
||||
"test.mkv", |
||||
#[cfg(not(windows))] |
||||
"test \" \' & < >.csv", |
||||
"😀.data", |
||||
"⎙.mp4", |
||||
"#[]{}()@!$&'`+,;= %20.test", |
||||
#[cfg(unix)] |
||||
":?#[]{}<>()@!$&'`|*+,;= %20.test", |
||||
#[cfg(not(windows))] |
||||
"foo\\bar.test", |
||||
]; |
||||
|
||||
/// Directory names for testing purpose
|
||||
#[allow(dead_code)] |
||||
pub static DIR_NO_INDEX: &str = "dir-no-index/"; |
||||
|
||||
/// Directory names for testing purpose
|
||||
#[allow(dead_code)] |
||||
pub static DIRECTORIES: &[&str] = &["dira/", "dirb/", "dirc/", DIR_NO_INDEX]; |
||||
|
||||
/// Name of a deeply nested file
|
||||
#[allow(dead_code)] |
||||
pub static DEEPLY_NESTED_FILE: &str = "very/deeply/nested/test.rs"; |
||||
|
||||
/// Test fixture which creates a temporary directory with a few files and directories inside.
|
||||
/// The directories also contain files.
|
||||
#[fixture] |
||||
#[allow(dead_code)] |
||||
pub fn tmpdir() -> TempDir { |
||||
let tmpdir = assert_fs::TempDir::new().expect("Couldn't create a temp dir for tests"); |
||||
for file in FILES { |
||||
tmpdir |
||||
.child(file) |
||||
.write_str(&format!("This is {}", file)) |
||||
.expect("Couldn't write to file"); |
||||
} |
||||
for directory in DIRECTORIES { |
||||
for file in FILES { |
||||
if *directory == DIR_NO_INDEX { |
||||
continue; |
||||
} |
||||
tmpdir |
||||
.child(format!("{}{}", directory, file)) |
||||
.write_str(&format!("This is {}{}", directory, file)) |
||||
.expect("Couldn't write to file"); |
||||
} |
||||
} |
||||
|
||||
tmpdir |
||||
.child(&DEEPLY_NESTED_FILE) |
||||
.write_str("File in a deeply nested directory.") |
||||
.expect("Couldn't write to file"); |
||||
tmpdir |
||||
} |
||||
|
||||
/// Get a free port.
|
||||
#[fixture] |
||||
#[allow(dead_code)] |
||||
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("duf") |
||||
.expect("Couldn't find test binary") |
||||
.env("RUST_LOG", "false") |
||||
.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("duf") |
||||
.expect("Couldn't find test binary") |
||||
.env("RUST_LOG", "false") |
||||
.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(); |
||||
} |
||||
} |
@ -0,0 +1,184 @@
@@ -0,0 +1,184 @@
|
||||
mod fixtures; |
||||
mod utils; |
||||
|
||||
use fixtures::{server, Error, TestServer}; |
||||
use rstest::rstest; |
||||
|
||||
#[rstest] |
||||
fn get_dir(server: TestServer) -> Result<(), Error> { |
||||
let resp = reqwest::blocking::get(server.url())?; |
||||
assert_index_resp!(resp); |
||||
Ok(()) |
||||
} |
||||
|
||||
#[rstest] |
||||
fn head_dir(server: TestServer) -> Result<(), Error> { |
||||
let resp = fetch!(b"HEAD", server.url()).send()?; |
||||
assert_eq!(resp.status(), 200); |
||||
assert_eq!( |
||||
resp.headers().get("content-type").unwrap(), |
||||
"text/html; charset=utf-8" |
||||
); |
||||
assert_eq!(resp.text()?, ""); |
||||
Ok(()) |
||||
} |
||||
|
||||
#[rstest] |
||||
fn get_dir_404(server: TestServer) -> Result<(), Error> { |
||||
let resp = reqwest::blocking::get(format!("{}404/", server.url()))?; |
||||
assert_eq!(resp.status(), 404); |
||||
Ok(()) |
||||
} |
||||
|
||||
#[rstest] |
||||
fn head_dir_404(server: TestServer) -> Result<(), Error> { |
||||
let resp = fetch!(b"HEAD", format!("{}404/", server.url())).send()?; |
||||
assert_eq!(resp.status(), 404); |
||||
Ok(()) |
||||
} |
||||
|
||||
#[rstest] |
||||
fn get_dir_zip(server: TestServer) -> Result<(), Error> { |
||||
let resp = reqwest::blocking::get(format!("{}?zip", server.url()))?; |
||||
assert_eq!(resp.status(), 200); |
||||
assert_eq!( |
||||
resp.headers().get("content-type").unwrap(), |
||||
"application/zip" |
||||
); |
||||
assert!(resp.headers().contains_key("content-disposition")); |
||||
Ok(()) |
||||
} |
||||
|
||||
#[rstest] |
||||
fn head_dir_zip(server: TestServer) -> Result<(), Error> { |
||||
let resp = fetch!(b"HEAD", format!("{}?zip", server.url())).send()?; |
||||
assert_eq!(resp.status(), 200); |
||||
assert_eq!( |
||||
resp.headers().get("content-type").unwrap(), |
||||
"application/zip" |
||||
); |
||||
assert!(resp.headers().contains_key("content-disposition")); |
||||
assert_eq!(resp.text()?, ""); |
||||
Ok(()) |
||||
} |
||||
|
||||
#[rstest] |
||||
fn get_dir_search(server: TestServer) -> Result<(), Error> { |
||||
let resp = reqwest::blocking::get(format!("{}?q={}", server.url(), "test.html"))?; |
||||
assert_eq!(resp.status(), 200); |
||||
let paths = utils::retrive_index_paths(&resp.text()?); |
||||
assert!(!paths.is_empty()); |
||||
for p in paths { |
||||
assert!(p.contains(&"test.html")); |
||||
} |
||||
Ok(()) |
||||
} |
||||
|
||||
#[rstest] |
||||
fn head_dir_search(server: TestServer) -> Result<(), Error> { |
||||
let resp = fetch!(b"HEAD", format!("{}?q={}", server.url(), "test.html")).send()?; |
||||
assert_eq!(resp.status(), 200); |
||||
assert_eq!( |
||||
resp.headers().get("content-type").unwrap(), |
||||
"text/html; charset=utf-8" |
||||
); |
||||
assert_eq!(resp.text()?, ""); |
||||
Ok(()) |
||||
} |
||||
|
||||
#[rstest] |
||||
fn get_file(server: TestServer) -> Result<(), Error> { |
||||
let resp = reqwest::blocking::get(format!("{}index.html", server.url()))?; |
||||
assert_eq!(resp.status(), 200); |
||||
assert_eq!(resp.headers().get("content-type").unwrap(), "text/html"); |
||||
assert_eq!(resp.headers().get("accept-ranges").unwrap(), "bytes"); |
||||
assert!(resp.headers().contains_key("etag")); |
||||
assert!(resp.headers().contains_key("last-modified")); |
||||
assert!(resp.headers().contains_key("content-length")); |
||||
assert_eq!(resp.text()?, "This is index.html"); |
||||
Ok(()) |
||||
} |
||||
|
||||
#[rstest] |
||||
fn head_file(server: TestServer) -> Result<(), Error> { |
||||
let resp = fetch!(b"HEAD", format!("{}index.html", server.url())).send()?; |
||||
assert_eq!(resp.status(), 200); |
||||
assert_eq!(resp.headers().get("content-type").unwrap(), "text/html"); |
||||
assert_eq!(resp.headers().get("accept-ranges").unwrap(), "bytes"); |
||||
assert!(resp.headers().contains_key("etag")); |
||||
assert!(resp.headers().contains_key("last-modified")); |
||||
assert!(resp.headers().contains_key("content-length")); |
||||
assert_eq!(resp.text()?, ""); |
||||
Ok(()) |
||||
} |
||||
|
||||
#[rstest] |
||||
fn get_file_404(server: TestServer) -> Result<(), Error> { |
||||
let resp = reqwest::blocking::get(format!("{}404", server.url()))?; |
||||
assert_eq!(resp.status(), 404); |
||||
Ok(()) |
||||
} |
||||
|
||||
#[rstest] |
||||
fn head_file_404(server: TestServer) -> Result<(), Error> { |
||||
let resp = fetch!(b"HEAD", format!("{}404", server.url())).send()?; |
||||
assert_eq!(resp.status(), 404); |
||||
Ok(()) |
||||
} |
||||
|
||||
#[rstest] |
||||
fn options_dir(server: TestServer) -> Result<(), Error> { |
||||
let resp = fetch!(b"OPTIONS", format!("{}index.html", server.url())).send()?; |
||||
assert_eq!(resp.status(), 204); |
||||
assert_eq!( |
||||
resp.headers().get("allow").unwrap(), |
||||
"GET,HEAD,PUT,OPTIONS,DELETE,PROPFIND,COPY,MOVE" |
||||
); |
||||
assert_eq!(resp.headers().get("dav").unwrap(), "1"); |
||||
Ok(()) |
||||
} |
||||
|
||||
#[rstest] |
||||
fn put_file(#[with(&["-A"])] server: TestServer) -> Result<(), Error> { |
||||
let url = format!("{}file1", server.url()); |
||||
let resp = fetch!(b"PUT", &url).body(b"abc".to_vec()).send()?; |
||||
assert_eq!(resp.status(), 201); |
||||
let resp = reqwest::blocking::get(url)?; |
||||
assert_eq!(resp.status(), 200); |
||||
Ok(()) |
||||
} |
||||
|
||||
#[rstest] |
||||
fn put_file_create_dir(#[with(&["-A"])] server: TestServer) -> Result<(), Error> { |
||||
let url = format!("{}xyz/file1", server.url()); |
||||
let resp = fetch!(b"PUT", &url).body(b"abc".to_vec()).send()?; |
||||
assert_eq!(resp.status(), 201); |
||||
let resp = reqwest::blocking::get(url)?; |
||||
assert_eq!(resp.status(), 200); |
||||
Ok(()) |
||||
} |
||||
|
||||
#[rstest] |
||||
fn put_file_conflict_dir(#[with(&["-A"])] server: TestServer) -> Result<(), Error> { |
||||
let url = format!("{}dira", server.url()); |
||||
let resp = fetch!(b"PUT", &url).body(b"abc".to_vec()).send()?; |
||||
assert_eq!(resp.status(), 403); |
||||
Ok(()) |
||||
} |
||||
|
||||
#[rstest] |
||||
fn delete_file(#[with(&["-A"])] server: TestServer) -> Result<(), Error> { |
||||
let url = format!("{}test.html", server.url()); |
||||
let resp = fetch!(b"DELETE", &url).send()?; |
||||
assert_eq!(resp.status(), 204); |
||||
let resp = reqwest::blocking::get(url)?; |
||||
assert_eq!(resp.status(), 404); |
||||
Ok(()) |
||||
} |
||||
|
||||
#[rstest] |
||||
fn delete_file_404(#[with(&["-A"])] server: TestServer) -> Result<(), Error> { |
||||
let resp = fetch!(b"DELETE", format!("{}file1", server.url())).send()?; |
||||
assert_eq!(resp.status(), 404); |
||||
Ok(()) |
||||
} |
@ -0,0 +1,30 @@
@@ -0,0 +1,30 @@
|
||||
mod fixtures; |
||||
mod utils; |
||||
|
||||
use fixtures::{server, Error, TestServer}; |
||||
use rstest::rstest; |
||||
|
||||
#[rstest] |
||||
fn path_prefix_index(#[with(&["--path-prefix", "xyz"])] server: TestServer) -> Result<(), Error> { |
||||
let resp = reqwest::blocking::get(format!("{}{}", server.url(), "xyz"))?; |
||||
assert_index_resp!(resp); |
||||
Ok(()) |
||||
} |
||||
|
||||
#[rstest] |
||||
fn path_prefix_file(#[with(&["--path-prefix", "xyz"])] server: TestServer) -> Result<(), Error> { |
||||
let resp = reqwest::blocking::get(format!("{}{}/index.html", server.url(), "xyz"))?; |
||||
assert_eq!(resp.status(), 200); |
||||
assert_eq!(resp.text()?, "This is index.html"); |
||||
Ok(()) |
||||
} |
||||
|
||||
#[rstest] |
||||
fn path_prefix_propfind( |
||||
#[with(&["--path-prefix", "xyz"])] server: TestServer, |
||||
) -> Result<(), Error> { |
||||
let resp = fetch!(b"PROPFIND", format!("{}{}", server.url(), "xyz")).send()?; |
||||
let text = resp.text()?; |
||||
assert!(text.contains("<D:href>/xyz/</D:href>")); |
||||
Ok(()) |
||||
} |
@ -0,0 +1,35 @@
@@ -0,0 +1,35 @@
|
||||
mod fixtures; |
||||
|
||||
use fixtures::{server, Error, TestServer, DIR_NO_INDEX}; |
||||
use rstest::rstest; |
||||
|
||||
#[rstest] |
||||
fn render_index(#[with(&["--render-index"])] server: TestServer) -> Result<(), Error> { |
||||
let resp = reqwest::blocking::get(server.url())?; |
||||
let text = resp.text()?; |
||||
assert_eq!(text, "This is index.html"); |
||||
Ok(()) |
||||
} |
||||
|
||||
#[rstest] |
||||
fn render_index_404(#[with(&["--render-index"])] server: TestServer) -> Result<(), Error> { |
||||
let resp = reqwest::blocking::get(format!("{}/{}", server.url(), DIR_NO_INDEX))?; |
||||
assert_eq!(resp.status(), 404); |
||||
Ok(()) |
||||
} |
||||
|
||||
#[rstest] |
||||
fn render_spa(#[with(&["--render-spa"])] server: TestServer) -> Result<(), Error> { |
||||
let resp = reqwest::blocking::get(server.url())?; |
||||
let text = resp.text()?; |
||||
assert_eq!(text, "This is index.html"); |
||||
Ok(()) |
||||
} |
||||
|
||||
#[rstest] |
||||
fn render_spa_no_404(#[with(&["--render-spa"])] server: TestServer) -> Result<(), Error> { |
||||
let resp = reqwest::blocking::get(format!("{}/{}", server.url(), DIR_NO_INDEX))?; |
||||
let text = resp.text()?; |
||||
assert_eq!(text, "This is index.html"); |
||||
Ok(()) |
||||
} |
@ -0,0 +1,46 @@
@@ -0,0 +1,46 @@
|
||||
mod fixtures; |
||||
mod utils; |
||||
|
||||
use assert_fs::fixture::TempDir; |
||||
use fixtures::{server, tmpdir, Error, TestServer}; |
||||
use rstest::rstest; |
||||
|
||||
#[cfg(unix)] |
||||
use std::os::unix::fs::symlink as symlink_dir; |
||||
#[cfg(windows)] |
||||
use std::os::windows::fs::symlink_dir; |
||||
|
||||
#[rstest] |
||||
fn default_not_allow_symlink(server: TestServer, tmpdir: TempDir) -> Result<(), Error> { |
||||
// Create symlink directory "foo" to point outside the root
|
||||
let dir = "foo"; |
||||
symlink_dir(tmpdir.path(), server.path().join(dir)).expect("Couldn't create symlink"); |
||||
let resp = reqwest::blocking::get(format!("{}{}", server.url(), dir))?; |
||||
assert_eq!(resp.status(), 404); |
||||
let resp = reqwest::blocking::get(format!("{}{}/index.html", server.url(), dir))?; |
||||
assert_eq!(resp.status(), 404); |
||||
let resp = reqwest::blocking::get(server.url())?; |
||||
let paths = utils::retrive_index_paths(&resp.text()?); |
||||
assert!(!paths.is_empty()); |
||||
assert!(!paths.contains(&format!("{}/", dir))); |
||||
Ok(()) |
||||
} |
||||
|
||||
#[rstest] |
||||
fn allow_symlink( |
||||
#[with(&["--allow-symlink"])] server: TestServer, |
||||
tmpdir: TempDir, |
||||
) -> Result<(), Error> { |
||||
// Create symlink directory "foo" to point outside the root
|
||||
let dir = "foo"; |
||||
symlink_dir(tmpdir.path(), server.path().join(dir)).expect("Couldn't create symlink"); |
||||
let resp = reqwest::blocking::get(format!("{}{}", server.url(), dir))?; |
||||
assert_eq!(resp.status(), 200); |
||||
let resp = reqwest::blocking::get(format!("{}{}/index.html", server.url(), dir))?; |
||||
assert_eq!(resp.status(), 200); |
||||
let resp = reqwest::blocking::get(server.url())?; |
||||
let paths = utils::retrive_index_paths(&resp.text()?); |
||||
assert!(!paths.is_empty()); |
||||
assert!(paths.contains(&format!("{}/", dir))); |
||||
Ok(()) |
||||
} |
@ -0,0 +1,51 @@
@@ -0,0 +1,51 @@
|
||||
mod fixtures; |
||||
mod utils; |
||||
|
||||
use assert_cmd::Command; |
||||
use fixtures::{server, Error, TestServer}; |
||||
use predicates::str::contains; |
||||
use reqwest::blocking::ClientBuilder; |
||||
use rstest::rstest; |
||||
|
||||
/// Can start the server with TLS and receive encrypted responses.
|
||||
#[rstest] |
||||
#[case(server(&[ |
||||
"--tls-cert", "tests/data/cert.pem", |
||||
"--tls-key", "tests/data/key_pkcs8.pem", |
||||
]))] |
||||
#[case(server(&[ |
||||
"--tls-cert", "tests/data/cert.pem", |
||||
"--tls-key", "tests/data/key_pkcs1.pem", |
||||
]))] |
||||
fn tls_works(#[case] server: TestServer) -> Result<(), Error> { |
||||
let client = ClientBuilder::new() |
||||
.danger_accept_invalid_certs(true) |
||||
.build()?; |
||||
let resp = client.get(server.url()).send()?.error_for_status()?; |
||||
assert_index_resp!(resp); |
||||
Ok(()) |
||||
} |
||||
|
||||
/// Wrong path for cert throws error.
|
||||
#[rstest] |
||||
fn wrong_path_cert() -> Result<(), Error> { |
||||
Command::cargo_bin("duf")? |
||||
.args(&["--tls-cert", "wrong", "--tls-key", "tests/data/key.pem"]) |
||||
.assert() |
||||
.failure() |
||||
.stderr(contains("error: Failed to access `wrong`")); |
||||
|
||||
Ok(()) |
||||
} |
||||
|
||||
/// Wrong paths for key throws errors.
|
||||
#[rstest] |
||||
fn wrong_path_key() -> Result<(), Error> { |
||||
Command::cargo_bin("duf")? |
||||
.args(&["--tls-cert", "tests/data/cert.pem", "--tls-key", "wrong"]) |
||||
.assert() |
||||
.failure() |
||||
.stderr(contains("error: Failed to access `wrong`")); |
||||
|
||||
Ok(()) |
||||
} |
@ -0,0 +1,61 @@
@@ -0,0 +1,61 @@
|
||||
use serde_json::Value; |
||||
use std::collections::HashSet; |
||||
|
||||
#[macro_export] |
||||
macro_rules! assert_index_resp { |
||||
($resp:ident) => { |
||||
assert_index_resp!($resp, self::fixtures::FILES) |
||||
}; |
||||
($resp:ident, $files:expr) => { |
||||
assert_eq!($resp.status(), 200); |
||||
let body = $resp.text()?; |
||||
let paths = self::utils::retrive_index_paths(&body); |
||||
assert!(!paths.is_empty()); |
||||
for file in $files { |
||||
assert!(paths.contains(&file.to_string())); |
||||
} |
||||
}; |
||||
} |
||||
|
||||
#[macro_export] |
||||
macro_rules! fetch { |
||||
($method:literal, $url:expr) => { |
||||
reqwest::blocking::Client::new().request(hyper::Method::from_bytes($method)?, $url) |
||||
}; |
||||
} |
||||
|
||||
#[allow(dead_code)] |
||||
pub fn retrive_index_paths(index: &str) -> HashSet<String> { |
||||
retrive_index_paths_impl(index).unwrap_or_default() |
||||
} |
||||
|
||||
#[allow(dead_code)] |
||||
pub fn encode_uri(v: &str) -> String { |
||||
let parts: Vec<_> = v.split('/').map(urlencoding::encode).collect(); |
||||
parts.join("/") |
||||
} |
||||
|
||||
fn retrive_index_paths_impl(index: &str) -> Option<HashSet<String>> { |
||||
let lines: Vec<&str> = index.lines().collect(); |
||||
let (i, _) = lines |
||||
.iter() |
||||
.enumerate() |
||||
.find(|(_, v)| v.contains("const DATA"))?; |
||||
let line = lines.get(i + 1)?; |
||||
let value: Value = line.parse().ok()?; |
||||
let paths = value |
||||
.get("paths")? |
||||
.as_array()? |
||||
.iter() |
||||
.flat_map(|v| { |
||||
let name = v.get("name")?.as_str()?; |
||||
let path_type = v.get("path_type")?.as_str()?; |
||||
if path_type.ends_with("Dir") { |
||||
Some(format!("{}/", name)) |
||||
} else { |
||||
Some(name.to_owned()) |
||||
} |
||||
}) |
||||
.collect(); |
||||
Some(paths) |
||||
} |
@ -0,0 +1,203 @@
@@ -0,0 +1,203 @@
|
||||
mod fixtures; |
||||
mod utils; |
||||
|
||||
use fixtures::{server, Error, TestServer, FILES}; |
||||
use rstest::rstest; |
||||
use xml::escape::escape_str_pcdata; |
||||
|
||||
#[rstest] |
||||
fn propfind_dir(server: TestServer) -> Result<(), Error> { |
||||
let resp = fetch!(b"PROPFIND", format!("{}dira", server.url())).send()?; |
||||
assert_eq!(resp.status(), 207); |
||||
let body = resp.text()?; |
||||
assert!(body.contains("<D:href>/dira</D:href>")); |
||||
assert!(body.contains("<D:displayname>dira</D:displayname>")); |
||||
for f in FILES { |
||||
assert!(body.contains(&format!("<D:href>/dira/{}</D:href>", utils::encode_uri(f)))); |
||||
assert!(body.contains(&format!( |
||||
"<D:displayname>{}</D:displayname>", |
||||
escape_str_pcdata(f) |
||||
))); |
||||
} |
||||
Ok(()) |
||||
} |
||||
|
||||
#[rstest] |
||||
fn propfind_dir_depth0(server: TestServer) -> Result<(), Error> { |
||||
let resp = fetch!(b"PROPFIND", format!("{}dira", server.url())) |
||||
.header("depth", "0") |
||||
.send()?; |
||||
assert_eq!(resp.status(), 207); |
||||
let body = resp.text()?; |
||||
assert!(body.contains("<D:href>/dira</D:href>")); |
||||
assert!(body.contains("<D:displayname>dira</D:displayname>")); |
||||
assert_eq!( |
||||
body.lines() |
||||
.filter(|v| *v == "<D:status>HTTP/1.1 200 OK</D:status>") |
||||
.count(), |
||||
1 |
||||
); |
||||
Ok(()) |
||||
} |
||||
|
||||
#[rstest] |
||||
fn propfind_404(server: TestServer) -> Result<(), Error> { |
||||
let resp = fetch!(b"PROPFIND", format!("{}404", server.url())).send()?; |
||||
assert_eq!(resp.status(), 404); |
||||
Ok(()) |
||||
} |
||||
|
||||
#[rstest] |
||||
fn propfind_file(server: TestServer) -> Result<(), Error> { |
||||
let resp = fetch!(b"PROPFIND", format!("{}test.html", server.url())).send()?; |
||||
assert_eq!(resp.status(), 207); |
||||
let body = resp.text()?; |
||||
assert!(body.contains("<D:href>/test.html</D:href>")); |
||||
assert!(body.contains("<D:displayname>test.html</D:displayname>")); |
||||
assert_eq!( |
||||
body.lines() |
||||
.filter(|v| *v == "<D:status>HTTP/1.1 200 OK</D:status>") |
||||
.count(), |
||||
1 |
||||
); |
||||
Ok(()) |
||||
} |
||||
|
||||
#[rstest] |
||||
fn proppatch_file(#[with(&["-A"])] server: TestServer) -> Result<(), Error> { |
||||
let resp = fetch!(b"PROPPATCH", format!("{}test.html", server.url())).send()?; |
||||
assert_eq!(resp.status(), 207); |
||||
let body = resp.text()?; |
||||
assert!(body.contains("<D:href>/test.html</D:href>")); |
||||
Ok(()) |
||||
} |
||||
|
||||
#[rstest] |
||||
fn proppatch_404(#[with(&["-A"])] server: TestServer) -> Result<(), Error> { |
||||
let resp = fetch!(b"PROPPATCH", format!("{}404", server.url())).send()?; |
||||
assert_eq!(resp.status(), 404); |
||||
Ok(()) |
||||
} |
||||
|
||||
#[rstest] |
||||
fn mkcol_dir(#[with(&["-A"])] server: TestServer) -> Result<(), Error> { |
||||
let resp = fetch!(b"MKCOL", format!("{}newdir", server.url())).send()?; |
||||
assert_eq!(resp.status(), 201); |
||||
Ok(()) |
||||
} |
||||
|
||||
#[rstest] |
||||
fn mkcol_not_allow_upload(server: TestServer) -> Result<(), Error> { |
||||
let resp = fetch!(b"MKCOL", format!("{}newdir", server.url())).send()?; |
||||
assert_eq!(resp.status(), 403); |
||||
Ok(()) |
||||
} |
||||
|
||||
#[rstest] |
||||
fn copy_file(#[with(&["-A"])] server: TestServer) -> Result<(), Error> { |
||||
let new_url = format!("{}test2.html", server.url()); |
||||
let resp = fetch!(b"COPY", format!("{}test.html", server.url())) |
||||
.header("Destination", &new_url) |
||||
.send()?; |
||||
assert_eq!(resp.status(), 204); |
||||
let resp = reqwest::blocking::get(new_url)?; |
||||
assert_eq!(resp.status(), 200); |
||||
Ok(()) |
||||
} |
||||
|
||||
#[rstest] |
||||
fn copy_not_allow_upload(server: TestServer) -> Result<(), Error> { |
||||
let new_url = format!("{}test2.html", server.url()); |
||||
let resp = fetch!(b"COPY", format!("{}test.html", server.url())) |
||||
.header("Destination", &new_url) |
||||
.send()?; |
||||
assert_eq!(resp.status(), 403); |
||||
Ok(()) |
||||
} |
||||
|
||||
#[rstest] |
||||
fn copy_file_404(#[with(&["-A"])] server: TestServer) -> Result<(), Error> { |
||||
let new_url = format!("{}test2.html", server.url()); |
||||
let resp = fetch!(b"COPY", format!("{}404", server.url())) |
||||
.header("Destination", &new_url) |
||||
.send()?; |
||||
assert_eq!(resp.status(), 404); |
||||
Ok(()) |
||||
} |
||||
|
||||
#[rstest] |
||||
fn move_file(#[with(&["-A"])] server: TestServer) -> Result<(), Error> { |
||||
let origin_url = format!("{}test.html", server.url()); |
||||
let new_url = format!("{}test2.html", server.url()); |
||||
let resp = fetch!(b"MOVE", &origin_url) |
||||
.header("Destination", &new_url) |
||||
.send()?; |
||||
assert_eq!(resp.status(), 204); |
||||
let resp = reqwest::blocking::get(new_url)?; |
||||
assert_eq!(resp.status(), 200); |
||||
let resp = reqwest::blocking::get(origin_url)?; |
||||
assert_eq!(resp.status(), 404); |
||||
Ok(()) |
||||
} |
||||
|
||||
#[rstest] |
||||
fn move_not_allow_upload(#[with(&["--allow-delete"])] server: TestServer) -> Result<(), Error> { |
||||
let origin_url = format!("{}test.html", server.url()); |
||||
let new_url = format!("{}test2.html", server.url()); |
||||
let resp = fetch!(b"MOVE", &origin_url) |
||||
.header("Destination", &new_url) |
||||
.send()?; |
||||
assert_eq!(resp.status(), 403); |
||||
Ok(()) |
||||
} |
||||
|
||||
#[rstest] |
||||
fn move_not_allow_delete(#[with(&["--allow-upload"])] server: TestServer) -> Result<(), Error> { |
||||
let origin_url = format!("{}test.html", server.url()); |
||||
let new_url = format!("{}test2.html", server.url()); |
||||
let resp = fetch!(b"MOVE", &origin_url) |
||||
.header("Destination", &new_url) |
||||
.send()?; |
||||
assert_eq!(resp.status(), 403); |
||||
Ok(()) |
||||
} |
||||
|
||||
#[rstest] |
||||
fn move_file_404(#[with(&["-A"])] server: TestServer) -> Result<(), Error> { |
||||
let new_url = format!("{}test2.html", server.url()); |
||||
let resp = fetch!(b"MOVE", format!("{}404", server.url())) |
||||
.header("Destination", &new_url) |
||||
.send()?; |
||||
assert_eq!(resp.status(), 404); |
||||
Ok(()) |
||||
} |
||||
|
||||
#[rstest] |
||||
fn lock_file(#[with(&["-A"])] server: TestServer) -> Result<(), Error> { |
||||
let resp = fetch!(b"LOCK", format!("{}test.html", server.url())).send()?; |
||||
assert_eq!(resp.status(), 200); |
||||
let body = resp.text()?; |
||||
assert!(body.contains("<D:href>/test.html</D:href>")); |
||||
Ok(()) |
||||
} |
||||
|
||||
#[rstest] |
||||
fn lock_file_404(#[with(&["-A"])] server: TestServer) -> Result<(), Error> { |
||||
let resp = fetch!(b"LOCK", format!("{}404", server.url())).send()?; |
||||
assert_eq!(resp.status(), 404); |
||||
Ok(()) |
||||
} |
||||
|
||||
#[rstest] |
||||
fn unlock_file(#[with(&["-A"])] server: TestServer) -> Result<(), Error> { |
||||
let resp = fetch!(b"LOCK", format!("{}test.html", server.url())).send()?; |
||||
assert_eq!(resp.status(), 200); |
||||
Ok(()) |
||||
} |
||||
|
||||
#[rstest] |
||||
fn unlock_file_404(#[with(&["-A"])] server: TestServer) -> Result<(), Error> { |
||||
let resp = fetch!(b"LOCK", format!("{}404", server.url())).send()?; |
||||
assert_eq!(resp.status(), 404); |
||||
Ok(()) |
||||
} |
Loading…
Reference in new issue