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