Home | History | Annotate | Download | only in vet
      1 // Copyright 2013 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 package main_test
      6 
      7 import (
      8 	"bytes"
      9 	"internal/testenv"
     10 	"os"
     11 	"os/exec"
     12 	"path/filepath"
     13 	"runtime"
     14 	"testing"
     15 )
     16 
     17 const (
     18 	dataDir = "testdata"
     19 	binary  = "testvet.exe"
     20 )
     21 
     22 // Run this shell script, but do it in Go so it can be run by "go test".
     23 // 	go build -o testvet
     24 // 	$(GOROOT)/test/errchk ./testvet -shadow -printfuncs='Warn:1,Warnf:1' testdata/*.go testdata/*.s
     25 // 	rm testvet
     26 //
     27 func TestVet(t *testing.T) {
     28 	testenv.MustHaveGoBuild(t)
     29 
     30 	switch runtime.GOOS {
     31 	case "plan9", "windows":
     32 		// Plan 9 and Windows systems can't be guaranteed to have Perl and so can't run errchk.
     33 		t.Skipf("skipping test; no Perl on %q", runtime.GOOS)
     34 	}
     35 
     36 	// go build
     37 	cmd := exec.Command("go", "build", "-o", binary)
     38 	run(cmd, t)
     39 
     40 	// defer removal of vet
     41 	defer os.Remove(binary)
     42 
     43 	// errchk ./testvet
     44 	gos, err := filepath.Glob(filepath.Join(dataDir, "*.go"))
     45 	if err != nil {
     46 		t.Fatal(err)
     47 	}
     48 	asms, err := filepath.Glob(filepath.Join(dataDir, "*.s"))
     49 	if err != nil {
     50 		t.Fatal(err)
     51 	}
     52 	files := append(gos, asms...)
     53 	errchk := filepath.Join(runtime.GOROOT(), "test", "errchk")
     54 	flags := []string{
     55 		"./" + binary,
     56 		"-printfuncs=Warn:1,Warnf:1",
     57 		"-test", // TODO: Delete once -shadow is part of -all.
     58 	}
     59 	cmd = exec.Command(errchk, append(flags, files...)...)
     60 	if !run(cmd, t) {
     61 		t.Fatal("vet command failed")
     62 	}
     63 }
     64 
     65 func run(c *exec.Cmd, t *testing.T) bool {
     66 	output, err := c.CombinedOutput()
     67 	os.Stderr.Write(output)
     68 	if err != nil {
     69 		t.Fatal(err)
     70 	}
     71 	// Errchk delights by not returning non-zero status if it finds errors, so we look at the output.
     72 	// It prints "BUG" if there is a failure.
     73 	if !c.ProcessState.Success() {
     74 		return false
     75 	}
     76 	return !bytes.Contains(output, []byte("BUG"))
     77 }
     78 
     79 // TestTags verifies that the -tags argument controls which files to check.
     80 func TestTags(t *testing.T) {
     81 	testenv.MustHaveGoBuild(t)
     82 
     83 	// go build
     84 	cmd := exec.Command("go", "build", "-o", binary)
     85 	run(cmd, t)
     86 
     87 	// defer removal of vet
     88 	defer os.Remove(binary)
     89 
     90 	args := []string{
     91 		"-tags=testtag",
     92 		"-v", // We're going to look at the files it examines.
     93 		"testdata/tagtest",
     94 	}
     95 	cmd = exec.Command("./"+binary, args...)
     96 	output, err := cmd.CombinedOutput()
     97 	if err != nil {
     98 		t.Fatal(err)
     99 	}
    100 	// file1 has testtag and file2 has !testtag.
    101 	if !bytes.Contains(output, []byte(filepath.Join("tagtest", "file1.go"))) {
    102 		t.Error("file1 was excluded, should be included")
    103 	}
    104 	if bytes.Contains(output, []byte(filepath.Join("tagtest", "file2.go"))) {
    105 		t.Error("file2 was included, should be excluded")
    106 	}
    107 }
    108