xref: /aosp_15_r20/build/soong/android/mutator_test.go (revision 333d2b3687b3a337dbcca9d65000bca186795e39)
1// Copyright 2015 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
15package android
16
17import (
18	"fmt"
19	"strings"
20	"sync"
21	"sync/atomic"
22	"testing"
23
24	"github.com/google/blueprint"
25)
26
27type mutatorTestModule struct {
28	ModuleBase
29	props struct {
30		Deps_missing_deps    []string
31		Mutator_missing_deps []string
32	}
33
34	missingDeps []string
35}
36
37func mutatorTestModuleFactory() Module {
38	module := &mutatorTestModule{}
39	module.AddProperties(&module.props)
40	InitAndroidModule(module)
41	return module
42}
43
44func (m *mutatorTestModule) GenerateAndroidBuildActions(ctx ModuleContext) {
45	ctx.Build(pctx, BuildParams{
46		Rule:   Touch,
47		Output: PathForModuleOut(ctx, "output"),
48	})
49
50	m.missingDeps = ctx.GetMissingDependencies()
51}
52
53func (m *mutatorTestModule) DepsMutator(ctx BottomUpMutatorContext) {
54	ctx.AddDependency(ctx.Module(), nil, m.props.Deps_missing_deps...)
55}
56
57func addMissingDependenciesMutator(ctx TopDownMutatorContext) {
58	ctx.AddMissingDependencies(ctx.Module().(*mutatorTestModule).props.Mutator_missing_deps)
59}
60
61func TestMutatorAddMissingDependencies(t *testing.T) {
62	bp := `
63		test {
64			name: "foo",
65			deps_missing_deps: ["regular_missing_dep"],
66			mutator_missing_deps: ["added_missing_dep"],
67		}
68	`
69
70	result := GroupFixturePreparers(
71		PrepareForTestWithAllowMissingDependencies,
72		FixtureRegisterWithContext(func(ctx RegistrationContext) {
73			ctx.RegisterModuleType("test", mutatorTestModuleFactory)
74			ctx.PreDepsMutators(func(ctx RegisterMutatorsContext) {
75				ctx.TopDown("add_missing_dependencies", addMissingDependenciesMutator)
76			})
77		}),
78		FixtureWithRootAndroidBp(bp),
79	).RunTest(t)
80
81	foo := result.ModuleForTests("foo", "").Module().(*mutatorTestModule)
82
83	AssertDeepEquals(t, "foo missing deps", []string{"added_missing_dep", "regular_missing_dep"}, foo.missingDeps)
84}
85
86type testTransitionMutator struct {
87	split              func(ctx BaseModuleContext) []string
88	outgoingTransition func(ctx OutgoingTransitionContext, sourceVariation string) string
89	incomingTransition func(ctx IncomingTransitionContext, incomingVariation string) string
90	mutate             func(ctx BottomUpMutatorContext, variation string)
91}
92
93func (t *testTransitionMutator) Split(ctx BaseModuleContext) []string {
94	if t.split != nil {
95		return t.split(ctx)
96	}
97	return []string{""}
98}
99
100func (t *testTransitionMutator) OutgoingTransition(ctx OutgoingTransitionContext, sourceVariation string) string {
101	if t.outgoingTransition != nil {
102		return t.outgoingTransition(ctx, sourceVariation)
103	}
104	return sourceVariation
105}
106
107func (t *testTransitionMutator) IncomingTransition(ctx IncomingTransitionContext, incomingVariation string) string {
108	if t.incomingTransition != nil {
109		return t.incomingTransition(ctx, incomingVariation)
110	}
111	return incomingVariation
112}
113
114func (t *testTransitionMutator) Mutate(ctx BottomUpMutatorContext, variation string) {
115	if t.mutate != nil {
116		t.mutate(ctx, variation)
117	}
118}
119
120func TestModuleString(t *testing.T) {
121	bp := `
122		test {
123			name: "foo",
124		}
125	`
126
127	var moduleStrings []string
128
129	GroupFixturePreparers(
130		FixtureRegisterWithContext(func(ctx RegistrationContext) {
131
132			ctx.PreArchMutators(func(ctx RegisterMutatorsContext) {
133				ctx.Transition("pre_arch", &testTransitionMutator{
134					split: func(ctx BaseModuleContext) []string {
135						moduleStrings = append(moduleStrings, ctx.Module().String())
136						return []string{"a", "b"}
137					},
138				})
139			})
140
141			ctx.PreDepsMutators(func(ctx RegisterMutatorsContext) {
142				ctx.Transition("pre_deps", &testTransitionMutator{
143					split: func(ctx BaseModuleContext) []string {
144						moduleStrings = append(moduleStrings, ctx.Module().String())
145						return []string{"c", "d"}
146					},
147				})
148			})
149
150			ctx.PostDepsMutators(func(ctx RegisterMutatorsContext) {
151				ctx.Transition("post_deps", &testTransitionMutator{
152					split: func(ctx BaseModuleContext) []string {
153						moduleStrings = append(moduleStrings, ctx.Module().String())
154						return []string{"e", "f"}
155					},
156					outgoingTransition: func(ctx OutgoingTransitionContext, sourceVariation string) string {
157						return ""
158					},
159				})
160				ctx.BottomUp("rename_bottom_up", func(ctx BottomUpMutatorContext) {
161					moduleStrings = append(moduleStrings, ctx.Module().String())
162					ctx.Rename(ctx.Module().base().Name() + "_renamed1")
163				}).UsesRename()
164				ctx.BottomUp("final", func(ctx BottomUpMutatorContext) {
165					moduleStrings = append(moduleStrings, ctx.Module().String())
166				})
167			})
168
169			ctx.RegisterModuleType("test", mutatorTestModuleFactory)
170		}),
171		FixtureWithRootAndroidBp(bp),
172	).RunTest(t)
173
174	want := []string{
175		// Initial name.
176		"foo{}",
177
178		// After pre_arch (reversed because rename_top_down is TopDown so it visits in reverse order).
179		"foo{pre_arch:b}",
180		"foo{pre_arch:a}",
181
182		// After pre_deps (reversed because post_deps TransitionMutator.Split is TopDown).
183		"foo{pre_arch:b,pre_deps:d}",
184		"foo{pre_arch:b,pre_deps:c}",
185		"foo{pre_arch:a,pre_deps:d}",
186		"foo{pre_arch:a,pre_deps:c}",
187
188		// After post_deps.
189		"foo{pre_arch:a,pre_deps:c,post_deps:e}",
190		"foo{pre_arch:a,pre_deps:c,post_deps:f}",
191		"foo{pre_arch:a,pre_deps:d,post_deps:e}",
192		"foo{pre_arch:a,pre_deps:d,post_deps:f}",
193		"foo{pre_arch:b,pre_deps:c,post_deps:e}",
194		"foo{pre_arch:b,pre_deps:c,post_deps:f}",
195		"foo{pre_arch:b,pre_deps:d,post_deps:e}",
196		"foo{pre_arch:b,pre_deps:d,post_deps:f}",
197
198		// After rename_bottom_up.
199		"foo_renamed1{pre_arch:a,pre_deps:c,post_deps:e}",
200		"foo_renamed1{pre_arch:a,pre_deps:c,post_deps:f}",
201		"foo_renamed1{pre_arch:a,pre_deps:d,post_deps:e}",
202		"foo_renamed1{pre_arch:a,pre_deps:d,post_deps:f}",
203		"foo_renamed1{pre_arch:b,pre_deps:c,post_deps:e}",
204		"foo_renamed1{pre_arch:b,pre_deps:c,post_deps:f}",
205		"foo_renamed1{pre_arch:b,pre_deps:d,post_deps:e}",
206		"foo_renamed1{pre_arch:b,pre_deps:d,post_deps:f}",
207	}
208
209	AssertDeepEquals(t, "module String() values", want, moduleStrings)
210}
211
212func TestFinalDepsPhase(t *testing.T) {
213	bp := `
214		test {
215			name: "common_dep_1",
216		}
217		test {
218			name: "common_dep_2",
219		}
220		test {
221			name: "foo",
222		}
223	`
224
225	finalGot := sync.Map{}
226
227	GroupFixturePreparers(
228		FixtureRegisterWithContext(func(ctx RegistrationContext) {
229			dep1Tag := struct {
230				blueprint.BaseDependencyTag
231			}{}
232			dep2Tag := struct {
233				blueprint.BaseDependencyTag
234			}{}
235
236			ctx.PostDepsMutators(func(ctx RegisterMutatorsContext) {
237				ctx.BottomUp("far_deps_1", func(ctx BottomUpMutatorContext) {
238					if !strings.HasPrefix(ctx.ModuleName(), "common_dep") {
239						ctx.AddFarVariationDependencies([]blueprint.Variation{}, dep1Tag, "common_dep_1")
240					}
241				})
242				ctx.Transition("variant", &testTransitionMutator{
243					split: func(ctx BaseModuleContext) []string {
244						return []string{"a", "b"}
245					},
246				})
247			})
248
249			ctx.FinalDepsMutators(func(ctx RegisterMutatorsContext) {
250				ctx.BottomUp("far_deps_2", func(ctx BottomUpMutatorContext) {
251					if !strings.HasPrefix(ctx.ModuleName(), "common_dep") {
252						ctx.AddFarVariationDependencies([]blueprint.Variation{}, dep2Tag, "common_dep_2")
253					}
254				})
255				ctx.BottomUp("final", func(ctx BottomUpMutatorContext) {
256					counter, _ := finalGot.LoadOrStore(ctx.Module().String(), &atomic.Int64{})
257					counter.(*atomic.Int64).Add(1)
258					ctx.VisitDirectDeps(func(mod Module) {
259						counter, _ := finalGot.LoadOrStore(fmt.Sprintf("%s -> %s", ctx.Module().String(), mod), &atomic.Int64{})
260						counter.(*atomic.Int64).Add(1)
261					})
262				})
263			})
264
265			ctx.RegisterModuleType("test", mutatorTestModuleFactory)
266		}),
267		FixtureWithRootAndroidBp(bp),
268	).RunTest(t)
269
270	finalWant := map[string]int{
271		"common_dep_1{variant:a}":                   1,
272		"common_dep_1{variant:b}":                   1,
273		"common_dep_2{variant:a}":                   1,
274		"common_dep_2{variant:b}":                   1,
275		"foo{variant:a}":                            1,
276		"foo{variant:a} -> common_dep_1{variant:a}": 1,
277		"foo{variant:a} -> common_dep_2{variant:a}": 1,
278		"foo{variant:b}":                            1,
279		"foo{variant:b} -> common_dep_1{variant:b}": 1,
280		"foo{variant:b} -> common_dep_2{variant:a}": 1,
281	}
282
283	finalGotMap := make(map[string]int)
284	finalGot.Range(func(k, v any) bool {
285		finalGotMap[k.(string)] = int(v.(*atomic.Int64).Load())
286		return true
287	})
288
289	AssertDeepEquals(t, "final", finalWant, finalGotMap)
290}
291
292func TestTransitionMutatorInFinalDeps(t *testing.T) {
293	GroupFixturePreparers(
294		FixtureRegisterWithContext(func(ctx RegistrationContext) {
295			ctx.FinalDepsMutators(func(ctx RegisterMutatorsContext) {
296				ctx.Transition("vars", &testTransitionMutator{
297					split: func(ctx BaseModuleContext) []string {
298						return []string{"a", "b"}
299					},
300				})
301			})
302
303			ctx.RegisterModuleType("test", mutatorTestModuleFactory)
304		}),
305		FixtureWithRootAndroidBp(`test {name: "foo"}`),
306	).
307		ExtendWithErrorHandler(FixtureExpectsOneErrorPattern("not allowed in FinalDepsMutators")).
308		RunTest(t)
309}
310