github.com/0xKiwi/rules_go@v0.24.3/tests/core/nogo/vet/vet_test.go (about) 1 // Copyright 2019 The Bazel Authors. All rights reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package vet_test 16 17 import ( 18 "bytes" 19 "fmt" 20 "io/ioutil" 21 "regexp" 22 "testing" 23 24 "github.com/bazelbuild/rules_go/go/tools/bazel_testing" 25 ) 26 27 func TestMain(m *testing.M) { 28 bazel_testing.TestMain(m, bazel_testing.Args{ 29 Main: ` 30 -- BUILD.bazel -- 31 load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_tool_library", "nogo") 32 33 nogo( 34 name = "nogo", 35 vet = True, 36 visibility = ["//visibility:public"], 37 ) 38 39 go_library( 40 name = "has_errors", 41 srcs = ["has_errors.go"], 42 importpath = "haserrors", 43 deps = [":fmtwrap"], 44 ) 45 46 go_library( 47 name = "no_errors", 48 srcs = ["no_errors.go"], 49 cgo = True, 50 importpath = "noerrors", 51 ) 52 53 go_library( 54 name = "fmtwrap", 55 srcs = ["fmtwrap.go"], 56 importpath = "fmtwrap", 57 ) 58 59 -- has_errors.go -- 60 package haserrors 61 62 // +build build_tags_error 63 64 import ( 65 "fmtwrap" 66 "sync/atomic" 67 ) 68 69 func F() {} 70 71 func Foo() bool { 72 x := uint64(1) 73 _ = atomic.AddUint64(&x, 1) 74 if F == nil { // nilfunc error. 75 return false 76 } 77 fmtwrap.Printf("%b", "hi") // printf error. 78 return true || true // redundant boolean error. 79 } 80 81 -- no_errors.go -- 82 package noerrors 83 84 // const int x = 1; 85 import "C" 86 87 func Foo() bool { 88 return bool(C.x == 1) 89 } 90 91 -- fmtwrap.go -- 92 package fmtwrap 93 94 import "fmt" 95 96 func Printf(format string, args ...interface{}) { 97 fmt.Printf(format, args...) 98 } 99 `, 100 }) 101 } 102 103 func Test(t *testing.T) { 104 for _, test := range []struct { 105 desc, nogo, target string 106 wantSuccess bool 107 includes, excludes []string 108 }{ 109 { 110 desc: "default", 111 target: "//:has_errors", 112 wantSuccess: true, 113 excludes: []string{ 114 "\\+build comment must appear before package clause and be followed by a blank line", 115 "comparison of function F == nil is always false", 116 "Printf format %b has arg \"hi\" of wrong type string", 117 "redundant or: true \\|\\| true", 118 }, 119 }, { 120 desc: "enabled_no_errors", 121 target: "//:no_errors", 122 wantSuccess: true, 123 }, { 124 desc: "enabled_has_errors", 125 nogo: "@//:nogo", 126 target: "//:has_errors", 127 includes: []string{ 128 "\\+build comment must appear before package clause and be followed by a blank line", 129 "comparison of function F == nil is always false", 130 "Printf format %b has arg \"hi\" of wrong type string", 131 "redundant or: true \\|\\| true", 132 }, 133 }, 134 } { 135 t.Run(test.desc, func(t *testing.T) { 136 if test.nogo != "" { 137 origRegister := "go_register_toolchains()" 138 customRegister := fmt.Sprintf("go_register_toolchains(nogo = %q)", test.nogo) 139 if err := replaceInFile("WORKSPACE", origRegister, customRegister); err != nil { 140 t.Fatal(err) 141 } 142 defer replaceInFile("WORKSPACE", customRegister, origRegister) 143 } 144 145 cmd := bazel_testing.BazelCmd("build", test.target) 146 stderr := &bytes.Buffer{} 147 cmd.Stderr = stderr 148 if err := cmd.Run(); err == nil && !test.wantSuccess { 149 t.Fatal("unexpected success") 150 } else if err != nil && test.wantSuccess { 151 t.Fatalf("unexpected error: %v", err) 152 } 153 154 for _, pattern := range test.includes { 155 if matched, err := regexp.Match(pattern, stderr.Bytes()); err != nil { 156 t.Fatal(err) 157 } else if !matched { 158 t.Errorf("output did not contain pattern: %s", pattern) 159 } 160 } 161 for _, pattern := range test.excludes { 162 if matched, err := regexp.Match(pattern, stderr.Bytes()); err != nil { 163 t.Fatal(err) 164 } else if matched { 165 t.Errorf("output contained pattern: %s", pattern) 166 } 167 } 168 }) 169 } 170 } 171 172 func replaceInFile(path, old, new string) error { 173 data, err := ioutil.ReadFile(path) 174 if err != nil { 175 return err 176 } 177 data = bytes.ReplaceAll(data, []byte(old), []byte(new)) 178 return ioutil.WriteFile(path, data, 0666) 179 }