Best Syzkaller code snippet using ast.less
expr_test.go
Source:expr_test.go
1package stateful_test2import (3 "errors"4 "fmt"5 "regexp"6 "testing"7 "time"8 "github.com/influxdata/kapacitor/tick/ast"9 "github.com/influxdata/kapacitor/tick/stateful"10)11type keyStruct struct {12 lhs interface{}13 rhs interface{}14 op ast.TokenType15}16func TestExpression_EvalNum_KeepsFunctionsState(t *testing.T) {17 se := mustCompileExpression(&ast.FunctionNode{18 Func: "sigma",19 Args: []ast.Node{&ast.ReferenceNode{Reference: "value"}},20 })21 // first22 scope := stateful.NewScope()23 scope.Set("value", float64(97.1))24 result, err := se.Eval(scope)25 if err != nil {26 t.Errorf("First: Got unexpected error: %v", err)27 }28 if result != float64(0) {29 t.Errorf("First: expected count to be math.NaN() but got %v", result)30 }31 // second32 scope.Set("value", float64(92.6))33 result, err = se.Eval(scope)34 if err != nil {35 t.Errorf("Second: Got unexpected error: %v", err)36 }37 if result != float64(0.7071067811865476) {38 t.Errorf("Second: expected count to be float64(0.7071067811865476) but got %v", result)39 }40}41func TestExpression_EvalBool_BinaryNodeWithDurationNode(t *testing.T) {42 leftValues := []interface{}{time.Duration(5), time.Duration(10)}43 rightValues := []interface{}{time.Duration(5), time.Duration(10), int64(5)}44 operators := []ast.TokenType{ast.TokenEqual, ast.TokenNotEqual, ast.TokenGreater, ast.TokenGreaterEqual, ast.TokenLessEqual, ast.TokenLess, ast.TokenOr}45 createNode := func(v interface{}) ast.Node {46 switch value := v.(type) {47 case time.Duration:48 return &ast.DurationNode{49 Dur: value,50 }51 // For the error case52 case int64:53 return &ast.NumberNode{54 IsInt: true,55 Int64: value,56 }57 default:58 panic(fmt.Sprintf("unexpected type time.Duration/int64: %T", v))59 }60 }61 runCompiledEvalBoolTests(t, createNode, leftValues, rightValues, operators, map[keyStruct]interface{}{62 // Left is float64(5), Right is float64(5)63 keyStruct{time.Duration(5), time.Duration(5), ast.TokenEqual}: true,64 keyStruct{time.Duration(5), time.Duration(5), ast.TokenNotEqual}: false,65 keyStruct{time.Duration(5), time.Duration(5), ast.TokenGreater}: false,66 keyStruct{time.Duration(5), time.Duration(5), ast.TokenGreaterEqual}: true,67 keyStruct{time.Duration(5), time.Duration(5), ast.TokenLess}: false,68 keyStruct{time.Duration(5), time.Duration(5), ast.TokenLessEqual}: true,69 // Left is time.Duration(5), Right is time.Duration(10)70 keyStruct{time.Duration(5), time.Duration(10), ast.TokenEqual}: false,71 keyStruct{time.Duration(5), time.Duration(10), ast.TokenNotEqual}: true,72 keyStruct{time.Duration(5), time.Duration(10), ast.TokenGreater}: false,73 keyStruct{time.Duration(5), time.Duration(10), ast.TokenGreaterEqual}: false,74 keyStruct{time.Duration(5), time.Duration(10), ast.TokenLess}: true,75 keyStruct{time.Duration(5), time.Duration(10), ast.TokenLessEqual}: true,76 // Left is time.Duration(10), Right is time.Duration(5)77 keyStruct{time.Duration(10), time.Duration(5), ast.TokenEqual}: false,78 keyStruct{time.Duration(10), time.Duration(5), ast.TokenNotEqual}: true,79 keyStruct{time.Duration(10), time.Duration(5), ast.TokenGreater}: true,80 keyStruct{time.Duration(10), time.Duration(5), ast.TokenGreaterEqual}: true,81 keyStruct{time.Duration(10), time.Duration(5), ast.TokenLess}: false,82 keyStruct{time.Duration(10), time.Duration(5), ast.TokenLessEqual}: false,83 // Left is time.Duration(10), Right is time.Duration(10)84 keyStruct{time.Duration(10), time.Duration(10), ast.TokenEqual}: true,85 keyStruct{time.Duration(10), time.Duration(10), ast.TokenNotEqual}: false,86 keyStruct{time.Duration(10), time.Duration(10), ast.TokenGreater}: false,87 keyStruct{time.Duration(10), time.Duration(10), ast.TokenGreaterEqual}: true,88 keyStruct{time.Duration(10), time.Duration(10), ast.TokenLess}: false,89 keyStruct{time.Duration(10), time.Duration(10), ast.TokenLessEqual}: true,90 }, map[keyStruct]error{91 // Invalid operator92 keyStruct{time.Duration(5), time.Duration(5), ast.TokenOr}: errors.New("invalid logical operator OR for type duration"),93 keyStruct{time.Duration(5), time.Duration(10), ast.TokenOr}: errors.New("invalid logical operator OR for type duration"),94 keyStruct{time.Duration(5), int64(5), ast.TokenOr}: errors.New("invalid logical operator OR for type duration"),95 keyStruct{time.Duration(10), time.Duration(5), ast.TokenOr}: errors.New("invalid logical operator OR for type duration"),96 keyStruct{time.Duration(10), time.Duration(10), ast.TokenOr}: errors.New("invalid logical operator OR for type duration"),97 keyStruct{time.Duration(10), int64(5), ast.TokenOr}: errors.New("invalid logical operator OR for type duration"),98 keyStruct{int64(5), time.Duration(5), ast.TokenOr}: errors.New("invalid logical operator OR for type int"),99 keyStruct{int64(5), time.Duration(10), ast.TokenOr}: errors.New("invalid logical operator OR for type int"),100 keyStruct{int64(5), int64(5), ast.TokenOr}: errors.New("invalid logical operator OR for type int"),101 // (Redundant case)102 keyStruct{time.Duration(5), int64(5), ast.TokenOr}: errors.New("invalid logical operator OR for type duration"),103 keyStruct{time.Duration(10), int64(5), ast.TokenOr}: errors.New("invalid logical operator OR for type duration"),104 keyStruct{int64(5), int64(5), ast.TokenOr}: errors.New("invalid logical operator OR for type int"),105 // Left is time.Duration(5), Right is int64(5)106 keyStruct{time.Duration(5), int64(5), ast.TokenEqual}: errors.New("mismatched type to binary operator. got duration == int. see bool(), int(), float(), string(), duration()"),107 keyStruct{time.Duration(5), int64(5), ast.TokenNotEqual}: errors.New("mismatched type to binary operator. got duration != int. see bool(), int(), float(), string(), duration()"),108 keyStruct{time.Duration(5), int64(5), ast.TokenGreater}: errors.New("mismatched type to binary operator. got duration > int. see bool(), int(), float(), string(), duration()"),109 keyStruct{time.Duration(5), int64(5), ast.TokenGreaterEqual}: errors.New("mismatched type to binary operator. got duration >= int. see bool(), int(), float(), string(), duration()"),110 keyStruct{time.Duration(5), int64(5), ast.TokenLess}: errors.New("mismatched type to binary operator. got duration < int. see bool(), int(), float(), string(), duration()"),111 keyStruct{time.Duration(5), int64(5), ast.TokenLessEqual}: errors.New("mismatched type to binary operator. got duration <= int. see bool(), int(), float(), string(), duration()"),112 // (Redundant case) Left is time.Duration(10), Right is int64(5)113 keyStruct{time.Duration(10), int64(5), ast.TokenEqual}: errors.New("mismatched type to binary operator. got duration == int. see bool(), int(), float(), string(), duration()"),114 keyStruct{time.Duration(10), int64(5), ast.TokenNotEqual}: errors.New("mismatched type to binary operator. got duration != int. see bool(), int(), float(), string(), duration()"),115 keyStruct{time.Duration(10), int64(5), ast.TokenGreater}: errors.New("mismatched type to binary operator. got duration > int. see bool(), int(), float(), string(), duration()"),116 keyStruct{time.Duration(10), int64(5), ast.TokenGreaterEqual}: errors.New("mismatched type to binary operator. got duration >= int. see bool(), int(), float(), string(), duration()"),117 keyStruct{time.Duration(10), int64(5), ast.TokenLess}: errors.New("mismatched type to binary operator. got duration < int. see bool(), int(), float(), string(), duration()"),118 keyStruct{time.Duration(10), int64(5), ast.TokenLessEqual}: errors.New("mismatched type to binary operator. got duration <= int. see bool(), int(), float(), string(), duration()"),119 })120}121func TestExpression_EvalDuration(t *testing.T) {122 leftValues := []interface{}{time.Duration(5), time.Duration(10), int64(2), float64(1.5)}123 rightValues := []interface{}{time.Duration(5), time.Duration(10), int64(2), float64(1.5)}124 operators := []ast.TokenType{125 ast.TokenPlus,126 ast.TokenMinus,127 ast.TokenMult,128 ast.TokenDiv,129 ast.TokenMod,130 }131 createNode := func(v interface{}) ast.Node {132 switch value := v.(type) {133 case time.Duration:134 return &ast.DurationNode{135 Dur: value,136 }137 case float64:138 return &ast.NumberNode{139 IsFloat: true,140 Float64: value,141 }142 case int64:143 return &ast.NumberNode{144 IsInt: true,145 Int64: value,146 }147 default:148 panic(fmt.Sprintf("unexpected type time.Duration/int64: %T", v))149 }150 }151 runCompiledNumericTests(t, createNode, leftValues, rightValues, operators, map[keyStruct]interface{}{152 // Left is time.Duration(5), Right is time.Duration(5)153 keyStruct{time.Duration(5), time.Duration(5), ast.TokenPlus}: time.Duration(10),154 keyStruct{time.Duration(5), time.Duration(5), ast.TokenMinus}: time.Duration(0),155 keyStruct{time.Duration(5), time.Duration(5), ast.TokenDiv}: int64(1),156 // Left is time.Duration(5), Right is time.Duration(10)157 keyStruct{time.Duration(5), time.Duration(10), ast.TokenPlus}: time.Duration(15),158 keyStruct{time.Duration(5), time.Duration(10), ast.TokenMinus}: time.Duration(-5),159 keyStruct{time.Duration(5), time.Duration(10), ast.TokenDiv}: int64(0),160 // Left is time.Duration(5), Right is int64(2)161 keyStruct{time.Duration(5), int64(2), ast.TokenMult}: time.Duration(10),162 keyStruct{time.Duration(5), int64(2), ast.TokenDiv}: time.Duration(2),163 // Left is time.Duration(5), Right is float64(1.5)164 keyStruct{time.Duration(5), float64(1.5), ast.TokenMult}: time.Duration(7),165 keyStruct{time.Duration(5), float64(1.5), ast.TokenDiv}: time.Duration(3),166 // Left is time.Duration(10), Right is time.Duration(5)167 keyStruct{time.Duration(10), time.Duration(5), ast.TokenPlus}: time.Duration(15),168 keyStruct{time.Duration(10), time.Duration(5), ast.TokenMinus}: time.Duration(5),169 keyStruct{time.Duration(10), time.Duration(5), ast.TokenDiv}: int64(2),170 // Left is time.Duration(10), Right is time.Duration(10)171 keyStruct{time.Duration(10), time.Duration(10), ast.TokenPlus}: time.Duration(20),172 keyStruct{time.Duration(10), time.Duration(10), ast.TokenMinus}: time.Duration(0),173 keyStruct{time.Duration(10), time.Duration(10), ast.TokenDiv}: int64(1),174 // Left is time.Duration(10), Right is int64(2)175 keyStruct{time.Duration(10), int64(2), ast.TokenMult}: time.Duration(20),176 keyStruct{time.Duration(10), int64(2), ast.TokenDiv}: time.Duration(5),177 // Left is time.Duration(10), Right is float64(1.5)178 keyStruct{time.Duration(10), float64(1.5), ast.TokenMult}: time.Duration(15),179 keyStruct{time.Duration(10), float64(1.5), ast.TokenDiv}: time.Duration(6),180 // Left is int64(2)181 keyStruct{int64(2), time.Duration(5), ast.TokenMult}: time.Duration(10),182 keyStruct{int64(2), time.Duration(10), ast.TokenMult}: time.Duration(20),183 // Left is float64(1.5)184 keyStruct{float64(1.5), time.Duration(5), ast.TokenMult}: time.Duration(7),185 keyStruct{float64(1.5), time.Duration(10), ast.TokenMult}: time.Duration(15),186 // Non duration related but still valid187 keyStruct{int64(2), int64(2), ast.TokenPlus}: int64(4),188 keyStruct{int64(2), int64(2), ast.TokenMinus}: int64(0),189 keyStruct{int64(2), int64(2), ast.TokenMult}: int64(4),190 keyStruct{int64(2), int64(2), ast.TokenDiv}: int64(1),191 keyStruct{int64(2), int64(2), ast.TokenMod}: int64(0),192 keyStruct{float64(1.5), float64(1.5), ast.TokenPlus}: float64(3),193 keyStruct{float64(1.5), float64(1.5), ast.TokenMinus}: float64(0),194 keyStruct{float64(1.5), float64(1.5), ast.TokenMult}: float64(1.5 * 1.5),195 keyStruct{float64(1.5), float64(1.5), ast.TokenDiv}: float64(1),196 }, map[keyStruct]error{197 // Modulo token where left is float198 keyStruct{time.Duration(5), time.Duration(5), ast.TokenMod}: errors.New("invalid math operator % for type duration"),199 keyStruct{time.Duration(5), time.Duration(10), ast.TokenMod}: errors.New("invalid math operator % for type duration"),200 keyStruct{time.Duration(5), int64(2), ast.TokenMod}: errors.New("invalid math operator % for type duration"),201 keyStruct{time.Duration(5), float64(1.5), ast.TokenMod}: errors.New("invalid math operator % for type duration"),202 keyStruct{time.Duration(10), time.Duration(5), ast.TokenMod}: errors.New("invalid math operator % for type duration"),203 keyStruct{time.Duration(10), time.Duration(10), ast.TokenMod}: errors.New("invalid math operator % for type duration"),204 keyStruct{time.Duration(10), int64(2), ast.TokenMod}: errors.New("invalid math operator % for type duration"),205 keyStruct{time.Duration(10), float64(1.5), ast.TokenMod}: errors.New("invalid math operator % for type duration"),206 // Muiltiply Divide durations207 keyStruct{time.Duration(5), time.Duration(5), ast.TokenMult}: errors.New("mismatched type to binary operator. got duration * duration. see bool(), int(), float(), string(), duration()"),208 keyStruct{time.Duration(5), time.Duration(10), ast.TokenMult}: errors.New("mismatched type to binary operator. got duration * duration. see bool(), int(), float(), string(), duration()"),209 keyStruct{time.Duration(10), time.Duration(10), ast.TokenMult}: errors.New("mismatched type to binary operator. got duration * duration. see bool(), int(), float(), string(), duration()"),210 keyStruct{time.Duration(10), time.Duration(5), ast.TokenMult}: errors.New("mismatched type to binary operator. got duration * duration. see bool(), int(), float(), string(), duration()"),211 // Add/Subtract duration with int/float212 keyStruct{time.Duration(5), int64(2), ast.TokenPlus}: errors.New("mismatched type to binary operator. got duration + int. see bool(), int(), float(), string(), duration()"),213 keyStruct{time.Duration(5), int64(2), ast.TokenMinus}: errors.New("mismatched type to binary operator. got duration - int. see bool(), int(), float(), string(), duration()"),214 keyStruct{time.Duration(5), float64(1.5), ast.TokenPlus}: errors.New("mismatched type to binary operator. got duration + float. see bool(), int(), float(), string(), duration()"),215 keyStruct{time.Duration(5), float64(1.5), ast.TokenMinus}: errors.New("mismatched type to binary operator. got duration - float. see bool(), int(), float(), string(), duration()"),216 keyStruct{int64(2), time.Duration(5), ast.TokenPlus}: errors.New("mismatched type to binary operator. got int + duration. see bool(), int(), float(), string(), duration()"),217 keyStruct{int64(2), time.Duration(5), ast.TokenMinus}: errors.New("mismatched type to binary operator. got int - duration. see bool(), int(), float(), string(), duration()"),218 keyStruct{int64(2), time.Duration(10), ast.TokenPlus}: errors.New("mismatched type to binary operator. got int + duration. see bool(), int(), float(), string(), duration()"),219 keyStruct{int64(2), time.Duration(10), ast.TokenMinus}: errors.New("mismatched type to binary operator. got int - duration. see bool(), int(), float(), string(), duration()"),220 keyStruct{float64(1.5), time.Duration(5), ast.TokenPlus}: errors.New("mismatched type to binary operator. got float + duration. see bool(), int(), float(), string(), duration()"),221 keyStruct{float64(1.5), time.Duration(5), ast.TokenMinus}: errors.New("mismatched type to binary operator. got float - duration. see bool(), int(), float(), string(), duration()"),222 keyStruct{float64(1.5), time.Duration(10), ast.TokenPlus}: errors.New("mismatched type to binary operator. got float + duration. see bool(), int(), float(), string(), duration()"),223 keyStruct{float64(1.5), time.Duration(10), ast.TokenMinus}: errors.New("mismatched type to binary operator. got float - duration. see bool(), int(), float(), string(), duration()"),224 // int / duration225 keyStruct{int64(2), time.Duration(5), ast.TokenDiv}: errors.New("mismatched type to binary operator. got int / duration. see bool(), int(), float(), string(), duration()"),226 keyStruct{int64(2), time.Duration(10), ast.TokenDiv}: errors.New("mismatched type to binary operator. got int / duration. see bool(), int(), float(), string(), duration()"),227 keyStruct{float64(1.5), time.Duration(5), ast.TokenDiv}: errors.New("mismatched type to binary operator. got float / duration. see bool(), int(), float(), string(), duration()"),228 keyStruct{float64(1.5), time.Duration(10), ast.TokenDiv}: errors.New("mismatched type to binary operator. got float / duration. see bool(), int(), float(), string(), duration()"),229 // int % duration230 keyStruct{int64(2), time.Duration(5), ast.TokenMod}: errors.New("mismatched type to binary operator. got int % duration. see bool(), int(), float(), string(), duration()"),231 keyStruct{int64(2), time.Duration(10), ast.TokenMod}: errors.New("mismatched type to binary operator. got int % duration. see bool(), int(), float(), string(), duration()"),232 keyStruct{float64(1.5), time.Duration(5), ast.TokenMod}: errors.New("invalid math operator % for type float"),233 keyStruct{float64(1.5), time.Duration(10), ast.TokenMod}: errors.New("invalid math operator % for type float"),234 keyStruct{time.Duration(10), int64(2), ast.TokenPlus}: errors.New("mismatched type to binary operator. got duration + int. see bool(), int(), float(), string(), duration()"),235 keyStruct{time.Duration(10), int64(2), ast.TokenMinus}: errors.New("mismatched type to binary operator. got duration - int. see bool(), int(), float(), string(), duration()"),236 keyStruct{time.Duration(10), float64(1.5), ast.TokenPlus}: errors.New("mismatched type to binary operator. got duration + float. see bool(), int(), float(), string(), duration()"),237 keyStruct{time.Duration(10), float64(1.5), ast.TokenMinus}: errors.New("mismatched type to binary operator. got duration - float. see bool(), int(), float(), string(), duration()"),238 // unrelated to durations but239 keyStruct{int64(2), float64(1.5), ast.TokenPlus}: errors.New("mismatched type to binary operator. got int + float. see bool(), int(), float(), string(), duration()"),240 keyStruct{int64(2), float64(1.5), ast.TokenMinus}: errors.New("mismatched type to binary operator. got int - float. see bool(), int(), float(), string(), duration()"),241 keyStruct{int64(2), float64(1.5), ast.TokenMult}: errors.New("mismatched type to binary operator. got int * float. see bool(), int(), float(), string(), duration()"),242 keyStruct{int64(2), float64(1.5), ast.TokenDiv}: errors.New("mismatched type to binary operator. got int / float. see bool(), int(), float(), string(), duration()"),243 keyStruct{int64(2), float64(1.5), ast.TokenMod}: errors.New("mismatched type to binary operator. got int % float. see bool(), int(), float(), string(), duration()"),244 keyStruct{float64(1.5), int64(2), ast.TokenPlus}: errors.New("mismatched type to binary operator. got float + int. see bool(), int(), float(), string(), duration()"),245 keyStruct{float64(1.5), int64(2), ast.TokenMinus}: errors.New("mismatched type to binary operator. got float - int. see bool(), int(), float(), string(), duration()"),246 keyStruct{float64(1.5), int64(2), ast.TokenMult}: errors.New("mismatched type to binary operator. got float * int. see bool(), int(), float(), string(), duration()"),247 keyStruct{float64(1.5), int64(2), ast.TokenDiv}: errors.New("mismatched type to binary operator. got float / int. see bool(), int(), float(), string(), duration()"),248 keyStruct{float64(1.5), int64(2), ast.TokenMod}: errors.New("invalid math operator % for type float"),249 keyStruct{float64(1.5), float64(1.5), ast.TokenMod}: errors.New("invalid math operator % for type float"),250 })251}252func TestExpression_Eval_NotSupportedNode(t *testing.T) {253 // Passing IdentifierNode, yeah.. this crazy test, but we want to make sure254 // we don't have panics or crashes255 se, err := stateful.NewExpression(&ast.IdentifierNode{})256 expectedError := errors.New("Given node type is not valid evaluation node: *ast.IdentifierNode")257 if err == nil {258 t.Errorf("EvalBool: Expected error, but got expression: %v", se)259 }260 if err != nil && err.Error() != expectedError.Error() {261 t.Errorf("EvalBool: Got unexpected error:\nexpected: %v\ngot: %v", expectedError, err)262 }263 // BinaryNode - Left is identifier264 se, err = stateful.NewExpression(&ast.BinaryNode{265 Operator: ast.TokenEqual,266 Left: &ast.IdentifierNode{},267 Right: &ast.BoolNode{Bool: true},268 })269 expectedError = errors.New("Failed to handle left node: Given node type is not valid evaluation node: *ast.IdentifierNode")270 if err == nil {271 t.Errorf("EvalBool BinaryNode(Left=>Identifier): Expected error, but got expression: %v", se)272 }273 if err != nil && err.Error() != expectedError.Error() {274 t.Errorf("EvalBool BinaryNode(Left=>Identifier): Got unexpected error:\nexpected: %v\ngot: %v", expectedError, err)275 }276 // BinaryNode - Right is identifier277 se, err = stateful.NewExpression(&ast.BinaryNode{278 Operator: ast.TokenEqual,279 Left: &ast.BoolNode{Bool: true},280 Right: &ast.IdentifierNode{},281 })282 expectedError = errors.New("Failed to handle right node: Given node type is not valid evaluation node: *ast.IdentifierNode")283 if err == nil {284 t.Errorf("EvalBool BinaryNode(Right=>Identifier): Expected error, but got expression: %v", se)285 }286 if err != nil && err.Error() != expectedError.Error() {287 t.Errorf("EvalBool BinaryNode(Right=>Identifier): Got unexpected error:\nexpected: %v\ngot: %v", expectedError, err)288 }289}290func TestExpression_Eval_NodeAndEvalTypeNotMatching(t *testing.T) {291 // Test EvalBool against BinaryNode that returns math result292 se := mustCompileExpression(&ast.BinaryNode{293 Operator: ast.TokenPlus,294 Left: &ast.NumberNode{295 IsFloat: true,296 Float64: float64(5),297 },298 Right: &ast.NumberNode{299 IsFloat: true,300 Float64: float64(10),301 },302 })303 result, err := se.EvalBool(stateful.NewScope())304 expectedError := errors.New("expression returned unexpected type float64")305 if err == nil {306 t.Errorf("EvalBool: Expected error result, but got result: %v", result)307 }308 if err != nil && err.Error() != expectedError.Error() {309 t.Errorf("EvalBool: Got unexpected error:\nexpected: %v\ngot: %v", expectedError, err)310 }311}312func TestExpression_EvalBool_BoolNode(t *testing.T) {313 leftValues := []interface{}{true, false}314 // Right values are the same as left, just add a mismatch case315 rightValues := []interface{}{true, false, "NON_BOOL_VALUE"}316 operators := []ast.TokenType{ast.TokenEqual, ast.TokenNotEqual, ast.TokenAnd, ast.TokenOr, ast.TokenLess}317 createBoolNode := func(v interface{}) ast.Node {318 switch value := v.(type) {319 case bool:320 return &ast.BoolNode{321 Bool: value,322 }323 case string:324 return &ast.StringNode{325 Literal: value,326 }327 default:328 panic(fmt.Sprintf("unexpected type %T", v))329 }330 }331 runCompiledEvalBoolTests(t, createBoolNode, leftValues, rightValues, operators, map[keyStruct]interface{}{332 // Left: True, Right: True333 keyStruct{true, true, ast.TokenEqual}: true,334 keyStruct{true, true, ast.TokenNotEqual}: false,335 keyStruct{true, true, ast.TokenAnd}: true,336 keyStruct{true, true, ast.TokenOr}: true,337 // Left: True, Right: False338 keyStruct{true, false, ast.TokenEqual}: false,339 keyStruct{true, false, ast.TokenNotEqual}: true,340 keyStruct{true, false, ast.TokenAnd}: false,341 keyStruct{true, false, ast.TokenOr}: true,342 // Left: False, Right: True343 keyStruct{false, true, ast.TokenEqual}: false,344 keyStruct{false, true, ast.TokenNotEqual}: true,345 keyStruct{false, true, ast.TokenAnd}: false,346 keyStruct{false, true, ast.TokenOr}: true,347 // Left: False, Right: False348 keyStruct{false, false, ast.TokenEqual}: true,349 keyStruct{false, false, ast.TokenNotEqual}: false,350 keyStruct{false, false, ast.TokenAnd}: false,351 keyStruct{false, false, ast.TokenOr}: false,352 }, map[keyStruct]error{353 // Check invalid bool operator354 keyStruct{true, true, ast.TokenLess}: errors.New("invalid comparison operator < for type boolean"),355 keyStruct{true, false, ast.TokenLess}: errors.New("invalid comparison operator < for type boolean"),356 keyStruct{false, true, ast.TokenLess}: errors.New("invalid comparison operator < for type boolean"),357 keyStruct{false, false, ast.TokenLess}: errors.New("invalid comparison operator < for type boolean"),358 // (Redundant test case)359 keyStruct{true, "NON_BOOL_VALUE", ast.TokenLess}: errors.New("invalid comparison operator < for type boolean"),360 keyStruct{false, "NON_BOOL_VALUE", ast.TokenLess}: errors.New("invalid comparison operator < for type boolean"),361 // Left: True, Right: "NON_BOOL_VALUE"362 keyStruct{true, "NON_BOOL_VALUE", ast.TokenEqual}: errors.New("mismatched type to binary operator. got boolean == string. see bool(), int(), float(), string(), duration()"),363 keyStruct{true, "NON_BOOL_VALUE", ast.TokenNotEqual}: errors.New("mismatched type to binary operator. got boolean != string. see bool(), int(), float(), string(), duration()"),364 keyStruct{true, "NON_BOOL_VALUE", ast.TokenAnd}: errors.New("mismatched type to binary operator. got boolean AND string. see bool(), int(), float(), string(), duration()"),365 keyStruct{true, "NON_BOOL_VALUE", ast.TokenOr}: errors.New("mismatched type to binary operator. got boolean OR string. see bool(), int(), float(), string(), duration()"),366 // Left: False, Right: "NON_BOOL_VALUE"367 keyStruct{false, "NON_BOOL_VALUE", ast.TokenEqual}: errors.New("mismatched type to binary operator. got boolean == string. see bool(), int(), float(), string(), duration()"),368 keyStruct{false, "NON_BOOL_VALUE", ast.TokenNotEqual}: errors.New("mismatched type to binary operator. got boolean != string. see bool(), int(), float(), string(), duration()"),369 keyStruct{false, "NON_BOOL_VALUE", ast.TokenAnd}: errors.New("mismatched type to binary operator. got boolean AND string. see bool(), int(), float(), string(), duration()"),370 keyStruct{false, "NON_BOOL_VALUE", ast.TokenOr}: errors.New("mismatched type to binary operator. got boolean OR string. see bool(), int(), float(), string(), duration()"),371 // Left: "NON_BOOL_VALUE", Right: True372 keyStruct{"NON_BOOL_VALUE", true, ast.TokenEqual}: errors.New("mismatched type to binary operator. got string == bool. see bool(), int(), float(), string(), duration()"),373 keyStruct{"NON_BOOL_VALUE", true, ast.TokenNotEqual}: errors.New("mismatched type to binary operator. got string != bool. see bool(), int(), float(), string(), duration()"),374 keyStruct{"NON_BOOL_VALUE", true, ast.TokenAnd}: errors.New("mismatched type to binary operator. got string AND bool. see bool(), int(), float(), string(), duration()"),375 keyStruct{"NON_BOOL_VALUE", true, ast.TokenOr}: errors.New("invalid comparison operator OR for type string"),376 // Left: "NON_BOOL_VALUE", Right: False377 keyStruct{"NON_BOOL_VALUE", false, ast.TokenEqual}: errors.New("mismatched type to binary operator. got string == bool. see bool(), int(), float(), string(), duration()"),378 keyStruct{"NON_BOOL_VALUE", false, ast.TokenNotEqual}: errors.New("mismatched type to binary operator. got string != bool. see bool(), int(), float(), string(), duration()"),379 keyStruct{"NON_BOOL_VALUE", false, ast.TokenAnd}: errors.New("mismatched type to binary operator. got string AND bool. see bool(), int(), float(), string(), duration()"),380 keyStruct{"NON_BOOL_VALUE", false, ast.TokenOr}: errors.New("invalid comparison operator OR for type string"),381 })382}383func TestExpression_EvalBool_NumberNode(t *testing.T) {384 leftValues := []interface{}{float64(5), float64(10), int64(5)}385 rightValues := []interface{}{float64(5), float64(10), int64(5), "NON_INT_VALUE"}386 operators := []ast.TokenType{ast.TokenEqual, ast.TokenNotEqual, ast.TokenGreater, ast.TokenGreaterEqual, ast.TokenLessEqual, ast.TokenLess, ast.TokenOr}387 createNumberNode := func(v interface{}) ast.Node {388 switch value := v.(type) {389 case float64:390 return &ast.NumberNode{391 IsFloat: true,392 Float64: value,393 }394 case int64:395 return &ast.NumberNode{396 IsInt: true,397 Int64: value,398 }399 // For the error case400 case string:401 return &ast.StringNode{402 Literal: value,403 }404 default:405 t.Fatalf("value supplied to createNumberNode is not string/int/float64: %t", v)406 return nil407 }408 }409 runCompiledEvalBoolTests(t, createNumberNode, leftValues, rightValues, operators, map[keyStruct]interface{}{410 // Left is float64(5), Right is float64(5)411 keyStruct{float64(5), float64(5), ast.TokenEqual}: true,412 keyStruct{float64(5), float64(5), ast.TokenNotEqual}: false,413 keyStruct{float64(5), float64(5), ast.TokenGreater}: false,414 keyStruct{float64(5), float64(5), ast.TokenGreaterEqual}: true,415 keyStruct{float64(5), float64(5), ast.TokenLess}: false,416 keyStruct{float64(5), float64(5), ast.TokenLessEqual}: true,417 // Left is float64(5), Right is float64(10)418 keyStruct{float64(5), float64(10), ast.TokenEqual}: false,419 keyStruct{float64(5), float64(10), ast.TokenNotEqual}: true,420 keyStruct{float64(5), float64(10), ast.TokenGreater}: false,421 keyStruct{float64(5), float64(10), ast.TokenGreaterEqual}: false,422 keyStruct{float64(5), float64(10), ast.TokenLess}: true,423 keyStruct{float64(5), float64(10), ast.TokenLessEqual}: true,424 // Left is float64(5), Right is int64(5)425 keyStruct{float64(5), int64(5), ast.TokenEqual}: true,426 keyStruct{float64(5), int64(5), ast.TokenNotEqual}: false,427 keyStruct{float64(5), int64(5), ast.TokenGreater}: false,428 keyStruct{float64(5), int64(5), ast.TokenGreaterEqual}: true,429 keyStruct{float64(5), int64(5), ast.TokenLess}: false,430 keyStruct{float64(5), int64(5), ast.TokenLessEqual}: true,431 // Left is float64(10), Right is float64(5)432 keyStruct{float64(10), float64(5), ast.TokenEqual}: false,433 keyStruct{float64(10), float64(5), ast.TokenNotEqual}: true,434 keyStruct{float64(10), float64(5), ast.TokenGreater}: true,435 keyStruct{float64(10), float64(5), ast.TokenGreaterEqual}: true,436 keyStruct{float64(10), float64(5), ast.TokenLess}: false,437 keyStruct{float64(10), float64(5), ast.TokenLessEqual}: false,438 // Left is float64(10), Right is float64(10)439 keyStruct{float64(10), float64(10), ast.TokenEqual}: true,440 keyStruct{float64(10), float64(10), ast.TokenNotEqual}: false,441 keyStruct{float64(10), float64(10), ast.TokenGreater}: false,442 keyStruct{float64(10), float64(10), ast.TokenGreaterEqual}: true,443 keyStruct{float64(10), float64(10), ast.TokenLess}: false,444 keyStruct{float64(10), float64(10), ast.TokenLessEqual}: true,445 // Left is float64(10), Right is float64(5)446 keyStruct{float64(10), int64(5), ast.TokenEqual}: false,447 keyStruct{float64(10), int64(5), ast.TokenNotEqual}: true,448 keyStruct{float64(10), int64(5), ast.TokenGreater}: true,449 keyStruct{float64(10), int64(5), ast.TokenGreaterEqual}: true,450 keyStruct{float64(10), int64(5), ast.TokenLess}: false,451 keyStruct{float64(10), int64(5), ast.TokenLessEqual}: false,452 // Left is int64(10), Right is float64(5)453 keyStruct{int64(10), float64(5), ast.TokenEqual}: false,454 keyStruct{int64(10), float64(5), ast.TokenNotEqual}: true,455 keyStruct{int64(10), float64(5), ast.TokenGreater}: true,456 keyStruct{int64(10), float64(5), ast.TokenGreaterEqual}: true,457 keyStruct{int64(10), float64(5), ast.TokenLess}: false,458 keyStruct{int64(10), float64(5), ast.TokenLessEqual}: false,459 // Left is int64(5), Right is float64(5)460 keyStruct{int64(5), float64(5), ast.TokenEqual}: true,461 keyStruct{int64(5), float64(5), ast.TokenNotEqual}: false,462 keyStruct{int64(5), float64(5), ast.TokenGreater}: false,463 keyStruct{int64(5), float64(5), ast.TokenGreaterEqual}: true,464 keyStruct{int64(5), float64(5), ast.TokenLess}: false,465 keyStruct{int64(5), float64(5), ast.TokenLessEqual}: true,466 // Left is int64(5), Right is float64(10)467 keyStruct{int64(5), float64(10), ast.TokenEqual}: false,468 keyStruct{int64(5), float64(10), ast.TokenNotEqual}: true,469 keyStruct{int64(5), float64(10), ast.TokenGreater}: false,470 keyStruct{int64(5), float64(10), ast.TokenGreaterEqual}: false,471 keyStruct{int64(5), float64(10), ast.TokenLess}: true,472 keyStruct{int64(5), float64(10), ast.TokenLessEqual}: true,473 // Left is int64(5), Right is int64(5)474 keyStruct{int64(5), int64(5), ast.TokenEqual}: true,475 keyStruct{int64(5), int64(5), ast.TokenNotEqual}: false,476 keyStruct{int64(5), int64(5), ast.TokenGreater}: false,477 keyStruct{int64(5), int64(5), ast.TokenGreaterEqual}: true,478 keyStruct{int64(5), int64(5), ast.TokenLess}: false,479 keyStruct{int64(5), int64(5), ast.TokenLessEqual}: true,480 }, map[keyStruct]error{481 // Invalid operator482 keyStruct{float64(5), float64(5), ast.TokenOr}: errors.New("invalid logical operator OR for type float"),483 keyStruct{float64(5), float64(10), ast.TokenOr}: errors.New("invalid logical operator OR for type float"),484 keyStruct{float64(5), int64(5), ast.TokenOr}: errors.New("invalid logical operator OR for type float"),485 keyStruct{float64(10), float64(5), ast.TokenOr}: errors.New("invalid logical operator OR for type float"),486 keyStruct{float64(10), float64(10), ast.TokenOr}: errors.New("invalid logical operator OR for type float"),487 keyStruct{float64(10), int64(5), ast.TokenOr}: errors.New("invalid logical operator OR for type float"),488 keyStruct{int64(5), float64(5), ast.TokenOr}: errors.New("invalid logical operator OR for type int"),489 keyStruct{int64(5), float64(10), ast.TokenOr}: errors.New("invalid logical operator OR for type int"),490 keyStruct{int64(5), int64(5), ast.TokenOr}: errors.New("invalid logical operator OR for type int"),491 // (Redundant case)492 keyStruct{float64(5), "NON_INT_VALUE", ast.TokenOr}: errors.New("invalid logical operator OR for type float"),493 keyStruct{float64(10), "NON_INT_VALUE", ast.TokenOr}: errors.New("invalid logical operator OR for type float"),494 keyStruct{int64(5), "NON_INT_VALUE", ast.TokenOr}: errors.New("invalid logical operator OR for type int"),495 // Left is float64(5), Right is "NON_INT_VALUE"496 keyStruct{float64(5), "NON_INT_VALUE", ast.TokenEqual}: errors.New("mismatched type to binary operator. got float == string. see bool(), int(), float(), string(), duration()"),497 keyStruct{float64(5), "NON_INT_VALUE", ast.TokenNotEqual}: errors.New("mismatched type to binary operator. got float != string. see bool(), int(), float(), string(), duration()"),498 keyStruct{float64(5), "NON_INT_VALUE", ast.TokenGreater}: errors.New("mismatched type to binary operator. got float > string. see bool(), int(), float(), string(), duration()"),499 keyStruct{float64(5), "NON_INT_VALUE", ast.TokenGreaterEqual}: errors.New("mismatched type to binary operator. got float >= string. see bool(), int(), float(), string(), duration()"),500 keyStruct{float64(5), "NON_INT_VALUE", ast.TokenLess}: errors.New("mismatched type to binary operator. got float < string. see bool(), int(), float(), string(), duration()"),501 keyStruct{float64(5), "NON_INT_VALUE", ast.TokenLessEqual}: errors.New("mismatched type to binary operator. got float <= string. see bool(), int(), float(), string(), duration()"),502 // (Redundant case) Left is float64(10), Right is "NON_INT_VALUE"503 keyStruct{float64(10), "NON_INT_VALUE", ast.TokenEqual}: errors.New("mismatched type to binary operator. got float == string. see bool(), int(), float(), string(), duration()"),504 keyStruct{float64(10), "NON_INT_VALUE", ast.TokenNotEqual}: errors.New("mismatched type to binary operator. got float != string. see bool(), int(), float(), string(), duration()"),505 keyStruct{float64(10), "NON_INT_VALUE", ast.TokenGreater}: errors.New("mismatched type to binary operator. got float > string. see bool(), int(), float(), string(), duration()"),506 keyStruct{float64(10), "NON_INT_VALUE", ast.TokenGreaterEqual}: errors.New("mismatched type to binary operator. got float >= string. see bool(), int(), float(), string(), duration()"),507 keyStruct{float64(10), "NON_INT_VALUE", ast.TokenLess}: errors.New("mismatched type to binary operator. got float < string. see bool(), int(), float(), string(), duration()"),508 keyStruct{float64(10), "NON_INT_VALUE", ast.TokenLessEqual}: errors.New("mismatched type to binary operator. got float <= string. see bool(), int(), float(), string(), duration()"),509 // Left is int64(5), Right is "NON_INT_VALUE"510 keyStruct{int64(5), "NON_INT_VALUE", ast.TokenEqual}: errors.New("mismatched type to binary operator. got int == string. see bool(), int(), float(), string(), duration()"),511 keyStruct{int64(5), "NON_INT_VALUE", ast.TokenNotEqual}: errors.New("mismatched type to binary operator. got int != string. see bool(), int(), float(), string(), duration()"),512 keyStruct{int64(5), "NON_INT_VALUE", ast.TokenGreater}: errors.New("mismatched type to binary operator. got int > string. see bool(), int(), float(), string(), duration()"),513 keyStruct{int64(5), "NON_INT_VALUE", ast.TokenGreaterEqual}: errors.New("mismatched type to binary operator. got int >= string. see bool(), int(), float(), string(), duration()"),514 keyStruct{int64(5), "NON_INT_VALUE", ast.TokenLess}: errors.New("mismatched type to binary operator. got int < string. see bool(), int(), float(), string(), duration()"),515 keyStruct{int64(5), "NON_INT_VALUE", ast.TokenLessEqual}: errors.New("mismatched type to binary operator. got int <= string. see bool(), int(), float(), string(), duration()"),516 })517}518func TestExpression_EvalBool_StringNode(t *testing.T) {519 leftValues := []interface{}{"a", "b"}520 rightValues := []interface{}{"a", "b", int64(123)}521 operators := []ast.TokenType{ast.TokenEqual, ast.TokenNotEqual, ast.TokenGreater, ast.TokenGreaterEqual, ast.TokenLessEqual, ast.TokenLess, ast.TokenOr}522 createStringNode := func(v interface{}) ast.Node {523 switch value := v.(type) {524 case string:525 return &ast.StringNode{526 Literal: value,527 }528 case int64:529 return &ast.NumberNode{530 IsInt: true,531 Int64: value,532 }533 default:534 t.Fatalf("value supplied to createStringNode is not string/int64: %t", v)535 return nil536 }537 }538 runCompiledEvalBoolTests(t, createStringNode, leftValues, rightValues, operators, map[keyStruct]interface{}{539 // Left is "a", Right is "a"540 keyStruct{"a", "a", ast.TokenEqual}: true,541 keyStruct{"a", "a", ast.TokenNotEqual}: false,542 keyStruct{"a", "a", ast.TokenGreater}: false,543 keyStruct{"a", "a", ast.TokenGreaterEqual}: true,544 keyStruct{"a", "a", ast.TokenLess}: false,545 keyStruct{"a", "a", ast.TokenLessEqual}: true,546 // Left is "a", Right is "b"547 keyStruct{"a", "b", ast.TokenEqual}: false,548 keyStruct{"a", "b", ast.TokenNotEqual}: true,549 keyStruct{"a", "b", ast.TokenGreater}: false,550 keyStruct{"a", "b", ast.TokenGreaterEqual}: false,551 keyStruct{"a", "b", ast.TokenLess}: true,552 keyStruct{"a", "b", ast.TokenLessEqual}: true,553 // Left is "b", Right is "a"554 keyStruct{"b", "a", ast.TokenEqual}: false,555 keyStruct{"b", "a", ast.TokenNotEqual}: true,556 keyStruct{"b", "a", ast.TokenGreater}: true,557 keyStruct{"b", "a", ast.TokenGreaterEqual}: true,558 keyStruct{"b", "a", ast.TokenLess}: false,559 keyStruct{"b", "a", ast.TokenLessEqual}: false,560 // Left is "b", Right is "b"561 keyStruct{"b", "b", ast.TokenEqual}: true,562 keyStruct{"b", "b", ast.TokenNotEqual}: false,563 keyStruct{"b", "b", ast.TokenGreater}: false,564 keyStruct{"b", "b", ast.TokenGreaterEqual}: true,565 keyStruct{"b", "b", ast.TokenLess}: false,566 keyStruct{"b", "b", ast.TokenLessEqual}: true,567 }, map[keyStruct]error{568 // Invalid operator569 keyStruct{"a", "a", ast.TokenOr}: errors.New("invalid logical operator OR for type string"),570 keyStruct{"a", "b", ast.TokenOr}: errors.New("invalid logical operator OR for type string"),571 keyStruct{"b", "a", ast.TokenOr}: errors.New("invalid logical operator OR for type string"),572 keyStruct{"b", "b", ast.TokenOr}: errors.New("invalid logical operator OR for type string"),573 keyStruct{"a", int64(123), ast.TokenOr}: errors.New("invalid logical operator OR for type string"),574 keyStruct{"b", int64(123), ast.TokenOr}: errors.New("invalid logical operator OR for type string"),575 // Left is "a", Right is int64(123)576 keyStruct{"a", int64(123), ast.TokenEqual}: errors.New("mismatched type to binary operator. got string == int. see bool(), int(), float(), string(), duration()"),577 keyStruct{"a", int64(123), ast.TokenNotEqual}: errors.New("mismatched type to binary operator. got string != int. see bool(), int(), float(), string(), duration()"),578 keyStruct{"a", int64(123), ast.TokenGreater}: errors.New("mismatched type to binary operator. got string > int. see bool(), int(), float(), string(), duration()"),579 keyStruct{"a", int64(123), ast.TokenGreaterEqual}: errors.New("mismatched type to binary operator. got string >= int. see bool(), int(), float(), string(), duration()"),580 keyStruct{"a", int64(123), ast.TokenLess}: errors.New("mismatched type to binary operator. got string < int. see bool(), int(), float(), string(), duration()"),581 keyStruct{"a", int64(123), ast.TokenLessEqual}: errors.New("mismatched type to binary operator. got string <= int. see bool(), int(), float(), string(), duration()"),582 // Left is "b", Right is int64(123)583 keyStruct{"b", int64(123), ast.TokenEqual}: errors.New("mismatched type to binary operator. got string == int. see bool(), int(), float(), string(), duration()"),584 keyStruct{"b", int64(123), ast.TokenNotEqual}: errors.New("mismatched type to binary operator. got string != int. see bool(), int(), float(), string(), duration()"),585 keyStruct{"b", int64(123), ast.TokenGreater}: errors.New("mismatched type to binary operator. got string > int. see bool(), int(), float(), string(), duration()"),586 keyStruct{"b", int64(123), ast.TokenGreaterEqual}: errors.New("mismatched type to binary operator. got string >= int. see bool(), int(), float(), string(), duration()"),587 keyStruct{"b", int64(123), ast.TokenLess}: errors.New("mismatched type to binary operator. got string < int. see bool(), int(), float(), string(), duration()"),588 keyStruct{"b", int64(123), ast.TokenLessEqual}: errors.New("mismatched type to binary operator. got string <= int. see bool(), int(), float(), string(), duration()"),589 })590}591func TestExpression_EvalBool_RegexNode(t *testing.T) {592 pattern := regexp.MustCompile(`^(.*)c$`)593 leftValues := []interface{}{"abc", "cba", pattern}594 // Right values are regex, but we are supplying strings because the keyStruct and maps don't play nice together595 // so we mark regex with prefix of regexp.MustCompile(``) and createStringOrRegexNode will convert it to regex596 rightValues := []interface{}{pattern}597 operators := []ast.TokenType{ast.TokenRegexEqual, ast.TokenRegexNotEqual, ast.TokenEqual}598 createStringOrRegexNode := func(v interface{}) ast.Node {599 switch value := v.(type) {600 case string:601 return &ast.StringNode{602 Literal: value,603 }604 case *regexp.Regexp:605 return &ast.RegexNode{606 Regex: value,607 }608 default:609 panic(fmt.Sprintf("unexpected type %T", v))610 }611 }612 runCompiledEvalBoolTests(t, createStringOrRegexNode, leftValues, rightValues, operators, map[keyStruct]interface{}{613 // Left is "abc", Right is regex "(.*)c"614 keyStruct{"abc", pattern, ast.TokenRegexEqual}: true,615 keyStruct{"abc", pattern, ast.TokenRegexNotEqual}: false,616 // Left is "cba", Right is regex "(.*)c"617 keyStruct{"cba", pattern, ast.TokenRegexEqual}: false,618 keyStruct{"cba", pattern, ast.TokenRegexNotEqual}: true,619 },620 map[keyStruct]error{621 // Errors for invalid operators622 keyStruct{"abc", pattern, ast.TokenEqual}: errors.New("mismatched type to binary operator. got string == regex. see bool(), int(), float(), string(), duration()"),623 keyStruct{"cba", pattern, ast.TokenEqual}: errors.New("mismatched type to binary operator. got string == regex. see bool(), int(), float(), string(), duration()"),624 keyStruct{pattern, "cba", ast.TokenEqual}: errors.New("invalid comparison operator == for type regex"),625 keyStruct{pattern, pattern, ast.TokenRegexEqual}: errors.New("mismatched type to binary operator. got regex =~ regex. see bool(), int(), float(), string(), duration()"),626 keyStruct{pattern, pattern, ast.TokenRegexNotEqual}: errors.New("mismatched type to binary operator. got regex !~ regex. see bool(), int(), float(), string(), duration()"),627 keyStruct{pattern, pattern, ast.TokenEqual}: errors.New("invalid comparison operator == for type regex"),628 })629}630func TestExpression_EvalBool_NotSupportedValueLeft(t *testing.T) {631 scope := stateful.NewScope()632 scope.Set("value", []int{1, 2, 3})633 _, err := evalCompiledBoolWithScope(t, scope, &ast.BinaryNode{634 Operator: ast.TokenEqual,635 Left: &ast.ReferenceNode{636 Reference: "value",637 },638 Right: &ast.StringNode{639 Literal: "yo",640 },641 })642 expectedError := "left value is invalid value type"643 if err != nil && (err.Error() != expectedError) {644 t.Errorf("Unexpected error result: \ngot: %v\nexpected: %v", err.Error(), expectedError)645 }646 if err == nil {647 t.Error("Unexpected error result: but didn't got any error")648 }649 // Swap sides650 _, err = evalCompiledBoolWithScope(t, scope, &ast.BinaryNode{651 Operator: ast.TokenEqual,652 Left: &ast.StringNode{653 Literal: "yo",654 },655 Right: &ast.ReferenceNode{656 Reference: "value",657 },658 })659 expectedError = "right value is invalid value type"660 if err != nil && (err.Error() != expectedError) {661 t.Errorf("Unexpected error result: \ngot: %v\nexpected: %v", err.Error(), expectedError)662 }663 if err == nil {664 t.Error("Unexpected error result: but didn't got any error")665 }666}667func TestExpression_EvalBool_UnknownOperator(t *testing.T) {668 node := &ast.BinaryNode{669 Operator: ast.TokenType(666),670 Left: &ast.StringNode{671 Literal: "value",672 },673 Right: &ast.StringNode{674 Literal: "yo",675 },676 }677 expectedError := "unknown binary operator 666"678 _, err := stateful.NewExpression(node)679 if err == nil {680 t.Fatal("Unexpected error result: but didn't got any error")681 }682 if got := err.Error(); got != expectedError {683 t.Errorf("Unexpected error result: \ngot: %v\nexpected: %v", got, expectedError)684 }685}686func TestExpression_EvalBool_ReferenceNodeDosentExist(t *testing.T) {687 emptyScope := stateful.NewScope()688 expectedError := `name "value" is undefined. Names in scope: `689 // Check left side690 _, err := evalCompiledBoolWithScope(t, emptyScope, &ast.BinaryNode{691 Operator: ast.TokenEqual,692 Left: &ast.ReferenceNode{693 Reference: "value",694 },695 Right: &ast.StringNode{696 Literal: "yo",697 },698 })699 if err != nil && (err.Error() != expectedError) {700 t.Errorf("Unexpected error result: \ngot: %v\nexpected: %v", err.Error(), expectedError)701 }702 if err == nil {703 t.Error("Unexpected error result: but didn't got any error")704 }705 // Check right side706 _, err = evalCompiledBoolWithScope(t, emptyScope, &ast.BinaryNode{707 Operator: ast.TokenEqual,708 Left: &ast.StringNode{709 Literal: "yo",710 },711 Right: &ast.ReferenceNode{712 Reference: "value",713 },714 })715 if err != nil && (err.Error() != expectedError) {716 t.Errorf("Unexpected error result: \ngot: %v\nexpected: %v", err.Error(), expectedError)717 }718 if err == nil {719 t.Error("Unexpected error result: but didn't got any error")720 }721}722func TestExpression_EvalBool_ReferenceNodeNil(t *testing.T) {723 scope := stateful.NewScope()724 scope.Set("value", nil)725 expectedError := `referenced value "value" is nil.`726 // Check left side727 _, err := evalCompiledBoolWithScope(t, scope, &ast.BinaryNode{728 Operator: ast.TokenEqual,729 Left: &ast.ReferenceNode{730 Reference: "value",731 },732 Right: &ast.StringNode{733 Literal: "yo",734 },735 })736 if err != nil && (err.Error() != expectedError) {737 t.Errorf("Unexpected error result: \ngot: %v\nexpected: %v", err.Error(), expectedError)738 }739 if err == nil {740 t.Error("Unexpected error result: but didn't got any error")741 }742 // Check right side743 _, err = evalCompiledBoolWithScope(t, scope, &ast.BinaryNode{744 Operator: ast.TokenEqual,745 Left: &ast.StringNode{746 Literal: "yo",747 },748 Right: &ast.ReferenceNode{749 Reference: "value",750 },751 })752 if err != nil && (err.Error() != expectedError) {753 t.Errorf("Unexpected error result: \ngot: %v\nexpected: %v", err.Error(), expectedError)754 }755 if err == nil {756 t.Error("Unexpected error result: but didn't got any error")757 }758}759func TestExpression_EvalBool_ReturnsReferenceNode(t *testing.T) {760 scope := stateful.NewScope()761 // First Case - true as boolValue762 boolValue := true763 scope.Set("boolValue", boolValue)764 result, err := evalCompiledBoolWithScope(t, scope, &ast.ReferenceNode{765 Reference: "boolValue",766 })767 if err != nil {768 t.Errorf("Unexpected error result: %v", err.Error())769 }770 if result != boolValue {771 t.Errorf("Unexpected result: \ngot: %v\nexp: %v", result, boolValue)772 }773 // Second Case - false as boolValue774 boolValue = false775 scope.Set("boolValue", boolValue)776 result, err = evalCompiledBoolWithScope(t, scope, &ast.ReferenceNode{777 Reference: "boolValue",778 })779 if err != nil {780 t.Errorf("Unexpected error result: %v", err.Error())781 }782 if result != boolValue {783 t.Errorf("Unexpected result: \ngot: %v\nexp: %v", result, boolValue)784 }785}786func TestExpression_EvalNum_ReferenceNodeDosentExist(t *testing.T) {787 emptyScope := stateful.NewScope()788 expectedError := `name "value" is undefined. Names in scope: `789 // Check left side790 se := mustCompileExpression(&ast.ReferenceNode{791 Reference: "value",792 })793 result, err := se.Eval(emptyScope)794 if err != nil && (err.Error() != expectedError) {795 t.Errorf("Unexpected error result: \ngot: %v\nexpected: %v", err.Error(), expectedError)796 }797 if err == nil {798 t.Errorf("Expected error result: but didn't got any error, got result: %v", result)799 }800}801func TestExpression_EvalBool_UnexpectedTypeResult(t *testing.T) {802 expectedError := `TypeGuard: expression returned unexpected type invalid type, expected boolean`803 scope := stateful.NewScope()804 scope.Set("value", []int{1, 2, 3})805 // Check left side806 _, err := evalCompiledBoolWithScope(t, scope, &ast.ReferenceNode{807 Reference: "value",808 })809 if err != nil && (err.Error() != expectedError) {810 t.Errorf("Unexpected error result: \ngot: %v\nexpected: %v", err.Error(), expectedError)811 }812 if err == nil {813 t.Error("Unexpected error result: but didn't got any error")814 }815}816func TestExpression_EvalBool_ReferenceNodeDosentExistInBinaryNode(t *testing.T) {817 emptyScope := stateful.NewScope()818 expectedError := `name "value" is undefined. Names in scope: `819 // Check left side820 _, err := evalCompiledBoolWithScope(t, emptyScope, &ast.BinaryNode{821 Operator: ast.TokenGreater,822 Left: &ast.ReferenceNode{823 Reference: "value",824 },825 Right: &ast.NumberNode{826 IsInt: true,827 Int64: int64(0),828 },829 })830 if err != nil && (err.Error() != expectedError) {831 t.Errorf("Unexpected error result: \ngot: %v\nexpected: %v", err.Error(), expectedError)832 }833 if err == nil {834 t.Error("Unexpected error result: but didn't got any error")835 }836}837func TestExpression_EvalString_StringConcat(t *testing.T) {838 se, err := stateful.NewExpression(&ast.BinaryNode{839 Operator: ast.TokenPlus,840 Left: &ast.StringNode{841 Literal: "left",842 },843 Right: &ast.StringNode{844 Literal: "right",845 },846 })847 if err != nil {848 t.Fatal(err)849 }850 scope := stateful.NewScope()851 result, err := se.EvalString(scope)852 if err != nil {853 t.Fatal("unexpected error EvalString:", err)854 }855 if exp := "leftright"; exp != result {856 t.Errorf("unexpected EvalString results: got %s exp %s", result, exp)857 }858}859func TestExpression_EvalString_StringConcatReferenceNode(t *testing.T) {860 se, err := stateful.NewExpression(&ast.BinaryNode{861 Operator: ast.TokenPlus,862 Left: &ast.StringNode{863 Literal: "left",864 },865 Right: &ast.ReferenceNode{866 Reference: "value",867 },868 })869 if err != nil {870 t.Fatal(err)871 }872 scope := stateful.NewScope()873 scope.Set("value", "right")874 result, err := se.EvalString(scope)875 if err != nil {876 t.Fatal("unexpected error EvalString:", err)877 }878 if exp := "leftright"; exp != result {879 t.Errorf("unexpected EvalString results: got %s exp %s", result, exp)880 }881}882func TestExpression_EvalNum_BinaryNodeWithUnary(t *testing.T) {883 // -"value" < 0 , yes, of course, this is always true..884 se := mustCompileExpression(&ast.BinaryNode{885 Operator: ast.TokenLess,886 Left: &ast.UnaryNode{887 Operator: ast.TokenMinus,888 Node: &ast.ReferenceNode{889 Reference: "value",890 },891 },892 Right: &ast.NumberNode{893 IsInt: true,894 Int64: int64(0),895 },896 })897 scope := stateful.NewScope()898 scope.Set("value", int64(4))899 result, err := se.EvalBool(scope)900 if err != nil {901 t.Errorf("Ref node: Failed to evaluate:\n%v", err)902 }903 if !result {904 t.Errorf("int ref test case: unexpected result: got: %t, expected: true", result)905 }906}907func TestExpression_EvalBool_BinaryNodeWithBoolUnaryNode(t *testing.T) {908 emptyScope := stateful.NewScope()909 se := mustCompileExpression(&ast.BinaryNode{910 Operator: ast.TokenEqual,911 Left: &ast.UnaryNode{912 Operator: ast.TokenNot,913 Node: &ast.BoolNode{914 Bool: false,915 },916 },917 Right: &ast.BoolNode{918 Bool: true,919 },920 })921 result, err := se.EvalBool(emptyScope)922 if err != nil {923 t.Errorf("first case: %v", err)924 }925 if !result {926 t.Errorf("first case: unexpected result: got: %t, expected: true", result)927 }928 // now with ref929 se = mustCompileExpression(&ast.BinaryNode{930 Operator: ast.TokenEqual,931 Left: &ast.UnaryNode{932 Operator: ast.TokenNot,933 Node: &ast.ReferenceNode{934 Reference: "value",935 },936 },937 Right: &ast.BoolNode{938 Bool: true,939 },940 })941 scope := stateful.NewScope()942 scope.Set("value", bool(false))943 result, err = se.EvalBool(scope)944 if err != nil {945 t.Errorf("ref case: %v", err)946 }947 if !result {948 t.Errorf("ref case: unexpected result: got: %t, expected: true", result)949 }950}951func TestExpression_EvalBool_BinaryNodeWithNumericUnaryNode(t *testing.T) {952 scope := stateful.NewScope()953 se := mustCompileExpression(&ast.BinaryNode{954 Operator: ast.TokenLess,955 Left: &ast.UnaryNode{956 Operator: ast.TokenMinus,957 Node: &ast.NumberNode{958 IsInt: true,959 Int64: 4,960 },961 },962 Right: &ast.NumberNode{963 IsInt: true,964 Int64: 0,965 },966 })967 result, err := se.EvalBool(scope)968 if err != nil {969 t.Error(err)970 }971 if !result {972 t.Errorf("unexpected result: got: %t, expected: true", result)973 }974}975func TestExpression_EvalBool_TwoLevelsDeepBinary(t *testing.T) {976 scope := stateful.NewScope()977 // passing978 scope.Set("a", int64(11))979 scope.Set("b", int64(5))980 // a > 10 and b < 10981 se := mustCompileExpression(&ast.BinaryNode{982 Operator: ast.TokenAnd,983 Left: &ast.BinaryNode{984 Operator: ast.TokenGreater,985 Left: &ast.ReferenceNode{986 Reference: "a",987 },988 Right: &ast.NumberNode{989 IsInt: true,990 Int64: 10,991 },992 },993 Right: &ast.BinaryNode{994 Operator: ast.TokenLess,995 Left: &ast.ReferenceNode{996 Reference: "b",997 },998 Right: &ast.NumberNode{999 IsInt: true,1000 Int64: 10,1001 },1002 },1003 })1004 result, err := se.EvalBool(scope)1005 if err != nil {1006 t.Error(err)1007 }1008 if !result {1009 t.Errorf("unexpected result: got: %t, expected: true", result)1010 }1011 // fail1012 scope.Set("a", int64(6))1013 result, err = se.EvalBool(scope)1014 if err != nil {1015 t.Error(err)1016 }1017 if result {1018 t.Errorf("unexpected result: got: %t, expected: false", result)1019 }1020}1021func TestExpression_EvalBool_TwoLevelsDeepBinaryWithEvalNum_Int64(t *testing.T) {1022 scope := stateful.NewScope()1023 // passing1024 scope.Set("a", int64(11))1025 scope.Set("b", int64(5))1026 // a > 10 and b < 101027 se := mustCompileExpression(&ast.BinaryNode{1028 Operator: ast.TokenAnd,1029 Left: &ast.BinaryNode{1030 Operator: ast.TokenGreater,1031 Left: &ast.ReferenceNode{1032 Reference: "a",1033 },1034 // right = 5 * 2 = 101035 Right: &ast.BinaryNode{1036 Operator: ast.TokenMult,1037 Left: &ast.NumberNode{1038 IsInt: true,1039 Int64: 5,1040 },1041 Right: &ast.NumberNode{1042 IsInt: true,1043 Int64: 2,1044 },1045 },1046 },1047 Right: &ast.BinaryNode{1048 Operator: ast.TokenLess,1049 Left: &ast.ReferenceNode{1050 Reference: "b",1051 },1052 Right: &ast.NumberNode{1053 IsInt: true,1054 Int64: 10,1055 },1056 },1057 })1058 result, err := se.EvalBool(scope)1059 if err != nil {1060 t.Error(err)1061 }1062 if !result {1063 t.Errorf("unexpected result: got: %t, expected: true", result)1064 }1065 // fail1066 scope.Set("a", int64(6))1067 result, err = se.EvalBool(scope)1068 if err != nil {1069 t.Error(err)1070 }1071 if result {1072 t.Errorf("unexpected result: got: %t, expected: false", result)1073 }1074}1075func TestExpression_EvalBool_TwoLevelsDeepBinaryWithEvalNum_Float64(t *testing.T) {1076 scope := stateful.NewScope()1077 // passing1078 scope.Set("a", float64(11))1079 scope.Set("b", float64(5))1080 // a > 10 and b < 101081 se := mustCompileExpression(&ast.BinaryNode{1082 Operator: ast.TokenAnd,1083 Left: &ast.BinaryNode{1084 Operator: ast.TokenGreater,1085 Left: &ast.ReferenceNode{1086 Reference: "a",1087 },1088 // right = 5 * 2 = 101089 Right: &ast.BinaryNode{1090 Operator: ast.TokenMult,1091 Left: &ast.NumberNode{1092 IsFloat: true,1093 Float64: 5,1094 },1095 Right: &ast.NumberNode{1096 IsFloat: true,1097 Float64: 2,1098 },1099 },1100 },1101 Right: &ast.BinaryNode{1102 Operator: ast.TokenLess,1103 Left: &ast.ReferenceNode{1104 Reference: "b",1105 },1106 Right: &ast.NumberNode{1107 IsFloat: true,1108 Float64: 10,1109 },1110 },1111 })1112 result, err := se.EvalBool(scope)1113 if err != nil {1114 t.Error(err)1115 }1116 if !result {1117 t.Errorf("unexpected result: got: %t, expected: true", result)1118 }1119 // fail1120 scope.Set("a", float64(6))1121 result, err = se.EvalBool(scope)1122 if err != nil {1123 t.Error(err)1124 }1125 if result {1126 t.Errorf("unexpected result: got: %t, expected: false", result)1127 }1128}1129func TestExpression_EvalNum_NumberNode(t *testing.T) {1130 leftValues := []interface{}{float64(5), float64(10), int64(5)}1131 rightValues := []interface{}{float64(5), float64(10), int64(5), "NON_INT_VALUE"}1132 operators := []ast.TokenType{1133 ast.TokenPlus,1134 ast.TokenMinus,1135 ast.TokenMult,1136 ast.TokenDiv,1137 ast.TokenMod,1138 }1139 createNumberNode := func(v interface{}) ast.Node {1140 switch value := v.(type) {1141 case float64:1142 return &ast.NumberNode{1143 IsFloat: true,1144 Float64: value,1145 }1146 case int64:1147 return &ast.NumberNode{1148 IsInt: true,1149 Int64: value,1150 }1151 // For the error case1152 case string:1153 return &ast.StringNode{1154 Literal: value,1155 }1156 default:1157 t.Fatalf("value supplied to createNumberNode is not string/int/float64: %t", v)1158 return nil1159 }1160 }1161 runCompiledNumericTests(t, createNumberNode, leftValues, rightValues, operators, map[keyStruct]interface{}{1162 // Left is float64(5), Right is float64(5)1163 keyStruct{float64(5), float64(5), ast.TokenPlus}: float64(10),1164 keyStruct{float64(5), float64(5), ast.TokenMinus}: float64(0),1165 keyStruct{float64(5), float64(5), ast.TokenMult}: float64(25),1166 keyStruct{float64(5), float64(5), ast.TokenDiv}: float64(1),1167 // Left is int64(5), Right is int64(5)1168 keyStruct{int64(5), int64(5), ast.TokenPlus}: int64(10),1169 keyStruct{int64(5), int64(5), ast.TokenMinus}: int64(0),1170 keyStruct{int64(5), int64(5), ast.TokenMult}: int64(25),1171 keyStruct{int64(5), int64(5), ast.TokenDiv}: int64(1),1172 keyStruct{int64(5), int64(5), ast.TokenMod}: int64(0),1173 // Left is float64(5), Right is float64(10)1174 keyStruct{float64(5), float64(10), ast.TokenPlus}: float64(15),1175 keyStruct{float64(5), float64(10), ast.TokenMinus}: float64(-5),1176 keyStruct{float64(5), float64(10), ast.TokenMult}: float64(50),1177 keyStruct{float64(5), float64(10), ast.TokenDiv}: float64(0.5),1178 // Left is float64(10), Right is float64(5)1179 keyStruct{float64(10), float64(5), ast.TokenPlus}: float64(15),1180 keyStruct{float64(10), float64(5), ast.TokenMinus}: float64(5),1181 keyStruct{float64(10), float64(5), ast.TokenMult}: float64(50),1182 keyStruct{float64(10), float64(5), ast.TokenDiv}: float64(2),1183 // Left is float64(10), Right is float64(10)1184 keyStruct{float64(10), float64(10), ast.TokenPlus}: float64(20),1185 keyStruct{float64(10), float64(10), ast.TokenMinus}: float64(0),1186 keyStruct{float64(10), float64(10), ast.TokenMult}: float64(100),1187 keyStruct{float64(10), float64(10), ast.TokenDiv}: float64(1),1188 }, map[keyStruct]error{1189 // Modulo token where left is float1190 keyStruct{float64(5), float64(5), ast.TokenMod}: errors.New("invalid math operator % for type float"),1191 keyStruct{float64(5), float64(10), ast.TokenMod}: errors.New("invalid math operator % for type float"),1192 keyStruct{float64(10), float64(5), ast.TokenMod}: errors.New("invalid math operator % for type float"),1193 keyStruct{float64(10), float64(10), ast.TokenMod}: errors.New("invalid math operator % for type float"),1194 keyStruct{float64(5), int64(5), ast.TokenMod}: errors.New("invalid math operator % for type float"),1195 keyStruct{float64(10), int64(5), ast.TokenMod}: errors.New("invalid math operator % for type float"),1196 keyStruct{float64(10), "NON_INT_VALUE", ast.TokenMod}: errors.New("invalid math operator % for type float"),1197 keyStruct{float64(5), "NON_INT_VALUE", ast.TokenMod}: errors.New("invalid math operator % for type float"),1198 // Left is int, right is float1199 keyStruct{int64(5), float64(5), ast.TokenPlus}: errors.New("mismatched type to binary operator. got int + float. see bool(), int(), float(), string(), duration()"),1200 keyStruct{int64(5), float64(5), ast.TokenMinus}: errors.New("mismatched type to binary operator. got int - float. see bool(), int(), float(), string(), duration()"),1201 keyStruct{int64(5), float64(5), ast.TokenMult}: errors.New("mismatched type to binary operator. got int * float. see bool(), int(), float(), string(), duration()"),1202 keyStruct{int64(5), float64(5), ast.TokenDiv}: errors.New("mismatched type to binary operator. got int / float. see bool(), int(), float(), string(), duration()"),1203 keyStruct{int64(5), float64(5), ast.TokenMod}: errors.New("mismatched type to binary operator. got int % float. see bool(), int(), float(), string(), duration()"),1204 keyStruct{int64(5), float64(10), ast.TokenPlus}: errors.New("mismatched type to binary operator. got int + float. see bool(), int(), float(), string(), duration()"),1205 keyStruct{int64(5), float64(10), ast.TokenMinus}: errors.New("mismatched type to binary operator. got int - float. see bool(), int(), float(), string(), duration()"),1206 keyStruct{int64(5), float64(10), ast.TokenMult}: errors.New("mismatched type to binary operator. got int * float. see bool(), int(), float(), string(), duration()"),1207 keyStruct{int64(5), float64(10), ast.TokenDiv}: errors.New("mismatched type to binary operator. got int / float. see bool(), int(), float(), string(), duration()"),1208 keyStruct{int64(5), float64(10), ast.TokenMod}: errors.New("mismatched type to binary operator. got int % float. see bool(), int(), float(), string(), duration()"),1209 // Left is float, right is int1210 keyStruct{float64(5), int64(5), ast.TokenPlus}: errors.New("mismatched type to binary operator. got float + int. see bool(), int(), float(), string(), duration()"),1211 keyStruct{float64(5), int64(5), ast.TokenMinus}: errors.New("mismatched type to binary operator. got float - int. see bool(), int(), float(), string(), duration()"),1212 keyStruct{float64(5), int64(5), ast.TokenMult}: errors.New("mismatched type to binary operator. got float * int. see bool(), int(), float(), string(), duration()"),1213 keyStruct{float64(5), int64(5), ast.TokenDiv}: errors.New("mismatched type to binary operator. got float / int. see bool(), int(), float(), string(), duration()"),1214 keyStruct{float64(10), int64(5), ast.TokenPlus}: errors.New("mismatched type to binary operator. got float + int. see bool(), int(), float(), string(), duration()"),1215 keyStruct{float64(10), int64(5), ast.TokenMinus}: errors.New("mismatched type to binary operator. got float - int. see bool(), int(), float(), string(), duration()"),1216 keyStruct{float64(10), int64(5), ast.TokenMult}: errors.New("mismatched type to binary operator. got float * int. see bool(), int(), float(), string(), duration()"),1217 keyStruct{float64(10), int64(5), ast.TokenDiv}: errors.New("mismatched type to binary operator. got float / int. see bool(), int(), float(), string(), duration()"),1218 // Left is int, Right is "NON_INT_VALUE"1219 keyStruct{int64(5), "NON_INT_VALUE", ast.TokenPlus}: errors.New("mismatched type to binary operator. got int + string. see bool(), int(), float(), string(), duration()"),1220 keyStruct{int64(5), "NON_INT_VALUE", ast.TokenMinus}: errors.New("mismatched type to binary operator. got int - string. see bool(), int(), float(), string(), duration()"),1221 keyStruct{int64(5), "NON_INT_VALUE", ast.TokenMult}: errors.New("mismatched type to binary operator. got int * string. see bool(), int(), float(), string(), duration()"),1222 keyStruct{int64(5), "NON_INT_VALUE", ast.TokenDiv}: errors.New("mismatched type to binary operator. got int / string. see bool(), int(), float(), string(), duration()"),1223 keyStruct{int64(5), "NON_INT_VALUE", ast.TokenMod}: errors.New("mismatched type to binary operator. got int % string. see bool(), int(), float(), string(), duration()"),1224 // Left is float, Right is "NON_INT_VALUE"1225 keyStruct{float64(5), "NON_INT_VALUE", ast.TokenPlus}: errors.New("mismatched type to binary operator. got float + string. see bool(), int(), float(), string(), duration()"),1226 keyStruct{float64(5), "NON_INT_VALUE", ast.TokenMinus}: errors.New("mismatched type to binary operator. got float - string. see bool(), int(), float(), string(), duration()"),1227 keyStruct{float64(5), "NON_INT_VALUE", ast.TokenMult}: errors.New("mismatched type to binary operator. got float * string. see bool(), int(), float(), string(), duration()"),1228 keyStruct{float64(5), "NON_INT_VALUE", ast.TokenDiv}: errors.New("mismatched type to binary operator. got float / string. see bool(), int(), float(), string(), duration()"),1229 keyStruct{float64(10), "NON_INT_VALUE", ast.TokenPlus}: errors.New("mismatched type to binary operator. got float + string. see bool(), int(), float(), string(), duration()"),1230 keyStruct{float64(10), "NON_INT_VALUE", ast.TokenMinus}: errors.New("mismatched type to binary operator. got float - string. see bool(), int(), float(), string(), duration()"),1231 keyStruct{float64(10), "NON_INT_VALUE", ast.TokenMult}: errors.New("mismatched type to binary operator. got float * string. see bool(), int(), float(), string(), duration()"),1232 keyStruct{float64(10), "NON_INT_VALUE", ast.TokenDiv}: errors.New("mismatched type to binary operator. got float / string. see bool(), int(), float(), string(), duration()"),1233 })1234}1235func runCompiledNumericTests(1236 t *testing.T,1237 createNodeFn func(v interface{}) ast.Node,1238 leftValues []interface{},1239 rightValues []interface{},1240 operators []ast.TokenType,1241 expected map[keyStruct]interface{},1242 errorExpectations map[keyStruct]error) {1243 runCompiledEvalTests(t, func(t *testing.T, scope *stateful.Scope, n ast.Node) (interface{}, error) {1244 se, err := stateful.NewExpression(n)1245 if err != nil {1246 return nil, err1247 }1248 return se.Eval(scope)1249 }, createNodeFn, leftValues, rightValues, operators, expected, errorExpectations)1250}1251func runCompiledEvalBoolTests(1252 t *testing.T,1253 createNodeFn func(v interface{}) ast.Node,1254 leftValues []interface{},1255 rightValues []interface{},1256 operators []ast.TokenType,1257 expected map[keyStruct]interface{},1258 errorExpectations map[keyStruct]error) {1259 runCompiledEvalTests(t, evalCompiledBoolWithScope, createNodeFn, leftValues, rightValues, operators, expected, errorExpectations)1260}1261func evalCompiledBoolWithScope(t *testing.T, scope *stateful.Scope, n ast.Node) (interface{}, error) {1262 se, err := stateful.NewExpression(n)1263 if err != nil {1264 return nil, err1265 }1266 return se.EvalBool(scope)1267}1268func runCompiledEvalTests(1269 t *testing.T,1270 evalNodeFn func(t *testing.T, scope *stateful.Scope, n ast.Node) (interface{}, error),1271 createNodeFn func(v interface{}) ast.Node,1272 leftValues []interface{},1273 rightValues []interface{},1274 operators []ast.TokenType,1275 expected map[keyStruct]interface{},1276 errorExpectations map[keyStruct]error) {1277 for _, lhs := range leftValues {1278 for _, rhs := range rightValues {1279 for _, op := range operators {1280 t.Log("testing", lhs, op, rhs)1281 key := keyStruct{lhs, rhs, op}1282 exp, isExpectedResultOk := expected[key]1283 errorExpected, isErrorOk := errorExpectations[key]1284 if !isExpectedResultOk && !isErrorOk {1285 t.Fatalf("Couldn't find an expected result/error for: lhs: %v, rhs: %v, op: %v", lhs, rhs, op)1286 }1287 if isExpectedResultOk && isErrorOk {1288 t.Fatalf("Found both an expected result and an expected error for: lhs: %v, rhs: %v, op: %v", lhs, rhs, op)1289 }1290 // Test simple const values compares1291 emptyScope := stateful.NewScope()1292 result, err := evalNodeFn(t, emptyScope, &ast.BinaryNode{1293 Operator: op,1294 Left: createNodeFn(lhs),1295 Right: createNodeFn(rhs),1296 })1297 // This is bool matching, but not error matching..1298 if isExpectedResultOk && !isErrorOk && err != nil {1299 t.Errorf("Got an error while evaluating: %v %v %v -- %T %v %T -- %v\n", lhs, op, rhs, lhs, op, rhs, err)1300 } else {1301 // Expect value can be error or bool1302 if isErrorOk && errorExpected.Error() != err.Error() {1303 t.Errorf("unexpected error result: %v %v %v\ngot: %v\nexp: %v", lhs, op, rhs, err, errorExpected)1304 } else if isExpectedResultOk && exp != result {1305 t.Errorf("unexpected result: %v %v %v\ngot: %v\nexp: %v", lhs, op, rhs, result, exp)1306 }1307 }1308 t.Log("testing reference:", lhs, op, rhs)1309 // Test left is reference while the right is const1310 scope := stateful.NewScope()1311 scope.Set("value", lhs)1312 result, err = evalNodeFn(t, scope, &ast.BinaryNode{1313 Operator: op,1314 Left: &ast.ReferenceNode{1315 Reference: "value",1316 },1317 Right: createNodeFn(rhs),1318 })1319 if isErrorOk {1320 if err == nil {1321 t.Errorf("reference test: expected an error but got result: %v %v %v\nresult: %v\nerr: %v", lhs, op, rhs, result, err)1322 } else if errorExpected.Error() != err.Error() {1323 t.Errorf("reference test: unexpected error result: %v %v %v\ngot: %v\nexp: %v", lhs, op, rhs, err, errorExpected)1324 }1325 } else if isExpectedResultOk && exp != result {1326 t.Errorf("reference test: unexpected bool result: %v %v %v\ngot: %v\nexp: %v", lhs, op, rhs, result, exp)1327 }1328 }1329 }1330 }1331}1332func mustCompileExpression(node ast.Node) stateful.Expression {1333 se, err := stateful.NewExpression(node)1334 if err != nil {1335 panic(fmt.Sprintf("Failed to compile expression: %v", err))1336 }1337 return se1338}...
binary.go
Source:binary.go
1package values2import (3 "fmt"4 "math"5 "github.com/influxdata/flux/ast"6 "github.com/influxdata/flux/semantic"7)8type BinaryFunction func(l, r Value) (Value, error)9type BinaryFuncSignature struct {10 Operator ast.OperatorKind11 Left, Right semantic.Type12}13// LookupBinaryFunction returns an appropriate binary function that evaluates two values and returns another value.14// If the two types are not compatible with the given operation, this returns an error.15func LookupBinaryFunction(sig BinaryFuncSignature) (BinaryFunction, error) {16 f, ok := binaryFuncLookup[sig]17 if !ok {18 return nil, fmt.Errorf("unsupported binary expression %v %v %v", sig.Left, sig.Operator, sig.Right)19 }20 return binaryFuncNullCheck(f), nil21}22// binaryFuncNullCheck will wrap any BinaryFunction and23// check that both of the arguments are non-nil.24//25// If either value is null, then it will return null.26// Otherwise, it will invoke the function to retrieve the result.27func binaryFuncNullCheck(fn BinaryFunction) BinaryFunction {28 return func(lv, rv Value) (Value, error) {29 if lv.IsNull() || rv.IsNull() {30 return Null, nil31 }32 return fn(lv, rv)33 }34}35// binaryFuncLookup contains a mapping of BinaryFuncSignature's to36// the BinaryFunction that implements them.37//38// The values passed into these functions will be non-nil so a null39// check is unnecessary inside of them.40//41// Even though nulls will never be passed to these functions,42// the left or right type can be defined as nil. This is used to43// mark that it is valid to use the operator between those two types,44// but the function will never be invoked so it can be nil.45var binaryFuncLookup = map[BinaryFuncSignature]BinaryFunction{46 //---------------47 // Math Operators48 //---------------49 {Operator: ast.AdditionOperator, Left: semantic.Int, Right: semantic.Int}: func(lv, rv Value) (Value, error) {50 l := lv.Int()51 r := rv.Int()52 return NewInt(l + r), nil53 },54 {Operator: ast.AdditionOperator, Left: semantic.UInt, Right: semantic.UInt}: func(lv, rv Value) (Value, error) {55 l := lv.UInt()56 r := rv.UInt()57 return NewUInt(l + r), nil58 },59 {Operator: ast.AdditionOperator, Left: semantic.Float, Right: semantic.Float}: func(lv, rv Value) (Value, error) {60 l := lv.Float()61 r := rv.Float()62 return NewFloat(l + r), nil63 },64 {Operator: ast.AdditionOperator, Left: semantic.String, Right: semantic.String}: func(lv, rv Value) (Value, error) {65 l := lv.Str()66 r := rv.Str()67 return NewString(l + r), nil68 },69 {Operator: ast.AdditionOperator, Left: semantic.Nil, Right: semantic.Nil}: nil,70 {Operator: ast.SubtractionOperator, Left: semantic.Int, Right: semantic.Int}: func(lv, rv Value) (Value, error) {71 l := lv.Int()72 r := rv.Int()73 return NewInt(l - r), nil74 },75 {Operator: ast.SubtractionOperator, Left: semantic.UInt, Right: semantic.UInt}: func(lv, rv Value) (Value, error) {76 l := lv.UInt()77 r := rv.UInt()78 return NewUInt(l - r), nil79 },80 {Operator: ast.SubtractionOperator, Left: semantic.Float, Right: semantic.Float}: func(lv, rv Value) (Value, error) {81 l := lv.Float()82 r := rv.Float()83 return NewFloat(l - r), nil84 },85 {Operator: ast.SubtractionOperator, Left: semantic.Nil, Right: semantic.Nil}: nil,86 {Operator: ast.MultiplicationOperator, Left: semantic.Int, Right: semantic.Int}: func(lv, rv Value) (Value, error) {87 l := lv.Int()88 r := rv.Int()89 return NewInt(l * r), nil90 },91 {Operator: ast.MultiplicationOperator, Left: semantic.UInt, Right: semantic.UInt}: func(lv, rv Value) (Value, error) {92 l := lv.UInt()93 r := rv.UInt()94 return NewUInt(l * r), nil95 },96 {Operator: ast.MultiplicationOperator, Left: semantic.Float, Right: semantic.Float}: func(lv, rv Value) (Value, error) {97 l := lv.Float()98 r := rv.Float()99 return NewFloat(l * r), nil100 },101 {Operator: ast.MultiplicationOperator, Left: semantic.Nil, Right: semantic.Nil}: nil,102 {Operator: ast.DivisionOperator, Left: semantic.Int, Right: semantic.Int}: func(lv, rv Value) (Value, error) {103 l := lv.Int()104 r := rv.Int()105 if r == 0 {106 return nil, fmt.Errorf("cannot divide by zero")107 }108 return NewInt(l / r), nil109 },110 {Operator: ast.DivisionOperator, Left: semantic.UInt, Right: semantic.UInt}: func(lv, rv Value) (Value, error) {111 l := lv.UInt()112 r := rv.UInt()113 if r == 0 {114 return nil, fmt.Errorf("cannot divide by zero")115 }116 return NewUInt(l / r), nil117 },118 {Operator: ast.DivisionOperator, Left: semantic.Float, Right: semantic.Float}: func(lv, rv Value) (Value, error) {119 l := lv.Float()120 r := rv.Float()121 if r == 0 {122 return nil, fmt.Errorf("cannot divide by zero")123 }124 return NewFloat(l / r), nil125 },126 {Operator: ast.DivisionOperator, Left: semantic.Nil, Right: semantic.Nil}: nil,127 {Operator: ast.ModuloOperator, Left: semantic.Int, Right: semantic.Int}: func(lv, rv Value) (Value, error) {128 l := lv.Int()129 r := rv.Int()130 if r == 0 {131 return nil, fmt.Errorf("cannot mod zero")132 }133 return NewInt(l % r), nil134 },135 {Operator: ast.ModuloOperator, Left: semantic.UInt, Right: semantic.UInt}: func(lv, rv Value) (Value, error) {136 l := lv.UInt()137 r := rv.UInt()138 if r == 0 {139 return nil, fmt.Errorf("cannot mod zero")140 }141 return NewUInt(l % r), nil142 },143 {Operator: ast.ModuloOperator, Left: semantic.Float, Right: semantic.Float}: func(lv, rv Value) (Value, error) {144 l := lv.Float()145 r := rv.Float()146 if r == 0 {147 return nil, fmt.Errorf("cannot mod zero")148 }149 return NewFloat(math.Mod(l, r)), nil150 },151 {Operator: ast.ModuloOperator, Left: semantic.Nil, Right: semantic.Nil}: nil,152 {Operator: ast.PowerOperator, Left: semantic.Int, Right: semantic.Int}: func(lv, rv Value) (Value, error) {153 l := lv.Int()154 r := rv.Int()155 return NewFloat(math.Pow(float64(l), float64(r))), nil156 },157 {Operator: ast.PowerOperator, Left: semantic.UInt, Right: semantic.UInt}: func(lv, rv Value) (Value, error) {158 l := lv.UInt()159 r := rv.UInt()160 return NewFloat(math.Pow(float64(l), float64(r))), nil161 },162 {Operator: ast.PowerOperator, Left: semantic.Float, Right: semantic.Float}: func(lv, rv Value) (Value, error) {163 l := lv.Float()164 r := rv.Float()165 return NewFloat(math.Pow(float64(l), float64(r))), nil166 },167 {Operator: ast.PowerOperator, Left: semantic.Nil, Right: semantic.Nil}: nil,168 //---------------------169 // Comparison Operators170 //---------------------171 // LessThanEqualOperator172 {Operator: ast.LessThanEqualOperator, Left: semantic.Int, Right: semantic.Int}: func(lv, rv Value) (Value, error) {173 l := lv.Int()174 r := rv.Int()175 return NewBool(l <= r), nil176 },177 {Operator: ast.LessThanEqualOperator, Left: semantic.Int, Right: semantic.UInt}: func(lv, rv Value) (Value, error) {178 l := lv.Int()179 r := rv.UInt()180 if l < 0 {181 return NewBool(true), nil182 }183 return NewBool(uint64(l) <= r), nil184 },185 {Operator: ast.LessThanEqualOperator, Left: semantic.Int, Right: semantic.Float}: func(lv, rv Value) (Value, error) {186 l := lv.Int()187 r := rv.Float()188 return NewBool(float64(l) <= r), nil189 },190 {Operator: ast.LessThanEqualOperator, Left: semantic.Int, Right: semantic.Nil}: nil,191 {Operator: ast.LessThanEqualOperator, Left: semantic.UInt, Right: semantic.Int}: func(lv, rv Value) (Value, error) {192 l := lv.UInt()193 r := rv.Int()194 if r < 0 {195 return NewBool(false), nil196 }197 return NewBool(l <= uint64(r)), nil198 },199 {Operator: ast.LessThanEqualOperator, Left: semantic.UInt, Right: semantic.UInt}: func(lv, rv Value) (Value, error) {200 l := lv.UInt()201 r := rv.UInt()202 return NewBool(l <= r), nil203 },204 {Operator: ast.LessThanEqualOperator, Left: semantic.UInt, Right: semantic.Float}: func(lv, rv Value) (Value, error) {205 l := lv.UInt()206 r := rv.Float()207 return NewBool(float64(l) <= r), nil208 },209 {Operator: ast.LessThanEqualOperator, Left: semantic.UInt, Right: semantic.Nil}: nil,210 {Operator: ast.LessThanEqualOperator, Left: semantic.Float, Right: semantic.Int}: func(lv, rv Value) (Value, error) {211 l := lv.Float()212 r := rv.Int()213 return NewBool(l <= float64(r)), nil214 },215 {Operator: ast.LessThanEqualOperator, Left: semantic.Float, Right: semantic.UInt}: func(lv, rv Value) (Value, error) {216 l := lv.Float()217 r := rv.UInt()218 return NewBool(l <= float64(r)), nil219 },220 {Operator: ast.LessThanEqualOperator, Left: semantic.Float, Right: semantic.Float}: func(lv, rv Value) (Value, error) {221 l := lv.Float()222 r := rv.Float()223 return NewBool(l <= r), nil224 },225 {Operator: ast.LessThanEqualOperator, Left: semantic.Float, Right: semantic.Nil}: nil,226 {Operator: ast.LessThanEqualOperator, Left: semantic.String, Right: semantic.String}: func(lv, rv Value) (Value, error) {227 l := lv.Str()228 r := rv.Str()229 return NewBool(l <= r), nil230 },231 {Operator: ast.LessThanEqualOperator, Left: semantic.String, Right: semantic.Nil}: nil,232 {Operator: ast.LessThanEqualOperator, Left: semantic.Time, Right: semantic.Time}: func(lv, rv Value) (Value, error) {233 l := lv.Time().Time()234 r := rv.Time().Time()235 return NewBool(!l.After(r)), nil236 },237 {Operator: ast.LessThanEqualOperator, Left: semantic.Time, Right: semantic.Nil}: nil,238 {Operator: ast.LessThanEqualOperator, Left: semantic.Nil, Right: semantic.Int}: nil,239 {Operator: ast.LessThanEqualOperator, Left: semantic.Nil, Right: semantic.UInt}: nil,240 {Operator: ast.LessThanEqualOperator, Left: semantic.Nil, Right: semantic.Float}: nil,241 {Operator: ast.LessThanEqualOperator, Left: semantic.Nil, Right: semantic.String}: nil,242 {Operator: ast.LessThanEqualOperator, Left: semantic.Nil, Right: semantic.Time}: nil,243 {Operator: ast.LessThanEqualOperator, Left: semantic.Nil, Right: semantic.Nil}: nil,244 // LessThanOperator245 {Operator: ast.LessThanOperator, Left: semantic.Int, Right: semantic.Int}: func(lv, rv Value) (Value, error) {246 l := lv.Int()247 r := rv.Int()248 return NewBool(l < r), nil249 },250 {Operator: ast.LessThanOperator, Left: semantic.Int, Right: semantic.UInt}: func(lv, rv Value) (Value, error) {251 l := lv.Int()252 r := rv.UInt()253 if l < 0 {254 return NewBool(true), nil255 }256 return NewBool(uint64(l) < r), nil257 },258 {Operator: ast.LessThanOperator, Left: semantic.Int, Right: semantic.Float}: func(lv, rv Value) (Value, error) {259 l := lv.Int()260 r := rv.Float()261 return NewBool(float64(l) < r), nil262 },263 {Operator: ast.LessThanOperator, Left: semantic.Int, Right: semantic.Nil}: nil,264 {Operator: ast.LessThanOperator, Left: semantic.UInt, Right: semantic.Int}: func(lv, rv Value) (Value, error) {265 l := lv.UInt()266 r := rv.Int()267 if r < 0 {268 return NewBool(false), nil269 }270 return NewBool(l < uint64(r)), nil271 },272 {Operator: ast.LessThanOperator, Left: semantic.UInt, Right: semantic.UInt}: func(lv, rv Value) (Value, error) {273 l := lv.UInt()274 r := rv.UInt()275 return NewBool(l < r), nil276 },277 {Operator: ast.LessThanOperator, Left: semantic.UInt, Right: semantic.Float}: func(lv, rv Value) (Value, error) {278 l := lv.UInt()279 r := rv.Float()280 return NewBool(float64(l) < r), nil281 },282 {Operator: ast.LessThanOperator, Left: semantic.UInt, Right: semantic.Nil}: nil,283 {Operator: ast.LessThanOperator, Left: semantic.Float, Right: semantic.Int}: func(lv, rv Value) (Value, error) {284 l := lv.Float()285 r := rv.Int()286 return NewBool(l < float64(r)), nil287 },288 {Operator: ast.LessThanOperator, Left: semantic.Float, Right: semantic.UInt}: func(lv, rv Value) (Value, error) {289 l := lv.Float()290 r := rv.UInt()291 return NewBool(l < float64(r)), nil292 },293 {Operator: ast.LessThanOperator, Left: semantic.Float, Right: semantic.Float}: func(lv, rv Value) (Value, error) {294 l := lv.Float()295 r := rv.Float()296 return NewBool(l < r), nil297 },298 {Operator: ast.LessThanOperator, Left: semantic.Float, Right: semantic.Nil}: nil,299 {Operator: ast.LessThanOperator, Left: semantic.String, Right: semantic.String}: func(lv, rv Value) (Value, error) {300 l := lv.Str()301 r := rv.Str()302 return NewBool(l < r), nil303 },304 {Operator: ast.LessThanOperator, Left: semantic.String, Right: semantic.Nil}: nil,305 {Operator: ast.LessThanOperator, Left: semantic.Time, Right: semantic.Time}: func(lv, rv Value) (Value, error) {306 l := lv.Time().Time()307 r := rv.Time().Time()308 return NewBool(l.Before(r)), nil309 },310 {Operator: ast.LessThanOperator, Left: semantic.Time, Right: semantic.Nil}: nil,311 {Operator: ast.LessThanOperator, Left: semantic.Nil, Right: semantic.Int}: nil,312 {Operator: ast.LessThanOperator, Left: semantic.Nil, Right: semantic.UInt}: nil,313 {Operator: ast.LessThanOperator, Left: semantic.Nil, Right: semantic.Float}: nil,314 {Operator: ast.LessThanOperator, Left: semantic.Nil, Right: semantic.String}: nil,315 {Operator: ast.LessThanOperator, Left: semantic.Nil, Right: semantic.Time}: nil,316 {Operator: ast.LessThanOperator, Left: semantic.Nil, Right: semantic.Nil}: nil,317 // GreaterThanEqualOperator318 {Operator: ast.GreaterThanEqualOperator, Left: semantic.Int, Right: semantic.Int}: func(lv, rv Value) (Value, error) {319 l := lv.Int()320 r := rv.Int()321 return NewBool(l >= r), nil322 },323 {Operator: ast.GreaterThanEqualOperator, Left: semantic.Int, Right: semantic.UInt}: func(lv, rv Value) (Value, error) {324 l := lv.Int()325 r := rv.UInt()326 if l < 0 {327 return NewBool(true), nil328 }329 return NewBool(uint64(l) >= r), nil330 },331 {Operator: ast.GreaterThanEqualOperator, Left: semantic.Int, Right: semantic.Float}: func(lv, rv Value) (Value, error) {332 l := lv.Int()333 r := rv.Float()334 return NewBool(float64(l) >= r), nil335 },336 {Operator: ast.GreaterThanEqualOperator, Left: semantic.Int, Right: semantic.Nil}: nil,337 {Operator: ast.GreaterThanEqualOperator, Left: semantic.UInt, Right: semantic.Int}: func(lv, rv Value) (Value, error) {338 l := lv.UInt()339 r := rv.Int()340 if r < 0 {341 return NewBool(false), nil342 }343 return NewBool(l >= uint64(r)), nil344 },345 {Operator: ast.GreaterThanEqualOperator, Left: semantic.UInt, Right: semantic.UInt}: func(lv, rv Value) (Value, error) {346 l := lv.UInt()347 r := rv.UInt()348 return NewBool(l >= r), nil349 },350 {Operator: ast.GreaterThanEqualOperator, Left: semantic.UInt, Right: semantic.Float}: func(lv, rv Value) (Value, error) {351 l := lv.UInt()352 r := rv.Float()353 return NewBool(float64(l) >= r), nil354 },355 {Operator: ast.GreaterThanEqualOperator, Left: semantic.UInt, Right: semantic.Nil}: nil,356 {Operator: ast.GreaterThanEqualOperator, Left: semantic.Float, Right: semantic.Int}: func(lv, rv Value) (Value, error) {357 l := lv.Float()358 r := rv.Int()359 return NewBool(l >= float64(r)), nil360 },361 {Operator: ast.GreaterThanEqualOperator, Left: semantic.Float, Right: semantic.UInt}: func(lv, rv Value) (Value, error) {362 l := lv.Float()363 r := rv.UInt()364 return NewBool(l >= float64(r)), nil365 },366 {Operator: ast.GreaterThanEqualOperator, Left: semantic.Float, Right: semantic.Float}: func(lv, rv Value) (Value, error) {367 l := lv.Float()368 r := rv.Float()369 return NewBool(l >= r), nil370 },371 {Operator: ast.GreaterThanEqualOperator, Left: semantic.Float, Right: semantic.Nil}: nil,372 {Operator: ast.GreaterThanEqualOperator, Left: semantic.String, Right: semantic.String}: func(lv, rv Value) (Value, error) {373 l := lv.Str()374 r := rv.Str()375 return NewBool(l >= r), nil376 },377 {Operator: ast.GreaterThanEqualOperator, Left: semantic.String, Right: semantic.Nil}: nil,378 {Operator: ast.GreaterThanEqualOperator, Left: semantic.Time, Right: semantic.Time}: func(lv, rv Value) (Value, error) {379 l := lv.Time().Time()380 r := rv.Time().Time()381 return NewBool(!r.After(l)), nil382 },383 {Operator: ast.GreaterThanEqualOperator, Left: semantic.Time, Right: semantic.Nil}: nil,384 {Operator: ast.GreaterThanEqualOperator, Left: semantic.Nil, Right: semantic.Int}: nil,385 {Operator: ast.GreaterThanEqualOperator, Left: semantic.Nil, Right: semantic.UInt}: nil,386 {Operator: ast.GreaterThanEqualOperator, Left: semantic.Nil, Right: semantic.Float}: nil,387 {Operator: ast.GreaterThanEqualOperator, Left: semantic.Nil, Right: semantic.String}: nil,388 {Operator: ast.GreaterThanEqualOperator, Left: semantic.Nil, Right: semantic.Time}: nil,389 {Operator: ast.GreaterThanEqualOperator, Left: semantic.Nil, Right: semantic.Nil}: nil,390 // GreaterThanOperator391 {Operator: ast.GreaterThanOperator, Left: semantic.Int, Right: semantic.Int}: func(lv, rv Value) (Value, error) {392 l := lv.Int()393 r := rv.Int()394 return NewBool(l > r), nil395 },396 {Operator: ast.GreaterThanOperator, Left: semantic.Int, Right: semantic.UInt}: func(lv, rv Value) (Value, error) {397 l := lv.Int()398 r := rv.UInt()399 if l < 0 {400 return NewBool(true), nil401 }402 return NewBool(uint64(l) > r), nil403 },404 {Operator: ast.GreaterThanOperator, Left: semantic.Int, Right: semantic.Float}: func(lv, rv Value) (Value, error) {405 l := lv.Int()406 r := rv.Float()407 return NewBool(float64(l) > r), nil408 },409 {Operator: ast.GreaterThanOperator, Left: semantic.Int, Right: semantic.Nil}: nil,410 {Operator: ast.GreaterThanOperator, Left: semantic.UInt, Right: semantic.Int}: func(lv, rv Value) (Value, error) {411 l := lv.UInt()412 r := rv.Int()413 if r < 0 {414 return NewBool(false), nil415 }416 return NewBool(l > uint64(r)), nil417 },418 {Operator: ast.GreaterThanOperator, Left: semantic.UInt, Right: semantic.UInt}: func(lv, rv Value) (Value, error) {419 l := lv.UInt()420 r := rv.UInt()421 return NewBool(l > r), nil422 },423 {Operator: ast.GreaterThanOperator, Left: semantic.UInt, Right: semantic.Float}: func(lv, rv Value) (Value, error) {424 l := lv.UInt()425 r := rv.Float()426 return NewBool(float64(l) > r), nil427 },428 {Operator: ast.GreaterThanOperator, Left: semantic.UInt, Right: semantic.Nil}: nil,429 {Operator: ast.GreaterThanOperator, Left: semantic.Float, Right: semantic.Int}: func(lv, rv Value) (Value, error) {430 l := lv.Float()431 r := rv.Int()432 return NewBool(l > float64(r)), nil433 },434 {Operator: ast.GreaterThanOperator, Left: semantic.Float, Right: semantic.UInt}: func(lv, rv Value) (Value, error) {435 l := lv.Float()436 r := rv.UInt()437 return NewBool(l > float64(r)), nil438 },439 {Operator: ast.GreaterThanOperator, Left: semantic.Float, Right: semantic.Float}: func(lv, rv Value) (Value, error) {440 l := lv.Float()441 r := rv.Float()442 return NewBool(l > r), nil443 },444 {Operator: ast.GreaterThanOperator, Left: semantic.Float, Right: semantic.Nil}: nil,445 {Operator: ast.GreaterThanOperator, Left: semantic.String, Right: semantic.String}: func(lv, rv Value) (Value, error) {446 l := lv.Str()447 r := rv.Str()448 return NewBool(l > r), nil449 },450 {Operator: ast.GreaterThanOperator, Left: semantic.String, Right: semantic.Nil}: nil,451 {Operator: ast.GreaterThanOperator, Left: semantic.Time, Right: semantic.Time}: func(lv, rv Value) (Value, error) {452 l := lv.Time().Time()453 r := rv.Time().Time()454 return NewBool(l.After(r)), nil455 },456 {Operator: ast.GreaterThanOperator, Left: semantic.Time, Right: semantic.Nil}: nil,457 {Operator: ast.GreaterThanOperator, Left: semantic.Nil, Right: semantic.Int}: nil,458 {Operator: ast.GreaterThanOperator, Left: semantic.Nil, Right: semantic.UInt}: nil,459 {Operator: ast.GreaterThanOperator, Left: semantic.Nil, Right: semantic.Float}: nil,460 {Operator: ast.GreaterThanOperator, Left: semantic.Nil, Right: semantic.String}: nil,461 {Operator: ast.GreaterThanOperator, Left: semantic.Nil, Right: semantic.Time}: nil,462 {Operator: ast.GreaterThanOperator, Left: semantic.Nil, Right: semantic.Nil}: nil,463 // EqualOperator464 {Operator: ast.EqualOperator, Left: semantic.Int, Right: semantic.Int}: func(lv, rv Value) (Value, error) {465 l := lv.Int()466 r := rv.Int()467 return NewBool(l == r), nil468 },469 {Operator: ast.EqualOperator, Left: semantic.Int, Right: semantic.UInt}: func(lv, rv Value) (Value, error) {470 l := lv.Int()471 r := rv.UInt()472 if l < 0 {473 return NewBool(false), nil474 }475 return NewBool(uint64(l) == r), nil476 },477 {Operator: ast.EqualOperator, Left: semantic.Int, Right: semantic.Float}: func(lv, rv Value) (Value, error) {478 l := lv.Int()479 r := rv.Float()480 return NewBool(float64(l) == r), nil481 },482 {Operator: ast.EqualOperator, Left: semantic.Int, Right: semantic.Nil}: nil,483 {Operator: ast.EqualOperator, Left: semantic.UInt, Right: semantic.Int}: func(lv, rv Value) (Value, error) {484 l := lv.UInt()485 r := rv.Int()486 if r < 0 {487 return NewBool(false), nil488 }489 return NewBool(l == uint64(r)), nil490 },491 {Operator: ast.EqualOperator, Left: semantic.UInt, Right: semantic.UInt}: func(lv, rv Value) (Value, error) {492 l := lv.UInt()493 r := rv.UInt()494 return NewBool(l == r), nil495 },496 {Operator: ast.EqualOperator, Left: semantic.UInt, Right: semantic.Float}: func(lv, rv Value) (Value, error) {497 l := lv.UInt()498 r := rv.Float()499 return NewBool(float64(l) == r), nil500 },501 {Operator: ast.EqualOperator, Left: semantic.UInt, Right: semantic.Nil}: nil,502 {Operator: ast.EqualOperator, Left: semantic.Float, Right: semantic.Int}: func(lv, rv Value) (Value, error) {503 l := lv.Float()504 r := rv.Int()505 return NewBool(l == float64(r)), nil506 },507 {Operator: ast.EqualOperator, Left: semantic.Float, Right: semantic.UInt}: func(lv, rv Value) (Value, error) {508 l := lv.Float()509 r := rv.UInt()510 return NewBool(l == float64(r)), nil511 },512 {Operator: ast.EqualOperator, Left: semantic.Float, Right: semantic.Float}: func(lv, rv Value) (Value, error) {513 l := lv.Float()514 r := rv.Float()515 return NewBool(l == r), nil516 },517 {Operator: ast.EqualOperator, Left: semantic.Float, Right: semantic.Nil}: nil,518 {Operator: ast.EqualOperator, Left: semantic.String, Right: semantic.String}: func(lv, rv Value) (Value, error) {519 l := lv.Str()520 r := rv.Str()521 return NewBool(l == r), nil522 },523 {Operator: ast.EqualOperator, Left: semantic.String, Right: semantic.Nil}: nil,524 {Operator: ast.EqualOperator, Left: semantic.Time, Right: semantic.Time}: func(lv, rv Value) (Value, error) {525 l := lv.Time().Time()526 r := rv.Time().Time()527 return NewBool(l.Equal(r)), nil528 },529 {Operator: ast.EqualOperator, Left: semantic.Time, Right: semantic.Nil}: nil,530 {Operator: ast.EqualOperator, Left: semantic.Nil, Right: semantic.Int}: nil,531 {Operator: ast.EqualOperator, Left: semantic.Nil, Right: semantic.UInt}: nil,532 {Operator: ast.EqualOperator, Left: semantic.Nil, Right: semantic.Float}: nil,533 {Operator: ast.EqualOperator, Left: semantic.Nil, Right: semantic.String}: nil,534 {Operator: ast.EqualOperator, Left: semantic.Nil, Right: semantic.Time}: nil,535 {Operator: ast.EqualOperator, Left: semantic.Nil, Right: semantic.Nil}: nil,536 // NotEqualOperator537 {Operator: ast.NotEqualOperator, Left: semantic.Int, Right: semantic.Int}: func(lv, rv Value) (Value, error) {538 l := lv.Int()539 r := rv.Int()540 return NewBool(l != r), nil541 },542 {Operator: ast.NotEqualOperator, Left: semantic.Int, Right: semantic.UInt}: func(lv, rv Value) (Value, error) {543 l := lv.Int()544 r := rv.UInt()545 if l < 0 {546 return NewBool(true), nil547 }548 return NewBool(uint64(l) != r), nil549 },550 {Operator: ast.NotEqualOperator, Left: semantic.Int, Right: semantic.Float}: func(lv, rv Value) (Value, error) {551 l := lv.Int()552 r := rv.Float()553 return NewBool(float64(l) != r), nil554 },555 {Operator: ast.NotEqualOperator, Left: semantic.Int, Right: semantic.Nil}: nil,556 {Operator: ast.NotEqualOperator, Left: semantic.UInt, Right: semantic.Int}: func(lv, rv Value) (Value, error) {557 l := lv.UInt()558 r := rv.Int()559 if r < 0 {560 return NewBool(true), nil561 }562 return NewBool(l != uint64(r)), nil563 },564 {Operator: ast.NotEqualOperator, Left: semantic.UInt, Right: semantic.UInt}: func(lv, rv Value) (Value, error) {565 l := lv.UInt()566 r := rv.UInt()567 return NewBool(l != r), nil568 },569 {Operator: ast.NotEqualOperator, Left: semantic.UInt, Right: semantic.Float}: func(lv, rv Value) (Value, error) {570 l := lv.UInt()571 r := rv.Float()572 return NewBool(float64(l) != r), nil573 },574 {Operator: ast.NotEqualOperator, Left: semantic.UInt, Right: semantic.Nil}: nil,575 {Operator: ast.NotEqualOperator, Left: semantic.Float, Right: semantic.Int}: func(lv, rv Value) (Value, error) {576 l := lv.Float()577 r := rv.Int()578 return NewBool(l != float64(r)), nil579 },580 {Operator: ast.NotEqualOperator, Left: semantic.Float, Right: semantic.UInt}: func(lv, rv Value) (Value, error) {581 l := lv.Float()582 r := rv.UInt()583 return NewBool(l != float64(r)), nil584 },585 {Operator: ast.NotEqualOperator, Left: semantic.Float, Right: semantic.Float}: func(lv, rv Value) (Value, error) {586 l := lv.Float()587 r := rv.Float()588 return NewBool(l != r), nil589 },590 {Operator: ast.NotEqualOperator, Left: semantic.Float, Right: semantic.Nil}: nil,591 {Operator: ast.NotEqualOperator, Left: semantic.String, Right: semantic.String}: func(lv, rv Value) (Value, error) {592 l := lv.Str()593 r := rv.Str()594 return NewBool(l != r), nil595 },596 {Operator: ast.NotEqualOperator, Left: semantic.String, Right: semantic.Nil}: nil,597 {Operator: ast.NotEqualOperator, Left: semantic.Time, Right: semantic.Time}: func(lv, rv Value) (Value, error) {598 l := lv.Time().Time()599 r := rv.Time().Time()600 return NewBool(!l.Equal(r)), nil601 },602 {Operator: ast.NotEqualOperator, Left: semantic.Time, Right: semantic.Nil}: nil,603 {Operator: ast.NotEqualOperator, Left: semantic.Nil, Right: semantic.Int}: nil,604 {Operator: ast.NotEqualOperator, Left: semantic.Nil, Right: semantic.UInt}: nil,605 {Operator: ast.NotEqualOperator, Left: semantic.Nil, Right: semantic.Float}: nil,606 {Operator: ast.NotEqualOperator, Left: semantic.Nil, Right: semantic.String}: nil,607 {Operator: ast.NotEqualOperator, Left: semantic.Nil, Right: semantic.Time}: nil,608 {Operator: ast.NotEqualOperator, Left: semantic.Nil, Right: semantic.Nil}: nil,609 {Operator: ast.RegexpMatchOperator, Left: semantic.String, Right: semantic.Regexp}: func(lv, rv Value) (Value, error) {610 l := lv.Str()611 r := rv.Regexp()612 return NewBool(r.MatchString(l)), nil613 },614 {Operator: ast.NotRegexpMatchOperator, Left: semantic.String, Right: semantic.Regexp}: func(lv, rv Value) (Value, error) {615 l := lv.Str()616 r := rv.Regexp()617 return NewBool(!r.MatchString(l)), nil618 },619}...
ineq.go
Source:ineq.go
1// Copyright 2016 The OPA Authors. All rights reserved.2// Use of this source code is governed by an Apache23// license that can be found in the LICENSE file.4package topdown5import "github.com/open-policy-agent/opa/ast"6type compareFunc func(a, b ast.Value) bool7func compareGreaterThan(a, b ast.Value) bool {8 return ast.Compare(a, b) > 09}10func compareGreaterThanEq(a, b ast.Value) bool {11 return ast.Compare(a, b) >= 012}13func compareLessThan(a, b ast.Value) bool {14 return ast.Compare(a, b) < 015}16func compareLessThanEq(a, b ast.Value) bool {17 return ast.Compare(a, b) <= 018}19func compareNotEq(a, b ast.Value) bool {20 return ast.Compare(a, b) != 021}22func builtinCompare(cmp compareFunc) FunctionalBuiltin2 {23 return func(a, b ast.Value) (ast.Value, error) {24 if !cmp(a, b) {25 return nil, BuiltinEmpty{}26 }27 return ast.Boolean(true), nil28 }29}30func init() {31 RegisterFunctionalBuiltin2(ast.GreaterThan.Name, builtinCompare(compareGreaterThan))32 RegisterFunctionalBuiltin2(ast.GreaterThanEq.Name, builtinCompare(compareGreaterThanEq))33 RegisterFunctionalBuiltin2(ast.LessThan.Name, builtinCompare(compareLessThan))34 RegisterFunctionalBuiltin2(ast.LessThanEq.Name, builtinCompare(compareLessThanEq))35 RegisterFunctionalBuiltin2(ast.NotEqual.Name, builtinCompare(compareNotEq))36}...
less
Using AI Code Generation
1import (2func main() {3 fset := token.NewFileSet()4 f, err := parser.ParseFile(fset, "1.go", nil, parser.ImportsOnly)5 if err != nil {6 fmt.Println(err)7 }8 for _, s := range f.Imports {9 fmt.Println(s.Path.Value)10 }11}12import (13func main() {14 fset := token.NewFileSet()15 f, err := parser.ParseFile(fset, "1.go", nil, parser.ParseComments)16 if err != nil {17 fmt.Println(err)18 }19 for _, c := range f.Comments {20 fmt.Println(c.Text())21 }22}23import (24func main() {25 fset := token.NewFileSet()26 f, err := parser.ParseFile(fset, "1.go", nil, parser.ImportsOnly)27 if err != nil {28 fmt.Println(err)29 }30 for _, s := range f.Imports {31 fmt.Println(s.Path.Value)32 }33}
less
Using AI Code Generation
1import (2func main() {3 f, err := parser.ParseFile(fset, "1.go", nil, parser.ImportsOnly)4 if err != nil {5 fmt.Println(err)6 }7 for _, s := range f.Imports {8 fmt.Println(s.Path.Value)9 }10 f, err = parser.ParseFile(fset, "1.go", nil, parser.ImportsOnly)11 if err != nil {12 fmt.Println(err)13 }14 for _, s := range f.Imports {15 fmt.Println(s.Path.Value)16 }17 f, err = parser.ParseFile(fset, "1.go", nil, parser.ImportsOnly)18 if err != nil {19 fmt.Println(err)20 }21 for _, s := range f.Imports {22 fmt.Println(s.Path.Value)23 }24 f, err = parser.ParseFile(fset, "1.go", nil, parser.ImportsOnly)25 if err != nil {26 fmt.Println(err)27 }28 for _, s := range f.Imports {29 fmt.Println(s.Path.Value)30 }31 f, err = parser.ParseFile(fset, "1.go", nil, parser.ImportsOnly)32 if err != nil {33 fmt.Println(err)34 }35 for _, s := range f.Imports {36 fmt.Println(s.Path.Value)37 }38 f, err = parser.ParseFile(fset, "1.go", nil, parser.ImportsOnly)39 if err != nil {
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!