github.com/cockroachdb/tools@v0.0.0-20230222021103-a6d27438930d/cmd/fiximports/main_test.go (about) 1 // Copyright 2015 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 // No testdata on Android. 6 7 //go:build !android 8 // +build !android 9 10 package main 11 12 import ( 13 "bytes" 14 "log" 15 "os" 16 "path/filepath" 17 "runtime" 18 "strings" 19 "testing" 20 21 "golang.org/x/tools/internal/testenv" 22 ) 23 24 // TODO(adonovan): 25 // - test introduction of renaming imports. 26 // - test induced failures of rewriteFile. 27 28 // Guide to the test packages: 29 // 30 // new.com/one -- canonical name for old.com/one 31 // old.com/one -- non-canonical; has import comment "new.com/one" 32 // old.com/bad -- has a parse error 33 // fruit.io/orange \ 34 // fruit.io/banana } orange -> pear -> banana -> titanic.biz/bar 35 // fruit.io/pear / 36 // titanic.biz/bar -- domain is sinking; package has jumped ship to new.com/bar 37 // titanic.biz/foo -- domain is sinking but package has no import comment yet 38 39 var gopath = filepath.Join(cwd, "testdata") 40 41 func init() { 42 if err := os.Setenv("GOPATH", gopath); err != nil { 43 log.Fatal(err) 44 } 45 46 // This test currently requires GOPATH mode. 47 // Explicitly disabling module mode should suffix, but 48 // we'll also turn off GOPROXY just for good measure. 49 if err := os.Setenv("GO111MODULE", "off"); err != nil { 50 log.Fatal(err) 51 } 52 if err := os.Setenv("GOPROXY", "off"); err != nil { 53 log.Fatal(err) 54 } 55 } 56 57 func TestFixImports(t *testing.T) { 58 if os.Getenv("GO_BUILDER_NAME") == "plan9-arm" { 59 t.Skipf("skipping test that times out on plan9-arm; see https://go.dev/issue/50775") 60 } 61 testenv.NeedsTool(t, "go") 62 63 defer func() { 64 stderr = os.Stderr 65 *badDomains = "code.google.com" 66 *replaceFlag = "" 67 }() 68 69 for i, test := range []struct { 70 packages []string // packages to rewrite, "go list" syntax 71 badDomains string // -baddomains flag 72 replaceFlag string // -replace flag 73 wantOK bool 74 wantStderr string 75 wantRewrite map[string]string 76 }{ 77 // #0. No errors. 78 { 79 packages: []string{"all"}, 80 badDomains: "code.google.com", 81 wantOK: true, 82 wantStderr: ` 83 testdata/src/old.com/bad/bad.go:2:43: expected 'package', found 'EOF' 84 fruit.io/banana 85 fixed: old.com/one -> new.com/one 86 fixed: titanic.biz/bar -> new.com/bar 87 `, 88 wantRewrite: map[string]string{ 89 "$GOPATH/src/fruit.io/banana/banana.go": `package banana 90 91 import ( 92 _ "new.com/bar" 93 _ "new.com/one" 94 _ "titanic.biz/foo" 95 )`, 96 }, 97 }, 98 // #1. No packages needed rewriting. 99 { 100 packages: []string{"titanic.biz/...", "old.com/...", "new.com/..."}, 101 badDomains: "code.google.com", 102 wantOK: true, 103 wantStderr: ` 104 testdata/src/old.com/bad/bad.go:2:43: expected 'package', found 'EOF' 105 `, 106 }, 107 // #2. Some packages without import comments matched bad domains. 108 { 109 packages: []string{"all"}, 110 badDomains: "titanic.biz", 111 wantOK: false, 112 wantStderr: ` 113 testdata/src/old.com/bad/bad.go:2:43: expected 'package', found 'EOF' 114 fruit.io/banana 115 testdata/src/fruit.io/banana/banana.go:6: import "titanic.biz/foo" 116 fixed: old.com/one -> new.com/one 117 fixed: titanic.biz/bar -> new.com/bar 118 ERROR: titanic.biz/foo has no import comment 119 imported directly by: 120 fruit.io/pear 121 imported indirectly by: 122 fruit.io/orange 123 `, 124 wantRewrite: map[string]string{ 125 "$GOPATH/src/fruit.io/banana/banana.go": `package banana 126 127 import ( 128 _ "new.com/bar" 129 _ "new.com/one" 130 _ "titanic.biz/foo" 131 )`, 132 }, 133 }, 134 // #3. The -replace flag lets user supply missing import comments. 135 { 136 packages: []string{"all"}, 137 replaceFlag: "titanic.biz/foo=new.com/foo", 138 wantOK: true, 139 wantStderr: ` 140 testdata/src/old.com/bad/bad.go:2:43: expected 'package', found 'EOF' 141 fruit.io/banana 142 fixed: old.com/one -> new.com/one 143 fixed: titanic.biz/bar -> new.com/bar 144 fixed: titanic.biz/foo -> new.com/foo 145 `, 146 wantRewrite: map[string]string{ 147 "$GOPATH/src/fruit.io/banana/banana.go": `package banana 148 149 import ( 150 _ "new.com/bar" 151 _ "new.com/foo" 152 _ "new.com/one" 153 )`, 154 }, 155 }, 156 // #4. The -replace flag supports wildcards. 157 // An explicit import comment takes precedence. 158 { 159 packages: []string{"all"}, 160 replaceFlag: "titanic.biz/...=new.com/...", 161 wantOK: true, 162 wantStderr: ` 163 testdata/src/old.com/bad/bad.go:2:43: expected 'package', found 'EOF' 164 fruit.io/banana 165 fixed: old.com/one -> new.com/one 166 fixed: titanic.biz/bar -> new.com/bar 167 fixed: titanic.biz/foo -> new.com/foo 168 `, 169 wantRewrite: map[string]string{ 170 "$GOPATH/src/fruit.io/banana/banana.go": `package banana 171 172 import ( 173 _ "new.com/bar" 174 _ "new.com/foo" 175 _ "new.com/one" 176 )`, 177 }, 178 }, 179 // #5. The -replace flag trumps -baddomains. 180 { 181 packages: []string{"all"}, 182 badDomains: "titanic.biz", 183 replaceFlag: "titanic.biz/foo=new.com/foo", 184 wantOK: true, 185 wantStderr: ` 186 testdata/src/old.com/bad/bad.go:2:43: expected 'package', found 'EOF' 187 fruit.io/banana 188 fixed: old.com/one -> new.com/one 189 fixed: titanic.biz/bar -> new.com/bar 190 fixed: titanic.biz/foo -> new.com/foo 191 `, 192 wantRewrite: map[string]string{ 193 "$GOPATH/src/fruit.io/banana/banana.go": `package banana 194 195 import ( 196 _ "new.com/bar" 197 _ "new.com/foo" 198 _ "new.com/one" 199 )`, 200 }, 201 }, 202 } { 203 *badDomains = test.badDomains 204 *replaceFlag = test.replaceFlag 205 206 stderr = new(bytes.Buffer) 207 gotRewrite := make(map[string]string) 208 writeFile = func(filename string, content []byte, mode os.FileMode) error { 209 filename = strings.Replace(filename, gopath, "$GOPATH", 1) 210 filename = filepath.ToSlash(filename) 211 gotRewrite[filename] = string(bytes.TrimSpace(content)) 212 return nil 213 } 214 215 if runtime.GOOS == "windows" { 216 test.wantStderr = strings.Replace(test.wantStderr, `testdata/src/old.com/bad/bad.go`, `testdata\src\old.com\bad\bad.go`, -1) 217 test.wantStderr = strings.Replace(test.wantStderr, `testdata/src/fruit.io/banana/banana.go`, `testdata\src\fruit.io\banana\banana.go`, -1) 218 } 219 test.wantStderr = strings.TrimSpace(test.wantStderr) 220 221 // Check status code. 222 if fiximports(test.packages...) != test.wantOK { 223 t.Errorf("#%d. fiximports() = %t", i, !test.wantOK) 224 } 225 226 // Compare stderr output. 227 if got := strings.TrimSpace(stderr.(*bytes.Buffer).String()); got != test.wantStderr { 228 if strings.Contains(got, "vendor/golang_org/x/text/unicode/norm") { 229 t.Skip("skipping known-broken test; see golang.org/issue/17417") 230 } 231 t.Errorf("#%d. stderr: got <<\n%s\n>>, want <<\n%s\n>>", 232 i, got, test.wantStderr) 233 } 234 235 // Compare rewrites. 236 for k, v := range gotRewrite { 237 if test.wantRewrite[k] != v { 238 t.Errorf("#%d. rewrite[%s] = <<%s>>, want <<%s>>", 239 i, k, v, test.wantRewrite[k]) 240 } 241 delete(test.wantRewrite, k) 242 } 243 for k, v := range test.wantRewrite { 244 t.Errorf("#%d. rewrite[%s] missing, want <<%s>>", i, k, v) 245 } 246 } 247 } 248 249 // TestDryRun tests that the -n flag suppresses calls to writeFile. 250 func TestDryRun(t *testing.T) { 251 if os.Getenv("GO_BUILDER_NAME") == "plan9-arm" { 252 t.Skipf("skipping test that times out on plan9-arm; see https://go.dev/issue/50775") 253 } 254 testenv.NeedsTool(t, "go") 255 256 *dryrun = true 257 defer func() { *dryrun = false }() // restore 258 stderr = new(bytes.Buffer) 259 writeFile = func(filename string, content []byte, mode os.FileMode) error { 260 t.Fatalf("writeFile(%s) called in dryrun mode", filename) 261 return nil 262 } 263 264 if !fiximports("all") { 265 t.Fatalf("fiximports failed: %s", stderr) 266 } 267 }