SilverSight/go/avm_test.go
allaun 3c4e039e48 fix(go): type conversion errors in floorDiv/avmClamp
- floorDiv returns int64 instead of int32 to match avmClamp signature
- instr.Arg wrapped in int64() for avmClamp/avmQ0Clamp calls
- Test expected value cast to int32

fix(julia): add Q16_SCALE export to Q16_16 module
2026-06-30 18:10:48 -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 := int32((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) }
}