Changeset 75480 in webkit
- Timestamp:
- Jan 11, 2011 2:36:36 AM (13 years ago)
- Location:
- trunk/Tools
- Files:
-
- 2 added
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Tools/ChangeLog
r75475 r75480 1 2011-01-11 Eric Seidel <eric@webkit.org> 2 3 Reviewed by Adam Barth. 4 5 commit-queue should know how to upload archived results (for test flakes or general failures) 6 https://bugs.webkit.org/show_bug.cgi?id=52048 7 8 Now the queue will always upload results. Either the entire zip, or just 9 the diffs.txt in the case of text failures. 10 11 This should make understanding flakes much easier, and paves the way 12 for having the EWS run layout tests (and upload failures). 13 14 In order to upload .zip files I had to teach bugzilla.py to autodetect 15 mime types from the filename. Since mimetypes.py doesn't include a mapping 16 for .patch files, I have it add one before calling guess_type. 17 18 We may find that always uploading the whole zip instead of just the -diffs.txt 19 file is preferable, but for now I'm keeping the old behavior because it makes 20 quickly understanding text failures easy. 21 22 * Scripts/webkitpy/common/net/bugzilla/bugzilla.py: 23 * Scripts/webkitpy/common/system/workspace.py: Added. 24 * Scripts/webkitpy/common/system/workspace_unittest.py: Added. 25 * Scripts/webkitpy/tool/bot/commitqueuetask.py: 26 * Scripts/webkitpy/tool/bot/commitqueuetask_unittest.py: 27 * Scripts/webkitpy/tool/bot/flakytestreporter.py: 28 * Scripts/webkitpy/tool/bot/flakytestreporter_unittest.py: 29 * Scripts/webkitpy/tool/commands/queues.py: 30 * Scripts/webkitpy/tool/commands/queues_unittest.py: 31 1 32 2011-01-10 Sheriff Bot <webkit.review.bot@gmail.com> 2 33 -
trunk/Tools/Scripts/webkitpy/common/net/bugzilla/bugzilla.py
r74138 r75480 31 31 # WebKit's Python module for interacting with Bugzilla 32 32 33 import mimetypes 33 34 import os.path 34 35 import re … … 442 443 443 444 filename = filename or "%s.patch" % timestamp() 444 mimetype = mimetype or "text/plain" 445 if not mimetype: 446 mimetypes.add_type('text/plain', '.patch') # Make sure mimetypes knows about .patch 447 mimetype, _ = mimetypes.guess_type(filename) 448 if not mimetype: 449 mimetype = "text/plain" # Bugzilla might auto-guess for us and we might not need this? 445 450 self.browser.add_file(file_object, mimetype, filename, 'data') 446 451 -
trunk/Tools/Scripts/webkitpy/tool/bot/commitqueuetask.py
r75366 r75480 47 47 raise NotImplementedError("subclasses must implement") 48 48 49 def report_flaky_tests(self, patch, flaky_tests): 49 def archive_last_layout_test_results(self, patch): 50 raise NotImplementedError("subclasses must implement") 51 52 # We could make results_archive optional, but for now it's required. 53 def report_flaky_tests(self, patch, flaky_tests, results_archive): 50 54 raise NotImplementedError("subclasses must implement") 51 55 … … 171 175 "Unable to land patch") 172 176 173 def _report_flaky_tests(self, flaky_test_results ):174 self._delegate.report_flaky_tests(self._patch, flaky_test_results )177 def _report_flaky_tests(self, flaky_test_results, results_archive): 178 self._delegate.report_flaky_tests(self._patch, flaky_test_results, results_archive) 175 179 176 180 def _test_patch(self): … … 180 184 return True 181 185 182 first_failing_results = self._failing_results_from_last_run() 183 first_failing_tests = [result.filename for result in first_failing_results] 186 first_results = self._failing_results_from_last_run() 187 first_failing_tests = [result.filename for result in first_results] 188 first_results_archive = self._delegate.archive_last_layout_test_results(self._patch) 184 189 if self._test(): 185 self._report_flaky_tests(first_ failing_results)186 return True 187 188 second_ failing_results = self._failing_results_from_last_run()189 second_failing_tests = [result.filename for result in second_ failing_results]190 self._report_flaky_tests(first_results, first_results_archive) 191 return True 192 193 second_results = self._failing_results_from_last_run() 194 second_failing_tests = [result.filename for result in second_results] 190 195 if first_failing_tests != second_failing_tests: 191 196 # We could report flaky tests here, but since run-webkit-tests -
trunk/Tools/Scripts/webkitpy/tool/bot/commitqueuetask_unittest.py
r75366 r75480 66 66 return None 67 67 68 def report_flaky_tests(self, patch, flaky_results ):68 def report_flaky_tests(self, patch, flaky_results, results_archive): 69 69 flaky_tests = [result.filename for result in flaky_results] 70 log("report_flaky_tests: patch='%s' flaky_tests='%s'" % (patch.id(), flaky_tests)) 70 log("report_flaky_tests: patch='%s' flaky_tests='%s' archive='%s'" % (patch.id(), flaky_tests, results_archive.filename)) 71 72 def archive_last_layout_test_results(self, patch): 73 log("archive_last_layout_test_results: patch='%s'" % patch.id()) 74 archive = Mock() 75 archive.filename = "mock-archive-%s.zip" % patch.id() 76 return archive 71 77 72 78 … … 195 201 run_webkit_patch: ['build-and-test', '--no-clean', '--no-update', '--test', '--non-interactive'] 196 202 command_failed: failure_message='Patch does not pass tests' script_error='MOCK tests failure' patch='197' 203 archive_last_layout_test_results: patch='197' 197 204 run_webkit_patch: ['build-and-test', '--no-clean', '--no-update', '--test', '--non-interactive'] 198 205 command_passed: success_message='Passed tests' patch='197' 199 report_flaky_tests: patch='197' flaky_tests='[]' 206 report_flaky_tests: patch='197' flaky_tests='[]' archive='mock-archive-197.zip' 200 207 run_webkit_patch: ['land-attachment', '--force-clean', '--ignore-builders', '--non-interactive', '--parent-command=commit-queue', 197] 201 208 command_passed: success_message='Landed patch' patch='197' … … 227 234 run_webkit_patch: ['build-and-test', '--no-clean', '--no-update', '--test', '--non-interactive'] 228 235 command_failed: failure_message='Patch does not pass tests' script_error='MOCK test failure' patch='197' 236 archive_last_layout_test_results: patch='197' 229 237 run_webkit_patch: ['build-and-test', '--no-clean', '--no-update', '--test', '--non-interactive'] 230 238 command_failed: failure_message='Patch does not pass tests' script_error='MOCK test failure again' patch='197' … … 264 272 run_webkit_patch: ['build-and-test', '--no-clean', '--no-update', '--test', '--non-interactive'] 265 273 command_failed: failure_message='Patch does not pass tests' script_error='MOCK test failure' patch='197' 274 archive_last_layout_test_results: patch='197' 266 275 run_webkit_patch: ['build-and-test', '--no-clean', '--no-update', '--test', '--non-interactive'] 267 276 command_failed: failure_message='Patch does not pass tests' script_error='MOCK test failure again' patch='197' … … 291 300 run_webkit_patch: ['build-and-test', '--no-clean', '--no-update', '--test', '--non-interactive'] 292 301 command_failed: failure_message='Patch does not pass tests' script_error='MOCK test failure' patch='197' 302 archive_last_layout_test_results: patch='197' 293 303 run_webkit_patch: ['build-and-test', '--no-clean', '--no-update', '--test', '--non-interactive'] 294 304 command_failed: failure_message='Patch does not pass tests' script_error='MOCK test failure again' patch='197' -
trunk/Tools/Scripts/webkitpy/tool/bot/flakytestreporter.py
r75114 r75480 132 132 return "%s\n%s" % (flake_message, self._bot_information()) 133 133 134 def _results_diff_path_for_test(self, flaky_test):134 def _results_diff_path_for_test(self, test_path): 135 135 # FIXME: This is a big hack. We should get this path from results.json 136 136 # except that old-run-webkit-tests doesn't produce a results.json 137 137 # so we just guess at the file path. 138 results_path = self._tool.port().layout_tests_results_path()139 results_directory = os.path.dirname(results_path)140 test_path = os.path.join(results_directory, flaky_test)141 138 (test_path_root, _) = os.path.splitext(test_path) 142 139 return "%s-diffs.txt" % test_path_root … … 154 151 self._tool.bugs.post_comment_to_bug(bug.id(), latest_flake_message) 155 152 156 def report_flaky_tests(self, flaky_test_results, patch): 153 def _attach_failure_diff(self, flake_bug_id, flaky_test, results_archive): 154 results_diff_path = self._results_diff_path_for_test(flaky_test) 155 # Check to make sure that the path makes sense. 156 # Since we're not actually getting this path from the results.html 157 # there is a chance it's wrong. 158 bot_id = self._tool.status_server.bot_id or "bot" 159 if results_diff_path in results_archive.namelist(): 160 results_diff = results_archive.read(results_diff_path) 161 description = "Failure diff from %s" % bot_id 162 self._tool.bugs.add_attachment_to_bug(flake_bug_id, results_diff, description, filename="failure.diff") 163 else: 164 _log.warn("%s does not exist in results archive, uploading entire archive." % results_diff_path) 165 description = "Archive of layout-test-results from %s" % bot_id 166 # results_archive is a ZipFile object, grab the File object (.fp) to pass to Mechanize for uploading. 167 self._tool.bugs.add_attachment_to_bug(flake_bug_id, results_archive.fp, description, filename="layout-test-results.zip") 168 169 def report_flaky_tests(self, patch, flaky_test_results, results_archive): 157 170 message = "The %s encountered the following flaky tests while processing attachment %s:\n\n" % (self._bot_name, patch.id()) 158 171 for flaky_result in flaky_test_results: … … 166 179 else: 167 180 bug = self._follow_duplicate_chain(bug) 181 # FIXME: Ideally we'd only make one comment per flake, not two. But that's not possible 182 # in all cases (e.g. when reopening), so for now file attachment and comment are separate. 168 183 self._update_bug_for_flaky_test(bug, latest_flake_message) 169 184 flake_bug_id = bug.id() 170 # FIXME: Ideally we'd only make one comment per flake, not two. But that's not possible 171 # in all cases (e.g. when reopening), so for now we do the attachment in a second step. 172 results_diff_path = self._results_diff_path_for_test(flaky_test) 173 # Check to make sure that the path makes sense. 174 # Since we're not actually getting this path from the results.html 175 # there is a high probaility it's totally wrong. 176 if self._tool.filesystem.exists(results_diff_path): 177 results_diff = self._tool.filesystem.read_binary_file(results_diff_path) 178 bot_id = self._tool.status_server.bot_id or "bot" 179 self._tool.bugs.add_attachment_to_bug(flake_bug_id, results_diff, "Failure diff from %s" % bot_id, filename="failure.diff") 180 else: 181 _log.error("%s does not exist as expected, not uploading." % results_diff_path) 185 186 self._attach_failure_diff(flake_bug_id, flaky_test, results_archive) 182 187 message += "%s bug %s%s\n" % (flaky_test, flake_bug_id, self._optional_author_string(author_emails)) 183 188 -
trunk/Tools/Scripts/webkitpy/tool/bot/flakytestreporter_unittest.py
r75114 r75480 34 34 from webkitpy.layout_tests.layout_package import test_results 35 35 from webkitpy.layout_tests.layout_package import test_failures 36 from webkitpy.thirdparty.mock import Mock 36 37 from webkitpy.tool.bot.flakytestreporter import FlakyTestReporter 37 38 from webkitpy.tool.mocktool import MockTool, MockStatusServer … … 141 142 """ 142 143 test_results = [self._mock_test_result('foo/bar.html')] 143 OutputCapture().assert_outputs(self, reporter.report_flaky_tests, [test_results, patch], expected_stderr=expected_stderr) 144 145 class MockZipFile(object): 146 def read(self, path): 147 return "" 148 149 def namelist(self): 150 return ['foo/bar-diffs.txt'] 151 152 OutputCapture().assert_outputs(self, reporter.report_flaky_tests, [patch, test_results, MockZipFile()], expected_stderr=expected_stderr) 144 153 145 154 def test_optional_author_string(self): … … 151 160 def test_results_diff_path_for_test(self): 152 161 reporter = FlakyTestReporter(MockTool(), 'dummy-queue') 153 self.assertEqual(reporter._results_diff_path_for_test("test.html"), " /mock/test-diffs.txt")162 self.assertEqual(reporter._results_diff_path_for_test("test.html"), "test-diffs.txt") 154 163 155 164 # report_flaky_tests is also tested by queues_unittest -
trunk/Tools/Scripts/webkitpy/tool/commands/queues.py
r75149 r75480 310 310 return LayoutTestResults.results_from_string(results_html) 311 311 312 def _results_directory(self): 313 results_path = self._tool.port().layout_tests_results_path() 314 # FIXME: This is wrong in two ways: 315 # 1. It assumes that results.html is at the top level of the results tree. 316 # 2. This uses the "old" ports.py infrastructure instead of the new layout_tests/port 317 # which will not support Chromium. However the new arch doesn't work with old-run-webkit-tests 318 # so we have to use this for now. 319 return os.path.dirname(results_path) 320 321 def archive_last_layout_test_results(self, patch): 322 results_directory = self._results_directory() 323 results_name, _ = os.path.splitext(os.path.basename(results_directory)) 324 # Note: We name the zip with the bug_id instead of patch_id to match work_item_log_path(). 325 zip_path = self._tool.workspace.find_unused_filename(self._log_directory(), "%s-%s" % (patch.bug_id(), results_name), "zip") 326 self._tool.workspace.create_zip(zip_path, results_directory) 327 return zip_path 328 312 329 def refetch_patch(self, patch): 313 330 return self._tool.bugs.fetch_attachment(patch.id()) 314 331 315 def report_flaky_tests(self, patch, flaky_test_results ):332 def report_flaky_tests(self, patch, flaky_test_results, results_archive=None): 316 333 reporter = FlakyTestReporter(self._tool, self.name) 317 reporter.report_flaky_tests( flaky_test_results, patch)334 reporter.report_flaky_tests(patch, flaky_test_results, results_archive) 318 335 319 336 # StepSequenceErrorHandler methods -
trunk/Tools/Scripts/webkitpy/tool/commands/queues_unittest.py
r75149 r75480 28 28 29 29 import os 30 import StringIO 30 31 31 32 from webkitpy.common.checkout.scm import CheckoutNeedsUpdate 32 33 from webkitpy.common.net.bugzilla import Attachment 34 from webkitpy.common.system.filesystem_mock import MockFileSystem 33 35 from webkitpy.common.system.outputcapture import OutputCapture 34 36 from webkitpy.layout_tests.layout_package import test_results … … 343 345 --- End comment --- 344 346 347 MOCK add_attachment_to_bug: bug_id=76, description=Failure diff from bot filename=failure.diff 345 348 MOCK bug comment: bug_id=76, cc=None 346 349 --- Begin comment --- … … 349 352 --- End comment --- 350 353 354 MOCK add_attachment_to_bug: bug_id=76, description=Archive of layout-test-results from bot filename=layout-test-results.zip 351 355 MOCK bug comment: bug_id=42, cc=None 352 356 --- Begin comment --- … … 361 365 test_names = ["foo/bar.html", "bar/baz.html"] 362 366 test_results = [self._mock_test_result(name) for name in test_names] 363 OutputCapture().assert_outputs(self, queue.report_flaky_tests, [QueuesTest.mock_work_item, test_results], expected_stderr=expected_stderr) 367 368 class MockZipFile(object): 369 def __init__(self): 370 self.fp = StringIO() 371 372 def read(self, path): 373 return "" 374 375 def namelist(self): 376 # This is intentionally missing one diffs.txt to exercise the "upload the whole zip" codepath. 377 return ['foo/bar-diffs.txt'] 378 379 OutputCapture().assert_outputs(self, queue.report_flaky_tests, [QueuesTest.mock_work_item, test_results, MockZipFile()], expected_stderr=expected_stderr) 364 380 365 381 def test_layout_test_results(self): … … 371 387 self.assertEquals(queue.layout_test_results(), None) 372 388 389 def test_archive_last_layout_test_results(self): 390 queue = CommitQueue() 391 queue.bind_to_tool(MockTool()) 392 patch = queue._tool.bugs.fetch_attachment(128) 393 queue.archive_last_layout_test_results(patch) 394 373 395 374 396 class StyleQueueTest(QueuesTest): -
trunk/Tools/Scripts/webkitpy/tool/main.py
r74138 r75480 41 41 from webkitpy.common.net.irc.ircproxy import IRCProxy 42 42 from webkitpy.common.net.statusserver import StatusServer 43 from webkitpy.common.system.executive import Executive 44 from webkitpy.common.system.filesystem import FileSystem 45 from webkitpy.common.system.platforminfo import PlatformInfo 46 from webkitpy.common.system.user import User 43 from webkitpy.common.system import executive, filesystem, platforminfo, user, workspace 47 44 from webkitpy.layout_tests import port 48 45 from webkitpy.tool.multicommandtool import MultiCommandTool … … 71 68 self.bugs = Bugzilla() 72 69 self.buildbot = BuildBot() 73 self.executive = Executive()70 self.executive = executive.Executive() 74 71 self._irc = None 75 self.filesystem = FileSystem() 72 self.filesystem = filesystem.FileSystem() 73 self.workspace = workspace.Workspace(self.filesystem, self.executive) 76 74 self._port = None 77 self.user = User()75 self.user = user.User() 78 76 self._scm = None 79 77 self._checkout = None 80 78 self.status_server = StatusServer() 81 79 self.port_factory = port.factory 82 self.platform = PlatformInfo()80 self.platform = platforminfo.PlatformInfo() 83 81 84 82 def scm(self): -
trunk/Tools/Scripts/webkitpy/tool/mocktool.py
r74927 r75480 687 687 688 688 689 class MockWorkspace(object): 690 def find_unused_filename(self, directory, name, extension, search_limit=10): 691 return "%s/%s.%s" % (directory, name, extension) 692 693 def create_zip(self, zip_path, source_path): 694 pass 695 696 689 697 class MockTool(object): 690 698 … … 695 703 self.executive = MockExecutive(should_log=log_executive) 696 704 self.filesystem = MockFileSystem() 705 self.workspace = MockWorkspace() 697 706 self._irc = None 698 707 self.user = MockUser()
Note: See TracChangeset
for help on using the changeset viewer.