use std::path::Path; use ferris_boi::cpu::Processor; use include_dir::{include_dir, Dir}; use test_generator::test_resources; use super::TestCase; const TESTDATA_DIR: Dir<'_> = include_dir!("$CARGO_MANIFEST_DIR/tests/cpu/jsmoo/testdata"); #[test_resources("tests/cpu/jsmoo/testdata/*.json")] fn test_jsmoo_test(filename: &str) { let basename = Path::new(filename).file_name().unwrap(); let testdata_file = TESTDATA_DIR .get_file(basename) .expect("could not find data file"); let test_cases = serde_json::from_slice::>(testdata_file.contents()) .expect("failed to parse test data file"); for test_case in test_cases { let test_name = test_case.name; println!("{test_name}"); let mut processor = Processor::default(); processor.registers.a = test_case.initial.a; processor.registers.b = test_case.initial.b; processor.registers.c = test_case.initial.c; processor.registers.d = test_case.initial.d; processor.registers.e = test_case.initial.e; processor .registers .set_raw_flag_bits(test_case.initial.f) .unwrap(); processor.registers.h = test_case.initial.h; processor.registers.l = test_case.initial.l; processor.registers.program_counter = test_case.initial.pc; processor.registers.stack_pointer = test_case.initial.sp; for (addr, value) in test_case.initial.ram { processor .memory .set(addr.into(), value) .unwrap_or_else(|err| { panic!("failed to set up initial memory for test {test_name}: {err}") }); } processor.run_next_instruction(); assert_eq!( test_case.r#final.a, processor.registers.a, "register a value was incorrect" ); assert_eq!( test_case.r#final.b, processor.registers.b, "register b value was incorrect" ); assert_eq!( test_case.r#final.c, processor.registers.c, "register c value was incorrect" ); assert_eq!( test_case.r#final.d, processor.registers.d, "register d value was incorrect" ); assert_eq!( test_case.r#final.e, processor.registers.e, "register e value was incorrect" ); assert_eq!( test_case.r#final.f, processor.registers.get_raw_flag_bits(), "register f value was incorrect" ); assert_eq!( test_case.r#final.h, processor.registers.h, "register h value was incorrect" ); assert_eq!( test_case.r#final.l, processor.registers.l, "register l value was incorrect" ); assert_eq!( test_case.r#final.pc, processor.registers.program_counter, "program counter was incorrect" ); assert_eq!( test_case.r#final.sp, processor.registers.stack_pointer, "stack pointer was incorrect" ); for (addr, value) in test_case.r#final.ram { let stored_val = processor .memory .get(addr.into()) .unwrap_or_else(|_| panic!("failed to set up final memory for test {test_name}")); assert_eq!( value, stored_val, "memory did not match at address 0x{addr:0X}" ); } let num_cycles_expected = test_case.cycles.len() * 4; assert_eq!( u128::try_from(num_cycles_expected).unwrap(), processor.num_cycles ); } }