mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-13 13:55:41 +00:00
kubelet: DRA: add unit test for ClaimInfo and claimInfoCache
This commit is contained in:
parent
6ce294558a
commit
f24134d7b2
@ -102,6 +102,10 @@ func (info *ClaimInfo) setCDIDevices(pluginName string, cdiDevices []string) err
|
|||||||
info.CDIDevices = make(map[string][]string)
|
info.CDIDevices = make(map[string][]string)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if info.annotations == nil {
|
||||||
|
info.annotations = make(map[string][]kubecontainer.Annotation)
|
||||||
|
}
|
||||||
|
|
||||||
info.CDIDevices[pluginName] = cdiDevices
|
info.CDIDevices[pluginName] = cdiDevices
|
||||||
info.annotations[pluginName] = annotations
|
info.annotations[pluginName] = annotations
|
||||||
|
|
||||||
|
894
pkg/kubelet/cm/dra/claiminfo_test.go
Normal file
894
pkg/kubelet/cm/dra/claiminfo_test.go
Normal file
@ -0,0 +1,894 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2024 The Kubernetes Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package dra
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"path"
|
||||||
|
"reflect"
|
||||||
|
"sort"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
resourcev1alpha2 "k8s.io/api/resource/v1alpha2"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/types"
|
||||||
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
|
"k8s.io/kubernetes/pkg/kubelet/cm/dra/state"
|
||||||
|
kubecontainer "k8s.io/kubernetes/pkg/kubelet/container"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ClaimInfo test cases
|
||||||
|
|
||||||
|
func TestNewClaimInfoFromClaim(t *testing.T) {
|
||||||
|
namespace := "test-namespace"
|
||||||
|
className := "test-class"
|
||||||
|
driverName := "test-plugin"
|
||||||
|
claimUID := types.UID("claim-uid")
|
||||||
|
claimName := "test-claim"
|
||||||
|
|
||||||
|
for _, test := range []struct {
|
||||||
|
description string
|
||||||
|
claim *resourcev1alpha2.ResourceClaim
|
||||||
|
expectedResult *ClaimInfo
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
description: "successfully created object",
|
||||||
|
claim: &resourcev1alpha2.ResourceClaim{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
UID: claimUID,
|
||||||
|
Name: claimName,
|
||||||
|
Namespace: namespace,
|
||||||
|
},
|
||||||
|
Status: resourcev1alpha2.ResourceClaimStatus{
|
||||||
|
DriverName: driverName,
|
||||||
|
Allocation: &resourcev1alpha2.AllocationResult{
|
||||||
|
ResourceHandles: []resourcev1alpha2.ResourceHandle{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Spec: resourcev1alpha2.ResourceClaimSpec{
|
||||||
|
ResourceClassName: className,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedResult: &ClaimInfo{
|
||||||
|
ClaimInfoState: state.ClaimInfoState{
|
||||||
|
DriverName: driverName,
|
||||||
|
ClassName: className,
|
||||||
|
ClaimUID: claimUID,
|
||||||
|
ClaimName: claimName,
|
||||||
|
Namespace: claimName,
|
||||||
|
PodUIDs: sets.New[string](),
|
||||||
|
ResourceHandles: []resourcev1alpha2.ResourceHandle{
|
||||||
|
{},
|
||||||
|
},
|
||||||
|
CDIDevices: make(map[string][]string),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "successfully created object with empty allocation",
|
||||||
|
claim: &resourcev1alpha2.ResourceClaim{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
UID: claimUID,
|
||||||
|
Name: claimName,
|
||||||
|
Namespace: namespace,
|
||||||
|
},
|
||||||
|
Status: resourcev1alpha2.ResourceClaimStatus{
|
||||||
|
DriverName: driverName,
|
||||||
|
Allocation: &resourcev1alpha2.AllocationResult{},
|
||||||
|
},
|
||||||
|
Spec: resourcev1alpha2.ResourceClaimSpec{
|
||||||
|
ResourceClassName: className,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedResult: &ClaimInfo{
|
||||||
|
ClaimInfoState: state.ClaimInfoState{
|
||||||
|
DriverName: driverName,
|
||||||
|
ClassName: className,
|
||||||
|
ClaimUID: claimUID,
|
||||||
|
ClaimName: claimName,
|
||||||
|
Namespace: claimName,
|
||||||
|
PodUIDs: sets.New[string](),
|
||||||
|
ResourceHandles: []resourcev1alpha2.ResourceHandle{
|
||||||
|
{},
|
||||||
|
},
|
||||||
|
CDIDevices: make(map[string][]string),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
t.Run(test.description, func(t *testing.T) {
|
||||||
|
result := newClaimInfoFromClaim(test.claim)
|
||||||
|
if reflect.DeepEqual(result, test.expectedResult) {
|
||||||
|
t.Errorf("Expected %v, but got %v", test.expectedResult, result)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNewClaimInfoFromState(t *testing.T) {
|
||||||
|
for _, test := range []struct {
|
||||||
|
description string
|
||||||
|
state *state.ClaimInfoState
|
||||||
|
expectedResult *ClaimInfo
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
description: "successfully created object",
|
||||||
|
state: &state.ClaimInfoState{
|
||||||
|
DriverName: "test-driver",
|
||||||
|
ClassName: "test-class",
|
||||||
|
ClaimUID: "test-uid",
|
||||||
|
ClaimName: "test-claim",
|
||||||
|
Namespace: "test-namespace",
|
||||||
|
PodUIDs: sets.New[string]("test-pod-uid"),
|
||||||
|
ResourceHandles: []resourcev1alpha2.ResourceHandle{},
|
||||||
|
CDIDevices: map[string][]string{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
t.Run(test.description, func(t *testing.T) {
|
||||||
|
result := newClaimInfoFromState(test.state)
|
||||||
|
if reflect.DeepEqual(result, test.expectedResult) {
|
||||||
|
t.Errorf("Expected %v, but got %v", test.expectedResult, result)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClaimInfoSetCDIDevices(t *testing.T) {
|
||||||
|
claimUID := types.UID("claim-uid")
|
||||||
|
pluginName := "test-plugin"
|
||||||
|
device := "vendor.com/device=device1"
|
||||||
|
annotationName := fmt.Sprintf("cdi.k8s.io/%s_%s", pluginName, claimUID)
|
||||||
|
for _, test := range []struct {
|
||||||
|
description string
|
||||||
|
claimInfo *ClaimInfo
|
||||||
|
devices []string
|
||||||
|
expectedCDIDevices map[string][]string
|
||||||
|
expectedAnnotations map[string][]kubecontainer.Annotation
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
description: "successfully add one device",
|
||||||
|
claimInfo: &ClaimInfo{
|
||||||
|
ClaimInfoState: state.ClaimInfoState{
|
||||||
|
DriverName: pluginName,
|
||||||
|
ClaimUID: claimUID,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
devices: []string{device},
|
||||||
|
expectedCDIDevices: map[string][]string{
|
||||||
|
pluginName: {device},
|
||||||
|
},
|
||||||
|
expectedAnnotations: map[string][]kubecontainer.Annotation{
|
||||||
|
pluginName: {
|
||||||
|
{
|
||||||
|
Name: annotationName,
|
||||||
|
Value: device,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "empty list of devices",
|
||||||
|
claimInfo: &ClaimInfo{
|
||||||
|
ClaimInfoState: state.ClaimInfoState{
|
||||||
|
DriverName: pluginName,
|
||||||
|
ClaimUID: claimUID,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
devices: []string{},
|
||||||
|
expectedCDIDevices: map[string][]string{pluginName: {}},
|
||||||
|
expectedAnnotations: map[string][]kubecontainer.Annotation{pluginName: nil},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "incorrect device format",
|
||||||
|
claimInfo: &ClaimInfo{
|
||||||
|
ClaimInfoState: state.ClaimInfoState{
|
||||||
|
DriverName: pluginName,
|
||||||
|
ClaimUID: claimUID,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
devices: []string{"incorrect"},
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
t.Run(test.description, func(t *testing.T) {
|
||||||
|
err := test.claimInfo.setCDIDevices(pluginName, test.devices)
|
||||||
|
if test.wantErr {
|
||||||
|
assert.Error(t, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, test.expectedCDIDevices, test.claimInfo.CDIDevices)
|
||||||
|
assert.Equal(t, test.expectedAnnotations, test.claimInfo.annotations)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClaimInfoAnnotationsAsList(t *testing.T) {
|
||||||
|
for _, test := range []struct {
|
||||||
|
description string
|
||||||
|
claimInfo *ClaimInfo
|
||||||
|
expectedResult []kubecontainer.Annotation
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
description: "empty annotations",
|
||||||
|
claimInfo: &ClaimInfo{
|
||||||
|
annotations: map[string][]kubecontainer.Annotation{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "nil annotations",
|
||||||
|
claimInfo: &ClaimInfo{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "valid annotations",
|
||||||
|
claimInfo: &ClaimInfo{
|
||||||
|
annotations: map[string][]kubecontainer.Annotation{
|
||||||
|
"test-plugin1": {
|
||||||
|
{
|
||||||
|
Name: "cdi.k8s.io/test-plugin1_claim-uid1",
|
||||||
|
Value: "vendor.com/device=device1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "cdi.k8s.io/test-plugin1_claim-uid2",
|
||||||
|
Value: "vendor.com/device=device2",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"test-plugin2": {
|
||||||
|
{
|
||||||
|
Name: "cdi.k8s.io/test-plugin2_claim-uid1",
|
||||||
|
Value: "vendor.com/device=device1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "cdi.k8s.io/test-plugin2_claim-uid2",
|
||||||
|
Value: "vendor.com/device=device2",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedResult: []kubecontainer.Annotation{
|
||||||
|
{
|
||||||
|
Name: "cdi.k8s.io/test-plugin1_claim-uid1",
|
||||||
|
Value: "vendor.com/device=device1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "cdi.k8s.io/test-plugin1_claim-uid2",
|
||||||
|
Value: "vendor.com/device=device2",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "cdi.k8s.io/test-plugin2_claim-uid1",
|
||||||
|
Value: "vendor.com/device=device1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "cdi.k8s.io/test-plugin2_claim-uid2",
|
||||||
|
Value: "vendor.com/device=device2",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
t.Run(test.description, func(t *testing.T) {
|
||||||
|
result := test.claimInfo.annotationsAsList()
|
||||||
|
sort.Slice(result, func(i, j int) bool {
|
||||||
|
return result[i].Name < result[j].Name
|
||||||
|
})
|
||||||
|
assert.Equal(t, test.expectedResult, result)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClaimInfoCDIdevicesAsList(t *testing.T) {
|
||||||
|
for _, test := range []struct {
|
||||||
|
description string
|
||||||
|
claimInfo *ClaimInfo
|
||||||
|
expectedResult []kubecontainer.CDIDevice
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
description: "empty CDI devices",
|
||||||
|
claimInfo: &ClaimInfo{
|
||||||
|
ClaimInfoState: state.ClaimInfoState{
|
||||||
|
CDIDevices: map[string][]string{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "nil CDI devices",
|
||||||
|
claimInfo: &ClaimInfo{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "valid CDI devices",
|
||||||
|
claimInfo: &ClaimInfo{
|
||||||
|
ClaimInfoState: state.ClaimInfoState{
|
||||||
|
CDIDevices: map[string][]string{
|
||||||
|
"test-plugin1": {
|
||||||
|
"vendor.com/device=device1",
|
||||||
|
"vendor.com/device=device2",
|
||||||
|
},
|
||||||
|
"test-plugin2": {
|
||||||
|
"vendor.com/device=device1",
|
||||||
|
"vendor.com/device=device2",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedResult: []kubecontainer.CDIDevice{
|
||||||
|
{
|
||||||
|
Name: "vendor.com/device=device1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "vendor.com/device=device1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "vendor.com/device=device2",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "vendor.com/device=device2",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
t.Run(test.description, func(t *testing.T) {
|
||||||
|
result := test.claimInfo.cdiDevicesAsList()
|
||||||
|
sort.Slice(result, func(i, j int) bool {
|
||||||
|
return result[i].Name < result[j].Name
|
||||||
|
})
|
||||||
|
assert.Equal(t, test.expectedResult, result)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func TestClaimInfoAddPodReference(t *testing.T) {
|
||||||
|
podUID := types.UID("pod-uid")
|
||||||
|
for _, test := range []struct {
|
||||||
|
description string
|
||||||
|
claimInfo *ClaimInfo
|
||||||
|
expectedLen int
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
description: "successfully add pod reference",
|
||||||
|
claimInfo: &ClaimInfo{
|
||||||
|
ClaimInfoState: state.ClaimInfoState{
|
||||||
|
PodUIDs: sets.New[string](),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedLen: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "duplicate pod reference",
|
||||||
|
claimInfo: &ClaimInfo{
|
||||||
|
ClaimInfoState: state.ClaimInfoState{
|
||||||
|
PodUIDs: sets.New[string](string(podUID)),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedLen: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "duplicate pod reference",
|
||||||
|
claimInfo: &ClaimInfo{
|
||||||
|
ClaimInfoState: state.ClaimInfoState{
|
||||||
|
PodUIDs: sets.New[string]("pod-uid1"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedLen: 2,
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
t.Run(test.description, func(t *testing.T) {
|
||||||
|
test.claimInfo.addPodReference(podUID)
|
||||||
|
assert.True(t, test.claimInfo.hasPodReference(podUID))
|
||||||
|
assert.Len(t, test.claimInfo.PodUIDs, test.expectedLen)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClaimInfoHasPodReference(t *testing.T) {
|
||||||
|
podUID := types.UID("pod-uid")
|
||||||
|
for _, test := range []struct {
|
||||||
|
description string
|
||||||
|
claimInfo *ClaimInfo
|
||||||
|
expectedResult bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
description: "claim doesn't reference pod",
|
||||||
|
claimInfo: &ClaimInfo{
|
||||||
|
ClaimInfoState: state.ClaimInfoState{
|
||||||
|
PodUIDs: sets.New[string](),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "claim references pod",
|
||||||
|
claimInfo: &ClaimInfo{
|
||||||
|
ClaimInfoState: state.ClaimInfoState{
|
||||||
|
PodUIDs: sets.New[string](string(podUID)),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedResult: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "empty claim info",
|
||||||
|
claimInfo: &ClaimInfo{},
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
t.Run(test.description, func(t *testing.T) {
|
||||||
|
assert.Equal(t, test.claimInfo.hasPodReference(podUID), test.expectedResult)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClaimInfoDeletePodReference(t *testing.T) {
|
||||||
|
podUID := types.UID("pod-uid")
|
||||||
|
for _, test := range []struct {
|
||||||
|
description string
|
||||||
|
claimInfo *ClaimInfo
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
description: "claim doesn't reference pod",
|
||||||
|
claimInfo: &ClaimInfo{
|
||||||
|
ClaimInfoState: state.ClaimInfoState{
|
||||||
|
PodUIDs: sets.New[string](),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "claim references pod",
|
||||||
|
claimInfo: &ClaimInfo{
|
||||||
|
ClaimInfoState: state.ClaimInfoState{
|
||||||
|
PodUIDs: sets.New[string](string(podUID)),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "empty claim info",
|
||||||
|
claimInfo: &ClaimInfo{},
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
t.Run(test.description, func(t *testing.T) {
|
||||||
|
test.claimInfo.deletePodReference(podUID)
|
||||||
|
assert.False(t, test.claimInfo.hasPodReference(podUID))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClaimInfoSetPrepared(t *testing.T) {
|
||||||
|
for _, test := range []struct {
|
||||||
|
description string
|
||||||
|
claimInfo *ClaimInfo
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
description: "claim info is not prepared",
|
||||||
|
claimInfo: &ClaimInfo{
|
||||||
|
prepared: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "claim info is prepared",
|
||||||
|
claimInfo: &ClaimInfo{
|
||||||
|
prepared: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "empty claim info",
|
||||||
|
claimInfo: &ClaimInfo{},
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
t.Run(test.description, func(t *testing.T) {
|
||||||
|
test.claimInfo.setPrepared()
|
||||||
|
assert.Equal(t, test.claimInfo.isPrepared(), true)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClaimInfoIsPrepared(t *testing.T) {
|
||||||
|
for _, test := range []struct {
|
||||||
|
description string
|
||||||
|
claimInfo *ClaimInfo
|
||||||
|
expectedResult bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
description: "claim info is not prepared",
|
||||||
|
claimInfo: &ClaimInfo{
|
||||||
|
prepared: false,
|
||||||
|
},
|
||||||
|
expectedResult: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "claim info is prepared",
|
||||||
|
claimInfo: &ClaimInfo{
|
||||||
|
prepared: true,
|
||||||
|
},
|
||||||
|
expectedResult: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "empty claim info",
|
||||||
|
claimInfo: &ClaimInfo{},
|
||||||
|
expectedResult: false,
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
t.Run(test.description, func(t *testing.T) {
|
||||||
|
assert.Equal(t, test.claimInfo.isPrepared(), test.expectedResult)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// claimInfoCache test cases
|
||||||
|
func TestNewClaimInfoCache(t *testing.T) {
|
||||||
|
for _, test := range []struct {
|
||||||
|
description string
|
||||||
|
stateDir string
|
||||||
|
checkpointName string
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
description: "successfully created cache",
|
||||||
|
stateDir: t.TempDir(),
|
||||||
|
checkpointName: "test-checkpoint",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "empty parameters",
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "empty checkpoint name",
|
||||||
|
stateDir: t.TempDir(),
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "incorrect checkpoint name",
|
||||||
|
stateDir: path.Join(t.TempDir(), "incorrect checkpoint"),
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
t.Run(test.description, func(t *testing.T) {
|
||||||
|
result, err := newClaimInfoCache(test.stateDir, test.checkpointName)
|
||||||
|
if test.wantErr {
|
||||||
|
assert.Error(t, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NotNil(t, result)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClaimInfoCacheWithLock(t *testing.T) {
|
||||||
|
for _, test := range []struct {
|
||||||
|
description string
|
||||||
|
funcGen func(cache *claimInfoCache) func() error
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
description: "cache is locked inside a function",
|
||||||
|
funcGen: func(cache *claimInfoCache) func() error {
|
||||||
|
return func() error {
|
||||||
|
if cache.RWMutex.TryLock() {
|
||||||
|
return errors.New("Lock succeeded")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "cache is Rlocked inside a function",
|
||||||
|
funcGen: func(cache *claimInfoCache) func() error {
|
||||||
|
return func() error {
|
||||||
|
if cache.RWMutex.TryRLock() {
|
||||||
|
return errors.New("RLock succeeded")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "successfully called function",
|
||||||
|
funcGen: func(cache *claimInfoCache) func() error {
|
||||||
|
return func() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "erroring function",
|
||||||
|
funcGen: func(cache *claimInfoCache) func() error {
|
||||||
|
return func() error {
|
||||||
|
return errors.New("test error")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
t.Run(test.description, func(t *testing.T) {
|
||||||
|
cache, err := newClaimInfoCache(t.TempDir(), "test-checkpoint")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NotNil(t, cache)
|
||||||
|
err = cache.withLock(test.funcGen(cache))
|
||||||
|
if test.wantErr {
|
||||||
|
assert.Error(t, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
assert.NoError(t, err)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClaimInfoCacheWithRLock(t *testing.T) {
|
||||||
|
for _, test := range []struct {
|
||||||
|
description string
|
||||||
|
funcGen func(cache *claimInfoCache) func() error
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
description: "RLock-ed cache allows another RLock",
|
||||||
|
funcGen: func(cache *claimInfoCache) func() error {
|
||||||
|
return func() error {
|
||||||
|
if !cache.RWMutex.TryRLock() {
|
||||||
|
return errors.New("RLock failed")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "cache is locked inside a function",
|
||||||
|
funcGen: func(cache *claimInfoCache) func() error {
|
||||||
|
return func() error {
|
||||||
|
if cache.RWMutex.TryLock() {
|
||||||
|
return errors.New("Lock succeeded")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "successfully called function",
|
||||||
|
funcGen: func(cache *claimInfoCache) func() error {
|
||||||
|
return func() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "erroring function",
|
||||||
|
funcGen: func(cache *claimInfoCache) func() error {
|
||||||
|
return func() error {
|
||||||
|
return errors.New("test error")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
t.Run(test.description, func(t *testing.T) {
|
||||||
|
cache, err := newClaimInfoCache(t.TempDir(), "test-checkpoint")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NotNil(t, cache)
|
||||||
|
err = cache.withRLock(test.funcGen(cache))
|
||||||
|
if test.wantErr {
|
||||||
|
assert.Error(t, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
assert.NoError(t, err)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClaimInfoCacheAdd(t *testing.T) {
|
||||||
|
for _, test := range []struct {
|
||||||
|
description string
|
||||||
|
claimInfo *ClaimInfo
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
description: "claimInfo successfully added",
|
||||||
|
claimInfo: &ClaimInfo{
|
||||||
|
ClaimInfoState: state.ClaimInfoState{
|
||||||
|
ClaimName: "test-claim",
|
||||||
|
Namespace: "test-namespace",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
t.Run(test.description, func(t *testing.T) {
|
||||||
|
cache, err := newClaimInfoCache(t.TempDir(), "test-checkpoint")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NotNil(t, cache)
|
||||||
|
cache.add(test.claimInfo)
|
||||||
|
assert.True(t, cache.contains(test.claimInfo.ClaimName, test.claimInfo.Namespace))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClaimInfoCacheContains(t *testing.T) {
|
||||||
|
claimName := "test-claim"
|
||||||
|
namespace := "test-namespace"
|
||||||
|
for _, test := range []struct {
|
||||||
|
description string
|
||||||
|
claimInfo *ClaimInfo
|
||||||
|
claimInfoCache *claimInfoCache
|
||||||
|
expectedResult bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
description: "cache hit",
|
||||||
|
claimInfoCache: &claimInfoCache{
|
||||||
|
claimInfo: map[string]*ClaimInfo{
|
||||||
|
namespace + "/" + claimName: {
|
||||||
|
ClaimInfoState: state.ClaimInfoState{
|
||||||
|
ClaimName: claimName,
|
||||||
|
Namespace: namespace,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
claimInfo: &ClaimInfo{
|
||||||
|
ClaimInfoState: state.ClaimInfoState{
|
||||||
|
ClaimName: claimName,
|
||||||
|
Namespace: namespace,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedResult: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "cache miss",
|
||||||
|
claimInfoCache: &claimInfoCache{},
|
||||||
|
claimInfo: &ClaimInfo{
|
||||||
|
ClaimInfoState: state.ClaimInfoState{
|
||||||
|
ClaimName: claimName,
|
||||||
|
Namespace: namespace,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "cache miss: empty cache and empty claim info",
|
||||||
|
claimInfoCache: &claimInfoCache{},
|
||||||
|
claimInfo: &ClaimInfo{
|
||||||
|
ClaimInfoState: state.ClaimInfoState{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
t.Run(test.description, func(t *testing.T) {
|
||||||
|
assert.Equal(t, test.expectedResult, test.claimInfoCache.contains(test.claimInfo.ClaimName, test.claimInfo.Namespace))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClaimInfoCacheGet(t *testing.T) {
|
||||||
|
claimName := "test-claim"
|
||||||
|
namespace := "test-namespace"
|
||||||
|
for _, test := range []struct {
|
||||||
|
description string
|
||||||
|
claimInfoCache *claimInfoCache
|
||||||
|
expectedNil bool
|
||||||
|
expectedExists bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
description: "cache hit",
|
||||||
|
claimInfoCache: &claimInfoCache{
|
||||||
|
claimInfo: map[string]*ClaimInfo{
|
||||||
|
namespace + "/" + claimName: {
|
||||||
|
ClaimInfoState: state.ClaimInfoState{
|
||||||
|
ClaimName: claimName,
|
||||||
|
Namespace: namespace,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedExists: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "cache miss",
|
||||||
|
claimInfoCache: &claimInfoCache{},
|
||||||
|
expectedNil: true,
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
t.Run(test.description, func(t *testing.T) {
|
||||||
|
result, exists := test.claimInfoCache.get(claimName, namespace)
|
||||||
|
assert.Equal(t, test.expectedExists, exists)
|
||||||
|
assert.Equal(t, test.expectedNil, result == nil)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClaimInfoCacheDelete(t *testing.T) {
|
||||||
|
claimName := "test-claim"
|
||||||
|
namespace := "test-namespace"
|
||||||
|
for _, test := range []struct {
|
||||||
|
description string
|
||||||
|
claimInfoCache *claimInfoCache
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
description: "item in cache",
|
||||||
|
claimInfoCache: &claimInfoCache{
|
||||||
|
claimInfo: map[string]*ClaimInfo{
|
||||||
|
claimName + namespace: {
|
||||||
|
ClaimInfoState: state.ClaimInfoState{
|
||||||
|
ClaimName: claimName,
|
||||||
|
Namespace: namespace,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "item not in cache",
|
||||||
|
claimInfoCache: &claimInfoCache{},
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
t.Run(test.description, func(t *testing.T) {
|
||||||
|
test.claimInfoCache.delete(claimName, namespace)
|
||||||
|
assert.False(t, test.claimInfoCache.contains(claimName, namespace))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClaimInfoCacheHasPodReference(t *testing.T) {
|
||||||
|
claimName := "test-claim"
|
||||||
|
namespace := "test-namespace"
|
||||||
|
uid := types.UID("test-uid")
|
||||||
|
for _, test := range []struct {
|
||||||
|
description string
|
||||||
|
claimInfoCache *claimInfoCache
|
||||||
|
expectedResult bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
description: "uid is referenced",
|
||||||
|
claimInfoCache: &claimInfoCache{
|
||||||
|
claimInfo: map[string]*ClaimInfo{
|
||||||
|
claimName + namespace: {
|
||||||
|
ClaimInfoState: state.ClaimInfoState{
|
||||||
|
ClaimName: claimName,
|
||||||
|
Namespace: namespace,
|
||||||
|
PodUIDs: sets.New[string](string(uid)),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedResult: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "uid is not referenced",
|
||||||
|
claimInfoCache: &claimInfoCache{},
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
t.Run(test.description, func(t *testing.T) {
|
||||||
|
assert.Equal(t, test.expectedResult, test.claimInfoCache.hasPodReference(uid))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSyncToCheckpoint(t *testing.T) {
|
||||||
|
for _, test := range []struct {
|
||||||
|
description string
|
||||||
|
stateDir string
|
||||||
|
checkpointName string
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
description: "successfully checkpointed cache",
|
||||||
|
stateDir: t.TempDir(),
|
||||||
|
checkpointName: "test-checkpoint",
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
t.Run(test.description, func(t *testing.T) {
|
||||||
|
cache, err := newClaimInfoCache(test.stateDir, test.checkpointName)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
err = cache.syncToCheckpoint()
|
||||||
|
if test.wantErr {
|
||||||
|
assert.Error(t, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
assert.NoError(t, err)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user