feat(verify): add the JIT execution substrate and gasm verify subcommand
Assisted-by: Qwen 3.8 Max Preview
This commit is contained in:
@@ -0,0 +1,159 @@
|
||||
// Copyright (c) 2026 Petr Balvín <opensource@petrbalvin.org> (https://petrbalvin.org)
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
package verify
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func loadBasic(t *testing.T) *Kernel {
|
||||
t.Helper()
|
||||
k, err := Load("../testdata/verify/basic_amd64.s")
|
||||
if err != nil {
|
||||
t.Fatalf("Load: %v", err)
|
||||
}
|
||||
t.Cleanup(k.Close)
|
||||
return k
|
||||
}
|
||||
|
||||
func TestJITAdd(t *testing.T) {
|
||||
k := loadBasic(t)
|
||||
|
||||
tests := []struct {
|
||||
a, b, want int64
|
||||
}{
|
||||
{0, 0, 0},
|
||||
{1, 2, 3},
|
||||
{-1, 1, 0},
|
||||
{1 << 62, 1 << 62, -9223372036854775808}, // overflow wraps (MinInt64)
|
||||
{-100, -200, -300},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
args := make([]byte, 24)
|
||||
PutUint64(args, 0, uint64(tt.a))
|
||||
PutUint64(args, 8, uint64(tt.b))
|
||||
|
||||
out, err := k.CallFunc("add", args)
|
||||
if err != nil {
|
||||
t.Fatalf("CallFunc(add, %d, %d): %v", tt.a, tt.b, err)
|
||||
}
|
||||
got := int64(GetUint64(out, 16))
|
||||
if got != tt.want {
|
||||
t.Errorf("add(%d, %d) = %d, want %d", tt.a, tt.b, got, tt.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestJITSum(t *testing.T) {
|
||||
k := loadBasic(t)
|
||||
|
||||
tests := []struct {
|
||||
data []int64
|
||||
want int64
|
||||
}{
|
||||
{nil, 0},
|
||||
{[]int64{1}, 1},
|
||||
{[]int64{1, 2, 3, 4, 5}, 15},
|
||||
{[]int64{-10, 20, -30, 40}, 20},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
args := make([]byte, 32)
|
||||
if len(tt.data) > 0 {
|
||||
PutPtr(args, 0, unsafe.Pointer(&tt.data[0]))
|
||||
}
|
||||
PutUint64(args, 8, uint64(len(tt.data)))
|
||||
PutUint64(args, 16, uint64(cap(tt.data)))
|
||||
|
||||
out, err := k.CallFunc("sum", args)
|
||||
if err != nil {
|
||||
t.Fatalf("CallFunc(sum, %v): %v", tt.data, err)
|
||||
}
|
||||
got := int64(GetUint64(out, 24))
|
||||
if got != tt.want {
|
||||
t.Errorf("sum(%v) = %d, want %d", tt.data, got, tt.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestJITWideCopy(t *testing.T) {
|
||||
k := loadBasic(t)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
n int
|
||||
}{
|
||||
{"empty", 0},
|
||||
{"tiny", 7},
|
||||
{"exact32", 32},
|
||||
{"overlap_range", 48},
|
||||
{"exact64", 64},
|
||||
{"unaligned", 45},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
src := make([]byte, tt.n)
|
||||
for i := range src {
|
||||
src[i] = byte(i * 7)
|
||||
}
|
||||
dst := make([]byte, tt.n)
|
||||
|
||||
args := make([]byte, 48)
|
||||
if tt.n > 0 {
|
||||
PutPtr(args, 0, unsafe.Pointer(&dst[0]))
|
||||
PutPtr(args, 24, unsafe.Pointer(&src[0]))
|
||||
}
|
||||
PutUint64(args, 8, uint64(tt.n)) // dst_len
|
||||
PutUint64(args, 16, uint64(tt.n)) // dst_cap
|
||||
PutUint64(args, 32, uint64(tt.n)) // src_len
|
||||
PutUint64(args, 40, uint64(tt.n)) // src_cap
|
||||
|
||||
_, err := k.CallFunc("wideCopy", args)
|
||||
if err != nil {
|
||||
t.Fatalf("CallFunc(wideCopy): %v", err)
|
||||
}
|
||||
if !bytes.Equal(dst, src) {
|
||||
t.Errorf("wideCopy: dst ≠ src\n got %x\n want %x", dst, src)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestKernelFuncNames(t *testing.T) {
|
||||
k := loadBasic(t)
|
||||
names := k.FuncNames()
|
||||
want := []string{"add", "sum", "wideCopy"}
|
||||
if len(names) != len(want) {
|
||||
t.Fatalf("FuncNames() = %v, want %v", names, want)
|
||||
}
|
||||
for i, n := range names {
|
||||
if n != want[i] {
|
||||
t.Errorf("FuncNames()[%d] = %q, want %q", i, n, want[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestKernelFuncNotFound(t *testing.T) {
|
||||
k := loadBasic(t)
|
||||
_, err := k.CallFunc("nonexistent", make([]byte, 8))
|
||||
if err == nil {
|
||||
t.Fatal("expected error for nonexistent function")
|
||||
}
|
||||
}
|
||||
|
||||
func TestKernelArgTooSmall(t *testing.T) {
|
||||
k := loadBasic(t)
|
||||
_, err := k.CallFunc("add", make([]byte, 8)) // needs 24
|
||||
if err == nil {
|
||||
t.Fatal("expected error for too-small arg block")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMapZeroLength(t *testing.T) {
|
||||
_, err := Map(nil)
|
||||
if err == nil {
|
||||
t.Fatal("expected error for zero-length code")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user