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 }