//! Smoke test for `Vm::snapshot`. Boots from a base snapshot,
//! drops a marker file inside the guest, captures, then loads
//! the new snapshot and verifies the marker file is still
//! there.
//!
//! Usage:
//!     cargo run --release --example _snapshot_smoke
//! (requires nginx_1_27-alpine to be already baked.)

use supermachine::{Image, VmConfig};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let snap = format!(
        "{}/.local/supermachine-snapshots/nginx_1_27-alpine",
        std::env::var("HOME").unwrap()
    );
    let dest = format!("/tmp/sm-snap-test-{}", std::process::id());
    let _ = std::fs::remove_dir_all(&dest);

    println!("=== boot base image, drop a marker ===");
    let base = Image::from_snapshot(&snap)?;
    let vm = base.start(&VmConfig::new())?;
    vm.write_file("/tmp/marker.txt", b"this survives the snapshot\n")?;
    let pre = vm.read_file("/tmp/marker.txt")?;
    println!("  pre-snapshot read: {:?}", String::from_utf8_lossy(&pre));

    println!("=== capture snapshot to {dest} ===");
    let t0 = std::time::Instant::now();
    let warm = vm.snapshot(&dest)?;
    println!("  snapshot captured + saved in {:?}", t0.elapsed());
    println!("  warm image: memory_mib={} vcpus={}", warm.memory_mib(), warm.vcpus());

    println!("=== restore from new snapshot via acquire, verify marker ===");
    // Note: Vm::start can only be called once per process (HVF
    // hv_vm_create singleton). Use Image::acquire (subprocess
    // pool) for additional VMs from the same process — the
    // snapshot use case naturally fits this: snapshot once,
    // then iterate via acquire.
    let vm2 = warm.acquire()?;
    let post = vm2.read_file("/tmp/marker.txt")?;
    println!(
        "  post-snapshot read: {:?}",
        String::from_utf8_lossy(&post)
    );
    assert_eq!(pre, post, "marker file did not survive snapshot/restore");
    drop(vm2);

    let _ = std::fs::remove_dir_all(&dest);
    println!("OK");
    Ok(())
}
