Add tparallel linter (#1380)
This commit is contained in:
parent
c88841dac4
commit
926e76dcf2
1
go.mod
1
go.mod
@ -34,6 +34,7 @@ require (
|
||||
github.com/mattn/go-colorable v0.1.7
|
||||
github.com/mitchellh/go-homedir v1.1.0
|
||||
github.com/mitchellh/go-ps v1.0.0
|
||||
github.com/moricho/tparallel v0.2.1
|
||||
github.com/nakabonne/nestif v0.3.0
|
||||
github.com/nishanths/exhaustive v0.0.0-20200811152831-6cf413ae40e0
|
||||
github.com/pkg/errors v0.9.1
|
||||
|
11
go.sum
generated
11
go.sum
generated
@ -68,6 +68,7 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9
|
||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||
github.com/go-ole/go-ole v1.2.1 h1:2lOsA72HgjxAuMlKpFiCbHTvu44PIVkZ5hqm3RSdI/E=
|
||||
github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8=
|
||||
github.com/go-sql-driver/mysql v1.4.0 h1:7LxgVwFb2hIQtMm87NdgAVfXjnt4OePseqT1tKx+opk=
|
||||
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/go-toolsmith/astcast v1.0.0 h1:JojxlmI6STnFVG9yOImLeGREv8W2ocNUM+iOhR6jE7g=
|
||||
@ -162,6 +163,10 @@ github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/ad
|
||||
github.com/gostaticanalysis/analysisutil v0.0.0-20190318220348-4088753ea4d3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE=
|
||||
github.com/gostaticanalysis/analysisutil v0.0.3 h1:iwp+5/UAyzQSFgQ4uR2sni99sJ8Eo9DEacKWM5pekIg=
|
||||
github.com/gostaticanalysis/analysisutil v0.0.3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE=
|
||||
github.com/gostaticanalysis/analysisutil v0.1.0 h1:E4c8Y1EQURbBEAHoXc/jBTK7Np14ArT8NPUiSFOl9yc=
|
||||
github.com/gostaticanalysis/analysisutil v0.1.0/go.mod h1:dMhHRU9KTiDcuLGdy87/2gTR8WruwYZrKdRq9m1O6uw=
|
||||
github.com/gostaticanalysis/comment v1.3.0 h1:wTVgynbFu8/nz6SGgywA0TcyIoAVsYc7ai/Zp5xNGlw=
|
||||
github.com/gostaticanalysis/comment v1.3.0/go.mod h1:xMicKDx7XRXYdVwY9f9wQpDJVnqWxw9wCauCMKp+IBI=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||
@ -194,6 +199,7 @@ github.com/jingyugao/rowserrcheck v0.0.0-20191204022205-72ab7603b68a/go.mod h1:x
|
||||
github.com/jirfag/go-printf-func-name v0.0.0-20191110105641-45db9963cdd3 h1:jNYPNLe3d8smommaoQlK7LOA5ESyUJJ+Wf79ZtA7Vp4=
|
||||
github.com/jirfag/go-printf-func-name v0.0.0-20191110105641-45db9963cdd3/go.mod h1:HEWGJkRDzjJY2sqdDwxccsGicWEf9BQOZsq2tV+xzM0=
|
||||
github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks=
|
||||
github.com/jmoiron/sqlx v1.2.1-0.20190826204134-d7d95172beb5 h1:lrdPtrORjGv1HbbEvKWDUAy97mPpFm4B8hp77tcCUJY=
|
||||
github.com/jmoiron/sqlx v1.2.1-0.20190826204134-d7d95172beb5/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks=
|
||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
@ -252,6 +258,8 @@ github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQz
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/moricho/tparallel v0.2.1 h1:95FytivzT6rYzdJLdtfn6m1bfFJylOJK41+lgv/EHf4=
|
||||
github.com/moricho/tparallel v0.2.1/go.mod h1:fXEIZxG2vdfl0ZF8b42f5a78EhjjD5mX8qUplsoSU4k=
|
||||
github.com/mozilla/tls-observatory v0.0.0-20200317151703-4fa42e1c2dee/go.mod h1:SrKMQvPiws7F7iqYp8/TX+IhxCYhzr6N/1yb8cwHsGk=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/nakabonne/nestif v0.3.0 h1:+yOViDGhg8ygGrmII72nV9B/zGxY188TYpfolntsaPw=
|
||||
@ -492,6 +500,7 @@ golang.org/x/tools v0.0.0-20190110163146-51295c7ec13a/go.mod h1:n7NCudcB/nEzxVGm
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190221204921-83362c3779f5/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190307163923-6a08e3108db3/go.mod h1:25r3+/G6/xytQM8iWZKq3Hn0kr0rgFKPUNVEL/dr3z4=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190311215038-5c2858a9cfe5/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
@ -518,11 +527,13 @@ golang.org/x/tools v0.0.0-20200414032229-332987a829c3/go.mod h1:EkVYQZoAsY45+roY
|
||||
golang.org/x/tools v0.0.0-20200422022333-3d57cf2e726e/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200426102838-f3a5411a4c3b/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200519015757-0d0afa43d58a/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200624225443-88f3c62a19ff/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200625211823-6506e20df31f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200701041122-1837592efa10/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200724022722-7017fd6b1305/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200731060945-b5fad4ed8dd6/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200812195022-5ae4c3c160a0/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200831203904-5a2aa26beb65/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
|
||||
golang.org/x/tools v0.0.0-20200918232735-d647fc253266 h1:k7tVuG0g1JwmD3Jh8oAl1vQ1C3jb4Hi/dUl1wWDBJpQ=
|
||||
golang.org/x/tools v0.0.0-20200918232735-d647fc253266/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
21
pkg/golinters/tparallel.go
Normal file
21
pkg/golinters/tparallel.go
Normal file
@ -0,0 +1,21 @@
|
||||
package golinters
|
||||
|
||||
import (
|
||||
"github.com/moricho/tparallel"
|
||||
"golang.org/x/tools/go/analysis"
|
||||
|
||||
"github.com/golangci/golangci-lint/pkg/golinters/goanalysis"
|
||||
)
|
||||
|
||||
func NewTparallel() *goanalysis.Linter {
|
||||
analyzers := []*analysis.Analyzer{
|
||||
tparallel.Analyzer,
|
||||
}
|
||||
|
||||
return goanalysis.NewLinter(
|
||||
"tparallel",
|
||||
"tparallel detects inappropriate usage of t.Parallel() method in your Go test codes",
|
||||
analyzers,
|
||||
nil,
|
||||
).WithLoadMode(goanalysis.LoadModeTypesInfo)
|
||||
}
|
@ -56,8 +56,10 @@ func (m *Manager) WithCustomLinters() *Manager {
|
||||
}
|
||||
|
||||
func (Manager) AllPresets() []string {
|
||||
return []string{linter.PresetBugs, linter.PresetComplexity, linter.PresetFormatting,
|
||||
linter.PresetPerformance, linter.PresetStyle, linter.PresetUnused}
|
||||
return []string{
|
||||
linter.PresetBugs, linter.PresetComplexity, linter.PresetFormatting,
|
||||
linter.PresetPerformance, linter.PresetStyle, linter.PresetUnused,
|
||||
}
|
||||
}
|
||||
|
||||
func (m Manager) allPresetsSet() map[string]bool {
|
||||
@ -305,6 +307,10 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config {
|
||||
WithPresets(linter.PresetStyle).
|
||||
WithLoadForGoAnalysis().
|
||||
WithURL("https://github.com/ssgreg/nlreturn"),
|
||||
linter.NewConfig(golinters.NewTparallel()).
|
||||
WithPresets(linter.PresetStyle).
|
||||
WithLoadForGoAnalysis().
|
||||
WithURL("https://github.com/moricho/tparallel"),
|
||||
// nolintlint must be last because it looks at the results of all the previous linters for unused nolint directives
|
||||
linter.NewConfig(golinters.NewNoLintLint()).
|
||||
WithPresets(linter.PresetStyle).
|
||||
|
@ -252,11 +252,55 @@ func TestExtractRunContextFromComments(t *testing.T) {
|
||||
assert.Equal(t, []string{"-Egoimports"}, rc.args)
|
||||
}
|
||||
|
||||
func TestGolintConsumesXTestFiles(t *testing.T) {
|
||||
dir := getTestDataDir("withxtest")
|
||||
const expIssue = "`if` block ends with a `return` statement, so drop this `else` and outdent its block"
|
||||
func TestTparallel(t *testing.T) {
|
||||
t.Run("should fail on missing top-level Parallel()", func(t *testing.T) {
|
||||
sourcePath := filepath.Join(testdataDir, "tparallel", "missing_toplevel_test.go")
|
||||
args := []string{
|
||||
"--disable-all", "--print-issued-lines=false", "--print-linter-name=false", "--out-format=line-number", "--enable", "tparallel",
|
||||
sourcePath,
|
||||
}
|
||||
rc := extractRunContextFromComments(t, sourcePath)
|
||||
args = append(args, rc.args...)
|
||||
|
||||
r := testshared.NewLintRunner(t)
|
||||
r.Run("--no-config", "--disable-all", "-Egolint", dir).ExpectHasIssue(expIssue)
|
||||
r.Run("--no-config", "--disable-all", "-Egolint", filepath.Join(dir, "p_test.go")).ExpectHasIssue(expIssue)
|
||||
cfg, err := yaml.Marshal(rc.config)
|
||||
assert.NoError(t, err)
|
||||
|
||||
testshared.NewLintRunner(t).RunWithYamlConfig(string(cfg), args...).
|
||||
ExpectHasIssue(
|
||||
"testdata/tparallel/missing_toplevel_test.go:7:6: TestTopLevel should call t.Parallel on the top level as well as its subtests\n",
|
||||
)
|
||||
})
|
||||
|
||||
t.Run("should fail on missing subtest Parallel()", func(t *testing.T) {
|
||||
sourcePath := filepath.Join(testdataDir, "tparallel", "missing_subtest_test.go")
|
||||
args := []string{
|
||||
"--disable-all", "--print-issued-lines=false", "--print-linter-name=false", "--out-format=line-number", "--enable", "tparallel",
|
||||
sourcePath,
|
||||
}
|
||||
rc := extractRunContextFromComments(t, sourcePath)
|
||||
args = append(args, rc.args...)
|
||||
|
||||
cfg, err := yaml.Marshal(rc.config)
|
||||
assert.NoError(t, err)
|
||||
|
||||
testshared.NewLintRunner(t).RunWithYamlConfig(string(cfg), args...).
|
||||
ExpectHasIssue(
|
||||
"testdata/tparallel/missing_subtest_test.go:7:6: TestSubtests's subtests should call t.Parallel\n",
|
||||
)
|
||||
})
|
||||
|
||||
t.Run("should pass on parallel test with no subtests", func(t *testing.T) {
|
||||
sourcePath := filepath.Join(testdataDir, "tparallel", "happy_path_test.go")
|
||||
args := []string{
|
||||
"--disable-all", "--print-issued-lines=false", "--print-linter-name=false", "--out-format=line-number", "--enable", "tparallel",
|
||||
sourcePath,
|
||||
}
|
||||
rc := extractRunContextFromComments(t, sourcePath)
|
||||
args = append(args, rc.args...)
|
||||
|
||||
cfg, err := yaml.Marshal(rc.config)
|
||||
assert.NoError(t, err)
|
||||
|
||||
testshared.NewLintRunner(t).RunWithYamlConfig(string(cfg), args...).ExpectNoIssues()
|
||||
})
|
||||
}
|
||||
|
16
test/testdata/tparallel/happy_path_test.go
vendored
Normal file
16
test/testdata/tparallel/happy_path_test.go
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
package testdata
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestValidHappyPath(t *testing.T) {
|
||||
t.Parallel()
|
||||
t.Run("", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
})
|
||||
}
|
||||
|
||||
func TestValidNoSubTest(t *testing.T) {
|
||||
t.Parallel()
|
||||
}
|
12
test/testdata/tparallel/missing_subtest_test.go
vendored
Normal file
12
test/testdata/tparallel/missing_subtest_test.go
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
package testdata
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSubtests(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
t.Run("", func(t *testing.T) {
|
||||
})
|
||||
}
|
11
test/testdata/tparallel/missing_toplevel_test.go
vendored
Normal file
11
test/testdata/tparallel/missing_toplevel_test.go
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
package testdata
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestTopLevel(t *testing.T) {
|
||||
t.Run("", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
})
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user