xref: /aosp_15_r20/build/soong/tradefed/autogen.go (revision 333d2b3687b3a337dbcca9d65000bca186795e39)
1*333d2b36SAndroid Build Coastguard Worker// Copyright 2018 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 tradefed
16*333d2b36SAndroid Build Coastguard Worker
17*333d2b36SAndroid Build Coastguard Workerimport (
18*333d2b36SAndroid Build Coastguard Worker	"fmt"
19*333d2b36SAndroid Build Coastguard Worker	"strings"
20*333d2b36SAndroid Build Coastguard Worker
21*333d2b36SAndroid Build Coastguard Worker	"github.com/google/blueprint"
22*333d2b36SAndroid Build Coastguard Worker	"github.com/google/blueprint/proptools"
23*333d2b36SAndroid Build Coastguard Worker
24*333d2b36SAndroid Build Coastguard Worker	"android/soong/android"
25*333d2b36SAndroid Build Coastguard Worker)
26*333d2b36SAndroid Build Coastguard Worker
27*333d2b36SAndroid Build Coastguard Workerconst test_xml_indent = "    "
28*333d2b36SAndroid Build Coastguard Worker
29*333d2b36SAndroid Build Coastguard Workerfunc getTestConfigTemplate(ctx android.ModuleContext, prop *string) android.OptionalPath {
30*333d2b36SAndroid Build Coastguard Worker	return ctx.ExpandOptionalSource(prop, "test_config_template")
31*333d2b36SAndroid Build Coastguard Worker}
32*333d2b36SAndroid Build Coastguard Worker
33*333d2b36SAndroid Build Coastguard Workerfunc getTestConfig(ctx android.ModuleContext, prop *string) android.Path {
34*333d2b36SAndroid Build Coastguard Worker	if p := ctx.ExpandOptionalSource(prop, "test_config"); p.Valid() {
35*333d2b36SAndroid Build Coastguard Worker		return p.Path()
36*333d2b36SAndroid Build Coastguard Worker	} else if p := android.ExistentPathForSource(ctx, ctx.ModuleDir(), "AndroidTest.xml"); p.Valid() {
37*333d2b36SAndroid Build Coastguard Worker		return p.Path()
38*333d2b36SAndroid Build Coastguard Worker	}
39*333d2b36SAndroid Build Coastguard Worker	return nil
40*333d2b36SAndroid Build Coastguard Worker}
41*333d2b36SAndroid Build Coastguard Worker
42*333d2b36SAndroid Build Coastguard Workervar autogenTestConfig = pctx.StaticRule("autogenTestConfig", blueprint.RuleParams{
43*333d2b36SAndroid Build Coastguard Worker	Command:     "sed 's&{MODULE}&${name}&g;s&{EXTRA_CONFIGS}&'${extraConfigs}'&g;s&{EXTRA_TEST_RUNNER_CONFIGS}&'${extraTestRunnerConfigs}'&g;s&{OUTPUT_FILENAME}&'${outputFileName}'&g;s&{TEST_INSTALL_BASE}&'${testInstallBase}'&g' $template > $out",
44*333d2b36SAndroid Build Coastguard Worker	CommandDeps: []string{"$template"},
45*333d2b36SAndroid Build Coastguard Worker}, "name", "template", "extraConfigs", "outputFileName", "testInstallBase", "extraTestRunnerConfigs")
46*333d2b36SAndroid Build Coastguard Worker
47*333d2b36SAndroid Build Coastguard Workerfunc testConfigPath(ctx android.ModuleContext, prop *string, testSuites []string, autoGenConfig *bool, testConfigTemplateProp *string) (path android.Path, autogenPath android.WritablePath) {
48*333d2b36SAndroid Build Coastguard Worker	p := getTestConfig(ctx, prop)
49*333d2b36SAndroid Build Coastguard Worker	if !Bool(autoGenConfig) && p != nil {
50*333d2b36SAndroid Build Coastguard Worker		return p, nil
51*333d2b36SAndroid Build Coastguard Worker	} else if BoolDefault(autoGenConfig, true) && (!android.InList("cts", testSuites) || testConfigTemplateProp != nil) {
52*333d2b36SAndroid Build Coastguard Worker		outputFile := android.PathForModuleOut(ctx, ctx.ModuleName()+".config")
53*333d2b36SAndroid Build Coastguard Worker		return nil, outputFile
54*333d2b36SAndroid Build Coastguard Worker	} else {
55*333d2b36SAndroid Build Coastguard Worker		// CTS modules can be used for test data, so test config files must be
56*333d2b36SAndroid Build Coastguard Worker		// explicitly created using AndroidTest.xml or test_config_template.
57*333d2b36SAndroid Build Coastguard Worker		return nil, nil
58*333d2b36SAndroid Build Coastguard Worker	}
59*333d2b36SAndroid Build Coastguard Worker}
60*333d2b36SAndroid Build Coastguard Worker
61*333d2b36SAndroid Build Coastguard Workertype Config interface {
62*333d2b36SAndroid Build Coastguard Worker	Config() string
63*333d2b36SAndroid Build Coastguard Worker}
64*333d2b36SAndroid Build Coastguard Worker
65*333d2b36SAndroid Build Coastguard Workertype Option struct {
66*333d2b36SAndroid Build Coastguard Worker	Name  string
67*333d2b36SAndroid Build Coastguard Worker	Key   string
68*333d2b36SAndroid Build Coastguard Worker	Value string
69*333d2b36SAndroid Build Coastguard Worker}
70*333d2b36SAndroid Build Coastguard Worker
71*333d2b36SAndroid Build Coastguard Workervar _ Config = Option{}
72*333d2b36SAndroid Build Coastguard Worker
73*333d2b36SAndroid Build Coastguard Workerfunc (o Option) Config() string {
74*333d2b36SAndroid Build Coastguard Worker	if o.Key != "" {
75*333d2b36SAndroid Build Coastguard Worker		return fmt.Sprintf(`<option name="%s" key="%s" value="%s" />`, o.Name, o.Key, o.Value)
76*333d2b36SAndroid Build Coastguard Worker	}
77*333d2b36SAndroid Build Coastguard Worker	return fmt.Sprintf(`<option name="%s" value="%s" />`, o.Name, o.Value)
78*333d2b36SAndroid Build Coastguard Worker}
79*333d2b36SAndroid Build Coastguard Worker
80*333d2b36SAndroid Build Coastguard Worker// It can be a template of object or target_preparer.
81*333d2b36SAndroid Build Coastguard Workertype Object struct {
82*333d2b36SAndroid Build Coastguard Worker	// Set it as a target_preparer if object type == "target_preparer".
83*333d2b36SAndroid Build Coastguard Worker	Type    string
84*333d2b36SAndroid Build Coastguard Worker	Class   string
85*333d2b36SAndroid Build Coastguard Worker	Options []Option
86*333d2b36SAndroid Build Coastguard Worker}
87*333d2b36SAndroid Build Coastguard Worker
88*333d2b36SAndroid Build Coastguard Workervar _ Config = Object{}
89*333d2b36SAndroid Build Coastguard Worker
90*333d2b36SAndroid Build Coastguard Workerfunc (ob Object) Config() string {
91*333d2b36SAndroid Build Coastguard Worker	var optionStrings []string
92*333d2b36SAndroid Build Coastguard Worker	for _, option := range ob.Options {
93*333d2b36SAndroid Build Coastguard Worker		optionStrings = append(optionStrings, option.Config())
94*333d2b36SAndroid Build Coastguard Worker	}
95*333d2b36SAndroid Build Coastguard Worker	var options string
96*333d2b36SAndroid Build Coastguard Worker	if len(ob.Options) == 0 {
97*333d2b36SAndroid Build Coastguard Worker		options = ""
98*333d2b36SAndroid Build Coastguard Worker	} else {
99*333d2b36SAndroid Build Coastguard Worker		optionDelimiter := fmt.Sprintf("\\n%s%s", test_xml_indent, test_xml_indent)
100*333d2b36SAndroid Build Coastguard Worker		options = optionDelimiter + strings.Join(optionStrings, optionDelimiter)
101*333d2b36SAndroid Build Coastguard Worker	}
102*333d2b36SAndroid Build Coastguard Worker	if ob.Type == "target_preparer" {
103*333d2b36SAndroid Build Coastguard Worker		return fmt.Sprintf(`<target_preparer class="%s">%s\n%s</target_preparer>`, ob.Class, options, test_xml_indent)
104*333d2b36SAndroid Build Coastguard Worker	} else {
105*333d2b36SAndroid Build Coastguard Worker		return fmt.Sprintf(`<object type="%s" class="%s">%s\n%s</object>`, ob.Type, ob.Class, options, test_xml_indent)
106*333d2b36SAndroid Build Coastguard Worker	}
107*333d2b36SAndroid Build Coastguard Worker
108*333d2b36SAndroid Build Coastguard Worker}
109*333d2b36SAndroid Build Coastguard Worker
110*333d2b36SAndroid Build Coastguard Workerfunc autogenTemplate(ctx android.ModuleContext, name string, output android.WritablePath, template string, configs []Config, testRunnerConfigs []Option, outputFileName string, testInstallBase string) {
111*333d2b36SAndroid Build Coastguard Worker	if template == "" {
112*333d2b36SAndroid Build Coastguard Worker		ctx.ModuleErrorf("Empty template")
113*333d2b36SAndroid Build Coastguard Worker	}
114*333d2b36SAndroid Build Coastguard Worker	var configStrings []string
115*333d2b36SAndroid Build Coastguard Worker	for _, config := range configs {
116*333d2b36SAndroid Build Coastguard Worker		configStrings = append(configStrings, config.Config())
117*333d2b36SAndroid Build Coastguard Worker	}
118*333d2b36SAndroid Build Coastguard Worker	extraConfigs := strings.Join(configStrings, fmt.Sprintf("\\n%s", test_xml_indent))
119*333d2b36SAndroid Build Coastguard Worker	extraConfigs = proptools.NinjaAndShellEscape(extraConfigs)
120*333d2b36SAndroid Build Coastguard Worker
121*333d2b36SAndroid Build Coastguard Worker	var testRunnerConfigStrings []string
122*333d2b36SAndroid Build Coastguard Worker	for _, config := range testRunnerConfigs {
123*333d2b36SAndroid Build Coastguard Worker		testRunnerConfigStrings = append(testRunnerConfigStrings, config.Config())
124*333d2b36SAndroid Build Coastguard Worker	}
125*333d2b36SAndroid Build Coastguard Worker	extraTestRunnerConfigs := strings.Join(testRunnerConfigStrings, fmt.Sprintf("\\n%s%s", test_xml_indent, test_xml_indent))
126*333d2b36SAndroid Build Coastguard Worker	if len(extraTestRunnerConfigs) > 0 {
127*333d2b36SAndroid Build Coastguard Worker		extraTestRunnerConfigs += fmt.Sprintf("\\n%s%s", test_xml_indent, test_xml_indent)
128*333d2b36SAndroid Build Coastguard Worker	}
129*333d2b36SAndroid Build Coastguard Worker	extraTestRunnerConfigs = proptools.NinjaAndShellEscape(extraTestRunnerConfigs)
130*333d2b36SAndroid Build Coastguard Worker
131*333d2b36SAndroid Build Coastguard Worker	ctx.Build(pctx, android.BuildParams{
132*333d2b36SAndroid Build Coastguard Worker		Rule:        autogenTestConfig,
133*333d2b36SAndroid Build Coastguard Worker		Description: "test config",
134*333d2b36SAndroid Build Coastguard Worker		Output:      output,
135*333d2b36SAndroid Build Coastguard Worker		Args: map[string]string{
136*333d2b36SAndroid Build Coastguard Worker			"name":                   name,
137*333d2b36SAndroid Build Coastguard Worker			"template":               template,
138*333d2b36SAndroid Build Coastguard Worker			"extraConfigs":           extraConfigs,
139*333d2b36SAndroid Build Coastguard Worker			"outputFileName":         outputFileName,
140*333d2b36SAndroid Build Coastguard Worker			"testInstallBase":        testInstallBase,
141*333d2b36SAndroid Build Coastguard Worker			"extraTestRunnerConfigs": extraTestRunnerConfigs,
142*333d2b36SAndroid Build Coastguard Worker		},
143*333d2b36SAndroid Build Coastguard Worker	})
144*333d2b36SAndroid Build Coastguard Worker}
145*333d2b36SAndroid Build Coastguard Worker
146*333d2b36SAndroid Build Coastguard Worker// AutoGenTestConfigOptions is used so that we can supply many optional
147*333d2b36SAndroid Build Coastguard Worker// arguments to the AutoGenTestConfig function.
148*333d2b36SAndroid Build Coastguard Workertype AutoGenTestConfigOptions struct {
149*333d2b36SAndroid Build Coastguard Worker	Name                    string
150*333d2b36SAndroid Build Coastguard Worker	OutputFileName          string
151*333d2b36SAndroid Build Coastguard Worker	TestConfigProp          *string
152*333d2b36SAndroid Build Coastguard Worker	TestConfigTemplateProp  *string
153*333d2b36SAndroid Build Coastguard Worker	TestSuites              []string
154*333d2b36SAndroid Build Coastguard Worker	Config                  []Config
155*333d2b36SAndroid Build Coastguard Worker	OptionsForAutogenerated []Option
156*333d2b36SAndroid Build Coastguard Worker	TestRunnerOptions       []Option
157*333d2b36SAndroid Build Coastguard Worker	AutoGenConfig           *bool
158*333d2b36SAndroid Build Coastguard Worker	UnitTest                *bool
159*333d2b36SAndroid Build Coastguard Worker	TestInstallBase         string
160*333d2b36SAndroid Build Coastguard Worker	DeviceTemplate          string
161*333d2b36SAndroid Build Coastguard Worker	HostTemplate            string
162*333d2b36SAndroid Build Coastguard Worker	HostUnitTestTemplate    string
163*333d2b36SAndroid Build Coastguard Worker}
164*333d2b36SAndroid Build Coastguard Worker
165*333d2b36SAndroid Build Coastguard Workerfunc AutoGenTestConfig(ctx android.ModuleContext, options AutoGenTestConfigOptions) android.Path {
166*333d2b36SAndroid Build Coastguard Worker	configs := append([]Config{}, options.Config...)
167*333d2b36SAndroid Build Coastguard Worker	for _, c := range options.OptionsForAutogenerated {
168*333d2b36SAndroid Build Coastguard Worker		configs = append(configs, c)
169*333d2b36SAndroid Build Coastguard Worker	}
170*333d2b36SAndroid Build Coastguard Worker	name := options.Name
171*333d2b36SAndroid Build Coastguard Worker	if name == "" {
172*333d2b36SAndroid Build Coastguard Worker		name = ctx.ModuleName()
173*333d2b36SAndroid Build Coastguard Worker	}
174*333d2b36SAndroid Build Coastguard Worker	path, autogenPath := testConfigPath(ctx, options.TestConfigProp, options.TestSuites, options.AutoGenConfig, options.TestConfigTemplateProp)
175*333d2b36SAndroid Build Coastguard Worker	if autogenPath != nil {
176*333d2b36SAndroid Build Coastguard Worker		templatePath := getTestConfigTemplate(ctx, options.TestConfigTemplateProp)
177*333d2b36SAndroid Build Coastguard Worker		if templatePath.Valid() {
178*333d2b36SAndroid Build Coastguard Worker			autogenTemplate(ctx, name, autogenPath, templatePath.String(), configs, options.TestRunnerOptions, options.OutputFileName, options.TestInstallBase)
179*333d2b36SAndroid Build Coastguard Worker		} else {
180*333d2b36SAndroid Build Coastguard Worker			if ctx.Device() {
181*333d2b36SAndroid Build Coastguard Worker				autogenTemplate(ctx, name, autogenPath, options.DeviceTemplate, configs, options.TestRunnerOptions, options.OutputFileName, options.TestInstallBase)
182*333d2b36SAndroid Build Coastguard Worker			} else {
183*333d2b36SAndroid Build Coastguard Worker				if Bool(options.UnitTest) {
184*333d2b36SAndroid Build Coastguard Worker					autogenTemplate(ctx, name, autogenPath, options.HostUnitTestTemplate, configs, options.TestRunnerOptions, options.OutputFileName, options.TestInstallBase)
185*333d2b36SAndroid Build Coastguard Worker				} else {
186*333d2b36SAndroid Build Coastguard Worker					autogenTemplate(ctx, name, autogenPath, options.HostTemplate, configs, options.TestRunnerOptions, options.OutputFileName, options.TestInstallBase)
187*333d2b36SAndroid Build Coastguard Worker				}
188*333d2b36SAndroid Build Coastguard Worker			}
189*333d2b36SAndroid Build Coastguard Worker		}
190*333d2b36SAndroid Build Coastguard Worker		return autogenPath
191*333d2b36SAndroid Build Coastguard Worker	}
192*333d2b36SAndroid Build Coastguard Worker	if len(options.OptionsForAutogenerated) > 0 {
193*333d2b36SAndroid Build Coastguard Worker		ctx.ModuleErrorf("Extra tradefed configurations were provided for an autogenerated xml file, but the autogenerated xml file was not used.")
194*333d2b36SAndroid Build Coastguard Worker	}
195*333d2b36SAndroid Build Coastguard Worker	return path
196*333d2b36SAndroid Build Coastguard Worker}
197*333d2b36SAndroid Build Coastguard Worker
198*333d2b36SAndroid Build Coastguard Workervar autogenInstrumentationTest = pctx.StaticRule("autogenInstrumentationTest", blueprint.RuleParams{
199*333d2b36SAndroid Build Coastguard Worker	Command: "${AutoGenTestConfigScript} $out $in ${EmptyTestConfig} $template ${extraConfigs} ${extraTestRunnerConfigs}",
200*333d2b36SAndroid Build Coastguard Worker	CommandDeps: []string{
201*333d2b36SAndroid Build Coastguard Worker		"${AutoGenTestConfigScript}",
202*333d2b36SAndroid Build Coastguard Worker		"${EmptyTestConfig}",
203*333d2b36SAndroid Build Coastguard Worker		"$template",
204*333d2b36SAndroid Build Coastguard Worker	},
205*333d2b36SAndroid Build Coastguard Worker}, "name", "template", "extraConfigs", "extraTestRunnerConfigs")
206*333d2b36SAndroid Build Coastguard Worker
207*333d2b36SAndroid Build Coastguard Workerfunc AutoGenInstrumentationTestConfig(ctx android.ModuleContext, testConfigProp *string,
208*333d2b36SAndroid Build Coastguard Worker	testConfigTemplateProp *string, manifest android.Path, testSuites []string, autoGenConfig *bool, configs []Config, testRunnerConfigs []Option) android.Path {
209*333d2b36SAndroid Build Coastguard Worker	path, autogenPath := testConfigPath(ctx, testConfigProp, testSuites, autoGenConfig, testConfigTemplateProp)
210*333d2b36SAndroid Build Coastguard Worker	var configStrings []string
211*333d2b36SAndroid Build Coastguard Worker	if autogenPath != nil {
212*333d2b36SAndroid Build Coastguard Worker		template := "${InstrumentationTestConfigTemplate}"
213*333d2b36SAndroid Build Coastguard Worker		moduleTemplate := getTestConfigTemplate(ctx, testConfigTemplateProp)
214*333d2b36SAndroid Build Coastguard Worker		if moduleTemplate.Valid() {
215*333d2b36SAndroid Build Coastguard Worker			template = moduleTemplate.String()
216*333d2b36SAndroid Build Coastguard Worker		}
217*333d2b36SAndroid Build Coastguard Worker		for _, config := range configs {
218*333d2b36SAndroid Build Coastguard Worker			configStrings = append(configStrings, config.Config())
219*333d2b36SAndroid Build Coastguard Worker		}
220*333d2b36SAndroid Build Coastguard Worker		extraConfigs := strings.Join(configStrings, fmt.Sprintf("\\n%s", test_xml_indent))
221*333d2b36SAndroid Build Coastguard Worker		extraConfigs = fmt.Sprintf("--extra-configs '%s'", extraConfigs)
222*333d2b36SAndroid Build Coastguard Worker
223*333d2b36SAndroid Build Coastguard Worker		var testRunnerConfigStrings []string
224*333d2b36SAndroid Build Coastguard Worker		for _, config := range testRunnerConfigs {
225*333d2b36SAndroid Build Coastguard Worker			testRunnerConfigStrings = append(testRunnerConfigStrings, config.Config())
226*333d2b36SAndroid Build Coastguard Worker		}
227*333d2b36SAndroid Build Coastguard Worker		extraTestRunnerConfigs := strings.Join(testRunnerConfigStrings, fmt.Sprintf("\\n%s%s", test_xml_indent, test_xml_indent))
228*333d2b36SAndroid Build Coastguard Worker		if len(extraTestRunnerConfigs) > 0 {
229*333d2b36SAndroid Build Coastguard Worker			extraTestRunnerConfigs += fmt.Sprintf("\\n%s%s", test_xml_indent, test_xml_indent)
230*333d2b36SAndroid Build Coastguard Worker		}
231*333d2b36SAndroid Build Coastguard Worker		extraTestRunnerConfigs = fmt.Sprintf("--extra-test-runner-configs '%s'", extraTestRunnerConfigs)
232*333d2b36SAndroid Build Coastguard Worker
233*333d2b36SAndroid Build Coastguard Worker		ctx.Build(pctx, android.BuildParams{
234*333d2b36SAndroid Build Coastguard Worker			Rule:        autogenInstrumentationTest,
235*333d2b36SAndroid Build Coastguard Worker			Description: "test config",
236*333d2b36SAndroid Build Coastguard Worker			Input:       manifest,
237*333d2b36SAndroid Build Coastguard Worker			Output:      autogenPath,
238*333d2b36SAndroid Build Coastguard Worker			Args: map[string]string{
239*333d2b36SAndroid Build Coastguard Worker				"name":                   ctx.ModuleName(),
240*333d2b36SAndroid Build Coastguard Worker				"template":               template,
241*333d2b36SAndroid Build Coastguard Worker				"extraConfigs":           extraConfigs,
242*333d2b36SAndroid Build Coastguard Worker				"extraTestRunnerConfigs": extraTestRunnerConfigs,
243*333d2b36SAndroid Build Coastguard Worker			},
244*333d2b36SAndroid Build Coastguard Worker		})
245*333d2b36SAndroid Build Coastguard Worker		return autogenPath
246*333d2b36SAndroid Build Coastguard Worker	}
247*333d2b36SAndroid Build Coastguard Worker	return path
248*333d2b36SAndroid Build Coastguard Worker}
249*333d2b36SAndroid Build Coastguard Worker
250*333d2b36SAndroid Build Coastguard Workervar Bool = proptools.Bool
251*333d2b36SAndroid Build Coastguard Workervar BoolDefault = proptools.BoolDefault
252