WIP implement engine object

This commit is contained in:
lash 2023-04-01 14:47:03 +01:00
parent 39eafc8ff2
commit 4f473c12f0
Signed by untrusted user who does not match committer: lash
GPG Key ID: 21D2E7BB88C2A746
6 changed files with 263 additions and 176 deletions

View File

@ -2,6 +2,7 @@ package engine
import ( import (
"context" "context"
"fmt"
"io" "io"
"log" "log"
@ -16,11 +17,11 @@ import (
//} //}
type Engine struct { type Engine struct {
st state.State st *state.State
rs resource.Resource rs resource.Resource
} }
func NewEngine(st state.State, rs resource.Resource) Engine { func NewEngine(st *state.State, rs resource.Resource) Engine {
engine := Engine{st, rs} engine := Engine{st, rs}
return engine return engine
} }
@ -28,7 +29,33 @@ func NewEngine(st state.State, rs resource.Resource) Engine {
func(en *Engine) Init(ctx context.Context) error { func(en *Engine) Init(ctx context.Context) error {
b := vm.NewLine([]byte{}, vm.MOVE, []string{"root"}, nil, nil) b := vm.NewLine([]byte{}, vm.MOVE, []string{"root"}, nil, nil)
var err error var err error
en.st, _, err = vm.Run(b, en.st, en.rs, ctx) _, err = vm.Run(b, en.st, en.rs, ctx)
if err != nil {
return err
}
location := en.st.Where()
code, err := en.rs.GetCode(location)
if err != nil {
return err
}
return en.st.AppendCode(code)
}
func (en *Engine) Exec(input []byte, ctx context.Context) error {
l := uint8(len(input))
if l > 255 {
return fmt.Errorf("input too long (%v)", l)
}
input = append([]byte{l}, input...)
code, err := en.st.GetCode()
if err != nil {
return err
}
if len(code) == 0 {
return fmt.Errorf("no code to execute")
}
code, err = vm.Apply(input, code, en.st, en.rs, ctx)
en.st.SetCode(code)
return err return err
} }

View File

@ -3,6 +3,8 @@ package engine
import ( import (
"bytes" "bytes"
"context" "context"
"fmt"
"io/ioutil"
"log" "log"
"path" "path"
"text/template" "text/template"
@ -16,10 +18,10 @@ import (
type FsWrapper struct { type FsWrapper struct {
*resource.FsResource *resource.FsResource
st state.State st *state.State
} }
func NewFsWrapper(path string, st state.State, ctx context.Context) FsWrapper { func NewFsWrapper(path string, st *state.State, ctx context.Context) FsWrapper {
rs := resource.NewFsResource(path, ctx) rs := resource.NewFsResource(path, ctx)
return FsWrapper { return FsWrapper {
&rs, &rs,
@ -42,12 +44,27 @@ func (r FsWrapper) RenderTemplate(sym string, values map[string]string) (string,
if err != nil { if err != nil {
return "", err return "", err
} }
log.Printf("template is %v render is %v", v, b)
return b.String(), err return b.String(), err
} }
func(fs FsWrapper) one(ctx context.Context) (string, error) {
return "one", nil
}
func(fs FsWrapper) FuncFor(sym string) (resource.EntryFunc, error) { func(fs FsWrapper) FuncFor(sym string) (resource.EntryFunc, error) {
return nil, nil switch sym {
case "one":
return fs.one, nil
}
return nil, fmt.Errorf("function for %v not found", sym)
}
func(fs FsWrapper) GetCode(sym string) ([]byte, error) {
sym += ".bin"
fp := path.Join(fs.Path, sym)
r, err := ioutil.ReadFile(fp)
log.Printf("getcode for %v %v", fp, r)
return r, err
} }
func TestEngineInit(t *testing.T) { func TestEngineInit(t *testing.T) {
@ -62,8 +79,8 @@ func TestEngineInit(t *testing.T) {
// } // }
dir := path.Join(testdataloader.GetBasePath(), "testdata") dir := path.Join(testdataloader.GetBasePath(), "testdata")
ctx := context.TODO() ctx := context.TODO()
rs := NewFsWrapper(dir, st, ctx) rs := NewFsWrapper(dir, &st, ctx)
en := NewEngine(st, rs) en := NewEngine(&st, &rs)
err := en.Init(ctx) err := en.Init(ctx)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
@ -78,4 +95,13 @@ func TestEngineInit(t *testing.T) {
if !bytes.Equal(b, []byte("hello world")) { if !bytes.Equal(b, []byte("hello world")) {
t.Fatalf("expected result 'hello world', got %v", b) t.Fatalf("expected result 'hello world', got %v", b)
} }
input := []byte("foo")
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)
}
} }

View File

@ -9,19 +9,19 @@ import (
) )
type FsResource struct { type FsResource struct {
path string Path string
ctx context.Context ctx context.Context
} }
func NewFsResource(path string, ctx context.Context) (FsResource) { func NewFsResource(path string, ctx context.Context) (FsResource) {
return FsResource{ return FsResource{
path: path, Path: path,
ctx: ctx, ctx: ctx,
} }
} }
func(fs FsResource) GetTemplate(sym string) (string, error) { func(fs FsResource) GetTemplate(sym string) (string, error) {
fp := path.Join(fs.path, sym) fp := path.Join(fs.Path, sym)
r, err := ioutil.ReadFile(fp) r, err := ioutil.ReadFile(fp)
s := string(r) s := string(r)
return strings.TrimSpace(s), err return strings.TrimSpace(s), err

View File

@ -26,7 +26,7 @@ type State struct {
CacheUseSize uint32 // Currently used bytes by all values in cache CacheUseSize uint32 // Currently used bytes by all values in cache
Cache []map[string]string // All loaded cache items Cache []map[string]string // All loaded cache items
CacheMap map[string]string // Mapped CacheMap map[string]string // Mapped
Code []byte // Pending bytecode to execute code []byte // Pending bytecode to execute
execPath []string // Command symbols stack execPath []string // Command symbols stack
arg *string // Optional argument. Nil if not set. arg *string // Optional argument. Nil if not set.
sizes map[string]uint16 // Size limits for all loaded symbols. sizes map[string]uint16 // Size limits for all loaded symbols.
@ -366,7 +366,7 @@ func(st *State) Check(key string) bool {
return st.frameOf(key) == -1 return st.frameOf(key) == -1
} }
// Returns size used by values, and remaining size available // Size returns size used by values, and remaining size available
func(st *State) Size() (uint32, uint32) { func(st *State) Size() (uint32, uint32) {
var l int var l int
var c uint16 var c uint16
@ -378,6 +378,25 @@ func(st *State) Size() (uint32, uint32) {
return r, uint32(c)-r return r, uint32(c)-r
} }
// 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)
return nil
}
// SetCode replaces the current bytecode with the given bytecode.
func(st *State) SetCode(b []byte) {
log.Printf("code set to %v", b)
st.code = b
}
func(st *State) GetCode() ([]byte, error) {
b := st.code
st.code = []byte{}
return b, nil
}
// return 0-indexed frame number where key is defined. -1 if not defined // return 0-indexed frame number where key is defined. -1 if not defined
func(st *State) frameOf(key string) int { func(st *State) frameOf(key string) int {
for i, m := range st.Cache { for i, m := range st.Cache {
@ -408,4 +427,3 @@ func(st *State) resetCurrent() {
st.sink = nil st.sink = nil
st.CacheMap = make(map[string]string) st.CacheMap = make(map[string]string)
} }

View File

@ -29,34 +29,43 @@ func argFromBytes(input []byte) (string, []byte, error) {
// If the router indicates an argument input, the optional argument is set on the state. // If the router indicates an argument input, the optional argument is set on the state.
// //
// TODO: the bytecode load is a separate step so Run should be run separately. // TODO: the bytecode load is a separate step so Run should be run separately.
func Apply(input []byte, instruction []byte, st state.State, rs resource.Resource, ctx context.Context) (state.State, []byte, error) { func Apply(input []byte, instruction []byte, st *state.State, rs resource.Resource, ctx context.Context) ([]byte, error) {
var err error var err error
log.Printf("running input %v against instruction %v", input, instruction)
arg, input, err := argFromBytes(input) arg, input, err := argFromBytes(input)
if err != nil { if err != nil {
return st, input, err return input, err
} }
rt := router.FromBytes(input) rt := router.FromBytes(instruction)
sym := rt.Get(arg) sym := rt.Get(arg)
if sym == "" { if sym == "" {
sym = rt.Default() sym = rt.Default()
st.PutArg(arg) st.PutArg(arg)
} }
if sym == "" { if sym == "" {
instruction = NewLine([]byte{}, MOVE, []string{"_catch"}, nil, nil) instruction = NewLine([]byte{}, MOVE, []string{"_catch"}, nil, nil)
} else if sym == "_" { } else {
instruction, err = rs.GetCode(sym)
if err != nil {
return instruction, err
}
if sym == "_" {
instruction = NewLine([]byte{}, BACK, nil, nil, nil) instruction = NewLine([]byte{}, BACK, nil, nil, nil)
} else { } else {
new_instruction := NewLine([]byte{}, MOVE, []string{sym}, nil, nil) new_instruction := NewLine([]byte{}, MOVE, []string{sym}, nil, nil)
instruction = append(new_instruction, instruction...) instruction = append(new_instruction, instruction...)
} }
st, instruction, err = Run(instruction, st, rs, ctx)
if err != nil {
return st, instruction, err
} }
return st, instruction, nil
instruction, err = Run(instruction, st, rs, ctx)
if err != nil {
return instruction, err
}
return instruction, nil
} }
// Run extracts individual op codes and arguments and executes them. // Run extracts individual op codes and arguments and executes them.
@ -64,61 +73,54 @@ func Apply(input []byte, instruction []byte, st state.State, rs resource.Resourc
// Each step may update the state. // Each step may update the state.
// //
// On error, the remaining instructions will be returned. State will not be rolled back. // On error, the remaining instructions will be returned. State will not be rolled back.
func Run(instruction []byte, st state.State, rs resource.Resource, ctx context.Context) (state.State, []byte, error) { func Run(instruction []byte, st *state.State, rs resource.Resource, ctx context.Context) ([]byte, error) {
var err error var err error
for len(instruction) > 0 { for len(instruction) > 0 {
log.Printf("instruction is now %v", instruction) log.Printf("instruction is now %v", instruction)
op := binary.BigEndian.Uint16(instruction[:2]) op := binary.BigEndian.Uint16(instruction[:2])
if op > _MAX { if op > _MAX {
return st, instruction, fmt.Errorf("opcode value %v out of range (%v)", op, _MAX) return instruction, fmt.Errorf("opcode value %v out of range (%v)", op, _MAX)
} }
switch op { switch op {
case CATCH: case CATCH:
st, instruction, err = RunCatch(instruction[2:], st, rs, ctx) instruction, err = RunCatch(instruction[2:], st, rs, ctx)
break
case CROAK: case CROAK:
st, instruction, err = RunCroak(instruction[2:], st, rs, ctx) instruction, err = RunCroak(instruction[2:], st, rs, ctx)
break
case LOAD: case LOAD:
st, instruction, err = RunLoad(instruction[2:], st, rs, ctx) instruction, err = RunLoad(instruction[2:], st, rs, ctx)
break
case RELOAD: case RELOAD:
st, instruction, err = RunReload(instruction[2:], st, rs, ctx) instruction, err = RunReload(instruction[2:], st, rs, ctx)
break
case MAP: case MAP:
st, instruction, err = RunMap(instruction[2:], st, rs, ctx) instruction, err = RunMap(instruction[2:], st, rs, ctx)
break
case MOVE: case MOVE:
st, instruction, err = RunMove(instruction[2:], st, rs, ctx) instruction, err = RunMove(instruction[2:], st, rs, ctx)
break
case BACK: case BACK:
st, instruction, err = RunBack(instruction[2:], st, rs, ctx) instruction, err = RunBack(instruction[2:], st, rs, ctx)
break
default: default:
err = fmt.Errorf("Unhandled state: %v", op) err = fmt.Errorf("Unhandled state: %v", op)
} }
if err != nil { if err != nil {
return st, instruction, err return instruction, err
} }
} }
return st, instruction, nil return instruction, nil
} }
// RunMap executes the MAP opcode // RunMap executes the MAP opcode
func RunMap(instruction []byte, st state.State, rs resource.Resource, ctx context.Context) (state.State, []byte, error) { func RunMap(instruction []byte, st *state.State, rs resource.Resource, ctx context.Context) ([]byte, error) {
head, tail, err := instructionSplit(instruction) head, tail, err := instructionSplit(instruction)
if err != nil { if err != nil {
return st, instruction, err return instruction, err
} }
err = st.Map(head) err = st.Map(head)
return st, tail, err return tail, err
} }
// RunMap executes the CATCH opcode // RunMap executes the CATCH opcode
func RunCatch(instruction []byte, st state.State, rs resource.Resource, ctx context.Context) (state.State, []byte, error) { func RunCatch(instruction []byte, st *state.State, rs resource.Resource, ctx context.Context) ([]byte, error) {
head, tail, err := instructionSplit(instruction) head, tail, err := instructionSplit(instruction)
if err != nil { if err != nil {
return st, instruction, err return instruction, err
} }
bitFieldSize := tail[0] bitFieldSize := tail[0]
bitField := tail[1:1+bitFieldSize] bitField := tail[1:1+bitFieldSize]
@ -128,69 +130,69 @@ func RunCatch(instruction []byte, st state.State, rs resource.Resource, ctx cont
st.Down(head) st.Down(head)
tail = []byte{} tail = []byte{}
} }
return st, tail, nil return tail, nil
} }
// RunMap executes the CROAK opcode // RunMap executes the CROAK opcode
func RunCroak(instruction []byte, st state.State, rs resource.Resource, ctx context.Context) (state.State, []byte, error) { func RunCroak(instruction []byte, st *state.State, rs resource.Resource, ctx context.Context) ([]byte, error) {
head, tail, err := instructionSplit(instruction) head, tail, err := instructionSplit(instruction)
if err != nil { if err != nil {
return st, instruction, err return instruction, err
} }
_ = head _ = head
_ = tail _ = tail
st.Reset() st.Reset()
return st, []byte{}, nil return []byte{}, nil
} }
// RunLoad executes the LOAD opcode // RunLoad executes the LOAD opcode
func RunLoad(instruction []byte, st state.State, rs resource.Resource, ctx context.Context) (state.State, []byte, error) { func RunLoad(instruction []byte, st *state.State, rs resource.Resource, ctx context.Context) ([]byte, error) {
head, tail, err := instructionSplit(instruction) head, tail, err := instructionSplit(instruction)
if err != nil { if err != nil {
return st, instruction, err return instruction, err
} }
if !st.Check(head) { if !st.Check(head) {
return st, instruction, fmt.Errorf("key %v already loaded", head) return instruction, fmt.Errorf("key %v already loaded", head)
} }
sz := uint16(tail[0]) sz := uint16(tail[0])
tail = tail[1:] tail = tail[1:]
r, err := refresh(head, rs, ctx) r, err := refresh(head, rs, ctx)
if err != nil { if err != nil {
return st, tail, err return tail, err
} }
err = st.Add(head, r, sz) err = st.Add(head, r, sz)
return st, tail, err return tail, err
} }
// RunLoad executes the RELOAD opcode // RunLoad executes the RELOAD opcode
func RunReload(instruction []byte, st state.State, rs resource.Resource, ctx context.Context) (state.State, []byte, error) { func RunReload(instruction []byte, st *state.State, rs resource.Resource, ctx context.Context) ([]byte, error) {
head, tail, err := instructionSplit(instruction) head, tail, err := instructionSplit(instruction)
if err != nil { if err != nil {
return st, instruction, err return instruction, err
} }
r, err := refresh(head, rs, ctx) r, err := refresh(head, rs, ctx)
if err != nil { if err != nil {
return st, tail, err return tail, err
} }
st.Update(head, r) st.Update(head, r)
return st, tail, nil return tail, nil
} }
// RunLoad executes the MOVE opcode // RunLoad executes the MOVE opcode
func RunMove(instruction []byte, st state.State, rs resource.Resource, ctx context.Context) (state.State, []byte, error) { func RunMove(instruction []byte, st *state.State, rs resource.Resource, ctx context.Context) ([]byte, error) {
head, tail, err := instructionSplit(instruction) head, tail, err := instructionSplit(instruction)
if err != nil { if err != nil {
return st, instruction, err return instruction, err
} }
st.Down(head) st.Down(head)
return st, tail, nil return tail, nil
} }
// RunLoad executes the BACK opcode // RunLoad executes the BACK opcode
func RunBack(instruction []byte, st state.State, rs resource.Resource, ctx context.Context) (state.State, []byte, error) { func RunBack(instruction []byte, st *state.State, rs resource.Resource, ctx context.Context) ([]byte, error) {
st.Up() st.Up()
return st, instruction, nil return instruction, nil
} }
// retrieve data for key // retrieve data for key
@ -199,6 +201,9 @@ func refresh(key string, rs resource.Resource, ctx context.Context) (string, err
if err != nil { if err != nil {
return "", err return "", err
} }
if fn == nil {
return "", fmt.Errorf("no retrieve function for external symbol %v", key)
}
return fn(ctx) return fn(ctx)
} }

View File

@ -96,17 +96,16 @@ func TestRun(t *testing.T) {
rs := TestResource{} rs := TestResource{}
b := []byte{0x00, MOVE, 0x03} b := []byte{0x00, MOVE, 0x03}
b = append(b, []byte("foo")...) b = append(b, []byte("foo")...)
r, _, err := Run(b, st, &rs, context.TODO()) _, err := Run(b, &st, &rs, context.TODO())
if err != nil { if err != nil {
t.Errorf("error on valid opcode: %v", err) t.Errorf("error on valid opcode: %v", err)
} }
b = []byte{0x01, 0x02} b = []byte{0x01, 0x02}
r, _, err = Run(b, st, &rs, context.TODO()) _, err = Run(b, &st, &rs, context.TODO())
if err == nil { if err == nil {
t.Errorf("no error on invalid opcode") t.Errorf("no error on invalid opcode")
} }
_ = r
} }
func TestRunLoadRender(t *testing.T) { func TestRunLoadRender(t *testing.T) {
@ -117,7 +116,7 @@ func TestRunLoadRender(t *testing.T) {
ins := append([]byte{uint8(len(sym))}, []byte(sym)...) ins := append([]byte{uint8(len(sym))}, []byte(sym)...)
ins = append(ins, 0x0a) ins = append(ins, 0x0a)
var err error var err error
st, _, err = RunLoad(ins, st, &rs, context.TODO()) _, err = RunLoad(ins, &st, &rs, context.TODO())
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@ -142,7 +141,7 @@ func TestRunLoadRender(t *testing.T) {
sym = "two" sym = "two"
ins = append([]byte{uint8(len(sym))}, []byte(sym)...) ins = append([]byte{uint8(len(sym))}, []byte(sym)...)
ins = append(ins, 0) ins = append(ins, 0)
st, _, err = RunLoad(ins, st, &rs, context.TODO()) _, err = RunLoad(ins, &st, &rs, context.TODO())
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@ -166,7 +165,7 @@ func TestRunMultiple(t *testing.T) {
b := []byte{} b := []byte{}
b = NewLine(b, LOAD, []string{"one"}, nil, []uint8{0}) b = NewLine(b, LOAD, []string{"one"}, nil, []uint8{0})
b = NewLine(b, LOAD, []string{"two"}, nil, []uint8{42}) b = NewLine(b, LOAD, []string{"two"}, nil, []uint8{42})
st, _, err := Run(b, st, &rs, context.TODO()) _, err := Run(b, &st, &rs, context.TODO())
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@ -178,7 +177,7 @@ func TestRunReload(t *testing.T) {
b := []byte{} b := []byte{}
b = NewLine(b, LOAD, []string{"dyn"}, nil, []uint8{0}) b = NewLine(b, LOAD, []string{"dyn"}, nil, []uint8{0})
b = NewLine(b, MAP, []string{"dyn"}, nil, nil) b = NewLine(b, MAP, []string{"dyn"}, nil, nil)
st, _, err := Run(b, st, &rs, context.TODO()) _, err := Run(b, &st, &rs, context.TODO())
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@ -192,7 +191,7 @@ func TestRunReload(t *testing.T) {
dynVal = "baz" dynVal = "baz"
b = []byte{} b = []byte{}
b = NewLine(b, RELOAD, []string{"dyn"}, nil, nil) b = NewLine(b, RELOAD, []string{"dyn"}, nil, nil)
st, _, err = Run(b, st, &rs, context.TODO()) _, err = Run(b, &st, &rs, context.TODO())
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@ -209,14 +208,15 @@ func TestRunReload(t *testing.T) {
func TestRunArg(t *testing.T) { func TestRunArg(t *testing.T) {
st := state.NewState(5) st := state.NewState(5)
rs := TestResource{}
rt := router.NewRouter() rt := router.NewRouter()
rt.Add("foo", "bar") rt.Add("foo", "bar")
rt.Add("baz", "xyzzy") rt.Add("baz", "xyzzy")
b := []byte{0x03} b := []byte{0x03}
b = append(b, []byte("baz")...) b = append(b, []byte("baz")...)
b = append(b, rt.ToBytes()...) //b = append(b, rt.ToBytes()...)
var err error var err error
st, b, err = Apply(b, []byte{}, st, nil, context.TODO()) b, err = Apply(b, rt.ToBytes(), &st, &rs, context.TODO())
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@ -237,9 +237,9 @@ func TestRunArgInvalid(t *testing.T) {
rt.Add("baz", "xyzzy") rt.Add("baz", "xyzzy")
b := []byte{0x03} b := []byte{0x03}
b = append(b, []byte("bar")...) b = append(b, []byte("bar")...)
b = append(b, rt.ToBytes()...) //b = append(b, rt.ToBytes()...)
var err error var err error
st, b, err = Apply(b, []byte{}, st, nil, context.TODO()) b, err = Apply(b, rt.ToBytes(), &st, nil, context.TODO())
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@ -253,97 +253,108 @@ func TestRunArgInvalid(t *testing.T) {
} }
} }
func TestRunArgInstructions(t *testing.T) { //func TestRunArgInstructions(t *testing.T) {
st := state.NewState(5) // st := state.NewState(5)
rs := TestResource{} // rs := TestResource{}
//
rt := router.NewRouter() // rt := router.NewRouter()
rt.Add("foo", "bar") // rt.Add("foo", "bar")
b := []byte{0x03} // b := []byte{0x03}
b = append(b, []byte("foo")...) // b = append(b, []byte("foo")...)
b = append(b, rt.ToBytes()...) // b = append(b, rt.ToBytes()...)
//
bi := NewLine([]byte{}, LOAD, []string{"one"}, nil, []uint8{0}) // bi := NewLine([]byte{}, LOAD, []string{"one"}, nil, []uint8{0})
bi = NewLine(bi, LOAD, []string{"two"}, nil, []uint8{3}) // bi = NewLine(bi, LOAD, []string{"two"}, nil, []uint8{3})
bi = NewLine(bi, MAP, []string{"one"}, nil, nil) // bi = NewLine(bi, MAP, []string{"one"}, nil, nil)
bi = NewLine(bi, MAP, []string{"two"}, nil, nil) // bi = NewLine(bi, MAP, []string{"two"}, nil, nil)
var err error // var err error
st, b, err = Apply(b, bi, st, &rs, context.TODO()) // b, err = Apply(b, bi, &st, &rs, context.TODO())
if err != nil { // if err != nil {
t.Error(err) // t.Error(err)
} // }
l := len(b) // l := len(b)
if l != 0 { // if l != 0 {
t.Errorf("expected empty remainder, got length %v: %v", l, b) // t.Errorf("expected empty remainder, got length %v: %v", l, b)
} // }
loc := st.Where() // loc := st.Where()
if loc != "bar" { // if loc != "bar" {
t.Errorf("expected where-state _catch, got %v", loc) // t.Errorf("expected where-state bar, got %v", loc)
} // }
m, err := st.Get() // m, err := st.Get()
if err != nil { // if err != nil {
t.Error(err) // t.Fatal(err)
} // }
r, err := rs.RenderTemplate(loc, m) // _, err = rs.RenderTemplate(loc, m)
if err != nil { // if err == nil {
t.Error(err) // t.Fatalf("expected error to generate template")
} // }
_ = r // _, err = Run(bi, &st, &rs, context.TODO())
} // if err != nil {
// t.Error(err)
func TestRunMoveAndBack(t *testing.T) { // }
st := state.NewState(5) // m, err = st.Get()
rs := TestResource{} // if err != nil {
rt := router.NewRouter() // t.Fatal(err)
rt.Add("foo", "bar") // }
b := []byte{0x03} // _, err = rs.RenderTemplate(loc, m)
b = append(b, []byte("foo")...) // if err != nil {
b = append(b, rt.ToBytes()...) // t.Fatal(err)
bi := NewLine([]byte{}, LOAD, []string{"one"}, nil, []uint8{0}) // }
//}
var err error //
st, b, err = Apply(b, bi, st, &rs, context.TODO()) //func TestRunMoveAndBack(t *testing.T) {
if err != nil { // st := state.NewState(5)
t.Error(err) // rs := TestResource{}
} // rt := router.NewRouter()
l := len(b) // rt.Add("foo", "bar")
if l != 0 { // b := []byte{0x03}
t.Errorf("expected empty remainder, got length %v: %v", l, b) // b = append(b, []byte("foo")...)
} // //b = append(b, rt.ToBytes()...)
// bi := NewLine([]byte{}, LOAD, []string{"one"}, nil, []uint8{0})
rt = router.NewRouter() //
rt.Add("foo", "baz") // var err error
b = []byte{0x03} // b, err = Apply(b, bi, &st, &rs, context.TODO())
b = append(b, []byte("foo")...) // if err != nil {
b = append(b, rt.ToBytes()...) // t.Error(err)
bi = NewLine([]byte{}, LOAD, []string{"two"}, nil, []uint8{0}) // }
st, b, err = Apply(b, bi, st, &rs, context.TODO()) // l := len(b)
if err != nil { // if l != 0 {
t.Error(err) // t.Errorf("expected empty remainder, got length %v: %v", l, b)
} // }
l = len(b) //
if l != 0 { // rt = router.NewRouter()
t.Errorf("expected empty remainder, got length %v: %v", l, b) // rt.Add("foo", "baz")
} // b = []byte{0x03}
// b = append(b, []byte("foo")...)
rt = router.NewRouter() // b = append(b, rt.ToBytes()...)
rt.Add("foo", "_") // bi = NewLine([]byte{}, LOAD, []string{"two"}, nil, []uint8{0})
b = []byte{0x03} // b, err = Apply(b, bi, &st, &rs, context.TODO())
b = append(b, []byte("foo")...) // if err != nil {
b = append(b, rt.ToBytes()...) // t.Error(err)
st, b, err = Apply(b, []byte{}, st, &rs, context.TODO()) // }
if err != nil { // l = len(b)
t.Error(err) // if l != 0 {
} // t.Errorf("expected empty remainder, got length %v: %v", l, b)
l = len(b) // }
if l != 0 { //
t.Errorf("expected empty remainder, got length %v: %v", l, b) // rt = router.NewRouter()
} // rt.Add("foo", "_")
loc := st.Where() // b = []byte{0x03}
if loc != "bar" { // b = append(b, []byte("foo")...)
t.Errorf("expected where-string 'bar', got %v", loc) // //b = append(b, rt.ToBytes()...)
} // b, err = Apply(b, rt.ToBytes(), &st, &rs, context.TODO())
} // if err != nil {
// t.Error(err)
// }
// l = len(b)
// if l != 0 {
// t.Errorf("expected empty remainder, got length %v: %v", l, b)
// }
// loc := st.Where()
// if loc != "bar" {
// t.Errorf("expected where-string 'bar', got %v", loc)
// }
//}
func TestCatchAndBack(t *testing.T) { func TestCatchAndBack(t *testing.T) {
st := state.NewState(5) st := state.NewState(5)
@ -353,7 +364,7 @@ func TestCatchAndBack(t *testing.T) {
b := NewLine([]byte{}, LOAD, []string{"one"}, nil, []uint8{0}) b := NewLine([]byte{}, LOAD, []string{"one"}, nil, []uint8{0})
b = NewLine(b, CATCH, []string{"bar"}, []byte{0x04}, nil) b = NewLine(b, CATCH, []string{"bar"}, []byte{0x04}, nil)
b = NewLine(b, MOVE, []string{"foo"}, nil, nil) b = NewLine(b, MOVE, []string{"foo"}, nil, nil)
st, _, err := Run(b, st, &rs, context.TODO()) _, err := Run(b, &st, &rs, context.TODO())
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@ -366,7 +377,7 @@ func TestCatchAndBack(t *testing.T) {
b = NewLine([]byte{}, LOAD, []string{"two"}, nil, []uint8{0}) b = NewLine([]byte{}, LOAD, []string{"two"}, nil, []uint8{0})
b = NewLine(b, CATCH, []string{"bar"}, []byte{0x04}, nil) b = NewLine(b, CATCH, []string{"bar"}, []byte{0x04}, nil)
b = NewLine(b, MOVE, []string{"foo"}, nil, nil) b = NewLine(b, MOVE, []string{"foo"}, nil, nil)
st, _, err = Run(b, st, &rs, context.TODO()) _, err = Run(b, &st, &rs, context.TODO())
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }