cli: Fix flaky init cancel test

There is a race between the MockSource and ShutdownCh which sometimes
causes this test to fail. Add a HangingSource implementation of Source
which hangs until the context is cancelled, so that there is always time
for a user-initiated shutdown to trigger the cancellation code path
under test.
This commit is contained in:
Alisdair McDiarmid 2021-10-18 16:54:31 -04:00
parent 7d3074df46
commit fb58f9e6d2
2 changed files with 35 additions and 8 deletions

View File

@ -1372,14 +1372,12 @@ func TestInit_cancel(t *testing.T) {
defer os.RemoveAll(td) defer os.RemoveAll(td)
defer testChdir(t, td)() defer testChdir(t, td)()
providerSource, closeSrc := newMockProviderSource(t, map[string][]string{ // Use a provider source implementation which is designed to hang indefinitely,
"test": {"1.2.3", "1.2.4"}, // to avoid a race between the closed shutdown channel and the provider source
"test-beta": {"1.2.4"}, // operations.
"source": {"1.2.2", "1.2.3", "1.2.1"}, providerSource := &getproviders.HangingSource{}
})
defer closeSrc()
// our shutdown channel is pre-closed so init will exit as soon as it // Our shutdown channel is pre-closed so init will exit as soon as it
// starts a cancelable portion of the process. // starts a cancelable portion of the process.
shutdownCh := make(chan struct{}) shutdownCh := make(chan struct{})
close(shutdownCh) close(shutdownCh)
@ -1401,7 +1399,7 @@ func TestInit_cancel(t *testing.T) {
args := []string{} args := []string{}
if code := c.Run(args); code == 0 { if code := c.Run(args); code == 0 {
t.Fatalf("succeeded; wanted error") t.Fatalf("succeeded; wanted error\n%s", ui.OutputWriter.String())
} }
// Currently the first operation that is cancelable is provider // Currently the first operation that is cancelable is provider
// installation, so our error message comes from there. If we // installation, so our error message comes from there. If we

View File

@ -0,0 +1,29 @@
package getproviders
import (
"context"
"github.com/hashicorp/terraform/internal/addrs"
)
// HangingSource is an implementation of Source which hangs until the given
// context is cancelled. This is useful only for unit tests of user-controlled
// cancels.
type HangingSource struct {
}
var _ Source = (*HangingSource)(nil)
func (s *HangingSource) AvailableVersions(ctx context.Context, provider addrs.Provider) (VersionList, Warnings, error) {
<-ctx.Done()
return nil, nil, nil
}
func (s *HangingSource) PackageMeta(ctx context.Context, provider addrs.Provider, version Version, target Platform) (PackageMeta, error) {
<-ctx.Done()
return PackageMeta{}, nil
}
func (s *HangingSource) ForDisplay(provider addrs.Provider) string {
return "hanging source"
}