From 3b6e611768df63c3a97b07da6a18e5506d36613d Mon Sep 17 00:00:00 2001 From: Nick Krichevsky Date: Sat, 15 Apr 2023 19:42:37 -0400 Subject: [PATCH] Test cleanup --- src/memory.rs | 4 + tests/cpu/arith8.rs | 226 ++++++++++++++++++------------------------ tests/cpu/load16.rs | 46 +++------ tests/cpu/load8.rs | 15 ++- tests/cpu/main.rs | 1 + tests/cpu/testutil.rs | 47 +++++++++ 6 files changed, 175 insertions(+), 164 deletions(-) create mode 100644 tests/cpu/testutil.rs diff --git a/src/memory.rs b/src/memory.rs index b618581..8665c6e 100644 --- a/src/memory.rs +++ b/src/memory.rs @@ -89,6 +89,8 @@ mod tests { #[test] fn test_get_invalid_address() { let memory = Memory::new(); + + #[allow(clippy::match_wild_err_arm)] match memory.get(0xCC_CC_CC_CC_CC) { Err(Error::GetInvalidAddress(addr)) => { assert_eq!(0xCC_CC_CC_CC_CC, addr); @@ -101,6 +103,8 @@ mod tests { #[test] fn test_set_invalid_address() { let mut memory = Memory::new(); + + #[allow(clippy::match_wild_err_arm)] match memory.set(0xCC_CC_CC_CC_CC, 100) { Err(Error::SetInvalidAddress(addr, value)) => { assert_eq!((0xCC_CC_CC_CC_CC, 100), (addr, value)); diff --git a/tests/cpu/arith8.rs b/tests/cpu/arith8.rs index 22b01e5..d884699 100644 --- a/tests/cpu/arith8.rs +++ b/tests/cpu/arith8.rs @@ -3,52 +3,16 @@ use ferris_boi::{ register, }; +use crate::testutil; + use test_case::test_case; -fn set_opposite_of_expected_flags( - processor: &mut Processor, - (zero_flag, sub_flag, half_carry_flag, carry_flag): (u8, u8, u8, u8), -) { - let invert_flag = |value| { - if value == 0 { - 1 - } else if value == 1 { - 0 - } else { - panic!("invalid flag value of {value} ") - } - }; - - processor - .registers - .set_flag_bit(register::Flag::Zero, invert_flag(zero_flag)); - - processor - .registers - .set_flag_bit(register::Flag::HalfCarry, invert_flag(half_carry_flag)); - - processor - .registers - .set_flag_bit(register::Flag::Carry, invert_flag(carry_flag)); - - processor - .registers - .set_flag_bit(register::Flag::Subtract, invert_flag(sub_flag)); +struct AdditionOperationFlags { + zero: u8, + half_carry: u8, + carry: u8, } -macro_rules! assert_flags_eq { - ($processor: expr, $(($flag: path, $value: expr)),+ $(,)?) => { - $( - assert_eq!( - $value, - $processor.registers.get_flag_bit($flag), - "{:?} flag had unexpected value", - $flag - ); - )+ - }; - } - #[test] fn test_add_a_to_itself() { let mut processor = Processor::default(); @@ -104,7 +68,10 @@ fn test_add_register_to_a_flags( processor.registers.a = a_value; // Set all the register to the opposite we expect to ensure they all get set - set_opposite_of_expected_flags(&mut processor, (zero_flag, 0, half_carry_flag, carry_flag)); + testutil::set_opposite_of_expected_flags( + &mut processor, + (zero_flag, 0, half_carry_flag, carry_flag), + ); processor.registers.set_single_8bit_register(src, src_value); let data = [opcode, 0x02]; @@ -115,7 +82,7 @@ fn test_add_register_to_a_flags( processor.run(&ins); - assert_flags_eq!( + testutil::assert_flags_eq!( processor, (register::Flag::Zero, zero_flag), (register::Flag::Subtract, 0), @@ -173,7 +140,10 @@ fn test_add_hl_addr_to_a_flags( .expect("expected to set address 0xFF00 but could not"); // Set all the register to the opposite we expect to ensure they all get set - set_opposite_of_expected_flags(&mut processor, (zero_flag, 0, half_carry_flag, carry_flag)); + testutil::set_opposite_of_expected_flags( + &mut processor, + (zero_flag, 0, half_carry_flag, carry_flag), + ); let data = [0x86, 0x01]; let (ins, extra_data) = @@ -182,7 +152,7 @@ fn test_add_hl_addr_to_a_flags( processor.run(&ins); - assert_flags_eq!( + testutil::assert_flags_eq!( processor, (register::Flag::Zero, zero_flag), (register::Flag::Subtract, 0), @@ -206,23 +176,25 @@ fn test_add_immediate_to_a_value() { assert_eq!(69, processor.registers.a); } -#[test_case(0x00, 0x00, 1, 0, 0; "zero flag for zero value")] -#[test_case(0x00, 0x01, 0, 0, 0; "no zero flag for non-zero value")] -#[test_case(0x0F, 0x01, 0, 1, 0; "half carry flag")] -#[test_case(0x80, 0x80, 0, 0, 1; "full carry flag")] -#[test_case(0xFF, 0x01, 0, 1, 1; "both full and half carry flag")] -fn test_add_immediate_to_a_flags( - a_value: u8, - n: u8, - zero_flag: u8, - half_carry_flag: u8, - carry_flag: u8, -) { +#[test_case(0x00, 0x00, AdditionOperationFlags{zero: 1, half_carry: 0, carry: 0}; "zero flag for zero value")] +#[test_case(0x00, 0x01, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 0}; "no zero flag for non-zero value")] +#[test_case(0x0F, 0x01, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 0}; "half carry flag")] +#[test_case(0x80, 0x80, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 1}; "full carry flag")] +#[test_case(0xFF, 0x01, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 1}; "both full and half carry flag")] +fn test_add_immediate_to_a_flags(a_value: u8, n: u8, expected_flags: AdditionOperationFlags) { let mut processor = Processor::default(); processor.registers.a = a_value; // Set all the register to the opposite we expect to ensure they all get set - set_opposite_of_expected_flags(&mut processor, (zero_flag, 0, half_carry_flag, carry_flag)); + testutil::set_opposite_of_expected_flags( + &mut processor, + ( + expected_flags.zero, + 0, + expected_flags.half_carry, + expected_flags.carry, + ), + ); let data = [0xC6, n, 0x01]; let (ins, extra_data) = @@ -231,12 +203,12 @@ fn test_add_immediate_to_a_flags( processor.run(&ins); - assert_flags_eq!( + testutil::assert_flags_eq!( processor, - (register::Flag::Zero, zero_flag), + (register::Flag::Zero, expected_flags.zero), (register::Flag::Subtract, 0), - (register::Flag::HalfCarry, half_carry_flag), - (register::Flag::Carry, carry_flag), + (register::Flag::HalfCarry, expected_flags.half_carry), + (register::Flag::Carry, expected_flags.carry), ); } @@ -280,74 +252,72 @@ fn test_add_with_carry_to_a_value( // these parameters are like impossible to read but I can't think of a nicer way to do this right now // B register -#[test_case(0x88, 0x12, 0, register::SingleEightBit::B, 0x5, 0, 0, 0; "no carry bit set, results in no flags, register b")] -#[test_case(0x88, 0x12, 1, register::SingleEightBit::B, 0x5, 0, 0, 0; "carry bit set, results in no flags, register b")] -#[test_case(0x88, 0x00, 0, register::SingleEightBit::B, 0x0, 1, 0, 0; "no carry bit set, zero operands result in zero flag set, register b")] -#[test_case(0x88, 0x00, 1, register::SingleEightBit::B, 0x0, 0, 0, 0; "carry bit set, zero operands result in no zero flag set, register b")] -#[test_case(0x88, 0x0F, 0, register::SingleEightBit::B, 0x1, 0, 1, 0; "no carry bit, half carry, register b")] -#[test_case(0x88, 0x0F, 1, register::SingleEightBit::B, 0x1, 0, 1, 0; "carry bit, half carry, register b")] -#[test_case(0x88, 0x0F, 0, register::SingleEightBit::B, 0x0F, 0, 1, 0; "no carry bit, full carry, register b")] -#[test_case(0x88, 0x0F, 1, register::SingleEightBit::B, 0x0F, 0, 1, 0; "carry bit, full carry, register b")] -#[test_case(0x88, 0xFF, 1, register::SingleEightBit::B, 0xFF, 0, 1, 1; "carry bit, both carries, register b")] +#[test_case(0x88, 0x12, 0, register::SingleEightBit::B, 0x5, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 0}; "no carry bit set, results in no flags, register b")] +#[test_case(0x88, 0x12, 1, register::SingleEightBit::B, 0x5, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 0}; "carry bit set, results in no flags, register b")] +#[test_case(0x88, 0x00, 0, register::SingleEightBit::B, 0x0, AdditionOperationFlags{zero: 1, half_carry: 0, carry: 0}; "no carry bit set, zero operands result in zero flag set, register b")] +#[test_case(0x88, 0x00, 1, register::SingleEightBit::B, 0x0, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 0}; "carry bit set, zero operands result in no zero flag set, register b")] +#[test_case(0x88, 0x0F, 0, register::SingleEightBit::B, 0x1, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 0}; "no carry bit, half carry, register b")] +#[test_case(0x88, 0x0F, 1, register::SingleEightBit::B, 0x1, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 0}; "carry bit, half carry, register b")] +#[test_case(0x88, 0x0F, 0, register::SingleEightBit::B, 0x0F, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 0}; "no carry bit, full carry, register b")] +#[test_case(0x88, 0x0F, 1, register::SingleEightBit::B, 0x0F, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 0}; "carry bit, full carry, register b")] +#[test_case(0x88, 0xFF, 1, register::SingleEightBit::B, 0xFF, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 1}; "carry bit, both carries, register b")] // C register -#[test_case(0x89, 0x12, 0, register::SingleEightBit::C, 0x5, 0, 0, 0; "no carry bit set, results in no flags, register c")] -#[test_case(0x89, 0x12, 1, register::SingleEightBit::C, 0x5, 0, 0, 0; "carry bit set, results in no flags, register c")] -#[test_case(0x89, 0x00, 0, register::SingleEightBit::C, 0x0, 1, 0, 0; "no carry bit set, zero operands result in zero flag set, register c")] -#[test_case(0x89, 0x00, 1, register::SingleEightBit::C, 0x0, 0, 0, 0; "carry bit set, zero operands result in no zero flag set, register c")] -#[test_case(0x89, 0x0F, 0, register::SingleEightBit::C, 0x1, 0, 1, 0; "no carry bit, half carry, register c")] -#[test_case(0x89, 0x0F, 1, register::SingleEightBit::C, 0x1, 0, 1, 0; "carry bit, half carry, register c")] -#[test_case(0x89, 0x0F, 0, register::SingleEightBit::C, 0x0F, 0, 1, 0; "no carry bit, full carry, register c")] -#[test_case(0x89, 0x0F, 1, register::SingleEightBit::C, 0x0F, 0, 1, 0; "carry bit, full carry, register c")] -#[test_case(0x89, 0xFF, 1, register::SingleEightBit::C, 0xFF, 0, 1, 1; "carry bit, both carries, register c")] +#[test_case(0x89, 0x12, 0, register::SingleEightBit::C, 0x5, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 0}; "no carry bit set, results in no flags, register c")] +#[test_case(0x89, 0x12, 1, register::SingleEightBit::C, 0x5, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 0}; "carry bit set, results in no flags, register c")] +#[test_case(0x89, 0x00, 0, register::SingleEightBit::C, 0x0, AdditionOperationFlags{zero: 1, half_carry: 0, carry: 0}; "no carry bit set, zero operands result in zero flag set, register c")] +#[test_case(0x89, 0x00, 1, register::SingleEightBit::C, 0x0, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 0}; "carry bit set, zero operands result in no zero flag set, register c")] +#[test_case(0x89, 0x0F, 0, register::SingleEightBit::C, 0x1, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 0}; "no carry bit, half carry, register c")] +#[test_case(0x89, 0x0F, 1, register::SingleEightBit::C, 0x1, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 0}; "carry bit, half carry, register c")] +#[test_case(0x89, 0x0F, 0, register::SingleEightBit::C, 0x0F, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 0}; "no carry bit, full carry, register c")] +#[test_case(0x89, 0x0F, 1, register::SingleEightBit::C, 0x0F, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 0}; "carry bit, full carry, register c")] +#[test_case(0x89, 0xFF, 1, register::SingleEightBit::C, 0xFF, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 1}; "carry bit, both carries, register c")] // D register -#[test_case(0x8A, 0x12, 0, register::SingleEightBit::D, 0x5, 0, 0, 0; "no carry bit set, results in no flags, register d")] -#[test_case(0x8A, 0x12, 1, register::SingleEightBit::D, 0x5, 0, 0, 0; "carry bit set, results in no flags, register d")] -#[test_case(0x8A, 0x00, 0, register::SingleEightBit::D, 0x0, 1, 0, 0; "no carry bit set, zero operands result in zero flag set, register d")] -#[test_case(0x8A, 0x00, 1, register::SingleEightBit::D, 0x0, 0, 0, 0; "carry bit set, zero operands result in no zero flag set, register d")] -#[test_case(0x8A, 0x0F, 0, register::SingleEightBit::D, 0x1, 0, 1, 0; "no carry bit, half carry, register d")] -#[test_case(0x8A, 0x0F, 1, register::SingleEightBit::D, 0x1, 0, 1, 0; "carry bit, half carry, register d")] -#[test_case(0x8A, 0x0F, 0, register::SingleEightBit::D, 0x0F, 0, 1, 0; "no carry bit, full carry, register d")] -#[test_case(0x8A, 0x0F, 1, register::SingleEightBit::D, 0x0F, 0, 1, 0; "carry bit, full carry, register d")] -#[test_case(0x8A, 0xFF, 1, register::SingleEightBit::D, 0xFF, 0, 1, 1; "carry bit, both carries, register d")] +#[test_case(0x8A, 0x12, 0, register::SingleEightBit::D, 0x5, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 0}; "no carry bit set, results in no flags, register d")] +#[test_case(0x8A, 0x12, 1, register::SingleEightBit::D, 0x5, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 0}; "carry bit set, results in no flags, register d")] +#[test_case(0x8A, 0x00, 0, register::SingleEightBit::D, 0x0, AdditionOperationFlags{zero: 1, half_carry: 0, carry: 0}; "no carry bit set, zero operands result in zero flag set, register d")] +#[test_case(0x8A, 0x00, 1, register::SingleEightBit::D, 0x0, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 0}; "carry bit set, zero operands result in no zero flag set, register d")] +#[test_case(0x8A, 0x0F, 0, register::SingleEightBit::D, 0x1, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 0}; "no carry bit, half carry, register d")] +#[test_case(0x8A, 0x0F, 1, register::SingleEightBit::D, 0x1, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 0}; "carry bit, half carry, register d")] +#[test_case(0x8A, 0x0F, 0, register::SingleEightBit::D, 0x0F, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 0}; "no carry bit, full carry, register d")] +#[test_case(0x8A, 0x0F, 1, register::SingleEightBit::D, 0x0F, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 0}; "carry bit, full carry, register d")] +#[test_case(0x8A, 0xFF, 1, register::SingleEightBit::D, 0xFF, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 1}; "carry bit, both carries, register d")] // E register -#[test_case(0x8B, 0x12, 0, register::SingleEightBit::E, 0x5, 0, 0, 0; "no carry bit set, results in no flags, register e")] -#[test_case(0x8B, 0x12, 1, register::SingleEightBit::E, 0x5, 0, 0, 0; "carry bit set, results in no flags, register e")] -#[test_case(0x8B, 0x00, 0, register::SingleEightBit::E, 0x0, 1, 0, 0; "no carry bit set, zero operands result in zero flag set, register e")] -#[test_case(0x8B, 0x00, 1, register::SingleEightBit::E, 0x0, 0, 0, 0; "carry bit set, zero operands result in no zero flag set, register e")] -#[test_case(0x8B, 0x0F, 0, register::SingleEightBit::E, 0x1, 0, 1, 0; "no carry bit, half carry, register e")] -#[test_case(0x8B, 0x0F, 1, register::SingleEightBit::E, 0x1, 0, 1, 0; "carry bit, half carry, register e")] -#[test_case(0x8B, 0x0F, 0, register::SingleEightBit::E, 0x0F, 0, 1, 0; "no carry bit, full carry, register e")] -#[test_case(0x8B, 0x0F, 1, register::SingleEightBit::E, 0x0F, 0, 1, 0; "carry bit, full carry, register e")] -#[test_case(0x8B, 0xFF, 1, register::SingleEightBit::E, 0xFF, 0, 1, 1; "carry bit, both carries, register e")] +#[test_case(0x8B, 0x12, 0, register::SingleEightBit::E, 0x5, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 0}; "no carry bit set, results in no flags, register e")] +#[test_case(0x8B, 0x12, 1, register::SingleEightBit::E, 0x5, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 0}; "carry bit set, results in no flags, register e")] +#[test_case(0x8B, 0x00, 0, register::SingleEightBit::E, 0x0, AdditionOperationFlags{zero: 1, half_carry: 0, carry: 0}; "no carry bit set, zero operands result in zero flag set, register e")] +#[test_case(0x8B, 0x00, 1, register::SingleEightBit::E, 0x0, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 0}; "carry bit set, zero operands result in no zero flag set, register e")] +#[test_case(0x8B, 0x0F, 0, register::SingleEightBit::E, 0x1, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 0}; "no carry bit, half carry, register e")] +#[test_case(0x8B, 0x0F, 1, register::SingleEightBit::E, 0x1, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 0}; "carry bit, half carry, register e")] +#[test_case(0x8B, 0x0F, 0, register::SingleEightBit::E, 0x0F, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 0}; "no carry bit, full carry, register e")] +#[test_case(0x8B, 0x0F, 1, register::SingleEightBit::E, 0x0F, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 0}; "carry bit, full carry, register e")] +#[test_case(0x8B, 0xFF, 1, register::SingleEightBit::E, 0xFF, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 1}; "carry bit, both carries, register e")] // H register -#[test_case(0x8C, 0x12, 0, register::SingleEightBit::H, 0x5, 0, 0, 0; "no carry bit set, results in no flags, register h")] -#[test_case(0x8C, 0x12, 1, register::SingleEightBit::H, 0x5, 0, 0, 0; "carry bit set, results in no flags, register h")] -#[test_case(0x8C, 0x00, 0, register::SingleEightBit::H, 0x0, 1, 0, 0; "no carry bit set, zero operands result in zero flag set, register h")] -#[test_case(0x8C, 0x00, 1, register::SingleEightBit::H, 0x0, 0, 0, 0; "carry bit set, zero operands result in no zero flag set, register h")] -#[test_case(0x8C, 0x0F, 0, register::SingleEightBit::H, 0x1, 0, 1, 0; "no carry bit, half carry, register h")] -#[test_case(0x8C, 0x0F, 1, register::SingleEightBit::H, 0x1, 0, 1, 0; "carry bit, half carry, register h")] -#[test_case(0x8C, 0x0F, 0, register::SingleEightBit::H, 0x0F, 0, 1, 0; "no carry bit, full carry, register h")] -#[test_case(0x8C, 0x0F, 1, register::SingleEightBit::H, 0x0F, 0, 1, 0; "carry bit, full carry, register h")] -#[test_case(0x8C, 0xFF, 1, register::SingleEightBit::H, 0xFF, 0, 1, 1; "carry bit, both carries, register h")] +#[test_case(0x8C, 0x12, 0, register::SingleEightBit::H, 0x5, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 0}; "no carry bit set, results in no flags, register h")] +#[test_case(0x8C, 0x12, 1, register::SingleEightBit::H, 0x5, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 0}; "carry bit set, results in no flags, register h")] +#[test_case(0x8C, 0x00, 0, register::SingleEightBit::H, 0x0, AdditionOperationFlags{zero: 1, half_carry: 0, carry: 0}; "no carry bit set, zero operands result in zero flag set, register h")] +#[test_case(0x8C, 0x00, 1, register::SingleEightBit::H, 0x0, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 0}; "carry bit set, zero operands result in no zero flag set, register h")] +#[test_case(0x8C, 0x0F, 0, register::SingleEightBit::H, 0x1, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 0}; "no carry bit, half carry, register h")] +#[test_case(0x8C, 0x0F, 1, register::SingleEightBit::H, 0x1, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 0}; "carry bit, half carry, register h")] +#[test_case(0x8C, 0x0F, 0, register::SingleEightBit::H, 0x0F, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 0}; "no carry bit, full carry, register h")] +#[test_case(0x8C, 0x0F, 1, register::SingleEightBit::H, 0x0F, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 0}; "carry bit, full carry, register h")] +#[test_case(0x8C, 0xFF, 1, register::SingleEightBit::H, 0xFF, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 1}; "carry bit, both carries, register h")] // L register -#[test_case(0x8D, 0x12, 0, register::SingleEightBit::L, 0x5, 0, 0, 0; "no carry bit set, results in no flags, register l")] -#[test_case(0x8D, 0x12, 1, register::SingleEightBit::L, 0x5, 0, 0, 0; "carry bit set, results in no flags, register l")] -#[test_case(0x8D, 0x00, 0, register::SingleEightBit::L, 0x0, 1, 0, 0; "no carry bit set, zero operands result in zero flag set, register l")] -#[test_case(0x8D, 0x00, 1, register::SingleEightBit::L, 0x0, 0, 0, 0; "carry bit set, zero operands result in no zero flag set, register l")] -#[test_case(0x8D, 0x0F, 0, register::SingleEightBit::L, 0x1, 0, 1, 0; "no carry bit, half carry, register l")] -#[test_case(0x8D, 0x0F, 1, register::SingleEightBit::L, 0x1, 0, 1, 0; "carry bit, half carry, register l")] -#[test_case(0x8D, 0x0F, 0, register::SingleEightBit::L, 0x0F, 0, 1, 0; "no carry bit, full carry, register l")] -#[test_case(0x8D, 0x0F, 1, register::SingleEightBit::L, 0x0F, 0, 1, 0; "carry bit, full carry, register l")] -#[test_case(0x8D, 0xFF, 1, register::SingleEightBit::L, 0xFF, 0, 1, 1; "carry bit, both carries, register l")] +#[test_case(0x8D, 0x12, 0, register::SingleEightBit::L, 0x5, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 0}; "no carry bit set, results in no flags, register l")] +#[test_case(0x8D, 0x12, 1, register::SingleEightBit::L, 0x5, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 0}; "carry bit set, results in no flags, register l")] +#[test_case(0x8D, 0x00, 0, register::SingleEightBit::L, 0x0, AdditionOperationFlags{zero: 1, half_carry: 0, carry: 0}; "no carry bit set, zero operands result in zero flag set, register l")] +#[test_case(0x8D, 0x00, 1, register::SingleEightBit::L, 0x0, AdditionOperationFlags{zero: 0, half_carry: 0, carry: 0}; "carry bit set, zero operands result in no zero flag set, register l")] +#[test_case(0x8D, 0x0F, 0, register::SingleEightBit::L, 0x1, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 0}; "no carry bit, half carry, register l")] +#[test_case(0x8D, 0x0F, 1, register::SingleEightBit::L, 0x1, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 0}; "carry bit, half carry, register l")] +#[test_case(0x8D, 0x0F, 0, register::SingleEightBit::L, 0x0F, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 0}; "no carry bit, full carry, register l")] +#[test_case(0x8D, 0x0F, 1, register::SingleEightBit::L, 0x0F, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 0}; "carry bit, full carry, register l")] +#[test_case(0x8D, 0xFF, 1, register::SingleEightBit::L, 0xFF, AdditionOperationFlags{zero: 0, half_carry: 1, carry: 1}; "carry bit, both carries, register l")] fn test_add_with_carry_to_a_flags( opcode: u8, initial_value: u8, carry_bit: u8, operand_register: register::SingleEightBit, operand: u8, - expected_zero_flag: u8, - expected_half_carry_flag: u8, - expected_carry_flag: u8, + expected_flags: AdditionOperationFlags, ) { let mut processor = Processor::default(); processor.registers.a = initial_value; @@ -356,13 +326,13 @@ fn test_add_with_carry_to_a_flags( .set_single_8bit_register(operand_register, operand); // Set all the register to the opposite we expect to ensure they all get set - set_opposite_of_expected_flags( + testutil::set_opposite_of_expected_flags( &mut processor, ( - expected_zero_flag, + expected_flags.zero, 0, - expected_half_carry_flag, - expected_carry_flag, + expected_flags.half_carry, + expected_flags.carry, ), ); @@ -377,11 +347,11 @@ fn test_add_with_carry_to_a_flags( assert_eq!(extra_data, &[0x01]); processor.run(&ins); - assert_flags_eq!( + testutil::assert_flags_eq!( processor, - (register::Flag::Zero, expected_zero_flag), + (register::Flag::Zero, expected_flags.zero), (register::Flag::Subtract, 0), - (register::Flag::HalfCarry, expected_half_carry_flag), - (register::Flag::Carry, expected_carry_flag), + (register::Flag::HalfCarry, expected_flags.half_carry), + (register::Flag::Carry, expected_flags.carry), ); } diff --git a/tests/cpu/load16.rs b/tests/cpu/load16.rs index f823dbd..fa8c0f1 100644 --- a/tests/cpu/load16.rs +++ b/tests/cpu/load16.rs @@ -3,6 +3,8 @@ use ferris_boi::{ register, }; +use crate::testutil; + use test_case::test_case; #[test_case(0x32, 0x64, 0x63)] @@ -93,17 +95,14 @@ fn test_load_effective_address(value: i8, expected_sp: u16) { 0xFF00, ); - #[allow(clippy::cast_sign_loss)] - // The truncation will only happen if |value| > 128 in the branch where we check it's equal to -128 - // so we're fine. - #[allow(clippy::cast_possible_truncation)] let unsigned_value = if value >= 0 { value as u8 } else if value == i8::MIN { - i16::from(i8::MIN).abs() as u8 + i8::MIN.unsigned_abs() } else { - !(value.abs() as u8) + 1 + !(value.unsigned_abs()) + 1 }; + let data = [0xF8, unsigned_value, 0x00]; let (ins, extra_data) = @@ -132,16 +131,12 @@ fn test_load_effective_address_flags(starting_sp: u16, add_value: i8, half_carry let mut processor = Processor::default(); processor.registers.stack_pointer = starting_sp; - #[allow(clippy::cast_sign_loss)] - // The truncation will only happen if |value| > 128 in the branch where we check it's equal to -128 - // so we're fine. - #[allow(clippy::cast_possible_truncation)] let unsigned_value = if add_value >= 0 { add_value as u8 } else if add_value == i8::MIN { - i16::from(i8::MIN).abs() as u8 + i8::MIN.unsigned_abs() } else { - !(add_value.abs() as u8) + 1 + !(add_value.unsigned_abs()) + 1 }; let data = [0xF8, unsigned_value, 0x00]; @@ -151,27 +146,12 @@ fn test_load_effective_address_flags(starting_sp: u16, add_value: i8, half_carry assert_eq!(extra_data, &[0x00]); processor.run(&ins); - assert_eq!( - half_carry, - processor.registers.get_flag_bit(register::Flag::HalfCarry), - "incorrect half carry bit" - ); - - assert_eq!( - carry, - processor.registers.get_flag_bit(register::Flag::Carry), - "incorrect carry bit" - ); - - assert_eq!( - 0, - processor.registers.get_flag_bit(register::Flag::Zero), - "incorrect zero bit" - ); - assert_eq!( - 0, - processor.registers.get_flag_bit(register::Flag::Subtract), - "incorrect subtract bit" + testutil::assert_flags_eq!( + processor, + (register::Flag::HalfCarry, half_carry), + (register::Flag::Carry, carry), + (register::Flag::Zero, 0), + (register::Flag::Subtract, 0), ); } diff --git a/tests/cpu/load8.rs b/tests/cpu/load8.rs index bbed723..6960e6f 100644 --- a/tests/cpu/load8.rs +++ b/tests/cpu/load8.rs @@ -196,7 +196,10 @@ fn test_load_immediate_to_memory() { #[test] fn test_load_from_immediate_address() { let mut processor = Processor::default(); - processor.memory.set(0xCCDE, 105); + processor + .memory + .set(0xCCDE, 105) + .expect("failed to set memory value"); let data = [0xFA, 0xDE, 0xCC, 0x00]; let (ins, extra_data) = @@ -264,7 +267,10 @@ fn test_load_from_register_address_then_do_arithmetic( processor .registers .set_combined_register(register::Combined::HL, hl_value_before); - processor.memory.set(hl_value_before.into(), 10); + processor + .memory + .set(hl_value_before.into(), 10) + .expect("failed to set memory value"); let data = [opcode, 0x00]; let (ins, extra_data) = @@ -299,7 +305,10 @@ fn test_load_to_io_register_zone_by_immediate() { #[test] fn test_load_from_io_register_zone_by_immediate() { let mut processor = Processor::default(); - processor.memory.set(0xFF05, 0xAF); + processor + .memory + .set(0xFF05, 0xAF) + .expect("failed to set memory value"); let data = [0xF0, 0x05, 0x06]; let (ins, extra_data) = diff --git a/tests/cpu/main.rs b/tests/cpu/main.rs index 4ee0b8f..6da275f 100644 --- a/tests/cpu/main.rs +++ b/tests/cpu/main.rs @@ -1,3 +1,4 @@ mod arith8; mod load16; mod load8; +mod testutil; diff --git a/tests/cpu/testutil.rs b/tests/cpu/testutil.rs new file mode 100644 index 0000000..d8795aa --- /dev/null +++ b/tests/cpu/testutil.rs @@ -0,0 +1,47 @@ +use ferris_boi::{cpu::Processor, register}; + +macro_rules! assert_flags_eq { + ($processor: expr, $(($flag: path, $value: expr)),+ $(,)?) => { + $( + assert_eq!( + $value, + $processor.registers.get_flag_bit($flag), + "{:?} flag had unexpected value", + $flag + ); + )+ + }; + } + +pub(crate) use assert_flags_eq; + +pub fn set_opposite_of_expected_flags( + processor: &mut Processor, + (zero_flag, sub_flag, half_carry_flag, carry_flag): (u8, u8, u8, u8), +) { + let invert_flag = |value| { + if value == 0 { + 1 + } else if value == 1 { + 0 + } else { + panic!("invalid flag value of {value} ") + } + }; + + processor + .registers + .set_flag_bit(register::Flag::Zero, invert_flag(zero_flag)); + + processor + .registers + .set_flag_bit(register::Flag::HalfCarry, invert_flag(half_carry_flag)); + + processor + .registers + .set_flag_bit(register::Flag::Carry, invert_flag(carry_flag)); + + processor + .registers + .set_flag_bit(register::Flag::Subtract, invert_flag(sub_flag)); +}