malvin 0.2.5

Non-interactive research and coding agent
use super::DotfileBackupState;
use super::slots::{
    DOTFILE_ROWS, DotfileSpecRow, backup_slot, dotfile_source_path, labels_for_test, restore_slot,
};
use super::slots_kiss_cov_shared::{MALVIN_CONFIG_WORKSPACE_SLOT, dotfile_spec_row_field_count};
use std::path::Path;

#[test]
fn kiss_cov_dotfile_spec_row_field_count() {
    for row in DOTFILE_ROWS {
        assert_eq!(dotfile_spec_row_field_count(&row), 7);
        let DotfileSpecRow {
            rel,
            home_subdir,
            mkdir_lbl,
            collision_lbl,
            restore_lbl,
            copy_err,
            restore_copy_err,
        } = row;
        let _ = (
            rel,
            home_subdir,
            mkdir_lbl,
            collision_lbl,
            restore_lbl,
            copy_err,
            restore_copy_err,
        );
    }
}

#[test]
fn slots_branchy_witness_covers_dotfile_rows() {
    for (slot, row_ref) in DOTFILE_ROWS.iter().enumerate() {
        let lbl = labels_for_test(row_ref);
        let path = dotfile_source_path(slot, Path::new("/tmp/w"));
        assert_eq!(dotfile_spec_row_field_count(row_ref), 7);
        if slot == 0 {
            assert!(
                path.to_string_lossy().contains("gates"),
                "gates slot path should mention gates: {path:?}"
            );
        } else if lbl.mkdir == row_ref.mkdir_lbl {
            assert_eq!(lbl.restore, row_ref.restore_lbl);
        } else {
            panic!("slot {slot} label mismatch");
        }
    }
    crate::test_utils::with_isolated_home(|work| {
        std::fs::create_dir_all(work.join(".malvin")).expect("mkdir");
        std::fs::write(work.join(".malvin/gates"), "make lint\n").expect("gates");
        let mut id = |n: usize| format!("slots-branchy-{n}");
        let backup = backup_slot(0, work, &mut id).expect("backup");
        if matches!(backup, DotfileBackupState::Present(_)) {
            restore_slot(work, &backup, 0).expect("restore");
        } else if matches!(backup, DotfileBackupState::Missing) {
            panic!("missing backup");
        } else {
            panic!("expected backup");
        }
    });
}

#[test]
fn kiss_cov_slots_static_unit_refs() {
    let _ = DotfileSpecRow::rel_path;
    let _ = labels_for_test;
    let _: [DotfileSpecRow; 3] = DOTFILE_ROWS;
}

#[test]
fn kiss_static_type_refs() {
    let row = &DOTFILE_ROWS[0];
    assert_eq!(row.rel, crate::MALVIN_CHECKS_REL);
    assert!(!row.home_subdir.is_empty());
    let _ = dotfile_source_path(0, Path::new("/tmp"));
}

#[cfg(unix)]
#[test]
fn kiss_cov_slots_workspace_config_slot_roundtrip() {
    crate::test_utils::with_isolated_home(|work| {
        std::fs::create_dir_all(work.join(".malvin")).expect("mkdir");
        std::fs::write(work.join(crate::MALVIN_CONFIG_REL), "workspace-config\n").expect("write");
        let mut generate_id = |n: usize| format!("kiss-cfg-{n}");
        let backup =
            backup_slot(MALVIN_CONFIG_WORKSPACE_SLOT, work, &mut generate_id).expect("backup");
        match backup {
            DotfileBackupState::Present(_) => {
                restore_slot(work, &backup, MALVIN_CONFIG_WORKSPACE_SLOT).expect("restore");
            }
            DotfileBackupState::Missing => panic!("workspace config slot should backup"),
        }
    });
}

#[test]
fn kiss_cov_slots_backup_restore_roundtrip() {
    crate::test_utils::with_isolated_home(|work| {
        std::fs::create_dir_all(work.join(".malvin")).expect("mkdir");
        std::fs::write(work.join(".malvin/gates"), "make lint\n").expect("gates");
        std::fs::write(work.join(".gitignore"), "target/\n").expect("gitignore");
        let mut generate_id = |n: usize| format!("kiss-slot-{n}");
        for slot in 0..DOTFILE_ROWS.len() {
            let backup = backup_slot(slot, work, &mut generate_id).expect("backup");
            match backup {
                DotfileBackupState::Present(_) => {
                    restore_slot(work, &backup, slot).expect("restore");
                }
                DotfileBackupState::Missing => {}
            }
        }
    });
}

#[test]
fn kiss_cov_dotfile_spec_row_construct_destructure_by_value() {
    let row = DOTFILE_ROWS[0];
    let touched = std::hint::black_box(row);
    let DotfileSpecRow {
        rel,
        home_subdir,
        mkdir_lbl,
        collision_lbl,
        restore_lbl,
        copy_err,
        restore_copy_err,
    } = touched;
    assert_eq!(rel, crate::MALVIN_CHECKS_REL);
    assert!(!home_subdir.is_empty());
    assert_eq!(mkdir_lbl, collision_lbl);
    assert!(!restore_lbl.is_empty());
    assert!(!copy_err.is_empty());
    assert!(!restore_copy_err.is_empty());
    let _ = std::mem::size_of::<DotfileSpecRow>();
    let lbl = labels_for_test(&DOTFILE_ROWS[0]);
    assert_eq!(lbl.mkdir, DOTFILE_ROWS[0].mkdir_lbl);
}

#[test]
fn kiss_cov_dotfile_rows_iterate_by_value() {
    for row in DOTFILE_ROWS {
        let moved: DotfileSpecRow = row;
        let copied = moved;
        let cloned = copied;
        assert_eq!(moved.rel, cloned.rel);
    }
}