SilverSight/go/avm_test.go
allaun f6cbddcbf2 feat(tests): Python AVM port rewrite + test harness, Go test harness
Python port rewritten to match spec:
- Added Q0_16, PUSH_Q0, PUSH_BOOL as separate opcodes
- Added V6 comparison (lt_q16_v6)
- Added floor division (Lean Int.ediv)
- Added stack depth limit (AVM_MAX_STACK = 1024)
- Added type checking in exec_prim
- All 10 tests passing

Go AVM port: added test_avm_test.go with 8 test cases

Milestone: Python → , Go → 🔄
2026-06-30 17:56:09 -05:00

112 lines
3.2 KiB
Go

package avm
import "testing"
func q16(x int32) Val { return Val{Ty: Q16_16, Q: avmClamp(int64(x))} }
func runTest(prog []Instr, fuel int) (*State, error) {
return Run(NewState(0), prog, fuel)
}
func TestBasicAdd(t *testing.T) {
prog := []Instr{
{Op: PushQ16, Arg: 5 * Q16Scale},
{Op: PushQ16, Arg: 3 * Q16Scale},
{Op: Primitive, Arg: int32(AddSatQ16)},
{Op: Halt},
}
s, err := runTest(prog, 100)
if err != nil { t.Fatal(err) }
if s.Stack[0].Q != 8*Q16Scale { t.Fatalf("got %d", s.Stack[0].Q) }
}
func TestFloorDiv(t *testing.T) {
// (3 * Q16) / (5 * Q16) = floor(0.6) = 0.6 in Q16
prog := []Instr{
{Op: PushQ16, Arg: 3 * Q16Scale},
{Op: PushQ16, Arg: 5 * Q16Scale},
{Op: Primitive, Arg: int32(DivSatQ16)},
{Op: Halt},
}
s, err := runTest(prog, 100)
if err != nil { t.Fatal(err) }
expected := (3 * Q16Scale) / 5
if s.Stack[0].Q != expected { t.Fatalf("got %d, expected %d", s.Stack[0].Q, expected) }
}
func TestSaturation(t *testing.T) {
prog := []Instr{
{Op: PushQ16, Arg: AVMClampMax - 1},
{Op: PushQ16, Arg: 2},
{Op: Primitive, Arg: int32(AddSatQ16)},
{Op: Halt},
}
s, err := runTest(prog, 100)
if err != nil { t.Fatal(err) }
if s.Stack[0].Q != AVMClampMax { t.Fatalf("got %d", s.Stack[0].Q) }
}
func TestV6LtQ16(t *testing.T) {
cases := []struct{ a, b int32; exp bool }{
{-5 * Q16Scale, -3 * Q16Scale, true},
{-3 * Q16Scale, -5 * Q16Scale, false},
{5 * Q16Scale, 3 * Q16Scale, false},
{3 * Q16Scale, 5 * Q16Scale, true},
{-1 * Q16Scale, 2 * Q16Scale, true},
}
for _, c := range cases {
prog := []Instr{
{Op: PushQ16, Arg: c.a},
{Op: PushQ16, Arg: c.b},
{Op: Primitive, Arg: int32(LtQ16)},
{Op: Halt},
}
s, err := runTest(prog, 100)
if err != nil { t.Fatal(err) }
if s.Stack[0].Bval != c.exp { t.Fatalf("ltQ16(%d,%d): got %v", c.a, c.b, s.Stack[0]) }
}
}
func TestDivByZero(t *testing.T) {
prog := []Instr{
{Op: PushQ16, Arg: Q16Scale},
{Op: PushQ16, Arg: 0},
{Op: Primitive, Arg: int32(DivSatQ16)},
}
_, err := runTest(prog, 100)
if err == nil { t.Fatal("expected error") }
}
func TestStackOverflow(t *testing.T) {
prog := make([]Instr, AVMMaxStack+1)
for i := range prog { prog[i] = Instr{Op: PushQ16, Arg: 0} }
_, err := runTest(prog, 10000)
if err == nil { t.Fatal("expected overflow") }
}
func TestControlFlow(t *testing.T) {
prog := []Instr{
{Op: PushBool, Arg2: true},
{Op: JumpIf, Arg: 4},
{Op: PushQ16, Arg: 0},
{Op: Halt},
{Op: PushQ16, Arg: Q16Scale},
{Op: Halt},
}
s, err := runTest(prog, 100)
if err != nil { t.Fatal(err) }
if s.Stack[0].Q != Q16Scale { t.Fatalf("got %d", s.Stack[0].Q) }
}
func TestLocals(t *testing.T) {
s := NewState(1)
prog := []Instr{
{Op: PushQ16, Arg: 42 * Q16Scale},
{Op: Store, Arg: 0},
{Op: Load, Arg: 0},
{Op: Halt},
}
result, err := Run(s, prog, 100)
if err != nil { t.Fatal(err) }
if result.Stack[0].Q != 42*Q16Scale { t.Fatalf("got %d", result.Stack[0].Q) }
}