1// Copyright 2018 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 tradefed 16 17import ( 18 "fmt" 19 "sort" 20 "strings" 21 22 "github.com/google/blueprint" 23 "github.com/google/blueprint/proptools" 24 25 "android/soong/android" 26) 27 28func getTestConfigTemplate(ctx android.ModuleContext, prop *string) android.OptionalPath { 29 return ctx.ExpandOptionalSource(prop, "test_config_template") 30} 31 32func getTestConfig(ctx android.ModuleContext, prop *string) android.Path { 33 if p := ctx.ExpandOptionalSource(prop, "test_config"); p.Valid() { 34 return p.Path() 35 } else if p := android.ExistentPathForSource(ctx, ctx.ModuleDir(), "AndroidTest.xml"); p.Valid() { 36 return p.Path() 37 } 38 return nil 39} 40 41var autogenTestConfig = pctx.StaticRule("autogenTestConfig", blueprint.RuleParams{ 42 Command: "sed 's&{MODULE}&${name}&g;s&{EXTRA_OPTIONS}&'${extraOptions}'&g' $template > $out", 43 CommandDeps: []string{"$template"}, 44}, "name", "template", "extraOptions") 45 46func testConfigPath(ctx android.ModuleContext, prop *string, testSuites []string) (path android.Path, autogenPath android.WritablePath) { 47 if p := getTestConfig(ctx, prop); p != nil { 48 return p, nil 49 } else if !android.InList("cts", testSuites) { 50 outputFile := android.PathForModuleOut(ctx, ctx.ModuleName()+".config") 51 return nil, outputFile 52 } else { 53 // CTS modules can be used for test data, so test config files must be 54 // explicitly created using AndroidTest.xml 55 // TODO(b/112602712): remove the path check 56 return nil, nil 57 } 58} 59 60func autogenTemplate(ctx android.ModuleContext, output android.WritablePath, template string, optionsMap map[string]string) { 61 // If no test option found, delete {EXTRA_OPTIONS} line. 62 var options []string 63 for optionName, value := range optionsMap { 64 if value != "" { 65 options = append(options, fmt.Sprintf(`<option name="%s" value="%s" />`, optionName, value)) 66 } 67 } 68 sort.Strings(options) 69 extraOptions := strings.Join(options, "\n ") 70 extraOptions = proptools.NinjaAndShellEscape(extraOptions) 71 72 ctx.Build(pctx, android.BuildParams{ 73 Rule: autogenTestConfig, 74 Description: "test config", 75 Output: output, 76 Args: map[string]string{ 77 "name": ctx.ModuleName(), 78 "template": template, 79 "extraOptions": extraOptions, 80 }, 81 }) 82} 83 84func AutoGenNativeTestConfig(ctx android.ModuleContext, testConfigProp *string, 85 testConfigTemplateProp *string, testSuites []string, 86 optionsMap map[string]string) android.Path { 87 path, autogenPath := testConfigPath(ctx, testConfigProp, testSuites) 88 if autogenPath != nil { 89 templatePath := getTestConfigTemplate(ctx, testConfigTemplateProp) 90 if templatePath.Valid() { 91 autogenTemplate(ctx, autogenPath, templatePath.String(), optionsMap) 92 } else { 93 if ctx.Device() { 94 autogenTemplate(ctx, autogenPath, "${NativeTestConfigTemplate}", 95 optionsMap) 96 } else { 97 autogenTemplate(ctx, autogenPath, "${NativeHostTestConfigTemplate}", 98 optionsMap) 99 } 100 } 101 return autogenPath 102 } 103 return path 104} 105 106func AutoGenNativeBenchmarkTestConfig(ctx android.ModuleContext, testConfigProp *string, 107 testConfigTemplateProp *string, testSuites []string) android.Path { 108 path, autogenPath := testConfigPath(ctx, testConfigProp, testSuites) 109 if autogenPath != nil { 110 templatePath := getTestConfigTemplate(ctx, testConfigTemplateProp) 111 if templatePath.Valid() { 112 autogenTemplate(ctx, autogenPath, templatePath.String(), nil) 113 } else { 114 autogenTemplate(ctx, autogenPath, "${NativeBenchmarkTestConfigTemplate}", nil) 115 } 116 return autogenPath 117 } 118 return path 119} 120 121func AutoGenJavaTestConfig(ctx android.ModuleContext, testConfigProp *string, testConfigTemplateProp *string, testSuites []string) android.Path { 122 path, autogenPath := testConfigPath(ctx, testConfigProp, testSuites) 123 if autogenPath != nil { 124 templatePath := getTestConfigTemplate(ctx, testConfigTemplateProp) 125 if templatePath.Valid() { 126 autogenTemplate(ctx, autogenPath, templatePath.String(), nil) 127 } else { 128 if ctx.Device() { 129 autogenTemplate(ctx, autogenPath, "${JavaTestConfigTemplate}", nil) 130 } else { 131 autogenTemplate(ctx, autogenPath, "${JavaHostTestConfigTemplate}", nil) 132 } 133 } 134 return autogenPath 135 } 136 return path 137} 138 139func AutoGenPythonBinaryHostTestConfig(ctx android.ModuleContext, testConfigProp *string, 140 testConfigTemplateProp *string, testSuites []string) android.Path { 141 142 path, autogenPath := testConfigPath(ctx, testConfigProp, testSuites) 143 if autogenPath != nil { 144 templatePath := getTestConfigTemplate(ctx, testConfigTemplateProp) 145 if templatePath.Valid() { 146 autogenTemplate(ctx, autogenPath, templatePath.String(), nil) 147 } else { 148 autogenTemplate(ctx, autogenPath, "${PythonBinaryHostTestConfigTemplate}", nil) 149 } 150 return autogenPath 151 } 152 return path 153} 154 155var autogenInstrumentationTest = pctx.StaticRule("autogenInstrumentationTest", blueprint.RuleParams{ 156 Command: "${AutoGenTestConfigScript} $out $in ${EmptyTestConfig} $template", 157 CommandDeps: []string{ 158 "${AutoGenTestConfigScript}", 159 "${EmptyTestConfig}", 160 "$template", 161 }, 162}, "name", "template") 163 164func AutoGenInstrumentationTestConfig(ctx android.ModuleContext, testConfigProp *string, testConfigTemplateProp *string, manifest android.Path, testSuites []string) android.Path { 165 path, autogenPath := testConfigPath(ctx, testConfigProp, testSuites) 166 if autogenPath != nil { 167 template := "${InstrumentationTestConfigTemplate}" 168 moduleTemplate := getTestConfigTemplate(ctx, testConfigTemplateProp) 169 if moduleTemplate.Valid() { 170 template = moduleTemplate.String() 171 } 172 ctx.Build(pctx, android.BuildParams{ 173 Rule: autogenInstrumentationTest, 174 Description: "test config", 175 Input: manifest, 176 Output: autogenPath, 177 Args: map[string]string{ 178 "name": ctx.ModuleName(), 179 "template": template, 180 }, 181 }) 182 return autogenPath 183 } 184 return path 185} 186