kubernetes validation_test 源码
kubernetes validation_test 代码
文件路径:/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/schema/listtype/validation_test.go
/*
Copyright 2019 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package listtype
import (
"testing"
"k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/apiextensions-apiserver/pkg/apiserver/schema"
)
func TestValidateListSetsAndMaps(t *testing.T) {
tests := []struct {
name string
schema *schema.Structural
obj map[string]interface{}
errors []validationMatch
}{
{name: "nil"},
{name: "no schema", obj: make(map[string]interface{})},
{name: "no object", schema: &schema.Structural{}},
{name: "list without schema",
obj: map[string]interface{}{
"array": []interface{}{"a", "b", "a"},
},
},
{name: "list without items",
obj: map[string]interface{}{
"array": []interface{}{"a", "b", "a"},
},
schema: &schema.Structural{
Generic: schema.Generic{
Type: "object",
},
Properties: map[string]schema.Structural{
"array": {
Generic: schema.Generic{
Type: "array",
},
},
},
},
},
{name: "set list with one item",
obj: map[string]interface{}{
"array": []interface{}{"a"},
},
schema: &schema.Structural{
Generic: schema.Generic{
Type: "object",
},
Properties: map[string]schema.Structural{
"array": {
Extensions: schema.Extensions{
XListType: strPtr("set"),
},
Generic: schema.Generic{
Type: "array",
},
},
},
},
},
{name: "set list with two equal items",
obj: map[string]interface{}{
"array": []interface{}{"a", "a"},
},
schema: &schema.Structural{
Generic: schema.Generic{
Type: "object",
},
Properties: map[string]schema.Structural{
"array": {
Extensions: schema.Extensions{
XListType: strPtr("set"),
},
Generic: schema.Generic{
Type: "array",
},
},
},
},
errors: []validationMatch{
duplicate("root", "array[1]"),
},
},
{name: "set list with two different items",
obj: map[string]interface{}{
"array": []interface{}{"a", "b"},
},
schema: &schema.Structural{
Generic: schema.Generic{
Type: "object",
},
Properties: map[string]schema.Structural{
"array": {
Extensions: schema.Extensions{
XListType: strPtr("set"),
},
Generic: schema.Generic{
Type: "array",
},
},
},
},
},
{name: "set list with multiple duplicated items",
obj: map[string]interface{}{
"array": []interface{}{"a", "a", "b", "c", "d", "c"},
},
schema: &schema.Structural{
Generic: schema.Generic{
Type: "object",
},
Properties: map[string]schema.Structural{
"array": {
Extensions: schema.Extensions{
XListType: strPtr("set"),
},
Generic: schema.Generic{
Type: "array",
},
},
},
},
errors: []validationMatch{
duplicate("root", "array[1]"),
duplicate("root", "array[5]"),
},
},
{name: "normal list with items",
obj: map[string]interface{}{
"array": []interface{}{"a", "b", "a"},
},
schema: &schema.Structural{
Generic: schema.Generic{
Type: "object",
},
Properties: map[string]schema.Structural{
"array": {
Generic: schema.Generic{
Type: "array",
},
Items: &schema.Structural{
Generic: schema.Generic{
Type: "string",
},
},
},
},
},
},
{name: "set list with items",
obj: map[string]interface{}{
"array": []interface{}{"a", "b", "a"},
},
schema: &schema.Structural{
Generic: schema.Generic{
Type: "object",
},
Properties: map[string]schema.Structural{
"array": {
Generic: schema.Generic{
Type: "array",
},
Extensions: schema.Extensions{
XListType: strPtr("set"),
},
Items: &schema.Structural{
Generic: schema.Generic{
Type: "string",
},
},
},
},
},
errors: []validationMatch{
duplicate("root", "array[2]"),
},
},
{name: "set list with items under additionalProperties",
obj: map[string]interface{}{
"array": []interface{}{"a", "b", "a"},
},
schema: &schema.Structural{
Generic: schema.Generic{
Type: "object",
AdditionalProperties: &schema.StructuralOrBool{
Structural: &schema.Structural{
Generic: schema.Generic{
Type: "array",
},
Extensions: schema.Extensions{
XListType: strPtr("set"),
},
Items: &schema.Structural{
Generic: schema.Generic{
Type: "string",
},
},
},
},
},
},
errors: []validationMatch{
duplicate("root[array][2]"),
},
},
{name: "set list with items under items",
obj: map[string]interface{}{
"array": []interface{}{
[]interface{}{"a", "b", "a"},
[]interface{}{"b", "b", "a"},
},
},
schema: &schema.Structural{
Generic: schema.Generic{
Type: "object",
},
Properties: map[string]schema.Structural{
"array": {
Generic: schema.Generic{
Type: "array",
},
Items: &schema.Structural{
Generic: schema.Generic{
Type: "array",
},
Extensions: schema.Extensions{
XListType: strPtr("set"),
},
Items: &schema.Structural{
Generic: schema.Generic{
Type: "string",
},
},
},
},
},
},
errors: []validationMatch{
duplicate("root", "array[0][2]"),
duplicate("root", "array[1][1]"),
},
},
{name: "nested set lists",
obj: map[string]interface{}{
"array": []interface{}{
"a", "b", "a", []interface{}{"b", "b", "a"},
},
},
schema: &schema.Structural{
Generic: schema.Generic{
Type: "object",
},
Properties: map[string]schema.Structural{
"array": {
Generic: schema.Generic{
Type: "array",
},
Extensions: schema.Extensions{
XListType: strPtr("set"),
},
Items: &schema.Structural{
Generic: schema.Generic{
Type: "array",
},
Extensions: schema.Extensions{
XListType: strPtr("set"),
},
},
},
},
},
errors: []validationMatch{
duplicate("root", "array[2]"),
duplicate("root", "array[3][1]"),
},
},
{name: "set list with compound map items",
obj: map[string]interface{}{
"strings": []interface{}{"a", "b", "a"},
"integers": []interface{}{int64(1), int64(2), int64(1)},
"booleans": []interface{}{false, true, true},
"float64": []interface{}{float64(1.0), float64(2.0), float64(2.0)},
"nil": []interface{}{"a", nil, nil},
"empty maps": []interface{}{map[string]interface{}{"a": "b"}, map[string]interface{}{}, map[string]interface{}{}},
"map values": []interface{}{map[string]interface{}{"a": "b"}, map[string]interface{}{"a": "c"}, map[string]interface{}{"a": "b"}},
"nil values": []interface{}{map[string]interface{}{"a": nil}, map[string]interface{}{"b": "c", "a": nil}},
"array": []interface{}{[]interface{}{}, []interface{}{"a"}, []interface{}{"b"}, []interface{}{"a"}},
"nil array": []interface{}{[]interface{}{}, []interface{}{nil}, []interface{}{nil, nil}, []interface{}{nil}, []interface{}{"a"}},
"multiple duplicates": []interface{}{map[string]interface{}{"a": "b"}, map[string]interface{}{"a": "c"}, map[string]interface{}{"a": "b"}, map[string]interface{}{"a": "c"}, map[string]interface{}{"a": "c"}},
},
schema: &schema.Structural{
Generic: schema.Generic{
Type: "object",
},
Properties: map[string]schema.Structural{
"strings": {
Generic: schema.Generic{
Type: "array",
},
Items: &schema.Structural{
Generic: schema.Generic{
Type: "string",
},
},
Extensions: schema.Extensions{
XListType: strPtr("set"),
},
},
"integers": {
Generic: schema.Generic{
Type: "array",
},
Items: &schema.Structural{
Generic: schema.Generic{
Type: "integer",
},
},
Extensions: schema.Extensions{
XListType: strPtr("set"),
},
},
"booleans": {
Generic: schema.Generic{
Type: "array",
},
Items: &schema.Structural{
Generic: schema.Generic{
Type: "boolean",
},
},
Extensions: schema.Extensions{
XListType: strPtr("set"),
},
},
"float64": {
Generic: schema.Generic{
Type: "array",
},
Items: &schema.Structural{
Generic: schema.Generic{
Type: "number",
},
},
Extensions: schema.Extensions{
XListType: strPtr("set"),
},
},
"nil": {
Generic: schema.Generic{
Type: "array",
}, Items: &schema.Structural{
Generic: schema.Generic{
Type: "string",
Nullable: true,
},
},
Extensions: schema.Extensions{
XListType: strPtr("set"),
},
},
"empty maps": {
Generic: schema.Generic{
Type: "array",
},
Items: &schema.Structural{
Generic: schema.Generic{
Type: "object",
AdditionalProperties: &schema.StructuralOrBool{
Structural: &schema.Structural{
Generic: schema.Generic{
Type: "string",
},
},
},
},
},
Extensions: schema.Extensions{
XListType: strPtr("set"),
},
},
"map values": {
Generic: schema.Generic{
Type: "array",
},
Items: &schema.Structural{
Generic: schema.Generic{
Type: "object",
AdditionalProperties: &schema.StructuralOrBool{
Structural: &schema.Structural{
Generic: schema.Generic{
Type: "string",
},
},
},
},
},
Extensions: schema.Extensions{
XListType: strPtr("set"),
},
},
"nil values": {
Generic: schema.Generic{
Type: "array",
},
Items: &schema.Structural{
Generic: schema.Generic{
Type: "object",
AdditionalProperties: &schema.StructuralOrBool{
Structural: &schema.Structural{
Generic: schema.Generic{
Type: "string",
Nullable: true,
},
},
},
},
},
Extensions: schema.Extensions{
XListType: strPtr("set"),
},
},
"array": {
Generic: schema.Generic{
Type: "array",
},
Items: &schema.Structural{
Generic: schema.Generic{
Type: "array",
},
Items: &schema.Structural{
Generic: schema.Generic{
Type: "string",
},
},
},
Extensions: schema.Extensions{
XListType: strPtr("set"),
},
},
"nil array": {
Generic: schema.Generic{
Type: "array",
},
Items: &schema.Structural{
Generic: schema.Generic{
Type: "array",
},
Items: &schema.Structural{
Generic: schema.Generic{
Type: "string",
Nullable: true,
},
},
},
Extensions: schema.Extensions{
XListType: strPtr("set"),
},
},
"multiple duplicates": {
Generic: schema.Generic{
Type: "array",
},
Items: &schema.Structural{
Generic: schema.Generic{
Type: "object",
AdditionalProperties: &schema.StructuralOrBool{
Structural: &schema.Structural{
Generic: schema.Generic{
Type: "string",
},
},
},
},
},
Extensions: schema.Extensions{
XListType: strPtr("set"),
},
},
},
},
errors: []validationMatch{
duplicate("root", "strings[2]"),
duplicate("root", "integers[2]"),
duplicate("root", "booleans[2]"),
duplicate("root", "float64[2]"),
duplicate("root", "nil[2]"),
duplicate("root", "empty maps[2]"),
duplicate("root", "map values[2]"),
duplicate("root", "array[3]"),
duplicate("root", "nil array[3]"),
duplicate("root", "multiple duplicates[2]"),
duplicate("root", "multiple duplicates[3]"),
},
},
{name: "set list with compound array items",
obj: map[string]interface{}{
"array": []interface{}{[]interface{}{}, []interface{}{"a"}, []interface{}{"a"}},
},
schema: &schema.Structural{
Generic: schema.Generic{
Type: "object",
},
Properties: map[string]schema.Structural{
"array": {
Generic: schema.Generic{
Type: "array",
},
Extensions: schema.Extensions{
XListType: strPtr("set"),
},
Items: &schema.Structural{
Generic: schema.Generic{
Type: "string",
},
},
},
},
},
errors: []validationMatch{
duplicate("root", "array[2]"),
},
},
{name: "map list with compound map items",
obj: map[string]interface{}{
"strings": []interface{}{"a"},
"integers": []interface{}{int64(1)},
"booleans": []interface{}{false},
"float64": []interface{}{float64(1.0)},
"nil": []interface{}{nil},
"array": []interface{}{[]interface{}{"a"}},
"one key": []interface{}{map[string]interface{}{"a": "0", "c": "2"}, map[string]interface{}{"a": "1", "c": "1"}, map[string]interface{}{"a": "1", "c": "2"}, map[string]interface{}{}},
"two keys": []interface{}{map[string]interface{}{"a": "1", "b": "1", "c": "1"}, map[string]interface{}{"a": "1", "b": "2", "c": "2"}, map[string]interface{}{"a": "1", "b": "2", "c": "3"}, map[string]interface{}{}},
"undefined key": []interface{}{map[string]interface{}{"a": "1", "b": "1", "c": "1"}, map[string]interface{}{"a": "1", "c": "2"}, map[string]interface{}{"a": "1", "c": "3"}, map[string]interface{}{}},
"compound key": []interface{}{map[string]interface{}{"a": []interface{}{}, "c": "1"}, map[string]interface{}{"a": nil, "c": "1"}, map[string]interface{}{"a": []interface{}{"a"}, "c": "1"}, map[string]interface{}{"a": []interface{}{"a", int64(42)}, "c": "2"}, map[string]interface{}{"a": []interface{}{"a", int64(42)}, "c": []interface{}{"3"}}},
"nil key": []interface{}{map[string]interface{}{"a": []interface{}{}, "c": "1"}, map[string]interface{}{"a": nil, "c": "1"}, map[string]interface{}{"c": "1"}, map[string]interface{}{"a": nil}},
"nil item": []interface{}{nil, map[string]interface{}{"a": "0", "c": "1"}, map[string]interface{}{"a": nil}, map[string]interface{}{"c": "1"}},
"nil item multiple keys": []interface{}{nil, map[string]interface{}{"b": "0", "c": "1"}, map[string]interface{}{"a": nil}, map[string]interface{}{"c": "1"}},
"multiple duplicates": []interface{}{
map[string]interface{}{"a": []interface{}{}, "c": "1"},
map[string]interface{}{"a": nil, "c": "1"},
map[string]interface{}{"a": []interface{}{"a"}, "c": "1"},
map[string]interface{}{"a": []interface{}{"a", int64(42)}, "c": "2"},
map[string]interface{}{"a": []interface{}{"a", int64(42)}, "c": []interface{}{"3"}},
map[string]interface{}{"a": []interface{}{"a"}, "c": "1", "d": "1"},
map[string]interface{}{"a": []interface{}{"a"}, "c": "1", "d": "2"},
},
},
schema: &schema.Structural{
Generic: schema.Generic{
Type: "object",
},
Properties: map[string]schema.Structural{
"strings": {
Generic: schema.Generic{
Type: "array",
},
Items: &schema.Structural{
Generic: schema.Generic{
Type: "string",
},
},
Extensions: schema.Extensions{
XListType: strPtr("map"),
XListMapKeys: []string{"a"},
},
},
"integers": {
Generic: schema.Generic{
Type: "array",
},
Items: &schema.Structural{
Generic: schema.Generic{
Type: "integer",
},
},
Extensions: schema.Extensions{
XListType: strPtr("map"),
XListMapKeys: []string{"a"},
},
},
"booleans": {
Generic: schema.Generic{
Type: "array",
},
Items: &schema.Structural{
Generic: schema.Generic{
Type: "boolean",
},
},
Extensions: schema.Extensions{
XListType: strPtr("map"),
XListMapKeys: []string{"a"},
},
},
"float64": {
Generic: schema.Generic{
Type: "array",
},
Items: &schema.Structural{
Generic: schema.Generic{
Type: "number",
},
},
Extensions: schema.Extensions{
XListType: strPtr("map"),
XListMapKeys: []string{"a"},
},
},
"nil": {
Generic: schema.Generic{
Type: "array",
},
Items: &schema.Structural{
Generic: schema.Generic{
Type: "string",
Nullable: true,
},
},
Extensions: schema.Extensions{
XListType: strPtr("map"),
XListMapKeys: []string{"a"},
},
},
"array": {
Generic: schema.Generic{
Type: "array",
},
Items: &schema.Structural{
Generic: schema.Generic{
Type: "array",
},
Items: &schema.Structural{
Generic: schema.Generic{
Type: "string",
},
},
},
Extensions: schema.Extensions{
XListType: strPtr("map"),
XListMapKeys: []string{"a"},
},
},
"one key": {
Generic: schema.Generic{
Type: "array",
},
Items: &schema.Structural{
Generic: schema.Generic{
Type: "object",
AdditionalProperties: &schema.StructuralOrBool{
Structural: &schema.Structural{
Generic: schema.Generic{
Type: "string",
},
},
},
},
},
Extensions: schema.Extensions{
XListType: strPtr("map"),
XListMapKeys: []string{"a"},
},
},
"two keys": {
Generic: schema.Generic{
Type: "array",
},
Items: &schema.Structural{
Generic: schema.Generic{
Type: "object",
AdditionalProperties: &schema.StructuralOrBool{
Structural: &schema.Structural{
Generic: schema.Generic{
Type: "string",
},
},
},
},
},
Extensions: schema.Extensions{
XListType: strPtr("map"),
XListMapKeys: []string{"a", "b"},
},
},
"undefined key": {
Generic: schema.Generic{
Type: "array",
},
Items: &schema.Structural{
Generic: schema.Generic{
Type: "object",
AdditionalProperties: &schema.StructuralOrBool{
Structural: &schema.Structural{
Generic: schema.Generic{
Type: "string",
},
},
},
},
},
Extensions: schema.Extensions{
XListType: strPtr("map"),
XListMapKeys: []string{"a", "b"},
},
},
"compound key": {
Generic: schema.Generic{
Type: "array",
},
Items: &schema.Structural{
Generic: schema.Generic{
Type: "object",
AdditionalProperties: &schema.StructuralOrBool{
Structural: &schema.Structural{
Generic: schema.Generic{
Type: "string",
Nullable: true,
},
},
},
},
},
Extensions: schema.Extensions{
XListType: strPtr("map"),
XListMapKeys: []string{"a"},
},
},
"nil key": {
Generic: schema.Generic{
Type: "array",
},
Items: &schema.Structural{
Generic: schema.Generic{
Type: "object",
},
Properties: map[string]schema.Structural{
"a": {
Generic: schema.Generic{
Type: "array",
Nullable: true,
},
Items: &schema.Structural{
Generic: schema.Generic{
Type: "string",
},
},
},
"c": {
Generic: schema.Generic{
Type: "string",
},
},
},
},
Extensions: schema.Extensions{
XListType: strPtr("map"),
XListMapKeys: []string{"a"},
},
},
"nil item": {
Generic: schema.Generic{
Type: "array",
},
Items: &schema.Structural{
Generic: schema.Generic{
Type: "object",
},
Properties: map[string]schema.Structural{
"a": {
Generic: schema.Generic{
Type: "array",
Nullable: true,
},
Items: &schema.Structural{
Generic: schema.Generic{
Type: "string",
},
},
},
"c": {
Generic: schema.Generic{
Type: "string",
},
},
},
},
Extensions: schema.Extensions{
XListType: strPtr("map"),
XListMapKeys: []string{"a"},
},
},
"nil item multiple keys": {
Generic: schema.Generic{
Type: "array",
},
Items: &schema.Structural{
Generic: schema.Generic{
Type: "object",
},
Properties: map[string]schema.Structural{
"a": {
Generic: schema.Generic{
Type: "array",
Nullable: true,
},
Items: &schema.Structural{
Generic: schema.Generic{
Type: "string",
},
},
},
"b": {
Generic: schema.Generic{
Type: "string",
},
},
"c": {
Generic: schema.Generic{
Type: "string",
},
},
},
},
Extensions: schema.Extensions{
XListType: strPtr("map"),
XListMapKeys: []string{"a", "b"},
},
},
"multiple duplicates": {
Generic: schema.Generic{
Type: "array",
},
Items: &schema.Structural{
Generic: schema.Generic{
Type: "object",
AdditionalProperties: &schema.StructuralOrBool{
Structural: &schema.Structural{
Generic: schema.Generic{
Type: "string",
Nullable: true,
},
},
},
},
},
Extensions: schema.Extensions{
XListType: strPtr("map"),
XListMapKeys: []string{"a"},
},
},
},
},
errors: []validationMatch{
invalid("root", "strings[0]"),
invalid("root", "integers[0]"),
invalid("root", "booleans[0]"),
invalid("root", "float64[0]"),
invalid("root", "array[0]"),
duplicate("root", "one key[2]"),
duplicate("root", "two keys[2]"),
duplicate("root", "undefined key[2]"),
duplicate("root", "compound key[4]"),
duplicate("root", "nil key[3]"),
duplicate("root", "nil item[3]"),
duplicate("root", "nil item multiple keys[3]"),
duplicate("root", "multiple duplicates[4]"),
duplicate("root", "multiple duplicates[5]"),
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
errs := ValidateListSetsAndMaps(field.NewPath("root"), tt.schema, tt.obj)
seenErrs := make([]bool, len(errs))
for _, expectedError := range tt.errors {
found := false
for i, err := range errs {
if expectedError.matches(err) && !seenErrs[i] {
found = true
seenErrs[i] = true
break
}
}
if !found {
t.Errorf("expected %v at %v, got %v", expectedError.errorType, expectedError.path.String(), errs)
}
}
for i, seen := range seenErrs {
if !seen {
t.Errorf("unexpected error: %v", errs[i])
}
}
})
}
}
type validationMatch struct {
path *field.Path
errorType field.ErrorType
}
func (v validationMatch) matches(err *field.Error) bool {
return err.Type == v.errorType && err.Field == v.path.String()
}
func duplicate(path ...string) validationMatch {
return validationMatch{path: field.NewPath(path[0], path[1:]...), errorType: field.ErrorTypeDuplicate}
}
func invalid(path ...string) validationMatch {
return validationMatch{path: field.NewPath(path[0], path[1:]...), errorType: field.ErrorTypeInvalid}
}
func strPtr(s string) *string { return &s }
相关信息
相关文章
0
赞
热门推荐
-
2、 - 优质文章
-
3、 gate.io
-
8、 golang
-
9、 openharmony
-
10、 Vue中input框自动聚焦