blob: ba328e941a92396cc7bb6f3df0f6f2b6119cc6cf [file] [log] [blame]
Liz Kammer2dd9ca42020-11-25 16:06:39 -08001package bp2build
2
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux0da7ce62021-08-23 17:04:20 +00003/*
4For shareable/common bp2build testing functionality and dumping ground for
5specific-but-shared functionality among tests in package
6*/
7
Liz Kammer2dd9ca42020-11-25 16:06:39 -08008import (
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux1c92aef2021-08-23 16:10:00 +00009 "strings"
Rupert Shuttleworth06559d02021-05-19 09:14:26 -040010 "testing"
11
Liz Kammer2dd9ca42020-11-25 16:06:39 -080012 "android/soong/android"
Jingwen Chen73850672020-12-14 08:25:34 -050013 "android/soong/bazel"
Liz Kammer2dd9ca42020-11-25 16:06:39 -080014)
15
Jingwen Chen91220d72021-03-24 02:18:33 -040016var (
17 // A default configuration for tests to not have to specify bp2build_available on top level targets.
18 bp2buildConfig = android.Bp2BuildConfig{
19 android.BP2BUILD_TOPLEVEL: android.Bp2BuildDefaultTrueRecursively,
20 }
Rupert Shuttleworth06559d02021-05-19 09:14:26 -040021
22 buildDir string
Jingwen Chen91220d72021-03-24 02:18:33 -040023)
24
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux1c92aef2021-08-23 16:10:00 +000025func errored(t *testing.T, desc string, errs []error) bool {
26 t.Helper()
27 if len(errs) > 0 {
28 for _, err := range errs {
29 t.Errorf("%s: %s", desc, err)
30 }
31 return true
32 }
33 return false
34}
35
Alex Márquez Pérez Muñíz Díaz Púras Thaureauxce0a07e2021-08-23 16:17:32 +000036func runBp2BuildTestCaseSimple(t *testing.T, tc bp2buildTestCase) {
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux1c92aef2021-08-23 16:10:00 +000037 t.Helper()
38 runBp2BuildTestCase(t, func(ctx android.RegistrationContext) {}, tc)
39}
40
41type bp2buildTestCase struct {
42 description string
43 moduleTypeUnderTest string
44 moduleTypeUnderTestFactory android.ModuleFactory
45 moduleTypeUnderTestBp2BuildMutator func(android.TopDownMutatorContext)
46 blueprint string
47 expectedBazelTargets []string
48 filesystem map[string]string
49 dir string
50}
51
52func runBp2BuildTestCase(t *testing.T, registerModuleTypes func(ctx android.RegistrationContext), tc bp2buildTestCase) {
53 t.Helper()
54 dir := "."
55 filesystem := make(map[string][]byte)
56 toParse := []string{
57 "Android.bp",
58 }
59 for f, content := range tc.filesystem {
60 if strings.HasSuffix(f, "Android.bp") {
61 toParse = append(toParse, f)
62 }
63 filesystem[f] = []byte(content)
64 }
65 config := android.TestConfig(buildDir, nil, tc.blueprint, filesystem)
66 ctx := android.NewTestContext(config)
67
68 registerModuleTypes(ctx)
69 ctx.RegisterModuleType(tc.moduleTypeUnderTest, tc.moduleTypeUnderTestFactory)
70 ctx.RegisterBp2BuildConfig(bp2buildConfig)
71 ctx.RegisterBp2BuildMutator(tc.moduleTypeUnderTest, tc.moduleTypeUnderTestBp2BuildMutator)
72 ctx.RegisterForBazelConversion()
73
74 _, errs := ctx.ParseFileList(dir, toParse)
75 if errored(t, tc.description, errs) {
76 return
77 }
78 _, errs = ctx.ResolveDependencies(config)
79 if errored(t, tc.description, errs) {
80 return
81 }
82
83 checkDir := dir
84 if tc.dir != "" {
85 checkDir = tc.dir
86 }
87 codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
88 bazelTargets := generateBazelTargetsForDir(codegenCtx, checkDir)
89 if actualCount, expectedCount := len(bazelTargets), len(tc.expectedBazelTargets); actualCount != expectedCount {
90 t.Errorf("%s: Expected %d bazel target, got %d", tc.description, expectedCount, actualCount)
91 } else {
92 for i, target := range bazelTargets {
93 if w, g := tc.expectedBazelTargets[i], target.content; w != g {
94 t.Errorf(
95 "%s: Expected generated Bazel target to be '%s', got '%s'",
96 tc.description,
97 w,
98 g,
99 )
100 }
101 }
102 }
103}
104
Liz Kammer2dd9ca42020-11-25 16:06:39 -0800105type nestedProps struct {
106 Nested_prop string
107}
108
109type customProps struct {
110 Bool_prop bool
111 Bool_ptr_prop *bool
112 // Ensure that properties tagged `blueprint:mutated` are omitted
113 Int_prop int `blueprint:"mutated"`
114 Int64_ptr_prop *int64
115 String_prop string
116 String_ptr_prop *string
117 String_list_prop []string
118
119 Nested_props nestedProps
120 Nested_props_ptr *nestedProps
Liz Kammer4562a3b2021-04-21 18:15:34 -0400121
Liz Kammer32b77cf2021-08-04 15:17:02 -0400122 Arch_paths []string `android:"path,arch_variant"`
123 Arch_paths_exclude []string `android:"path,arch_variant"`
Liz Kammer2dd9ca42020-11-25 16:06:39 -0800124}
125
126type customModule struct {
127 android.ModuleBase
Liz Kammerea6666f2021-02-17 10:17:28 -0500128 android.BazelModuleBase
Liz Kammer2dd9ca42020-11-25 16:06:39 -0800129
130 props customProps
131}
132
133// OutputFiles is needed because some instances of this module use dist with a
134// tag property which requires the module implements OutputFileProducer.
135func (m *customModule) OutputFiles(tag string) (android.Paths, error) {
136 return android.PathsForTesting("path" + tag), nil
137}
138
139func (m *customModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
140 // nothing for now.
141}
142
143func customModuleFactoryBase() android.Module {
144 module := &customModule{}
145 module.AddProperties(&module.props)
Liz Kammerea6666f2021-02-17 10:17:28 -0500146 android.InitBazelModule(module)
Liz Kammer2dd9ca42020-11-25 16:06:39 -0800147 return module
148}
149
150func customModuleFactory() android.Module {
151 m := customModuleFactoryBase()
Liz Kammer4562a3b2021-04-21 18:15:34 -0400152 android.InitAndroidArchModule(m, android.HostAndDeviceSupported, android.MultilibBoth)
Liz Kammer2dd9ca42020-11-25 16:06:39 -0800153 return m
154}
155
156type testProps struct {
157 Test_prop struct {
158 Test_string_prop string
159 }
160}
161
162type customTestModule struct {
163 android.ModuleBase
164
165 props customProps
166 test_props testProps
167}
168
169func (m *customTestModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
170 // nothing for now.
171}
172
173func customTestModuleFactoryBase() android.Module {
174 m := &customTestModule{}
175 m.AddProperties(&m.props)
176 m.AddProperties(&m.test_props)
177 return m
178}
179
180func customTestModuleFactory() android.Module {
181 m := customTestModuleFactoryBase()
182 android.InitAndroidModule(m)
183 return m
184}
185
186type customDefaultsModule struct {
187 android.ModuleBase
188 android.DefaultsModuleBase
189}
190
191func customDefaultsModuleFactoryBase() android.DefaultsModule {
192 module := &customDefaultsModule{}
193 module.AddProperties(&customProps{})
194 return module
195}
196
197func customDefaultsModuleFactoryBasic() android.Module {
198 return customDefaultsModuleFactoryBase()
199}
200
201func customDefaultsModuleFactory() android.Module {
202 m := customDefaultsModuleFactoryBase()
203 android.InitDefaultsModule(m)
204 return m
205}
Jingwen Chen73850672020-12-14 08:25:34 -0500206
207type customBazelModuleAttributes struct {
Jingwen Chen73850672020-12-14 08:25:34 -0500208 String_prop string
209 String_list_prop []string
Liz Kammer4562a3b2021-04-21 18:15:34 -0400210 Arch_paths bazel.LabelListAttribute
Jingwen Chen73850672020-12-14 08:25:34 -0500211}
212
213type customBazelModule struct {
214 android.BazelTargetModuleBase
215 customBazelModuleAttributes
216}
217
Jingwen Chen73850672020-12-14 08:25:34 -0500218func customBp2BuildMutator(ctx android.TopDownMutatorContext) {
219 if m, ok := ctx.Module().(*customModule); ok {
Jingwen Chen12b4c272021-03-10 02:05:59 -0500220 if !m.ConvertWithBp2build(ctx) {
Jingwen Chen77e8b7b2021-02-05 03:03:24 -0500221 return
222 }
223
Liz Kammer32b77cf2021-08-04 15:17:02 -0400224 paths := bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrcExcludes(ctx, m.props.Arch_paths, m.props.Arch_paths_exclude))
Liz Kammer4562a3b2021-04-21 18:15:34 -0400225
Liz Kammer9abd62d2021-05-21 08:37:59 -0400226 for axis, configToProps := range m.GetArchVariantProperties(ctx, &customProps{}) {
227 for config, props := range configToProps {
228 if archProps, ok := props.(*customProps); ok && archProps.Arch_paths != nil {
Liz Kammer32b77cf2021-08-04 15:17:02 -0400229 paths.SetSelectValue(axis, config, android.BazelLabelForModuleSrcExcludes(ctx, archProps.Arch_paths, archProps.Arch_paths_exclude))
Liz Kammer9abd62d2021-05-21 08:37:59 -0400230 }
Liz Kammer4562a3b2021-04-21 18:15:34 -0400231 }
232 }
233
Liz Kammer32b77cf2021-08-04 15:17:02 -0400234 paths.ResolveExcludes()
235
Jingwen Chen1fd14692021-02-05 03:01:50 -0500236 attrs := &customBazelModuleAttributes{
Jingwen Chen73850672020-12-14 08:25:34 -0500237 String_prop: m.props.String_prop,
238 String_list_prop: m.props.String_list_prop,
Liz Kammer4562a3b2021-04-21 18:15:34 -0400239 Arch_paths: paths,
Jingwen Chen1fd14692021-02-05 03:01:50 -0500240 }
241
Liz Kammerfc46bc12021-02-19 11:06:17 -0500242 props := bazel.BazelTargetModuleProperties{
243 Rule_class: "custom",
244 }
Jingwen Chen1fd14692021-02-05 03:01:50 -0500245
Liz Kammer2ada09a2021-08-11 00:17:36 -0400246 ctx.CreateBazelTargetModule(m.Name(), props, attrs)
Jingwen Chen73850672020-12-14 08:25:34 -0500247 }
248}
Jingwen Chen40067de2021-01-26 21:58:43 -0500249
250// A bp2build mutator that uses load statements and creates a 1:M mapping from
251// module to target.
252func customBp2BuildMutatorFromStarlark(ctx android.TopDownMutatorContext) {
253 if m, ok := ctx.Module().(*customModule); ok {
Jingwen Chen12b4c272021-03-10 02:05:59 -0500254 if !m.ConvertWithBp2build(ctx) {
Jingwen Chen77e8b7b2021-02-05 03:03:24 -0500255 return
256 }
257
Jingwen Chen1fd14692021-02-05 03:01:50 -0500258 baseName := m.Name()
259 attrs := &customBazelModuleAttributes{}
260
Liz Kammerfc46bc12021-02-19 11:06:17 -0500261 myLibraryProps := bazel.BazelTargetModuleProperties{
262 Rule_class: "my_library",
263 Bzl_load_location: "//build/bazel/rules:rules.bzl",
264 }
Liz Kammer2ada09a2021-08-11 00:17:36 -0400265 ctx.CreateBazelTargetModule(baseName, myLibraryProps, attrs)
Jingwen Chen1fd14692021-02-05 03:01:50 -0500266
Liz Kammerfc46bc12021-02-19 11:06:17 -0500267 protoLibraryProps := bazel.BazelTargetModuleProperties{
268 Rule_class: "proto_library",
269 Bzl_load_location: "//build/bazel/rules:proto.bzl",
270 }
Liz Kammer2ada09a2021-08-11 00:17:36 -0400271 ctx.CreateBazelTargetModule(baseName+"_proto_library_deps", protoLibraryProps, attrs)
Jingwen Chen1fd14692021-02-05 03:01:50 -0500272
Liz Kammerfc46bc12021-02-19 11:06:17 -0500273 myProtoLibraryProps := bazel.BazelTargetModuleProperties{
274 Rule_class: "my_proto_library",
275 Bzl_load_location: "//build/bazel/rules:proto.bzl",
276 }
Liz Kammer2ada09a2021-08-11 00:17:36 -0400277 ctx.CreateBazelTargetModule(baseName+"_my_proto_library_deps", myProtoLibraryProps, attrs)
Jingwen Chen40067de2021-01-26 21:58:43 -0500278 }
279}
Jingwen Chenba369ad2021-02-22 10:19:34 -0500280
281// Helper method for tests to easily access the targets in a dir.
Liz Kammerba3ea162021-02-17 13:22:03 -0500282func generateBazelTargetsForDir(codegenCtx *CodegenContext, dir string) BazelTargets {
Rupert Shuttleworth2a4fc3e2021-04-21 07:10:09 -0400283 // TODO: Set generateFilegroups to true and/or remove the generateFilegroups argument completely
Jingwen Chenc63677b2021-06-17 05:43:19 +0000284 buildFileToTargets, _, _ := GenerateBazelTargets(codegenCtx, false)
Jingwen Chenba369ad2021-02-22 10:19:34 -0500285 return buildFileToTargets[dir]
286}
Liz Kammer32b77cf2021-08-04 15:17:02 -0400287
288func registerCustomModuleForBp2buildConversion(ctx *android.TestContext) {
289 ctx.RegisterModuleType("custom", customModuleFactory)
290 ctx.RegisterBp2BuildMutator("custom", customBp2BuildMutator)
291 ctx.RegisterForBazelConversion()
292}