sigs.k8s.io/cluster-api-provider-aws@v1.5.5/pkg/cloud/services/wait/wait_test.go (about)

     1  /*
     2  Copyright 2019 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 wait_test
    18  
    19  import (
    20  	"errors"
    21  	"testing"
    22  	"time"
    23  
    24  	"github.com/aws/aws-sdk-go/aws/awserr"
    25  	"k8s.io/apimachinery/pkg/util/wait"
    26  
    27  	. "sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/services/wait"
    28  )
    29  
    30  var (
    31  	errRetryable        = awserr.New("retryable error", "", nil)
    32  	errNonRetryable     = errors.New("non retryable error")
    33  	retryableErrorCodes = []string{"retryable error"}
    34  )
    35  
    36  func TestWaitForWithRetryable(t *testing.T) {
    37  	backoff := wait.Backoff{
    38  		Duration: 1 * time.Millisecond,
    39  		Factor:   0,
    40  		Jitter:   0,
    41  		Steps:    2,
    42  		Cap:      3 * time.Millisecond,
    43  	}
    44  	var firstIteration bool
    45  
    46  	tests := []struct {
    47  		name            string
    48  		backoff         wait.Backoff
    49  		condition       wait.ConditionFunc
    50  		retryableErrors []string
    51  		expectedError   error
    52  	}{
    53  		{
    54  			name:    "return nil",
    55  			backoff: backoff,
    56  			condition: func() (done bool, err error) {
    57  				return true, nil
    58  			},
    59  			retryableErrors: retryableErrorCodes,
    60  			expectedError:   nil,
    61  		},
    62  		{
    63  			name:    "returns timeout error",
    64  			backoff: backoff,
    65  			condition: func() (done bool, err error) {
    66  				return false, nil
    67  			},
    68  			retryableErrors: retryableErrorCodes,
    69  			expectedError:   wait.ErrWaitTimeout,
    70  		},
    71  		{
    72  			name:    "error occurred in conditionFunc, returns actual error",
    73  			backoff: backoff,
    74  			condition: func() (done bool, err error) {
    75  				return false, errNonRetryable
    76  			},
    77  			retryableErrors: retryableErrorCodes,
    78  			expectedError:   errNonRetryable,
    79  		},
    80  		{
    81  			name:    "timed out in retryable error, returns the retryable error",
    82  			backoff: backoff,
    83  			condition: func() (done bool, err error) {
    84  				return false, errRetryable
    85  			},
    86  			retryableErrors: retryableErrorCodes,
    87  			expectedError:   errRetryable,
    88  		},
    89  		{
    90  			name:    "retryable err at first, non-retryable err after that, returns latest error",
    91  			backoff: backoff,
    92  			condition: func() (done bool, err error) {
    93  				if firstIteration {
    94  					firstIteration = false
    95  					return false, errRetryable
    96  				}
    97  				firstIteration = false
    98  				return false, errNonRetryable
    99  			},
   100  			retryableErrors: retryableErrorCodes,
   101  			expectedError:   errNonRetryable,
   102  		},
   103  		{
   104  			name:    "retryable err at first, failure but no error after that, returns timeout error",
   105  			backoff: backoff,
   106  			condition: func() (done bool, err error) {
   107  				if firstIteration {
   108  					firstIteration = false
   109  					return false, errRetryable
   110  				}
   111  				return false, nil
   112  			},
   113  			retryableErrors: retryableErrorCodes,
   114  			expectedError:   wait.ErrWaitTimeout,
   115  		},
   116  		{
   117  			name:    "retryable error at first, success after that, returns nil",
   118  			backoff: backoff,
   119  			condition: func() (done bool, err error) {
   120  				if firstIteration {
   121  					firstIteration = false
   122  					return false, errRetryable
   123  				}
   124  				return true, nil
   125  			},
   126  			retryableErrors: retryableErrorCodes,
   127  			expectedError:   nil,
   128  		},
   129  	}
   130  	for _, tt := range tests {
   131  		t.Run(tt.name, func(t *testing.T) {
   132  			firstIteration = true
   133  
   134  			err := WaitForWithRetryable(tt.backoff, tt.condition, tt.retryableErrors...)
   135  
   136  			var expected, actual string
   137  			if err != nil {
   138  				actual = err.Error()
   139  			}
   140  			if tt.expectedError != nil {
   141  				expected = tt.expectedError.Error()
   142  			}
   143  
   144  			if expected != actual {
   145  				t.Errorf("expected error: %v, got error: %v", expected, actual)
   146  			}
   147  		})
   148  	}
   149  }