sal-os 0.1.2

SAL OS - Operating system interaction utilities with cross-platform abstraction
Documentation
use sal_os::fs;
use std::fs as std_fs;
use tempfile::TempDir;

#[test]
fn test_exist() {
    let temp_dir = TempDir::new().unwrap();
    let temp_path = temp_dir.path();

    // Test directory exists
    assert!(fs::exist(temp_path.to_str().unwrap()));

    // Test file doesn't exist
    let non_existent = temp_path.join("non_existent.txt");
    assert!(!fs::exist(non_existent.to_str().unwrap()));

    // Create a file and test it exists
    let test_file = temp_path.join("test.txt");
    std_fs::write(&test_file, "test content").unwrap();
    assert!(fs::exist(test_file.to_str().unwrap()));
}

#[test]
fn test_mkdir() {
    let temp_dir = TempDir::new().unwrap();
    let new_dir = temp_dir.path().join("new_directory");

    // Directory shouldn't exist initially
    assert!(!fs::exist(new_dir.to_str().unwrap()));

    // Create directory
    let result = fs::mkdir(new_dir.to_str().unwrap());
    assert!(result.is_ok());

    // Directory should now exist
    assert!(fs::exist(new_dir.to_str().unwrap()));

    // Creating existing directory should not error (defensive)
    let result2 = fs::mkdir(new_dir.to_str().unwrap());
    assert!(result2.is_ok());
}

#[test]
fn test_file_write_and_read() {
    let temp_dir = TempDir::new().unwrap();
    let test_file = temp_dir.path().join("test_write.txt");
    let content = "Hello, World!";

    // Write file
    let write_result = fs::file_write(test_file.to_str().unwrap(), content);
    assert!(write_result.is_ok());

    // File should exist
    assert!(fs::exist(test_file.to_str().unwrap()));

    // Read file
    let read_result = fs::file_read(test_file.to_str().unwrap());
    assert!(read_result.is_ok());
    assert_eq!(read_result.unwrap(), content);
}

#[test]
fn test_file_write_append() {
    let temp_dir = TempDir::new().unwrap();
    let test_file = temp_dir.path().join("test_append.txt");

    // Write initial content
    let initial_content = "Line 1\n";
    let append_content = "Line 2\n";

    let write_result = fs::file_write(test_file.to_str().unwrap(), initial_content);
    assert!(write_result.is_ok());

    // Append content
    let append_result = fs::file_write_append(test_file.to_str().unwrap(), append_content);
    assert!(append_result.is_ok());

    // Read and verify
    let read_result = fs::file_read(test_file.to_str().unwrap());
    assert!(read_result.is_ok());
    assert_eq!(
        read_result.unwrap(),
        format!("{}{}", initial_content, append_content)
    );
}

#[test]
fn test_file_size() {
    let temp_dir = TempDir::new().unwrap();
    let test_file = temp_dir.path().join("test_size.txt");
    let content = "Hello, World!"; // 13 bytes

    // Write file
    fs::file_write(test_file.to_str().unwrap(), content).unwrap();

    // Check size
    let size_result = fs::file_size(test_file.to_str().unwrap());
    assert!(size_result.is_ok());
    assert_eq!(size_result.unwrap(), 13);
}

#[test]
fn test_delete() {
    let temp_dir = TempDir::new().unwrap();
    let test_file = temp_dir.path().join("test_delete.txt");

    // Create file
    fs::file_write(test_file.to_str().unwrap(), "test").unwrap();
    assert!(fs::exist(test_file.to_str().unwrap()));

    // Delete file
    let delete_result = fs::delete(test_file.to_str().unwrap());
    assert!(delete_result.is_ok());

    // File should no longer exist
    assert!(!fs::exist(test_file.to_str().unwrap()));

    // Deleting non-existent file should not error (defensive)
    let delete_result2 = fs::delete(test_file.to_str().unwrap());
    assert!(delete_result2.is_ok());
}

#[test]
fn test_copy() {
    let temp_dir = TempDir::new().unwrap();
    let source_file = temp_dir.path().join("source.txt");
    let dest_file = temp_dir.path().join("dest.txt");
    let content = "Copy test content";

    // Create source file
    fs::file_write(source_file.to_str().unwrap(), content).unwrap();

    // Copy file
    let copy_result = fs::copy(source_file.to_str().unwrap(), dest_file.to_str().unwrap());
    assert!(copy_result.is_ok());

    // Destination should exist and have same content
    assert!(fs::exist(dest_file.to_str().unwrap()));
    let dest_content = fs::file_read(dest_file.to_str().unwrap()).unwrap();
    assert_eq!(dest_content, content);
}

#[test]
fn test_mv() {
    let temp_dir = TempDir::new().unwrap();
    let source_file = temp_dir.path().join("source_mv.txt");
    let dest_file = temp_dir.path().join("dest_mv.txt");
    let content = "Move test content";

    // Create source file
    fs::file_write(source_file.to_str().unwrap(), content).unwrap();

    // Move file
    let mv_result = fs::mv(source_file.to_str().unwrap(), dest_file.to_str().unwrap());
    assert!(mv_result.is_ok());

    // Source should no longer exist, destination should exist
    assert!(!fs::exist(source_file.to_str().unwrap()));
    assert!(fs::exist(dest_file.to_str().unwrap()));

    // Destination should have same content
    let dest_content = fs::file_read(dest_file.to_str().unwrap()).unwrap();
    assert_eq!(dest_content, content);
}

#[test]
fn test_which() {
    // Test with a command that should exist on all systems
    #[cfg(target_os = "windows")]
    let existing_cmd = "cmd";
    #[cfg(not(target_os = "windows"))]
    let existing_cmd = "ls";

    let result = fs::which(existing_cmd);
    assert!(
        !result.is_empty(),
        "Command '{}' should exist",
        existing_cmd
    );

    // Test with a command that shouldn't exist
    let result = fs::which("nonexistentcommand12345");
    assert!(result.is_empty());
}

#[test]
fn test_find_files() {
    let temp_dir = TempDir::new().unwrap();
    let temp_path = temp_dir.path();

    // Create test files
    fs::file_write(&temp_path.join("test1.txt").to_string_lossy(), "content1").unwrap();
    fs::file_write(&temp_path.join("test2.txt").to_string_lossy(), "content2").unwrap();
    fs::file_write(
        &temp_path.join("other.log").to_string_lossy(),
        "log content",
    )
    .unwrap();

    // Find .txt files
    let txt_files = fs::find_files(temp_path.to_str().unwrap(), "*.txt");
    assert!(txt_files.is_ok());
    let files = txt_files.unwrap();
    assert_eq!(files.len(), 2);

    // Find all files
    let all_files = fs::find_files(temp_path.to_str().unwrap(), "*");
    assert!(all_files.is_ok());
    let files = all_files.unwrap();
    assert!(files.len() >= 3); // At least our 3 files
}

#[test]
fn test_find_dirs() {
    let temp_dir = TempDir::new().unwrap();
    let temp_path = temp_dir.path();

    // Create test directories
    fs::mkdir(&temp_path.join("dir1").to_string_lossy()).unwrap();
    fs::mkdir(&temp_path.join("dir2").to_string_lossy()).unwrap();
    fs::mkdir(&temp_path.join("subdir").to_string_lossy()).unwrap();

    // Find directories
    let dirs = fs::find_dirs(temp_path.to_str().unwrap(), "dir*");
    assert!(dirs.is_ok());
    let found_dirs = dirs.unwrap();
    assert!(found_dirs.len() >= 2); // At least dir1 and dir2
}