Catch missing input on empty bytecode buffer
This commit is contained in:
parent
f0bfff3a20
commit
6325ef4afd
@ -2,4 +2,5 @@ package state
|
||||
|
||||
const (
|
||||
FLAG_INMATCH = 1
|
||||
FLAG_TERMINATE = 2
|
||||
)
|
||||
|
@ -57,6 +57,12 @@ func Run(b []byte, st *state.State, rs resource.Resource, ctx context.Context) (
|
||||
if err != nil {
|
||||
return b, err
|
||||
}
|
||||
if len(b) == 0 {
|
||||
b, err = RunDeadCheck(b, st, rs, ctx)
|
||||
if err != nil {
|
||||
return b, err
|
||||
}
|
||||
}
|
||||
if len(b) == 0 {
|
||||
return []byte{}, nil
|
||||
}
|
||||
@ -64,6 +70,36 @@ func Run(b []byte, st *state.State, rs resource.Resource, ctx context.Context) (
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// RunDeadCheck determines whether a state of empty bytecode should result in termination.
|
||||
//
|
||||
// If there is remaining bytecode, this method is a noop.
|
||||
//
|
||||
// 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) {
|
||||
if len(b) > 0 {
|
||||
return b, nil
|
||||
}
|
||||
log.Printf("no code remaining, let's check if we terminate")
|
||||
r, err := matchFlag(st, state.FLAG_TERMINATE, false)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if r {
|
||||
return b, nil
|
||||
}
|
||||
location := st.Where()
|
||||
if location == "" {
|
||||
return b, fmt.Errorf("dead runner with no current location")
|
||||
}
|
||||
b = NewLine(nil, MOVE, []string{"_catch"}, nil, nil)
|
||||
b = NewLine(b, HALT, nil, nil, nil)
|
||||
b = NewLine(b, MOVE, []string{location}, nil, nil)
|
||||
log.Printf("code is now %x", b)
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// RunMap executes the MAP opcode
|
||||
func RunMap(b []byte, st *state.State, rs resource.Resource, ctx context.Context) ([]byte, error) {
|
||||
sym, b, err := ParseMap(b)
|
||||
@ -73,6 +109,7 @@ func RunMap(b []byte, st *state.State, rs resource.Resource, ctx context.Context
|
||||
|
||||
// RunMap executes the CATCH opcode
|
||||
func RunCatch(b []byte, st *state.State, rs resource.Resource, ctx context.Context) ([]byte, error) {
|
||||
log.Printf("zzz %x", b)
|
||||
sym, sig, mode, b, err := ParseCatch(b)
|
||||
if err != nil {
|
||||
return b, err
|
||||
|
@ -104,6 +104,7 @@ func TestRunLoadRender(t *testing.T) {
|
||||
|
||||
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())
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
@ -127,11 +128,13 @@ func TestRunLoadRender(t *testing.T) {
|
||||
}
|
||||
|
||||
b = NewLine(nil, LOAD, []string{"two"}, []byte{0x0a}, nil)
|
||||
b = NewLine(b, HALT, nil, nil, nil)
|
||||
b, err = Run(b, &st, &rs, 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())
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
@ -155,6 +158,7 @@ func TestRunMultiple(t *testing.T) {
|
||||
rs := TestResource{}
|
||||
b := NewLine(nil, 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())
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
@ -167,33 +171,35 @@ func TestRunMultiple(t *testing.T) {
|
||||
func TestRunReload(t *testing.T) {
|
||||
st := state.NewState(5)
|
||||
rs := TestResource{}
|
||||
b := NewLine(nil, LOAD, []string{"dyn"}, nil, []uint8{0})
|
||||
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())
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
t.Fatal(err)
|
||||
}
|
||||
r, err := st.Val("dyn")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
t.Fatal(err)
|
||||
}
|
||||
if r != "three" {
|
||||
t.Errorf("expected result 'three', got %v", r)
|
||||
t.Fatalf("expected result 'three', got %v", r)
|
||||
}
|
||||
dynVal = "baz"
|
||||
b = []byte{}
|
||||
b = NewLine(b, RELOAD, []string{"dyn"}, nil, nil)
|
||||
b = NewLine(nil, RELOAD, []string{"dyn"}, nil, nil)
|
||||
b = NewLine(b, HALT, nil, nil, nil)
|
||||
_, err = Run(b, &st, &rs, context.TODO())
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
t.Fatal(err)
|
||||
}
|
||||
r, err = st.Val("dyn")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
t.Fatal(err)
|
||||
}
|
||||
log.Printf("dun now %s", r)
|
||||
if r != "baz" {
|
||||
t.Errorf("expected result 'baz', got %v", r)
|
||||
t.Fatalf("expected result 'baz', got %v", r)
|
||||
}
|
||||
|
||||
}
|
||||
@ -225,7 +231,8 @@ func TestRunArg(t *testing.T) {
|
||||
input := []byte("bar")
|
||||
_ = st.SetInput(input)
|
||||
|
||||
bi := NewLine([]byte{}, INCMP, []string{"bar", "baz"}, nil, nil)
|
||||
bi := NewLine(nil, INCMP, []string{"bar", "baz"}, nil, nil)
|
||||
bi = NewLine(bi, HALT, nil, nil, nil)
|
||||
b, err := Run(bi, &st, &rs, context.TODO())
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
@ -252,6 +259,7 @@ func TestRunInputHandler(t *testing.T) {
|
||||
bi = NewLine(bi, LOAD, []string{"two"}, []byte{0x03}, nil)
|
||||
bi = NewLine(bi, MAP, []string{"one"}, nil, nil)
|
||||
bi = NewLine(bi, MAP, []string{"two"}, nil, nil)
|
||||
bi = NewLine(bi, HALT, nil, nil, nil)
|
||||
|
||||
var err error
|
||||
_, err = Run(bi, &st, &rs, context.TODO())
|
||||
@ -272,20 +280,21 @@ func TestRunArgInvalid(t *testing.T) {
|
||||
|
||||
var err error
|
||||
|
||||
b := NewLine([]byte{}, INCMP, []string{"bar", "baz"}, nil, nil)
|
||||
b = NewLine(b, CATCH, []string{"_catch"}, []byte{state.FLAG_INMATCH}, []uint8{1})
|
||||
st.Down("root")
|
||||
b := NewLine(nil, INCMP, []string{"bar", "baz"}, nil, nil)
|
||||
//b = NewLine(b, CATCH, []string{"_catch"}, []byte{state.FLAG_INMATCH}, []uint8{1})
|
||||
|
||||
b, err = Run(b, &st, &rs, context.TODO())
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
t.Fatal(err)
|
||||
}
|
||||
l := len(b)
|
||||
if l != 0 {
|
||||
t.Errorf("expected empty remainder, got length %v: %v", l, b)
|
||||
expect := NewLine(nil, MOVE, []string{"root"}, nil, nil)
|
||||
if !bytes.Equal(b, expect) {
|
||||
t.Fatalf("expected:\n\t%x\ngot:\b\t%x\n", expect, b)
|
||||
}
|
||||
r := st.Where()
|
||||
if r != "_catch" {
|
||||
t.Errorf("expected where-state _catch, got %v", r)
|
||||
t.Fatalf("expected where-state _catch, got %v", r)
|
||||
}
|
||||
}
|
||||
|
||||
@ -298,6 +307,7 @@ func TestRunMenu(t *testing.T) {
|
||||
b := NewLine(nil, MOVE, []string{"foo"}, nil, nil)
|
||||
b = NewLine(b, MOUT, []string{"0", "one"}, nil, nil)
|
||||
b = NewLine(b, MOUT, []string{"1", "two"}, nil, nil)
|
||||
b = NewLine(b, HALT, nil, nil, nil)
|
||||
|
||||
b, err = Run(b, &st, &rs, context.TODO())
|
||||
if err != nil {
|
||||
@ -331,6 +341,7 @@ func TestRunMenuBrowse(t *testing.T) {
|
||||
b = NewLine(b, MPREV, []string{"22", "two"}, nil, nil)
|
||||
b = NewLine(b, MOUT, []string{"0", "one"}, nil, nil)
|
||||
b = NewLine(b, MOUT, []string{"1", "two"}, nil, nil)
|
||||
b = NewLine(b, HALT, nil, nil, nil)
|
||||
|
||||
b, err = Run(b, &st, &rs, context.TODO())
|
||||
if err != nil {
|
||||
@ -350,3 +361,4 @@ func TestRunMenuBrowse(t *testing.T) {
|
||||
t.Fatalf("expected:\n\t%s\ngot:\n\t%s\n", expect, r)
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user