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