Add render interface defs, rehabilitate vm

This commit is contained in:
lash 2023-04-09 09:44:32 +01:00
parent 7e01f2725d
commit d183ec1824
Signed by untrusted user who does not match committer: lash
GPG Key ID: 21D2E7BB88C2A746
9 changed files with 297 additions and 111 deletions

8
go/cache/cache.go vendored
View File

@ -108,6 +108,8 @@ func(ca *Cache) Update(key string, value string) error {
ca.CacheUseSize += l ca.CacheUseSize += l
return fmt.Errorf("Cache capacity exceeded %v of %v", baseUseSize + sz, ca.CacheSize) return fmt.Errorf("Cache capacity exceeded %v of %v", baseUseSize + sz, ca.CacheSize)
} }
ca.Cache[checkFrame][key] = value
ca.CacheUseSize += uint32(len(value))
return nil return nil
} }
@ -162,12 +164,6 @@ func(ca *Cache) Check(key string) bool {
return ca.frameOf(key) == -1 return ca.frameOf(key) == -1
} }
// flush relveant properties for level change
//func(ca *Cache) resetCurrent() {
// ca.sink = nil
// ca.CacheMap = make(map[string]string)
//}
// bytes that will be added to cache use size for string // bytes that will be added to cache use size for string
// returns 0 if capacity would be exceeded // returns 0 if capacity would be exceeded
func(ca *Cache) checkCapacity(v string) uint32 { func(ca *Cache) checkCapacity(v string) uint32 {

11
go/cache/memory.go vendored Normal file
View File

@ -0,0 +1,11 @@
package cache
type Memory interface {
Add(key string, val string, sizeLimit uint16) error
Update(key string, val string) error
ReservedSize(key string) (uint16, error)
Get() (map[string]string, error)
Push() error
Pop() error
Reset()
}

View File

@ -58,6 +58,11 @@ func(m *Menu) WithBrowseConfig(cfg BrowseConfig) *Menu {
return m return m
} }
// GetBrowseConfig returns a copy of the current state of the browse configuration.
func(m *Menu) GetBrowseConfig() BrowseConfig {
return m.browse
}
// Put adds a menu option to the menu rendering. // Put adds a menu option to the menu rendering.
func(m *Menu) Put(selector string, title string) error { func(m *Menu) Put(selector string, title string) error {
m.menu = append(m.menu, [2]string{selector, title}) m.menu = append(m.menu, [2]string{selector, title})

View File

@ -80,7 +80,7 @@ func(pg *Page) Map(key string) error {
return err return err
} }
if l == 0 { if l == 0 {
if pg.sink != nil { if pg.sink != nil && *pg.sink != key {
return fmt.Errorf("sink already set to symbol '%v'", *pg.sink) return fmt.Errorf("sink already set to symbol '%v'", *pg.sink)
} }
pg.sink = &key pg.sink = &key

114
go/render/page_test.go Normal file
View File

@ -0,0 +1,114 @@
package render
import (
"testing"
"git.defalsify.org/festive/cache"
)
func TestPageCurrentSize(t *testing.T) {
ca := cache.NewCache()
pg := NewPage(ca, nil)
err := ca.Push()
if err != nil {
t.Error(err)
}
err = ca.Add("foo", "inky", 0)
if err != nil {
t.Error(err)
}
err = ca.Push()
pg.Reset()
err = ca.Add("bar", "pinky", 10)
if err != nil {
t.Error(err)
}
err = ca.Add("baz", "tinkywinkydipsylalapoo", 51)
if err != nil {
t.Error(err)
}
err = pg.Map("foo")
if err != nil {
t.Error(err)
}
err = pg.Map("bar")
if err != nil {
t.Error(err)
}
err = pg.Map("baz")
if err != nil {
t.Error(err)
}
l, c, err := pg.Usage()
if err != nil {
t.Error(err)
}
if l != 27 {
t.Errorf("expected actual length 27, got %v", l)
}
if c != 34 {
t.Errorf("expected remaining length 34, got %v", c)
}
mn := NewMenu().WithOutputSize(32)
pg = pg.WithMenu(mn)
l, c, err = pg.Usage()
if err != nil {
t.Error(err)
}
if l != 59 {
t.Errorf("expected actual length 59, got %v", l)
}
if c != 2 {
t.Errorf("expected remaining length 2, got %v", c)
}
}
func TestStateMapSink(t *testing.T) {
ca := cache.NewCache()
pg := NewPage(ca, nil)
ca.Push()
err := ca.Add("foo", "bar", 0)
if err != nil {
t.Error(err)
}
ca.Push()
pg.Reset()
err = ca.Add("bar", "xyzzy", 6)
if err != nil {
t.Error(err)
}
err = ca.Add("baz", "bazbaz", 18)
if err != nil {
t.Error(err)
}
err = ca.Add("xyzzy", "plugh", 0)
if err != nil {
t.Error(err)
}
err = pg.Map("foo")
if err != nil {
t.Error(err)
}
err = pg.Map("xyzzy")
if err == nil {
t.Errorf("Expected fail on duplicate sink")
}
err = pg.Map("baz")
if err != nil {
t.Error(err)
}
ca.Push()
pg.Reset()
err = pg.Map("foo")
if err != nil {
t.Error(err)
}
ca.Pop()
pg.Reset()
err = pg.Map("foo")
if err != nil {
t.Error(err)
}
}

7
go/render/render.go Normal file
View File

@ -0,0 +1,7 @@
package render
type Renderer interface {
Map(key string) error
Render(sym string, values map[string]string, idx uint16) (string, error)
Reset()
}

View File

@ -275,21 +275,6 @@ func(st *State) Depth() uint8 {
return uint8(len(st.execPath)-1) return uint8(len(st.execPath)-1)
} }
//func(st *State) SetMenuSize(size uint16) error {
// st.menuSize = size
// log.Printf("menu size changed to %v", st.menuSize)
// return nil
//}
//
//func(st *State) GetMenuSize() uint16 {
// return st.menuSize
//}
//
//func(st *State) GetOutputSize() uint32 {
// return st.outputSize
//}
// Appendcode adds the given bytecode to the end of the existing code. // Appendcode adds the given bytecode to the end of the existing code.
func(st *State) AppendCode(b []byte) error { func(st *State) AppendCode(b []byte) error {
st.code = append(st.code, b...) st.code = append(st.code, b...)
@ -328,3 +313,6 @@ func(st *State) SetInput(input []byte) error {
return nil return nil
} }
// Reset to initial state (start navigation over).
func(st *State) Reset() {
}

View File

@ -5,10 +5,31 @@ import (
"fmt" "fmt"
"log" "log"
"git.defalsify.org/festive/cache"
"git.defalsify.org/festive/render"
"git.defalsify.org/festive/resource" "git.defalsify.org/festive/resource"
"git.defalsify.org/festive/state" "git.defalsify.org/festive/state"
) )
type Vm struct {
st *state.State
rs resource.Resource
pg render.Renderer
ca cache.Memory
mn *render.Menu
}
func NewVm(st *state.State, rs resource.Resource, ca cache.Memory, mn *render.Menu, pg render.Renderer) *Vm {
return &Vm{
st: st,
rs: rs,
pg: pg,
ca: ca,
mn: mn,
}
}
//type Runner func(instruction []byte, st state.State, rs resource.Resource, ctx context.Context) (state.State, []byte, error) //type Runner func(instruction []byte, st state.State, rs resource.Resource, ctx context.Context) (state.State, []byte, error)
// Run extracts individual op codes and arguments and executes them. // Run extracts individual op codes and arguments and executes them.
@ -16,7 +37,7 @@ import (
// 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(b []byte, st *state.State, rs resource.Resource, ctx context.Context) ([]byte, error) { func(vm *Vm) Run(b []byte, ctx context.Context) ([]byte, error) {
running := true running := true
for running { for running {
op, bb, err := opSplit(b) op, bb, err := opSplit(b)
@ -27,29 +48,29 @@ func Run(b []byte, st *state.State, rs resource.Resource, ctx context.Context) (
log.Printf("execute code %x (%s) %x", op, OpcodeString[op], b) log.Printf("execute code %x (%s) %x", op, OpcodeString[op], b)
switch op { switch op {
case CATCH: case CATCH:
b, err = RunCatch(b, st, rs, ctx) b, err = vm.RunCatch(b, ctx)
case CROAK: case CROAK:
b, err = RunCroak(b, st, rs, ctx) b, err = vm.RunCroak(b, ctx)
case LOAD: case LOAD:
b, err = RunLoad(b, st, rs, ctx) b, err = vm.RunLoad(b, ctx)
case RELOAD: case RELOAD:
b, err = RunReload(b, st, rs, ctx) b, err = vm.RunReload(b, ctx)
case MAP: case MAP:
b, err = RunMap(b, st, rs, ctx) b, err = vm.RunMap(b, ctx)
case MOVE: case MOVE:
b, err = RunMove(b, st, rs, ctx) b, err = vm.RunMove(b, ctx)
case INCMP: case INCMP:
b, err = RunInCmp(b, st, rs, ctx) b, err = vm.RunInCmp(b, ctx)
case MSIZE: case MSIZE:
b, err = RunMSize(b, st, rs, ctx) b, err = vm.RunMSize(b, ctx)
case MOUT: case MOUT:
b, err = RunMOut(b, st, rs, ctx) b, err = vm.RunMOut(b, ctx)
case MNEXT: case MNEXT:
b, err = RunMNext(b, st, rs, ctx) b, err = vm.RunMNext(b, ctx)
case MPREV: case MPREV:
b, err = RunMPrev(b, st, rs, ctx) b, err = vm.RunMPrev(b, ctx)
case HALT: case HALT:
b, err = RunHalt(b, st, rs, ctx) b, err = vm.RunHalt(b, ctx)
return b, err return b, err
default: default:
err = fmt.Errorf("Unhandled state: %v", op) err = fmt.Errorf("Unhandled state: %v", op)
@ -58,7 +79,7 @@ func Run(b []byte, st *state.State, rs resource.Resource, ctx context.Context) (
return b, err return b, err
} }
if len(b) == 0 { if len(b) == 0 {
b, err = RunDeadCheck(b, st, rs, ctx) b, err = vm.RunDeadCheck(b, ctx)
if err != nil { if err != nil {
return b, err return b, err
} }
@ -77,19 +98,19 @@ func Run(b []byte, st *state.State, rs resource.Resource, ctx context.Context) (
// If input has not been matched, a default invalid input page should be generated aswell as a possiblity of return to last screen (or exit). // If input has not been matched, a default invalid input page should be generated aswell as a possiblity of return to last screen (or exit).
// //
// If the termination flag has been set but not yet handled, execution is allowed to terminate. // If the termination flag has been set but not yet handled, execution is allowed to terminate.
func RunDeadCheck(b []byte, st *state.State, rs resource.Resource, ctx context.Context) ([]byte, error) { func(vm *Vm) RunDeadCheck(b []byte, ctx context.Context) ([]byte, error) {
if len(b) > 0 { if len(b) > 0 {
return b, nil return b, nil
} }
log.Printf("no code remaining, let's check if we terminate") log.Printf("no code remaining, let's check if we terminate")
r, err := st.MatchFlag(state.FLAG_TERMINATE, false) r, err := vm.st.MatchFlag(state.FLAG_TERMINATE, false)
if err != nil { if err != nil {
panic(err) panic(err)
} }
if r { if r {
return b, nil return b, nil
} }
location, _ := st.Where() location, _ := vm.st.Where()
if location == "" { if location == "" {
return b, fmt.Errorf("dead runner with no current location") return b, fmt.Errorf("dead runner with no current location")
} }
@ -99,92 +120,102 @@ func RunDeadCheck(b []byte, st *state.State, rs resource.Resource, ctx context.C
} }
// RunMap executes the MAP opcode // RunMap executes the MAP opcode
func RunMap(b []byte, st *state.State, rs resource.Resource, ctx context.Context) ([]byte, error) { func(vm *Vm) RunMap(b []byte, ctx context.Context) ([]byte, error) {
sym, b, err := ParseMap(b) sym, b, err := ParseMap(b)
err = st.Map(sym) err = vm.pg.Map(sym)
return b, err return b, err
} }
// RunMap executes the CATCH opcode // RunMap executes the CATCH opcode
func RunCatch(b []byte, st *state.State, rs resource.Resource, ctx context.Context) ([]byte, error) { func(vm *Vm) RunCatch(b []byte, ctx context.Context) ([]byte, error) {
log.Printf("zzz %x", b) log.Printf("zzz %x", b)
sym, sig, mode, b, err := ParseCatch(b) sym, sig, mode, b, err := ParseCatch(b)
if err != nil { if err != nil {
return b, err return b, err
} }
r, err := st.MatchFlag(sig, mode) r, err := vm.st.MatchFlag(sig, mode)
if err != nil { if err != nil {
return b, err return b, err
} }
if r { if r {
log.Printf("catch at flag %v, moving to %v", sig, sym) //bitField, d) log.Printf("catch at flag %v, moving to %v", sig, sym) //bitField, d)
st.Down(sym) vm.st.Down(sym)
b = []byte{} b = []byte{}
} }
return b, nil return b, nil
} }
// RunMap executes the CROAK opcode // RunMap executes the CROAK opcode
func RunCroak(b []byte, st *state.State, rs resource.Resource, ctx context.Context) ([]byte, error) { func(vm *Vm) RunCroak(b []byte, ctx context.Context) ([]byte, error) {
sig, mode, b, err := ParseCroak(b) sig, mode, b, err := ParseCroak(b)
if err != nil { if err != nil {
return b, err return b, err
} }
r, err := st.MatchFlag(sig, mode) r, err := vm.st.MatchFlag(sig, mode)
if err != nil { if err != nil {
return b, err return b, err
} }
if r { if r {
log.Printf("croak at flag %v, purging and moving to top", sig) log.Printf("croak at flag %v, purging and moving to top", sig)
st.Reset() vm.st.Reset()
vm.pg.Reset()
vm.ca.Reset()
b = []byte{} b = []byte{}
} }
return []byte{}, nil return []byte{}, nil
} }
// RunLoad executes the LOAD opcode // RunLoad executes the LOAD opcode
func RunLoad(b []byte, st *state.State, rs resource.Resource, ctx context.Context) ([]byte, error) { func(vm *Vm) RunLoad(b []byte, ctx context.Context) ([]byte, error) {
sym, sz, b, err := ParseLoad(b) sym, sz, b, err := ParseLoad(b)
if err != nil { if err != nil {
return b, err return b, err
} }
r, err := refresh(sym, rs, ctx) r, err := refresh(sym, vm.rs, ctx)
if err != nil { if err != nil {
return b, err return b, err
} }
err = st.Add(sym, r, uint16(sz)) err = vm.ca.Add(sym, r, uint16(sz))
return b, err return b, err
} }
// RunLoad executes the RELOAD opcode // RunLoad executes the RELOAD opcode
func RunReload(b []byte, st *state.State, rs resource.Resource, ctx context.Context) ([]byte, error) { func(vm *Vm) RunReload(b []byte, ctx context.Context) ([]byte, error) {
sym, b, err := ParseReload(b) sym, b, err := ParseReload(b)
if err != nil { if err != nil {
return b, err return b, err
} }
r, err := refresh(sym, rs, ctx) r, err := refresh(sym, vm.rs, ctx)
if err != nil { if err != nil {
return b, err return b, err
} }
st.Update(sym, r) vm.ca.Update(sym, r)
if vm.pg != nil {
err := vm.pg.Map(sym)
if err != nil {
return b, err
}
}
return b, nil return b, nil
} }
// RunLoad executes the MOVE opcode // RunLoad executes the MOVE opcode
func RunMove(b []byte, st *state.State, rs resource.Resource, ctx context.Context) ([]byte, error) { func(vm *Vm) RunMove(b []byte, ctx context.Context) ([]byte, error) {
sym, b, err := ParseMove(b) sym, b, err := ParseMove(b)
if err != nil { if err != nil {
return b, err return b, err
} }
if sym == "_" { if sym == "_" {
st.Up() vm.st.Up()
sym, _ = st.Where() vm.ca.Pop()
sym, _ = vm.st.Where()
} else { } else {
st.Down(sym) vm.st.Down(sym)
vm.ca.Push()
} }
code, err := rs.GetCode(sym) code, err := vm.rs.GetCode(sym)
if err != nil { if err != nil {
return b, err return b, err
} }
@ -194,19 +225,19 @@ func RunMove(b []byte, st *state.State, rs resource.Resource, ctx context.Contex
} }
// RunIncmp executes the INCMP opcode // RunIncmp executes the INCMP opcode
func RunInCmp(b []byte, st *state.State, rs resource.Resource, ctx context.Context) ([]byte, error) { func(vm *Vm) RunInCmp(b []byte, ctx context.Context) ([]byte, error) {
sym, target, b, err := ParseInCmp(b) sym, target, b, err := ParseInCmp(b)
if err != nil { if err != nil {
return b, err return b, err
} }
v, err := st.GetFlag(state.FLAG_INMATCH) v, err := vm.st.GetFlag(state.FLAG_INMATCH)
if err != nil { if err != nil {
return b, err return b, err
} }
if v { if v {
return b, nil return b, nil
} }
input, err := st.GetInput() input, err := vm.st.GetInput()
if err != nil { if err != nil {
return b, err return b, err
} }
@ -215,11 +246,11 @@ func RunInCmp(b []byte, st *state.State, rs resource.Resource, ctx context.Conte
} }
log.Printf("input match for '%s'", input) log.Printf("input match for '%s'", input)
_, err = st.SetFlag(state.FLAG_INMATCH) _, err = vm.st.SetFlag(state.FLAG_INMATCH)
sym, _, err = applyTarget([]byte(target), st, ctx) sym, _, err = applyTarget([]byte(target), vm.st, ctx)
code, err := rs.GetCode(target) code, err := vm.rs.GetCode(target)
if err != nil { if err != nil {
return b, err return b, err
} }
@ -229,52 +260,60 @@ func RunInCmp(b []byte, st *state.State, rs resource.Resource, ctx context.Conte
} }
// RunHalt executes the HALT opcode // RunHalt executes the HALT opcode
func RunHalt(b []byte, st *state.State, rs resource.Resource, ctx context.Context) ([]byte, error) { func(vm *Vm) RunHalt(b []byte, ctx context.Context) ([]byte, error) {
var err error var err error
b, err = ParseHalt(b) b, err = ParseHalt(b)
if err != nil { if err != nil {
return b, err return b, err
} }
log.Printf("found HALT, stopping") log.Printf("found HALT, stopping")
_, err = st.ResetFlag(state.FLAG_INMATCH) _, err = vm.st.ResetFlag(state.FLAG_INMATCH)
return b, err return b, err
} }
// RunMSize executes the HALT opcode // RunMSize executes the MSIZE opcode
func RunMSize(b []byte, st *state.State, rs resource.Resource, ctx context.Context) ([]byte, error) { func(vm *Vm) RunMSize(b []byte, ctx context.Context) ([]byte, error) {
log.Printf("WARNING MSIZE not yet implemented") log.Printf("WARNING MSIZE not yet implemented")
_, _, b, err := ParseMSize(b) _, _, b, err := ParseMSize(b)
return b, err return b, err
} }
// RunMOut executes the MOUT opcode // RunMOut executes the MOUT opcode
func RunMOut(b []byte, st *state.State, rs resource.Resource, ctx context.Context) ([]byte, error) { func(vm *Vm) RunMOut(b []byte, ctx context.Context) ([]byte, error) {
choice, title, b, err := ParseMOut(b) choice, title, b, err := ParseMOut(b)
if err != nil { if err != nil {
return b, err return b, err
} }
err = rs.PutMenu(choice, title) err = vm.mn.Put(choice, title)
return b, err return b, err
} }
// RunMNext executes the MNEXT opcode // RunMNext executes the MNEXT opcode
func RunMNext(b []byte, st *state.State, rs resource.Resource, ctx context.Context) ([]byte, error) { func(vm *Vm) RunMNext(b []byte, ctx context.Context) ([]byte, error) {
selector, display, b, err := ParseMNext(b) selector, display, b, err := ParseMNext(b)
if err != nil { if err != nil {
return b, err return b, err
} }
err = rs.SetMenuBrowse(selector, display, false) cfg := vm.mn.GetBrowseConfig()
return b, err cfg.NextSelector = selector
cfg.NextTitle = display
cfg.NextAvailable = true
vm.mn = vm.mn.WithBrowseConfig(cfg)
return b, nil
} }
// RunMPrev executes the MPREV opcode // RunMPrev executes the MPREV opcode
func RunMPrev(b []byte, st *state.State, rs resource.Resource, ctx context.Context) ([]byte, error) { func(vm *Vm) RunMPrev(b []byte, ctx context.Context) ([]byte, error) {
selector, display, b, err := ParseMPrev(b) selector, display, b, err := ParseMPrev(b)
if err != nil { if err != nil {
return b, err return b, err
} }
err = rs.SetMenuBrowse(selector, display, false) cfg := vm.mn.GetBrowseConfig()
return b, err cfg.PreviousSelector = selector
cfg.PreviousTitle = display
cfg.PreviousAvailable = true
vm.mn = vm.mn.WithBrowseConfig(cfg)
return b, nil
} }
// retrieve data for key // retrieve data for key

View File

@ -7,6 +7,8 @@ import (
"log" "log"
"testing" "testing"
"git.defalsify.org/festive/cache"
"git.defalsify.org/festive/render"
"git.defalsify.org/festive/resource" "git.defalsify.org/festive/resource"
"git.defalsify.org/festive/state" "git.defalsify.org/festive/state"
) )
@ -34,7 +36,7 @@ type TestStatefulResolver struct {
state *state.State state *state.State
} }
func (r *TestResource) GetTemplate(sym string, sizer *resource.Sizer) (string, error) { func (r TestResource) GetTemplate(sym string) (string, error) {
switch sym { switch sym {
case "foo": case "foo":
return "inky pinky blinky clyde", nil return "inky pinky blinky clyde", nil
@ -51,11 +53,7 @@ func (r *TestResource) GetTemplate(sym string, sizer *resource.Sizer) (string, e
return "", fmt.Errorf("unknown symbol %s", sym) return "", fmt.Errorf("unknown symbol %s", sym)
} }
func (r *TestResource) RenderTemplate(sym string, values map[string]string, idx uint16, sizer *resource.Sizer) (string, error) { func (r TestResource) FuncFor(sym string) (resource.EntryFunc, error) {
return resource.DefaultRenderTemplate(r, sym, values, idx, sizer)
}
func (r *TestResource) FuncFor(sym string) (resource.EntryFunc, error) {
switch sym { switch sym {
case "one": case "one":
return getOne, nil return getOne, nil
@ -69,12 +67,12 @@ func (r *TestResource) FuncFor(sym string) (resource.EntryFunc, error) {
return nil, fmt.Errorf("invalid function: '%s'", sym) return nil, fmt.Errorf("invalid function: '%s'", sym)
} }
func(r *TestResource) getInput(ctx context.Context) (string, error) { func(r TestResource) getInput(ctx context.Context) (string, error) {
v, err := r.state.GetInput() v, err := r.state.GetInput()
return string(v), err return string(v), err
} }
func(r *TestResource) GetCode(sym string) ([]byte, error) { func(r TestResource) GetCode(sym string) ([]byte, error) {
var b []byte var b []byte
if sym == "_catch" { if sym == "_catch" {
b = NewLine(b, MOUT, []string{"0", "repent"}, nil, nil) b = NewLine(b, MOUT, []string{"0", "repent"}, nil, nil)
@ -86,16 +84,18 @@ func(r *TestResource) GetCode(sym string) ([]byte, error) {
func TestRun(t *testing.T) { func TestRun(t *testing.T) {
st := state.NewState(5) st := state.NewState(5)
rs := TestResource{} rs := TestResource{}
ca := cache.NewCache()
vm := NewVm(&st, &rs, ca, nil, nil)
b := NewLine(nil, MOVE, []string{"foo"}, nil, nil) b := NewLine(nil, MOVE, []string{"foo"}, nil, nil)
b = NewLine(b, HALT, nil, nil, nil) b = NewLine(b, HALT, nil, nil, nil)
_, err := Run(b, &st, &rs, context.TODO()) _, err := vm.Run(b, context.TODO())
if err != nil { if err != nil {
t.Errorf("run error: %v", err) t.Errorf("run error: %v", err)
} }
b = []byte{0x01, 0x02} b = []byte{0x01, 0x02}
_, err = Run(b, &st, &rs, context.TODO()) _, err = vm.Run(b, context.TODO())
if err == nil { if err == nil {
t.Errorf("no error on invalid opcode") t.Errorf("no error on invalid opcode")
} }
@ -103,21 +103,25 @@ func TestRun(t *testing.T) {
func TestRunLoadRender(t *testing.T) { func TestRunLoadRender(t *testing.T) {
st := state.NewState(5) st := state.NewState(5)
st.Down("barbarbar")
rs := TestResource{} rs := TestResource{}
ca := cache.NewCache()
pg := render.NewPage(ca, rs)
vm := NewVm(&st, &rs, ca, nil, pg)
st.Down("barbarbar")
var err error var err error
b := NewLine(nil, LOAD, []string{"one"}, []byte{0x0a}, nil) b := NewLine(nil, LOAD, []string{"one"}, []byte{0x0a}, nil)
b = NewLine(b, HALT, nil, nil, nil) b = NewLine(b, HALT, nil, nil, nil)
b, err = Run(b, &st, &rs, context.TODO()) b, err = vm.Run(b, context.TODO())
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
m, err := st.Get() m, err := ca.Get()
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
r, err := rs.RenderTemplate("foo", m, 0, nil) r, err := pg.RenderTemplate("foo", m, 0)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@ -126,28 +130,28 @@ func TestRunLoadRender(t *testing.T) {
t.Errorf("Expected %v, got %v", []byte(expect), []byte(r)) t.Errorf("Expected %v, got %v", []byte(expect), []byte(r))
} }
r, err = rs.RenderTemplate("bar", m, 0, nil) r, err = pg.RenderTemplate("bar", m, 0)
if err == nil { if err == nil {
t.Errorf("expected error for render of bar: %v" ,err) t.Errorf("expected error for render of bar: %v" ,err)
} }
b = NewLine(nil, LOAD, []string{"two"}, []byte{0x0a}, nil) b = NewLine(nil, LOAD, []string{"two"}, []byte{0x0a}, nil)
b = NewLine(b, HALT, nil, nil, nil) b = NewLine(b, HALT, nil, nil, nil)
b, err = Run(b, &st, &rs, context.TODO()) b, err = vm.Run(b, context.TODO())
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
b = NewLine(nil, MAP, []string{"one"}, nil, nil) b = NewLine(nil, MAP, []string{"one"}, nil, nil)
b = NewLine(b, HALT, nil, nil, nil) b = NewLine(b, HALT, nil, nil, nil)
_, err = Run(b, &st, &rs, context.TODO()) _, err = vm.Run(b, context.TODO())
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
m, err = st.Get() m, err = ca.Get()
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
r, err = rs.RenderTemplate("bar", m, 0, nil) r, err = pg.RenderTemplate("bar", m, 0)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@ -160,11 +164,14 @@ func TestRunLoadRender(t *testing.T) {
func TestRunMultiple(t *testing.T) { func TestRunMultiple(t *testing.T) {
st := state.NewState(5) st := state.NewState(5)
rs := TestResource{} rs := TestResource{}
ca := cache.NewCache()
vm := NewVm(&st, &rs, ca, nil, nil)
b := NewLine(nil, MOVE, []string{"test"}, nil, nil) b := NewLine(nil, MOVE, []string{"test"}, nil, nil)
b = NewLine(b, LOAD, []string{"one"}, []byte{0x00}, nil) b = NewLine(b, LOAD, []string{"one"}, []byte{0x00}, nil)
b = NewLine(b, LOAD, []string{"two"}, []byte{42}, nil) b = NewLine(b, LOAD, []string{"two"}, []byte{42}, nil)
b = NewLine(b, HALT, nil, nil, nil) b = NewLine(b, HALT, nil, nil, nil)
b, err := Run(b, &st, &rs, context.TODO()) b, err := vm.Run(b, context.TODO())
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@ -176,15 +183,19 @@ func TestRunMultiple(t *testing.T) {
func TestRunReload(t *testing.T) { func TestRunReload(t *testing.T) {
st := state.NewState(5) st := state.NewState(5)
rs := TestResource{} rs := TestResource{}
ca := cache.NewCache()
pg := render.NewPage(ca, rs)
vm := NewVm(&st, &rs, ca, nil, pg)
b := NewLine(nil, MOVE, []string{"root"}, nil, nil) b := NewLine(nil, MOVE, []string{"root"}, nil, nil)
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)
b = NewLine(b, HALT, nil, nil, nil) b = NewLine(b, HALT, nil, nil, nil)
_, err := Run(b, &st, &rs, context.TODO()) _, err := vm.Run(b, context.TODO())
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
r, err := st.Val("dyn") r, err := pg.Val("dyn")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -194,11 +205,11 @@ func TestRunReload(t *testing.T) {
dynVal = "baz" dynVal = "baz"
b = NewLine(nil, RELOAD, []string{"dyn"}, nil, nil) b = NewLine(nil, RELOAD, []string{"dyn"}, nil, nil)
b = NewLine(b, HALT, nil, nil, nil) b = NewLine(b, HALT, nil, nil, nil)
_, err = Run(b, &st, &rs, context.TODO()) _, err = vm.Run(b, context.TODO())
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
r, err = st.Val("dyn") r, err = pg.Val("dyn")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -206,18 +217,20 @@ func TestRunReload(t *testing.T) {
if r != "baz" { if r != "baz" {
t.Fatalf("expected result 'baz', got %v", r) t.Fatalf("expected result 'baz', got %v", r)
} }
} }
func TestHalt(t *testing.T) { func TestHalt(t *testing.T) {
st := state.NewState(5) st := state.NewState(5)
rs := TestResource{} rs := TestResource{}
ca := cache.NewCache()
vm := NewVm(&st, &rs, ca, nil, nil)
b := NewLine(nil, MOVE, []string{"root"}, nil, nil) b := NewLine(nil, MOVE, []string{"root"}, nil, nil)
b = NewLine(b, LOAD, []string{"one"}, nil, []uint8{0}) b = NewLine(b, LOAD, []string{"one"}, nil, []uint8{0})
b = NewLine(b, HALT, nil, nil, nil) b = NewLine(b, HALT, nil, nil, nil)
b = NewLine(b, MOVE, []string{"foo"}, nil, nil) b = NewLine(b, MOVE, []string{"foo"}, nil, nil)
var err error var err error
b, err = Run(b, &st, &rs, context.TODO()) b, err = vm.Run(b, context.TODO())
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@ -233,13 +246,15 @@ func TestHalt(t *testing.T) {
func TestRunArg(t *testing.T) { func TestRunArg(t *testing.T) {
st := state.NewState(5) st := state.NewState(5)
rs := TestResource{} rs := TestResource{}
ca := cache.NewCache()
vm := NewVm(&st, &rs, ca, nil, nil)
input := []byte("bar") input := []byte("bar")
_ = st.SetInput(input) _ = st.SetInput(input)
bi := NewLine(nil, INCMP, []string{"bar", "baz"}, nil, nil) bi := NewLine(nil, INCMP, []string{"bar", "baz"}, nil, nil)
bi = NewLine(bi, HALT, nil, nil, nil) bi = NewLine(bi, HALT, nil, nil, nil)
b, err := Run(bi, &st, &rs, context.TODO()) b, err := vm.Run(bi, context.TODO())
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@ -256,6 +271,9 @@ func TestRunArg(t *testing.T) {
func TestRunInputHandler(t *testing.T) { func TestRunInputHandler(t *testing.T) {
st := state.NewState(5) st := state.NewState(5)
rs := TestResource{} rs := TestResource{}
ca := cache.NewCache()
pg := render.NewPage(ca, rs)
vm := NewVm(&st, &rs, ca, nil, pg)
_ = st.SetInput([]byte("baz")) _ = st.SetInput([]byte("baz"))
@ -268,7 +286,7 @@ func TestRunInputHandler(t *testing.T) {
bi = NewLine(bi, HALT, nil, nil, nil) bi = NewLine(bi, HALT, nil, nil, nil)
var err error var err error
_, err = Run(bi, &st, &rs, context.TODO()) _, err = vm.Run(bi, context.TODO())
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -281,6 +299,9 @@ func TestRunInputHandler(t *testing.T) {
func TestRunArgInvalid(t *testing.T) { func TestRunArgInvalid(t *testing.T) {
st := state.NewState(5) st := state.NewState(5)
rs := TestResource{} rs := TestResource{}
ca := cache.NewCache()
mn := render.NewMenu()
vm := NewVm(&st, &rs, ca, mn, nil)
_ = st.SetInput([]byte("foo")) _ = st.SetInput([]byte("foo"))
@ -289,7 +310,7 @@ func TestRunArgInvalid(t *testing.T) {
st.Down("root") st.Down("root")
b := NewLine(nil, INCMP, []string{"bar", "baz"}, nil, nil) b := NewLine(nil, INCMP, []string{"bar", "baz"}, nil, nil)
b, err = Run(b, &st, &rs, context.TODO()) b, err = vm.Run(b, context.TODO())
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -302,6 +323,9 @@ func TestRunArgInvalid(t *testing.T) {
func TestRunMenu(t *testing.T) { func TestRunMenu(t *testing.T) {
st := state.NewState(5) st := state.NewState(5)
rs := TestResource{} rs := TestResource{}
ca := cache.NewCache()
mn := render.NewMenu()
vm := NewVm(&st, &rs, ca, mn, nil)
var err error var err error
@ -310,7 +334,7 @@ func TestRunMenu(t *testing.T) {
b = NewLine(b, MOUT, []string{"1", "two"}, nil, nil) b = NewLine(b, MOUT, []string{"1", "two"}, nil, nil)
b = NewLine(b, HALT, nil, nil, nil) b = NewLine(b, HALT, nil, nil, nil)
b, err = Run(b, &st, &rs, context.TODO()) b, err = vm.Run(b, context.TODO())
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@ -319,7 +343,7 @@ func TestRunMenu(t *testing.T) {
t.Errorf("expected empty remainder, got length %v: %v", l, b) t.Errorf("expected empty remainder, got length %v: %v", l, b)
} }
r, err := rs.RenderMenu(0) r, err := mn.Render(0)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -329,11 +353,13 @@ func TestRunMenu(t *testing.T) {
} }
} }
func TestRunMenuBrowse(t *testing.T) { func TestRunMenuBrowse(t *testing.T) {
log.Printf("This test is incomplete, it must check the output of a menu browser once one is implemented. For now it only checks whether it can execute the runner endpoints for the instrucitons.") log.Printf("This test is incomplete, it must check the output of a menu browser once one is implemented. For now it only checks whether it can execute the runner endpoints for the instrucitons.")
st := state.NewState(5) st := state.NewState(5)
rs := TestResource{} rs := TestResource{}
ca := cache.NewCache()
mn := render.NewMenu()
vm := NewVm(&st, &rs, ca, mn, nil)
var err error var err error
@ -342,7 +368,7 @@ func TestRunMenuBrowse(t *testing.T) {
b = NewLine(b, MOUT, []string{"1", "two"}, nil, nil) b = NewLine(b, MOUT, []string{"1", "two"}, nil, nil)
b = NewLine(b, HALT, nil, nil, nil) b = NewLine(b, HALT, nil, nil, nil)
b, err = Run(b, &st, &rs, context.TODO()) b, err = vm.Run(b, context.TODO())
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@ -351,7 +377,7 @@ func TestRunMenuBrowse(t *testing.T) {
t.Errorf("expected empty remainder, got length %v: %v", l, b) t.Errorf("expected empty remainder, got length %v: %v", l, b)
} }
r, err := rs.RenderMenu(0) r, err := mn.Render(0)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }