package chip8 import ( "fmt" "testing" ) func slicesEqual(x, y []byte) bool { if len(x) != len(y) { return false } for i, xi := range x { if xi != y[i] { return false } } return true } // This test is kinda shit, there's so much stuff we ain't testing // Maybe fix func TestCreateCPU(t *testing.T) { prog := []byte{1, 2, 3, 4} newCPU := NewCHIP8(prog) if !slicesEqual(newCPU.memory[200:204], prog) { t.Errorf("CPU not initalized properly") } } func TestClearDisplay(t *testing.T) { cpu := Chip8{opcode: 0x00E0} for i := range cpu.graphics { cpu.graphics[i] = byte(i % 255) } cpu.zeroIndexOpcodes() graphicsArray := cpu.GetGraphicsBuffer() graphicsSlice := graphicsArray[:] emptySlice := make([]byte, len(cpu.graphics)) if !slicesEqual(graphicsSlice, emptySlice) { t.Errorf("Graphics buffer not cleared properly") } } func TestLeaveFunction(t *testing.T) { cpu := Chip8{pc: 50, opcode: 0x00EE} cpu.stack = append(cpu.stack, 1, 2, 3, 4, 5) cpu.zeroIndexOpcodes() if cpu.pc != 4 && len(cpu.stack) != 4 { t.Errorf("TestLeaveFunction not in expected state") } } func TestGoTo(t *testing.T) { cpu := Chip8{opcode: 0x3420} cpu.goTo() if cpu.pc != 0x420 { t.Errorf("Test GoTo not working as expected") } } func TestCallSubroutine(t *testing.T) { cpu := Chip8{opcode: 0x3420, pc: 43} cpu.callSubroutine() if (cpu.pc != 420) && (cpu.stack[0] != 43) && (len(cpu.stack) != 1) { t.Errorf("CallSubroutine not working as expected") } } func TestSkipIfRegisterEqual(t *testing.T) { var tests = []struct { register, regValue byte compValue, want uint16 }{ {0, 2, 4, 0}, {0, 2, 2, 2}, {15, 2, 2, 2}, {15, 1, 12, 0}, } for _, tt := range tests { testname := fmt.Sprintf("Reg:%d,RegVal:%d,Comp:%d", tt.register, tt.regValue, tt.compValue) t.Run(testname, func(t *testing.T) { cpu := Chip8{opcode: tt.compValue + uint16(tt.register)<<8} cpu.registers[tt.register] = tt.regValue cpu.skipIfRegisterEqual() if tt.want != cpu.pc { t.Errorf("PC is %d, Wanted %d", cpu.pc, tt.want) } }) } } func TestSkipIfRegisterNotEqual(t *testing.T) { var tests = []struct { register, regValue byte compValue, want uint16 }{ {0, 2, 4, 2}, {0, 2, 2, 0}, {15, 2, 2, 0}, {15, 1, 12, 2}, } for _, tt := range tests { testname := fmt.Sprintf("Reg:%d,RegVal:%d,Comp:%d", tt.register, tt.regValue, tt.compValue) t.Run(testname, func(t *testing.T) { cpu := Chip8{opcode: tt.compValue + uint16(tt.register)<<8} cpu.registers[tt.register] = tt.regValue cpu.skipIfRegisterNotEqual() if tt.want != cpu.pc { t.Errorf("PC is %d, Wanted %d", cpu.pc, tt.want) } }) } } func TestSkipIfRegistersEqual(t *testing.T) { var tests = []struct { reg1, reg2, val1, val2 byte }{ {0, 2, 4, 2}, {0, 2, 2, 2}, {15, 1, 2, 0}, {15, 4, 12, 12}, } for _, tt := range tests { testname := fmt.Sprintf("Reg1:%d,Reg2:%d,val1:%d,val2:%d", tt.reg1, tt.reg2, tt.val1, tt.val2) t.Run(testname, func(t *testing.T) { cpu := Chip8{opcode: uint16(tt.reg1)<<8 + uint16(tt.reg2)<<4} cpu.registers[tt.reg1] = tt.val1 cpu.registers[tt.reg2] = tt.val2 cpu.skipIfRegistersEqual() if (2 != cpu.pc) && (tt.val1 == tt.val2) { t.Errorf("PC is %d, Wanted %d", cpu.pc, 2) } else if (0 != cpu.pc) && (tt.val1 != tt.val2) { t.Errorf("PC is %d, Wanted %d", cpu.pc, 2) } }) } } func TestSetRegisterTo(t *testing.T) { cpu := Chip8{opcode: 0x0824} cpu.setRegisterTo() if cpu.registers[8] != 0x24 { t.Errorf("Register 8 is %d wanted %d", cpu.registers[8], 0x24) } } func TestRegisterPlusEqualsNN(t *testing.T) { var tests = []struct { register, initalVal, toAdd, expected byte }{ {0, 2, 2, 4}, {0, 254, 3, 1}, {15, 2, 0, 2}, {15, 250, 6, 0}, } for _, tt := range tests { testname := fmt.Sprintf("Register:%d,inital:%d,toAdd:%d,expected:%d", tt.register, tt.initalVal, tt.toAdd, tt.expected) t.Run(testname, func(t *testing.T) { cpu := Chip8{opcode: uint16(tt.register)<<8 + uint16(tt.toAdd)} cpu.registers[tt.register] = tt.initalVal cpu.registerPlusEqualsNN() if cpu.registers[tt.register] != tt.expected { t.Errorf("Register is %d, wanted %d", cpu.registers[tt.register], tt.expected) } }) } }