run-webkit-tests calls "nm" when it doesn't need to
authorojan@chromium.org <ojan@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 27 Jan 2012 00:03:23 +0000 (00:03 +0000)
committerojan@chromium.org <ojan@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 27 Jan 2012 00:03:23 +0000 (00:03 +0000)
https://bugs.webkit.org/show_bug.cgi?id=77143

Reviewed by Dirk Pranke.

If we are not running any test that can be skipped by checking
the DRT feature list or looking at the list of symbols, avoid calling
out to DRT or calling "nm".

This saves ~700ms on my Mac Pro. In cases where you still have to call out
to "nm" it's only a couple ms slower.

* Scripts/webkitpy/layout_tests/models/test_expectations.py:
(TestExpectations.__init__):
* Scripts/webkitpy/layout_tests/port/base.py:
(Port.skipped_tests):
* Scripts/webkitpy/layout_tests/port/webkit.py:
(WebKitPort._should_check_for_missing_features):
(WebKitPort):
(WebKitPort._should_check_for_missing_symbols):
(WebKitPort._skipped_tests_for_unsupported_features):
(WebKitPort.skipped_layout_tests):
(WebKitPort.skipped_tests):
* Scripts/webkitpy/layout_tests/port/webkit_unittest.py:
(WebKitPortTest.test_skipped_directories_for_symbols):
(test_skipped_directories_for_features):
(test_skipped_directories_for_features_no_matching_tests_in_test_list):
(test_skipped_layout_tests):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@106058 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Tools/ChangeLog
Tools/Scripts/webkitpy/layout_tests/models/test_expectations.py
Tools/Scripts/webkitpy/layout_tests/port/base.py
Tools/Scripts/webkitpy/layout_tests/port/webkit.py
Tools/Scripts/webkitpy/layout_tests/port/webkit_unittest.py

index 2486f1e..ced9a25 100644 (file)
@@ -1,3 +1,34 @@
+2012-01-26  Ojan Vafai  <ojan@chromium.org>
+
+        run-webkit-tests calls "nm" when it doesn't need to
+        https://bugs.webkit.org/show_bug.cgi?id=77143
+
+        Reviewed by Dirk Pranke.
+
+        If we are not running any test that can be skipped by checking
+        the DRT feature list or looking at the list of symbols, avoid calling
+        out to DRT or calling "nm".
+
+        This saves ~700ms on my Mac Pro. In cases where you still have to call out
+        to "nm" it's only a couple ms slower.
+
+        * Scripts/webkitpy/layout_tests/models/test_expectations.py:
+        (TestExpectations.__init__):
+        * Scripts/webkitpy/layout_tests/port/base.py:
+        (Port.skipped_tests):
+        * Scripts/webkitpy/layout_tests/port/webkit.py:
+        (WebKitPort._should_check_for_missing_features):
+        (WebKitPort):
+        (WebKitPort._should_check_for_missing_symbols):
+        (WebKitPort._skipped_tests_for_unsupported_features):
+        (WebKitPort.skipped_layout_tests):
+        (WebKitPort.skipped_tests):
+        * Scripts/webkitpy/layout_tests/port/webkit_unittest.py:
+        (WebKitPortTest.test_skipped_directories_for_symbols):
+        (test_skipped_directories_for_features):
+        (test_skipped_directories_for_features_no_matching_tests_in_test_list):
+        (test_skipped_layout_tests):
+
 2012-01-26  Benjamin Poulain  <bpoulain@apple.com>
 
         Support a suffix on ChangeLog filenames based on a configuration file
index 012135a..7fe7301 100644 (file)
@@ -707,7 +707,7 @@ class TestExpectations(object):
 
         self._expectations = self._parser.parse(expectations)
         self._add_expectations(self._expectations, overrides_allowed=False)
-        self._add_skipped_tests(port.skipped_tests())
+        self._add_skipped_tests(port.skipped_tests(tests))
 
         if overrides:
             overrides_expectations = self._parser.parse(overrides)
index ea86ec6..edd6166 100755 (executable)
@@ -600,7 +600,7 @@ class Port(object):
     def skipped_perf_tests(self):
         return self._expectations_from_skipped_files([self.perf_tests_dir()])
 
-    def skipped_tests(self):
+    def skipped_tests(self, test_list):
         return []
 
     def skips_layout_test(self, test_name):
index 0c35f49..41a152d 100644 (file)
@@ -32,6 +32,7 @@
 """WebKit implementations of the Port interface."""
 
 import base64
+import itertools
 import logging
 import operator
 import os
@@ -305,20 +306,34 @@ class WebKitPort(Port):
             "MHTMLArchive": ["mhtml"],
         }
 
-    def _skipped_tests_for_unsupported_features(self):
-        # If the port supports runtime feature detection, disable any tests
-        # for features missing from the runtime feature list.
-        supported_feature_list = self._runtime_feature_list()
-        # If _runtime_feature_list returns a non-None value, then prefer
-        # runtime feature detection over static feature detection.
-        if supported_feature_list is not None:
-            return reduce(operator.add, [directories for feature, directories in self._missing_feature_to_skipped_tests().items() if feature not in supported_feature_list])
-
-        # Runtime feature detection not supported, fallback to static dectection:
-        # Disable any tests for symbols missing from the webcore symbol string.
-        webcore_symbols_string = self._webcore_symbols_string()
-        if webcore_symbols_string is not None:
-            return reduce(operator.add, [directories for symbol_substring, directories in self._missing_symbol_to_skipped_tests().items() if symbol_substring not in webcore_symbols_string], [])
+    def _has_test_in_directories(self, directory_lists, test_list):
+        directories = itertools.chain.from_iterable(directory_lists)
+        for directory, test in itertools.product(directories, test_list):
+            if test.startswith(directory):
+                return True
+        return False
+
+    def _skipped_tests_for_unsupported_features(self, test_list):
+        # Only check the runtime feature list of there are tests in the test_list that might get skipped.
+        # This is a performance optimization to avoid the subprocess call to DRT.
+        if self._has_test_in_directories(self._missing_feature_to_skipped_tests().values(), test_list):
+            # If the port supports runtime feature detection, disable any tests
+            # for features missing from the runtime feature list.
+            supported_feature_list = self._runtime_feature_list()
+            # If _runtime_feature_list returns a non-None value, then prefer
+            # runtime feature detection over static feature detection.
+            if supported_feature_list is not None:
+                return reduce(operator.add, [directories for feature, directories in self._missing_feature_to_skipped_tests().items() if feature not in supported_feature_list])
+
+        # Only check the symbols of there are tests in the test_list that might get skipped.
+        # This is a performance optimization to avoid the calling nm.
+        if self._has_test_in_directories(self._missing_symbol_to_skipped_tests().values(), test_list):
+            # Runtime feature detection not supported, fallback to static dectection:
+            # Disable any tests for symbols missing from the webcore symbol string.
+            webcore_symbols_string = self._webcore_symbols_string()
+            if webcore_symbols_string is not None:
+                return reduce(operator.add, [directories for symbol_substring, directories in self._missing_symbol_to_skipped_tests().items() if symbol_substring not in webcore_symbols_string], [])
+
         # Failed to get any runtime or symbol information, don't skip any tests.
         return []
 
@@ -350,16 +365,15 @@ class WebKitPort(Port):
             expectations = self._filesystem.read_text_file(expectations_path)
         return expectations
 
-    @memoized
-    def skipped_layout_tests(self):
+    def skipped_layout_tests(self, test_list):
         # Use a set to allow duplicates
         tests_to_skip = set(self._expectations_from_skipped_files(self._skipped_file_search_paths()))
         tests_to_skip.update(self._tests_for_other_platforms())
-        tests_to_skip.update(self._skipped_tests_for_unsupported_features())
+        tests_to_skip.update(self._skipped_tests_for_unsupported_features(test_list))
         return tests_to_skip
 
-    def skipped_tests(self):
-        return self.skipped_layout_tests()
+    def skipped_tests(self, test_list):
+        return self.skipped_layout_tests(test_list)
 
     def _build_path(self, *comps):
         # --root is used for running with a pre-built root (like from a nightly zip).
index d2056fb..a8cc8e5 100755 (executable)
@@ -111,7 +111,7 @@ class WebKitPortTest(port_testcase.PortTestCase):
             "mhtml",  # Requires MHTMLArchive
         ])
 
-        result_directories = set(TestWebKitPort(symbols_string, None)._skipped_tests_for_unsupported_features())
+        result_directories = set(TestWebKitPort(symbols_string, None)._skipped_tests_for_unsupported_features(test_list=['mathml/foo.html']))
         self.assertEqual(result_directories, expected_directories)
 
         # Test that the nm string parsing actually works:
@@ -122,7 +122,7 @@ class WebKitPortTest(port_testcase.PortTestCase):
 """
         # Note 'compositing' is not in the list of skipped directories (hence the parsing of GraphicsLayer worked):
         expected_directories = set(['mathml', 'transforms/3d', 'compositing/webgl', 'fast/canvas/webgl', 'animations/3d', 'mhtml', 'http/tests/canvas/webgl'])
-        result_directories = set(TestWebKitPort(symbols_string, None)._skipped_tests_for_unsupported_features())
+        result_directories = set(TestWebKitPort(symbols_string, None)._skipped_tests_for_unsupported_features(test_list=['mathml/foo.html']))
         self.assertEqual(result_directories, expected_directories)
 
     def test_runtime_feature_list(self):
@@ -136,11 +136,17 @@ class WebKitPortTest(port_testcase.PortTestCase):
     def test_skipped_directories_for_features(self):
         supported_features = ["Accelerated Compositing", "Foo Feature"]
         expected_directories = set(["animations/3d", "transforms/3d"])
-        result_directories = set(TestWebKitPort(None, supported_features)._skipped_tests_for_unsupported_features())
+        result_directories = set(TestWebKitPort(None, supported_features)._skipped_tests_for_unsupported_features(test_list=["animations/3d/foo.html"]))
+        self.assertEqual(result_directories, expected_directories)
+
+    def test_skipped_directories_for_features_no_matching_tests_in_test_list(self):
+        supported_features = ["Accelerated Compositing", "Foo Feature"]
+        expected_directories = set([])
+        result_directories = set(TestWebKitPort(None, supported_features)._skipped_tests_for_unsupported_features(test_list=['foo.html']))
         self.assertEqual(result_directories, expected_directories)
 
     def test_skipped_layout_tests(self):
-        self.assertEqual(TestWebKitPort(None, None).skipped_layout_tests(), set(['media']))
+        self.assertEqual(TestWebKitPort(None, None).skipped_layout_tests(test_list=[]), set(['media']))
 
     def test_skipped_file_search_paths(self):
         port = TestWebKitPort()