1# Copyright 2015 The Chromium OS Authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5import os 6import logging 7import re 8 9import common 10from autotest_lib.client.common_lib import error 11from autotest_lib.client.common_lib import global_config 12from autotest_lib.client.common_lib.cros import dev_server 13from autotest_lib.server import test 14from autotest_lib.server.hosts import adb_host 15from autotest_lib.server.hosts import host_info 16from autotest_lib.site_utils import acts_lib 17from server.cros import dnsname_mangler 18 19CONFIG = global_config.global_config 20 21CONFIG_FOLDER_LOCATION = global_config.global_config.get_config_value( 22 'ACTS', 'acts_config_folder', default='') 23 24TEST_CONFIG_FILE_FOLDER = os.path.join(CONFIG_FOLDER_LOCATION, 25 'autotest_config') 26 27TEST_CAMPAIGN_FILE_FOLDER = os.path.join(CONFIG_FOLDER_LOCATION, 28 'autotest_campaign') 29DEFAULT_TEST_RELATIVE_LOG_PATH = 'results/logs' 30 31 32def get_global_config_value_regex(section, regex): 33 """Get config values from global config based on regex of the key. 34 35 @param section: Section of the config, e.g., CLIENT. 36 @param regex: Regular expression of the key pattern. 37 38 @return: A dictionary of all config values matching the regex. Value is 39 assumed to be comma separated, and is converted to a list. 40 """ 41 configs = CONFIG.get_config_value_regex(section, regex) 42 result = {} 43 for key, value in configs.items(): 44 match = re.match(regex, key) 45 result[match.group(1)] = [v.strip() for v in value.split(',') 46 if v.strip()] 47 return result 48 49 50class android_ACTS(test.test): 51 """Run an Android CTS test case. 52 53 Component relationship: 54 Workstation ----(ssh)---> TestStation -----(adb)-----> Android DUT 55 This code runs on Workstation. 56 """ 57 version = 1 58 59 BRANCH_ALIAS_PATTERN = 'acts_branch_alias_(.*)' 60 aliases_map = get_global_config_value_regex('ACTS', BRANCH_ALIAS_PATTERN) 61 62 def run_once(self, 63 testbed=None, 64 config_file=None, 65 testbed_name=None, 66 test_case=None, 67 test_file=None, 68 additional_configs=[], 69 additional_apks=[], 70 override_build_url=None, 71 override_build=None, 72 override_acts_zip=None, 73 override_internal_acts_dir=None, 74 override_python_bin='python', 75 acts_timeout=7200, 76 perma_path=None, 77 additional_cmd_line_params=None, 78 branch_mappings={}, 79 valid_job_urls_only=False, 80 testtracker_project_id=None, 81 testtracker_extra_env=None, 82 testtracker_owner=None): 83 """Runs an acts test case. 84 85 @param testbed: The testbed to test on. 86 @config_file: The main config file to use for running the test. This 87 should be relative to the autotest_config folder. 88 @param test_case: The test case to run. Should be None when test_file 89 is given. 90 @param test_file: The campaign file to run. Should be None when 91 test_case is given. This should be relative to the 92 autotest_campaign folder. If multiple are given, 93 multiple test cases will be run. 94 @param additional_configs: Any additional config files to use. 95 These should be relative to the 96 autotest_config folder. 97 @param additional_apks: An array of apk info dictionaries. 98 apk = Name of the apk (eg. sl4a.apk) 99 package = Name of the package (eg. test.tools) 100 artifact = Name of the artifact, if not given 101 package is used. 102 @param override_build_url: Deprecated, use override_build instead. 103 @param override_build: The android build to fetch test artifacts from. 104 If not provided a default is selected from one 105 of the devices. 106 @param override_acts_zip: If given a zip file on the drone is used 107 rather than pulling a build. 108 @param override_internal_acts_dir: The directory within the artifact 109 where the acts framework folder 110 lives. 111 @param override_python_bin: Overrides the default python binary that 112 is used. 113 @param acts_timeout: How long to wait for acts to finish. 114 @param valid_job_urls_only: Apps and resources will be downloaded and 115 installed only on devices that have valid 116 job urls. 117 @param perma_path: If given a permantent path will be used rather than 118 a temp path. 119 @para branch_mappings: A dictionary of branch names to branch names. 120 When pulling test resources, if the current 121 branch is found in the mapping it will use 122 the mapped branch instead. 123 @param testtracker_project_id: ID to use for test tracker project. 124 @param testtracker_extra_env: Extra environment info to publish 125 with the results. 126 """ 127 hostname = testbed.hostname 128 if not testbed_name: 129 if dnsname_mangler.is_ip_address(hostname): 130 testbed_name = hostname 131 else: 132 testbed_name = hostname.split('.')[0] 133 134 logging.info('Using testbed name %s', testbed_name) 135 136 if not override_build: 137 override_build = override_build_url 138 139 valid_hosts = [] 140 if valid_job_urls_only: 141 for v in testbed.get_adb_devices().values(): 142 try: 143 info = v.host_info_store.get() 144 except host_info.StoreError: 145 pass 146 else: 147 if v.job_repo_url_attribute in info.attributes: 148 valid_hosts.append(v) 149 else: 150 valid_hosts = list(testbed.get_adb_devices().values()) 151 152 if not valid_hosts: 153 raise error.TestError('No valid hosts defined for this test, cannot' 154 ' determine build to grab artifact from.') 155 156 primary_host = valid_hosts[0] 157 158 info = primary_host.host_info_store.get() 159 job_repo_url = info.attributes.get(primary_host.job_repo_url_attribute, 160 '') 161 test_station = testbed.teststation 162 if not perma_path: 163 ts_tempfolder = test_station.get_tmp_dir() 164 else: 165 test_station.run('rm -fr "%s"' % perma_path) 166 test_station.run('mkdir "%s"' % perma_path) 167 ts_tempfolder = perma_path 168 target_zip = os.path.join(ts_tempfolder, 'acts.zip') 169 170 if override_build: 171 build_pieces = override_build.split('/') 172 job_build_branch = build_pieces[0] 173 job_build_target = build_pieces[1] 174 job_build_id = build_pieces[2] 175 else: 176 job_build_info = adb_host.ADBHost.get_build_info_from_build_url( 177 job_repo_url) 178 job_build_branch = job_build_info['branch'] 179 job_build_target = job_build_info['target'] 180 job_build_id = job_build_info['build_id'] 181 182 if not override_build_url: 183 if job_build_branch in branch_mappings: 184 logging.info('Replacing branch %s -> %s', 185 job_build_branch, 186 branch_mappings[job_build_branch].strip()) 187 job_build_branch = branch_mappings[job_build_branch].strip() 188 job_build_id = "LATEST" 189 elif job_build_branch in self.aliases_map: 190 logging.info('Replacing branch %s -> %s', 191 job_build_branch, 192 self.aliases_map[job_build_branch][0].strip()) 193 job_build_branch = self.aliases_map[job_build_branch][0].strip() 194 job_build_id = "LATEST" 195 196 build_name = '%s/%s/%s' % (job_build_branch, 197 job_build_target, 198 job_build_id) 199 devserver = dev_server.AndroidBuildServer.resolve(build_name, 200 primary_host.hostname) 201 build_name = devserver.translate(build_name) 202 build_branch, build_target, build_id = build_name.split('/') 203 204 logging.info('Using build info BRANCH:%s, TARGET:%s, BUILD_ID:%s', 205 build_branch, build_target, build_id) 206 207 if override_acts_zip: 208 package = acts_lib.create_acts_package_from_zip(test_station, 209 override_acts_zip, 210 target_zip) 211 else: 212 package = acts_lib.create_acts_package_from_artifact(test_station, 213 build_branch, 214 build_target, 215 build_id, 216 devserver, 217 target_zip) 218 219 test_env = package.create_environment( 220 container_directory=ts_tempfolder, 221 testbed_name=testbed_name, 222 devices=valid_hosts, 223 internal_acts_directory=override_internal_acts_dir) 224 225 test_env.install_sl4a_apk() 226 227 for apk in additional_apks: 228 test_env.install_apk(apk) 229 230 test_env.setup_enviroment(python_bin=override_python_bin) 231 232 test_env.upload_config(config_file) 233 234 if additional_configs: 235 for additional_config in additional_configs: 236 test_env.upload_config(additional_config) 237 238 if test_file: 239 test_env.upload_campaign(test_file) 240 241 results = test_env.run_test( 242 config_file, 243 campaign=test_file, 244 test_case=test_case, 245 python_bin=override_python_bin, 246 timeout=acts_timeout, 247 additional_cmd_line_params=additional_cmd_line_params) 248 249 results.log_output() 250 results.report_to_autotest(self) 251 results.save_test_info(self) 252 results.rethrow_exception() 253