radiance/pkg/sealevel/sealevel_test.go

154 lines
3.3 KiB
Go

package sealevel
import (
_ "embed"
"encoding/json"
"io/fs"
"os"
"path/filepath"
"strings"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.firedancer.io/radiance/fixtures"
"go.firedancer.io/radiance/pkg/sbpf"
"go.firedancer.io/radiance/pkg/sbpf/loader"
)
func TestExecute_Memo(t *testing.T) {
tx := TxContext{}
opts := tx.newVMOpts(&Params{
Accounts: nil,
Data: []byte("Bla"),
ProgramID: [32]byte{},
})
loader, err := loader.NewLoaderFromBytes(fixtures.Load(t, "sealevel", "MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr.so"))
require.NoError(t, err)
require.NotNil(t, loader)
program, err := loader.Load()
require.NoError(t, err)
require.NotNil(t, program)
require.NoError(t, program.Verify())
interpreter := sbpf.NewInterpreter(program, opts)
require.NotNil(t, interpreter)
err = interpreter.Run()
assert.NoError(t, err)
logs := opts.Context.(*Execution).Log.(*LogRecorder).Logs
assert.Equal(t, logs, []string{
`Program log: Memo (len 3): "Bla"`,
})
}
func TestInterpreter_Noop(t *testing.T) {
// TODO simplify API?
loader, err := loader.NewLoaderFromBytes(fixtures.Load(t, "sbpf", "noop.so"))
require.NoError(t, err)
require.NotNil(t, loader)
program, err := loader.Load()
require.NoError(t, err)
require.NotNil(t, program)
require.NoError(t, program.Verify())
syscalls := sbpf.NewSyscallRegistry()
syscalls.Register("log", SyscallLog)
syscalls.Register("log_64", SyscallLog64)
var log LogRecorder
interpreter := sbpf.NewInterpreter(program, &sbpf.VMOpts{
HeapSize: 32 * 1024,
Input: nil,
MaxCU: 10000,
Syscalls: syscalls,
Context: &Execution{Log: &log},
})
require.NotNil(t, interpreter)
err = interpreter.Run()
require.NoError(t, err)
assert.Equal(t, log.Logs, []string{
"Program log: entrypoint\x00",
"Program log: 0x1, 0x2, 0x3, 0x4, 0x5\n",
})
}
type executeCase struct {
Name string
Program string
Params Params
Logs []string
}
func (e *executeCase) run(t *testing.T) {
ld, err := loader.NewLoaderFromBytes(fixtures.Load(t, e.Program))
require.NoError(t, err)
require.NotNil(t, ld)
program, err := ld.Load()
require.NoError(t, err)
require.NotNil(t, program)
require.NoError(t, program.Verify())
tx := TxContext{}
opts := tx.newVMOpts(&e.Params)
opts.Tracer = testLogger{t}
interpreter := sbpf.NewInterpreter(program, opts)
require.NotNil(t, interpreter)
err = interpreter.Run()
assert.NoError(t, err)
logs := opts.Context.(*Execution).Log.(*LogRecorder).Logs
assert.Equal(t, logs, e.Logs)
}
func TestExecute(t *testing.T) {
// Collect test cases
var cases []executeCase
err := filepath.WalkDir(fixtures.Path(t, "sealevel"), func(path string, entry fs.DirEntry, err error) error {
if !entry.Type().IsRegular() ||
!strings.HasPrefix(filepath.Base(path), "test_") ||
filepath.Ext(path) != ".json" {
return nil
}
buf, err := os.ReadFile(path)
require.NoError(t, err, path)
var _case executeCase
require.NoError(t, json.Unmarshal(buf, &_case), path)
cases = append(cases, _case)
return nil
})
require.NoError(t, err)
for i := range cases {
_case := cases[i]
t.Run(_case.Name, func(t *testing.T) {
t.Parallel()
_case.run(t)
})
}
}
type testLogger struct {
t *testing.T
}
func (t testLogger) Printf(format string, args ...any) {
t.t.Logf(format, args...)
}