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 }