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