blob: 74084b1007918e3d5f8e981cefed736e48ef74b0 [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 (
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux1c92aef2021-08-23 16:10:00 +000023 "strings"
Rupert Shuttleworth06559d02021-05-19 09:14:26 -040024 "testing"
25
Liz Kammer2dd9ca42020-11-25 16:06:39 -080026 "android/soong/android"
Jingwen Chen73850672020-12-14 08:25:34 -050027 "android/soong/bazel"
Liz Kammer2dd9ca42020-11-25 16:06:39 -080028)
29
Jingwen Chen91220d72021-03-24 02:18:33 -040030var (
31 // A default configuration for tests to not have to specify bp2build_available on top level targets.
32 bp2buildConfig = android.Bp2BuildConfig{
33 android.BP2BUILD_TOPLEVEL: android.Bp2BuildDefaultTrueRecursively,
34 }
Rupert Shuttleworth06559d02021-05-19 09:14:26 -040035
36 buildDir string
Jingwen Chen91220d72021-03-24 02:18:33 -040037)
38
Jingwen Chen5146ac02021-09-02 11:44:42 +000039func 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 +000040 t.Helper()
Jingwen Chen5146ac02021-09-02 11:44:42 +000041
Jingwen Chen5146ac02021-09-02 11:44:42 +000042 if len(errs) != 1 {
Liz Kammer6eff3232021-08-26 08:37:59 -040043 return false
Jingwen Chen5146ac02021-09-02 11:44:42 +000044 }
45 if errs[0].Error() == expectedErr.Error() {
46 return true
47 }
48
49 return false
50}
51
52func errored(t *testing.T, tc bp2buildTestCase, errs []error) bool {
53 t.Helper()
54 if tc.expectedErr != nil {
55 // Rely on checkErrors, as this test case is expected to have an error.
56 return false
57 }
58
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux1c92aef2021-08-23 16:10:00 +000059 if len(errs) > 0 {
60 for _, err := range errs {
Jingwen Chen5146ac02021-09-02 11:44:42 +000061 t.Errorf("%s: %s", tc.description, err)
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux1c92aef2021-08-23 16:10:00 +000062 }
63 return true
64 }
Jingwen Chen5146ac02021-09-02 11:44:42 +000065
66 // All good, continue execution.
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux1c92aef2021-08-23 16:10:00 +000067 return false
68}
69
Alex Márquez Pérez Muñíz Díaz Púras Thaureauxce0a07e2021-08-23 16:17:32 +000070func runBp2BuildTestCaseSimple(t *testing.T, tc bp2buildTestCase) {
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux1c92aef2021-08-23 16:10:00 +000071 t.Helper()
72 runBp2BuildTestCase(t, func(ctx android.RegistrationContext) {}, tc)
73}
74
75type bp2buildTestCase struct {
76 description string
77 moduleTypeUnderTest string
78 moduleTypeUnderTestFactory android.ModuleFactory
79 moduleTypeUnderTestBp2BuildMutator func(android.TopDownMutatorContext)
80 blueprint string
81 expectedBazelTargets []string
82 filesystem map[string]string
83 dir string
Jingwen Chen5146ac02021-09-02 11:44:42 +000084 expectedErr error
Liz Kammer6eff3232021-08-26 08:37:59 -040085 unconvertedDepsMode unconvertedDepsMode
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux1c92aef2021-08-23 16:10:00 +000086}
87
88func runBp2BuildTestCase(t *testing.T, registerModuleTypes func(ctx android.RegistrationContext), tc bp2buildTestCase) {
89 t.Helper()
90 dir := "."
91 filesystem := make(map[string][]byte)
92 toParse := []string{
93 "Android.bp",
94 }
95 for f, content := range tc.filesystem {
96 if strings.HasSuffix(f, "Android.bp") {
97 toParse = append(toParse, f)
98 }
99 filesystem[f] = []byte(content)
100 }
101 config := android.TestConfig(buildDir, nil, tc.blueprint, filesystem)
102 ctx := android.NewTestContext(config)
103
104 registerModuleTypes(ctx)
105 ctx.RegisterModuleType(tc.moduleTypeUnderTest, tc.moduleTypeUnderTestFactory)
106 ctx.RegisterBp2BuildConfig(bp2buildConfig)
107 ctx.RegisterBp2BuildMutator(tc.moduleTypeUnderTest, tc.moduleTypeUnderTestBp2BuildMutator)
108 ctx.RegisterForBazelConversion()
109
Jingwen Chen5146ac02021-09-02 11:44:42 +0000110 _, parseErrs := ctx.ParseFileList(dir, toParse)
111 if errored(t, tc, parseErrs) {
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux1c92aef2021-08-23 16:10:00 +0000112 return
113 }
Jingwen Chen5146ac02021-09-02 11:44:42 +0000114 _, resolveDepsErrs := ctx.ResolveDependencies(config)
115 if errored(t, tc, resolveDepsErrs) {
116 return
117 }
118
119 errs := append(parseErrs, resolveDepsErrs...)
120 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 +0000121 return
122 }
123
124 checkDir := dir
125 if tc.dir != "" {
126 checkDir = tc.dir
127 }
128 codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
Liz Kammer6eff3232021-08-26 08:37:59 -0400129 codegenCtx.unconvertedDepMode = tc.unconvertedDepsMode
130 bazelTargets, errs := generateBazelTargetsForDir(codegenCtx, checkDir)
131 if tc.expectedErr != nil && checkError(t, errs, tc.expectedErr) {
132 return
133 } else {
134 android.FailIfErrored(t, errs)
135 }
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux1c92aef2021-08-23 16:10:00 +0000136 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 +0000137 t.Errorf("%s: Expected %d bazel target, got %d; %v",
138 tc.description, expectedCount, actualCount, bazelTargets)
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux1c92aef2021-08-23 16:10:00 +0000139 } else {
140 for i, target := range bazelTargets {
141 if w, g := tc.expectedBazelTargets[i], target.content; w != g {
142 t.Errorf(
143 "%s: Expected generated Bazel target to be '%s', got '%s'",
144 tc.description,
145 w,
146 g,
147 )
148 }
149 }
150 }
151}
152
Liz Kammer2dd9ca42020-11-25 16:06:39 -0800153type nestedProps struct {
154 Nested_prop string
155}
156
Liz Kammer32a03392021-09-14 11:17:21 -0400157type EmbeddedProps struct {
158 Embedded_prop string
159}
160
161type OtherEmbeddedProps struct {
162 Other_embedded_prop string
163}
164
Liz Kammer2dd9ca42020-11-25 16:06:39 -0800165type customProps struct {
Liz Kammer32a03392021-09-14 11:17:21 -0400166 EmbeddedProps
167 *OtherEmbeddedProps
168
Liz Kammer2dd9ca42020-11-25 16:06:39 -0800169 Bool_prop bool
170 Bool_ptr_prop *bool
171 // Ensure that properties tagged `blueprint:mutated` are omitted
172 Int_prop int `blueprint:"mutated"`
173 Int64_ptr_prop *int64
174 String_prop string
175 String_ptr_prop *string
176 String_list_prop []string
177
178 Nested_props nestedProps
179 Nested_props_ptr *nestedProps
Liz Kammer4562a3b2021-04-21 18:15:34 -0400180
Liz Kammer32b77cf2021-08-04 15:17:02 -0400181 Arch_paths []string `android:"path,arch_variant"`
182 Arch_paths_exclude []string `android:"path,arch_variant"`
Liz Kammer2dd9ca42020-11-25 16:06:39 -0800183}
184
185type customModule struct {
186 android.ModuleBase
Liz Kammerea6666f2021-02-17 10:17:28 -0500187 android.BazelModuleBase
Liz Kammer2dd9ca42020-11-25 16:06:39 -0800188
189 props customProps
190}
191
192// OutputFiles is needed because some instances of this module use dist with a
193// tag property which requires the module implements OutputFileProducer.
194func (m *customModule) OutputFiles(tag string) (android.Paths, error) {
195 return android.PathsForTesting("path" + tag), nil
196}
197
198func (m *customModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
199 // nothing for now.
200}
201
202func customModuleFactoryBase() android.Module {
203 module := &customModule{}
204 module.AddProperties(&module.props)
Liz Kammerea6666f2021-02-17 10:17:28 -0500205 android.InitBazelModule(module)
Liz Kammer2dd9ca42020-11-25 16:06:39 -0800206 return module
207}
208
209func customModuleFactory() android.Module {
210 m := customModuleFactoryBase()
Liz Kammer4562a3b2021-04-21 18:15:34 -0400211 android.InitAndroidArchModule(m, android.HostAndDeviceSupported, android.MultilibBoth)
Liz Kammer2dd9ca42020-11-25 16:06:39 -0800212 return m
213}
214
215type testProps struct {
216 Test_prop struct {
217 Test_string_prop string
218 }
219}
220
221type customTestModule struct {
222 android.ModuleBase
223
224 props customProps
225 test_props testProps
226}
227
228func (m *customTestModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
229 // nothing for now.
230}
231
232func customTestModuleFactoryBase() android.Module {
233 m := &customTestModule{}
234 m.AddProperties(&m.props)
235 m.AddProperties(&m.test_props)
236 return m
237}
238
239func customTestModuleFactory() android.Module {
240 m := customTestModuleFactoryBase()
241 android.InitAndroidModule(m)
242 return m
243}
244
245type customDefaultsModule struct {
246 android.ModuleBase
247 android.DefaultsModuleBase
248}
249
250func customDefaultsModuleFactoryBase() android.DefaultsModule {
251 module := &customDefaultsModule{}
252 module.AddProperties(&customProps{})
253 return module
254}
255
256func customDefaultsModuleFactoryBasic() android.Module {
257 return customDefaultsModuleFactoryBase()
258}
259
260func customDefaultsModuleFactory() android.Module {
261 m := customDefaultsModuleFactoryBase()
262 android.InitDefaultsModule(m)
263 return m
264}
Jingwen Chen73850672020-12-14 08:25:34 -0500265
Liz Kammer32a03392021-09-14 11:17:21 -0400266type EmbeddedAttr struct {
267 Embedded_attr string
268}
269
270type OtherEmbeddedAttr struct {
271 Other_embedded_attr string
272}
273
Jingwen Chen73850672020-12-14 08:25:34 -0500274type customBazelModuleAttributes struct {
Liz Kammer32a03392021-09-14 11:17:21 -0400275 EmbeddedAttr
276 *OtherEmbeddedAttr
Jingwen Chen73850672020-12-14 08:25:34 -0500277 String_prop string
278 String_list_prop []string
Liz Kammer4562a3b2021-04-21 18:15:34 -0400279 Arch_paths bazel.LabelListAttribute
Jingwen Chen73850672020-12-14 08:25:34 -0500280}
281
Jingwen Chen73850672020-12-14 08:25:34 -0500282func customBp2BuildMutator(ctx android.TopDownMutatorContext) {
283 if m, ok := ctx.Module().(*customModule); ok {
Jingwen Chen12b4c272021-03-10 02:05:59 -0500284 if !m.ConvertWithBp2build(ctx) {
Jingwen Chen77e8b7b2021-02-05 03:03:24 -0500285 return
286 }
287
Liz Kammer32b77cf2021-08-04 15:17:02 -0400288 paths := bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrcExcludes(ctx, m.props.Arch_paths, m.props.Arch_paths_exclude))
Liz Kammer4562a3b2021-04-21 18:15:34 -0400289
Liz Kammer9abd62d2021-05-21 08:37:59 -0400290 for axis, configToProps := range m.GetArchVariantProperties(ctx, &customProps{}) {
291 for config, props := range configToProps {
292 if archProps, ok := props.(*customProps); ok && archProps.Arch_paths != nil {
Liz Kammer32b77cf2021-08-04 15:17:02 -0400293 paths.SetSelectValue(axis, config, android.BazelLabelForModuleSrcExcludes(ctx, archProps.Arch_paths, archProps.Arch_paths_exclude))
Liz Kammer9abd62d2021-05-21 08:37:59 -0400294 }
Liz Kammer4562a3b2021-04-21 18:15:34 -0400295 }
296 }
297
Liz Kammer32b77cf2021-08-04 15:17:02 -0400298 paths.ResolveExcludes()
299
Jingwen Chen1fd14692021-02-05 03:01:50 -0500300 attrs := &customBazelModuleAttributes{
Jingwen Chen73850672020-12-14 08:25:34 -0500301 String_prop: m.props.String_prop,
302 String_list_prop: m.props.String_list_prop,
Liz Kammer4562a3b2021-04-21 18:15:34 -0400303 Arch_paths: paths,
Jingwen Chen1fd14692021-02-05 03:01:50 -0500304 }
Liz Kammer32a03392021-09-14 11:17:21 -0400305 attrs.Embedded_attr = m.props.Embedded_prop
306 if m.props.OtherEmbeddedProps != nil {
307 attrs.OtherEmbeddedAttr = &OtherEmbeddedAttr{Other_embedded_attr: m.props.OtherEmbeddedProps.Other_embedded_prop}
308 }
Jingwen Chen1fd14692021-02-05 03:01:50 -0500309
Liz Kammerfc46bc12021-02-19 11:06:17 -0500310 props := bazel.BazelTargetModuleProperties{
311 Rule_class: "custom",
312 }
Jingwen Chen1fd14692021-02-05 03:01:50 -0500313
Liz Kammer2ada09a2021-08-11 00:17:36 -0400314 ctx.CreateBazelTargetModule(m.Name(), props, attrs)
Jingwen Chen73850672020-12-14 08:25:34 -0500315 }
316}
Jingwen Chen40067de2021-01-26 21:58:43 -0500317
318// A bp2build mutator that uses load statements and creates a 1:M mapping from
319// module to target.
320func customBp2BuildMutatorFromStarlark(ctx android.TopDownMutatorContext) {
321 if m, ok := ctx.Module().(*customModule); ok {
Jingwen Chen12b4c272021-03-10 02:05:59 -0500322 if !m.ConvertWithBp2build(ctx) {
Jingwen Chen77e8b7b2021-02-05 03:03:24 -0500323 return
324 }
325
Jingwen Chen1fd14692021-02-05 03:01:50 -0500326 baseName := m.Name()
327 attrs := &customBazelModuleAttributes{}
328
Liz Kammerfc46bc12021-02-19 11:06:17 -0500329 myLibraryProps := bazel.BazelTargetModuleProperties{
330 Rule_class: "my_library",
331 Bzl_load_location: "//build/bazel/rules:rules.bzl",
332 }
Liz Kammer2ada09a2021-08-11 00:17:36 -0400333 ctx.CreateBazelTargetModule(baseName, myLibraryProps, attrs)
Jingwen Chen1fd14692021-02-05 03:01:50 -0500334
Liz Kammerfc46bc12021-02-19 11:06:17 -0500335 protoLibraryProps := bazel.BazelTargetModuleProperties{
336 Rule_class: "proto_library",
337 Bzl_load_location: "//build/bazel/rules:proto.bzl",
338 }
Liz Kammer2ada09a2021-08-11 00:17:36 -0400339 ctx.CreateBazelTargetModule(baseName+"_proto_library_deps", protoLibraryProps, attrs)
Jingwen Chen1fd14692021-02-05 03:01:50 -0500340
Liz Kammerfc46bc12021-02-19 11:06:17 -0500341 myProtoLibraryProps := bazel.BazelTargetModuleProperties{
342 Rule_class: "my_proto_library",
343 Bzl_load_location: "//build/bazel/rules:proto.bzl",
344 }
Liz Kammer2ada09a2021-08-11 00:17:36 -0400345 ctx.CreateBazelTargetModule(baseName+"_my_proto_library_deps", myProtoLibraryProps, attrs)
Jingwen Chen40067de2021-01-26 21:58:43 -0500346 }
347}
Jingwen Chenba369ad2021-02-22 10:19:34 -0500348
349// Helper method for tests to easily access the targets in a dir.
Liz Kammer6eff3232021-08-26 08:37:59 -0400350func generateBazelTargetsForDir(codegenCtx *CodegenContext, dir string) (BazelTargets, []error) {
Rupert Shuttleworth2a4fc3e2021-04-21 07:10:09 -0400351 // TODO: Set generateFilegroups to true and/or remove the generateFilegroups argument completely
Liz Kammer6eff3232021-08-26 08:37:59 -0400352 res, err := GenerateBazelTargets(codegenCtx, false)
353 return res.buildFileToTargets[dir], err
Jingwen Chenba369ad2021-02-22 10:19:34 -0500354}
Liz Kammer32b77cf2021-08-04 15:17:02 -0400355
356func registerCustomModuleForBp2buildConversion(ctx *android.TestContext) {
357 ctx.RegisterModuleType("custom", customModuleFactory)
358 ctx.RegisterBp2BuildMutator("custom", customBp2BuildMutator)
359 ctx.RegisterForBazelConversion()
360}