func TestActivePodFiltering(t *testing.T) { logger, _ := ktesting.NewTestContext(t) <del> // This rc is not needed by the test, only the newPodList to give the pods labels/a namespace. rc := newReplicationController(0) podList := newPodList(nil, 5, v1.PodRunning, rc) podList.Items[0].Status.Phase = v1.PodSucceeded podList.Items[1].Status.Phase = v1.PodFailed expectedNames := sets.NewString() for _, pod := range podList.Items[2:] { expectedNames.Insert(pod.Name) </del> <ins> type podData struct { podName  string podPhase v1.PodPhase </ins> } <del> var podPointers []*v1.Pod for i := range podList.Items { podPointers = append(podPointers, &podList.Items[i]) </del> <ins> type test struct { name         string pods         []podData wantPodNames []string </ins> } <del> got := FilterActivePods(logger, podPointers) gotNames := sets.NewString() for _, pod := range got { gotNames.Insert(pod.Name) </del> <ins> tests := []test{ { name: "Filters active pods", pods: []podData{ {podName: "pod-1", podPhase: v1.PodSucceeded}, {podName: "pod-2", podPhase: v1.PodFailed}, {podName: "pod-3"}, {podName: "pod-4"}, {podName: "pod-5"}, }, wantPodNames: []string{"pod-3", "pod-4", "pod-5"}, }, </ins> } <del> if diff := cmp.Diff(expectedNames.List(), gotNames.List()); diff != "" { t.Errorf("Active pod names (-want,+got):n%s", diff) </del> <ins> for _, test := range tests { t.Run(test.name, func(t *testing.T) { // This rc is not needed by the test, only the newPodList to give the pods labels/a namespace. rc := newReplicationController(0) podList := newPodList(nil, 5, v1.PodRunning, rc) for idx, testPod := range test.pods { podList.Items[idx].Name = testPod.podName podList.Items[idx].Status.Phase = testPod.podPhase } var podPointers []*v1.Pod for i := range podList.Items { podPointers = append(podPointers, &podList.Items[i]) } got := FilterActivePods(logger, podPointers) gotNames := sets.NewString() for _, pod := range got { gotNames.Insert(pod.Name) } if diff := cmp.Diff(test.wantPodNames, gotNames.List()); diff != "" { t.Errorf("Active pod names (-want,+got):n%s", diff) } }) </ins> } } func TestSortingActivePods(t *testing.T) { <del> numPods := 9 // This rc is not needed by the test, only the newPodList to give the pods labels/a namespace. rc := newReplicationController(0) podList := newPodList(nil, numPods, v1.PodRunning, rc) pods := make([]*v1.Pod, len(podList.Items)) for i := range podList.Items { pods[i] = &podList.Items[i] } // pods[0] is not scheduled yet. pods[0].Spec.NodeName = "" pods[0].Status.Phase = v1.PodPending // pods[1] is scheduled but pending. pods[1].Spec.NodeName = "bar" pods[1].Status.Phase = v1.PodPending // pods[2] is unknown. pods[2].Spec.NodeName = "foo" pods[2].Status.Phase = v1.PodUnknown // pods[3] is running but not ready. pods[3].Spec.NodeName = "foo" pods[3].Status.Phase = v1.PodRunning // pods[4] is running and ready but without LastTransitionTime. </del> now := metav1.Now() <del> pods[4].Spec.NodeName = "foo" pods[4].Status.Phase = v1.PodRunning pods[4].Status.Conditions = []v1.PodCondition{{Type: v1.PodReady, Status: v1.ConditionTrue}} pods[4].Status.ContainerStatuses = []v1.ContainerStatus{{RestartCount: 3}, {RestartCount: 0}} // pods[5] is running and ready and with LastTransitionTime. pods[5].Spec.NodeName = "foo" pods[5].Status.Phase = v1.PodRunning pods[5].Status.Conditions = []v1.PodCondition{{Type: v1.PodReady, Status: v1.ConditionTrue, LastTransitionTime: now}} pods[5].Status.ContainerStatuses = []v1.ContainerStatus{{RestartCount: 3}, {RestartCount: 0}} // pods[6] is running ready for a longer time than pods[5]. </del> then := metav1.Time{Time: now.AddDate(0, -1, 0)} <del> pods[6].Spec.NodeName = "foo" pods[6].Status.Phase = v1.PodRunning pods[6].Status.Conditions = []v1.PodCondition{{Type: v1.PodReady, Status: v1.ConditionTrue, LastTransitionTime: then}} pods[6].Status.ContainerStatuses = []v1.ContainerStatus{{RestartCount: 3}, {RestartCount: 0}} // pods[7] has lower container restart count than pods[6]. pods[7].Spec.NodeName = "foo" pods[7].Status.Phase = v1.PodRunning pods[7].Status.Conditions = []v1.PodCondition{{Type: v1.PodReady, Status: v1.ConditionTrue, LastTransitionTime: then}} pods[7].Status.ContainerStatuses = []v1.ContainerStatus{{RestartCount: 2}, {RestartCount: 1}} pods[7].CreationTimestamp = now // pods[8] is older than pods[7]. pods[8].Spec.NodeName = "foo" pods[8].Status.Phase = v1.PodRunning pods[8].Status.Conditions = []v1.PodCondition{{Type: v1.PodReady, Status: v1.ConditionTrue, LastTransitionTime: then}} pods[8].Status.ContainerStatuses = []v1.ContainerStatus{{RestartCount: 2}, {RestartCount: 1}} pods[8].CreationTimestamp = then getOrder := func(pods []*v1.Pod) []string { names := make([]string, len(pods)) for i := range pods { names[i] = pods[i].Name } return names </del> <ins> tests := []struct { name      string pods      []v1.Pod wantOrder []string }{ { name: "Sorts by active pod", pods: []v1.Pod{ { ObjectMeta: metav1.ObjectMeta{Name: "unscheduled"}, Spec:       v1.PodSpec{NodeName: ""}, Status:     v1.PodStatus{Phase: v1.PodPending}, }, { ObjectMeta: metav1.ObjectMeta{Name: "scheduledButPending"}, Spec:       v1.PodSpec{NodeName: "bar"}, Status:     v1.PodStatus{Phase: v1.PodPending}, }, { ObjectMeta: metav1.ObjectMeta{Name: "unknownPhase"}, Spec:       v1.PodSpec{NodeName: "foo"}, Status:     v1.PodStatus{Phase: v1.PodUnknown}, }, { ObjectMeta: metav1.ObjectMeta{Name: "runningButNotReady"}, Spec:       v1.PodSpec{NodeName: "foo"}, Status:     v1.PodStatus{Phase: v1.PodRunning}, }, { ObjectMeta: metav1.ObjectMeta{Name: "runningNoLastTransitionTime"}, Spec:       v1.PodSpec{NodeName: "foo"}, Status: v1.PodStatus{ Phase:             v1.PodRunning, Conditions:        []v1.PodCondition{{Type: v1.PodReady, Status: v1.ConditionTrue}}, ContainerStatuses: []v1.ContainerStatus{{RestartCount: 3}, {RestartCount: 0}}, }, }, { ObjectMeta: metav1.ObjectMeta{Name: "runningWithLastTransitionTime"}, Spec:       v1.PodSpec{NodeName: "foo"}, Status: v1.PodStatus{ Phase:             v1.PodRunning, Conditions:        []v1.PodCondition{{Type: v1.PodReady, Status: v1.ConditionTrue, LastTransitionTime: now}}, ContainerStatuses: []v1.ContainerStatus{{RestartCount: 3}, {RestartCount: 0}}, }, }, { ObjectMeta: metav1.ObjectMeta{Name: "runningLongerTime"}, Spec:       v1.PodSpec{NodeName: "foo"}, Status: v1.PodStatus{ Phase:             v1.PodRunning, Conditions:        []v1.PodCondition{{Type: v1.PodReady, Status: v1.ConditionTrue, LastTransitionTime: then}}, ContainerStatuses: []v1.ContainerStatus{{RestartCount: 3}, {RestartCount: 0}}, }, }, { ObjectMeta: metav1.ObjectMeta{Name: "lowerContainerRestartCount", CreationTimestamp: now}, Spec:       v1.PodSpec{NodeName: "foo"}, Status: v1.PodStatus{ Phase:             v1.PodRunning, Conditions:        []v1.PodCondition{{Type: v1.PodReady, Status: v1.ConditionTrue, LastTransitionTime: then}}, ContainerStatuses: []v1.ContainerStatus{{RestartCount: 2}, {RestartCount: 1}}, }, }, { ObjectMeta: metav1.ObjectMeta{Name: "oldest", CreationTimestamp: then}, Spec:       v1.PodSpec{NodeName: "foo"}, Status: v1.PodStatus{ Phase:             v1.PodRunning, Conditions:        []v1.PodCondition{{Type: v1.PodReady, Status: v1.ConditionTrue, LastTransitionTime: then}}, ContainerStatuses: []v1.ContainerStatus{{RestartCount: 2}, {RestartCount: 1}}, }, }, }, wantOrder: []string{ "unscheduled", "scheduledButPending", "unknownPhase", "runningButNotReady", "runningNoLastTransitionTime", "runningWithLastTransitionTime", "runningLongerTime", "lowerContainerRestartCount", "oldest", }, }, </ins> } <del> expected := getOrder(pods) </del> <ins> for _, test := range tests { t.Run(test.name, func(t *testing.T) { numPods := len(test.pods) </ins> <del> for i := 0; i < 20; i++ { idx := rand.Perm(numPods) randomizedPods := make([]*v1.Pod, numPods) for j := 0; j < numPods; j++ { randomizedPods[j] = pods[idx[j]] } sort.Sort(ActivePods(randomizedPods)) actual := getOrder(randomizedPods) </del> <ins> for i := 0; i < 20; i++ { idx := rand.Perm(numPods) randomizedPods := make([]*v1.Pod, numPods) for j := 0; j < numPods; j++ { randomizedPods[j] = &test.pods[idx[j]] } </ins> <del> assert.EqualValues(t, expected, actual, "expected %v, got %v", expected, actual) </del> <ins> sort.Sort(ActivePods(randomizedPods)) gotOrder := make([]string, len(randomizedPods)) for i := range randomizedPods { gotOrder[i] = randomizedPods[i].Name } if diff := cmp.Diff(test.wantOrder, gotOrder); diff != "" { t.Errorf("Sorted active pod names (-want,+got):n%s", diff) } } }) </ins> } }