From aa219d1f3d1c77ed43eb1248c39a1c34eeeb02d7 Mon Sep 17 00:00:00 2001 From: sonda2208 Date: Thu, 13 Jun 2019 14:39:40 +0700 Subject: [PATCH] Implement operation on duration type and add tests --- evaluator.go | 60 +++++++++++++++++++++ evaluator_test.go | 130 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 190 insertions(+) diff --git a/evaluator.go b/evaluator.go index 2d61bdd..2486310 100644 --- a/evaluator.go +++ b/evaluator.go @@ -138,6 +138,16 @@ func computeEQ(lhs, rhs Expr) (*BoolLiteral, error) { return &BoolLiteral{Val: (l.Val == dt)}, nil } + case *DurationLiteral: + rv, ok := rhs.(*StringLiteral) + if ok { + v, err := time.ParseDuration(rv.Val) + if err != nil { + return nil, err + } + + return &BoolLiteral{Val: l.Val == v}, nil + } } return nil, fmt.Errorf(`cannot convert "%s" to %s`, rhs.String(), lhs.Type()) @@ -175,6 +185,16 @@ func computeNEQ(lhs, rhs Expr) (*BoolLiteral, error) { return &BoolLiteral{Val: (l.Val != dt)}, nil } + case *DurationLiteral: + rv, ok := rhs.(*StringLiteral) + if ok { + v, err := time.ParseDuration(rv.Val) + if err != nil { + return nil, err + } + + return &BoolLiteral{Val: l.Val != v}, nil + } } return nil, fmt.Errorf(`cannot convert "%s" to %s`, rhs.String(), lhs.Type()) @@ -207,6 +227,16 @@ func computeLT(lhs, rhs Expr) (*BoolLiteral, error) { return &BoolLiteral{Val: l.Val.Before(dt)}, nil } + case *DurationLiteral: + rv, ok := rhs.(*StringLiteral) + if ok { + v, err := time.ParseDuration(rv.Val) + if err != nil { + return nil, err + } + + return &BoolLiteral{Val: l.Val < v}, nil + } } return nil, fmt.Errorf(`cannot convert "%s" to %s`, rhs.String(), lhs.Type()) @@ -239,6 +269,16 @@ func computeLTE(lhs, rhs Expr) (*BoolLiteral, error) { return &BoolLiteral{Val: l.Val.Before(dt)}, nil } + case *DurationLiteral: + rv, ok := rhs.(*StringLiteral) + if ok { + v, err := time.ParseDuration(rv.Val) + if err != nil { + return nil, err + } + + return &BoolLiteral{Val: l.Val <= v}, nil + } } return nil, fmt.Errorf(`cannot convert "%s" to %s`, rhs.String(), lhs.Type()) @@ -271,6 +311,16 @@ func computeGT(lhs, rhs Expr) (*BoolLiteral, error) { return &BoolLiteral{Val: l.Val.After(dt)}, nil } + case *DurationLiteral: + rv, ok := rhs.(*StringLiteral) + if ok { + v, err := time.ParseDuration(rv.Val) + if err != nil { + return nil, err + } + + return &BoolLiteral{Val: l.Val > v}, nil + } } return nil, fmt.Errorf(`cannot convert "%s" to %s`, rhs.String(), lhs.Type()) @@ -303,6 +353,16 @@ func computeGTE(lhs, rhs Expr) (*BoolLiteral, error) { return &BoolLiteral{Val: l.Val.After(dt)}, nil } + case *DurationLiteral: + rv, ok := rhs.(*StringLiteral) + if ok { + v, err := time.ParseDuration(rv.Val) + if err != nil { + return nil, err + } + + return &BoolLiteral{Val: l.Val >= v}, nil + } } return nil, fmt.Errorf(`cannot convert "%s" to %s`, rhs.String(), lhs.Type()) diff --git a/evaluator_test.go b/evaluator_test.go index 866397f..6f01757 100644 --- a/evaluator_test.go +++ b/evaluator_test.go @@ -25,6 +25,15 @@ func TestEvaluator(t *testing.T) { dt, err := time.Parse(time.RFC3339, "2019-03-28T11:39:43+07:00") require.NoError(t, err) + dur2m, err := time.ParseDuration("2m") + require.NoError(t, err) + + dur1m30s, err := time.ParseDuration("1m30s") + require.NoError(t, err) + + dur45s, err := time.ParseDuration("45s") + require.NoError(t, err) + tests := []TestCase{ { `{ "comparator": "||", "rules": [ { "comparator": "&&", "rules": [ { "var": "a", "op": "==", "val": 1 }, { "var": "b", "op": "==", "val": 2 } ] }, { "comparator": "&&", "rules": [ { "var": "c", "op": "==", "val": 3 }, { "var": "d", "op": "==", "val": 4 } ] } ] }`, @@ -342,6 +351,127 @@ func TestEvaluator(t *testing.T) { }, }, }, + { + `{ "var": "a", "op": "==", "val": "1m30s" }`, + []Evaluation{ + { + map[string]interface{}{ + "a": dur2m, + }, + false, + false, + }, + { + map[string]interface{}{ + "a": dur1m30s, + }, + true, + false, + }, + { + map[string]interface{}{ + "a": 1, + }, + false, + true, + }, + }, + }, + { + `{ "var": "a", "op": "!=", "val": "1m30s" }`, + []Evaluation{ + { + map[string]interface{}{ + "a": dur2m, + }, + true, + false, + }, + { + map[string]interface{}{ + "a": dur1m30s, + }, + false, + false, + }, + }, + }, + { + `{ "var": "a", "op": ">", "val": "1m30s" }`, + []Evaluation{ + { + map[string]interface{}{ + "a": dur2m, + }, + true, + false, + }, + { + map[string]interface{}{ + "a": dur1m30s, + }, + false, + false, + }, + }, + }, + { + `{ "var": "a", "op": ">=", "val": "1m30s" }`, + []Evaluation{ + { + map[string]interface{}{ + "a": dur2m, + }, + true, + false, + }, + { + map[string]interface{}{ + "a": dur1m30s, + }, + true, + false, + }, + }, + }, + { + `{ "var": "a", "op": "<", "val": "1m30s" }`, + []Evaluation{ + { + map[string]interface{}{ + "a": dur45s, + }, + true, + false, + }, + { + map[string]interface{}{ + "a": dur2m, + }, + false, + false, + }, + }, + }, + { + `{ "var": "a", "op": "<=", "val": "1m30s" }`, + []Evaluation{ + { + map[string]interface{}{ + "a": dur1m30s, + }, + true, + false, + }, + { + map[string]interface{}{ + "a": dur2m, + }, + false, + false, + }, + }, + }, } for _, test := range tests {