diff --git a/.golangci.next.reference.yml b/.golangci.next.reference.yml index 1685b9e72ae6..36c49fbc452e 100644 --- a/.golangci.next.reference.yml +++ b/.golangci.next.reference.yml @@ -3399,6 +3399,7 @@ linters: - contains - empty - encoded-compare + - equal-values - error-is-as - error-nil - expected-actual @@ -3413,6 +3414,7 @@ linters: - suite-broken-parallel - suite-dont-use-pkg - suite-extra-assert-call + - suite-method-signature - suite-subtest-run - suite-thelper - useless-assert @@ -3422,9 +3424,10 @@ linters: disable-all: true # Enable checkers by name # (in addition to default - # blank-import, bool-compare, compares, contains, empty, encoded-compare, error-is-as, error-nil, expected-actual, - # go-require, float-compare, formatter, len, negative-positive, nil-compare, regexp, require-error, - # suite-broken-parallel, suite-dont-use-pkg, suite-extra-assert-call, suite-subtest-run, useless-assert + # blank-import, bool-compare, compares, contains, empty, encoded-compare, equal-values, error-is-as, error-nil, + # expected-actual, go-require, float-compare, formatter, len, negative-positive, nil-compare, regexp, require-error, + # suite-broken-parallel, suite-dont-use-pkg, suite-extra-assert-call, suite-subtest-run, suite-method-signature, + # useless-assert # ). enable: - blank-import @@ -3433,6 +3436,7 @@ linters: - contains - empty - encoded-compare + - equal-values - error-is-as - error-nil - expected-actual @@ -3447,6 +3451,7 @@ linters: - suite-broken-parallel - suite-dont-use-pkg - suite-extra-assert-call + - suite-method-signature - suite-subtest-run - suite-thelper - useless-assert @@ -3471,6 +3476,10 @@ linters: # https://github.com/Antonboom/testifylint?tab=readme-ov-file#historical-reference-of-formatter. # Default: false require-f-funcs: true + # To require that the first element of msgAndArgs (msg) has a string type. + # For example, in such case assertion like `assert.True(t, b, tt.case)` will be considered as invalid. + # Default: true + require-string-msg: false go-require: # To ignore HTTP handlers (like http.HandlerFunc). # Default: false diff --git a/go.mod b/go.mod index 28b515fb7c42..1042e2ca9c00 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/Abirdcfly/dupword v0.1.3 github.com/Antonboom/errname v1.0.0 github.com/Antonboom/nilnil v1.0.1 - github.com/Antonboom/testifylint v1.5.2 + github.com/Antonboom/testifylint v1.6.0 github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c github.com/Crocmagnon/fatcontext v0.7.1 github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 diff --git a/go.sum b/go.sum index f7dda33add88..4e5210159020 100644 --- a/go.sum +++ b/go.sum @@ -43,8 +43,8 @@ github.com/Antonboom/errname v1.0.0 h1:oJOOWR07vS1kRusl6YRSlat7HFnb3mSfMl6sDMRoT github.com/Antonboom/errname v1.0.0/go.mod h1:gMOBFzK/vrTiXN9Oh+HFs+e6Ndl0eTFbtsRTSRdXyGI= github.com/Antonboom/nilnil v1.0.1 h1:C3Tkm0KUxgfO4Duk3PM+ztPncTFlOf0b2qadmS0s4xs= github.com/Antonboom/nilnil v1.0.1/go.mod h1:CH7pW2JsRNFgEh8B2UaPZTEPhCMuFowP/e8Udp9Nnb0= -github.com/Antonboom/testifylint v1.5.2 h1:4s3Xhuv5AvdIgbd8wOOEeo0uZG7PbDKQyKY5lGoQazk= -github.com/Antonboom/testifylint v1.5.2/go.mod h1:vxy8VJ0bc6NavlYqjZfmp6EfqXMtBgQ4+mhCojwC1P8= +github.com/Antonboom/testifylint v1.6.0 h1:6rdILVPt4+rqcvhid8w9wJNynKLUgqHNpFyM67UeXyc= +github.com/Antonboom/testifylint v1.6.0/go.mod h1:k+nEkathI2NFjKO6HvwmSrbzUcQ6FAnbZV+ZRrnXPLI= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c h1:pxW6RcqyfI9/kWtOwnv/G+AzdKuy2ZrqINhenH4HyNs= github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= diff --git a/jsonschema/golangci.jsonschema.json b/jsonschema/golangci.jsonschema.json index 686de7d66405..112bcb721997 100644 --- a/jsonschema/golangci.jsonschema.json +++ b/jsonschema/golangci.jsonschema.json @@ -3370,6 +3370,7 @@ "contains", "empty", "encoded-compare", + "equal-values", "error-is-as", "error-nil", "expected-actual", @@ -3384,6 +3385,7 @@ "suite-broken-parallel", "suite-dont-use-pkg", "suite-extra-assert-call", + "suite-method-signature", "suite-subtest-run", "suite-thelper", "useless-assert" @@ -3396,6 +3398,7 @@ "contains", "empty", "encoded-compare", + "equal-values", "error-is-as", "error-nil", "expected-actual", @@ -3410,6 +3413,7 @@ "suite-broken-parallel", "suite-dont-use-pkg", "suite-extra-assert-call", + "suite-method-signature", "suite-subtest-run", "useless-assert" ] @@ -3425,6 +3429,7 @@ "contains", "empty", "encoded-compare", + "equal-values", "error-is-as", "error-nil", "expected-actual", @@ -3439,6 +3444,7 @@ "suite-broken-parallel", "suite-dont-use-pkg", "suite-extra-assert-call", + "suite-method-signature", "suite-subtest-run", "suite-thelper", "useless-assert" @@ -3483,6 +3489,11 @@ "description": "To require f-assertions (e.g. assert.Equalf) if format string is used, even if there are no variable-length variables.", "type": "boolean", "default": false + }, + "require-string-msg": { + "description": "To require that the first element of msgAndArgs (msg) has a string type.", + "type": "boolean", + "default": true } } }, diff --git a/jsonschema/golangci.next.jsonschema.json b/jsonschema/golangci.next.jsonschema.json index 686de7d66405..112bcb721997 100644 --- a/jsonschema/golangci.next.jsonschema.json +++ b/jsonschema/golangci.next.jsonschema.json @@ -3370,6 +3370,7 @@ "contains", "empty", "encoded-compare", + "equal-values", "error-is-as", "error-nil", "expected-actual", @@ -3384,6 +3385,7 @@ "suite-broken-parallel", "suite-dont-use-pkg", "suite-extra-assert-call", + "suite-method-signature", "suite-subtest-run", "suite-thelper", "useless-assert" @@ -3396,6 +3398,7 @@ "contains", "empty", "encoded-compare", + "equal-values", "error-is-as", "error-nil", "expected-actual", @@ -3410,6 +3413,7 @@ "suite-broken-parallel", "suite-dont-use-pkg", "suite-extra-assert-call", + "suite-method-signature", "suite-subtest-run", "useless-assert" ] @@ -3425,6 +3429,7 @@ "contains", "empty", "encoded-compare", + "equal-values", "error-is-as", "error-nil", "expected-actual", @@ -3439,6 +3444,7 @@ "suite-broken-parallel", "suite-dont-use-pkg", "suite-extra-assert-call", + "suite-method-signature", "suite-subtest-run", "suite-thelper", "useless-assert" @@ -3483,6 +3489,11 @@ "description": "To require f-assertions (e.g. assert.Equalf) if format string is used, even if there are no variable-length variables.", "type": "boolean", "default": false + }, + "require-string-msg": { + "description": "To require that the first element of msgAndArgs (msg) has a string type.", + "type": "boolean", + "default": true } } }, diff --git a/pkg/config/linters_settings.go b/pkg/config/linters_settings.go index db18a564306b..4ecb1b2d94b9 100644 --- a/pkg/config/linters_settings.go +++ b/pkg/config/linters_settings.go @@ -849,6 +849,7 @@ type TestifylintSettings struct { Formatter TestifylintFormatter `mapstructure:"formatter"` GoRequire TestifylintGoRequire `mapstructure:"go-require"` RequireError TestifylintRequireError `mapstructure:"require-error"` + RequireStringMsg bool `mapstructure:"require-string-msg"` SuiteExtraAssertCall TestifylintSuiteExtraAssertCall `mapstructure:"suite-extra-assert-call"` } @@ -863,6 +864,7 @@ type TestifylintExpectedActual struct { type TestifylintFormatter struct { CheckFormatString *bool `mapstructure:"check-format-string"` RequireFFuncs bool `mapstructure:"require-f-funcs"` + RequireStringMsg bool `mapstructure:"require-string-msg"` } type TestifylintGoRequire struct { diff --git a/pkg/golinters/testifylint/testdata/fix/in/testifylint.go b/pkg/golinters/testifylint/testdata/fix/in/testifylint.go index a79161f9ca7a..1e93db5bc229 100644 --- a/pkg/golinters/testifylint/testdata/fix/in/testifylint.go +++ b/pkg/golinters/testifylint/testdata/fix/in/testifylint.go @@ -30,7 +30,8 @@ func TestTestifylint(t *testing.T) { assert.Nil(t, err) // want "error-nil: use assert\\.NoError" assert.Equal(t, resultInt, 42) // want "expected-actual: need to reverse actual and expected values" assert.Equal(t, resultFloat, 42.42) // want "float-compare: use assert\\.InEpsilon \\(or InDelta\\)" - assert.Equal(t, len(arr), 10) // want "len: use assert\\.Len" + assert.Equal(t, len(arr), 10) // want "expected-actual: need to reverse actual and expected values" + assert.Equal(t, 10, len(arr)) // want "len: use assert\\.Len" assert.True(t, predicate) assert.Equal(t, resultInt, 1) // want "expected-actual: need to reverse actual and expected values" diff --git a/pkg/golinters/testifylint/testdata/fix/out/testifylint.go b/pkg/golinters/testifylint/testdata/fix/out/testifylint.go index 5d1f101d4e2c..bba789a4ff22 100644 --- a/pkg/golinters/testifylint/testdata/fix/out/testifylint.go +++ b/pkg/golinters/testifylint/testdata/fix/out/testifylint.go @@ -30,6 +30,7 @@ func TestTestifylint(t *testing.T) { assert.NoError(t, err) // want "error-nil: use assert\\.NoError" assert.Equal(t, 42, resultInt) // want "expected-actual: need to reverse actual and expected values" assert.Equal(t, resultFloat, 42.42) // want "float-compare: use assert\\.InEpsilon \\(or InDelta\\)" + assert.Equal(t, 10, len(arr)) // want "expected-actual: need to reverse actual and expected values" assert.Len(t, arr, 10) // want "len: use assert\\.Len" assert.True(t, predicate) diff --git a/pkg/golinters/testifylint/testdata/testifylint.go b/pkg/golinters/testifylint/testdata/testifylint.go index a79161f9ca7a..1e93db5bc229 100644 --- a/pkg/golinters/testifylint/testdata/testifylint.go +++ b/pkg/golinters/testifylint/testdata/testifylint.go @@ -30,7 +30,8 @@ func TestTestifylint(t *testing.T) { assert.Nil(t, err) // want "error-nil: use assert\\.NoError" assert.Equal(t, resultInt, 42) // want "expected-actual: need to reverse actual and expected values" assert.Equal(t, resultFloat, 42.42) // want "float-compare: use assert\\.InEpsilon \\(or InDelta\\)" - assert.Equal(t, len(arr), 10) // want "len: use assert\\.Len" + assert.Equal(t, len(arr), 10) // want "expected-actual: need to reverse actual and expected values" + assert.Equal(t, 10, len(arr)) // want "len: use assert\\.Len" assert.True(t, predicate) assert.Equal(t, resultInt, 1) // want "expected-actual: need to reverse actual and expected values" diff --git a/pkg/golinters/testifylint/testdata/testifylint_cgo.go b/pkg/golinters/testifylint/testdata/testifylint_cgo.go index 8a96b0de3e6c..12ce85fa532a 100644 --- a/pkg/golinters/testifylint/testdata/testifylint_cgo.go +++ b/pkg/golinters/testifylint/testdata/testifylint_cgo.go @@ -46,7 +46,8 @@ func TestTestifylint(t *testing.T) { assert.Nil(t, err) // want "error-nil: use assert\\.NoError" assert.Equal(t, resultInt, 42) // want "expected-actual: need to reverse actual and expected values" assert.Equal(t, resultFloat, 42.42) // want "float-compare: use assert\\.InEpsilon \\(or InDelta\\)" - assert.Equal(t, len(arr), 10) // want "len: use assert\\.Len" + assert.Equal(t, len(arr), 10) // want "expected-actual: need to reverse actual and expected values" + assert.Equal(t, 10, len(arr)) // want "len: use assert\\.Len" assert.True(t, predicate) assert.Equal(t, resultInt, 1) // want "expected-actual: need to reverse actual and expected values" diff --git a/pkg/golinters/testifylint/testdata/testifylint_formatter_dont_require_string_msg.go b/pkg/golinters/testifylint/testdata/testifylint_formatter_dont_require_string_msg.go new file mode 100644 index 000000000000..8f2a7c233a0b --- /dev/null +++ b/pkg/golinters/testifylint/testdata/testifylint_formatter_dont_require_string_msg.go @@ -0,0 +1,16 @@ +//golangcitest:args -Etestifylint +//golangcitest:config_path testdata/testifylint_formatter_dont_require_string_msg.yml +package testdata + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestTestifylint(t *testing.T) { + var b bool + assert.True(t, b, b) + assert.True(t, b, "msg %v", 1) + assert.True(t, b, b, 1) // want "formatter: using msgAndArgs with non-string first element \\(msg\\) causes panic" +} diff --git a/pkg/golinters/testifylint/testdata/testifylint_formatter_dont_require_string_msg.yml b/pkg/golinters/testifylint/testdata/testifylint_formatter_dont_require_string_msg.yml new file mode 100644 index 000000000000..749500b93f4b --- /dev/null +++ b/pkg/golinters/testifylint/testdata/testifylint_formatter_dont_require_string_msg.yml @@ -0,0 +1,12 @@ +version: "2" + +linters: + settings: + testifylint: + disable-all: true + enable: + - formatter + formatter: + check-format-string: false + require-f-funcs: false + require-string-msg: false diff --git a/pkg/golinters/testifylint/testdata/testifylint_formatter_only.go b/pkg/golinters/testifylint/testdata/testifylint_formatter_only.go index 0128e55c5089..7934fe7473ee 100644 --- a/pkg/golinters/testifylint/testdata/testifylint_formatter_only.go +++ b/pkg/golinters/testifylint/testdata/testifylint_formatter_only.go @@ -12,8 +12,12 @@ import ( func TestTestifylint(t *testing.T) { var err error var args []any + var b bool assert.Error(t, err, "Parse(%v) should fail.", args) // want "formatter: use assert\\.Errorf$" assert.Equal(t, 1, 2, fmt.Sprintf("msg")) // want "formatter: remove unnecessary fmt\\.Sprintf and use assert\\.Equalf" assert.DirExistsf(t, "", "msg with arg", 42) + + assert.True(t, b, b) // want "formatter: do not use non-string value as first element \\(msg\\) of msgAndArgs" + assert.True(t, b, b, 1) // want "formatter: using msgAndArgs with non-string first element \\(msg\\) causes panic" } diff --git a/pkg/golinters/testifylint/testdata/testifylint_formatter_only.yml b/pkg/golinters/testifylint/testdata/testifylint_formatter_only.yml index c85e9fe7ad10..cd4f406d56cc 100644 --- a/pkg/golinters/testifylint/testdata/testifylint_formatter_only.yml +++ b/pkg/golinters/testifylint/testdata/testifylint_formatter_only.yml @@ -9,3 +9,4 @@ linters: formatter: check-format-string: false require-f-funcs: true + require-string-msg: true diff --git a/pkg/golinters/testifylint/testifylint.go b/pkg/golinters/testifylint/testifylint.go index b5eb30048e8b..b19471c1ea05 100644 --- a/pkg/golinters/testifylint/testifylint.go +++ b/pkg/golinters/testifylint/testifylint.go @@ -19,6 +19,7 @@ func New(settings *config.TestifylintSettings) *goanalysis.Linter { "bool-compare.ignore-custom-types": settings.BoolCompare.IgnoreCustomTypes, "formatter.require-f-funcs": settings.Formatter.RequireFFuncs, + "formatter.require-string-msg": settings.Formatter.RequireStringMsg, "go-require.ignore-http-handlers": settings.GoRequire.IgnoreHTTPHandlers, } if len(settings.EnabledCheckers) > 0 { diff --git a/test/testshared/runner.go b/test/testshared/runner.go index 846cc657e672..c516ad9a181a 100644 --- a/test/testshared/runner.go +++ b/test/testshared/runner.go @@ -279,7 +279,7 @@ type RunnerResult struct { func (r *RunnerResult) ExpectNoIssues() { r.tb.Helper() - assert.Equal(r.tb, "", r.output, "exit code is %d", r.exitCode) + assert.Empty(r.tb, r.output, "exit code is %d", r.exitCode) assert.Equal(r.tb, exitcodes.Success, r.exitCode, "output is %s", r.output) }