src.elv.sh@v0.21.0-dev.0.20240515223629-06979efb9a2a/pkg/eval/eval_test.go (about) 1 package eval_test 2 3 import ( 4 "sync" 5 "testing" 6 7 . "src.elv.sh/pkg/eval" 8 9 "src.elv.sh/pkg/eval/vars" 10 "src.elv.sh/pkg/parse" 11 ) 12 13 func TestEval_AlternativeGlobal(t *testing.T) { 14 ev := NewEvaler() 15 g := BuildNs().AddVar("a", vars.NewReadOnly("")).Ns() 16 err := ev.Eval(parse.Source{Name: "[test]", Code: "nop $a"}, EvalCfg{Global: g}) 17 if err != nil { 18 t.Errorf("got error %v, want nil", err) 19 } 20 // Regression test for #1223 21 if ev.Global().HasKeyString("a") { 22 t.Errorf("$a from alternative global leaked into Evaler global") 23 } 24 } 25 26 func TestEval_Concurrent(t *testing.T) { 27 ev := NewEvaler() 28 29 var wg sync.WaitGroup 30 wg.Add(2) 31 go func() { 32 ev.Eval(parse.Source{Name: "[test]", Code: "var a"}, EvalCfg{}) 33 wg.Done() 34 }() 35 go func() { 36 ev.Eval(parse.Source{Name: "[test]", Code: "var b"}, EvalCfg{}) 37 wg.Done() 38 }() 39 wg.Wait() 40 g := ev.Global() 41 if !g.HasKeyString("a") { 42 t.Errorf("variable $a not created") 43 } 44 if !g.HasKeyString("b") { 45 t.Errorf("variable $b not created") 46 } 47 } 48 49 type fooOpts struct{ Opt string } 50 51 func (*fooOpts) SetDefaultOptions() {} 52 53 func TestCall(t *testing.T) { 54 ev := NewEvaler() 55 var gotOpt, gotArg string 56 fn := NewGoFn("foo", func(fm *Frame, opts fooOpts, arg string) { 57 gotOpt = opts.Opt 58 gotArg = arg 59 }) 60 61 passedArg := "arg value" 62 passedOpt := "opt value" 63 ev.Call(fn, 64 CallCfg{ 65 Args: []any{passedArg}, 66 Opts: map[string]any{"opt": passedOpt}, 67 From: "[TestCall]"}, 68 EvalCfg{}) 69 70 if gotArg != passedArg { 71 t.Errorf("got arg %q, want %q", gotArg, passedArg) 72 } 73 if gotOpt != passedOpt { 74 t.Errorf("got opt %q, want %q", gotOpt, passedOpt) 75 } 76 } 77 78 var checkTests = []struct { 79 name string 80 code string 81 wantParseErr bool 82 wantCompileErr bool 83 }{ 84 {name: "no error", code: "put $nil"}, 85 {name: "parse error only", code: "put [", 86 wantParseErr: true}, 87 {name: "compile error only", code: "put $x", 88 wantCompileErr: true}, 89 {name: "both parse and compile error", code: "put [$x", 90 wantParseErr: true, wantCompileErr: true}, 91 } 92 93 func TestCheck(t *testing.T) { 94 ev := NewEvaler() 95 for _, test := range checkTests { 96 t.Run(test.name, func(t *testing.T) { 97 parseErr, _, compileErr := ev.Check(parse.Source{Name: "[test]", Code: test.code}, nil) 98 if (parseErr != nil) != test.wantParseErr { 99 t.Errorf("got parse error %v, when wantParseErr = %v", 100 parseErr, test.wantParseErr) 101 } 102 if (compileErr != nil) != test.wantCompileErr { 103 t.Errorf("got compile error %v, when wantCompileErr = %v", 104 compileErr, test.wantCompileErr) 105 } 106 }) 107 } 108 }