mirror of https://github.com/k3s-io/k3s
Merge pull request #63666 from xchapter7x/pkg-scheduler-factory
Automatic merge from submit-queue (batch tested with PRs 58487, 63666). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>. use subtest for table units (pkg/scheduler/factory) **What this PR does / why we need it**: Update scheduler's unit table tests to use subtest **Which issue(s) this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close the issue(s) when PR gets merged)*: **Special notes for your reviewer**: breaks up PR: https://github.com/kubernetes/kubernetes/pull/63281 /ref #63267 **Release note**: ```release-note This PR will leverage subtests on the existing table tests for the scheduler units. Some refactoring of error/status messages and functions to align with new approach. ```pull/8/head
commit
357decc9db
|
@ -27,27 +27,29 @@ import (
|
|||
)
|
||||
|
||||
func TestCompareNodes(t *testing.T) {
|
||||
compare := compareStrategy{}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
actual []string
|
||||
cached []string
|
||||
missing []string
|
||||
redundant []string
|
||||
}{
|
||||
{
|
||||
name: "redundant cached value",
|
||||
actual: []string{"foo", "bar"},
|
||||
cached: []string{"bar", "foo", "foobar"},
|
||||
missing: []string{},
|
||||
redundant: []string{"foobar"},
|
||||
},
|
||||
{
|
||||
name: "missing cached value",
|
||||
actual: []string{"foo", "bar", "foobar"},
|
||||
cached: []string{"bar", "foo"},
|
||||
missing: []string{"foobar"},
|
||||
redundant: []string{},
|
||||
},
|
||||
{
|
||||
name: "proper cache set",
|
||||
actual: []string{"foo", "bar", "foobar"},
|
||||
cached: []string{"bar", "foobar", "foo"},
|
||||
missing: []string{},
|
||||
|
@ -56,34 +58,40 @@ func TestCompareNodes(t *testing.T) {
|
|||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
testCompareNodes(test.actual, test.cached, test.missing, test.redundant, t)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func testCompareNodes(actual, cached, missing, redundant []string, t *testing.T) {
|
||||
compare := compareStrategy{}
|
||||
nodes := []*v1.Node{}
|
||||
for _, nodeName := range test.actual {
|
||||
for _, nodeName := range actual {
|
||||
node := &v1.Node{}
|
||||
node.Name = nodeName
|
||||
nodes = append(nodes, node)
|
||||
}
|
||||
|
||||
nodeInfo := make(map[string]*schedulercache.NodeInfo)
|
||||
for _, nodeName := range test.cached {
|
||||
for _, nodeName := range cached {
|
||||
nodeInfo[nodeName] = &schedulercache.NodeInfo{}
|
||||
}
|
||||
|
||||
m, r := compare.CompareNodes(nodes, nodeInfo)
|
||||
|
||||
if !reflect.DeepEqual(m, test.missing) {
|
||||
t.Errorf("missing expected to be %s; got %s", test.missing, m)
|
||||
if !reflect.DeepEqual(m, missing) {
|
||||
t.Errorf("missing expected to be %s; got %s", missing, m)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(r, test.redundant) {
|
||||
t.Errorf("redundant expected to be %s; got %s", test.redundant, r)
|
||||
}
|
||||
if !reflect.DeepEqual(r, redundant) {
|
||||
t.Errorf("redundant expected to be %s; got %s", redundant, r)
|
||||
}
|
||||
}
|
||||
|
||||
func TestComparePods(t *testing.T) {
|
||||
compare := compareStrategy{}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
actual []string
|
||||
cached []string
|
||||
queued []string
|
||||
|
@ -91,6 +99,7 @@ func TestComparePods(t *testing.T) {
|
|||
redundant []string
|
||||
}{
|
||||
{
|
||||
name: "redundant cached value",
|
||||
actual: []string{"foo", "bar"},
|
||||
cached: []string{"bar", "foo", "foobar"},
|
||||
queued: []string{},
|
||||
|
@ -98,6 +107,7 @@ func TestComparePods(t *testing.T) {
|
|||
redundant: []string{"foobar"},
|
||||
},
|
||||
{
|
||||
name: "redundant and queued values",
|
||||
actual: []string{"foo", "bar"},
|
||||
cached: []string{"foo", "foobar"},
|
||||
queued: []string{"bar"},
|
||||
|
@ -105,6 +115,7 @@ func TestComparePods(t *testing.T) {
|
|||
redundant: []string{"foobar"},
|
||||
},
|
||||
{
|
||||
name: "missing cached value",
|
||||
actual: []string{"foo", "bar", "foobar"},
|
||||
cached: []string{"bar", "foo"},
|
||||
queued: []string{},
|
||||
|
@ -112,6 +123,7 @@ func TestComparePods(t *testing.T) {
|
|||
redundant: []string{},
|
||||
},
|
||||
{
|
||||
name: "missing and queued values",
|
||||
actual: []string{"foo", "bar", "foobar"},
|
||||
cached: []string{"foo"},
|
||||
queued: []string{"bar"},
|
||||
|
@ -119,6 +131,7 @@ func TestComparePods(t *testing.T) {
|
|||
redundant: []string{},
|
||||
},
|
||||
{
|
||||
name: "correct cache set",
|
||||
actual: []string{"foo", "bar", "foobar"},
|
||||
cached: []string{"bar", "foobar", "foo"},
|
||||
queued: []string{},
|
||||
|
@ -126,6 +139,7 @@ func TestComparePods(t *testing.T) {
|
|||
redundant: []string{},
|
||||
},
|
||||
{
|
||||
name: "queued cache value",
|
||||
actual: []string{"foo", "bar", "foobar"},
|
||||
cached: []string{"foobar", "foo"},
|
||||
queued: []string{"bar"},
|
||||
|
@ -135,22 +149,30 @@ func TestComparePods(t *testing.T) {
|
|||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
testComparePods(test.actual, test.cached, test.queued, test.missing, test.redundant, t)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func testComparePods(actual, cached, queued, missing, redundant []string, t *testing.T) {
|
||||
compare := compareStrategy{}
|
||||
pods := []*v1.Pod{}
|
||||
for _, uid := range test.actual {
|
||||
for _, uid := range actual {
|
||||
pod := &v1.Pod{}
|
||||
pod.UID = types.UID(uid)
|
||||
pods = append(pods, pod)
|
||||
}
|
||||
|
||||
queuedPods := []*v1.Pod{}
|
||||
for _, uid := range test.queued {
|
||||
for _, uid := range queued {
|
||||
pod := &v1.Pod{}
|
||||
pod.UID = types.UID(uid)
|
||||
queuedPods = append(queuedPods, pod)
|
||||
}
|
||||
|
||||
nodeInfo := make(map[string]*schedulercache.NodeInfo)
|
||||
for _, uid := range test.cached {
|
||||
for _, uid := range cached {
|
||||
pod := &v1.Pod{}
|
||||
pod.UID = types.UID(uid)
|
||||
pod.Namespace = "ns"
|
||||
|
@ -161,38 +183,39 @@ func TestComparePods(t *testing.T) {
|
|||
|
||||
m, r := compare.ComparePods(pods, queuedPods, nodeInfo)
|
||||
|
||||
if !reflect.DeepEqual(m, test.missing) {
|
||||
t.Errorf("missing expected to be %s; got %s", test.missing, m)
|
||||
if !reflect.DeepEqual(m, missing) {
|
||||
t.Errorf("missing expected to be %s; got %s", missing, m)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(r, test.redundant) {
|
||||
t.Errorf("redundant expected to be %s; got %s", test.redundant, r)
|
||||
}
|
||||
if !reflect.DeepEqual(r, redundant) {
|
||||
t.Errorf("redundant expected to be %s; got %s", redundant, r)
|
||||
}
|
||||
}
|
||||
|
||||
func TestComparePdbs(t *testing.T) {
|
||||
compare := compareStrategy{}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
actual []string
|
||||
cached []string
|
||||
missing []string
|
||||
redundant []string
|
||||
}{
|
||||
{
|
||||
name: "redundant cache value",
|
||||
actual: []string{"foo", "bar"},
|
||||
cached: []string{"bar", "foo", "foobar"},
|
||||
missing: []string{},
|
||||
redundant: []string{"foobar"},
|
||||
},
|
||||
{
|
||||
name: "missing cache value",
|
||||
actual: []string{"foo", "bar", "foobar"},
|
||||
cached: []string{"bar", "foo"},
|
||||
missing: []string{"foobar"},
|
||||
redundant: []string{},
|
||||
},
|
||||
{
|
||||
name: "correct cache",
|
||||
actual: []string{"foo", "bar", "foobar"},
|
||||
cached: []string{"bar", "foobar", "foo"},
|
||||
missing: []string{},
|
||||
|
@ -201,15 +224,23 @@ func TestComparePdbs(t *testing.T) {
|
|||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
testComparePdbs(test.actual, test.cached, test.missing, test.redundant, t)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func testComparePdbs(actual, cached, missing, redundant []string, t *testing.T) {
|
||||
compare := compareStrategy{}
|
||||
pdbs := []*policy.PodDisruptionBudget{}
|
||||
for _, uid := range test.actual {
|
||||
for _, uid := range actual {
|
||||
pdb := &policy.PodDisruptionBudget{}
|
||||
pdb.UID = types.UID(uid)
|
||||
pdbs = append(pdbs, pdb)
|
||||
}
|
||||
|
||||
cache := make(map[string]*policy.PodDisruptionBudget)
|
||||
for _, uid := range test.cached {
|
||||
for _, uid := range cached {
|
||||
pdb := &policy.PodDisruptionBudget{}
|
||||
pdb.UID = types.UID(uid)
|
||||
cache[uid] = pdb
|
||||
|
@ -217,12 +248,11 @@ func TestComparePdbs(t *testing.T) {
|
|||
|
||||
m, r := compare.ComparePdbs(pdbs, cache)
|
||||
|
||||
if !reflect.DeepEqual(m, test.missing) {
|
||||
t.Errorf("missing expected to be %s; got %s", test.missing, m)
|
||||
if !reflect.DeepEqual(m, missing) {
|
||||
t.Errorf("missing expected to be %s; got %s", missing, m)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(r, test.redundant) {
|
||||
t.Errorf("redundant expected to be %s; got %s", test.redundant, r)
|
||||
}
|
||||
if !reflect.DeepEqual(r, redundant) {
|
||||
t.Errorf("redundant expected to be %s; got %s", redundant, r)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -331,6 +331,7 @@ func TestNodeEnumerator(t *testing.T) {
|
|||
t.Fatalf("expected %v, got %v", e, a)
|
||||
}
|
||||
for i := range testList.Items {
|
||||
t.Run(fmt.Sprintf("node enumerator/%v", i), func(t *testing.T) {
|
||||
gotObj := me.Get(i)
|
||||
if e, a := testList.Items[i].Name, gotObj.(*v1.Node).Name; e != a {
|
||||
t.Errorf("Expected %v, got %v", e, a)
|
||||
|
@ -338,14 +339,18 @@ func TestNodeEnumerator(t *testing.T) {
|
|||
if e, a := &testList.Items[i], gotObj; !reflect.DeepEqual(e, a) {
|
||||
t.Errorf("Expected %#v, got %v#", e, a)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestBind(t *testing.T) {
|
||||
table := []struct {
|
||||
name string
|
||||
binding *v1.Binding
|
||||
}{
|
||||
{binding: &v1.Binding{
|
||||
{
|
||||
name: "binding can bind and validate request",
|
||||
binding: &v1.Binding{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: metav1.NamespaceDefault,
|
||||
Name: "foo",
|
||||
|
@ -353,10 +358,18 @@ func TestBind(t *testing.T) {
|
|||
Target: v1.ObjectReference{
|
||||
Name: "foohost.kubernetes.mydomain.com",
|
||||
},
|
||||
}},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, item := range table {
|
||||
for _, test := range table {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
testBind(test.binding, t)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func testBind(binding *v1.Binding, t *testing.T) {
|
||||
handler := utiltesting.FakeHandler{
|
||||
StatusCode: 200,
|
||||
ResponseBody: "",
|
||||
|
@ -367,15 +380,14 @@ func TestBind(t *testing.T) {
|
|||
client := clientset.NewForConfigOrDie(&restclient.Config{Host: server.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}})
|
||||
b := binder{client}
|
||||
|
||||
if err := b.Bind(item.binding); err != nil {
|
||||
if err := b.Bind(binding); err != nil {
|
||||
t.Errorf("Unexpected error: %v", err)
|
||||
continue
|
||||
return
|
||||
}
|
||||
expectedBody := runtime.EncodeOrDie(schedulertesting.Test.Codec(), item.binding)
|
||||
expectedBody := runtime.EncodeOrDie(schedulertesting.Test.Codec(), binding)
|
||||
handler.ValidateRequest(t,
|
||||
schedulertesting.Test.SubResourcePath(string(v1.ResourcePods), metav1.NamespaceDefault, "foo", "binding"),
|
||||
"POST", &expectedBody)
|
||||
}
|
||||
}
|
||||
|
||||
func TestInvalidHardPodAffinitySymmetricWeight(t *testing.T) {
|
||||
|
@ -406,38 +418,44 @@ func TestInvalidFactoryArgs(t *testing.T) {
|
|||
client := clientset.NewForConfigOrDie(&restclient.Config{Host: server.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Group: "", Version: "v1"}}})
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
hardPodAffinitySymmetricWeight int32
|
||||
expectErr string
|
||||
}{
|
||||
{
|
||||
name: "symmetric weight below range",
|
||||
hardPodAffinitySymmetricWeight: -1,
|
||||
expectErr: "invalid hardPodAffinitySymmetricWeight: -1, must be in the range 0-100",
|
||||
},
|
||||
{
|
||||
name: "symmetric weight above range",
|
||||
hardPodAffinitySymmetricWeight: 101,
|
||||
expectErr: "invalid hardPodAffinitySymmetricWeight: 101, must be in the range 0-100",
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
factory := newConfigFactory(client, test.hardPodAffinitySymmetricWeight)
|
||||
_, err := factory.Create()
|
||||
if err == nil {
|
||||
t.Errorf("expected err: %s, got nothing", test.expectErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestSkipPodUpdate(t *testing.T) {
|
||||
for _, test := range []struct {
|
||||
table := []struct {
|
||||
pod *v1.Pod
|
||||
isAssumedPodFunc func(*v1.Pod) bool
|
||||
getPodFunc func(*v1.Pod) *v1.Pod
|
||||
expected bool
|
||||
name string
|
||||
}{
|
||||
// Non-assumed pod should not be skipped.
|
||||
{
|
||||
name: "Non-assumed pod",
|
||||
pod: &v1.Pod{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "pod-0",
|
||||
|
@ -453,9 +471,8 @@ func TestSkipPodUpdate(t *testing.T) {
|
|||
},
|
||||
expected: false,
|
||||
},
|
||||
// Pod update (with changes on ResourceVersion, Spec.NodeName and/or
|
||||
// Annotations) for an already assumed pod should be skipped.
|
||||
{
|
||||
name: "with changes on ResourceVersion, Spec.NodeName and/or Annotations",
|
||||
pod: &v1.Pod{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "pod-0",
|
||||
|
@ -483,9 +500,8 @@ func TestSkipPodUpdate(t *testing.T) {
|
|||
},
|
||||
expected: true,
|
||||
},
|
||||
// Pod update (with changes on Labels) for an already assumed pod
|
||||
// should not be skipped.
|
||||
{
|
||||
name: "with changes on Labels",
|
||||
pod: &v1.Pod{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "pod-0",
|
||||
|
@ -505,7 +521,9 @@ func TestSkipPodUpdate(t *testing.T) {
|
|||
},
|
||||
expected: false,
|
||||
},
|
||||
} {
|
||||
}
|
||||
for _, test := range table {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
c := &configFactory{
|
||||
schedulerCache: &schedulertesting.FakeCache{
|
||||
IsAssumedPodFunc: test.isAssumedPodFunc,
|
||||
|
@ -516,6 +534,7 @@ func TestSkipPodUpdate(t *testing.T) {
|
|||
if got != test.expected {
|
||||
t.Errorf("skipPodUpdate() = %t, expected = %t", got, test.expected)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -593,24 +612,22 @@ func (f *fakeExtender) IsInterested(pod *v1.Pod) bool {
|
|||
}
|
||||
|
||||
func TestGetBinderFunc(t *testing.T) {
|
||||
for _, test := range []struct {
|
||||
table := []struct {
|
||||
podName string
|
||||
extenders []algorithm.SchedulerExtender
|
||||
|
||||
expectedBinderType string
|
||||
name string
|
||||
}{
|
||||
// Expect to return the default binder because the extender is not a
|
||||
// binder, even though it's interested in the pod.
|
||||
{
|
||||
name: "the extender is not a binder",
|
||||
podName: "pod0",
|
||||
extenders: []algorithm.SchedulerExtender{
|
||||
&fakeExtender{isBinder: false, interestedPodName: "pod0"},
|
||||
},
|
||||
expectedBinderType: "*factory.binder",
|
||||
},
|
||||
// Expect to return the fake binder because one of the extenders is a
|
||||
// binder and it's interested in the pod.
|
||||
{
|
||||
name: "one of the extenders is a binder and interested in pod",
|
||||
podName: "pod0",
|
||||
extenders: []algorithm.SchedulerExtender{
|
||||
&fakeExtender{isBinder: false, interestedPodName: "pod0"},
|
||||
|
@ -618,9 +635,8 @@ func TestGetBinderFunc(t *testing.T) {
|
|||
},
|
||||
expectedBinderType: "*factory.fakeExtender",
|
||||
},
|
||||
// Expect to return the default binder because one of the extenders is
|
||||
// a binder but the binder is not interested in the pod.
|
||||
{
|
||||
name: "one of the extenders is a binder, but not interested in pod",
|
||||
podName: "pod1",
|
||||
extenders: []algorithm.SchedulerExtender{
|
||||
&fakeExtender{isBinder: false, interestedPodName: "pod1"},
|
||||
|
@ -628,20 +644,28 @@ func TestGetBinderFunc(t *testing.T) {
|
|||
},
|
||||
expectedBinderType: "*factory.binder",
|
||||
},
|
||||
} {
|
||||
}
|
||||
|
||||
for _, test := range table {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
testGetBinderFunc(test.expectedBinderType, test.podName, test.extenders, t)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func testGetBinderFunc(expectedBinderType, podName string, extenders []algorithm.SchedulerExtender, t *testing.T) {
|
||||
pod := &v1.Pod{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: test.podName,
|
||||
Name: podName,
|
||||
},
|
||||
}
|
||||
|
||||
f := &configFactory{}
|
||||
binderFunc := f.getBinderFunc(test.extenders)
|
||||
binderFunc := f.getBinderFunc(extenders)
|
||||
binder := binderFunc(pod)
|
||||
|
||||
binderType := fmt.Sprintf("%s", reflect.TypeOf(binder))
|
||||
if binderType != test.expectedBinderType {
|
||||
t.Errorf("Expected binder %q but got %q", test.expectedBinderType, binderType)
|
||||
}
|
||||
if binderType != expectedBinderType {
|
||||
t.Errorf("Expected binder %q but got %q", expectedBinderType, binderType)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,14 +36,18 @@ func TestAlgorithmNameValidation(t *testing.T) {
|
|||
"Some,Alg:orithm",
|
||||
}
|
||||
for _, name := range algorithmNamesShouldValidate {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
if !validName.MatchString(name) {
|
||||
t.Errorf("%v should be a valid algorithm name but is not valid.", name)
|
||||
t.Errorf("should be a valid algorithm name but is not valid.")
|
||||
}
|
||||
})
|
||||
}
|
||||
for _, name := range algorithmNamesShouldNotValidate {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
if validName.MatchString(name) {
|
||||
t.Errorf("%v should be an invalid algorithm name but is valid.", name)
|
||||
t.Errorf("should be an invalid algorithm name but is valid.")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -70,16 +74,18 @@ func TestValidatePriorityConfigOverFlow(t *testing.T) {
|
|||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
t.Run(test.description, func(t *testing.T) {
|
||||
err := validateSelectedConfigs(test.configs)
|
||||
if test.expected {
|
||||
if err == nil {
|
||||
t.Errorf("Expected Overflow for %s", test.description)
|
||||
t.Errorf("Expected Overflow")
|
||||
}
|
||||
} else {
|
||||
if err != nil {
|
||||
t.Errorf("Did not expect an overflow for %s", test.description)
|
||||
t.Errorf("Did not expect an overflow")
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue