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