1 | // Copyright 2020 The Go Authors. All rights reserved. |
---|---|
2 | // Use of this source code is governed by a BSD-style |
3 | // license that can be found in the LICENSE file. |
4 | |
5 | package analysis |
6 | |
7 | import ( |
8 | "strings" |
9 | "testing" |
10 | ) |
11 | |
12 | func TestValidate(t *testing.T) { |
13 | var ( |
14 | run = func(p *Pass) (interface{}, error) { |
15 | return nil, nil |
16 | } |
17 | dependsOnSelf = &Analyzer{ |
18 | Name: "dependsOnSelf", |
19 | Doc: "this analyzer depends on itself", |
20 | Run: run, |
21 | } |
22 | inCycleA = &Analyzer{ |
23 | Name: "inCycleA", |
24 | Doc: "this analyzer depends on inCycleB", |
25 | Run: run, |
26 | } |
27 | inCycleB = &Analyzer{ |
28 | Name: "inCycleB", |
29 | Doc: "this analyzer depends on inCycleA and notInCycleA", |
30 | Run: run, |
31 | } |
32 | pointsToCycle = &Analyzer{ |
33 | Name: "pointsToCycle", |
34 | Doc: "this analyzer depends on inCycleA", |
35 | Run: run, |
36 | } |
37 | notInCycleA = &Analyzer{ |
38 | Name: "notInCycleA", |
39 | Doc: "this analyzer depends on notInCycleB and notInCycleC", |
40 | Run: run, |
41 | } |
42 | notInCycleB = &Analyzer{ |
43 | Name: "notInCycleB", |
44 | Doc: "this analyzer depends on notInCycleC", |
45 | Run: run, |
46 | } |
47 | notInCycleC = &Analyzer{ |
48 | Name: "notInCycleC", |
49 | Doc: "this analyzer has no dependencies", |
50 | Run: run, |
51 | } |
52 | ) |
53 | |
54 | dependsOnSelf.Requires = append(dependsOnSelf.Requires, dependsOnSelf) |
55 | inCycleA.Requires = append(inCycleA.Requires, inCycleB) |
56 | inCycleB.Requires = append(inCycleB.Requires, inCycleA, notInCycleA) |
57 | pointsToCycle.Requires = append(pointsToCycle.Requires, inCycleA) |
58 | notInCycleA.Requires = append(notInCycleA.Requires, notInCycleB, notInCycleC) |
59 | notInCycleB.Requires = append(notInCycleB.Requires, notInCycleC) |
60 | notInCycleC.Requires = []*Analyzer{} |
61 | |
62 | cases := []struct { |
63 | analyzers []*Analyzer |
64 | wantErr bool |
65 | analyzersInCycle map[string]bool |
66 | }{ |
67 | { |
68 | []*Analyzer{dependsOnSelf}, |
69 | true, |
70 | map[string]bool{"dependsOnSelf": true}, |
71 | }, |
72 | { |
73 | []*Analyzer{inCycleA, inCycleB}, |
74 | true, |
75 | map[string]bool{"inCycleA": true, "inCycleB": true}, |
76 | }, |
77 | { |
78 | []*Analyzer{pointsToCycle}, |
79 | true, |
80 | map[string]bool{"inCycleA": true, "inCycleB": true}, |
81 | }, |
82 | { |
83 | []*Analyzer{notInCycleA}, |
84 | false, |
85 | map[string]bool{}, |
86 | }, |
87 | } |
88 | |
89 | for _, c := range cases { |
90 | got := Validate(c.analyzers) |
91 | |
92 | if !c.wantErr { |
93 | if got == nil { |
94 | continue |
95 | } |
96 | t.Errorf("got unexpected error while validating analyzers %v: %v", c.analyzers, got) |
97 | } |
98 | |
99 | if got == nil { |
100 | t.Errorf("expected error while validating analyzers %v, but got nil", c.analyzers) |
101 | } |
102 | |
103 | err, ok := got.(*CycleInRequiresGraphError) |
104 | if !ok { |
105 | t.Errorf("want CycleInRequiresGraphError, got %T", err) |
106 | } |
107 | |
108 | for a := range c.analyzersInCycle { |
109 | if !err.AnalyzerNames[a] { |
110 | t.Errorf("analyzer %s should be in cycle", a) |
111 | } |
112 | } |
113 | for a := range err.AnalyzerNames { |
114 | if !c.analyzersInCycle[a] { |
115 | t.Errorf("analyzer %s should not be in cycle", a) |
116 | } |
117 | } |
118 | } |
119 | } |
120 | |
121 | func TestCycleInRequiresGraphErrorMessage(t *testing.T) { |
122 | err := CycleInRequiresGraphError{} |
123 | errMsg := err.Error() |
124 | wantSubstring := "cycle detected" |
125 | if !strings.Contains(errMsg, wantSubstring) { |
126 | t.Errorf("error string %s does not contain expected substring %q", errMsg, wantSubstring) |
127 | } |
128 | } |
129 | |
130 | func TestValidateEmptyDoc(t *testing.T) { |
131 | withoutDoc := &Analyzer{ |
132 | Name: "withoutDoc", |
133 | Run: func(p *Pass) (interface{}, error) { |
134 | return nil, nil |
135 | }, |
136 | } |
137 | err := Validate([]*Analyzer{withoutDoc}) |
138 | if err == nil || !strings.Contains(err.Error(), "is undocumented") { |
139 | t.Errorf("got unexpected error while validating analyzers withoutDoc: %v", err) |
140 | } |
141 | } |
142 | |
143 | func TestValidateNoRun(t *testing.T) { |
144 | withoutRun := &Analyzer{ |
145 | Name: "withoutRun", |
146 | Doc: "this analyzer has no Run", |
147 | } |
148 | err := Validate([]*Analyzer{withoutRun}) |
149 | if err == nil || !strings.Contains(err.Error(), "has nil Run") { |
150 | t.Errorf("got unexpected error while validating analyzers withoutRun: %v", err) |
151 | } |
152 | } |
153 |
Members