from __future__ import absolute_import from mozlog import get_proxy_logger from .mitmproxy import MitmproxyDesktop, MitmproxyAndroid LOG = get_proxy_logger(component='mitmproxy') playback_cls = { 'mitmproxy': MitmproxyDesktop, 'mitmproxy-android': MitmproxyAndroid, } def get_playback(config, android_device=None): tool_name = config.get('playback_tool', None) if tool_name is None: LOG.critical("playback_tool name not found in config") return if playback_cls.get(tool_name, None) is None: LOG.critical("specified playback tool is unsupported: %s" % tool_name) return None cls = playback_cls.get(tool_name) if android_device is None: return cls(config) else: return cls(config, android_device)
# 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/. from __future__ import absolute_import import json import os from manifestparser import TestManifest from mozlog import get_proxy_logger here = os.path.abspath(os.path.dirname(__file__)) raptor_ini = os.path.join(here, 'raptor.ini') tests_dir = os.path.join(here, 'tests') LOG = get_proxy_logger(component="raptor-manifest") required_settings = ['apps', 'type', 'page_cycles', 'test_url', 'measure', 'unit', 'lower_is_better', 'alert_threshold'] playback_settings = ['playback_binary_manifest', 'playback_binary_zip_mac', 'playback_pageset_manifest', 'playback_pageset_zip_mac', 'playback_recordings'] def filter_app(tests, values): for test in tests: if values["app"] in test['apps']: yield test def get_browser_test_list(browser_app):
from mozregression.errors import MozRegressionError, GoodBadExpectationError from mozregression.bisector import (Bisector, NightlyHandler, InboundHandler, Bisection) from mozregression.launchers import REGISTRY as APP_REGISTRY from mozregression.network import set_http_session from mozregression.tempdir import safe_mkdtemp from mozregression.test_runner import ManualTestRunner, CommandTestRunner from mozregression.download_manager import BuildDownloadManager from mozregression.persist_limit import PersistLimit from mozregression.fetch_build_info import (NightlyInfoFetcher, InboundInfoFetcher) from mozregression.json_pushes import JsonPushes from mozregression.bugzilla import find_bugids_in_push, bug_url from mozregression.approx_persist import ApproxPersistChooser LOG = get_proxy_logger("main") class Application(object): def __init__(self, fetch_config, options): self.fetch_config = fetch_config self.options = options self._test_runner = None self._bisector = None self._build_download_manager = None self._download_dir = options.persist self._rm_download_dir = False if not options.persist: self._download_dir = safe_mkdtemp() self._rm_download_dir = True launcher_class = APP_REGISTRY.get(fetch_config.app_name)
# 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/. # some parts of this originally taken from /testing/talos/talos/output.py """output raptor test results""" from __future__ import absolute_import import filter import json import os from mozlog import get_proxy_logger LOG = get_proxy_logger(component="raptor-output") class Output(object): """class for raptor output""" def __init__(self, results): """ - results : list of RaptorTestResult instances """ self.results = results self.summarized_results = {} def summarize(self): suites = [] test_results = { 'framework': {
import os import signal import subprocess import sys import time import mozinfo from mozlog import get_proxy_logger from mozprocess import ProcessHandler from .base import Playback here = os.path.dirname(os.path.realpath(__file__)) LOG = get_proxy_logger(component='raptor-mitmproxy') # needed so unit tests can find their imports if os.environ.get('SCRIPTSPATH', None) is not None: # in production it is env SCRIPTS_PATH mozharness_dir = os.environ['SCRIPTSPATH'] else: # locally it's in source tree mozharness_dir = os.path.join(here, '../../../mozharness') sys.path.insert(0, mozharness_dir) # required for using a python3 virtualenv on win for mitmproxy from mozharness.base.python import Python3Virtualenv from mozharness.mozilla.testing.testbase import TestingMixin from mozharness.base.vcs.vcsbase import MercurialScript
from __future__ import absolute_import, print_function import os import sys import tempfile import threading from contextlib import closing import mozfile import requests from mozlog import get_proxy_logger from mozregression.persist_limit import PersistLimit LOG = get_proxy_logger("Download") class DownloadInterrupt(Exception): pass class Download(object): """ Download is reponsible of downloading one file in the background. Example of use: :: dl = Download(url, dest) dl.start() dl.wait() # this will block until completion / cancel / error
from six.moves.urllib.request import urlretrieve try: import zstandard except ImportError: zstandard = None try: import lzma except ImportError: lzma = None from mozlog import get_proxy_logger from mozprocess import ProcessHandler from mozproxy import mozharness_dir LOG = get_proxy_logger(component="mozproxy") external_tools_path = os.environ.get("EXTERNALTOOLSPATH", None) if external_tools_path is not None: # running in production via mozharness TOOLTOOL_PATH = os.path.join(external_tools_path, "tooltool.py") else: # running locally via mach TOOLTOOL_PATH = os.path.join(mozharness_dir, "external_tools", "tooltool.py") def transform_platform(str_to_transform, config_platform, config_processor=None): """Transform platform name i.e. 'mitmproxy-rel-bin-{platform}.manifest'
# 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/. from __future__ import absolute_import import os from mozlog import get_proxy_logger here = os.path.abspath(os.path.dirname(__file__)) webext_dir = os.path.join(os.path.dirname(here), 'webext', 'raptor') LOG = get_proxy_logger(component="raptor-gen-test-config") def gen_test_config(browser, test, cs_port, b_port=0): LOG.info("writing test settings into background js, so webext can get it") data = """// this file is auto-generated by raptor, do not edit directly function getTestConfig() { return {"browser": "%s", "cs_port": "%d", "test_name": "%s", "test_settings_url": "http://localhost:%d/%s.json", "benchmark_port": "%d"}; } """ % (browser, cs_port, test, cs_port, test, b_port) webext_background_script = (os.path.join(webext_dir, "auto_gen_test_config.js"))
import datetime from mozlog import get_proxy_logger from mozregression.errors import MozRegressionError, EmptyPushlogError from mozregression.network import retry_get from mozregression import branches from mozregression.dates import is_date_or_datetime LOG = get_proxy_logger("JsonPushes") class Push(object): """ Simple wrapper around a json push object from json-pushes API. """ __slots__ = ('_data', '_push_id') # to save memory usage def __init__(self, push_id, data): self._data = data self._push_id = push_id @property def push_id(self): return self._push_id @property def changesets(self): return self._data['changesets'] @property
import tempfile import threading import requests import os import sys import mozfile from contextlib import closing from mozlog import get_proxy_logger from mozregression.persist_limit import PersistLimit LOG = get_proxy_logger('Download') class DownloadInterrupt(Exception): pass class Download(object): """ Download is reponsible of downloading one file in the background. Example of use: :: dl = Download(url, dest) dl.start() dl.wait() # this will block until completion / cancel / error If a download fail or is canceled, the temporary dest is removed from the disk.
from __future__ import absolute_import from __future__ import print_function import tempfile import threading import requests import os import sys import mozfile from contextlib import closing from mozlog import get_proxy_logger from mozregression.persist_limit import PersistLimit import six LOG = get_proxy_logger('Download') class DownloadInterrupt(Exception): pass class Download(object): """ Download is reponsible of downloading one file in the background. Example of use: :: dl = Download(url, dest) dl.start() dl.wait() # this will block until completion / cancel / error
"""Utility functions for Raptor""" # 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/. from __future__ import absolute_import import os import subprocess import sys import time from mozlog import get_proxy_logger, get_default_logger LOG = get_proxy_logger(component="raptor-utils") here = os.path.dirname(os.path.realpath(__file__)) if os.environ.get('SCRIPTSPATH', None) is not None: # in production it is env SCRIPTS_PATH mozharness_dir = os.environ['SCRIPTSPATH'] else: # locally it's in source tree mozharness_dir = os.path.join(here, '../../mozharness') sys.path.insert(0, mozharness_dir) external_tools_path = os.environ.get('EXTERNALTOOLSPATH', None) if external_tools_path is not None: # running in production via mozharness TOOLTOOL_PATH = os.path.join(external_tools_path, 'tooltool.py') else:
# 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/. # control server for raptor performance framework # communicates with the raptor browser webextension from __future__ import absolute_import import BaseHTTPServer import json import os import socket import threading from mozlog import get_proxy_logger LOG = get_proxy_logger(component='control_server') here = os.path.abspath(os.path.dirname(__file__)) def MakeCustomHandlerClass(results_handler, shutdown_browser): class MyHandler(BaseHTTPServer.BaseHTTPRequestHandler, object): def __init__(self, *args, **kwargs): self.results_handler = results_handler self.shutdown_browser = shutdown_browser super(MyHandler, self).__init__(*args, **kwargs) def do_GET(self): # get handler, received request for test settings from web ext runner self.send_response(200) head, tail = os.path.split(self.path)
import time from multiprocessing import Process from pathlib import Path from glean import Configuration, Glean, load_metrics, load_pings from mozlog import get_proxy_logger from pkg_resources import resource_filename from mozregression import __version__ LOG = get_proxy_logger("telemetry") PINGS = load_pings(resource_filename(__name__, "pings.yaml")) METRICS = load_metrics(resource_filename(__name__, "metrics.yaml")) def initialize_telemetry(upload_enabled): mozregression_path = Path.home() / ".mozilla" / "mozregression" Glean.initialize( application_id="org.mozilla.mozregression", application_version=__version__, upload_enabled=upload_enabled, configuration=Configuration(allow_multiprocessing=False), data_dir=mozregression_path / "data", ) def _send_telemetry_ping(variant, appname): METRICS.usage.variant.set(variant) METRICS.usage.app.set(appname) PINGS.usage.submit()
# 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/. """output formats for Talos""" import filter import json import utils from mozlog import get_proxy_logger # NOTE: we have a circular dependecy with output.py when we import results import results as TalosResults LOG = get_proxy_logger() def filesizeformat(bytes): """ Format the value like a 'human-readable' file size (i.e. 13 KB, 4.1 MB, 102 bytes, etc). """ bytes = float(bytes) formats = ('B', 'KB', 'MB') for f in formats: if bytes < 1024: return "%.1f%s" % (bytes, f) bytes /= 1024 return "%.1fGB" % bytes # has to be GB
# Fix intermittent bug due to strptime first call not being thread safe # see https://bugzilla.mozilla.org/show_bug.cgi?id=1200270 # and http://bugs.python.org/issue7980 import _strptime # noqa import taskcluster from mozlog import get_proxy_logger from requests import HTTPError from taskcluster.exceptions import TaskclusterFailure from mozregression.build_info import IntegrationBuildInfo, NightlyBuildInfo from mozregression.config import OLD_TC_ROOT_URL, TC_ROOT_URL, TC_ROOT_URL_MIGRATION_FLAG_DATE from mozregression.errors import BuildInfoNotFound, MozRegressionError from mozregression.json_pushes import JsonPushes, Push from mozregression.network import retry_get, url_links LOG = get_proxy_logger(__name__) class InfoFetcher(object): def __init__(self, fetch_config): self.fetch_config = fetch_config self.build_regex = re.compile(fetch_config.build_regex()) self.build_info_regex = re.compile(fetch_config.build_info_regex()) def _update_build_info_from_txt(self, build_info): if "build_txt_url" in build_info: build_info.update(self._fetch_txt_info( build_info["build_txt_url"])) def _fetch_txt_info(self, url): """
import results import subprocess import utils import mozcrash import talosconfig import shutil import mozfile from mozlog import get_proxy_logger from talos.utils import TalosCrash, TalosRegression from talos.talos_process import run_browser from talos.ffsetup import FFSetup from talos.cmanager import CounterManagement LOG = get_proxy_logger() class TTest(object): platform_type = utils.PLATFORM_TYPE def check_for_crashes(self, browser_config, minidump_dir, test_name): # check for minidumps found = mozcrash.check_for_crashes(minidump_dir, browser_config['symbols_path'], test_name=test_name) mozfile.remove(minidump_dir) if found: raise TalosCrash("Found crashes after test run, terminating test")
# 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/. # originally from talos_process.py from __future__ import absolute_import import json from mozlog import get_proxy_logger LOG = get_proxy_logger(component='raptor_process') class OutputHandler(object): def __init__(self): self.proc = None def __call__(self, line): if not line.strip(): return line = line.decode('utf-8', errors='replace') try: data = json.loads(line) except ValueError: self.process_output(line) return if isinstance(data, dict) and 'action' in data: LOG.log_raw(data)
from __future__ import absolute_import import datetime from mozlog import get_proxy_logger from mozregression.errors import MozRegressionError, EmptyPushlogError from mozregression.network import retry_get from mozregression import branches from mozregression.dates import is_date_or_datetime import six LOG = get_proxy_logger("JsonPushes") class Push(object): """ Simple wrapper around a json push object from json-pushes API. """ __slots__ = ('_data', '_push_id') # to save memory usage def __init__(self, push_id, data): self._data = data self._push_id = push_id @property def push_id(self): return self._push_id @property def changesets(self): return self._data['changesets']
objects that are loaded on demand. A BuildRange is used for bisecting builds. """ import copy import datetime from threading import Thread from mozlog import get_proxy_logger from mozregression.dates import to_date, is_date_or_datetime, \ to_datetime from mozregression.errors import BuildInfoNotFound from mozregression.fetch_build_info import (InboundInfoFetcher, NightlyInfoFetcher) LOG = get_proxy_logger("Bisector") class FutureBuildInfo(object): def __init__(self, build_info_fetcher, data): self.build_info_fetcher = build_info_fetcher self.data = data self._build_info = None def date_or_changeset(self): return self.data def _fetch(self): return self.build_info_fetcher.find_build_info(self.data) @property
import os import math import threading from mozlog import get_proxy_logger from mozregression.build_range import range_for_inbounds, range_for_nightlies from mozregression.dates import to_datetime from mozregression.errors import LauncherError, MozRegressionError, \ GoodBadExpectationError, EmptyPushlogError from mozregression.history import BisectionHistory from mozregression.branches import find_branch_in_merge_commit, get_name from mozregression.json_pushes import JsonPushes from abc import ABCMeta, abstractmethod LOG = get_proxy_logger('Bisector') def compute_steps_left(steps): if steps <= 1: return 0 return math.trunc(math.log(steps, 2)) class BisectorHandler: """ React to events of a :class:`Bisector`. This is intended to be subclassed. A BisectorHandler keep the state of the current bisection process. """ __metaclass__ = ABCMeta
# 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/. # control server for raptor performance framework # communicates with the raptor browser webextension from __future__ import absolute_import import BaseHTTPServer import json import os import socket import threading from mozlog import get_proxy_logger LOG = get_proxy_logger(component='raptor-control-server') here = os.path.abspath(os.path.dirname(__file__)) def MakeCustomHandlerClass(results_handler, shutdown_browser): class MyHandler(BaseHTTPServer.BaseHTTPRequestHandler, object): def __init__(self, *args, **kwargs): self.results_handler = results_handler self.shutdown_browser = shutdown_browser super(MyHandler, self).__init__(*args, **kwargs) def do_GET(self): # get handler, received request for test settings from web ext runner
# 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/. from __future__ import absolute_import import json import os from manifestparser import TestManifest from mozlog import get_proxy_logger here = os.path.abspath(os.path.dirname(__file__)) raptor_ini = os.path.join(here, 'raptor.ini') tests_dir = os.path.join(here, 'tests') LOG = get_proxy_logger(component="manifest") required_settings = [ 'apps', 'type', 'page_cycles', 'test_url', 'measure', 'unit', 'lower_is_better', 'alert_threshold' ] playback_settings = [ 'playback_binary_manifest', 'playback_binary_zip_mac', 'playback_pageset_manifest', 'playback_pageset_zip_mac', 'playback_recordings' ] def filter_app(tests, values): for test in tests: if values["app"] in test['apps']:
# 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/. # originally from talos_process.py from __future__ import absolute_import import json from mozlog import get_proxy_logger LOG = get_proxy_logger(component='raptor-output-handler') class OutputHandler(object): def __init__(self): self.proc = None def __call__(self, line): if not line.strip(): return line = line.decode('utf-8', errors='replace') try: data = json.loads(line) except ValueError: self.process_output(line) return if isinstance(data, dict) and 'action' in data:
# 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/. # class to process, format, and report raptor test results # received from the raptor control server from __future__ import absolute_import from mozlog import get_proxy_logger from output import Output LOG = get_proxy_logger(component='results-handler') class RaptorResultsHandler(): """Handle Raptor test results""" def __init__(self): self.results = [] self.page_timeout_list = [] self.images = [] self.supporting_data = None def add(self, new_result_json): # add to results LOG.info("received results in RaptorResultsHandler.add") new_result = RaptorTestResult(new_result_json) self.results.append(new_result) def add_image(self, screenshot, test_name, page_cycle): # add to results LOG.info("received screenshot")
# 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/. from __future__ import absolute_import import os import shutil import socket from mozlog import get_proxy_logger from wptserve import server, handlers LOG = get_proxy_logger(component="raptor-benchmark") here = os.path.abspath(os.path.dirname(__file__)) class Benchmark(object): """utility class for running benchmarks in raptor""" def __init__(self, config, test): self.config = config self.test = test # bench_dir is where we will download all mitmproxy required files # when running locally it comes from obj_path via mozharness/mach if self.config.get("obj_path", None) is not None: self.bench_dir = self.config.get("obj_path") else: # in production it is ../tasks/task_N/build/tests/raptor/raptor/...
# file, You can obtain one at http://mozilla.org/MPL/2.0/. from __future__ import absolute_import import argparse import os import socket import sys import six import webbrowser from mozlog import commandline, get_proxy_logger from mozlog.commandline import add_logging_group here = os.path.abspath(os.path.dirname(__file__)) LOG = get_proxy_logger("profiler") if six.PY2: # Import for Python 2 from SocketServer import TCPServer from SimpleHTTPServer import SimpleHTTPRequestHandler from urllib import quote else: # Import for Python 3 from socketserver import TCPServer from http.server import SimpleHTTPRequestHandler from urllib.parse import quote class ProfileServingHTTPRequestHandler(SimpleHTTPRequestHandler): """Extends the basic SimpleHTTPRequestHandler (which serves a directory
import os import re import taskcluster from datetime import datetime from taskcluster.exceptions import TaskclusterFailure from mozlog import get_proxy_logger from threading import Thread, Lock from requests import HTTPError from mozregression.network import url_links, retry_get from mozregression.errors import BuildInfoNotFound, MozRegressionError from mozregression.build_info import NightlyBuildInfo, InboundBuildInfo from mozregression.json_pushes import JsonPushes, Push from mozregression.fetch_configs import TIMESTAMP_GECKO_V2 LOG = get_proxy_logger(__name__) # Fix intermittent bug due to strptime first call not being thread safe # see https://bugzilla.mozilla.org/show_bug.cgi?id=1200270 # and http://bugs.python.org/issue7980 import _strptime # noqa class InfoFetcher(object): def __init__(self, fetch_config): self.fetch_config = fetch_config self.build_regex = re.compile(fetch_config.build_regex()) self.build_info_regex = re.compile(fetch_config.build_info_regex()) def _update_build_info_from_txt(self, build_info): if 'build_txt_url' in build_info: build_info.update(
""" Access to mozilla branches information. """ import re from collections import defaultdict from mozlog import get_proxy_logger from mozregression.errors import MozRegressionError LOG = get_proxy_logger('Branches') class Branches(object): DEFAULT_REPO_URL = 'https://hg.mozilla.org/' def __init__(self): self._branches = {} self._aliases = {} self._categories = defaultdict(list) def set_branch(self, name, path, category='default'): assert name not in self._branches, "branch %s already defined" % name self._branches[name] = self.DEFAULT_REPO_URL + path self._categories[category].append(name) def get_branches(self, category=None): if category is None: return self._branches.keys() return self._categories[category]
# 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/. from __future__ import absolute_import import os from mozlog import get_proxy_logger here = os.path.abspath(os.path.dirname(__file__)) webext_dir = os.path.join(os.path.dirname(here), 'webext', 'raptor') LOG = get_proxy_logger(component="gen_test_url") def gen_test_config(browser, test, cs_port): LOG.info("writing test settings url background js, so webext can get it") data = """// this file is auto-generated by raptor, do not edit directly function getTestConfig() { return {"browser": "%s", "test_settings_url": "http://localhost:%d/%s.json"}; } """ % (browser, cs_port, test) webext_background_script = (os.path.join(webext_dir, "auto_gen_test_config.js")) file = open(webext_background_script, "w") file.write(data) file.close()
""" Access to mozilla branches information. """ from __future__ import absolute_import import re from collections import defaultdict import six from mozlog import get_proxy_logger from mozregression.errors import MozRegressionError LOG = get_proxy_logger("Branches") class Branches(object): DEFAULT_REPO_URL = "https://hg.mozilla.org/" def __init__(self): self._branches = {} self._aliases = {} self._categories = defaultdict(list) def set_branch(self, name, path, category="default"): assert name not in self._branches, "branch %s already defined" % name self._branches[name] = self.DEFAULT_REPO_URL + path self._categories[category].append(name) def get_branches(self, category=None):
""" This module implements a :class:`TestRunner` interface for testing builds and a default implementation :class:`ManualTestRunner`. """ from mozlog import get_proxy_logger import subprocess import shlex import os import datetime from mozregression.launchers import create_launcher from mozregression.errors import TestCommandError, LauncherError LOG = get_proxy_logger("Test Runner") class TestRunner(object): """ Abstract class that allows to test a build. :meth:`evaluate` must be implemented by subclasses. """ def create_launcher(self, build_info): """ Create and returns a :class:`mozregression.launchers.Launcher`. """ if build_info.build_type == 'nightly': if isinstance(build_info.build_date, datetime.datetime):
import time import sys import subprocess from mozlog import get_proxy_logger logger = get_proxy_logger("windowController") if sys.platform == "win32": import win32gui import win32con elif sys.platform == "darwin": from appscript import * # NOQA class WindowObject(object): DEFAULT_WMCTRL_CMD = "/usr/bin/wmctrl" def __init__(self, input_window_name_list, pos_x=0, pos_y=0, window_width=800, window_height=600, window_gravity=0, current=False): self.window_type = sys.platform self.window_name_list = input_window_name_list self.window_identity = None self.window_identity_name = None self.callback_ret = None self.rect = None