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	"testing"
21
22	"github.com/google/blueprint"
23)
24
25type mutatorTestModule struct {
26	ModuleBase
27	props struct {
28		Deps_missing_deps    []string
29		Mutator_missing_deps []string
30	}
31
32	missingDeps []string
33}
34
35func mutatorTestModuleFactory() Module {
36	module := &mutatorTestModule{}
37	module.AddProperties(&module.props)
38	InitAndroidModule(module)
39	return module
40}
41
42func (m *mutatorTestModule) GenerateAndroidBuildActions(ctx ModuleContext) {
43	ctx.Build(pctx, BuildParams{
44		Rule:   Touch,
45		Output: PathForModuleOut(ctx, "output"),
46	})
47
48	m.missingDeps = ctx.GetMissingDependencies()
49}
50
51func (m *mutatorTestModule) DepsMutator(ctx BottomUpMutatorContext) {
52	ctx.AddDependency(ctx.Module(), nil, m.props.Deps_missing_deps...)
53}
54
55func addMissingDependenciesMutator(ctx TopDownMutatorContext) {
56	ctx.AddMissingDependencies(ctx.Module().(*mutatorTestModule).props.Mutator_missing_deps)
57}
58
59func TestMutatorAddMissingDependencies(t *testing.T) {
60	bp := `
61		test {
62			name: "foo",
63			deps_missing_deps: ["regular_missing_dep"],
64			mutator_missing_deps: ["added_missing_dep"],
65		}
66	`
67
68	result := GroupFixturePreparers(
69		PrepareForTestWithAllowMissingDependencies,
70		FixtureRegisterWithContext(func(ctx RegistrationContext) {
71			ctx.RegisterModuleType("test", mutatorTestModuleFactory)
72			ctx.PreDepsMutators(func(ctx RegisterMutatorsContext) {
73				ctx.TopDown("add_missing_dependencies", addMissingDependenciesMutator)
74			})
75		}),
76		FixtureWithRootAndroidBp(bp),
77	).RunTest(t)
78
79	foo := result.ModuleForTests("foo", "").Module().(*mutatorTestModule)
80
81	AssertDeepEquals(t, "foo missing deps", []string{"added_missing_dep", "regular_missing_dep"}, foo.missingDeps)
82}
83
84func TestModuleString(t *testing.T) {
85	bp := `
86		test {
87			name: "foo",
88		}
89	`
90
91	var moduleStrings []string
92
93	GroupFixturePreparers(
94		FixtureRegisterWithContext(func(ctx RegistrationContext) {
95
96			ctx.PreArchMutators(func(ctx RegisterMutatorsContext) {
97				ctx.BottomUp("pre_arch", func(ctx BottomUpMutatorContext) {
98					moduleStrings = append(moduleStrings, ctx.Module().String())
99					ctx.CreateVariations("a", "b")
100				})
101				ctx.TopDown("rename_top_down", func(ctx TopDownMutatorContext) {
102					moduleStrings = append(moduleStrings, ctx.Module().String())
103					ctx.Rename(ctx.Module().base().Name() + "_renamed1")
104				})
105			})
106
107			ctx.PreDepsMutators(func(ctx RegisterMutatorsContext) {
108				ctx.BottomUp("pre_deps", func(ctx BottomUpMutatorContext) {
109					moduleStrings = append(moduleStrings, ctx.Module().String())
110					ctx.CreateVariations("c", "d")
111				})
112			})
113
114			ctx.PostDepsMutators(func(ctx RegisterMutatorsContext) {
115				ctx.BottomUp("post_deps", func(ctx BottomUpMutatorContext) {
116					moduleStrings = append(moduleStrings, ctx.Module().String())
117					ctx.CreateLocalVariations("e", "f")
118				})
119				ctx.BottomUp("rename_bottom_up", func(ctx BottomUpMutatorContext) {
120					moduleStrings = append(moduleStrings, ctx.Module().String())
121					ctx.Rename(ctx.Module().base().Name() + "_renamed2")
122				})
123				ctx.BottomUp("final", func(ctx BottomUpMutatorContext) {
124					moduleStrings = append(moduleStrings, ctx.Module().String())
125				})
126			})
127
128			ctx.RegisterModuleType("test", mutatorTestModuleFactory)
129		}),
130		FixtureWithRootAndroidBp(bp),
131	).RunTest(t)
132
133	want := []string{
134		// Initial name.
135		"foo{}",
136
137		// After pre_arch (reversed because rename_top_down is TopDown so it visits in reverse order).
138		"foo{pre_arch:b}",
139		"foo{pre_arch:a}",
140
141		// After rename_top_down.
142		"foo_renamed1{pre_arch:a}",
143		"foo_renamed1{pre_arch:b}",
144
145		// After pre_deps.
146		"foo_renamed1{pre_arch:a,pre_deps:c}",
147		"foo_renamed1{pre_arch:a,pre_deps:d}",
148		"foo_renamed1{pre_arch:b,pre_deps:c}",
149		"foo_renamed1{pre_arch:b,pre_deps:d}",
150
151		// After post_deps.
152		"foo_renamed1{pre_arch:a,pre_deps:c,post_deps:e}",
153		"foo_renamed1{pre_arch:a,pre_deps:c,post_deps:f}",
154		"foo_renamed1{pre_arch:a,pre_deps:d,post_deps:e}",
155		"foo_renamed1{pre_arch:a,pre_deps:d,post_deps:f}",
156		"foo_renamed1{pre_arch:b,pre_deps:c,post_deps:e}",
157		"foo_renamed1{pre_arch:b,pre_deps:c,post_deps:f}",
158		"foo_renamed1{pre_arch:b,pre_deps:d,post_deps:e}",
159		"foo_renamed1{pre_arch:b,pre_deps:d,post_deps:f}",
160
161		// After rename_bottom_up.
162		"foo_renamed2{pre_arch:a,pre_deps:c,post_deps:e}",
163		"foo_renamed2{pre_arch:a,pre_deps:c,post_deps:f}",
164		"foo_renamed2{pre_arch:a,pre_deps:d,post_deps:e}",
165		"foo_renamed2{pre_arch:a,pre_deps:d,post_deps:f}",
166		"foo_renamed2{pre_arch:b,pre_deps:c,post_deps:e}",
167		"foo_renamed2{pre_arch:b,pre_deps:c,post_deps:f}",
168		"foo_renamed2{pre_arch:b,pre_deps:d,post_deps:e}",
169		"foo_renamed2{pre_arch:b,pre_deps:d,post_deps:f}",
170	}
171
172	AssertDeepEquals(t, "module String() values", want, moduleStrings)
173}
174
175func TestFinalDepsPhase(t *testing.T) {
176	bp := `
177		test {
178			name: "common_dep_1",
179		}
180		test {
181			name: "common_dep_2",
182		}
183		test {
184			name: "foo",
185		}
186	`
187
188	finalGot := map[string]int{}
189
190	GroupFixturePreparers(
191		FixtureRegisterWithContext(func(ctx RegistrationContext) {
192			dep1Tag := struct {
193				blueprint.BaseDependencyTag
194			}{}
195			dep2Tag := struct {
196				blueprint.BaseDependencyTag
197			}{}
198
199			ctx.PostDepsMutators(func(ctx RegisterMutatorsContext) {
200				ctx.BottomUp("far_deps_1", func(ctx BottomUpMutatorContext) {
201					if !strings.HasPrefix(ctx.ModuleName(), "common_dep") {
202						ctx.AddFarVariationDependencies([]blueprint.Variation{}, dep1Tag, "common_dep_1")
203					}
204				})
205				ctx.BottomUp("variant", func(ctx BottomUpMutatorContext) {
206					ctx.CreateLocalVariations("a", "b")
207				})
208			})
209
210			ctx.FinalDepsMutators(func(ctx RegisterMutatorsContext) {
211				ctx.BottomUp("far_deps_2", func(ctx BottomUpMutatorContext) {
212					if !strings.HasPrefix(ctx.ModuleName(), "common_dep") {
213						ctx.AddFarVariationDependencies([]blueprint.Variation{}, dep2Tag, "common_dep_2")
214					}
215				})
216				ctx.BottomUp("final", func(ctx BottomUpMutatorContext) {
217					finalGot[ctx.Module().String()] += 1
218					ctx.VisitDirectDeps(func(mod Module) {
219						finalGot[fmt.Sprintf("%s -> %s", ctx.Module().String(), mod)] += 1
220					})
221				})
222			})
223
224			ctx.RegisterModuleType("test", mutatorTestModuleFactory)
225		}),
226		FixtureWithRootAndroidBp(bp),
227	).RunTest(t)
228
229	finalWant := map[string]int{
230		"common_dep_1{variant:a}":                   1,
231		"common_dep_1{variant:b}":                   1,
232		"common_dep_2{variant:a}":                   1,
233		"common_dep_2{variant:b}":                   1,
234		"foo{variant:a}":                            1,
235		"foo{variant:a} -> common_dep_1{variant:a}": 1,
236		"foo{variant:a} -> common_dep_2{variant:a}": 1,
237		"foo{variant:b}":                            1,
238		"foo{variant:b} -> common_dep_1{variant:b}": 1,
239		"foo{variant:b} -> common_dep_2{variant:a}": 1,
240	}
241
242	AssertDeepEquals(t, "final", finalWant, finalGot)
243}
244
245func TestNoCreateVariationsInFinalDeps(t *testing.T) {
246	checkErr := func() {
247		if err := recover(); err == nil || !strings.Contains(fmt.Sprintf("%s", err), "not allowed in FinalDepsMutators") {
248			panic("Expected FinalDepsMutators consistency check to fail")
249		}
250	}
251
252	GroupFixturePreparers(
253		FixtureRegisterWithContext(func(ctx RegistrationContext) {
254			ctx.FinalDepsMutators(func(ctx RegisterMutatorsContext) {
255				ctx.BottomUp("vars", func(ctx BottomUpMutatorContext) {
256					defer checkErr()
257					ctx.CreateVariations("a", "b")
258				})
259				ctx.BottomUp("local_vars", func(ctx BottomUpMutatorContext) {
260					defer checkErr()
261					ctx.CreateLocalVariations("a", "b")
262				})
263			})
264
265			ctx.RegisterModuleType("test", mutatorTestModuleFactory)
266		}),
267		FixtureWithRootAndroidBp(`test {name: "foo"}`),
268	).RunTest(t)
269}
270