1 package gval
2
3 import (
4 "context"
5 "fmt"
6 "reflect"
7 "strings"
8 "testing"
9 )
10
11 func TestEvaluable_IsConst(t *testing.T) {
12 p := Parser{}
13 tests := []struct {
14 name string
15 e Evaluable
16 want bool
17 }{
18 {
19 "const",
20 p.Const(80.5),
21 true,
22 },
23 {
24 "var",
25 p.Var(),
26 false,
27 },
28 }
29 for _, tt := range tests {
30 t.Run(tt.name, func(t *testing.T) {
31 if got := tt.e.IsConst(); got != tt.want {
32 t.Errorf("Evaluable.IsConst() = %v, want %v", got, tt.want)
33 }
34 })
35 }
36 }
37
38 func TestEvaluable_EvalInt(t *testing.T) {
39 tests := []struct {
40 name string
41 e Evaluable
42 want int
43 wantErr bool
44 }{
45 {
46 "point",
47 constant("5.3"),
48 5,
49 false,
50 },
51 {
52 "number",
53 constant(255.),
54 255,
55 false,
56 },
57 {
58 "error",
59 constant("5.3 cm"),
60 0,
61 true,
62 },
63 }
64 for _, tt := range tests {
65 t.Run(tt.name, func(t *testing.T) {
66 got, err := tt.e.EvalInt(context.Background(), nil)
67 if (err != nil) != tt.wantErr {
68 t.Errorf("Evaluable.EvalInt() error = %v, wantErr %v", err, tt.wantErr)
69 return
70 }
71 if got != tt.want {
72 t.Errorf("Evaluable.EvalInt() = %v, want %v", got, tt.want)
73 }
74 })
75 }
76 }
77
78 func TestEvaluable_EvalFloat64(t *testing.T) {
79 tests := []struct {
80 name string
81 e Evaluable
82 want float64
83 wantErr bool
84 }{
85 {
86 "point",
87 constant("5.3"),
88 5.3,
89 false,
90 },
91 {
92 "number",
93 constant(255.),
94 255,
95 false,
96 },
97 {
98 "error",
99 constant("5.3 cm"),
100 0,
101 true,
102 },
103 }
104 for _, tt := range tests {
105 t.Run(tt.name, func(t *testing.T) {
106 got, err := tt.e.EvalFloat64(context.Background(), nil)
107 if (err != nil) != tt.wantErr {
108 t.Errorf("Evaluable.EvalFloat64() error = %v, wantErr %v", err, tt.wantErr)
109 return
110 }
111 if got != tt.want {
112 t.Errorf("Evaluable.EvalFloat64() = %v, want %v", got, tt.want)
113 }
114 })
115 }
116 }
117
118 type testSelector struct {
119 str string
120 Map map[string]interface{}
121 }
122
123 func (s testSelector) SelectGVal(ctx context.Context, k string) (interface{}, error) {
124 if k == "str" {
125 return s.str, nil
126 }
127
128 if k == "map" {
129 return s.Map, nil
130 }
131
132 if strings.HasPrefix(k, "deep") {
133 return s, nil
134 }
135
136 return nil, fmt.Errorf("unknown-key")
137
138 }
139
140 func TestEvaluable_CustomSelector(t *testing.T) {
141 var (
142 lang = Base()
143 tests = []struct {
144 name string
145 expr string
146 params interface{}
147 want interface{}
148 wantErr bool
149 }{
150 {
151 "unknown",
152 "s.Foo",
153 map[string]interface{}{"s": &testSelector{}},
154 nil,
155 true,
156 },
157 {
158 "field directly",
159 "s.Str",
160 map[string]interface{}{"s": &testSelector{str: "test-value"}},
161 nil,
162 true,
163 },
164 {
165 "field via selector",
166 "s.str",
167 map[string]interface{}{"s": &testSelector{str: "test-value"}},
168 "test-value",
169 false,
170 },
171 {
172 "flat",
173 "str",
174 &testSelector{str: "test-value"},
175 "test-value",
176 false,
177 },
178 {
179 "map field",
180 "s.map.foo",
181 map[string]interface{}{"s": &testSelector{Map: map[string]interface{}{"foo": "bar"}}},
182 "bar",
183 false,
184 },
185 {
186 "crawl to val",
187 "deep.deeper.deepest.str",
188 &testSelector{str: "foo"},
189 "foo",
190 false,
191 },
192 {
193 "crawl to struct",
194 "deep.deeper.deepest",
195 &testSelector{},
196 testSelector{},
197 false,
198 },
199 }
200 )
201
202 for _, tt := range tests {
203 t.Run(tt.name, func(t *testing.T) {
204 got, err := lang.Evaluate(tt.expr, tt.params)
205 if (err != nil) != tt.wantErr {
206 t.Errorf("Evaluable.Evaluate() error = %v, wantErr %v", err, tt.wantErr)
207 return
208 }
209 if !reflect.DeepEqual(got, tt.want) {
210 t.Errorf("Evaluable.Evaluate() = %v, want %v", got, tt.want)
211 }
212 })
213 }
214 }
215
View as plain text