xref: /aosp_15_r20/build/soong/android/rule_builder_test.go (revision 333d2b3687b3a337dbcca9d65000bca186795e39)
1*333d2b36SAndroid Build Coastguard Worker// Copyright 2019 Google Inc. All rights reserved.
2*333d2b36SAndroid Build Coastguard Worker//
3*333d2b36SAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License");
4*333d2b36SAndroid Build Coastguard Worker// you may not use this file except in compliance with the License.
5*333d2b36SAndroid Build Coastguard Worker// You may obtain a copy of the License at
6*333d2b36SAndroid Build Coastguard Worker//
7*333d2b36SAndroid Build Coastguard Worker//     http://www.apache.org/licenses/LICENSE-2.0
8*333d2b36SAndroid Build Coastguard Worker//
9*333d2b36SAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software
10*333d2b36SAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS,
11*333d2b36SAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*333d2b36SAndroid Build Coastguard Worker// See the License for the specific language governing permissions and
13*333d2b36SAndroid Build Coastguard Worker// limitations under the License.
14*333d2b36SAndroid Build Coastguard Worker
15*333d2b36SAndroid Build Coastguard Workerpackage android
16*333d2b36SAndroid Build Coastguard Worker
17*333d2b36SAndroid Build Coastguard Workerimport (
18*333d2b36SAndroid Build Coastguard Worker	"crypto/sha256"
19*333d2b36SAndroid Build Coastguard Worker	"encoding/hex"
20*333d2b36SAndroid Build Coastguard Worker	"fmt"
21*333d2b36SAndroid Build Coastguard Worker	"path/filepath"
22*333d2b36SAndroid Build Coastguard Worker	"regexp"
23*333d2b36SAndroid Build Coastguard Worker	"strings"
24*333d2b36SAndroid Build Coastguard Worker	"testing"
25*333d2b36SAndroid Build Coastguard Worker
26*333d2b36SAndroid Build Coastguard Worker	"github.com/google/blueprint"
27*333d2b36SAndroid Build Coastguard Worker
28*333d2b36SAndroid Build Coastguard Worker	"android/soong/shared"
29*333d2b36SAndroid Build Coastguard Worker)
30*333d2b36SAndroid Build Coastguard Worker
31*333d2b36SAndroid Build Coastguard Workervar (
32*333d2b36SAndroid Build Coastguard Worker	pctx_ruleBuilderTest           = NewPackageContext("android/soong/rule_builder")
33*333d2b36SAndroid Build Coastguard Worker	pctx_ruleBuilderTestSubContext = NewPackageContext("android/soong/rule_builder/config")
34*333d2b36SAndroid Build Coastguard Worker)
35*333d2b36SAndroid Build Coastguard Worker
36*333d2b36SAndroid Build Coastguard Workerfunc init() {
37*333d2b36SAndroid Build Coastguard Worker	pctx_ruleBuilderTest.Import("android/soong/rule_builder/config")
38*333d2b36SAndroid Build Coastguard Worker	pctx_ruleBuilderTest.StaticVariable("cmdFlags", "${config.ConfigFlags}")
39*333d2b36SAndroid Build Coastguard Worker	pctx_ruleBuilderTestSubContext.StaticVariable("ConfigFlags", "--some-clang-flag")
40*333d2b36SAndroid Build Coastguard Worker}
41*333d2b36SAndroid Build Coastguard Worker
42*333d2b36SAndroid Build Coastguard Workerfunc builderContext() BuilderContext {
43*333d2b36SAndroid Build Coastguard Worker	return BuilderContextForTesting(TestConfig("out", nil, "", map[string][]byte{
44*333d2b36SAndroid Build Coastguard Worker		"ld":      nil,
45*333d2b36SAndroid Build Coastguard Worker		"a.o":     nil,
46*333d2b36SAndroid Build Coastguard Worker		"b.o":     nil,
47*333d2b36SAndroid Build Coastguard Worker		"cp":      nil,
48*333d2b36SAndroid Build Coastguard Worker		"a":       nil,
49*333d2b36SAndroid Build Coastguard Worker		"b":       nil,
50*333d2b36SAndroid Build Coastguard Worker		"ls":      nil,
51*333d2b36SAndroid Build Coastguard Worker		"turbine": nil,
52*333d2b36SAndroid Build Coastguard Worker		"java":    nil,
53*333d2b36SAndroid Build Coastguard Worker		"javac":   nil,
54*333d2b36SAndroid Build Coastguard Worker	}))
55*333d2b36SAndroid Build Coastguard Worker}
56*333d2b36SAndroid Build Coastguard Worker
57*333d2b36SAndroid Build Coastguard Workerfunc ExampleRuleBuilder() {
58*333d2b36SAndroid Build Coastguard Worker	ctx := builderContext()
59*333d2b36SAndroid Build Coastguard Worker
60*333d2b36SAndroid Build Coastguard Worker	rule := NewRuleBuilder(pctx, ctx)
61*333d2b36SAndroid Build Coastguard Worker
62*333d2b36SAndroid Build Coastguard Worker	rule.Command().
63*333d2b36SAndroid Build Coastguard Worker		Tool(PathForSource(ctx, "ld")).
64*333d2b36SAndroid Build Coastguard Worker		Inputs(PathsForTesting("a.o", "b.o")).
65*333d2b36SAndroid Build Coastguard Worker		FlagWithOutput("-o ", PathForOutput(ctx, "linked"))
66*333d2b36SAndroid Build Coastguard Worker	rule.Command().Text("echo success")
67*333d2b36SAndroid Build Coastguard Worker
68*333d2b36SAndroid Build Coastguard Worker	// To add the command to the build graph:
69*333d2b36SAndroid Build Coastguard Worker	// rule.Build("link", "link")
70*333d2b36SAndroid Build Coastguard Worker
71*333d2b36SAndroid Build Coastguard Worker	fmt.Printf("commands: %q\n", strings.Join(rule.Commands(), " && "))
72*333d2b36SAndroid Build Coastguard Worker	fmt.Printf("tools: %q\n", rule.Tools())
73*333d2b36SAndroid Build Coastguard Worker	fmt.Printf("inputs: %q\n", rule.Inputs())
74*333d2b36SAndroid Build Coastguard Worker	fmt.Printf("outputs: %q\n", rule.Outputs())
75*333d2b36SAndroid Build Coastguard Worker
76*333d2b36SAndroid Build Coastguard Worker	// Output:
77*333d2b36SAndroid Build Coastguard Worker	// commands: "ld a.o b.o -o out/soong/linked && echo success"
78*333d2b36SAndroid Build Coastguard Worker	// tools: ["ld"]
79*333d2b36SAndroid Build Coastguard Worker	// inputs: ["a.o" "b.o"]
80*333d2b36SAndroid Build Coastguard Worker	// outputs: ["out/soong/linked"]
81*333d2b36SAndroid Build Coastguard Worker}
82*333d2b36SAndroid Build Coastguard Worker
83*333d2b36SAndroid Build Coastguard Workerfunc ExampleRuleBuilder_Temporary() {
84*333d2b36SAndroid Build Coastguard Worker	ctx := builderContext()
85*333d2b36SAndroid Build Coastguard Worker
86*333d2b36SAndroid Build Coastguard Worker	rule := NewRuleBuilder(pctx, ctx)
87*333d2b36SAndroid Build Coastguard Worker
88*333d2b36SAndroid Build Coastguard Worker	rule.Command().
89*333d2b36SAndroid Build Coastguard Worker		Tool(PathForSource(ctx, "cp")).
90*333d2b36SAndroid Build Coastguard Worker		Input(PathForSource(ctx, "a")).
91*333d2b36SAndroid Build Coastguard Worker		Output(PathForOutput(ctx, "b"))
92*333d2b36SAndroid Build Coastguard Worker	rule.Command().
93*333d2b36SAndroid Build Coastguard Worker		Tool(PathForSource(ctx, "cp")).
94*333d2b36SAndroid Build Coastguard Worker		Input(PathForOutput(ctx, "b")).
95*333d2b36SAndroid Build Coastguard Worker		Output(PathForOutput(ctx, "c"))
96*333d2b36SAndroid Build Coastguard Worker	rule.Temporary(PathForOutput(ctx, "b"))
97*333d2b36SAndroid Build Coastguard Worker
98*333d2b36SAndroid Build Coastguard Worker	fmt.Printf("commands: %q\n", strings.Join(rule.Commands(), " && "))
99*333d2b36SAndroid Build Coastguard Worker	fmt.Printf("tools: %q\n", rule.Tools())
100*333d2b36SAndroid Build Coastguard Worker	fmt.Printf("inputs: %q\n", rule.Inputs())
101*333d2b36SAndroid Build Coastguard Worker	fmt.Printf("outputs: %q\n", rule.Outputs())
102*333d2b36SAndroid Build Coastguard Worker
103*333d2b36SAndroid Build Coastguard Worker	// Output:
104*333d2b36SAndroid Build Coastguard Worker	// commands: "cp a out/soong/b && cp out/soong/b out/soong/c"
105*333d2b36SAndroid Build Coastguard Worker	// tools: ["cp"]
106*333d2b36SAndroid Build Coastguard Worker	// inputs: ["a"]
107*333d2b36SAndroid Build Coastguard Worker	// outputs: ["out/soong/c"]
108*333d2b36SAndroid Build Coastguard Worker}
109*333d2b36SAndroid Build Coastguard Worker
110*333d2b36SAndroid Build Coastguard Workerfunc ExampleRuleBuilder_DeleteTemporaryFiles() {
111*333d2b36SAndroid Build Coastguard Worker	ctx := builderContext()
112*333d2b36SAndroid Build Coastguard Worker
113*333d2b36SAndroid Build Coastguard Worker	rule := NewRuleBuilder(pctx, ctx)
114*333d2b36SAndroid Build Coastguard Worker
115*333d2b36SAndroid Build Coastguard Worker	rule.Command().
116*333d2b36SAndroid Build Coastguard Worker		Tool(PathForSource(ctx, "cp")).
117*333d2b36SAndroid Build Coastguard Worker		Input(PathForSource(ctx, "a")).
118*333d2b36SAndroid Build Coastguard Worker		Output(PathForOutput(ctx, "b"))
119*333d2b36SAndroid Build Coastguard Worker	rule.Command().
120*333d2b36SAndroid Build Coastguard Worker		Tool(PathForSource(ctx, "cp")).
121*333d2b36SAndroid Build Coastguard Worker		Input(PathForOutput(ctx, "b")).
122*333d2b36SAndroid Build Coastguard Worker		Output(PathForOutput(ctx, "c"))
123*333d2b36SAndroid Build Coastguard Worker	rule.Temporary(PathForOutput(ctx, "b"))
124*333d2b36SAndroid Build Coastguard Worker	rule.DeleteTemporaryFiles()
125*333d2b36SAndroid Build Coastguard Worker
126*333d2b36SAndroid Build Coastguard Worker	fmt.Printf("commands: %q\n", strings.Join(rule.Commands(), " && "))
127*333d2b36SAndroid Build Coastguard Worker	fmt.Printf("tools: %q\n", rule.Tools())
128*333d2b36SAndroid Build Coastguard Worker	fmt.Printf("inputs: %q\n", rule.Inputs())
129*333d2b36SAndroid Build Coastguard Worker	fmt.Printf("outputs: %q\n", rule.Outputs())
130*333d2b36SAndroid Build Coastguard Worker
131*333d2b36SAndroid Build Coastguard Worker	// Output:
132*333d2b36SAndroid Build Coastguard Worker	// commands: "cp a out/soong/b && cp out/soong/b out/soong/c && rm -f out/soong/b"
133*333d2b36SAndroid Build Coastguard Worker	// tools: ["cp"]
134*333d2b36SAndroid Build Coastguard Worker	// inputs: ["a"]
135*333d2b36SAndroid Build Coastguard Worker	// outputs: ["out/soong/c"]
136*333d2b36SAndroid Build Coastguard Worker}
137*333d2b36SAndroid Build Coastguard Worker
138*333d2b36SAndroid Build Coastguard Workerfunc ExampleRuleBuilder_Installs() {
139*333d2b36SAndroid Build Coastguard Worker	ctx := builderContext()
140*333d2b36SAndroid Build Coastguard Worker
141*333d2b36SAndroid Build Coastguard Worker	rule := NewRuleBuilder(pctx, ctx)
142*333d2b36SAndroid Build Coastguard Worker
143*333d2b36SAndroid Build Coastguard Worker	out := PathForOutput(ctx, "linked")
144*333d2b36SAndroid Build Coastguard Worker
145*333d2b36SAndroid Build Coastguard Worker	rule.Command().
146*333d2b36SAndroid Build Coastguard Worker		Tool(PathForSource(ctx, "ld")).
147*333d2b36SAndroid Build Coastguard Worker		Inputs(PathsForTesting("a.o", "b.o")).
148*333d2b36SAndroid Build Coastguard Worker		FlagWithOutput("-o ", out)
149*333d2b36SAndroid Build Coastguard Worker	rule.Install(out, "/bin/linked")
150*333d2b36SAndroid Build Coastguard Worker	rule.Install(out, "/sbin/linked")
151*333d2b36SAndroid Build Coastguard Worker
152*333d2b36SAndroid Build Coastguard Worker	fmt.Printf("rule.Installs().String() = %q\n", rule.Installs().String())
153*333d2b36SAndroid Build Coastguard Worker
154*333d2b36SAndroid Build Coastguard Worker	// Output:
155*333d2b36SAndroid Build Coastguard Worker	// rule.Installs().String() = "out/soong/linked:/bin/linked out/soong/linked:/sbin/linked"
156*333d2b36SAndroid Build Coastguard Worker}
157*333d2b36SAndroid Build Coastguard Worker
158*333d2b36SAndroid Build Coastguard Workerfunc ExampleRuleBuilderCommand() {
159*333d2b36SAndroid Build Coastguard Worker	ctx := builderContext()
160*333d2b36SAndroid Build Coastguard Worker
161*333d2b36SAndroid Build Coastguard Worker	rule := NewRuleBuilder(pctx, ctx)
162*333d2b36SAndroid Build Coastguard Worker
163*333d2b36SAndroid Build Coastguard Worker	// chained
164*333d2b36SAndroid Build Coastguard Worker	rule.Command().
165*333d2b36SAndroid Build Coastguard Worker		Tool(PathForSource(ctx, "ld")).
166*333d2b36SAndroid Build Coastguard Worker		Inputs(PathsForTesting("a.o", "b.o")).
167*333d2b36SAndroid Build Coastguard Worker		FlagWithOutput("-o ", PathForOutput(ctx, "linked"))
168*333d2b36SAndroid Build Coastguard Worker
169*333d2b36SAndroid Build Coastguard Worker	// unchained
170*333d2b36SAndroid Build Coastguard Worker	cmd := rule.Command()
171*333d2b36SAndroid Build Coastguard Worker	cmd.Tool(PathForSource(ctx, "ld"))
172*333d2b36SAndroid Build Coastguard Worker	cmd.Inputs(PathsForTesting("a.o", "b.o"))
173*333d2b36SAndroid Build Coastguard Worker	cmd.FlagWithOutput("-o ", PathForOutput(ctx, "linked"))
174*333d2b36SAndroid Build Coastguard Worker
175*333d2b36SAndroid Build Coastguard Worker	// mixed:
176*333d2b36SAndroid Build Coastguard Worker	cmd = rule.Command().Tool(PathForSource(ctx, "ld"))
177*333d2b36SAndroid Build Coastguard Worker	cmd.Inputs(PathsForTesting("a.o", "b.o"))
178*333d2b36SAndroid Build Coastguard Worker	cmd.FlagWithOutput("-o ", PathForOutput(ctx, "linked"))
179*333d2b36SAndroid Build Coastguard Worker}
180*333d2b36SAndroid Build Coastguard Worker
181*333d2b36SAndroid Build Coastguard Workerfunc ExampleRuleBuilderCommand_Flag() {
182*333d2b36SAndroid Build Coastguard Worker	ctx := builderContext()
183*333d2b36SAndroid Build Coastguard Worker	fmt.Println(NewRuleBuilder(pctx, ctx).Command().
184*333d2b36SAndroid Build Coastguard Worker		Tool(PathForSource(ctx, "ls")).Flag("-l"))
185*333d2b36SAndroid Build Coastguard Worker	// Output:
186*333d2b36SAndroid Build Coastguard Worker	// ls -l
187*333d2b36SAndroid Build Coastguard Worker}
188*333d2b36SAndroid Build Coastguard Worker
189*333d2b36SAndroid Build Coastguard Workerfunc ExampleRuleBuilderCommand_Flags() {
190*333d2b36SAndroid Build Coastguard Worker	ctx := builderContext()
191*333d2b36SAndroid Build Coastguard Worker	fmt.Println(NewRuleBuilder(pctx, ctx).Command().
192*333d2b36SAndroid Build Coastguard Worker		Tool(PathForSource(ctx, "ls")).Flags([]string{"-l", "-a"}))
193*333d2b36SAndroid Build Coastguard Worker	// Output:
194*333d2b36SAndroid Build Coastguard Worker	// ls -l -a
195*333d2b36SAndroid Build Coastguard Worker}
196*333d2b36SAndroid Build Coastguard Worker
197*333d2b36SAndroid Build Coastguard Workerfunc ExampleRuleBuilderCommand_FlagWithArg() {
198*333d2b36SAndroid Build Coastguard Worker	ctx := builderContext()
199*333d2b36SAndroid Build Coastguard Worker	fmt.Println(NewRuleBuilder(pctx, ctx).Command().
200*333d2b36SAndroid Build Coastguard Worker		Tool(PathForSource(ctx, "ls")).
201*333d2b36SAndroid Build Coastguard Worker		FlagWithArg("--sort=", "time"))
202*333d2b36SAndroid Build Coastguard Worker	// Output:
203*333d2b36SAndroid Build Coastguard Worker	// ls --sort=time
204*333d2b36SAndroid Build Coastguard Worker}
205*333d2b36SAndroid Build Coastguard Worker
206*333d2b36SAndroid Build Coastguard Workerfunc ExampleRuleBuilderCommand_FlagForEachArg() {
207*333d2b36SAndroid Build Coastguard Worker	ctx := builderContext()
208*333d2b36SAndroid Build Coastguard Worker	fmt.Println(NewRuleBuilder(pctx, ctx).Command().
209*333d2b36SAndroid Build Coastguard Worker		Tool(PathForSource(ctx, "ls")).
210*333d2b36SAndroid Build Coastguard Worker		FlagForEachArg("--sort=", []string{"time", "size"}))
211*333d2b36SAndroid Build Coastguard Worker	// Output:
212*333d2b36SAndroid Build Coastguard Worker	// ls --sort=time --sort=size
213*333d2b36SAndroid Build Coastguard Worker}
214*333d2b36SAndroid Build Coastguard Worker
215*333d2b36SAndroid Build Coastguard Workerfunc ExampleRuleBuilderCommand_FlagForEachInput() {
216*333d2b36SAndroid Build Coastguard Worker	ctx := builderContext()
217*333d2b36SAndroid Build Coastguard Worker	fmt.Println(NewRuleBuilder(pctx, ctx).Command().
218*333d2b36SAndroid Build Coastguard Worker		Tool(PathForSource(ctx, "turbine")).
219*333d2b36SAndroid Build Coastguard Worker		FlagForEachInput("--classpath ", PathsForTesting("a.jar", "b.jar")))
220*333d2b36SAndroid Build Coastguard Worker	// Output:
221*333d2b36SAndroid Build Coastguard Worker	// turbine --classpath a.jar --classpath b.jar
222*333d2b36SAndroid Build Coastguard Worker}
223*333d2b36SAndroid Build Coastguard Worker
224*333d2b36SAndroid Build Coastguard Workerfunc ExampleRuleBuilderCommand_FlagWithInputList() {
225*333d2b36SAndroid Build Coastguard Worker	ctx := builderContext()
226*333d2b36SAndroid Build Coastguard Worker	fmt.Println(NewRuleBuilder(pctx, ctx).Command().
227*333d2b36SAndroid Build Coastguard Worker		Tool(PathForSource(ctx, "java")).
228*333d2b36SAndroid Build Coastguard Worker		FlagWithInputList("-classpath=", PathsForTesting("a.jar", "b.jar"), ":"))
229*333d2b36SAndroid Build Coastguard Worker	// Output:
230*333d2b36SAndroid Build Coastguard Worker	// java -classpath=a.jar:b.jar
231*333d2b36SAndroid Build Coastguard Worker}
232*333d2b36SAndroid Build Coastguard Worker
233*333d2b36SAndroid Build Coastguard Workerfunc ExampleRuleBuilderCommand_FlagWithInput() {
234*333d2b36SAndroid Build Coastguard Worker	ctx := builderContext()
235*333d2b36SAndroid Build Coastguard Worker	fmt.Println(NewRuleBuilder(pctx, ctx).Command().
236*333d2b36SAndroid Build Coastguard Worker		Tool(PathForSource(ctx, "java")).
237*333d2b36SAndroid Build Coastguard Worker		FlagWithInput("-classpath=", PathForSource(ctx, "a")))
238*333d2b36SAndroid Build Coastguard Worker	// Output:
239*333d2b36SAndroid Build Coastguard Worker	// java -classpath=a
240*333d2b36SAndroid Build Coastguard Worker}
241*333d2b36SAndroid Build Coastguard Worker
242*333d2b36SAndroid Build Coastguard Workerfunc ExampleRuleBuilderCommand_FlagWithList() {
243*333d2b36SAndroid Build Coastguard Worker	ctx := builderContext()
244*333d2b36SAndroid Build Coastguard Worker	fmt.Println(NewRuleBuilder(pctx, ctx).Command().
245*333d2b36SAndroid Build Coastguard Worker		Tool(PathForSource(ctx, "ls")).
246*333d2b36SAndroid Build Coastguard Worker		FlagWithList("--sort=", []string{"time", "size"}, ","))
247*333d2b36SAndroid Build Coastguard Worker	// Output:
248*333d2b36SAndroid Build Coastguard Worker	// ls --sort=time,size
249*333d2b36SAndroid Build Coastguard Worker}
250*333d2b36SAndroid Build Coastguard Worker
251*333d2b36SAndroid Build Coastguard Workerfunc ExampleRuleBuilderCommand_FlagWithRspFileInputList() {
252*333d2b36SAndroid Build Coastguard Worker	ctx := builderContext()
253*333d2b36SAndroid Build Coastguard Worker	fmt.Println(NewRuleBuilder(pctx, ctx).Command().
254*333d2b36SAndroid Build Coastguard Worker		Tool(PathForSource(ctx, "javac")).
255*333d2b36SAndroid Build Coastguard Worker		FlagWithRspFileInputList("@", PathForOutput(ctx, "foo.rsp"), PathsForTesting("a.java", "b.java")).
256*333d2b36SAndroid Build Coastguard Worker		String())
257*333d2b36SAndroid Build Coastguard Worker	// Output:
258*333d2b36SAndroid Build Coastguard Worker	// javac @out/soong/foo.rsp
259*333d2b36SAndroid Build Coastguard Worker}
260*333d2b36SAndroid Build Coastguard Worker
261*333d2b36SAndroid Build Coastguard Workerfunc ExampleRuleBuilderCommand_String() {
262*333d2b36SAndroid Build Coastguard Worker	ctx := builderContext()
263*333d2b36SAndroid Build Coastguard Worker	fmt.Println(NewRuleBuilder(pctx, ctx).Command().
264*333d2b36SAndroid Build Coastguard Worker		Text("FOO=foo").
265*333d2b36SAndroid Build Coastguard Worker		Text("echo $FOO").
266*333d2b36SAndroid Build Coastguard Worker		String())
267*333d2b36SAndroid Build Coastguard Worker	// Output:
268*333d2b36SAndroid Build Coastguard Worker	// FOO=foo echo $FOO
269*333d2b36SAndroid Build Coastguard Worker}
270*333d2b36SAndroid Build Coastguard Worker
271*333d2b36SAndroid Build Coastguard Workerfunc TestRuleBuilder(t *testing.T) {
272*333d2b36SAndroid Build Coastguard Worker	fs := map[string][]byte{
273*333d2b36SAndroid Build Coastguard Worker		"dep_fixer":  nil,
274*333d2b36SAndroid Build Coastguard Worker		"input":      nil,
275*333d2b36SAndroid Build Coastguard Worker		"Implicit":   nil,
276*333d2b36SAndroid Build Coastguard Worker		"Input":      nil,
277*333d2b36SAndroid Build Coastguard Worker		"OrderOnly":  nil,
278*333d2b36SAndroid Build Coastguard Worker		"OrderOnlys": nil,
279*333d2b36SAndroid Build Coastguard Worker		"Tool":       nil,
280*333d2b36SAndroid Build Coastguard Worker		"input2":     nil,
281*333d2b36SAndroid Build Coastguard Worker		"tool2":      nil,
282*333d2b36SAndroid Build Coastguard Worker		"input3":     nil,
283*333d2b36SAndroid Build Coastguard Worker	}
284*333d2b36SAndroid Build Coastguard Worker
285*333d2b36SAndroid Build Coastguard Worker	pathCtx := PathContextForTesting(TestConfig("out_local", nil, "", fs))
286*333d2b36SAndroid Build Coastguard Worker	ctx := builderContextForTests{
287*333d2b36SAndroid Build Coastguard Worker		PathContext: pathCtx,
288*333d2b36SAndroid Build Coastguard Worker	}
289*333d2b36SAndroid Build Coastguard Worker
290*333d2b36SAndroid Build Coastguard Worker	addCommands := func(rule *RuleBuilder) {
291*333d2b36SAndroid Build Coastguard Worker		cmd := rule.Command().
292*333d2b36SAndroid Build Coastguard Worker			DepFile(PathForOutput(ctx, "module/DepFile")).
293*333d2b36SAndroid Build Coastguard Worker			Flag("Flag").
294*333d2b36SAndroid Build Coastguard Worker			FlagWithArg("FlagWithArg=", "arg").
295*333d2b36SAndroid Build Coastguard Worker			FlagWithDepFile("FlagWithDepFile=", PathForOutput(ctx, "module/depfile")).
296*333d2b36SAndroid Build Coastguard Worker			FlagWithInput("FlagWithInput=", PathForSource(ctx, "input")).
297*333d2b36SAndroid Build Coastguard Worker			FlagWithOutput("FlagWithOutput=", PathForOutput(ctx, "module/output")).
298*333d2b36SAndroid Build Coastguard Worker			FlagWithRspFileInputList("FlagWithRspFileInputList=", PathForOutput(ctx, "rsp"),
299*333d2b36SAndroid Build Coastguard Worker				Paths{
300*333d2b36SAndroid Build Coastguard Worker					PathForSource(ctx, "RspInput"),
301*333d2b36SAndroid Build Coastguard Worker					PathForOutput(ctx, "other/RspOutput2"),
302*333d2b36SAndroid Build Coastguard Worker				}).
303*333d2b36SAndroid Build Coastguard Worker			Implicit(PathForSource(ctx, "Implicit")).
304*333d2b36SAndroid Build Coastguard Worker			ImplicitDepFile(PathForOutput(ctx, "module/ImplicitDepFile")).
305*333d2b36SAndroid Build Coastguard Worker			ImplicitOutput(PathForOutput(ctx, "module/ImplicitOutput")).
306*333d2b36SAndroid Build Coastguard Worker			Input(PathForSource(ctx, "Input")).
307*333d2b36SAndroid Build Coastguard Worker			Output(PathForOutput(ctx, "module/Output")).
308*333d2b36SAndroid Build Coastguard Worker			OrderOnly(PathForSource(ctx, "OrderOnly")).
309*333d2b36SAndroid Build Coastguard Worker			Validation(PathForSource(ctx, "Validation")).
310*333d2b36SAndroid Build Coastguard Worker			Text("Text").
311*333d2b36SAndroid Build Coastguard Worker			Tool(PathForSource(ctx, "Tool"))
312*333d2b36SAndroid Build Coastguard Worker
313*333d2b36SAndroid Build Coastguard Worker		rule.Command().
314*333d2b36SAndroid Build Coastguard Worker			Text("command2").
315*333d2b36SAndroid Build Coastguard Worker			DepFile(PathForOutput(ctx, "module/depfile2")).
316*333d2b36SAndroid Build Coastguard Worker			Input(PathForSource(ctx, "input2")).
317*333d2b36SAndroid Build Coastguard Worker			Output(PathForOutput(ctx, "module/output2")).
318*333d2b36SAndroid Build Coastguard Worker			OrderOnlys(PathsForSource(ctx, []string{"OrderOnlys"})).
319*333d2b36SAndroid Build Coastguard Worker			Validations(PathsForSource(ctx, []string{"Validations"})).
320*333d2b36SAndroid Build Coastguard Worker			Tool(PathForSource(ctx, "tool2"))
321*333d2b36SAndroid Build Coastguard Worker
322*333d2b36SAndroid Build Coastguard Worker		// Test updates to the first command after the second command has been started
323*333d2b36SAndroid Build Coastguard Worker		cmd.Text("after command2")
324*333d2b36SAndroid Build Coastguard Worker		// Test updating a command when the previous update did not replace the cmd variable
325*333d2b36SAndroid Build Coastguard Worker		cmd.Text("old cmd")
326*333d2b36SAndroid Build Coastguard Worker
327*333d2b36SAndroid Build Coastguard Worker		// Test a command that uses the output of a previous command as an input
328*333d2b36SAndroid Build Coastguard Worker		rule.Command().
329*333d2b36SAndroid Build Coastguard Worker			Text("command3").
330*333d2b36SAndroid Build Coastguard Worker			Input(PathForSource(ctx, "input3")).
331*333d2b36SAndroid Build Coastguard Worker			Input(PathForOutput(ctx, "module/output2")).
332*333d2b36SAndroid Build Coastguard Worker			Output(PathForOutput(ctx, "module/output3")).
333*333d2b36SAndroid Build Coastguard Worker			Text(cmd.PathForInput(PathForSource(ctx, "input3"))).
334*333d2b36SAndroid Build Coastguard Worker			Text(cmd.PathForOutput(PathForOutput(ctx, "module/output2")))
335*333d2b36SAndroid Build Coastguard Worker	}
336*333d2b36SAndroid Build Coastguard Worker
337*333d2b36SAndroid Build Coastguard Worker	wantInputs := PathsForSource(ctx, []string{"Implicit", "Input", "input", "input2", "input3"})
338*333d2b36SAndroid Build Coastguard Worker	wantRspFileInputs := Paths{PathForSource(ctx, "RspInput"),
339*333d2b36SAndroid Build Coastguard Worker		PathForOutput(ctx, "other/RspOutput2")}
340*333d2b36SAndroid Build Coastguard Worker	wantOutputs := PathsForOutput(ctx, []string{
341*333d2b36SAndroid Build Coastguard Worker		"module/ImplicitOutput", "module/Output", "module/output", "module/output2",
342*333d2b36SAndroid Build Coastguard Worker		"module/output3"})
343*333d2b36SAndroid Build Coastguard Worker	wantDepFiles := PathsForOutput(ctx, []string{
344*333d2b36SAndroid Build Coastguard Worker		"module/DepFile", "module/depfile", "module/ImplicitDepFile", "module/depfile2"})
345*333d2b36SAndroid Build Coastguard Worker	wantTools := PathsForSource(ctx, []string{"Tool", "tool2"})
346*333d2b36SAndroid Build Coastguard Worker	wantOrderOnlys := PathsForSource(ctx, []string{"OrderOnly", "OrderOnlys"})
347*333d2b36SAndroid Build Coastguard Worker	wantValidations := PathsForSource(ctx, []string{"Validation", "Validations"})
348*333d2b36SAndroid Build Coastguard Worker
349*333d2b36SAndroid Build Coastguard Worker	t.Run("normal", func(t *testing.T) {
350*333d2b36SAndroid Build Coastguard Worker		rule := NewRuleBuilder(pctx, ctx)
351*333d2b36SAndroid Build Coastguard Worker		addCommands(rule)
352*333d2b36SAndroid Build Coastguard Worker
353*333d2b36SAndroid Build Coastguard Worker		wantCommands := []string{
354*333d2b36SAndroid Build Coastguard Worker			"out_local/soong/module/DepFile Flag FlagWithArg=arg FlagWithDepFile=out_local/soong/module/depfile " +
355*333d2b36SAndroid Build Coastguard Worker				"FlagWithInput=input FlagWithOutput=out_local/soong/module/output FlagWithRspFileInputList=out_local/soong/rsp " +
356*333d2b36SAndroid Build Coastguard Worker				"Input out_local/soong/module/Output Text Tool after command2 old cmd",
357*333d2b36SAndroid Build Coastguard Worker			"command2 out_local/soong/module/depfile2 input2 out_local/soong/module/output2 tool2",
358*333d2b36SAndroid Build Coastguard Worker			"command3 input3 out_local/soong/module/output2 out_local/soong/module/output3 input3 out_local/soong/module/output2",
359*333d2b36SAndroid Build Coastguard Worker		}
360*333d2b36SAndroid Build Coastguard Worker
361*333d2b36SAndroid Build Coastguard Worker		wantDepMergerCommand := "out_local/soong/host/" + ctx.Config().PrebuiltOS() + "/bin/dep_fixer " +
362*333d2b36SAndroid Build Coastguard Worker			"out_local/soong/module/DepFile out_local/soong/module/depfile out_local/soong/module/ImplicitDepFile out_local/soong/module/depfile2"
363*333d2b36SAndroid Build Coastguard Worker
364*333d2b36SAndroid Build Coastguard Worker		AssertDeepEquals(t, "rule.Commands()", wantCommands, rule.Commands())
365*333d2b36SAndroid Build Coastguard Worker
366*333d2b36SAndroid Build Coastguard Worker		AssertDeepEquals(t, "rule.Inputs()", wantInputs, rule.Inputs())
367*333d2b36SAndroid Build Coastguard Worker		AssertDeepEquals(t, "rule.RspfileInputs()", wantRspFileInputs, rule.RspFileInputs())
368*333d2b36SAndroid Build Coastguard Worker		AssertDeepEquals(t, "rule.Outputs()", wantOutputs, rule.Outputs())
369*333d2b36SAndroid Build Coastguard Worker		AssertDeepEquals(t, "rule.DepFiles()", wantDepFiles, rule.DepFiles())
370*333d2b36SAndroid Build Coastguard Worker		AssertDeepEquals(t, "rule.Tools()", wantTools, rule.Tools())
371*333d2b36SAndroid Build Coastguard Worker		AssertDeepEquals(t, "rule.OrderOnlys()", wantOrderOnlys, rule.OrderOnlys())
372*333d2b36SAndroid Build Coastguard Worker		AssertDeepEquals(t, "rule.Validations()", wantValidations, rule.Validations())
373*333d2b36SAndroid Build Coastguard Worker
374*333d2b36SAndroid Build Coastguard Worker		AssertSame(t, "rule.depFileMergerCmd()", wantDepMergerCommand, rule.depFileMergerCmd(rule.DepFiles()).String())
375*333d2b36SAndroid Build Coastguard Worker	})
376*333d2b36SAndroid Build Coastguard Worker
377*333d2b36SAndroid Build Coastguard Worker	t.Run("sbox", func(t *testing.T) {
378*333d2b36SAndroid Build Coastguard Worker		rule := NewRuleBuilder(pctx, ctx).Sbox(PathForOutput(ctx, "module"),
379*333d2b36SAndroid Build Coastguard Worker			PathForOutput(ctx, "sbox.textproto"))
380*333d2b36SAndroid Build Coastguard Worker		addCommands(rule)
381*333d2b36SAndroid Build Coastguard Worker
382*333d2b36SAndroid Build Coastguard Worker		wantCommands := []string{
383*333d2b36SAndroid Build Coastguard Worker			"__SBOX_SANDBOX_DIR__/out/DepFile Flag FlagWithArg=arg FlagWithDepFile=__SBOX_SANDBOX_DIR__/out/depfile " +
384*333d2b36SAndroid Build Coastguard Worker				"FlagWithInput=input FlagWithOutput=__SBOX_SANDBOX_DIR__/out/output " +
385*333d2b36SAndroid Build Coastguard Worker				"FlagWithRspFileInputList=out_local/soong/rsp Input __SBOX_SANDBOX_DIR__/out/Output " +
386*333d2b36SAndroid Build Coastguard Worker				"Text Tool after command2 old cmd",
387*333d2b36SAndroid Build Coastguard Worker			"command2 __SBOX_SANDBOX_DIR__/out/depfile2 input2 __SBOX_SANDBOX_DIR__/out/output2 tool2",
388*333d2b36SAndroid Build Coastguard Worker			"command3 input3 __SBOX_SANDBOX_DIR__/out/output2 __SBOX_SANDBOX_DIR__/out/output3 input3 __SBOX_SANDBOX_DIR__/out/output2",
389*333d2b36SAndroid Build Coastguard Worker		}
390*333d2b36SAndroid Build Coastguard Worker
391*333d2b36SAndroid Build Coastguard Worker		wantDepMergerCommand := "out_local/soong/host/" + ctx.Config().PrebuiltOS() + "/bin/dep_fixer __SBOX_SANDBOX_DIR__/out/DepFile __SBOX_SANDBOX_DIR__/out/depfile __SBOX_SANDBOX_DIR__/out/ImplicitDepFile __SBOX_SANDBOX_DIR__/out/depfile2"
392*333d2b36SAndroid Build Coastguard Worker
393*333d2b36SAndroid Build Coastguard Worker		AssertDeepEquals(t, "rule.Commands()", wantCommands, rule.Commands())
394*333d2b36SAndroid Build Coastguard Worker
395*333d2b36SAndroid Build Coastguard Worker		AssertDeepEquals(t, "rule.Inputs()", wantInputs, rule.Inputs())
396*333d2b36SAndroid Build Coastguard Worker		AssertDeepEquals(t, "rule.RspfileInputs()", wantRspFileInputs, rule.RspFileInputs())
397*333d2b36SAndroid Build Coastguard Worker		AssertDeepEquals(t, "rule.Outputs()", wantOutputs, rule.Outputs())
398*333d2b36SAndroid Build Coastguard Worker		AssertDeepEquals(t, "rule.DepFiles()", wantDepFiles, rule.DepFiles())
399*333d2b36SAndroid Build Coastguard Worker		AssertDeepEquals(t, "rule.Tools()", wantTools, rule.Tools())
400*333d2b36SAndroid Build Coastguard Worker		AssertDeepEquals(t, "rule.OrderOnlys()", wantOrderOnlys, rule.OrderOnlys())
401*333d2b36SAndroid Build Coastguard Worker		AssertDeepEquals(t, "rule.Validations()", wantValidations, rule.Validations())
402*333d2b36SAndroid Build Coastguard Worker
403*333d2b36SAndroid Build Coastguard Worker		AssertSame(t, "rule.depFileMergerCmd()", wantDepMergerCommand, rule.depFileMergerCmd(rule.DepFiles()).String())
404*333d2b36SAndroid Build Coastguard Worker	})
405*333d2b36SAndroid Build Coastguard Worker
406*333d2b36SAndroid Build Coastguard Worker	t.Run("sbox tools", func(t *testing.T) {
407*333d2b36SAndroid Build Coastguard Worker		rule := NewRuleBuilder(pctx, ctx).Sbox(PathForOutput(ctx, "module"),
408*333d2b36SAndroid Build Coastguard Worker			PathForOutput(ctx, "sbox.textproto")).SandboxTools()
409*333d2b36SAndroid Build Coastguard Worker		addCommands(rule)
410*333d2b36SAndroid Build Coastguard Worker
411*333d2b36SAndroid Build Coastguard Worker		wantCommands := []string{
412*333d2b36SAndroid Build Coastguard Worker			"__SBOX_SANDBOX_DIR__/out/DepFile Flag FlagWithArg=arg FlagWithDepFile=__SBOX_SANDBOX_DIR__/out/depfile " +
413*333d2b36SAndroid Build Coastguard Worker				"FlagWithInput=input FlagWithOutput=__SBOX_SANDBOX_DIR__/out/output " +
414*333d2b36SAndroid Build Coastguard Worker				"FlagWithRspFileInputList=out_local/soong/rsp Input __SBOX_SANDBOX_DIR__/out/Output " +
415*333d2b36SAndroid Build Coastguard Worker				"Text __SBOX_SANDBOX_DIR__/tools/src/Tool after command2 old cmd",
416*333d2b36SAndroid Build Coastguard Worker			"command2 __SBOX_SANDBOX_DIR__/out/depfile2 input2 __SBOX_SANDBOX_DIR__/out/output2 __SBOX_SANDBOX_DIR__/tools/src/tool2",
417*333d2b36SAndroid Build Coastguard Worker			"command3 input3 __SBOX_SANDBOX_DIR__/out/output2 __SBOX_SANDBOX_DIR__/out/output3 input3 __SBOX_SANDBOX_DIR__/out/output2",
418*333d2b36SAndroid Build Coastguard Worker		}
419*333d2b36SAndroid Build Coastguard Worker
420*333d2b36SAndroid Build Coastguard Worker		wantDepMergerCommand := "__SBOX_SANDBOX_DIR__/tools/out/bin/dep_fixer __SBOX_SANDBOX_DIR__/out/DepFile __SBOX_SANDBOX_DIR__/out/depfile __SBOX_SANDBOX_DIR__/out/ImplicitDepFile __SBOX_SANDBOX_DIR__/out/depfile2"
421*333d2b36SAndroid Build Coastguard Worker
422*333d2b36SAndroid Build Coastguard Worker		AssertDeepEquals(t, "rule.Commands()", wantCommands, rule.Commands())
423*333d2b36SAndroid Build Coastguard Worker
424*333d2b36SAndroid Build Coastguard Worker		AssertDeepEquals(t, "rule.Inputs()", wantInputs, rule.Inputs())
425*333d2b36SAndroid Build Coastguard Worker		AssertDeepEquals(t, "rule.RspfileInputs()", wantRspFileInputs, rule.RspFileInputs())
426*333d2b36SAndroid Build Coastguard Worker		AssertDeepEquals(t, "rule.Outputs()", wantOutputs, rule.Outputs())
427*333d2b36SAndroid Build Coastguard Worker		AssertDeepEquals(t, "rule.DepFiles()", wantDepFiles, rule.DepFiles())
428*333d2b36SAndroid Build Coastguard Worker		AssertDeepEquals(t, "rule.Tools()", wantTools, rule.Tools())
429*333d2b36SAndroid Build Coastguard Worker		AssertDeepEquals(t, "rule.OrderOnlys()", wantOrderOnlys, rule.OrderOnlys())
430*333d2b36SAndroid Build Coastguard Worker		AssertDeepEquals(t, "rule.Validations()", wantValidations, rule.Validations())
431*333d2b36SAndroid Build Coastguard Worker
432*333d2b36SAndroid Build Coastguard Worker		AssertSame(t, "rule.depFileMergerCmd()", wantDepMergerCommand, rule.depFileMergerCmd(rule.DepFiles()).String())
433*333d2b36SAndroid Build Coastguard Worker	})
434*333d2b36SAndroid Build Coastguard Worker
435*333d2b36SAndroid Build Coastguard Worker	t.Run("sbox inputs", func(t *testing.T) {
436*333d2b36SAndroid Build Coastguard Worker		rule := NewRuleBuilder(pctx, ctx).Sbox(PathForOutput(ctx, "module"),
437*333d2b36SAndroid Build Coastguard Worker			PathForOutput(ctx, "sbox.textproto")).SandboxInputs()
438*333d2b36SAndroid Build Coastguard Worker		addCommands(rule)
439*333d2b36SAndroid Build Coastguard Worker
440*333d2b36SAndroid Build Coastguard Worker		wantCommands := []string{
441*333d2b36SAndroid Build Coastguard Worker			"__SBOX_SANDBOX_DIR__/out/DepFile Flag FlagWithArg=arg FlagWithDepFile=__SBOX_SANDBOX_DIR__/out/depfile " +
442*333d2b36SAndroid Build Coastguard Worker				"FlagWithInput=input FlagWithOutput=__SBOX_SANDBOX_DIR__/out/output " +
443*333d2b36SAndroid Build Coastguard Worker				"FlagWithRspFileInputList=__SBOX_SANDBOX_DIR__/out/soong/rsp Input __SBOX_SANDBOX_DIR__/out/Output " +
444*333d2b36SAndroid Build Coastguard Worker				"Text __SBOX_SANDBOX_DIR__/tools/src/Tool after command2 old cmd",
445*333d2b36SAndroid Build Coastguard Worker			"command2 __SBOX_SANDBOX_DIR__/out/depfile2 input2 __SBOX_SANDBOX_DIR__/out/output2 __SBOX_SANDBOX_DIR__/tools/src/tool2",
446*333d2b36SAndroid Build Coastguard Worker			"command3 input3 __SBOX_SANDBOX_DIR__/out/output2 __SBOX_SANDBOX_DIR__/out/output3 input3 __SBOX_SANDBOX_DIR__/out/output2",
447*333d2b36SAndroid Build Coastguard Worker		}
448*333d2b36SAndroid Build Coastguard Worker
449*333d2b36SAndroid Build Coastguard Worker		wantDepMergerCommand := "__SBOX_SANDBOX_DIR__/tools/out/bin/dep_fixer __SBOX_SANDBOX_DIR__/out/DepFile __SBOX_SANDBOX_DIR__/out/depfile __SBOX_SANDBOX_DIR__/out/ImplicitDepFile __SBOX_SANDBOX_DIR__/out/depfile2"
450*333d2b36SAndroid Build Coastguard Worker
451*333d2b36SAndroid Build Coastguard Worker		AssertDeepEquals(t, "rule.Commands()", wantCommands, rule.Commands())
452*333d2b36SAndroid Build Coastguard Worker
453*333d2b36SAndroid Build Coastguard Worker		AssertDeepEquals(t, "rule.Inputs()", wantInputs, rule.Inputs())
454*333d2b36SAndroid Build Coastguard Worker		AssertDeepEquals(t, "rule.RspfileInputs()", wantRspFileInputs, rule.RspFileInputs())
455*333d2b36SAndroid Build Coastguard Worker		AssertDeepEquals(t, "rule.Outputs()", wantOutputs, rule.Outputs())
456*333d2b36SAndroid Build Coastguard Worker		AssertDeepEquals(t, "rule.DepFiles()", wantDepFiles, rule.DepFiles())
457*333d2b36SAndroid Build Coastguard Worker		AssertDeepEquals(t, "rule.Tools()", wantTools, rule.Tools())
458*333d2b36SAndroid Build Coastguard Worker		AssertDeepEquals(t, "rule.OrderOnlys()", wantOrderOnlys, rule.OrderOnlys())
459*333d2b36SAndroid Build Coastguard Worker		AssertDeepEquals(t, "rule.Validations()", wantValidations, rule.Validations())
460*333d2b36SAndroid Build Coastguard Worker
461*333d2b36SAndroid Build Coastguard Worker		AssertSame(t, "rule.depFileMergerCmd()", wantDepMergerCommand, rule.depFileMergerCmd(rule.DepFiles()).String())
462*333d2b36SAndroid Build Coastguard Worker	})
463*333d2b36SAndroid Build Coastguard Worker}
464*333d2b36SAndroid Build Coastguard Worker
465*333d2b36SAndroid Build Coastguard Workerfunc testRuleBuilderFactory() Module {
466*333d2b36SAndroid Build Coastguard Worker	module := &testRuleBuilderModule{}
467*333d2b36SAndroid Build Coastguard Worker	module.AddProperties(&module.properties)
468*333d2b36SAndroid Build Coastguard Worker	InitAndroidModule(module)
469*333d2b36SAndroid Build Coastguard Worker	return module
470*333d2b36SAndroid Build Coastguard Worker}
471*333d2b36SAndroid Build Coastguard Worker
472*333d2b36SAndroid Build Coastguard Workertype testRuleBuilderModule struct {
473*333d2b36SAndroid Build Coastguard Worker	ModuleBase
474*333d2b36SAndroid Build Coastguard Worker	properties struct {
475*333d2b36SAndroid Build Coastguard Worker		Srcs  []string
476*333d2b36SAndroid Build Coastguard Worker		Flags []string
477*333d2b36SAndroid Build Coastguard Worker
478*333d2b36SAndroid Build Coastguard Worker		Restat      bool
479*333d2b36SAndroid Build Coastguard Worker		Sbox        bool
480*333d2b36SAndroid Build Coastguard Worker		Sbox_inputs bool
481*333d2b36SAndroid Build Coastguard Worker	}
482*333d2b36SAndroid Build Coastguard Worker}
483*333d2b36SAndroid Build Coastguard Worker
484*333d2b36SAndroid Build Coastguard Workerfunc (t *testRuleBuilderModule) GenerateAndroidBuildActions(ctx ModuleContext) {
485*333d2b36SAndroid Build Coastguard Worker	in := PathsForSource(ctx, t.properties.Srcs)
486*333d2b36SAndroid Build Coastguard Worker	implicit := PathForSource(ctx, "implicit")
487*333d2b36SAndroid Build Coastguard Worker	orderOnly := PathForSource(ctx, "orderonly")
488*333d2b36SAndroid Build Coastguard Worker	validation := PathForSource(ctx, "validation")
489*333d2b36SAndroid Build Coastguard Worker	out := PathForModuleOut(ctx, "gen", ctx.ModuleName())
490*333d2b36SAndroid Build Coastguard Worker	outDep := PathForModuleOut(ctx, "gen", ctx.ModuleName()+".d")
491*333d2b36SAndroid Build Coastguard Worker	outDir := PathForModuleOut(ctx, "gen")
492*333d2b36SAndroid Build Coastguard Worker	rspFile := PathForModuleOut(ctx, "rsp")
493*333d2b36SAndroid Build Coastguard Worker	rspFile2 := PathForModuleOut(ctx, "rsp2")
494*333d2b36SAndroid Build Coastguard Worker	rspFileContents := PathsForSource(ctx, []string{"rsp_in"})
495*333d2b36SAndroid Build Coastguard Worker	rspFileContents2 := PathsForSource(ctx, []string{"rsp_in2"})
496*333d2b36SAndroid Build Coastguard Worker	manifestPath := PathForModuleOut(ctx, "sbox.textproto")
497*333d2b36SAndroid Build Coastguard Worker
498*333d2b36SAndroid Build Coastguard Worker	testRuleBuilder_Build(ctx, in, implicit, orderOnly, validation, t.properties.Flags,
499*333d2b36SAndroid Build Coastguard Worker		out, outDep, outDir,
500*333d2b36SAndroid Build Coastguard Worker		manifestPath, t.properties.Restat, t.properties.Sbox, t.properties.Sbox_inputs,
501*333d2b36SAndroid Build Coastguard Worker		rspFile, rspFileContents, rspFile2, rspFileContents2)
502*333d2b36SAndroid Build Coastguard Worker}
503*333d2b36SAndroid Build Coastguard Worker
504*333d2b36SAndroid Build Coastguard Workertype testRuleBuilderSingleton struct{}
505*333d2b36SAndroid Build Coastguard Worker
506*333d2b36SAndroid Build Coastguard Workerfunc testRuleBuilderSingletonFactory() Singleton {
507*333d2b36SAndroid Build Coastguard Worker	return &testRuleBuilderSingleton{}
508*333d2b36SAndroid Build Coastguard Worker}
509*333d2b36SAndroid Build Coastguard Worker
510*333d2b36SAndroid Build Coastguard Workerfunc (t *testRuleBuilderSingleton) GenerateBuildActions(ctx SingletonContext) {
511*333d2b36SAndroid Build Coastguard Worker	in := PathsForSource(ctx, []string{"in"})
512*333d2b36SAndroid Build Coastguard Worker	implicit := PathForSource(ctx, "implicit")
513*333d2b36SAndroid Build Coastguard Worker	orderOnly := PathForSource(ctx, "orderonly")
514*333d2b36SAndroid Build Coastguard Worker	validation := PathForSource(ctx, "validation")
515*333d2b36SAndroid Build Coastguard Worker	out := PathForOutput(ctx, "singleton/gen/baz")
516*333d2b36SAndroid Build Coastguard Worker	outDep := PathForOutput(ctx, "singleton/gen/baz.d")
517*333d2b36SAndroid Build Coastguard Worker	outDir := PathForOutput(ctx, "singleton/gen")
518*333d2b36SAndroid Build Coastguard Worker	rspFile := PathForOutput(ctx, "singleton/rsp")
519*333d2b36SAndroid Build Coastguard Worker	rspFile2 := PathForOutput(ctx, "singleton/rsp2")
520*333d2b36SAndroid Build Coastguard Worker	rspFileContents := PathsForSource(ctx, []string{"rsp_in"})
521*333d2b36SAndroid Build Coastguard Worker	rspFileContents2 := PathsForSource(ctx, []string{"rsp_in2"})
522*333d2b36SAndroid Build Coastguard Worker	manifestPath := PathForOutput(ctx, "singleton/sbox.textproto")
523*333d2b36SAndroid Build Coastguard Worker
524*333d2b36SAndroid Build Coastguard Worker	testRuleBuilder_Build(ctx, in, implicit, orderOnly, validation, nil, out, outDep, outDir,
525*333d2b36SAndroid Build Coastguard Worker		manifestPath, true, false, false,
526*333d2b36SAndroid Build Coastguard Worker		rspFile, rspFileContents, rspFile2, rspFileContents2)
527*333d2b36SAndroid Build Coastguard Worker}
528*333d2b36SAndroid Build Coastguard Worker
529*333d2b36SAndroid Build Coastguard Workerfunc testRuleBuilder_Build(ctx BuilderContext, in Paths, implicit, orderOnly, validation Path,
530*333d2b36SAndroid Build Coastguard Worker	flags []string,
531*333d2b36SAndroid Build Coastguard Worker	out, outDep, outDir, manifestPath WritablePath,
532*333d2b36SAndroid Build Coastguard Worker	restat, sbox, sboxInputs bool,
533*333d2b36SAndroid Build Coastguard Worker	rspFile WritablePath, rspFileContents Paths, rspFile2 WritablePath, rspFileContents2 Paths) {
534*333d2b36SAndroid Build Coastguard Worker
535*333d2b36SAndroid Build Coastguard Worker	rule := NewRuleBuilder(pctx_ruleBuilderTest, ctx)
536*333d2b36SAndroid Build Coastguard Worker
537*333d2b36SAndroid Build Coastguard Worker	if sbox {
538*333d2b36SAndroid Build Coastguard Worker		rule.Sbox(outDir, manifestPath)
539*333d2b36SAndroid Build Coastguard Worker		if sboxInputs {
540*333d2b36SAndroid Build Coastguard Worker			rule.SandboxInputs()
541*333d2b36SAndroid Build Coastguard Worker		}
542*333d2b36SAndroid Build Coastguard Worker	}
543*333d2b36SAndroid Build Coastguard Worker
544*333d2b36SAndroid Build Coastguard Worker	rule.Command().
545*333d2b36SAndroid Build Coastguard Worker		Tool(PathForSource(ctx, "cp")).
546*333d2b36SAndroid Build Coastguard Worker		Flags(flags).
547*333d2b36SAndroid Build Coastguard Worker		Inputs(in).
548*333d2b36SAndroid Build Coastguard Worker		Implicit(implicit).
549*333d2b36SAndroid Build Coastguard Worker		OrderOnly(orderOnly).
550*333d2b36SAndroid Build Coastguard Worker		Validation(validation).
551*333d2b36SAndroid Build Coastguard Worker		Output(out).
552*333d2b36SAndroid Build Coastguard Worker		ImplicitDepFile(outDep).
553*333d2b36SAndroid Build Coastguard Worker		FlagWithRspFileInputList("@", rspFile, rspFileContents).
554*333d2b36SAndroid Build Coastguard Worker		FlagWithRspFileInputList("@", rspFile2, rspFileContents2)
555*333d2b36SAndroid Build Coastguard Worker
556*333d2b36SAndroid Build Coastguard Worker	if restat {
557*333d2b36SAndroid Build Coastguard Worker		rule.Restat()
558*333d2b36SAndroid Build Coastguard Worker	}
559*333d2b36SAndroid Build Coastguard Worker
560*333d2b36SAndroid Build Coastguard Worker	rule.Build("rule", "desc")
561*333d2b36SAndroid Build Coastguard Worker}
562*333d2b36SAndroid Build Coastguard Worker
563*333d2b36SAndroid Build Coastguard Workervar prepareForRuleBuilderTest = FixtureRegisterWithContext(func(ctx RegistrationContext) {
564*333d2b36SAndroid Build Coastguard Worker	ctx.RegisterModuleType("rule_builder_test", testRuleBuilderFactory)
565*333d2b36SAndroid Build Coastguard Worker	ctx.RegisterSingletonType("rule_builder_test", testRuleBuilderSingletonFactory)
566*333d2b36SAndroid Build Coastguard Worker})
567*333d2b36SAndroid Build Coastguard Worker
568*333d2b36SAndroid Build Coastguard Workerfunc TestRuleBuilder_Build(t *testing.T) {
569*333d2b36SAndroid Build Coastguard Worker	fs := MockFS{
570*333d2b36SAndroid Build Coastguard Worker		"in": nil,
571*333d2b36SAndroid Build Coastguard Worker		"cp": nil,
572*333d2b36SAndroid Build Coastguard Worker	}
573*333d2b36SAndroid Build Coastguard Worker
574*333d2b36SAndroid Build Coastguard Worker	bp := `
575*333d2b36SAndroid Build Coastguard Worker		rule_builder_test {
576*333d2b36SAndroid Build Coastguard Worker			name: "foo",
577*333d2b36SAndroid Build Coastguard Worker			srcs: ["in"],
578*333d2b36SAndroid Build Coastguard Worker			restat: true,
579*333d2b36SAndroid Build Coastguard Worker		}
580*333d2b36SAndroid Build Coastguard Worker		rule_builder_test {
581*333d2b36SAndroid Build Coastguard Worker			name: "foo_sbox",
582*333d2b36SAndroid Build Coastguard Worker			srcs: ["in"],
583*333d2b36SAndroid Build Coastguard Worker			sbox: true,
584*333d2b36SAndroid Build Coastguard Worker		}
585*333d2b36SAndroid Build Coastguard Worker		rule_builder_test {
586*333d2b36SAndroid Build Coastguard Worker			name: "foo_sbox_inputs",
587*333d2b36SAndroid Build Coastguard Worker			srcs: ["in"],
588*333d2b36SAndroid Build Coastguard Worker			sbox: true,
589*333d2b36SAndroid Build Coastguard Worker			sbox_inputs: true,
590*333d2b36SAndroid Build Coastguard Worker		}
591*333d2b36SAndroid Build Coastguard Worker	`
592*333d2b36SAndroid Build Coastguard Worker
593*333d2b36SAndroid Build Coastguard Worker	result := GroupFixturePreparers(
594*333d2b36SAndroid Build Coastguard Worker		prepareForRuleBuilderTest,
595*333d2b36SAndroid Build Coastguard Worker		FixtureWithRootAndroidBp(bp),
596*333d2b36SAndroid Build Coastguard Worker		fs.AddToFixture(),
597*333d2b36SAndroid Build Coastguard Worker	).RunTest(t)
598*333d2b36SAndroid Build Coastguard Worker
599*333d2b36SAndroid Build Coastguard Worker	check := func(t *testing.T, params TestingBuildParams, rspFile2Params TestingBuildParams,
600*333d2b36SAndroid Build Coastguard Worker		wantCommand, wantOutput, wantDepfile, wantRspFile, wantRspFile2 string,
601*333d2b36SAndroid Build Coastguard Worker		wantRestat bool, extraImplicits, extraCmdDeps []string) {
602*333d2b36SAndroid Build Coastguard Worker
603*333d2b36SAndroid Build Coastguard Worker		t.Helper()
604*333d2b36SAndroid Build Coastguard Worker		command := params.RuleParams.Command
605*333d2b36SAndroid Build Coastguard Worker		re := regexp.MustCompile(" # hash of input list: [a-z0-9]*$")
606*333d2b36SAndroid Build Coastguard Worker		command = re.ReplaceAllLiteralString(command, "")
607*333d2b36SAndroid Build Coastguard Worker
608*333d2b36SAndroid Build Coastguard Worker		AssertStringEquals(t, "RuleParams.Command", wantCommand, command)
609*333d2b36SAndroid Build Coastguard Worker
610*333d2b36SAndroid Build Coastguard Worker		wantDeps := append([]string{"cp"}, extraCmdDeps...)
611*333d2b36SAndroid Build Coastguard Worker		AssertArrayString(t, "RuleParams.CommandDeps", wantDeps, params.RuleParams.CommandDeps)
612*333d2b36SAndroid Build Coastguard Worker
613*333d2b36SAndroid Build Coastguard Worker		AssertBoolEquals(t, "RuleParams.Restat", wantRestat, params.RuleParams.Restat)
614*333d2b36SAndroid Build Coastguard Worker
615*333d2b36SAndroid Build Coastguard Worker		wantInputs := []string{"rsp_in"}
616*333d2b36SAndroid Build Coastguard Worker		AssertArrayString(t, "Inputs", wantInputs, params.Inputs.Strings())
617*333d2b36SAndroid Build Coastguard Worker
618*333d2b36SAndroid Build Coastguard Worker		wantImplicits := append([]string{"implicit", "in"}, extraImplicits...)
619*333d2b36SAndroid Build Coastguard Worker		// The second rsp file and the files listed in it should be in implicits
620*333d2b36SAndroid Build Coastguard Worker		wantImplicits = append(wantImplicits, "rsp_in2", wantRspFile2)
621*333d2b36SAndroid Build Coastguard Worker		AssertPathsRelativeToTopEquals(t, "Implicits", wantImplicits, params.Implicits)
622*333d2b36SAndroid Build Coastguard Worker
623*333d2b36SAndroid Build Coastguard Worker		wantOrderOnlys := []string{"orderonly"}
624*333d2b36SAndroid Build Coastguard Worker		AssertPathsRelativeToTopEquals(t, "OrderOnly", wantOrderOnlys, params.OrderOnly)
625*333d2b36SAndroid Build Coastguard Worker
626*333d2b36SAndroid Build Coastguard Worker		wantValidations := []string{"validation"}
627*333d2b36SAndroid Build Coastguard Worker		AssertPathsRelativeToTopEquals(t, "Validations", wantValidations, params.Validations)
628*333d2b36SAndroid Build Coastguard Worker
629*333d2b36SAndroid Build Coastguard Worker		wantRspFileContent := "$in"
630*333d2b36SAndroid Build Coastguard Worker		AssertStringEquals(t, "RspfileContent", wantRspFileContent, params.RuleParams.RspfileContent)
631*333d2b36SAndroid Build Coastguard Worker
632*333d2b36SAndroid Build Coastguard Worker		AssertStringEquals(t, "Rspfile", wantRspFile, params.RuleParams.Rspfile)
633*333d2b36SAndroid Build Coastguard Worker
634*333d2b36SAndroid Build Coastguard Worker		AssertPathRelativeToTopEquals(t, "Output", wantOutput, params.Output)
635*333d2b36SAndroid Build Coastguard Worker
636*333d2b36SAndroid Build Coastguard Worker		if len(params.ImplicitOutputs) != 0 {
637*333d2b36SAndroid Build Coastguard Worker			t.Errorf("want ImplicitOutputs = [], got %q", params.ImplicitOutputs.Strings())
638*333d2b36SAndroid Build Coastguard Worker		}
639*333d2b36SAndroid Build Coastguard Worker
640*333d2b36SAndroid Build Coastguard Worker		AssertPathRelativeToTopEquals(t, "Depfile", wantDepfile, params.Depfile)
641*333d2b36SAndroid Build Coastguard Worker
642*333d2b36SAndroid Build Coastguard Worker		if params.Deps != blueprint.DepsGCC {
643*333d2b36SAndroid Build Coastguard Worker			t.Errorf("want Deps = %q, got %q", blueprint.DepsGCC, params.Deps)
644*333d2b36SAndroid Build Coastguard Worker		}
645*333d2b36SAndroid Build Coastguard Worker
646*333d2b36SAndroid Build Coastguard Worker		rspFile2Content := ContentFromFileRuleForTests(t, result.TestContext, rspFile2Params)
647*333d2b36SAndroid Build Coastguard Worker		AssertStringEquals(t, "rspFile2 content", "rsp_in2\n", rspFile2Content)
648*333d2b36SAndroid Build Coastguard Worker	}
649*333d2b36SAndroid Build Coastguard Worker
650*333d2b36SAndroid Build Coastguard Worker	t.Run("module", func(t *testing.T) {
651*333d2b36SAndroid Build Coastguard Worker		outFile := "out/soong/.intermediates/foo/gen/foo"
652*333d2b36SAndroid Build Coastguard Worker		rspFile := "out/soong/.intermediates/foo/rsp"
653*333d2b36SAndroid Build Coastguard Worker		rspFile2 := "out/soong/.intermediates/foo/rsp2"
654*333d2b36SAndroid Build Coastguard Worker		module := result.ModuleForTests("foo", "")
655*333d2b36SAndroid Build Coastguard Worker		check(t, module.Rule("rule"), module.Output(rspFile2),
656*333d2b36SAndroid Build Coastguard Worker			"cp in "+outFile+" @"+rspFile+" @"+rspFile2,
657*333d2b36SAndroid Build Coastguard Worker			outFile, outFile+".d", rspFile, rspFile2, true, nil, nil)
658*333d2b36SAndroid Build Coastguard Worker	})
659*333d2b36SAndroid Build Coastguard Worker	t.Run("sbox", func(t *testing.T) {
660*333d2b36SAndroid Build Coastguard Worker		outDir := "out/soong/.intermediates/foo_sbox"
661*333d2b36SAndroid Build Coastguard Worker		sboxOutDir := filepath.Join(outDir, "gen")
662*333d2b36SAndroid Build Coastguard Worker		outFile := filepath.Join(sboxOutDir, "foo_sbox")
663*333d2b36SAndroid Build Coastguard Worker		depFile := filepath.Join(sboxOutDir, "foo_sbox.d")
664*333d2b36SAndroid Build Coastguard Worker		rspFile := filepath.Join(outDir, "rsp")
665*333d2b36SAndroid Build Coastguard Worker		rspFile2 := filepath.Join(outDir, "rsp2")
666*333d2b36SAndroid Build Coastguard Worker		manifest := filepath.Join(outDir, "sbox.textproto")
667*333d2b36SAndroid Build Coastguard Worker		sbox := filepath.Join("out", "soong", "host", result.Config.PrebuiltOS(), "bin/sbox")
668*333d2b36SAndroid Build Coastguard Worker		sandboxPath := shared.TempDirForOutDir("out/soong")
669*333d2b36SAndroid Build Coastguard Worker
670*333d2b36SAndroid Build Coastguard Worker		cmd := sbox + ` --sandbox-path ` + sandboxPath + ` --output-dir ` + sboxOutDir + ` --manifest ` + manifest
671*333d2b36SAndroid Build Coastguard Worker		module := result.ModuleForTests("foo_sbox", "")
672*333d2b36SAndroid Build Coastguard Worker		check(t, module.Output("gen/foo_sbox"), module.Output(rspFile2),
673*333d2b36SAndroid Build Coastguard Worker			cmd, outFile, depFile, rspFile, rspFile2, false, []string{manifest}, []string{sbox})
674*333d2b36SAndroid Build Coastguard Worker	})
675*333d2b36SAndroid Build Coastguard Worker	t.Run("sbox_inputs", func(t *testing.T) {
676*333d2b36SAndroid Build Coastguard Worker		outDir := "out/soong/.intermediates/foo_sbox_inputs"
677*333d2b36SAndroid Build Coastguard Worker		sboxOutDir := filepath.Join(outDir, "gen")
678*333d2b36SAndroid Build Coastguard Worker		outFile := filepath.Join(sboxOutDir, "foo_sbox_inputs")
679*333d2b36SAndroid Build Coastguard Worker		depFile := filepath.Join(sboxOutDir, "foo_sbox_inputs.d")
680*333d2b36SAndroid Build Coastguard Worker		rspFile := filepath.Join(outDir, "rsp")
681*333d2b36SAndroid Build Coastguard Worker		rspFile2 := filepath.Join(outDir, "rsp2")
682*333d2b36SAndroid Build Coastguard Worker		manifest := filepath.Join(outDir, "sbox.textproto")
683*333d2b36SAndroid Build Coastguard Worker		sbox := filepath.Join("out", "soong", "host", result.Config.PrebuiltOS(), "bin/sbox")
684*333d2b36SAndroid Build Coastguard Worker		sandboxPath := shared.TempDirForOutDir("out/soong")
685*333d2b36SAndroid Build Coastguard Worker
686*333d2b36SAndroid Build Coastguard Worker		cmd := sbox + ` --sandbox-path ` + sandboxPath + ` --output-dir ` + sboxOutDir + ` --manifest ` + manifest
687*333d2b36SAndroid Build Coastguard Worker
688*333d2b36SAndroid Build Coastguard Worker		module := result.ModuleForTests("foo_sbox_inputs", "")
689*333d2b36SAndroid Build Coastguard Worker		check(t, module.Output("gen/foo_sbox_inputs"), module.Output(rspFile2),
690*333d2b36SAndroid Build Coastguard Worker			cmd, outFile, depFile, rspFile, rspFile2, false, []string{manifest}, []string{sbox})
691*333d2b36SAndroid Build Coastguard Worker	})
692*333d2b36SAndroid Build Coastguard Worker	t.Run("singleton", func(t *testing.T) {
693*333d2b36SAndroid Build Coastguard Worker		outFile := filepath.Join("out/soong/singleton/gen/baz")
694*333d2b36SAndroid Build Coastguard Worker		rspFile := filepath.Join("out/soong/singleton/rsp")
695*333d2b36SAndroid Build Coastguard Worker		rspFile2 := filepath.Join("out/soong/singleton/rsp2")
696*333d2b36SAndroid Build Coastguard Worker		singleton := result.SingletonForTests("rule_builder_test")
697*333d2b36SAndroid Build Coastguard Worker		check(t, singleton.Rule("rule"), singleton.Output(rspFile2),
698*333d2b36SAndroid Build Coastguard Worker			"cp in "+outFile+" @"+rspFile+" @"+rspFile2,
699*333d2b36SAndroid Build Coastguard Worker			outFile, outFile+".d", rspFile, rspFile2, true, nil, nil)
700*333d2b36SAndroid Build Coastguard Worker	})
701*333d2b36SAndroid Build Coastguard Worker}
702*333d2b36SAndroid Build Coastguard Worker
703*333d2b36SAndroid Build Coastguard Workerfunc TestRuleBuilderHashInputs(t *testing.T) {
704*333d2b36SAndroid Build Coastguard Worker	// The basic idea here is to verify that the command (in the case of a
705*333d2b36SAndroid Build Coastguard Worker	// non-sbox rule) or the sbox textproto manifest contain a hash of the
706*333d2b36SAndroid Build Coastguard Worker	// inputs.
707*333d2b36SAndroid Build Coastguard Worker
708*333d2b36SAndroid Build Coastguard Worker	// By including a hash of the inputs, we cause the rule to re-run if
709*333d2b36SAndroid Build Coastguard Worker	// the list of inputs changes because the command line or a dependency
710*333d2b36SAndroid Build Coastguard Worker	// changes.
711*333d2b36SAndroid Build Coastguard Worker
712*333d2b36SAndroid Build Coastguard Worker	hashOf := func(s string) string {
713*333d2b36SAndroid Build Coastguard Worker		sum := sha256.Sum256([]byte(s))
714*333d2b36SAndroid Build Coastguard Worker		return hex.EncodeToString(sum[:])
715*333d2b36SAndroid Build Coastguard Worker	}
716*333d2b36SAndroid Build Coastguard Worker
717*333d2b36SAndroid Build Coastguard Worker	bp := `
718*333d2b36SAndroid Build Coastguard Worker			rule_builder_test {
719*333d2b36SAndroid Build Coastguard Worker				name: "hash0",
720*333d2b36SAndroid Build Coastguard Worker				srcs: ["in1.txt", "in2.txt"],
721*333d2b36SAndroid Build Coastguard Worker			}
722*333d2b36SAndroid Build Coastguard Worker			rule_builder_test {
723*333d2b36SAndroid Build Coastguard Worker				name: "hash0_sbox",
724*333d2b36SAndroid Build Coastguard Worker				srcs: ["in1.txt", "in2.txt"],
725*333d2b36SAndroid Build Coastguard Worker				sbox: true,
726*333d2b36SAndroid Build Coastguard Worker			}
727*333d2b36SAndroid Build Coastguard Worker			rule_builder_test {
728*333d2b36SAndroid Build Coastguard Worker				name: "hash1",
729*333d2b36SAndroid Build Coastguard Worker				srcs: ["in1.txt", "in2.txt", "in3.txt"],
730*333d2b36SAndroid Build Coastguard Worker			}
731*333d2b36SAndroid Build Coastguard Worker			rule_builder_test {
732*333d2b36SAndroid Build Coastguard Worker				name: "hash1_sbox",
733*333d2b36SAndroid Build Coastguard Worker				srcs: ["in1.txt", "in2.txt", "in3.txt"],
734*333d2b36SAndroid Build Coastguard Worker				sbox: true,
735*333d2b36SAndroid Build Coastguard Worker			}
736*333d2b36SAndroid Build Coastguard Worker		`
737*333d2b36SAndroid Build Coastguard Worker	testcases := []struct {
738*333d2b36SAndroid Build Coastguard Worker		name         string
739*333d2b36SAndroid Build Coastguard Worker		expectedHash string
740*333d2b36SAndroid Build Coastguard Worker	}{
741*333d2b36SAndroid Build Coastguard Worker		{
742*333d2b36SAndroid Build Coastguard Worker			name:         "hash0",
743*333d2b36SAndroid Build Coastguard Worker			expectedHash: hashOf("implicit\nin1.txt\nin2.txt"),
744*333d2b36SAndroid Build Coastguard Worker		},
745*333d2b36SAndroid Build Coastguard Worker		{
746*333d2b36SAndroid Build Coastguard Worker			name:         "hash1",
747*333d2b36SAndroid Build Coastguard Worker			expectedHash: hashOf("implicit\nin1.txt\nin2.txt\nin3.txt"),
748*333d2b36SAndroid Build Coastguard Worker		},
749*333d2b36SAndroid Build Coastguard Worker	}
750*333d2b36SAndroid Build Coastguard Worker
751*333d2b36SAndroid Build Coastguard Worker	result := GroupFixturePreparers(
752*333d2b36SAndroid Build Coastguard Worker		prepareForRuleBuilderTest,
753*333d2b36SAndroid Build Coastguard Worker		FixtureWithRootAndroidBp(bp),
754*333d2b36SAndroid Build Coastguard Worker	).RunTest(t)
755*333d2b36SAndroid Build Coastguard Worker
756*333d2b36SAndroid Build Coastguard Worker	for _, test := range testcases {
757*333d2b36SAndroid Build Coastguard Worker		t.Run(test.name, func(t *testing.T) {
758*333d2b36SAndroid Build Coastguard Worker			t.Run("sbox", func(t *testing.T) {
759*333d2b36SAndroid Build Coastguard Worker				gen := result.ModuleForTests(test.name+"_sbox", "")
760*333d2b36SAndroid Build Coastguard Worker				manifest := RuleBuilderSboxProtoForTests(t, result.TestContext, gen.Output("sbox.textproto"))
761*333d2b36SAndroid Build Coastguard Worker				hash := manifest.Commands[0].GetInputHash()
762*333d2b36SAndroid Build Coastguard Worker
763*333d2b36SAndroid Build Coastguard Worker				AssertStringEquals(t, "hash", test.expectedHash, hash)
764*333d2b36SAndroid Build Coastguard Worker			})
765*333d2b36SAndroid Build Coastguard Worker			t.Run("", func(t *testing.T) {
766*333d2b36SAndroid Build Coastguard Worker				gen := result.ModuleForTests(test.name+"", "")
767*333d2b36SAndroid Build Coastguard Worker				command := gen.Output("gen/" + test.name).RuleParams.Command
768*333d2b36SAndroid Build Coastguard Worker				if g, w := command, " # hash of input list: "+test.expectedHash; !strings.HasSuffix(g, w) {
769*333d2b36SAndroid Build Coastguard Worker					t.Errorf("Expected command line to end with %q, got %q", w, g)
770*333d2b36SAndroid Build Coastguard Worker				}
771*333d2b36SAndroid Build Coastguard Worker			})
772*333d2b36SAndroid Build Coastguard Worker		})
773*333d2b36SAndroid Build Coastguard Worker	}
774*333d2b36SAndroid Build Coastguard Worker}
775