golang.org/x/tools@v0.21.0/go/analysis/multichecker/multichecker_test.go (about)

     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  }