use getattrlistbulk::{read_dir, DirReader, RequestedAttributes, ObjectType};
use std::fs;
use tempfile::tempdir;
#[test]
fn test_parse_name_only() {
let dir = tempdir().expect("create temp dir");
fs::write(dir.path().join("simple.txt"), "content").expect("write file");
let attrs = RequestedAttributes {
name: true,
..Default::default()
};
let entries: Vec<_> = read_dir(dir.path(), attrs)
.expect("read dir")
.filter_map(|e| e.ok())
.collect();
assert_eq!(entries.len(), 1);
assert_eq!(entries[0].name, "simple.txt");
assert!(entries[0].size.is_none());
assert!(entries[0].object_type.is_none());
}
#[test]
fn test_parse_all_attributes() {
let dir = tempdir().expect("create temp dir");
let content = "test content 12345";
fs::write(dir.path().join("full.txt"), content).expect("write file");
let attrs = RequestedAttributes::all();
let entries: Vec<_> = read_dir(dir.path(), attrs)
.expect("read dir")
.filter_map(|e| e.ok())
.collect();
assert_eq!(entries.len(), 1);
let entry = &entries[0];
assert_eq!(entry.name, "full.txt");
assert_eq!(entry.object_type, Some(ObjectType::Regular));
assert_eq!(entry.size, Some(content.len() as u64));
assert!(entry.alloc_size.is_some());
assert!(entry.modified_time.is_some());
assert!(entry.permissions.is_some());
assert!(entry.inode.is_some());
assert!(entry.entry_count.is_none());
}
#[test]
fn test_parse_directory_entry() {
let dir = tempdir().expect("create temp dir");
fs::create_dir(dir.path().join("subdir")).expect("create subdir");
fs::write(dir.path().join("subdir").join("child.txt"), "x").expect("write child");
let attrs = RequestedAttributes {
name: true,
object_type: true,
entry_count: true,
..Default::default()
};
let entries: Vec<_> = read_dir(dir.path(), attrs)
.expect("read dir")
.filter_map(|e| e.ok())
.collect();
assert_eq!(entries.len(), 1);
let entry = &entries[0];
assert_eq!(entry.name, "subdir");
assert_eq!(entry.object_type, Some(ObjectType::Directory));
assert!(entry.is_dir());
assert!(entry.entry_count.is_some());
assert_eq!(entry.entry_count, Some(1)); }
#[test]
fn test_parse_multiple_entries() {
let dir = tempdir().expect("create temp dir");
for i in 0..10 {
fs::write(dir.path().join(format!("file_{}.txt", i)), format!("content {}", i))
.expect("write file");
}
let attrs = RequestedAttributes {
name: true,
size: true,
..Default::default()
};
let entries: Vec<_> = read_dir(dir.path(), attrs)
.expect("read dir")
.filter_map(|e| e.ok())
.collect();
assert_eq!(entries.len(), 10);
let names: Vec<_> = entries.iter().map(|e| e.name.as_str()).collect();
for i in 0..10 {
let expected = format!("file_{}.txt", i);
assert!(names.contains(&expected.as_str()), "missing {}", expected);
}
}
#[test]
fn test_parse_special_filenames() {
let dir = tempdir().expect("create temp dir");
let filenames = [
"normal.txt",
"with spaces.txt",
"with-dashes.txt",
"with_underscores.txt",
"UPPERCASE.TXT",
"MixedCase.Txt",
"123numeric.txt",
".hidden",
];
for name in &filenames {
fs::write(dir.path().join(name), "x").expect("write file");
}
let attrs = RequestedAttributes {
name: true,
..Default::default()
};
let entries: Vec<_> = read_dir(dir.path(), attrs)
.expect("read dir")
.filter_map(|e| e.ok())
.collect();
assert_eq!(entries.len(), filenames.len());
let names: Vec<_> = entries.iter().map(|e| e.name.as_str()).collect();
for expected in &filenames {
assert!(names.contains(expected), "missing {}", expected);
}
}
#[test]
fn test_parse_with_small_buffer() {
let dir = tempdir().expect("create temp dir");
for i in 0..50 {
fs::write(dir.path().join(format!("file_{:03}.txt", i)), format!("content {}", i))
.expect("write file");
}
let attrs = RequestedAttributes {
name: true,
size: true,
..Default::default()
};
let entries: Vec<_> = getattrlistbulk::read_dir_with_buffer(dir.path(), attrs, 4 * 1024)
.expect("read dir")
.filter_map(|e| e.ok())
.collect();
assert_eq!(entries.len(), 50, "should read all files even with small buffer");
}
#[test]
fn test_object_type_parsing() {
let dir = tempdir().expect("create temp dir");
fs::write(dir.path().join("regular.txt"), "content").expect("write file");
fs::create_dir(dir.path().join("directory")).expect("create dir");
#[cfg(unix)]
{
use std::os::unix::fs::symlink;
let _ = symlink("regular.txt", dir.path().join("link.txt"));
}
let attrs = RequestedAttributes {
name: true,
object_type: true,
..Default::default()
};
let entries: Vec<_> = read_dir(dir.path(), attrs)
.expect("read dir")
.filter_map(|e| e.ok())
.collect();
let regular = entries.iter().find(|e| e.name == "regular.txt");
assert!(regular.is_some());
assert_eq!(regular.unwrap().object_type, Some(ObjectType::Regular));
assert!(regular.unwrap().is_file());
let directory = entries.iter().find(|e| e.name == "directory");
assert!(directory.is_some());
assert_eq!(directory.unwrap().object_type, Some(ObjectType::Directory));
assert!(directory.unwrap().is_dir());
#[cfg(unix)]
{
if let Some(link) = entries.iter().find(|e| e.name == "link.txt") {
assert!(link.object_type.is_some());
}
}
}
#[test]
fn test_dir_entry_helpers() {
let dir = tempdir().expect("create temp dir");
fs::write(dir.path().join("file.txt"), "x").expect("write file");
fs::create_dir(dir.path().join("subdir")).expect("create dir");
let attrs = RequestedAttributes {
name: true,
object_type: true,
..Default::default()
};
let entries: Vec<_> = read_dir(dir.path(), attrs)
.expect("read dir")
.filter_map(|e| e.ok())
.collect();
let file = entries.iter().find(|e| e.name == "file.txt").unwrap();
let subdir = entries.iter().find(|e| e.name == "subdir").unwrap();
assert!(file.is_file());
assert!(!file.is_dir());
assert!(!file.is_symlink());
assert!(subdir.is_dir());
assert!(!subdir.is_file());
assert!(!subdir.is_symlink());
}
#[test]
fn test_builder_selective_attributes() {
let dir = tempdir().expect("create temp dir");
fs::write(dir.path().join("test.txt"), "hello world").expect("write file");
let entries: Vec<_> = DirReader::new(dir.path())
.name()
.size()
.read()
.expect("read dir")
.filter_map(|e| e.ok())
.collect();
assert_eq!(entries.len(), 1);
let entry = &entries[0];
assert_eq!(entry.name, "test.txt");
assert_eq!(entry.size, Some(11));
assert!(entry.object_type.is_none());
}