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