blob: a9911808ef226a5d764b007d9624998a593283ff [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)
270 bazelTargets := generateBazelTargetsForDir(codegenCtx, checkDir)
271 if actualCount, expectedCount := len(bazelTargets), len(testCase.expectedBazelTargets); actualCount != expectedCount {
272 t.Errorf("%s: Expected %d bazel target, got %d", testCase.description, expectedCount, actualCount)
273 } else {
274 for i, target := range bazelTargets {
275 if w, g := testCase.expectedBazelTargets[i], target.content; w != g {
276 t.Errorf(
277 "%s: Expected generated Bazel target to be '%s', got '%s'",
278 testCase.description,
279 w,
280 g,
281 )
282 }
283 }
284 }
285 }
286}
287
288func TestBp2BuildInlinesDefaults(t *testing.T) {
289 testCases := []struct {
290 moduleTypesUnderTest map[string]android.ModuleFactory
291 bp2buildMutatorsUnderTest map[string]bp2buildMutator
292 bp string
293 expectedBazelTarget string
294 description string
295 }{
296 {
297 moduleTypesUnderTest: map[string]android.ModuleFactory{
298 "genrule": genrule.GenRuleFactory,
299 "genrule_defaults": func() android.Module { return genrule.DefaultsFactory() },
300 },
301 bp2buildMutatorsUnderTest: map[string]bp2buildMutator{
302 "genrule": genrule.GenruleBp2Build,
303 },
304 bp: `genrule_defaults {
305 name: "gen_defaults",
306 cmd: "do-something $(in) $(out)",
307}
308genrule {
309 name: "gen",
310 out: ["out"],
311 srcs: ["in1"],
312 defaults: ["gen_defaults"],
313 bazel_module: { bp2build_available: true },
314}
315`,
316 expectedBazelTarget: `genrule(
317 name = "gen",
318 cmd = "do-something $(SRCS) $(OUTS)",
319 outs = ["out"],
320 srcs = ["in1"],
321)`,
322 description: "genrule applies properties from a genrule_defaults dependency if not specified",
323 },
324 {
325 moduleTypesUnderTest: map[string]android.ModuleFactory{
326 "genrule": genrule.GenRuleFactory,
327 "genrule_defaults": func() android.Module { return genrule.DefaultsFactory() },
328 },
329 bp2buildMutatorsUnderTest: map[string]bp2buildMutator{
330 "genrule": genrule.GenruleBp2Build,
331 },
332 bp: `genrule_defaults {
333 name: "gen_defaults",
334 out: ["out-from-defaults"],
335 srcs: ["in-from-defaults"],
336 cmd: "cmd-from-defaults",
337}
338genrule {
339 name: "gen",
340 out: ["out"],
341 srcs: ["in1"],
342 defaults: ["gen_defaults"],
343 cmd: "do-something $(in) $(out)",
344 bazel_module: { bp2build_available: true },
345}
346`,
347 expectedBazelTarget: `genrule(
348 name = "gen",
349 cmd = "do-something $(SRCS) $(OUTS)",
350 outs = [
351 "out-from-defaults",
352 "out",
353 ],
354 srcs = [
355 "in-from-defaults",
356 "in1",
357 ],
358)`,
359 description: "genrule does merges properties from a genrule_defaults dependency, latest-first",
360 },
361 {
362 moduleTypesUnderTest: map[string]android.ModuleFactory{
363 "genrule": genrule.GenRuleFactory,
364 "genrule_defaults": func() android.Module { return genrule.DefaultsFactory() },
365 },
366 bp2buildMutatorsUnderTest: map[string]bp2buildMutator{
367 "genrule": genrule.GenruleBp2Build,
368 },
369 bp: `genrule_defaults {
370 name: "gen_defaults1",
371 cmd: "cp $(in) $(out)",
372}
373
374genrule_defaults {
375 name: "gen_defaults2",
376 srcs: ["in1"],
377}
378
379genrule {
380 name: "gen",
381 out: ["out"],
382 defaults: ["gen_defaults1", "gen_defaults2"],
383 bazel_module: { bp2build_available: true },
384}
385`,
386 expectedBazelTarget: `genrule(
387 name = "gen",
388 cmd = "cp $(SRCS) $(OUTS)",
389 outs = ["out"],
390 srcs = ["in1"],
391)`,
392 description: "genrule applies properties from list of genrule_defaults",
393 },
394 {
395 moduleTypesUnderTest: map[string]android.ModuleFactory{
396 "genrule": genrule.GenRuleFactory,
397 "genrule_defaults": func() android.Module { return genrule.DefaultsFactory() },
398 },
399 bp2buildMutatorsUnderTest: map[string]bp2buildMutator{
400 "genrule": genrule.GenruleBp2Build,
401 },
402 bp: `genrule_defaults {
403 name: "gen_defaults1",
404 defaults: ["gen_defaults2"],
405 cmd: "cmd1 $(in) $(out)", // overrides gen_defaults2's cmd property value.
406}
407
408genrule_defaults {
409 name: "gen_defaults2",
410 defaults: ["gen_defaults3"],
411 cmd: "cmd2 $(in) $(out)",
412 out: ["out-from-2"],
413 srcs: ["in1"],
414}
415
416genrule_defaults {
417 name: "gen_defaults3",
418 out: ["out-from-3"],
419 srcs: ["srcs-from-3"],
420}
421
422genrule {
423 name: "gen",
424 out: ["out"],
425 defaults: ["gen_defaults1"],
426 bazel_module: { bp2build_available: true },
427}
428`,
429 expectedBazelTarget: `genrule(
430 name = "gen",
431 cmd = "cmd1 $(SRCS) $(OUTS)",
432 outs = [
433 "out-from-3",
434 "out-from-2",
435 "out",
436 ],
437 srcs = [
438 "srcs-from-3",
439 "in1",
440 ],
441)`,
442 description: "genrule applies properties from genrule_defaults transitively",
443 },
444 }
445
446 dir := "."
447 for _, testCase := range testCases {
448 config := android.TestConfig(buildDir, nil, testCase.bp, nil)
449 ctx := android.NewTestContext(config)
450 for m, factory := range testCase.moduleTypesUnderTest {
451 ctx.RegisterModuleType(m, factory)
452 }
453 for mutator, f := range testCase.bp2buildMutatorsUnderTest {
454 ctx.RegisterBp2BuildMutator(mutator, f)
455 }
456 ctx.RegisterForBazelConversion()
457
458 _, errs := ctx.ParseFileList(dir, []string{"Android.bp"})
459 android.FailIfErrored(t, errs)
460 _, errs = ctx.ResolveDependencies(config)
461 android.FailIfErrored(t, errs)
462
463 codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
464 bazelTargets := generateBazelTargetsForDir(codegenCtx, dir)
465 if actualCount := len(bazelTargets); actualCount != 1 {
466 t.Fatalf("%s: Expected 1 bazel target, got %d", testCase.description, actualCount)
467 }
468
469 actualBazelTarget := bazelTargets[0]
470 if actualBazelTarget.content != testCase.expectedBazelTarget {
471 t.Errorf(
472 "%s: Expected generated Bazel target to be '%s', got '%s'",
473 testCase.description,
474 testCase.expectedBazelTarget,
475 actualBazelTarget.content,
476 )
477 }
478 }
479}