github.com/golang/dep@v0.5.4/gps/prune_test.go (about) 1 // Copyright 2017 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 package gps 6 7 import ( 8 "io/ioutil" 9 "os" 10 "testing" 11 12 "github.com/golang/dep/internal/test" 13 ) 14 15 func TestCascadingPruneOptions(t *testing.T) { 16 cases := []struct { 17 name string 18 co CascadingPruneOptions 19 results map[ProjectRoot]PruneOptions 20 }{ 21 { 22 name: "all empty values", 23 co: CascadingPruneOptions{ 24 DefaultOptions: PruneNestedVendorDirs, 25 PerProjectOptions: map[ProjectRoot]PruneOptionSet{ 26 ProjectRoot("github.com/golang/dep"): {}, 27 }, 28 }, 29 results: map[ProjectRoot]PruneOptions{ 30 ProjectRoot("github.com/golang/dep"): PruneNestedVendorDirs, 31 }, 32 }, 33 { 34 name: "all overridden", 35 co: CascadingPruneOptions{ 36 DefaultOptions: PruneNestedVendorDirs, 37 PerProjectOptions: map[ProjectRoot]PruneOptionSet{ 38 ProjectRoot("github.com/golang/dep"): { 39 NestedVendor: 2, 40 UnusedPackages: 1, 41 NonGoFiles: 1, 42 GoTests: 1, 43 }, 44 }, 45 }, 46 results: map[ProjectRoot]PruneOptions{ 47 ProjectRoot("github.com/golang/dep"): PruneUnusedPackages | PruneNonGoFiles | PruneGoTestFiles, 48 }, 49 }, 50 { 51 name: "all redundant", 52 co: CascadingPruneOptions{ 53 DefaultOptions: PruneNestedVendorDirs, 54 PerProjectOptions: map[ProjectRoot]PruneOptionSet{ 55 ProjectRoot("github.com/golang/dep"): { 56 NestedVendor: 1, 57 UnusedPackages: 2, 58 NonGoFiles: 2, 59 GoTests: 2, 60 }, 61 }, 62 }, 63 results: map[ProjectRoot]PruneOptions{ 64 ProjectRoot("github.com/golang/dep"): PruneNestedVendorDirs, 65 }, 66 }, 67 { 68 name: "multiple projects, all combos", 69 co: CascadingPruneOptions{ 70 DefaultOptions: PruneNestedVendorDirs, 71 PerProjectOptions: map[ProjectRoot]PruneOptionSet{ 72 ProjectRoot("github.com/golang/dep"): { 73 NestedVendor: 1, 74 UnusedPackages: 2, 75 NonGoFiles: 2, 76 GoTests: 2, 77 }, 78 ProjectRoot("github.com/other/one"): { 79 NestedVendor: 2, 80 UnusedPackages: 1, 81 NonGoFiles: 1, 82 GoTests: 1, 83 }, 84 }, 85 }, 86 results: map[ProjectRoot]PruneOptions{ 87 ProjectRoot("github.com/golang/dep"): PruneNestedVendorDirs, 88 ProjectRoot("github.com/other/one"): PruneUnusedPackages | PruneNonGoFiles | PruneGoTestFiles, 89 ProjectRoot("not/there"): PruneNestedVendorDirs, 90 }, 91 }, 92 } 93 94 for _, c := range cases { 95 t.Run(c.name, func(t *testing.T) { 96 for pr, wanted := range c.results { 97 if c.co.PruneOptionsFor(pr) != wanted { 98 t.Fatalf("did not get expected final PruneOptions value from cascade:\n\t(GOT): %d\n\t(WNT): %d", c.co.PruneOptionsFor(pr), wanted) 99 } 100 101 } 102 }) 103 } 104 } 105 106 func TestPruneProject(t *testing.T) { 107 h := test.NewHelper(t) 108 defer h.Cleanup() 109 110 pr := "github.com/project/repository" 111 h.TempDir(pr) 112 113 baseDir := h.Path(".") 114 lp := lockedProject{ 115 pi: ProjectIdentifier{ 116 ProjectRoot: ProjectRoot(pr), 117 }, 118 pkgs: []string{}, 119 } 120 121 options := PruneNestedVendorDirs | PruneNonGoFiles | PruneGoTestFiles | PruneUnusedPackages 122 123 err := PruneProject(baseDir, lp, options) 124 if err != nil { 125 t.Fatal(err) 126 } 127 } 128 129 func TestPruneUnusedPackages(t *testing.T) { 130 h := test.NewHelper(t) 131 defer h.Cleanup() 132 133 h.TempDir(".") 134 135 pr := "github.com/sample/repository" 136 pi := ProjectIdentifier{ProjectRoot: ProjectRoot(pr)} 137 138 testcases := []struct { 139 name string 140 lp LockedProject 141 fs fsTestCase 142 err bool 143 }{ 144 { 145 "one-package", 146 lockedProject{ 147 pi: pi, 148 pkgs: []string{ 149 ".", 150 }, 151 }, 152 fsTestCase{ 153 before: filesystemState{ 154 files: []string{ 155 "main.go", 156 }, 157 }, 158 after: filesystemState{ 159 files: []string{ 160 "main.go", 161 }, 162 }, 163 }, 164 false, 165 }, 166 { 167 "nested-package", 168 lockedProject{ 169 pi: pi, 170 pkgs: []string{ 171 "pkg", 172 }, 173 }, 174 fsTestCase{ 175 before: filesystemState{ 176 dirs: []string{ 177 "pkg", 178 }, 179 files: []string{ 180 "main.go", 181 "pkg/main.go", 182 }, 183 }, 184 after: filesystemState{ 185 dirs: []string{ 186 "pkg", 187 }, 188 files: []string{ 189 "pkg/main.go", 190 }, 191 }, 192 }, 193 false, 194 }, 195 { 196 "complex-project", 197 lockedProject{ 198 pi: pi, 199 pkgs: []string{ 200 "pkg", 201 "pkg/nestedpkg/otherpkg", 202 }, 203 }, 204 fsTestCase{ 205 before: filesystemState{ 206 dirs: []string{ 207 "pkg", 208 "pkg/nestedpkg", 209 "pkg/nestedpkg/otherpkg", 210 }, 211 files: []string{ 212 "main.go", 213 "COPYING", 214 "pkg/main.go", 215 "pkg/nestedpkg/main.go", 216 "pkg/nestedpkg/legal.go", 217 "pkg/nestedpkg/PATENT.md", 218 "pkg/nestedpkg/otherpkg/main.go", 219 }, 220 }, 221 after: filesystemState{ 222 dirs: []string{ 223 "pkg", 224 "pkg/nestedpkg", 225 "pkg/nestedpkg/otherpkg", 226 }, 227 files: []string{ 228 "COPYING", 229 "pkg/main.go", 230 "pkg/nestedpkg/PATENT.md", 231 "pkg/nestedpkg/otherpkg/main.go", 232 }, 233 }, 234 }, 235 false, 236 }, 237 } 238 239 for _, tc := range testcases { 240 t.Run(tc.name, func(t *testing.T) { 241 h.TempDir(pr) 242 baseDir := h.Path(pr) 243 tc.fs.before.root = baseDir 244 tc.fs.after.root = baseDir 245 tc.fs.setup(t) 246 247 fs, err := deriveFilesystemState(baseDir) 248 if err != nil { 249 t.Fatal(err) 250 } 251 252 _, err = pruneUnusedPackages(tc.lp, fs) 253 if tc.err && err == nil { 254 t.Fatalf("expected an error, got nil") 255 } else if !tc.err && err != nil { 256 t.Fatalf("unexpected error: %s", err) 257 } 258 259 tc.fs.assert(t) 260 }) 261 } 262 } 263 264 func TestPruneNonGoFiles(t *testing.T) { 265 h := test.NewHelper(t) 266 defer h.Cleanup() 267 268 h.TempDir(".") 269 270 testcases := []struct { 271 name string 272 fs fsTestCase 273 err bool 274 }{ 275 { 276 "one-file", 277 fsTestCase{ 278 before: filesystemState{ 279 files: []string{ 280 "README.md", 281 }, 282 }, 283 after: filesystemState{}, 284 }, 285 false, 286 }, 287 { 288 "multiple-files", 289 fsTestCase{ 290 before: filesystemState{ 291 files: []string{ 292 "main.go", 293 "main_test.go", 294 "README", 295 }, 296 }, 297 after: filesystemState{ 298 files: []string{ 299 "main.go", 300 "main_test.go", 301 }, 302 }, 303 }, 304 false, 305 }, 306 { 307 "mixed-files", 308 fsTestCase{ 309 before: filesystemState{ 310 dirs: []string{ 311 "dir", 312 }, 313 files: []string{ 314 "dir/main.go", 315 "dir/main_test.go", 316 "dir/db.sqlite", 317 }, 318 }, 319 after: filesystemState{ 320 dirs: []string{ 321 "dir", 322 }, 323 files: []string{ 324 "dir/main.go", 325 "dir/main_test.go", 326 }, 327 }, 328 }, 329 false, 330 }, 331 } 332 333 for _, tc := range testcases { 334 t.Run(tc.name, func(t *testing.T) { 335 h.TempDir(tc.name) 336 baseDir := h.Path(tc.name) 337 tc.fs.before.root = baseDir 338 tc.fs.after.root = baseDir 339 340 tc.fs.setup(t) 341 342 fs, err := deriveFilesystemState(baseDir) 343 if err != nil { 344 t.Fatal(err) 345 } 346 347 err = pruneNonGoFiles(fs) 348 if tc.err && err == nil { 349 t.Errorf("expected an error, got nil") 350 } else if !tc.err && err != nil { 351 t.Errorf("unexpected error: %s", err) 352 } 353 354 tc.fs.assert(t) 355 }) 356 } 357 } 358 359 func TestPruneGoTestFiles(t *testing.T) { 360 h := test.NewHelper(t) 361 defer h.Cleanup() 362 363 h.TempDir(".") 364 365 testcases := []struct { 366 name string 367 fs fsTestCase 368 err bool 369 }{ 370 { 371 "one-test-file", 372 fsTestCase{ 373 before: filesystemState{ 374 files: []string{ 375 "main_test.go", 376 }, 377 }, 378 after: filesystemState{}, 379 }, 380 false, 381 }, 382 { 383 "multiple-files", 384 fsTestCase{ 385 before: filesystemState{ 386 dirs: []string{ 387 "dir", 388 }, 389 files: []string{ 390 "dir/main_test.go", 391 "dir/main2_test.go", 392 }, 393 }, 394 after: filesystemState{ 395 dirs: []string{ 396 "dir", 397 }, 398 }, 399 }, 400 false, 401 }, 402 { 403 "mixed-files", 404 fsTestCase{ 405 before: filesystemState{ 406 dirs: []string{ 407 "dir", 408 }, 409 files: []string{ 410 "dir/main.go", 411 "dir/main2.go", 412 "dir/main_test.go", 413 "dir/main2_test.go", 414 }, 415 }, 416 after: filesystemState{ 417 dirs: []string{ 418 "dir", 419 }, 420 files: []string{ 421 "dir/main.go", 422 "dir/main2.go", 423 }, 424 }, 425 }, 426 false, 427 }, 428 } 429 430 for _, tc := range testcases { 431 t.Run(tc.name, func(t *testing.T) { 432 h.TempDir(tc.name) 433 baseDir := h.Path(tc.name) 434 tc.fs.before.root = baseDir 435 tc.fs.after.root = baseDir 436 437 tc.fs.setup(t) 438 439 fs, err := deriveFilesystemState(baseDir) 440 if err != nil { 441 t.Fatal(err) 442 } 443 444 err = pruneGoTestFiles(fs) 445 if tc.err && err == nil { 446 t.Fatalf("expected an error, got nil") 447 } else if !tc.err && err != nil { 448 t.Fatalf("unexpected error: %s", err) 449 } 450 451 tc.fs.assert(t) 452 }) 453 } 454 } 455 456 func TestPruneVendorDirs(t *testing.T) { 457 tests := []struct { 458 name string 459 test fsTestCase 460 }{ 461 { 462 name: "vendor directory", 463 test: fsTestCase{ 464 before: filesystemState{ 465 dirs: []string{ 466 "package", 467 "package/vendor", 468 }, 469 }, 470 after: filesystemState{ 471 dirs: []string{ 472 "package", 473 }, 474 }, 475 }, 476 }, 477 { 478 name: "vendor file", 479 test: fsTestCase{ 480 before: filesystemState{ 481 dirs: []string{ 482 "package", 483 }, 484 files: []string{ 485 "package/vendor", 486 }, 487 }, 488 after: filesystemState{ 489 dirs: []string{ 490 "package", 491 }, 492 files: []string{ 493 "package/vendor", 494 }, 495 }, 496 }, 497 }, 498 { 499 name: "vendor symlink", 500 test: fsTestCase{ 501 before: filesystemState{ 502 dirs: []string{ 503 "package", 504 "package/_vendor", 505 }, 506 links: []fsLink{ 507 { 508 path: "package/vendor", 509 to: "_vendor", 510 }, 511 }, 512 }, 513 after: filesystemState{ 514 dirs: []string{ 515 "package", 516 "package/_vendor", 517 }, 518 }, 519 }, 520 }, 521 { 522 name: "nonvendor symlink", 523 test: fsTestCase{ 524 before: filesystemState{ 525 dirs: []string{ 526 "package", 527 "package/_vendor", 528 }, 529 links: []fsLink{ 530 { 531 path: "package/link", 532 to: "_vendor", 533 }, 534 }, 535 }, 536 after: filesystemState{ 537 dirs: []string{ 538 "package", 539 "package/_vendor", 540 }, 541 links: []fsLink{ 542 { 543 path: "package/link", 544 to: "_vendor", 545 }, 546 }, 547 }, 548 }, 549 }, 550 { 551 name: "vendor symlink to file", 552 test: fsTestCase{ 553 before: filesystemState{ 554 files: []string{ 555 "file", 556 }, 557 links: []fsLink{ 558 { 559 path: "vendor", 560 to: "file", 561 }, 562 }, 563 }, 564 after: filesystemState{ 565 files: []string{ 566 "file", 567 }, 568 }, 569 }, 570 }, 571 { 572 name: "broken vendor symlink", 573 test: fsTestCase{ 574 before: filesystemState{ 575 dirs: []string{ 576 "package", 577 }, 578 links: []fsLink{ 579 { 580 path: "package/vendor", 581 to: "nonexistence", 582 }, 583 }, 584 }, 585 after: filesystemState{ 586 dirs: []string{ 587 "package", 588 }, 589 links: []fsLink{}, 590 }, 591 }, 592 }, 593 { 594 name: "chained symlinks", 595 test: fsTestCase{ 596 before: filesystemState{ 597 dirs: []string{ 598 "_vendor", 599 }, 600 links: []fsLink{ 601 { 602 path: "vendor", 603 to: "vendor2", 604 }, 605 { 606 path: "vendor2", 607 to: "_vendor", 608 }, 609 }, 610 }, 611 after: filesystemState{ 612 dirs: []string{ 613 "_vendor", 614 }, 615 links: []fsLink{ 616 { 617 path: "vendor2", 618 to: "_vendor", 619 }, 620 }, 621 }, 622 }, 623 }, 624 { 625 name: "circular symlinks", 626 test: fsTestCase{ 627 before: filesystemState{ 628 dirs: []string{ 629 "package", 630 }, 631 links: []fsLink{ 632 { 633 path: "package/link1", 634 to: "link2", 635 }, 636 { 637 path: "package/link2", 638 to: "link1", 639 }, 640 }, 641 }, 642 after: filesystemState{ 643 dirs: []string{ 644 "package", 645 }, 646 links: []fsLink{ 647 { 648 path: "package/link1", 649 to: "link2", 650 }, 651 { 652 path: "package/link2", 653 to: "link1", 654 }, 655 }, 656 }, 657 }, 658 }, 659 } 660 661 for _, test := range tests { 662 t.Run(test.name, pruneVendorDirsTestCase(test.test)) 663 } 664 } 665 666 func pruneVendorDirsTestCase(tc fsTestCase) func(*testing.T) { 667 return func(t *testing.T) { 668 tempDir, err := ioutil.TempDir("", "pruneVendorDirsTestCase") 669 if err != nil { 670 t.Fatalf("ioutil.TempDir err=%q", err) 671 } 672 defer func() { 673 if err := os.RemoveAll(tempDir); err != nil { 674 t.Errorf("os.RemoveAll(%q) err=%q", tempDir, err) 675 } 676 }() 677 678 tc.before.root = tempDir 679 tc.after.root = tempDir 680 681 tc.setup(t) 682 683 fs, err := deriveFilesystemState(tempDir) 684 if err != nil { 685 t.Fatalf("deriveFilesystemState failed: %s", err) 686 } 687 688 if err := pruneVendorDirs(fs); err != nil { 689 t.Errorf("pruneVendorDirs err=%q", err) 690 } 691 692 tc.assert(t) 693 } 694 } 695 696 func TestDeleteEmptyDirs(t *testing.T) { 697 testcases := []struct { 698 name string 699 fs fsTestCase 700 }{ 701 { 702 name: "empty-dir", 703 fs: fsTestCase{ 704 before: filesystemState{ 705 dirs: []string{ 706 "pkg1", 707 }, 708 }, 709 after: filesystemState{}, 710 }, 711 }, 712 { 713 name: "nested-empty-dirs", 714 fs: fsTestCase{ 715 before: filesystemState{ 716 dirs: []string{ 717 "pkg1", 718 "pkg1/pkg2", 719 }, 720 }, 721 after: filesystemState{}, 722 }, 723 }, 724 { 725 name: "non-empty-dir", 726 fs: fsTestCase{ 727 before: filesystemState{ 728 dirs: []string{ 729 "pkg1", 730 }, 731 files: []string{ 732 "pkg1/file1", 733 }, 734 }, 735 after: filesystemState{ 736 dirs: []string{ 737 "pkg1", 738 }, 739 files: []string{ 740 "pkg1/file1", 741 }, 742 }, 743 }, 744 }, 745 { 746 name: "mixed-dirs", 747 fs: fsTestCase{ 748 before: filesystemState{ 749 dirs: []string{ 750 "pkg1", 751 "pkg1/pkg2", 752 }, 753 files: []string{ 754 "pkg1/file1", 755 }, 756 }, 757 after: filesystemState{ 758 dirs: []string{ 759 "pkg1", 760 }, 761 files: []string{ 762 "pkg1/file1", 763 }, 764 }, 765 }, 766 }, 767 } 768 769 for _, tc := range testcases { 770 t.Run(tc.name, func(t *testing.T) { 771 h := test.NewHelper(t) 772 h.Cleanup() 773 h.TempDir(".") 774 775 tc.fs.before.root = h.Path(".") 776 tc.fs.after.root = h.Path(".") 777 778 if err := tc.fs.before.setup(); err != nil { 779 t.Fatal("unexpected error in fs setup: ", err) 780 } 781 782 if err := deleteEmptyDirs(tc.fs.before); err != nil { 783 t.Fatal("unexpected error in deleteEmptyDirs: ", err) 784 } 785 786 tc.fs.assert(t) 787 }) 788 } 789 }