1// 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 (
18	"android/soong/android"
19	"android/soong/tradefed"
20)
21
22type TestProperties struct {
23	// Disables the creation of a test-specific directory when used with
24	// relative_install_path. Useful if several tests need to be in the same
25	// directory, but test_per_src doesn't work.
26	No_named_install_directory *bool
27
28	// the name of the test configuration (for example "AndroidTest.xml") that should be
29	// installed with the module.
30	Test_config *string `android:"path,arch_variant"`
31
32	// the name of the test configuration template (for example "AndroidTestTemplate.xml") that
33	// should be installed with the module.
34	Test_config_template *string `android:"path,arch_variant"`
35
36	// list of compatibility suites (for example "cts", "vts") that the module should be
37	// installed into.
38	Test_suites []string `android:"arch_variant"`
39
40	// Flag to indicate whether or not to create test config automatically. If AndroidTest.xml
41	// doesn't exist next to the Android.bp, this attribute doesn't need to be set to true
42	// explicitly.
43	Auto_gen_config *bool
44}
45
46// A test module is a binary module with extra --test compiler flag
47// and different default installation directory.
48// In golang, inheriance is written as a component.
49type testDecorator struct {
50	*binaryDecorator
51	Properties TestProperties
52	testConfig android.Path
53}
54
55func (test *testDecorator) nativeCoverage() bool {
56	return true
57}
58
59func NewRustTest(hod android.HostOrDeviceSupported) (*Module, *testDecorator) {
60	// Build both 32 and 64 targets for device tests.
61	// Cannot build both for host tests yet if the test depends on
62	// something like proc-macro2 that cannot be built for both.
63	multilib := android.MultilibBoth
64	if hod != android.DeviceSupported && hod != android.HostAndDeviceSupported {
65		multilib = android.MultilibFirst
66	}
67	module := newModule(hod, multilib)
68
69	test := &testDecorator{
70		binaryDecorator: &binaryDecorator{
71			baseCompiler: NewBaseCompiler("nativetest", "nativetest64", InstallInData),
72		},
73	}
74
75	module.compiler = test
76	module.AddProperties(&test.Properties)
77	return module, test
78}
79
80func (test *testDecorator) compilerProps() []interface{} {
81	return append(test.binaryDecorator.compilerProps(), &test.Properties)
82}
83
84func (test *testDecorator) install(ctx ModuleContext, file android.Path) {
85	test.testConfig = tradefed.AutoGenRustTestConfig(ctx,
86		test.Properties.Test_config,
87		test.Properties.Test_config_template,
88		test.Properties.Test_suites,
89		nil,
90		test.Properties.Auto_gen_config)
91
92	// default relative install path is module name
93	if !Bool(test.Properties.No_named_install_directory) {
94		test.baseCompiler.relative = ctx.ModuleName()
95	} else if String(test.baseCompiler.Properties.Relative_install_path) == "" {
96		ctx.PropertyErrorf("no_named_install_directory", "Module install directory may only be disabled if relative_install_path is set")
97	}
98
99	test.binaryDecorator.install(ctx, file)
100}
101
102func (test *testDecorator) compilerFlags(ctx ModuleContext, flags Flags) Flags {
103	flags = test.binaryDecorator.compilerFlags(ctx, flags)
104	flags.RustFlags = append(flags.RustFlags, "--test")
105	return flags
106}
107
108func (test *testDecorator) autoDep() autoDep {
109	return rlibAutoDep
110}
111
112func init() {
113	// Rust tests are binary files built with --test.
114	android.RegisterModuleType("rust_test", RustTestFactory)
115	android.RegisterModuleType("rust_test_host", RustTestHostFactory)
116}
117
118func RustTestFactory() android.Module {
119	module, _ := NewRustTest(android.HostAndDeviceSupported)
120	return module.Init()
121}
122
123func RustTestHostFactory() android.Module {
124	module, _ := NewRustTest(android.HostSupported)
125	return module.Init()
126}
127