Commit ecadfa3e authored by Andrew Halberstadt's avatar Andrew Halberstadt
Browse files

Bug 1460914 - [mozprofile] Move mochitest's 'parseKeyValue' function into mozprofile.cli, r=ted

Parsing prefs and env on the command line is a common task performed by our harnesses, let's
move it into mozbase.

Depends on D9717

Differential Revision: https://phabricator.services.mozilla.com/D9796

--HG--
extra : moz-landing-system : lando
parent 27e3bcc6
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -17,12 +17,13 @@ sys.path.insert(

from automation import Automation
from remoteautomation import RemoteAutomation, fennecLogcatFilters
from runtests import KeyValueParseError, MochitestDesktop, MessageLogger, parseKeyValue
from runtests import KeyValueParseError, MochitestDesktop, MessageLogger
from mochitest_options import MochitestArgumentParser

from manifestparser import TestManifest
from manifestparser.filters import chunk_by_slice
from mozdevice import ADBAndroid, ADBTimeoutError
from mozprofile.cli import parse_key_value
import mozfile
import mozinfo

@@ -414,7 +415,7 @@ class RobocopTestRunner(MochitestDesktop):
        try:
            browserEnv.update(
                dict(
                    parseKeyValue(
                    parse_key_value(
                        self.options.environment,
                        context='--setenv')))
        except KeyValueParseError as e:
+5 −43
Original line number Diff line number Diff line
@@ -66,7 +66,8 @@ from leaks import ShutdownLeaks, LSANLeaks
from mochitest_options import (
    MochitestArgumentParser, build_obj, get_default_valgrind_suppression_files
)
from mozprofile import Profile, Preferences
from mozprofile import Profile
from mozprofile.cli import parse_preferences, parse_key_value, KeyValueParseError
from mozprofile.permissions import ServerLocations
from urllib import quote_plus as encodeURIComponent
from mozlog.formatters import TbplFormatter
@@ -780,31 +781,6 @@ def findTestMediaDevices(log):
    return info


class KeyValueParseError(Exception):

    """error when parsing strings of serialized key-values"""

    def __init__(self, msg, errors=()):
        self.errors = errors
        Exception.__init__(self, msg)


def parseKeyValue(strings, separator='=', context='key, value: '):
    """
    parse string-serialized key-value pairs in the form of
    `key = value`. Returns a list of 2-tuples.
    Note that whitespace is not stripped.
    """

    # syntax check
    missing = [string for string in strings if separator not in string]
    if missing:
        raise KeyValueParseError(
            "Error: syntax error in %s" %
            (context, ','.join(missing)), errors=missing)
    return [string.split(separator, 1) for string in strings]


def create_zip(path):
    """
    Takes a `path` on disk and creates a zipfile with its contents. Returns a
@@ -909,20 +885,6 @@ class MochitestDesktop(object):
        kwargs['log'] = self.log
        return test_environment(**kwargs)

    def parseExtraPrefs(self, prefs):
        """Interpolate extra preferences from option strings"""

        try:
            prefs = dict(parseKeyValue(prefs, context='--setpref='))
        except KeyValueParseError as e:
            print(str(e))
            sys.exit(1)

        for pref, value in prefs.items():
            value = Preferences.cast(value)
            prefs[pref] = value
        return prefs

    def getFullPath(self, path):
        " Get an absolute path relative to self.oldcwd."
        return os.path.normpath(
@@ -1662,7 +1624,7 @@ toolbar#nav-bar {
        try:
            browserEnv.update(
                dict(
                    parseKeyValue(
                    parse_key_value(
                        options.environment,
                        context='--setenv')))
        except KeyValueParseError as e:
@@ -2560,7 +2522,7 @@ toolbar#nav-bar {

    def runTests(self, options):
        """ Prepare, configure, run tests and cleanup """
        self.extraPrefs = self.parseExtraPrefs(options.extraPrefs)
        self.extraPrefs = parse_preferences(options.extraPrefs)

        # a11y and chrome tests don't run with e10s enabled in CI. Need to set
        # this here since |mach mochitest| sets the flavor after argument parsing.
@@ -2610,7 +2572,7 @@ toolbar#nav-bar {
                prefs = prefs.strip().split()
                self.log.info("The following extra prefs will be set:\n  {}".format(
                    '\n  '.join(prefs)))
                self.extraPrefs.update(self.parseExtraPrefs(prefs))
                self.extraPrefs.update(parse_preferences(prefs))

            # If we are using --run-by-manifest, we should not use the profile path (if) provided
            # by the user, since we need to create a new directory for each run. We would face
+52 −8
Original line number Diff line number Diff line
@@ -18,7 +18,57 @@ from .prefs import Preferences
from .profile import FirefoxProfile
from .profile import Profile

__all__ = ['MozProfileCLI', 'cli']
__all__ = ['MozProfileCLI', 'cli', 'KeyValueParseError', 'parse_key_value', 'parse_preferences']


class KeyValueParseError(Exception):
    """Error when parsing strings of serialized key-values."""

    def __init__(self, msg, errors=()):
        self.errors = errors
        Exception.__init__(self, msg)


def parse_key_value(strings, separator='=', context='key, value: '):
    """Parse string-serialized key-value pairs in the form of `key = value`.

    Args:
        strings (list): List of strings to parse.
        separator (str): Identifier used to split the strings.

    Returns:
        list: A list of (<key>, <value>) tuples. Whitespace is not stripped.

    Raises:
        KeyValueParseError
    """

    # syntax check
    missing = [string for string in strings if separator not in string]
    if missing:
        raise KeyValueParseError(
            "Error: syntax error in %s" %
            (context, ','.join(missing)), errors=missing)
    return [string.split(separator, 1) for string in strings]


def parse_preferences(prefs, context='--setpref='):
    """Parse preferences specified on the command line.

    Args:
        prefs (list): A list of strings, usually of the form "<pref>=<value>".

    Returns:
        dict: A dictionary of the form {<pref>: <value>} where values have been
              cast.
    """
    try:
        prefs = dict(parse_key_value(prefs, context=context))
    except KeyValueParseError as e:
        print(str(e))
        sys.exit(1)

    return {k: Preferences.cast(v) for k, v in prefs.items()}


class MozProfileCLI(object):
@@ -70,13 +120,7 @@ class MozProfileCLI(object):
            prefs.add_file(prefs_file)

        # change CLI preferences into 2-tuples
        separator = ':'
        cli_prefs = []
        for pref in self.options.prefs:
            if separator not in pref:
                self.parser.error("Preference must be a key-value pair separated by "
                                  "a ':' (You gave: %s)" % pref)
            cli_prefs.append(pref.split(separator, 1))
        cli_prefs = parse_key_value(self.options.prefs, separator=':')

        # string preferences
        prefs.add(cli_prefs, cast=True)