# Copyright (C) 2019 Apple Inc. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from webkitcorepy import BytesIO import json import requests import sys import time import unittest try: from collections.abc import Iterable, Mapping except ImportError: from collections import Iterable, Mapping from webkitpy.results.upload import Upload from webkitpy.thirdparty import mock if sys.version_info > (3, 0): basestring = str class UploadTest(unittest.TestCase): class Options(object): def __init__(self, **kwargs): for key, value in kwargs.items(): setattr(self, key, value) class MockResponse(object): def __init__(self, status_code=200, text=''): self.status_code = status_code self.text = text def json(self): return json.loads(self.text) @staticmethod def normalize(data): if isinstance(data, basestring): return str(data) elif isinstance(data, Mapping): return dict(map(UploadTest.normalize, data.items())) elif isinstance(data, Iterable): return type(data)(map(UploadTest.normalize, data)) return data @staticmethod def raise_requests_ConnectionError(): raise requests.exceptions.ConnectionError() def test_encoding(self): start_time, end_time = time.time() - 3, time.time() upload = Upload( suite='webkitpy-tests', configuration=Upload.create_configuration( platform='mac', version='10.13.0', version_name='High Sierra', architecture='x86_64', sdk='17A405', ), details=Upload.create_details(link='https://webkit.org'), commits=[Upload.create_commit( repository_id='webkit', id='5', branch='trunk', )], run_stats=Upload.create_run_stats( start_time=start_time, end_time=end_time, tests_skipped=0, ), results={ 'webkitpy.test1': {}, 'webkitpy.test2': Upload.create_test_result(expected=Upload.Expectations.PASS, actual=Upload.Expectations.FAIL), }, ) generated_dict = self.normalize(json.loads(json.dumps(upload, cls=Upload.Encoder))) self.assertEqual(generated_dict['version'], 0) self.assertEqual(generated_dict['suite'], 'webkitpy-tests') self.assertEqual(generated_dict['configuration'], self.normalize(dict( platform='mac', is_simulator=False, version='10.13.0', version_name='High Sierra', architecture='x86_64', sdk='17A405', ))) self.assertEqual(generated_dict['commits'], [dict( repository_id='webkit', id='5', branch='trunk', )]) self.assertEqual(generated_dict['test_results']['details'], self.normalize(dict(link='https://webkit.org'))) self.assertEqual(generated_dict['test_results']['run_stats'], self.normalize(dict( start_time=start_time, end_time=end_time, tests_skipped=0, ))) self.assertEqual(generated_dict['test_results']['results'], self.normalize({ 'webkitpy.test1': {}, 'webkitpy.test2': Upload.create_test_result(expected=Upload.Expectations.PASS, actual=Upload.Expectations.FAIL), })) def test_upload(self): upload = Upload( suite='webkitpy-tests', commits=[Upload.create_commit( repository_id='webkit', id='5', branch='trunk', )], ) with mock.patch('requests.post', new=lambda url, headers={}, data={}, verify=True: self.MockResponse()): self.assertTrue(upload.upload('https://results.webkit.org', log_line_func=lambda _: None)) with mock.patch('requests.post', new=lambda url, headers={}, data={}, verify=True: self.raise_requests_ConnectionError()): lines = [] self.assertFalse(upload.upload('https://results.webkit.org', log_line_func=lambda line: lines.append(line))) self.assertEqual([' ' * 4 + 'Failed to upload to https://results.webkit.org, results server not online'], lines) mock_404 = mock.patch('requests.post', new=lambda url, headers={}, data={}, verify=True: self.MockResponse( status_code=404, text=json.dumps(dict(description='No such address')), )) with mock_404: self.assertFalse(upload.upload('https://results.webkit.org', log_line_func=lambda _: None)) def test_packed_test(self): upload = Upload( suite='webkitpy-tests', commits=[Upload.create_commit( repository_id='webkit', id='5', branch='trunk', )], results={ 'dir1/sub-dir1/test1': Upload.create_test_result(actual=Upload.Expectations.FAIL), 'dir1/sub-dir1/test2': Upload.create_test_result(actual=Upload.Expectations.TIMEOUT), 'dir1/sub-dir2/test3': {}, 'dir1/sub-dir2/test4': {}, 'dir2/sub-dir3/test5': {}, 'dir2/test6': {}, } ) generated_dict = self.normalize(json.loads(json.dumps(upload, cls=Upload.Encoder))) self.assertEqual(generated_dict['test_results']['results'], self.normalize({ 'dir1': { 'sub-dir1': { 'test1': {'actual': Upload.Expectations.FAIL}, 'test2': {'actual': Upload.Expectations.TIMEOUT}, }, 'sub-dir2': { 'test3': {}, 'test4': {}, } }, 'dir2': { 'sub-dir3': {'test5': {}}, 'test6': {}, }, })) def test_no_suite(self): upload = Upload( commits=[Upload.create_commit( repository_id='webkit', id='5', branch='trunk', )], ) with self.assertRaises(ValueError): json.dumps(upload, cls=Upload.Encoder) def test_no_commits(self): upload = Upload( suite='webkitpy-tests', ) with self.assertRaises(ValueError): json.dumps(upload, cls=Upload.Encoder) def test_buildbot(self): upload = Upload( suite='webkitpy-tests', commits=[Upload.create_commit( repository_id='webkit', id='5', branch='trunk', )], details=Upload.create_details(options=self.Options( buildbot_master='webkit.org', builder_name='Queue-1', build_number=1, ))) with self.assertRaises(ValueError): json.dumps(upload, cls=Upload.Encoder) upload.details['buildbot-worker'] = 'bot123' generated_dict = self.normalize(json.loads(json.dumps(upload, cls=Upload.Encoder))) self.assertEqual(generated_dict['test_results']['details'], self.normalize({ 'buildbot-master': 'webkit.org', 'builder-name': 'Queue-1', 'build-number': 1, 'buildbot-worker': 'bot123', })) def test_archive_upload(self): upload = Upload( suite='webkitpy-tests', commits=[Upload.create_commit( repository_id='webkit', id='5', branch='trunk', )], ) with mock.patch('requests.post', new=lambda url, headers={}, data={}, files={}, verify=True: self.MockResponse()): self.assertTrue(upload.upload_archive('https://results.webkit.org', archive=BytesIO(b'content'), log_line_func=lambda _: None)) with mock.patch('requests.post', new=lambda url, headers={}, data={}, files={}, verify=True: self.raise_requests_ConnectionError()): lines = [] self.assertTrue(upload.upload_archive('https://results.webkit.org', archive=BytesIO(b'content'), log_line_func=lambda line: lines.append(line))) self.assertEqual([ ' ' * 4 + 'Failed to upload test archive to https://results.webkit.org, results server dropped connection, likely due to archive size (0.0 MB).', ' ' * 4 + 'This error is not fatal, continuing' ], lines) mock_404 = mock.patch('requests.post', new=lambda url, headers={}, data={}, files={}, verify=True: self.MockResponse( status_code=404, text=json.dumps(dict(description='No such address')), )) with mock_404: lines = [] self.assertFalse(upload.upload_archive('https://results.webkit.org', archive='content', log_line_func=lambda line: lines.append(line))) self.assertEqual([ ' ' * 4 + 'Error uploading archive to https://results.webkit.org', ' ' * 8 + 'No such address', ], lines) mock_413 = mock.patch('requests.post', new=lambda url, headers={}, data={}, files={}, verify=True: self.MockResponse( status_code=413, text=json.dumps(dict(description='Request Entity Too Large')), )) with mock_413: lines = [] self.assertTrue(upload.upload_archive('https://results.webkit.org', archive='content', log_line_func=lambda line: lines.append(line))) self.assertEqual([ ' ' * 4 + 'Upload to https://results.webkit.org failed:', ' ' * 8 + 'Request Entity Too Large', ' ' * 4 + 'This error is not fatal, continuing', ], lines)