blob: f3bc1baf4e98755884618846122f90b9e0954be2 [file] [log] [blame]
Rupert Shuttleworthc5fa3062021-09-08 10:36:41 -04001// Copyright 2021 Google Inc. 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
15package bp2build
16
17import (
18 "android/soong/android"
19 "android/soong/genrule"
20 "strings"
21 "testing"
22)
23
24func TestGenruleBp2Build(t *testing.T) {
25 otherGenruleBp := map[string]string{
26 "other/Android.bp": `genrule {
27 name: "foo.tool",
28 out: ["foo_tool.out"],
29 srcs: ["foo_tool.in"],
30 cmd: "cp $(in) $(out)",
31}
32genrule {
33 name: "other.tool",
34 out: ["other_tool.out"],
35 srcs: ["other_tool.in"],
36 cmd: "cp $(in) $(out)",
37}`,
38 }
39
40 testCases := []bp2buildTestCase{
41 {
42 description: "genrule with command line variable replacements",
43 moduleTypeUnderTest: "genrule",
44 moduleTypeUnderTestFactory: genrule.GenRuleFactory,
45 moduleTypeUnderTestBp2BuildMutator: genrule.GenruleBp2Build,
46 blueprint: `genrule {
47 name: "foo.tool",
48 out: ["foo_tool.out"],
49 srcs: ["foo_tool.in"],
50 cmd: "cp $(in) $(out)",
51 bazel_module: { bp2build_available: true },
52}
53
54genrule {
55 name: "foo",
56 out: ["foo.out"],
57 srcs: ["foo.in"],
58 tools: [":foo.tool"],
59 cmd: "$(location :foo.tool) --genDir=$(genDir) arg $(in) $(out)",
60 bazel_module: { bp2build_available: true },
61}`,
62 expectedBazelTargets: []string{
63 `genrule(
64 name = "foo",
65 cmd = "$(location :foo.tool) --genDir=$(GENDIR) arg $(SRCS) $(OUTS)",
66 outs = ["foo.out"],
67 srcs = ["foo.in"],
68 tools = [":foo.tool"],
69)`,
70 `genrule(
71 name = "foo.tool",
72 cmd = "cp $(SRCS) $(OUTS)",
73 outs = ["foo_tool.out"],
74 srcs = ["foo_tool.in"],
75)`,
76 },
77 },
78 {
79 description: "genrule using $(locations :label)",
80 moduleTypeUnderTest: "genrule",
81 moduleTypeUnderTestFactory: genrule.GenRuleFactory,
82 moduleTypeUnderTestBp2BuildMutator: genrule.GenruleBp2Build,
83 blueprint: `genrule {
84 name: "foo.tools",
85 out: ["foo_tool.out", "foo_tool2.out"],
86 srcs: ["foo_tool.in"],
87 cmd: "cp $(in) $(out)",
88 bazel_module: { bp2build_available: true },
89}
90
91genrule {
92 name: "foo",
93 out: ["foo.out"],
94 srcs: ["foo.in"],
95 tools: [":foo.tools"],
96 cmd: "$(locations :foo.tools) -s $(out) $(in)",
97 bazel_module: { bp2build_available: true },
98}`,
99 expectedBazelTargets: []string{`genrule(
100 name = "foo",
101 cmd = "$(locations :foo.tools) -s $(OUTS) $(SRCS)",
102 outs = ["foo.out"],
103 srcs = ["foo.in"],
104 tools = [":foo.tools"],
105)`,
106 `genrule(
107 name = "foo.tools",
108 cmd = "cp $(SRCS) $(OUTS)",
109 outs = [
110 "foo_tool.out",
111 "foo_tool2.out",
112 ],
113 srcs = ["foo_tool.in"],
114)`,
115 },
116 },
117 {
118 description: "genrule using $(locations //absolute:label)",
119 moduleTypeUnderTest: "genrule",
120 moduleTypeUnderTestFactory: genrule.GenRuleFactory,
121 moduleTypeUnderTestBp2BuildMutator: genrule.GenruleBp2Build,
122 blueprint: `genrule {
123 name: "foo",
124 out: ["foo.out"],
125 srcs: ["foo.in"],
126 tool_files: [":foo.tool"],
127 cmd: "$(locations :foo.tool) -s $(out) $(in)",
128 bazel_module: { bp2build_available: true },
129}`,
130 expectedBazelTargets: []string{`genrule(
131 name = "foo",
132 cmd = "$(locations //other:foo.tool) -s $(OUTS) $(SRCS)",
133 outs = ["foo.out"],
134 srcs = ["foo.in"],
135 tools = ["//other:foo.tool"],
136)`,
137 },
138 filesystem: otherGenruleBp,
139 },
140 {
141 description: "genrule srcs using $(locations //absolute:label)",
142 moduleTypeUnderTest: "genrule",
143 moduleTypeUnderTestFactory: genrule.GenRuleFactory,
144 moduleTypeUnderTestBp2BuildMutator: genrule.GenruleBp2Build,
145 blueprint: `genrule {
146 name: "foo",
147 out: ["foo.out"],
148 srcs: [":other.tool"],
149 tool_files: [":foo.tool"],
150 cmd: "$(locations :foo.tool) -s $(out) $(location :other.tool)",
151 bazel_module: { bp2build_available: true },
152}`,
153 expectedBazelTargets: []string{`genrule(
154 name = "foo",
155 cmd = "$(locations //other:foo.tool) -s $(OUTS) $(location //other:other.tool)",
156 outs = ["foo.out"],
157 srcs = ["//other:other.tool"],
158 tools = ["//other:foo.tool"],
159)`,
160 },
161 filesystem: otherGenruleBp,
162 },
163 {
164 description: "genrule using $(location) label should substitute first tool label automatically",
165 moduleTypeUnderTest: "genrule",
166 moduleTypeUnderTestFactory: genrule.GenRuleFactory,
167 moduleTypeUnderTestBp2BuildMutator: genrule.GenruleBp2Build,
168 blueprint: `genrule {
169 name: "foo",
170 out: ["foo.out"],
171 srcs: ["foo.in"],
172 tool_files: [":foo.tool", ":other.tool"],
173 cmd: "$(location) -s $(out) $(in)",
174 bazel_module: { bp2build_available: true },
175}`,
176 expectedBazelTargets: []string{`genrule(
177 name = "foo",
178 cmd = "$(location //other:foo.tool) -s $(OUTS) $(SRCS)",
179 outs = ["foo.out"],
180 srcs = ["foo.in"],
181 tools = [
182 "//other:foo.tool",
183 "//other:other.tool",
184 ],
185)`,
186 },
187 filesystem: otherGenruleBp,
188 },
189 {
190 description: "genrule using $(locations) label should substitute first tool label automatically",
191 moduleTypeUnderTest: "genrule",
192 moduleTypeUnderTestFactory: genrule.GenRuleFactory,
193 moduleTypeUnderTestBp2BuildMutator: genrule.GenruleBp2Build,
194 blueprint: `genrule {
195 name: "foo",
196 out: ["foo.out"],
197 srcs: ["foo.in"],
198 tools: [":foo.tool", ":other.tool"],
199 cmd: "$(locations) -s $(out) $(in)",
200 bazel_module: { bp2build_available: true },
201}`,
202 expectedBazelTargets: []string{`genrule(
203 name = "foo",
204 cmd = "$(locations //other:foo.tool) -s $(OUTS) $(SRCS)",
205 outs = ["foo.out"],
206 srcs = ["foo.in"],
207 tools = [
208 "//other:foo.tool",
209 "//other:other.tool",
210 ],
211)`,
212 },
213 filesystem: otherGenruleBp,
214 },
215 {
216 description: "genrule without tools or tool_files can convert successfully",
217 moduleTypeUnderTest: "genrule",
218 moduleTypeUnderTestFactory: genrule.GenRuleFactory,
219 moduleTypeUnderTestBp2BuildMutator: genrule.GenruleBp2Build,
220 blueprint: `genrule {
221 name: "foo",
222 out: ["foo.out"],
223 srcs: ["foo.in"],
224 cmd: "cp $(in) $(out)",
225 bazel_module: { bp2build_available: true },
226}`,
227 expectedBazelTargets: []string{`genrule(
228 name = "foo",
229 cmd = "cp $(SRCS) $(OUTS)",
230 outs = ["foo.out"],
231 srcs = ["foo.in"],
232)`,
233 },
234 },
235 }
236
237 dir := "."
238 for _, testCase := range testCases {
239 fs := make(map[string][]byte)
240 toParse := []string{
241 "Android.bp",
242 }
243 for f, content := range testCase.filesystem {
244 if strings.HasSuffix(f, "Android.bp") {
245 toParse = append(toParse, f)
246 }
247 fs[f] = []byte(content)
248 }
249 config := android.TestConfig(buildDir, nil, testCase.blueprint, fs)
250 ctx := android.NewTestContext(config)
251 ctx.RegisterModuleType(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestFactory)
252 ctx.RegisterBp2BuildMutator(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestBp2BuildMutator)
253 ctx.RegisterForBazelConversion()
254
255 _, errs := ctx.ParseFileList(dir, toParse)
256 if errored(t, testCase, errs) {
257 continue
258 }
259 _, errs = ctx.ResolveDependencies(config)
260 if errored(t, testCase, errs) {
261 continue
262 }
263
264 checkDir := dir
265 if testCase.dir != "" {
266 checkDir = testCase.dir
267 }
268
269 codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
Liz Kammer6eff3232021-08-26 08:37:59 -0400270 bazelTargets, err := generateBazelTargetsForDir(codegenCtx, checkDir)
271 android.FailIfErrored(t, err)
Rupert Shuttleworthc5fa3062021-09-08 10:36:41 -0400272 if actualCount, expectedCount := len(bazelTargets), len(testCase.expectedBazelTargets); actualCount != expectedCount {
273 t.Errorf("%s: Expected %d bazel target, got %d", testCase.description, expectedCount, actualCount)
274 } else {
275 for i, target := range bazelTargets {
276 if w, g := testCase.expectedBazelTargets[i], target.content; w != g {
277 t.Errorf(
278 "%s: Expected generated Bazel target to be '%s', got '%s'",
279 testCase.description,
280 w,
281 g,
282 )
283 }
284 }
285 }
286 }
287}
288
289func TestBp2BuildInlinesDefaults(t *testing.T) {
290 testCases := []struct {
291 moduleTypesUnderTest map[string]android.ModuleFactory
292 bp2buildMutatorsUnderTest map[string]bp2buildMutator
293 bp string
294 expectedBazelTarget string
295 description string
296 }{
297 {
298 moduleTypesUnderTest: map[string]android.ModuleFactory{
299 "genrule": genrule.GenRuleFactory,
300 "genrule_defaults": func() android.Module { return genrule.DefaultsFactory() },
301 },
302 bp2buildMutatorsUnderTest: map[string]bp2buildMutator{
303 "genrule": genrule.GenruleBp2Build,
304 },
305 bp: `genrule_defaults {
306 name: "gen_defaults",
307 cmd: "do-something $(in) $(out)",
308}
309genrule {
310 name: "gen",
311 out: ["out"],
312 srcs: ["in1"],
313 defaults: ["gen_defaults"],
314 bazel_module: { bp2build_available: true },
315}
316`,
317 expectedBazelTarget: `genrule(
318 name = "gen",
319 cmd = "do-something $(SRCS) $(OUTS)",
320 outs = ["out"],
321 srcs = ["in1"],
322)`,
323 description: "genrule applies properties from a genrule_defaults dependency if not specified",
324 },
325 {
326 moduleTypesUnderTest: map[string]android.ModuleFactory{
327 "genrule": genrule.GenRuleFactory,
328 "genrule_defaults": func() android.Module { return genrule.DefaultsFactory() },
329 },
330 bp2buildMutatorsUnderTest: map[string]bp2buildMutator{
331 "genrule": genrule.GenruleBp2Build,
332 },
333 bp: `genrule_defaults {
334 name: "gen_defaults",
335 out: ["out-from-defaults"],
336 srcs: ["in-from-defaults"],
337 cmd: "cmd-from-defaults",
338}
339genrule {
340 name: "gen",
341 out: ["out"],
342 srcs: ["in1"],
343 defaults: ["gen_defaults"],
344 cmd: "do-something $(in) $(out)",
345 bazel_module: { bp2build_available: true },
346}
347`,
348 expectedBazelTarget: `genrule(
349 name = "gen",
350 cmd = "do-something $(SRCS) $(OUTS)",
351 outs = [
352 "out-from-defaults",
353 "out",
354 ],
355 srcs = [
356 "in-from-defaults",
357 "in1",
358 ],
359)`,
360 description: "genrule does merges properties from a genrule_defaults dependency, latest-first",
361 },
362 {
363 moduleTypesUnderTest: map[string]android.ModuleFactory{
364 "genrule": genrule.GenRuleFactory,
365 "genrule_defaults": func() android.Module { return genrule.DefaultsFactory() },
366 },
367 bp2buildMutatorsUnderTest: map[string]bp2buildMutator{
368 "genrule": genrule.GenruleBp2Build,
369 },
370 bp: `genrule_defaults {
371 name: "gen_defaults1",
372 cmd: "cp $(in) $(out)",
373}
374
375genrule_defaults {
376 name: "gen_defaults2",
377 srcs: ["in1"],
378}
379
380genrule {
381 name: "gen",
382 out: ["out"],
383 defaults: ["gen_defaults1", "gen_defaults2"],
384 bazel_module: { bp2build_available: true },
385}
386`,
387 expectedBazelTarget: `genrule(
388 name = "gen",
389 cmd = "cp $(SRCS) $(OUTS)",
390 outs = ["out"],
391 srcs = ["in1"],
392)`,
393 description: "genrule applies properties from list of genrule_defaults",
394 },
395 {
396 moduleTypesUnderTest: map[string]android.ModuleFactory{
397 "genrule": genrule.GenRuleFactory,
398 "genrule_defaults": func() android.Module { return genrule.DefaultsFactory() },
399 },
400 bp2buildMutatorsUnderTest: map[string]bp2buildMutator{
401 "genrule": genrule.GenruleBp2Build,
402 },
403 bp: `genrule_defaults {
404 name: "gen_defaults1",
405 defaults: ["gen_defaults2"],
406 cmd: "cmd1 $(in) $(out)", // overrides gen_defaults2's cmd property value.
407}
408
409genrule_defaults {
410 name: "gen_defaults2",
411 defaults: ["gen_defaults3"],
412 cmd: "cmd2 $(in) $(out)",
413 out: ["out-from-2"],
414 srcs: ["in1"],
415}
416
417genrule_defaults {
418 name: "gen_defaults3",
419 out: ["out-from-3"],
420 srcs: ["srcs-from-3"],
421}
422
423genrule {
424 name: "gen",
425 out: ["out"],
426 defaults: ["gen_defaults1"],
427 bazel_module: { bp2build_available: true },
428}
429`,
430 expectedBazelTarget: `genrule(
431 name = "gen",
432 cmd = "cmd1 $(SRCS) $(OUTS)",
433 outs = [
434 "out-from-3",
435 "out-from-2",
436 "out",
437 ],
438 srcs = [
439 "srcs-from-3",
440 "in1",
441 ],
442)`,
443 description: "genrule applies properties from genrule_defaults transitively",
444 },
445 }
446
447 dir := "."
448 for _, testCase := range testCases {
449 config := android.TestConfig(buildDir, nil, testCase.bp, nil)
450 ctx := android.NewTestContext(config)
451 for m, factory := range testCase.moduleTypesUnderTest {
452 ctx.RegisterModuleType(m, factory)
453 }
454 for mutator, f := range testCase.bp2buildMutatorsUnderTest {
455 ctx.RegisterBp2BuildMutator(mutator, f)
456 }
457 ctx.RegisterForBazelConversion()
458
459 _, errs := ctx.ParseFileList(dir, []string{"Android.bp"})
460 android.FailIfErrored(t, errs)
461 _, errs = ctx.ResolveDependencies(config)
462 android.FailIfErrored(t, errs)
463
464 codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
Liz Kammer6eff3232021-08-26 08:37:59 -0400465 bazelTargets, err := generateBazelTargetsForDir(codegenCtx, dir)
466 android.FailIfErrored(t, err)
Rupert Shuttleworthc5fa3062021-09-08 10:36:41 -0400467 if actualCount := len(bazelTargets); actualCount != 1 {
468 t.Fatalf("%s: Expected 1 bazel target, got %d", testCase.description, actualCount)
469 }
470
471 actualBazelTarget := bazelTargets[0]
472 if actualBazelTarget.content != testCase.expectedBazelTarget {
473 t.Errorf(
474 "%s: Expected generated Bazel target to be '%s', got '%s'",
475 testCase.description,
476 testCase.expectedBazelTarget,
477 actualBazelTarget.content,
478 )
479 }
480 }
481}