diff --git a/agent/agentproc/api_test.go b/agent/agentproc/api_test.go index 73efa6bdf7..c718cf3248 100644 --- a/agent/agentproc/api_test.go +++ b/agent/agentproc/api_test.go @@ -964,13 +964,11 @@ func TestProcessOutput(t *testing.T) { codes [2]int ) for i := range 2 { - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { w := getOutputWithWait(t, handler, id) codes[i] = w.Code _ = json.NewDecoder(w.Body).Decode(&resps[i]) - }() + }) } // Signal the process to exit so both waiters unblock. diff --git a/agent/filefinder/bench_test.go b/agent/filefinder/bench_test.go index fd36be5612..33182cfc74 100644 --- a/agent/filefinder/bench_test.go +++ b/agent/filefinder/bench_test.go @@ -300,13 +300,11 @@ func BenchmarkSearch_ConcurrentReads_Throughput(b *testing.B) { perGoroutine = 1 } for gi := 0; gi < g; gi++ { - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { for j := 0; j < perGoroutine; j++ { _ = filefinder.SearchSnapshotForTest(plan, snap, maxCands) } - }() + }) } wg.Wait() totalOps := float64(g * perGoroutine) diff --git a/agent/immortalstreams/backedpipe/backed_pipe_test.go b/agent/immortalstreams/backedpipe/backed_pipe_test.go index 5e81cf7c4e..82ed838127 100644 --- a/agent/immortalstreams/backedpipe/backed_pipe_test.go +++ b/agent/immortalstreams/backedpipe/backed_pipe_test.go @@ -756,13 +756,11 @@ func TestBackedPipe_DuplicateReconnectionPrevention(t *testing.T) { // Start all goroutines for i := 0; i < numConcurrent; i++ { - wg.Add(1) - go func(idx int) { - defer wg.Done() + wg.Go(func() { // Wait for the signal to start - <-startSignals[idx] - errors[idx] = bp.ForceReconnect() - }(i) + <-startSignals[i] + errors[i] = bp.ForceReconnect() + }) } // Start the first ForceReconnect and wait for it to block diff --git a/agent/immortalstreams/backedpipe/backed_writer_test.go b/agent/immortalstreams/backedpipe/backed_writer_test.go index b61425e827..20c301cbca 100644 --- a/agent/immortalstreams/backedpipe/backed_writer_test.go +++ b/agent/immortalstreams/backedpipe/backed_writer_test.go @@ -883,14 +883,12 @@ func TestBackedWriter_MultipleWritesDuringReconnect(t *testing.T) { writesStarted := make(chan struct{}, numWriters) for i := 0; i < numWriters; i++ { - wg.Add(1) - go func(id int) { - defer wg.Done() + wg.Go(func() { // Signal that this write is starting writesStarted <- struct{}{} - data := []byte{byte('A' + id)} - _, writeResults[id] = bw.Write(data) - }(i) + data := []byte{byte('A' + i)} + _, writeResults[i] = bw.Write(data) + }) } // Wait for all writes to start diff --git a/agent/unit/graph_test.go b/agent/unit/graph_test.go index f7d1117be7..287cf04442 100644 --- a/agent/unit/graph_test.go +++ b/agent/unit/graph_test.go @@ -244,16 +244,14 @@ func TestGraphThreadSafety(t *testing.T) { barrier := make(chan struct{}) // Launch writers for i := 0; i < numWriters; i++ { - wg.Add(1) - go func(writerID int) { - defer wg.Done() + wg.Go(func() { <-barrier for j := 0; j < operationsPerWriter; j++ { - from := &testGraphVertex{Name: fmt.Sprintf("writer-%d-%d", writerID, j)} - to := &testGraphVertex{Name: fmt.Sprintf("writer-%d-%d", writerID, j+1)} + from := &testGraphVertex{Name: fmt.Sprintf("writer-%d-%d", i, j)} + to := &testGraphVertex{Name: fmt.Sprintf("writer-%d-%d", i, j+1)} graph.AddEdge(from, to, testEdgeCompleted) } - }(i) + }) } // Launch readers @@ -263,20 +261,18 @@ func TestGraphThreadSafety(t *testing.T) { }, numReaders) for i := 0; i < numReaders; i++ { - wg.Add(1) - go func(readerID int) { - defer wg.Done() + wg.Go(func() { <-barrier defer func() { if r := recover(); r != nil { - readerResults[readerID].panicked = true + readerResults[i].panicked = true } }() readCount := 0 for j := 0; j < operationsPerReader; j++ { // Create a test vertex and read - testUnit := &testGraphVertex{Name: fmt.Sprintf("test-reader-%d-%d", readerID, j)} + testUnit := &testGraphVertex{Name: fmt.Sprintf("test-reader-%d-%d", i, j)} forwardEdges := graph.GetForwardAdjacentVertices(testUnit) reverseEdges := graph.GetReverseAdjacentVertices(testUnit) @@ -285,8 +281,8 @@ func TestGraphThreadSafety(t *testing.T) { _ = reverseEdges readCount++ } - readerResults[readerID].readCount = readCount - }(i) + readerResults[i].readCount = readCount + }) } close(barrier) @@ -324,13 +320,11 @@ func TestGraphThreadSafety(t *testing.T) { // Launch goroutines trying to add D→A (creates cycle) for i := 0; i < numGoroutines; i++ { - wg.Add(1) - go func(goroutineID int) { - defer wg.Done() + wg.Go(func() { <-barrier err := graph.AddEdge(unitD, unitA, testEdgeCompleted) - cycleErrors[goroutineID] = err - }(i) + cycleErrors[i] = err + }) } close(barrier) @@ -370,28 +364,24 @@ func TestGraphThreadSafety(t *testing.T) { // Launch readers calling ToDOT dotErrors := make([]error, numReaders) for i := 0; i < numReaders; i++ { - wg.Add(1) - go func(readerID int) { - defer wg.Done() + wg.Go(func() { <-barrier - dot, err := graph.ToDOT(fmt.Sprintf("test-%d", readerID)) - dotErrors[readerID] = err + dot, err := graph.ToDOT(fmt.Sprintf("test-%d", i)) + dotErrors[i] = err if err == nil { - dotResults[readerID] = dot + dotResults[i] = dot } - }(i) + }) } // Launch writers adding edges for i := 0; i < numWriters; i++ { - wg.Add(1) - go func(writerID int) { - defer wg.Done() + wg.Go(func() { <-barrier - from := &testGraphVertex{Name: fmt.Sprintf("writer-dot-%d", writerID)} - to := &testGraphVertex{Name: fmt.Sprintf("writer-dot-target-%d", writerID)} + from := &testGraphVertex{Name: fmt.Sprintf("writer-dot-%d", i)} + to := &testGraphVertex{Name: fmt.Sprintf("writer-dot-target-%d", i)} graph.AddEdge(from, to, testEdgeCompleted) - }(i) + }) } close(barrier) @@ -418,9 +408,7 @@ func BenchmarkGraph_ConcurrentMixedOperations(b *testing.B) { for i := 0; i < b.N; i++ { // Launch goroutines performing random operations for j := 0; j < numGoroutines; j++ { - wg.Add(1) - go func(goroutineID int) { - defer wg.Done() + wg.Go(func() { operationCount := 0 for operationCount < 50 { @@ -428,7 +416,7 @@ func BenchmarkGraph_ConcurrentMixedOperations(b *testing.B) { if operation < 0.6 { // 60% reads // Read operation - testUnit := &testGraphVertex{Name: fmt.Sprintf("bench-read-%d-%d", goroutineID, operationCount)} + testUnit := &testGraphVertex{Name: fmt.Sprintf("bench-read-%d-%d", j, operationCount)} forwardEdges := graph.GetForwardAdjacentVertices(testUnit) reverseEdges := graph.GetReverseAdjacentVertices(testUnit) @@ -437,14 +425,14 @@ func BenchmarkGraph_ConcurrentMixedOperations(b *testing.B) { _ = reverseEdges } else { // 40% writes // Write operation - from := &testGraphVertex{Name: fmt.Sprintf("bench-write-%d-%d", goroutineID, operationCount)} - to := &testGraphVertex{Name: fmt.Sprintf("bench-write-target-%d-%d", goroutineID, operationCount)} + from := &testGraphVertex{Name: fmt.Sprintf("bench-write-%d-%d", j, operationCount)} + to := &testGraphVertex{Name: fmt.Sprintf("bench-write-target-%d-%d", j, operationCount)} graph.AddEdge(from, to, testEdgeCompleted) } operationCount++ } - }(j) + }) } wg.Wait() diff --git a/aibridge/internal/integrationtest/circuit_breaker_internal_test.go b/aibridge/internal/integrationtest/circuit_breaker_internal_test.go index 57f9b27df3..bd06d09e27 100644 --- a/aibridge/internal/integrationtest/circuit_breaker_internal_test.go +++ b/aibridge/internal/integrationtest/circuit_breaker_internal_test.go @@ -474,12 +474,10 @@ func TestCircuitBreaker_HalfOpenMaxRequests(t *testing.T) { responses := make(chan int, totalRequests) for i := 0; i < totalRequests; i++ { - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { status := doRequest() responses <- status - }() + }) } wg.Wait() diff --git a/aibridge/keypool/keypool_test.go b/aibridge/keypool/keypool_test.go index d1ab09e7de..9880c59e08 100644 --- a/aibridge/keypool/keypool_test.go +++ b/aibridge/keypool/keypool_test.go @@ -619,11 +619,9 @@ func TestKeyConcurrent(t *testing.T) { const numGoroutines = 10 var wg sync.WaitGroup for r := range numGoroutines { - wg.Add(1) - go func(r int) { - defer wg.Done() + wg.Go(func() { tc.run(r, key) - }(r) + }) } wg.Wait() diff --git a/cli/portforward_test.go b/cli/portforward_test.go index ac4146ef28..fd693120c3 100644 --- a/cli/portforward_test.go +++ b/cli/portforward_test.go @@ -429,11 +429,9 @@ func setupTestListener(t *testing.T, l net.Listener, prefix []byte) string { return } - wg.Add(1) - go func() { + wg.Go(func() { echoIfPrefixed(t, c, prefix) - wg.Done() - }() + }) } }() diff --git a/cli/ssh_test.go b/cli/ssh_test.go index eb31dc801e..2221a23e7b 100644 --- a/cli/ssh_test.go +++ b/cli/ssh_test.go @@ -1360,12 +1360,10 @@ func TestSSH(t *testing.T) { return } - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { defer fd.Close() agentssh.Bicopy(ctx, fd, fd) - }() + }) } }) @@ -1426,12 +1424,10 @@ func TestSSH(t *testing.T) { return } - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { defer fd.Close() agentssh.Bicopy(ctx, fd, fd) - }() + }) } }) @@ -1576,12 +1572,10 @@ func TestSSH(t *testing.T) { return } - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { defer fd.Close() agentssh.Bicopy(ctx, fd, fd) - }() + }) } }) diff --git a/coderd/boundaryusage/tracker_test.go b/coderd/boundaryusage/tracker_test.go index a351647512..a271f7eed2 100644 --- a/coderd/boundaryusage/tracker_test.go +++ b/coderd/boundaryusage/tracker_test.go @@ -124,15 +124,13 @@ func TestTracker_Track_Concurrent(t *testing.T) { var wg sync.WaitGroup for i := 0; i < numGoroutines; i++ { - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { workspaceID := uuid.New() ownerID := uuid.New() for j := 0; j < requestsPerGoroutine; j++ { tracker.Track(workspaceID, ownerID, 1, 1) } - }() + }) } wg.Wait() @@ -507,22 +505,18 @@ func TestTracker_ConcurrentFlushAndTrack(t *testing.T) { var wg sync.WaitGroup // Goroutine 1: Continuously track. - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { for i := 0; i < numOperations; i++ { tracker.Track(uuid.New(), uuid.New(), 1, 1) } - }() + }) // Goroutine 2: Continuously flush. - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { for i := 0; i < numOperations; i++ { _ = tracker.FlushToDB(ctx, db, replicaID) } - }() + }) wg.Wait() diff --git a/coderd/httpmw/ratelimit_test.go b/coderd/httpmw/ratelimit_test.go index 49e46ccf46..1e4ca1828b 100644 --- a/coderd/httpmw/ratelimit_test.go +++ b/coderd/httpmw/ratelimit_test.go @@ -286,9 +286,7 @@ func TestConcurrencyLimit(t *testing.T) { var wg sync.WaitGroup for i := 0; i < maxConcurrency; i++ { - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { req, err := http.NewRequestWithContext(ctx, http.MethodGet, server.URL+"/", nil) if err != nil { results <- result{err: err} @@ -301,7 +299,7 @@ func TestConcurrencyLimit(t *testing.T) { } defer resp.Body.Close() results <- result{statusCode: resp.StatusCode} - }() + }) } // Wait for all requests to enter the handler with a timeout. diff --git a/coderd/notifications/dispatch/smtp_test.go b/coderd/notifications/dispatch/smtp_test.go index 34aed0feed..ee9b6a3d7a 100644 --- a/coderd/notifications/dispatch/smtp_test.go +++ b/coderd/notifications/dispatch/smtp_test.go @@ -445,11 +445,9 @@ func TestSMTP(t *testing.T) { // Start mock SMTP server in the background. var wg sync.WaitGroup - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { assert.NoError(t, srv.Serve(listen)) - }() + }) // Wait for the server to become pingable. require.Eventually(t, func() bool { @@ -590,11 +588,9 @@ func TestSMTPEnvelopeAndHeaders(t *testing.T) { handler := dispatch.NewSMTPHandler(cfg, logger.Named("smtp")) var wg sync.WaitGroup - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { assert.NoError(t, srv.Serve(listen)) - }() + }) require.Eventually(t, func() bool { cl, err := smtptest.PingClient(listen, false, false) diff --git a/coderd/notifications/notifications_test.go b/coderd/notifications/notifications_test.go index aaceb4fe3c..839958f91c 100644 --- a/coderd/notifications/notifications_test.go +++ b/coderd/notifications/notifications_test.go @@ -1541,11 +1541,9 @@ func TestNotificationTemplates_Golden(t *testing.T) { // Start mock SMTP server in the background. var wg sync.WaitGroup - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { assert.NoError(t, srv.Serve(listen)) - }() + }) // Wait for the server to become pingable. require.Eventually(t, func() bool { diff --git a/coderd/oauth2_security_test.go b/coderd/oauth2_security_test.go index baab37e3d3..47190cd2bf 100644 --- a/coderd/oauth2_security_test.go +++ b/coderd/oauth2_security_test.go @@ -421,13 +421,10 @@ func TestOAuth2ConcurrentSecurityOperations(t *testing.T) { // Launch concurrent attempts to access the client configuration for i := 0; i < numGoroutines; i++ { - wg.Add(1) - go func(index int) { - defer wg.Done() - + wg.Go(func() { _, err := client.GetOAuth2ClientConfiguration(ctx, regResp.ClientID, regResp.RegistrationAccessToken) - errors[index] = err - }(i) + errors[i] = err + }) } wg.Wait() @@ -448,23 +445,20 @@ func TestOAuth2ConcurrentSecurityOperations(t *testing.T) { // Launch concurrent attempts with invalid tokens for i := 0; i < numGoroutines; i++ { - wg.Add(1) - go func(index int) { - defer wg.Done() - - _, err := client.GetOAuth2ClientConfiguration(ctx, regResp.ClientID, fmt.Sprintf("invalid-token-%d", index)) + wg.Go(func() { + _, err := client.GetOAuth2ClientConfiguration(ctx, regResp.ClientID, fmt.Sprintf("invalid-token-%d", i)) if err == nil { - t.Errorf("Expected error for goroutine %d", index) + t.Errorf("Expected error for goroutine %d", i) return } var httpErr *codersdk.Error if !errors.As(err, &httpErr) { - t.Errorf("Expected codersdk.Error for goroutine %d", index) + t.Errorf("Expected codersdk.Error for goroutine %d", i) return } - statusCodes[index] = httpErr.StatusCode() - }(i) + statusCodes[i] = httpErr.StatusCode() + }) } wg.Wait() @@ -494,13 +488,10 @@ func TestOAuth2ConcurrentSecurityOperations(t *testing.T) { // Launch concurrent deletion attempts for i := 0; i < numGoroutines; i++ { - wg.Add(1) - go func(index int) { - defer wg.Done() - + wg.Go(func() { err := client.DeleteOAuth2ClientConfiguration(ctx, deleteRegResp.ClientID, deleteRegResp.RegistrationAccessToken) - deleteResults[index] = err - }(i) + deleteResults[i] = err + }) } wg.Wait() diff --git a/coderd/workspacestats/tracker_test.go b/coderd/workspacestats/tracker_test.go index 1ea81f63fb..cd60e32294 100644 --- a/coderd/workspacestats/tracker_test.go +++ b/coderd/workspacestats/tracker_test.go @@ -87,11 +87,9 @@ func TestTracker(t *testing.T) { var wg sync.WaitGroup count = 0 for i := 0; i < len(ids); i++ { - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { tickCh <- now - }() + }) wut.Add(ids[i]) } @@ -173,18 +171,14 @@ func TestTracker_MultipleInstances(t *testing.T) { nowB := now.Add(2 * time.Minute) var wg sync.WaitGroup var flushedA, flushedB int - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { wuTickA <- nowA flushedA = <-wuFlushA - }() - wg.Add(1) - go func() { - defer wg.Done() + }) + wg.Go(func() { wuTickB <- nowB flushedB = <-wuFlushB - }() + }) wg.Wait() // We expect 5 flushed IDs each diff --git a/coderd/x/chatd/configcache_internal_test.go b/coderd/x/chatd/configcache_internal_test.go index 4686254241..f868c321a9 100644 --- a/coderd/x/chatd/configcache_internal_test.go +++ b/coderd/x/chatd/configcache_internal_test.go @@ -416,12 +416,10 @@ func TestConfigCache_Singleflight(t *testing.T) { var wg sync.WaitGroup start := make(chan struct{}) for i := 0; i < callers; i++ { - wg.Add(1) - go func(i int) { - defer wg.Done() + wg.Go(func() { <-start results[i], errs[i] = cache.EnabledProviders(ctx) - }(i) + }) } close(start) diff --git a/coderd/x/nats/pubsub_test.go b/coderd/x/nats/pubsub_test.go index 7b65228b7a..057ed0e1c0 100644 --- a/coderd/x/nats/pubsub_test.go +++ b/coderd/x/nats/pubsub_test.go @@ -139,11 +139,9 @@ func TestPubsub(t *testing.T) { var first, second error var wg sync.WaitGroup - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { first = ps.Close() - }() + }) wg.Wait() second = ps.Close() assert.NoError(t, first) diff --git a/enterprise/cli/create_test.go b/enterprise/cli/create_test.go index 94a04a5501..213d8f12f1 100644 --- a/enterprise/cli/create_test.go +++ b/enterprise/cli/create_test.go @@ -76,11 +76,9 @@ func TestEnterpriseCreate(t *testing.T) { createTemplate := func(tplName string, orgID uuid.UUID) { version := coderdtest.CreateTemplateVersion(t, ownerClient, orgID, nil) - wg.Add(1) - go func() { + wg.Go(func() { coderdtest.AwaitTemplateVersionJobCompleted(t, ownerClient, version.ID) - wg.Done() - }() + }) coderdtest.CreateTemplate(t, ownerClient, orgID, version.ID, func(request *codersdk.CreateTemplateRequest) { request.Name = tplName diff --git a/enterprise/coderd/prebuilds/reconcile_test.go b/enterprise/coderd/prebuilds/reconcile_test.go index 1fb67fd2d4..40fdae42aa 100644 --- a/enterprise/coderd/prebuilds/reconcile_test.go +++ b/enterprise/coderd/prebuilds/reconcile_test.go @@ -1974,9 +1974,7 @@ func TestReconciliationLock(t *testing.T) { wg := sync.WaitGroup{} mutex := sync.Mutex{} for i := 0; i < 5; i++ { - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { cache := files.New(prometheus.NewRegistry(), &coderdtest.FakeAuthorizer{}) reconciler := prebuilds.NewStoreReconciler( db, @@ -2002,7 +2000,7 @@ func TestReconciliationLock(t *testing.T) { defer mutex.Unlock() return nil }) - }() + }) } wg.Wait() } diff --git a/enterprise/coderd/workspacequota_test.go b/enterprise/coderd/workspacequota_test.go index 241b832e71..b73563727c 100644 --- a/enterprise/coderd/workspacequota_test.go +++ b/enterprise/coderd/workspacequota_test.go @@ -152,13 +152,11 @@ func TestWorkspaceQuota(t *testing.T) { // Spin up three workspaces fine var wg sync.WaitGroup for i := 0; i < 4; i++ { - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { workspace := coderdtest.CreateWorkspace(t, client, template.ID) build := coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, workspace.LatestBuild.ID) assert.Equal(t, codersdk.WorkspaceStatusRunning, build.Status) - }() + }) } wg.Wait() verifyQuota(ctx, t, client, user.OrganizationID.String(), 4, 4) diff --git a/enterprise/wsproxy/wsproxy_test.go b/enterprise/wsproxy/wsproxy_test.go index 8115e4ae15..ec6ecc01d3 100644 --- a/enterprise/wsproxy/wsproxy_test.go +++ b/enterprise/wsproxy/wsproxy_test.go @@ -1201,12 +1201,10 @@ func createProxyReplicas(ctx context.Context, t *testing.T, opts *createProxyRep ok = false // Retry registration on this proxy. - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { err := proxy.RegisterNow(ctx) t.Logf("replica %d re-registered: err=%v", i, err) - }() + }) } } wg.Wait() diff --git a/provisioner/terraform/install_test.go b/provisioner/terraform/install_test.go index aedd3fe7b3..7f87969a68 100644 --- a/provisioner/terraform/install_test.go +++ b/provisioner/terraform/install_test.go @@ -140,13 +140,11 @@ func TestInstall(t *testing.T) { var wg sync.WaitGroup paths := make(chan string, 8) for i := 0; i < 8; i++ { - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { p, err := terraform.Install(ctx, log, false, dir, version, "http://"+proxy.listener.Addr().String()) assert.NoError(t, err) paths <- p - }() + }) } go func() { wg.Wait() diff --git a/provisionersdk/agent_test.go b/provisionersdk/agent_test.go index 3101959fe0..01b06233c2 100644 --- a/provisionersdk/agent_test.go +++ b/provisionersdk/agent_test.go @@ -94,15 +94,12 @@ func TestAgentScript(t *testing.T) { done := make(chan error, 1) var wg sync.WaitGroup - wg.Add(1) - go func() { - defer wg.Done() - + wg.Go(func() { // The bootstrap scripts trap exit codes to allow operators to view the script logs and debug the process // while it is still running. We do not expect Wait() to complete. err := cmd.Wait() done <- err - }() + }) select { case <-ctx.Done(): diff --git a/scripts/develop/main_test.go b/scripts/develop/main_test.go index 2491d52b4c..6d3df9728e 100644 --- a/scripts/develop/main_test.go +++ b/scripts/develop/main_test.go @@ -101,13 +101,11 @@ func TestLogWriter(t *testing.T) { var wg sync.WaitGroup for range 10 { - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { for range 50 { _, _ = w.Write([]byte("x\n")) } - }() + }) } wg.Wait()