Skip to content

Commit cd18362

Browse files
adonovangopherbot
authored andcommitted
go/packages: add test that go list closes file handles
Updates golang/go#71544 Change-Id: I349f97a0c5eb679115ea251d37dbd56042c7679b Reviewed-on: https://go-review.googlesource.com/c/tools/+/647516 Reviewed-by: Robert Findley <[email protected]> Auto-Submit: Alan Donovan <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]> Commit-Queue: Alan Donovan <[email protected]>
1 parent 04af9bf commit cd18362

File tree

1 file changed

+56
-0
lines changed

1 file changed

+56
-0
lines changed

go/packages/packages_test.go

+56
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,9 @@ import (
2828
"time"
2929

3030
"github.com/google/go-cmp/cmp"
31+
"golang.org/x/sync/errgroup"
3132
"golang.org/x/tools/go/packages"
33+
"golang.org/x/tools/internal/gocommand"
3234
"golang.org/x/tools/internal/packagesinternal"
3335
"golang.org/x/tools/internal/packagestest"
3436
"golang.org/x/tools/internal/testenv"
@@ -3400,3 +3402,57 @@ func writeTree(t *testing.T, archive string) string {
34003402
}
34013403
return root
34023404
}
3405+
3406+
// This is not a test of go/packages at all: it's a test of whether it
3407+
// is possible to delete the directory used by go list once it has
3408+
// finished. It is intended to evaluate the hypothesis (to explain
3409+
// issue #71544) that the go command, on Windows, occasionally fails
3410+
// to release all its handles to the temporary directory even when it
3411+
// should have finished. If this test ever fails, the go command has a bug.
3412+
func TestRmdirAfterGoList(t *testing.T) {
3413+
testenv.NeedsExec(t)
3414+
3415+
dir := t.TempDir()
3416+
if err := os.Mkdir(filepath.Join(dir, "p"), 0777); err != nil {
3417+
t.Fatalf("mkdir p: %v", err)
3418+
}
3419+
3420+
// Create a go.mod file and 100 trivial Go files for the go command to read.
3421+
if err := os.WriteFile(filepath.Join(dir, "go.mod"), []byte("module example.com"), 0666); err != nil {
3422+
t.Fatal(err)
3423+
}
3424+
for i := range 100 {
3425+
filename := filepath.Join(dir, fmt.Sprintf("p/%d.go", i))
3426+
if err := os.WriteFile(filename, []byte("package p"), 0666); err != nil {
3427+
t.Fatal(err)
3428+
}
3429+
}
3430+
3431+
runner := gocommand.Runner{}
3432+
3433+
g, ctx := errgroup.WithContext(context.Background())
3434+
for range 10 {
3435+
g.Go(func() error {
3436+
stdout, stderr, friendlyErr, err := runner.RunRaw(ctx, gocommand.Invocation{
3437+
Verb: "list",
3438+
Args: []string{"-json", "example.com/p"},
3439+
WorkingDir: dir,
3440+
})
3441+
if ctx.Err() != nil {
3442+
return nil // don't report error if canceled
3443+
}
3444+
if err != nil || friendlyErr != nil {
3445+
t.Fatalf("go list failed: %v, %v (stdout=%s stderr=%s)",
3446+
err, friendlyErr, stdout, stderr)
3447+
}
3448+
// Return an error so that concurrent invocations are canceled.
3449+
return fmt.Errorf("oops")
3450+
})
3451+
}
3452+
g.Wait() // ignore expected error
3453+
3454+
// This is the critical operation.
3455+
if err := os.RemoveAll(dir); err != nil {
3456+
t.Fatalf("failed to remove temp dir: %v", err)
3457+
}
3458+
}

0 commit comments

Comments
 (0)