• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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	"strings"
21
22	"github.com/google/blueprint/proptools"
23
24	"android/soong/android"
25	"android/soong/bazel"
26	"android/soong/bazel/cquery"
27	"android/soong/tradefed"
28)
29
30// TestLinkerProperties properties to be registered via the linker
31type TestLinkerProperties struct {
32	// if set, build against the gtest library. Defaults to true.
33	Gtest *bool
34
35	// if set, use the isolated gtest runner. Defaults to true if gtest is also true and the arch is Windows, false
36	// otherwise.
37	Isolated *bool
38}
39
40// TestInstallerProperties properties to be registered via the installer
41type TestInstallerProperties struct {
42	// list of compatibility suites (for example "cts", "vts") that the module should be installed into.
43	Test_suites []string `android:"arch_variant"`
44}
45
46// Test option struct.
47type TestOptions struct {
48	android.CommonTestOptions
49
50	// The UID that you want to run the test as on a device.
51	Run_test_as *string
52
53	// A list of free-formed strings without spaces that categorize the test.
54	Test_suite_tag []string
55
56	// a list of extra test configuration files that should be installed with the module.
57	Extra_test_configs []string `android:"path,arch_variant"`
58
59	// Add ShippingApiLevelModuleController to auto generated test config. If the device properties
60	// for the shipping api level is less than the min_shipping_api_level, skip this module.
61	Min_shipping_api_level *int64
62
63	// Add ShippingApiLevelModuleController to auto generated test config. If any of the device
64	// shipping api level and vendor api level properties are less than the
65	// vsr_min_shipping_api_level, skip this module.
66	// As this includes the shipping api level check, it is not allowed to define
67	// min_shipping_api_level at the same time with this property.
68	Vsr_min_shipping_api_level *int64
69
70	// Add MinApiLevelModuleController with ro.vndk.version property. If ro.vndk.version has an
71	// integer value and the value is less than the min_vndk_version, skip this module.
72	Min_vndk_version *int64
73}
74
75type TestBinaryProperties struct {
76	// Create a separate binary for each source file.  Useful when there is
77	// global state that can not be torn down and reset between each test suite.
78	Test_per_src *bool
79
80	// Disables the creation of a test-specific directory when used with
81	// relative_install_path. Useful if several tests need to be in the same
82	// directory, but test_per_src doesn't work.
83	No_named_install_directory *bool
84
85	// list of files or filegroup modules that provide data that should be installed alongside
86	// the test
87	Data []string `android:"path,arch_variant"`
88
89	// list of shared library modules that should be installed alongside the test
90	Data_libs []string `android:"arch_variant"`
91
92	// list of binary modules that should be installed alongside the test
93	Data_bins []string `android:"arch_variant"`
94
95	// the name of the test configuration (for example "AndroidTest.xml") that should be
96	// installed with the module.
97	Test_config *string `android:"path,arch_variant"`
98
99	// the name of the test configuration template (for example "AndroidTestTemplate.xml") that
100	// should be installed with the module.
101	Test_config_template *string `android:"path,arch_variant"`
102
103	// Test options.
104	Test_options TestOptions
105
106	// Add RootTargetPreparer to auto generated test config. This guarantees the test to run
107	// with root permission.
108	Require_root *bool
109
110	// Add RunCommandTargetPreparer to stop framework before the test and start it after the test.
111	Disable_framework *bool
112
113	// Flag to indicate whether or not to create test config automatically. If AndroidTest.xml
114	// doesn't exist next to the Android.bp, this attribute doesn't need to be set to true
115	// explicitly.
116	Auto_gen_config *bool
117
118	// Add parameterized mainline modules to auto generated test config. The options will be
119	// handled by TradeFed to download and install the specified modules on the device.
120	Test_mainline_modules []string
121
122	// Install the test into a folder named for the module in all test suites.
123	Per_testcase_directory *bool
124}
125
126func init() {
127	android.RegisterModuleType("cc_test", TestFactory)
128	android.RegisterModuleType("cc_test_library", TestLibraryFactory)
129	android.RegisterModuleType("cc_benchmark", BenchmarkFactory)
130	android.RegisterModuleType("cc_test_host", TestHostFactory)
131	android.RegisterModuleType("cc_benchmark_host", BenchmarkHostFactory)
132}
133
134// cc_test generates a test config file and an executable binary file to test
135// specific functionality on a device. The executable binary gets an implicit
136// static_libs dependency on libgtests unless the gtest flag is set to false.
137func TestFactory() android.Module {
138	module := NewTest(android.HostAndDeviceSupported, true)
139	module.bazelHandler = &ccTestBazelHandler{module: module}
140	return module.Init()
141}
142
143// cc_test_library creates an archive of files (i.e. .o files) which is later
144// referenced by another module (such as cc_test, cc_defaults or cc_test_library)
145// for archiving or linking.
146func TestLibraryFactory() android.Module {
147	module := NewTestLibrary(android.HostAndDeviceSupported)
148	return module.Init()
149}
150
151// cc_benchmark compiles an executable binary that performs benchmark testing
152// of a specific component in a device. Additional files such as test suites
153// and test configuration are installed on the side of the compiled executed
154// binary.
155func BenchmarkFactory() android.Module {
156	module := NewBenchmark(android.HostAndDeviceSupported)
157	return module.Init()
158}
159
160// cc_test_host compiles a test host binary.
161func TestHostFactory() android.Module {
162	module := NewTest(android.HostSupported, true)
163	return module.Init()
164}
165
166// cc_benchmark_host compiles an executable binary that performs benchmark
167// testing of a specific component in the host. Additional files such as
168// test suites and test configuration are installed on the side of the
169// compiled executed binary.
170func BenchmarkHostFactory() android.Module {
171	module := NewBenchmark(android.HostSupported)
172	return module.Init()
173}
174
175type testPerSrc interface {
176	testPerSrc() bool
177	srcs() []string
178	isAllTestsVariation() bool
179	setSrc(string, string)
180	unsetSrc()
181}
182
183func (test *testBinary) testPerSrc() bool {
184	return Bool(test.Properties.Test_per_src)
185}
186
187func (test *testBinary) srcs() []string {
188	return test.baseCompiler.Properties.Srcs
189}
190
191func (test *testBinary) dataPaths() []android.DataPath {
192	return test.data
193}
194
195func (test *testBinary) isAllTestsVariation() bool {
196	stem := test.binaryDecorator.Properties.Stem
197	return stem != nil && *stem == ""
198}
199
200func (test *testBinary) setSrc(name, src string) {
201	test.baseCompiler.Properties.Srcs = []string{src}
202	test.binaryDecorator.Properties.Stem = StringPtr(name)
203}
204
205func (test *testBinary) unsetSrc() {
206	test.baseCompiler.Properties.Srcs = nil
207	test.binaryDecorator.Properties.Stem = StringPtr("")
208}
209
210func (test *testBinary) testBinary() bool {
211	return true
212}
213
214var _ testPerSrc = (*testBinary)(nil)
215
216func TestPerSrcMutator(mctx android.BottomUpMutatorContext) {
217	if m, ok := mctx.Module().(*Module); ok {
218		if test, ok := m.linker.(testPerSrc); ok {
219			numTests := len(test.srcs())
220			if test.testPerSrc() && numTests > 0 {
221				if duplicate, found := android.CheckDuplicate(test.srcs()); found {
222					mctx.PropertyErrorf("srcs", "found a duplicate entry %q", duplicate)
223					return
224				}
225				testNames := make([]string, numTests)
226				for i, src := range test.srcs() {
227					testNames[i] = strings.TrimSuffix(filepath.Base(src), filepath.Ext(src))
228				}
229				// In addition to creating one variation per test source file,
230				// create an additional "all tests" variation named "", and have it
231				// depends on all other test_per_src variations. This is useful to
232				// create subsequent dependencies of a given module on all
233				// test_per_src variations created above: by depending on
234				// variation "", that module will transitively depend on all the
235				// other test_per_src variations without the need to know their
236				// name or even their number.
237				testNames = append(testNames, "")
238				tests := mctx.CreateLocalVariations(testNames...)
239				allTests := tests[numTests]
240				allTests.(*Module).linker.(testPerSrc).unsetSrc()
241				// Prevent the "all tests" variation from being installable nor
242				// exporting to Make, as it won't create any output file.
243				allTests.(*Module).Properties.PreventInstall = true
244				allTests.(*Module).Properties.HideFromMake = true
245				for i, src := range test.srcs() {
246					tests[i].(*Module).linker.(testPerSrc).setSrc(testNames[i], src)
247					mctx.AddInterVariantDependency(testPerSrcDepTag, allTests, tests[i])
248				}
249				mctx.AliasVariation("")
250			}
251		}
252	}
253}
254
255type testDecorator struct {
256	LinkerProperties    TestLinkerProperties
257	InstallerProperties TestInstallerProperties
258	installer           *baseInstaller
259	linker              *baseLinker
260}
261
262func (test *testDecorator) gtest() bool {
263	return BoolDefault(test.LinkerProperties.Gtest, true)
264}
265
266func (test *testDecorator) isolated(ctx BaseModuleContext) bool {
267	return BoolDefault(test.LinkerProperties.Isolated, false)
268}
269
270// NOTE: Keep this in sync with cc/cc_test.bzl#gtest_copts
271func (test *testDecorator) linkerFlags(ctx ModuleContext, flags Flags) Flags {
272	if !test.gtest() {
273		return flags
274	}
275
276	flags.Local.CFlags = append(flags.Local.CFlags, "-DGTEST_HAS_STD_STRING")
277	if ctx.Host() {
278		flags.Local.CFlags = append(flags.Local.CFlags, "-O0", "-g")
279
280		switch ctx.Os() {
281		case android.Windows:
282			flags.Local.CFlags = append(flags.Local.CFlags, "-DGTEST_OS_WINDOWS")
283		case android.Linux:
284			flags.Local.CFlags = append(flags.Local.CFlags, "-DGTEST_OS_LINUX")
285		case android.Darwin:
286			flags.Local.CFlags = append(flags.Local.CFlags, "-DGTEST_OS_MAC")
287		}
288	} else {
289		flags.Local.CFlags = append(flags.Local.CFlags, "-DGTEST_OS_LINUX_ANDROID")
290	}
291
292	return flags
293}
294
295func (test *testDecorator) linkerDeps(ctx BaseModuleContext, deps Deps) Deps {
296	if test.gtest() {
297		if ctx.useSdk() && ctx.Device() {
298			deps.StaticLibs = append(deps.StaticLibs, "libgtest_main_ndk_c++", "libgtest_ndk_c++")
299		} else if test.isolated(ctx) {
300			deps.StaticLibs = append(deps.StaticLibs, "libgtest_isolated_main")
301			// The isolated library requires liblog, but adding it
302			// as a static library means unit tests cannot override
303			// liblog functions. Instead make it a shared library
304			// dependency.
305			deps.SharedLibs = append(deps.SharedLibs, "liblog")
306		} else {
307			deps.StaticLibs = append(deps.StaticLibs, "libgtest_main", "libgtest")
308		}
309	}
310
311	return deps
312}
313
314func (test *testDecorator) linkerProps() []interface{} {
315	return []interface{}{&test.LinkerProperties}
316}
317
318func (test *testDecorator) installerProps() []interface{} {
319	return []interface{}{&test.InstallerProperties}
320}
321
322func NewTestInstaller() *baseInstaller {
323	return NewBaseInstaller("nativetest", "nativetest64", InstallInData)
324}
325
326type testBinary struct {
327	*testDecorator
328	*binaryDecorator
329	*baseCompiler
330	Properties       TestBinaryProperties
331	data             []android.DataPath
332	testConfig       android.Path
333	extraTestConfigs android.Paths
334}
335
336func (test *testBinary) linkerProps() []interface{} {
337	props := append(test.testDecorator.linkerProps(), test.binaryDecorator.linkerProps()...)
338	props = append(props, &test.Properties)
339	return props
340}
341
342func (test *testBinary) linkerDeps(ctx DepsContext, deps Deps) Deps {
343	deps = test.testDecorator.linkerDeps(ctx, deps)
344	deps = test.binaryDecorator.linkerDeps(ctx, deps)
345	deps.DataLibs = append(deps.DataLibs, test.Properties.Data_libs...)
346	deps.DataBins = append(deps.DataBins, test.Properties.Data_bins...)
347	return deps
348}
349
350func (test *testBinary) linkerFlags(ctx ModuleContext, flags Flags) Flags {
351	flags = test.binaryDecorator.linkerFlags(ctx, flags)
352	flags = test.testDecorator.linkerFlags(ctx, flags)
353	return flags
354}
355
356func (test *testBinary) installerProps() []interface{} {
357	return append(test.baseInstaller.installerProps(), test.testDecorator.installerProps()...)
358}
359
360func (test *testBinary) install(ctx ModuleContext, file android.Path) {
361	dataSrcPaths := android.PathsForModuleSrc(ctx, test.Properties.Data)
362
363	for _, dataSrcPath := range dataSrcPaths {
364		test.data = append(test.data, android.DataPath{SrcPath: dataSrcPath})
365	}
366
367	ctx.VisitDirectDepsWithTag(dataLibDepTag, func(dep android.Module) {
368		depName := ctx.OtherModuleName(dep)
369		linkableDep, ok := dep.(LinkableInterface)
370		if !ok {
371			ctx.ModuleErrorf("data_lib %q is not a LinkableInterface module", depName)
372		}
373		if linkableDep.OutputFile().Valid() {
374			test.data = append(test.data,
375				android.DataPath{SrcPath: linkableDep.OutputFile().Path(),
376					RelativeInstallPath: linkableDep.RelativeInstallPath()})
377		}
378	})
379	ctx.VisitDirectDepsWithTag(dataBinDepTag, func(dep android.Module) {
380		depName := ctx.OtherModuleName(dep)
381		linkableDep, ok := dep.(LinkableInterface)
382		if !ok {
383			ctx.ModuleErrorf("data_bin %q is not a LinkableInterface module", depName)
384		}
385		if linkableDep.OutputFile().Valid() {
386			test.data = append(test.data,
387				android.DataPath{SrcPath: linkableDep.OutputFile().Path(),
388					RelativeInstallPath: linkableDep.RelativeInstallPath()})
389		}
390	})
391
392	useVendor := ctx.inVendor() || ctx.useVndk()
393	testInstallBase := getTestInstallBase(useVendor)
394	configs := getTradefedConfigOptions(ctx, &test.Properties, test.isolated(ctx))
395
396	test.testConfig = tradefed.AutoGenTestConfig(ctx, tradefed.AutoGenTestConfigOptions{
397		TestConfigProp:         test.Properties.Test_config,
398		TestConfigTemplateProp: test.Properties.Test_config_template,
399		TestSuites:             test.testDecorator.InstallerProperties.Test_suites,
400		Config:                 configs,
401		AutoGenConfig:          test.Properties.Auto_gen_config,
402		TestInstallBase:        testInstallBase,
403		DeviceTemplate:         "${NativeTestConfigTemplate}",
404		HostTemplate:           "${NativeHostTestConfigTemplate}",
405	})
406
407	test.extraTestConfigs = android.PathsForModuleSrc(ctx, test.Properties.Test_options.Extra_test_configs)
408
409	test.binaryDecorator.baseInstaller.dir = "nativetest"
410	test.binaryDecorator.baseInstaller.dir64 = "nativetest64"
411
412	if !Bool(test.Properties.No_named_install_directory) {
413		test.binaryDecorator.baseInstaller.relative = ctx.ModuleName()
414	} else if String(test.binaryDecorator.baseInstaller.Properties.Relative_install_path) == "" {
415		ctx.PropertyErrorf("no_named_install_directory", "Module install directory may only be disabled if relative_install_path is set")
416	}
417
418	if ctx.Host() && test.gtest() && test.Properties.Test_options.Unit_test == nil {
419		test.Properties.Test_options.Unit_test = proptools.BoolPtr(true)
420	}
421	test.binaryDecorator.baseInstaller.install(ctx, file)
422}
423
424func getTestInstallBase(useVendor bool) string {
425	// TODO: (b/167308193) Switch to /data/local/tests/unrestricted as the default install base.
426	testInstallBase := "/data/local/tmp"
427	if useVendor {
428		testInstallBase = "/data/local/tests/vendor"
429	}
430	return testInstallBase
431}
432
433func getTradefedConfigOptions(ctx android.EarlyModuleContext, properties *TestBinaryProperties, isolated bool) []tradefed.Config {
434	var configs []tradefed.Config
435
436	for _, module := range properties.Test_mainline_modules {
437		configs = append(configs, tradefed.Option{Name: "config-descriptor:metadata", Key: "mainline-param", Value: module})
438	}
439	if Bool(properties.Require_root) {
440		configs = append(configs, tradefed.Object{"target_preparer", "com.android.tradefed.targetprep.RootTargetPreparer", nil})
441	} else {
442		var options []tradefed.Option
443		options = append(options, tradefed.Option{Name: "force-root", Value: "false"})
444		configs = append(configs, tradefed.Object{"target_preparer", "com.android.tradefed.targetprep.RootTargetPreparer", options})
445	}
446	if Bool(properties.Disable_framework) {
447		var options []tradefed.Option
448		configs = append(configs, tradefed.Object{"target_preparer", "com.android.tradefed.targetprep.StopServicesSetup", options})
449	}
450	if isolated {
451		configs = append(configs, tradefed.Option{Name: "not-shardable", Value: "true"})
452	}
453	if properties.Test_options.Run_test_as != nil {
454		configs = append(configs, tradefed.Option{Name: "run-test-as", Value: String(properties.Test_options.Run_test_as)})
455	}
456	for _, tag := range properties.Test_options.Test_suite_tag {
457		configs = append(configs, tradefed.Option{Name: "test-suite-tag", Value: tag})
458	}
459	if properties.Test_options.Min_shipping_api_level != nil {
460		if properties.Test_options.Vsr_min_shipping_api_level != nil {
461			ctx.PropertyErrorf("test_options.min_shipping_api_level", "must not be set at the same time as 'vsr_min_shipping_api_level'.")
462		}
463		var options []tradefed.Option
464		options = append(options, tradefed.Option{Name: "min-api-level", Value: strconv.FormatInt(int64(*properties.Test_options.Min_shipping_api_level), 10)})
465		configs = append(configs, tradefed.Object{"module_controller", "com.android.tradefed.testtype.suite.module.ShippingApiLevelModuleController", options})
466	}
467	if properties.Test_options.Vsr_min_shipping_api_level != nil {
468		var options []tradefed.Option
469		options = append(options, tradefed.Option{Name: "vsr-min-api-level", Value: strconv.FormatInt(int64(*properties.Test_options.Vsr_min_shipping_api_level), 10)})
470		configs = append(configs, tradefed.Object{"module_controller", "com.android.tradefed.testtype.suite.module.ShippingApiLevelModuleController", options})
471	}
472	if properties.Test_options.Min_vndk_version != nil {
473		var options []tradefed.Option
474		options = append(options, tradefed.Option{Name: "min-api-level", Value: strconv.FormatInt(int64(*properties.Test_options.Min_vndk_version), 10)})
475		options = append(options, tradefed.Option{Name: "api-level-prop", Value: "ro.vndk.version"})
476		configs = append(configs, tradefed.Object{"module_controller", "com.android.tradefed.testtype.suite.module.MinApiLevelModuleController", options})
477	}
478	return configs
479}
480
481func NewTest(hod android.HostOrDeviceSupported, bazelable bool) *Module {
482	module, binary := newBinary(hod, bazelable)
483	module.bazelable = bazelable
484	module.multilib = android.MultilibBoth
485	binary.baseInstaller = NewTestInstaller()
486
487	test := &testBinary{
488		testDecorator: &testDecorator{
489			linker:    binary.baseLinker,
490			installer: binary.baseInstaller,
491		},
492		binaryDecorator: binary,
493		baseCompiler:    NewBaseCompiler(),
494	}
495	module.compiler = test
496	module.linker = test
497	module.installer = test
498	return module
499}
500
501type testLibrary struct {
502	*testDecorator
503	*libraryDecorator
504}
505
506func (test *testLibrary) testLibrary() bool {
507	return true
508}
509
510func (test *testLibrary) linkerProps() []interface{} {
511	var props []interface{}
512	props = append(props, test.testDecorator.linkerProps()...)
513	return append(props, test.libraryDecorator.linkerProps()...)
514}
515
516func (test *testLibrary) linkerDeps(ctx DepsContext, deps Deps) Deps {
517	deps = test.testDecorator.linkerDeps(ctx, deps)
518	deps = test.libraryDecorator.linkerDeps(ctx, deps)
519	return deps
520}
521
522func (test *testLibrary) linkerFlags(ctx ModuleContext, flags Flags) Flags {
523	flags = test.libraryDecorator.linkerFlags(ctx, flags)
524	flags = test.testDecorator.linkerFlags(ctx, flags)
525	return flags
526}
527
528func (test *testLibrary) installerProps() []interface{} {
529	return append(test.baseInstaller.installerProps(), test.testDecorator.installerProps()...)
530}
531
532func NewTestLibrary(hod android.HostOrDeviceSupported) *Module {
533	module, library := NewLibrary(android.HostAndDeviceSupported)
534	library.baseInstaller = NewTestInstaller()
535	test := &testLibrary{
536		testDecorator: &testDecorator{
537			linker:    library.baseLinker,
538			installer: library.baseInstaller,
539		},
540		libraryDecorator: library,
541	}
542	module.linker = test
543	module.installer = test
544	module.bazelable = true
545	return module
546}
547
548type BenchmarkProperties struct {
549	// list of files or filegroup modules that provide data that should be installed alongside
550	// the test
551	Data []string `android:"path"`
552
553	// list of compatibility suites (for example "cts", "vts") that the module should be
554	// installed into.
555	Test_suites []string `android:"arch_variant"`
556
557	// the name of the test configuration (for example "AndroidTest.xml") that should be
558	// installed with the module.
559	Test_config *string `android:"path,arch_variant"`
560
561	// the name of the test configuration template (for example "AndroidTestTemplate.xml") that
562	// should be installed with the module.
563	Test_config_template *string `android:"path,arch_variant"`
564
565	// Add RootTargetPreparer to auto generated test config. This guarantees the test to run
566	// with root permission.
567	Require_root *bool
568
569	// Flag to indicate whether or not to create test config automatically. If AndroidTest.xml
570	// doesn't exist next to the Android.bp, this attribute doesn't need to be set to true
571	// explicitly.
572	Auto_gen_config *bool
573}
574
575type benchmarkDecorator struct {
576	*binaryDecorator
577	Properties BenchmarkProperties
578	data       android.Paths
579	testConfig android.Path
580}
581
582func (benchmark *benchmarkDecorator) benchmarkBinary() bool {
583	return true
584}
585
586func (benchmark *benchmarkDecorator) linkerProps() []interface{} {
587	props := benchmark.binaryDecorator.linkerProps()
588	props = append(props, &benchmark.Properties)
589	return props
590}
591
592func (benchmark *benchmarkDecorator) linkerDeps(ctx DepsContext, deps Deps) Deps {
593	deps = benchmark.binaryDecorator.linkerDeps(ctx, deps)
594	deps.StaticLibs = append(deps.StaticLibs, "libgoogle-benchmark")
595	return deps
596}
597
598func (benchmark *benchmarkDecorator) install(ctx ModuleContext, file android.Path) {
599	benchmark.data = android.PathsForModuleSrc(ctx, benchmark.Properties.Data)
600
601	var configs []tradefed.Config
602	if Bool(benchmark.Properties.Require_root) {
603		configs = append(configs, tradefed.Object{"target_preparer", "com.android.tradefed.targetprep.RootTargetPreparer", nil})
604	}
605	benchmark.testConfig = tradefed.AutoGenTestConfig(ctx, tradefed.AutoGenTestConfigOptions{
606		TestConfigProp:         benchmark.Properties.Test_config,
607		TestConfigTemplateProp: benchmark.Properties.Test_config_template,
608		TestSuites:             benchmark.Properties.Test_suites,
609		Config:                 configs,
610		AutoGenConfig:          benchmark.Properties.Auto_gen_config,
611		DeviceTemplate:         "${NativeBenchmarkTestConfigTemplate}",
612		HostTemplate:           "${NativeBenchmarkTestConfigTemplate}",
613	})
614
615	benchmark.binaryDecorator.baseInstaller.dir = filepath.Join("benchmarktest", ctx.ModuleName())
616	benchmark.binaryDecorator.baseInstaller.dir64 = filepath.Join("benchmarktest64", ctx.ModuleName())
617	benchmark.binaryDecorator.baseInstaller.install(ctx, file)
618}
619
620func NewBenchmark(hod android.HostOrDeviceSupported) *Module {
621	module, binary := newBinary(hod, false)
622	module.multilib = android.MultilibBoth
623	binary.baseInstaller = NewBaseInstaller("benchmarktest", "benchmarktest64", InstallInData)
624
625	benchmark := &benchmarkDecorator{
626		binaryDecorator: binary,
627	}
628	module.linker = benchmark
629	module.installer = benchmark
630	return module
631}
632
633type ccTestBazelHandler struct {
634	module *Module
635}
636
637var _ BazelHandler = (*ccTestBazelHandler)(nil)
638
639func (handler *ccTestBazelHandler) QueueBazelCall(ctx android.BaseModuleContext, label string) {
640	bazelCtx := ctx.Config().BazelContext
641	bazelCtx.QueueBazelRequest(label, cquery.GetCcUnstrippedInfo, android.GetConfigKey(ctx))
642}
643
644func (handler *ccTestBazelHandler) ProcessBazelQueryResponse(ctx android.ModuleContext, label string) {
645	bazelCtx := ctx.Config().BazelContext
646	info, err := bazelCtx.GetCcUnstrippedInfo(label, android.GetConfigKey(ctx))
647	if err != nil {
648		ctx.ModuleErrorf(err.Error())
649		return
650	}
651
652	var outputFilePath android.Path = android.PathForBazelOut(ctx, info.OutputFile)
653	if len(info.TidyFiles) > 0 {
654		handler.module.tidyFiles = android.PathsForBazelOut(ctx, info.TidyFiles)
655		outputFilePath = android.AttachValidationActions(ctx, outputFilePath, handler.module.tidyFiles)
656	}
657	handler.module.outputFile = android.OptionalPathForPath(outputFilePath)
658	handler.module.linker.(*testBinary).unstrippedOutputFile = android.PathForBazelOut(ctx, info.UnstrippedOutput)
659
660	handler.module.setAndroidMkVariablesFromCquery(info.CcAndroidMkInfo)
661}
662
663// binaryAttributes contains Bazel attributes corresponding to a cc test
664type testBinaryAttributes struct {
665	binaryAttributes
666
667	Gtest    bool
668	Isolated bool
669
670	tidyAttributes
671	tradefed.TestConfigAttributes
672}
673
674// testBinaryBp2build is the bp2build converter for cc_test modules. A cc_test's
675// dependency graph and compilation/linking steps are functionally similar to a
676// cc_binary, but has additional dependencies on test deps like gtest, and
677// produces additional runfiles like XML plans for Tradefed orchestration
678//
679// TODO(b/244432609): handle `isolated` property.
680// TODO(b/244432134): handle custom runpaths for tests that assume runfile layouts not
681// default to bazel. (see linkerInit function)
682func testBinaryBp2build(ctx android.TopDownMutatorContext, m *Module) {
683	var testBinaryAttrs testBinaryAttributes
684	testBinaryAttrs.binaryAttributes = binaryBp2buildAttrs(ctx, m)
685
686	var data bazel.LabelListAttribute
687	var tags bazel.StringListAttribute
688
689	testBinaryProps := m.GetArchVariantProperties(ctx, &TestBinaryProperties{})
690	for axis, configToProps := range testBinaryProps {
691		for config, props := range configToProps {
692			if p, ok := props.(*TestBinaryProperties); ok {
693				// Combine data, data_bins and data_libs into a single 'data' attribute.
694				var combinedData bazel.LabelList
695				combinedData.Append(android.BazelLabelForModuleSrc(ctx, p.Data))
696				combinedData.Append(android.BazelLabelForModuleDeps(ctx, p.Data_bins))
697				combinedData.Append(android.BazelLabelForModuleDeps(ctx, p.Data_libs))
698				data.SetSelectValue(axis, config, combinedData)
699				tags.SetSelectValue(axis, config, p.Test_options.Tags)
700			}
701		}
702	}
703
704	m.convertTidyAttributes(ctx, &testBinaryAttrs.tidyAttributes)
705
706	for _, propIntf := range m.GetProperties() {
707		if testLinkerProps, ok := propIntf.(*TestLinkerProperties); ok {
708			testBinaryAttrs.Gtest = proptools.BoolDefault(testLinkerProps.Gtest, true)
709			testBinaryAttrs.Isolated = proptools.BoolDefault(testLinkerProps.Isolated, true)
710			break
711		}
712	}
713
714	for _, testProps := range m.GetProperties() {
715		if p, ok := testProps.(*TestBinaryProperties); ok {
716			useVendor := false // TODO Bug: 262914724
717			testInstallBase := getTestInstallBase(useVendor)
718			testConfigAttributes := tradefed.GetTestConfigAttributes(
719				ctx,
720				p.Test_config,
721				p.Test_options.Extra_test_configs,
722				p.Auto_gen_config,
723				p.Test_options.Test_suite_tag,
724				p.Test_config_template,
725				getTradefedConfigOptions(ctx, p, testBinaryAttrs.Isolated),
726				&testInstallBase,
727			)
728			testBinaryAttrs.TestConfigAttributes = testConfigAttributes
729		}
730	}
731
732	// TODO (b/262914724): convert to tradefed_cc_test and tradefed_cc_test_host
733	ctx.CreateBazelTargetModule(
734		bazel.BazelTargetModuleProperties{
735			Rule_class:        "cc_test",
736			Bzl_load_location: "//build/bazel/rules/cc:cc_test.bzl",
737		},
738		android.CommonAttributes{
739			Name: m.Name(),
740			Data: data,
741			Tags: tags,
742		},
743		&testBinaryAttrs)
744}
745