280 lines
4.0 KiB
Go
280 lines
4.0 KiB
Go
package creature
|
|
|
|
import "testing"
|
|
|
|
func runMachineTest(
|
|
program []int,
|
|
memory []int,
|
|
test *testing.T,
|
|
) (
|
|
machine *Machine[int],
|
|
) {
|
|
machine = &Machine[int]{}
|
|
machine.LoadProgram(program)
|
|
if memory != nil {
|
|
machine.LoadMemory(memory)
|
|
}
|
|
|
|
err := machine.Execute(0)
|
|
if err != nil {
|
|
test.Log("machine exited with error:", err)
|
|
test.Fail()
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func TestPush(test *testing.T) {
|
|
machine := runMachineTest([]int{
|
|
PUSH, 3,
|
|
POP,
|
|
PUSH, 654,
|
|
}, nil, test)
|
|
|
|
result := machine.Pop()
|
|
test.Log("popped:", result)
|
|
|
|
if result != 654 {
|
|
test.Log("result should be", 654)
|
|
test.Fail()
|
|
}
|
|
}
|
|
|
|
func TestArithmetic(test *testing.T) {
|
|
machine := runMachineTest([]int{
|
|
PUSH, 3,
|
|
PUSH, 2,
|
|
ADD,
|
|
|
|
PUSH, 10,
|
|
PUSH, 4,
|
|
SUB,
|
|
|
|
PUSH, 2,
|
|
PUSH, 7,
|
|
MUL,
|
|
|
|
PUSH, 12,
|
|
PUSH, 3,
|
|
DIV,
|
|
|
|
PUSH, 8,
|
|
PUSH, 6,
|
|
MOD,
|
|
}, nil, test)
|
|
|
|
modResult := machine.Pop()
|
|
divResult := machine.Pop()
|
|
mulResult := machine.Pop()
|
|
subResult := machine.Pop()
|
|
addResult := machine.Pop()
|
|
|
|
test.Log("add:", addResult)
|
|
test.Log("sub:", subResult)
|
|
test.Log("mul:", mulResult)
|
|
test.Log("div:", divResult)
|
|
test.Log("mod:", modResult)
|
|
|
|
if addResult != 5 {
|
|
test.Log("add result should be", 5)
|
|
test.Fail()
|
|
}
|
|
|
|
if subResult != 6 {
|
|
test.Log("sub result should be", 6)
|
|
test.Fail()
|
|
}
|
|
|
|
if mulResult != 14 {
|
|
test.Log("mul result should be", 14)
|
|
test.Fail()
|
|
}
|
|
|
|
if divResult != 4 {
|
|
test.Log("div result should be", 4)
|
|
test.Fail()
|
|
}
|
|
|
|
if modResult != 2 {
|
|
test.Log("mod result should be", 2)
|
|
test.Fail()
|
|
}
|
|
}
|
|
|
|
func TestComparison(test *testing.T) {
|
|
machine := runMachineTest([]int{
|
|
PUSH, 6,
|
|
PUSH, 6,
|
|
EQ,
|
|
|
|
PUSH, 324,
|
|
PUSH, 4,
|
|
GT,
|
|
|
|
PUSH, 4,
|
|
PUSH, 324,
|
|
LT,
|
|
|
|
PUSH, 54,
|
|
PUSH, 6,
|
|
NEQ,
|
|
}, nil, test)
|
|
|
|
neqResult := machine.Pop()
|
|
ltResult := machine.Pop()
|
|
gtResult := machine.Pop()
|
|
eqResult := machine.Pop()
|
|
|
|
test.Log("eq:", eqResult)
|
|
test.Log("gt:", gtResult)
|
|
test.Log("lt:", ltResult)
|
|
test.Log("neq:", neqResult)
|
|
|
|
if eqResult != 1 {
|
|
test.Log("eq result should be", 1)
|
|
test.Fail()
|
|
}
|
|
|
|
if gtResult != 1 {
|
|
test.Log("gt result should be", 1)
|
|
test.Fail()
|
|
}
|
|
|
|
if ltResult != 1 {
|
|
test.Log("lt result should be", 1)
|
|
test.Fail()
|
|
}
|
|
|
|
if neqResult != 1 {
|
|
test.Log("neq result should be", 1)
|
|
test.Fail()
|
|
}
|
|
}
|
|
|
|
func TestPeekPoke(test *testing.T) {
|
|
machine := runMachineTest([]int{
|
|
PUSH, 0,
|
|
PEEK,
|
|
|
|
PUSH, 29,
|
|
PUSH, 1,
|
|
POKE,
|
|
|
|
PUSH, 1,
|
|
PEEK,
|
|
}, []int{
|
|
632,
|
|
13,
|
|
}, test)
|
|
|
|
secondResult := machine.Pop()
|
|
firstResult := machine.Pop()
|
|
|
|
test.Log("first:", firstResult)
|
|
test.Log("second:", secondResult)
|
|
|
|
if firstResult != 632 {
|
|
test.Log("first result should be", 632)
|
|
test.Fail()
|
|
}
|
|
|
|
if secondResult != 29 {
|
|
test.Log("second result should be", 29)
|
|
test.Fail()
|
|
}
|
|
}
|
|
|
|
func TestHalt(test *testing.T) {
|
|
machine := runMachineTest([]int{
|
|
PUSH, 32,
|
|
HALT,
|
|
PUSH, 3,
|
|
}, nil, test)
|
|
|
|
result := machine.Pop()
|
|
test.Log("popped:", result)
|
|
|
|
if result != 32 {
|
|
test.Log("result should be", 32)
|
|
test.Fail()
|
|
}
|
|
}
|
|
|
|
func TestJump(test *testing.T) {
|
|
machine := runMachineTest([]int{
|
|
PUSH, 1,
|
|
PUSH, 8,
|
|
JMP,
|
|
|
|
PUSH, 3,
|
|
HALT,
|
|
|
|
PUSH, 0,
|
|
PUSH, 16,
|
|
JMP,
|
|
|
|
PUSH, 4,
|
|
HALT,
|
|
|
|
PUSH, 5,
|
|
}, nil, test)
|
|
|
|
result := machine.Pop()
|
|
test.Log("popped:", result)
|
|
|
|
if result != 4 {
|
|
test.Log("result should be", 4)
|
|
test.Fail()
|
|
}
|
|
}
|
|
|
|
func TestRegister(test *testing.T) {
|
|
output := ""
|
|
machine := &Machine[int]{}
|
|
machine.LoadProgram([]int{
|
|
PUSH, int('h'),
|
|
PUSH, 4,
|
|
CAL,
|
|
PUSH, int('e'),
|
|
PUSH, 4,
|
|
CAL,
|
|
PUSH, int('l'),
|
|
PUSH, 4,
|
|
CAL,
|
|
PUSH, int('l'),
|
|
PUSH, 4,
|
|
CAL,
|
|
PUSH, int('o'),
|
|
PUSH, 4,
|
|
CAL,
|
|
PUSH, int('r'),
|
|
PUSH, 4,
|
|
CAL,
|
|
PUSH, int('l'),
|
|
PUSH, 4,
|
|
CAL,
|
|
PUSH, int('d'),
|
|
PUSH, 4,
|
|
CAL,
|
|
PUSH, int('!'),
|
|
PUSH, 4,
|
|
CAL,
|
|
})
|
|
machine.Register(4, func(machine *Machine[int]) (stop bool) {
|
|
output += string(rune(machine.Pop()))
|
|
return
|
|
})
|
|
|
|
err := machine.Execute(0)
|
|
if err != nil {
|
|
test.Log("machine exited with error:", err)
|
|
test.Fail()
|
|
}
|
|
|
|
test.Log("printed:", output)
|
|
if output != "hellorld!" {
|
|
test.Log("result should be", "hellorld!")
|
|
test.Fail()
|
|
}
|
|
}
|