diff --git a/api/nfd/v1alpha1/types.go b/api/nfd/v1alpha1/types.go index 79c0c2891..c7994bd33 100644 --- a/api/nfd/v1alpha1/types.go +++ b/api/nfd/v1alpha1/types.go @@ -296,16 +296,44 @@ type MatchExpression struct { // In other cases Value should contain at least one element. // +optional Value MatchValue `json:"value,omitempty"` + + // Type defines the value type for specific operators. + // The currently supported type is 'version' for Gt,Ge,Lt,Le,GtLt,GeLe operators. + // +optional + Type ValueType `json:"type,omitempty"` } // MatchOp is the match operator that is applied on values when evaluating a // MatchExpression. -// +kubebuilder:validation:Enum="In";"NotIn";"InRegexp";"Exists";"DoesNotExist";"Gt";"Lt";"GtLt";"IsTrue";"IsFalse" +// +kubebuilder:validation:Enum="In";"NotIn";"InRegexp";"Exists";"DoesNotExist";"Gt";"Ge";"Lt";"Le";"GtLt";"GeLe";"IsTrue";"IsFalse" type MatchOp string // MatchValue is the list of values associated with a MatchExpression. type MatchValue []string +// VersionComparisonResult represents the output of versions comparison. +type VersionComparisonResult int + +const ( + // CmpGt returns 1 when version1 > version2 + CmpGt VersionComparisonResult = 1 + // CmpLt returns -1 when version1 < version2 + CmpLt VersionComparisonResult = -1 + // CmpEq returns 0 when version1 == version2 + CmpEq VersionComparisonResult = 0 +) + +// ValueType represents the type of value in the expression. +type ValueType string + +const ( + // TypeVersion represents a version with the following supported formats: + // %d.%d.%d (e.g., 1.2.3), + // %d.%d (e.g., 1.2), + // %d (e.g., 1) + TypeVersion ValueType = "version" +) + const ( // MatchAny returns always true. MatchAny MatchOp = "" diff --git a/api/nfd/v1alpha1/utils.go b/api/nfd/v1alpha1/utils.go index 49c34a426..1fe1ca041 100644 --- a/api/nfd/v1alpha1/utils.go +++ b/api/nfd/v1alpha1/utils.go @@ -18,6 +18,8 @@ package v1alpha1 import ( "fmt" + "strconv" + "strings" ) // String represents the match expression as a string type. @@ -27,3 +29,59 @@ func (m MatchExpression) String() string { } return fmt.Sprintf("{op: %q, value: %q}", m.Op, m.Value) } + +// ExtractVersion extracts version from string with the following formats: +// %d.%d.%d (e.g., 1.2.3) +// %d.%d (e.g., 1.2) +// %d (e.g., 1) +func ExtractVersion(s string) (string, error) { + var major, minor, patch int + + _, err := fmt.Sscanf(s, "%d.%d.%d", &major, &minor, &patch) + if err == nil { + return fmt.Sprintf("%d.%d.%d", major, minor, patch), nil + } + + _, err = fmt.Sscanf(s, "%d.%d", &major, &minor) + if err == nil { + return fmt.Sprintf("%d.%d", major, minor), nil + } + + _, err = fmt.Sscanf(s, "%d", &major) + if err == nil { + return fmt.Sprintf("%d", major), nil + } + + return "", fmt.Errorf("unable to extract semantic version from value: %s", s) +} + +// CompareVersions compare two versions with the following formats: +// %d.%d.%d (e.g., 1.2.3) +// %d.%d (e.g., 1.2) +// %d (e.g., 1) +// Returns: +// -1 if v1 < v2 +// 0 if v1 == v2 +// 1 if v1 > v2 +func CompareVersions(v1, v2 string) VersionComparisonResult { + p1 := strings.Split(v1, ".") + p2 := strings.Split(v2, ".") + + maxLen := max(len(p1), len(p2)) + + for i := 0; i < maxLen; i++ { + var num1, num2 int + if i < len(p1) { + num1, _ = strconv.Atoi(p1[i]) + } + if i < len(p2) { + num2, _ = strconv.Atoi(p2[i]) + } + if num1 < num2 { + return CmpLt + } else if num1 > num2 { + return CmpGt + } + } + return CmpEq +} diff --git a/api/nfd/v1alpha1/utils_test.go b/api/nfd/v1alpha1/utils_test.go new file mode 100644 index 000000000..c83cdaa5a --- /dev/null +++ b/api/nfd/v1alpha1/utils_test.go @@ -0,0 +1,70 @@ +package v1alpha1 + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +type ValueAssertionFunc func(assert.TestingT, interface{}, ...interface{}) bool + +func TestExtractVersion(t *testing.T) { + tcs := []struct { + name string + input string + result string + err ValueAssertionFunc + }{ + {name: "1", input: "1", result: "1", err: assert.Nil}, + {name: "2", input: "1.2", result: "1.2", err: assert.Nil}, + {name: "3", input: "1.2.3", result: "1.2.3", err: assert.Nil}, + {name: "4", input: "1.2.3-flavor", result: "1.2.3", err: assert.Nil}, + {name: "5", input: "1.2.3-flavor.2.3.4", result: "1.2.3", err: assert.Nil}, + {name: "6", input: "flavor-1.2.3", result: "", err: assert.NotNil}, + {name: "7", input: "A.2.3", result: "", err: assert.NotNil}, + {name: "8", input: "str", result: "", err: assert.NotNil}, + } + + for _, tc := range tcs { + t.Run(tc.name, func(t *testing.T) { + result, err := ExtractVersion(tc.input) + assert.Equal(t, result, tc.result) + tc.err(t, err) + }) + } +} + +func TestCompareVersions(t *testing.T) { + tcs := []struct { + name string + v1 string + v2 string + result VersionComparisonResult + }{ + {name: "1", v1: "1", v2: "2", result: CmpLt}, + {name: "2", v1: "2", v2: "2", result: CmpEq}, + {name: "3", v1: "3", v2: "2", result: CmpGt}, + {name: "4", v1: "1.9", v2: "2.0", result: CmpLt}, + {name: "5", v1: "2.0", v2: "2.0", result: CmpEq}, + {name: "6", v1: "2.1", v2: "2.0", result: CmpGt}, + {name: "7", v1: "1.9.9", v2: "2.0.0", result: CmpLt}, + {name: "8", v1: "2.0.0", v2: "2.0.0", result: CmpEq}, + {name: "9", v1: "2.0.1", v2: "2.0.0", result: CmpGt}, + {name: "10", v1: "1", v2: "2.0", result: CmpLt}, + {name: "11", v1: "2", v2: "2.0", result: CmpEq}, + {name: "12", v1: "3", v2: "2.0", result: CmpGt}, + {name: "13", v1: "1", v2: "2.0.0", result: CmpLt}, + {name: "14", v1: "2", v2: "2.0.0", result: CmpEq}, + {name: "15", v1: "3", v2: "2.0.0", result: CmpGt}, + {name: "16", v1: "1.9.9", v2: "2", result: CmpLt}, + {name: "17", v1: "2.0.0", v2: "2", result: CmpEq}, + {name: "18", v1: "2.0.1", v2: "2", result: CmpGt}, + } + + for _, tc := range tcs { + t.Run(tc.name, func(t *testing.T) { + result := CompareVersions(tc.v1, tc.v2) + assert.Equal(t, result, tc.result) + }) + } +} diff --git a/deployment/base/nfd-crds/nfd-api-crds.yaml b/deployment/base/nfd-crds/nfd-api-crds.yaml index 223d2e661..69e306c3b 100644 --- a/deployment/base/nfd-crds/nfd-api-crds.yaml +++ b/deployment/base/nfd-crds/nfd-api-crds.yaml @@ -204,11 +204,19 @@ spec: - Exists - DoesNotExist - Gt + - Ge - Lt + - Le - GtLt + - GeLe - IsTrue - IsFalse type: string + type: + description: |- + Type defines the value type for specific operators. + The currently supported type is 'version' for Gt,Ge,Lt,Le,GtLt,GeLe operators. + type: string value: description: |- Value is the list of values that the operand evaluates the input @@ -240,11 +248,19 @@ spec: - Exists - DoesNotExist - Gt + - Ge - Lt + - Le - GtLt + - GeLe - IsTrue - IsFalse type: string + type: + description: |- + Type defines the value type for specific operators. + The currently supported type is 'version' for Gt,Ge,Lt,Le,GtLt,GeLe operators. + type: string value: description: |- Value is the list of values that the operand evaluates the input @@ -295,11 +311,19 @@ spec: - Exists - DoesNotExist - Gt + - Ge - Lt + - Le - GtLt + - GeLe - IsTrue - IsFalse type: string + type: + description: |- + Type defines the value type for specific operators. + The currently supported type is 'version' for Gt,Ge,Lt,Le,GtLt,GeLe operators. + type: string value: description: |- Value is the list of values that the operand evaluates the input @@ -331,11 +355,19 @@ spec: - Exists - DoesNotExist - Gt + - Ge - Lt + - Le - GtLt + - GeLe - IsTrue - IsFalse type: string + type: + description: |- + Type defines the value type for specific operators. + The currently supported type is 'version' for Gt,Ge,Lt,Le,GtLt,GeLe operators. + type: string value: description: |- Value is the list of values that the operand evaluates the input @@ -511,11 +543,19 @@ spec: - Exists - DoesNotExist - Gt + - Ge - Lt + - Le - GtLt + - GeLe - IsTrue - IsFalse type: string + type: + description: |- + Type defines the value type for specific operators. + The currently supported type is 'version' for Gt,Ge,Lt,Le,GtLt,GeLe operators. + type: string value: description: |- Value is the list of values that the operand evaluates the input @@ -547,11 +587,19 @@ spec: - Exists - DoesNotExist - Gt + - Ge - Lt + - Le - GtLt + - GeLe - IsTrue - IsFalse type: string + type: + description: |- + Type defines the value type for specific operators. + The currently supported type is 'version' for Gt,Ge,Lt,Le,GtLt,GeLe operators. + type: string value: description: |- Value is the list of values that the operand evaluates the input @@ -602,11 +650,19 @@ spec: - Exists - DoesNotExist - Gt + - Ge - Lt + - Le - GtLt + - GeLe - IsTrue - IsFalse type: string + type: + description: |- + Type defines the value type for specific operators. + The currently supported type is 'version' for Gt,Ge,Lt,Le,GtLt,GeLe operators. + type: string value: description: |- Value is the list of values that the operand evaluates the input @@ -638,11 +694,19 @@ spec: - Exists - DoesNotExist - Gt + - Ge - Lt + - Le - GtLt + - GeLe - IsTrue - IsFalse type: string + type: + description: |- + Type defines the value type for specific operators. + The currently supported type is 'version' for Gt,Ge,Lt,Le,GtLt,GeLe operators. + type: string value: description: |- Value is the list of values that the operand evaluates the input diff --git a/deployment/helm/node-feature-discovery/crds/nfd-api-crds.yaml b/deployment/helm/node-feature-discovery/crds/nfd-api-crds.yaml index 223d2e661..69e306c3b 100644 --- a/deployment/helm/node-feature-discovery/crds/nfd-api-crds.yaml +++ b/deployment/helm/node-feature-discovery/crds/nfd-api-crds.yaml @@ -204,11 +204,19 @@ spec: - Exists - DoesNotExist - Gt + - Ge - Lt + - Le - GtLt + - GeLe - IsTrue - IsFalse type: string + type: + description: |- + Type defines the value type for specific operators. + The currently supported type is 'version' for Gt,Ge,Lt,Le,GtLt,GeLe operators. + type: string value: description: |- Value is the list of values that the operand evaluates the input @@ -240,11 +248,19 @@ spec: - Exists - DoesNotExist - Gt + - Ge - Lt + - Le - GtLt + - GeLe - IsTrue - IsFalse type: string + type: + description: |- + Type defines the value type for specific operators. + The currently supported type is 'version' for Gt,Ge,Lt,Le,GtLt,GeLe operators. + type: string value: description: |- Value is the list of values that the operand evaluates the input @@ -295,11 +311,19 @@ spec: - Exists - DoesNotExist - Gt + - Ge - Lt + - Le - GtLt + - GeLe - IsTrue - IsFalse type: string + type: + description: |- + Type defines the value type for specific operators. + The currently supported type is 'version' for Gt,Ge,Lt,Le,GtLt,GeLe operators. + type: string value: description: |- Value is the list of values that the operand evaluates the input @@ -331,11 +355,19 @@ spec: - Exists - DoesNotExist - Gt + - Ge - Lt + - Le - GtLt + - GeLe - IsTrue - IsFalse type: string + type: + description: |- + Type defines the value type for specific operators. + The currently supported type is 'version' for Gt,Ge,Lt,Le,GtLt,GeLe operators. + type: string value: description: |- Value is the list of values that the operand evaluates the input @@ -511,11 +543,19 @@ spec: - Exists - DoesNotExist - Gt + - Ge - Lt + - Le - GtLt + - GeLe - IsTrue - IsFalse type: string + type: + description: |- + Type defines the value type for specific operators. + The currently supported type is 'version' for Gt,Ge,Lt,Le,GtLt,GeLe operators. + type: string value: description: |- Value is the list of values that the operand evaluates the input @@ -547,11 +587,19 @@ spec: - Exists - DoesNotExist - Gt + - Ge - Lt + - Le - GtLt + - GeLe - IsTrue - IsFalse type: string + type: + description: |- + Type defines the value type for specific operators. + The currently supported type is 'version' for Gt,Ge,Lt,Le,GtLt,GeLe operators. + type: string value: description: |- Value is the list of values that the operand evaluates the input @@ -602,11 +650,19 @@ spec: - Exists - DoesNotExist - Gt + - Ge - Lt + - Le - GtLt + - GeLe - IsTrue - IsFalse type: string + type: + description: |- + Type defines the value type for specific operators. + The currently supported type is 'version' for Gt,Ge,Lt,Le,GtLt,GeLe operators. + type: string value: description: |- Value is the list of values that the operand evaluates the input @@ -638,11 +694,19 @@ spec: - Exists - DoesNotExist - Gt + - Ge - Lt + - Le - GtLt + - GeLe - IsTrue - IsFalse type: string + type: + description: |- + Type defines the value type for specific operators. + The currently supported type is 'version' for Gt,Ge,Lt,Le,GtLt,GeLe operators. + type: string value: description: |- Value is the list of values that the operand evaluates the input diff --git a/docs/usage/customization-guide.md b/docs/usage/customization-guide.md index 23e49bd36..c131c3b39 100644 --- a/docs/usage/customization-guide.md +++ b/docs/usage/customization-guide.md @@ -786,6 +786,7 @@ feature. value: - - ... + type: ``` In each MatchExpression the `key` specifies the name of of the feature element @@ -820,6 +821,13 @@ below. The `value` field of MatchExpression is a list of string arguments to the operator. +Type optional `type` field specifies the type of the `value` field. +Valid types for specific operators are described below. + +| Type | Description | Supported Operators | +| --------- | ----------- | ------------------- | +| `version` | Input is recognized as a version in the following formats `%d.%d.%d`, `%d.%d`, `%d` (e.g., "1.2.3", "1.2", "1") |`Gt`,`Ge`,`Lt`,`Le`,`GtLt`,`GeLe` | + ##### matchName The `.matchFeatures[].matchName` field is used to match against the diff --git a/pkg/apis/nfd/nodefeaturerule/expression.go b/pkg/apis/nfd/nodefeaturerule/expression.go index 3bdbfa1bf..9bbc1dcc0 100644 --- a/pkg/apis/nfd/nodefeaturerule/expression.go +++ b/pkg/apis/nfd/nodefeaturerule/expression.go @@ -122,40 +122,94 @@ func evaluateMatchExpression(m *nfdv1alpha1.MatchExpression, valid bool, value i if len(m.Value) != 1 { return false, fmt.Errorf("invalid expression, 'value' field must contain exactly one element for Op %q (have %v)", m.Op, m.Value) } - - l, err := strconv.Atoi(value) - if err != nil { - return false, fmt.Errorf("not a number %q", value) - } - r, err := strconv.Atoi(m.Value[0]) - if err != nil { - return false, fmt.Errorf("not a number %q in %v", m.Value[0], m) + if m.Type != "" && m.Type != nfdv1alpha1.TypeVersion { + return false, fmt.Errorf("invalid expression, 'type' field only accepts %q value for Op %q (have %q)", nfdv1alpha1.TypeVersion, m.Op, m.Type) } - if (l < r && m.Op == nfdv1alpha1.MatchLt) || (l <= r && m.Op == nfdv1alpha1.MatchLe) || - (l > r && m.Op == nfdv1alpha1.MatchGt) || (l >= r && m.Op == nfdv1alpha1.MatchGe) { - return true, nil + switch m.Type { + case nfdv1alpha1.TypeVersion: + l, err := nfdv1alpha1.ExtractVersion(value) + if err != nil { + return false, fmt.Errorf("not a version %q", value) + } + + r, err := nfdv1alpha1.ExtractVersion(m.Value[0]) + if err != nil { + return false, fmt.Errorf("not a version %q in %v", m.Value[0], m) + } + + cmp := nfdv1alpha1.CompareVersions(l, r) + if (m.Op == nfdv1alpha1.MatchLt && cmp == nfdv1alpha1.CmpLt) || + (m.Op == nfdv1alpha1.MatchGt && cmp == nfdv1alpha1.CmpGt) || + (m.Op == nfdv1alpha1.MatchLe && (cmp == nfdv1alpha1.CmpLt || cmp == nfdv1alpha1.CmpEq)) || + (m.Op == nfdv1alpha1.MatchGe && (cmp == nfdv1alpha1.CmpGt || cmp == nfdv1alpha1.CmpEq)) { + return true, nil + } + return false, nil + default: + l, err := strconv.Atoi(value) + if err != nil { + return false, fmt.Errorf("not a number %q", value) + } + r, err := strconv.Atoi(m.Value[0]) + if err != nil { + return false, fmt.Errorf("not a number %q in %v", m.Value[0], m) + } + + if (l < r && m.Op == nfdv1alpha1.MatchLt) || (l <= r && m.Op == nfdv1alpha1.MatchLe) || + (l > r && m.Op == nfdv1alpha1.MatchGt) || (l >= r && m.Op == nfdv1alpha1.MatchGe) { + return true, nil + } } case nfdv1alpha1.MatchGtLt, nfdv1alpha1.MatchGeLe: if len(m.Value) != 2 { - return false, fmt.Errorf("invalid expression, value' field must contain exactly two elements for Op %q (have %v)", m.Op, m.Value) + return false, fmt.Errorf("invalid expression, 'value' field must contain exactly two elements for Op %q (have %v)", m.Op, m.Value) } - v, err := strconv.Atoi(value) - if err != nil { - return false, fmt.Errorf("not a number %q", value) - } - lr := make([]int, 2) - for i := range 2 { - lr[i], err = strconv.Atoi(m.Value[i]) + + switch m.Type { + case nfdv1alpha1.TypeVersion: + v, err := nfdv1alpha1.ExtractVersion(value) if err != nil { - return false, fmt.Errorf("not a number %q in %v", m.Value[i], m) + return false, fmt.Errorf("not a version %q", value) } + lr := make([]string, 2) + for i := range 2 { + lr[i], err = nfdv1alpha1.ExtractVersion(m.Value[i]) + if err != nil { + return false, fmt.Errorf("not a version %q in %v", m.Value[i], m) + } + } + + lRange := nfdv1alpha1.CompareVersions(v, lr[0]) + rRange := nfdv1alpha1.CompareVersions(v, lr[1]) + + if (m.Op == nfdv1alpha1.MatchGtLt && lRange == nfdv1alpha1.CmpGt && rRange == nfdv1alpha1.CmpLt) || + (m.Op == nfdv1alpha1.MatchGeLe && + (lRange == nfdv1alpha1.CmpGt || lRange == nfdv1alpha1.CmpEq) && + (rRange == nfdv1alpha1.CmpLt || rRange == nfdv1alpha1.CmpEq)) { + return true, nil + } + + return false, nil + + default: + v, err := strconv.Atoi(value) + if err != nil { + return false, fmt.Errorf("not a number %q", value) + } + lr := make([]int, 2) + for i := range 2 { + lr[i], err = strconv.Atoi(m.Value[i]) + if err != nil { + return false, fmt.Errorf("not a number %q in %v", m.Value[i], m) + } + } + if lr[0] >= lr[1] { + return false, fmt.Errorf("invalid expression, value[0] must be less than Value[1] for Op %q (have %v)", m.Op, m.Value) + } + return (v > lr[0] && v < lr[1] && m.Op == nfdv1alpha1.MatchGtLt) || + (v >= lr[0] && v <= lr[1] && m.Op == nfdv1alpha1.MatchGeLe), nil } - if lr[0] >= lr[1] { - return false, fmt.Errorf("invalid expression, value[0] must be less than Value[1] for Op %q (have %v)", m.Op, m.Value) - } - return (v > lr[0] && v < lr[1] && m.Op == nfdv1alpha1.MatchGtLt) || - (v >= lr[0] && v <= lr[1] && m.Op == nfdv1alpha1.MatchGeLe), nil case nfdv1alpha1.MatchIsTrue: if len(m.Value) != 0 { return false, fmt.Errorf("invalid expression, 'value' field must be empty for Op %q (have %v)", m.Op, m.Value) diff --git a/pkg/apis/nfd/nodefeaturerule/expression_test.go b/pkg/apis/nfd/nodefeaturerule/expression_test.go index 179861d70..c9073d918 100644 --- a/pkg/apis/nfd/nodefeaturerule/expression_test.go +++ b/pkg/apis/nfd/nodefeaturerule/expression_test.go @@ -197,13 +197,14 @@ func TestEvaluateMatchExpressionValues(t *testing.T) { type I = map[string]string type TC struct { - name string - op nfdv1alpha1.MatchOp - values V - key string - input I - result BoolAssertionFunc - err ValueAssertionFunc + name string + op nfdv1alpha1.MatchOp + values V + valueType nfdv1alpha1.ValueType + key string + input I + result BoolAssertionFunc + err ValueAssertionFunc } tcs := []TC{ @@ -231,45 +232,127 @@ func TestEvaluateMatchExpressionValues(t *testing.T) { {name: "16", op: nfdv1alpha1.MatchGt, values: V{"2"}, key: "foo", input: I{"bar": "3", "foo": "2"}, result: assert.False, err: assert.Nil}, {name: "17", op: nfdv1alpha1.MatchGt, values: V{"2"}, key: "foo", input: I{"bar": "3", "foo": "3"}, result: assert.True, err: assert.Nil}, {name: "18", op: nfdv1alpha1.MatchGt, values: V{"2"}, key: "foo", input: I{"bar": "str", "foo": "str"}, result: assert.False, err: assert.NotNil}, + {name: "19", op: nfdv1alpha1.MatchGt, values: V{"2.0"}, key: "foo", input: I{"bar": "str", "foo": "3"}, result: assert.False, err: assert.NotNil}, + {name: "20", op: nfdv1alpha1.MatchGt, values: V{"2"}, valueType: "version", key: "foo", input: I{"bar": "3"}, result: assert.False, err: assert.Nil}, + {name: "21", op: nfdv1alpha1.MatchGt, values: V{"2"}, valueType: "version", key: "foo", input: I{"bar": "3", "foo": "2"}, result: assert.False, err: assert.Nil}, + {name: "22", op: nfdv1alpha1.MatchGt, values: V{"2"}, valueType: "version", key: "foo", input: I{"bar": "3", "foo": "3"}, result: assert.True, err: assert.Nil}, + {name: "23", op: nfdv1alpha1.MatchGt, values: V{"2.0"}, valueType: "version", key: "foo", input: I{"bar": "3", "foo": "2.0"}, result: assert.False, err: assert.Nil}, + {name: "24", op: nfdv1alpha1.MatchGt, values: V{"2.0"}, valueType: "version", key: "foo", input: I{"bar": "3", "foo": "2.1"}, result: assert.True, err: assert.Nil}, + {name: "25", op: nfdv1alpha1.MatchGt, values: V{"2.0.1"}, valueType: "version", key: "foo", input: I{"bar": "3", "foo": "2.0.1"}, result: assert.False, err: assert.Nil}, + {name: "26", op: nfdv1alpha1.MatchGt, values: V{"2.0.1"}, valueType: "version", key: "foo", input: I{"bar": "3", "foo": "2.0.2"}, result: assert.True, err: assert.Nil}, + {name: "27", op: nfdv1alpha1.MatchGt, values: V{"2.0.1"}, valueType: "version", key: "foo", input: I{"bar": "str", "foo": "str"}, result: assert.False, err: assert.NotNil}, - {name: "19", op: nfdv1alpha1.MatchGe, values: V{"2"}, key: "foo", input: I{"bar": "3"}, result: assert.False, err: assert.Nil}, - {name: "20", op: nfdv1alpha1.MatchGe, values: V{"2"}, key: "foo", input: I{"bar": "3", "foo": "2"}, result: assert.True, err: assert.Nil}, - {name: "21", op: nfdv1alpha1.MatchGe, values: V{"2"}, key: "foo", input: I{"bar": "3", "foo": "3"}, result: assert.True, err: assert.Nil}, - {name: "22", op: nfdv1alpha1.MatchGe, values: V{"2"}, key: "foo", input: I{"bar": "str", "foo": "str"}, result: assert.False, err: assert.NotNil}, + {name: "28", op: nfdv1alpha1.MatchGe, values: V{"2"}, key: "foo", input: I{"bar": "3"}, result: assert.False, err: assert.Nil}, + {name: "29", op: nfdv1alpha1.MatchGe, values: V{"2"}, key: "foo", input: I{"bar": "3", "foo": "2"}, result: assert.True, err: assert.Nil}, + {name: "30", op: nfdv1alpha1.MatchGe, values: V{"2"}, key: "foo", input: I{"bar": "3", "foo": "3"}, result: assert.True, err: assert.Nil}, + {name: "31", op: nfdv1alpha1.MatchGe, values: V{"2"}, key: "foo", input: I{"bar": "str", "foo": "str"}, result: assert.False, err: assert.NotNil}, + {name: "32", op: nfdv1alpha1.MatchGe, values: V{"2.0"}, key: "foo", input: I{"bar": "3", "foo": "3"}, result: assert.False, err: assert.NotNil}, + {name: "33", op: nfdv1alpha1.MatchGe, values: V{"2"}, valueType: "version", key: "foo", input: I{"bar": "3"}, result: assert.False, err: assert.Nil}, + {name: "34", op: nfdv1alpha1.MatchGe, values: V{"2"}, valueType: "version", key: "foo", input: I{"bar": "3", "foo": "2"}, result: assert.True, err: assert.Nil}, + {name: "35", op: nfdv1alpha1.MatchGe, values: V{"2"}, valueType: "version", key: "foo", input: I{"bar": "3", "foo": "3"}, result: assert.True, err: assert.Nil}, + {name: "36", op: nfdv1alpha1.MatchGe, values: V{"2"}, valueType: "version", key: "foo", input: I{"bar": "3", "foo": "1"}, result: assert.False, err: assert.Nil}, + {name: "37", op: nfdv1alpha1.MatchGe, values: V{"2.0"}, valueType: "version", key: "foo", input: I{"bar": "3"}, result: assert.False, err: assert.Nil}, + {name: "38", op: nfdv1alpha1.MatchGe, values: V{"2.0"}, valueType: "version", key: "foo", input: I{"bar": "3", "foo": "2.0"}, result: assert.True, err: assert.Nil}, + {name: "39", op: nfdv1alpha1.MatchGe, values: V{"2.0"}, valueType: "version", key: "foo", input: I{"bar": "3", "foo": "2.1"}, result: assert.True, err: assert.Nil}, + {name: "40", op: nfdv1alpha1.MatchGe, values: V{"2.0"}, valueType: "version", key: "foo", input: I{"bar": "3", "foo": "1.9"}, result: assert.False, err: assert.Nil}, + {name: "41", op: nfdv1alpha1.MatchGe, values: V{"2.0.1"}, valueType: "version", key: "foo", input: I{"bar": "3"}, result: assert.False, err: assert.Nil}, + {name: "42", op: nfdv1alpha1.MatchGe, values: V{"2.0.1"}, valueType: "version", key: "foo", input: I{"bar": "3", "foo": "2.0.1"}, result: assert.True, err: assert.Nil}, + {name: "43", op: nfdv1alpha1.MatchGe, values: V{"2.0.1"}, valueType: "version", key: "foo", input: I{"bar": "3", "foo": "2.0.2"}, result: assert.True, err: assert.Nil}, + {name: "44", op: nfdv1alpha1.MatchGe, values: V{"2.0.1"}, valueType: "version", key: "foo", input: I{"bar": "3", "foo": "2.0.0"}, result: assert.False, err: assert.Nil}, + {name: "45", op: nfdv1alpha1.MatchGe, values: V{"2.0.1"}, valueType: "version", key: "foo", input: I{"bar": "str", "foo": "str"}, result: assert.False, err: assert.NotNil}, - {name: "23", op: nfdv1alpha1.MatchLt, values: V{"2"}, key: "foo", input: I{"bar": "1"}, result: assert.False, err: assert.Nil}, - {name: "24", op: nfdv1alpha1.MatchLt, values: V{"2"}, key: "foo", input: I{"bar": "1", "foo": "2"}, result: assert.False, err: assert.Nil}, - {name: "25", op: nfdv1alpha1.MatchLt, values: V{"2"}, key: "foo", input: I{"bar": "1", "foo": "1"}, result: assert.True, err: assert.Nil}, - {name: "26", op: nfdv1alpha1.MatchLt, values: V{"2"}, key: "foo", input: I{"bar": "str", "foo": "str"}, result: assert.False, err: assert.NotNil}, + {name: "46", op: nfdv1alpha1.MatchLt, values: V{"2"}, key: "foo", input: I{"bar": "1"}, result: assert.False, err: assert.Nil}, + {name: "47", op: nfdv1alpha1.MatchLt, values: V{"2"}, key: "foo", input: I{"bar": "1", "foo": "2"}, result: assert.False, err: assert.Nil}, + {name: "48", op: nfdv1alpha1.MatchLt, values: V{"2"}, key: "foo", input: I{"bar": "1", "foo": "1"}, result: assert.True, err: assert.Nil}, + {name: "49", op: nfdv1alpha1.MatchLt, values: V{"2"}, key: "foo", input: I{"bar": "str", "foo": "str"}, result: assert.False, err: assert.NotNil}, + {name: "50", op: nfdv1alpha1.MatchLt, values: V{"2.0"}, key: "foo", input: I{"bar": "str", "foo": "1"}, result: assert.False, err: assert.NotNil}, + {name: "51", op: nfdv1alpha1.MatchLt, values: V{"2"}, valueType: "version", key: "foo", input: I{"bar": "1"}, result: assert.False, err: assert.Nil}, + {name: "52", op: nfdv1alpha1.MatchLt, values: V{"2"}, valueType: "version", key: "foo", input: I{"bar": "1", "foo": "2"}, result: assert.False, err: assert.Nil}, + {name: "53", op: nfdv1alpha1.MatchLt, values: V{"2"}, valueType: "version", key: "foo", input: I{"bar": "1", "foo": "1"}, result: assert.True, err: assert.Nil}, + {name: "54", op: nfdv1alpha1.MatchLt, values: V{"2.0"}, valueType: "version", key: "foo", input: I{"bar": "1"}, result: assert.False, err: assert.Nil}, + {name: "55", op: nfdv1alpha1.MatchLt, values: V{"2.0"}, valueType: "version", key: "foo", input: I{"bar": "1", "foo": "2.0"}, result: assert.False, err: assert.Nil}, + {name: "56", op: nfdv1alpha1.MatchLt, values: V{"2.0"}, valueType: "version", key: "foo", input: I{"bar": "1", "foo": "1.9"}, result: assert.True, err: assert.Nil}, + {name: "57", op: nfdv1alpha1.MatchLt, values: V{"2.0.1"}, valueType: "version", key: "foo", input: I{"bar": "1"}, result: assert.False, err: assert.Nil}, + {name: "58", op: nfdv1alpha1.MatchLt, values: V{"2.0.1"}, valueType: "version", key: "foo", input: I{"bar": "1", "foo": "2.0.1"}, result: assert.False, err: assert.Nil}, + {name: "59", op: nfdv1alpha1.MatchLt, values: V{"2.0.1"}, valueType: "version", key: "foo", input: I{"bar": "1", "foo": "2.0.0"}, result: assert.True, err: assert.Nil}, + {name: "49", op: nfdv1alpha1.MatchLt, values: V{"2.0.1"}, valueType: "version", key: "foo", input: I{"bar": "str", "foo": "str"}, result: assert.False, err: assert.NotNil}, - {name: "27", op: nfdv1alpha1.MatchLe, values: V{"2"}, key: "foo", input: I{"bar": "1"}, result: assert.False, err: assert.Nil}, - {name: "28", op: nfdv1alpha1.MatchLe, values: V{"2"}, key: "foo", input: I{"bar": "1", "foo": "2"}, result: assert.True, err: assert.Nil}, - {name: "29", op: nfdv1alpha1.MatchLe, values: V{"2"}, key: "foo", input: I{"bar": "1", "foo": "1"}, result: assert.True, err: assert.Nil}, - {name: "30", op: nfdv1alpha1.MatchLe, values: V{"2"}, key: "foo", input: I{"bar": "str", "foo": "str"}, result: assert.False, err: assert.NotNil}, + {name: "60", op: nfdv1alpha1.MatchLe, values: V{"2"}, key: "foo", input: I{"bar": "1"}, result: assert.False, err: assert.Nil}, + {name: "61", op: nfdv1alpha1.MatchLe, values: V{"2"}, key: "foo", input: I{"bar": "1", "foo": "2"}, result: assert.True, err: assert.Nil}, + {name: "62", op: nfdv1alpha1.MatchLe, values: V{"2"}, key: "foo", input: I{"bar": "1", "foo": "1"}, result: assert.True, err: assert.Nil}, + {name: "63", op: nfdv1alpha1.MatchLe, values: V{"2"}, key: "foo", input: I{"bar": "str", "foo": "str"}, result: assert.False, err: assert.NotNil}, + {name: "64", op: nfdv1alpha1.MatchLe, values: V{"2"}, key: "foo", input: I{"bar": "1", "foo": "1.0"}, result: assert.False, err: assert.NotNil}, + {name: "65", op: nfdv1alpha1.MatchLe, values: V{"2"}, valueType: "version", key: "foo", input: I{"bar": "1"}, result: assert.False, err: assert.Nil}, + {name: "66", op: nfdv1alpha1.MatchLe, values: V{"2"}, valueType: "version", key: "foo", input: I{"bar": "1", "foo": "2"}, result: assert.True, err: assert.Nil}, + {name: "67", op: nfdv1alpha1.MatchLe, values: V{"2"}, valueType: "version", key: "foo", input: I{"bar": "1", "foo": "1"}, result: assert.True, err: assert.Nil}, + {name: "68", op: nfdv1alpha1.MatchLe, values: V{"2"}, valueType: "version", key: "foo", input: I{"bar": "1", "foo": "3"}, result: assert.False, err: assert.Nil}, + {name: "69", op: nfdv1alpha1.MatchLe, values: V{"2.0"}, valueType: "version", key: "foo", input: I{"bar": "1.0"}, result: assert.False, err: assert.Nil}, + {name: "70", op: nfdv1alpha1.MatchLe, values: V{"2.0"}, valueType: "version", key: "foo", input: I{"bar": "1", "foo": "2.0"}, result: assert.True, err: assert.Nil}, + {name: "71", op: nfdv1alpha1.MatchLe, values: V{"2.0"}, valueType: "version", key: "foo", input: I{"bar": "1", "foo": "1.0"}, result: assert.True, err: assert.Nil}, + {name: "72", op: nfdv1alpha1.MatchLe, values: V{"2.0"}, valueType: "version", key: "foo", input: I{"bar": "1", "foo": "2.1"}, result: assert.False, err: assert.Nil}, + {name: "73", op: nfdv1alpha1.MatchLe, values: V{"2.0.1"}, valueType: "version", key: "foo", input: I{"bar": "1.0"}, result: assert.False, err: assert.Nil}, + {name: "74", op: nfdv1alpha1.MatchLe, values: V{"2.0.1"}, valueType: "version", key: "foo", input: I{"bar": "1", "foo": "2.0.1"}, result: assert.True, err: assert.Nil}, + {name: "75", op: nfdv1alpha1.MatchLe, values: V{"2.0.1"}, valueType: "version", key: "foo", input: I{"bar": "1", "foo": "2.0.0"}, result: assert.True, err: assert.Nil}, + {name: "76", op: nfdv1alpha1.MatchLe, values: V{"2.0.1"}, valueType: "version", key: "foo", input: I{"bar": "1", "foo": "2.0.2"}, result: assert.False, err: assert.Nil}, + {name: "77", op: nfdv1alpha1.MatchLe, values: V{"2.0.1"}, valueType: "version", key: "foo", input: I{"bar": "str", "foo": "str"}, result: assert.False, err: assert.NotNil}, - {name: "31", op: nfdv1alpha1.MatchGtLt, values: V{"-10", "10"}, key: "foo", input: I{"bar": "1"}, result: assert.False, err: assert.Nil}, - {name: "32", op: nfdv1alpha1.MatchGtLt, values: V{"-10", "10"}, key: "foo", input: I{"bar": "1", "foo": "11"}, result: assert.False, err: assert.Nil}, - {name: "33", op: nfdv1alpha1.MatchGtLt, values: V{"-10", "10"}, key: "foo", input: I{"bar": "1", "foo": "-11"}, result: assert.False, err: assert.Nil}, - {name: "34", op: nfdv1alpha1.MatchGtLt, values: V{"-10", "10"}, key: "foo", input: I{"bar": "1", "foo": "1"}, result: assert.True, err: assert.Nil}, - {name: "35", op: nfdv1alpha1.MatchGtLt, values: V{"-10", "10"}, key: "foo", input: I{"bar": "str", "foo": "str"}, result: assert.False, err: assert.NotNil}, + {name: "78", op: nfdv1alpha1.MatchGtLt, values: V{"-10", "10"}, key: "foo", input: I{"bar": "1"}, result: assert.False, err: assert.Nil}, + {name: "79", op: nfdv1alpha1.MatchGtLt, values: V{"-10", "10"}, key: "foo", input: I{"bar": "1", "foo": "11"}, result: assert.False, err: assert.Nil}, + {name: "80", op: nfdv1alpha1.MatchGtLt, values: V{"-10", "10"}, key: "foo", input: I{"bar": "1", "foo": "-11"}, result: assert.False, err: assert.Nil}, + {name: "81", op: nfdv1alpha1.MatchGtLt, values: V{"-10", "10"}, key: "foo", input: I{"bar": "1", "foo": "1"}, result: assert.True, err: assert.Nil}, + {name: "82", op: nfdv1alpha1.MatchGtLt, values: V{"-10", "10"}, key: "foo", input: I{"bar": "str", "foo": "str"}, result: assert.False, err: assert.NotNil}, + {name: "83", op: nfdv1alpha1.MatchGtLt, values: V{"-10", "10"}, key: "foo", input: I{"bar": "str", "foo": "5.0"}, result: assert.False, err: assert.NotNil}, + {name: "84", op: nfdv1alpha1.MatchGtLt, values: V{"1", "10"}, valueType: "version", key: "foo", input: I{"bar": "1"}, result: assert.False, err: assert.Nil}, + {name: "85", op: nfdv1alpha1.MatchGtLt, values: V{"1", "10"}, valueType: "version", key: "foo", input: I{"bar": "1", "foo": "11"}, result: assert.False, err: assert.Nil}, + {name: "86", op: nfdv1alpha1.MatchGtLt, values: V{"1", "10"}, valueType: "version", key: "foo", input: I{"bar": "1", "foo": "1"}, result: assert.False, err: assert.Nil}, + {name: "87", op: nfdv1alpha1.MatchGtLt, values: V{"1", "10"}, valueType: "version", key: "foo", input: I{"bar": "1", "foo": "2"}, result: assert.True, err: assert.Nil}, + {name: "88", op: nfdv1alpha1.MatchGtLt, values: V{"1", "10"}, valueType: "version", key: "foo", input: I{"bar": "1", "foo": "0"}, result: assert.False, err: assert.Nil}, + {name: "89", op: nfdv1alpha1.MatchGtLt, values: V{"1.0", "10.0"}, valueType: "version", key: "foo", input: I{"bar": "1.1"}, result: assert.False, err: assert.Nil}, + {name: "90", op: nfdv1alpha1.MatchGtLt, values: V{"1.0", "10.0"}, valueType: "version", key: "foo", input: I{"bar": "1", "foo": "10.1"}, result: assert.False, err: assert.Nil}, + {name: "91", op: nfdv1alpha1.MatchGtLt, values: V{"1.0", "10.0"}, valueType: "version", key: "foo", input: I{"bar": "1", "foo": "1.0"}, result: assert.False, err: assert.Nil}, + {name: "92", op: nfdv1alpha1.MatchGtLt, values: V{"1.0", "10.0"}, valueType: "version", key: "foo", input: I{"bar": "1", "foo": "1.1"}, result: assert.True, err: assert.Nil}, + {name: "93", op: nfdv1alpha1.MatchGtLt, values: V{"1.0", "10.0"}, valueType: "version", key: "foo", input: I{"bar": "1", "foo": "0.9"}, result: assert.False, err: assert.Nil}, + {name: "94", op: nfdv1alpha1.MatchGtLt, values: V{"1.0.1", "10.0.1"}, valueType: "version", key: "foo", input: I{"bar": "1.1"}, result: assert.False, err: assert.Nil}, + {name: "95", op: nfdv1alpha1.MatchGtLt, values: V{"1.0.1", "10.0.1"}, valueType: "version", key: "foo", input: I{"bar": "1", "foo": "10.0.1"}, result: assert.False, err: assert.Nil}, + {name: "96", op: nfdv1alpha1.MatchGtLt, values: V{"1.0.1", "10.0.1"}, valueType: "version", key: "foo", input: I{"bar": "1", "foo": "1.0.1"}, result: assert.False, err: assert.Nil}, + {name: "97", op: nfdv1alpha1.MatchGtLt, values: V{"1.0.1", "10.0.1"}, valueType: "version", key: "foo", input: I{"bar": "1", "foo": "1.0.2"}, result: assert.True, err: assert.Nil}, + {name: "98", op: nfdv1alpha1.MatchGtLt, values: V{"1.0.1", "10.0.1"}, valueType: "version", key: "foo", input: I{"bar": "1", "foo": "0.0.9"}, result: assert.False, err: assert.Nil}, + {name: "99", op: nfdv1alpha1.MatchGtLt, values: V{"1.0.1", "10.0.1"}, key: "foo", input: I{"bar": "str", "foo": "str"}, result: assert.False, err: assert.NotNil}, - {name: "36", op: nfdv1alpha1.MatchGeLe, values: V{"-10", "10"}, key: "foo", input: I{"bar": "1"}, result: assert.False, err: assert.Nil}, - {name: "37", op: nfdv1alpha1.MatchGeLe, values: V{"-10", "10"}, key: "foo", input: I{"bar": "-10", "foo": "10"}, result: assert.True, err: assert.Nil}, - {name: "38", op: nfdv1alpha1.MatchGeLe, values: V{"-10", "10"}, key: "foo", input: I{"bar": "1", "foo": "-11"}, result: assert.False, err: assert.Nil}, - {name: "39", op: nfdv1alpha1.MatchGeLe, values: V{"-10", "10"}, key: "foo", input: I{"bar": "1", "foo": "1"}, result: assert.True, err: assert.Nil}, - {name: "40", op: nfdv1alpha1.MatchGeLe, values: V{"-10", "10"}, key: "foo", input: I{"bar": "str", "foo": "str"}, result: assert.False, err: assert.NotNil}, + {name: "100", op: nfdv1alpha1.MatchGeLe, values: V{"-10", "10"}, key: "foo", input: I{"bar": "1"}, result: assert.False, err: assert.Nil}, + {name: "101", op: nfdv1alpha1.MatchGeLe, values: V{"-10", "10"}, key: "foo", input: I{"bar": "-10", "foo": "10"}, result: assert.True, err: assert.Nil}, + {name: "102", op: nfdv1alpha1.MatchGeLe, values: V{"-10", "10"}, key: "foo", input: I{"bar": "1", "foo": "-11"}, result: assert.False, err: assert.Nil}, + {name: "103", op: nfdv1alpha1.MatchGeLe, values: V{"-10", "10"}, key: "foo", input: I{"bar": "1", "foo": "1"}, result: assert.True, err: assert.Nil}, + {name: "104", op: nfdv1alpha1.MatchGeLe, values: V{"-10", "10"}, key: "foo", input: I{"bar": "str", "foo": "str"}, result: assert.False, err: assert.NotNil}, + {name: "105", op: nfdv1alpha1.MatchGeLe, values: V{"-10", "10"}, key: "foo", input: I{"bar": "1", "foo": "1.0"}, result: assert.False, err: assert.NotNil}, + {name: "106", op: nfdv1alpha1.MatchGeLe, values: V{"1", "10"}, valueType: "version", key: "foo", input: I{"bar": "1"}, result: assert.False, err: assert.Nil}, + {name: "107", op: nfdv1alpha1.MatchGeLe, values: V{"1", "10"}, valueType: "version", key: "foo", input: I{"bar": "-10", "foo": "10"}, result: assert.True, err: assert.Nil}, + {name: "108", op: nfdv1alpha1.MatchGeLe, values: V{"1", "10"}, valueType: "version", key: "foo", input: I{"bar": "1", "foo": "-11"}, result: assert.False, err: assert.Nil}, + {name: "109", op: nfdv1alpha1.MatchGeLe, values: V{"1", "10"}, valueType: "version", key: "foo", input: I{"bar": "1", "foo": "1"}, result: assert.True, err: assert.Nil}, + {name: "110", op: nfdv1alpha1.MatchGeLe, values: V{"1", "10"}, valueType: "version", key: "foo", input: I{"bar": "1", "foo": "0"}, result: assert.False, err: assert.Nil}, + {name: "111", op: nfdv1alpha1.MatchGeLe, values: V{"1.0", "10.0"}, valueType: "version", key: "foo", input: I{"bar": "1"}, result: assert.False, err: assert.Nil}, + {name: "112", op: nfdv1alpha1.MatchGeLe, values: V{"1.0", "10.0"}, valueType: "version", key: "foo", input: I{"bar": "-10", "foo": "10.0"}, result: assert.True, err: assert.Nil}, + {name: "113", op: nfdv1alpha1.MatchGeLe, values: V{"1.0", "10.0"}, valueType: "version", key: "foo", input: I{"bar": "1", "foo": "10.1"}, result: assert.False, err: assert.Nil}, + {name: "114", op: nfdv1alpha1.MatchGeLe, values: V{"1.0", "10.0"}, valueType: "version", key: "foo", input: I{"bar": "1", "foo": "1.1"}, result: assert.True, err: assert.Nil}, + {name: "115", op: nfdv1alpha1.MatchGeLe, values: V{"1.0", "10.0"}, valueType: "version", key: "foo", input: I{"bar": "1", "foo": "0.9"}, result: assert.False, err: assert.Nil}, + {name: "116", op: nfdv1alpha1.MatchGeLe, values: V{"1.0.1", "10.0.1"}, valueType: "version", key: "foo", input: I{"bar": "1"}, result: assert.False, err: assert.Nil}, + {name: "117", op: nfdv1alpha1.MatchGeLe, values: V{"1.0.1", "10.0.1"}, valueType: "version", key: "foo", input: I{"bar": "-10", "foo": "10.0.1"}, result: assert.True, err: assert.Nil}, + {name: "118", op: nfdv1alpha1.MatchGeLe, values: V{"1.0.1", "10.0.1"}, valueType: "version", key: "foo", input: I{"bar": "1", "foo": "10.0.2"}, result: assert.False, err: assert.Nil}, + {name: "119", op: nfdv1alpha1.MatchGeLe, values: V{"1.0.1", "10.0.1"}, valueType: "version", key: "foo", input: I{"bar": "1", "foo": "1.0.2"}, result: assert.True, err: assert.Nil}, + {name: "120", op: nfdv1alpha1.MatchGeLe, values: V{"1.0.1", "10.0.1"}, valueType: "version", key: "foo", input: I{"bar": "1", "foo": "0.0.9"}, result: assert.False, err: assert.Nil}, + {name: "121", op: nfdv1alpha1.MatchGeLe, values: V{"1.0.1", "10.0.1"}, valueType: "version", key: "foo", input: I{"bar": "str", "foo": "str"}, result: assert.False, err: assert.NotNil}, - {name: "41", op: nfdv1alpha1.MatchIsTrue, key: "foo", result: assert.False, err: assert.Nil}, - {name: "42", op: nfdv1alpha1.MatchIsTrue, key: "foo", input: I{"foo": "1"}, result: assert.False, err: assert.Nil}, - {name: "43", op: nfdv1alpha1.MatchIsTrue, key: "foo", input: I{"foo": "true"}, result: assert.True, err: assert.Nil}, + {name: "122", op: nfdv1alpha1.MatchIsTrue, key: "foo", result: assert.False, err: assert.Nil}, + {name: "123", op: nfdv1alpha1.MatchIsTrue, key: "foo", input: I{"foo": "1"}, result: assert.False, err: assert.Nil}, + {name: "124", op: nfdv1alpha1.MatchIsTrue, key: "foo", input: I{"foo": "true"}, result: assert.True, err: assert.Nil}, - {name: "44", op: nfdv1alpha1.MatchIsFalse, key: "foo", input: I{"foo": "true"}, result: assert.False, err: assert.Nil}, - {name: "45", op: nfdv1alpha1.MatchIsFalse, key: "foo", input: I{"foo": "false"}, result: assert.True, err: assert.Nil}, + {name: "125", op: nfdv1alpha1.MatchIsFalse, key: "foo", input: I{"foo": "true"}, result: assert.False, err: assert.Nil}, + {name: "126", op: nfdv1alpha1.MatchIsFalse, key: "foo", input: I{"foo": "false"}, result: assert.True, err: assert.Nil}, } for _, tc := range tcs { t.Run(tc.name, func(t *testing.T) { - me := &nfdv1alpha1.MatchExpression{Op: tc.op, Value: tc.values} + me := &nfdv1alpha1.MatchExpression{Op: tc.op, Value: tc.values, Type: tc.valueType} res, err := evaluateMatchExpressionValues(me, tc.key, tc.input) tc.result(t, res) tc.err(t, err)