mirror of
https://github.com/rancher/steve.git
synced 2025-09-09 03:09:50 +00:00
Attempting to fix flaky tests
Some tests which relied on timeouts were a bit flaky in CI. This PR refactors a few of them to work on a more reliable method of receiving from a channel and raises the timeout of another test.
This commit is contained in:
@@ -2,7 +2,7 @@ package definitions
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync/atomic"
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -14,22 +14,27 @@ import (
|
||||
)
|
||||
|
||||
type refreshable struct {
|
||||
wasRefreshed atomic.Bool
|
||||
refreshChannel chan struct{}
|
||||
}
|
||||
|
||||
func (r *refreshable) Refresh() error {
|
||||
r.wasRefreshed.Store(true)
|
||||
r.refreshChannel <- struct{}{}
|
||||
return nil
|
||||
}
|
||||
|
||||
func Test_onChangeCRD(t *testing.T) {
|
||||
internalRefresh := refreshable{}
|
||||
t.Parallel()
|
||||
refreshChannel := make(chan struct{}, 1)
|
||||
defer close(refreshChannel)
|
||||
internalRefresh := refreshable{
|
||||
refreshChannel: refreshChannel,
|
||||
}
|
||||
refresher := debounce.DebounceableRefresher{
|
||||
Refreshable: &internalRefresh,
|
||||
}
|
||||
refreshHandler := refreshHandler{
|
||||
debounceRef: &refresher,
|
||||
debounceDuration: time.Microsecond * 5,
|
||||
debounceDuration: time.Microsecond * 2,
|
||||
}
|
||||
input := apiextv1.CustomResourceDefinition{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
@@ -39,19 +44,23 @@ func Test_onChangeCRD(t *testing.T) {
|
||||
output, err := refreshHandler.onChangeCRD("test-crd", &input)
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, input, *output)
|
||||
// waiting to allow the debouncer to refresh the refreshable
|
||||
time.Sleep(time.Millisecond * 2)
|
||||
require.True(t, internalRefresh.wasRefreshed.Load())
|
||||
err = receiveWithTimeout(refreshChannel, time.Second*5)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func Test_onChangeAPIService(t *testing.T) {
|
||||
internalRefresh := refreshable{}
|
||||
t.Parallel()
|
||||
refreshChannel := make(chan struct{}, 1)
|
||||
defer close(refreshChannel)
|
||||
internalRefresh := refreshable{
|
||||
refreshChannel: refreshChannel,
|
||||
}
|
||||
refresher := debounce.DebounceableRefresher{
|
||||
Refreshable: &internalRefresh,
|
||||
}
|
||||
refreshHandler := refreshHandler{
|
||||
debounceRef: &refresher,
|
||||
debounceDuration: time.Microsecond * 5,
|
||||
debounceDuration: time.Microsecond * 2,
|
||||
}
|
||||
input := apiregv1.APIService{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
@@ -61,24 +70,44 @@ func Test_onChangeAPIService(t *testing.T) {
|
||||
output, err := refreshHandler.onChangeAPIService("test-apiservice", &input)
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, input, *output)
|
||||
// waiting to allow the debouncer to refresh the refreshable
|
||||
time.Sleep(time.Millisecond * 2)
|
||||
require.True(t, internalRefresh.wasRefreshed.Load())
|
||||
err = receiveWithTimeout(refreshChannel, time.Second*5)
|
||||
require.NoError(t, err)
|
||||
|
||||
}
|
||||
|
||||
func Test_startBackgroundRefresh(t *testing.T) {
|
||||
internalRefresh := refreshable{}
|
||||
t.Parallel()
|
||||
refreshChannel := make(chan struct{}, 1)
|
||||
internalRefresh := refreshable{
|
||||
refreshChannel: refreshChannel,
|
||||
}
|
||||
refresher := debounce.DebounceableRefresher{
|
||||
Refreshable: &internalRefresh,
|
||||
}
|
||||
refreshHandler := refreshHandler{
|
||||
debounceRef: &refresher,
|
||||
debounceDuration: time.Microsecond * 5,
|
||||
debounceDuration: time.Microsecond * 2,
|
||||
}
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
refreshHandler.startBackgroundRefresh(ctx, time.Microsecond*10)
|
||||
time.Sleep(time.Millisecond * 2)
|
||||
require.True(t, internalRefresh.wasRefreshed.Load())
|
||||
refreshHandler.startBackgroundRefresh(ctx, time.Microsecond*2)
|
||||
|
||||
err := receiveWithTimeout(refreshChannel, time.Second*5)
|
||||
require.NoError(t, err)
|
||||
// we want to stop the refresher before closing the channel to avoid errors
|
||||
// since this just stops the background refresh from asking for a new refresh, we still
|
||||
// need to wait for any currently debounced refreshes to finish
|
||||
cancel()
|
||||
time.Sleep(time.Second * 1)
|
||||
close(refreshChannel)
|
||||
}
|
||||
|
||||
func receiveWithTimeout(channel chan struct{}, timeout time.Duration) error {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), timeout)
|
||||
defer cancel()
|
||||
select {
|
||||
case <-channel:
|
||||
return nil
|
||||
case <-ctx.Done():
|
||||
return fmt.Errorf("channel did not recieve value in timeout %d", timeout)
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user