Skip to content

Add a test runner in module mode #431

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 15 additions & 9 deletions go/analysis/analysistest/analysistest.go
Original file line number Diff line number Diff line change
Expand Up @@ -240,12 +240,11 @@ func RunWithSuggestedFixes(t Testing, dir string, a *analysis.Analyzer, patterns
return r
}

// Run applies an analysis to the packages denoted by the "go list" patterns.
// RunModule applies an analysis to the packages denoted by the "go list" patterns.
//
// It loads the packages from the specified GOPATH-style project
// directory using golang.org/x/tools/go/packages, runs the analysis on
// them, and checks that each analysis emits the expected diagnostics
// and facts specified by the contents of '// want ...' comments in the
// It loads the packages from the module using golang.org/x/tools/go/packages,
// runs the analysis on them, and checks that each analysis emits the expected
// diagnostics and facts specified by the contents of '// want ...' comments in the
// package's source files. It treats a comment of the form
// "//...// want..." or "/*...// want... */" as if it starts at 'want'
//
Expand Down Expand Up @@ -278,7 +277,7 @@ func RunWithSuggestedFixes(t Testing, dir string, a *analysis.Analyzer, patterns
// Run also returns a Result for each package for which analysis was
// attempted, even if unsuccessful. It is safe for a test to ignore all
// the results, but a test may use it to perform additional checks.
func Run(t Testing, dir string, a *analysis.Analyzer, patterns ...string) []*Result {
func RunModule(t Testing, dir string, a *analysis.Analyzer, patterns ...string) []*Result {
if t, ok := t.(testing.TB); ok {
testenv.NeedsGoPackages(t)
}
Expand All @@ -300,12 +299,20 @@ func Run(t Testing, dir string, a *analysis.Analyzer, patterns ...string) []*Res
return results
}

// Run applies an analysis to the packages denoted by the "go list" patterns.
// It performs the same analysis as [RunModule], but uses GOPATH instead.
func Run(t Testing, dir string, a *analysis.Analyzer, patterns ...string) []*Result {
os.Setenv("GOPATH", dir)
os.Setenv("GO111MODULE", "off")
os.Setenv("GOPROXY", "off")
return RunModule(t, dir, a, patterns...)
}

// A Result holds the result of applying an analyzer to a package.
type Result = checker.TestAnalyzerResult

// loadPackages uses go/packages to load a specified packages (from source, with
// dependencies) from dir, which is the root of a GOPATH-style project
// tree. It returns an error if any package had an error, or the pattern
// dependencies) from dir. It returns an error if any package had an error, or the pattern
// matched no packages.
func loadPackages(a *analysis.Analyzer, dir string, patterns ...string) ([]*packages.Package, error) {
// packages.Load loads the real standard library, not a minimal
Expand All @@ -322,7 +329,6 @@ func loadPackages(a *analysis.Analyzer, dir string, patterns ...string) ([]*pack
Mode: mode,
Dir: dir,
Tests: true,
Env: append(os.Environ(), "GOPATH="+dir, "GO111MODULE=off", "GOPROXY=off"),
}
pkgs, err := packages.Load(cfg, patterns...)
if err != nil {
Expand Down
25 changes: 16 additions & 9 deletions go/analysis/analysistest/analysistest_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,32 +6,30 @@ package analysistest_test

import (
"fmt"
"log"
"os"
"reflect"
"strings"
"testing"

"golang.org/x/tools/go/analysis"
"golang.org/x/tools/go/analysis/analysistest"
"golang.org/x/tools/go/analysis/passes/findcall"
"golang.org/x/tools/internal/testenv"
)

func init() {
// TestTheTest tests the analysistest testing infrastructure.
func TestTheTest(t *testing.T) {
testenv.NeedsTool(t, "go")

// This test currently requires GOPATH mode.
// Explicitly disabling module mode should suffice, but
// we'll also turn off GOPROXY just for good measure.
if err := os.Setenv("GO111MODULE", "off"); err != nil {
log.Fatal(err)
t.Fatal(err)
}
if err := os.Setenv("GOPROXY", "off"); err != nil {
log.Fatal(err)
t.Fatal(err)
}
}

// TestTheTest tests the analysistest testing infrastructure.
func TestTheTest(t *testing.T) {
testenv.NeedsTool(t, "go")

// We'll simulate a partly failing test of the findcall analysis,
// which (by default) reports calls to functions named 'println'.
Expand Down Expand Up @@ -160,3 +158,12 @@ type errorfunc func(string)
func (f errorfunc) Errorf(format string, args ...interface{}) {
f(fmt.Sprintf(format, args...))
}

func TestModule(t *testing.T) {
// the analyzer does nothing, but it will fail if the module cannot be loaded
var happyAnalyzer = &analysis.Analyzer{
Name: "happy",
Run: func(p *analysis.Pass) (interface{}, error) { return nil, nil }}

analysistest.RunModule(t, analysistest.TestData(), happyAnalyzer, "golang.org/x/tools/go/analysis/analysistest/testdata/mod")
}
1 change: 1 addition & 0 deletions go/analysis/analysistest/testdata/mod/mod.go
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package mod