# Copyright (C) 2011 Google Inc. All rights reserved.
# Copyright (c) 2015, 2016 Apple 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:
#
#     * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#     * 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.
#     * Neither the Google name 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
# OWNER OR 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 base64
import logging
import re
import shlex
import sys
import time
import os

from os.path import normpath
from webkitpy.common.system import path
from webkitpy.common.system.profiler import ProfilerFactory


_log = logging.getLogger(__name__)


class DriverInput(object):
    def __init__(self, test_name, timeout, image_hash, should_run_pixel_test, should_dump_jsconsolelog_in_stderr=None, args=None):
        self.test_name = test_name
        self.timeout = timeout  # in ms
        self.image_hash = image_hash
        self.should_run_pixel_test = should_run_pixel_test
        self.should_dump_jsconsolelog_in_stderr = should_dump_jsconsolelog_in_stderr
        self.args = args or []

    def __repr__(self):
        return "DriverInput(test_name='{}', timeout={}, image_hash={}, should_run_pixel_test={}, should_dump_jsconsolelog_in_stderr={}'".format(self.test_name, self.timeout, self.image_hash, self.should_run_pixel_test, self.should_dump_jsconsolelog_in_stderr)


class DriverOutput(object):
    """Groups information about a output from driver for easy passing
    and post-processing of data."""

    metrics_patterns = []
    metrics_patterns.append((re.compile('at \(-?[0-9]+,-?[0-9]+\) *'), ''))
    metrics_patterns.append((re.compile('size -?[0-9]+x-?[0-9]+ *'), ''))
    metrics_patterns.append((re.compile('text run width -?[0-9]+: '), ''))
    metrics_patterns.append((re.compile('text run width -?[0-9]+ [a-zA-Z ]+: '), ''))
    metrics_patterns.append((re.compile('RenderButton {BUTTON} .*'), 'RenderButton {BUTTON}'))
    metrics_patterns.append((re.compile('RenderImage {INPUT} .*'), 'RenderImage {INPUT}'))
    metrics_patterns.append((re.compile('RenderBlock {INPUT} .*'), 'RenderBlock {INPUT}'))
    metrics_patterns.append((re.compile('RenderTextControl {INPUT} .*'), 'RenderTextControl {INPUT}'))
    metrics_patterns.append((re.compile('\([0-9]+px'), 'px'))
    metrics_patterns.append((re.compile(' *" *\n +" *'), ' '))
    metrics_patterns.append((re.compile('" +$'), '"'))
    metrics_patterns.append((re.compile('- '), '-'))
    metrics_patterns.append((re.compile('\n( *)"\s+'), '\n\g<1>"'))
    metrics_patterns.append((re.compile('\s+"\n'), '"\n'))
    metrics_patterns.append((re.compile('scrollWidth [0-9]+'), 'scrollWidth'))
    metrics_patterns.append((re.compile('scrollHeight [0-9]+'), 'scrollHeight'))
    metrics_patterns.append((re.compile('scrollX [0-9]+'), 'scrollX'))
    metrics_patterns.append((re.compile('scrollY [0-9]+'), 'scrollY'))
    metrics_patterns.append((re.compile('scrolled to [0-9]+,[0-9]+'), 'scrolled'))

    def __init__(self, text, image, image_hash, audio, crash=False,
            test_time=0, measurements=None, timeout=False, error='', crashed_process_name='??',
            crashed_pid=None, crash_log=None, pid=None):
        # FIXME: Args could be renamed to better clarify what they do.
        self.text = text
        self.image = image  # May be empty-string if the test crashes.
        self.image_hash = image_hash
        self.image_diff = None  # image_diff gets filled in after construction.
        self.audio = audio  # Binary format is port-dependent.
        self.crash = crash
        self.crashed_process_name = crashed_process_name
        self.crashed_pid = crashed_pid
        self.crash_log = crash_log
        self.test_time = test_time
        self.measurements = measurements
        self.timeout = timeout
        self.error = error  # stderr output
        self.pid = pid

    def has_stderr(self):
        return bool(self.error)

    def strip_metrics(self):
        self.strip_patterns(self.metrics_patterns)

    def strip_patterns(self, patterns):
        if not self.text:
            return
        for pattern in patterns:
            self.text = re.sub(pattern[0], pattern[1], self.text)

    def strip_stderror_patterns(self, patterns):
        if not self.error:
            return
        for pattern in patterns:
            self.error = re.sub(pattern[0], pattern[1], self.error)


class Driver(object):
    """object for running test(s) using DumpRenderTree/WebKitTestRunner."""

    def __init__(self, port, worker_number, pixel_tests, no_timeout=False):
        """Initialize a Driver to subsequently run tests.

        Typically this routine will spawn DumpRenderTree in a config
        ready for subsequent input.

        port - reference back to the port object.
        worker_number - identifier for a particular worker/driver instance
        """
        self._port = port
        self._worker_number = worker_number
        self._no_timeout = no_timeout
        self._target_host = port.target_host(worker_number)

        self._driver_tempdir = None
        self._driver_user_directory_suffix = None
        self._driver_user_cache_directory = None

        # WebKitTestRunner can report back subprocess crashes by printing
        # "#CRASHED - PROCESSNAME".  Since those can happen at any time and ServerProcess
        # won't be aware of them (since the actual tool didn't crash, just a subprocess)
        # we record the crashed subprocess name here.
        self._crashed_process_name = None
        self._crashed_pid = None

        self._driver_timed_out = False

        # stderr reading is scoped on a per-test (not per-block) basis, so we store the accumulated
        # stderr output, as well as if we've seen #EOF on this driver instance.
        # FIXME: We should probably remove _read_first_block and _read_optional_image_block and
        # instead scope these locally in run_test.
        self.error_from_test = str()
        self.err_seen_eof = False

        self._server_name = self._port.driver_name()
        self._server_process = None

        self._measurements = {}
        if self._port.get_option("profile"):
            profiler_name = self._port.get_option("profiler")
            self._profiler = ProfilerFactory.create_profiler(self._port.host,
                self._port._path_to_driver(), self._port.results_directory(), profiler_name)
        else:
            self._profiler = None

        self.web_platform_test_server_doc_root = self._port.web_platform_test_server_doc_root()
        self.web_platform_test_server_base_http_url = self._port.web_platform_test_server_base_http_url()
        self.web_platform_test_server_base_https_url = self._port.web_platform_test_server_base_https_url()

    def __del__(self):
        self.stop()

    def run_test(self, driver_input, stop_when_done):
        """Run a single test and return the results.

        Note that it is okay if a test times out or crashes and leaves
        the driver in an indeterminate state. The upper layers of the program
        are responsible for cleaning up and ensuring things are okay.

        Returns a DriverOutput object.
        """
        start_time = time.time()
        self.start(driver_input.should_run_pixel_test, driver_input.args)
        test_begin_time = time.time()
        self._driver_timed_out = False
        self._crash_report_from_driver = None
        self.error_from_test = str()
        self.err_seen_eof = False

        command = self._command_from_driver_input(driver_input)

        # Certain timeouts are detected by the tool itself; tool detection is better,
        # because results contain partial output in this case. Make script timeout longer
        # by 5 seconds to avoid racing for which timeout is detected first.
        # FIXME: It's not the job of the driver to decide what the timeouts should be.
        # Move the additional timeout to driver_input.
        if self._no_timeout:
            deadline = test_begin_time + 60 * 60 * 24 * 7  # 7 days. Using sys.maxint causes a hang.
        else:
            deadline = test_begin_time + int(driver_input.timeout) / 1000.0 + 5

        self._server_process.write(command)
        text, audio = self._read_first_block(deadline, driver_input.test_name)  # First block is either text or audio
        image, actual_image_hash = self._read_optional_image_block(deadline, driver_input.test_name)  # The second (optional) block is image data.

        crashed = self.has_crashed()
        timed_out = self._server_process.timed_out
        driver_timed_out = self._driver_timed_out
        pid = self._server_process.pid()

        if stop_when_done or crashed or timed_out:
            # We call stop() even if we crashed or timed out in order to get any remaining stdout/stderr output.
            # In the timeout case, we kill the hung process as well.
            out, err = self._server_process.stop(self._port.driver_stop_timeout() if stop_when_done else 0.0)
            if out:
                text += out
            if err:
                self.error_from_test += err
            self._server_process = None

        crash_log = None
        if self._crash_report_from_driver:
            crash_log = self._crash_report_from_driver
        elif crashed:
            self.error_from_test, crash_log = self._get_crash_log(text, self.error_from_test, newer_than=start_time)
            # If we don't find a crash log use a placeholder error message instead.
            if not crash_log:
                pid_str = str(self._crashed_pid) if self._crashed_pid else "unknown pid"
                crash_log = 'No crash log found for %s:%s.\n' % (self._crashed_process_name, pid_str)

                # Print stdout and stderr to the placeholder crash log; we want as much context as possible.
                if self.error_from_test:
                    crash_log += '\nstdout:\n%s\nstderr:\n%s\n' % (text, self.error_from_test)

        return DriverOutput(text, image, actual_image_hash, audio,
            crash=crashed, test_time=time.time() - test_begin_time, measurements=self._measurements,
            timeout=timed_out or driver_timed_out, error=self.error_from_test,
            crashed_process_name=self._crashed_process_name,
            crashed_pid=self._crashed_pid, crash_log=crash_log, pid=pid)

    def _get_crash_log(self, stdout, stderr, newer_than):
        return self._port._get_crash_log(self._crashed_process_name, self._crashed_pid, stdout, stderr, newer_than, target_host=self._target_host)

    def _command_wrapper(self):
        # Hook for injecting valgrind or other runtime instrumentation, used by e.g. tools/valgrind/valgrind_tests.py.
        wrapper_arguments = []
        if self._profiler:
            wrapper_arguments = self._profiler.wrapper_arguments()
        if self._port.get_option('wrapper'):
            return shlex.split(self._port.get_option('wrapper')) + wrapper_arguments
        return wrapper_arguments

    HTTP_DIR = normpath("http/tests") + os.sep
    HTTP_LOCAL_DIR = normpath("http/tests/local") + os.sep
    WEBKIT_SPECIFIC_WEB_PLATFORM_TEST_SUBDIR = normpath("http/wpt") + os.sep
    WEBKIT_WEB_PLATFORM_TEST_SERVER_ROUTE = normpath("WebKit") + os.sep

    def is_http_test(self, test_name):
        return test_name.startswith(self.HTTP_DIR) and not test_name.startswith(self.HTTP_LOCAL_DIR)

    def is_webkit_specific_web_platform_test(self, test_name):
        return test_name.startswith(self.WEBKIT_SPECIFIC_WEB_PLATFORM_TEST_SUBDIR)

    def is_web_platform_test(self, test_name):
        return test_name.startswith(self.web_platform_test_server_doc_root)

    def wpt_test_path_to_uri(self, path):
        return self.web_platform_test_server_base_https_url + path if ".https." in path else self.web_platform_test_server_base_http_url + path

    def http_test_path_to_uri(self, path):
        path = path.replace(os.sep, '/')
        return self.http_base_url(secure=self.is_secure_path(path)) + path

    def is_secure_path(self, path):
        return path.startswith("ssl") or ".https." in path

    def http_base_url(self, secure=None):
        return "%s://127.0.0.1:%d/" % (('https', 8443) if secure else ('http', 8000))

    def test_to_uri(self, test_name):
        """Convert a test name to a URI."""
        if self.is_web_platform_test(test_name):
            return self.wpt_test_path_to_uri(test_name[len(self.web_platform_test_server_doc_root):])
        if self.is_webkit_specific_web_platform_test(test_name):
            return self.wpt_test_path_to_uri(self.WEBKIT_WEB_PLATFORM_TEST_SERVER_ROUTE + test_name[len(self.WEBKIT_SPECIFIC_WEB_PLATFORM_TEST_SUBDIR):])

        if not self.is_http_test(test_name):
            return path.abspath_to_uri(self._port.host.platform, self._port.abspath_for_test(test_name))

        return self.http_test_path_to_uri(test_name[len(self.HTTP_DIR):])

    def uri_to_test(self, uri):
        """Return the base layout test name for a given URI.

        This returns the test name for a given URI, e.g., if you passed in
        "file:///src/LayoutTests/fast/html/keygen.html" it would return
        "fast/html/keygen.html".

        """
        if uri.startswith("file:///"):
            prefix = path.abspath_to_uri(self._port.host.platform, self._port.layout_tests_dir())
            if not prefix.endswith('/'):
                prefix += '/'
            return uri[len(prefix):]
        if uri.startswith(self.web_platform_test_server_base_http_url + self.WEBKIT_WEB_PLATFORM_TEST_SERVER_ROUTE):
            return uri.replace(self.web_platform_test_server_base_http_url + self.WEBKIT_WEB_PLATFORM_TEST_SERVER_ROUTE, self.WEBKIT_SPECIFIC_WEB_PLATFORM_TEST_SUBDIR)
        if uri.startswith(self.web_platform_test_server_base_https_url + self.WEBKIT_WEB_PLATFORM_TEST_SERVER_ROUTE):
            return uri.replace(self.web_platform_test_server_base_https_url + self.WEBKIT_WEB_PLATFORM_TEST_SERVER_ROUTE, self.WEBKIT_SPECIFIC_WEB_PLATFORM_TEST_SUBDIR)
        if uri.startswith(self.web_platform_test_server_base_http_url):
            return uri.replace(self.web_platform_test_server_base_http_url, self.web_platform_test_server_doc_root)
        if uri.startswith(self.web_platform_test_server_base_https_url):
            return uri.replace(self.web_platform_test_server_base_https_url, self.web_platform_test_server_doc_root)
        if uri.startswith("http://"):
            return uri.replace(self.http_base_url(secure=False), self.HTTP_DIR)
        if uri.startswith("https://"):
            return uri.replace(self.http_base_url(secure=True), self.HTTP_DIR)
        raise NotImplementedError('unknown url type: %s' % uri)

    def has_crashed(self):
        if self._server_process is None:
            return False
        if self._crashed_process_name:
            return True
        if self._server_process.has_crashed():
            self._crashed_process_name = self._server_process.process_name()
            self._crashed_pid = self._server_process.pid()
            return True
        return False

    def start(self, pixel_tests, per_test_args):
        # FIXME: Callers shouldn't normally call this, since this routine
        # may not be specifying the correct combination of pixel test and
        # per_test args.
        #
        # The only reason we have this routine at all is so the perftestrunner
        # can pause before running a test; it might be better to push that
        # into run_test() directly.
        if not self._server_process:
            self._start(pixel_tests, per_test_args)
            self._run_post_start_tasks()

    def _append_environment_variable_path(self, environment, variable, path):
        if variable in environment:
            environment[variable] = environment[variable] + os.pathsep + path
        else:
            environment[variable] = path

    def _setup_environ_for_driver(self, environment):
        build_root_path = str(self._port._build_path())
        self._append_environment_variable_path(environment, 'DYLD_LIBRARY_PATH', build_root_path)
        self._append_environment_variable_path(environment, '__XPC_DYLD_LIBRARY_PATH', build_root_path)
        self._append_environment_variable_path(environment, 'DYLD_FRAMEWORK_PATH', build_root_path)
        self._append_environment_variable_path(environment, '__XPC_DYLD_FRAMEWORK_PATH', build_root_path)
        # Use an isolated temp directory that can be deleted after testing (especially important on Mac, as
        # CoreMedia disk cache is in the temp directory).
        environment['TMPDIR'] = str(self._driver_tempdir)
        environment['DIRHELPER_USER_DIR_SUFFIX'] = self._driver_user_directory_suffix
        # Put certain normally persistent files into the temp directory (e.g. IndexedDB storage).
        if sys.platform == 'cygwin':
            environment['DUMPRENDERTREE_TEMP'] = path.cygpath(str(self._driver_tempdir))
        else:
            environment['DUMPRENDERTREE_TEMP'] = str(self._driver_tempdir)
        environment['LOCAL_RESOURCE_ROOT'] = str(self._port.layout_tests_dir())
        environment['ASAN_OPTIONS'] = "allocator_may_return_null=1"
        environment['__XPC_ASAN_OPTIONS'] = environment['ASAN_OPTIONS']
        if self._profiler:
            environment = self._profiler.adjusted_environment(environment)
        return environment

    def _setup_environ_for_test(self):
        environment = self._port.setup_environ_for_server(self._server_name)
        environment = self._setup_environ_for_driver(environment)
        return environment

    def _start(self, pixel_tests, per_test_args):
        self.stop()
        # Each driver process should be using individual directories under _driver_tempdir (which is deleted when stopping),
        # however some subsystems on some platforms could end up using process default ones.
        self._port._clear_global_caches_and_temporary_files()
        self._driver_tempdir = self._port._driver_tempdir(self._target_host)
        self._driver_user_directory_suffix = os.path.basename(str(self._driver_tempdir))
        user_cache_directory = self._port._path_to_user_cache_directory(self._driver_user_directory_suffix)
        if user_cache_directory:
            self._target_host.filesystem.maybe_make_directory(user_cache_directory)
            self._driver_user_cache_directory = user_cache_directory
        environment = self._setup_environ_for_test()
        self._crashed_process_name = None
        self._crashed_pid = None
        self._server_process = self._port._test_runner_process_constructor(self._port, self._server_name, self.cmd_line(pixel_tests, per_test_args), environment, target_host=self._target_host)
        self._server_process.start()

    def _run_post_start_tasks(self):
        # Remote drivers may override this to delay post-start tasks until the server has ack'd.
        if self._profiler:
            self._profiler.attach_to_pid(self._pid_on_target())

    def _pid_on_target(self):
        # Remote drivers will override this method to return the pid on the device.
        return self._server_process.pid()

    def stop(self):
        if self._server_process:
            self._server_process.stop(self._port.driver_stop_timeout())
            self._server_process = None
            if self._profiler:
                self._profiler.profile_after_exit()

        if self._driver_tempdir:
            self._target_host.filesystem.rmtree(str(self._driver_tempdir))
            self._driver_tempdir = None
        if self._driver_user_cache_directory:
            self._target_host.filesystem.rmtree(self._driver_user_cache_directory)
            self._driver_user_cache_directory = None

    def cmd_line(self, pixel_tests, per_test_args):
        cmd = self._command_wrapper()
        cmd.append(self._port._path_to_driver())
        if self._port.get_option('gc_between_tests'):
            cmd.append('--gc-between-tests')
        if self._port.get_option('complex_text'):
            cmd.append('--complex-text')
        if self._port.get_option('accelerated_drawing'):
            cmd.append('--accelerated-drawing')
        if self._port.get_option('remote_layer_tree'):
            cmd.append('--remote-layer-tree')
        if self._port.get_option('threaded'):
            cmd.append('--threaded')
        if self._no_timeout:
            cmd.append('--no-timeout')
        if self._port.get_option('show_touches'):
            cmd.append('--show-touches')

        for allowed_host in self._port.allowed_hosts():
            cmd.append('--allowed-host')
            cmd.append(allowed_host)

        cmd.extend(self._port.get_option('additional_drt_flag', []))
        cmd.extend(self._port.additional_drt_flag())

        cmd.extend(per_test_args)

        cmd.append('-')
        return cmd

    def _check_for_driver_timeout(self, out_line):
        if out_line.startswith("#PID UNRESPONSIVE - "):
            match = re.match('#PID UNRESPONSIVE - (\S+)', out_line)
            child_process_name = match.group(1) if match else 'WebProcess'
            match = re.search('pid (\d+)', out_line)
            child_process_pid = int(match.group(1)) if match else None
            err_line = 'Wait on notifyDone timed out, process ' + child_process_name + ' pid = ' + str(child_process_pid)
            self.error_from_test += err_line
            _log.debug(err_line)
            if self._port.get_option("sample_on_timeout"):
                self._port.sample_process(child_process_name, child_process_pid, self._target_host)
        if out_line == "FAIL: Timed out waiting for notifyDone to be called\n":
            self._driver_timed_out = True

    def _check_for_address_sanitizer_violation(self, error_line):
        if "ERROR: AddressSanitizer" in error_line:
            return True

    def _check_for_driver_crash_or_unresponsiveness(self, error_line):
        crashed_check = error_line.rstrip('\r\n')
        if crashed_check == "#CRASHED":
            self._crashed_process_name = self._server_process.process_name()
            self._crashed_pid = self._server_process.pid()
            return True
        elif error_line.startswith("#CRASHED - "):
            match = re.match('#CRASHED - (\S+)', error_line)
            self._crashed_process_name = match.group(1) if match else 'WebProcess'
            match = re.search('pid (\d+)', error_line)
            self._crashed_pid = int(match.group(1)) if match else None
            _log.debug('%s crash, pid = %s' % (self._crashed_process_name, str(self._crashed_pid)))
            return True
        elif error_line.startswith("#PROCESS UNRESPONSIVE - "):
            match = re.match('#PROCESS UNRESPONSIVE - (\S+)', error_line)
            child_process_name = match.group(1) if match else 'WebProcess'
            match = re.search('pid (\d+)', error_line)
            child_process_pid = int(match.group(1)) if match else None
            _log.debug('%s is unresponsive, pid = %s' % (child_process_name, str(child_process_pid)))
            self._driver_timed_out = True
            if child_process_pid:
                self._port.sample_process(child_process_name, child_process_pid, self._target_host)
            self.error_from_test += error_line
            self._server_process.write('#SAMPLE FINISHED\n', True)  # Must be able to ignore a broken pipe here, target process may already be closed.
            return True
        return self.has_crashed()

    def _command_from_driver_input(self, driver_input):
        # FIXME: performance tests pass in full URLs instead of test names.
        if driver_input.test_name.startswith('http://') or driver_input.test_name.startswith('https://')  or driver_input.test_name == ('about:blank'):
            command = driver_input.test_name
        elif self.is_web_platform_test(driver_input.test_name) or self.is_webkit_specific_web_platform_test(driver_input.test_name) or self.is_http_test(driver_input.test_name):
            command = self.test_to_uri(driver_input.test_name)
            command += "'--absolutePath'"
            command += self._port.abspath_for_test(driver_input.test_name, self._target_host)
        else:
            command = self._port.abspath_for_test(driver_input.test_name, self._target_host)
            if sys.platform == 'cygwin':
                command = path.cygpath(command)

        assert not driver_input.image_hash or driver_input.should_run_pixel_test

        # ' is the separator between arguments.
        if self._port.supports_per_test_timeout():
            command += "'--timeout'%s" % driver_input.timeout
        if driver_input.should_run_pixel_test:
            command += "'--pixel-test"
        if driver_input.should_dump_jsconsolelog_in_stderr:
            command += "'--dump-jsconsolelog-in-stderr"
        if driver_input.image_hash:
            command += "'" + driver_input.image_hash
        return command + "\n"

    def _read_first_block(self, deadline, test_name):
        # returns (text_content, audio_content)
        block = self._read_block(deadline, test_name)
        if block.malloc:
            self._measurements['Malloc'] = float(block.malloc)
        if block.js_heap:
            self._measurements['JSHeap'] = float(block.js_heap)
        if block.content_type == 'audio/wav':
            return (None, block.decoded_content)
        return (block.decoded_content, None)

    def _read_optional_image_block(self, deadline, test_name):
        # returns (image, actual_image_hash)
        block = self._read_block(deadline, test_name, wait_for_stderr_eof=True)
        if block.content and block.content_type == 'image/png':
            return (block.decoded_content, block.content_hash)
        return (None, block.content_hash)

    def _read_header(self, block, line, header_text, header_attr, header_filter=None):
        if line.startswith(header_text) and getattr(block, header_attr) is None:
            value = line.split()[1]
            if header_filter:
                value = header_filter(value)
            setattr(block, header_attr, value)
            return True
        return False

    def _process_stdout_line(self, block, line):
        if (self._read_header(block, line, 'Content-Type: ', 'content_type')
            or self._read_header(block, line, 'Content-Transfer-Encoding: ', 'encoding')
            or self._read_header(block, line, 'Content-Length: ', '_content_length', int)
            or self._read_header(block, line, 'ActualHash: ', 'content_hash')
            or self._read_header(block, line, 'DumpMalloc: ', 'malloc')
            or self._read_header(block, line, 'DumpJSHeap: ', 'js_heap')):
            return
        # Note, we're not reading ExpectedHash: here, but we could.
        # If the line wasn't a header, we just append it to the content.
        block.content += line

    def _strip_eof(self, line):
        if line and line.endswith("#EOF\n"):
            return line[:-5], True
        return line, False

    def _read_block(self, deadline, test_name, wait_for_stderr_eof=False):
        block = ContentBlock()
        out_seen_eof = False
        asan_violation_detected = False

        while True:
            if out_seen_eof and (self.err_seen_eof or not wait_for_stderr_eof):
                break

            if self.err_seen_eof:
                out_line = self._server_process.read_stdout_line(deadline)
                err_line = None
            elif out_seen_eof:
                out_line = None
                err_line = self._server_process.read_stderr_line(deadline)
            else:
                out_line, err_line = self._server_process.read_either_stdout_or_stderr_line(deadline)

            # ServerProcess returns None for time outs and crashes.
            if out_line is None and err_line is None:
                break

            if out_line:
                assert not out_seen_eof
                out_line, out_seen_eof = self._strip_eof(out_line)
            if err_line:
                assert not self.err_seen_eof
                err_line, self.err_seen_eof = self._strip_eof(err_line)

            if out_line:
                self._check_for_driver_timeout(out_line)
                if out_line[-1] != "\n":
                    _log.error("  %s -> Last character read from DRT stdout line was not a newline!  This indicates either a NRWT or DRT bug." % test_name)
                content_length_before_header_check = block._content_length
                self._process_stdout_line(block, out_line)
                # FIXME: Unlike HTTP, DRT dumps the content right after printing a Content-Length header.
                # Don't wait until we're done with headers, just read the binary blob right now.
                if content_length_before_header_check != block._content_length:
                    block.content = self._server_process.read_stdout(deadline, block._content_length)

            if err_line:
                if self._check_for_driver_crash_or_unresponsiveness(err_line):
                    break
                elif self._check_for_address_sanitizer_violation(err_line):
                    asan_violation_detected = True
                    self._crash_report_from_driver = ""
                    # ASan report starts with a nondescript line, we only detect the second line.
                    end_of_previous_error_line = self.error_from_test.rfind('\n', 0, -1)
                    if end_of_previous_error_line > 0:
                        self.error_from_test = self.error_from_test[:end_of_previous_error_line]
                    else:
                        self.error_from_test = ""
                    # Symbolication can take a very long time, give it 10 extra minutes to finish.
                    # FIXME: This can likely be removed once <rdar://problem/18701447> is fixed.
                    deadline += 10 * 60 * 1000
                if asan_violation_detected:
                    self._crash_report_from_driver += err_line
                else:
                    self.error_from_test += err_line

        if asan_violation_detected and not self._crashed_process_name:
            self._crashed_process_name = self._server_process.process_name()
            self._crashed_pid = self._server_process.pid()

        block.decode_content()
        return block

    @staticmethod
    def check_driver(port):
        # This checks if the required system dependencies for the driver are met.
        # Since this is the generic class implementation, just return True.
        return True


class ContentBlock(object):
    def __init__(self):
        self.content_type = None
        self.encoding = None
        self.content_hash = None
        self._content_length = None
        # Content is treated as binary data even though the text output is usually UTF-8.
        self.content = str()  # FIXME: Should be bytearray() once we require Python 2.6.
        self.decoded_content = None
        self.malloc = None
        self.js_heap = None

    def decode_content(self):
        if self.encoding == 'base64' and self.content is not None:
            self.decoded_content = base64.b64decode(self.content)
        else:
            self.decoded_content = self.content


class DriverProxy(object):
    """A wrapper for managing two Driver instances, one with pixel tests and
    one without. This allows us to handle plain text tests and ref tests with a
    single driver."""

    def __init__(self, port, worker_number, driver_instance_constructor, pixel_tests, no_timeout):
        self._port = port
        self._worker_number = worker_number
        self._driver_instance_constructor = driver_instance_constructor
        self._no_timeout = no_timeout

        # FIXME: We shouldn't need to create a driver until we actually run a test.
        self._driver = self._make_driver(pixel_tests)
        self._driver_cmd_line = None

    def _make_driver(self, pixel_tests):
        return self._driver_instance_constructor(self._port, self._worker_number, pixel_tests, self._no_timeout)

    # FIXME: this should be a @classmethod (or implemented on Port instead).
    def is_http_test(self, test_name):
        return self._driver.is_http_test(test_name)

    def is_web_platform_test(self, test_name):
        return self._driver.is_web_platform_test(test_name)

    def is_webkit_specific_web_platform_test(self, test_name):
        return self._driver.is_webkit_specific_web_platform_test(test_name)

    # FIXME: this should be a @classmethod (or implemented on Port instead).
    def test_to_uri(self, test_name):
        return self._driver.test_to_uri(test_name)

    # FIXME: this should be a @classmethod (or implemented on Port instead).
    def uri_to_test(self, uri):
        return self._driver.uri_to_test(uri)

    def run_test(self, driver_input, stop_when_done):
        pixel_tests_needed = driver_input.should_run_pixel_test
        cmd_line_key = self._cmd_line_as_key(pixel_tests_needed, driver_input.args)
        if cmd_line_key != self._driver_cmd_line:
            self._driver.stop()
            self._driver = self._make_driver(pixel_tests_needed)
            self._driver_cmd_line = cmd_line_key

        return self._driver.run_test(driver_input, stop_when_done)

    def has_crashed(self):
        return self._driver.has_crashed()

    def stop(self):
        self._driver.stop()

    # FIXME: this should be a @classmethod (or implemented on Port instead).
    def cmd_line(self, pixel_tests=None, per_test_args=None):
        return self._driver.cmd_line(pixel_tests, per_test_args or [])

    def _cmd_line_as_key(self, pixel_tests, per_test_args):
        return ' '.join(self.cmd_line(pixel_tests, per_test_args))
