go-vise

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

engine_test.go (7000B)


      1 package engine
      2 
      3 import (
      4 	"bytes"
      5 	"context"
      6 	"fmt"
      7 	"io/ioutil"
      8 	"path"
      9 	"testing"
     10 
     11 	"git.defalsify.org/vise.git/cache"
     12 	"git.defalsify.org/vise.git/lang"
     13 	"git.defalsify.org/vise.git/resource"
     14 	"git.defalsify.org/vise.git/state"
     15 	"git.defalsify.org/vise.git/testdata"
     16 	"git.defalsify.org/vise.git/vm"
     17 )
     18 
     19 var (
     20 	dataGenerated bool = false
     21 	dataDir string = testdata.DataDir
     22 )
     23 
     24 type FsWrapper struct {
     25 	*resource.FsResource
     26 	st *state.State
     27 }
     28 
     29 func NewFsWrapper(path string, st *state.State) FsWrapper {
     30 	rs := resource.NewFsResource(path)
     31 	wr := FsWrapper {
     32 		rs, 
     33 		st,
     34 	}
     35 	wr.AddLocalFunc("one", wr.one)
     36 	//wr.AddLocalFunc("inky", wr.inky)
     37 	wr.AddLocalFunc("pinky", wr.pinky)
     38 	wr.AddLocalFunc("set_lang", wr.set_lang)
     39 	wr.AddLocalFunc("translate", wr.translate)
     40 	return wr
     41 }
     42 
     43 func(fs FsWrapper) one(ctx context.Context, sym string, input []byte) (resource.Result, error) {
     44 	return resource.Result{
     45 		Content: "one",
     46 	}, nil
     47 }
     48 
     49 func(fs FsWrapper) inky(ctx context.Context, sym string, input []byte) (resource.Result, error) {
     50 	return resource.Result{
     51 		Content: "tinkywinky",
     52 	}, nil
     53 }
     54 
     55 func(fs FsWrapper) pinky(ctx context.Context, sym string, input []byte) (resource.Result, error) {
     56 	r := fmt.Sprintf("xyzzy: %x", input)
     57 	return resource.Result{
     58 		Content: r,
     59 	}, nil
     60 }
     61 
     62 func(fs FsWrapper) translate(ctx context.Context, sym string, input []byte) (resource.Result, error) {
     63 	r := "cool"
     64 	v := ctx.Value("Language")
     65 	code := ""
     66 	lang, ok := v.(lang.Language)
     67 	if ok {
     68 		code = lang.Code
     69 	}
     70 	if code == "nor" {
     71 		r = "fett"
     72 	}
     73 	return resource.Result{
     74 		Content: r,
     75 	}, nil
     76 }
     77 
     78 func(fs FsWrapper) set_lang(ctx context.Context, sym string, input []byte) (resource.Result, error) {
     79 	return resource.Result{
     80 		Content: string(input),
     81 		FlagSet: []uint32{state.FLAG_LANG},
     82 	}, nil
     83 }
     84 
     85 func(fs FsWrapper) GetCode(sym string) ([]byte, error) {
     86 	sym += ".bin"
     87 	fp := path.Join(fs.Path, sym)
     88 	r, err := ioutil.ReadFile(fp)
     89 	return r, err
     90 }
     91 
     92 func generateTestData(t *testing.T) {
     93 	if dataGenerated {
     94 		return
     95 	}
     96 	var err error
     97 	dataDir, err = testdata.Generate()
     98 	if err != nil {
     99 		t.Fatal(err)
    100 	}
    101 }
    102 
    103 func TestEngineInit(t *testing.T) {
    104 	var err error
    105 	generateTestData(t)
    106 	ctx := context.TODO()
    107 	st := state.NewState(17)
    108 	rs := NewFsWrapper(dataDir, &st)
    109 	ca := cache.NewCache().WithCacheSize(1024)
    110 
    111 	cfg := Config{
    112 		Root: "root",
    113 	}
    114 	en := NewEngine(ctx, cfg, &st, &rs, ca)
    115 
    116 	_, err = en.Init(ctx)
    117 	if err != nil {
    118 		t.Fatal(err)
    119 	}
    120 	w := bytes.NewBuffer(nil)
    121 	_, err = en.WriteResult(ctx, w)
    122 	if err != nil {
    123 		t.Fatal(err)
    124 	}
    125 	b := w.Bytes()
    126 	expect_str := `hello world
    127 1:do the foo
    128 2:go to the bar
    129 3:language template`
    130 
    131 	if !bytes.Equal(b, []byte(expect_str)) {
    132 		t.Fatalf("expected:\n\t%s\ngot:\n\t%s\n", expect_str, b)
    133 	}
    134 
    135 	input := []byte("1")
    136 	_, err = en.Exec(ctx, input)
    137 	if err != nil {
    138 		t.Fatal(err)
    139 	}
    140 	r, _ := st.Where()
    141 	if r != "foo" {
    142 		t.Fatalf("expected where-string 'foo', got %s", r)
    143 	}
    144 	w = bytes.NewBuffer(nil)
    145 	_, err = en.WriteResult(ctx, w)
    146 	if err != nil {
    147 		t.Fatal(err)
    148 	}
    149 	b = w.Bytes()
    150 	expect := `this is in foo
    151 
    152 it has more lines
    153 0:to foo
    154 1:go bar
    155 2:see long`
    156 
    157 	if !bytes.Equal(b, []byte(expect)) {
    158 		t.Fatalf("expected\n\t%s\ngot:\n\t%s\n", expect, b)
    159 	}
    160 }
    161 
    162 func TestEngineExecInvalidInput(t *testing.T) {
    163 	generateTestData(t)
    164 	ctx := context.TODO()
    165 	st := state.NewState(17)
    166 	rs := NewFsWrapper(dataDir, &st)
    167 	ca := cache.NewCache().WithCacheSize(1024)
    168 
    169 	cfg := Config{
    170 		Root: "root",
    171 	}	
    172 	en := NewEngine(ctx, cfg, &st, &rs, ca)
    173 	var err error
    174 	_, err = en.Init(ctx)
    175 	if err != nil {
    176 		t.Fatal(err)
    177 	}
    178 	_, err = en.Exec(ctx, []byte("_foo"))
    179 	if err == nil {
    180 		t.Fatalf("expected fail on invalid input")
    181 	}
    182 }
    183 
    184 func TestEngineResumeTerminated(t *testing.T) {
    185 	generateTestData(t)
    186 	ctx := context.TODO()
    187 	st := state.NewState(17)
    188 	rs := NewFsWrapper(dataDir, &st)
    189 	ca := cache.NewCache().WithCacheSize(1024)
    190 	
    191 	cfg := Config{
    192 		Root: "root",
    193 	}
    194 	en := NewEngine(ctx, cfg, &st, &rs, ca)
    195 	var err error
    196 	_, err = en.Init(ctx)
    197 	if err != nil {
    198 		t.Fatal(err)
    199 	}
    200 
    201 	_, err = en.Exec(ctx, []byte("1"))
    202 	if err != nil {
    203 		t.Fatal(err)
    204 	}
    205 
    206 	_, err = en.Exec(ctx, []byte("1"))
    207 	if err != nil {
    208 		t.Fatal(err)
    209 	}
    210 
    211 	location, idx := st.Where()
    212 	if location != "root" {
    213 		t.Fatalf("expected 'root', got %s", location)
    214 	}
    215 	if idx != 0 {
    216 		t.Fatalf("expected idx '0', got %v", idx)
    217 	}
    218 }
    219 
    220 func TestLanguageSet(t *testing.T) {
    221 	generateTestData(t)
    222 	ctx := context.TODO()
    223 	st := state.NewState(0)
    224 	rs := NewFsWrapper(dataDir, &st)
    225 	ca := cache.NewCache().WithCacheSize(1024)
    226 
    227 	cfg := Config{
    228 		Root: "root",
    229 	}
    230 	en := NewEngine(ctx, cfg, &st, &rs, ca)
    231 
    232 	var err error
    233 	_, err = en.Init(ctx)
    234 	if err != nil {
    235 		t.Fatal(err)
    236 	}
    237 
    238 	b := vm.NewLine(nil, vm.LOAD, []string{"translate"}, []byte{0x01, 0xff}, nil)
    239 	b = vm.NewLine(b, vm.LOAD, []string{"set_lang"}, []byte{0x01, 0x00}, nil)
    240 	b = vm.NewLine(b, vm.MOVE, []string{"."}, nil, nil)
    241 	st.SetCode(b)
    242 
    243 	_, err = en.Exec(ctx, []byte("no"))
    244 	if err != nil {
    245 		t.Fatal(err)
    246 	}
    247 	r, err := ca.Get("translate")
    248 	if err != nil {
    249 		t.Fatal(err)
    250 	}
    251 	if r != "cool" {
    252 		t.Fatalf("expected 'cool', got '%s'", r)
    253 	}
    254 
    255 
    256 	b = vm.NewLine(nil, vm.RELOAD, []string{"translate"}, nil, nil)
    257 	b = vm.NewLine(b, vm.MOVE, []string{"."}, nil, nil)
    258 	st.SetCode(b)
    259 
    260 	_, err = en.Exec(ctx, []byte("no"))
    261 	if err != nil {
    262 		t.Fatal(err)
    263 	}
    264 	r, err = ca.Get("translate")
    265 	if err != nil {
    266 		t.Fatal(err)
    267 	}
    268 	if r != "fett" {
    269 		t.Fatalf("expected 'fett', got '%s'", r)
    270 	}
    271 }
    272 
    273 func TestLanguageRender(t *testing.T) {
    274 	generateTestData(t)
    275 	ctx := context.TODO()
    276 	st := state.NewState(0)
    277 	rs := NewFsWrapper(dataDir, &st)
    278 	ca := cache.NewCache()
    279 
    280 	cfg := Config{
    281 		Root: "root",
    282 	}
    283 	en := NewEngine(ctx, cfg, &st, &rs, ca)
    284 
    285 	var err error
    286 	_, err = en.Init(ctx)
    287 	if err != nil {
    288 		t.Fatal(err)
    289 	}
    290 
    291 	b := vm.NewLine(nil, vm.LOAD, []string{"set_lang"}, []byte{0x01, 0x00}, nil)
    292 	b = vm.NewLine(b, vm.MOVE, []string{"lang"}, nil, nil)
    293 	st.SetCode(b)
    294 
    295 	_, err = en.Exec(ctx, []byte("nor"))
    296 	if err != nil {
    297 		t.Fatal(err)
    298 	}
    299 	
    300 	br := bytes.NewBuffer(nil)
    301 	_, err = en.WriteResult(ctx, br)
    302 	if err != nil {
    303 		t.Fatal(err)
    304 	}
    305 	expect := "dette endrer"
    306 	r := br.String()
    307 	if r[:len(expect)] != expect {
    308 		t.Fatalf("expected %s, got %s", expect, r[:len(expect)])
    309 	}
    310 
    311 }
    312 
    313 func TestConfigLanguageRender(t *testing.T) {
    314 	generateTestData(t)
    315 	ctx := context.TODO()
    316 	st := state.NewState(0)
    317 	rs := NewFsWrapper(dataDir, &st)
    318 	ca := cache.NewCache()
    319 
    320 	cfg := Config{
    321 		Root: "root",
    322 		Language: "nor",
    323 	}
    324 	en := NewEngine(ctx, cfg, &st, &rs, ca)
    325 
    326 	var err error
    327 	_, err = en.Init(ctx)
    328 	if err != nil {
    329 		t.Fatal(err)
    330 	}
    331 
    332 	b := vm.NewLine(nil, vm.LOAD, []string{"set_lang"}, []byte{0x01, 0x00}, nil)
    333 	b = vm.NewLine(b, vm.MOVE, []string{"lang"}, nil, nil)
    334 	st.SetCode(b)
    335 
    336 	_, err = en.Exec(ctx, []byte("foo"))
    337 	if err != nil {
    338 		t.Fatal(err)
    339 	}
    340 	br := bytes.NewBuffer(nil)
    341 	_, err = en.WriteResult(ctx, br)
    342 	if err != nil {
    343 		t.Fatal(err)
    344 	}
    345 	
    346 	expect := `dette endrer med språket one
    347 0:tilbake`
    348 	r := br.String()
    349 	if r != expect {
    350 		t.Fatalf("expected:\n\t%s\ngot:\n\t%s", expect, r)
    351 	}
    352 }