Diff
Modified: trunk/Tools/ChangeLog (122233 => 122234)
--- trunk/Tools/ChangeLog 2012-07-10 17:05:24 UTC (rev 122233)
+++ trunk/Tools/ChangeLog 2012-07-10 17:33:41 UTC (rev 122234)
@@ -1,3 +1,84 @@
+2012-07-09 Ojan Vafai <[email protected]>
+
+ Improve webkit-patch rebaseline to work for more cases
+ https://bugs.webkit.org/show_bug.cgi?id=90504
+
+ Reviewed by Adam Barth.
+
+ -Makes it work for the build.chromium.org bots.
+ -Lets you rebaseline all builders instead of just one.
+ -Lets you pass in the builders or tests to rebaseline.
+
+ * Scripts/webkitpy/common/host.py:
+ (Host.buildbot_for_builder_name):
+ * Scripts/webkitpy/common/net/buildbot/buildbot.py:
+ (Builder.__init__):
+ (Builder.latest_layout_test_results):
+ Provide a way to get to the LayoutTestResults of the latest build.
+ Most of the time we only need to get the latest one and the Chromium bots
+ only expose the full_results.json file for the latest build.
+
+ (Builder):
+ (Builder._fetch_file_from_results):
+ (Builder.fetch_layout_test_results):
+ Move these functions into Builder so that Builder and Build can both
+ fetch layout test results.
+
+ (Build.results_zip_url):
+ (Build.layout_test_results):
+ * Scripts/webkitpy/common/net/buildbot/buildbot_unittest.py:
+ (BuilderTest.test_latest_layout_test_results):
+ (BuildTest.test_layout_test_results):
+ * Scripts/webkitpy/common/system/user.py:
+ (User.prompt_with_multiple_lists):
+ Prompt with multiple sublists, but still have a global numbering.
+ This lets the build.chromium.org bots be clearly separated from the
+ build.webkit.org bots, which helps understand the builder names.
+
+ (User):
+ (User._wait_on_list_response):
+ (User.prompt_with_list):
+ * Scripts/webkitpy/common/system/user_unittest.py:
+ (UserTest.test_prompt_with_multiple_lists):
+ (UserTest.test_prompt_with_multiple_lists.run_prompt_test):
+ (UserTest.test_prompt_with_multiple_lists.run_prompt_test.mock_raw_input):
+ * Scripts/webkitpy/layout_tests/port/base.py:
+ (Port.is_chromium):
+ Provide a way to tell if a port is a Chromium port that doesn't involve string
+ manipulation on the port name or builder name.
+
+ * Scripts/webkitpy/layout_tests/port/builders.py:
+ (builder_path_from_name):
+ (all_builder_names):
+ Memoizing here is incorrect because the test override _exact_matches,
+ so these can return different values. In either case, I'm pretty sure these
+ are not remotely hot codepaths. I manually inspected all call sites and they're
+ all in high-level calls (e.g. execute calls for webkit-patch commands) and not
+ called in a loop.
+
+ * Scripts/webkitpy/layout_tests/port/chromium.py:
+ (ChromiumPort.is_chromium):
+ * Scripts/webkitpy/tool/commands/rebaseline.py:
+ (RebaselineTest._results_url):
+ (AbstractParallelRebaselineCommand.__init__):
+ (Rebaseline.__init__):
+ (Rebaseline):
+ (Rebaseline._builders_to_pull_from):
+ (Rebaseline._tests_to_update):
+ (Rebaseline.execute):
+ * Scripts/webkitpy/tool/commands/rebaseline_unittest.py:
+ (test_rebaseline.mock_builders_to_pull_from):
+ (test_rebaseline):
+ (test_rebaseline_command_line_flags):
+ (test_rebaseline_multiple_builders):
+ (test_rebaseline_multiple_builders.mock_builders_to_pull_from):
+ (test_rebaseline_multiple_builders.mock_tests_to_update):
+ (test_rebaseline_multiple_builders_and_tests_command_line):
+ * Scripts/webkitpy/tool/mocktool.py:
+ (MockTool.irc):
+ (MockTool):
+ (MockTool.buildbot_for_builder_name):
+
2012-07-10 Alice Cheng <[email protected]>
Editing: Reproducible crasher when pasting a 0x0 image into Mail
Modified: trunk/Tools/Scripts/webkitpy/common/host.py (122233 => 122234)
--- trunk/Tools/Scripts/webkitpy/common/host.py 2012-07-10 17:05:24 UTC (rev 122233)
+++ trunk/Tools/Scripts/webkitpy/common/host.py 2012-07-10 17:33:41 UTC (rev 122234)
@@ -138,6 +138,11 @@
def checkout(self):
return self._checkout
+ def buildbot_for_builder_name(self, name):
+ if self.port_factory.get_from_builder_name(name).is_chromium():
+ return self.chromium_buildbot()
+ return self.buildbot
+
@memoized
def chromium_buildbot(self):
return ChromiumBuildBot()
Modified: trunk/Tools/Scripts/webkitpy/common/net/buildbot/buildbot.py (122233 => 122234)
--- trunk/Tools/Scripts/webkitpy/common/net/buildbot/buildbot.py 2012-07-10 17:05:24 UTC (rev 122233)
+++ trunk/Tools/Scripts/webkitpy/common/net/buildbot/buildbot.py 2012-07-10 17:33:41 UTC (rev 122234)
@@ -33,6 +33,7 @@
import urllib2
import webkitpy.common.config.urls as config_urls
+from webkitpy.common.memoized import memoized
from webkitpy.common.net.failuremap import FailureMap
from webkitpy.common.net.layouttestresults import LayoutTestResults
from webkitpy.common.net.networktransaction import NetworkTransaction
@@ -65,6 +66,31 @@
def accumulated_results_url(self):
return None
+ def latest_layout_test_results_url(self):
+ return self.accumulated_results_url() or self.latest_cached_build().results_url();
+
+ @memoized
+ def latest_layout_test_results(self):
+ return self.fetch_layout_test_results(self.latest_layout_test_results_url())
+
+ def _fetch_file_from_results(self, results_url, file_name):
+ # It seems this can return None if the url redirects and then returns 404.
+ result = urllib2.urlopen("%s/%s" % (results_url, file_name))
+ if not result:
+ return None
+ # urlopen returns a file-like object which sometimes works fine with str()
+ # but sometimes is a addinfourl object. In either case calling read() is correct.
+ return result.read()
+
+ def fetch_layout_test_results(self, results_url):
+ # FIXME: This should cache that the result was a 404 and stop hitting the network.
+ results_file = NetworkTransaction(convert_404_to_None=True).run(lambda: self._fetch_file_from_results(results_url, "full_results.json"))
+ if not results_file:
+ results_file = NetworkTransaction(convert_404_to_None=True).run(lambda: self._fetch_file_from_results(results_url, "results.html"))
+
+ # results_from_string accepts either ORWT html or NRWT json.
+ return LayoutTestResults.results_from_string(results_file)
+
def url_encoded_name(self):
return urllib.quote(self._name)
@@ -229,7 +255,6 @@
self._number = build_number
self._revision = revision
self._is_green = is_green
- self._layout_test_results = None
@staticmethod
def build_url(builder, build_number):
@@ -245,28 +270,10 @@
def results_zip_url(self):
return "%s.zip" % self.results_url()
- def _fetch_file_from_results(self, file_name):
- # It seems this can return None if the url redirects and then returns 404.
- result = urllib2.urlopen("%s/%s" % (self.results_url(), file_name))
- if not result:
- return None
- # urlopen returns a file-like object which sometimes works fine with str()
- # but sometimes is a addinfourl object. In either case calling read() is correct.
- return result.read()
-
+ @memoized
def layout_test_results(self):
- if self._layout_test_results:
- return self._layout_test_results
+ return self._builder.fetch_layout_test_results(self.results_url())
- # FIXME: This should cache that the result was a 404 and stop hitting the network.
- results_file = NetworkTransaction(convert_404_to_None=True).run(lambda: self._fetch_file_from_results("full_results.json"))
- if not results_file:
- results_file = NetworkTransaction(convert_404_to_None=True).run(lambda: self._fetch_file_from_results("results.html"))
-
- # results_from_string accepts either ORWT html or NRWT json.
- self._layout_test_results = LayoutTestResults.results_from_string(results_file)
- return self._layout_test_results
-
def builder(self):
return self._builder
Modified: trunk/Tools/Scripts/webkitpy/common/net/buildbot/buildbot_mock.py (122233 => 122234)
--- trunk/Tools/Scripts/webkitpy/common/net/buildbot/buildbot_mock.py 2012-07-10 17:05:24 UTC (rev 122233)
+++ trunk/Tools/Scripts/webkitpy/common/net/buildbot/buildbot_mock.py 2012-07-10 17:33:41 UTC (rev 122234)
@@ -49,6 +49,9 @@
def accumulated_results_url(self):
return "http://example.com/f/builders/%s/results/layout-test-results" % self.name()
+ def latest_layout_test_results_url(self):
+ return self.accumulated_results_url()
+
def force_build(self, username, comments):
log("MOCK: force_build: name=%s, username=%s, comments=%s" % (
self._name, username, comments))
Modified: trunk/Tools/Scripts/webkitpy/common/net/buildbot/buildbot_unittest.py (122233 => 122234)
--- trunk/Tools/Scripts/webkitpy/common/net/buildbot/buildbot_unittest.py 2012-07-10 17:05:24 UTC (rev 122233)
+++ trunk/Tools/Scripts/webkitpy/common/net/buildbot/buildbot_unittest.py 2012-07-10 17:33:41 UTC (rev 122234)
@@ -48,7 +48,10 @@
is_green=build_number < 4
)
results = [self._mock_test_result(testname) for testname in failure(build_number)]
- build._layout_test_results = LayoutTestResults(results)
+ layout_test_results = LayoutTestResults(results)
+ def mock_layout_test_results():
+ return layout_test_results
+ build.layout_test_results = mock_layout_test_results
return build
self.builder._fetch_build = _mock_fetch_build
@@ -57,6 +60,11 @@
self.builder = Builder(u"Test Builder \u2661", self.buildbot)
self._install_fetch_build(lambda build_number: ["test1", "test2"])
+ def test_latest_layout_test_results(self):
+ self.builder.fetch_layout_test_results = lambda results_url: LayoutTestResults([self._mock_test_result(testname) for testname in ["test1", "test2"]])
+ self.builder.accumulated_results_url = lambda: "http://dummy_url.org"
+ self.assertTrue(self.builder.latest_layout_test_results())
+
def test_find_regression_window(self):
regression_window = self.builder.find_regression_window(self.builder.build(10))
self.assertEqual(regression_window.build_before_failure().revision(), 1003)
@@ -147,8 +155,8 @@
def test_layout_test_results(self):
buildbot = BuildBot()
builder = Builder(u"Foo Builder (test)", buildbot)
+ builder._fetch_file_from_results = lambda results_url, file_name: None
build = Build(builder, None, None, None)
- build._fetch_file_from_results = lambda file_name: None
# Test that layout_test_results() returns None if the fetch fails.
self.assertEqual(build.layout_test_results(), None)
Modified: trunk/Tools/Scripts/webkitpy/common/system/user.py (122233 => 122234)
--- trunk/Tools/Scripts/webkitpy/common/system/user.py 2012-07-10 17:05:24 UTC (rev 122233)
+++ trunk/Tools/Scripts/webkitpy/common/system/user.py 2012-07-10 17:33:41 UTC (rev 122234)
@@ -74,14 +74,20 @@
return cls.prompt(message, repeat=repeat, raw_input=getpass.getpass)
@classmethod
- def prompt_with_list(cls, list_title, list_items, can_choose_multiple=False, raw_input=raw_input):
+ def prompt_with_multiple_lists(cls, list_title, subtitles, lists, can_choose_multiple=False, raw_input=raw_input):
+ item_index = 0
+ cumulated_list = []
print list_title
- i = 0
- for item in list_items:
- i += 1
- print "%2d. %s" % (i, item)
+ for i in range(len(subtitles)):
+ print "\n" + subtitles[i]
+ for item in lists[i]:
+ item_index += 1
+ print "%2d. %s" % (item_index, item)
+ cumulated_list += lists[i]
+ return cls._wait_on_list_response(cumulated_list, can_choose_multiple, raw_input)
- # Loop until we get valid input
+ @classmethod
+ def _wait_on_list_response(cls, list_items, can_choose_multiple, raw_input):
while True:
if can_choose_multiple:
response = cls.prompt("Enter one or more numbers (comma-separated), or \"all\": ", raw_input=raw_input)
@@ -99,6 +105,15 @@
continue
return list_items[result]
+ @classmethod
+ def prompt_with_list(cls, list_title, list_items, can_choose_multiple=False, raw_input=raw_input):
+ print list_title
+ i = 0
+ for item in list_items:
+ i += 1
+ print "%2d. %s" % (i, item)
+ return cls._wait_on_list_response(list_items, can_choose_multiple, raw_input)
+
def edit(self, files):
editor = os.environ.get("EDITOR") or "vi"
args = shlex.split(editor)
Modified: trunk/Tools/Scripts/webkitpy/common/system/user_unittest.py (122233 => 122234)
--- trunk/Tools/Scripts/webkitpy/common/system/user_unittest.py 2012-07-10 17:05:24 UTC (rev 122233)
+++ trunk/Tools/Scripts/webkitpy/common/system/user_unittest.py 2012-07-10 17:33:41 UTC (rev 122234)
@@ -51,6 +51,32 @@
return None
self.assertEqual(User.prompt("input", repeat=self.repeatsRemaining, raw_input=mock_raw_input), None)
+ def test_prompt_with_multiple_lists(self):
+ def run_prompt_test(inputs, expected_result, can_choose_multiple=False):
+ def mock_raw_input(message):
+ return inputs.pop(0)
+ output_capture = OutputCapture()
+ actual_result = output_capture.assert_outputs(
+ self,
+ User.prompt_with_multiple_lists,
+ args=["title", ["subtitle1", "subtitle2"], [["foo", "bar"], ["foobar", "barbaz"]]],
+ kwargs={"can_choose_multiple": can_choose_multiple, "raw_input": mock_raw_input},
+ expected_stdout="title\n\nsubtitle1\n 1. foo\n 2. bar\n\nsubtitle2\n 3. foobar\n 4. barbaz\n")
+ self.assertEqual(actual_result, expected_result)
+ self.assertEqual(len(inputs), 0)
+
+ run_prompt_test(["1"], "foo")
+ run_prompt_test(["badinput", "2"], "bar")
+ run_prompt_test(["3"], "foobar")
+ run_prompt_test(["4"], "barbaz")
+
+ run_prompt_test(["1,2"], ["foo", "bar"], can_choose_multiple=True)
+ run_prompt_test([" 1, 2 "], ["foo", "bar"], can_choose_multiple=True)
+ run_prompt_test(["all"], ["foo", "bar", 'foobar', 'barbaz'], can_choose_multiple=True)
+ run_prompt_test([""], ["foo", "bar", 'foobar', 'barbaz'], can_choose_multiple=True)
+ run_prompt_test([" "], ["foo", "bar", 'foobar', 'barbaz'], can_choose_multiple=True)
+ run_prompt_test(["badinput", "all"], ["foo", "bar", 'foobar', 'barbaz'], can_choose_multiple=True)
+
def test_prompt_with_list(self):
def run_prompt_test(inputs, expected_result, can_choose_multiple=False):
def mock_raw_input(message):
Modified: trunk/Tools/Scripts/webkitpy/layout_tests/port/base.py (122233 => 122234)
--- trunk/Tools/Scripts/webkitpy/layout_tests/port/base.py 2012-07-10 17:05:24 UTC (rev 122233)
+++ trunk/Tools/Scripts/webkitpy/layout_tests/port/base.py 2012-07-10 17:33:41 UTC (rev 122234)
@@ -654,6 +654,9 @@
return True
return False
+ def is_chromium(self):
+ return False
+
def name(self):
"""Returns a name that uniquely identifies this particular type of port
(e.g., "mac-snowleopard" or "chromium-linux-x86_x64" and can be passed
Modified: trunk/Tools/Scripts/webkitpy/layout_tests/port/builders.py (122233 => 122234)
--- trunk/Tools/Scripts/webkitpy/layout_tests/port/builders.py 2012-07-10 17:05:24 UTC (rev 122233)
+++ trunk/Tools/Scripts/webkitpy/layout_tests/port/builders.py 2012-07-10 17:33:41 UTC (rev 122234)
@@ -96,12 +96,10 @@
return re.sub(r'[\s().]', '_', builder_name)
-@memoized
def all_builder_names():
return sorted(set(_exact_matches.keys()))
-@memoized
def all_port_names():
return sorted(set(map(lambda x: x["port_name"], _exact_matches.values()) + _ports_without_builders))
Modified: trunk/Tools/Scripts/webkitpy/layout_tests/port/chromium.py (122233 => 122234)
--- trunk/Tools/Scripts/webkitpy/layout_tests/port/chromium.py 2012-07-10 17:05:24 UTC (rev 122233)
+++ trunk/Tools/Scripts/webkitpy/layout_tests/port/chromium.py 2012-07-10 17:33:41 UTC (rev 122234)
@@ -110,6 +110,9 @@
# All sub-classes override this, but we need an initial value for testing.
self._chromium_base_dir_path = None
+ def is_chromium(self):
+ return True
+
def default_pixel_tests(self):
return True
Modified: trunk/Tools/Scripts/webkitpy/tool/commands/rebaseline.py (122233 => 122234)
--- trunk/Tools/Scripts/webkitpy/tool/commands/rebaseline.py 2012-07-10 17:05:24 UTC (rev 122233)
+++ trunk/Tools/Scripts/webkitpy/tool/commands/rebaseline.py 2012-07-10 17:33:41 UTC (rev 122234)
@@ -81,11 +81,7 @@
self._scm_changes = {'add': []}
def _results_url(self, builder_name):
- port = self._tool.port_factory.get_from_builder_name(builder_name)
- # FIXME: Come up with a better way than string manipulation to see if the port is a chromium port.
- if port.name().startswith('chromium-'):
- return self._tool.chromium_buildbot().builder_with_name(builder_name).accumulated_results_url()
- return self._tool.buildbot.builder_with_name(builder_name).latest_cached_build().results_url()
+ return self._tool.buildbot_for_builder_name(builder_name).builder_with_name(builder_name).latest_layout_test_results_url()
def _baseline_directory(self, builder_name):
port = self._tool.port_factory.get_from_builder_name(builder_name)
@@ -229,13 +225,13 @@
class AbstractParallelRebaselineCommand(AbstractDeclarativeCommand):
- def __init__(self):
- options = [
+ def __init__(self, options=None):
+ options = options or []
+ options.extend([
optparse.make_option('--no-optimize', dest='optimize', action='', default=True,
help=('Do not optimize/de-dup the expectations after rebaselining '
'(default is to de-dup automatically). '
- 'You can use "webkit-patch optimize-baselines" to optimize separately.')),
- ]
+ 'You can use "webkit-patch optimize-baselines" to optimize separately.'))])
AbstractDeclarativeCommand.__init__(self, options=options)
def _run_webkit_patch(self, args):
@@ -369,30 +365,56 @@
class Rebaseline(AbstractParallelRebaselineCommand):
name = "rebaseline"
- help_text = "Replaces local expected.txt files with new results from build bots"
+ help_text = "Replaces local expected.txt files with new results from build bots. Shows the list of failing tests on the builders if no test names are provided."
+ argument_names = "[TEST_NAMES]"
- # FIXME: This should share more code with FailureReason._builder_to_explain
- def _builder_to_pull_from(self):
- builder_statuses = self._tool.buildbot.builder_statuses()
- red_statuses = [status for status in builder_statuses if not status["is_green"]]
- _log.info("%s failing" % (pluralize("builder", len(red_statuses))))
- builder_choices = [status["name"] for status in red_statuses]
- chosen_name = self._tool.user.prompt_with_list("Which builder to pull results from:", builder_choices)
- # FIXME: prompt_with_list should really take a set of objects and a set of names and then return the object.
- for status in red_statuses:
- if status["name"] == chosen_name:
- return (self._tool.buildbot.builder_with_name(chosen_name), status["build_number"])
+ def __init__(self):
+ options = [
+ optparse.make_option("--builders", default=None, action="" help="Comma-separated-list of builders to pull new baselines from (can also be provided multiple times)"),
+ ]
+ AbstractParallelRebaselineCommand.__init__(self, options=options)
- def _tests_to_update(self, build):
- failing_tests = build.layout_test_results().tests_matching_failure_types([test_failures.FailureTextMismatch])
- return self._tool.user.prompt_with_list("Which test(s) to rebaseline:", failing_tests, can_choose_multiple=True)
+ def _builders_to_pull_from(self):
+ chromium_buildbot_builder_names = []
+ webkit_buildbot_builder_names = []
+ for name in builders.all_builder_names():
+ if self._tool.port_factory.get_from_builder_name(name).is_chromium():
+ chromium_buildbot_builder_names.append(name)
+ else:
+ webkit_buildbot_builder_names.append(name)
+ titles = ["build.webkit.org bots", "build.chromium.org bots"]
+ lists = [webkit_buildbot_builder_names, chromium_buildbot_builder_names]
+
+ chosen_names = self._tool.user.prompt_with_multiple_lists("Which builder to pull results from:", titles, lists, can_choose_multiple=True)
+ return [self._builder_with_name(name) for name in chosen_names]
+
+ def _builder_with_name(self, name):
+ return self._tool.buildbot_for_builder_name(name).builder_with_name(name)
+
+ def _tests_to_update(self, builder):
+ failing_tests = builder.latest_layout_test_results().tests_matching_failure_types([test_failures.FailureTextMismatch])
+ return self._tool.user.prompt_with_list("Which test(s) to rebaseline for %s:" % builder.name(), failing_tests, can_choose_multiple=True)
+
def execute(self, options, args, tool):
- builder, build_number = self._builder_to_pull_from()
- build = builder.build(build_number)
+ if options.builders:
+ builders = []
+ for builder_names in options.builders:
+ builders += [self._builder_with_name(name) for name in builder_names.split(",")]
+ else:
+ builders = self._builders_to_pull_from()
- builder_name = builder.name()
test_list = {}
- for test in self._tests_to_update(build):
- test_list[test] = {builder_name: ['txt']}
+
+ for builder in builders:
+ tests = args or self._tests_to_update(builder)
+ for test in tests:
+ if test not in test_list:
+ test_list[test] = {}
+ # FIXME: Allow for choosing the suffixes.
+ test_list[test][builder.name()] = ['txt']
+
+ if options.verbose:
+ print "rebaseline-json: " + str(test_list)
+
self._rebaseline(options, test_list)
Modified: trunk/Tools/Scripts/webkitpy/tool/commands/rebaseline_unittest.py (122233 => 122234)
--- trunk/Tools/Scripts/webkitpy/tool/commands/rebaseline_unittest.py 2012-07-10 17:05:24 UTC (rev 122233)
+++ trunk/Tools/Scripts/webkitpy/tool/commands/rebaseline_unittest.py 2012-07-10 17:33:41 UTC (rev 122234)
@@ -351,20 +351,132 @@
tool.executive = MockExecutive(should_log=True)
- def mock_builder_to_pull_from():
- return MockBuilder('MOCK builder'), 1234
+ def mock_builders_to_pull_from():
+ return [MockBuilder('MOCK builder')]
def mock_tests_to_update(build):
return ['mock/path/to/test.html']
- command._builder_to_pull_from = mock_builder_to_pull_from
+ command._builders_to_pull_from = mock_builders_to_pull_from
command._tests_to_update = mock_tests_to_update
+ expected_stdout = """rebaseline-json: {'mock/path/to/test.html': {'MOCK builder': ['txt']}}
+"""
+
expected_stderr = """MOCK run_command: ['echo', 'rebaseline-test-internal', '--suffixes', 'txt', '--builder', 'MOCK builder', '--test', 'mock/path/to/test.html'], cwd=/mock-checkout
MOCK run_command: ['echo', 'optimize-baselines', '--suffixes', 'txt', 'mock/path/to/test.html'], cwd=/mock-checkout
"""
- OutputCapture().assert_outputs(self, command.execute, [MockOptions(optimize=True), [], tool], expected_stderr=expected_stderr)
+ OutputCapture().assert_outputs(self, command.execute, [MockOptions(optimize=True, builders=None, verbose=True), [], tool], expected_stdout=expected_stdout, expected_stderr=expected_stderr)
finally:
builders._exact_matches = old_exact_matches
+
+ def test_rebaseline_command_line_flags(self):
+ old_exact_matches = builders._exact_matches
+ try:
+ builders._exact_matches = {
+ "MOCK builder": {"port_name": "test-mac-leopard", "specifiers": set(["mock-specifier"])},
+ }
+
+ command = Rebaseline()
+ tool = MockTool()
+ command.bind_to_tool(tool)
+
+ for port_name in tool.port_factory.all_port_names():
+ port = tool.port_factory.get(port_name)
+ for path in port.expectations_files():
+ tool.filesystem.write_text_file(path, '')
+
+ tool.executive = MockExecutive(should_log=True)
+
+ expected_stdout = """rebaseline-json: {'mock/path/to/test.html': {'MOCK builder': ['txt']}}
+"""
+
+ expected_stderr = """MOCK run_command: ['echo', 'rebaseline-test-internal', '--suffixes', 'txt', '--builder', 'MOCK builder', '--test', 'mock/path/to/test.html'], cwd=/mock-checkout
+MOCK run_command: ['echo', 'optimize-baselines', '--suffixes', 'txt', 'mock/path/to/test.html'], cwd=/mock-checkout
+"""
+
+ builder = "MOCK builder"
+ test = "mock/path/to/test.html"
+ OutputCapture().assert_outputs(self, command.execute, [MockOptions(optimize=True, builders=[builder], verbose=True), [test], tool], expected_stdout=expected_stdout, expected_stderr=expected_stderr)
+
+ finally:
+ builders._exact_matches = old_exact_matches
+
+ def test_rebaseline_multiple_builders(self):
+ old_exact_matches = builders._exact_matches
+ try:
+ builders._exact_matches = {
+ "MOCK builder": {"port_name": "test-mac-leopard", "specifiers": set(["mock-specifier"])},
+ "MOCK builder2": {"port_name": "test-mac-snowleopard", "specifiers": set(["mock-specifier2"])},
+ }
+
+ command = Rebaseline()
+ tool = MockTool()
+ command.bind_to_tool(tool)
+
+ for port_name in tool.port_factory.all_port_names():
+ port = tool.port_factory.get(port_name)
+ for path in port.expectations_files():
+ tool.filesystem.write_text_file(path, '')
+
+ tool.executive = MockExecutive(should_log=True)
+
+ def mock_builders_to_pull_from():
+ return [MockBuilder('MOCK builder'), MockBuilder('MOCK builder2')]
+
+ def mock_tests_to_update(build):
+ return ['mock/path/to/test.html']
+
+ command._builders_to_pull_from = mock_builders_to_pull_from
+ command._tests_to_update = mock_tests_to_update
+
+ expected_stdout = """rebaseline-json: {'mock/path/to/test.html': {'MOCK builder2': ['txt'], 'MOCK builder': ['txt']}}
+"""
+
+ expected_stderr = """MOCK run_command: ['echo', 'rebaseline-test-internal', '--suffixes', 'txt', '--builder', 'MOCK builder2', '--test', 'mock/path/to/test.html'], cwd=/mock-checkout
+MOCK run_command: ['echo', 'rebaseline-test-internal', '--suffixes', 'txt', '--builder', 'MOCK builder', '--test', 'mock/path/to/test.html'], cwd=/mock-checkout
+MOCK run_command: ['echo', 'optimize-baselines', '--suffixes', 'txt', 'mock/path/to/test.html'], cwd=/mock-checkout
+"""
+
+ OutputCapture().assert_outputs(self, command.execute, [MockOptions(optimize=True, builders=None, verbose=True), [], tool], expected_stdout=expected_stdout, expected_stderr=expected_stderr)
+
+ finally:
+ builders._exact_matches = old_exact_matches
+
+ def test_rebaseline_multiple_builders_and_tests_command_line(self):
+ old_exact_matches = builders._exact_matches
+ try:
+ builders._exact_matches = {
+ "MOCK builder": {"port_name": "test-mac-leopard", "specifiers": set(["mock-specifier"])},
+ "MOCK builder2": {"port_name": "test-mac-snowleopard", "specifiers": set(["mock-specifier2"])},
+ "MOCK builder3": {"port_name": "test-mac-snowleopard", "specifiers": set(["mock-specifier2"])},
+ }
+
+ command = Rebaseline()
+ tool = MockTool()
+ command.bind_to_tool(tool)
+
+ for port_name in tool.port_factory.all_port_names():
+ port = tool.port_factory.get(port_name)
+ for path in port.expectations_files():
+ tool.filesystem.write_text_file(path, '')
+
+ tool.executive = MockExecutive(should_log=True)
+
+ expected_stdout = """rebaseline-json: {'mock/path/to/test.html': {'MOCK builder2': ['txt'], 'MOCK builder': ['txt'], 'MOCK builder3': ['txt']}, 'mock/path/to/test2.html': {'MOCK builder2': ['txt'], 'MOCK builder': ['txt'], 'MOCK builder3': ['txt']}}
+"""
+
+ expected_stderr = """MOCK run_command: ['echo', 'rebaseline-test-internal', '--suffixes', 'txt', '--builder', 'MOCK builder2', '--test', 'mock/path/to/test.html'], cwd=/mock-checkout
+MOCK run_command: ['echo', 'rebaseline-test-internal', '--suffixes', 'txt', '--builder', 'MOCK builder', '--test', 'mock/path/to/test.html'], cwd=/mock-checkout
+MOCK run_command: ['echo', 'rebaseline-test-internal', '--suffixes', 'txt', '--builder', 'MOCK builder2', '--test', 'mock/path/to/test2.html'], cwd=/mock-checkout
+MOCK run_command: ['echo', 'rebaseline-test-internal', '--suffixes', 'txt', '--builder', 'MOCK builder', '--test', 'mock/path/to/test2.html'], cwd=/mock-checkout
+MOCK run_command: ['echo', 'optimize-baselines', '--suffixes', 'txt', 'mock/path/to/test.html'], cwd=/mock-checkout
+MOCK run_command: ['echo', 'optimize-baselines', '--suffixes', 'txt', 'mock/path/to/test2.html'], cwd=/mock-checkout
+"""
+
+ OutputCapture().assert_outputs(self, command.execute, [MockOptions(optimize=True, builders=["MOCK builder,MOCK builder2", "MOCK builder3"], verbose=True), ["mock/path/to/test.html", "mock/path/to/test2.html"], tool], expected_stdout=expected_stdout, expected_stderr=expected_stderr)
+
+ finally:
+ builders._exact_matches = old_exact_matches
Modified: trunk/Tools/Scripts/webkitpy/tool/mocktool.py (122233 => 122234)
--- trunk/Tools/Scripts/webkitpy/tool/mocktool.py 2012-07-10 17:05:24 UTC (rev 122233)
+++ trunk/Tools/Scripts/webkitpy/tool/mocktool.py 2012-07-10 17:33:41 UTC (rev 122234)
@@ -29,6 +29,7 @@
import threading
from webkitpy.common.host_mock import MockHost
+from webkitpy.common.net.buildbot.buildbot_mock import MockBuildBot
from webkitpy.common.net.statusserver_mock import MockStatusServer
from webkitpy.common.net.irc.irc_mock import MockIRC
@@ -82,3 +83,6 @@
def irc(self):
return self._irc
+
+ def buildbot_for_builder_name(self, name):
+ return MockBuildBot()