commit 9e6ece0959f4650df00b1d621906b1cf7e6b5b71
parent d0187608aa26307f4ee88d9431303e28b855f345
Author: lash <dev@holbrook.no>
Date: Sun, 2 Apr 2023 09:07:53 +0100
Add testdata generator
Diffstat:
10 files changed, 170 insertions(+), 16 deletions(-)
diff --git a/go/dev/generate_testdata.go b/go/dev/generate_testdata.go
@@ -0,0 +1,21 @@
+package main
+
+import (
+ "fmt"
+ "os"
+
+ "git.defalsify.org/festive/testdata"
+)
+
+func main() {
+ var err error
+ if len(os.Args) > 1 {
+ err = testdata.GenerateTo(os.Args[1])
+ } else {
+ _, err = testdata.Generate()
+ }
+ if err != nil {
+ os.Exit(1)
+ }
+ fmt.Println(testdata.DataDir)
+}
diff --git a/go/engine/engine.go b/go/engine/engine.go
@@ -31,8 +31,8 @@ func NewEngine(st *state.State, rs resource.Resource) Engine {
// Init must be explicitly called before using the Engine instance.
//
// It makes sure bootstrapping code has been executed, and that the exposed bytecode is ready for user input.
-func(en *Engine) Init(ctx context.Context) error {
- b := vm.NewLine([]byte{}, vm.MOVE, []string{"root"}, nil, nil)
+func(en *Engine) Init(sym string, ctx context.Context) error {
+ b := vm.NewLine([]byte{}, vm.MOVE, []string{sym}, nil, nil)
var err error
_, err = vm.Run(b, en.st, en.rs, ctx)
if err != nil {
@@ -65,6 +65,7 @@ func (en *Engine) Exec(input []byte, ctx context.Context) error {
if err != nil {
return err
}
+ log.Printf("new execution with input 0x%x (%v)", input, len(input))
code, err := en.st.GetCode()
if err != nil {
return err
diff --git a/go/engine/engine_test.go b/go/engine/engine_test.go
@@ -9,10 +9,14 @@ import (
"text/template"
"testing"
- testdataloader "github.com/peteole/testdata-loader"
-
- "git.defalsify.org/festive/state"
"git.defalsify.org/festive/resource"
+ "git.defalsify.org/festive/state"
+ "git.defalsify.org/festive/testdata"
+)
+
+var (
+ dataGenerated bool = false
+ dataDir string = testdata.DataDir
)
type FsWrapper struct {
@@ -65,13 +69,24 @@ func(fs FsWrapper) GetCode(sym string) ([]byte, error) {
return r, err
}
+func generateTestData(t *testing.T) {
+ if dataGenerated {
+ return
+ }
+ var err error
+ dataDir, err = testdata.Generate()
+ if err != nil {
+ t.Fatal(err)
+ }
+}
+
func TestEngineInit(t *testing.T) {
st := state.NewState(17).WithCacheSize(1024)
- dir := path.Join(testdataloader.GetBasePath(), "testdata")
+ generateTestData(t)
ctx := context.TODO()
- rs := NewFsWrapper(dir, &st, ctx)
+ rs := NewFsWrapper(dataDir, &st, ctx)
en := NewEngine(&st, &rs)
- err := en.Init(ctx)
+ err := en.Init("root", ctx)
if err != nil {
t.Fatal(err)
}
@@ -85,13 +100,14 @@ func TestEngineInit(t *testing.T) {
if !bytes.Equal(b, []byte("hello world")) {
t.Fatalf("expected result 'hello world', got %v", b)
}
- input := []byte("ooo")
+
+ input := []byte("1")
err = en.Exec(input, ctx)
if err != nil {
t.Fatal(err)
}
r := st.Where()
- if r != "bar" {
- t.Fatalf("expected where-string 'bar', got %v", r)
+ if r != "foo" {
+ t.Fatalf("expected where-string 'foo', got %v", r)
}
}
diff --git a/go/state/state.go b/go/state/state.go
@@ -363,13 +363,13 @@ func(st *State) Size() (uint32, uint32) {
// Appendcode adds the given bytecode to the end of the existing code.
func(st *State) AppendCode(b []byte) error {
st.code = append(st.code, b...)
- log.Printf("code changed to %v", b)
+ log.Printf("code changed to 0x%x", b)
return nil
}
// SetCode replaces the current bytecode with the given bytecode.
func(st *State) SetCode(b []byte) {
- log.Printf("code set to %v", b)
+ log.Printf("code set to 0x%x", b)
st.code = b
}
diff --git a/go/testdata/bar b/go/testdata/bar
@@ -1 +0,0 @@
-i am in bar
diff --git a/go/testdata/bar.bin b/go/testdata/bar.bin
Binary files differ.
diff --git a/go/testdata/root b/go/testdata/root
@@ -1 +0,0 @@
-hello world
diff --git a/go/testdata/root.bin b/go/testdata/root.bin
Binary files differ.
diff --git a/go/testdata/testdata.go b/go/testdata/testdata.go
@@ -0,0 +1,118 @@
+package testdata
+
+import (
+ "fmt"
+ "io/ioutil"
+ "os"
+ "path"
+
+ testdataloader "github.com/peteole/testdata-loader"
+
+ "git.defalsify.org/festive/vm"
+)
+
+type genFunc func() error
+
+var (
+ BaseDir = testdataloader.GetBasePath()
+ DataDir = ""
+ dirLock = false
+)
+
+func out(sym string, b []byte, tpl string) error {
+ fp := path.Join(DataDir, sym)
+ err := ioutil.WriteFile(fp, []byte(tpl), 0644)
+ if err != nil {
+ return err
+ }
+
+ fb := sym + ".bin"
+ fp = path.Join(DataDir, fb)
+ err = ioutil.WriteFile(fp, b, 0644)
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
+func root() error {
+ b := []byte{}
+ b = vm.NewLine(b, vm.INCMP, []string{"1", "foo"}, nil, nil)
+ b = vm.NewLine(b, vm.INCMP, []string{"2", "bar"}, nil, nil)
+
+ tpl := "hello world"
+
+ return out("root", b, tpl)
+}
+
+func foo() error {
+ b := []byte{}
+ b = vm.NewLine(b, vm.LOAD, []string{"inky"}, []byte{20}, nil)
+ b = vm.NewLine(b, vm.HALT, nil, nil, nil)
+ b = vm.NewLine(b, vm.INCMP, []string{"0", "_back"}, nil, nil)
+ b = vm.NewLine(b, vm.INCMP, []string{"1", "baz"}, nil, nil)
+ b = vm.NewLine(b, vm.CATCH, []string{"_catch"}, []byte{1}, []uint8{1})
+
+ tpl := `this is in foo
+
+it has more lines`
+
+ return out("foo", b, tpl)
+}
+
+func bar() error {
+ b := []byte{}
+ b = vm.NewLine(b, vm.LOAD, []string{"pinky"}, []byte{0}, nil)
+ b = vm.NewLine(b, vm.HALT, nil, nil, nil)
+ b = vm.NewLine(b, vm.INCMP, []string{"0", "_home"}, nil, nil)
+
+ tpl := "this is bar - an end node"
+
+ return out("bar", b, tpl)
+}
+
+func baz() error {
+ b := []byte{}
+ b = vm.NewLine(b, vm.MAP, []string{"inky"}, nil, nil)
+ b = vm.NewLine(b, vm.HALT, nil, nil, nil)
+
+ tpl := "this is baz which uses the var {{.inky}} in the template."
+
+ return out("baz", b, tpl)
+}
+
+func generate() error {
+ err := os.MkdirAll(DataDir, 0755)
+ if err != nil {
+ return err
+ }
+
+ fns := []genFunc{root, foo, bar, baz}
+ for _, fn := range fns {
+ err = fn()
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func Generate() (string, error) {
+ dir, err := ioutil.TempDir("", "festive_testdata_")
+ if err != nil {
+ return "", err
+ }
+ DataDir = dir
+ dirLock = true
+ err = generate()
+ return dir, err
+}
+
+func GenerateTo(dir string) error {
+ if dirLock {
+ return fmt.Errorf("directory already overridden")
+ }
+ DataDir = dir
+ dirLock = true
+ return generate()
+}
diff --git a/go/vm/vm.go b/go/vm/vm.go
@@ -29,7 +29,7 @@ func argFromBytes(input []byte) (string, []byte, error) {
func Run(instruction []byte, st *state.State, rs resource.Resource, ctx context.Context) ([]byte, error) {
var err error
for len(instruction) > 0 {
- log.Printf("instruction is now %v", instruction)
+ log.Printf("instruction is now 0x%x", instruction)
op := binary.BigEndian.Uint16(instruction[:2])
if op > _MAX {
return instruction, fmt.Errorf("opcode value %v out of range (%v)", op, _MAX)