github.com/kubewharf/katalyst-core@v0.5.3/pkg/metaserver/external/cgroupid/manager_linux_test.go (about) 1 //go:build linux 2 // +build linux 3 4 /* 5 Copyright 2022 The Katalyst Authors. 6 7 Licensed under the Apache License, Version 2.0 (the "License"); 8 you may not use this file except in compliance with the License. 9 You may obtain a copy of the License at 10 11 http://www.apache.org/licenses/LICENSE-2.0 12 13 Unless required by applicable law or agreed to in writing, software 14 distributed under the License is distributed on an "AS IS" BASIS, 15 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 See the License for the specific language governing permissions and 17 limitations under the License. 18 */ 19 20 package cgroupid 21 22 import ( 23 "reflect" 24 "sort" 25 "testing" 26 "time" 27 28 "github.com/stretchr/testify/assert" 29 v1 "k8s.io/api/core/v1" 30 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 31 "k8s.io/apimachinery/pkg/types" 32 "k8s.io/apimachinery/pkg/util/sets" 33 34 "github.com/kubewharf/katalyst-core/pkg/metaserver/agent/pod" 35 ) 36 37 var ( 38 podFetcher = makePodFetcher(makePodList()) 39 podUIDList = []string{"uid-1", "uid-2", "uid-3", "uid-4"} 40 containerIDList = []string{"container-id-1", "container-id-2", "container-id-3", "container-id-4", "container-id-5", "container-id-6"} 41 containerNameList = []string{"container-name-1", "container-name-2", "container-name-3", "container-name-4", "container-name-5", "container-name-6"} 42 cgIDList = []uint64{1, 2, 3, 4, 5, 6} 43 ) 44 45 func TestGetCgroupIDForContainer(t *testing.T) { 46 t.Parallel() 47 48 cgroupIDManager := NewCgroupIDManager(podFetcher).(*cgroupIDManagerImpl) 49 assert.NotNil(t, cgroupIDManager) 50 51 cgroupIDManager.setCgroupID(podUIDList[0], containerIDList[0], cgIDList[0]) 52 cgroupIDManager.setCgroupID(podUIDList[1], containerIDList[1], cgIDList[1]) 53 54 tests := []struct { 55 name string 56 podUID string 57 containerID string 58 want uint64 59 }{ 60 { 61 name: "get cgID for container 1", 62 podUID: podUIDList[0], 63 containerID: containerIDList[0], 64 want: cgIDList[0], 65 }, 66 { 67 name: "get cgID for container 2", 68 podUID: podUIDList[1], 69 containerID: containerIDList[1], 70 want: cgIDList[1], 71 }, 72 } 73 74 for _, tt := range tests { 75 tt := tt 76 t.Run(tt.name, func(t *testing.T) { 77 t.Parallel() 78 cgID, err := cgroupIDManager.GetCgroupIDForContainer(tt.podUID, tt.containerID) 79 assert.NoError(t, err) 80 assert.Equal(t, tt.want, cgID) 81 }) 82 } 83 } 84 85 func TestListCgroupIDsForPod(t *testing.T) { 86 t.Parallel() 87 88 cgroupIDManager := NewCgroupIDManager(podFetcher).(*cgroupIDManagerImpl) 89 assert.NotNil(t, cgroupIDManager) 90 91 cgroupIDManager.setCgroupID(podUIDList[0], containerIDList[0], cgIDList[0]) 92 cgroupIDManager.setCgroupID(podUIDList[1], containerIDList[1], cgIDList[1]) 93 cgroupIDManager.setCgroupID(podUIDList[1], containerIDList[2], cgIDList[2]) 94 95 tests := []struct { 96 name string 97 podUID string 98 want []uint64 99 }{ 100 { 101 name: "get cgID for pod 1", 102 podUID: podUIDList[0], 103 want: []uint64{cgIDList[0]}, 104 }, 105 { 106 name: "get cgID for pod 2", 107 podUID: podUIDList[1], 108 want: []uint64{cgIDList[1], cgIDList[2]}, 109 }, 110 } 111 112 for _, tt := range tests { 113 tt := tt 114 t.Run(tt.name, func(t *testing.T) { 115 t.Parallel() 116 117 cgIDs, err := cgroupIDManager.ListCgroupIDsForPod(tt.podUID) 118 assert.NoError(t, err) 119 sort.Slice(tt.want, func(i, j int) bool { return tt.want[i] < tt.want[j] }) 120 sort.Slice(cgIDs, func(i, j int) bool { return cgIDs[i] < cgIDs[j] }) 121 assert.True(t, reflect.DeepEqual(tt.want, cgIDs)) 122 }) 123 } 124 } 125 126 func TestGetAbsentContainers(t *testing.T) { 127 t.Parallel() 128 129 cgroupIDManager := NewCgroupIDManager(podFetcher).(*cgroupIDManagerImpl) 130 assert.NotNil(t, cgroupIDManager) 131 132 cgroupIDManager.setCgroupID(podUIDList[0], containerIDList[0], cgIDList[0]) 133 cgroupIDManager.setCgroupID(podUIDList[1], containerIDList[1], cgIDList[1]) 134 cgroupIDManager.setCgroupID(podUIDList[1], containerIDList[2], cgIDList[2]) 135 136 tests := []struct { 137 name string 138 podList []*v1.Pod 139 want map[string]sets.String 140 }{ 141 { 142 name: "get absent containers", 143 podList: makePodList(), 144 want: map[string]sets.String{ 145 podUIDList[1]: sets.NewString(containerIDList[3]), 146 podUIDList[2]: sets.NewString(containerIDList[4]), 147 }, 148 }, 149 } 150 151 for _, tt := range tests { 152 tt := tt 153 t.Run(tt.name, func(t *testing.T) { 154 t.Parallel() 155 156 gotAbsentContainers := cgroupIDManager.getAbsentContainers(tt.podList) 157 assert.Equal(t, len(tt.want), len(gotAbsentContainers)) 158 for wantPodUID, wantContainerSet := range tt.want { 159 gotContainerSet, ok := gotAbsentContainers[wantPodUID] 160 assert.True(t, ok) 161 assert.True(t, wantContainerSet.Equal(gotContainerSet)) 162 } 163 }) 164 } 165 } 166 167 func TestClearResidualPodsInCache(t *testing.T) { 168 t.Parallel() 169 170 cgroupIDManager := NewCgroupIDManager(podFetcher).(*cgroupIDManagerImpl) 171 assert.NotNil(t, cgroupIDManager) 172 173 cgroupIDManager.setCgroupID(podUIDList[0], containerIDList[0], cgIDList[0]) 174 cgroupIDManager.setCgroupID(podUIDList[1], containerIDList[1], cgIDList[1]) 175 cgroupIDManager.setCgroupID(podUIDList[1], containerIDList[2], cgIDList[2]) 176 cgroupIDManager.setCgroupID(podUIDList[3], containerIDList[5], cgIDList[5]) 177 178 tests := []struct { 179 name string 180 podList []*v1.Pod 181 want map[string]map[string]uint64 182 }{ 183 { 184 name: "clear residual pods in cache", 185 podList: makePodList(), 186 want: map[string]map[string]uint64{ 187 podUIDList[0]: { 188 containerIDList[0]: cgIDList[0], 189 }, 190 podUIDList[1]: { 191 containerIDList[1]: cgIDList[1], 192 containerIDList[2]: cgIDList[2], 193 }, 194 }, 195 }, 196 } 197 198 for _, tt := range tests { 199 tt := tt 200 t.Run(tt.name, func(t *testing.T) { 201 t.Parallel() 202 for i := 0; time.Duration(i)*cgroupIDManager.reconcilePeriod < maxResidualTime; i++ { 203 cgroupIDManager.clearResidualPodsInCache(tt.podList) 204 } 205 206 assert.Equal(t, len(tt.want), len(cgroupIDManager.podCgroupIDCache)) 207 for wantPodUID, wantContainerMap := range tt.want { 208 cgroupIDManager.Lock() 209 gotContainerMap, ok := cgroupIDManager.podCgroupIDCache[wantPodUID] 210 211 assert.True(t, ok) 212 assert.Equal(t, len(wantContainerMap), len(gotContainerMap)) 213 for wantContainerID, wantCgID := range wantContainerMap { 214 gotCgID, ok := wantContainerMap[wantContainerID] 215 assert.True(t, ok) 216 assert.Equal(t, wantCgID, gotCgID) 217 } 218 cgroupIDManager.Unlock() 219 } 220 }) 221 } 222 } 223 224 func makePodFetcher(podList []*v1.Pod) pod.PodFetcher { 225 podFetcher := pod.PodFetcherStub{} 226 if len(podList) > 0 { 227 podFetcher.PodList = podList 228 } 229 return &podFetcher 230 } 231 232 func makePodList() []*v1.Pod { 233 return []*v1.Pod{ 234 { 235 ObjectMeta: metav1.ObjectMeta{ 236 UID: types.UID(podUIDList[0]), 237 }, 238 Spec: v1.PodSpec{ 239 Containers: []v1.Container{ 240 { 241 Name: containerNameList[0], 242 }, 243 }, 244 }, 245 Status: v1.PodStatus{ 246 ContainerStatuses: []v1.ContainerStatus{ 247 { 248 Name: containerNameList[0], 249 ContainerID: containerIDList[0], 250 }, 251 }, 252 }, 253 }, 254 { 255 ObjectMeta: metav1.ObjectMeta{ 256 UID: types.UID(podUIDList[1]), 257 }, 258 Spec: v1.PodSpec{ 259 Containers: []v1.Container{ 260 { 261 Name: containerNameList[1], 262 }, 263 { 264 Name: containerNameList[2], 265 }, 266 { 267 Name: containerNameList[3], 268 }, 269 }, 270 }, 271 Status: v1.PodStatus{ 272 ContainerStatuses: []v1.ContainerStatus{ 273 { 274 Name: containerNameList[1], 275 ContainerID: containerIDList[1], 276 }, 277 { 278 Name: containerNameList[2], 279 ContainerID: containerIDList[2], 280 }, 281 { 282 Name: containerNameList[3], 283 ContainerID: containerIDList[3], 284 }, 285 }, 286 }, 287 }, 288 { 289 ObjectMeta: metav1.ObjectMeta{ 290 UID: types.UID(podUIDList[2]), 291 }, 292 Spec: v1.PodSpec{ 293 Containers: []v1.Container{ 294 { 295 Name: containerNameList[4], 296 }, 297 }, 298 }, 299 Status: v1.PodStatus{ 300 ContainerStatuses: []v1.ContainerStatus{ 301 { 302 Name: containerNameList[4], 303 ContainerID: containerIDList[4], 304 }, 305 }, 306 }, 307 }, 308 } 309 }