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 | |
8 | package multichecker_test |
9 | |
10 | import ( |
11 | "fmt" |
12 | "os" |
13 | "os/exec" |
14 | "runtime" |
15 | "testing" |
16 | |
17 | "golang.org/x/tools/go/analysis" |
18 | "golang.org/x/tools/go/analysis/multichecker" |
19 | "golang.org/x/tools/go/analysis/passes/findcall" |
20 | "golang.org/x/tools/internal/testenv" |
21 | ) |
22 | |
23 | func main() { |
24 | fail := &analysis.Analyzer{ |
25 | Name: "fail", |
26 | Doc: "always fail on a package 'sort'", |
27 | Run: func(pass *analysis.Pass) (interface{}, error) { |
28 | if pass.Pkg.Path() == "sort" { |
29 | return nil, fmt.Errorf("failed") |
30 | } |
31 | return nil, nil |
32 | }, |
33 | } |
34 | multichecker.Main(findcall.Analyzer, fail) |
35 | } |
36 | |
37 | // TestExitCode ensures that analysis failures are reported correctly. |
38 | // This test fork/execs the main function above. |
39 | func TestExitCode(t *testing.T) { |
40 | if runtime.GOOS != "linux" { |
41 | t.Skipf("skipping fork/exec test on this platform") |
42 | } |
43 | |
44 | if os.Getenv("MULTICHECKER_CHILD") == "1" { |
45 | // child process |
46 | |
47 | // replace [progname -test.run=TestExitCode -- ...] |
48 | // by [progname ...] |
49 | os.Args = os.Args[2:] |
50 | os.Args[0] = "vet" |
51 | main() |
52 | panic("unreachable") |
53 | } |
54 | |
55 | testenv.NeedsTool(t, "go") |
56 | |
57 | for _, test := range []struct { |
58 | args []string |
59 | want int |
60 | }{ |
61 | {[]string{"nosuchdir/..."}, 1}, // matched no packages |
62 | {[]string{"nosuchpkg"}, 1}, // matched no packages |
63 | {[]string{"-unknownflag"}, 2}, // flag error |
64 | {[]string{"-findcall.name=panic", "io"}, 3}, // finds diagnostics |
65 | {[]string{"-findcall=0", "io"}, 0}, // no checkers |
66 | {[]string{"-findcall.name=nosuchfunc", "io"}, 0}, // no diagnostics |
67 | {[]string{"-findcall.name=panic", "sort", "io"}, 1}, // 'fail' failed on 'sort' |
68 | |
69 | // -json: exits zero even in face of diagnostics or package errors. |
70 | {[]string{"-findcall.name=panic", "-json", "io"}, 0}, |
71 | {[]string{"-findcall.name=panic", "-json", "io"}, 0}, |
72 | {[]string{"-findcall.name=panic", "-json", "sort", "io"}, 0}, |
73 | } { |
74 | args := []string{"-test.run=TestExitCode", "--"} |
75 | args = append(args, test.args...) |
76 | cmd := exec.Command(os.Args[0], args...) |
77 | cmd.Env = append(os.Environ(), "MULTICHECKER_CHILD=1") |
78 | out, err := cmd.CombinedOutput() |
79 | if len(out) > 0 { |
80 | t.Logf("%s: out=<<%s>>", test.args, out) |
81 | } |
82 | var exitcode int |
83 | if err, ok := err.(*exec.ExitError); ok { |
84 | exitcode = err.ExitCode() // requires go1.12 |
85 | } |
86 | if exitcode != test.want { |
87 | t.Errorf("%s: exited %d, want %d", test.args, exitcode, test.want) |
88 | } |
89 | } |
90 | } |
91 |
Members