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