From 351aaa669bc270cece07816953e8fbe67c783b24 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Thu, 6 Jan 2022 16:56:19 -0500 Subject: [PATCH] internal/lsp/tests: re-enable MultiModule tests on plan9 According to https://go.dev/issue/50478#issuecomment-1006947143, Plan 9 does not support renaming across directories. For the MultiModule test cases we want to rename go.mod to testdata/go.mod, so we need to fall back to copying if os.Rename fails. Fixes golang/go#50478. Change-Id: I30b7601e1d4b122ce114015f3585f6ba6d6c9714 Reviewed-on: https://go-review.googlesource.com/c/tools/+/376115 Trust: Bryan Mills Run-TryBot: Bryan Mills gopls-CI: kokoro Reviewed-by: Robert Findley --- internal/lsp/tests/tests.go | 44 ++++++++++++++++++++++++++++++++----- 1 file changed, 39 insertions(+), 5 deletions(-) diff --git a/internal/lsp/tests/tests.go b/internal/lsp/tests/tests.go index 2589e77f41..86cea2e340 100644 --- a/internal/lsp/tests/tests.go +++ b/internal/lsp/tests/tests.go @@ -12,11 +12,11 @@ import ( "fmt" "go/ast" "go/token" + "io" "io/ioutil" "os" "path/filepath" "regexp" - "runtime" "sort" "strconv" "strings" @@ -274,9 +274,6 @@ func RunTests(t *testing.T, dataDir string, includeMultiModule bool, f func(*tes if mode == "MultiModule" { // Some bug in 1.12 breaks reading markers, and it's not worth figuring out. testenv.NeedsGo1Point(t, 13) - if runtime.GOOS == "plan9" { - t.Skipf("MultiModule setup fails for undiagnosed reasons on plan9; see https://go.dev/issue/50478") - } } datum := load(t, mode, dataDir) t.Helper() @@ -500,7 +497,7 @@ func load(t testing.TB, mode string, dir string) *Data { t.Fatal(err) } if mode == "MultiModule" { - if err := os.Rename(filepath.Join(datum.Config.Dir, "go.mod"), filepath.Join(datum.Config.Dir, "testmodule/go.mod")); err != nil { + if err := moveFile(filepath.Join(datum.Config.Dir, "go.mod"), filepath.Join(datum.Config.Dir, "testmodule/go.mod")); err != nil { t.Fatal(err) } } @@ -508,6 +505,43 @@ func load(t testing.TB, mode string, dir string) *Data { return datum } +// moveFile moves the file at oldpath to newpath, by renaming if possible +// or copying otherwise. +func moveFile(oldpath, newpath string) (err error) { + renameErr := os.Rename(oldpath, newpath) + if renameErr == nil { + return nil + } + + src, err := os.Open(oldpath) + if err != nil { + return err + } + defer func() { + src.Close() + if err == nil { + err = os.Remove(oldpath) + } + }() + + perm := os.ModePerm + fi, err := src.Stat() + if err == nil { + perm = fi.Mode().Perm() + } + + dst, err := os.OpenFile(newpath, os.O_WRONLY|os.O_CREATE|os.O_EXCL, perm) + if err != nil { + return err + } + + _, err = io.Copy(dst, src) + if closeErr := dst.Close(); err == nil { + err = closeErr + } + return err +} + func Run(t *testing.T, tests Tests, data *Data) { t.Helper() checkData(t, data)