Пример #1
0
class FennecLauncher(Launcher):
    app_info = None
    adb = None
    package_name = None
    profile_class = FirefoxRegressionProfile
    remote_profile = None

    @classmethod
    def check_is_runnable(cls):
        try:
            devices = ADBHost().devices()
        except ADBError as adb_error:
            raise LauncherNotRunnable(str(adb_error))
        if not devices:
            raise LauncherNotRunnable("No android device connected."
                                      " Connect a device and try again.")

    def _install(self, dest):
        # get info now, as dest may be removed
        self.app_info = safe_get_version(binary=dest)
        self.package_name = self.app_info.get("package_name",
                                              "org.mozilla.fennec")
        self.adb = ADBAndroid()
        try:
            self.adb.uninstall_app(self.package_name)
        except ADBError, msg:
            LOG.warning(
                "Failed to uninstall %s (%s)\nThis is normal if it is the"
                " first time the application is installed."
                % (self.package_name, msg)
            )
        self.adb.install_app(dest)
Пример #2
0
class FennecContext(RemoteContext):
    _remote_profiles_ini = None
    _remote_test_root = None

    def __init__(self,
                 app=None,
                 adb_path=None,
                 avd_home=None,
                 device_serial=None):
        self._adb = adb_path
        self.avd_home = avd_home
        self.remote_process = app
        self.device_serial = device_serial
        self.device = ADBAndroid(adb=self.adb, device=device_serial)

    def stop_application(self):
        self.device.stop_application(self.remote_process)

    @property
    def remote_test_root(self):
        if not self._remote_test_root:
            self._remote_test_root = self.device.test_root
        return self._remote_test_root

    @property
    def remote_profiles_ini(self):
        if not self._remote_profiles_ini:
            self._remote_profiles_ini = posixpath.join('/data', 'data',
                                                       self.remote_process,
                                                       'files', 'mozilla',
                                                       'profiles.ini')
        return self._remote_profiles_ini
Пример #3
0
class FennecLauncher(Launcher):
    app_info = None
    adb = None
    package_name = None
    profile_class = FirefoxRegressionProfile
    remote_profile = None

    @classmethod
    def check_is_runnable(cls):
        try:
            devices = ADBHost().devices()
        except ADBError as adb_error:
            raise LauncherNotRunnable(str(adb_error))
        if not devices:
            raise LauncherNotRunnable("No android device connected."
                                      " Connect a device and try again.")

    def _install(self, dest):
        # get info now, as dest may be removed
        self.app_info = safe_get_version(binary=dest)
        self.package_name = self.app_info.get("package_name",
                                              "org.mozilla.fennec")
        self.adb = ADBAndroid()
        try:
            self.adb.uninstall_app(self.package_name)
        except ADBError, msg:
            LOG.warning(
                "Failed to uninstall %s (%s)\nThis is normal if it is the"
                " first time the application is installed." %
                (self.package_name, msg))
        self.adb.install_app(dest)
Пример #4
0
    def __init__(self, app, binary, run_local=False, obj_path=None,
                 gecko_profile=False, gecko_profile_interval=None, gecko_profile_entries=None,
                 symbols_path=None):
        self.config = {}
        self.config['app'] = app
        self.config['binary'] = binary
        self.config['platform'] = mozinfo.os
        self.config['processor'] = mozinfo.processor
        self.config['run_local'] = run_local
        self.config['obj_path'] = obj_path
        self.config['gecko_profile'] = gecko_profile
        self.config['gecko_profile_interval'] = gecko_profile_interval
        self.config['gecko_profile_entries'] = gecko_profile_entries
        self.config['symbols_path'] = symbols_path
        self.raptor_venv = os.path.join(os.getcwd(), 'raptor-venv')
        self.log = get_default_logger(component='raptor-main')
        self.control_server = None
        self.playback = None
        self.benchmark = None
        self.gecko_profiler = None
        self.post_startup_delay = 30000  # raptor webext pause time after browser startup

        # Create the profile; for geckoview we want a firefox profile type
        if self.config['app'] == 'geckoview':
            self.profile = create_profile('firefox')
        else:
            self.profile = create_profile(self.config['app'])

        # Merge in base profiles
        with open(os.path.join(self.profile_data_dir, 'profiles.json'), 'r') as fh:
            base_profiles = json.load(fh)['raptor']

        for name in base_profiles:
            path = os.path.join(self.profile_data_dir, name)
            self.log.info("Merging profile: {}".format(path))
            self.profile.merge(path)

        # create results holder
        self.results_handler = RaptorResultsHandler()

        # when testing desktop browsers we use mozrunner to start the browser; when
        # testing on android (i.e. geckoview) we use mozdevice to control the device app

        if self.config['app'] == "geckoview":
            # create the android device handler; it gets initiated and sets up adb etc
            self.log.info("creating android device handler using mozdevice")
            self.device = ADBAndroid(verbose=True)
            self.device.clear_logcat()
        else:
            # create the desktop browser runner
            self.log.info("creating browser runner using mozrunner")
            self.output_handler = OutputHandler()
            process_args = {
                'processOutputLine': [self.output_handler],
            }
            runner_cls = runners[app]
            self.runner = runner_cls(
                binary, profile=self.profile, process_args=process_args)

        self.log.info("raptor config: %s" % str(self.config))
Пример #5
0
class FennecLauncher(Launcher):
    app_info = None
    adb = None
    package_name = None
    remote_profile = None

    @classmethod
    def check_is_runnable(cls):
        # ADBHost().devices() seems to raise OSError when adb is not
        # installed and in PATH. TODO: maybe fix this in mozdevice.
        try:
            devices = ADBHost().devices()
        except OSError:
            raise LauncherNotRunnable("adb (Android Debug Bridge) is not"
                                      " installed or not in the PATH.")
        if not devices:
            raise LauncherNotRunnable("No android device connected."
                                      " Connect a device and try again.")

    def _install(self, dest):
        # get info now, as dest may be removed
        self.app_info = mozversion.get_version(binary=dest)
        self.package_name = self.app_info.get("package_name",
                                              "org.mozilla.fennec")
        self.adb = ADBAndroid()
        try:
            self.adb.uninstall_app(self.package_name)
        except ADBError, msg:
            LOG.warning(
                "Failed to uninstall %s (%s)\nThis is normal if it is the"
                " first time the application is installed."
                % (self.package_name, msg)
            )
        self.adb.install_app(dest)
Пример #6
0
    def __init__(self, log, options):
        self.log = log
        verbose = False
        if options.log_tbpl_level == 'debug' or options.log_mach_level == 'debug':
            verbose = True
        self.device = ADBAndroid(adb=options.adbPath or 'adb',
                                 device=options.deviceSerial,
                                 test_root=options.remoteTestRoot,
                                 verbose=verbose)
        self.options = options
        self.log.debug("options=%s" % vars(options))
        update_mozinfo()
        self.remote_profile = posixpath.join(self.device.test_root, 'junit-profile')

        if self.options.coverage and not self.options.coverage_output_path:
            raise Exception("--coverage-output-path is required when using --enable-coverage")
        self.remote_coverage_output_path = posixpath.join(self.device.test_root,
                                                          'junit-coverage.ec')
        self.server_init()

        self.cleanup()
        self.device.clear_logcat()
        self.build_profile()
        self.startServers(
            self.options,
            debuggerInfo=None,
            ignoreSSLTunnelExts=True)
        self.log.debug("Servers started")
Пример #7
0
 def _install(self, dest):
     # get info now, as dest may be removed
     self.app_info = mozversion.get_version(binary=dest)
     self.package_name = self.app_info.get("package_name",
                                           "org.mozilla.fennec")
     self.adb = ADBAndroid()
     self.adb.uninstall_app(self.package_name)
     self.adb.install_app(dest)
 def __init__(self, log, options):
     self.log = log
     self.device = ADBAndroid(adb=options.adbPath or 'adb',
                              device=options.deviceSerial,
                              test_root=options.remoteTestRoot)
     self.options = options
     self.appname = self.options.app.split('/')[-1]
     self.logcat = None
     self.build_profile()
     self.log.debug("options=%s" % vars(options))
Пример #9
0
 def __init__(self,
              app=None,
              adb_path=None,
              avd_home=None,
              device_serial=None):
     self._adb = adb_path
     self.avd_home = avd_home
     self.remote_process = app
     self.device_serial = device_serial
     self.device = ADBAndroid(adb=self.adb, device=device_serial)
Пример #10
0
 def _install(self, dest):
     if self._get_device_status():
         self.adb = ADBAndroid()
         if "y" != raw_input("WARNING: bisecting nightly fennec builds will"
                             " clobber your existing nightly profile."
                             " Continue? (y or n)"):
             raise Exception("Aborting!")
     self.adb.uninstall_app("org.mozilla.fennec")
     self.adb.install_app(dest)
     # get info now, as dest may be removed
     self.app_info = mozversion.get_version(binary=dest)
Пример #11
0
 def __init__(self, options, progs):
     cppunittests.CPPUnitTests.__init__(self)
     self.options = options
     self.device = ADBAndroid(adb=options.adb_path or 'adb',
                              device=options.device_serial,
                              test_root=options.remote_test_root)
     self.remote_test_root = posixpath.join(self.device.test_root, "cppunittests")
     self.remote_bin_dir = posixpath.join(self.remote_test_root, "b")
     self.remote_tmp_dir = posixpath.join(self.remote_test_root, "tmp")
     self.remote_home_dir = posixpath.join(self.remote_test_root, "h")
     if options.setup:
         self.setup_bin(progs)
Пример #12
0
    def __init__(self, options, message_logger):
        """
           Simple one-time initialization.
        """
        MochitestDesktop.__init__(self, options.flavor, vars(options))

        verbose = False
        if options.log_tbpl_level == 'debug' or options.log_mach_level == 'debug':
            verbose = True
        self.device = ADBAndroid(adb=options.adbPath or 'adb',
                                 device=options.deviceSerial,
                                 test_root=options.remoteTestRoot,
                                 verbose=verbose)

        # Check that Firefox is installed
        expected = options.app.split('/')[-1]
        if not self.device.is_app_installed(expected):
            raise Exception("%s is not installed on this device" % expected)

        options.logFile = "robocop.log"
        if options.remoteTestRoot is None:
            options.remoteTestRoot = self.device.test_root
        self.remoteProfile = posixpath.join(options.remoteTestRoot, "profile")
        self.remoteProfileCopy = posixpath.join(options.remoteTestRoot,
                                                "profile-copy")

        self.remoteModulesDir = posixpath.join(options.remoteTestRoot,
                                               "modules/")
        self.remoteConfigFile = posixpath.join(options.remoteTestRoot,
                                               "robotium.config")
        self.remoteLogFile = posixpath.join(options.remoteTestRoot, "logs",
                                            "robocop.log")

        self.options = options

        process_args = {'messageLogger': message_logger}
        self.auto = RemoteAutomation(self.device,
                                     options.remoteappname,
                                     self.remoteProfile,
                                     self.remoteLogFile,
                                     processArgs=process_args)
        self.environment = self.auto.environment

        self.remoteScreenshots = "/mnt/sdcard/Robotium-Screenshots"
        self.remoteMozLog = posixpath.join(options.remoteTestRoot, "mozlog")

        self.localLog = options.logFile
        self.localProfile = None
        self.certdbNew = True
        self.passed = 0
        self.failed = 0
        self.todo = 0
Пример #13
0
 def _install(self, dest):
     # get info now, as dest may be removed
     self.app_info = safe_get_version(binary=dest)
     self.package_name = self.app_info.get("package_name",
                                           "org.mozilla.fennec")
     self.adb = ADBAndroid()
     try:
         self.adb.uninstall_app(self.package_name)
     except ADBError, msg:
         LOG.warning(
             "Failed to uninstall %s (%s)\nThis is normal if it is the"
             " first time the application is installed." %
             (self.package_name, msg))
Пример #14
0
class FennecLauncher(Launcher):
    app_info = None

    def _get_device_status(self):
        self.adbhost = ADBHost()
        if self.adbhost.devices():
            return True
        if "y" == raw_input("WARNING: no device connected."
                            " Connect a device and try again.\n"
                            "Try again? (y or n): "):
            return self.get_device_status()
        raise Exception("Aborting!")

    def _install(self, dest):
        if self._get_device_status():
            self.adb = ADBAndroid()
            if "y" != raw_input("WARNING: bisecting nightly fennec builds will"
                                " clobber your existing nightly profile."
                                " Continue? (y or n)"):
                raise Exception("Aborting!")
        self.adb.uninstall_app("org.mozilla.fennec")
        self.adb.install_app(dest)
        # get info now, as dest may be removed
        self.app_info = mozversion.get_version(binary=dest)

    def _start(self, **args):
        self.adb.launch_fennec("org.mozilla.fennec")

    def _stop(self):
        self.adb.stop_application("org.mozilla.fennec")

    def _get_app_info(self):
        return self.app_info
Пример #15
0
 def _install(self, dest):
     # get info now, as dest may be removed
     self.app_info = safe_get_version(binary=dest)
     self.package_name = self.app_info.get("package_name",
                                           self._get_package_name())
     self.adb = ADBAndroid(require_root=False)
     try:
         self.adb.uninstall_app(self.package_name)
     except ADBError as msg:
         LOG.warning(
             "Failed to uninstall %s (%s)\nThis is normal if it is the"
             " first time the application is installed." %
             (self.package_name, msg))
     self.adb.install_app(dest)
Пример #16
0
class FennecLauncher(Launcher):
    app_info = None

    def _get_device_status(self):
        self.adbhost = ADBHost()
        if self.adbhost.devices():
            return True
        if "y" == raw_input("WARNING: no device connected."
                            " Connect a device and try again.\n"
                            "Try again? (y or n): "):
            return self.get_device_status()
        raise Exception("Aborting!")

    def _install(self, dest):
        if self._get_device_status():
            self.adb = ADBAndroid()
            if "y" != raw_input("WARNING: bisecting nightly fennec builds will"
                                " clobber your existing nightly profile."
                                " Continue? (y or n)"):
                raise Exception("Aborting!")
        self.adb.uninstall_app("org.mozilla.fennec")
        self.adb.install_app(dest)
        # get info now, as dest may be removed
        self.app_info = mozversion.get_version(binary=dest)

    def _start(self, **args):
        self.adb.launch_fennec("org.mozilla.fennec")

    def _stop(self):
        self.adb.stop_application("org.mozilla.fennec")

    def _get_app_info(self):
        return self.app_info
Пример #17
0
class FennecLauncher(Launcher):
    app_info = None
    adb = None

    @classmethod
    def check_is_runnable(cls):
        # ADBHost().devices() seems to raise OSError when adb is not
        # installed and in PATH. TODO: maybe fix this in mozdevice.
        try:
            devices = ADBHost().devices()
        except OSError:
            raise LauncherNotRunnable("adb (Android Debug Bridge) is not"
                                      " installed or not in the PATH.")
        if not devices:
            raise LauncherNotRunnable("No android device connected."
                                      " Connect a device and try again.")
        if not raw_input("WARNING: bisecting fennec builds will clobber your"
                         " existing profile. Type 'y' to continue:") == 'y':
            raise LauncherNotRunnable('Aborted.')

    def _install(self, dest):
        self.adb = ADBAndroid()
        self.adb.uninstall_app("org.mozilla.fennec")
        self.adb.install_app(dest)
        # get info now, as dest may be removed
        self.app_info = mozversion.get_version(binary=dest)

    def _start(self, **kwargs):
        self.adb.launch_fennec("org.mozilla.fennec")

    def _stop(self):
        self.adb.stop_application("org.mozilla.fennec")

    def get_app_info(self):
        return self.app_info
Пример #18
0
    def run_raptor_test(self, **kwargs):

        build_obj = MozbuildObject.from_environment(cwd=HERE)

        firefox_android_browsers = ["fennec", "geckoview", "refbrow", "fenix"]

        if conditions.is_android(
                build_obj) or kwargs['app'] in firefox_android_browsers:
            from mozrunner.devices.android_device import verify_android_device
            from mozdevice import ADBAndroid, ADBHost
            if not verify_android_device(
                    build_obj, install=True, app=kwargs['binary'],
                    xre=True):  # Equivalent to 'run_local' = True.
                return 1

        debug_command = '--debug-command'
        if debug_command in sys.argv:
            sys.argv.remove(debug_command)

        raptor = self._spawn(RaptorRunner)

        try:
            if kwargs['app'] in firefox_android_browsers and kwargs[
                    'power_test']:
                device = ADBAndroid(verbose=True)
                adbhost = ADBHost(verbose=True)
                device_serial = "%s:5555" % device.get_ip_address()
                device.command_output(["tcpip", "5555"])
                raw_input(
                    "Please disconnect your device from USB then press Enter/return..."
                )
                adbhost.command_output(["connect", device_serial])
                while len(adbhost.devices()) > 1:
                    raw_input(
                        "You must disconnect your device from USB before continuing."
                    )
                # must reset the environment DEVICE_SERIAL which was set during
                # verify_android_device to match our new tcpip value.
                os.environ["DEVICE_SERIAL"] = device_serial
            return raptor.run_test(sys.argv[2:], kwargs)
        except Exception as e:
            print(repr(e))
            return 1
        finally:
            try:
                if kwargs['app'] in firefox_android_browsers and kwargs[
                        'power_test']:
                    raw_input(
                        "Connect device via USB and press Enter/return...")
                    device = ADBAndroid(device=device_serial, verbose=True)
                    device.command_output(["usb"])
                    adbhost.command_output(["disconnect", device_serial])
            except Exception:
                adbhost.command_output(["kill-server"])
Пример #19
0
    def run_raptor(self, **kwargs):
        build_obj = self

        is_android = Conditions.is_android(build_obj) or \
            kwargs['app'] in FIREFOX_ANDROID_BROWSERS

        if is_android:
            from mozrunner.devices.android_device import (
                verify_android_device, InstallIntent)
            from mozdevice import ADBAndroid, ADBHost
            install = InstallIntent.NO if kwargs.pop(
                'noinstall', False) else InstallIntent.PROMPT
            if not verify_android_device(
                    build_obj, install=install, app=kwargs['binary'],
                    xre=True):  # Equivalent to 'run_local' = True.
                return 1

        debug_command = '--debug-command'
        if debug_command in sys.argv:
            sys.argv.remove(debug_command)

        raptor = self._spawn(RaptorRunner)

        try:
            if is_android and kwargs['power_test']:
                device = ADBAndroid(verbose=True)
                adbhost = ADBHost(verbose=True)
                device_serial = "{}:5555".format(device.get_ip_address())
                device.command_output(["tcpip", "5555"])
                six.input(
                    "Please disconnect your device from USB then press Enter/return..."
                )
                adbhost.command_output(["connect", device_serial])
                while len(adbhost.devices()) > 1:
                    six.input(
                        "You must disconnect your device from USB before continuing."
                    )
                # must reset the environment DEVICE_SERIAL which was set during
                # verify_android_device to match our new tcpip value.
                os.environ["DEVICE_SERIAL"] = device_serial
            return raptor.run_test(sys.argv[2:], kwargs)
        except Exception as e:
            print(repr(e))
            return 1
        finally:
            try:
                if is_android and kwargs['power_test']:
                    six.input(
                        "Connect device via USB and press Enter/return...")
                    device = ADBAndroid(device=device_serial, verbose=True)
                    device.command_output(["usb"])
                    adbhost.command_output(["disconnect", device_serial])
            except Exception:
                adbhost.command_output(["kill-server"])
Пример #20
0
    def setup_app(self):
        # create the android device handler; it gets initiated and sets up adb etc
        self.log.info("creating android device handler using mozdevice")
        self.device = ADBAndroid(verbose=True, logger_name="recorder-adb - ")

        self.device_raptor_dir = "/sdcard/raptor"
        self.config['device_raptor_dir'] = self.device_raptor_dir
        if self.device.is_dir(self.device_raptor_dir):
            self.log.info("deleting existing device raptor dir: %s" %
                          self.device_raptor_dir)
            self.device.rm(self.device_raptor_dir, recursive=True)
            self.log.info("creating raptor folder on sdcard: %s" %
                          self.device_raptor_dir)
        self.device.mkdir(self.device_raptor_dir)
        self.device.chmod(self.device_raptor_dir, recursive=True)
Пример #21
0
    def run_raptor(self, **kwargs):
        build_obj = self

        is_android = Conditions.is_android(build_obj) or \
            kwargs['app'] in FIREFOX_ANDROID_BROWSERS

        if is_android:
            from mozrunner.devices.android_device import (
                verify_android_device, InstallIntent)
            from mozdevice import ADBAndroid
            install = InstallIntent.NO if kwargs.pop(
                'noinstall', False) else InstallIntent.PROMPT
            if not verify_android_device(
                    build_obj, install=install, app=kwargs['binary'],
                    xre=True):  # Equivalent to 'run_local' = True.
                return 1

        debug_command = '--debug-command'
        if debug_command in sys.argv:
            sys.argv.remove(debug_command)

        raptor = self._spawn(RaptorRunner)
        device = None

        try:
            if kwargs['power_test'] and is_android:
                device = ADBAndroid(verbose=True)
                disable_charging(device)
            return raptor.run_test(sys.argv[2:], kwargs)
        except Exception as e:
            print(repr(e))
            return 1
        finally:
            if kwargs['power_test'] and device:
                enable_charging(device)
Пример #22
0
 def setup_device(self):
     self.device = ADBAndroid()
     if self.binary and self.proxy.mode is "record":
         if not self.skip_install:
             if self.device.is_app_installed(self.APP_NAME):
                 print("Uninstalling app %s" % self.APP_NAME)
                 self.device.uninstall_app(self.APP_NAME)
             print("Installing app %s" % self.APP_NAME)
             self.device.install_app(apk_path=self.binary)
             self.skip_install = True
         else:
             print("App already installed in a previous recording!!!!")
     else:
         print(
             "No binary provided or proxy in replay mode! Using existing app on the device."
         )
Пример #23
0
class Robocop(object):
    device = ADBAndroid()
    logger = logging.getLogger()

    def __init__(self, app, log):
        self.app = app
        self.log = log

    def run(self, identifier):
        # build browser environment
        # setup robotium config
        # setup remote profile
        # build browser args
        cmd = [
            "am",
            "instrument",
            "-e quit_and_finish 1",
            "-e deviceroot {}".format(self.device.test_root),
            "-e class org.mozilla.gecko.tests.{}".format(identifier),
            "org.mozilla.roboexample.test/org.mozilla.gecko.FennecInstrumentationTestRunner",
        ]
        self.device.clear_logcat()
        self.logger.info("Running: {}".format(" ".join(cmd)))
        self.device.shell(" ".join(cmd))

        # wait for process to end
        top = self.app
        while top == self.app:
            time.sleep(0.5)
            top = self.device.get_top_activity(timeout=60)

        log = "\n".join(self.device.get_logcat())
        with open(self.log, "w") as f:
            f.writelines(log)
        assert "Failed: 0" in log
Пример #24
0
 def _install(self, dest):
     # get info now, as dest may be removed
     self.app_info = mozversion.get_version(binary=dest)
     self.package_name = self.app_info.get("package_name",
                                           "org.mozilla.fennec")
     self.adb = ADBAndroid()
     self.adb.uninstall_app(self.package_name)
     self.adb.install_app(dest)
Пример #25
0
 def __init__(self, inbound_branch=None, bits=mozinfo.bits, persist=None):
     self.inbound_branch = inbound_branch
     self.persist = persist
     if self.get_device_status():
         self.adb = ADBAndroid()
         if "y" != raw_input("WARNING: bisecting nightly fennec builds will"
                             " clobber your existing nightly profile."
                             " Continue? (y or n)"):
             raise Exception("Aborting!")
Пример #26
0
 def _install(self, dest):
     if self._get_device_status():
         self.adb = ADBAndroid()
         if "y" != raw_input("WARNING: bisecting nightly fennec builds will"
                             " clobber your existing nightly profile."
                             " Continue? (y or n)"):
             raise Exception("Aborting!")
     self.adb.uninstall_app("org.mozilla.fennec")
     self.adb.install_app(dest)
     # get info now, as dest may be removed
     self.app_info = mozversion.get_version(binary=dest)
def _get_device(substs, device_serial=None):
    global devices
    if device_serial in devices:
        device = devices[device_serial]
    else:
        adb_path = _find_sdk_exe(substs, 'adb', False)
        if not adb_path:
            adb_path = 'adb'
        device = ADBAndroid(adb=adb_path, verbose=verbose_logging, device=device_serial)
        devices[device_serial] = device
    return device
Пример #28
0
 def get_device(self, adb_path, device_serial):
     # Create a mozdevice.ADBAndroid object for the specified device_serial
     # and cache it for future use. If the same device_serial is subsequently
     # requested, retrieve it from the cache to avoid costly re-initialization.
     global devices
     if device_serial in devices:
         device = devices[device_serial]
     else:
         device = ADBAndroid(adb=adb_path, device=device_serial)
         devices[device_serial] = device
     return device
    def run_raptor(self, **kwargs):
        # Defers this import so that a transitive dependency doesn't
        # stop |mach bootstrap| from running
        from raptor.power import enable_charging, disable_charging

        build_obj = self

        is_android = Conditions.is_android(build_obj) or \
            kwargs['app'] in ANDROID_BROWSERS

        if is_android:
            from mozrunner.devices.android_device import (
                verify_android_device, InstallIntent)
            from mozdevice import ADBAndroid
            install = InstallIntent.NO if kwargs.pop(
                'noinstall', False) else InstallIntent.YES
            verbose = False
            if kwargs.get('log_mach_verbose') or kwargs.get('log_tbpl_level') == 'debug' or \
               kwargs.get('log_mach_level') == 'debug' or kwargs.get('log_raw_level') == 'debug':
                verbose = True
            if not verify_android_device(
                    build_obj,
                    install=install,
                    app=kwargs['binary'],
                    verbose=verbose,
                    xre=True):  # Equivalent to 'run_local' = True.
                return 1

        debug_command = '--debug-command'
        if debug_command in sys.argv:
            sys.argv.remove(debug_command)

        raptor = self._spawn(RaptorRunner)
        device = None

        try:
            if kwargs['power_test'] and is_android:
                device = ADBAndroid(verbose=True)
                disable_charging(device)
            return raptor.run_test(sys.argv[2:], kwargs)
        except BinaryNotFoundException as e:
            self.log(logging.ERROR, 'raptor', {'error': str(e)},
                     'ERROR: {error}')
            self.log(logging.INFO, 'raptor', {'help': e.help()}, '{help}')
            return 1
        except Exception as e:
            print(repr(e))
            return 1
        finally:
            if kwargs['power_test'] and device:
                enable_charging(device)
Пример #30
0
class FennecNightly(Nightly):
    app_name = 'fennec'
    name = 'fennec'
    profile_class = FirefoxProfile
    build_regex = r'fennec-.*\.apk'
    build_info_regex = r'fennec-.*\.txt'
    binary = 'org.mozilla.fennec/.App'
    bits = None
    build_base_repo_name = "mobile"

    def get_device_status(self):
        self.adbhost = ADBHost()
        if self.adbhost.devices():
            return True
        if "y" == raw_input("WARNING: no device connected."
                            " Connect a device and try again.\n"
                            "Try again? (y or n): "):
            return self.get_device_status()
        raise Exception("Aborting!")

    def __init__(self, inbound_branch=None, bits=mozinfo.bits, persist=None):
        self.inbound_branch = inbound_branch
        self.persist = persist
        if self.get_device_status():
            self.adb = ADBAndroid()
            if "y" != raw_input("WARNING: bisecting nightly fennec builds will"
                                " clobber your existing nightly profile."
                                " Continue? (y or n)"):
                raise Exception("Aborting!")

    def get_inbound_branch(self, date):
        return "mozilla-central-android"

    def install(self):
        self.adb.uninstall_app("org.mozilla.fennec")
        self.adb.install_app(self.dest)
        return True

    def start(self, profile, addons, cmdargs):
        self.adb.launch_fennec("org.mozilla.fennec")
        return True

    def stop(self):
        self.adb.stop_application("org.mozilla.fennec")
        return True

    def get_app_info(self):
        return mozversion.get_version(binary=self.dest)
Пример #31
0
 def _install(self, dest):
     # get info now, as dest may be removed
     self.app_info = mozversion.get_version(binary=dest)
     self.package_name = self.app_info.get("package_name",
                                           "org.mozilla.fennec")
     self.adb = ADBAndroid()
     try:
         self.adb.uninstall_app(self.package_name)
     except ADBError, msg:
         LOG.warning(
             "Failed to uninstall %s (%s)\nThis is normal if it is the"
             " first time the application is installed."
             % (self.package_name, msg)
         )
Пример #32
0
 def _install(self, dest):
     # get info now, as dest may be removed
     self.app_info = safe_get_version(binary=dest)
     self.package_name = self.app_info.get("package_name",
                                           self._get_package_name())
     self.adb = ADBAndroid(require_root=False)
     try:
         self.adb.uninstall_app(self.package_name)
     except ADBError, msg:
         LOG.warning(
             "Failed to uninstall %s (%s)\nThis is normal if it is the"
             " first time the application is installed."
             % (self.package_name, msg)
         )
    def __init__(self, log, options):
        self.log = log
        verbose = False
        if options.log_tbpl_level == 'debug' or options.log_mach_level == 'debug':
            verbose = True
        self.device = ADBAndroid(adb=options.adbPath or 'adb',
                                 device=options.deviceSerial,
                                 test_root=options.remoteTestRoot,
                                 verbose=verbose)
        self.options = options
        self.log.debug("options=%s" % vars(options))
        update_mozinfo()
        self.remote_profile = posixpath.join(self.device.test_root, 'junit-profile')
        self.server_init()

        self.cleanup()
        self.device.clear_logcat()
        self.build_profile()
        self.startServers(
            self.options,
            debuggerInfo=None,
            ignoreSSLTunnelExts=True)
        self.log.debug("Servers started")
Пример #34
0
 def verify_device(self, adb_path, device):
     """
        Check that the specified device is available and rooted.
     """
     try:
         device = ADBAndroid(adb=adb_path, device=device, timeout=10)
         if device._have_su or device._have_android_su or device._have_root_shell:
             return True
     except Exception:
         self.build_obj.log(
             logging.WARN, "autophone", {},
             "Unable to verify root on device.")
         if self.verbose:
             self.build_obj.log(logging.ERROR, "autophone", {},
                                str(sys.exc_info()[0]))
     return False
Пример #35
0
    def run_raptor(self, **kwargs):
        build_obj = self

        is_android = Conditions.is_android(build_obj) or \
            kwargs['app'] in ANDROID_BROWSERS

        if is_android:
            from mozrunner.devices.android_device import (
                verify_android_device, InstallIntent)
            from mozdevice import ADBAndroid
            install = InstallIntent.NO if kwargs.pop(
                'noinstall', False) else InstallIntent.YES
            if not verify_android_device(
                    build_obj, install=install, app=kwargs['binary'],
                    xre=True):  # Equivalent to 'run_local' = True.
                return 1

        debug_command = '--debug-command'
        if debug_command in sys.argv:
            sys.argv.remove(debug_command)

        raptor = self._spawn(RaptorRunner)
        device = None

        try:
            if kwargs['power_test'] and is_android:
                device = ADBAndroid(verbose=True)
                disable_charging(device)
            return raptor.run_test(sys.argv[2:], kwargs)
        except BinaryNotFoundException as e:
            self.log(logging.ERROR, 'raptor', {'error': str(e)},
                     'ERROR: {error}')
            self.log(logging.INFO, 'raptor', {'help': e.help()}, '{help}')
            return 1
        except Exception as e:
            print(repr(e))
            return 1
        finally:
            if kwargs['power_test'] and device:
                enable_charging(device)
Пример #36
0
class RemoteReftest(RefTest):
    use_marionette = False
    resolver_cls = RemoteReftestResolver

    def __init__(self, options, scriptDir):
        RefTest.__init__(self, options.suite)
        self.run_by_manifest = False
        self.scriptDir = scriptDir
        self.localLogName = options.localLogName

        verbose = False
        if options.log_tbpl_level == 'debug' or options.log_mach_level == 'debug':
            verbose = True
            print "set verbose!"
        self.device = ADBAndroid(adb=options.adb_path,
                                 device=options.deviceSerial,
                                 test_root=options.remoteTestRoot,
                                 verbose=verbose)

        if options.remoteTestRoot is None:
            options.remoteTestRoot = posixpath.join(self.device.test_root,
                                                    "reftest")
        options.remoteProfile = posixpath.join(options.remoteTestRoot,
                                               "profile")
        options.remoteLogFile = posixpath.join(options.remoteTestRoot,
                                               "reftest.log")
        options.logFile = options.remoteLogFile
        self.remoteProfile = options.remoteProfile
        self.remoteTestRoot = options.remoteTestRoot

        if not options.ignoreWindowSize:
            parts = self.device.get_info('screen')['screen'][0].split()
            width = int(parts[0].split(':')[1])
            height = int(parts[1].split(':')[1])
            if (width < 1366 or height < 1050):
                self.error("ERROR: Invalid screen resolution %sx%s, "
                           "please adjust to 1366x1050 or higher" %
                           (width, height))

        self._populate_logger(options)
        self.outputHandler = OutputHandler(self.log, options.utilityPath,
                                           options.symbolsPath)
        # RemoteAutomation.py's 'messageLogger' is also used by mochitest. Mimic a mochitest
        # MessageLogger object to re-use this code path.
        self.outputHandler.write = self.outputHandler.__call__
        self.automation = RemoteAutomation(self.device,
                                           options.app,
                                           self.remoteProfile,
                                           options.remoteLogFile,
                                           processArgs=None)
        self.automation._processArgs['messageLogger'] = self.outputHandler

        self.environment = self.automation.environment
        if self.automation.IS_DEBUG_BUILD:
            self.SERVER_STARTUP_TIMEOUT = 180
        else:
            self.SERVER_STARTUP_TIMEOUT = 90

        self.remoteCache = os.path.join(options.remoteTestRoot, "cache/")

        # Check that Firefox is installed
        expected = options.app.split('/')[-1]
        if not self.device.is_app_installed(expected):
            raise Exception("%s is not installed on this device" % expected)

        self.automation.deleteANRs()
        self.automation.deleteTombstones()
        self.device.clear_logcat()

        self.device.rm(self.remoteCache, force=True, recursive=True)

        procName = options.app.split('/')[-1]
        self.device.pkill(procName)
        if self.device.process_exist(procName):
            self.log.error("unable to kill %s before starting tests!" %
                           procName)

    def findPath(self, paths, filename=None):
        for path in paths:
            p = path
            if filename:
                p = os.path.join(p, filename)
            if os.path.exists(self.getFullPath(p)):
                return path
        return None

    def startWebServer(self, options):
        """ Create the webserver on the host and start it up """
        remoteXrePath = options.xrePath
        remoteUtilityPath = options.utilityPath
        localAutomation = Automation()
        localAutomation.IS_WIN32 = False
        localAutomation.IS_LINUX = False
        localAutomation.IS_MAC = False
        localAutomation.UNIXISH = False
        hostos = sys.platform
        if (hostos == 'mac' or hostos == 'darwin'):
            localAutomation.IS_MAC = True
        elif (hostos == 'linux' or hostos == 'linux2'):
            localAutomation.IS_LINUX = True
            localAutomation.UNIXISH = True
        elif (hostos == 'win32' or hostos == 'win64'):
            localAutomation.BIN_SUFFIX = ".exe"
            localAutomation.IS_WIN32 = True

        paths = [options.xrePath, localAutomation.DIST_BIN]
        options.xrePath = self.findPath(paths)
        if options.xrePath is None:
            print(
                "ERROR: unable to find xulrunner path for %s, "
                "please specify with --xre-path" % (os.name))
            return 1
        paths.append("bin")
        paths.append(os.path.join("..", "bin"))

        xpcshell = "xpcshell"
        if (os.name == "nt"):
            xpcshell += ".exe"

        if (options.utilityPath):
            paths.insert(0, options.utilityPath)
        options.utilityPath = self.findPath(paths, xpcshell)
        if options.utilityPath is None:
            print(
                "ERROR: unable to find utility path for %s, "
                "please specify with --utility-path" % (os.name))
            return 1

        options.serverProfilePath = tempfile.mkdtemp()
        self.server = ReftestServer(localAutomation, options, self.scriptDir)
        retVal = self.server.start()
        if retVal:
            return retVal
        retVal = self.server.ensureReady(self.SERVER_STARTUP_TIMEOUT)
        if retVal:
            return retVal

        options.xrePath = remoteXrePath
        options.utilityPath = remoteUtilityPath
        return 0

    def stopWebServer(self, options):
        self.server.stop()

    def killNamedProc(self, pname, orphans=True):
        """ Kill processes matching the given command name """
        self.log.info("Checking for %s processes..." % pname)

        for proc in psutil.process_iter():
            try:
                if proc.name() == pname:
                    procd = proc.as_dict(
                        attrs=['pid', 'ppid', 'name', 'username'])
                    if proc.ppid() == 1 or not orphans:
                        self.log.info("killing %s" % procd)
                        try:
                            os.kill(proc.pid,
                                    getattr(signal, "SIGKILL", signal.SIGTERM))
                        except Exception as e:
                            self.log.info("Failed to kill process %d: %s" %
                                          (proc.pid, str(e)))
                    else:
                        self.log.info("NOT killing %s (not an orphan?)" %
                                      procd)
            except Exception:
                # may not be able to access process info for all processes
                continue

    def createReftestProfile(self, options, **kwargs):
        profile = RefTest.createReftestProfile(self,
                                               options,
                                               server=options.remoteWebServer,
                                               port=options.httpPort,
                                               **kwargs)
        profileDir = profile.profile
        prefs = {}
        prefs["app.update.url.android"] = ""
        prefs["browser.firstrun.show.localepicker"] = False
        prefs["reftest.remote"] = True
        prefs[
            "datareporting.policy.dataSubmissionPolicyBypassAcceptance"] = True
        # move necko cache to a location that can be cleaned up
        prefs["browser.cache.disk.parent_directory"] = self.remoteCache

        prefs["layout.css.devPixelsPerPx"] = "1.0"
        # Because Fennec is a little wacky (see bug 1156817) we need to load the
        # reftest pages at 1.0 zoom, rather than zooming to fit the CSS viewport.
        prefs["apz.allow_zooming"] = False

        # Set the extra prefs.
        profile.set_preferences(prefs)

        try:
            self.device.push(profileDir, options.remoteProfile)
            self.device.chmod(options.remoteProfile, recursive=True)
        except Exception:
            print "Automation Error: Failed to copy profiledir to device"
            raise

        return profile

    def copyExtraFilesToProfile(self, options, profile):
        profileDir = profile.profile
        RefTest.copyExtraFilesToProfile(self, options, profile)
        if len(os.listdir(profileDir)) > 0:
            try:
                self.device.push(profileDir, options.remoteProfile)
                self.device.chmod(options.remoteProfile, recursive=True)
            except Exception:
                print "Automation Error: Failed to copy extra files to device"
                raise

    def printDeviceInfo(self, printLogcat=False):
        try:
            if printLogcat:
                logcat = self.device.get_logcat(
                    filter_out_regexps=fennecLogcatFilters)
                print ''.join(logcat)
            print "Device info:"
            devinfo = self.device.get_info()
            for category in devinfo:
                if type(devinfo[category]) is list:
                    print "  %s:" % category
                    for item in devinfo[category]:
                        print "     %s" % item
                else:
                    print "  %s: %s" % (category, devinfo[category])
            print "Test root: %s" % self.device.test_root
        except Exception as e:
            print "WARNING: Error getting device information: %s" % str(e)

    def environment(self, **kwargs):
        return self.automation.environment(**kwargs)

    def buildBrowserEnv(self, options, profileDir):
        browserEnv = RefTest.buildBrowserEnv(self, options, profileDir)
        # remove desktop environment not used on device
        if "XPCOM_MEM_BLOAT_LOG" in browserEnv:
            del browserEnv["XPCOM_MEM_BLOAT_LOG"]
        return browserEnv

    def runApp(self,
               options,
               cmdargs=None,
               timeout=None,
               debuggerInfo=None,
               symbolsPath=None,
               valgrindPath=None,
               valgrindArgs=None,
               valgrindSuppFiles=None,
               **profileArgs):
        if cmdargs is None:
            cmdargs = []

        if self.use_marionette:
            cmdargs.append('-marionette')

        binary = options.app
        profile = self.createReftestProfile(options, **profileArgs)

        # browser environment
        env = self.buildBrowserEnv(options, profile.profile)

        self.log.info("Running with e10s: {}".format(options.e10s))
        status, self.lastTestSeen = self.automation.runApp(
            None,
            env,
            binary,
            profile.profile,
            cmdargs,
            utilityPath=options.utilityPath,
            xrePath=options.xrePath,
            debuggerInfo=debuggerInfo,
            symbolsPath=symbolsPath,
            timeout=timeout)

        self.cleanup(profile.profile)
        return status

    def cleanup(self, profileDir):
        self.device.rm(self.remoteTestRoot, force=True, recursive=True)
        self.device.rm(self.remoteProfile, force=True, recursive=True)
        self.device.rm(self.remoteCache, force=True, recursive=True)
        RefTest.cleanup(self, profileDir)
Пример #37
0
class AndroidLauncher(Launcher):
    app_info = None
    adb = None
    package_name = None
    profile_class = FirefoxRegressionProfile
    remote_profile = None

    @abstractmethod
    def _get_package_name(self):
        raise NotImplementedError

    @abstractmethod
    def _launch(self):
        raise NotImplementedError

    @classmethod
    def check_is_runnable(cls):
        try:
            devices = ADBHost().devices()
        except ADBError as adb_error:
            raise LauncherNotRunnable(str(adb_error))
        if not devices:
            raise LauncherNotRunnable("No android device connected."
                                      " Connect a device and try again.")

    def _install(self, dest):
        # get info now, as dest may be removed
        self.app_info = safe_get_version(binary=dest)
        self.package_name = self.app_info.get("package_name",
                                              self._get_package_name())
        self.adb = ADBAndroid(require_root=False)
        try:
            self.adb.uninstall_app(self.package_name)
        except ADBError as msg:
            LOG.warning(
                "Failed to uninstall %s (%s)\nThis is normal if it is the"
                " first time the application is installed." %
                (self.package_name, msg))
        self.adb.install_app(dest)

    def _start(self,
               profile=None,
               addons=(),
               cmdargs=(),
               preferences=None,
               adb_profile_dir=None):
        # for now we don't handle addons on the profile for fennec
        profile = self._create_profile(profile=profile,
                                       preferences=preferences)
        # send the profile on the device
        if not adb_profile_dir:
            adb_profile_dir = self.adb.test_root
        self.remote_profile = "/".join(
            [adb_profile_dir,
             os.path.basename(profile.profile)])
        if self.adb.exists(self.remote_profile):
            self.adb.rm(self.remote_profile, recursive=True)
        LOG.debug("Pushing profile to device (%s -> %s)" %
                  (profile.profile, self.remote_profile))
        self.adb.push(profile.profile, self.remote_profile)
        self._launch()

    def _wait(self):
        while self.adb.process_exist(self.package_name):
            time.sleep(0.1)

    def _stop(self):
        self.adb.stop_application(self.package_name)
        if self.adb.exists(self.remote_profile):
            self.adb.rm(self.remote_profile, recursive=True)

    def get_app_info(self):
        return self.app_info
Пример #38
0
    def __init__(self, options, scriptDir):
        RefTest.__init__(self, options.suite)
        self.run_by_manifest = False
        self.scriptDir = scriptDir
        self.localLogName = options.localLogName

        verbose = False
        if options.log_tbpl_level == 'debug' or options.log_mach_level == 'debug':
            verbose = True
            print "set verbose!"
        self.device = ADBAndroid(adb=options.adb_path,
                                 device=options.deviceSerial,
                                 test_root=options.remoteTestRoot,
                                 verbose=verbose)

        if options.remoteTestRoot is None:
            options.remoteTestRoot = posixpath.join(self.device.test_root,
                                                    "reftest")
        options.remoteProfile = posixpath.join(options.remoteTestRoot,
                                               "profile")
        options.remoteLogFile = posixpath.join(options.remoteTestRoot,
                                               "reftest.log")
        options.logFile = options.remoteLogFile
        self.remoteProfile = options.remoteProfile
        self.remoteTestRoot = options.remoteTestRoot

        if not options.ignoreWindowSize:
            parts = self.device.get_info('screen')['screen'][0].split()
            width = int(parts[0].split(':')[1])
            height = int(parts[1].split(':')[1])
            if (width < 1366 or height < 1050):
                self.error("ERROR: Invalid screen resolution %sx%s, "
                           "please adjust to 1366x1050 or higher" %
                           (width, height))

        self._populate_logger(options)
        self.outputHandler = OutputHandler(self.log, options.utilityPath,
                                           options.symbolsPath)
        # RemoteAutomation.py's 'messageLogger' is also used by mochitest. Mimic a mochitest
        # MessageLogger object to re-use this code path.
        self.outputHandler.write = self.outputHandler.__call__
        self.automation = RemoteAutomation(self.device,
                                           options.app,
                                           self.remoteProfile,
                                           options.remoteLogFile,
                                           processArgs=None)
        self.automation._processArgs['messageLogger'] = self.outputHandler

        self.environment = self.automation.environment
        if self.automation.IS_DEBUG_BUILD:
            self.SERVER_STARTUP_TIMEOUT = 180
        else:
            self.SERVER_STARTUP_TIMEOUT = 90

        self.remoteCache = os.path.join(options.remoteTestRoot, "cache/")

        # Check that Firefox is installed
        expected = options.app.split('/')[-1]
        if not self.device.is_app_installed(expected):
            raise Exception("%s is not installed on this device" % expected)

        self.automation.deleteANRs()
        self.automation.deleteTombstones()
        self.device.clear_logcat()

        self.device.rm(self.remoteCache, force=True, recursive=True)

        procName = options.app.split('/')[-1]
        self.device.pkill(procName)
        if self.device.process_exist(procName):
            self.log.error("unable to kill %s before starting tests!" %
                           procName)
Пример #39
0
class Raptor(object):
    """Container class for Raptor"""
    def __init__(self, app, binary, run_local=False, obj_path=None):
        self.config = {}
        self.config['app'] = app
        self.config['binary'] = binary
        self.config['platform'] = mozinfo.os
        self.config['processor'] = mozinfo.processor
        self.config['run_local'] = run_local
        self.config['obj_path'] = obj_path
        self.raptor_venv = os.path.join(os.getcwd(), 'raptor-venv')
        self.log = get_default_logger(component='raptor-main')
        self.control_server = None
        self.playback = None
        self.benchmark = None

        # Create the profile; for geckoview we want a firefox profile type
        if self.config['app'] == 'geckoview':
            self.profile = create_profile('firefox')
        else:
            self.profile = create_profile(self.config['app'])

        # Merge in base profiles
        with open(os.path.join(self.profile_data_dir, 'profiles.json'),
                  'r') as fh:
            base_profiles = json.load(fh)['raptor']

        for name in base_profiles:
            path = os.path.join(self.profile_data_dir, name)
            self.log.info("Merging profile: {}".format(path))
            self.profile.merge(path)

        # create results holder
        self.results_handler = RaptorResultsHandler()

        # when testing desktop browsers we use mozrunner to start the browser; when
        # testing on android (i.e. geckoview) we use mozdevice to control the device app

        if self.config['app'] == "geckoview":
            # create the android device handler; it gets initiated and sets up adb etc
            self.log.info("creating android device handler using mozdevice")
            self.device = ADBAndroid(verbose=True)
            self.device.clear_logcat()
        else:
            # create the desktop browser runner
            self.log.info("creating browser runner using mozrunner")
            self.output_handler = OutputHandler()
            process_args = {
                'processOutputLine': [self.output_handler],
            }
            runner_cls = runners[app]
            self.runner = runner_cls(binary,
                                     profile=self.profile,
                                     process_args=process_args)

        self.log.info("raptor config: %s" % str(self.config))

    @property
    def profile_data_dir(self):
        if 'MOZ_DEVELOPER_REPO_DIR' in os.environ:
            return os.path.join(os.environ['MOZ_DEVELOPER_REPO_DIR'],
                                'testing', 'profiles')
        if build:
            return os.path.join(build.topsrcdir, 'testing', 'profiles')
        return os.path.join(here, 'profile_data')

    def start_control_server(self):
        self.control_server = RaptorControlServer(self.results_handler)
        self.control_server.start()

        # for android we must make the control server available to the device
        if self.config['app'] == "geckoview":
            self.log.info(
                "making the raptor control server port available to device")
            _tcp_port = "tcp:%s" % self.control_server.port
            self.device.create_socket_connection('reverse', _tcp_port,
                                                 _tcp_port)

    def get_playback_config(self, test):
        self.config['playback_tool'] = test.get('playback')
        self.log.info("test uses playback tool: %s " %
                      self.config['playback_tool'])
        self.config['playback_binary_manifest'] = test.get(
            'playback_binary_manifest', None)
        _key = 'playback_binary_zip_%s' % self.config['platform']
        self.config['playback_binary_zip'] = test.get(_key, None)
        self.config['playback_pageset_manifest'] = test.get(
            'playback_pageset_manifest', None)
        _key = 'playback_pageset_zip_%s' % self.config['platform']
        self.config['playback_pageset_zip'] = test.get(_key, None)
        self.config['playback_recordings'] = test.get('playback_recordings',
                                                      None)
        self.config['python3_win_manifest'] = test.get('python3_win_manifest',
                                                       None)

    def run_test(self, test, timeout=None):
        self.log.info("starting raptor test: %s" % test['name'])
        self.log.info("test settings: %s" % str(test))
        self.log.info("raptor config: %s" % str(self.config))

        # benchmark-type tests require the benchmark test to be served out
        if test.get('type') == "benchmark":
            self.benchmark = Benchmark(self.config, test)
            benchmark_port = int(self.benchmark.port)
        else:
            benchmark_port = 0

        gen_test_config(self.config['app'], test['name'],
                        self.control_server.port, benchmark_port)

        # for android we must make the benchmarks server available to the device
        if self.config['app'] == "geckoview":
            self.log.info(
                "making the raptor benchmarks server port available to device")
            _tcp_port = "tcp:%s" % benchmark_port
            self.device.create_socket_connection('reverse', _tcp_port,
                                                 _tcp_port)

        # must intall raptor addon each time because we dynamically update some content
        raptor_webext = os.path.join(webext_dir, 'raptor')
        self.log.info("installing webext %s" % raptor_webext)
        self.profile.addons.install(raptor_webext)

        # add test specific preferences
        if test.get("preferences", None) is not None:
            if self.config['app'] == "firefox":
                self.profile.set_preferences(json.loads(test['preferences']))
            else:
                self.log.info("preferences were configured for the test, \
                              but we do not install them on non Firefox browsers."
                              )

        # on firefox we can get an addon id; chrome addon actually is just cmd line arg
        if self.config['app'] in ["firefox", "geckoview"]:
            webext_id = self.profile.addons.addon_details(raptor_webext)['id']

        # some tests require tools to playback the test pages
        if test.get('playback', None) is not None:
            self.get_playback_config(test)
            # startup the playback tool
            self.playback = get_playback(self.config)

        # for geckoview we must copy the profile onto the device and set perms
        if self.config['app'] == "geckoview":
            if not self.device.is_app_installed(self.config['binary']):
                raise Exception('%s is not installed' % self.config['binary'])

            self.log.info("copying firefox profile onto the android device")
            self.device_profile = "/sdcard/raptor-profile"
            if self.device.is_dir(self.device_profile):
                self.device.rm(self.device_profile, recursive=True)

            self.device.mkdir(self.device_profile)
            self.device.push(self.profile.profile, self.device_profile)

            self.log.info("setting permisions to profile dir on the device")
            self.device.chmod(self.device_profile, recursive=True)

            # now start the geckoview app
            self.log.info("starting %s" % self.config['app'])

            extra_args = [
                "-profile", self.device_profile, "--es", "env0",
                "LOG_VERBOSE=1", "--es", "env1", "R_LOG_LEVEL=6"
            ]

            try:
                # make sure the geckoview app is not running before
                # attempting to start.
                self.device.stop_application(self.config['binary'])
                self.device.launch_activity(self.config['binary'],
                                            "GeckoViewActivity",
                                            extra_args=extra_args,
                                            url='about:blank',
                                            fail_if_running=False)
            except Exception:
                self.log.error("Exception launching %s" %
                               self.config['binary'])
                raise
            self.control_server.device = self.device
            self.control_server.app_name = self.config['binary']

        else:
            # now start the desktop browser
            self.log.info("starting %s" % self.config['app'])

            self.runner.start()
            proc = self.runner.process_handler
            self.output_handler.proc = proc

            self.control_server.browser_proc = proc

        # set our cs flag to indicate we are running the browser/app
        self.control_server._finished = False

        # convert to seconds and account for page cycles
        timeout = int(timeout / 1000) * int(test['page_cycles'])
        try:
            elapsed_time = 0
            while not self.control_server._finished:
                time.sleep(1)
                elapsed_time += 1
                if elapsed_time > (timeout) - 5:  # stop 5 seconds early
                    self.log.info(
                        "application timed out after {} seconds".format(
                            timeout))
                    self.control_server.wait_for_quit()
                    break
        finally:
            if self.config['app'] != "geckoview":
                try:
                    self.runner.check_for_crashes()
                except NotImplementedError:  # not implemented for Chrome
                    pass
            # TODO: if on geckoview is there some cleanup here i.e. check for crashes?

        if self.playback is not None:
            self.playback.stop()

        # remove the raptor webext; as it must be reloaded with each subtest anyway
        # applies to firefox only; chrome the addon is actually just cmd line arg
        if self.config['app'] in ["firefox", "geckoview"]:
            self.log.info("removing webext %s" % raptor_webext)
            self.profile.addons.remove_addon(webext_id)

        if self.config['app'] != "geckoview":
            if self.runner.is_running():
                self.runner.stop()
        # TODO the geckoview app should have been shutdown by this point by the
        # control server, but we can double-check here to make sure

    def process_results(self):
        # when running locally output results in build/raptor.json; when running
        # in production output to a local.json to be turned into tc job artifact
        if self.config.get('run_local', False):
            if 'MOZ_DEVELOPER_REPO_DIR' in os.environ:
                raptor_json_path = os.path.join(
                    os.environ['MOZ_DEVELOPER_REPO_DIR'], 'testing',
                    'mozharness', 'build', 'raptor.json')
            else:
                raptor_json_path = os.path.join(here, 'raptor.json')
        else:
            raptor_json_path = os.path.join(os.getcwd(), 'local.json')

        self.config['raptor_json_path'] = raptor_json_path
        return self.results_handler.summarize_and_output(self.config)

    def clean_up(self):
        self.control_server.stop()
        if self.config['app'] != "geckoview":
            self.runner.stop()
        elif self.config['app'] == 'geckoview':
            self.log.info('removing reverse socket connections')
            self.device.remove_socket_connections('reverse')
        else:
            pass
        self.log.info("finished")
Пример #40
0
class FennecLauncher(Launcher):
    app_info = None
    adb = None
    package_name = None
    remote_profile = None

    @classmethod
    def check_is_runnable(cls):
        # ADBHost().devices() seems to raise OSError when adb is not
        # installed and in PATH. TODO: maybe fix this in mozdevice.
        try:
            devices = ADBHost().devices()
        except OSError:
            raise LauncherNotRunnable("adb (Android Debug Bridge) is not"
                                      " installed or not in the PATH.")
        if not devices:
            raise LauncherNotRunnable("No android device connected."
                                      " Connect a device and try again.")

    def _install(self, dest):
        # get info now, as dest may be removed
        self.app_info = mozversion.get_version(binary=dest)
        self.package_name = self.app_info.get("package_name",
                                              "org.mozilla.fennec")
        self.adb = ADBAndroid()
        self.adb.uninstall_app(self.package_name)
        self.adb.install_app(dest)

    def _start(self, profile=None, addons=(), cmdargs=(), preferences=None):
        # for now we don't handle addons on the profile for fennec
        profile = self._create_profile(profile=profile,
                                       preferences=preferences)
        # send the profile on the device
        self.remote_profile = "/".join([self.adb.test_root,
                                       os.path.basename(profile.profile)])
        if self.adb.exists(self.remote_profile):
            self.adb.rm(self.remote_profile, recursive=True)
        self.adb.push(profile.profile, self.remote_profile)

        self.adb.launch_fennec(self.package_name,
                               extra_args=["-profile", self.remote_profile])

    def _stop(self):
        self.adb.stop_application(self.package_name)
        if self.adb.exists(self.remote_profile):
            self.adb.rm(self.remote_profile, recursive=True)

    def get_app_info(self):
        return self.app_info