github.com/kyma-project/kyma-environment-broker@v0.0.1/internal/btpmanager/credentials/utils_test.go (about)

     1  package btpmgrcreds
     2  
     3  import (
     4  	"fmt"
     5  	"sync"
     6  	"testing"
     7  	"time"
     8  
     9  	"github.com/stretchr/testify/assert"
    10  )
    11  
    12  type foo struct {
    13  	x, y int
    14  }
    15  
    16  type fakeService struct {
    17  	reachable bool
    18  	ticks     int
    19  }
    20  
    21  func (fs *fakeService) fakeCall1() (int, error) {
    22  	return 91, nil
    23  }
    24  
    25  func (fs *fakeService) fakeCall2() (foo, error) {
    26  	foo := foo{
    27  		x: 1,
    28  		y: 4,
    29  	}
    30  	return foo, nil
    31  }
    32  
    33  func (fs *fakeService) fakeCall3() (any, error) {
    34  	return nil, fmt.Errorf("expected error")
    35  }
    36  
    37  func (fs *fakeService) fakeCall4() (any, error) {
    38  	return nil, nil
    39  }
    40  
    41  func (fs *fakeService) fakeCall5() (foo, error) {
    42  	if fs.reachable {
    43  		return foo{x: -1, y: -1999}, nil
    44  	} else {
    45  		return foo{}, fmt.Errorf("expected error")
    46  	}
    47  }
    48  
    49  func TestCallWithRetry(t *testing.T) {
    50  	t.Run("call without any problems 1", func(t *testing.T) {
    51  		fakeService := &fakeService{}
    52  		result, err := CallWithRetry(func() (int, error) {
    53  			return fakeService.fakeCall1()
    54  		}, 1, time.Second*1)
    55  		assert.NoError(t, err)
    56  		assert.Equal(t, 91, result)
    57  	})
    58  
    59  	t.Run("call without any problems 2", func(t *testing.T) {
    60  		fakeService := &fakeService{}
    61  		result, err := CallWithRetry(func() (foo, error) {
    62  			return fakeService.fakeCall2()
    63  		}, 1, time.Second*1)
    64  		assert.NoError(t, err)
    65  		assert.Equal(t, foo{
    66  			x: 1,
    67  			y: 4,
    68  		}, result)
    69  	})
    70  
    71  	t.Run("call with error 1", func(t *testing.T) {
    72  		fakeService := &fakeService{}
    73  		result, err := CallWithRetry(func() (any, error) {
    74  			return fakeService.fakeCall3()
    75  		}, 1, time.Second*1)
    76  		assert.Error(t, err)
    77  		assert.Nil(t, result)
    78  	})
    79  
    80  	t.Run("call with error 2", func(t *testing.T) {
    81  		fakeService := &fakeService{}
    82  		result, err := CallWithRetry(func() (any, error) {
    83  			return fakeService.fakeCall3()
    84  		}, 1, time.Second*1)
    85  		assert.Error(t, err)
    86  		assert.Nil(t, result)
    87  	})
    88  
    89  	t.Run("call with no error and no response", func(t *testing.T) {
    90  		fakeService := &fakeService{}
    91  		result, err := CallWithRetry(func() (any, error) {
    92  			return fakeService.fakeCall4()
    93  		}, 1, time.Second*1)
    94  		assert.NoError(t, err)
    95  		assert.Nil(t, result)
    96  	})
    97  
    98  	t.Run("service become reachable after some time", func(t *testing.T) {
    99  		//Service will be not reachable for 10s.
   100  		//The retry will try to connect 5 times * 5 seconds = 25 seconds. 25 > 10 so Result should be returned without error
   101  		fakeService := &fakeService{ticks: 10}
   102  		var wg sync.WaitGroup
   103  		wg.Add(1)
   104  		go func() {
   105  			defer wg.Done()
   106  			for range time.Tick(time.Second * 1) {
   107  				fakeService.ticks--
   108  				if fakeService.ticks <= 0 {
   109  					fakeService.reachable = true
   110  					return
   111  				}
   112  			}
   113  		}()
   114  		result, err := CallWithRetry(func() (foo, error) {
   115  			return fakeService.fakeCall5()
   116  		}, 5, time.Second*5)
   117  		assert.NoError(t, err)
   118  		assert.NotNil(t, result)
   119  		assert.NotEmpty(t, result)
   120  		assert.Equal(t, result, foo{x: -1, y: -1999})
   121  		wg.Wait()
   122  	})
   123  
   124  	t.Run("service is not reachable for all time", func(t *testing.T) {
   125  		//Service will be not reachable for 10s.
   126  		//The retry will try to connect 2 times * 2 seconds = 4 seconds. 4 < 10 so Result should be returned with error
   127  		fakeService := &fakeService{ticks: 10}
   128  		var wg sync.WaitGroup
   129  		wg.Add(1)
   130  		go func() {
   131  			defer wg.Done()
   132  			for range time.Tick(time.Second * 1) {
   133  				fakeService.ticks--
   134  				if fakeService.ticks <= 0 {
   135  					fakeService.reachable = true
   136  					return
   137  				}
   138  			}
   139  		}()
   140  		result, err := CallWithRetry(func() (foo, error) {
   141  			return fakeService.fakeCall5()
   142  		}, 2, time.Second*2)
   143  		assert.Error(t, err)
   144  		assert.Empty(t, result)
   145  		wg.Wait()
   146  	})
   147  }