- added Equate() function
    - reworked and renamed registers/assert package. now called
	registers/test
This commit is contained in:
steve 2019-11-28 00:53:11 +00:00
parent 15e418411d
commit 704ff4d185
9 changed files with 303 additions and 249 deletions

View file

@ -3,7 +3,7 @@ package cpu_test
import (
"gopher2600/errors"
"gopher2600/hardware/cpu"
"gopher2600/hardware/cpu/registers/assert"
rtest "gopher2600/hardware/cpu/registers/test"
"testing"
)
@ -78,25 +78,25 @@ func testStatusInstructions(t *testing.T, mc *cpu.CPU, mem *mockMem) {
// SEC; CLC; CLI; SEI; SED; CLD; CLV
origin = mem.putInstructions(origin, 0x38, 0x18, 0x58, 0x78, 0xf8, 0xd8, 0xb8)
step(t, mc) // SEC
assert.Assert(t, mc.Status, "sv-bdiZC")
rtest.EquateRegisters(t, mc.Status, "sv-bdiZC")
step(t, mc) // CLC
assert.Assert(t, mc.Status, "sv-bdiZc")
rtest.EquateRegisters(t, mc.Status, "sv-bdiZc")
step(t, mc) // CLI
assert.Assert(t, mc.Status, "sv-bdiZc")
rtest.EquateRegisters(t, mc.Status, "sv-bdiZc")
step(t, mc) // SEI
assert.Assert(t, mc.Status, "sv-bdIZc")
rtest.EquateRegisters(t, mc.Status, "sv-bdIZc")
step(t, mc) // SED
assert.Assert(t, mc.Status, "sv-bDIZc")
rtest.EquateRegisters(t, mc.Status, "sv-bDIZc")
step(t, mc) // CLD
assert.Assert(t, mc.Status, "sv-bdIZc")
rtest.EquateRegisters(t, mc.Status, "sv-bdIZc")
step(t, mc) // CLV
assert.Assert(t, mc.Status, "sv-bdIZc")
rtest.EquateRegisters(t, mc.Status, "sv-bdIZc")
// PHP; PLP
_ = mem.putInstructions(origin, 0x08, 0x28)
step(t, mc) // PHP
assert.Assert(t, mc.Status, "sv-bdIZc")
assert.Assert(t, mc.SP, 254)
rtest.EquateRegisters(t, mc.Status, "sv-bdIZc")
rtest.EquateRegisters(t, mc.SP, 254)
// mangle status register
mc.Status.Sign = true
@ -105,8 +105,8 @@ func testStatusInstructions(t *testing.T, mc *cpu.CPU, mem *mockMem) {
// restore status register
step(t, mc) // PLP
assert.Assert(t, mc.SP, 255)
assert.Assert(t, mc.Status, "sv-bdIZc")
rtest.EquateRegisters(t, mc.SP, 255)
rtest.EquateRegisters(t, mc.Status, "sv-bdIZc")
}
func testRegsiterArithmetic(t *testing.T, mc *cpu.CPU, mem *mockMem) {
@ -118,13 +118,13 @@ func testRegsiterArithmetic(t *testing.T, mc *cpu.CPU, mem *mockMem) {
origin = mem.putInstructions(origin, 0xa9, 1, 0x69, 10)
step(t, mc) // LDA #1
step(t, mc) // ADC #10
assert.Assert(t, mc.A, 11)
rtest.EquateRegisters(t, mc.A, 11)
// SEC; SBC immediate
_ = mem.putInstructions(origin, 0x38, 0xe9, 8)
step(t, mc) // SEC
step(t, mc) // SBC #8
assert.Assert(t, mc.A, 3)
rtest.EquateRegisters(t, mc.A, 3)
}
func testRegsiterBitwiseInstructions(t *testing.T, mc *cpu.CPU, mem *mockMem) {
@ -134,40 +134,40 @@ func testRegsiterBitwiseInstructions(t *testing.T, mc *cpu.CPU, mem *mockMem) {
// ORA immediate; EOR immediate; AND immediate
origin = mem.putInstructions(origin, 0x09, 0xff, 0x49, 0xf0, 0x29, 0x01)
assert.Assert(t, mc.A, 0)
rtest.EquateRegisters(t, mc.A, 0)
step(t, mc) // ORA #$FF
assert.Assert(t, mc.A, 255)
rtest.EquateRegisters(t, mc.A, 255)
step(t, mc) // EOR #$F0
assert.Assert(t, mc.A, 15)
rtest.EquateRegisters(t, mc.A, 15)
step(t, mc) // AND #$01
assert.Assert(t, mc.A, 1)
rtest.EquateRegisters(t, mc.A, 1)
// ASL implied; LSR implied; LSR implied
origin = mem.putInstructions(origin, 0x0a, 0x4a, 0x4a)
step(t, mc) // ASL
assert.Assert(t, mc.A, 2)
assert.Assert(t, mc.Status, "sv-bdizc")
rtest.EquateRegisters(t, mc.A, 2)
rtest.EquateRegisters(t, mc.Status, "sv-bdizc")
step(t, mc) // LSR
assert.Assert(t, mc.A, 1)
assert.Assert(t, mc.Status, "sv-bdizc")
rtest.EquateRegisters(t, mc.A, 1)
rtest.EquateRegisters(t, mc.Status, "sv-bdizc")
step(t, mc) // LSR
assert.Assert(t, mc.A, 0)
assert.Assert(t, mc.Status, "sv-bdiZC")
rtest.EquateRegisters(t, mc.A, 0)
rtest.EquateRegisters(t, mc.Status, "sv-bdiZC")
// ROL implied; ROR implied; ROR implied; ROR implied
_ = mem.putInstructions(origin, 0x2a, 0x6a, 0x6a, 0x6a)
step(t, mc) // ROL
assert.Assert(t, mc.A, 1)
assert.Assert(t, mc.Status, "sv-bdizc")
rtest.EquateRegisters(t, mc.A, 1)
rtest.EquateRegisters(t, mc.Status, "sv-bdizc")
step(t, mc) // ROR
assert.Assert(t, mc.A, 0)
assert.Assert(t, mc.Status, "sv-bdiZC")
rtest.EquateRegisters(t, mc.A, 0)
rtest.EquateRegisters(t, mc.Status, "sv-bdiZC")
step(t, mc) // ROR
assert.Assert(t, mc.A, 128)
assert.Assert(t, mc.Status, "Sv-bdizc")
rtest.EquateRegisters(t, mc.A, 128)
rtest.EquateRegisters(t, mc.Status, "Sv-bdizc")
step(t, mc) // ROR
assert.Assert(t, mc.A, 64)
assert.Assert(t, mc.Status, "sv-bdizc")
rtest.EquateRegisters(t, mc.A, 64)
rtest.EquateRegisters(t, mc.Status, "sv-bdizc")
}
func testImmediateImplied(t *testing.T, mc *cpu.CPU, mem *mockMem) {
@ -178,48 +178,48 @@ func testImmediateImplied(t *testing.T, mc *cpu.CPU, mem *mockMem) {
// LDX immediate; INX; DEX
origin = mem.putInstructions(origin, 0xa2, 5, 0xe8, 0xca)
step(t, mc) // LDX #5
assert.Assert(t, mc.X, 5)
rtest.EquateRegisters(t, mc.X, 5)
step(t, mc) // INX
assert.Assert(t, mc.X, 6)
rtest.EquateRegisters(t, mc.X, 6)
step(t, mc) // DEX
assert.Assert(t, mc.X, 5)
assert.Assert(t, mc.Status, "sv-bdizc")
rtest.EquateRegisters(t, mc.X, 5)
rtest.EquateRegisters(t, mc.Status, "sv-bdizc")
// PHA; LDA immediate; PLA
origin = mem.putInstructions(origin, 0xa9, 5, 0x48, 0xa9, 0, 0x68)
step(t, mc) // LDA #5
step(t, mc) // PHA
assert.Assert(t, mc.SP, 254)
rtest.EquateRegisters(t, mc.SP, 254)
step(t, mc) // LDA #0
assert.Assert(t, mc.A, 0)
assert.Assert(t, mc.Status.Zero, true)
rtest.EquateRegisters(t, mc.A, 0)
rtest.EquateRegisters(t, mc.Status.Zero, true)
step(t, mc) // PLA
assert.Assert(t, mc.A, 5)
rtest.EquateRegisters(t, mc.A, 5)
// TAX; TAY; LDX immediate; TXA; LDY immediate; TYA; INY; DEY
origin = mem.putInstructions(origin, 0xaa, 0xa8, 0xa2, 1, 0x8a, 0xa0, 2, 0x98, 0xc8, 0x88)
step(t, mc) // TAX
assert.Assert(t, mc.X, 5)
rtest.EquateRegisters(t, mc.X, 5)
step(t, mc) // TAY
assert.Assert(t, mc.Y, 5)
rtest.EquateRegisters(t, mc.Y, 5)
step(t, mc) // LDX #1
step(t, mc) // TXA
assert.Assert(t, mc.A, 1)
rtest.EquateRegisters(t, mc.A, 1)
step(t, mc) // LDY #2
step(t, mc) // TYA
assert.Assert(t, mc.A, 2)
rtest.EquateRegisters(t, mc.A, 2)
step(t, mc) // INY
assert.Assert(t, mc.Y, 3)
rtest.EquateRegisters(t, mc.Y, 3)
step(t, mc) // DEY
assert.Assert(t, mc.Y, 2)
rtest.EquateRegisters(t, mc.Y, 2)
// TSX; LDX immediate; TXS
_ = mem.putInstructions(origin, 0xba, 0xa2, 100, 0x9a)
step(t, mc) // TSX
assert.Assert(t, mc.X, 255)
rtest.EquateRegisters(t, mc.X, 255)
step(t, mc) // LDX #100
step(t, mc) // TXS
assert.Assert(t, mc.SP, 100)
rtest.EquateRegisters(t, mc.SP, 100)
}
func testOtherAddressingModes(t *testing.T, mc *cpu.CPU, mem *mockMem) {
@ -233,38 +233,38 @@ func testOtherAddressingModes(t *testing.T, mc *cpu.CPU, mem *mockMem) {
// LDA zero page
origin = mem.putInstructions(origin, 0xa5, 0x00)
step(t, mc) // LDA $00
assert.Assert(t, mc.A, 0xa5)
rtest.EquateRegisters(t, mc.A, 0xa5)
// LDX immediate; LDA zero page,X
origin = mem.putInstructions(origin, 0xa2, 1, 0xb5, 0x01)
step(t, mc) // LDX #1
step(t, mc) // LDA 01,X
assert.Assert(t, mc.A, 0xa2)
rtest.EquateRegisters(t, mc.A, 0xa2)
// LDY immediate; LDX zero page,Y
origin = mem.putInstructions(origin, 0xa0, 3, 0xb6, 0x01)
step(t, mc) // LDX #3
step(t, mc) // LDA 01,Y
assert.Assert(t, mc.A, 0xa2)
rtest.EquateRegisters(t, mc.A, 0xa2)
// LDA absolute
origin = mem.putInstructions(origin, 0xad, 0x00, 0x01)
step(t, mc) // LDA $0100
assert.Assert(t, mc.A, 123)
rtest.EquateRegisters(t, mc.A, 123)
// LDX immediate; LDA absolute,X
origin = mem.putInstructions(origin, 0xa2, 1, 0xbd, 0x01, 0x00)
step(t, mc) // LDX #1
assert.Assert(t, mc.X, 1)
rtest.EquateRegisters(t, mc.X, 1)
step(t, mc) // LDA $0001,X
assert.Assert(t, mc.A, 0xa2)
rtest.EquateRegisters(t, mc.A, 0xa2)
// LDY immediate; LDA absolute,Y
origin = mem.putInstructions(origin, 0xa0, 1, 0xb9, 0x01, 0x00)
step(t, mc) // LDY #1
assert.Assert(t, mc.X, 1)
rtest.EquateRegisters(t, mc.X, 1)
step(t, mc) // LDA $0001,Y
assert.Assert(t, mc.A, 0xa2)
rtest.EquateRegisters(t, mc.A, 0xa2)
// pre-indexed indirect
// X = 1
@ -272,8 +272,8 @@ func testOtherAddressingModes(t *testing.T, mc *cpu.CPU, mem *mockMem) {
origin = mem.putInstructions(origin, 0xe8, 0xa1, 0x0b)
step(t, mc) // INX (x equals 2)
step(t, mc) // LDA (0x0b,X)
assert.Assert(t, mc.LastResult.Bug, "")
assert.Assert(t, mc.A, 47)
rtest.EquateRegisters(t, mc.LastResult.Bug, "")
rtest.EquateRegisters(t, mc.A, 47)
// post-indexed indirect (see below)
@ -283,8 +283,8 @@ func testOtherAddressingModes(t *testing.T, mc *cpu.CPU, mem *mockMem) {
origin = mem.putInstructions(origin, 0xe8, 0xa1, 0xff)
step(t, mc) // INX (x equals 2)
step(t, mc) // LDA (0xff,X)
assert.Assert(t, mc.LastResult.Bug, "indirect addressing bug")
assert.Assert(t, mc.A, 47)
rtest.EquateRegisters(t, mc.LastResult.Bug, "indirect addressing bug")
rtest.EquateRegisters(t, mc.A, 47)
// post-indexed indirect (with page-fault)
// Y = 1
@ -294,8 +294,8 @@ func testOtherAddressingModes(t *testing.T, mc *cpu.CPU, mem *mockMem) {
step(t, mc) // INY (y = 2)
step(t, mc) // INY (y = 2)
step(t, mc) // LDA (0x0b),Y
assert.Assert(t, mc.A, 123)
assert.Assert(t, mc.LastResult.PageFault, true)
rtest.EquateRegisters(t, mc.A, 123)
rtest.EquateRegisters(t, mc.LastResult.PageFault, true)
}
func testPostIndexedIndirect(t *testing.T, mc *cpu.CPU, mem *mockMem) {
@ -309,10 +309,10 @@ func testPostIndexedIndirect(t *testing.T, mc *cpu.CPU, mem *mockMem) {
origin = mem.putInstructions(origin, 0x01, 0xee, 0xfe, 0xfd)
origin = mem.putInstructions(origin, 0xa0, 0x01)
step(t, mc)
assert.Assert(t, mc.Y, 1)
rtest.EquateRegisters(t, mc.Y, 1)
_ = mem.putInstructions(origin, 0xb1, 0x00)
step(t, mc)
assert.Assert(t, mc.A, 0x03)
rtest.EquateRegisters(t, mc.A, 0x03)
}
func testStorageInstructions(t *testing.T, mc *cpu.CPU, mem *mockMem) {
@ -362,21 +362,21 @@ func testBranching(t *testing.T, mc *cpu.CPU, mem *mockMem) {
_ = mc.Reset()
_ = mem.putInstructions(origin, 0x10, 0x10)
step(t, mc) // BPL $10
assert.Assert(t, mc.PC, 0x12)
rtest.EquateRegisters(t, mc.PC, 0x12)
origin = 0
mem.Clear()
_ = mc.Reset()
_ = mem.putInstructions(origin, 0x50, 0x10)
step(t, mc) // BVC $10
assert.Assert(t, mc.PC, 0x12)
rtest.EquateRegisters(t, mc.PC, 0x12)
origin = 0
mem.Clear()
_ = mc.Reset()
_ = mem.putInstructions(origin, 0x90, 0x10)
step(t, mc) // BCC $10
assert.Assert(t, mc.PC, 0x12)
rtest.EquateRegisters(t, mc.PC, 0x12)
origin = 0
mem.Clear()
@ -384,7 +384,7 @@ func testBranching(t *testing.T, mc *cpu.CPU, mem *mockMem) {
_ = mem.putInstructions(origin, 0x38, 0xb0, 0x10)
step(t, mc) // SEC
step(t, mc) // BCS $10
assert.Assert(t, mc.PC, 0x13)
rtest.EquateRegisters(t, mc.PC, 0x13)
origin = 0
mem.Clear()
@ -392,7 +392,7 @@ func testBranching(t *testing.T, mc *cpu.CPU, mem *mockMem) {
_ = mem.putInstructions(origin, 0xe8, 0xd0, 0x10)
step(t, mc) // INX
step(t, mc) // BNE $10
assert.Assert(t, mc.PC, 0x13)
rtest.EquateRegisters(t, mc.PC, 0x13)
origin = 0
mem.Clear()
@ -400,12 +400,12 @@ func testBranching(t *testing.T, mc *cpu.CPU, mem *mockMem) {
_ = mem.putInstructions(origin, 0xca, 0x30, 0x10)
step(t, mc) // DEX
step(t, mc) // BMI $10
assert.Assert(t, mc.PC, 0x13)
rtest.EquateRegisters(t, mc.PC, 0x13)
_ = mem.putInstructions(0x13, 0xe8, 0xf0, 0x10)
step(t, mc) // INX
step(t, mc) // BEQ $10
assert.Assert(t, mc.PC, 0x26)
rtest.EquateRegisters(t, mc.PC, 0x26)
origin = 0
mem.Clear()
@ -414,7 +414,7 @@ func testBranching(t *testing.T, mc *cpu.CPU, mem *mockMem) {
mc.Status.Overflow = true
_ = mem.putInstructions(origin, 0x70, 0x10)
step(t, mc) // BVS $10
assert.Assert(t, mc.PC, 0x12)
rtest.EquateRegisters(t, mc.PC, 0x12)
}
func testJumps(t *testing.T, mc *cpu.CPU, mem *mockMem) {
@ -425,7 +425,7 @@ func testJumps(t *testing.T, mc *cpu.CPU, mem *mockMem) {
// JMP absolute
_ = mem.putInstructions(origin, 0x4c, 0x00, 0x01)
step(t, mc) // JMP $100
assert.Assert(t, mc.PC, 0x0100)
rtest.EquateRegisters(t, mc.PC, 0x0100)
// JMP indirect
origin = 0
@ -435,7 +435,7 @@ func testJumps(t *testing.T, mc *cpu.CPU, mem *mockMem) {
mem.putInstructions(0x0050, 0x49, 0x01)
_ = mem.putInstructions(origin, 0x6c, 0x50, 0x00)
step(t, mc) // JMP ($50)
assert.Assert(t, mc.PC, 0x0149)
rtest.EquateRegisters(t, mc.PC, 0x0149)
// JMP indirect (bug)
origin = 0
@ -446,7 +446,7 @@ func testJumps(t *testing.T, mc *cpu.CPU, mem *mockMem) {
mem.putInstructions(0x0100, 0x00)
_ = mem.putInstructions(origin, 0x6c, 0xFF, 0x01)
step(t, mc) // JMP ($0x01FF)
assert.Assert(t, mc.PC, 0x0003)
rtest.EquateRegisters(t, mc.PC, 0x0003)
}
func testComparisonInstructions(t *testing.T, mc *cpu.CPU, mem *mockMem) {
@ -457,41 +457,41 @@ func testComparisonInstructions(t *testing.T, mc *cpu.CPU, mem *mockMem) {
// CMP immediate (equality)
origin = mem.putInstructions(origin, 0xc9, 0x00)
step(t, mc) // CMP $00
assert.Assert(t, mc.Status, "sv-bdiZC")
rtest.EquateRegisters(t, mc.Status, "sv-bdiZC")
// LDA immediate; CMP immediate
origin = mem.putInstructions(origin, 0xa9, 0xf6, 0xc9, 0x18)
step(t, mc) // LDA $F6
step(t, mc) // CMP $10
assert.Assert(t, mc.Status, "Sv-bdizC")
rtest.EquateRegisters(t, mc.Status, "Sv-bdizC")
// LDX immediate; CMP immediate
origin = mem.putInstructions(origin, 0xa2, 0xf6, 0xe0, 0x18)
step(t, mc) // LDX $F6
step(t, mc) // CMP $10
assert.Assert(t, mc.Status, "Sv-bdizC")
rtest.EquateRegisters(t, mc.Status, "Sv-bdizC")
// LDY immediate; CMP immediate
origin = mem.putInstructions(origin, 0xa0, 0xf6, 0xc0, 0x18)
step(t, mc) // LDY $F6
step(t, mc) // CMP $10
assert.Assert(t, mc.Status, "Sv-bdizC")
rtest.EquateRegisters(t, mc.Status, "Sv-bdizC")
// LDA immediate; CMP immediate
origin = mem.putInstructions(origin, 0xa9, 0x18, 0xc9, 0xf6)
step(t, mc) // LDA $F6
step(t, mc) // CMP $10
assert.Assert(t, mc.Status, "sv-bdizc")
rtest.EquateRegisters(t, mc.Status, "sv-bdizc")
// BIT zero page
origin = mem.putInstructions(origin, 0x24, 0x01)
step(t, mc) // BIT $01
assert.Assert(t, mc.Status, "sv-bdiZc")
rtest.EquateRegisters(t, mc.Status, "sv-bdiZc")
// BIT immediate
_ = mem.putInstructions(origin, 0x24, 0x01)
step(t, mc) // BIT $01
assert.Assert(t, mc.Status, "sv-bdiZc")
rtest.EquateRegisters(t, mc.Status, "sv-bdiZc")
}
func testSubroutineInstructions(t *testing.T, mc *cpu.CPU, mem *mockMem) {
@ -502,17 +502,17 @@ func testSubroutineInstructions(t *testing.T, mc *cpu.CPU, mem *mockMem) {
// JSR absolute
_ = mem.putInstructions(origin, 0x20, 0x00, 0x01)
step(t, mc) // JSR $0100
assert.Assert(t, mc.PC, 0x0100)
rtest.EquateRegisters(t, mc.PC, 0x0100)
mem.assert(t, 255, 0x00)
mem.assert(t, 254, 0x02)
assert.Assert(t, mc.SP, 253)
rtest.EquateRegisters(t, mc.SP, 253)
_ = mem.putInstructions(0x100, 0x60)
step(t, mc) // RTS
assert.Assert(t, mc.PC, 0x0003)
rtest.EquateRegisters(t, mc.PC, 0x0003)
mem.assert(t, 255, 0x00)
mem.assert(t, 254, 0x02)
assert.Assert(t, mc.SP, 255)
rtest.EquateRegisters(t, mc.SP, 255)
}
func testDecimalMode(t *testing.T, mc *cpu.CPU, mem *mockMem) {
@ -525,7 +525,7 @@ func testDecimalMode(t *testing.T, mc *cpu.CPU, mem *mockMem) {
step(t, mc) // LDA #$20
step(t, mc) // SEC
step(t, mc) // SBC #$00
assert.Assert(t, mc.A, 0x19)
rtest.EquateRegisters(t, mc.A, 0x19)
}
func testStrictAddressing(t *testing.T, mc *cpu.CPU, mem *mockMem) {

View file

@ -1,102 +0,0 @@
package assert
import (
"gopher2600/hardware/cpu/registers"
"reflect"
"testing"
)
// Assert is used to test equality between one value and another
func Assert(t *testing.T, r, x interface{}) {
t.Helper()
switch r := r.(type) {
default:
t.Errorf("assert failed (unknown type [%s])", reflect.TypeOf(r))
case *registers.Register:
switch x := x.(type) {
default:
t.Errorf("assert failed (unknown type [%s])", reflect.TypeOf(x))
case int:
if int(r.Value()) != x {
t.Errorf("assert Register failed (%d - wanted %d", r.Value(), x)
}
}
case *registers.ProgramCounter:
switch x := x.(type) {
default:
t.Errorf("assert failed (unknown type [%s])", reflect.TypeOf(x))
case int:
if int(r.Address()) != x {
t.Errorf("assert ProgramCounter failed (%d - wanted %d", r.Address(), x)
}
}
case *registers.StatusRegister:
switch x := x.(type) {
default:
t.Errorf("assert failed (unknown type [%s])", reflect.TypeOf(x))
case int:
if int(r.Value()) != x {
t.Errorf("assert StatusRegister failed (%d - wanted %d", r.Value(), x)
}
case string:
if len(x) != 8 {
t.Errorf("assert StatusRegister failed (status flags must be integer of a string of 8 chars)")
}
if x[0] != 's' && !r.Sign || x[0] != 'S' && r.Sign {
t.Errorf("assert StatusRegister failed (unexpected sign flag")
}
if x[1] != 'v' && !r.Overflow || x[1] != 'V' && r.Overflow {
t.Errorf("assert StatusRegister failed (unexpected overflow flag")
}
if x[3] != 'b' && !r.Break || x[3] != 'B' && r.Break {
t.Errorf("assert StatusRegister failed (unexpected break flag")
}
if x[4] != 'd' && !r.DecimalMode || x[4] != 'D' && r.DecimalMode {
t.Errorf("assert StatusRegister failed (unexpected decimal mode flag")
}
if x[5] != 'i' && !r.InterruptDisable || x[5] != 'I' && r.InterruptDisable {
t.Errorf("assert StatusRegister failed (unexpected interrupt disable flag")
}
if x[6] != 'z' && !r.Zero || x[6] != 'Z' && r.Zero {
t.Errorf("assert StatusRegister failed (unexpected zero flag")
}
if x[7] != 'c' && !r.Carry || x[7] != 'C' && r.Carry {
t.Errorf("assert StatusRegister failed (unexpected carry flag")
}
}
case uint16:
switch x := x.(type) {
default:
t.Errorf("assert failed (unknown type [%s])", reflect.TypeOf(x))
case int:
if int(r) != x {
t.Errorf("assert Register failed (%d - wanted %d", r, x)
}
}
case string:
if r != x.(string) {
t.Errorf("assert string failed (%v - wanted %v", r, x.(string))
}
case bool:
if r != x.(bool) {
t.Errorf("assert bool failed (%v - wanted %v", r, x.(bool))
}
case int:
if r != x.(int) {
t.Errorf("assert int failed (%d - wanted %d)", r, x.(int))
}
}
}

View file

@ -2,7 +2,8 @@ package registers_test
import (
"gopher2600/hardware/cpu/registers"
"gopher2600/hardware/cpu/registers/assert"
rtest "gopher2600/hardware/cpu/registers/test"
"gopher2600/test"
"testing"
)
@ -14,42 +15,42 @@ func TestDecimalMode(t *testing.T) {
// addition without carry
rcarry = r8.AddDecimal(1, false)
assert.Assert(t, r8, 0x01)
assert.Assert(t, rcarry, false)
rtest.EquateRegisters(t, r8, 0x01)
test.Equate(t, rcarry, false)
// addition with carry
rcarry = r8.AddDecimal(1, true)
assert.Assert(t, r8, 0x03)
assert.Assert(t, rcarry, false)
rtest.EquateRegisters(t, r8, 0x03)
test.Equate(t, rcarry, false)
// subtraction with carry (subtract value)
r8.Load(9)
assert.Assert(t, r8, 0x09)
rtest.EquateRegisters(t, r8, 0x09)
rcarry = r8.SubtractDecimal(1, true)
assert.Assert(t, r8, 0x08)
rtest.EquateRegisters(t, r8, 0x08)
// subtraction without carry (subtract value and another 1)
rcarry = r8.SubtractDecimal(1, false)
assert.Assert(t, r8, 0x06)
rtest.EquateRegisters(t, r8, 0x06)
// addition on tens boundary
r8.Load(9)
assert.Assert(t, r8, 0x09)
rtest.EquateRegisters(t, r8, 0x09)
rcarry = r8.AddDecimal(1, false)
assert.Assert(t, r8, 0x10)
rtest.EquateRegisters(t, r8, 0x10)
// subtraction on tens boundary
rcarry = r8.SubtractDecimal(1, true)
assert.Assert(t, r8, 0x09)
rtest.EquateRegisters(t, r8, 0x09)
// addition on hundreds boundary
r8.Load(0x99)
assert.Assert(t, r8, 0x99)
rtest.EquateRegisters(t, r8, 0x99)
rcarry = r8.AddDecimal(1, false)
assert.Assert(t, r8, 0x00)
assert.Assert(t, rcarry, true)
rtest.EquateRegisters(t, r8, 0x00)
test.Equate(t, rcarry, true)
// subtraction on hundreds boundary
rcarry = r8.SubtractDecimal(1, true)
assert.Assert(t, r8, 0x99)
rtest.EquateRegisters(t, r8, 0x99)
}

View file

@ -2,18 +2,19 @@ package registers_test
import (
"gopher2600/hardware/cpu/registers"
"gopher2600/hardware/cpu/registers/assert"
rtest "gopher2600/hardware/cpu/registers/test"
"gopher2600/test"
"testing"
)
func TestProgramCounter(t *testing.T) {
// initialisation
pc := registers.NewProgramCounter(0)
assert.Assert(t, pc.Address(), 0)
test.Equate(t, pc.Address(), 0)
// loading & addition
pc.Load(127)
assert.Assert(t, pc, 127)
rtest.EquateRegisters(t, pc, 127)
pc.Add(2)
assert.Assert(t, pc, 129)
rtest.EquateRegisters(t, pc, 129)
}

View file

@ -2,7 +2,8 @@ package registers_test
import (
"gopher2600/hardware/cpu/registers"
"gopher2600/hardware/cpu/registers/assert"
rtest "gopher2600/hardware/cpu/registers/test"
"gopher2600/test"
"testing"
)
@ -11,91 +12,91 @@ func TestRegister(t *testing.T) {
// initialisation
r8 := registers.NewRegister(0, "test")
assert.Assert(t, r8.IsZero(), true)
assert.Assert(t, r8, 0)
test.Equate(t, r8.IsZero(), true)
rtest.EquateRegisters(t, r8, 0)
// loading & addition
r8.Load(127)
assert.Assert(t, r8, 127)
rtest.EquateRegisters(t, r8, 127)
r8.Add(2, false)
assert.Assert(t, r8, 129)
rtest.EquateRegisters(t, r8, 129)
// addtion boundary
r8.Load(255)
assert.Assert(t, r8.IsNegative(), true)
test.Equate(t, r8.IsNegative(), true)
carry, overflow = r8.Add(1, false)
assert.Assert(t, carry, true)
assert.Assert(t, overflow, false)
assert.Assert(t, r8.IsZero(), true)
assert.Assert(t, r8, 0)
test.Equate(t, carry, true)
test.Equate(t, overflow, false)
test.Equate(t, r8.IsZero(), true)
rtest.EquateRegisters(t, r8, 0)
// addition boundary with carry
r8.Load(254)
assert.Assert(t, r8.IsNegative(), true)
test.Equate(t, r8.IsNegative(), true)
carry, overflow = r8.Add(1, true)
assert.Assert(t, carry, true)
assert.Assert(t, overflow, false)
assert.Assert(t, r8.IsZero(), true)
assert.Assert(t, r8, 0)
test.Equate(t, carry, true)
test.Equate(t, overflow, false)
test.Equate(t, r8.IsZero(), true)
rtest.EquateRegisters(t, r8, 0)
// addition boundary with carry
r8.Load(255)
assert.Assert(t, r8.IsNegative(), true)
test.Equate(t, r8.IsNegative(), true)
carry, overflow = r8.Add(1, true)
assert.Assert(t, carry, true)
assert.Assert(t, overflow, false)
assert.Assert(t, r8.IsZero(), false)
assert.Assert(t, r8, 1)
test.Equate(t, carry, true)
test.Equate(t, overflow, false)
test.Equate(t, r8.IsZero(), false)
rtest.EquateRegisters(t, r8, 1)
// subtraction
r8.Load(11)
r8.Subtract(1, true)
assert.Assert(t, r8, 10)
rtest.EquateRegisters(t, r8, 10)
r8.Load(12)
r8.Subtract(1, false)
assert.Assert(t, r8, 10)
rtest.EquateRegisters(t, r8, 10)
r8.Load(0x01)
r8.Subtract(0x06, false)
assert.Assert(t, r8, 0xFA)
rtest.EquateRegisters(t, r8, 0xFA)
// subtract on boundary
r8.Load(0)
r8.Subtract(1, true)
assert.Assert(t, r8, 255)
rtest.EquateRegisters(t, r8, 255)
r8.Load(1)
r8.Subtract(1, false)
assert.Assert(t, r8, 255)
rtest.EquateRegisters(t, r8, 255)
r8.Load(1)
r8.Subtract(2, true)
assert.Assert(t, r8, 255)
rtest.EquateRegisters(t, r8, 255)
// logical operators
r8.Load(0x21)
r8.AND(0x01)
assert.Assert(t, r8, 0x01)
rtest.EquateRegisters(t, r8, 0x01)
r8.EOR(0xFF)
assert.Assert(t, r8, 0xFE)
rtest.EquateRegisters(t, r8, 0xFE)
r8.ORA(0x1)
assert.Assert(t, r8, 0xFF)
rtest.EquateRegisters(t, r8, 0xFF)
// shifts
carry = r8.ASL()
assert.Assert(t, r8, 0xFE)
assert.Assert(t, carry, true)
rtest.EquateRegisters(t, r8, 0xFE)
test.Equate(t, carry, true)
carry = r8.LSR()
assert.Assert(t, r8, 0x007F)
assert.Assert(t, carry, false)
rtest.EquateRegisters(t, r8, 0x007F)
test.Equate(t, carry, false)
carry = r8.LSR()
assert.Assert(t, carry, true)
test.Equate(t, carry, true)
// rotation
r8.Load(0xff)
carry = r8.ROL(false)
assert.Assert(t, r8, 0xfe)
assert.Assert(t, carry, true)
rtest.EquateRegisters(t, r8, 0xfe)
test.Equate(t, carry, true)
carry = r8.ROR(true)
assert.Assert(t, r8, 0xff)
assert.Assert(t, carry, false)
rtest.EquateRegisters(t, r8, 0xff)
test.Equate(t, carry, false)
}

View file

@ -0,0 +1,3 @@
// Package test contains functions useful for testing CPU registers. For now it
// contains just one function, EquateRegisters()
package test

View file

@ -0,0 +1,77 @@
package test
import (
"gopher2600/hardware/cpu/registers"
"testing"
)
// EquateRegisters is used to test equality between two instances of a register
// type. Used in testing packages.
func EquateRegisters(t *testing.T, value, expectedValue interface{}) {
t.Helper()
switch value := value.(type) {
default:
t.Fatalf("not a register type (%T)", value)
case *registers.Register:
switch expectedValue := expectedValue.(type) {
default:
t.Fatalf("unhandled type (%T)", value)
case int:
if int(value.Value()) != expectedValue {
t.Errorf("unexpected Register value (%d wanted %d)", value.Value(), expectedValue)
}
}
case *registers.ProgramCounter:
switch expectedValue := expectedValue.(type) {
default:
t.Fatalf("unhandled type (%T)", value)
case int:
if int(value.Address()) != expectedValue {
t.Errorf("unexpected ProgramCounter value (%d wanted %d)", value, expectedValue)
}
}
case *registers.StatusRegister:
switch expectedValue := expectedValue.(type) {
default:
t.Fatalf("unhandled type (%T)", value)
case int:
if int(value.Value()) != expectedValue {
t.Errorf("unexpected StatusRegister value (%d wanted %d)", value.Value(), expectedValue)
}
case string:
if len(expectedValue) != 8 {
t.Fatalf("status expressed as string must be 8 chars long")
}
if expectedValue[0] != 's' && !value.Sign || expectedValue[0] != 'S' && value.Sign {
t.Errorf("unexpected StatusRegister flag (sign)")
}
if expectedValue[1] != 'v' && !value.Overflow || expectedValue[1] != 'V' && value.Overflow {
t.Errorf("unexpected StatusRegister flag (overflow)")
}
if expectedValue[3] != 'b' && !value.Break || expectedValue[3] != 'B' && value.Break {
t.Errorf("unexpected StatusRegister flag (break)")
}
if expectedValue[4] != 'd' && !value.DecimalMode || expectedValue[4] != 'D' && value.DecimalMode {
t.Errorf("unexpected StatusRegister flag (decimal mode)")
}
if expectedValue[5] != 'i' && !value.InterruptDisable || expectedValue[5] != 'I' && value.InterruptDisable {
t.Errorf("unexpected StatusRegister flag (interrupt diable)")
}
if expectedValue[6] != 'z' && !value.Zero || expectedValue[6] != 'Z' && value.Zero {
t.Errorf("unexpected StatusRegister flag (zero)")
}
if expectedValue[7] != 'c' && !value.Carry || expectedValue[7] != 'C' && value.Carry {
t.Errorf("unexpected StatusRegister flag (carry)")
}
}
}
}

View file

@ -1,6 +1,5 @@
// Package test contains several helper functions that should make construction
// of test packages a little bit easier and remove boilerplate in many common
// test situations.
// Package test contains helper functions to remove common boilerplate to make
// testing easier.
//
// The ExpectedFailure and ExpectedSuccess functions test for failure and
// success under generic conditions. The documenation for those functions
@ -18,4 +17,8 @@
// The Writer type meanwhile, implements the io.Writer interface and should be
// used to capture output. The Writer.Compare() function can then be used to
// test for equality.
//
// The Equate() function compares like-typed variables for equality. Some
// types (eg. uint16) can be compared against int for convenience. See Equate()
// documentation for discussion why.
package test

70
test/equate.go Normal file
View file

@ -0,0 +1,70 @@
package test
import (
"reflect"
"testing"
)
// Equate is used to test equality between one value and another. Generally,
// both values must be of the same type but if a is of type uint16, b can be
// uint16 or int. The reason for this is that a literal number value is of type
// int. It is very convenient to write something like this, without having to
// cast the expected number value:
//
// var r uint16
// r = someFunction()
// test.Equate(t, r, 10)
//
// This is by no means a comprehensive comparison function. With a bit more
// work with the reflect package we could generalise the testing a lot more. At
// is is however, it's good enough.
func Equate(t *testing.T, value, expectedValue interface{}) {
t.Helper()
switch value := value.(type) {
default:
t.Fatalf("unhandled type for Equate() function (%T))", value)
case int:
if reflect.TypeOf(value) != reflect.TypeOf(expectedValue) {
t.Fatalf("values for Equate() are not the same type (%T and %T)", value, expectedValue)
}
if value != expectedValue.(int) {
t.Errorf("equation of type %T failed (%d - wanted %d)", value, value, expectedValue.(int))
}
case uint16:
switch expectedValue := expectedValue.(type) {
case int:
if value != uint16(expectedValue) {
t.Errorf("equation of type %T failed (%d - wanted %d)", value, value, expectedValue)
}
case uint16:
if value != expectedValue {
t.Errorf("equation of type %T failed (%d - wanted %d)", value, value, expectedValue)
}
default:
t.Fatalf("values for Equate() are not the same compatible (%T and %T)", value, expectedValue)
}
case string:
if reflect.TypeOf(value) != reflect.TypeOf(expectedValue) {
t.Fatalf("values for Equate() are not the same type (%T and %T)", value, expectedValue)
}
if value != expectedValue.(string) {
t.Errorf("equation of type %T failed (%s - wanted %s)", value, value, expectedValue.(string))
}
case bool:
if reflect.TypeOf(value) != reflect.TypeOf(expectedValue) {
t.Fatalf("values for Equate() are not the same type (%T and %T)", value, expectedValue)
}
if value != expectedValue.(bool) {
t.Errorf("equation of type %T failed (%v - wanted %v", value, value, expectedValue.(bool))
}
}
}