istio.io/istio@v0.0.0-20240520182934-d79c90f27776/operator/pkg/cache/cache_test.go (about)

     1  // Copyright Istio Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package cache
    16  
    17  import (
    18  	"reflect"
    19  	"sync"
    20  	"testing"
    21  
    22  	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
    23  
    24  	"istio.io/istio/operator/pkg/object"
    25  )
    26  
    27  func TestFlushObjectCaches(t *testing.T) {
    28  	tests := []struct {
    29  		desc     string
    30  		wantSize int
    31  	}{
    32  		{
    33  			desc:     "flush-cache",
    34  			wantSize: 0,
    35  		},
    36  	}
    37  	for _, tt := range tests {
    38  		t.Run(tt.desc, func(t *testing.T) {
    39  			unstObjs := make(map[string]any)
    40  			tUnstructured := &unstructured.Unstructured{Object: unstObjs}
    41  			testCache := make(map[string]*object.K8sObject)
    42  			testCache["foo"] = object.NewK8sObject(tUnstructured, nil, nil)
    43  			objectCaches["foo"] = &ObjectCache{
    44  				Cache: testCache,
    45  				Mu:    &sync.RWMutex{},
    46  			}
    47  			if len(objectCaches) != 1 {
    48  				t.Errorf("%s: Expected len 1, got len 0.", tt.desc)
    49  			}
    50  			FlushObjectCaches()
    51  			if gotLen := len(objectCaches); gotLen != tt.wantSize {
    52  				t.Errorf("%s: Expected size %v after flush, got size %v", tt.desc, tt.wantSize, gotLen)
    53  			}
    54  		})
    55  	}
    56  }
    57  
    58  func TestGetCache(t *testing.T) {
    59  	tests := []struct {
    60  		desc string
    61  		key  string
    62  		in   map[string]*ObjectCache
    63  		want ObjectCache
    64  	}{
    65  		{
    66  			desc: "value-exists",
    67  			key:  "foo-key",
    68  			in: map[string]*ObjectCache{
    69  				"foo-key": {
    70  					Cache: make(map[string]*object.K8sObject),
    71  					Mu:    nil,
    72  				},
    73  			},
    74  			want: ObjectCache{
    75  				Cache: make(map[string]*object.K8sObject),
    76  				Mu:    nil,
    77  			},
    78  		},
    79  		{
    80  			desc: "key-does-not-exist",
    81  			key:  "foo-key",
    82  			in:   make(map[string]*ObjectCache),
    83  			want: ObjectCache{
    84  				Cache: make(map[string]*object.K8sObject),
    85  				Mu:    &sync.RWMutex{},
    86  			},
    87  		},
    88  	}
    89  	for _, tt := range tests {
    90  		t.Run(tt.desc, func(t *testing.T) {
    91  			defer FlushObjectCaches()
    92  			for key, value := range tt.in {
    93  				objectCaches[key] = value
    94  			}
    95  			if gotCache := GetCache(tt.key); !reflect.DeepEqual(*gotCache, tt.want) {
    96  				t.Errorf("%s: expected cache %v, got cache %v\n", tt.desc, tt.want, *gotCache)
    97  			}
    98  		})
    99  	}
   100  }
   101  
   102  func TestRemoveObject(t *testing.T) {
   103  	tests := []struct {
   104  		desc string
   105  		in   map[string]*ObjectCache
   106  		// key for map of caches
   107  		objCacheRemovalKey string
   108  		// key for map of K8sObjects
   109  		removalKey string
   110  		// cache in position objectCaches[objCacheRemovalKey]
   111  		expectedCache ObjectCache
   112  	}{
   113  		{
   114  			desc: "remove-cache",
   115  			in: map[string]*ObjectCache{
   116  				"cache-foo-key": {
   117  					Cache: map[string]*object.K8sObject{
   118  						"obj-foo-key": object.NewK8sObject(&unstructured.Unstructured{
   119  							Object: make(map[string]any),
   120  						}, nil, nil),
   121  						"dont-touch-me-key": object.NewK8sObject(&unstructured.Unstructured{
   122  							Object: make(map[string]any),
   123  						}, nil, nil),
   124  					},
   125  					Mu: &sync.RWMutex{},
   126  				},
   127  			},
   128  			objCacheRemovalKey: "cache-foo-key",
   129  			removalKey:         "obj-foo-key",
   130  			expectedCache: ObjectCache{
   131  				Cache: map[string]*object.K8sObject{
   132  					"dont-touch-me-key": object.NewK8sObject(&unstructured.Unstructured{
   133  						Object: make(map[string]any),
   134  					}, nil, nil),
   135  				},
   136  				Mu: &sync.RWMutex{},
   137  			},
   138  		},
   139  	}
   140  	for _, tt := range tests {
   141  		t.Run(tt.desc, func(t *testing.T) {
   142  			for key, value := range tt.in {
   143  				objectCaches[key] = value
   144  			}
   145  			defer FlushObjectCaches()
   146  			RemoveObject(tt.objCacheRemovalKey, tt.removalKey)
   147  			if got := objectCaches[tt.objCacheRemovalKey]; !reflect.DeepEqual(*got, tt.expectedCache) {
   148  				t.Errorf("%s: expected object cache %v, got %v\n", tt.desc, tt.expectedCache, got)
   149  			}
   150  		})
   151  	}
   152  }
   153  
   154  func TestRemoveCache(t *testing.T) {
   155  	tests := []struct {
   156  		desc string
   157  		in   map[string]*ObjectCache
   158  		// key for map of caches
   159  		objCacheRemovalKey string
   160  		expected           map[string]*ObjectCache
   161  	}{
   162  		{
   163  			desc: "remove-cache",
   164  			in: map[string]*ObjectCache{
   165  				"cache-foo-key": {
   166  					Cache: map[string]*object.K8sObject{
   167  						"obj-foo-key": object.NewK8sObject(&unstructured.Unstructured{
   168  							Object: make(map[string]any),
   169  						}, nil, nil),
   170  					},
   171  					Mu: &sync.RWMutex{},
   172  				},
   173  				"dont-touch-me-key": {
   174  					Cache: map[string]*object.K8sObject{
   175  						"obj-foo-key": object.NewK8sObject(&unstructured.Unstructured{
   176  							Object: make(map[string]any),
   177  						}, nil, nil),
   178  					},
   179  					Mu: &sync.RWMutex{},
   180  				},
   181  			},
   182  			objCacheRemovalKey: "cache-foo-key",
   183  			expected: map[string]*ObjectCache{
   184  				"dont-touch-me-key": {
   185  					Cache: map[string]*object.K8sObject{
   186  						"obj-foo-key": object.NewK8sObject(&unstructured.Unstructured{
   187  							Object: make(map[string]any),
   188  						}, nil, nil),
   189  					},
   190  					Mu: &sync.RWMutex{},
   191  				},
   192  			},
   193  		},
   194  	}
   195  	for _, tt := range tests {
   196  		t.Run(tt.desc, func(t *testing.T) {
   197  			for key, value := range tt.in {
   198  				objectCaches[key] = value
   199  			}
   200  			defer FlushObjectCaches()
   201  			RemoveCache(tt.objCacheRemovalKey)
   202  			if !reflect.DeepEqual(objectCaches, tt.expected) {
   203  				t.Errorf("%s: expected object cache %v, got %v\n", tt.desc, tt.expected, objectCaches)
   204  			}
   205  		})
   206  	}
   207  }