[webkitpy, WinCairo] Launch Apache HTTPD for HTTP Tests.
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 9 Mar 2018 18:48:46 +0000 (18:48 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 9 Mar 2018 18:48:46 +0000 (18:48 +0000)
https://bugs.webkit.org/show_bug.cgi?id=183265

Patch by Basuke Suzuki <Basuke.Suzuki@sony.com> on 2018-03-09
Reviewed by Daniel Bates.

Launch apache httpd server from python script for WinCairo HTTP LayoutTests. By now, AppleWin uses
Cygwin to launch httpd server. This patch enables native Windows to run HTTP LayoutTests by starting
and stopping httpd server from the script.

Tools:

* Scripts/webkitpy/layout_tests/servers/apache_http_server.py:
(LayoutTestApacheHttpd.__init__):
(LayoutTestApacheHttpd._copy_apache_config_file):
(LayoutTestApacheHttpd):
(LayoutTestApacheHttpd.platform):
(LayoutTestApacheHttpd._spawn_process):
(LayoutTestApacheHttpd._stop_running_server):
(LayoutTestApacheHttpd._run):
(LayoutTestApacheHttpd._server_error):
* Scripts/webkitpy/layout_tests/servers/http_server_base.py:
(HttpServerBase.aliases):
(HttpServerBase):
(HttpServerBase._build_alias_path_pairs):
(HttpServerBase._build_alias_path_pairs._make_path):
* Scripts/webkitpy/layout_tests/servers/http_server_base_unittest.py:
(TestHttpServerBase.test_corrupt_pid_file):
(TestHttpServerBase):
(TestHttpServerBase.test_build_alias_path_pairs):
* Scripts/webkitpy/port/base.py:
(Port._apache_config_file_name_for_platform):
* Scripts/webkitpy/port/port_testcase.py:
(test_apache_config_file_name_for_platform):
* Scripts/webkitpy/port/win.py:
(WinPort._path_to_apache):
(WinCairoPort.default_baseline_search_path):
(WinCairoPort):
(WinCairoPort.check_httpd):

LayoutTests:

* http/conf/win-httpd-2.4-php7.conf: Added.
For WinCairo from native Windows environment.

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

LayoutTests/ChangeLog
LayoutTests/http/conf/win-httpd-2.4-php7.conf [new file with mode: 0644]
Tools/ChangeLog
Tools/Scripts/webkitpy/layout_tests/servers/apache_http_server.py
Tools/Scripts/webkitpy/layout_tests/servers/http_server_base.py
Tools/Scripts/webkitpy/layout_tests/servers/http_server_base_unittest.py
Tools/Scripts/webkitpy/port/base.py
Tools/Scripts/webkitpy/port/port_testcase.py
Tools/Scripts/webkitpy/port/win.py

index f189403..a13d0b2 100644 (file)
@@ -1,3 +1,17 @@
+2018-03-09  Basuke Suzuki  <Basuke.Suzuki@sony.com>
+
+        [webkitpy, WinCairo] Launch Apache HTTPD for HTTP Tests.
+        https://bugs.webkit.org/show_bug.cgi?id=183265
+
+        Reviewed by Daniel Bates.
+
+        Launch apache httpd server from python script for WinCairo HTTP LayoutTests. By now, AppleWin uses
+        Cygwin to launch httpd server. This patch enables native Windows to run HTTP LayoutTests by starting
+        and stopping httpd server from the script.
+
+        * http/conf/win-httpd-2.4-php7.conf: Added.
+        For WinCairo from native Windows environment.
+
 2018-03-09  Chris Dumez  <cdumez@apple.com>
 
         http/tests/security/frame-loading-via-document-write-async-delegates.html fails with async delegates
diff --git a/LayoutTests/http/conf/win-httpd-2.4-php7.conf b/LayoutTests/http/conf/win-httpd-2.4-php7.conf
new file mode 100644 (file)
index 0000000..2b8196a
--- /dev/null
@@ -0,0 +1,140 @@
+ServerRoot "C:\xampp\apache"
+
+Timeout 300
+KeepAlive On
+MaxKeepAliveRequests 100
+KeepAliveTimeout 15
+
+LoadModule access_compat_module modules/mod_access_compat.so
+LoadModule authn_core_module modules/mod_authn_core.so
+LoadModule authz_core_module modules/mod_authz_core.so
+LoadModule authz_host_module modules/mod_authz_host.so
+LoadModule include_module modules/mod_include.so
+LoadModule log_config_module modules/mod_log_config.so
+LoadModule headers_module modules/mod_headers.so
+LoadModule ssl_module modules/mod_ssl.so
+LoadModule mime_module modules/mod_mime.so
+LoadModule asis_module modules/mod_asis.so
+LoadModule cgi_module modules/mod_cgi.so
+LoadModule negotiation_module modules/mod_negotiation.so
+LoadModule actions_module modules/mod_actions.so
+LoadModule alias_module modules/mod_alias.so
+LoadModule rewrite_module modules/mod_rewrite.so
+LoadFile "C:\xampp\php\php7ts.dll"
+LoadFile "C:\xampp\php\libpq.dll"
+LoadModule php7_module "C:\xampp\php\php7apache2_4.dll"
+
+
+ServerName 127.0.0.1
+
+<Directory />
+    Options Indexes FollowSymLinks MultiViews ExecCGI Includes
+    AllowOverride All
+    Order allow,deny
+    Allow from all
+</Directory>
+
+AccessFileName .htaccess
+
+<Files ~ "^\.([Hh][Tt]|[Dd][Ss]_[Ss])">
+    Order allow,deny
+    Deny from all
+    Satisfy All
+</Files>
+
+UseCanonicalName On
+HostnameLookups Off
+
+ScriptInterpreterSource Registry-Strict
+
+LogLevel warn
+
+LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
+LogFormat "%h %l %u %t \"%r\" %>s %b %D" common
+LogFormat "%{Referer}i -> %U" referer
+LogFormat "%{User-agent}i" agent
+
+ServerSignature On
+
+<IfModule mod_mime.c>
+    AddLanguage da .dk
+    AddLanguage nl .nl
+    AddLanguage en .en
+    AddLanguage et .ee
+    AddLanguage fr .fr
+    AddLanguage de .de
+    AddLanguage el .el
+    AddLanguage he .he
+    AddCharset ISO-8859-8 .iso8859-8
+    AddLanguage it .it
+    AddLanguage ja .ja
+    AddCharset ISO-2022-JP .jis
+    AddLanguage kr .kr
+    AddCharset ISO-2022-KR .iso-kr
+    AddLanguage nn .nn
+    AddLanguage no .no
+    AddLanguage pl .po
+    AddCharset ISO-8859-2 .iso-pl
+    AddLanguage pt .pt
+    AddLanguage pt-br .pt-br
+    AddLanguage ltz .lu
+    AddLanguage ca .ca
+    AddLanguage es .es
+    AddLanguage sv .sv
+    AddLanguage cs .cz .cs
+    AddLanguage ru .ru
+    AddLanguage zh-TW .zh-tw
+    AddCharset Big5         .Big5    .big5
+    AddCharset WINDOWS-1251 .cp-1251
+    AddCharset CP866        .cp866
+    AddCharset ISO-8859-5   .iso-ru
+    AddCharset KOI8-R       .koi8-r
+    AddCharset UCS-2        .ucs2
+    AddCharset UCS-4        .ucs4
+    AddCharset UTF-8        .utf8
+
+    <IfModule mod_negotiation.c>
+        LanguagePriority en da nl et fr de el it ja kr no pl pt pt-br ru ltz ca es sv tw
+    </IfModule>
+
+    AddType application/x-tar .tgz
+
+    AddEncoding x-compress .Z
+    AddEncoding x-gzip .gz .tgz
+
+    AddHandler cgi-script .cgi .pl
+
+    AddType text/html .shtml
+    AddHandler server-parsed .shtml
+
+    AddHandler send-as-is asis
+</IfModule>
+
+<IfModule mod_php7.c>
+    AddType application/x-httpd-php .php
+    AddType application/x-httpd-php .bat
+    AddType application/x-httpd-php-source .phps
+
+    <IfModule mod_dir.c>
+        DirectoryIndex index.html index.php
+    </IfModule>
+
+    php_flag log_errors on
+    php_flag short_open_tag on
+</IfModule>
+
+<IfModule mod_rewrite.c>
+    RewriteEngine On
+    RewriteCond %{REQUEST_METHOD} ^TRACE
+    RewriteRule .* - [F]
+</IfModule>
+
+<IfModule ssl_module>
+SSLRandomSeed startup builtin
+SSLRandomSeed connect builtin
+</IfModule>
+
+<VirtualHost *:8443>
+    ServerName 127.0.0.1
+    SSLEngine On
+</VirtualHost>
index 9cf330e..bdf7d83 100644 (file)
@@ -1,3 +1,42 @@
+2018-03-09  Basuke Suzuki  <Basuke.Suzuki@sony.com>
+
+        [webkitpy, WinCairo] Launch Apache HTTPD for HTTP Tests.
+        https://bugs.webkit.org/show_bug.cgi?id=183265
+
+        Reviewed by Daniel Bates.
+
+        Launch apache httpd server from python script for WinCairo HTTP LayoutTests. By now, AppleWin uses
+        Cygwin to launch httpd server. This patch enables native Windows to run HTTP LayoutTests by starting
+        and stopping httpd server from the script.
+
+        * Scripts/webkitpy/layout_tests/servers/apache_http_server.py:
+        (LayoutTestApacheHttpd.__init__):
+        (LayoutTestApacheHttpd._copy_apache_config_file):
+        (LayoutTestApacheHttpd):
+        (LayoutTestApacheHttpd.platform):
+        (LayoutTestApacheHttpd._spawn_process):
+        (LayoutTestApacheHttpd._stop_running_server):
+        (LayoutTestApacheHttpd._run):
+        (LayoutTestApacheHttpd._server_error):
+        * Scripts/webkitpy/layout_tests/servers/http_server_base.py:
+        (HttpServerBase.aliases):
+        (HttpServerBase):
+        (HttpServerBase._build_alias_path_pairs):
+        (HttpServerBase._build_alias_path_pairs._make_path):
+        * Scripts/webkitpy/layout_tests/servers/http_server_base_unittest.py:
+        (TestHttpServerBase.test_corrupt_pid_file):
+        (TestHttpServerBase):
+        (TestHttpServerBase.test_build_alias_path_pairs):
+        * Scripts/webkitpy/port/base.py:
+        (Port._apache_config_file_name_for_platform):
+        * Scripts/webkitpy/port/port_testcase.py:
+        (test_apache_config_file_name_for_platform):
+        * Scripts/webkitpy/port/win.py:
+        (WinPort._path_to_apache):
+        (WinCairoPort.default_baseline_search_path):
+        (WinCairoPort):
+        (WinCairoPort.check_httpd):
+
 2018-03-09  Carlos Garcia Campos  <cgarcia@igalia.com>
 
         [GTK] Do not use WebKitDOMHTMLFormElement as argument of signal WebKitWebPage::will-submit-form
index b522dc4..1df818f 100644 (file)
@@ -101,8 +101,8 @@ class LayoutTestApacheHttpd(http_server_base.HttpServerBase):
             '-c', 'PidFile "%s"' % self._pid_file,
             '-k', "start"]
 
-        for alias in self.aliases():
-            start_cmd.extend(['-c', 'Alias %s "%s"' % (alias[0], alias[1])])
+        for (alias, path) in self.aliases():
+            start_cmd.extend(['-c', 'Alias %s "%s"' % (alias, path)])
 
         if not port_obj.host.platform.is_win():
             start_cmd.extend(['-C', 'User "%s"' % os.environ.get("USERNAME", os.environ.get("USER", ""))])
@@ -164,7 +164,7 @@ class LayoutTestApacheHttpd(http_server_base.HttpServerBase):
         # FIXME: Why do we need to copy the config file since we're not modifying it?
         self._filesystem.write_text_file(httpd_config_copy, httpd_conf)
 
-        if self._port_obj.host.platform.is_cygwin():
+        if self.platform.is_cygwin():
             # Convert to MSDOS file naming:
             precompiledDrive = re.compile('^/cygdrive/[cC]')
             httpd_config_copy = precompiledDrive.sub("C:", httpd_config_copy)
@@ -173,11 +173,15 @@ class LayoutTestApacheHttpd(http_server_base.HttpServerBase):
 
         return httpd_config_copy
 
+    @property
+    def platform(self):
+        return self._port_obj.host.platform
+
     def _spawn_process(self):
         _log.debug('Starting %s server, cmd="%s"' % (self._name, str(self._start_cmd)))
         retval, err = self._run(self._start_cmd)
         if retval or len(err):
-            raise http_server_base.ServerError('Failed to start %s: %s' % (self._name, err))
+            raise self._server_error('Failed to start %s' % self._name, err, retval)
 
         # For some reason apache isn't guaranteed to have created the pid file before
         # the process exits, so we wait a little while longer.
@@ -189,25 +193,25 @@ class LayoutTestApacheHttpd(http_server_base.HttpServerBase):
     def _stop_running_server(self):
         # If apache was forcefully killed, the pid file will not have been deleted, so check
         # that the process specified by the pid_file no longer exists before deleting the file.
-        if self._pid and not self._port_obj.host.platform.is_win() and not self._executive.check_running_pid(self._pid):
+        if self._pid and not self.platform.is_win() and not self._executive.check_running_pid(self._pid):
             self._filesystem.remove(self._pid_file)
             return
 
         retval, err = self._run(self._stop_cmd)
 
         # Windows httpd outputs shutdown status in stderr:
-        if self._port_obj.host.platform.is_win() and not retval and len(err):
+        if self.platform.is_win() and not retval and len(err):
             _log.debug('Shutdown: %s' % err)
             err = ""
 
         if retval or len(err):
-            raise http_server_base.ServerError('Failed to stop %s: %s' % (self._name, err))
+            raise self._server_error('Failed to stop %s' % self._name, err, retval)
 
         # For some reason apache isn't guaranteed to have actually stopped after
         # the stop command returns, so we wait a little while longer for the
         # pid file to be removed.
         if not self._wait_for_action(lambda: not self._filesystem.exists(self._pid_file)):
-            if self._port_obj.host.platform.is_win():
+            if self.platform.is_win():
                 self._remove_pid_file()
                 return
 
@@ -219,3 +223,8 @@ class LayoutTestApacheHttpd(http_server_base.HttpServerBase):
         retval = process.returncode
         err = process.stderr.read()
         return (retval, err)
+
+    def _server_error(self, message, stderr_output, exit_code):
+        if self.platform.is_win() and exit_code == 720005 and not stderr_output:
+            stderr_output = 'Access is denied. Do you have administrator privilege?'
+        return http_server_base.ServerError('{}: {} (exit code={})'.format(message, stderr_output, exit_code))
index 19acd7b..5fb1dc7 100644 (file)
@@ -164,11 +164,15 @@ class HttpServerBase(object):
     # Utility routines.
 
     def aliases(self):
+        """Return path pairs used to define aliases. First item is URL path and second
+        one is actual location in the file system."""
         json_data = self._filesystem.read_text_file(self._port_obj.path_from_webkit_base("Tools", "Scripts", "webkitpy", "layout_tests", "servers", "aliases.json"))
-        results = []
-        for item in json.loads(json_data):
-            results.append([item[0], self._port_obj._filesystem.join(self.tests_dir, item[1])])
-        return results
+        return self._build_alias_path_pairs(json.loads(json_data))
+
+    def _build_alias_path_pairs(self, data):
+        def _make_path(path):
+            return self._filesystem.join(self.tests_dir, self._filesystem.normpath(path))
+        return [(alias, _make_path(path)) for (alias, path) in data]
 
     def _remove_pid_file(self):
         if self._filesystem.exists(self._pid_file):
index 8b81bc3..f344b01 100644 (file)
@@ -56,3 +56,22 @@ class TestHttpServerBase(unittest.TestCase):
         # Note that the pid file would not be None if _spawn_process()
         # was actually a real implementation.
         self.assertEqual(host.filesystem.files[server._pid_file], None)
+
+    def test_build_alias_path_pairs(self):
+        host = MockHost()
+        test_port = test.TestPort(host)
+        server = HttpServerBase(test_port)
+
+        data = [
+            ['/media-resources', 'media'],
+            ['/modern-media-controls', '../Source/WebCore/Modules/modern-media-controls'],
+            ['/resources/testharness.css', 'resources/testharness.css'],
+        ]
+
+        expected = [
+            ('/media-resources', '/test.checkout/LayoutTests/media'),
+            ('/modern-media-controls', '/test.checkout/LayoutTests/../Source/WebCore/Modules/modern-media-controls'),
+            ('/resources/testharness.css', '/test.checkout/LayoutTests/resources/testharness.css'),
+        ]
+
+        self.assertEqual(server._build_alias_path_pairs(data), expected)
index cfd161a..1da06c7 100644 (file)
@@ -1250,8 +1250,10 @@ class Port(object):
 
     # We pass sys_platform into this method to make it easy to unit test.
     def _apache_config_file_name_for_platform(self, sys_platform):
-        if sys_platform == 'cygwin' or sys_platform.startswith('win'):
+        if sys_platform == 'cygwin':
             return 'apache' + self._apache_version() + '-httpd-win.conf'
+        if sys_platform == 'win32':
+            return 'win-httpd-' + self._apache_version() + '-php7.conf'
         if sys_platform == 'darwin':
             return 'apache' + self._apache_version() + self._darwin_php_version() + '-httpd.conf'
         if sys_platform.startswith('linux'):
index c3157b5..03c703a 100644 (file)
@@ -629,7 +629,7 @@ MOCK output of child process
         self._assert_config_file_for_platform(port, 'linux2', 'debian-httpd-2.2.conf')
 
         self._assert_config_file_for_platform(port, 'mac', 'apache2.2-httpd.conf')
-        self._assert_config_file_for_platform(port, 'win32', 'apache2.2-httpd-win.conf')  # win32 isn't a supported sys.platform.  AppleWin/WinCairo ports all use cygwin.
+        self._assert_config_file_for_platform(port, 'win32', 'win-httpd-2.2-php7.conf')  # WinCairo uses win32. Only AppleWin port uses cygwin.
         self._assert_config_file_for_platform(port, 'barf', 'apache2.2-httpd.conf')
 
     def test_path_to_apache_config_file(self):
index 9814613..4a3d453 100644 (file)
@@ -184,10 +184,11 @@ class WinPort(ApplePort):
         return True
 
     def _path_to_apache(self):
-        httpdPath = os.path.join('C:', 'xampp', 'apache', 'bin', 'httpd.exe')
-        if self._filesystem.exists(httpdPath):
-            return httpdPath
-        _log.error("Could not find apache. Not installed or unknown path.")
+        root = os.environ.get('XAMPP_ROOT', 'C:\\xampp')
+        path = self._filesystem.join(root, 'apache', 'bin', 'httpd.exe')
+        if self._filesystem.exists(path):
+            return path
+        _log.error('Could not find apache in the expected location. (path=%s)' % path)
         return None
 
     def _path_to_lighttpd(self):
@@ -463,3 +464,19 @@ class WinCairoPort(WinPort):
         fallback_names = ['wincairo-' + version_name_map.to_name(version, platform=self.port_name).lower().replace(' ', '') for version in fallback_versions]
         fallback_names.append('wincairo')
         return map(self._webkit_baseline_path, fallback_names)
+
+    def check_httpd(self):
+        if not super(WinCairoPort, self).check_httpd():
+            return False
+
+        path = self._path_to_apache()
+        if not path:
+            return False
+
+        # To launch Apache as a daemon, service installation is required.
+        exit_code = self._executive.run_command([path, '-k', 'install', '-T'], return_exit_code=True)
+        # 0=success, 2=already installed, 720005=permission error, etc.
+        if exit_code == 0 or exit_code == 2:
+            return True
+        _log.error('Httpd cannot run as a service. Perhaps you forgot to log in as an adminstrator user? (exit code=%s)' % exit_code)
+        return False