github.com/afking/bazel-gazelle@v0.0.0-20180301150245-c02bc0f529e8/cmd/gazelle/integration_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 // This file contains integration tests for all of Gazelle. It's meant to test 17 // common usage patterns and check for errors that are difficult to test in 18 // unit tests. 19 20 package main 21 22 import ( 23 "io/ioutil" 24 "os" 25 "path/filepath" 26 "strings" 27 "testing" 28 29 "github.com/bazelbuild/bazel-gazelle/internal/config" 30 "github.com/bazelbuild/bazel-gazelle/internal/wspace" 31 ) 32 33 type fileSpec struct { 34 path, content string 35 } 36 37 func createFiles(files []fileSpec) (string, error) { 38 dir, err := ioutil.TempDir(os.Getenv("TEST_TEMPDIR"), "integration_test") 39 if err != nil { 40 return "", err 41 } 42 43 for _, f := range files { 44 path := filepath.Join(dir, filepath.FromSlash(f.path)) 45 if strings.HasSuffix(f.path, "/") { 46 if err := os.MkdirAll(path, 0700); err != nil { 47 os.RemoveAll(dir) 48 return "", err 49 } 50 continue 51 } 52 if err := os.MkdirAll(filepath.Dir(path), 0700); err != nil { 53 os.RemoveAll(dir) 54 return "", err 55 } 56 if err := ioutil.WriteFile(path, []byte(f.content), 0600); err != nil { 57 os.RemoveAll(dir) 58 return "", err 59 } 60 } 61 return dir, nil 62 } 63 64 // skipIfWorkspaceVisible skips the test if the WORKSPACE file for the 65 // repository is visible. This happens in newer Bazel versions when tests 66 // are run without sandboxing, since temp directories may be inside the 67 // exec root. 68 func skipIfWorkspaceVisible(t *testing.T, dir string) { 69 if parent, err := wspace.Find(dir); err == nil { 70 t.Skipf("WORKSPACE visible in parent %q of tmp %q", parent, dir) 71 } 72 } 73 74 func checkFiles(t *testing.T, dir string, files []fileSpec) { 75 for _, f := range files { 76 path := filepath.Join(dir, f.path) 77 if strings.HasSuffix(f.path, "/") { 78 if st, err := os.Stat(path); err != nil { 79 t.Errorf("could not stat %s: %v", f.path, err) 80 } else if !st.IsDir() { 81 t.Errorf("not a directory: %s", f.path) 82 } 83 } else { 84 want := f.content 85 if len(want) > 0 && want[0] == '\n' { 86 // Strip leading newline, added for readability. 87 want = want[1:] 88 } 89 gotBytes, err := ioutil.ReadFile(filepath.Join(dir, f.path)) 90 if err != nil { 91 t.Errorf("could not read %s: %v", f.path, err) 92 continue 93 } 94 got := string(gotBytes) 95 if got != want { 96 t.Errorf("%s: got %s ; want %s", f.path, got, f.content) 97 } 98 } 99 } 100 } 101 102 func runGazelle(wd string, args []string) error { 103 oldWd, err := os.Getwd() 104 if err != nil { 105 return err 106 } 107 if err := os.Chdir(wd); err != nil { 108 return err 109 } 110 defer os.Chdir(oldWd) 111 112 return run(args) 113 } 114 115 func TestNoRepoRootOrWorkspace(t *testing.T) { 116 dir, err := createFiles(nil) 117 if err != nil { 118 t.Fatal(err) 119 } 120 defer os.RemoveAll(dir) 121 skipIfWorkspaceVisible(t, dir) 122 want := "-repo_root not specified" 123 if err := runGazelle(dir, nil); err == nil { 124 t.Fatalf("got success; want %q", want) 125 } else if !strings.Contains(err.Error(), want) { 126 t.Fatalf("got %q; want %q", err, want) 127 } 128 } 129 130 func TestNoGoPrefixArgOrRule(t *testing.T) { 131 dir, err := createFiles([]fileSpec{ 132 {path: "WORKSPACE", content: ""}, 133 }) 134 if err != nil { 135 t.Fatal(err) 136 } 137 want := "-go_prefix not set" 138 if err := runGazelle(dir, nil); err == nil { 139 t.Fatalf("got success; want %q", want) 140 } else if !strings.Contains(err.Error(), want) { 141 t.Fatalf("got %q; want %q", err, want) 142 } 143 } 144 145 // TestSelectLabelsSorted checks that string lists in srcs and deps are sorted 146 // using buildifier order, even if they are inside select expressions. 147 // This applies to both new and existing lists and should preserve comments. 148 // buildifier does not do this yet bazelbuild/buildtools#122, so we do this 149 // in addition to calling build.Rewrite. 150 func TestSelectLabelsSorted(t *testing.T) { 151 dir, err := createFiles([]fileSpec{ 152 {path: "WORKSPACE"}, 153 { 154 path: "BUILD", 155 content: ` 156 load("@io_bazel_rules_go//go:def.bzl", "go_library") 157 158 go_library( 159 name = "go_default_library", 160 srcs = select({ 161 "@io_bazel_rules_go//go/platform:linux": [ 162 # top comment 163 "foo.go", # side comment 164 # bar comment 165 "bar.go", 166 ], 167 "//conditions:default": [], 168 }), 169 importpath = "example.com/foo", 170 ) 171 `, 172 }, 173 { 174 path: "foo.go", 175 content: ` 176 // +build linux 177 178 package foo 179 180 import ( 181 _ "example.com/foo/outer" 182 _ "example.com/foo/outer/inner" 183 _ "github.com/jr_hacker/tools" 184 ) 185 `, 186 }, 187 { 188 path: "bar.go", 189 content: `// +build linux 190 191 package foo 192 `, 193 }, 194 {path: "outer/outer.go", content: "package outer"}, 195 {path: "outer/inner/inner.go", content: "package inner"}, 196 }) 197 want := `load("@io_bazel_rules_go//go:def.bzl", "go_library") 198 199 go_library( 200 name = "go_default_library", 201 srcs = select({ 202 "@io_bazel_rules_go//go/platform:linux": [ 203 # top comment 204 # bar comment 205 "bar.go", 206 "foo.go", # side comment 207 ], 208 "//conditions:default": [], 209 }), 210 importpath = "example.com/foo", 211 visibility = ["//visibility:public"], 212 deps = select({ 213 "@io_bazel_rules_go//go/platform:linux": [ 214 "//outer:go_default_library", 215 "//outer/inner:go_default_library", 216 "@com_github_jr_hacker_tools//:go_default_library", 217 ], 218 "//conditions:default": [], 219 }), 220 ) 221 ` 222 if err != nil { 223 t.Fatal(err) 224 } 225 226 if err := runGazelle(dir, []string{"-go_prefix", "example.com/foo"}); err != nil { 227 t.Fatal(err) 228 } 229 if got, err := ioutil.ReadFile(filepath.Join(dir, "BUILD")); err != nil { 230 t.Fatal(err) 231 } else if string(got) != want { 232 t.Fatalf("got %s ; want %s", string(got), want) 233 } 234 } 235 236 func TestFixAndUpdateChanges(t *testing.T) { 237 files := []fileSpec{ 238 {path: "WORKSPACE"}, 239 { 240 path: "BUILD", 241 content: `load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_prefix") 242 load("@io_bazel_rules_go//go:def.bzl", "cgo_library", "go_test") 243 244 go_prefix("example.com/foo") 245 246 go_library( 247 name = "go_default_library", 248 srcs = [ 249 "extra.go", 250 "pure.go", 251 ], 252 library = ":cgo_default_library", 253 visibility = ["//visibility:default"], 254 ) 255 256 cgo_library( 257 name = "cgo_default_library", 258 srcs = ["cgo.go"], 259 ) 260 `, 261 }, 262 { 263 path: "pure.go", 264 content: "package foo", 265 }, 266 { 267 path: "cgo.go", 268 content: `package foo 269 270 import "C" 271 `, 272 }, 273 } 274 275 cases := []struct { 276 cmd, want string 277 }{ 278 { 279 cmd: "update", 280 want: `load("@io_bazel_rules_go//go:def.bzl", "cgo_library", "go_library", "go_prefix") 281 282 go_prefix("example.com/foo") 283 284 go_library( 285 name = "go_default_library", 286 srcs = [ 287 "cgo.go", 288 "pure.go", 289 ], 290 cgo = True, 291 importpath = "example.com/foo", 292 visibility = ["//visibility:default"], 293 ) 294 295 cgo_library( 296 name = "cgo_default_library", 297 srcs = ["cgo.go"], 298 ) 299 `, 300 }, { 301 cmd: "fix", 302 want: `load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_prefix") 303 304 go_prefix("example.com/foo") 305 306 go_library( 307 name = "go_default_library", 308 srcs = [ 309 "cgo.go", 310 "pure.go", 311 ], 312 cgo = True, 313 importpath = "example.com/foo", 314 visibility = ["//visibility:default"], 315 ) 316 `, 317 }, 318 } 319 320 for _, c := range cases { 321 t.Run(c.cmd, func(t *testing.T) { 322 dir, err := createFiles(files) 323 if err != nil { 324 t.Fatal(err) 325 } 326 327 if err := runGazelle(dir, []string{c.cmd}); err != nil { 328 t.Fatal(err) 329 } 330 if got, err := ioutil.ReadFile(filepath.Join(dir, "BUILD")); err != nil { 331 t.Fatal(err) 332 } else if string(got) != c.want { 333 t.Fatalf("got %s ; want %s", string(got), c.want) 334 } 335 }) 336 } 337 } 338 339 func TestFixUnlinkedCgoLibrary(t *testing.T) { 340 files := []fileSpec{ 341 {path: "WORKSPACE"}, 342 { 343 path: "BUILD", 344 content: `load("@io_bazel_rules_go//go:def.bzl", "cgo_library", "go_library") 345 346 cgo_library( 347 name = "cgo_default_library", 348 srcs = ["cgo.go"], 349 ) 350 351 go_library( 352 name = "go_default_library", 353 srcs = ["pure.go"], 354 importpath = "example.com/foo", 355 visibility = ["//visibility:public"], 356 ) 357 `, 358 }, { 359 path: "pure.go", 360 content: "package foo", 361 }, 362 } 363 364 dir, err := createFiles(files) 365 if err != nil { 366 t.Fatal(err) 367 } 368 369 want := `load("@io_bazel_rules_go//go:def.bzl", "go_library") 370 371 go_library( 372 name = "go_default_library", 373 srcs = ["pure.go"], 374 importpath = "example.com/foo", 375 visibility = ["//visibility:public"], 376 ) 377 ` 378 if err := runGazelle(dir, []string{"fix", "-go_prefix", "example.com/foo"}); err != nil { 379 t.Fatal(err) 380 } 381 if got, err := ioutil.ReadFile(filepath.Join(dir, "BUILD")); err != nil { 382 t.Fatal(err) 383 } else if string(got) != want { 384 t.Fatalf("got %s ; want %s", string(got), want) 385 } 386 } 387 388 // TestMultipleDirectories checks that all directories in a repository are 389 // indexed but only directories listed on the command line are updated. 390 func TestMultipleDirectories(t *testing.T) { 391 files := []fileSpec{ 392 {path: "WORKSPACE"}, 393 { 394 path: "a/BUILD.bazel", 395 content: `# This file shouldn't be modified. 396 load("@io_bazel_rules_go//go:def.bzl", "go_library") 397 398 go_library( 399 name = "go_default_library", 400 srcs = ["a.go"], 401 importpath = "example.com/foo/x", 402 ) 403 `, 404 }, { 405 path: "a/a.go", 406 content: "package a", 407 }, { 408 path: "b/b.go", 409 content: ` 410 package b 411 412 import _ "example.com/foo/x" 413 `, 414 }, 415 } 416 dir, err := createFiles(files) 417 if err != nil { 418 t.Fatal(err) 419 } 420 defer os.RemoveAll(dir) 421 422 args := []string{"-go_prefix", "example.com/foo", "b"} 423 if err := runGazelle(dir, args); err != nil { 424 t.Fatal(err) 425 } 426 427 checkFiles(t, dir, []fileSpec{ 428 files[1], // should not change 429 { 430 path: "b/BUILD.bazel", 431 content: `load("@io_bazel_rules_go//go:def.bzl", "go_library") 432 433 go_library( 434 name = "go_default_library", 435 srcs = ["b.go"], 436 importpath = "example.com/foo/b", 437 visibility = ["//visibility:public"], 438 deps = ["//a:go_default_library"], 439 ) 440 `, 441 }, 442 }) 443 } 444 445 func TestErrorOutsideWorkspace(t *testing.T) { 446 files := []fileSpec{ 447 {path: "a/"}, 448 {path: "b/"}, 449 } 450 dir, err := createFiles(files) 451 if err != nil { 452 t.Fatal(err) 453 } 454 defer os.RemoveAll(dir) 455 skipIfWorkspaceVisible(t, dir) 456 457 cases := []struct { 458 name, dir, want string 459 args []string 460 }{ 461 { 462 name: "outside workspace", 463 dir: dir, 464 args: nil, 465 want: "WORKSPACE cannot be found", 466 }, { 467 name: "outside repo_root", 468 dir: filepath.Join(dir, "a"), 469 args: []string{"-repo_root", filepath.Join(dir, "b")}, 470 want: "not a subdirectory of repo root", 471 }, 472 } 473 for _, c := range cases { 474 t.Run(c.name, func(t *testing.T) { 475 if err := runGazelle(c.dir, c.args); err == nil { 476 t.Fatal("got success; want %q", c.want) 477 } else if !strings.Contains(err.Error(), c.want) { 478 t.Fatal("got %q; want %q", err, c.want) 479 } 480 }) 481 } 482 } 483 484 func TestBuildFileNameIgnoresBuild(t *testing.T) { 485 files := []fileSpec{ 486 {path: "WORKSPACE"}, 487 {path: "BUILD/"}, 488 { 489 path: "a/BUILD", 490 content: "!!! parse error", 491 }, { 492 path: "a.go", 493 content: "package a", 494 }, 495 } 496 dir, err := createFiles(files) 497 if err != nil { 498 t.Fatal(err) 499 } 500 defer os.Remove(dir) 501 502 args := []string{"-go_prefix", "example.com/foo", "-build_file_name", "BUILD.bazel"} 503 if err := runGazelle(dir, args); err != nil { 504 t.Fatal(err) 505 } 506 if _, err := os.Stat(filepath.Join(dir, "BUILD.bazel")); err != nil { 507 t.Errorf("BUILD.bazel not created: %v", err) 508 } 509 } 510 511 func TestExternalVendor(t *testing.T) { 512 files := []fileSpec{ 513 {path: "WORKSPACE"}, 514 { 515 path: "a.go", 516 content: `package foo 517 518 import _ "golang.org/x/bar" 519 `, 520 }, { 521 path: "vendor/golang.org/x/bar/bar.go", 522 content: `package bar 523 524 import _ "golang.org/x/baz" 525 `, 526 }, { 527 path: "vendor/golang.org/x/baz/baz.go", 528 content: "package baz", 529 }, 530 } 531 dir, err := createFiles(files) 532 if err != nil { 533 t.Fatal(err) 534 } 535 defer os.RemoveAll(dir) 536 537 args := []string{"-go_prefix", "example.com/foo", "-external", "vendored"} 538 if err := runGazelle(dir, args); err != nil { 539 t.Fatal(err) 540 } 541 542 checkFiles(t, dir, []fileSpec{ 543 { 544 path: config.DefaultValidBuildFileNames[0], 545 content: `load("@io_bazel_rules_go//go:def.bzl", "go_library") 546 547 go_library( 548 name = "go_default_library", 549 srcs = ["a.go"], 550 importpath = "example.com/foo", 551 visibility = ["//visibility:public"], 552 deps = ["//vendor/golang.org/x/bar:go_default_library"], 553 ) 554 `, 555 }, { 556 path: "vendor/golang.org/x/bar/" + config.DefaultValidBuildFileNames[0], 557 content: `load("@io_bazel_rules_go//go:def.bzl", "go_library") 558 559 go_library( 560 name = "go_default_library", 561 srcs = ["bar.go"], 562 importpath = "golang.org/x/bar", 563 visibility = ["//visibility:public"], 564 deps = ["//vendor/golang.org/x/baz:go_default_library"], 565 ) 566 `, 567 }, 568 }) 569 } 570 571 func TestMigrateProtoRules(t *testing.T) { 572 files := []fileSpec{ 573 {path: "WORKSPACE"}, 574 { 575 path: config.DefaultValidBuildFileNames[0], 576 content: ` 577 load("@io_bazel_rules_go//proto:go_proto_library.bzl", "go_proto_library") 578 579 filegroup( 580 name = "go_default_library_protos", 581 srcs = ["foo.proto"], 582 visibility = ["//visibility:public"], 583 ) 584 585 go_proto_library( 586 name = "go_default_library", 587 srcs = [":go_default_library_protos"], 588 ) 589 `, 590 }, { 591 path: "foo.proto", 592 content: `syntax = "proto3"; 593 594 option go_package = "example.com/repo"; 595 `, 596 }, { 597 path: "foo.pb.go", 598 content: `package repo`, 599 }, 600 } 601 602 for _, tc := range []struct { 603 args []string 604 want string 605 }{ 606 { 607 args: []string{"update", "-go_prefix", "example.com/repo"}, 608 want: ` 609 load("@io_bazel_rules_go//proto:go_proto_library.bzl", "go_proto_library") 610 611 filegroup( 612 name = "go_default_library_protos", 613 srcs = ["foo.proto"], 614 visibility = ["//visibility:public"], 615 ) 616 617 go_proto_library( 618 name = "go_default_library", 619 srcs = [":go_default_library_protos"], 620 ) 621 `, 622 }, { 623 args: []string{"fix", "-go_prefix", "example.com/repo"}, 624 want: ` 625 load("@io_bazel_rules_go//go:def.bzl", "go_library") 626 load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library") 627 628 proto_library( 629 name = "repo_proto", 630 srcs = ["foo.proto"], 631 visibility = ["//visibility:public"], 632 ) 633 634 go_proto_library( 635 name = "repo_go_proto", 636 importpath = "example.com/repo", 637 proto = ":repo_proto", 638 visibility = ["//visibility:public"], 639 ) 640 641 go_library( 642 name = "go_default_library", 643 embed = [":repo_go_proto"], 644 importpath = "example.com/repo", 645 visibility = ["//visibility:public"], 646 ) 647 `, 648 }, 649 } { 650 t.Run(tc.args[0], func(t *testing.T) { 651 dir, err := createFiles(files) 652 if err != nil { 653 t.Fatal(err) 654 } 655 defer os.RemoveAll(dir) 656 657 if err := runGazelle(dir, tc.args); err != nil { 658 t.Fatal(err) 659 } 660 661 checkFiles(t, dir, []fileSpec{{ 662 path: config.DefaultValidBuildFileNames[0], 663 content: tc.want, 664 }}) 665 }) 666 } 667 } 668 669 func TestRemoveProtoDeletesRules(t *testing.T) { 670 files := []fileSpec{ 671 {path: "WORKSPACE"}, 672 { 673 path: config.DefaultValidBuildFileNames[0], 674 content: ` 675 load("@io_bazel_rules_go//go:def.bzl", "go_library") 676 load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library") 677 678 filegroup( 679 name = "go_default_library_protos", 680 srcs = ["foo.proto"], 681 visibility = ["//visibility:public"], 682 ) 683 684 proto_library( 685 name = "repo_proto", 686 srcs = ["foo.proto"], 687 visibility = ["//visibility:public"], 688 ) 689 690 go_proto_library( 691 name = "repo_go_proto", 692 importpath = "example.com/repo", 693 proto = ":repo_proto", 694 visibility = ["//visibility:public"], 695 ) 696 697 go_library( 698 name = "go_default_library", 699 srcs = ["extra.go"], 700 embed = [":repo_go_proto"], 701 importpath = "example.com/repo", 702 visibility = ["//visibility:public"], 703 ) 704 `, 705 }, { 706 path: "extra.go", 707 content: `package repo`, 708 }, 709 } 710 dir, err := createFiles(files) 711 if err != nil { 712 t.Fatal(err) 713 } 714 defer os.RemoveAll(dir) 715 716 args := []string{"fix", "-go_prefix", "example.com/repo"} 717 if err := runGazelle(dir, args); err != nil { 718 t.Fatal(err) 719 } 720 721 checkFiles(t, dir, []fileSpec{{ 722 path: config.DefaultValidBuildFileNames[0], 723 content: ` 724 load("@io_bazel_rules_go//go:def.bzl", "go_library") 725 726 go_library( 727 name = "go_default_library", 728 srcs = ["extra.go"], 729 importpath = "example.com/repo", 730 visibility = ["//visibility:public"], 731 ) 732 `, 733 }}) 734 } 735 736 func TestAddServiceConvertsToGrpc(t *testing.T) { 737 files := []fileSpec{ 738 {path: "WORKSPACE"}, 739 { 740 path: config.DefaultValidBuildFileNames[0], 741 content: ` 742 load("@io_bazel_rules_go//go:def.bzl", "go_library") 743 load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library") 744 745 proto_library( 746 name = "repo_proto", 747 srcs = ["foo.proto"], 748 visibility = ["//visibility:public"], 749 ) 750 751 go_proto_library( 752 name = "repo_go_proto", 753 importpath = "example.com/repo", 754 proto = ":repo_proto", 755 visibility = ["//visibility:public"], 756 ) 757 758 go_library( 759 name = "go_default_library", 760 embed = [":repo_go_proto"], 761 importpath = "example.com/repo", 762 visibility = ["//visibility:public"], 763 ) 764 `, 765 }, { 766 path: "foo.proto", 767 content: `syntax = "proto3"; 768 769 option go_package = "example.com/repo"; 770 771 service {} 772 `, 773 }, 774 } 775 776 dir, err := createFiles(files) 777 if err != nil { 778 t.Fatal(err) 779 } 780 defer os.RemoveAll(dir) 781 782 args := []string{"-go_prefix", "example.com/repo"} 783 if err := runGazelle(dir, args); err != nil { 784 t.Fatal(err) 785 } 786 787 checkFiles(t, dir, []fileSpec{{ 788 path: config.DefaultValidBuildFileNames[0], 789 content: ` 790 load("@io_bazel_rules_go//go:def.bzl", "go_library") 791 load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library") 792 793 proto_library( 794 name = "repo_proto", 795 srcs = ["foo.proto"], 796 visibility = ["//visibility:public"], 797 ) 798 799 go_proto_library( 800 name = "repo_go_proto", 801 compilers = ["@io_bazel_rules_go//proto:go_grpc"], 802 importpath = "example.com/repo", 803 proto = ":repo_proto", 804 visibility = ["//visibility:public"], 805 ) 806 807 go_library( 808 name = "go_default_library", 809 embed = [":repo_go_proto"], 810 importpath = "example.com/repo", 811 visibility = ["//visibility:public"], 812 ) 813 `, 814 }}) 815 } 816 817 func TestEmptyGoPrefix(t *testing.T) { 818 files := []fileSpec{ 819 {path: "WORKSPACE"}, 820 { 821 path: "foo/foo.go", 822 content: "package foo", 823 }, { 824 path: "bar/bar.go", 825 content: ` 826 package bar 827 828 import ( 829 _ "fmt" 830 _ "foo" 831 ) 832 `, 833 }, 834 } 835 836 dir, err := createFiles(files) 837 if err != nil { 838 t.Fatal(err) 839 } 840 defer os.RemoveAll(dir) 841 842 args := []string{"-go_prefix", ""} 843 if err := runGazelle(dir, args); err != nil { 844 t.Fatal(err) 845 } 846 847 checkFiles(t, dir, []fileSpec{{ 848 path: filepath.Join("bar", config.DefaultValidBuildFileNames[0]), 849 content: ` 850 load("@io_bazel_rules_go//go:def.bzl", "go_library") 851 852 go_library( 853 name = "go_default_library", 854 srcs = ["bar.go"], 855 importpath = "bar", 856 visibility = ["//visibility:public"], 857 deps = ["//foo:go_default_library"], 858 ) 859 `, 860 }}) 861 } 862 863 // TestResolveKeptImportpath checks that Gazelle can resolve dependencies 864 // against a library with a '# keep' comment on its importpath attribute 865 // when the importpath doesn't match what Gazelle would infer. 866 func TestResolveKeptImportpath(t *testing.T) { 867 files := []fileSpec{ 868 {path: "WORKSPACE"}, 869 { 870 path: "foo/foo.go", 871 content: ` 872 package foo 873 874 import _ "example.com/alt/baz" 875 `, 876 }, { 877 path: "bar/BUILD.bazel", 878 content: `load("@io_bazel_rules_go//go:def.bzl", "go_library") 879 880 go_library( 881 name = "go_default_library", 882 srcs = ["bar.go"], 883 importpath = "example.com/alt/baz", # keep 884 visibility = ["//visibility:public"], 885 ) 886 `, 887 }, { 888 path: "bar/bar.go", 889 content: "package bar", 890 }, 891 } 892 893 dir, err := createFiles(files) 894 if err != nil { 895 t.Fatal(err) 896 } 897 defer os.RemoveAll(dir) 898 899 args := []string{"-go_prefix", "example.com/repo"} 900 if err := runGazelle(dir, args); err != nil { 901 t.Fatal(err) 902 } 903 904 checkFiles(t, dir, []fileSpec{ 905 { 906 path: "foo/BUILD.bazel", 907 content: ` 908 load("@io_bazel_rules_go//go:def.bzl", "go_library") 909 910 go_library( 911 name = "go_default_library", 912 srcs = ["foo.go"], 913 importpath = "example.com/repo/foo", 914 visibility = ["//visibility:public"], 915 deps = ["//bar:go_default_library"], 916 ) 917 `, 918 }, { 919 path: "bar/BUILD.bazel", 920 content: `load("@io_bazel_rules_go//go:def.bzl", "go_library") 921 922 go_library( 923 name = "go_default_library", 924 srcs = ["bar.go"], 925 importpath = "example.com/alt/baz", # keep 926 visibility = ["//visibility:public"], 927 ) 928 `, 929 }, 930 }) 931 } 932 933 // TestResolveVendorSubdirectory checks that Gazelle can resolve libraries 934 // in a vendor directory which is not at the repository root. 935 func TestResolveVendorSubdirectory(t *testing.T) { 936 files := []fileSpec{ 937 {path: "WORKSPACE"}, 938 { 939 path: "sub/vendor/example.com/foo/foo.go", 940 content: "package foo", 941 }, { 942 path: "sub/bar/bar.go", 943 content: ` 944 package bar 945 946 import _ "example.com/foo" 947 `, 948 }, 949 } 950 dir, err := createFiles(files) 951 if err != nil { 952 t.Fatal(err) 953 } 954 defer os.RemoveAll(dir) 955 956 args := []string{"-go_prefix", "example.com/repo"} 957 if err := runGazelle(dir, args); err != nil { 958 t.Fatal(err) 959 } 960 961 checkFiles(t, dir, []fileSpec{ 962 { 963 path: "sub/vendor/example.com/foo/BUILD.bazel", 964 content: ` 965 load("@io_bazel_rules_go//go:def.bzl", "go_library") 966 967 go_library( 968 name = "go_default_library", 969 srcs = ["foo.go"], 970 importpath = "example.com/foo", 971 visibility = ["//visibility:public"], 972 ) 973 `, 974 }, { 975 path: "sub/bar/BUILD.bazel", 976 content: ` 977 load("@io_bazel_rules_go//go:def.bzl", "go_library") 978 979 go_library( 980 name = "go_default_library", 981 srcs = ["bar.go"], 982 importpath = "example.com/repo/sub/bar", 983 visibility = ["//visibility:public"], 984 deps = ["//sub/vendor/example.com/foo:go_default_library"], 985 ) 986 `, 987 }, 988 }) 989 } 990 991 // TestDeleteProtoWithDeps checks that Gazelle will delete proto rules with 992 // dependencies after the proto sources are removed. 993 func TestDeleteProtoWithDeps(t *testing.T) { 994 files := []fileSpec{ 995 {path: "WORKSPACE"}, 996 { 997 path: "foo/BUILD.bazel", 998 content: ` 999 load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library") 1000 load("@io_bazel_rules_go//go:def.bzl", "go_library") 1001 1002 go_library( 1003 name = "go_default_library", 1004 srcs = ["extra.go"], 1005 embed = [":scratch_go_proto"], 1006 importpath = "example.com/repo/foo", 1007 visibility = ["//visibility:public"], 1008 ) 1009 1010 proto_library( 1011 name = "foo_proto", 1012 srcs = ["foo.proto"], 1013 visibility = ["//visibility:public"], 1014 deps = ["//foo/bar:bar_proto"], 1015 ) 1016 1017 go_proto_library( 1018 name = "foo_go_proto", 1019 importpath = "example.com/repo/foo", 1020 proto = ":foo_proto", 1021 visibility = ["//visibility:public"], 1022 deps = ["//foo/bar:go_default_library"], 1023 ) 1024 `, 1025 }, { 1026 path: "foo/extra.go", 1027 content: "package foo", 1028 }, { 1029 path: "foo/bar/bar.proto", 1030 content: ` 1031 syntax = "proto3"; 1032 1033 option go_package = "example.com/repo/foo/bar"; 1034 1035 message Bar {}; 1036 `, 1037 }, 1038 } 1039 dir, err := createFiles(files) 1040 if err != nil { 1041 t.Fatal(err) 1042 } 1043 defer os.RemoveAll(dir) 1044 1045 args := []string{"-go_prefix", "example.com/repo"} 1046 if err := runGazelle(dir, args); err != nil { 1047 t.Fatal(err) 1048 } 1049 1050 checkFiles(t, dir, []fileSpec{ 1051 { 1052 path: "foo/BUILD.bazel", 1053 content: ` 1054 load("@io_bazel_rules_go//go:def.bzl", "go_library") 1055 1056 go_library( 1057 name = "go_default_library", 1058 srcs = ["extra.go"], 1059 importpath = "example.com/repo/foo", 1060 visibility = ["//visibility:public"], 1061 ) 1062 `, 1063 }, 1064 }) 1065 } 1066 1067 func TestCustomRepoNames(t *testing.T) { 1068 files := []fileSpec{ 1069 { 1070 path: "WORKSPACE", 1071 content: ` 1072 go_repository( 1073 name = "custom_repo", 1074 importpath = "example.com/bar", 1075 commit = "123456", 1076 ) 1077 `, 1078 }, { 1079 path: "foo.go", 1080 content: ` 1081 package foo 1082 1083 import _ "example.com/bar" 1084 `, 1085 }, 1086 } 1087 dir, err := createFiles(files) 1088 if err != nil { 1089 t.Fatal(err) 1090 } 1091 defer os.RemoveAll(dir) 1092 1093 args := []string{"-go_prefix", "example.com/foo"} 1094 if err := runGazelle(dir, args); err != nil { 1095 t.Fatal(err) 1096 } 1097 1098 checkFiles(t, dir, []fileSpec{ 1099 { 1100 path: "BUILD.bazel", 1101 content: ` 1102 load("@io_bazel_rules_go//go:def.bzl", "go_library") 1103 1104 go_library( 1105 name = "go_default_library", 1106 srcs = ["foo.go"], 1107 importpath = "example.com/foo", 1108 visibility = ["//visibility:public"], 1109 deps = ["@custom_repo//:go_default_library"], 1110 ) 1111 `, 1112 }, 1113 }) 1114 } 1115 1116 func TestImportReposFromDep(t *testing.T) { 1117 files := []fileSpec{ 1118 { 1119 path: "WORKSPACE", 1120 content: `workspace(name = "bazel_gazelle") 1121 1122 http_archive( 1123 name = "io_bazel_rules_go", 1124 url = "https://github.com/bazelbuild/rules_go/releases/download/0.7.1/rules_go-0.7.1.tar.gz", 1125 sha256 = "341d5eacef704415386974bc82a1783a8b7ffbff2ab6ba02375e1ca20d9b031c", 1126 ) 1127 load("@io_bazel_rules_go//go:def.bzl", "go_rules_dependencies", "go_register_toolchains") 1128 go_rules_dependencies() 1129 go_register_toolchains() 1130 1131 load("//:deps.bzl", "gazelle_dependencies") 1132 gazelle_dependencies() 1133 1134 go_repository( 1135 name = "org_golang_x_net", 1136 importpath = "golang.org/x/net", 1137 tag = "1.2", 1138 ) 1139 1140 # keep 1141 go_repository( 1142 name = "org_golang_x_sys", 1143 importpath = "golang.org/x/sys", 1144 remote = "https://github.com/golang/sys", 1145 ) 1146 1147 http_archive( 1148 name = "com_github_go_yaml_yaml", 1149 urls = ["https://example.com/yaml.tar.gz"], 1150 sha256 = "1234", 1151 ) 1152 `, 1153 }, { 1154 path: "Gopkg.lock", 1155 content: `# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. 1156 1157 1158 [[projects]] 1159 name = "github.com/pkg/errors" 1160 packages = ["."] 1161 revision = "645ef00459ed84a119197bfb8d8205042c6df63d" 1162 version = "v0.8.0" 1163 1164 [[projects]] 1165 branch = "master" 1166 name = "golang.org/x/net" 1167 packages = ["context"] 1168 revision = "66aacef3dd8a676686c7ae3716979581e8b03c47" 1169 1170 [[projects]] 1171 branch = "master" 1172 name = "golang.org/x/sys" 1173 packages = ["unix"] 1174 revision = "bb24a47a89eac6c1227fbcb2ae37a8b9ed323366" 1175 1176 [[projects]] 1177 branch = "v2" 1178 name = "github.com/go-yaml/yaml" 1179 packages = ["."] 1180 revision = "cd8b52f8269e0feb286dfeef29f8fe4d5b397e0b" 1181 1182 [solve-meta] 1183 analyzer-name = "dep" 1184 analyzer-version = 1 1185 inputs-digest = "05c1cd69be2c917c0cc4b32942830c2acfa044d8200fdc94716aae48a8083702" 1186 solver-name = "gps-cdcl" 1187 solver-version = 1 1188 `, 1189 }, 1190 } 1191 dir, err := createFiles(files) 1192 if err != nil { 1193 t.Fatal(err) 1194 } 1195 defer os.RemoveAll(dir) 1196 1197 args := []string{"update-repos", "-from_file", "Gopkg.lock"} 1198 if err := runGazelle(dir, args); err != nil { 1199 t.Fatal(err) 1200 } 1201 1202 checkFiles(t, dir, []fileSpec{ 1203 { 1204 path: "WORKSPACE", 1205 content: `workspace(name = "bazel_gazelle") 1206 1207 http_archive( 1208 name = "io_bazel_rules_go", 1209 url = "https://github.com/bazelbuild/rules_go/releases/download/0.7.1/rules_go-0.7.1.tar.gz", 1210 sha256 = "341d5eacef704415386974bc82a1783a8b7ffbff2ab6ba02375e1ca20d9b031c", 1211 ) 1212 1213 load("@io_bazel_rules_go//go:def.bzl", "go_register_toolchains", "go_repository", "go_rules_dependencies") 1214 1215 go_rules_dependencies() 1216 1217 go_register_toolchains() 1218 1219 load("//:deps.bzl", "gazelle_dependencies") 1220 1221 gazelle_dependencies() 1222 1223 go_repository( 1224 name = "org_golang_x_net", 1225 importpath = "golang.org/x/net", 1226 commit = "66aacef3dd8a676686c7ae3716979581e8b03c47", 1227 ) 1228 1229 # keep 1230 go_repository( 1231 name = "org_golang_x_sys", 1232 importpath = "golang.org/x/sys", 1233 remote = "https://github.com/golang/sys", 1234 ) 1235 1236 http_archive( 1237 name = "com_github_go_yaml_yaml", 1238 urls = ["https://example.com/yaml.tar.gz"], 1239 sha256 = "1234", 1240 ) 1241 1242 go_repository( 1243 name = "com_github_pkg_errors", 1244 commit = "645ef00459ed84a119197bfb8d8205042c6df63d", 1245 importpath = "github.com/pkg/errors", 1246 ) 1247 `, 1248 }}) 1249 } 1250 1251 func TestDeleteRulesInEmptyDir(t *testing.T) { 1252 files := []fileSpec{ 1253 {path: "WORKSPACE"}, 1254 { 1255 path: "BUILD.bazel", 1256 content: ` 1257 load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_binary") 1258 1259 go_library( 1260 name = "go_default_library", 1261 srcs = [ 1262 "bar.go", 1263 "foo.go", 1264 ], 1265 importpath = "example.com/repo", 1266 visibility = ["//visibility:private"], 1267 ) 1268 1269 go_binary( 1270 name = "cmd", 1271 embed = [":go_default_library"], 1272 visibility = ["//visibility:public"], 1273 ) 1274 `, 1275 }, 1276 } 1277 dir, err := createFiles(files) 1278 if err != nil { 1279 t.Fatal(err) 1280 } 1281 defer os.RemoveAll(dir) 1282 1283 args := []string{"-go_prefix=example.com/repo"} 1284 if err := runGazelle(dir, args); err != nil { 1285 t.Fatal(err) 1286 } 1287 1288 checkFiles(t, dir, []fileSpec{ 1289 { 1290 path: "BUILD.bazel", 1291 content: "", 1292 }, 1293 }) 1294 } 1295 1296 // TODO(jayconrod): more tests 1297 // run in fix mode in testdata directories to create new files 1298 // run in diff mode in testdata directories to update existing files (no change)