-
Notifications
You must be signed in to change notification settings - Fork 9
/
eval_test.go
125 lines (119 loc) · 2.81 KB
/
eval_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
package ugo_test
import (
"context"
"runtime"
"testing"
"github.com/stretchr/testify/require"
. "github.com/ozanh/ugo"
ugotime "github.com/ozanh/ugo/stdlib/time"
)
func TestEval(t *testing.T) {
type scriptResult struct {
script string
result Object
}
testCases := []struct {
name string
opts CompilerOptions
global Object
args []Object
ctx context.Context
sr []scriptResult
}{
{
name: "simple",
sr: []scriptResult{
{`var a`, Undefined},
{`1`, Int(1)},
{`return 10`, Int(10)},
{`a = 10`, Undefined},
{`return a`, Int(10)},
{`return a*a`, Int(100)},
},
},
{
name: "import",
opts: CompilerOptions{
ModuleMap: NewModuleMap().
AddBuiltinModule("time", ugotime.Module),
},
sr: []scriptResult{
{`time := import("time")`, Undefined},
{`time.Second`, ugotime.Module["Second"]},
{`tmp := time.Second`, Undefined},
{`tmp`, ugotime.Module["Second"]},
{`time.Second = ""`, Undefined},
{`time.Second`, String("")},
{`time.Second = tmp`, Undefined},
{`time.Second`, ugotime.Module["Second"]},
},
},
{
name: "globals",
global: Map{"g": String("test")},
sr: []scriptResult{
{`global g`, Undefined},
{`return g`, String("test")},
{`globals()["g"]`, String("test")},
},
},
{
name: "locals",
args: []Object{Int(1), Int(2)},
sr: []scriptResult{
{`var (a, b, c)`, Undefined},
{`a`, Undefined},
{`b`, Undefined},
{`c`, Undefined},
},
},
{
name: "params",
args: []Object{Int(1), Int(2)},
sr: []scriptResult{
{`param (a, b, c)`, Undefined},
{`a`, Int(1)},
{`b`, Int(2)},
{`c`, Undefined},
},
},
}
for _, tC := range testCases {
t.Run(tC.name, func(t *testing.T) {
eval := NewEval(tC.opts, tC.global, tC.args...)
for _, sr := range tC.sr {
ret, _, err := eval.Run(tC.ctx, []byte(sr.script))
require.NoError(t, err, sr.script)
require.Equal(t, sr.result, ret, sr.script)
}
})
}
// test context
t.Run("context", func(t *testing.T) {
globals := Map{
"Gosched": &Function{
Value: func(args ...Object) (Object, error) {
runtime.Gosched()
return Undefined, nil
},
},
}
eval := NewEval(DefaultCompilerOptions, globals)
ctx, cancel := context.WithCancel(context.Background())
cancel()
ret, bc, err := eval.Run(ctx, []byte(`
global Gosched; Gosched(); foo := "bar"; return foo`))
require.Nilf(t, ret, "return value:%v", ret)
require.Equal(t, context.Canceled, err, err)
require.NotNil(t, bc)
})
// test error
t.Run("parser error", func(t *testing.T) {
eval := NewEval(DefaultCompilerOptions, nil)
ret, bc, err := eval.Run(context.Background(), []byte(`...`))
require.Nil(t, ret)
require.Nil(t, bc)
require.Contains(t, err.Error(),
`Parse Error: expected statement, found '...'`)
})
}