blob: 533b09087d865629b8f276397e52f24a0a0234e3 [file] [log] [blame]
Colin Crossfeec25b2019-01-30 17:32:39 -08001// Copyright 2019 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package android
16
17import (
18 "io/ioutil"
19 "os"
20 "path/filepath"
21 "reflect"
22 "testing"
23)
24
25func TestRuleBuilder(t *testing.T) {
26 rule := RuleBuilder{}
27
28 cmd := rule.Command().
29 Flag("Flag").
30 FlagWithArg("FlagWithArg=", "arg").
31 FlagWithInput("FlagWithInput=", "input").
32 FlagWithOutput("FlagWithOutput=", "output").
33 Implicit("Implicit").
34 ImplicitOutput("ImplicitOutput").
35 Input("Input").
36 Output("Output").
37 Text("Text").
38 Tool("Tool")
39
40 rule.Command().
41 Text("command2").
42 Input("input2").
43 Output("output2").
44 Tool("tool2")
45
46 // Test updates to the first command after the second command has been started
47 cmd.Text("after command2")
48 // Test updating a command when the previous update did not replace the cmd variable
49 cmd.Text("old cmd")
50
51 // Test a command that uses the output of a previous command as an input
52 rule.Command().
53 Text("command3").
54 Input("input3").
55 Input("output2").
56 Output("output3")
57
58 wantCommands := []string{
59 "Flag FlagWithArg=arg FlagWithInput=input FlagWithOutput=output Input Output Text Tool after command2 old cmd",
60 "command2 input2 output2 tool2",
61 "command3 input3 output2 output3",
62 }
63 wantInputs := []string{"Implicit", "Input", "input", "input2", "input3"}
64 wantOutputs := []string{"ImplicitOutput", "Output", "output", "output2", "output3"}
65 wantTools := []string{"Tool", "tool2"}
66
67 if !reflect.DeepEqual(rule.Commands(), wantCommands) {
68 t.Errorf("\nwant rule.Commands() = %#v\n got %#v", wantCommands, rule.Commands())
69 }
70 if !reflect.DeepEqual(rule.Inputs(), wantInputs) {
71 t.Errorf("\nwant rule.Inputs() = %#v\n got %#v", wantInputs, rule.Inputs())
72 }
73 if !reflect.DeepEqual(rule.Outputs(), wantOutputs) {
74 t.Errorf("\nwant rule.Outputs() = %#v\n got %#v", wantOutputs, rule.Outputs())
75 }
76 if !reflect.DeepEqual(rule.Tools(), wantTools) {
77 t.Errorf("\nwant rule.Tools() = %#v\n got %#v", wantTools, rule.Tools())
78 }
79}
80
81func testRuleBuilderFactory() Module {
82 module := &testRuleBuilderModule{}
83 module.AddProperties(&module.properties)
84 InitAndroidModule(module)
85 return module
86}
87
88type testRuleBuilderModule struct {
89 ModuleBase
90 properties struct {
91 Src string
92 }
93}
94
95func (t *testRuleBuilderModule) GenerateAndroidBuildActions(ctx ModuleContext) {
Colin Crossfeec25b2019-01-30 17:32:39 -080096 in := PathForSource(ctx, t.properties.Src)
97 out := PathForModuleOut(ctx, ctx.ModuleName())
98
Colin Cross786cd6d2019-02-01 16:41:11 -080099 testRuleBuilder_Build(ctx, in, out)
100}
101
102type testRuleBuilderSingleton struct{}
103
104func testRuleBuilderSingletonFactory() Singleton {
105 return &testRuleBuilderSingleton{}
106}
107
108func (t *testRuleBuilderSingleton) GenerateBuildActions(ctx SingletonContext) {
109 in := PathForSource(ctx, "bar")
110 out := PathForOutput(ctx, "baz")
111 testRuleBuilder_Build(ctx, in, out)
112}
113
114func testRuleBuilder_Build(ctx BuilderContext, in Path, out WritablePath) {
115 rule := RuleBuilder{}
116
Colin Crossfeec25b2019-01-30 17:32:39 -0800117 rule.Command().Tool("cp").Input(in.String()).Output(out.String())
118
119 rule.Build(pctx, ctx, "rule", "desc")
120}
121
122func TestRuleBuilder_Build(t *testing.T) {
123 buildDir, err := ioutil.TempDir("", "soong_test_rule_builder")
124 if err != nil {
125 t.Fatal(err)
126 }
127 defer os.RemoveAll(buildDir)
128
129 bp := `
130 rule_builder_test {
131 name: "foo",
132 src: "bar",
133 }
134 `
135
136 config := TestConfig(buildDir, nil)
137 ctx := NewTestContext()
138 ctx.MockFileSystem(map[string][]byte{
139 "Android.bp": []byte(bp),
140 "bar": nil,
141 "cp": nil,
142 })
143 ctx.RegisterModuleType("rule_builder_test", ModuleFactoryAdaptor(testRuleBuilderFactory))
Colin Cross786cd6d2019-02-01 16:41:11 -0800144 ctx.RegisterSingletonType("rule_builder_test", SingletonFactoryAdaptor(testRuleBuilderSingletonFactory))
Colin Crossfeec25b2019-01-30 17:32:39 -0800145 ctx.Register()
146
147 _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
148 FailIfErrored(t, errs)
149 _, errs = ctx.PrepareBuildActions(config)
150 FailIfErrored(t, errs)
151
152 foo := ctx.ModuleForTests("foo", "").Rule("rule")
153
154 // TODO: make RuleParams accessible to tests and verify rule.Command().Tools() ends up in CommandDeps
155
156 if len(foo.Implicits) != 1 || foo.Implicits[0].String() != "bar" {
157 t.Errorf("want foo.Implicits = [%q], got %q", "bar", foo.Implicits.Strings())
158 }
159
160 wantOutput := filepath.Join(buildDir, ".intermediates", "foo", "foo")
161 if len(foo.Outputs) != 1 || foo.Outputs[0].String() != wantOutput {
162 t.Errorf("want foo.Outputs = [%q], got %q", wantOutput, foo.Outputs.Strings())
163 }
164
165}