• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2020 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 blueprint
16
17import (
18	"fmt"
19	"reflect"
20	"strings"
21	"testing"
22)
23
24type providerTestModule struct {
25	SimpleName
26	properties struct {
27		Deps []string
28	}
29
30	mutatorProviderValues              []string
31	generateBuildActionsProviderValues []string
32}
33
34func newProviderTestModule() (Module, []interface{}) {
35	m := &providerTestModule{}
36	return m, []interface{}{&m.properties, &m.SimpleName.Properties}
37}
38
39type providerTestMutatorInfo struct {
40	Values []string
41}
42
43type providerTestGenerateBuildActionsInfo struct {
44	Value string
45}
46
47type providerTestUnsetInfo string
48
49var providerTestMutatorInfoProvider = NewMutatorProvider[*providerTestMutatorInfo]("provider_mutator")
50var providerTestGenerateBuildActionsInfoProvider = NewProvider[*providerTestGenerateBuildActionsInfo]()
51var providerTestUnsetInfoProvider = NewMutatorProvider[providerTestUnsetInfo]("provider_mutator")
52var providerTestUnusedMutatorProvider = NewMutatorProvider[*struct{ unused string }]("nonexistent_mutator")
53
54func (p *providerTestModule) GenerateBuildActions(ctx ModuleContext) {
55	unset, ok := ModuleProvider(ctx, providerTestUnsetInfoProvider)
56	if ok {
57		panic(fmt.Errorf("expected false return value for providerTestGenerateBuildActionsInfoProvider before it was set"))
58	}
59	if unset != "" {
60		panic(fmt.Errorf("expected zero value for providerTestGenerateBuildActionsInfoProvider before it was set, got %q",
61			unset))
62	}
63
64	// Verify reading providerTestUnusedMutatorProvider doesn't panic
65	_, _ = ModuleProvider(ctx, providerTestUnusedMutatorProvider)
66
67	SetProvider(ctx, providerTestGenerateBuildActionsInfoProvider, &providerTestGenerateBuildActionsInfo{
68		Value: ctx.ModuleName(),
69	})
70
71	mp, ok := ModuleProvider(ctx, providerTestMutatorInfoProvider)
72	if ok {
73		p.mutatorProviderValues = mp.Values
74	}
75
76	ctx.VisitDirectDeps(func(module Module) {
77		gbap, _ := OtherModuleProvider(ctx, module, providerTestGenerateBuildActionsInfoProvider)
78		if gbap != nil {
79			p.generateBuildActionsProviderValues = append(p.generateBuildActionsProviderValues, gbap.Value)
80		}
81	})
82}
83
84func providerTestDepsMutator(ctx BottomUpMutatorContext) {
85	if p, ok := ctx.Module().(*providerTestModule); ok {
86		ctx.AddDependency(ctx.Module(), nil, p.properties.Deps...)
87	}
88}
89
90func providerTestMutator(ctx BottomUpMutatorContext) {
91	values := []string{strings.ToLower(ctx.ModuleName())}
92
93	ctx.VisitDirectDeps(func(module Module) {
94		mp, _ := OtherModuleProvider(ctx, module, providerTestMutatorInfoProvider)
95		if mp != nil {
96			values = append(values, mp.Values...)
97		}
98	})
99
100	SetProvider(ctx, providerTestMutatorInfoProvider, &providerTestMutatorInfo{
101		Values: values,
102	})
103}
104
105func providerTestAfterMutator(ctx BottomUpMutatorContext) {
106	// Verify reading providerTestUnusedMutatorProvider doesn't panic
107	_, _ = ModuleProvider(ctx, providerTestMutatorInfoProvider)
108}
109
110func TestProviders(t *testing.T) {
111	ctx := NewContext()
112	ctx.RegisterModuleType("provider_module", newProviderTestModule)
113	ctx.RegisterBottomUpMutator("provider_deps_mutator", providerTestDepsMutator)
114	ctx.RegisterBottomUpMutator("provider_mutator", providerTestMutator)
115	ctx.RegisterBottomUpMutator("provider_after_mutator", providerTestAfterMutator)
116
117	ctx.MockFileSystem(map[string][]byte{
118		"Android.bp": []byte(`
119			provider_module {
120				name: "A",
121				deps: ["B"],
122			}
123
124			provider_module {
125				name: "B",
126				deps: ["C", "D"],
127			}
128
129			provider_module {
130				name: "C",
131				deps: ["D"],
132			}
133
134			provider_module {
135				name: "D",
136			}
137		`),
138	})
139
140	_, errs := ctx.ParseBlueprintsFiles("Android.bp", nil)
141	if len(errs) == 0 {
142		_, errs = ctx.ResolveDependencies(nil)
143	}
144	if len(errs) == 0 {
145		_, errs = ctx.PrepareBuildActions(nil)
146	}
147	if len(errs) > 0 {
148		t.Errorf("unexpected errors:")
149		for _, err := range errs {
150			t.Errorf("  %s", err)
151		}
152		t.FailNow()
153	}
154
155	aModule := ctx.moduleGroupFromName("A", nil).moduleByVariantName("").logicModule.(*providerTestModule)
156	if g, w := aModule.generateBuildActionsProviderValues, []string{"B"}; !reflect.DeepEqual(g, w) {
157		t.Errorf("expected A.generateBuildActionsProviderValues %q, got %q", w, g)
158	}
159	if g, w := aModule.mutatorProviderValues, []string{"a", "b", "c", "d", "d"}; !reflect.DeepEqual(g, w) {
160		t.Errorf("expected A.mutatorProviderValues %q, got %q", w, g)
161	}
162
163	bModule := ctx.moduleGroupFromName("B", nil).moduleByVariantName("").logicModule.(*providerTestModule)
164	if g, w := bModule.generateBuildActionsProviderValues, []string{"C", "D"}; !reflect.DeepEqual(g, w) {
165		t.Errorf("expected B.generateBuildActionsProviderValues %q, got %q", w, g)
166	}
167	if g, w := bModule.mutatorProviderValues, []string{"b", "c", "d", "d"}; !reflect.DeepEqual(g, w) {
168		t.Errorf("expected B.mutatorProviderValues %q, got %q", w, g)
169	}
170}
171
172type invalidProviderUsageMutatorInfo string
173type invalidProviderUsageGenerateBuildActionsInfo string
174
175var invalidProviderUsageMutatorInfoProvider = NewMutatorProvider[invalidProviderUsageMutatorInfo]("mutator_under_test")
176var invalidProviderUsageGenerateBuildActionsInfoProvider = NewProvider[invalidProviderUsageGenerateBuildActionsInfo]()
177
178type invalidProviderUsageTestModule struct {
179	SimpleName
180	properties struct {
181		Deps []string
182
183		Early_mutator_set_of_mutator_provider       bool
184		Late_mutator_set_of_mutator_provider        bool
185		Late_build_actions_set_of_mutator_provider  bool
186		Early_mutator_set_of_build_actions_provider bool
187
188		Early_mutator_get_of_mutator_provider       bool
189		Early_mutator_get_of_build_actions_provider bool
190
191		Duplicate_set bool
192	}
193}
194
195func invalidProviderUsageDepsMutator(ctx BottomUpMutatorContext) {
196	if i, ok := ctx.Module().(*invalidProviderUsageTestModule); ok {
197		ctx.AddDependency(ctx.Module(), nil, i.properties.Deps...)
198	}
199}
200
201func invalidProviderUsageBeforeMutator(ctx BottomUpMutatorContext) {
202	if i, ok := ctx.Module().(*invalidProviderUsageTestModule); ok {
203		if i.properties.Early_mutator_set_of_mutator_provider {
204			// A mutator attempting to set the value of a provider associated with a later mutator.
205			SetProvider(ctx, invalidProviderUsageMutatorInfoProvider, invalidProviderUsageMutatorInfo(""))
206		}
207		if i.properties.Early_mutator_get_of_mutator_provider {
208			// A mutator attempting to get the value of a provider associated with a later mutator.
209			_, _ = ModuleProvider(ctx, invalidProviderUsageMutatorInfoProvider)
210		}
211	}
212}
213
214func invalidProviderUsageMutatorUnderTest(ctx BottomUpMutatorContext) {
215	if i, ok := ctx.Module().(*invalidProviderUsageTestModule); ok {
216		if i.properties.Early_mutator_set_of_build_actions_provider {
217			// A mutator attempting to set the value of a non-mutator provider.
218			SetProvider(ctx, invalidProviderUsageGenerateBuildActionsInfoProvider, invalidProviderUsageGenerateBuildActionsInfo(""))
219		}
220		if i.properties.Early_mutator_get_of_build_actions_provider {
221			// A mutator attempting to get the value of a non-mutator provider.
222			_, _ = ModuleProvider(ctx, invalidProviderUsageGenerateBuildActionsInfoProvider)
223		}
224	}
225}
226
227func invalidProviderUsageAfterMutator(ctx BottomUpMutatorContext) {
228	if i, ok := ctx.Module().(*invalidProviderUsageTestModule); ok {
229		if i.properties.Late_mutator_set_of_mutator_provider {
230			// A mutator trying to set the value of a provider associated with an earlier mutator.
231			SetProvider(ctx, invalidProviderUsageMutatorInfoProvider, invalidProviderUsageMutatorInfo(""))
232		}
233		if i.properties.Late_mutator_set_of_mutator_provider {
234			// A mutator trying to set the value of a provider associated with an earlier mutator.
235			SetProvider(ctx, invalidProviderUsageMutatorInfoProvider, invalidProviderUsageMutatorInfo(""))
236		}
237	}
238}
239
240func (i *invalidProviderUsageTestModule) GenerateBuildActions(ctx ModuleContext) {
241	if i.properties.Late_build_actions_set_of_mutator_provider {
242		// A GenerateBuildActions trying to set the value of a provider associated with a mutator.
243		SetProvider(ctx, invalidProviderUsageMutatorInfoProvider, invalidProviderUsageMutatorInfo(""))
244	}
245	if i.properties.Duplicate_set {
246		SetProvider(ctx, invalidProviderUsageGenerateBuildActionsInfoProvider, invalidProviderUsageGenerateBuildActionsInfo(""))
247		SetProvider(ctx, invalidProviderUsageGenerateBuildActionsInfoProvider, invalidProviderUsageGenerateBuildActionsInfo(""))
248	}
249}
250
251func TestInvalidProvidersUsage(t *testing.T) {
252	run := func(t *testing.T, module string, prop string, panicMsg string) {
253		t.Helper()
254		ctx := NewContext()
255		ctx.RegisterModuleType("invalid_provider_usage_test_module", func() (Module, []interface{}) {
256			m := &invalidProviderUsageTestModule{}
257			return m, []interface{}{&m.properties, &m.SimpleName.Properties}
258		})
259		ctx.RegisterBottomUpMutator("deps", invalidProviderUsageDepsMutator)
260		ctx.RegisterBottomUpMutator("before", invalidProviderUsageBeforeMutator)
261		ctx.RegisterBottomUpMutator("mutator_under_test", invalidProviderUsageMutatorUnderTest)
262		ctx.RegisterBottomUpMutator("after", invalidProviderUsageAfterMutator)
263
264		// Don't invalidate the parent pointer and before GenerateBuildActions.
265		ctx.SkipCloneModulesAfterMutators = true
266
267		var parentBP, moduleUnderTestBP, childBP string
268
269		prop += ": true,"
270
271		switch module {
272		case "parent":
273			parentBP = prop
274		case "module_under_test":
275			moduleUnderTestBP = prop
276		case "child":
277			childBP = prop
278		}
279
280		bp := fmt.Sprintf(`
281			invalid_provider_usage_test_module {
282				name: "parent",
283				deps: ["module_under_test"],
284				%s
285			}
286
287			invalid_provider_usage_test_module {
288				name: "module_under_test",
289				deps: ["child"],
290				%s
291			}
292
293			invalid_provider_usage_test_module {
294				name: "child",
295				%s
296			}
297
298		`,
299			parentBP,
300			moduleUnderTestBP,
301			childBP)
302
303		ctx.MockFileSystem(map[string][]byte{
304			"Android.bp": []byte(bp),
305		})
306
307		_, errs := ctx.ParseBlueprintsFiles("Android.bp", nil)
308
309		if len(errs) == 0 {
310			_, errs = ctx.ResolveDependencies(nil)
311		}
312
313		if len(errs) == 0 {
314			_, errs = ctx.PrepareBuildActions(nil)
315		}
316
317		if len(errs) == 0 {
318			t.Fatal("expected an error")
319		}
320
321		if len(errs) > 1 {
322			t.Errorf("expected a single error, got %d:", len(errs))
323			for i, err := range errs {
324				t.Errorf("%d:  %s", i, err)
325			}
326			t.FailNow()
327		}
328
329		if panicErr, ok := errs[0].(panicError); ok {
330			if panicErr.panic != panicMsg {
331				t.Fatalf("expected panic %q, got %q", panicMsg, panicErr.panic)
332			}
333		} else {
334			t.Fatalf("expected a panicError, got %T: %s", errs[0], errs[0].Error())
335		}
336
337	}
338
339	tests := []struct {
340		prop   string
341		module string
342
343		panicMsg string
344		skip     string
345	}{
346		{
347			prop:     "early_mutator_set_of_mutator_provider",
348			module:   "module_under_test",
349			panicMsg: "Can't set value of provider blueprint.invalidProviderUsageMutatorInfo before mutator mutator_under_test started",
350		},
351		{
352			prop:     "late_mutator_set_of_mutator_provider",
353			module:   "module_under_test",
354			panicMsg: "Can't set value of provider blueprint.invalidProviderUsageMutatorInfo after mutator mutator_under_test finished",
355		},
356		{
357			prop:     "late_build_actions_set_of_mutator_provider",
358			module:   "module_under_test",
359			panicMsg: "Can't set value of provider blueprint.invalidProviderUsageMutatorInfo after mutator mutator_under_test finished",
360		},
361		{
362			prop:     "early_mutator_set_of_build_actions_provider",
363			module:   "module_under_test",
364			panicMsg: "Can't set value of provider blueprint.invalidProviderUsageGenerateBuildActionsInfo before GenerateBuildActions started",
365		},
366
367		{
368			prop:     "early_mutator_get_of_mutator_provider",
369			module:   "module_under_test",
370			panicMsg: "Can't get value of provider blueprint.invalidProviderUsageMutatorInfo before mutator mutator_under_test finished",
371		},
372		{
373			prop:     "early_mutator_get_of_build_actions_provider",
374			module:   "module_under_test",
375			panicMsg: "Can't get value of provider blueprint.invalidProviderUsageGenerateBuildActionsInfo before GenerateBuildActions finished",
376		},
377		{
378			prop:     "duplicate_set",
379			module:   "module_under_test",
380			panicMsg: "Value of provider blueprint.invalidProviderUsageGenerateBuildActionsInfo is already set",
381		},
382	}
383
384	for _, tt := range tests {
385		t.Run(tt.prop, func(t *testing.T) {
386			run(t, tt.module, tt.prop, tt.panicMsg)
387		})
388	}
389}
390