xref: /aosp_15_r20/build/soong/rust/test.go (revision 333d2b3687b3a337dbcca9d65000bca186795e39)
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