use super::*;
use std::fs;
use tempfile::tempdir;
fn enc(path: &str) -> String {
path.replace('/', "%2F")
}
#[test]
fn delivery_root_is_the_state_roots_bl_delivery_tree() {
assert_eq!(
delivery_root(Path::new("/s/balls/clones")),
Some(PathBuf::from("/s/balls/plugins/bl-delivery")),
);
assert_eq!(delivery_root(Path::new("/")), None);
}
#[test]
fn is_internal_matches_only_under_the_delivery_tree() {
let d = PathBuf::from("/s/balls/plugins/bl-delivery");
assert!(is_internal(
Path::new("/s/balls/plugins/bl-delivery/home/u/p/bl-1"),
Some(&d),
));
assert!(!is_internal(Path::new("/home/u/p"), Some(&d)));
assert!(!is_internal(Path::new("/anything"), None));
}
#[test]
fn missing_clones_dir_enumerates_empty() {
let dir = tempdir().unwrap();
assert!(enumerate(&dir.path().join("absent")).is_empty());
}
#[test]
fn enumerate_decodes_flags_internal_and_skips_non_dirs() {
let root = tempdir().unwrap();
let clones = root.path().join("balls").join("clones");
fs::create_dir_all(&clones).unwrap();
let delivery = root.path().join("balls/plugins/bl-delivery");
fs::create_dir(clones.join(enc("/home/u/proj"))).unwrap();
let internal_path = format!("{}/home/u/proj/bl-1", delivery.display());
fs::create_dir(clones.join(enc(&internal_path))).unwrap();
fs::write(clones.join("stray-file"), b"x").unwrap();
let projects = enumerate(&clones);
assert_eq!(projects.len(), 2, "non-dir entry skipped");
let normal = projects.iter().find(|p| !p.internal).unwrap();
assert_eq!(normal.path, PathBuf::from("/home/u/proj"));
let internal = projects.iter().find(|p| p.internal).unwrap();
assert_eq!(internal.path, PathBuf::from(internal_path));
let mut sorted = projects.clone();
sorted.sort_by(|a, b| a.path.cmp(&b.path));
assert_eq!(projects, sorted);
}
#[cfg(not(target_os = "macos"))]
#[test]
fn enumerate_skips_non_utf8_basenames() {
use std::ffi::OsStr;
use std::os::unix::ffi::OsStrExt;
let clones = tempdir().unwrap();
fs::create_dir(clones.path().join(enc("/home/u/proj"))).unwrap();
fs::create_dir(clones.path().join(OsStr::from_bytes(&[0x66, 0x80]))).unwrap();
let projects = enumerate(clones.path());
assert_eq!(projects.len(), 1, "non-UTF-8 basename skipped");
assert_eq!(projects[0].path, PathBuf::from("/home/u/proj"));
}
#[test]
fn a_label_is_the_basename() {
let paths = [
PathBuf::from("/home/u/dev/yog"),
PathBuf::from("/tmp/scratch-9f2/litany"),
];
assert_eq!(labels(&paths), vec!["yog".to_owned(), "litany".to_owned()]);
}
#[test]
fn colliding_basenames_extend_leftward_until_they_differ() {
let paths = [
PathBuf::from("/home/u/work/yog"),
PathBuf::from("/home/u/play/yog"),
PathBuf::from("/home/u/play/litany"),
];
assert_eq!(
labels(&paths),
vec![
"work/yog".to_owned(),
"play/yog".to_owned(),
"litany".to_owned(),
]
);
}
#[test]
fn a_label_extends_no_further_than_it_must_and_a_repeat_labels_alike() {
let paths = [PathBuf::from("/a/p"), PathBuf::from("/b/p")];
assert_eq!(labels(&paths), vec!["a/p".to_owned(), "b/p".to_owned()]);
let twice = [PathBuf::from("/a/p"), PathBuf::from("/a/p")];
assert_eq!(labels(&twice), vec!["/a/p".to_owned(), "/a/p".to_owned()]);
}
#[test]
fn a_runaway_label_elides() {
let long = format!("/home/u/{}", "x".repeat(200));
let got = labels(&[PathBuf::from(&long)]);
assert_eq!(got[0].chars().count(), LABEL_MAX, "capped");
assert!(got[0].ends_with('…'), "marked: {}", got[0]);
assert!(got[0].starts_with("xxx"), "head kept: {}", got[0]);
let exact = PathBuf::from(format!("/home/u/{}", "y".repeat(LABEL_MAX)));
assert_eq!(labels(&[exact])[0], "y".repeat(LABEL_MAX));
}
#[test]
fn no_projects_label_nothing() {
assert!(labels(&[]).is_empty());
}
#[test]
fn visible_always_filters_internal_clones() {
let projects = vec![
Project {
path: PathBuf::from("/a"),
internal: false,
},
Project {
path: PathBuf::from("/b"),
internal: true,
},
];
let shown: Vec<_> = visible(&projects).iter().map(|p| &p.path).collect();
assert_eq!(shown, vec![&PathBuf::from("/a")]);
}