| # Copyright (c) 2014, Canon Inc. All rights reserved. |
| # Redistribution and use in source and binary forms, with or without |
| # modification, are permitted provided that the following conditions |
| # are met: |
| # 1. Redistributions of source code must retain the above copyright |
| # notice, this list of conditions and the following disclaimer. |
| # 2. Redistributions in binary form must reproduce the above copyright |
| # notice, this list of conditions and the following disclaimer in the |
| # documentation and/or other materials provided with the distribution. |
| # 3. Neither the name of Canon Inc. nor the names of |
| # its contributors may be used to endorse or promote products derived |
| # from this software without specific prior written permission. |
| # THIS SOFTWARE IS PROVIDED BY CANON INC. AND ITS CONTRIBUTORS "AS IS" AND ANY |
| # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| # DISCLAIMED. IN NO EVENT SHALL CANON INC. AND ITS CONTRIBUTORS BE LIABLE FOR |
| # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
| # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
| # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
| # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| |
| import json |
| import logging |
| import time |
| |
| from webkitpy.layout_tests.servers import http_server_base |
| |
| _log = logging.getLogger(__name__) |
| |
| |
| def doc_root(port_obj): |
| doc_root = port_obj.get_option("wptserver_doc_root") |
| if doc_root is None: |
| return port_obj.host.filesystem.join("imported", "w3c", "web-platform-tests") |
| return doc_root |
| |
| |
| def wpt_config_json(port_obj): |
| config_wk_filepath = port_obj._filesystem.join(port_obj.layout_tests_dir(), "imported", "w3c", "resources", "config.json") |
| if not port_obj.host.filesystem.isfile(config_wk_filepath): |
| return |
| json_data = port_obj._filesystem.read_text_file(config_wk_filepath) |
| return json.loads(json_data) |
| |
| |
| def base_http_url(port_obj): |
| config = wpt_config_json(port_obj) |
| if not config: |
| # This should only be hit by webkitpy unit tests |
| _log.debug("No WPT config file found") |
| return "http://localhost:8800/" |
| ports = config["ports"] |
| return "http://" + config["browser_host"] + ":" + str(ports["http"][0]) + "/" |
| |
| |
| def base_https_url(port_obj): |
| config = wpt_config_json(port_obj) |
| if not config: |
| # This should only be hit by webkitpy unit tests |
| _log.debug("No WPT config file found") |
| return "https://localhost:9443/" |
| ports = config["ports"] |
| return "https://" + config["browser_host"] + ":" + str(ports["https"][0]) + "/" |
| |
| |
| def is_wpt_server_running(port_obj): |
| config = wpt_config_json(port_obj) |
| if not config: |
| return False |
| return http_server_base.HttpServerBase._is_running_on_port(config["ports"]["http"][0]) |
| |
| |
| class WebPlatformTestServer(http_server_base.HttpServerBase): |
| def __init__(self, port_obj, name, pidfile=None): |
| http_server_base.HttpServerBase.__init__(self, port_obj) |
| self._output_dir = port_obj.results_directory() |
| |
| self._name = name |
| self._log_file_name = '%s_process_log.out.txt' % (self._name) |
| |
| self._output_log_path = None |
| self._wsout = None |
| self._process = None |
| self._pid_file = pidfile |
| if not self._pid_file: |
| self._pid_file = self._filesystem.join(self._runtime_path, '%s.pid' % self._name) |
| |
| self._filesystem = port_obj.host.filesystem |
| self._layout_root = port_obj.layout_tests_dir() |
| self._doc_root = self._filesystem.join(self._layout_root, doc_root(port_obj)) |
| |
| self._doc_root_path = self._filesystem.join(self._layout_root, self._doc_root) |
| self._config_filename = self._filesystem.join(self._doc_root_path, "config.json") |
| |
| wpt_file = self._filesystem.join(self._doc_root_path, "wpt.py") |
| self._start_cmd = ["python", wpt_file, "serve", "--config", self._config_filename] |
| |
| self._mappings = [] |
| config = wpt_config_json(port_obj) |
| if config: |
| ports = config["ports"] |
| for key in ports: |
| for value in ports[key]: |
| port = {"port": value} |
| if key == "https": |
| port["sslcert"] = True |
| self._mappings.append(port) |
| |
| def ports_to_forward(self): |
| return [mapping['port'] for mapping in self._mappings] |
| |
| def _prepare_config(self): |
| self._filesystem.maybe_make_directory(self._output_dir) |
| self._output_log_path = self._filesystem.join(self._output_dir, self._log_file_name) |
| self._wsout = self._filesystem.open_text_file_for_writing(self._output_log_path) |
| |
| _log.debug('Copying WebKit web platform server config.json') |
| config_wk_filename = self._filesystem.join(self._layout_root, "imported", "w3c", "resources", "config.json") |
| if self._filesystem.isfile(config_wk_filename): |
| config = json.loads(self._filesystem.read_text_file(config_wk_filename)) |
| config['ssl']['openssl']['base_path'] = self._filesystem.join(self._output_dir, "_wpt_certs") |
| self._filesystem.write_text_file(self._config_filename, json.dumps(config)) |
| |
| def _spawn_process(self): |
| self._process = self._executive.popen(self._start_cmd, cwd=self._doc_root_path, shell=False, stdin=self._executive.PIPE, stdout=self._wsout, stderr=self._wsout) |
| self._filesystem.write_text_file(self._pid_file, str(self._process.pid)) |
| |
| # Wait a second for the server to actually start so that tests do not start until server is running. |
| time.sleep(1) |
| |
| # The server is not running after 1 second, something went wrong. |
| if self._process.poll() is not None: |
| self._stop_running_server() |
| error_log = ('WPT Server process exited prematurely with status code %s\n' % self._process.returncode |
| + 'The cmdline for running the WPT server was: %s\n' % self._start_cmd |
| + 'The working dir was: %s\n' % self._doc_root_path) |
| if self._output_log_path is not None and self._filesystem.exists(self._output_log_path): |
| error_log += 'Check the logfile for the command at: %s\n' % self._output_log_path |
| raise http_server_base.ServerError(error_log) |
| |
| return self._process.pid |
| |
| def _stop_running_server(self): |
| _log.debug('Cleaning WPT web platform server config.json') |
| if self._filesystem.isfile(self._config_filename): |
| self._filesystem.remove(self._config_filename) |
| |
| if self._wsout: |
| self._wsout.close() |
| self._wsout = None |
| |
| if self._pid: |
| # kill_process will not kill the subprocesses, interrupt does the job. |
| self._executive.interrupt(self._pid) |
| |
| self._remove_pid_file() |