From 317bd6a5d42a83c9c5e874788282a6e76f638211 Mon Sep 17 00:00:00 2001 From: Lukas Stabe Date: Thu, 6 Feb 2025 00:03:05 +0100 Subject: add read-only webdav support --- tests/webdav.rs | 164 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 164 insertions(+) create mode 100644 tests/webdav.rs (limited to 'tests/webdav.rs') diff --git a/tests/webdav.rs b/tests/webdav.rs new file mode 100644 index 0000000..1bc7e12 --- /dev/null +++ b/tests/webdav.rs @@ -0,0 +1,164 @@ +#[cfg(unix)] +use std::os::unix::fs::{symlink as symlink_dir, symlink as symlink_file}; +#[cfg(windows)] +use std::os::windows::fs::{symlink_dir, symlink_file}; +use std::process::Command; + +use assert_cmd::prelude::*; +use assert_fs::TempDir; +use predicates::str::contains; +use reqwest::{blocking::Client, Method}; +use reqwest_dav::{ + list_cmd::{ListEntity, ListFile, ListFolder}, + ClientBuilder as DavClientBuilder, +}; +use rstest::rstest; + +mod fixtures; + +use crate::fixtures::{ + server, tmpdir, Error, TestServer, DIRECTORIES, FILES, HIDDEN_DIRECTORIES, HIDDEN_FILES, +}; + +#[rstest] +#[case(server(&["--enable-webdav"]), true)] +#[case(server(&[] as &[&str]), false)] +fn webdav_flag_works( + #[case] server: TestServer, + #[case] should_respond: bool, +) -> Result<(), Error> { + let client = Client::new(); + let response = client + .request(Method::from_bytes(b"PROPFIND").unwrap(), server.url()) + .header("Depth", "1") + .send()?; + + assert_eq!(should_respond, response.status().is_success()); + + Ok(()) +} + +#[rstest] +fn webdav_advertised_in_options( + #[with(&["--enable-webdav"])] server: TestServer, +) -> Result<(), Error> { + let response = Client::new() + .request(Method::OPTIONS, server.url()) + .send()? + .error_for_status()?; + + let headers = response.headers(); + let allow = headers.get("allow").unwrap().to_str()?; + + assert!(allow.contains("OPTIONS") && allow.contains("PROPFIND")); + assert!(headers.get("dav").is_some()); + + Ok(()) +} + +fn list_webdav(url: url::Url, path: &str) -> Result, reqwest_dav::Error> { + let client = DavClientBuilder::new().set_host(url.to_string()).build()?; + + let rt = tokio::runtime::Runtime::new().unwrap(); + + rt.block_on(async { client.list(path, reqwest_dav::Depth::Number(1)).await }) +} + +#[rstest] +#[case(server(&["--enable-webdav"]), false)] +#[case(server(&["--enable-webdav", "--hidden"]), true)] +fn webdav_respects_hidden_flag( + #[case] server: TestServer, + #[case] hidden_should_show: bool, +) -> Result<(), Error> { + let list = list_webdav(server.url(), "/")?; + + assert_eq!( + hidden_should_show, + list.iter().any(|el| + matches!(el, ListEntity::File(ListFile { href, .. }) if href.contains(HIDDEN_FILES[0])) + ) + ); + + assert_eq!( + hidden_should_show, + list.iter().any(|el| + matches!(el, ListEntity::Folder(ListFolder { href, .. }) if href.contains(HIDDEN_DIRECTORIES[0])) + ) + ); + + Ok(()) +} + +#[rstest] +#[case(server(&["--enable-webdav"]), true)] +#[should_panic] +#[case(server(&["--enable-webdav", "--no-symlinks"]), false)] +fn webdav_respects_no_symlink_flag(#[case] server: TestServer, #[case] symlinks_should_show: bool) { + // Make symlinks + let symlink_directory_str = "symlink_directory"; + let symlink_directory = server.path().join(symlink_directory_str); + let symlinked_direcotry = server.path().join(DIRECTORIES[0]); + symlink_dir(symlinked_direcotry, symlink_directory).unwrap(); + + let symlink_filename_str = "symlink_file"; + let symlink_filename = server.path().join(symlink_filename_str); + let symlinked_file = server.path().join(FILES[0]); + symlink_file(symlinked_file, symlink_filename).unwrap(); + + let list = list_webdav(server.url(), "/").unwrap(); + + assert_eq!( + symlinks_should_show, + list.iter().any(|el| + matches!(el, ListEntity::File(ListFile { href, .. }) if href.contains(symlink_filename_str)) + ), + ); + + assert_eq!( + symlinks_should_show, + list.iter().any(|el| + matches!(el, ListEntity::Folder(ListFolder { href, .. }) if href.contains(symlink_directory_str)) + ), + ); + + let list_linked = list_webdav(server.url(), &format!("/{}", symlink_directory_str)); + + assert_eq!(symlinks_should_show, list_linked.is_ok()); +} + +#[rstest] +fn webdav_works_with_route_prefix( + #[with(&["--enable-webdav", "--route-prefix", "test-prefix"])] server: TestServer, +) -> Result<(), Error> { + let prefixed_list = list_webdav(server.url().join("test-prefix")?, "/")?; + + assert!( + prefixed_list.iter().any(|el| + matches!(el, ListEntity::Folder(ListFolder { href, .. }) if href.contains(DIRECTORIES[0])) + ) + ); + + let root_list = list_webdav(server.url(), "/"); + + assert!(root_list.is_err()); + + Ok(()) +} + +// timeout is used in case the binary does not exit as expected and starts waiting for requests +#[rstest] +#[timeout(std::time::Duration::from_secs(1))] +fn webdav_single_file_refuses_starting(tmpdir: TempDir) { + Command::cargo_bin("miniserve") + .unwrap() + .current_dir(tmpdir.path()) + .arg(FILES[0]) + .arg("--enable-webdav") + .assert() + .failure() + .stderr(contains(format!( + "Error: The --enable-webdav option was provided, but the serve path '{}' is a file", + FILES[0] + ))); +} -- cgit v1.2.3 From a4144c9fb39c7a3cc1c15a8caec68b32de938ce7 Mon Sep 17 00:00:00 2001 From: Sven-Hendrik Haase Date: Thu, 6 Feb 2025 04:12:21 +0100 Subject: Make symlinks into global fixtures So far, tests had to create their own symlinks which made them less concise. Also, now that we always have symlinks in all tests, side effects of having them won't go undetected. --- tests/webdav.rs | 26 ++++++-------------------- 1 file changed, 6 insertions(+), 20 deletions(-) (limited to 'tests/webdav.rs') diff --git a/tests/webdav.rs b/tests/webdav.rs index 1bc7e12..eb97e3c 100644 --- a/tests/webdav.rs +++ b/tests/webdav.rs @@ -1,7 +1,3 @@ -#[cfg(unix)] -use std::os::unix::fs::{symlink as symlink_dir, symlink as symlink_file}; -#[cfg(windows)] -use std::os::windows::fs::{symlink_dir, symlink_file}; use std::process::Command; use assert_cmd::prelude::*; @@ -17,7 +13,8 @@ use rstest::rstest; mod fixtures; use crate::fixtures::{ - server, tmpdir, Error, TestServer, DIRECTORIES, FILES, HIDDEN_DIRECTORIES, HIDDEN_FILES, + server, server_no_stderr, tmpdir, Error, TestServer, DIRECTORIES, DIRECTORY_SYMLINK, FILES, + FILE_SYMLINK, HIDDEN_DIRECTORIES, HIDDEN_FILES, }; #[rstest] @@ -93,36 +90,25 @@ fn webdav_respects_hidden_flag( #[rstest] #[case(server(&["--enable-webdav"]), true)] #[should_panic] -#[case(server(&["--enable-webdav", "--no-symlinks"]), false)] +#[case(server_no_stderr(&["--enable-webdav", "--no-symlinks"]), false)] fn webdav_respects_no_symlink_flag(#[case] server: TestServer, #[case] symlinks_should_show: bool) { - // Make symlinks - let symlink_directory_str = "symlink_directory"; - let symlink_directory = server.path().join(symlink_directory_str); - let symlinked_direcotry = server.path().join(DIRECTORIES[0]); - symlink_dir(symlinked_direcotry, symlink_directory).unwrap(); - - let symlink_filename_str = "symlink_file"; - let symlink_filename = server.path().join(symlink_filename_str); - let symlinked_file = server.path().join(FILES[0]); - symlink_file(symlinked_file, symlink_filename).unwrap(); - let list = list_webdav(server.url(), "/").unwrap(); assert_eq!( symlinks_should_show, list.iter().any(|el| - matches!(el, ListEntity::File(ListFile { href, .. }) if href.contains(symlink_filename_str)) + matches!(el, ListEntity::File(ListFile { href, .. }) if href.contains(FILE_SYMLINK)) ), ); assert_eq!( symlinks_should_show, list.iter().any(|el| - matches!(el, ListEntity::Folder(ListFolder { href, .. }) if href.contains(symlink_directory_str)) + matches!(el, ListEntity::Folder(ListFolder { href, .. }) if href.contains(DIRECTORY_SYMLINK)) ), ); - let list_linked = list_webdav(server.url(), &format!("/{}", symlink_directory_str)); + let list_linked = list_webdav(server.url(), &format!("/{}", DIRECTORY_SYMLINK)); assert_eq!(symlinks_should_show, list_linked.is_ok()); } -- cgit v1.2.3 From f0eb61436e62d0d0d755ac8280bf97b4b52d4e0b Mon Sep 17 00:00:00 2001 From: Sven-Hendrik Haase Date: Thu, 6 Feb 2025 04:30:28 +0100 Subject: Get rid of server_no_stderr We'll now always just pipe the contents of the child to the parent. --- tests/webdav.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'tests/webdav.rs') diff --git a/tests/webdav.rs b/tests/webdav.rs index eb97e3c..09d04e9 100644 --- a/tests/webdav.rs +++ b/tests/webdav.rs @@ -13,8 +13,8 @@ use rstest::rstest; mod fixtures; use crate::fixtures::{ - server, server_no_stderr, tmpdir, Error, TestServer, DIRECTORIES, DIRECTORY_SYMLINK, FILES, - FILE_SYMLINK, HIDDEN_DIRECTORIES, HIDDEN_FILES, + server, tmpdir, Error, TestServer, DIRECTORIES, DIRECTORY_SYMLINK, FILES, FILE_SYMLINK, + HIDDEN_DIRECTORIES, HIDDEN_FILES, }; #[rstest] @@ -90,7 +90,7 @@ fn webdav_respects_hidden_flag( #[rstest] #[case(server(&["--enable-webdav"]), true)] #[should_panic] -#[case(server_no_stderr(&["--enable-webdav", "--no-symlinks"]), false)] +#[case(server(&["--enable-webdav", "--no-symlinks"]), false)] fn webdav_respects_no_symlink_flag(#[case] server: TestServer, #[case] symlinks_should_show: bool) { let list = list_webdav(server.url(), "/").unwrap(); -- cgit v1.2.3