• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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