go-vise

Constrained Size Output Virtual Machine
Info | Log | Files | Refs | README | LICENSE

runner_test.go (16581B)


      1 package vm
      2 
      3 import (
      4 	"bytes"
      5 	"context"
      6 	"fmt"
      7 	"log"
      8 	"testing"
      9 	
     10 	"git.defalsify.org/vise.git/cache"
     11 	"git.defalsify.org/vise.git/render"
     12 	"git.defalsify.org/vise.git/resource"
     13 	"git.defalsify.org/vise.git/state"
     14 )
     15 
     16 var dynVal = "three"
     17 
     18 type TestResource struct {
     19 	resource.MemResource
     20 	state *state.State
     21 	RootCode []byte
     22 	CatchContent string
     23 }
     24 
     25 func NewTestResource(st *state.State) TestResource {
     26 	tr := TestResource{
     27 		MemResource: resource.NewMemResource(),
     28 		state: st,	
     29 	}
     30 	tr.AddTemplate("foo", "inky pinky blinky clyde")
     31 	tr.AddTemplate("bar", "inky pinky {{.one}} blinky {{.two}} clyde")
     32 	tr.AddTemplate("baz", "inky pinky {{.baz}} blinky clyde")
     33 	tr.AddTemplate("three", "{{.one}} inky pinky {{.three}} blinky clyde {{.two}}")
     34 	tr.AddTemplate("root", "root")
     35 	tr.AddTemplate("_catch", tr.CatchContent)
     36 	tr.AddTemplate("ouf", "ouch")
     37 	tr.AddTemplate("flagCatch", "flagiee")
     38 	tr.AddEntryFunc("one", getOne)
     39 	tr.AddEntryFunc("two", getTwo)
     40 	tr.AddEntryFunc("dyn", getDyn)
     41 	tr.AddEntryFunc("arg", tr.getInput)
     42 	tr.AddEntryFunc("echo", getEcho)
     43 	tr.AddEntryFunc("setFlagOne", setFlag)
     44 	tr.AddEntryFunc("set_lang", set_lang)
     45 	tr.AddEntryFunc("aiee", uhOh)
     46 
     47 	var b []byte
     48 	b = NewLine(nil, HALT, nil, nil, nil)
     49 	tr.AddBytecode("one", b)
     50 
     51 	b = NewLine(nil, MOUT, []string{"0", "repent"}, nil, nil)
     52 	b = NewLine(b, HALT, nil, nil, nil)
     53 	tr.AddBytecode("_catch", b)
     54 
     55 	b = NewLine(nil, MOUT, []string{"0", "repent"}, nil, nil)
     56 	b = NewLine(b, HALT, nil, nil, nil)
     57 	b = NewLine(b, MOVE, []string{"_"}, nil, nil)
     58 	tr.AddBytecode("flagCatch", b)
     59 
     60 	b = NewLine(nil, MOUT, []string{"1", "oo"}, nil, nil)
     61 	b = NewLine(b, HALT, nil, nil, nil)
     62 	tr.AddBytecode("ouf", b)
     63 	
     64 	tr.AddBytecode("root", tr.RootCode)
     65 	return tr
     66 }
     67 
     68 func getOne(ctx context.Context, sym string, input []byte) (resource.Result, error) {
     69 	return resource.Result{
     70 		Content: "one",
     71 	}, nil
     72 }
     73 
     74 func getTwo(ctx context.Context, sym string, input []byte) (resource.Result, error) {
     75 	return resource.Result{
     76 		Content: "two",
     77 	}, nil
     78 }
     79 
     80 func getDyn(ctx context.Context, sym string, input []byte) (resource.Result, error) {
     81 	return resource.Result{
     82 		Content: dynVal,
     83 	}, nil
     84 }
     85 
     86 func getEcho(ctx context.Context, sym string, input []byte) (resource.Result, error) {
     87 	r := fmt.Sprintf("echo: %s", input)
     88 	return resource.Result{
     89 		Content: r,
     90 	}, nil
     91 }
     92 
     93 
     94 func uhOh(ctx context.Context, sym string, input []byte) (resource.Result, error) {
     95 	return resource.Result{}, fmt.Errorf("uh-oh spaghetti'ohs")
     96 }
     97 
     98 func setFlag(ctx context.Context, sym string, input []byte) (resource.Result, error) {
     99 	s := fmt.Sprintf("ping")
    100 	r := resource.Result{
    101 		Content: s,
    102 	}
    103 	if len(input) > 0 {
    104 		r.FlagSet = append(r.FlagSet, uint32(input[0]))
    105 	}
    106 	if len(input) > 1 {
    107 		r.FlagReset = append(r.FlagReset, uint32(input[1]))
    108 	}
    109 	log.Printf("setflag %v", r)
    110 	return r, nil 
    111 
    112 }
    113 
    114 func set_lang(ctx context.Context, sym string, input []byte) (resource.Result, error) {
    115 	return resource.Result{
    116 		Content: string(input),
    117 		FlagSet: []uint32{state.FLAG_LANG},
    118 	}, nil
    119 }
    120 //
    121 //type TestStatefulResolver struct {
    122 //	state *state.State
    123 //}
    124 
    125 func (r TestResource) FuncFor(sym string) (resource.EntryFunc, error) {
    126 	switch sym {
    127 	case "one":
    128 		return getOne, nil
    129 	case "two":
    130 		return getTwo, nil
    131 	case "dyn":
    132 		return getDyn, nil
    133 	case "arg":
    134 		return r.getInput, nil
    135 	case "echo":
    136 		return getEcho, nil
    137 	case "setFlagOne":
    138 		return setFlag, nil
    139 	case "set_lang":
    140 		return set_lang, nil
    141 	case "aiee":
    142 		return uhOh, nil
    143 	}
    144 	return nil, fmt.Errorf("invalid function: '%s'", sym)
    145 }
    146 
    147 func(r TestResource) getInput(ctx context.Context, sym string, input []byte) (resource.Result, error) {
    148 	v, err := r.state.GetInput()
    149 	return resource.Result{
    150 		Content: string(v),
    151 	}, err
    152 }
    153 
    154 func(r TestResource) getCode(sym string) ([]byte, error) {
    155 	var b []byte
    156 	switch sym {
    157 	case "_catch":
    158 		b = NewLine(b, MOUT, []string{"0", "repent"}, nil, nil)
    159 		b = NewLine(b, HALT, nil, nil, nil)
    160 	case "flagCatch":
    161 		b = NewLine(b, MOUT, []string{"0", "repent"}, nil, nil)
    162 		b = NewLine(b, HALT, nil, nil, nil)
    163 		b = NewLine(b, MOVE, []string{"_"}, nil, nil)
    164 	case "root":
    165 		b = r.RootCode
    166 	case "ouf":
    167 		b = NewLine(b, MOUT, []string{"1", "oo"}, nil, nil)
    168 		b = NewLine(b, HALT, nil, nil, nil)
    169 	}
    170 
    171 	return b, nil
    172 }
    173 
    174 func TestRun(t *testing.T) {
    175 	st := state.NewState(5)
    176 	rs := NewTestResource(&st)
    177 	ca := cache.NewCache()
    178 	vm := NewVm(&st, &rs, ca, nil)
    179 
    180 	b := NewLine(nil, MOVE, []string{"foo"}, nil, nil)
    181 	b = NewLine(b, HALT, nil, nil, nil)
    182 	ctx := context.TODO()
    183 	_, err := vm.Run(ctx, b)
    184 	if err == nil {
    185 		t.Fatalf("expected error")
    186 	}
    187 
    188 	b = []byte{0x01, 0x02}
    189 	_, err = vm.Run(ctx, b)
    190 	if err == nil {
    191 		t.Fatalf("no error on invalid opcode")	
    192 	}
    193 }
    194 
    195 func TestRunLoadRender(t *testing.T) {
    196 	st := state.NewState(5)
    197 	rs := NewTestResource(&st)
    198 	ca := cache.NewCache()
    199 	vm := NewVm(&st, &rs, ca, nil)
    200 
    201 	st.Down("bar")
    202 
    203 	var err error
    204 	ctx := context.TODO()
    205 	b := NewLine(nil, LOAD, []string{"one"}, []byte{0x0a}, nil)
    206 	b = NewLine(b, MAP, []string{"one"}, nil, nil)
    207 	b = NewLine(b, LOAD, []string{"two"}, []byte{0x0a}, nil)
    208 	b = NewLine(b, MAP, []string{"two"}, nil, nil)
    209 	b = NewLine(b, HALT, nil, nil, nil)
    210 	b, err = vm.Run(ctx, b)
    211 	if err != nil {
    212 		t.Fatal(err)
    213 	}
    214 	r, err := vm.Render(ctx)
    215 	if err != nil {
    216 		t.Fatal(err)
    217 	}
    218 	expect := "inky pinky one blinky two clyde"
    219 	if r != expect {
    220 		t.Fatalf("Expected\n\t%s\ngot\n\t%s\n", expect, r)
    221 	}
    222 
    223 	b = NewLine(nil, LOAD, []string{"two"}, []byte{0x0a}, nil)
    224 	b = NewLine(b, MAP, []string{"two"}, nil, nil)
    225 	b = NewLine(b, HALT, nil, nil, nil)
    226 	b, err = vm.Run(ctx, b)
    227 	if err != nil {
    228 		t.Fatal(err)
    229 	}
    230 	b = NewLine(nil, MAP, []string{"one"}, nil, nil)
    231 	b = NewLine(b, MAP, []string{"two"}, nil, nil)
    232 	b = NewLine(b, HALT, nil, nil, nil)
    233 	_, err = vm.Run(ctx, b)
    234 	if err != nil {
    235 		t.Fatal(err)
    236 	}
    237 	r, err = vm.Render(ctx)
    238 	if err != nil {
    239 		t.Fatal(err)
    240 	}
    241 	expect = "inky pinky one blinky two clyde"
    242 	if r != expect {
    243 		t.Fatalf("Expected %v, got %v", expect, r)
    244 	}
    245 }
    246 
    247 func TestRunMultiple(t *testing.T) {
    248 	st := state.NewState(5)
    249 	rs := NewTestResource(&st)
    250 	ca := cache.NewCache()
    251 	vm := NewVm(&st, &rs, ca, nil)
    252 
    253 	ctx := context.TODO()
    254 	b := NewLine(nil, MOVE, []string{"test"}, nil, nil)
    255 	b = NewLine(b, LOAD, []string{"one"}, []byte{0x00}, nil)
    256 	b = NewLine(b, LOAD, []string{"two"}, []byte{42}, nil)
    257 	b = NewLine(b, HALT, nil, nil, nil)
    258 	var err error
    259 	b, err = vm.Run(ctx, b)
    260 	if err == nil {
    261 		t.Fatal(err)
    262 	}
    263 }
    264 
    265 func TestRunReload(t *testing.T) {
    266 	st := state.NewState(5)
    267 	rs := NewTestResource(&st)
    268 	ca := cache.NewCache()
    269 	szr := render.NewSizer(128)
    270 	vm := NewVm(&st, &rs, ca, szr)
    271 
    272 	ctx := context.TODO()
    273 	b := NewLine(nil, MOVE, []string{"root"}, nil, nil)
    274 	b = NewLine(b, LOAD, []string{"dyn"}, nil, []uint8{0})
    275 	b = NewLine(b, MAP, []string{"dyn"}, nil, nil)
    276 	b = NewLine(b, HALT, nil, nil, nil)
    277 	_, err := vm.Run(ctx, b)
    278 	if err != nil {
    279 		t.Fatal(err)
    280 	}
    281 	r, err := vm.Render(ctx)
    282 	if err != nil {
    283 		t.Fatal(err)
    284 	}
    285 	if r != "root" {
    286 		t.Fatalf("expected result 'root', got %v", r)
    287 	}
    288 	dynVal = "baz"
    289 	b = NewLine(nil, RELOAD, []string{"dyn"}, nil, nil)
    290 	b = NewLine(b, HALT, nil, nil, nil)
    291 	_, err = vm.Run(ctx, b)
    292 	if err != nil {
    293 		t.Fatal(err)
    294 	}
    295 }
    296 
    297 func TestHalt(t *testing.T) {
    298 	st := state.NewState(5)
    299 	rs := NewTestResource(&st)
    300 	ca := cache.NewCache()
    301 	vm := NewVm(&st, &rs, ca, nil)
    302 
    303 	b := NewLine(nil, MOVE, []string{"root"}, nil, nil)
    304 	b = NewLine(b, LOAD, []string{"one"}, nil, []uint8{0})
    305 	b = NewLine(b, HALT, nil, nil, nil)
    306 	b = NewLine(b, MOVE, []string{"foo"}, nil, nil)
    307 	var err error
    308 	ctx := context.TODO()
    309 	b, err = vm.Run(ctx, b)
    310 	if err != nil {
    311 		t.Error(err)
    312 	}
    313 	r, _ := st.Where()
    314 	if r == "foo" {
    315 		t.Fatalf("Expected where-symbol not to be 'foo'")
    316 	}
    317 	if !bytes.Equal(b[:2], []byte{0x00, MOVE}) {
    318 		t.Fatalf("Expected MOVE instruction, found '%v'", b)
    319 	}
    320 }
    321 
    322 func TestRunArg(t *testing.T) {
    323 	st := state.NewState(5)
    324 	rs := NewTestResource(&st)
    325 	ca := cache.NewCache()
    326 	vm := NewVm(&st, &rs, ca, nil)
    327 
    328 	input := []byte("bar")
    329 	_ = st.SetInput(input)
    330 
    331 	bi := NewLine(nil, INCMP, []string{"baz", "bar"}, nil, nil)
    332 	ctx := context.TODO()
    333 
    334 	var err error
    335 	b, err := vm.Run(ctx, bi)
    336 	if err == nil {
    337 		t.Fatalf("expected error")
    338 	}
    339 	l := len(b)
    340 	if l != 0 {
    341 		t.Fatalf("expected empty remainder, got length %v: %v", l, b)
    342 	}
    343 	r, _ := st.Where()
    344 	if r != "baz" {
    345 		t.Fatalf("expected where-state baz, got %v", r)
    346 	}
    347 }
    348 
    349 func TestRunInputHandler(t *testing.T) {
    350 	st := state.NewState(5)
    351 	rs := NewTestResource(&st)
    352 	ca := cache.NewCache()
    353 	vm := NewVm(&st, &rs, ca, nil)
    354 
    355 	_ = st.SetInput([]byte("baz"))
    356 
    357 	bi := NewLine([]byte{}, INCMP, []string{"aiee", "bar"}, nil, nil)
    358 	bi = NewLine(bi, INCMP, []string{"foo", "baz"}, nil, nil)
    359 	bi = NewLine(bi, LOAD, []string{"one"}, []byte{0x00}, nil)
    360 	bi = NewLine(bi, LOAD, []string{"two"}, []byte{0x03}, nil)
    361 	bi = NewLine(bi, MAP, []string{"one"}, nil, nil)
    362 	bi = NewLine(bi, MAP, []string{"two"}, nil, nil)
    363 	bi = NewLine(bi, HALT, nil, nil, nil)
    364 
    365 	var err error
    366 	ctx := context.TODO()
    367 	_, err = vm.Run(ctx, bi)
    368 	if err == nil {
    369 		t.Fatalf("expected error")
    370 	}
    371 	r, _ := st.Where()
    372 	if r != "foo" {
    373 		t.Fatalf("expected where-sym 'foo', got '%v'", r)
    374 	}
    375 }
    376 
    377 func TestRunArgInvalid(t *testing.T) {
    378 	st := state.NewState(5)
    379 	rs := NewTestResource(&st)
    380 	ca := cache.NewCache()
    381 	vm := NewVm(&st, &rs, ca, nil)
    382 
    383 	_ = st.SetInput([]byte("foo"))
    384 
    385 	var err error
    386 	
    387 	st.Down("root")
    388 	b := NewLine(nil, INCMP, []string{"baz", "bar"}, nil, nil)
    389 
    390 	ctx := context.TODO()
    391 	b, err = vm.Run(ctx, b)
    392 	if err != nil {
    393 		t.Fatal(err)	
    394 	}
    395 	location, _ := st.Where()
    396 	if location != "_catch" {
    397 		t.Fatalf("expected where-state _catch, got %v", location)
    398 	}
    399 
    400 	r, err := vm.Render(ctx)
    401 	if err != nil {
    402 		t.Fatal(err)	
    403 	}
    404 	expect := `invalid input: 'foo'
    405 0:repent`
    406 	if r != expect {
    407 		t.Fatalf("expected:\n\t%s\ngot:\n\t%s", expect, r)
    408 	}
    409 }
    410 
    411 func TestRunMenu(t *testing.T) {
    412 	st := state.NewState(5)
    413 	rs := NewTestResource(&st)
    414 	ca := cache.NewCache()
    415 	vm := NewVm(&st, &rs, ca, nil)
    416 
    417 	var err error
    418 
    419 	ctx := context.TODO()
    420 
    421 	rs.AddBytecode("foo", []byte{})
    422 	b := NewLine(nil, MOVE, []string{"foo"}, nil, nil)
    423 	b = NewLine(b, MOUT, []string{"0", "one"}, nil, nil)
    424 	b = NewLine(b, MOUT, []string{"1", "two"}, nil, nil)
    425 	b = NewLine(b, HALT, nil, nil, nil)
    426 
    427 	b, err = vm.Run(ctx, b)
    428 	if err != nil {
    429 		t.Error(err)	
    430 	}
    431 	l := len(b)
    432 	if l != 0 {
    433 		t.Errorf("expected empty remainder, got length %v: %v", l, b)
    434 	}
    435 	
    436 	r, err := vm.Render(ctx)
    437 	if err != nil {
    438 		t.Fatal(err)
    439 	}
    440 	expect := "inky pinky blinky clyde\n0:one\n1:two"
    441 	if r != expect {
    442 		t.Fatalf("expected:\n\t%s\ngot:\n\t%s\n", expect, r)
    443 	}
    444 }
    445 
    446 func TestRunMenuBrowse(t *testing.T) {
    447 	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.")
    448 	st := state.NewState(5)
    449 	rs := NewTestResource(&st)
    450 	ca := cache.NewCache()
    451 	vm := NewVm(&st, &rs, ca, nil)
    452 
    453 	var err error
    454 
    455 	ctx := context.TODO()
    456 
    457 	rs.AddBytecode("foo", []byte{})
    458 	b := NewLine(nil, MOVE, []string{"foo"}, nil, nil)
    459 	b = NewLine(b, MOUT, []string{"0", "one"}, nil, nil)
    460 	b = NewLine(b, MOUT, []string{"1", "two"}, nil, nil)
    461 	b = NewLine(b, HALT, nil, nil, nil)
    462 
    463 	b, err = vm.Run(ctx, b)
    464 	if err != nil {
    465 		t.Error(err)	
    466 	}
    467 	l := len(b)
    468 	if l != 0 {
    469 		t.Errorf("expected empty remainder, got length %v: %v", l, b)
    470 	}
    471 	
    472 	r, err := vm.Render(ctx)
    473 	if err != nil {
    474 		t.Fatal(err)
    475 	}
    476 	expect := "inky pinky blinky clyde\n0:one\n1:two"
    477 	if r != expect {
    478 		t.Fatalf("expected:\n\t%s\ngot:\n\t%s\n", expect, r)
    479 	}
    480 }
    481 
    482 func TestRunReturn(t *testing.T) {
    483 	st := state.NewState(5)
    484 	rs := NewTestResource(&st)
    485 	ca := cache.NewCache()
    486 	vm := NewVm(&st, &rs, ca, nil)
    487 
    488 	var err error
    489 
    490 	st.Down("root")
    491 	b := NewLine(nil, INCMP, []string{"bar", "0"}, nil, nil)
    492 	b = NewLine(b, INCMP, []string{"_", "1"}, nil, nil)
    493 
    494 	ctx := context.TODO()
    495 
    496 	st.SetInput([]byte("0"))
    497 	b, err = vm.Run(ctx, b)
    498 	if err == nil {
    499 		t.Fatalf("expected error")
    500 	}
    501 	location, _ := st.Where()
    502 	if location != "bar" {
    503 		t.Fatalf("expected location 'bar', got '%s'", location)
    504 	}
    505 
    506 	st.SetInput([]byte("1"))
    507 	b, err = vm.Run(ctx, b)
    508 	if err != nil {
    509 		t.Fatal(err)
    510 	}
    511 	location, _ = st.Where()
    512 	if location != "root" {
    513 		t.Fatalf("expected location 'root', got '%s'", location)
    514 	}
    515 }
    516 
    517 
    518 func TestRunLoadInput(t *testing.T) {
    519 	st := state.NewState(5)
    520 	rs := NewTestResource(&st)
    521 	ca := cache.NewCache()
    522 	vm := NewVm(&st, &rs, ca, nil)
    523 
    524 	var err error
    525 
    526 	st.Down("root")
    527 	st.SetInput([]byte("foobar"))
    528 
    529 	b := NewLine(nil, LOAD, []string{"echo"}, []byte{0x00}, nil)
    530 	b = NewLine(b, HALT, nil, nil, nil)
    531 
    532 	ctx := context.TODO()
    533 
    534 	b, err = vm.Run(ctx, b)
    535 	if err != nil {
    536 		t.Fatal(err)
    537 	}
    538 
    539 	r, err := ca.Get("echo")
    540 	if err != nil {
    541 		t.Fatal(err)
    542 	}
    543 	if r != "echo: foobar" {
    544 		t.Fatalf("expected 'echo: foobar', got %s", r)
    545 	}
    546 }
    547 
    548 func TestInputBranch(t *testing.T) {
    549 	st := state.NewState(5)
    550 	rs := NewTestResource(&st)
    551 	ca := cache.NewCache()
    552 	vm := NewVm(&st, &rs, ca, nil)
    553 
    554 	var err error
    555 
    556 	st.Down("root")
    557 
    558 	b := NewLine(nil, LOAD, []string{"setFlagOne"}, []byte{0x00}, nil)
    559 	b = NewLine(b, RELOAD, []string{"setFlagOne"}, nil, nil)
    560 	b = NewLine(b, CATCH, []string{"flagCatch"}, []byte{8}, []uint8{1})
    561 	b = NewLine(b, CATCH, []string{"one"}, []byte{9}, []uint8{1})
    562 	rs.RootCode = b
    563 	rs.AddBytecode("root", rs.RootCode)
    564 
    565 	ctx := context.TODO()
    566 
    567 	st.SetInput([]byte{0x08})
    568 	b, err = vm.Run(ctx, b)
    569 	if err != nil {
    570 		t.Fatal(err)
    571 	}
    572 	location, _ := st.Where()
    573 	if location != "flagCatch" {
    574 		t.Fatalf("expected 'flagCatch', got %s", location)
    575 	}
    576 
    577 	st.SetInput([]byte{0x09, 0x08})
    578 	b, err = vm.Run(ctx, b)
    579 	if err != nil {
    580 		t.Fatal(err)
    581 	}
    582 	location, _ = st.Where()
    583 	if location != "one" {
    584 		t.Fatalf("expected 'one', got %s", location)
    585 	}
    586 }
    587 
    588 func TestInputIgnore(t *testing.T) {
    589 	st := state.NewState(5)
    590 	rs := NewTestResource(&st)
    591 	ca := cache.NewCache()
    592 	vm := NewVm(&st, &rs, ca, nil)
    593 
    594 	var err error
    595 
    596 	st.Down("root")
    597 
    598 	b := NewLine(nil, INCMP, []string{"one", "foo"}, nil, nil)
    599 	b = NewLine(b, INCMP, []string{"two", "bar"}, nil, nil)
    600 	b = NewLine(b, HALT, nil, nil, nil)
    601 
    602 	ctx := context.TODO()
    603 
    604 	st.SetInput([]byte("foo"))
    605 	b, err = vm.Run(ctx, b)
    606 	if err != nil {
    607 		t.Fatal(err)
    608 	}
    609 
    610 	location, _ := st.Where()
    611 	if location != "one" {
    612 		t.Fatalf("expected 'one', got %s", location)
    613 	}
    614 }
    615 
    616 func TestInputIgnoreWildcard(t *testing.T) {
    617 	st := state.NewState(5)
    618 	rs := NewTestResource(&st)
    619 	ca := cache.NewCache()
    620 	vm := NewVm(&st, &rs, ca, nil)
    621 
    622 	var err error
    623 
    624 	st.Down("root")
    625 
    626 	b := NewLine(nil, INCMP, []string{"one", "foo"}, nil, nil)
    627 	b = NewLine(b, INCMP, []string{"two", "*"}, nil, nil)
    628 
    629 	ctx := context.TODO()
    630 
    631 	st.SetInput([]byte("foo"))
    632 	b, err = vm.Run(ctx, b)
    633 	if err != nil {
    634 		t.Fatal(err)
    635 	}
    636 
    637 	location, _ := st.Where()
    638 	if location != "one" {
    639 		t.Fatalf("expected 'one', got %s", location)
    640 	}
    641 }
    642 
    643 func TestCatchCleanMenu(t *testing.T) {
    644 	st := state.NewState(5)
    645 	rs := NewTestResource(&st)
    646 	ca := cache.NewCache()
    647 	vm := NewVm(&st, &rs, ca, nil)
    648 
    649 	var err error
    650 
    651 	st.Down("root")
    652 
    653 	b := NewLine(nil, MOUT, []string{"1", "one"}, nil, nil)
    654 	b = NewLine(b, MOUT, []string{"2", "two"}, nil, nil)
    655 	b = NewLine(b, HALT, nil, nil, nil)
    656 	b = NewLine(b, INCMP, []string{"foo", "1"}, nil, nil)
    657 	b = NewLine(b, CATCH, []string{"ouf"}, []byte{0x08}, []uint8{0x00})
    658 
    659 	ctx := context.TODO()
    660 
    661 	st.SetInput([]byte("foo"))
    662 	b, err = vm.Run(ctx, b)
    663 	if err != nil {
    664 		t.Fatal(err)
    665 	}
    666 
    667 	st.SetInput([]byte("foo"))
    668 	b, err = vm.Run(ctx, b)
    669 	if err != nil {
    670 		t.Fatal(err)
    671 	}
    672 
    673 	r, err := vm.Render(ctx)
    674 	if err != nil {
    675 		t.Fatal(err)
    676 	}
    677 	fmt.Printf("Result:\n%s", r)
    678 }
    679 
    680 func TestSetLang(t *testing.T) {
    681 	st := state.NewState(0)
    682 	rs := NewTestResource(&st)
    683 	ca := cache.NewCache()
    684 	vm := NewVm(&st, &rs, ca, nil)
    685 
    686 	var err error
    687 
    688 	st.Down("root")
    689 
    690 	st.SetInput([]byte("no"))
    691 	b := NewLine(nil, LOAD, []string{"set_lang"}, []byte{0x01, 0x00}, nil)
    692 	b = NewLine(b, HALT, nil, nil, nil)
    693 
    694 	ctx := context.TODO()
    695 	b, err = vm.Run(ctx, b)
    696 	if err != nil {
    697 		t.Fatal(err)
    698 	}
    699 	lang := *st.Language
    700 	if lang.Code != "nor" {
    701 		t.Fatalf("expected language 'nor',, got %s", lang.Code)
    702 	}
    703 }
    704 
    705 func TestLoadError(t *testing.T) {
    706 	st := state.NewState(0).WithDebug()
    707 	rs := NewTestResource(&st)
    708 	ca := cache.NewCache()
    709 	vm := NewVm(&st, &rs, ca, nil)
    710 
    711 	st.Down("root")
    712 	st.SetInput([]byte{})
    713 	b := NewLine(nil, LOAD, []string{"aiee"}, []byte{0x01, 0x10}, nil)
    714 	b = NewLine(b, HALT, nil, nil, nil)
    715 
    716 	var err error
    717 	ctx := context.TODO()
    718 	b, err = vm.Run(ctx, b)
    719 	if err != nil {
    720 		t.Fatal(err)
    721 	}
    722 
    723 	r, err := vm.Render(ctx)
    724 	if err != nil {
    725 		t.Fatal(err)
    726 	}
    727 	expect := `error aiee:0
    728 0:repent`
    729 	if r != expect {
    730 		t.Fatalf("expected: \n\t%s\ngot:\n\t%s", expect, r)
    731 	}
    732 }