Add tradefed attributes to cc_test bazel macro

The BUILD file will now have the needed attributes to run the tradefed
test rules.

Test: b test //packages/modules/adb:adbd_test --platforms=//build/bazel/platforms:android_target
Change-Id: I5cb84ccdde27a7fadbef479269df594344a29187
This commit is contained in:
Kevin Dagostino 2022-12-04 11:16:42 +00:00
parent 2731ca8377
commit 32edd1a608
4 changed files with 275 additions and 51 deletions

View file

@ -26,6 +26,7 @@ import (
type ccTestBp2buildTestCase struct {
description string
blueprint string
filesystem map[string]string
targets []testBazelTarget
}
@ -41,12 +42,12 @@ func registerCcTestModuleTypes(ctx android.RegistrationContext) {
func runCcTestTestCase(t *testing.T, testCase ccTestBp2buildTestCase) {
t.Helper()
moduleTypeUnderTest := "cc_test"
description := fmt.Sprintf("%s %s", moduleTypeUnderTest, testCase.description)
t.Run(description, func(t *testing.T) {
t.Helper()
RunBp2BuildTestCase(t, registerCcTestModuleTypes, Bp2buildTestCase{
ExpectedBazelTargets: generateBazelTargetsForTest(testCase.targets, android.HostAndDeviceSupported),
Filesystem: testCase.filesystem,
ModuleTypeUnderTest: moduleTypeUnderTest,
ModuleTypeUnderTestFactory: cc.TestFactory,
Description: description,
@ -172,3 +173,90 @@ cc_test {
},
})
}
func TestCcTest_TestConfig(t *testing.T) {
runCcTestTestCase(t, ccTestBp2buildTestCase{
description: "cc test that sets a test_config",
filesystem: map[string]string{
"test_config.xml": "",
},
blueprint: `
cc_test {
name: "mytest",
srcs: ["test.cpp"],
test_config: "test_config.xml",
}
`,
targets: []testBazelTarget{
{"cc_test", "mytest", AttrNameToString{
"gtest": "True",
"isolated": "True",
"local_includes": `["."]`,
"srcs": `["test.cpp"]`,
"target_compatible_with": `["//build/bazel/platforms/os:android"]`,
"test_config": `"test_config.xml"`,
},
},
},
})
}
func TestCcTest_TestConfigAndroidTestXML(t *testing.T) {
runCcTestTestCase(t, ccTestBp2buildTestCase{
description: "cc test that defaults to test config AndroidTest.xml",
filesystem: map[string]string{
"AndroidTest.xml": "",
},
blueprint: `
cc_test {
name: "mytest",
srcs: ["test.cpp"],
}
`,
targets: []testBazelTarget{
{"cc_test", "mytest", AttrNameToString{
"gtest": "True",
"isolated": "True",
"local_includes": `["."]`,
"srcs": `["test.cpp"]`,
"target_compatible_with": `["//build/bazel/platforms/os:android"]`,
"test_config": `"AndroidTest.xml"`,
},
},
},
})
}
func TestCcTest_TestConfigTemplateOptions(t *testing.T) {
runCcTestTestCase(t, ccTestBp2buildTestCase{
description: "cc test that sets test config template attributes",
filesystem: map[string]string{
"test_config_template.xml": "",
},
blueprint: `
cc_test {
name: "mytest",
srcs: ["test.cpp"],
test_config_template: "test_config_template.xml",
auto_gen_config: true,
}
`,
targets: []testBazelTarget{
{"cc_test", "mytest", AttrNameToString{
"auto_generate_test_config": "True",
"gtest": "True",
"isolated": "True",
"local_includes": `["."]`,
"srcs": `["test.cpp"]`,
"target_compatible_with": `["//build/bazel/platforms/os:android"]`,
"template_configs": `[
"'<target_preparer class=\"com.android.tradefed.targetprep.RootTargetPreparer\">\\n <option name=\"force-root\" value=\"false\" />\\n </target_preparer>'",
"'<option name=\"not-shardable\" value=\"true\" />'",
]`,
"template_install_base": `"/data/local/tmp"`,
"template_test_config": `"test_config_template.xml"`,
},
},
},
})
}

View file

@ -378,12 +378,6 @@ func (test *testBinary) installerProps() []interface{} {
}
func (test *testBinary) install(ctx ModuleContext, file android.Path) {
// TODO: (b/167308193) Switch to /data/local/tests/unrestricted as the default install base.
testInstallBase := "/data/local/tmp"
if ctx.inVendor() || ctx.useVndk() {
testInstallBase = "/data/local/tests/vendor"
}
dataSrcPaths := android.PathsForModuleSrc(ctx, test.Properties.Data)
for _, dataSrcPath := range dataSrcPaths {
@ -415,49 +409,9 @@ func (test *testBinary) install(ctx ModuleContext, file android.Path) {
}
})
var configs []tradefed.Config
for _, module := range test.Properties.Test_mainline_modules {
configs = append(configs, tradefed.Option{Name: "config-descriptor:metadata", Key: "mainline-param", Value: module})
}
if Bool(test.Properties.Require_root) {
configs = append(configs, tradefed.Object{"target_preparer", "com.android.tradefed.targetprep.RootTargetPreparer", nil})
} else {
var options []tradefed.Option
options = append(options, tradefed.Option{Name: "force-root", Value: "false"})
configs = append(configs, tradefed.Object{"target_preparer", "com.android.tradefed.targetprep.RootTargetPreparer", options})
}
if Bool(test.Properties.Disable_framework) {
var options []tradefed.Option
configs = append(configs, tradefed.Object{"target_preparer", "com.android.tradefed.targetprep.StopServicesSetup", options})
}
if test.isolated(ctx) {
configs = append(configs, tradefed.Option{Name: "not-shardable", Value: "true"})
}
if test.Properties.Test_options.Run_test_as != nil {
configs = append(configs, tradefed.Option{Name: "run-test-as", Value: String(test.Properties.Test_options.Run_test_as)})
}
for _, tag := range test.Properties.Test_options.Test_suite_tag {
configs = append(configs, tradefed.Option{Name: "test-suite-tag", Value: tag})
}
if test.Properties.Test_options.Min_shipping_api_level != nil {
if test.Properties.Test_options.Vsr_min_shipping_api_level != nil {
ctx.PropertyErrorf("test_options.min_shipping_api_level", "must not be set at the same time as 'vsr_min_shipping_api_level'.")
}
var options []tradefed.Option
options = append(options, tradefed.Option{Name: "min-api-level", Value: strconv.FormatInt(int64(*test.Properties.Test_options.Min_shipping_api_level), 10)})
configs = append(configs, tradefed.Object{"module_controller", "com.android.tradefed.testtype.suite.module.ShippingApiLevelModuleController", options})
}
if test.Properties.Test_options.Vsr_min_shipping_api_level != nil {
var options []tradefed.Option
options = append(options, tradefed.Option{Name: "vsr-min-api-level", Value: strconv.FormatInt(int64(*test.Properties.Test_options.Vsr_min_shipping_api_level), 10)})
configs = append(configs, tradefed.Object{"module_controller", "com.android.tradefed.testtype.suite.module.ShippingApiLevelModuleController", options})
}
if test.Properties.Test_options.Min_vndk_version != nil {
var options []tradefed.Option
options = append(options, tradefed.Option{Name: "min-api-level", Value: strconv.FormatInt(int64(*test.Properties.Test_options.Min_vndk_version), 10)})
options = append(options, tradefed.Option{Name: "api-level-prop", Value: "ro.vndk.version"})
configs = append(configs, tradefed.Object{"module_controller", "com.android.tradefed.testtype.suite.module.MinApiLevelModuleController", options})
}
useVendor := ctx.inVendor() || ctx.useVndk()
testInstallBase := getTestInstallBase(useVendor)
configs := getTradefedConfigOptions(ctx, &test.Properties, test.isolated(ctx))
test.testConfig = tradefed.NewMaybeAutoGenTestConfigBuilder(ctx).
SetTestConfigProp(test.Properties.Test_config).
@ -487,6 +441,63 @@ func (test *testBinary) install(ctx ModuleContext, file android.Path) {
test.binaryDecorator.baseInstaller.install(ctx, file)
}
func getTestInstallBase(useVendor bool) string {
// TODO: (b/167308193) Switch to /data/local/tests/unrestricted as the default install base.
testInstallBase := "/data/local/tmp"
if useVendor {
testInstallBase = "/data/local/tests/vendor"
}
return testInstallBase
}
func getTradefedConfigOptions(ctx android.EarlyModuleContext, properties *TestBinaryProperties, isolated bool) []tradefed.Config {
var configs []tradefed.Config
for _, module := range properties.Test_mainline_modules {
configs = append(configs, tradefed.Option{Name: "config-descriptor:metadata", Key: "mainline-param", Value: module})
}
if Bool(properties.Require_root) {
configs = append(configs, tradefed.Object{"target_preparer", "com.android.tradefed.targetprep.RootTargetPreparer", nil})
} else {
var options []tradefed.Option
options = append(options, tradefed.Option{Name: "force-root", Value: "false"})
configs = append(configs, tradefed.Object{"target_preparer", "com.android.tradefed.targetprep.RootTargetPreparer", options})
}
if Bool(properties.Disable_framework) {
var options []tradefed.Option
configs = append(configs, tradefed.Object{"target_preparer", "com.android.tradefed.targetprep.StopServicesSetup", options})
}
if isolated {
configs = append(configs, tradefed.Option{Name: "not-shardable", Value: "true"})
}
if properties.Test_options.Run_test_as != nil {
configs = append(configs, tradefed.Option{Name: "run-test-as", Value: String(properties.Test_options.Run_test_as)})
}
for _, tag := range properties.Test_options.Test_suite_tag {
configs = append(configs, tradefed.Option{Name: "test-suite-tag", Value: tag})
}
if properties.Test_options.Min_shipping_api_level != nil {
if properties.Test_options.Vsr_min_shipping_api_level != nil {
ctx.PropertyErrorf("test_options.min_shipping_api_level", "must not be set at the same time as 'vsr_min_shipping_api_level'.")
}
var options []tradefed.Option
options = append(options, tradefed.Option{Name: "min-api-level", Value: strconv.FormatInt(int64(*properties.Test_options.Min_shipping_api_level), 10)})
configs = append(configs, tradefed.Object{"module_controller", "com.android.tradefed.testtype.suite.module.ShippingApiLevelModuleController", options})
}
if properties.Test_options.Vsr_min_shipping_api_level != nil {
var options []tradefed.Option
options = append(options, tradefed.Option{Name: "vsr-min-api-level", Value: strconv.FormatInt(int64(*properties.Test_options.Vsr_min_shipping_api_level), 10)})
configs = append(configs, tradefed.Object{"module_controller", "com.android.tradefed.testtype.suite.module.ShippingApiLevelModuleController", options})
}
if properties.Test_options.Min_vndk_version != nil {
var options []tradefed.Option
options = append(options, tradefed.Option{Name: "min-api-level", Value: strconv.FormatInt(int64(*properties.Test_options.Min_vndk_version), 10)})
options = append(options, tradefed.Option{Name: "api-level-prop", Value: "ro.vndk.version"})
configs = append(configs, tradefed.Object{"module_controller", "com.android.tradefed.testtype.suite.module.MinApiLevelModuleController", options})
}
return configs
}
func NewTest(hod android.HostOrDeviceSupported, bazelable bool) *Module {
module, binary := newBinary(hod, bazelable)
module.multilib = android.MultilibBoth
@ -660,6 +671,7 @@ type testBinaryAttributes struct {
Isolated bool
tidyAttributes
tradefed.TestConfigAttributes
}
// testBinaryBp2build is the bp2build converter for cc_test modules. A cc_test's
@ -670,7 +682,6 @@ type testBinaryAttributes struct {
// TODO(b/244432609): handle `isolated` property.
// TODO(b/244432134): handle custom runpaths for tests that assume runfile layouts not
// default to bazel. (see linkerInit function)
// TODO(b/244432500): handle test.testConfig generation (see install function)
func testBinaryBp2build(ctx android.TopDownMutatorContext, m *Module) {
var testBinaryAttrs testBinaryAttributes
testBinaryAttrs.binaryAttributes = binaryBp2buildAttrs(ctx, m)
@ -703,6 +714,25 @@ func testBinaryBp2build(ctx android.TopDownMutatorContext, m *Module) {
}
}
for _, testProps := range m.GetProperties() {
if p, ok := testProps.(*TestBinaryProperties); ok {
useVendor := false // TODO Bug: 262914724
testInstallBase := getTestInstallBase(useVendor)
testConfigAttributes := tradefed.GetTestConfigAttributes(
ctx,
p.Test_config,
p.Test_options.Extra_test_configs,
p.Auto_gen_config,
p.Test_options.Test_suite_tag,
p.Test_config_template,
getTradefedConfigOptions(ctx, p, testBinaryAttrs.Isolated),
&testInstallBase,
)
testBinaryAttrs.TestConfigAttributes = testConfigAttributes
}
}
// TODO (b/262914724): convert to tradefed_cc_test and tradefed_cc_test_host
ctx.CreateBazelTargetModule(
bazel.BazelTargetModuleProperties{
Rule_class: "cc_test",

View file

@ -11,6 +11,7 @@ bootstrap_go_package {
],
srcs: [
"autogen.go",
"autogen_bazel.go",
"config.go",
"makevars.go",
],

105
tradefed/autogen_bazel.go Normal file
View file

@ -0,0 +1,105 @@
// Copyright 2022 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package tradefed
import (
"android/soong/android"
"android/soong/bazel"
"github.com/google/blueprint/proptools"
)
const (
InstrumentationTestConfigTemplate = "build/make/core/instrumentation_test_config_template.xml"
JavaTestConfigTemplate = "build/make/core/java_test_config_template.xml"
JavaHostTestConfigTemplate = "build/make/core/java_host_test_config_template.xml"
JavaHostUnitTestConfigTemplate = "build/make/core/java_host_unit_test_config_template.xml"
NativeBenchmarkTestConfigTemplate = "build/make/core/native_benchmark_test_config_template.xml"
NativeHostTestConfigTemplate = "build/make/core/native_host_test_config_template.xml"
NativeTestConfigTemplate = "build/make/core/native_test_config_template.xml"
PythonBinaryHostTestConfigTemplate = "build/make/core/python_binary_host_test_config_template.xml"
RustDeviceTestConfigTemplate = "build/make/core/rust_device_test_config_template.xml"
RustHostTestConfigTemplate = "build/make/core/rust_host_test_config_template.xml"
RustDeviceBenchmarkConfigTemplate = "build/make/core/rust_device_benchmark_config_template.xml"
RustHostBenchmarkConfigTemplate = "build/make/core/rust_host_benchmark_config_template.xml"
RobolectricTestConfigTemplate = "build/make/core/robolectric_test_config_template.xml"
ShellTestConfigTemplate = "build/make/core/shell_test_config_template.xml"
)
type TestConfigAttributes struct {
Test_config *bazel.Label
Auto_generate_test_config *bool
Template_test_config *bazel.Label
Template_configs []string
Template_install_base *string
}
func GetTestConfigAttributes(
ctx android.TopDownMutatorContext,
testConfig *string,
extraTestConfigs []string,
autoGenConfig *bool,
testSuites []string,
template *string,
templateConfigs []Config,
templateInstallBase *string) TestConfigAttributes {
attrs := TestConfigAttributes{}
attrs.Test_config = GetTestConfig(ctx, testConfig)
// do not generate a test config if
// 1) test config already found
// 2) autoGenConfig == false
// 3) CTS tests and no template specified.
// CTS Modules can be used for test data, so test config files must be explicitly specified.
if (attrs.Template_test_config != nil) ||
proptools.Bool(autoGenConfig) == false ||
(template == nil && !android.InList("cts", testSuites)) {
return attrs
}
// Add properties for the bazel rule to generate a test config
// since a test config was not specified.
templateLabel := android.BazelLabelForModuleSrcSingle(ctx, *template)
attrs.Template_test_config = &templateLabel
attrs.Auto_generate_test_config = autoGenConfig
var configStrings []string
for _, c := range templateConfigs {
configString := proptools.NinjaAndShellEscape(c.Config())
configStrings = append(configStrings, configString)
}
attrs.Template_configs = configStrings
attrs.Template_install_base = templateInstallBase
return attrs
}
func GetTestConfig(
ctx android.TopDownMutatorContext,
testConfig *string,
) *bazel.Label {
if testConfig != nil {
c, _ := android.BazelStringOrLabelFromProp(ctx, testConfig)
if c.Value != nil {
return c.Value
}
}
// check for default AndroidTest.xml
defaultTestConfigPath := ctx.ModuleDir() + "/AndroidTest.xml"
c, _ := android.BazelStringOrLabelFromProp(ctx, &defaultTestConfigPath)
return c.Value
}