use std::sync::Arc; use repo_metadata::file_tree_store::{FileTreeDirectoryEntryState, FileTreeEntryState}; use repo_metadata::{FileMetadata, FileTreeEntry}; use warp_util::standardized_path::StandardizedPath; use super::sort_entries_for_file_tree; fn std_path(s: &str) -> StandardizedPath { StandardizedPath::try_new(s).expect("test path should be valid") } fn dir_state(path: &str) -> FileTreeEntryState { FileTreeEntryState::Directory(FileTreeDirectoryEntryState { path: Arc::new(std_path(path)), ignored: false, loaded: true, }) } fn file_state(path: &str) -> FileTreeEntryState { FileTreeEntryState::File(FileMetadata::from_standardized(std_path(path), false).into()) } #[test] fn sort_entries_for_file_tree_is_antisymmetric_for_missing_entries() { let root = std_path("/repo"); let mut entry = FileTreeEntry::new_for_directory(Arc::new(root.clone())); entry.insert_child_state(&root, dir_state("/repo/src")); entry.insert_child_state(&root, file_state("/repo/README.md")); let paths = [ std_path("/repo/src"), // present (directory) std_path("/repo/README.md"), // present (file) std_path("/repo/ghost_a"), // missing std_path("/repo/ghost_b"), // missing ]; for a in &paths { for b in &paths { let ab = sort_entries_for_file_tree(a, b, &entry); let ba = sort_entries_for_file_tree(b, a, &entry); assert_eq!( ab.reverse(), ba, "comparator not antisymmetric for ({}, {}): cmp(a,b) = {:?}, cmp(b,a) = {:?}", a.as_str(), b.as_str(), ab, ba, ); } } } #[test] fn sort_entries_for_file_tree_sorts_without_panicking_on_missing_children() { let root = std_path("/repo"); let mut entry = FileTreeEntry::new_for_directory(Arc::new(root.clone())); entry.insert_child_state(&root, dir_state("/repo/src")); // Multiple missing entries are required to reliably trigger the sort's // total-order violation check. let mut paths = [ std_path("/repo/src"), std_path("/repo/ghost_a"), std_path("/repo/ghost_b"), std_path("/repo/ghost_c"), std_path("/repo/ghost_d"), std_path("/repo/ghost_e"), ]; paths.sort_by(|a, b| sort_entries_for_file_tree(a, b, &entry)); } #[test] fn sort_entries_for_file_tree_uses_natural_order_for_numbered_files() { let root = std_path("/repo"); let mut entry = FileTreeEntry::new_for_directory(Arc::new(root.clone())); for name in ["L1", "L2", "L3", "L10", "L11", "L12"] { entry.insert_child_state(&root, file_state(&format!("/repo/{name}.tsx"))); } let mut paths = [ std_path("/repo/L10.tsx"), std_path("/repo/L2.tsx"), std_path("/repo/L1.tsx"), std_path("/repo/L12.tsx"), std_path("/repo/L3.tsx"), std_path("/repo/L11.tsx"), ]; paths.sort_by(|a, b| sort_entries_for_file_tree(a, b, &entry)); let sorted: Vec<&str> = paths.iter().map(|p| p.as_str()).collect(); assert_eq!( sorted, [ "/repo/L1.tsx", "/repo/L2.tsx", "/repo/L3.tsx", "/repo/L10.tsx", "/repo/L11.tsx", "/repo/L12.tsx", ] ); }