Adding tests for Kubelet pod update functions

This commit is contained in:
Amim Knabben 2020-05-21 11:37:26 -04:00
parent 3995c1a54d
commit ef6a731b42
2 changed files with 274 additions and 56 deletions

View File

@ -35,10 +35,10 @@ go_test(
], ],
embed = [":go_default_library"], embed = [":go_default_library"],
deps = [ deps = [
"//pkg/apis/scheduling:go_default_library",
"//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/github.com/stretchr/testify/assert:go_default_library", "//vendor/github.com/stretchr/testify/assert:go_default_library",
"//vendor/github.com/stretchr/testify/require:go_default_library",
], ],
) )

View File

@ -20,69 +20,131 @@ import (
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
v1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/kubernetes/pkg/apis/scheduling"
) )
var (
systemPriority = int32(scheduling.SystemCriticalPriority)
systemPriorityUpper = systemPriority + 1000
)
// getTestPod generates a new instance of an empty test Pod
func getTestPod(annotations map[string]string, podPriority *int32) *v1.Pod {
pod := v1.Pod{
TypeMeta: metav1.TypeMeta{
Kind: "Pod",
APIVersion: "v1",
},
ObjectMeta: metav1.ObjectMeta{
Name: "foo",
Namespace: "default",
},
}
// Set pod Priority in Spec if exists
if podPriority != nil {
pod.Spec = v1.PodSpec{
Priority: podPriority,
}
}
// Set annotations if exists
if annotations != nil {
pod.Annotations = annotations
}
return &pod
}
func configSourceAnnotation(source string) map[string]string {
return map[string]string{ConfigSourceAnnotationKey: source}
}
func configMirrorAnnotation() map[string]string {
return map[string]string{ConfigMirrorAnnotationKey: "true"}
}
func TestGetValidatedSources(t *testing.T) { func TestGetValidatedSources(t *testing.T) {
// Empty. tests := []struct {
sources, err := GetValidatedSources([]string{""}) name string
require.NoError(t, err) sources []string
require.Len(t, sources, 0) errExpected bool
sourcesLen int
}{
{
name: "empty source",
sources: []string{""},
errExpected: false,
sourcesLen: 0,
},
{
name: "file and apiserver source",
sources: []string{FileSource, ApiserverSource},
errExpected: false,
sourcesLen: 2,
},
{
name: "all source",
sources: []string{AllSource},
errExpected: false,
sourcesLen: 3,
},
{
name: "unknown source",
sources: []string{"unknown"},
errExpected: true,
sourcesLen: 0,
},
}
// Success. for _, test := range tests {
sources, err = GetValidatedSources([]string{FileSource, ApiserverSource}) t.Run(test.name, func(t *testing.T) {
require.NoError(t, err) sources, err := GetValidatedSources(test.sources)
require.Len(t, sources, 2) if test.errExpected {
assert.Error(t, err)
// All. } else {
sources, err = GetValidatedSources([]string{AllSource}) assert.NoError(t, err)
require.NoError(t, err) }
require.Len(t, sources, 3) assert.Len(t, sources, test.sourcesLen)
})
// Unknown source. }
_, err = GetValidatedSources([]string{"taco"})
require.Error(t, err)
} }
func TestGetPodSource(t *testing.T) { func TestGetPodSource(t *testing.T) {
cases := []struct { tests := []struct {
pod v1.Pod name string
pod *v1.Pod
expected string expected string
errExpected bool errExpected bool
}{ }{
{ {
pod: v1.Pod{}, name: "cannot get pod source",
pod: getTestPod(nil, nil),
expected: "", expected: "",
errExpected: true, errExpected: true,
}, },
{ {
pod: v1.Pod{ name: "valid annotation returns the source",
ObjectMeta: metav1.ObjectMeta{ pod: getTestPod(configSourceAnnotation("host-ipc-sources"), nil),
Annotations: map[string]string{
"kubernetes.io/config.source": "host-ipc-sources",
},
},
},
expected: "host-ipc-sources", expected: "host-ipc-sources",
errExpected: false, errExpected: false,
}, },
} }
for i, data := range cases {
source, err := GetPodSource(&data.pod) for _, test := range tests {
if data.errExpected { t.Run(test.name, func(t *testing.T) {
assert.Error(t, err) source, err := GetPodSource(test.pod)
} else { if test.errExpected {
assert.NoError(t, err) assert.Error(t, err)
} } else {
assert.Equal(t, data.expected, source, "test[%d]", i) assert.NoError(t, err)
t.Logf("Test case [%d]", i) }
assert.Equal(t, test.expected, source)
})
} }
} }
func TestString(t *testing.T) { func TestString(t *testing.T) {
cases := []struct { tests := []struct {
sp SyncPodType sp SyncPodType
expected string expected string
}{ }{
@ -107,34 +169,190 @@ func TestString(t *testing.T) {
expected: "unknown", expected: "unknown",
}, },
} }
for i, data := range cases { for _, test := range tests {
syncPodString := data.sp.String() t.Run(test.expected, func(t *testing.T) {
assert.Equal(t, data.expected, syncPodString, "test[%d]", i) syncPodString := test.sp.String()
t.Logf("Test case [%d]", i) assert.Equal(t, test.expected, syncPodString)
})
}
}
func TestIsMirrorPod(t *testing.T) {
tests := []struct {
name string
pod *v1.Pod
expected bool
}{
{
name: "mirror pod",
pod: getTestPod(configMirrorAnnotation(), nil),
expected: true,
},
{
name: "not a mirror pod",
pod: getTestPod(nil, nil),
expected: false,
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
isMirrorPod := IsMirrorPod(test.pod)
assert.Equal(t, test.expected, isMirrorPod)
})
}
}
func TestIsStaticPod(t *testing.T) {
tests := []struct {
name string
pod *v1.Pod
expected bool
}{
{
name: "static pod with file source",
pod: getTestPod(configSourceAnnotation(FileSource), nil),
expected: true,
},
{
name: "static pod with http source",
pod: getTestPod(configSourceAnnotation(HTTPSource), nil),
expected: true,
},
{
name: "static pod with api server source",
pod: getTestPod(configSourceAnnotation(ApiserverSource), nil),
expected: false,
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
isStaticPod := IsStaticPod(test.pod)
assert.Equal(t, test.expected, isStaticPod)
})
}
}
func TestIsCriticalPod(t *testing.T) {
tests := []struct {
name string
pod *v1.Pod
expected bool
}{
{
name: "critical pod with file source",
pod: getTestPod(configSourceAnnotation(FileSource), nil),
expected: true,
},
{
name: "critical pod with mirror annotation",
pod: getTestPod(configMirrorAnnotation(), nil),
expected: true,
},
{
name: "critical pod using system priority",
pod: getTestPod(nil, &systemPriority),
expected: true,
},
{
name: "critical pod using greater than system priority",
pod: getTestPod(nil, &systemPriorityUpper),
expected: true,
},
{
name: "not a critical pod with api server annotation",
pod: getTestPod(configSourceAnnotation(ApiserverSource), nil),
expected: false,
},
{
name: "not critical if not static, mirror or without a priority",
pod: getTestPod(nil, nil),
expected: false,
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
isCriticalPod := IsCriticalPod(test.pod)
assert.Equal(t, test.expected, isCriticalPod)
})
}
}
func TestPreemptable(t *testing.T) {
tests := []struct {
name string
preemptor *v1.Pod
preemptee *v1.Pod
expected bool
}{
{
name: "a critical preemptor pod preempts a non critical pod",
preemptor: getTestPod(configSourceAnnotation(FileSource), nil),
preemptee: getTestPod(nil, nil),
expected: true,
},
{
name: "a preemptor pod with higher priority preempts a critical pod",
preemptor: getTestPod(configSourceAnnotation(FileSource), &systemPriorityUpper),
preemptee: getTestPod(configSourceAnnotation(FileSource), &systemPriority),
expected: true,
},
{
name: "a not critical pod with higher priority preempts a critical pod",
preemptor: getTestPod(configSourceAnnotation(ApiserverSource), &systemPriorityUpper),
preemptee: getTestPod(configSourceAnnotation(FileSource), &systemPriority),
expected: true,
},
{
name: "a critical pod with less priority do not preempts a critical pod",
preemptor: getTestPod(configSourceAnnotation(FileSource), &systemPriority),
preemptee: getTestPod(configSourceAnnotation(FileSource), &systemPriorityUpper),
expected: false,
},
{
name: "a critical pod without priority do not preempts a critical pod without priority",
preemptor: getTestPod(configSourceAnnotation(FileSource), nil),
preemptee: getTestPod(configSourceAnnotation(FileSource), nil),
expected: false,
},
{
name: "a critical pod with priority do not preempts a critical pod with the same priority",
preemptor: getTestPod(configSourceAnnotation(FileSource), &systemPriority),
preemptee: getTestPod(configSourceAnnotation(FileSource), &systemPriority),
expected: false,
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
isPreemtable := Preemptable(test.preemptor, test.preemptee)
assert.Equal(t, test.expected, isPreemtable)
})
} }
} }
func TestIsCriticalPodBasedOnPriority(t *testing.T) { func TestIsCriticalPodBasedOnPriority(t *testing.T) {
tests := []struct { tests := []struct {
priority int32 priority int32
description string name string
expected bool expected bool
}{ }{
{ {
priority: int32(2000000001), name: "a system critical pod",
description: "A system critical pod", priority: systemPriority,
expected: true, expected: true,
}, },
{ {
priority: int32(1000000000), name: "a non system critical pod",
description: "A non system critical pod", priority: scheduling.HighestUserDefinablePriority,
expected: false, expected: false,
}, },
} }
for _, test := range tests { for _, test := range tests {
actual := IsCriticalPodBasedOnPriority(test.priority) t.Run(test.name, func(t *testing.T) {
if actual != test.expected { actual := IsCriticalPodBasedOnPriority(test.priority)
t.Errorf("IsCriticalPodBased on priority should have returned %v for test %v but got %v", test.expected, test.description, actual) if actual != test.expected {
} t.Errorf("IsCriticalPodBased on priority should have returned %v for test %v but got %v", test.expected, test.name, actual)
}
})
} }
} }