Support require_root in auto-gen test configs

require_root is added to allow auto-generated test config to include
RootTargetPreparer so the test runs with root permission.

Bug: 134509111
Test: add "require_root: true" to init_benchmarks and libpower_test
  build the modules, confirm the extra target preparer is added in the
  test configs.

Change-Id: Ia07503e338935d6aa92560e7cf7b18d2a4c51243
This commit is contained in:
Dan Shi 2019-06-06 16:23:32 -07:00
parent e77a57336f
commit 37ee3b8f49
2 changed files with 62 additions and 32 deletions

View File

@ -64,6 +64,10 @@ type TestBinaryProperties struct {
// Test options. // Test options.
Test_options TestOptions Test_options TestOptions
// Add RootTargetPreparer to auto generated test config. This guarantees the test to run
// with root permission.
Require_root *bool
} }
func init() { func init() {
@ -273,18 +277,19 @@ func (test *testBinary) linkerFlags(ctx ModuleContext, flags Flags) Flags {
func (test *testBinary) install(ctx ModuleContext, file android.Path) { func (test *testBinary) install(ctx ModuleContext, file android.Path) {
test.data = android.PathsForModuleSrc(ctx, test.Properties.Data) test.data = android.PathsForModuleSrc(ctx, test.Properties.Data)
optionsMap := map[string]string{} var configs []tradefed.Config
if Bool(test.testDecorator.Properties.Isolated) { if Bool(test.Properties.Require_root) {
optionsMap["not-shardable"] = "true" configs = append(configs, tradefed.Preparer{"com.android.tradefed.targetprep.RootTargetPreparer"})
}
if Bool(test.testDecorator.Properties.Isolated) {
configs = append(configs, tradefed.Option{"not-shardable", "true"})
} }
if test.Properties.Test_options.Run_test_as != nil { if test.Properties.Test_options.Run_test_as != nil {
optionsMap["run-test-as"] = String(test.Properties.Test_options.Run_test_as) configs = append(configs, tradefed.Option{"run-test-as", String(test.Properties.Test_options.Run_test_as)})
} }
test.testConfig = tradefed.AutoGenNativeTestConfig(ctx, test.Properties.Test_config, test.testConfig = tradefed.AutoGenNativeTestConfig(ctx, test.Properties.Test_config,
test.Properties.Test_config_template, test.Properties.Test_config_template, test.Properties.Test_suites, configs)
test.Properties.Test_suites, optionsMap)
test.binaryDecorator.baseInstaller.dir = "nativetest" test.binaryDecorator.baseInstaller.dir = "nativetest"
test.binaryDecorator.baseInstaller.dir64 = "nativetest64" test.binaryDecorator.baseInstaller.dir64 = "nativetest64"
@ -371,6 +376,10 @@ type BenchmarkProperties struct {
// the name of the test configuration template (for example "AndroidTestTemplate.xml") that // the name of the test configuration template (for example "AndroidTestTemplate.xml") that
// should be installed with the module. // should be installed with the module.
Test_config_template *string `android:"path,arch_variant"` Test_config_template *string `android:"path,arch_variant"`
// Add RootTargetPreparer to auto generated test config. This guarantees the test to run
// with root permission.
Require_root *bool
} }
type benchmarkDecorator struct { type benchmarkDecorator struct {
@ -403,8 +412,12 @@ func (benchmark *benchmarkDecorator) linkerDeps(ctx DepsContext, deps Deps) Deps
func (benchmark *benchmarkDecorator) install(ctx ModuleContext, file android.Path) { func (benchmark *benchmarkDecorator) install(ctx ModuleContext, file android.Path) {
benchmark.data = android.PathsForModuleSrc(ctx, benchmark.Properties.Data) benchmark.data = android.PathsForModuleSrc(ctx, benchmark.Properties.Data)
var configs []tradefed.Config
if Bool(benchmark.Properties.Require_root) {
configs = append(configs, tradefed.Preparer{"com.android.tradefed.targetprep.RootTargetPreparer"})
}
benchmark.testConfig = tradefed.AutoGenNativeBenchmarkTestConfig(ctx, benchmark.Properties.Test_config, benchmark.testConfig = tradefed.AutoGenNativeBenchmarkTestConfig(ctx, benchmark.Properties.Test_config,
benchmark.Properties.Test_config_template, benchmark.Properties.Test_suites) benchmark.Properties.Test_config_template, benchmark.Properties.Test_suites, configs)
benchmark.binaryDecorator.baseInstaller.dir = filepath.Join("benchmarktest", ctx.ModuleName()) benchmark.binaryDecorator.baseInstaller.dir = filepath.Join("benchmarktest", ctx.ModuleName())
benchmark.binaryDecorator.baseInstaller.dir64 = filepath.Join("benchmarktest64", ctx.ModuleName()) benchmark.binaryDecorator.baseInstaller.dir64 = filepath.Join("benchmarktest64", ctx.ModuleName())

View File

@ -16,7 +16,6 @@ package tradefed
import ( import (
"fmt" "fmt"
"sort"
"strings" "strings"
"github.com/google/blueprint" "github.com/google/blueprint"
@ -39,9 +38,9 @@ func getTestConfig(ctx android.ModuleContext, prop *string) android.Path {
} }
var autogenTestConfig = pctx.StaticRule("autogenTestConfig", blueprint.RuleParams{ var autogenTestConfig = pctx.StaticRule("autogenTestConfig", blueprint.RuleParams{
Command: "sed 's&{MODULE}&${name}&g;s&{EXTRA_OPTIONS}&'${extraOptions}'&g' $template > $out", Command: "sed 's&{MODULE}&${name}&g;s&{EXTRA_CONFIGS}&'${extraConfigs}'&g' $template > $out",
CommandDeps: []string{"$template"}, CommandDeps: []string{"$template"},
}, "name", "template", "extraOptions") }, "name", "template", "extraConfigs")
func testConfigPath(ctx android.ModuleContext, prop *string, testSuites []string) (path android.Path, autogenPath android.WritablePath) { func testConfigPath(ctx android.ModuleContext, prop *string, testSuites []string) (path android.Path, autogenPath android.WritablePath) {
if p := getTestConfig(ctx, prop); p != nil { if p := getTestConfig(ctx, prop); p != nil {
@ -57,17 +56,38 @@ func testConfigPath(ctx android.ModuleContext, prop *string, testSuites []string
} }
} }
func autogenTemplate(ctx android.ModuleContext, output android.WritablePath, template string, optionsMap map[string]string) { type Config interface {
// If no test option found, delete {EXTRA_OPTIONS} line. Config() string
var options []string }
for optionName, value := range optionsMap {
if value != "" { type Option struct {
options = append(options, fmt.Sprintf(`<option name="%s" value="%s" />`, optionName, value)) Name string
} Value string
}
var _ Config = Option{}
func (o Option) Config() string {
return fmt.Sprintf(`<option name="%s" value="%s" />`, o.Name, o.Value)
}
type Preparer struct {
Class string
}
var _ Config = Preparer{}
func (p Preparer) Config() string {
return fmt.Sprintf(`<target_preparer class="%s" />`, p.Class)
}
func autogenTemplate(ctx android.ModuleContext, output android.WritablePath, template string, configs []Config) {
var configStrings []string
for _, config := range configs {
configStrings = append(configStrings, config.Config())
} }
sort.Strings(options) extraConfigs := strings.Join(configStrings, "\n ")
extraOptions := strings.Join(options, "\n ") extraConfigs = proptools.NinjaAndShellEscape(extraConfigs)
extraOptions = proptools.NinjaAndShellEscape(extraOptions)
ctx.Build(pctx, android.BuildParams{ ctx.Build(pctx, android.BuildParams{
Rule: autogenTestConfig, Rule: autogenTestConfig,
@ -76,26 +96,23 @@ func autogenTemplate(ctx android.ModuleContext, output android.WritablePath, tem
Args: map[string]string{ Args: map[string]string{
"name": ctx.ModuleName(), "name": ctx.ModuleName(),
"template": template, "template": template,
"extraOptions": extraOptions, "extraConfigs": extraConfigs,
}, },
}) })
} }
func AutoGenNativeTestConfig(ctx android.ModuleContext, testConfigProp *string, func AutoGenNativeTestConfig(ctx android.ModuleContext, testConfigProp *string,
testConfigTemplateProp *string, testSuites []string, testConfigTemplateProp *string, testSuites []string, config []Config) android.Path {
optionsMap map[string]string) android.Path {
path, autogenPath := testConfigPath(ctx, testConfigProp, testSuites) path, autogenPath := testConfigPath(ctx, testConfigProp, testSuites)
if autogenPath != nil { if autogenPath != nil {
templatePath := getTestConfigTemplate(ctx, testConfigTemplateProp) templatePath := getTestConfigTemplate(ctx, testConfigTemplateProp)
if templatePath.Valid() { if templatePath.Valid() {
autogenTemplate(ctx, autogenPath, templatePath.String(), optionsMap) autogenTemplate(ctx, autogenPath, templatePath.String(), config)
} else { } else {
if ctx.Device() { if ctx.Device() {
autogenTemplate(ctx, autogenPath, "${NativeTestConfigTemplate}", autogenTemplate(ctx, autogenPath, "${NativeTestConfigTemplate}", config)
optionsMap)
} else { } else {
autogenTemplate(ctx, autogenPath, "${NativeHostTestConfigTemplate}", autogenTemplate(ctx, autogenPath, "${NativeHostTestConfigTemplate}", config)
optionsMap)
} }
} }
return autogenPath return autogenPath
@ -104,14 +121,14 @@ func AutoGenNativeTestConfig(ctx android.ModuleContext, testConfigProp *string,
} }
func AutoGenNativeBenchmarkTestConfig(ctx android.ModuleContext, testConfigProp *string, func AutoGenNativeBenchmarkTestConfig(ctx android.ModuleContext, testConfigProp *string,
testConfigTemplateProp *string, testSuites []string) android.Path { testConfigTemplateProp *string, testSuites []string, configs []Config) android.Path {
path, autogenPath := testConfigPath(ctx, testConfigProp, testSuites) path, autogenPath := testConfigPath(ctx, testConfigProp, testSuites)
if autogenPath != nil { if autogenPath != nil {
templatePath := getTestConfigTemplate(ctx, testConfigTemplateProp) templatePath := getTestConfigTemplate(ctx, testConfigTemplateProp)
if templatePath.Valid() { if templatePath.Valid() {
autogenTemplate(ctx, autogenPath, templatePath.String(), nil) autogenTemplate(ctx, autogenPath, templatePath.String(), configs)
} else { } else {
autogenTemplate(ctx, autogenPath, "${NativeBenchmarkTestConfigTemplate}", nil) autogenTemplate(ctx, autogenPath, "${NativeBenchmarkTestConfigTemplate}", configs)
} }
return autogenPath return autogenPath
} }