From: miller Date: Wed, 1 Mar 2023 16:55:45 +0000 (+0000) Subject: os: make TestProgWideChdir detect more possible failure cases X-Git-Tag: go1.21rc1~309 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=392fbaa0f394592a9924daf498f58226fd9b3e79;p=gostls13.git os: make TestProgWideChdir detect more possible failure cases This test is meant to detect the effect of Chdir not being observed in other concurrent goroutines, possible in Plan 9 because each M runs in a separate OS process with its own working directory. The test depends on Getwd to report the correct working directory, but if Chdir fails then Getwd may fail for the same reasons. We add a consistency check that Stat(Getwd()) and Stat(".") refer to the same file. Also change channel usage and add a sync.WaitGroup to ensure test goroutines are not left blocked or running when the main test function exits. For #58802 Change-Id: I80d554fcf3617427c28bbe16e5e396367dcfe673 Reviewed-on: https://go-review.googlesource.com/c/go/+/472555 Reviewed-by: Ian Lance Taylor Reviewed-by: David du Colombier <0intro@gmail.com> Reviewed-by: Bryan Mills Run-TryBot: Ian Lance Taylor TryBot-Result: Gopher Robot Auto-Submit: Ian Lance Taylor --- diff --git a/src/os/os_test.go b/src/os/os_test.go index 0a6be3516a..ad30756cbd 100644 --- a/src/os/os_test.go +++ b/src/os/os_test.go @@ -1696,11 +1696,35 @@ func TestChdirAndGetwd(t *testing.T) { // Test that Chdir+Getwd is program-wide. func TestProgWideChdir(t *testing.T) { const N = 10 - const ErrPwd = "Error!" - c := make(chan bool) - cpwd := make(chan string, N) + var wg sync.WaitGroup + hold := make(chan struct{}) + done := make(chan struct{}) + + d := t.TempDir() + oldwd, err := Getwd() + if err != nil { + t.Fatalf("Getwd: %v", err) + } + defer func() { + if err := Chdir(oldwd); err != nil { + // It's not safe to continue with tests if we can't get back to + // the original working directory. + panic(err) + } + }() + + // Note the deferred Wait must be called after the deferred close(done), + // to ensure the N goroutines have been released even if the main goroutine + // calls Fatalf. It must be called before the Chdir back to the original + // directory, and before the deferred deletion implied by TempDir, + // so as not to interfere while the N goroutines are still running. + defer wg.Wait() + defer close(done) + for i := 0; i < N; i++ { + wg.Add(1) go func(i int) { + defer wg.Done() // Lock half the goroutines in their own operating system // thread to exercise more scheduler possibilities. if i%2 == 1 { @@ -1711,57 +1735,48 @@ func TestProgWideChdir(t *testing.T) { // See issue 9428. runtime.LockOSThread() } - hasErr, closed := <-c - if !closed && hasErr { - cpwd <- ErrPwd + select { + case <-done: + return + case <-hold: + } + // Getwd might be wrong + f0, err := Stat(".") + if err != nil { + t.Error(err) return } pwd, err := Getwd() if err != nil { - t.Errorf("Getwd on goroutine %d: %v", i, err) - cpwd <- ErrPwd + t.Errorf("Getwd: %v", err) + return + } + if pwd != d { + t.Errorf("Getwd() = %q, want %q", pwd, d) + return + } + f1, err := Stat(pwd) + if err != nil { + t.Error(err) + return + } + if !SameFile(f0, f1) { + t.Errorf(`Samefile(Stat("."), Getwd()) reports false (%s != %s)`, f0.Name(), f1.Name()) return } - cpwd <- pwd }(i) } - oldwd, err := Getwd() - if err != nil { - c <- true - t.Fatalf("Getwd: %v", err) - } - d, err := MkdirTemp("", "test") - if err != nil { - c <- true - t.Fatalf("TempDir: %v", err) - } - defer func() { - if err := Chdir(oldwd); err != nil { - t.Fatalf("Chdir: %v", err) - } - RemoveAll(d) - }() - if err := Chdir(d); err != nil { - c <- true + if err = Chdir(d); err != nil { t.Fatalf("Chdir: %v", err) } // OS X sets TMPDIR to a symbolic link. // So we resolve our working directory again before the test. d, err = Getwd() if err != nil { - c <- true t.Fatalf("Getwd: %v", err) } - close(c) - for i := 0; i < N; i++ { - pwd := <-cpwd - if pwd == ErrPwd { - t.FailNow() - } - if pwd != d { - t.Errorf("Getwd returned %q; want %q", pwd, d) - } - } + close(hold) + wg.Wait() } func TestSeek(t *testing.T) {