From c7a7c66ac99d91eb08ce6091ecee53d22a0d945f Mon Sep 17 00:00:00 2001 From: Lzzzt <101313294+Lzzzzzt@users.noreply.github.com> Date: Tue, 24 Sep 2024 11:03:03 +0800 Subject: [PATCH] test: add unit test for dfget (#748) Signed-off-by: lzzzt --- Cargo.lock | 1 + dragonfly-client/Cargo.toml | 3 + dragonfly-client/src/bin/dfget/main.rs | 182 +++++++++++++++++++++++++ 3 files changed, 186 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index 2d16fff5..93e8fee2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -903,6 +903,7 @@ dependencies = [ "serde_json", "sysinfo", "tabled", + "tempfile", "termion", "tikv-jemallocator", "tokio", diff --git a/dragonfly-client/Cargo.toml b/dragonfly-client/Cargo.toml index 230b5826..17e797c7 100644 --- a/dragonfly-client/Cargo.toml +++ b/dragonfly-client/Cargo.toml @@ -92,6 +92,9 @@ termion = "4.0.2" tabled = "0.16.0" path-absolutize = "3.1.1" +[dev-dependencies] +tempfile.workspace = true + [target.'cfg(not(target_env = "msvc"))'.dependencies] tikv-jemallocator = { version = "0.5.4", features = ["profiling", "stats", "unprefixed_malloc_on_supported_platforms", "background_threads"] } diff --git a/dragonfly-client/src/bin/dfget/main.rs b/dragonfly-client/src/bin/dfget/main.rs index 2b441aa4..231b66a0 100644 --- a/dragonfly-client/src/bin/dfget/main.rs +++ b/dragonfly-client/src/bin/dfget/main.rs @@ -888,3 +888,185 @@ fn validate_args(args: &Args) -> Result<()> { Ok(()) } + +#[cfg(test)] +mod tests { + use tempfile::tempdir; + + use super::*; + + const BIN: &str = "dfget"; + const OUTPUT: &str = "--output"; + const FILE_URL: &str = "http://test.local/test.txt"; + const DIR_URL: &str = "http://test.local/test-dir/"; + + #[test] + fn should_validate_args() { + let tempdir = tempfile::tempdir().unwrap(); + // Download file. + let output_path = tempdir.path().join("test.txt"); + let args = Args::parse_from(vec![ + BIN.to_string(), + FILE_URL.to_string(), + OUTPUT.into(), + output_path.display().to_string(), + ]); + + let result = validate_args(&args); + assert!(result.is_ok()); + + // Download directory. + let output_path = tempdir.path(); + let args = Args::parse_from(vec![ + BIN.to_string(), + DIR_URL.to_string(), + OUTPUT.into(), + output_path.display().to_string(), + ]); + + let result = validate_args(&args); + assert!(result.is_ok()); + } + + #[test] + fn should_return_error_when_args_is_not_valid() { + let tempdir = tempfile::tempdir().unwrap(); + let file_path = tempdir.path().join("test.txt"); + let dir_path = tempdir.path(); + let non_existent_dir_path = dir_path.join("non_exsitent"); + let non_existent_file_path = non_existent_dir_path.join("test.txt"); + + std::fs::File::create(&file_path).unwrap(); + + let test_cases = vec![ + ( + Args::parse_from(vec![ + BIN.to_string(), + DIR_URL.to_string(), + OUTPUT.into(), + file_path.display().to_string(), + ]), + format!("output path {} is not a directory", file_path.display()), + ), + ( + Args::parse_from(vec![ + BIN.to_string(), + DIR_URL.to_string(), + OUTPUT.into(), + non_existent_dir_path.display().to_string(), + ]), + format!( + "output path {} is not a directory", + non_existent_dir_path.display() + ), + ), + ( + Args::parse_from(vec![ + BIN.to_string(), + FILE_URL.to_string(), + OUTPUT.into(), + file_path.display().to_string(), + ]), + format!("output path {} is already exist", file_path.display()), + ), + ( + Args::parse_from(vec![ + BIN.to_string(), + FILE_URL.into(), + OUTPUT.into(), + non_existent_file_path.display().to_string(), + ]), + format!( + "output path {} is not a directory", + non_existent_dir_path.display() + ), + ), + ( + Args::parse_from(vec![ + BIN.to_string(), + FILE_URL.into(), + OUTPUT.into(), + "/".to_string(), + ]), + "output path / is not exist".to_string(), + ), + ]; + + for (args, error_message) in test_cases { + let result = validate_args(&args); + assert!(result.is_err()); + assert_eq!( + result.unwrap_err().to_string(), + Error::ValidationError(error_message).to_string() + ) + } + } + + #[test] + fn should_make_output_by_entry() { + let url = Url::parse("http://example.com/root/").unwrap(); + + let temp_dir = tempdir().unwrap(); + let output = temp_dir.path().to_path_buf(); + + let entry = DirEntry { + url: Url::parse("http://example.com/root/dir/file.txt") + .unwrap() + .to_string(), + content_length: 100, + is_dir: false, + }; + + let result = make_output_by_entry(url, &output, entry); + + assert!(result.is_ok()); + assert_eq!(result.unwrap(), output.join("dir/file.txt")); + } + + #[test] + fn should_make_output_by_entry_no_trailing_slash_in_output() { + let url = Url::parse("http://example.com/root/").unwrap(); + + let temp_dir = tempdir().unwrap(); + let output = PathBuf::from_str( + temp_dir + .path() + .to_string_lossy() + .to_string() + .trim_end_matches('/'), + ) + .unwrap(); + + let entry = DirEntry { + url: Url::parse("http://example.com/root/dir/file.txt") + .unwrap() + .to_string(), + content_length: 100, + is_dir: false, + }; + + let result = make_output_by_entry(url, &output, entry); + + assert!(result.is_ok()); + let path = result.unwrap(); + assert_eq!(path, output.join("dir/file.txt")); + } + + #[test] + fn should_return_error_when_make_output_with_invalid_url() { + let url = Url::parse("http://example.com/root/dir/file.txt").unwrap(); + + let temp_dir = tempdir().unwrap(); + let output = temp_dir.path().to_path_buf(); + + let entry = DirEntry { + url: "invalid_url".to_string(), + content_length: 100, + is_dir: false, + }; + + let result = make_output_by_entry(url, &output, entry); + + assert!(result.is_err()); + } +}