10
10
package importgraph_test
11
11
12
12
import (
13
+ "fmt"
13
14
"go/build"
15
+ "os"
14
16
"sort"
15
17
"strings"
16
18
"testing"
@@ -30,56 +32,138 @@ func TestBuild(t *testing.T) {
30
32
31
33
var gopath string
32
34
for _ , env := range exported .Config .Env {
33
- if ! strings .HasPrefix (env , "GOPATH=" ) {
35
+ eq := strings .Index (env , "=" )
36
+ if eq == 0 {
37
+ // We sometimes see keys with a single leading "=" in the environment on Windows.
38
+ // TODO(#49886): What is the correct way to parse them in general?
39
+ eq = strings .Index (env [1 :], "=" ) + 1
40
+ }
41
+ if eq < 0 {
42
+ t .Fatalf ("invalid variable in exported.Config.Env: %q" , env )
43
+ }
44
+ k := env [:eq ]
45
+ v := env [eq + 1 :]
46
+ if k == "GOPATH" {
47
+ gopath = v
48
+ }
49
+
50
+ if os .Getenv (k ) == v {
34
51
continue
35
52
}
36
- gopath = strings .TrimPrefix (env , "GOPATH=" )
53
+ defer func (prev string , prevOK bool ) {
54
+ if ! prevOK {
55
+ if err := os .Unsetenv (k ); err != nil {
56
+ t .Fatal (err )
57
+ }
58
+ } else {
59
+ if err := os .Setenv (k , prev ); err != nil {
60
+ t .Fatal (err )
61
+ }
62
+ }
63
+ }(os .LookupEnv (k ))
64
+
65
+ if err := os .Setenv (k , v ); err != nil {
66
+ t .Fatal (err )
67
+ }
68
+ t .Logf ("%s=%s" , k , v )
37
69
}
38
70
if gopath == "" {
39
71
t .Fatal ("Failed to fish GOPATH out of env: " , exported .Config .Env )
40
72
}
41
73
42
74
var buildContext = build .Default
43
75
buildContext .GOPATH = gopath
76
+ buildContext .Dir = exported .Config .Dir
77
+
78
+ forward , reverse , errs := importgraph .Build (& buildContext )
79
+ for path , err := range errs {
80
+ t .Errorf ("%s: %s" , path , err )
81
+ }
82
+ if t .Failed () {
83
+ return
84
+ }
85
+
86
+ // Log the complete graph before the errors, so that the errors are near the
87
+ // end of the log (where we expect them to be).
88
+ nodePrinted := map [string ]bool {}
89
+ printNode := func (direction string , from string ) {
90
+ key := fmt .Sprintf ("%s[%q]" , direction , from )
91
+ if nodePrinted [key ] {
92
+ return
93
+ }
94
+ nodePrinted [key ] = true
95
+
96
+ var g importgraph.Graph
97
+ switch direction {
98
+ case "forward" :
99
+ g = forward
100
+ case "reverse" :
101
+ g = reverse
102
+ default :
103
+ t .Helper ()
104
+ t .Fatalf ("bad direction: %q" , direction )
105
+ }
106
+
107
+ t .Log (key )
108
+ var pkgs []string
109
+ for pkg := range g [from ] {
110
+ pkgs = append (pkgs , pkg )
111
+ }
112
+ sort .Strings (pkgs )
113
+ for _ , pkg := range pkgs {
114
+ t .Logf ("\t %s" , pkg )
115
+ }
116
+ }
44
117
45
- forward , reverse , errors := importgraph .Build (& buildContext )
118
+ if testing .Verbose () {
119
+ printNode ("forward" , this )
120
+ printNode ("reverse" , this )
121
+ }
46
122
47
123
// Test direct edges.
48
124
// We throw in crypto/hmac to prove that external test files
49
125
// (such as this one) are inspected.
50
126
for _ , p := range []string {"go/build" , "testing" , "crypto/hmac" } {
51
127
if ! forward [this ][p ] {
52
- t .Errorf ("forward[importgraph][%s] not found" , p )
128
+ printNode ("forward" , this )
129
+ t .Errorf ("forward[%q][%q] not found" , this , p )
53
130
}
54
131
if ! reverse [p ][this ] {
55
- t .Errorf ("reverse[%s][importgraph] not found" , p )
132
+ printNode ("reverse" , p )
133
+ t .Errorf ("reverse[%q][%q] not found" , p , this )
56
134
}
57
135
}
58
136
59
137
// Test non-existent direct edges
60
138
for _ , p := range []string {"errors" , "reflect" } {
61
139
if forward [this ][p ] {
62
- t .Errorf ("unexpected: forward[importgraph][%s] found" , p )
140
+ printNode ("forward" , this )
141
+ t .Errorf ("unexpected: forward[%q][%q] found" , this , p )
63
142
}
64
143
if reverse [p ][this ] {
65
- t .Errorf ("unexpected: reverse[%s][importgraph] found" , p )
144
+ printNode ("reverse" , p )
145
+ t .Errorf ("unexpected: reverse[%q][%q] found" , p , this )
66
146
}
67
147
}
68
148
69
149
// Test Search is reflexive.
70
150
if ! forward .Search (this )[this ] {
151
+ printNode ("forward" , this )
71
152
t .Errorf ("irreflexive: forward.Search(importgraph)[importgraph] not found" )
72
153
}
73
154
if ! reverse .Search (this )[this ] {
155
+ printNode ("reverse" , this )
74
156
t .Errorf ("irrefexive: reverse.Search(importgraph)[importgraph] not found" )
75
157
}
76
158
77
159
// Test Search is transitive. (There is no direct edge to these packages.)
78
160
for _ , p := range []string {"errors" , "reflect" , "unsafe" } {
79
161
if ! forward .Search (this )[p ] {
162
+ printNode ("forward" , this )
80
163
t .Errorf ("intransitive: forward.Search(importgraph)[%s] not found" , p )
81
164
}
82
165
if ! reverse .Search (p )[this ] {
166
+ printNode ("reverse" , p )
83
167
t .Errorf ("intransitive: reverse.Search(%s)[importgraph] not found" , p )
84
168
}
85
169
}
@@ -95,26 +179,10 @@ func TestBuild(t *testing.T) {
95
179
! forward .Search ("io" )["fmt" ] ||
96
180
! reverse .Search ("fmt" )["io" ] ||
97
181
! reverse .Search ("io" )["fmt" ] {
182
+ printNode ("forward" , "fmt" )
183
+ printNode ("forward" , "io" )
184
+ printNode ("reverse" , "fmt" )
185
+ printNode ("reverse" , "io" )
98
186
t .Errorf ("fmt and io are not mutually reachable despite being in the same SCC" )
99
187
}
100
-
101
- // debugging
102
- if false {
103
- for path , err := range errors {
104
- t .Logf ("%s: %s" , path , err )
105
- }
106
- printSorted := func (direction string , g importgraph.Graph , start string ) {
107
- t .Log (direction )
108
- var pkgs []string
109
- for pkg := range g .Search (start ) {
110
- pkgs = append (pkgs , pkg )
111
- }
112
- sort .Strings (pkgs )
113
- for _ , pkg := range pkgs {
114
- t .Logf ("\t %s" , pkg )
115
- }
116
- }
117
- printSorted ("forward" , forward , this )
118
- printSorted ("reverse" , reverse , this )
119
- }
120
188
}
0 commit comments