| 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 |