go-vise

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

engine_test.go (11246B)


      1 package engine
      2 
      3 import (
      4 	"bytes"
      5 	"context"
      6 	"fmt"
      7 
      8 	//	"io/ioutil"
      9 	"log"
     10 	//	"path"
     11 	"testing"
     12 
     13 	"git.defalsify.org/vise.git/cache"
     14 	"git.defalsify.org/vise.git/db"
     15 	fsdb "git.defalsify.org/vise.git/db/fs"
     16 	"git.defalsify.org/vise.git/lang"
     17 	"git.defalsify.org/vise.git/resource"
     18 	"git.defalsify.org/vise.git/state"
     19 	"git.defalsify.org/vise.git/testdata"
     20 	"git.defalsify.org/vise.git/vm"
     21 )
     22 
     23 var (
     24 	dataGenerated bool   = false
     25 	dataDir       string = testdata.DataDir
     26 )
     27 
     28 type testWrapper struct {
     29 	resource.Resource
     30 	st *state.State
     31 	db db.Db
     32 }
     33 
     34 func newTestWrapper(path string, st *state.State) testWrapper {
     35 	ctx := context.Background()
     36 	store := fsdb.NewFsDb()
     37 	store.Connect(ctx, path)
     38 	rs := resource.NewDbResource(store)
     39 	rs.With(db.DATATYPE_STATICLOAD)
     40 	wr := testWrapper{
     41 		rs,
     42 		st,
     43 		store,
     44 	}
     45 	rs.AddLocalFunc("one", wr.one)
     46 	rs.AddLocalFunc("inky", wr.inky)
     47 	rs.AddLocalFunc("pinky", wr.pinky)
     48 	rs.AddLocalFunc("set_lang", wr.set_lang)
     49 	rs.AddLocalFunc("translate", wr.translate)
     50 	rs.AddLocalFunc("quit", quitFunc)
     51 	return wr
     52 }
     53 
     54 func (fs testWrapper) getStore() db.Db {
     55 	return fs.db
     56 }
     57 
     58 func (fs testWrapper) one(ctx context.Context, sym string, input []byte) (resource.Result, error) {
     59 	return resource.Result{
     60 		Content: "one",
     61 	}, nil
     62 }
     63 
     64 func (fs testWrapper) inky(ctx context.Context, sym string, input []byte) (resource.Result, error) {
     65 	return resource.Result{
     66 		Content: "tinkywinky",
     67 	}, nil
     68 }
     69 
     70 func (fs testWrapper) pinky(ctx context.Context, sym string, input []byte) (resource.Result, error) {
     71 	r := fmt.Sprintf("xyzzy: %x", input)
     72 	return resource.Result{
     73 		Content: r,
     74 	}, nil
     75 }
     76 
     77 func (fs testWrapper) translate(ctx context.Context, sym string, input []byte) (resource.Result, error) {
     78 	r := "cool"
     79 	v := ctx.Value("Language")
     80 	code := ""
     81 	lang, ok := v.(lang.Language)
     82 	if ok {
     83 		code = lang.Code
     84 	}
     85 	if code == "nor" {
     86 		r = "fett"
     87 	}
     88 	return resource.Result{
     89 		Content: r,
     90 	}, nil
     91 }
     92 
     93 func (fs testWrapper) set_lang(ctx context.Context, sym string, input []byte) (resource.Result, error) {
     94 	return resource.Result{
     95 		Content: string(input),
     96 		FlagSet: []uint32{state.FLAG_LANG},
     97 	}, nil
     98 }
     99 
    100 //func(fs testWrapper) GetCode(ctx context.Context, sym string) ([]byte, error) {
    101 //	sym += ".bin"
    102 //	fp := path.Join(fs.Path, sym)
    103 //	r, err := ioutil.ReadFile(fp)
    104 //	return r, err
    105 //}
    106 
    107 func generateTestData(t *testing.T) {
    108 	if dataGenerated {
    109 		return
    110 	}
    111 	var err error
    112 	dataDir, err = testdata.Generate()
    113 	if err != nil {
    114 		t.Fatal(err)
    115 	}
    116 }
    117 
    118 func quitFunc(ctx context.Context, sym string, input []byte) (resource.Result, error) {
    119 	return resource.Result{
    120 		Content: "these aren't the droids you are looking for",
    121 	}, nil
    122 }
    123 
    124 func TestEngineInit(t *testing.T) {
    125 	var err error
    126 	generateTestData(t)
    127 	ctx := context.Background()
    128 	st := state.NewState(17)
    129 	rs := newTestWrapper(dataDir, st)
    130 	ca := cache.NewCache().WithCacheSize(1024)
    131 
    132 	cfg := Config{
    133 		Root: "root",
    134 	}
    135 	en := NewEngine(cfg, &rs)
    136 	en = en.WithState(st)
    137 	en = en.WithMemory(ca)
    138 
    139 	//_, err = en.Init(ctx)
    140 	_, err = en.Exec(ctx, []byte{})
    141 	if err != nil {
    142 		t.Fatal(err)
    143 	}
    144 	w := bytes.NewBuffer(nil)
    145 	_, err = en.Flush(ctx, w)
    146 	if err != nil {
    147 		t.Fatal(err)
    148 	}
    149 	b := w.Bytes()
    150 	expect_str := `hello world
    151 1:do the foo
    152 2:go to the bar
    153 3:language template`
    154 
    155 	if !bytes.Equal(b, []byte(expect_str)) {
    156 		t.Fatalf("expected:\n\t%s\ngot:\n\t%s\n", expect_str, b)
    157 	}
    158 
    159 	input := []byte("1")
    160 	_, err = en.Exec(ctx, input)
    161 	if err != nil {
    162 		t.Fatal(err)
    163 	}
    164 	r, _ := st.Where()
    165 	if r != "foo" {
    166 		t.Fatalf("expected where-string 'foo', got %s", r)
    167 	}
    168 	w = bytes.NewBuffer(nil)
    169 	_, err = en.Flush(ctx, w)
    170 	if err != nil {
    171 		t.Fatal(err)
    172 	}
    173 	b = w.Bytes()
    174 	expect := `this is in foo
    175 
    176 it has more lines
    177 0:to foo
    178 1:go bar
    179 2:see long`
    180 
    181 	if !bytes.Equal(b, []byte(expect)) {
    182 		t.Fatalf("expected\n\t%s\ngot:\n\t%s\n", expect, b)
    183 	}
    184 }
    185 
    186 func TestEngineExecInvalidInput(t *testing.T) {
    187 	generateTestData(t)
    188 	ctx := context.Background()
    189 	st := state.NewState(17)
    190 	rs := newTestWrapper(dataDir, st)
    191 	ca := cache.NewCache().WithCacheSize(1024)
    192 
    193 	cfg := Config{
    194 		Root: "root",
    195 	}
    196 	en := NewEngine(cfg, &rs)
    197 	en = en.WithState(st)
    198 	en = en.WithMemory(ca)
    199 	var err error
    200 	//_, err = en.Init(ctx)
    201 	_, err = en.Exec(ctx, []byte{})
    202 	if err != nil {
    203 		t.Fatal(err)
    204 	}
    205 	_, err = en.Exec(ctx, []byte("_foo"))
    206 	if err == nil {
    207 		t.Fatalf("expected fail on invalid input")
    208 	}
    209 }
    210 
    211 func TestEngineResumeTerminated(t *testing.T) {
    212 	generateTestData(t)
    213 	ctx := context.Background()
    214 	st := state.NewState(17)
    215 	rs := newTestWrapper(dataDir, st)
    216 	ca := cache.NewCache().WithCacheSize(1024)
    217 
    218 	cfg := Config{
    219 		Root: "root",
    220 	}
    221 	en := NewEngine(cfg, &rs)
    222 	en = en.WithState(st)
    223 	en = en.WithMemory(ca)
    224 	var err error
    225 	//_, err = en.Init(ctx)
    226 	_, err = en.Exec(ctx, []byte{})
    227 	if err != nil {
    228 		t.Fatal(err)
    229 	}
    230 
    231 	_, err = en.Exec(ctx, []byte("1"))
    232 	if err != nil {
    233 		t.Fatal(err)
    234 	}
    235 
    236 	_, err = en.Exec(ctx, []byte("1"))
    237 	if err != nil {
    238 		t.Fatal(err)
    239 	}
    240 
    241 	location, idx := st.Where()
    242 	if location != "baz" {
    243 		t.Fatalf("expected 'baz', got %s", location)
    244 	}
    245 	if idx != 0 {
    246 		t.Fatalf("expected idx '0', got %v", idx)
    247 	}
    248 }
    249 
    250 func TestLanguageSet(t *testing.T) {
    251 	generateTestData(t)
    252 	ctx := context.Background()
    253 	st := state.NewState(0)
    254 	rs := newTestWrapper(dataDir, st)
    255 	ca := cache.NewCache().WithCacheSize(1024)
    256 
    257 	cfg := Config{
    258 		Root: "root",
    259 	}
    260 	en := NewEngine(cfg, &rs)
    261 	en = en.WithState(st)
    262 	en = en.WithMemory(ca)
    263 
    264 	var err error
    265 	//_, err = en.Init(ctx)
    266 	_, err = en.Exec(ctx, []byte{})
    267 	if err != nil {
    268 		t.Fatal(err)
    269 	}
    270 
    271 	b := vm.NewLine(nil, vm.LOAD, []string{"translate"}, []byte{0x01, 0xff}, nil)
    272 	b = vm.NewLine(b, vm.LOAD, []string{"set_lang"}, []byte{0x01, 0x00}, nil)
    273 	b = vm.NewLine(b, vm.MOVE, []string{"."}, nil, nil)
    274 	st.SetCode(b)
    275 
    276 	_, err = en.Exec(ctx, []byte("no"))
    277 	if err != nil {
    278 		t.Fatal(err)
    279 	}
    280 	r, err := ca.Get("translate")
    281 	if err != nil {
    282 		t.Fatal(err)
    283 	}
    284 	if r != "cool" {
    285 		t.Fatalf("expected 'cool', got '%s'", r)
    286 	}
    287 
    288 	b = vm.NewLine(nil, vm.RELOAD, []string{"translate"}, nil, nil)
    289 	b = vm.NewLine(b, vm.MOVE, []string{"."}, nil, nil)
    290 	st.SetCode(b)
    291 
    292 	_, err = en.Exec(ctx, []byte("no"))
    293 	if err != nil {
    294 		t.Fatal(err)
    295 	}
    296 	r, err = ca.Get("translate")
    297 	if err != nil {
    298 		t.Fatal(err)
    299 	}
    300 	if r != "fett" {
    301 		t.Fatalf("expected 'fett', got '%s'", r)
    302 	}
    303 }
    304 
    305 func TestLanguageRender(t *testing.T) {
    306 	generateTestData(t)
    307 	ctx := context.Background()
    308 	st := state.NewState(0)
    309 	rs := newTestWrapper(dataDir, st)
    310 	ca := cache.NewCache()
    311 
    312 	cfg := Config{
    313 		Root: "root",
    314 	}
    315 	en := NewEngine(cfg, &rs)
    316 	en = en.WithState(st)
    317 	en = en.WithMemory(ca)
    318 
    319 	var err error
    320 	//_, err = en.Init(ctx)
    321 	_, err = en.Exec(ctx, []byte{})
    322 	if err != nil {
    323 		t.Fatal(err)
    324 	}
    325 
    326 	b := vm.NewLine(nil, vm.LOAD, []string{"set_lang"}, []byte{0x01, 0x00}, nil)
    327 	b = vm.NewLine(b, vm.MOVE, []string{"lang"}, nil, nil)
    328 	st.SetCode(b)
    329 
    330 	_, err = en.Exec(ctx, []byte("nor"))
    331 	if err != nil {
    332 		t.Fatal(err)
    333 	}
    334 
    335 	br := bytes.NewBuffer(nil)
    336 	_, err = en.Flush(ctx, br)
    337 	if err != nil {
    338 		t.Fatal(err)
    339 	}
    340 	expect := "dette endrer"
    341 	r := br.String()
    342 	if r[:len(expect)] != expect {
    343 		t.Fatalf("expected %s, got %s", expect, r[:len(expect)])
    344 	}
    345 
    346 }
    347 
    348 func TestConfigLanguageRender(t *testing.T) {
    349 	generateTestData(t)
    350 	ctx := context.Background()
    351 	st := state.NewState(0)
    352 	rs := newTestWrapper(dataDir, st)
    353 	ca := cache.NewCache()
    354 
    355 	cfg := Config{
    356 		Root:     "root",
    357 		Language: "nor",
    358 	}
    359 	en := NewEngine(cfg, &rs)
    360 	en = en.WithState(st)
    361 	en = en.WithMemory(ca)
    362 
    363 	var err error
    364 	//_, err = en.Init(ctx)
    365 	_, err = en.Exec(ctx, []byte{})
    366 	if err != nil {
    367 		t.Fatal(err)
    368 	}
    369 
    370 	b := vm.NewLine(nil, vm.LOAD, []string{"set_lang"}, []byte{0x01, 0x00}, nil)
    371 	b = vm.NewLine(b, vm.MOVE, []string{"lang"}, nil, nil)
    372 	st.SetCode(b)
    373 
    374 	_, err = en.Exec(ctx, []byte("foo"))
    375 	if err != nil {
    376 		t.Fatal(err)
    377 	}
    378 	br := bytes.NewBuffer(nil)
    379 	_, err = en.Flush(ctx, br)
    380 	if err != nil {
    381 		t.Fatal(err)
    382 	}
    383 
    384 	expect := `dette endrer med språket tinkywinky
    385 0:tilbake`
    386 	r := br.String()
    387 	if r != expect {
    388 		t.Fatalf("expected:\n\t%s\ngot:\n\t%s", expect, r)
    389 	}
    390 }
    391 
    392 func preBlock(ctx context.Context, sym string, input []byte) (resource.Result, error) {
    393 	log.Printf("executing preBlock")
    394 	return resource.Result{
    395 		Content: "None shall pass",
    396 		FlagSet: []uint32{state.FLAG_TERMINATE},
    397 	}, nil
    398 }
    399 
    400 func preAllow(ctx context.Context, sym string, input []byte) (resource.Result, error) {
    401 	log.Printf("executing preAllow")
    402 	return resource.Result{}, nil
    403 }
    404 
    405 func TestPreVm(t *testing.T) {
    406 	var b []byte
    407 	var out *bytes.Buffer
    408 	generateTestData(t)
    409 	ctx := context.Background()
    410 	st := state.NewState(0)
    411 	st.UseDebug()
    412 	rs := newTestWrapper(dataDir, st)
    413 	ca := cache.NewCache()
    414 
    415 	cfg := Config{
    416 		Root: "root",
    417 	}
    418 	en := NewEngine(cfg, &rs)
    419 	en = en.WithState(st)
    420 	en = en.WithMemory(ca)
    421 	en = en.WithFirst(preBlock)
    422 	//r, err := en.Init(ctx)
    423 	r, err := en.Exec(ctx, []byte{})
    424 	if err != nil {
    425 		t.Fatal(err)
    426 	}
    427 	if r {
    428 		t.Fatalf("expected init to return 'not continue'")
    429 	}
    430 	out = bytes.NewBuffer(b)
    431 	_, err = en.Flush(ctx, out)
    432 	if err != nil {
    433 		t.Fatal(err)
    434 	}
    435 	if !bytes.Equal(out.Bytes(), []byte("None shall pass")) {
    436 		t.Fatalf("expected writeresult 'None shall pass', got %s", out)
    437 	}
    438 
    439 	st = state.NewState(0)
    440 	ca = cache.NewCache()
    441 	en = NewEngine(cfg, &rs)
    442 	en = en.WithState(st)
    443 	en = en.WithMemory(ca)
    444 	en = en.WithFirst(preAllow)
    445 	//r, err = en.Init(ctx)
    446 	r, err = en.Exec(ctx, []byte{})
    447 	if err != nil {
    448 		t.Fatal(err)
    449 	}
    450 	if !r {
    451 		t.Fatalf("expected init to return 'continue'")
    452 	}
    453 }
    454 
    455 func TestManyQuits(t *testing.T) {
    456 	b := bytes.NewBuffer(nil)
    457 	ctx := context.Background()
    458 	st := state.NewState(0)
    459 	st.UseDebug()
    460 	generateTestData(t)
    461 	rs := newTestWrapper(dataDir, st)
    462 	ca := cache.NewCache()
    463 
    464 	cfg := Config{
    465 		Root: "nothing",
    466 	}
    467 
    468 	en := NewEngine(cfg, rs)
    469 	en = en.WithState(st)
    470 	en = en.WithMemory(ca)
    471 	r, err := en.Exec(ctx, []byte{})
    472 	if err != nil {
    473 		t.Fatal(err)
    474 	}
    475 	if r {
    476 		t.Fatalf("expected init to return 'not continue'")
    477 	}
    478 	_, err = en.Flush(ctx, b)
    479 	if err != nil {
    480 		t.Fatal(err)
    481 	}
    482 
    483 	en = NewEngine(cfg, rs)
    484 	en = en.WithState(st)
    485 	en = en.WithMemory(ca)
    486 	r, err = en.Exec(ctx, []byte{})
    487 	if err != nil {
    488 		t.Fatal(err)
    489 	}
    490 	if r {
    491 		t.Fatalf("expected init to return 'not continue'")
    492 	}
    493 	_, err = en.Flush(ctx, b)
    494 	if err != nil {
    495 		t.Fatal(err)
    496 	}
    497 
    498 	en = NewEngine(cfg, rs)
    499 	en = en.WithState(st)
    500 	en = en.WithMemory(ca)
    501 	r, err = en.Exec(ctx, []byte{})
    502 	if err != nil {
    503 		t.Fatal(err)
    504 	}
    505 	if r {
    506 		t.Fatalf("expected init to return 'not continue'")
    507 	}
    508 
    509 	b = bytes.NewBuffer(nil)
    510 	_, err = en.Flush(ctx, b)
    511 	if err != nil {
    512 		t.Fatal(err)
    513 	}
    514 	x := "these aren't the droids you are looking for"
    515 	if !bytes.Equal(b.Bytes(), []byte(x)) {
    516 		t.Fatalf("expected '%s', got '%s'", x, b.Bytes())
    517 	}
    518 }
    519 
    520 func TestOutEmpty(t *testing.T) {
    521 	ctx := context.Background()
    522 	st := state.NewState(0)
    523 	st.UseDebug()
    524 	generateTestData(t)
    525 	rs := newTestWrapper(dataDir, st)
    526 	ca := cache.NewCache()
    527 
    528 	cfg := Config{
    529 		Root: "something",
    530 	}
    531 
    532 	en := NewEngine(cfg, rs)
    533 	en = en.WithState(st)
    534 	en = en.WithMemory(ca)
    535 	r, err := en.Exec(ctx, []byte{})
    536 	if err != nil {
    537 		t.Fatal(err)
    538 	}
    539 	if r {
    540 		t.Fatalf("expected init to return 'not continue'")
    541 	}
    542 
    543 	v := bytes.NewBuffer(nil)
    544 	en.Flush(ctx, v)
    545 	x := "mmmm, something..."
    546 	if !bytes.Equal(v.Bytes(), []byte(x)) {
    547 		t.Fatalf("expected '%s', got '%s'", x, v.Bytes())
    548 	}
    549 }