xref: /aosp_15_r20/build/blueprint/provider_test.go (revision 1fa6dee971e1612fa5cc0aa5ca2d35a22e2c34a3)
1*1fa6dee9SAndroid Build Coastguard Worker// Copyright 2020 Google Inc. All rights reserved.
2*1fa6dee9SAndroid Build Coastguard Worker//
3*1fa6dee9SAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License");
4*1fa6dee9SAndroid Build Coastguard Worker// you may not use this file except in compliance with the License.
5*1fa6dee9SAndroid Build Coastguard Worker// You may obtain a copy of the License at
6*1fa6dee9SAndroid Build Coastguard Worker//
7*1fa6dee9SAndroid Build Coastguard Worker//     http://www.apache.org/licenses/LICENSE-2.0
8*1fa6dee9SAndroid Build Coastguard Worker//
9*1fa6dee9SAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software
10*1fa6dee9SAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS,
11*1fa6dee9SAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*1fa6dee9SAndroid Build Coastguard Worker// See the License for the specific language governing permissions and
13*1fa6dee9SAndroid Build Coastguard Worker// limitations under the License.
14*1fa6dee9SAndroid Build Coastguard Worker
15*1fa6dee9SAndroid Build Coastguard Workerpackage blueprint
16*1fa6dee9SAndroid Build Coastguard Worker
17*1fa6dee9SAndroid Build Coastguard Workerimport (
18*1fa6dee9SAndroid Build Coastguard Worker	"fmt"
19*1fa6dee9SAndroid Build Coastguard Worker	"reflect"
20*1fa6dee9SAndroid Build Coastguard Worker	"strings"
21*1fa6dee9SAndroid Build Coastguard Worker	"testing"
22*1fa6dee9SAndroid Build Coastguard Worker)
23*1fa6dee9SAndroid Build Coastguard Worker
24*1fa6dee9SAndroid Build Coastguard Workertype providerTestModule struct {
25*1fa6dee9SAndroid Build Coastguard Worker	SimpleName
26*1fa6dee9SAndroid Build Coastguard Worker	properties struct {
27*1fa6dee9SAndroid Build Coastguard Worker		Deps []string
28*1fa6dee9SAndroid Build Coastguard Worker	}
29*1fa6dee9SAndroid Build Coastguard Worker
30*1fa6dee9SAndroid Build Coastguard Worker	mutatorProviderValues              []string
31*1fa6dee9SAndroid Build Coastguard Worker	generateBuildActionsProviderValues []string
32*1fa6dee9SAndroid Build Coastguard Worker}
33*1fa6dee9SAndroid Build Coastguard Worker
34*1fa6dee9SAndroid Build Coastguard Workerfunc newProviderTestModule() (Module, []interface{}) {
35*1fa6dee9SAndroid Build Coastguard Worker	m := &providerTestModule{}
36*1fa6dee9SAndroid Build Coastguard Worker	return m, []interface{}{&m.properties, &m.SimpleName.Properties}
37*1fa6dee9SAndroid Build Coastguard Worker}
38*1fa6dee9SAndroid Build Coastguard Worker
39*1fa6dee9SAndroid Build Coastguard Workertype providerTestMutatorInfo struct {
40*1fa6dee9SAndroid Build Coastguard Worker	Values []string
41*1fa6dee9SAndroid Build Coastguard Worker}
42*1fa6dee9SAndroid Build Coastguard Worker
43*1fa6dee9SAndroid Build Coastguard Workertype providerTestGenerateBuildActionsInfo struct {
44*1fa6dee9SAndroid Build Coastguard Worker	Value string
45*1fa6dee9SAndroid Build Coastguard Worker}
46*1fa6dee9SAndroid Build Coastguard Worker
47*1fa6dee9SAndroid Build Coastguard Workertype providerTestUnsetInfo string
48*1fa6dee9SAndroid Build Coastguard Worker
49*1fa6dee9SAndroid Build Coastguard Workervar providerTestMutatorInfoProvider = NewMutatorProvider[*providerTestMutatorInfo]("provider_mutator")
50*1fa6dee9SAndroid Build Coastguard Workervar providerTestGenerateBuildActionsInfoProvider = NewProvider[*providerTestGenerateBuildActionsInfo]()
51*1fa6dee9SAndroid Build Coastguard Workervar providerTestUnsetInfoProvider = NewMutatorProvider[providerTestUnsetInfo]("provider_mutator")
52*1fa6dee9SAndroid Build Coastguard Workervar providerTestUnusedMutatorProvider = NewMutatorProvider[*struct{ unused string }]("nonexistent_mutator")
53*1fa6dee9SAndroid Build Coastguard Worker
54*1fa6dee9SAndroid Build Coastguard Workerfunc (p *providerTestModule) GenerateBuildActions(ctx ModuleContext) {
55*1fa6dee9SAndroid Build Coastguard Worker	unset, ok := ModuleProvider(ctx, providerTestUnsetInfoProvider)
56*1fa6dee9SAndroid Build Coastguard Worker	if ok {
57*1fa6dee9SAndroid Build Coastguard Worker		panic(fmt.Errorf("expected false return value for providerTestGenerateBuildActionsInfoProvider before it was set"))
58*1fa6dee9SAndroid Build Coastguard Worker	}
59*1fa6dee9SAndroid Build Coastguard Worker	if unset != "" {
60*1fa6dee9SAndroid Build Coastguard Worker		panic(fmt.Errorf("expected zero value for providerTestGenerateBuildActionsInfoProvider before it was set, got %q",
61*1fa6dee9SAndroid Build Coastguard Worker			unset))
62*1fa6dee9SAndroid Build Coastguard Worker	}
63*1fa6dee9SAndroid Build Coastguard Worker
64*1fa6dee9SAndroid Build Coastguard Worker	// Verify reading providerTestUnusedMutatorProvider doesn't panic
65*1fa6dee9SAndroid Build Coastguard Worker	_, _ = ModuleProvider(ctx, providerTestUnusedMutatorProvider)
66*1fa6dee9SAndroid Build Coastguard Worker
67*1fa6dee9SAndroid Build Coastguard Worker	SetProvider(ctx, providerTestGenerateBuildActionsInfoProvider, &providerTestGenerateBuildActionsInfo{
68*1fa6dee9SAndroid Build Coastguard Worker		Value: ctx.ModuleName(),
69*1fa6dee9SAndroid Build Coastguard Worker	})
70*1fa6dee9SAndroid Build Coastguard Worker
71*1fa6dee9SAndroid Build Coastguard Worker	mp, ok := ModuleProvider(ctx, providerTestMutatorInfoProvider)
72*1fa6dee9SAndroid Build Coastguard Worker	if ok {
73*1fa6dee9SAndroid Build Coastguard Worker		p.mutatorProviderValues = mp.Values
74*1fa6dee9SAndroid Build Coastguard Worker	}
75*1fa6dee9SAndroid Build Coastguard Worker
76*1fa6dee9SAndroid Build Coastguard Worker	ctx.VisitDirectDeps(func(module Module) {
77*1fa6dee9SAndroid Build Coastguard Worker		gbap, _ := OtherModuleProvider(ctx, module, providerTestGenerateBuildActionsInfoProvider)
78*1fa6dee9SAndroid Build Coastguard Worker		if gbap != nil {
79*1fa6dee9SAndroid Build Coastguard Worker			p.generateBuildActionsProviderValues = append(p.generateBuildActionsProviderValues, gbap.Value)
80*1fa6dee9SAndroid Build Coastguard Worker		}
81*1fa6dee9SAndroid Build Coastguard Worker	})
82*1fa6dee9SAndroid Build Coastguard Worker}
83*1fa6dee9SAndroid Build Coastguard Worker
84*1fa6dee9SAndroid Build Coastguard Workerfunc providerTestDepsMutator(ctx BottomUpMutatorContext) {
85*1fa6dee9SAndroid Build Coastguard Worker	if p, ok := ctx.Module().(*providerTestModule); ok {
86*1fa6dee9SAndroid Build Coastguard Worker		ctx.AddDependency(ctx.Module(), nil, p.properties.Deps...)
87*1fa6dee9SAndroid Build Coastguard Worker	}
88*1fa6dee9SAndroid Build Coastguard Worker}
89*1fa6dee9SAndroid Build Coastguard Worker
90*1fa6dee9SAndroid Build Coastguard Workerfunc providerTestMutator(ctx BottomUpMutatorContext) {
91*1fa6dee9SAndroid Build Coastguard Worker	values := []string{strings.ToLower(ctx.ModuleName())}
92*1fa6dee9SAndroid Build Coastguard Worker
93*1fa6dee9SAndroid Build Coastguard Worker	ctx.VisitDirectDeps(func(module Module) {
94*1fa6dee9SAndroid Build Coastguard Worker		mp, _ := OtherModuleProvider(ctx, module, providerTestMutatorInfoProvider)
95*1fa6dee9SAndroid Build Coastguard Worker		if mp != nil {
96*1fa6dee9SAndroid Build Coastguard Worker			values = append(values, mp.Values...)
97*1fa6dee9SAndroid Build Coastguard Worker		}
98*1fa6dee9SAndroid Build Coastguard Worker	})
99*1fa6dee9SAndroid Build Coastguard Worker
100*1fa6dee9SAndroid Build Coastguard Worker	SetProvider(ctx, providerTestMutatorInfoProvider, &providerTestMutatorInfo{
101*1fa6dee9SAndroid Build Coastguard Worker		Values: values,
102*1fa6dee9SAndroid Build Coastguard Worker	})
103*1fa6dee9SAndroid Build Coastguard Worker}
104*1fa6dee9SAndroid Build Coastguard Worker
105*1fa6dee9SAndroid Build Coastguard Workerfunc providerTestAfterMutator(ctx BottomUpMutatorContext) {
106*1fa6dee9SAndroid Build Coastguard Worker	// Verify reading providerTestUnusedMutatorProvider doesn't panic
107*1fa6dee9SAndroid Build Coastguard Worker	_, _ = ModuleProvider(ctx, providerTestMutatorInfoProvider)
108*1fa6dee9SAndroid Build Coastguard Worker}
109*1fa6dee9SAndroid Build Coastguard Worker
110*1fa6dee9SAndroid Build Coastguard Workerfunc TestProviders(t *testing.T) {
111*1fa6dee9SAndroid Build Coastguard Worker	ctx := NewContext()
112*1fa6dee9SAndroid Build Coastguard Worker	ctx.RegisterModuleType("provider_module", newProviderTestModule)
113*1fa6dee9SAndroid Build Coastguard Worker	ctx.RegisterBottomUpMutator("provider_deps_mutator", providerTestDepsMutator)
114*1fa6dee9SAndroid Build Coastguard Worker	ctx.RegisterBottomUpMutator("provider_mutator", providerTestMutator)
115*1fa6dee9SAndroid Build Coastguard Worker	ctx.RegisterBottomUpMutator("provider_after_mutator", providerTestAfterMutator)
116*1fa6dee9SAndroid Build Coastguard Worker
117*1fa6dee9SAndroid Build Coastguard Worker	ctx.MockFileSystem(map[string][]byte{
118*1fa6dee9SAndroid Build Coastguard Worker		"Android.bp": []byte(`
119*1fa6dee9SAndroid Build Coastguard Worker			provider_module {
120*1fa6dee9SAndroid Build Coastguard Worker				name: "A",
121*1fa6dee9SAndroid Build Coastguard Worker				deps: ["B"],
122*1fa6dee9SAndroid Build Coastguard Worker			}
123*1fa6dee9SAndroid Build Coastguard Worker
124*1fa6dee9SAndroid Build Coastguard Worker			provider_module {
125*1fa6dee9SAndroid Build Coastguard Worker				name: "B",
126*1fa6dee9SAndroid Build Coastguard Worker				deps: ["C", "D"],
127*1fa6dee9SAndroid Build Coastguard Worker			}
128*1fa6dee9SAndroid Build Coastguard Worker
129*1fa6dee9SAndroid Build Coastguard Worker			provider_module {
130*1fa6dee9SAndroid Build Coastguard Worker				name: "C",
131*1fa6dee9SAndroid Build Coastguard Worker				deps: ["D"],
132*1fa6dee9SAndroid Build Coastguard Worker			}
133*1fa6dee9SAndroid Build Coastguard Worker
134*1fa6dee9SAndroid Build Coastguard Worker			provider_module {
135*1fa6dee9SAndroid Build Coastguard Worker				name: "D",
136*1fa6dee9SAndroid Build Coastguard Worker			}
137*1fa6dee9SAndroid Build Coastguard Worker		`),
138*1fa6dee9SAndroid Build Coastguard Worker	})
139*1fa6dee9SAndroid Build Coastguard Worker
140*1fa6dee9SAndroid Build Coastguard Worker	_, errs := ctx.ParseBlueprintsFiles("Android.bp", nil)
141*1fa6dee9SAndroid Build Coastguard Worker	if len(errs) == 0 {
142*1fa6dee9SAndroid Build Coastguard Worker		_, errs = ctx.ResolveDependencies(nil)
143*1fa6dee9SAndroid Build Coastguard Worker	}
144*1fa6dee9SAndroid Build Coastguard Worker	if len(errs) == 0 {
145*1fa6dee9SAndroid Build Coastguard Worker		_, errs = ctx.PrepareBuildActions(nil)
146*1fa6dee9SAndroid Build Coastguard Worker	}
147*1fa6dee9SAndroid Build Coastguard Worker	if len(errs) > 0 {
148*1fa6dee9SAndroid Build Coastguard Worker		t.Errorf("unexpected errors:")
149*1fa6dee9SAndroid Build Coastguard Worker		for _, err := range errs {
150*1fa6dee9SAndroid Build Coastguard Worker			t.Errorf("  %s", err)
151*1fa6dee9SAndroid Build Coastguard Worker		}
152*1fa6dee9SAndroid Build Coastguard Worker		t.FailNow()
153*1fa6dee9SAndroid Build Coastguard Worker	}
154*1fa6dee9SAndroid Build Coastguard Worker
155*1fa6dee9SAndroid Build Coastguard Worker	aModule := ctx.moduleGroupFromName("A", nil).moduleByVariantName("").logicModule.(*providerTestModule)
156*1fa6dee9SAndroid Build Coastguard Worker	if g, w := aModule.generateBuildActionsProviderValues, []string{"B"}; !reflect.DeepEqual(g, w) {
157*1fa6dee9SAndroid Build Coastguard Worker		t.Errorf("expected A.generateBuildActionsProviderValues %q, got %q", w, g)
158*1fa6dee9SAndroid Build Coastguard Worker	}
159*1fa6dee9SAndroid Build Coastguard Worker	if g, w := aModule.mutatorProviderValues, []string{"a", "b", "c", "d", "d"}; !reflect.DeepEqual(g, w) {
160*1fa6dee9SAndroid Build Coastguard Worker		t.Errorf("expected A.mutatorProviderValues %q, got %q", w, g)
161*1fa6dee9SAndroid Build Coastguard Worker	}
162*1fa6dee9SAndroid Build Coastguard Worker
163*1fa6dee9SAndroid Build Coastguard Worker	bModule := ctx.moduleGroupFromName("B", nil).moduleByVariantName("").logicModule.(*providerTestModule)
164*1fa6dee9SAndroid Build Coastguard Worker	if g, w := bModule.generateBuildActionsProviderValues, []string{"C", "D"}; !reflect.DeepEqual(g, w) {
165*1fa6dee9SAndroid Build Coastguard Worker		t.Errorf("expected B.generateBuildActionsProviderValues %q, got %q", w, g)
166*1fa6dee9SAndroid Build Coastguard Worker	}
167*1fa6dee9SAndroid Build Coastguard Worker	if g, w := bModule.mutatorProviderValues, []string{"b", "c", "d", "d"}; !reflect.DeepEqual(g, w) {
168*1fa6dee9SAndroid Build Coastguard Worker		t.Errorf("expected B.mutatorProviderValues %q, got %q", w, g)
169*1fa6dee9SAndroid Build Coastguard Worker	}
170*1fa6dee9SAndroid Build Coastguard Worker}
171*1fa6dee9SAndroid Build Coastguard Worker
172*1fa6dee9SAndroid Build Coastguard Workertype invalidProviderUsageMutatorInfo string
173*1fa6dee9SAndroid Build Coastguard Workertype invalidProviderUsageGenerateBuildActionsInfo string
174*1fa6dee9SAndroid Build Coastguard Worker
175*1fa6dee9SAndroid Build Coastguard Workervar invalidProviderUsageMutatorInfoProvider = NewMutatorProvider[invalidProviderUsageMutatorInfo]("mutator_under_test")
176*1fa6dee9SAndroid Build Coastguard Workervar invalidProviderUsageGenerateBuildActionsInfoProvider = NewProvider[invalidProviderUsageGenerateBuildActionsInfo]()
177*1fa6dee9SAndroid Build Coastguard Worker
178*1fa6dee9SAndroid Build Coastguard Workertype invalidProviderUsageTestModule struct {
179*1fa6dee9SAndroid Build Coastguard Worker	parent *invalidProviderUsageTestModule
180*1fa6dee9SAndroid Build Coastguard Worker
181*1fa6dee9SAndroid Build Coastguard Worker	SimpleName
182*1fa6dee9SAndroid Build Coastguard Worker	properties struct {
183*1fa6dee9SAndroid Build Coastguard Worker		Deps []string
184*1fa6dee9SAndroid Build Coastguard Worker
185*1fa6dee9SAndroid Build Coastguard Worker		Early_mutator_set_of_mutator_provider       bool
186*1fa6dee9SAndroid Build Coastguard Worker		Late_mutator_set_of_mutator_provider        bool
187*1fa6dee9SAndroid Build Coastguard Worker		Late_build_actions_set_of_mutator_provider  bool
188*1fa6dee9SAndroid Build Coastguard Worker		Early_mutator_set_of_build_actions_provider bool
189*1fa6dee9SAndroid Build Coastguard Worker
190*1fa6dee9SAndroid Build Coastguard Worker		Early_mutator_get_of_mutator_provider       bool
191*1fa6dee9SAndroid Build Coastguard Worker		Early_module_get_of_mutator_provider        bool
192*1fa6dee9SAndroid Build Coastguard Worker		Early_mutator_get_of_build_actions_provider bool
193*1fa6dee9SAndroid Build Coastguard Worker		Early_module_get_of_build_actions_provider  bool
194*1fa6dee9SAndroid Build Coastguard Worker
195*1fa6dee9SAndroid Build Coastguard Worker		Duplicate_set bool
196*1fa6dee9SAndroid Build Coastguard Worker	}
197*1fa6dee9SAndroid Build Coastguard Worker}
198*1fa6dee9SAndroid Build Coastguard Worker
199*1fa6dee9SAndroid Build Coastguard Workerfunc invalidProviderUsageDepsMutator(ctx BottomUpMutatorContext) {
200*1fa6dee9SAndroid Build Coastguard Worker	if i, ok := ctx.Module().(*invalidProviderUsageTestModule); ok {
201*1fa6dee9SAndroid Build Coastguard Worker		ctx.AddDependency(ctx.Module(), nil, i.properties.Deps...)
202*1fa6dee9SAndroid Build Coastguard Worker	}
203*1fa6dee9SAndroid Build Coastguard Worker}
204*1fa6dee9SAndroid Build Coastguard Worker
205*1fa6dee9SAndroid Build Coastguard Workerfunc invalidProviderUsageParentMutator(ctx TopDownMutatorContext) {
206*1fa6dee9SAndroid Build Coastguard Worker	if i, ok := ctx.Module().(*invalidProviderUsageTestModule); ok {
207*1fa6dee9SAndroid Build Coastguard Worker		ctx.VisitDirectDeps(func(module Module) {
208*1fa6dee9SAndroid Build Coastguard Worker			module.(*invalidProviderUsageTestModule).parent = i
209*1fa6dee9SAndroid Build Coastguard Worker		})
210*1fa6dee9SAndroid Build Coastguard Worker	}
211*1fa6dee9SAndroid Build Coastguard Worker}
212*1fa6dee9SAndroid Build Coastguard Worker
213*1fa6dee9SAndroid Build Coastguard Workerfunc invalidProviderUsageBeforeMutator(ctx BottomUpMutatorContext) {
214*1fa6dee9SAndroid Build Coastguard Worker	if i, ok := ctx.Module().(*invalidProviderUsageTestModule); ok {
215*1fa6dee9SAndroid Build Coastguard Worker		if i.properties.Early_mutator_set_of_mutator_provider {
216*1fa6dee9SAndroid Build Coastguard Worker			// A mutator attempting to set the value of a provider associated with a later mutator.
217*1fa6dee9SAndroid Build Coastguard Worker			SetProvider(ctx, invalidProviderUsageMutatorInfoProvider, invalidProviderUsageMutatorInfo(""))
218*1fa6dee9SAndroid Build Coastguard Worker		}
219*1fa6dee9SAndroid Build Coastguard Worker		if i.properties.Early_mutator_get_of_mutator_provider {
220*1fa6dee9SAndroid Build Coastguard Worker			// A mutator attempting to get the value of a provider associated with a later mutator.
221*1fa6dee9SAndroid Build Coastguard Worker			_, _ = ModuleProvider(ctx, invalidProviderUsageMutatorInfoProvider)
222*1fa6dee9SAndroid Build Coastguard Worker		}
223*1fa6dee9SAndroid Build Coastguard Worker	}
224*1fa6dee9SAndroid Build Coastguard Worker}
225*1fa6dee9SAndroid Build Coastguard Worker
226*1fa6dee9SAndroid Build Coastguard Workerfunc invalidProviderUsageMutatorUnderTest(ctx TopDownMutatorContext) {
227*1fa6dee9SAndroid Build Coastguard Worker	if i, ok := ctx.Module().(*invalidProviderUsageTestModule); ok {
228*1fa6dee9SAndroid Build Coastguard Worker		if i.properties.Early_mutator_set_of_build_actions_provider {
229*1fa6dee9SAndroid Build Coastguard Worker			// A mutator attempting to set the value of a non-mutator provider.
230*1fa6dee9SAndroid Build Coastguard Worker			SetProvider(ctx, invalidProviderUsageGenerateBuildActionsInfoProvider, invalidProviderUsageGenerateBuildActionsInfo(""))
231*1fa6dee9SAndroid Build Coastguard Worker		}
232*1fa6dee9SAndroid Build Coastguard Worker		if i.properties.Early_mutator_get_of_build_actions_provider {
233*1fa6dee9SAndroid Build Coastguard Worker			// A mutator attempting to get the value of a non-mutator provider.
234*1fa6dee9SAndroid Build Coastguard Worker			_, _ = ModuleProvider(ctx, invalidProviderUsageGenerateBuildActionsInfoProvider)
235*1fa6dee9SAndroid Build Coastguard Worker		}
236*1fa6dee9SAndroid Build Coastguard Worker		if i.properties.Early_module_get_of_mutator_provider {
237*1fa6dee9SAndroid Build Coastguard Worker			// A mutator attempting to get the value of a provider associated with this mutator on
238*1fa6dee9SAndroid Build Coastguard Worker			// a module for which this mutator hasn't run.  This is a top down mutator so
239*1fa6dee9SAndroid Build Coastguard Worker			// dependencies haven't run yet.
240*1fa6dee9SAndroid Build Coastguard Worker			ctx.VisitDirectDeps(func(module Module) {
241*1fa6dee9SAndroid Build Coastguard Worker				_, _ = OtherModuleProvider(ctx, module, invalidProviderUsageMutatorInfoProvider)
242*1fa6dee9SAndroid Build Coastguard Worker			})
243*1fa6dee9SAndroid Build Coastguard Worker		}
244*1fa6dee9SAndroid Build Coastguard Worker	}
245*1fa6dee9SAndroid Build Coastguard Worker}
246*1fa6dee9SAndroid Build Coastguard Worker
247*1fa6dee9SAndroid Build Coastguard Workerfunc invalidProviderUsageAfterMutator(ctx BottomUpMutatorContext) {
248*1fa6dee9SAndroid Build Coastguard Worker	if i, ok := ctx.Module().(*invalidProviderUsageTestModule); ok {
249*1fa6dee9SAndroid Build Coastguard Worker		if i.properties.Late_mutator_set_of_mutator_provider {
250*1fa6dee9SAndroid Build Coastguard Worker			// A mutator trying to set the value of a provider associated with an earlier mutator.
251*1fa6dee9SAndroid Build Coastguard Worker			SetProvider(ctx, invalidProviderUsageMutatorInfoProvider, invalidProviderUsageMutatorInfo(""))
252*1fa6dee9SAndroid Build Coastguard Worker		}
253*1fa6dee9SAndroid Build Coastguard Worker		if i.properties.Late_mutator_set_of_mutator_provider {
254*1fa6dee9SAndroid Build Coastguard Worker			// A mutator trying to set the value of a provider associated with an earlier mutator.
255*1fa6dee9SAndroid Build Coastguard Worker			SetProvider(ctx, invalidProviderUsageMutatorInfoProvider, invalidProviderUsageMutatorInfo(""))
256*1fa6dee9SAndroid Build Coastguard Worker		}
257*1fa6dee9SAndroid Build Coastguard Worker	}
258*1fa6dee9SAndroid Build Coastguard Worker}
259*1fa6dee9SAndroid Build Coastguard Worker
260*1fa6dee9SAndroid Build Coastguard Workerfunc (i *invalidProviderUsageTestModule) GenerateBuildActions(ctx ModuleContext) {
261*1fa6dee9SAndroid Build Coastguard Worker	if i.properties.Late_build_actions_set_of_mutator_provider {
262*1fa6dee9SAndroid Build Coastguard Worker		// A GenerateBuildActions trying to set the value of a provider associated with a mutator.
263*1fa6dee9SAndroid Build Coastguard Worker		SetProvider(ctx, invalidProviderUsageMutatorInfoProvider, invalidProviderUsageMutatorInfo(""))
264*1fa6dee9SAndroid Build Coastguard Worker	}
265*1fa6dee9SAndroid Build Coastguard Worker	if i.properties.Early_module_get_of_build_actions_provider {
266*1fa6dee9SAndroid Build Coastguard Worker		// A GenerateBuildActions trying to get the value of a provider on a module for which
267*1fa6dee9SAndroid Build Coastguard Worker		// GenerateBuildActions hasn't run.
268*1fa6dee9SAndroid Build Coastguard Worker		_, _ = OtherModuleProvider(ctx, i.parent, invalidProviderUsageGenerateBuildActionsInfoProvider)
269*1fa6dee9SAndroid Build Coastguard Worker	}
270*1fa6dee9SAndroid Build Coastguard Worker	if i.properties.Duplicate_set {
271*1fa6dee9SAndroid Build Coastguard Worker		SetProvider(ctx, invalidProviderUsageGenerateBuildActionsInfoProvider, invalidProviderUsageGenerateBuildActionsInfo(""))
272*1fa6dee9SAndroid Build Coastguard Worker		SetProvider(ctx, invalidProviderUsageGenerateBuildActionsInfoProvider, invalidProviderUsageGenerateBuildActionsInfo(""))
273*1fa6dee9SAndroid Build Coastguard Worker	}
274*1fa6dee9SAndroid Build Coastguard Worker}
275*1fa6dee9SAndroid Build Coastguard Worker
276*1fa6dee9SAndroid Build Coastguard Workerfunc TestInvalidProvidersUsage(t *testing.T) {
277*1fa6dee9SAndroid Build Coastguard Worker	run := func(t *testing.T, module string, prop string, panicMsg string) {
278*1fa6dee9SAndroid Build Coastguard Worker		t.Helper()
279*1fa6dee9SAndroid Build Coastguard Worker		ctx := NewContext()
280*1fa6dee9SAndroid Build Coastguard Worker		ctx.RegisterModuleType("invalid_provider_usage_test_module", func() (Module, []interface{}) {
281*1fa6dee9SAndroid Build Coastguard Worker			m := &invalidProviderUsageTestModule{}
282*1fa6dee9SAndroid Build Coastguard Worker			return m, []interface{}{&m.properties, &m.SimpleName.Properties}
283*1fa6dee9SAndroid Build Coastguard Worker		})
284*1fa6dee9SAndroid Build Coastguard Worker		ctx.RegisterBottomUpMutator("deps", invalidProviderUsageDepsMutator)
285*1fa6dee9SAndroid Build Coastguard Worker		ctx.RegisterBottomUpMutator("before", invalidProviderUsageBeforeMutator)
286*1fa6dee9SAndroid Build Coastguard Worker		ctx.RegisterTopDownMutator("mutator_under_test", invalidProviderUsageMutatorUnderTest)
287*1fa6dee9SAndroid Build Coastguard Worker		ctx.RegisterBottomUpMutator("after", invalidProviderUsageAfterMutator)
288*1fa6dee9SAndroid Build Coastguard Worker		ctx.RegisterTopDownMutator("parent", invalidProviderUsageParentMutator)
289*1fa6dee9SAndroid Build Coastguard Worker
290*1fa6dee9SAndroid Build Coastguard Worker		// Don't invalidate the parent pointer and before GenerateBuildActions.
291*1fa6dee9SAndroid Build Coastguard Worker		ctx.SkipCloneModulesAfterMutators = true
292*1fa6dee9SAndroid Build Coastguard Worker
293*1fa6dee9SAndroid Build Coastguard Worker		var parentBP, moduleUnderTestBP, childBP string
294*1fa6dee9SAndroid Build Coastguard Worker
295*1fa6dee9SAndroid Build Coastguard Worker		prop += ": true,"
296*1fa6dee9SAndroid Build Coastguard Worker
297*1fa6dee9SAndroid Build Coastguard Worker		switch module {
298*1fa6dee9SAndroid Build Coastguard Worker		case "parent":
299*1fa6dee9SAndroid Build Coastguard Worker			parentBP = prop
300*1fa6dee9SAndroid Build Coastguard Worker		case "module_under_test":
301*1fa6dee9SAndroid Build Coastguard Worker			moduleUnderTestBP = prop
302*1fa6dee9SAndroid Build Coastguard Worker		case "child":
303*1fa6dee9SAndroid Build Coastguard Worker			childBP = prop
304*1fa6dee9SAndroid Build Coastguard Worker		}
305*1fa6dee9SAndroid Build Coastguard Worker
306*1fa6dee9SAndroid Build Coastguard Worker		bp := fmt.Sprintf(`
307*1fa6dee9SAndroid Build Coastguard Worker			invalid_provider_usage_test_module {
308*1fa6dee9SAndroid Build Coastguard Worker				name: "parent",
309*1fa6dee9SAndroid Build Coastguard Worker				deps: ["module_under_test"],
310*1fa6dee9SAndroid Build Coastguard Worker				%s
311*1fa6dee9SAndroid Build Coastguard Worker			}
312*1fa6dee9SAndroid Build Coastguard Worker
313*1fa6dee9SAndroid Build Coastguard Worker			invalid_provider_usage_test_module {
314*1fa6dee9SAndroid Build Coastguard Worker				name: "module_under_test",
315*1fa6dee9SAndroid Build Coastguard Worker				deps: ["child"],
316*1fa6dee9SAndroid Build Coastguard Worker				%s
317*1fa6dee9SAndroid Build Coastguard Worker			}
318*1fa6dee9SAndroid Build Coastguard Worker
319*1fa6dee9SAndroid Build Coastguard Worker			invalid_provider_usage_test_module {
320*1fa6dee9SAndroid Build Coastguard Worker				name: "child",
321*1fa6dee9SAndroid Build Coastguard Worker				%s
322*1fa6dee9SAndroid Build Coastguard Worker			}
323*1fa6dee9SAndroid Build Coastguard Worker
324*1fa6dee9SAndroid Build Coastguard Worker		`,
325*1fa6dee9SAndroid Build Coastguard Worker			parentBP,
326*1fa6dee9SAndroid Build Coastguard Worker			moduleUnderTestBP,
327*1fa6dee9SAndroid Build Coastguard Worker			childBP)
328*1fa6dee9SAndroid Build Coastguard Worker
329*1fa6dee9SAndroid Build Coastguard Worker		ctx.MockFileSystem(map[string][]byte{
330*1fa6dee9SAndroid Build Coastguard Worker			"Android.bp": []byte(bp),
331*1fa6dee9SAndroid Build Coastguard Worker		})
332*1fa6dee9SAndroid Build Coastguard Worker
333*1fa6dee9SAndroid Build Coastguard Worker		_, errs := ctx.ParseBlueprintsFiles("Android.bp", nil)
334*1fa6dee9SAndroid Build Coastguard Worker
335*1fa6dee9SAndroid Build Coastguard Worker		if len(errs) == 0 {
336*1fa6dee9SAndroid Build Coastguard Worker			_, errs = ctx.ResolveDependencies(nil)
337*1fa6dee9SAndroid Build Coastguard Worker		}
338*1fa6dee9SAndroid Build Coastguard Worker
339*1fa6dee9SAndroid Build Coastguard Worker		if len(errs) == 0 {
340*1fa6dee9SAndroid Build Coastguard Worker			_, errs = ctx.PrepareBuildActions(nil)
341*1fa6dee9SAndroid Build Coastguard Worker		}
342*1fa6dee9SAndroid Build Coastguard Worker
343*1fa6dee9SAndroid Build Coastguard Worker		if len(errs) == 0 {
344*1fa6dee9SAndroid Build Coastguard Worker			t.Fatal("expected an error")
345*1fa6dee9SAndroid Build Coastguard Worker		}
346*1fa6dee9SAndroid Build Coastguard Worker
347*1fa6dee9SAndroid Build Coastguard Worker		if len(errs) > 1 {
348*1fa6dee9SAndroid Build Coastguard Worker			t.Errorf("expected a single error, got %d:", len(errs))
349*1fa6dee9SAndroid Build Coastguard Worker			for i, err := range errs {
350*1fa6dee9SAndroid Build Coastguard Worker				t.Errorf("%d:  %s", i, err)
351*1fa6dee9SAndroid Build Coastguard Worker			}
352*1fa6dee9SAndroid Build Coastguard Worker			t.FailNow()
353*1fa6dee9SAndroid Build Coastguard Worker		}
354*1fa6dee9SAndroid Build Coastguard Worker
355*1fa6dee9SAndroid Build Coastguard Worker		if panicErr, ok := errs[0].(panicError); ok {
356*1fa6dee9SAndroid Build Coastguard Worker			if panicErr.panic != panicMsg {
357*1fa6dee9SAndroid Build Coastguard Worker				t.Fatalf("expected panic %q, got %q", panicMsg, panicErr.panic)
358*1fa6dee9SAndroid Build Coastguard Worker			}
359*1fa6dee9SAndroid Build Coastguard Worker		} else {
360*1fa6dee9SAndroid Build Coastguard Worker			t.Fatalf("expected a panicError, got %T: %s", errs[0], errs[0].Error())
361*1fa6dee9SAndroid Build Coastguard Worker		}
362*1fa6dee9SAndroid Build Coastguard Worker
363*1fa6dee9SAndroid Build Coastguard Worker	}
364*1fa6dee9SAndroid Build Coastguard Worker
365*1fa6dee9SAndroid Build Coastguard Worker	tests := []struct {
366*1fa6dee9SAndroid Build Coastguard Worker		prop   string
367*1fa6dee9SAndroid Build Coastguard Worker		module string
368*1fa6dee9SAndroid Build Coastguard Worker
369*1fa6dee9SAndroid Build Coastguard Worker		panicMsg string
370*1fa6dee9SAndroid Build Coastguard Worker		skip     string
371*1fa6dee9SAndroid Build Coastguard Worker	}{
372*1fa6dee9SAndroid Build Coastguard Worker		{
373*1fa6dee9SAndroid Build Coastguard Worker			prop:     "early_mutator_set_of_mutator_provider",
374*1fa6dee9SAndroid Build Coastguard Worker			module:   "module_under_test",
375*1fa6dee9SAndroid Build Coastguard Worker			panicMsg: "Can't set value of provider blueprint.invalidProviderUsageMutatorInfo before mutator mutator_under_test started",
376*1fa6dee9SAndroid Build Coastguard Worker		},
377*1fa6dee9SAndroid Build Coastguard Worker		{
378*1fa6dee9SAndroid Build Coastguard Worker			prop:     "late_mutator_set_of_mutator_provider",
379*1fa6dee9SAndroid Build Coastguard Worker			module:   "module_under_test",
380*1fa6dee9SAndroid Build Coastguard Worker			panicMsg: "Can't set value of provider blueprint.invalidProviderUsageMutatorInfo after mutator mutator_under_test finished",
381*1fa6dee9SAndroid Build Coastguard Worker		},
382*1fa6dee9SAndroid Build Coastguard Worker		{
383*1fa6dee9SAndroid Build Coastguard Worker			prop:     "late_build_actions_set_of_mutator_provider",
384*1fa6dee9SAndroid Build Coastguard Worker			module:   "module_under_test",
385*1fa6dee9SAndroid Build Coastguard Worker			panicMsg: "Can't set value of provider blueprint.invalidProviderUsageMutatorInfo after mutator mutator_under_test finished",
386*1fa6dee9SAndroid Build Coastguard Worker		},
387*1fa6dee9SAndroid Build Coastguard Worker		{
388*1fa6dee9SAndroid Build Coastguard Worker			prop:     "early_mutator_set_of_build_actions_provider",
389*1fa6dee9SAndroid Build Coastguard Worker			module:   "module_under_test",
390*1fa6dee9SAndroid Build Coastguard Worker			panicMsg: "Can't set value of provider blueprint.invalidProviderUsageGenerateBuildActionsInfo before GenerateBuildActions started",
391*1fa6dee9SAndroid Build Coastguard Worker		},
392*1fa6dee9SAndroid Build Coastguard Worker
393*1fa6dee9SAndroid Build Coastguard Worker		{
394*1fa6dee9SAndroid Build Coastguard Worker			prop:     "early_mutator_get_of_mutator_provider",
395*1fa6dee9SAndroid Build Coastguard Worker			module:   "module_under_test",
396*1fa6dee9SAndroid Build Coastguard Worker			panicMsg: "Can't get value of provider blueprint.invalidProviderUsageMutatorInfo before mutator mutator_under_test finished",
397*1fa6dee9SAndroid Build Coastguard Worker		},
398*1fa6dee9SAndroid Build Coastguard Worker		{
399*1fa6dee9SAndroid Build Coastguard Worker			prop:     "early_module_get_of_mutator_provider",
400*1fa6dee9SAndroid Build Coastguard Worker			module:   "module_under_test",
401*1fa6dee9SAndroid Build Coastguard Worker			panicMsg: "Can't get value of provider blueprint.invalidProviderUsageMutatorInfo before mutator mutator_under_test finished",
402*1fa6dee9SAndroid Build Coastguard Worker		},
403*1fa6dee9SAndroid Build Coastguard Worker		{
404*1fa6dee9SAndroid Build Coastguard Worker			prop:     "early_mutator_get_of_build_actions_provider",
405*1fa6dee9SAndroid Build Coastguard Worker			module:   "module_under_test",
406*1fa6dee9SAndroid Build Coastguard Worker			panicMsg: "Can't get value of provider blueprint.invalidProviderUsageGenerateBuildActionsInfo before GenerateBuildActions finished",
407*1fa6dee9SAndroid Build Coastguard Worker		},
408*1fa6dee9SAndroid Build Coastguard Worker		{
409*1fa6dee9SAndroid Build Coastguard Worker			prop:     "early_module_get_of_build_actions_provider",
410*1fa6dee9SAndroid Build Coastguard Worker			module:   "module_under_test",
411*1fa6dee9SAndroid Build Coastguard Worker			panicMsg: "Can't get value of provider blueprint.invalidProviderUsageGenerateBuildActionsInfo before GenerateBuildActions finished",
412*1fa6dee9SAndroid Build Coastguard Worker		},
413*1fa6dee9SAndroid Build Coastguard Worker		{
414*1fa6dee9SAndroid Build Coastguard Worker			prop:     "duplicate_set",
415*1fa6dee9SAndroid Build Coastguard Worker			module:   "module_under_test",
416*1fa6dee9SAndroid Build Coastguard Worker			panicMsg: "Value of provider blueprint.invalidProviderUsageGenerateBuildActionsInfo is already set",
417*1fa6dee9SAndroid Build Coastguard Worker		},
418*1fa6dee9SAndroid Build Coastguard Worker	}
419*1fa6dee9SAndroid Build Coastguard Worker
420*1fa6dee9SAndroid Build Coastguard Worker	for _, tt := range tests {
421*1fa6dee9SAndroid Build Coastguard Worker		t.Run(tt.prop, func(t *testing.T) {
422*1fa6dee9SAndroid Build Coastguard Worker			run(t, tt.module, tt.prop, tt.panicMsg)
423*1fa6dee9SAndroid Build Coastguard Worker		})
424*1fa6dee9SAndroid Build Coastguard Worker	}
425*1fa6dee9SAndroid Build Coastguard Worker}
426