OLD | NEW |
1 # Copyright 2014 The Chromium Authors. All rights reserved. | 1 # Copyright 2014 The Chromium Authors. All rights reserved. |
2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 """Run specific test on specific environment.""" | 5 """Run specific test on specific environment.""" |
6 | 6 |
7 import logging | 7 import logging |
8 import os | 8 import os |
9 import sys | 9 import sys |
10 import tempfile | 10 import tempfile |
11 import time | 11 import time |
12 import zipfile | 12 import zipfile |
13 | 13 |
14 from pylib import constants | 14 from pylib import constants |
15 from pylib.base import test_run | 15 from pylib.base import test_run |
16 from pylib.remote.device import appurify_sanitized | 16 from pylib.remote.device import appurify_sanitized |
17 from pylib.remote.device import remote_device_helper | 17 from pylib.remote.device import remote_device_helper |
18 from pylib.utils import zip_utils | 18 from pylib.utils import zip_utils |
19 | 19 |
20 class RemoteDeviceTestRun(test_run.TestRun): | 20 class RemoteDeviceTestRun(test_run.TestRun): |
21 """Run gtests and uirobot tests on a remote device.""" | 21 """Run gtests and uirobot tests on a remote device.""" |
22 | 22 |
23 WAIT_TIME = 5 | 23 WAIT_TIME = 5 |
24 COMPLETE = 'complete' | 24 COMPLETE = 'complete' |
| 25 HEARTBEAT_INTERVAL = 300 |
25 | 26 |
26 def __init__(self, env, test_instance): | 27 def __init__(self, env, test_instance): |
27 """Constructor. | 28 """Constructor. |
28 | 29 |
29 Args: | 30 Args: |
30 env: Environment the tests will run in. | 31 env: Environment the tests will run in. |
31 test_instance: The test that will be run. | 32 test_instance: The test that will be run. |
32 """ | 33 """ |
33 super(RemoteDeviceTestRun, self).__init__(env, test_instance) | 34 super(RemoteDeviceTestRun, self).__init__(env, test_instance) |
34 self._env = env | 35 self._env = env |
35 self._test_instance = test_instance | 36 self._test_instance = test_instance |
36 self._app_id = '' | 37 self._app_id = '' |
37 self._test_id = '' | 38 self._test_id = '' |
38 self._results = '' | 39 self._results = '' |
39 self._test_run_id = '' | 40 self._test_run_id = '' |
40 self._current_status = '' | |
41 | 41 |
42 #override | 42 #override |
43 def RunTests(self): | 43 def RunTests(self): |
44 """Run the test.""" | 44 """Run the test.""" |
45 if self._env.trigger: | 45 if self._env.trigger: |
46 with appurify_sanitized.SanitizeLogging(self._env.verbose_count, | 46 with appurify_sanitized.SanitizeLogging(self._env.verbose_count, |
47 logging.WARNING): | 47 logging.WARNING): |
48 test_start_res = appurify_sanitized.api.tests_run( | 48 test_start_res = appurify_sanitized.api.tests_run( |
49 self._env.token, self._env.device, self._app_id, self._test_id) | 49 self._env.token, self._env.device, self._app_id, self._test_id) |
50 remote_device_helper.TestHttpResponse( | 50 remote_device_helper.TestHttpResponse( |
51 test_start_res, 'Unable to run test.') | 51 test_start_res, 'Unable to run test.') |
52 self._test_run_id = test_start_res.json()['response']['test_run_id'] | 52 self._test_run_id = test_start_res.json()['response']['test_run_id'] |
53 logging.info('Test run id: %s' % self._test_run_id) | 53 logging.info('Test run id: %s' % self._test_run_id) |
54 if not self._env.collect: | 54 if not self._env.collect: |
55 assert isinstance(self._env.trigger, basestring), ( | 55 assert isinstance(self._env.trigger, basestring), ( |
56 'File for storing test_run_id must be a string.') | 56 'File for storing test_run_id must be a string.') |
57 with open(self._env.trigger, 'w') as test_run_id_file: | 57 with open(self._env.trigger, 'w') as test_run_id_file: |
58 test_run_id_file.write(self._test_run_id) | 58 test_run_id_file.write(self._test_run_id) |
59 | 59 |
60 if self._env.collect: | 60 if self._env.collect: |
61 if not self._env.trigger: | 61 if not self._env.trigger: |
62 assert isinstance(self._env.trigger, basestring), ( | 62 assert isinstance(self._env.trigger, basestring), ( |
63 'File for storing test_run_id must be a string.') | 63 'File for storing test_run_id must be a string.') |
64 with open(self._env.collect, 'r') as test_run_id_file: | 64 with open(self._env.collect, 'r') as test_run_id_file: |
65 self._test_run_id = test_run_id_file.read().strip() | 65 self._test_run_id = test_run_id_file.read().strip() |
| 66 current_status = '' |
| 67 timeout_counter = 0 |
| 68 heartbeat_counter = 0 |
66 while self._GetTestStatus(self._test_run_id) != self.COMPLETE: | 69 while self._GetTestStatus(self._test_run_id) != self.COMPLETE: |
| 70 if self._results['detailed_status'] != current_status: |
| 71 logging.info('Test status: %s', self._results['detailed_status']) |
| 72 current_status = self._results['detailed_status'] |
| 73 timeout_counter = 0 |
| 74 heartbeat_counter = 0 |
| 75 if heartbeat_counter > self.HEARTBEAT_INTERVAL: |
| 76 logging.info('Test status: %s', self._results['detailed_status']) |
| 77 heartbeat_counter = 0 |
| 78 |
| 79 timeout = self._env.timeouts.get( |
| 80 current_status, self._env.timeouts['unknown']) |
| 81 if timeout_counter > timeout: |
| 82 raise remote_device_helper.RemoteDeviceError( |
| 83 'Timeout while in %s state for %s seconds' |
| 84 % (current_status, timeout)) |
67 time.sleep(self.WAIT_TIME) | 85 time.sleep(self.WAIT_TIME) |
| 86 timeout_counter += self.WAIT_TIME |
| 87 heartbeat_counter += self.WAIT_TIME |
68 self._DownloadTestResults(self._env.results_path) | 88 self._DownloadTestResults(self._env.results_path) |
69 return self._ParseTestResults() | 89 return self._ParseTestResults() |
70 | 90 |
71 #override | 91 #override |
72 def TearDown(self): | 92 def TearDown(self): |
73 """Tear down the test run.""" | 93 """Tear down the test run.""" |
74 if (self._env.collect | 94 if (self._env.collect |
75 and self._GetTestStatus(self._test_run_id) != self.COMPLETE): | 95 and self._GetTestStatus(self._test_run_id) != self.COMPLETE): |
76 with appurify_sanitized.SanitizeLogging(self._env.verbose_count, | 96 with appurify_sanitized.SanitizeLogging(self._env.verbose_count, |
77 logging.WARNING): | 97 logging.WARNING): |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
141 test_run_id: Id of test on on remote service. | 161 test_run_id: Id of test on on remote service. |
142 """ | 162 """ |
143 | 163 |
144 with appurify_sanitized.SanitizeLogging(self._env.verbose_count, | 164 with appurify_sanitized.SanitizeLogging(self._env.verbose_count, |
145 logging.WARNING): | 165 logging.WARNING): |
146 test_check_res = appurify_sanitized.api.tests_check_result( | 166 test_check_res = appurify_sanitized.api.tests_check_result( |
147 self._env.token, test_run_id) | 167 self._env.token, test_run_id) |
148 remote_device_helper.TestHttpResponse(test_check_res, | 168 remote_device_helper.TestHttpResponse(test_check_res, |
149 'Unable to get test status.') | 169 'Unable to get test status.') |
150 self._results = test_check_res.json()['response'] | 170 self._results = test_check_res.json()['response'] |
151 if self._results['detailed_status'] != self._current_status: | |
152 logging.info('Test status: %s', self._results['detailed_status']) | |
153 self._current_status = self._results['detailed_status'] | |
154 return self._results['status'] | 171 return self._results['status'] |
155 | 172 |
156 def _AmInstrumentTestSetup(self, app_path, test_path, runner_package): | 173 def _AmInstrumentTestSetup(self, app_path, test_path, runner_package): |
157 config = {'runner': runner_package} | 174 config = {'runner': runner_package} |
158 | 175 |
159 self._app_id = self._UploadAppToDevice(app_path) | 176 self._app_id = self._UploadAppToDevice(app_path) |
160 | 177 |
161 data_deps = self._test_instance.GetDataDependencies() | 178 data_deps = self._test_instance.GetDataDependencies() |
162 if data_deps: | 179 if data_deps: |
163 with tempfile.NamedTemporaryFile(suffix='.zip') as test_with_deps: | 180 with tempfile.NamedTemporaryFile(suffix='.zip') as test_with_deps: |
(...skipping 13 matching lines...) Expand all Loading... |
177 'robotium', test_with_deps.name) | 194 'robotium', test_with_deps.name) |
178 else: | 195 else: |
179 self._test_id = self._UploadTestToDevice('robotium', test_path) | 196 self._test_id = self._UploadTestToDevice('robotium', test_path) |
180 | 197 |
181 logging.info('Setting config: %s' % config) | 198 logging.info('Setting config: %s' % config) |
182 self._SetTestConfig('robotium', config) | 199 self._SetTestConfig('robotium', config) |
183 | 200 |
184 def _UploadAppToDevice(self, app_path): | 201 def _UploadAppToDevice(self, app_path): |
185 """Upload app to device.""" | 202 """Upload app to device.""" |
186 logging.info('Uploading %s to remote service.', app_path) | 203 logging.info('Uploading %s to remote service.', app_path) |
187 apk_name = os.path.basename(app_path) | |
188 with open(app_path, 'rb') as apk_src: | 204 with open(app_path, 'rb') as apk_src: |
189 with appurify_sanitized.SanitizeLogging(self._env.verbose_count, | 205 with appurify_sanitized.SanitizeLogging(self._env.verbose_count, |
190 logging.WARNING): | 206 logging.WARNING): |
191 upload_results = appurify_sanitized.api.apps_upload( | 207 upload_results = appurify_sanitized.api.apps_upload( |
192 self._env.token, apk_src, 'raw', name=apk_name) | 208 self._env.token, apk_src, 'raw', name=self._test_instance.suite) |
193 remote_device_helper.TestHttpResponse( | 209 remote_device_helper.TestHttpResponse( |
194 upload_results, 'Unable to upload %s.' % app_path) | 210 upload_results, 'Unable to upload %s.' % app_path) |
195 return upload_results.json()['response']['app_id'] | 211 return upload_results.json()['response']['app_id'] |
196 | 212 |
197 def _UploadTestToDevice(self, test_type, test_path): | 213 def _UploadTestToDevice(self, test_type, test_path): |
198 """Upload test to device | 214 """Upload test to device |
199 Args: | 215 Args: |
200 test_type: Type of test that is being uploaded. Ex. uirobot, gtest.. | 216 test_type: Type of test that is being uploaded. Ex. uirobot, gtest.. |
201 """ | 217 """ |
202 logging.info('Uploading %s to remote service.' % test_path) | 218 logging.info('Uploading %s to remote service.' % test_path) |
(...skipping 17 matching lines...) Expand all Loading... |
220 config_data.extend('%s=%s' % (k, v) for k, v in body.iteritems()) | 236 config_data.extend('%s=%s' % (k, v) for k, v in body.iteritems()) |
221 config.write(''.join('%s\n' % l for l in config_data)) | 237 config.write(''.join('%s\n' % l for l in config_data)) |
222 config.flush() | 238 config.flush() |
223 config.seek(0) | 239 config.seek(0) |
224 with appurify_sanitized.SanitizeLogging(self._env.verbose_count, | 240 with appurify_sanitized.SanitizeLogging(self._env.verbose_count, |
225 logging.WARNING): | 241 logging.WARNING): |
226 config_response = appurify_sanitized.api.config_upload( | 242 config_response = appurify_sanitized.api.config_upload( |
227 self._env.token, config, self._test_id) | 243 self._env.token, config, self._test_id) |
228 remote_device_helper.TestHttpResponse( | 244 remote_device_helper.TestHttpResponse( |
229 config_response, 'Unable to upload test config.') | 245 config_response, 'Unable to upload test config.') |
OLD | NEW |