返回 DeepSeek-Reasonix
complexity_test.go
根目录 / tools / repolint / complexity_test.go
1 package main
2
3 import (
4 "go/ast"
5 "strings"
6 "testing"
7 )
8
9 func firstFunc(t *testing.T, src string) (*sourceFile, *ast.FuncDecl) {
10 t.Helper()
11 s := parseBytes("t.go", []byte(src))
12 if s == nil {
13 t.Fatal("parse failed")
14 }
15 for _, decl := range s.file.Decls {
16 if fn, ok := decl.(*ast.FuncDecl); ok {
17 return s, fn
18 }
19 }
20 t.Fatal("no function in source")
21 return nil, nil
22 }
23
24 func TestCyclomaticIgnoresDefaultClause(t *testing.T) {
25 _, fn := firstFunc(t, "package p\n\nfunc f(x int) int {\n\tswitch x {\n\tcase 1:\n\t\treturn 1\n\tcase 2:\n\t\treturn 2\n\tdefault:\n\t\treturn 0\n\t}\n}\n")
26 if got := cyclomatic(fn.Body); got != 3 {
27 t.Fatalf("cyclomatic = %d, want 3: one base plus two real cases, default is not a branch", got)
28 }
29 }
30
31 func TestCyclomaticCountsShortCircuitOperators(t *testing.T) {
32 _, fn := firstFunc(t, "package p\n\nfunc f(a, b bool) bool {\n\treturn a && b || !a\n}\n")
33 if got := cyclomatic(fn.Body); got != 3 {
34 t.Fatalf("cyclomatic = %d, want 3: one base plus && and ||", got)
35 }
36 }
37
38 func TestComplexityFlagsOnlyWhatExceedsTheLimit(t *testing.T) {
39 var b strings.Builder
40 b.WriteString("package p\n\nfunc f(x int) int {\n")
41 for range maxComplexity {
42 b.WriteString("\tif x > 0 {\n\t\tx--\n\t}\n")
43 }
44 b.WriteString("\treturn x\n}\n")
45 s := parseBytes("t.go", []byte(b.String()))
46 found := checkComplexity(s)
47 if len(found) == 0 {
48 t.Fatal("a function past both limits was not flagged")
49 }
50 for _, f := range found {
51 if f.Weight < 1 {
52 t.Fatalf("%s weight = %d, want the excess over the limit", f.Rule, f.Weight)
53 }
54 }
55 }
56
57 func TestShortSimpleFunctionIsClean(t *testing.T) {
58 s := parseBytes("t.go", []byte("package p\n\nfunc f() int { return 1 }\n"))
59 if got := checkComplexity(s); len(got) != 0 {
60 t.Fatalf("clean function flagged: %v", got)
61 }
62 }
63
64 func TestTestFilesAreNotMeasured(t *testing.T) {
65 s := parseBytes("t_test.go", []byte("package p\n\nfunc f() int { return 1 }\n"))
66 if got := checkComplexity(s); got != nil {
67 t.Fatalf("test file measured: %v", got)
68 }
69 }
70
71 func TestMethodNamesCarryTheirReceiver(t *testing.T) {
72 _, fn := firstFunc(t, "package p\n\ntype T struct{}\n\nfunc (t *T) Do() {}\n")
73 if got := funcName(fn); got != "T.Do" {
74 t.Fatalf("funcName = %q, want T.Do", got)
75 }
76 }
77
77 lines GO