Files
zzg 8b41184b28
ci / test (push) Canceled after 0s
initial commit
2026-09-25 21:49:09 -07:00

110 lines
2.5 KiB
Go

package code
import "testing"
func TestMake(t *testing.T) {
tests := []struct {
op Opcode
operands []int
want []byte
}{
{OpConstant, []int{65534}, []byte{byte(OpConstant), 255, 254}},
{OpAdd, nil, []byte{byte(OpAdd)}},
{OpGetLocal, []int{255}, []byte{byte(OpGetLocal), 255}},
{OpClosure, []int{65534, 255}, []byte{byte(OpClosure), 255, 254, 255}},
}
for _, tt := range tests {
ins := Make(tt.op, tt.operands...)
if len(ins) != len(tt.want) {
t.Fatalf("length = %d, want %d", len(ins), len(tt.want))
}
for i, b := range tt.want {
if ins[i] != b {
t.Errorf("byte %d = %d, want %d", i, ins[i], b)
}
}
}
}
// Every instruction must decode back to exactly what was encoded, or the
// VM and compiler would silently disagree.
func TestReadOperandsRoundTrip(t *testing.T) {
tests := []struct {
op Opcode
operands []int
bytesRead int
}{
{OpConstant, []int{65535}, 2},
{OpGetLocal, []int{255}, 1},
{OpClosure, []int{65535, 255}, 3},
}
for _, tt := range tests {
ins := Make(tt.op, tt.operands...)
def, err := Lookup(byte(tt.op))
if err != nil {
t.Fatal(err)
}
got, n := ReadOperands(def, ins[1:])
if n != tt.bytesRead {
t.Errorf("read %d bytes, want %d", n, tt.bytesRead)
}
for i, want := range tt.operands {
if got[i] != want {
t.Errorf("operand %d = %d, want %d", i, got[i], want)
}
}
}
}
// Every defined opcode must round-trip, so a newly added one cannot be
// forgotten in ReadOperands.
func TestAllOpcodesRoundTrip(t *testing.T) {
for op, def := range definitions {
operands := make([]int, len(def.OperandWidths))
for i, w := range def.OperandWidths {
if w == 1 {
operands[i] = 200
} else {
operands[i] = 40000
}
}
ins := Make(op, operands...)
if len(ins) == 0 {
t.Errorf("%s: Make returned nothing", def.Name)
continue
}
got, _ := ReadOperands(def, ins[1:])
for i := range operands {
if got[i] != operands[i] {
t.Errorf("%s operand %d: got %d, want %d", def.Name, i, got[i], operands[i])
}
}
}
}
func TestInstructionsString(t *testing.T) {
ins := Instructions{}
for _, i := range []Instructions{
Make(OpAdd),
Make(OpGetLocal, 1),
Make(OpConstant, 2),
Make(OpClosure, 65535, 255),
} {
ins = append(ins, i...)
}
want := `0000 OpAdd
0001 OpGetLocal 1
0003 OpConstant 2
0006 OpClosure 65535 255
`
if got := ins.String(); got != want {
t.Errorf("got:\n%s\nwant:\n%s", got, want)
}
}
func TestLookupUnknownOpcode(t *testing.T) {
if _, err := Lookup(254); err == nil {
t.Error("expected an error for an undefined opcode")
}
}