Changeset 143833 in webkit
- Timestamp:
- Feb 22, 2013 8:28:47 PM (11 years ago)
- Location:
- trunk/Tools
- Files:
-
- 12 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Tools/ChangeLog
r143824 r143833 1 2013-02-22 Ryosuke Niwa <rniwa@webkit.org> 2 3 Upload results to perf.webkit.org in addition to the one specified by --test-results-server 4 https://bugs.webkit.org/show_bug.cgi?id=108577 5 6 Reviewed by Dirk Pranke. 7 8 Upload results to perf.webkit.org using new JSON format as well as the host specified by 9 --test-results-server. The new format is needed to provide extra information perf.webkit.org 10 need such as the subversion commit time and test URLs. This is a temporarily measure until 11 we complete the transition and the old JSON format and the code to upload results to 12 webkit-perf.appspot.com can be deleted. 13 14 This patch adds scm.timestamp_of_latest_commit to obtain the timestamp of the latest commit present 15 in a svn checkout or a git clone. This information is embedded in JSON submitted to perf.webkit.org 16 so that the app can sort performance test results based on the timestamp of the last commit. 17 18 It also changes the repository names returned by port objects to be properly capitalized 19 human readable names such as WebKit instead of lowercased names such as webkit since these names 20 are displayed on perf.webkit.org for humans. Several users of this feature has been updated 21 to explicitly lowercase the names. 22 23 24 * Scripts/webkitpy/common/checkout/scm/git.py: 25 (Git.timestamp_of_latest_commit): Added. Obtains the timestamp of the last commit. Unfortunately, 26 git's timestamp granularity is seconds so we're losing some information compared to using a regular 27 subversion client. To make matters worse, git doesn't have any option to show ISO-format timestamp in 28 UTC so we're going to manually fiddle with timezone. 29 30 * Scripts/webkitpy/common/checkout/scm/scm.py: 31 (SCM.timestamp_of_latest_commit): Added. 32 33 * Scripts/webkitpy/common/checkout/scm/scm_mock.py: 34 (MockSCM.timestamp_of_latest_commit): Added. 35 36 * Scripts/webkitpy/common/checkout/scm/scm_unittest.py: 37 (test_timestamp_of_latest_commit): Added a test for Git.timestamp_of_latest_commit. 38 39 * Scripts/webkitpy/common/checkout/scm/svn.py: 40 (SVN.timestamp_of_latest_commit): Added. With svn, all we need to do is to use --xml option and parse 41 the timestamp which is always in UTC. 42 43 * Scripts/webkitpy/layout_tests/layout_package/json_results_generator.py: 44 (JSONResultsGeneratorBase._insert_generic_metadata): Lowercase the name. Note that the name 45 'chromium' needs to be substituted by 'chrome' for historical reasons. 46 47 * Scripts/webkitpy/layout_tests/port/base.py: 48 (Port.repository_paths): Return WebKit instead of webkit as noted above. 49 50 * Scripts/webkitpy/layout_tests/port/chromium.py: 51 (ChromiumPort.repository_paths): Return Chromium instead of chromium as noted above. 52 53 * Scripts/webkitpy/performance_tests/perftestsrunner.py: 54 (PerfTestsRunner.__init__): Store the current time in UTC as well as in local time. 55 (PerfTestsRunner._collect_tests): 56 57 (PerfTestsRunner._generate_and_show_results): Retrieve both regular output and one for perf.webkit.org, 58 and upload them appropriately. 59 60 (PerfTestsRunner._generate_results_dict): Store WebKit and Chromium revisions at which tests were ran 61 in revisions_for_perf_webkit and construct an output for perf.webkit.org. 62 63 (PerfTestsRunner._datetime_in_ES5_compatible_iso_format): Added. 64 65 (PerfTestsRunner._merge_slave_config_json): Merge slave configuration files into both regular output 66 and one for perf.webkit.org. Here, we prefix each key with "builder" for perf.webkit.org. 67 e.g. "processor" would be renamed to "builderProcessor". 68 69 (PerfTestsRunner._generate_output_files): 70 71 (PerfTestsRunner._upload_json): Added a remote path as an argument since we upload JSONs to /api/report 72 on perf.webkit.org whereas we upload it to /api/test/report on webkit-perf.appspot.com. Also added the code 73 to parse response as JSON when possible since perf.webkit.org returns a JSON response as opposed to 74 webkit-perf.appspot.com which spits out a plaintext response. 75 76 * Scripts/webkitpy/performance_tests/perftestsrunner_integrationtest.py: 77 (MainTest._test_run_with_json_output.mock_upload_json): Tolerate perf.webkit.org/api/report for now. 78 (MainTest._test_run_with_json_output): Store a UTC time as perftestrunner would do. 79 (MainTest.test_run_with_upload_json_should_generate_perf_webkit_json): Added. 80 81 * Scripts/webkitpy/performance_tests/perftestsrunner_unittest.py: 82 (MainTest.test_upload_json): Moved from itegrationtest.py since it really is a unit test. Also added test 83 cases to parse JSON responses. 84 (MainTest.test_upload_json.MockFileUploader): Refactored. 85 (MainTest.test_upload_json.MockFileUploader.reset): Added. 86 (MainTest.test_upload_json.MockFileUploader.__init__): 87 (MainTest.test_upload_json.MockFileUploader.upload_single_text_file): 88 1 89 2013-02-22 Roger Fong <roger_fong@apple.com> 2 90 -
trunk/Tools/Scripts/webkitpy/common/checkout/scm/git.py
r142178 r143833 28 28 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 29 30 import datetime 30 31 import logging 31 32 import os … … 253 254 return "" 254 255 return str(match.group('svn_revision')) 256 257 def timestamp_of_latest_commit(self, path): 258 git_log = self._run_git(['log', '-1', '--date=iso', self.find_checkout_root(path)]) 259 match = re.search("^Date:\s*(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2}) ([+-])(\d{2})(\d{2})$", git_log, re.MULTILINE) 260 if not match: 261 return "" 262 263 # Manually modify the timezone since Git doesn't have an option to show it in UTC. 264 # Git also truncates milliseconds but we're going to ignore that for now. 265 time_with_timezone = datetime.datetime(int(match.group(1)), int(match.group(2)), int(match.group(3)), 266 int(match.group(4)), int(match.group(5)), int(match.group(6)), 0) 267 268 sign = 1 if match.group(7) == '+' else -1 269 time_without_timezone = time_with_timezone - datetime.timedelta(hours=sign * int(match.group(8)), minutes=int(match.group(9))) 270 return time_without_timezone.strftime('%Y-%m-%dT%H:%M:%SZ') 255 271 256 272 def prepend_svn_revision(self, diff): -
trunk/Tools/Scripts/webkitpy/common/checkout/scm/scm.py
r139712 r143833 170 170 self._subclass_must_implement() 171 171 172 def timestamp_of_latest_commit(self, path): 173 self._subclass_must_implement() 174 172 175 def create_patch(self, git_commit=None, changed_files=None): 173 176 self._subclass_must_implement() -
trunk/Tools/Scripts/webkitpy/common/checkout/scm/scm_mock.py
r139712 r143833 85 85 return '5678' 86 86 87 def timestamp_of_latest_commit(self, path): 88 return '2013-02-01 08:48:05 +0000' 89 87 90 def create_patch(self, git_commit, changed_files=None): 88 91 return "Patch1" -
trunk/Tools/Scripts/webkitpy/common/checkout/scm/scm_unittest.py
r140089 r143833 1578 1578 def test_push_local_commits_to_server_without_username_and_with_password(self): 1579 1579 self.assertRaises(AuthenticationError, self.make_scm().push_local_commits_to_server, {'password': 'blah'}) 1580 1581 def test_timestamp_of_latest_commit(self): 1582 scm = self.make_scm() 1583 scm.find_checkout_root = lambda path: '' 1584 scm._run_git = lambda args: 'Date: 2013-02-08 08:05:49 +0000' 1585 self.assertEqual(scm.timestamp_of_latest_commit('some-path'), '2013-02-08T08:05:49Z') 1586 1587 scm._run_git = lambda args: 'Date: 2013-02-08 01:02:03 +0130' 1588 self.assertEqual(scm.timestamp_of_latest_commit('some-path'), '2013-02-07T23:32:03Z') 1589 1590 scm._run_git = lambda args: 'Date: 2013-02-08 01:55:21 -0800' 1591 self.assertEqual(scm.timestamp_of_latest_commit('some-path'), '2013-02-08T09:55:21Z') -
trunk/Tools/Scripts/webkitpy/common/checkout/scm/svn.py
r140508 r143833 247 247 return self.value_from_svn_info(path, 'Revision') 248 248 249 def timestamp_of_latest_commit(self, path): 250 # We use --xml to get timestamps like 2013-02-08T08:18:04.964409Z 251 info_output = Executive().run_command([self.executable_name, 'info', '--xml'], cwd=path).rstrip() 252 match = re.search(r"^<date>(?P<value>.+)</date>$", info_output, re.MULTILINE) 253 return match.group('value') 254 249 255 # FIXME: This method should be on Checkout. 250 256 def create_patch(self, git_commit=None, changed_files=None): -
trunk/Tools/Scripts/webkitpy/layout_tests/layout_package/json_results_generator.py
r130356 r143833 527 527 # Note: for JSON file's backward-compatibility we use 'chrome' rather 528 528 # than 'chromium' here. 529 if name == 'chromium': 530 name = 'chrome' 529 lowercase_name = name.lower() 530 if lowercase_name == 'chromium': 531 lowercase_name = 'chrome' 531 532 self._insert_item_into_raw_list(results_for_builder, 532 533 self._get_svn_revision(path), 533 name + 'Revision')534 lowercase_name + 'Revision') 534 535 535 536 self._insert_item_into_raw_list(results_for_builder, -
trunk/Tools/Scripts/webkitpy/layout_tests/port/base.py
r142941 r143833 1098 1098 def repository_paths(self): 1099 1099 """Returns a list of (repository_name, repository_path) tuples of its depending code base. 1100 By default it returns a list that only contains a (' webkit', <webkitRepossitoryPath>) tuple."""1101 1102 # We use LayoutTest directory here because webkit_base isn't a part webkit repository in Chromium port1100 By default it returns a list that only contains a ('WebKit', <webkitRepositoryPath>) tuple.""" 1101 1102 # We use LayoutTest directory here because webkit_base isn't a part of WebKit repository in Chromium port 1103 1103 # where turnk isn't checked out as a whole. 1104 return [(' webkit', self.layout_tests_dir())]1104 return [('WebKit', self.layout_tests_dir())] 1105 1105 1106 1106 _WDIFF_DEL = '##WDIFF_DEL##' -
trunk/Tools/Scripts/webkitpy/layout_tests/port/chromium.py
r142941 r143833 365 365 def repository_paths(self): 366 366 repos = super(ChromiumPort, self).repository_paths() 367 repos.append((' chromium', self.path_from_chromium_base('build')))367 repos.append(('Chromium', self.path_from_chromium_base('build'))) 368 368 return repos 369 369 -
trunk/Tools/Scripts/webkitpy/performance_tests/perftestsrunner.py
r138058 r143833 34 34 import optparse 35 35 import time 36 import datetime 36 37 37 38 from webkitpy.common import find_files … … 68 69 self._results = {} 69 70 self._timestamp = time.time() 71 self._utc_timestamp = datetime.datetime.utcnow() 70 72 self._needs_http = None 71 73 self._has_http_lock = False … … 127 129 128 130 def _collect_tests(self): 129 """Return the list of tests found."""130 131 131 test_extensions = ['.html', '.svg'] 132 132 if self._options.replay: … … 209 209 options = self._options 210 210 output_json_path = self._output_json_path() 211 output = self._generate_results_dict(self._timestamp, options.description, options.platform, options.builder_name, options.build_number)211 output, perf_webkit_output = self._generate_results_dict(self._timestamp, options.description, options.platform, options.builder_name, options.build_number) 212 212 213 213 if options.slave_config_json_path: 214 output = self._merge_slave_config_json(options.slave_config_json_path,output)214 output, perf_webkit_output = self._merge_slave_config_json(options.slave_config_json_path, output, perf_webkit_output) 215 215 if not output: 216 216 return self.EXIT_CODE_BAD_SOURCE_JSON … … 219 219 if not output: 220 220 return self.EXIT_CODE_BAD_MERGE 221 perf_webkit_output = [perf_webkit_output] 221 222 222 223 results_page_path = self._host.filesystem.splitext(output_json_path)[0] + '.html' 223 self._generate_output_files(output_json_path, results_page_path, output) 224 perf_webkit_json_path = self._host.filesystem.splitext(output_json_path)[0] + '-perf-webkit.json' if options.test_results_server else None 225 self._generate_output_files(output_json_path, perf_webkit_json_path, results_page_path, output, perf_webkit_output) 224 226 225 227 if options.test_results_server: 226 228 if not self._upload_json(options.test_results_server, output_json_path): 229 return self.EXIT_CODE_FAILED_UPLOADING 230 231 # FIXME: Remove this code once we've made transition to use perf.webkit.org 232 if not self._upload_json('perf.webkit.org', perf_webkit_json_path, "/api/report"): 227 233 return self.EXIT_CODE_FAILED_UPLOADING 228 234 … … 234 240 if description: 235 241 contents['description'] = description 242 243 revisions_for_perf_webkit = {} 236 244 for (name, path) in self._port.repository_paths(): 237 245 scm = SCMDetector(self._host.filesystem, self._host.executive).detect_scm_system(path) or self._host.scm() 238 contents[name + '-revision'] = scm.svn_revision(path) 246 revision = scm.svn_revision(path) 247 contents[name.lower() + '-revision'] = revision 248 revisions_for_perf_webkit[name] = {'revision': str(revision), 'timestamp': scm.timestamp_of_latest_commit(path)} 239 249 240 250 # FIXME: Add --branch or auto-detect the branch we're in … … 244 254 contents[key] = value 245 255 246 return contents 247 248 def _merge_slave_config_json(self, slave_config_json_path, output): 256 contents_for_perf_webkit = { 257 'builderName': builder_name, 258 'buildNumber': str(build_number), 259 'buildTime': self._datetime_in_ES5_compatible_iso_format(self._utc_timestamp), 260 'platform': platform, 261 'revisions': revisions_for_perf_webkit, 262 'tests': {}} 263 264 # FIXME: Make this function shorter once we've transitioned to use perf.webkit.org. 265 for metric_full_name, result in self._results.iteritems(): 266 if not isinstance(result, dict): # We can't reports results without indivisual measurements. 267 continue 268 269 assert metric_full_name.count(':') <= 1 270 test_full_name, _, metric = metric_full_name.partition(':') 271 if not metric: 272 metric = {'fps': 'FrameRate', 'runs/s': 'Runs', 'ms': 'Time'}[result['unit']] 273 274 tests = contents_for_perf_webkit['tests'] 275 path = test_full_name.split('/') 276 for i in range(0, len(path)): 277 # FIXME: We shouldn't assume HTML extension. 278 is_last_token = i + 1 == len(path) 279 url = 'http://trac.webkit.org/browser/trunk/PerformanceTests/' + '/'.join(path[0:i + 1]) 280 if is_last_token: 281 url += '.html' 282 283 tests.setdefault(path[i], {'url': url}) 284 current_test = tests[path[i]] 285 if is_last_token: 286 current_test.setdefault('metrics', {}) 287 assert metric not in current_test['metrics'] 288 current_test['metrics'][metric] = {'current': result['values']} 289 else: 290 current_test.setdefault('tests', {}) 291 tests = current_test['tests'] 292 293 return contents, contents_for_perf_webkit 294 295 @staticmethod 296 def _datetime_in_ES5_compatible_iso_format(datetime): 297 return datetime.strftime('%Y-%m-%dT%H:%M:%S.%f') 298 299 def _merge_slave_config_json(self, slave_config_json_path, contents, contents_for_perf_webkit): 249 300 if not self._host.filesystem.isfile(slave_config_json_path): 250 301 _log.error("Missing slave configuration JSON file: %s" % slave_config_json_path) 251 return None 302 return None, None 252 303 253 304 try: 254 305 slave_config_json = self._host.filesystem.open_text_file_for_reading(slave_config_json_path) 255 306 slave_config = json.load(slave_config_json) 256 return dict(slave_config.items() + output.items()) 307 contents = dict(slave_config.items() + contents.items()) 308 for key in slave_config: 309 contents_for_perf_webkit['builder' + key.capitalize()] = slave_config[key] 310 return contents, contents_for_perf_webkit 257 311 except Exception, error: 258 312 _log.error("Failed to merge slave configuration JSON file %s: %s" % (slave_config_json_path, error)) 259 return None 313 return None, None 260 314 261 315 def _merge_outputs_if_needed(self, output_json_path, output): … … 269 323 return None 270 324 271 def _generate_output_files(self, output_json_path, results_page_path,output):325 def _generate_output_files(self, output_json_path, perf_webkit_json_path, results_page_path, output, perf_webkit_output): 272 326 filesystem = self._host.filesystem 273 327 274 328 json_output = json.dumps(output) 275 329 filesystem.write_text_file(output_json_path, json_output) 330 331 if perf_webkit_json_path: 332 filesystem.write_text_file(perf_webkit_json_path, json.dumps(perf_webkit_output)) 276 333 277 334 if results_page_path: … … 285 342 filesystem.write_text_file(results_page_path, results_page) 286 343 287 def _upload_json(self, test_results_server, json_path, file_uploader=FileUploader): 288 uploader = file_uploader("https://%s/api/test/report" % test_results_server, 120) 344 def _upload_json(self, test_results_server, json_path, host_path="/api/test/report", file_uploader=FileUploader): 345 url = "https://%s%s" % (test_results_server, host_path) 346 uploader = file_uploader(url, 120) 289 347 try: 290 348 response = uploader.upload_single_text_file(self._host.filesystem, 'application/json', json_path) 291 349 except Exception, error: 292 _log.error("Failed to upload JSON file in 120s: %s" % error)350 _log.error("Failed to upload JSON file to %s in 120s: %s" % (url, error)) 293 351 return False 294 352 295 353 response_body = [line.strip('\n') for line in response] 296 354 if response_body != ['OK']: 297 _log.error("Uploaded JSON but got a bad response:") 298 for line in response_body: 299 _log.error(line) 300 return False 301 302 _log.info("JSON file uploaded.") 355 try: 356 parsed_response = json.loads('\n'.join(response_body)) 357 except: 358 _log.error("Uploaded JSON to %s but got a bad response:" % url) 359 for line in response_body: 360 _log.error(line) 361 return False 362 if parsed_response.get('status') != 'OK': 363 _log.error("Uploaded JSON to %s but got an error:" % url) 364 _log.error(json.dumps(parsed_response, indent=4)) 365 return False 366 367 _log.info("JSON file uploaded to %s." % url) 303 368 return True 304 369 -
trunk/Tools/Scripts/webkitpy/performance_tests/perftestsrunner_integrationtest.py
r140510 r143833 30 30 31 31 import StringIO 32 import datetime 32 33 import json 33 34 import re … … 322 323 uploaded = [False] 323 324 324 def mock_upload_json(hostname, json_path): 325 self.assertEqual(hostname, 'some.host') 326 self.assertEqual(json_path, '/mock-checkout/output.json') 325 def mock_upload_json(hostname, json_path, host_path=None): 326 # FIXME: Get rid of the hard-coded perf.webkit.org once we've completed the transition. 327 self.assertIn(hostname, ['some.host', 'perf.webkit.org']) 328 self.assertIn(json_path, ['/mock-checkout/output.json', '/mock-checkout/output-perf-webkit.json']) 329 self.assertIn(host_path, [None, '/api/report']) 327 330 uploaded[0] = upload_suceeds 328 331 return upload_suceeds … … 330 333 runner._upload_json = mock_upload_json 331 334 runner._timestamp = 123456789 335 runner._utc_timestamp = datetime.datetime(2013, 2, 8, 15, 19, 37, 460000) 332 336 output_capture = OutputCapture() 333 337 output_capture.capture_output() … … 522 526 self._test_run_with_json_output(runner, port.host.filesystem, upload_suceeds=False, expected_exit_code=PerfTestsRunner.EXIT_CODE_FAILED_UPLOADING) 523 527 524 def test_upload_json(self): 525 runner, port = self.create_runner() 526 port.host.filesystem.files['/mock-checkout/some.json'] = 'some content' 527 528 called = [] 529 upload_single_text_file_throws = False 530 upload_single_text_file_return_value = StringIO.StringIO('OK') 531 532 class MockFileUploader: 533 def __init__(mock, url, timeout): 534 self.assertEqual(url, 'https://some.host/api/test/report') 535 self.assertTrue(isinstance(timeout, int) and timeout) 536 called.append('FileUploader') 537 538 def upload_single_text_file(mock, filesystem, content_type, filename): 539 self.assertEqual(filesystem, port.host.filesystem) 540 self.assertEqual(content_type, 'application/json') 541 self.assertEqual(filename, 'some.json') 542 called.append('upload_single_text_file') 543 if upload_single_text_file_throws: 544 raise "Some exception" 545 return upload_single_text_file_return_value 546 547 runner._upload_json('some.host', 'some.json', MockFileUploader) 548 self.assertEqual(called, ['FileUploader', 'upload_single_text_file']) 549 550 output = OutputCapture() 551 output.capture_output() 552 upload_single_text_file_return_value = StringIO.StringIO('Some error') 553 runner._upload_json('some.host', 'some.json', MockFileUploader) 554 _, _, logs = output.restore_output() 555 self.assertEqual(logs, 'Uploaded JSON but got a bad response:\nSome error\n') 556 557 # Throwing an exception upload_single_text_file shouldn't blow up _upload_json 558 called = [] 559 upload_single_text_file_throws = True 560 runner._upload_json('some.host', 'some.json', MockFileUploader) 561 self.assertEqual(called, ['FileUploader', 'upload_single_text_file']) 528 def test_run_with_upload_json_should_generate_perf_webkit_json(self): 529 runner, port = self.create_runner_and_setup_results_template(args=['--output-json-path=/mock-checkout/output.json', 530 '--test-results-server', 'some.host', '--platform', 'platform1', '--builder-name', 'builder1', '--build-number', '123', 531 '--slave-config-json-path=/mock-checkout/slave-config.json']) 532 port.host.filesystem.write_text_file('/mock-checkout/slave-config.json', '{"key": "value1"}') 533 534 self._test_run_with_json_output(runner, port.host.filesystem, upload_suceeds=True) 535 generated_json = json.loads(port.host.filesystem.files['/mock-checkout/output-perf-webkit.json']) 536 self.assertTrue(isinstance(generated_json, list)) 537 self.assertEqual(len(generated_json), 1) 538 539 output = generated_json[0] 540 self.maxDiff = None 541 self.assertEqual(output['platform'], 'platform1') 542 self.assertEqual(output['buildNumber'], '123') 543 self.assertEqual(output['buildTime'], '2013-02-08T15:19:37.460000') 544 self.assertEqual(output['builderName'], 'builder1') 545 self.assertEqual(output['builderKey'], 'value1') 546 self.assertEqual(output['revisions'], {'WebKit': {'revision': '5678', 'timestamp': '2013-02-01 08:48:05 +0000'}}) 547 self.assertEqual(output['tests'].keys(), ['Bindings']) 548 self.assertEqual(sorted(output['tests']['Bindings'].keys()), ['tests', 'url']) 549 self.assertEqual(output['tests']['Bindings']['url'], 'http://trac.webkit.org/browser/trunk/PerformanceTests/Bindings') 550 self.assertEqual(output['tests']['Bindings']['tests'].keys(), ['event-target-wrapper']) 551 self.assertEqual(output['tests']['Bindings']['tests']['event-target-wrapper'], { 552 'url': 'http://trac.webkit.org/browser/trunk/PerformanceTests/Bindings/event-target-wrapper.html', 553 'metrics': {'Time': {'current': [1486.0, 1471.0, 1510.0, 1505.0, 1478.0, 1490.0]}}}) -
trunk/Tools/Scripts/webkitpy/performance_tests/perftestsrunner_unittest.py
r140510 r143833 35 35 36 36 from webkitpy.common.host_mock import MockHost 37 from webkitpy.common.system.outputcapture import OutputCapture 37 38 from webkitpy.layout_tests.port.test import TestPort 38 39 from webkitpy.performance_tests.perftestsrunner import PerfTestsRunner … … 148 149 self.assertEqual(options.slave_config_json_path, 'a/source.json') 149 150 self.assertEqual(options.test_results_server, 'somehost') 151 152 def test_upload_json(self): 153 runner, port = self.create_runner() 154 port.host.filesystem.files['/mock-checkout/some.json'] = 'some content' 155 156 class MockFileUploader: 157 called = [] 158 upload_single_text_file_throws = False 159 upload_single_text_file_return_value = None 160 161 @classmethod 162 def reset(cls): 163 cls.called = [] 164 cls.upload_single_text_file_throws = False 165 cls.upload_single_text_file_return_value = None 166 167 def __init__(mock, url, timeout): 168 self.assertEqual(url, 'https://some.host/some/path') 169 self.assertTrue(isinstance(timeout, int) and timeout) 170 mock.called.append('FileUploader') 171 172 def upload_single_text_file(mock, filesystem, content_type, filename): 173 self.assertEqual(filesystem, port.host.filesystem) 174 self.assertEqual(content_type, 'application/json') 175 self.assertEqual(filename, 'some.json') 176 mock.called.append('upload_single_text_file') 177 if mock.upload_single_text_file_throws: 178 raise Exception 179 return mock.upload_single_text_file_return_value 180 181 MockFileUploader.upload_single_text_file_return_value = StringIO.StringIO('OK') 182 self.assertTrue(runner._upload_json('some.host', 'some.json', '/some/path', MockFileUploader)) 183 self.assertEqual(MockFileUploader.called, ['FileUploader', 'upload_single_text_file']) 184 185 MockFileUploader.reset() 186 MockFileUploader.upload_single_text_file_return_value = StringIO.StringIO('Some error') 187 output = OutputCapture() 188 output.capture_output() 189 self.assertFalse(runner._upload_json('some.host', 'some.json', '/some/path', MockFileUploader)) 190 _, _, logs = output.restore_output() 191 self.assertEqual(logs, 'Uploaded JSON to https://some.host/some/path but got a bad response:\nSome error\n') 192 193 # Throwing an exception upload_single_text_file shouldn't blow up _upload_json 194 MockFileUploader.reset() 195 MockFileUploader.upload_single_text_file_throws = True 196 self.assertFalse(runner._upload_json('some.host', 'some.json', '/some/path', MockFileUploader)) 197 self.assertEqual(MockFileUploader.called, ['FileUploader', 'upload_single_text_file']) 198 199 MockFileUploader.reset() 200 MockFileUploader.upload_single_text_file_return_value = StringIO.StringIO('{"status": "OK"}') 201 self.assertTrue(runner._upload_json('some.host', 'some.json', '/some/path', MockFileUploader)) 202 self.assertEqual(MockFileUploader.called, ['FileUploader', 'upload_single_text_file']) 203 204 MockFileUploader.reset() 205 MockFileUploader.upload_single_text_file_return_value = StringIO.StringIO('{"status": "SomethingHasFailed", "failureStored": false}') 206 output = OutputCapture() 207 output.capture_output() 208 self.assertFalse(runner._upload_json('some.host', 'some.json', '/some/path', MockFileUploader)) 209 _, _, logs = output.restore_output() 210 serialized_json = json.dumps({'status': 'SomethingHasFailed', 'failureStored': False}, indent=4) 211 self.assertEqual(logs, 'Uploaded JSON to https://some.host/some/path but got an error:\n%s\n' % serialized_json)
Note: See TracChangeset
for help on using the changeset viewer.