k8s.io/apiserver@v0.29.3/pkg/storage/selection_predicate_test.go (about) 1 /* 2 Copyright 2016 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package storage 18 19 import ( 20 "errors" 21 "reflect" 22 "testing" 23 24 "k8s.io/apimachinery/pkg/fields" 25 "k8s.io/apimachinery/pkg/labels" 26 "k8s.io/apimachinery/pkg/runtime" 27 "k8s.io/apimachinery/pkg/runtime/schema" 28 ) 29 30 type Ignored struct { 31 ID string 32 } 33 34 func (obj *Ignored) GetObjectKind() schema.ObjectKind { return schema.EmptyObjectKind } 35 func (obj *Ignored) DeepCopyObject() runtime.Object { 36 panic("Ignored does not support DeepCopy") 37 } 38 39 func TestSelectionPredicate(t *testing.T) { 40 table := map[string]struct { 41 labelSelector, fieldSelector string 42 labels labels.Set 43 fields fields.Set 44 err error 45 shouldMatch bool 46 matchSingleKey string 47 }{ 48 "A": { 49 labelSelector: "name=foo", 50 fieldSelector: "uid=12345", 51 labels: labels.Set{"name": "foo"}, 52 fields: fields.Set{"uid": "12345"}, 53 shouldMatch: true, 54 }, 55 "B": { 56 labelSelector: "name=foo", 57 fieldSelector: "uid=12345", 58 labels: labels.Set{"name": "foo"}, 59 fields: fields.Set{}, 60 shouldMatch: false, 61 }, 62 "C": { 63 labelSelector: "name=foo", 64 fieldSelector: "uid=12345", 65 labels: labels.Set{}, 66 fields: fields.Set{"uid": "12345"}, 67 shouldMatch: false, 68 }, 69 "D": { 70 fieldSelector: "metadata.name=12345", 71 labels: labels.Set{}, 72 fields: fields.Set{"metadata.name": "12345"}, 73 shouldMatch: true, 74 matchSingleKey: "12345", 75 }, 76 "error": { 77 labelSelector: "name=foo", 78 fieldSelector: "uid=12345", 79 err: errors.New("maybe this is a 'wrong object type' error"), 80 shouldMatch: false, 81 }, 82 } 83 84 for name, item := range table { 85 parsedLabel, err := labels.Parse(item.labelSelector) 86 if err != nil { 87 panic(err) 88 } 89 parsedField, err := fields.ParseSelector(item.fieldSelector) 90 if err != nil { 91 panic(err) 92 } 93 sp := &SelectionPredicate{ 94 Label: parsedLabel, 95 Field: parsedField, 96 GetAttrs: func(runtime.Object) (label labels.Set, field fields.Set, err error) { 97 return item.labels, item.fields, item.err 98 }, 99 } 100 got, err := sp.Matches(&Ignored{}) 101 if e, a := item.err, err; e != a { 102 t.Errorf("%v: expected %v, got %v", name, e, a) 103 continue 104 } 105 if e, a := item.shouldMatch, got; e != a { 106 t.Errorf("%v: expected %v, got %v", name, e, a) 107 } 108 got = sp.MatchesObjectAttributes(item.labels, item.fields) 109 if e, a := item.shouldMatch, got; e != a { 110 t.Errorf("%v: expected %v, got %v", name, e, a) 111 } 112 if key := item.matchSingleKey; key != "" { 113 got, ok := sp.MatchesSingle() 114 if !ok { 115 t.Errorf("%v: expected single match", name) 116 } 117 if e, a := key, got; e != a { 118 t.Errorf("%v: expected %v, got %v", name, e, a) 119 } 120 } 121 } 122 } 123 124 func TestSelectionPredicateMatcherIndex(t *testing.T) { 125 testCases := map[string]struct { 126 labelSelector, fieldSelector string 127 indexLabels []string 128 indexFields []string 129 expected []MatchValue 130 }{ 131 "Match nil": { 132 labelSelector: "name=foo", 133 fieldSelector: "uid=12345", 134 indexLabels: []string{"bar"}, 135 indexFields: []string{}, 136 expected: nil, 137 }, 138 "Match field": { 139 labelSelector: "name=foo", 140 fieldSelector: "uid=12345", 141 indexLabels: []string{}, 142 indexFields: []string{"uid"}, 143 expected: []MatchValue{{IndexName: FieldIndex("uid"), Value: "12345"}}, 144 }, 145 "Match label": { 146 labelSelector: "name=foo", 147 fieldSelector: "uid=12345", 148 indexLabels: []string{"name"}, 149 indexFields: []string{}, 150 expected: []MatchValue{{IndexName: LabelIndex("name"), Value: "foo"}}, 151 }, 152 "Match field and label": { 153 labelSelector: "name=foo", 154 fieldSelector: "uid=12345", 155 indexLabels: []string{"name"}, 156 indexFields: []string{"uid"}, 157 expected: []MatchValue{{IndexName: FieldIndex("uid"), Value: "12345"}, {IndexName: LabelIndex("name"), Value: "foo"}}, 158 }, 159 "Negative match field and label": { 160 labelSelector: "name!=foo", 161 fieldSelector: "uid!=12345", 162 indexLabels: []string{"name"}, 163 indexFields: []string{"uid"}, 164 expected: nil, 165 }, 166 "Negative match field and match label": { 167 labelSelector: "name=foo", 168 fieldSelector: "uid!=12345", 169 indexLabels: []string{"name"}, 170 indexFields: []string{"uid"}, 171 expected: []MatchValue{{IndexName: LabelIndex("name"), Value: "foo"}}, 172 }, 173 "Negative match label and match field": { 174 labelSelector: "name!=foo", 175 fieldSelector: "uid=12345", 176 indexLabels: []string{"name"}, 177 indexFields: []string{"uid"}, 178 expected: []MatchValue{{IndexName: FieldIndex("uid"), Value: "12345"}}, 179 }, 180 } 181 for name, testCase := range testCases { 182 parsedLabel, err := labels.Parse(testCase.labelSelector) 183 if err != nil { 184 panic(err) 185 } 186 parsedField, err := fields.ParseSelector(testCase.fieldSelector) 187 if err != nil { 188 panic(err) 189 } 190 191 sp := &SelectionPredicate{ 192 Label: parsedLabel, 193 Field: parsedField, 194 IndexLabels: testCase.indexLabels, 195 IndexFields: testCase.indexFields, 196 } 197 actual := sp.MatcherIndex() 198 if !reflect.DeepEqual(testCase.expected, actual) { 199 t.Errorf("%v: expected %v, got %v", name, testCase.expected, actual) 200 } 201 } 202 }