blob: b7ddd06a3ae582ddc82140c87f0afb94e500697f [file] [log] [blame]
Chih-Hung Hsieha5f22ed2019-10-24 20:47:54 -07001// Copyright 2019 The Android Open Source Project
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 rust
16
17import (
Jooyung Han10bea7d2022-04-29 02:04:30 +090018 "path/filepath"
19
Julien Desprez84c94942021-01-15 15:10:01 -080020 "github.com/google/blueprint/proptools"
21
Chih-Hung Hsieha5f22ed2019-10-24 20:47:54 -070022 "android/soong/android"
Ivan Lozano4e5f07d2021-11-04 14:09:38 -040023 "android/soong/cc"
Chih-Hung Hsieh41805be2019-10-31 20:56:47 -070024 "android/soong/tradefed"
Chih-Hung Hsieha5f22ed2019-10-24 20:47:54 -070025)
26
Chih-Hung Hsieh41805be2019-10-31 20:56:47 -070027type TestProperties struct {
Ivan Lozanofc80fe72020-06-11 13:25:36 -040028 // Disables the creation of a test-specific directory when used with
29 // relative_install_path. Useful if several tests need to be in the same
Colin Cross3a02c7b2024-05-21 13:46:22 -070030 // directory.
Ivan Lozanofc80fe72020-06-11 13:25:36 -040031 No_named_install_directory *bool
32
Chih-Hung Hsieh41805be2019-10-31 20:56:47 -070033 // the name of the test configuration (for example "AndroidTest.xml") that should be
34 // installed with the module.
Colin Crossa6384822020-06-09 15:09:22 -070035 Test_config *string `android:"path,arch_variant"`
Chih-Hung Hsieh41805be2019-10-31 20:56:47 -070036
37 // the name of the test configuration template (for example "AndroidTestTemplate.xml") that
38 // should be installed with the module.
Colin Crossa6384822020-06-09 15:09:22 -070039 Test_config_template *string `android:"path,arch_variant"`
Chih-Hung Hsieh41805be2019-10-31 20:56:47 -070040
41 // list of compatibility suites (for example "cts", "vts") that the module should be
42 // installed into.
43 Test_suites []string `android:"arch_variant"`
44
Ivan Lozano9da4aa82021-01-29 12:48:05 -050045 // list of files or filegroup modules that provide data that should be installed alongside
46 // the test
47 Data []string `android:"path,arch_variant"`
48
Ivan Lozano4e5f07d2021-11-04 14:09:38 -040049 // list of shared library modules that should be installed alongside the test
50 Data_libs []string `android:"arch_variant"`
51
52 // list of binary modules that should be installed alongside the test
53 Data_bins []string `android:"arch_variant"`
54
Chih-Hung Hsieh41805be2019-10-31 20:56:47 -070055 // Flag to indicate whether or not to create test config automatically. If AndroidTest.xml
56 // doesn't exist next to the Android.bp, this attribute doesn't need to be set to true
57 // explicitly.
58 Auto_gen_config *bool
Stephen Crane02a623d2020-04-25 21:40:35 -070059
60 // if set, build with the standard Rust test harness. Defaults to true.
61 Test_harness *bool
Dan Shid79572f2020-11-13 14:33:46 -080062
63 // Test options.
Zhenhuang Wang0ac5a432022-08-12 18:49:20 +080064 Test_options android.CommonTestOptions
Ivan Lozanoba222612021-09-21 10:49:13 -040065
66 // Add RootTargetPreparer to auto generated test config. This guarantees the test to run
67 // with root permission.
68 Require_root *bool
Chih-Hung Hsieh41805be2019-10-31 20:56:47 -070069}
70
Chih-Hung Hsieha5f22ed2019-10-24 20:47:54 -070071// A test module is a binary module with extra --test compiler flag
72// and different default installation directory.
73// In golang, inheriance is written as a component.
Chih-Hung Hsieh41805be2019-10-31 20:56:47 -070074type testDecorator struct {
Chih-Hung Hsieha5f22ed2019-10-24 20:47:54 -070075 *binaryDecorator
Chih-Hung Hsieh41805be2019-10-31 20:56:47 -070076 Properties TestProperties
77 testConfig android.Path
Ivan Lozano9da4aa82021-01-29 12:48:05 -050078
79 data []android.DataPath
80}
81
82func (test *testDecorator) dataPaths() []android.DataPath {
83 return test.data
Chih-Hung Hsieha5f22ed2019-10-24 20:47:54 -070084}
85
Ivan Lozanoa0cd8f92020-04-09 09:56:02 -040086func (test *testDecorator) nativeCoverage() bool {
87 return true
88}
89
Stephen Crane02a623d2020-04-25 21:40:35 -070090func (test *testDecorator) testHarness() bool {
91 return BoolDefault(test.Properties.Test_harness, true)
92}
93
Chih-Hung Hsieh41805be2019-10-31 20:56:47 -070094func NewRustTest(hod android.HostOrDeviceSupported) (*Module, *testDecorator) {
Chih-Hung Hsiehe728a892020-06-16 01:25:27 -070095 // Build both 32 and 64 targets for device tests.
96 // Cannot build both for host tests yet if the test depends on
97 // something like proc-macro2 that cannot be built for both.
98 multilib := android.MultilibBoth
99 if hod != android.DeviceSupported && hod != android.HostAndDeviceSupported {
100 multilib = android.MultilibFirst
101 }
102 module := newModule(hod, multilib)
Chih-Hung Hsieha5f22ed2019-10-24 20:47:54 -0700103
Chih-Hung Hsieh41805be2019-10-31 20:56:47 -0700104 test := &testDecorator{
Chih-Hung Hsieha5f22ed2019-10-24 20:47:54 -0700105 binaryDecorator: &binaryDecorator{
Chih-Hung Hsieh9a4a7ba2019-12-12 19:36:05 -0800106 baseCompiler: NewBaseCompiler("nativetest", "nativetest64", InstallInData),
Chih-Hung Hsieha5f22ed2019-10-24 20:47:54 -0700107 },
108 }
109
110 module.compiler = test
Chih-Hung Hsieha5f22ed2019-10-24 20:47:54 -0700111 return module, test
112}
113
Chih-Hung Hsieh41805be2019-10-31 20:56:47 -0700114func (test *testDecorator) compilerProps() []interface{} {
115 return append(test.binaryDecorator.compilerProps(), &test.Properties)
116}
117
ThiƩbaud Weksteenfabaff62020-08-27 13:48:36 +0200118func (test *testDecorator) install(ctx ModuleContext) {
Nikita Putikhin5f23bc92024-07-05 15:08:01 +0200119 // TODO: (b/167308193) Switch to /data/local/tests/unrestricted as the default install base.
120 testInstallBase := "/data/local/tmp"
Kiyoung Kimaa394802024-01-08 12:55:45 +0900121 if ctx.RustModule().InVendorOrProduct() {
Ivan Lozanoba222612021-09-21 10:49:13 -0400122 testInstallBase = "/data/local/tests/vendor"
123 }
124
125 var configs []tradefed.Config
126 if Bool(test.Properties.Require_root) {
127 configs = append(configs, tradefed.Object{"target_preparer", "com.android.tradefed.targetprep.RootTargetPreparer", nil})
128 } else {
129 var options []tradefed.Option
130 options = append(options, tradefed.Option{Name: "force-root", Value: "false"})
131 configs = append(configs, tradefed.Object{"target_preparer", "com.android.tradefed.targetprep.RootTargetPreparer", options})
132 }
133
Cole Faust21680542022-12-07 18:18:37 -0800134 test.testConfig = tradefed.AutoGenTestConfig(ctx, tradefed.AutoGenTestConfigOptions{
135 TestConfigProp: test.Properties.Test_config,
136 TestConfigTemplateProp: test.Properties.Test_config_template,
137 TestSuites: test.Properties.Test_suites,
138 Config: configs,
139 AutoGenConfig: test.Properties.Auto_gen_config,
140 TestInstallBase: testInstallBase,
141 DeviceTemplate: "${RustDeviceTestConfigTemplate}",
142 HostTemplate: "${RustHostTestConfigTemplate}",
143 })
Ivan Lozanofc80fe72020-06-11 13:25:36 -0400144
Ivan Lozano9da4aa82021-01-29 12:48:05 -0500145 dataSrcPaths := android.PathsForModuleSrc(ctx, test.Properties.Data)
146
Ivan Lozano4e5f07d2021-11-04 14:09:38 -0400147 ctx.VisitDirectDepsWithTag(dataLibDepTag, func(dep android.Module) {
148 depName := ctx.OtherModuleName(dep)
149 linkableDep, ok := dep.(cc.LinkableInterface)
150 if !ok {
151 ctx.ModuleErrorf("data_lib %q is not a linkable module", depName)
152 }
153 if linkableDep.OutputFile().Valid() {
Jooyung Han10bea7d2022-04-29 02:04:30 +0900154 // Copy the output in "lib[64]" so that it's compatible with
155 // the default rpath values.
156 libDir := "lib"
157 if linkableDep.Target().Arch.ArchType.Multilib == "lib64" {
158 libDir = "lib64"
159 }
Ivan Lozano4e5f07d2021-11-04 14:09:38 -0400160 test.data = append(test.data,
161 android.DataPath{SrcPath: linkableDep.OutputFile().Path(),
Jooyung Han10bea7d2022-04-29 02:04:30 +0900162 RelativeInstallPath: filepath.Join(libDir, linkableDep.RelativeInstallPath())})
Ivan Lozano4e5f07d2021-11-04 14:09:38 -0400163 }
164 })
165
166 ctx.VisitDirectDepsWithTag(dataBinDepTag, func(dep android.Module) {
167 depName := ctx.OtherModuleName(dep)
168 linkableDep, ok := dep.(cc.LinkableInterface)
169 if !ok {
170 ctx.ModuleErrorf("data_bin %q is not a linkable module", depName)
171 }
172 if linkableDep.OutputFile().Valid() {
173 test.data = append(test.data,
174 android.DataPath{SrcPath: linkableDep.OutputFile().Path(),
175 RelativeInstallPath: linkableDep.RelativeInstallPath()})
176 }
177 })
178
Ivan Lozano9da4aa82021-01-29 12:48:05 -0500179 for _, dataSrcPath := range dataSrcPaths {
180 test.data = append(test.data, android.DataPath{SrcPath: dataSrcPath})
181 }
182
Chih-Hung Hsieh9a4a7ba2019-12-12 19:36:05 -0800183 // default relative install path is module name
Ivan Lozanofc80fe72020-06-11 13:25:36 -0400184 if !Bool(test.Properties.No_named_install_directory) {
Chih-Hung Hsieh9a4a7ba2019-12-12 19:36:05 -0800185 test.baseCompiler.relative = ctx.ModuleName()
Ivan Lozanofc80fe72020-06-11 13:25:36 -0400186 } else if String(test.baseCompiler.Properties.Relative_install_path) == "" {
187 ctx.PropertyErrorf("no_named_install_directory", "Module install directory may only be disabled if relative_install_path is set")
Chih-Hung Hsieh9a4a7ba2019-12-12 19:36:05 -0800188 }
Ivan Lozanofc80fe72020-06-11 13:25:36 -0400189
Julien Desprez84c94942021-01-15 15:10:01 -0800190 if ctx.Host() && test.Properties.Test_options.Unit_test == nil {
191 test.Properties.Test_options.Unit_test = proptools.BoolPtr(true)
192 }
Colin Cross5c1d5fb2023-11-15 12:39:40 -0800193 test.binaryDecorator.installTestData(ctx, test.data)
ThiƩbaud Weksteenfabaff62020-08-27 13:48:36 +0200194 test.binaryDecorator.install(ctx)
Chih-Hung Hsieh41805be2019-10-31 20:56:47 -0700195}
196
197func (test *testDecorator) compilerFlags(ctx ModuleContext, flags Flags) Flags {
Chih-Hung Hsieha5f22ed2019-10-24 20:47:54 -0700198 flags = test.binaryDecorator.compilerFlags(ctx, flags)
Stephen Crane02a623d2020-04-25 21:40:35 -0700199 if test.testHarness() {
200 flags.RustFlags = append(flags.RustFlags, "--test")
201 }
Jeff Vander Stoepbf7a9022021-01-26 14:35:38 +0100202 if ctx.Device() {
203 flags.RustFlags = append(flags.RustFlags, "-Z panic_abort_tests")
204 }
Colin Cross225a37a2023-01-11 14:17:39 -0800205
Chih-Hung Hsieha5f22ed2019-10-24 20:47:54 -0700206 return flags
207}
208
Liz Kammer356f7d42021-01-26 09:18:53 -0500209func (test *testDecorator) autoDep(ctx android.BottomUpMutatorContext) autoDep {
Matthew Maurer0f003b12020-06-29 14:34:06 -0700210 return rlibAutoDep
211}
212
Chih-Hung Hsieha5f22ed2019-10-24 20:47:54 -0700213func init() {
214 // Rust tests are binary files built with --test.
215 android.RegisterModuleType("rust_test", RustTestFactory)
216 android.RegisterModuleType("rust_test_host", RustTestHostFactory)
217}
218
219func RustTestFactory() android.Module {
220 module, _ := NewRustTest(android.HostAndDeviceSupported)
Ivan Lozanof5c98a22021-12-07 10:17:00 -0500221
222 // NewRustTest will set MultilibBoth true, however the host variant
223 // cannot produce the non-primary target. Therefore, add the
224 // rustTestHostMultilib load hook to set MultilibFirst for the
225 // host target.
226 android.AddLoadHook(module, rustTestHostMultilib)
Aditya Choudhary87b2ab22023-11-17 15:27:06 +0000227 module.testModule = true
Chih-Hung Hsieha5f22ed2019-10-24 20:47:54 -0700228 return module.Init()
229}
230
231func RustTestHostFactory() android.Module {
232 module, _ := NewRustTest(android.HostSupported)
Aditya Choudhary87b2ab22023-11-17 15:27:06 +0000233 module.testModule = true
Chih-Hung Hsieha5f22ed2019-10-24 20:47:54 -0700234 return module.Init()
235}
Ivan Lozano2b081132020-09-08 12:46:52 -0400236
Ivan Lozanodd055472020-09-28 13:22:45 -0400237func (test *testDecorator) stdLinkage(ctx *depsContext) RustLinkage {
238 return RlibLinkage
Ivan Lozano2b081132020-09-08 12:46:52 -0400239}
Ivan Lozano3ee74c82021-07-15 15:44:10 -0400240
241func (test *testDecorator) compilerDeps(ctx DepsContext, deps Deps) Deps {
242 deps = test.binaryDecorator.compilerDeps(ctx, deps)
243
244 deps.Rustlibs = append(deps.Rustlibs, "libtest")
245
Ivan Lozano4e5f07d2021-11-04 14:09:38 -0400246 deps.DataLibs = append(deps.DataLibs, test.Properties.Data_libs...)
247 deps.DataBins = append(deps.DataBins, test.Properties.Data_bins...)
248
Ivan Lozano3ee74c82021-07-15 15:44:10 -0400249 return deps
250}
Ivan Lozano62cd0382021-11-01 10:27:54 -0400251
252func (test *testDecorator) testBinary() bool {
253 return true
254}
Ivan Lozanof5c98a22021-12-07 10:17:00 -0500255
256func rustTestHostMultilib(ctx android.LoadHookContext) {
257 type props struct {
258 Target struct {
259 Host struct {
260 Compile_multilib *string
261 }
262 }
263 }
264 p := &props{}
265 p.Target.Host.Compile_multilib = proptools.StringPtr("first")
266 ctx.AppendProperties(p)
267}