DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Mercurial (02b89c29412b)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

"""Utility functions for Talos"""
from __future__ import absolute_import

import os
import platform
import re
import string
import time
import urllib
import urlparse

from mozlog import get_proxy_logger

# directory of this file for use with interpolatePath()
here = os.path.dirname(os.path.realpath(__file__))
LOG = get_proxy_logger()


class Timer(object):
    def __init__(self):
        self._start_time = 0
        self.start()

    def start(self):
        self._start_time = time.time()

    def elapsed(self):
        seconds = time.time() - self._start_time
        return time.strftime('%H:%M:%S', time.gmtime(seconds))


class TalosError(Exception):
    "Errors found while running the talos harness."


class TalosRegression(Exception):
    """When a regression is detected at runtime, report it properly
       Currently this is a simple definition so we can detect the class type
    """


class TalosCrash(Exception):
    """Exception type where we want to report a crash and stay
       compatible with tbpl while allowing us to continue on.

       https://bugzilla.mozilla.org/show_bug.cgi?id=829734
    """


def interpolate(template, **kwargs):
    """
    Use string.Template to substitute variables in a string.

    The placeholder ${talos} is always defined and will be replaced by the
    folder containing this file (global variable 'here').

    You can add placeholders using kwargs.
    """
    kwargs.setdefault('talos', here)
    return string.Template(template).safe_substitute(**kwargs)


def findall(string, token):
    """find all occurences in a string"""
    return [m.start() for m in re.finditer(re.escape(token), string)]


def tokenize(string, start, end):
    """
    tokenize a string by start + end tokens,
    returns parts and position of last token
    """
    assert end not in start, \
        "End token '%s' is contained in start token '%s'" % (end, start)
    assert start not in end, \
        "Start token '%s' is contained in end token '%s'" % (start, end)
    _start = findall(string, start)
    _end = findall(string, end)
    if not _start and not _end:
        return [], -1
    assert len(_start), "Could not find start token: '%s'" % start
    assert len(_end), "Could not find end token: '%s'" % end
    assert len(_start) == len(_end), \
        ("Unmatched number of tokens found: '%s' (%d) vs '%s' (%d)"
         % (start, len(_start), end, len(_end)))
    for i in range(len(_start)):
        assert _end[i] > _start[i], \
            "End token '%s' occurs before start token '%s'" % (end, start)
    parts = []
    for i in range(len(_start)):
        parts.append(string[_start[i] + len(start):_end[i]])
    return parts, _end[-1]


def urlsplit(url, default_scheme='file'):
    """front-end to urlparse.urlsplit"""

    if '://' not in url:
        url = '%s://%s' % (default_scheme, url)

    if url.startswith('file://'):
        # file:// URLs do not play nice with windows
        # https://bugzilla.mozilla.org/show_bug.cgi?id=793875
        return ['file', '', url[len('file://'):], '', '']

    # split the URL and return a list
    return [i for i in urlparse.urlsplit(url)]


def parse_pref(value):
    """parse a preference value from a string"""
    from mozprofile.prefs import Preferences
    return Preferences.cast(value)


def GenerateBrowserCommandLine(browser_path, extra_args, profile_dir, url, profiling_info=None):
    # TODO: allow for spaces in file names on Windows
    command_args = [browser_path.strip()]

    if platform.system() == 'Darwin':
        command_args.extend(['-foreground'])

    if isinstance(extra_args, list):
        command_args.extend(extra_args)

    elif extra_args.strip():
        command_args.extend([extra_args])

    command_args.extend(['-profile', profile_dir])

    if profiling_info:
        # pageloader tests use a tpmanifest browser pref instead of passing in a manifest url
        # profiling info is handled differently for pageloader vs non-pageloader (startup) tests
        # for pageloader the profiling info was mirrored already in an env var; so here just
        # need to setup profiling info for startup / non-pageloader tests
        if url is not None:
            # for non-pageloader/non-manifest tests the profiling info is added to the test url
            if url.find('?') != -1:
                url += '&' + urllib.urlencode(profiling_info)
            else:
                url += '?' + urllib.urlencode(profiling_info)
            command_args.extend(url.split(' '))

    # if there's a url i.e. startup test / non-manifest test, add it to the cmd line args
    if url is not None:
        command_args.extend(url.split(' '))

    return command_args


def indexed_items(itr):
    """
    Generator that allows us to figure out which item is the last one so
    that we can serialize this data properly
    """
    prev_i, prev_val = 0, itr.next()
    for i, val in enumerate(itr, start=1):
        yield prev_i, prev_val
        prev_i, prev_val = i, val
    yield -1, prev_val


def run_in_debug_mode(browser_config):
    if browser_config.get('debug') or browser_config.get('debugger') or \
            browser_config.get('debugg_args'):
        return True
    return False