259 lines
6.4 KiB
Go
259 lines
6.4 KiB
Go
package test
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"os/exec"
|
|
"path"
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/golangci/golangci-lint/pkg/exitcodes"
|
|
"github.com/golangci/golangci-lint/test/testshared"
|
|
)
|
|
|
|
func TestSourcesFromTestdataWithIssuesDir(t *testing.T) {
|
|
testSourcesFromDir(t, testdataDir)
|
|
}
|
|
|
|
func TestTypecheck(t *testing.T) {
|
|
testSourcesFromDir(t, filepath.Join(testdataDir, "notcompiles"))
|
|
}
|
|
|
|
func testSourcesFromDir(t *testing.T, dir string) {
|
|
t.Helper()
|
|
|
|
t.Log(filepath.Join(dir, "*.go"))
|
|
|
|
findSources := func(pathPatterns ...string) []string {
|
|
sources, err := filepath.Glob(filepath.Join(pathPatterns...))
|
|
require.NoError(t, err)
|
|
require.NotEmpty(t, sources)
|
|
return sources
|
|
}
|
|
sources := findSources(dir, "*.go")
|
|
|
|
testshared.InstallGolangciLint(t)
|
|
|
|
for _, s := range sources {
|
|
s := s
|
|
t.Run(filepath.Base(s), func(subTest *testing.T) {
|
|
subTest.Parallel()
|
|
testOneSource(subTest, s)
|
|
})
|
|
}
|
|
}
|
|
|
|
func testOneSource(t *testing.T, sourcePath string) {
|
|
t.Helper()
|
|
|
|
args := []string{
|
|
"--allow-parallel-runners",
|
|
"--disable-all",
|
|
"--print-issued-lines=false",
|
|
"--out-format=line-number",
|
|
"--max-same-issues=100",
|
|
}
|
|
|
|
rc := testshared.ParseTestDirectives(t, sourcePath)
|
|
if rc == nil {
|
|
t.Skipf("Skipped: %s", sourcePath)
|
|
}
|
|
|
|
for _, addArg := range []string{"", "-Etypecheck"} {
|
|
caseArgs := append([]string{}, args...)
|
|
|
|
if addArg != "" {
|
|
caseArgs = append(caseArgs, addArg)
|
|
}
|
|
|
|
files := []string{sourcePath}
|
|
|
|
runner := testshared.NewRunnerBuilder(t).
|
|
WithNoParallelRunners().
|
|
WithArgs(caseArgs...).
|
|
WithRunContext(rc).
|
|
WithTargetPath(sourcePath).
|
|
Runner()
|
|
|
|
output, err := runner.RawRun()
|
|
// The returned error will be nil if the test file does not have any issues
|
|
// and thus the linter exits with exit code 0.
|
|
// So perform the additional assertions only if the error is non-nil.
|
|
if err != nil {
|
|
var exitErr *exec.ExitError
|
|
require.ErrorAs(t, err, &exitErr)
|
|
require.Equal(t, exitcodes.IssuesFound, exitErr.ExitCode(), "Unexpected exit code: %s", string(output))
|
|
}
|
|
|
|
fullshort := make([]string, 0, len(files)*2)
|
|
for _, f := range files {
|
|
fullshort = append(fullshort, f, filepath.Base(f))
|
|
}
|
|
|
|
err = errorCheck(string(output), false, rc.ExpectedLinter, fullshort...)
|
|
require.NoError(t, err)
|
|
}
|
|
}
|
|
|
|
func TestMultipleOutputs(t *testing.T) {
|
|
sourcePath := filepath.Join(testdataDir, "gci", "gci.go")
|
|
|
|
testshared.NewRunnerBuilder(t).
|
|
WithArgs(
|
|
"--disable-all",
|
|
"--print-issued-lines=false",
|
|
"--print-linter-name=false",
|
|
"--out-format=line-number,json:stdout",
|
|
).
|
|
WithDirectives(sourcePath).
|
|
WithTargetPath(sourcePath).
|
|
Runner().
|
|
Install().
|
|
Run().
|
|
ExpectHasIssue("testdata/gci/gci.go:8: File is not `gci`-ed").
|
|
ExpectOutputContains(`"Issues":[`)
|
|
}
|
|
|
|
func TestStderrOutput(t *testing.T) {
|
|
sourcePath := filepath.Join(testdataDir, "gci", "gci.go")
|
|
|
|
testshared.NewRunnerBuilder(t).
|
|
WithArgs(
|
|
"--disable-all",
|
|
"--print-issued-lines=false",
|
|
"--print-linter-name=false",
|
|
"--out-format=line-number,json:stderr",
|
|
).
|
|
WithDirectives(sourcePath).
|
|
WithTargetPath(sourcePath).
|
|
Runner().
|
|
Install().
|
|
Run().
|
|
ExpectHasIssue("testdata/gci/gci.go:8: File is not `gci`-ed").
|
|
ExpectOutputContains(`"Issues":[`)
|
|
}
|
|
|
|
func TestFileOutput(t *testing.T) {
|
|
resultPath := path.Join(t.TempDir(), "golangci_lint_test_result")
|
|
|
|
sourcePath := filepath.Join(testdataDir, "gci", "gci.go")
|
|
|
|
testshared.NewRunnerBuilder(t).
|
|
WithArgs(
|
|
"--disable-all",
|
|
"--print-issued-lines=false",
|
|
"--print-linter-name=false",
|
|
fmt.Sprintf("--out-format=json:%s,line-number", resultPath),
|
|
).
|
|
WithDirectives(sourcePath).
|
|
WithTargetPath(sourcePath).
|
|
Runner().
|
|
Install().
|
|
Run().
|
|
ExpectHasIssue("testdata/gci/gci.go:8: File is not `gci`-ed").
|
|
ExpectOutputNotContains(`"Issues":[`)
|
|
|
|
b, err := os.ReadFile(resultPath)
|
|
require.NoError(t, err)
|
|
require.Contains(t, string(b), `"Issues":[`)
|
|
}
|
|
|
|
func TestLinter_goimports_local(t *testing.T) {
|
|
sourcePath := filepath.Join(testdataDir, "goimports", "goimports.go")
|
|
|
|
testshared.NewRunnerBuilder(t).
|
|
WithArgs(
|
|
"--disable-all",
|
|
"--print-issued-lines=false",
|
|
"--print-linter-name=false",
|
|
"--out-format=line-number",
|
|
).
|
|
WithDirectives(sourcePath).
|
|
WithTargetPath(sourcePath).
|
|
Runner().
|
|
Install().
|
|
Run().
|
|
ExpectHasIssue("testdata/goimports/goimports.go:8: File is not `goimports`-ed")
|
|
}
|
|
|
|
func TestLinter_gci_Local(t *testing.T) {
|
|
sourcePath := filepath.Join(testdataDir, "gci", "gci.go")
|
|
|
|
testshared.NewRunnerBuilder(t).
|
|
WithArgs(
|
|
"--disable-all",
|
|
"--print-issued-lines=false",
|
|
"--print-linter-name=false",
|
|
"--out-format=line-number",
|
|
).
|
|
WithDirectives(sourcePath).
|
|
WithTargetPath(sourcePath).
|
|
Runner().
|
|
Install().
|
|
Run().
|
|
ExpectHasIssue("testdata/gci/gci.go:8: File is not `gci`-ed")
|
|
}
|
|
|
|
// TODO(ldez) need to be converted to a classic linter test.
|
|
func TestLinter_tparallel(t *testing.T) {
|
|
testCases := []struct {
|
|
desc string
|
|
sourcePath string
|
|
expected func(result *testshared.RunnerResult)
|
|
}{
|
|
{
|
|
desc: "should fail on missing top-level Parallel()",
|
|
sourcePath: filepath.Join(testdataDir, "tparallel", "missing_toplevel_test.go"),
|
|
expected: func(result *testshared.RunnerResult) {
|
|
result.ExpectHasIssue(
|
|
"testdata/tparallel/missing_toplevel_test.go:7:6: TestTopLevel should call t.Parallel on the top level as well as its subtests\n",
|
|
)
|
|
},
|
|
},
|
|
{
|
|
desc: "should fail on missing subtest Parallel()",
|
|
sourcePath: filepath.Join(testdataDir, "tparallel", "missing_subtest_test.go"),
|
|
expected: func(result *testshared.RunnerResult) {
|
|
result.ExpectHasIssue(
|
|
"testdata/tparallel/missing_subtest_test.go:7:6: TestSubtests's subtests should call t.Parallel\n",
|
|
)
|
|
},
|
|
},
|
|
{
|
|
desc: "should pass on parallel test with no subtests",
|
|
sourcePath: filepath.Join(testdataDir, "tparallel", "happy_path_test.go"),
|
|
expected: func(result *testshared.RunnerResult) {
|
|
result.ExpectNoIssues()
|
|
},
|
|
},
|
|
}
|
|
|
|
testshared.InstallGolangciLint(t)
|
|
|
|
for _, test := range testCases {
|
|
test := test
|
|
t.Run(test.desc, func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
result := testshared.NewRunnerBuilder(t).
|
|
WithDirectives(test.sourcePath).
|
|
WithArgs(
|
|
"--disable-all",
|
|
"--enable",
|
|
"tparallel",
|
|
"--print-issued-lines=false",
|
|
"--print-linter-name=false",
|
|
"--out-format=line-number",
|
|
).
|
|
WithTargetPath(test.sourcePath).
|
|
Runner().
|
|
Run()
|
|
|
|
test.expected(result)
|
|
})
|
|
}
|
|
}
|