func TestEvalFunctionNode_EvalFloat64_Sanity(t *testing.T) { evaluator, err := stateful.NewEvalFunctionNode(&ast.FunctionNode{ Func: "abs", Args: []ast.Node{ &ast.NumberNode{ IsFloat: true, Float64: float64(-1), }, }, }) if err != nil { t.Fatalf("Failed to create node evaluator: %v", err) } result, err := evaluator.EvalFloat(stateful.NewScope(), stateful.CreateExecutionState()) if err != nil { t.Errorf("Expected a result, but got error - %v", err) return } if result != float64(1) { t.Errorf("unexpected result: got: %T(%v), expected: float64(1)", result, result) } }
func TestEvalFunctionNode_FailedToEvaluateArgumentNodes(t *testing.T) { // bool("value"), where in our case "value" won't exist evaluator, err := stateful.NewEvalFunctionNode(&ast.FunctionNode{ Func: "bool", Args: []ast.Node{ &ast.ReferenceNode{Reference: "value"}, }, }) if err != nil { t.Fatalf("Failed to create node evaluator: %v", err) } result, err := evaluator.EvalBool(stateful.NewScope(), stateful.CreateExecutionState()) expectedError := errors.New("Failed to handle 1 argument: name \"value\" is undefined. Names in scope:") if err == nil { t.Errorf("Expected an error, but got nil error and result (%t)", result) return } if strings.TrimSpace(err.Error()) != expectedError.Error() { t.Errorf("Got unexpected error:\ngot: %v\nexpected: %v\n", err, expectedError) } }
func TestEvalFunctionNode_EvalInt64_KeepConsistentState(t *testing.T) { evaluator, err := stateful.NewEvalFunctionNode(&ast.FunctionNode{ Func: "count", Args: []ast.Node{}, }) if err != nil { t.Fatalf("Failed to create node evaluator: %v", err) } executionState := stateful.CreateExecutionState() // first evaluation result, err := evaluator.EvalInt(stateful.NewScope(), executionState) if err != nil { t.Errorf("first evaluation: Expected a result, but got error - %v", err) return } if result != int64(1) { t.Errorf("first evaluation: unexpected result: got: %T(%v), expected: int64(1)", result, result) } // second evaluation result, err = evaluator.EvalInt(stateful.NewScope(), executionState) if err != nil { t.Errorf("second evaluation: Expected a result, but got error - %v", err) return } if result != int64(2) { t.Errorf("second evaluation: unexpected result: got: %T(%v), expected: int64(2)", result, result) } }
func TestEvalFunctionNode_InvalidNodeAsArgument(t *testing.T) { evaluator, err := stateful.NewEvalFunctionNode(&ast.FunctionNode{ Args: []ast.Node{&ast.CommentNode{}}, }) expectedError := errors.New("Failed to handle 1 argument: Given node type is not valid evaluation node: *ast.CommentNode") if err == nil && evaluator != nil { t.Error("Expected an error, but go nil error and evaluator") return } if err.Error() != expectedError.Error() { t.Errorf("Got unexpected error:\ngot: %v\nexpected: %v\n", err, expectedError) } }
func TestEvalFunctionNode_EvalBool_Sanity(t *testing.T) { evaluator, err := stateful.NewEvalFunctionNode(&ast.FunctionNode{ Func: "bool", Args: []ast.Node{&ast.StringNode{Literal: "true"}}, }) if err != nil { t.Fatalf("Failed to create node evaluator: %v", err) } result, err := evaluator.EvalBool(stateful.NewScope(), stateful.CreateExecutionState()) if err != nil { t.Errorf("Expected a result, but got error - %v", err) return } if !result { t.Errorf("unexpected result: got: %v, expected: true", result) } }
func TestEvalFunctionNode_AryMismatch(t *testing.T) { evaluator, err := stateful.NewEvalFunctionNode(&ast.FunctionNode{ Func: "sigma", Args: []ast.Node{&ast.BoolNode{Bool: true}}, }) if err != nil { t.Fatalf("Failed to create node evaluator: %v", err) } result, err := evaluator.EvalFloat(stateful.NewScope(), stateful.CreateExecutionState()) expectedError := errors.New("error calling \"sigma\": value is not a float") if err == nil { t.Errorf("Expected an error, but got nil error and result (%v)", result) return } if strings.TrimSpace(err.Error()) != expectedError.Error() { t.Errorf("Got unexpected error:\ngot: %v\nexpected: %v\n", err, expectedError) } }
func TestEvalFunctionNode_UndefinedFunction(t *testing.T) { evaluator, err := stateful.NewEvalFunctionNode(&ast.FunctionNode{ Func: "yosi_the_king", Args: []ast.Node{}, }) if err != nil { t.Fatalf("Failed to create node evaluator: %v", err) } result, err := evaluator.EvalBool(stateful.NewScope(), stateful.CreateExecutionState()) expectedError := errors.New("undefined function: \"yosi_the_king\"") if err == nil { t.Errorf("Expected an error, but got nil error and result (%t)", result) return } if strings.TrimSpace(err.Error()) != expectedError.Error() { t.Errorf("Got unexpected error:\ngot: %v\nexpected: %v\n", err, expectedError) } }
func TestEvalFunctionNode_EvalInt64_Reset(t *testing.T) { evaluator, err := stateful.NewEvalFunctionNode(&ast.FunctionNode{ Func: "count", Args: []ast.Node{}, }) if err != nil { t.Fatalf("Failed to create node evaluator: %v", err) } executionState := stateful.CreateExecutionState() // first evaluation result, err := evaluator.EvalInt(stateful.NewScope(), executionState) if err != nil { t.Errorf("first evaluation: Expected a result, but got error - %v", err) return } if result != int64(1) { t.Errorf("first evaluation: unexpected result: got: %T(%v), expected: int64(1)", result, result) } // reset (we don't call ResetAll on ExecutionState in order to isolate the scope of this test) for _, fnc := range executionState.Funcs { fnc.Reset() } // second evaluation result, err = evaluator.EvalInt(stateful.NewScope(), executionState) if err != nil { t.Errorf("second evaluation (after reset): Expected a result, but got error - %v", err) return } if result != int64(1) { t.Errorf("second evaluation (after reset): unexpected result: got: %T(%v), expected: int64(1)", result, result) } }
func TestEvalFunctionNode_ComplexNodes(t *testing.T) { // pow("x" * 2, -"y") => pow(4, -1) evaluator, err := stateful.NewEvalFunctionNode(&ast.FunctionNode{ Func: "pow", Args: []ast.Node{ // "x" * 2 &ast.BinaryNode{ Operator: ast.TokenMult, Left: &ast.ReferenceNode{Reference: "x"}, Right: &ast.NumberNode{IsFloat: true, Float64: float64(2)}, }, // -"y" &ast.UnaryNode{ Operator: ast.TokenMinus, Node: &ast.ReferenceNode{Reference: "y"}, }, }, }) if err != nil { t.Fatalf("Failed to create node evaluator: %v", err) } scope := stateful.NewScope() scope.Set("x", float64(2)) scope.Set("y", float64(1)) result, err := evaluator.EvalFloat(scope, stateful.CreateExecutionState()) if err != nil { t.Errorf("Expected a result, but got error - %v", err) return } if result != float64(0.25) { t.Errorf("unexpected result: got: %T(%v), expected: float64(0.25)", result, result) } }