blob: 029ba49385b9feb6997eb03e57841a630e0611d0 [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"
Sam Delmerico24c56032022-03-28 19:53:03 +000028 "android/soong/android/allowlists"
Jingwen Chen73850672020-12-14 08:25:34 -050029 "android/soong/bazel"
Liz Kammer2dd9ca42020-11-25 16:06:39 -080030)
31
Jingwen Chen91220d72021-03-24 02:18:33 -040032var (
33 // A default configuration for tests to not have to specify bp2build_available on top level targets.
Sam Delmerico24c56032022-03-28 19:53:03 +000034 bp2buildConfig = android.NewBp2BuildAllowlist().SetDefaultConfig(
35 allowlists.Bp2BuildConfig{
36 android.Bp2BuildTopLevel: allowlists.Bp2BuildDefaultTrueRecursively,
37 },
38 )
Rupert Shuttleworth06559d02021-05-19 09:14:26 -040039
40 buildDir string
Jingwen Chen91220d72021-03-24 02:18:33 -040041)
42
Jingwen Chen5146ac02021-09-02 11:44:42 +000043func 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 +000044 t.Helper()
Jingwen Chen5146ac02021-09-02 11:44:42 +000045
Jingwen Chen5146ac02021-09-02 11:44:42 +000046 if len(errs) != 1 {
Liz Kammer6eff3232021-08-26 08:37:59 -040047 return false
Jingwen Chen5146ac02021-09-02 11:44:42 +000048 }
Liz Kammer54309532021-12-14 12:21:22 -050049 if strings.Contains(errs[0].Error(), expectedErr.Error()) {
Jingwen Chen5146ac02021-09-02 11:44:42 +000050 return true
51 }
52
53 return false
54}
55
56func errored(t *testing.T, tc bp2buildTestCase, errs []error) bool {
57 t.Helper()
58 if tc.expectedErr != nil {
59 // Rely on checkErrors, as this test case is expected to have an error.
60 return false
61 }
62
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux1c92aef2021-08-23 16:10:00 +000063 if len(errs) > 0 {
64 for _, err := range errs {
Jingwen Chen5146ac02021-09-02 11:44:42 +000065 t.Errorf("%s: %s", tc.description, err)
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux1c92aef2021-08-23 16:10:00 +000066 }
67 return true
68 }
Jingwen Chen5146ac02021-09-02 11:44:42 +000069
70 // All good, continue execution.
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux1c92aef2021-08-23 16:10:00 +000071 return false
72}
73
Alex Márquez Pérez Muñíz Díaz Púras Thaureauxce0a07e2021-08-23 16:17:32 +000074func runBp2BuildTestCaseSimple(t *testing.T, tc bp2buildTestCase) {
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux1c92aef2021-08-23 16:10:00 +000075 t.Helper()
76 runBp2BuildTestCase(t, func(ctx android.RegistrationContext) {}, tc)
77}
78
79type bp2buildTestCase struct {
Liz Kammerbe46fcc2021-11-01 15:32:43 -040080 description string
81 moduleTypeUnderTest string
82 moduleTypeUnderTestFactory android.ModuleFactory
83 blueprint string
84 expectedBazelTargets []string
85 filesystem map[string]string
86 dir string
Trevor Radcliffe58ea4512022-04-07 20:36:39 +000087 // An error with a string contained within the string of the expected error
88 expectedErr error
89 unconvertedDepsMode unconvertedDepsMode
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux1c92aef2021-08-23 16:10:00 +000090}
91
92func runBp2BuildTestCase(t *testing.T, registerModuleTypes func(ctx android.RegistrationContext), tc bp2buildTestCase) {
93 t.Helper()
94 dir := "."
95 filesystem := make(map[string][]byte)
96 toParse := []string{
97 "Android.bp",
98 }
99 for f, content := range tc.filesystem {
100 if strings.HasSuffix(f, "Android.bp") {
101 toParse = append(toParse, f)
102 }
103 filesystem[f] = []byte(content)
104 }
105 config := android.TestConfig(buildDir, nil, tc.blueprint, filesystem)
106 ctx := android.NewTestContext(config)
107
108 registerModuleTypes(ctx)
109 ctx.RegisterModuleType(tc.moduleTypeUnderTest, tc.moduleTypeUnderTestFactory)
110 ctx.RegisterBp2BuildConfig(bp2buildConfig)
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux1c92aef2021-08-23 16:10:00 +0000111 ctx.RegisterForBazelConversion()
112
Jingwen Chen5146ac02021-09-02 11:44:42 +0000113 _, parseErrs := ctx.ParseFileList(dir, toParse)
114 if errored(t, tc, parseErrs) {
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux1c92aef2021-08-23 16:10:00 +0000115 return
116 }
Jingwen Chen5146ac02021-09-02 11:44:42 +0000117 _, resolveDepsErrs := ctx.ResolveDependencies(config)
118 if errored(t, tc, resolveDepsErrs) {
119 return
120 }
121
122 errs := append(parseErrs, resolveDepsErrs...)
123 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 +0000124 return
125 }
126
127 checkDir := dir
128 if tc.dir != "" {
129 checkDir = tc.dir
130 }
131 codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
Liz Kammer6eff3232021-08-26 08:37:59 -0400132 codegenCtx.unconvertedDepMode = tc.unconvertedDepsMode
133 bazelTargets, errs := generateBazelTargetsForDir(codegenCtx, checkDir)
Liz Kammer54309532021-12-14 12:21:22 -0500134 if tc.expectedErr != nil {
135 if checkError(t, errs, tc.expectedErr) {
136 return
137 } else {
138 t.Errorf("Expected error: %q, got: %q", tc.expectedErr, errs)
139 }
Liz Kammer6eff3232021-08-26 08:37:59 -0400140 } else {
141 android.FailIfErrored(t, errs)
142 }
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux1c92aef2021-08-23 16:10:00 +0000143 if actualCount, expectedCount := len(bazelTargets), len(tc.expectedBazelTargets); actualCount != expectedCount {
Liz Kammeraabfb5d2021-12-08 15:25:06 -0500144 t.Errorf("%s: Expected %d bazel target (%s), got `%d`` (%s)",
145 tc.description, expectedCount, tc.expectedBazelTargets, actualCount, bazelTargets)
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux1c92aef2021-08-23 16:10:00 +0000146 } else {
147 for i, target := range bazelTargets {
148 if w, g := tc.expectedBazelTargets[i], target.content; w != g {
149 t.Errorf(
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux447f6c92021-08-31 20:30:36 +0000150 "%s: Expected generated Bazel target to be `%s`, got `%s`",
151 tc.description, w, g)
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux1c92aef2021-08-23 16:10:00 +0000152 }
153 }
154 }
155}
156
Liz Kammer2dd9ca42020-11-25 16:06:39 -0800157type nestedProps struct {
Liz Kammer46fb7ab2021-12-01 10:09:34 -0500158 Nested_prop *string
Liz Kammer2dd9ca42020-11-25 16:06:39 -0800159}
160
Liz Kammer32a03392021-09-14 11:17:21 -0400161type EmbeddedProps struct {
Liz Kammer46fb7ab2021-12-01 10:09:34 -0500162 Embedded_prop *string
Liz Kammer32a03392021-09-14 11:17:21 -0400163}
164
165type OtherEmbeddedProps struct {
Liz Kammer46fb7ab2021-12-01 10:09:34 -0500166 Other_embedded_prop *string
Liz Kammer32a03392021-09-14 11:17:21 -0400167}
168
Liz Kammer2dd9ca42020-11-25 16:06:39 -0800169type customProps struct {
Liz Kammer32a03392021-09-14 11:17:21 -0400170 EmbeddedProps
171 *OtherEmbeddedProps
172
Liz Kammer2dd9ca42020-11-25 16:06:39 -0800173 Bool_prop bool
174 Bool_ptr_prop *bool
175 // Ensure that properties tagged `blueprint:mutated` are omitted
176 Int_prop int `blueprint:"mutated"`
177 Int64_ptr_prop *int64
178 String_prop string
179 String_ptr_prop *string
180 String_list_prop []string
181
182 Nested_props nestedProps
183 Nested_props_ptr *nestedProps
Liz Kammer4562a3b2021-04-21 18:15:34 -0400184
Liz Kammer32b77cf2021-08-04 15:17:02 -0400185 Arch_paths []string `android:"path,arch_variant"`
186 Arch_paths_exclude []string `android:"path,arch_variant"`
Liz Kammerbe46fcc2021-11-01 15:32:43 -0400187
188 // Prop used to indicate this conversion should be 1 module -> multiple targets
189 One_to_many_prop *bool
Liz Kammer2dd9ca42020-11-25 16:06:39 -0800190}
191
192type customModule struct {
193 android.ModuleBase
Liz Kammerea6666f2021-02-17 10:17:28 -0500194 android.BazelModuleBase
Liz Kammer2dd9ca42020-11-25 16:06:39 -0800195
196 props customProps
197}
198
199// OutputFiles is needed because some instances of this module use dist with a
200// tag property which requires the module implements OutputFileProducer.
201func (m *customModule) OutputFiles(tag string) (android.Paths, error) {
202 return android.PathsForTesting("path" + tag), nil
203}
204
205func (m *customModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
206 // nothing for now.
207}
208
209func customModuleFactoryBase() android.Module {
210 module := &customModule{}
211 module.AddProperties(&module.props)
Liz Kammerea6666f2021-02-17 10:17:28 -0500212 android.InitBazelModule(module)
Liz Kammer2dd9ca42020-11-25 16:06:39 -0800213 return module
214}
215
216func customModuleFactory() android.Module {
217 m := customModuleFactoryBase()
Liz Kammer4562a3b2021-04-21 18:15:34 -0400218 android.InitAndroidArchModule(m, android.HostAndDeviceSupported, android.MultilibBoth)
Liz Kammer2dd9ca42020-11-25 16:06:39 -0800219 return m
220}
221
222type testProps struct {
223 Test_prop struct {
224 Test_string_prop string
225 }
226}
227
228type customTestModule struct {
229 android.ModuleBase
230
231 props customProps
232 test_props testProps
233}
234
235func (m *customTestModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
236 // nothing for now.
237}
238
239func customTestModuleFactoryBase() android.Module {
240 m := &customTestModule{}
241 m.AddProperties(&m.props)
242 m.AddProperties(&m.test_props)
243 return m
244}
245
246func customTestModuleFactory() android.Module {
247 m := customTestModuleFactoryBase()
248 android.InitAndroidModule(m)
249 return m
250}
251
252type customDefaultsModule struct {
253 android.ModuleBase
254 android.DefaultsModuleBase
255}
256
257func customDefaultsModuleFactoryBase() android.DefaultsModule {
258 module := &customDefaultsModule{}
259 module.AddProperties(&customProps{})
260 return module
261}
262
263func customDefaultsModuleFactoryBasic() android.Module {
264 return customDefaultsModuleFactoryBase()
265}
266
267func customDefaultsModuleFactory() android.Module {
268 m := customDefaultsModuleFactoryBase()
269 android.InitDefaultsModule(m)
270 return m
271}
Jingwen Chen73850672020-12-14 08:25:34 -0500272
Liz Kammer32a03392021-09-14 11:17:21 -0400273type EmbeddedAttr struct {
Liz Kammer46fb7ab2021-12-01 10:09:34 -0500274 Embedded_attr *string
Liz Kammer32a03392021-09-14 11:17:21 -0400275}
276
277type OtherEmbeddedAttr struct {
Liz Kammer46fb7ab2021-12-01 10:09:34 -0500278 Other_embedded_attr *string
Liz Kammer32a03392021-09-14 11:17:21 -0400279}
280
Jingwen Chen73850672020-12-14 08:25:34 -0500281type customBazelModuleAttributes struct {
Liz Kammer32a03392021-09-14 11:17:21 -0400282 EmbeddedAttr
283 *OtherEmbeddedAttr
Liz Kammer46fb7ab2021-12-01 10:09:34 -0500284 String_ptr_prop *string
Jingwen Chen73850672020-12-14 08:25:34 -0500285 String_list_prop []string
Liz Kammer4562a3b2021-04-21 18:15:34 -0400286 Arch_paths bazel.LabelListAttribute
Jingwen Chen73850672020-12-14 08:25:34 -0500287}
288
Liz Kammerbe46fcc2021-11-01 15:32:43 -0400289func (m *customModule) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
290 paths := bazel.LabelListAttribute{}
Jingwen Chen77e8b7b2021-02-05 03:03:24 -0500291
Liz Kammerbe46fcc2021-11-01 15:32:43 -0400292 if p := m.props.One_to_many_prop; p != nil && *p {
293 customBp2buildOneToMany(ctx, m)
294 return
295 }
Liz Kammer4562a3b2021-04-21 18:15:34 -0400296
Liz Kammerbe46fcc2021-11-01 15:32:43 -0400297 for axis, configToProps := range m.GetArchVariantProperties(ctx, &customProps{}) {
298 for config, props := range configToProps {
299 if archProps, ok := props.(*customProps); ok && archProps.Arch_paths != nil {
300 paths.SetSelectValue(axis, config, android.BazelLabelForModuleSrcExcludes(ctx, archProps.Arch_paths, archProps.Arch_paths_exclude))
Liz Kammer4562a3b2021-04-21 18:15:34 -0400301 }
302 }
Jingwen Chen73850672020-12-14 08:25:34 -0500303 }
Liz Kammerbe46fcc2021-11-01 15:32:43 -0400304
305 paths.ResolveExcludes()
306
307 attrs := &customBazelModuleAttributes{
308 String_ptr_prop: m.props.String_ptr_prop,
309 String_list_prop: m.props.String_list_prop,
310 Arch_paths: paths,
311 }
312 attrs.Embedded_attr = m.props.Embedded_prop
313 if m.props.OtherEmbeddedProps != nil {
314 attrs.OtherEmbeddedAttr = &OtherEmbeddedAttr{Other_embedded_attr: m.props.OtherEmbeddedProps.Other_embedded_prop}
315 }
316
317 props := bazel.BazelTargetModuleProperties{
318 Rule_class: "custom",
319 }
320
321 ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: m.Name()}, attrs)
Jingwen Chen73850672020-12-14 08:25:34 -0500322}
Jingwen Chen40067de2021-01-26 21:58:43 -0500323
324// A bp2build mutator that uses load statements and creates a 1:M mapping from
325// module to target.
Liz Kammerbe46fcc2021-11-01 15:32:43 -0400326func customBp2buildOneToMany(ctx android.TopDownMutatorContext, m *customModule) {
Jingwen Chen77e8b7b2021-02-05 03:03:24 -0500327
Liz Kammerbe46fcc2021-11-01 15:32:43 -0400328 baseName := m.Name()
329 attrs := &customBazelModuleAttributes{}
Jingwen Chen1fd14692021-02-05 03:01:50 -0500330
Liz Kammerbe46fcc2021-11-01 15:32:43 -0400331 myLibraryProps := bazel.BazelTargetModuleProperties{
332 Rule_class: "my_library",
333 Bzl_load_location: "//build/bazel/rules:rules.bzl",
Jingwen Chen40067de2021-01-26 21:58:43 -0500334 }
Liz Kammerbe46fcc2021-11-01 15:32:43 -0400335 ctx.CreateBazelTargetModule(myLibraryProps, android.CommonAttributes{Name: baseName}, attrs)
336
337 protoLibraryProps := bazel.BazelTargetModuleProperties{
338 Rule_class: "proto_library",
339 Bzl_load_location: "//build/bazel/rules:proto.bzl",
340 }
341 ctx.CreateBazelTargetModule(protoLibraryProps, android.CommonAttributes{Name: baseName + "_proto_library_deps"}, attrs)
342
343 myProtoLibraryProps := bazel.BazelTargetModuleProperties{
344 Rule_class: "my_proto_library",
345 Bzl_load_location: "//build/bazel/rules:proto.bzl",
346 }
347 ctx.CreateBazelTargetModule(myProtoLibraryProps, android.CommonAttributes{Name: baseName + "_my_proto_library_deps"}, attrs)
Jingwen Chen40067de2021-01-26 21:58:43 -0500348}
Jingwen Chenba369ad2021-02-22 10:19:34 -0500349
350// Helper method for tests to easily access the targets in a dir.
Liz Kammer6eff3232021-08-26 08:37:59 -0400351func generateBazelTargetsForDir(codegenCtx *CodegenContext, dir string) (BazelTargets, []error) {
Rupert Shuttleworth2a4fc3e2021-04-21 07:10:09 -0400352 // TODO: Set generateFilegroups to true and/or remove the generateFilegroups argument completely
Liz Kammer6eff3232021-08-26 08:37:59 -0400353 res, err := GenerateBazelTargets(codegenCtx, false)
354 return res.buildFileToTargets[dir], err
Jingwen Chenba369ad2021-02-22 10:19:34 -0500355}
Liz Kammer32b77cf2021-08-04 15:17:02 -0400356
357func registerCustomModuleForBp2buildConversion(ctx *android.TestContext) {
358 ctx.RegisterModuleType("custom", customModuleFactory)
Liz Kammer32b77cf2021-08-04 15:17:02 -0400359 ctx.RegisterForBazelConversion()
360}
Liz Kammer7a210ac2021-09-22 15:52:58 -0400361
362func simpleModuleDoNotConvertBp2build(typ, name string) string {
363 return fmt.Sprintf(`
364%s {
365 name: "%s",
366 bazel_module: { bp2build_available: false },
367}`, typ, name)
368}
Liz Kammer78cfdaa2021-11-08 12:56:31 -0500369
370type attrNameToString map[string]string
371
372func makeBazelTarget(typ, name string, attrs attrNameToString) string {
373 attrStrings := make([]string, 0, len(attrs)+1)
374 attrStrings = append(attrStrings, fmt.Sprintf(` name = "%s",`, name))
375 for _, k := range android.SortedStringKeys(attrs) {
376 attrStrings = append(attrStrings, fmt.Sprintf(" %s = %s,", k, attrs[k]))
377 }
378 return fmt.Sprintf(`%s(
379%s
380)`, typ, strings.Join(attrStrings, "\n"))
381}