mod common;
use common::TempDir;
use diskr::scanner::walker::{scan_path, WalkOptions};
use diskr::analyzer;
use std::fs;
use std::thread::sleep;
use std::time::Duration;
fn scan(dir: &TempDir) -> diskr::scanner::ScanResult {
let opts = WalkOptions { show_progress: false, ..Default::default() };
scan_path(dir.path(), &opts).unwrap()
}
#[test]
fn top_files_respects_min_size_and_order() {
let dir = TempDir::new("size");
fs::write(dir.path().join("small.bin"), vec![0u8; 10]).unwrap();
fs::write(dir.path().join("big.bin"), vec![0u8; 5000]).unwrap();
let result = scan(&dir);
let top = analyzer::size::top_files(&result.root, 1000, 10);
assert_eq!(top.len(), 1);
assert!(top[0].path.ends_with("big.bin"));
}
#[test]
fn type_breakdown_groups_by_category() {
let dir = TempDir::new("types");
fs::write(dir.path().join("a.jpg"), vec![0u8; 100]).unwrap();
fs::write(dir.path().join("b.png"), vec![0u8; 100]).unwrap();
fs::write(dir.path().join("c.mp4"), vec![0u8; 100]).unwrap();
let result = scan(&dir);
let groups = analyzer::size::type_breakdown(&result.root);
let image = groups.iter().find(|(name, _, _)| name == "image").unwrap();
assert_eq!(image.2, 2);
let video = groups.iter().find(|(name, _, _)| name == "video").unwrap();
assert_eq!(video.2, 1);
}
#[test]
fn zero_byte_files_are_found() {
let dir = TempDir::new("zero");
fs::write(dir.path().join("empty.txt"), b"").unwrap();
fs::write(dir.path().join("full.txt"), b"data").unwrap();
let result = scan(&dir);
let zero = analyzer::age::zero_byte_files(&result.root);
assert_eq!(zero.len(), 1);
assert!(zero[0].ends_with("empty.txt"));
}
#[test]
fn empty_dirs_are_found() {
let dir = TempDir::new("emptydir");
fs::create_dir_all(dir.path().join("nested/empty")).unwrap();
fs::write(dir.path().join("nested/file.txt"), b"x").unwrap();
let result = scan(&dir);
let mut out = Vec::new();
analyzer::age::empty_dirs(&result.root, &mut out);
assert!(out.iter().any(|p| p.ends_with("empty")));
assert!(!out.iter().any(|p| p.ends_with("nested")));
}
#[test]
fn duplicate_files_are_detected() {
let dir = TempDir::new("dupes");
let content = vec![7u8; 20_000];
fs::write(dir.path().join("a.bin"), &content).unwrap();
fs::write(dir.path().join("b.bin"), &content).unwrap();
fs::write(dir.path().join("c.bin"), vec![9u8; 20_000]).unwrap();
let result = scan(&dir);
let groups = analyzer::duplicates::find_duplicates(&result.root, 1024);
assert_eq!(groups.len(), 1);
assert_eq!(groups[0].paths.len(), 2);
assert_eq!(groups[0].wasted, content.len() as u64);
}
#[test]
fn dev_caches_are_detected() {
let dir = TempDir::new("caches");
fs::create_dir_all(dir.path().join("project/node_modules/pkg")).unwrap();
fs::write(dir.path().join("project/node_modules/pkg/index.js"), b"x").unwrap();
fs::create_dir_all(dir.path().join("project/src")).unwrap();
let result = scan(&dir);
let mut caches = Vec::new();
analyzer::patterns::find_dev_caches(&result.root, &mut caches);
assert_eq!(caches.len(), 1);
assert_eq!(caches[0].kind, "node_modules");
}
#[test]
fn stale_files_respect_access_time_threshold() {
let dir = TempDir::new("stale");
fs::write(dir.path().join("recent.bin"), vec![0u8; 100_000]).unwrap();
sleep(Duration::from_millis(10));
let result = scan(&dir);
let stale = analyzer::age::stale_files(&result.root, 9999, 1);
assert!(stale.is_empty());
}
#[test]
fn cleanup_script_contains_every_path() {
let paths = vec![std::path::PathBuf::from("/tmp/a"), std::path::PathBuf::from("/tmp/b")];
let script = analyzer::extra::generate_cleanup_script(&paths, true);
assert!(script.starts_with("#!/usr/bin/env bash"));
assert!(script.contains("trash-put \"/tmp/a\""));
assert!(script.contains("trash-put \"/tmp/b\""));
}