diff --git a/internal/checker/imports_test.go b/internal/checker/imports_test.go index 29fc094..33df643 100644 --- a/internal/checker/imports_test.go +++ b/internal/checker/imports_test.go @@ -72,7 +72,7 @@ func TestImports(t *testing.T) { ar, err := Txtar(t, fset, test.txtarPath) assert.Nil(t, err) - assert.Len(t, len(ar), 1) + assert.Len(t, ar, 1) ins := inspector.New(ar) testImports := Load(fset, ins) diff --git a/internal/checker/testing_test.go b/internal/checker/testing_test.go index 2e956f9..8f86f16 100644 --- a/internal/checker/testing_test.go +++ b/internal/checker/testing_test.go @@ -8,9 +8,16 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" "golang.org/x/tools/txtar" ) +func ParseExprFrom(t *testing.T, fset *token.FileSet, src any) ast.Expr { + astExpr, err := parser.ParseExprFrom(fset, "a.go", src, parser.AllErrors) + assert.NoError(t, err) + return astExpr +} + func Txtar(t *testing.T, fset *token.FileSet, txtarPath string) (files []*ast.File, err error) { t.Helper() diff --git a/internal/checker/violation_test.go b/internal/checker/violation_test.go new file mode 100644 index 0000000..1b685bc --- /dev/null +++ b/internal/checker/violation_test.go @@ -0,0 +1,107 @@ +package checker + +import ( + "go/ast" + "go/token" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestViolation(t *testing.T) { + for i := range tests { + test := tests[i] + t.Run(test.Name, func(t *testing.T) { + fset := token.NewFileSet() + expr := ParseExprFrom(t, fset, test.Expression).(*ast.CallExpr) + args := make(map[int]ast.Expr, len(test.Args)) + base := []byte(test.Base) + + for n := range test.Args { + args[n] = ParseExprFrom(t, fset, test.Args[n]) + } + + v2 := test.Violation.With(base, expr, args) + assert.Equal(t, test.ExpectedSuggest, string(v2.suggest(fset))) + assert.Equal(t, test.Message, v2.Message()) + }) + } +} + +var tests = []struct { + Name string + Violation Violation + Expression string + Base string + Args map[int]string + ExpectedSuggest string + Message string +}{ + { + Name: "alt Caller", + Violation: Violation{ + Targets: Strings, + Type: Function, + Package: "regexp", + Caller: "MatchString", + Args: []int{1}, + AltPackage: "foobar", + AltCaller: "Match", + }, + Expression: `regexp.MatchString("[0-9]+", []bytes("foo"))`, + Args: map[int]string{1: `"foo"`}, + Base: "regexp", + ExpectedSuggest: `regexp.Match("[0-9]+", "foo")`, + Message: `avoid allocations with foobar.Match`, + }, + { + Name: "Has More Args Then WeNeed", + Violation: Violation{ + Targets: Strings, + Type: Function, + Package: "regexp", + Caller: "MatchString", + Args: []int{1}, + AltPackage: "foobar", + AltCaller: "Match", + }, + Expression: `regexp.MatchString("[0-9]+", []bytes("foo"))`, + Args: map[int]string{1: `"foo"`, 2: `"foo"`, 3: `"foo"`, 4: `"foo"`}, + Base: "regexp", + ExpectedSuggest: `regexp.Match("[0-9]+", "foo")`, + Message: `avoid allocations with foobar.Match`, + }, + { + Name: "Regular Suggestion Work", + Violation: Violation{ + Targets: Strings, + Type: Function, + Package: "regexp", + Caller: "MatchString", + Args: []int{1}, + AltCaller: "Match", + }, + Expression: `regexp.MatchString("[0-9]+", []bytes("foo"))`, + Args: map[int]string{1: `"foo"`}, + Base: "regexp", + ExpectedSuggest: `regexp.Match("[0-9]+", "foo")`, + Message: `avoid allocations with regexp.Match`, + }, + { + Name: "Methods", + Violation: Violation{ + Targets: Strings, + Type: Method, + Package: "regexp", + Struct: "Regexp", + Caller: "MatchString", + Args: []int{1}, + AltCaller: "Match", + }, + Expression: `re.MatchString("[0-9]+", []bytes("foo"))`, + Args: map[int]string{1: `"foo"`}, + Base: "re", + ExpectedSuggest: `re.Match("[0-9]+", "foo")`, + Message: `avoid allocations with (*regexp.Regexp).Match`, + }, +}