go-vise

Constrained Size Output Virtual Machine
Info | Log | Files | Refs | README | LICENSE

commit 9e6ece0959f4650df00b1d621906b1cf7e6b5b71
parent d0187608aa26307f4ee88d9431303e28b855f345
Author: lash <dev@holbrook.no>
Date:   Sun,  2 Apr 2023 09:07:53 +0100

Add testdata generator

Diffstat:
Ago/dev/generate_testdata.go | 21+++++++++++++++++++++
Mgo/engine/engine.go | 5+++--
Mgo/engine/engine_test.go | 34+++++++++++++++++++++++++---------
Mgo/state/state.go | 4++--
Dgo/testdata/bar | 1-
Dgo/testdata/bar.bin | 0
Dgo/testdata/root | 1-
Dgo/testdata/root.bin | 0
Ago/testdata/testdata.go | 118+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mgo/vm/vm.go | 2+-
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)