GoPLS Viewer

Home|gopls/refactor/importgraph/graph_test.go
1// Copyright 2015 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// Incomplete std lib sources on Android.
6
7//go:build !android
8// +build !android
9
10package importgraph_test
11
12import (
13    "fmt"
14    "go/build"
15    "os"
16    "sort"
17    "strings"
18    "testing"
19
20    "golang.org/x/tools/go/packages/packagestest"
21    "golang.org/x/tools/refactor/importgraph"
22
23    _ "crypto/hmac" // just for test, below
24)
25
26const this = "golang.org/x/tools/refactor/importgraph"
27
28func TestBuild(t *testing.T) {
29    exported := packagestest.Export(tpackagestest.GOPATH, []packagestest.Module{
30        {Name"golang.org/x/tools/refactor/importgraph"Filespackagestest.MustCopyFileTree(".")}})
31    defer exported.Cleanup()
32
33    var gopath string
34    for _env := range exported.Config.Env {
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 {
51            continue
52        }
53        defer func(prev stringprevOK bool) {
54            if !prevOK {
55                if err := os.Unsetenv(k); err != nil {
56                    t.Fatal(err)
57                }
58            } else {
59                if err := os.Setenv(kprev); err != nil {
60                    t.Fatal(err)
61                }
62            }
63        }(os.LookupEnv(k))
64
65        if err := os.Setenv(kv); err != nil {
66            t.Fatal(err)
67        }
68        t.Logf("%s=%s"kv)
69    }
70    if gopath == "" {
71        t.Fatal("Failed to fish GOPATH out of env: "exported.Config.Env)
72    }
73
74    var buildContext = build.Default
75    buildContext.GOPATH = gopath
76    buildContext.Dir = exported.Config.Dir
77
78    forwardreverseerrs := importgraph.Build(&buildContext)
79    for patherr := range errs {
80        t.Errorf("%s: %s"patherr)
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 stringfrom string) {
90        key := fmt.Sprintf("%s[%q]"directionfrom)
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(pkgspkg)
111        }
112        sort.Strings(pkgs)
113        for _pkg := range pkgs {
114            t.Logf("\t%s"pkg)
115        }
116    }
117
118    if testing.Verbose() {
119        printNode("forward"this)
120        printNode("reverse"this)
121    }
122
123    // Test direct edges.
124    // We throw in crypto/hmac to prove that external test files
125    // (such as this one) are inspected.
126    for _p := range []string{"go/build""testing""crypto/hmac"} {
127        if !forward[this][p] {
128            printNode("forward"this)
129            t.Errorf("forward[%q][%q] not found"thisp)
130        }
131        if !reverse[p][this] {
132            printNode("reverse"p)
133            t.Errorf("reverse[%q][%q] not found"pthis)
134        }
135    }
136
137    // Test non-existent direct edges
138    for _p := range []string{"errors""reflect"} {
139        if forward[this][p] {
140            printNode("forward"this)
141            t.Errorf("unexpected: forward[%q][%q] found"thisp)
142        }
143        if reverse[p][this] {
144            printNode("reverse"p)
145            t.Errorf("unexpected: reverse[%q][%q] found"pthis)
146        }
147    }
148
149    // Test Search is reflexive.
150    if !forward.Search(this)[this] {
151        printNode("forward"this)
152        t.Errorf("irreflexive: forward.Search(importgraph)[importgraph] not found")
153    }
154    if !reverse.Search(this)[this] {
155        printNode("reverse"this)
156        t.Errorf("irrefexive: reverse.Search(importgraph)[importgraph] not found")
157    }
158
159    // Test Search is transitive.  (There is no direct edge to these packages.)
160    for _p := range []string{"errors""reflect""unsafe"} {
161        if !forward.Search(this)[p] {
162            printNode("forward"this)
163            t.Errorf("intransitive: forward.Search(importgraph)[%s] not found"p)
164        }
165        if !reverse.Search(p)[this] {
166            printNode("reverse"p)
167            t.Errorf("intransitive: reverse.Search(%s)[importgraph] not found"p)
168        }
169    }
170
171    // Test strongly-connected components.  Because A's external
172    // test package can depend on B, and vice versa, most of the
173    // standard libraries are mutually dependent when their external
174    // tests are considered.
175    //
176    // For any nodes x, y in the same SCC, y appears in the results
177    // of both forward and reverse searches starting from x
178    if !forward.Search("fmt")["io"] ||
179        !forward.Search("io")["fmt"] ||
180        !reverse.Search("fmt")["io"] ||
181        !reverse.Search("io")["fmt"] {
182        printNode("forward""fmt")
183        printNode("forward""io")
184        printNode("reverse""fmt")
185        printNode("reverse""io")
186        t.Errorf("fmt and io are not mutually reachable despite being in the same SCC")
187    }
188}
189
MembersX
TestBuild.RangeStmt_3841.p
TestBuild.BlockStmt.RangeStmt_2572.pkg
TestBuild.RangeStmt_3162.p
TestBuild.RangeStmt_1847.err
this
TestBuild.buildContext
strings
_
TestBuild.t
TestBuild.RangeStmt_781.BlockStmt.BlockStmt.BlockStmt.err
TestBuild.RangeStmt_781.BlockStmt.err
TestBuild.forward
os
sort
TestBuild.BlockStmt.key
TestBuild.BlockStmt.RangeStmt_2490.pkg
TestBuild.reverse
TestBuild.RangeStmt_1847.path
TestBuild.nodePrinted
importgraph
TestBuild.RangeStmt_781.BlockStmt.eq
TestBuild
TestBuild.RangeStmt_781.env
TestBuild.gopath
TestBuild.RangeStmt_2840.p
packagestest
TestBuild.exported
fmt
testing
TestBuild.BlockStmt.pkgs
TestBuild.errs
TestBuild.BlockStmt.g
Members
X