Changeset 121821 in webkit


Ignore:
Timestamp:
Jul 3, 2012 7:13:13 PM (12 years ago)
Author:
ojan@chromium.org
Message:

Improve webkit-patch rebaseline to work for more cases
https://bugs.webkit.org/show_bug.cgi?id=90504

Reviewed by Dirk Pranke.

-Makes it work for the build.chromium.org bots.
-Lets you rebaseline all builders instead of just one.
-Lets you pass in the builder or test to rebaseline.

  • Scripts/webkitpy/common/net/buildbot/buildbot.py:

(Build.results_url):
Make this work for build.chromium.org builders as well.

  • Scripts/webkitpy/common/net/buildbot/chromiumbuildbot.py:

(ChromiumBuilder):
(ChromiumBuilder.latest_cached_build):
ChromiumBuilder doesn't support large parts of the Builder interface.
This provides the bare minimum for this patch to work. Eventually,
we should create a single interface that can be supported for both
sets of buildbots.

  • 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.

  • Scripts/webkitpy/tool/commands/rebaseline.py:

(AbstractParallelRebaselineCommand.init):
(Rebaseline):
(Rebaseline.init):
(Rebaseline._builders_to_pull_from):
(Rebaseline._builder_with_name):
(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):

Location:
trunk/Tools
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/Tools/ChangeLog

    r121819 r121821  
     12012-07-03  Ojan Vafai  <ojan@chromium.org>
     2
     3        Improve webkit-patch rebaseline to work for more cases
     4        https://bugs.webkit.org/show_bug.cgi?id=90504
     5
     6        Reviewed by Dirk Pranke.
     7
     8        -Makes it work for the build.chromium.org bots.
     9        -Lets you rebaseline all builders instead of just one.
     10        -Lets you pass in the builder or test to rebaseline.
     11
     12        * Scripts/webkitpy/common/net/buildbot/buildbot.py:
     13        (Build.results_url):
     14        Make this work for build.chromium.org builders as well.
     15
     16        * Scripts/webkitpy/common/net/buildbot/chromiumbuildbot.py:
     17        (ChromiumBuilder):
     18        (ChromiumBuilder.latest_cached_build):
     19        ChromiumBuilder doesn't support large parts of the Builder interface.
     20        This provides the bare minimum for this patch to work. Eventually,
     21        we should create a single interface that can be supported for both
     22        sets of buildbots.
     23
     24        * Scripts/webkitpy/layout_tests/port/builders.py:
     25        (builder_path_from_name):
     26        (all_builder_names):
     27        memoizing here is incorrect because the test override _exact_matches,
     28        so these can return different values. In either case, I'm pretty sure these
     29        are not remotely hot codepaths.
     30
     31        * Scripts/webkitpy/tool/commands/rebaseline.py:
     32        (AbstractParallelRebaselineCommand.__init__):
     33        (Rebaseline):
     34        (Rebaseline.__init__):
     35        (Rebaseline._builders_to_pull_from):
     36        (Rebaseline._builder_with_name):
     37        (Rebaseline._tests_to_update):
     38        (Rebaseline.execute):
     39        * Scripts/webkitpy/tool/commands/rebaseline_unittest.py:
     40        (test_rebaseline.mock_builders_to_pull_from):
     41        (test_rebaseline):
     42        (test_rebaseline_command_line_flags):
     43        (test_rebaseline_multiple_builders):
     44        (test_rebaseline_multiple_builders.mock_builders_to_pull_from):
     45        (test_rebaseline_multiple_builders.mock_tests_to_update):
     46
    1472012-07-03  Christophe Dumez  <christophe.dumez@intel.com>
    248
  • trunk/Tools/Scripts/webkitpy/common/net/buildbot/buildbot.py

    r121447 r121821  
    240240
    241241    def results_url(self):
    242         results_directory = "r%s (%s)" % (self.revision(), self._number)
     242        # FIXME: We should probably have a better way of determining chromium builders than checking if the name starts with 'Webkit'.
     243        results_directory = "results/layout-test-results" if self._builder.name().startswith('Webkit') else "r%s (%s)" % (self.revision(), self._number)
    243244        return "%s/%s" % (self._builder.results_url(), urllib.quote(results_directory))
    244245
  • trunk/Tools/Scripts/webkitpy/common/net/buildbot/chromiumbuildbot.py

    r90770 r121821  
    4242        return self.results_url() + "/results/layout-test-results"
    4343
     44    # We override Builder.latest_cached_build because it relies on functions that assume too much about
     45    # the information provided on the buildbot pages.
     46    # FIXME: Have Builder and ChromiumBuilder actually provide a unified inteface that they both support.
     47    def latest_cached_build(self):
     48        for builder_status in self._buildbot.builder_statuses():
     49            if builder_status["name"] == self.name():
     50                build_number = builder_status["build_number"]
     51                break
     52        return self.build(build_number)
     53
    4454
    4555class ChromiumBuildBot(BuildBot):
  • trunk/Tools/Scripts/webkitpy/layout_tests/port/builders.py

    r121595 r121821  
    9797
    9898
    99 @memoized
    10099def all_builder_names():
    101100    return sorted(set(_exact_matches.keys()))
    102101
    103102
    104 @memoized
    105103def all_port_names():
    106104    return sorted(set(map(lambda x: x["port_name"], _exact_matches.values()) + _ports_without_builders))
  • trunk/Tools/Scripts/webkitpy/tool/commands/rebaseline.py

    r121800 r121821  
    230230
    231231class AbstractParallelRebaselineCommand(AbstractDeclarativeCommand):
    232     def __init__(self):
    233         options = [
     232    def __init__(self, options=None):
     233        options = options or []
     234        options.extend([
    234235            optparse.make_option('--no-optimize', dest='optimize', action='store_false', default=True,
    235236                help=('Do not optimize/de-dup the expectations after rebaselining '
    236237                      '(default is to de-dup automatically). '
    237                       'You can use "webkit-patch optimize-baselines" to optimize separately.')),
    238         ]
     238                      'You can use "webkit-patch optimize-baselines" to optimize separately.'))])
    239239        AbstractDeclarativeCommand.__init__(self, options=options)
    240240
     
    371371    name = "rebaseline"
    372372    help_text = "Replaces local expected.txt files with new results from build bots"
    373 
    374     # FIXME: This should share more code with FailureReason._builder_to_explain
    375     def _builder_to_pull_from(self):
    376         builder_statuses = self._tool.buildbot.builder_statuses()
    377         red_statuses = [status for status in builder_statuses if not status["is_green"]]
    378         _log.info("%s failing" % (pluralize("builder", len(red_statuses))))
    379         builder_choices = [status["name"] for status in red_statuses]
    380         chosen_name = self._tool.user.prompt_with_list("Which builder to pull results from:", builder_choices)
    381         # FIXME: prompt_with_list should really take a set of objects and a set of names and then return the object.
    382         for status in red_statuses:
    383             if status["name"] == chosen_name:
    384                 return (self._tool.buildbot.builder_with_name(chosen_name), status["build_number"])
    385 
    386     def _tests_to_update(self, build):
    387         failing_tests = build.layout_test_results().tests_matching_failure_types([test_failures.FailureTextMismatch])
    388         return self._tool.user.prompt_with_list("Which test(s) to rebaseline:", failing_tests, can_choose_multiple=True)
    389 
    390     def execute(self, options, args, tool):
    391         builder, build_number = self._builder_to_pull_from()
    392         build = builder.build(build_number)
    393 
    394         builder_name = builder.name()
     373    _chromium_prefix = 'Chromium - '
     374
     375    def __init__(self):
     376        options = [
     377            # FIXME: Make this builders/tests and have it take a comma-separated list.
     378            optparse.make_option("--builder", default=None, help="Builder to pull new baselines from"),
     379            optparse.make_option("--test", help="Test to rebaseline"),
     380        ]
     381        AbstractParallelRebaselineCommand.__init__(self, options=options)
     382
     383    def _builders_to_pull_from(self):
     384        # FIXME: Instead of prefixing the chromium builder names, show a build.webkit.org list and a build.chromium.org list.
     385        builder_names = [self._chromium_prefix + name if name.startswith('Webkit') else name for name in builders.all_builder_names()]
     386        chosen_names = self._tool.user.prompt_with_list("Which builder to pull results from:", builder_names, can_choose_multiple=True)
     387        return [self._builder_with_name(name) for name in chosen_names]
     388
     389    def _builder_with_name(self, name):
     390        if name.startswith(self._chromium_prefix):
     391            name = name[len(self._chromium_prefix):]
     392
     393        # FIXME: Share this code with the code in RebaselineTest._results_url.
     394        port = self._tool.port_factory.get_from_builder_name(name)
     395        if port.name().startswith('chromium-'):
     396            return self._tool.chromium_buildbot().builder_with_name(name)
     397        return self._tool.buildbot.builder_with_name(name)
     398
     399    def _tests_to_update(self, builder):
     400        failing_tests = builder.latest_cached_build().layout_test_results().tests_matching_failure_types([test_failures.FailureTextMismatch])
     401        return self._tool.user.prompt_with_list("Which test(s) to rebaseline for %s:" % builder.name(), failing_tests, can_choose_multiple=True)
     402
     403    def execute(self, options, args, tool):
     404        if options.builder:
     405            builders = [self._builder_with_name(options.builder)]
     406        else:
     407            builders = self._builders_to_pull_from()
     408
    395409        test_list = {}
    396         for test in self._tests_to_update(build):
    397             test_list[test] = {builder_name: ['txt']}
     410
     411        for builder in builders:
     412            tests = [options.test] if options.test else self._tests_to_update(builder)
     413            for test in tests:
     414                if test not in test_list:
     415                    test_list[test] = {}
     416                # FIXME: Allow for choosing the suffixes.
     417                test_list[test][builder.name()] = ['txt']
     418
     419        if options.verbose:
     420            print "rebaseline-json: " + str(test_list)
     421
    398422        self._rebaseline(options, test_list)
  • trunk/Tools/Scripts/webkitpy/tool/commands/rebaseline_unittest.py

    r121800 r121821  
    352352            tool.executive = MockExecutive(should_log=True)
    353353
    354             def mock_builder_to_pull_from():
    355                 return MockBuilder('MOCK builder'), 1234
     354            def mock_builders_to_pull_from():
     355                return [MockBuilder('MOCK builder')]
    356356
    357357            def mock_tests_to_update(build):
    358358                return ['mock/path/to/test.html']
    359359
    360             command._builder_to_pull_from = mock_builder_to_pull_from
     360            command._builders_to_pull_from = mock_builders_to_pull_from
    361361            command._tests_to_update = mock_tests_to_update
     362
     363            expected_stdout = """rebaseline-json: {'mock/path/to/test.html': {'MOCK builder': ['txt']}}
     364"""
    362365
    363366            expected_stderr = """MOCK run_command: ['echo', 'rebaseline-test-internal', '--suffixes', 'txt', '--builder', 'MOCK builder', '--test', 'mock/path/to/test.html'], cwd=/mock-checkout
     
    365368"""
    366369
    367             OutputCapture().assert_outputs(self, command.execute, [MockOptions(optimize=True), [], tool], expected_stderr=expected_stderr)
     370            OutputCapture().assert_outputs(self, command.execute, [MockOptions(optimize=True, builder=None, test=None, verbose=True), [], tool], expected_stdout=expected_stdout, expected_stderr=expected_stderr)
    368371
    369372        finally:
    370373            builders._exact_matches = old_exact_matches
     374
     375    def test_rebaseline_command_line_flags(self):
     376        old_exact_matches = builders._exact_matches
     377        try:
     378            builders._exact_matches = {
     379                "MOCK builder": {"port_name": "test-mac-leopard", "specifiers": set(["mock-specifier"])},
     380            }
     381
     382            command = Rebaseline()
     383            tool = MockTool()
     384            command.bind_to_tool(tool)
     385
     386            for port_name in tool.port_factory.all_port_names():
     387                port = tool.port_factory.get(port_name)
     388                for path in port.expectations_files():
     389                    tool.filesystem.write_text_file(path, '')
     390
     391            tool.executive = MockExecutive(should_log=True)
     392
     393            expected_stdout = """rebaseline-json: {'mock/path/to/test.html': {'MOCK builder': ['txt']}}
     394"""
     395
     396            expected_stderr = """MOCK run_command: ['echo', 'rebaseline-test-internal', '--suffixes', 'txt', '--builder', 'MOCK builder', '--test', 'mock/path/to/test.html'], cwd=/mock-checkout
     397MOCK run_command: ['echo', 'optimize-baselines', '--suffixes', 'txt', 'mock/path/to/test.html'], cwd=/mock-checkout
     398"""
     399
     400            builder = "MOCK builder"
     401            test = "mock/path/to/test.html"
     402            OutputCapture().assert_outputs(self, command.execute, [MockOptions(optimize=True, builder=builder, test=test, verbose=True), [], tool], expected_stdout=expected_stdout, expected_stderr=expected_stderr)
     403
     404        finally:
     405            builders._exact_matches = old_exact_matches
     406
     407    def test_rebaseline_multiple_builders(self):
     408        old_exact_matches = builders._exact_matches
     409        try:
     410            builders._exact_matches = {
     411                "MOCK builder": {"port_name": "test-mac-leopard", "specifiers": set(["mock-specifier"])},
     412                "MOCK builder2": {"port_name": "test-mac-snowleopard", "specifiers": set(["mock-specifier2"])},
     413            }
     414
     415            command = Rebaseline()
     416            tool = MockTool()
     417            command.bind_to_tool(tool)
     418
     419            for port_name in tool.port_factory.all_port_names():
     420                port = tool.port_factory.get(port_name)
     421                for path in port.expectations_files():
     422                    tool.filesystem.write_text_file(path, '')
     423
     424            tool.executive = MockExecutive(should_log=True)
     425
     426            def mock_builders_to_pull_from():
     427                return [MockBuilder('MOCK builder'), MockBuilder('MOCK builder2')]
     428
     429            def mock_tests_to_update(build):
     430                return ['mock/path/to/test.html']
     431
     432            command._builders_to_pull_from = mock_builders_to_pull_from
     433            command._tests_to_update = mock_tests_to_update
     434
     435            expected_stdout = """rebaseline-json: {'mock/path/to/test.html': {'MOCK builder2': ['txt'], 'MOCK builder': ['txt']}}
     436"""
     437
     438            expected_stderr = """MOCK run_command: ['echo', 'rebaseline-test-internal', '--suffixes', 'txt', '--builder', 'MOCK builder2', '--test', 'mock/path/to/test.html'], cwd=/mock-checkout
     439MOCK run_command: ['echo', 'rebaseline-test-internal', '--suffixes', 'txt', '--builder', 'MOCK builder', '--test', 'mock/path/to/test.html'], cwd=/mock-checkout
     440MOCK run_command: ['echo', 'optimize-baselines', '--suffixes', 'txt', 'mock/path/to/test.html'], cwd=/mock-checkout
     441"""
     442
     443            OutputCapture().assert_outputs(self, command.execute, [MockOptions(optimize=True, builder=None, test=None, verbose=True), [], tool], expected_stdout=expected_stdout, expected_stderr=expected_stderr)
     444
     445        finally:
     446            builders._exact_matches = old_exact_matches
Note: See TracChangeset for help on using the changeset viewer.