use hxcfe::{HeadId, Hxcfe, SectorId, TrackEncoding, TrackId};
const HFE: &str = "tests/EXPERTS.HFE";
const DSK: &str = "tests/EXPERTS.DSK";
fn hxcfe() -> &'static hxcfe::Hxcfe {
Hxcfe::get()
}
#[test]
fn sector_access_created_and_dropped_repeatedly() {
let ctx = hxcfe();
let img = ctx.load(HFE).expect("load");
for _ in 0..50 {
let _sa = img.sector_access().expect("sector_access");
}
}
#[test]
fn sector_access_dropped_before_img() {
let ctx = hxcfe();
let img = ctx.load(HFE).expect("load");
{
let _sa = img.sector_access().expect("sector_access");
} assert!(img.nb_tracks() > 0);
}
#[test]
fn search_sector_drop_is_clean() {
let ctx = hxcfe();
let img = ctx.load(HFE).expect("load");
let sa = img.sector_access().expect("sector_access");
for _ in 0..20 {
let cfg = sa.search_sector(
HeadId::new(0),
TrackId::new(0),
SectorId::new(0xC1),
TrackEncoding::IsoibmMfm,
);
drop(cfg);
}
}
#[test]
fn get_next_sector_drop_is_clean() {
let ctx = hxcfe();
let img = ctx.load(HFE).expect("load");
let sa = img.sector_access().expect("sector_access");
for _pass in 0..3 {
sa.reset_search_track_position();
let mut count = 0usize;
while let Some(cfg) = sa.get_next_sector(
HeadId::new(0),
TrackId::new(0),
TrackEncoding::IsoibmMfm,
) {
let _data = cfg.read();
count += 1;
}
assert!(count > 0, "expected at least one sector on track 0");
}
}
#[test]
fn owned_sector_config_data_consistent_after_multiple_drops() {
let ctx = hxcfe();
let img = ctx.load(HFE).expect("load");
let sa = img.sector_access().expect("sector_access");
let read_once = || -> Vec<u8> {
sa.search_sector(
HeadId::new(0),
TrackId::new(0),
SectorId::new(0xC1),
TrackEncoding::IsoibmMfm,
)
.map(|cfg| cfg.read().to_vec())
.expect("sector C1 must exist")
};
let first = read_once();
let second = read_once();
assert_eq!(first, second, "sector data must be stable across reads");
}
#[test]
fn sector_config_array_dropped_without_borrowing() {
let ctx = hxcfe();
let img = ctx.load(HFE).expect("load");
let sa = img.sector_access().expect("sector_access");
for _ in 0..20 {
let _arr = sa.all_track_sectors(
HeadId::new(0),
TrackId::new(0),
TrackEncoding::IsoibmMfm,
);
}
}
#[test]
fn borrowed_sector_configs_dropped_before_array_no_double_free() {
let ctx = hxcfe();
let img = ctx.load(HFE).expect("load");
let sa = img.sector_access().expect("sector_access");
let arr = sa
.all_track_sectors(HeadId::new(0), TrackId::new(0), TrackEncoding::IsoibmMfm)
.expect("track 0 must have sectors");
let n = arr.nb_sectors();
assert!(n > 0);
for i in 0..n {
let cfg = arr.sector_config(i);
let _data = cfg.read();
}
}
#[test]
fn re_borrow_after_borrowed_config_drop_is_safe() {
let ctx = hxcfe();
let img = ctx.load(HFE).expect("load");
let sa = img.sector_access().expect("sector_access");
let arr = sa
.all_track_sectors(HeadId::new(0), TrackId::new(0), TrackEncoding::IsoibmMfm)
.expect("track 0 must have sectors");
if arr.nb_sectors() == 0 {
return;
}
let data_a = {
let cfg = arr.sector_config(0);
cfg.read().to_vec() };
let data_b = {
let cfg = arr.sector_config(0); cfg.read().to_vec()
};
assert_eq!(data_a, data_b, "re-borrowed config must yield same data");
}
#[test]
fn sector_access_drops_on_dsk() {
let ctx = hxcfe();
let img = ctx.load(DSK).expect("load DSK");
let sa = img.sector_access().expect("sector_access");
let arr = sa.all_track_sectors(
HeadId::new(0),
TrackId::new(0),
TrackEncoding::IsoibmMfm,
);
if let Some(arr) = arr {
let n = arr.nb_sectors();
for i in 0..n {
let _data = arr.sector_config(i).read().to_vec();
}
}
}
#[test]
fn full_scan_all_tracks_repeated() {
let ctx = hxcfe();
let img = ctx.load(HFE).expect("load");
for _pass in 0..5 {
let sa = img.sector_access().expect("sector_access");
for track_n in 0..img.nb_tracks() {
for side_n in 0..img.nb_sides() {
if let Some(arr) = sa.all_track_sectors(
HeadId::new(side_n as i32),
TrackId::new(track_n as i32),
TrackEncoding::IsoibmMfm,
) {
for i in 0..arr.nb_sectors() {
let _data = arr.sector_config(i).read().to_vec();
}
}
}
}
}
}