1// Copyright 2017 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 python 16 17import ( 18 "fmt" 19 20 "github.com/google/blueprint/proptools" 21 22 "android/soong/android" 23 "android/soong/tradefed" 24) 25 26// This file contains the module types for building Python test. 27 28func init() { 29 registerPythonTestComponents(android.InitRegistrationContext) 30} 31 32func registerPythonTestComponents(ctx android.RegistrationContext) { 33 ctx.RegisterModuleType("python_test_host", PythonTestHostFactory) 34 ctx.RegisterModuleType("python_test", PythonTestFactory) 35} 36 37func NewTest(hod android.HostOrDeviceSupported) *PythonTestModule { 38 return &PythonTestModule{PythonBinaryModule: *NewBinary(hod)} 39} 40 41func PythonTestHostFactory() android.Module { 42 return NewTest(android.HostSupportedNoCross).init() 43} 44 45func PythonTestFactory() android.Module { 46 module := NewTest(android.HostAndDeviceSupported) 47 module.multilib = android.MultilibBoth 48 return module.init() 49} 50 51type TestProperties struct { 52 // the name of the test configuration (for example "AndroidTest.xml") that should be 53 // installed with the module. 54 Test_config *string `android:"path,arch_variant"` 55 56 // the name of the test configuration template (for example "AndroidTestTemplate.xml") that 57 // should be installed with the module. 58 Test_config_template *string `android:"path,arch_variant"` 59 60 // list of files or filegroup modules that provide data that should be installed alongside 61 // the test 62 Data []string `android:"path,arch_variant"` 63 64 // list of java modules that provide data that should be installed alongside the test. 65 Java_data []string 66 67 // Test options. 68 Test_options TestOptions 69} 70 71type TestOptions struct { 72 android.CommonTestOptions 73 74 // Runner for the test. Supports "tradefed" and "mobly" (for multi-device tests). Default is "tradefed". 75 Runner *string 76 77 // Metadata to describe the test configuration. 78 Metadata []Metadata 79} 80 81type Metadata struct { 82 Name string 83 Value string 84} 85 86type PythonTestModule struct { 87 PythonBinaryModule 88 89 testProperties TestProperties 90 testConfig android.Path 91 data []android.DataPath 92} 93 94func (p *PythonTestModule) init() android.Module { 95 p.AddProperties(&p.properties, &p.protoProperties) 96 p.AddProperties(&p.binaryProperties) 97 p.AddProperties(&p.testProperties) 98 android.InitAndroidArchModule(p, p.hod, p.multilib) 99 android.InitDefaultableModule(p) 100 android.InitBazelModule(p) 101 if p.hod == android.HostSupportedNoCross && p.testProperties.Test_options.Unit_test == nil { 102 p.testProperties.Test_options.Unit_test = proptools.BoolPtr(true) 103 } 104 return p 105} 106 107func (p *PythonTestModule) GenerateAndroidBuildActions(ctx android.ModuleContext) { 108 // We inherit from only the library's GenerateAndroidBuildActions, and then 109 // just use buildBinary() so that the binary is not installed into the location 110 // it would be for regular binaries. 111 p.PythonLibraryModule.GenerateAndroidBuildActions(ctx) 112 p.buildBinary(ctx) 113 114 var configs []tradefed.Option 115 for _, metadata := range p.testProperties.Test_options.Metadata { 116 configs = append(configs, tradefed.Option{Name: "config-descriptor:metadata", Key: metadata.Name, Value: metadata.Value}) 117 } 118 119 runner := proptools.StringDefault(p.testProperties.Test_options.Runner, "tradefed") 120 if runner == "tradefed" { 121 p.testConfig = tradefed.AutoGenTestConfig(ctx, tradefed.AutoGenTestConfigOptions{ 122 TestConfigProp: p.testProperties.Test_config, 123 TestConfigTemplateProp: p.testProperties.Test_config_template, 124 TestSuites: p.binaryProperties.Test_suites, 125 OptionsForAutogenerated: configs, 126 AutoGenConfig: p.binaryProperties.Auto_gen_config, 127 DeviceTemplate: "${PythonBinaryHostTestConfigTemplate}", 128 HostTemplate: "${PythonBinaryHostTestConfigTemplate}", 129 }) 130 } else if runner == "mobly" { 131 if p.testProperties.Test_config != nil || p.testProperties.Test_config_template != nil || p.binaryProperties.Auto_gen_config != nil { 132 panic(fmt.Errorf("cannot set test_config, test_config_template or auto_gen_config for mobly test")) 133 } 134 135 for _, testSuite := range p.binaryProperties.Test_suites { 136 if testSuite == "cts" { 137 configs = append(configs, tradefed.Option{Name: "test-suite-tag", Value: "cts"}) 138 break 139 } 140 } 141 p.testConfig = tradefed.AutoGenTestConfig(ctx, tradefed.AutoGenTestConfigOptions{ 142 OptionsForAutogenerated: configs, 143 DeviceTemplate: "${PythonBinaryHostMoblyTestConfigTemplate}", 144 HostTemplate: "${PythonBinaryHostMoblyTestConfigTemplate}", 145 }) 146 } else { 147 panic(fmt.Errorf("unknown python test runner '%s', should be 'tradefed' or 'mobly'", runner)) 148 } 149 150 p.installedDest = ctx.InstallFile(installDir(ctx, "nativetest", "nativetest64", ctx.ModuleName()), p.installSource.Base(), p.installSource) 151 152 for _, dataSrcPath := range android.PathsForModuleSrc(ctx, p.testProperties.Data) { 153 p.data = append(p.data, android.DataPath{SrcPath: dataSrcPath}) 154 } 155 156 // Emulate the data property for java_data dependencies. 157 for _, javaData := range ctx.GetDirectDepsWithTag(javaDataTag) { 158 for _, javaDataSrcPath := range android.OutputFilesForModule(ctx, javaData, "") { 159 p.data = append(p.data, android.DataPath{SrcPath: javaDataSrcPath}) 160 } 161 } 162} 163 164func (p *PythonTestModule) AndroidMkEntries() []android.AndroidMkEntries { 165 entriesList := p.PythonBinaryModule.AndroidMkEntries() 166 if len(entriesList) != 1 { 167 panic("Expected 1 entry") 168 } 169 entries := &entriesList[0] 170 171 entries.Class = "NATIVE_TESTS" 172 173 entries.ExtraEntries = append(entries.ExtraEntries, 174 func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) { 175 //entries.AddCompatibilityTestSuites(p.binaryProperties.Test_suites...) 176 if p.testConfig != nil { 177 entries.SetString("LOCAL_FULL_TEST_CONFIG", p.testConfig.String()) 178 } 179 180 entries.SetBoolIfTrue("LOCAL_DISABLE_AUTO_GENERATE_TEST_CONFIG", !BoolDefault(p.binaryProperties.Auto_gen_config, true)) 181 182 entries.AddStrings("LOCAL_TEST_DATA", android.AndroidMkDataPaths(p.data)...) 183 184 p.testProperties.Test_options.SetAndroidMkEntries(entries) 185 }) 186 187 return entriesList 188} 189