github.com/wolfd/bazel-gazelle@v0.14.0/internal/language/go/fileinfo_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 golang 17 18 import ( 19 "io/ioutil" 20 "os" 21 "path/filepath" 22 "reflect" 23 "testing" 24 ) 25 26 func TestOtherFileInfo(t *testing.T) { 27 dir := "." 28 for _, tc := range []struct { 29 desc, name, source string 30 wantTags []tagLine 31 }{ 32 { 33 "empty file", 34 "foo.c", 35 "", 36 nil, 37 }, 38 { 39 "tags file", 40 "foo.c", 41 `// +build foo bar 42 // +build baz,!ignore 43 44 `, 45 []tagLine{{{"foo"}, {"bar"}}, {{"baz", "!ignore"}}}, 46 }, 47 } { 48 t.Run(tc.desc, func(t *testing.T) { 49 if err := ioutil.WriteFile(tc.name, []byte(tc.source), 0600); err != nil { 50 t.Fatal(err) 51 } 52 defer os.Remove(tc.name) 53 54 got := otherFileInfo(filepath.Join(dir, tc.name)) 55 56 // Only check that we can extract tags. Everything else is covered 57 // by other tests. 58 if !reflect.DeepEqual(got.tags, tc.wantTags) { 59 t.Errorf("got %#v; want %#v", got.tags, tc.wantTags) 60 } 61 }) 62 } 63 } 64 65 func TestFileNameInfo(t *testing.T) { 66 for _, tc := range []struct { 67 desc, name string 68 want fileInfo 69 }{ 70 { 71 "simple go file", 72 "simple.go", 73 fileInfo{ 74 ext: goExt, 75 }, 76 }, 77 { 78 "simple go test", 79 "foo_test.go", 80 fileInfo{ 81 ext: goExt, 82 isTest: true, 83 }, 84 }, 85 { 86 "test source", 87 "test.go", 88 fileInfo{ 89 ext: goExt, 90 isTest: false, 91 }, 92 }, 93 { 94 "_test source", 95 "_test.go", 96 fileInfo{ 97 ext: goExt, 98 isTest: true, 99 }, 100 }, 101 { 102 "source with goos", 103 "foo_linux.go", 104 fileInfo{ 105 ext: goExt, 106 goos: "linux", 107 }, 108 }, 109 { 110 "source with goarch", 111 "foo_amd64.go", 112 fileInfo{ 113 ext: goExt, 114 goarch: "amd64", 115 }, 116 }, 117 { 118 "source with goos then goarch", 119 "foo_linux_amd64.go", 120 fileInfo{ 121 ext: goExt, 122 goos: "linux", 123 goarch: "amd64", 124 }, 125 }, 126 { 127 "source with goarch then goos", 128 "foo_amd64_linux.go", 129 fileInfo{ 130 ext: goExt, 131 goos: "linux", 132 }, 133 }, 134 { 135 "test with goos and goarch", 136 "foo_linux_amd64_test.go", 137 fileInfo{ 138 ext: goExt, 139 goos: "linux", 140 goarch: "amd64", 141 isTest: true, 142 }, 143 }, 144 { 145 "test then goos", 146 "foo_test_linux.go", 147 fileInfo{ 148 ext: goExt, 149 goos: "linux", 150 }, 151 }, 152 { 153 "goos source", 154 "linux.go", 155 fileInfo{ 156 ext: goExt, 157 goos: "", 158 }, 159 }, 160 { 161 "goarch source", 162 "amd64.go", 163 fileInfo{ 164 ext: goExt, 165 goarch: "", 166 }, 167 }, 168 { 169 "goos test", 170 "linux_test.go", 171 fileInfo{ 172 ext: goExt, 173 goos: "", 174 isTest: true, 175 }, 176 }, 177 { 178 "c file", 179 "foo_test.cxx", 180 fileInfo{ 181 ext: cExt, 182 isTest: false, 183 }, 184 }, 185 { 186 "c os test file", 187 "foo_linux_test.c", 188 fileInfo{ 189 ext: cExt, 190 isTest: false, 191 goos: "linux", 192 }, 193 }, 194 { 195 "h file", 196 "foo_linux.h", 197 fileInfo{ 198 ext: hExt, 199 goos: "linux", 200 }, 201 }, 202 { 203 "go asm file", 204 "foo_amd64.s", 205 fileInfo{ 206 ext: sExt, 207 goarch: "amd64", 208 }, 209 }, 210 { 211 "c asm file", 212 "foo.S", 213 fileInfo{ 214 ext: csExt, 215 }, 216 }, 217 { 218 "unsupported file", 219 "foo.m", 220 fileInfo{ 221 ext: cExt, 222 }, 223 }, 224 { 225 "ignored test file", 226 "foo_test.py", 227 fileInfo{ 228 isTest: false, 229 }, 230 }, 231 { 232 "ignored xtest file", 233 "foo_xtest.py", 234 fileInfo{ 235 isTest: false, 236 }, 237 }, 238 { 239 "ignored file", 240 "foo.txt", 241 fileInfo{ 242 ext: unknownExt, 243 }, 244 }, 245 } { 246 tc.want.name = tc.name 247 tc.want.path = filepath.Join("dir", tc.name) 248 249 if got := fileNameInfo(tc.want.path); !reflect.DeepEqual(got, tc.want) { 250 t.Errorf("case %q: got %#v; want %#v", tc.desc, got, tc.want) 251 } 252 } 253 } 254 255 func TestReadTags(t *testing.T) { 256 for _, tc := range []struct { 257 desc, source string 258 want []tagLine 259 }{ 260 { 261 "empty file", 262 "", 263 nil, 264 }, 265 { 266 "single comment without blank line", 267 "// +build foo\npackage main", 268 nil, 269 }, 270 { 271 "multiple comments without blank link", 272 `// +build foo 273 274 // +build bar 275 package main 276 277 `, 278 []tagLine{{{"foo"}}}, 279 }, 280 { 281 "single comment", 282 "// +build foo\n\n", 283 []tagLine{{{"foo"}}}, 284 }, 285 { 286 "multiple comments", 287 `// +build foo 288 // +build bar 289 290 package main`, 291 []tagLine{{{"foo"}}, {{"bar"}}}, 292 }, 293 { 294 "multiple comments with blank", 295 `// +build foo 296 297 // +build bar 298 299 package main`, 300 []tagLine{{{"foo"}}, {{"bar"}}}, 301 }, 302 { 303 "comment with space", 304 " // +build foo bar \n\n", 305 []tagLine{{{"foo"}, {"bar"}}}, 306 }, 307 { 308 "slash star comment", 309 "/* +build foo */\n\n", 310 nil, 311 }, 312 } { 313 f, err := ioutil.TempFile(".", "TestReadTags") 314 if err != nil { 315 t.Fatal(err) 316 } 317 path := f.Name() 318 defer os.Remove(path) 319 if err = f.Close(); err != nil { 320 t.Fatal(err) 321 } 322 if err = ioutil.WriteFile(path, []byte(tc.source), 0600); err != nil { 323 t.Fatal(err) 324 } 325 326 if got, err := readTags(path); err != nil { 327 t.Fatal(err) 328 } else if !reflect.DeepEqual(got, tc.want) { 329 t.Errorf("case %q: got %#v; want %#v", tc.desc, got, tc.want) 330 } 331 } 332 } 333 334 func TestCheckConstraints(t *testing.T) { 335 dir, err := ioutil.TempDir(os.Getenv("TEST_TEMPDIR"), "TestCheckConstraints") 336 if err != nil { 337 t.Fatal(err) 338 } 339 defer os.RemoveAll(dir) 340 for _, tc := range []struct { 341 desc string 342 genericTags map[string]bool 343 os, arch, filename, content string 344 want bool 345 }{ 346 { 347 desc: "unconstrained", 348 want: true, 349 }, { 350 desc: "goos satisfied", 351 filename: "foo_linux.go", 352 os: "linux", 353 want: true, 354 }, { 355 desc: "goos unsatisfied", 356 filename: "foo_linux.go", 357 os: "darwin", 358 want: false, 359 }, { 360 desc: "goarch satisfied", 361 filename: "foo_amd64.go", 362 arch: "amd64", 363 want: true, 364 }, { 365 desc: "goarch unsatisfied", 366 filename: "foo_amd64.go", 367 arch: "arm", 368 want: false, 369 }, { 370 desc: "goos goarch satisfied", 371 filename: "foo_linux_amd64.go", 372 os: "linux", 373 arch: "amd64", 374 want: true, 375 }, { 376 desc: "goos goarch unsatisfied", 377 filename: "foo_linux_amd64.go", 378 os: "darwin", 379 arch: "amd64", 380 want: false, 381 }, { 382 desc: "goos unsatisfied tags satisfied", 383 filename: "foo_linux.go", 384 content: "// +build foo\n\npackage foo", 385 want: false, 386 }, { 387 desc: "tags all satisfied", 388 genericTags: map[string]bool{"a": true, "b": true}, 389 content: "// +build a,b\n\npackage foo", 390 want: true, 391 }, { 392 desc: "tags some satisfied", 393 genericTags: map[string]bool{"a": true}, 394 content: "// +build a,b\n\npackage foo", 395 want: false, 396 }, { 397 desc: "tag unsatisfied negated", 398 content: "// +build !a\n\npackage foo", 399 want: true, 400 }, { 401 desc: "tag satisfied negated", 402 genericTags: map[string]bool{"a": true}, 403 content: "// +build !a\n\npackage foo", 404 want: false, 405 }, { 406 desc: "tag double negative", 407 content: "// +build !!a\n\npackage foo", 408 want: false, 409 }, { 410 desc: "tag group and satisfied", 411 genericTags: map[string]bool{"foo": true, "bar": true}, 412 content: "// +build foo,bar\n\npackage foo", 413 want: true, 414 }, { 415 desc: "tag group and unsatisfied", 416 genericTags: map[string]bool{"foo": true}, 417 content: "// +build foo,bar\n\npackage foo", 418 want: false, 419 }, { 420 desc: "tag line or satisfied", 421 genericTags: map[string]bool{"foo": true}, 422 content: "// +build foo bar\n\npackage foo", 423 want: true, 424 }, { 425 desc: "tag line or unsatisfied", 426 genericTags: map[string]bool{"foo": true}, 427 content: "// +build !foo bar\n\npackage foo", 428 want: false, 429 }, { 430 desc: "tag lines and satisfied", 431 genericTags: map[string]bool{"foo": true, "bar": true}, 432 content: ` 433 // +build foo 434 // +build bar 435 436 package foo`, 437 want: true, 438 }, { 439 desc: "tag lines and unsatisfied", 440 genericTags: map[string]bool{"foo": true}, 441 content: ` 442 // +build foo 443 // +build bar 444 445 package foo`, 446 want: false, 447 }, { 448 desc: "cgo tags satisfied", 449 os: "linux", 450 genericTags: map[string]bool{"foo": true}, 451 content: ` 452 // +build foo 453 454 package foo 455 456 /* 457 #cgo linux CFLAGS: -Ilinux 458 */ 459 import "C" 460 `, 461 want: true, 462 }, { 463 desc: "cgo tags unsatisfied", 464 os: "linux", 465 content: ` 466 package foo 467 468 /* 469 #cgo !linux CFLAGS: -Inotlinux 470 */ 471 import "C" 472 `, 473 want: false, 474 }, { 475 desc: "release tags", 476 content: "// +build go1.7,go1.8,go1.9,go1.91,go2.0\n\npackage foo", 477 want: true, 478 }, { 479 desc: "release tag negated", 480 content: "// +build !go1.8\n\npackage foo", 481 want: true, 482 }, { 483 desc: "cgo tag", 484 content: "// +build cgo", 485 want: true, 486 }, { 487 desc: "cgo tag negated", 488 content: "// +build !cgo", 489 want: true, 490 }, { 491 desc: "race msan tags", 492 content: "// +build msan race", 493 want: true, 494 }, { 495 desc: "race msan tags negated", 496 content: "//+ build !msan,!race", 497 want: true, 498 }, 499 } { 500 t.Run(tc.desc, func(t *testing.T) { 501 c, _, _ := testConfig() 502 gc := getGoConfig(c) 503 gc.genericTags = tc.genericTags 504 if gc.genericTags == nil { 505 gc.genericTags = map[string]bool{"gc": true} 506 } 507 filename := tc.filename 508 if filename == "" { 509 filename = tc.desc + ".go" 510 } 511 content := []byte(tc.content) 512 if len(content) == 0 { 513 content = []byte(`package foo`) 514 } 515 516 path := filepath.Join(dir, filename) 517 if err := ioutil.WriteFile(path, []byte(content), 0666); err != nil { 518 t.Fatal(err) 519 } 520 521 fi := goFileInfo(path, "") 522 var cgoTags tagLine 523 if len(fi.copts) > 0 { 524 cgoTags = fi.copts[0].tags 525 } 526 527 got := checkConstraints(c, tc.os, tc.arch, fi.goos, fi.goarch, fi.tags, cgoTags) 528 if got != tc.want { 529 t.Errorf("got %v ; want %v", got, tc.want) 530 } 531 }) 532 } 533 }