15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# Copyright (C) 2011 Google Inc. All rights reserved.
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# Redistribution and use in source and binary forms, with or without
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# modification, are permitted provided that the following conditions are
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# met:
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#     * Redistributions of source code must retain the above copyright
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# notice, this list of conditions and the following disclaimer.
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#     * Redistributions in binary form must reproduce the above
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# copyright notice, this list of conditions and the following disclaimer
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# in the documentation and/or other materials provided with the
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# distribution.
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#     * Neither the name of Google Inc. nor the names of its
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# contributors may be used to endorse or promote products derived from
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# this software without specific prior written permission.
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)"""Base class used to start servers used by the layout tests."""
305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)import errno
325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)import logging
335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)import socket
345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)import tempfile
355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)import time
365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)_log = logging.getLogger(__name__)
395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)class ServerError(Exception):
425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    pass
435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)class ServerBase(object):
465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    """A skeleton class for starting and stopping servers used by the layout tests."""
475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    def __init__(self, port_obj, output_dir):
4909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        self._port_obj = port_obj
505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        self._executive = port_obj._executive
515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        self._filesystem = port_obj._filesystem
52c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        self._platform = port_obj.host.platform
5309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        self._output_dir = output_dir
545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        # We need a non-checkout-dependent place to put lock files, etc. We
565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        # don't use the Python default on the Mac because it defaults to a
575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        # randomly-generated directory under /var/folders and no one would ever
585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        # look there.
595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        tmpdir = tempfile.gettempdir()
60c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        if self._platform.is_mac():
615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            tmpdir = '/tmp'
625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        self._runtime_path = self._filesystem.join(tmpdir, "WebKit")
645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        self._filesystem.maybe_make_directory(self._runtime_path)
655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        # Subclasses must override these fields.
6709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        self._name = '<virtual>'
6809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        self._log_prefixes = tuple()
6909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        self._mappings = {}
7009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        self._pid_file = None
7109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        self._start_cmd = None
7209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
7309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        # Subclasses may override these fields.
7409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        self._env = None
7509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        self._stdout = self._executive.PIPE
7609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        self._stderr = self._executive.PIPE
7709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        self._process = None
7809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        self._pid = None
79c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        self._error_log_path = None
8009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    def start(self):
825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        """Starts the server. It is an error to start an already started server.
835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        This method also stops any stale servers started by a previous instance."""
855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        assert not self._pid, '%s server is already running' % self._name
865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        # Stop any stale servers left over from previous instances.
885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if self._filesystem.exists(self._pid_file):
89926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            try:
90926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                self._pid = int(self._filesystem.read_text_file(self._pid_file))
91c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)                _log.debug('stale %s pid file, pid %d' % (self._name, self._pid))
92926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                self._stop_running_server()
93926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            except (ValueError, UnicodeDecodeError):
94926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                # These could be raised if the pid file is corrupt.
95926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                self._remove_pid_file()
965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            self._pid = None
975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        self._remove_stale_logs()
995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        self._prepare_config()
1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        self._check_that_all_ports_are_available()
1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        self._pid = self._spawn_process()
1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if self._wait_for_action(self._is_server_running_on_all_ports):
1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            _log.debug("%s successfully started (pid = %d)" % (self._name, self._pid))
1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        else:
107c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)            self._log_errors_from_subprocess()
1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            self._stop_running_server()
1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            raise ServerError('Failed to start %s server' % self._name)
1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    def stop(self):
1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        """Stops the server. Stopping a server that isn't started is harmless."""
1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        actual_pid = None
114926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        try:
115926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            if self._filesystem.exists(self._pid_file):
116926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                try:
117926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                    actual_pid = int(self._filesystem.read_text_file(self._pid_file))
118926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                except (ValueError, UnicodeDecodeError):
119926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                    # These could be raised if the pid file is corrupt.
120926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                    pass
121926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                if not self._pid:
122926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                    self._pid = actual_pid
123926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if not self._pid:
125926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                return
126926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
127926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            if not actual_pid:
128926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                _log.warning('Failed to stop %s: pid file is missing' % self._name)
129926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                return
130926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            if self._pid != actual_pid:
131926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                _log.warning('Failed to stop %s: pid file contains %d, not %d' %
132926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                            (self._name, actual_pid, self._pid))
133926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                # Try to kill the existing pid, anyway, in case it got orphaned.
134926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                self._executive.kill_process(self._pid)
135926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                self._pid = None
136926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                return
137926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
138926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            _log.debug("Attempting to shut down %s server at pid %d" % (self._name, self._pid))
139926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            self._stop_running_server()
140926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            _log.debug("%s server at pid %d stopped" % (self._name, self._pid))
1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            self._pid = None
142926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        finally:
143926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            # Make sure we delete the pid file no matter what happens.
144926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            self._remove_pid_file()
1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    def _prepare_config(self):
1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        """This routine can be overridden by subclasses to do any sort
1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        of initialization required prior to starting the server that may fail."""
1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        pass
1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    def _remove_stale_logs(self):
1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        """This routine can be overridden by subclasses to try and remove logs
1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        left over from a prior run. This routine should log warnings if the
1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        files cannot be deleted, but should not fail unless failure to
1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        delete the logs will actually cause start() to fail."""
15609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        # Sometimes logs are open in other processes but they should clear eventually.
15709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        for log_prefix in self._log_prefixes:
15809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            try:
15909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)                self._remove_log_files(self._output_dir, log_prefix)
16009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            except OSError, e:
16109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)                _log.warning('Failed to remove old %s %s files' % (self._name, log_prefix))
1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    def _spawn_process(self):
16409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        _log.debug('Starting %s server, cmd="%s"' % (self._name, self._start_cmd))
16509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        process = self._executive.popen(self._start_cmd, env=self._env, stdout=self._stdout, stderr=self._stderr)
16609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        pid = process.pid
16709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        self._filesystem.write_text_file(self._pid_file, str(pid))
16809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return pid
1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    def _stop_running_server(self):
17109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        self._wait_for_action(self._check_and_kill)
17209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        if self._filesystem.exists(self._pid_file):
17309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            self._filesystem.remove(self._pid_file)
1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
17509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    def _check_and_kill(self):
17609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        if self._executive.check_running_pid(self._pid):
177c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)            _log.debug('pid %d is running, killing it' % self._pid)
17809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            host = self._port_obj.host
17909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            self._executive.kill_process(self._pid)
18009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            return False
181c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        else:
182c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)            _log.debug('pid %d is not running' % self._pid)
183c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
18409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return True
1855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
186926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    def _remove_pid_file(self):
187926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if self._filesystem.exists(self._pid_file):
188926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            self._filesystem.remove(self._pid_file)
189926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    def _remove_log_files(self, folder, starts_with):
1915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        files = self._filesystem.listdir(folder)
1925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for file in files:
1935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if file.startswith(starts_with):
1945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                full_path = self._filesystem.join(folder, file)
1955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                self._filesystem.remove(full_path)
1965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
197c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    def _log_errors_from_subprocess(self):
198c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        _log.error('logging %s errors, if any' % self._name)
199c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        if self._process:
200c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)            _log.error('%s returncode %s' % (self._name, str(self._process.returncode)))
201c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)            if self._process.stderr:
202c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)                stderr_text = self._process.stderr.read()
203c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)                if stderr_text:
204c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)                    _log.error('%s stderr:' % self._name)
205c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)                    for line in stderr_text.splitlines():
206c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)                        _log.error('  %s' % line)
207c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)                else:
208c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)                    _log.error('%s no stderr' % self._name)
209c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)            else:
210c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)                _log.error('%s no stderr handle' % self._name)
211c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        else:
212c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)            _log.error('%s no process' % self._name)
213c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        if self._error_log_path and self._filesystem.exists(self._error_log_path):
214c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)            error_log_text = self._filesystem.read_text_file(self._error_log_path)
215c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)            if error_log_text:
216c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)                _log.error('%s error log (%s) contents:' % (self._name, self._error_log_path))
217c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)                for line in error_log_text.splitlines():
218c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)                    _log.error('  %s' % line)
219c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)            else:
220c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)                _log.error('%s error log empty' % self._name)
221c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)            _log.error('')
222c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        else:
223c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)            _log.error('%s no error log' % self._name)
224c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
2255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    def _wait_for_action(self, action, wait_secs=20.0, sleep_secs=1.0):
2265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        """Repeat the action for wait_sec or until it succeeds, sleeping for sleep_secs
2275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        in between each attempt. Returns whether it succeeded."""
2285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        start_time = time.time()
2295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        while time.time() - start_time < wait_secs:
2305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if action():
2315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return True
2325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            _log.debug("Waiting for action: %s" % action)
2335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            time.sleep(sleep_secs)
2345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return False
2365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    def _is_server_running_on_all_ports(self):
2385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        """Returns whether the server is running on all the desired ports."""
239c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
240c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        # TODO(dpranke): crbug/378444 maybe pid is unreliable on win?
241c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        if not self._platform.is_win() and not self._executive.check_running_pid(self._pid):
2425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            _log.debug("Server isn't running at all")
243c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)            self._log_errors_from_subprocess()
2445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            raise ServerError("Server exited")
2455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for mapping in self._mappings:
2475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            s = socket.socket()
2485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            port = mapping['port']
2495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            try:
2505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                s.connect(('localhost', port))
2515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                _log.debug("Server running on %d" % port)
2525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            except IOError, e:
2535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if e.errno not in (errno.ECONNREFUSED, errno.ECONNRESET):
2545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    raise
2555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                _log.debug("Server NOT running on %d: %s" % (port, e))
2565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return False
2575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            finally:
2585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                s.close()
2595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return True
2605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    def _check_that_all_ports_are_available(self):
2625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for mapping in self._mappings:
2635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            s = socket.socket()
264e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)            if not self._platform.is_win():
265e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)                s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
2665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            port = mapping['port']
2675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            try:
2685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                s.bind(('localhost', port))
2695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            except IOError, e:
2705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if e.errno in (errno.EALREADY, errno.EADDRINUSE):
2715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    raise ServerError('Port %d is already in use.' % port)
272c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)                elif self._platform.is_win() and e.errno in (errno.WSAEACCES,):  # pylint: disable=E1101
2735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    raise ServerError('Port %d is already in use.' % port)
2745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                else:
2755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    raise
2765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            finally:
2775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                s.close()
278c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        _log.debug('all ports are available')
279