/vendor/github.com/Knetic/govaluate/evaluationFailure_test.go
https://github.com/kevin-hf/education · Go · 484 lines · 381 code · 92 blank · 11 comment · 23 complexity · 9935891dbde16f20cc24a39122ac5e8e MD5 · raw file
- package govaluate
- /*
- Tests to make sure evaluation fails in the expected ways.
- */
- import (
- "errors"
- "fmt"
- "strings"
- "testing"
- )
- type DebugStruct struct {
- x int
- }
- /*
- Represents a test for parsing failures
- */
- type EvaluationFailureTest struct {
- Name string
- Input string
- Functions map[string]ExpressionFunction
- Parameters map[string]interface{}
- Expected string
- }
- const (
- INVALID_MODIFIER_TYPES string = "cannot be used with the modifier"
- INVALID_COMPARATOR_TYPES = "cannot be used with the comparator"
- INVALID_LOGICALOP_TYPES = "cannot be used with the logical operator"
- INVALID_TERNARY_TYPES = "cannot be used with the ternary operator"
- ABSENT_PARAMETER = "No parameter"
- INVALID_REGEX = "Unable to compile regexp pattern"
- )
- // preset parameter map of types that can be used in an evaluation failure test to check typing.
- var EVALUATION_FAILURE_PARAMETERS = map[string]interface{}{
- "number": 1,
- "string": "foo",
- "bool": true,
- }
- func TestComplexParameter(test *testing.T) {
- var expression *EvaluableExpression
- var err error
- var v interface{}
- parameters := map[string]interface{}{
- "complex64": complex64(0),
- "complex128": complex128(0),
- }
- expression, _ = NewEvaluableExpression("complex64")
- v, err = expression.Evaluate(parameters)
- if err != nil {
- test.Errorf("Expected no error, but have %s", err)
- }
- if v.(complex64) != complex64(0) {
- test.Errorf("Expected %v == %v", v, complex64(0))
- }
- expression, _ = NewEvaluableExpression("complex128")
- v, err = expression.Evaluate(parameters)
- if err != nil {
- test.Errorf("Expected no error, but have %s", err)
- }
- if v.(complex128) != complex128(0) {
- test.Errorf("Expected %v == %v", v, complex128(0))
- }
- }
- func TestStructParameter(t *testing.T) {
- expected := DebugStruct{}
- expression, _ := NewEvaluableExpression("foo")
- parameters := map[string]interface{}{"foo": expected}
- v, err := expression.Evaluate(parameters)
- if err != nil {
- t.Errorf("Expected no error, but have %s", err)
- } else if v.(DebugStruct) != expected {
- t.Errorf("Values mismatch: %v != %v", expected, v)
- }
- }
- func TestNilParameterUsage(test *testing.T) {
- evaluationTests := []EvaluationFailureTest{
- EvaluationFailureTest{
- Name: "Absent parameter used",
- Input: "foo > 1",
- Expected: ABSENT_PARAMETER,
- },
- }
- runEvaluationFailureTests(evaluationTests, test)
- }
- func TestModifierTyping(test *testing.T) {
- evaluationTests := []EvaluationFailureTest{
- EvaluationFailureTest{
- Name: "PLUS literal number to literal bool",
- Input: "1 + true",
- Expected: INVALID_MODIFIER_TYPES,
- },
- EvaluationFailureTest{
- Name: "PLUS number to bool",
- Input: "number + bool",
- Expected: INVALID_MODIFIER_TYPES,
- },
- EvaluationFailureTest{
- Name: "MINUS number to bool",
- Input: "number - bool",
- Expected: INVALID_MODIFIER_TYPES,
- },
- EvaluationFailureTest{
- Name: "MINUS number to bool",
- Input: "number - bool",
- Expected: INVALID_MODIFIER_TYPES,
- },
- EvaluationFailureTest{
- Name: "MULTIPLY number to bool",
- Input: "number * bool",
- Expected: INVALID_MODIFIER_TYPES,
- },
- EvaluationFailureTest{
- Name: "DIVIDE number to bool",
- Input: "number / bool",
- Expected: INVALID_MODIFIER_TYPES,
- },
- EvaluationFailureTest{
- Name: "EXPONENT number to bool",
- Input: "number ** bool",
- Expected: INVALID_MODIFIER_TYPES,
- },
- EvaluationFailureTest{
- Name: "MODULUS number to bool",
- Input: "number % bool",
- Expected: INVALID_MODIFIER_TYPES,
- },
- EvaluationFailureTest{
- Name: "XOR number to bool",
- Input: "number % bool",
- Expected: INVALID_MODIFIER_TYPES,
- },
- EvaluationFailureTest{
- Name: "BITWISE_OR number to bool",
- Input: "number | bool",
- Expected: INVALID_MODIFIER_TYPES,
- },
- EvaluationFailureTest{
- Name: "BITWISE_AND number to bool",
- Input: "number & bool",
- Expected: INVALID_MODIFIER_TYPES,
- },
- EvaluationFailureTest{
- Name: "BITWISE_XOR number to bool",
- Input: "number ^ bool",
- Expected: INVALID_MODIFIER_TYPES,
- },
- EvaluationFailureTest{
- Name: "BITWISE_LSHIFT number to bool",
- Input: "number << bool",
- Expected: INVALID_MODIFIER_TYPES,
- },
- EvaluationFailureTest{
- Name: "BITWISE_RSHIFT number to bool",
- Input: "number >> bool",
- Expected: INVALID_MODIFIER_TYPES,
- },
- }
- runEvaluationFailureTests(evaluationTests, test)
- }
- func TestLogicalOperatorTyping(test *testing.T) {
- evaluationTests := []EvaluationFailureTest{
- EvaluationFailureTest{
- Name: "AND number to number",
- Input: "number && number",
- Expected: INVALID_LOGICALOP_TYPES,
- },
- EvaluationFailureTest{
- Name: "OR number to number",
- Input: "number || number",
- Expected: INVALID_LOGICALOP_TYPES,
- },
- EvaluationFailureTest{
- Name: "AND string to string",
- Input: "string && string",
- Expected: INVALID_LOGICALOP_TYPES,
- },
- EvaluationFailureTest{
- Name: "OR string to string",
- Input: "string || string",
- Expected: INVALID_LOGICALOP_TYPES,
- },
- EvaluationFailureTest{
- Name: "AND number to string",
- Input: "number && string",
- Expected: INVALID_LOGICALOP_TYPES,
- },
- EvaluationFailureTest{
- Name: "OR number to string",
- Input: "number || string",
- Expected: INVALID_LOGICALOP_TYPES,
- },
- EvaluationFailureTest{
- Name: "AND bool to string",
- Input: "bool && string",
- Expected: INVALID_LOGICALOP_TYPES,
- },
- EvaluationFailureTest{
- Name: "OR string to bool",
- Input: "string || bool",
- Expected: INVALID_LOGICALOP_TYPES,
- },
- }
- runEvaluationFailureTests(evaluationTests, test)
- }
- /*
- While there is type-safe transitions checked at parse-time, tested in the "parsing_test" and "parsingFailure_test" files,
- we also need to make sure that we receive type mismatch errors during evaluation.
- */
- func TestComparatorTyping(test *testing.T) {
- evaluationTests := []EvaluationFailureTest{
- EvaluationFailureTest{
- Name: "GT literal bool to literal bool",
- Input: "true > true",
- Expected: INVALID_COMPARATOR_TYPES,
- },
- EvaluationFailureTest{
- Name: "GT bool to bool",
- Input: "bool > bool",
- Expected: INVALID_COMPARATOR_TYPES,
- },
- EvaluationFailureTest{
- Name: "GTE bool to bool",
- Input: "bool >= bool",
- Expected: INVALID_COMPARATOR_TYPES,
- },
- EvaluationFailureTest{
- Name: "LT bool to bool",
- Input: "bool < bool",
- Expected: INVALID_COMPARATOR_TYPES,
- },
- EvaluationFailureTest{
- Name: "LTE bool to bool",
- Input: "bool <= bool",
- Expected: INVALID_COMPARATOR_TYPES,
- },
- EvaluationFailureTest{
- Name: "GT number to string",
- Input: "number > string",
- Expected: INVALID_COMPARATOR_TYPES,
- },
- EvaluationFailureTest{
- Name: "GTE number to string",
- Input: "number >= string",
- Expected: INVALID_COMPARATOR_TYPES,
- },
- EvaluationFailureTest{
- Name: "LT number to string",
- Input: "number < string",
- Expected: INVALID_COMPARATOR_TYPES,
- },
- EvaluationFailureTest{
- Name: "REQ number to string",
- Input: "number =~ string",
- Expected: INVALID_COMPARATOR_TYPES,
- },
- EvaluationFailureTest{
- Name: "REQ number to bool",
- Input: "number =~ bool",
- Expected: INVALID_COMPARATOR_TYPES,
- },
- EvaluationFailureTest{
- Name: "REQ bool to number",
- Input: "bool =~ number",
- Expected: INVALID_COMPARATOR_TYPES,
- },
- EvaluationFailureTest{
- Name: "REQ bool to string",
- Input: "bool =~ string",
- Expected: INVALID_COMPARATOR_TYPES,
- },
- EvaluationFailureTest{
- Name: "NREQ number to string",
- Input: "number !~ string",
- Expected: INVALID_COMPARATOR_TYPES,
- },
- EvaluationFailureTest{
- Name: "NREQ number to bool",
- Input: "number !~ bool",
- Expected: INVALID_COMPARATOR_TYPES,
- },
- EvaluationFailureTest{
- Name: "NREQ bool to number",
- Input: "bool !~ number",
- Expected: INVALID_COMPARATOR_TYPES,
- },
- EvaluationFailureTest{
- Name: "NREQ bool to string",
- Input: "bool !~ string",
- Expected: INVALID_COMPARATOR_TYPES,
- },
- EvaluationFailureTest{
- Name: "IN non-array numeric",
- Input: "1 in 2",
- Expected: INVALID_COMPARATOR_TYPES,
- },
- EvaluationFailureTest{
- Name: "IN non-array string",
- Input: "1 in 'foo'",
- Expected: INVALID_COMPARATOR_TYPES,
- },
- EvaluationFailureTest{
- Name: "IN non-array boolean",
- Input: "1 in true",
- Expected: INVALID_COMPARATOR_TYPES,
- },
- }
- runEvaluationFailureTests(evaluationTests, test)
- }
- func TestTernaryTyping(test *testing.T) {
- evaluationTests := []EvaluationFailureTest{
- EvaluationFailureTest{
- Name: "Ternary with number",
- Input: "10 ? true",
- Expected: INVALID_TERNARY_TYPES,
- },
- EvaluationFailureTest{
- Name: "Ternary with string",
- Input: "'foo' ? true",
- Expected: INVALID_TERNARY_TYPES,
- },
- }
- runEvaluationFailureTests(evaluationTests, test)
- }
- func TestRegexParameterCompilation(test *testing.T) {
- evaluationTests := []EvaluationFailureTest{
- EvaluationFailureTest{
- Name: "Regex equality runtime parsing",
- Input: "'foo' =~ foo",
- Parameters: map[string]interface{}{
- "foo": "[foo",
- },
- Expected: INVALID_REGEX,
- },
- EvaluationFailureTest{
- Name: "Regex inequality runtime parsing",
- Input: "'foo' =~ foo",
- Parameters: map[string]interface{}{
- "foo": "[foo",
- },
- Expected: INVALID_REGEX,
- },
- }
- runEvaluationFailureTests(evaluationTests, test)
- }
- func TestFunctionExecution(test *testing.T) {
- evaluationTests := []EvaluationFailureTest{
- EvaluationFailureTest{
- Name: "Function error bubbling",
- Input: "error()",
- Functions: map[string]ExpressionFunction{
- "error": func(arguments ...interface{}) (interface{}, error) {
- return nil, errors.New("Huge problems")
- },
- },
- Expected: "Huge problems",
- },
- }
- runEvaluationFailureTests(evaluationTests, test)
- }
- func runEvaluationFailureTests(evaluationTests []EvaluationFailureTest, test *testing.T) {
- var expression *EvaluableExpression
- var err error
- fmt.Printf("Running %d negative parsing test cases...\n", len(evaluationTests))
- for _, testCase := range evaluationTests {
- if len(testCase.Functions) > 0 {
- expression, err = NewEvaluableExpressionWithFunctions(testCase.Input, testCase.Functions)
- } else {
- expression, err = NewEvaluableExpression(testCase.Input)
- }
- if err != nil {
- test.Logf("Test '%s' failed", testCase.Name)
- test.Logf("Expected evaluation error, but got parsing error: '%s'", err)
- test.Fail()
- continue
- }
- if testCase.Parameters == nil {
- testCase.Parameters = EVALUATION_FAILURE_PARAMETERS
- }
- _, err = expression.Evaluate(testCase.Parameters)
- if err == nil {
- test.Logf("Test '%s' failed", testCase.Name)
- test.Logf("Expected error, received none.")
- test.Fail()
- continue
- }
- if !strings.Contains(err.Error(), testCase.Expected) {
- test.Logf("Test '%s' failed", testCase.Name)
- test.Logf("Got error: '%s', expected '%s'", err.Error(), testCase.Expected)
- test.Fail()
- continue
- }
- }
- }