WIP implement engine object
This commit is contained in:
parent
39eafc8ff2
commit
4f473c12f0
@ -2,6 +2,7 @@ package engine
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
|
||||
@ -16,11 +17,11 @@ import (
|
||||
//}
|
||||
|
||||
type Engine struct {
|
||||
st state.State
|
||||
st *state.State
|
||||
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}
|
||||
return engine
|
||||
}
|
||||
@ -28,7 +29,33 @@ func NewEngine(st state.State, rs resource.Resource) Engine {
|
||||
func(en *Engine) Init(ctx context.Context) error {
|
||||
b := vm.NewLine([]byte{}, vm.MOVE, []string{"root"}, nil, nil)
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,8 @@ package engine
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"path"
|
||||
"text/template"
|
||||
@ -16,10 +18,10 @@ import (
|
||||
|
||||
type FsWrapper struct {
|
||||
*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)
|
||||
return FsWrapper {
|
||||
&rs,
|
||||
@ -42,12 +44,27 @@ func (r FsWrapper) RenderTemplate(sym string, values map[string]string) (string,
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
log.Printf("template is %v render is %v", v, b)
|
||||
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) {
|
||||
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) {
|
||||
@ -62,8 +79,8 @@ func TestEngineInit(t *testing.T) {
|
||||
// }
|
||||
dir := path.Join(testdataloader.GetBasePath(), "testdata")
|
||||
ctx := context.TODO()
|
||||
rs := NewFsWrapper(dir, st, ctx)
|
||||
en := NewEngine(st, rs)
|
||||
rs := NewFsWrapper(dir, &st, ctx)
|
||||
en := NewEngine(&st, &rs)
|
||||
err := en.Init(ctx)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@ -78,4 +95,13 @@ func TestEngineInit(t *testing.T) {
|
||||
if !bytes.Equal(b, []byte("hello world")) {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
@ -9,19 +9,19 @@ import (
|
||||
)
|
||||
|
||||
type FsResource struct {
|
||||
path string
|
||||
Path string
|
||||
ctx context.Context
|
||||
}
|
||||
|
||||
func NewFsResource(path string, ctx context.Context) (FsResource) {
|
||||
return FsResource{
|
||||
path: path,
|
||||
Path: path,
|
||||
ctx: ctx,
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
s := string(r)
|
||||
return strings.TrimSpace(s), err
|
||||
|
@ -26,7 +26,7 @@ type State struct {
|
||||
CacheUseSize uint32 // Currently used bytes by all values in cache
|
||||
Cache []map[string]string // All loaded cache items
|
||||
CacheMap map[string]string // Mapped
|
||||
Code []byte // Pending bytecode to execute
|
||||
code []byte // Pending bytecode to execute
|
||||
execPath []string // Command symbols stack
|
||||
arg *string // Optional argument. Nil if not set.
|
||||
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
|
||||
}
|
||||
|
||||
// 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) {
|
||||
var l int
|
||||
var c uint16
|
||||
@ -378,6 +378,25 @@ func(st *State) Size() (uint32, uint32) {
|
||||
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
|
||||
func(st *State) frameOf(key string) int {
|
||||
for i, m := range st.Cache {
|
||||
@ -408,4 +427,3 @@ func(st *State) resetCurrent() {
|
||||
st.sink = nil
|
||||
st.CacheMap = make(map[string]string)
|
||||
}
|
||||
|
||||
|
117
go/vm/vm.go
117
go/vm/vm.go
@ -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.
|
||||
//
|
||||
// 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
|
||||
|
||||
log.Printf("running input %v against instruction %v", input, instruction)
|
||||
arg, input, err := argFromBytes(input)
|
||||
if err != nil {
|
||||
return st, input, err
|
||||
return input, err
|
||||
}
|
||||
|
||||
rt := router.FromBytes(input)
|
||||
rt := router.FromBytes(instruction)
|
||||
sym := rt.Get(arg)
|
||||
if sym == "" {
|
||||
sym = rt.Default()
|
||||
st.PutArg(arg)
|
||||
}
|
||||
if sym == "" {
|
||||
instruction = NewLine([]byte{}, MOVE, []string{"_catch"}, nil, nil)
|
||||
} else if sym == "_" {
|
||||
instruction = NewLine([]byte{}, BACK, nil, nil, nil)
|
||||
} else {
|
||||
new_instruction := NewLine([]byte{}, MOVE, []string{sym}, nil, nil)
|
||||
instruction = append(new_instruction, instruction...)
|
||||
}
|
||||
|
||||
st, instruction, err = Run(instruction, st, rs, ctx)
|
||||
if err != nil {
|
||||
return st, instruction, err
|
||||
if sym == "" {
|
||||
instruction = NewLine([]byte{}, MOVE, []string{"_catch"}, nil, nil)
|
||||
} else {
|
||||
instruction, err = rs.GetCode(sym)
|
||||
if err != nil {
|
||||
return instruction, err
|
||||
}
|
||||
|
||||
if sym == "_" {
|
||||
instruction = NewLine([]byte{}, BACK, nil, nil, nil)
|
||||
} else {
|
||||
new_instruction := NewLine([]byte{}, MOVE, []string{sym}, nil, nil)
|
||||
instruction = append(new_instruction, instruction...)
|
||||
}
|
||||
}
|
||||
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.
|
||||
@ -64,61 +73,54 @@ func Apply(input []byte, instruction []byte, st state.State, rs resource.Resourc
|
||||
// Each step may update the state.
|
||||
//
|
||||
// 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
|
||||
for len(instruction) > 0 {
|
||||
log.Printf("instruction is now %v", instruction)
|
||||
op := binary.BigEndian.Uint16(instruction[:2])
|
||||
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 {
|
||||
case CATCH:
|
||||
st, instruction, err = RunCatch(instruction[2:], st, rs, ctx)
|
||||
break
|
||||
instruction, err = RunCatch(instruction[2:], st, rs, ctx)
|
||||
case CROAK:
|
||||
st, instruction, err = RunCroak(instruction[2:], st, rs, ctx)
|
||||
break
|
||||
instruction, err = RunCroak(instruction[2:], st, rs, ctx)
|
||||
case LOAD:
|
||||
st, instruction, err = RunLoad(instruction[2:], st, rs, ctx)
|
||||
break
|
||||
instruction, err = RunLoad(instruction[2:], st, rs, ctx)
|
||||
case RELOAD:
|
||||
st, instruction, err = RunReload(instruction[2:], st, rs, ctx)
|
||||
break
|
||||
instruction, err = RunReload(instruction[2:], st, rs, ctx)
|
||||
case MAP:
|
||||
st, instruction, err = RunMap(instruction[2:], st, rs, ctx)
|
||||
break
|
||||
instruction, err = RunMap(instruction[2:], st, rs, ctx)
|
||||
case MOVE:
|
||||
st, instruction, err = RunMove(instruction[2:], st, rs, ctx)
|
||||
break
|
||||
instruction, err = RunMove(instruction[2:], st, rs, ctx)
|
||||
case BACK:
|
||||
st, instruction, err = RunBack(instruction[2:], st, rs, ctx)
|
||||
break
|
||||
instruction, err = RunBack(instruction[2:], st, rs, ctx)
|
||||
default:
|
||||
err = fmt.Errorf("Unhandled state: %v", op)
|
||||
}
|
||||
if err != nil {
|
||||
return st, instruction, err
|
||||
return instruction, err
|
||||
}
|
||||
}
|
||||
return st, instruction, nil
|
||||
return instruction, nil
|
||||
}
|
||||
|
||||
// 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)
|
||||
if err != nil {
|
||||
return st, instruction, err
|
||||
return instruction, err
|
||||
}
|
||||
err = st.Map(head)
|
||||
return st, tail, err
|
||||
return tail, err
|
||||
}
|
||||
|
||||
// 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)
|
||||
if err != nil {
|
||||
return st, instruction, err
|
||||
return instruction, err
|
||||
}
|
||||
bitFieldSize := tail[0]
|
||||
bitField := tail[1:1+bitFieldSize]
|
||||
@ -128,69 +130,69 @@ func RunCatch(instruction []byte, st state.State, rs resource.Resource, ctx cont
|
||||
st.Down(head)
|
||||
tail = []byte{}
|
||||
}
|
||||
return st, tail, nil
|
||||
return tail, nil
|
||||
}
|
||||
|
||||
// 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)
|
||||
if err != nil {
|
||||
return st, instruction, err
|
||||
return instruction, err
|
||||
}
|
||||
_ = head
|
||||
_ = tail
|
||||
st.Reset()
|
||||
return st, []byte{}, nil
|
||||
return []byte{}, nil
|
||||
}
|
||||
|
||||
// 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)
|
||||
if err != nil {
|
||||
return st, instruction, err
|
||||
return instruction, err
|
||||
}
|
||||
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])
|
||||
tail = tail[1:]
|
||||
|
||||
r, err := refresh(head, rs, ctx)
|
||||
if err != nil {
|
||||
return st, tail, err
|
||||
return tail, err
|
||||
}
|
||||
err = st.Add(head, r, sz)
|
||||
return st, tail, err
|
||||
return tail, err
|
||||
}
|
||||
|
||||
// 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)
|
||||
if err != nil {
|
||||
return st, instruction, err
|
||||
return instruction, err
|
||||
}
|
||||
r, err := refresh(head, rs, ctx)
|
||||
if err != nil {
|
||||
return st, tail, err
|
||||
return tail, err
|
||||
}
|
||||
st.Update(head, r)
|
||||
return st, tail, nil
|
||||
return tail, nil
|
||||
}
|
||||
|
||||
// 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)
|
||||
if err != nil {
|
||||
return st, instruction, err
|
||||
return instruction, err
|
||||
}
|
||||
st.Down(head)
|
||||
return st, tail, nil
|
||||
return tail, nil
|
||||
}
|
||||
|
||||
// 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()
|
||||
return st, instruction, nil
|
||||
return instruction, nil
|
||||
}
|
||||
|
||||
// retrieve data for key
|
||||
@ -199,6 +201,9 @@ func refresh(key string, rs resource.Resource, ctx context.Context) (string, err
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if fn == nil {
|
||||
return "", fmt.Errorf("no retrieve function for external symbol %v", key)
|
||||
}
|
||||
return fn(ctx)
|
||||
}
|
||||
|
||||
|
221
go/vm/vm_test.go
221
go/vm/vm_test.go
@ -96,17 +96,16 @@ func TestRun(t *testing.T) {
|
||||
rs := TestResource{}
|
||||
b := []byte{0x00, MOVE, 0x03}
|
||||
b = append(b, []byte("foo")...)
|
||||
r, _, err := Run(b, st, &rs, context.TODO())
|
||||
_, err := Run(b, &st, &rs, context.TODO())
|
||||
if err != nil {
|
||||
t.Errorf("error on valid opcode: %v", err)
|
||||
}
|
||||
|
||||
b = []byte{0x01, 0x02}
|
||||
r, _, err = Run(b, st, &rs, context.TODO())
|
||||
_, err = Run(b, &st, &rs, context.TODO())
|
||||
if err == nil {
|
||||
t.Errorf("no error on invalid opcode")
|
||||
}
|
||||
_ = r
|
||||
}
|
||||
|
||||
func TestRunLoadRender(t *testing.T) {
|
||||
@ -117,7 +116,7 @@ func TestRunLoadRender(t *testing.T) {
|
||||
ins := append([]byte{uint8(len(sym))}, []byte(sym)...)
|
||||
ins = append(ins, 0x0a)
|
||||
var err error
|
||||
st, _, err = RunLoad(ins, st, &rs, context.TODO())
|
||||
_, err = RunLoad(ins, &st, &rs, context.TODO())
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
@ -142,7 +141,7 @@ func TestRunLoadRender(t *testing.T) {
|
||||
sym = "two"
|
||||
ins = append([]byte{uint8(len(sym))}, []byte(sym)...)
|
||||
ins = append(ins, 0)
|
||||
st, _, err = RunLoad(ins, st, &rs, context.TODO())
|
||||
_, err = RunLoad(ins, &st, &rs, context.TODO())
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
@ -166,7 +165,7 @@ func TestRunMultiple(t *testing.T) {
|
||||
b := []byte{}
|
||||
b = NewLine(b, LOAD, []string{"one"}, nil, []uint8{0})
|
||||
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 {
|
||||
t.Error(err)
|
||||
}
|
||||
@ -178,7 +177,7 @@ func TestRunReload(t *testing.T) {
|
||||
b := []byte{}
|
||||
b = NewLine(b, LOAD, []string{"dyn"}, nil, []uint8{0})
|
||||
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 {
|
||||
t.Error(err)
|
||||
}
|
||||
@ -192,7 +191,7 @@ func TestRunReload(t *testing.T) {
|
||||
dynVal = "baz"
|
||||
b = []byte{}
|
||||
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 {
|
||||
t.Error(err)
|
||||
}
|
||||
@ -209,14 +208,15 @@ func TestRunReload(t *testing.T) {
|
||||
|
||||
func TestRunArg(t *testing.T) {
|
||||
st := state.NewState(5)
|
||||
rs := TestResource{}
|
||||
rt := router.NewRouter()
|
||||
rt.Add("foo", "bar")
|
||||
rt.Add("baz", "xyzzy")
|
||||
b := []byte{0x03}
|
||||
b = append(b, []byte("baz")...)
|
||||
b = append(b, rt.ToBytes()...)
|
||||
//b = append(b, rt.ToBytes()...)
|
||||
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 {
|
||||
t.Error(err)
|
||||
}
|
||||
@ -237,9 +237,9 @@ func TestRunArgInvalid(t *testing.T) {
|
||||
rt.Add("baz", "xyzzy")
|
||||
b := []byte{0x03}
|
||||
b = append(b, []byte("bar")...)
|
||||
b = append(b, rt.ToBytes()...)
|
||||
//b = append(b, rt.ToBytes()...)
|
||||
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 {
|
||||
t.Error(err)
|
||||
}
|
||||
@ -253,97 +253,108 @@ func TestRunArgInvalid(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunArgInstructions(t *testing.T) {
|
||||
st := state.NewState(5)
|
||||
rs := TestResource{}
|
||||
|
||||
rt := router.NewRouter()
|
||||
rt.Add("foo", "bar")
|
||||
b := []byte{0x03}
|
||||
b = append(b, []byte("foo")...)
|
||||
b = append(b, rt.ToBytes()...)
|
||||
|
||||
bi := NewLine([]byte{}, LOAD, []string{"one"}, nil, []uint8{0})
|
||||
bi = NewLine(bi, LOAD, []string{"two"}, nil, []uint8{3})
|
||||
bi = NewLine(bi, MAP, []string{"one"}, nil, nil)
|
||||
bi = NewLine(bi, MAP, []string{"two"}, nil, nil)
|
||||
var err error
|
||||
st, b, err = Apply(b, bi, 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-state _catch, got %v", loc)
|
||||
}
|
||||
m, err := st.Get()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
r, err := rs.RenderTemplate(loc, m)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
_ = r
|
||||
}
|
||||
|
||||
func TestRunMoveAndBack(t *testing.T) {
|
||||
st := state.NewState(5)
|
||||
rs := TestResource{}
|
||||
rt := router.NewRouter()
|
||||
rt.Add("foo", "bar")
|
||||
b := []byte{0x03}
|
||||
b = append(b, []byte("foo")...)
|
||||
b = append(b, rt.ToBytes()...)
|
||||
bi := NewLine([]byte{}, LOAD, []string{"one"}, nil, []uint8{0})
|
||||
|
||||
var err error
|
||||
st, b, err = Apply(b, bi, 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)
|
||||
}
|
||||
|
||||
rt = router.NewRouter()
|
||||
rt.Add("foo", "baz")
|
||||
b = []byte{0x03}
|
||||
b = append(b, []byte("foo")...)
|
||||
b = append(b, rt.ToBytes()...)
|
||||
bi = NewLine([]byte{}, LOAD, []string{"two"}, nil, []uint8{0})
|
||||
st, b, err = Apply(b, bi, 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)
|
||||
}
|
||||
|
||||
rt = router.NewRouter()
|
||||
rt.Add("foo", "_")
|
||||
b = []byte{0x03}
|
||||
b = append(b, []byte("foo")...)
|
||||
b = append(b, rt.ToBytes()...)
|
||||
st, b, err = Apply(b, []byte{}, 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 TestRunArgInstructions(t *testing.T) {
|
||||
// st := state.NewState(5)
|
||||
// rs := TestResource{}
|
||||
//
|
||||
// rt := router.NewRouter()
|
||||
// rt.Add("foo", "bar")
|
||||
// b := []byte{0x03}
|
||||
// b = append(b, []byte("foo")...)
|
||||
// b = append(b, rt.ToBytes()...)
|
||||
//
|
||||
// bi := NewLine([]byte{}, LOAD, []string{"one"}, nil, []uint8{0})
|
||||
// bi = NewLine(bi, LOAD, []string{"two"}, nil, []uint8{3})
|
||||
// bi = NewLine(bi, MAP, []string{"one"}, nil, nil)
|
||||
// bi = NewLine(bi, MAP, []string{"two"}, nil, nil)
|
||||
// var err error
|
||||
// b, err = Apply(b, bi, &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-state bar, got %v", loc)
|
||||
// }
|
||||
// m, err := st.Get()
|
||||
// if err != nil {
|
||||
// t.Fatal(err)
|
||||
// }
|
||||
// _, err = rs.RenderTemplate(loc, m)
|
||||
// if err == nil {
|
||||
// t.Fatalf("expected error to generate template")
|
||||
// }
|
||||
// _, err = Run(bi, &st, &rs, context.TODO())
|
||||
// if err != nil {
|
||||
// t.Error(err)
|
||||
// }
|
||||
// m, err = st.Get()
|
||||
// if err != nil {
|
||||
// t.Fatal(err)
|
||||
// }
|
||||
// _, err = rs.RenderTemplate(loc, m)
|
||||
// if err != nil {
|
||||
// t.Fatal(err)
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//func TestRunMoveAndBack(t *testing.T) {
|
||||
// st := state.NewState(5)
|
||||
// rs := TestResource{}
|
||||
// rt := router.NewRouter()
|
||||
// rt.Add("foo", "bar")
|
||||
// b := []byte{0x03}
|
||||
// b = append(b, []byte("foo")...)
|
||||
// //b = append(b, rt.ToBytes()...)
|
||||
// bi := NewLine([]byte{}, LOAD, []string{"one"}, nil, []uint8{0})
|
||||
//
|
||||
// var err error
|
||||
// b, err = Apply(b, bi, &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)
|
||||
// }
|
||||
//
|
||||
// rt = router.NewRouter()
|
||||
// rt.Add("foo", "baz")
|
||||
// b = []byte{0x03}
|
||||
// b = append(b, []byte("foo")...)
|
||||
// b = append(b, rt.ToBytes()...)
|
||||
// bi = NewLine([]byte{}, LOAD, []string{"two"}, nil, []uint8{0})
|
||||
// b, err = Apply(b, bi, &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)
|
||||
// }
|
||||
//
|
||||
// rt = router.NewRouter()
|
||||
// rt.Add("foo", "_")
|
||||
// b = []byte{0x03}
|
||||
// b = append(b, []byte("foo")...)
|
||||
// //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) {
|
||||
st := state.NewState(5)
|
||||
@ -353,7 +364,7 @@ func TestCatchAndBack(t *testing.T) {
|
||||
b := NewLine([]byte{}, LOAD, []string{"one"}, nil, []uint8{0})
|
||||
b = NewLine(b, CATCH, []string{"bar"}, []byte{0x04}, 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 {
|
||||
t.Error(err)
|
||||
}
|
||||
@ -366,7 +377,7 @@ func TestCatchAndBack(t *testing.T) {
|
||||
b = NewLine([]byte{}, LOAD, []string{"two"}, nil, []uint8{0})
|
||||
b = NewLine(b, CATCH, []string{"bar"}, []byte{0x04}, 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 {
|
||||
t.Error(err)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user