github.com/shulhan/golangci-lint@v1.10.1/pkg/packages/resolver_test.go (about) 1 package packages_test 2 3 import ( 4 "io/ioutil" 5 "os" 6 "path/filepath" 7 "sort" 8 "strings" 9 "testing" 10 11 "github.com/golangci/golangci-lint/pkg/fsutils" 12 "github.com/golangci/golangci-lint/pkg/logutils" 13 "github.com/golangci/golangci-lint/pkg/packages" 14 "github.com/stretchr/testify/assert" 15 ) 16 17 type fsPreparer struct { 18 t *testing.T 19 root string 20 prevWD string 21 } 22 23 func (fp fsPreparer) clean() { 24 err := os.Chdir(fp.prevWD) 25 assert.NoError(fp.t, err) 26 27 err = os.RemoveAll(fp.root) 28 assert.NoError(fp.t, err) 29 } 30 31 func prepareFS(t *testing.T, paths ...string) *fsPreparer { 32 root, err := ioutil.TempDir("/tmp", "golangci.test.path_resolver") 33 assert.NoError(t, err) 34 35 prevWD, err := fsutils.Getwd() 36 assert.NoError(t, err) 37 38 err = os.Chdir(root) 39 assert.NoError(t, err) 40 41 for _, p := range paths { 42 err = os.MkdirAll(filepath.Dir(p), os.ModePerm) 43 assert.NoError(t, err) 44 45 if strings.HasSuffix(p, "/") { 46 continue 47 } 48 49 goFile := "package p\n" 50 err = ioutil.WriteFile(p, []byte(goFile), os.ModePerm) 51 assert.NoError(t, err) 52 } 53 54 return &fsPreparer{ 55 root: root, 56 t: t, 57 prevWD: prevWD, 58 } 59 } 60 61 func newTestResolver(t *testing.T, excludeDirs []string) *packages.Resolver { 62 r, err := packages.NewResolver(nil, excludeDirs, logutils.NewStderrLog("")) 63 assert.NoError(t, err) 64 65 return r 66 } 67 68 func TestPathResolverNotExistingPath(t *testing.T) { 69 fp := prepareFS(t) 70 defer fp.clean() 71 72 _, err := newTestResolver(t, nil).Resolve("a") 73 assert.EqualError(t, err, "can't eval symlinks for path a: lstat a: no such file or directory") 74 } 75 76 func TestPathResolverCommonCases(t *testing.T) { 77 type testCase struct { 78 name string 79 prepare []string 80 resolve []string 81 expFiles []string 82 expDirs []string 83 includeTests bool 84 } 85 86 testCases := []testCase{ 87 { 88 name: "empty root recursively", 89 resolve: []string{"./..."}, 90 }, 91 { 92 name: "empty root", 93 resolve: []string{"./"}, 94 }, 95 { 96 name: "vendor is excluded recursively", 97 prepare: []string{"vendor/a/b.go"}, 98 resolve: []string{"./..."}, 99 }, 100 { 101 name: "vendor is excluded", 102 prepare: []string{"vendor/a.go"}, 103 resolve: []string{"./..."}, 104 }, 105 { 106 name: "nested vendor is excluded", 107 prepare: []string{"d/vendor/a.go"}, 108 resolve: []string{"./..."}, 109 }, 110 { 111 name: "vendor dir is excluded by regexp, not the exact match", 112 prepare: []string{"vendors/a.go", "novendor/b.go"}, 113 resolve: []string{"./..."}, 114 expDirs: []string{"vendors"}, 115 expFiles: []string{"vendors/a.go"}, 116 }, 117 { 118 name: "vendor explicitly resolved", 119 prepare: []string{"vendor/a.go"}, 120 resolve: []string{"./vendor"}, 121 expDirs: []string{"vendor"}, 122 expFiles: []string{"vendor/a.go"}, 123 }, 124 { 125 name: "nested vendor explicitly resolved", 126 prepare: []string{"d/vendor/a.go"}, 127 resolve: []string{"d/vendor"}, 128 expDirs: []string{"d/vendor"}, 129 expFiles: []string{"d/vendor/a.go"}, 130 }, 131 { 132 name: "extensions filter recursively", 133 prepare: []string{"a/b.go", "a/c.txt", "d.go", "e.csv"}, 134 resolve: []string{"./..."}, 135 expDirs: []string{".", "a"}, 136 expFiles: []string{"a/b.go", "d.go"}, 137 }, 138 { 139 name: "extensions filter", 140 prepare: []string{"a/b.go", "a/c.txt", "d.go"}, 141 resolve: []string{"a"}, 142 expDirs: []string{"a"}, 143 expFiles: []string{"a/b.go"}, 144 }, 145 { 146 name: "one level dirs exclusion", 147 prepare: []string{"a/b/d.go", "a/c.go"}, 148 resolve: []string{"./a"}, 149 expDirs: []string{"a"}, 150 expFiles: []string{"a/c.go"}, 151 }, 152 { 153 name: "explicitly resolved files", 154 prepare: []string{"a/b/c.go", "a/d.txt"}, 155 resolve: []string{"./a/...", "a/d.txt"}, 156 expDirs: []string{"a/b"}, 157 expFiles: []string{"a/b/c.go", "a/d.txt"}, 158 }, 159 { 160 name: ".* dotfiles are always ignored", 161 prepare: []string{".git/a.go", ".circleci/b.go"}, 162 resolve: []string{"./..."}, 163 }, 164 { 165 name: "exclude dirs on any depth level", 166 prepare: []string{"ok/.git/a.go", "ok/b.go"}, 167 resolve: []string{"./..."}, 168 expDirs: []string{"ok"}, 169 expFiles: []string{"ok/b.go"}, 170 }, 171 { 172 name: "exclude path, not name", 173 prepare: []string{"ex/clude/me/a.go", "c/d.go"}, 174 resolve: []string{"./..."}, 175 expDirs: []string{"c"}, 176 expFiles: []string{"c/d.go"}, 177 }, 178 { 179 name: "exclude partial path", 180 prepare: []string{"prefix/ex/clude/me/a.go", "prefix/ex/clude/me/subdir/c.go", "prefix/b.go"}, 181 resolve: []string{"./..."}, 182 expDirs: []string{"prefix"}, 183 expFiles: []string{"prefix/b.go"}, 184 }, 185 { 186 name: "don't exclude file instead of dir", 187 prepare: []string{"a/exclude.go"}, 188 resolve: []string{"a"}, 189 expDirs: []string{"a"}, 190 expFiles: []string{"a/exclude.go"}, 191 }, 192 { 193 name: "don't exclude file instead of dir: check dir is excluded", 194 prepare: []string{"a/exclude.go/b.go"}, 195 resolve: []string{"a/..."}, 196 }, 197 { 198 name: "ignore _*", 199 prepare: []string{"_any/a.go"}, 200 resolve: []string{"./..."}, 201 }, 202 { 203 name: "include tests", 204 prepare: []string{"a/b.go", "a/b_test.go"}, 205 resolve: []string{"./..."}, 206 expDirs: []string{"a"}, 207 expFiles: []string{"a/b.go", "a/b_test.go"}, 208 includeTests: true, 209 }, 210 { 211 name: "exclude tests", 212 prepare: []string{"a/b.go", "a/b_test.go"}, 213 resolve: []string{"./..."}, 214 expDirs: []string{"a"}, 215 expFiles: []string{"a/b.go"}, 216 }, 217 { 218 name: "exclude tests except explicitly set", 219 prepare: []string{"a/b.go", "a/b_test.go", "a/c_test.go"}, 220 resolve: []string{"./...", "a/c_test.go"}, 221 expDirs: []string{"a"}, 222 expFiles: []string{"a/b.go", "a/c_test.go"}, 223 }, 224 { 225 name: "exclude dirs with no go files", 226 prepare: []string{"a/b.txt", "a/c/d.go"}, 227 resolve: []string{"./..."}, 228 expDirs: []string{"a/c"}, 229 expFiles: []string{"a/c/d.go"}, 230 }, 231 { 232 name: "exclude dirs with no go files with root dir", 233 prepare: []string{"a/b.txt", "a/c/d.go", "e.go"}, 234 resolve: []string{"./..."}, 235 expDirs: []string{".", "a/c"}, 236 expFiles: []string{"a/c/d.go", "e.go"}, 237 }, 238 { 239 name: "resolve absolute paths", 240 prepare: []string{"a/b.go", "a/c.txt", "d.go", "e.csv"}, 241 resolve: []string{"${CWD}/..."}, 242 expDirs: []string{".", "a"}, 243 expFiles: []string{"a/b.go", "d.go"}, 244 }, 245 } 246 247 fsutils.UseWdCache(false) 248 for _, tc := range testCases { 249 t.Run(tc.name, func(t *testing.T) { 250 fp := prepareFS(t, tc.prepare...) 251 defer fp.clean() 252 253 for i, rp := range tc.resolve { 254 tc.resolve[i] = strings.Replace(rp, "${CWD}", fp.root, -1) 255 } 256 257 r := newTestResolver(t, []string{"vendor$", "ex/clude/me", "exclude"}) 258 259 prog, err := r.Resolve(tc.resolve...) 260 assert.NoError(t, err) 261 assert.NotNil(t, prog) 262 263 progFiles := prog.Files(tc.includeTests) 264 sort.StringSlice(progFiles).Sort() 265 sort.StringSlice(tc.expFiles).Sort() 266 267 progDirs := prog.Dirs() 268 sort.StringSlice(progDirs).Sort() 269 sort.StringSlice(tc.expDirs).Sort() 270 271 if tc.expFiles == nil { 272 assert.Empty(t, progFiles) 273 } else { 274 assert.Equal(t, tc.expFiles, progFiles, "files") 275 } 276 277 if tc.expDirs == nil { 278 assert.Empty(t, progDirs) 279 } else { 280 assert.Equal(t, tc.expDirs, progDirs, "dirs") 281 } 282 }) 283 } 284 }