Skip to content

Commit 59f79bc

Browse files
xieyuschengopherbot
authored andcommitted
go/ssa: speed up TestTypeparamTest by loading tests once
Previously, TestTypeparamTest constructs a go module for each file under test/typeparam and uses packages.Load to load it. However, the packages.Load utilizes the 'go list' underlying and it costs a lot. As a result, this made the test 50x slower. This change tries to put each file under a separated package in the same go module so 'go list' will be used only once. It supports to skip the test if the test/typeparam under GOROOT doesn't exist. Fixes golang/go#70078 Change-Id: I2953709236602f1f6d0b53457ef21bb83561e656 Reviewed-on: https://go-review.googlesource.com/c/tools/+/623135 Reviewed-by: Alan Donovan <[email protected]> Reviewed-by: Robert Findley <[email protected]> Auto-Submit: Alan Donovan <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]> Reviewed-by: Richard Miller <[email protected]>
1 parent 70e82e0 commit 59f79bc

File tree

1 file changed

+31
-13
lines changed

1 file changed

+31
-13
lines changed

go/ssa/builder_test.go

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package ssa_test
66

77
import (
88
"bytes"
9+
"errors"
910
"fmt"
1011
"go/ast"
1112
"go/importer"
@@ -686,8 +687,10 @@ func TestTypeparamTest(t *testing.T) {
686687
t.Fatalf("Failed to load errors package from std: %s", err)
687688
}
688689
goroot := filepath.Dir(filepath.Dir(filepath.Dir(stdPkgs[0].GoFiles[0])))
689-
690690
dir := filepath.Join(goroot, "test", "typeparam")
691+
if _, err = os.Stat(dir); errors.Is(err, os.ErrNotExist) {
692+
t.Skipf("test/typeparam doesn't exist under GOROOT %s", goroot)
693+
}
691694

692695
// Collect all of the .go files in
693696
fsys := os.DirFS(dir)
@@ -696,24 +699,39 @@ func TestTypeparamTest(t *testing.T) {
696699
t.Fatal(err)
697700
}
698701

702+
// Each call to buildPackage calls package.Load, which invokes "go list",
703+
// and with over 300 subtests this can be very slow (minutes, or tens
704+
// on some platforms). So, we use an overlay to map each test file to a
705+
// distinct single-file package and load them all at once.
706+
overlay := map[string][]byte{
707+
"go.mod": goMod("example.com", -1),
708+
}
699709
for _, entry := range entries {
700710
if entry.IsDir() || !strings.HasSuffix(entry.Name(), ".go") {
701711
continue // Consider standalone go files.
702712
}
703-
t.Run(entry.Name(), func(t *testing.T) {
704-
src, err := fs.ReadFile(fsys, entry.Name())
705-
if err != nil {
706-
t.Fatal(err)
707-
}
708-
709-
// Only build test files that can be compiled, or compiled and run.
710-
if !bytes.HasPrefix(src, []byte("// run")) && !bytes.HasPrefix(src, []byte("// compile")) {
711-
t.Skipf("not detected as a run test")
712-
}
713+
src, err := fs.ReadFile(fsys, entry.Name())
714+
if err != nil {
715+
t.Fatal(err)
716+
}
717+
// Only build test files that can be compiled, or compiled and run.
718+
if !bytes.HasPrefix(src, []byte("// run")) && !bytes.HasPrefix(src, []byte("// compile")) {
719+
t.Logf("%s: not detected as a run test", entry.Name())
720+
continue
721+
}
713722

714-
t.Logf("Input: %s\n", entry.Name())
723+
filename := fmt.Sprintf("%s/main.go", entry.Name())
724+
overlay[filename] = src
725+
}
715726

716-
_, _ = buildPackage(t, string(src), ssa.SanityCheckFunctions|ssa.InstantiateGenerics)
727+
// load all packages inside the overlay so 'go list' will be triggered only once.
728+
pkgs := loadPackages(t, overlayFS(overlay), "./...")
729+
for _, p := range pkgs {
730+
originFilename := filepath.Base(filepath.Dir(p.GoFiles[0]))
731+
t.Run(originFilename, func(t *testing.T) {
732+
t.Parallel()
733+
prog, _ := ssautil.Packages([]*packages.Package{p}, ssa.SanityCheckFunctions|ssa.InstantiateGenerics)
734+
prog.Package(p.Types).Build()
717735
})
718736
}
719737
}

0 commit comments

Comments
 (0)