1
15
16 package walk
17
18 import (
19 "flag"
20 "path"
21 "path/filepath"
22 "testing"
23
24 "github.com/bazelbuild/bazel-gazelle/config"
25 "github.com/bazelbuild/bazel-gazelle/rule"
26 "github.com/bazelbuild/bazel-gazelle/testtools"
27 "github.com/google/go-cmp/cmp"
28 )
29
30 func TestConfigureCallbackOrder(t *testing.T) {
31 dir, cleanup := testtools.CreateFiles(t, []testtools.FileSpec{{Path: "a/b/"}})
32 defer cleanup()
33
34 var configureRels, callbackRels []string
35 c, cexts := testConfig(t, dir)
36 cexts = append(cexts, &testConfigurer{func(_ *config.Config, rel string, _ *rule.File) {
37 configureRels = append(configureRels, rel)
38 }})
39 Walk(c, cexts, []string{dir}, VisitAllUpdateSubdirsMode, func(_ string, rel string, _ *config.Config, _ bool, _ *rule.File, _, _, _ []string) {
40 callbackRels = append(callbackRels, rel)
41 })
42 configureWant := []string{"", "a", "a/b"}
43 if diff := cmp.Diff(configureWant, configureRels); diff != "" {
44 t.Errorf("configure order (-want +got):\n%s", diff)
45 }
46 callbackWant := []string{"a/b", "a", ""}
47 if diff := cmp.Diff(callbackWant, callbackRels); diff != "" {
48 t.Errorf("callback order (-want +got):\n%s", diff)
49 }
50 }
51
52 func TestUpdateDirs(t *testing.T) {
53 dir, cleanup := testtools.CreateFiles(t, []testtools.FileSpec{
54 {Path: "update/sub/"},
55 {Path: "update/sub/sub/"},
56 {
57 Path: "update/ignore/BUILD.bazel",
58 Content: "# gazelle:ignore",
59 },
60 {Path: "update/ignore/sub/"},
61 {
62 Path: "update/error/BUILD.bazel",
63 Content: "(",
64 },
65 {Path: "update/error/sub/"},
66 })
67 defer cleanup()
68
69 type visitSpec struct {
70 Rel string
71 Update bool
72 }
73 for _, tc := range []struct {
74 desc string
75 rels []string
76 mode Mode
77 want []visitSpec
78 }{
79 {
80 desc: "visit_all_update_subdirs",
81 rels: []string{"update"},
82 mode: VisitAllUpdateSubdirsMode,
83 want: []visitSpec{
84 {"update/error/sub", true},
85 {"update/error", false},
86 {"update/ignore/sub", true},
87 {"update/ignore", false},
88 {"update/sub/sub", true},
89 {"update/sub", true},
90 {"update", true},
91 {"", false},
92 },
93 }, {
94 desc: "visit_all_update_dirs",
95 rels: []string{"update", "update/ignore/sub"},
96 mode: VisitAllUpdateDirsMode,
97 want: []visitSpec{
98 {"update/error/sub", false},
99 {"update/error", false},
100 {"update/ignore/sub", true},
101 {"update/ignore", false},
102 {"update/sub/sub", false},
103 {"update/sub", false},
104 {"update", true},
105 {"", false},
106 },
107 }, {
108 desc: "update_dirs",
109 rels: []string{"update", "update/ignore/sub"},
110 mode: UpdateDirsMode,
111 want: []visitSpec{
112 {"update/ignore/sub", true},
113 {"update", true},
114 },
115 }, {
116 desc: "update_subdirs",
117 rels: []string{"update/ignore", "update/sub"},
118 mode: UpdateSubdirsMode,
119 want: []visitSpec{
120 {"update/ignore/sub", true},
121 {"update/ignore", false},
122 {"update/sub/sub", true},
123 {"update/sub", true},
124 },
125 },
126 } {
127 t.Run(tc.desc, func(t *testing.T) {
128 c, cexts := testConfig(t, dir)
129 dirs := make([]string, len(tc.rels))
130 for i, rel := range tc.rels {
131 dirs[i] = filepath.Join(dir, filepath.FromSlash(rel))
132 }
133 var visits []visitSpec
134 Walk(c, cexts, dirs, tc.mode, func(_ string, rel string, _ *config.Config, update bool, _ *rule.File, _, _, _ []string) {
135 visits = append(visits, visitSpec{rel, update})
136 })
137 if diff := cmp.Diff(tc.want, visits); diff != "" {
138 t.Errorf("Walk visits (-want +got):\n%s", diff)
139 }
140 })
141 }
142 }
143
144 func TestCustomBuildName(t *testing.T) {
145 dir, cleanup := testtools.CreateFiles(t, []testtools.FileSpec{
146 {
147 Path: "BUILD.bazel",
148 Content: "# gazelle:build_file_name BUILD.test",
149 }, {
150 Path: "BUILD",
151 }, {
152 Path: "sub/BUILD.test",
153 }, {
154 Path: "sub/BUILD.bazel",
155 },
156 })
157 defer cleanup()
158
159 c, cexts := testConfig(t, dir)
160 var rels []string
161 Walk(c, cexts, []string{dir}, VisitAllUpdateSubdirsMode, func(_ string, _ string, _ *config.Config, _ bool, f *rule.File, _, _, _ []string) {
162 rel, err := filepath.Rel(c.RepoRoot, f.Path)
163 if err != nil {
164 t.Error(err)
165 } else {
166 rels = append(rels, filepath.ToSlash(rel))
167 }
168 })
169 want := []string{
170 "sub/BUILD.test",
171 "BUILD.bazel",
172 }
173 if diff := cmp.Diff(want, rels); diff != "" {
174 t.Errorf("Walk relative paths (-want +got):\n%s", diff)
175 }
176 }
177
178 func TestExcludeFiles(t *testing.T) {
179 dir, cleanup := testtools.CreateFiles(t, []testtools.FileSpec{
180 {
181 Path: "BUILD.bazel",
182 Content: `
183 # gazelle:exclude **/*.pb.go
184 # gazelle:exclude *.gen.go
185 # gazelle:exclude a.go
186 # gazelle:exclude c/**/b
187 # gazelle:exclude gen
188 # gazelle:exclude ign
189 # gazelle:exclude sub/b.go
190
191 gen(
192 name = "x",
193 out = "gen",
194 )`,
195 },
196 {
197 Path: ".bazelignore",
198 Content: `
199 dir
200 dir2/a/b
201 dir3/
202
203 # Globs are not allowed in .bazelignore so this will not be ignored
204 foo/*
205
206 # Random comment followed by a line
207 a.file
208 `,
209 },
210 {Path: ".dot"},
211 {Path: "_blank"},
212 {Path: "a/a.proto"},
213 {Path: "a/b.gen.go"},
214 {Path: "dir2/a/c"},
215 {Path: "foo/a/c"},
216
217 {Path: "a.gen.go"},
218 {Path: "a.go"},
219 {Path: "a.pb.go"},
220 {Path: "a/a.pb.go"},
221 {Path: "a/b/a.pb.go"},
222 {Path: "c/x/b/foo"},
223 {Path: "c/x/y/b/bar"},
224 {Path: "c/x/y/b/foo/bar"},
225 {Path: "ign/bad"},
226 {Path: "sub/b.go"},
227 {Path: "dir/contents"},
228 {Path: "dir2/a/b"},
229 {Path: "dir3/g/h"},
230 {Path: "a.file"},
231 })
232 defer cleanup()
233
234 c, cexts := testConfig(t, dir)
235 var files []string
236 Walk(c, cexts, []string{dir}, VisitAllUpdateSubdirsMode, func(_ string, rel string, _ *config.Config, _ bool, _ *rule.File, _, regularFiles, genFiles []string) {
237 for _, f := range regularFiles {
238 files = append(files, path.Join(rel, f))
239 }
240 for _, f := range genFiles {
241 files = append(files, path.Join(rel, f))
242 }
243 })
244 want := []string{"a/a.proto", "a/b.gen.go", "dir2/a/c", "foo/a/c", ".bazelignore", ".dot", "BUILD.bazel", "_blank"}
245 if diff := cmp.Diff(want, files); diff != "" {
246 t.Errorf("Walk files (-want +got):\n%s", diff)
247 }
248 }
249
250 func TestExcludeSelf(t *testing.T) {
251 dir, cleanup := testtools.CreateFiles(t, []testtools.FileSpec{
252 {
253 Path: "BUILD.bazel",
254 }, {
255 Path: "sub/BUILD.bazel",
256 Content: "# gazelle:exclude .",
257 }, {
258 Path: "sub/below/BUILD.bazel",
259 },
260 })
261 defer cleanup()
262
263 c, cexts := testConfig(t, dir)
264 var rels []string
265 Walk(c, cexts, []string{dir}, VisitAllUpdateDirsMode, func(_ string, rel string, _ *config.Config, _ bool, f *rule.File, _, _, _ []string) {
266 rels = append(rels, rel)
267 })
268
269 want := []string{""}
270 if diff := cmp.Diff(want, rels); diff != "" {
271 t.Errorf("Walk relative paths (-want +got):\n%s", diff)
272 }
273 }
274
275 func TestGeneratedFiles(t *testing.T) {
276 dir, cleanup := testtools.CreateFiles(t, []testtools.FileSpec{
277 {
278 Path: "BUILD.bazel",
279 Content: `
280 unknown_rule(
281 name = "blah1",
282 out = "gen1",
283 )
284
285 unknown_rule(
286 name = "blah2",
287 outs = [
288 "gen2",
289 "gen-and-static",
290 ],
291 )
292 `,
293 },
294 {Path: "gen-and-static"},
295 {Path: "static"},
296 })
297 defer cleanup()
298
299 c, cexts := testConfig(t, dir)
300 var regularFiles, genFiles []string
301 Walk(c, cexts, []string{dir}, VisitAllUpdateSubdirsMode, func(_ string, rel string, _ *config.Config, _ bool, _ *rule.File, _, reg, gen []string) {
302 for _, f := range reg {
303 regularFiles = append(regularFiles, path.Join(rel, f))
304 }
305 for _, f := range gen {
306 genFiles = append(genFiles, path.Join(rel, f))
307 }
308 })
309 regWant := []string{"BUILD.bazel", "gen-and-static", "static"}
310 if diff := cmp.Diff(regWant, regularFiles); diff != "" {
311 t.Errorf("Walk regularFiles (-want +got):\n%s", diff)
312 }
313 genWant := []string{"gen1", "gen2", "gen-and-static"}
314 if diff := cmp.Diff(genWant, genFiles); diff != "" {
315 t.Errorf("Walk genFiles (-want +got):\n%s", diff)
316 }
317 }
318
319 func testConfig(t *testing.T, dir string) (*config.Config, []config.Configurer) {
320 args := []string{"-repo_root", dir}
321 cexts := []config.Configurer{&config.CommonConfigurer{}, &Configurer{}}
322 c := testtools.NewTestConfig(t, cexts, nil, args)
323 return c, cexts
324 }
325
326 type testConfigurer struct {
327 configure func(c *config.Config, rel string, f *rule.File)
328 }
329
330 func (*testConfigurer) RegisterFlags(_ *flag.FlagSet, _ string, _ *config.Config) {}
331
332 func (*testConfigurer) CheckFlags(_ *flag.FlagSet, _ *config.Config) error { return nil }
333
334 func (*testConfigurer) KnownDirectives() []string { return nil }
335
336 func (tc *testConfigurer) Configure(c *config.Config, rel string, f *rule.File) {
337 tc.configure(c, rel, f)
338 }
339
View as plain text