From 2e515b75f6baf4e2f74afc8b632d97cd505b4f7e Mon Sep 17 00:00:00 2001 From: "ojan@chromium.org" Date: Mon, 2 Jul 2012 19:22:43 +0000 Subject: [PATCH] Move rebaseline-all command from the gardening-server down into webkit-patch https://bugs.webkit.org/show_bug.cgi?id=90395 Reviewed by Adam Barth. This is just moving code. It it in preparation for making rebaseline-expectations use the same code in order to get the parallelism benefits and reduces the amount of code we have for doing rebaselines. * Scripts/webkitpy/common/checkout/checkout_unittest.py: (CheckoutTest.test_apply_patch): Updated due to the change to executive_mock. * Scripts/webkitpy/common/system/executive_mock.py: (MockExecutive.run_command): Update to print out the input passed to stdin. * Scripts/webkitpy/tool/commands/download_unittest.py: Updated due to executive_mock change. * Scripts/webkitpy/tool/commands/rebaseline.py: (RebaselineAll): (RebaselineAll._run_webkit_patch): (RebaselineAll._builders_to_fetch_from): (RebaselineAll._rebaseline_commands): (RebaselineAll._files_to_add): (RebaselineAll._optimize_baselines): (RebaselineAll._rebaseline): (RebaselineAll.execute): All this code is just copy-pasted except for mechanical changes (e.g. self.server.tool --> self._tool) and the reading in of the JSON from stdin instead of the post body. * Scripts/webkitpy/tool/commands/rebaseline_unittest.py: (test_rebaseline_all): Copied the test-case out of gardeningserver_unittest.py. * Scripts/webkitpy/tool/servers/gardeningserver.py: (GardeningHTTPRequestHandler): (GardeningHTTPRequestHandler.rebaseline): (GardeningHTTPRequestHandler.rebaselineall): * Scripts/webkitpy/tool/servers/gardeningserver_unittest.py: (GardeningServerTest.test_rebaselineall): (GardeningServerTest.test_rebaselineall.run_command): git-svn-id: http://svn.webkit.org/repository/webkit/trunk@121699 268f45cc-cd09-0410-ab3c-d52691b4dbfc --- Tools/ChangeLog | 42 ++++++++++++ .../webkitpy/common/checkout/checkout_unittest.py | 2 +- .../webkitpy/common/system/executive_mock.py | 5 +- .../webkitpy/tool/commands/download_unittest.py | 2 +- Tools/Scripts/webkitpy/tool/commands/rebaseline.py | 76 ++++++++++++++++++++++ .../webkitpy/tool/commands/rebaseline_unittest.py | 29 +++++++++ .../webkitpy/tool/servers/gardeningserver.py | 62 +----------------- .../tool/servers/gardeningserver_unittest.py | 18 ++--- .../webkitpy/tool/servers/reflectionhandler.py | 4 +- 9 files changed, 164 insertions(+), 76 deletions(-) diff --git a/Tools/ChangeLog b/Tools/ChangeLog index 97671b3..106fcb6 100644 --- a/Tools/ChangeLog +++ b/Tools/ChangeLog @@ -1,5 +1,47 @@ 2012-07-02 Ojan Vafai + Move rebaseline-all command from the gardening-server down into webkit-patch + https://bugs.webkit.org/show_bug.cgi?id=90395 + + Reviewed by Adam Barth. + + This is just moving code. It it in preparation for making rebaseline-expectations + use the same code in order to get the parallelism benefits and reduces the amount + of code we have for doing rebaselines. + + * Scripts/webkitpy/common/checkout/checkout_unittest.py: + (CheckoutTest.test_apply_patch): + Updated due to the change to executive_mock. + * Scripts/webkitpy/common/system/executive_mock.py: + (MockExecutive.run_command): + Update to print out the input passed to stdin. + * Scripts/webkitpy/tool/commands/download_unittest.py: + Updated due to executive_mock change. + * Scripts/webkitpy/tool/commands/rebaseline.py: + (RebaselineAll): + (RebaselineAll._run_webkit_patch): + (RebaselineAll._builders_to_fetch_from): + (RebaselineAll._rebaseline_commands): + (RebaselineAll._files_to_add): + (RebaselineAll._optimize_baselines): + (RebaselineAll._rebaseline): + (RebaselineAll.execute): + All this code is just copy-pasted except for mechanical changes + (e.g. self.server.tool --> self._tool) and the reading in of the + JSON from stdin instead of the post body. + * Scripts/webkitpy/tool/commands/rebaseline_unittest.py: + (test_rebaseline_all): + Copied the test-case out of gardeningserver_unittest.py. + * Scripts/webkitpy/tool/servers/gardeningserver.py: + (GardeningHTTPRequestHandler): + (GardeningHTTPRequestHandler.rebaseline): + (GardeningHTTPRequestHandler.rebaselineall): + * Scripts/webkitpy/tool/servers/gardeningserver_unittest.py: + (GardeningServerTest.test_rebaselineall): + (GardeningServerTest.test_rebaselineall.run_command): + +2012-07-02 Ojan Vafai + Remove Leopard support from the flakiness dashboard https://bugs.webkit.org/show_bug.cgi?id=90390 diff --git a/Tools/Scripts/webkitpy/common/checkout/checkout_unittest.py b/Tools/Scripts/webkitpy/common/checkout/checkout_unittest.py index 78d25cb..e9c2cdd 100644 --- a/Tools/Scripts/webkitpy/common/checkout/checkout_unittest.py +++ b/Tools/Scripts/webkitpy/common/checkout/checkout_unittest.py @@ -259,5 +259,5 @@ class CheckoutTest(unittest.TestCase): mock_patch = Mock() mock_patch.contents = lambda: "foo" mock_patch.reviewer = lambda: None - expected_stderr = "MOCK run_command: ['svn-apply', '--force'], cwd=/mock-checkout\n" + expected_stderr = "MOCK run_command: ['svn-apply', '--force'], cwd=/mock-checkout, input=foo\n" OutputCapture().assert_outputs(self, checkout.apply_patch, [mock_patch], expected_stderr=expected_stderr) diff --git a/Tools/Scripts/webkitpy/common/system/executive_mock.py b/Tools/Scripts/webkitpy/common/system/executive_mock.py index a15c365..cfe9899 100644 --- a/Tools/Scripts/webkitpy/common/system/executive_mock.py +++ b/Tools/Scripts/webkitpy/common/system/executive_mock.py @@ -88,7 +88,10 @@ class MockExecutive(object): env_string = "" if env: env_string = ", env=%s" % env - log("MOCK run_command: %s, cwd=%s%s" % (args, cwd, env_string)) + input_string = "" + if input: + input_string = ", input=%s" % input + log("MOCK run_command: %s, cwd=%s%s%s" % (args, cwd, env_string, input_string)) output = "MOCK output of child process" if self._should_throw: raise ScriptError("MOCK ScriptError", output=output) diff --git a/Tools/Scripts/webkitpy/tool/commands/download_unittest.py b/Tools/Scripts/webkitpy/tool/commands/download_unittest.py index 7f19fbd..79b729a 100644 --- a/Tools/Scripts/webkitpy/tool/commands/download_unittest.py +++ b/Tools/Scripts/webkitpy/tool/commands/download_unittest.py @@ -136,7 +136,7 @@ MockWatchList: determine_cc_and_messages def test_land_cowboy(self): expected_stderr = """MOCK run_and_throw_if_fail: ['mock-prepare-ChangeLog', '--email=MOCK email', '--merge-base=None', 'MockFile1'], cwd=/mock-checkout MOCK run_and_throw_if_fail: ['mock-check-webkit-style', '--git-commit', 'MOCK git commit', '--diff-files', 'MockFile1', '--filter', '-changelog'], cwd=/mock-checkout -MOCK run_command: ['ruby', '-I', '/mock-checkout/Websites/bugs.webkit.org/PrettyPatch', '/mock-checkout/Websites/bugs.webkit.org/PrettyPatch/prettify.rb'], cwd=None +MOCK run_command: ['ruby', '-I', '/mock-checkout/Websites/bugs.webkit.org/PrettyPatch', '/mock-checkout/Websites/bugs.webkit.org/PrettyPatch/prettify.rb'], cwd=None, input=Patch1 MOCK: user.open_url: file://... Was that diff correct? Building WebKit diff --git a/Tools/Scripts/webkitpy/tool/commands/rebaseline.py b/Tools/Scripts/webkitpy/tool/commands/rebaseline.py index b5ec84c..34b4ece 100644 --- a/Tools/Scripts/webkitpy/tool/commands/rebaseline.py +++ b/Tools/Scripts/webkitpy/tool/commands/rebaseline.py @@ -32,6 +32,7 @@ import optparse import os.path import re import shutil +import sys import urllib import webkitpy.common.config.urls as config_urls @@ -301,6 +302,81 @@ class RebaselineExpectations(AbstractDeclarativeCommand): self._run_webkit_patch(['optimize-baselines', '--suffixes', ','.join(suffixes), test_name]) +class RebaselineAll(AbstractDeclarativeCommand): + name = "rebaseline-all" + help_text = "Rebaseline based off JSON passed to stdin. Intended to only be called from other scripts." + + def _run_webkit_patch(self, args): + try: + self._tool.executive.run_command([self._tool.path()] + args, cwd=self._tool.scm().checkout_root) + except ScriptError, e: + _log.error(e) + + def _builders_to_fetch_from(self, builders): + # This routine returns the subset of builders that will cover all of the baseline search paths + # used in the input list. In particular, if the input list contains both Release and Debug + # versions of a configuration, we *only* return the Release version (since we don't save + # debug versions of baselines). + release_builders = set() + debug_builders = set() + builders_to_fallback_paths = {} + for builder in builders: + port = self._tool.port_factory.get_from_builder_name(builder) + if port.test_configuration().build_type == 'Release': + release_builders.add(builder) + else: + debug_builders.add(builder) + for builder in list(release_builders) + list(debug_builders): + port = self._tool.port_factory.get_from_builder_name(builder) + fallback_path = port.baseline_search_path() + if fallback_path not in builders_to_fallback_paths.values(): + builders_to_fallback_paths[builder] = fallback_path + return builders_to_fallback_paths.keys() + + def _rebaseline_commands(self, test_list): + path_to_webkit_patch = self._tool.path() + cwd = self._tool.scm().checkout_root + commands = [] + for test in test_list: + for builder in self._builders_to_fetch_from(test_list[test]): + suffixes = ','.join(test_list[test][builder]) + cmd_line = [path_to_webkit_patch, 'rebaseline-test', '--print-scm-changes', '--suffixes', suffixes, builder, test] + commands.append(tuple([cmd_line, cwd])) + return commands + + def _files_to_add(self, command_results): + files_to_add = set() + for output in [result[1] for result in command_results]: + try: + files_to_add.update(json.loads(output)['add']) + except ValueError, e: + _log.warning('"%s" is not a JSON object, ignoring' % output) + + return list(files_to_add) + + def _optimize_baselines(self, test_list): + # We don't run this in parallel because modifying the SCM in parallel is unreliable. + for test in test_list: + all_suffixes = set() + for builder in self._builders_to_fetch_from(test_list[test]): + all_suffixes.update(test_list[test][builder]) + self._run_webkit_patch(['optimize-baselines', '--suffixes', ','.join(all_suffixes), test]) + + def _rebaseline(self, json_input): + test_list = json.loads(json_input) + + commands = self._rebaseline_commands(test_list) + command_results = self._tool.executive.run_in_parallel(commands) + + files_to_add = self._files_to_add(command_results) + self._tool.scm().add_list(list(files_to_add)) + + self._optimize_baselines(test_list) + + def execute(self, options, args, tool): + self._rebaseline(sys.stdin.read()) + + class Rebaseline(AbstractDeclarativeCommand): name = "rebaseline" help_text = "Replaces local expected.txt files with new results from build bots" diff --git a/Tools/Scripts/webkitpy/tool/commands/rebaseline_unittest.py b/Tools/Scripts/webkitpy/tool/commands/rebaseline_unittest.py index d3e68e5..169e2a8 100644 --- a/Tools/Scripts/webkitpy/tool/commands/rebaseline_unittest.py +++ b/Tools/Scripts/webkitpy/tool/commands/rebaseline_unittest.py @@ -189,6 +189,35 @@ Retrieving http://example.com/f/builders/Webkit Mac10.7/results/layout-test-resu """ OutputCapture().assert_outputs(self, command._rebaseline_test, ["Webkit Mac10.7", "userscripts/another-test.html", ["chromium-mac-snowleopard"], "txt"], expected_logs=expected_logs) + def test_rebaseline_all(self): + old_exact_matches = builders._exact_matches + builders._exact_matches = { + "MOCK builder": {"port_name": "test-mac-leopard", "specifiers": set(["mock-specifier"])}, + "MOCK builder (Debug)": {"port_name": "test-mac-leopard", "specifiers": set(["mock-specifier", "debug"])}, + } + + command = RebaselineAll() + tool = MockTool() + command.bind_to_tool(tool) + tool.executive = MockExecutive(should_log=True) + + expected_stderr = """MOCK run_command: ['echo', 'rebaseline-test', '--print-scm-changes', '--suffixes', u'txt,png', u'MOCK builder', u'user-scripts/another-test.html'], cwd=/mock-checkout +MOCK run_command: ['echo', 'optimize-baselines', '--suffixes', u'txt,png', u'user-scripts/another-test.html'], cwd=/mock-checkout +""" + OutputCapture().assert_outputs(self, command._rebaseline, ['{"user-scripts/another-test.html":{"MOCK builder": ["txt","png"]}}'], expected_stderr=expected_stderr) + + expected_stderr = """MOCK run_command: ['echo', 'rebaseline-test', '--print-scm-changes', '--suffixes', u'txt,png', u'MOCK builder (Debug)', u'user-scripts/another-test.html'], cwd=/mock-checkout +MOCK run_command: ['echo', 'optimize-baselines', '--suffixes', u'txt,png', u'user-scripts/another-test.html'], cwd=/mock-checkout +""" + OutputCapture().assert_outputs(self, command._rebaseline, ['{"user-scripts/another-test.html":{"MOCK builder (Debug)": ["txt","png"]}}'], expected_stderr=expected_stderr) + + expected_stderr = """MOCK run_command: ['echo', 'rebaseline-test', '--print-scm-changes', '--suffixes', u'txt', u'MOCK builder', u'user-scripts/another-test.html'], cwd=/mock-checkout +MOCK run_command: ['echo', 'optimize-baselines', '--suffixes', u'txt', u'user-scripts/another-test.html'], cwd=/mock-checkout +""" + OutputCapture().assert_outputs(self, command._rebaseline, ['{"user-scripts/another-test.html":{"MOCK builder (Debug)": ["txt","png"], "MOCK builder": ["txt"]}}'], expected_stderr=expected_stderr) + + builders._exact_matches = old_exact_matches + def test_rebaseline_expectations(self): command = RebaselineExpectations() tool = MockTool() diff --git a/Tools/Scripts/webkitpy/tool/servers/gardeningserver.py b/Tools/Scripts/webkitpy/tool/servers/gardeningserver.py index bfe003f..4415ee8 100644 --- a/Tools/Scripts/webkitpy/tool/servers/gardeningserver.py +++ b/Tools/Scripts/webkitpy/tool/servers/gardeningserver.py @@ -140,6 +140,7 @@ class GardeningHTTPRequestHandler(ReflectionHandler): self._expectations_updater().update_expectations(self._read_entity_body_as_json()) self._serve_text('success') + # FIXME: Is this dead code? def rebaseline(self): builder = self.query['builder'][0] command = [ 'rebaseline-test' ] @@ -155,64 +156,7 @@ class GardeningHTTPRequestHandler(ReflectionHandler): self._run_webkit_patch(command) self._serve_text('success') - def _builders_to_fetch_from(self, builders): - # This routine returns the subset of builders that will cover all of the baseline search paths - # used in the input list. In particular, if the input list contains both Release and Debug - # versions of a configuration, we *only* return the Release version (since we don't save - # debug versions of baselines). - release_builders = set() - debug_builders = set() - builders_to_fallback_paths = {} - for builder in builders: - port = self.server.tool.port_factory.get_from_builder_name(builder) - if port.test_configuration().build_type == 'Release': - release_builders.add(builder) - else: - debug_builders.add(builder) - for builder in list(release_builders) + list(debug_builders): - port = self.server.tool.port_factory.get_from_builder_name(builder) - fallback_path = port.baseline_search_path() - if fallback_path not in builders_to_fallback_paths.values(): - builders_to_fallback_paths[builder] = fallback_path - return builders_to_fallback_paths.keys() - - def _rebaseline_commands(self, test_list): - path_to_webkit_patch = self.server.tool.path() - cwd = self.server.tool.scm().checkout_root - commands = [] - for test in test_list: - for builder in self._builders_to_fetch_from(test_list[test]): - suffixes = ','.join(test_list[test][builder]) - cmd_line = [path_to_webkit_patch, 'rebaseline-test', '--print-scm-changes', '--suffixes', suffixes, builder, test] - commands.append(tuple([cmd_line, cwd])) - return commands - - def _files_to_add(self, command_results): - files_to_add = set() - for output in [result[1] for result in command_results]: - try: - files_to_add.update(json.loads(output)['add']) - except ValueError, e: - _log.warning('"%s" is not a JSON object, ignoring' % output) - - return list(files_to_add) - - def _optimize_baselines(self, test_list): - # We don't run this in parallel because modifying the SCM in parallel is unreliable. - for test in test_list: - all_suffixes = set() - for builder in self._builders_to_fetch_from(test_list[test]): - all_suffixes.update(test_list[test][builder]) - self._run_webkit_patch(['optimize-baselines', '--suffixes', ','.join(all_suffixes), test]) - def rebaselineall(self): - test_list = self._read_entity_body_as_json() - - commands = self._rebaseline_commands(test_list) - command_results = self.server.tool.executive.run_in_parallel(commands) - - files_to_add = self._files_to_add(command_results) - self.server.tool.scm().add_list(list(files_to_add)) - - self._optimize_baselines(test_list) + command = ['rebaseline-all'] + self.server.tool.executive.run_command([self.server.tool.path()] + command, input=self.read_entity_body(), cwd=self.server.tool.scm().checkout_root) self._serve_text('success') diff --git a/Tools/Scripts/webkitpy/tool/servers/gardeningserver_unittest.py b/Tools/Scripts/webkitpy/tool/servers/gardeningserver_unittest.py index 4cc772c..d6dca47 100644 --- a/Tools/Scripts/webkitpy/tool/servers/gardeningserver_unittest.py +++ b/Tools/Scripts/webkitpy/tool/servers/gardeningserver_unittest.py @@ -69,7 +69,7 @@ class TestGardeningHTTPRequestHandler(GardeningHTTPRequestHandler): def _expectations_updater(self): return GardeningExpectationsUpdater(self.server.tool, TestPortFactory.create()) - def _read_entity_body(self): + def read_entity_body(self): return self.body if self.body else '' def _serve_text(self, text): @@ -183,26 +183,20 @@ class GardeningServerTest(unittest.TestCase): self._post_to_path("/rollout?revision=2314&reason=MOCK+rollout+reason", expected_stderr=expected_stderr, expected_stdout=expected_stdout) def test_rebaselineall(self): - builders._exact_matches = { - "MOCK builder": {"port_name": "test-mac-leopard", "specifiers": set(["mock-specifier"])}, - "MOCK builder (Debug)": {"port_name": "test-mac-leopard", "specifiers": set(["mock-specifier", "debug"])}, - } - expected_stderr = "MOCK run_command: ['echo', 'rebaseline-test', '--print-scm-changes', '--suffixes', u'%s', u'%s', u'user-scripts/another-test.html'], cwd=/mock-checkout\nMOCK run_command: ['echo', 'optimize-baselines', '--suffixes', u'%s', u'user-scripts/another-test.html'], cwd=/mock-checkout\n" + expected_stderr = "MOCK run_command: ['echo', 'rebaseline-all'], cwd=/mock-checkout, input={\"user-scripts/another-test.html\":{\"%s\": [%s]}}\n" expected_stdout = "== Begin Response ==\nsuccess\n== End Response ==\n" server = MockServer() self.output = ['{"add": [], "delete": []}', ''] - def run_command(args, cwd=None, **kwargs): - print >> sys.stderr, "MOCK run_command: %s, cwd=%s" % (args, cwd) + def run_command(args, cwd=None, input=None, **kwargs): + print >> sys.stderr, "MOCK run_command: %s, cwd=%s, input=%s" % (args, cwd, input) return self.output.pop(0) server.tool.executive.run_command = run_command - self._post_to_path("/rebaselineall", body='{"user-scripts/another-test.html":{"MOCK builder": ["txt","png"]}}', expected_stderr=expected_stderr % ('txt,png', 'MOCK builder', 'txt,png'), expected_stdout=expected_stdout, server=server) + self._post_to_path("/rebaselineall", body='{"user-scripts/another-test.html":{"MOCK builder": ["txt","png"]}}', expected_stderr=expected_stderr % ('MOCK builder', '"txt","png"'), expected_stdout=expected_stdout, server=server) - self._post_to_path("/rebaselineall", body='{"user-scripts/another-test.html":{"MOCK builder (Debug)": ["txt","png"]}}', expected_stderr=expected_stderr % ('txt,png', 'MOCK builder (Debug)', 'txt,png'), expected_stdout=expected_stdout) - - self._post_to_path("/rebaselineall", body='{"user-scripts/another-test.html":{"MOCK builder (Debug)": ["txt","png"], "MOCK builder": ["txt"]}}', expected_stderr=expected_stderr % ('txt', 'MOCK builder', 'txt'), expected_stdout=expected_stdout) + self._post_to_path("/rebaselineall", body='{"user-scripts/another-test.html":{"MOCK builder (Debug)": ["txt","png"]}}', expected_stderr=expected_stderr % ('MOCK builder (Debug)', '"txt","png"'), expected_stdout=expected_stdout) def test_rebaseline_new_port(self): builders._exact_matches = {"MOCK builder": {"port_name": "test-mac-leopard", "specifiers": set(["mock-specifier"]), "move_overwritten_baselines_to": ["mock-port-fallback", "mock-port-fallback2"]}} diff --git a/Tools/Scripts/webkitpy/tool/servers/reflectionhandler.py b/Tools/Scripts/webkitpy/tool/servers/reflectionhandler.py index 6a3f207..24bb277 100644 --- a/Tools/Scripts/webkitpy/tool/servers/reflectionhandler.py +++ b/Tools/Scripts/webkitpy/tool/servers/reflectionhandler.py @@ -59,12 +59,12 @@ class ReflectionHandler(BaseHTTPServer.BaseHTTPRequestHandler): def do_POST(self): self._handle_request() - def _read_entity_body(self): + def read_entity_body(self): length = int(self.headers.getheader('content-length')) return self.rfile.read(length) def _read_entity_body_as_json(self): - return json.loads(self._read_entity_body()) + return json.loads(self.read_entity_body()) def _handle_request(self): if "?" in self.path: -- 2.7.4