2016-07-29 21:48:20 +02:00
// Copyright 2016 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 cc
import (
"path/filepath"
2019-09-17 10:35:23 +02:00
"strconv"
2016-07-29 21:48:20 +02:00
"strings"
2021-01-14 20:49:15 +01:00
"github.com/google/blueprint/proptools"
2016-07-29 21:48:20 +02:00
"android/soong/android"
2022-08-24 13:53:27 +02:00
"android/soong/bazel"
2022-12-12 13:20:58 +01:00
"android/soong/bazel/cquery"
2018-08-08 01:49:25 +02:00
"android/soong/tradefed"
2016-07-29 21:48:20 +02:00
)
2022-03-24 22:06:14 +01:00
// TestLinkerProperties properties to be registered via the linker
type TestLinkerProperties struct {
2016-07-29 21:48:20 +02:00
// if set, build against the gtest library. Defaults to true.
2016-09-13 21:26:16 +02:00
Gtest * bool
2018-08-21 21:40:08 +02:00
2022-05-03 16:51:16 +02:00
// if set, use the isolated gtest runner. Defaults to true if gtest is also true and the arch is Windows, false
// otherwise.
2018-08-21 21:40:08 +02:00
Isolated * bool
2016-07-30 02:28:03 +02:00
}
2016-07-29 21:48:20 +02:00
2022-03-24 22:06:14 +01:00
// TestInstallerProperties properties to be registered via the installer
type TestInstallerProperties struct {
// list of compatibility suites (for example "cts", "vts") that the module should be installed into.
Test_suites [ ] string ` android:"arch_variant" `
}
2018-10-01 13:23:14 +02:00
// Test option struct.
type TestOptions struct {
2022-08-12 12:49:20 +02:00
android . CommonTestOptions
2018-10-01 13:23:14 +02:00
// The UID that you want to run the test as on a device.
Run_test_as * string
2020-08-15 21:24:26 +02:00
2020-06-18 19:07:00 +02:00
// A list of free-formed strings without spaces that categorize the test.
Test_suite_tag [ ] string
2020-08-15 21:24:26 +02:00
// a list of extra test configuration files that should be installed with the module.
Extra_test_configs [ ] string ` android:"path,arch_variant" `
2020-11-13 23:33:46 +01:00
2021-05-04 11:42:24 +02:00
// Add ShippingApiLevelModuleController to auto generated test config. If the device properties
2021-05-13 05:39:42 +02:00
// for the shipping api level is less than the min_shipping_api_level, skip this module.
Min_shipping_api_level * int64
// Add ShippingApiLevelModuleController to auto generated test config. If any of the device
// shipping api level and vendor api level properties are less than the
// vsr_min_shipping_api_level, skip this module.
// As this includes the shipping api level check, it is not allowed to define
// min_shipping_api_level at the same time with this property.
Vsr_min_shipping_api_level * int64
2021-05-04 11:42:24 +02:00
// Add MinApiLevelModuleController with ro.vndk.version property. If ro.vndk.version has an
2021-05-13 05:39:42 +02:00
// integer value and the value is less than the min_vndk_version, skip this module.
Min_vndk_version * int64
2023-05-26 06:21:44 +02:00
// Extra <option> tags to add to the auto generated test xml file under the test runner, e.g., GTest.
// The "key" is optional in each of these.
Test_runner_options [ ] tradefed . Option
2018-10-01 13:23:14 +02:00
}
2016-07-30 02:28:03 +02:00
type TestBinaryProperties struct {
2016-07-29 21:48:20 +02:00
// Create a separate binary for each source file. Useful when there is
// global state that can not be torn down and reset between each test suite.
Test_per_src * bool
2016-12-27 23:40:40 +01:00
// Disables the creation of a test-specific directory when used with
// relative_install_path. Useful if several tests need to be in the same
// directory, but test_per_src doesn't work.
No_named_install_directory * bool
2017-02-01 23:12:44 +01:00
// list of files or filegroup modules that provide data that should be installed alongside
// the test
2020-02-26 01:34:39 +01:00
Data [ ] string ` android:"path,arch_variant" `
2017-03-28 01:27:50 +02:00
2020-06-05 23:26:16 +02:00
// list of shared library modules that should be installed alongside the test
Data_libs [ ] string ` android:"arch_variant" `
2021-09-25 01:50:14 +02:00
// list of binary modules that should be installed alongside the test
Data_bins [ ] string ` android:"arch_variant" `
2018-08-03 00:00:46 +02:00
// the name of the test configuration (for example "AndroidTest.xml") that should be
// installed with the module.
2019-03-05 07:35:41 +01:00
Test_config * string ` android:"path,arch_variant" `
2018-09-19 11:21:28 +02:00
// the name of the test configuration template (for example "AndroidTestTemplate.xml") that
// should be installed with the module.
2019-03-05 07:35:41 +01:00
Test_config_template * string ` android:"path,arch_variant" `
2018-10-01 13:23:14 +02:00
// Test options.
Test_options TestOptions
2019-06-07 01:23:32 +02:00
// Add RootTargetPreparer to auto generated test config. This guarantees the test to run
// with root permission.
Require_root * bool
2019-08-27 19:37:24 +02:00
// Add RunCommandTargetPreparer to stop framework before the test and start it after the test.
Disable_framework * bool
2019-09-17 10:35:23 +02:00
2019-09-26 20:41:36 +02:00
// Flag to indicate whether or not to create test config automatically. If AndroidTest.xml
// doesn't exist next to the Android.bp, this attribute doesn't need to be set to true
// explicitly.
Auto_gen_config * bool
2020-04-30 04:08:33 +02:00
// Add parameterized mainline modules to auto generated test config. The options will be
// handled by TradeFed to download and install the specified modules on the device.
Test_mainline_modules [ ] string
2021-09-25 00:47:17 +02:00
// Install the test into a folder named for the module in all test suites.
Per_testcase_directory * bool
2016-07-29 21:48:20 +02:00
}
func init ( ) {
2017-11-03 05:38:28 +01:00
android . RegisterModuleType ( "cc_test" , TestFactory )
android . RegisterModuleType ( "cc_test_library" , TestLibraryFactory )
android . RegisterModuleType ( "cc_benchmark" , BenchmarkFactory )
android . RegisterModuleType ( "cc_test_host" , TestHostFactory )
android . RegisterModuleType ( "cc_benchmark_host" , BenchmarkHostFactory )
2016-07-29 21:48:20 +02:00
}
2019-03-20 01:00:29 +01:00
// cc_test generates a test config file and an executable binary file to test
// specific functionality on a device. The executable binary gets an implicit
// static_libs dependency on libgtests unless the gtest flag is set to false.
2017-11-03 05:38:28 +01:00
func TestFactory ( ) android . Module {
2022-08-24 13:53:27 +02:00
module := NewTest ( android . HostAndDeviceSupported , true )
2022-12-12 13:20:58 +01:00
module . bazelHandler = & ccTestBazelHandler { module : module }
2023-11-17 16:27:06 +01:00
module . testModule = true
2016-07-29 21:48:20 +02:00
return module . Init ( )
}
2019-03-20 01:00:29 +01:00
// cc_test_library creates an archive of files (i.e. .o files) which is later
// referenced by another module (such as cc_test, cc_defaults or cc_test_library)
// for archiving or linking.
2017-11-03 05:38:28 +01:00
func TestLibraryFactory ( ) android . Module {
2016-07-29 21:48:20 +02:00
module := NewTestLibrary ( android . HostAndDeviceSupported )
return module . Init ( )
}
2019-03-20 01:00:29 +01:00
// cc_benchmark compiles an executable binary that performs benchmark testing
// of a specific component in a device. Additional files such as test suites
// and test configuration are installed on the side of the compiled executed
// binary.
2017-11-03 05:38:28 +01:00
func BenchmarkFactory ( ) android . Module {
2016-07-29 21:48:20 +02:00
module := NewBenchmark ( android . HostAndDeviceSupported )
2023-11-17 16:27:06 +01:00
module . testModule = true
2016-07-29 21:48:20 +02:00
return module . Init ( )
}
2019-03-20 01:00:29 +01:00
// cc_test_host compiles a test host binary.
2017-11-03 05:38:28 +01:00
func TestHostFactory ( ) android . Module {
2022-08-24 13:53:27 +02:00
module := NewTest ( android . HostSupported , true )
2023-11-17 16:27:06 +01:00
module . testModule = true
2016-07-29 21:48:20 +02:00
return module . Init ( )
}
2019-03-20 01:00:29 +01:00
// cc_benchmark_host compiles an executable binary that performs benchmark
// testing of a specific component in the host. Additional files such as
// test suites and test configuration are installed on the side of the
// compiled executed binary.
2017-11-03 05:38:28 +01:00
func BenchmarkHostFactory ( ) android . Module {
2016-07-29 21:48:20 +02:00
module := NewBenchmark ( android . HostSupported )
return module . Init ( )
}
2016-07-30 02:28:03 +02:00
type testPerSrc interface {
testPerSrc ( ) bool
srcs ( ) [ ] string
2019-06-28 16:41:19 +02:00
isAllTestsVariation ( ) bool
2016-07-30 02:28:03 +02:00
setSrc ( string , string )
2019-06-28 16:41:19 +02:00
unsetSrc ( )
2016-07-30 02:28:03 +02:00
}
func ( test * testBinary ) testPerSrc ( ) bool {
return Bool ( test . Properties . Test_per_src )
}
func ( test * testBinary ) srcs ( ) [ ] string {
return test . baseCompiler . Properties . Srcs
}
2020-07-09 23:12:52 +02:00
func ( test * testBinary ) dataPaths ( ) [ ] android . DataPath {
2020-05-13 00:26:55 +02:00
return test . data
}
2019-06-28 16:41:19 +02:00
func ( test * testBinary ) isAllTestsVariation ( ) bool {
stem := test . binaryDecorator . Properties . Stem
return stem != nil && * stem == ""
}
2016-07-30 02:28:03 +02:00
func ( test * testBinary ) setSrc ( name , src string ) {
test . baseCompiler . Properties . Srcs = [ ] string { src }
2017-11-07 19:57:05 +01:00
test . binaryDecorator . Properties . Stem = StringPtr ( name )
2016-07-30 02:28:03 +02:00
}
2019-06-28 16:41:19 +02:00
func ( test * testBinary ) unsetSrc ( ) {
test . baseCompiler . Properties . Srcs = nil
test . binaryDecorator . Properties . Stem = StringPtr ( "" )
}
2022-08-24 13:53:27 +02:00
func ( test * testBinary ) testBinary ( ) bool {
return true
}
2016-07-30 02:28:03 +02:00
var _ testPerSrc = ( * testBinary ) ( nil )
2019-06-28 16:41:19 +02:00
func TestPerSrcMutator ( mctx android . BottomUpMutatorContext ) {
2016-07-29 21:48:20 +02:00
if m , ok := mctx . Module ( ) . ( * Module ) ; ok {
2016-07-30 02:28:03 +02:00
if test , ok := m . linker . ( testPerSrc ) ; ok {
2019-06-28 16:41:19 +02:00
numTests := len ( test . srcs ( ) )
if test . testPerSrc ( ) && numTests > 0 {
2019-10-25 05:47:54 +02:00
if duplicate , found := android . CheckDuplicate ( test . srcs ( ) ) ; found {
2019-02-28 10:06:34 +01:00
mctx . PropertyErrorf ( "srcs" , "found a duplicate entry %q" , duplicate )
return
}
2019-06-28 16:41:19 +02:00
testNames := make ( [ ] string , numTests )
2016-07-30 02:28:03 +02:00
for i , src := range test . srcs ( ) {
2016-07-29 21:48:20 +02:00
testNames [ i ] = strings . TrimSuffix ( filepath . Base ( src ) , filepath . Ext ( src ) )
}
2019-06-28 16:41:19 +02:00
// In addition to creating one variation per test source file,
// create an additional "all tests" variation named "", and have it
// depends on all other test_per_src variations. This is useful to
// create subsequent dependencies of a given module on all
// test_per_src variations created above: by depending on
// variation "", that module will transitively depend on all the
// other test_per_src variations without the need to know their
// name or even their number.
testNames = append ( testNames , "" )
2016-07-29 21:48:20 +02:00
tests := mctx . CreateLocalVariations ( testNames ... )
2020-12-21 18:11:10 +01:00
allTests := tests [ numTests ]
allTests . ( * Module ) . linker . ( testPerSrc ) . unsetSrc ( )
2019-06-28 16:41:19 +02:00
// Prevent the "all tests" variation from being installable nor
// exporting to Make, as it won't create any output file.
2020-12-21 18:11:10 +01:00
allTests . ( * Module ) . Properties . PreventInstall = true
allTests . ( * Module ) . Properties . HideFromMake = true
2016-07-30 02:28:03 +02:00
for i , src := range test . srcs ( ) {
tests [ i ] . ( * Module ) . linker . ( testPerSrc ) . setSrc ( testNames [ i ] , src )
2020-12-21 18:11:10 +01:00
mctx . AddInterVariantDependency ( testPerSrcDepTag , allTests , tests [ i ] )
2016-07-29 21:48:20 +02:00
}
2020-08-22 00:55:50 +02:00
mctx . AliasVariation ( "" )
2016-07-29 21:48:20 +02:00
}
}
}
}
2016-07-30 02:28:03 +02:00
type testDecorator struct {
2022-03-24 22:06:14 +01:00
LinkerProperties TestLinkerProperties
InstallerProperties TestInstallerProperties
installer * baseInstaller
linker * baseLinker
2016-07-29 21:48:20 +02:00
}
2016-09-13 21:26:16 +02:00
func ( test * testDecorator ) gtest ( ) bool {
2022-03-24 22:06:14 +01:00
return BoolDefault ( test . LinkerProperties . Gtest , true )
2016-09-13 21:26:16 +02:00
}
2023-07-22 05:16:53 +02:00
func ( test * testDecorator ) isolated ( ctx android . EarlyModuleContext ) bool {
2022-05-03 16:51:16 +02:00
return BoolDefault ( test . LinkerProperties . Isolated , false )
}
2022-08-24 13:53:27 +02:00
// NOTE: Keep this in sync with cc/cc_test.bzl#gtest_copts
2016-07-30 02:28:03 +02:00
func ( test * testDecorator ) linkerFlags ( ctx ModuleContext , flags Flags ) Flags {
2016-09-13 21:26:16 +02:00
if ! test . gtest ( ) {
2016-07-29 21:48:20 +02:00
return flags
}
2019-11-04 18:37:55 +01:00
flags . Local . CFlags = append ( flags . Local . CFlags , "-DGTEST_HAS_STD_STRING" )
2016-07-29 21:48:20 +02:00
if ctx . Host ( ) {
2019-11-04 18:37:55 +01:00
flags . Local . CFlags = append ( flags . Local . CFlags , "-O0" , "-g" )
2016-07-29 21:48:20 +02:00
switch ctx . Os ( ) {
case android . Windows :
2019-11-04 18:37:55 +01:00
flags . Local . CFlags = append ( flags . Local . CFlags , "-DGTEST_OS_WINDOWS" )
2016-07-29 21:48:20 +02:00
case android . Linux :
2019-11-04 18:37:55 +01:00
flags . Local . CFlags = append ( flags . Local . CFlags , "-DGTEST_OS_LINUX" )
2016-07-29 21:48:20 +02:00
case android . Darwin :
2019-11-04 18:37:55 +01:00
flags . Local . CFlags = append ( flags . Local . CFlags , "-DGTEST_OS_MAC" )
2016-07-29 21:48:20 +02:00
}
} else {
2019-11-04 18:37:55 +01:00
flags . Local . CFlags = append ( flags . Local . CFlags , "-DGTEST_OS_LINUX_ANDROID" )
2016-07-29 21:48:20 +02:00
}
return flags
}
2016-07-30 02:28:03 +02:00
func ( test * testDecorator ) linkerDeps ( ctx BaseModuleContext , deps Deps ) Deps {
2016-09-13 21:26:16 +02:00
if test . gtest ( ) {
2017-09-28 02:01:44 +02:00
if ctx . useSdk ( ) && ctx . Device ( ) {
2018-02-10 00:22:59 +01:00
deps . StaticLibs = append ( deps . StaticLibs , "libgtest_main_ndk_c++" , "libgtest_ndk_c++" )
2022-05-03 16:51:16 +02:00
} else if test . isolated ( ctx ) {
2018-08-21 21:40:08 +02:00
deps . StaticLibs = append ( deps . StaticLibs , "libgtest_isolated_main" )
2019-07-18 00:46:29 +02:00
// The isolated library requires liblog, but adding it
// as a static library means unit tests cannot override
// liblog functions. Instead make it a shared library
// dependency.
deps . SharedLibs = append ( deps . SharedLibs , "liblog" )
2016-07-29 21:48:20 +02:00
} else {
deps . StaticLibs = append ( deps . StaticLibs , "libgtest_main" , "libgtest" )
}
}
2016-07-30 02:28:03 +02:00
return deps
2016-07-29 21:48:20 +02:00
}
2016-07-30 02:28:03 +02:00
func ( test * testDecorator ) linkerProps ( ) [ ] interface { } {
2022-03-24 22:06:14 +01:00
return [ ] interface { } { & test . LinkerProperties }
}
func ( test * testDecorator ) installerProps ( ) [ ] interface { } {
return [ ] interface { } { & test . InstallerProperties }
2016-07-29 21:48:20 +02:00
}
2016-07-30 02:28:03 +02:00
func NewTestInstaller ( ) * baseInstaller {
return NewBaseInstaller ( "nativetest" , "nativetest64" , InstallInData )
2016-07-29 21:48:20 +02:00
}
2016-07-30 02:28:03 +02:00
type testBinary struct {
2022-03-24 22:06:14 +01:00
* testDecorator
2016-07-30 02:28:03 +02:00
* binaryDecorator
* baseCompiler
2020-08-15 21:24:26 +02:00
Properties TestBinaryProperties
data [ ] android . DataPath
testConfig android . Path
extraTestConfigs android . Paths
2016-07-29 21:48:20 +02:00
}
2016-07-30 02:28:03 +02:00
func ( test * testBinary ) linkerProps ( ) [ ] interface { } {
props := append ( test . testDecorator . linkerProps ( ) , test . binaryDecorator . linkerProps ( ) ... )
props = append ( props , & test . Properties )
return props
2016-07-29 21:48:20 +02:00
}
2016-12-14 02:06:13 +01:00
func ( test * testBinary ) linkerDeps ( ctx DepsContext , deps Deps ) Deps {
2016-07-30 02:28:03 +02:00
deps = test . testDecorator . linkerDeps ( ctx , deps )
deps = test . binaryDecorator . linkerDeps ( ctx , deps )
2020-06-05 23:26:16 +02:00
deps . DataLibs = append ( deps . DataLibs , test . Properties . Data_libs ... )
2021-09-25 01:50:14 +02:00
deps . DataBins = append ( deps . DataBins , test . Properties . Data_bins ... )
2016-07-29 21:48:20 +02:00
return deps
}
2016-07-30 02:28:03 +02:00
func ( test * testBinary ) linkerFlags ( ctx ModuleContext , flags Flags ) Flags {
flags = test . binaryDecorator . linkerFlags ( ctx , flags )
flags = test . testDecorator . linkerFlags ( ctx , flags )
return flags
2016-07-29 21:48:20 +02:00
}
2022-03-24 22:06:14 +01:00
func ( test * testBinary ) installerProps ( ) [ ] interface { } {
return append ( test . baseInstaller . installerProps ( ) , test . testDecorator . installerProps ( ) ... )
}
2016-07-30 02:28:03 +02:00
func ( test * testBinary ) install ( ctx ModuleContext , file android . Path ) {
2020-07-09 23:12:52 +02:00
dataSrcPaths := android . PathsForModuleSrc ( ctx , test . Properties . Data )
for _ , dataSrcPath := range dataSrcPaths {
test . data = append ( test . data , android . DataPath { SrcPath : dataSrcPath } )
}
2020-06-05 23:26:16 +02:00
ctx . VisitDirectDepsWithTag ( dataLibDepTag , func ( dep android . Module ) {
depName := ctx . OtherModuleName ( dep )
2021-11-04 19:09:38 +01:00
linkableDep , ok := dep . ( LinkableInterface )
2020-07-09 23:12:52 +02:00
if ! ok {
2021-11-04 19:09:38 +01:00
ctx . ModuleErrorf ( "data_lib %q is not a LinkableInterface module" , depName )
2020-07-09 23:12:52 +02:00
}
2021-11-04 19:09:38 +01:00
if linkableDep . OutputFile ( ) . Valid ( ) {
2020-07-09 23:12:52 +02:00
test . data = append ( test . data ,
2021-11-04 19:09:38 +01:00
android . DataPath { SrcPath : linkableDep . OutputFile ( ) . Path ( ) ,
RelativeInstallPath : linkableDep . RelativeInstallPath ( ) } )
2021-09-25 01:50:14 +02:00
}
} )
ctx . VisitDirectDepsWithTag ( dataBinDepTag , func ( dep android . Module ) {
depName := ctx . OtherModuleName ( dep )
2021-11-04 19:09:38 +01:00
linkableDep , ok := dep . ( LinkableInterface )
2021-09-25 01:50:14 +02:00
if ! ok {
2021-11-04 19:09:38 +01:00
ctx . ModuleErrorf ( "data_bin %q is not a LinkableInterface module" , depName )
2021-09-25 01:50:14 +02:00
}
2021-11-04 19:09:38 +01:00
if linkableDep . OutputFile ( ) . Valid ( ) {
2021-09-25 01:50:14 +02:00
test . data = append ( test . data ,
2021-11-04 19:09:38 +01:00
android . DataPath { SrcPath : linkableDep . OutputFile ( ) . Path ( ) ,
RelativeInstallPath : linkableDep . RelativeInstallPath ( ) } )
2020-06-05 23:26:16 +02:00
}
} )
2022-12-04 12:16:42 +01:00
useVendor := ctx . inVendor ( ) || ctx . useVndk ( )
testInstallBase := getTestInstallBase ( useVendor )
2023-08-02 22:53:00 +02:00
configs := getTradefedConfigOptions ( ctx , & test . Properties , test . isolated ( ctx ) , ctx . Device ( ) )
2022-12-04 12:16:42 +01:00
2022-12-08 03:18:37 +01:00
test . testConfig = tradefed . AutoGenTestConfig ( ctx , tradefed . AutoGenTestConfigOptions {
TestConfigProp : test . Properties . Test_config ,
TestConfigTemplateProp : test . Properties . Test_config_template ,
TestSuites : test . testDecorator . InstallerProperties . Test_suites ,
Config : configs ,
2023-05-26 06:21:44 +02:00
TestRunnerOptions : test . Properties . Test_options . Test_runner_options ,
2022-12-08 03:18:37 +01:00
AutoGenConfig : test . Properties . Auto_gen_config ,
TestInstallBase : testInstallBase ,
DeviceTemplate : "${NativeTestConfigTemplate}" ,
HostTemplate : "${NativeHostTestConfigTemplate}" ,
} )
2022-12-04 12:16:42 +01:00
test . extraTestConfigs = android . PathsForModuleSrc ( ctx , test . Properties . Test_options . Extra_test_configs )
test . binaryDecorator . baseInstaller . dir = "nativetest"
test . binaryDecorator . baseInstaller . dir64 = "nativetest64"
if ! Bool ( test . Properties . No_named_install_directory ) {
test . binaryDecorator . baseInstaller . relative = ctx . ModuleName ( )
} else if String ( test . binaryDecorator . baseInstaller . Properties . Relative_install_path ) == "" {
ctx . PropertyErrorf ( "no_named_install_directory" , "Module install directory may only be disabled if relative_install_path is set" )
}
if ctx . Host ( ) && test . gtest ( ) && test . Properties . Test_options . Unit_test == nil {
test . Properties . Test_options . Unit_test = proptools . BoolPtr ( true )
}
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
}
2023-08-02 22:53:00 +02:00
func getTradefedConfigOptions ( ctx android . EarlyModuleContext , properties * TestBinaryProperties , isolated bool , device bool ) [ ] tradefed . Config {
2019-06-07 01:23:32 +02:00
var configs [ ] tradefed . Config
2022-12-04 12:16:42 +01:00
for _ , module := range properties . Test_mainline_modules {
2020-04-30 04:08:33 +02:00
configs = append ( configs , tradefed . Option { Name : "config-descriptor:metadata" , Key : "mainline-param" , Value : module } )
}
2023-08-02 22:53:00 +02:00
if device {
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 } )
}
2019-06-07 01:23:32 +02:00
}
2022-12-04 12:16:42 +01:00
if isolated {
2020-04-30 04:08:33 +02:00
configs = append ( configs , tradefed . Option { Name : "not-shardable" , Value : "true" } )
2019-02-28 17:45:28 +01:00
}
2022-12-04 12:16:42 +01:00
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 ) } )
2018-10-01 13:23:14 +02:00
}
2022-12-04 12:16:42 +01:00
for _ , tag := range properties . Test_options . Test_suite_tag {
2020-06-18 19:07:00 +02:00
configs = append ( configs , tradefed . Option { Name : "test-suite-tag" , Value : tag } )
}
2022-12-04 12:16:42 +01:00
if properties . Test_options . Min_shipping_api_level != nil {
if properties . Test_options . Vsr_min_shipping_api_level != nil {
2021-05-13 05:39:42 +02:00
ctx . PropertyErrorf ( "test_options.min_shipping_api_level" , "must not be set at the same time as 'vsr_min_shipping_api_level'." )
}
2021-05-04 11:42:24 +02:00
var options [ ] tradefed . Option
2022-12-04 12:16:42 +01:00
options = append ( options , tradefed . Option { Name : "min-api-level" , Value : strconv . FormatInt ( int64 ( * properties . Test_options . Min_shipping_api_level ) , 10 ) } )
2021-05-04 11:42:24 +02:00
configs = append ( configs , tradefed . Object { "module_controller" , "com.android.tradefed.testtype.suite.module.ShippingApiLevelModuleController" , options } )
2019-09-17 10:35:23 +02:00
}
2022-12-04 12:16:42 +01:00
if properties . Test_options . Vsr_min_shipping_api_level != nil {
2021-05-13 05:39:42 +02:00
var options [ ] tradefed . Option
2022-12-04 12:16:42 +01:00
options = append ( options , tradefed . Option { Name : "vsr-min-api-level" , Value : strconv . FormatInt ( int64 ( * properties . Test_options . Vsr_min_shipping_api_level ) , 10 ) } )
2021-05-13 05:39:42 +02:00
configs = append ( configs , tradefed . Object { "module_controller" , "com.android.tradefed.testtype.suite.module.ShippingApiLevelModuleController" , options } )
}
2022-12-04 12:16:42 +01:00
if properties . Test_options . Min_vndk_version != nil {
2021-05-04 11:42:24 +02:00
var options [ ] tradefed . Option
2022-12-04 12:16:42 +01:00
options = append ( options , tradefed . Option { Name : "min-api-level" , Value : strconv . FormatInt ( int64 ( * properties . Test_options . Min_vndk_version ) , 10 ) } )
2021-05-04 11:42:24 +02:00
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 } )
}
2022-12-04 12:16:42 +01:00
return configs
2016-07-29 21:48:20 +02:00
}
2022-08-24 13:53:27 +02:00
func NewTest ( hod android . HostOrDeviceSupported , bazelable bool ) * Module {
module , binary := newBinary ( hod , bazelable )
2022-12-12 13:20:58 +01:00
module . bazelable = bazelable
2016-07-30 02:28:03 +02:00
module . multilib = android . MultilibBoth
2016-08-30 00:53:15 +02:00
binary . baseInstaller = NewTestInstaller ( )
2016-07-30 02:28:03 +02:00
test := & testBinary {
2022-03-24 22:06:14 +01:00
testDecorator : & testDecorator {
linker : binary . baseLinker ,
installer : binary . baseInstaller ,
2016-07-29 21:48:20 +02:00
} ,
2016-07-30 02:28:03 +02:00
binaryDecorator : binary ,
baseCompiler : NewBaseCompiler ( ) ,
2016-07-29 21:48:20 +02:00
}
2016-07-30 02:28:03 +02:00
module . compiler = test
module . linker = test
module . installer = test
2016-07-29 21:48:20 +02:00
return module
}
2016-07-30 02:28:03 +02:00
type testLibrary struct {
2022-03-24 22:06:14 +01:00
* testDecorator
2016-07-30 02:28:03 +02:00
* libraryDecorator
}
2022-08-24 13:53:27 +02:00
func ( test * testLibrary ) testLibrary ( ) bool {
return true
}
2016-07-30 02:28:03 +02:00
func ( test * testLibrary ) linkerProps ( ) [ ] interface { } {
2022-03-24 22:06:14 +01:00
var props [ ] interface { }
props = append ( props , test . testDecorator . linkerProps ( ) ... )
return append ( props , test . libraryDecorator . linkerProps ( ) ... )
2016-07-30 02:28:03 +02:00
}
2016-12-14 02:06:13 +01:00
func ( test * testLibrary ) linkerDeps ( ctx DepsContext , deps Deps ) Deps {
2016-07-30 02:28:03 +02:00
deps = test . testDecorator . linkerDeps ( ctx , deps )
deps = test . libraryDecorator . linkerDeps ( ctx , deps )
return deps
}
func ( test * testLibrary ) linkerFlags ( ctx ModuleContext , flags Flags ) Flags {
flags = test . libraryDecorator . linkerFlags ( ctx , flags )
flags = test . testDecorator . linkerFlags ( ctx , flags )
return flags
}
2022-03-24 22:06:14 +01:00
func ( test * testLibrary ) installerProps ( ) [ ] interface { } {
return append ( test . baseInstaller . installerProps ( ) , test . testDecorator . installerProps ( ) ... )
}
2016-07-29 21:48:20 +02:00
func NewTestLibrary ( hod android . HostOrDeviceSupported ) * Module {
2016-12-09 23:46:15 +01:00
module , library := NewLibrary ( android . HostAndDeviceSupported )
2016-09-01 01:32:55 +02:00
library . baseInstaller = NewTestInstaller ( )
2016-07-30 02:28:03 +02:00
test := & testLibrary {
2022-03-24 22:06:14 +01:00
testDecorator : & testDecorator {
linker : library . baseLinker ,
installer : library . baseInstaller ,
2016-07-29 21:48:20 +02:00
} ,
2016-07-30 02:28:03 +02:00
libraryDecorator : library ,
2016-07-29 21:48:20 +02:00
}
2016-07-30 02:28:03 +02:00
module . linker = test
2022-03-24 22:06:14 +01:00
module . installer = test
2022-08-24 13:53:27 +02:00
module . bazelable = true
2016-07-29 21:48:20 +02:00
return module
}
2017-04-25 03:10:29 +02:00
type BenchmarkProperties struct {
2017-07-15 00:20:13 +02:00
// list of files or filegroup modules that provide data that should be installed alongside
// the test
2019-03-05 07:35:41 +01:00
Data [ ] string ` android:"path" `
2017-07-15 00:20:13 +02:00
2017-04-25 03:10:29 +02:00
// list of compatibility suites (for example "cts", "vts") that the module should be
// installed into.
2018-08-03 00:00:46 +02:00
Test_suites [ ] string ` android:"arch_variant" `
// the name of the test configuration (for example "AndroidTest.xml") that should be
// installed with the module.
2019-03-05 07:35:41 +01:00
Test_config * string ` android:"path,arch_variant" `
2018-09-19 11:21:28 +02:00
// the name of the test configuration template (for example "AndroidTestTemplate.xml") that
// should be installed with the module.
2019-03-05 07:35:41 +01:00
Test_config_template * string ` android:"path,arch_variant" `
2019-06-07 01:23:32 +02:00
// Add RootTargetPreparer to auto generated test config. This guarantees the test to run
// with root permission.
Require_root * bool
2019-09-26 20:41:36 +02:00
// Flag to indicate whether or not to create test config automatically. If AndroidTest.xml
// doesn't exist next to the Android.bp, this attribute doesn't need to be set to true
// explicitly.
Auto_gen_config * bool
2017-04-25 03:10:29 +02:00
}
2016-07-30 02:28:03 +02:00
type benchmarkDecorator struct {
* binaryDecorator
2017-04-25 03:10:29 +02:00
Properties BenchmarkProperties
2017-07-15 00:20:13 +02:00
data android . Paths
2018-08-08 01:49:25 +02:00
testConfig android . Path
2016-07-29 21:48:20 +02:00
}
2021-11-01 20:32:43 +01:00
func ( benchmark * benchmarkDecorator ) benchmarkBinary ( ) bool {
return true
}
2017-04-25 03:10:29 +02:00
func ( benchmark * benchmarkDecorator ) linkerProps ( ) [ ] interface { } {
props := benchmark . binaryDecorator . linkerProps ( )
props = append ( props , & benchmark . Properties )
return props
}
2016-12-14 02:06:13 +01:00
func ( benchmark * benchmarkDecorator ) linkerDeps ( ctx DepsContext , deps Deps ) Deps {
2016-07-30 02:28:03 +02:00
deps = benchmark . binaryDecorator . linkerDeps ( ctx , deps )
2016-07-29 21:48:20 +02:00
deps . StaticLibs = append ( deps . StaticLibs , "libgoogle-benchmark" )
return deps
}
2016-07-30 02:28:03 +02:00
func ( benchmark * benchmarkDecorator ) install ( ctx ModuleContext , file android . Path ) {
2019-03-06 07:25:09 +01:00
benchmark . data = android . PathsForModuleSrc ( ctx , benchmark . Properties . Data )
2020-06-05 23:26:16 +02:00
2019-06-07 01:23:32 +02:00
var configs [ ] tradefed . Config
if Bool ( benchmark . Properties . Require_root ) {
2019-09-17 10:35:23 +02:00
configs = append ( configs , tradefed . Object { "target_preparer" , "com.android.tradefed.targetprep.RootTargetPreparer" , nil } )
2019-06-07 01:23:32 +02:00
}
2022-12-08 03:18:37 +01:00
benchmark . testConfig = tradefed . AutoGenTestConfig ( ctx , tradefed . AutoGenTestConfigOptions {
TestConfigProp : benchmark . Properties . Test_config ,
TestConfigTemplateProp : benchmark . Properties . Test_config_template ,
TestSuites : benchmark . Properties . Test_suites ,
Config : configs ,
AutoGenConfig : benchmark . Properties . Auto_gen_config ,
DeviceTemplate : "${NativeBenchmarkTestConfigTemplate}" ,
HostTemplate : "${NativeBenchmarkTestConfigTemplate}" ,
} )
2018-08-08 01:49:25 +02:00
2017-09-09 01:20:30 +02:00
benchmark . binaryDecorator . baseInstaller . dir = filepath . Join ( "benchmarktest" , ctx . ModuleName ( ) )
benchmark . binaryDecorator . baseInstaller . dir64 = filepath . Join ( "benchmarktest64" , ctx . ModuleName ( ) )
2016-08-30 00:53:15 +02:00
benchmark . binaryDecorator . baseInstaller . install ( ctx , file )
2016-07-30 02:28:03 +02:00
}
2016-07-29 21:48:20 +02:00
func NewBenchmark ( hod android . HostOrDeviceSupported ) * Module {
2021-11-01 20:32:43 +01:00
module , binary := newBinary ( hod , false )
2016-07-30 02:28:03 +02:00
module . multilib = android . MultilibBoth
2017-09-09 01:20:30 +02:00
binary . baseInstaller = NewBaseInstaller ( "benchmarktest" , "benchmarktest64" , InstallInData )
2016-07-30 02:28:03 +02:00
benchmark := & benchmarkDecorator {
binaryDecorator : binary ,
2016-07-29 21:48:20 +02:00
}
2016-07-30 02:28:03 +02:00
module . linker = benchmark
module . installer = benchmark
2016-07-29 21:48:20 +02:00
return module
}
2022-08-24 13:53:27 +02:00
2022-12-12 13:20:58 +01:00
type ccTestBazelHandler struct {
module * Module
}
var _ BazelHandler = ( * ccTestBazelHandler ) ( nil )
2023-07-24 16:56:28 +02:00
// The top level target named $label is a test_suite target,
// not the internal cc_test executable target.
//
// This is to ensure `b test //$label` runs the test_suite target directly,
// which depends on tradefed_test targets, instead of the internal cc_test
// target, which doesn't have tradefed integrations.
//
// However, for cquery, we want the internal cc_test executable target, which
// has the suffix "__tf_internal".
func mixedBuildsTestLabel ( label string ) string {
return label + "__tf_internal"
}
2022-12-12 13:20:58 +01:00
func ( handler * ccTestBazelHandler ) QueueBazelCall ( ctx android . BaseModuleContext , label string ) {
bazelCtx := ctx . Config ( ) . BazelContext
2023-07-24 16:56:28 +02:00
bazelCtx . QueueBazelRequest ( mixedBuildsTestLabel ( label ) , cquery . GetCcUnstrippedInfo , android . GetConfigKey ( ctx ) )
2022-12-12 13:20:58 +01:00
}
func ( handler * ccTestBazelHandler ) ProcessBazelQueryResponse ( ctx android . ModuleContext , label string ) {
bazelCtx := ctx . Config ( ) . BazelContext
2023-07-24 16:56:28 +02:00
info , err := bazelCtx . GetCcUnstrippedInfo ( mixedBuildsTestLabel ( label ) , android . GetConfigKey ( ctx ) )
2022-12-12 13:20:58 +01:00
if err != nil {
ctx . ModuleErrorf ( err . Error ( ) )
return
}
2023-02-04 00:12:15 +01:00
var outputFilePath android . Path = android . PathForBazelOut ( ctx , info . OutputFile )
if len ( info . TidyFiles ) > 0 {
handler . module . tidyFiles = android . PathsForBazelOut ( ctx , info . TidyFiles )
outputFilePath = android . AttachValidationActions ( ctx , outputFilePath , handler . module . tidyFiles )
}
2022-12-12 13:20:58 +01:00
handler . module . outputFile = android . OptionalPathForPath ( outputFilePath )
handler . module . linker . ( * testBinary ) . unstrippedOutputFile = android . PathForBazelOut ( ctx , info . UnstrippedOutput )
2023-01-27 22:01:37 +01:00
handler . module . setAndroidMkVariablesFromCquery ( info . CcAndroidMkInfo )
2022-12-12 13:20:58 +01:00
}
2022-08-24 13:53:27 +02:00
// binaryAttributes contains Bazel attributes corresponding to a cc test
type testBinaryAttributes struct {
binaryAttributes
2023-07-26 19:35:20 +02:00
Gtest * bool
2022-10-21 16:42:24 +02:00
tidyAttributes
2022-12-04 12:16:42 +01:00
tradefed . TestConfigAttributes
2023-08-17 03:03:37 +02:00
Runs_on bazel . StringListAttribute
2022-08-24 13:53:27 +02:00
}
// testBinaryBp2build is the bp2build converter for cc_test modules. A cc_test's
// dependency graph and compilation/linking steps are functionally similar to a
// cc_binary, but has additional dependencies on test deps like gtest, and
// produces additional runfiles like XML plans for Tradefed orchestration
//
// 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)
2023-09-19 22:09:00 +02:00
func testBinaryBp2build ( ctx android . Bp2buildMutatorContext , m * Module ) {
2022-08-24 13:53:27 +02:00
var testBinaryAttrs testBinaryAttributes
testBinaryAttrs . binaryAttributes = binaryBp2buildAttrs ( ctx , m )
2022-09-01 20:54:50 +02:00
var data bazel . LabelListAttribute
2022-09-16 04:32:03 +02:00
var tags bazel . StringListAttribute
2022-09-01 20:54:50 +02:00
2022-08-24 13:53:27 +02:00
testBinaryProps := m . GetArchVariantProperties ( ctx , & TestBinaryProperties { } )
for axis , configToProps := range testBinaryProps {
for config , props := range configToProps {
if p , ok := props . ( * TestBinaryProperties ) ; ok {
// Combine data, data_bins and data_libs into a single 'data' attribute.
var combinedData bazel . LabelList
combinedData . Append ( android . BazelLabelForModuleSrc ( ctx , p . Data ) )
combinedData . Append ( android . BazelLabelForModuleDeps ( ctx , p . Data_bins ) )
combinedData . Append ( android . BazelLabelForModuleDeps ( ctx , p . Data_libs ) )
2022-09-01 20:54:50 +02:00
data . SetSelectValue ( axis , config , combinedData )
2022-09-16 04:32:03 +02:00
tags . SetSelectValue ( axis , config , p . Test_options . Tags )
2022-08-24 13:53:27 +02:00
}
}
}
2023-08-26 01:56:33 +02:00
// The logic comes from https://cs.android.com/android/platform/superproject/main/+/0df8153267f96da877febc5332240fa06ceb8533:build/soong/cc/sanitize.go;l=488
var features bazel . StringListAttribute
curFeatures := testBinaryAttrs . binaryAttributes . Features . SelectValue ( bazel . OsArchConfigurationAxis , bazel . OsArchAndroidArm64 )
var newFeatures [ ] string
if ! android . InList ( "memtag_heap" , curFeatures ) && ! android . InList ( "-memtag_heap" , curFeatures ) {
newFeatures = append ( newFeatures , "memtag_heap" )
if ! android . InList ( "diag_memtag_heap" , curFeatures ) && ! android . InList ( "-diag_memtag_heap" , curFeatures ) {
newFeatures = append ( newFeatures , "diag_memtag_heap" )
}
}
features . SetSelectValue ( bazel . OsArchConfigurationAxis , bazel . OsArchAndroidArm64 , newFeatures )
testBinaryAttrs . binaryAttributes . Features . Append ( features )
testBinaryAttrs . binaryAttributes . Features . DeduplicateAxesFromBase ( )
2022-10-25 21:47:17 +02:00
m . convertTidyAttributes ( ctx , & testBinaryAttrs . tidyAttributes )
2022-10-21 16:42:24 +02:00
2023-07-26 19:35:20 +02:00
testBinary := m . linker . ( * testBinary )
gtest := testBinary . gtest ( )
gtestIsolated := testBinary . isolated ( ctx )
// Use the underling bool pointer for Gtest in attrs
// This ensures that if this property is not set in Android.bp file, it will not be set in BUILD file either
// cc_test macro will default gtest to True
testBinaryAttrs . Gtest = testBinary . LinkerProperties . Gtest
2022-08-24 13:53:27 +02:00
2023-07-26 19:35:20 +02:00
addImplicitGtestDeps ( ctx , & testBinaryAttrs , gtest , gtestIsolated )
2023-07-22 00:55:32 +02:00
2023-08-17 03:03:37 +02:00
var unitTest * bool
2022-12-04 12:16:42 +01:00
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 ,
2023-08-02 22:53:00 +02:00
getTradefedConfigOptions ( ctx , p , gtestIsolated , true ) ,
2022-12-04 12:16:42 +01:00
& testInstallBase ,
)
testBinaryAttrs . TestConfigAttributes = testConfigAttributes
2023-08-17 03:03:37 +02:00
unitTest = p . Test_options . Unit_test
2022-12-04 12:16:42 +01:00
}
}
2023-08-17 03:03:37 +02:00
testBinaryAttrs . Runs_on = bazel . MakeStringListAttribute ( android . RunsOn (
m . ModuleBase . HostSupported ( ) ,
m . ModuleBase . DeviceSupported ( ) ,
gtest || ( unitTest != nil && * unitTest ) ) )
2022-12-04 12:16:42 +01:00
// TODO (b/262914724): convert to tradefed_cc_test and tradefed_cc_test_host
2022-08-24 13:53:27 +02:00
ctx . CreateBazelTargetModule (
bazel . BazelTargetModuleProperties {
Rule_class : "cc_test" ,
Bzl_load_location : "//build/bazel/rules/cc:cc_test.bzl" ,
} ,
2022-09-01 20:54:50 +02:00
android . CommonAttributes {
Name : m . Name ( ) ,
Data : data ,
2022-09-16 04:32:03 +02:00
Tags : tags ,
2022-09-01 20:54:50 +02:00
} ,
2022-08-24 13:53:27 +02:00
& testBinaryAttrs )
}
2023-07-22 00:55:32 +02:00
// cc_test that builds using gtest needs some additional deps
// addImplicitGtestDeps makes these deps explicit in the generated BUILD files
2023-09-28 22:41:03 +02:00
func addImplicitGtestDeps ( ctx android . Bp2buildMutatorContext , attrs * testBinaryAttributes , gtest , gtestIsolated bool ) {
2023-07-22 04:19:42 +02:00
addDepsAndDedupe := func ( lla * bazel . LabelListAttribute , modules [ ] string ) {
moduleLabels := android . BazelLabelForModuleDeps ( ctx , modules )
lla . Value . Append ( moduleLabels )
// Dedupe
lla . Value = bazel . FirstUniqueBazelLabelList ( lla . Value )
}
// this must be kept in sync with Soong's implementation in:
// https://cs.android.com/android/_/android/platform/build/soong/+/460fb2d6d546b5ab493a7e5479998c4933a80f73:cc/test.go;l=300-313;drc=ec7314336a2b35ea30ce5438b83949c28e3ac429;bpv=1;bpt=0
2023-07-26 19:35:20 +02:00
if gtest {
2023-07-22 04:19:42 +02:00
// TODO - b/244433197: Handle canUseSdk
if gtestIsolated {
addDepsAndDedupe ( & attrs . Deps , [ ] string { "libgtest_isolated_main" } )
addDepsAndDedupe ( & attrs . Dynamic_deps , [ ] string { "liblog" } )
} else {
addDepsAndDedupe ( & attrs . Deps , [ ] string {
2023-07-22 00:55:32 +02:00
"libgtest_main" ,
"libgtest" ,
2023-07-22 04:19:42 +02:00
} )
}
2023-07-22 00:55:32 +02:00
}
}