Changeset 129138 in webkit


Ignore:
Timestamp:
Sep 20, 2012 8:48:36 AM (12 years ago)
Author:
Carlos Garcia Campos
Message:

[GTK] run-api-tests should not buffer test stdout
https://bugs.webkit.org/show_bug.cgi?id=88474

Reviewed by Philippe Normand.

  • Scripts/run-gtk-tests:

(TestRunner._run_test_command): Use os.forkpty() instead of
subprocess.Popen() so that gtest sends the output with colors to
stdout. Use common.parse_output_lines() to parse the output and
write it to stdout while it's read.
(TestRunner._run_test_command.parse_line): Parse the line to get
the test pid and write the line to stdout.
(TestRunner._run_test_command.waitpid): Helper function to call
waitpid handling EINTR.
(TestRunner._run_test_command.return_code_from_exit_status):
Helper function to convert exit status of test commands to a
return code.

  • gtk/common.py:

(parse_output_lines): Helper function that uses select to read
the given file descriptor and call the given callback for every
line read.

Location:
trunk/Tools
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/Tools/ChangeLog

    r129129 r129138  
     12012-09-20  Carlos Garcia Campos  <cgarcia@igalia.com>
     2
     3        [GTK] run-api-tests should not buffer test stdout
     4        https://bugs.webkit.org/show_bug.cgi?id=88474
     5
     6        Reviewed by Philippe Normand.
     7
     8        * Scripts/run-gtk-tests:
     9        (TestRunner._run_test_command): Use os.forkpty() instead of
     10        subprocess.Popen() so that gtest sends the output with colors to
     11        stdout. Use common.parse_output_lines() to parse the output and
     12        write it to stdout while it's read.
     13        (TestRunner._run_test_command.parse_line): Parse the line to get
     14        the test pid and write the line to stdout.
     15        (TestRunner._run_test_command.waitpid): Helper function to call
     16        waitpid handling EINTR.
     17        (TestRunner._run_test_command.return_code_from_exit_status):
     18        Helper function to convert exit status of test commands to a
     19        return code.
     20        * gtk/common.py:
     21        (parse_output_lines): Helper function that uses select to read
     22        the given file descriptor and call the given callback for every
     23        line read.
     24
    1252012-09-20  Simon Hausmann  <simon.hausmann@digia.com>
    226
  • trunk/Tools/Scripts/run-gtk-tests

    r125533 r129138  
    214214            raise TestTimeout
    215215
    216         p = subprocess.Popen(command, stdout=subprocess.PIPE, env=self._test_env)
     216        child_pid = [-1]
     217        def parse_line(line, child_pid = child_pid):
     218            if child_pid[0] == -1:
     219                child_pid[0] = self._get_child_pid_from_test_output(line)
     220            sys.stdout.write(line)
     221
     222        def waitpid(pid):
     223            while True:
     224                try:
     225                    return os.waitpid(pid, 0)
     226                except (OSError, IOError) as e:
     227                    if e.errno == errno.EINTR:
     228                        continue
     229                    raise
     230
     231        def return_code_from_exit_status(status):
     232            if os.WIFSIGNALED(status):
     233                return -os.WTERMSIG(status)
     234            elif os.WIFEXITED(status):
     235                return os.WEXITSTATUS(status)
     236            else:
     237                # Should never happen
     238                raise RuntimeError("Unknown child exit status!")
     239
     240        pid, fd = os.forkpty()
     241        if pid == 0:
     242            os.execvpe(command[0], command, self._test_env)
     243            sys.exit(0)
     244
    217245        if timeout > 0:
    218246            signal(SIGALRM, alarm_handler)
    219247            alarm(timeout)
    220248
    221         stdout = ""
    222         try:
    223             stdout = p.communicate()[0]
     249        try:
     250            common.parse_output_lines(fd, parse_line)
    224251            if timeout > 0:
    225252                alarm(0)
    226             sys.stdout.write(stdout)
    227             sys.stdout.flush()
    228253        except TestTimeout:
    229             self._kill_process(p.pid)
    230             child_pid = self._get_child_pid_from_test_output(stdout)
    231             if child_pid > 0:
    232                 self._kill_process(child_pid)
     254            self._kill_process(pid)
     255            if child_pid[0] > 0:
     256                self._kill_process(child_pid[0])
    233257            raise
    234258
    235         return not p.returncode
     259        try:
     260            dummy, status = waitpid(pid)
     261        except OSError as e:
     262            if e.errno != errno.ECHILD:
     263                raise
     264            # This happens if SIGCLD is set to be ignored or waiting
     265            # for child processes has otherwise been disabled for our
     266            # process.  This child is dead, we can't get the status.
     267            status = 0
     268
     269        return not return_code_from_exit_status(status)
    236270
    237271    def _run_test_glib(self, test_program):
  • trunk/Tools/gtk/common.py

    r121837 r129138  
    1616# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
    1717
     18import errno
    1819import os
     20import select
    1921import subprocess
    2022import sys
     
    103105        return 3
    104106    return 2
     107
     108
     109def parse_output_lines(fd, parse_line_callback):
     110    output = ''
     111    read_set = [fd]
     112    while read_set:
     113        rlist, wlist, xlist = select.select(read_set, [], [])
     114
     115        if fd in rlist:
     116            try:
     117                chunk = os.read(fd, 1024)
     118            except OSError as e:
     119                if e.errno == errno.EIO:
     120                    # Child process finished.
     121                    chunk = ''
     122                else:
     123                    raise e
     124            if not chunk:
     125                read_set.remove(fd)
     126
     127            output += chunk
     128            while '\n' in output:
     129                pos = output.find('\n')
     130                parse_line_callback(output[:pos + 1])
     131                output = output[pos + 1:]
     132
     133            if len(chunk) < 1024 and output:
     134                parse_line_callback(output)
     135                output = ''
Note: See TracChangeset for help on using the changeset viewer.