Add render interface defs, rehabilitate vm
This commit is contained in:
parent
7e01f2725d
commit
d183ec1824
8
go/cache/cache.go
vendored
8
go/cache/cache.go
vendored
@ -108,6 +108,8 @@ func(ca *Cache) Update(key string, value string) error {
|
||||
ca.CacheUseSize += l
|
||||
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
|
||||
}
|
||||
|
||||
@ -162,12 +164,6 @@ func(ca *Cache) Check(key string) bool {
|
||||
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
|
||||
// returns 0 if capacity would be exceeded
|
||||
func(ca *Cache) checkCapacity(v string) uint32 {
|
||||
|
11
go/cache/memory.go
vendored
Normal file
11
go/cache/memory.go
vendored
Normal 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()
|
||||
}
|
@ -58,6 +58,11 @@ func(m *Menu) WithBrowseConfig(cfg BrowseConfig) *Menu {
|
||||
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.
|
||||
func(m *Menu) Put(selector string, title string) error {
|
||||
m.menu = append(m.menu, [2]string{selector, title})
|
||||
|
@ -80,7 +80,7 @@ func(pg *Page) Map(key string) error {
|
||||
return err
|
||||
}
|
||||
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)
|
||||
}
|
||||
pg.sink = &key
|
||||
|
114
go/render/page_test.go
Normal file
114
go/render/page_test.go
Normal 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
7
go/render/render.go
Normal 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()
|
||||
}
|
@ -275,21 +275,6 @@ func(st *State) Depth() uint8 {
|
||||
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.
|
||||
func(st *State) AppendCode(b []byte) error {
|
||||
st.code = append(st.code, b...)
|
||||
@ -328,3 +313,6 @@ func(st *State) SetInput(input []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Reset to initial state (start navigation over).
|
||||
func(st *State) Reset() {
|
||||
}
|
||||
|
147
go/vm/runner.go
147
go/vm/runner.go
@ -5,10 +5,31 @@ import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"git.defalsify.org/festive/cache"
|
||||
"git.defalsify.org/festive/render"
|
||||
"git.defalsify.org/festive/resource"
|
||||
"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)
|
||||
|
||||
// Run extracts individual op codes and arguments and executes them.
|
||||
@ -16,7 +37,7 @@ import (
|
||||
// Each step may update the state.
|
||||
//
|
||||
// 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
|
||||
for running {
|
||||
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)
|
||||
switch op {
|
||||
case CATCH:
|
||||
b, err = RunCatch(b, st, rs, ctx)
|
||||
b, err = vm.RunCatch(b, ctx)
|
||||
case CROAK:
|
||||
b, err = RunCroak(b, st, rs, ctx)
|
||||
b, err = vm.RunCroak(b, ctx)
|
||||
case LOAD:
|
||||
b, err = RunLoad(b, st, rs, ctx)
|
||||
b, err = vm.RunLoad(b, ctx)
|
||||
case RELOAD:
|
||||
b, err = RunReload(b, st, rs, ctx)
|
||||
b, err = vm.RunReload(b, ctx)
|
||||
case MAP:
|
||||
b, err = RunMap(b, st, rs, ctx)
|
||||
b, err = vm.RunMap(b, ctx)
|
||||
case MOVE:
|
||||
b, err = RunMove(b, st, rs, ctx)
|
||||
b, err = vm.RunMove(b, ctx)
|
||||
case INCMP:
|
||||
b, err = RunInCmp(b, st, rs, ctx)
|
||||
b, err = vm.RunInCmp(b, ctx)
|
||||
case MSIZE:
|
||||
b, err = RunMSize(b, st, rs, ctx)
|
||||
b, err = vm.RunMSize(b, ctx)
|
||||
case MOUT:
|
||||
b, err = RunMOut(b, st, rs, ctx)
|
||||
b, err = vm.RunMOut(b, ctx)
|
||||
case MNEXT:
|
||||
b, err = RunMNext(b, st, rs, ctx)
|
||||
b, err = vm.RunMNext(b, ctx)
|
||||
case MPREV:
|
||||
b, err = RunMPrev(b, st, rs, ctx)
|
||||
b, err = vm.RunMPrev(b, ctx)
|
||||
case HALT:
|
||||
b, err = RunHalt(b, st, rs, ctx)
|
||||
b, err = vm.RunHalt(b, ctx)
|
||||
return b, err
|
||||
default:
|
||||
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
|
||||
}
|
||||
if len(b) == 0 {
|
||||
b, err = RunDeadCheck(b, st, rs, ctx)
|
||||
b, err = vm.RunDeadCheck(b, ctx)
|
||||
if err != nil {
|
||||
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 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 {
|
||||
return b, nil
|
||||
}
|
||||
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 {
|
||||
panic(err)
|
||||
}
|
||||
if r {
|
||||
return b, nil
|
||||
}
|
||||
location, _ := st.Where()
|
||||
location, _ := vm.st.Where()
|
||||
if 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
|
||||
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)
|
||||
err = st.Map(sym)
|
||||
err = vm.pg.Map(sym)
|
||||
return b, err
|
||||
}
|
||||
|
||||
// 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)
|
||||
sym, sig, mode, b, err := ParseCatch(b)
|
||||
if err != nil {
|
||||
return b, err
|
||||
}
|
||||
r, err := st.MatchFlag(sig, mode)
|
||||
r, err := vm.st.MatchFlag(sig, mode)
|
||||
if err != nil {
|
||||
return b, err
|
||||
}
|
||||
if r {
|
||||
log.Printf("catch at flag %v, moving to %v", sig, sym) //bitField, d)
|
||||
st.Down(sym)
|
||||
vm.st.Down(sym)
|
||||
b = []byte{}
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// 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)
|
||||
if err != nil {
|
||||
return b, err
|
||||
}
|
||||
r, err := st.MatchFlag(sig, mode)
|
||||
r, err := vm.st.MatchFlag(sig, mode)
|
||||
if err != nil {
|
||||
return b, err
|
||||
}
|
||||
if r {
|
||||
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{}
|
||||
}
|
||||
return []byte{}, nil
|
||||
}
|
||||
|
||||
// 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)
|
||||
if err != nil {
|
||||
return b, err
|
||||
}
|
||||
|
||||
r, err := refresh(sym, rs, ctx)
|
||||
r, err := refresh(sym, vm.rs, ctx)
|
||||
if err != nil {
|
||||
return b, err
|
||||
}
|
||||
err = st.Add(sym, r, uint16(sz))
|
||||
err = vm.ca.Add(sym, r, uint16(sz))
|
||||
return b, err
|
||||
}
|
||||
|
||||
// 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)
|
||||
if err != nil {
|
||||
return b, err
|
||||
}
|
||||
|
||||
r, err := refresh(sym, rs, ctx)
|
||||
r, err := refresh(sym, vm.rs, ctx)
|
||||
if err != nil {
|
||||
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
|
||||
}
|
||||
|
||||
// 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)
|
||||
if err != nil {
|
||||
return b, err
|
||||
}
|
||||
if sym == "_" {
|
||||
st.Up()
|
||||
sym, _ = st.Where()
|
||||
vm.st.Up()
|
||||
vm.ca.Pop()
|
||||
sym, _ = vm.st.Where()
|
||||
} 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 {
|
||||
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
|
||||
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)
|
||||
if err != nil {
|
||||
return b, err
|
||||
}
|
||||
v, err := st.GetFlag(state.FLAG_INMATCH)
|
||||
v, err := vm.st.GetFlag(state.FLAG_INMATCH)
|
||||
if err != nil {
|
||||
return b, err
|
||||
}
|
||||
if v {
|
||||
return b, nil
|
||||
}
|
||||
input, err := st.GetInput()
|
||||
input, err := vm.st.GetInput()
|
||||
if err != nil {
|
||||
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)
|
||||
_, 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 {
|
||||
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
|
||||
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
|
||||
b, err = ParseHalt(b)
|
||||
if err != nil {
|
||||
return b, err
|
||||
}
|
||||
log.Printf("found HALT, stopping")
|
||||
_, err = st.ResetFlag(state.FLAG_INMATCH)
|
||||
_, err = vm.st.ResetFlag(state.FLAG_INMATCH)
|
||||
return b, err
|
||||
}
|
||||
|
||||
// RunMSize executes the HALT opcode
|
||||
func RunMSize(b []byte, st *state.State, rs resource.Resource, ctx context.Context) ([]byte, error) {
|
||||
// RunMSize executes the MSIZE opcode
|
||||
func(vm *Vm) RunMSize(b []byte, ctx context.Context) ([]byte, error) {
|
||||
log.Printf("WARNING MSIZE not yet implemented")
|
||||
_, _, b, err := ParseMSize(b)
|
||||
return b, err
|
||||
}
|
||||
|
||||
// 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)
|
||||
if err != nil {
|
||||
return b, err
|
||||
}
|
||||
err = rs.PutMenu(choice, title)
|
||||
err = vm.mn.Put(choice, title)
|
||||
return b, err
|
||||
}
|
||||
|
||||
// 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)
|
||||
if err != nil {
|
||||
return b, err
|
||||
}
|
||||
err = rs.SetMenuBrowse(selector, display, false)
|
||||
return b, err
|
||||
cfg := vm.mn.GetBrowseConfig()
|
||||
cfg.NextSelector = selector
|
||||
cfg.NextTitle = display
|
||||
cfg.NextAvailable = true
|
||||
vm.mn = vm.mn.WithBrowseConfig(cfg)
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// 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)
|
||||
if err != nil {
|
||||
return b, err
|
||||
}
|
||||
err = rs.SetMenuBrowse(selector, display, false)
|
||||
return b, err
|
||||
cfg := vm.mn.GetBrowseConfig()
|
||||
cfg.PreviousSelector = selector
|
||||
cfg.PreviousTitle = display
|
||||
cfg.PreviousAvailable = true
|
||||
vm.mn = vm.mn.WithBrowseConfig(cfg)
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// retrieve data for key
|
||||
|
@ -7,6 +7,8 @@ import (
|
||||
"log"
|
||||
"testing"
|
||||
|
||||
"git.defalsify.org/festive/cache"
|
||||
"git.defalsify.org/festive/render"
|
||||
"git.defalsify.org/festive/resource"
|
||||
"git.defalsify.org/festive/state"
|
||||
)
|
||||
@ -34,7 +36,7 @@ type TestStatefulResolver struct {
|
||||
state *state.State
|
||||
}
|
||||
|
||||
func (r *TestResource) GetTemplate(sym string, sizer *resource.Sizer) (string, error) {
|
||||
func (r TestResource) GetTemplate(sym string) (string, error) {
|
||||
switch sym {
|
||||
case "foo":
|
||||
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)
|
||||
}
|
||||
|
||||
func (r *TestResource) RenderTemplate(sym string, values map[string]string, idx uint16, sizer *resource.Sizer) (string, error) {
|
||||
return resource.DefaultRenderTemplate(r, sym, values, idx, sizer)
|
||||
}
|
||||
|
||||
func (r *TestResource) FuncFor(sym string) (resource.EntryFunc, error) {
|
||||
func (r TestResource) FuncFor(sym string) (resource.EntryFunc, error) {
|
||||
switch sym {
|
||||
case "one":
|
||||
return getOne, nil
|
||||
@ -69,12 +67,12 @@ func (r *TestResource) FuncFor(sym string) (resource.EntryFunc, error) {
|
||||
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()
|
||||
return string(v), err
|
||||
}
|
||||
|
||||
func(r *TestResource) GetCode(sym string) ([]byte, error) {
|
||||
func(r TestResource) GetCode(sym string) ([]byte, error) {
|
||||
var b []byte
|
||||
if sym == "_catch" {
|
||||
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) {
|
||||
st := state.NewState(5)
|
||||
rs := TestResource{}
|
||||
ca := cache.NewCache()
|
||||
vm := NewVm(&st, &rs, ca, nil, nil)
|
||||
|
||||
b := NewLine(nil, MOVE, []string{"foo"}, 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 {
|
||||
t.Errorf("run error: %v", err)
|
||||
}
|
||||
|
||||
b = []byte{0x01, 0x02}
|
||||
_, err = Run(b, &st, &rs, context.TODO())
|
||||
_, err = vm.Run(b, context.TODO())
|
||||
if err == nil {
|
||||
t.Errorf("no error on invalid opcode")
|
||||
}
|
||||
@ -103,21 +103,25 @@ func TestRun(t *testing.T) {
|
||||
|
||||
func TestRunLoadRender(t *testing.T) {
|
||||
st := state.NewState(5)
|
||||
st.Down("barbarbar")
|
||||
rs := TestResource{}
|
||||
ca := cache.NewCache()
|
||||
pg := render.NewPage(ca, rs)
|
||||
vm := NewVm(&st, &rs, ca, nil, pg)
|
||||
|
||||
st.Down("barbarbar")
|
||||
|
||||
var err error
|
||||
b := NewLine(nil, LOAD, []string{"one"}, []byte{0x0a}, 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 {
|
||||
t.Error(err)
|
||||
}
|
||||
m, err := st.Get()
|
||||
m, err := ca.Get()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
r, err := rs.RenderTemplate("foo", m, 0, nil)
|
||||
r, err := pg.RenderTemplate("foo", m, 0)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
@ -126,28 +130,28 @@ func TestRunLoadRender(t *testing.T) {
|
||||
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 {
|
||||
t.Errorf("expected error for render of bar: %v" ,err)
|
||||
}
|
||||
|
||||
b = NewLine(nil, LOAD, []string{"two"}, []byte{0x0a}, 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 {
|
||||
t.Error(err)
|
||||
}
|
||||
b = NewLine(nil, MAP, []string{"one"}, 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 {
|
||||
t.Error(err)
|
||||
}
|
||||
m, err = st.Get()
|
||||
m, err = ca.Get()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
r, err = rs.RenderTemplate("bar", m, 0, nil)
|
||||
r, err = pg.RenderTemplate("bar", m, 0)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
@ -160,11 +164,14 @@ func TestRunLoadRender(t *testing.T) {
|
||||
func TestRunMultiple(t *testing.T) {
|
||||
st := state.NewState(5)
|
||||
rs := TestResource{}
|
||||
ca := cache.NewCache()
|
||||
vm := NewVm(&st, &rs, ca, nil, nil)
|
||||
|
||||
b := NewLine(nil, MOVE, []string{"test"}, nil, nil)
|
||||
b = NewLine(b, LOAD, []string{"one"}, []byte{0x00}, nil)
|
||||
b = NewLine(b, LOAD, []string{"two"}, []byte{42}, 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 {
|
||||
t.Error(err)
|
||||
}
|
||||
@ -176,15 +183,19 @@ func TestRunMultiple(t *testing.T) {
|
||||
func TestRunReload(t *testing.T) {
|
||||
st := state.NewState(5)
|
||||
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(b, LOAD, []string{"dyn"}, nil, []uint8{0})
|
||||
b = NewLine(b, MAP, []string{"dyn"}, 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 {
|
||||
t.Fatal(err)
|
||||
}
|
||||
r, err := st.Val("dyn")
|
||||
r, err := pg.Val("dyn")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -194,11 +205,11 @@ func TestRunReload(t *testing.T) {
|
||||
dynVal = "baz"
|
||||
b = NewLine(nil, RELOAD, []string{"dyn"}, 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 {
|
||||
t.Fatal(err)
|
||||
}
|
||||
r, err = st.Val("dyn")
|
||||
r, err = pg.Val("dyn")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -206,18 +217,20 @@ func TestRunReload(t *testing.T) {
|
||||
if r != "baz" {
|
||||
t.Fatalf("expected result 'baz', got %v", r)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestHalt(t *testing.T) {
|
||||
st := state.NewState(5)
|
||||
rs := TestResource{}
|
||||
ca := cache.NewCache()
|
||||
vm := NewVm(&st, &rs, ca, nil, nil)
|
||||
|
||||
b := NewLine(nil, MOVE, []string{"root"}, nil, nil)
|
||||
b = NewLine(b, LOAD, []string{"one"}, nil, []uint8{0})
|
||||
b = NewLine(b, HALT, nil, nil, nil)
|
||||
b = NewLine(b, MOVE, []string{"foo"}, nil, nil)
|
||||
var err error
|
||||
b, err = Run(b, &st, &rs, context.TODO())
|
||||
b, err = vm.Run(b, context.TODO())
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
@ -233,13 +246,15 @@ func TestHalt(t *testing.T) {
|
||||
func TestRunArg(t *testing.T) {
|
||||
st := state.NewState(5)
|
||||
rs := TestResource{}
|
||||
ca := cache.NewCache()
|
||||
vm := NewVm(&st, &rs, ca, nil, nil)
|
||||
|
||||
input := []byte("bar")
|
||||
_ = st.SetInput(input)
|
||||
|
||||
bi := NewLine(nil, INCMP, []string{"bar", "baz"}, 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 {
|
||||
t.Error(err)
|
||||
}
|
||||
@ -256,6 +271,9 @@ func TestRunArg(t *testing.T) {
|
||||
func TestRunInputHandler(t *testing.T) {
|
||||
st := state.NewState(5)
|
||||
rs := TestResource{}
|
||||
ca := cache.NewCache()
|
||||
pg := render.NewPage(ca, rs)
|
||||
vm := NewVm(&st, &rs, ca, nil, pg)
|
||||
|
||||
_ = st.SetInput([]byte("baz"))
|
||||
|
||||
@ -268,7 +286,7 @@ func TestRunInputHandler(t *testing.T) {
|
||||
bi = NewLine(bi, HALT, nil, nil, nil)
|
||||
|
||||
var err error
|
||||
_, err = Run(bi, &st, &rs, context.TODO())
|
||||
_, err = vm.Run(bi, context.TODO())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -281,6 +299,9 @@ func TestRunInputHandler(t *testing.T) {
|
||||
func TestRunArgInvalid(t *testing.T) {
|
||||
st := state.NewState(5)
|
||||
rs := TestResource{}
|
||||
ca := cache.NewCache()
|
||||
mn := render.NewMenu()
|
||||
vm := NewVm(&st, &rs, ca, mn, nil)
|
||||
|
||||
_ = st.SetInput([]byte("foo"))
|
||||
|
||||
@ -289,7 +310,7 @@ func TestRunArgInvalid(t *testing.T) {
|
||||
st.Down("root")
|
||||
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 {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -302,6 +323,9 @@ func TestRunArgInvalid(t *testing.T) {
|
||||
func TestRunMenu(t *testing.T) {
|
||||
st := state.NewState(5)
|
||||
rs := TestResource{}
|
||||
ca := cache.NewCache()
|
||||
mn := render.NewMenu()
|
||||
vm := NewVm(&st, &rs, ca, mn, nil)
|
||||
|
||||
var err error
|
||||
|
||||
@ -310,7 +334,7 @@ func TestRunMenu(t *testing.T) {
|
||||
b = NewLine(b, MOUT, []string{"1", "two"}, 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 {
|
||||
t.Error(err)
|
||||
}
|
||||
@ -319,7 +343,7 @@ func TestRunMenu(t *testing.T) {
|
||||
t.Errorf("expected empty remainder, got length %v: %v", l, b)
|
||||
}
|
||||
|
||||
r, err := rs.RenderMenu(0)
|
||||
r, err := mn.Render(0)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -329,11 +353,13 @@ func TestRunMenu(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.")
|
||||
st := state.NewState(5)
|
||||
rs := TestResource{}
|
||||
ca := cache.NewCache()
|
||||
mn := render.NewMenu()
|
||||
vm := NewVm(&st, &rs, ca, mn, nil)
|
||||
|
||||
var err error
|
||||
|
||||
@ -342,7 +368,7 @@ func TestRunMenuBrowse(t *testing.T) {
|
||||
b = NewLine(b, MOUT, []string{"1", "two"}, 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 {
|
||||
t.Error(err)
|
||||
}
|
||||
@ -351,7 +377,7 @@ func TestRunMenuBrowse(t *testing.T) {
|
||||
t.Errorf("expected empty remainder, got length %v: %v", l, b)
|
||||
}
|
||||
|
||||
r, err := rs.RenderMenu(0)
|
||||
r, err := mn.Render(0)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user