blob: a92056a9c22c64fd726fef66b09deb7de007d0cd [file] [log] [blame]
// Copyright 2023 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package cache
import (
"os"
"testing"
"github.com/google/go-cmp/cmp"
"golang.org/x/sync/errgroup"
"golang.org/x/tools/go/packages"
"golang.org/x/tools/gopls/internal/file"
"golang.org/x/tools/gopls/internal/protocol"
"golang.org/x/tools/gopls/internal/util/bug"
"golang.org/x/tools/internal/testenv"
)
func TestMain(m *testing.M) {
bug.PanicOnBugs = true
os.Exit(m.Run())
}
func TestMatchingPortsStdlib(t *testing.T) {
// This test checks that we don't encounter a bug when matching ports, and
// sanity checks that the optimization to use trimmed/fake file content
// before delegating to go/build.Context.MatchFile does not affect
// correctness.
if testing.Short() {
t.Skip("skipping in short mode: takes to long on slow file systems")
}
testenv.NeedsTool(t, "go")
// Load, parse and type-check the program.
cfg := &packages.Config{
Mode: packages.LoadFiles,
Tests: true,
}
pkgs, err := packages.Load(cfg, "std", "cmd")
if err != nil {
t.Fatal(err)
}
var g errgroup.Group
packages.Visit(pkgs, nil, func(pkg *packages.Package) {
for _, f := range pkg.CompiledGoFiles {
f := f
g.Go(func() error {
content, err := os.ReadFile(f)
// We report errors via t.Error, not by returning,
// so that a single test can report multiple test failures.
if err != nil {
t.Errorf("failed to read %s: %v", f, err)
return nil
}
fh := makeFakeFileHandle(protocol.URIFromPath(f), content)
fastPorts := matchingPreferredPorts(t, fh, true)
slowPorts := matchingPreferredPorts(t, fh, false)
if diff := cmp.Diff(fastPorts, slowPorts); diff != "" {
t.Errorf("%s: ports do not match (-trimmed +untrimmed):\n%s", f, diff)
return nil
}
return nil
})
}
})
g.Wait()
}
func matchingPreferredPorts(tb testing.TB, fh file.Handle, trimContent bool) map[port]unit {
content, err := fh.Content()
if err != nil {
tb.Fatal(err)
}
if trimContent {
content = trimContentForPortMatch(content)
}
path := fh.URI().Path()
matching := make(map[port]unit)
for _, port := range preferredPorts {
if port.matches(path, content) {
matching[port] = unit{}
}
}
return matching
}
func BenchmarkMatchingPreferredPorts(b *testing.B) {
// Copy of robustio_posix.go
const src = `
// Copyright 2022 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build unix
// +build unix
package robustio
import (
"os"
"syscall"
"time"
)
func getFileID(filename string) (FileID, time.Time, error) {
fi, err := os.Stat(filename)
if err != nil {
return FileID{}, time.Time{}, err
}
stat := fi.Sys().(*syscall.Stat_t)
return FileID{
device: uint64(stat.Dev), // (int32 on darwin, uint64 on linux)
inode: stat.Ino,
}, fi.ModTime(), nil
}
`
fh := makeFakeFileHandle("file:///path/to/test/file.go", []byte(src))
for i := 0; i < b.N; i++ {
_ = matchingPreferredPorts(b, fh, true)
}
}