use std::time::{Duration, Instant}; use common::emulator_setup; use gb_emu_lib::connect::{EmulatorCoreTrait, RomFile}; mod common; #[test] fn cpu_instrs() -> anyhow::Result<()> { run_blargg_test("cpu_instrs\n\n01:ok 02:ok 03:ok 04:ok 05:ok 06:ok 07:ok 08:ok 09:ok 10:ok 11:ok \n\nPassed all tests", include_bytes!( "../../test-roms/blargg/cpu_instrs/cpu_instrs.gb" ),None) } #[test] fn instr_timing() -> anyhow::Result<()> { run_blargg_test( "instr_timing\n\n\nPassed", include_bytes!("../../test-roms/blargg/instr_timing/instr_timing.gb"), Some(vec!["Failed"]), ) } #[test] fn mem_timing() -> anyhow::Result<()> { run_blargg_test( "mem_timing\n\n\nPassed", include_bytes!("../../test-roms/blargg/mem_timing/mem_timing.gb"), None, ) } #[derive(Debug, thiserror::Error)] enum TestError { #[error("Timeout")] Timeout(String), } fn run_blargg_test( correct_output: &str, rom: &[u8; N], extra_end: Option>, ) -> anyhow::Result<()> { let mut emu = emulator_setup(RomFile::Raw(rom.to_vec()))?; let mut end_strings = extra_end.unwrap_or_default(); end_strings.append(&mut vec![".", "tests"]); let mut chars = String::new(); let began = Instant::now(); let timeout = Duration::from_secs(60); 'outer: loop { emu.core.run(100); while let Ok(v) = emu.serial_rx.try_recv() { chars.push(v as char); if end_strings.iter().any(|end| chars.ends_with(end)) { break 'outer; } } if began.elapsed() > timeout { return Err(TestError::Timeout(format!("Test timed out: output was {chars}")).into()); } } assert_eq!(correct_output, chars); Ok(()) }