Make slider tick mark snapping threshold configurable for each platform
[WebKit-https.git] / Tools / Scripts / webkitpy / tool / commands / earlywarningsystem.py
1 # Copyright (c) 2009 Google Inc. All rights reserved.
2 #
3 # Redistribution and use in source and binary forms, with or without
4 # modification, are permitted provided that the following conditions are
5 # met:
6 #
7 #     * Redistributions of source code must retain the above copyright
8 # notice, this list of conditions and the following disclaimer.
9 #     * Redistributions in binary form must reproduce the above
10 # copyright notice, this list of conditions and the following disclaimer
11 # in the documentation and/or other materials provided with the
12 # distribution.
13 #     * Neither the name of Google Inc. nor the names of its
14 # contributors may be used to endorse or promote products derived from
15 # this software without specific prior written permission.
16 #
17 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29 from optparse import make_option
30
31 from webkitpy.common.config.committers import CommitterList
32 from webkitpy.common.config.ports import DeprecatedPort
33 from webkitpy.common.system.deprecated_logging import error, log
34 from webkitpy.common.system.executive import ScriptError
35 from webkitpy.tool.bot.earlywarningsystemtask import EarlyWarningSystemTask, EarlyWarningSystemTaskDelegate
36 from webkitpy.tool.bot.expectedfailures import ExpectedFailures
37 from webkitpy.tool.bot.layouttestresultsreader import LayoutTestResultsReader
38 from webkitpy.tool.bot.patchanalysistask import UnableToApplyPatch
39 from webkitpy.tool.bot.queueengine import QueueEngine
40 from webkitpy.tool.commands.queues import AbstractReviewQueue
41
42
43 class AbstractEarlyWarningSystem(AbstractReviewQueue, EarlyWarningSystemTaskDelegate):
44     _build_style = "release"
45     # FIXME: Switch _default_run_tests from opt-in to opt-out once more bots are ready to run tests.
46     _default_run_tests = False
47
48     def __init__(self):
49         options = [make_option("--run-tests", action="store_true", dest="run_tests", default=self._default_run_tests, help="Run the Layout tests for each patch")]
50         AbstractReviewQueue.__init__(self, options=options)
51         self.port = DeprecatedPort.port(self.port_name)
52
53     def begin_work_queue(self):
54         # FIXME: This violates abstraction
55         self._tool._deprecated_port = self.port
56         AbstractReviewQueue.begin_work_queue(self)
57         self._expected_failures = ExpectedFailures()
58         self._layout_test_results_reader = LayoutTestResultsReader(self._tool, self._log_directory())
59
60     def _failing_tests_message(self, task, patch):
61         results = task.results_from_patch_test_run(patch)
62         unexpected_failures = self._expected_failures.unexpected_failures_observed(results)
63         if not unexpected_failures:
64             return None
65         return "New failing tests:\n%s" % "\n".join(unexpected_failures)
66
67     def _post_reject_message_on_bug(self, tool, patch, status_id, extra_message_text=None):
68         results_link = tool.status_server.results_url_for_status(status_id)
69         message = "Attachment %s did not pass %s (%s):\nOutput: %s" % (patch.id(), self.name, self.port_name, results_link)
70         # FIXME: We might want to add some text about rejecting from the commit-queue in
71         # the case where patch.commit_queue() isn't already set to '-'.
72         if self.watchers:
73             tool.bugs.add_cc_to_bug(patch.bug_id(), self.watchers)
74         tool.bugs.set_flag_on_attachment(patch.id(), "commit-queue", "-", message, extra_message_text)
75
76     def review_patch(self, patch):
77         task = EarlyWarningSystemTask(self, patch, self._options.run_tests)
78         if not task.validate():
79             self._did_error(patch, "%s did not process patch." % self.name)
80             return False
81         try:
82             return task.run()
83         except UnableToApplyPatch, e:
84             self._did_error(patch, "%s unable to apply patch." % self.name)
85             return False
86         except ScriptError, e:
87             self._post_reject_message_on_bug(self._tool, patch, task.failure_status_id, self._failing_tests_message(task, patch))
88             results_archive = task.results_archive_from_patch_test_run(patch)
89             if results_archive:
90                 self._upload_results_archive_for_patch(patch, results_archive)
91             self._did_fail(patch)
92             # FIXME: We're supposed to be able to raise e again here and have
93             # one of our base classes mark the patch as fail, but there seems
94             # to be an issue with the exit_code.
95             return False
96
97     # EarlyWarningSystemDelegate methods
98
99     def parent_command(self):
100         return self.name
101
102     def run_command(self, command):
103         self.run_webkit_patch(command + [self.port.flag()])
104
105     def command_passed(self, message, patch):
106         pass
107
108     def command_failed(self, message, script_error, patch):
109         failure_log = self._log_from_script_error_for_upload(script_error)
110         return self._update_status(message, patch=patch, results_file=failure_log)
111
112     def expected_failures(self):
113         return self._expected_failures
114
115     def test_results(self):
116         return self._layout_test_results_reader.results()
117
118     def archive_last_test_results(self, patch):
119         return self._layout_test_results_reader.archive(patch)
120
121     def build_style(self):
122         return self._build_style
123
124     def refetch_patch(self, patch):
125         return self._tool.bugs.fetch_attachment(patch.id())
126
127     def report_flaky_tests(self, patch, flaky_test_results, results_archive):
128         pass
129
130     # StepSequenceErrorHandler methods
131
132     @classmethod
133     def handle_script_error(cls, tool, state, script_error):
134         # FIXME: Why does this not exit(1) like the superclass does?
135         log(script_error.message_with_output())
136
137
138 class GtkEWS(AbstractEarlyWarningSystem):
139     name = "gtk-ews"
140     port_name = "gtk"
141     watchers = AbstractEarlyWarningSystem.watchers + [
142         "gns@gnome.org",
143         "xan.lopez@gmail.com",
144     ]
145
146
147 class EflEWS(AbstractEarlyWarningSystem):
148     name = "efl-ews"
149     port_name = "efl"
150     watchers = AbstractEarlyWarningSystem.watchers + [
151         "leandro@profusion.mobi",
152         "antognolli@profusion.mobi",
153         "lucas.demarchi@profusion.mobi",
154         "gyuyoung.kim@samsung.com",
155     ]
156
157
158 class QtEWS(AbstractEarlyWarningSystem):
159     name = "qt-ews"
160     port_name = "qt"
161
162
163 class QtWK2EWS(AbstractEarlyWarningSystem):
164     name = "qt-wk2-ews"
165     port_name = "qt"
166
167
168 class WinEWS(AbstractEarlyWarningSystem):
169     name = "win-ews"
170     port_name = "win"
171     # Use debug, the Apple Win port fails to link Release on 32-bit Windows.
172     # https://bugs.webkit.org/show_bug.cgi?id=39197
173     _build_style = "debug"
174
175
176 class AbstractChromiumEWS(AbstractEarlyWarningSystem):
177     port_name = "chromium"
178     watchers = AbstractEarlyWarningSystem.watchers + [
179         "dglazkov@chromium.org",
180     ]
181
182
183 class ChromiumLinuxEWS(AbstractChromiumEWS):
184     # FIXME: We should rename this command to cr-linux-ews, but that requires
185     #        a database migration. :(
186     name = "chromium-ews"
187     port_name = "chromium-xvfb"
188     _default_run_tests = True
189
190
191 class ChromiumWindowsEWS(AbstractChromiumEWS):
192     name = "cr-win-ews"
193
194
195 class ChromiumAndroidEWS(AbstractChromiumEWS):
196     name = "cr-android-ews"
197     watchers = AbstractChromiumEWS.watchers + [
198         "peter+ews@chromium.org",
199     ]
200
201
202 class MacEWS(AbstractEarlyWarningSystem):
203     name = "mac-ews"
204     port_name = "mac"
205     _default_run_tests = True