1*333d2b36SAndroid Build Coastguard Worker// Copyright 2019 The Android Open Source Project 2*333d2b36SAndroid Build Coastguard Worker// 3*333d2b36SAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License"); 4*333d2b36SAndroid Build Coastguard Worker// you may not use this file except in compliance with the License. 5*333d2b36SAndroid Build Coastguard Worker// You may obtain a copy of the License at 6*333d2b36SAndroid Build Coastguard Worker// 7*333d2b36SAndroid Build Coastguard Worker// http://www.apache.org/licenses/LICENSE-2.0 8*333d2b36SAndroid Build Coastguard Worker// 9*333d2b36SAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software 10*333d2b36SAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS, 11*333d2b36SAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*333d2b36SAndroid Build Coastguard Worker// See the License for the specific language governing permissions and 13*333d2b36SAndroid Build Coastguard Worker// limitations under the License. 14*333d2b36SAndroid Build Coastguard Worker 15*333d2b36SAndroid Build Coastguard Workerpackage rust 16*333d2b36SAndroid Build Coastguard Worker 17*333d2b36SAndroid Build Coastguard Workerimport ( 18*333d2b36SAndroid Build Coastguard Worker "path/filepath" 19*333d2b36SAndroid Build Coastguard Worker 20*333d2b36SAndroid Build Coastguard Worker "github.com/google/blueprint/proptools" 21*333d2b36SAndroid Build Coastguard Worker 22*333d2b36SAndroid Build Coastguard Worker "android/soong/android" 23*333d2b36SAndroid Build Coastguard Worker "android/soong/cc" 24*333d2b36SAndroid Build Coastguard Worker "android/soong/tradefed" 25*333d2b36SAndroid Build Coastguard Worker) 26*333d2b36SAndroid Build Coastguard Worker 27*333d2b36SAndroid Build Coastguard Workertype TestProperties struct { 28*333d2b36SAndroid Build Coastguard Worker // Disables the creation of a test-specific directory when used with 29*333d2b36SAndroid Build Coastguard Worker // relative_install_path. Useful if several tests need to be in the same 30*333d2b36SAndroid Build Coastguard Worker // directory. 31*333d2b36SAndroid Build Coastguard Worker No_named_install_directory *bool 32*333d2b36SAndroid Build Coastguard Worker 33*333d2b36SAndroid Build Coastguard Worker // the name of the test configuration (for example "AndroidTest.xml") that should be 34*333d2b36SAndroid Build Coastguard Worker // installed with the module. 35*333d2b36SAndroid Build Coastguard Worker Test_config *string `android:"path,arch_variant"` 36*333d2b36SAndroid Build Coastguard Worker 37*333d2b36SAndroid Build Coastguard Worker // the name of the test configuration template (for example "AndroidTestTemplate.xml") that 38*333d2b36SAndroid Build Coastguard Worker // should be installed with the module. 39*333d2b36SAndroid Build Coastguard Worker Test_config_template *string `android:"path,arch_variant"` 40*333d2b36SAndroid Build Coastguard Worker 41*333d2b36SAndroid Build Coastguard Worker // list of compatibility suites (for example "cts", "vts") that the module should be 42*333d2b36SAndroid Build Coastguard Worker // installed into. 43*333d2b36SAndroid Build Coastguard Worker Test_suites []string `android:"arch_variant"` 44*333d2b36SAndroid Build Coastguard Worker 45*333d2b36SAndroid Build Coastguard Worker // list of files or filegroup modules that provide data that should be installed alongside 46*333d2b36SAndroid Build Coastguard Worker // the test 47*333d2b36SAndroid Build Coastguard Worker Data []string `android:"path,arch_variant"` 48*333d2b36SAndroid Build Coastguard Worker 49*333d2b36SAndroid Build Coastguard Worker // Same as data, but will add dependencies on the device's 50*333d2b36SAndroid Build Coastguard Worker Device_common_data []string `android:"path_device_common"` 51*333d2b36SAndroid Build Coastguard Worker 52*333d2b36SAndroid Build Coastguard Worker // list of shared library modules that should be installed alongside the test 53*333d2b36SAndroid Build Coastguard Worker Data_libs []string `android:"arch_variant"` 54*333d2b36SAndroid Build Coastguard Worker 55*333d2b36SAndroid Build Coastguard Worker // list of binary modules that should be installed alongside the test 56*333d2b36SAndroid Build Coastguard Worker Data_bins []string `android:"arch_variant"` 57*333d2b36SAndroid Build Coastguard Worker 58*333d2b36SAndroid Build Coastguard Worker // Flag to indicate whether or not to create test config automatically. If AndroidTest.xml 59*333d2b36SAndroid Build Coastguard Worker // doesn't exist next to the Android.bp, this attribute doesn't need to be set to true 60*333d2b36SAndroid Build Coastguard Worker // explicitly. 61*333d2b36SAndroid Build Coastguard Worker Auto_gen_config *bool 62*333d2b36SAndroid Build Coastguard Worker 63*333d2b36SAndroid Build Coastguard Worker // if set, build with the standard Rust test harness. Defaults to true. 64*333d2b36SAndroid Build Coastguard Worker Test_harness *bool 65*333d2b36SAndroid Build Coastguard Worker 66*333d2b36SAndroid Build Coastguard Worker // Test options. 67*333d2b36SAndroid Build Coastguard Worker Test_options android.CommonTestOptions 68*333d2b36SAndroid Build Coastguard Worker 69*333d2b36SAndroid Build Coastguard Worker // Add RootTargetPreparer to auto generated test config. This guarantees the test to run 70*333d2b36SAndroid Build Coastguard Worker // with root permission. 71*333d2b36SAndroid Build Coastguard Worker Require_root *bool 72*333d2b36SAndroid Build Coastguard Worker} 73*333d2b36SAndroid Build Coastguard Worker 74*333d2b36SAndroid Build Coastguard Worker// A test module is a binary module with extra --test compiler flag 75*333d2b36SAndroid Build Coastguard Worker// and different default installation directory. 76*333d2b36SAndroid Build Coastguard Worker// In golang, inheriance is written as a component. 77*333d2b36SAndroid Build Coastguard Workertype testDecorator struct { 78*333d2b36SAndroid Build Coastguard Worker *binaryDecorator 79*333d2b36SAndroid Build Coastguard Worker Properties TestProperties 80*333d2b36SAndroid Build Coastguard Worker testConfig android.Path 81*333d2b36SAndroid Build Coastguard Worker 82*333d2b36SAndroid Build Coastguard Worker data []android.DataPath 83*333d2b36SAndroid Build Coastguard Worker} 84*333d2b36SAndroid Build Coastguard Worker 85*333d2b36SAndroid Build Coastguard Workerfunc (test *testDecorator) dataPaths() []android.DataPath { 86*333d2b36SAndroid Build Coastguard Worker return test.data 87*333d2b36SAndroid Build Coastguard Worker} 88*333d2b36SAndroid Build Coastguard Worker 89*333d2b36SAndroid Build Coastguard Workerfunc (test *testDecorator) nativeCoverage() bool { 90*333d2b36SAndroid Build Coastguard Worker return true 91*333d2b36SAndroid Build Coastguard Worker} 92*333d2b36SAndroid Build Coastguard Worker 93*333d2b36SAndroid Build Coastguard Workerfunc (test *testDecorator) testHarness() bool { 94*333d2b36SAndroid Build Coastguard Worker return BoolDefault(test.Properties.Test_harness, true) 95*333d2b36SAndroid Build Coastguard Worker} 96*333d2b36SAndroid Build Coastguard Worker 97*333d2b36SAndroid Build Coastguard Workerfunc NewRustTest(hod android.HostOrDeviceSupported) (*Module, *testDecorator) { 98*333d2b36SAndroid Build Coastguard Worker // Build both 32 and 64 targets for device tests. 99*333d2b36SAndroid Build Coastguard Worker // Cannot build both for host tests yet if the test depends on 100*333d2b36SAndroid Build Coastguard Worker // something like proc-macro2 that cannot be built for both. 101*333d2b36SAndroid Build Coastguard Worker multilib := android.MultilibBoth 102*333d2b36SAndroid Build Coastguard Worker if hod != android.DeviceSupported && hod != android.HostAndDeviceSupported { 103*333d2b36SAndroid Build Coastguard Worker multilib = android.MultilibFirst 104*333d2b36SAndroid Build Coastguard Worker } 105*333d2b36SAndroid Build Coastguard Worker module := newModule(hod, multilib) 106*333d2b36SAndroid Build Coastguard Worker 107*333d2b36SAndroid Build Coastguard Worker test := &testDecorator{ 108*333d2b36SAndroid Build Coastguard Worker binaryDecorator: &binaryDecorator{ 109*333d2b36SAndroid Build Coastguard Worker baseCompiler: NewBaseCompiler("nativetest", "nativetest64", InstallInData), 110*333d2b36SAndroid Build Coastguard Worker }, 111*333d2b36SAndroid Build Coastguard Worker } 112*333d2b36SAndroid Build Coastguard Worker 113*333d2b36SAndroid Build Coastguard Worker module.compiler = test 114*333d2b36SAndroid Build Coastguard Worker return module, test 115*333d2b36SAndroid Build Coastguard Worker} 116*333d2b36SAndroid Build Coastguard Worker 117*333d2b36SAndroid Build Coastguard Workerfunc (test *testDecorator) compilerProps() []interface{} { 118*333d2b36SAndroid Build Coastguard Worker return append(test.binaryDecorator.compilerProps(), &test.Properties) 119*333d2b36SAndroid Build Coastguard Worker} 120*333d2b36SAndroid Build Coastguard Worker 121*333d2b36SAndroid Build Coastguard Workerfunc (test *testDecorator) install(ctx ModuleContext) { 122*333d2b36SAndroid Build Coastguard Worker // TODO: (b/167308193) Switch to /data/local/tests/unrestricted as the default install base. 123*333d2b36SAndroid Build Coastguard Worker testInstallBase := "/data/local/tmp" 124*333d2b36SAndroid Build Coastguard Worker if ctx.RustModule().InVendorOrProduct() { 125*333d2b36SAndroid Build Coastguard Worker testInstallBase = "/data/local/tests/vendor" 126*333d2b36SAndroid Build Coastguard Worker } 127*333d2b36SAndroid Build Coastguard Worker 128*333d2b36SAndroid Build Coastguard Worker var configs []tradefed.Config 129*333d2b36SAndroid Build Coastguard Worker if Bool(test.Properties.Require_root) { 130*333d2b36SAndroid Build Coastguard Worker configs = append(configs, tradefed.Object{"target_preparer", "com.android.tradefed.targetprep.RootTargetPreparer", nil}) 131*333d2b36SAndroid Build Coastguard Worker } else { 132*333d2b36SAndroid Build Coastguard Worker var options []tradefed.Option 133*333d2b36SAndroid Build Coastguard Worker options = append(options, tradefed.Option{Name: "force-root", Value: "false"}) 134*333d2b36SAndroid Build Coastguard Worker configs = append(configs, tradefed.Object{"target_preparer", "com.android.tradefed.targetprep.RootTargetPreparer", options}) 135*333d2b36SAndroid Build Coastguard Worker } 136*333d2b36SAndroid Build Coastguard Worker 137*333d2b36SAndroid Build Coastguard Worker test.testConfig = tradefed.AutoGenTestConfig(ctx, tradefed.AutoGenTestConfigOptions{ 138*333d2b36SAndroid Build Coastguard Worker TestConfigProp: test.Properties.Test_config, 139*333d2b36SAndroid Build Coastguard Worker TestConfigTemplateProp: test.Properties.Test_config_template, 140*333d2b36SAndroid Build Coastguard Worker TestSuites: test.Properties.Test_suites, 141*333d2b36SAndroid Build Coastguard Worker Config: configs, 142*333d2b36SAndroid Build Coastguard Worker AutoGenConfig: test.Properties.Auto_gen_config, 143*333d2b36SAndroid Build Coastguard Worker TestInstallBase: testInstallBase, 144*333d2b36SAndroid Build Coastguard Worker DeviceTemplate: "${RustDeviceTestConfigTemplate}", 145*333d2b36SAndroid Build Coastguard Worker HostTemplate: "${RustHostTestConfigTemplate}", 146*333d2b36SAndroid Build Coastguard Worker }) 147*333d2b36SAndroid Build Coastguard Worker 148*333d2b36SAndroid Build Coastguard Worker dataSrcPaths := android.PathsForModuleSrc(ctx, test.Properties.Data) 149*333d2b36SAndroid Build Coastguard Worker dataSrcPaths = append(dataSrcPaths, android.PathsForModuleSrc(ctx, test.Properties.Device_common_data)...) 150*333d2b36SAndroid Build Coastguard Worker 151*333d2b36SAndroid Build Coastguard Worker ctx.VisitDirectDepsWithTag(dataLibDepTag, func(dep android.Module) { 152*333d2b36SAndroid Build Coastguard Worker depName := ctx.OtherModuleName(dep) 153*333d2b36SAndroid Build Coastguard Worker linkableDep, ok := dep.(cc.LinkableInterface) 154*333d2b36SAndroid Build Coastguard Worker if !ok { 155*333d2b36SAndroid Build Coastguard Worker ctx.ModuleErrorf("data_lib %q is not a linkable module", depName) 156*333d2b36SAndroid Build Coastguard Worker } 157*333d2b36SAndroid Build Coastguard Worker if linkableDep.OutputFile().Valid() { 158*333d2b36SAndroid Build Coastguard Worker // Copy the output in "lib[64]" so that it's compatible with 159*333d2b36SAndroid Build Coastguard Worker // the default rpath values. 160*333d2b36SAndroid Build Coastguard Worker libDir := "lib" 161*333d2b36SAndroid Build Coastguard Worker if linkableDep.Target().Arch.ArchType.Multilib == "lib64" { 162*333d2b36SAndroid Build Coastguard Worker libDir = "lib64" 163*333d2b36SAndroid Build Coastguard Worker } 164*333d2b36SAndroid Build Coastguard Worker test.data = append(test.data, 165*333d2b36SAndroid Build Coastguard Worker android.DataPath{SrcPath: linkableDep.OutputFile().Path(), 166*333d2b36SAndroid Build Coastguard Worker RelativeInstallPath: filepath.Join(libDir, linkableDep.RelativeInstallPath())}) 167*333d2b36SAndroid Build Coastguard Worker } 168*333d2b36SAndroid Build Coastguard Worker }) 169*333d2b36SAndroid Build Coastguard Worker 170*333d2b36SAndroid Build Coastguard Worker ctx.VisitDirectDepsWithTag(dataBinDepTag, func(dep android.Module) { 171*333d2b36SAndroid Build Coastguard Worker depName := ctx.OtherModuleName(dep) 172*333d2b36SAndroid Build Coastguard Worker linkableDep, ok := dep.(cc.LinkableInterface) 173*333d2b36SAndroid Build Coastguard Worker if !ok { 174*333d2b36SAndroid Build Coastguard Worker ctx.ModuleErrorf("data_bin %q is not a linkable module", depName) 175*333d2b36SAndroid Build Coastguard Worker } 176*333d2b36SAndroid Build Coastguard Worker if linkableDep.OutputFile().Valid() { 177*333d2b36SAndroid Build Coastguard Worker test.data = append(test.data, 178*333d2b36SAndroid Build Coastguard Worker android.DataPath{SrcPath: linkableDep.OutputFile().Path(), 179*333d2b36SAndroid Build Coastguard Worker RelativeInstallPath: linkableDep.RelativeInstallPath()}) 180*333d2b36SAndroid Build Coastguard Worker } 181*333d2b36SAndroid Build Coastguard Worker }) 182*333d2b36SAndroid Build Coastguard Worker 183*333d2b36SAndroid Build Coastguard Worker for _, dataSrcPath := range dataSrcPaths { 184*333d2b36SAndroid Build Coastguard Worker test.data = append(test.data, android.DataPath{SrcPath: dataSrcPath}) 185*333d2b36SAndroid Build Coastguard Worker } 186*333d2b36SAndroid Build Coastguard Worker 187*333d2b36SAndroid Build Coastguard Worker // default relative install path is module name 188*333d2b36SAndroid Build Coastguard Worker if !Bool(test.Properties.No_named_install_directory) { 189*333d2b36SAndroid Build Coastguard Worker test.baseCompiler.relative = ctx.ModuleName() 190*333d2b36SAndroid Build Coastguard Worker } else if String(test.baseCompiler.Properties.Relative_install_path) == "" { 191*333d2b36SAndroid Build Coastguard Worker ctx.PropertyErrorf("no_named_install_directory", "Module install directory may only be disabled if relative_install_path is set") 192*333d2b36SAndroid Build Coastguard Worker } 193*333d2b36SAndroid Build Coastguard Worker 194*333d2b36SAndroid Build Coastguard Worker if ctx.Host() && test.Properties.Test_options.Unit_test == nil { 195*333d2b36SAndroid Build Coastguard Worker test.Properties.Test_options.Unit_test = proptools.BoolPtr(true) 196*333d2b36SAndroid Build Coastguard Worker } 197*333d2b36SAndroid Build Coastguard Worker test.binaryDecorator.installTestData(ctx, test.data) 198*333d2b36SAndroid Build Coastguard Worker test.binaryDecorator.install(ctx) 199*333d2b36SAndroid Build Coastguard Worker} 200*333d2b36SAndroid Build Coastguard Worker 201*333d2b36SAndroid Build Coastguard Workerfunc (test *testDecorator) compilerFlags(ctx ModuleContext, flags Flags) Flags { 202*333d2b36SAndroid Build Coastguard Worker flags = test.binaryDecorator.compilerFlags(ctx, flags) 203*333d2b36SAndroid Build Coastguard Worker if test.testHarness() { 204*333d2b36SAndroid Build Coastguard Worker flags.RustFlags = append(flags.RustFlags, "--test") 205*333d2b36SAndroid Build Coastguard Worker } 206*333d2b36SAndroid Build Coastguard Worker if ctx.Device() { 207*333d2b36SAndroid Build Coastguard Worker flags.RustFlags = append(flags.RustFlags, "-Z panic_abort_tests") 208*333d2b36SAndroid Build Coastguard Worker } 209*333d2b36SAndroid Build Coastguard Worker 210*333d2b36SAndroid Build Coastguard Worker return flags 211*333d2b36SAndroid Build Coastguard Worker} 212*333d2b36SAndroid Build Coastguard Worker 213*333d2b36SAndroid Build Coastguard Workerfunc (test *testDecorator) autoDep(ctx android.BottomUpMutatorContext) autoDep { 214*333d2b36SAndroid Build Coastguard Worker return rlibAutoDep 215*333d2b36SAndroid Build Coastguard Worker} 216*333d2b36SAndroid Build Coastguard Worker 217*333d2b36SAndroid Build Coastguard Workerfunc init() { 218*333d2b36SAndroid Build Coastguard Worker // Rust tests are binary files built with --test. 219*333d2b36SAndroid Build Coastguard Worker android.RegisterModuleType("rust_test", RustTestFactory) 220*333d2b36SAndroid Build Coastguard Worker android.RegisterModuleType("rust_test_host", RustTestHostFactory) 221*333d2b36SAndroid Build Coastguard Worker} 222*333d2b36SAndroid Build Coastguard Worker 223*333d2b36SAndroid Build Coastguard Workerfunc RustTestFactory() android.Module { 224*333d2b36SAndroid Build Coastguard Worker module, _ := NewRustTest(android.HostAndDeviceSupported) 225*333d2b36SAndroid Build Coastguard Worker 226*333d2b36SAndroid Build Coastguard Worker // NewRustTest will set MultilibBoth true, however the host variant 227*333d2b36SAndroid Build Coastguard Worker // cannot produce the non-primary target. Therefore, add the 228*333d2b36SAndroid Build Coastguard Worker // rustTestHostMultilib load hook to set MultilibFirst for the 229*333d2b36SAndroid Build Coastguard Worker // host target. 230*333d2b36SAndroid Build Coastguard Worker android.AddLoadHook(module, rustTestHostMultilib) 231*333d2b36SAndroid Build Coastguard Worker module.testModule = true 232*333d2b36SAndroid Build Coastguard Worker return module.Init() 233*333d2b36SAndroid Build Coastguard Worker} 234*333d2b36SAndroid Build Coastguard Worker 235*333d2b36SAndroid Build Coastguard Workerfunc RustTestHostFactory() android.Module { 236*333d2b36SAndroid Build Coastguard Worker module, _ := NewRustTest(android.HostSupported) 237*333d2b36SAndroid Build Coastguard Worker module.testModule = true 238*333d2b36SAndroid Build Coastguard Worker return module.Init() 239*333d2b36SAndroid Build Coastguard Worker} 240*333d2b36SAndroid Build Coastguard Worker 241*333d2b36SAndroid Build Coastguard Workerfunc (test *testDecorator) stdLinkage(ctx *depsContext) RustLinkage { 242*333d2b36SAndroid Build Coastguard Worker return RlibLinkage 243*333d2b36SAndroid Build Coastguard Worker} 244*333d2b36SAndroid Build Coastguard Worker 245*333d2b36SAndroid Build Coastguard Workerfunc (test *testDecorator) compilerDeps(ctx DepsContext, deps Deps) Deps { 246*333d2b36SAndroid Build Coastguard Worker deps = test.binaryDecorator.compilerDeps(ctx, deps) 247*333d2b36SAndroid Build Coastguard Worker 248*333d2b36SAndroid Build Coastguard Worker deps.Rustlibs = append(deps.Rustlibs, "libtest") 249*333d2b36SAndroid Build Coastguard Worker 250*333d2b36SAndroid Build Coastguard Worker deps.DataLibs = append(deps.DataLibs, test.Properties.Data_libs...) 251*333d2b36SAndroid Build Coastguard Worker deps.DataBins = append(deps.DataBins, test.Properties.Data_bins...) 252*333d2b36SAndroid Build Coastguard Worker 253*333d2b36SAndroid Build Coastguard Worker return deps 254*333d2b36SAndroid Build Coastguard Worker} 255*333d2b36SAndroid Build Coastguard Worker 256*333d2b36SAndroid Build Coastguard Workerfunc (test *testDecorator) testBinary() bool { 257*333d2b36SAndroid Build Coastguard Worker return true 258*333d2b36SAndroid Build Coastguard Worker} 259*333d2b36SAndroid Build Coastguard Worker 260*333d2b36SAndroid Build Coastguard Workerfunc rustTestHostMultilib(ctx android.LoadHookContext) { 261*333d2b36SAndroid Build Coastguard Worker type props struct { 262*333d2b36SAndroid Build Coastguard Worker Target struct { 263*333d2b36SAndroid Build Coastguard Worker Host struct { 264*333d2b36SAndroid Build Coastguard Worker Compile_multilib *string 265*333d2b36SAndroid Build Coastguard Worker } 266*333d2b36SAndroid Build Coastguard Worker } 267*333d2b36SAndroid Build Coastguard Worker } 268*333d2b36SAndroid Build Coastguard Worker p := &props{} 269*333d2b36SAndroid Build Coastguard Worker p.Target.Host.Compile_multilib = proptools.StringPtr("first") 270*333d2b36SAndroid Build Coastguard Worker ctx.AppendProperties(p) 271*333d2b36SAndroid Build Coastguard Worker} 272