1
0
mirror of https://github.com/mgechev/revive.git synced 2024-11-21 17:16:40 +02:00

adds tests for specific go versions (#1043)

Co-authored-by: chavacava <salvador.cavadini@gmail.com>
This commit is contained in:
chavacava 2024-09-20 16:09:24 +02:00 committed by GitHub
parent 4ac5cb5e39
commit a65fb8d1b5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 341 additions and 15 deletions

View File

@ -9,3 +9,7 @@ import (
func TestDatarace(t *testing.T) {
testRule(t, "datarace", &rule.DataRaceRule{})
}
func TestDataraceAfterGo1_22(t *testing.T) {
testRule(t, "go1.22/datarace", &rule.DataRaceRule{})
}

View File

@ -38,7 +38,7 @@ func TestFileExcludeFilterAtRuleLevel(t *testing.T) {
t.Run("not called if exclude not match", func(t *testing.T) {
rule := &TestFileFilterRule{}
cfg := &lint.RuleConfig{Exclude: []string{"file-to-exclude.go"}}
cfg := &lint.RuleConfig{Exclude: []string{"../testdata/file-to-exclude.go"}}
cfg.Initialize()
testRule(t, "file-to-exclude", rule, cfg)
if rule.WasApplyed {

View File

@ -64,7 +64,7 @@ func TestAll(t *testing.T) {
t.Fatalf("Failed reading %s: %v", fi.Name(), err)
}
if err := assertFailures(t, baseDir, fileInfo, src, rules, map[string]lint.RuleConfig{}); err != nil {
if err := assertFailures(t, path.Dir(baseDir), fileInfo, src, rules, map[string]lint.RuleConfig{}); err != nil {
t.Errorf("Linting %s: %v", fi.Name(), err)
}
})

View File

@ -10,3 +10,7 @@ import (
func TestRangeValAddress(t *testing.T) {
testRule(t, "range-val-address", &rule.RangeValAddress{}, &lint.RuleConfig{})
}
func TestRangeValAddressAfterGo1_22(t *testing.T) {
testRule(t, "go1.22/range-val-address", &rule.RangeValAddress{}, &lint.RuleConfig{})
}

View File

@ -10,3 +10,7 @@ import (
func TestRangeValInClosure(t *testing.T) {
testRule(t, "range-val-in-closure", &rule.RangeValInClosureRule{}, &lint.RuleConfig{})
}
func TestRangeValInClosureAfterGo1_22(t *testing.T) {
testRule(t, "go1.22/range-val-in-closure", &rule.RangeValInClosureRule{}, &lint.RuleConfig{})
}

View File

@ -10,3 +10,7 @@ import (
func TestRedefinesBuiltinID(t *testing.T) {
testRule(t, "redefines-builtin-id", &rule.RedefinesBuiltinIDRule{})
}
func TestRedefinesBuiltinIDAfterGo1_21(t *testing.T) {
testRule(t, "go1.21/redefines-builtin-id", &rule.RedefinesBuiltinIDRule{})
}

View File

@ -10,6 +10,7 @@ import (
"go/token"
"go/types"
"os"
"path"
"strconv"
"strings"
"testing"
@ -18,13 +19,14 @@ import (
)
func testRule(t *testing.T, filename string, rule lint.Rule, config ...*lint.RuleConfig) {
baseDir := "../testdata/"
filename = filename + ".go"
src, err := os.ReadFile(baseDir + filename)
baseDir := path.Join("../testdata/" + path.Dir(filename))
filename = path.Base(filename) + ".go"
fullFilePath := path.Join(baseDir, filename)
src, err := os.ReadFile(fullFilePath)
if err != nil {
t.Fatalf("Bad filename path in test for %s: %v", rule.Name(), err)
}
stat, err := os.Stat(baseDir + filename)
stat, err := os.Stat(fullFilePath)
if err != nil {
t.Fatalf("Cannot get file info for %s: %v", rule.Name(), err)
}
@ -32,7 +34,7 @@ func testRule(t *testing.T, filename string, rule lint.Rule, config ...*lint.Rul
if config != nil {
c[rule.Name()] = *config[0]
}
if parseInstructions(t, filename, src) == nil {
if parseInstructions(t, fullFilePath, src) == nil {
assertSuccess(t, baseDir, stat, []lint.Rule{rule}, c)
return
}
@ -41,10 +43,11 @@ func testRule(t *testing.T, filename string, rule lint.Rule, config ...*lint.Rul
func assertSuccess(t *testing.T, baseDir string, fi os.FileInfo, rules []lint.Rule, config map[string]lint.RuleConfig) error {
l := lint.New(func(file string) ([]byte, error) {
return os.ReadFile(baseDir + file)
return os.ReadFile(file)
}, 0)
ps, err := l.Lint([][]string{{fi.Name()}}, rules, lint.Config{
filePath := path.Join(baseDir, fi.Name())
ps, err := l.Lint([][]string{{filePath}}, rules, lint.Config{
Rules: config,
})
if err != nil {
@ -63,15 +66,15 @@ func assertSuccess(t *testing.T, baseDir string, fi os.FileInfo, rules []lint.Ru
func assertFailures(t *testing.T, baseDir string, fi os.FileInfo, src []byte, rules []lint.Rule, config map[string]lint.RuleConfig) error {
l := lint.New(func(file string) ([]byte, error) {
return os.ReadFile(baseDir + file)
return os.ReadFile(file)
}, 0)
ins := parseInstructions(t, fi.Name(), src)
ins := parseInstructions(t, path.Join(baseDir, fi.Name()), src)
if ins == nil {
return fmt.Errorf("Test file %v does not have instructions", fi.Name())
}
ps, err := l.Lint([][]string{{fi.Name()}}, rules, lint.Config{
ps, err := l.Lint([][]string{{path.Join(baseDir, fi.Name())}}, rules, lint.Config{
Rules: config,
})
if err != nil {

5
testdata/go.mod vendored Normal file
View File

@ -0,0 +1,5 @@
module github.com/mgechev/revive/testdata
// set the lowest go version
// to trigger testing of all rules
go 1.0

3
testdata/go1.21/go.mod vendored Normal file
View File

@ -0,0 +1,3 @@
module github.com/mgechev/revive/testdata
go 1.21

54
testdata/go1.21/redefines-builtin-id.go vendored Normal file
View File

@ -0,0 +1,54 @@
package fixtures
func (this data) vmethod() {
nil := true // MATCH /assignment creates a shadow of built-in identifier nil/
iota = 1 // MATCH /assignment modifies built-in identifier iota/
}
func append(i, j int) { // MATCH /redefinition of the built-in function append/
}
type string int16 // MATCH /redefinition of the built-in type string/
func delete(set []int64, i int) (y []int64) { // MATCH /redefinition of the built-in function delete/
for j, v := range set {
if j != i {
y = append(y, v)
}
}
return
}
type any int // MATCH /redefinition of the built-in type any/
func any() {} // MATCH /redefinition of the built-in type any/
var any int // MATCH /redefinition of the built-in type any/
const any = 1 // MATCH /redefinition of the built-in type any/
var i, copy int // MATCH /redefinition of the built-in function copy/
// issue #792
type ()
func foo() {
clear := 0 // MATCH /redefinition of the built-in function clear/
max := 0 // MATCH /redefinition of the built-in function max/
min := 0 // MATCH /redefinition of the built-in function min/
_ = clear
_ = max
_ = min
}
func foo1(new int) { // MATCH /redefinition of the built-in function new/
_ = new
}
func foo2() (new int) { // MATCH /redefinition of the built-in function new/
return
}
func foo3[new any]() { // MATCH /redefinition of the built-in function new/
}

30
testdata/go1.22/datarace.go vendored Normal file
View File

@ -0,0 +1,30 @@
package fixtures
func datarace() (r int, c char) {
for _, p := range []int{1, 2} {
go func() {
print(r) // MATCH /potential datarace: return value r is captured (by-reference) in goroutine/
print(p) // Shall not match /datarace: range value p is captured (by-reference) in goroutine/
}()
for i, p1 := range []int{1, 2} {
a := p1
go func() {
print(r) // MATCH /potential datarace: return value r is captured (by-reference) in goroutine/
print(p) // Shall not match /datarace: range value p is captured (by-reference) in goroutine/
print(p1) // Shall not match /datarace: range value p1 is captured (by-reference) in goroutine/
print(a)
print(i) // Shall not match /datarace: range value i is captured (by-reference) in goroutine/
}()
print(i)
print(p)
go func() {
_ = c // MATCH /potential datarace: return value c is captured (by-reference) in goroutine/
}()
}
print(p1)
}
go func() {
print(r) // MATCH /potential datarace: return value r is captured (by-reference) in goroutine/
}()
print(r)
}

3
testdata/go1.22/go.mod vendored Normal file
View File

@ -0,0 +1,3 @@
module github.com/mgechev/revive/testdata
go 1.22

163
testdata/go1.22/range-val-address.go vendored Normal file
View File

@ -0,0 +1,163 @@
package fixtures
func rangeValAddress() {
m := map[string]*string{}
mySlice := []string{"A", "B", "C"}
for _, value := range mySlice {
m["address"] = &value // Shall not match /suspicious assignment of 'value'. range-loop variables always have the same address/
}
}
func rangeValAddress2() {
m := map[string]*string{}
mySlice := []string{"A", "B", "C"}
for i := range mySlice {
m["address"] = &mySlice[i]
}
}
func rangeValAddress3() {
m := map[string]*string{}
mySlice := []string{"A", "B", "C"}
for _, value := range mySlice {
a := &value // Shall not match /suspicious assignment of 'value'. range-loop variables always have the same address/
m["address"] = a
}
}
func rangeValAddress4() {
m := []*string{}
mySlice := []string{"A", "B", "C"}
for _, value := range mySlice {
m = append(m, &value) // Shall not match /suspicious assignment of 'value'. range-loop variables always have the same address/
}
}
func rangeValAddress5() {
m := map[*string]string{}
mySlice := []string{"A", "B", "C"}
for _, value := range mySlice {
m[&value] = value // Shall not match /suspicious assignment of 'value'. range-loop variables always have the same address/
}
}
func rangeValAddress6() {
type v struct {
id string
}
m := []*string{}
mySlice := []v{{id: "A"}, {id: "B"}, {id: "C"}}
for _, value := range mySlice {
m = append(m, &value.id) // Shall not match /suspicious assignment of 'value'. range-loop variables always have the same address/
}
}
func rangeValAddress7() {
type v struct {
id string
}
m := []*string{}
for _, value := range []v{{id: "A"}, {id: "B"}, {id: "C"}} {
m = append(m, &value.id) // Shall not match /suspicious assignment of 'value'. range-loop variables always have the same address/
}
}
func rangeValAddress8() {
type v struct {
id string
}
m := []*string{}
mySlice := []*v{{id: "A"}, {id: "B"}, {id: "C"}}
for _, value := range mySlice {
m = append(m, &value.id)
}
}
func rangeValAddress9() {
type v struct {
id string
}
m := []*string{}
mySlice := map[string]*v{"a": {id: "A"}, "b": {id: "B"}, "c": {id: "C"}}
for _, value := range mySlice {
m = append(m, &value.id)
}
}
func rangeValAddress10() {
type v struct {
id string
}
m := []*string{}
for _, value := range map[string]*v{"a": {id: "A"}, "b": {id: "B"}, "c": {id: "C"}} {
m = append(m, &value.id)
}
}
func rangeValAddress11() {
type v struct {
id string
}
m := map[string]*string{}
for key, value := range map[string]*v{"a": {id: "A"}, "b": {id: "B"}, "c": {id: "C"}} {
m[key] = &value.id
}
}
func rangeValAddress12() {
type v struct {
id string
}
m := map[string]*string{}
for key, value := range map[string]v{"a": {id: "A"}, "b": {id: "B"}, "c": {id: "C"}} {
m[key] = &value.id // Shall not match /suspicious assignment of 'value'. range-loop variables always have the same address/
}
}
func rangeValAddress13() {
type v struct {
id string
}
m := []*string{}
otherSlice := map[string]*v{"a": {id: "A"}, "b": {id: "B"}, "c": {id: "C"}}
mySlice := otherSlice
for _, value := range mySlice {
m = append(m, &value.id)
}
}
func rangeValAddress14() {
type v struct {
id *string
}
m := []v{}
for _, value := range []string{"A", "B", "C"} {
a := v{id: &value} // Shall not match /suspicious assignment of 'value'. range-loop variables always have the same address/
m = append(m, a)
}
}
func rangeValAddress15() {
type v struct {
id *string
}
m := []v{}
for _, value := range []string{"A", "B", "C"} {
m = append(m, v{id: &value}) // Shall not match /suspicious assignment of 'value'. range-loop variables always have the same address/
}
}

49
testdata/go1.22/range-val-in-closure.go vendored Normal file
View File

@ -0,0 +1,49 @@
package fixtures
import "fmt"
func foo() {
mySlice := []string{"A", "B", "C"}
for index, value := range mySlice {
go func() {
fmt.Printf("Index: %d\n", index) // Shall not match
fmt.Printf("Value: %s\n", value) // Shall not match
}()
}
myDict := make(map[string]int)
myDict["A"] = 1
myDict["B"] = 2
myDict["C"] = 3
for key, value := range myDict {
defer func() {
fmt.Printf("Index: %d\n", key) // Shall not match
fmt.Printf("Value: %s\n", value) // Shall not match
}()
}
for i, newg := range groups {
go func(newg int) {
newg.run(m.opts.Context, i) // Shall not match
}(newg)
}
for i, newg := range groups {
newg := newg
go func() {
newg.run(m.opts.Context, i) // Shall not match
}()
}
}
func issue637() {
for key := range m {
myKey := key
go func() {
println(t{
key: myKey,
otherField: (10 + key), // Shall not match
})
}()
}
}

View File

@ -34,9 +34,9 @@ var i, copy int // MATCH /redefinition of the built-in function copy/
type ()
func foo() {
clear := 0 // MATCH /redefinition of the built-in function clear/
max := 0 // MATCH /redefinition of the built-in function max/
min := 0 // MATCH /redefinition of the built-in function min/
clear := 0 // Shall not match /redefinition of the built-in function clear/
max := 0 // Shall not match /redefinition of the built-in function max/
min := 0 // Shall not match /redefinition of the built-in function min/
_ = clear
_ = max
_ = min