Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions wait/all.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package wait
import (
"context"
"errors"
"reflect"
"time"
)

Expand Down Expand Up @@ -62,6 +63,13 @@ func (ms *MultiStrategy) WaitUntilReady(ctx context.Context, target StrategyTarg
}

for _, strategy := range ms.Strategies {
if strategy == nil || reflect.ValueOf(strategy).IsNil() {
// A module could be appending strategies after part of the container initialization,
// and use wait.ForAll on a not initialized strategy.
// In this case, we just skip the nil strategy.
continue
}

strategyCtx := ctx

// Set default Timeout when strategy implements StrategyTimeout
Expand Down
54 changes: 54 additions & 0 deletions wait/all_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,3 +124,57 @@ func TestMultiStrategy_WaitUntilReady(t *testing.T) {
})
}
}

func TestMultiStrategy_handleNils(t *testing.T) {
Comment thread
mdelapenya marked this conversation as resolved.
t.Run("nil-strategy", func(t *testing.T) {
strategy := ForAll(nil)
err := strategy.WaitUntilReady(context.Background(), NopStrategyTarget{})
require.NoError(t, err)
})

t.Run("nil-strategy-in-the-middle", func(t *testing.T) {
strategy := ForAll(nil, ForLog("docker"))
err := strategy.WaitUntilReady(context.Background(), NopStrategyTarget{
ReaderCloser: io.NopCloser(bytes.NewReader([]byte("docker"))),
})
require.NoError(t, err)
})

t.Run("nil-strategy-last", func(t *testing.T) {
strategy := ForAll(ForLog("docker"), nil)
err := strategy.WaitUntilReady(context.Background(), NopStrategyTarget{
ReaderCloser: io.NopCloser(bytes.NewReader([]byte("docker"))),
})
require.NoError(t, err)
})

t.Run("nil-type-implements-strategy", func(t *testing.T) {
var nilStrategy Strategy

strategy := ForAll(ForLog("docker"), nilStrategy)
err := strategy.WaitUntilReady(context.Background(), NopStrategyTarget{
ReaderCloser: io.NopCloser(bytes.NewReader([]byte("docker"))),
})
require.NoError(t, err)
})

t.Run("nil-concrete-value-implements-strategy", func(t *testing.T) {
// Create a nil pointer to a type that implements Strategy
var nilPointerStrategy *nilWaitStrategy
// When we assign it to the interface, the type information is preserved
// but the concrete value is nil
var strategyInterface Strategy = nilPointerStrategy

strategy := ForAll(ForLog("docker"), strategyInterface)
err := strategy.WaitUntilReady(context.Background(), NopStrategyTarget{
ReaderCloser: io.NopCloser(bytes.NewReader([]byte("docker"))),
})
require.NoError(t, err)
})
}

type nilWaitStrategy struct{}

func (s *nilWaitStrategy) WaitUntilReady(_ context.Context, _ StrategyTarget) error {
return nil
}