db_test.go (8555B)
1 package engine 2 3 import ( 4 "bytes" 5 "context" 6 "fmt" 7 "io" 8 "os" 9 "strings" 10 "testing" 11 12 "git.defalsify.org/vise.git/resource" 13 "git.defalsify.org/vise.git/persist" 14 "git.defalsify.org/vise.git/state" 15 "git.defalsify.org/vise.git/cache" 16 "git.defalsify.org/vise.git/vm" 17 memdb "git.defalsify.org/vise.git/db/mem" 18 ) 19 20 func getNull() io.WriteCloser { 21 nul, err := os.OpenFile(os.DevNull, os.O_WRONLY, 0700) 22 if err != nil { 23 panic(err) 24 } 25 return nul 26 } 27 28 func codeGet(ctx context.Context, s string) ([]byte, error) { 29 var b []byte 30 var err error 31 switch s { 32 case "root": 33 b = vm.NewLine(nil, vm.HALT, nil, nil, nil) 34 b = vm.NewLine(b, vm.LOAD, []string{"foo"}, []byte{0x0}, nil) 35 case "tinkywinky": 36 b = vm.NewLine(nil, vm.MOVE, []string{"dipsy"}, nil, nil) 37 b = vm.NewLine(b, vm.LOAD, []string{"foo"}, []byte{0x0}, nil) 38 case "dipsy": 39 b = vm.NewLine(nil, vm.HALT, nil, nil, nil) 40 b = vm.NewLine(b, vm.LOAD, []string{"foo"}, []byte{0x0}, nil) 41 default: 42 err = fmt.Errorf("unknown code symbol '%s'", s) 43 } 44 return b, err 45 } 46 47 func flagSet(ctx context.Context, nodeSym string, input []byte) (resource.Result, error) { 48 return resource.Result{ 49 Content: "xyzzy", 50 FlagSet: []uint32{state.FLAG_USERSTART}, 51 }, nil 52 } 53 54 func TestDbEngineMinimal(t *testing.T) { 55 ctx := context.Background() 56 cfg := Config{} 57 rs := resource.NewMenuResource() 58 en := NewEngine(cfg, rs) 59 //cont, err := en.Init(ctx) 60 cont, err := en.Exec(ctx, []byte{}) 61 if err != nil { 62 t.Fatal(err) 63 } 64 if cont { 65 t.Fatalf("expected not continue") 66 } 67 err = en.Finish() 68 if err != nil { 69 t.Fatal(err) 70 } 71 } 72 73 func TestDbEngineNoResource(t *testing.T) { 74 cfg := Config{} 75 defer func() { 76 if r := recover(); r == nil { 77 t.Fatal("did not panic") 78 } 79 }() 80 NewEngine(cfg, nil) 81 } 82 83 func TestDbEngineStateNil(t *testing.T) { 84 cfg := Config{} 85 rs := resource.NewMenuResource() 86 defer func() { 87 if r := recover(); r == nil { 88 t.Fatal("did not panic") 89 } 90 }() 91 NewEngine(cfg, rs).WithState(nil) 92 } 93 94 func TestDbEngineCacheNil(t *testing.T) { 95 cfg := Config{} 96 rs := resource.NewMenuResource() 97 defer func() { 98 if r := recover(); r == nil { 99 t.Fatal("did not panic") 100 } 101 }() 102 NewEngine(cfg, rs).WithMemory(nil) 103 } 104 105 func TestDbEnginePersisterNil(t *testing.T) { 106 cfg := Config{} 107 rs := resource.NewMenuResource() 108 defer func() { 109 if r := recover(); r == nil { 110 t.Fatal("did not panic") 111 } 112 }() 113 NewEngine(cfg, rs).WithPersister(nil) 114 } 115 116 func TestDbEngineFirstNil(t *testing.T) { 117 cfg := Config{} 118 rs := resource.NewMenuResource() 119 defer func() { 120 if r := recover(); r == nil { 121 t.Fatal("did not panic") 122 } 123 }() 124 NewEngine(cfg, rs).WithFirst(nil) 125 } 126 127 func TestDbEngineStateDup(t *testing.T) { 128 cfg := Config{} 129 rs := resource.NewMenuResource() 130 st := state.NewState(0) 131 en := NewEngine(cfg, rs).WithState(st) 132 defer func() { 133 if r := recover(); r == nil { 134 t.Fatal("did not panic") 135 } 136 }() 137 en.WithState(st) 138 } 139 140 141 func TestDbEngineCacheDup(t *testing.T) { 142 cfg := Config{} 143 rs := resource.NewMenuResource() 144 ca := cache.NewCache() 145 en := NewEngine(cfg, rs).WithMemory(ca) 146 defer func() { 147 if r := recover(); r == nil { 148 t.Fatal("did not panic") 149 } 150 }() 151 en.WithMemory(ca) 152 } 153 154 func TestDbEnginePersisterDup(t *testing.T) { 155 ctx := context.Background() 156 cfg := Config{} 157 rs := resource.NewMenuResource() 158 store := memdb.NewMemDb() 159 store.Connect(ctx, "") 160 pe := persist.NewPersister(store) 161 en := NewEngine(cfg, rs).WithPersister(pe) 162 defer func() { 163 if r := recover(); r == nil { 164 t.Fatal("did not panic") 165 } 166 }() 167 en.WithPersister(pe) 168 } 169 170 func TestDbEngineFirstDup(t *testing.T) { 171 cfg := Config{} 172 rs := resource.NewMenuResource() 173 en := NewEngine(cfg, rs).WithFirst(flagSet) 174 defer func() { 175 if r := recover(); r == nil { 176 t.Fatal("did not panic") 177 } 178 }() 179 en.WithFirst(flagSet) 180 } 181 182 func TestDbEngineRoot(t *testing.T) { 183 nul := getNull() 184 defer nul.Close() 185 ctx := context.Background() 186 cfg := Config{} 187 rs := resource.NewMenuResource() 188 rs.WithCodeGetter(codeGet) 189 en := NewEngine(cfg, rs) 190 //cont, err := en.Init(ctx) 191 cont, err := en.Exec(ctx, []byte{}) 192 if err != nil { 193 t.Fatal(err) 194 } 195 if !cont { 196 t.Fatalf("expected continue") 197 } 198 199 cont, err = en.Exec(ctx, []byte{0x30}) 200 if err == nil { 201 t.Fatalf("expected loadfail") 202 } 203 204 cont, err = en.Exec(ctx, []byte{0x30}) 205 if err == nil { 206 t.Fatalf("expected nocode") 207 } 208 err = en.Finish() 209 if err != nil { 210 t.Fatal(err) 211 } 212 } 213 214 func TestDbEnginePersist(t *testing.T) { 215 nul := getNull() 216 defer nul.Close() 217 ctx := context.Background() 218 cfg := Config{ 219 FlagCount: 1, 220 SessionId: "bar", 221 } 222 store := memdb.NewMemDb() 223 store.Connect(ctx, "") 224 pe := persist.NewPersister(store) 225 rs := resource.NewMenuResource() 226 rs.WithCodeGetter(codeGet) 227 rs.AddLocalFunc("foo", flagSet) 228 en := NewEngine(cfg, rs) 229 en = en.WithPersister(pe) 230 //cont, err := en.Init(ctx) 231 cont, err := en.Exec(ctx, []byte{}) 232 if err != nil { 233 t.Fatal(err) 234 } 235 if !cont { 236 t.Fatalf("expected continue") 237 } 238 239 cont, err = en.Exec(ctx, []byte{0x30}) 240 if err != nil { 241 t.Fatal(err) 242 } 243 244 _, err = en.Flush(ctx, nul) 245 if err != nil { 246 t.Fatal(err) 247 } 248 err = en.Finish() 249 if err != nil { 250 t.Fatal(err) 251 } 252 253 en = NewEngine(cfg, rs) 254 pe = persist.NewPersister(store) 255 en = NewEngine(cfg, rs) 256 en = en.WithPersister(pe) 257 cont, err = en.Exec(ctx, []byte{}) 258 if err != nil { 259 t.Fatal(err) 260 } 261 stn := pe.GetState() 262 if !stn.MatchFlag(state.FLAG_USERSTART, true) { 263 t.Fatalf("expected userstart set, have state %v", stn) 264 } 265 } 266 267 func TestDbEngineDebug(t *testing.T) { 268 w := bytes.NewBuffer(nil) 269 ctx := context.Background() 270 cfg := Config{ 271 Root: "tinkywinky", 272 FlagCount: 1, 273 } 274 rs := resource.NewMenuResource() 275 rs = rs.WithCodeGetter(codeGet) 276 rs.AddLocalFunc("foo", flagSet) 277 dbg := NewSimpleDebug(w) 278 en := NewEngine(cfg, rs).WithDebug(dbg) 279 //c, err := en.Init(ctx) 280 c, err := en.Exec(ctx, []byte{}) 281 if err != nil { 282 t.Fatal(err) 283 } 284 if !c { 285 t.Fatal("expected true") 286 } 287 if len(w.Bytes()) == 0 { 288 t.Fatal("expected non-empty debug") 289 } 290 } 291 292 func TestDbConfigString(t *testing.T) { 293 cfg := Config{ 294 Root: "tinkywinky", 295 } 296 s := cfg.String() 297 if !strings.Contains(s, "tinky") { 298 t.Fatalf("expected contains 'tinky', got: '%s'", s) 299 } 300 } 301 302 func TestDbEnsure(t *testing.T) { 303 var err error 304 var cfg Config 305 ctx := context.Background() 306 rs := resource.NewMenuResource() 307 store := memdb.NewMemDb() 308 store.Connect(ctx, "") 309 pe := persist.NewPersister(store) 310 en := NewEngine(cfg, rs).WithPersister(pe) 311 //_, err = en.Init(ctx) 312 _, err = en.Exec(ctx, []byte{}) 313 if err != nil { 314 t.Fatal(err) 315 } 316 if pe.GetState() == nil { 317 t.Fatal("expected persister state") 318 } 319 if pe.GetMemory() == nil { 320 t.Fatal("expected persister memory") 321 } 322 } 323 324 func TestDbKeepPersisterContent(t *testing.T) { 325 var err error 326 var cfg Config 327 ctx := context.Background() 328 rs := resource.NewMenuResource() 329 st := state.NewState(0) 330 ca := cache.NewCache() 331 store := memdb.NewMemDb() 332 store.Connect(ctx, "") 333 pe := persist.NewPersister(store) 334 pe = pe.WithContent(st, ca) 335 en := NewEngine(cfg, rs).WithPersister(pe) 336 //_, err = en.Init(ctx) 337 _, err = en.Exec(ctx, []byte{}) 338 if err != nil { 339 t.Fatal(err) 340 } 341 pest := pe.GetState() 342 if pest != st { 343 t.Fatalf("expected persisted state %p same as engine %p", pest, st) 344 } 345 peca := pe.GetMemory() 346 if peca != ca { 347 t.Fatalf("expected persisted cache %p same as engine %p", peca, st) 348 } 349 } 350 351 func TestDbKeepState(t *testing.T) { 352 var err error 353 var cfg Config 354 ctx := context.Background() 355 rs := resource.NewMenuResource() 356 st := state.NewState(0) 357 ca := cache.NewCache() 358 store := memdb.NewMemDb() 359 store.Connect(ctx, "") 360 pe := persist.NewPersister(store) 361 en := NewEngine(cfg, rs) 362 en = en.WithState(st) 363 en = en.WithMemory(ca) 364 en = en.WithPersister(pe) 365 //_, err = en.Init(ctx) 366 _, err = en.Exec(ctx, []byte{}) 367 if err != nil { 368 t.Fatal(err) 369 } 370 pest := pe.GetState() 371 if pest != st { 372 t.Fatalf("expected persisted state %p same as engine preset %p", pest, st) 373 } 374 peca := pe.GetMemory() 375 if peca != ca { 376 t.Fatalf("expected persisted cache %p same as engine preset %p", peca, st) 377 } 378 } 379 380 func TestDbFirst(t *testing.T) { 381 var err error 382 var cfg Config 383 ctx := context.Background() 384 rs := resource.NewMenuResource() 385 st := state.NewState(1) 386 store := memdb.NewMemDb() 387 store.Connect(ctx, "") 388 389 v := st.GetFlag(state.FLAG_USERSTART) 390 if v { 391 t.Fatal("expected flag unset") 392 } 393 en := NewEngine(cfg, rs) 394 en = en.WithState(st) 395 en = en.WithFirst(flagSet) 396 //_, err = en.Init(ctx) 397 _, err = en.Exec(ctx, []byte{}) 398 if err != nil { 399 t.Fatal(err) 400 } 401 v = st.GetFlag(state.FLAG_USERSTART) 402 if !v { 403 t.Fatal("expected flag set") 404 } 405 } 406