Changeset 90192 in webkit


Ignore:
Timestamp:
Jun 30, 2011 7:10:25 PM (13 years ago)
Author:
dpranke@chromium.org
Message:

2011-06-30 Dirk Pranke <dpranke@chromium.org>

Reviewed by Ojan Vafai.

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

This change also changes the manager logic so that it will
drop the server lock as soon as all of the shards requiring
the lock have completed.

This change includes some minor namespace/import changes in the
unit tests, and also makes the Manager a new-style object, which
it should've been all along.

  • 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

    r90191 r90192  
     12011-06-30  Dirk Pranke  <dpranke@chromium.org>
     2
     3        Reviewed by Ojan Vafai.
     4
     5        nrwt: make sharding tests needing locks less hard-coded
     6        https://bugs.webkit.org/show_bug.cgi?id=63112
     7
     8        This change also changes the manager logic so that it will
     9        drop the server lock as soon as all of the shards requiring
     10        the lock have completed.
     11
     12        This change includes some minor namespace/import changes in the
     13        unit tests, and also makes the Manager a new-style object, which
     14        it should've been all along.
     15
     16        * Scripts/webkitpy/layout_tests/layout_package/manager.py:
     17        * Scripts/webkitpy/layout_tests/layout_package/manager_unittest.py:
     18
    1192011-06-30  Adam Barth  <abarth@webkit.org>
    220
  • trunk/Tools/Scripts/webkitpy/layout_tests/layout_package/manager.py

    r90176 r90192  
    236236
    237237
    238 class Manager:
     238class Manager(object):
    239239    """A class for managing running a series of tests on a series of layout
    240240    test files."""
     
    264264        self.LAYOUT_TESTS_DIRECTORY = "LayoutTests" + self._fs.sep
    265265        self._has_http_lock = False
     266
     267        self._remaining_locked_shards = []
    266268
    267269        # disable wss server. need to install pyOpenSSL on buildbots.
     
    541543
    542544        Return:
    543             A list of lists of TestInput objects.
    544         """
    545         # FIXME: when we added http locking, we changed how this works such
    546         # that we always lump all of the HTTP threads into a single shard.
    547         # That will slow down experimental-fully-parallel, but it's unclear
    548         # what the best alternative is completely revamping how we track
    549         # when to grab the lock.
    550 
    551         test_lists = []
     545            Two lists of lists of TestInput objects. The first list should
     546            only be run under the server lock, the second can be run whenever.
     547        """
     548        # FIXME: We still need to support multiple locked shards.
     549        locked_shards = []
     550        unlocked_shards = []
    552551        tests_to_http_lock = []
    553552        if not use_real_shards:
     
    557556                    tests_to_http_lock.append(test_input)
    558557                else:
    559                     test_lists.append((".", [test_input]))
     558                    unlocked_shards.append((".", [test_input]))
    560559        else:
    561560            tests_by_dir = {}
     
    571570                test_list = tests_by_dir[directory]
    572571                test_list_tuple = (directory, test_list)
    573                 test_lists.append(test_list_tuple)
     572                unlocked_shards.append(test_list_tuple)
    574573
    575574            # Sort the shards by directory name.
    576             test_lists.sort(lambda a, b: cmp(a[0], b[0]))
    577 
    578         # Put the http tests first. There are only a couple hundred of them,
    579         # but each http test takes a very long time to run, so sorting by the
    580         # number of tests doesn't accurately capture how long they take to run.
     575            unlocked_shards.sort(lambda a, b: cmp(a[0], b[0]))
     576
    581577        if tests_to_http_lock:
    582             test_lists.insert(0, ("tests_to_http_lock", tests_to_http_lock))
    583 
    584         return test_lists
     578            locked_shards = [("tests_to_http_lock", tests_to_http_lock)]
     579
     580        return (locked_shards, unlocked_shards)
    585581
    586582    def _contains_tests(self, subdir):
     
    627623
    628624        self._printer.print_update('Sharding tests ...')
    629         test_lists = self._shard_tests(file_list,
     625        locked_shards, unlocked_shards = self._shard_tests(file_list,
    630626            int(self._options.child_processes) > 1 and not self._options.experimental_fully_parallel)
    631627
    632         # FIXME: we need a less hard-coded way of figuring out if we need to
    633         # start the servers.
    634         if test_lists[0][0] == 'tests_to_http_lock':
     628        # FIXME: We don't have a good way to coordinate the workers so that
     629        # they don't try to run the shards that need a lock if we don't actually
     630        # have the lock. The easiest solution at the moment is to grab the
     631        # lock at the beginning of the run, and then run all of the locked
     632        # shards first. This minimizes the time spent holding the lock, but
     633        # means that we won't be running tests while we're waiting for the lock.
     634        # If this becomes a problem in practice we'll need to change this.
     635
     636        all_shards = locked_shards + unlocked_shards
     637        self._remaining_locked_shards = locked_shards
     638        if locked_shards:
    635639            self.start_servers_with_lock()
    636640
    637         num_workers = self._num_workers(len(test_lists))
     641        num_workers = self._num_workers(len(all_shards))
    638642        manager_connection = manager_worker_broker.get(self._port, self._options,
    639643                                                       self, worker.Worker)
     
    657661
    658662        self._printer.print_update("Starting testing ...")
    659         for test_list in test_lists:
    660             manager_connection.post_message('test_list', test_list[0], test_list[1])
     663        for shard in all_shards:
     664            manager_connection.post_message('test_list', shard[0], shard[1])
    661665
    662666        # We post one 'stop' message for each worker. Because the stop message
     
    13551359        self._group_stats[list_name] = (num_tests, elapsed_time)
    13561360
     1361        def find(name, test_lists):
     1362            for i in range(len(test_lists)):
     1363                if test_lists[i][0] == name:
     1364                    return i
     1365            return -1
     1366
     1367        index = find(list_name, self._remaining_locked_shards)
     1368        if index >= 0:
     1369            self._remaining_locked_shards.pop(index)
     1370            if not self._remaining_locked_shards:
     1371                self.stop_servers_with_lock()
     1372
    13571373    def handle_finished_test(self, source, result, elapsed_time):
    13581374        worker_state = self._worker_states[source]
  • trunk/Tools/Scripts/webkitpy/layout_tests/layout_package/manager_unittest.py

    r89206 r90192  
    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
    38 from webkitpy.layout_tests.layout_package import manager
     40from webkitpy import layout_tests
     41from webkitpy.layout_tests import run_webkit_tests
     42from webkitpy.layout_tests.layout_package.manager import Manager, natural_sort_key, path_key
     43from webkitpy.layout_tests.layout_package import printing
    3944
    4045
    41 class ManagerWrapper(manager.Manager):
     46class ManagerWrapper(Manager):
    4247    def _get_test_input_for_file(self, test_file):
    4348        return test_file
     
    7176        ])
    7277
    73         # FIXME: Ideally the HTTP tests don't have to all be in one shard.
    74         single_thread_results = manager._shard_tests(test_list, False)
    75         multi_thread_results = manager._shard_tests(test_list, True)
     78        single_locked, single_unlocked = manager._shard_tests(test_list, False)
     79        multi_locked, multi_unlocked = manager._shard_tests(test_list, True)
    7680
    77         self.assertEqual("tests_to_http_lock", single_thread_results[0][0])
    78         self.assertEqual(expected_tests_to_http_lock, set(single_thread_results[0][1]))
    79         self.assertEqual("tests_to_http_lock", multi_thread_results[0][0])
    80         self.assertEqual(expected_tests_to_http_lock, set(multi_thread_results[0][1]))
     81        self.assertEqual("tests_to_http_lock", single_locked[0][0])
     82        self.assertEqual(expected_tests_to_http_lock, set(single_locked[0][1]))
     83        self.assertEqual("tests_to_http_lock", multi_locked[0][0])
     84        self.assertEqual(expected_tests_to_http_lock, set(multi_locked[0][1]))
     85
     86    def test_http_locking(tester):
     87        class LockCheckingManager(Manager):
     88            def __init__(self, port, options, printer):
     89                super(LockCheckingManager, self).__init__(port, options, printer)
     90                self._finished_list_called = False
     91
     92            def handle_finished_list(self, source, list_name, num_tests, elapsed_time):
     93                if not self._finished_list_called:
     94                    tester.assertEquals(list_name, 'tests_to_http_lock')
     95                    tester.assertTrue(self._remaining_locked_shards)
     96                    tester.assertTrue(self._has_http_lock)
     97
     98                super(LockCheckingManager, self).handle_finished_list(source, list_name, num_tests, elapsed_time)
     99
     100                if not self._finished_list_called:
     101                    tester.assertEquals(self._remaining_locked_shards, [])
     102                    tester.assertFalse(self._has_http_lock)
     103                    self._finished_list_called = True
     104
     105        options, args = run_webkit_tests.parse_args(['--platform=test', '--print=nothing', 'http/tests/passes', 'passes'])
     106        port = layout_tests.port.get(port_name=options.platform, options=options)
     107        run_webkit_tests._set_up_derived_options(port, options)
     108        printer = printing.Printer(port, options, StringIO.StringIO(), StringIO.StringIO(),
     109                                   configure_logging=True)
     110        manager = LockCheckingManager(port, options, printer)
     111        manager.collect_tests(args, [])
     112        manager.parse_expectations()
     113        result_summary = manager.set_up_run()
     114        num_unexpected_results = manager.run(result_summary)
     115        manager.clean_up_run()
     116        printer.cleanup()
     117        tester.assertEquals(num_unexpected_results, 0)
    81118
    82119
    83120class NaturalCompareTest(unittest.TestCase):
    84121    def assert_cmp(self, x, y, result):
    85         self.assertEquals(cmp(manager.natural_sort_key(x), manager.natural_sort_key(y)), result)
     122        self.assertEquals(cmp(natural_sort_key(x), natural_sort_key(y)), result)
    86123
    87124    def test_natural_compare(self):
     
    108145
    109146    def path_key(self, k):
    110         return manager.path_key(self.filesystem, k)
     147        return path_key(self.filesystem, k)
    111148
    112149    def assert_cmp(self, x, y, result):
Note: See TracChangeset for help on using the changeset viewer.