blob: 1e7e53c9fa646e823e9b6fdd4c5c8b9e3f3fac2d [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 Thaureaux560cb662021-08-26 20:13:29 +0000138 t.Errorf("%s: Expected %d bazel target, got %d; %v",
139 tc.description, expectedCount, actualCount, bazelTargets)
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(
144 "%s: Expected generated Bazel target to be '%s', got '%s'",
145 tc.description,
146 w,
147 g,
148 )
149 }
150 }
151 }
152}
153
Liz Kammer2dd9ca42020-11-25 16:06:39 -0800154type nestedProps struct {
155 Nested_prop string
156}
157
Liz Kammer32a03392021-09-14 11:17:21 -0400158type EmbeddedProps struct {
159 Embedded_prop string
160}
161
162type OtherEmbeddedProps struct {
163 Other_embedded_prop string
164}
165
Liz Kammer2dd9ca42020-11-25 16:06:39 -0800166type customProps struct {
Liz Kammer32a03392021-09-14 11:17:21 -0400167 EmbeddedProps
168 *OtherEmbeddedProps
169
Liz Kammer2dd9ca42020-11-25 16:06:39 -0800170 Bool_prop bool
171 Bool_ptr_prop *bool
172 // Ensure that properties tagged `blueprint:mutated` are omitted
173 Int_prop int `blueprint:"mutated"`
174 Int64_ptr_prop *int64
175 String_prop string
176 String_ptr_prop *string
177 String_list_prop []string
178
179 Nested_props nestedProps
180 Nested_props_ptr *nestedProps
Liz Kammer4562a3b2021-04-21 18:15:34 -0400181
Liz Kammer32b77cf2021-08-04 15:17:02 -0400182 Arch_paths []string `android:"path,arch_variant"`
183 Arch_paths_exclude []string `android:"path,arch_variant"`
Liz Kammer2dd9ca42020-11-25 16:06:39 -0800184}
185
186type customModule struct {
187 android.ModuleBase
Liz Kammerea6666f2021-02-17 10:17:28 -0500188 android.BazelModuleBase
Liz Kammer2dd9ca42020-11-25 16:06:39 -0800189
190 props customProps
191}
192
193// OutputFiles is needed because some instances of this module use dist with a
194// tag property which requires the module implements OutputFileProducer.
195func (m *customModule) OutputFiles(tag string) (android.Paths, error) {
196 return android.PathsForTesting("path" + tag), nil
197}
198
199func (m *customModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
200 // nothing for now.
201}
202
203func customModuleFactoryBase() android.Module {
204 module := &customModule{}
205 module.AddProperties(&module.props)
Liz Kammerea6666f2021-02-17 10:17:28 -0500206 android.InitBazelModule(module)
Liz Kammer2dd9ca42020-11-25 16:06:39 -0800207 return module
208}
209
210func customModuleFactory() android.Module {
211 m := customModuleFactoryBase()
Liz Kammer4562a3b2021-04-21 18:15:34 -0400212 android.InitAndroidArchModule(m, android.HostAndDeviceSupported, android.MultilibBoth)
Liz Kammer2dd9ca42020-11-25 16:06:39 -0800213 return m
214}
215
216type testProps struct {
217 Test_prop struct {
218 Test_string_prop string
219 }
220}
221
222type customTestModule struct {
223 android.ModuleBase
224
225 props customProps
226 test_props testProps
227}
228
229func (m *customTestModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
230 // nothing for now.
231}
232
233func customTestModuleFactoryBase() android.Module {
234 m := &customTestModule{}
235 m.AddProperties(&m.props)
236 m.AddProperties(&m.test_props)
237 return m
238}
239
240func customTestModuleFactory() android.Module {
241 m := customTestModuleFactoryBase()
242 android.InitAndroidModule(m)
243 return m
244}
245
246type customDefaultsModule struct {
247 android.ModuleBase
248 android.DefaultsModuleBase
249}
250
251func customDefaultsModuleFactoryBase() android.DefaultsModule {
252 module := &customDefaultsModule{}
253 module.AddProperties(&customProps{})
254 return module
255}
256
257func customDefaultsModuleFactoryBasic() android.Module {
258 return customDefaultsModuleFactoryBase()
259}
260
261func customDefaultsModuleFactory() android.Module {
262 m := customDefaultsModuleFactoryBase()
263 android.InitDefaultsModule(m)
264 return m
265}
Jingwen Chen73850672020-12-14 08:25:34 -0500266
Liz Kammer32a03392021-09-14 11:17:21 -0400267type EmbeddedAttr struct {
268 Embedded_attr string
269}
270
271type OtherEmbeddedAttr struct {
272 Other_embedded_attr string
273}
274
Jingwen Chen73850672020-12-14 08:25:34 -0500275type customBazelModuleAttributes struct {
Liz Kammer32a03392021-09-14 11:17:21 -0400276 EmbeddedAttr
277 *OtherEmbeddedAttr
Jingwen Chen73850672020-12-14 08:25:34 -0500278 String_prop string
279 String_list_prop []string
Liz Kammer4562a3b2021-04-21 18:15:34 -0400280 Arch_paths bazel.LabelListAttribute
Jingwen Chen73850672020-12-14 08:25:34 -0500281}
282
Jingwen Chen73850672020-12-14 08:25:34 -0500283func customBp2BuildMutator(ctx android.TopDownMutatorContext) {
284 if m, ok := ctx.Module().(*customModule); ok {
Jingwen Chen12b4c272021-03-10 02:05:59 -0500285 if !m.ConvertWithBp2build(ctx) {
Jingwen Chen77e8b7b2021-02-05 03:03:24 -0500286 return
287 }
288
Liz Kammer32b77cf2021-08-04 15:17:02 -0400289 paths := bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrcExcludes(ctx, m.props.Arch_paths, m.props.Arch_paths_exclude))
Liz Kammer4562a3b2021-04-21 18:15:34 -0400290
Liz Kammer9abd62d2021-05-21 08:37:59 -0400291 for axis, configToProps := range m.GetArchVariantProperties(ctx, &customProps{}) {
292 for config, props := range configToProps {
293 if archProps, ok := props.(*customProps); ok && archProps.Arch_paths != nil {
Liz Kammer32b77cf2021-08-04 15:17:02 -0400294 paths.SetSelectValue(axis, config, android.BazelLabelForModuleSrcExcludes(ctx, archProps.Arch_paths, archProps.Arch_paths_exclude))
Liz Kammer9abd62d2021-05-21 08:37:59 -0400295 }
Liz Kammer4562a3b2021-04-21 18:15:34 -0400296 }
297 }
298
Liz Kammer32b77cf2021-08-04 15:17:02 -0400299 paths.ResolveExcludes()
300
Jingwen Chen1fd14692021-02-05 03:01:50 -0500301 attrs := &customBazelModuleAttributes{
Jingwen Chen73850672020-12-14 08:25:34 -0500302 String_prop: m.props.String_prop,
303 String_list_prop: m.props.String_list_prop,
Liz Kammer4562a3b2021-04-21 18:15:34 -0400304 Arch_paths: paths,
Jingwen Chen1fd14692021-02-05 03:01:50 -0500305 }
Liz Kammer32a03392021-09-14 11:17:21 -0400306 attrs.Embedded_attr = m.props.Embedded_prop
307 if m.props.OtherEmbeddedProps != nil {
308 attrs.OtherEmbeddedAttr = &OtherEmbeddedAttr{Other_embedded_attr: m.props.OtherEmbeddedProps.Other_embedded_prop}
309 }
Jingwen Chen1fd14692021-02-05 03:01:50 -0500310
Liz Kammerfc46bc12021-02-19 11:06:17 -0500311 props := bazel.BazelTargetModuleProperties{
312 Rule_class: "custom",
313 }
Jingwen Chen1fd14692021-02-05 03:01:50 -0500314
Liz Kammer2ada09a2021-08-11 00:17:36 -0400315 ctx.CreateBazelTargetModule(m.Name(), props, attrs)
Jingwen Chen73850672020-12-14 08:25:34 -0500316 }
317}
Jingwen Chen40067de2021-01-26 21:58:43 -0500318
319// A bp2build mutator that uses load statements and creates a 1:M mapping from
320// module to target.
321func customBp2BuildMutatorFromStarlark(ctx android.TopDownMutatorContext) {
322 if m, ok := ctx.Module().(*customModule); ok {
Jingwen Chen12b4c272021-03-10 02:05:59 -0500323 if !m.ConvertWithBp2build(ctx) {
Jingwen Chen77e8b7b2021-02-05 03:03:24 -0500324 return
325 }
326
Jingwen Chen1fd14692021-02-05 03:01:50 -0500327 baseName := m.Name()
328 attrs := &customBazelModuleAttributes{}
329
Liz Kammerfc46bc12021-02-19 11:06:17 -0500330 myLibraryProps := bazel.BazelTargetModuleProperties{
331 Rule_class: "my_library",
332 Bzl_load_location: "//build/bazel/rules:rules.bzl",
333 }
Liz Kammer2ada09a2021-08-11 00:17:36 -0400334 ctx.CreateBazelTargetModule(baseName, myLibraryProps, attrs)
Jingwen Chen1fd14692021-02-05 03:01:50 -0500335
Liz Kammerfc46bc12021-02-19 11:06:17 -0500336 protoLibraryProps := bazel.BazelTargetModuleProperties{
337 Rule_class: "proto_library",
338 Bzl_load_location: "//build/bazel/rules:proto.bzl",
339 }
Liz Kammer2ada09a2021-08-11 00:17:36 -0400340 ctx.CreateBazelTargetModule(baseName+"_proto_library_deps", protoLibraryProps, attrs)
Jingwen Chen1fd14692021-02-05 03:01:50 -0500341
Liz Kammerfc46bc12021-02-19 11:06:17 -0500342 myProtoLibraryProps := bazel.BazelTargetModuleProperties{
343 Rule_class: "my_proto_library",
344 Bzl_load_location: "//build/bazel/rules:proto.bzl",
345 }
Liz Kammer2ada09a2021-08-11 00:17:36 -0400346 ctx.CreateBazelTargetModule(baseName+"_my_proto_library_deps", myProtoLibraryProps, attrs)
Jingwen Chen40067de2021-01-26 21:58:43 -0500347 }
348}
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)
359 ctx.RegisterBp2BuildMutator("custom", customBp2BuildMutator)
360 ctx.RegisterForBazelConversion()
361}
Liz Kammer7a210ac2021-09-22 15:52:58 -0400362
363func simpleModuleDoNotConvertBp2build(typ, name string) string {
364 return fmt.Sprintf(`
365%s {
366 name: "%s",
367 bazel_module: { bp2build_available: false },
368}`, typ, name)
369}