blob: daa9c22dbf9c381af355ce4170de71e82eaaeace [file] [log] [blame]
Alex Márquez Pérez Muñíz Díaz Púras Thaureauxf5a3eac2021-08-23 17:05:17 +00001// 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
Liz Kammer2dd9ca42020-11-25 16:06:39 -080015package bp2build
16
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux0da7ce62021-08-23 17:04:20 +000017/*
18For shareable/common bp2build testing functionality and dumping ground for
19specific-but-shared functionality among tests in package
20*/
21
Liz Kammer2dd9ca42020-11-25 16:06:39 -080022import (
Liz Kammer7a210ac2021-09-22 15:52:58 -040023 "fmt"
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux1c92aef2021-08-23 16:10:00 +000024 "strings"
Rupert Shuttleworth06559d02021-05-19 09:14:26 -040025 "testing"
26
Liz Kammer2dd9ca42020-11-25 16:06:39 -080027 "android/soong/android"
Jingwen Chen73850672020-12-14 08:25:34 -050028 "android/soong/bazel"
Liz Kammer2dd9ca42020-11-25 16:06:39 -080029)
30
Jingwen Chen91220d72021-03-24 02:18:33 -040031var (
32 // A default configuration for tests to not have to specify bp2build_available on top level targets.
33 bp2buildConfig = android.Bp2BuildConfig{
34 android.BP2BUILD_TOPLEVEL: android.Bp2BuildDefaultTrueRecursively,
35 }
Rupert Shuttleworth06559d02021-05-19 09:14:26 -040036
37 buildDir string
Jingwen Chen91220d72021-03-24 02:18:33 -040038)
39
Jingwen Chen5146ac02021-09-02 11:44:42 +000040func checkError(t *testing.T, errs []error, expectedErr error) bool {
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux1c92aef2021-08-23 16:10:00 +000041 t.Helper()
Jingwen Chen5146ac02021-09-02 11:44:42 +000042
Jingwen Chen5146ac02021-09-02 11:44:42 +000043 if len(errs) != 1 {
Liz Kammer6eff3232021-08-26 08:37:59 -040044 return false
Jingwen Chen5146ac02021-09-02 11:44:42 +000045 }
46 if errs[0].Error() == expectedErr.Error() {
47 return true
48 }
49
50 return false
51}
52
53func errored(t *testing.T, tc bp2buildTestCase, errs []error) bool {
54 t.Helper()
55 if tc.expectedErr != nil {
56 // Rely on checkErrors, as this test case is expected to have an error.
57 return false
58 }
59
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux1c92aef2021-08-23 16:10:00 +000060 if len(errs) > 0 {
61 for _, err := range errs {
Jingwen Chen5146ac02021-09-02 11:44:42 +000062 t.Errorf("%s: %s", tc.description, err)
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux1c92aef2021-08-23 16:10:00 +000063 }
64 return true
65 }
Jingwen Chen5146ac02021-09-02 11:44:42 +000066
67 // All good, continue execution.
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux1c92aef2021-08-23 16:10:00 +000068 return false
69}
70
Alex Márquez Pérez Muñíz Díaz Púras Thaureauxce0a07e2021-08-23 16:17:32 +000071func runBp2BuildTestCaseSimple(t *testing.T, tc bp2buildTestCase) {
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux1c92aef2021-08-23 16:10:00 +000072 t.Helper()
73 runBp2BuildTestCase(t, func(ctx android.RegistrationContext) {}, tc)
74}
75
76type bp2buildTestCase struct {
77 description string
78 moduleTypeUnderTest string
79 moduleTypeUnderTestFactory android.ModuleFactory
80 moduleTypeUnderTestBp2BuildMutator func(android.TopDownMutatorContext)
81 blueprint string
82 expectedBazelTargets []string
83 filesystem map[string]string
84 dir string
Jingwen Chen5146ac02021-09-02 11:44:42 +000085 expectedErr error
Liz Kammer6eff3232021-08-26 08:37:59 -040086 unconvertedDepsMode unconvertedDepsMode
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux1c92aef2021-08-23 16:10:00 +000087}
88
89func runBp2BuildTestCase(t *testing.T, registerModuleTypes func(ctx android.RegistrationContext), tc bp2buildTestCase) {
90 t.Helper()
91 dir := "."
92 filesystem := make(map[string][]byte)
93 toParse := []string{
94 "Android.bp",
95 }
96 for f, content := range tc.filesystem {
97 if strings.HasSuffix(f, "Android.bp") {
98 toParse = append(toParse, f)
99 }
100 filesystem[f] = []byte(content)
101 }
102 config := android.TestConfig(buildDir, nil, tc.blueprint, filesystem)
103 ctx := android.NewTestContext(config)
104
105 registerModuleTypes(ctx)
106 ctx.RegisterModuleType(tc.moduleTypeUnderTest, tc.moduleTypeUnderTestFactory)
107 ctx.RegisterBp2BuildConfig(bp2buildConfig)
108 ctx.RegisterBp2BuildMutator(tc.moduleTypeUnderTest, tc.moduleTypeUnderTestBp2BuildMutator)
109 ctx.RegisterForBazelConversion()
110
Jingwen Chen5146ac02021-09-02 11:44:42 +0000111 _, parseErrs := ctx.ParseFileList(dir, toParse)
112 if errored(t, tc, parseErrs) {
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux1c92aef2021-08-23 16:10:00 +0000113 return
114 }
Jingwen Chen5146ac02021-09-02 11:44:42 +0000115 _, resolveDepsErrs := ctx.ResolveDependencies(config)
116 if errored(t, tc, resolveDepsErrs) {
117 return
118 }
119
120 errs := append(parseErrs, resolveDepsErrs...)
121 if tc.expectedErr != nil && checkError(t, errs, tc.expectedErr) {
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux1c92aef2021-08-23 16:10:00 +0000122 return
123 }
124
125 checkDir := dir
126 if tc.dir != "" {
127 checkDir = tc.dir
128 }
129 codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
Liz Kammer6eff3232021-08-26 08:37:59 -0400130 codegenCtx.unconvertedDepMode = tc.unconvertedDepsMode
131 bazelTargets, errs := generateBazelTargetsForDir(codegenCtx, checkDir)
132 if tc.expectedErr != nil && checkError(t, errs, tc.expectedErr) {
133 return
134 } else {
135 android.FailIfErrored(t, errs)
136 }
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux1c92aef2021-08-23 16:10:00 +0000137 if actualCount, expectedCount := len(bazelTargets), len(tc.expectedBazelTargets); actualCount != expectedCount {
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux447f6c92021-08-31 20:30:36 +0000138 t.Errorf("%s: Expected %d bazel target, got `%d``",
139 tc.description, expectedCount, actualCount)
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux1c92aef2021-08-23 16:10:00 +0000140 } else {
141 for i, target := range bazelTargets {
142 if w, g := tc.expectedBazelTargets[i], target.content; w != g {
143 t.Errorf(
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux447f6c92021-08-31 20:30:36 +0000144 "%s: Expected generated Bazel target to be `%s`, got `%s`",
145 tc.description, w, g)
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux1c92aef2021-08-23 16:10:00 +0000146 }
147 }
148 }
149}
150
Liz Kammer2dd9ca42020-11-25 16:06:39 -0800151type nestedProps struct {
152 Nested_prop string
153}
154
Liz Kammer32a03392021-09-14 11:17:21 -0400155type EmbeddedProps struct {
156 Embedded_prop string
157}
158
159type OtherEmbeddedProps struct {
160 Other_embedded_prop string
161}
162
Liz Kammer2dd9ca42020-11-25 16:06:39 -0800163type customProps struct {
Liz Kammer32a03392021-09-14 11:17:21 -0400164 EmbeddedProps
165 *OtherEmbeddedProps
166
Liz Kammer2dd9ca42020-11-25 16:06:39 -0800167 Bool_prop bool
168 Bool_ptr_prop *bool
169 // Ensure that properties tagged `blueprint:mutated` are omitted
170 Int_prop int `blueprint:"mutated"`
171 Int64_ptr_prop *int64
172 String_prop string
173 String_ptr_prop *string
174 String_list_prop []string
175
176 Nested_props nestedProps
177 Nested_props_ptr *nestedProps
Liz Kammer4562a3b2021-04-21 18:15:34 -0400178
Liz Kammer32b77cf2021-08-04 15:17:02 -0400179 Arch_paths []string `android:"path,arch_variant"`
180 Arch_paths_exclude []string `android:"path,arch_variant"`
Liz Kammer2dd9ca42020-11-25 16:06:39 -0800181}
182
183type customModule struct {
184 android.ModuleBase
Liz Kammerea6666f2021-02-17 10:17:28 -0500185 android.BazelModuleBase
Liz Kammer2dd9ca42020-11-25 16:06:39 -0800186
187 props customProps
188}
189
190// OutputFiles is needed because some instances of this module use dist with a
191// tag property which requires the module implements OutputFileProducer.
192func (m *customModule) OutputFiles(tag string) (android.Paths, error) {
193 return android.PathsForTesting("path" + tag), nil
194}
195
196func (m *customModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
197 // nothing for now.
198}
199
200func customModuleFactoryBase() android.Module {
201 module := &customModule{}
202 module.AddProperties(&module.props)
Liz Kammerea6666f2021-02-17 10:17:28 -0500203 android.InitBazelModule(module)
Liz Kammer2dd9ca42020-11-25 16:06:39 -0800204 return module
205}
206
207func customModuleFactory() android.Module {
208 m := customModuleFactoryBase()
Liz Kammer4562a3b2021-04-21 18:15:34 -0400209 android.InitAndroidArchModule(m, android.HostAndDeviceSupported, android.MultilibBoth)
Liz Kammer2dd9ca42020-11-25 16:06:39 -0800210 return m
211}
212
213type testProps struct {
214 Test_prop struct {
215 Test_string_prop string
216 }
217}
218
219type customTestModule struct {
220 android.ModuleBase
221
222 props customProps
223 test_props testProps
224}
225
226func (m *customTestModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
227 // nothing for now.
228}
229
230func customTestModuleFactoryBase() android.Module {
231 m := &customTestModule{}
232 m.AddProperties(&m.props)
233 m.AddProperties(&m.test_props)
234 return m
235}
236
237func customTestModuleFactory() android.Module {
238 m := customTestModuleFactoryBase()
239 android.InitAndroidModule(m)
240 return m
241}
242
243type customDefaultsModule struct {
244 android.ModuleBase
245 android.DefaultsModuleBase
246}
247
248func customDefaultsModuleFactoryBase() android.DefaultsModule {
249 module := &customDefaultsModule{}
250 module.AddProperties(&customProps{})
251 return module
252}
253
254func customDefaultsModuleFactoryBasic() android.Module {
255 return customDefaultsModuleFactoryBase()
256}
257
258func customDefaultsModuleFactory() android.Module {
259 m := customDefaultsModuleFactoryBase()
260 android.InitDefaultsModule(m)
261 return m
262}
Jingwen Chen73850672020-12-14 08:25:34 -0500263
Liz Kammer32a03392021-09-14 11:17:21 -0400264type EmbeddedAttr struct {
265 Embedded_attr string
266}
267
268type OtherEmbeddedAttr struct {
269 Other_embedded_attr string
270}
271
Jingwen Chen73850672020-12-14 08:25:34 -0500272type customBazelModuleAttributes struct {
Liz Kammer32a03392021-09-14 11:17:21 -0400273 EmbeddedAttr
274 *OtherEmbeddedAttr
Jingwen Chen73850672020-12-14 08:25:34 -0500275 String_prop string
276 String_list_prop []string
Liz Kammer4562a3b2021-04-21 18:15:34 -0400277 Arch_paths bazel.LabelListAttribute
Jingwen Chen73850672020-12-14 08:25:34 -0500278}
279
Jingwen Chen73850672020-12-14 08:25:34 -0500280func customBp2BuildMutator(ctx android.TopDownMutatorContext) {
281 if m, ok := ctx.Module().(*customModule); ok {
Jingwen Chen12b4c272021-03-10 02:05:59 -0500282 if !m.ConvertWithBp2build(ctx) {
Jingwen Chen77e8b7b2021-02-05 03:03:24 -0500283 return
284 }
285
Liz Kammerfdd72e62021-10-11 15:41:03 -0400286 paths := bazel.LabelListAttribute{}
Liz Kammer4562a3b2021-04-21 18:15:34 -0400287
Liz Kammer9abd62d2021-05-21 08:37:59 -0400288 for axis, configToProps := range m.GetArchVariantProperties(ctx, &customProps{}) {
289 for config, props := range configToProps {
290 if archProps, ok := props.(*customProps); ok && archProps.Arch_paths != nil {
Liz Kammer32b77cf2021-08-04 15:17:02 -0400291 paths.SetSelectValue(axis, config, android.BazelLabelForModuleSrcExcludes(ctx, archProps.Arch_paths, archProps.Arch_paths_exclude))
Liz Kammer9abd62d2021-05-21 08:37:59 -0400292 }
Liz Kammer4562a3b2021-04-21 18:15:34 -0400293 }
294 }
295
Liz Kammer32b77cf2021-08-04 15:17:02 -0400296 paths.ResolveExcludes()
297
Jingwen Chen1fd14692021-02-05 03:01:50 -0500298 attrs := &customBazelModuleAttributes{
Jingwen Chen73850672020-12-14 08:25:34 -0500299 String_prop: m.props.String_prop,
300 String_list_prop: m.props.String_list_prop,
Liz Kammer4562a3b2021-04-21 18:15:34 -0400301 Arch_paths: paths,
Jingwen Chen1fd14692021-02-05 03:01:50 -0500302 }
Liz Kammer32a03392021-09-14 11:17:21 -0400303 attrs.Embedded_attr = m.props.Embedded_prop
304 if m.props.OtherEmbeddedProps != nil {
305 attrs.OtherEmbeddedAttr = &OtherEmbeddedAttr{Other_embedded_attr: m.props.OtherEmbeddedProps.Other_embedded_prop}
306 }
Jingwen Chen1fd14692021-02-05 03:01:50 -0500307
Liz Kammerfc46bc12021-02-19 11:06:17 -0500308 props := bazel.BazelTargetModuleProperties{
309 Rule_class: "custom",
310 }
Jingwen Chen1fd14692021-02-05 03:01:50 -0500311
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux447f6c92021-08-31 20:30:36 +0000312 ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: m.Name()}, attrs)
Jingwen Chen73850672020-12-14 08:25:34 -0500313 }
314}
Jingwen Chen40067de2021-01-26 21:58:43 -0500315
316// A bp2build mutator that uses load statements and creates a 1:M mapping from
317// module to target.
318func customBp2BuildMutatorFromStarlark(ctx android.TopDownMutatorContext) {
319 if m, ok := ctx.Module().(*customModule); ok {
Jingwen Chen12b4c272021-03-10 02:05:59 -0500320 if !m.ConvertWithBp2build(ctx) {
Jingwen Chen77e8b7b2021-02-05 03:03:24 -0500321 return
322 }
323
Jingwen Chen1fd14692021-02-05 03:01:50 -0500324 baseName := m.Name()
325 attrs := &customBazelModuleAttributes{}
326
Liz Kammerfc46bc12021-02-19 11:06:17 -0500327 myLibraryProps := bazel.BazelTargetModuleProperties{
328 Rule_class: "my_library",
329 Bzl_load_location: "//build/bazel/rules:rules.bzl",
330 }
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux447f6c92021-08-31 20:30:36 +0000331 ctx.CreateBazelTargetModule(myLibraryProps, android.CommonAttributes{Name: baseName}, attrs)
Jingwen Chen1fd14692021-02-05 03:01:50 -0500332
Liz Kammerfc46bc12021-02-19 11:06:17 -0500333 protoLibraryProps := bazel.BazelTargetModuleProperties{
334 Rule_class: "proto_library",
335 Bzl_load_location: "//build/bazel/rules:proto.bzl",
336 }
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux447f6c92021-08-31 20:30:36 +0000337 ctx.CreateBazelTargetModule(protoLibraryProps, android.CommonAttributes{Name: baseName + "_proto_library_deps"}, attrs)
Jingwen Chen1fd14692021-02-05 03:01:50 -0500338
Liz Kammerfc46bc12021-02-19 11:06:17 -0500339 myProtoLibraryProps := bazel.BazelTargetModuleProperties{
340 Rule_class: "my_proto_library",
341 Bzl_load_location: "//build/bazel/rules:proto.bzl",
342 }
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux447f6c92021-08-31 20:30:36 +0000343 ctx.CreateBazelTargetModule(myProtoLibraryProps, android.CommonAttributes{Name: baseName + "_my_proto_library_deps"}, attrs)
Jingwen Chen40067de2021-01-26 21:58:43 -0500344 }
345}
Jingwen Chenba369ad2021-02-22 10:19:34 -0500346
347// Helper method for tests to easily access the targets in a dir.
Liz Kammer6eff3232021-08-26 08:37:59 -0400348func generateBazelTargetsForDir(codegenCtx *CodegenContext, dir string) (BazelTargets, []error) {
Rupert Shuttleworth2a4fc3e2021-04-21 07:10:09 -0400349 // TODO: Set generateFilegroups to true and/or remove the generateFilegroups argument completely
Liz Kammer6eff3232021-08-26 08:37:59 -0400350 res, err := GenerateBazelTargets(codegenCtx, false)
351 return res.buildFileToTargets[dir], err
Jingwen Chenba369ad2021-02-22 10:19:34 -0500352}
Liz Kammer32b77cf2021-08-04 15:17:02 -0400353
354func registerCustomModuleForBp2buildConversion(ctx *android.TestContext) {
355 ctx.RegisterModuleType("custom", customModuleFactory)
356 ctx.RegisterBp2BuildMutator("custom", customBp2BuildMutator)
357 ctx.RegisterForBazelConversion()
358}
Liz Kammer7a210ac2021-09-22 15:52:58 -0400359
360func simpleModuleDoNotConvertBp2build(typ, name string) string {
361 return fmt.Sprintf(`
362%s {
363 name: "%s",
364 bazel_module: { bp2build_available: false },
365}`, typ, name)
366}
Liz Kammer78cfdaa2021-11-08 12:56:31 -0500367
368type attrNameToString map[string]string
369
370func makeBazelTarget(typ, name string, attrs attrNameToString) string {
371 attrStrings := make([]string, 0, len(attrs)+1)
372 attrStrings = append(attrStrings, fmt.Sprintf(` name = "%s",`, name))
373 for _, k := range android.SortedStringKeys(attrs) {
374 attrStrings = append(attrStrings, fmt.Sprintf(" %s = %s,", k, attrs[k]))
375 }
376 return fmt.Sprintf(`%s(
377%s
378)`, typ, strings.Join(attrStrings, "\n"))
379}