//! Тесты на `reloc.rs`.
use rasm_core::codegen::reloc::{RelocKind, RelocTable, Relocation};
use rasm_core::str_pool::StrId;

#[test]
fn reloc_kind_debug() {
    let r = RelocKind::Rel32;
    let d = format!("{r:?}");
    assert_eq!(d, "Rel32");
}

#[test]
fn reloc_kind_abs64_debug() {
    let r = RelocKind::Abs64;
    let d = format!("{r:?}");
    assert_eq!(d, "Abs64");
}

#[test]
fn reloc_kind_equality() {
    assert_eq!(RelocKind::Rel32, RelocKind::Rel32);
    assert_eq!(RelocKind::Abs64, RelocKind::Abs64);
    assert_ne!(RelocKind::Rel32, RelocKind::Abs64);
}

#[test]
fn reloc_kind_copy() {
    let r = RelocKind::Rel32;
    let r2 = r;
    assert_eq!(r, r2);
}

#[test]
fn relocation_new_rel32() {
    let id = StrId(0);
    let reloc = Relocation::new(42, id, RelocKind::Rel32);
    assert_eq!(reloc.patch_offset, 42);
    assert_eq!(reloc.target_label, id);
    assert_eq!(reloc.kind, RelocKind::Rel32);
}

#[test]
fn relocation_new_abs64() {
    let id = StrId(7);
    let reloc = Relocation::new(100, id, RelocKind::Abs64);
    assert_eq!(reloc.patch_offset, 100);
    assert_eq!(reloc.target_label, id);
    assert_eq!(reloc.kind, RelocKind::Abs64);
}

#[test]
fn relocation_zero_offset() {
    let id = StrId(0);
    let reloc = Relocation::new(0, id, RelocKind::Rel32);
    assert_eq!(reloc.patch_offset, 0);
}

#[test]
fn relocation_debug() {
    let id = StrId(1);
    let reloc = Relocation::new(10, id, RelocKind::Rel32);
    let d = format!("{reloc:?}");
    assert!(d.contains("patch_offset"));
    assert!(d.contains("Rel32"));
}

#[test]
fn reloc_table_new_is_empty() {
    let table = RelocTable::new();
    assert!(table.entries.is_empty());
}

#[test]
fn reloc_table_default_is_empty() {
    let table: RelocTable = Default::default();
    assert!(table.entries.is_empty());
}

#[test]
fn reloc_table_add_one() {
    let mut table = RelocTable::new();
    table.add(0, StrId(0), RelocKind::Rel32);
    assert_eq!(table.entries.len(), 1);
    assert_eq!(table.entries[0].patch_offset, 0);
}

#[test]
fn reloc_table_add_multiple() {
    let mut table = RelocTable::new();
    table.add(10, StrId(1), RelocKind::Rel32);
    table.add(20, StrId(2), RelocKind::Abs64);
    table.add(30, StrId(3), RelocKind::Rel32);
    assert_eq!(table.entries.len(), 3);
    assert_eq!(table.entries[1].kind, RelocKind::Abs64);
}

#[test]
fn reloc_table_add_same_offset_twice() {
    let mut table = RelocTable::new();
    table.add(100, StrId(0), RelocKind::Rel32);
    table.add(100, StrId(1), RelocKind::Abs64);
    assert_eq!(table.entries.len(), 2);
    assert_eq!(table.entries[0].patch_offset, table.entries[1].patch_offset);
}

#[test]
fn reloc_table_debug() {
    let mut table = RelocTable::new();
    table.add(0, StrId(0), RelocKind::Rel32);
    let d = format!("{table:?}");
    assert!(d.contains("RelocTable"));
}

#[test]
fn reloc_table_empty_debug() {
    let table: RelocTable = Default::default();
    let d = format!("{table:?}");
    assert!(d.contains("entries"));
}
