From eee57280f6fed190206182f53685c0d50c819d1a Mon Sep 17 00:00:00 2001 From: Alisdair McDiarmid Date: Wed, 18 Nov 2020 15:35:48 -0500 Subject: [PATCH] backend: Faster remote backend tests The remote backend tests spent most of their execution time sleeping in various polling and backoff waits. This is unnecessary when testing against a mock server, so reduce all of these delays when under test to much lower values. Only one remaining test has an artificial delay: verifying the discovery of services against an unknown hostname. This times out at DNS resolution, which is more difficult to fix than seems worth it at this time. --- backend/remote/backend_apply_test.go | 14 +++++++------- backend/remote/backend_common.go | 13 ++++++++++--- backend/remote/backend_mock.go | 2 +- backend/remote/backend_plan.go | 4 +++- backend/remote/backend_plan_test.go | 6 +++--- backend/remote/remote_test.go | 7 +++++++ 6 files changed, 31 insertions(+), 15 deletions(-) diff --git a/backend/remote/backend_apply_test.go b/backend/remote/backend_apply_test.go index 7fe5c1c0c..1e0107416 100644 --- a/backend/remote/backend_apply_test.go +++ b/backend/remote/backend_apply_test.go @@ -542,8 +542,8 @@ func TestRemote_applyApprovedExternally(t *testing.T) { t.Fatalf("error starting operation: %v", err) } - // Wait 2 seconds to make sure the run started. - time.Sleep(2 * time.Second) + // Wait 50 milliseconds to make sure the run started. + time.Sleep(50 * time.Millisecond) wl, err := b.client.Workspaces.List( ctx, @@ -617,8 +617,8 @@ func TestRemote_applyDiscardedExternally(t *testing.T) { t.Fatalf("error starting operation: %v", err) } - // Wait 2 seconds to make sure the run started. - time.Sleep(2 * time.Second) + // Wait 50 milliseconds to make sure the run started. + time.Sleep(50 * time.Millisecond) wl, err := b.client.Workspaces.List( ctx, @@ -871,7 +871,7 @@ func TestRemote_applyLockTimeout(t *testing.T) { "approve": "yes", }) - op.StateLockTimeout = 5 * time.Second + op.StateLockTimeout = 50 * time.Millisecond op.UIIn = input op.UIOut = b.CLI op.Workspace = backend.DefaultStateName @@ -887,8 +887,8 @@ func TestRemote_applyLockTimeout(t *testing.T) { case <-sigint: // Stop redirecting SIGINT signals. signal.Stop(sigint) - case <-time.After(10 * time.Second): - t.Fatalf("expected lock timeout after 5 seconds, waited 10 seconds") + case <-time.After(200 * time.Millisecond): + t.Fatalf("expected lock timeout after 50 milliseconds, waited 200 milliseconds") } if len(input.answers) != 2 { diff --git a/backend/remote/backend_common.go b/backend/remote/backend_common.go index c881838da..08f9aa3b0 100644 --- a/backend/remote/backend_common.go +++ b/backend/remote/backend_common.go @@ -24,6 +24,13 @@ var ( errRunOverridden = errors.New("overridden using the UI or API") ) +var ( + backoffMin = 1000.0 + backoffMax = 3000.0 + + runPollInterval = 3 * time.Second +) + // backoff will perform exponential backoff based on the iteration and // limited by the provided min and max (in milliseconds) durations. func backoff(min, max float64, iter int) time.Duration { @@ -43,7 +50,7 @@ func (b *Remote) waitForRun(stopCtx, cancelCtx context.Context, op *backend.Oper return r, stopCtx.Err() case <-cancelCtx.Done(): return r, cancelCtx.Err() - case <-time.After(backoff(1000, 3000, i)): + case <-time.After(backoff(backoffMin, backoffMax, i)): // Timer up, show status } @@ -260,7 +267,7 @@ func (b *Remote) costEstimate(stopCtx, cancelCtx context.Context, op *backend.Op return stopCtx.Err() case <-cancelCtx.Done(): return cancelCtx.Err() - case <-time.After(1 * time.Second): + case <-time.After(backoff(backoffMin, backoffMax, i)): } // Retrieve the cost estimate to get its current status. @@ -454,7 +461,7 @@ func (b *Remote) confirm(stopCtx context.Context, op *backend.Operation, opts *t return case <-stopCtx.Done(): return - case <-time.After(3 * time.Second): + case <-time.After(runPollInterval): // Retrieve the run again to get its current status. r, err := b.client.Runs.Read(stopCtx, r.ID) if err != nil { diff --git a/backend/remote/backend_mock.go b/backend/remote/backend_mock.go index eaa81cbfc..6f12115ef 100644 --- a/backend/remote/backend_mock.go +++ b/backend/remote/backend_mock.go @@ -360,7 +360,7 @@ func (m *mockLogReader) Read(l []byte) (int, error) { if written, err := m.read(l); err != io.ErrNoProgress { return written, err } - time.Sleep(500 * time.Millisecond) + time.Sleep(1 * time.Millisecond) } } diff --git a/backend/remote/backend_plan.go b/backend/remote/backend_plan.go index f9fcf82b6..e42ec9576 100644 --- a/backend/remote/backend_plan.go +++ b/backend/remote/backend_plan.go @@ -20,6 +20,8 @@ import ( "github.com/hashicorp/terraform/tfdiags" ) +var planConfigurationVersionsPollInterval = 500 * time.Millisecond + func (b *Remote) opPlan(stopCtx, cancelCtx context.Context, op *backend.Operation, w *tfe.Workspace) (*tfe.Run, error) { log.Printf("[INFO] backend/remote: starting Plan operation") @@ -213,7 +215,7 @@ in order to capture the filesystem context the remote workspace expects: return nil, context.Canceled case <-cancelCtx.Done(): return nil, context.Canceled - case <-time.After(500 * time.Millisecond): + case <-time.After(planConfigurationVersionsPollInterval): cv, err = b.client.ConfigurationVersions.Read(stopCtx, cv.ID) if err != nil { return nil, generalError("Failed to retrieve configuration version", err) diff --git a/backend/remote/backend_plan_test.go b/backend/remote/backend_plan_test.go index a2c6e4ad2..a2fecf2d5 100644 --- a/backend/remote/backend_plan_test.go +++ b/backend/remote/backend_plan_test.go @@ -620,7 +620,7 @@ func TestRemote_planLockTimeout(t *testing.T) { "approve": "yes", }) - op.StateLockTimeout = 5 * time.Second + op.StateLockTimeout = 50 * time.Millisecond op.UIIn = input op.UIOut = b.CLI op.Workspace = backend.DefaultStateName @@ -636,8 +636,8 @@ func TestRemote_planLockTimeout(t *testing.T) { case <-sigint: // Stop redirecting SIGINT signals. signal.Stop(sigint) - case <-time.After(10 * time.Second): - t.Fatalf("expected lock timeout after 5 seconds, waited 10 seconds") + case <-time.After(200 * time.Millisecond): + t.Fatalf("expected lock timeout after 50 milliseconds, waited 200 milliseconds") } if len(input.answers) != 2 { diff --git a/backend/remote/remote_test.go b/backend/remote/remote_test.go index dbd0a72d6..f4cc3c5c2 100644 --- a/backend/remote/remote_test.go +++ b/backend/remote/remote_test.go @@ -4,6 +4,7 @@ import ( "flag" "os" "testing" + "time" _ "github.com/hashicorp/terraform/internal/logging" ) @@ -14,5 +15,11 @@ func TestMain(m *testing.M) { // Make sure TF_FORCE_LOCAL_BACKEND is unset os.Unsetenv("TF_FORCE_LOCAL_BACKEND") + // Reduce delays to make tests run faster + backoffMin = 1.0 + backoffMax = 1.0 + planConfigurationVersionsPollInterval = 1 * time.Millisecond + runPollInterval = 1 * time.Millisecond + os.Exit(m.Run()) }