xref: /aosp_15_r20/build/blueprint/transition_test.go (revision 1fa6dee971e1612fa5cc0aa5ca2d35a22e2c34a3)
1*1fa6dee9SAndroid Build Coastguard Worker// Copyright 2024 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	"regexp"
20*1fa6dee9SAndroid Build Coastguard Worker	"slices"
21*1fa6dee9SAndroid Build Coastguard Worker	"strings"
22*1fa6dee9SAndroid Build Coastguard Worker	"testing"
23*1fa6dee9SAndroid Build Coastguard Worker)
24*1fa6dee9SAndroid Build Coastguard Worker
25*1fa6dee9SAndroid Build Coastguard Workerfunc testTransitionCommon(bp string, neverFar bool, ctxHook func(*Context)) (*Context, []error) {
26*1fa6dee9SAndroid Build Coastguard Worker	ctx := newContext()
27*1fa6dee9SAndroid Build Coastguard Worker	ctx.MockFileSystem(map[string][]byte{
28*1fa6dee9SAndroid Build Coastguard Worker		"Android.bp": []byte(bp),
29*1fa6dee9SAndroid Build Coastguard Worker	})
30*1fa6dee9SAndroid Build Coastguard Worker
31*1fa6dee9SAndroid Build Coastguard Worker	ctx.RegisterBottomUpMutator("deps", depsMutator)
32*1fa6dee9SAndroid Build Coastguard Worker	handle := ctx.RegisterTransitionMutator("transition", transitionTestMutator{})
33*1fa6dee9SAndroid Build Coastguard Worker	if neverFar {
34*1fa6dee9SAndroid Build Coastguard Worker		handle.NeverFar()
35*1fa6dee9SAndroid Build Coastguard Worker	}
36*1fa6dee9SAndroid Build Coastguard Worker	ctx.RegisterBottomUpMutator("post_transition_deps", postTransitionDepsMutator).UsesReverseDependencies()
37*1fa6dee9SAndroid Build Coastguard Worker
38*1fa6dee9SAndroid Build Coastguard Worker	ctx.RegisterModuleType("transition_module", newTransitionModule)
39*1fa6dee9SAndroid Build Coastguard Worker
40*1fa6dee9SAndroid Build Coastguard Worker	if ctxHook != nil {
41*1fa6dee9SAndroid Build Coastguard Worker		ctxHook(ctx)
42*1fa6dee9SAndroid Build Coastguard Worker	}
43*1fa6dee9SAndroid Build Coastguard Worker
44*1fa6dee9SAndroid Build Coastguard Worker	_, errs := ctx.ParseBlueprintsFiles("Android.bp", nil)
45*1fa6dee9SAndroid Build Coastguard Worker	if len(errs) > 0 {
46*1fa6dee9SAndroid Build Coastguard Worker		return nil, errs
47*1fa6dee9SAndroid Build Coastguard Worker	}
48*1fa6dee9SAndroid Build Coastguard Worker
49*1fa6dee9SAndroid Build Coastguard Worker	_, errs = ctx.ResolveDependencies(nil)
50*1fa6dee9SAndroid Build Coastguard Worker	if len(errs) > 0 {
51*1fa6dee9SAndroid Build Coastguard Worker		return nil, errs
52*1fa6dee9SAndroid Build Coastguard Worker	}
53*1fa6dee9SAndroid Build Coastguard Worker
54*1fa6dee9SAndroid Build Coastguard Worker	return ctx, nil
55*1fa6dee9SAndroid Build Coastguard Worker}
56*1fa6dee9SAndroid Build Coastguard Worker
57*1fa6dee9SAndroid Build Coastguard Workerfunc testTransition(bp string) (*Context, []error) {
58*1fa6dee9SAndroid Build Coastguard Worker	return testTransitionCommon(bp, false, nil)
59*1fa6dee9SAndroid Build Coastguard Worker}
60*1fa6dee9SAndroid Build Coastguard Worker
61*1fa6dee9SAndroid Build Coastguard Workerfunc testTransitionNeverFar(bp string) (*Context, []error) {
62*1fa6dee9SAndroid Build Coastguard Worker	return testTransitionCommon(bp, true, nil)
63*1fa6dee9SAndroid Build Coastguard Worker}
64*1fa6dee9SAndroid Build Coastguard Worker
65*1fa6dee9SAndroid Build Coastguard Workerfunc testTransitionAllowMissingDeps(bp string) (*Context, []error) {
66*1fa6dee9SAndroid Build Coastguard Worker	return testTransitionCommon(bp, false, func(ctx *Context) {
67*1fa6dee9SAndroid Build Coastguard Worker		ctx.SetAllowMissingDependencies(true)
68*1fa6dee9SAndroid Build Coastguard Worker	})
69*1fa6dee9SAndroid Build Coastguard Worker}
70*1fa6dee9SAndroid Build Coastguard Worker
71*1fa6dee9SAndroid Build Coastguard Workerfunc assertNoErrors(t *testing.T, errs []error) {
72*1fa6dee9SAndroid Build Coastguard Worker	t.Helper()
73*1fa6dee9SAndroid Build Coastguard Worker	if len(errs) > 0 {
74*1fa6dee9SAndroid Build Coastguard Worker		t.Errorf("unexpected errors:")
75*1fa6dee9SAndroid Build Coastguard Worker		for _, err := range errs {
76*1fa6dee9SAndroid Build Coastguard Worker			t.Errorf("  %s", err)
77*1fa6dee9SAndroid Build Coastguard Worker		}
78*1fa6dee9SAndroid Build Coastguard Worker		t.FailNow()
79*1fa6dee9SAndroid Build Coastguard Worker	}
80*1fa6dee9SAndroid Build Coastguard Worker}
81*1fa6dee9SAndroid Build Coastguard Worker
82*1fa6dee9SAndroid Build Coastguard Workerfunc assertOneErrorMatches(t *testing.T, errs []error, re string) {
83*1fa6dee9SAndroid Build Coastguard Worker	t.Helper()
84*1fa6dee9SAndroid Build Coastguard Worker	if len(errs) == 0 {
85*1fa6dee9SAndroid Build Coastguard Worker		t.Fatalf("expected 1 error, but found 0")
86*1fa6dee9SAndroid Build Coastguard Worker	}
87*1fa6dee9SAndroid Build Coastguard Worker	if len(errs) > 1 {
88*1fa6dee9SAndroid Build Coastguard Worker		t.Errorf("expected exactly 1 error, but found:")
89*1fa6dee9SAndroid Build Coastguard Worker		for _, err := range errs {
90*1fa6dee9SAndroid Build Coastguard Worker			t.Errorf("  %s", err)
91*1fa6dee9SAndroid Build Coastguard Worker		}
92*1fa6dee9SAndroid Build Coastguard Worker		t.FailNow()
93*1fa6dee9SAndroid Build Coastguard Worker	}
94*1fa6dee9SAndroid Build Coastguard Worker	if match, err := regexp.MatchString(re, errs[0].Error()); err != nil {
95*1fa6dee9SAndroid Build Coastguard Worker		t.Fatal(err.Error())
96*1fa6dee9SAndroid Build Coastguard Worker	} else if !match {
97*1fa6dee9SAndroid Build Coastguard Worker		t.Fatalf("expected error matching %q, but got: %q", re, errs[0].Error())
98*1fa6dee9SAndroid Build Coastguard Worker	}
99*1fa6dee9SAndroid Build Coastguard Worker}
100*1fa6dee9SAndroid Build Coastguard Worker
101*1fa6dee9SAndroid Build Coastguard Workerconst testTransitionBp = `
102*1fa6dee9SAndroid Build Coastguard Worker			transition_module {
103*1fa6dee9SAndroid Build Coastguard Worker			    name: "A",
104*1fa6dee9SAndroid Build Coastguard Worker			    deps: ["B", "C"],
105*1fa6dee9SAndroid Build Coastguard Worker				split: ["b", "a"],
106*1fa6dee9SAndroid Build Coastguard Worker			}
107*1fa6dee9SAndroid Build Coastguard Worker
108*1fa6dee9SAndroid Build Coastguard Worker			transition_module {
109*1fa6dee9SAndroid Build Coastguard Worker				name: "B",
110*1fa6dee9SAndroid Build Coastguard Worker				deps: ["C"],
111*1fa6dee9SAndroid Build Coastguard Worker				outgoing: "c",
112*1fa6dee9SAndroid Build Coastguard Worker				%s
113*1fa6dee9SAndroid Build Coastguard Worker			}
114*1fa6dee9SAndroid Build Coastguard Worker
115*1fa6dee9SAndroid Build Coastguard Worker			transition_module {
116*1fa6dee9SAndroid Build Coastguard Worker				name: "C",
117*1fa6dee9SAndroid Build Coastguard Worker				deps: ["D"],
118*1fa6dee9SAndroid Build Coastguard Worker			}
119*1fa6dee9SAndroid Build Coastguard Worker
120*1fa6dee9SAndroid Build Coastguard Worker			transition_module {
121*1fa6dee9SAndroid Build Coastguard Worker				name: "D",
122*1fa6dee9SAndroid Build Coastguard Worker				incoming: "d",
123*1fa6dee9SAndroid Build Coastguard Worker				deps: ["E"],
124*1fa6dee9SAndroid Build Coastguard Worker			}
125*1fa6dee9SAndroid Build Coastguard Worker
126*1fa6dee9SAndroid Build Coastguard Worker			transition_module {
127*1fa6dee9SAndroid Build Coastguard Worker				name: "E",
128*1fa6dee9SAndroid Build Coastguard Worker			}
129*1fa6dee9SAndroid Build Coastguard Worker
130*1fa6dee9SAndroid Build Coastguard Worker			transition_module {
131*1fa6dee9SAndroid Build Coastguard Worker				name: "F",
132*1fa6dee9SAndroid Build Coastguard Worker				incoming: "",
133*1fa6dee9SAndroid Build Coastguard Worker			}
134*1fa6dee9SAndroid Build Coastguard Worker
135*1fa6dee9SAndroid Build Coastguard Worker			transition_module {
136*1fa6dee9SAndroid Build Coastguard Worker				name: "G",
137*1fa6dee9SAndroid Build Coastguard Worker				outgoing: "h",
138*1fa6dee9SAndroid Build Coastguard Worker				%s
139*1fa6dee9SAndroid Build Coastguard Worker			}
140*1fa6dee9SAndroid Build Coastguard Worker
141*1fa6dee9SAndroid Build Coastguard Worker			transition_module {
142*1fa6dee9SAndroid Build Coastguard Worker				name: "H",
143*1fa6dee9SAndroid Build Coastguard Worker				split: ["h"],
144*1fa6dee9SAndroid Build Coastguard Worker			}
145*1fa6dee9SAndroid Build Coastguard Worker		`
146*1fa6dee9SAndroid Build Coastguard Worker
147*1fa6dee9SAndroid Build Coastguard Workerfunc getTransitionModule(ctx *Context, name, variant string) *transitionModule {
148*1fa6dee9SAndroid Build Coastguard Worker	group := ctx.moduleGroupFromName(name, nil)
149*1fa6dee9SAndroid Build Coastguard Worker	module := group.moduleByVariantName(variant)
150*1fa6dee9SAndroid Build Coastguard Worker	return module.logicModule.(*transitionModule)
151*1fa6dee9SAndroid Build Coastguard Worker}
152*1fa6dee9SAndroid Build Coastguard Worker
153*1fa6dee9SAndroid Build Coastguard Workerfunc checkTransitionVariants(t *testing.T, ctx *Context, name string, expectedVariants []string) {
154*1fa6dee9SAndroid Build Coastguard Worker	t.Helper()
155*1fa6dee9SAndroid Build Coastguard Worker	group := ctx.moduleGroupFromName(name, nil)
156*1fa6dee9SAndroid Build Coastguard Worker	var gotVariants []string
157*1fa6dee9SAndroid Build Coastguard Worker	for _, module := range group.modules {
158*1fa6dee9SAndroid Build Coastguard Worker		gotVariants = append(gotVariants, module.variant.variations.get("transition"))
159*1fa6dee9SAndroid Build Coastguard Worker	}
160*1fa6dee9SAndroid Build Coastguard Worker	if !slices.Equal(expectedVariants, gotVariants) {
161*1fa6dee9SAndroid Build Coastguard Worker		t.Errorf("expected variants of %q to be %q, got %q", name, expectedVariants, gotVariants)
162*1fa6dee9SAndroid Build Coastguard Worker	}
163*1fa6dee9SAndroid Build Coastguard Worker}
164*1fa6dee9SAndroid Build Coastguard Worker
165*1fa6dee9SAndroid Build Coastguard Workerfunc checkTransitionDeps(t *testing.T, ctx *Context, m Module, expected ...string) {
166*1fa6dee9SAndroid Build Coastguard Worker	t.Helper()
167*1fa6dee9SAndroid Build Coastguard Worker	var got []string
168*1fa6dee9SAndroid Build Coastguard Worker	ctx.VisitDirectDeps(m, func(m Module) {
169*1fa6dee9SAndroid Build Coastguard Worker		got = append(got, ctx.ModuleName(m)+"("+ctx.ModuleSubDir(m)+")")
170*1fa6dee9SAndroid Build Coastguard Worker	})
171*1fa6dee9SAndroid Build Coastguard Worker	if !slices.Equal(got, expected) {
172*1fa6dee9SAndroid Build Coastguard Worker		t.Errorf("unexpected %q dependencies, got %q expected %q",
173*1fa6dee9SAndroid Build Coastguard Worker			ctx.ModuleName(m), got, expected)
174*1fa6dee9SAndroid Build Coastguard Worker	}
175*1fa6dee9SAndroid Build Coastguard Worker}
176*1fa6dee9SAndroid Build Coastguard Worker
177*1fa6dee9SAndroid Build Coastguard Workerfunc checkTransitionMutate(t *testing.T, m *transitionModule, variant string) {
178*1fa6dee9SAndroid Build Coastguard Worker	t.Helper()
179*1fa6dee9SAndroid Build Coastguard Worker	if m.properties.Mutated != variant {
180*1fa6dee9SAndroid Build Coastguard Worker		t.Errorf("unexpected mutated property in %q, expected %q got %q", m.Name(), variant, m.properties.Mutated)
181*1fa6dee9SAndroid Build Coastguard Worker	}
182*1fa6dee9SAndroid Build Coastguard Worker}
183*1fa6dee9SAndroid Build Coastguard Worker
184*1fa6dee9SAndroid Build Coastguard Workerfunc TestTransition(t *testing.T) {
185*1fa6dee9SAndroid Build Coastguard Worker	ctx, errs := testTransition(fmt.Sprintf(testTransitionBp, "", ""))
186*1fa6dee9SAndroid Build Coastguard Worker	assertNoErrors(t, errs)
187*1fa6dee9SAndroid Build Coastguard Worker
188*1fa6dee9SAndroid Build Coastguard Worker	// Module A uses Split to create a and b variants
189*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionVariants(t, ctx, "A", []string{"b", "a"})
190*1fa6dee9SAndroid Build Coastguard Worker	// Module B inherits a and b variants from A
191*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionVariants(t, ctx, "B", []string{"", "a", "b"})
192*1fa6dee9SAndroid Build Coastguard Worker	// Module C inherits a and b variants from A, but gets an outgoing c variant from B
193*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionVariants(t, ctx, "C", []string{"", "a", "b", "c"})
194*1fa6dee9SAndroid Build Coastguard Worker	// Module D always has incoming variant d
195*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionVariants(t, ctx, "D", []string{"", "d"})
196*1fa6dee9SAndroid Build Coastguard Worker	// Module E inherits d from D
197*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionVariants(t, ctx, "E", []string{"", "d"})
198*1fa6dee9SAndroid Build Coastguard Worker	// Module F is untouched
199*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionVariants(t, ctx, "F", []string{""})
200*1fa6dee9SAndroid Build Coastguard Worker
201*1fa6dee9SAndroid Build Coastguard Worker	A_a := getTransitionModule(ctx, "A", "a")
202*1fa6dee9SAndroid Build Coastguard Worker	A_b := getTransitionModule(ctx, "A", "b")
203*1fa6dee9SAndroid Build Coastguard Worker	B_a := getTransitionModule(ctx, "B", "a")
204*1fa6dee9SAndroid Build Coastguard Worker	B_b := getTransitionModule(ctx, "B", "b")
205*1fa6dee9SAndroid Build Coastguard Worker	C_a := getTransitionModule(ctx, "C", "a")
206*1fa6dee9SAndroid Build Coastguard Worker	C_b := getTransitionModule(ctx, "C", "b")
207*1fa6dee9SAndroid Build Coastguard Worker	C_c := getTransitionModule(ctx, "C", "c")
208*1fa6dee9SAndroid Build Coastguard Worker	D_d := getTransitionModule(ctx, "D", "d")
209*1fa6dee9SAndroid Build Coastguard Worker	E_d := getTransitionModule(ctx, "E", "d")
210*1fa6dee9SAndroid Build Coastguard Worker	F := getTransitionModule(ctx, "F", "")
211*1fa6dee9SAndroid Build Coastguard Worker	G := getTransitionModule(ctx, "G", "")
212*1fa6dee9SAndroid Build Coastguard Worker	H_h := getTransitionModule(ctx, "H", "h")
213*1fa6dee9SAndroid Build Coastguard Worker
214*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionDeps(t, ctx, A_a, "B(a)", "C(a)")
215*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionDeps(t, ctx, A_b, "B(b)", "C(b)")
216*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionDeps(t, ctx, B_a, "C(c)")
217*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionDeps(t, ctx, B_b, "C(c)")
218*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionDeps(t, ctx, C_a, "D(d)")
219*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionDeps(t, ctx, C_b, "D(d)")
220*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionDeps(t, ctx, C_c, "D(d)")
221*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionDeps(t, ctx, D_d, "E(d)")
222*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionDeps(t, ctx, E_d)
223*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionDeps(t, ctx, F)
224*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionDeps(t, ctx, G)
225*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionDeps(t, ctx, H_h)
226*1fa6dee9SAndroid Build Coastguard Worker
227*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionMutate(t, A_a, "a")
228*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionMutate(t, A_b, "b")
229*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionMutate(t, B_a, "a")
230*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionMutate(t, B_b, "b")
231*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionMutate(t, C_a, "a")
232*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionMutate(t, C_b, "b")
233*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionMutate(t, C_c, "c")
234*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionMutate(t, D_d, "d")
235*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionMutate(t, E_d, "d")
236*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionMutate(t, F, "")
237*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionMutate(t, G, "")
238*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionMutate(t, H_h, "h")
239*1fa6dee9SAndroid Build Coastguard Worker}
240*1fa6dee9SAndroid Build Coastguard Worker
241*1fa6dee9SAndroid Build Coastguard Workerfunc TestPostTransitionDeps(t *testing.T) {
242*1fa6dee9SAndroid Build Coastguard Worker	ctx, errs := testTransition(fmt.Sprintf(testTransitionBp,
243*1fa6dee9SAndroid Build Coastguard Worker		`post_transition_deps: ["C", "D:late", "E:d", "F"],`,
244*1fa6dee9SAndroid Build Coastguard Worker		`post_transition_deps: ["H"],`))
245*1fa6dee9SAndroid Build Coastguard Worker	assertNoErrors(t, errs)
246*1fa6dee9SAndroid Build Coastguard Worker
247*1fa6dee9SAndroid Build Coastguard Worker	// Module A uses Split to create a and b variants
248*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionVariants(t, ctx, "A", []string{"b", "a"})
249*1fa6dee9SAndroid Build Coastguard Worker	// Module B inherits a and b variants from A
250*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionVariants(t, ctx, "B", []string{"", "a", "b"})
251*1fa6dee9SAndroid Build Coastguard Worker	// Module C inherits a and b variants from A, but gets an outgoing c variant from B
252*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionVariants(t, ctx, "C", []string{"", "a", "b", "c"})
253*1fa6dee9SAndroid Build Coastguard Worker	// Module D always has incoming variant d
254*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionVariants(t, ctx, "D", []string{"", "d"})
255*1fa6dee9SAndroid Build Coastguard Worker	// Module E inherits d from D
256*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionVariants(t, ctx, "E", []string{"", "d"})
257*1fa6dee9SAndroid Build Coastguard Worker	// Module F is untouched
258*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionVariants(t, ctx, "F", []string{""})
259*1fa6dee9SAndroid Build Coastguard Worker
260*1fa6dee9SAndroid Build Coastguard Worker	A_a := getTransitionModule(ctx, "A", "a")
261*1fa6dee9SAndroid Build Coastguard Worker	A_b := getTransitionModule(ctx, "A", "b")
262*1fa6dee9SAndroid Build Coastguard Worker	B_a := getTransitionModule(ctx, "B", "a")
263*1fa6dee9SAndroid Build Coastguard Worker	B_b := getTransitionModule(ctx, "B", "b")
264*1fa6dee9SAndroid Build Coastguard Worker	C_a := getTransitionModule(ctx, "C", "a")
265*1fa6dee9SAndroid Build Coastguard Worker	C_b := getTransitionModule(ctx, "C", "b")
266*1fa6dee9SAndroid Build Coastguard Worker	C_c := getTransitionModule(ctx, "C", "c")
267*1fa6dee9SAndroid Build Coastguard Worker	D_d := getTransitionModule(ctx, "D", "d")
268*1fa6dee9SAndroid Build Coastguard Worker	E_d := getTransitionModule(ctx, "E", "d")
269*1fa6dee9SAndroid Build Coastguard Worker	F := getTransitionModule(ctx, "F", "")
270*1fa6dee9SAndroid Build Coastguard Worker	G := getTransitionModule(ctx, "G", "")
271*1fa6dee9SAndroid Build Coastguard Worker	H_h := getTransitionModule(ctx, "H", "h")
272*1fa6dee9SAndroid Build Coastguard Worker
273*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionDeps(t, ctx, A_a, "B(a)", "C(a)")
274*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionDeps(t, ctx, A_b, "B(b)", "C(b)")
275*1fa6dee9SAndroid Build Coastguard Worker	// Verify post-mutator dependencies added to B.  The first C(c) is a pre-mutator dependency.
276*1fa6dee9SAndroid Build Coastguard Worker	//  C(c) was added by C and rewritten by OutgoingTransition on B
277*1fa6dee9SAndroid Build Coastguard Worker	//  D(d) was added by D:late and rewritten by IncomingTransition on D
278*1fa6dee9SAndroid Build Coastguard Worker	//  E(d) was added by E:d
279*1fa6dee9SAndroid Build Coastguard Worker	//  F() was added by F and rewritten OutgoingTransition on B and then IncomingTransition on F
280*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionDeps(t, ctx, B_a, "C(c)", "C(c)", "D(d)", "E(d)", "F()")
281*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionDeps(t, ctx, B_b, "C(c)", "C(c)", "D(d)", "E(d)", "F()")
282*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionDeps(t, ctx, C_a, "D(d)")
283*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionDeps(t, ctx, C_b, "D(d)")
284*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionDeps(t, ctx, C_c, "D(d)")
285*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionDeps(t, ctx, D_d, "E(d)")
286*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionDeps(t, ctx, E_d)
287*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionDeps(t, ctx, F)
288*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionDeps(t, ctx, G, "H(h)")
289*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionDeps(t, ctx, H_h)
290*1fa6dee9SAndroid Build Coastguard Worker
291*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionMutate(t, A_a, "a")
292*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionMutate(t, A_b, "b")
293*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionMutate(t, B_a, "a")
294*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionMutate(t, B_b, "b")
295*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionMutate(t, C_a, "a")
296*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionMutate(t, C_b, "b")
297*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionMutate(t, C_c, "c")
298*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionMutate(t, D_d, "d")
299*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionMutate(t, E_d, "d")
300*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionMutate(t, F, "")
301*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionMutate(t, G, "")
302*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionMutate(t, H_h, "h")
303*1fa6dee9SAndroid Build Coastguard Worker}
304*1fa6dee9SAndroid Build Coastguard Worker
305*1fa6dee9SAndroid Build Coastguard Workerfunc TestPostTransitionReverseDeps(t *testing.T) {
306*1fa6dee9SAndroid Build Coastguard Worker	ctx, errs := testTransition(`
307*1fa6dee9SAndroid Build Coastguard Worker		transition_module {
308*1fa6dee9SAndroid Build Coastguard Worker			name: "A",
309*1fa6dee9SAndroid Build Coastguard Worker			split: ["a1", "a2"],
310*1fa6dee9SAndroid Build Coastguard Worker		}
311*1fa6dee9SAndroid Build Coastguard Worker
312*1fa6dee9SAndroid Build Coastguard Worker		transition_module {
313*1fa6dee9SAndroid Build Coastguard Worker			name: "B",
314*1fa6dee9SAndroid Build Coastguard Worker			split: ["a1", "a2"],
315*1fa6dee9SAndroid Build Coastguard Worker			post_transition_reverse_deps: ["A"],
316*1fa6dee9SAndroid Build Coastguard Worker		}
317*1fa6dee9SAndroid Build Coastguard Worker	`)
318*1fa6dee9SAndroid Build Coastguard Worker	assertNoErrors(t, errs)
319*1fa6dee9SAndroid Build Coastguard Worker
320*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionVariants(t, ctx, "A", []string{"a1", "a2"})
321*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionVariants(t, ctx, "B", []string{"a1", "a2"})
322*1fa6dee9SAndroid Build Coastguard Worker
323*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionDeps(t, ctx, getTransitionModule(ctx, "A", "a1"), "B(a1)")
324*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionDeps(t, ctx, getTransitionModule(ctx, "A", "a2"), "B(a2)")
325*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionDeps(t, ctx, getTransitionModule(ctx, "B", "a1"))
326*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionDeps(t, ctx, getTransitionModule(ctx, "B", "a2"))
327*1fa6dee9SAndroid Build Coastguard Worker}
328*1fa6dee9SAndroid Build Coastguard Worker
329*1fa6dee9SAndroid Build Coastguard Workerfunc TestPostTransitionReverseVariationDeps(t *testing.T) {
330*1fa6dee9SAndroid Build Coastguard Worker	ctx, errs := testTransition(`
331*1fa6dee9SAndroid Build Coastguard Worker		transition_module {
332*1fa6dee9SAndroid Build Coastguard Worker			name: "A",
333*1fa6dee9SAndroid Build Coastguard Worker			split: ["a"],
334*1fa6dee9SAndroid Build Coastguard Worker		}
335*1fa6dee9SAndroid Build Coastguard Worker
336*1fa6dee9SAndroid Build Coastguard Worker		transition_module {
337*1fa6dee9SAndroid Build Coastguard Worker			name: "B",
338*1fa6dee9SAndroid Build Coastguard Worker			split: ["b"],
339*1fa6dee9SAndroid Build Coastguard Worker			post_transition_reverse_variation_deps: ["A(a)"],
340*1fa6dee9SAndroid Build Coastguard Worker		}
341*1fa6dee9SAndroid Build Coastguard Worker	`)
342*1fa6dee9SAndroid Build Coastguard Worker	assertNoErrors(t, errs)
343*1fa6dee9SAndroid Build Coastguard Worker
344*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionVariants(t, ctx, "A", []string{"a"})
345*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionVariants(t, ctx, "B", []string{"b"})
346*1fa6dee9SAndroid Build Coastguard Worker
347*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionDeps(t, ctx, getTransitionModule(ctx, "A", "a"), "B(b)")
348*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionDeps(t, ctx, getTransitionModule(ctx, "B", "b"))
349*1fa6dee9SAndroid Build Coastguard Worker}
350*1fa6dee9SAndroid Build Coastguard Worker
351*1fa6dee9SAndroid Build Coastguard Workerfunc TestFarVariationDep(t *testing.T) {
352*1fa6dee9SAndroid Build Coastguard Worker	ctx, errs := testTransition(`
353*1fa6dee9SAndroid Build Coastguard Worker		transition_module {
354*1fa6dee9SAndroid Build Coastguard Worker			name: "A",
355*1fa6dee9SAndroid Build Coastguard Worker			split: ["a"],
356*1fa6dee9SAndroid Build Coastguard Worker			deps: ["B"],
357*1fa6dee9SAndroid Build Coastguard Worker		}
358*1fa6dee9SAndroid Build Coastguard Worker		transition_module {
359*1fa6dee9SAndroid Build Coastguard Worker			name: "B",
360*1fa6dee9SAndroid Build Coastguard Worker			split: ["", "a"],
361*1fa6dee9SAndroid Build Coastguard Worker		}
362*1fa6dee9SAndroid Build Coastguard Worker		transition_module {
363*1fa6dee9SAndroid Build Coastguard Worker			name: "C",
364*1fa6dee9SAndroid Build Coastguard Worker			split: ["c"],
365*1fa6dee9SAndroid Build Coastguard Worker			post_transition_far_deps: ["D"],
366*1fa6dee9SAndroid Build Coastguard Worker		}
367*1fa6dee9SAndroid Build Coastguard Worker		transition_module {
368*1fa6dee9SAndroid Build Coastguard Worker			name: "D",
369*1fa6dee9SAndroid Build Coastguard Worker			split: ["", "c"],
370*1fa6dee9SAndroid Build Coastguard Worker		}
371*1fa6dee9SAndroid Build Coastguard Worker	`)
372*1fa6dee9SAndroid Build Coastguard Worker	assertNoErrors(t, errs)
373*1fa6dee9SAndroid Build Coastguard Worker
374*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionVariants(t, ctx, "A", []string{"a"})
375*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionVariants(t, ctx, "B", []string{"", "a"})
376*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionVariants(t, ctx, "C", []string{"c"})
377*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionVariants(t, ctx, "D", []string{"", "c"})
378*1fa6dee9SAndroid Build Coastguard Worker
379*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionDeps(t, ctx, getTransitionModule(ctx, "A", "a"), "B(a)")
380*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionDeps(t, ctx, getTransitionModule(ctx, "C", "c"), "D()")
381*1fa6dee9SAndroid Build Coastguard Worker}
382*1fa6dee9SAndroid Build Coastguard Worker
383*1fa6dee9SAndroid Build Coastguard Workerfunc TestNeverFarFarVariationDep(t *testing.T) {
384*1fa6dee9SAndroid Build Coastguard Worker	ctx, errs := testTransitionNeverFar(`
385*1fa6dee9SAndroid Build Coastguard Worker		transition_module {
386*1fa6dee9SAndroid Build Coastguard Worker			name: "A",
387*1fa6dee9SAndroid Build Coastguard Worker			split: ["a"],
388*1fa6dee9SAndroid Build Coastguard Worker			deps: ["B"],
389*1fa6dee9SAndroid Build Coastguard Worker		}
390*1fa6dee9SAndroid Build Coastguard Worker		transition_module {
391*1fa6dee9SAndroid Build Coastguard Worker			name: "B",
392*1fa6dee9SAndroid Build Coastguard Worker			split: ["", "a"],
393*1fa6dee9SAndroid Build Coastguard Worker		}
394*1fa6dee9SAndroid Build Coastguard Worker		transition_module {
395*1fa6dee9SAndroid Build Coastguard Worker			name: "C",
396*1fa6dee9SAndroid Build Coastguard Worker			split: ["c"],
397*1fa6dee9SAndroid Build Coastguard Worker			post_transition_far_deps: ["D"],
398*1fa6dee9SAndroid Build Coastguard Worker		}
399*1fa6dee9SAndroid Build Coastguard Worker		transition_module {
400*1fa6dee9SAndroid Build Coastguard Worker			name: "D",
401*1fa6dee9SAndroid Build Coastguard Worker			split: ["", "c"],
402*1fa6dee9SAndroid Build Coastguard Worker		}
403*1fa6dee9SAndroid Build Coastguard Worker	`)
404*1fa6dee9SAndroid Build Coastguard Worker	assertNoErrors(t, errs)
405*1fa6dee9SAndroid Build Coastguard Worker
406*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionVariants(t, ctx, "A", []string{"a"})
407*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionVariants(t, ctx, "B", []string{"", "a"})
408*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionVariants(t, ctx, "C", []string{"c"})
409*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionVariants(t, ctx, "D", []string{"", "c"})
410*1fa6dee9SAndroid Build Coastguard Worker
411*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionDeps(t, ctx, getTransitionModule(ctx, "A", "a"), "B(a)")
412*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionDeps(t, ctx, getTransitionModule(ctx, "C", "c"), "D(c)")
413*1fa6dee9SAndroid Build Coastguard Worker}
414*1fa6dee9SAndroid Build Coastguard Worker
415*1fa6dee9SAndroid Build Coastguard Workerfunc TestPostTransitionReverseDepsErrorOnMissingDep(t *testing.T) {
416*1fa6dee9SAndroid Build Coastguard Worker	_, errs := testTransition(`
417*1fa6dee9SAndroid Build Coastguard Worker		transition_module {
418*1fa6dee9SAndroid Build Coastguard Worker			name: "A",
419*1fa6dee9SAndroid Build Coastguard Worker			split: ["a"],
420*1fa6dee9SAndroid Build Coastguard Worker		}
421*1fa6dee9SAndroid Build Coastguard Worker
422*1fa6dee9SAndroid Build Coastguard Worker		transition_module {
423*1fa6dee9SAndroid Build Coastguard Worker			name: "B",
424*1fa6dee9SAndroid Build Coastguard Worker			split: ["b"],
425*1fa6dee9SAndroid Build Coastguard Worker			post_transition_reverse_deps: ["A"],
426*1fa6dee9SAndroid Build Coastguard Worker		}
427*1fa6dee9SAndroid Build Coastguard Worker	`)
428*1fa6dee9SAndroid Build Coastguard Worker	assertOneErrorMatches(t, errs, `reverse dependency "A" of "B" missing variant:\s*transition:b\s*available variants:\s*transition:a`)
429*1fa6dee9SAndroid Build Coastguard Worker}
430*1fa6dee9SAndroid Build Coastguard Worker
431*1fa6dee9SAndroid Build Coastguard Workerfunc TestErrorInIncomingTransition(t *testing.T) {
432*1fa6dee9SAndroid Build Coastguard Worker	_, errs := testTransition(`
433*1fa6dee9SAndroid Build Coastguard Worker		transition_module {
434*1fa6dee9SAndroid Build Coastguard Worker			name: "A",
435*1fa6dee9SAndroid Build Coastguard Worker			split: ["a"],
436*1fa6dee9SAndroid Build Coastguard Worker			deps: ["B"],
437*1fa6dee9SAndroid Build Coastguard Worker		}
438*1fa6dee9SAndroid Build Coastguard Worker		transition_module {
439*1fa6dee9SAndroid Build Coastguard Worker			name: "B",
440*1fa6dee9SAndroid Build Coastguard Worker			split: ["a"],
441*1fa6dee9SAndroid Build Coastguard Worker			incoming_transition_error: "my incoming transition error",
442*1fa6dee9SAndroid Build Coastguard Worker		}
443*1fa6dee9SAndroid Build Coastguard Worker	`)
444*1fa6dee9SAndroid Build Coastguard Worker	assertOneErrorMatches(t, errs, "my incoming transition error")
445*1fa6dee9SAndroid Build Coastguard Worker}
446*1fa6dee9SAndroid Build Coastguard Worker
447*1fa6dee9SAndroid Build Coastguard Workerfunc TestErrorInOutgoingTransition(t *testing.T) {
448*1fa6dee9SAndroid Build Coastguard Worker	_, errs := testTransition(`
449*1fa6dee9SAndroid Build Coastguard Worker		transition_module {
450*1fa6dee9SAndroid Build Coastguard Worker			name: "A",
451*1fa6dee9SAndroid Build Coastguard Worker			split: ["a"],
452*1fa6dee9SAndroid Build Coastguard Worker			deps: ["B"],
453*1fa6dee9SAndroid Build Coastguard Worker			outgoing_transition_error: "my outgoing transition error",
454*1fa6dee9SAndroid Build Coastguard Worker		}
455*1fa6dee9SAndroid Build Coastguard Worker		transition_module {
456*1fa6dee9SAndroid Build Coastguard Worker			name: "B",
457*1fa6dee9SAndroid Build Coastguard Worker			split: ["a"],
458*1fa6dee9SAndroid Build Coastguard Worker		}
459*1fa6dee9SAndroid Build Coastguard Worker	`)
460*1fa6dee9SAndroid Build Coastguard Worker	assertOneErrorMatches(t, errs, "my outgoing transition error")
461*1fa6dee9SAndroid Build Coastguard Worker}
462*1fa6dee9SAndroid Build Coastguard Worker
463*1fa6dee9SAndroid Build Coastguard Workerfunc TestPostTransitionReverseDepsAllowMissingDeps(t *testing.T) {
464*1fa6dee9SAndroid Build Coastguard Worker	_, errs := testTransitionAllowMissingDeps(`
465*1fa6dee9SAndroid Build Coastguard Worker		transition_module {
466*1fa6dee9SAndroid Build Coastguard Worker			name: "A",
467*1fa6dee9SAndroid Build Coastguard Worker			split: ["a"],
468*1fa6dee9SAndroid Build Coastguard Worker		}
469*1fa6dee9SAndroid Build Coastguard Worker
470*1fa6dee9SAndroid Build Coastguard Worker		transition_module {
471*1fa6dee9SAndroid Build Coastguard Worker			name: "B",
472*1fa6dee9SAndroid Build Coastguard Worker			split: ["b"],
473*1fa6dee9SAndroid Build Coastguard Worker			post_transition_reverse_deps: ["A"],
474*1fa6dee9SAndroid Build Coastguard Worker		}
475*1fa6dee9SAndroid Build Coastguard Worker	`)
476*1fa6dee9SAndroid Build Coastguard Worker	assertNoErrors(t, errs)
477*1fa6dee9SAndroid Build Coastguard Worker}
478*1fa6dee9SAndroid Build Coastguard Worker
479*1fa6dee9SAndroid Build Coastguard Workerfunc TestPostTransitionDepsMissingVariant(t *testing.T) {
480*1fa6dee9SAndroid Build Coastguard Worker	// TODO: eventually this will create the missing variant on demand
481*1fa6dee9SAndroid Build Coastguard Worker	_, errs := testTransition(fmt.Sprintf(testTransitionBp,
482*1fa6dee9SAndroid Build Coastguard Worker		`post_transition_deps: ["E:missing"],`, ""))
483*1fa6dee9SAndroid Build Coastguard Worker	expectedError := `Android.bp:8:4: dependency "E" of "B" missing variant:
484*1fa6dee9SAndroid Build Coastguard Worker  transition:missing
485*1fa6dee9SAndroid Build Coastguard Workeravailable variants:
486*1fa6dee9SAndroid Build Coastguard Worker  <empty variant>
487*1fa6dee9SAndroid Build Coastguard Worker  transition:d`
488*1fa6dee9SAndroid Build Coastguard Worker	if len(errs) != 1 || errs[0].Error() != expectedError {
489*1fa6dee9SAndroid Build Coastguard Worker		t.Errorf("expected error %q, got %q", expectedError, errs)
490*1fa6dee9SAndroid Build Coastguard Worker	}
491*1fa6dee9SAndroid Build Coastguard Worker}
492*1fa6dee9SAndroid Build Coastguard Worker
493*1fa6dee9SAndroid Build Coastguard Workerfunc TestIsAddingDependency(t *testing.T) {
494*1fa6dee9SAndroid Build Coastguard Worker	ctx, errs := testTransition(`
495*1fa6dee9SAndroid Build Coastguard Worker		transition_module {
496*1fa6dee9SAndroid Build Coastguard Worker			name: "A",
497*1fa6dee9SAndroid Build Coastguard Worker			split: ["a1"],
498*1fa6dee9SAndroid Build Coastguard Worker			deps: ["C"],
499*1fa6dee9SAndroid Build Coastguard Worker		}
500*1fa6dee9SAndroid Build Coastguard Worker
501*1fa6dee9SAndroid Build Coastguard Worker		transition_module {
502*1fa6dee9SAndroid Build Coastguard Worker			name: "B",
503*1fa6dee9SAndroid Build Coastguard Worker			split: ["b1"],
504*1fa6dee9SAndroid Build Coastguard Worker			post_transition_deps: ["C"],
505*1fa6dee9SAndroid Build Coastguard Worker		}
506*1fa6dee9SAndroid Build Coastguard Worker
507*1fa6dee9SAndroid Build Coastguard Worker		transition_module {
508*1fa6dee9SAndroid Build Coastguard Worker			name: "C",
509*1fa6dee9SAndroid Build Coastguard Worker			split: ["c1", "c2"],
510*1fa6dee9SAndroid Build Coastguard Worker			incoming: "c1",
511*1fa6dee9SAndroid Build Coastguard Worker			post_transition_incoming: "c2",
512*1fa6dee9SAndroid Build Coastguard Worker		}
513*1fa6dee9SAndroid Build Coastguard Worker	`)
514*1fa6dee9SAndroid Build Coastguard Worker	assertNoErrors(t, errs)
515*1fa6dee9SAndroid Build Coastguard Worker
516*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionVariants(t, ctx, "A", []string{"a1"})
517*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionVariants(t, ctx, "B", []string{"b1"})
518*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionVariants(t, ctx, "C", []string{"c1", "c2"})
519*1fa6dee9SAndroid Build Coastguard Worker
520*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionDeps(t, ctx, getTransitionModule(ctx, "A", "a1"), "C(c1)")
521*1fa6dee9SAndroid Build Coastguard Worker	checkTransitionDeps(t, ctx, getTransitionModule(ctx, "B", "b1"), "C(c2)")
522*1fa6dee9SAndroid Build Coastguard Worker}
523*1fa6dee9SAndroid Build Coastguard Worker
524*1fa6dee9SAndroid Build Coastguard Workertype transitionTestMutator struct{}
525*1fa6dee9SAndroid Build Coastguard Worker
526*1fa6dee9SAndroid Build Coastguard Workerfunc (transitionTestMutator) Split(ctx BaseModuleContext) []string {
527*1fa6dee9SAndroid Build Coastguard Worker	if split := ctx.Module().(*transitionModule).properties.Split; len(split) > 0 {
528*1fa6dee9SAndroid Build Coastguard Worker		return split
529*1fa6dee9SAndroid Build Coastguard Worker	}
530*1fa6dee9SAndroid Build Coastguard Worker	return []string{""}
531*1fa6dee9SAndroid Build Coastguard Worker}
532*1fa6dee9SAndroid Build Coastguard Worker
533*1fa6dee9SAndroid Build Coastguard Workerfunc (transitionTestMutator) OutgoingTransition(ctx OutgoingTransitionContext, sourceVariation string) string {
534*1fa6dee9SAndroid Build Coastguard Worker	if err := ctx.Module().(*transitionModule).properties.Outgoing_transition_error; err != nil {
535*1fa6dee9SAndroid Build Coastguard Worker		ctx.ModuleErrorf("Error: %s", *err)
536*1fa6dee9SAndroid Build Coastguard Worker	}
537*1fa6dee9SAndroid Build Coastguard Worker	if outgoing := ctx.Module().(*transitionModule).properties.Outgoing; outgoing != nil {
538*1fa6dee9SAndroid Build Coastguard Worker		return *outgoing
539*1fa6dee9SAndroid Build Coastguard Worker	}
540*1fa6dee9SAndroid Build Coastguard Worker	return sourceVariation
541*1fa6dee9SAndroid Build Coastguard Worker}
542*1fa6dee9SAndroid Build Coastguard Worker
543*1fa6dee9SAndroid Build Coastguard Workerfunc (transitionTestMutator) IncomingTransition(ctx IncomingTransitionContext, incomingVariation string) string {
544*1fa6dee9SAndroid Build Coastguard Worker	if err := ctx.Module().(*transitionModule).properties.Incoming_transition_error; err != nil {
545*1fa6dee9SAndroid Build Coastguard Worker		ctx.ModuleErrorf("Error: %s", *err)
546*1fa6dee9SAndroid Build Coastguard Worker	}
547*1fa6dee9SAndroid Build Coastguard Worker	if ctx.IsAddingDependency() {
548*1fa6dee9SAndroid Build Coastguard Worker		if incoming := ctx.Module().(*transitionModule).properties.Post_transition_incoming; incoming != nil {
549*1fa6dee9SAndroid Build Coastguard Worker			return *incoming
550*1fa6dee9SAndroid Build Coastguard Worker		}
551*1fa6dee9SAndroid Build Coastguard Worker	}
552*1fa6dee9SAndroid Build Coastguard Worker	if incoming := ctx.Module().(*transitionModule).properties.Incoming; incoming != nil {
553*1fa6dee9SAndroid Build Coastguard Worker		return *incoming
554*1fa6dee9SAndroid Build Coastguard Worker	}
555*1fa6dee9SAndroid Build Coastguard Worker	return incomingVariation
556*1fa6dee9SAndroid Build Coastguard Worker}
557*1fa6dee9SAndroid Build Coastguard Worker
558*1fa6dee9SAndroid Build Coastguard Workerfunc (transitionTestMutator) Mutate(ctx BottomUpMutatorContext, variation string) {
559*1fa6dee9SAndroid Build Coastguard Worker	ctx.Module().(*transitionModule).properties.Mutated = variation
560*1fa6dee9SAndroid Build Coastguard Worker}
561*1fa6dee9SAndroid Build Coastguard Worker
562*1fa6dee9SAndroid Build Coastguard Workertype transitionModule struct {
563*1fa6dee9SAndroid Build Coastguard Worker	SimpleName
564*1fa6dee9SAndroid Build Coastguard Worker	properties struct {
565*1fa6dee9SAndroid Build Coastguard Worker		Deps                                   []string
566*1fa6dee9SAndroid Build Coastguard Worker		Post_transition_deps                   []string
567*1fa6dee9SAndroid Build Coastguard Worker		Post_transition_far_deps               []string
568*1fa6dee9SAndroid Build Coastguard Worker		Post_transition_reverse_deps           []string
569*1fa6dee9SAndroid Build Coastguard Worker		Post_transition_reverse_variation_deps []string
570*1fa6dee9SAndroid Build Coastguard Worker		Split                                  []string
571*1fa6dee9SAndroid Build Coastguard Worker		Outgoing                               *string
572*1fa6dee9SAndroid Build Coastguard Worker		Incoming                               *string
573*1fa6dee9SAndroid Build Coastguard Worker		Post_transition_incoming               *string
574*1fa6dee9SAndroid Build Coastguard Worker		Outgoing_transition_error              *string
575*1fa6dee9SAndroid Build Coastguard Worker		Incoming_transition_error              *string
576*1fa6dee9SAndroid Build Coastguard Worker
577*1fa6dee9SAndroid Build Coastguard Worker		Mutated string `blueprint:"mutated"`
578*1fa6dee9SAndroid Build Coastguard Worker	}
579*1fa6dee9SAndroid Build Coastguard Worker}
580*1fa6dee9SAndroid Build Coastguard Worker
581*1fa6dee9SAndroid Build Coastguard Workerfunc newTransitionModule() (Module, []interface{}) {
582*1fa6dee9SAndroid Build Coastguard Worker	m := &transitionModule{}
583*1fa6dee9SAndroid Build Coastguard Worker	return m, []interface{}{&m.properties, &m.SimpleName.Properties}
584*1fa6dee9SAndroid Build Coastguard Worker}
585*1fa6dee9SAndroid Build Coastguard Worker
586*1fa6dee9SAndroid Build Coastguard Workerfunc (f *transitionModule) GenerateBuildActions(ModuleContext) {
587*1fa6dee9SAndroid Build Coastguard Worker}
588*1fa6dee9SAndroid Build Coastguard Worker
589*1fa6dee9SAndroid Build Coastguard Workerfunc (f *transitionModule) Deps() []string {
590*1fa6dee9SAndroid Build Coastguard Worker	return f.properties.Deps
591*1fa6dee9SAndroid Build Coastguard Worker}
592*1fa6dee9SAndroid Build Coastguard Worker
593*1fa6dee9SAndroid Build Coastguard Workerfunc (f *transitionModule) IgnoreDeps() []string {
594*1fa6dee9SAndroid Build Coastguard Worker	return nil
595*1fa6dee9SAndroid Build Coastguard Worker}
596*1fa6dee9SAndroid Build Coastguard Worker
597*1fa6dee9SAndroid Build Coastguard Workervar nameAndVariantRegexp = regexp.MustCompile(`([a-zA-Z0-9_]+)\(([a-zA-Z0-9_]+)\)`)
598*1fa6dee9SAndroid Build Coastguard Worker
599*1fa6dee9SAndroid Build Coastguard Workerfunc postTransitionDepsMutator(mctx BottomUpMutatorContext) {
600*1fa6dee9SAndroid Build Coastguard Worker	if m, ok := mctx.Module().(*transitionModule); ok {
601*1fa6dee9SAndroid Build Coastguard Worker		for _, dep := range m.properties.Post_transition_deps {
602*1fa6dee9SAndroid Build Coastguard Worker			module, variation, _ := strings.Cut(dep, ":")
603*1fa6dee9SAndroid Build Coastguard Worker			var variations []Variation
604*1fa6dee9SAndroid Build Coastguard Worker			if variation != "" {
605*1fa6dee9SAndroid Build Coastguard Worker				variations = append(variations, Variation{"transition", variation})
606*1fa6dee9SAndroid Build Coastguard Worker			}
607*1fa6dee9SAndroid Build Coastguard Worker			mctx.AddVariationDependencies(variations, walkerDepsTag{follow: true}, module)
608*1fa6dee9SAndroid Build Coastguard Worker		}
609*1fa6dee9SAndroid Build Coastguard Worker		for _, dep := range m.properties.Post_transition_far_deps {
610*1fa6dee9SAndroid Build Coastguard Worker			mctx.AddFarVariationDependencies(nil, walkerDepsTag{follow: true}, dep)
611*1fa6dee9SAndroid Build Coastguard Worker		}
612*1fa6dee9SAndroid Build Coastguard Worker		for _, dep := range m.properties.Post_transition_reverse_deps {
613*1fa6dee9SAndroid Build Coastguard Worker			mctx.AddReverseDependency(m, walkerDepsTag{follow: true}, dep)
614*1fa6dee9SAndroid Build Coastguard Worker		}
615*1fa6dee9SAndroid Build Coastguard Worker		for _, dep := range m.properties.Post_transition_reverse_variation_deps {
616*1fa6dee9SAndroid Build Coastguard Worker			match := nameAndVariantRegexp.FindStringSubmatch(dep)
617*1fa6dee9SAndroid Build Coastguard Worker			if len(match) == 0 || match[0] != dep {
618*1fa6dee9SAndroid Build Coastguard Worker				panic(fmt.Sprintf("Invalid Post_transition_reverse_variation_deps: %q. Expected module_name(variant)", dep))
619*1fa6dee9SAndroid Build Coastguard Worker			}
620*1fa6dee9SAndroid Build Coastguard Worker			mctx.AddReverseVariationDependency([]Variation{
621*1fa6dee9SAndroid Build Coastguard Worker				{Mutator: "transition", Variation: match[2]},
622*1fa6dee9SAndroid Build Coastguard Worker			}, walkerDepsTag{follow: true}, match[1])
623*1fa6dee9SAndroid Build Coastguard Worker		}
624*1fa6dee9SAndroid Build Coastguard Worker	}
625*1fa6dee9SAndroid Build Coastguard Worker}
626