...

Source file src/k8s.io/client-go/tools/cache/retry_with_deadline_test.go

Documentation: k8s.io/client-go/tools/cache

     1  /*
     2  Copyright 2022 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package cache
    18  
    19  import (
    20  	"fmt"
    21  	"testing"
    22  	"time"
    23  
    24  	apierrors "k8s.io/apimachinery/pkg/api/errors"
    25  	testingclock "k8s.io/utils/clock/testing"
    26  )
    27  
    28  type retryScenarioStep struct {
    29  	clockStep time.Duration
    30  	err       error
    31  	wantRetry bool
    32  }
    33  
    34  func TestRetryWithDeadline(t *testing.T) {
    35  	internalError := apierrors.NewInternalError(fmt.Errorf("etcdserver: no leader"))
    36  	otherError := fmt.Errorf("some other error")
    37  
    38  	testCases := []struct {
    39  		name        string
    40  		duration    time.Duration
    41  		reset       time.Duration
    42  		isRetryable func(error) bool
    43  		scenario    []retryScenarioStep
    44  	}{
    45  		{
    46  			name:        "Never retry when duration is zero",
    47  			duration:    time.Duration(0),
    48  			reset:       time.Second * 30,
    49  			isRetryable: func(err error) bool { return false },
    50  			scenario: []retryScenarioStep{
    51  				{
    52  					clockStep: time.Second * 1,
    53  					err:       nil,
    54  					wantRetry: false,
    55  				},
    56  				{
    57  					clockStep: time.Second * 0,
    58  					err:       internalError,
    59  					wantRetry: false,
    60  				},
    61  				{
    62  					clockStep: time.Second * 1,
    63  					err:       otherError,
    64  					wantRetry: false,
    65  				},
    66  			},
    67  		},
    68  		{
    69  			name:        "Retry when internal error happens only within duration",
    70  			duration:    time.Second * 1,
    71  			reset:       time.Second * 30,
    72  			isRetryable: apierrors.IsInternalError,
    73  			scenario: []retryScenarioStep{
    74  				{
    75  					clockStep: time.Second * 1,
    76  					err:       internalError,
    77  					wantRetry: true,
    78  				},
    79  				{
    80  					clockStep: time.Second * 1,
    81  					err:       internalError,
    82  					wantRetry: true,
    83  				},
    84  				{
    85  					clockStep: time.Second * 1,
    86  					err:       internalError,
    87  					wantRetry: false,
    88  				},
    89  			},
    90  		},
    91  		{
    92  			name:        "Don't retry when other error happens",
    93  			duration:    time.Second * 1,
    94  			reset:       time.Second * 30,
    95  			isRetryable: apierrors.IsInternalError,
    96  			scenario: []retryScenarioStep{
    97  				{
    98  					clockStep: time.Second * 1,
    99  					err:       otherError,
   100  					wantRetry: false,
   101  				},
   102  			},
   103  		},
   104  		{
   105  			name:        "Ignore other errors for retries",
   106  			duration:    time.Second * 1,
   107  			reset:       time.Second * 30,
   108  			isRetryable: apierrors.IsInternalError,
   109  			scenario: []retryScenarioStep{
   110  				{
   111  					clockStep: time.Second * 1,
   112  					err:       internalError,
   113  					wantRetry: true,
   114  				},
   115  				{
   116  					clockStep: time.Second * 0,
   117  					err:       otherError,
   118  					wantRetry: true,
   119  				},
   120  				{
   121  					clockStep: time.Second * 1,
   122  					err:       internalError,
   123  					wantRetry: true,
   124  				},
   125  			},
   126  		},
   127  	}
   128  
   129  	for _, tc := range testCases {
   130  		fakeClock := testingclock.NewFakeClock(time.Now())
   131  		retry := NewRetryWithDeadline(tc.duration, tc.reset, tc.isRetryable, fakeClock)
   132  
   133  		for i, step := range tc.scenario {
   134  			fakeClock.Step(step.clockStep)
   135  			retry.After(step.err)
   136  			result := retry.ShouldRetry()
   137  			if result != step.wantRetry {
   138  				t.Errorf("%v unexpected retry, step %d, result %v want %v", tc, i, result, step.wantRetry)
   139  				break
   140  			}
   141  		}
   142  	}
   143  }
   144  

View as plain text