use std::io::Write;
use mint_core::data::{ExcelDataSource, ExcelDataSourceOptions};
#[path = "common/mod.rs"]
mod common;
fn default_excel_source() -> ExcelDataSource {
ExcelDataSource::from_path(
"tests/data/data.xlsx",
ExcelDataSourceOptions::new(vec!["Default".to_owned()]),
)
.expect("datasource loads")
}
#[test]
fn non_strict_integer_conversions_saturate() {
common::ensure_out_dir();
let layout_toml = r#"
[mint]
endianness = "little"
[block.header]
start_address = 0x80000
length = 0x100
padding = 0x00
[block.data]
overflow.u8_high = { value = 256, type = "u8" }
overflow.u8_low = { value = -1, type = "u8" }
overflow.i8_high = { value = 128, type = "i8" }
overflow.i8_low = { value = -129, type = "i8" }
overflow.u8_float_trunc = { value = 1.5, type = "u8" }
overflow.u8_float_high = { value = 300.0, type = "u8" }
"#;
let path = std::path::Path::new("out").join("test_non_strict_saturation.toml");
let mut f = std::fs::File::create(&path).unwrap();
f.write_all(layout_toml.as_bytes()).unwrap();
let cfg = mint_core::layout::load_layout(path.to_str().unwrap()).expect("parse layout");
let block = cfg.blocks.get("block").expect("block present");
let (bytes, _) =
common::build_block(block, &cfg.mint, false, None).expect("non-strict converts");
assert_eq!(
&bytes[..6],
&[0xff, 0x00, 0x7f, 0x80, 0x01, 0xff],
"non-strict integer conversions should saturate, while floats still truncate"
);
}
#[test]
fn strict_conversions_success() {
common::ensure_out_dir();
let layout_toml = r#"
[mint]
endianness = "little"
[block.header]
start_address = 0x80000
length = 0x100
padding = 0x00
[block.data]
ok.float_exact_to_i16 = { value = 42.0, type = "i16" }
ok.int_exact_to_f32 = { value = 16777216, type = "f32" }
"#;
let path = std::path::Path::new("out").join("test_strict_ok.toml");
let mut f = std::fs::File::create(&path).unwrap();
f.write_all(layout_toml.as_bytes()).unwrap();
let cfg = mint_core::layout::load_layout(path.to_str().unwrap()).expect("parse ok layout");
let block = cfg.blocks.get("block").expect("block present");
let ds = default_excel_source();
let (bytes, _) = common::build_block(block, &cfg.mint, true, Some(&ds))
.expect("strict conversions should succeed");
assert!(!bytes.is_empty());
}
#[test]
fn strict_conversions_fail_fractional_float_to_int() {
common::ensure_out_dir();
let layout_toml = r#"
[mint]
endianness = "little"
[block.header]
start_address = 0x80000
length = 0x100
padding = 0x00
[block.data]
bad.frac_to_u8 = { value = 1.5, type = "u8" }
"#;
let path = std::path::Path::new("out").join("test_strict_bad_frac.toml");
let mut f = std::fs::File::create(&path).unwrap();
f.write_all(layout_toml.as_bytes()).unwrap();
let cfg = mint_core::layout::load_layout(path.to_str().unwrap()).expect("parse bad layout");
let block = cfg.blocks.get("block").expect("block present");
let ds = default_excel_source();
let res = common::build_block(block, &cfg.mint, true, Some(&ds));
assert!(
res.is_err(),
"strict mode should reject fractional float to int"
);
}
#[test]
fn strict_conversions_fail_large_int_to_f64_lossy() {
common::ensure_out_dir();
let layout_toml = r#"
[mint]
endianness = "little"
[block.header]
start_address = 0x80000
length = 0x100
padding = 0x00
[block.data]
bad.large_int_to_f64 = { value = 9007199254740993, type = "f64" }
"#;
let path = std::path::Path::new("out").join("test_strict_bad_large.toml");
let mut f = std::fs::File::create(&path).unwrap();
f.write_all(layout_toml.as_bytes()).unwrap();
let cfg = mint_core::layout::load_layout(path.to_str().unwrap()).expect("parse bad layout");
let block = cfg.blocks.get("block").expect("block present");
let ds = default_excel_source();
let res = common::build_block(block, &cfg.mint, true, Some(&ds));
assert!(
res.is_err(),
"strict mode should reject lossy int to f64 conversion"
);
}
#[test]
fn strict_conversions_accept_bool_literals() {
common::ensure_out_dir();
let layout_toml = r#"
[mint]
endianness = "little"
[block.header]
start_address = 0x80000
length = 0x100
padding = 0x00
[block.data]
bools.true_flag = { value = true, type = "u8" }
bools.false_flag = { value = false, type = "u8" }
bools.array_flags = { value = [true, false, true], type = "u8", size = 3 }
"#;
let path = std::path::Path::new("out").join("test_bool_literals.toml");
let mut f = std::fs::File::create(&path).unwrap();
f.write_all(layout_toml.as_bytes()).unwrap();
let cfg = mint_core::layout::load_layout(path.to_str().unwrap()).expect("parse bool layout");
let block = cfg.blocks.get("block").expect("block present");
let (bytes, _) =
common::build_block(block, &cfg.mint, true, None).expect("bool literals convert");
assert!(
bytes.starts_with(&[1, 0, 1, 0, 1]),
"bool values should map to 0/1, got {:?}",
&bytes[..5.min(bytes.len())]
);
}