github.com/afking/bazel-gazelle@v0.0.0-20180301150245-c02bc0f529e8/internal/packages/fileinfo_go_test.go (about) 1 /* Copyright 2017 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 16 package packages 17 18 import ( 19 "io/ioutil" 20 "os" 21 "path/filepath" 22 "reflect" 23 "strings" 24 "testing" 25 26 "github.com/bazelbuild/bazel-gazelle/internal/config" 27 ) 28 29 func TestGoFileInfo(t *testing.T) { 30 c := &config.Config{} 31 dir := "." 32 rel := "" 33 for _, tc := range []struct { 34 desc, name, source string 35 want fileInfo 36 }{ 37 { 38 "empty file", 39 "foo.go", 40 "package foo\n", 41 fileInfo{ 42 packageName: "foo", 43 }, 44 }, 45 { 46 "xtest file", 47 "foo_test.go", 48 "package foo_test\n", 49 fileInfo{ 50 packageName: "foo", 51 isTest: true, 52 isXTest: true, 53 }, 54 }, 55 { 56 "xtest suffix on non-test", 57 "foo_xtest.go", 58 "package foo_test\n", 59 fileInfo{ 60 packageName: "foo_test", 61 isTest: false, 62 isXTest: false, 63 }, 64 }, 65 { 66 "single import", 67 "foo.go", 68 `package foo 69 70 import "github.com/foo/bar" 71 `, 72 fileInfo{ 73 packageName: "foo", 74 imports: []string{"github.com/foo/bar"}, 75 }, 76 }, 77 { 78 "multiple imports", 79 "foo.go", 80 `package foo 81 82 import ( 83 "github.com/foo/bar" 84 x "github.com/local/project/y" 85 ) 86 `, 87 fileInfo{ 88 packageName: "foo", 89 imports: []string{"github.com/foo/bar", "github.com/local/project/y"}, 90 }, 91 }, 92 { 93 "standard imports included", 94 "foo.go", 95 `package foo 96 97 import "fmt" 98 `, 99 fileInfo{ 100 packageName: "foo", 101 imports: []string{"fmt"}, 102 }, 103 }, 104 { 105 "cgo", 106 "foo.go", 107 `package foo 108 109 import "C" 110 `, 111 fileInfo{ 112 packageName: "foo", 113 isCgo: true, 114 }, 115 }, 116 { 117 "build tags", 118 "foo.go", 119 `// +build linux darwin 120 121 // +build !ignore 122 123 package foo 124 `, 125 fileInfo{ 126 packageName: "foo", 127 tags: []tagLine{{{"linux"}, {"darwin"}}, {{"!ignore"}}}, 128 }, 129 }, 130 { 131 "build tags without blank line", 132 "route.go", 133 `// Copyright 2017 134 135 // +build darwin dragonfly freebsd netbsd openbsd 136 137 // Package route provides basic functions for the manipulation of 138 // packet routing facilities on BSD variants. 139 package route 140 `, 141 fileInfo{ 142 packageName: "route", 143 tags: []tagLine{{{"darwin"}, {"dragonfly"}, {"freebsd"}, {"netbsd"}, {"openbsd"}}}, 144 }, 145 }, 146 } { 147 if err := ioutil.WriteFile(tc.name, []byte(tc.source), 0600); err != nil { 148 t.Fatal(err) 149 } 150 defer os.Remove(tc.name) 151 152 got := goFileInfo(c, dir, rel, tc.name) 153 154 // Clear fields we don't care about for testing. 155 got = fileInfo{ 156 packageName: got.packageName, 157 isTest: got.isTest, 158 isXTest: got.isXTest, 159 imports: got.imports, 160 isCgo: got.isCgo, 161 tags: got.tags, 162 } 163 164 if !reflect.DeepEqual(got, tc.want) { 165 t.Errorf("case %q: got %#v; want %#v", tc.desc, got, tc.want) 166 } 167 } 168 } 169 170 func TestGoFileInfoFailure(t *testing.T) { 171 dir := "." 172 name := "foo_linux_amd64.go" 173 if err := ioutil.WriteFile(name, []byte("pakcage foo"), 0600); err != nil { 174 t.Fatal(err) 175 } 176 defer os.Remove(name) 177 178 c := &config.Config{} 179 got := goFileInfo(c, dir, "", name) 180 want := fileInfo{ 181 path: filepath.Join(dir, name), 182 name: name, 183 ext: ".go", 184 category: goExt, 185 goos: "linux", 186 goarch: "amd64", 187 } 188 if !reflect.DeepEqual(got, want) { 189 t.Errorf("got %#v ; want %#v", got, want) 190 } 191 } 192 193 func TestCgo(t *testing.T) { 194 c := &config.Config{} 195 dir := "." 196 rel := "" 197 for _, tc := range []struct { 198 desc, source string 199 want fileInfo 200 }{ 201 { 202 "not cgo", 203 "package foo\n", 204 fileInfo{isCgo: false}, 205 }, 206 { 207 "empty cgo", 208 `package foo 209 210 import "C" 211 `, 212 fileInfo{isCgo: true}, 213 }, 214 { 215 "simple flags", 216 `package foo 217 218 /* 219 #cgo CFLAGS: -O0 220 #cgo CPPFLAGS: -O1 221 #cgo CXXFLAGS: -O2 222 #cgo LDFLAGS: -O3 -O4 223 */ 224 import "C" 225 `, 226 fileInfo{ 227 isCgo: true, 228 copts: []taggedOpts{ 229 {opts: "-O0"}, 230 {opts: "-O1"}, 231 {opts: "-O2"}, 232 }, 233 clinkopts: []taggedOpts{ 234 {opts: strings.Join([]string{"-O3", "-O4"}, OptSeparator)}, 235 }, 236 }, 237 }, 238 { 239 "cflags with conditions", 240 `package foo 241 242 /* 243 #cgo foo bar,!baz CFLAGS: -O0 244 */ 245 import "C" 246 `, 247 fileInfo{ 248 isCgo: true, 249 copts: []taggedOpts{ 250 { 251 tags: tagLine{{"foo"}, {"bar", "!baz"}}, 252 opts: "-O0", 253 }, 254 }, 255 }, 256 }, 257 { 258 "slashslash comments", 259 `package foo 260 261 // #cgo CFLAGS: -O0 262 // #cgo CFLAGS: -O1 263 import "C" 264 `, 265 fileInfo{ 266 isCgo: true, 267 copts: []taggedOpts{ 268 {opts: "-O0"}, 269 {opts: "-O1"}, 270 }, 271 }, 272 }, 273 { 274 "comment above single import group", 275 `package foo 276 277 /* 278 #cgo CFLAGS: -O0 279 */ 280 import ("C") 281 `, 282 fileInfo{ 283 isCgo: true, 284 copts: []taggedOpts{ 285 {opts: "-O0"}, 286 }, 287 }, 288 }, 289 } { 290 path := "TestCgo.go" 291 if err := ioutil.WriteFile(path, []byte(tc.source), 0600); err != nil { 292 t.Fatal(err) 293 } 294 defer os.Remove(path) 295 296 got := goFileInfo(c, dir, rel, path) 297 298 // Clear fields we don't care about for testing. 299 got = fileInfo{isCgo: got.isCgo, copts: got.copts, clinkopts: got.clinkopts} 300 301 if !reflect.DeepEqual(got, tc.want) { 302 t.Errorf("case %q: got %#v; want %#v", tc.desc, got, tc.want) 303 } 304 } 305 } 306 307 // Copied from go/build build_test.go 308 var ( 309 expandSrcDirPath = filepath.Join(string(filepath.Separator)+"projects", "src", "add") 310 ) 311 312 // Copied from go/build build_test.go 313 var expandSrcDirTests = []struct { 314 input, expected string 315 }{ 316 {"-L ${SRCDIR}/libs -ladd", "-L /projects/src/add/libs -ladd"}, 317 {"${SRCDIR}/add_linux_386.a -pthread -lstdc++", "/projects/src/add/add_linux_386.a -pthread -lstdc++"}, 318 {"Nothing to expand here!", "Nothing to expand here!"}, 319 {"$", "$"}, 320 {"$$", "$$"}, 321 {"${", "${"}, 322 {"$}", "$}"}, 323 {"$FOO ${BAR}", "$FOO ${BAR}"}, 324 {"Find me the $SRCDIRECTORY.", "Find me the $SRCDIRECTORY."}, 325 {"$SRCDIR is missing braces", "$SRCDIR is missing braces"}, 326 } 327 328 // Copied from go/build build_test.go 329 func TestExpandSrcDir(t *testing.T) { 330 for _, test := range expandSrcDirTests { 331 output, _ := expandSrcDir(test.input, expandSrcDirPath) 332 if output != test.expected { 333 t.Errorf("%q expands to %q with SRCDIR=%q when %q is expected", test.input, output, expandSrcDirPath, test.expected) 334 } else { 335 t.Logf("%q expands to %q with SRCDIR=%q", test.input, output, expandSrcDirPath) 336 } 337 } 338 } 339 340 func TestExpandSrcDirRepoRelative(t *testing.T) { 341 repo, err := ioutil.TempDir(os.Getenv("TEST_TEMPDIR"), "repo") 342 if err != nil { 343 t.Fatal(err) 344 } 345 sub := filepath.Join(repo, "sub") 346 if err := os.Mkdir(sub, 0755); err != nil { 347 t.Fatal(err) 348 } 349 goFile := filepath.Join(sub, "sub.go") 350 content := []byte(`package sub 351 352 /* 353 #cgo CFLAGS: -I${SRCDIR}/.. 354 */ 355 import "C" 356 `) 357 if err := ioutil.WriteFile(goFile, content, 0644); err != nil { 358 t.Fatal(err) 359 } 360 c := &config.Config{ 361 RepoRoot: repo, 362 GoPrefix: "example.com/repo", 363 } 364 got := buildPackage(c, sub, "sub", []string{"sub.go"}, nil, nil, false) 365 want := &Package{ 366 Name: "sub", 367 Dir: sub, 368 Rel: "sub", 369 ImportPath: "example.com/repo/sub", 370 Library: GoTarget{ 371 Sources: PlatformStrings{ 372 Generic: []string{"sub.go"}, 373 }, 374 COpts: PlatformStrings{ 375 Generic: []string{"-Isub/.."}, 376 }, 377 Cgo: true, 378 }, 379 } 380 if !reflect.DeepEqual(got, want) { 381 t.Errorf("got %#v ; want %#v", got, want) 382 } 383 } 384 385 // Copied from go/build build_test.go 386 func TestShellSafety(t *testing.T) { 387 tests := []struct { 388 input, srcdir, expected string 389 result bool 390 }{ 391 {"-I${SRCDIR}/../include", "/projects/src/issue 11868", "-I/projects/src/issue 11868/../include", true}, 392 {"-I${SRCDIR}", "wtf$@%", "-Iwtf$@%", true}, 393 {"-X${SRCDIR}/1,${SRCDIR}/2", "/projects/src/issue 11868", "-X/projects/src/issue 11868/1,/projects/src/issue 11868/2", true}, 394 {"-I/tmp -I/tmp", "/tmp2", "-I/tmp -I/tmp", false}, 395 {"-I/tmp", "/tmp/[0]", "-I/tmp", true}, 396 {"-I${SRCDIR}/dir", "/tmp/[0]", "-I/tmp/[0]/dir", false}, 397 } 398 for _, test := range tests { 399 output, ok := expandSrcDir(test.input, test.srcdir) 400 if ok != test.result { 401 t.Errorf("Expected %t while %q expands to %q with SRCDIR=%q; got %t", test.result, test.input, output, test.srcdir, ok) 402 } 403 if output != test.expected { 404 t.Errorf("Expected %q while %q expands with SRCDIR=%q; got %q", test.expected, test.input, test.srcdir, output) 405 } 406 } 407 }