use crate::domain::bad_block::BadBlockStrategy;
use crate::domain::chip::{ChipCapabilities, ChipLayout, ChipSpec};
use crate::domain::types::{Capacity, FlashType, JedecId};
use crate::domain::{Address, FlashOperation, OobMode, Progress, ReadRequest};
use crate::infrastructure::flash_protocol::nor::SpiNor;
use crate::infrastructure::programmer::mock::MockProgrammer;
use crate::infrastructure::programmer::Programmer; use std::cell::RefCell;
fn create_test_nor_spec() -> ChipSpec {
ChipSpec {
name: "W25Q64".to_string(),
manufacturer: "Winbond".to_string(),
jedec_id: JedecId::new([0xEF, 0x40, 0x17]),
flash_type: FlashType::Nor,
capacity: Capacity::megabytes(8),
layout: ChipLayout {
page_size: 256,
block_size: 64 * 1024, oob_size: None,
is_dataflash: false,
},
capabilities: ChipCapabilities::default(),
otp: None,
}
}
#[test]
fn test_nor_read_basic() {
let mock = MockProgrammer::new();
let spec = create_test_nor_spec();
mock.expect_read(vec![0xFF; 5]); let test_data = vec![0xDE, 0xAD, 0xBE, 0xEF];
mock.expect_read(test_data.clone());
let mut nor = SpiNor::new(mock, spec);
let request = ReadRequest {
address: Address::new(0),
length: 4,
use_ecc: false,
ignore_ecc_errors: false,
oob_mode: OobMode::None,
bad_block_strategy: BadBlockStrategy::Fail,
bbt: None,
retry_count: 0,
};
let result = nor.read(request, &|_| {}).unwrap();
assert_eq!(result, vec![0xDE, 0xAD, 0xBE, 0xEF]);
}
#[test]
fn test_nor_read_progress_callback() {
let mock = MockProgrammer::new();
let spec = create_test_nor_spec();
mock.expect_read(vec![0xFF; 5]); mock.expect_read(vec![0x00; 4095]); mock.expect_read(vec![0xFF; 5]); mock.expect_read(vec![0x00; 4095]);
let mut nor = SpiNor::new(mock, spec);
let request = ReadRequest {
address: Address::new(0),
length: 8190, use_ecc: false,
ignore_ecc_errors: false,
oob_mode: OobMode::None,
bad_block_strategy: BadBlockStrategy::Fail,
bbt: None,
retry_count: 0,
};
let progress_calls = RefCell::new(Vec::new());
let result = nor.read(request, &|p: Progress| {
progress_calls.borrow_mut().push((p.current, p.total));
});
assert!(result.is_ok());
let calls = progress_calls.borrow();
assert!(
calls.len() >= 2,
"Expected at least 2 progress calls, got {}",
calls.len()
);
if let Some(last) = calls.last() {
assert_eq!(last.0, last.1, "Final progress should show completion");
}
}
#[test]
fn test_nor_spec_access() {
let mock = MockProgrammer::new();
let spec = create_test_nor_spec();
let nor = SpiNor::new(mock, spec);
assert_eq!(nor.spec().name, "W25Q64");
assert_eq!(nor.spec().flash_type, FlashType::Nor);
assert_eq!(nor.spec().capacity.as_megabytes(), 8);
}
#[test]
fn test_mock_programmer_transactions() {
let mut mock = MockProgrammer::new();
mock.set_cs(true).unwrap();
assert!(mock.is_cs_active());
mock.set_cs(false).unwrap();
assert!(!mock.is_cs_active());
mock.expect_read(vec![0xAB, 0xCD]);
let mut rx = [0u8; 2];
mock.spi_transfer(&[0x9F, 0x00], &mut rx).unwrap();
assert_eq!(rx, [0xAB, 0xCD]);
let writes = mock.get_writes();
assert!(!writes.is_empty());
}