2010-02-22 Dirk Pranke <dpranke@chromium.org>
authoreric@webkit.org <eric@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 23 Feb 2010 07:53:40 +0000 (07:53 +0000)
committereric@webkit.org <eric@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 23 Feb 2010 07:53:40 +0000 (07:53 +0000)
        Reviewed by Eric Siedel.

        Add more checking for missing binaries and packages to check_sys_deps()

        https://bugs.webkit.org/show_bug.cgi?id=35062

        * Scripts/webkitpy/layout_tests/port/base.py:
        * Scripts/webkitpy/layout_tests/port/chromium.py:
        * Scripts/webkitpy/layout_tests/port/chromium_linux.py:
        * Scripts/webkitpy/layout_tests/port/chromium_mac.py:
        * Scripts/webkitpy/layout_tests/port/chromium_win.py:
        * Scripts/webkitpy/layout_tests/run_chromium_webkit_tests.py:

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

WebKitTools/ChangeLog
WebKitTools/Scripts/webkitpy/layout_tests/port/base.py
WebKitTools/Scripts/webkitpy/layout_tests/port/chromium.py
WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_linux.py
WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_mac.py
WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_win.py
WebKitTools/Scripts/webkitpy/layout_tests/run_chromium_webkit_tests.py

index 9c410c2..31d1ca7 100644 (file)
@@ -1,3 +1,18 @@
+2010-02-22  Dirk Pranke  <dpranke@chromium.org>
+
+        Reviewed by Eric Siedel.
+
+        Add more checking for missing binaries and packages to check_sys_deps()
+
+        https://bugs.webkit.org/show_bug.cgi?id=35062
+
+        * Scripts/webkitpy/layout_tests/port/base.py:
+        * Scripts/webkitpy/layout_tests/port/chromium.py:
+        * Scripts/webkitpy/layout_tests/port/chromium_linux.py:
+        * Scripts/webkitpy/layout_tests/port/chromium_mac.py:
+        * Scripts/webkitpy/layout_tests/port/chromium_win.py:
+        * Scripts/webkitpy/layout_tests/run_chromium_webkit_tests.py:
+
 2010-02-22  Shinichiro Hamaji  <hamaji@chromium.org>
 
         Reviewed by David Levin.
index 2b25e29..cb1e0e9 100644 (file)
@@ -68,7 +68,7 @@ class Port(object):
         baselines. The directories are searched in order."""
         raise NotImplementedError('Port.baseline_search_path')
 
-    def check_sys_deps(self):
+    def check_sys_deps(self, needs_http):
         """If the port needs to do some runtime checks to ensure that the
         tests can be run successfully, they should be done here.
 
@@ -547,7 +547,7 @@ class Port(object):
         This is needed only by ports that use the apache_http_server module."""
         raise NotImplementedError('Port.path_to_apache_config_file')
 
-    def _path_to_driver(self):
+    def _path_to_driver(self, target=None):
         """Returns the full path to the test driver (DumpRenderTree)."""
         raise NotImplementedError('Port.path_to_driver')
 
index 1123376..c81d0a7 100644 (file)
@@ -42,6 +42,14 @@ import http_server
 import websocket_server
 
 
+def check_file_exists(path_to_file, str):
+    """Verify the executable is present where expected or log an error."""
+    if not os.path.exists(path_to_file):
+        logging.error('Unable to find %s at %s' % (str, path_to_file))
+        return False
+    return True
+
+
 class ChromiumPort(base.Port):
     """Abstract base class for Chromium implementations of the Port class."""
 
@@ -52,28 +60,33 @@ class ChromiumPort(base.Port):
     def baseline_path(self):
         return self._chromium_baseline_path(self._name)
 
-    def check_sys_deps(self):
+    def check_sys_deps(self, needs_http):
         result = True
         test_shell_binary_path = self._path_to_driver()
-        if os.path.exists(test_shell_binary_path):
+        result = check_file_exists(test_shell_binary_path,
+                                   'test driver')
+        if result:
+            result = (self._check_build_up_to_date(self._options.target)
+                      and result)
+
             proc = subprocess.Popen([test_shell_binary_path,
                                      '--check-layout-test-sys-deps'])
             if proc.wait() != 0:
-                logging.error("Aborting because system dependencies check "
-                              "failed.")
-                logging.error("To override, invoke with --nocheck-sys-deps")
+                logging.error('System dependencies check failed.')
+                logging.error('To override, invoke with --nocheck-sys-deps')
+                logging.error('')
                 result = False
+
         else:
-            logging.error('test driver is not found at %s' %
-                          test_shell_binary_path)
-            result = False
+            logging.error('')
 
-        image_diff_path = self._path_to_image_diff()
-        if (not os.path.exists(image_diff_path) and not
-            self._options.no_pixel_tests):
-            logging.error('image diff not found at %s' % image_diff_path)
-            logging.error("To override, invoke with --no-pixel-tests")
-            result = False
+
+        if not self._options.no_pixel_tests:
+            image_diff_path = self._path_to_image_diff()
+            if not check_file_exists(image_diff_path, 'image diff exe'):
+                logging.error('To override, invoke with --no-pixel-tests')
+                logging.error('')
+                result = False
 
         return result
 
@@ -151,12 +164,36 @@ class ChromiumPort(base.Port):
     # or any subclasses.
     #
 
+    def _check_build_up_to_date(self, target):
+        if target in ('Debug', 'Release'):
+            try:
+                debug_path = self._path_to_driver('Debug')
+                release_path = self._path_to_driver('Release')
+
+                debug_mtime = os.stat(debug_path).st_mtime
+                release_mtime = os.stat(release_path).st_mtime
+
+                if (debug_mtime > release_mtime and target == 'Release' or
+                    release_mtime > debug_mtime and target == 'Debug'):
+                    logging.warning('You are not running the most '
+                                    'recent test_shell binary. You need to '
+                                    'pass --debug or not to select between '
+                                    'Debug and Release.')
+                    logging.warning('')
+            # This will fail if we don't have both a debug and release binary.
+            # That's fine because, in this case, we must already be running the
+            # most up-to-date one.
+            except OSError:
+                pass
+        return True
+
     def _chromium_baseline_path(self, platform):
         if platform is None:
             platform = self.name()
         return self.path_from_chromium_base('webkit', 'data', 'layout_tests',
             'platform', platform, 'LayoutTests')
 
+
 class ChromiumDriver(base.Driver):
     """Abstract interface for the DumpRenderTree interface."""
 
index b817251..7495572 100644 (file)
@@ -27,8 +27,9 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-"""Chromium Mac implementation of the Port interface."""
+"""Chromium Linux implementation of the Port interface."""
 
+import logging
 import os
 import platform
 import signal
@@ -53,9 +54,21 @@ class ChromiumLinuxPort(chromium.ChromiumPort):
                 self._webkit_baseline_path('win'),
                 self._webkit_baseline_path('mac')]
 
-    def check_sys_deps(self):
-        # We have no platform-specific dependencies to check.
-        return True
+    def check_sys_deps(self, needs_http):
+        result = chromium.ChromiumPort.check_sys_deps(self, needs_http)
+        if needs_http:
+            if self._options.use_apache:
+                result = self._check_apache_install() and result
+            else:
+                result = self._check_lighttpd_install() and result
+        result = self._check_wdiff_install() and result
+
+        if not result:
+            logging.error('For complete Linux build requirements, please see:')
+            logging.error('')
+            logging.error('    http://code.google.com/p/chromium/wiki/'
+                          'LinuxBuildInstructions')
+        return result
 
     def num_cores(self):
         num_cores = os.sysconf("SC_NPROCESSORS_ONLN")
@@ -78,11 +91,42 @@ class ChromiumLinuxPort(chromium.ChromiumPort):
     def _build_path(self, *comps):
         base = self.path_from_chromium_base()
         if os.path.exists(os.path.join(base, 'sconsbuild')):
-            return self.path_from_chromium_base('sconsbuild',
-                self._options.target, *comps)
+            return self.path_from_chromium_base('sconsbuild', *comps)
         else:
-            return self.path_from_chromium_base('out',
-                self._options.target, *comps)
+            return self.path_from_chromium_base('out', *comps)
+
+    def _check_apache_install(self):
+        result = chromium.check_file_exists(self._path_to_apache(),
+            "apache2")
+        result = chromium.check_file_exists(self._path_to_apache_config_file(),
+            "apache2 config file") and result
+        if not result:
+            logging.error('Please install using: "sudo apt-get install '
+                          'apache2 libapache2-mod-php5"')
+            logging.error('')
+        return result
+
+    def _check_lighttpd_install(self):
+        result = chromium.check_file_exists(
+            self._path_to_lighttpd(), "LigHTTPd executable")
+        result = chromium.check_file_exists(self._path_to_lighttpd_php(),
+            "PHP CGI executable") and result
+        result = chromium.check_file_exists(self._path_to_lighttpd_modules(),
+            "LigHTTPd modules") and result
+        if not result:
+            logging.error('Please install using: "sudo apt-get install '
+                          'lighttpd php5-cgi"')
+            logging.error('')
+        return result
+
+    def _check_wdiff_install(self):
+        result = chromium.check_file_exists(self._path_to_wdiff(), 'wdiff')
+        if not result:
+            logging.error('Please install using: "sudo apt-get install '
+                          'wdiff"')
+            logging.error('')
+        return result
+
 
     def _kill_process(self, pid):
         """Forcefully kill the process.
@@ -114,17 +158,19 @@ class ChromiumLinuxPort(chromium.ChromiumPort):
     def _path_to_lighttpd_php(self):
         return "/usr/bin/php-cgi"
 
-    def _path_to_driver(self):
-        return self._build_path('test_shell')
+    def _path_to_driver(self, target=None):
+        if not target:
+            target = self._options.target
+        return self._build_path(target, 'test_shell')
 
     def _path_to_helper(self):
         return None
 
     def _path_to_image_diff(self):
-        return self._build_path('image_diff')
+        return self._build_path(self._options.target, 'image_diff')
 
     def _path_to_wdiff(self):
-        return 'wdiff'
+        return '/usr/bin/wdiff'
 
     def _shut_down_http_server(self, server_pid):
         """Shut down the lighttpd web server. Blocks until it's fully
index bcffcf8..7e4f264 100644 (file)
@@ -29,6 +29,7 @@
 
 """Chromium Mac implementation of the Port interface."""
 
+import logging
 import os
 import platform
 import signal
@@ -52,9 +53,15 @@ class ChromiumMacPort(chromium.ChromiumPort):
                 self._webkit_baseline_path('mac' + self.version()),
                 self._webkit_baseline_path('mac')]
 
-    def check_sys_deps(self):
-        # We have no specific platform dependencies.
-        return True
+    def check_sys_deps(self, needs_http):
+        result = chromium.ChromiumPort.check_sys_deps(self, needs_http)
+        result = self._check_wdiff_install() and result
+        if not result:
+            logging.error('For complete Mac build requirements, please see:')
+            logging.error('')
+            logging.error('    http://code.google.com/p/chromium/wiki/'
+                          'MacBuildInstructions')
+        return result
 
     def num_cores(self):
         return int(subprocess.Popen(['sysctl','-n','hw.ncpu'],
@@ -81,8 +88,17 @@ class ChromiumMacPort(chromium.ChromiumPort):
     #
 
     def _build_path(self, *comps):
-        return self.path_from_chromium_base('xcodebuild', self._options.target,
-                                            *comps)
+        return self.path_from_chromium_base('xcodebuild', *comps)
+
+    def _check_wdiff_install(self):
+        f = open(os.devnull, 'w')
+        rcode = subprocess.call(['wdiff'], stderr=f)
+        f.close()
+        if rcode == 127:
+            logging.error('wdiff not found. Install using MacPorts or some '
+                          'other means')
+            return False
+        return True
 
     def _lighttpd_path(self, *comps):
         return self.path_from_chromium_base('third_party', 'lighttpd',
@@ -124,17 +140,19 @@ class ChromiumMacPort(chromium.ChromiumPort):
     def _path_to_lighttpd_php(self):
         return self._lighttpd_path('bin', 'php-cgi')
 
-    def _path_to_driver(self):
+    def _path_to_driver(self, target=None):
         # TODO(pinkerton): make |target| happy with case-sensitive file
         # systems.
-        return self._build_path('TestShell.app', 'Contents', 'MacOS', 
+        if not target:
+            target = self._options.target
+        return self._build_path(target, 'TestShell.app', 'Contents', 'MacOS',
                                 'TestShell')
 
     def _path_to_helper(self):
-        return self._build_path('layout_test_helper')
+        return self._build_path(self._options.target, 'layout_test_helper')
 
     def _path_to_image_diff(self):
-        return self._build_path('image_diff')
+        return self._build_path(self._options.target, 'image_diff')
 
     def _path_to_wdiff(self):
         return 'wdiff'
index 5eb0ba1..25b1a2a 100644 (file)
@@ -29,6 +29,7 @@
 
 """Chromium Win implementation of the Port interface."""
 
+import logging
 import os
 import platform
 import signal
@@ -59,9 +60,15 @@ class ChromiumWinPort(chromium.ChromiumPort):
         dirs.append(self._webkit_baseline_path('mac'))
         return dirs
 
-    def check_sys_deps(self):
-        # TODO(dpranke): implement this
-        return True
+    def check_sys_deps(self, needs_http):
+        result = chromium.ChromiumPort.check_sys_deps(self, needs_http)
+        if not result:
+            logging.error('For complete Windows build requirements, please '
+                          'see:')
+            logging.error('')
+            logging.error('    http://dev.chromium.org/developers/how-tos/'
+                          'build-instructions-windows')
+        return result
 
     def get_absolute_path(self, filename):
         """Return the absolute path in unix format for the given filename."""
@@ -94,9 +101,10 @@ class ChromiumWinPort(chromium.ChromiumPort):
     #
 
     def _build_path(self, *comps):
-        # FIXME(dpranke): allow for builds under 'chrome' as well.
-        return self.path_from_chromium_base('webkit', self._options.target,
-                                            *comps)
+        p = self.path_from_chromium_base('webkit', *comps)
+        if os.path.exists(p):
+            return p
+        return self.path_from_chromium_base('chrome', *comps)
 
     def _lighttpd_path(self, *comps):
         return self.path_from_chromium_base('third_party', 'lighttpd', 'win',
@@ -129,14 +137,16 @@ class ChromiumWinPort(chromium.ChromiumPort):
     def _path_to_lighttpd_php(self):
         return self._lighttpd_path('php5', 'php-cgi.exe')
 
-    def _path_to_driver(self):
-        return self._build_path('test_shell.exe')
+    def _path_to_driver(self, target=None):
+        if not target:
+            target = self._options.target
+        return self._build_path(target, 'test_shell.exe')
 
     def _path_to_helper(self):
-        return self._build_path('layout_test_helper.exe')
+        return self._build_path(self._options.target, 'layout_test_helper.exe')
 
     def _path_to_image_diff(self):
-        return self._build_path('image_diff.exe')
+        return self._build_path(self._options.target, 'image_diff.exe')
 
     def _path_to_wdiff(self):
         return self.path_from_chromium_base('third_party', 'cygwin', 'bin',
index f0b68ee..b6d9b35 100755 (executable)
@@ -495,7 +495,7 @@ class TestRunner:
         return test_args, png_path, shell_args
 
     def _contains_tests(self, subdir):
-        for test_file in self._test_files_list:
+        for test_file in self._test_files:
             if test_file.find(subdir) >= 0:
                 return True
         return False
@@ -594,6 +594,10 @@ class TestRunner:
         self.update_summary(result_summary)
         return (thread_timings, test_timings, individual_test_timings)
 
+    def needs_http(self):
+        """Returns whether the test runner needs an HTTP server."""
+        return self._contains_tests(self.HTTP_SUBDIR)
+
     def run(self, result_summary):
         """Run all our tests on all our test files.
 
@@ -614,7 +618,7 @@ class TestRunner:
         if not self._options.no_pixel_tests:
             self._port.start_helper()
 
-        if self._contains_tests(self.HTTP_SUBDIR):
+        if self.needs_http():
             self._port.start_http_server()
 
         if self._contains_tests(self.WEBSOCKET_SUBDIR):
@@ -1458,7 +1462,7 @@ def main(options, args):
 
     # Check that the system dependencies (themes, fonts, ...) are correct.
     if not options.nocheck_sys_deps:
-        if not port_obj.check_sys_deps():
+        if not port_obj.check_sys_deps(test_runner.needs_http()):
             sys.exit(1)
 
     write = create_logging_writer(options, "config")