GoPLS Viewer

Home|gopls/go/analysis/unitchecker/unitchecker_test.go
1// Copyright 2018 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//go:build go1.12
6// +build go1.12
7
8package unitchecker_test
9
10// This test depends on features such as
11// go vet's support for vetx files (1.11) and
12// the (*os.ProcessState).ExitCode method (1.12).
13
14import (
15    "flag"
16    "os"
17    "os/exec"
18    "regexp"
19    "runtime"
20    "strings"
21    "testing"
22
23    "golang.org/x/tools/go/analysis/passes/assign"
24    "golang.org/x/tools/go/analysis/passes/findcall"
25    "golang.org/x/tools/go/analysis/passes/printf"
26    "golang.org/x/tools/go/analysis/unitchecker"
27    "golang.org/x/tools/go/packages/packagestest"
28)
29
30func TestMain(m *testing.M) {
31    if os.Getenv("UNITCHECKER_CHILD") == "1" {
32        // child process
33        main()
34        panic("unreachable")
35    }
36
37    flag.Parse()
38    os.Exit(m.Run())
39}
40
41func main() {
42    unitchecker.Main(
43        findcall.Analyzer,
44        printf.Analyzer,
45        assign.Analyzer,
46    )
47}
48
49// This is a very basic integration test of modular
50// analysis with facts using unitchecker under "go vet".
51// It fork/execs the main function above.
52func TestIntegration(t *testing.T) { packagestest.TestAll(ttestIntegration) }
53func testIntegration(t *testing.Texporter packagestest.Exporter) {
54    if runtime.GOOS != "linux" && runtime.GOOS != "darwin" {
55        t.Skipf("skipping fork/exec test on this platform")
56    }
57
58    exported := packagestest.Export(texporter, []packagestest.Module{{
59        Name"golang.org/fake",
60        Files: map[string]interface{}{
61            "a/a.go"`package a
62
63func _() {
64    MyFunc123()
65}
66
67func MyFunc123() {}
68`,
69            "b/b.go"`package b
70
71import "golang.org/fake/a"
72
73func _() {
74    a.MyFunc123()
75    MyFunc123()
76}
77
78func MyFunc123() {}
79`,
80            "c/c.go"`package c
81
82func _() {
83    i := 5
84    i = i
85}
86`,
87        }}})
88    defer exported.Cleanup()
89
90    const wantA = `# golang.org/fake/a
91([/._\-a-zA-Z0-9]+[\\/]fake[\\/])?a/a.go:4:11: call of MyFunc123\(...\)
92`
93    const wantB = `# golang.org/fake/b
94([/._\-a-zA-Z0-9]+[\\/]fake[\\/])?b/b.go:6:13: call of MyFunc123\(...\)
95([/._\-a-zA-Z0-9]+[\\/]fake[\\/])?b/b.go:7:11: call of MyFunc123\(...\)
96`
97    const wantC = `# golang.org/fake/c
98([/._\-a-zA-Z0-9]+[\\/]fake[\\/])?c/c.go:5:5: self-assignment of i to i
99`
100    const wantAJSON = `# golang.org/fake/a
101\{
102    "golang.org/fake/a": \{
103        "findcall": \[
104            \{
105                "posn": "([/._\-a-zA-Z0-9]+[\\/]fake[\\/])?a/a.go:4:11",
106                "message": "call of MyFunc123\(...\)",
107                "suggested_fixes": \[
108                    \{
109                        "message": "Add '_TEST_'",
110                        "edits": \[
111                            \{
112                                "filename": "([/._\-a-zA-Z0-9]+[\\/]fake[\\/])?a/a.go",
113                                "start": 32,
114                                "end": 32,
115                                "new": "_TEST_"
116                            \}
117                        \]
118                    \}
119                \]
120            \}
121        \]
122    \}
123\}
124`
125    const wantCJSON = `# golang.org/fake/c
126\{
127    "golang.org/fake/c": \{
128        "assign": \[
129            \{
130                "posn": "([/._\-a-zA-Z0-9]+[\\/]fake[\\/])?c/c.go:5:5",
131                "message": "self-assignment of i to i",
132                "suggested_fixes": \[
133                    \{
134                        "message": "Remove",
135                        "edits": \[
136                            \{
137                                "filename": "([/._\-a-zA-Z0-9]+[\\/]fake[\\/])?c/c.go",
138                                "start": 37,
139                                "end": 42,
140                                "new": ""
141                            \}
142                        \]
143                    \}
144                \]
145            \}
146        \]
147    \}
148\}
149`
150    for _test := range []struct {
151        args          string
152        wantOut       string
153        wantExitError bool
154    }{
155        {args"golang.org/fake/a"wantOutwantAwantExitErrortrue},
156        {args"golang.org/fake/b"wantOutwantBwantExitErrortrue},
157        {args"golang.org/fake/c"wantOutwantCwantExitErrortrue},
158        {args"golang.org/fake/a golang.org/fake/b"wantOutwantA + wantBwantExitErrortrue},
159        {args"-json golang.org/fake/a"wantOutwantAJSONwantExitErrorfalse},
160        {args"-json golang.org/fake/c"wantOutwantCJSONwantExitErrorfalse},
161        {args"-c=0 golang.org/fake/a"wantOutwantA + "4        MyFunc123\\(\\)\n"wantExitErrortrue},
162    } {
163        cmd := exec.Command("go""vet""-vettool="+os.Args[0], "-findcall.name=MyFunc123")
164        cmd.Args = append(cmd.Argsstrings.Fields(test.args)...)
165        cmd.Env = append(exported.Config.Env"UNITCHECKER_CHILD=1")
166        cmd.Dir = exported.Config.Dir
167
168        outerr := cmd.CombinedOutput()
169        exitcode := 0
170        if exitErrok := err.(*exec.ExitError); ok {
171            exitcode = exitErr.ExitCode()
172        }
173        if (exitcode != 0) != test.wantExitError {
174            want := "zero"
175            if test.wantExitError {
176                want = "nonzero"
177            }
178            t.Errorf("%s: got exit code %d, want %s"test.argsexitcodewant)
179        }
180
181        matchederr := regexp.Match(test.wantOutout)
182        if err != nil {
183            t.Fatalf("regexp.Match(<<%s>>): %v"test.wantOuterr)
184        }
185        if !matched {
186            t.Errorf("%s: got <<%s>>, want match of regexp <<%s>>"test.argsouttest.wantOut)
187        }
188    }
189}
190
MembersX
testIntegration.RangeStmt_3111.BlockStmt.exitcode
runtime
testing
TestMain.m
TestIntegration
TestIntegration.t
testIntegration
testIntegration.t
testIntegration.exporter
exec
regexp
packagestest
testIntegration.RangeStmt_3111.test
testIntegration.RangeStmt_3111.BlockStmt.cmd
testIntegration.wantB
testIntegration.wantC
testIntegration.wantAJSON
testIntegration.RangeStmt_3111.BlockStmt.BlockStmt.want
testIntegration.RangeStmt_3111.BlockStmt.matched
TestMain
testIntegration.wantCJSON
testIntegration.RangeStmt_3111.BlockStmt.err
testIntegration.RangeStmt_3111.BlockStmt.out
findcall
testIntegration.exported
testIntegration.wantA
Members
X