diff --git a/.golangci.example.yml b/.golangci.example.yml index 496cb5e485b2..d8cd938dbcde 100644 --- a/.golangci.example.yml +++ b/.golangci.example.yml @@ -627,6 +627,11 @@ linters-settings: name: true begin: true + tenv: + # The option `all` will run against whole test files (`_test.go`) regardless of method/function signatures. + # By default, only methods that take `*testing.T`, `*testing.B`, and `testing.TB` as arguments are checked. + all: false + unparam: # Inspect exported functions, default is false. Set to true if no external program/library imports your code. # XXX: if you enable this setting, unparam will report a lot of false-positives in text editors: diff --git a/go.mod b/go.mod index 449fb85dc3df..1189ca90a29c 100644 --- a/go.mod +++ b/go.mod @@ -69,6 +69,7 @@ require ( github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c github.com/shirou/gopsutil/v3 v3.21.8 github.com/sirupsen/logrus v1.8.1 + github.com/sivchari/tenv v1.4.7 github.com/sonatard/noctx v0.0.1 github.com/sourcegraph/go-diff v0.6.1 github.com/spf13/cobra v1.2.1 diff --git a/go.sum b/go.sum index 8733e21d36bc..915ff19e46eb 100644 --- a/go.sum +++ b/go.sum @@ -350,6 +350,8 @@ github.com/gostaticanalysis/forcetypeassert v0.0.0-20200621232751-01d4955beaa5 h github.com/gostaticanalysis/forcetypeassert v0.0.0-20200621232751-01d4955beaa5/go.mod h1:qZEedyP/sY1lTGV1uJ3VhWZ2mqag3IkWsDHVbplHXak= github.com/gostaticanalysis/nilerr v0.1.1 h1:ThE+hJP0fEp4zWLkWHWcRyI2Od0p7DlgYG3Uqrmrcpk= github.com/gostaticanalysis/nilerr v0.1.1/go.mod h1:wZYb6YI5YAxxq0i1+VJbY0s2YONW0HU0GPE3+5PWN4A= +github.com/gostaticanalysis/testutil v0.4.0 h1:nhdCmubdmDF6VEatUNjgUZBJKWRqugoISdUv3PPQgHY= +github.com/gostaticanalysis/testutil v0.4.0/go.mod h1:bLIoPefWXrRi/ssLFWX1dx7Repi5x3CuviD3dgAZaBU= github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= @@ -379,6 +381,8 @@ github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerX github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-version v1.2.1 h1:zEfKbn2+PDgroKdiOzqiE8rsmLqU2uwi5PB5pBJ3TkI= +github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= @@ -414,6 +418,8 @@ github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfC github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/jonboulle/clockwork v0.2.0/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= +github.com/josharian/txtarfs v0.0.0-20210218200122-0702f000015a h1:8NZHLa6Gp0hW6xJ0c3F1Kse7dJw30fOcDzHuF9sLbnE= +github.com/josharian/txtarfs v0.0.0-20210218200122-0702f000015a/go.mod h1:izVPOvVRsHiKkeGCT6tYBNWyDVuzj9wAaBb5R9qamfw= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= @@ -565,6 +571,14 @@ github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1y github.com/onsi/gomega v1.13.0 h1:7lLHu94wT9Ij0o6EWWclhu0aOh32VxhkwEJvzuWPeak= github.com/onsi/gomega v1.13.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/otiai10/copy v1.2.0 h1:HvG945u96iNadPoG2/Ja2+AUJeW5YuFQMixq9yirC+k= +github.com/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw= +github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= +github.com/otiai10/curr v1.0.0 h1:TJIWdbX0B+kpNagQrjgq8bCMrbhiuX73M2XwgtDMoOI= +github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs= +github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo= +github.com/otiai10/mint v1.3.1 h1:BCmzIS3n71sGfHB5NMNDB3lHYPz8fWSkCAErHed//qc= +github.com/otiai10/mint v1.3.1/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= @@ -652,6 +666,9 @@ github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrf github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sivchari/tenv v1.4.7 h1:FdTpgRlTue5eb5nXIYgS/lyVXSjugU8UUVDwhP1NLU8= +github.com/sivchari/tenv v1.4.7/go.mod h1:5nF+bITvkebQVanjU6IuMbvIot/7ReNsUV7I5NbprB0= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= @@ -701,6 +718,10 @@ github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/tdakkota/asciicheck v0.0.0-20200416200610-e657995f937b h1:HxLVTlqcHhFAz3nWUcuvpH7WuOMv8LQoCWmruLfFH2U= github.com/tdakkota/asciicheck v0.0.0-20200416200610-e657995f937b/go.mod h1:yHp0ai0Z9gUljN3o0xMhYJnH/IcvkdTBOX2fmJ93JEM= +github.com/tenntenn/modver v1.0.1 h1:2klLppGhDgzJrScMpkj9Ujy3rXPUspSjAcev9tSEBgA= +github.com/tenntenn/modver v1.0.1/go.mod h1:bePIyQPb7UeioSRkw3Q0XeMhYZSMx9B8ePqg6SAMGH0= +github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3 h1:f+jULpRQGxTSkNYKJ51yaw6ChIqO+Je8UqsTKN/cDag= +github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3/go.mod h1:ON8b8w4BN/kE1EOhwT0o+d62W65a6aPw1nouo9LMgyY= github.com/tetafro/godot v1.4.11 h1:BVoBIqAf/2QdbFmSwAWnaIqDivZdOV0ZRwEm6jivLKw= github.com/tetafro/godot v1.4.11/go.mod h1:LR3CJpxDVGlYOWn3ZZg1PgNZdTUvzsZWu8xaEohUpn8= github.com/timakin/bodyclose v0.0.0-20200424151742-cb6215831a94 h1:ig99OeTyDwQWhPe2iw9lwfQVF1KB3Q4fpP3X7/2VBG8= @@ -1088,6 +1109,7 @@ golang.org/x/tools v0.0.0-20210104081019-d8d6ddbec6ee/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.1-0.20210205202024-ef80cdb6ec6d/go.mod h1:9bzcO0MWcOuT0tm1iBGzDVPshzfwoVvREIui8C+MHqU= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= diff --git a/pkg/config/linters_settings.go b/pkg/config/linters_settings.go index 9ef297f9c35f..c32f2570706a 100644 --- a/pkg/config/linters_settings.go +++ b/pkg/config/linters_settings.go @@ -132,6 +132,7 @@ type LintersSettings struct { Tagliatelle TagliatelleSettings Testpackage TestpackageSettings Thelper ThelperSettings + Tenv TenvSettings Unparam UnparamSettings Unused StaticCheckSettings Varcheck VarCheckSettings @@ -463,6 +464,10 @@ type ThelperSettings struct { } `mapstructure:"tb"` } +type TenvSettings struct { + All bool `mapstructure:"all"` +} + type UnparamSettings struct { CheckExported bool `mapstructure:"check-exported"` Algo string diff --git a/pkg/golinters/tenv.go b/pkg/golinters/tenv.go new file mode 100644 index 000000000000..8e3e9c61f601 --- /dev/null +++ b/pkg/golinters/tenv.go @@ -0,0 +1,33 @@ +package golinters + +import ( + "github.com/sivchari/tenv" + "golang.org/x/tools/go/analysis" + + "github.com/golangci/golangci-lint/pkg/config" + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" +) + +func NewTenv(settings *config.TenvSettings) *goanalysis.Linter { + a := tenv.Analyzer + + analyzers := []*analysis.Analyzer{ + a, + } + + var cfg map[string]map[string]interface{} + if settings != nil { + cfg = map[string]map[string]interface{}{ + a.Name: { + tenv.A: settings.All, + }, + } + } + + return goanalysis.NewLinter( + a.Name, + a.Doc, + analyzers, + cfg, + ).WithLoadMode(goanalysis.LoadModeSyntax) +} diff --git a/pkg/lint/lintersdb/manager.go b/pkg/lint/lintersdb/manager.go index ecc2efec97e3..e8fd7dd0e626 100644 --- a/pkg/lint/lintersdb/manager.go +++ b/pkg/lint/lintersdb/manager.go @@ -116,6 +116,7 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config { var staticcheckCfg *config.StaticCheckSettings var stylecheckCfg *config.StaticCheckSettings var tagliatelleCfg *config.TagliatelleSettings + var tenvCfg *config.TenvSettings var testpackageCfg *config.TestpackageSettings var thelperCfg *config.ThelperSettings var unusedCfg *config.StaticCheckSettings @@ -140,6 +141,7 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config { staticcheckCfg = &m.cfg.LintersSettings.Staticcheck stylecheckCfg = &m.cfg.LintersSettings.Stylecheck tagliatelleCfg = &m.cfg.LintersSettings.Tagliatelle + tenvCfg = &m.cfg.LintersSettings.Tenv testpackageCfg = &m.cfg.LintersSettings.Testpackage thelperCfg = &m.cfg.LintersSettings.Thelper unusedCfg = &m.cfg.LintersSettings.Unused @@ -522,6 +524,11 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config { WithLoadForGoAnalysis(). WithURL("https://github.com/Antonboom/nilnil"). WithSince("v1.43.0"), + linter.NewConfig(golinters.NewTenv(tenvCfg)). + WithSince("v1.43.0"). + WithPresets(linter.PresetStyle). + WithLoadForGoAnalysis(). + WithURL("https://github.com/sivchari/tenv"), // nolintlint must be last because it looks at the results of all the previous linters for unused nolint directives linter.NewConfig(golinters.NewNoLintLint()). diff --git a/test/testdata/configs/tenv_all.yml b/test/testdata/configs/tenv_all.yml new file mode 100644 index 000000000000..f0ae4fd226c4 --- /dev/null +++ b/test/testdata/configs/tenv_all.yml @@ -0,0 +1,3 @@ +linters-settings: + tenv: + all: true diff --git a/test/testdata/tenv.go b/test/testdata/tenv.go new file mode 100644 index 000000000000..45bebd129ba1 --- /dev/null +++ b/test/testdata/tenv.go @@ -0,0 +1,48 @@ +// args: -Etenv +// config_path: testdata/configs/tenv_all.yml +package testdata + +import ( + "os" + "testing" +) + +var ( + e = os.Setenv("a", "b") // never seen +) + +func setup() { + os.Setenv("a", "b") // never seen + err := os.Setenv("a", "b") // never seen + _ = err + if err := os.Setenv("a", "b"); err != nil { // never seen + _ = err + } +} + +func TestF(t *testing.T) { + os.Setenv("a", "b") // ERROR "os\\.Setenv\\(\\) can be replaced by `t\\.Setenv\\(\\)` in TestF" + err := os.Setenv("a", "b") // ERROR "os\\.Setenv\\(\\) can be replaced by `t\\.Setenv\\(\\)` in TestF" + _ = err + if err := os.Setenv("a", "b"); err != nil { // ERROR "os\\.Setenv\\(\\) can be replaced by `t\\.Setenv\\(\\)` in TestF" + _ = err + } +} + +func BenchmarkF(b *testing.B) { + os.Setenv("a", "b") // ERROR "os\\.Setenv\\(\\) can be replaced by `b\\.Setenv\\(\\)` in BenchmarkF" + err := os.Setenv("a", "b") // ERROR "os\\.Setenv\\(\\) can be replaced by `b\\.Setenv\\(\\)` in BenchmarkF" + _ = err + if err := os.Setenv("a", "b"); err != nil { // ERROR "os\\.Setenv\\(\\) can be replaced by `b\\.Setenv\\(\\)` in BenchmarkF" + _ = err + } +} + +func testTB(tb testing.TB) { + os.Setenv("a", "b") // ERROR "os\\.Setenv\\(\\) can be replaced by `tb\\.Setenv\\(\\)` in testTB" + err := os.Setenv("a", "b") // ERROR "os\\.Setenv\\(\\) can be replaced by `tb\\.Setenv\\(\\)` in testTB" + _ = err + if err := os.Setenv("a", "b"); err != nil { // ERROR "os\\.Setenv\\(\\) can be replaced by `tb\\.Setenv\\(\\)` in testTB" + _ = err + } +} diff --git a/test/testdata/tenv_all.go b/test/testdata/tenv_all.go new file mode 100644 index 000000000000..45bebd129ba1 --- /dev/null +++ b/test/testdata/tenv_all.go @@ -0,0 +1,48 @@ +// args: -Etenv +// config_path: testdata/configs/tenv_all.yml +package testdata + +import ( + "os" + "testing" +) + +var ( + e = os.Setenv("a", "b") // never seen +) + +func setup() { + os.Setenv("a", "b") // never seen + err := os.Setenv("a", "b") // never seen + _ = err + if err := os.Setenv("a", "b"); err != nil { // never seen + _ = err + } +} + +func TestF(t *testing.T) { + os.Setenv("a", "b") // ERROR "os\\.Setenv\\(\\) can be replaced by `t\\.Setenv\\(\\)` in TestF" + err := os.Setenv("a", "b") // ERROR "os\\.Setenv\\(\\) can be replaced by `t\\.Setenv\\(\\)` in TestF" + _ = err + if err := os.Setenv("a", "b"); err != nil { // ERROR "os\\.Setenv\\(\\) can be replaced by `t\\.Setenv\\(\\)` in TestF" + _ = err + } +} + +func BenchmarkF(b *testing.B) { + os.Setenv("a", "b") // ERROR "os\\.Setenv\\(\\) can be replaced by `b\\.Setenv\\(\\)` in BenchmarkF" + err := os.Setenv("a", "b") // ERROR "os\\.Setenv\\(\\) can be replaced by `b\\.Setenv\\(\\)` in BenchmarkF" + _ = err + if err := os.Setenv("a", "b"); err != nil { // ERROR "os\\.Setenv\\(\\) can be replaced by `b\\.Setenv\\(\\)` in BenchmarkF" + _ = err + } +} + +func testTB(tb testing.TB) { + os.Setenv("a", "b") // ERROR "os\\.Setenv\\(\\) can be replaced by `tb\\.Setenv\\(\\)` in testTB" + err := os.Setenv("a", "b") // ERROR "os\\.Setenv\\(\\) can be replaced by `tb\\.Setenv\\(\\)` in testTB" + _ = err + if err := os.Setenv("a", "b"); err != nil { // ERROR "os\\.Setenv\\(\\) can be replaced by `tb\\.Setenv\\(\\)` in testTB" + _ = err + } +} diff --git a/test/testdata/tenv_all_test.go b/test/testdata/tenv_all_test.go new file mode 100644 index 000000000000..c870c29ba0dd --- /dev/null +++ b/test/testdata/tenv_all_test.go @@ -0,0 +1,48 @@ +// args: -Etenv +// config_path: testdata/configs/tenv_all.yml +package testdata + +import ( + "os" + "testing" +) + +var ( + e = os.Setenv("a", "b") // never seen +) + +func setup() { + os.Setenv("a", "b") // ERROR "os\\.Setenv\\(\\) can be replaced by `testing\\.Setenv\\(\\)` in setup" + err := os.Setenv("a", "b") // ERROR "os\\.Setenv\\(\\) can be replaced by `testing\\.Setenv\\(\\)` in setup" + _ = err + if err := os.Setenv("a", "b"); err != nil { // ERROR "os\\.Setenv\\(\\) can be replaced by `testing\\.Setenv\\(\\)` in setup" + _ = err + } +} + +func TestF(t *testing.T) { + os.Setenv("a", "b") // ERROR "os\\.Setenv\\(\\) can be replaced by `t\\.Setenv\\(\\)` in TestF" + err := os.Setenv("a", "b") // ERROR "os\\.Setenv\\(\\) can be replaced by `t\\.Setenv\\(\\)` in TestF" + _ = err + if err := os.Setenv("a", "b"); err != nil { // ERROR "os\\.Setenv\\(\\) can be replaced by `t\\.Setenv\\(\\)` in TestF" + _ = err + } +} + +func BenchmarkF(b *testing.B) { + os.Setenv("a", "b") // ERROR "os\\.Setenv\\(\\) can be replaced by `b\\.Setenv\\(\\)` in BenchmarkF" + err := os.Setenv("a", "b") // ERROR "os\\.Setenv\\(\\) can be replaced by `b\\.Setenv\\(\\)` in BenchmarkF" + _ = err + if err := os.Setenv("a", "b"); err != nil { // ERROR "os\\.Setenv\\(\\) can be replaced by `b\\.Setenv\\(\\)` in BenchmarkF" + _ = err + } +} + +func testTB(tb testing.TB) { + os.Setenv("a", "b") // ERROR "os\\.Setenv\\(\\) can be replaced by `tb\\.Setenv\\(\\)` in testTB" + err := os.Setenv("a", "b") // ERROR "os\\.Setenv\\(\\) can be replaced by `tb\\.Setenv\\(\\)` in testTB" + _ = err + if err := os.Setenv("a", "b"); err != nil { // ERROR "os\\.Setenv\\(\\) can be replaced by `tb\\.Setenv\\(\\)` in testTB" + _ = err + } +} diff --git a/test/testdata/tenv_test.go b/test/testdata/tenv_test.go new file mode 100644 index 000000000000..03977d482d8c --- /dev/null +++ b/test/testdata/tenv_test.go @@ -0,0 +1,47 @@ +// args: -Etenv +package testdata + +import ( + "os" + "testing" +) + +var ( + e = os.Setenv("a", "b") // never seen +) + +func setup() { + os.Setenv("a", "b") // OK + err := os.Setenv("a", "b") // OK + _ = err + if err := os.Setenv("a", "b"); err != nil { // OK + _ = err + } +} + +func TestF(t *testing.T) { + os.Setenv("a", "b") // ERROR "os\\.Setenv\\(\\) can be replaced by `t\\.Setenv\\(\\)` in TestF" + err := os.Setenv("a", "b") // ERROR "os\\.Setenv\\(\\) can be replaced by `t\\.Setenv\\(\\)` in TestF" + _ = err + if err := os.Setenv("a", "b"); err != nil { // ERROR "os\\.Setenv\\(\\) can be replaced by `t\\.Setenv\\(\\)` in TestF" + _ = err + } +} + +func BenchmarkF(b *testing.B) { + os.Setenv("a", "b") // ERROR "os\\.Setenv\\(\\) can be replaced by `b\\.Setenv\\(\\)` in BenchmarkF" + err := os.Setenv("a", "b") // ERROR "os\\.Setenv\\(\\) can be replaced by `b\\.Setenv\\(\\)` in BenchmarkF" + _ = err + if err := os.Setenv("a", "b"); err != nil { // ERROR "os\\.Setenv\\(\\) can be replaced by `b\\.Setenv\\(\\)` in BenchmarkF" + _ = err + } +} + +func testTB(tb testing.TB) { + os.Setenv("a", "b") // ERROR "os\\.Setenv\\(\\) can be replaced by `tb\\.Setenv\\(\\)` in testTB" + err := os.Setenv("a", "b") // ERROR "os\\.Setenv\\(\\) can be replaced by `tb\\.Setenv\\(\\)` in testTB" + _ = err + if err := os.Setenv("a", "b"); err != nil { // ERROR "os\\.Setenv\\(\\) can be replaced by `tb\\.Setenv\\(\\)` in testTB" + _ = err + } +}