mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-04 04:08:16 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			513 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			513 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
/*
 | 
						|
Copyright 2023 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 job
 | 
						|
 | 
						|
import (
 | 
						|
	"testing"
 | 
						|
	"time"
 | 
						|
 | 
						|
	"github.com/google/go-cmp/cmp"
 | 
						|
	v1 "k8s.io/api/core/v1"
 | 
						|
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
						|
	"k8s.io/klog/v2/ktesting"
 | 
						|
	clocktesting "k8s.io/utils/clock/testing"
 | 
						|
	"k8s.io/utils/ptr"
 | 
						|
)
 | 
						|
 | 
						|
func TestNewBackoffRecord(t *testing.T) {
 | 
						|
	emptyStoreInitializer := func(*backoffStore) {}
 | 
						|
	defaultTestTime := metav1.NewTime(time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC))
 | 
						|
	testCases := map[string]struct {
 | 
						|
		storeInitializer  func(*backoffStore)
 | 
						|
		uncounted         uncountedTerminatedPods
 | 
						|
		newSucceededPods  []metav1.Time
 | 
						|
		newFailedPods     []metav1.Time
 | 
						|
		wantBackoffRecord backoffRecord
 | 
						|
	}{
 | 
						|
		"Empty backoff store and one new failure": {
 | 
						|
			storeInitializer: emptyStoreInitializer,
 | 
						|
			newSucceededPods: []metav1.Time{},
 | 
						|
			newFailedPods: []metav1.Time{
 | 
						|
				defaultTestTime,
 | 
						|
			},
 | 
						|
			wantBackoffRecord: backoffRecord{
 | 
						|
				key:                      "key",
 | 
						|
				lastFailureTime:          &defaultTestTime.Time,
 | 
						|
				failuresAfterLastSuccess: 1,
 | 
						|
			},
 | 
						|
		},
 | 
						|
		"Empty backoff store and two new failures": {
 | 
						|
			storeInitializer: emptyStoreInitializer,
 | 
						|
			newSucceededPods: []metav1.Time{},
 | 
						|
			newFailedPods: []metav1.Time{
 | 
						|
				defaultTestTime,
 | 
						|
				metav1.NewTime(defaultTestTime.Add(-1 * time.Millisecond)),
 | 
						|
			},
 | 
						|
			wantBackoffRecord: backoffRecord{
 | 
						|
				key:                      "key",
 | 
						|
				lastFailureTime:          &defaultTestTime.Time,
 | 
						|
				failuresAfterLastSuccess: 2,
 | 
						|
			},
 | 
						|
		},
 | 
						|
		"Empty backoff store, two failures followed by success": {
 | 
						|
			storeInitializer: emptyStoreInitializer,
 | 
						|
			newSucceededPods: []metav1.Time{
 | 
						|
				defaultTestTime,
 | 
						|
			},
 | 
						|
			newFailedPods: []metav1.Time{
 | 
						|
				metav1.NewTime(defaultTestTime.Add(-2 * time.Millisecond)),
 | 
						|
				metav1.NewTime(defaultTestTime.Add(-1 * time.Millisecond)),
 | 
						|
			},
 | 
						|
			wantBackoffRecord: backoffRecord{
 | 
						|
				key:                      "key",
 | 
						|
				failuresAfterLastSuccess: 0,
 | 
						|
			},
 | 
						|
		},
 | 
						|
		"Empty backoff store, two failures, one success and two more failures": {
 | 
						|
			storeInitializer: emptyStoreInitializer,
 | 
						|
			newSucceededPods: []metav1.Time{
 | 
						|
				metav1.NewTime(defaultTestTime.Add(-2 * time.Millisecond)),
 | 
						|
			},
 | 
						|
			newFailedPods: []metav1.Time{
 | 
						|
				defaultTestTime,
 | 
						|
				metav1.NewTime(defaultTestTime.Add(-4 * time.Millisecond)),
 | 
						|
				metav1.NewTime(defaultTestTime.Add(-3 * time.Millisecond)),
 | 
						|
				metav1.NewTime(defaultTestTime.Add(-1 * time.Millisecond)),
 | 
						|
			},
 | 
						|
			wantBackoffRecord: backoffRecord{
 | 
						|
				key:                      "key",
 | 
						|
				lastFailureTime:          &defaultTestTime.Time,
 | 
						|
				failuresAfterLastSuccess: 2,
 | 
						|
			},
 | 
						|
		},
 | 
						|
		"Backoff store having failure count 2 and one new failure": {
 | 
						|
			storeInitializer: func(bis *backoffStore) {
 | 
						|
				bis.updateBackoffRecord(backoffRecord{
 | 
						|
					key:                      "key",
 | 
						|
					failuresAfterLastSuccess: 2,
 | 
						|
					lastFailureTime:          nil,
 | 
						|
				})
 | 
						|
			},
 | 
						|
			newSucceededPods: []metav1.Time{},
 | 
						|
			newFailedPods: []metav1.Time{
 | 
						|
				defaultTestTime,
 | 
						|
			},
 | 
						|
			wantBackoffRecord: backoffRecord{
 | 
						|
				key:                      "key",
 | 
						|
				lastFailureTime:          &defaultTestTime.Time,
 | 
						|
				failuresAfterLastSuccess: 3,
 | 
						|
			},
 | 
						|
		},
 | 
						|
		"Empty backoff store with success and failure at same timestamp": {
 | 
						|
			storeInitializer: emptyStoreInitializer,
 | 
						|
			newSucceededPods: []metav1.Time{
 | 
						|
				defaultTestTime,
 | 
						|
			},
 | 
						|
			newFailedPods: []metav1.Time{
 | 
						|
				defaultTestTime,
 | 
						|
			},
 | 
						|
			wantBackoffRecord: backoffRecord{
 | 
						|
				key:                      "key",
 | 
						|
				failuresAfterLastSuccess: 0,
 | 
						|
			},
 | 
						|
		},
 | 
						|
		"Empty backoff store with no success/failure": {
 | 
						|
			storeInitializer: emptyStoreInitializer,
 | 
						|
			newSucceededPods: []metav1.Time{},
 | 
						|
			newFailedPods:    []metav1.Time{},
 | 
						|
			wantBackoffRecord: backoffRecord{
 | 
						|
				key:                      "key",
 | 
						|
				failuresAfterLastSuccess: 0,
 | 
						|
			},
 | 
						|
		},
 | 
						|
		"Empty backoff store with one success": {
 | 
						|
			storeInitializer: emptyStoreInitializer,
 | 
						|
			newSucceededPods: []metav1.Time{
 | 
						|
				defaultTestTime,
 | 
						|
			},
 | 
						|
			newFailedPods: []metav1.Time{},
 | 
						|
			wantBackoffRecord: backoffRecord{
 | 
						|
				key:                      "key",
 | 
						|
				failuresAfterLastSuccess: 0,
 | 
						|
			},
 | 
						|
		},
 | 
						|
	}
 | 
						|
 | 
						|
	for name, tc := range testCases {
 | 
						|
		t.Run(name, func(t *testing.T) {
 | 
						|
			backoffRecordStore := newBackoffStore()
 | 
						|
			tc.storeInitializer(backoffRecordStore)
 | 
						|
 | 
						|
			newSucceededPods := []*v1.Pod{}
 | 
						|
			newFailedPods := []*v1.Pod{}
 | 
						|
 | 
						|
			for _, finishTime := range tc.newSucceededPods {
 | 
						|
				newSucceededPods = append(newSucceededPods, &v1.Pod{
 | 
						|
					ObjectMeta: metav1.ObjectMeta{},
 | 
						|
					Status: v1.PodStatus{
 | 
						|
						Phase: v1.PodSucceeded,
 | 
						|
						ContainerStatuses: []v1.ContainerStatus{
 | 
						|
							{
 | 
						|
								State: v1.ContainerState{
 | 
						|
									Terminated: &v1.ContainerStateTerminated{
 | 
						|
										FinishedAt: finishTime,
 | 
						|
									},
 | 
						|
								},
 | 
						|
							},
 | 
						|
						},
 | 
						|
					},
 | 
						|
				})
 | 
						|
			}
 | 
						|
 | 
						|
			for _, finishTime := range tc.newFailedPods {
 | 
						|
				newFailedPods = append(newFailedPods, &v1.Pod{
 | 
						|
					ObjectMeta: metav1.ObjectMeta{},
 | 
						|
					Status: v1.PodStatus{
 | 
						|
						Phase: v1.PodFailed,
 | 
						|
						ContainerStatuses: []v1.ContainerStatus{
 | 
						|
							{
 | 
						|
								State: v1.ContainerState{
 | 
						|
									Terminated: &v1.ContainerStateTerminated{
 | 
						|
										FinishedAt: finishTime,
 | 
						|
									},
 | 
						|
								},
 | 
						|
							},
 | 
						|
						},
 | 
						|
					},
 | 
						|
				})
 | 
						|
			}
 | 
						|
 | 
						|
			backoffRecord := backoffRecordStore.newBackoffRecord("key", newSucceededPods, newFailedPods)
 | 
						|
			if diff := cmp.Diff(tc.wantBackoffRecord, backoffRecord, cmp.AllowUnexported(backoffRecord)); diff != "" {
 | 
						|
				t.Errorf("backoffRecord not matching; (-want,+got): %v", diff)
 | 
						|
			}
 | 
						|
		})
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func TestGetFinishedTime(t *testing.T) {
 | 
						|
	defaultTestTime := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)
 | 
						|
	defaultTestTimeMinus30s := defaultTestTime.Add(-30 * time.Second)
 | 
						|
	testCases := map[string]struct {
 | 
						|
		pod            v1.Pod
 | 
						|
		wantFinishTime time.Time
 | 
						|
	}{
 | 
						|
		"Pod with multiple containers and all containers terminated": {
 | 
						|
			pod: v1.Pod{
 | 
						|
				Status: v1.PodStatus{
 | 
						|
					ContainerStatuses: []v1.ContainerStatus{
 | 
						|
						{
 | 
						|
							State: v1.ContainerState{
 | 
						|
								Terminated: &v1.ContainerStateTerminated{FinishedAt: metav1.NewTime(defaultTestTime.Add(-1 * time.Second))},
 | 
						|
							},
 | 
						|
						},
 | 
						|
						{
 | 
						|
							State: v1.ContainerState{
 | 
						|
								Terminated: &v1.ContainerStateTerminated{FinishedAt: metav1.NewTime(defaultTestTime)},
 | 
						|
							},
 | 
						|
						},
 | 
						|
						{
 | 
						|
							State: v1.ContainerState{
 | 
						|
								Terminated: &v1.ContainerStateTerminated{FinishedAt: metav1.NewTime(defaultTestTime.Add(-2 * time.Second))},
 | 
						|
							},
 | 
						|
						},
 | 
						|
					},
 | 
						|
				},
 | 
						|
			},
 | 
						|
			wantFinishTime: defaultTestTime,
 | 
						|
		},
 | 
						|
		"Pod with multiple containers; two containers in terminated state and one in running state; fallback to deletionTimestamp": {
 | 
						|
			pod: v1.Pod{
 | 
						|
				Status: v1.PodStatus{
 | 
						|
					ContainerStatuses: []v1.ContainerStatus{
 | 
						|
						{
 | 
						|
							State: v1.ContainerState{
 | 
						|
								Terminated: &v1.ContainerStateTerminated{FinishedAt: metav1.NewTime(defaultTestTime.Add(-1 * time.Second))},
 | 
						|
							},
 | 
						|
						},
 | 
						|
						{
 | 
						|
							State: v1.ContainerState{
 | 
						|
								Running: &v1.ContainerStateRunning{},
 | 
						|
							},
 | 
						|
						},
 | 
						|
						{
 | 
						|
							State: v1.ContainerState{
 | 
						|
								Terminated: &v1.ContainerStateTerminated{FinishedAt: metav1.NewTime(defaultTestTime.Add(-2 * time.Second))},
 | 
						|
							},
 | 
						|
						},
 | 
						|
					},
 | 
						|
				},
 | 
						|
				ObjectMeta: metav1.ObjectMeta{
 | 
						|
					DeletionTimestamp: &metav1.Time{Time: defaultTestTime},
 | 
						|
				},
 | 
						|
			},
 | 
						|
			wantFinishTime: defaultTestTime,
 | 
						|
		},
 | 
						|
		"fallback to deletionTimestamp": {
 | 
						|
			pod: v1.Pod{
 | 
						|
				Status: v1.PodStatus{
 | 
						|
					ContainerStatuses: []v1.ContainerStatus{
 | 
						|
						{
 | 
						|
							State: v1.ContainerState{
 | 
						|
								Running: &v1.ContainerStateRunning{},
 | 
						|
							},
 | 
						|
						},
 | 
						|
					},
 | 
						|
				},
 | 
						|
				ObjectMeta: metav1.ObjectMeta{
 | 
						|
					DeletionTimestamp: &metav1.Time{Time: defaultTestTime},
 | 
						|
				},
 | 
						|
			},
 | 
						|
			wantFinishTime: defaultTestTime,
 | 
						|
		},
 | 
						|
		"fallback to deletionTimestamp, decremented by grace period": {
 | 
						|
			pod: v1.Pod{
 | 
						|
				Status: v1.PodStatus{
 | 
						|
					ContainerStatuses: []v1.ContainerStatus{
 | 
						|
						{
 | 
						|
							State: v1.ContainerState{
 | 
						|
								Running: &v1.ContainerStateRunning{},
 | 
						|
							},
 | 
						|
						},
 | 
						|
					},
 | 
						|
				},
 | 
						|
				ObjectMeta: metav1.ObjectMeta{
 | 
						|
					DeletionTimestamp:          &metav1.Time{Time: defaultTestTime},
 | 
						|
					DeletionGracePeriodSeconds: ptr.To[int64](30),
 | 
						|
				},
 | 
						|
			},
 | 
						|
			wantFinishTime: defaultTestTimeMinus30s,
 | 
						|
		},
 | 
						|
		"fallback to PodReady.LastTransitionTime when status of the condition is False": {
 | 
						|
			pod: v1.Pod{
 | 
						|
				Status: v1.PodStatus{
 | 
						|
					ContainerStatuses: []v1.ContainerStatus{
 | 
						|
						{
 | 
						|
							State: v1.ContainerState{
 | 
						|
								Terminated: &v1.ContainerStateTerminated{},
 | 
						|
							},
 | 
						|
						},
 | 
						|
					},
 | 
						|
					Conditions: []v1.PodCondition{
 | 
						|
						{
 | 
						|
							Type:               v1.PodReady,
 | 
						|
							Status:             v1.ConditionFalse,
 | 
						|
							Reason:             "PodFailed",
 | 
						|
							LastTransitionTime: metav1.Time{Time: defaultTestTime},
 | 
						|
						},
 | 
						|
					},
 | 
						|
				},
 | 
						|
			},
 | 
						|
			wantFinishTime: defaultTestTime,
 | 
						|
		},
 | 
						|
		"skip fallback to PodReady.LastTransitionTime when status of the condition is True": {
 | 
						|
			pod: v1.Pod{
 | 
						|
				Status: v1.PodStatus{
 | 
						|
					ContainerStatuses: []v1.ContainerStatus{
 | 
						|
						{
 | 
						|
							State: v1.ContainerState{
 | 
						|
								Terminated: &v1.ContainerStateTerminated{},
 | 
						|
							},
 | 
						|
						},
 | 
						|
					},
 | 
						|
					Conditions: []v1.PodCondition{
 | 
						|
						{
 | 
						|
							Type:               v1.PodReady,
 | 
						|
							Status:             v1.ConditionTrue,
 | 
						|
							LastTransitionTime: metav1.Time{Time: defaultTestTimeMinus30s},
 | 
						|
						},
 | 
						|
					},
 | 
						|
				},
 | 
						|
				ObjectMeta: metav1.ObjectMeta{
 | 
						|
					DeletionTimestamp: &metav1.Time{Time: defaultTestTime},
 | 
						|
				},
 | 
						|
			},
 | 
						|
			wantFinishTime: defaultTestTime,
 | 
						|
		},
 | 
						|
		"fallback to creationTimestamp": {
 | 
						|
			pod: v1.Pod{
 | 
						|
				Status: v1.PodStatus{
 | 
						|
					ContainerStatuses: []v1.ContainerStatus{
 | 
						|
						{
 | 
						|
							State: v1.ContainerState{
 | 
						|
								Terminated: &v1.ContainerStateTerminated{},
 | 
						|
							},
 | 
						|
						},
 | 
						|
					},
 | 
						|
				},
 | 
						|
				ObjectMeta: metav1.ObjectMeta{
 | 
						|
					CreationTimestamp: metav1.Time{Time: defaultTestTime},
 | 
						|
				},
 | 
						|
			},
 | 
						|
			wantFinishTime: defaultTestTime,
 | 
						|
		},
 | 
						|
	}
 | 
						|
 | 
						|
	for name, tc := range testCases {
 | 
						|
		t.Run(name, func(t *testing.T) {
 | 
						|
			f := getFinishedTime(&tc.pod)
 | 
						|
			if !f.Equal(tc.wantFinishTime) {
 | 
						|
				t.Errorf("Expected value of finishedTime %v; got %v", tc.wantFinishTime, f)
 | 
						|
			}
 | 
						|
		})
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func TestGetRemainingBackoffTime(t *testing.T) {
 | 
						|
	defaultTestTime := metav1.NewTime(time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC))
 | 
						|
	testCases := map[string]struct {
 | 
						|
		backoffRecord  backoffRecord
 | 
						|
		currentTime    time.Time
 | 
						|
		maxBackoff     time.Duration
 | 
						|
		defaultBackoff time.Duration
 | 
						|
		wantDuration   time.Duration
 | 
						|
	}{
 | 
						|
		"no failures": {
 | 
						|
			backoffRecord: backoffRecord{
 | 
						|
				lastFailureTime:          nil,
 | 
						|
				failuresAfterLastSuccess: 0,
 | 
						|
			},
 | 
						|
			defaultBackoff: 5 * time.Second,
 | 
						|
			maxBackoff:     700 * time.Second,
 | 
						|
			wantDuration:   0 * time.Second,
 | 
						|
		},
 | 
						|
		"one failure; current time and failure time are same": {
 | 
						|
			backoffRecord: backoffRecord{
 | 
						|
				lastFailureTime:          &defaultTestTime.Time,
 | 
						|
				failuresAfterLastSuccess: 1,
 | 
						|
			},
 | 
						|
			currentTime:    defaultTestTime.Time,
 | 
						|
			defaultBackoff: 5 * time.Second,
 | 
						|
			maxBackoff:     700 * time.Second,
 | 
						|
			wantDuration:   5 * time.Second,
 | 
						|
		},
 | 
						|
		"one failure; current time == 1 second + failure time": {
 | 
						|
			backoffRecord: backoffRecord{
 | 
						|
				lastFailureTime:          &defaultTestTime.Time,
 | 
						|
				failuresAfterLastSuccess: 1,
 | 
						|
			},
 | 
						|
			currentTime:    defaultTestTime.Time.Add(time.Second),
 | 
						|
			defaultBackoff: 5 * time.Second,
 | 
						|
			maxBackoff:     700 * time.Second,
 | 
						|
			wantDuration:   4 * time.Second,
 | 
						|
		},
 | 
						|
		"one failure; current time == expected backoff time": {
 | 
						|
			backoffRecord: backoffRecord{
 | 
						|
				lastFailureTime:          &defaultTestTime.Time,
 | 
						|
				failuresAfterLastSuccess: 1,
 | 
						|
			},
 | 
						|
			currentTime:    defaultTestTime.Time.Add(5 * time.Second),
 | 
						|
			defaultBackoff: 5 * time.Second,
 | 
						|
			maxBackoff:     700 * time.Second,
 | 
						|
			wantDuration:   0 * time.Second,
 | 
						|
		},
 | 
						|
		"one failure; current time == expected backoff time + 1 Second": {
 | 
						|
			backoffRecord: backoffRecord{
 | 
						|
				lastFailureTime:          &defaultTestTime.Time,
 | 
						|
				failuresAfterLastSuccess: 1,
 | 
						|
			},
 | 
						|
			currentTime:    defaultTestTime.Time.Add(6 * time.Second),
 | 
						|
			defaultBackoff: 5 * time.Second,
 | 
						|
			maxBackoff:     700 * time.Second,
 | 
						|
			wantDuration:   0 * time.Second,
 | 
						|
		},
 | 
						|
		"three failures; current time and failure time are same": {
 | 
						|
			backoffRecord: backoffRecord{
 | 
						|
				lastFailureTime:          &defaultTestTime.Time,
 | 
						|
				failuresAfterLastSuccess: 3,
 | 
						|
			},
 | 
						|
			currentTime:    defaultTestTime.Time,
 | 
						|
			defaultBackoff: 5 * time.Second,
 | 
						|
			maxBackoff:     700 * time.Second,
 | 
						|
			wantDuration:   20 * time.Second,
 | 
						|
		},
 | 
						|
		"eight failures; current time and failure time are same; backoff not exceeding maxBackoff": {
 | 
						|
			backoffRecord: backoffRecord{
 | 
						|
				lastFailureTime:          &defaultTestTime.Time,
 | 
						|
				failuresAfterLastSuccess: 8,
 | 
						|
			},
 | 
						|
			currentTime:    defaultTestTime.Time,
 | 
						|
			defaultBackoff: 5 * time.Second,
 | 
						|
			maxBackoff:     700 * time.Second,
 | 
						|
			wantDuration:   640 * time.Second,
 | 
						|
		},
 | 
						|
		"nine failures; current time and failure time are same; backoff exceeding maxBackoff": {
 | 
						|
			backoffRecord: backoffRecord{
 | 
						|
				lastFailureTime:          &defaultTestTime.Time,
 | 
						|
				failuresAfterLastSuccess: 9,
 | 
						|
			},
 | 
						|
			currentTime:    defaultTestTime.Time,
 | 
						|
			defaultBackoff: 5 * time.Second,
 | 
						|
			maxBackoff:     700 * time.Second,
 | 
						|
			wantDuration:   700 * time.Second,
 | 
						|
		},
 | 
						|
	}
 | 
						|
 | 
						|
	for name, tc := range testCases {
 | 
						|
		t.Run(name, func(t *testing.T) {
 | 
						|
			fakeClock := clocktesting.NewFakeClock(tc.currentTime.Truncate(time.Second))
 | 
						|
			d := tc.backoffRecord.getRemainingTime(fakeClock, tc.defaultBackoff, tc.maxBackoff)
 | 
						|
			if d.Seconds() != tc.wantDuration.Seconds() {
 | 
						|
				t.Errorf("Expected value of duration %v; got %v", tc.wantDuration, d)
 | 
						|
			}
 | 
						|
		})
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func TestGetRemainingBackoffTimePerIndex(t *testing.T) {
 | 
						|
	defaultTestTime := metav1.NewTime(time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC))
 | 
						|
	testCases := map[string]struct {
 | 
						|
		currentTime    time.Time
 | 
						|
		maxBackoff     time.Duration
 | 
						|
		defaultBackoff time.Duration
 | 
						|
		lastFailedPod  *v1.Pod
 | 
						|
		wantDuration   time.Duration
 | 
						|
	}{
 | 
						|
		"no failures": {
 | 
						|
			lastFailedPod:  nil,
 | 
						|
			defaultBackoff: 5 * time.Second,
 | 
						|
			maxBackoff:     700 * time.Second,
 | 
						|
			wantDuration:   0 * time.Second,
 | 
						|
		},
 | 
						|
		"two prev failures; current time and failure time are same": {
 | 
						|
			lastFailedPod:  buildPod().phase(v1.PodFailed).indexFailureCount("2").customDeletionTimestamp(defaultTestTime.Time).Pod,
 | 
						|
			currentTime:    defaultTestTime.Time,
 | 
						|
			defaultBackoff: 5 * time.Second,
 | 
						|
			maxBackoff:     700 * time.Second,
 | 
						|
			wantDuration:   20 * time.Second,
 | 
						|
		},
 | 
						|
		"one prev failure counted and one ignored; current time and failure time are same": {
 | 
						|
			lastFailedPod:  buildPod().phase(v1.PodFailed).indexFailureCount("1").indexIgnoredFailureCount("1").customDeletionTimestamp(defaultTestTime.Time).Pod,
 | 
						|
			currentTime:    defaultTestTime.Time,
 | 
						|
			defaultBackoff: 5 * time.Second,
 | 
						|
			maxBackoff:     700 * time.Second,
 | 
						|
			wantDuration:   20 * time.Second,
 | 
						|
		},
 | 
						|
	}
 | 
						|
 | 
						|
	for name, tc := range testCases {
 | 
						|
		t.Run(name, func(t *testing.T) {
 | 
						|
			logger, _ := ktesting.NewTestContext(t)
 | 
						|
			fakeClock := clocktesting.NewFakeClock(tc.currentTime.Truncate(time.Second))
 | 
						|
			d := getRemainingTimePerIndex(logger, fakeClock, tc.defaultBackoff, tc.maxBackoff, tc.lastFailedPod)
 | 
						|
			if d.Seconds() != tc.wantDuration.Seconds() {
 | 
						|
				t.Errorf("Expected value of duration %v; got %v", tc.wantDuration, d)
 | 
						|
			}
 | 
						|
		})
 | 
						|
	}
 | 
						|
}
 |