From 504f63bf28afa1673625d8a5b4fbbe3162f72f99 Mon Sep 17 00:00:00 2001 From: Ferran Borreguero Date: Sun, 11 Jan 2026 09:55:49 +0800 Subject: [PATCH 1/3] Use fixtures in tests --- Cargo.lock | 2 + crates/fetcher/Cargo.toml | 2 + crates/fetcher/src/lib.rs | 100 +++++++++++++++++++++++++++++++++----- 3 files changed, 91 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5a704c8..a719a67 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1776,6 +1776,8 @@ dependencies = [ "eyre", "flate2", "reqwest", + "serde", + "serde_json", "sha2", "tar", "tracing", diff --git a/crates/fetcher/Cargo.toml b/crates/fetcher/Cargo.toml index 5b9226b..aa21943 100644 --- a/crates/fetcher/Cargo.toml +++ b/crates/fetcher/Cargo.toml @@ -17,3 +17,5 @@ tar = "0.4" sha2 = "0.10" tracing = "0.1" tracing-subscriber = { version = "0.3", features = ["env-filter"] } +serde = { workspace = true, features = ["derive"] } +serde_json = { workspace = true } diff --git a/crates/fetcher/src/lib.rs b/crates/fetcher/src/lib.rs index 296b5b0..a22b6d8 100644 --- a/crates/fetcher/src/lib.rs +++ b/crates/fetcher/src/lib.rs @@ -241,34 +241,108 @@ fn extract_tar_gz(reader: R, destination: &Path) -> Result<()> { mod tests { use super::*; use std::fs; + use std::sync::{Arc, Mutex}; - #[test] - fn test_download_readme() { - let source = - "https://raw.githubusercontent.com/ferranbt/bbuilder/refs/heads/main/README.md"; - let destination = PathBuf::from("/tmp/fetcher_test_readme.md"); + struct TestProgressTracker { + set_total_called: Arc>, + update_called: Arc>, + finish_called: Arc>, + } + + impl ProgressTracker for TestProgressTracker { + fn set_total(&mut self, _total: u64) { + *self.set_total_called.lock().unwrap() = true; + } + + fn update(&mut self, _downloaded: u64) { + *self.update_called.lock().unwrap() = true; + } + + fn finish(&mut self) { + *self.finish_called.lock().unwrap() = true; + } + } + + fn test_download_file(filename: &str, checksum: &str) { + let source = format!( + "https://raw.githubusercontent.com/ferranbt/bbuilder/refs/heads/main/crates/fetcher/fixtures/{}", + filename + ); + let destination = PathBuf::from(format!("/tmp/fetcher_test_{}", filename)); // Clean up any existing file let _ = fs::remove_file(&destination); - // Download the file with checksum verification - // Expected SHA-256 checksum for the README.md file - let checksum = "79dcadb1ef725cbc30bb3a9a877cff3702e9d3bb28baff74265a9d70a2e8874b"; - let result = fetch(source, &destination, Some(checksum.to_string())); + let set_total_called = Arc::new(Mutex::new(false)); + let update_called = Arc::new(Mutex::new(false)); + let finish_called = Arc::new(Mutex::new(false)); + + let mut progress = TestProgressTracker { + set_total_called: set_total_called.clone(), + update_called: update_called.clone(), + finish_called: finish_called.clone(), + }; + + // Download the file with checksum verification and progress tracking + let result = fetch_with_progress( + &source, + &destination, + &mut progress, + Some(checksum.to_string()), + ); assert!( result.is_ok(), - "Failed to download file or verify checksum: {:?}", + "Failed to download {} or verify checksum: {:?}", + filename, result.err() ); // Verify the file exists - assert!(destination.exists(), "Downloaded file does not exist"); + assert!( + destination.exists(), + "Downloaded file {} does not exist", + filename + ); // Verify the file has content - let content = fs::read_to_string(&destination).expect("Failed to read downloaded file"); - assert!(!content.is_empty(), "Downloaded file is empty"); + let metadata = fs::metadata(&destination) + .expect(&format!("Failed to read file metadata for {}", filename)); + assert!(metadata.len() > 0, "Downloaded file {} is empty", filename); + + // Verify progress tracker methods were called + assert!( + *set_total_called.lock().unwrap(), + "set_total was not called for {}", + filename + ); + assert!( + *update_called.lock().unwrap(), + "update was not called for {}", + filename + ); + assert!( + *finish_called.lock().unwrap(), + "finish was not called for {}", + filename + ); // Clean up let _ = fs::remove_file(&destination); } + + #[test] + fn test_download_content_txt() { + test_download_file( + "content.txt", + "3dc7bc0209231cc61cb7d09c2efdfdf7aacb1f0b098db150780e980fa10d6b7a", + ); + } + + #[test] + fn test_download_content_tar_gz() { + test_download_file( + "content.tar.gz", + "aa7d1aae79175b06c5529409d65f4794479c9b060381e059a8b6d1510fa2ae48", + ); + } } From dff977ed0a56b2ea5ea1618e6dad9c848d31e797 Mon Sep 17 00:00:00 2001 From: Ferran Borreguero Date: Sun, 11 Jan 2026 09:57:39 +0800 Subject: [PATCH 2/3] Remove comments --- crates/fetcher/src/lib.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/crates/fetcher/src/lib.rs b/crates/fetcher/src/lib.rs index a22b6d8..44b39a7 100644 --- a/crates/fetcher/src/lib.rs +++ b/crates/fetcher/src/lib.rs @@ -270,7 +270,6 @@ mod tests { ); let destination = PathBuf::from(format!("/tmp/fetcher_test_{}", filename)); - // Clean up any existing file let _ = fs::remove_file(&destination); let set_total_called = Arc::new(Mutex::new(false)); @@ -283,7 +282,6 @@ mod tests { finish_called: finish_called.clone(), }; - // Download the file with checksum verification and progress tracking let result = fetch_with_progress( &source, &destination, @@ -297,19 +295,16 @@ mod tests { result.err() ); - // Verify the file exists assert!( destination.exists(), "Downloaded file {} does not exist", filename ); - // Verify the file has content let metadata = fs::metadata(&destination) .expect(&format!("Failed to read file metadata for {}", filename)); assert!(metadata.len() > 0, "Downloaded file {} is empty", filename); - // Verify progress tracker methods were called assert!( *set_total_called.lock().unwrap(), "set_total was not called for {}", @@ -326,7 +321,6 @@ mod tests { filename ); - // Clean up let _ = fs::remove_file(&destination); } From 5bcf9e88421e4c3c8da90ad1ee3c582b884708b6 Mon Sep 17 00:00:00 2001 From: Ferran Borreguero Date: Sun, 11 Jan 2026 16:22:52 +0800 Subject: [PATCH 3/3] Improve tar.gz test --- crates/fetcher/src/lib.rs | 107 +++++++++++++++++++++----------------- 1 file changed, 59 insertions(+), 48 deletions(-) diff --git a/crates/fetcher/src/lib.rs b/crates/fetcher/src/lib.rs index 44b39a7..76d739f 100644 --- a/crates/fetcher/src/lib.rs +++ b/crates/fetcher/src/lib.rs @@ -249,6 +249,25 @@ mod tests { finish_called: Arc>, } + impl TestProgressTracker { + fn new() -> Self { + Self { + set_total_called: Arc::new(Mutex::new(false)), + update_called: Arc::new(Mutex::new(false)), + finish_called: Arc::new(Mutex::new(false)), + } + } + + fn assert_ok(&self) { + assert!( + *self.set_total_called.lock().unwrap(), + "set_total was not called", + ); + assert!(*self.update_called.lock().unwrap(), "update was not called",); + assert!(*self.finish_called.lock().unwrap(), "finish was not called",); + } + } + impl ProgressTracker for TestProgressTracker { fn set_total(&mut self, _total: u64) { *self.set_total_called.lock().unwrap() = true; @@ -263,24 +282,30 @@ mod tests { } } - fn test_download_file(filename: &str, checksum: &str) { - let source = format!( + fn get_fixture_path(filename: &str) -> String { + format!( "https://raw.githubusercontent.com/ferranbt/bbuilder/refs/heads/main/crates/fetcher/fixtures/{}", filename - ); + ) + } + + fn ensure_fixture_file(path: &PathBuf) { + const CONTENT_TXT: &[u8] = include_bytes!("../fixtures/content.txt"); + let actual_content = fs::read(path).expect(&format!("Failed to read file at {:?}", path)); + assert_eq!(actual_content, CONTENT_TXT); + } + + #[test] + fn test_download_content_txt() { + let filename = "content.txt"; + let checksum = "3dc7bc0209231cc61cb7d09c2efdfdf7aacb1f0b098db150780e980fa10d6b7a"; + + let source = get_fixture_path(filename); let destination = PathBuf::from(format!("/tmp/fetcher_test_{}", filename)); let _ = fs::remove_file(&destination); - let set_total_called = Arc::new(Mutex::new(false)); - let update_called = Arc::new(Mutex::new(false)); - let finish_called = Arc::new(Mutex::new(false)); - - let mut progress = TestProgressTracker { - set_total_called: set_total_called.clone(), - update_called: update_called.clone(), - finish_called: finish_called.clone(), - }; + let mut progress = TestProgressTracker::new(); let result = fetch_with_progress( &source, @@ -295,48 +320,34 @@ mod tests { result.err() ); - assert!( - destination.exists(), - "Downloaded file {} does not exist", - filename - ); - - let metadata = fs::metadata(&destination) - .expect(&format!("Failed to read file metadata for {}", filename)); - assert!(metadata.len() > 0, "Downloaded file {} is empty", filename); - - assert!( - *set_total_called.lock().unwrap(), - "set_total was not called for {}", - filename - ); - assert!( - *update_called.lock().unwrap(), - "update was not called for {}", - filename - ); - assert!( - *finish_called.lock().unwrap(), - "finish was not called for {}", - filename - ); + ensure_fixture_file(&destination); + progress.assert_ok(); let _ = fs::remove_file(&destination); } - #[test] - fn test_download_content_txt() { - test_download_file( - "content.txt", - "3dc7bc0209231cc61cb7d09c2efdfdf7aacb1f0b098db150780e980fa10d6b7a", - ); - } - #[test] fn test_download_content_tar_gz() { - test_download_file( - "content.tar.gz", - "aa7d1aae79175b06c5529409d65f4794479c9b060381e059a8b6d1510fa2ae48", + let filename = "content.tar.gz"; + + let source = get_fixture_path(filename); + let destination = PathBuf::from(format!("/tmp/fetcher_test_{}", filename)); + + let _ = fs::remove_file(&destination); + + let mut progress = TestProgressTracker::new(); + + let result = fetch_with_progress(&source, &destination, &mut progress, None); + assert!( + result.is_ok(), + "Failed to download {} or verify checksum: {:?}", + filename, + result.err() ); + + ensure_fixture_file(&destination.join("content.txt")); + progress.assert_ok(); + + let _ = fs::remove_file(&destination); } }