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  }