tree-type 0.4.5

Rust macros for creating type-safe filesystem tree structures
Documentation
use tempfile::TempDir;
use tree_type::GenericDir;
use tree_type::GenericFile;
use tree_type::dir_type;
use tree_type::file_type;

#[cfg(unix)]
use std::os::unix::fs::PermissionsExt;

// Test secure() method on file_type generated structs
#[cfg(unix)]
#[test]
fn test_file_type_secure() {
    file_type!(TestFile);

    let temp_dir = TempDir::new().unwrap();
    let file_path = temp_dir.path().join("test.txt");
    let test_file = TestFile::new(file_path).unwrap();

    // Create the file first
    test_file.write("test content").unwrap();

    // Test secure() method
    test_file.secure().unwrap();

    // Verify permissions (0o600 = read/write for owner only)
    let metadata = std::fs::metadata(test_file.as_path()).unwrap();
    let permissions = metadata.permissions();
    assert_eq!(permissions.mode() & 0o777, 0o600);
}

// Test secure() method on dir_type generated structs
#[cfg(unix)]
#[test]
fn test_dir_type_secure() {
    dir_type!(TestDir);

    let temp_dir = TempDir::new().unwrap();
    let dir_path = temp_dir.path().join("test_dir");
    let test_dir = TestDir::new(dir_path).unwrap();

    // Create the directory first
    test_dir.create().unwrap();

    // Test secure() method
    test_dir.secure().unwrap();

    // Verify permissions (0o700 = read/write/execute for owner only)
    let metadata = std::fs::metadata(test_dir.as_path()).unwrap();
    let permissions = metadata.permissions();
    assert_eq!(permissions.mode() & 0o777, 0o700);
}

// Test secure() method signature matches GenericFile/GenericDir
#[cfg(unix)]
#[test]
fn test_secure_method_signature() {
    file_type!(TestFile);
    dir_type!(TestDir);

    let temp_dir = TempDir::new().unwrap();

    // Test file types
    let file_path = temp_dir.path().join("test.txt");
    let test_file = TestFile::new(&file_path).unwrap();
    let generic_file = GenericFile::new(&file_path).unwrap();

    test_file.write("test").unwrap();

    // Both should have the same signature: secure(&self) -> Result<(), std::io::Error>
    let _: Result<(), std::io::Error> = test_file.secure();
    let _: Result<(), std::io::Error> = generic_file.secure();

    // Test directory types
    let dir_path = temp_dir.path().join("test_dir");
    let test_dir = TestDir::new(&dir_path).unwrap();
    let generic_dir = GenericDir::new(&dir_path).unwrap();

    test_dir.create().unwrap();

    // Both should have the same signature: secure(&self) -> Result<(), std::io::Error>
    let _: Result<(), std::io::Error> = test_dir.secure();
    let _: Result<(), std::io::Error> = generic_dir.secure();
}

// Test that secure() method works through delegation
#[cfg(unix)]
#[test]
fn test_secure_delegation() {
    file_type!(TestFile);
    dir_type!(TestDir);

    let temp_dir = TempDir::new().unwrap();

    // Test file delegation
    let file_path = temp_dir.path().join("test.txt");
    let test_file = TestFile::new(&file_path).unwrap();
    test_file.write("test content").unwrap();

    // This should delegate to as_generic().secure()
    test_file.secure().unwrap();

    // Verify it worked the same as calling secure() on GenericFile directly
    let generic_file = test_file.as_generic();
    let metadata1 = std::fs::metadata(&file_path).unwrap();

    // Reset permissions and test GenericFile directly
    let reset_perms = std::fs::Permissions::from_mode(0o644);
    std::fs::set_permissions(&file_path, reset_perms).unwrap();

    generic_file.secure().unwrap();
    let metadata2 = std::fs::metadata(&file_path).unwrap();

    // Both should result in the same permissions
    assert_eq!(
        metadata1.permissions().mode() & 0o777,
        metadata2.permissions().mode() & 0o777
    );

    // Test directory delegation
    let dir_path = temp_dir.path().join("test_dir");
    let test_dir = TestDir::new(&dir_path).unwrap();
    test_dir.create().unwrap();

    // This should delegate to as_generic().secure()
    test_dir.secure().unwrap();

    // Verify it worked the same as calling secure() on GenericDir directly
    let generic_dir = test_dir.as_generic();
    let metadata1 = std::fs::metadata(&dir_path).unwrap();

    // Reset permissions and test GenericDir directly
    let reset_perms = std::fs::Permissions::from_mode(0o755);
    std::fs::set_permissions(&dir_path, reset_perms).unwrap();

    generic_dir.secure().unwrap();
    let metadata2 = std::fs::metadata(&dir_path).unwrap();

    // Both should result in the same permissions
    assert_eq!(
        metadata1.permissions().mode() & 0o777,
        metadata2.permissions().mode() & 0o777
    );
}