2017-06-26 15:33:07 +02:00
|
|
|
package expressions
|
2017-06-26 14:23:50 +02:00
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
)
|
|
|
|
|
|
|
|
var evaluatorTests = []struct {
|
|
|
|
in string
|
|
|
|
expected interface{}
|
|
|
|
}{
|
2017-06-26 18:51:56 +02:00
|
|
|
// Literals
|
2017-06-28 23:18:48 +02:00
|
|
|
{`12`, 12},
|
|
|
|
{`12.3`, 12.3},
|
|
|
|
{`true`, true},
|
|
|
|
{`false`, false},
|
2017-06-26 18:51:56 +02:00
|
|
|
{`'abc'`, "abc"},
|
|
|
|
{`"abc"`, "abc"},
|
2017-06-26 15:06:55 +02:00
|
|
|
|
|
|
|
// Variables
|
2017-06-28 23:18:48 +02:00
|
|
|
{`n`, 123},
|
2017-06-28 19:53:37 +02:00
|
|
|
|
|
|
|
// Attributes
|
2017-06-28 23:18:48 +02:00
|
|
|
{`obj.a`, "first"},
|
|
|
|
{`obj.b.c`, "d"},
|
|
|
|
{`obj.x`, nil},
|
2017-06-28 19:53:37 +02:00
|
|
|
{`fruits.first`, "apples"},
|
|
|
|
{`fruits.last`, "plums"},
|
|
|
|
{`empty_list.first`, nil},
|
|
|
|
{`empty_list.last`, nil},
|
2017-06-28 20:41:46 +02:00
|
|
|
{`"abc".size`, 3},
|
|
|
|
{`fruits.size`, 4},
|
2017-06-28 19:53:37 +02:00
|
|
|
|
|
|
|
// Indices
|
2017-06-28 23:18:48 +02:00
|
|
|
{`ar[1]`, "second"},
|
|
|
|
{`ar[-1]`, "third"}, // undocumented
|
|
|
|
{`ar[100]`, nil},
|
|
|
|
{`obj[1]`, nil},
|
|
|
|
{`obj.c[0]`, "r"},
|
2017-06-28 19:53:37 +02:00
|
|
|
|
|
|
|
// Expressions
|
2017-06-28 23:18:48 +02:00
|
|
|
{`(n)`, 123},
|
2017-06-26 15:06:55 +02:00
|
|
|
|
|
|
|
// Operators
|
2017-06-28 23:18:48 +02:00
|
|
|
{`1 == 1`, true},
|
|
|
|
{`1 == 2`, false},
|
|
|
|
{`1.0 == 1.0`, true},
|
|
|
|
{`1.0 == 2.0`, false},
|
|
|
|
{`1.0 == 1`, true},
|
|
|
|
{`1 == 1.0`, true},
|
|
|
|
{`"a" == "a"`, true},
|
|
|
|
{`"a" == "b"`, false},
|
|
|
|
|
|
|
|
{`1 != 1`, false},
|
|
|
|
{`1 != 2`, true},
|
|
|
|
{`1.0 != 1.0`, false},
|
|
|
|
{`1 != 1.0`, false},
|
|
|
|
{`1 != 2.0`, true},
|
|
|
|
|
|
|
|
{`1 < 2`, true},
|
|
|
|
{`2 < 1`, false},
|
|
|
|
{`1.0 < 2.0`, true},
|
|
|
|
{`1.0 < 2`, true},
|
|
|
|
{`1 < 2.0`, true},
|
|
|
|
{`1.0 < 2`, true},
|
|
|
|
{`"a" < "a"`, false},
|
|
|
|
{`"a" < "b"`, true},
|
|
|
|
{`"b" < "a"`, false},
|
|
|
|
|
|
|
|
{`1 > 2`, false},
|
|
|
|
{`2 > 1`, true},
|
|
|
|
|
|
|
|
{`1 <= 1`, true},
|
|
|
|
{`1 <= 2`, true},
|
|
|
|
{`2 <= 1`, false},
|
|
|
|
{`"a" <= "a"`, true},
|
|
|
|
{`"a" <= "b"`, true},
|
|
|
|
{`"b" <= "a"`, false},
|
|
|
|
|
|
|
|
{`1 >= 1`, true},
|
|
|
|
{`1 >= 2`, false},
|
|
|
|
{`2 >= 1`, true},
|
|
|
|
|
|
|
|
{`true and false`, false},
|
|
|
|
{`true and true`, true},
|
|
|
|
{`true and true and true`, true},
|
|
|
|
{`false or false`, false},
|
|
|
|
{`false or true`, true},
|
|
|
|
|
|
|
|
{`ar contains "first"`, true},
|
|
|
|
{`ar contains "missing"`, false},
|
2017-06-26 14:23:50 +02:00
|
|
|
}
|
|
|
|
|
2017-06-26 21:36:05 +02:00
|
|
|
var evaluatorTestContext = NewContext(map[string]interface{}{
|
2017-06-27 23:29:50 +02:00
|
|
|
"n": 123,
|
|
|
|
"ar": []string{"first", "second", "third"},
|
2017-06-28 20:41:46 +02:00
|
|
|
"empty_list": []interface{}{},
|
2017-06-27 23:29:50 +02:00
|
|
|
"fruits": []string{"apples", "oranges", "peaches", "plums"},
|
2017-06-26 18:51:56 +02:00
|
|
|
"obj": map[string]interface{}{
|
|
|
|
"a": "first",
|
|
|
|
"b": map[string]interface{}{"c": "d"},
|
|
|
|
"c": []string{"r", "g", "b"},
|
|
|
|
},
|
2017-06-26 21:36:05 +02:00
|
|
|
})
|
2017-06-26 18:51:56 +02:00
|
|
|
|
2017-06-26 14:23:50 +02:00
|
|
|
func TestEvaluator(t *testing.T) {
|
|
|
|
for i, test := range evaluatorTests {
|
|
|
|
t.Run(fmt.Sprint(i), func(t *testing.T) {
|
2017-06-29 13:54:31 +02:00
|
|
|
val, err := EvaluateString(test.in, evaluatorTestContext)
|
2017-06-26 14:23:50 +02:00
|
|
|
require.NoErrorf(t, err, test.in)
|
|
|
|
require.Equalf(t, test.expected, val, test.in)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|