1// Copyright 2016 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 cc 16 17import ( 18 "path/filepath" 19 "strconv" 20 21 "github.com/google/blueprint/depset" 22 "github.com/google/blueprint/proptools" 23 24 "android/soong/android" 25 "android/soong/tradefed" 26) 27 28// TestLinkerProperties properties to be registered via the linker 29type TestLinkerProperties struct { 30 // if set, build against the gtest library. Defaults to true. 31 Gtest *bool 32 33 // if set, use the isolated gtest runner. Defaults to false. 34 // Isolation is not supported on Windows. 35 Isolated *bool 36} 37 38// TestInstallerProperties properties to be registered via the installer 39type TestInstallerProperties struct { 40 // list of compatibility suites (for example "cts", "vts") that the module should be installed into. 41 Test_suites []string `android:"arch_variant"` 42} 43 44// Test option struct. 45type TestOptions struct { 46 android.CommonTestOptions 47 48 // The UID that you want to run the test as on a device. 49 Run_test_as *string 50 51 // A list of free-formed strings without spaces that categorize the test. 52 Test_suite_tag []string 53 54 // a list of extra test configuration files that should be installed with the module. 55 Extra_test_configs []string `android:"path,arch_variant"` 56 57 // Add ShippingApiLevelModuleController to auto generated test config. If the device properties 58 // for the shipping api level is less than the min_shipping_api_level, skip this module. 59 Min_shipping_api_level *int64 60 61 // Add ShippingApiLevelModuleController to auto generated test config. If any of the device 62 // shipping api level and vendor api level properties are less than the 63 // vsr_min_shipping_api_level, skip this module. 64 // As this includes the shipping api level check, it is not allowed to define 65 // min_shipping_api_level at the same time with this property. 66 Vsr_min_shipping_api_level *int64 67 68 // Add MinApiLevelModuleController with ro.vndk.version property. If ro.vndk.version has an 69 // integer value and the value is less than the min_vndk_version, skip this module. 70 Min_vndk_version *int64 71 72 // Extra <option> tags to add to the auto generated test xml file under the test runner, e.g., GTest. 73 // The "key" is optional in each of these. 74 Test_runner_options []tradefed.Option 75} 76 77type TestBinaryProperties struct { 78 // Disables the creation of a test-specific directory when used with 79 // relative_install_path. Useful if several tests need to be in the same 80 // directory. 81 No_named_install_directory *bool 82 83 // list of files or filegroup modules that provide data that should be installed alongside 84 // the test 85 Data []string `android:"path,arch_variant"` 86 87 // Same as data, but adds dependencies on modules using the device's os variant, and common 88 // architecture's variant. Can be useful to add device-built apps to the data of a host 89 // test. 90 Device_common_data []string `android:"path_device_common"` 91 92 // Same as data, but adds dependencies on modules using the device's os variant, and the 93 // device's first architecture's variant. Can be useful to add device-built apps to the data 94 // of a host test. 95 Device_first_data []string `android:"path_device_first"` 96 97 // Same as data, but will add dependencies on modules using the host's os variation and 98 // the common arch variation. Useful for a device test that wants to depend on a host 99 // module, for example to include a custom Tradefed test runner. 100 Host_common_data []string `android:"path_host_common"` 101 102 // list of shared library modules that should be installed alongside the test 103 Data_libs []string `android:"arch_variant"` 104 105 // list of binary modules that should be installed alongside the test 106 Data_bins []string `android:"arch_variant"` 107 108 // the name of the test configuration (for example "AndroidTest.xml") that should be 109 // installed with the module. 110 Test_config *string `android:"path,arch_variant"` 111 112 // the name of the test configuration template (for example "AndroidTestTemplate.xml") that 113 // should be installed with the module. 114 Test_config_template *string `android:"path,arch_variant"` 115 116 // Test options. 117 Test_options TestOptions 118 119 // Add RootTargetPreparer to auto generated test config. This guarantees the test to run 120 // with root permission. 121 Require_root *bool 122 123 // Add RunCommandTargetPreparer to stop framework before the test and start it after the test. 124 Disable_framework *bool 125 126 // Flag to indicate whether or not to create test config automatically. If AndroidTest.xml 127 // doesn't exist next to the Android.bp, this attribute doesn't need to be set to true 128 // explicitly. 129 Auto_gen_config *bool 130 131 // Add parameterized mainline modules to auto generated test config. The options will be 132 // handled by TradeFed to download and install the specified modules on the device. 133 Test_mainline_modules []string 134 135 // Install the test into a folder named for the module in all test suites. 136 Per_testcase_directory *bool 137 138 // Install the test's dependencies into a folder named standalone-libs relative to the 139 // test's installation path. ld-library-path will be set to this path in the test's 140 // auto-generated config. This way the dependencies can be used by the test without having 141 // to manually install them to the device. See more details in 142 // go/standalone-native-device-tests. 143 Standalone_test *bool 144} 145 146func init() { 147 android.RegisterModuleType("cc_test", TestFactory) 148 android.RegisterModuleType("cc_test_library", TestLibraryFactory) 149 android.RegisterModuleType("cc_benchmark", BenchmarkFactory) 150 android.RegisterModuleType("cc_test_host", TestHostFactory) 151 android.RegisterModuleType("cc_benchmark_host", BenchmarkHostFactory) 152} 153 154// cc_test generates a test config file and an executable binary file to test 155// specific functionality on a device. The executable binary gets an implicit 156// static_libs dependency on libgtests unless the gtest flag is set to false. 157func TestFactory() android.Module { 158 module := NewTest(android.HostAndDeviceSupported) 159 return module.Init() 160} 161 162// cc_test_library creates an archive of files (i.e. .o files) which is later 163// referenced by another module (such as cc_test, cc_defaults or cc_test_library) 164// for archiving or linking. 165func TestLibraryFactory() android.Module { 166 module := NewTestLibrary(android.HostAndDeviceSupported) 167 return module.Init() 168} 169 170// cc_benchmark compiles an executable binary that performs benchmark testing 171// of a specific component in a device. Additional files such as test suites 172// and test configuration are installed on the side of the compiled executed 173// binary. 174func BenchmarkFactory() android.Module { 175 module := NewBenchmark(android.HostAndDeviceSupported) 176 module.testModule = true 177 return module.Init() 178} 179 180// cc_test_host compiles a test host binary. 181func TestHostFactory() android.Module { 182 module := NewTest(android.HostSupported) 183 return module.Init() 184} 185 186// cc_benchmark_host compiles an executable binary that performs benchmark 187// testing of a specific component in the host. Additional files such as 188// test suites and test configuration are installed on the side of the 189// compiled executed binary. 190func BenchmarkHostFactory() android.Module { 191 module := NewBenchmark(android.HostSupported) 192 return module.Init() 193} 194 195func (test *testBinary) dataPaths() []android.DataPath { 196 return test.data 197} 198 199func (test *testBinary) testBinary() bool { 200 return true 201} 202 203type testDecorator struct { 204 LinkerProperties TestLinkerProperties 205 InstallerProperties TestInstallerProperties 206 installer *baseInstaller 207 linker *baseLinker 208} 209 210func (test *testDecorator) gtest() bool { 211 return BoolDefault(test.LinkerProperties.Gtest, true) 212} 213 214func (test *testDecorator) isolated(ctx android.BaseModuleContext) bool { 215 return BoolDefault(test.LinkerProperties.Isolated, false) && !ctx.Windows() 216} 217 218// NOTE: Keep this in sync with cc/cc_test.bzl#gtest_copts 219func (test *testDecorator) linkerFlags(ctx ModuleContext, flags Flags) Flags { 220 if !test.gtest() { 221 return flags 222 } 223 224 flags.Local.CFlags = append(flags.Local.CFlags, "-DGTEST_HAS_STD_STRING") 225 if ctx.Host() { 226 flags.Local.CFlags = append(flags.Local.CFlags, "-O0", "-g") 227 228 switch ctx.Os() { 229 case android.Windows: 230 flags.Local.CFlags = append(flags.Local.CFlags, "-DGTEST_OS_WINDOWS") 231 case android.Linux: 232 flags.Local.CFlags = append(flags.Local.CFlags, "-DGTEST_OS_LINUX") 233 case android.Darwin: 234 flags.Local.CFlags = append(flags.Local.CFlags, "-DGTEST_OS_MAC") 235 } 236 } else { 237 flags.Local.CFlags = append(flags.Local.CFlags, "-DGTEST_OS_LINUX_ANDROID") 238 } 239 240 return flags 241} 242 243func (test *testDecorator) linkerDeps(ctx BaseModuleContext, deps Deps) Deps { 244 if test.gtest() { 245 if ctx.useSdk() && ctx.Device() { 246 deps.StaticLibs = append(deps.StaticLibs, "libgtest_main_ndk_c++", "libgtest_ndk_c++") 247 } else if test.isolated(ctx) { 248 deps.StaticLibs = append(deps.StaticLibs, "libgtest_isolated_main") 249 // The isolated library requires liblog, but adding it 250 // as a static library means unit tests cannot override 251 // liblog functions. Instead make it a shared library 252 // dependency. 253 deps.SharedLibs = append(deps.SharedLibs, "liblog") 254 } else { 255 deps.StaticLibs = append(deps.StaticLibs, "libgtest_main", "libgtest") 256 } 257 } 258 259 return deps 260} 261 262func (test *testDecorator) linkerProps() []interface{} { 263 return []interface{}{&test.LinkerProperties} 264} 265 266func (test *testDecorator) installerProps() []interface{} { 267 return []interface{}{&test.InstallerProperties} 268} 269 270func (test *testDecorator) moduleInfoJSON(ctx android.ModuleContext, moduleInfoJSON *android.ModuleInfoJSON) { 271 if android.PrefixInList(moduleInfoJSON.CompatibilitySuites, "mts-") && 272 !android.InList("mts", moduleInfoJSON.CompatibilitySuites) { 273 moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, "mts") 274 } 275} 276 277func (test *testDecorator) testSuiteInfo(ctx ModuleContext) { 278 android.SetProvider(ctx, android.TestSuiteInfoProvider, android.TestSuiteInfo{ 279 TestSuites: test.InstallerProperties.Test_suites, 280 }) 281} 282 283func NewTestInstaller() *baseInstaller { 284 return NewBaseInstaller("nativetest", "nativetest64", InstallInData) 285} 286 287type testBinary struct { 288 *testDecorator 289 *binaryDecorator 290 *baseCompiler 291 Properties TestBinaryProperties 292 data []android.DataPath 293 testConfig android.Path 294 extraTestConfigs android.Paths 295} 296 297func (test *testBinary) linkerProps() []interface{} { 298 props := append(test.testDecorator.linkerProps(), test.binaryDecorator.linkerProps()...) 299 props = append(props, &test.Properties) 300 return props 301} 302 303func (test *testBinary) linkerDeps(ctx DepsContext, deps Deps) Deps { 304 deps = test.testDecorator.linkerDeps(ctx, deps) 305 deps = test.binaryDecorator.linkerDeps(ctx, deps) 306 deps.DataLibs = append(deps.DataLibs, test.Properties.Data_libs...) 307 deps.DataBins = append(deps.DataBins, test.Properties.Data_bins...) 308 return deps 309} 310 311func (test *testBinary) linkerFlags(ctx ModuleContext, flags Flags) Flags { 312 flags = test.binaryDecorator.linkerFlags(ctx, flags) 313 flags = test.testDecorator.linkerFlags(ctx, flags) 314 315 // Add a default rpath to allow tests to dlopen libraries specified in data_libs. 316 // Host modules already get an rpath specified in linker.go. 317 if !ctx.Host() { 318 flags.Global.LdFlags = append(flags.Global.LdFlags, `-Wl,-rpath,\$$ORIGIN`) 319 } 320 return flags 321} 322 323func (test *testBinary) moduleInfoJSON(ctx ModuleContext, moduleInfoJSON *android.ModuleInfoJSON) { 324 if ctx.Host() && Bool(test.Properties.Test_options.Unit_test) { 325 moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, "host-unit-tests") 326 } 327 moduleInfoJSON.TestOptionsTags = append(moduleInfoJSON.TestOptionsTags, test.Properties.Test_options.Tags...) 328 moduleInfoJSON.TestMainlineModules = append(moduleInfoJSON.TestMainlineModules, test.Properties.Test_mainline_modules...) 329 if test.testConfig != nil { 330 if _, ok := test.testConfig.(android.WritablePath); ok { 331 moduleInfoJSON.AutoTestConfig = []string{"true"} 332 } 333 moduleInfoJSON.TestConfig = append(moduleInfoJSON.TestConfig, test.testConfig.String()) 334 } 335 moduleInfoJSON.TestConfig = append(moduleInfoJSON.TestConfig, test.extraTestConfigs.Strings()...) 336 337 moduleInfoJSON.DataDependencies = append(moduleInfoJSON.DataDependencies, test.Properties.Data_bins...) 338 339 if len(test.InstallerProperties.Test_suites) > 0 { 340 moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, test.InstallerProperties.Test_suites...) 341 } else { 342 moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, "null-suite") 343 } 344 345 test.binaryDecorator.moduleInfoJSON(ctx, moduleInfoJSON) 346 test.testDecorator.moduleInfoJSON(ctx, moduleInfoJSON) 347 moduleInfoJSON.Class = []string{"NATIVE_TESTS"} 348 349} 350 351func (test *testBinary) testSuiteInfo(ctx ModuleContext) { 352 test.testDecorator.testSuiteInfo(ctx) 353} 354 355func (test *testBinary) installerProps() []interface{} { 356 return append(test.baseInstaller.installerProps(), test.testDecorator.installerProps()...) 357} 358 359func (test *testBinary) install(ctx ModuleContext, file android.Path) { 360 dataSrcPaths := android.PathsForModuleSrc(ctx, test.Properties.Data) 361 dataSrcPaths = append(dataSrcPaths, android.PathsForModuleSrc(ctx, test.Properties.Device_common_data)...) 362 dataSrcPaths = append(dataSrcPaths, android.PathsForModuleSrc(ctx, test.Properties.Device_first_data)...) 363 dataSrcPaths = append(dataSrcPaths, android.PathsForModuleSrc(ctx, test.Properties.Host_common_data)...) 364 365 for _, dataSrcPath := range dataSrcPaths { 366 test.data = append(test.data, android.DataPath{SrcPath: dataSrcPath}) 367 } 368 369 ctx.VisitDirectDepsProxyWithTag(dataLibDepTag, func(dep android.ModuleProxy) { 370 depName := ctx.OtherModuleName(dep) 371 linkableDep, ok := android.OtherModuleProvider(ctx, dep, LinkableInfoProvider) 372 if !ok { 373 ctx.ModuleErrorf("data_lib %q is not a LinkableInterface module", depName) 374 } 375 if linkableDep.OutputFile.Valid() { 376 test.data = append(test.data, 377 android.DataPath{SrcPath: linkableDep.OutputFile.Path(), 378 RelativeInstallPath: linkableDep.RelativeInstallPath}) 379 } 380 }) 381 ctx.VisitDirectDepsProxyWithTag(dataBinDepTag, func(dep android.ModuleProxy) { 382 depName := ctx.OtherModuleName(dep) 383 linkableDep, ok := android.OtherModuleProvider(ctx, dep, LinkableInfoProvider) 384 if !ok { 385 ctx.ModuleErrorf("data_bin %q is not a LinkableInterface module", depName) 386 } 387 if linkableDep.OutputFile.Valid() { 388 test.data = append(test.data, 389 android.DataPath{SrcPath: linkableDep.OutputFile.Path(), 390 RelativeInstallPath: linkableDep.RelativeInstallPath}) 391 } 392 }) 393 394 testInstallBase := getTestInstallBase(ctx.InVendorOrProduct()) 395 configs := getTradefedConfigOptions(ctx, &test.Properties, test.isolated(ctx), ctx.Device()) 396 397 test.testConfig = tradefed.AutoGenTestConfig(ctx, tradefed.AutoGenTestConfigOptions{ 398 TestConfigProp: test.Properties.Test_config, 399 TestConfigTemplateProp: test.Properties.Test_config_template, 400 TestSuites: test.testDecorator.InstallerProperties.Test_suites, 401 Config: configs, 402 TestRunnerOptions: test.Properties.Test_options.Test_runner_options, 403 AutoGenConfig: test.Properties.Auto_gen_config, 404 TestInstallBase: testInstallBase, 405 DeviceTemplate: "${NativeTestConfigTemplate}", 406 HostTemplate: "${NativeHostTestConfigTemplate}", 407 StandaloneTest: test.Properties.Standalone_test, 408 }) 409 410 test.extraTestConfigs = android.PathsForModuleSrc(ctx, test.Properties.Test_options.Extra_test_configs) 411 412 test.binaryDecorator.baseInstaller.dir = "nativetest" 413 test.binaryDecorator.baseInstaller.dir64 = "nativetest64" 414 415 if !Bool(test.Properties.No_named_install_directory) { 416 test.binaryDecorator.baseInstaller.relative = ctx.ModuleName() 417 } else if String(test.binaryDecorator.baseInstaller.Properties.Relative_install_path) == "" { 418 ctx.PropertyErrorf("no_named_install_directory", "Module install directory may only be disabled if relative_install_path is set") 419 } 420 421 if ctx.Host() && test.gtest() && test.Properties.Test_options.Unit_test == nil { 422 test.Properties.Test_options.Unit_test = proptools.BoolPtr(true) 423 } 424 425 if !ctx.Config().KatiEnabled() { // TODO(spandandas): Remove the special case for kati 426 // Install the test config in testcases/ directory for atest. 427 c, ok := ctx.Module().(*Module) 428 if !ok { 429 ctx.ModuleErrorf("Not a cc_test module") 430 } 431 // Install configs in the root of $PRODUCT_OUT/testcases/$module 432 testCases := android.PathForModuleInPartitionInstall(ctx, "testcases", ctx.ModuleName()+c.SubName()) 433 if ctx.PrimaryArch() { 434 if test.testConfig != nil { 435 ctx.InstallFile(testCases, ctx.ModuleName()+".config", test.testConfig) 436 } 437 dynamicConfig := android.ExistentPathForSource(ctx, ctx.ModuleDir(), "DynamicConfig.xml") 438 if dynamicConfig.Valid() { 439 ctx.InstallFile(testCases, ctx.ModuleName()+".dynamic", dynamicConfig.Path()) 440 } 441 for _, extraTestConfig := range test.extraTestConfigs { 442 ctx.InstallFile(testCases, extraTestConfig.Base(), extraTestConfig) 443 } 444 } 445 // Install tests and data in arch specific subdir $PRODUCT_OUT/testcases/$module/$arch 446 testCases = testCases.Join(ctx, ctx.Target().Arch.ArchType.String()) 447 ctx.InstallTestData(testCases, test.data) 448 ctx.InstallFile(testCases, file.Base(), file) 449 } 450 451 test.binaryDecorator.baseInstaller.installTestData(ctx, test.data) 452 test.binaryDecorator.baseInstaller.install(ctx, file) 453 if Bool(test.Properties.Standalone_test) { 454 packagingSpecsBuilder := depset.NewBuilder[android.PackagingSpec](depset.TOPOLOGICAL) 455 456 ctx.VisitDirectDeps(func(dep android.Module) { 457 deps := android.OtherModuleProviderOrDefault(ctx, dep, android.InstallFilesProvider) 458 packagingSpecsBuilder.Transitive(deps.TransitivePackagingSpecs) 459 }) 460 461 for _, standaloneTestDep := range packagingSpecsBuilder.Build().ToList() { 462 if standaloneTestDep.ToGob().SrcPath == nil { 463 continue 464 } 465 if standaloneTestDep.SkipInstall() { 466 continue 467 } 468 if standaloneTestDep.Partition() == "data" { 469 continue 470 } 471 test.binaryDecorator.baseInstaller.installStandaloneTestDep(ctx, standaloneTestDep) 472 } 473 } 474} 475 476func getTestInstallBase(useVendor bool) string { 477 // TODO: (b/167308193) Switch to /data/local/tests/unrestricted as the default install base. 478 testInstallBase := "/data/local/tmp" 479 if useVendor { 480 testInstallBase = "/data/local/tests/vendor" 481 } 482 return testInstallBase 483} 484 485func getTradefedConfigOptions(ctx android.EarlyModuleContext, properties *TestBinaryProperties, isolated bool, device bool) []tradefed.Config { 486 var configs []tradefed.Config 487 488 for _, module := range properties.Test_mainline_modules { 489 configs = append(configs, tradefed.Option{Name: "config-descriptor:metadata", Key: "mainline-param", Value: module}) 490 } 491 if device { 492 if Bool(properties.Require_root) { 493 configs = append(configs, tradefed.Object{"target_preparer", "com.android.tradefed.targetprep.RootTargetPreparer", nil}) 494 } else { 495 var options []tradefed.Option 496 options = append(options, tradefed.Option{Name: "force-root", Value: "false"}) 497 configs = append(configs, tradefed.Object{"target_preparer", "com.android.tradefed.targetprep.RootTargetPreparer", options}) 498 } 499 if Bool(properties.Disable_framework) { 500 var options []tradefed.Option 501 configs = append(configs, tradefed.Object{"target_preparer", "com.android.tradefed.targetprep.StopServicesSetup", options}) 502 } 503 } 504 if isolated { 505 configs = append(configs, tradefed.Option{Name: "not-shardable", Value: "true"}) 506 } 507 if properties.Test_options.Run_test_as != nil { 508 configs = append(configs, tradefed.Option{Name: "run-test-as", Value: String(properties.Test_options.Run_test_as)}) 509 } 510 for _, tag := range properties.Test_options.Test_suite_tag { 511 configs = append(configs, tradefed.Option{Name: "test-suite-tag", Value: tag}) 512 } 513 if properties.Test_options.Min_shipping_api_level != nil { 514 if properties.Test_options.Vsr_min_shipping_api_level != nil { 515 ctx.PropertyErrorf("test_options.min_shipping_api_level", "must not be set at the same time as 'vsr_min_shipping_api_level'.") 516 } 517 var options []tradefed.Option 518 options = append(options, tradefed.Option{Name: "min-api-level", Value: strconv.FormatInt(int64(*properties.Test_options.Min_shipping_api_level), 10)}) 519 configs = append(configs, tradefed.Object{"module_controller", "com.android.tradefed.testtype.suite.module.ShippingApiLevelModuleController", options}) 520 } 521 if properties.Test_options.Vsr_min_shipping_api_level != nil { 522 var options []tradefed.Option 523 options = append(options, tradefed.Option{Name: "vsr-min-api-level", Value: strconv.FormatInt(int64(*properties.Test_options.Vsr_min_shipping_api_level), 10)}) 524 configs = append(configs, tradefed.Object{"module_controller", "com.android.tradefed.testtype.suite.module.ShippingApiLevelModuleController", options}) 525 } 526 if properties.Test_options.Min_vndk_version != nil { 527 var options []tradefed.Option 528 options = append(options, tradefed.Option{Name: "min-api-level", Value: strconv.FormatInt(int64(*properties.Test_options.Min_vndk_version), 10)}) 529 options = append(options, tradefed.Option{Name: "api-level-prop", Value: "ro.vndk.version"}) 530 configs = append(configs, tradefed.Object{"module_controller", "com.android.tradefed.testtype.suite.module.MinApiLevelModuleController", options}) 531 } 532 return configs 533} 534 535func NewTest(hod android.HostOrDeviceSupported) *Module { 536 module, binary := newBinary(hod) 537 module.multilib = android.MultilibBoth 538 module.testModule = true 539 binary.baseInstaller = NewTestInstaller() 540 541 test := &testBinary{ 542 testDecorator: &testDecorator{ 543 linker: binary.baseLinker, 544 installer: binary.baseInstaller, 545 }, 546 binaryDecorator: binary, 547 baseCompiler: NewBaseCompiler(), 548 } 549 module.compiler = test 550 module.linker = test 551 module.installer = test 552 return module 553} 554 555type testLibrary struct { 556 *testDecorator 557 *libraryDecorator 558} 559 560func (test *testLibrary) testLibrary() bool { 561 return true 562} 563 564func (test *testLibrary) linkerProps() []interface{} { 565 var props []interface{} 566 props = append(props, test.testDecorator.linkerProps()...) 567 return append(props, test.libraryDecorator.linkerProps()...) 568} 569 570func (test *testLibrary) linkerDeps(ctx DepsContext, deps Deps) Deps { 571 deps = test.testDecorator.linkerDeps(ctx, deps) 572 deps = test.libraryDecorator.linkerDeps(ctx, deps) 573 return deps 574} 575 576func (test *testLibrary) linkerFlags(ctx ModuleContext, flags Flags) Flags { 577 flags = test.libraryDecorator.linkerFlags(ctx, flags) 578 flags = test.testDecorator.linkerFlags(ctx, flags) 579 return flags 580} 581 582func (test *testLibrary) moduleInfoJSON(ctx ModuleContext, moduleInfoJSON *android.ModuleInfoJSON) { 583 if len(test.InstallerProperties.Test_suites) > 0 { 584 moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, test.InstallerProperties.Test_suites...) 585 } 586 587 test.libraryDecorator.moduleInfoJSON(ctx, moduleInfoJSON) 588 test.testDecorator.moduleInfoJSON(ctx, moduleInfoJSON) 589} 590 591func (test *testLibrary) testSuiteInfo(ctx ModuleContext) { 592 test.testDecorator.testSuiteInfo(ctx) 593} 594 595func (test *testLibrary) installerProps() []interface{} { 596 return append(test.baseInstaller.installerProps(), test.testDecorator.installerProps()...) 597} 598 599func NewTestLibrary(hod android.HostOrDeviceSupported) *Module { 600 module, library := NewLibrary(android.HostAndDeviceSupported) 601 library.baseInstaller = NewTestInstaller() 602 test := &testLibrary{ 603 testDecorator: &testDecorator{ 604 linker: library.baseLinker, 605 installer: library.baseInstaller, 606 }, 607 libraryDecorator: library, 608 } 609 module.linker = test 610 module.installer = test 611 return module 612} 613 614type BenchmarkProperties struct { 615 // list of files or filegroup modules that provide data that should be installed alongside 616 // the test 617 Data []string `android:"path"` 618 619 // list of compatibility suites (for example "cts", "vts") that the module should be 620 // installed into. 621 Test_suites []string `android:"arch_variant"` 622 623 // the name of the test configuration (for example "AndroidTest.xml") that should be 624 // installed with the module. 625 Test_config *string `android:"path,arch_variant"` 626 627 // the name of the test configuration template (for example "AndroidTestTemplate.xml") that 628 // should be installed with the module. 629 Test_config_template *string `android:"path,arch_variant"` 630 631 // Add RootTargetPreparer to auto generated test config. This guarantees the test to run 632 // with root permission. 633 Require_root *bool 634 635 // Flag to indicate whether or not to create test config automatically. If AndroidTest.xml 636 // doesn't exist next to the Android.bp, this attribute doesn't need to be set to true 637 // explicitly. 638 Auto_gen_config *bool 639} 640 641type benchmarkDecorator struct { 642 *binaryDecorator 643 Properties BenchmarkProperties 644 data []android.DataPath 645 testConfig android.Path 646} 647 648func (benchmark *benchmarkDecorator) benchmarkBinary() bool { 649 return true 650} 651 652func (benchmark *benchmarkDecorator) linkerProps() []interface{} { 653 props := benchmark.binaryDecorator.linkerProps() 654 props = append(props, &benchmark.Properties) 655 return props 656} 657 658func (benchmark *benchmarkDecorator) linkerDeps(ctx DepsContext, deps Deps) Deps { 659 deps = benchmark.binaryDecorator.linkerDeps(ctx, deps) 660 deps.StaticLibs = append(deps.StaticLibs, "libgoogle-benchmark") 661 return deps 662} 663 664func (benchmark *benchmarkDecorator) install(ctx ModuleContext, file android.Path) { 665 for _, d := range android.PathsForModuleSrc(ctx, benchmark.Properties.Data) { 666 benchmark.data = append(benchmark.data, android.DataPath{SrcPath: d}) 667 } 668 669 var configs []tradefed.Config 670 if Bool(benchmark.Properties.Require_root) { 671 configs = append(configs, tradefed.Object{"target_preparer", "com.android.tradefed.targetprep.RootTargetPreparer", nil}) 672 } 673 benchmark.testConfig = tradefed.AutoGenTestConfig(ctx, tradefed.AutoGenTestConfigOptions{ 674 TestConfigProp: benchmark.Properties.Test_config, 675 TestConfigTemplateProp: benchmark.Properties.Test_config_template, 676 TestSuites: benchmark.Properties.Test_suites, 677 Config: configs, 678 AutoGenConfig: benchmark.Properties.Auto_gen_config, 679 DeviceTemplate: "${NativeBenchmarkTestConfigTemplate}", 680 HostTemplate: "${NativeBenchmarkTestConfigTemplate}", 681 }) 682 683 benchmark.binaryDecorator.baseInstaller.dir = filepath.Join("benchmarktest", ctx.ModuleName()) 684 benchmark.binaryDecorator.baseInstaller.dir64 = filepath.Join("benchmarktest64", ctx.ModuleName()) 685 benchmark.binaryDecorator.baseInstaller.installTestData(ctx, benchmark.data) 686 benchmark.binaryDecorator.baseInstaller.install(ctx, file) 687} 688 689func (benchmark *benchmarkDecorator) moduleInfoJSON(ctx ModuleContext, moduleInfoJSON *android.ModuleInfoJSON) { 690 benchmark.binaryDecorator.moduleInfoJSON(ctx, moduleInfoJSON) 691 692 moduleInfoJSON.Class = []string{"NATIVE_TESTS"} 693 if len(benchmark.Properties.Test_suites) > 0 { 694 moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, benchmark.Properties.Test_suites...) 695 } else { 696 moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, "null-suite") 697 } 698 699 if android.PrefixInList(moduleInfoJSON.CompatibilitySuites, "mts-") && 700 !android.InList("mts", moduleInfoJSON.CompatibilitySuites) { 701 moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, "mts") 702 } 703 704 if benchmark.testConfig != nil { 705 if _, ok := benchmark.testConfig.(android.WritablePath); ok { 706 moduleInfoJSON.AutoTestConfig = []string{"true"} 707 } 708 moduleInfoJSON.TestConfig = []string{benchmark.testConfig.String()} 709 } 710} 711 712func (benchmark *benchmarkDecorator) testSuiteInfo(ctx ModuleContext) { 713 android.SetProvider(ctx, android.TestSuiteInfoProvider, android.TestSuiteInfo{ 714 TestSuites: benchmark.Properties.Test_suites, 715 }) 716} 717 718func NewBenchmark(hod android.HostOrDeviceSupported) *Module { 719 module, binary := newBinary(hod) 720 module.multilib = android.MultilibBoth 721 binary.baseInstaller = NewBaseInstaller("benchmarktest", "benchmarktest64", InstallInData) 722 723 benchmark := &benchmarkDecorator{ 724 binaryDecorator: binary, 725 } 726 module.linker = benchmark 727 module.installer = benchmark 728 return module 729} 730