init.rs•7.46 kB
use procspawn;
use std::fs;
use std::path::Path;
use std::process::Command;
use tempfile::TempDir;
//--------------------------------------------------------------------------------------------------
// Function: Helper
//--------------------------------------------------------------------------------------------------
/// Get the path to the microsandbox binary from build directory
fn get_microsandbox_bin() -> String {
    let manifest_dir = std::env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set");
    let project_root = Path::new(&manifest_dir)
        .parent()
        .expect("Failed to get project root");
    project_root
        .join("build")
        .join("microsandbox")
        .to_string_lossy()
        .into_owned()
}
/// Create a temporary directory for testing
fn create_temp_dir() -> (TempDir, std::path::PathBuf) {
    let temp_dir = TempDir::new().expect("Failed to create temp directory");
    let temp_path = temp_dir.path().to_path_buf();
    (temp_dir, temp_path)
}
/// Helper function to run microsandbox init command and verify its results
fn verify_init_results(dir_path: &std::path::Path) {
    // Verify .menv directory was created
    let menv_path = dir_path.join(".menv");
    assert!(menv_path.exists(), ".menv directory should exist");
    assert!(menv_path.is_dir(), ".menv should be a directory");
    // Verify log directory was created
    let log_path = menv_path.join("log");
    assert!(log_path.exists(), "log directory should exist");
    assert!(log_path.is_dir(), "log should be a directory");
    // Verify active.db was created
    let db_path = menv_path.join("active.db");
    assert!(db_path.exists(), "active.db should exist");
    assert!(db_path.is_file(), "active.db should be a file");
    // Verify microsandbox.yaml was created
    let config_path = dir_path.join("microsandbox.yaml");
    assert!(config_path.exists(), "microsandbox.yaml should exist");
    assert!(config_path.is_file(), "microsandbox.yaml should be a file");
    // Verify microsandbox.yaml contents
    let config_contents = fs::read_to_string(config_path).unwrap();
    assert!(
        config_contents.contains("sandboxes:"),
        "config should have sandboxes section"
    );
}
//--------------------------------------------------------------------------------------------------
// Tests
//--------------------------------------------------------------------------------------------------
#[test]
fn integration_test_init_command_with_path() {
    procspawn::init();
    // Create temp directory and get binary path
    let (_temp_dir, temp_path) = create_temp_dir();
    let microsandbox_bin = get_microsandbox_bin();
    // Run the microsandbox init command with explicit path in a separate process
    let handle = procspawn::spawn((microsandbox_bin, temp_path.clone()), |(bin, path)| {
        let output = Command::new(bin)
            .arg("init")
            .arg(path)
            .output()
            .expect("Failed to execute microsandbox init command");
        assert!(
            output.status.success(),
            "microsandbox init failed: {}",
            String::from_utf8_lossy(&output.stderr)
        );
    });
    // Wait for the process to complete
    handle.join().expect("Process failed");
    verify_init_results(&temp_path);
}
#[test]
fn integration_test_init_command_current_dir() {
    procspawn::init();
    // Create temp directory and get binary path
    let (_temp_dir, temp_path) = create_temp_dir();
    let microsandbox_bin = get_microsandbox_bin();
    // Run the microsandbox init command without path in a separate process
    let handle = procspawn::spawn((microsandbox_bin, temp_path.clone()), |(bin, path)| {
        let output = Command::new(bin)
            .arg("init")
            .current_dir(&path)
            .output()
            .expect("Failed to execute microsandbox init command");
        assert!(
            output.status.success(),
            "microsandbox init failed: {}",
            String::from_utf8_lossy(&output.stderr)
        );
    });
    // Wait for the process to complete
    handle.join().expect("Process failed");
    verify_init_results(&temp_path);
}
#[test]
fn integration_test_init_command_existing_dir() {
    procspawn::init();
    // Create temp directory and get binary path
    let (_temp_dir, temp_path) = create_temp_dir();
    let microsandbox_bin = get_microsandbox_bin();
    // Create a file in the directory that shouldn't be affected
    let test_file = temp_path.join("test.txt");
    fs::write(&test_file, "test content").unwrap();
    // Run the microsandbox init command in a separate process
    let handle = procspawn::spawn(
        (microsandbox_bin, temp_path.clone(), test_file.clone()),
        |(bin, path, test_file)| {
            let output = Command::new(bin)
                .arg("init")
                .arg(&path)
                .output()
                .expect("Failed to execute microsandbox init command");
            assert!(
                output.status.success(),
                "microsandbox init failed: {}",
                String::from_utf8_lossy(&output.stderr)
            );
            // Verify the test file still exists and is unchanged
            assert!(test_file.exists(), "test file should still exist");
            let contents = fs::read_to_string(&test_file).unwrap();
            assert_eq!(
                contents, "test content",
                "test file contents should be unchanged"
            );
        },
    );
    // Wait for the process to complete
    handle.join().expect("Process failed");
    // Verify microsandbox files were created
    assert!(temp_path.join(".menv").exists());
    assert!(temp_path.join("microsandbox.yaml").exists());
}
#[test]
fn integration_test_init_command_idempotent() {
    procspawn::init();
    // Create temp directory and get binary path
    let (_temp_dir, temp_path) = create_temp_dir();
    let microsandbox_bin = get_microsandbox_bin();
    // Run the first init in a separate process
    let handle = procspawn::spawn((microsandbox_bin, temp_path.clone()), |(bin, path)| {
        // First init
        let output = Command::new(&bin)
            .arg("init")
            .arg(&path)
            .output()
            .expect("Failed to execute first microsandbox init command");
        assert!(
            output.status.success(),
            "First microsandbox init failed: {}",
            String::from_utf8_lossy(&output.stderr)
        );
        // Modify the config file to verify it's not overwritten
        let config_path = path.join("microsandbox.yaml");
        fs::write(&config_path, "modified content").unwrap();
        // Run the second init
        let output = Command::new(&bin)
            .arg("init")
            .arg(&path)
            .output()
            .expect("Failed to execute second microsandbox init command");
        assert!(
            output.status.success(),
            "Second microsandbox init failed: {}",
            String::from_utf8_lossy(&output.stderr)
        );
        // Verify the config file wasn't overwritten
        let contents = fs::read_to_string(&config_path).unwrap();
        assert_eq!(
            contents, "modified content",
            "config file should not be overwritten"
        );
    });
    // Wait for the process to complete
    handle.join().expect("Process failed");
}