golang.org/x/tools/gopls@v0.15.3/internal/cache/port_test.go (about) 1 // Copyright 2023 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package cache 6 7 import ( 8 "os" 9 "testing" 10 11 "github.com/google/go-cmp/cmp" 12 "golang.org/x/sync/errgroup" 13 "golang.org/x/tools/go/packages" 14 "golang.org/x/tools/gopls/internal/file" 15 "golang.org/x/tools/gopls/internal/protocol" 16 "golang.org/x/tools/gopls/internal/util/bug" 17 "golang.org/x/tools/internal/testenv" 18 ) 19 20 func TestMain(m *testing.M) { 21 bug.PanicOnBugs = true 22 os.Exit(m.Run()) 23 } 24 25 func TestMatchingPortsStdlib(t *testing.T) { 26 // This test checks that we don't encounter a bug when matching ports, and 27 // sanity checks that the optimization to use trimmed/fake file content 28 // before delegating to go/build.Context.MatchFile does not affect 29 // correctness. 30 if testing.Short() { 31 t.Skip("skipping in short mode: takes to long on slow file systems") 32 } 33 34 testenv.NeedsTool(t, "go") 35 36 // Load, parse and type-check the program. 37 cfg := &packages.Config{ 38 Mode: packages.LoadFiles, 39 Tests: true, 40 } 41 pkgs, err := packages.Load(cfg, "std", "cmd") 42 if err != nil { 43 t.Fatal(err) 44 } 45 46 var g errgroup.Group 47 packages.Visit(pkgs, nil, func(pkg *packages.Package) { 48 for _, f := range pkg.CompiledGoFiles { 49 f := f 50 g.Go(func() error { 51 content, err := os.ReadFile(f) 52 // We report errors via t.Error, not by returning, 53 // so that a single test can report multiple test failures. 54 if err != nil { 55 t.Errorf("failed to read %s: %v", f, err) 56 return nil 57 } 58 fh := makeFakeFileHandle(protocol.URIFromPath(f), content) 59 fastPorts := matchingPreferredPorts(t, fh, true) 60 slowPorts := matchingPreferredPorts(t, fh, false) 61 if diff := cmp.Diff(fastPorts, slowPorts); diff != "" { 62 t.Errorf("%s: ports do not match (-trimmed +untrimmed):\n%s", f, diff) 63 return nil 64 } 65 return nil 66 }) 67 } 68 }) 69 g.Wait() 70 } 71 72 func matchingPreferredPorts(tb testing.TB, fh file.Handle, trimContent bool) map[port]unit { 73 content, err := fh.Content() 74 if err != nil { 75 tb.Fatal(err) 76 } 77 if trimContent { 78 content = trimContentForPortMatch(content) 79 } 80 path := fh.URI().Path() 81 matching := make(map[port]unit) 82 for _, port := range preferredPorts { 83 if port.matches(path, content) { 84 matching[port] = unit{} 85 } 86 } 87 return matching 88 } 89 90 func BenchmarkMatchingPreferredPorts(b *testing.B) { 91 // Copy of robustio_posix.go 92 const src = ` 93 // Copyright 2022 The Go Authors. All rights reserved. 94 // Use of this source code is governed by a BSD-style 95 // license that can be found in the LICENSE file. 96 97 //go:build !windows && !plan9 98 // +build !windows,!plan9 99 100 // TODO(adonovan): use 'unix' tag when go1.19 can be assumed. 101 102 package robustio 103 104 import ( 105 "os" 106 "syscall" 107 "time" 108 ) 109 110 func getFileID(filename string) (FileID, time.Time, error) { 111 fi, err := os.Stat(filename) 112 if err != nil { 113 return FileID{}, time.Time{}, err 114 } 115 stat := fi.Sys().(*syscall.Stat_t) 116 return FileID{ 117 device: uint64(stat.Dev), // (int32 on darwin, uint64 on linux) 118 inode: stat.Ino, 119 }, fi.ModTime(), nil 120 } 121 ` 122 fh := makeFakeFileHandle("file:///path/to/test/file.go", []byte(src)) 123 for i := 0; i < b.N; i++ { 124 _ = matchingPreferredPorts(b, fh, true) 125 } 126 }