Skip to content

Commit 4a9ef58

Browse files
adonovangopherbot
authored andcommitted
internal/gocommand: add TestRmdirAfterGoList WaitDelay variant
The new test is intended to confirm that a non-zero WaitDelay is the reason we observe Wait return before go list has exited. Updates golang/go#73736 Change-Id: I5d97d0601594a67dad37b0f8b323f4a9a8cfbe8f Reviewed-on: https://go-review.googlesource.com/c/tools/+/689755 Auto-Submit: Alan Donovan <[email protected]> Reviewed-by: Hongxiang Jiang <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]>
1 parent 365b9b0 commit 4a9ef58

File tree

1 file changed

+33
-18
lines changed

1 file changed

+33
-18
lines changed

internal/gocommand/invoke_test.go

Lines changed: 33 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"path/filepath"
1414
"strings"
1515
"testing"
16+
"time"
1617

1718
"golang.org/x/sync/errgroup"
1819
"golang.org/x/tools/internal/gocommand"
@@ -64,23 +65,34 @@ func TestRmdirAfterGoList_Runner(t *testing.T) {
6465
// TestRmdirAfterGoList_Runner that executes go list directly, to
6566
// control for the substantial logic of the gocommand package.
6667
//
67-
// If this test ever fails, the go command itself has a bug; as of May
68-
// 2025 this has never been observed.
68+
// It has two variants: the first does not set WaitDelay; the second
69+
// sets it to 30s. If the first variant ever fails, the go command
70+
// itself has a bug; as of May 2025 this has never been observed.
71+
//
72+
// If the second variant fails, it indicates that the WaitDelay
73+
// mechanism is responsible for causing Wait to return before the
74+
// child process has naturally finished. This is to confirm the
75+
// hypothesis at https://github.com/golang/go/issues/73736#issuecomment-2885407104.
6976
func TestRmdirAfterGoList_Direct(t *testing.T) {
70-
testRmdirAfterGoList(t, func(ctx context.Context, dir string) {
71-
cmd := exec.Command("go", "list", "-json", "example.com/p")
72-
cmd.Dir = dir
73-
cmd.Stdout = new(strings.Builder)
74-
cmd.Stderr = new(strings.Builder)
75-
err := cmd.Run()
76-
if ctx.Err() != nil {
77-
return // don't report error if canceled
78-
}
79-
if err != nil {
80-
t.Fatalf("go list failed: %v (stdout=%s stderr=%s)",
81-
err, cmd.Stdout, cmd.Stderr)
82-
}
83-
})
77+
for _, delay := range []time.Duration{0, 30 * time.Second} {
78+
t.Run(delay.String(), func(t *testing.T) {
79+
testRmdirAfterGoList(t, func(ctx context.Context, dir string) {
80+
cmd := exec.Command("go", "list", "-json", "example.com/p")
81+
cmd.Dir = dir
82+
cmd.Stdout = new(strings.Builder)
83+
cmd.Stderr = new(strings.Builder)
84+
cmd.WaitDelay = delay
85+
err := cmd.Run()
86+
if ctx.Err() != nil {
87+
return // don't report error if canceled
88+
}
89+
if err != nil {
90+
t.Fatalf("go list failed: %v (stdout=%s stderr=%s)",
91+
err, cmd.Stdout, cmd.Stderr)
92+
}
93+
})
94+
})
95+
}
8496
}
8597

8698
func testRmdirAfterGoList(t *testing.T, f func(ctx context.Context, dir string)) {
@@ -102,6 +114,7 @@ func testRmdirAfterGoList(t *testing.T, f func(ctx context.Context, dir string))
102114
}
103115
}
104116

117+
t0 := time.Now()
105118
g, ctx := errgroup.WithContext(context.Background())
106119
for range 10 {
107120
g.Go(func() error {
@@ -110,7 +123,9 @@ func testRmdirAfterGoList(t *testing.T, f func(ctx context.Context, dir string))
110123
return fmt.Errorf("oops")
111124
})
112125
}
113-
g.Wait() // ignore expected error
126+
g.Wait() // ignore error (expected)
127+
128+
t.Logf("10 concurrent executions (9 canceled) took %v", time.Since(t0))
114129

115130
// This is the critical operation.
116131
if err := os.RemoveAll(dir); err != nil {
@@ -119,6 +134,6 @@ func testRmdirAfterGoList(t *testing.T, f func(ctx context.Context, dir string))
119134
filepath.WalkDir(dir, func(path string, d fs.DirEntry, err error) error {
120135
t.Log(path, d, err)
121136
return nil
122-
})
137+
}) // ignore error
123138
}
124139
}

0 commit comments

Comments
 (0)