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  }