github.com/kyma-incubator/compass/components/director@v0.0.0-20230623144113-d764f56ff805/internal/healthz/indicator_test.go (about) 1 package healthz_test 2 3 import ( 4 "context" 5 "errors" 6 "sync/atomic" 7 "testing" 8 "time" 9 10 "github.com/kyma-incubator/compass/components/director/internal/healthz/automock" 11 12 "github.com/kyma-incubator/compass/components/director/internal/healthz" 13 "github.com/stretchr/testify/require" 14 ) 15 16 func TestNewIndicator(t *testing.T) { 17 t.Run("should return not nil indicator", func(t *testing.T) { 18 // GIVEN 19 indicatorFunc := dummyIndicatorFunc(nil) 20 21 // WHEN 22 indicator := healthz.NewIndicator("test", indicatorFunc) 23 24 // THEN 25 require.NotNil(t, indicator) 26 require.Equal(t, "test", indicator.Name()) 27 require.NotNil(t, indicator.Status()) 28 require.NoError(t, indicator.Status().Error()) 29 require.Equal(t, "", indicator.Status().Details()) 30 }) 31 } 32 33 func TestRun(t *testing.T) { 34 t.Run("should return context timeout when timeout is reached", func(t *testing.T) { 35 // GIVEN 36 ctx, cancel := context.WithCancel(context.TODO()) 37 defer cancel() 38 39 indicatorFunc := timeOutIndicatorFunc() 40 cfg := healthz.IndicatorConfig{ 41 Name: "First", 42 Interval: time.Minute, 43 Timeout: time.Nanosecond, 44 InitialDelay: 0, 45 Threshold: 0, 46 } 47 48 // WHEN 49 indicator := healthz.NewIndicator("test", indicatorFunc) 50 indicator.Configure(cfg) 51 indicator.Run(ctx) 52 53 // THEN 54 require.Eventually(t, func() bool { 55 return indicator.Status().Error() != nil 56 }, time.Second, time.Second/2) 57 require.NotNil(t, indicator) 58 require.NotNil(t, indicator.Status()) 59 require.Error(t, indicator.Status().Error()) 60 require.Contains(t, indicator.Status().Error().Error(), "timeout") 61 require.Contains(t, indicator.Status().Details(), "timeout") 62 }) 63 t.Run("should call function on interval time", func(t *testing.T) { 64 // GIVEN 65 var counter uint64 66 67 ctx, cancel := context.WithCancel(context.TODO()) 68 defer cancel() 69 70 cfg := healthz.IndicatorConfig{ 71 Name: "First", 72 Interval: 10 * time.Millisecond, 73 Timeout: time.Second, 74 InitialDelay: 0, 75 Threshold: 0, 76 } 77 status := &automock.Status{} 78 status.On("Error").Return(nil) 79 80 // WHEN 81 indicator := healthz.NewIndicator("test", func(ctx context.Context) healthz.Status { 82 atomic.AddUint64(&counter, 1) 83 return status 84 }) 85 86 indicator.Configure(cfg) 87 indicator.Run(ctx) 88 89 // THEN 90 require.Eventually(t, func() bool { 91 return atomic.LoadUint64(&counter) >= 4 92 }, 50*time.Millisecond, 10*time.Millisecond) 93 require.NotNil(t, indicator) 94 }) 95 t.Run("should respect the threshold", func(t *testing.T) { 96 // GIVEN 97 ctx, cancel := context.WithCancel(context.TODO()) 98 defer cancel() 99 100 cfg := healthz.IndicatorConfig{ 101 Name: "First", 102 Interval: 10 * time.Millisecond, 103 Timeout: time.Second, 104 InitialDelay: 0, 105 Threshold: 3, 106 } 107 status := &automock.Status{} 108 status.On("Error").Return(errors.New("some error")) 109 status.On("Details").Return("some details") 110 // WHEN 111 indicator := healthz.NewIndicator("test", func(ctx context.Context) healthz.Status { 112 return status 113 }) 114 indicator.Configure(cfg) 115 indicator.Run(ctx) 116 117 // THEN 118 require.NotNil(t, indicator) 119 120 require.NoError(t, indicator.Status().Error()) 121 require.Eventually(t, func() bool { 122 return indicator.Status().Error() != nil 123 }, 50*time.Millisecond, 10*time.Millisecond) 124 }) 125 } 126 127 func dummyIndicatorFunc(status *automock.Status) func(ctx context.Context) healthz.Status { 128 return func(ctx context.Context) healthz.Status { 129 return status 130 } 131 } 132 133 func timeOutIndicatorFunc() func(ctx context.Context) healthz.Status { 134 status := &automock.Status{} 135 status.On("Error").Return(errors.New("timeout")).Times(6) 136 status.On("Details").Return("some timeout details").Times(2) 137 return func(ctx context.Context) healthz.Status { 138 select { 139 case <-ctx.Done(): 140 return status 141 case <-time.After(time.Second): 142 } 143 return nil 144 } 145 }