Changeset 90417 in webkit


Ignore:
Timestamp:
Jul 5, 2011 5:07:12 PM (13 years ago)
Author:
dpranke@chromium.org
Message:

2011-07-05 Dirk Pranke <dpranke@chromium.org>

Re-land nrwt: make sharding tests needing locks less hard-coded
https://bugs.webkit.org/show_bug.cgi?id=63112

Reviewed by Ojan Vafai.

  • Scripts/webkitpy/layout_tests/layout_package/manager.py:
  • Scripts/webkitpy/layout_tests/layout_package/manager_unittest.py:
Location:
trunk/Tools
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/Tools/ChangeLog

    r90416 r90417  
     12011-07-05  Dirk Pranke  <dpranke@chromium.org>
     2
     3        Re-land nrwt: make sharding tests needing locks less hard-coded
     4        https://bugs.webkit.org/show_bug.cgi?id=63112
     5
     6        Reviewed by Ojan Vafai.
     7
     8        * Scripts/webkitpy/layout_tests/layout_package/manager.py:
     9        * Scripts/webkitpy/layout_tests/layout_package/manager_unittest.py:
     10
    1112011-07-05  Adam Barth  <abarth@webkit.org>
    212
  • trunk/Tools/Scripts/webkitpy/layout_tests/layout_package/manager.py

    r90413 r90417  
    238238
    239239
    240 class Manager:
     240class Manager(object):
    241241    """A class for managing running a series of tests on a series of layout
    242242    test files."""
     
    266266        self.LAYOUT_TESTS_DIRECTORY = "LayoutTests" + self._fs.sep
    267267        self._has_http_lock = False
     268
     269        self._remaining_locked_shards = []
    268270
    269271        # disable wss server. need to install pyOpenSSL on buildbots.
     
    543545
    544546        Return:
    545             A list of lists of TestInput objects.
    546         """
    547         # FIXME: when we added http locking, we changed how this works such
    548         # that we always lump all of the HTTP threads into a single shard.
    549         # That will slow down experimental-fully-parallel, but it's unclear
    550         # what the best alternative is completely revamping how we track
    551         # when to grab the lock.
    552 
    553         test_lists = []
     547            Two lists of lists of TestInput objects. The first list should
     548            only be run under the server lock, the second can be run whenever.
     549        """
     550        # FIXME: We still need to support multiple locked shards.
     551        locked_shards = []
     552        unlocked_shards = []
    554553        tests_to_http_lock = []
    555554        if not use_real_shards:
     
    559558                    tests_to_http_lock.append(test_input)
    560559                else:
    561                     test_lists.append((".", [test_input]))
     560                    unlocked_shards.append((".", [test_input]))
    562561        else:
    563562            tests_by_dir = {}
     
    573572                test_list = tests_by_dir[directory]
    574573                test_list_tuple = (directory, test_list)
    575                 test_lists.append(test_list_tuple)
     574                unlocked_shards.append(test_list_tuple)
    576575
    577576            # Sort the shards by directory name.
    578             test_lists.sort(lambda a, b: cmp(a[0], b[0]))
    579 
    580         # Put the http tests first. There are only a couple hundred of them,
    581         # but each http test takes a very long time to run, so sorting by the
    582         # number of tests doesn't accurately capture how long they take to run.
     577            unlocked_shards.sort(lambda a, b: cmp(a[0], b[0]))
     578
    583579        if tests_to_http_lock:
    584             test_lists.insert(0, ("tests_to_http_lock", tests_to_http_lock))
    585 
    586         return test_lists
     580            locked_shards = [("tests_to_http_lock", tests_to_http_lock)]
     581
     582        return (locked_shards, unlocked_shards)
    587583
    588584    def _contains_tests(self, subdir):
     
    629625
    630626        self._printer.print_update('Sharding tests ...')
    631         test_lists = self._shard_tests(file_list,
     627        locked_shards, unlocked_shards = self._shard_tests(file_list,
    632628            int(self._options.child_processes) > 1 and not self._options.experimental_fully_parallel)
    633629
    634         # FIXME: we need a less hard-coded way of figuring out if we need to
    635         # start the servers.
    636         if test_lists[0][0] == 'tests_to_http_lock':
     630        # FIXME: We don't have a good way to coordinate the workers so that
     631        # they don't try to run the shards that need a lock if we don't actually
     632        # have the lock. The easiest solution at the moment is to grab the
     633        # lock at the beginning of the run, and then run all of the locked
     634        # shards first. This minimizes the time spent holding the lock, but
     635        # means that we won't be running tests while we're waiting for the lock.
     636        # If this becomes a problem in practice we'll need to change this.
     637
     638        all_shards = locked_shards + unlocked_shards
     639        self._remaining_locked_shards = locked_shards
     640        if locked_shards:
    637641            self.start_servers_with_lock()
    638642
    639         num_workers = self._num_workers(len(test_lists))
     643        num_workers = self._num_workers(len(all_shards))
    640644        manager_connection = manager_worker_broker.get(self._port, self._options,
    641645                                                       self, worker.Worker)
     
    659663
    660664        self._printer.print_update("Starting testing ...")
    661         for test_list in test_lists:
    662             manager_connection.post_message('test_list', test_list[0], test_list[1])
     665        for shard in all_shards:
     666            manager_connection.post_message('test_list', shard[0], shard[1])
    663667
    664668        # We post one 'stop' message for each worker. Because the stop message
     
    13411345        self._group_stats[list_name] = (num_tests, elapsed_time)
    13421346
     1347        def find(name, test_lists):
     1348            for i in range(len(test_lists)):
     1349                if test_lists[i][0] == name:
     1350                    return i
     1351            return -1
     1352
     1353        index = find(list_name, self._remaining_locked_shards)
     1354        if index >= 0:
     1355            self._remaining_locked_shards.pop(index)
     1356            if not self._remaining_locked_shards:
     1357                self.stop_servers_with_lock()
     1358
    13431359    def handle_finished_test(self, source, result, elapsed_time):
    13441360        worker_state = self._worker_states[source]
  • trunk/Tools/Scripts/webkitpy/layout_tests/layout_package/manager_unittest.py

    r90413 r90417  
    2929# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    3030
    31 """Unit tests for manager.Manager()."""
     31"""Unit tests for manager.py."""
    3232
     33import StringIO
    3334import unittest
    3435
    3536from webkitpy.common.system import filesystem_mock
     37from webkitpy.common.system import outputcapture
    3638from webkitpy.thirdparty.mock import Mock
    3739
     40from webkitpy import layout_tests
     41from webkitpy.layout_tests import run_webkit_tests
    3842from webkitpy.layout_tests.layout_package.manager import Manager, natural_sort_key, path_key, TestRunInterruptedException
     43from webkitpy.layout_tests.layout_package import printing
    3944from webkitpy.layout_tests.layout_package.result_summary import ResultSummary
    4045from webkitpy.tool.mocktool import MockOptions
     
    7378        ])
    7479
    75         # FIXME: Ideally the HTTP tests don't have to all be in one shard.
    76         single_thread_results = manager._shard_tests(test_list, False)
    77         multi_thread_results = manager._shard_tests(test_list, True)
     80        single_locked, single_unlocked = manager._shard_tests(test_list, False)
     81        multi_locked, multi_unlocked = manager._shard_tests(test_list, True)
    7882
    79         self.assertEqual("tests_to_http_lock", single_thread_results[0][0])
    80         self.assertEqual(expected_tests_to_http_lock, set(single_thread_results[0][1]))
    81         self.assertEqual("tests_to_http_lock", multi_thread_results[0][0])
    82         self.assertEqual(expected_tests_to_http_lock, set(multi_thread_results[0][1]))
     83        self.assertEqual("tests_to_http_lock", single_locked[0][0])
     84        self.assertEqual(expected_tests_to_http_lock, set(single_locked[0][1]))
     85        self.assertEqual("tests_to_http_lock", multi_locked[0][0])
     86        self.assertEqual(expected_tests_to_http_lock, set(multi_locked[0][1]))
     87
     88    def test_http_locking(tester):
     89        class LockCheckingManager(Manager):
     90            def __init__(self, port, options, printer):
     91                super(LockCheckingManager, self).__init__(port, options, printer)
     92                self._finished_list_called = False
     93
     94            def handle_finished_list(self, source, list_name, num_tests, elapsed_time):
     95                if not self._finished_list_called:
     96                    tester.assertEquals(list_name, 'tests_to_http_lock')
     97                    tester.assertTrue(self._remaining_locked_shards)
     98                    tester.assertTrue(self._has_http_lock)
     99
     100                super(LockCheckingManager, self).handle_finished_list(source, list_name, num_tests, elapsed_time)
     101
     102                if not self._finished_list_called:
     103                    tester.assertEquals(self._remaining_locked_shards, [])
     104                    tester.assertFalse(self._has_http_lock)
     105                    self._finished_list_called = True
     106
     107        options, args = run_webkit_tests.parse_args(['--platform=test', '--print=nothing', 'http/tests/passes', 'passes'])
     108        port = layout_tests.port.get(port_name=options.platform, options=options)
     109        run_webkit_tests._set_up_derived_options(port, options)
     110        printer = printing.Printer(port, options, StringIO.StringIO(), StringIO.StringIO(),
     111                                   configure_logging=True)
     112        manager = LockCheckingManager(port, options, printer)
     113        manager.collect_tests(args, [])
     114        manager.parse_expectations()
     115        result_summary = manager.set_up_run()
     116        num_unexpected_results = manager.run(result_summary)
     117        manager.clean_up_run()
     118        printer.cleanup()
     119        tester.assertEquals(num_unexpected_results, 0)
    83120
    84121    def test_interrupt_if_at_failure_limits(self):
Note: See TracChangeset for help on using the changeset viewer.